from otree import settings from otree.api import * import random import time #SESSION class C(BaseConstants): NAME_IN_URL = 'sg_pre' PLAYERS_PER_GROUP = None NUM_ROUNDS = 1 #INSTRUCTIONS spectator_instructions = __name__ + "/shortinstructions.html" #SUBSESSION class Subsession(BaseSubsession): pass #GROUP class Group(BaseGroup): pass #PLAYER class Player(BasePlayer): digit = models.IntegerField(label='Shown number',initial=0) recall = models.IntegerField(label='Which number was shown at the beginning of this round?') correct = models.IntegerField(label='Recall was correct') time_start = models.FloatField(label='Time: Start') time_recall = models.FloatField(label='Time: Recall') comp_general1 = models.IntegerField( label="1) How many times will you make decisions?", choices=[[0, '1 time'], [1, '5 times'], [2, '10 times'], [3, '15 times'], [4, '20 times'], [5, '25 times']], widget=widgets.RadioSelect, blank=True ) comp_general2 = models.IntegerField( label="1) How many times will you make decisions?", choices=[[0, '1 time'], [1, '5 times'], [2, '10 times'], [3, '15 times'], [4, '20 times'], [5, '25 times']], widget=widgets.RadioSelect, blank=True ) comp_digit1 = models.BooleanField( label="2) You will be shown the same number in each scenario", choices=[[True, 'Yes'], [False, 'No']], widget=widgets.RadioSelect, blank=True ) comp_digit2 = models.BooleanField( label="3) You can provide several answers for each digit recall", choices=[[True, 'Yes'], [False, 'No']], widget=widgets.RadioSelect, blank=True ) comp_digit3 = models.BooleanField( label="4) You will earn an additional 10 USD bonus if you correctly recalled the digit for the chosen round", choices=[[True, 'Yes'], [False, 'No']], widget=widgets.RadioSelect, blank=True ) comp_agents = models.IntegerField( label="2) What is the Agents' task?", choices=[[0, "Decide on how to split the bonus between Agents"], [1, "One half solve a series of letter-to-number conversions, the other half participate in a lottery"], [2, "Both of the above"]], widget=widgets.RadioSelect, blank=True ) comp_spectators = models.IntegerField( label="3) What is the Spectators' task?", choices=[[0, "Decide on how to split the bonus between Agents"], [1, "One half solve a series of letter-to-number conversions, the other half participate in a lottery"], [2, "Both of the above"]], widget=widgets.RadioSelect, blank=True ) comp_role = models.IntegerField( label="4) What is your role?", choices=[[0, "Agent"], [1, "Spectator"]], widget=widgets.RadioSelect, blank=True ) comp_rele = models.BooleanField( label="5) Can your decisions affect other participants' earnings?", choices=[[True, 'Yes'], [False, 'No']], widget=widgets.RadioSelect, blank=True ) comp0_failed_attempts = models.IntegerField( label="Errors in Comprehension test for Digit Recall", initial=0 ) comp1_failed_attempts = models.IntegerField( label="Errors in Comprehension test for SG", initial=0 ) # FUNCTIONS def order(player): participant = player.participant #PRACTICE LIST practice_list = [0,5] random.shuffle(practice_list) participant.practice_list = practice_list #DEFAULT LIST tasks_list = [0, 0, 1, 2, 3, 4, 5, 5, 6, 7, 8, 9] random.shuffle(tasks_list) tasks_list.insert(0, 0) participant.tasks_list = tasks_list #NO-DEFAULT LIST nodefault_list = [10,11] random.shuffle(nodefault_list) participant.nodefault_list = nodefault_list #PERFORMANCE LIST performance_list = [20,21,22,23,24,24,25,26,27,28] random.shuffle(performance_list) participant.performance_list = performance_list #NO-IMPLEMENTATION LIST noimplementation_list = [0,4,5,9,10,11] random.shuffle(noimplementation_list) participant.noimplementation_list = noimplementation_list #MATH LIST math_list = [] participant.math_list = math_list def prepare_cognitiveload(player): correct = [] participant = player.participant participant.cognitiveload_list = correct def comp_general1_error_message(player, value): if value not in [0, 1, 2, 3, 4, 5]: return 'You have to select one of the options.' def comp_general2_error_message(player, value): if value not in [0, 1, 2, 3, 4, 5]: return 'You have to select one of the options.' def comp_digit1_error_message(player, value): if value not in [False, True]: return 'You have to select one of the options.' def comp_digit2_error_message(player, value): if value not in [False, True]: return 'You have to select one of the options.' def comp_digit3_error_message(player, value): if value not in [False, True]: return 'You have to select one of the options.' def comp_agents_error_message(player, value): if value not in [0, 1, 2]: return 'You have to select one of the options.' def comp_spectators_error_message(player, value): if value not in [0, 1, 2]: return 'You have to select one of the options.' def comp_role_error_message(player, value): if value not in [0, 1, 2]: return 'You have to select one of the options.' def comp_rele_error_message(player, value): if value not in [False, True]: return 'You have to select one of the options.' # PAGES class Instructions0(Page): @staticmethod def vars_for_template(player): # TREATMENT session = player.subsession.session participant = player.participant if session.config['short_version']==2: if player.id_in_group == 1: participant.treatment = 'T1' if player.id_in_group == 2: participant.treatment = 'T2' if player.round_number == 1: participant.cognitiveload_random = random.randint(0, 14) treatment = participant.treatment load = 1 if treatment == 'T0': load = 0 return dict(load=load) class Instructions1(Page): @staticmethod def vars_for_template(player): participant = player.participant treatment = participant.treatment load = 1 if treatment == 'T0': load = 0 return dict(treatment=treatment, load=load) class PreComprehension1(Page): @staticmethod def is_displayed(player): participant = player.participant digit_recall = {'T1','T2'} return participant.treatment in digit_recall class IncorrectResponse1(ExtraModel): player = models.Link(Player) field_name = models.StringField() response = models.StringField() class Comprehension1(Page): form_model = 'player' form_fields = ['comp_general1', 'comp_digit1', 'comp_digit2', 'comp_digit3'] @staticmethod def error_message(player: Player, values): solutions = dict(comp_general1=5, comp_digit1=False, comp_digit2=False, comp_digit3=True) errors = {f: 'Wrong answer! Please try again' for f in solutions if values[f] != solutions[f]} if errors: player.comp0_failed_attempts += 1 for field_name in errors: response = values[field_name] IncorrectResponse1.create(player=player, field_name=field_name, response=str(response)) return errors @staticmethod def is_displayed(player): participant = player.participant digit_recall = {'T1','T2'} return participant.treatment in digit_recall @staticmethod def vars_for_template(player): failed = 1 if player.comp0_failed_attempts>0 else 0 return dict(failed=failed) class CompResult1(Page): @staticmethod def is_displayed(player): participant = player.participant digit_recall = {'T1','T2'} return participant.treatment in digit_recall class Instructions2(Page): @staticmethod def vars_for_template(player): participant = player.participant treatment = participant.treatment load = 1 if treatment == 'T0': load = 0 return dict(load=load) class PreComprehension2(Page): @staticmethod def vars_for_template(player): participant = player.participant treatment = participant.treatment load = 1 if treatment == 'T0': load = 0 return dict(load=load) class IncorrectResponse2(ExtraModel): player = models.Link(Player) field_name = models.StringField() response = models.StringField() class Comprehension2(Page): form_model = 'player' form_fields = ['comp_general2', 'comp_agents', 'comp_spectators', 'comp_role', 'comp_rele'] @staticmethod def error_message(player: Player, values): solutions = dict(comp_general2=5, comp_agents=1, comp_spectators=0, comp_role=1, comp_rele=True) errors = {f: 'Wrong answer! Please try again' for f in solutions if values[f] != solutions[f]} if errors: player.comp1_failed_attempts += 1 for field_name in errors: response = values[field_name] IncorrectResponse2.create(player=player, field_name=field_name, response=str(response)) return errors @staticmethod def vars_for_template(player): failed = 1 if player.comp1_failed_attempts>0 else 0 return dict(failed=failed) class CompResult2(Page): @staticmethod def before_next_page(player, timeout_happened): order(player) prepare_cognitiveload(player) page_sequence = [Instructions0, Instructions1,PreComprehension1,Comprehension1,CompResult1, Instructions2,PreComprehension2,Comprehension2,CompResult2]