from otree.api import Currency as c, currency_range from ._builtin import Page, WaitPage from .models import Constants import random import logging # pylint: disable=no-member logger = logging.getLogger(__name__) def vars_for_all_templates(self): return{ 'market_item_1': self.session.config['market_item_1'], 'market_item 2': self.session.config['market_item_2'], 'market_item_3' : self.session.config['market_item_3'], 'market_item_4' : self.session.config['market_item_4'], 'price': self.player.price, 'number_of_players': len(self.group.get_players()) } class Introduction(Page): timeout_seconds = 45 def is_displayed(self): if(self.subsession.round_number == 1): template_name = 'free_entry_exit/Introduction.html' return True else: return False class Decide(Page): logger = logging.getLogger(__name__) timeout_seconds = 60 form_model = 'player' form_fields = ['market_choice'] template_name = 'free_entry_exit/Decide.html' def before_next_page(self): # Test for negative profits in all rounds but the first round # should the last rounds profit be positive, we'll stay in our current market # If it was negative we'll select a new market, which is a semi random choice # If no one was in a market last round that market is added to the mix of markets # to choose from, else, if all markets had at least one player in them we'll choose # at random, any market that had a positive profit. if self.timeout_happened: if self.round_number != 1: logger.info(F'Going into best response, {self.player.id_in_group} previous market was: {self.player.in_round(self.round_number -1).market_choice}') # Had this happen twice now so I'm working around it, players returned None (null) after hitting best response: if self.player.in_round(self.round_number - 1).market_choice == '': logger.error(f'NO MARKET LAST ROUND SETTING NEW MARKET>>>') self.player.market_choice = self.group.random_market_choice() logger.info(f"NEW MARKET == {self.player.market_choice}") self.player.market_choice # Also had few instances where the profit was not set on a player, hoping to avoid that here: # FIXME: Although this doesn't set the profit for the player, it does avoid an error... elif self.player.in_round(self.round_number - 1).profit == None: logger.error(f'NO POFIT LAST ROUND') self.player.in_round(self.round_number - 1) == self.group.in_round(self.round_number - 1).highest_profit elif self.group.is_negative(self.player.in_round(self.round_number - 1).profit) == True: self.player.market_choice = self.player.in_round(self.round_number - 1).market_choice logger.info(f'Positive profit last round, keeping market {self.player.market_choice}, prev market: {self.player.in_round(self.round_number - 1).market_choice}') # Give bots a 50% chance of swapping markets if they made a negative profit: # selected a number 1-10: if even, swap markets, if odd, stay in their previous market. elif self.group.is_negative(self.player.in_round(self.round_number - 1).profit) == False: if self.group.change_market_chance() == 0: logger.info(f'Player {self.player.id_in_group} was chosen to change markets') self.player.market_choice = self.group.best_response() else: logger.info(f'Player {self.player.id_in_group} was chosen to stay in previous market') self.player.market_choice = self.player.in_round(self.round_number - 1).market_choice #print("Best response was: ", self.player.market_choice) else: self.player.market_choice = self.group.random_market_choice() logger.info(F"Player {self.player.id_in_group} has chosen {self.player.market_choice} for round: {self.round_number}") class ResultsWaitPage(WaitPage): body_text = 'Waiting for other players to decide...' def after_all_players_arrive(self): self.group.set_markets() self.group.set_base_price() self.group.set_price_per_player() self.group.set_payoff() self.group.set_profit_per_player() #self.group.set_vars_for_best_response() # migrated code to Set_payoff function class Results(Page): def vars_for_template(self): return { 'corn': self.group.total_corn, 'corn_price': self.group.corn_price, 'corn_profit': self.group.corn_profit, 'wheat': self.group.total_wheat, 'wheat_price': self.group.wheat_price, 'wheat_profit': self.group.wheat_profit, 'soybean': self.group.total_soybean, 'soybean_price': self.group.soybean_price, 'soybean_profit': self.group.soybean_profit, 'rice': self.group.total_rice, 'rice_price': self.group.rice_price, 'rice_profit': self.group.rice_profit } timeout_seconds = 15 template_name = 'free_entry_exit/Results.html' class FinalResults(Page): template_name = 'free_entry_exit/FinalResults.html' def is_displayed(self): return self.subsession.round_number == Constants.num_rounds def vars_for_template(self): group = self.group player_data = [] corn_profit = [g.corn_profit for g in group.in_all_rounds()] player_data.append({ 'name':'Corn Profit', 'data':corn_profit }) wheat_profit = [g.wheat_profit for g in group.in_all_rounds()] player_data.append({ 'name':'Wheat Profit', 'data':wheat_profit }) rice_profit = [g.rice_profit for g in group.in_all_rounds()] player_data.append({ 'name':'Rice Profit', 'data':rice_profit }) soybean_profit = [g.soybean_profit for g in group.in_all_rounds()] player_data.append({ 'name':'Soybean Profit', 'data':soybean_profit }) return { 'units': player_data, 'categories': list(range(1, Constants.num_rounds, 1)) } page_sequence = [ Introduction, Decide, ResultsWaitPage, Results, FinalResults, ]