from otree.api import * c = cu doc = 'Disruption Game' class C(BaseConstants): NAME_IN_URL = 'Change_Instructions_Game1' PLAYERS_PER_GROUP = None NUM_ROUNDS = 3 PRACTICE_ROUND_DEMAND = (110, 87, 106) PRETAIL_COST1 = 30 PWHOLESALE_COST1 = 12 PHOLDING_COST1 = 2 PRETAIL_COST2 = 8 PHOLDING_COST2 = 1 PWHOLESALE_COST2 = 3 NUM_DECISIONS = 10 LOTTERY_A_HI = 2 LOTTERY_A_LO = 1.6 LOTTERY_B_HI = 3.85 LOTTERY_B_LO = 0.1 class Subsession(BaseSubsession): pass def creating_session(subsession: Subsession): pass class Group(BaseGroup): pass class Player(BasePlayer): payment = models.CurrencyField() prolificid = models.StringField(label='Please provide your prolific ID here') q1_answer = models.StringField(choices=[['A', '100 units'], ['B', '40 units'], ['C', '50 units'], ['D', '0 units']], label=' ', widget=widgets.RadioSelect) q1_correct = models.BooleanField(initial=False) q2_answer = models.StringField(choices=[['A', '$50'], ['B', '$450'], ['C', '$500'], ['D', '$950']], label=' Your Answer', widget=widgets.RadioSelect) q2_correct = models.BooleanField(initial=False) consent = models.BooleanField(choices=[[True, 'Yes'], [False, 'No']], label='Do you consent to participating in this study? ', widget=widgets.RadioSelect) Risk = models.StringField(choices=[['A', 'Fully unwilling to take risks'], ['B', 'Unwilling to take risks'], ['C', 'Somewhat unwilling to take'], ['D', 'Neutral'], ['E', 'Somewhat prepared to take risks'], ['F', 'Prepared to take risks'], ['G', '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?', widget=widgets.RadioSelect) selected_decision = models.IntegerField(initial=0) decision_1 = models.StringField(choices=[['A', 'A'], ['B', 'B']], widget=widgets.RadioSelectHorizontal) decision_2 = models.StringField(choices=[['A', 'A'], ['B', 'B']], widget=widgets.RadioSelectHorizontal) decision_3 = models.StringField(choices=[['A', 'A'], ['B', 'B']], widget=widgets.RadioSelectHorizontal) decision_4 = models.StringField(choices=[['A', 'A'], ['B', 'B']], widget=widgets.RadioSelectHorizontal) decision_5 = models.StringField(choices=[['A', 'A'], ['B', 'B']], widget=widgets.RadioSelectHorizontal) decision_6 = models.StringField(choices=[['A', 'A'], ['B', 'B']], widget=widgets.RadioSelectHorizontal) decision_7 = models.StringField(choices=[['A', 'A'], ['B', 'B']], widget=widgets.RadioSelectHorizontal) decision_8 = models.StringField(choices=[['A', 'A'], ['B', 'B']], widget=widgets.RadioSelectHorizontal) decision_9 = models.StringField(choices=[['A', 'A'], ['B', 'B']], widget=widgets.RadioSelectHorizontal) decision_10 = models.StringField(choices=[['A', 'A'], ['B', 'B']], widget=widgets.RadioSelectHorizontal) selected_decisio = models.IntegerField() mpl_payoff = models.CurrencyField(initial=0) treatment = models.StringField() q2_attempts = models.IntegerField(initial=0) q1_attempts = models.IntegerField(initial=0) class ConsentForm(Page): form_model = 'player' form_fields = ['consent', 'prolificid'] @staticmethod def is_displayed(player: Player): if player.round_number == 1: return True return False @staticmethod def before_next_page(player: Player, timeout_happened): import random player.participant.vars['which_game'] = random.choice(['ChangeOrders', 'ChangeOrders2']) class NoConsent(Page): form_model = 'player' @staticmethod def is_displayed(player: Player): # Check if this is the first round and the participant did not give consent if player.round_number == 1: if player.consent is None: return False # Prevents errors if consent is uninitialized return not player.consent return False class Video_Instructions(Page): form_model = 'player' @staticmethod def vars_for_template(player: Player): treatment = player.participant.vars['which_game'] if treatment == 'ChangeOrders2': video_html = '''

Please watch the following video carefully before proceeding. There will be two comprehension questions after the video is done.

If you'd like to review the instructions in text form, you can find them here.

''' video_duration = 331 # adjust as needed else: video_html = '''

Please watch the following video carefully before proceeding. There will be two comprehension questions after the video is done.

If you'd like to review the instructions in text form, you can find them here.

''' video_duration = 430 # adjust as needed return dict(video_html=video_html, video_duration=video_duration) class UnitsInventoryQuestion(Page): form_model = 'player' form_fields = ['q1_answer'] @staticmethod def is_displayed(player: Player): return not player.q1_correct @staticmethod def vars_for_template(player: Player): return dict(feedback_q1=player.participant.vars.get('feedback_q1', ''), attempts=player.q1_attempts) @staticmethod def before_next_page(player: Player, timeout_happened): correct_answer_q1 = "C" # Correct answer for units sold if player.q1_answer == correct_answer_q1: player.q1_correct = True player.participant.vars['feedback_q1'] = ( "Correct! Units sold are the minimum of available inventory and demand. " "Here, 50 (demand) < 100 (available inventory), so units sold = 50." ) else: player.q1_correct = False # No message needed here anymore — it's handled in `error_message` @staticmethod def error_message(player: Player, values): correct_answer_q1 = "C" player.q1_attempts += 1 if not values.get('q1_answer'): return "Please select an answer before proceeding." if values['q1_answer'] != correct_answer_q1: return ( "That is incorrect. Hint: Sold Inventory = Minimum (Available Inventory,Demand)" ) class FeedbackQ1(Page): form_model = 'player' @staticmethod def is_displayed(player: Player): return player.q1_correct @staticmethod def vars_for_template(player: Player): return dict( feedback_q1=player.participant.vars.get('feedback_q1', ''), attempts=player.q1_attempts ) class ProfitQuestion(Page): form_model = 'player' form_fields = ['q2_answer'] @staticmethod def is_displayed(player: Player): return not player.q2_correct @staticmethod def vars_for_template(player: Player): return dict(feedback_q2=player.participant.vars.get('feedback_q2', ''), attempts=player.q2_attempts) @staticmethod def before_next_page(player: Player, timeout_happened): correct_answer_q2 = "B" if player.q2_answer == correct_answer_q2: player.q2_correct = True player.participant.vars['feedback_q2'] = ( "Correct! Profit = (units sold × retail price) − (units ordered × purchase price) = 50 × 10 - 100 x 1 = $450." ) else: player.q2_correct = False # No message needed here anymore — it's handled in `error_message` @staticmethod def error_message(player: Player, values): correct_answer_q2 = "B" player.q2_attempts += 1 if not values.get('q2_answer'): return "Please select an answer before proceeding." if values['q2_answer'] != correct_answer_q2: return ( "That is incorrect. Hint: Profit = (units sold × retail price) − (units ordered × purchase price). " ) class FeedbackQ2(Page): form_model = 'player' @staticmethod def is_displayed(player: Player): return player.q2_correct @staticmethod def vars_for_template(player: Player): return dict( feedback_q2=player.participant.vars.get('feedback_q2', ''), attempts=player.q2_attempts ) @staticmethod def app_after_this_page(player: Player, upcoming_apps): return player.participant.vars['which_game'] page_sequence = [ConsentForm, NoConsent, Video_Instructions, UnitsInventoryQuestion, FeedbackQ1, ProfitQuestion, FeedbackQ2]