import random import numpy as np from otree.api import * doc = """ Informational Cost of Interventions - baseline & deterministic app with 10 rounds. In base its 5 Part 1s, 1 Part 2, 5 Part 1s and 1 Part 2. In Det its 5 Treatments, 5 Part 1s, and 1 Part 2. """ class C(BaseConstants): NAME_IN_URL = 'strategy_method' PLAYERS_PER_GROUP = None PARAMETERIZATIONS = list(range(1, 11)) NUM_ROUNDS = len(PARAMETERIZATIONS) OUTSIDE_OPTION = cu(2.2) PROBABILITY_OF_SWITCH = 0.25 REVIEW_INSTRUCTIONS = 'informational_cost/reviewInstructions.html' COMPUTER_INTRO_TYPES = 'informational_cost/computerTypes.html' COMPUTER_INTRO_TYPES_INTRO = 'intro/computerTypes.html' PART1_TEMPLATE = 'intro/part1.html' # this comes from the other app PART2_TEMPLATE = 'informational_cost/part2.html' BONUS_PART1_TEMPLATE = 'informational_cost/bonus_part1.html' BONUS_PART2_TEMPLATE = 'informational_cost/bonus_part2.html' INSTRUCTIONS1_TEMPLATE = 'informational_cost/instructions1_template.html' PART1_INTRO_TEMPLATE = 'intro/part1.html' PART2_INTRO_TEMPLATE = 'intro/part2.html' BONUS_INTRO_TEMPLATE = 'intro/bonus.html' # Each of the 5 stages corresponds to our parameterization as in the overleaf document LABEL_POOL = ['Green', 'Blue', 'Orange', 'Purple', 'Gray', 'Black', 'Gold', 'Silver', 'Navy', 'Indigo'] LABEL_SEP = ['Yellow', 'Red', 'Violet', 'Pink', 'Brown', 'Beige', 'White', 'Maroon', 'Burgundy', 'Olive'] class Subsession(BaseSubsession): pass # def make_field_bonusChoice_sep(): # choices = [ # [1, 'The amount produced by the Good computer.'], # [2, 'The amount produced by the Bad computer.'], # [3, 'The fixed payment, independent of how much the computers produce.'] # ] # random.shuffle(choices) # return models.IntegerField(blank=True, # choices=choices, # widget=widgets.RadioSelect) # # def make_field_bonusChoice_pool(): # x = random.randint(1, 2) # print('x='+str(x)) # choices = [ # [x, 'The amount produced by the computer of unknown quality.'], # # [2, 'The amount produced by the computer of unknown quality.'], # [3, 'The fixed payment, independent of how much the computers produce.'] # ] # random.shuffle(choices) # return models.IntegerField(blank=True, # choices=choices, # widget=widgets.RadioSelect) class Group(BaseGroup): pass class Player(BasePlayer): timeSpent = models.FloatField() # one unit is 100 milliseconds (a decimal of a second): 96 means 9.6 secs timeSpentBonus = models.FloatField() # one unit is 100 milliseconds (a decimal of a second): 96 means 9.6 secs cq1_intro = models.IntegerField(blank=True, choices=[ [1, 'It does not do anything.'], [2, 'It solves different tasks.'], [3, 'It decides what task it solves.'] ], widget=widgets.RadioSelect, label='What does the computer do?' ) cq2_intro = models.IntegerField(blank=True, choices=[ [1, 'Only one, which can be of Good or the Bad quality.'], [2, 'Two, one of Good quality and one of Bad quality.'], [3, 'There are no computers.'] ], widget=widgets.RadioSelect, label='How many computers are there in this decision?' ) cq3_intro = models.IntegerField(blank=True, choices=[ [1, 'Yes, there is only one computer which solves tasks in both part 1 ' 'and part 2, but the computer can be of a different quality in part 1 and part 2.'], [2, 'No, there are two computers, one for each part.'], [3, 'Yes, there is only one computer in this decision which solves tasks in both ' 'part 1 and part 2, and the computer is of the same quality in both parts.'] ], widget=widgets.RadioSelect, label='Is the computer that solves the task in part 1 the same as the one that ' 'solves the task in part 2 in this decision?' ) cq1_intro_det = models.IntegerField(blank=True, choices=[ [1, 'They do not do anything.'], [2, 'They solve tasks.'], [3, 'They decide what task they solve.'] ], widget=widgets.RadioSelect, label='What do the computers do?' ) cq2_intro_det = models.IntegerField(blank=True, choices=[ [1, 'Only one, which can be of Good or the Bad quality.'], [2, 'Two, one of Good quality and one of Bad quality.'], [3, 'There are no computers.'] ], widget=widgets.RadioSelect, label='How many computers are there in this decision?' ) cq3_intro_det = models.IntegerField(blank=True, choices=[ [1, 'Yes, there are two computers which solve tasks in both part 1 ' 'and part 2, but the computers can be of different quality in part 1 and part 2.'], [2, 'No, there are four computers, two for each part.'], [3, 'Yes, there are two computers in this decision which solve tasks in both ' 'part 1 and part 2, and the computers are of the same quality in both parts.'] ], widget=widgets.RadioSelect, label='Are the computers that solve the task in part 1 the same as the ones ' 'that solve the task in part 2 in this decision?' ) cq1 = models.IntegerField(blank=True, widget=widgets.RadioSelect, label='In part 2 of this decision, which type of task does the computer solve?' ) cq2 = models.IntegerField(blank=True, widget=widgets.RadioSelect, label='How is your bonus determined in this decision?' ) # cq3 = models.IntegerField(blank=True, # widget=widgets.RadioSelect, # label=" Which task allows you to tell the computer's quality after part 1? " # "" # ) # cq_part2 = models.IntegerField(blank=True, # widget=widgets.RadioSelect) for j in range(1, 4): locals()['cq' + str(j) + '_intro_mistakes'] = models.IntegerField(blank=True, initial=0) del j for j in range(1, 4): locals()['cq' + str(j) + '_intro_det_mistakes'] = models.IntegerField(blank=True, initial=0) del j intro_cq_mistakes = models.IntegerField(blank=True) for j in range(1, 4): locals()['cq' + str(j) + '_mistakes'] = models.IntegerField(blank=True, initial=0) del j # cq_part2_mistakes = models.IntegerField(blank=True, initial=0) info_cost_cq_mistakes = models.IntegerField(blank=True, initial=0) bonusChoice = models.IntegerField(blank=True, widget=widgets.RadioSelect, label='How do you want your bonus for part 2 to be determined?') environment_choice = models.BooleanField( widget=widgets.RadioSelect, blank=True) message = models.LongStringField(blank=True, label='What approach did you use in the last 5 decisions?') explain = models.LongStringField(blank=True) approach = models.LongStringField(blank=True, label= 'Throughout this study, what was your approach to choosing the task? Did it change over time?') advice = models.IntegerField(blank=True, widget=widgets.RadioSelect ) change = models.IntegerField(blank=True, choices=[ [1, 'Yes'], [2, 'No'] ], widget=widgets.RadioSelect ) sep_task = models.IntegerField(blank=True, widget=widgets.RadioSelect ) bonusChoicePool = models.IntegerField(blank=True, widget=widgets.RadioSelect) bonusChoiceSep = models.IntegerField(blank=True, widget=widgets.RadioSelect) # bonusChoiceSepBad = make_field_bonusChoice() bonus_guess_plan = models.FloatField(blank=True, label='Average bonus of participants with the planning tool:') bonus_guess_no_plan = models.FloatField(blank=True, label='Average bonus of participants without the planning tool:') # FUNCTIONS def environment_choice_choices(player): pp = player.participant ps = player.session current_parameterization = pp.param_rounds[player.round_number - 1] part1_bonus = ps.parameterization[current_parameterization - 1][:3] part2_bonus = ps.parameterization[current_parameterization - 1][-2:] comp_type = pp.compType[player.round_number - 1] if player.participant.treatment == 'strategy': if player.bonusChoicePool == 3: # if in pooling they chose outside option choices = [ [True, C.LABEL_POOL[player.round_number - 1] + " task. The computers produce " + str(cu(part1_bonus[0]*2)) + " and you get a " + str(C.OUTSIDE_OPTION) + " bonus in part 2, as you selected."]] else: choices = [ [True, C.LABEL_POOL[player.round_number - 1] + " task. You get a " + str(cu(part1_bonus[0]*2)) + ' bonus in part 1. If you chose the Good computer, you get a ' + str(cu(part2_bonus[0])) + " bonus in part 2." " If you chose the Bad computer, you get a " + str(cu(part2_bonus[1])) + " bonus in part 2."]] # part_1_bonus = str(cu(part1_bonus[1])) if comp_type == 1 else str(cu(part1_bonus[2])) if player.bonusChoiceSep == 3: # if in separating they chose outside option choices.append([False, C.LABEL_SEP[player.round_number-1] + " task. You " "get a " + str(cu(part1_bonus[1]+part1_bonus[2])) + ' bonus in part 1, and a ' + str(C.OUTSIDE_OPTION) + " bonus in part 2."]) if player.bonusChoiceSep == 1: # if in separating they chose Good choices.append([False, C.LABEL_SEP[ player.round_number - 1] + " task. You " "get a " + str(cu(part1_bonus[1] + part1_bonus[2])) + ' bonus in part 1, and a ' + str(cu(part2_bonus[0])) + " bonus in part 2."]) if player.bonusChoiceSep == 2: choices.append([False, C.LABEL_SEP[ player.round_number - 1] + " task. You " "get a " + str(cu(part1_bonus[1] + part1_bonus[2])) + ' bonus in part 1, and a ' + str( cu(part2_bonus[1])) + " bonus in part 2."]) else: choices = [ [True, C.LABEL_POOL[player.round_number - 1] + ' task.'], [False, C.LABEL_SEP[player.round_number - 1] + ' task.']] # elif player.bonusChoiceSepBad == 3: # if in separating-bad they chose outside option # choices.append([False, C.LABEL_SEP[player.round_number-1] + " task. If the computer is of the Good quality, you " # "get a " + str(cu(part1_bonus[1])) + # ' bonus in part 1, and a ' + str(C.OUTSIDE_OPTION) + " bonus in part 2. If it is of the Bad quality, " # "you get a " + str(cu(part1_bonus[2])) + # ' bonus in part 1, and a ' + str(C.OUTSIDE_OPTION) + " bonus in part 2."]) # elif player.bonusChoiceSepGood == 1: # if in separating-good they chose hire # if player.bonusChoiceSepBad == 1: # if in separating-bad they chose hire # choices.append([False, C.LABEL_SEP[player.round_number-1] + " task. If the computer is of the Good quality, you " # "get a " + str(cu(part1_bonus[1])) + # ' bonus in part 1, and a ' + str(cu(part2_bonus[0])) + # " bonus in part 2. If it is of the Bad quality, you get a " + str(cu(part1_bonus[2])) + # ' bonus in part 1, and a ' + str(cu(part2_bonus[1])) + " bonus in part 2."]) # elif player.bonusChoiceSepBad == 3: # if in separating-bad they chose outside option # choices.append([False, C.LABEL_SEP[player.round_number-1] + " task. If the computer is of the Good quality, you " # "get a " + str(cu(part1_bonus[1])) + # ' bonus in part 1, and a ' + str(cu(part2_bonus[0])) + # " bonus in part 2. If it is of the Bad quality, you get a " + str(cu(part1_bonus[2])) + # ' bonus in part 1, and a ' + str(C.OUTSIDE_OPTION) + " bonus in part 2."]) random.shuffle(choices) return choices def sep_task_choices(player): choices = [ [1, C.LABEL_SEP[-1]], [2, C.LABEL_POOL[-1]] ] random.shuffle(choices) return choices # def cq_part2_choices(player): # pp = player.participant # chosen_decision_index = pp.chosen_decisions # if pp.treatment == 'deterministic' and chosen_decision_index < 6: # choices = [ # [1, 'No, I will never learn exactly how much each computer produced.'], # [2, 'Yes, I will learn about it, but only once the experiment ends and I get my bonus payment.'], # [3, 'Yes, I will learn how much each computer produced before part 2.'] # ] # elif pp.treatment == 'salient' and chosen_decision_index < 6: # if player.environment_choice: # choices = [ # [3, "No, we will not tell you the computer's quality."], # [2, "Yes, we will tell you the computer's quality, but only once the experiment ends and you get " # "your bonus payment."], # [1, "Yes, we will tell you the computer's quality before part 2."], # ] # else: # choices = [ # [1, "No, we will not tell you the computer's quality."], # [2, "Yes, we will tell you the computer's quality, but only once the experiment ends and you get " # "your bonus payment."], # [3, "Yes, we will tell you the computer's quality before part 2."], # ] # else: # choices = [ # [1, 'No, I will never learn exactly how much the computer produced.'], # [2, 'Yes, I will learn about it, but only once the experiment ends and I get ' # 'my bonus payment.'], # [3, 'Yes, I will learn how much the computer produced before part 2.'], # ] # return choices # def cq_part2_error_message(player, value): # if not player.session.config['development']: # if value is None: # return 'Please, answer the question.' # elif value != 3: # player.cq_part2_mistakes += 1 # return 'Your answer is incorrect.' def cq1_choices(player): pp = player.participant if not pp.base: choices = [ [1, 'They solve the ' + C.LABEL_POOL[player.round_number-1] + ' task, and the ' + C.LABEL_SEP[player.round_number-1] + ' task, for a total of two tasks.'], [2, 'It has not yet been decided. It is my task to decide it.'], [3, 'They solve the ' + C.LABEL_SEP[player.round_number-1] + ' task.'], [4, 'They solve the ' + C.LABEL_POOL[player.round_number - 1] + ' task.'] ] else: choices = [ [1, 'It solves the ' + C.LABEL_POOL[player.round_number-1] + ' task, and the ' + C.LABEL_SEP[player.round_number-1] + ' task, for a total of two tasks.'], [2, 'It has not yet been decided. It is my task to decide it.'], [3, 'It solves the ' + C.LABEL_SEP[player.round_number-1] + ' task.'], [4, 'It solves the ' + C.LABEL_POOL[player.round_number - 1] + ' task.'] ] random.shuffle(choices) return choices def cq1_error_message(player, value): if not player.session.config['development']: if value is None: return 'Please, answer the question.' elif value != 3: player.cq1_mistakes += 1 return 'Your answer is incorrect. Please review the instructions for this decision.' def cq2_choices(player): pp = player.participant if not pp.base: choices = [ [1, 'For each task that the computers solve, I get ' + str(cu(player.session.parameterization[player.participant.param_rounds[player.round_number-1] - 1][0]) ) + '. This applies to both tasks.'], [2, "In part 1, I get whatever amount the computers produce in that part's tasks. " "I can choose my bonus for part 2 to be whatever amount the computer of my choice" " produces in that part's task or a fixed bonus of " + str(C.OUTSIDE_OPTION) + '.'], [3, 'For each task the computers solve, I get the amount they produce.' ' This applies to both tasks, and I get ' + str(C.OUTSIDE_OPTION) + ' on top of it.'] ] else: choices = [ [1, 'For each task that the computer solves, I get ' + str(cu(player.session.parameterization[player.participant.param_rounds[player.round_number-1] - 1][0]) ) + '. This applies to both tasks.'], [2, "In part 1, I get whatever amount the computer produces in that part's task. " "I can choose my bonus for part 2 to be whatever amount the computer produces in that part's " "task or a fixed bonus of " + str(C.OUTSIDE_OPTION) + '.'], [3, 'For each task the computer solves, I get the amount it produces.' ' This applies to both tasks, and I get ' + str(C.OUTSIDE_OPTION) + ' on top of it.'] ] random.shuffle(choices) return choices def cq2_error_message(player, value): if not player.session.config['development']: if value is None: return 'Please, answer the question.' elif value != 2: player.cq2_mistakes += 1 return 'Your answer is incorrect. Please review the instructions for this decision.' # def cq3_choices(player): # pp = player.participant # choices = [ # [1, C.LABEL_POOL[player.round_number-1] + ' task.'], # [2, C.LABEL_SEP[player.round_number-1] + ' task.'] # ] # random.shuffle(choices) # return choices # def cq3_error_message(player, value): # if not player.session.config['development']: # if value is None: # return 'Please, answer the question.' # elif value != 2: # player.cq3_mistakes += 1 # return 'Your answer is incorrect. Please review the instructions for this decision.' def bonusChoicePool_choices(player): pp = player.participant ps = player.session # chosen_decision_index = pp.chosen_decisions part1_bonus = ps.parameterization[pp.param_rounds[player.round_number - 1] - 1][:3] part1_bonus_pool = cu(part1_bonus[0]) x = player.participant.pool_choice[player.round_number-1] if player.participant.treatment == 'strategy': choices = [ [x, 'Both computers are of unknown quality. I want to get what one of them, chosen randomly, produces in part 2 as my bonus.'], # [2, 'The amount produced by the computer of unknown quality.'], [3, 'I want to get the fixed payment as my bonus.'] ] else: choices = [ [x, 'Both computers produce '+ str(part1_bonus_pool) + ' in the ' + str(C.LABEL_POOL[player.round_number - 1]) +' task in part 1. I want to get what one of them, chosen randomly, produces in part 2 as my bonus.'], # [2, 'The amount produced by the computer of unknown quality.'], [3, 'I want to get the fixed payment as my bonus.'] ] random.shuffle(choices) return choices def bonusChoiceSep_choices(player): pp = player.participant ps = player.session # chosen_decision_index = pp.chosen_decisions part1_bonus = ps.parameterization[pp.param_rounds[player.round_number - 1] - 1][:3] part1_bonus_good_sep = cu(part1_bonus[1]) part1_bonus_bad_sep = cu(part1_bonus[2]) # chosen_decision_index = pp.chosen_decisions if player.participant.treatment == 'strategy': choices = [ [1, 'This computer is Good. I want to get what it produces in part 2 as my bonus.'], [2, 'This computer is Bad. I want to get what it produces in part 2 as my bonus.'], [3, 'I want to get the fixed payment as my bonus.'] ] else: choices = [ [1, 'This computer produces '+ str(part1_bonus_good_sep) + ' in the ' + str(C.LABEL_SEP[player.round_number - 1]) +' task in part 1. I want to get what it produces in part 2 as my bonus.'], [2, 'This computer produces '+ str(part1_bonus_bad_sep) + ' in the ' + str(C.LABEL_SEP[player.round_number - 1]) +' task in part 1. I want to get what it produces in part 2 as my bonus.'], [3, 'I want to get the fixed payment as my bonus.'] ] random.shuffle(choices) return choices def bonusChoice_error_message(player, value): if not player.session.config['development'] and value is None: return 'Please, answer the question.' def environment_choice_error_message(player, value): if not player.session.config['development'] and value is None: return 'Please, answer the question.' def vars_for_template1(player: Player): pp = player.participant ps = player.session current_parameterization = pp.param_rounds[player.round_number - 1] # chosen_decision_index = pp.chosen_decisions # chosen_decision = chosen_decision_index if chosen_decision_index < 6 else chosen_decision_index - 5 part2_bonus = ps.parameterization[current_parameterization - 1][-2:] part1_bonus = ps.parameterization[current_parameterization - 1][:3] return dict( comp_type=pp.compType[player.round_number-1], part2_bonus_good=cu(part2_bonus[0]), part2_bonus_bad=cu(part2_bonus[1]), part1_bonus_pool=cu(part1_bonus[0]), part1_bonus_good_sep=cu(part1_bonus[1]), part1_bonus_bad_sep=cu(part1_bonus[2]), current_parameterization=current_parameterization, # chosen_decision=chosen_decision, label_pool=C.LABEL_POOL[player.round_number-1], label_sep=C.LABEL_SEP[player.round_number-1], stage2_rounds=player.round_number - 5, # stage_of_chosen_decision=1 if chosen_decision_index < 6 else 2, decision_name = C.LABEL_POOL[player.round_number - 1] + '/' + C.LABEL_SEP[player.round_number - 1] ) def advice_choices(player): choices = [ [1, 'Advise that the computer solves the ' + C.LABEL_POOL[-1] + ' task.'], [2, 'Advise that the computer solves the ' + C.LABEL_SEP[-1] + ' task.'] ] return choices # PAGES class Parameterization(Page): vars_for_template = vars_for_template1 @staticmethod def before_next_page(player: Player, timeout_happened): print(player.participant.param_rounds[player.round_number-1]) class CQIntro(Page): form_model = 'player' @staticmethod def is_displayed(player: Player): return player.round_number == 1 @staticmethod def get_form_fields(player): questions = ['cq1_intro', 'cq2_intro', 'cq3_intro'] if not player.participant.base: questions = [x + '_det' for x in questions] return questions @staticmethod def error_message(player, values): if not player.session.config['development']: if player.participant.base: solutions = dict(cq1_intro=2, cq2_intro=1, cq3_intro=3 ) else: solutions = dict(cq1_intro_det=2, cq2_intro_det=2, cq3_intro_det=3 ) error_messages = dict() for field_name in solutions: if values[field_name] is None: error_messages[field_name] = 'Please, answer the question.' elif values[field_name] != solutions[field_name]: error_messages[field_name] = 'Please, correct your answer!' name = 'player.' + str(field_name) + '_mistakes' exec("%s += 1" % name) return error_messages @staticmethod def before_next_page(player: Player, timeout_happened): if not player.participant.base: player.intro_cq_mistakes = player.cq1_intro_det_mistakes + player.cq2_intro_det_mistakes + player.cq3_intro_det_mistakes else: player.intro_cq_mistakes = player.cq1_intro_mistakes + player.cq2_intro_mistakes + player.cq3_intro_mistakes player.participant.pool_choice = random.choices([1, 2], k=C.NUM_ROUNDS) # + player.cq4_mistakes + player.cq5_mistakes + player.cq1_det_mistakes + player.cq2_det_mistakes + \ # player.cq3_det_mistakes + player.cq4_det_mistakes @staticmethod def vars_for_template(player): pp = player.participant ps = player.session # chosen_decision_index = pp.chosen_decisions current_parameterization = pp.param_rounds[player.round_number - 1] part2_bonus = ps.parameterization[current_parameterization - 1][-2:] part1_bonus = ps.parameterization[current_parameterization - 1][:3] return dict( label_pool=C.LABEL_POOL[player.round_number - 1], label_sep=C.LABEL_SEP[player.round_number - 1], # stage_of_chosen_decision=1 if chosen_decision_index < 6 else 2, current_parameterization=current_parameterization, part2_bonus_good=cu(part2_bonus[0]), part2_bonus_bad=cu(part2_bonus[1]), part1_bonus_pool=cu(part1_bonus[0]), part1_bonus_good_sep=cu(part1_bonus[1]), part1_bonus_bad_sep=cu(part1_bonus[2]), ) class CQ(Page): form_model = 'player' @staticmethod def get_form_fields(player): form_fields = ['cq1'] if player.round_number == 1: form_fields += ['cq2'] return form_fields @staticmethod def before_next_page(player: Player, timeout_happened): player.info_cost_cq_mistakes = player.cq1_mistakes + player.cq2_mistakes @staticmethod def vars_for_template(player): pp = player.participant ps = player.session current_parameterization = pp.param_rounds[player.round_number - 1] # chosen_decision_index = pp.chosen_decisions # chosen_decision = chosen_decision_index if chosen_decision_index < 6 else chosen_decision_index - 5 part2_bonus = ps.parameterization[current_parameterization - 1][-2:] part1_bonus = ps.parameterization[current_parameterization - 1][:3] if not player.participant.base: cq1_label = 'In part 2 of this decision, which task do the computers solve?' else: cq1_label = 'In part 2 of this decision, which task does the computer solve?' cq2_label = 'How is your bonus determined in this decision?' return dict( comp_type=pp.compType[player.round_number - 1], part2_bonus_good=cu(part2_bonus[0]), part2_bonus_bad=cu(part2_bonus[1]), part1_bonus_pool=cu(part1_bonus[0]), part1_bonus_good_sep=cu(part1_bonus[1]), part1_bonus_bad_sep=cu(part1_bonus[2]), current_parameterization=current_parameterization, # chosen_decision=chosen_decision, label_pool=C.LABEL_POOL[player.round_number - 1], label_sep=C.LABEL_SEP[player.round_number - 1], stage2_rounds=player.round_number - 5, # stage_of_chosen_decision=1 if chosen_decision_index < 6 else 2, cq1_label=cq1_label, cq2_label=cq2_label, current_round = player.round_number ) class EnvironmentStage(Page): form_model = 'player' form_fields = ['environment_choice', 'timeSpent'] def vars_for_template(player: Player): pp = player.participant ps = player.session current_parameterization = pp.param_rounds[player.round_number - 1] # chosen_decision_index = pp.chosen_decisions # chosen_decision = chosen_decision_index if chosen_decision_index < 6 else chosen_decision_index - 5 part2_bonus = ps.parameterization[current_parameterization - 1][-2:] part1_bonus = ps.parameterization[current_parameterization - 1][:3] label = 'Which task do you want the computers to solve in part 1?' if not pp.base \ else 'Which task do you want the computer to solve in part 1?' return dict( comp_type=pp.compType[player.round_number - 1], part2_bonus_good=cu(part2_bonus[0]), part2_bonus_bad=cu(part2_bonus[1]), part1_bonus_pool=cu(part1_bonus[0]), part1_bonus_good_sep=cu(part1_bonus[1]), part1_bonus_bad_sep=cu(part1_bonus[2]), current_parameterization=current_parameterization, # chosen_decision=chosen_decision, label_pool=C.LABEL_POOL[player.round_number-1], label_sep=C.LABEL_SEP[player.round_number-1], label=label, stage2_rounds=player.round_number - 5, # stage_of_chosen_decision=1 if chosen_decision_index < 6 else 2, decision_name = C.LABEL_POOL[player.round_number - 1] + '/' + C.LABEL_SEP[player.round_number - 1] ) @staticmethod def error_message(player, values): if player.session.config['development']: values['environment_choice'] = True player.environment_choice = True elif values['environment_choice'] is None: return 'Please, answer the question.' @staticmethod def before_next_page(player, timeout_happened): environment_choice_MaybeNone = player.field_maybe_none('environment_choice') if player.session.config['development'] and environment_choice_MaybeNone is None: player.environment_choice = True @staticmethod def is_displayed(player: Player): return player.participant.treatment == 'strategy' # if player.participant.det and player.round_number == 5: # player.participant.det = False # player.participant.base = True # if player.participant.salient and player.round_number == 5: # player.participant.salient = False # player.participant.base = True # class PostDifficultyChoice(Page): # form_model = 'player' # form_fields = ['cq_part2'] # # def vars_for_template(player: Player): # pp = player.participant # chosen_decision_index = pp.chosen_decisions # chosen_decision = chosen_decision_index if chosen_decision_index < 6 else chosen_decision_index - 5 # current_parameterization = pp.param_rounds[player.round_number - 1] # if pp.treatment == 'deterministic' and chosen_decision_index < 6: # label = 'Will you learn how much money each computer produced in part 1?' # elif pp.treatment == 'salient' and chosen_decision_index < 6: # label = "Will we tell you the computer's quality?" # else: # label = 'Will you learn how much money the computer produced in part 1?' # return dict( # comp_type=player.participant.compType[player.round_number - 1], # current_parameterization=current_parameterization, # chosen_decision=chosen_decision, # label_pool=C.LABEL_POOL[player.round_number - 1], # label_sep=C.LABEL_SEP[player.round_number - 1], # label=label, # environment_chosen_decision=player.environment_choice, # ) # class ObserveMistakes(Page): # @staticmethod # def vars_for_template(player: Player): # pp = player.participant # ps = player.session # chosen_decision_index = pp.chosen_decisions # chosen_decision = chosen_decision_index if chosen_decision_index < 6 else chosen_decision_index - 5 # part1_bonus = ps.parameterization[player.participant.param_rounds[player.round_number - 1] - 1][:3] # myDict = dict(chosen_decision=chosen_decision, # environment_chosen_decision=player.environment_choice, # label_pool=C.LABEL_POOL[player.round_number - 1], # label_sep=C.LABEL_SEP[player.round_number - 1], # stage_of_chosen_decision=1 if chosen_decision_index < 6 else 2, # part1_bonus_pool=cu(part1_bonus[0]), # part1_bonus_good_sep=cu(part1_bonus[1]), # part1_bonus_bad_sep=cu(part1_bonus[2]), # current_parameterization=pp.param_rounds[player.round_number - 1], # comp_type=pp.compType[player.round_number - 1], # ) # # Below we compute payoffs # # if pp.treatment == 'deterministic' and chosen_decision_index < 6: # # if environment_chosen_decision: # pooling chosen # # payoff_part1 = ps.parameterization[pp.param_rounds[chosen_decision_index - 1] - 1][0] * 2 # # pp.part1_payoffs.append(payoff_part1) # # else: # separating chosen # # payoff_part1_good = ps.parameterization[pp.param_rounds[chosen_decision_index - 1] - 1][1] # # payoff_part1_bad = ps.parameterization[pp.param_rounds[chosen_decision_index - 1] - 1][2] # # payoff_part1 = payoff_part1_good + payoff_part1_bad # # pp.part1_payoffs.append(payoff_part1) # # myDict.update(payoff_part1_good=cu(payoff_part1_good), # # payoff_part1_bad=cu(payoff_part1_bad)) # # else: # if player.environment_choice: # pooling chosen # payoff_part1 = ps.parameterization[pp.param_rounds[player.round_number - 1] - 1][0] # else: # separating chosen # if pp.compType[player.round_number - 1] == 1: # if comp is Good # payoff_part1 = ps.parameterization[pp.param_rounds[player.round_number - 1] - 1][1] # else: # if comp is Bad # payoff_part1 = ps.parameterization[pp.param_rounds[player.round_number - 1] - 1][2] # pp.part1_payoffs.append(payoff_part1) # myDict.update(payoff_part1=cu(payoff_part1)) # # if not pp.treatment == 'base': # # pp.part1_payoffs.append(payoff_part1) # return myDict class BonusChoice(Page): form_model = 'player' @staticmethod def get_form_fields(player): questions = ['bonusChoicePool', 'bonusChoiceSep', 'timeSpentBonus'] if player.participant.treatment == 'plan': questions += ['environment_choice'] return questions def vars_for_template(player: Player): pp = player.participant ps = player.session # chosen_decision_index = pp.chosen_decisions # chosen_decision = chosen_decision_index if chosen_decision_index < 6 else chosen_decision_index - 5 part2_bonus = ps.parameterization[pp.param_rounds[player.round_number - 1] - 1][-2:] part1_bonus = ps.parameterization[pp.param_rounds[player.round_number - 1] - 1][:3] if player.participant.treatment=='strategy': label_Pool = 'If the computers solve the ' + str(C.LABEL_POOL[player.round_number - 1]) + \ ' task in part 1 (and hence you will not know their quality):' label_Sep = 'If the computers solve the ' + str(C.LABEL_SEP[player.round_number - 1]) + \ ' task in part 1 (and hence you will know their quality):' else: label_Pool = 'If the computers solve the ' + str(C.LABEL_POOL[player.round_number - 1]) + \ ' task in part 1:' label_Sep = 'If the computers solve the ' + str(C.LABEL_SEP[player.round_number - 1]) + \ ' task in part 1:' label_env = 'Which task do you want the computers to solve in part 1?' # environment_chosen_decision = player.environment_choice payoff_part1_good = ps.parameterization[pp.param_rounds[player.round_number - 1] - 1][1] payoff_part1_bad = ps.parameterization[pp.param_rounds[player.round_number - 1] - 1][2] # stage_of_chosen_decision = 1 if chosen_decision_index < 6 else 2 return dict( comp_type=pp.compType[player.round_number - 1], part2_bonus_good=cu(part2_bonus[0]), part2_bonus_bad=cu(part2_bonus[1]), part1_bonus_pool=cu(part1_bonus[0]), part1_bonus_good_sep=cu(part1_bonus[1]), part1_bonus_bad_sep=cu(part1_bonus[2]), current_parameterization=pp.param_rounds[player.round_number - 1], # chosen_decision=chosen_decision, label_pool=C.LABEL_POOL[player.round_number - 1], label_sep=C.LABEL_SEP[player.round_number - 1], label_env=label_env, # stage_of_chosen_decision=stage_of_chosen_decision, # environment_chosen_decision=environment_chosen_decision, # payoff_part1=cu(pp.part1_payoffs[player.round_number-1]), # payoff_part1_indiv=cu(pp.part1_payoffs[player.round_number-1]/2), # payoff_part1_good=cu(payoff_part1_good), # payoff_part1_bad=cu(payoff_part1_bad), label_Pool=label_Pool, label_Sep=label_Sep, # label_Sep_Bad='If the computer faces the ' + str(C.LABEL_SEP[player.round_number - 1]) + # ' task in part 1 and is of the Bad Quality:', decision_name=C.LABEL_POOL[player.round_number - 1] + '/' + C.LABEL_SEP[player.round_number - 1] ) @staticmethod def before_next_page(player, timeout_happened): bonusChoicePool_MaybeNone = player.field_maybe_none('bonusChoicePool') bonusChoiceSep_MaybeNone = player.field_maybe_none('bonusChoiceSep') environment_choice_MaybeNone = player.field_maybe_none('environment_choice') # bonusChoiceSepBad_MaybeNone = player.field_maybe_none('bonusChoiceSepBad') if player.session.config['development'] and bonusChoicePool_MaybeNone is None: player.bonusChoicePool = 1 if player.session.config['development'] and bonusChoiceSep_MaybeNone is None: player.bonusChoiceSep = 1 if player.session.config['development'] and environment_choice_MaybeNone is None and player.participant.treatment=='plan': player.environment_choice = True # if player.participant.treatment == 'strategy': # player.environment_choice = True # if player.session.config['development'] and bonusChoiceSepBad_MaybeNone is None: # player.bonusChoiceSepBad = 1 @staticmethod def error_message(player, values): if not player.session.config['development'] and values['bonusChoicePool'] is None: return 'Please, answer the question.' if not player.session.config['development'] and values['bonusChoiceSep'] is None: return 'Please, answer the question.' if player.participant.treatment == 'plan' and not player.session.config['development'] and values['environment_choice'] is None: return 'Please, answer the question.' # if not player.session.config['development'] and values['bonusChoiceSepBad'] is None: # return 'Please, answer the question.' class PostBonusChoice(Page): @staticmethod def vars_for_template(player: Player): pp = player.participant ps = player.session if player.environment_choice: # pooling chosen payoff_part1 = cu(ps.parameterization[pp.param_rounds[player.round_number - 1] - 1][0]*2) if player.bonusChoicePool == 1: # if variable payment is chosen and computer is good payoff_part2 = cu(ps.parameterization[pp.param_rounds[player.round_number - 1] - 1][3]) elif player.bonusChoicePool == 2: # variable payment chosen and computer is bad payoff_part2 = cu(ps.parameterization[pp.param_rounds[player.round_number - 1] - 1][4]) else: # if outside option is chosen payoff_part2 = C.OUTSIDE_OPTION # if player.bonusChoicePool == 1: # if variable payment is chosen # if pp.compType[player.round_number - 1] == 1: # variable payment chosen and computer is good # payoff_part2 = cu(ps.parameterization[pp.param_rounds[player.round_number - 1] - 1][3]) # else: # variable payment chosen and computer is bad # payoff_part2 = cu(ps.parameterization[pp.param_rounds[player.round_number - 1] - 1][4]) # else: # if outside option is chosen # payoff_part2 = C.OUTSIDE_OPTION else: # separating chosen payoff_part1 = cu(ps.parameterization[pp.param_rounds[player.round_number - 1] - 1][1]+ps.parameterization[pp.param_rounds[player.round_number - 1] - 1][2]) if player.bonusChoiceSep == 1: # if variable payment is chosen and computer is good payoff_part2 = cu(ps.parameterization[pp.param_rounds[player.round_number - 1] - 1][3]) elif player.bonusChoiceSep == 2: # variable payment chosen and computer is bad payoff_part2 = cu(ps.parameterization[pp.param_rounds[player.round_number - 1] - 1][4]) else: # if outside option is chosen payoff_part2 = C.OUTSIDE_OPTION # if pp.compType[player.round_number - 1] == 1: # if comp is Good # payoff_part1 = cu(ps.parameterization[pp.param_rounds[player.round_number - 1] - 1][1]) # if player.bonusChoiceSepGood == 1: # if variable payment is chosen # payoff_part2 = cu(ps.parameterization[pp.param_rounds[player.round_number - 1] - 1][3]) # else: # if outside option is chosen # payoff_part2 = C.OUTSIDE_OPTION # else: # if comp is Bad # payoff_part1 = cu(ps.parameterization[pp.param_rounds[player.round_number - 1] - 1][2]) # if player.bonusChoiceSepBad == 1: # if variable payment is chosen # payoff_part2 = cu(ps.parameterization[pp.param_rounds[player.round_number - 1] - 1][4]) # else: # if outside option is chosen # payoff_part2 = C.OUTSIDE_OPTION pp.part1_payoffs.append(payoff_part1) pp.part2_payoffs.append(payoff_part2) part2_sep = True if (player.environment_choice and not player.bonusChoicePool == 3) or \ (not player.environment_choice and not player.bonusChoiceSep == 3) else False # if not pp.treatment == 'base': # pp.part2_payoffs.append(payoff_part2) return dict( payoff_part2=payoff_part2, payoff_part1=payoff_part1, payoff_total = payoff_part1+payoff_part2, part2_sep = part2_sep, label_pool=C.LABEL_POOL[player.round_number - 1], label_sep=C.LABEL_SEP[player.round_number - 1], decision_name=C.LABEL_POOL[player.round_number - 1] + '/' + C.LABEL_SEP[player.round_number - 1], progress=int(player.round_number / C.NUM_ROUNDS * 100), part2_unknown=player.environment_choice, part2_good = True if (not player.environment_choice and player.bonusChoiceSep == 1) else False ) # @staticmethod # def before_next_page(player: Player, timeout_happened): # pp = player.participant # all_participant_choices = [] # all_bonus_participant_choices = [] # if not pp.treatment == 'base': # in these treatments we only record the last bonusChoice since its the only one elicited # pp.environment_choice = player.environment_choice # pp.bonus_choices = player.bonusChoice # else: # if player.round_number == C.NUM_ROUNDS: # in baseline we record the last bonusChoice and the one in round 5, which are the two we elicit # all_participant_choices.append(player.in_round(5).environment_choice) # all_participant_choices.append(player.environment_choice) # pp.environment_choice = all_participant_choices # all_bonus_participant_choices.append(player.in_round(5).bonusChoice) # all_bonus_participant_choices.append(player.bonusChoice) # pp.bonus_choices = all_bonus_participant_choices class Transition(Page): @staticmethod def is_displayed(player: Player): return player.round_number == C.NUM_ROUNDS # class TransitionDet(Page): # vars_for_template = vars_for_template1 # # @staticmethod # def is_displayed(player: Player): # return player.round_number == 5 and player.participant.treatment == 'deterministic' class TransitionSalient(Page): vars_for_template = vars_for_template1 @staticmethod def is_displayed(player: Player): return player.round_number == 5 and player.participant.treatment == 'salient' class Message(Page): form_model = 'player' form_fields = ['message'] # @staticmethod # def vars_for_template(player): # ps = player.session # # if player.environment_choice: # # label = 'In part 1 of the last decision, you chose the ' + \ # # C.LABEL_POOL[-1] + ' task. Why did you choose this task?' # # change_label = 'In part 1 of the last decision, you chose the ' + \ # # C.LABEL_POOL[-1] + ' task. If you had a chance to revise your choice, would you prefer to choose the '+ C.LABEL_SEP[-1] + ' task instead?' # # else: # # label = 'In part 1 of the last decision, you chose the ' + \ # # C.LABEL_SEP[-1] + ' task. Why did you choose this task?' # # change_label = 'In part 1 of the last decision, you chose the ' + \ # # C.LABEL_SEP[-1] + ' task. If you had a chance to revise your choice, would you prefer to choose the ' + C.LABEL_POOL[ # # -1] + ' task instead?' # # if not player.participant.base: # # adv_label = 'If you could advise another participant on the last decision of whether the computers ' \ # # 'solve the ' + C.LABEL_POOL[-1] + ' or the ' + C.LABEL_SEP[ # # -1] + ' task, which would you advise ' \ # # 'them to choose?' # # sep_task_label = 'In part 1 of the last decision, which task allows you to learn the quality of the computers?' # # else: # # adv_label = 'If you could advise another participant on the last decision of whether the computer ' \ # # 'solves the ' + C.LABEL_POOL[-1] + ' or the ' + C.LABEL_SEP[-1] + ' task, which would you advise ' \ # # 'them to choose?' # # sep_task_label= 'In part 1 of the last decision, which task allows you to learn the quality of the computer?' # current_parameterization = player.participant.param_rounds[- 1] # part2_bonus = ps.parameterization[current_parameterization - 1][-2:] # part1_bonus = ps.parameterization[current_parameterization - 1][:3] # return dict( # # explain_label=label, # # advice_label=adv_label, # # change_label = change_label, # # sep_task_label=sep_task_label, # label_pool=C.LABEL_POOL[- 1], # label_sep=C.LABEL_SEP[- 1], # # # stage_of_chosen_decision=2, # current_parameterization=current_parameterization, # part2_bonus_good=cu(part2_bonus[0]), # part2_bonus_bad=cu(part2_bonus[1]), # part1_bonus_pool=cu(part1_bonus[0]), # part1_bonus_good_sep=cu(part1_bonus[1]), # part1_bonus_bad_sep=cu(part1_bonus[2]) # ) @staticmethod def error_message(player, values): if not player.session.config['development'] and (values['message']==''): return 'Please, answer the questions.' @staticmethod def is_displayed(player: Player): return player.round_number == C.NUM_ROUNDS class GuessBonus(Page): form_model = 'player' form_fields = ['bonus_guess_plan', 'bonus_guess_no_plan'] @staticmethod def error_message(player, values): if not player.session.config['development'] and (values['bonus_guess_plan'] is None or values['bonus_guess_no_plan'] is None): return 'Please, answer the questions.' @staticmethod def is_displayed(player: Player): return player.round_number == C.NUM_ROUNDS and player.participant.treatment == 'plan' class Hypothetical(Page): form_model = 'player' # form_fields = ['explain', 'approach', 'advice', 'change', 'sep_task'] form_fields = ['explain', 'advice', 'change', 'sep_task'] @staticmethod def vars_for_template(player): ps = player.session if player.environment_choice: label = 'In part 1 of the last decision, you chose the ' + \ C.LABEL_POOL[-1] + ' task. Why did you choose this task?' change_label = 'In part 1 of the last decision, you chose the ' + \ C.LABEL_POOL[-1] + ' task. If you had a chance to revise your choice, would you prefer to choose the ' + C.LABEL_SEP[ -1] + ' task instead?' else: label = 'In part 1 of the last decision, you chose the ' + \ C.LABEL_SEP[-1] + ' task. Why did you choose this task?' change_label = 'In part 1 of the last decision, you chose the ' + \ C.LABEL_SEP[-1] + ' task. If you had a chance to revise your choice, would you prefer to choose the ' + C.LABEL_POOL[ -1] + ' task instead?' adv_label = 'If you could advise another participant on the last decision of whether the computer ' \ 'solves the ' + C.LABEL_POOL[-1] + ' or the ' + C.LABEL_SEP[-1] + ' task, which would you advise ' \ 'them to choose?' sep_task_label = 'In part 1 of the last decision, which task allows you to learn the quality of the computers?' current_parameterization = player.participant.param_rounds[- 1] part2_bonus = ps.parameterization[current_parameterization - 1][-2:] part1_bonus = ps.parameterization[current_parameterization - 1][:3] return dict( explain_label=label, advice_label=adv_label, change_label=change_label, sep_task_label=sep_task_label, label_pool=C.LABEL_POOL[- 1], label_sep=C.LABEL_SEP[- 1], stage_of_chosen_decision=2, current_parameterization=current_parameterization, part2_bonus_good=cu(part2_bonus[0]), part2_bonus_bad=cu(part2_bonus[1]), part1_bonus_pool=cu(part1_bonus[0]), part1_bonus_good_sep=cu(part1_bonus[1]), part1_bonus_bad_sep=cu(part1_bonus[2]), ) @staticmethod def error_message(player, values): # if not player.session.config['development'] and (values['advice'] is None or values['change'] is None or values['sep_task'] is None or values['explain']=='' or values['approach']==''): if not player.session.config['development'] and (values['advice'] is None or values['change'] is None or values['sep_task'] is None or values['explain']==''): return 'Please, answer the questions.' @staticmethod def is_displayed(player: Player): return player.round_number == C.NUM_ROUNDS page_sequence = [ Parameterization, CQIntro, CQ, # PostDifficultyChoice, # ObserveMistakes, BonusChoice, EnvironmentStage, PostBonusChoice, Message, GuessBonus, Hypothetical # Transition # TransitionDet, # TransitionSalient ]