from otree.api import * def get_story2_opening(): html = ' Constraints: ' html += '' html += '

Line 0: "I will grant you three wishes", the genie proclaimed. "Speak fast and you will be rewarded." ' html += 'I hesitated just for a minute, and said ...

' return html def get_story1_opening(): html = '

Line 0: "It’s my dream! You cannot stop me", I yelled in frustration. ' html += '"The dream that will cause you to be a penniless pauper or worse kill you", bellowed my father ...

' return html class C(BaseConstants): NAME_IN_URL = 'improv_ind' PLAYERS_PER_GROUP = 1 NUM_ROUNDS = 15 TIMEOUT = 30 STORY1_ROUNDS_END = 5 STORY2_ROUNDS_END = 14 DROPOUT = 60 INSTR = 45 STORY1_OPENING = get_story1_opening() STORY2_OPENING = get_story2_opening() class Subsession(BaseSubsession): pass class Group(BaseGroup): pass class Player(BasePlayer): player_line = models.LongStringField(label='Continue the story!', initial='', blank=True) is_dropout = models.BooleanField(initial=False) class Consent(Page): form_model = 'player' @staticmethod def is_displayed(player: Player): return (player.round_number == 1) class Instr0(Page): timeout_seconds = C.INSTR form_model = 'player' @staticmethod def is_displayed(player: Player): return (player.round_number == 1) class Instr1(Page): timeout_seconds = C.DROPOUT form_model = 'player' @staticmethod def before_next_page(player: Player, timeout_happened): if timeout_happened: player.is_dropout = True player.participant.finished = True @staticmethod def is_displayed(player: Player): return (player.round_number == 1) class ByeDropout(Page): @staticmethod def is_displayed(player: Player): return player.is_dropout @staticmethod def error_message(player: Player, values): return "Cannot proceed past this page" class Story1(Page): timeout_seconds = C.TIMEOUT form_model = 'player' form_fields = ['player_line'] @staticmethod def vars_for_template(player): messages = player.in_rounds(1, C.STORY1_ROUNDS_END ) return dict( messages = messages ) @staticmethod def before_next_page(player: Player, timeout_happened): count = 0 if player.round_number <= C.STORY1_ROUNDS_END: messages = player.in_previous_rounds()[-3:] for message in messages: if message.player_line == "": count += 1 if count > 2: player.is_dropout = True player.participant.finished = True @staticmethod def is_displayed(player: Player): return (player.round_number <= C.STORY1_ROUNDS_END + 1) class Instr2(Page): timeout_seconds = C.DROPOUT form_model = 'player' @staticmethod def before_next_page(player: Player, timeout_happened): if timeout_happened: player.is_dropout = True player.participant.finished = True @staticmethod def is_displayed(player: Player): return (player.round_number == C.STORY1_ROUNDS_END + 1) class StoryConstr(Page): timeout_seconds = C.TIMEOUT form_model = 'player' @staticmethod def is_displayed(player: Player): return (player.round_number == C.STORY1_ROUNDS_END + 1) class Story2(Page): timeout_seconds = C.TIMEOUT form_model = 'player' form_fields = ['player_line'] @staticmethod def vars_for_template(player): messages = player.in_rounds(C.STORY1_ROUNDS_END + 1, C.STORY2_ROUNDS_END ) return dict( messages = messages ) @staticmethod def is_displayed(player: Player): return (player.round_number > C.STORY1_ROUNDS_END) & (player.round_number <= C.STORY2_ROUNDS_END + 1) @staticmethod def before_next_page(player: Player, timeout_happened): count = 0 if player.round_number <= C.STORY2_ROUNDS_END: messages = player.in_rounds(C.STORY1_ROUNDS_END + 1, player.round_number - 1)[-3:] for message in messages: if message.player_line == "": count += 1 if count > 2: player.is_dropout = True player.participant.finished = True page_sequence = [Consent, Instr0, Instr1, ByeDropout, Story1, ByeDropout, Instr2, StoryConstr, Story2, ByeDropout]