from otree.api import * import time # 時間計測に用いる doc = """ Summation Task with Goal """ class Constants(BaseConstants): practice_round = 0 # 練習のラウンド数(実験者側で設定) production_round = 3 # 本番のラウンド数(実験者側で設定) round_minutes = 0 # 各ラウンドの所要時間(分) round_seconds = 30 # 各ラウンドの所要時間(秒) name_in_url = 'summation_task_withgoal' players_per_group = None num_rounds = practice_round + production_round goal_difficulty_10 = 567 # 10% of pilot participants achieved this goal goal_difficulty_90 = 357 # 90% of pilot participants achieved this goal class Subsession(BaseSubsession): pass class Group(BaseGroup): pass class Player(BasePlayer): start_timestamp = models.IntegerField() num_of_responses = models.IntegerField() # 回答数 num_of_correct = models.IntegerField() # 正答数 assigned_goal = models.IntegerField() def check_answer(group, q_formula, q_response, num_of_responses): ans = q_response.split('.') # 少数でない、もしくは小数点以下が00でない場合は不正解 if len(ans) != 2 or ans[1] != "00": return False q_response = ans[0] # プレイヤーの解が数字であるか判断 if not q_response.isdecimal(): return False return sum(q_formula) == int(q_response) # def gen_map(q_field): # return q_field.split(',') def live_method(player: Player, data): group = player.group players = group.get_players() if data: try: q_formula = data['q_formula'] q_response = data['q_response'] except Exception: print('invalid message received:', data) # For developer message return if check_answer(group, q_formula, q_response, player.num_of_responses): player.num_of_correct = player.num_of_correct + 1 # 1桁の答えがあっている場合は正答数を増やす player.num_of_responses = player.num_of_responses + 1 return { player.id_in_group: dict( num_of_responses=player.num_of_responses ) } def goal_assignment(player: Player): if (player.participant.id_in_session % 2) == 0: player.assigned_goal = Constants.goal_difficulty_90 else: player.assigned_goal = Constants.goal_difficulty_10 return dict(assigned_goal=player.assigned_goal) # PAGES class Instruction_Withgoal(Page): @staticmethod def before_next_page(player: Player, timeout_happened): player.num_of_responses = -1 # ライブページの初期呼び出し時になぜか実行されるので-1にした(直せるなら直したい) player.num_of_correct = 0 player.start_timestamp = int(time.time()) goal_assignment(player) def vars_for_template(player: Player): round_number = player.round_number if player.round_number - Constants.practice_round <= 0 else player.round_number - Constants.practice_round return dict(round_number=round_number) class Goal_Assignment(Page): pass class Main_Withgoal(Page): live_method = live_method @staticmethod def vars_for_template(player: Player): round_number = player.round_number if player.round_number - Constants.practice_round <= 0 else player.round_number - Constants.practice_round return dict(round_number=round_number) @staticmethod def js_vars(player: Player): return dict(id_in_group=player.id_in_group) @staticmethod def get_timeout_seconds(player: Player): import time group = player.group return Constants.round_minutes * 60 + Constants.round_seconds + player.start_timestamp - time.time() class Results_Withgoal(Page): # ラウンド数とプレイヤーの獲得ポイントを計算した値を返す def vars_for_template(player: Player): raw_point = player.num_of_correct * 20 if raw_point > player.assigned_goal: point = raw_point + 0.5 * (raw_point - player.assigned_goal) else: point = raw_point player.participant.vars['point_list'][player.round_number + 8] = point return dict(raw_point=raw_point, point=point) page_sequence = [Instruction_Withgoal, Goal_Assignment, Main_Withgoal, Results_Withgoal]