from otree.api import * import random as rd from copy import deepcopy doc = """ This is a 30-shot game. One player is asked separately whether they want to choose option 1, 2, or 3. Their choices directly determine the payoffs. """ def randq(qlist): seed = rd.random() for item in qlist: rd.Random(seed).shuffle(item) def contactlist(list1, list2, list3): list0 = [] for i in range(0, len(list1)): q = list1[i] + list2[i] + list3[i] list0.append(q) return list0 # models class C(BaseConstants): NAME_IN_URL = 'money_game1' PLAYERS_PER_GROUP = None INSTRUCTIONS_TEMPLATE = 'strategyLearningExperiment/instructions.html' INSTRUCTIONREST_TEMPLATE = 'strategyLearningExperiment/instructionsRest.html' # session1 PAYOFF_A11_1 = [79, 56, 67, 64, 78, 44, 60, 38, 45, 20] PAYOFF_A12_1 = [60, 46, 43, 36, 52, 61, 69, 75, 55, 43] PAYOFF_A13_1 = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0] PAYOFF_A21_1 = [70, 51, 55, 74, 88, 29, 52, 62, 52, 34] PAYOFF_A22_1 = [44, 36, 22, 54, 68, 52, 65, 89, 59, 51] PAYOFF_A23_1 = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0] PAYOFF_A31_1 = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0] PAYOFF_A32_1 = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0] PAYOFF_A33_1 = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0] PAYOFF_B11_1 = [37, 32, 13, 82, 95, 56, 67, 25, 41, 12] PAYOFF_B12_1 = [74, 53, 61, 26, 42, 22, 48, 99, 62, 57] PAYOFF_B13_1 = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0] PAYOFF_B21_1 = [86, 60, 76, 29, 44, 20, 47, 82, 57, 47] PAYOFF_B22_1 = [35, 31, 10, 69, 83, 67, 73, 28, 42, 14] PAYOFF_B23_1 = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0] PAYOFF_B31_1 = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0] PAYOFF_B32_1 = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0] PAYOFF_B33_1 = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0] OtherChoice_1 = [2, 2, 2, 2, 2, 1, 1, 1, 1, 1] CorrectChoice_1 = [1, 1, 1, 2, 2, 1, 1, 2, 2, 2] # session2 PAYOFF_A11_2 = [30, 39, 52, 50, 63, 76, 95, 49, 26, 38] PAYOFF_A12_2 = [56, 67, 85, 35, 38, 31, 54, 77, 69, 66] PAYOFF_A13_2 = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0] PAYOFF_A21_2 = [44, 54, 70, 42, 49, 13, 37, 91, 90, 80] PAYOFF_A22_2 = [19, 28, 38, 57, 75, 56, 76, 61, 45, 50] PAYOFF_A23_2 = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0] PAYOFF_A31_2 = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0] PAYOFF_A32_2 = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0] PAYOFF_A33_2 = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0] PAYOFF_B11_2 = [42, 52, 67, 43, 51, 9, 33, 53, 32, 42] PAYOFF_B12_2 = [17, 25, 35, 37, 42, 52, 72, 64, 49, 53] PAYOFF_B13_2 = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0] PAYOFF_B21_2 = [32, 42, 55, 49, 61, 19, 42, 46, 22, 35] PAYOFF_B22_2 = [23, 31, 43, 34, 36, 35, 57, 75, 65, 64] PAYOFF_B23_2 = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0] PAYOFF_B31_2 = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0] PAYOFF_B32_2 = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0] PAYOFF_B33_2 = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0] OtherChoice_2 = [1, 1, 1, 1, 1, 2, 2, 2, 2, 2] CorrectChoice_2 = [2, 2, 2, 1, 1, 2, 2, 1, 1, 1] # session3 PAYOFF_A11_3 = [65, 48, 71, 42, 65, 43, 52, 38, 29, 50] PAYOFF_A12_3 = [74, 29, 53, 72, 53, 16, 78, 17, 66, 33] PAYOFF_A13_3 = [50, 31, 55, 95, 33, 65, 54, 51, 50, 31] PAYOFF_A21_3 = [79, 31, 39, 81, 51, 45, 67, 58, 42, 17] PAYOFF_A22_3 = [64, 42, 63, 59, 72, 34, 32, 38, 27, 62] PAYOFF_A23_3 = [65, 13, 82, 61, 53, 14, 94, 36, 51, 42] PAYOFF_A31_3 = [52, 15, 55, 61, 63, 32, 69, 19, 56, 33] PAYOFF_A32_3 = [73, 40, 65, 74, 35, 52, 54, 72, 42, 15] PAYOFF_A33_3 = [89, 60, 38, 40, 85, 34, 30, 49, 41, 44] PAYOFF_B11_3 = [63, 52, 74, 37, 69, 32, 84, 35, 25, 54] PAYOFF_B12_3 = [77, 53, 75, 59, 50, 11, 83, 49, 32, 28] PAYOFF_B13_3 = [73, 26, 50, 46, 63, 20, 48, 55, 41, 55] PAYOFF_B21_3 = [82, 28, 35, 86, 77, 49, 52, 63, 40, 12] PAYOFF_B22_3 = [83, 45, 53, 87, 76, 31, 26, 33, 50, 20] PAYOFF_B23_3 = [61, 40, 43, 56, 48, 43, 37, 64, 54, 31] PAYOFF_B31_3 = [48, 10, 52, 58, 51, 57, 74, 14, 59, 30] PAYOFF_B32_3 = [64, 29, 68, 78, 30, 56, 51, 23, 38, 42] PAYOFF_B33_3 = [55, 18, 63, 72, 39, 29, 67, 36, 60, 47] OtherChoice_3 = [2, 2, 2, 2, 1, 1, 1, 3, 3, 3] CorrectChoice_3 = [1, 2, 3, 3, 1, 2, 3, 1, 2, 3] # random Qlist1 = [PAYOFF_A11_1, PAYOFF_A12_1, PAYOFF_A13_1, PAYOFF_A21_1, PAYOFF_A22_1, PAYOFF_A23_1, PAYOFF_A31_1, PAYOFF_A32_1, PAYOFF_A33_1, PAYOFF_B11_1, PAYOFF_B12_1, PAYOFF_B13_1, PAYOFF_B21_1, PAYOFF_B22_1, PAYOFF_B23_1, PAYOFF_B31_1, PAYOFF_B32_1, PAYOFF_B33_1, OtherChoice_1, CorrectChoice_1] Qlist2 = [PAYOFF_A11_2, PAYOFF_A12_2, PAYOFF_A13_2, PAYOFF_A21_2, PAYOFF_A22_2, PAYOFF_A23_2, PAYOFF_A31_2, PAYOFF_A32_2, PAYOFF_A33_2, PAYOFF_B11_2, PAYOFF_B12_2, PAYOFF_B13_2, PAYOFF_B21_2, PAYOFF_B22_2, PAYOFF_B23_2, PAYOFF_B31_2, PAYOFF_B32_2, PAYOFF_B33_2, OtherChoice_2, CorrectChoice_2] Qlist3 = [PAYOFF_A11_3, PAYOFF_A12_3, PAYOFF_A13_3, PAYOFF_A21_3, PAYOFF_A22_3, PAYOFF_A23_3, PAYOFF_A31_3, PAYOFF_A32_3, PAYOFF_A33_3, PAYOFF_B11_3, PAYOFF_B12_3, PAYOFF_B13_3, PAYOFF_B21_3, PAYOFF_B22_3, PAYOFF_B23_3, PAYOFF_B31_3, PAYOFF_B32_3, PAYOFF_B33_3, OtherChoice_3, CorrectChoice_3] randq(Qlist1) randq(Qlist2) randq(Qlist3) # get together Qlist = contactlist(Qlist1, Qlist2, Qlist3) PAYOFF_A11, PAYOFF_A12, PAYOFF_A13, PAYOFF_A21, PAYOFF_A22 = Qlist[0], Qlist[1], Qlist[2], Qlist[3], Qlist[4] PAYOFF_A23, PAYOFF_A31, PAYOFF_A32, PAYOFF_A33, PAYOFF_B11 = Qlist[5], Qlist[6], Qlist[7], Qlist[8], Qlist[9] PAYOFF_B12, PAYOFF_B13, PAYOFF_B21, PAYOFF_B22, PAYOFF_B23 = Qlist[10], Qlist[11], Qlist[12], Qlist[13], Qlist[14] PAYOFF_B31, PAYOFF_B32, PAYOFF_B33, OtherChoice, CorrectChoice = Qlist[15], Qlist[16], Qlist[17], Qlist[18], Qlist[19] NUM_ROUNDS = len(PAYOFF_A11) class Subsession(BaseSubsession): pass class Group(BaseGroup): pass class Player(BasePlayer): option1 = models.IntegerField( choices=[[1, 'Option1'], [2, 'Option2'], [3, 'Option3']], doc="""This player's decision""", widget=widgets.RadioSelect, ) payoff_per_trial = models.IntegerField # luck = models.IntegerField # choose the participant who can get a random payoff from all 10 trials except for the third smallest payoff # functions def set_payoff(player: Player): participant = player.participant payoff_matrix = { (1, 1): C.PAYOFF_A11[player.round_number - 1], (1, 2): C.PAYOFF_A12[player.round_number - 1], (1, 3): C.PAYOFF_A13[player.round_number - 1], (2, 1): C.PAYOFF_A21[player.round_number - 1], (2, 2): C.PAYOFF_A22[player.round_number - 1], (2, 3): C.PAYOFF_A23[player.round_number - 1], (3, 1): C.PAYOFF_A31[player.round_number - 1], (3, 2): C.PAYOFF_A32[player.round_number - 1], (3, 3): C.PAYOFF_A33[player.round_number - 1], } player.payoff_per_trial = payoff_matrix[(player.option1, C.OtherChoice[player.round_number - 1])] player.payoff = player.payoff_per_trial # random select if player.round_number == 1: participant.selected_payoff = [] participant.selected_round = [] participant.pays_per_trial = [] participant.correct_choice = [] participant.selected = [] participant.luck = rd.randint(1, 10) participant.pays_per_trial.append(player.payoff_per_trial) participant.correct_choice.append(C.CorrectChoice[player.round_number-1]) if player.round_number % len(C.PAYOFF_A11_1) == 0: ranked_pays_last = sorted(participant.pays_per_trial[-10:]) if participant.luck == 1: selected_trial = rd.randint(0, 9) participant.selected_payoff.append(ranked_pays_last[selected_trial]) participant.selected_round.append( participant.pays_per_trial[-10:].index(ranked_pays_last[selected_trial]) + 1) else: participant.selected_payoff.append(ranked_pays_last[2]) participant.selected_round.append(participant.pays_per_trial[-10:].index(ranked_pays_last[2])+1) select_round_list = [1 if value == participant.selected_payoff[-1] else 0 for value in participant.pays_per_trial[-10:]] participant.selected.extend(select_round_list) # customer output def custom_export(players): yield ['participant.id_in_session', 'participant', 'start_time', 'round_number', 'option', 'equilibrium_choice', 'payoff_per_round', 'selected_pay', 'total_payment', 'session.code'] for p in players: participant = p.participant session = p.session yield [participant.id_in_session, participant.code, participant.time_started_utc, p.round_number, p.option1, participant.correct_choice[p.round_number - 1], participant.pays_per_trial[p.round_number-1], participant.selected[p.round_number-1], sum(participant.selected_payoff), session.code] # PAGES class Introduction(Page): # timeout_seconds = 100 luck = rd.randint(1, 10) @staticmethod def is_displayed(player): return player.round_number % len(C.PAYOFF_A11_1) == 1 def vars_for_template(self): session_num = self.round_number // len(C.PAYOFF_A11_1) session_num_word = models.StringField if session_num == 1: session_num_word = 'second' elif session_num == 2: session_num_word = 'third' else: session_num_word = 'final' return { 'restInstruct': self.round_number // len(C.PAYOFF_A11_1) >= 1, 'session_number': session_num_word } class Decision(Page): form_model = 'player' form_fields = ['option1'] a = models.IntegerField def vars_for_template(self): hard = models.IntegerField if C.PAYOFF_A13[self.round_number - 1] == 0: hard = 2 round_num = models.IntegerField if self.round_number % len(C.PAYOFF_A11_1) == 0: round_num = len(C.PAYOFF_A11_1) else: round_num = self.round_number % len(C.PAYOFF_A11_1) return { 'frame': hard == 2, 'round_number': round_num, 'payoffA11': C.PAYOFF_A11[self.round_number - 1], 'payoffA12': C.PAYOFF_A12[self.round_number - 1], 'payoffA13': C.PAYOFF_A13[self.round_number - 1], 'payoffB11': C.PAYOFF_B11[self.round_number - 1], 'payoffB12': C.PAYOFF_B12[self.round_number - 1], 'payoffB13': C.PAYOFF_B13[self.round_number - 1], 'payoffA21': C.PAYOFF_A21[self.round_number - 1], 'payoffA22': C.PAYOFF_A22[self.round_number - 1], 'payoffA23': C.PAYOFF_A23[self.round_number - 1], 'payoffB21': C.PAYOFF_B21[self.round_number - 1], 'payoffB22': C.PAYOFF_B22[self.round_number - 1], 'payoffB23': C.PAYOFF_B23[self.round_number - 1], 'payoffA31': C.PAYOFF_A31[self.round_number - 1], 'payoffA32': C.PAYOFF_A32[self.round_number - 1], 'payoffA33': C.PAYOFF_A33[self.round_number - 1], 'payoffB31': C.PAYOFF_B31[self.round_number - 1], 'payoffB32': C.PAYOFF_B32[self.round_number - 1], 'payoffB33': C.PAYOFF_B33[self.round_number - 1] } def before_next_page(player: Player, timeout_happened): set_payoff(player) class Results(Page): @staticmethod def vars_for_template(player: Player): payoff_sum = player.session.config['participation_fee'] + player.session.config['real_world_currency_per_point']*sum(player.participant.selected_payoff) points = sum(player.participant.selected_payoff) return dict( round1=player.participant.selected_round[0], round2=player.participant.selected_round[1], round3=player.participant.selected_round[2], pay1=player.participant.selected_payoff[0], pay2=player.participant.selected_payoff[1], pay3=player.participant.selected_payoff[2], points=points, payoff_all=payoff_sum ) def is_displayed(player: Player): return player.round_number == len(C.PAYOFF_A11) class Rest(Page): timeout_seconds = 60 @staticmethod def is_displayed(player): return player.round_number % len(C.PAYOFF_A11_1) == 0 and player.round_number < len(C.PAYOFF_A11) def vars_for_template(self): session_num = self.round_number//len(C.PAYOFF_A11_1) session_num_word = models.StringField if session_num == 1: session_num_word = 'first' elif session_num == 2: session_num_word = 'second' return { 'session_number': session_num_word } page_sequence = [Introduction, Decision, Rest, Results]