import math from numbers import Number import random from statistics import mode import numpy as np from secrets import choice from otree.api import * doc = """ Your app description """ class C(BaseConstants): NAME_IN_URL = 'eden_expert' PLAYERS_PER_GROUP = None NUM_ROUNDS = 1 NUM_TRIALS = 1 ########################################## 100 CONDITIONS = ["Abstract", "Expert"] PAYMENT_STRUCTURES = ["Payment1", "Payment2"] PAYOFFS_BY_MODE = [ lambda: np.random.choice([2, -2], p=[0.6, 0.4]), lambda: np.random.choice([3, -3], p=[0.5, 0.5]), lambda: np.random.choice([2, -2], p=[0.4, 0.6]), lambda: np.random.choice([3, -3], p=[0.5, 0.5]) ] ATTENTION_SCORES = [1, -2, -12, 12, 5] ATTENTION_LABELS = ["A", "B", "C", "D", "E"] ATTENTION_FOR_BONUS = "D" class Subsession(BaseSubsession): pass def creating_session(subsession: Subsession): if (subsession.round_number == 1): for p in subsession.get_players(): # p.condition = C.CONDITIONS[random.randint(0, 4)] p.condition_id = 1 ####################################################### random.choice([0, 1]) p.button_location = random.choice([0, 1]) p.total_points = 0 p.luck_level = round(random.uniform(-20, 20), 3) class Group(BaseGroup): pass class Player(BasePlayer): age = models.IntegerField(min=15, max=90) gender = models.StringField(choices=['Male', 'Female', 'Other']) comments = models.StringField(blank=True) connect_id = models.StringField() total_points = models.FloatField() luck_level = models.FloatField() condition_id = models.IntegerField() button_location = models.IntegerField() # already finished rounds rounds_in_mainpage = models.IntegerField(initial=0) ################################################ =(0) attention_choice = models.StringField() submission_code = models.StringField() pass class Choice(ExtraModel): player = models.Link(Player) payoff = models.CurrencyField() forgone = models.IntegerField() time = models.IntegerField() # Add Field here choice = models.IntegerField() # 0 for certain, 1 for gain_lose # PAGES class Intro(Page): form_model = 'player' form_fields = ['gender', 'age', 'comments', 'connect_id'] class BreakPage(Page): pass def handleMainRequest(player: Player, data, subMain: int): if player.rounds_in_mainpage >= 4: ###################C.NUM_TRIALS * subMain: return print(data) # extract data choice = data["choice"] time = data["time"] # mode # current rounds player.rounds_in_mainpage += 1 ########################################################### DELETE the # # payoff if choice is 1, then loss or gain loss_gain = C.PAYOFFS_BY_MODE[subMain-1] if callable(loss_gain): loss_gain = int(loss_gain()) payoff = loss_gain if choice == 1 else 0 forgone = loss_gain if choice == 0 else 0 player.total_points += payoff # create extra model Choice.create(player=player, payoff=payoff, forgone=forgone, time=time, choice=choice) return {player.id_in_group: {"payoff": payoff, "choices": [0, loss_gain]}} class MainScreen(Page): subMainScreen = 1 @staticmethod def live_method(player: Player, data): return handleMainRequest(player, data, MainScreen.subMainScreen) @staticmethod def js_vars(player: Player): condition_id = player.condition_id return dict(condition_id=condition_id, button_location=player.button_location, current_round=player.rounds_in_mainpage+1, ############################################ 1 current_points=player.total_points, total_rounds=1, #1 * C.NUM_TRIALS, ############################################# 1 buttons_description=[ ["?", "?"], ["Zero for sure", "2 with probability 60% and -2 otherwise"] ][condition_id] ) class MainScreen2(MainScreen): subMainScreen = 2 ############################################################################# 2 @staticmethod def live_method(player: Player, data): return handleMainRequest(player, data, MainScreen2.subMainScreen) @staticmethod def js_vars(player: Player): condition_id = player.condition_id return dict(condition_id=condition_id, button_location=player.button_location, current_round=player.rounds_in_mainpage+1, current_points=player.total_points, total_rounds=2, #2 * C.NUM_TRIALS, ################################################# 2 buttons_description=[ ["?", "?"], ["Zero for sure", "3 with probability 50% and -3 otherwise"] ][condition_id] ) ##################################################################<><><><><><>><<><<>><><><><><><><><><><><<><>< class MainScreen3(MainScreen): subMainScreen = 3 @staticmethod def live_method(player: Player, data): return handleMainRequest(player, data, MainScreen3.subMainScreen) @staticmethod def js_vars(player: Player): condition_id = player.condition_id return dict(condition_id=condition_id, button_location=player.button_location, current_round=player.rounds_in_mainpage+1, current_points=player.total_points, total_rounds=3 * C.NUM_TRIALS, ########################################## 2 buttons_description=[ ["?", "?"], ["Zero for sure", "2 with probability 40% and -2 otherwise"] ][condition_id] ) #######################################################################################><><><>><><><><><><><<><><><> class MainScreen4(MainScreen): subMainScreen = 4 @staticmethod def live_method(player: Player, data): return handleMainRequest(player, data, MainScreen4.subMainScreen) @staticmethod def js_vars(player: Player): condition_id = player.condition_id return dict(condition_id=condition_id, button_location=player.button_location, current_round=player.rounds_in_mainpage+1, current_points=player.total_points, total_rounds=4 * C.NUM_TRIALS, ########################################## 2 buttons_description=[ ["?", "?"], ["Zero for sure", "3 with probability 50% and -3 otherwise"] ][condition_id] ) #######################################################################################><><><>><><><><><><><<><><><> class AttentionTestScreen2(Page): form_model = 'player' form_fields = ['attention_choice'] @staticmethod def vars_for_template(player: Player): attention = map(lambda i: dict( abs_score=abs(C.ATTENTION_SCORES[i]), label=C.ATTENTION_LABELS[i], score=C.ATTENTION_SCORES[i] ), range(len(C.ATTENTION_SCORES))) return dict( attention=list(attention) ) @staticmethod def before_next_page(player: Player, timeout_happened): if player.total_points >= player.luck_level and player.attention_choice == C.ATTENTION_FOR_BONUS: player.submission_code = player.session.config['completion_code'] player.payoff = 1 else: player.submission_code = player.session.config['incompletion_code'] player.payoff = 0 class Results(Page): pass def custom_export(players: list[Player]): yield ['Session', 'Id', 'Participant Code', 'Round', 'Choice', 'Payoff', 'Forgone', 'Time', 'age', 'gender', 'comments', 'connect_id', 'condition', 'button_location', 'attention_choice', 'total_points', 'luck_level', 'payoff', 'submission_code'] for p in players: session = p.session participant = p.participant choices = Choice.filter(player=p) rn = 0 player_info = [p.age, p.gender, p.comments, p.connect_id, C.CONDITIONS[1], p.button_location, p.attention_choice, p.total_points, p.luck_level, p.payoff, p.submission_code] # player_info = [p.age, p.gender, p.comments, p.connect_id, C.CONDITIONS[p.condition_id], p.button_location, # p.attention_choice, p.total_points, p.luck_level, p.payoff, p.submission_code] for c in choices: rn = rn + 1 choice = "0 with certainty" if c.choice == 0 else "Gain or Loss" yield_array = [session.code, p.id_in_group, participant.code, rn, choice, c.payoff, c.forgone, c.time] if rn == len(choices): yield_array = yield_array + player_info yield yield_array # page_sequence = [Intro, # MainScreen, BreakPage, MainScreen2, AttentionTestScreen2, Results] page_sequence = [Intro, MainScreen, MainScreen2, MainScreen3, MainScreen4, AttentionTestScreen2, Results] ###########################