Skip to content

Commit

Permalink
Make one gamble count for real.
Browse files Browse the repository at this point in the history
  • Loading branch information
Kodiologist committed Mar 21, 2012
1 parent d4182b4 commit 682e6be
Showing 1 changed file with 110 additions and 30 deletions.
140 changes: 110 additions & 30 deletions cookie-task
Expand Up @@ -5,8 +5,8 @@ VERSION = 'undeployed'
from sys import argv
from math import sqrt
from itertools import permutations
from re import match
from random import sample, choice
from re import match, search
from random import sample, choice, randint
from datetime import datetime
from types import MethodType
from psychopy.monitors import Monitor
Expand All @@ -24,6 +24,8 @@ output_path_prefix = argv[1] if len(argv) >= 2 else "results_"
splotch_path_fmt = argv[2] if len(argv) >= 3 else "splotches/%d.png"
condition_permutations_path = argv[3] if len(argv) >= 4 else 'condition-perms.txt'

splotch_total_pixels = 250000
splotch_pixels = {1: {'bad': 37385, 'neutral': 174690, 'good': 37925}, 2: {'bad': 149966, 'neutral': 49810, 'good': 50224}, 3: {'bad': 149780, 'neutral': 50266, 'good': 49954}, 4: {'bad': 112144, 'neutral': 25551, 'good': 112305}, 5: {'bad': 149255, 'neutral': 50927, 'good': 49818}, 6: {'bad': 111848, 'neutral': 25370, 'good': 112782}, 7: {'bad': 50098, 'neutral': 100555, 'good': 99347}, 8: {'bad': 150000, 'neutral': 49967, 'good': 50033}, 9: {'bad': 100374, 'neutral': 49878, 'good': 99748}, 10: {'bad': 37934, 'neutral': 174369, 'good': 37697}, 11: {'bad': 149495, 'neutral': 50313, 'good': 50192}, 12: {'bad': 38295, 'neutral': 174036, 'good': 37669}, 13: {'bad': 75402, 'neutral': 24463, 'good': 150135}, 14: {'bad': 49772, 'neutral': 50617, 'good': 149611}, 15: {'bad': 112498, 'neutral': 25286, 'good': 112216}, 16: {'bad': 37267, 'neutral': 174749, 'good': 37984}, 17: {'bad': 112314, 'neutral': 25618, 'good': 112068}, 18: {'bad': 49872, 'neutral': 50189, 'good': 149939}, 19: {'bad': 112406, 'neutral': 24157, 'good': 113437}, 20: {'bad': 224066, 'neutral': 12456, 'good': 13478}, 21: {'bad': 49721, 'neutral': 49613, 'good': 150666}, 22: {'bad': 149475, 'neutral': 50065, 'good': 50460}, 23: {'bad': 50039, 'neutral': 50786, 'good': 149175}, 24: {'bad': 50723, 'neutral': 49886, 'good': 149391}, 25: {'bad': 112703, 'neutral': 24866, 'good': 112431}, 26: {'bad': 37818, 'neutral': 174544, 'good': 37638}, 27: {'bad': 149837, 'neutral': 24239, 'good': 75924}, 28: {'bad': 50496, 'neutral': 50169, 'good': 149335}, 29: {'bad': 36787, 'neutral': 175052, 'good': 38161}, 30: {'bad': 82667, 'neutral': 82231, 'good': 85102}, 31: {'bad': 50427, 'neutral': 149626, 'good': 49947}, 32: {'bad': 49803, 'neutral': 149665, 'good': 50532}, 33: {'bad': 50697, 'neutral': 149629, 'good': 49674}, 34: {'bad': 50605, 'neutral': 149859, 'good': 49536}, 35: {'bad': 49408, 'neutral': 149920, 'good': 50672}, 36: {'bad': 50376, 'neutral': 149810, 'good': 49814}, 37: {'bad': 50844, 'neutral': 149624, 'good': 49532}, 38: {'bad': 50753, 'neutral': 149172, 'good': 50075}, 39: {'bad': 50102, 'neutral': 149516, 'good': 50382}, 40: {'bad': 50043, 'neutral': 149942, 'good': 50015}}
test_splotches = [
22, 3, 11, 14, 28, 23, 35, 37, 31, 6, 15, 19, 7, 30]
example_splotch = 20
Expand Down Expand Up @@ -248,37 +250,68 @@ def button_screen(dkey, *stimuli):
save(dkey, filter(lambda x: x.activated(), buttons)[0].string)
wait(.25)

def get_amount(dkey, string):
"Ask for a monetary amount with the given prompt."
def get_string(dkey, prompt,
dialog_field_label, dialog_hint, dialog_error,
extractor):
"""Ask for a string with the given prompt. The extractor should
be a function that translates the user's input into
whatever should go into 'data' or returns None if the input
is invalid. dialog_field_label, dialog_hint, and dialog_error
are strings used in the dialog box."""
draw(
text(0, .8, string, vAlign = 'top'))
text(0, .8, prompt, vAlign = 'top'))
with timestamps(dkey):
trying_again = False
while True:
dialog = DlgSansCancel(
title = 'Entry',
pos = (screen_width/2 - approx_dialog_box_width, .85 * screen_height))
dialog.addText(' ' * 45)
dialog.addField('Amount:')
dialog.addText(
'Invalid dollar amount; please try again.'
if trying_again
else 'Enter a dollar amount. Cents are allowed.')
dialog.addField(dialog_field_label)
dialog.addText(dialog_error if trying_again else dialog_hint)
dialog.show()
amount = dialog.data[0]
mo = match(r'\s*\$?\s*(\d+(?:\.\d\d?)?)\s*$', amount)
if mo:
save(dkey, mo.groups(1)[0])
inp = extractor(dialog.data[0])
if inp is not None:
save(dkey, inp)
break
else:
trying_again = True
wait(.25)

def integer_math_problem(dkey, string):
def extractor(inp):
mo = match(r'\s*(\d+)\s*$', inp)
if mo:
return mo.groups(1)
return None
get_string(dkey, string,
dialog_field_label = 'Your answer:',
dialog_hint = 'Enter a whole number.',
dialog_error = "That didn't look like a whole number.",
extractor = extractor)

def get_amount(dkey, string):
"Ask for a monetary amount with the given prompt."
def extractor(inp):
mo = match(r'\s*\$?\s*(\d+(?:\.\d\d?)?)\s*$', inp)
if mo:
return mo.groups(1)[0]
return None
get_string(dkey, string,
dialog_field_label = 'Amount:',
dialog_hint = 'Enter a dollar amount. Cents are allowed.',
dialog_error = 'Invalid dollar amount; please try again.',
extractor = extractor)

def wait_screen(time_to_wait, *stimuli):
'Display some stimuli for a given amount of time.'
draw(*stimuli)
wait(time_to_wait)

def instructions(dkey, string): button_screen(dkey,
text(0, .8, string, vAlign = 'top'),
Button(0, -.5, 'Next'))

# ------------------------------------------------------------
# Get the subject number
# ------------------------------------------------------------
Expand Down Expand Up @@ -321,10 +354,6 @@ save('brownie_condition',
# Explain the gamble outcomes
# ------------------------------------------------------------

def instructions(dkey, string): button_screen(dkey,
text(0, .8, string, vAlign = 'top'),
Button(0, -.5, 'Next'))

def rating(dkey, string, lo, hi): return scale_screen(dkey,
text(0, .3, string),
likert_scale(lo, hi, y = -.3))
Expand Down Expand Up @@ -378,46 +407,52 @@ with dkey_prefix('discount'):
# ------------------------------------------------------------

with showing(splotch):
def instructions(dkey, string, *stimuli): button_screen(dkey,
def example_gamble_instructions(dkey, string, *stimuli): button_screen(dkey,
text(-.95, .75, string, hAlign = 'left', vAlign = 'top', wrap = .5),
Button(0, -.8, 'Next'),
*stimuli)

instructions(('picture_explan', 0), "Each of the gambles you'll be asked to evaluate will be presented as a picture like this.")
example_gamble_instructions(('picture_explan', 0), "Each of the gambles you'll be asked to evaluate will be presented as a picture like this.")

instructions(('picture_explan', 1), 'Each color represents the probability of a different outcome. Yellow represents the good outcome (a brownie), black represents the netural outcome (nothing), and blue represents the bad outcome (arithmetic). Each probability is expressed as area.')
example_gamble_instructions(('picture_explan', 1), 'Each color represents the probability of a different outcome. Yellow represents the good outcome (a brownie), black represents the netural outcome (nothing), and blue represents the bad outcome (arithmetic). Each probability is expressed as area.')

instructions(('picture_explan', 2), "For example, one-twentieth of this image's area is yellow. Thus, the probability of getting the brownie outcome from this gamble is 1 out of 20.")
example_gamble_instructions(('picture_explan', 2), "For example, one-twentieth of this image's area is yellow. Thus, the probability of getting the brownie outcome from this gamble is 1 out of 20.")

with showing(probability_scale(0, -.5, fixed = .05)):
instructions('mark_example', "You'll provide your judgments of probability using a linear scale like this. In this case, if you were asked the probability of the brownie outcome, you would click on the point marked by the green line.")
example_gamble_instructions('mark_example', "You'll provide your judgments of probability using a linear scale like this. In this case, if you were asked the probability of the brownie outcome, you would click on the point marked by the green line.")

instructions('click_precisely', "Please take your time and CLICK PRECISELY. You'll need to be careful in order to make these judgments accurately.")
example_gamble_instructions('click_precisely', "Please take your time and CLICK PRECISELY. You'll need to be careful in order to make these judgments accurately.")

button_screen('before_gambles',
text(0, .8, 'Now for the first gamble.', vAlign = 'top'),
Button(0, -.5, 'Next'))
instructions('after_prob_judgments', "In addition to these probability judgments, you'll be asked how much each gamble appeals to you and whether, were this gamble offered to you, you would take it.")

instructions('only_one_gamble_counts', "After you've evaluated all of the gambles, one of them will be chosen at random to count for real. If you said you'd take that gamble, you'll get a brownie, arithmetic, or nothing, according to the gamble's probabilites. But if you said you wouldn't take the gamble, you won't have to take it, and nothing more will happen.")

instructions('one_gamble_counting_implies', "Since you can't tell in advance which gamble will count for real, you'll need to decide carefully for all of them.")

instructions('before_gambles', 'Now for the first gamble.')

# ------------------------------------------------------------
# Have the subject evaluate some gambles
# ------------------------------------------------------------

label_x = -.25
label_x = -.3
scale_1_y = -.45
scale_2_y = -.7
splotches_to_trials = {}

with showing(splotch):
for trial, splotch_num in enumerate(shuffled(test_splotches)):
splotch.setImage(splotch_path_fmt % (splotch_num,))
with dkey_prefix(('gambles', trial)):
save('splotch', splotch_num)
splotches_to_trials[splotch_num] = trial
scale_screen('probs',
text(-.95, -.2, u'How likely is…', 'left'),
rect((label_x - .025, scale_1_y - .05), .625, .1,
rect((label_x - .025, scale_1_y - .05), .75, .1,
(1, 1, 0)),
text(label_x, scale_1_y - .1, u'…the brownie outcome?', 'left'),
probability_scale(0, scale_1_y),
rect((label_x - .025, scale_2_y - .05), .625, .1,
rect((label_x - .025, scale_2_y - .05), .75, .1,
(0, .5, 1)),
text(label_x, scale_2_y - .1, u'…the math outcome?', 'left'),
probability_scale(0, scale_2_y))
Expand All @@ -429,6 +464,51 @@ with showing(splotch):
Button(-.25, -.75, 'Yes'),
Button(.25, -.75, 'No'))

# ------------------------------------------------------------
# Make one gamble count for real
# ------------------------------------------------------------

instructions('before_payout', "Okay, that's all the gambles. I'll now pick one at random to count for real.")

with dkey_prefix('payout'):

def payout_instructions(dkey, string, *stimuli): button_screen(dkey,
text(0, -.5, string),
Button(0, -.8, 'Next'),
*stimuli)

splotch_num = choice(test_splotches)
save('splotch', splotch_num)
splotch.setImage(splotch_path_fmt % (splotch_num,))

inflict_bad_outcome = False
with showing(splotch):
payout_instructions('picked_gamble', "Here's the gamble I picked.")
if data['gambles'][ splotches_to_trials[splotch_num] ]['choice'] == 'Yes':
# The subject said they would take this gamble.
pixel = randint(1, splotch_total_pixels)
save('pixel', pixel)
sp = splotch_pixels[splotch_num]
if pixel <= sp['bad']:
save('outcome', 'arithmetic')
payout_instructions('got_arithmetic', u'Oh no, you got the arithmetic outcome! Here we go…')
inflict_bad_outcome = True
elif pixel - sp['bad'] <= sp['neutral']:
save('outcome', 'nothing')
payout_instructions('got_nothing', 'You got the neutral outcome. Nothing happens.')
else:
save('outcome', 'brownie')
payout_instructions('got_brownie', 'You won a brownie! Show this screen to the experimenter in order to claim it.')
else:
payout_instructions('you_wimped_out', "You didn't say you'd take this gamble, so you get nothing.")

if inflict_bad_outcome:
with dkey_prefix('division'):
integer_math_problem('bad_outcome_p1_9/1', 'What is 9 divided by 1?')
integer_math_problem('bad_outcome_p2_50/10', 'What is 50 divided by 10?')
integer_math_problem('bad_outcome_p3_24/8', 'What is 24 divided by 8?')
#instructions('bad_outcome_done', "Actually, having you do half an hour of division problems would be a waste of your time as well as ours, so let's wrap this up.")

# ------------------------------------------------------------
# Done!
# ------------------------------------------------------------
Expand Down

0 comments on commit 682e6be

Please sign in to comment.