psychopy / psychojs

PsychoJS is the online counterpart of the PsychoPy Python library
MIT License
165 stars 68 forks source link

Python's logical operators "and" and "or" are not always translated to "||" and "&&" in JS #561

Open rshamsnejad opened 1 year ago

rshamsnejad commented 1 year ago

In the Builder, I have defined a button that appears and disappears on two conditions :

image

The conditions are the following :

# Start
(sound_original.status != NOT_STARTED) or (sound_A.status != NOT_STARTED) or (sound_B.status != NOT_STARTED)
# Stop
(sound_original.status != STARTED) and (sound_A.status != STARTED) and (sound_B.status != STARTED)

And when I compile to JS, it produces the following :

    if ((((sound_original.status != NOT_STARTED) or (sound_A.status != NOT_STARTED) or (sound_B.status != NOT_STARTED))) && stop.status === PsychoJS.Status.NOT_STARTED) {
      // keep track of start time/frame for later
      stop.tStart = t;  // (not accounting for frame time here)
      stop.frameNStart = frameN;  // exact frame index

      stop.setAutoDraw(true);
    }

    if (stop.status === PsychoJS.Status.STARTED && Boolean(((sound_original.status != STARTED) and (sound_A.status != STARTED) and (sound_B.status != STARTED)))) {
      stop.setAutoDraw(false);
    }

This causes the webpage to get stuck on "initialiasing the experiment..." unless I replace all the "or" and "and" by "||" and "&&" respectively.

And thanks for this awesome tool !

F-said commented 1 year ago

We ran into a similar issue. The workaround we implemented was to create a variable in a code component which gets flipped to True when a proposition in a component condition contains and or or.

For example, in my Begin Experiment tab I'd have:

# init variable set to False
showFirstButton = False

Then in Each Frame, I'd have:

# show button after set amount of time of passage completion
if passage_sound.status == FINISHED and t > passage_sound.getDuration() + WAIT_DURATION:
    showFirstButton = True

Then in the condition text-box of my component I'd place theshowFirstButton variable with the dollar-sign notation $showFirstButton.

Hope it helps!

TEParsons commented 5 months ago

The translation from Python to JS is handled by the psychopy app, so this is one I can handle :) @apitiot if you transfer this issue over to the psychopy repo I'll be able to link it to the PR once I figure out a fix.

I actually don't think or is the problem here - if you use the same code in a Code component (as in @F-said 's solution), it translates just fine. I think it's that start/stop conditions aren't translated at all, or possibly are translated via a different function (I know we have two, one for code blocks and one for single-line expressions).