from otree.api import * doc = """ Your app description """ class C(BaseConstants): NAME_IN_URL = 'niuge' PLAYERS_PER_GROUP = 3 NUM_ROUNDS = 1 # endowment ENDOWMENT = 50 # noises NOISE_LIST = [0.48, 0.50, 0.52] # game true multipliers # game1 #game_1_multiplier = 0.73333 # game2 #game_2_multiplier = 0.66667 timers = dict(start_next_part = 120, game = 120, instruction = 120) information_template = 'choose_leader/Information.html' example1_template = 'choose_leader/Example1.html' class Subsession(BaseSubsession): pass class Group(BaseGroup): treatment = models.IntegerField() # treatments game_1 = models.BooleanField() # if play game 1 leader = models.IntegerField() # leader player id has_dropout = models.BooleanField(initial = False) # treatments chosen = models.StringField() #total_cont = models.FloatField() class Player(BasePlayer): # if player is leader is_leader = models.BooleanField(initial = False) timeout = models.IntegerField(initial = 0) total_payoff = models.FloatField(initial = 0) excluded = models.BooleanField(initial = False) # fail comprehension quiz num_failed_attempts = models.IntegerField(initial = 0) failed_too_many = models.BooleanField(initial = False) # vr leader selection leader_vr = models.IntegerField(label ="", widget=widgets.RadioSelect)#label = "", #choices=[ #[0, 'The player who had the highest accuracy level.'], # [1, 'The player who had the second highest accuracy level.'], # [2, 'The player who had the lowest accuracy level.'], #])#) # game the player chooses choose_game_1 = models.BooleanField( label = "Would you choose Project A or Project B? ", choices = [ [True, "Project A"], [False, "Project B"] ]) # old comprehension quiz #q10 = models.IntegerField( # label="Suppose the rate of return of Project A is 40%, " # "if you contribute 50 tokens to the public account, both the other two group members " # "contribute 0 tokens, then YOUR final bonus is:", #choices=[ #[0, "(50-0) +[(1+40%)*50]/3=73.3 tokens"], # [1, "(50-0) +[(1+40%)*50]=120 tokens"], # [2, "(50-50) +[(1+40%)*50]/3=23.3 tokens"], # correct #[3, "(50-50) +[(1+40%)*50]=70 tokens"] #]) #q11 = models.IntegerField( # label="Suppose you contribute 40 tokens and you eventually" # "receive 15 tokens from the public account, then your final bonus in this study is:", #choices=[ # [0, "(50-40) +15=25 tokens"], # correct # [1, "50+15=65 tokens"] #) #q12 = models.IntegerField( # label="Suppose the rate of return of Project A is -40%," # "if you contribute 50 tokens to the public account, each of the other two group " # "members contribute 0 tokens, then your final bonus in this study is:", # choices=[ # [0, "(50-50) +[(1-40%)*50]/3=10 tokens"], # correct # [1, "0 tokens"], # [2, "(50-0) +[(1+40%)*50]/3=60 tokens"], # [3, "50 tokens"] # ]) #q20 = models.IntegerField( # label="Suppose the rate of return of Project B is 40%, " # "if you contribute 50 tokens to the public account, both the other two group members " # "contribute 0 tokens, then your final bonus is:", #choices=[ # [0, "(50-0) +[(1+40%)*50]/3=73.3 tokens"], # [1, "(50-0) +[(1+40%)*50]=120 tokens"], # [2, "(50-50) +[(1+40%)*50]/3=23.3 tokens"], # correct # [3, "(50-50) +[(1+40%)*50]=70 tokens"] # ]) # q21 = models.IntegerField( # label="Suppose you contribute 40 tokens and you eventually" # "receive 15 tokens from the public account, then your final bonus in this study is:", # choices=[ # [0, "(50-40) +15=25 tokens"], # correct # [1, "50+15=65 tokens"] # ]) # q22 = models.IntegerField( # label="Suppose the rate of return of Project B is negative and is -40%, " # "if you contribute 50 tokens to the public account, each of the other two group " # "members contribute 0 tokens, then your final bonus in this study is:", # choices=[ # [0, "(50-50) +[(1-40%)*50]/3=10 tokens"], # correct # [1, "0 tokens"], # [2, "(50-0) +[(1+40%)*50]/3=60 tokens"], # [3, "50 tokens"] # ]) # contribution contribution = models.FloatField( label = "How much would you invest? ", min=0, max=50 ) prediction = models.IntegerField( label="Please give a guess on the range within which the highest accuracy level of your " "group is most likely to fall:", choices=[ [0, '40%-50%'], [1, '50%-60%'], [2, '60%-70%'], [3, '70%-80%'], [4, '80%-90%'], [5, '90%-100%'] ] ) # noise given to player noise = models.FloatField() def leader_vr_choices(player: Player): import random choices = [ [0, 'The player who had the highest accuracy level.'], [1, 'The player who had the medium accuracy level.'], [2, 'The player who had the lowest accuracy level.'], ] random.shuffle(choices) return choices # make noisy game2 payoff def set_payoffs(player: Player, const: C): import random noise = random.random() game = "Project B" if noise < player.noise else "Project A" return game # PAGES class StartWaitPage(WaitPage): group_by_arrival_time = True @staticmethod def is_displayed(player: Player): return player.participant.dropout == False @staticmethod def after_all_players_arrive(group: Group): import random group.treatment = random.randint(0, 2) # 0 is control, 1 is VR, 2 is CR li = C.NOISE_LIST.copy() # for every player in group for p in group.get_players(): p.noise = random.choice(li) # assign random from noise list li.remove(p.noise) # remove assigned value class ChooseGame(Page): timeout_seconds = C.timers['start_next_part'] timer_text = 'Time Remaining: ' @staticmethod def is_displayed(player: Player): return player.group.has_dropout == False @staticmethod def vars_for_template(player: Player): game = set_payoffs(player, C) acc = (1 - player.noise)*100 return { "game": game, "acc": acc } @staticmethod def before_next_page(player: Player, timeout_happened): if timeout_happened: player.participant.dropout = True player.group.has_dropout = True @staticmethod def app_after_this_page(player: Player, upcoming_apps): participant = player.participant if participant.dropout: return upcoming_apps[-1] form_model = "player" form_fields = ["choose_game_1"] class ResultGame(Page): timeout_seconds = C.timers['start_next_part'] timer_text = 'Time Remaining: ' @staticmethod def is_displayed(player: Player): return player.group.has_dropout == False @staticmethod def before_next_page(player: Player, timeout_happened): import random if timeout_happened: player.participant.dropout = True player.group.has_dropout = True @staticmethod def app_after_this_page(player: Player, upcoming_apps): participant = player.participant if participant.dropout: return upcoming_apps[-1] @staticmethod def vars_for_template(player: Player): result = "Project A. " if player.choose_game_1 else "Project B. " return { "result": result } class EXO(Page): timeout_seconds = C.timers['instruction'] timer_text = 'Time Remaining: ' @staticmethod def is_displayed(player: Player): return player.group.has_dropout == False and player.group.treatment == 0 @staticmethod def before_next_page(player: Player, timeout_happened): if timeout_happened: player.participant.dropout = True player.group.has_dropout = True @staticmethod def app_after_this_page(player: Player, upcoming_apps): participant = player.participant if participant.dropout: return upcoming_apps[-1] class CR(Page): timeout_seconds = C.timers['instruction'] timer_text = 'Time Remaining: ' @staticmethod def is_displayed(player: Player): return player.group.has_dropout == False and player.group.treatment == 2 @staticmethod def before_next_page(player: Player, timeout_happened): if timeout_happened: player.participant.dropout = True player.group.has_dropout = True @staticmethod def app_after_this_page(player: Player, upcoming_apps): participant = player.participant if participant.dropout: return upcoming_apps[-1] class VR(Page): timeout_seconds = C.timers['instruction'] timer_text = 'Time Remaining: ' @staticmethod def is_displayed(player: Player): return player.group.has_dropout == False and player.group.treatment == 1 @staticmethod def before_next_page(player: Player, timeout_happened): if timeout_happened: player.participant.dropout = True player.group.has_dropout = True @staticmethod def app_after_this_page(player: Player, upcoming_apps): participant = player.participant if participant.dropout: return upcoming_apps[-1] form_model = "player" form_fields = ["leader_vr"] class ResultWaitPage(WaitPage): @staticmethod def is_displayed(player: Player): return player.group.has_dropout == False @staticmethod def after_all_players_arrive(group: Group): if group.has_dropout == False: import random choice_list = [] # store choices noise_list = {} # store noises chosen_list = ["highest", "medium", "lowest"] for p in group.get_players(): noise_list[p.id_in_group] = p.noise noise_list = dict(sorted(noise_list.items(), key = lambda item: item[1])) # sort noises: 0.45, 0.48, 0.52 # get all players' choices choice = 0 if group.treatment == 1: for p in group.get_players(): choice = p.leader_vr choice_list.append(choice) # Out of the loop -- if treatment 1, get majority choice choice = max(set(choice_list), key = choice_list.count) group.leader = list(noise_list)[choice] # get the player ID with majority-chosen noise group.chosen = chosen_list[choice] # else just get the one with the lowest noise else: group.leader = list(noise_list)[0] if group.treatment == 0: group.game_1 = bool(random.getrandbits(1)) else: # switch the person to leader, switch group game according to leader choice for p in group.get_players(): if p.id_in_group == p.group.leader: p.is_leader = True p.group.game_1 = p.choose_game_1 else: pass class ResultLeader(Page): timeout_seconds = C.timers['start_next_part'] timer_text = 'Time Remaining: ' @staticmethod def is_displayed(player: Player): return player.group.has_dropout == False @staticmethod def vars_for_template(player: Player): result = "Project A. " if player.group.game_1 else "Project B. " if player.group.treatment != 0: message = "The leader has now been selected. The player who has the " + player.group.chosen + " accuracy level has been selected as the leader. The leader's choice is " + result if player.group.treatment == 1 else "The leader has been selected. The leader's choice is " + result else: message = " " return { "message": message, "result": result } @staticmethod def before_next_page(player: Player, timeout_happened): if timeout_happened: player.participant.dropout = True player.group.has_dropout = True @staticmethod def app_after_this_page(player: Player, upcoming_apps): participant = player.participant if participant.dropout: return upcoming_apps[-1] class Contribute(Page): timeout_seconds = C.timers['game'] timer_text = 'Time Remaining: ' @staticmethod def is_displayed(player: Player): return player.group.has_dropout == False @staticmethod def vars_for_template(player: Player): project = "Project A " if player.group.game_1 else "Project B " return { "project": project } @staticmethod def before_next_page(player: Player, timeout_happened): if timeout_happened: player.participant.dropout = True player.group.has_dropout = True @staticmethod def app_after_this_page(player: Player, upcoming_apps): participant = player.participant if participant.dropout: return upcoming_apps[-1] form_model = "player" form_fields = ["contribution","prediction"] class FinalWaitPage(WaitPage): @staticmethod def is_displayed(player: Player): return player.group.has_dropout == False @staticmethod def after_all_players_arrive(group: Group): #group.total_cont = 0 #for p in group.get_players(): #group.total_cont += p.contribution for p in group.get_players(): reward = 0 if group.game_1 else p.contribution * 2 p.total_payoff = C.ENDOWMENT - p.contribution + reward p.participant.game_payoff = p.total_payoff @staticmethod def before_next_page(player: Player, timeout_happened): import random if timeout_happened: player.participant.dropout = True @staticmethod def app_after_this_page(player: Player, upcoming_apps): participant = player.participant if participant.dropout: return upcoming_apps[-1] class FinalResult(Page): timeout_seconds = C.timers['start_next_part'] timer_text = 'Time Remaining: ' @staticmethod def is_displayed(player: Player): return player.group.has_dropout == False @staticmethod def before_next_page(player: Player, timeout_happened): if timeout_happened: player.participant.dropout = True player.group.has_dropout = True @staticmethod def app_after_this_page(player: Player, upcoming_apps): participant = player.participant if participant.dropout: return upcoming_apps[-1] class DropOutHappened(Page): @staticmethod def is_displayed(player: Player): group = player.group return group.has_dropout @staticmethod def before_next_page(player: Player, timeout_happened): group = player.group for p in group.get_players(): if p.participant.dropout == False: p.participant.excluded = True @staticmethod def app_after_this_page(player: Player, upcoming_apps): return upcoming_apps[-1] page_sequence = [StartWaitPage, ChooseGame, ResultGame, CR, VR, EXO, ResultWaitPage, ResultLeader, Contribute, FinalWaitPage, FinalResult, DropOutHappened]#, CR, ResultWaitPage, Result2]