from otree.api import * c = cu doc = 'Random transparency' class C(BaseConstants): NAME_IN_URL = 'transparency_game' PLAYERS_PER_GROUP = None NUM_ROUNDS = 2 ENDOWMENT = cu(200) MULTIPLIER = 3 INSTRUCTIONS_TEMPLATE = 'transparency_game/instructions.html' class Subsession(BaseSubsession): pass def assigning_transparency(subsession: Subsession): session = subsession.session import itertools transparencies = itertools.cycle([0, 10, 50, 100]) for player in subsession.get_players(): participant = player.participant participant.transparency = next(transparencies) class Group(BaseGroup): pass class Player(BasePlayer): first_sent_back_amount = models.CurrencyField(label="Amount I'm sending back to Participant A in Round 1", min=0) second_sent_back_amount = models.CurrencyField(label="Amount I'm sending back to Participant A in Round 2", min=0) first_sent_amount = models.CurrencyField(initial=100) second_sent_amount = models.CurrencyField(max=200, min=0) first_transparent = models.BooleanField() second_transparent = models.BooleanField() first_sent_back_explanation = models.LongStringField(label='In a few sentences, please explain why you chose to send back that amount.') signature = models.StringField(label='Signature') date = models.StringField(label='Date') payoff_round = models.IntegerField() race_white = models.BooleanField(choices=[[True, 'Yes'], [False, 'No']], label='White', widget=widgets.RadioSelect) race_black = models.BooleanField(choices=[[True, 'Yes'], [False, 'No']], label='Black or African-American', widget=widgets.RadioSelect) race_hispanic = models.BooleanField(choices=[[True, 'Yes'], [False, 'No']], label='Hispanic or Latino', widget=widgets.RadioSelect) race_american_indian = models.BooleanField(choices=[[True, 'Yes'], [False, 'No']], label='American Indian or Alaskan Native', widget=widgets.RadioSelect) race_asian = models.BooleanField(choices=[[True, 'Yes'], [False, 'No']], label='Asian or Pacific Islander', widget=widgets.RadioSelect) race_other = models.BooleanField(choices=[[True, 'Yes'], [False, 'No']], label='Other', widget=widgets.RadioSelect) age = models.IntegerField(label='Age (in years):', min=0) sex = models.StringField(choices=[['Male', 'Male'], ['Female', 'Female']], label='Sex:', widget=widgets.RadioSelect) education = models.StringField(choices=[['Less than high school', 'Less than high school'], ['High school', 'High school'], ['Some college', 'Some college'], ['Undergraduate college degree', 'Undergraduate college degree'], ['Graduate college degree', 'Graduate college degree']], label='Highest level education:', widget=widgets.RadioSelect) income = models.StringField(choices=[['Less than $10,000', 'Less than $10,000'], ['$10,000-$19,999', '$10,000-$19,999'], ['$20,000-$29,999', '$20,000-$29,999'], ['$30,000-$39,999', '$30,000-$39,999'], ['$40,000-$49,999', '$40,000-$49,999'], ['$50,000-$59,999', '$50,000-$59,999'], ['$60,000-$69,999', '$60,000-$69,999'], ['$70,000-$79,999', '$70,000-$79,999'], ['$80,000-$89,999', '$80,000-$89,999'], ['$90,000-$99,999', '$90,000-$99,999'], ['$100,000 or more', '$100,000 or more'], ['Refuse to answer', 'Refuse to answer']], label='Annual household income:', widget=widgets.RadioSelect) work = models.IntegerField(label='Work experience (in years):', min=0) transparency = models.IntegerField() connect_ID = models.StringField(label='Connect ID:') def first_sent_back_amount_max(player: Player): return player.first_sent_amount * C.MULTIPLIER def second_sent_back_amount_max(player: Player): return player.second_sent_amount * C.MULTIPLIER class Introduction(Page): form_model = 'player' @staticmethod def is_displayed(player: Player): return (player.round_number == 1) class ConsentForm(Page): form_model = 'player' form_fields = ['signature', 'date'] @staticmethod def is_displayed(player: Player): return (player.round_number == 1) class InstructionsPart1(Page): form_model = 'player' @staticmethod def is_displayed(player: Player): return (player.round_number == 1) class InstructionsPart2(Page): form_model = 'player' @staticmethod def is_displayed(player: Player): return (player.round_number == 1) class BeforeRoundInstructions(Page): form_model = 'player' class FirstSend(Page): form_model = 'group' timeout_seconds = 90 @staticmethod def is_displayed(player: Player): return player.round_number == 1 @staticmethod def before_next_page(player: Player, timeout_happened): import random player.transparency = random.choice([0, 10, 50, 100]) if player.transparency == 0: player.first_transparent = False elif player.transparency == 10: if random.randint(0, 9) == 0: player.first_transparent = True else: player.first_transparent = False elif player.transparency == 50: if random.randint(0, 1) == 0: player.first_transparent = False else: player.first_transparent = True else: player.first_transparent = True class SecondSend(Page): form_model = 'player' timeout_seconds = 90 @staticmethod def is_displayed(player: Player): return player.round_number == 2 @staticmethod def before_next_page(player: Player, timeout_happened): player.first_transparent = player.in_round(1).first_transparent player.second_sent_amount = player.in_round(1).second_sent_amount player.transparency = player.in_round(1).transparency import random if player.transparency == 0: player.second_transparent = False elif player.transparency == 10: if random.randint(0, 9) == 0: player.second_transparent = True else: player.second_transparent = False elif player.transparency == 50: if random.randint(0, 1) == 0: player.second_transparent = False else: player.second_transparent = True else: player.second_transparent = True class FirstSendBack(Page): form_model = 'player' form_fields = ['first_sent_back_amount'] @staticmethod def is_displayed(player: Player): return player.round_number == 1 @staticmethod def vars_for_template(player: Player): return dict(tripled_amount = player.first_sent_amount * C.MULTIPLIER) class FirstSendBackExplanation(Page): form_model = 'player' form_fields = ['first_sent_back_explanation'] @staticmethod def is_displayed(player: Player): return player.round_number == 1 class SecondSendBack(Page): form_model = 'player' form_fields = ['second_sent_back_amount'] @staticmethod def is_displayed(player: Player): return player.round_number == 2 @staticmethod def vars_for_template(player: Player): return dict(tripled_amount = player.second_sent_amount * C.MULTIPLIER) class RoundResults(Page): form_model = 'player' @staticmethod def vars_for_template(player: Player): if (player.round_number == 1): return dict( received = player.first_sent_amount * C.MULTIPLIER, payoff = player.first_sent_amount * C.MULTIPLIER - player.first_sent_back_amount, tripled_amount = player.first_sent_amount * C.MULTIPLIER, ) else: return dict( received = player.second_sent_amount * C.MULTIPLIER, payoff = player.second_sent_amount * C.MULTIPLIER - player.second_sent_back_amount, tripled_amount = player.second_sent_amount * C.MULTIPLIER, ) @staticmethod def before_next_page(player: Player, timeout_happened): import random if player.round_number == 1: if player.first_transparent == False: player.second_sent_amount = random.randint(80, 120) else: if player.first_sent_back_amount <= 50: player.second_sent_amount = random.randint(0, 50) elif player.first_sent_back_amount <= 100: player.second_sent_amount = random.randint(51, 100) elif player.first_sent_back_amount <= 150: player.second_sent_amount = random.randint(101, 200) else: player.second_sent_amount = random.randint(201, 300) else: rand = random.randint(1,2) if rand == 1: player.payoff_round = 1 player.payoff = player.in_round(1).first_sent_amount * C.MULTIPLIER - player.in_round(1).first_sent_back_amount else: player.payoff_round = 2 player.payoff = player.second_sent_amount * C.MULTIPLIER - player.second_sent_back_amount class Payoff(Page): form_model = 'player' form_fields = ['race_white', 'race_black', 'race_hispanic', 'race_american_indian', 'race_asian', 'race_other', 'age', 'sex', 'education', 'income', 'work', 'connect_ID'] @staticmethod def is_displayed(player: Player): return player.round_number == 2 @staticmethod def vars_for_template(player: Player): session = player.session return dict(us_payoff = player.payoff.to_real_world_currency(session)) class Debriefing(Page): form_model = 'player' @staticmethod def is_displayed(player: Player): return player.round_number == 2 page_sequence = [Introduction, ConsentForm, InstructionsPart1, InstructionsPart2, BeforeRoundInstructions, FirstSend, SecondSend, FirstSendBack, FirstSendBackExplanation, SecondSendBack, RoundResults, Payoff, Debriefing]