from otree.api import * doc = """ Your app description """ class C(BaseConstants): NAME_IN_URL = 'Guess_6_5' PLAYERS_PER_GROUP = 50 NUM_ROUNDS = 5 number_intervals_vars_for_admin = 10 class Subsession(BaseSubsession): pass class Group(BaseGroup): six_fifths_mean = models.FloatField() class Player(BasePlayer): number = models.FloatField( min=0, max=100, label="Your Number:" ) distance = models.FloatField() place = models.IntegerField # FUNCTIONS def vars_for_admin_report(subsession): interval_list = [] for elem in range(C.number_intervals_vars_for_admin): if elem == 0: interval_list.append(str(0) + "-" + str(round(100 / C.number_intervals_vars_for_admin))) else: interval_list.append(str((round(100 / C.number_intervals_vars_for_admin) * elem)) + "-" + str( (round(100 / C.number_intervals_vars_for_admin) * (elem + 1)))) player_numbers = ([p.field_maybe_none('number') for p in subsession.get_players() if p.field_maybe_none('number') is not None]) absolute_frequencies = [0] * C.number_intervals_vars_for_admin threshold_values = [0] for elem in range(C.number_intervals_vars_for_admin + 1): if elem != 0: threshold_values.append(round(100 / C.number_intervals_vars_for_admin) * elem) for i in range(len(player_numbers)): for elem in range(C.number_intervals_vars_for_admin): if player_numbers[i] > threshold_values[elem] and player_numbers[i] <= threshold_values[elem + 1]: absolute_frequencies[elem] += 1 return { "interval_list": interval_list, "threshold_values": threshold_values, "absolute_frequencies": absolute_frequencies, "mean_guess": sum(player_numbers) / len(player_numbers) } # PAGES class Instructions(Page): timeout_seconds = 60 @staticmethod def is_displayed(player): return player.round_number == 1 class MyPage(Page): form_model = "player" form_fields = ["number"] @staticmethod def before_next_page(player, timeout_happened): if timeout_happened: player.number = None def Calculate_Six_Fifths(group: Group): list_of_numbers = [p.field_maybe_none('number') for p in group.get_players() if p.field_maybe_none('number') is not None] group.six_fifths_mean = sum(list_of_numbers) / len(list_of_numbers) * 6 / 5 class ResultsWaitPage(WaitPage): after_all_players_arrive = Calculate_Six_Fifths class Results(Page): def vars_for_template(player: Player): list_of_all_players_numbers = [p.field_maybe_none('number') for p in player.group.get_players() if p.field_maybe_none('number') is not None] list_of_all_players_distances = [] for elem in list_of_all_players_numbers: list_of_all_players_distances.append(abs(elem - player.group.six_fifths_mean)) if player.field_maybe_none('number') is not None: player.distance = abs(player.number - player.group.six_fifths_mean) list_of_all_players_distances = sorted(list_of_all_players_distances) if player.field_maybe_none('distance') is not None: player.place = list_of_all_players_distances.index(player.distance)+1 ans = [{"id": str(player.id_in_group), "value": round(player.field_maybe_none('number'),2), "highlight": False} for player in player.get_others_in_group() if player.field_maybe_none('number') is not None] ans.append({"id": "Six Fifths Average", "value": round(player.group.six_fifths_mean,2), "highlight": True }) if player.field_maybe_none('number') is not None: ans.append({"id": "You (Player "+str(player.id_in_group)+")", "value": round(player.field_maybe_none('number'),2), "highlight": True}) # WRONG: ans = ans.append({"id": "Six Fifths Average", "value": player.group.six_fifths_mean }) --> returns none because append returns none # ans = [] # ans.append({"id": str(player.id_in_group), "value": player.number} for player in player.get_others_in_group()) ans = sorted(ans, key=lambda elem: elem["value"]) return {"ans": ans, "list_of_all_players_distances": list_of_all_players_distances, } page_sequence = [Instructions, MyPage, ResultsWaitPage, Results]