from otree.api import * import random doc = """ Your app description """ class C(BaseConstants): NAME_IN_URL = 'Questionnaire' PLAYERS_PER_GROUP = None NUM_ROUNDS = 1 class Subsession(BaseSubsession): pass class Group(BaseGroup): pass def make_field(label): return models.IntegerField( choices=[[1, 'Strongly disagree'], [2, 'Disagree'], [3, 'Slightly disagree'], [4, 'Neither agree or disagree'], [5, 'Slightly agree'], [6, 'Agree'], [7, 'Strongly agree']], label=label, widget=widgets.RadioSelect, ) def all_countries(label): return models.StringField( label=label, initial='', choices=[ ('Afghanistan', 'Afghanistan'), ('Albania', 'Albania'), ('Algeria', 'Algeria'), ('Andorra', 'Andorra'), ('Angola', 'Angola'), ('Antigua & Deps', 'Antigua & Deps'), ('Argentina', 'Argentina'), ('Armenia', 'Armenia'), ('Australia', 'Australia'), ('Austria', 'Austria'), ('Azerbaijan', 'Azerbaijan'), ('Bahamas', 'Bahamas'), ('Bahrain', 'Bahrain'), ('Bangladesh', 'Bangladesh'), ('Barbados', 'Barbados'), ('Belarus', 'Belarus'), ('Belgium', 'Belgium'), ('Belize', 'Belize'), ('Benin', 'Benin'), ('Bhutan', 'Bhutan'), ('Bolivia', 'Bolivia'), ('Bosnia Herzegovina', 'Bosnia Herzegovina'), ('Botswana', 'Botswana'), ('Brazil', 'Brazil'), ('Brunei', 'Brunei'), ('Bulgaria', 'Bulgaria'), ('Burkina', 'Burkina'), ('Burundi', 'Burundi'), ('Cambodia', 'Cambodia'), ('Cameroon', 'Cameroon'), ('Canada', 'Canada'), ('Cape Verde', 'Cape Verde'), ('Central African Rep', 'Central African Rep'), ('Chad', 'Chad'), ('Chile', 'Chile'), ('China', 'China'), ('Colombia', 'Colombia'), ('Comoros', 'Comoros'), ('Congo', 'Congo'), ('Congo {Democratic Rep}', 'Congo {Democratic Rep}'), ('Costa Rica', 'Costa Rica'), ('Croatia', 'Croatia'), ('Cuba', 'Cuba'), ('Cyprus', 'Cyprus'), ('Czech Republic', 'Czech Republic'), ('Denmark', 'Denmark'), ('Djibouti', 'Djibouti'), ('Dominica', 'Dominica'), ('Dominican Republic', 'Dominican Republic'), ('East Timor', 'East Timor'), ('Ecuador', 'Ecuador'), ('Egypt', 'Egypt'), ('El Salvador', 'El Salvador'), ('Equatorial Guinea', 'Equatorial Guinea'), ('Eritrea', 'Eritrea'), ('Estonia', 'Estonia'), ('Ethiopia', 'Ethiopia'), ('Fiji', 'Fiji'), ('Finland', 'Finland'), ('France', 'France'), ('Gabon', 'Gabon'), ('Gambia', 'Gambia'), ('Georgia', 'Georgia'), ('Germany', 'Germany'), ('Ghana', 'Ghana'), ('Greece', 'Greece'), ('Grenada', 'Grenada'), ('Guatemala', 'Guatemala'), ('Guinea', 'Guinea'), ('Guinea-Bissau', 'Guinea-Bissau'), ('Guyana', 'Guyana'), ('Haiti', 'Haiti'), ('Honduras', 'Honduras'), ('Hungary', 'Hungary'), ('Iceland', 'Iceland'), ('India', 'India'), ('Indonesia', 'Indonesia'), ('Iran', 'Iran'), ('Iraq', 'Iraq'), ('Ireland {Republic}', 'Ireland {Republic}'), ('Israel', 'Israel'), ('Italy', 'Italy'), ('Ivory Coast', 'Ivory Coast'), ('Jamaica', 'Jamaica'), ('Japan', 'Japan'), ('Jordan', 'Jordan'), ('Kazakhstan', 'Kazakhstan'), ('Kenya', 'Kenya'), ('Kiribati', 'Kiribati'), ('Korea North', 'Korea North'), ('Korea South', 'Korea South'), ('Kosovo', 'Kosovo'), ('Kuwait', 'Kuwait'), ('Kyrgyzstan', 'Kyrgyzstan'), ('Laos', 'Laos'), ('Latvia', 'Latvia'), ('Lebanon', 'Lebanon'), ('Lesotho', 'Lesotho'), ('Liberia', 'Liberia'), ('Libya', 'Libya'), ('Liechtenstein', 'Liechtenstein'), ('Lithuania', 'Lithuania'), ('Luxembourg', 'Luxembourg'), ('Macedonia', 'Macedonia'), ('Madagascar', 'Madagascar'), ('Malawi', 'Malawi'), ('Malaysia', 'Malaysia'), ('Maldives', 'Maldives'), ('Mali', 'Mali'), ('Malta', 'Malta'), ('Marshall Islands', 'Marshall Islands'), ('Mauritania', 'Mauritania'), ('Mauritius', 'Mauritius'), ('Mexico', 'Mexico'), ('Micronesia', 'Micronesia'), ('Moldova', 'Moldova'), ('Monaco', 'Monaco'), ('Mongolia', 'Mongolia'), ('Montenegro', 'Montenegro'), ('Morocco', 'Morocco'), ('Mozambique', 'Mozambique'), ('Myanmar, {Burma}', 'Myanmar, {Burma}'), ('Namibia', 'Namibia'), ('Nauru', 'Nauru'), ('Nepal', 'Nepal'), ('Netherlands', 'Netherlands'), ('New Zealand', 'New Zealand'), ('Nicaragua', 'Nicaragua'), ('Niger', 'Niger'), ('Nigeria', 'Nigeria'), ('Norway', 'Norway'), ('Oman', 'Oman'), ('Pakistan', 'Pakistan'), ('Palau', 'Palau'), ('Panama', 'Panama'), ('Papua New Guinea', 'Papua New Guinea'), ('Paraguay', 'Paraguay'), ('Peru', 'Peru'), ('Philippines', 'Philippines'), ('Poland', 'Poland'), ('Portugal', 'Portugal'), ('Qatar', 'Qatar'), ('Romania', 'Romania'), ('Russian Federation', 'Russian Federation'), ('Rwanda', 'Rwanda'), ('St Kitts & Nevis', 'St Kitts & Nevis'), ('St Lucia', 'St Lucia'), ('Saint Vincent & the Grenadines', 'Saint Vincent & the Grenadines'), ('Samoa', 'Samoa'), ('San Marino', 'San Marino'), ('Sao Tome & Principe', 'Sao Tome & Principe'), ('Saudi Arabia', 'Saudi Arabia'), ('Senegal', 'Senegal'), ('Serbia', 'Serbia'), ('Seychelles', 'Seychelles'), ('Sierra Leone', 'Sierra Leone'), ('Singapore', 'Singapore'), ('Slovakia', 'Slovakia'), ('Slovenia', 'Slovenia'), ('Solomon Islands', 'Solomon Islands'), ('Somalia', 'Somalia'), ('South Africa', 'South Africa'), ('South Sudan', 'South Sudan'), ('Spain', 'Spain'), ('Sri Lanka', 'Sri Lanka'), ('Sudan', 'Sudan'), ('Suriname', 'Suriname'), ('Swaziland', 'Swaziland'), ('Sweden', 'Sweden'), ('Switzerland', 'Switzerland'), ('Syria', 'Syria'), ('Taiwan', 'Taiwan'), ('Tajikistan', 'Tajikistan'), ('Tanzania', 'Tanzania'), ('Thailand', 'Thailand'), ('Togo', 'Togo'), ('Tonga', 'Tonga'), ('Trinidad & Tobago', 'Trinidad & Tobago'), ('Tunisia', 'Tunisia'), ('Turkey', 'Turkey'), ('Turkmenistan', 'Turkmenistan'), ('Tuvalu', 'Tuvalu'), ('Uganda', 'Uganda'), ('Ukraine', 'Ukraine'), ('United Arab Emirates', 'United Arab Emirates'), ('United Kingdom', 'United Kingdom'), ('United States', 'United States'), ('Uruguay', 'Uruguay'), ('Uzbekistan', 'Uzbekistan'), ('Vanuatu', 'Vanuatu'), ('Vatican City', 'Vatican City'), ('Venezuela', 'Venezuela'), ('Vietnam', 'Vietnam'), ('Yemen', 'Yemen'), ('Zambia', 'Zambia'), ('Zimbabwe', 'Zimbabwe'), ] ) class Player(BasePlayer): # ------ Survey -------- age = models.IntegerField(label='How old are you?', min=16, max=125) country = all_countries(label='In which country do you currently reside?') gender = models.StringField( choices=[['Male', 'Male'], ['Female', 'Female'], ['Other', 'Other'], ['Prefer not to disclose', 'Prefer not to disclose']], label='What is your gender?', widget=widgets.RadioSelect, ) education = models.StringField( choices=[['GED equivalent', 'GED equivalent'], ['High school', 'High school'], ['Some college but not degree', 'Some college but not degree'], ['Bachelor degree', 'Bachelor degree'], ['Master/Doctoral or professional degree', 'Master/Doctoral or professional degree'], ['Prefer not to disclose', 'Prefer not to disclose']], label='What is your highest education level?', widget=widgets.RadioSelect, ) employment = models.StringField( choices=[["Full-time employed", "Full-time employed"], ["Part-time employed", "Part-time employed"], ["Not employed", "Not employed"], ["Retired", "Retired"], ["Student", "Student"], ["Other", "Other"]], label="Which of the following categories best describes your employment status?", widget=widgets.RadioSelect, ) income = models.StringField( choices=[['Less than 15,000$', 'Less than 15,000$'], ['15,000$ - 30,000$', '15,000$ - 30,000$'], ['30,000$-45,000$', '30,000$-45,000$'], ['45,000$-60,000$', '45,000$-60,000$'], ['60,000$-75,000$', '60,000$-75,000$'], ['75,000$-90,000$', '75,000$-90,000$'], ['More than 90,000$', 'More than 90,000$']], label='What is your yearly income level?', widget=widgets.RadioSelect, ) # --- Questionnaire Questions ----# # Define task-related questionnaire questions q1_understanding = make_field("I understood the sequence of tasks.") q2_understanding = make_field("I understood what task would come up next.") q3_understanding = make_field("I was unaware of the remaining tasks.") q1_progress = make_field("I feel I made progress with regard to solving the tasks.") q2_progress = make_field(" I feel the task was not progressing.") q3_progress = make_field("I feel I moved quickly to the next task.") q1_control = make_field("It was hard for me to accept the waiting between the tasks.") attention = make_field("Please select 'Disagree'.") q2_control = make_field("I feel that I was in control of the task sequence.") q3_control = make_field("I was able to monitor the sequence of tasks with a great sense of confidence.") q1_satisfaction = make_field("I was satisfied with the performance on this task.") q2_satisfaction = make_field("I was satisfied with how much I learned.") q3_satisfaction = make_field("I enjoyed performing this task.") #Manipulation question: Did they even notice that they have received information? ManipulationCheck = models.IntegerField( label="", choices=[ [1, 'No, I did not receive any such information.'], [2, 'Yes, I received information about (a).'], [3, 'Yes, I received information about (a) and (b).'], [4, 'I don’t remember.'], ], widget=widgets.RadioSelect ) ManipulationCheck2 = models.IntegerField( label="", choices=[ [1, 'Yes.'], [2, 'No.'], [3, 'I do not remember.'], ], widget=widgets.RadioSelect ) experience_with_similar_tasks = models.IntegerField( label="How experienced are you with problem-solving tasks like the ones in this study (counting numbers, transcribing sequences of characters)? ", choices=[ [1, 'Not at all experienced'], [2, 'Slightly experienced'], [3, 'Moderately experienced'], [4, 'Very experienced'], [5, 'Extremely experienced'] ], widget=widgets.RadioSelect ) value_tasks = models.IntegerField( label="How much do you generally value receiving task-related information when solving tasks?", choices=[ [1, 'Not at all'], [2, 'Slightly'], [3, 'Moderately'], [4, 'Very'], [5, 'Very much'] ], widget=widgets.RadioSelect ) satisfaction_experience = models.IntegerField( label="Overall, how satisfied were you with your experience in completing the tasks?", choices=[[1, 'Very dissatisfied'], [2, 'Dissatisfied'], [3, 'Slightly dissatisfied'], [4, 'Neutral'], [5, 'Slightly satisfied'], [6, 'Satisfied'], [7, 'Very satisfied']], widget=widgets.RadioSelect ) abandonment_consideration = models.BooleanField( label="At any point, did you consider abandoning the study?", choices=[[True, 'Yes'], [False, 'No']], ) abandonment_reason = models.LongStringField( label="If yes, what prompted you to consider abandoning the study?", # This makes the field optional blank=True ) skipped = models.BooleanField( label="Did you skip any tasks?", choices=[[True, 'Yes'], [False, 'No']] ) skip_reason = models.LongStringField( label="If no, why did you not skip (any of) the tasks?", # This makes the field optional blank=True ) frustration_level = models.IntegerField( label="", choices=[i for i in range(1, 101)], # Range from 1 to 100 widget=widgets.RadioSelectHorizontal, blank=False ) def offer_error_message(player, value): if player.frustration_level is None: return 'Please indicatre your frustration level' # PAGES class Demographics(Page): form_model = 'player' form_fields = ['experience_with_similar_tasks', 'value_tasks', 'age', 'gender', 'country', 'education', 'employment', 'income'] class Questionnaire(Page): form_model = 'player' @staticmethod def get_form_fields(player: Player): fields = [ "q1_understanding", "q2_understanding", "q3_understanding", "q1_progress", "q2_progress", "q3_progress" ] random.shuffle(fields) return fields class Questionnaire1(Page): form_model = 'player' @staticmethod def get_form_fields(player: Player): fields = [ "q1_control", "q2_control", "q3_control", "q1_satisfaction", "q2_satisfaction", "q3_satisfaction" # add other fields if needed ] random.shuffle(fields) fields.insert(1, "attention") return fields class ManipulationCheck(Page): form_model = 'player' form_fields = ["ManipulationCheck"] class ManipulationCheck2(Page): form_model = 'player' form_fields = ["ManipulationCheck2"] class Questionnaire2(Page): form_model = 'player' @staticmethod def get_form_fields(player: Player): fields = [ "frustration_level", "satisfaction_experience", "abandonment_consideration", "abandonment_reason", "skipped", "skip_reason" # add other fields if needed ] return fields class Thanks(Page): @staticmethod def vars_for_template(player: Player): session = player.session player.participant.finished = True # Convert payoff from points to real-world currency points_to_currency = player.participant.payoff.to_real_world_currency(session) # Add participation fee total_reward = points_to_currency + session.config['participation_fee'] payoff = player.participant.payoff_plus_participation_fee() return { 'total_reward': total_reward, 'points_to_currency': points_to_currency, 'payoff': payoff, } class Results(Page): pass page_sequence = [Questionnaire, Questionnaire1, ManipulationCheck, ManipulationCheck2, Questionnaire2, Demographics, Thanks] #Questionnaire, ManipulationCheck, Questionnaire1, Questionnaire2, Demographics, Thanks