import random, itertools import numpy as np from otree.api import * import json c = cu doc = """""" # CLASSES class C(BaseConstants): NAME_IN_URL = 'example' PLAYERS_PER_GROUP = None NUM_ROUNDS = 1 SETSIZE = 30 MU = [2,8] class Subsession(BaseSubsession): pass class Group(BaseGroup): pass class Player(BasePlayer): seq_value = models.LongStringField(initial= "") allXP = models.LongStringField() seq_arm = models.LongStringField(initial= "") choice = models.IntegerField(label= "Choose a slot machine to play for real:", choices= range(1,C.SETSIZE+1)) estimation = models.IntegerField( label= "How many times do you expect to win if you get 100 draws from this slot machine?", min = 0, max = 100) chosen_x = models.FloatField() chosen_p = models.FloatField() is_understand = models.BooleanField(initial=True) # FUNCTIONS def make_field(label,answer): return models.IntegerField( blank= False, label = label, widget = widgets.RadioSelect, choices= [ [1, answer[0]], [2, answer[1]], [3, answer[2]], [4, answer[3]]] ) q1 = make_field(label="How much does it cost to play a slot machine for fun with no real rewards?", answer= ['A. 1 Euro','B. 1 point','C. 0.01 point','D. Free']) q2 = make_field(label="My actual score in this task is determined by:", answer= ['A. The outcome of a draw from my chosen machine', 'B. The outcome of a draw from a random machine', 'C. The outcome of a draw from my chosen machine minus the search cost', 'D. None of the above']) q3 = make_field(label= "Who will get a bonus of 10 Euro in this task?", answer= ['A. The person with the lowest score', 'B. A random person', 'C. The person with the highest score', 'D. The person with an average score']) def creating_session(subsession): # create mus and sds lists for player in subsession.get_players(): np.random.seed(player.id_in_subsession + 3) n = C.SETSIZE # generate p and x from evs, similar evs, different sds ev1 = np.random.uniform( C.MU[0], C.MU[1], int(C.SETSIZE)) p1 = np.random.uniform(0.1,0.9, int(C.SETSIZE)) x1 = np.round(ev1/p1,2) # create dictionary data = {'x':x1.tolist() , 'p': p1.tolist() } # convert dictionary to json string xPText = json.dumps(data) player.allXP = xPText # Functions def custom_export(players): yield ['participant_code', 'id_in_group'] # THESE ARE 2 OBJECTS OF PLAYERS for p in players: pp = p.participant yield [pp.code, p.id_in_group] # PAGES class Introduction(Page): pass class Bandit(Page): form_model = 'player' form_fields = ['choice','estimation'] @staticmethod def live_method(player, data): # receive data from the page player.seq_arm = data['seq_arm'] player.seq_value = data['seq_value'] @staticmethod def js_vars(player): # to include set size variable in javascript return dict(setSize = C.SETSIZE, allXP = player.allXP) @staticmethod def error_message(player, values): if player.seq_arm == "": return "You haven't sampled any option" @staticmethod def before_next_page(player, timeout_happened): player.chosen_x = json.loads(player.allXP)['x'][player.choice -1] player.chosen_p = json.loads(player.allXP)['p'][player.choice -1] class Quiz(Page): form_model = 'player' form_fields = ['q1','q2','q3'] @staticmethod def error_message(player: Player, values): correct_answers = 0 solutions = dict(q1=3, q2=3, q3=3) for q in solutions: if q in values and values[q] == solutions[q]: correct_answers += 1 if correct_answers == 0: player.is_understand = False class Exclude(Page): @staticmethod def is_displayed(player: Player): return player.is_understand == False page_sequence = [Introduction, Bandit, Quiz, Exclude]