empiricaly / empirica

Open source project to tackle the problem of long development cycles required to produce software to conduct multi-participant and real-time human experiments online.
https://empirica.ly/
Apache License 2.0
44 stars 8 forks source link

Can't reach <Game /> in EmpiricaContext since v1.9.0 #512

Closed yankai-wang closed 5 months ago

yankai-wang commented 5 months ago

Is there an existing issue for this?

What happened?

After upgrading to v1.9.0, the game is not running and get stuck on the blue circle page for certain conditions.

image

Steps To Reproduce

In the admin page, create a new game with treatments "full_decom_add_growFromIndiv" or "full_decom_add_growFromDyad". Then, open the game page and the bug shows after clicking "I AGREE". If keep the game running and switch back to v 1.8.x, the bug will disappear.

Empirica Version

The bug appears since v1.9.0

What OS are you seeing the problem on?

macOS

What browser are you seeing the problem on?

Chrome

Relevant log output

No response

Anything else?

No response

Code of Conduct

npaton commented 5 months ago

It looks like the problem comes from a discrepancy between the treatment.playerCount and the number of players actually in the Game. Looks like you might be starting a game with fewer players than playerCount with your custom assignment scheme. I think you should be able to get around this by adding unmanagedGame on <EmpiricaContext>. This will skip waiting for the Game to be assigned before intro steps (which shouldn't be a problem in your case, since you're only intro step does not depend on Game), and it will not wait for all expected objects to be ready before rendering <Game>. That second part might be a problem, so I'd recommend adding a modified version of this code at the top of your <Game>.

Let me know if that makes sense and works for you. 🙏

yankai-wang commented 5 months ago

More detailed solution just for record: pass unmanagedGame to <EmpiricaContext> and in the Game component, add the following function:

function useAllReady() {
  const player = usePlayer();
  const players = usePlayers();
  const game = useGame();
  const stage = useStage();
  const round = useRound();

  if (
    !player ||
    !players ||
    !stage ||
    !round ||
    !game ||
    !player.game ||
    !player.round ||
    !player.stage
  ) {
    return false;
  }

  for (const p of players) {
    if (!p.game || !p.round || !p.stage) {
      return false;
    }
  }

  return true;
}

Then in Game, if not allReady, return <Loading />