from otree.api import Currency as c, currency_range from ._builtin import Page, WaitPage from .models import Constants from scipy.stats import norm import datetime class Intro(Page): def is_displayed(player): return player.round_number == 1 def vars_for_template(self): if self.player.id_in_group == 1: role = 1 else: role = 2 return { 'role': role, } class P1_pf(Page): form_model = 'group' form_fields = ['point_forecast'] def is_displayed(self): return self.player.id_in_group == 1 def vars_for_template(self): y1 = Constants.historical_demand[:] y2 = Constants.historical_demand[:] group = self.group.in_previous_rounds() new_round_num_minus = self.group.new_round_number - 1 if self.player.round_number == 1: last_demand = Constants.historical_demand[49] else: last_demand = Constants.realized_demand[self.group.round_number-2] for p in group: y1.append(p.demand) round_operator = self.round_number while round_operator <= 15: round_operator = round_operator + 1 y1.append(None) y2.reverse() group.reverse() new_round_number = self.group.round_number + 49 next_period = new_round_number+1 return { 'highchart_series1': y1, 'groups_in_previous_rounds': group,'demand_series': y2, 'last_demand': last_demand, 'new_round_num_minus': new_round_num_minus, 'period': new_round_number, 'next_period': next_period, } class P1_df(Page): form_model = 'group' form_fields = ['distribution_forecast'] def is_displayed(self): return self.player.id_in_group == 1 def vars_for_template(self): y1 = Constants.historical_demand[:] y2 = Constants.historical_demand[:] group = self.group.in_previous_rounds() new_round_num_minus = self.group.new_round_number - 1 if self.player.round_number == 1: last_demand = Constants.historical_demand[49] else: last_demand = Constants.realized_demand[self.group.round_number-2] for p in group: y1.append(p.demand) round_operator = self.round_number while round_operator <= 15: round_operator = round_operator + 1 y1.append(None) y2.reverse() group.reverse() new_round_number = self.group.round_number + 49 next_period = new_round_number+1 point_forecast = self.group.point_forecast return { 'highchart_series1': y1, 'groups_in_previous_rounds': group, 'demand_series': y2, 'last_demand': last_demand, 'new_round_num_minus': new_round_num_minus, 'period': new_round_number, 'next_period': next_period, 'point_forecast':point_forecast, } def before_next_page(self): self.group.upper_bound = 2*self.group.point_forecast - self.group.distribution_forecast class WaitforP1(WaitPage): pass class P2(Page): form_model = 'group' form_fields = ['service_level'] def is_displayed(self): return self.player.id_in_group == 2 def vars_for_template(self): y1 = Constants.historical_demand[:] y2 = Constants.historical_demand[:] point_forecast = self.group.point_forecast distribution_forecast = self.group.distribution_forecast group = self.group.in_previous_rounds() upper_bound = self.group.upper_bound new_round_number = self.group.round_number + 49 new_round_num_minus = self.group.new_round_number - 1 if self.player.round_number == 1: last_demand = Constants.historical_demand[49] else: last_demand = Constants.realized_demand[self.group.round_number-2] for p in group: y1.append(p.demand) round_operator = self.round_number while round_operator <= 15: round_operator = round_operator + 1 y1.append(None) y2.reverse() group.reverse() new_round_number = self.group.round_number + 49 next_period = new_round_number+1 return { 'highchart_series1': y1, 'groups_in_previous_rounds': group, 'demand_series': y2, 'last_demand': last_demand, 'point_forecast': point_forecast, 'distribution_forecast': distribution_forecast, 'upper_bound': upper_bound, 'new_round_num_minus': new_round_num_minus, 'period': new_round_number, 'next_period': next_period, } class WaitforP2(WaitPage): def calculation(self): self.group.demand = Constants.realized_demand[self.group.round_number-1] self.group.standard_deviation = (self.group.point_forecast-self.group.distribution_forecast)/norm.ppf(0.95) self.group.order_quantity = round(self.group.point_forecast + norm.ppf(self.group.service_level/100, loc=0, scale=1)*self.group.standard_deviation) if self.group.order_quantity >= self.group.demand: self.group.mismatch_cost = Constants.overage_cost*(self.group.order_quantity-self.group.demand) else: self.group.mismatch_cost = Constants.underage_cost*(self.group.demand-self.group.order_quantity) self.group.profit = 139 - 0.04*self.group.mismatch_cost after_all_players_arrive = calculation class Results(Page): def vars_for_template(self): point_forecast = self.group.point_forecast distribution_forecast = self.group.distribution_forecast service_level = self.group.service_level mismatch_cost = self.group.mismatch_cost order_quantity = round(self.group.order_quantity) standard_deviation = self.group.standard_deviation demand = self.group.demand new_round_number = self.group.round_number + 49 next_period = new_round_number+1 upper_bound = self.group.upper_bound group_profit = round(139 - 0.04 * self.group.mismatch_cost, 2) y1 = Constants.historical_demand[:] y2 = Constants.historical_demand[:] group = self.group.in_previous_rounds() if self.player.round_number == 1: last_demand = Constants.historical_demand[49] else: last_demand = Constants.realized_demand[self.group.round_number-2] for p in group: y1.append(p.demand) round_operator = self.round_number while round_operator <= 15: round_operator = round_operator + 1 y1.append(None) y2.reverse() group.reverse() total_bonus = 5 for p in group: total_bonus = total_bonus + p.profit*0.01 total_bonus = total_bonus + self.group.profit*0.01 total_bonus = round(total_bonus,2) self.participant.payoff = total_bonus if self.round_number == Constants.num_rounds: if total_bonus < 11: self.participant.payoff = 11 total_bonus = 11 return { 'mismatch_cost': mismatch_cost, 'point_forecast':point_forecast, 'distribution_forecast': distribution_forecast, 'service_level': service_level, 'order_quantity': order_quantity, 'standard_deviation':standard_deviation, 'demand':demand, 'period': new_round_number, 'next_period': next_period, 'upper_bound': upper_bound, 'profit': group_profit, 'highchart_series1': y1, 'groups_in_previous_rounds': group, 'demand_series': y2, 'bonus': total_bonus, } page_sequence = [ Intro, P1_pf, P1_df, WaitforP1, P2, WaitforP2, Results ]