from otree.api import * doc = 'Narratives with Dictator Game' #-----------------CLASSES-----------------# class C(BaseConstants): NAME_IN_URL = 'Narrative' PLAYERS_PER_GROUP = None NUM_ROUNDS = 1 class Subsession(BaseSubsession): pass class Group(BaseGroup): pass class Player(BasePlayer): consent = models.BooleanField(label='I have read and understood the information above, and I give my consent to participate in this study.') narrative_treatment = models.StringField() #social_context = models.StringField() allocation = models.IntegerField() en_q1 = models.BooleanField( label='The main character of The OceanMaker is a female pilot who flies a small red airplane.', choices=[[True, 'True'], [False, 'False']] ) en_q2 = models.BooleanField( label='The world of the film shows a dry ocean floor—ships are stranded on land with no water around them.', choices=[[True, 'True'], [False, 'False']] ) en_q3 = models.BooleanField( label='The water in the film is created by a giant underground machine that pumps water from deep wells.', choices=[[True, 'True'], [False, 'False']] ) en_q4 = models.BooleanField( label='The pilot battles sky pirates who try to steal clouds using their own aircraft.', choices=[[True, 'True'], [False, 'False']] ) en_q5 = models.BooleanField( label='There is no spoken dialogue in the film; the whole story is told visually.', choices=[[True, 'True'], [False, 'False']] ) en_q6 = models.BooleanField( label='At one point, the pilot uses a harpoon-like device to pull water out of the air.', choices=[[True, 'True'], [False, 'False']] ) en_q7 = models.BooleanField( label='The final cloud in the movie is turned into rain by a special device attached to the pilot’s plane.', choices=[[True, 'True'], [False, 'False']] ) en_q8 = models.BooleanField( label='A large desert storm destroys the pilot’s plane before she can reach the cloud.', choices=[[True, 'True'], [False, 'False']] ) en_q9 = models.BooleanField( label='The pirates use grappling hooks and nets to capture clouds.', choices=[[True, 'True'], [False, 'False']] ) en_q10 = models.BooleanField( label='In the final scene, the young girl who appears earlier is shown witnessing the return of rainfall.', choices=[[True, 'True'], [False, 'False']] ) sn_q1 = models.BooleanField( label='The main character is a secret agent named Walter Beckett.', choices=[[True, 'True'], [False, 'False']] ) sn_q2 = models.BooleanField( label='The short begins with the protagonist accidentally dropping his high-tech briefcase in a pigeon’s nest.', choices=[[True, 'True'], [False, 'False']] ) sn_q3 = models.BooleanField( label='The briefcase contains top-secret nuclear launch codes.', choices=[[True, 'True'], [False, 'False']] ) sn_q4 = models.BooleanField( label='The pigeon inside the briefcase causes chaos by pressing buttons on the equipment.', choices=[[True, 'True'], [False, 'False']] ) sn_q5 = models.BooleanField( label='There is spoken dialogue in the film throughout the entire short.', choices=[[True, 'True'], [False, 'False']] ) sn_q6 = models.BooleanField( label='At one point, the pigeon flies the briefcase through a restaurant, causing destruction.', choices=[[True, 'True'], [False, 'False']] ) sn_q7 = models.BooleanField( label='Walter successfully recovers the briefcase without any damage by the end of the film.', choices=[[True, 'True'], [False, 'False']] ) sn_q8 = models.BooleanField( label='The film is roughly 6 minutes long.', choices=[[True, 'True'], [False, 'False']] ) sn_q9 = models.BooleanField( label='The pigeon is caught in the briefcase accidentally while trying to steal food.', choices=[[True, 'True'], [False, 'False']] ) sn_q10 = models.BooleanField( label='The short ends with the pigeon safely flying away after the chaos.', choices=[[True, 'True'], [False, 'False']] ) transport_1 = models.IntegerField( label='While I was watching the video, I could easily picture the events in it taking place.', max=7, min=1, widget=widgets.RadioSelectHorizontal, choices=[1,2,3,4,5,6,7] ) transport_2 = models.IntegerField( label='I could imagine myself in the scene of the events described in the video.', max=7, min=1, widget=widgets.RadioSelectHorizontal, choices=[1,2,3,4,5,6,7] ) transport_3 = models.IntegerField( label='I was mentally involved in the video while watching it.', max=7, min=1, widget=widgets.RadioSelectHorizontal, choices=[1,2,3,4,5,6,7] ) transport_4 = models.IntegerField( label='After finishing the video, I found it easy to put it out of my mind.', max=7, min=1, widget=widgets.RadioSelectHorizontal, choices=[1,2,3,4,5,6,7] ) transport_5 = models.IntegerField( label='The video affected me emotionally.', max=7, min=1, widget=widgets.RadioSelectHorizontal, choices=[1,2,3,4,5,6,7] ) transport_6 = models.IntegerField( label='The events in the video have changed my concerns about the future.', max=7, min=1, widget=widgets.RadioSelectHorizontal, choices=[1,2,3,4,5,6,7] ) char_image_vivid = models.IntegerField( label='While watching the video I had a vivid image of the main character.', max=7, min=1, widget=widgets.RadioSelectHorizontal, choices=[1,2,3,4,5,6,7] ) char_good_bad = models.IntegerField( label='How would you rate the main character:
Bad (1) – Good (7)', max=7, min=1, widget=widgets.RadioSelectHorizontal, choices=[1,2,3,4,5,6,7] ) char_pleasant_unpleasant = models.IntegerField( label='How would you rate the main character:
Unpleasant (1) – Pleasant (7)', max=7, min=1, widget=widgets.RadioSelectHorizontal, choices=[1,2,3,4,5,6,7] ) char_attractive_unattractive = models.IntegerField( label='How would you rate the main character:
Unattractive (1) – Attractive (7)', max=7, min=1, widget=widgets.RadioSelectHorizontal, choices=[1,2,3,4,5,6,7] ) char_responsible_irresponsible = models.IntegerField( label='How would you rate the main character:
Irresponsible (1) – Responsible (7)', max=7, min=1, widget=widgets.RadioSelectHorizontal, choices=[1,2,3,4,5,6,7] ) belief_just_world = models.IntegerField(label='People usually receive the outcomes that they deserve.', widget=widgets.RadioSelectHorizontal, choices=[1, 2, 3, 4, 5, 6, 7] ) belief_climate_relevant = models.IntegerField(label='Climate change is a relevant issue that must be actively addressed.', widget=widgets.RadioSelectHorizontal, choices=[1, 2, 3, 4, 5, 6, 7] ) video_watched = models.BooleanField(initial=False) time_on_page = models.IntegerField(initial=0) pause_count = models.IntegerField(initial=0) gender = models.StringField( label='What is your gender?', choices=['Male', 'Female', 'Other'] ) age = models.IntegerField( label='What is your age?', min=18, max=99 ) employment_status = models.StringField( label='Which of the following describes your situation the best?', choices=[ 'Unemployed', 'Student', 'Working either part-time or full-time', 'Self-employed', 'Other' ] ) education = models.StringField( label='What is the highest level of education you achieved to date?', choices=[ 'No formal education', 'Lower than a high school diploma', 'High school diploma', 'Bachelor degree', "Master's degree", 'Doctoral degree' ] ) income_us = models.IntegerField( label='Imagine an income scale on which 1 indicates the lowest income group and 10 the highest income group in the United States. We would like to know in what group your household is.
Please, specify the appropriate number, counting all wages, salaries, pensions and other incomes earned.', min=1, max=10 ) us_state = models.StringField( label='In which US state are you residing?', choices=[ 'Alabama','Alaska','Arizona','Arkansas','California','Colorado','Connecticut', 'Delaware','District of Columbia','Florida','Georgia','Hawaii','Idaho','Illinois', 'Indiana','Iowa','Kansas','Kentucky','Louisiana','Maine','Maryland','Massachusetts', 'Michigan','Minnesota','Mississippi','Missouri','Montana','Nebraska','Nevada', 'New Hampshire','New Jersey','New Mexico','New York','North Carolina','North Dakota', 'Ohio','Oklahoma','Oregon','Pennsylvania','Rhode Island','South Carolina', 'South Dakota','Tennessee','Texas','Utah','Vermont','Virginia','Washington', 'West Virginia','Wisconsin','Wyoming' ] ) book = models.IntegerField( label="How many books, e-books, or audiobooks have you read in the past 12 months? Please include only books read for non-academic or non-professional purposes.", blank=False ) book3 = models.StringField( choices=[ ('0', '0'), ('1', '1–10'), ('2', '11–50'), ('3', '50–100'), ('4', 'More than 100') ], label="Approximately how many books do you own at home or on your computer/smartphone, in physical or digital format?", blank=False ) teatro = models.IntegerField( choices=[(1, 'Never'), (2, '1–3 times'), (3, '4–6 times'), (4, '7–12 times'), (5, 'More than 12 times')], label="Theater", widget=widgets.RadioSelect ) cinema = models.IntegerField( choices=[(1, 'Never'), (2, '1–3 times'), (3, '4–6 times'), (4, '7–12 times'), (5, 'More than 12 times')], label="Cinema", widget=widgets.RadioSelect ) musei_mostre = models.IntegerField( choices=[(1, 'Never'), (2, '1–3 times'), (3, '4–6 times'), (4, '7–12 times'), (5, 'More than 12 times')], label="Museums and exhibitions", widget=widgets.RadioSelect ) classica_opera = models.IntegerField( choices=[(1, 'Never'), (2, '1–3 times'), (3, '4–6 times'), (4, '7–12 times'), (5, 'More than 12 times')], label="Classical music concerts and opera", widget=widgets.RadioSelect ) altri_concerti = models.IntegerField( choices=[(1, 'Never'), (2, '1–3 times'), (3, '4–6 times'), (4, '7–12 times'), (5, 'More than 12 times')], label="Other music concerts", widget=widgets.RadioSelect ) sport = models.IntegerField( choices=[(1, 'Never'), (2, '1–3 times'), (3, '4–6 times'), (4, '7–12 times'), (5, 'More than 12 times')], label="Sporting events", widget=widgets.RadioSelect ) discoteche = models.IntegerField( choices=[(1, 'Never'), (2, '1–3 times'), (3, '4–6 times'), (4, '7–12 times'), (5, 'More than 12 times')], label="Nightclubs, dance halls, or other venues for dancing", widget=widgets.RadioSelect ) siti_archeologici = models.IntegerField( choices=[(1, 'Never'), (2, '1–3 times'), (3, '4–6 times'), (4, '7–12 times'), (5, 'More than 12 times')], label="Archaeological sites and monuments", widget=widgets.RadioSelect ) video_completed = models.StringField(blank=True) hidden_count = models.IntegerField(initial=0) correct_mc = models.IntegerField(initial=0) wrong_mc = models.IntegerField(initial=0) #----------------- FUNCTIONS -----------------# def creating_session(subsession: Subsession): players = subsession.get_players() import random # balanced assignment for narrative_treatment: EN, SN, C n = len(players) base = ['EN', 'SN', 'C'] reps = n // 3 remainder = n % 3 assignments = base * reps + base[:remainder] random.shuffle(assignments) for p, t in zip(players, assignments): p.narrative_treatment = t # # balanced assignment for social_context: PE, AE # base_sc = ['PE', 'AE'] # reps_sc = n // 2 # remainder_sc = n % 2 # contexts = base_sc * reps_sc + base_sc[:remainder_sc] # random.shuffle(contexts) # # for p, sc in zip(players, contexts): # p.social_context = sc def set_payoff(player: Player): player.payoff = player.allocation #----------------- PAGES -----------------# class Consent(Page): form_model = 'player' form_fields = ['consent'] @staticmethod def before_next_page(player: Player, timeout_happened): participant = player.participant participant.consent = player.consent class Intro(Page): form_model = 'player' @staticmethod def is_displayed(player: Player): return player.consent class NarrativeTreatmentPage(Page): form_model = 'player' form_fields = ['time_on_page', 'pause_count', 'video_watched'] @staticmethod def is_displayed(player: Player): return player.narrative_treatment in ['EN', 'SN'] and player.consent @staticmethod def vars_for_template(player: Player): if player.narrative_treatment == 'EN': video_url = 'https://www.youtube.com/embed/0umI5yPcHFY' min_watch_seconds = 600 buffer_seconds = 30 elif player.narrative_treatment == 'SN': video_url = 'https://www.youtube.com/embed/jEjUAnPc2VA' min_watch_seconds = 360 buffer_seconds = 30 else: video_url = None min_watch_seconds = 0 buffer_seconds = 0 return dict( video_url=video_url, treatment=player.narrative_treatment, min_watch_seconds=min_watch_seconds, buffer_seconds=buffer_seconds ) @staticmethod def before_next_page(player: Player, timeout_happened): if not player.video_watched: player.time_on_page = 0 player.pause_count = 0 class SocialContextPage(Page): form_model = 'player' form_fields = ['allocation'] @staticmethod def vars_for_template(player: Player): # # if player.social_context == 'PE': # X, Y = 5, 5 # # else: # AE # # X, Y = 10, 0 # choices = [ (10, "Take $5 from the organization
(You get $10, the organization gets $0)"), (9, "Take $4 from the organization
(You get $9, the organization gets $1)"), (8, "Take $3 from the organization
(You get $8, the organization gets $2)"), (7, "Take $2 from the organization
(You get $7, the organization gets $3)"), (6, "Take $1 from Ithe organization
(You get $6, the organization gets $4)"), (5, "Give $0 / Take $0 to/from the organization
(You get $5, the organization gets $5)"), (4, "Give $1 to the organization
(You get $4, the organization gets $6)"), (3, "Give $2 to the organization
(You get $3, the organization gets $7)"), (2, "Give $3 to the organization
(You get $2, the organization gets $8)"), (1, "Give $4 to the organization
(You get $1, the organization gets $9)"), (0, "Give $5 to the organization
(You get $0, the organization gets $10)") ] # return dict(choices=choices) @staticmethod def before_next_page(player, timeout_happened): set_payoff(player) @staticmethod def is_displayed(player: Player): return player.consent class ManipulationCheck(Page): form_model = 'player' form_fields = ['en_q1', 'en_q2', 'en_q3', 'en_q4', 'en_q5', 'en_q6', 'en_q7', 'en_q8', 'en_q9', 'en_q10', 'sn_q1', 'sn_q2', 'sn_q3', 'sn_q4', 'sn_q5', 'sn_q6', 'sn_q7', 'sn_q8', 'sn_q9', 'sn_q10',] @staticmethod def get_form_fields(player: Player): if player.narrative_treatment == 'EN': return ['en_q1','en_q2','en_q3','en_q4','en_q5','en_q6','en_q7','en_q8','en_q9','en_q10'] elif player.narrative_treatment == 'SN': return ['sn_q1','sn_q2','sn_q3','sn_q4','sn_q5','sn_q6','sn_q7','sn_q8','sn_q9','sn_q10'] else: return [] @staticmethod def before_next_page(player: Player, timeout_happened): en_key = [True, True, False, True, True, False, True, False, True, True] sn_key = [True, False, True, True, False, True, False, True, False, True] correct = 0 if player.narrative_treatment == 'EN': answers = [ player.en_q1, player.en_q2, player.en_q3, player.en_q4, player.en_q5, player.en_q6, player.en_q7, player.en_q8, player.en_q9, player.en_q10 ] for a, k in zip(answers, en_key): if a == k: correct += 1 elif player.narrative_treatment == 'SN': answers = [ player.sn_q1, player.sn_q2, player.sn_q3, player.sn_q4, player.sn_q5, player.sn_q6, player.sn_q7, player.sn_q8, player.sn_q9, player.sn_q10 ] for a, k in zip(answers, sn_key): if a == k: correct += 1 player.correct_mc = correct player.wrong_mc = 10 - correct @staticmethod def is_displayed(player: Player): return player.narrative_treatment in ['EN', 'SN'] and player.consent class Transportation(Page): form_model = 'player' form_fields = ['transport_1', 'transport_2', 'transport_3', 'transport_4', 'transport_5', 'transport_6', 'char_image_vivid', 'char_good_bad', 'char_pleasant_unpleasant', 'char_attractive_unattractive', 'char_responsible_irresponsible'] @staticmethod def is_displayed(player: Player): return player.narrative_treatment in ['EN', 'SN'] and player.consent class Beliefs(Page): form_model = 'player' form_fields = ['belief_just_world', 'belief_climate_relevant'] @staticmethod def is_displayed(player: Player): return player.consent class Culture(Page): form_model = 'player' form_fields = ['teatro', 'cinema', 'musei_mostre', 'classica_opera', 'altri_concerti', 'sport', 'discoteche', 'siti_archeologici'] @staticmethod def is_displayed(player: Player): return player.consent class Demographics(Page): form_model = 'player' form_fields = [ 'book', 'book3', 'gender', 'age', 'employment_status', 'education', 'income_us', 'us_state' ] @staticmethod def is_displayed(player: Player): return player.consent class Thanks(Page): pass @staticmethod def is_displayed(player: Player): return player.consent class Noconsent(Page): pass @staticmethod def is_displayed(player: Player): return not player.consent #----------------- SEQUENCE -----------------# page_sequence = [ Consent, Intro, NarrativeTreatmentPage, ManipulationCheck, Transportation, SocialContextPage, Beliefs, Culture, Demographics, Thanks, Noconsent]