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 = 'Thomas Graeber' doc = """ Intertemporal Choice """ class Constants(BaseConstants): name_in_url = 'inter_mel_complete' players_per_group = None decisions = { 'front_end': [ ['In 1 week', 'Today'], ['In 1 year and 1 week', 'In 1 year'], ['In 3 years and 1 week', 'In 3 years'], ['In 2 weeks', 'Today'], ['In 1 year and 2 weeks', 'In 1 year'], ['In 3 years and 2 weeks', 'In 3 years'], ['In 1 month', 'Today'], ['In 1 year and 1 month', 'In 1 year'], ['In 3 years and 1 month', 'In 3 years'], ['In 2 months', 'Today'], ['In 1 year and 2 months', 'In 1 year'], ['In 3 years and 2 months', 'In 3 years'], ], # 'main': [ # ['In 1 week', 'Today'], # ['In 2 weeks', 'Today'], # ['In 1 month', 'Today'], # ['In 3 months', 'Today'], # ['In 6 months', 'Today'], # ['In 9 months', 'Today'], # ['In 1 year', 'Today'], # ['In 1.5 years', 'Today'], # ['In 2 years', 'Today'], # ['In 3 years', 'Today'], # ['In 4 years', 'Today'], # ['In 5 years', 'Today'], # ], # 'low_default': [ # ['In 1 week', 'Today'], # ['In 2 weeks', 'Today'], # ['In 1 month', 'Today'], # ['In 3 months', 'Today'], # ['In 6 months', 'Today'], # ['In 9 months', 'Today'], # ['In 1 year', 'Today'], # ], # 'subadditivity': [ # ['In 9 months', 'Today'], # ['In 1 year and 6 months', 'In 9 months'], # ['In 1 year and 9 months', 'In 1 year'], # ['In 5 years and 9 months', 'In 5 years'], # ['In 1 month', 'Today'], # ['In 2 months', 'In 1 month'], # ['In 1 year and 1 month', 'In 1 year'], # ['In 5 years and 1 month', 'In 5 years'], # ['In 6 months', 'Today'], # ['In 9 months', 'In 3 months'], # ['In 1 year and 6 months', 'In 1 year'], # ['In 5 years and 6 months', 'In 5 years'], # ['In 1 year', 'Today'], # ['In 1 year and 1 month', 'In 1 month'], # ['In 2 years', 'In 1 year'], # ['In 11 years', 'In 10 years'], # ], } units = [ [1, 'week(s)'], [2, 'month(s)'], [3, 'year(s)'], ] amounts = [50, 60, 70, 80] num_rounds = 12 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) c = random.choice(list(Constants.decisions.keys())) p.participant.vars['condition'] = c if c == "front_end": payoffs = np.repeat(random.sample(Constants.amounts, len(Constants.amounts)), 3) zipped_list = list(zip(range(0, Constants.num_rounds), payoffs)) if c == "main": zipped_list = list(zip(range(0, Constants.num_rounds), np.random.choice(Constants.amounts, Constants.num_rounds))) # lol = random.sample([random.sample(range(0, 3), 3), random.sample(range(3, 6), 3)], 2) # p.participant.vars['list_sequence'] = [item for sublist in lol for item in sublist] elif c == "low_default": zipped_list = list(zip(np.random.choice(range(0, len(Constants.decisions['low_default'])), Constants.num_rounds), np.random.choice(Constants.amounts, Constants.num_rounds))) elif c == "subadditivity": payoffs = np.repeat(random.sample(Constants.amounts, len(Constants.amounts)), 3) zipped_list = list(zip(range(0, Constants.num_rounds), payoffs)) p.participant.vars['list_sequence'] = random.sample(zipped_list, Constants.num_rounds) # p.participant.vars['pay_sequence'] = np.repeat(Constants.amounts, 3) for p in self.get_players(): p.condition = p.participant.vars['condition'] p.set_current_task_number() if self.round_number == Constants.num_rounds: for p in self.get_players(): p.draw_default() class Group(BaseGroup): pass class Player(BasePlayer): condition = models.StringField() total_pay = models.CurrencyField() task_identifier = models.StringField() switching_point_1 = models.FloatField() # switching_point_2 = models.FloatField() on_paying_round = models.BooleanField(initial=False) set_identifier = models.IntegerField() choice_number = models.IntegerField() pay_amount = models.IntegerField() time_date_lhs = models.StringField() time_date_rhs = models.StringField() draw_default_num_early = models.IntegerField() draw_default_unit_early = models.IntegerField() draw_default_num_late = models.IntegerField() draw_default_unit_late = models.IntegerField() default_num_early = models.FloatField(min=0, max=100, blank=False, label="") default_unit_early = models.IntegerField( choices=Constants.units, blank=False, label="" ) default_num_late = models.FloatField(min = 0, max = 100, blank = False, label="") default_unit_late = models.IntegerField( choices=Constants.units, blank = False, label="" ) type = models.StringField() endowment = models.FloatField() indicator_never_always_switcher = models.IntegerField() switching_point = models.FloatField() 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_hypo_got_wrong = models.BooleanField(initial=False) 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_list = models.IntegerField( choices=[ [0, 'This person indicated that the delayed payment would be worth more to them than $9 today.'], [0, 'This person indicated that the delayed payment would be worth between $3 and $7 to them today.'], [1, 'This person indicated that the delayed payment would be 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): c = self.condition setattr(self, 'time_date_lhs', Constants.decisions[c][self.participant.vars['list_sequence'][self.round_number-1][0]][0]) setattr(self, 'time_date_rhs', Constants.decisions[c][self.participant.vars['list_sequence'][self.round_number-1][0]][1]) setattr(self, 'pay_amount', self.participant.vars['list_sequence'][self.round_number-1][1]) if self.condition == 'front_end': setattr(self, 'set_identifier', self.participant.vars['list_sequence'][self.round_number-1][0] // 4) setattr(self, 'choice_number', self.participant.vars['list_sequence'][self.round_number-1][0]) if self.condition == 'subadditivity': setattr(self, 'set_identifier', self.participant.vars['list_sequence'][self.round_number-1][0] // 4) setattr(self, 'choice_number', self.participant.vars['list_sequence'][self.round_number-1][0] + len(Constants.decisions['main']) + len(Constants.decisions['low_default'])) elif self.condition == 'low_default': setattr(self, 'choice_number', self.participant.vars['list_sequence'][self.round_number-1][0] + len(Constants.decisions['main'])) else: setattr(self, 'choice_number', self.participant.vars['list_sequence'][self.round_number-1][0]) 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, 2) 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)/2 + 1 def current_choice(self): iet_choice = [(self.time_date_lhs, self.time_date_rhs, self.pay_amount)] return iet_choice def draw_default(self): self.draw_default_unit_early = np.random.choice([item[0] for item in Constants.units]) self.draw_default_unit_late = np.random.choice([item[0] for item in Constants.units]) while self.draw_default_unit_late <= self.draw_default_unit_early: self.draw_default_unit_early = np.random.choice([item[0] for item in Constants.units]) self.draw_default_unit_late = np.random.choice([item[0] for item in Constants.units]) self.draw_default_num_early = np.random.choice([1, 2, 3, 4]) self.draw_default_num_late = np.random.choice([1, 2, 3, 4]) def current_choice_default(self): iet_choice = [('In {} {}'.format(self.draw_default_num_late, Constants.units[self.draw_default_unit_late-1][1]), 'In {} {}'.format(self.draw_default_num_early, Constants.units[self.draw_default_unit_early-1][1]), 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 + 2 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