import random import numpy as np from otree.api import * doc = """ Your new decision-making task where participants choose between a random number from a normal distribution or a fixed number. """ class C(BaseConstants): NAME_IN_URL = 'new_decision_making_experiment' PLAYERS_PER_GROUP = None NUM_ROUNDS = 10 # Generating a normal distribution of 30 numbers rounded to the nearest integer # risk_list = np.random.normal(50, 15, 30).clip(0, 100).astype(int).tolist() - This worked negative_risk = np.random.randint(-100, 0, size=int(30 * 0.10)).tolist() # 10% of values between -100 and -1 low_risk = np.random.randint(1, 70, size=int(30 * 0.70)).tolist() # 70% of values between 1 and 70 high_risk = np.random.randint(71, 101, size=int(30 * 0.20)).tolist() # 20% of values between 71 and 100 risk_list = negative_risk + low_risk + high_risk np.random.shuffle(risk_list) # Shuffle the list to mix the distributions base_payment = Currency(0) risk = 'A' safe = 'B' class Subsession(BaseSubsession): pass class Group(BaseGroup): pass class Player(BasePlayer): age = models.IntegerField(min=15, max=90) gender = models.StringField(choices=['Male', 'Female', 'Other']) connect_id = models.StringField() choice_val = models.StringField(choices=[C.risk, C.safe], label="Choose A for a random number or B for 40") random_number = models.IntegerField() #total_points = models.FloatField(initial=C.base_payment) current_round = models.IntegerField() current_points = models.FloatField() total_points = models.FloatField() def creating_session(subsession: Subsession): for player in subsession.get_players(): # This line should be removed or adjusted, as it contradicts the logic for round 1 that follows. # player.total_points = C.base_payment if subsession.round_number == 1: # Initialize values for the first round player.total_points = 0 # Reset total points to 0 at the start of the experiment player.current_round = 1 # Explicitly setting current_round to 1 is redundant since you can use subsession.round_number else: # Carry over values from the previous round previous_player = player.in_round(subsession.round_number - 1) player.total_points = previous_player.total_points player.current_round = subsession.round_number # Directly use subsession.round_number # The rest of your player setup for each round would go here # Pages class Intro(Page): form_model = 'player' form_fields = ['gender', 'age', 'connect_id'] @staticmethod def is_displayed(player: Player): return player.round_number == 1 class ShowDistribution(Page): @staticmethod def vars_for_template(player: Player): # Assuming you have 30 numbers and you want 5 numbers per row numbers_in_rows = [C.risk_list[i:i + 5] for i in range(0, len(C.risk_list), 5)] return {'numbers': numbers_in_rows} class MakeChoice(Page): form_model = 'player' form_fields = ['choice_val'] @staticmethod def vars_for_template(player: Player): return { 'risk_choice': C.risk, 'safe_choice': C.safe, } @staticmethod def before_next_page(player: Player, timeout_happened): if player.choice_val == C.risk: player.random_number = random.choice(C.risk_list) player.total_points += player.random_number else: player.total_points += 40 # Fixed number for choice B class Results(Page): @staticmethod def vars_for_template(player: Player): return {'total_payoff': player.total_points} page_sequence = [Intro, ShowDistribution, MakeChoice, Results]