Setting up a Sugar Factory Task on Psychopy

Hi -

I am creating a Dynamic Systems Control Task (Sugar Factory) and we have a code that we used to run the experiment in Octave locally. We now need to design the experiment such that it can be run with a wider audience and want to use Psychopy given it seems the most flexible platform for this task and the experiment can also be run online.

As a caveat, I have little experience in coding and have never used Psychopy. However, I have tried to re code our original experiment in Octave into Python (below) but I am struggling to get it to run in Psychopy. I think the easiest option I have found for me is to use the builder tool and then use this custom coding to create the experiment in the trials, however, whichever way I try and use the code it does not seem to run in JS.

The experiment should essentially work as follows (at a high level):

  • Participant sees a chart with a starting bar chart of 6000
  • They are then asked to enter a number from 100-1200 (in intervals of 100) in order to reach a target production level of 9000
  • After they enter the number, they also have to mark how confident they are on a scale of 1-5 that they will reach the target production
  • Once they enter a value, the bar chart updates based on the equation in this code and they see the new production
  • This repeats 20 times which is one block
  • The experiment should have five blocks in this format

There are two issues here:

  • the code (I imagine the code in and of itself is not correct and does not include the necessary psychopy language to run in JS especially)
  • how the code will be used in Psychopy (I am not sure if the best way would be to have psychopy run the entire script in a trial or separate the code so Psychopy runs the loops in the builder and have separate blocks with the same code)

Any advice/suggestions or guidance is welcome. Hoping someone with much more experience in both areas may be able to help!

Thanks so much in advance

Code:

from psychopy import visual, event, core, gui, simpledialog

Create a window

win = visual.Window([1800,700], monitor=“testMonitor”)

W_level = list(range(100, 1300, 100)) # possible worker numbers (100-1200 in steps of 100)
C_level = list(range(1, 6)) # possible confidence ratings
random_er = [-1000, 0, 1000] # possible random error in final production +/- 1000

trial_perblock = 20 # number of trials per block
blockn = 5 # number of blocks

P_start=6000 # starting production level (hard-coded in line with the paper)
W_start=600 # startiang worker level; The values are reset to these levels at the start of each block

input_check=0 # for worker number input
conf_check=0 # for confidence rating input

W = [[0 for i in range(trial_perblock)] for j in range(blockn)]
E = [[0 for i in range(trial_perblock)] for j in range(blockn)]
P = [[0 for i in range(trial_perblock)] for j in range(blockn)]
C = [[0 for i in range(trial_perblock)] for j in range(blockn)]

for b in range(1, blockn + 1):
# Initialize block & display first W&P
ok = 0 # for end-of block

print("Workers   : ", W_start)
print("Production: ", P_start)

# create the chart to display to participants
win = visual.Window()

bar = visual.Rect(win, width=0.5, height=P_start, pos=(0, 0), fillColor='blue')
line = visual.Line(win, start=(-0.5, 9000), end=(trial_perblock + 1.5, 9000), lineColor='red')
xaxis = visual.Line(win, start=(-0.5, 0), end=(trial_perblock + 1.5, 0), lineColor='black')
yaxis = visual.Line(win, start=(0, 0), end=(0, 12000), lineColor='black')

for t in range(1, trial_perblock+1):
while True:
userinput = simpledialog.askinteger(“Select number of workers”,
"Workers: " + str(W_level) + "\nBlock: " + str(b) + " Day: " + str(t),
minvalue=100, maxvalue=1200)

    if userinput in W_level:
        W[b-1][t-1] = userinput
        E[b-1][t-1] = random.choice(random_er)
        if t == 1:
            P[b-1][t-1] = 20*W[b-1][t-1] - P_start + E[b-1][t-1]
        else:
            P[b-1][t-1] = 20*W[b-1][t-1] - P[b-1][t-2] + E[b-1][t-1]
        P[b-1][t-1] = max(1000, min(12000, P[b-1][t-1]))
        break

        conf_check = 0
        while conf_check == 0:
            conf_input = int(input("Confidence in producing between 8000-10000 on THIS day: \n 1=Not at all confident \n 2=Slightly confident \n 3=Confident \n 4=Very confident \n 5=Extremely confident \n"))
            if conf_input in C_level:
                conf_check = 1
                C[b][t] = conf_input
            else:
                print("Invalid input. Please enter a valid number from 1 to 5.")

        print("Workers: " + str(W[b][t]))
        print("Production: " + str(P[b][t]))
        print("Confidence: " + str(C[b][t]))

        bar.height = P[b][t]
        bar.draw()
        line.draw()
        xaxis.draw()
        yaxis.draw()
        win.flip()

win.close()

while ok == 0:
end_block = input(“Press Q to end the block”)
if end_block == ‘Q’ or end_block == ‘q’:
ok = 1

W_start = W_level[random.choice(range(len(W_level)))]
P_start = 6000
print(“Next block”)