from otree import constants from otree.api import * from starlette.types import Message from words import game_words import random doc = """ Your app description """ # Note: As an app, using "app_after_this_page" gives an error if the entered value is more than 5 dollars # This app runs properly when combined with another app class Constants(BaseConstants): name_in_url = 'taboo2' players_per_group = None num_rounds = 50 right_guesses = 1 class Subsession(BaseSubsession): pass class Group(BaseGroup): pass class Player(BasePlayer): # message = models.StringField(initial='') player_word = models.StringField( label = "What is your predicted word?", ) number_of_right_guesses = models.IntegerField(initial=0) number_of_rounds = models.IntegerField(initial=0) error_message = models.StringField(initial="Please enter at least one character before submission.") # Ask the participant for the number of dollars he/she is willing to value user_payment = models.IntegerField(label="How much do you value this activity in terms of dollars?") # PAGES class InstructionsPage(Page): # only shows instructions on the first round @staticmethod def is_displayed(player: Player): return player.round_number == 1 class CounterOfferPage(Page): form_model = "player" form_fields = ["user_payment"] # @staticmethod # def is_displayed(player: Player): # return player.round_number == 1 # only shows counteroffer on the first round @staticmethod def is_displayed(player: Player): return player.round_number == 1 # skips the entire app if the user puts an amount greater than 5 dollars def app_after_this_page(player, upcoming_apps): if player.user_payment > 5: return upcoming_apps[0] # When this page "ends", a session timer will start @staticmethod def before_next_page(player: Player, timeout_happened): participant = player.participant import time participant.expiry = time.time() + 1*20 # 1*60sec class TabooPage(Page): form_model = "player" form_fields = ["player_word"] pre_index = -1 @staticmethod def vars_for_template(player: Player): # use this to randomly choose a index word set rand_idx = random.randrange(len(game_words)) # randomize the set of words while rand_idx == TabooPage.pre_index: rand_idx = random.randrange(len(game_words)) # randomly choose a game word set and export the respective target word, taboos words, and hints TabooPage.target_word = game_words[rand_idx][0] # [game word list][target word] TabooPage.taboo_words = game_words[rand_idx][1] # [game word list][taboo words] TabooPage.hint_words = game_words[rand_idx][2] # [game word list][hint words] # random index will alwasys be different from the last one TabooPage.pre_index = rand_idx hints = TabooPage.hint_words return { "hints": hints } # before the next page loads, compare the participants entered lowercase (.lower()) guess (player.player_word) with the "TabooPage.target_word" # if the lowercase guessed word is the same as the target word, then add "1" to the number of right guesses (right_guesses) def before_next_page(player: Player, timeout_happened): if player.player_word.lower() == TabooPage.target_word: player.number_of_right_guesses = Constants.right_guesses # everytime a round is done, add "1" to total number of rounds player.number_of_rounds = Constants.right_guesses # literrly change the timer text timer_text = 'Time left to complete this section:' # everytime another round is generated, carry over the remaining time from the previous page def get_timeout_seconds(player): participant = player.participant import time return participant.expiry - time.time() # remember to add 'expiry' to PARTICIPANT_FIELDS in settings.py # # Display this page only if paricipant payment is less than or equal to 5. # @staticmethod # def is_displayed(player): # if player.round_number == 1: # if player.user_payment <= 5: # return True # else: # return False # when the time is less that two seconds, quit the current round and skip to the "Results" page @staticmethod def is_displayed(player): participant = player.participant import time time_remaining = participant.expiry - time.time() return time_remaining > 2 class Results(Page): # # Display this page only if paricipant payment is less than or equal to 5. # @staticmethod # def is_displayed(player): # if player.round_number == 1: # if player.user_payment <= 5: # return True # else: # return False # this page will only appear when the number of rounds are complete @staticmethod def is_displayed(player: Player): return player.round_number == Constants.num_rounds @staticmethod def vars_for_template(player: Player): # add the number of correct answer payments from the previous rounds all_players = player.in_all_rounds() combined_right_guess = 0 for temp_player in all_players: combined_right_guess += temp_player.number_of_right_guesses # add the number of total rounds all_players = player.in_all_rounds() combined_rounds = 0 for temp_round in all_players: combined_rounds += temp_round.number_of_rounds return { "combined_right_guess": combined_right_guess, "combined_rounds": combined_rounds } class DisagreePage(Page): # # Display this page only if paricipant payment is greater than 5. # @staticmethod # def is_displayed(player): # if player.round_number == 1: # if player.user_payment > 5: # return True # else: # return False pass page_sequence = [InstructionsPage, CounterOfferPage, TabooPage, Results]