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 = 'beautycontestincompleteVHB' 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 ''' #in this method we want to determine which players are the winners of the complete contest over all rounds #it can be one winner, or there could be several winners def determine_total_winners(group: Group): ## Determine the maximum winnings for all rounds maximum = 0 for player in group.get_players(): #determine for all players how many rounds each player has won #assign the highest number of won rounds by a player to the variable maximum ### Now we want to check who the winners are amount_winner = 0 for player in group.get_players(): player_winnings = sum([p.is_winner for p in player.in_all_rounds()]) #this gives you the number of times a player won a round in the complete contest #set player.is_overall_winner to True is the particular player has won the most rounds #increase the number of winners by 1 group.num_overall_winners = amount_winner class Player(BasePlayer): ''' a player in our experiment needs a guess: is an integer, and between 0 and our GUESS_MAX from the constant is_winner: is a yes or no choice, so you can store it as a boolean is_overall_winner: is a yes or no choice, if player one the overall contest, also a boolean ''' guess = models.IntegerField( min=0, max=C.GUESS_MAX, label="Please pick a number from 0 to 100:" ) # PAGES class Introduction(Page): @staticmethod def is_displayed(player): ### should only be displayed in the first round class Guess(Page): #here you need to pass on the player guess variable so that users can enter their number 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): @staticmethod def vars_for_template(player:Player): return dict( example_entry = 'dies ist ein beispiel', ## add more entries comma seperated as shown in example_entry to use them in the template ResultRounds.html ##group average should store the calculated average number of the group, target_value the calculated target value and diff ##the difference between the single number of the player and the target value ##use round(,2) to round each variable to 2 decimal places group_average = target_value = diff = ) class TotalResultsWaitPage(WaitPage): body_text = 'Please wait until the final results will be displayed to you' @staticmethod def is_displayed(player): ## 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): ## Show only in the last round @staticmethod def vars_for_template(player): return dict( '''retrieve from your player variables if the player is one of the winners of the contest and store the information in overall_winner below retrieve from your group variables the number of winners of the contest and store the information in num_winners below ##in only_one_winner store if there is only one player who one the contest or several''' overall_winner= num_winners= only_one_winner= ) page_sequence = [Introduction,StandardWaitPage,Guess,ResultsWaitPage,ResultRounds,TotalResultsWaitPage,Results]