import random from otree.api import * author = 'Alistair Munro, Fitawhidan Nashuha, and Gerald Ezra Charles' doc = """ Second Session Survey. """ class C(BaseConstants): NAME_IN_URL = 'Ses2_a_Treatment' PLAYERS_PER_GROUP = None NUM_ROUNDS = 1 class Subsession(BaseSubsession): pass class Group(BaseGroup): pass def creating_session(subsession: Subsession): for player in subsession.get_players(): if subsession.round_number == 1: condition = random.choice([ 'control', 'treatment_1', 'treatment_2', 'treatment_3', 'treatment_4', ]) player.participant.vars['condition'] = condition player.condition = condition def get_language(player): return player.session.config.get('language', 'en') == 'en' # =========================================================================== # Field-customization functions — MODULE LEVEL (required by the no-self # format). oTree resolves `{field}_choices` via getattr on this module, so # these must live here, not inside class Player. # =========================================================================== def Comprehension_Treatment_3_choices(player): if get_language(player): return [ [1, 'A Good Investment Strategy.'], [2, "Probability and the Gambler's Fallacy."], [3, 'How to Take Opportunities on the Path to Success.'], [4, 'Financial Management According to Experts.'], [5, 'The Concept of "The House Always Wins" in Gambling.'], ] return [ [1, 'Metode investasi yang baik.'], [2, 'Probabilitas dan Gambling Fallacy.'], [3, 'Cara mengambil kesempatan menuju kesuksesan.'], [4, 'Pengelolaan finansial menurut para ahli.'], [5, "'Bandar Selalu Menang' dalam dunia perjudian."], ] def Comprehension_Treatment_4_choices(player): if get_language(player): return [ [1, 'A Good Investment Strategy.'], [2, "Probability and the Gambler's Fallacy."], [3, 'How to Take Opportunities on the Path to Success.'], [4, 'Financial Management According to Experts.'], [5, 'The Concept of "The House Always Wins" in Gambling.'], ] return [ [1, 'Metode investasi yang baik.'], [2, 'Probabilitas dan Gambling Fallacy.'], [3, 'Cara mengambil kesempatan menuju kesuksesan.'], [4, 'Pengelolaan finansial menurut para ahli.'], [5, "'Bandar Selalu Menang' dalam dunia perjudian."], ] def continue_session_choices(player): if get_language(player): return [ [True, 'Yes, I wish to continue participating in this study.'], [False, "No, I wish to withdraw from this study."], ] return [ [True, "Ya, saya bersedia melanjutkan partisipasi dalam penelitian ini."], [False, "Tidak, saya ingin mengundurkan diri dari penelitian ini."], ] def confirm_withdrawal_choices(player): if get_language(player): return [ [True, 'Yes, I am sure. I wish to withdraw from this study.'], [False, "No, I changed my mind. I wish to continue participating in this study."], ] return [ [True, "Ya, saya yakin. Saya ingin mengundurkan diri dari penelitian ini."], [False, "Tidak, saya berubah pikiran. Saya bersedia melanjutkan partisipasi dalam penelitian ini."], ] def continue_session_after_treatment_choices(player): if get_language(player): return [ [True, 'Yes, I wish to continue participating in this study.'], [False, "No, I wish to withdraw from this study."], ] return [ [True, "Ya, saya bersedia melanjutkan partisipasi dalam penelitian ini."], [False, "Tidak, saya ingin mengundurkan diri dari penelitian ini."], ] def confirm_withdrawal_after_treatment_choices(player): if get_language(player): return [ [True, 'Yes, I am sure. I wish to withdraw from this study.'], [False, "No, I changed my mind. I wish to continue participating in this study."], ] return [ [True, "Ya, saya yakin. Saya ingin mengundurkan diri dari penelitian ini."], [False, "Tidak, saya berubah pikiran. Saya bersedia melanjutkan partisipasi dalam penelitian ini."], ] def Play_Gacha_choices(player): if get_language(player): return [ ['1', 'Yes, I play Games with Random Reward Mechanics (gacha, loot boxes, mystery boxes, card packs, or capsule mechanics).'], ['2', "No, I DO NOT play Games with Random Reward Mechanics (gacha, loot boxes, mystery boxes, card packs, or capsule mechanics)."], ['3', 'I am not sure'], ] return [ ['1', "Ya, saya bermain permainan dengan mekanisme hadiah random (Random Reward Mechanics; seperti gacha, loot boxes, mystery boxes, card packs, atau capsule)."], ['2', "Tidak, saya TIDAK bermain permainan dengan mekanisme hadiah random (Random Reward Mechanics; seperti gacha, loot boxes, mystery boxes, card packs, atau capsule)."], ['3', 'Saya tidak yakin'] ] def Play_Games_choices(player): if get_language(player): return [ [True, 'Yes, I play Games'], [False, 'No, I do not play Games'] ] return[ [True, 'Ya, saya bermain games'], [False, 'Tidak, saya tidak bermain games'] ] def Frequency_Obtain_Gacha_choices(player): if get_language(player): return [ 'Less than once per month', '1–3 times per month', '2–4 times per week', 'Almost every day' ] return[ 'Kurang dari 1x per bulan', '1-3 kali per bulan', '2-4 kali per minggu', 'Hampir setiap hari' ] def SpentMoney_Gacha_choices(player): if get_language(player): return [ [True, 'Yes, I have'], [False, 'No, I never'] ] return[ [True, 'Ya, pernah'], [False, 'Tidak pernah'] ] def Enjoy_Gacha_choices(player): if get_language(player): return [ [1, 'Not enjoyable at all'], [2, 'Mostly un-enjoyable'], [3, 'Slightly un-enjoyable'], [4, 'Neither enjoyable nor un-enjoyable'], [5, 'Slightly enjoyable'], [6, 'Enjoyable'], [7, 'Extremely enjoyable'], ] return[ [1, 'Sangat tidak menyenangkan'], [2, 'Tidak menyenangkan'], [3, 'Agak tidak menyenangkan'], [4, 'Biasa-biasa saja'], [5, 'Agak menyenangkan'], [6, 'Menyenangkan'], [7, 'Sangat menyenangkan'], ] def HowMuch_Spent_Money_Gacha_choices(player): if get_language(player): return[ [1, 'Less than Rp100,000'], [2, 'Rp100,001 - Rp150,000'], [3, 'Rp150,001 - Rp250,000'], [4, 'Rp250,001 - Rp500,000'], [5, 'Rp500,001 - Rp750,000'], [6, 'Rp750,001 - Rp1,000,000'], [7, 'Rp1,000,001 - Rp1,500,000'], [8, 'Rp1,500,001 - Rp1,750,000'], [9, 'Rp1,750,001 - Rp2,500,000'], [10, 'Rp2,500,001 - Rp3,000,000'], [11, 'More than Rp3,000,000'], ] return[ [1, 'Kurang dari Rp100.000'], [2, 'Rp100.001 - Rp150.000'], [3, 'Rp150.001 - Rp250.000'], [4, 'Rp250.001 - Rp500.000'], [5, 'Rp500.001 - Rp750.000'], [6, 'Rp750.001 - Rp1.000.000'], [7, 'Rp1.000.001 - Rp1.500.000'], [8, 'Rp1.500.001 - Rp1.750.000'], [9, 'Rp1.750.001 - Rp2.500.000'], [10, 'Rp2.500.001 - Rp3.000.000'], [11, 'Lebih dari Rp3.000.000'], ] def Disappointed_Fail_Gacha_choices(player): if get_language(player): return [ [1, 'Not disappointed at all'], [2, 'Slightly disappointed'], [3, 'Somewhat disappointed'], [4, 'Moderately disappointed'], [5, 'Quite disappointed'], [6, 'Very disappointed'], [7, 'Extremely disappointed'], ] return [ [1, 'Tidak kecewa sama sekali'], [2, 'Sedikit kecewa'], [3, 'Agak kecewa'], [4, 'Cukup kecewa'], [5, 'Kecewa'], [6, 'Sangat kecewa'], [7, 'Sangat kecewa sekali'], ] def Excitement_Opening_Gacha_choices(player): if get_language(player): return [ [1, 'Not excited at all'], [2, 'Slightly excited'], [3, 'Somewhat excited'], [4, 'Moderately excited'], [5, 'Quite excited'], [6, 'Very excited'], [7, 'Extremely excited'], ] return [ [1, 'Tidak bersemangat sama sekali'], [2, 'Sedikit bersemangat'], [3, 'Agak bersemangat'], [4, 'Cukup bersemangat'], [5, 'Bersemangat'], [6, 'Sangat bersemangat'], [7, 'Sangat bersemangat sekali'], ] def Continue_Purchasing_gacha_choices(player): if get_language(player): return [ [1, 'Never'], [2, 'Rarely'], [3, 'Sometimes'], [4, 'Often'], [5, 'Very often'], ] return [ [1, 'Tidak pernah'], [2, 'Jarang'], [3, 'Kadang-kadang'], [4, 'Sering'], [5, 'Sangat sering'], ] def Effort_Continue_Gacha_choices(player): if get_language(player): return [ [1, 'Never'], [2, 'Rarely'], [3, 'Sometimes'], [4, 'Often'], [5, 'Very often'], ] return [ [1, 'Tidak pernah'], [2, 'Jarang'], [3, 'Kadang-kadang'], [4, 'Sering'], [5, 'Sangat sering'], ] class Player(BasePlayer): condition = models.StringField() # Gacha Play_Gacha = models.StringField( #Do any of the games you play contain random reward systems # such as gacha, loot boxes, mystery boxes, card packs, or capsule mechanics? label='', widget=widgets.RadioSelect, choices=Play_Gacha_choices, ) Game_Genres_1 = models.StringField( #Genre of the game, if multiple, the genre of your most played game/games blank=True, choices=[ ['FPS', 'FPS'], ['MOBA', 'MOBA'], ['Battle Royale', 'Battle Royale'], ['MMORPG', 'MMORPG'], ['RPG', 'RPG'], ['Action Adventure', 'Action Adventure'], ['Strategy / RTS', 'Strategy / RTS'], ['Simulation', 'Simulation'], ['Sports', 'Sports'], ['Puzzle', 'Puzzle'], ['Rhythm', 'Rhythm'], ['Casual', 'Casual'], ['Other', 'Other'], ], widget=widgets.RadioSelect, ) Game_Genres_2 = models.StringField( # Genre of the game, if multiple, the genre of your most played game/games blank=True, choices=[ ['FPS', 'FPS'], ['MOBA', 'MOBA'], ['Battle Royale', 'Battle Royale'], ['MMORPG', 'MMORPG'], ['RPG', 'RPG'], ['Action Adventure', 'Action Adventure'], ['Strategy / RTS', 'Strategy / RTS'], ['Simulation', 'Simulation'], ['Sports', 'Sports'], ['Puzzle', 'Puzzle'], ['Rhythm', 'Rhythm'], ['Casual', 'Casual'], ['Other', 'Other'], ], widget=widgets.RadioSelect, ) Popular_Game_1 = models.StringField( #Select up to 5 games, game 1 blank=True, label='', choices=[ 'Mobile Legends', 'PUBG Mobile', 'Free Fire', 'Honor of Kings', 'Genshin Impact', 'Honkai: Star Rail', 'Zenless Zone Zero', 'Wuthering Waves', 'Fate/Grand Order', 'Blue Archive', 'Arknights', 'League of Legends', 'Valorant', 'Counter Strike 2', 'Dota 2', 'EA FC', 'Roblox', 'Minecraft', 'Other', ], widget=widgets.RadioSelect, ) Popular_Game_2 = models.StringField( # Select up to 5 games, game 2 blank=True, label='', choices=[ 'Mobile Legends', 'PUBG Mobile', 'Free Fire', 'Honor of Kings', 'Genshin Impact', 'Honkai: Star Rail', 'Zenless Zone Zero', 'Wuthering Waves', 'Fate/Grand Order', 'Blue Archive', 'Arknights', 'League of Legends', 'Valorant', 'Counter Strike 2', 'Dota 2', 'EA FC', 'Roblox', 'Minecraft', 'Other', ], widget=widgets.RadioSelect, ) Popular_Game_3 = models.StringField( # Select up to 5 games, game 3 blank=True, label='', choices=[ 'Mobile Legends', 'PUBG Mobile', 'Free Fire', 'Honor of Kings', 'Genshin Impact', 'Honkai: Star Rail', 'Zenless Zone Zero', 'Wuthering Waves', 'Fate/Grand Order', 'Blue Archive', 'Arknights', 'League of Legends', 'Valorant', 'Counter Strike 2', 'Dota 2', 'EA FC', 'Roblox', 'Minecraft', 'Other', ], widget=widgets.RadioSelect, ) Popular_Game_4 = models.StringField( # Select up to 5 games, game 4 blank=True, label='', choices=[ 'Mobile Legends', 'PUBG Mobile', 'Free Fire', 'Honor of Kings', 'Genshin Impact', 'Honkai: Star Rail', 'Zenless Zone Zero', 'Wuthering Waves', 'Fate/Grand Order', 'Blue Archive', 'Arknights', 'League of Legends', 'Valorant', 'Counter Strike 2', 'Dota 2', 'EA FC', 'Roblox', 'Minecraft', 'Other', ], widget=widgets.RadioSelect, ) Popular_Game_5 = models.StringField( # Select up to 5 games, game 5 blank=True, label='', choices=[ 'Mobile Legends', 'PUBG Mobile', 'Free Fire', 'Honor of Kings', 'Genshin Impact', 'Honkai: Star Rail', 'Zenless Zone Zero', 'Wuthering Waves', 'Fate/Grand Order', 'Blue Archive', 'Arknights', 'League of Legends', 'Valorant', 'Counter Strike 2', 'Dota 2', 'EA FC', 'Roblox', 'Minecraft', 'Other', ], widget=widgets.RadioSelect, ) Frequency_Obtain_Gacha=models.StringField( #How often do you obtain random rewards (gacha, loot boxes, etc.)? label='', choices=Frequency_Obtain_Gacha_choices, widget=widgets.RadioSelect, ) Enjoy_Gacha=models.IntegerField( #How much do you enjoy opening random rewards? label='', choices=Enjoy_Gacha_choices, widget=widgets.RadioSelect, ) SpentMoney_Gacha=models.BooleanField( #Have you ever spent real money to obtain a random reward? label='', choices=SpentMoney_Gacha_choices, widget=widgets.RadioSelect, ) HowMuch_Spent_Money_Gacha=models.IntegerField( #Approximately how much money have you # spent on random reward mechanics during the past 12 months? label='', choices=HowMuch_Spent_Money_Gacha_choices, widget=widgets.RadioSelect, ) Effort_Continue_Gacha=models.IntegerField( # Have you ever continued playing primarily to obtain a specific random reward? label='', choices=Effort_Continue_Gacha_choices, widget=widgets.RadioSelect, ) Continue_Purchasing_gacha = models.IntegerField( # Have you ever continued purchasing random rewards because # you had already spent money trying to obtain a particular item? label='', choices=Continue_Purchasing_gacha_choices, widget=widgets.RadioSelect, ) Excitement_Opening_Gacha = models.IntegerField( #When opening a random reward, how excited do you usually feel? label='', choices=Excitement_Opening_Gacha_choices, widget=widgets.RadioSelect, ) Disappointed_Fail_Gacha = models.IntegerField( #When you fail to obtain the item you wanted, how disappointed do you usually feel? label='', choices=Disappointed_Fail_Gacha_choices, widget=widgets.RadioSelect, ) # No choices= kwarg: the module-level *_choices functions above supply them. Comprehension_Treatment_3 = models.IntegerField( label='', widget=widgets.RadioSelect, ) # Was StringField — changed to IntegerField so the `!= 5` check in # b_Treatment_4.error_message can actually match (a StringField returns # '5', and '5' != 5 is always True, rejecting every answer). Comprehension_Treatment_4 = models.IntegerField( label='', widget=widgets.RadioSelect, ) continue_session = models.BooleanField( label='', choices=continue_session_choices, widget=widgets.RadioSelectHorizontal ) confirm_withdrawal = models.BooleanField( label='', choices=confirm_withdrawal_choices, widget=widgets.RadioSelectHorizontal ) continue_session_after_treatment = models.BooleanField( label='', choices=continue_session_after_treatment_choices, widget=widgets.RadioSelectHorizontal ) confirm_withdrawal_after_treatment = models.BooleanField( label='', choices=confirm_withdrawal_after_treatment_choices, widget=widgets.RadioSelectHorizontal ) phone_number = models.StringField( label='', ) name = models.StringField( label='', ) email_address = models.StringField( label='' ) # PAGES class a_gacha(Page): form_model = 'player' form_fields = ['Play_Gacha'] def vars_for_template(player): return dict(en=get_language(player)) def is_displayed(player): return ( player.continue_session ) class a_gacha_detail_1(Page): form_model = 'player' form_fields = [ 'Game_Genres_1', 'Game_Genres_2', 'Popular_Game_1', 'Popular_Game_2', 'Popular_Game_3', 'Popular_Game_4', 'Popular_Game_5', ] def vars_for_template(player): return dict(en=get_language(player)) def is_displayed(player): return ( player.continue_session and player.Play_Gacha == '1' ) class a_gacha_detail_2(Page): form_model = 'player' form_fields = [ 'Frequency_Obtain_Gacha', 'Enjoy_Gacha', 'SpentMoney_Gacha', 'HowMuch_Spent_Money_Gacha', 'Effort_Continue_Gacha', 'Continue_Purchasing_gacha', 'Excitement_Opening_Gacha', 'Disappointed_Fail_Gacha', ] def vars_for_template(player): return dict(en=get_language(player)) def is_displayed(player): return ( player.continue_session and player.Play_Gacha == '1' ) class a_Welcome(Page): form_model = 'player' form_fields = ['continue_session'] def vars_for_template(player): return dict(en=get_language(player)) class a_ConfirmWithdrawal(Page): form_model = 'player' form_fields = ['confirm_withdrawal'] @staticmethod def is_displayed(player): return player.continue_session is False def vars_for_template(player): return dict(en=get_language(player)) def before_next_page(player, timeout_happened): if player.confirm_withdrawal is False: player.continue_session = True class a_information_page(Page): form_model = 'player' form_fields = [ 'phone_number', 'name', 'email_address', ] def vars_for_template(player): return dict( en=get_language(player), ) class b_Control(Page): def is_displayed(player): return ( player.continue_session and player.participant.vars.get('condition') == 'control' ) def vars_for_template(player): return dict(en=get_language(player)) class b_Treatment_1(Page): form_model = 'player' form_fields = ['continue_session_after_treatment'] def is_displayed(player): return ( player.continue_session and player.participant.vars.get('condition') == 'treatment_1' ) def vars_for_template(player): return dict(en=get_language(player)) class b_Treatment_2(Page): form_model = 'player' form_fields = ['continue_session_after_treatment'] def is_displayed(player): return ( player.continue_session and player.participant.vars.get('condition') == 'treatment_2' ) def vars_for_template(player): return dict(en=get_language(player)) class b_WithdrawalConfirmation_AfterTreatment(Page): form_model = 'player' form_fields = ['confirm_withdrawal_after_treatment'] def vars_for_template(player): return dict(en=get_language(player)) def is_displayed(player): return ( player.participant.vars.get('condition') in ['treatment_1', 'treatment_2'] and player.continue_session_after_treatment is False ) def before_next_page(player, timeout_happened): if player.confirm_withdrawal_after_treatment is False: player.continue_session_after_treatment = True class b_Treatment_3(Page): form_model = 'player' form_fields = ['Comprehension_Treatment_3'] def is_displayed(player): return ( player.continue_session and player.participant.vars.get('condition') == 'treatment_3' ) def error_message(player, values): if values['Comprehension_Treatment_3'] != 2: return {'Comprehension_Treatment_3': 'Your answer is incorrect. Please watch the video again.'} def vars_for_template(player): return dict(en=get_language(player)) class b_Treatment_4(Page): form_model = 'player' form_fields = ['Comprehension_Treatment_4'] def is_displayed(player): return ( player.continue_session and player.participant.vars.get('condition') == 'treatment_4' ) def error_message(player, values): if values['Comprehension_Treatment_4'] != 5: return {'Comprehension_Treatment_4': 'Your answer is incorrect. Please watch the video again.'} def vars_for_template(player): return dict(en=get_language(player)) class c_Exit_Page(Page): def vars_for_template(player): return dict(en=get_language(player)) def is_displayed(player): return player.continue_session is False or player.participant.vars.get('condition') in ['treatment_1', 'treatment_2'] and player.continue_session_after_treatment is False page_sequence = [a_information_page, a_Welcome, a_ConfirmWithdrawal, a_gacha, a_gacha_detail_1, a_gacha_detail_2, b_Control, b_Treatment_1, b_Treatment_2, b_Treatment_3, b_Treatment_4, b_WithdrawalConfirmation_AfterTreatment, c_Exit_Page]