import random from otree.api import * doc = """ Your app description """ class Constants(BaseConstants): name_in_url = 'Study' players_per_group = None tasks = ['UG'] FORM_TEMPLATE = __name__ + '/form.html' num_rounds = 1 class Subsession(BaseSubsession): pass class Group(BaseGroup): pass class Player(BasePlayer): consent = models.IntegerField(widget=widgets.RadioSelect, label="", choices=[[0, 'Consent and Proceed'], [1, 'Leave this survey']]) code = models.StringField(label="Insert your code here") # This is for main choices, each variable is one row in the choice table MPL UG_1 = models.PositiveIntegerField(choices=[[1, '
Very Inappropriate
'], [2, 'Inappropriate
'], [3, 'Rather Inappropriate
'], [4, 'Rather Appropriate
'], [5, 'Appropriate
'], [6, 'Very Appropriate
']], widget=widgets.RadioSelectHorizontal) UG_2 = models.PositiveIntegerField(choices=[[1, 'Very Inappropriate
'], [2, 'Inappropriate
'], [3, 'Rather Inappropriate
'], [4, 'Rather Appropriate
'], [5, 'Appropriate
'], [6, 'Very Appropriate
']], widget=widgets.RadioSelectHorizontal) UG_3 = models.PositiveIntegerField(choices=[[1, 'Very Inappropriate
'], [2, 'Inappropriate
'], [3, 'Rather Inappropriate
'], [4, 'Rather Appropriate
'], [5, 'Appropriate
'], [6, 'Very Appropriate
']], widget=widgets.RadioSelectHorizontal) UG_4 = models.PositiveIntegerField(choices=[[1, 'Very Inappropriate
'], [2, 'Inappropriate
'], [3, 'Rather Inappropriate
'], [4, 'Rather Appropriate
'], [5, 'Appropriate
'], [6, 'Very Appropriate
']], widget=widgets.RadioSelectHorizontal) UG_5 = models.PositiveIntegerField(choices=[[1, 'Very Inappropriate
'], [2, 'Inappropriate
'], [3, 'Rather Inappropriate
'], [4, 'Rather Appropriate
'], [5, 'Appropriate
'], [6, 'Very Appropriate
']], widget=widgets.RadioSelectHorizontal) UG_6 = models.PositiveIntegerField(choices=[[1, 'Very Inappropriate
'], [2, 'Inappropriate
'], [3, 'Rather Inappropriate
'], [4, 'Rather Appropriate
'], [5, 'Appropriate
'], [6, 'Very Appropriate
']], widget=widgets.RadioSelectHorizontal) UG_7 = models.PositiveIntegerField(choices=[[1, 'Very Inappropriate
'], [2, 'Inappropriate
'], [3, 'Rather Inappropriate
'], [4, 'Rather Appropriate
'], [5, 'Appropriate
'], [6, 'Very Appropriate
']], widget=widgets.RadioSelectHorizontal) UG_8 = models.PositiveIntegerField(choices=[[1, 'Very Inappropriate
'], [2, 'Inappropriate
'], [3, 'Rather Inappropriate
'], [4, 'Rather Appropriate
'], [5, 'Appropriate
'], [6, 'Very Appropriate
']], widget=widgets.RadioSelectHorizontal) UG_9 = models.PositiveIntegerField(choices=[[1, 'Very Inappropriate
'], [2, 'Inappropriate
'], [3, 'Rather Inappropriate
'], [4, 'Rather Appropriate
'], [5, 'Appropriate
'], [6, 'Very Appropriate
']], widget=widgets.RadioSelectHorizontal) UG_10 = models.PositiveIntegerField(choices=[[1, 'Very Inappropriate
'], [2, 'Inappropriate
'], [3, 'Rather Inappropriate
'], [4, 'Rather Appropriate
'], [5, 'Appropriate
'], [6, 'Very Appropriate
']], widget=widgets.RadioSelectHorizontal) UG_11 = models.PositiveIntegerField(choices=[[1, 'Very Inappropriate
'], [2, 'Inappropriate
'], [3, 'Rather Inappropriate
'], [4, 'Rather Appropriate
'], [5, 'Appropriate
'], [6, 'Very Appropriate
']], widget=widgets.RadioSelectHorizontal) UG1 = models.PositiveIntegerField(choices=[[1, 'Person A earns 7€ and Person B earns 3€.'], [2, 'Person A earns 0€ and Person B earns 0€.'], [3, 'Person A earns 3€ and Person B earns 7€.']], label="How much does Person A and Person B earn, if Person A offers 3€ to " "Person B and Person B rejects the offer?", widget=widgets.RadioSelect) UG2 = models.PositiveIntegerField(choices=[[1, 'Person A earns 7€ and Person B earns 3€.'], [2, 'Person A earns 0€ and Person B earns 0€.'], [3, 'Person A earns 3€ and Person B earns 7€.']], label="How much does Person A and Person B earn, if Person A offers 3€" " to Person B and Person B accepts the offer? ", widget=widgets.RadioSelect) UG3 = models.PositiveIntegerField(choices=[[1, 'Person A earns 7€ and Person B earns 3€.'], [2, 'Person A earns 0€ and Person B earns 0€.'], [3, 'Person A earns 3€ and Person B earns 7€.']], label="How much does Person A and Person B earn, if Person A offers 7€ to " "Person B and Person B rejects the offer?", widget=widgets.RadioSelect) UG4 = models.PositiveIntegerField(choices=[[1, 'Person A earns 7€ and Person B earns 3€.'], [2, 'Person A earns 0€ and Person B earns 0€.'], [3, 'Person A earns 3€ and Person B earns 7€.']], label="How much does Person A and Person B earn, if Person A offers 7€" " to Person B and Person B accepts the offer? ", widget=widgets.RadioSelect) Doubled1 = models.PositiveIntegerField(choices=[[1, 'Person A earns 3€ and Person B earns 7€.'], [2, 'Person A earns 7€ and Person B earns 6€.'], [3, 'Person A earns 7€ and Person B earns 3€. ']], label="How much does Person A and Person B earn, if Person A gives 3€ to Person B?", widget=widgets.RadioSelect) Doubled2 = models.PositiveIntegerField(choices=[[1, 'Person A earns 3€ and Person B earns 7€.'], [2, 'Person A earns 7€ and Person B earns 3€.'], [3, 'Person A earns 3€ and Person B earns 14€.']], label="How much does Person A and Person B earn, if Person A gives 7€ to Person B?", widget=widgets.RadioSelect) Half1 = models.PositiveIntegerField(choices=[[1, 'Person A earns 3€ and Person B earns 7€.'], [2, 'Person A earns 7€ and Person B earns 1.50€.'], [3, 'Person A earns 7€ and Person B earns 3€.']], label="How much does Person A and Person B earn, if Person A gives 3€ to Person B?", widget=widgets.RadioSelect) Half2 = models.PositiveIntegerField(choices=[[1, 'Person A earns 3€ and Person B earns 7€.'], [2, 'Person A earns 7€ and Person B earns 3€.'], [3, 'Person A earns 3€ and Person B earns 3.50€. ']], label="How much does Person A and Person B earn, if Person A gives 7€ to Person B?", widget=widgets.RadioSelect) MoralA1 = models.PositiveIntegerField(choices=[[1, 'Strongly disagree
'], [2, 'Disagree
'], [3, 'Somewhat disagree
'], [4, 'Neither agree or disagree
'], [5, 'Somewhat agree
'], [6, 'Agree
'], [7, 'Strongly agree
']], widget=widgets.RadioSelectHorizontal) MoralA2 = models.PositiveIntegerField(choices=[[1, 'Strongly disagree
'], [2, 'Disagree
'], [3, 'Somewhat disagree
'], [4, 'Neither agree or disagree
'], [5, 'Somewhat agree
'], [6, 'Agree
'], [7, 'Strongly agree
']], widget=widgets.RadioSelectHorizontal) MoralA3 = models.PositiveIntegerField(choices=[[1, 'Strongly disagree
'], [2, 'Disagree
'], [3, 'Somewhat disagree
'], [4, 'Neither agree or disagree
'], [5, 'Somewhat agree
'], [6, 'Agree
'], [7, 'Strongly agree
']], widget=widgets.RadioSelectHorizontal) MoralA4 = models.PositiveIntegerField(choices=[[1, 'Strongly disagree
'], [2, 'Disagree
'], [3, 'Somewhat disagree
'], [4, 'Neither agree or disagree
'], [5, 'Somewhat agree
'], [6, 'Agree
'], [7, 'Strongly agree
']], widget=widgets.RadioSelectHorizontal) MoralA5 = models.PositiveIntegerField(choices=[[1, 'Strongly disagree
'], [2, 'Disagree
'], [3, 'Somewhat disagree
'], [4, 'Neither agree or disagree
'], [5, 'Somewhat agree
'], [6, 'Agree
'], [7, 'Strongly agree
']], widget=widgets.RadioSelectHorizontal) MoralA6 = models.PositiveIntegerField(choices=[[1, 'Strongly disagree
'], [2, 'Disagree
'], [3, 'Somewhat disagree
'], [4, 'Neither agree or disagree
'], [5, 'Somewhat agree
'], [6, 'Agree
'], [7, 'Strongly agree
']], widget=widgets.RadioSelectHorizontal) MoralA7 = models.PositiveIntegerField(choices=[[1, 'Strongly disagree
'], [2, 'Disagree
'], [3, 'Somewhat disagree
'], [4, 'Neither agree or disagree
'], [5, 'Somewhat agree
'], [6, 'Agree
'], [7, 'Strongly agree
']], widget=widgets.RadioSelectHorizontal) MoralA8 = models.PositiveIntegerField(choices=[[1, 'Strongly disagree
'], [2, 'Disagree
'], [3, 'Somewhat disagree
'], [4, 'Neither agree or disagree
'], [5, 'Somewhat agree
'], [6, 'Agree
'], [7, 'Strongly agree
']], widget=widgets.RadioSelectHorizontal) MoralA9 = models.PositiveIntegerField(choices=[[1, 'Strongly disagree
'], [2, 'Disagree
'], [3, 'Somewhat disagree
'], [4, 'Neither agree or disagree
'], [5, 'Somewhat agree
'], [6, 'Agree
'], [7, 'Strongly agree
']], widget=widgets.RadioSelectHorizontal) Spite1 = models.PositiveIntegerField(choices=[[1, 'Strongly disagree
'], [2, 'Disagree
'], [3, 'Neither agree nor disagree
'], [4, 'Agree
'], [5, 'Strongly agree
']], widget=widgets.RadioSelectHorizontal) Spite2 = models.PositiveIntegerField(choices=[[1, 'Strongly disagree
'], [2, 'Disagree
'], [3, 'Neither agree nor disagree
'], [4, 'Agree
'], [5, 'Strongly agree
']], widget=widgets.RadioSelectHorizontal) Spite3 = models.PositiveIntegerField(choices=[[1, 'Strongly disagree
'], [2, 'Disagree
'], [3, 'Neither agree nor disagree
'], [4, 'Agree
'], [5, 'Strongly agree
']], widget=widgets.RadioSelectHorizontal) Spite4 = models.PositiveIntegerField(choices=[[1, 'Strongly disagree
'], [2, 'Disagree
'], [3, 'Neither agree nor disagree
'], [4, 'Agree
'], [5, 'Strongly agree
']], widget=widgets.RadioSelectHorizontal) Spite5 = models.PositiveIntegerField(choices=[[1, 'Strongly disagree
'], [2, 'Disagree
'], [3, 'Neither agree nor disagree
'], [4, 'Agree
'], [5, 'Strongly agree
']], widget=widgets.RadioSelectHorizontal) Spite6 = models.PositiveIntegerField(choices=[[1, 'Strongly disagree
'], [2, 'Disagree
'], [3, 'Neither agree nor disagree
'], [4, 'Agree
'], [5, 'Strongly agree
']], widget=widgets.RadioSelectHorizontal) Spite7 = models.PositiveIntegerField(choices=[[1, 'Strongly disagree
'], [2, 'Disagree
'], [3, 'Neither agree nor disagree
'], [4, 'Agree
'], [5, 'Strongly agree
']], widget=widgets.RadioSelectHorizontal) Spite8 = models.PositiveIntegerField(choices=[[1, 'Strongly disagree
'], [2, 'Disagree
'], [3, 'Neither agree nor disagree
'], [4, 'Agree
'], [5, 'Strongly agree
']], widget=widgets.RadioSelectHorizontal) Spite9 = models.PositiveIntegerField(choices=[[1, 'Strongly disagree
'], [2, 'Disagree
'], [3, 'Neither agree nor disagree
'], [4, 'Agree
'], [5, 'Strongly agree
']], widget=widgets.RadioSelectHorizontal) Spite10 = models.PositiveIntegerField(choices=[[1, 'Strongly disagree
'], [2, 'Disagree
'], [3, 'Neither agree nor disagree
'], [4, 'Agree
'], [5, 'Strongly agree
']], widget=widgets.RadioSelectHorizontal) Spite11 = models.PositiveIntegerField(choices=[[1, 'Strongly disagree
'], [2, 'Disagree
'], [3, 'Neither agree nor disagree
'], [4, 'Agree
'], [5, 'Strongly agree
']], widget=widgets.RadioSelectHorizontal) Spite12 = models.PositiveIntegerField(choices=[[1, 'Strongly disagree
'], [2, 'Disagree
'], [3, 'Neither agree nor disagree
'], [4, 'Agree
'], [5, 'Strongly agree
']], widget=widgets.RadioSelectHorizontal) Spite13 = models.PositiveIntegerField(choices=[[1, 'Strongly disagree
'], [2, 'Disagree
'], [3, 'Neither agree nor disagree
'], [4, 'Agree
'], [5, 'Strongly agree
']], widget=widgets.RadioSelectHorizontal) Spite14 = models.PositiveIntegerField(choices=[[1, 'Strongly disagree
'], [2, 'Disagree
'], [3, 'Neither agree nor disagree
'], [4, 'Agree
'], [5, 'Strongly agree
']], widget=widgets.RadioSelectHorizontal) Spite15 = models.PositiveIntegerField(choices=[[1, 'Strongly disagree
'], [2, 'Disagree
'], [3, 'Neither agree nor disagree
'], [4, 'Agree
'], [5, 'Strongly agree
']], widget=widgets.RadioSelectHorizontal) Spite16 = models.PositiveIntegerField(choices=[[1, 'Strongly disagree
'], [2, 'Disagree
'], [3, 'Neither agree nor disagree
'], [4, 'Agree
'], [5, 'Strongly agree
']], widget=widgets.RadioSelectHorizontal) Spite17 = models.PositiveIntegerField(choices=[[1, 'Strongly disagree
'], [2, 'Disagree
'], [3, 'Neither agree nor disagree
'], [4, 'Agree
'], [5, 'Strongly agree
']], widget=widgets.RadioSelectHorizontal) Negative1 = models.IntegerField(choices=[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10], widget=widgets.RadioSelectHorizontal, label="Please use a scale from 0 to 10 where 0 means you are “does not describe me at all” and a 10 means you are “describes me " " perfectly”. " "You can also use the values in-between to indicate where you fall on the scale.") Negative2 = models.IntegerField(choices=[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10], widget=widgets.RadioSelectHorizontal, label="Please use a scale from 0 to 10 where 0 means you are “completely " "unwilling to punish” and a 10 means you are “very willing " "to punish”. " "You can also use the values in-between to indicate where you fall on the scale.") Negative3 = models.IntegerField(choices=[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10], widget=widgets.RadioSelectHorizontal, label="Please use a scale from 0 to 10 where 0 means you are “completely " "unwilling to punish” and a 10 means you are “very willing " "to punish”. " "You can also use the values in-between to indicate where you fall on the scale.") # # These variables are collected in the final questionnaire gender = models.StringField(widget=widgets.RadioSelectHorizontal(), choices=['Male', 'Female']) age = models.IntegerField(choices=range(18, 60, 1)) Study = models.TextField(label="What are your current field and level of studies? (example: Law M1). In case you " "are not" " currently studying, what are your last studies?") Nationality = models.TextField(label="What is your nationality? (example: French)") # FUNCTIONS def creating_session(subsession: Subsession): if subsession.round_number == 1: for p in subsession.get_players(): round_numbers = list(range(1, Constants.num_rounds + 1)) random.shuffle(round_numbers) p.participant.vars['task_rounds'] = dict(zip(Constants.tasks, round_numbers)) p.participant.vars['consent1'] = 2 def get_quiz_data(): return [ dict( name='a', solution=3, explanation="The selected answer is incorrect. The correct answer is “Person A earns 7€ and Person B " "earns 3€”. Recall that Person A receives 10€. Therefore, if Person A gives 3€ to Person B," " Person A earns (10 - 3) = 7€ and Person B earns 3€.", ), dict( name='b', solution=1, explanation="The selected answer is incorrect. The correct answer is “Person A earns 3€ " "and Person B earns 7€”. Recall that Person A receives 10€. " "Therefore, if Person A gives 7€ to Person B, Person A earns (10 - 7) = 3€ " "and Person B earns 7€. ", ), ] def get_quiz_dataUG(): return[ dict( name='UG1', solution=2, explanation="The selected answer is incorrect. The correct answer is “Person A earns 0€ and " "Person B earns 0€”. Person B rejected the offer. Recall that when Person B " "rejects an offer both Person A and Person B earn 0€.", ), dict( name='UG2', solution=1, explanation="The selected answer is incorrect. The correct answer is “Person A " "earns 7€ and Person B earns 3€”. Person B accepted the offer. " "Therefore, Person A earns (10 - 3) = 7€ when he gives 3€ to Person B. Person B earns 3€.", ), dict( name='UG3', solution=2, explanation="The selected answer is incorrect. The correct answer is “Person A earns 0€ and " "Person B earns 0€”. Person B rejected the offer. Recall that when Person B " "rejects an offer both Person A and Person B earn 0€.", ), dict( name='UG4', solution=3, explanation="The selected answer is incorrect. The correct answer is “Person A " "earns 3€ and Person B earns 7€”. Person B accepted the offer. " "Therefore, Person A earns (10 - 7) = 3€ when he gives 7€ to Person B. Person B earns 7€.", ), ] # PAGE class ElicitationNormsUG(Page): @staticmethod def is_displayed(player: Player): return player.participant.vars['consent1'] == 0 # which forms are needed from class player form_model = 'player' form_fields = ['UG_1', 'UG_2', 'UG_3', 'UG_4', 'UG_5', 'UG_6', 'UG_7', 'UG_8', 'UG_9', 'UG_10', 'UG_11'] # all 11 options class Instructions1(Page): # which forms are needed from class player form_model = 'player' @staticmethod def is_displayed(player: Player): participant = player.participant return player.participant.vars['consent1'] == 0 class ExampleSituation(Page): # which forms are needed from class player form_model = 'player' @staticmethod def is_displayed(player: Player): participant = player.participant return player.participant.vars['consent1'] == 0 class SituationDescriptionUG(Page): form_model = 'player' @staticmethod def is_displayed(player: Player): participant = player.participant return player.participant.vars['consent1'] == 0 class ConsentForm(Page): # which forms are needed from class player form_model = 'player' form_fields = ['consent'] @staticmethod def is_displayed(player: Player): participant = player.participant return player.round_number == 1 def before_next_page(player, timeout_happened): player.participant.vars['consent1'] = player.consent class GeneralInstructions(Page): # which forms are needed from class player form_model = 'player' @staticmethod def is_displayed(player: Player): participant = player.participant return player.participant.vars['consent1'] == 0 class Questionnaire(Page): @staticmethod def is_displayed(player: Player): participant = player.participant return player.participant.vars['consent1'] == 0 # forms to retrieve individual information form_model = 'player' form_fields = ['age', 'gender', 'Nationality', 'Study'] class Code1(Page): form_model = 'player' form_fields = ['code'] @staticmethod def is_displayed(player: Player): participant = player.participant return player.participant.vars['consent1'] == 0 class InstructionsExperiment(Page): # which forms are needed from class player form_model = 'player' @staticmethod def is_displayed(player: Player): participant = player.participant return player.participant.vars['consent1'] == 0 class InstructionsNormsUG(Page): @staticmethod def is_displayed(player: Player): return player.participant.vars['consent1'] == 0 # which forms are needed from class player form_model = 'player' form_fields = ['UG1', 'UG2', 'UG3', 'UG4'] # all 11 options class ResultsUG(Page): form_model = 'player' form_fields = ['UG1', 'UG2', 'UG3', 'UG4'] @staticmethod def is_displayed(player: Player): participant = player.participant return player.participant.vars['consent1'] == 0 @staticmethod def vars_for_template(player: Player): fields = get_quiz_dataUG() # we add an extra entry 'is_correct' (True/False) to each field for d in fields: d['is_correct'] = getattr(player, d['name']) == d['solution'] return dict(fields=fields, show_solutions=True) class ResultsDoubled(Page): form_model = 'player' form_fields = ['Doubled1', 'Doubled2'] @staticmethod def is_displayed(player: Player): participant = player.participant return player.round_number == player.participant.vars['consent1'] == 0 @staticmethod def vars_for_template(player: Player): fields = get_quiz_dataDoubled() # we add an extra entry 'is_correct' (True/False) to each field for d in fields: d['is_correct'] = getattr(player, d['name']) == d['solution'] return dict(fields=fields, show_solutions=True) class ResultsHalf(Page): form_model = 'player' form_fields = ['Half1', 'Half2'] @staticmethod def is_displayed(player: Player): participant = player.participant return player.round_number == player.participant.vars['consent1'] == 0 @staticmethod def vars_for_template(player: Player): fields = get_quiz_dataHalf() # we add an extra entry 'is_correct' (True/False) to each field for d in fields: d['is_correct'] = getattr(player, d['name']) == d['solution'] return dict(fields=fields, show_solutions=True) class Moral1(Page): @staticmethod def is_displayed(player: Player): participant = player.participant return player.participant.vars['consent1'] == 0 # forms to retrieve individual information form_model = 'player' form_fields = ['MoralA1', 'MoralA2', 'MoralA3', 'MoralA4', 'MoralA5', 'MoralA6', 'MoralA7', 'MoralA8', 'MoralA9'] class Spite(Page): @staticmethod def is_displayed(player: Player): participant = player.participant return player.participant.vars['consent1'] == 0 # forms to retrieve individual information form_model = 'player' form_fields = ['Spite1', 'Spite2', 'Spite3', 'Spite4', 'Spite5', 'Spite6', 'Spite7', 'Spite8', 'Spite9', 'Spite10', 'Spite11', 'Spite12', 'Spite13', 'Spite14', 'Spite15', 'Spite16', 'Spite17'] class IntructionsQuestionnaires(Page): @staticmethod def is_displayed(player: Player): participant = player.participant return player.participant.vars['consent1'] == 0 # forms to retrieve individual information form_model = 'player' class NegativeReciprocity(Page): @staticmethod def is_displayed(player: Player): participant = player.participant return player.participant.vars['consent1'] == 0 # forms to retrieve individual information form_model = 'player' form_fields = ['Negative1', 'Negative2', 'Negative3'] page_sequence = [ConsentForm, Code1, InstructionsExperiment, InstructionsNormsUG, ResultsUG, ElicitationNormsUG, IntructionsQuestionnaires, Spite, Moral1, NegativeReciprocity, Questionnaire]