from otree.api import * import pandas import random import timeit from datetime import datetime as dt doc = """""" class C(BaseConstants): NAME_IN_URL = 'predict-numbers' PLAYERS_PER_GROUP = None NUM_BLOCKS = 1 BLOCK_ROUNDS = 60 NUM_ROUNDS = NUM_BLOCKS*BLOCK_ROUNDS show_up_fee = 0.8 incentives = {"25vs35" : [25 , 35], "65vs75" : [65, 75], "25vs75" : [25, 75] } class Subsession(BaseSubsession): pass class Group(BaseGroup): pass class Player(BasePlayer): show_up_fee = models.CurrencyField() is_mobile = models.BooleanField(initial=False) is_dropout = models.BooleanField(initial=False, blank=True) instruction_time_taken_min = models.StringField() total_time_taken_min = models.StringField() time_ended_utc = models.StringField() starting_question1 = models.BooleanField() starting_question2 = models.BooleanField() starting_question3 = models.BooleanField() block_type = models.StringField() low_points = models.IntegerField() high_points = models.IntegerField() yes_side = models.StringField() die_outcome = models.IntegerField() chose_yes = models.BooleanField() rt_think_ms = models.FloatField() rt_choice_ms = models.FloatField() trial_points = models.IntegerField() total_yes_ratio = models.FloatField() # total_points = models.CurrencyField() bonus = models.CurrencyField() finished = models.BooleanField() def creating_session(subsession: Subsession): print("Repeated mind game:") if subsession.round_number == 1: start = timeit.default_timer() for p in subsession.get_players(): print(f'plyaer num: {p.id_in_group}') participant = p.participant for p_r in p.in_rounds(1, C.NUM_ROUNDS): p_r.show_up_fee = cu(participant.show_up_fee) p_r.payoff = participant.payoff p_r.yes_side = participant.yes_side p_r.block_type = participant.block_type p_r.low_points = participant.low_points p_r.high_points = participant.high_points stop = timeit.default_timer() print('Time to create session: ', (stop - start)/60) def get_time_taken(curr_timestamp, time_started): if "." in time_started: diff_timestamp = curr_timestamp - dt.strptime(time_started[:time_started.rfind(".")], '%Y-%m-%d %H:%M:%S').timestamp() else: diff_timestamp = curr_timestamp - dt.strptime(ptime_started, '%Y-%m-%d %H:%M:%S').timestamp() minutes, seconds = divmod(int(diff_timestamp), 60) while minutes >= 60 or minutes < 0: if minutes >= 60: minutes -= 60 else: minutes += 60 time_difference = f"{minutes}:{seconds:02d}" return time_difference # PAGES class Consent(Page): form_model = 'player' form_fields = ['consent', 'is_dropout'] timeout_seconds = 60*3 def is_displayed(player: Player): return player.round_number == 1 def before_next_page(player: Player, timeout_happened): if timeout_happened: for p in player.in_rounds(1, C.NUM_ROUNDS): p.is_dropout = True for p_r in player.in_rounds(1, C.NUM_ROUNDS): p_r.consent = player.consent class Welcome(Page): form_model = 'player' form_fields = ['is_dropout'] timeout_seconds = 60*5 def is_displayed(player: Player): return player.round_number == 1 def vars_for_template(player: Player): if player.yes_side == 'right': yes_side = 'right' no_side = 'left' else: yes_side = 'left' no_side = 'right' return{ 'yes_side': yes_side, 'no_side': no_side, 'img_choice': 'mind_game/Choice/' + player.block_type + player.yes_side + '.jpeg', 'img_feedback': 'mind_game/Feedback/' + player.block_type + player.yes_side + random.choice(['yes', 'no']) + '.jpeg', } def before_next_page(player: Player, timeout_happened): if timeout_happened: for p in player.in_rounds(1, C.NUM_ROUNDS): p.is_dropout = True class EarningBonus(Page): form_model = 'player' form_fields = ['is_dropout'] timeout_seconds = 60*3 def is_displayed(player: Player): return player.round_number == 1 def vars_for_template(player: Player): if player.yes_side == 'right': yes_side = 'right' no_side = 'left' img_choice = "mind_game/Choice/ChoicePage_yesRight.jpeg" else: yes_side = 'left' no_side = 'right' img_choice = "mind_game/Choice/ChoicePage_yesLeft.jpeg" return{ 'yes_side': yes_side, 'no_side': no_side, 'img_choice': img_choice, 'img_feedback': 'mind_game/Feedback/FeedbackPage_' + random.choice(['yes', 'no']) + 'Chosen.jpeg' } def before_next_page(player: Player, timeout_happened): if timeout_happened: for p in player.in_rounds(1, C.NUM_ROUNDS): p.is_dropout = True class DoYourBest(Page): form_model = 'player' form_fields = ['is_dropout'] timeout_seconds = 60*2 def is_displayed(player: Player): return player.round_number == 1 def before_next_page(player: Player, timeout_happened): if timeout_happened: for p in player.in_rounds(1, C.NUM_ROUNDS): p.is_dropout = True class StartingQuestions(Page): form_model = 'player' form_fields = ['starting_question1', 'starting_question2', 'starting_question3', 'is_dropout' ] timeout_seconds = 60*5 def is_displayed(player: Player): return player.round_number == 1 def before_next_page(player: Player, timeout_happened): if timeout_happened: for p in player.in_rounds(1, C.NUM_ROUNDS): p.is_dropout = True ans1 = player.starting_question1 ans2 = not player.starting_question2 ans3 = not player.starting_question3 curr_timestamp = dt.now().timestamp() time_difference = get_time_taken(curr_timestamp, player.participant.time_started_utc) for p in player.in_rounds(1, C.NUM_ROUNDS): p.starting_question1 = ans1 p.starting_question2 = ans2 p.starting_question3 = ans3 p.instruction_time_taken_min = time_difference class ThinkNumber(Page): form_model = 'player' form_fields = ['rt_think_ms'] timeout_seconds = 60 def before_next_page(player: Player, timeout_happened): if timeout_happened: for p in player.in_rounds(1, C.NUM_ROUNDS): p.is_dropout = True class Choice(Page): form_model = 'player' form_fields = ['chose_yes', 'rt_choice_ms', 'die_outcome'] timeout_seconds = 60 def vars_for_template(player: Player): if player.yes_side == "right": on_right = "Yes" on_left = "No" else: on_right = "No" on_left = "Yes" return { 'right': on_right, 'left': on_left, # 'generated_number': player.die_outcome, 'high_points': player.high_points, 'low_points': player.low_points } def before_next_page(player: Player, timeout_happened): if timeout_happened: for p in player.in_rounds(1, C.NUM_ROUNDS): p.is_dropout = True class DropOut(Page): form_model = 'player' form_fields = ['total_time_taken_min'] def is_displayed(player: Player): if player.is_dropout: end_time = dt.now().strftime('%Y-%m-%d %H:%M:%S') curr_timestamp = dt.now().timestamp() time_difference = get_time_taken(curr_timestamp, player.participant.time_started_utc) for p_r in player.in_rounds(1, C.NUM_ROUNDS): p_r.total_time_taken_min = time_difference p_r.time_ended_utc = end_time return player.is_dropout class Feedback(Page): form_model = 'player' timeout_seconds = 1 def vars_for_template(player: Player): if player.yes_side == "right": on_right = player.high_points on_left = player.low_points text_right = "Yes" text_left = "No" else: on_right = player.low_points on_left = player.high_points text_right = "No" text_left = "Yes" if player.chose_yes: chosen_ans = "Yes" chosen_points = player.high_points player.trial_points = chosen_points else: chosen_ans = "No" chosen_points = player.low_points player.trial_points = chosen_points return { 'right': on_right, 'left': on_left, 'text_right': text_right, 'text_left': text_left, 'chosen_ans': chosen_ans, 'chosen_points': chosen_points } def before_next_page(player: Player, timeout_happened): if player.round_number == C.NUM_ROUNDS: player.bonus = player.in_round(random.randint(1, C.NUM_ROUNDS)).trial_points # class EndBlock(Page): # timeout_seconds = 60 # # def js_vars(player: Player): # return { # 'start_utc': player.participant.time_started_utc # } # # def vars_for_template(player: Player): # curr_block = player.block_num # curr_round = player.round_number # block_points = 0 # block_yes = 0 # for p_r in player.in_rounds(1, curr_round): # if p_r.block_num == curr_block: # block_points += p_r.trial_points # block_yes += p_r.chose_yes # # # for p_r in player.in_rounds(1, curr_round): # if p_r.block_num == curr_block: # p_r.block_points = block_points # p_r.block_yes_ratio = round(block_yes/C.BLOCK_ROUNDS, 2) # # if curr_block == 1: # game = 'first' # elif curr_block == 2: # game = 'second' # # return {'game': game, # 'high_points': player.in_round(player.round_number+1).high_points, # 'low_points': player.in_round(player.round_number+1).low_points # } # # def is_displayed(player: Player): # if player.round_number == C.NUM_ROUNDS: # curr_block = player.block_num # curr_round = player.round_number # block_points = 0 # block_yes = 0 # for p_r in player.in_rounds(1, curr_round): # if p_r.block_num == curr_block: # block_points += p_r.trial_points # block_yes += p_r.chose_yes # # for p_r in player.in_rounds(1, curr_round): # if p_r.block_num == curr_block: # p_r.block_points = block_points # p_r.block_yes_ratio = round(block_yes/C.BLOCK_ROUNDS, 2) # # return player.round_number < C.NUM_ROUNDS and (player.round_number % C.BLOCK_ROUNDS) + 1 == 1 # # def before_next_page(player: Player, timeout_happened): # if timeout_happened: # for p in player.in_rounds(1, C.NUM_ROUNDS): # p.is_dropout = True class EndPage(Page): timeout_seconds = 60 def is_displayed(player: Player): return player.round_number == C.NUM_ROUNDS def js_vars(player: Player): return { 'start_utc': player.participant.time_started_utc, 'completion': player.session.prolific_completion_url } def vars_for_template(player: Player): total_points = 0 total_yes = 0 for p_r in player.in_rounds(1, C.NUM_ROUNDS): total_points += p_r.trial_points total_yes += p_r.chose_yes second_bonus = int(player.bonus) for p_r in player.in_rounds(1, C.NUM_ROUNDS): p_r.total_yes_ratio = round(total_yes/C.NUM_ROUNDS, 2) p_r.bonus = second_bonus player.payoff = player.bonus/100 if float(player.participant.payoff) >= 1: all_bonus = player.participant.payoff first_bonus = int(all_bonus*100) - second_bonus else: all_bonus = int(player.participant.payoff*100) first_bonus = all_bonus - second_bonus all_bonus = str(all_bonus) + " pennies" return {'first_bonus' : str(first_bonus) + " pennies", 'second_bonus': str(second_bonus) + " pennies", 'all_bonus': all_bonus} def before_next_page(player: Player, timeout_happened): end_time = dt.now().strftime('%Y-%m-%d %H:%M:%S') curr_timestamp = dt.now().timestamp() time_difference = get_time_taken(curr_timestamp, player.participant.time_started_utc) player.participant.finished = True for p_r in player.in_rounds(1, C.NUM_ROUNDS): p_r.total_time_taken_min = time_difference p_r.time_ended_utc = end_time p_r.finished = True # print(f'player: {player.payoff}, participant: {player.participant.payoff}') class CloseWindow(Page): def is_displayed(player: Player): return player.round_number == C.NUM_ROUNDS page_sequence = [ EarningBonus, DropOut, DoYourBest, DropOut, StartingQuestions, DropOut, ThinkNumber, DropOut, Choice, DropOut, Feedback, DropOut, EndPage, DropOut, CloseWindow ]