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
43 stars 8 forks source link

game.assignPlayer(player) not working #542

Closed dharakyu closed 2 months ago

dharakyu commented 3 months ago

Is there an existing issue for this?

What happened?

I'm having an issue with the game.assignPlayer(player) function for custom assignment. Previously, in v1.8.4 I was able to assign a player to a specific game upon entering their player identifier, using something similar to the following logic:

async function assignPlayerToGame(games, player) {
  // assign to first game in games object
  await games[0].assignPlayer(player);
}

Empirica.on("player", "participantIdentifier", (ctx, { player }) => {
  console.log(player.get('initialized'))
  if (player.get("initialized")) {
    return; // this is to make sure that the callback doesn't run twice, which it does for some reason
  }
  player.set("initialized", true);

  const openBatches = getOpenBatches(ctx);
  const batch = selectOldestBatch(openBatches);
  const games = batch.games;
  await assignPlayerToGame(games, player);
}

But now in v1.9.8 I'm getting an error upon the the call to games[0].assignPlayer(player). Specifically, I get the following:

[server] Unhandled Promise Rejection. Reason:  [t [CombinedError]: [GraphQL] cannot be null] {
[server]   graphQLErrors: [
[server]     Oi [GraphQLError]: cannot be null
[server]         at bI (/Users/dharakyu/Documents/parking-lot-exp-empirica/server/node_modules/@urql/core/src/utils/error.ts:24:10)
[server]         at Array.map (<anonymous>)
[server]         at t (/Users/dharakyu/Documents/parking-lot-exp-empirica/server/node_modules/@urql/core/src/utils/error.ts:61:5)
[server]         at Cd (/Users/dharakyu/Documents/parking-lot-exp-empirica/server/node_modules/@urql/core/src/utils/result.ts:22:15)
[server]         at <anonymous> (/Users/dharakyu/Documents/parking-lot-exp-empirica/server/node_modules/@urql/core/src/internal/fetchSource.ts:45:10)
[server]         at processTicksAndRejections (node:internal/process/task_queues:96:5) {
[server]       path: [Array],
[server]       locations: undefined,
[server]       extensions: [Object]
[server]     }
[server]   ],
[server]   networkError: undefined,
[server]   response: nr [Response] {
[server]     size: 0,
[server]     timeout: 0,
[server]     [Symbol(Body internals)]: { body: [PassThrough], disturbed: true, error: null },
[server]     [Symbol(Response internals)]: {
[server]       url: 'http://localhost:3000/query',
[server]       status: 422,
[server]       statusText: 'Unprocessable Entity',
[server]       headers: [ar [Headers]],
[server]       counter: 0
[server]     }
[server]   }
[server] }
[server] 20:48:43.719 WRN failed load: [GraphQL] cannot be null

I checked the game and player objects and neither appear to be null, so I'm confused where the null is coming from. The only potential hypothesis comes from the following experiment: when I set the game assignment to trigger on a later event, i.e. Empirica.on("player", "introDone", (ctx, { player }), the player sees the spinning circle after clicking "Enter" on the player identifier page (which is the expected behavior I think, since the player has not been manually assigned to a game and by default isn't assigned to any game). Then, when I change the code in callbacks.js to trigger on participantIdentifier (i.e. Empirica.on("player", "participantIdentifier", (ctx, { player })) and then the app is hot reloaded, the player is successfully assigned to a game (the intro steps appear). This leads me to believe that it might be a sequencing issue, where the game assignment with the participantIdentifier trigger is being triggered before it's ready (somehow), but I am not at all sure.

Steps To Reproduce

No response

Empirica Version

v1.9.8

What OS are you seeing the problem on?

macOS

What browser are you seeing the problem on?

Chrome

Relevant log output

[server] Unhandled Promise Rejection. Reason:  [t [CombinedError]: [GraphQL] cannot be null] {
[server]   graphQLErrors: [
[server]     Oi [GraphQLError]: cannot be null
[server]         at bI (/Users/dharakyu/Documents/parking-lot-exp-empirica/server/node_modules/@urql/core/src/utils/error.ts:24:10)
[server]         at Array.map (<anonymous>)
[server]         at t (/Users/dharakyu/Documents/parking-lot-exp-empirica/server/node_modules/@urql/core/src/utils/error.ts:61:5)
[server]         at Cd (/Users/dharakyu/Documents/parking-lot-exp-empirica/server/node_modules/@urql/core/src/utils/result.ts:22:15)
[server]         at <anonymous> (/Users/dharakyu/Documents/parking-lot-exp-empirica/server/node_modules/@urql/core/src/internal/fetchSource.ts:45:10)
[server]         at processTicksAndRejections (node:internal/process/task_queues:96:5) {
[server]       path: [Array],
[server]       locations: undefined,
[server]       extensions: [Object]
[server]     }
[server]   ],
[server]   networkError: undefined,
[server]   response: nr [Response] {
[server]     size: 0,
[server]     timeout: 0,
[server]     [Symbol(Body internals)]: { body: [PassThrough], disturbed: true, error: null },
[server]     [Symbol(Response internals)]: {
[server]       url: 'http://localhost:3000/query',
[server]       status: 422,
[server]       statusText: 'Unprocessable Entity',
[server]       headers: [ar [Headers]],
[server]       counter: 0
[server]     }
[server]   }
[server] }
[server] 20:48:43.719 WRN failed load: [GraphQL] cannot be null

Anything else?

No response

Code of Conduct

dharakyu commented 3 months ago

I'm adding some more info here in case it's helpful for debugging - I'm not sure it's actually a bug (it might just be me not properly configuring the assignment).

Separately but relatedly, I am trying to implement logic to allow a player to join another new game once the player has reached the exit steps of a previous game. I'd like to have the player have the option to click a button to be assigned to a new game, and then start in the waiting room to be paired with another player, to start another game from the top. I'm trying to do that by implementing a callback that listens for a variable playAgain ; once that variable is set, I then assign the player to another game via game.assignPlayer(player). The problem is that the player seems to be stuck in the exit steps, even as I can see on the admin console that they are actually in a different game. More concretely, it is still attempting to render the exit step component even as I am in the new game. Instead, I would like it to render the last introStep or just go straight to the pairing screen, depending on my conditional logic. Any thoughts on how to fix this?

npaton commented 2 months ago

This should be fixed in the next release, v1.11.1. Let me know.