import random from otree.api import * doc = """ For each participant, randomize the order of tasks A, B, and C. Task B has 2 pages, which are always shown in the same order. The page_sequence contains all tasks; in each round we show a randomly determined subset of pages. """ class C(BaseConstants): NAME_IN_URL = 'Charity_Experiment' PLAYERS_PER_GROUP = None FACTOR = cu(5) MULTIPLIER = 2 ENDOWMENT = cu(100) FIXED_PAYMENT = cu(50) PAYMENT_PER_ENVELOPE = cu(5) MAX_ENVELOPES = 20 TASKS = ['A', 'B', 'C'] INITIAL_CONTRIBUTIONS = [cu(0), cu(50), cu(100)] NUM_ROUNDS = len(TASKS) + 2 class Subsession(BaseSubsession): pass class Group(BaseGroup): pass class Player(BasePlayer): payoff_game1 = models.CurrencyField() payoff_game2 = models.CurrencyField() payoff_game3 = models.CurrencyField() win = models.IntegerField() # Game 1 number_entered_1 = models.IntegerField( choices=[[1, 'Heads'], [0, 'Tails']], label="What is the result of your first coin flip?", widget=widgets.RadioSelectHorizontal ) number_entered_2 = models.IntegerField( choices=[[1, 'Heads'], [0, 'Tails']], label="What is the result of your second coin flip?", widget=widgets.RadioSelectHorizontal ) number_entered_3 = models.IntegerField( choices=[[1, 'Heads'], [0, 'Tails']], label="What is the result of your third coin flip?", widget=widgets.RadioSelectHorizontal ) number_entered_4 = models.IntegerField( choices=[[1, 'Heads'], [0, 'Tails']], label="What is the result of your fourth coin flip?", widget=widgets.RadioSelectHorizontal ) number_entered_5 = models.IntegerField( choices=[[1, 'Heads'], [0, 'Tails']], label="What is the result of your fifth coin flip?", widget=widgets.RadioSelectHorizontal ) number_entered_6 = models.IntegerField( choices=[[1, 'Heads'], [0, 'Tails']], label="What is the result of your sixth coin flip?", widget=widgets.RadioSelectHorizontal ) number_entered_7 = models.IntegerField( choices=[[1, 'Heads'], [0, 'Tails']], label="What is the result of your seventh coin flip?", widget=widgets.RadioSelectHorizontal ) number_entered_8 = models.IntegerField( choices=[[1, 'Heads'], [0, 'Tails']], label="What is the result of your eighth coin flip?", widget=widgets.RadioSelectHorizontal ) number_entered_9 = models.IntegerField( choices=[[1, 'Heads'], [0, 'Tails']], label="What is the result of your ninth coin flip?", widget=widgets.RadioSelectHorizontal ) number_entered_10 = models.IntegerField( choices=[[1, 'Heads'], [0, 'Tails']], label="What is the result of your tenth coin flip?", widget=widgets.RadioSelectHorizontal ) def set_payoff_game_1(player): win = player.number_entered_1 + player.number_entered_2 + \ player.number_entered_3 + player.number_entered_4 + \ player.number_entered_5 + player.number_entered_6 + \ player.number_entered_7 + player.number_entered_8 + \ player.number_entered_9 + player.number_entered_10 player.payoff = win * C.FACTOR player.participant.vars['win'] = win player.participant.vars['payoff_game1'] = player.payoff # Game 2 contribution = models.CurrencyField( choices=[[0, '0'], [50, '50'], [100, '100']], label="How much will you contribute?", widget=widgets.RadioSelectHorizontal ) selected_random_numbers = models.StringField() def set_payoff_game_2(player): past_contributions = [ p.vars['contribution'] for p in player.session.get_participants() if 'contribution' in p.vars ] print(past_contributions) choices = C.INITIAL_CONTRIBUTIONS + past_contributions random_numbers = (random.sample(choices, 2)) player.selected_random_numbers = ' & '.join(map(str, random_numbers)) avg_contribution = ((player.contribution + sum(random_numbers))*C.MULTIPLIER)/3 player.payoff = C.ENDOWMENT - player.contribution + avg_contribution player.participant.vars['payoff_game2'] = player.payoff player.participant.vars['contribution'] = player.contribution player.participant.vars['selected_random_numbers'] = player.selected_random_numbers # Game 3 num_envelopes = models.IntegerField( label="How many envelopes did the player fold?", min=0, max=C.MAX_ENVELOPES ) take_fixed_payment = models.BooleanField( label="Do you want to take the fixed payment of 50 rupees instead of folding envelopes?", choices=[ [True, 'Yes'], [False, 'No'] ] ) def set_payoff_game_3(player): if player.take_fixed_payment: player.payoff += C.FIXED_PAYMENT else: num_envelopes = player.field_maybe_none('num_envelopes') if num_envelopes is not None: player.payoff += num_envelopes * C.PAYMENT_PER_ENVELOPE else: player.payoff += cu(0) player.participant.vars['payoff_game3'] = player.payoff player.participant.vars['num_envelopes'] = player.field_maybe_none('num_envelopes') player.participant.vars['take_fixed_payment'] = player.take_fixed_payment # FUNCTIONS def creating_session(subsession: Subsession): if subsession.round_number == 1: for p in subsession.get_players(): round_numbers = list(range(1, C.NUM_ROUNDS + 1)) random.shuffle(round_numbers) task_rounds = dict(zip(C.TASKS, round_numbers)) print('player', p.id_in_subsession) print('task_rounds is', task_rounds) p.participant.task_rounds = task_rounds # PAGES class TaskAIntro(Page): @staticmethod def is_displayed(player: Player): participant = player.participant return player.round_number == participant.task_rounds['A'] form_model = "player" class TaskA(Page): @staticmethod def is_displayed(player: Player): participant = player.participant return player.round_number == participant.task_rounds['A'] form_model = "player" form_fields = ["number_entered_1", "number_entered_2", "number_entered_3", "number_entered_4", "number_entered_5", "number_entered_6", "number_entered_7", "number_entered_8", "number_entered_9", "number_entered_10"] @staticmethod def before_next_page(player, timeout_happened): player.set_payoff_game_1() class TaskBIntro(Page): @staticmethod def is_displayed(player: Player): participant = player.participant return player.round_number == participant.task_rounds['B'] form_model = "player" class TaskB1(Page): @staticmethod def is_displayed(player: Player): participant = player.participant return player.round_number == participant.task_rounds['B'] form_model = 'player' form_fields = ['take_fixed_payment'] @staticmethod def before_next_page(player: Player, timeout_happened): player.set_payoff_game_3() class TaskB2(Page): @staticmethod def is_displayed(player: Player): participant = player.participant return player.round_number == participant.task_rounds['B'] \ and not player.take_fixed_payment form_model = 'player' form_fields = ['num_envelopes'] @staticmethod def before_next_page(player: Player, timeout_happened): player.set_payoff_game_3() class TaskCIntro(Page): @staticmethod def is_displayed(player: Player): participant = player.participant return player.round_number == participant.task_rounds['C'] form_model = "player" class TaskC(Page): @staticmethod def is_displayed(player: Player): participant = player.participant return player.round_number == participant.task_rounds['C'] form_model = 'player' form_fields = ['contribution'] @staticmethod def before_next_page(player, timeout_happened): player.set_payoff_game_2() class TaskD(Page): @staticmethod def vars_for_template(player: Player): participant = player.participant payoff_game1 = participant.vars['payoff_game1'] payoff_game2 = participant.vars['payoff_game2'] payoff_game3 = participant.vars['payoff_game3'] payoff_game2_round = round(payoff_game2 / 5) * 5 win = participant.vars['win'] contribution = participant.vars['contribution'] selected_random_numbers = player.participant.vars['selected_random_numbers'] num_envelopes = player.participant.vars['num_envelopes'] take_fixed_payment = player.participant.vars['take_fixed_payment'] final_payoff = round((payoff_game1 + payoff_game2 + payoff_game3) / 5) * 5 return { 'payoff_game1': payoff_game1, 'payoff_game2_round': payoff_game2_round, 'payoff_game3': payoff_game3, 'win': win, 'contribution': contribution, 'selected_random_numbers': selected_random_numbers, 'num_envelopes': num_envelopes, 'take_fixed_payment': take_fixed_payment, 'final_payoff': final_payoff } @staticmethod def is_displayed(player: Player): participant = player.participant return player.round_number == C.NUM_ROUNDS page_sequence = [ TaskAIntro, TaskA, TaskBIntro, TaskB1, TaskB2, TaskCIntro, TaskC, TaskD ]