from otree.api import * from numpy import random as nprand import math doc = """ EPS prediction """ class C(BaseConstants): NAME_IN_URL = 'eps' PLAYERS_PER_GROUP = None # remember to change the FinalResults page NUM_ROUNDS = 20 NUM_ROUNDS_PRACTICE = 10 NUM_ROUNDS_PAID = NUM_ROUNDS - NUM_ROUNDS_PRACTICE BLANK = False T_MEAN = 1000 T_VAR = 10000 E1_VAR = [10000, 10000, 10000, 10000, 10000, 10000, 10000, 10000, 50000, 50000] E2_VAR = [2000, 2000, 2000, 2000, 2000, 2000, 10000, 10000, 50000, 50000] ALPHA = [0, 0, 0.1, 0.1, 0.8, 0.8, 0.8, 0.8, 0.1, 0.1] K_BAR = [2000, 2000, 2000, 2000, 6000, 6000, 6000, 6000, 9000, 9000] T_PRACTICE = [876.504382, 906.4601833, 1148.494747, 1146.559861, 1125.669774, 897.7330639, 1066.774489, 1035.568771, 817.3964174, 1137.985715] X1_PRACTICE = [932.5740182, 984.0424414, 1238.60234, 1121.810929, 1002.332256, 910.4617282, 1120.253996, 1098.794241, 1033.840857, 1151.118714] X2_PRACTICE = [850.8454165, 961.0458127, 1209.623963, 1131.611498, 1060.490698, 889.1847475, 980.4035461, 1125.975527, 751.1025738, 989.9071976] INSTRUCTIONS = '_templates/instruction.html' DEFINITIONS = '_templates/definitions.html' class Subsession(BaseSubsession): pass class Group(BaseGroup): pass class Player(BasePlayer): # EPS prediction variables p = models.FloatField( initial=None, blank=True, label='' ) t = models.FloatField(initial=None) x1 = models.FloatField(initial=None) x2 = models.FloatField(initial=None) win_prob = models.FloatField(initial=None) random_01 = models.FloatField(initial=None) won = models.StringField(initial='No') in_practice = models.BooleanField(initial=None) parameter = models.IntegerField(initial=None) attention_check = models.FloatField(initial=None, blank=True, label='') def p_error_message(player, value): # print('value is', value) if value is None: return 'PLEASE ENTER YOUR PREDICTION BEFORE CLICKING "NEXT"' def attention_check_error_message(player, value): # print('value is', value) if value is None: return 'PLEASE ENTER YOUR PREDICTION BEFORE CLICKING "NEXT"' def creating_session(subsession): import random for player in subsession.get_players(): if player.round_number == C.NUM_ROUNDS: # parameter_sequence_practice = random.sample(range(0, C.NUM_ROUNDS_PRACTICE), C.NUM_ROUNDS_PRACTICE) parameter_sequence_practice = [7, 5, 9, 3, 2, 1, 4, 6, 0, 8] parameter_sequence_paid = random.sample(range(0, C.NUM_ROUNDS_PAID), C.NUM_ROUNDS_PAID) for p in player.in_rounds(1, C.NUM_ROUNDS): if p.round_number <= C.NUM_ROUNDS_PRACTICE: p.in_practice = True p.parameter = parameter_sequence_practice[p.round_number - 1] p.t = round(C.T_PRACTICE[p.parameter], 2) p.x1 = round(C.X1_PRACTICE[p.parameter], 2) p.x2 = round(C.X2_PRACTICE[p.parameter], 2) else: p.in_practice = False p.parameter = parameter_sequence_paid[p.round_number - C.NUM_ROUNDS_PRACTICE - 1] e1 = round(nprand.normal(loc=0, scale=math.sqrt(C.E1_VAR[p.parameter]), size=1)[0], 2) e2 = round(nprand.normal(loc=0, scale=math.sqrt(C.E2_VAR[p.parameter]), size=1)[0], 2) p.t = round(nprand.normal(loc=C.T_MEAN, scale=math.sqrt(C.T_VAR), size=1)[0], 2) p.x1 = round(p.t + e1, 2) p.x2 = round(C.ALPHA[p.parameter] * p.x1 + (1 - C.ALPHA[p.parameter]) * p.t + e2, 2) p.random_01 = random.random() # PAGES class Prediction(Page): form_model = 'player' form_fields = ['p'] @staticmethod def vars_for_template(player: Player): if player.in_practice: paid_round_number = 0 paid_stock_letter = '' else: paid_round_number = player.round_number - C.NUM_ROUNDS_PRACTICE paid_stock_letters_range = [chr(i) for i in range(ord('A'), ord('J') + 1)] paid_stock_letter = paid_stock_letters_range[paid_round_number - 1] return dict(paid_round_number=paid_round_number, paid_stock_letter=paid_stock_letter, e1_var=C.E1_VAR[player.parameter], e2_var=C.E2_VAR[player.parameter], alpha=C.ALPHA[player.parameter], one_minus_alpha=round(1 - C.ALPHA[player.parameter], 1), k_bar=C.K_BAR[player.parameter]) @staticmethod def before_next_page(player, timeout_happened): player.p = round(player.p, 2) if (player.p - player.t) ** 2 > C.K_BAR[player.parameter]: player.win_prob = 0 else: player.win_prob = round(1 - (player.p - player.t) ** 2 / C.K_BAR[player.parameter], 2) if player.in_practice: player.payoff = 0 else: # rand_between_0_1 = random.random() # player.random_01 = random.random() player.payoff = 3 if player.random_01 < player.win_prob else 0 player.won = 'Yes' if player.random_01 < player.win_prob else 'No' class PracticeResults(Page): @staticmethod def is_displayed(player): return player.in_practice @staticmethod def vars_for_template(player: Player): p_minus_t_squared = round((player.p - player.t) ** 2, 2) return dict(e1_var=C.E1_VAR[player.parameter], e2_var=C.E2_VAR[player.parameter], alpha=C.ALPHA[player.parameter], one_minus_alpha=round(1 - C.ALPHA[player.parameter], 1), k_bar=C.K_BAR[player.parameter], p_minus_t_squared=p_minus_t_squared) class PracticeToPaid(Page): @staticmethod def is_displayed(player): return player.round_number == C.NUM_ROUNDS_PRACTICE class TestPeriod(Page): form_model = 'player' form_fields = ['attention_check'] @staticmethod def is_displayed(player): return player.round_number == 15 or player.round_number == C.NUM_ROUNDS class EPSToRisk(Page): @staticmethod def is_displayed(player): return player.round_number == C.NUM_ROUNDS @staticmethod def before_next_page(player, timeout_happened): player.participant.eps_payoff = player.participant.payoff num_of_rewards_won = 0 for p in player.in_rounds(C.NUM_ROUNDS_PRACTICE + 1, C.NUM_ROUNDS): num_of_rewards_won += 1 if p.won == 'Yes' else 0 player.participant.num_of_rewards_won = num_of_rewards_won player.participant.p = [i.p for i in player.in_rounds(C.NUM_ROUNDS_PRACTICE + 1, C.NUM_ROUNDS)] player.participant.t = [i.t for i in player.in_rounds(C.NUM_ROUNDS_PRACTICE + 1, C.NUM_ROUNDS)] player.participant.win_prob = [i.win_prob for i in player.in_rounds(C.NUM_ROUNDS_PRACTICE + 1, C.NUM_ROUNDS)] player.participant.won = [i.won for i in player.in_rounds(C.NUM_ROUNDS_PRACTICE + 1, C.NUM_ROUNDS)] page_sequence = [ Prediction, PracticeResults, PracticeToPaid, TestPeriod, EPSToRisk, ]