PennController for IBEX › Forums › Support › Restart trial
- This topic has 4 replies, 2 voices, and was last updated 3 years, 2 months ago by ekakoki.
-
AuthorPosts
-
June 21, 2021 at 5:12 pm #7069ekakokiParticipant
Hello,
I’ve been trying to write a code for a series of practice trials that would each restart until the desired choice is selected. However, I keep running into the error “Cannot read property ‘id’ of undefined”. This is what I have so far:
newVar("selected", "") const whichOne = (number, selectorName) => [ getSelector(selectorName).test.selected(getImage("o" + number)) .success( newAudio("o" + number + "selected", "o" + number + "Audio.m4a") .play() .wait() , selected = number) .failure(whichOne(number + 1)) ] const runPractice = (LP,RP,LO,RO,tag) => [ clear() , defaultImage.size(200,200) , newCanvas("images", 1500, 600) .color("white") .add( 0 , 100 , newImage("p1", LP + ".jpeg" ).size(400, 400) ) .add(450 , 100 , newImage("p2", LP + RP + ".jpeg").size(600,400) ) .add(1100 , 100 , newImage("p3", RP + ".jpeg").size(400, 400) ) .add( 0 , 500 , newImage("o1", LO + ".png") ) .add(200 , 500 , newImage("o2", RO + ".png") ) .add(550 , 500 , newImage("o3", LO + ".png") ) .add(750 , 500 , newImage("o4", RO + ".png") ) .add(1100 , 500 , newImage("o5", LO + ".png") ) .add(1300, 500 , newImage("o6", RO + ".png") ) .print("center at 50vw","top at 2em") , newButton("Go").center().wait() , newAudio("description", tag + ".m4a") .play() .wait() , newSelector("response") .add( getImage("o1") , getImage("o2") , getImage("o3") , getImage("o4") , getImage("o5") , getImage("o6")) .wait() , newButton("whichOneLaunch").callback(whichOne(1)).click() ] Template("examples.csv", row => newTrial("practice", newButton("runPracticeLaunch") .callback(...runPractice(row.LP,row.RP,row.LO,row.RO,row.tag)) .click() , getVar("selected").test.is(row.correctChoice) .failure(newButton("Restart").callback(getButton("runPracticeLaunch").click())) , newHtml("readyscreen", "readyscreen.html") .center() .print() , newButton("Continue") .center() .print() .wait() ) )
I’m fairly new to using .callback() commands, so that could be the issue, but I’m not sure how else to format this. I would appreciate any suggestions to make this run! Thank you!
- This topic was modified 3 years, 2 months ago by ekakoki.
June 21, 2021 at 5:54 pm #7071JeremyKeymasterHello,
There are a couple problematic aspects with your code. First, elements are specific to trials, so you cannot define a Var element outside the scope of a
newTrial
. Second, yourwhichOne
function runs the risk of an infinite recursive loop (although I have to say it’s a pretty smart way of testing many values without having to duplicate your code). I recommend you read this guide to get a better idea of when commands are executedAll
callback
commands will run a series of commands when the corresponding element’s relevant event happens (eg. a click on a Button element). They’re mainly useful to escape the purely top-down execution of the code, in allowing for interactions to unfold while the main thread of the script iswait
ing somewhere. It is true that they can also be used to re-execute a pre-defined block of code, but I think you are overusing thecallback
command in your codeI think what you want is this:
const whichOne = (numbers, selectorName) => numbers.map( number => getSelector(selectorName).test.selected(getImage("o" + number)) .success( newAudio("o" + number + "selected", "o" + number + "Audio.m4a") .play() .wait() , getVar("selected").set(number) ) ) const runPractice = (LP,RP,LO,RO,tag,correctChoice) => [ clear() , newCanvas("images", 1500, 750) .color("white") .add( 0 , 100 , newImage("p1", LP + ".jpeg" ).size(400, 400) ) .add(450 , 100 , newImage("p2", LP + RP + ".jpeg").size(600,400) ) .add(1100 , 100 , newImage("p3", RP + ".jpeg").size(400, 400) ) .add( 0 , 500 , newImage("o1", LO + ".png") ) .add(200 , 500 , newImage("o2", RO + ".png") ) .add(550 , 500 , newImage("o3", LO + ".png") ) .add(750 , 500 , newImage("o4", RO + ".png") ) .add(1100 , 500 , newImage("o5", LO + ".png") ) .add(1300, 500 , newImage("o6", RO + ".png") ) .add( "center at 50%", "bottom at 100%", newButton("Go") ) .print("center at 50vw","top at 2em") , getButton("Go").wait().remove() , newAudio("description", tag + ".m4a") .play() .wait() , newSelector("response") .add( getImage("o1") , getImage("o2") , getImage("o3") , getImage("o4") , getImage("o5") , getImage("o6") ) .wait() , ...whichOne([1,2,3,4,5,6],"response") , getVar("selected").test.is(row.correctChoice) .success( newHtml("readyscreen", "readyscreen.html") .center() .print() , getButton("Continue").print("center at 50%","bottom at 100%",getCanvas("images")) ) .failure( getButton("runPracticeLaunch").click() ) ] Template("examples.csv", row => newTrial("practice", newVar("selected", 0) , defaultImage.size(200,200) , newButton("runPracticeLaunch") .callback(...runPractice(row.LP,row.RP,row.LO,row.RO,row.tag,row.correctChoice)) .click() , newButton("Continue") .center() .wait() ) )
I couldn’t test this code with your project’s material (feel free to share the demonstration link with me so I can do it) but I tried an non-Template non-Audio version of it which worked. Note that I’m printing the button onto the Canvas element because otherwise they appear below it
Jeremy
June 21, 2021 at 7:52 pm #7072ekakokiParticipantThank you for the help! It runs!…But I also realized that I’d need to include the trial number in describing which audio to play, as each trial has a different correct answer. I tried simply adding the trial number as a new parameter and into the newAudio line of
whichOne
, but it came back with another undefined property error. I then tried taking the newAudio line out completely and using it immediately afterwards:...whichOne([1,2,3,4,5,6], "response") , newAudio("ex" + exNum + "o" + getVar("selected") + ".m4a").play().wait()
However, it won’t play anything upon clicking on the options, and it doesn’t let me continue to the next practice example. The demonstration link is here: https://farm.pcibex.net/r/EIXHMT/
Maybe I can’t use getVar in this context? But I’m not sure why not.June 21, 2021 at 10:14 pm #7073JeremyKeymasterYou cannot use
getVar
that way, as explained in this guide I mentioned earlierYour first attempt was on the right track, but maybe you forgot to include the trial number in addition to the selection index?
const whichOne = (numbers, selectorName, ex) => numbers.map( number => getSelector(selectorName).test.selected(getImage("o" + number)) .success( newAudio("o" + number + "selected", "ex" + ex + "o" + number + ".m4a") .play() .wait() , getVar("selected").set(number) ) )
and then use it like this:
...whichOne([1,2,3,4,5,6], "response", exNum)
Jeremy
June 22, 2021 at 12:50 am #7074ekakokiParticipantThat was it! Thank you so much for your help, everything is running smoothly now!
-
AuthorPosts
- You must be logged in to reply to this topic.