from otree.api import ( models, widgets, BaseConstants, BaseSubsession, BaseGroup, BasePlayer, Currency as c, currency_range, Page, WaitPage, ) import random # need to do this every time to tell Pycharm I'll use this package doc = """ This is a 2nd Price Auction - Assignment #3 """ class Constants(BaseConstants): name_in_url = 'my_2_bid' players_per_group = 3 num_rounds = 4 timeout_seconds = 60 class Subsession(BaseSubsession): pass class Group(BaseGroup): highest_bid = models.CurrencyField() second_highest_bid = models.CurrencyField() winner = models.IntegerField() class Player(BasePlayer): value = models.CurrencyField() bid = models.CurrencyField() is_winner = models.BooleanField() # Functions def creating_session(subsession): print('in creating session') # Establish a total earnings variable for each participant and initialize to 0 at beginning of session for p in subsession.get_players(): p.value = random.random()*100 p.is_winner = False if subsession.round_number == 1: p.participant.vars['totalEarnings'] = 0 # Varying groups for half of sessions #for g in subsession.get_groups(): # print('round', subsession.round_number) # if subsession.round_number == 3: # subsession.group_randomly() if subsession.round_number == 1 or subsession.round_number == 3: subsession.group_randomly() else: subsession.group_like_round(subsession.round_number - 1) # group like prior round def auction_outcome(g: Group): # Get the set of players in the group players = g.get_players() # Get the set of bids from the players bids = [p.bid for p in players] # square brackets make a list # Sort the bids in descending order bids.sort(reverse=True) # Set the highest and second highest bids to the appropriate group variables g.highest_bid = bids[0] # 0 is the first number in a list in Python g.second_highest_bid = bids[1] # Tie break # We always do this even though there is not a tie # first get the set of player IDs who bid the highest highest_bidders = [p.id_in_group for p in players if p.bid == g.highest_bid] # Next randomly select one of these players IDs to the winner g.winner = random.choice(highest_bidders) # Finally get the player model of the winning bidder and flag as winner winning_player = g.get_player_by_id(g.winner) winning_player.is_winner = True # Set payoffs for each round for p in players: if p.is_winner: p.payoff = p.value - g.second_highest_bid else: p.payoff = 0 # PAGES class Intro(Page): def is_displayed(player): return player.round_number == 1 class Bid_page(Page): form_model = 'player' form_fields = ['bid'] # list of one element, could have more elements such as price and quantity @staticmethod def get_timeout_seconds(player): return Constants.timeout_seconds # in seconds @staticmethod def before_next_page(player, timeout_happened): if timeout_happened: player.bid = random.random*player.value class ResultsWaitPage(WaitPage): after_all_players_arrive = 'auction_outcome' body_text = "Please wait for everyone to submit their bids." class Regroup(Page): def is_displayed(player): return player.round_number == 3 class Results(Page): pass class End_page(Page): def is_displayed(player): return player.round_number == 4 page_sequence = [Intro, Regroup, Bid_page, ResultsWaitPage, Results, End_page]