from otree.api import ( models, widgets, BaseConstants, BaseSubsession, BaseGroup, BasePlayer, Currency as c, currency_range ) from Multiple_Price_List.config import * import random from random import randrange author = 'Felix Holzmeister' doc = """ Multiple price list task as proposed by Holt/Laury (2002), American Economic Review 92(5). """ # ******************************************************************************************************************** # # *** CLASS SUBSESSION # ******************************************************************************************************************** # class Subsession(BaseSubsession): def creating_session(self): n = Constants.num_choices step = Constants.step cert_equi = Constants.cert_equi for p in self.get_players(): # here, the object is subsession. therefore, we cannot write self.player # because there is more than one player in the subsession. instead we write self.get_players(), which # returns a list of all players in the subsession. so we have written a loop over all players in this # list. # create list of lottery indices # ---------------------------------------------------------------------------------------------------- indices = [j for j in range(1, n)] indices.append(n) if Constants.certain_choice else None # create list of probabilities # ---------------------------------------------------------------------------------------------------- if Constants.percentage: #this command means that if percentage = True in the confif.py tab probabilities = [ "{0:.0f}".format(Constants.probability_hi*100) + "%" for k in indices ] # Note that the Zero in front of the f in the curly brackets determines the number of digits after # the comma else: probabilities = [ str(Constants.probability_hi*100) + "/" + str(100) for k in indices ] #create Option B choices #option_b = [cert_equi - step * (k - 1) for k in indices] #determines all option B values #option_b = [c(i) for i in option_b] #turns every item in the list into a currency variable # create list corresponding to form_field variables including all choices # ---------------------------------------------------------------------------------------------------- form_fields = ['choice_' + str(k) for k in indices] # create list of choices # ---------------------------------------------------------------------------------------------------- p.participant.vars['mpl_choices'] = list( zip(indices, form_fields, probabilities, Constants.option_b) ) #ramdomly determine round to pay # ---------------------------------------------------------------------------------------------------- p.participant.vars['mpl_round_to_pay'] = randrange(1, Constants.num_rounds +1) #we need to add 1 because the last integer is exclusive # randomly determine index/choice of binary decision to pay # ---------------------------------------------------------------------------------------------------- p.participant.vars['mpl_index_to_pay'] = random.choice(indices) p.participant.vars['mpl_choice_to_pay'] = 'choice_' + str(p.participant.vars['mpl_index_to_pay']) # randomize order of lotteries if # ---------------------------------------------------------------------------------------------------- # initiate list for choices made # ---------------------------------------------------------------------------------------------------- p.participant.vars['mpl_choices_made'] = [None for j in range(1, n + 1)] # ******************************************************************************************************************** # # *** CLASS GROUP # ******************************************************************************************************************** # class Group(BaseGroup): pass # ******************************************************************************************************************** # # *** CLASS PLAYER # ******************************************************************************************************************** # class Player(BasePlayer): # add model fields to class player # :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: if Constants.certain_choice: for j in range(1, Constants.num_choices + 1): locals()['choice_' + str(j)] = models.StringField() del j else: for j in range(1, Constants.num_choices): locals()['choice_' + str(j)] = models.StringField() del j round_to_pay = models.IntegerField() random_draw = models.IntegerField() choice_to_pay = models.StringField() option_to_pay = models.StringField() inconsistent = models.IntegerField() switching_row = models.IntegerField() # set player's payoff # :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: def set_payoffs(self): # random draw to determine which round to pay # ------------------------------------------------------------------------------------------------------------ self.round_to_pay = self.participant.vars['mpl_round_to_pay'] # 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.vars['mpl_choices'])) # set to participant.var['choice_to_pay'] determined creating_session # ------------------------------------------------------------------------------------------------------------ self.choice_to_pay = self.participant.vars['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.vars['mpl_index_to_pay']: self.payoff = Constants.lottery_a_hi else: self.payoff = Constants.lottery_a_lo else: self.payoff = Constants.option_b[self.participant.vars['mpl_index_to_pay']-1] # set payoff as global variable # ------------------------------------------------------------------------------------------------------------ self.participant.vars['mpl_payoff'] = self.in_round(self.round_to_pay).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.vars['mpl_choices_made'] = [ 1 if j == 'A' else 0 for j in self.participant.vars['mpl_choices_made'] ] # check for multiple switching behavior for j in range(1, n): choices = self.participant.vars['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.vars['mpl_choices_made']) + 1