from otree.api import Currency as c, currency_range from ._builtin import Page, WaitPage from .models import Constants, Subsession import random import math import time from django.utils.translation import ugettext from django.conf import settings from .models import BotPlayer class MyPage(WaitPage): pass class Setup(WaitPage): def after_all_players_arrive(self): botplayers = self.subsession.get_bot_players() group = self.group group.allowance_allocator() players = group.get_players() if self.round_number > 1: for p in players: p.money = p.in_round(self.round_number - 1).money for b in botplayers: b.money = self.subsession.get_bot_player_in_round(b.id_in_group, self.round_number - 1).money b.save() class AuctionBids(Page): def is_displayed(self): return self.session.config['percentage_of_allowances_allocated_by_auctions'] > 0 form_model = 'player' form_fields = Subsession.auction_form_generator(3) def vars_for_template(self): botplayers = self.subsession.get_bot_players() # Since the bots are a class that we've defined independently from the otree api, we need the manually pass the attributes from it to the templates botplayer_list = [] for b in botplayers: botplayer_dict = dict( id_in_group = b.id_in_group, money = b.money, allowances = b.allowances, emissions = b.emissions, demand_quantity = b.demand_quantity, supply_quantity = b.supply_quantity, demand_price = b.demand_price, supply_price = b.supply_price, ) botplayer_list.append(botplayer_dict) return dict( botplayer_list = botplayer_list, cap = int(self.session.config['emissions_cap']*100), percent_auctions = int(self.session.config['percentage_of_allowances_allocated_by_auctions']*100), percent_output_based = int(100 - self.session.config['percentage_of_allowances_allocated_by_auctions']*100), javascript_text_price = ugettext("Price £"), # Add all text that goes into any JavaScript here! javascript_text_period = ugettext("Allowances"), javascript_text_emissions = ugettext("Emissions(tC)") ) class AuctionResults(WaitPage): def after_all_players_arrive(self): botplayers = self.subsession.get_bot_players() for b in botplayers: b.auction_play() self.group.auction_mechanism() class Dashboard(Page): form_model = 'player' form_fields = ['demand_price','demand_quantity','supply_price','supply_quantity', 'invest'] def error_message(self, values): print('values is', values) if values['demand_quantity']*values['demand_price'] > self.player.money: return ugettext('You can make a bid that you do not have the money for!') def error_message(self, values): print('values is', values) if values['supply_price'] <= values['demand_price'] and values['supply_quantity'] > 0 and values['demand_quantity'] > 0: return ugettext('Your sell price must be higher than your buy price!') def error_message(self, values): # Enforces the price celing and floor for the supply side. print('values is', values) if ( ((values['supply_price'] < self.session.config['price_floor_level'] and self.session.config['price_floor'] == True) or (values['supply_price'] > self.session.config['price_ceiling_level'] and self.session.config['price_ceiling'] == True)) and values['supply_quantity'] > 0 ): return ugettext('You have made an illeagal supply bid. The price floor is £' + str(settings.SESSION_CONFIGS[0]['price_floor_level']) + ' and price ceiling £' + str(settings.SESSION_CONFIGS[0]['price_ceiling_level']) + '. Please make a bid within the legal interval.') def error_message(self, values): # Enforces the price celing and floor for the demand side. print('values is', values) if ( ((values['demand_price'] < self.session.config['price_floor_level'] and self.session.config['price_floor'] == True) or (values['demand_price'] > self.session.config['price_ceiling_level'] and self.session.config['price_ceiling'] == True)) and values['demand_quantity'] > 0 ): return ugettext('You have made an illeagal supply bid. The price floor is £' + str(settings.SESSION_CONFIGS[0]['price_floor_level']) + ' and price ceiling £' + str(settings.SESSION_CONFIGS[0]['price_ceiling_level']) + '. Please make a bid within the legal interval.') def before_next_page(self): self.player.time = time.time() def vars_for_template(self): botplayers = self.subsession.get_bot_players() # Since the bots are a class that we've defined independently from the otree api, we need the manually pass the attributes from it to the templates botplayer_list = [] for b in botplayers: botplayer_dict = dict( id_in_group = b.id_in_group, money = b.money, allowances = b.allowances, emissions = b.emissions, demand_quantity = b.demand_quantity, supply_quantity = b.supply_quantity, demand_price = b.demand_price, supply_price = b.supply_price, ) botplayer_list.append(botplayer_dict) return dict( botplayer_list = botplayer_list, cap = int(self.session.config['emissions_cap']*100), percent_auctions = int(self.session.config['percentage_of_allowances_allocated_by_auctions']*100), percent_output_based = int(100 - self.session.config['percentage_of_allowances_allocated_by_auctions']*100), javascript_text_price = ugettext("Price £"), # Add all text that goes into any JavaScript here! javascript_text_period = ugettext("Allowances"), javascript_text_emissions = ugettext("Emissions(tC)") ) class ResultsWaitPageMoreThanTwoPlayer(WaitPage): def after_all_players_arrive(self): group = self.group # Specifies which group we are referring to - only one exists in our particular case, but has to be done becuase of the way otree is constructed. players = group.get_players() # Creates a list with all players if Constants.num_bots > 0: botplayers = self.subsession.get_bot_players() for b in botplayers: b.trading_play() players = players + botplayers self.group.calculate_market_price() # Calculate the market price this periods self.group.execute_trades() # Executing trades according to that market price and saving the market price and volume traded # ABATEMENT TECHNOLOGY for p in players: # Deducts £400 for player who invested in abatement technology in the previous period. if p.invest == True and p.already_invested == False: p.money = p.money - 400 p.already_invested = True # To make sure we don't deduct money from player more than once. # GENERATING NEW EMISSIONS for p in players: p.emission_generator() # SAVING EMISSIONS INFORMTION FOR TEMPLATES group.save_emissions_information() #----------------------------------- group.current_trading_period += 1 # Keeps track of what trading period we are in. self.subsession.current_trading_period += 1 class PenaltyCalculation(WaitPage): def after_all_players_arrive(self): group = self.group players = self.group.get_players() allowance_deficit = 0 for p in players: p.participant.vars["allowances_at_the_end_of_round"].append(p.allowances) if p.allowances < p.emissions: # Checks if participant are in compliance, and if they're not it gives a penalty. allowance_deficit = p.emissions - p.allowances p.total_penalty = self.session.config['per_unit_penalty']*allowance_deficit p.money = p.money - p.total_penalty p.not_complying = True p.allowances = p.allowances - p.emissions if self.round_number > 1: self.session.vars["rounds"].append(self.round_number) # Need this list for making the dropdowns in the template. for p in players: p.participant_vars_dump = str(p.participant.vars) self.group.session_vars_dump = str(self.session.vars) class Results(Page): pass page_sequence = [Setup, AuctionBids, AuctionResults] for i in range(1, Constants.num_periods + 1): page_sequence.append(Dashboard) page_sequence.append(ResultsWaitPageMoreThanTwoPlayer) page_sequence.append(PenaltyCalculation) page_sequence.append(Results)