from otree.api import * from settings import SESSION_CONFIG_DEFAULTS author = 'Nathaniel Lawrence, LEMMA, Université Panthéon-Assas' doc = """ This app collects demographic information. """ ### Define constants here, in all-caps class C(BaseConstants): NAME_IN_URL = 'q' PLAYERS_PER_GROUP = None NUM_ROUNDS = 1 NUM_QUESTIONS = 23 + 1 PARTICIPATION_FEE = SESSION_CONFIG_DEFAULTS['participation_fee'] class Subsession(BaseSubsession): pass class Group(BaseGroup): pass class Player(BasePlayer): ## Session indices day = models.IntegerField() app_sequence = models.IntegerField() inf_sequence = models.IntegerField() intervention = models.IntegerField() ### choices = [[value,label],[value,label]] age = models.IntegerField( label='What is your age?' ) gender = models.BooleanField( choices=[[False, 'Male'], [True, 'Female']], label='What is your gender?', widget=widgets.RadioSelect, ) educationLevel = models.IntegerField( choices = [[1,'High school'],[2,'Undergraduate'],[3,'Masters'],[4,'Doctorate'],[0,'I have not completed high school'],[5,'I do not know']], label='What level of education have you completed?', widget=widgets.RadioSelect ) employmentStatus = models.IntegerField( choices = [[1,'Employed'],[0,'Unemployed'],[2,'Student'],[3,'Retired'],[4,'I do not know']], label='What is your current employment status?', widget=widgets.RadioSelect ) financialStatusIncome = models.FloatField( label='What is your monthly income? (€)', min=0 ) financialStatusSavings_1 = models.BooleanField( choices = [[True,'Yes'],[False, 'No']], label='Do you feel you are currently able to save money?', widget=widgets.RadioSelect ) financialStatusSavings_2 = models.FloatField( label='On average, how much money do you keep in your checking account? (€)', min=0 ) financialStatusDebt_1 = models.BooleanField( choices = [[True,'Yes'],[False, 'No']], label='Did you borrow money in the past twelve (12) months other than for a mortgage?', min=0 ) financialStatusDebt_2 = models.FloatField( label='Approximately how much money did you borrow in the past twelve (12) months other than for a mortgage? (€)', min=0 ) ### multiple checkboxes --> see Demographics.html and Multiple Choice bookmark stocks = models.BooleanField(blank=True, initial=False) mutualFunds = models.BooleanField(blank=True, initial=False) bonds = models.BooleanField(blank=True, initial=False) savingsAccounts = models.BooleanField(blank=True, initial=False) lifeInsurance = models.BooleanField(blank=True, initial=False) retirementAccounts = models.BooleanField(blank=True, initial=False) crypto = models.BooleanField(blank=True, initial=False) ### investment preferences and expectations (Arrondel & Masson, 2014) invP_1 = models.IntegerField( choices = [[1,'Placer l’essentiel de vos économies sur des placements risqués, mais qui peuvent rapporter beaucoup',], [2,'Placer une part importante de vos économies sur des placements risqués, mais qui peuvent rapporter beaucoup, et le reste sur des placements sûrs'], [3,'Placer une petite partie de vos économies sur des placements risqués, mais qui peuvent rapporter beaucoup, et le reste sur des placements sûrs'], [4,'Placer toutes vos économies sur des placements sûrs']], label = 'En matière de placements financiers, que préférez-vous ?', widget = widgets.RadioSelect ) invP_2_assurance = models.IntegerField( choices = [[1,'''Plus d'argent'''],[-1,'''Moins d'argent'''],[0,'''Autant d'argent'''],[9,'''Pas concerné''']], label = 'Assurance vie', widget = widgets.RadioSelect ) invP_2_logement = models.IntegerField( choices = [[1,'''Plus d'argent'''],[-1,'''Moins d'argent'''],[0,'''Autant d'argent'''],[9,'''Pas concerné''']], label = 'Épargne logement', widget = widgets.RadioSelect ) invP_2_livret = models.IntegerField( choices = [[1,'''Plus d'argent'''],[-1,'''Moins d'argent'''],[0,'''Autant d'argent'''],[9,'''Pas concerné''']], label = 'Livrets d’épargne', widget = widgets.RadioSelect ) invP_2_fonds = models.IntegerField( choices = [[1,'''Plus d'argent'''],[-1,'''Moins d'argent'''],[0,'''Autant d'argent'''],[9,'''Pas concerné''']], label = 'Fonds communs de placement', widget = widgets.RadioSelect ) invP_2_actions = models.IntegerField( choices = [[1,'''Plus d'argent'''],[-1,'''Moins d'argent'''],[0,'''Autant d'argent'''],[9,'''Pas concerné''']], label = 'Actions', widget = widgets.RadioSelect ) invP_3 = models.IntegerField( choices = [[0,'Dépenser tout',], [1,'Placer l’essentiel de vos économies sur des placements risqués, mais qui peuvent rapporter beaucoup'], [2,'Placer une part importante de vos économies sur des placements risqués, mais qui peuvent rapporter beaucoup, et le reste sur des placements sûrs'], [3,'Placer une petite partie de vos économies sur des placements risqués, mais qui peuvent rapporter beaucoup, et le reste sur des placements sûrs'], [4,'Placer toutes vos économies sur des placements sûrs']], label = 'Imagine you receive 500.000€, what would you do with this money? / Imaginez que vous recevez 500.000€. Que faites-vous avec cet argent ?', widget = widgets.RadioSelect ) # PAGES class Questionnaire_Intro(Page): counter_questions = 0 class Questionnaire_1(Page): form_model = 'player' form_fields = [ 'age', 'gender', 'educationLevel', 'employmentStatus', 'financialStatusIncome', 'financialStatusSavings_1', 'financialStatusSavings_2', 'financialStatusDebt_1', 'financialStatusDebt_2' ] counter_questions = Questionnaire_Intro.counter_questions + 1 ## For progress bars @staticmethod def vars_for_template(player: Player): return dict( percentage=round(Questionnaire_1.counter_questions / C.NUM_QUESTIONS * 100,) ) @staticmethod def error_message(player: Player, values): solutions = dict( age=18 ) error_messages = dict( age='You must be 18 years of age or older to participate.', a1='Please enter a valid age in years.' ) for field_name in solutions: if values[field_name] < solutions[field_name]: error_messages = error_messages[field_name] return error_messages if values[field_name] > 99: error_messages = error_messages['a1'] return error_messages class Questionnaire_2(Page): form_model = 'player' form_fields =['stocks','mutualFunds','bonds','savingsAccounts','lifeInsurance','retirementAccounts','crypto'] counter_questions = Questionnaire_1.counter_questions + len(Questionnaire_1.form_fields) ## For progress bars @staticmethod def vars_for_template(player: Player): return dict( percentage=round(Questionnaire_2.counter_questions / C.NUM_QUESTIONS * 100,) ) class Questionnaire_3(Page): form_model = 'player' form_fields =['invP_1'] counter_questions = Questionnaire_2.counter_questions + len(Questionnaire_2.form_fields) ## For progress bars @staticmethod def vars_for_template(player: Player): return dict( percentage=round(Questionnaire_3.counter_questions / C.NUM_QUESTIONS * 100,) ) class Questionnaire_4(Page): form_model = 'player' form_fields =['invP_2_assurance','invP_2_logement','invP_2_livret','invP_2_fonds','invP_2_actions'] counter_questions = Questionnaire_3.counter_questions + len(Questionnaire_3.form_fields) ## For progress bars @staticmethod def vars_for_template(player: Player): return dict( percentage=round(Questionnaire_4.counter_questions / C.NUM_QUESTIONS * 100,) ) class Questionnaire_5(Page): form_model = 'player' form_fields =['invP_3'] counter_questions = Questionnaire_4.counter_questions + len(Questionnaire_4.form_fields) ## For progress bars @staticmethod def vars_for_template(player: Player): return dict( percentage=round(Questionnaire_5.counter_questions / C.NUM_QUESTIONS * 100,) ) class Results(Page): counter_questions = Questionnaire_5.counter_questions + len(Questionnaire_5.form_fields) ## For progress bars @staticmethod def vars_for_template(player: Player): return dict( percentage=round(Results.counter_questions / C.NUM_QUESTIONS * 100,) ) page_sequence = [ Questionnaire_Intro, Questionnaire_1, Questionnaire_2, Questionnaire_3, Questionnaire_4, Questionnaire_5, Results ]