import csv import random from otree.api import * from . import models author = 'Manuela Collis' doc = """ A quiz app that reads its questions from a spreadsheet (see quiz.csv in this directory). There is 1 question per page; the number of pages in the game is determined by the number of questions in the CSV. See the comment below about how to randomize the order of pages. """ class Constants(BaseConstants): name_in_url = 'quiz' players_per_group = None with open('quiz_pilot/quiz.csv') as f: questions = list(csv.DictReader(f)) num_rounds = len(questions) class Subsession(BaseSubsession): def creating_session(self): for player in self.get_players(): player.payoff = c(10) # randomize order of quiz player.quiz_order = random.choice([1, 2]) # set values if player.quiz_order == 1: # Computer Science, History player.quiz_topics = ['Computer Science', 'History'] else: # History, Computer Science player.quiz_topics = ['History', 'Computer Science'] player.session.vars['questions'] = Constants.questions.copy() randomized_questions = random.sample(Constants.questions, len(Constants.questions)) player.participant.vars['questions'] = randomized_questions class Group(BaseGroup): pass class Player(BasePlayer): question_id = models.PositiveIntegerField() question = models.CharField() solution = models.CharField() submitted_answer = models.CharField(widget=widgets.RadioSelect) is_correct = models.BooleanField() # FUNCTIONS def creating_session(subsession: Subsession): if subsession.round_number == 1: subsession.session.vars['questions'] = Constants.questions.copy() ## ALTERNATIVE DESIGN: ## to randomize the order of the questions, you could instead do: randomized_questions = random.sample(Constants.questions, len(Constants.questions)) for player in self.get_players(): player.participant.vars['questions'] = randomized_questions #self.participant.vars['questions'] = randomized_questions #and to randomize differently for each participant, you could use #the random.sample technique, but assign into participant.vars ## instead of session.vars. for p in subsession.get_players(): question_data = current_question(p) p.question_id = question_data['id'] p.question = question_data['question'] p.solution = question_data['solution'] def current_question(player: Player): return player.session.vars['questions'][player.round_number - 1] def check_correct(player: Player): player.is_correct = player.submitted_answer == player.solution def submitted_answer_choices(player: Player): qd = current_question(player) return [ qd['choice1'], qd['choice2'], qd['choice3'], qd['choice4'], ] # PAGES class Question(Page): form_model = 'player' form_fields = ['submitted_answer'] @staticmethod def before_next_page(player: Player, timeout_happened): check_correct(player) class Results(Page): @staticmethod def is_displayed(player: Player): return player.round_number == Constants.num_rounds @staticmethod def vars_for_template(player: Player): player_in_all_rounds = player.in_all_rounds() return { 'player_in_all_rounds': player_in_all_rounds, 'questions_correct': sum([p.is_correct for p in player_in_all_rounds]), } page_sequence = [Question, Results]