from otree.api import ( models, widgets, BaseConstants, BaseSubsession, BaseGroup, BasePlayer, Currency as c, currency_range, ) import random import itertools import numpy as np import math author = 'Tsahi Halyo' doc = """ Direct Elicitation for risk experiment """ class Constants(BaseConstants): name_in_url = 'direct_elicitation_v3' players_per_group = None decisions = { 'probabilities': [1,5, 10, 25, 35, 50, 65, 75, 90, 95, 99], 'amounts': [20,21,22,23,24,25,26,27,28,29,30], } combinations = len(decisions['probabilities']) * len(decisions['amounts']) num_rounds_gains = 3 num_rounds_losses = 0 #Needs to be self.session.config['init_gain_lott']+1+self.session.config['init_loss_lott'] +1 num_rounds = num_rounds_gains + num_rounds_losses #+ 2 # 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) class Subsession(BaseSubsession): def creating_session(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_gains) for p in self.get_players(): p.set_current_task_number() class Group(BaseGroup): pass class Player(BasePlayer): # whether the participant has been passing all tests so far tests_passed = models.BooleanField(initial=True) clicked_payoff_info = models.BooleanField(initial=False, blank=True) # current set sub_identifier = models.IntegerField() # parameters in the optimization problem task_number = models.IntegerField() lottery_amount = models.IntegerField() # benchmark payment at tau2 lottery_probability = models.IntegerField() lottery_loss_prob = models.IntegerField() # indicator_never_always_switcher = models.IntegerField() random_payoff = models.CurrencyField() # indifferent payment task: switching_point = models.IntegerField(min=0) def switching_point_max(self): return self.lottery_amount confidence = models.FloatField() # higher -> more confident; from 0 to 20 respectively corresponding to from 0% to 100%; step = $5% def set_current_task_number(self): self.task_number = self.participant.vars['list_sequence'][self.round_number-1] task_list = [] #Cartesian product l = itertools.product( Constants.decisions['probabilities'], Constants.decisions['amounts'], ) task_list.extend(l) tup = task_list[self.task_number] self.lottery_probability = tup[0] self.lottery_loss_prob = 100-tup[0] self.lottery_amount = tup[1] def current_choice(self): choice = [(self.lottery_probability, self.lottery_amount)] return choice def set_payoffs(self): possible_payoff = 0 r = random.randint(1, self.lottery_amount) if self.round_number == self.participant.vars['lists_paying_round']: if self.switching_point <= r: outcome = random.random() < self.lottery_probability / 100 possible_payoff = c(outcome * self.lottery_amount) self.random_payoff = possible_payoff else: possible_payoff = c(r) self.random_payoff = possible_payoff if 'possible_payoffs' in self.participant.vars: self.participant.vars['possible_payoffs'].append(round(possible_payoff, 2)) else: self.participant.vars['possible_payoffs'] = [round(possible_payoff, 2)]