from otree.api import *
from scenario_text import SCENARIOS
doc = """
End-of-experiment questionnaire
"""
def likert_1_5():
return [
[1, "1"],
[2, "2"],
[3, "3"],
[4, "4"],
[5, "5"],
]
def scale_0_10():
# RadioSelectHorizontal works well with 0-10.
return [[i, str(i)] for i in range(0, 11)]
class C(BaseConstants):
NAME_IN_URL = "questionnaire"
PLAYERS_PER_GROUP = None
NUM_ROUNDS = 1
class Subsession(BaseSubsession):
pass
class Group(BaseGroup):
pass
class Player(BasePlayer):
# -------------------------
# 1) Informations générales
# -------------------------
gender = models.StringField(
label="Vous vous identifiez comme :",
choices=[
["Femme", "Femme"],
["Homme", "Homme"],
["Non-binaire / Autre", "Non-binaire / Autre"],
["Préfère ne pas répondre", "Préfère ne pas répondre"],
],
widget=widgets.RadioSelect,
)
age = models.IntegerField(
label="Quel âge avez-vous ?",
min=18,
max=100,
)
current_status = models.StringField(
label="Quelle est votre situation actuelle ?",
choices=[
["Étudiant·e licence", "Étudiant·e licence"],
["Étudiant·e en master ou doctorat", "Étudiant·e en master ou doctorat"],
["En emploi (temps plein ou temps partiel)", "En emploi (temps plein ou temps partiel)"],
["Autre", "Autre"],
],
widget=widgets.RadioSelect,
)
current_other = models.LongStringField(
label="Si vous avez sélectionné « Autre », veuillez préciser :",
blank=True,
)
field_of_study_or_work = models.StringField(
label="Quel est votre domaine d’études / secteur d’activité ?",
choices=[
'Économie',
'Gestion / Management / Business',
'Finance / Comptabilité / Audit',
'Marketing / Communication',
'Droit',
'Sciences politiques / Relations internationales',
'Psychologie',
'Sociologie / Anthropologie',
'Éducation / Enseignement',
'Langues / Lettres / Arts / Design',
'Histoire / Géographie / Philosophie',
'Mathématiques / Statistiques',
'Informatique / Data / IA',
'Ingénierie (général)',
'Sciences physiques (physique, chimie, etc.)',
'Sciences de la vie (biologie, biochimie, etc.)',
'Médecine / Santé (hors médecine : paramédical, etc.)',
'Pharmacie',
'Architecture / Urbanisme',
'Environnement / Développement durable',
'Logistique / Supply chain',
'Ressources humaines',
'Secteur public / Administration',
'Autre (précisez)',
'Je préfère ne pas répondre',
],
blank=True,
)
field_of_study_or_work_other = models.LongStringField(
label="Si autre, précisez :",
blank=True,
)
baccalaureat_grade = models.LongStringField(
label=(
"
Quel était votre résultat au baccalauréat ? "
"Merci d’indiquer votre note.
"
" - Si vous avez passé un autre diplôme de fin d'études secondaires, précisez aussi l’échelle utilisée.
"
"- Vous pouvez passer la question si vous ne souhaitez pas y répondre.
"
),
blank=True,
)
# --------------------------------
# 2) Choix et ressenti durant l'étude
# --------------------------------
satisfaction_performance = models.IntegerField(
label="Dans quelle mesure êtes-vous satisfait·e de votre performance concernant l’activité de résolution d’exercices de logique de la Partie 2 ?
(0 = Pas du tout, 10 = Extrêmement satisfait·e)",
choices=scale_0_10(),
widget=widgets.RadioSelectHorizontal,
)
perceived_difficulty = models.IntegerField(
label="À quel point avez-vous trouvé les exercices de logique difficile ?
(0 = Extrêmement facile, 10 = Extrêmement difficile)",
choices=scale_0_10(),
widget=widgets.RadioSelectHorizontal,
)
stress_level = models.IntegerField(
label="À quel point vous êtes-vous senti·e stressé·e en résolvant les exercices de logique ?
(0 = Pas du tout stressé·e, 10 = Extrêmement stressé·e)",
choices=scale_0_10(),
widget=widgets.RadioSelectHorizontal,
)
ppm_reflects_ability = models.IntegerField(
label="Dans quelle mesure pensez-vous que le nombre d’exercices résolus par minute reflète votre véritable capacité pour ce type d'exercices ?
"
"(0 = Pas du tout, 10 = Parfaitement)",
choices=scale_0_10(),
widget=widgets.RadioSelectHorizontal,
)
ppm_depends_on_duration = models.IntegerField(
label="Pensez-vous que le nombre d’exercices résolus par minute dépend de la durée passée sur l'activité ?
(0 = Pas du tout, 10 = Énormément)",
choices=scale_0_10(),
widget=widgets.RadioSelectHorizontal,
)
time_allocation_explanation = models.LongStringField(
label=(""),
blank=True,
)
# -------------------------
# 3) Personnalité (Grit)
# -------------------------
grit_1 = models.IntegerField(label="Les nouvelles idées ou projets me distraient parfois de ceux que j’ai commencés.", choices=likert_1_5(), widget=widgets.RadioSelectHorizontal)
grit_2 = models.IntegerField(label="Les contretemps ne me découragent pas.", choices=likert_1_5(), widget=widgets.RadioSelectHorizontal)
grit_3 = models.IntegerField(label="J'ai déjà été passionné·e par une idée ou un projet pendant un certain temps, puis j’ai fini par ne plus m’y intéresser.", choices=likert_1_5(), widget=widgets.RadioSelectHorizontal)
grit_4 = models.IntegerField(label="Je travaille dur.", choices=likert_1_5(), widget=widgets.RadioSelectHorizontal)
grit_5 = models.IntegerField(label="Je me fixe souvent un objectif mais choisis d'en poursuivre un autre par la suite.", choices=likert_1_5(), widget=widgets.RadioSelectHorizontal)
grit_6 = models.IntegerField(label="J’ai du mal à rester concentré·e sur des projets qui durent plus que quelques mois.", choices=likert_1_5(), widget=widgets.RadioSelectHorizontal)
grit_7 = models.IntegerField(label="Je termine toujours ce que je commence.", choices=likert_1_5(), widget=widgets.RadioSelectHorizontal)
grit_8 = models.IntegerField(label="Je suis appliqué·e.", choices=likert_1_5(), widget=widgets.RadioSelectHorizontal)
def calculate_grit_score(self):
def rev(x):
return 6 - x
items = [
rev(self.grit_1),
self.grit_2,
rev(self.grit_3),
self.grit_4,
rev(self.grit_5),
rev(self.grit_6),
self.grit_7,
self.grit_8,
]
return sum(items) / len(items)
# -------------------------
# Questions sur les choix de temps
# -------------------------
imp_earnings = models.IntegerField(
label="Gagner le plus d’argent possible.",
choices=likert_1_5(),
widget=widgets.RadioSelectHorizontal,
)
imp_goodrank = models.IntegerField(
label="Obtenir un bon classement.",
choices=likert_1_5(),
widget=widgets.RadioSelectHorizontal,
)
imp_shape = models.IntegerField(
label="Influencer ce que ma position dans le classement révèle sur ma productivité par rapport aux autres.
(Par exemple, en passant moins de temps que les autres pour avoir une excuse si mon classement est mauvais)",
choices=likert_1_5(),
widget=widgets.RadioSelectHorizontal,
)
imp_fair = models.IntegerField(
label="Rendre la comparaison avec les autres plus équitable et précise.",
choices=likert_1_5(),
widget=widgets.RadioSelectHorizontal,
)
# -------------------------
# 4) Questions sur les classements
# -------------------------
competitiveness_self_report = models.IntegerField(
label="Je suis une personne compétitive.",
choices=likert_1_5(),
widget=widgets.RadioSelectHorizontal,
)
importance1 = models.IntegerField(
label="Quand je suis comparé·e à d'autres, obtenir un meilleur résultat que les autres compte beaucoup pour moi.",
choices=likert_1_5(),
widget=widgets.RadioSelectHorizontal,
)
importance2 = models.IntegerField(
label="Je préfère connaître précisément mon niveau, même si cela peut être désagréable.",
choices=likert_1_5(),
widget=widgets.RadioSelectHorizontal,
)
importance3 = models.IntegerField(
label="Quand je suis comparé·e à d'autres, j'ai tendance à préférer que la comparaison reflète précisément mon niveau par rapport aux autres.",
choices=likert_1_5(),
widget=widgets.RadioSelectHorizontal,
)
importance4 = models.IntegerField(
label="Quand je suis comparé·e aux autres, il m'arrive de ne pas me donner à fond afin d’avoir une excuse si mes résultats sont moins bons.",
choices=likert_1_5(),
widget=widgets.RadioSelectHorizontal,
)
importance5 = models.IntegerField(
label="Avant une tâche importante, il m'arrive de faire en sorte d’avoir une excuse en cas d’échec.",
choices=likert_1_5(),
widget=widgets.RadioSelectHorizontal,
)
grit_score = models.FloatField()
def is_session1(player) -> bool:
return bool(player.session.config.get('session1', False))
class BaseQPage(Page):
@staticmethod
def vars_for_template(player):
return dict(
session1=is_session1(player),
)
class Questionnaire1(BaseQPage):
form_model = "player"
form_fields = [
# 1) Informations générales
"gender",
"age",
"current_status",
"current_other",
"field_of_study_or_work",
'field_of_study_or_work_other',
"baccalaureat_grade",]
def error_message(self, values):
# Require explanation if "Autre" is selected
if values.get("current_status") == "Autre" and not values.get("current_other"):
return "Vous avez sélectionné « Autre ». Merci de préciser."
# Disallow filling other-text when not selecting "Autre"
if values.get("current_status") != "Autre" and values.get("current_other"):
return "Vous avez renseigné une précision pour « Autre » mais vous n’avez pas sélectionné « Autre »."
# field_of_study_or_work: require other text if Autre (précisez)
if values.get("field_of_study_or_work") == "Autre (précisez)" and not values.get(
"field_of_study_or_work_other"):
return "Vous avez sélectionné « Autre (précisez) ». Merci de préciser votre domaine / secteur."
if values.get("field_of_study_or_work") != "Autre (précisez)" and values.get(
"field_of_study_or_work_other"):
return "Vous avez renseigné une précision pour « Autre » mais vous n’avez pas sélectionné « Autre (précisez) »."
class Questionnaire2(BaseQPage):
form_model = "player"
form_fields = [
"satisfaction_performance",
"perceived_difficulty",
"stress_level",
"ppm_reflects_ability",
"ppm_depends_on_duration",
]
class QuestionnaireTimeChoices(BaseQPage):
form_model = "player"
form_fields = [
"imp_earnings",
"imp_goodrank",
"imp_shape",
"imp_fair",
]
class Questionnaire3(BaseQPage):
form_model = "player"
form_fields = [
"competitiveness_self_report",
# 4) Classements
"importance2",
"importance5",
# 3) Personnalité
"grit_1",
"grit_2",
"grit_3",
"grit_4",
]
class Questionnaire4(BaseQPage):
form_model = "player"
form_fields = [
"grit_5",
"grit_6",
"grit_7",
"grit_8",
"importance1",
"importance3",
"importance4",
]
def before_next_page(player, timeout_happened=False):
player.grit_score = player.calculate_grit_score()
page_sequence = [Questionnaire1, Questionnaire2, QuestionnaireTimeChoices, Questionnaire3, Questionnaire4]