import random import itertools from otree.api import * from settings import STRATEGIES, ROUNDS_PER_STRATEGY doc = """ Introductory pages to read for the participants. Also used to randomly determine the order of apps for the respective participant (Strategy following task first or other tasks first). """ TREATMENTS_REMINDER = [ "Baseline", "Strategy reminder", "Action reminder", "Strategy and action reminder", ] def creating_session(subsession: BaseSubsession): treatments = list(itertools.product(TREATMENTS_REMINDER, STRATEGIES)) nr_players = len(subsession.get_players()) if nr_players % len(treatments) != 0: raise ValueError( f"You have {len(TREATMENTS_REMINDER)} different reminder treatments and " f"{len(STRATEGIES)} different rules to follow in the strategy task, " f"i.e. {len(TREATMENTS_REMINDER)*len(STRATEGIES)} treatments in total. " f"Having {nr_players} participants therefore leads to imbalanced " "treatment groups." ) treatment_iter = itertools.cycle(treatments) for player in subsession.get_players(): treatment = next(treatment_iter) player.participant.treatment_reminder = treatment[0] player.participant.treatment_rule = treatment[1] class Constants(BaseConstants): name_in_url = "welcome" players_per_group = None num_rounds = 1 class Subsession(BaseSubsession): pass class Group(BaseGroup): pass class Player(BasePlayer): review = models.BooleanField( label="", ) read = models.BooleanField( label="", ) consent = models.BooleanField( label="", ) def review_error_message(player, value): if value != 1: return "Consent is required" def read_error_message(player, value): if value != 1: return "Consent is required" def consent_error_message(player, value): if value != 1: return "Consent is required" class Info(Page): timeout_seconds = 600 form_model = "player" form_fields = ["review", "read", "consent"] # initializing the attention check and timeout participant variables for later apps @staticmethod def before_next_page(player, timeout_happened): participant = player.participant participant.audiocheck_answer = None participant.attention_check_quiz = None participant.attention_check_sft = None participant.nr_correct_answers_subtractions = None participant.crt_score = None participant.num_correct_words_delay = None participant.sft_pay = None participant.points = None participant.attention_check_failed = False for i in range(1, ROUNDS_PER_STRATEGY + 1): exec(f"participant.mistake_round_{i} = False") if timeout_happened: participant.timeout = True else: participant.timeout = False @staticmethod def app_after_this_page(player, upcoming_apps): participant = player.participant if participant.timeout: return "kick" class Welcome(Page): timeout_seconds = 600 @staticmethod def app_after_this_page(player: Player, upcoming_apps): """ Remove participants that timed out and randomly send other participants either to the strategy following task or the demographic/other tasks section. :param player: Player for which the next app is determined. :return: Name of next app for the player. """ participant = player.participant rndm = random.random() if participant.timeout: return "kick" else: if rndm < 0.5: participant.order = 1 return "quiz" else: participant.order = 2 @staticmethod def before_next_page(player, timeout_happened): participant = player.participant if timeout_happened: participant.timeout = True else: participant.timeout = False @staticmethod def vars_for_template(player: Player): session = player.session return dict( exchange_rate_points_real_currency="{:.2f}".format( session.config["real_world_currency_per_point"] ), participation_fee=session.config["participation_fee"], ) page_sequence = [Info, Welcome]