from otree.api import * import random import time import requests from otree.settings import RECAPTCHA_SECRET_KEY, RECAPTCHA_SITE_KEY doc = """ Instructions for the experiment """ class C(BaseConstants): NAME_IN_URL = 'Instructions' PLAYERS_PER_GROUP = None NUM_ROUNDS = 1 TREAT_SEQ = [['no','ews'],['no','noise'],['ews','no'],['noise','no']] RANGE = 40 class Subsession(BaseSubsession): pass class Group(BaseGroup): pass class Player(BasePlayer): Question1 = models.StringField( label='How many independent parts are there?', choices=['1', '3', '4','6','8'], widget=widgets.RadioSelect, ) Question3 = models.StringField( label='In a given part, is the number of tokens the same in each round? ', choices=['Yes', 'No'], widget=widgets.RadioSelect, ) Question2 = models.StringField( label='Is the number of tokens the same in each part?', choices=['Yes, always. (The computer draws one number for all three parts.)', 'No, never. (The computer samples without replacement making sure that no number is drawn twice.)', 'It is very unlikely, but it may happen. (The computer draws a new number every part – sampling with replacement.)'], widget=widgets.RadioSelect, ) Question4 = models.StringField( label='If you have successfully claimed a certain number of tokens in one round, is it safe to claim the same number of tokens in the next round? ', choices=['Yes', 'No'], widget=widgets.RadioSelect, ) box_length = models.IntegerField() treatment1 = models.BooleanField() treatment2 = models.BooleanField() noise = models.BooleanField() prolific_id = models.StringField(default=str(" ")) time_start = models.FloatField() is_human = models.BooleanField(initial=False) class IncorrectResponse(ExtraModel): player = models.Link(Player) field_name = models.StringField() response = models.StringField() def treat_def(player): treatment_sequence = random.choice(C.TREAT_SEQ) first_treatment = treatment_sequence[0] second_treatment = treatment_sequence[1] if first_treatment == 'no': player.treatment1 = False else: if first_treatment == 'ews': player.box_length = C.RANGE player.treatment1 = True player.noise= False else: player.box_length = C.RANGE player.treatment1 = True player.noise = True if second_treatment == 'no': player.treatment2 = False else: if second_treatment == 'ews': player.box_length = C.RANGE player.treatment2 = True player.noise = False else: player.box_length = C.RANGE player.treatment2 = True player.noise = True return { 'treatment1': player.treatment1, 'treatment2': player.treatment2, 'box_length': player.box_length, 'noise':player.noise } # PAGES class Blank(Page): pass class Start(Page): def vars_for_template(player: Player): return { "RECAPTCHA_SITE_KEY": RECAPTCHA_SITE_KEY } def live_method(player: Player, data): if recaptcha_valid(data["response_token"]): player.is_human = True @staticmethod def error_message(player, values): if not player.is_human: return 'You did not solve the captcha.' @staticmethod def before_next_page(player, timeout_happened): player.prolific_id = player.participant.label player.time_start = time.time() class Quizcompleted(Page): @staticmethod def app_after_this_page(player, upcoming_apps): if player.treatment1 == False: return upcoming_apps[0] else: return upcoming_apps[3] class Instructions(Page): @staticmethod def vars_for_template(player): player.participant.vars['treatment1','treatment2','box_length','noise'] = treat_def(player) @staticmethod def before_next_page(player, timeout_happened): player.participant.vars['treatment1'] = player.treatment1 player.participant.vars['treatment2'] = player.treatment2 player.participant.vars['box_length'] = player.box_length player.participant.vars['noise'] = player.noise class Instructions2(Page): pass class Instructions3(Page): pass class Quiz(Page): form_model = 'player' form_fields = ['Question1', 'Question2', 'Question3', 'Question4'] @staticmethod def error_message(player, values): solutions = dict(Question1='3', Question3='Yes', Question2='It is very unlikely, but it may happen. (The computer draws a new number every part – sampling with replacement.)', Question4='Yes') errors = {f: 'This answer is not correct.' for f in solutions if values[f] != solutions[f]} if errors: for name in errors: response = values[name] IncorrectResponse.create(player=player, field_name=name, response=str(response)) return errors page_sequence = [Blank, Start, Instructions, Instructions2, Quiz, Quizcompleted] def custom_export(players): """For data export page""" yield ['participant_code', 'id_in_session', 'round_number', 'field_name', 'response'] responses = IncorrectResponse.filter() for resp in responses: player = resp.player participant = player.participant yield [participant.code, participant.id_in_session, player.round_number, resp.field_name, resp.response] def recaptcha_valid(response_token): res = requests.post("https://www.google.com/recaptcha/api/siteverify", data={ 'secret': RECAPTCHA_SECRET_KEY, 'response': response_token }) return res.json()["success"]