from otree.api import ( models, widgets, BaseConstants, BaseSubsession, BaseGroup, BasePlayer, Currency as c, currency_range, ) import random import itertools import numpy as np from django import forms from django.forms import widgets as django_widgets import math author = 'Zheng Li' doc = """ Intertemporal Choice """ class Constants(BaseConstants): name_in_url = 'inter_default_v6' players_per_group = None decisions_low = [ #[0:4] ['In 12 months', 'Today'], ['In 10 months', 'Today'], ['In 8 months', 'Today'], ['In 6 months', 'Today'], #[4:12] ['In 5 months', 'Today'], ['In 4 months', 'Today'], ['In 3 months', 'Today'], ['In 2 months', 'Today'], ['In 1 month', 'Today'], ['In 2 weeks', 'Today'], ['In 1 week', 'Today'], ['In 3 days', 'Today'], ] decisions_high = [ # [0:8] ['In 4 years', 'Today'], ['In 3.5 years', 'Today'], ['In 3 years', 'Today'], ['In 2.5 years', 'Today'], ['In 2 years', 'Today'], ['In 21 months', 'Today'], ['In 18 months', 'Today'], ['In 15 months', 'Today'], #[8:12] ['In 12 months', 'Today'], ['In 10 months', 'Today'], ['In 8 months', 'Today'], ['In 6 months', 'Today'], ] amounts = range(36,58,2) steps = 2 num_rounds = 12 # to generate the certainty-uncertainty spectrum bar list1 = np.arange(1 * 20, - 1, -1) list2 = [] list2.append(0) for x in range(20): list2.append((x+1)*5) example_set = [('In 6 months', 'Today', 40)] example_set_low = [('In 3 months', 'Today', 40)] example_set_high = [('In 18 months', 'Today', 40)] example_steps = 2 class Subsession(BaseSubsession): def creating_session(self): if self.round_number == 1: for p in self.get_players(): # set treatment group: low default or high default p.participant.vars['default_identifier'] = random.choice([0, 1]) # set default; only if failed check, becomes True p.participant.vars['failed_comprehension'] = False if p.participant.vars['default_identifier'] == 0: decisions = Constants.decisions_low[0:4]+ Constants.decisions_low[4:12] elif p.participant.vars['default_identifier'] == 1: decisions = Constants.decisions_high[8:12] + Constants.decisions_high[0:8] p.participant.vars['date_list'] = list() for date in decisions: p.participant.vars['date_list'].append(date[0]) dates_target = list() for date in decisions[0:4]: amount_tmp = random.choice(Constants.amounts) date = (date, amount_tmp) dates_target.append(date) dates_target = random.sample(dates_target, 4) dates_default = list() for date in decisions[4:12]: amount_tmp = random.choice(Constants.amounts) date = (date, amount_tmp) dates_default.append(date) dates_default = random.sample(dates_default, 8) p.participant.vars['dates'] = dates_target + dates_default for p in self.get_players(): p.default_identifier = p.participant.vars['default_identifier'] p.set_current_task_number() class Group(BaseGroup): pass class Player(BasePlayer): prolific_id = models.StringField() # indicator for low/high default group default_identifier = models.IntegerField( choices=[ [0, 'low default'], [1, 'high default'], ], widget=widgets.RadioSelect, blank=False, label="" ) # parameters in the optimization problem pay_amount = models.IntegerField() # benchmark payment at tau2 time_date_lhs = models.StringField() #tau2 time_date_rhs = models.StringField() #tau1 # indicator_never_always_switcher = models.IntegerField() # indifferent payment task: switching_point = models.FloatField() confidence = models.FloatField() # higher -> more confident; from 0 to 20 respectively corresponding to from 0% to 100%; step = $5% # overall indicator of whether passed the comprehension check failed_comprehension = models.BooleanField(initial=False) # indicators of whether correctly answered each question qn_lottery_got_wrong = models.BooleanField(initial=False) qn_confidence_got_wrong = models.BooleanField(initial=False) qn_hypo_got_wrong = models.BooleanField(initial=False) qn_datelist_got_wrong = models.BooleanField(initial=False) # 4 comprehension questions qn_hypo = models.IntegerField( choices=[ [1, 'In making my decisions, I am asked to assume that I will actually receive all payments indicated, regardless of whether they take place now or in the future.'], [0, 'In making my decisions, I am asked to assume that it is less likely that I will actually receive payments that are meant to take place in the future.'], [0, 'In making my decisions, I am asked to assume that it is less likely that I will actually receive payments that are meant to take place now.'], ], widget=widgets.RadioSelect, blank=False, label="" ) qn_lottery = models.IntegerField( choices=[ [0, 'It would be possible that I get paid both $15 and $20, i.e., I may receive a total amount of $35 from this decision.'], [1, 'I would receive EITHER $15 today OR $20 in 10 days.'], [0, 'It would be possible that I receive no money from this decision.'], ], widget=widgets.RadioSelect, blank=False, label="" ) qn_confidence = models.FloatField( blank=False, label="" ) qn_datelist = models.IntegerField( choices=[ [2, 'In 3 months. This is marked as the relevant payment date.'], [1, 'In 18 months. This is marked as the relevant payment date.'], [50,'Which date is marked as “Relevant date” does not mean anything and can be ignored. The relevant delayed payment date is not fixed in this price list but depends on the row.'] ], widget=widgets.RadioSelect, blank=False, label="" ) # to determine parameters in the current task def set_current_task_number(self): setattr(self, 'time_date_lhs', self.participant.vars['dates'][self.round_number - 1][0][0]) setattr(self, 'time_date_rhs', self.participant.vars['dates'][self.round_number - 1][0][1]) setattr(self, 'pay_amount', self.participant.vars['dates'][self.round_number - 1][1]) def current_choice(self): iet_choice = [(self.time_date_lhs, self.time_date_rhs, self.pay_amount)] return iet_choice def example_choice(self): if self.default_identifier == 0: iet_choice = Constants.example_set_low elif self.default_identifier == 1: iet_choice = Constants.example_set_high return iet_choice # to generate the list of payments for option B in ListLoad.html def frange(self, start, stop, step): i = start + step while i < stop: if isinstance(i, int): yield i else: yield round(i, 2) i += step # to display the list of payments for option B in List.html def right_side_amounts1(self): if self.pay_amount > 0: lst = self.frange(0, self.pay_amount + 1, Constants.steps) return list(enumerate(lst, 1)) # creating a list of tuples from looping "lst" with the starting index = 1 def right_side_amounts2(self): lst = self.frange(0, Constants.example_set[0][2] + 1, Constants.example_steps) return list(enumerate(lst, 1)) # to display the confidence interval in Valuation.html def range_bounds(self): if self.pay_amount > 0: bounds = [0, self.pay_amount] return bounds # def table_length1(self): return abs(self.pay_amount)/Constants.steps + 1 # def set_switching_point_and_indicator(self): if self.switching_point == 9999: # the template sets it to be 9999 when the player always chooses option A self.switching_point = self.pay_amount + Constants.steps self.indicator_never_always_switcher = 2 elif self.switching_point == Constants.steps: # the template sets it to be 0 when the player always chooses option B self.indicator_never_always_switcher = 0 else: self.indicator_never_always_switcher = 1 # when a middle point is chosen (what is desired)