from otree.api import * c = cu doc = '' class C(BaseConstants): NAME_IN_URL = 'practice_change' PLAYERS_PER_GROUP = None NUM_ROUNDS = 3 PRACTICE_MEANS = (80, 100, 120) PRACTICE_SDS = (20, 40, 40) PRACTICE_IMAGES = ('PR1.png', 'PR2.png', 'PR3.png') PRACTICE_DEMAND = (98, 151, 115) PRACTICE_CF = (10, 8, 15) class Subsession(BaseSubsession): pass def creating_session(subsession: Subsession): import random for player in subsession.get_players(): if subsession.round_number == 1: scenario_order = list(range(1, C.NUM_ROUNDS + 1)) random.shuffle(scenario_order) player.participant.vars['machine_scenario_order'] = scenario_order class Group(BaseGroup): pass class Player(BasePlayer): practice_choice = models.StringField(choices=[['Keep current quantity', 'Keep current quantity'], ['Change quantity', 'Change quantity']], widget=widgets.RadioSelect) practice_scenario_id = models.IntegerField() practice_updated_mean = models.IntegerField() practice_updated_sd = models.IntegerField() practice_final_qty = models.IntegerField() Student_status = models.BooleanField(choices=[[True, 'Yes'], [False, 'No']], label='Are you currently a graduate student studying supply chain management or another related field? ') gender = models.StringField(label='If comfortable, please provide your gender below:') Age = models.StringField(label='If comfortable, please provide your age below: ') Consent = models.BooleanField(choices=[[True, 'Yes'], [False, 'No']], label='Do you consent to participating in this study? ') practice_initial_q1 = models.IntegerField(label='How much would you like to order of product 1? ', max=1000, min=0) practice_initial_q2 = models.IntegerField(label='How much would you like to order of product 2? ', max=1000, min=0) practice_initial_q3 = models.IntegerField(label='How much would you like to order of product 3? ', max=1000, min=0) practice_new_qty = models.IntegerField(blank=True) practice_updated_cf = models.IntegerField() class Consent(Page): form_model = 'player' form_fields = ['Student_status', 'gender', 'Age', 'Consent'] @staticmethod def is_displayed(player: Player): return player.round_number == 1 class NoConsent(Page): form_model = 'player' @staticmethod def is_displayed(player: Player): return player.round_number == 1 and player.Consent == False class PracticeInitialOrder(Page): form_model = 'player' form_fields = ['practice_initial_q1', 'practice_initial_q2', 'practice_initial_q3'] @staticmethod def is_displayed(player: Player): return player.round_number == 1 class PracticeDecision(Page): form_model = 'player' form_fields = ['practice_choice', 'practice_new_qty'] @staticmethod def vars_for_template(player: Player): idx = player.round_number - 1 initial_player = player.in_round(1) prior_quantities = [ initial_player.practice_initial_q1, initial_player.practice_initial_q2, initial_player.practice_initial_q3, ] prior_quantity = prior_quantities[idx] return dict( practice_product_number=player.round_number, updated_mean=C.PRACTICE_MEANS[idx], updated_sd=C.PRACTICE_SDS[idx], updated_cf=C.PRACTICE_CF[idx], scenario_image_path='Distributions/' + C.PRACTICE_IMAGES[idx], prior_quantity=prior_quantity, ) @staticmethod def before_next_page(player: Player, timeout_happened): idx = player.round_number - 1 player.practice_scenario_id = player.round_number player.practice_updated_mean = C.PRACTICE_MEANS[idx] player.practice_updated_sd = C.PRACTICE_SDS[idx] player.practice_updated_cf = C.PRACTICE_CF[idx] initial_player = player.in_round(1) prior_quantities = [ initial_player.practice_initial_q1, initial_player.practice_initial_q2, initial_player.practice_initial_q3, ] prior_quantity = prior_quantities[idx] if player.practice_choice == "Keep current quantity": player.practice_final_qty = prior_quantity else: player.practice_final_qty = player.practice_new_qty @staticmethod def error_message(player: Player, values): if values["practice_choice"] == "Change quantity" and values["practice_new_qty"] is None: return "Please enter a new quantity if you choose to change the current order." if values["practice_choice"] == "Keep current quantity" and values["practice_new_qty"] is not None: return "Please leave the new quantity box blank if you choose to keep the current order quantity." class PracticeComplete(Page): form_model = 'player' @staticmethod def is_displayed(player: Player): return player.round_number == C.NUM_ROUNDS @staticmethod def vars_for_template(player: Player): initial_player = player.in_round(1) initial_quantities = [ initial_player.practice_initial_q1, initial_player.practice_initial_q2, initial_player.practice_initial_q3, ] practice_results = [] practice_total_profit = 0 for p in player.in_all_rounds(): scenario_id = p.practice_scenario_id idx = scenario_id - 1 initial_quantity = initial_quantities[idx] final_quantity = p.practice_final_qty demand = C.PRACTICE_DEMAND[idx] sales = min(demand, final_quantity) leftover = max(0, final_quantity - demand) if p.practice_choice == "Keep current quantity": change_fee_paid = 0 else: change_fee_paid = p.practice_updated_cf profit = (sales * 15) - (final_quantity * 3.5) - change_fee_paid practice_total_profit += profit practice_results.append({ "scenario_id": scenario_id, "initial_quantity": initial_quantity, "final_quantity": final_quantity, "demand": demand, "sales": sales, "leftover": leftover, "change_fee_paid": change_fee_paid, "profit": profit, }) practice_results = sorted(practice_results, key=lambda x: x["scenario_id"]) return dict( practice_results=practice_results, practice_total_profit=practice_total_profit, ) page_sequence = [Consent, NoConsent, PracticeInitialOrder, PracticeDecision, PracticeComplete]