from otree.api import ( models, widgets, BaseConstants, BaseSubsession, BaseGroup, BasePlayer, Currency as c, currency_range, ) import random import itertools from django import forms from django.forms import widgets as django_widgets import math author = 'Nikolas Kirk' doc = """ Intertemporal Choice """ class Constants(BaseConstants): name_in_url = 'intertemporal_choice_new' players_per_group = None decisions = { 'time': [[2], [10], [30], [50], [100], [160], [180], [200]], 'amounts': [10, 15, 20], } combinations = len(decisions['time']) * len(decisions['amounts']) num_rounds = 6 class Subsession(BaseSubsession): def before_session_starts(self): if self.round_number == 1: for p in self.get_players(): p.participant.vars['failed_comprehension'] = False p.participant.vars['lists_paying_round'] = random.randint(1, Constants.num_rounds) p.participant.vars['list_sequence'] = random.sample(range(0, Constants.combinations), Constants.num_rounds) for p in self.get_players(): p.set_current_task_number() if p.round_number == p.participant.vars['lists_paying_round']: p.on_paying_round = True class Group(BaseGroup): pass class Player(BasePlayer): task_number = models.IntegerField() task_identifier = models.StringField() switching_point_1 = models.FloatField() # switching_point_2 = models.FloatField() on_paying_round = models.BooleanField(initial=False) pay_amount = models.IntegerField() time_span = models.IntegerField() type = models.StringField() endowment = models.FloatField() indicator_never_always_switcher = models.IntegerField() switching_point = models.FloatField() choice_identifier = models.StringField() confidence = models.FloatField() confidence_upper_bound = models.FloatField() confidence_lower_bound = models.FloatField() question_failed = models.IntegerField() random_payoff = models.CurrencyField() random_right_side_amount = models.CurrencyField() delayed_payment_bool = models.StringField() delayed_payment_time = models.StringField() failed_comprehension = models.BooleanField(initial=False) qn_lottery_got_wrong = models.BooleanField(initial=False) qn_list_got_wrong = models.BooleanField(initial=False) qn_confidence_got_wrong = models.BooleanField(initial=False) qn_lottery = models.IntegerField( choices=[ [0, 'It is possible that I get paid both $15 and $20, i.e., I may receive a total amount of $35 from this decision.'], [1, 'I receive EITHER $15 today OR $20 in 10 days.'], [0, 'It is possible that I receive no money from this decision.'], ], widget=widgets.RadioSelect, blank=False, label="" ) qn_list = models.IntegerField( choices=[ [0, 'This person indicated that the delayed payment is worth more to them than $9 today.'], [0, 'This person indicated that the delayed payment is worth between $3 and $7 to them today.'], [1, 'This person indicated that the delayed payment is worth between $8 and $9 to them today.'], ], widget=widgets.RadioSelect, blank=False, label="" ) qn_confidence = models.FloatField( blank=False, label="" ) def set_current_task_number(self): setattr(self, 'task_number', self.participant.vars['list_sequence'][self.round_number-1]) task_list = [] l = itertools.product( Constants.decisions['time'], Constants.decisions['amounts'], ) task_list.extend(l) tup = task_list[self.task_number] setattr(self, 'time_span', random.choice(tup[0])) setattr(self, 'pay_amount', tup[1]) if self.pay_amount > 0: setattr(self, 'endowment', 0) else: setattr(self, 'endowment', abs(self.pay_amount)) def frange(self, start, stop, step): i = start while i < stop: if isinstance(i, int): yield i else: yield round(i, 2) i += step def right_side_amounts1(self): if self.pay_amount > 0: lst = self.frange(0, self.pay_amount + 1, 1) return list(enumerate(lst, 1)) 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) + 1 def current_choice(self): iet_choice = [(self.time_span, self.pay_amount)] return iet_choice def set_switching_point_and_indicator(self): if self.pay_amount > 0: if self.switching_point == 9999: self.switching_point = self.pay_amount + 1 self.indicator_never_always_switcher = 2 elif self.switching_point == 0: self.indicator_never_always_switcher = 0 else: self.indicator_never_always_switcher = 1 elif self.pay_amount < 0: if self.switching_point == 9999: self.switching_point = 1 self.indicator_never_always_switcher = 2 elif self.switching_point == self.pay_amount: self.indicator_never_always_switcher = 0 else: self.indicator_never_always_switcher = 1 def set_payoffs(self): random_right_side_amount = random.choice(self.right_side_amounts1())[1] possible_payoff = 0 if random_right_side_amount >= self.switching_point: possible_payoff = c(random_right_side_amount + self.endowment) delay = 'no' time = 'Today' else: possible_payoff = c(self.pay_amount + self.endowment) delay = 'yes' time = str(self.time_span) setattr(self, 'random_payoff', possible_payoff) setattr(self, 'delayed_payment_bool', delay) setattr(self, 'delayed_payment_time', time) if self.on_paying_round: if 'possible_payoffs' in self.participant.vars: self.participant.vars['possible_payoffs'].append(round(possible_payoff, 2)) self.participant.vars['delayed_payment'].append(delay) self.participant.vars['payment_timeframe'].append(time) else: self.participant.vars['possible_payoffs'] = [round(possible_payoff, 2)] self.participant.vars['delayed_payment'] = delay self.participant.vars['payment_timeframe'] = time