from otree.api import * import random doc = """ Your app description """ class Constants(BaseConstants): name_in_url = 'p2' players_per_group = 2 num_rounds = 1 showup = 125 intervals = [ [-75, -50], [-49, -25], [-24, -1], [0, 25], [26, 50], [51, 75], [76, 100], [101, 125], [126, 150], [151, 175], [176, 200], [201, 225], [226, 250] ] class Subsession(BaseSubsession): pass def creating_session(subsession): for player in subsession.get_players(): # set treatment from session config, if not set before if player.participant.vars.get('treatment') is None: player.treatment = subsession.session.config['treatment'] player.participant.vars['treatment'] = player.treatment else: player.treatment = player.participant.vars['treatment'] # set types by group ids, if not grouped before if player.participant.vars.get('type') is None: if player.id_in_group == 1: player.type = "A" if player.id_in_group == 2: player.type = "B" player.participant.vars['type'] = player.type else: player.type = player.participant.vars['type'] # set fake decisions from p1 for results for group in subsession.get_groups(): players = group.get_players() player_A = [p for p in players if p.type == "A"][0] player_B = [p for p in players if p.type == "B"][0] player_B.participant.vars['p1'] = {'decision_B': 50} class Group(BaseGroup): pass class Player(BasePlayer): type = models.StringField() treatment = models.StringField() decision1_A = models.IntegerField() decision1_A_min = models.IntegerField() decision1_A_max = models.IntegerField() decision2_A = models.IntegerField() decision3_A1 = models.IntegerField(max=100, min=0, label="") decision3_A2 = models.IntegerField(max=100, min=0, label="") decision3_A3 = models.IntegerField(max=100, min=0, label="") decision3_A4 = models.IntegerField(max=100, min=0, label="") decision3_A5 = models.IntegerField(max=100, min=0, label="") decision3_A6 = models.IntegerField(max=100, min=0, label="") decision3_A7 = models.IntegerField(max=100, min=0, label="") decision3_A8 = models.IntegerField(max=100, min=0, label="") decision3_A9 = models.IntegerField(max=100, min=0, label="") decision3_A10 = models.IntegerField(max=100, min=0, label="") decision3_A11 = models.IntegerField(max=100, min=0, label="") decision3_A12 = models.IntegerField(max=100, min=0, label="") decision3_A13 = models.IntegerField(max=100, min=0, label="") decision1_B = models.IntegerField(min=0, max=13) decision2_B = models.IntegerField(min=0, max=100) # PAGES class Instructions_A(Page): def is_displayed(player: Player): return player.type == "A" class Decision1_A(Page): form_model = 'player' form_fields = ['decision1_A'] def before_next_page(player: Player, timeout_happened): chosen_interval = Constants.intervals[int(player.decision1_A) - 1] player.decision1_A_min = chosen_interval[0] player.decision1_A_max = chosen_interval[1] def is_displayed(player: Player): return player.type == "A" class Decision2_A(Page): form_model = 'player' form_fields = ['decision2_A'] def is_displayed(player: Player): return player.type == "A" class Decision3_A(Page): form_model = 'player' def get_form_fields(player): if player.treatment == 'T1' or player.treatment == 'T1_B': return ['decision3_A1', 'decision3_A2', 'decision3_A3', 'decision3_A4', 'decision3_A5', 'decision3_A6', 'decision3_A7', 'decision3_A8', 'decision3_A9', 'decision3_A10', 'decision3_A11', 'decision3_A12', 'decision3_A13', ] else: return [ 'decision3_A4', 'decision3_A5', 'decision3_A6', 'decision3_A7', 'decision3_A8', 'decision3_A9', 'decision3_A10', 'decision3_A11', 'decision3_A12', 'decision3_A13', ] def is_displayed(player: Player): return player.type == "A" # B Player class Instructions_B(Page): def is_displayed(player: Player): return player.type == "B" class Decision1_B(Page): form_model = 'player' form_fields = ['decision1_B'] def is_displayed(player: Player): return player.type == "B" class Decision2_B(Page): form_model = 'player' form_fields = ['decision2_B'] def is_displayed(player: Player): return player.type == "B" class WaitForAll(WaitPage): def after_all_players_arrive(group: Group): players = group.get_players() player_A = [p for p in players if p.type == "A"][0] player_B = [p for p in players if p.type == "B"][0] # calculate average of Bs within treatment all_players_b = [p for p in group.subsession.get_players() if p.type == "B"] b_choices = [p.participant.vars['p1']['decision_B'] for p in all_players_b] average_of_all_b = sum(b_choices) / len(b_choices) average_of_all_b_interval = 0 average_of_all_b_interval_max = 0 average_of_all_b_interval_min = 0 print(b_choices, average_of_all_b_interval, average_of_all_b) for x, i in enumerate(Constants.intervals): min_range = i[0] max_range = i[1] if int(average_of_all_b) >= min_range and int(average_of_all_b) <= max_range: average_of_all_b_interval = x average_of_all_b_interval_max = max_range average_of_all_b_interval_min = min_range break print(average_of_all_b_interval) # player A # threshold = random.randint(0, 100) threshold = - 100 draw = random.randint(0, 100) percentage = int(player_A.decision2_A) lottery = False win = False pay = 0 if threshold >= percentage: lottery = True if draw <= threshold: win = True pay = 200 else: if player_A.decision1_A == average_of_all_b_interval: win = True pay = 200 player_A.participant.vars['p2'] = { 'threshold': threshold, 'draw': draw, 'percentage': percentage, 'lottery': lottery, 'win': win, 'average_of_b_number': average_of_all_b, 'average_of_b': average_of_all_b_interval, 'average_of_b_max': average_of_all_b_interval_max, 'average_of_b_min': average_of_all_b_interval_min, 'decision1_A_min': player_A.decision1_A_min, 'decision1_A_max': player_A.decision1_A_max } if player_A.participant.vars.get('payoffs'): player_A.participant.vars['payoffs']['p2'] = pay + Constants.showup else: player_A.participant.vars['payoffs'] = {'p2': pay + Constants.showup} # player B selected_decision = random.randint(1, 2) payoff_b = 0 if selected_decision == 1: win = False if player_A.decision1_A == player_B.decision1_B: payoff_b = 200 win = True chosen_interval = Constants.intervals[int(player_B.decision1_B) - 1] decision1_B_min = chosen_interval[0] decision1_B_max = chosen_interval[1] if player_B.treatment == 'T1' or player_B.treatment == "T1_B": answered_prob = player_A.decision3_A1 + player_A.decision3_A2 + player_A.decision3_A3 else: answered_prob = player_A.decision3_A13 + player_A.decision3_A12 + player_A.decision3_A11 + \ player_A.decision3_A10 + player_A.decision3_A9 + player_A.decision3_A8 + \ player_A.decision3_A7 + player_A.decision3_A6 if selected_decision == 2: # depends on treatment win = False tolerance = 5 if abs(player_B.decision2_B - answered_prob) <= tolerance: payoff_b = 200 win = True player_B.participant.vars['p2'] = { 'decision': selected_decision, 'player_A.decision': player_A.decision1_A, 'decision1_A_min': player_A.decision1_A_min, 'decision1_A_max': player_A.decision1_A_max, 'player_B.decision': player_B.decision1_B, 'decision1_B_min': decision1_B_min, 'decision1_B_max': decision1_B_max, 'win': win, 'answered_prob': answered_prob, 'estimated_prob': player_B.decision2_B, } if player_B.participant.vars.get('payoffs'): player_B.participant.vars['payoffs']['p2'] = payoff_b + Constants.showup else: player_B.participant.vars['payoffs'] = {'p2': payoff_b + Constants.showup} player_A.participant.vars['payoffs']['p2_b'] = player_B.participant.vars['payoffs']['p2'] player_B.participant.vars['payoffs']['p2_a'] = player_A.participant.vars['payoffs']['p2'] player_A.participant.vars['payoffs']['p2_a'] = player_A.participant.vars['payoffs']['p2'] player_B.participant.vars['payoffs']['p2_b'] = player_B.participant.vars['payoffs']['p2'] class Complete(Page): pass page_sequence = [Instructions_A, Decision1_A, Decision2_A, Decision3_A, Instructions_B, Decision1_B, Decision2_B, WaitForAll, Complete]