from otree.api import * import random as rd doc = """ This is a 5-shot game. One player is asked separately whether they want to choose option 1 or 2. Their choices directly determine the payoffs. """ class C(BaseConstants): NAME_IN_URL = 'money_game_exc' PLAYERS_PER_GROUP = None INSTRUCTIONS_TEMPLATE = 'strategyLearningExcercise/instructions.html' # original questions PAYOFF_A11 = [48, 69, 33, 49, 34] PAYOFF_A12 = [39, 60, 49, 60, 12] PAYOFF_A21 = [21, 45, 54, 53, 30] PAYOFF_A22 = [43, 64, 46, 29, 40] PAYOFF_B11 = [19, 43, 75, 71, 36] PAYOFF_B12 = [58, 78, 51, 27, 71] PAYOFF_B21 = [78, 95, 32, 56, 51] PAYOFF_B22 = [45, 66, 61, 93, 10] OtherChoice = [1, 1, 2, 2, 1] # random seed = rd.random() rd.Random(seed).shuffle(PAYOFF_A11) rd.Random(seed).shuffle(PAYOFF_A12) rd.Random(seed).shuffle(PAYOFF_A21) rd.Random(seed).shuffle(PAYOFF_A22) rd.Random(seed).shuffle(PAYOFF_B11) rd.Random(seed).shuffle(PAYOFF_B12) rd.Random(seed).shuffle(PAYOFF_B21) rd.Random(seed).shuffle(PAYOFF_B22) rd.Random(seed).shuffle(OtherChoice) NUM_ROUNDS = len(PAYOFF_A11) * 5 # global variables, changeable # trial selection pool = list(range(0, len(C.PAYOFF_A11))) pay_per_trial = [] selected_round = [] selected_payoff = [] class Subsession(BaseSubsession): pass class Group(BaseGroup): pass class Player(BasePlayer): option1 = models.IntegerField( choices=[[1, 'Option1'], [2, 'Option2']], doc="""This player's decision""", widget=widgets.RadioSelect, ) payoff_per_trial = models.IntegerField, gonext = models.BooleanField( choices=[[False, 'play again'], [True, 'continue']], doc="""whether to re-practice""", widget=widgets.RadioSelect, ) # FUNCTIONS def cancontinue(player: Player): if player.gonext: return True else: return False # PAGES class Introduction(Page): # timeout_seconds = 100 @staticmethod def is_displayed(player): return player.round_number % len(C.PAYOFF_A11) == 1 class Decision(Page): form_model = 'player' form_fields = ['option1'] def vars_for_template(self): round_num = 0 if self.round_number % len(C.PAYOFF_A11) == 0: round_num = 5 else: round_num = self.round_number % len(C.PAYOFF_A11) return { 'round_number': round_num, 'payoffA11': C.PAYOFF_A11[self.round_number % len(C.PAYOFF_A11) - 1], 'payoffA12': C.PAYOFF_A12[self.round_number % len(C.PAYOFF_A11) - 1], 'payoffB11': C.PAYOFF_B11[self.round_number % len(C.PAYOFF_A11) - 1], 'payoffB12': C.PAYOFF_B12[self.round_number % len(C.PAYOFF_A11) - 1], 'payoffA21': C.PAYOFF_A21[self.round_number % len(C.PAYOFF_A11) - 1], 'payoffB21': C.PAYOFF_B21[self.round_number % len(C.PAYOFF_A11) - 1], 'payoffA22': C.PAYOFF_A22[self.round_number % len(C.PAYOFF_A11) - 1], 'payoffB22': C.PAYOFF_B22[self.round_number % len(C.PAYOFF_A11) - 1] } class Return(Page): form_model = 'player' form_fields = ['gonext'] @staticmethod def is_displayed(player): return player.round_number % len(C.PAYOFF_A11) == 0 def app_after_this_page(self, upcoming_apps): if cancontinue(self): return upcoming_apps[0] page_sequence = [Introduction, Decision, Return]