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 { 'num_others': len(self.group.get_players())-1, '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 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 { 'num_others': len(self.group.get_players())-1, '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 { 'num_others': len(self.group.get_players())-1, '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 new_bid = self.player.bid_set.create() new_bid.amount = self.player.second_stage_bid_amount new_bid.at_time = time.time() - self.group.auctionstartdate new_bid.in_stage = 2 if random.random() <= Constants.bid_success_probability: new_bid.success = 1 else: new_bid.success = 0 self.player.second_stage_bid = False new_bid.in_round = self.player.subsession.round_number new_bid.p_value = self.player.private_value new_bid.save() if new_bid.amount <= self.group.second_price: message_for_player = 'Your new bid must exceed the current selling price.' else: print('Bid is relevant') # 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) message_for_player = 'Your bid was submitted successfully.' self.group.save() 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 ]