from otree.api import * import random, pandas as pd import csv doc = """ Basic Newsvendor Game with margin type (high/low) within-subject (randomized) Author: Anugna Reddy Gondi Updated: 11-23-21 """ class Constants(BaseConstants): name_in_url = 'nv_game_bm' players_per_group = None # Number of rounds (change the value below) half are HM, half are LM num_rounds = 10 num_rounds_eachmarg = int(num_rounds / 2) # selling price (change the value below) price = 12 # cost hm-high margin lm-low margin (change the value below) hm_cost = 3 lm_cost = 9 # demand uniformly distributed[0, 300] (change the values below) demand_min = 0 demand_max = 300 # demand_realz = pd.read_csv('demand.csv').to_dict()['demand'] #to have the same series for everybody class Subsession(BaseSubsession): pass class Group(BaseGroup): pass class Player(BasePlayer): order_qty = models.IntegerField(min=0, label="Order Quantity:") test_order_qty = models.IntegerField(min=0, label="Test Order Quantity:") # demand realz demand_realization = models.IntegerField(min=Constants.demand_min, max=Constants.demand_max) # functions def creating_session(subsession): import itertools margin_types = itertools.cycle(['hm', 'lm']) if subsession.round_number == 1: for player in subsession.get_players(): participant = player.participant participant.margin_type = next(margin_types) def set_payoffs(player): if ((player.round_number <= Constants.num_rounds / 2) & (player.participant.margin_type == 'lm')) | (( player.round_number > Constants.num_rounds / 2) & (player.participant.margin_type == 'hm')): player.payoff = min(player.order_qty, player.demand_realization) * Constants.price - player.order_qty * Constants.lm_cost else: player.payoff = min(player.order_qty, player.demand_realization) * Constants.price - player.order_qty * Constants.hm_cost # def deam(player): # for i in list(range(0,301)): # player.potential_profits[i]=min(player.test_order_qty, i) * Constants.price - player.test_order_qty * player.participant.item_cost # return player.potential_profits # PAGES class FirstPage(Page): @staticmethod def is_displayed(player): return player.round_number == 1 class InstructionsLM(Page): @staticmethod def is_displayed(player): return ((player.round_number == 1) & (player.participant.margin_type == 'lm')) | (( player.round_number == 1 + (Constants.num_rounds / 2)) & (player.participant.margin_type == 'hm')) @staticmethod def vars_for_template(player): return {'round': player.round_number, 'price': Constants.price, 'cost': Constants.lm_cost, 'demand_min': Constants.demand_min, 'demand_max': Constants.demand_max} class InstructionsHM(Page): @staticmethod def is_displayed(player): return ((player.round_number == 1) & (player.participant.margin_type == 'hm')) | ( (player.round_number == 1 + (Constants.num_rounds / 2)) & (player.participant.margin_type == 'lm')) @staticmethod def vars_for_template(player): return {'round': player.round_number, 'price': Constants.price, 'cost': Constants.hm_cost, 'demand_min': Constants.demand_min, 'demand_max': Constants.demand_max} class RoundData(Page): form_model = 'player' form_fields = ['test_order_qty', 'order_qty', 'demand_realization'] @staticmethod def is_displayed(player): return player.round_number <= Constants.num_rounds @staticmethod def vars_for_template(player): if ((player.round_number <= Constants.num_rounds / 2) & (player.participant.margin_type == 'lm')) | (( player.round_number > Constants.num_rounds / 2) & (player.participant.margin_type == 'hm')): return {'round': player.round_number, 'price': Constants.price, 'cost': Constants.lm_cost, 'demand_min': Constants.demand_min, 'demand_max': Constants.demand_max} else: return {'round': player.round_number, 'price': Constants.price, 'cost': Constants.hm_cost, 'demand_min': Constants.demand_min, 'demand_max': Constants.demand_max} @staticmethod def js_vars(player): all_poss_dems = list(range(Constants.demand_min, Constants.demand_max + 1)) return dict( payoff=player.payoff, all_poss_dems=all_poss_dems, ) @staticmethod def before_next_page(player, timeout_happened): set_payoffs(player) # class ResultsWaitPage(WaitPage): # after_all_players_arrive = 'set_payoffs' class Results(Page): @staticmethod def vars_for_template(player): if ((player.round_number <= Constants.num_rounds / 2) & (player.participant.margin_type == 'lm')) | (( player.round_number > Constants.num_rounds / 2) & (player.participant.margin_type == 'hm')): return {'round': player.round_number, 'price': Constants.price, 'cost': Constants.lm_cost, 'demand_realized_round': player.demand_realization, 'qty_sold': min(player.order_qty, player.demand_realization) } else: return {'round': player.round_number, 'price': Constants.price, 'cost': Constants.hm_cost, 'demand_realized_round': player.demand_realization, 'qty_sold': min(player.order_qty, player.demand_realization) } page_sequence = [FirstPage, InstructionsLM, InstructionsHM, RoundData, Results]