apps:
- bots: 'yield Welcome
yield Consent
yield InstructionsIntro'
constants:
- datatype: int
js_value: 2
name: PLAYERS_PER_GROUP
- datatype: int
js_value: 1
name: NUM_ROUNDS
custom_export: "# Header\nyield [\n 'session_code',\n 'participant_id_in_session',\n
\ 'participant_code',\n 'id_in_group',\n 'group_number'\n]\n\n# Rows\nfor
p in players:\n pp = p.participant\n pg = p.group\n ps = p.session\n
\ \n yield [\n ps.code,\n pp.id_in_session,\n pp.code,\n
\ p.id_in_group,\n pg.id_in_subsession\n ]"
doc: Intro to experiment. Provides players brief introduction and gets informed
consent. Then plays video instructions for first phase of experiment.
includable_templates:
- content: "\n{%
load otree %}\n\n\n\n
"
name: uw_teton_bg
models:
Group:
fields: []
methods: []
Player:
fields:
- datatype: StringField
kwargs:
blank: null
choices: null
initial: null
label:
constant: null
expr_type: plain
js_value: Please enter your couple code
widget: null
name: couple_code
- datatype: IntegerField
kwargs:
blank: null
choices:
constant: null
expr_type: plain
js_value: []
initial: null
label: null
max: null
min: null
widget: null
name: my_field
methods: []
Subsession:
fields: []
methods:
- code: "# Build a dict: code → list of player IDs\nbuckets = {}\nfor p in subsession.get_players():\n
\ buckets.setdefault(p.couple_code.strip().lower(), []).append(p.id_in_subsession)\n#
Now turn that into a list-of-lists matrix\nmatrix = [ids for ids in buckets.values()
if len(ids) == 2]\n# (You can handle odd or mistyped codes however you like
here.)\nsubsession.set_group_matrix(matrix)\nsubsession.session.vars['couple_matrix']
= matrix"
is_method: false
name: after_all_players_arrive
name: Intro
pages:
- app_after_this_page: null
before_next_page: '# copy into participant.vars so it’s visible at grouping time
player.participant.vars[''couple_code''] = player.couple_code'
error_message: null
form_fields:
- couple_code
form_model: player
get_form_fields: null
get_timeout_seconds: null
is_displayed: null
is_waitpage: false
js_vars: null
live_method: null
name: Assignment
template:
content: '
{{ include_sibling ''uw_teton_bg.html'' }}
{{ formfields }}
{{ next_button }}'
javascript: null
title: Couple Assignment
timeout_seconds: null
timer_text: null
vars_for_template: null
- after_all_players_arrive: after_all_players_arrive
body_text: null
group_by_arrival_time: null
is_displayed: null
is_waitpage: true
name: AssignmentWaitPage
template: null
title_text: null
wait_for_all_groups: true
- app_after_this_page: null
before_next_page: null
error_message: null
form_fields: null
form_model: player
get_form_fields: null
get_timeout_seconds: null
is_displayed: null
is_waitpage: false
js_vars: null
live_method: null
name: Welcome
template:
content: "\n{{
include_sibling 'uw_teton_bg.html' }}\n\n
\n You are about to participate
in an economic decision-making study. You have the opportunity to make money
in this study. How much money you make depends on your decisions. Whatever
money you make will be paid to you in cash at the end of the study.\n
\n
\ \n
\n During the study, verbal or nonverbal communication with other
participants, cell phone use, and so on, is strictly prohibited. Communication
between participants will lead to your exclusion from the study and forfeiting
all monetary earnings. Please raise your hand if you have any questions; a
member of the research team will come to you and answer your questions privately.\n
\n Thank you for
signing up to participate in a decision-making study. The study should last
about {{session.config.exp_time}}, and you will be paid in cash at
the end of the study.\n
\n\n
\n Participation is voluntary. Your decisions
will remain confidential, and your name will not be recorded anywhere in the
data. All information collected in this study is confidential and will be
used for statistical purposes only. The data will be securely stored. The
risks associated with this study are minimal. Risks are similar to everyday
computer use, though some participants may feel some stress in playing a game.
Although this study will not benefit you personally, the results will help
our understanding of strategic behavior.\n
\n\n
\n The University
of Wyoming, the principal investigator, and the research team are not liable
for any injury participants might sustain while participating in this study
and are not able to offer financial compensation or absorb the costs of medical
treatment should the participant sustain such an injury. By agreeing to participate,
you do not waive any of your legal rights; however, no funds have been set
aside to compensate you in the event of injury.\n
\n\n
\n For additional
information related to this study, contact Dr. Linda Thunström, Department
of Economics, University of Wyoming, at lthunstr@uwyo.edu, or Collin DePaemelere,
Department of Economics, University of Wyoming, at cdepaeme@uwyo.edu. University
of Wyoming's Institutional Review Board (IRB) has determined this study to
be exempt from review by the IRB administration. You can contact UW IRB if
you have questions about your rights as participants (irb@uwyo.edu; 307-766-5322).\n
\n\n
\n
\ By continuing in the session, you are indicating that you are at least
18 years old, have read and understood this consent form, and agree to participate.
Thank you.\n
\n\n{% next_button %}"
javascript: null
title: Consent
timeout_seconds: null
timer_text: null
vars_for_template: "return dict(\n my_label=player.participant.label,\n my_group=player.group.id_in_subsession,\n)"
- after_all_players_arrive: null
body_text: null
group_by_arrival_time: null
is_displayed: null
is_waitpage: true
name: IntroEndPage
template: null
title_text: null
wait_for_all_groups: true
- bots: ''
constants:
- datatype: int
js_value: 2
name: PLAYERS_PER_GROUP
- datatype: int
js_value: 1
name: NUM_ROUNDS
- datatype: list_str
js_value:
- A
- B
- C
- D
- E
- F
- G
- H
- I
- J
name: CHOICES
custom_export: "# Header\nyield [\n 'session_code',\n 'participant_id_in_session',\n
\ 'participant_code',\n 'id_in_group',\n 'group_number',\n 'ranking',\n
\ 'partner_ranking',\n 'correct_belief',\n 'spender_item'\n]\n\n# Rows\nfor
p in players:\n pp = p.participant\n pg = p.group\n ps = p.session\n
\ \n # Pull participant fields (needed as these are only saved in 'all apps
wide' normally)\n correct_belief = p.participant.vars.get('correct_belief',
'')\n \n yield [\n ps.code,\n pp.id_in_session,\n pp.code,\n
\ p.id_in_group,\n pg.id_in_subsession,\n p.ranking,\n p.partner_ranking,\n
\ correct_belief,\n pg.spender_item\n ]"
doc: 'Preference rating of potential items for BDM auction. Involves participants
ranking their preferences for the selection of items, and then predicting their
partner''s preferences. '
includable_templates:
- content: '{% load otree %}'
name: instructions
- content: "\n{%
load otree %}\n\n\n\n"
name: uw_teton_bg
- content: ""
name: data_id
models:
Group:
fields:
- datatype: StringField
kwargs:
blank: null
choices: null
initial: null
label: null
widget: null
name: spender_item
methods:
- code: "import json\n\n# Retrieve all players in the group\nplayers = group.get_players()\n\n#
Map actual preferences for easy reference\nactual_prefs = {p.id_in_group:
p.ranking.split(',') for p in players}\n\nfor p in players:\n # Only
proceed if there are valid rankings\n if p.ranking and p.partner_ranking:\n
\ \n # Split the comma-separated strings of rankings into lists
of item IDs\n own_pref = p.ranking.split(',')\n predicted_partner_pref
= p.partner_ranking.split(',')\n\n # Find the group partner\n partner
= p.get_others_in_group()[0]\n partner_actual_pref = actual_prefs[partner.id_in_group]\n
\ \n # Calculate differences between own preference and partner's
actual preference\n differences = {}\n for item in own_pref:\n
\ index1 = own_pref.index(item)\n index2 = predicted_partner_pref.index(item)\n
\ differences[item] = index1 - index2\n\n diffs = json.dumps([differences])\n
\ min_difference = min(differences.values(), key=lambda x: (x, own_pref.index(item)))\n
\ selected_item = [key for key, value in differences.items() if value
== min_difference][0]\n\n # Store selected item and differences\n
\ p.participant.selected_item = selected_item\n p.diffs = diffs\n
\ \n # Only proceed if there are valid partner rankings\n if
partner_actual_pref != ['']:\n\n # Count matching positions between
predicted and actual preferences\n match_count = sum([\n predicted_partner_pref[i]
== partner_actual_pref[i]\n for i in range(len(predicted_partner_pref))\n
\ ])\n\n # Store the number of matches\n p.participant.belief_match_count
= match_count\n\n # Reward if at least 5 match\n p.participant.correct_belief
= 1 if match_count >= session.config['match_requirement'] else 0\n \n
\ # If any partner ranking is left blank\n else:\n p.participant.belief_match_count
= 0\n p.participant.correct_belief = 0\n \n # If any personal
ranking is left blank\n else:\n p.diffs = json.dumps([{\"\": 0}])\n
\ p.participant.selected_item = \"\"\n p.participant.belief_match_count
= 0\n p.participant.correct_belief = 0"
is_method: false
name: set_pref_diff
- code: "import random\n\n# Randomly choosing one of the group members to be
the earner in round 1\nr = random.randint(1,2)\n\n# Gather players \nplayers
= group.get_players()\n\n# Assign roles based on random draw\nfor p in players:\n
\ if p.id_in_group == r: # If your player id in your group matches the
draw, you are the spender (permanent throughout experiment)\n p.participant.spender
= 1\n group.spender_item = p.participant.selected_item \n else:
# If not, then you will sit out of the spending tasks\n p.participant.spender
= 0\n \n # set the exit\n p.participant.exit_1 = 0"
is_method: false
name: assign_spender
- code: "# Gather players \nplayers = group.get_players()\n\n# Assign roles
based on random draw\nfor p in players:\n# set spender_selected_item so
both players see same item later\n p.participant.spender_selected_item
= group.spender_item"
is_method: false
name: assign_spender_item
Player:
fields:
- datatype: StringField
kwargs:
blank: null
choices: null
initial: null
label: null
widget: null
name: ranking
- datatype: StringField
kwargs:
blank: null
choices: null
initial: null
label: null
widget: null
name: partner_ranking
- datatype: LongStringField
kwargs:
blank: null
choices: null
initial: null
label: null
widget: null
name: diffs
methods: []
Subsession:
fields: []
methods:
- code: "# pull the matrix you stored in the code‐entry app\nmatrix = subsession.session.vars.get('couple_matrix')\nif
not matrix:\n # safety check in case someone forgot to run grouping first\n
\ raise RuntimeError(\"No couple_matrix in session.vars\")\n# re‐apply
it in this app's subsession\nsubsession.set_group_matrix(matrix)"
is_method: false
name: after_all_players_arrive
name: PrefRating
pages:
- after_all_players_arrive: after_all_players_arrive
body_text: null
group_by_arrival_time: null
is_displayed: null
is_waitpage: true
name: GroupingWaitPage
template: null
title_text: null
wait_for_all_groups: true
- app_after_this_page: null
before_next_page: null
error_message: null
form_fields:
- ranking
form_model: player
get_form_fields: null
get_timeout_seconds: null
is_displayed: null
is_waitpage: false
js_vars: null
live_method: null
name: PrefRanking
template:
content: "\n{{
include_sibling 'uw_teton_bg.html' }}\n\n\n
\n Please arrange the items in the list by
dragging them into your own preferred order. Start with the
item you like the most, placing it at the top of the list (ranked as 1), and
proceed to rank each item in descending order of your own preference until
the item you like the least, which should be placed at the bottom (ranked
as 10). All items are of equal market value and are priced at approximately
$30.\n
\n\n\n
\n \n
\n {% for item in image_paths %}\n \n
\n
\ \n {{
item.description }} \n
\n
\ {% endfor %}\n
\n
\n\n\n\n\n\n\n\n\n\n{{ formfield_errors
'ranking' }}\n\n\n{{ next_button }}"
javascript: ''
title: Personal Product Ranking
timeout_seconds: null
timer_text: null
vars_for_template: "# Define the list of items with unique identifiers, their
associated image URLs, and a description\nimgur_urls = [\n {'id': 'A', 'url':
'https://i.imgur.com/OfsrPbR.jpeg', 'description': \"Coloring book with pencils\"},
# Image and description for item A\n {'id': 'B', 'url': 'https://i.imgur.com/tmBYFwX.jpeg',
'description': \"Headphones\"}, # Image and description for item B\n {'id':
'C', 'url': 'https://i.imgur.com/oBfC4Mz.jpeg', 'description': \"Moisturizer\"},
# Image and description for item C\n {'id': 'D', 'url': 'https://i.imgur.com/q7bBuv6.jpeg',
'description': \"Spa kit\"}, # Image and description for item D\n {'id':
'E', 'url': 'https://i.imgur.com/Zc7vR6m.jpeg', 'description': \"Grilling accessories\"},
# Image and description for item E\n {'id': 'F', 'url': 'https://i.imgur.com/YLEoKGI.jpeg',
'description': \"Tactical flashlight\"}, # Image and description for item F\n
\ {'id': 'G', 'url': 'https://i.imgur.com/lmMFuFL.jpeg', 'description': \"Lip
Balm\"}, # Image and description for item G\n {'id': 'H', 'url': 'https://i.imgur.com/5KfUIfj.jpeg',
'description': \"Water bottle\"}, # Image and description for item H\n {'id':
'I', 'url': 'https://i.imgur.com/AS1feBP.jpeg', 'description': \"Car detailing
kit\"}, # Image and description for item I\n {'id': 'J', 'url': 'https://i.imgur.com/SfJ7GmF.jpeg',
'description': \"Multi-tool\"} # Image and description for item J\n]\n\n#
Passing Python variables to the HTML template of the page\nreturn dict(\n image_paths=imgur_urls
# Key 'image_paths' will be accessible in the HTML template\n )"
- app_after_this_page: null
before_next_page: null
error_message: null
form_fields:
- partner_ranking
form_model: player
get_form_fields: null
get_timeout_seconds: null
is_displayed: null
is_waitpage: false
js_vars: null
live_method: null
name: PartnerPrefRanking
template:
content: "\n{{
include_sibling 'uw_teton_bg.html' }}\n\n\n
\n Please arrange the items in the list by
dragging them into your partner's preferred order, based
on your understanding of their tastes. Start with the item you believe your
partner likes the most, placing it at the top of the list (ranked as 1), and
proceed to rank each item in descending order of preference until the item
you believe they like the least, which should be placed at the bottom (ranked
as 10). All items are of equal market value and are priced at approximately
$30.\n
\n\n
\n You can earn money from this task. Your partner
will also rank these items for themselves. If you can correctly guess your
partner's rankings, you earn ${{ session.config.belief_payout }}. Specifically,
we will compare your guess of your partner's preferences to your partner's
actual ranking. If you have accurately guessed the numerical ranking of least
{{ session.config.match_requirement }} of these items, you will earn ${{ session.config.belief_payout
}}.\n
\n\n\n
\n \n
\n {% for item in image_paths %}\n \n
\n
\ \n {{
item.description }} \n
\n
\ {% endfor %}\n
\n
\n\n\n\n\n\n\n\n\n\n{{ formfield_errors
'partner_ranking' }}\n\n\n{{ next_button }}"
javascript: null
title: Partner Product Ranking
timeout_seconds: null
timer_text: null
vars_for_template: "# Define the list of items with unique identifiers, their
associated image URLs, and a description\nimgur_urls = [\n {'id': 'A', 'url':
'https://i.imgur.com/OfsrPbR.jpeg', 'description': \"Coloring book with pencils\"},
# Image and description for item A\n {'id': 'B', 'url': 'https://i.imgur.com/tmBYFwX.jpeg',
'description': \"Headphones\"}, # Image and description for item B\n {'id':
'C', 'url': 'https://i.imgur.com/oBfC4Mz.jpeg', 'description': \"Moisturizer\"},
# Image and description for item C\n {'id': 'D', 'url': 'https://i.imgur.com/q7bBuv6.jpeg',
'description': \"Spa kit\"}, # Image and description for item D\n {'id':
'E', 'url': 'https://i.imgur.com/Zc7vR6m.jpeg', 'description': \"Grilling accessories\"},
# Image and description for item E\n {'id': 'F', 'url': 'https://i.imgur.com/YLEoKGI.jpeg',
'description': \"Tactical flashlight\"}, # Image and description for item F\n
\ {'id': 'G', 'url': 'https://i.imgur.com/lmMFuFL.jpeg', 'description': \"Lip
Balm\"}, # Image and description for item G\n {'id': 'H', 'url': 'https://i.imgur.com/5KfUIfj.jpeg',
'description': \"Water bottle\"}, # Image and description for item H\n {'id':
'I', 'url': 'https://i.imgur.com/AS1feBP.jpeg', 'description': \"Car detailing
kit\"}, # Image and description for item I\n {'id': 'J', 'url': 'https://i.imgur.com/SfJ7GmF.jpeg',
'description': \"Multi-tool\"} # Image and description for item J\n]\n\n#
Passing Python variables to the HTML template of the page\nreturn dict(\n image_paths=imgur_urls
# Key 'image_paths' will be accessible in the HTML template\n )"
- after_all_players_arrive: set_pref_diff
body_text: null
group_by_arrival_time: null
is_displayed: null
is_waitpage: true
name: PrefDiffWaitPage
template: null
title_text: null
wait_for_all_groups: null
- after_all_players_arrive: assign_spender
body_text: null
group_by_arrival_time: null
is_displayed: null
is_waitpage: true
name: AssignSpenderWaitPage
template: null
title_text: null
wait_for_all_groups: null
- after_all_players_arrive: assign_spender_item
body_text: null
group_by_arrival_time: null
is_displayed: null
is_waitpage: true
name: AssignSpenderItemWaitPage
template: null
title_text: null
wait_for_all_groups: null
- after_all_players_arrive: null
body_text: null
group_by_arrival_time: null
is_displayed: null
is_waitpage: true
name: PrefRatingEndPage
template: null
title_text: null
wait_for_all_groups: true
- bots: ''
constants:
- datatype: int
js_value: 2
name: PLAYERS_PER_GROUP
- datatype: int
js_value: 1
name: NUM_ROUNDS
- datatype: str
js_value: 'CQ1: The answer is TRUE. They will be presented with a series of matrices
and will need to count the number of 1s.'
name: Q1_ANSWER
- datatype: str
js_value: 'CQ2: The answer is FALSE. They will be rewarded per matrix they complete.'
name: Q2_ANSWER
- datatype: str
js_value: 'CQ3: The answer is FALSE. One of you will be picked at random to complete
the earnings task, while the other waits.'
name: Q3_ANSWER
custom_export: "# Header\nyield [\n 'session_code',\n 'participant_id_in_session',\n
\ 'participant_code',\n 'id_in_group',\n 'group_number',\n 'RET_cq_1',\n
\ 'RET_cq_2',\n 'RET_cq_3'\n]\n\n# Rows\nfor p in players:\n pp = p.participant\n
\ pg = p.group\n ps = p.session\n \n yield [\n ps.code,\n pp.id_in_session,\n
\ pp.code,\n p.id_in_group,\n pg.id_in_subsession,\n p.cq_1,\n
\ p.cq_2,\n p.cq_3\n ]"
doc: Provides video instructions for the earning task, with comprehension questions
for additional understanding.
includable_templates:
- content: "\n{%
load otree %}\n\n\n\n"
name: uw_teton_bg
models:
Group:
fields: []
methods:
- code: ''
is_method: false
name: my_function
Player:
fields:
- datatype: BooleanField
kwargs:
blank: null
choices:
constant: null
expr_type: plain
js_value:
- - true
- 'True'
- - false
- 'False'
initial: null
label:
constant: null
expr_type: plain
js_value: The person assigned to earning money will earn money by counting
the number of 1s in a matrix.
widget: null
name: cq_1
- datatype: BooleanField
kwargs:
blank: null
choices:
constant: null
expr_type: plain
js_value:
- - true
- 'True'
- - false
- 'False'
initial: null
label:
constant: null
expr_type: plain
js_value: The person earning money will only be rewarded if they get every
matrix correct.
widget: null
name: cq_2
- datatype: BooleanField
kwargs:
blank: null
choices:
constant: null
expr_type: plain
js_value:
- - true
- 'True'
- - false
- 'False'
initial: null
label:
constant: null
expr_type: plain
js_value: You and your partner will both get the opportunity to do the
earnings task.
widget: null
name: cq_3
methods: []
Subsession:
fields: []
methods:
- code: "# pull the matrix you stored in the code‐entry app\nmatrix = subsession.session.vars.get('couple_matrix')\nif
not matrix:\n # safety check in case someone forgot to run grouping first\n
\ raise RuntimeError(\"No couple_matrix in session.vars\")\n# re‐apply
it in this app's subsession\nsubsession.set_group_matrix(matrix)"
is_method: false
name: after_all_players_arrive
name: RET_instructions
pages:
- after_all_players_arrive: after_all_players_arrive
body_text: null
group_by_arrival_time: null
is_displayed: null
is_waitpage: true
name: GroupingWaitPage
template: null
title_text: null
wait_for_all_groups: true
- app_after_this_page: null
before_next_page: null
error_message: null
form_fields: null
form_model: player
get_form_fields: null
get_timeout_seconds: null
is_displayed: null
is_waitpage: false
js_vars: null
live_method: null
name: ExpIntro
template:
content: "\n{{ include_sibling 'uw_teton_bg.html' }}\n\n
\n This study will
consist of 2 rounds. Within each round, your performance will directly impact
your final earnings. At the end of the study, we will randomly draw one round
to determine your final payoff.\n
\n
\ In one part of the study, you or your partner will be randomly chosen
to get the opportunity to earn money. The person selected will earn their
money by completing a task that involves counting the number of 1s in matrices
made up of 1s and 0s. \n
\n\n
\n If you are chosen to do the matrix
task to earn money, your task is to count the number of 1s in each matrix.
Your pay from this task will be determined by how many matrices you correctly
answer. If you answer a matrix incorrectly, you will move on to a new matrix.
You will have {{session.config.time_limit}} minutes to earn up to ${{max_budget}}
by completing up to {{session.config.num_correct}} matrices.\n
\n
\n
\ You will each get an opportunity to practice the matrix task. Below is
an example of a {{session.config.m_size}} by {{session.config.m_size}} matrix
identical to what you would see during the task. In this example, there are
{{matrix_sum}} total 1s that you would need to count.\n
\n\n\n
{% for row in matrix %} \n
{% for
cell in row %} \n
{{ cell }}
{% endfor %} \n
{% endfor
%} \n
\n\n{{ formfields }}\n\n{{ next_button }}"
javascript: null
title: Earning Money
timeout_seconds: null
timer_text: null
vars_for_template: "import random\n\n# Generate C.M_SIZExC.M_SIZE matrix with
random 0s and 1s\nmatrix = [[random.randint(0, 1) for _ in range(session.config['m_size'])]
for _ in range(session.config['m_size'])]\n\n# Calculate the sum of all 1s in
the matrix\nmatrix_sum = sum(sum(row) for row in matrix)\n\n# Calculate max
earnings from the task\nmax_budget = session.config['x_rate'] * session.config['num_correct']\n\n#
Passing Python variables to the HTML template of the page\nreturn dict(\n matrix=matrix,\n
\ matrix_sum=matrix_sum,\n max_budget = max_budget\n)"
- app_after_this_page: null
before_next_page: null
error_message: null
form_fields:
- cq_2
form_model: player
get_form_fields: null
get_timeout_seconds: null
is_displayed: null
is_waitpage: false
js_vars: null
live_method: null
name: CQ_2
template:
content: "\n{{ include_sibling 'uw_teton_bg.html' }}\n\n\n\n\n\n\n\n
\n
\ In one part of the study, you or your partner will be randomly chosen
to get the opportunity to earn money. The person selected will earn their
money by completing a task that involves counting the number of 1s in matrices
made up of 1s and 0s. \n
\n\n
\n If you are chosen to do the matrix
task to earn money, your task is to count the number of 1s in each matrix.
Your pay from this task will be determined by how many matrices you correctly
answer. If you answer a matrix incorrectly, you will move on to a new matrix.
You will have {{session.config.time_limit}} minutes to earn up to ${{max_budget}}
by completing up to {{session.config.num_correct}} matrices.\n
\n
\n
\ You will each get an opportunity to practice the matrix task. Below is
an example of a {{session.config.m_size}} by {{session.config.m_size}} matrix
identical to what you would see during the task. In this example, there are
{{matrix_sum}} total 1s that you would need to count.\n
\n\n\n
{% for row in matrix %} \n
{% for
cell in row %} \n
{{ cell }}
{% endfor %} \n
{% endfor
%} \n
\n\n
\n {{ C.Q1_ANSWER }}\n
\n \n\n{{ formfields
}}\n\n{{ next_button }}"
javascript: null
title: Comprehension Questions
timeout_seconds: null
timer_text: null
vars_for_template: "import random\n\n# Generate C.M_SIZExC.M_SIZE matrix with
random 0s and 1s\nmatrix = [[random.randint(0, 1) for _ in range(session.config['m_size'])]
for _ in range(session.config['m_size'])]\n\n# Calculate the sum of all 1s in
the matrix\nmatrix_sum = sum(sum(row) for row in matrix)\n\n# Calculate max
earnings from the task\nmax_budget = session.config['x_rate'] * session.config['num_correct']\n\n#
Passing Python variables to the HTML template of the page\nreturn dict(\n matrix=matrix,\n
\ matrix_sum=matrix_sum,\n max_budget = max_budget\n)"
- app_after_this_page: null
before_next_page: null
error_message: null
form_fields:
- cq_3
form_model: player
get_form_fields: null
get_timeout_seconds: null
is_displayed: null
is_waitpage: false
js_vars: null
live_method: null
name: CQ_3
template:
content: "\n{{ include_sibling 'uw_teton_bg.html' }}\n\n\n\n\n\n\n\n
\n
\ In one part of the study, you or your partner will be randomly chosen
to get the opportunity to earn money. The person selected will earn their
money by completing a task that involves counting the number of 1s in matrices
made up of 1s and 0s. \n
\n\n
\n If you are chosen to do the matrix
task to earn money, your task is to count the number of 1s in each matrix.
Your pay from this task will be determined by how many matrices you correctly
answer. If you answer a matrix incorrectly, you will move on to a new matrix.
You will have {{session.config.time_limit}} minutes to earn up to ${{max_budget}}
by completing up to {{session.config.num_correct}} matrices.\n
\n
\n
\ You will each get an opportunity to practice the matrix task. Below is
an example of a {{session.config.m_size}} by {{session.config.m_size}} matrix
identical to what you would see during the task. In this example, there are
{{matrix_sum}} total 1s that you would need to count.\n
\n\n\n
{% for row in matrix %} \n
{% for
cell in row %} \n
{{ cell }}
{% endfor %} \n
{% endfor
%} \n
\n\n
\n {{ C.Q1_ANSWER }}\n
\n \n
\n {{
C.Q2_ANSWER }}\n
\n \n\n{{ formfields }}\n\n{{ next_button }}"
javascript: null
title: Comprehension Questions
timeout_seconds: null
timer_text: null
vars_for_template: "import random\n\n# Generate C.M_SIZExC.M_SIZE matrix with
random 0s and 1s\nmatrix = [[random.randint(0, 1) for _ in range(session.config['m_size'])]
for _ in range(session.config['m_size'])]\n\n# Calculate the sum of all 1s in
the matrix\nmatrix_sum = sum(sum(row) for row in matrix)\n\n# Calculate max
earnings from the task\nmax_budget = session.config['x_rate'] * session.config['num_correct']\n\n#
Passing Python variables to the HTML template of the page\nreturn dict(\n matrix=matrix,\n
\ matrix_sum=matrix_sum,\n max_budget = max_budget\n)"
- app_after_this_page: null
before_next_page: null
error_message: null
form_fields: null
form_model: player
get_form_fields: null
get_timeout_seconds: null
is_displayed: null
is_waitpage: false
js_vars: null
live_method: null
name: CQ_Answers
template:
content: "\n{{ include_sibling 'uw_teton_bg.html' }}\n\n\n\n\n\n\n\n
\n
\ In one part of the study, you or your partner will be randomly chosen
to get the opportunity to earn money. The person selected will earn their
money by completing a task that involves counting the number of 1s in matrices
made up of 1s and 0s. \n
\n\n
\n If you are chosen to do the matrix
task to earn money, your task is to count the number of 1s in each matrix.
Your pay from this task will be determined by how many matrices you correctly
answer. If you answer a matrix incorrectly, you will move on to a new matrix.
You will have {{session.config.time_limit}} minutes to earn up to ${{max_budget}}
by completing up to {{session.config.num_correct}} matrices.\n
\n
\n
\ You will each get an opportunity to practice the matrix task. Below is
an example of a {{session.config.m_size}} by {{session.config.m_size}} matrix
identical to what you would see during the task. In this example, there are
{{matrix_sum}} total 1s that you would need to count.\n
\n\n\n
{% for row in matrix %} \n
{% for
cell in row %} \n
{{ cell }}
{% endfor %} \n
{% endfor
%} \n
\n\n
\n {{ C.Q1_ANSWER }}\n
\n \n
\n {{
C.Q2_ANSWER }}\n
\n \n
\n {{ C.Q3_ANSWER }}\n
\n \n\n{{ formfields
}}\n\n{{ next_button }}"
javascript: null
title: Comprehension Questions
timeout_seconds: null
timer_text: null
vars_for_template: "import random\n\n# Generate C.M_SIZExC.M_SIZE matrix with
random 0s and 1s\nmatrix = [[random.randint(0, 1) for _ in range(session.config['m_size'])]
for _ in range(session.config['m_size'])]\n\n# Calculate the sum of all 1s in
the matrix\nmatrix_sum = sum(sum(row) for row in matrix)\n\n# Calculate max
earnings from the task\nmax_budget = session.config['x_rate'] * session.config['num_correct']\n\n#
Passing Python variables to the HTML template of the page\nreturn dict(\n matrix=matrix,\n
\ matrix_sum=matrix_sum,\n max_budget = max_budget\n)"
- after_all_players_arrive: null
body_text: null
group_by_arrival_time: null
is_displayed: null
is_waitpage: true
name: RET_instructionsEndPage
template: null
title_text: null
wait_for_all_groups: true
- bots: ''
constants:
- datatype: int
js_value: 2
name: PLAYERS_PER_GROUP
- datatype: int
js_value: 3
name: NUM_ROUNDS
- datatype: int
js_value: 3
name: NUM_CORRECT
custom_export: "# Header\nyield [\n 'session_code',\n 'participant_id_in_session',\n
\ 'participant_code',\n 'id_in_group',\n 'group_number'\n]\n\n# Rows\nfor
p in players:\n pp = p.participant\n pg = p.group\n ps = p.session\n
\ \n yield [\n ps.code,\n pp.id_in_session,\n pp.code,\n
\ p.id_in_group,\n pg.id_in_subsession\n ]"
doc: Real-effort task (RET) portion of the experiment. RET is counting the number
of 1s in a matrix of 1s and 0s.
includable_templates:
- content: "\n{%
load otree %}\n\n\n\n"
name: uw_teton_bg
models:
Group:
fields:
- datatype: IntegerField
kwargs:
blank: null
choices: null
initial: null
label: null
max: null
min: null
widget: null
name: budget
- datatype: IntegerField
kwargs:
blank: null
choices: null
initial:
constant: null
expr_type: plain
js_value: 0
label: null
max: null
min: null
widget: null
name: correct
- datatype: FloatField
kwargs:
blank: null
choices: null
initial: null
label: null
max: null
min: null
widget: null
name: earner_id
methods:
- code: "# Access all players in the current group\nplayers = group.get_players()\n\n#
Exit check for conditions that don't require individual updates\nif group.round_number
> 1 and group.correct == C.NUM_CORRECT:\n # Directly carry over the correct
count from the previous round\n group.correct = group.in_round(group.round_number
- 1).correct\n return\n\n# Initialize or update correct counts for players\nfor
p in players:\n # Ensure that player_sum is not None, treat None as an
incorrect guess\n if p.player_sum is None:\n p.last_guess_correct
= False\n current_guess_correct = 0 # This will treat None as an
incorrect guess\n else:\n # Compare player_sum with matrix_sum
and update correct and feedback accordingly\n current_guess_correct
= int(p.player_sum == p.matrix_sum)\n p.last_guess_correct = (p.player_sum
== p.matrix_sum)\n\n # Update the correct count based on the current
guess\n if group.round_number == 1:\n p.correct = current_guess_correct\n
\ else:\n previous_correct = p.in_round(group.round_number - 1).correct\n
\ p.correct = previous_correct + current_guess_correct"
is_method: false
name: check_func
Player:
fields:
- datatype: IntegerField
kwargs:
blank: null
choices: null
initial:
constant: null
expr_type: plain
js_value: 1
label: null
max: null
min: null
widget: null
name: matrix_sum
- datatype: IntegerField
kwargs:
blank: null
choices: null
initial:
constant: null
expr_type: plain
js_value: 0
label:
constant: null
expr_type: plain
js_value: How many 1s are in the above matrix?
max: null
min:
constant: null
expr_type: plain
js_value: 0
widget: null
name: player_sum
- datatype: IntegerField
kwargs:
blank: null
choices: null
initial:
constant: null
expr_type: plain
js_value: 0
label: null
max: null
min:
constant: null
expr_type: plain
js_value: 0
widget: null
name: correct
- datatype: BooleanField
kwargs:
blank: null
choices: null
initial: null
label: null
widget: null
name: last_guess_correct
- datatype: FloatField
kwargs:
blank: null
choices: null
initial:
constant: null
expr_type: plain
js_value: 0
label: null
max: null
min: null
widget: null
name: exit_1
methods:
- code: return session.config['m_size'] * session.config['m_size']
is_method: false
name: player_sum_max
Subsession:
fields: []
methods:
- code: "# pull the matrix you stored in the code‐entry app\nmatrix = subsession.session.vars.get('couple_matrix')\nif
not matrix:\n # safety check in case someone forgot to run grouping first\n
\ raise RuntimeError(\"No couple_matrix in session.vars\")\n# re‐apply
it in this app's subsession\nsubsession.set_group_matrix(matrix)"
is_method: false
name: after_all_players_arrive
name: RET_practice
pages:
- after_all_players_arrive: after_all_players_arrive
body_text: null
group_by_arrival_time: null
is_displayed: null
is_waitpage: true
name: GroupingWaitPage
template: null
title_text: null
wait_for_all_groups: true
- app_after_this_page: null
before_next_page: ''
error_message: null
form_fields: null
form_model: player
get_form_fields: null
get_timeout_seconds: null
is_displayed: "if group.round_number == 1: \n return True"
is_waitpage: false
js_vars: null
live_method: null
name: Intro
template:
content: "{{ include_sibling 'uw_teton_bg.html' }}\n\n
\n Again, you or
your partner will be given the chance to earn money by solving matrices. You
will now be given a chance to practice the matrix task. In this practice round,
both you and your partner will be given the opportunity to solve {{ C.NUM_ROUNDS
}} matrices.\n
\n\n{{ next_button }}"
javascript: null
title: Practice Round
timeout_seconds: null
timer_text: null
vars_for_template: null
- app_after_this_page: null
before_next_page: "if timeout_happened:\n # Default value for any form fields
if timeout occurs, because otherwise they may be left null\n player.player_sum
= 0"
error_message: null
form_fields:
- player_sum
form_model: player
get_form_fields: null
get_timeout_seconds: null
is_displayed: "# Display if it's round 1\nif group.round_number == 1:\n return
True\n\n# Display if it's after round 1 AND is not done with the task\nelif
group.in_round(group.round_number - 1).correct != C.NUM_CORRECT:\n return
True"
is_waitpage: false
js_vars: null
live_method: null
name: Task
template:
content: "\n{{
include_sibling 'uw_teton_bg.html' }}\n\n\n\n\n\n\n\n\n
{% for row in matrix %} \n
{% for cell in
row %} \n
{{ cell }}
{% endfor %} \n
{% endfor %}
\n
\n\n\n\n\n \n\n{{
formfields }}\n\n{{ next_button }}"
javascript: null
title: Practice Task
timeout_seconds: 60
timer_text: null
vars_for_template: "import random\n\n# Generate C.M_SIZExC.M_SIZE matrix with
random 0s and 1s\nmatrix = [[random.randint(0, 1) for _ in range(session.config['m_size'])]
for _ in range(session.config['m_size'])]\n\n# Calculate the sum of all 1s in
the matrix\nmatrix_sum = sum(sum(row) for row in matrix)\n\n# Store the sum
in the player variable\nplayer.matrix_sum = matrix_sum\n\n# Passing Python variables
to the HTML template of the page\nreturn dict(\n matrix=matrix,\n matrix_sum=matrix_sum,\n)"
- after_all_players_arrive: check_func
body_text: null
group_by_arrival_time: null
is_displayed: null
is_waitpage: true
name: EarningWaitPage
template: null
title_text: null
wait_for_all_groups: null
- app_after_this_page: null
before_next_page: null
error_message: null
form_fields: null
form_model: player
get_form_fields: null
get_timeout_seconds: null
is_displayed: "# Display if participant is the earner AND it's round 1\nif group.round_number
== 1:\n return True\n\n# Display if participant is the earner AND it's after
round 1 AND is not done with the task\nelif group.in_round(group.round_number
- 1).correct != C.NUM_CORRECT:\n return True\n\n# Don't display if final
round\nif group.round_number == C.NUM_CORRECT:\n return False"
is_waitpage: false
js_vars: null
live_method: null
name: Feedback
template:
content: "\n{{
include_sibling 'uw_teton_bg.html' }}\n\n\n
\n
\ {% if player.last_guess_correct %}\n
\n
\ Correct! You guessed the right number of 1s.\n
\n {%
else %}\n
\n Incorrect guess. You
will have another chance with a new matrix.\n
\n {% endif %}\n
\ \n \n
\n Number of correct guesses: {{
player.correct }}.\n
\n
\n\n\n{{ next_button }}"
javascript: null
title: Feedback
timeout_seconds: null
timer_text: null
vars_for_template: null
- app_after_this_page: '# Used to skip directly to the next app
return "RET_1"'
before_next_page: null
error_message: null
form_fields: null
form_model: player
get_form_fields: null
get_timeout_seconds: null
is_displayed: "# Display if they are done or we hit the round limit\nif group.round_number
== C.NUM_ROUNDS:\n return True\nelse:\n return False"
is_waitpage: false
js_vars: null
live_method: null
name: Results
template:
content: "\n{{
include_sibling 'uw_teton_bg.html' }}\n\n
\n You have finished the practice
round. You correctly guessed {{ player.correct }} of the {{C.NUM_ROUNDS}}
matrices. We will now move on to the real task.\n
\n\n{{ next_button }}"
javascript: null
title: Results
timeout_seconds: null
timer_text: null
vars_for_template: null
- after_all_players_arrive: null
body_text: null
group_by_arrival_time: null
is_displayed: "# Display if they are done or we hit the round limit\nif group.round_number
== C.NUM_ROUNDS:\n return True\nelse:\n return False"
is_waitpage: true
name: RET_practiceEndPage
template: null
title_text: null
wait_for_all_groups: true
- bots: ''
constants:
- datatype: int
js_value: 2
name: PLAYERS_PER_GROUP
- datatype: int
js_value: 20
name: NUM_ROUNDS
- datatype: str
js_value: 'Time left to complete the matrix task:'
name: TIMER_TEXT
custom_export: "# Header\nyield [\n 'session_code',\n 'participant_id_in_session',\n
\ 'participant_code',\n 'id_in_group',\n 'group_number',\n 'earner_round_1',\n
\ 'budget_1'\n]\n\n# Rows\nfor p in players:\n pp = p.participant\n pg
= p.group\n ps = p.session\n \n # Pull participant fields\n earner_round_1
= p.participant.vars.get('earner_round_1', '')\n budget_1 = p.participant.vars.get('budget_1',
'')\n \n yield [\n ps.code,\n pp.id_in_session,\n pp.code,\n
\ p.id_in_group,\n pg.id_in_subsession,\n earner_round_1,\n
\ budget_1\n ]"
doc: Real-effort task (RET) portion of the experiment. RET is counting the number
of 1s in a matrix of 1s and 0s.
includable_templates:
- content: "\n{%
load otree %}\n\n\n\n"
name: uw_teton_bg
models:
Group:
fields:
- datatype: IntegerField
kwargs:
blank: null
choices: null
initial: null
label: null
max: null
min: null
widget: null
name: budget
- datatype: IntegerField
kwargs:
blank: null
choices: null
initial:
constant: null
expr_type: plain
js_value: 0
label: null
max: null
min: null
widget: null
name: correct
- datatype: FloatField
kwargs:
blank: null
choices: null
initial: null
label: null
max: null
min: null
widget: null
name: earner_id
methods:
- code: "# Access all players in the current group\nplayers = group.get_players()\n\n#
Exit check for conditions that don't require individual updates\nif group.round_number
> 1 and group.correct == session.config['num_correct']:\n # Directly
carry over the correct count from the previous round\n group.correct
= group.in_round(group.round_number - 1).correct\n return\n\n# Identify
the player who did the task in the first round\nptask = group.get_player_by_id(group.in_round(1).earner_id)\n\n#
Initialize or update correct counts for players\nfor p in players:\n #
Ensure that player_sum is not None, treat None as an incorrect guess\n if
p.player_sum is None:\n p.last_guess_correct = False\n current_guess_correct
= 0 # This will treat None as an incorrect guess\n else:\n #
Compare player_sum with matrix_sum and update correct and feedback accordingly\n
\ current_guess_correct = int(p.player_sum == p.matrix_sum)\n p.last_guess_correct
= (p.player_sum == p.matrix_sum)\n\n # Update the correct count based
on the current guess\n if group.round_number == 1:\n p.correct
= current_guess_correct\n else:\n previous_correct = p.in_round(group.round_number
- 1).correct\n p.correct = previous_correct + current_guess_correct\n\n
\ # Update the group.correct counter if this is the player who did the
task\n if p == ptask:\n group.correct = p.correct"
is_method: false
name: check_func
- code: "# Defining player that did the task\nptask = group.get_player_by_id(group.in_round(1).earner_id)\n\n#
Setting the budget based on how many were correct and the pay per correct
answer\ngroup.budget = ptask.correct * session.config['x_rate']\n\n# Defining
the players\nplayers = group.get_players()\n\n# Store budget at the participant
level for the next app\nfor p in players:\n p.participant.budget_1 =
group.budget"
is_method: false
name: RET_payoff
- code: "import random\n\n# Randomly choosing one of the group members to be
the earner in round 1\nr = random.randint(1,2)\n\n# Gather players \nplayers
= group.get_players()\n\n# Initialize earner_id at the group level\ngroup.earner_id
= None\n\n# Assign roles based on random draw\nfor p in players:\n if
p.id_in_group == r:\n p.participant.earner_round_1 = 1\n group.earner_id
= p.id_in_group # Store the earner's id_in_group at the group level\n else:\n
\ p.participant.earner_round_1 = 0\n \n p.exit_1 = 0"
is_method: false
name: assign_earner_1
- code: "# Defining players\nplayers = group.get_players()\n\n# Setting the
exit condition to avoid duplicating the results page\nfor p in players:\n
\ p.exit_1 = 1"
is_method: false
name: exit
Player:
fields:
- datatype: IntegerField
kwargs:
blank: null
choices: null
initial:
constant: null
expr_type: plain
js_value: 1
label: null
max: null
min: null
widget: null
name: matrix_sum
- datatype: IntegerField
kwargs:
blank: null
choices: null
initial:
constant: null
expr_type: plain
js_value: 0
label:
constant: null
expr_type: plain
js_value: How many 1s are in the above matrix?
max: null
min:
constant: null
expr_type: plain
js_value: 0
widget: null
name: player_sum
- datatype: IntegerField
kwargs:
blank: null
choices: null
initial:
constant: null
expr_type: plain
js_value: 0
label: null
max: null
min:
constant: null
expr_type: plain
js_value: 0
widget: null
name: correct
- datatype: BooleanField
kwargs:
blank: null
choices: null
initial: null
label: null
widget: null
name: last_guess_correct
- datatype: FloatField
kwargs:
blank: null
choices: null
initial:
constant: null
expr_type: plain
js_value: 0
label: null
max: null
min: null
widget: null
name: exit_1
- datatype: IntegerField
kwargs:
blank: null
choices:
constant: null
expr_type: plain
js_value:
- - 1
- The money goes to the participant who earned it through the matrix
task
- - 2
- The money is split evenly between both partners
- - 3
- The participant chosen to spend money keeps all remaining funds
initial: null
label:
constant: null
expr_type: plain
js_value: What happens to the money in the joint account at the end of
the study?
max: null
min: null
widget:
constant: null
expr_type: plain
js_value: RadioSelect
name: cq
- datatype: IntegerField
kwargs:
blank: null
choices:
constant: null
expr_type: plain
js_value:
- - 1
- The money goes to the participant who earned it through the matrix
task
- - 2
- The money is split evenly between both partners
- - 3
- The participant chosen to spend money keeps all remaining funds
initial: null
label:
constant: null
expr_type: plain
js_value: What happens to the money in the joint account at the end of
the study?
max: null
min: null
widget:
constant: null
expr_type: plain
js_value: RadioSelect
name: cq_try2
methods:
- code: return session.config['m_size'] * session.config['m_size']
is_method: false
name: player_sum_max
Subsession:
fields: []
methods:
- code: "# pull the matrix you stored in the code‐entry app\nmatrix = subsession.session.vars.get('couple_matrix')\nif
not matrix:\n # safety check in case someone forgot to run grouping first\n
\ raise RuntimeError(\"No couple_matrix in session.vars\")\n# re‐apply
it in this app's subsession\nsubsession.set_group_matrix(matrix)"
is_method: false
name: after_all_players_arrive
name: RET_1
pages:
- after_all_players_arrive: after_all_players_arrive
body_text: null
group_by_arrival_time: null
is_displayed: null
is_waitpage: true
name: GroupingWaitPage
template: null
title_text: null
wait_for_all_groups: true
- after_all_players_arrive: assign_earner_1
body_text: null
group_by_arrival_time: null
is_displayed: "if group.round_number == 1: \n return True"
is_waitpage: true
name: RoleAssignmentWaitPage
template: null
title_text: null
wait_for_all_groups: null
- app_after_this_page: null
before_next_page: '# Set a global ''task_min'' minute timer for all the task pages
participant = player.participant
import time
# Defining the global timer amount using the session.config
participant.expiry = time.time() + session.config[''task_min'']*60'
error_message: null
form_fields: null
form_model: player
get_form_fields: null
get_timeout_seconds: null
is_displayed: "if group.round_number == 1: \n return True"
is_waitpage: false
js_vars: null
live_method: null
name: RoleAssignment
template:
content: "\n{{
include_sibling 'uw_teton_bg.html' }}\n\n\n{{ if player.participant.earner_round_1 == 1 }}\n
\n You
were randomly selected to earn money by completing the earnings task. You
will have {{ session.config.time_limit }} minutes to earn up to ${{max_budget}}
by completing {{ session.config.num_correct }} matrices.\n
\n\n\n{{ else }}\n
\n You were
not selected to earn money by completing the earnings task. Please wait for
further instructions.\n
\n\n{{ endif}}\n\n{{ next_button }}"
javascript: null
title: Role Assignment
timeout_seconds: null
timer_text: null
vars_for_template: '# Calculate the maximum possible earnings from the task
max_budget = session.config[''x_rate''] * session.config[''num_correct'']
# Passing Python variables to the HTML template of the page
return dict(max_budget = max_budget)'
- app_after_this_page: null
before_next_page: "if timeout_happened:\n # Default value for any form fields
if timeout occurs, because otherwise they may be left null\n player.player_sum
= 0"
error_message: null
form_fields:
- player_sum
form_model: player
get_form_fields: null
get_timeout_seconds: '# Using the global timer set at RoleAssignment
participant = player.participant
import time
# Passing the global timer to the HTML template of the page
return participant.expiry - time.time()'
is_displayed: "import time\n\n# Display if participant is the earner AND it's
round 1 AND global timer isn't 0\nif player.participant.earner_round_1 == 1
and group.round_number == 1 and max(participant.expiry - time.time(), 0) > 3:\n
\ return True\n\n# Display if participant is the earner AND it's after round
1 AND is not done with the task AND global timer isn't 0\nelif player.participant.earner_round_1
== 1 and group.in_round(group.round_number - 1).correct != session.config['num_correct']
and max(participant.expiry - time.time(), 0) > 3:\n return True"
is_waitpage: false
js_vars: null
live_method: null
name: Task
template:
content: "\n{{
include_sibling 'uw_teton_bg.html' }}\n\n\n\n\n\n\n\n\n
{% for row in matrix %} \n
{% for cell in
row %} \n
{{ cell }}
{% endfor %} \n
{% endfor %}
\n
\n\n\n\n\n \n\n{{
formfields }}\n\n{{ next_button }}"
javascript: null
title: Matrix Task
timeout_seconds: null
timer_text: 'Time left to complete the matrix task:'
vars_for_template: "import random\n\n# Generate session.config.m_size x session.config.m_size
matrix with random 0s and 1s\nmatrix = [[random.randint(0, 1) for _ in range(session.config['m_size'])]
for _ in range(session.config['m_size'])]\n\n# Calculate the sum of all 1s in
the matrix\nmatrix_sum = sum(sum(row) for row in matrix)\n\n# Store the sum
in the player variable\nplayer.matrix_sum = matrix_sum\n\n# Passing Python variables
to the HTML template of the page\nreturn dict(\n matrix=matrix,\n matrix_sum=matrix_sum,\n)"
- after_all_players_arrive: check_func
body_text: null
group_by_arrival_time: null
is_displayed: "# Display if earner\nif participant.earner_round_1 == 1:\n return
True"
is_waitpage: true
name: EarningWaitPage
template: null
title_text: null
wait_for_all_groups: null
- app_after_this_page: null
before_next_page: null
error_message: null
form_fields: null
form_model: player
get_form_fields: null
get_timeout_seconds: '# Using the global timer set at RoleAssignment
participant = player.participant
import time
# Passing the global timer to the HTML template of the page
return participant.expiry - time.time()'
is_displayed: "import time\n\n# Display if participant is the earner AND it's
round 1 AND global timer isn't 0\nif participant.earner_round_1 == 1 and group.round_number
== 1 and max(participant.expiry - time.time(), 0) > 3:\n return True\n\n#
Display if participant is the earner AND it's after round 1 AND is not done
with the task AND global timer isn't 0\nelif participant.earner_round_1 == 1
and group.in_round(group.round_number - 1).correct != session.config['num_correct']
and max(participant.expiry - time.time(), 0) > 3:\n return True"
is_waitpage: false
js_vars: null
live_method: null
name: Feedback
template:
content: "\n{{
include_sibling 'uw_teton_bg.html' }}\n\n\n\n\n\n
\n {% if player.last_guess_correct %}\n
\n Correct! You guessed the right number
of 1s.\n
\n {% else %}\n
\n
\ Incorrect guess. You will have another chance with a new matrix.\n
\
\n {% endif %}\n \n \n
\n Number
of correct guesses: {{ player.correct }}.\n
\n
\n\n\n{{ next_button }}"
javascript: null
title: Feedback
timeout_seconds: null
timer_text: 'Time left to complete the matrix task:'
vars_for_template: null
- app_after_this_page: null
before_next_page: '# Used to manually reach the exit condition to get to the results
screen if timed out
group.round_number = session.config[''num_rounds'']'
error_message: null
form_fields: null
form_model: player
get_form_fields: null
get_timeout_seconds: null
is_displayed: 'import time
# Only display this page if the participant ran out of time on the matrix task
return (player.participant.expiry - time.time()) <= 3'
is_waitpage: false
js_vars: null
live_method: null
name: TimeExpired
template:
content: "{{ include_sibling 'uw_teton_bg.html' }}\n\n
\n The time allotted
for this task has ended. Please proceed to the next part of the experiment.\n
\n\n{{
next_button }}"
javascript: null
title: Time Limit Reached
timeout_seconds: null
timer_text: null
vars_for_template: null
- after_all_players_arrive: null
body_text: null
group_by_arrival_time: null
is_displayed: "# If the participant is not the earner, have them sit on this wait
page\nif participant.earner_round_1 != 1:\n return True"
is_waitpage: true
name: NotEarningWaitPage
template: null
title_text: Please wait for further instructions.
wait_for_all_groups: null
- after_all_players_arrive: RET_payoff
body_text: null
group_by_arrival_time: null
is_displayed: "# Only reach this page if the group has gotten enough matrices
correct OR they hit the max number of rounds\nif group.correct == session.config['num_correct']
or group.round_number == session.config['num_rounds']:\n return True"
is_waitpage: true
name: PayoffWaitPage
template: null
title_text: null
wait_for_all_groups: null
- after_all_players_arrive: null
body_text: null
group_by_arrival_time: null
is_displayed: "# Display if they are done or we hit the round limit\nif group.correct
== session.config['num_correct'] or group.round_number == session.config['num_rounds']:\n
\ return True\nelse:\n return False"
is_waitpage: true
name: ExitWaitPage
template: null
title_text: null
wait_for_all_groups: true
- app_after_this_page: null
before_next_page: null
error_message: null
form_fields: null
form_model: player
get_form_fields: null
get_timeout_seconds: null
is_displayed: "# Display if they are done or we hit the round limit\nif group.correct
== session.config['num_correct'] or group.round_number == session.config['num_rounds']:\n
\ return True\nelse:\n return False\n\n# Only show the page if we haven't
already shown it\nif player.participant.vars.get('my_page_shown', False):\n
\ return False\nelse:\n player.participant.vars['my_page_shown'] = True\n
\ return True"
is_waitpage: false
js_vars: null
live_method: null
name: Results
template:
content: "\n{{
include_sibling 'uw_teton_bg.html' }}\n\n{{ if player.participant.earner_round_1
== 1 }}
\n You got {{ player.correct }} of the matrices correct. For
every correct matrix, you receive ${{ session.config.x_rate }}. You earned
${{ group.budget }}.\n
\n\n{{ else }}
\n Your partner has completed
the earnings task. They earned ${{ group.budget }}.\n
\n\n{{ endif }}\n\n{{
next_button }}"
javascript: null
title: Results
timeout_seconds: null
timer_text: null
vars_for_template: null
- app_after_this_page: null
before_next_page: null
error_message: null
form_fields:
- cq
form_model: player
get_form_fields: null
get_timeout_seconds: null
is_displayed: "# Display if they are done or we hit the round limit\nif group.correct
== session.config['num_correct'] or group.round_number == session.config['num_rounds']:\n
\ return True\nelse:\n return False"
is_waitpage: false
js_vars: null
live_method: null
name: JointAccount
template:
content: "\n{{ include_sibling 'uw_teton_bg.html' }}\n\n\n\n\n\n\n\n
\n
\ The money {{ if player.participant.earner_round_1 == 1 }}you{{ else }}your
partner{{ endif }} earned from the matrix task has been placed in a joint
account you share with your partner. At the end of the study, the money remaining
in this joint account will be split evenly between you and your partner. For
example, if there were $20 remaining in the joint account at the end of the
study, you would each be given $10.\n
\n\n
\n There is ${{ group.budget
}} in the joint account. In this part of the study, you or your partner will
be randomly chosen to receive the opportunity to spend the money {{ if player.participant.earner_round_1
== 1 }}you{{ else }}your partner{{ endif }} earned. The participant who is
not given the opportunity to spend money will wait for further instructions.\n
\n\n \n\n{{
formfields }}\n\n{{ next_button }}"
javascript: null
title: Joint Account
timeout_seconds: null
timer_text: null
vars_for_template: null
- app_after_this_page: null
before_next_page: null
error_message: null
form_fields:
- cq_try2
form_model: player
get_form_fields: null
get_timeout_seconds: null
is_displayed: "# Display if they are done or we hit the round limit and If participant
got comprehension question wrong, show them this page\nif group.correct == session.config['num_correct']
and player.cq != 2 or group.round_number == session.config['num_rounds'] and
player.cq != 2:\n return True\nelse:\n return False"
is_waitpage: false
js_vars: null
live_method: null
name: CQ
template:
content: "\n{{
include_sibling 'uw_teton_bg.html' }}\n\n\n\n\n\n\n\n\nIncorrect.
At the end of the study, all funds in the joint account are split evenly between
you and your partner.
\n\n{{ formfields }}\n\n{{ next_button }}"
javascript: null
title: Joint Account
timeout_seconds: null
timer_text: null
vars_for_template: null
- app_after_this_page: '# Used to skip directly to the next app
return "Auction_instructions"'
before_next_page: null
error_message: null
form_fields: null
form_model: player
get_form_fields: null
get_timeout_seconds: null
is_displayed: "# Display if they are done or we hit the round limit\nif group.correct
== session.config['num_correct'] or group.round_number == session.config['num_rounds']:\n
\ return True\nelse:\n return False"
is_waitpage: false
js_vars: null
live_method: null
name: JointAccountEnd
template:
content: "\n{{
include_sibling 'uw_teton_bg.html' }}\n\n\n\n\n\n\n\n\n{{ if player.cq == 2 or player.cq_try2
== 2 }}Correct!{{ else }}Incorrect.{{ endif }} At the end of the study, all funds in
the joint account are split evenly between you and your partner.
\n\n{{
formfields }}\n\n{{ next_button }}"
javascript: null
title: Joint Account
timeout_seconds: null
timer_text: null
vars_for_template: null
- bots: ''
constants:
- datatype: int
js_value: 2
name: PLAYERS_PER_GROUP
- datatype: int
js_value: 1
name: NUM_ROUNDS
custom_export: "# Header\nyield [\n 'session_code',\n 'participant_id_in_session',\n
\ 'participant_code',\n 'id_in_group', \n 'group_number',\n 'cq_1',
'cq_1_try2',\n 'cq_2', 'cq_2_try2',\n 'cq_3', 'cq_3_try2',\n 'cq_4',
'cq_4_try2',\n]\n\n# Rows\nfor p in players:\n pp = p.participant\n pg =
p.group\n ps = p.session\n \n yield [\n ps.code,\n pp.id_in_session,\n
\ pp.code,\n p.id_in_group,\n pg.id_in_subsession,\n p.cq_1,
p.cq_1_try2, \n p.cq_2, p.cq_2_try2, \n p.cq_3, p.cq_3_try2, \n
\ p.cq_4, p.cq_4_try2\n ]"
doc: Provides instructions for the spending task, with comprehension questions for
additional understanding.
includable_templates:
- content: "\n{%
load otree %}\n\n\n\n"
name: uw_teton_bg
models:
Group:
fields:
- datatype: IntegerField
kwargs:
blank: null
choices: null
initial: null
label: null
max: null
min: null
widget: null
name: budget
methods:
- code: "# Gather players\nplayers = group.get_players()\n\n# Define the group
budget from RET1\ngroup.budget = players[0].participant.budget_1\n\n# Set
default for comprehension questions\nfor p in players:\n p.cq_1 = \"NA\"\n
\ p.cq_1_try2 = \"NA\"\n p.cq_2 = \"NA\"\n p.cq_2_try2 = \"NA\"\n
\ p.cq_3 = \"NA\"\n p.cq_3_try2 = \"NA\"\n p.cq_4 = \"NA\"\n p.cq_4_try2
= \"NA\"\n\n# Set default for winner_X checks\nfor p in players:\n p.participant.winner_1
= 0\n p.participant.winner_2 = 0"
is_method: false
name: set_budget
Player:
fields:
- datatype: StringField
kwargs:
blank: null
choices:
constant: null
expr_type: plain
js_value:
- - '1'
- You pay the amount the computer bid
- - '2'
- You pay the amount you bid
- - '3'
- You pay the average of your bid and the computer's bid
initial: null
label:
constant: null
expr_type: plain
js_value: In this auction, if you win, how much do you pay?
widget:
constant: null
expr_type: plain
js_value: RadioSelect
name: cq_1
- datatype: StringField
kwargs:
blank: null
choices:
constant: null
expr_type: plain
js_value:
- - '1'
- You pay the amount the computer bid
- - '2'
- You pay the amount you bid
- - '3'
- You pay the average of your bid and the computer's bid
initial: null
label:
constant: null
expr_type: plain
js_value: In this auction, if you win, how much do you pay?
widget:
constant: null
expr_type: plain
js_value: RadioSelect
name: cq_1_try2
- datatype: StringField
kwargs:
blank: null
choices:
constant: null
expr_type: plain
js_value:
- - '1'
- You should bid more than $50
- - '2'
- You should bid exactly $50
- - '3'
- You should bid less than $50
initial: null
label:
constant: null
expr_type: plain
js_value: If you think an item is worth $50 to you, what amount should
you bid in this auction?
widget:
constant: null
expr_type: plain
js_value: RadioSelect
name: cq_2
- datatype: StringField
kwargs:
blank: null
choices:
constant: null
expr_type: plain
js_value:
- - '1'
- You should bid more than $50
- - '2'
- You should bid exactly $50
- - '3'
- You should bid less than $50
initial: null
label:
constant: null
expr_type: plain
js_value: If you think an item is worth $50 to you, what amount should
you bid in this auction?
widget:
constant: null
expr_type: plain
js_value: RadioSelect
name: cq_2_try2
- datatype: StringField
kwargs:
blank: null
choices:
constant: null
expr_type: plain
js_value:
- - '1'
- You lose the auction and pay nothing
- - '2'
- You win the auction and pay $75
- - '3'
- You win the auction and pay $60
initial: null
label:
constant: null
expr_type: plain
js_value: If you bid $75 and the computer randomly selects $60, what happens?
widget:
constant: null
expr_type: plain
js_value: RadioSelect
name: cq_3
- datatype: StringField
kwargs:
blank: null
choices:
constant: null
expr_type: plain
js_value:
- - '1'
- You lose the auction and pay nothing
- - '2'
- You win the auction and pay $75
- - '3'
- You win the auction and pay $60
initial: null
label:
constant: null
expr_type: plain
js_value: If you bid $75 and the computer randomly selects $60, what happens?
widget:
constant: null
expr_type: plain
js_value: RadioSelect
name: cq_3_try2
- datatype: StringField
kwargs:
blank: null
choices:
constant: null
expr_type: plain
js_value:
- - '1'
- You win the auction, get red chair, and you get $800
at the end of the study
- - '2'
- You win the auction, get red chair, and you get $400
and your partner gets $400 at the end of the study
- - '3'
- You lost the auction and you get $800 at the end of the study
initial: null
label:
constant: null
expr_type: plain
js_value: Now that you know how this auction works, let’s put this in
the context of the study. You will be asked to bid on an item using
money from the joint account with your partner. Imagine that you and
your partner had $1,000 in the joint account. Remember, at the end of
the study, anything that is not spent will be equally split between
the two of you. Imagine that you bid $200 on the red chair, and the
computer chooses $200. What is the outcome of the auction and your final
payment for the study?
widget:
constant: null
expr_type: plain
js_value: RadioSelect
name: cq_4
- datatype: StringField
kwargs:
blank: null
choices:
constant: null
expr_type: plain
js_value:
- - '1'
- You win the auction, get red chair, and you get $800
at the end of the study
- - '2'
- You win the auction, get red chair, and you get $400
and your partner gets $400 at the end of the study
- - '3'
- You lose the auction and you get $800 at the end of
the study
initial: null
label:
constant: null
expr_type: plain
js_value: You will be asked to bid on an item using money from the joint
account with your partner. Imagine that you and your partner had $1,000
in the joint account. Remember, at the end of the study, anything
that is not spent will be equally split between the two of you.
Imagine that you bid $200 on the red chair, and the computer chooses
$200. What is the outcome of the auction and your final payment for
the study?
widget:
constant: null
expr_type: plain
js_value: RadioSelect
name: cq_4_try2
methods: []
Subsession:
fields: []
methods:
- code: "# pull the matrix you stored in the code‐entry app\nmatrix = subsession.session.vars.get('couple_matrix')\nif
not matrix:\n # safety check in case someone forgot to run grouping first\n
\ raise RuntimeError(\"No couple_matrix in session.vars\")\n# re‐apply
it in this app's subsession\nsubsession.set_group_matrix(matrix)"
is_method: false
name: after_all_players_arrive
name: Auction_instructions
pages:
- after_all_players_arrive: after_all_players_arrive
body_text: null
group_by_arrival_time: null
is_displayed: null
is_waitpage: true
name: GroupingWaitPage
template: null
title_text: null
wait_for_all_groups: true
- after_all_players_arrive: null
body_text: null
group_by_arrival_time: null
is_displayed: null
is_waitpage: true
name: AuctionInstructionsStartPage
template: null
title_text: null
wait_for_all_groups: true
- after_all_players_arrive: set_budget
body_text: null
group_by_arrival_time: null
is_displayed: null
is_waitpage: true
name: SetBudgetWaitPage
template: null
title_text: null
wait_for_all_groups: null
- app_after_this_page: null
before_next_page: null
error_message: null
form_fields:
- cq_1
form_model: player
get_form_fields: null
get_timeout_seconds: null
is_displayed: '# If participant is the spender, show them this page
return participant.spender == 1'
is_waitpage: false
js_vars: null
live_method: null
name: SpenderInstructions1
template:
content: "\n{{ include_sibling 'uw_teton_bg.html' }}\n\n\n\n\n\n\n\n
\n
\ You have been selected to spend the money {{ if player.participant.earner_round_1
== 1 }}you{{ else }} your partner{{ endif }} earned that is in the joint account.
You will spend the money by participating in a special type of auction. This
auction works differently from regular auctions you might be familiar with.\n
\n\n\n
\
In this auction, you're not competing with other people. Instead,
your bid will be compared with a random bid generated by the computer.
\n
\
If your bid is greater than or equal to the computer's random bid,
you win the auction. If your bid is lower than the computer's bid, you lose
the auction.
\n
If you win, you don't pay your own bid amount.
Instead, you pay the computer's (lower) bid amount.
\n\n\n
\n For
example, suppose that you were asked to state your bid to purchase a red chair.
Also, suppose we paid you a larger amount of $1,000 to participate in this
study. Your payment from participating in this study will be this amount minus
anything you spend on the chair.\n
\n\n
\n Let's say you decide to
bid $100 to purchase the red chair. Now we'll consider two example prices:\n
\n\n
\n Scenario 1: The computer randomly draws a bid of
$82.\n
\n\n
\n Since your bid ($100) is higher than the computer's
bid ($82), you WIN the auction! You get to purchase the red chair,
and you pay $82 (the computer's bid), not your bid of $100. So your final
payment are $1,000 - $82 = $918.\n
\n\n
\n Scenario 2:
The computer randomly draws a bid of $110.\n
\n\n
\n Since your bid
($100) is lower than the computer's bid ($82), you LOSE the
auction! You don't get the red chair and don't pay anything. So, your final
earnings are $1,000.\n
\n\n{{ formfields }}\n\n{{ next_button }}"
javascript: "// This script is included to ensure that if tags are included
in form fields they are observed\n$(document).ready(function (e) {\n labels
= document.getElementsByTagName(\"label\");\n\n for (var i = 0; i < labels.length;
i++) {\n labels[i].innerHTML = labels[i].innerHTML.replaceAll(\"<\",
\"<\").\n replaceAll(\">\", \">\");\n }\n});"
title: Instructions
timeout_seconds: null
timer_text: null
vars_for_template: null
- app_after_this_page: null
before_next_page: null
error_message: null
form_fields:
- cq_1_try2
form_model: player
get_form_fields: null
get_timeout_seconds: null
is_displayed: '# If participant is the spender and got comprehension question
wrong, show them this page
return participant.spender == 1 and player.cq_1 != "1"'
is_waitpage: false
js_vars: null
live_method: null
name: CQ_1
template:
content: "\n{{
include_sibling 'uw_teton_bg.html' }}\n\n\n\n\n\n\n\n\nIncorrect.
If you win the auction, you pay the amount the computer bid.
\n\n{{
formfields }}\n\n{{ next_button }}"
javascript: "// This script is included to ensure that if tags are included
in form fields they are observed\n$(document).ready(function (e) {\n labels
= document.getElementsByTagName(\"label\");\n\n for (var i = 0; i < labels.length;
i++) {\n labels[i].innerHTML = labels[i].innerHTML.replaceAll(\"<\",
\"<\").\n replaceAll(\">\", \">\");\n }\n});"
title: Comprehension Question
timeout_seconds: null
timer_text: null
vars_for_template: null
- app_after_this_page: null
before_next_page: null
error_message: null
form_fields:
- cq_2
form_model: player
get_form_fields: null
get_timeout_seconds: null
is_displayed: '# If participant is the spender, show them this page
return participant.spender == 1'
is_waitpage: false
js_vars: null
live_method: null
name: SpenderInstructions2
template:
content: "\n{{ include_sibling 'uw_teton_bg.html' }}\n\n\n\n\n\n\n\n\n{{ if player.cq_1
== \"1\" or player.cq_1_try2 == \"1\" }}Correct!{{
else }}Incorrect.{{ endif }} If you win
the auction, you pay the amount the computer bid.
\n\n
\n
\ Tips for How to Bid\n
\n\n
\n The best bidding strategy
in this type of auction is to bid exactly how much the item is worth to
you. Here's why:\n
\n\n
\n Let's say you decide the red chair
is worth $200 to you. This means you'd be equally happy keeping your money
or spending $200 to buy the red chair. Is your best strategy bidding more
than $200, less than $200, or exactly $200? The answer is exactly $200.\n
\n\n
\n
\ If you were to bid less than $200 (say $100), then the auction might be
won by the computer (if its random bid was $150, say). You would not be able
to buy the red chair even though you were truly willing to pay more than $150.
You miss out on a good deal. Therefore, bidding less than your true value
is not a good strategy.\n
\n\n
\n If you bid more than $200 (say $300),
you might win the auction but have to pay a higher price than your value of
the red chair. If the computer bids $250, you win the auction but have to
pay $250, which is more than the $200 the chair is worth to you. You end up
with a bad deal. Therefore, bidding more than your true value is not a good
strategy.\n
\n\n
\n Let's say you choose to bid exactly $200. If the
computer bids less than $200, you win and pay less than what the chair is
worth to you. If the computer bids more than $200, you lose, but that's okay
because the price would have been too high anyway. You do not risk paying
more for the good than you want to, and you will never pay more than the computer’s
bid anyway.\n
\n\n{{ formfields }}\n\n{{ next_button }}"
javascript: "// This script is included to ensure that if tags are included
in form fields they are observed\n$(document).ready(function (e) {\n labels
= document.getElementsByTagName(\"label\");\n\n for (var i = 0; i < labels.length;
i++) {\n labels[i].innerHTML = labels[i].innerHTML.replaceAll(\"<\",
\"<\").\n replaceAll(\">\", \">\");\n }\n});"
title: Instructions
timeout_seconds: null
timer_text: null
vars_for_template: null
- app_after_this_page: null
before_next_page: null
error_message: null
form_fields:
- cq_2_try2
form_model: player
get_form_fields: null
get_timeout_seconds: null
is_displayed: '# If participant is the spender and got comprehension question
wrong, show them this page
return participant.spender == 1 and player.cq_2 != "2"'
is_waitpage: false
js_vars: null
live_method: null
name: CQ_2
template:
content: "\n{{
include_sibling 'uw_teton_bg.html' }}\n\n\n\n\n\n\n\n\nIncorrect.
In this auction you should bid exactly how much you value the item.
\n\n{{ formfields }}\n\n{{ next_button }}"
javascript: "// This script is included to ensure that if tags are included
in form fields they are observed\n$(document).ready(function (e) {\n labels
= document.getElementsByTagName(\"label\");\n\n for (var i = 0; i < labels.length;
i++) {\n labels[i].innerHTML = labels[i].innerHTML.replaceAll(\"<\",
\"<\").\n replaceAll(\">\", \">\");\n }\n});"
title: Comprehension Question
timeout_seconds: null
timer_text: null
vars_for_template: null
- app_after_this_page: null
before_next_page: null
error_message: null
form_fields:
- cq_3
form_model: player
get_form_fields: null
get_timeout_seconds: null
is_displayed: '# If participant is the spender, show them this page
return participant.spender == 1'
is_waitpage: false
js_vars: null
live_method: null
name: SpenderInstructions3
template:
content: "\n{{ include_sibling 'uw_teton_bg.html' }}\n\n\n\n\n\n\n\n\n{{ if player.cq_2
== \"2\" or player.cq_2_try2 == \"2\" }}Correct!{{
else }}Incorrect.{{ endif }} In this auction
you should bid exactly how much you value the item, which in this example
is $50.
\n\n
\n Final Notes\n
\n\n
\n
In
this auction, you should always bid the exact maximum amount you would be
willing to pay.
\n
You never pay more than what the computer bids.
\n
\
If you don't want the item at all, you should bid zero. Since the
computer's bid is always positive, you'll lose the auction and keep all your
money
\n
\n\n{{ formfields }}\n\n{{ next_button }}"
javascript: "// This script is included to ensure that if tags are included
in form fields they are observed\n$(document).ready(function (e) {\n labels
= document.getElementsByTagName(\"label\");\n\n for (var i = 0; i < labels.length;
i++) {\n labels[i].innerHTML = labels[i].innerHTML.replaceAll(\"<\",
\"<\").\n replaceAll(\">\", \">\");\n }\n});"
title: Instructions
timeout_seconds: null
timer_text: null
vars_for_template: null
- app_after_this_page: null
before_next_page: null
error_message: null
form_fields:
- cq_3_try2
form_model: player
get_form_fields: null
get_timeout_seconds: null
is_displayed: '# If participant is the spender and got comprehension question
wrong, show them this page
return participant.spender == 1 and player.cq_3 != "3"'
is_waitpage: false
js_vars: null
live_method: null
name: CQ_3
template:
content: "\n{{
include_sibling 'uw_teton_bg.html' }}\n\n\n\n\n\n\n\n\nIncorrect.
If your bid is higher than the computer's, you will win the auction and pay
the computer's bid.
\n\n{{ formfields }}\n\n{{ next_button }}"
javascript: "// This script is included to ensure that if tags are included
in form fields they are observed\n$(document).ready(function (e) {\n labels
= document.getElementsByTagName(\"label\");\n\n for (var i = 0; i < labels.length;
i++) {\n labels[i].innerHTML = labels[i].innerHTML.replaceAll(\"<\",
\"<\").\n replaceAll(\">\", \">\");\n }\n});"
title: Comprehension Questions
timeout_seconds: null
timer_text: null
vars_for_template: null
- app_after_this_page: null
before_next_page: null
error_message: null
form_fields:
- cq_4
form_model: player
get_form_fields: null
get_timeout_seconds: null
is_displayed: '# If participant is the spender, show them this page
return participant.spender == 1'
is_waitpage: false
js_vars: null
live_method: null
name: SpenderInstructions4
template:
content: "\n{{
include_sibling 'uw_teton_bg.html' }}\n\n\n\n\n\n\n\n\nIncorrect.
If you bid $200 on the chair and the computer chooses $200, you win
the auction, paying $200 and getting the red chair. This means the money remaining
in the joint account is $1,000 - $200 = $800. At the end of the study, whatever
is left in the joint account is split equally between you and your partner.
So, you will get the red chair, receive $400, and your partner will receive
$400.
\n\n{{ formfields }}\n\n{{ next_button }}"
javascript: "// This script is included to ensure that if tags are included
in form fields they are observed\n$(document).ready(function (e) {\n labels
= document.getElementsByTagName(\"label\");\n\n for (var i = 0; i < labels.length;
i++) {\n labels[i].innerHTML = labels[i].innerHTML.replaceAll(\"<\",
\"<\").\n replaceAll(\">\", \">\");\n }\n});"
title: Instructions
timeout_seconds: null
timer_text: null
vars_for_template: null
- app_after_this_page: null
before_next_page: null
error_message: null
form_fields:
- cq_4_try2
form_model: player
get_form_fields: null
get_timeout_seconds: null
is_displayed: '# If participant is the spender and got comprehension question
wrong, show them this page
return participant.spender == 1 and player.cq_4 != "2"'
is_waitpage: false
js_vars: null
live_method: null
name: CQ_4
template:
content: "\n{{
include_sibling 'uw_teton_bg.html' }}\n\n\n\n\n\n\n\n\nIncorrect.
If you bid $200 on the chair and the computer chooses $200, you win
the auction, paying $200 and getting the red chair. This means the money remaining
in the joint account is $1,000 - $200 = $800. At the end of the study, whatever
is left in the joint account is split equally between you and your partner.
So, you will get the red chair, receive $400, and your partner will receive
$400.
\n\n{{ formfields }}\n\n{{ next_button }}"
javascript: "// This script is included to ensure that if tags are included
in form fields they are observed\n$(document).ready(function (e) {\n labels
= document.getElementsByTagName(\"label\");\n\n for (var i = 0; i < labels.length;
i++) {\n labels[i].innerHTML = labels[i].innerHTML.replaceAll(\"<\",
\"<\").\n replaceAll(\">\", \">\");\n }\n});"
title: Comprehension Questions
timeout_seconds: null
timer_text: null
vars_for_template: null
- app_after_this_page: null
before_next_page: null
error_message: null
form_fields: null
form_model: player
get_form_fields: null
get_timeout_seconds: null
is_displayed: '# If participant is the spender, show them this page
return participant.spender == 1'
is_waitpage: false
js_vars: null
live_method: null
name: SpenderInstructionsEnd
template:
content: "\n{{ include_sibling 'uw_teton_bg.html' }}\n\n\n\n\n\n\n\n\n{{ if player.cq_4
== \"2\" or player.cq_4_try2 == \"2\" }}Correct!{{
else }}Incorrect.{{ endif }} If you bid
$200 on the chair and the computer chooses $200, you win the auction,
paying $200 and getting the red chair. This means the money remaining in the
joint account is $1,000 - $200 = $800. At the end of the study, whatever is
left in the joint account is split equally between you and your partner. So,
you will get the red chair, receive $400, and your partner will receive
$400.
\n\n{{ next_button }}"
javascript: "// This script is included to ensure that if tags are included
in form fields they are observed\n$(document).ready(function (e) {\n labels
= document.getElementsByTagName(\"label\");\n\n for (var i = 0; i < labels.length;
i++) {\n labels[i].innerHTML = labels[i].innerHTML.replaceAll(\"<\",
\"<\").\n replaceAll(\">\", \">\");\n }\n});"
title: Instructions
timeout_seconds: null
timer_text: null
vars_for_template: null
- after_all_players_arrive: null
body_text: null
group_by_arrival_time: null
is_displayed: null
is_waitpage: true
name: AuctionInstructionsEndPage
template: null
title_text: Your partner is being given instructions for their next task. Please
wait for your partner.
wait_for_all_groups: true
- bots: ''
constants:
- datatype: int
js_value: 2
name: PLAYERS_PER_GROUP
- datatype: int
js_value: 1
name: NUM_ROUNDS
- datatype: int
js_value: 40
name: NUM_POP_QS
- datatype: list_int
js_value:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
name: PRICE_STEPS
- datatype: list_int
js_value:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
name: SMILEY_LIKERT_OPTS
custom_export: "# Header\nyield [\n 'session_code',\n 'participant_id_in_session',\n
\ 'participant_code',\n 'id_in_group',\n 'group_member',\n 'spender',\n
\ 'earner_round_1',\n 'WTP_1',\n 'computer_price_1',\n 'won_auction_1'\n]\n\n#
Rows\nfor p in players:\n pp = p.participant\n pg = p.group\n ps = p.session\n
\ \n # Pull participant fields (needed as these are only saved in 'all apps
wide' normally)\n spender = p.participant.vars.get('spender', '')\n earner_round_1
= p.participant.vars.get('earner_round_1', '')\n computer_price_1 = p.participant.vars.get('computer_price_1',
'')\n \n yield [\n ps.code,\n pp.id_in_session,\n pp.code,\n
\ p.id_in_group,\n pg.id_in_subsession,\n spender,\n earner_round_1,\n
\ p.WTP,\n computer_price_1,\n pg.win\n ]"
doc: BDM auction to elicit WTP/ pain of paying of the spender. One person (spender)
participates in auction while other (waiter) waits until next phase. If spender
is successful in auction, fills out information for either lab pick-up or shipping.
includable_templates:
- content: "
\n
\n
\n
\ Auction Instructions\n
\n
\n Here are the rules
of the auction:\n
\n
\n
You
will place a bid on the item, corresponding to how much you would be willing
to pay for this item.
\n
The computer will randomly draw a price
for the item.
\n
Once you have determined the number of 1s in
the matrix, enter that number into the text box below the matrix.
\n
If
your bid is higher than the computer's randomly chosen price, you will pay the
computer's chosen price and receive the item. If your bid is lower than the
price that the computer randomly selects, you do not pay the price and receive
nothing.
\n
\n
\n
"
name: auction_instructions
- content: "\n{%
load otree %}\n\n\n\n"
name: uw_teton_bg
- content: "{% load otree %}\n\n\n"
name: uw_teton_survey
- content: "{% load otree %}\n\n"
name: two_column_flex_container
models:
Group:
fields:
- datatype: IntegerField
kwargs:
blank: null
choices: null
initial: null
label: null
max: null
min: null
widget: null
name: budget
- datatype: IntegerField
kwargs:
blank: null
choices: null
initial: null
label: null
max: null
min: null
widget: null
name: price
- datatype: BooleanField
kwargs:
blank: null
choices: null
initial: null
label: null
widget: null
name: win
- datatype: FloatField
kwargs:
blank: null
choices: null
initial: null
label: null
max: null
min: null
widget: null
name: WTP_spender
- datatype: IntegerField
kwargs:
blank: null
choices: null
initial: null
label: null
max: null
min: null
widget: null
name: budget_initial
methods:
- code: "# import random\nimport random\n\n# Gather players\nplayers = group.get_players()\n\n#
Define the group budget from RET1\ngroup.budget = players[0].participant.budget_1\ngroup.budget_initial
= players[0].participant.budget_1\n\n# Draw a single random number to use
as the price\ngroup.price = int((random.uniform((group.budget*0.85), group.budget))
+ 0.5) # UNIFORM DIST VERSION\n\n# Sanity check for price bounds\nif group.price
<= 1:\n group.price = 1\nelif group.price >= group.budget:\n group.price
= group.budget"
is_method: false
name: set_price
- code: "# Gather players\nplayers = group.get_players()\n\n# Identify the player
with the spending role\nspender_player = None\nfor p in players:\n p.participant.WTP_1
= 0 # set default value of WTP to participant field if not used\n if
p.participant.spender == 1:\n spender_player = p\n p.participant.WTP_1
= spender_player.WTP # set WTP for spender to participant field\n\n# Compare
the WTP to price\nif spender_player.WTP >= group.price:\n group.win =
True\n group.budget = group.budget - group.price # Money taken from joint
account\nelse:\n group.win = False\n group.budget = group.budget #
Nothing spent from joint account\n \n# If winner, save to participant
field\nfor p in players:\n if p.participant.spender == 1 and group.win
== True:\n p.participant.winner_1 = 1\n\n# Save final earnings to
a global variable\nfor p in players:\n p.participant.earnings_1 = group.budget
/2\n p.participant.computer_price_1 = group.price"
is_method: false
name: auction_check
Player:
fields:
- datatype: BooleanField
kwargs:
blank: null
choices: null
initial:
constant: null
expr_type: plain
js_value: false
label: null
widget: null
name: won_auction
- datatype: FloatField
kwargs:
blank: null
choices: null
initial: null
label:
constant: null
expr_type: plain
js_value: How much would you be willing to spend on the item shown above
in dollars? (Enter your bid as a dollar value using at maximum 2
decimals)
max: null
min:
constant: null
expr_type: plain
js_value: 0
widget: null
name: WTP
methods:
- code: return group.budget
is_method: false
name: WTP_max
Subsession:
fields: []
methods:
- code: "# pull the matrix you stored in the code‐entry app\nmatrix = subsession.session.vars.get('couple_matrix')\nif
not matrix:\n # safety check in case someone forgot to run grouping first\n
\ raise RuntimeError(\"No couple_matrix in session.vars\")\n# re‐apply
it in this app's subsession\nsubsession.set_group_matrix(matrix)"
is_method: false
name: after_all_players_arrive
name: Auction_1
pages:
- after_all_players_arrive: after_all_players_arrive
body_text: null
group_by_arrival_time: null
is_displayed: null
is_waitpage: true
name: GroupingWaitPage
template: null
title_text: null
wait_for_all_groups: true
- after_all_players_arrive: set_price
body_text: null
group_by_arrival_time: null
is_displayed: null
is_waitpage: true
name: SetBudgetWaitPage
template: null
title_text: null
wait_for_all_groups: null
- app_after_this_page: null
before_next_page: null
error_message: null
form_fields: null
form_model: player
get_form_fields: null
get_timeout_seconds: null
is_displayed: null
is_waitpage: false
js_vars: null
live_method: null
name: RoleReveal
template:
content: "\n{{ include_sibling 'uw_teton_bg.html' }}\n\n\n{{ if
player.participant.spender == 1 }}
\n You have been selected and are
receiving the opportunity to spend the money {{ if player.participant.earner_round_1
== 1 }} you{{ else }} your partner{{ endif }} earned
from the matrix task. In other words, ${{ group.budget }} in the joint account.
Remember, whatever balance is remaining in the joint account at the end of
the study will be split equally between you and your partner.\n
\n\n
\n
\ It is important to our study that the item you purchase is for your own
use and that, after the study, you do not compensate your partner for having
bought the item.\n
\n\n
\n The budget for you to spend is ${{ group.budget
}}.\n
\n\n\n{{ else }}
\n You were not selected
to complete the spending task. Please wait for further instructions.\n
\n\n{{
endif}}\n\n{{ next_button }}"
javascript: null
title: Spending Task
timeout_seconds: null
timer_text: null
vars_for_template: null
- after_all_players_arrive: null
body_text: null
group_by_arrival_time: null
is_displayed: "# If the participant is not the spender, sit on this wait page\nif
participant.spender != 1:\n return True"
is_waitpage: true
name: NotSpendingWaitPage
template: null
title_text: You were not selected for the spending task. Please wait for further
instructions.
wait_for_all_groups: null
- app_after_this_page: null
before_next_page: "group.WTP_spender = player.WTP\nif timeout_happened:\n #
Default value for any form fields if timeout occurs, because otherwise they
may be left null\n player.WTP = 0\n participant.WTP_1_timeout = 1"
error_message: null
form_fields:
- WTP
form_model: player
get_form_fields: null
get_timeout_seconds: null
is_displayed: '# If participant is the spender, show them this page
return participant.spender == 1'
is_waitpage: false
js_vars: null
live_method: null
name: Spending
template:
content: "\n{{ include_sibling 'uw_teton_bg.html' }}\n\n\n\n\n\n\n\n
\n You are being offered
this item, whose market value is approximately $30:\n
\n\n\n\n\n\n
\n {{ description }}\n
\n\n\n
\n You will get the opportunity
to buy this item by participating in an auction that works the same way as
the practice auction you just learned about. If you win the auction, the item
will be delivered to the lab and we will contact you so you can pick it up
from us at a time that is convenient to you. The total amount you can spend
on this task is the ${{group.budget}}, the money that {{if player.participant.earner_round_1
== 1}}you{{else}}your partner{{endif}} earned from the
matrix task; in other words you can spend up to ${{group.budget}} from the
joint account. Remember, all money remaining in the joint account at the end
of the study will be split evenly between you and your partner.\n
\n
\n
\ Here's a reminder of the rules of the auction:\n
\n
\n
\
You will place a bid on the item, corresponding to how much you would
be willing to pay for this item.
\n
The computer will randomly
draw a price for the item.
\n
If your bid is higher than the
price that the computer randomly selects, you win the auction,
and you will pay the computer's chosen price to receive the item. If your
bid is lower than the price that the computer randomly selects, you
lose the auction, you do not pay the price and receive nothing.
\n
\
The strategy for this kind of auction is to bid exactly the maximum
amount you are willing to pay for the good.
\n
\n\n
\n The
money you can spend on this item is the ${{ group.budget }} in the joint account.\n
\n\n \n\n\n{{ formfields }}\n\n{{
next_button }}"
javascript: "// This script is included to ensure that if tags are included
in form fields they are observed\n$(document).ready(function (e) {\n labels
= document.getElementsByTagName(\"label\");\n\n for (var i = 0; i < labels.length;
i++) {\n labels[i].innerHTML = labels[i].innerHTML.replaceAll(\"<\",
\"<\").\n replaceAll(\">\", \">\");\n }\n});"
title: The Auction
timeout_seconds: 180
timer_text: null
vars_for_template: "# Define the list of items with unique identifiers, their
associated image URLs, and a description\nimgur_urls = [\n {'id': 'A', 'url':
'https://i.imgur.com/OfsrPbR.jpeg', 'description': \"Coloring book with pencils\"},\n
\ {'id': 'B', 'url': 'https://i.imgur.com/tmBYFwX.jpeg', 'description': \"Headphones\"},\n
\ {'id': 'C', 'url': 'https://i.imgur.com/oBfC4Mz.jpeg', 'description': \"Moisturizer\"},\n
\ {'id': 'D', 'url': 'https://i.imgur.com/q7bBuv6.jpeg', 'description': \"Spa
kit\"},\n {'id': 'E', 'url': 'https://i.imgur.com/Zc7vR6m.jpeg', 'description':
\"Grilling accessories\"},\n {'id': 'F', 'url': 'https://i.imgur.com/YLEoKGI.jpeg',
'description': \"Tactical flashlight\"},\n {'id': 'G', 'url': 'https://i.imgur.com/lmMFuFL.jpeg',
'description': \"Lip Balm\"},\n {'id': 'H', 'url': 'https://i.imgur.com/5KfUIfj.jpeg',
'description': \"Water bottle\"},\n {'id': 'I', 'url': 'https://i.imgur.com/AS1feBP.jpeg',
'description': \"Car detailing kit\"},\n {'id': 'J', 'url': 'https://i.imgur.com/SfJ7GmF.jpeg',
'description': \"Multi-tool\"}\n]\n\n# Default fallback if selected_item is
missing or invalid\ndefault_image = 'https://miro.medium.com/v2/resize:fit:1100/format:webp/1*MXyMqcEJ6Se0SCWcYCKZTQ.jpeg'\ndefault_desc
= 'No description available.'\n\n# Retrieve the selected item from participant
data\nselected_item = participant.selected_item # Expect one of 'A' through
'J'\n\n# Find the dictionary for the selected item\nselected = next((item for
item in imgur_urls if item['id'] == selected_item),\n {'url':
default_image, 'description': default_desc})\n\n# Pass both the full list and
the selected item's data to the template\nreturn dict(\n image_paths=imgur_urls,\n
\ image_path=selected['url'],\n description=selected['description'],\n)"
- after_all_players_arrive: auction_check
body_text: null
group_by_arrival_time: null
is_displayed: null
is_waitpage: true
name: ResultsWaitPage
template: null
title_text: null
wait_for_all_groups: null
- app_after_this_page: null
before_next_page: null
error_message: null
form_fields: null
form_model: player
get_form_fields: null
get_timeout_seconds: null
is_displayed: null
is_waitpage: false
js_vars: null
live_method: null
name: Results
template:
content: "\n{{ include_sibling 'uw_teton_bg.html' }}\n\n
\n You have finished
Round 1 of the study, and we will now proceed to Round 2.{{if participant.spender
== 1}} We will repeat the earning and spending games.{{endif}} At the end
of the study, we will randomly choose one of the rounds to determine your
final payoff{{ if participant.spender == 1 }}, including the result of the
auction.{{else}}.{{endif}}\n
\n\n{{ next_button }}"
javascript: ''
title: Auction Results
timeout_seconds: null
timer_text: null
vars_for_template: null
- after_all_players_arrive: null
body_text: null
group_by_arrival_time: null
is_displayed: null
is_waitpage: true
name: Auction_1EndPage
template: null
title_text: Please wait for further instructions.
wait_for_all_groups: true
- bots: ''
constants:
- datatype: int
js_value: 2
name: PLAYERS_PER_GROUP
- datatype: int
js_value: 20
name: NUM_ROUNDS
- datatype: str
js_value: 'Time left to complete the matrix task:'
name: TIMER_TEXT
custom_export: "# Header\nyield [\n 'session_code',\n 'participant_id_in_session',\n
\ 'participant_code',\n 'id_in_group',\n 'earner_round_2',\n 'budget_2'\n]\n\n#
Rows\nfor p in players:\n pp = p.participant\n pg = p.group\n ps = p.session\n
\ # Pull participant fields\n earner_round_2 = p.participant.vars.get('earner_round_2',
'')\n budget_2 = p.participant.vars.get('budget_2', '')\n yield [\n ps.code,\n
\ pp.id_in_session,\n pp.code,\n p.id_in_group,\n earner_round_2,\n
\ budget_2\n ]"
doc: Real-effort task (RET) portion of the experiment. RET is counting the number
of 1s in a matrix of 1s and 0s.
includable_templates:
- content: "\n{%
load otree %}\n\n\n\n"
name: uw_teton_bg
models:
Group:
fields:
- datatype: IntegerField
kwargs:
blank: null
choices: null
initial: null
label: null
max: null
min: null
widget: null
name: budget
- datatype: IntegerField
kwargs:
blank: null
choices: null
initial:
constant: null
expr_type: plain
js_value: 0
label: null
max: null
min: null
widget: null
name: correct
- datatype: FloatField
kwargs:
blank: null
choices: null
initial: null
label: null
max: null
min: null
widget: null
name: earner_id
methods:
- code: "# Access all players in the current group\nplayers = group.get_players()\n\n#
Exit check for conditions that don't require individual updates\nif group.round_number
> 1 and group.correct == session.config['num_correct']:\n # Directly
carry over the correct count from the previous round\n group.correct
= group.in_round(group.round_number - 1).correct\n return\n\n# Identify
the player who did the task in the first round\nptask = group.get_player_by_id(group.in_round(1).earner_id)\n\n#
Initialize or update correct counts for players\nfor p in players:\n #
Ensure that player_sum is not None, treat None as an incorrect guess\n if
p.player_sum is None:\n p.last_guess_correct = False\n current_guess_correct
= 0 # This will treat None as an incorrect guess\n else:\n #
Compare player_sum with matrix_sum and update correct and feedback accordingly\n
\ current_guess_correct = int(p.player_sum == p.matrix_sum)\n p.last_guess_correct
= (p.player_sum == p.matrix_sum)\n\n # Update the correct count based
on the current guess\n if group.round_number == 1:\n p.correct
= current_guess_correct\n else:\n previous_correct = p.in_round(group.round_number
- 1).correct\n p.correct = previous_correct + current_guess_correct\n\n
\ # Update the group.correct counter if this is the player who did the
task\n if p == ptask:\n group.correct = p.correct"
is_method: false
name: check_func
- code: "# Defining player that did the task\nptask = group.get_player_by_id(group.in_round(1).earner_id)\n\n#
Setting the budget based on how many were correct and the pay per correct
answer\ngroup.budget = ptask.correct * session.config['x_rate']\n\n# Defining
the players\nplayers = group.get_players()\n\n# Store budget at the participant
level for the next app\nfor p in players:\n p.participant.budget_2 =
group.budget"
is_method: false
name: RET_payoff
- code: "# Gather players \nplayers = group.get_players()\n\n# Initialize earner_id
at the group level\ngroup.earner_id = None\n\n# Assign roles based on random
draw\nfor p in players:\n if p.participant.earner_round_1 == 0: # if
they were not the earner in round 1\n p.participant.earner_round_2
= 1\n group.earner_id = p.id_in_group # Store the earner's id_in_group
at the group level\n else:\n p.participant.earner_round_2 = 0\n
\ \n p.exit_2 = 0"
is_method: false
name: assign_earner_2
- code: "# Defining players\nplayers = group.get_players()\n\n# Setting the
exit condition to avoid duplicating the results page\nfor p in players:\n
\ p.exit_2 = 1"
is_method: false
name: exit
Player:
fields:
- datatype: IntegerField
kwargs:
blank: null
choices: null
initial:
constant: null
expr_type: plain
js_value: 1
label: null
max: null
min: null
widget: null
name: matrix_sum
- datatype: IntegerField
kwargs:
blank: null
choices: null
initial:
constant: null
expr_type: plain
js_value: 0
label:
constant: null
expr_type: plain
js_value: How many 1s are in the above matrix?
max: null
min:
constant: null
expr_type: plain
js_value: 0
widget: null
name: player_sum
- datatype: IntegerField
kwargs:
blank: null
choices: null
initial:
constant: null
expr_type: plain
js_value: 0
label: null
max: null
min:
constant: null
expr_type: plain
js_value: 0
widget: null
name: correct
- datatype: BooleanField
kwargs:
blank: null
choices: null
initial: null
label: null
widget: null
name: last_guess_correct
- datatype: FloatField
kwargs:
blank: null
choices: null
initial:
constant: null
expr_type: plain
js_value: 0
label: null
max: null
min: null
widget: null
name: exit_2
methods:
- code: return session.config['m_size'] * session.config['m_size']
is_method: false
name: player_sum_max
Subsession:
fields: []
methods:
- code: "# pull the matrix you stored in the code‐entry app\nmatrix = subsession.session.vars.get('couple_matrix')\nif
not matrix:\n # safety check in case someone forgot to run grouping first\n
\ raise RuntimeError(\"No couple_matrix in session.vars\")\n# re‐apply
it in this app's subsession\nsubsession.set_group_matrix(matrix)"
is_method: false
name: after_all_players_arrive
name: RET_2
pages:
- after_all_players_arrive: after_all_players_arrive
body_text: null
group_by_arrival_time: null
is_displayed: null
is_waitpage: true
name: GroupingWaitPage
template: null
title_text: null
wait_for_all_groups: true
- after_all_players_arrive: assign_earner_2
body_text: null
group_by_arrival_time: null
is_displayed: "if group.round_number == 1: \n return True"
is_waitpage: true
name: RoleAssignmentWaitPage
template: null
title_text: null
wait_for_all_groups: null
- app_after_this_page: null
before_next_page: '# Set a global 5 minute timer for all the task pages
participant = player.participant
import time
participant.expiry = time.time() + session.config[''task_min'']*60'
error_message: null
form_fields: null
form_model: player
get_form_fields: null
get_timeout_seconds: null
is_displayed: "if group.round_number == 1: \n return True"
is_waitpage: false
js_vars: null
live_method: null
name: RoleAssignment
template:
content: "\n{{
include_sibling 'uw_teton_bg.html' }}\n\n\n{{ if player.participant.earner_round_2 == 1 }}\n
\n You
were randomly selected to earn money by completing the earnings task. You
will have {{ session.config.time_limit }} minutes to earn up to ${{max_budget}}
by completing {{ session.config.num_correct }} matrices.\n
\n\n\n{{ else }}\n
\n You were
not selected to earn money by completing the earnings task. Please wait for
further instructions.\n
\n\n{{ endif}}\n\n{{ next_button }}"
javascript: null
title: Role Assignment
timeout_seconds: null
timer_text: null
vars_for_template: 'max_budget = session.config[''x_rate''] * session.config[''num_correct'']
return dict(max_budget = max_budget)'
- app_after_this_page: null
before_next_page: "if timeout_happened:\n # Default value for any form fields
if timeout occurs, because otherwise they may be left null\n player.player_sum
= 0"
error_message: null
form_fields:
- player_sum
form_model: player
get_form_fields: null
get_timeout_seconds: '# Using the global timer set at RoleAssignment
participant = player.participant
import time
# Passing the global timer to the HTML template of the page
return participant.expiry - time.time()'
is_displayed: "import time\n\n# Display if participant is the earner AND it's
round 1 AND global timer isn't 0\nif player.participant.earner_round_2 == 1
and group.round_number == 1 and max(participant.expiry - time.time(), 0) > 3:\n
\ return True\n\n# Display if participant is the earner AND it's after round
1 AND is not done with the task AND global timer isn't 0\nelif player.participant.earner_round_2
== 1 and group.in_round(group.round_number - 1).correct != session.config['num_correct']
and max(participant.expiry - time.time(), 0) > 3:\n return True"
is_waitpage: false
js_vars: null
live_method: null
name: Task
template:
content: "\n{{
include_sibling 'uw_teton_bg.html' }}\n\n\n\n\n\n\n\n\n
{% for row in matrix %} \n
{% for cell in
row %} \n
{{ cell }}
{% endfor %} \n
{% endfor %}
\n
\n\n\n\n\n \n\n{{
formfields }}\n\n{{ next_button }}"
javascript: null
title: Matrix Task
timeout_seconds: null
timer_text: 'Time left to complete the matrix task:'
vars_for_template: "import random\n\n# Generate session.config.m_size x session.config.m_size
matrix with random 0s and 1s\nmatrix = [[random.randint(0, 1) for _ in range(session.config['m_size'])]
for _ in range(session.config['m_size'])]\n\n# Calculate the sum of all 1s in
the matrix\nmatrix_sum = sum(sum(row) for row in matrix)\n\n# Store the sum
in the player variable\nplayer.matrix_sum = matrix_sum\n\n# Passing Python variables
to the HTML template of the page\nreturn dict(\n matrix=matrix,\n matrix_sum=matrix_sum,\n)"
- after_all_players_arrive: check_func
body_text: null
group_by_arrival_time: null
is_displayed: "# Display if earner\nif participant.earner_round_2 == 1:\n return
True"
is_waitpage: true
name: EarningWaitPage
template: null
title_text: null
wait_for_all_groups: null
- app_after_this_page: null
before_next_page: null
error_message: null
form_fields: null
form_model: player
get_form_fields: null
get_timeout_seconds: '# Using the global timer set at RoleAssignment
participant = player.participant
import time
# Passing the global timer to the HTML template of the page
return participant.expiry - time.time()'
is_displayed: "import time\n\n# Display if participant is the earner AND it's
round 1 AND global timer isn't 0\nif participant.earner_round_2 == 1 and group.round_number
== 1 and max(participant.expiry - time.time(), 0) > 3:\n return True\n\n#
Display if participant is the earner AND it's after round 1 AND is not done
with the task AND global timer isn't 0\nelif participant.earner_round_2 == 1
and group.in_round(group.round_number - 1).correct != session.config['num_correct']
and max(participant.expiry - time.time(), 0) > 3:\n return True"
is_waitpage: false
js_vars: null
live_method: null
name: Feedback
template:
content: "\n{{
include_sibling 'uw_teton_bg.html' }}\n\n\n\n\n\n
\n {% if player.last_guess_correct %}\n
\n Correct! You guessed the right number
of 1s.\n
\n {% else %}\n
\n
\ Incorrect guess. You will have another chance with a new matrix.\n
\
\n {% endif %}\n \n \n
\n Number
of correct guesses: {{ player.correct }}.\n
\n
\n\n\n{{ next_button }}"
javascript: null
title: Feedback
timeout_seconds: null
timer_text: 'Time left to complete the matrix task:'
vars_for_template: null
- app_after_this_page: null
before_next_page: '# Used to manually reach the exit condition to get to the results
screen
group.round_number = session.config[''num_rounds'']'
error_message: null
form_fields: null
form_model: player
get_form_fields: null
get_timeout_seconds: null
is_displayed: 'import time
# Only display this page if the participant ran out of time on the matrix task
return (player.participant.expiry - time.time()) <= 3'
is_waitpage: false
js_vars: null
live_method: null
name: TimeExpired
template:
content: "{{ include_sibling 'uw_teton_bg.html' }}\n\n
\n The time allotted
for this task has ended. Please proceed to the next part of the experiment.\n
\n\n{{
next_button }}"
javascript: null
title: Time Limit Reached
timeout_seconds: null
timer_text: null
vars_for_template: null
- after_all_players_arrive: null
body_text: null
group_by_arrival_time: null
is_displayed: "# If the participant is not the earner, have them sit on this wait
page\nif participant.earner_round_2 != 1:\n return True"
is_waitpage: true
name: NotEarningWaitPage
template: null
title_text: Please wait for further instructions.
wait_for_all_groups: null
- after_all_players_arrive: RET_payoff
body_text: null
group_by_arrival_time: null
is_displayed: "if group.correct == session.config['num_correct'] or group.round_number
== session.config['num_rounds']:\n return True"
is_waitpage: true
name: PayoffWaitPage
template: null
title_text: null
wait_for_all_groups: null
- after_all_players_arrive: null
body_text: null
group_by_arrival_time: null
is_displayed: "# Display if they are done or we hit the round limit\nif group.correct
== session.config['num_correct'] or group.round_number == session.config['num_rounds']:\n
\ return True\nelse:\n return False"
is_waitpage: true
name: ExitWaitPage
template: null
title_text: null
wait_for_all_groups: true
- app_after_this_page: null
before_next_page: null
error_message: null
form_fields: null
form_model: player
get_form_fields: null
get_timeout_seconds: null
is_displayed: "# Display if they are done or we hit the round limit\nif group.correct
== session.config['num_correct'] or group.round_number == session.config['num_rounds']:\n
\ return True\nelse:\n return False\n\n# Only show the page if we haven't
already shown it\nif player.participant.vars.get('my_page_shown', False):\n
\ return False\nelse:\n player.participant.vars['my_page_shown'] = True\n
\ return True"
is_waitpage: false
js_vars: null
live_method: null
name: Results
template:
content: "\n{{
include_sibling 'uw_teton_bg.html' }}\n\n{{ if player.participant.earner_round_2
== 1 }}
\n You got {{ player.correct }} of the matrices correct. For
every correct matrix, you receive ${{ session.config.x_rate }}. You earned
${{ group.budget }}.\n
\n\n{{ else }}
\n Your partner has completed
the earnings task. They earned ${{ group.budget }}.\n
\n\n{{ endif }}\n\n{{
next_button }}"
javascript: null
title: Results
timeout_seconds: null
timer_text: null
vars_for_template: null
- app_after_this_page: '# Used to skip directly to the next app
return "Auction_2"'
before_next_page: null
error_message: null
form_fields: null
form_model: player
get_form_fields: null
get_timeout_seconds: null
is_displayed: "# Display if they are done or we hit the round limit\nif group.correct
== session.config['num_correct'] or group.round_number == session.config['num_rounds']:\n
\ return True\nelse:\n return False"
is_waitpage: false
js_vars: null
live_method: null
name: JointAccount
template:
content: "\n{{ include_sibling 'uw_teton_bg.html' }}\n\n
\n The money {{ if
player.participant.earner_round_2 == 1 }}you{{ else }}your partner{{ endif
}} earned from the matrix task has been placed in a joint account you share
with your partner. At the end of the study, the money remaining in this joint
account will be split evenly between you and your partner. For example, if
there were $20 remaining in the joint account at the end of the study, you
would each be given $10.\n
\n\n
\n There is ${{ group.budget }} in
the joint account. In this part of the study, you or your partner will be
randomly chosen to receive the opportunity to spend the money {{ if player.participant.earner_round_2
== 1 }}you{{ else }}your partner{{ endif }} earned. The participant who is
not given the opportunity to spend money will wait for further instructions.\n
\n\n{{
next_button }}"
javascript: null
title: Joint Account
timeout_seconds: null
timer_text: null
vars_for_template: null
- bots: ''
constants:
- datatype: int
js_value: 2
name: PLAYERS_PER_GROUP
- datatype: int
js_value: 1
name: NUM_ROUNDS
- datatype: int
js_value: 40
name: NUM_POP_QS
- datatype: list_int
js_value:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
name: PRICE_STEPS
- datatype: list_int
js_value:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
name: SMILEY_LIKERT_OPTS
custom_export: "# Header\nyield [\n 'session_code',\n 'participant_id_in_session',\n
\ 'participant_code',\n 'id_in_group',\n 'group_member',\n 'spender',\n
\ 'earner_round_2',\n 'WTP_2',\n 'computer_price_2',\n 'won_auction_2'\n]\n\n#
Rows\nfor p in players:\n pp = p.participant\n pg = p.group\n ps = p.session\n
\ \n # Pull participant fields\n spender = p.participant.vars.get('spender',
'')\n earner_round_2 = p.participant.vars.get('earner_round_2', '')\n computer_price_2
= p.participant.vars.get('computer_price_2', '')\n \n yield [\n ps.code,\n
\ pp.id_in_session,\n pp.code,\n p.id_in_group,\n pg.id_in_subsession,\n
\ spender,\n earner_round_2,\n p.WTP,\n computer_price_2,\n
\ pg.win\n ]"
doc: BDM auction to elicit WTP/ pain of paying of the spender. One person (spender)
participates in auction while other (waiter) waits until next phase. If spender
is successful in auction, fills out information for either lab pick-up or shipping.
includable_templates:
- content: "
\n
\n
\n
\ Auction Instructions\n
\n
\n Here are the rules
of the auction:\n
\n
\n
You
will place a bid on the item, corresponding to how much you would be willing
to pay for this item.
\n
The computer will randomly draw a price
for the item.
\n
Once you have determined the number of 1s in
the matrix, enter that number into the text box below the matrix.
\n
If
your bid is higher than the computer's randomly chosen price, you will pay the
computer's chosen price and receive the item. If your bid is lower than the
price that the computer randomly selects, you do not pay the price and receive
nothing.
\n
\n
\n
"
name: auction_instructions
- content: "\n{%
load otree %}\n\n\n\n"
name: uw_teton_bg
- content: "{% load otree %}\n\n\n"
name: uw_teton_survey
- content: "{% load otree %}\n\n"
name: two_column_flex_container
models:
Group:
fields:
- datatype: IntegerField
kwargs:
blank: null
choices: null
initial: null
label: null
max: null
min: null
widget: null
name: budget
- datatype: IntegerField
kwargs:
blank: null
choices: null
initial: null
label: null
max: null
min: null
widget: null
name: price
- datatype: BooleanField
kwargs:
blank: null
choices: null
initial: null
label: null
widget: null
name: win
- datatype: FloatField
kwargs:
blank: null
choices: null
initial: null
label: null
max: null
min: null
widget: null
name: WTP_spender
- datatype: IntegerField
kwargs:
blank: null
choices: null
initial: null
label: null
max: null
min: null
widget: null
name: budget_initial
methods:
- code: "# import random\nimport random\n\n# Gather players\nplayers = group.get_players()\n\n#
Define the group budget from RET1\ngroup.budget = players[0].participant.budget_2\ngroup.budget_initial
= players[0].participant.budget_2\n\n# Draw a single random number to use
as the price\ngroup.price = int((random.uniform((group.budget*0.85), group.budget))
+ 0.5) # UNIFORM DIST VERSION\n\n# Sanity check for price bounds and bounding
the distribution if normal\nif group.price <= 1:\n group.price = 1\nelif
group.price >= group.budget:\n group.price = group.budget"
is_method: false
name: set_price
- code: "# Gather players\nplayers = group.get_players()\n\n# Identify the player
with the spending role\nspender_player = None\nfor p in players:\n p.participant.WTP_2
= 0 # set default value of WTP to participant field if not used\n if
p.participant.spender == 1:\n spender_player = p\n p.participant.WTP_2
= spender_player.WTP # set WTP for spender to participant field\n\n# Compare
the WTP to price\nif spender_player.WTP >= group.price:\n group.win =
True\n group.budget = group.budget - group.price # Money taken from joint
account\nelse:\n group.win = False\n group.budget = group.budget #
Nothing spent from joint account\n \n# If winner, save to participant
field\nfor p in players:\n if p.participant.spender == 1 and group.win
== True:\n p.participant.winner_2 = 1\n\n# Save final earnings to
a global variable\nfor p in players:\n p.participant.earnings_2 = group.budget
/2\n p.participant.computer_price_2 = group.price"
is_method: false
name: auction_check
Player:
fields:
- datatype: BooleanField
kwargs:
blank: null
choices: null
initial:
constant: null
expr_type: plain
js_value: false
label: null
widget: null
name: won_auction
- datatype: FloatField
kwargs:
blank: null
choices: null
initial: null
label:
constant: null
expr_type: plain
js_value: How much would you be willing to spend on the item shown above
in dollars? (Enter your bid as a dollar value using at maximum 2
decimals)
max: null
min:
constant: null
expr_type: plain
js_value: 0
widget: null
name: WTP
methods:
- code: return group.budget
is_method: false
name: WTP_max
Subsession:
fields: []
methods:
- code: "# pull the matrix you stored in the code‐entry app\nmatrix = subsession.session.vars.get('couple_matrix')\nif
not matrix:\n # safety check in case someone forgot to run grouping first\n
\ raise RuntimeError(\"No couple_matrix in session.vars\")\n# re‐apply
it in this app's subsession\nsubsession.set_group_matrix(matrix)"
is_method: false
name: after_all_players_arrive
name: Auction_2
pages:
- after_all_players_arrive: after_all_players_arrive
body_text: null
group_by_arrival_time: null
is_displayed: null
is_waitpage: true
name: GroupingWaitPage
template: null
title_text: null
wait_for_all_groups: true
- after_all_players_arrive: null
body_text: null
group_by_arrival_time: null
is_displayed: null
is_waitpage: true
name: Auction_2StartPage
template: null
title_text: null
wait_for_all_groups: true
- after_all_players_arrive: set_price
body_text: null
group_by_arrival_time: null
is_displayed: null
is_waitpage: true
name: SetBudgetWaitPage
template: null
title_text: null
wait_for_all_groups: null
- app_after_this_page: null
before_next_page: null
error_message: null
form_fields: null
form_model: player
get_form_fields: null
get_timeout_seconds: null
is_displayed: null
is_waitpage: false
js_vars: null
live_method: null
name: RoleReveal
template:
content: "\n{{ include_sibling 'uw_teton_bg.html' }}\n\n\n{{ if
player.participant.spender == 1 }}
\n You have been selected and are
receiving the opportunity to spend the money {{ if player.participant.earner_round_2
== 1 }} you{{ else }} your partner{{ endif }} earned
from the matrix task. In other words, ${{ group.budget }} in the joint account.
Remember, whatever balance is remaining in the joint account at the end of
the experiment will be split equally between you and your partner.\n
\n\n
\n
\ It is important to our study that the item you purchase is for your own
use and that, after the experiment, you do not compensate your partner for
having bought the item.\n
\n\n
\n The budget for you to spend is ${{
group.budget }}.\n
\n\n\n{{ else }}
\n You
were not selected to complete the spending task. Please wait for further instructions.\n
\n\n{{
endif}}\n\n{{ next_button }}"
javascript: null
title: Spending Task
timeout_seconds: null
timer_text: null
vars_for_template: null
- after_all_players_arrive: null
body_text: null
group_by_arrival_time: null
is_displayed: "# If the participant is not the spender, sit on this wait page\nif
participant.spender != 1:\n return True"
is_waitpage: true
name: NotSpendingWaitPage
template: null
title_text: You were not selected for the spending task. Please wait for further
instructions.
wait_for_all_groups: null
- app_after_this_page: null
before_next_page: "group.WTP_spender = player.WTP\nif timeout_happened:\n #
Default value for any form fields if timeout occurs, because otherwise they
may be left null\n player.player_sum = 0\n participant.WTP_2_timeout =
1"
error_message: null
form_fields:
- WTP
form_model: player
get_form_fields: null
get_timeout_seconds: null
is_displayed: '# If participant is the spender, show them this page
return participant.spender == 1'
is_waitpage: false
js_vars: null
live_method: null
name: Spending
template:
content: "\n{{ include_sibling 'uw_teton_bg.html' }}\n\n\n\n\n\n
\n You are being offered
this item, whose market value is approximately $30:\n
\n\n\n\n\n\n
\n {{ description }}\n
\n\n\n
\n You will participate in
an auction to determine if you will purchase this item. The total amount you
can spend on this task is the ${{group.budget}}, the money that {{if player.participant.earner_round_2
== 1}}you{{else}}your partner{{endif}} earned from the
matrix task; in other words you can spend up to ${{group.budget}} from the
joint account. Remember, all money remaining in the joint account at the end
of the study will be split evenly between you and your partner.\n
\n
\n
\ Remember, the results of the first and second joint account and
auction are completely separate, and only one will be chosen randomly
for your final payment.\n
\n
\n Here's a reminder of the rules
of the auction:\n
\n
\n
You
will place a bid on the item, corresponding to how much you would be willing
to pay for this item.
\n
The computer will randomly draw a price
for the item.
\n
If your bid is higher than the price that
the computer randomly selects, you win the auction, and you will pay
the computer's chosen price to receive the item. If your bid is lower than
the price that the computer randomly selects, you lose the auction,
you do not pay the price and receive nothing.
\n
The strategy for
this kind of auction is to bid exactly the maximum amount you are willing
to pay for the good.
\n
\n\n \n\n\n{{ formfields }}\n\n{{ next_button }}"
javascript: "// This script is included to ensure that if tags are included
in form fields they are observed\n$(document).ready(function (e) {\n labels
= document.getElementsByTagName(\"label\");\n\n for (var i = 0; i < labels.length;
i++) {\n labels[i].innerHTML = labels[i].innerHTML.replaceAll(\"<\",
\"<\").\n replaceAll(\">\", \">\");\n }\n});"
title: The Auction
timeout_seconds: 180
timer_text: null
vars_for_template: "# Define the list of items with unique identifiers, their
associated image URLs, and a description\nimgur_urls = [\n {'id': 'A', 'url':
'https://i.imgur.com/OfsrPbR.jpeg', 'description': \"Coloring book with pencils\"},\n
\ {'id': 'B', 'url': 'https://i.imgur.com/tmBYFwX.jpeg', 'description': \"Headphones\"},\n
\ {'id': 'C', 'url': 'https://i.imgur.com/oBfC4Mz.jpeg', 'description': \"Moisturizer\"},\n
\ {'id': 'D', 'url': 'https://i.imgur.com/q7bBuv6.jpeg', 'description': \"Spa
kit\"},\n {'id': 'E', 'url': 'https://i.imgur.com/Zc7vR6m.jpeg', 'description':
\"Grilling accessories\"},\n {'id': 'F', 'url': 'https://i.imgur.com/YLEoKGI.jpeg',
'description': \"Tactical flashlight\"},\n {'id': 'G', 'url': 'https://i.imgur.com/lmMFuFL.jpeg',
'description': \"Lip Balm\"},\n {'id': 'H', 'url': 'https://i.imgur.com/5KfUIfj.jpeg',
'description': \"Water bottle\"},\n {'id': 'I', 'url': 'https://i.imgur.com/AS1feBP.jpeg',
'description': \"Car detailing kit\"},\n {'id': 'J', 'url': 'https://i.imgur.com/SfJ7GmF.jpeg',
'description': \"Multi-tool\"}\n]\n\n# Default fallback if selected_item is
missing or invalid\ndefault_image = 'https://miro.medium.com/v2/resize:fit:1100/format:webp/1*MXyMqcEJ6Se0SCWcYCKZTQ.jpeg'\ndefault_desc
= 'No description available.'\n\n# Retrieve the selected item from participant
data\nselected_item = participant.selected_item # Expect one of 'A' through
'J'\n\n# Find the dictionary for the selected item\nselected = next((item for
item in imgur_urls if item['id'] == selected_item),\n {'url':
default_image, 'description': default_desc})\n\n# Pass both the full list and
the selected item's data to the template\nreturn dict(\n image_paths=imgur_urls,\n
\ image_path=selected['url'],\n description=selected['description'],\n)"
- after_all_players_arrive: auction_check
body_text: null
group_by_arrival_time: null
is_displayed: null
is_waitpage: true
name: ResultsWaitPage
template: null
title_text: null
wait_for_all_groups: null
- after_all_players_arrive: null
body_text: null
group_by_arrival_time: null
is_displayed: null
is_waitpage: true
name: Auction_1EndPage
template: null
title_text: Please wait for further instructions.
wait_for_all_groups: true
- bots: ''
constants:
- datatype: int
js_value: 2
name: PLAYERS_PER_GROUP
- datatype: int
js_value: 1
name: NUM_ROUNDS
- datatype: int
js_value: 22
name: NUM_POP_QS
- datatype: list_int
js_value:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
name: PRICE_STEPS
- datatype: list_int
js_value:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
name: SMILEY_LIKERT_OPTS
custom_export: "# Header\nyield [\n 'session_code',\n 'participant_id_in_session',\n
\ 'participant_code',\n 'id_in_group',\n 'group_number',\n 'spender',\n
\ 'pop_self_00', 'pop_self_02', 'pop_self_04', 'pop_self_06', 'pop_self_08',
'pop_self_10', 'pop_self_12', 'pop_self_16', 'pop_self_20',\n 'pop_partner_00',
'pop_partner_02', 'pop_partner_04', 'pop_partner_06', 'pop_partner_08', 'pop_partner_10',
'pop_partner_12', 'pop_partner_16', 'pop_partner_20', \n]\n\n# Rows\nfor p in
players:\n pp = p.participant\n pg = p.group\n ps = p.session\n #
Pull participant fields\n spender = p.participant.vars.get('spender', '')\n
\ yield [\n ps.code,\n pp.id_in_session,\n pp.code,\n p.id_in_group,\n
\ pg.id_in_subsession,\n spender,\n p.pop_self_00, p.pop_self_02,
p.pop_self_04, p.pop_self_06, p.pop_self_08, p.pop_self_10, p.pop_self_12, p.pop_self_16,
p.pop_self_20, \n p.pop_partner_00, p.pop_partner_02, p.pop_partner_04,
p.pop_partner_06, p.pop_partner_08, p.pop_partner_10, p.pop_partner_12, p.pop_partner_16,
p.pop_partner_20\n ]"
doc: ''
includable_templates:
- content: "
\n
\n
\n
\ Auction Instructions\n
\n
\n Here are the rules
of the auction:\n
\n
\n
You
will place a bid on the item, corresponding to how much you would be willing
to pay for this item.
\n
The computer will randomly draw a price
for the item.
\n
Once you have determined the number of 1s in
the matrix, enter that number into the text box below the matrix.
\n
If
your bid is higher than the computer's randomly chosen price, you will pay the
computer's chosen price and receive the item. If your bid is lower than the
price that the computer randomly selects, you do not pay the price and receive
nothing.
{{ if player.participant.spender
== 1 }}\n You just attempted to purchase the following item using money
from the joint account.\n
\n\n\n
{{
else }}\n Your partner attempted to purchase the following item using money
from the joint account.\n
\n \n{{ endif }}\n\n\n\n\n\n
\n {{ description }}\n
\n\n
\n
\n We will ask you
how you would feel purchasing the item at amounts ranging from $0 to $20.
For instance, how would you feel if {{ if player.participant.spender == 1
}}you{{ else }}your partner{{ endif }} were able to purchase the item for
$8 with money earned by you? How would you feel if {{ if player.participant.spender
== 1 }}you{{ else }}your partner{{ endif }} were able to purchase the item
for $8 with money earned by your partner? How would your feelings change
if {{ if player.participant.spender == 1 }}you{{ else }}your partner{{ endif
}} were instead paying $12 for the item? Please indicate your feelings using
the smiley face scale above — ranging from very positive (Face A) to very
negative (Face G).\n
\n \n \n \n \n
\n Please indicate
how you would feel about the purchase at the different prices, stating a letter
(A-G) that best corresponds to your feelings.\n
\n\n \n
\n\n
\ \n
\n
\
\n Money YOU earned, from the joint account\n
\
\n
\n
\n
\
Price
\n
A
\n
\
B
\n
C
\n
\
D
\n
E
\n
\
F
\n
G
\n
\
\n
\n
\n\n \n
\n
\n
\ Money YOUR PARTNER earned, the from joint account\n
\n
\
\n
\n
Price
\n
\
A
\n
B
\n
\
C
\n
D
\n
\
E
\n
F
\n
\
G
\n
\n
\n
\n\n
\n \n
\n\n\n
\n \n \n
\
\n
\n {% for field
in form %}\n {% if field.name.startswith('pop_self') %}\n
\n
\
{{ field.label }}
\n {%
for choice in field %}\n
{{ choice }}
\n
\ {% endfor %}\n
\n {%
endif %}\n {% endfor %}\n
\n
\n\n
\ \n
\n
\n {% for field in form %}\n {%
if field.name.startswith('pop_partner') %}\n
\n
{{
field.label }}
\n {% for choice in field %}\n
{{
choice }}
\n {% endfor %}\n
\n
\ {% endif %}\n {% endfor %}\n
\n
\
\n \n
\n\n{{ next_button }}"
javascript: null
title: Feelings on Purchase
timeout_seconds: null
timer_text: null
vars_for_template: "# Define the list of items with unique identifiers, their
associated image URLs, and a description\nimgur_urls = [\n {'id': 'A', 'url':
'https://i.imgur.com/OfsrPbR.jpeg', 'description': \"Coloring book with pencils\"},
# Image and description for item A\n {'id': 'B', 'url': 'https://i.imgur.com/tmBYFwX.jpeg',
'description': \"Headphones\"}, # Image and description for item B\n {'id':
'C', 'url': 'https://i.imgur.com/oBfC4Mz.jpeg', 'description': \"Moisturizer\"},
# Image and description for item C\n {'id': 'D', 'url': 'https://i.imgur.com/q7bBuv6.jpeg',
'description': \"Spa kit\"}, # Image and description for item D\n {'id':
'E', 'url': 'https://i.imgur.com/Zc7vR6m.jpeg', 'description': \"Grilling accessories\"},
# Image and description for item E\n {'id': 'F', 'url': 'https://i.imgur.com/YLEoKGI.jpeg',
'description': \"Tactical flashlight\"}, # Image and description for item F\n
\ {'id': 'G', 'url': 'https://i.imgur.com/lmMFuFL.jpeg', 'description': \"Lip
Balm\"}, # Image and description for item G\n {'id': 'H', 'url': 'https://i.imgur.com/5KfUIfj.jpeg',
'description': \"Water bottle\"}, # Image and description for item H\n {'id':
'I', 'url': 'https://i.imgur.com/AS1feBP.jpeg', 'description': \"Car detailing
kit\"}, # Image and description for item I\n {'id': 'J', 'url': 'https://i.imgur.com/SfJ7GmF.jpeg',
'description': \"Multi-tool\"} # Image and description for item J\n]\n\n#
Fallback defaults for missing items\ndefault_image = 'https://miro.medium.com/v2/resize:fit:1100/format:webp/1*MXyMqcEJ6Se0SCWcYCKZTQ.jpeg'\ndefault_desc
= 'No description available.'\n\n# Get the selected item code from participant\nselected_item
= participant.spender_selected_item\n# Look up the selected entry or fall back
to defaults\nselected = next(\n (item for item in imgur_urls if item['id']
== selected_item),\n {'url': default_image, 'description': default_desc}\n)\n\n#
Pass data to template\nreturn dict(\n price_steps=C.PRICE_STEPS,\n img_url='https://imgur.com/N7q1Rts.png',\n
\ image_paths=imgur_urls,\n image_path=selected['url'],\n description=selected['description'],\n)"
- after_all_players_arrive: null
body_text: null
group_by_arrival_time: null
is_displayed: null
is_waitpage: true
name: POPEndPage
template: null
title_text: Please wait for further instructions.
wait_for_all_groups: true
- bots: ''
constants:
- datatype: int
js_value: 2
name: PLAYERS_PER_GROUP
- datatype: int
js_value: 1
name: NUM_ROUNDS
- datatype: list_int
js_value:
- 1
- 2
- 3
- 4
- 5
name: LIKERT_OPTS
- datatype: list_int
js_value:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
name: SMILEY_LIKERT_OPTS
custom_export: "# Header\nyield [\n 'session_code',\n 'participant_id_in_session',\n
\ 'participant_code',\n 'id_in_group',\n 'group_number',\n 'spender',\n
\ 'earner_1', # noticed error (not correct variable), keeping for consistency
in custom exports\n 'earner_2', # noticed error (not correct variable), keeping
for consistency in custom exports\n # Relationship Qs\n 'r_entiltedMe',
'r_entiltedPartner', 'r_upsetPartner', 'r_guilty', # Spender likert Qs\n 'r_entitledPartnerToSpendTheirs',
'r_entitledPartnerToSpendMine', 'r_upsetWithPartner', 'r_expectPartnerGuilt',
# Nonspender likert Qs\n 'r_importance', 'r_uncomfortable', 'r_liveTogether',
'r_maritalStatus', 'r_relationshipLength', 'r_relationshipLast', 'r_householdAdults',
'r_householdChildren', 'r_happy',\n # TWST Qs\n 'TWST_1', 'TWST_2a', 'TWST_2b',
'TWST_3',\n # General Demographis Qs\n 'gender',\n 'age',\n 'student',\n
\ 'education',\n 'householdIncome'\n]\n\n# Rows\nfor p in players:\n pp
= p.participant\n pg = p.group\n ps = p.session\n # Pull participant
fields\n spender = p.participant.vars.get('spender', '')\n earner_round_1
= p.participant.vars.get('earner_round_1', '')\n earner_round_2 = p.participant.vars.get('earner_round_2',
'')\n yield [\n ps.code,\n pp.id_in_session,\n pp.code,\n
\ p.id_in_group,\n pg.id_in_subsession,\n spender,\n earner_1,
# noticed error (not correct variable), keeping for consistency in custom exports\n
\ earner2, # noticed error (not correct variable), keeping for consistency
in custom exports\n p.r_entiltedMe, p.r_entiltedPartner, p.r_upsetPartner,
p.r_guilty,\n p.r_entitledPartnerToSpendTheirs, p.r_entitledPartnerToSpendMine,
p.r_upsetWithPartner, p.r_expectPartnerGuilt,\n 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,\n p.TWST_1, p.TWST_2a,
p.TWST_2b, p.TWST_3,\n p.gender,\n p.age,\n p.student,\n
\ p.education,\n p.f_householdIncome\n ]"
doc: 'Post experiment questions. Includes survey questions, Tightwad-spendthrift
scale by Rick Scott, Cynthia Cryder, and George Loewenstein (2008), and demographic
questions.
'
includable_templates:
- content: "\n{%
load otree %}\n\n\n\n"
name: uw_teton_bg
- content: "{% load otree %}\n"
name: uw_teton_survey
- content: "{% load otree %}\n\n"
name: checkbox_list
models:
Group:
fields: []
methods: []
Player:
fields:
- datatype: IntegerField
kwargs:
blank: null
choices:
constant: LIKERT_OPTS
expr_type: constant
js_value: null
initial: null
label:
constant: null
expr_type: plain
js_value: I felt entitled to spend the money earned by me in the
joint account.
max: null
min: null
widget:
constant: null
expr_type: plain
js_value: RadioSelectHorizontal
name: r_entiltedMe
- datatype: IntegerField
kwargs:
blank: null
choices:
constant: LIKERT_OPTS
expr_type: constant
js_value: null
initial: null
label:
constant: null
expr_type: plain
js_value: I felt entitled to spend the money earned by my partner
in the joint account.
max: null
min: null
widget:
constant: null
expr_type: plain
js_value: RadioSelectHorizontal
name: r_entiltedPartner
- datatype: IntegerField
kwargs:
blank: null
choices:
constant: LIKERT_OPTS
expr_type: constant
js_value: null
initial: null
label:
constant: null
expr_type: plain
js_value: 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.
max: null
min: null
widget:
constant: null
expr_type: plain
js_value: RadioSelectHorizontal
name: r_upsetPartner
- datatype: IntegerField
kwargs:
blank: null
choices:
constant: LIKERT_OPTS
expr_type: constant
js_value: null
initial: null
label:
constant: null
expr_type: plain
js_value: 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.
max: null
min: null
widget:
constant: null
expr_type: plain
js_value: RadioSelectHorizontal
name: r_guilty
- datatype: IntegerField
kwargs:
blank: null
choices:
constant: LIKERT_OPTS
expr_type: constant
js_value: null
initial: null
label:
constant: null
expr_type: plain
js_value: I felt my partner was entitled to spend the money earned
by themselves in the joint account.
max: null
min: null
widget:
constant: null
expr_type: plain
js_value: RadioSelectHorizontal
name: r_entitledPartnerToSpendTheirs
- datatype: IntegerField
kwargs:
blank: null
choices:
constant: LIKERT_OPTS
expr_type: constant
js_value: null
initial: null
label:
constant: null
expr_type: plain
js_value: I felt my partner was entitled to spend the money earned
by me in the joint account.
max: null
min: null
widget:
constant: null
expr_type: plain
js_value: RadioSelectHorizontal
name: r_entitledPartnerToSpendMine
- datatype: IntegerField
kwargs:
blank: null
choices:
constant: LIKERT_OPTS
expr_type: constant
js_value: null
initial: null
label:
constant: null
expr_type: plain
js_value: 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.
max: null
min: null
widget:
constant: null
expr_type: plain
js_value: RadioSelectHorizontal
name: r_upsetWithPartner
- datatype: IntegerField
kwargs:
blank: null
choices:
constant: LIKERT_OPTS
expr_type: constant
js_value: null
initial: null
label:
constant: null
expr_type: plain
js_value: 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.
max: null
min: null
widget:
constant: null
expr_type: plain
js_value: RadioSelectHorizontal
name: r_expectPartnerGuilt
- datatype: IntegerField
kwargs:
blank: null
choices:
constant: LIKERT_OPTS
expr_type: constant
js_value: null
initial: null
label:
constant: null
expr_type: plain
js_value: My relationship with my partner is very important to me.
max: null
min: null
widget:
constant: null
expr_type: plain
js_value: RadioSelectHorizontal
name: r_importance
- datatype: IntegerField
kwargs:
blank: null
choices:
constant: LIKERT_OPTS
expr_type: constant
js_value: null
initial: null
label:
constant: null
expr_type: plain
js_value: I feel very uncomfortable when my partner is upset with me.
max: null
min: null
widget:
constant: null
expr_type: plain
js_value: RadioSelectHorizontal
name: r_uncomfortable
- datatype: BooleanField
kwargs:
blank: null
choices:
constant: null
expr_type: plain
js_value:
- - true
- Yes
- - false
- No
initial: null
label:
constant: null
expr_type: plain
js_value: Do you live with your partner?
widget:
constant: null
expr_type: plain
js_value: RadioSelect
name: r_liveTogether
- datatype: StringField
kwargs:
blank: null
choices:
constant: null
expr_type: plain
js_value:
- - '0'
- Relationship with Partner
- - '1'
- Married
initial: null
label:
constant: null
expr_type: plain
js_value: What is your current relationship status?
widget:
constant: null
expr_type: plain
js_value: RadioSelect
name: r_maritalStatus
- datatype: StringField
kwargs:
blank: null
choices:
constant: null
expr_type: plain
js_value:
- - '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
initial: null
label:
constant: null
expr_type: plain
js_value: 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:
constant: null
expr_type: plain
js_value: RadioSelect
name: r_relationshipLength
- datatype: StringField
kwargs:
blank: null
choices:
constant: null
expr_type: plain
js_value:
- - '1'
- A few months at most
- - '2'
- Around a year
- - '3'
- Several years
- - '4'
- A lifetime
initial: null
label:
constant: null
expr_type: plain
js_value: How long do you believe your relationship with your partner
will last?
widget:
constant: null
expr_type: plain
js_value: RadioSelect
name: r_relationshipLast
- datatype: IntegerField
kwargs:
blank: null
choices: null
initial: null
label:
constant: null
expr_type: plain
js_value: How many adults (age 18 or older) are in your household (including
you)?
max: null
min:
constant: null
expr_type: plain
js_value: 0
widget: null
name: r_householdAdults
- datatype: IntegerField
kwargs:
blank: null
choices: null
initial: null
label:
constant: null
expr_type: plain
js_value: How many children (under age 18) are in your household?
max: null
min:
constant: null
expr_type: plain
js_value: 0
widget: null
name: r_householdChildren
- datatype: StringField
kwargs:
blank: null
choices:
constant: null
expr_type: plain
js_value:
- - '1'
- ''
- - '2'
- ''
- - '3'
- ''
- - '4'
- ''
- - '5'
- ''
- - '6'
- ''
- - '7'
- ''
initial: null
label:
constant: null
expr_type: plain
js_value: How happy are you in your relationship?
widget:
constant: null
expr_type: plain
js_value: RadioSelectHorizontal
name: r_happy
- datatype: StringField
kwargs:
blank: null
choices:
constant: null
expr_type: plain
js_value:
- - '1'
- '1'
- - '2'
- '2'
- - '3'
- '3'
- - '4'
- '4'
- - '5'
- '5'
- - '6'
- '6'
- - '7'
- '7'
- - '8'
- '8'
- - '9'
- '9'
- - '10'
- '10'
- - '11'
- '11'
initial: null
label:
constant: null
expr_type: plain
js_value: Which of the following descriptions fits you better?
widget:
constant: null
expr_type: plain
js_value: RadioSelectHorizontal
name: TWST_1
- datatype: StringField
kwargs:
blank: null
choices:
constant: null
expr_type: plain
js_value:
- - '1'
- Never
- - '2'
- Rarely
- - '3'
- Sometimes
- - '4'
- Often
- - '5'
- Always
initial: null
label:
constant: null
expr_type: plain
js_value: How well does the the first description fit you? That is, do
you have trouble limiting your spending?
widget:
constant: null
expr_type: plain
js_value: RadioSelectHorizontal
name: TWST_2a
- datatype: StringField
kwargs:
blank: null
choices:
constant: null
expr_type: plain
js_value:
- - '1'
- Never
- - '2'
- Rarely
- - '3'
- Sometimes
- - '4'
- Often
- - '5'
- Always
initial: null
label:
constant: null
expr_type: plain
js_value: How well does the the second description fit you? That is, do
you have trouble spending money?
widget:
constant: null
expr_type: plain
js_value: RadioSelectHorizontal
name: TWST_2b
- datatype: StringField
kwargs:
blank: null
choices:
constant: null
expr_type: plain
js_value:
- - '1'
- '1'
- - '2'
- '2'
- - '3'
- '3'
- - '4'
- '4'
- - '5'
- '5'
initial: null
label:
constant: null
expr_type: plain
js_value: In terms of your own behavior, who are you more similar to,
Mr. A or Mr. B?
widget:
constant: null
expr_type: plain
js_value: RadioSelectHorizontal
name: TWST_3
- datatype: StringField
kwargs:
blank: null
choices:
constant: null
expr_type: plain
js_value:
- - '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
initial: null
label:
constant: null
expr_type: plain
js_value: What is your household's combined, pre-tax, annual income (including
bonuses and commissions) last year in U.S. dollars?
widget:
constant: null
expr_type: plain
js_value: RadioSelect
name: f_householdIncome
- datatype: StringField
kwargs:
blank: null
choices:
constant: null
expr_type: plain
js_value:
- - '0'
- Male
- - '1'
- Female
- - '2'
- Other
initial: null
label:
constant: null
expr_type: plain
js_value: What is your gender?
widget:
constant: null
expr_type: plain
js_value: RadioSelect
name: gender
- datatype: StringField
kwargs:
blank: null
choices: null
initial: null
label:
constant: null
expr_type: plain
js_value: '"You selected ''Other'' as your gender. Please describe your
gender identity:"'
widget: null
name: gender_other
- datatype: IntegerField
kwargs:
blank: null
choices: null
initial: null
label:
constant: null
expr_type: plain
js_value: What is your age? Please enter your answer as a number
max:
constant: null
expr_type: plain
js_value: 99
min:
constant: null
expr_type: plain
js_value: 18
widget: null
name: age
- datatype: StringField
kwargs:
blank: null
choices:
constant: null
expr_type: plain
js_value:
- - '1'
- Yes
- - '0'
- No
initial: null
label:
constant: null
expr_type: plain
js_value: Are you a college student?
widget:
constant: null
expr_type: plain
js_value: RadioSelect
name: student
- datatype: StringField
kwargs:
blank: null
choices:
constant: null
expr_type: plain
js_value:
- - '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.)
initial: null
label:
constant: null
expr_type: plain
js_value: What is the highest level of education you have completed?
widget:
constant: null
expr_type: plain
js_value: RadioSelect
name: education
methods: []
Subsession:
fields: []
methods:
- code: "# pull the matrix you stored in the code‐entry app\nmatrix = subsession.session.vars.get('couple_matrix')\nif
not matrix:\n # safety check in case someone forgot to run grouping first\n
\ raise RuntimeError(\"No couple_matrix in session.vars\")\n# re‐apply
it in this app's subsession\nsubsession.set_group_matrix(matrix)"
is_method: false
name: after_all_players_arrive
name: Survey
pages:
- after_all_players_arrive: after_all_players_arrive
body_text: null
group_by_arrival_time: null
is_displayed: null
is_waitpage: true
name: GroupingWaitPage
template: null
title_text: null
wait_for_all_groups: true
- app_after_this_page: null
before_next_page: null
error_message: null
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
form_model: player
get_form_fields: null
get_timeout_seconds: null
is_displayed: "# Display if participant is the spender\nif player.participant.spender
== 1:\n return True"
is_waitpage: false
js_vars: null
live_method: null
name: Relationship_Qs_Spender
template:
content: "\n{{ include_sibling 'uw_teton_survey.html' }} \n\n\n\n
\n
\n
\
\n In this final part of the study, we will ask you
to answer a series of questions about yourself and your partner. These questions
will help us gather additional information for our research. All details
are confidential and cannot be used to track your personal identity.\n
\
\n
\n
\n\n\n
\n Please rate how much you agree with the following statements:\n
\n
\n
\n
Question
\n
Strongly
Disagree
\n
Somewhat Disagree
\n
\
Neutral
\n
Somewhat Agree
\n
\
Strongly Agree
\n
\n {% for field
in form %}\n {% if field.name in likert_fields_spender %}\n
\n
\
{{ field.label }}
\n {% for choice
in field %}\n
{{ choice }}
\n {%
endfor %}\n
\n {% endif %}\n {% endfor %}\n
\n\n\n
\n
\ {% for field in form %}\n {% if not field.name in likert_fields_spender
and not field.name in happiness_fields %}\n
\n
\ \n {{ field
}}\n
\n {% endif %}\n {% endfor %}\n
\n\n\n
\n Please rate how much
you agree with the following statements according to the smiley face scale
below:\n
\n\n \n\n
\n
\n
\n
A
\n
\
B
\n
C
\n
\
D
\n
E
\n
\
F
\n
G
\n
\
\n {% for field in form %}\n {% if field.name in happiness_fields
%}\n
\n
{{ field.label }}
\n {%
for choice in field %}\n
{{ choice }}
\n {%
endfor %}\n
\n {% endif %}\n {% endfor %}\n
\n\n{{ next_button }}"
javascript: "// This script is included to ensure that if tags are included
in form fields they are observed\n$(document).ready(function (e) {\n labels
= document.getElementsByTagName(\"label\");\n\n for (var i = 0; i < labels.length;
i++) {\n labels[i].innerHTML = labels[i].innerHTML.replaceAll(\"<\",
\"<\").\n replaceAll(\">\", \">\");\n }\n});"
title: Questionnaire
timeout_seconds: null
timer_text: null
vars_for_template: "# List of fields to include in the Likert scale table\nlikert_fields_spender
= ['r_entiltedMe','r_entiltedPartner', 'r_upsetPartner','r_guilty','r_importance','r_uncomfortable']\n\n#
List of fields for the happiness Likert scale\nhappiness_fields = ['r_happy']\n\n#
Passing Python variables to the HTML template of the page\nreturn {\n 'img_url':
'https://imgur.com/N7q1Rts.png',\n 'likert_fields_spender': likert_fields_spender,\n
\ 'happiness_fields': happiness_fields\n}"
- app_after_this_page: null
before_next_page: null
error_message: null
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
form_model: player
get_form_fields: null
get_timeout_seconds: null
is_displayed: "# Display if participant is the spender\nif player.participant.spender
!= 1:\n return True"
is_waitpage: false
js_vars: null
live_method: null
name: Relationship_Qs_Nonspender
template:
content: "\n{{ include_sibling 'uw_teton_survey.html' }} \n\n\n\n
\n
\n
\
\n In this final part of the study, we will ask you
to answer a series of questions about yourself and your partner. These questions
will help us gather additional information for our research. All details
are confidential and cannot be used to track your personal identity.\n
\
\n
\n
\n\n\n
\n Please rate how much you agree with the following statements:\n
\n
\n
\n
Question
\n
Strongly
Disagree
\n
Somewhat Disagree
\n
\
Neutral
\n
Somewhat Agree
\n
\
Strongly Agree
\n
\n {% for field
in form %}\n {% if field.name in likert_fields_nonspender %}\n
\n
\
{{ field.label }}
\n {% for choice
in field %}\n
{{ choice }}
\n {%
endfor %}\n
\n {% endif %}\n {% endfor %}\n
\n\n\n
\n
\ {% for field in form %}\n {% if not field.name in likert_fields_nonspender
and not field.name in happiness_fields %}\n
\n
\ \n {{ field
}}\n
\n {% endif %}\n {% endfor %}\n
\n\n\n
\n Please rate how much
you agree with the following statements according to the smiley face scale
below:\n
\n\n \n\n
\n
\n
\n
A
\n
\
B
\n
C
\n
\
D
\n
E
\n
\
F
\n
G
\n
\
\n {% for field in form %}\n {% if field.name in happiness_fields
%}\n
\n
{{ field.label }}
\n {%
for choice in field %}\n
{{ choice }}
\n {%
endfor %}\n
\n {% endif %}\n {% endfor %}\n
\n\n{{ next_button }}"
javascript: "// This script is included to ensure that if tags are included
in form fields they are observed\n$(document).ready(function (e) {\n labels
= document.getElementsByTagName(\"label\");\n\n for (var i = 0; i < labels.length;
i++) {\n labels[i].innerHTML = labels[i].innerHTML.replaceAll(\"<\",
\"<\").\n replaceAll(\">\", \">\");\n }\n});"
title: Questionnaire
timeout_seconds: null
timer_text: null
vars_for_template: "# List of fields to include in the Likert scale table\nlikert_fields_nonspender
= ['r_entitledPartnerToSpendMine','r_entitledPartnerToSpendTheirs', 'r_upsetWithPartner','r_expectPartnerGuilt','r_importance','r_uncomfortable']\n\n#
List of fields for the happiness Likert scale\nhappiness_fields = ['r_happy']\n\n#
Passing Python variables to the HTML template of the page\nreturn {\n 'img_url':
'https://imgur.com/N7q1Rts.png',\n 'likert_fields_nonspender': likert_fields_nonspender,\n
\ 'happiness_fields': happiness_fields\n}"
- app_after_this_page: null
before_next_page: null
error_message: null
form_fields:
- TWST_1
- TWST_2a
- TWST_2b
- TWST_3
form_model: player
get_form_fields: null
get_timeout_seconds: null
is_displayed: null
is_waitpage: false
js_vars: null
live_method: null
name: TWST_Questions
template:
content: "\n{{ include_sibling 'uw_teton_survey.html' }} \n\n\n
\n
\n Consider
which of the following descriptions fits you better:\n
\n
\
\n \"I find it difficult to spend money\" OR \"I have
difficulty controlling my spending\"\n
\n
\n Below, select
a number from 1 to 11 below to indicate where you fall on this dimension.
1 indicates \"I find it difficult to spend money.\" 11 indicates \"I have
difficulty controlling my spending.\"\n
\n
\n
\
\n
1
\n
2
\n
\
3
\n
4
\n
\
5
\n
6
\n
\
7
\n
8
\n
\
9
\n
10
\n
\
11
\n
\n
\n {%
for choice in form.TWST_1 %}\n
{{ choice }}
\n {%
endfor %}\n
\n
\n
Tightwad (difficulty
spending money)
\n
\n
\n
\
\n
\n
\
About the the same or neither
\n
\n
\
\n
\n
\
\n
Spendthrift (difficulty
controlling spending)
\n
\n
\n
\n\n\n
\n
\n Some people have
trouble limiting their spending: they often spend money—for example on clothes,
meals, vacations, phone calls—when they would do better not to.\n
\n
\
\n Other people have trouble spending money. Perhaps because
spending money makes them anxious, they often don't spend money on things
they should spend it on.\n
\n \n
\
\n
\n {% for choice
in form.TWST_2a %}\n
{{ choice }}
\n {%
endfor %}\n
\n
\n
Never
\n
\
Rarely
\n
Sometimes
\n
\
Often
\n
Always
\n
\
\n
\n
\n\n\n\n
\n \n
\n
\n {% for choice in form.TWST_2b
%}\n
{{ choice }}
\n {% endfor %}\n
\n
\
\n
Never
\n
Rarely
\n
\
Sometimes
\n
Often
\n
\
Always
\n
\n
\n
\n\n\n
\n
\n The
following is a scenario describing the behavior of two shoppers. After reading
about each shopper, please answer the question that follows.\n
\n
\n
\ Mr. A is accompanying a good friend who is on a shopping spree at
a local mall. When they enter a large department store, Mr. A sees that the
store has a \"one-day-only-sale\" where everything is priced 10-60% off. He
realizes he doesn't need anything, yet can't resist and ends up spending almost
$100 on stuff.\n
\n
\n Mr. B is accompanying a good friend
who is on a shopping spree at a local mall. When they enter a large department
store, Mr. B sees that the store has a \"one-day-only-sale\" where everything
is priced 10-60% off. He figures he can get great deals on many items that
he needs, yet the thought of spending the money keeps him from buying the
stuff.\n
\n \n
\n
\
\n
1
\n
2
\n
\
3
\n
4
\n
\
5
\n
\n
\n {%
for choice in form.TWST_3 %}\n
{{ choice }}
\n {%
endfor %}\n
\n
\n
Mr. A
\n
\
\n
About the
same or neither
\n
\n
Mr.
B
\n
\n
\n
\n\n{{ next_button }}\n"
javascript: "// This script is included to ensure that if tags are included
in form fields they are observed\n$(document).ready(function (e) {\n labels
= document.getElementsByTagName(\"label\");\n\n for (var i = 0; i < labels.length;
i++) {\n labels[i].innerHTML = labels[i].innerHTML.replaceAll(\"<\",
\"<\").\n replaceAll(\">\", \">\");\n }\n});"
title: Questionnaire
timeout_seconds: null
timer_text: null
vars_for_template: null
- app_after_this_page: null
before_next_page: null
error_message: null
form_fields:
- gender
- age
- student
- education
- f_householdIncome
form_model: player
get_form_fields: null
get_timeout_seconds: null
is_displayed: null
is_waitpage: false
js_vars: null
live_method: null
name: Demo_Questions
template:
content: "\n{{ include_sibling 'uw_teton_survey.html' }} \n{{
include_sibling 'checkbox_list.html' }}\n\n
\n
\ {% for field in form %}\n
\n \n {{ field }}\n
\n {%
endfor %}\n
\n\n{{ next_button }}"
javascript: "// This script is included to ensure that if tags are included
in form fields they are observed\n$(document).ready(function (e) {\n labels
= document.getElementsByTagName(\"label\");\n\n for (var i = 0; i < labels.length;
i++) {\n labels[i].innerHTML = labels[i].innerHTML.replaceAll(\"<\",
\"<\").\n replaceAll(\">\", \">\");\n }\n});"
title: Questionnaire
timeout_seconds: null
timer_text: null
vars_for_template: null
- after_all_players_arrive: null
body_text: null
group_by_arrival_time: null
is_displayed: null
is_waitpage: true
name: SurveyEndPage
template: null
title_text: null
wait_for_all_groups: true
- bots: ''
constants:
- datatype: int
js_value: 2
name: PLAYERS_PER_GROUP
- datatype: int
js_value: 1
name: NUM_ROUNDS
- datatype: int
js_value: 5
name: BASE_PAY
custom_export: "# Header\nyield [\n 'session_code',\n 'participant_id_in_session',\n
\ 'participant_code',\n 'id_in_group',\n 'group_number',\n 'spender',\n
\ 'payoff',\n 'show_up_fee',\n 'earnings',\n 'selected_round',\n 'winner_round_1',\n
\ 'winner_round_2',\n 'group_winner',\n 'selected_item',\n 'auction_win_code'\n]\n\n#
Rows\nfor p in players:\n pp = p.participant\n pg = p.group\n ps = p.session\n
\ \n # Calculating the earnings\n payoff = p.participant.payoff\n fee
= p.session.config['fee']\n # if fee is stored as a plain number, wrap it in
Currency:\n fee_currency = c(fee) \n earnings = payoff + fee_currency\n
\ \n # Pull participant fields\n spender = p.participant.vars.get('spender',
'')\n selected_round = p.participant.vars.get('selected_round', '')\n winner_1
= p.participant.vars.get('winner_1', '')\n winner_2 = p.participant.vars.get('winner_2',
'')\n spender_selected_item = p.participant.vars.get('spender_selected_item',
'')\n random_code = p.participant.vars.get('random_code', '')\n \n yield
[\n ps.code,\n pp.id_in_session,\n pp.code,\n p.id_in_group,\n
\ pg.id_in_subsession,\n spender,\n payoff,\n fee_currency,\n
\ earnings,\n selected_round,\n winner_1,\n winner_2,\n
\ pg.winner,\n spender_selected_item,\n random_code\n ]"
doc: Participants are told their earnings (cumulative for entire experiment) and
debriefed. Shown amount to be paid and then dismissed.
includable_templates:
- content: "\n{%
load otree %}\n\n\n\n"
name: uw_teton_bg
models:
Group:
fields:
- datatype: IntegerField
kwargs:
blank: null
choices: null
initial: null
label: null
max: null
min: null
widget: null
name: selected_round_price
- datatype: IntegerField
kwargs:
blank: null
choices: null
initial: null
label: null
max: null
min: null
widget: null
name: spender_WTP
- datatype: IntegerField
kwargs:
blank: null
choices: null
initial: null
label: null
max: null
min: null
widget: null
name: winner
methods:
- code: "import random\n\nplayers = group.get_players()\n\nfor p in players:\n
\ payoff_round = p.participant.selected_round\n p.participant.random_code
= random.randint(10000, 99999) # code used for verifying item payout\n\n#
Assign payoff depending on selected round and add correct belief bonus\nif
payoff_round == 1:\n for p in players:\n p.participant.final_earnings_without_fee
= p.participant.earnings_1\n if p.participant.correct_belief == 1:\n
\ p.participant.final_earnings_without_fee += session.config['belief_payout']\n
\ p.payoff = p.participant.final_earnings_without_fee\nelse:\n for
p in players:\n p.participant.final_earnings_without_fee = p.participant.earnings_2\n
\ if p.participant.correct_belief == 1:\n p.participant.final_earnings_without_fee
+= session.config['belief_payout']\n p.payoff = p.participant.final_earnings_without_fee\n\n#
Add in the participation fee, adjusted for rounding\nfor p in players:\n
\ p.participant.final_earnings_with_fee = int(p.participant.final_earnings_without_fee
+ session.config[\"fee\"] + 0.5) # the \"int(x + 0.5)\" is used to round.
Basically, there's some weird behavior with the round function due to \"banker's
rounding\": if using round(), if the leading number is even, the number
will round up, and if leading number is odd, the number will round down.
This way will work no matter what, as int() always rounds down (so 2.3 ->
2.3 + 0.5 = 2.8, int(2.8) = 2, and 2.7 -> 2.7 + 0.5 = 3.2, int(3.3) = 3)"
is_method: false
name: payoff_calc_func
- code: "import random\n\n# Select the round for payoff for the group\npayoff_round
= random.randint(1,2)\n\nplayers = group.get_players()\n\nfor p in players:\n
\ # Save the selected round to the participant field\n p.participant.selected_round
= payoff_round\n # Conditional depending on which round was selected
for payoff\n if payoff_round == 1:\n # Save the spender's WTP
for the selected round in a group variable\n if p.participant.spender
== 1:\n group.spender_WTP = int(p.participant.WTP_1)\n #
Save the computer's price for the selected round in a group variable\n group.selected_round_price
= p.participant.computer_price_1\n # If the participant is the spender
AND won in the selected round\n if p.participant.spender == 1 and
p.participant.winner_1 == 1:\n group.winner = 1\n else:\n
\ group.winner = 0\n else: # i.e. if the selected round is
round 2\n # Save the spender's WTP for the selected round in a group
variable\n if p.participant.spender == 1:\n group.spender_WTP
= int(p.participant.WTP_2)\n # Save the computer's price and spender's
WTP for the selected round in a group variable\n group.selected_round_price
= p.participant.computer_price_2\n # If the participant is the spender
AND won in the selected round\n if p.participant.spender == 1 and
p.participant.winner_2 == 1:\n group.winner = 1\n else:\n
\ group.winner = 0"
is_method: false
name: select_payoff_round
Player:
fields:
- datatype: FloatField
kwargs:
blank: null
choices: null
initial: null
label: null
max: null
min: null
widget: null
name: exp_payment
methods: []
Subsession:
fields: []
methods:
- code: "# pull the matrix you stored in the code‐entry app\nmatrix = subsession.session.vars.get('couple_matrix')\nif
not matrix:\n # safety check in case someone forgot to run grouping first\n
\ raise RuntimeError(\"No couple_matrix in session.vars\")\n# re‐apply
it in this app's subsession\nsubsession.set_group_matrix(matrix)"
is_method: false
name: after_all_players_arrive
name: Outro
pages:
- after_all_players_arrive: after_all_players_arrive
body_text: null
group_by_arrival_time: null
is_displayed: null
is_waitpage: true
name: GroupingWaitPage
template: null
title_text: null
wait_for_all_groups: true
- after_all_players_arrive: select_payoff_round
body_text: null
group_by_arrival_time: null
is_displayed: null
is_waitpage: true
name: SelectRoundWaitPage
template: null
title_text: null
wait_for_all_groups: null
- after_all_players_arrive: payoff_calc_func
body_text: null
group_by_arrival_time: null
is_displayed: null
is_waitpage: true
name: PayoffCalcWaitPage
template: null
title_text: null
wait_for_all_groups: null
- app_after_this_page: null
before_next_page: null
error_message: null
form_fields: null
form_model: player
get_form_fields: null
get_timeout_seconds: null
is_displayed: null
is_waitpage: false
js_vars: null
live_method: null
name: Dismissal
template:
content: "\n{{
include_sibling 'uw_teton_bg.html' }}\n\n\n
\n The randomly selected round that determined
your earnings was: Round {{selected_round}}. \n
\n\n\n{{ if participant.spender
== 1 }}\n
\n In Round {{selected_round}}, the computer's random price
was ${{computer_price}}, and your bid was ${{spender_WTP}}.\n
\n \n {{ if selected_round ==
1 and winner_1 == 1 or selected_round == 2 and winner_2 == 1}}\n
\n
\ Since your bid was higher than the computer's price, you won the
auction. You paid the computer's price of ${{computer_price}} for your item.\n
\
\n \n {{
else }}\n
\n Since your bid was lower than the computer's
price, you lost the auction. You did not purchase an item, and no funds were
removed from the joint account.\n
\n {{ endif }}\n{{ endif }}\n\n\n\n
\n Your total earnings
in the study {{ if participant.spender == 1 and group.winner == 1 }}(after
removing your purchase){{ endif }} are ${{payoff}}. \n
\n\n{{
if participant.spender == 1 and selected_round == 1 and winner_1 == 1 or participant.spender
== 1 and selected_round == 2 and winner_2 == 1 }} \n
\n Please
write down the following code on your receipt so we can ask you for more information
about shipping: {{participant.random_code}} \n