PennController for IBEX › Forums › Support › About timeouts
- This topic has 10 replies, 2 voices, and was last updated 1 year, 1 month ago by Jeremy.
-
AuthorPosts
-
August 2, 2023 at 3:33 pm #10797Larissa_CuryParticipant
Hello! I’m wondering why the code below is indeed working. It is working, but I’m not sure WHY it is working. I’d like to know if the code is doing what I think it is. I’ve put my guesses into comments. I have a trial WITH feedback (a) and a trial WITHOUT feedback + Reaction time (b)
I’m mostly in doubt about the .wait() command
TRIAL A) WITH FEEDBACK
Template("simonStimuliPracticeNeutral.csv", row => newTrial("practice--neutral--block", ... , newTimer("timeout",5000).start() // HERE THE TIMEOUT STARTS. USER HAS ONLY 5s to ANSWER , newImage('stimuli', row.direction).print() // Print arrow left or right // hiding css details }) , newKey("answerKey","SK") .log("all") .callback( getTimer("timeout").stop() ) // THE KEYPRESS STOPS THE TIME, RIGHT? , getTimer("timeout").wait() // IF THERE ISN'T A KEY PRESS, THEN THE TIME ISN'T STOPPED, RIGHT? BUT how is it actually functioning? How is the 'wait()' functioning here? , getImage('stimuli').remove() // remove the image so that the feedback answer appears , getKey("answerKey") // Check for the correct key press or timeout .test.pressed(row.correctKey) // check keys (options are K and S) .success( newText("Correct ✅").center().print(), // Display "Correct" message newTimer('wait-positive-feedback', 500).start().wait() // Wait for positive feedback timer ) .failure( getKey("answerKey").disable().test.pressed("K", "S") // IF NEITHER K OR S was pressed, then display the timeout .failure( // Display "Timeout" message and wait for feedback timer newText("Timeout ⏰").center().print(), newTimer('wait-feedback', 500).start().wait() ) .success( // IF EITHER K OR S was pressed, then display the INCORRECT ANSWER IF IT DOENSN'T MATCH THE row.correctKey key newText("Incorrect ❌").center().print(), // display negative feedback newTimer('wait-neg-feedback', 500).start().wait() // Wait for negative feedback timer ) ) ) );
TRIAL B) WITHOUT FEEDBACK + RT, ONLY THE TIMEOUT
Template("simonStimuliNeutral.csv", row => newTrial("neutral--block", ... , newText('fixationCross', '+').center().print().cssContainer({'font-size': '200px'}) , newTimer('waitFixation', row.fixationTime).start().wait() , getText('fixationCross').remove() , newTimer("timeout",5000).start() // User has 5s to answer; otherwise => timeout , newImage('stimuli', row.direction).print() // Print arrow left or right // CSS HIDDEN // }) , newVar("RT").global().set( v => Date.now() ) // compute Reaction Time , newKey("answerKey","SK") .log("all") .callback( getTimer("timeout").stop() ) // THE KEYPRESS STOPS THE TIME, RIGHT? , getTimer("timeout").wait() // wait for the timeout to finish (no keypress, the time isn't stoped) ??? , getVar("RT").set( v => Date.now() - v ) // Set Reaction Time value BEFORE the msg for the timeout so that I //compute the timeout in case the user doens't press a key and his/her RT if she/he presses. //BUT: WHY is it working and NOT computing the RT + 5000s of the timeout //if I'm computing the RT AFTER the .wait() ? , getImage('stimuli').remove() , getKey("answerKey").disable().test.pressed().failure( newText("Incorrect", "Consegue ir mais rápido? ⏰").center().print(), newTimer('wait-feedback',500).start().wait() ) ) // LOG A BUNCH OF STUFF );
- This topic was modified 1 year, 1 month ago by Larissa_Cury. Reason: edit coding
August 3, 2023 at 5:15 am #10799JeremyKeymasterHi,
callback
commands inform the script of what to do whenever the relevant event happens, and immediately move on to the next line in the script. By contrast,wait
commands halt the execution of the script until the relevant event happens, after which only do they move on to the next line in the script. When you have these lines in a script:newTimer("timeout", 5000).start() // A , newVar("RT").global().set( v => Date.now() ) // B , newKey("answerKey","SK").log("all").callback( getTimer("timeout").stop() ) // C , getTimer("timeout").wait() // D , getVar("RT").set( v => Date.now() - v ) // E
The script first executes (A): it starts a 5s timer and moves on to (B) without waiting for the timer to elapse (because there is no
wait
command in A). At (B), which is executed immediately after (A), the scripts sets the Var element to the current timestamp, ie. a timestamp that corresponds to when the timer was started. The script immediately moves on to (C), which evaluates thecallback
command: here, the script learns that whenever the participant presses S or K, the commandgetTimer("timeout").stop()
should take effect. But importantly, there is nowait
command in (C) so the script immediately moves on to (D), but it now keeps in mind what should happen were the participant to press S or K at any point. At (D) the script sees await
command so it stays on (D) until the timer has stopped. This could happen because the 5s have elapsed, the normal course of events for a timer; or it could happen because the timer was stopped early, which is precisely what we instructed the script to do if the participant ever presses S or K, in the precedingcallback
command. So when the timer stops, regardless of which scenario we’re in, the script then moves on to (E) and sets the Var element to the current timestamp minus the previous one. If we’re in a scenario where the participant didn’t press S or K, then the script must have reached this line after waiting 5s, so the subtraction will result in that duration. But if we’re in a scenario where the timer was stopped because the user pressed S or K, then it hasn’t been 5s yet, and the subtraction will reflect that, and the result of the subtraction will be a lesser value. Once the Var element has been set, the script immediately moves on to the next line (if any)Jeremy
August 3, 2023 at 6:10 am #10800Larissa_CuryParticipantHi,Jeremy! Thank you for this detailed answer, I REALLY appreciate it! Now I got it! So, I can say that the
.stop()
command makes the.wait()
understand that the time has finished without waiting for the whol 5s, right? Now I got it! What about the feedback in the previous trial:It should be: “If user presses the correctKey, show the ✅; if he/she presses the wrong key, ❌; in case of a timwout (5 seconds), show the timeout message ⏰
Is this the correct syntax? It seems to be working just fine, but I’m not 100% sure
getKey("answerKey") // Check for the correct key press or timeout .test.pressed(row.correctKey) // check keys (options are K and S) .success( newText("Correct ✅").center().print(), // Display "Correct" message newTimer('wait-positive-feedback', 500).start().wait() // Wait for positive feedback timer ) .failure( getKey("answerKey").disable().test.pressed("K", "S") // IF NEITHER K OR S was pressed, then display the timeout .failure( // Display "Timeout" message and wait for feedback timer newText("Timeout ⏰").center().print(), newTimer('wait-feedback', 500).start().wait() ) .success( // IF EITHER K OR S was pressed, then display the INCORRECT ANSWER IF IT DOENSN'T MATCH THE row.correctKey key newText("Incorrect ❌").center().print(), // display negative feedback newTimer('wait-neg-feedback', 500).start().wait() // Wait for negative feedback timer ) ) )
August 3, 2023 at 6:21 am #10801JeremyKeymasterYou want to replace
getKey("answerKey").disable().test.pressed("K", "S")
withgetKey("answerKey").disable().test.pressed()
: this line is in afailure
command which already corresponds to a situation where the correct key wasn’t pressed so if, in that situation,test.pressed()
succeeds it means that the incorrect key was pressed, and if it fails it means that no key was pressedOther than that I don’t see any problems with this piece of code
Jeremy
August 3, 2023 at 6:35 am #10802Larissa_CuryParticipantThanks for the quick response!! So, the logic is:
.success: ✅ : if the eow.correctKey was pressed
timeout ⏰: if NO KEY was pressed
error message ❌: if a key != from row.correctKey (already evaluated before) was pressed. Right?getKey("answerKey") // Check for the correct key press or timeout .test.pressed(row.correctKey) // check keys (options are K and S) .success( newText("Correct ✅").center().print(), // Display "Correct" message newTimer('wait-positive-feedback', 500).start().wait() // Wait for positive feedback timer ) .failure( getKey("answerKey").disable().test.pressed() // => IF ANY KEY WAS PRESSED Was pressed, then display the timeout .failure( // Display "Timeout" message and wait for feedback timer newText("Timeout ⏰").center().print(), newTimer('wait-feedback', 500).start().wait() ) .success( // IF A KEY != FROM row.correctKey was pressed, then display the INCORRECT newText("Incorrect ❌").center().print(), // display negative feedback newTimer('wait-neg-feedback', 500).start().wait() // Wait for negative feedback timer ) ) )
August 3, 2023 at 7:59 am #10803Larissa_CuryParticipant@Jeremy, If I include an audio effect, will I bias the reaction time and the time out ? Like this:
does it influence the rt and the timeout?
... newAudio('keyPressAudio', "keyPress1.mp3") , newKey("answerKey","SK") .log("all") .callback( getTimer("timeout").stop(), // the key stops the time getAudio('keyPressAudio').play()) ////////////////// <--------------------- HERE , getTimer("timeout").wait() // wait for the timeout to finish (no keypress, the time isn't stoped) ??? , getImage('stimuli').remove() , // Check for the correct key press or timeout getKey("answerKey") .test.pressed(row.correctKey) // check keys .success( // Display "Correct" message and wait for positive feedback timer newText("Correct ✅").center().print(), newTimer('wait-positive-feedback', 500).start().wait() ) .failure( // Check for timeout before displaying "Incorrect" message getKey("answerKey").disable().test.pressed() .failure( // Display "Timeout" message and wait for feedback timer getVar('errorCount').set(v=> v+1), newText("Timeout ⏰").center().print(), newTimer('wait-feedback', 500).start().wait() ) .success( // Display "Incorrect" message and wait for negative feedback timer getVar('errorCount').set(v=> v+1), newText("Incorrect ❌").center().print(), newTimer('wait-neg-feedback', 500).start().wait() ) )
August 3, 2023 at 8:58 am #10804JeremyKeymasterIt won’t make a difference, since the
wait
command will be released as soon asgetTimer("timeout").stop()
from thecallback
command has been executed; the commandgetAudio('keyPressAudio').play()
insidecallback
will just run in parallel togetImage('stimuli').remove()
and the commands coming after that (including theset
commands further down) from the main threadJeremy
August 4, 2023 at 12:07 pm #10805Larissa_CuryParticipantPerfect! Thank you very much (again) for the detailed feedback 🙂
August 10, 2023 at 8:14 am #10809Larissa_CuryParticipantHi, @Jeremy ! What is the best way to get the same effect (play the click sound when a button is clicked) using a selector? Like this:
I tried to use a .callback as well, but it didn’t work…With the code below, sometimes it works, sometimes it doesn’t (the audio is just an effect of a click)
newImage("mainImage", row.image) .css({ "display": "block", "position": "fixed", "top": "35vh", // 50% of the viewport height "left": '50%', // Use 50% for horizontal centering and 15% and 85% left/right "transform": "translate(-50%, -50%)", // "width": "25em", // Replace with the desired width of the image in em units // "height": "25em", // Replace with the desired height of the image in em units "z-index": "9999", // To make sure the image is on top of other elements }) .print() , newAudio('keyPressAudio', "keyPress1.mp3") , newSelector("position") , newCanvas("buttons",1180,100) .add("center at 10%", "bottom at 100%", newButton("btn--1", "1").selector("position")) .add("center at 30%", "bottom at 100%", newButton("btn--2", "2").selector("position")) .add("center at 50%", "bottom at 100%", newButton("btn--3", "3").selector("position")) .add("center at 70%", "bottom at 100%", newButton("btn--4", "4").selector("position")) .add("center at 90%", "bottom at 100%", newButton("btn--5", "5").selector("position")) .css({ "top": "40vh" }) .center() .print() , getSelector("position") .once() .wait() .log() , getAudio('keyPressAudio').play() ) // .log("item", row.imageAudio) .log('image', row.image) .log("correctKey", row.correctKey) );
August 10, 2023 at 8:27 am #10810Larissa_CuryParticipantgetAudio('keyPressAudio').play().wait('first')
<- this seems to work, but I don’t think that’s the best way to do it, right?August 11, 2023 at 11:37 am #10812JeremyKeymasterHi Larissa,
If you end the trial immediately after a selection is made, there just won’t be enough time to hear the audio which starts playing but is stopped immediately, along with the trial’s end. Using
wait
on the Audio element, as in your last message, after thewait
on the Selector element has been released, is one solution to make sure that the trial doesn’t end before the audio is done playingJeremy
-
AuthorPosts
- You must be logged in to reply to this topic.