from otree.api import * from shared import helpers doc = """ Your app description """ class C(BaseConstants): NAME_IN_URL = "intro1" PLAYERS_PER_GROUP = None NUM_ROUNDS = 1 TIME_PART1 = 10 TIME_PART2 = 10 CHOICES = [[1, "True"], [0, "False"]] SOLUTIONS = dict(question1=1, question2=0, question3=1, question4=1, question5=0, question6=0) NUM_ATTEMPTS = 2 ERR_MSG = "Not all questions were answered correctly. Please try again." COMPREHENSION_DROPOUT_MSG = f"it took you more than {NUM_ATTEMPTS} attempts to answer the comprehension questions correctly. Please return your submission" ATTENTION_DROPOUT_MSG = ( "you failed both our attention checks. Unfortunately, this is the end of the experiment for you" ) CONSENT_DROPOUT_MSG = "you did not agree to participate in this experiment under the rules and regulations listed. Please return your submission" class Subsession(BaseSubsession): pass class Group(BaseGroup): pass class Player(BasePlayer): consent = models.BooleanField( label="Do you agree to participate in this experiment?", choices=[[True, "I agree"], [False, "I don't agree"]] ) # Comprehension question models question1 = models.BooleanField( label="To receive full payment you need to complete all parts of this study.", choices=C.CHOICES ) question2 = models.BooleanField(label="You can complete this study using a mobile device.", choices=C.CHOICES) question3 = models.BooleanField( label="All the instructions must be truthful.", choices=C.CHOICES ) question4 = models.BooleanField(label="Your reward level (High or Low) is decided randomly.", choices=C.CHOICES) question5 = models.BooleanField( label="Not every task gives a reward, so you do not need to pay attention or apply yourself all the time.", choices=C.CHOICES, ) question6 = models.BooleanField( label="In some tasks your reward type will be High, while in others it will be Low.", choices=C.CHOICES ) attempts1 = models.IntegerField(initial=0) attempts2 = models.IntegerField(initial=0) failed_attention1 = models.BooleanField(initial=False) failed_attention2 = models.BooleanField(initial=False) prolific_id = models.LongStringField(label="Prolific ID") # Attention check models football = models.BooleanField(blank=True, initial=False) tennis = models.BooleanField(blank=True, initial=False) hiking = models.BooleanField(blank=True, initial=False) basketball = models.BooleanField(blank=True, initial=False) flying = models.StringField( choices=["Strongly Disagree", "Disagree", "Agree", "Strongly Agree"], label="I fly halfway across the world to go to work every day.", widget=widgets.RadioSelect, ) # PAGES class Consent(Page): form_model = "player" form_fields = ["consent"] @staticmethod def app_after_this_page(player: Player, upcoming_apps): if player.consent is False: helpers.set_dropout(player, C.CONSENT_DROPOUT_MSG) return "dropout" class Comprehension1(Page): form_model = "player" form_fields = ["question1", "question2", "question3"] @staticmethod def vars_for_template(player: Player): return dict(completion_fee=cu(helpers.COMPLETION_FEE)) @staticmethod def error_message(player: Player, values: dict): for field, answer in values.items(): solution = C.SOLUTIONS[field] if solution != answer: player.attempts1 += 1 return C.ERR_MSG @staticmethod def app_after_this_page(player: Player, upcoming_apps): if C.NUM_ATTEMPTS <= player.attempts1: helpers.set_dropout(player, C.COMPREHENSION_DROPOUT_MSG) return "dropout" class Comprehension2(Page): form_model = "player" form_fields = ["question4", "question5", "question6"] @staticmethod def error_message(player: Player, values: dict): for field, answer in values.items(): solution = C.SOLUTIONS[field] if solution != answer: player.attempts2 += 1 return C.ERR_MSG @staticmethod def app_after_this_page(player: Player, upcoming_apps): if C.NUM_ATTEMPTS <= player.attempts2: helpers.set_dropout(player, C.COMPREHENSION_DROPOUT_MSG) return "dropout" class Attention1(Page): form_model = "player" form_fields = ["football", "tennis", "hiking", "basketball"] @staticmethod def before_next_page(player: Player, timeout_happened): failed_attention1 = not (player.football and not player.tennis and not player.hiking and player.basketball) if failed_attention1: player.failed_attention1 = True class Attention2(Page): form_model = "player" form_fields = ["flying"] @staticmethod def app_after_this_page(player: Player, upcoming_apps): failed_attention2 = "Disagree" not in player.flying if failed_attention2: player.failed_attention2 = True if player.failed_attention1: helpers.set_dropout(player, C.ATTENTION_DROPOUT_MSG) return "dropout" class Success(Page): form_model = "player" form_fields = ["prolific_id"] class SuccessMid(Page): pass page_sequence = [ Consent, Comprehension1, SuccessMid, Comprehension2, Success, ]