from otree.api import * doc = """ Keynesian beauty ocntest (https://en.wikipedia.org/wiki/Keynesian_beauty_contest) All players guess a number, whoever is closest to 2/3 of the average wins """ ## Constant Variables ; They don't change over the course of the experiment class C(BaseConstants): NAME_IN_URL = 'beautycontestVHB' PLAYERS_PER_GROUP = None NUM_ROUNDS = 3 GUESS_MAX = 100 PRIZE = cu(10) ## For this experiment it's empty ## You can use here variables and methods that are on a higher scope than group or player level class Subsession(BaseSubsession): pass ## Store here the variables and methods of the group class Group(BaseGroup): group_average = models.FloatField() ## Average are most likely not whole numbers target_value = models.FloatField() ## 2/3 of group average best_guess = models.FloatField() ## Just a option to save the best/nearest guess num_winners = models.IntegerField() ## how many winners are in the current round num_overall_winners = models.IntegerField() ##how many winners in the whole contest (over all rounds) ## your task, calculate the payoff for each group ## the group : Group says that whenever you use group inside this method your IDE (e.g PyCharm) knows ## it is an Group object and gives you autocomplete with methods & fields of the group def set_payoffs(group: Group): players = group.get_players() ## list of all players ''' 1) Calculate the average of all received guesses save it in group.group_average 2) Calculate the two third of this save it in the corresponding group variable 3) Calculate the best guess (see hints or ask if stuck) save it in the corresponding group variable 4) for all players that have the best guess give them the tag of is_winner and determine how many players had the best guess. Save it in the corresponding group variable ''' ''' HINTS: min is a method to get the minimum from a list of numbers min(5,2,9,20,1) = 1 min(myguess,yourguess) = the smallest --- list() or [] is an empty list- you can add players to this and store them: .add(player) e.g old_player = [player1, player5] with len(old_player) you get the amount of people you classified as old ''' '''LÖSCHEN AB HIER FÜRS INCOMPLETE''' guesses = [p.guess for p in players] group.group_average = sum(guesses) / len(players) two_thirds_avg = (2 / 3) * group.group_average group.target_value = round(two_thirds_avg, 2) group.best_guess = min(guesses, key=lambda guess: abs(guess - group.target_value)) winners = [p for p in players if p.guess == group.best_guess] group.num_winners = len(winners) for p in winners: p.is_winner = True ''' delta_ = 1000 ind = 0 for i,player in enumerate(players): delta_ = min(delta_, abs(player.guess - group.target_value)) if delta_ == abs(player.guess - group.target_value): ind = i group.best_guess = guesses[i] ''' ''' Löschen bis hier''' def determine_total_winners(group: Group): ## Determine the maximum winnings for all rounds maximum = 0 for player in group.get_players(): player_winnings = sum([p.is_winner for p in player.in_all_rounds()]) if player_winnings > maximum: maximum = player_winnings ### Now we want to check for all winners amount_winner = 0 for player in group.get_players(): player_winnings = sum([p.is_winner for p in player.in_all_rounds()]) if player_winnings==maximum: player.is_overall_winner = True player.payoff = 1 amount_winner += 1 group.num_overall_winners = amount_winner class Player(BasePlayer): guess = models.IntegerField( min=0, max=C.GUESS_MAX, label="Please pick a number from 0 to 100:" ) is_winner = models.BooleanField(initial=False) is_overall_winner = models.BooleanField(initial=False) ''' bis hierhin ''' # PAGES class Introduction(Page): @staticmethod def is_displayed(player:Player): ### only in the first round return player.round_number == 1 class Guess(Page): form_model = 'player' ## we use the player variables here form_fields = ['guess'] ## this one you created above class StandardWaitPage(WaitPage): body_text = "Please wait for the other contestants" class ResultsWaitPage(WaitPage): body_text = "Please wait for the other contestants" @staticmethod def after_all_players_arrive(group): ### use your payoff calculation here ## delete for incomplete set_payoffs(group) class ResultRounds(Page): ''' Please name the 3 Variables for the ResultRounds.html as followed , otherwise the page will not work: 'group_average' 'target_value' 'diff' use round(,2) to round it to 2 decimalpoints. ''' @staticmethod def vars_for_template(player): return dict( example_entry = 'dies ist ein beispiel', ## add more entries comma seperated as above to use them in the template (look into ResultRounds.html) group_average = player.group.group_average, target_value = player.group.target_value, diff = abs(player.group.target_value - player.guess) ) class TotalResultsWaitPage(WaitPage): body_text = 'Please wait until the final results will be displayed to you' @staticmethod def is_displayed(player): return player.round_number == C.NUM_ROUNDS ## Show only in the last round @staticmethod def after_all_players_arrive(group): determine_total_winners(group) class Results(Page): @staticmethod def is_displayed(player): return player.round_number == C.NUM_ROUNDS ## Show only in the last round @staticmethod def vars_for_template(player): return dict( overall_winner=player.is_overall_winner, num_winners=player.group.num_overall_winners, only_one_winner=player.group.num_overall_winners == 1 ) page_sequence = [Introduction,StandardWaitPage,Guess,ResultsWaitPage,ResultRounds,TotalResultsWaitPage,Results]