import random from otree.api import * doc = """ Your app description """ class C(BaseConstants): NAME_IN_URL = 'instructions' PLAYERS_PER_GROUP = None NUM_ROUNDS = 1 class Subsession(BaseSubsession): pass class Group(BaseGroup): pass class Player(BasePlayer): welcome_duration = models.FloatField() instruction_duration = models.FloatField() errors_comprehension_check = models.IntegerField(initial=0) # Question 1: Total Rounds (10-20 + 45 = 55-65) quiz_total_rounds = models.IntegerField( label="Approximately how many rounds will be played in total across Part 1 and Part 2?", choices=[ [1, 'Between 25 and 35 rounds'], [2, 'Between 55 and 65 rounds'], [3, 'Between 125 and 135 rounds'], ], widget=widgets.RadioSelect ) # Question 2: Payment rounds quiz_payment_rounds = models.IntegerField( label="How many rounds of the game will determine your bonus payment?", choices=[ [1, 'My bonus payment is based on all the rounds I played.'], [2, 'My bonus payment is based on 1 randomly selected round.'], [3, 'My bonus payment is based on 5 randomly selected rounds.'], ], widget=widgets.RadioSelect ) # Question 3: Neighbors Change quiz_neighbors_change = models.IntegerField( label="Will the players who are assigned as your neighbours change between Part 1 and Part 2?", choices=[ [1, 'Yes'], [2, 'No'], ], widget=widgets.RadioSelect ) # Question 4: Who is a neighbour quiz_neighbors = models.IntegerField( label="Which players are your neighbours?", choices=[ [1, 'Every player with the same network position as you'], [2, 'Every player thats in your network'], [3, 'Every player that is directly connected to you within the network'], ], widget=widgets.RadioSelect ) # Question 5: bonus points dependency quiz_bonus_points = models.IntegerField( label="Your bonus points each round depend on...?", choices=[ [1, 'Your decision and your neighbours decisions'], [2, 'Your decision only'], [3, 'Your decision and all other players decisions'], ], widget=widgets.RadioSelect ) # Question 6: Math 1 (@ and 5/5 neighbours) quiz_math_1 = models.IntegerField( label="What will you earn in this scenario?", choices=[ [1, '50 basis points + [(5/5) x 150] = 150 coordination bonus points = total: 200'], [2, '100 basis points + [(5/5) x 150] = 150 coordination bonus points = total: 250'], [3, '100 basis points + [(1/5) x 150] = 30 coordination bonus points = total: 130'], [4, '100 basis points + [(5/5) x 300] = 300 coordination bonus points = total: 400'], ], widget=widgets.RadioSelect ) # Question 7: Math 2 (@ and 1/6 neighbours) quiz_math_2 = models.IntegerField( label="What will you earn in this scenario?", choices=[ [1, '50 basis points + [(6/6) x 150] = 150 coordination bonus points = total: 200'], [2, '100 basis points + [(6/6) x 150] = 150 coordination bonus points = total: 250'], [3, '100 basis points + [(1/6) x 150] = 25 coordination bonus points = total: 125'], [4, '100 basis points + [(1/5) x 150] = 30 coordination bonus points = total: 130'], ], widget=widgets.RadioSelect ) # Question 8: Anonymity quiz_anonymity = models.IntegerField( label="Will the other players be able to connect your decisions with you as a person?", choices=[ [1, 'Yes'], [2, 'No'], ], widget=widgets.RadioSelect ) # PAGES class Welcome(Page): @staticmethod def before_next_page(player: Player, timeout_happened): import time # participant._last_page_timestamp ist ein interner oTree-Wert start_time = player.participant._last_page_timestamp if start_time: player.welcome_duration = time.time() - start_time class Game_instructions(Page): form_model = 'player' form_fields = [ 'quiz_total_rounds', 'quiz_payment_rounds', 'quiz_neighbors_change', 'quiz_neighbors', 'quiz_bonus_points', 'quiz_math_1', 'quiz_math_2', 'quiz_anonymity' ] @staticmethod def vars_for_template(player: Player): import json # Symbole holen sym_1 = "#" sym_0 = "@" # Parameter aus der Config (mit Fallback-Werten) bp0 = player.session.config.get('bp0', 100) bp1 = player.session.config.get('bp1', 50) ep = player.session.config.get('ep', 150) base_1 = bp1 base_0 = bp0 choice_order = [1, 0] return dict( label_for_1=sym_1, label_for_0=sym_0, ep=ep, base_1=base_1, base_0=base_0, choice_order=choice_order, ) def error_message(player, values): # Define the correct values based on the numbers in choices=[] solutions = { 'quiz_total_rounds': 2, 'quiz_payment_rounds': 3, 'quiz_neighbors_change': 2, 'quiz_neighbors': 3, 'quiz_bonus_points': 1, 'quiz_math_1': 2, 'quiz_math_2': 3, 'quiz_anonymity': 2, } # Check each field and build a list of errors errors = [] if values['quiz_total_rounds'] != solutions['quiz_total_rounds']: errors.append("Question 1 is incorrect.") if values['quiz_payment_rounds'] != solutions['quiz_payment_rounds']: errors.append("Question 2 is incorrect.") if values['quiz_neighbors_change'] != solutions['quiz_neighbors_change']: errors.append("Question 3 is incorrect.") if values['quiz_neighbors'] != solutions['quiz_neighbors']: errors.append("Question 4 is incorrect.") if values['quiz_bonus_points'] != solutions['quiz_bonus_points']: errors.append("Question 5 is incorrect.") if values['quiz_math_1'] != solutions['quiz_math_1']: errors.append("Question 6 is incorrect.") if values['quiz_math_2'] != solutions['quiz_math_2']: errors.append("Question 7 is incorrect.") if values['quiz_anonymity'] != solutions['quiz_anonymity']: errors.append("Question 8 is incorrect.") if errors: return (f"One or more answers are incorrect. Please review the instructions and try again. {errors}") @staticmethod def before_next_page(player: Player, timeout_happened): import time # participant._last_page_timestamp ist ein interner oTree-Wert start_time = player.participant._last_page_timestamp if start_time: player.instruction_duration = time.time() - start_time page_sequence = [Welcome, Game_instructions]