from tracemalloc import start from otree.api import * from json import dumps as json_dumps, loads as json_loads import time from datetime import datetime, timedelta, timezone doc = """ Your app description """ class Constants(BaseConstants): name_in_url = 'Introduction' players_per_group = 2 num_rounds = 1 width = '850px' height = 1.7 match_waiting_seconds = 5 match_waiting_mins = match_waiting_seconds/60 # 理解測驗超過10分鐘就drop(預防他回來) drop_waiting_seconds = 600 # 聊天室 PAPERCUPS_TEMPLATE = __name__ + '/papercups.html' # rounds玩超過20分鐘就drop drop_round_seconds = 1200 # 剩3分鐘的時候提醒 alert_last_seconds = 180 class Subsession(BaseSubsession): pass class Group(BaseGroup): # json fields wait_for_ids = models.LongStringField(initial='[]') arrived_ids = models.LongStringField(initial='[]') print(arrived_ids, '測試') pass def unarrived_players(group: Group): return set(json_loads(group.wait_for_ids)) - set(json_loads(group.arrived_ids)) # def arrived_players(group: Group): # return set(json_loads(group.arrived_ids)) class Player(BasePlayer): start_hour = models.StringField() start_min = models.StringField() pass # PAGES class MyPage(Page): pass class Check_in(Page): timer_text = "您距離報到截止時間還有:" @staticmethod def get_timeout_seconds(player): # 標準時間 today_UTC = datetime.utcnow().replace(tzinfo=timezone.utc) # 標準時間+8 today_TW = today_UTC.astimezone(timezone(timedelta(hours=8))) # config 輸入的時間 start_time_set=player.session.config['start_time_set'] # 設定 +8 utc_8 = timezone(timedelta(hours=8)) # 轉換 config 輸入的時間 到時間格式+正確時區 start_time = datetime.strptime(start_time_set,"%Y/%m/%d %H:%M:%S").replace(tzinfo=utc_8) check_in_duration = timedelta(minutes = 6) start_time = start_time + check_in_duration diff = (start_time - today_TW).total_seconds() print(diff) return diff # 停留過久跳轉 @staticmethod def before_next_page(player, timeout_happened): if timeout_happened: # 記錄為參加失敗 player.participant.participated = False player.participant.jump_to_next = False player.participant.total_payoff = 0 else: player.participant.participated = True player.participant.jump_to_next = False @staticmethod def app_after_this_page(player, upcoming_apps): if player.participant.participated == False: return upcoming_apps[-1] pass class ScratchWaitPage(Page): print("test") @staticmethod # 顯示給受試者用的 def vars_for_template(player: Player): import time start_time_set=player.session.config['start_time_set'] # 設定 +8 utc_8 = timezone(timedelta(hours=8)) # 轉換 config 輸入的時間 到時間格式+正確時區 start_time = datetime.strptime(start_time_set,"%Y/%m/%d %H:%M:%S").replace(tzinfo=utc_8) check_in_duration = timedelta(minutes = 6) start_time = start_time + check_in_duration # 最多需等待到幾點幾分 player.start_hour = str(start_time.hour).zfill(2) player.start_min = str(start_time.minute).zfill(2) # 報到完可以有50元車馬費 player.participant.total_payoff = 50 # 設定時限 @staticmethod def get_timeout_seconds(player): # 標準時間 today_UTC = datetime.utcnow().replace(tzinfo=timezone.utc) # 標準時間+8 today_TW = today_UTC.astimezone(timezone(timedelta(hours=8))) # config 輸入的時間 start_time_set=player.session.config['start_time_set'] # 設定 +8 utc_8 = timezone(timedelta(hours=8)) # 轉換 config 輸入的時間 到時間格式+正確時區 start_time = datetime.strptime(start_time_set,"%Y/%m/%d %H:%M:%S").replace(tzinfo=utc_8) check_in_duration = timedelta(minutes = 6) start_time = start_time + check_in_duration diff = (start_time - today_TW).total_seconds() print(diff) return diff @staticmethod def before_next_page(player, timeout_happened): if timeout_happened: player.participant.jump_to_next = True player.participant.participated = False else: player.participant.jump_to_next = False player.participant.participated = True @staticmethod def app_after_this_page(player, upcoming_apps): if player.participant.jump_to_next == True: return upcoming_apps[-1] @staticmethod def is_displayed(player: Player): group = player.group # first time if not json_loads(group.wait_for_ids): wait_for_ids = [p.id_in_subsession for p in group.get_players()] # print(wait_for_ids) group.wait_for_ids = json_dumps(wait_for_ids) return unarrived_players(group) @staticmethod def live_method(player: Player, data): if data.get('type') == 'wait_page': return wait_page_live_method(player, data) pass class Introduction(Page): # 這頁給5分鐘,還剩3分鐘時提醒 timeout_seconds= 300 timer_text = '請於時間內閱讀完實驗說明,並進入下一頁:' # 停留過久跳轉 @staticmethod def before_next_page(player, timeout_happened): if timeout_happened: # 記錄為參加失敗 player.participant.participated = False player.participant.jump_to_next = False player.participant.total_payoff = 0 else: player.participant.participated = True player.participant.jump_to_next = False # 設定時限 intro_start_time_UTC = datetime.utcnow().replace(tzinfo=timezone.utc) # 標準時間+8 intro_start_time_TW = intro_start_time_UTC.astimezone(timezone(timedelta(hours=8))) round_duration = timedelta(seconds = Constants.drop_waiting_seconds) # 實驗說明+理解測驗超過 10 分鐘後drop player.participant.intro_drop_time = intro_start_time_TW + round_duration @staticmethod def app_after_this_page(player, upcoming_apps): if player.participant.participated == False: return upcoming_apps[-1] pass class Instruction_rd(Page): # 停留過久跳轉 # timeout_seconds= Constants.drop_waiting_seconds timer_text = '請於時間內閱讀完本頁的實驗說明&完成下一頁的理解測驗:' # 設定時限 @staticmethod def get_timeout_seconds(player): # 標準時間 today_UTC = datetime.utcnow().replace(tzinfo=timezone.utc) # 標準時間+8 today_TW = today_UTC.astimezone(timezone(timedelta(hours=8))) diff = (player.participant.intro_drop_time - today_TW).total_seconds() # print(diff) return diff @staticmethod def is_displayed(player): return player.id_in_group == 1 # 停留過久跳轉 @staticmethod def before_next_page(player, timeout_happened): if timeout_happened: # 記錄為參加失敗 player.participant.jump_to_next = False player.participant.participated = False player.participant.total_payoff = 0 # my_id_in_group = player.id_in_group @staticmethod def app_after_this_page(player, upcoming_apps): if player.participant.participated == False: return upcoming_apps[-1] pass class test_rd(Page): # 停留過久跳轉 # timeout_seconds= Constants.drop_waiting_seconds timer_text = '請於時間內完成理解測驗:' # 設定時限 @staticmethod def get_timeout_seconds(player): # 標準時間 today_UTC = datetime.utcnow().replace(tzinfo=timezone.utc) # 標準時間+8 today_TW = today_UTC.astimezone(timezone(timedelta(hours=8))) diff = (player.participant.intro_drop_time - today_TW).total_seconds() # print(diff) return diff @staticmethod def is_displayed(player): return player.id_in_group == 1 # 停留過久跳轉 @staticmethod def before_next_page(player, timeout_happened): if timeout_happened: # 記錄為參加失敗 player.participant.jump_to_next = False player.participant.participated = False player.participant.total_payoff = 0 # my_id_in_group = player.id_in_group @staticmethod def app_after_this_page(player, upcoming_apps): if player.participant.participated == False: return upcoming_apps[-1] pass class Instruction_ud(Page): # 停留過久跳轉 # timeout_seconds= Constants.drop_waiting_seconds timer_text = '請於時間內閱讀完實驗說明,並完成理解測驗:' # 設定時限 @staticmethod def get_timeout_seconds(player): # 標準時間 today_UTC = datetime.utcnow().replace(tzinfo=timezone.utc) # 標準時間+8 today_TW = today_UTC.astimezone(timezone(timedelta(hours=8))) diff = (player.participant.intro_drop_time - today_TW).total_seconds() # print(diff) return diff @staticmethod def is_displayed(player): return player.id_in_group == 2 # 停留過久跳轉 @staticmethod def before_next_page(player, timeout_happened): if timeout_happened: # 記錄為參加失敗 player.participant.jump_to_next = False player.participant.participated = False player.participant.total_payoff = 0 # my_id_in_group = player.id_in_group @staticmethod def app_after_this_page(player, upcoming_apps): if player.participant.participated == False: return upcoming_apps[-1] class test_ud(Page): # 停留過久跳轉 # timeout_seconds= Constants.drop_waiting_seconds timer_text = '請於時間內閱讀完實驗說明,並完成理解測驗:' # 設定時限 @staticmethod def get_timeout_seconds(player): # 標準時間 today_UTC = datetime.utcnow().replace(tzinfo=timezone.utc) # 標準時間+8 today_TW = today_UTC.astimezone(timezone(timedelta(hours=8))) diff = (player.participant.intro_drop_time - today_TW).total_seconds() # print(diff) return diff @staticmethod def is_displayed(player): return player.id_in_group == 2 # 停留過久跳轉 @staticmethod def before_next_page(player, timeout_happened): if timeout_happened: # 記錄為參加失敗 player.participant.jump_to_next = False player.participant.participated = False player.participant.total_payoff = 0 # my_id_in_group = player.id_in_group @staticmethod def app_after_this_page(player, upcoming_apps): if player.participant.participated == False: return upcoming_apps[-1] class Ready_to_start(Page): # 停留過久跳轉 timeout_seconds= 300 timer_text = '請於時間內點擊Next,以進入實驗正式回合:' # 停留過久跳轉 @staticmethod def before_next_page(player, timeout_happened): if timeout_happened: # 記錄為參加失敗 player.participant.jump_to_next = False player.participant.participated = False player.participant.total_payoff = 0 # my_id_in_group = player.id_in_group # 設定時限 else: round_start_time_UTC = datetime.utcnow().replace(tzinfo=timezone.utc) # 標準時間+8 round_start_time_TW = round_start_time_UTC.astimezone(timezone(timedelta(hours=8))) round_duration = timedelta(seconds = Constants.drop_round_seconds) # 玩超過 15 分鐘後drop player.participant.round_drop_time = round_start_time_TW + round_duration @staticmethod def app_after_this_page(player, upcoming_apps): if player.participant.participated == False: return upcoming_apps[-1] pass class ResultsWaitPage(WaitPage): pass def wait_page_live_method(player: Player, data): group = player.group arrived_ids_set = set(json_loads(group.arrived_ids)) arrived_ids_set.add(player.id_in_subsession) group.arrived_ids = json_dumps(list(arrived_ids_set)) if not unarrived_players(group): return {0: dict(finished=True)} class Results(Page): pass page_sequence = [ Check_in, ScratchWaitPage, Introduction, Instruction_rd, test_rd, Instruction_ud, test_ud, Ready_to_start] #ScratchWaitPage,