Looking at the code I see a couple potential issues.
One is that you might be doing more than you need to with the code component. Your code component asks “ding” to play, but you are also setting a condition for “ding” to play in the builder. So if you look at the builder-compiled JS (https://gitlab.pavlovia.org/learningdevlab/v17_i_give_up/blob/master/html/all2afc_backbone.js) you’ll notice on lines 2627-2638:
if ((timetoDing = true) && ding.status === PsychoJS.Status.NOT_STARTED) {
// keep track of start time/frame for later
ding.tStart = t; // (not accounting for frame time here)
ding.frameNStart = frameN; // exact frame index
psychoJS.window.callOnFlip(function(){ ding.play(); }); // screen flip
ding.status = PsychoJS.Status.STARTED;
}
if (t >= (ding.getDuration() + ding.tStart) && ding.status === PsychoJS.Status.STARTED) {
ding.stop(); // stop the sound (if longer than duration)
ding.status = PsychoJS.Status.FINISHED;
}
and then in the same function, on lines 2663-2680:
if ((repeat == "r") && (exposure_sound.status === PsychoJS.Status.FINISHED))
{
let repeatedRespKeys = repeated_resp.getKeys();
if (repeatedRespKeys[0] == 'y')
{
timetoDing = true;
ding.play();
ding.getDuration(2);
ding.PsychoJS.status = STARTED;
continueRoutine = false;
}
}
else if ((repeat !== "r") && (exposure_sound.status === PsychoJS.Status.FINISHED))
{
timetoDing = false
ding.PyschoJS.status = NOT_STARTED;
continueRoutine = false;
}
There’s a few problems. You’re setting the status to “STARTED” rather than “PsychoJS.Status.STARTED”, so it’s possible that it’s calling “ding” twice then timetoDing is set to true. You may not need to tell it to actually play ding in your code component at all if you leave that conditional in, it looks like it will just figure itself out.
On the other hand, if you want to control it exclusively through the code component, my recommendation would be to change the status to PsychoJS.Status.STARTED and add this from the auto-generated code:
psychoJS.window.callOnFlip(function(){ ding.play(); }); // screen flip
I don’t know how much that actually makes a difference, but it can’t hurt.
I’m also, now that I’m looking at the compiled JS code, realizing a few problems in how I was thinking about getKeys. I have a better idea of why it’s not working now, it involves keyboard buffers being cleared and some naming conventions I wasn’t paying close enough attention to. I think you do want to turn “force end of routine” off, but then you should change the code component again (sorry, I think I’ve led you astray several times because I didn’t look closely enough at how keyboard components work):
if ((repeat == "r") && (exposure_sound.status === PsychoJS.Status.FINISHED))
{
if (repeated_resp.keys == 'y')
{
timetoDing = true;
// include the following only if you want to control the sound entirely through the code component.
ding.play();
ding.getDuration(2);
ding.PsychoJS.status = PsychoJS.Status.STARTED;
psychoJS.window.callOnFlip(function(){ ding.play(); });
// end lines to include
//continueRoutine = false; I think this is ending the thing immediately, but in principle if all the components have the status "finished" then it should end the routine anyway
//if not, we'll need another condition to check when ding ends and end it then.
}
}
else if ((repeat !== "r") && (exposure_sound.status === PsychoJS.Status.FINISHED))
{
timetoDing = false
ding.PyschoJS.status = PsychoJS.Status.FINISHED;
continueRoutine = false;
}
}
Right now, before getting to your code component, it’s doing the “getKeys” call, which is clearing the key buffer, so calling it again in the code component will return nothing. However, it should be storing the last key pressed as repeated_resp.keys. If the code above doesn’t work try repeated_resp.keys[0] == ‘y’ instead (I’m not sure if it’s an array or a string).
I think this will work but unfortunately do not have time to test it myself. Let me know if that at least changes the behavior.