from otree.api import * import random from random import randrange c = Currency doc = """ Your app description """ class Constants(BaseConstants): name_in_url = 'risk_elicitation' players_per_group = None num_rounds = 1 lottery_a_hi = c(2.00) lottery_a_lo = c(1.60) lottery_b_hi = c(3.85) lottery_b_lo = c(0.10) num_choices = 10 percentage = True small_pies = True enforce_consistency = True class Subsession(BaseSubsession): pass class Group(BaseGroup): pass class Player(BasePlayer): for j in range(1, Constants.num_choices + 1): locals()['choice_' + str(j)] = models.StringField() del j random_draw = models.IntegerField() choice_to_pay = models.StringField() option_to_pay = models.StringField() inconsistent = models.IntegerField() switching_row = models.IntegerField() def creating_session(self): n = Constants.num_choices # create list of lottery indices # ---------------------------------------------------------------------------------------------------- indices = [j for j in range(1, n)] indices.append(n) # create list of probabilities # ---------------------------------------------------------------------------------------------------- probabilities = [ "{0:.2f}".format(k / n * 100) + "%" for k in indices ] form_fields = ['choice_' + str(k) for k in indices] # create list of choices # ---------------------------------------------------------------------------------------------------- self.participant.mpl_choices = list( zip(indices, form_fields, probabilities) ) # randomly determine index/choice of binary decision to pay # ---------------------------------------------------------------------------------------------------- self.participant.mpl_index_to_pay = random.choice(indices) self.participant.mpl_choice_to_pay = 'choice_' + str(self.participant.mpl_index_to_pay) # initiate list for choices made # ---------------------------------------------------------------------------------------------------- self.participant.mpl_choices_made = [None for j in range(1, n + 1)] # set player's payoff # :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: def set_payoffs(self): # random draw to determine whether to pay the "high" or "low" outcome of the randomly picked lottery # ------------------------------------------------------------------------------------------------------------ self.random_draw = randrange(1, len(self.participant.mpl_choices)) # set to participant.var['choice_to_pay'] determined creating_session # ------------------------------------------------------------------------------------------------------------ self.choice_to_pay = self.participant.mpl_choice_to_pay # elicit whether lottery "A" or "B" was chosen for the respective choice # ------------------------------------------------------------------------------------------------------------ self.option_to_pay = getattr(self, self.choice_to_pay) # set player's payoff # ------------------------------------------------------------------------------------------------------------ if self.option_to_pay == 'A': if self.random_draw <= self.participant.mpl_index_to_pay: self.payoff = Constants.lottery_a_hi else: self.payoff = Constants.lottery_a_lo else: if self.random_draw <= self.participant.mpl_index_to_pay: self.payoff = Constants.lottery_b_hi else: self.payoff = Constants.lottery_b_lo # set payoff as global variable # ------------------------------------------------------------------------------------------------------------ self.participant.mpl_payoff = self.payoff self.payoff = self.participant.mpl_payoff + self.participant.os_payoff self.participant.payoff = self.payoff # determine consistency # :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: def set_consistency(self): n = Constants.num_choices # replace A's by 1's and B's by 0's self.participant.mpl_choices_made = [ 1 if j == 'A' else 0 for j in self.participant.mpl_choices_made ] # check for multiple switching behavior for j in range(1, n): choices = self.participant.mpl_choices_made self.inconsistent = 1 if choices[j] > choices[j - 1] else 0 if self.inconsistent == 1: break # determine switching row # :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: def set_switching_row(self): # set switching point to row number of first 'B' choice if self.inconsistent == 0: self.switching_row = sum(self.participant.mpl_choices_made) + 1 # PAGES class Instructions(Page): @staticmethod def before_next_page(player: Player, timeout_happened): player.creating_session() class Decision(Page): # form model # ---------------------------------------------------------------------------------------------------------------- form_model = 'player' # form fields # ---------------------------------------------------------------------------------------------------------------- @staticmethod def get_form_fields(player: Player): # unzip list of form_fields from list form_fields = [list(t) for t in zip(*player.participant.mpl_choices)][1] # provide form field associated with pagination or full list return form_fields # variables for template # ---------------------------------------------------------------------------------------------------------------- @staticmethod def vars_for_template(player: Player): return { 'choices': player.participant.mpl_choices, 'lottery_a_lo': c(Constants.lottery_a_lo), 'lottery_a_hi': c(Constants.lottery_a_hi), 'lottery_b_lo': c(Constants.lottery_b_lo), 'lottery_b_hi': c(Constants.lottery_b_hi) } # set player's payoff # ---------------------------------------------------------------------------------------------------------------- @staticmethod def before_next_page(player: Player, timeout_happened): # unzip indices and form fields from list round_number = player.round_number form_fields = [list(t) for t in zip(*player.participant.mpl_choices)][1] indices = [list(t) for t in zip(*player.participant.mpl_choices)][0] index = indices[round_number - 1] # replace choices in for j, choice in zip(indices, form_fields): choice_i = getattr(player, choice) player.participant.mpl_choices_made[j - 1] = choice_i # set payoff player.set_payoffs() # determine consistency player.set_consistency() # set switching row player.set_switching_row() class Results(Page) : @staticmethod def vars_for_template(player: Player): # unzip into list of lists choices = [list(t) for t in zip(*player.participant.mpl_choices)] indices = choices[0] # get index, round, and choice to pay index_to_pay = player.participant.mpl_index_to_pay round_to_pay = indices.index(index_to_pay) + 1 choice_to_pay = player.participant.mpl_choices[round_to_pay - 1] return { 'choice_to_pay': [choice_to_pay], 'option_to_pay': player.option_to_pay, 'payoff': player.payoff, 'lottery_a_lo': c(Constants.lottery_a_lo), 'lottery_a_hi': c(Constants.lottery_a_hi), 'lottery_b_lo': c(Constants.lottery_b_lo), 'lottery_b_hi': c(Constants.lottery_b_hi), 'payoff_os' : float(player.participant.os_payoff)*2 } page_sequence = [Instructions, Decision, Results]