first commit

This commit is contained in:
duartegoncalvesds 2026-03-12 21:05:38 +00:00
commit 73fc2121bf
30 changed files with 13308 additions and 0 deletions

313
Task1/__init__.py Normal file
View file

@ -0,0 +1,313 @@
from otree.api import *
import random
import math
import json
import numpy as np
import random
import itertools
doc = """Template"""
class C(BaseConstants):
NAME_IN_URL = 'Decision'
PLAYERS_PER_GROUP = None
# Rounds
NUM_PRACTICE_ROUNDS = 2
NUM_PAYMENT_ROUNDS = 3
NUM_ROUNDS = NUM_PRACTICE_ROUNDS + NUM_PAYMENT_ROUNDS
# Captchas
max_captcha_time = 60
captcha_rounds = [1, 2, ] # The rounds in which captchas occur
captcha_text = ["bonus", "payment", ] # The text the participants need to input (can use upper or lowercase)
treatments_between_list = [0, 1]
cost_list = [5, 15, 25, 35, 45, 55, 65, 75, 85, 95]
value_list = [10, 30, 50, 70, 90]
payoffs_list = []
for cost in cost_list:
for value in value_list:
payoffs_list.append([value, cost])
class Subsession(BaseSubsession):
pass
class Group(BaseGroup):
pass
class Player(BasePlayer):
practice = models.IntegerField()
player_round = models.IntegerField()
decision = models.IntegerField()
belief_1 = models.FloatField(min=0, max=100)
# Between-Participant Treatment
treatment_between = models.IntegerField()
# Within-Participant Treatment
treatment_index_within = models.IntegerField()
value = models.FloatField()
cost = models.FloatField()
# Time fields
time_spent = models.IntegerField()
time_spent_instructions = models.IntegerField()
# Captcha
captcha_attempt_1 = models.StringField(label="", initial="")
captcha_attempt_2 = models.StringField(label="", initial="")
captcha_attempt_3 = models.StringField(label="", initial="")
# Instructions
incorrect_instruction_answers = models.StringField(blank=True)
errors_quiz = models.IntegerField()
instructions_clicked = models.BooleanField()
prolific_id = models.StringField(default=str(" "))
# FUNCTIONS
def creating_session(subsession: Subsession):
# Between-participant treatment
# Extend between treatment list * Total participants in session /2 /Nr Between treatments and shuffle
total_number_participants = 10 # max([1,math.floor(len(player.session.get_participants())/2/len(C.treatments_between_list))])
between_treatment_list_shuffled = C.treatments_between_list * total_number_participants
random.shuffle(between_treatment_list_shuffled)
# Within-participant treatment
reps = len(C.payoffs_list) // C.NUM_PAYMENT_ROUNDS
remainder = len(C.payoffs_list) % C.NUM_PAYMENT_ROUNDS
for player in subsession.get_players():
player.prolific_id = player.participant.label
player.player_round = player.round_number
player.participant.vars['failed_captcha'] = False
# Between-participant treatment assignment
player.treatment_between = between_treatment_list_shuffled[len(between_treatment_list_shuffled) % player.participant.id_in_session-1]
if player.round_number == 1:
# Within-participant treatment assignment
treatments_indices_within = list(range(len(C.payoffs_list))) * reps
remaining_treatments = list(range(len(C.payoffs_list)))
random.shuffle(remaining_treatments)
treatments_indices_within = treatments_indices_within + remaining_treatments[:remainder]
random.shuffle(treatments_indices_within)
for r in range(C.NUM_PAYMENT_ROUNDS):
player.in_round(C.NUM_PRACTICE_ROUNDS+1+r).treatment_index_within = treatments_indices_within[r]
if player.player_round <= C.NUM_PRACTICE_ROUNDS:
player.practice = 1
player.value = random.choice(C.value_list)
player.cost = np.round(random.choice(C.cost_list)+10*(random.random()-.5),1)
if player.player_round > C.NUM_PRACTICE_ROUNDS:
player.practice = 0
player.value = C.payoffs_list[player.treatment_index_within][0]
player.cost = np.round(C.payoffs_list[player.treatment_index_within][1]+10*(random.random()-.5),1)
# PAGES
class Instructions(Page):
form_model = 'player'
form_fields = ['incorrect_instruction_answers', 'errors_quiz', 'time_spent_instructions',]
@staticmethod
def is_displayed(player):
return player.round_number == 1
@staticmethod
def vars_for_template(player: Player):
return dict(
participation_fee=player.session.config['participation_fee'],
min_bonus_payment=player.session.config['min_bonus_payment'],
max_bonus_payment=player.session.config['max_bonus_payment'],
min_payment=player.session.config['min_payment'],
max_payment=player.session.config['max_payment'],
)
@staticmethod
def before_next_page(player, timeout_happened):
player.incorrect_instruction_answers = player.field_maybe_none('incorrect_instruction_answers')
class TaskIntro(Page):
@staticmethod
def is_displayed(player):
return (
player.round_number in [1,C.NUM_PRACTICE_ROUNDS+1] and
not player.participant.vars.get('failed_captcha', False)
)
class Task(Page):
form_model = 'player'
form_fields = ['decision','belief_1','time_spent',]
@staticmethod
def is_displayed(player):
return (
not player.participant.vars.get('failed_captcha', False)
)
@staticmethod
def vars_for_template(player):
return dict(
payment_round_number = player.round_number-C.NUM_PRACTICE_ROUNDS,
practice_round_number = player.round_number,
round_number = player.round_number,
)
class TaskFeedback(Page):
@staticmethod
def is_displayed(player):
return (
player.round_number <= C.NUM_PRACTICE_ROUNDS and
not player.participant.vars.get('failed_captcha', False)
)
@staticmethod
def vars_for_template(player):
return dict(
payment_round_number = player.round_number-C.NUM_PRACTICE_ROUNDS,
practice_round_number = player.round_number,
round_number = player.round_number,
belief_A = player.belief_1,
belief_B = 100-player.belief_1,
paymentbelief_A = 2*player.belief_1-player.belief_1**2/100,
paymentbelief_B = 100-player.belief_1**2/100,
)
@staticmethod
def js_vars(player):
return dict(
decision = player.decision,
belief_1 = player.belief_1,
)
class CaptchaFailed(Page):
@staticmethod
def is_displayed(player):
return (
player.participant.vars.get('failed_captcha', True)
)
class Captcha1(Page):
template_name = 'Task1/Captcha.html'
form_model = 'player'
form_fields = ['captcha_attempt_1']
@staticmethod
def is_displayed(player):
if not (
player.round_number in C.captcha_rounds
and not player.participant.vars.get('failed_captcha', False)
and player.subsession.session.config['use_captchas'] == 1
):
return False
else:
return True
@staticmethod
def vars_for_template(player):
max_captcha_time = C.max_captcha_time
return {
'image_path': "images/captchas/captcha{}.png".format(C.captcha_rounds.index(player.round_number) + 1),
'attempt': 1,
'max_captcha_time': max_captcha_time,
}
class Captcha2(Page):
template_name = 'Task1/Captcha.html'
form_model = 'player'
form_fields = ['captcha_attempt_2']
@staticmethod
def is_displayed(player):
if not (
player.round_number in C.captcha_rounds
and not player.participant.vars.get('failed_captcha', False)
and player.subsession.session.config['use_captchas'] == 1
):
return False
else:
return player.captcha_attempt_1.lower() != C.captcha_text[C.captcha_rounds.index(player.round_number)].lower()
@staticmethod
def vars_for_template(player):
max_captcha_time = C.max_captcha_time
return {
'image_path': "images/captchas/captcha{}.png".format(C.captcha_rounds.index(player.round_number) + 1),
'attempt': 2,
'max_captcha_time': max_captcha_time,
}
class Captcha3(Page):
template_name = 'Task1/Captcha.html'
form_model = 'player'
form_fields = ['captcha_attempt_3']
@staticmethod
def is_displayed(player):
if not (
player.round_number in C.captcha_rounds
and not player.participant.vars.get('failed_captcha', False)
and player.subsession.session.config['use_captchas'] == 1
):
return False
else:
return (
player.captcha_attempt_1.lower() != C.captcha_text[
C.captcha_rounds.index(player.round_number)
].lower()
and player.captcha_attempt_2.lower() != C.captcha_text[
C.captcha_rounds.index(player.round_number)
].lower()
)
@staticmethod
def vars_for_template(player):
max_captcha_time = C.max_captcha_time
return {
'image_path': "images/captchas/captcha{}.png".format(C.captcha_rounds.index(player.round_number) + 1),
'attempt': 3,
'max_captcha_time': max_captcha_time,
}
@staticmethod
def before_next_page(player, timeout_happened):
correct_text = C.captcha_text[C.captcha_rounds.index(player.round_number)].lower()
if (
player.round_number in C.captcha_rounds
and player.captcha_attempt_1.lower() != correct_text
and player.captcha_attempt_2.lower() != correct_text
and player.captcha_attempt_3.lower() != correct_text
):
player.participant.vars['failed_captcha'] = True
# Update page_sequence
page_sequence = [
Instructions,
Captcha1,
Captcha2,
Captcha3,
CaptchaFailed,
TaskIntro,
Task,
TaskFeedback,
]