from otree.api import * """ Sim for "Beauty Contest" game. Each player guesses a number from 0 to 100, up to 3 decimal places. After all guesses are submitted, the winner is the player whose guess was closest to 2/3 of the value of the average guess. """ class Constants(BaseConstants): name_in_url = 'beauty' players_per_group = None num_rounds = 1 instructions_template = 'beautyContest/instructions.html' class Subsession(BaseSubsession): pass class Group(BaseGroup): winning = models.FloatField() class Player(BasePlayer): guess = models.FloatField(min=0, label='') winner = models.BooleanField() # FUNCTIONS def guess_max(player: Player): return player.session.config['endowment'] def guess_error_message(player: Player, value): if str(value)[::-1].find('.') > 3: return 'Up to 3 decimal places are allowed' # PAGES class Introduction(Page): pass class Main(Page): form_model = 'player' form_fields = ['guess'] class ResultsWaitPage(WaitPage): @staticmethod def after_all_players_arrive( group: Group, ): # not a great practice to have this much in pages but it felt easiest players = group.get_players() group.winning = round((sum([p.guess for p in players]) / len(players)) * 2 / 3, 3) winner = min([p.guess for p in players], key=lambda x: abs(x - group.winning)) for p in players: p.winner = True if p.guess == winner else False class Results(Page): @staticmethod def vars_for_template(player: Player): return {'mean': round(player.group.winning * (3 / 2), 3)} page_sequence = [Introduction, Main, ResultsWaitPage, Results]