from otree.api import ( models, widgets, BaseConstants, BaseSubsession, BaseGroup, BasePlayer, Currency as c, currency_range ) from mpl.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): # code for simple anchoring def creating_session(self): for p in self.get_players(): import random p.ascending = random.choice([True,False]) if self.round_number == 1: n = Constants.num_choices for p in self.get_players(): # 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: probabilities = [ "{0:.2f}".format(k / n * 100) + "%" for k in indices ] else: probabilities = [ str(k) + "/" + str(n) for k in indices ] lottery_a_hi = [ str(k*Constants.A_interval) for k in indices ] # 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, lottery_a_hi) ) # 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 # ---------------------------------------------------------------------------------------------------- if Constants.random_order: random.shuffle(p.participant.vars['mpl_choices']) # initiate list for choices made # ---------------------------------------------------------------------------------------------------- p.participant.vars['mpl_choices_made'] = [None for j in range(1, n + 1)] # generate random switching point for PlayerBot in tests.py # -------------------------------------------------------------------------------------------------------- for participant in self.session.get_participants(): participant.vars['mpl_switching_point'] = random.randint(1, n) # ******************************************************************************************************************** # # *** CLASS GROUP # ******************************************************************************************************************** # class Group(BaseGroup): pass # ******************************************************************************************************************** # # *** CLASS PLAYER # ******************************************************************************************************************** # class Player(BasePlayer): # Model of Demographic Survey dob = models.StringField() age = models.IntegerField(label='What is your age?', min=10, max=125) resident = models.StringField( choices=[['Andaman and Nicobar Islands', 'Andaman and Nicobar Islands'], ['Andhra Pradesh', 'Andhra Pradesh'],['Arunachal Pradesh', 'Arunachal Pradesh'],['Assam', 'Assam'],['Bihar', 'Bihar'],['Chandigarh', 'Chandigarh'],['Chhattisgarh', 'Chhattisgarh'],['Dadra and Nagar Haveli and Daman and Diu', 'Dadra and Nagar Haveli and Daman and Diu'],['Delhi', 'Delhi'],['Goa', 'Goa'],['Gujarat', 'Gujarat'],['Haryana', 'Haryana'],['Himachal Pradesh', 'Himachal Pradesh'],['Jammu and Kashmir', 'Jammu and Kashmir'],['Jharkhand', 'Jharkhand'],['Karnataka', 'Karnataka'],['Kerala', 'Kerala'],['Ladakh', 'Ladakh'],['Lakshadweep', 'Lakshadweep'],['Madhya Pradesh', 'Madhya Pradesh'],['Maharashtra', 'Maharashtra'],['Manipur', 'Manipur'],['Meghalaya', 'Meghalaya'],['Mizoram', 'Mizoram'],['Nagaland', 'Nagaland'],['Odisha', 'Odisha'],['Puducherry', 'Puducherry'],['Punjab', 'Punjab'],['Rajasthan', 'Rajasthan'],['Sikkim', 'Sikkim'],['Tamil Nadu', 'Tamil Nadu'],['Telangana', 'Telangana'],['Tripura', 'Tripura'],['Uttar Pradesh', 'Uttar Pradesh'],['Uttarakhand', 'Uttarakhand'],['West Bengal', 'West Bengal']], label='Which state/union territory in India do you currently live in?', widget=widgets.RadioSelect, ) # resident = models.StringField( # choices=[['Andaman and Nicobar Islands', 'Andaman and Nicobar Islands'], ['Andhra Pradesh', 'Andhra Pradesh'],['Arunachal Pradesh', 'Arunachal Pradesh'],['Assam', 'Assam'],['Bihar', 'Bihar'],['Chandigarh', 'Chandigarh'],['Chhattisgarh', 'Chhattisgarh'],['Dadra and Nagar Haveli and Daman and Diu', 'Dadra and Nagar Haveli and Daman and Diu'],['Delhi', 'Delhi'],['Goa', 'Goa'],['Gujarat', 'Gujarat'],['Haryana', 'Haryana'],['Himachal Pradesh', 'Himachal Pradesh'],['Jammu and Kashmir', 'Jammu and Kashmir'],['Jharkhand', 'Jharkhand'],['Karnataka', 'Karnataka'],['Kerala', 'Kerala'],['Ladakh', 'Ladakh'],['Lakshadweep', 'Lakshadweep'],['Madhya Pradesh', 'Madhya Pradesh'],['Maharashtra', 'Maharashtra'],['Manipur', 'Manipur'],['Meghalaya', 'Meghalaya'],['Mizoram', 'Mizoram'],['Nagaland', 'Nagaland'],['Odisha', 'Odisha'],['Puducherry', 'Puducherry'],['Punjab', 'Punjab'],['Rajasthan', 'Rajasthan'],['Sikkim', 'Sikkim'],['Tamil Nadu', 'Tamil Nadu'],['Telangana', 'Telangana'],['Tripura', 'Tripura'],['Uttar Pradesh', 'Uttar Pradesh'],['Uttarakhand', 'Uttarakhand'],['West Bengal', 'West Bengal']], # label='Which state/union territory in India do you currently live in?', # ) gender = models.StringField( choices=[['Male', 'Male'], ['Female', 'Female'], ['Other', 'Other'],['Prefer not to answer', 'Prefer not to answer']], label='What is your gender?', widget=widgets.RadioSelect, ) martial_status = models.StringField( choices=[['Married (or has partners)', 'Married (or has partners)'], ['Single (or divorced)', 'Single (or divorced)'],['Prefer not to answer', 'Prefer not to answer']], label='Marital status', widget=widgets.RadioSelect, ) religion = models.StringField( choices=[['Christian', 'Christian'],['Muslim', 'Muslim'],['Hindu', 'Hindu'],['Buddhist', 'Buddhist'], ['Others', 'Others'],['Prefer not to answer', 'Prefer not to answer']], label='Please specific your religion', widget=widgets.RadioSelect, ) caste = models.StringField( choices=[['General(G)', 'General(G)'], ['Other Backward Class(OBC)', 'Other Backward Class(OBC)'],['Scheduled Caste(SC)', 'Scheduled Caste(SC)'],['Scheduled Tribe(ST)', 'Scheduled Tribe(ST)'],['Prefer not to answer', 'Prefer not to answer']], label='Please specific your caste', widget=widgets.RadioSelect, ) highest_qualification = models.StringField( choices=[['Less than Class X', 'Less than Class X'], ['Class X', 'Class X'],['Class XII', 'Class XII'],['Bachelor’s degree', 'Bachelor’s degree'],['Master’s degree', 'Master’s degree'],['Higher than master’s degree ', 'Higher than master’s degree']], label='What is the highest level of education you have attained?', widget=widgets.RadioSelect, ) monthly_family_income = models.StringField( choices=[['less than 10,000', 'less than 10,000'],['10,001-20,000', '10,001-20,000'],['20,001-30,000', '20,001-30,000 '],['30,001-40,000', '30,001-40,000'],['40,001-50,000', '40,001-50,000'],['50,001-60,000', '50,001-60,000'],['50,001-60,000', '50,001-60,000'],['60,001-70,000', '60,001-70,000'],['70,001-80,000', '70,001-80,000 '],['80,001-90,000', '90,001-1,00,000'],['1,00,001-2,00,000', '1,00,001-2,00,000'],['2,00,001 and above ', '2,00,001 and above ']], label='Monthly family income before tax (in rupees):', widget=widgets.RadioSelect, ) mturk_primary_source = models.StringField( choices=[['Yes', 'Yes'], ['No', 'no'],], label='Is the income from MTurk your primary source of income for you? ', widget=widgets.RadioSelect, ) mother_tongue = models.StringField( choices=[['Assamese', 'Assamese'],['Bengali', 'Bengali'],['Bodo', 'Bodo'],['Dogri', 'Dogri'],['English', 'English'],['Gujarati', 'Gujarati'],['Kannada', 'Kannada'],['Kashmiri', 'Kashmiri'],['Konkani', 'Konkani'],['Maithili', 'Maithili'],['Malayalam', 'Malayalam'],['Manipuri', 'Manipuri'],['Marathi', 'Marathi'],['Nepali', 'Nepali'],['Odia', 'Odia'],['Punjabi', 'Punjabi'],['Sanskrit', 'Sanskrit'],['Santali', 'Santali'],['Sindhi', 'Sindhi'],['Tamil', 'Tamil'],['Telugu', 'Telugu'],['Urdu', 'Urdu'],['Other', 'Other']], label='Please specify your mother tongue:', widget=widgets.RadioSelect, ) # caste = models.StringField( # choices=[['General', 'General'], ['OBC', 'OBC'],['Scheduled Caste or Scheduled Tribe', 'Scheduled Caste or Scheduled Tribe'],['Others', 'Others'],['Prefer not to answer', 'Prefer not to answer']], # label='Please specific your caste', # widget=widgets.RadioSelect, risk_attitude = models.StringField( choices=[['0', '0'], ['1', '1'],['2', '2'],['3', '3'], ['4', '4'],['5', '5'],['6', '6'], ['7', '7'],['8', '8'],['9', '9'], ['10', '10']], label='How do you see yourself: are you generally a person who is fully prepared to take risks or do you try to avoid taking risks? Please select an option from the scale where the value 0 means: "not at all willing to take risks" and the value 10 means: "very willing to take risks" ', widget=widgets.RadioSelectHorizontal, ) # martial_status = models.StringField( # choices=[['Yes', 'Yes'], ['No', 'no'],['Prefer not to answer', 'Prefer not to answer']], # label='Are you Married?', # widget=widgets.RadioSelect, # ) # employment_status = models.StringField( # choices=[['Full-time employment', 'Full-time employment'], ['Part-time employment', 'Part-time employment'],['Self-employed', 'Unemployed '],['Student', 'Student']], # label='Which of the following best describes your current employment status?', # widget=widgets.RadioSelect, # ) # religion = models.StringField( # choices=[['Hindu', 'Hindu'], ['Muslim', 'Muslim'],['Christian', 'Christian'],['Others', 'Others'],['Prefer not to answer', 'Prefer not to answer']], # label='Please specific your religion', # widget=widgets.RadioSelect, # ) # ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: # Model for Dictator Game kept = models.CurrencyField( doc="""Amount dictator decided to keep for himself""", min=0, max=Constants.endowment, ) left = models.CurrencyField() def remaining_value(self): self.left = Constants.endowment - self.kept return self.left # :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: # Model of MPL : 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 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 whether to pay the "high" or "low" outcome of the randomly picked lottery # ------------------------------------------------------------------------------------------------------------ self.random_draw = randrange(1, len(self.participant.vars['mpl_choices'])) print ((self.participant.vars['mpl_choices'])) print(self.participant.vars['mpl_choices_made']) # 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 = (self.participant.vars['mpl_index_to_pay']) * Constants.A_interval # else: # self.payoff = Constants.lottery_a_lo else: if self.random_draw <= self.participant.vars['mpl_index_to_pay']: self.payoff = Constants.lottery_b_hi else: self.payoff = Constants.lottery_b_lo # set payoff as global variable # ------------------------------------------------------------------------------------------------------------ self.participant.vars['mpl_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.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 # Trial for treatments using simple anchoring task ascending = models.BooleanField() guess = models.IntegerField(label = "Please enter a quick approximate guess of the answer")