import csv from otree.api import * from . import models author = 'Khoi Nguyen' 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 num_rounds = 20 # big enough number class Subsession(BaseSubsession): pass 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): # Init questions if subsession.round_number == 1: with open(subsession.session.config['quiz_path']) as f: subsession.session.vars['questions'] = list(csv.DictReader(f)) print(len(subsession.session.vars['questions'])) ## ALTERNATIVE DESIGN: ## to randomize the order of the questions, you could instead do: # import random # randomized_questions = random.sample(Constants.questions, len(Constants.questions)) # self.session.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 = int(question_data['id']) p.question = question_data['question'] p.solution = question_data[question_data['solution']] def current_question(player: Player): # print('calling Current question', player.round_number - 1) index = player.round_number - 1 questions = player.session.vars['questions'] if index >= len(questions): return questions[0] else: return questions[index] def check_correct(player: Player): player.is_correct = player.submitted_answer == player.solution def submitted_answer_choices(player: Player): qd = current_question(player) ret = [] for choice in ['A', 'B', 'C', 'D', 'E']: if choice in qd.keys(): ret.append(qd[choice]) return ret # return [ # qd['A'], # qd['B'], # qd['C'], # qd['D'], # qd['E'], # ] # def show_quiz(player: Player): # # TODO: generalize the role to display # participant = player.participant # # print(participant.__dict__) # # print(f'In quiz, id = {player.id_in_group}, earning = {participant.earning}') # return participant.role == 'dictator' and participant.earning # PAGES # class Introduction(Page): # @staticmethod # def vars_for_template(player: Player): # return dict( # P1=(player.id_in_group()==1) # ) class Question(Page): form_model = 'player' form_fields = ['submitted_answer'] @staticmethod def before_next_page(player: Player, timeout_happened): check_correct(player) @staticmethod def is_displayed(player: Player): return player.round_number <= len(player.session.vars['questions']) @staticmethod def vars_for_template(player: Player): return dict( num_questions=len(player.session.vars['questions']) ) class Results(Page): # @staticmethod def is_displayed(player: Player): return (player.round_number == len(player.session.vars['questions'])) @staticmethod def vars_for_template(player: Player): num_questions = len(player.session.vars['questions']) player_in_all_rounds = player.in_all_rounds()[:num_questions] score = sum([p.is_correct for p in player_in_all_rounds]) print(f'Score = {score}') player.participant.score = score return { 'player_in_all_rounds': player_in_all_rounds, 'questions_correct': score, 'num_questions': num_questions } page_sequence = [Question, Results]