import argparse from otree.api import * import random import csv doc = """ Your app description """ def read_csv(): import random import csv fichier = open(__name__ + '/risk.csv', 'wt') f = csv.writer(fichier, delimiter=",") f.writerow(['Round','Budget1','Budget2','Account1_A123','Account1_A456','Account1_B123','Account1_B456','Account2_C123','Account2_C456','Account2_D123','Account2_D456','num_acc']) for i in range(1,51): f.writerow([i, random.randint(40,80),random.randint(40,80),round(random.uniform(1, 1.20),2),round(random.uniform(1, 1.20),2),round(random.uniform(1, 1.20),2),round(random.uniform(1, 1.20),2),round(random.uniform(1, 1.20),2),round(random.uniform(1, 1.20),2),round(random.uniform(1, 1.20),2),round(random.uniform(1, 1.20),2), random.choices([1,2], weights=(1/3,2/3), k=1)[0] ]) fichier.close() fichier = open(__name__ + '/risk.csv',encoding='utf-8-sig') rows = list(csv.DictReader(fichier)) return rows class Constants(BaseConstants): name_in_url = 'risk' players_per_group = None num_rounds = 50 factors = read_csv() order = ["A","B","C","D","E","A","B","C","D","E","A","B","C","D","E","A","B","C","D","E","A","B","C","D","E","A","B","C","D","E","A","B","C","D","E","A","B","C","D","E","A","B","C","D","E",] order2 = [i for i in range (1,51)] class Subsession(BaseSubsession): pass class Group(BaseGroup): pass def creating_session(subsession): import random treatments = [1, 2, 3, 4] tabs = [0,1] import itertools balanced_treats = itertools.cycle(treatments) if subsession.round_number == 1: for p in subsession.get_players(): p.participant.treatment = next(balanced_treats) #p.participant.tab = 1 is for tab version. Change to 0 for slider version if p.participant.treatment in [1, 3]: p.participant.tab = 0 else: p.participant.tab = 0 p.tabs = p.participant.tab p.treatment = p.participant.treatment round_numbers = list(range(1, Constants.num_rounds + 1)) random.shuffle(round_numbers) task_rounds = dict(zip(Constants.order2, round_numbers)) p.participant.task_rounds = round_numbers if subsession.round_number == 1: for p in subsession.get_players(): participant = p.participant factors = read_csv() participant.task_rounds = factors random.shuffle(participant.task_rounds) for p in subsession.get_players(): participant = p.participant current_round = participant.task_rounds[subsession.round_number - 1] p.roundt = int(current_round['Round']) p.num_acc = int(current_round['num_acc']) p.budget1 = int(current_round['Budget1']) p.budget2 = int(current_round['Budget2']) p.acc1_A123 = float(current_round['Account1_A123']) p.acc1_A456 = float(current_round['Account1_A456']) p.acc1_B123 = float(current_round['Account1_B123']) p.acc1_B456 = float(current_round['Account1_B456']) p.acc2_C123 = float(current_round['Account2_C123']) p.acc2_C456 = float(current_round['Account2_C456']) p.acc2_D123 = float(current_round['Account2_D123']) p.acc2_D456 = float(current_round['Account2_D456']) class Player(BasePlayer): treatment = models.IntegerField() num_acc = models.IntegerField() tabs = models.IntegerField() asset_A = models.IntegerField() asset_B = models.IntegerField() asset_C = models.IntegerField() asset_D = models.IntegerField() dice = models.IntegerField() q2 = models.FloatField(label="If this round determines your payment, how much will you earn if the dice roll is 2?") q3 = models.FloatField(label="If this round determines your payment, how much will you earn if the dice roll is 6?") q4 = models.IntegerField(label="", choices=[[1,"True"],[2,"False"]]) budget1 = models.IntegerField() budget2 = models.IntegerField() acc1_A123 = models.FloatField() acc1_A456 = models.FloatField() acc1_B123 = models.FloatField() acc1_B456 = models.FloatField() acc2_C123 = models.FloatField() acc2_C456 = models.FloatField() acc2_D123 = models.FloatField() acc2_D456 = models.FloatField() roundt = models.IntegerField() click_res = models.StringField() survey0 = models.StringField() survey1 = models.StringField() survey2 = models.StringField() survey3 = models.StringField() survey4 = models.StringField() survey5 = models.StringField() survey6 = models.StringField() survey7 = models.StringField() survey8 = models.StringField() survey9 = models.StringField() survey10 = models.StringField() result = models.FloatField() rnd = models.IntegerField() is_mobile = models.BooleanField() prolific = models.StringField(label="Prolific ID") order_acc = models.IntegerField() def set_payoffs(self): self.dice = random.randint(1, 6) if self.dice in [1, 2, 3]: factorA, factorB, factorC, factorD = [self.acc1_A123,self.acc1_B123,self.acc2_C123,self.acc2_D123] else: factorA, factorB, factorC, factorD = [self.acc1_A456,self.acc1_B456,self.acc2_C456,self.acc2_D456] if self.num_acc==1: self.asset_B = self.budget1 - self.asset_A self.asset_D = None self.result = self.asset_A * factorA + self.asset_B*factorB else: self.asset_B = self.budget1 - self.asset_A self.asset_D = self.budget2 - self.asset_C self.result = self.asset_A * factorA + self.asset_B * factorB + \ self.asset_C * factorC + self.asset_D * factorD return self.result # PAGES class Data(ExtraModel): player = models.Link(Player) slider_move = models.IntegerField() slider_move2 = models.IntegerField() click_res = models.IntegerField() tab_click = models.IntegerField() class Round_slider(Page): form_model = 'player' @staticmethod def get_form_fields(player): if player.roundt == 1 or player.roundt == 3: return ['asset_A', 'asset_C'] else: return ['asset_A'] def is_displayed(player): participant = player.participant if participant.tab == 0: return True else: pass def vars_for_template(self): factor_list = [self.acc1_A123, self.acc1_A456, self.acc1_B123, self.acc1_B456, self.acc2_C123, self.acc2_C456, self.acc2_D123, self.acc2_D456] for i in range(len(factor_list)): if isinstance(factor_list[i], float): factor_list[i] = format(factor_list[i], '.2f') if self.roundt in [1,3]: random_acc = [1, 2] self.order_acc = random.choice(random_acc) else: self.order_acc = 0 return {'A_123': factor_list[0], 'A_456': factor_list[1], 'B_123': factor_list[2], 'B_456': factor_list[3], 'C_123': factor_list[4], 'C_456': factor_list[5], 'D_123': factor_list[6], 'D_456': factor_list[7], 'budgetAB': self.budget1, 'budgetCD': self.budget2, 'order_acc': self.order_acc} def js_vars(self): return dict(budgetAB= self.budget1, budgetCD= self.budget2, order = self.order_acc) def live_method(player: Player, data): player.click_res = '' if 'slider_move' in data: slider_move = data['slider_move'] Data.create( player=player, slider_move=slider_move, ) if 'slider_move2' in data: slider_move2 = data['slider_move2'] Data.create( player=player, slider_move2=slider_move2, ) tab_history = [[dat.slider_move, dat.slider_move2] for dat in Data.filter(player=player)] for u in tab_history: if u[0] != None: player.click_res += 'A1S' + str(u[0]) + '-' if u[1] != None: player.click_res += 'A2S' + str(u[1]) + '-' class Round_tab(Page): form_model = 'player' @staticmethod def get_form_fields(player): if player.roundt == 1 or player.roundt == 3: return ['asset_A', 'asset_C'] else: return ['asset_A'] def is_displayed(player): participant = player.participant if participant.tab == 1: return True else: pass def vars_for_template(self): factor_list = [self.acc1_A123, self.acc1_A456, self.acc1_B123, self.acc1_B456, self.acc2_C123, self.acc2_C456, self.acc2_D123, self.acc2_D456] for i in range(len(factor_list)): if isinstance(factor_list[i], float): factor_list[i] = format(factor_list[i], '.2f') if self.roundt in [1,3]: random_acc = [1, 2] self.order_acc = random.choice(random_acc) else: self.order_acc = 0 return {'A_123': factor_list[0], 'A_456': factor_list[1], 'B_123': factor_list[2], 'B_456': factor_list[3], 'C_123': factor_list[4], 'C_456': factor_list[5], 'D_123': factor_list[6], 'D_456': factor_list[7], 'budgetAB': self.budget1, 'budgetCD': self.budget2, 'order_acc': self.order_acc} def js_vars(player): return dict(budgetAB=player.budget1, budgetCD=player.budget2, order = player.order_acc) def live_method(player: Player, data): player.click_res = '' if 'tab_click' in data: tab_click = data['tab_click'] Data.create( player=player, tab_click=tab_click, ) if 'slider_move' in data: slider_move = data['slider_move'] Data.create( player=player, slider_move=slider_move, ) if 'slider_move2' in data: slider_move2 = data['slider_move2'] Data.create( player=player, slider_move2=slider_move2, ) tab_history = [[dat.tab_click, dat.slider_move, dat.slider_move2] for dat in Data.filter(player=player)] for u in tab_history: if u[0] == 1: player.click_res += 'T1-' elif u[0] == 2: player.click_res += 'T2-' if u[1] != None: player.click_res += 'A1S' + str(u[1]) + '-' if u[2] != None: player.click_res += 'A2S' + str(u[2]) + '-' class Results(Page): def vars_for_template(player): p1 = Player.set_payoffs(player) return None class Ins_Risk(Page): def is_displayed(player): return player.round_number == 1 class Consent(Page): form_model = 'player' form_fields = ['is_mobile','prolific'] def is_displayed(player): return player.round_number == 1 def error_message(player: Player, values): if values['is_mobile']: return "Sorry, this experiment does not allow mobile browsers." class Quiz2(Page): form_model = 'player' form_fields = ['q2', 'q3'] @staticmethod def error_message(player, values): solutions = dict(q2=9, q3=7) error_messages = dict() for f in solutions: if len(str((values[f]))[str((values[f])).rfind('.') + 1:]) <= 2 and values[f] != solutions[f]: error_messages[f] = 'Wrong' elif len(str((values[f]))[str((values[f])).rfind('.') + 1:]) > 2: error_messages[f] = 'Please input up to only 2 digits after decimal point' return error_messages def is_displayed(player): return player.round_number == 1 class Quiz3(Page): form_model = 'player' form_fields = ['q4'] @staticmethod def error_message(player, values): if values['q4'] != 1: return 'Try again' def is_displayed(player): participant = player.participant if participant.treatment in [3, 4]: return player.round_number == 1 else: pass class Quiz4(Page): form_model = 'player' def is_displayed(player): return player.round_number == 1 class Enter_Round(Page): def is_displayed(player): return player.round_number == 1 class End(Page): def is_displayed(player): return player.round_number == 50 def vars_for_template(player): player.rnd = random.randint(1,51) p = player.in_round(player.rnd) player.payoff = p.result return class Final_Survey(Page): form_model = 'player' form_fields = ['survey0', 'survey1', 'survey2','survey3', 'survey4', 'survey5','survey6', 'survey7', 'survey8','survey9','survey10'] def is_displayed(player): return player.round_number == 50 page_sequence = [Consent,Ins_Risk,Quiz2,Quiz3,Quiz4,Enter_Round,Round_slider,Round_tab,Results,Final_Survey,End]