from otree.api import * import random doc = """ Both players work on a real-effort task and create a joint endowment. One player decides how to divide a certain amount between themself and the other player. Akdeniz & Mathew, 2022, Normative versus prosocial underpinnings of human decision making. """ class Constants(BaseConstants): name_in_url = 'part1task3' players_per_group = None num_rounds = 32 endowment_dictator = 600 sit = 3 class Subsession(BaseSubsession): pass def creating_session(subsession: Subsession): if subsession.round_number == 1: for player in subsession.get_players(): participant = player.participant # player.task_difficulty = 1 player.task_difficulty = random.randint(1, 2) print('task difficulty is', player.task_difficulty) participant.number_rounds = (16 * player.task_difficulty) print('number of rounds is', participant.number_rounds) participant.tables = random.sample(range(36), 32) print('in creating_session', subsession.round_number) for p in subsession.get_players(): participant = p.participant p.table = participant.tables[subsession.round_number - 1] + 1 print('set the table for player', p.id_in_subsession, 'and round', p.round_number, 'to', p.table, 'where the original element was', participant.tables[subsession.round_number - 1]) class Group(BaseGroup): pass class Player(BasePlayer): dg_earned1 = models.IntegerField( label='if you worked harder for the reward?', min=0, max=Constants.endowment_dictator,) dg_earned2 = models.IntegerField( label='if Participant B worked harder for the reward?', min=0, max=Constants.endowment_dictator,) ex1 = models.CurrencyField( doc="""Answer to first example""", min=0, max=Constants.endowment_dictator, label="", ) ex2 = models.CurrencyField( doc="""Answer to second example""", min=0, max=Constants.endowment_dictator, label="", ) task_difficulty = models.IntegerField() # t1 = models.IntegerField(label='', min=0, max=25) # t2 = models.IntegerField(label='', min=0, max=25) # t3 = models.IntegerField(label='', min=0, max=25) count = models.IntegerField(label='', min=0, max=25) table = models.IntegerField(label='', min=0, max=36) def custom_export(players): # header row yield ['session', 'participant_code', 'participant_label', 'id_in_group', 'task difficulty', 'dg_earned1', 'dg_earned2'] for p in players: participant = p.participant session = p.session yield [session.code, participant.code, participant.label, p.id_in_group, p.task_difficulty, p.dg_earned1, p.dg_earned2] # PAGES class Start(Page): def is_displayed(self): return self.round_number == 1 class InstructionsCounting(Page): form_model = 'player' form_fields = ['ex1', 'ex2'] def is_displayed(self): return self.round_number == 1 def error_message(self, value): if value["ex1"] != 200: return 'The first question is not answered correctly. Consult the instructions and try again.' elif value["ex2"] != 400: return 'The second question is not answered correctly. Consult the instructions and try again.' class Table(Page): form_model = 'player' form_fields = ['count'] @staticmethod def is_displayed(player: Player): participant = player.participant return player.round_number <= participant.number_rounds def vars_for_template(self): return dict( table='part1task3/table{}.png'.format(self.table) ) def error_message(self, value): if (value["count"] != 11) and (self.table == 3 or self.table == 4 or self.table == 9 or self.table == 12 or self.table == 21 or self.table == 33): return 'Please try again.' elif (value["count"] != 14) and (self.table == 1 or self.table == 18): return 'Please try again.' elif (value["count"] != 8) and (self.table == 2 or self.table == 14 or self.table == 19 or self.table == 22 or self.table == 28 or self.table == 29 or self.table == 31 or self.table == 32): return 'Please try again.' elif (value["count"] != 6) and (self.table == 5): return 'Please try again.' elif (value["count"] != 10) and (self.table == 6 or self.table == 7 or self.table == 15 or self.table == 16 or self.table == 23 or self.table == 26 or self.table == 27 or self.table == 30 or self.table == 34): return 'Please try again.' elif (value["count"] != 7) and (self.table == 8 or self.table == 24): return 'Please try again.' elif (value["count"] != 12) and (self.table == 10 or self.table == 25): return 'Please try again.' elif (value["count"] != 9) and (self.table == 11 or self.table == 13 or self.table == 17 or self.table == 20): return 'Please try again.' elif (value["count"] != 15) and (self.table == 35): return 'Please try again.' elif (value["count"] != 13) and (self.table == 36): return 'Please try again.' # class Table1(Page): # form_model = 'player' # form_fields = ['t1'] # # def error_message(self, value): # if value["t1"] != 14: # return 'Please try again.' # # # class Table2(Page): # form_model = 'player' # form_fields = ['t2'] # # def error_message(self, value): # if value["t2"] != 8: # return 'Please try again.' # # # class Table3(Page): # form_model = 'player' # form_fields = ['t3'] # # def error_message(self, value): # if value["t3"] != 11: # return 'Please try again.' class Instructions(Page): def is_displayed(self): return self.round_number == Constants.num_rounds class Round1(Page): form_model = 'player' form_fields = ['dg_earned1', 'dg_earned2'] def is_displayed(self): return self.round_number == Constants.num_rounds class Round2(Page): def is_displayed(self): return self.round_number == Constants.num_rounds @staticmethod def app_after_this_page(player, upcoming_apps): print('upcoming_apps is', upcoming_apps) participant = player.participant if participant.dg_order == 1: return "part1task1t_2" # elif participant.dg_order == 2: # return "part1task1_2" page_sequence = [Start, InstructionsCounting, Table, Instructions, Round1, Round2]