from otree.api import Currency as c, currency_range # To show currency from . import models # Contains my data structure and functions from ._builtin import Page, WaitPage # Necessary to build custom pages from .models import Constants, Bid # Constants is necessary. Bid is my own from datetime import datetime # To handle time properly import time # Why? import datetime # Why? import random # For 'risky' stuff #from pip._vendor.requests.sessions import session #from .utils import get_field_names_for_csv from collections import OrderedDict from django.http import JsonResponse from django.contrib.auth.decorators import login_required class WPstart(WaitPage): def after_all_players_arrive(self): for p in self.group.get_players(): p.private_value = int( self.session.config['min_private_value']*(100/self.session.config['point_worth_ct']) + random.random() * ( (self.session.config['max_private_value'] - self.session.config['min_private_value']) *(100/self.session.config['point_worth_ct']) ) ) class WP(WaitPage): def after_all_players_arrive(self): now = time.time() self.group.auctionstartdate = now #self.group.auctionenddate = now + Constants.starting_time class ResultsWP(WaitPage): def after_all_players_arrive(self): self.group.set_payoffs() #self.group.write_results_to_file() class InbetweenWP(WaitPage): def is_displayed(self): if all(p.second_stage_bid == False for p in self.group.get_players()): return False else: return True def after_all_players_arrive(self): if not all(p.second_stage_bid == False for p in self.group.get_players()): for pl in self.group.get_players(): pl.second_stage_bid = True for pl in self.group.get_players(): pl.second_stage_bid_amount = None class InstructionsPage(Page): def is_displayed(self): return self.round_number == 1 def vars_for_template(self): return { 'probability': Constants.bid_success_probability, 'low':int(self.session.config['min_private_value']*(100/self.session.config['point_worth_ct'])), 'high':int(self.session.config['max_private_value']*(100/self.session.config['point_worth_ct'])), } class Stage1(Page): timeout_seconds = Constants.timeout_seconds live_method = 'live_auction' def is_displayed(self): if all(p.second_stage_bid == False for p in self.group.get_players()): return False else: return True def vars_for_template(self): return { 'max_bid': self.player.highest_bid().amount, 'probability': Constants.bid_success_probability, 'low':int(self.session.config['min_private_value']*(100/self.session.config['point_worth_ct'])), 'high':int(self.session.config['max_private_value']*(100/self.session.config['point_worth_ct'])), } #def before_next_page(self): # self.player.second_stage_bid_amount = self.player.highest_bid().amount class Stage2(Page): def is_displayed(self): if all(p.second_stage_bid == False for p in self.group.get_players()): return False else: return True form_model = models.Player form_fields = ['second_stage_bid', 'second_stage_bid_amount'] def second_stage_bid_amount_max(self): return Constants.endowment def second_stage_bid_amount_min(self): return max(self.player.highest_bid().amount, self.group.second_price)+1 def vars_for_template(self): return { 'first_price': self.group.first_price, 'second_price': self.group.second_price, 'winner': self.group.curwinner, 'max_bid': self.player.highest_bid().amount, 'probability': Constants.bid_success_probability, 'low':int(self.session.config['min_private_value']*(100/self.session.config['point_worth_ct'])), 'high':int(self.session.config['max_private_value']*(100/self.session.config['point_worth_ct'])), } def before_next_page(self): if self.player.second_stage_bid == True: if not self.player.second_stage_bid_amount == None: # "Illegal" bids are prevented by formfield validation if random.random() <= Constants.bid_success_probability: Bid.objects.create( player=self.player, amount = self.player.second_stage_bid_amount, at_time = time.time() - self.group.auctionstartdate, in_stage = 2, success = 1, in_round = self.subsession.round_number, p_value = self.player.private_value ) else: Bid.objects.create( player=self.player, amount = self.player.second_stage_bid_amount, at_time = time.time() - self.group.auctionstartdate, in_stage = 2, success = 0, in_round = self.subsession.round_number, p_value = self.player.private_value ) # Ugly hack (conceptually), but it works # Resets only because of rng self.player.second_stage_bid = False # Sort players by their respective maximum bid and then the time they submitted it (in case of duplicates) sorted_players = sorted( self.group.get_players(), key=lambda player: (player.highest_bid().amount,-player.highest_bid().at_time), reverse = True) # Replace the prices self.group.first_price = sorted_players[0].highest_bid().amount self.group.second_price = sorted_players[1].highest_bid().amount # Set winner self.group.curwinner = sorted_players[0].id_in_group #print('winner: ', mygroup.curwinner) else: print('Player submitted last bid empty') class Results(Page): pass class ResultsSummary(Page): def is_displayed(self): return self.round_number == Constants.num_rounds def vars_for_template(self): return { 'total_payoff': sum([p.payoff for p in self.player.in_all_rounds()]), 'paying_round': self.session.vars['paying_round'] } page_sequence = [ WPstart, InstructionsPage, WP, Stage1, Stage2, InbetweenWP, Stage1, Stage2, InbetweenWP, Stage1, Stage2, InbetweenWP, Stage1, Stage2, InbetweenWP, Stage1, Stage2, InbetweenWP, Stage1, Stage2, InbetweenWP, ResultsWP, Results, #ResultsSummary ]