All files / adapters/cubing twistyPlayerSync.ts

100% Statements 11/11
100% Branches 0/0
100% Functions 0/0
100% Lines 11/11

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48                                      37x     68x   68x 68x 68x     1x       37x   26x 26x       42x     3x        
import type { TwistyPlayer } from 'cubing/twisty';
 
type TwistyPlayerModel = {
  alg: { get: () => Promise<unknown> };
};
 
type TwistyPlayerPort = Pick<TwistyPlayer, 'experimentalAddMove'> & {
  alg: string;
  experimentalModel: TwistyPlayerModel;
};
 
/**
 * Serializes TwistyPlayer writes.
 *
 * `experimentalAddMove` reads and updates its algorithm asynchronously. Calling
 * it once per BLE packet without awaiting its model update lets concurrent calls
 * append to the same old algorithm, so all but one move can be lost.
 */
export function createTwistyPlayerSync(player: TwistyPlayerPort, onUpdate?: () => void) {
  let writes = Promise.resolve();
 
  function enqueue(write: () => void): void {
    writes = writes
      .then(async () => {
        write();
        await player.experimentalModel.alg.get();
        onUpdate?.();
      })
      .catch((error: unknown) => {
        console.error('TwistyPlayer state update failed.', error);
      });
  }
 
  return {
    setAlgorithm(algorithm: string): void {
      enqueue(() => {
        player.alg = algorithm;
      });
    },
    addMove(move: string): void {
      enqueue(() => player.experimentalAddMove(move, { cancel: false }));
    },
    async whenIdle(): Promise<void> {
      await writes;
    },
  };
}