from otree.api import ( models, widgets, BaseConstants, BaseSubsession, BaseGroup, BasePlayer, Currency as c, currency_range ) import random import itertools import json from datetime import datetime, timedelta import datetime from random import randrange author = 'Adrian Leuenberger' doc = """ Implementation of 2 different Timepreference (Patience) MPLs by: Camerer, C., Chapman, J., Snowberg, E., Dean, M. & Ortoleva, P. (2016). Design Document for Robust Econographics. Part III.N """ class Constants(BaseConstants): name_in_url = 'MPL_Patience_en' players_per_group = None num_rounds = 1 num_mpl = 4 n1 = 10 # Number of entries in the lists. Could have been a len() call but whatever. n2 = 14 n3 = 16 n4 = 8 base_endowment = 10000 long_delay_days_per_list = [60, 395, 395, 60] #MPL1 Patience (Chapman et al. (2016), Part III.N): In 60 days! mpl_pat_1_a = [4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000] mpl_pat_1_b = [0, 500, 1000, 1500, 2000, 2500, 3000, 3500, 4000, 4500] #MPL2 Patience (Chapman et al. (2016), Part III.N): In 395 days! mpl_pat_2_a = [6000, 6000, 6000, 6000, 6000, 6000, 6000, 6000, 6000, 6000, 6000, 6000, 6000, 6000] mpl_pat_2_b = [0, 500, 1000, 1500, 2000, 2500, 3000, 3500, 4000, 4500, 5000, 5500, 6000, 6500] # MPL3 Patience Loss: In 395 days! mpl_pat_3_a = [-7000, -7000, -7000, -7000, -7000, -7000, -7000, -7000, -7000, -7000, -7000, -7000, -7000, -7000, -7000, -7000] mpl_pat_3_b = [0, -500, -1000, -1500, -2000, -2500, -3000, -3500, -4000, -4500, -5000, -5500, -6000, -6500, -7000, -7500] # MPL4 Patience Loss: In 60 days! mpl_pat_4_a = [-3000, -3000, -3000, -3000, -3000, -3000, -3000, -3000] mpl_pat_4_b = [0, -500, -1000, -1500, -2000, -2500, -3000, -3500] class Subsession(BaseSubsession): def creating_session(self): # randomization of pages from .pages import initial_page_sequence aaa = [i.__name__.split('_') for i in initial_page_sequence] page_blocks = [list(group) for key, group in itertools.groupby(aaa, key=lambda x: x[0])] for p in self.get_players(): pb = page_blocks.copy() random.shuffle(pb) level1 = list(itertools.chain.from_iterable(pb)) level2 = ['_'.join(i) for i in level1] p.page_sequence = json.dumps(level2) if self.round_number == 1: for p in self.get_players(): # create lists # ---------------------------------------------------------------------------------------------------- indices_1 = [j for j in range(1, Constants.n1)] indices_1.append(Constants.n1) mpl_pat_1_a = Constants.mpl_pat_1_a mpl_pat_1_b = Constants.mpl_pat_1_b indices_2 = [j for j in range(1, Constants.n2)] indices_2.append(Constants.n2) mpl_pat_2_a = Constants.mpl_pat_2_a mpl_pat_2_b = Constants.mpl_pat_2_b indices_3 = [j for j in range(1, Constants.n3)] indices_3.append(Constants.n3) mpl_pat_3_a = Constants.mpl_pat_3_a mpl_pat_3_b = Constants.mpl_pat_3_b indices_4 = [j for j in range(1, Constants.n4)] indices_4.append(Constants.n4) mpl_pat_4_a = Constants.mpl_pat_4_a mpl_pat_4_b = Constants.mpl_pat_4_b # create list corresponding to form_field variables including all choices # ---------------------------------------------------------------------------------------------------- form_fields_1 = ['timepref_pat_mpl_1_choice_' + str(k) for k in indices_1] form_fields_2 = ['timepref_pat_mpl_2_choice_' + str(k) for k in indices_2] form_fields_3 = ['timepref_pat_mpl_3_choice_' + str(k) for k in indices_3] form_fields_4 = ['timepref_pat_mpl_4_choice_' + str(k) for k in indices_4] # create list of choices # ---------------------------------------------------------------------------------------------------- p.participant.vars['mpl_pat_1_choices'] = list( zip(indices_1, form_fields_1, mpl_pat_1_a, mpl_pat_1_b) ) # print(p.participant.vars['mpl_pat_1_choices']) p.participant.vars['mpl_pat_2_choices'] = list( zip(indices_2, form_fields_2, mpl_pat_2_a, mpl_pat_2_b) ) # print(p.participant.vars['mpl_pat_2_choices']) p.participant.vars['mpl_pat_3_choices'] = list( zip(indices_3, form_fields_3, mpl_pat_3_a, mpl_pat_3_b) ) # print(p.participant.vars['mpl_pat_3_choices']) p.participant.vars['mpl_pat_4_choices'] = list( zip(indices_4, form_fields_4, mpl_pat_4_a, mpl_pat_4_b) ) # print(p.participant.vars['mpl_pat_4_choices']) # randomly determine mpl to pay # ---------------------------------------------------------------------------------------------------- p.participant.vars['timepref_pat_mpl_to_pay'] = random.randint(1, Constants.num_mpl) p.participant.vars['long_delay_days'] = Constants.long_delay_days_per_list[ p.participant.vars['timepref_pat_mpl_to_pay'] - 1] # randomly determine index/choice of binary decision to pay # ---------------------------------------------------------------------------------------------------- if p.participant.vars['timepref_pat_mpl_to_pay'] == 1: p.participant.vars['timepref_pat_mpl_index_to_pay'] = random.randint(1, Constants.n1) if p.participant.vars['timepref_pat_mpl_to_pay'] == 2: p.participant.vars['timepref_pat_mpl_index_to_pay'] = random.randint(1, Constants.n2) if p.participant.vars['timepref_pat_mpl_to_pay'] == 3: p.participant.vars['timepref_pat_mpl_index_to_pay'] = random.randint(1, Constants.n3) if p.participant.vars['timepref_pat_mpl_to_pay'] == 4: p.participant.vars['timepref_pat_mpl_index_to_pay'] = random.randint(1, Constants.n4) # print(p.participant.vars['timepref_pat_mpl_index_to_pay']) p.participant.vars['timepref_pat_mpl_row_to_pay'] = p.participant.vars['timepref_pat_mpl_index_to_pay']-1 # print(p.participant.vars['timepref_pat_mpl_row_to_pay']) p.participant.vars['timepref_pat_mpl_choice_to_pay'] = 'timepref_pat_mpl_' +\ str(p.participant.vars['timepref_pat_mpl_to_pay']) + '_choice_' +\ str(p.participant.vars['timepref_pat_mpl_index_to_pay']) # print(p.participant.vars['timepref_pat_mpl_choice_to_pay']) # initiate lists for choices made # ---------------------------------------------------------------------------------------------------- p.participant.vars['timepref_pat_mpl_1_choices_made'] = [None for j in range(1, Constants.n1 + 1)] p.participant.vars['timepref_pat_mpl_2_choices_made'] = [None for j in range(1, Constants.n2 + 1)] p.participant.vars['timepref_pat_mpl_3_choices_made'] = [None for j in range(1, Constants.n3 + 1)] p.participant.vars['timepref_pat_mpl_4_choices_made'] = [None for j in range(1, Constants.n4 + 1)] class Group(BaseGroup): pass class Player(BasePlayer): # add model fields to class player # :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: timepref_pat_mpl_1_count_impatient_option = models.IntegerField() timepref_pat_mpl_1_count_patient_option = models.IntegerField() timepref_pat_mpl_1_error = models.BooleanField(initial='False') timepref_pat_mpl_2_count_impatient_option = models.IntegerField() timepref_pat_mpl_2_count_patient_option = models.IntegerField() timepref_pat_mpl_2_error = models.BooleanField(initial='False') timepref_pat_mpl_3_count_impatient_option = models.IntegerField() timepref_pat_mpl_3_count_patient_option = models.IntegerField() timepref_pat_mpl_3_error = models.BooleanField(initial='False') timepref_pat_mpl_4_count_impatient_option = models.IntegerField() timepref_pat_mpl_4_count_patient_option = models.IntegerField() timepref_pat_mpl_4_error = models.BooleanField(initial='False') timepref_pat_choice_to_pay = models.StringField() timepref_pat_option_to_pay = models.StringField() MPL_to_pay = models.IntegerField() index_of_payout_choice_in_MPL = models.IntegerField() timepref_payout_day = models.StringField() timepref_option_delay = models.IntegerField() timepref_pat_payout_day = models.StringField() timepref_delayed_payoff = models.IntegerField() timepref_delayed_payoff_floored = models.IntegerField() page_sequence = models.StringField() for j in range(1, Constants.n1 + 1): locals()['timepref_pat_mpl_1_choice_' + str(j)] = models.StringField() del j for j in range(1, Constants.n2 + 1): locals()['timepref_pat_mpl_2_choice_' + str(j)] = models.StringField() del j for j in range(1, Constants.n3 + 1): locals()['timepref_pat_mpl_3_choice_' + str(j)] = models.StringField() del j for j in range(1, Constants.n4 + 1): locals()['timepref_pat_mpl_4_choice_' + str(j)] = models.StringField() del j # set player's payoff # :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: def set_payoffs(self): self.participant.vars['MPL_base_endowment'] = Constants.base_endowment # set to participant.var['choice_to_pay'] determined creating_session # ------------------------------------------------------------------------------------------------------------ self.timepref_pat_choice_to_pay = self.participant.vars['timepref_pat_mpl_choice_to_pay'] self.MPL_to_pay = self.participant.vars['timepref_pat_mpl_to_pay'] self.index_of_payout_choice_in_MPL = self.participant.vars['timepref_pat_mpl_index_to_pay'] # elicit whether lottery "A" or "B" was chosen for the respective choice # ------------------------------------------------------------------------------------------------------------ self.timepref_pat_option_to_pay = getattr(self, self.timepref_pat_choice_to_pay) self.participant.vars['timepref_pat_mpl_delay'] = self.timepref_pat_option_to_pay # How many days is the payoff delayed: if self.timepref_pat_option_to_pay == 'impatient': self.timepref_option_delay = self.participant.vars['timepref_pat_mpl_delay_days'] = 30 self.timepref_payout_day = str(datetime.date.today() + timedelta(days=30)) self.participant.vars['timepref_pat_mpl_payout_day'] = self.timepref_payout_day else: self.timepref_option_delay = Constants.long_delay_days_per_list[ self.participant.vars['timepref_pat_mpl_to_pay'] - 1] self.participant.vars['timepref_pat_mpl_delay_days'] = self.timepref_option_delay self.timepref_payout_day = str(datetime.date.today() + timedelta(days=self.timepref_option_delay)) self.participant.vars['timepref_pat_mpl_payout_day'] = self.timepref_payout_day # set player's payoff # ------------------------------------------------------------------------------------------------------------ if self.timepref_pat_option_to_pay == 'patient': if self.participant.vars['timepref_pat_mpl_to_pay'] == 1: self.participant.vars['mpl_pat_pot_payoff'] = Constants.base_endowment +\ Constants.mpl_pat_1_a[self.participant.vars['timepref_pat_mpl_row_to_pay']] if self.participant.vars['timepref_pat_mpl_to_pay'] == 2: self.participant.vars['mpl_pat_pot_payoff'] = Constants.base_endowment +\ Constants.mpl_pat_2_a[self.participant.vars['timepref_pat_mpl_row_to_pay']] if self.participant.vars['timepref_pat_mpl_to_pay'] == 3: self.participant.vars['mpl_pat_pot_payoff'] = Constants.base_endowment +\ Constants.mpl_pat_3_a[self.participant.vars['timepref_pat_mpl_row_to_pay']] if self.participant.vars['timepref_pat_mpl_to_pay'] == 4: self.participant.vars['mpl_pat_pot_payoff'] = Constants.base_endowment +\ Constants.mpl_pat_4_a[self.participant.vars['timepref_pat_mpl_row_to_pay']] else: if self.participant.vars['timepref_pat_mpl_to_pay'] == 1: self.participant.vars['mpl_pat_pot_payoff'] = Constants.base_endowment +\ Constants.mpl_pat_1_b[self.participant.vars['timepref_pat_mpl_row_to_pay']] if self.participant.vars['timepref_pat_mpl_to_pay'] == 2: self.participant.vars['mpl_pat_pot_payoff'] = Constants.base_endowment +\ Constants.mpl_pat_2_b[self.participant.vars['timepref_pat_mpl_row_to_pay']] if self.participant.vars['timepref_pat_mpl_to_pay'] == 3: self.participant.vars['mpl_pat_pot_payoff'] = Constants.base_endowment +\ Constants.mpl_pat_3_b[self.participant.vars['timepref_pat_mpl_row_to_pay']] if self.participant.vars['timepref_pat_mpl_to_pay'] == 4: self.participant.vars['mpl_pat_pot_payoff'] = Constants.base_endowment +\ Constants.mpl_pat_4_b[self.participant.vars['timepref_pat_mpl_row_to_pay']] self.timepref_delayed_payoff = self.participant.vars['mpl_pat_pot_payoff'] self.timepref_delayed_payoff_floored = self.participant.vars['mpl_pat_pot_payoff'] if\ self.participant.vars['mpl_pat_pot_payoff'] >= 0 else 0 # print(self.participant.vars['mpl_pat_pot_payoff']) pat_date_1 = (datetime.date.today() + timedelta(days=60)) pat_date_2 = (datetime.date.today() + timedelta(days=395)) pat_date_0 = (datetime.date.today() + timedelta(days=30)) # determine consistency # :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: def set_consistency(self): # replace patient by 1's and safe by 0's self.participant.vars['timepref_pat_mpl_1_choices_made'] = [ 1 if j == 'patient' else 0 for j in self.participant.vars['timepref_pat_mpl_1_choices_made'] ] self.participant.vars['timepref_pat_mpl_2_choices_made'] = [ 1 if j == 'patient' else 0 for j in self.participant.vars['timepref_pat_mpl_2_choices_made'] ] self.participant.vars['timepref_pat_mpl_3_choices_made'] = [ 1 if j == 'patient' else 0 for j in self.participant.vars['timepref_pat_mpl_3_choices_made'] ] self.participant.vars['timepref_pat_mpl_4_choices_made'] = [ 1 if j == 'patient' else 0 for j in self.participant.vars['timepref_pat_mpl_4_choices_made'] ] # count patient options def set_count_patient_option_mpl_1(self): self.timepref_pat_mpl_1_count_patient_option = sum(self.participant.vars['timepref_pat_mpl_1_choices_made']) def set_count_patient_option_mpl_2(self): self.timepref_pat_mpl_2_count_patient_option = sum(self.participant.vars['timepref_pat_mpl_2_choices_made']) def set_count_patient_option_mpl_3(self): self.timepref_pat_mpl_3_count_patient_option = sum(self.participant.vars['timepref_pat_mpl_3_choices_made']) def set_count_patient_option_mpl_4(self): self.timepref_pat_mpl_4_count_patient_option = sum(self.participant.vars['timepref_pat_mpl_4_choices_made']) # count impatient options def set_count_impatient_option_mpl_1(self): self.timepref_pat_mpl_1_count_impatient_option = Constants.n1-self.timepref_pat_mpl_1_count_patient_option def set_count_impatient_option_mpl_2(self): self.timepref_pat_mpl_2_count_impatient_option = Constants.n2 - self.timepref_pat_mpl_2_count_patient_option def set_count_impatient_option_mpl_3(self): self.timepref_pat_mpl_3_count_impatient_option = Constants.n3 - self.timepref_pat_mpl_3_count_patient_option def set_count_impatient_option_mpl_4(self): self.timepref_pat_mpl_4_count_impatient_option = Constants.n4 - self.timepref_pat_mpl_4_count_patient_option