from otree.api import * class C(BaseConstants): NAME_IN_URL = 'gsp_auction' PLAYERS_PER_GROUP = None NUM_ROUNDS = 8 BID_MIN = cu(0) BID_MAX = cu(10) ENDOWMENT = cu(10) class Subsession(BaseSubsession): pass class Group(BaseGroup): highest_bid = models.CurrencyField() second_highest_bid = models.CurrencyField() random_player_id = models.IntegerField() class Player(BasePlayer): bid_amount = models.CurrencyField( min=C.BID_MIN, max=C.BID_MAX, doc="""Amount bidded by the player""", label="Bid amount", ) is_winner = models.BooleanField( initial=False, doc="""Indicates whether the player is the winner""" ) # Add a field for private valuation private_value = models.CurrencyField() def get_custom_identifier(self): return f"Player {self.participant.id_in_session}" # FUNCTIONS def creating_session(subsession: Subsession): for g in subsession.get_groups(): item_value = random.uniform(C.BID_MIN, C.BID_MAX) g.item_value = round(item_value, 1) random_player_id = random.randint(1,3) # use in Bid.html sheet when want to assign privileged info randomly g.random_player_id = round(random_player_id) # Assign random private valuations to each player for player in g.get_players(): player.private_value = random.uniform(C.BID_MIN, C.BID_MAX) def set_winner(group: Group): players = group.get_players() group.highest_bid = max([p.bid_amount for p in players]) sorted_bids = sorted([p.bid_amount for p in players], reverse=True) # Set second-highest bid group.second_highest_bid = sorted_bids[1] # if len(sorted_bids) > 1 else None # Sort players by their bid amounts in descending order players_sorted_by_bid = sorted(players, key=lambda x: x.bid_amount, reverse=True) for i, player in enumerate(players_sorted_by_bid): if i == 0: player.is_winner = True player.payoff = player.private_value - group.second_highest_bid if len(sorted_bids) > 1 else 0 else: player.is_winner = False player.payoff = 0 def set_payoff(player: Player): # GSP payment has already been set in set_winner pass # PAGES # models.py import random class Introduction(Page): @staticmethod def before_next_page(player: Player, timeout_happened): # Assign a random private valuation to each player player.private_value = random.uniform(C.BID_MIN, C.BID_MAX) @staticmethod def vars_for_template(group): random_player_id = random.randint(1,3) return dict(random_player_id=random_player_id) class Bid(Page): form_model = 'player' form_fields = ['bid_amount'] class ResultsWaitPage(WaitPage): after_all_players_arrive = set_winner class Results(Page): pass page_sequence = [Introduction, Bid, ResultsWaitPage, Results]