from otree.api import * import random import itertools import time from random import choice doc = """ """ author = 'Zeyu Qiu' class Constants(BaseConstants): name_in_url = 'repeated_pgg_english' players_per_group = 4 num_rounds = 20 equal = 20 low = 10 high = 30 multiplier = 0.4 pounds = 0.025 fixed = 10 class Subsession(BaseSubsession): pass def creating_session(subsession): for p in subsession.get_players(): if p.id_in_subsession: pressures = itertools.cycle([1, 1, 1, 1, 2, 2, 2, 2]) for player in subsession.get_players(): player.code_treatment = next(pressures) if p.code_treatment == 1: p.treatment = "equal" elif p.code_treatment == 2: p.treatment = "unequal" for player in subsession.get_players(): if player.treatment == "equal": player.my_endowment = Constants.equal elif player.treatment == "unequal": if player.id_in_group == 1: player.type = 'high' player.my_endowment = Constants.high elif player.id_in_group == 2: player.type = 'high' player.my_endowment = Constants.high elif player.id_in_group == 3: player.type = 'low' player.my_endowment = Constants.low elif player.id_in_group == 4: player.type = 'low' player.my_endowment = Constants.low class Group(BaseGroup): total_contribution = models.FloatField() individual_share = models.FloatField() sum_equal = models.FloatField() sum_low = models.FloatField() sum_high = models.FloatField() class Player(BasePlayer): choice = models.IntegerField() treatment = models.StringField() public = models.FloatField() private = models.FloatField() est_equal = models.FloatField() est_low = models.FloatField() est_high = models.FloatField() earn = models.FloatField() final_earn = models.FloatField() sum_pay = models.FloatField() part_a = models.IntegerField() final_pay = models.FloatField() type = models.StringField() my_endowment = models.IntegerField() contribution = models.IntegerField( min=0, label="Please, write below the amount of tokens you would like to contribute to the project:" ) belief_equal = models.IntegerField( min=0, label="" ) belief_low = models.IntegerField( min=0, label="" ) belief_high = models.IntegerField( min=0, label="" ) question1 = models.IntegerField( label="", min=0, ) question2 = models.FloatField( label="", min=0, ) fair_contribute = models.IntegerField( label="", min=0, ) other_fair_contribute = models.IntegerField( label="", min=0, ) other_low_fair_contribute = models.IntegerField( label="", min=0, ) other_high_fair_contribute = models.IntegerField( label="", min=0, ) onescale = models.StringField( choices=[['1', 'A'], ['2', 'B'], ['3', 'C'], ['4', 'D'], ['5', 'E'], ['6', 'F'], ['7', 'G'], ], label="", widget=widgets.RadioSelectHorizontal ) wescale = models.StringField( choices=[['1', ''], ['2', ''], ['3', ''], ['4', ''], ['5', ''], ['6', ''], ['7', ''], ], label="", widget=widgets.RadioSelectHorizontal ) onescale_low = models.StringField( choices=[['1', 'A'], ['2', 'B'], ['3', 'C'], ['4', 'D'], ['5', 'E'], ['6', 'F'], ['7', 'G'], ], label="", widget=widgets.RadioSelectHorizontal ) wescale_low = models.StringField( choices=[['1', ''], ['2', ''], ['3', ''], ['4', ''], ['5', ''], ['6', ''], ['7', ''], ], label="", widget=widgets.RadioSelectHorizontal ) onescale_high = models.StringField( choices=[['1', 'A'], ['2', 'B'], ['3', 'C'], ['4', 'D'], ['5', 'E'], ['6', 'F'], ['7', 'G'], ], label="", widget=widgets.RadioSelectHorizontal ) wescale_high = models.StringField( choices=[['1', ''], ['2', ''], ['3', ''], ['4', ''], ['5', ''], ['6', ''], ['7', ''], ], label="", widget=widgets.RadioSelectHorizontal ) gender = models.StringField( choices=[ ['1', 'Male'], ['2', 'Female'], ['3', 'Other'], ], label="1. What is your gender?", widget=widgets.RadioSelect ) age = models.IntegerField( label="2. How old are you?", min=0, max=120 ) income = models.StringField( choices=[ ['1', 'much lower than average '], ['2', 'lower than average '], ['3', 'average'], ['4', 'slightly higher than average '], ['5', 'higher than average'], ['6', 'much higher than average'] ], label="3. At the age of 16, how would you assess the income of your family compared to the average index?", widget=widgets.RadioSelect ) city = models.StringField( choices=[ ['1', 'in the city where the number of population is less than 10000'], ['2', 'in the city where the number of population is at least 10000'] ], label="4. In how big a city have you spent most part of your life?", widget=widgets.RadioSelect ) religious = models.StringField( choices=[ ['1', ''], ['2', ''], ['3', ''], ['4', ''], ['5', ''], ['6', ''], ['7', ''] ], label="", widget=widgets.RadioSelectHorizontal ) language = models.StringField( choices=[ ['1', 'Yes'], ['2', 'No'], ], label="6. Is Georgian your native language?", widget=widgets.RadioSelect ) max_income = models.StringField( choices=[ ['1', 'very important'], ['2', 'important'], ['3', 'neutral '], ['4', 'unimportant'], ['5', 'absolutely unimportant'], ], label="7. How important is it for you to earn maximum amount of money during this experiment? ", widget=widgets.RadioSelect ) trust = models.StringField( choices=[ ['1', 'most people can be trusted'], ['2', 'you should be very careful in relations with people '], ], label="8. How do you think, can people be trusted in general or is it better to be careful in relations with them?", widget=widgets.RadioSelect ) risk = models.StringField( choices=[ ['1', ''], ['2', ''], ['3', ''], ['4', ''], ['5', ''], ['6', ''], ['7', ''], ['8', ''], ['9', ''], ['10', ''], ], label="", widget=widgets.RadioSelectHorizontal ) instructions = models.StringField( choices=[ ['1', 'very difficult'], ['2', 'difficult'], ['3', 'neutral'], ['4', 'simple'], ['5', 'very simple'], ], label="10. In your opinion, what the instructions were like? ", widget=widgets.RadioSelect ) econ_exp = models.IntegerField( label="11. In how many economic experiments have you participated, apart from this experiment? ", ) feedback = models.StringField( blank=True, label="12. Do you have any other comment or feedback in connection with this experiment? ", ) email = models.StringField( label="Please below indicate the official email assigned to you by your university. Please note that without providing your university email, we will be unable to process your payment." ) A_1 = models.StringField( choices=[['1', '1'], ['2', '2'], ['3', '3'], ['4', '4'], ['5', '5'], ['6', '6'], ['7', '7'], ['8', '8'] ], label="", widget=widgets.RadioSelectHorizontal, blank=True ) A_2 = models.StringField( choices=[['1', '1'], ['2', '2'], ['3', '3'], ['4', '4'], ['5', '5'], ['6', '6'], ['7', '7'], ['8', '8'] ], label="", widget=widgets.RadioSelectHorizontal, blank=True ) A_3 = models.StringField( choices=[['1', '1'], ['2', '2'], ['3', '3'], ['4', '4'], ['5', '5'], ['6', '6'], ['7', '7'], ['8', '8'] ], label="", widget=widgets.RadioSelectHorizontal, blank=True ) A_4 = models.StringField( choices=[['1', '1'], ['2', '2'], ['3', '3'], ['4', '4'], ['5', '5'], ['6', '6'], ['7', '7'], ['8', '8'] ], label="", widget=widgets.RadioSelectHorizontal, blank=True ) A_5 = models.StringField( choices=[['1', '1'], ['2', '2'], ['3', '3'], ['4', '4'], ['5', '5'], ['6', '6'], ['7', '7'], ['8', '8'] ], label="", widget=widgets.RadioSelectHorizontal, blank=True ) A_6 = models.StringField( choices=[['1', '1'], ['2', '2'], ['3', '3'], ['4', '4'], ['5', '5'], ['6', '6'], ['7', '7'], ['8', '8'] ], label="", widget=widgets.RadioSelectHorizontal, blank=True ) A_7 = models.StringField( choices=[['1', '1'], ['2', '2'], ['3', '3'], ['4', '4'], ['5', '5'], ['6', '6'], ['7', '7'], ['8', '8'] ], label="", widget=widgets.RadioSelectHorizontal, blank=True ) A_8 = models.StringField( choices=[['1', '1'], ['2', '2'], ['3', '3'], ['4', '4'], ['5', '5'], ['6', '6'], ['7', '7'], ['8', '8'] ], label="", widget=widgets.RadioSelectHorizontal, blank=True ) A_9 = models.StringField( choices=[['1', '1'], ['2', '2'], ['3', '3'], ['4', '4'], ['5', '5'], ['6', '6'], ['7', '7'], ['8', '8'] ], label="", widget=widgets.RadioSelectHorizontal, blank=True ) A_10 = models.StringField( choices=[['1', '1'], ['2', '2'], ['3', '3'], ['4', '4'], ['5', '5'], ['6', '6'], ['7', '7'], ['8', '8'] ], label="", widget=widgets.RadioSelectHorizontal, blank=True ) def belief_equal_error_message(player, value): contribution_answer= 60 if value > contribution_answer: error_message = "You cannot estimate more than the number of tokens the other group members have been allocated. " \ "Please try again." return error_message def belief_low_error_message(player, value): if player.treatment == "unequal" and player.type == "low": contribution_answer= 10 if value > contribution_answer: error_message = "You cannot estimate more than the number of tokens the other group member has been allocated. " \ "Please try again." return error_message elif player.treatment == "unequal" and player.type == "high": contribution_answer= 20 if value > contribution_answer: error_message = "You cannot estimate more than the number of tokens the other group members have been allocated. " \ "Please try again." return error_message def belief_high_error_message(player, value): if player.treatment == "unequal" and player.type == "low": contribution_answer= 60 if value > contribution_answer: error_message = "You cannot estimate more than the number of tokens the other group members have been allocated. " \ "Please try again." return error_message elif player.treatment == "unequal" and player.type == "high": contribution_answer= 30 if value > contribution_answer: error_message = "You cannot estimate more than the number of tokens the other group member has been allocated. " \ "Please try again." return error_message def contribution_error_message(player, value): contribution_answer= player.my_endowment if value > contribution_answer: error_message = "You cannot contribute more than the number of tokens you have been allocated. " \ "Please try again." return error_message def fair_contribute_error_message(player, value): fair_answer= player.my_endowment if value > fair_answer: error_message = "You cannot enter more than the number of tokens you have been allocated. " \ "Please try again." return error_message def other_fair_contribute_error_message(player, value): contribution_answer= 60 if value > contribution_answer: error_message = "You cannot enter more than the number of tokens the other group members have been allocated. " \ "Please try again." return error_message def other_low_fair_contribute_error_message(player, value): if player.treatment == "unequal" and player.type == "low": contribution_answer= 10 if value > contribution_answer: error_message = "You cannot enter more than the number of tokens the other group member has been allocated. " \ "Please try again." return error_message elif player.treatment == "unequal" and player.type == "high": contribution_answer= 20 if value > contribution_answer: error_message = "You cannot enter more than the number of tokens the other group members have been allocated. " \ "Please try again." return error_message def other_high_fair_contribute_error_message(player, value): if player.treatment == "unequal" and player.type == "low": contribution_answer= 60 if value > contribution_answer: error_message = "You cannot enter more than the number of tokens the other group members have been allocated. " \ "Please try again." return error_message elif player.treatment == "unequal" and player.type == "high": contribution_answer= 30 if value > contribution_answer: error_message = "You cannot enter more than the number of tokens the other group member has been allocated. " \ "Please try again." return error_message def question1_error_message(player, value): correct_equal_q1 = 20 correct_unequal_low_q1 = 10 correct_unequal_high_q1 = 30 if player.treatment == "equal": if value != correct_equal_q1: error_equal_q1 = "Answer: (20 - 0) + 0.4 x 0 = 20 points" return error_equal_q1 elif player.treatment == "unequal" and player.type == "low": if value != correct_unequal_low_q1: error_unequal_low_q1 = "Answer: (10 - 0) + 0.4 x 0 = 10 points" return error_unequal_low_q1 elif player.treatment == "unequal" and player.type == "high": if value != correct_unequal_high_q1: error_unequal_high_q1 = "Aanswer: (30 - 0) + 0.4 x 0 = 30 points" return error_unequal_high_q1 def question2_error_message(player, value): correct_equal_q2 = 16.8 correct_unequal_low_q2 = 6.8 correct_unequal_high_q2 = 26.8 if player.treatment == "equal": if value != correct_equal_q2: error_equal_q2 = "Answer: (20 - 8) + 0.4 x 12 = 16.8 points" return error_equal_q2 elif player.treatment == "unequal" and player.type == "low": if value != correct_unequal_low_q2: error_unequal_low_q2 = "Answer: (10 - 8) + 0.4 x 12 = 6.8 points" return error_unequal_low_q2 elif player.treatment == "unequal" and player.type == "high": if value != correct_unequal_high_q2: error_unequal_high_q2 = "Answer: (30 - 8) + 0.4 x 12 = 26.8 points" return error_unequal_high_q2 # FUNCTIONS def set_payoffs(group: Group): players = group.get_players() contributions = [p.contribution for p in players] group.total_contribution = sum(contributions) group.individual_share = ( group.total_contribution * Constants.multiplier ) for p in players: p.public = round(group.individual_share, 2) p.private = p.my_endowment - p.contribution p.earn = round(p.public + p.private, 2) for p in players: p.choice = random.randint(1, 10) correct_answers = ["8", "2", "1", "5", "1", "6", "3", "2", "4", "5"] player_answers = [ p.field_maybe_none('A_1'), p.field_maybe_none('A_2'), p.field_maybe_none('A_3'), p.field_maybe_none('A_4'), p.field_maybe_none('A_5'), p.field_maybe_none('A_6'), p.field_maybe_none('A_7'), p.field_maybe_none('A_8'), p.field_maybe_none('A_9'), p.field_maybe_none('A_10') ] player_input = player_answers[p.choice - 1] if p.round_number == 1: if player_input == correct_answers[p.choice - 1]: p.part_a = 4 else: p.part_a = 0 else: p.part_a = p.in_round(1).part_a # PAGES class Welcome(Page): form_model = 'player' def is_displayed(player: Player): return player.round_number == 1 class PartA(Page): form_model = 'player' def is_displayed(player: Player): return player.round_number == 1 class A_1(Page): form_model = 'player' form_fields = ['A_1', ] def is_displayed(player: Player): return player.round_number == 1 class A_2(Page): form_model = 'player' form_fields = ['A_2', ] def is_displayed(player: Player): return player.round_number == 1 class A_3(Page): form_model = 'player' form_fields = ['A_3', ] def is_displayed(player: Player): return player.round_number == 1 class A_4(Page): form_model = 'player' form_fields = ['A_4', ] def is_displayed(player: Player): return player.round_number == 1 class A_5(Page): form_model = 'player' form_fields = ['A_5', ] def is_displayed(player: Player): return player.round_number == 1 class A_6(Page): form_model = 'player' form_fields = ['A_6', ] def is_displayed(player: Player): return player.round_number == 1 class A_7(Page): form_model = 'player' form_fields = ['A_7', ] def is_displayed(player: Player): return player.round_number == 1 class A_8(Page): form_model = 'player' form_fields = ['A_8', ] def is_displayed(player: Player): return player.round_number == 1 class A_9(Page): form_model = 'player' form_fields = ['A_9', ] def is_displayed(player: Player): return player.round_number == 1 class A_10(Page): form_model = 'player' form_fields = ['A_10', ] def is_displayed(player: Player): return player.round_number == 1 class General_Instructions(Page): form_model = 'player' def is_displayed(player: Player): return player.round_number == 1 class Instructions(Page): form_model = 'player' def is_displayed(player: Player): return player.round_number == 1 class Examples(Page): form_model = 'player' def is_displayed(player: Player): return player.round_number == 1 class Questions(Page): form_model = 'player' form_fields = ['question1', 'question2'] def is_displayed(player: Player): return player.round_number == 1 class Contribute(Page): form_model = 'player' form_fields = ['contribution'] class Beliefs(Page): form_model = 'player' def get_form_fields(player: Player): if player.treatment == "equal": return ['belief_equal'] elif player.treatment == "unequal": return ['belief_low', 'belief_high'] class ResultsWaitPage(WaitPage): title_text = "Please wait" body_text = "Please wait for the other participants to make their decisions" after_all_players_arrive = set_payoffs class Results(Page): form_model = 'player' class ResultsWaitPage2(WaitPage): title_text = "Please wait" body_text = "Please wait for the other participants to make their decisions" class Final_results(Page): form_model = 'player' def is_displayed(player: Player): return player.round_number == Constants.num_rounds def vars_for_template(player: Player): player.final_earn = sum([p.earn for p in player.in_all_rounds()]) player.sum_pay = round(player.final_earn*Constants.pounds,2) player.final_pay = round(player.sum_pay+Constants.fixed+player.part_a,2) class questionnaire(Page): form_model = 'player' def get_form_fields(player: Player): if player.treatment == "equal": return ['fair_contribute', 'other_fair_contribute', 'onescale', 'wescale'] elif player.treatment == "unequal": return ['fair_contribute', 'other_low_fair_contribute', 'other_high_fair_contribute', 'onescale_low', 'onescale_high', 'wescale_low', 'wescale_high'] def is_displayed(player: Player): return player.round_number == Constants.num_rounds class Final_Questionnaire(Page): form_model = 'player' form_fields = ['gender', 'age', 'income', 'city', 'religious', 'language', 'max_income', 'trust', 'risk', 'instructions', 'econ_exp', 'feedback'] def is_displayed(player: Player): return player.round_number == Constants.num_rounds class Email(Page): def is_displayed(player: Player): return player.round_number == Constants.num_rounds form_model = 'player' form_fields = ['email'] class Thanks(Page): def is_displayed(player: Player): return player.round_number == Constants.num_rounds page_sequence = [Welcome,PartA, A_1,A_2,A_3,A_4,A_5,A_6,A_7,A_8, A_9,A_10,General_Instructions, Instructions, Examples, Questions, Contribute, Beliefs,ResultsWaitPage, Results, ResultsWaitPage2,Final_results, questionnaire,Final_Questionnaire,Email,Thanks]