from otree.api import ( models, widgets, BaseConstants, BaseSubsession, BaseGroup, BasePlayer, Currency as c, currency_range, safe_json ) import itertools import random author = 'Thomas Graeber' doc = """ Assign treatment status. """ class Constants(BaseConstants): """Contains constants of the current experiment app.""" name_in_url = 'belief_formation' players_per_group = None tasks = [ [ { 'name': "p50_d70_1red", 'type': "baseline", 'specification': { 'n_chips': 10, 'a_chips': 5, 'b_chips': 5, 'prior': 50, 'red_chips_a': 70, 'blue_chips_a': 30, 'n_sample': 1, 'red_sample': 1, 'blue_sample': 0, 'bayes': 70, } }, { 'name': "p50_d70_3red_seq", 'type': "sequential", 'specification': { 'n_chips': 10, 'a_chips': 5, 'b_chips': 5, 'prior': 50, 'red_chips_a': 70, 'blue_chips_a': 30, 'n_sample': 1, 'red_sample': 1, 'blue_sample': 0, 'n_sample2': 2, 'red_sample2': 2, 'blue_sample2': 0, 'bayes': 92.7, } } ], [ { 'name': "p90_d70_1red", 'type': "baseline", 'specification': { 'n_chips': 10, 'a_chips': 9, 'b_chips': 1, 'prior': 90, 'red_chips_a': 70, 'blue_chips_a': 30, 'n_sample': 1, 'red_sample': 1, 'blue_sample': 0, 'bayes': 95.45, } } ], [ { 'name': "p90_d70_1blue", 'type': "baseline", 'specification': { 'n_chips': 10, 'a_chips': 9, 'b_chips': 1, 'prior': 90, 'red_chips_a': 70, 'blue_chips_a': 30, 'n_sample': 1, 'red_sample': 0, 'blue_sample': 1, 'bayes': 79.41, } } ], [ { 'name': "p50_d70_5red_2blue", 'type': "baseline", 'specification': { 'n_chips': 10, 'a_chips': 5, 'b_chips': 5, 'prior': 50, 'red_chips_a': 70, 'blue_chips_a': 30, 'n_sample': 7, 'red_sample': 5, 'blue_sample': 2, 'bayes': 92.7, } } ], [ { 'name': "p50_d70_3red", 'type': "baseline", 'specification': { 'n_chips': 10, 'a_chips': 5, 'b_chips': 5, 'prior': 50, 'red_chips_a': 70, 'blue_chips_a': 30, 'n_sample': 3, 'red_sample': 3, 'blue_sample': 0, 'bayes': 92.7, } } ], [ { 'name': "p50_d70_15red_6blue", 'type': "baseline", 'specification': { 'n_chips': 10, 'a_chips': 5, 'b_chips': 5, 'prior': 50, 'red_chips_a': 70, 'blue_chips_a': 30, 'n_sample': 21, 'red_sample': 15, 'blue_sample': 6, 'bayes': 99.95, } } ], [ { 'name': "p50_d90_1red", 'type': "baseline", 'specification': { 'n_chips': 10, 'a_chips': 5, 'b_chips': 5, 'prior': 50, 'red_chips_a': 90, 'blue_chips_a': 10, 'n_sample': 1, 'red_sample': 1, 'blue_sample': 0, 'bayes': 90, } } ], [ { 'name': "p50_d60_1red", 'type': "baseline", 'specification': { 'n_chips': 10, 'a_chips': 5, 'b_chips': 5, 'prior': 50, 'red_chips_a': 60, 'blue_chips_a': 40, 'n_sample': 1, 'red_sample': 1, 'blue_sample': 0, 'bayes': 60, } } ], [ { 'name': "p60_d70_5red_4blue", 'type': "baseline", 'specification': { 'n_chips': 10, 'a_chips': 6, 'b_chips': 4, 'prior': 60, 'red_chips_a': 70, 'blue_chips_a': 30, 'n_sample': 9, 'red_sample': 5, 'blue_sample': 4, 'bayes': 77.8, } }, { 'name': "p90_d70_5red_4blue", 'type': "baseline", 'specification': { 'n_chips': 10, 'a_chips': 9, 'b_chips': 1, 'prior': 90, 'red_chips_a': 70, 'blue_chips_a': 30, 'n_sample': 9, 'red_sample': 5, 'blue_sample': 4, 'bayes': 95.45, } } ], ] conditions = [ 'baseline' ] num_rounds = len(tasks) class Subsession(BaseSubsession): """Contains subsession-level objects of the current experiment app.""" def before_session_starts(self): """Depending on session configs, get respective list of treatment conditions from constants. Then distribute treatment conditions and groups to participants. """ if self.round_number == 1: conditions = itertools.cycle(Constants.conditions) for p in self.get_players(): p.participant.vars['condition'] = next(conditions) p.participant.vars['task_sequence'] = random.sample(range(0, Constants.num_rounds), Constants.num_rounds) p.participant.vars['task_conditions'] = [] p.participant.vars['paying_round'] = random.randint(1, Constants.num_rounds) for r in p.participant.vars['task_sequence']: p.participant.vars['task_conditions'].append(random.randint(0, len(Constants.tasks[r])-1)) for p in self.get_players(): p.set_current_task_identifier() p.set_task_specification_in_data() p.condition = p.participant.vars['condition'] if p.round_number == p.participant.vars['paying_round']: p.on_paying_round = True class Group(BaseGroup): """Contains group-level objects of the current experiment app.""" pass class Player(BasePlayer): """Contains player-level objects of the current experiment app.""" condition = models.StringField() task_identifier = models.StringField() wtp = models.FloatField() on_paying_round = models.BooleanField(initial=False) total_payoff = models.FloatField() prior = models.FloatField() bayesian_posterior = models.FloatField() sample_size = models.IntegerField() sample_fraction_red = models.FloatField() diagnosticity = models.FloatField() answer2 = models.FloatField( min=0, max=100, blank=False, ) answer = models.FloatField( min=0, max=100, blank=False, ) difficulty = models.IntegerField( choices=[ [1, '1 = not difficult at all'], [2, '2'], [3, '3'], [4, '4'], [5, '5'], [6, '6'], [7, '7 = extremely difficult'], ], widget=widgets.RadioSelectHorizontal, label="" ) def set_current_task_identifier(self): # setattr(self, 'task_number', self.participant.vars['page_sequence'][self.round_number - 1]) task_version = self.participant.vars['task_conditions'][self.round_number-1] task = self.participant.vars['task_sequence'][self.round_number-1] setattr(self, 'task_identifier', Constants.tasks[task][task_version]['name']) # setattr(self, 'task_identifier', self.participant.vars['page_sequence'][self.round_number-1]) def set_task_specification_in_data(self): task_version = self.participant.vars['task_conditions'][self.round_number-1] task = self.participant.vars['task_sequence'][self.round_number-1] setattr(self, 'prior', Constants.tasks[task][task_version]['prior']/100) setattr(self, 'bayesian_posterior', Constants.tasks[task][task_version]['bayes']) setattr(self, 'sample_size', Constants.tasks[task][task_version]['n_sample']) setattr(self, 'sample_fraction_red', Constants.tasks[task][task_version]['red_sample']/self.sample_size) setattr(self, 'diagnosticity', Constants.tasks[task][task_version]['red_chips_a']/100) def specification(self): task_version = self.participant.vars['task_conditions'][self.round_number-1] task = self.participant.vars['task_sequence'][self.round_number-1] return Constants.tasks[task][task_version]['specification'] def set_type(self): task_version = self.participant.vars['task_conditions'][self.round_number-1] task = self.participant.vars['task_sequence'][self.round_number-1] return Constants.tasks[task][task_version]['type'] def set_payoffs(self): # Setup task_version = self.participant.vars['task_conditions'][self.round_number-1] task = self.participant.vars['task_sequence'][self.round_number-1] purchased_machine = False bayesian_guess = Constants.tasks[task][task_version]['specification']['bayes'] urn_A_drawn = (bayesian_guess > random.random()) prize_lottery_q = random.random() won_prize = False get_paid = (random.randint(1, self.session.config['every_xth_person_paid']) == 1) # Determine payoff if get_paid: wtp_draw = round(random.uniform(0, self.session.config['endowment']), 2) if self.wtp > wtp_draw: purchased_machine = True if purchased_machine and random.random() < self.session.config['machine_probability']/100: counting_guess = bayesian_guess else: counting_guess = self.answer if urn_A_drawn and counting_guess > prize_lottery_q: won_prize = True elif not urn_A_drawn and counting_guess < prize_lottery_q: won_prize = True self.participant.vars['bonus'] = self.session.config['endowment'] if won_prize: self.participant.vars['bonus'] += self.session.config['prize'] if purchased_machine: self.participant.vars['bonus'] -= wtp_draw else: self.participant.vars['bonus'] = 0 self.payoff = self.participant.vars['bonus']