from otree.api import * c = cu doc = '' class C(BaseConstants): NAME_IN_URL = 'individual_change' PLAYERS_PER_GROUP = None NUM_ROUNDS = 9 SCENARIO_MEANS = (400, 400, 400, 500, 500, 500, 600, 600, 600) SCENARIO_SDS = (100, 200, 300, 100, 200, 300, 100, 200, 300) SCENARIO_IMAGES = ('mean_down_sd_down.png', 'mean_down_sd_same.png', 'mean_down_sd_up.png', 'mean_same_sd_down.png', 'mean_same_sd_same.png', 'mean_same_sd_up.png', 'mean_up_sd_down.png', 'mean_up_sd_same.png', 'mean_up_sd_up.png') REALIZED_DEMAND = (435, 520, 310, 540, 460, 680, 575, 720, 510) MACHINE_REALIZED_DEMAND = (382, 615, 455, 470, 560, 290, 640, 515, 735) HUMAN_PROFILE_1 = (700, 700, 700, 700, 700, 700, 700, 700, 700) HUMAN_PROFILE_2 = (577, 577, 577, 577, 577, 577, 577, 577, 577) HUMAN_PROFILE_3 = (550, 500, 700, 650, 500, 545, 600, 450, 700) 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): choice = models.StringField(choices=[['Keep current quantity', 'Keep current quantity'], ['Change quantity', 'Change quantity']], widget=widgets.RadioSelect) new_qty = models.IntegerField(blank=True, label='How much would you like to order? ', max=1000, min=0) scenario_id = models.IntegerField() updated_mean = models.IntegerField() updated_sd = models.IntegerField() final_quantity = models.IntegerField() treatment = models.StringField() initial_q1 = models.IntegerField(label='How much would you like to order for Product 1? ', min=0) initial_q2 = models.IntegerField(label='How much would you like to order for Product 2? ', min=0) initial_q3 = models.IntegerField(label='How much would you like to order for Product 3? ', min=0) initial_q4 = models.IntegerField(label='How much would you like to order for Product 4? ', min=0) initial_q5 = models.IntegerField(label='How much would you like to order for Product 5? ', min=0) initial_q6 = models.IntegerField(label='How much would you like to order for Product 6? ', min=0) initial_q7 = models.IntegerField(label='How much would you like to order for Product 7? ', min=0) initial_q8 = models.IntegerField(label='How much would you like to order for Product 8? ', min=0) initial_q9 = models.IntegerField(label='How much would you like to order for Product 9? ', min=0) human_profile_id = models.IntegerField() my_field = models.StringField() Risk = models.IntegerField(choices=[[1, 'Fully unwilling to take risks'], [2, 'Unwilling to take risks'], [3, 'Somewhat unwilling to take risks'], [4, 'Neutral'], [5, 'Somewhat prepared to take risks'], [6, 'Prepared to take risks'], [7, 'Fully prepared to take risks']], label=' Are you generally a person who is fully prepared to take risks or do you try to avoid taking risks?') MEAN_IMPORTANCE = models.IntegerField(choices=[[1, 'Not at all'], [2, 'Low importance'], [3, 'Slightly important'], [4, 'Neutral'], [5, 'Moderately important'], [6, 'Very important'], [7, 'Extremely important']], label='Mean Changes') STD_IMPORTANCE = models.IntegerField(choices=[[1, 'Not at all important'], [2, 'Low importance'], [3, 'Slightly important'], [4, 'Neutral'], [5, 'Moderately important'], [6, 'Very important'], [7, 'Extremely important']], label='Standard Deviation Changes') Venmo_Pin = models.IntegerField(label='Please put a 4 digit Pin below- use this same Pin to request the amount you earned through the Venmo QR Code above') No_Venmo = models.StringField(blank=True, label='No Venmo? Please provide another form of electronic payment (cashapp, paypal, zelle) or provide an organization you would like to donate your earnings to. ') class Intro(Page): form_model = 'player' @staticmethod def is_displayed(player: Player): return player.round_number == 1 @staticmethod def vars_for_template(player: Player): import random participant = player.participant if 'treatment' not in participant.vars: treatment = random.choice(["self", "other_human"]) participant.vars['treatment'] = treatment else: treatment = participant.vars['treatment'] player.treatment = treatment if treatment == "other_human" and 'human_profile_id' not in participant.vars: participant.vars['human_profile_id'] = random.randint(1, 3) if treatment == "other_human": player.human_profile_id = participant.vars['human_profile_id'] return dict() class Self_Initial_Orders(Page): form_model = 'player' form_fields = ['initial_q1', 'initial_q2', 'initial_q3', 'initial_q4', 'initial_q5', 'initial_q6', 'initial_q7', 'initial_q8', 'initial_q9'] @staticmethod def is_displayed(player: Player): return player.round_number == 1 and player.participant.vars['treatment'] == "self" @staticmethod def error_message(player: Player, values): values_list = [ values['initial_q1'], values['initial_q2'], values['initial_q3'], values['initial_q4'], values['initial_q5'], values['initial_q6'], values['initial_q7'], values['initial_q8'], values['initial_q9'], ] if any(v is None for v in values_list): return "Please enter an order quantity for all 9 products before continuing." class Other_Humans_Orders(Page): form_model = 'player' @staticmethod def is_displayed(player: Player): return player.round_number == 1 and player.participant.vars['treatment'] == "other_human" class Decision(Page): form_model = 'player' form_fields = ['choice', 'new_qty'] @staticmethod def vars_for_template(player: Player): import random participant = player.participant if 'second_scenario_order' not in participant.vars: scenario_order = list(range(1, C.NUM_ROUNDS + 1)) random.shuffle(scenario_order) participant.vars['second_scenario_order'] = scenario_order scenario_order = participant.vars['second_scenario_order'] scenario_id = scenario_order[player.round_number - 1] idx = scenario_id - 1 treatment = participant.vars['treatment'] if treatment == "self": initial_player = player.in_round(1) prior_quantities = [ initial_player.initial_q1, initial_player.initial_q2, initial_player.initial_q3, initial_player.initial_q4, initial_player.initial_q5, initial_player.initial_q6, initial_player.initial_q7, initial_player.initial_q8, initial_player.initial_q9, ] prior_quantity = prior_quantities[idx] else: profile_id = participant.vars['human_profile_id'] if profile_id == 1: prior_quantities = C.HUMAN_PROFILE_1 elif profile_id == 2: prior_quantities = C.HUMAN_PROFILE_2 elif profile_id == 3: prior_quantities = C.HUMAN_PROFILE_3 prior_quantity = prior_quantities[idx] return dict( product_number=scenario_id, scenario_id=scenario_id, updated_mean=C.SCENARIO_MEANS[idx], updated_sd=C.SCENARIO_SDS[idx], scenario_image_path='Change_New/' + C.SCENARIO_IMAGES[idx], prior_quantity=prior_quantity, treatment=treatment, ) @staticmethod def before_next_page(player: Player, timeout_happened): participant = player.participant scenario_order = participant.vars['second_scenario_order'] scenario_id = scenario_order[player.round_number - 1] idx = scenario_id - 1 treatment = participant.vars['treatment'] player.treatment = treatment player.scenario_id = scenario_id player.updated_mean = C.SCENARIO_MEANS[idx] player.updated_sd = C.SCENARIO_SDS[idx] if treatment == "self": initial_player = player.in_round(1) prior_quantities = [ initial_player.initial_q1, initial_player.initial_q2, initial_player.initial_q3, initial_player.initial_q4, initial_player.initial_q5, initial_player.initial_q6, initial_player.initial_q7, initial_player.initial_q8, initial_player.initial_q9, ] prior_quantity = prior_quantities[idx] else: profile_id = participant.vars['human_profile_id'] player.human_profile_id = profile_id if profile_id == 1: prior_quantities = C.HUMAN_PROFILE_1 elif profile_id == 2: prior_quantities = C.HUMAN_PROFILE_2 elif profile_id == 3: prior_quantities = C.HUMAN_PROFILE_3 prior_quantity = prior_quantities[idx] if player.choice == "Keep current quantity": player.final_quantity = prior_quantity else: player.final_quantity = player.new_qty @staticmethod def error_message(player: Player, values): if values["choice"] == "Change quantity" and values["new_qty"] is None: return "Please enter a new quantity if you choose to change the current order." if values["choice"] == "Keep current quantity" and values["new_qty"] is not None: return "Please leave the new quantity box blank if you choose to keep the current order quantity." class Qualitative(Page): form_model = 'player' form_fields = ['Risk', 'MEAN_IMPORTANCE', 'STD_IMPORTANCE'] @staticmethod def is_displayed(player: Player): return player.round_number == C.NUM_ROUNDS class Results(Page): form_model = 'player' @staticmethod def is_displayed(player: Player): return player.round_number == C.NUM_ROUNDS @staticmethod def vars_for_template(player: Player): participant = player.participant machine_results_raw = participant.vars.get('machine_results', []) machine_results = [] machine_total_profit = 0 for r in machine_results_raw: scenario_id = r["scenario_id"] quantity = r["final_quantity"] demand = C.MACHINE_REALIZED_DEMAND[scenario_id - 1] sales = min(demand, quantity) leftover = max(0, quantity - demand) profit = (sales * 57) - (quantity * 9) machine_total_profit += profit machine_results.append({ "scenario_id": scenario_id, "quantity": quantity, "demand": demand, "sales": sales, "leftover": leftover, "profit": profit, }) individual_results = [] individual_total_profit = 0 for p in player.in_all_rounds(): scenario_id = p.scenario_id quantity = p.final_quantity demand = C.REALIZED_DEMAND[scenario_id - 1] sales = min(demand, quantity) leftover = max(0, quantity - demand) profit = (sales * 57) - (quantity * 9) individual_total_profit += profit individual_results.append({ "scenario_id": scenario_id, "quantity": quantity, "demand": demand, "sales": sales, "leftover": leftover, "profit": profit, }) overall_total_profit = machine_total_profit + individual_total_profit if participant.vars['treatment'] == "self": second_block_title = "Results for Your Later Ordering Decisions" else: second_block_title = "Results for the Orders You Reviewed" machine_results = sorted(machine_results, key=lambda x: x["scenario_id"]) individual_results = sorted(individual_results, key=lambda x: x["scenario_id"]) return dict( machine_results=machine_results, individual_results=individual_results, machine_total_profit=machine_total_profit, individual_total_profit=individual_total_profit, overall_total_profit=overall_total_profit, second_block_title=second_block_title, ) class Final_Results(Page): form_model = 'player' form_fields = ['Venmo_Pin', 'No_Venmo'] @staticmethod def is_displayed(player: Player): return player.round_number == C.NUM_ROUNDS @staticmethod def vars_for_template(player: Player): participant = player.participant machine_results_raw = participant.vars.get('machine_results', []) machine_total_profit = 0 for r in machine_results_raw: scenario_id = r["scenario_id"] quantity = r["final_quantity"] demand = C.MACHINE_REALIZED_DEMAND[scenario_id - 1] sales = min(demand, quantity) profit = (sales * 57) - (quantity * 9) machine_total_profit += profit individual_total_profit = 0 for p in player.in_all_rounds(): scenario_id = p.scenario_id quantity = p.final_quantity demand = C.REALIZED_DEMAND[scenario_id - 1] sales = min(demand, quantity) profit = (sales * 57) - (quantity * 9) individual_total_profit += profit overall_total_profit = machine_total_profit + individual_total_profit payout = max(0, round(overall_total_profit / 80000, 2)) return dict( overall_total_profit=overall_total_profit, payout=payout, ) class End(Page): form_model = 'player' @staticmethod def is_displayed(player: Player): return player.round_number == C.NUM_ROUNDS page_sequence = [Intro, Self_Initial_Orders, Other_Humans_Orders, Decision, Qualitative, Results, Final_Results, End]