from otree.api import * import random doc = """ This is a one-shot "Prisoner's Dilemma". Two players are asked separately whether they want to cooperate or defect. Their choices directly determine the payoffs. """ class C(BaseConstants): NAME_IN_URL = 'prisoner' PLAYERS_PER_GROUP = 2 NUM_ROUNDS = 1 PAYOFF_A = cu(200) PAYOFF_B = cu(180) PAYOFF_C = cu(120) PAYOFF_D = cu(0) class Subsession(BaseSubsession): pass class Group(BaseGroup): pass class Player(BasePlayer): payment = models.IntegerField(initial=100) is_bid_winner = models.BooleanField(initial=False) selected_bid = models.IntegerField(min=0, max=100) final_euro_amount = models.FloatField(initial=8.00) cooperate = models.BooleanField( choices=[[True, 'Cooperate'], [False, 'Defect']], doc="""This player's decision""", widget=widgets.RadioSelect, ) q1 = models.StringField( choices=[['True', 'True'], ['False', 'False']], label='Question 1: In the BDM mechanism, if my bid is lower than the randomly chosen price, I will still receive the advice but will not have to pay for it.', widget=widgets.RadioSelectHorizontal, ) q2 = models.StringField( choices=[['True', 'True'], ['False', 'False']], label='Question 2: In the Prisoner Dilemma game, if both players defect, they will receive a smaller punishment than if they both cooperate.', widget=widgets.RadioSelectHorizontal, ) q3 = models.StringField( choices=[['You get a small punishment, and the other gets a reward', 'You get a small punishment, and the other gets a reward'], ['Both get a moderate punishment','Both get a moderate punishment'], ['You get a heavy punishment, and the other gets a reward','You get a heavy punishment, and the other gets a reward'], ['Both get a small punishment','Both get a small punishment'],], label='Question 3: In the Prisoners Dilemma, what happens if you cooperate and the other participant defects?', ) q4 = models.StringField( choices=[['50 ECU', '50 ECU'], ['100 ECU', '100 ECU'], ['150 ECU', '150 ECU'], ['200 ECU', '200 ECU']], label='Question 4: What is the maximum amount you can bid for the advice in the BDM mechanism?', widget=widgets.RadioSelectHorizontal, ) bid = models.IntegerField(label='What is bid for the Advice?', min=0, max=100) program = models.StringField( choices=[['MSc. Digital Economy', 'MSc. Digital Economy'], ['MSc. International Management/CEMS', 'MSc. International Management/CEMS'], ['MSc. Marketing', 'MSc. Marketing'], ['MSc. Supply Chain Management', 'MSc. Supply Chain Management'], ['Prefer Not To Say', 'Prefer Not To Say']], label='What is your Program?', ) age = models.IntegerField(label='What is your age?', min=13, max=125) gender = models.StringField( choices=[['Male', 'Male'], ['Female', 'Female'], ['Other', 'Other'], ['Prefer Not To Say', 'Prefer Not To Say']], label='What is your Gender?', ) knowledge = models.StringField( choices=[['Yes', 'Yes'], ['No', 'No']], label='Did you have any prior knowledge of the game?', widget=widgets.RadioSelectHorizontal, ) feedback = models.StringField( choices=[['Yes', 'Yes'], ['No', 'No']], label='Did you find the advice valuable when making your decision?', widget=widgets.RadioSelectHorizontal, ) # FUNCTIONS def set_payoffs(group: Group): for p in group.get_players(): set_payoff(p) def decide_bid_winner(group: Group): players = group.get_players() the_selected_bid = random.randint(1, 100) for p in players: p.is_bid_winner = True if p.bid >= the_selected_bid else False p.selected_bid = the_selected_bid if p.is_bid_winner == True: p.payment -= the_selected_bid def other_player(player: Player): return player.get_others_in_group()[0] def set_payoff(player: Player): payoff_matrix = { (False, True): C.PAYOFF_A, (True, True): C.PAYOFF_B, (False, False): C.PAYOFF_C, (True, False): C.PAYOFF_D, } other = other_player(player) player.payoff = payoff_matrix[(player.cooperate, other.cooperate)] player.payment += int(player.payoff) player.final_euro_amount += (player.payment/100)*1.5 # PAGES class Introduction_p(Page): timeout_seconds = 100 class Introduction_bdm(Page): timeout_seconds = 100 class Evaluation(Page): timeout_seconds = 120 form_model = 'player' form_fields = ['q1','q2','q3','q4'] def error_message(self, values): # Custom validation logic goes here error_messages = [] # Check if answers are correct if values['q1'] != 'False': error_messages.append("Answer to Question 1 is incorrect.") if values['q2'] != 'False': error_messages.append("Answer to Question 2 is incorrect.") if values['q3'] != 'You get a heavy punishment, and the other gets a reward': error_messages.append("Answer to Question 3 is incorrect.") if values['q4'] != '100 ECU': error_messages.append("Answer to Question 4 is incorrect.") # Display retry warning if any answers are incorrect if error_messages: return '\n'.join(error_messages) class Bidding(Page): timeout_seconds = 60 form_model = 'player' form_fields = ['bid'] class Decision(Page): form_model = 'player' form_fields = ['cooperate'] class ResultsWaitPage(WaitPage): after_all_players_arrive = set_payoffs class ResultsWaitPageBDM(WaitPage): after_all_players_arrive = decide_bid_winner class Results(Page): @staticmethod def vars_for_template(player: Player): opponent = other_player(player) return dict( opponent=opponent, same_choice=player.cooperate == opponent.cooperate, my_decision=player.field_display('cooperate'), opponent_decision=opponent.field_display('cooperate'), ) class Questions(Page): form_model = 'player' form_fields = ['program', 'age', 'gender', 'knowledge', 'feedback'] class ThankYou(Page): form_model = 'player' page_sequence = [Introduction_p, Introduction_bdm, Evaluation, Bidding, ResultsWaitPageBDM, Decision, ResultsWaitPage, Results, Questions, ThankYou]