from otree.api import ( models, widgets, BaseConstants, BaseSubsession, BaseGroup, BasePlayer, Currency as c, currency_range ) import random from django import forms import time import datetime from otree.db.models import Model, ForeignKey author = 'Filipp Chapkovskii, UZH, chapkovski@gmail.com' doc = """ Amazon-like auction. Bidding time is extended after each bid. """ class Constants(BaseConstants): instructions_template = 'AuctionAmazon08All/Instructions.html' name_in_url = 'AuctionAmazon08All' players_per_group = None num_rounds = 1 # starting_time = 30 # extra_time = 20 timeout_seconds = 60 endowment = 100 prize = 100 bid_success_probability = 0.8 class Subsession(BaseSubsession): def before_session_starts(self): # Group randomly with fixed IDs self.group_randomly(fixed_id_in_group=True) # There will be a single paying round if self.round_number == 1: paying_round = random.randint(1, Constants.num_rounds) self.session.vars['paying_round'] = 1 #paying_round #this is set for all apps! # Set start time / Not necessary, only for logs for g in self.get_groups(): g.first_price = 0 g.second_price = 0 g.auctionstartdate = time.time() # Add one bid to each player, otherwise error on first screen for player in self.get_players(): _ = player.bid_set.create() _.save() def vars_for_admin_report(self): # Randomly select a group for each round # Then look up the players in that group, # and return their IDs, Codenames and Payoffs selected_groups = [] for r in range(0,Constants.num_rounds): selected_groups.append(random.choice(self.get_group_matrix())) selected_players = [] for round in range(0, Constants.num_rounds): players_and_payoffs = [] for player in selected_groups[round]: # selected_groups[round] is a list of players players_and_payoffs.append(player.in_round(round+1).participant.label) players_and_payoffs.append(player.in_round(round+1).preliminary_payoff) selected_players.append(players_and_payoffs) return {'selected_players': selected_players} class Group(BaseGroup): first_price = models.IntegerField(initial=0) second_price = models.IntegerField(initial=0) auctionstartdate = models.FloatField() #auctionenddate = models.FloatField() curwinner = models.IntegerField() curstage = models.IntegerField(initial=1) # def time_left(self): # now = time.time() # time_left = self.auctionenddate - now # time_left = round(time_left) if time_left > 0 else 0 # return time_left def set_payoffs(self): for p in self.get_players(): if str(self.curwinner) == str(p.id_in_group): p.preliminary_payoff = p.private_value - self.second_price else: p.preliminary_payoff = 0 if (self.round_number == self.session.vars['paying_round']): p.payoff = p.preliminary_payoff else: p.payoff = 0 def write_results_to_file(self): players = '' for p in self.get_players(): players += str(p.participant.id_in_session) players += 'vs' players = players[:-2] #Cuts off last 'vs' with open('Amazon_All_started_' + str(time.strftime('%m_%d_%H_%M_%S',time.localtime(self.auctionstartdate))) + '_played_by_' + players + 'round_' + str(self.round_number) + '.txt','w') as f: # First write down the winner f.write("The participants payoffs are:" + '\n') for p in self.get_players(): f.write("Participant_" + str(p.participant.id_in_session) + ': ' + str(p.preliminary_payoff) + '\n'+ '\n'+ '\n') # Now write down all bids f.write("The participants bids are:" + '\n') for p in self.get_players(): bid_qs = Bid.objects.filter(player__exact=p) for bid in bid_qs: f.write(str(bid) + '\n') f.closed class Player(BasePlayer): #max_bid = models.IntegerField(initial=0) #bid_submitted_time = models.FloatField() private_value = models.IntegerField() proceed = models.IntegerField(initial = 0) preliminary_payoff = models.IntegerField(initial = 0) second_stage_bid = models.BooleanField() second_stage_bid_amount = models.IntegerField(blank = True) def last_bid(self): sorted_bids = sorted( self.bid_set.all(), key=lambda bid: bid.at_time, reverse = True) sorted_successful_bids = [bid for bid in sorted_bids if bid.success==1] return sorted_successful_bids[0] def highest_bid(self): sorted_bids = sorted( self.bid_set.all(), key=lambda bid: bid.amount, reverse = True) sorted_successful_bids = [bid for bid in sorted_bids if bid.success==1] return sorted_successful_bids[0] class Bid(Model): mode = models.IntegerField(initial=2) amount = models.IntegerField(initial=0) at_time = models.FloatField(initial=0) in_stage = models.IntegerField(initial=0) success = models.IntegerField(initial=1) in_round = models.IntegerField(initial=0) p_value = models.IntegerField(initial=0) player = ForeignKey(Player) # creates 1:m relation -> this bid was submitted by a certain player def __str__(self): bidstr = "Round " + str(self.player.subsession.round_number) + '\n' bidstr += "Group " + str(self.player.subsession.round_number) + '\n' bidstr += "Player " + str(self.player.id_in_group) + '\n' bidstr += "Value " + str(self.player.private_value) + '\n' bidstr += "Stage " + str(self.in_stage) + '\n' bidstr += "Time " + str(self.at_time) + '\n' bidstr += "Success " + str(self.success) + '\n' bidstr += "Amount " + str(self.amount) + '\n' return bidstr