More woe with conditional loops

URL of experiment:

Description of the problem:
The loop is not behaving as it is supposed to online and is behaving very strangely.

The way the loop is supposed to work:
(1) object is correct if within 150 pixels (i.e., inside the polygon i’ve included for easy testing)
(2) if an object is answered correctly twice in a row , (i.e., on two consecutive occasions that item, e.g., cow is attempted) it drops from the loop (i.e., its value goes from 0>1>2; if it is answered incorrectly, its value in the dict drops to 0 - the values for the other objects should stay the same here and they should still be skipped if their value reaches 2)
(3) loop terminates when all objects placed in correct location twice in a row (i.e., all objects values are 2 in dict).

The java script is behaving in the current undesirable way:
(0) if the participant answers all questions correctly the loop terminates as it should
(1) if an object is answered incorrectly it seems to reset to 0 as desired
(2) it will then finish all the objects in the that round of the loop
(3) it will then demand two new full loops in which I answer the original incorrect trial correctly (i.e., it is not skipping)
(4) then it will start a final round of the loop and terminate only once it reaches the object I originally answered incorrectly

note* currently I have all values of objects in dict set to 1 for quicker testing.

note* works fine in psychopy builder and has done since Feb, I just can’t get it going in the browser

note - @jonathan.kominsky made the helpful suggestion that it may have something to do with how the dictionary updates between loops. I am starting to look into learning some basic debugging but progress is slow as I have no js training.

Some of the threads I have checked out:

among others - I have a done a LOT of playing around with where the code should go (each frame,end routine, etc)

  • i’m at my wits end with this and the only reasonable option I see at this point is to quit my PhD, learn how to live off the land and never look at a computer screen again :sweat_smile:

Any help much appreciated :grinning:

Cheers,
Tom

Sorry for the lack of clarity. You put console.log directly into the JS code. So, whenever your dictionary updates, you can put (in the JS directly, which you can access by changing code type to “both”):

console.log(obs_dict[image]);

for example, and it will output the value of the dictionary for that image at that time.

my code type is already to both, I added that console log command to the part of the js code directly after the dictionary is updated and nothing happened, i ran it both online (nothing new was outputted) and locally, nothing was added to the console - what am i missing?

Cheers,
Tom

Sorry, possibly I’m having a curse of knowledge issue. Which console are you looking in? JS console.log commands will show up in your browser’s javascript console. In Chrome (and it’s similar in most others) you go to view -> developer ->javascript console and the console will open as a panel at the side of your browser window. This will allow you to see any error messages and any console.log commands.

Putting this command in the JS won’t do anything on local runs because local runs use Python code. Only Pavlovia uses JS code. Python has a different way of doing this kind of debugging (you can just use print('whatever')), but it sounds like this is working just fine in Python, so you could add corresponding print commands to your python code to compare and see where they’re diverging but otherwise it’s not really necessary.

There are also other options for getting the code to tell you what it’s doing. If you want JS to make it really obvious what it’s doing, the other command you can use (and this is also JS-only) is “alert”, which will throw a pop-up window (for example: https://www.w3schools.com/jsref/tryit.asp?filename=tryjsref_alert)

thanks - i’m looking into how to use the javascript console in chrome, that was the bit that was unclear.

ok so now my console.log commands suggest to me that:
(1) the correct answer works fine and updates the dictionary
(2) skipThisTrial=True never works (this fits with what the experience I have when I run it, described above) and this lets the dictionary values keep climbing when the experiment should finish when they all reach the value of 2.

i’ve seen other threads with issues with skipping trials which are usually fixed just by moving the code to a different location (e.g. every frame, end routine) but that doesn’t seem to be working for me.

any suggestions on how to fix this?

@dvbridges @apitiot @jon

OK, we’re making progress. I have a couple ideas. They’re not guaranteed to work, but even if they don’t, it should help clarify what’s going on.

  1. Rather than making the condition for “skipThisTrial” that obs_dict[image] is exactly 2, make it >= 2. That way, even if obs_dict keeps counting up, it should correctly set skipThisTrial. That’s a sort of backstop rather than a fix to the underlying issue, however.

  2. As for the underlying issue, try changing if (!skipThisTrial) to if (skipThisTrial == false) (in JS; in Python “False” would be capitalized). There is a weird subtlety in how JS interprets conditional statements like “if(boolean)” as compared to “if(boolean==true)”, they do mean different things. If you’re curious, see here: https://stackoverflow.com/questions/23061921/javascript-ifx-vs-ifx-true

Let me know what happens.

ok that was interesting - skipThisTrial still isn’t initiating but the program did work a little better than before. This time the loop terminated as soon as the the final object reached a value of 2 (before the object would reach and then terminate as soon as it was about to be presented for time 3 for some reason i don’t know).

if ((obs_dict[image] >= 2)) {
    if (! _pj.in_es6(0, Object.values(obs_dict)) && (! _pj.in_es6(1, Object.values(obs_dict)))) {
        trials.finished = true;
        skipThisTrial = true;
        console.log(skipThisTrial);
        continueRoutine = false;
        }
    } else {
        skipThisTrial = false;
        console.log(skipThisTrial);
        }

are the not values (e.g., ! _pj.in_es6…etc) a problem too then?

cheers,
Tom

I think that condition is the issue, but maybe not for that reason. I’m trying to puzzle through exactly how you want “skipThisTrial” to work. With that code, as far as I can see, it will only be true when everything in obs_dict is 2. The current logic is, “if obs_dict for this image is greater than or equal to two, if the values of obs_dict do not include any instances of 1 or 0, skipThisTrial is true, end this loop, end this trial”. Is that what you’re after? Or is the intent “if obs_dict for this image is greater than or equal to two, skipThisTrial is true. If that is also true for every other image, then end the loop and routine”?

Basically right now it’s only going to set skipThisTrial to true when they’ve gotten everything right twice in a row, but I think the logic of what you describe in your first post would look more like this:

if ((obs_dict[image] >= 2)) {
    skipThisTrial = true;
    console.log(skipThisTrial);
    if (! _pj.in_es6(0, Object.values(obs_dict)) && (! _pj.in_es6(1, Object.values(obs_dict)))) {
        trials.finished = true;
        continueRoutine = false;
        }
    } else {
        skipThisTrial = false;
        console.log(skipThisTrial);
        }

ok that was definitely another step in the right direction for sure.

What I want to happen, which is working in python, is that as soon as an object reaches 2 (i.e., a cow) we don’t see the cow again, and the loop terminates when all the objects reach 2.

applying your suggested code had a weird effect i’m not sure of yet -
(1) the pic shows it definitely turned on skipThisTrial=true
(2) the loop terminated when the final image reached 2
(3) the problem was that it only skipped the feedback routines for the images that had reached 2 or above - is it maybe time to start moving around the code again to e.g., begin routine again, or is it something to do with the structure of the code itself :thinking:?

cheers,
Tom

Need clarification on that behavior:

Is the idea that it should only show feedback if they got it wrong, even if they haven’t yet gotten it right twice in a row?

feedback is shown for all trials that are still in circulation regardless of whether the participant was correct or not.

As soon as the image reaches 2, they aren’t supposed to see the image or the feedback for that item again.

Cheers,
Tom

Then what is it doing that it’s not supposed to? The description you give is that once an image has reached 2, it no longer shows the feedback, right? Or is the issue that it is showing feedback for trials that it is not supposed to? Please clarify.

Glancing at the code it seems like it should be doing what you describe, it checks skipThisTrial on every frame, which is when it needs to check it in order to end the feedback routine.

when I tried it, it cut out the feedback at the right time, but didn’t cut out the images that were meant to be skipped.

So say a cat, cow and piano all reached 2 - these will still presented until all items reached 2 (i don’t want this to happen, i don’t want participants to see an object or its feedback routine again as soon as the object reaches 2) but the feedback routine for them were skipped (a good thing).

So this definitely seems like a step in the right direction but its still slightly off.

Cheers,
Tom

Ahhhh, got it. So it was only skipping the feedback, not the trial itself. I understand now. Another small restructuring of the conditional should do it:

if ((obs_dict[image] >= 2)) {
    skipThisTrial = true;
    console.log(skipThisTrial);
    continueRoutine = false;
    if (! _pj.in_es6(0, Object.values(obs_dict)) && (! _pj.in_es6(1, Object.values(obs_dict)))) {
        trials.finished = true;
        }
    } else {
        skipThisTrial = false;
        console.log(skipThisTrial);
        }

That should end the current trial but not the loop when obs_dict for that image is >= 2, and as it sets skipThisTrial to true, it should also skip the feedback for that trial.

omg i think you’ve cracked it!

I’ll check it a lot more thoroughly tomorrow for anything unexpected but it seems to be working perfectly now.

I can’t thank you enough - i’ve been struggling with this stage for about 5-6 weeks now and i can finally start my projects.

I’m delighted, thank you so much Jonathan you absolute legend. :love_you_gesture:

Cheers,
Tom

1 Like