from otree.api import ( Page, WaitPage, models, widgets, BaseConstants, BaseSubsession, BaseGroup, BasePlayer, Currency as c, currency_range, ) import csv import random import json doc = """ Your app description """ class Constants(BaseConstants): name_in_url = 'RPIPromotions' players_per_group = 6 num_rounds = 7 with open('RPIPromotions/multiplication.csv') as f: questions = list(csv.DictReader(f)) with open('RPIPromotions/addition.csv') as f: questions2 = list(csv.DictReader(f)) class Subsession(BaseSubsession): pass class Group(BaseGroup): highest_correct1 = models.IntegerField() winner = models.IntegerField() unique_correct = models.StringField() class Player(BasePlayer): question = models.StringField() choice1 = models.StringField() choice2 = models.StringField() choice3 = models.StringField() choice4 = models.StringField() choice5 = models.StringField() solution = models.StringField() responses = models.StringField(initial="[]") num_correct = models.IntegerField(initial=0) num_incorrect = models.IntegerField(initial=0) finished = models.BooleanField(initial=False) is_winner = models.BooleanField(initial=False) math = models.StringField() name = models.StringField() # FUNCTIONS def creating_session(subsession: Subsession): # randomize to treatments import itertools math_groups = itertools.cycle(['addition', 'multiplication']) # if subsession.round == 1 for p in subsession.get_players(): p.math = next(math_groups) print('set player.math to', p.math) p.participant.math = p.math num_questions = len(Constants.questions) for p in subsession.get_players(): p.participant.vars['total_attempted'] = 0 p.participant.vars['question_sequence'] = random.sample(range(num_questions), num_questions) print(p.participant.vars['question_sequence']) q = p.participant.vars['question_sequence'][0] if p.math == 'addition': p.question = Constants.questions2[q]['question'] p.choice1 = Constants.questions2[q]['choice1'] p.choice2 = Constants.questions2[q]['choice2'] p.choice3 = Constants.questions2[q]['choice3'] p.choice4 = Constants.questions2[q]['choice4'] p.choice5 = Constants.questions2[q]['choice5'] p.solution = Constants.questions2[q]['solution'] else: p.question = Constants.questions[q]['question'] p.choice1 = Constants.questions[q]['choice1'] p.choice2 = Constants.questions[q]['choice2'] p.choice3 = Constants.questions[q]['choice3'] p.choice4 = Constants.questions[q]['choice4'] p.choice5 = Constants.questions[q]['choice5'] p.solution = Constants.questions[q]['solution'] def promotion_outcome(g: Group): players = [p for p in g.get_players() if p.math == 'addition'] correct = [p.num_correct for p in players] correct.sort(reverse=True) g.highest_correct1 = correct[0] highest_correct_tie = [p.id_in_group for p in players if p.num_correct == g.highest_correct1] g.winner = random.choice(highest_correct_tie) winning_player = g.get_player_by_id(g.winner) winning_player.is_winner = True winning_player.math = 'multiplication' for p in winning_player.in_rounds(3,7): p.math = 'multiplication' num_questions = len(Constants.questions) p.participant.vars['question_sequence'] = random.sample(range(num_questions), num_questions) print(p.participant.vars['question_sequence']) q = p.participant.vars['question_sequence'][0] p.question = Constants.questions[q]['question'] p.choice1 = Constants.questions[q]['choice1'] p.choice2 = Constants.questions[q]['choice2'] p.choice3 = Constants.questions[q]['choice3'] p.choice4 = Constants.questions[q]['choice4'] p.choice5 = Constants.questions[q]['choice5'] p.solution = Constants.questions[q]['solution'] def public_rpi(g: Group): players = [p for p in g.get_players() if p.math == 'multiplication'] correct = [p.num_correct for p in players] unique_correct = list(set(correct)) unique_correct.sort(reverse=True) print("unique", unique_correct) g.unique_correct = json.dumps(unique_correct) # PAGES class Instructions(Page): def is_displayed(player): return player.round_number == 1 class Name(Page): def is_displayed(player): return player.round_number == 1 form_model = 'player' form_fields = ['name'] def before_next_page(player: Player, timeout_happened): player.participant.vars['name'] = player.name class Task(Page): timeout_seconds = 180 def live_method(player, data): print(data) player.participant.vars['total_attempted'] += 1 print("participant total attempted", player.participant.vars['total_attempted']) # score the response if data == player.solution: player.num_correct += 1 else: player.num_incorrect += 1 # record the response; convert to/from string/list lst = json.loads(player.responses) print("data", data) lst.append(data) player.responses = json.dumps(lst) # Check to see if any questions left num_completed = player.num_correct + player.num_incorrect if num_completed < len(Constants.questions2): # need to add this for multiplication players # load the next question q = player.participant.vars['question_sequence'][player.participant.vars['total_attempted']] # Assigning next (single) question to the player model variables allows for graceful refresh/reconnect if player.math == 'addition': player.question = Constants.questions2[q]['question'] player.choice1 = Constants.questions2[q]['choice1'] player.choice2 = Constants.questions2[q]['choice2'] player.choice3 = Constants.questions2[q]['choice3'] player.choice4 = Constants.questions2[q]['choice4'] player.choice5 = Constants.questions2[q]['choice5'] player.solution = Constants.questions2[q]['solution'] else: player.question = Constants.questions[q]['question'] player.choice1 = Constants.questions[q]['choice1'] player.choice2 = Constants.questions[q]['choice2'] player.choice3 = Constants.questions[q]['choice3'] player.choice4 = Constants.questions[q]['choice4'] player.choice5 = Constants.questions[q]['choice5'] player.solution = Constants.questions[q]['solution'] else: player.finished = True msg = { 'question': player.question, 'choice1': player.choice1, 'choice2': player.choice2, 'choice3': player.choice3, 'choice4': player.choice4, 'choice5': player.choice5, 'finished': player.finished, 'num_correct': player.num_correct, 'num_incorrect': player.num_incorrect, } return {player.id_in_group: msg} class MultiplicationHint (Page): def is_displayed(player: Player): return player.round_number == 1 and player.math == 'multiplication' class PromotionWaitPage(WaitPage): def is_displayed(player: Player): return player.round_number == 2 after_all_players_arrive = 'promotion_outcome' class Promotion(Page): def is_displayed(player: Player): return player.round_number == 2 class ResultsWaitPage(WaitPage): after_all_players_arrive = 'public_rpi' class Results(Page): def vars_for_template(player): players = [p for p in player.group.get_players() if p.math == 'multiplication'] question_total = player.num_correct + player.num_incorrect rank1 = [p.participant.vars['name'] for p in players if p.num_correct == json.loads(p.group.unique_correct)[0]] print("rank1", rank1) if len(json.loads(player.group.unique_correct)) > 1: rank2 = [p.participant.vars['name'] for p in players if p.num_correct == json.loads(p.group.unique_correct)[1]] else: rank2 = [] print("rank2", rank2) if len(json.loads(player.group.unique_correct)) > 2: rank3 = [p.participant.vars['name'] for p in players if p.num_correct == json.loads(p.group.unique_correct)[2]] else: rank3 = [] print("rank3", rank3) if len(json.loads(player.group.unique_correct)) > 3: rank4 = [p.participant.vars['name'] for p in players if p.num_correct == json.loads(p.group.unique_correct)[3]] else: rank4 = [] print("rank4", rank4) return dict( rank1=rank1, rank2=rank2, rank3=rank3, rank4=rank4, question_total=question_total, ) class ThankYou(Page): def is_displayed(player: Player): return player.round_number == 7 def vars_for_template(player: Player): payoff_round = random.randint(1, Constants.num_rounds) correct = player.in_round(payoff_round).num_correct correct1 = player.in_round(1).num_correct correct2 = player.in_round(2).num_correct correct3 = player.in_round(3).num_correct correct4 = player.in_round(4).num_correct correct5 = player.in_round(5).num_correct correct6 = player.in_round(6).num_correct correct7 = player.in_round(7).num_correct if player.math == 'multiplication': player.payoff = correct * 2.5 else: player.payoff = correct * .75 return dict( payoff=player.payoff, payoff_round=payoff_round, correct=correct, correct1=correct1, correct2=correct2, correct3=correct3, correct4=correct4, correct5=correct5, correct6=correct6, correct7=correct7, ) page_sequence = [Instructions, Name, Task, ResultsWaitPage, Results, PromotionWaitPage, MultiplicationHint, Promotion, ThankYou]