from otree.api import *
c = cu
doc = 'Post experiment questions. Includes survey questions, Tightwad-spendthrift scale by Rick Scott, Cynthia Cryder, and George Loewenstein (2008), and demographic questions.\n'
class C(BaseConstants):
# built-in constants
NAME_IN_URL = 'Survey'
PLAYERS_PER_GROUP = 2
NUM_ROUNDS = 1
# user-defined constants
LIKERT_OPTS = (1, 2, 3, 4, 5)
SMILEY_LIKERT_OPTS = (1, 2, 3, 4, 5, 6, 7)
UW_TETON_BG_TEMPLATE = 'Survey/uw_teton_bg.html'
UW_TETON_SURVEY_TEMPLATE = 'Survey/uw_teton_survey.html'
CHECKBOX_LIST_TEMPLATE = 'Survey/checkbox_list.html'
class Subsession(BaseSubsession):
pass
def after_all_players_arrive(subsession: Subsession):
session = subsession.session
# pull the matrix you stored in the code‐entry app
matrix = subsession.session.vars.get('couple_matrix')
if not matrix:
# safety check in case someone forgot to run grouping first
raise RuntimeError("No couple_matrix in session.vars")
# re‐apply it in this app's subsession
subsession.set_group_matrix(matrix)
class Group(BaseGroup):
pass
class Player(BasePlayer):
r_entiltedMe = models.IntegerField(choices=C.LIKERT_OPTS, label='I felt entitled to spend the money earned by me in the joint account.', widget=widgets.RadioSelectHorizontal)
r_entiltedPartner = models.IntegerField(choices=C.LIKERT_OPTS, label='I felt entitled to spend the money earned by my partner in the joint account.', widget=widgets.RadioSelectHorizontal)
r_upsetPartner = models.IntegerField(choices=C.LIKERT_OPTS, label='My partner would be upset with me if I spent a large portion of the money from the joint account in this study on an item only I would use.', widget=widgets.RadioSelectHorizontal)
r_guilty = models.IntegerField(choices=C.LIKERT_OPTS, label='I would feel guilty if I spent a large portion of the money from the joint account in this study on an item only I would use.', widget=widgets.RadioSelectHorizontal)
r_entitledPartnerToSpendTheirs = models.IntegerField(choices=C.LIKERT_OPTS, label='I felt my partner was entitled to spend the money earned by themselves in the joint account.', widget=widgets.RadioSelectHorizontal)
r_entitledPartnerToSpendMine = models.IntegerField(choices=C.LIKERT_OPTS, label='I felt my partner was entitled to spend the money earned by me in the joint account.', widget=widgets.RadioSelectHorizontal)
r_upsetWithPartner = models.IntegerField(choices=C.LIKERT_OPTS, label='I would be upset with my partner if they spent a large portion of the money from the joint account in this study on an item only they would use.', widget=widgets.RadioSelectHorizontal)
r_expectPartnerGuilt = models.IntegerField(choices=C.LIKERT_OPTS, label='I would expect my partner to feel guilty if they spent a large portion of the money from the joint account in this study on an item only they would use.', widget=widgets.RadioSelectHorizontal)
r_importance = models.IntegerField(choices=C.LIKERT_OPTS, label='My relationship with my partner is very important to me.', widget=widgets.RadioSelectHorizontal)
r_uncomfortable = models.IntegerField(choices=C.LIKERT_OPTS, label='I feel very uncomfortable when my partner is upset with me.', widget=widgets.RadioSelectHorizontal)
r_liveTogether = models.BooleanField(choices=[[True, 'Yes'], [False, 'No']], label='Do you live with your partner?', widget=widgets.RadioSelect)
r_maritalStatus = models.StringField(choices=[['0', 'Relationship with Partner'], ['1', 'Married']], label='What is your current relationship status?', widget=widgets.RadioSelect)
r_relationshipLength = models.StringField(choices=[['1', 'Less than 6 months'], ['2', '6 months to 1 year'], ['3', '1 to 2 years'], ['4', '3 to 5 years'], ['5', '6 to 10 years'], ['6', '11 to 20 years'], ['7', 'More than 20 years']], label='How long have you been in a relationship with your partner? (Please round to the nearest full year. For example, 2.3 years = "1 to 2 years")', widget=widgets.RadioSelect)
r_relationshipLast = models.StringField(choices=[['1', 'A few months at most'], ['2', 'Around a year'], ['3', 'Several years'], ['4', 'A lifetime']], label='How long do you believe your relationship with your partner will last?', widget=widgets.RadioSelect)
r_householdAdults = models.IntegerField(label='How many adults (age 18 or older) are in your household (including you)?', min=0)
r_householdChildren = models.IntegerField(label='How many children (under age 18) are in your household?', min=0)
r_happy = models.StringField(choices=[['1', ''], ['2', ''], ['3', ''], ['4', ''], ['5', ''], ['6', ''], ['7', '']], label='How happy are you in your relationship?', widget=widgets.RadioSelectHorizontal)
TWST_1 = models.StringField(choices=[['1', '1'], ['2', '2'], ['3', '3'], ['4', '4'], ['5', '5'], ['6', '6'], ['7', '7'], ['8', '8'], ['9', '9'], ['10', '10'], ['11', '11']], label='Which of the following descriptions fits you better?', widget=widgets.RadioSelectHorizontal)
TWST_2a = models.StringField(choices=[['1', 'Never'], ['2', 'Rarely'], ['3', 'Sometimes'], ['4', 'Often'], ['5', 'Always']], label='How well does the the first description fit you? That is, do you have trouble limiting your spending?', widget=widgets.RadioSelectHorizontal)
TWST_2b = models.StringField(choices=[['1', 'Never'], ['2', 'Rarely'], ['3', 'Sometimes'], ['4', 'Often'], ['5', 'Always']], label='How well does the the second description fit you? That is, do you have trouble spending money?', widget=widgets.RadioSelectHorizontal)
TWST_3 = models.StringField(choices=[['1', '1'], ['2', '2'], ['3', '3'], ['4', '4'], ['5', '5']], label='In terms of your own behavior, who are you more similar to, Mr. A or Mr. B?', widget=widgets.RadioSelectHorizontal)
f_householdIncome = models.StringField(choices=[['1', 'Under $25,000'], ['2', 'Between $25,001 and $50,000'], ['3', 'Between $50,001 and $75,000'], ['4', 'Between $75,001 and $100,000'], ['5', 'Between $100,001 and $125,000'], ['6', 'Between $125,001 and $150,000'], ['7', 'Between $150,001 and $175,000'], ['8', 'Between $175,001 and $200,000'], ['9', 'More than $200,001']], label="What is your household's combined, pre-tax, annual income (including bonuses and commissions) last year in U.S. dollars?", widget=widgets.RadioSelect)
gender = models.StringField(choices=[['0', 'Male'], ['1', 'Female'], ['2', 'Other']], label='What is your gender?', widget=widgets.RadioSelect)
gender_other = models.StringField(label='"You selected \'Other\' as your gender. Please describe your gender identity:"')
age = models.IntegerField(label='What is your age? Please enter your answer as a number', max=99, min=18)
student = models.StringField(choices=[['1', 'Yes'], ['0', 'No']], label='Are you a college student?', widget=widgets.RadioSelect)
education = models.StringField(choices=[['1', 'Some high school or less'], ['2', 'High school diploma or GED'], ['3', 'Some college, but no degree'], ['4', 'Associates or technical degree'], ['5', "Bachelor's degree"], ['6', 'Graduate or professional degree (MA, MS, MBA, PhD, JD, MD, DDS etc.)']], label='What is the highest level of education you have completed?', widget=widgets.RadioSelect)
def custom_export(players):
# Header
yield [
'session_code',
'participant_id_in_session',
'participant_code',
'id_in_group',
'group_number',
'spender',
'earner_1', # noticed error (not correct variable), keeping for consistency in custom exports
'earner_2', # noticed error (not correct variable), keeping for consistency in custom exports
# Relationship Qs
'r_entiltedMe', 'r_entiltedPartner', 'r_upsetPartner', 'r_guilty', # Spender likert Qs
'r_entitledPartnerToSpendTheirs', 'r_entitledPartnerToSpendMine', 'r_upsetWithPartner', 'r_expectPartnerGuilt', # Nonspender likert Qs
'r_importance', 'r_uncomfortable', 'r_liveTogether', 'r_maritalStatus', 'r_relationshipLength', 'r_relationshipLast', 'r_householdAdults', 'r_householdChildren', 'r_happy',
# TWST Qs
'TWST_1', 'TWST_2a', 'TWST_2b', 'TWST_3',
# General Demographis Qs
'gender',
'age',
'student',
'education',
'householdIncome'
]
# Rows
for p in players:
pp = p.participant
pg = p.group
ps = p.session
# Pull participant fields
spender = p.participant.vars.get('spender', '')
earner_round_1 = p.participant.vars.get('earner_round_1', '')
earner_round_2 = p.participant.vars.get('earner_round_2', '')
yield [
ps.code,
pp.id_in_session,
pp.code,
p.id_in_group,
pg.id_in_subsession,
spender,
earner_1, # noticed error (not correct variable), keeping for consistency in custom exports
earner2, # noticed error (not correct variable), keeping for consistency in custom exports
p.r_entiltedMe, p.r_entiltedPartner, p.r_upsetPartner, p.r_guilty,
p.r_entitledPartnerToSpendTheirs, p.r_entitledPartnerToSpendMine, p.r_upsetWithPartner, p.r_expectPartnerGuilt,
p.r_importance, p.r_uncomfortable, p.r_liveTogether, p.r_maritalStatus, p.r_relationshipLength, p.r_relationshipLast, p.r_householdAdults, p.r_householdChildren, p.r_happy,
p.TWST_1, p.TWST_2a, p.TWST_2b, p.TWST_3,
p.gender,
p.age,
p.student,
p.education,
p.f_householdIncome
]
class GroupingWaitPage(WaitPage):
wait_for_all_groups = True
after_all_players_arrive = after_all_players_arrive
class Relationship_Qs_Spender(Page):
form_model = 'player'
form_fields = ['r_entiltedMe', 'r_entiltedPartner', 'r_upsetPartner', 'r_guilty', 'r_importance', 'r_uncomfortable', 'r_liveTogether', 'r_maritalStatus', 'r_relationshipLength', 'r_relationshipLast', 'r_householdAdults', 'r_householdChildren', 'r_happy']
@staticmethod
def is_displayed(player: Player):
participant = player.participant
# Display if participant is the spender
if player.participant.spender == 1:
return True
# vars_for_template is deprecated in favor of python-based renderers
@staticmethod
def vars_for_template(player: Player):
# List of fields to include in the Likert scale table
likert_fields_spender = ['r_entiltedMe','r_entiltedPartner', 'r_upsetPartner','r_guilty','r_importance','r_uncomfortable']
# List of fields for the happiness Likert scale
happiness_fields = ['r_happy']
# Passing Python variables to the HTML template of the page
return {
'img_url': 'https://imgur.com/N7q1Rts.png',
'likert_fields_spender': likert_fields_spender,
'happiness_fields': happiness_fields
}
class Relationship_Qs_Nonspender(Page):
form_model = 'player'
form_fields = ['r_entitledPartnerToSpendTheirs', 'r_entitledPartnerToSpendMine', 'r_upsetWithPartner', 'r_expectPartnerGuilt', 'r_importance', 'r_uncomfortable', 'r_liveTogether', 'r_maritalStatus', 'r_relationshipLength', 'r_relationshipLast', 'r_householdAdults', 'r_householdChildren', 'r_happy']
@staticmethod
def is_displayed(player: Player):
participant = player.participant
# Display if participant is the spender
if player.participant.spender != 1:
return True
# vars_for_template is deprecated in favor of python-based renderers
@staticmethod
def vars_for_template(player: Player):
# List of fields to include in the Likert scale table
likert_fields_nonspender = ['r_entitledPartnerToSpendMine','r_entitledPartnerToSpendTheirs', 'r_upsetWithPartner','r_expectPartnerGuilt','r_importance','r_uncomfortable']
# List of fields for the happiness Likert scale
happiness_fields = ['r_happy']
# Passing Python variables to the HTML template of the page
return {
'img_url': 'https://imgur.com/N7q1Rts.png',
'likert_fields_nonspender': likert_fields_nonspender,
'happiness_fields': happiness_fields
}
class TWST_Questions(Page):
form_model = 'player'
form_fields = ['TWST_1', 'TWST_2a', 'TWST_2b', 'TWST_3']
class Demo_Questions(Page):
form_model = 'player'
form_fields = ['gender', 'age', 'student', 'education', 'f_householdIncome']
class SurveyEndPage(WaitPage):
wait_for_all_groups = True
page_sequence = [GroupingWaitPage, Relationship_Qs_Spender, Relationship_Qs_Nonspender, TWST_Questions, Demo_Questions, SurveyEndPage]