from otree.api import * author = 'Alistair Munro, Fitawhidan Nashuha, and Gerald Ezra Charles' doc = """ Post-Session Survey (bilingual: English / Indonesian). Language is chosen from the SESSION CONFIG key 'language' ('en' or 'id'), the same source used by the coin-flip game app, so the entire session runs in one language. Pattern: every label / choice set is returned by a method on Player that branches on the language. No runtime mutation of class-level field objects (that approach is not thread-safe across concurrent participants). """ class C(BaseConstants): NAME_IN_URL = 'f_Post_Game_Survey' PLAYERS_PER_GROUP = None NUM_ROUNDS = 1 class Subsession(BaseSubsession): pass class Group(BaseGroup): pass # =========================================================================== # LANGUAGE HELPERS — single source of truth: the session config. # Matches get_language() in the coin-flip game app. # =========================================================================== def get_language(player): return player.session.config.get('language', 'en') == 'en' class Player(BasePlayer): # ======================================================================= # DYNAMIC LABELS & CHOICES # Defined BEFORE the fields so each `choices=` reference resolves. # `{field}_label` is auto-picked-up by oTree the same way the coin game # uses `bet_amount_label`. (Verify labels render in your oTree version / # templates; if your templates pass labels explicitly, these still work.) # ======================================================================= # ------------------------- Demographics ------------------------------- def HH_Decision_Maker_choices(player): if get_language(player): return ( [ ['Me', 'Myself'], ['Spouse', 'My spouse'], ['Father', 'My father'], ['Mother', 'My mother'], ['Sister', 'My sister'], ['Brother', 'My brother'], ['Grandfather', 'My grandfather'], ['Grandmother', 'My grandmother'], ['Uncle', 'My uncle'], ['Aunt', 'My aunt'], ['Others', 'Others'], ], ) return ( [ ['Me', 'Saya sendiri'], ['Spouse', 'Pasangan saya'], ['Father', 'Ayah saya'], ['Mother', 'Ibu saya'], ['Sister', 'Saudara perempuan saya'], ['Brother', 'Saudara laki-laki saya'], ['Grandfather', 'Kakek saya'], ['Grandmother', 'Nenek saya'], ['Uncle', 'Paman saya'], ['Aunt', 'Bibi saya'], ['Others', 'Lainnya'] ] ) def Religion_choices(player): if get_language(player): return ( [ ['Islam', 'Islam'], ['Catholic', 'Catholic'], ['Christian', 'Christian'], ['Hindu', 'Hindu'], ['Buddha', 'Buddhism'], ['Konghucu/Confucius', 'Confucianism'], ['Others', 'Others'], ], ) return( [ ['Islam', 'Islam'], ['Catholic', 'Katolik'], ['Christian', 'Kristen'], ['Hindu', 'Hindu'], ['Buddha', 'Buddha'], ['Konghucu/Confucius', 'Konghucu'], ['Others', 'Lainnya'] ] ) # ------------------------- Smoking / Alcohol -------------------------- def Smoke_Cigarettes_choices(player): if get_language(player): return ( [[True, 'Yes, I smoke'], [False, 'No, I do not smoke']] ) return( [ [True, 'Ya, saya merokok'], [False, 'Tidak, saya tidak merokok'] ] ) def Smoke_Ecig_choices(player): if get_language(player): return ( [ [True, 'Yes'], [False, 'No'] ] ) return( [ [True, 'Ya'], [False, 'Tidak'] ] ) def Smoke_Chew_choices(player): if get_language(player): return ( [ [True, 'Yes'], [False, 'No'] ] ) return ( [ [True, 'Ya'], [False, 'Tidak'] ] ) def Smoke_Hookah_choices(player): if get_language(player): return ( [ [True, 'Yes'], [False, 'No'] ] ) return ( [ [True, 'Ya'], [False, 'Tidak'] ] ) def Drink_Alcohol_choices(player): if get_language(player): return ( [ ['No', 'No, I do not consume alcohol'], ['Yes', 'Yes, I consume alcohol'], ['Used to', 'I used to consume alcohol but no longer do'], ]) # TODO(ID) return( [ ['No', 'Tidak, saya tidak mengonsumsi alkohol'], ['Yes', 'Ya, saya mengonsumsi alkohol'], ['Used to', 'Saya dulu mengonsumsi alkohol tetapi sekarang tidak'], ] ) # ------------------------- Debt Profile ------------------------------- # Reusable choice sets (English only for now). def _yes_no_refused(player): return tr_choices(player, [['Yes', 'Yes'], ['No', 'No'], ['Refused', 'I prefer not to answer']]) # TODO(ID) def Debt_A_choices(player): if get_language(player): return( [ ['Yes', 'Yes'], ['No', 'No'], ['Refused', 'I prefer not to answer'] ] ) return( [ ['Yes', 'Ya'], ['No', 'Tidak'], ['Refused', 'Saya menolak menjawab'] ] ) def Debt_B_choices(player): if get_language(player): return ( [ ['Yes', 'Yes'], ['No', 'No'], ['Refused', 'I prefer not to answer'] ] ) return ( [ ['Yes', 'Ya'], ['No', 'Tidak'], ['Refused', 'Saya menolak menjawab'] ] ) def Debt_Online_Past_choices(player): if get_language(player): return ( [ ['Yes', 'Yes'], ['No', 'No'], ['Refused', 'I prefer not to answer'] ] ) return ( [ ['Yes', 'Ya'], ['No', 'Tidak'], ['Refused', 'Saya menolak menjawab'] ] ) def Debt_Paylater_Credit_Past_choices(player): if get_language(player): return ( [ ['Yes', 'Yes'], ['No', 'No'], ['Refused', 'I prefer not to answer'] ] ) return ( [ ['Yes', 'Ya'], ['No', 'Tidak'], ['Refused', 'Saya menolak menjawab'] ] ) def Debt_Family_Past_choices(player): if get_language(player): return ( [ ['Yes', 'Yes'], ['No', 'No'], ['Refused', 'I prefer not to answer'] ] ) return ( [ ['Yes', 'Ya'], ['No', 'Tidak'], ['Refused', 'Saya menolak menjawab'] ] ) def Debt_Online_choices(player): if get_language(player): return ( [ ['Yes', 'Yes'], ['No', 'No'], ['Refused', 'I prefer not to answer'] ] ) return ( [ ['Yes', 'Ya'], ['No', 'Tidak'], ['Refused', 'Saya menolak menjawab'] ] ) def Debt_Paylater_Credit_choices(player): if get_language(player): return ( [ ['Yes', 'Yes'], ['No', 'No'], ['Refused', 'I prefer not to answer'] ] ) return ( [ ['Yes', 'Ya'], ['No', 'Tidak'], ['Refused', 'Saya menolak menjawab'] ] ) def Debt_Family_choices(player): if get_language(player): return ( [ ['Yes', 'Yes'], ['No', 'No'], ['Refused', 'I prefer not to answer'] ] ) return ( [ ['Yes', 'Ya'], ['No', 'Tidak'], ['Refused', 'Saya menolak menjawab'] ] ) def Debt_Friend_choices(player): if get_language(player): return ( [ ['Yes', 'Yes'], ['No', 'No'], ['Refused', 'I prefer not to answer'] ] ) return ( [ ['Yes', 'Ya'], ['No', 'Tidak'], ['Refused', 'Saya menolak menjawab'] ] ) def Debt_Private_Lender_choices(player): if get_language(player): return ( [ ['Yes', 'Yes'], ['No', 'No'], ['Refused', 'I prefer not to answer'] ] ) return ( [ ['Yes', 'Ya'], ['No', 'Tidak'], ['Refused', 'Saya menolak menjawab'] ] ) def Debt_Health_choices(player): if get_language(player): return ( [ ['Yes', 'Yes'], ['No', 'No'], ['Refused', 'I prefer not to answer'] ] ) return ( [ ['Yes', 'Ya'], ['No', 'Tidak'], ['Refused', 'Saya menolak menjawab'] ] ) def Debt_Food_choices(player): if get_language(player): return ( [ ['Yes', 'Yes'], ['No', 'No'], ['Refused', 'I prefer not to answer'] ] ) return ( [ ['Yes', 'Ya'], ['No', 'Tidak'], ['Refused', 'Saya menolak menjawab'] ] ) def Debt_Capital_choices(player): if get_language(player): return ( [ ['Yes', 'Yes'], ['No', 'No'], ['Refused', 'I prefer not to answer'] ] ) return ( [ ['Yes', 'Ya'], ['No', 'Tidak'], ['Refused', 'Saya menolak menjawab'] ] ) def Desperation_Finance_choices(player): if get_language(player): return ( [ ['True', 'Yes, I feel financially pressured'], ['False', 'No, I do not feel financially pressured'], ['Refused', 'I prefer not to answer'], ]) return( [ ['True', 'Ya, saya merasa terdesak secara finansial'], ['False', 'Tidak, saya tidak merasa terdesak secara finansial'], ['Refused', 'Saya menolak menjawab'] ] ) def Quick_Money_choices(player): if get_language(player): return ( [ ['Yes', 'Yes'], ['No', 'No'], ['Likely', 'Not sure, but likely'], ['Unlikely', 'Not sure, but unlikely'], ['Refused', 'I prefer not to answer'], ] ) return( [ ['Yes', 'Ya'], ['No', 'Tidak'], ['Likely', 'Saya tidak yakin, tetapi kemungkinan akan melakukannya'], ['Unlikely', 'Saya tidak yakin, tetapi kemungkinan tidak akan melakukannya'], ['Refused', 'Saya menolak menjawab'], ] ) # ------------------- World Bank Financial Literacy -------------------- # NOTE: validated instrument — use the official Indonesian wording, not a # paraphrase. Needs verification. def WB_FinLit_1_choices(player): if get_language(player): return ( [ ['1', 'I have no knowledge and skills'], ['2', 'My knowledge and skills are inadequate'], ['3', 'My knowledge and skills are sufficient'], ['4', 'My knowledge and skills are good'], ['5', 'My knowledge and skills are very good'], ['99', 'I do not know'], ]) return( [ ['1', 'Saya tidak memiliki pengetahuan dan keterampilan'], ['2', 'Pengetahuan dan keterampilan saya kurang memadai'], ['3', 'Pengetahuan dan keterampilan saya cukup'], ['4', 'Pengetahuan dan keterampilan saya baik'], ['5', 'Pengetahuan dan keterampilan saya sangat baik'], ['99', 'Saya tidak tahu'], ] ) def WB_FinLit_2_choices(player): if get_language(player): return ( [ ['1', 'More than now'], ['2', 'The same as now'], ['3', 'Less than now'], ['99', 'I do not know'], ]) return( [ ['1', 'Lebih banyak dari sekarang'], ['2', 'Sama seperti sekarang'], ['3', 'Lebih sedikit dari sekarang'], ['99', 'Saya tidak tahu'], ] ) def WB_FinLit_3_choices(player): if get_language(player): return ( [ ['1', 'More than Rp12,000,000'], ['2', 'Exactly Rp12,000,000'], ['3', 'Less than Rp12,000,000'], ['99', 'I do not know'], ]) return( [ ['1', 'Lebih dari Rp12.000.000'], ['2', 'Tepat Rp12.000.000'], ['3', 'Kurang dari Rp12.000.000'], ['99', 'Saya tidak tahu'], ] ) def WB_FinLit_4_choices(player): if get_language(player): return ( [ ['1', 'Rp150,000 discount'], ['2', 'Both are the same'], ['3', '10% discount'], ['99', 'I do not know'], ] ) return( [ ['1', 'Diskon Rp150.000'], ['2', 'Keduanya sama'], ['3', 'Diskon 10%'], ['99', 'Saya tidak tahu'], ] ) def WB_FinLit_5_choices(player): if get_language(player): return ( [ ['1', '3%'], ['2', '6%'], ['3', '9%'], ['4', '12%'], ['99', 'I do not know'], ] ) return( [ ['1', '3%'], ['2', '6%'], ['3', '9%'], ['4', '12%'], ['99', 'Saya Tidak tahu'], ] ) # ----------------------- OECD Financial Literacy ---------------------- def OECD_FinLit_1_choices(player): if get_language(player): return ( [ ['1', 'More than now'], ['2', 'The same'], ['3', 'Less'], ['4', 'Depends on goods'], ['99', 'I do not know'], ]) return( [ ['1', 'Lebih banyak dari sekarang'], ['2', 'Sama seperti sekarang'], ['3', 'Lebih sedikit dari sekarang'], ['4', 'Tergantung pada jenis barang'], ['99', 'Saya tidak tahu'], ] ) def OECD_FinLit_2_choices(player): if get_language(player): return ( [ ['1', 'Rp1,200,000'], ['2', 'Rp1,020,000'], ['3', 'Rp1,100,000'], ['99', 'I do not know'] ] ) return( [ ['1', 'Rp1.200.000'], ['2', 'Rp1.020.000'], ['3', 'Rp1.100.000'], ['99', 'Saya tidak tahu'] ] ) def OECD_FinLit_3_choices(player): if get_language(player): return ( [ ['1', 'Rp1,200,000'], ['2', 'Rp1,020,000'], ['3', 'Rp1,100,000'], ['99', 'I do not know'] ] ) return( [ ['1', 'Rp1,200,000'], ['2', 'Rp1,020,000'], ['3', 'Rp1,100,000'], ['99', 'Saya tidak tahu'] ] ) def OECD_FinLit_4_choices(player): if get_language(player): return ( [ ['True', 'True'], ['False', 'False'], ['99', 'I do not know'] ] ) return( [ ['True', 'Benar'], ['False', 'Salah'], ['99', 'Saya tidak tahu'] ] ) def OECD_FinLit_5_choices(player): if get_language(player): return ( [ ['True', 'True'], ['False', 'False'], ['99', 'I do not know'] ] ) return ( [ ['True', 'Benar'], ['False', 'Salah'], ['99', 'Saya tidak tahu'] ] ) # OECD_FinLit_6 — Indonesian available. def OECD_FinLit_6_label(player): return tr(player, 'True or False: Risk in stock investments can be reduced through ' 'diversification.', 'Benar atau Salah: Risiko investasi saham dapat dikurangi melalui ' 'diversifikasi.', ) def OECD_FinLit_6_choices(player): if get_language(player): return ( [ ['True', 'True'], ['False', 'False'], ['99', 'I do not know'] ] ) return( [ ['True', 'Benar'], ['False', 'Salah'], ['99', 'Saya tidak tahu'] ] ) def OECD_Time_Value_choices(player): if get_language(player): return ( [ ['1', 'More goods'], ['2', 'Almost the same amount'], ['3', 'Less goods'], ['4', 'Depends on the type of goods'], ['5', 'Depends on price changes'], ['99', 'I do not know'], ]) return( [ ['1', 'Lebih banyak barang'], ['2', 'Hampir sama'], ['3', 'Lebih sedikit barang'], ['4', 'Tergantung jenis barang'], ['5', 'Tergantung perubahan harga'], ['99', 'Saya tidak tahu'], ], ) def OECD_Diversification_choices(player): if get_language(player): return ( [ ['True', 'True'], ['False', 'False'], ['99', 'I do not know'] ] ) return( [ ['True', 'Benar'], ['False', 'Salah'], ['99', 'Saya tidak tahu'] ] ) def OECD_RisknReturn_choices(player): if get_language(player): return ( [ ['True', 'True'], ['False', 'False'], ['99', 'I do not know'] ] ) return( [ ['True', 'Benar'], ['False', 'Salah'], ['99', 'Saya tidak tahu'] ] ) def OECD_Interest_Compound_choices(player): if get_language(player): return ( [ ['1', 'More than Rp110,000'], ['2', 'Exactly Rp110,000'], ['3', 'Less than Rp110,000'], ['4', 'Cannot be determined'], ['99', 'I do not know'], ] ) return( [ ['1', 'Lebih dari Rp110,000'], ['2', 'Rp110,000'], ['3', 'Kurang dariRp110,000'], ['4', 'Tidak dapat ditentukan'], ['99', 'Saya tidak tahu'], ] ) def OECD_Diversification2_choices(player): if get_language(player): return ( [ ['True', 'True'], ['False', 'False'], ['99', 'I do not know'] ] ) return ( [ ['True', 'Benar'], ['False', 'Salah'], ['99', 'Saya tidak tahu'] ] ) # ----------------------- General Risk Preference ---------------------- # General_Risk_Q — Indonesian available. def General_Risk_Q_choices(player): if get_language(player): return ( [ ['1', 'Very unwilling'], ['2', 'Unwilling'], ['3', 'Somewhat willing'], ['4', 'Willing'], ['5', 'Very willing'], ], ) return( [ ['1', 'Sangat tidak bersedia'], ['2', 'Tidak bersedia'], ['3', 'Cukup bersedia'], ['4', 'Bersedia'], ['5', 'Sangat bersedia'], ], ) # ======================================================================= # FIELD DEFINITIONS # label='' (filled by {field}_label); choices reference the methods above. # ======================================================================= # ---- Demographics ---- def education_choices(player): if get_language(player): return ( [ ['1', 'Primary School'], ['2', 'Junior High School'], ['3', 'Senior High School / Vocational High School'], ['4', 'Vocational School / Diploma (D1/D2/D3)'], ['5', "Bachelor's Degree (S1 / D4)"], ['6', 'Master\'s Degree (S2)'], ['7', 'Doctoral Degree (S3)'], ['95', 'Do not know / Prefer not to answer'], ['99', 'Never attended school'], ], ) return ( [ ['1', 'Sekolah Dasar'], ['2', 'Sekolah Menengah Pertama'], ['3', 'Sekolah Menengah Atas / SMK'], ['4', 'Sekolah Kejuruan / Diploma (D1/D2/D3)'], ['5', 'Sarjana (S1 / D4)'], ['6', 'Magister (S2)'], ['7', 'Doktor (S3)'], ['95', 'Tidak tahu / Tidak ingin menjawab'], ['99', 'Tidak pernah bersekolah'], ] ) education = models.StringField(widget=widgets.RadioSelect, choices=education_choices, label='') HH_Number = models.IntegerField(label='') HH_5yo = models.IntegerField(min=0, label='') HH_Decision_Maker = models.StringField(widget=widgets.RadioSelect, choices=HH_Decision_Maker_choices, label='') Religion = models.StringField(widget=widgets.RadioSelect, choices=Religion_choices, label='') # ---- Smoking / Alcohol ---- Smoke_Cigarettes = models.BooleanField(widget=widgets.RadioSelect, choices=Smoke_Cigarettes_choices, label='') Smoke_Ecig = models.BooleanField(widget=widgets.RadioSelect, choices=Smoke_Ecig_choices, label='') Smoke_Chew = models.BooleanField(widget=widgets.RadioSelect, choices=Smoke_Chew_choices, label='') Smoke_Hookah = models.BooleanField(widget=widgets.RadioSelect, choices=Smoke_Hookah_choices, label='') Drink_Alcohol = models.StringField(widget=widgets.RadioSelect, choices=Drink_Alcohol_choices, label='') # ---- Debt Profile ---- Debt_A = models.StringField(widget=widgets.RadioSelect, choices=Debt_A_choices, label='') Debt_B = models.StringField(widget=widgets.RadioSelect, choices=Debt_B_choices, label='') Debt_Online_Past = models.StringField(widget=widgets.RadioSelectHorizontal, choices=Debt_Online_Past_choices, label='') Debt_Paylater_Credit_Past = models.StringField(widget=widgets.RadioSelectHorizontal, choices=Debt_Paylater_Credit_Past_choices, label='') Debt_Family_Past = models.StringField(widget=widgets.RadioSelectHorizontal, choices=Debt_Family_Past_choices, label='') Debt_Online = models.StringField(widget=widgets.RadioSelect, choices=Debt_Online_choices, label='') Debt_Paylater_Credit = models.StringField(widget=widgets.RadioSelect, choices=Debt_Paylater_Credit_choices, label='') Debt_Family = models.StringField(widget=widgets.RadioSelect, choices=Debt_Family_choices, label='') Debt_Friend = models.StringField(widget=widgets.RadioSelect, choices=Debt_Friend_choices, label='') Debt_Private_Lender = models.StringField(widget=widgets.RadioSelect, choices=Debt_Private_Lender_choices, label='') Debt_Health = models.StringField(widget=widgets.RadioSelect, choices=Debt_Health_choices, label='') Debt_Food = models.StringField(widget=widgets.RadioSelect, choices=Debt_Food_choices, label='') Debt_Capital = models.StringField(widget=widgets.RadioSelect, choices=Debt_Capital_choices, label='') Desperation_Finance = models.StringField(widget=widgets.RadioSelect, choices=Desperation_Finance_choices, label='') Quick_Money = models.StringField(widget=widgets.RadioSelect, choices=Quick_Money_choices, label='') # ---- World Bank Financial Literacy ---- WB_FinLit_1 = models.StringField(widget=widgets.RadioSelect, choices=WB_FinLit_1_choices, label='') WB_FinLit_2 = models.StringField(widget=widgets.RadioSelect, choices=WB_FinLit_2_choices, label='') WB_FinLit_3 = models.StringField(widget=widgets.RadioSelect, choices=WB_FinLit_3_choices, label='') WB_FinLit_4 = models.StringField(widget=widgets.RadioSelect, choices=WB_FinLit_4_choices, label='') WB_FinLit_5 = models.StringField(widget=widgets.RadioSelect, choices=WB_FinLit_5_choices, label='') # ---- OECD Financial Literacy ---- OECD_FinLit_1 = models.StringField(widget=widgets.RadioSelect, choices=OECD_FinLit_1_choices, label='') OECD_FinLit_2 = models.StringField(widget=widgets.RadioSelect, choices=OECD_FinLit_2_choices, label='') OECD_FinLit_3 = models.StringField(widget=widgets.RadioSelect, choices=OECD_FinLit_3_choices, label='') OECD_FinLit_4 = models.StringField(widget=widgets.RadioSelect, choices=OECD_FinLit_4_choices, label='') OECD_FinLit_5 = models.StringField(widget=widgets.RadioSelect, choices=OECD_FinLit_5_choices, label='') OECD_FinLit_6 = models.StringField(widget=widgets.RadioSelect, choices=OECD_FinLit_6_choices, label='') OECD_FinLit_7 = models.IntegerField(min=0, max=10_000_000, label='') # ---- OECD Additional Literacy Measures ---- OECD_Division = models.IntegerField(min=0, max=10_000_000, label='') OECD_Time_Value = models.StringField(widget=widgets.RadioSelect, choices=OECD_Time_Value_choices, label='') OECD_Diversification = models.StringField(widget=widgets.RadioSelect, choices=OECD_Diversification_choices, label='') OECD_RisknReturn = models.StringField(widget=widgets.RadioSelect, choices=OECD_RisknReturn_choices, label='') # ---- DROPPED in the 2nd file — confirm whether to keep ---- OECD_Interest = models.IntegerField(min=0, max=10_000_000, label='') OECD_Interest_Compound = models.StringField(widget=widgets.RadioSelect, choices=OECD_Interest_Compound_choices, label='') OECD_Interest_Loan = models.IntegerField(min=0, max=10_000_000, label='') OECD_Diversification2 = models.StringField(widget=widgets.RadioSelect, choices=OECD_Diversification2_choices, label='') # ---- General Risk Preference ---- General_Risk_Q = models.StringField(widget=widgets.RadioSelect, choices=General_Risk_Q_choices, label='')