from otree.api import * c = Currency doc = """ instructions """ class C(BaseConstants): NAME_IN_URL = 'instructions' PLAYERS_PER_GROUP = None NUM_ROUNDS = 1 timers = dict(pre_ret = 120, start_next_part = 120) example_template = 'instructions/Example.html' example2_template = 'instructions/Example2.html' class Subsession(BaseSubsession): pass class Group(BaseGroup): pass class Player(BasePlayer): timeout = models.IntegerField(initial = 0) excluded = models.BooleanField(initial = False) # comprehension questions #q1 = models.BooleanField(label = "In Game II, if your contribution is 10 tokens, and the total contribution of your group is 60 tokens, then your payoff is:", #choices = [ # [True, "(50-10) +(y*60)/3"], # correct # [False, "(50-10) +(x*60)/3"] #]) # fail comprehension quiz num_failed_attempts = models.IntegerField(initial = 0) failed_too_many = models.BooleanField(initial = False) q1 = models.IntegerField( label=" How are the tokens of the public account divided between the three group members?", choices=[ [0, "Group members who contributed more to the public account receive more tokens."], [1, "All group members receive the same number of tokens from the public account, regardless how much they contributed."],# correct [2, "The tokens from the public account are randomly divided between all group members."], [3, "Group members who contributed less to the public account receive more tokens."] ]) q2 = models.FloatField( label="Suppose you have X=2 tokens initially and the rate of return is 20%, if you contribute 1 token to the public account, " "and the others' contribution of your group is 0, then how much tokens you have eventually in the game" " (hint: every token contributed to the public account will be multiplied by 1.2, and distributed evenly to all three group members):", min=0, max=2 ) # comprehension quiz game_com = models.IntegerField( label="Which player is more likely to receive true information: ", choices=[ [0, "A player with an accuracy level of 41% "], [1, "A player with an accuracy level of 65% "], [2, "A player with an accuracy level of 86% "], # correct [3, "A player with an accuracy level of 57% "] ]) acc_level = models.IntegerField( label="Which of the following statements is TRUE: ", choices=[ [0, "All group member have the same accuracy level"], [1, "Each group member has a different accuracy level"], # correct [2, "It is possible that an accuracy level is lower than 40%"] ]) failed_project = models.IntegerField( label="If you invest 45 tokens in the failed project, then your final bonus in this study is:", choices=[ [0, "0"], [1, "5"], # correct [2, "50"], [3, "45"] ]) # PAGES class intro(Page): timeout_seconds = C.timers['pre_ret'] class Comprehension(Page): #timeout_seconds = C.timers['start_next_part'] #timer_text = 'Time Remaining: ' @staticmethod def error_message(player: Player, values): # alternatively, you could make quiz1_error_message, quiz2_error_message, etc. # but if you have many similar fields, this is more efficient. # error_message can return a dict whose keys are field names and whose # values are error messages errors = {name: 'Wrong' for name in solutions if values[name] != solutions[name]} # print('errors is', errors) if errors: return errors @staticmethod def error_message(player: Player, values): # alternatively, you could make quiz1_error_message, quiz2_error_message, etc. # but if you have many similar fields, this is more efficient. solutions = dict(q1=1, q2=1.4) # error_message can return a dict whose keys are field names and whose # values are error messages errors = {name: 'Wrong' for name in solutions if values[name] != solutions[name]} # print('errors is', errors) if errors: player.num_failed_attempts += 1 if player.num_failed_attempts >= 3: player.failed_too_many = True # we don't return any error here; just let the user proceed to the # next page, but the next page is the 'failed' page that boots them # from the experiment. else: return errors @staticmethod def before_next_page(player: Player, timeout_happened): if timeout_happened: player.participant.dropout = True @staticmethod def app_after_this_page(player: Player, upcoming_apps): participant = player.participant if participant.dropout: return upcoming_apps[-1] form_model = "player" form_fields = ["q1","q2"] class Failed(Page): @staticmethod def is_displayed(player: Player): return player.failed_too_many @staticmethod def before_next_page(player: Player, timeout_happened): player.participant.dropout = True @staticmethod def app_after_this_page(player: Player, upcoming_apps): participant = player.participant if participant.dropout: return upcoming_apps[-1] class StartNextPart(Page): timeout_seconds = C.timers['start_next_part'] @staticmethod def before_next_page(player: Player, timeout_happened): if timeout_happened: player.participant.dropout = True @staticmethod def app_after_this_page(player: Player, upcoming_apps): participant = player.participant if participant.dropout: return upcoming_apps[-1] class GameInstruction(Page): #@staticmethod # def is_displayed(player: Player): # return player.group.has_dropout == False #timeout_seconds = C.timers['instruction'] #timer_text = 'Time Remaining: ' @staticmethod def error_message(player: Player, values): # alternatively, you could make quiz1_error_message, quiz2_error_message, etc. # but if you have many similar fields, this is more efficient. solutions = dict(game_com=2, acc_level=1, failed_project=1) # error_message can return a dict whose keys are field names and whose # values are error messages errors = {name: 'Wrong' for name in solutions if values[name] != solutions[name]} # print('errors is', errors) if errors: player.num_failed_attempts += 1 if player.num_failed_attempts >= 3: player.failed_too_many = True # player.group.has_dropout = True # we don't return any error here; just let the user proceed to the # next page, but the next page is the 'failed' page that boots them # from the experiment. else: return errors form_model = "player" form_fields = ["game_com", "acc_level", "failed_project"] @staticmethod def before_next_page(player: Player, timeout_happened): if timeout_happened: player.participant.dropout = True #player.group.has_dropout = True @staticmethod def app_after_this_page(player: Player, upcoming_apps): participant = player.participant if participant.dropout: return upcoming_apps[-1] page_sequence = [intro, #Comprehension, GameInstruction, Failed, StartNextPart ]