fix(core): empty the first pit when animating a single stone move
PitAnimator guessed the played pit of a single stone move from the first sowing step and skipped index 0, so playing one stone from player 1's first pit showed it still holding the stone until the animation ended. It now empties the move's own pit (moveIndex).
This commit is contained in:
parent
27f13e2f9a
commit
3ea2ba18e3
@ -7,6 +7,7 @@ import {
|
||||
GAME_STEP_LAST_STONE_IN_BANK,
|
||||
GAME_STEP_DOUBLE_STONE_IN_PIT,
|
||||
MancalaGame,
|
||||
MoveHistoryItem,
|
||||
} from "mancala.js";
|
||||
import { v4 } from "uuid";
|
||||
import { BoardViewModel } from "../viewmodel/BoardViewModel";
|
||||
@ -92,12 +93,6 @@ export class PitAnimator {
|
||||
this.animationIndex++;
|
||||
}
|
||||
|
||||
getGameMoveStepCount(historyItem: HistoryItem) {
|
||||
return historyItem.gameSteps.filter(
|
||||
(gameStep) => gameStep.type === GAME_STEP_GAME_MOVE
|
||||
).length;
|
||||
}
|
||||
|
||||
animatePit(
|
||||
index: number,
|
||||
boardViewModel: BoardViewModel,
|
||||
@ -106,15 +101,9 @@ export class PitAnimator {
|
||||
if (!this.currentHistoryItem || !this.game || !this.mancalaGame) return;
|
||||
const pitViewModel = boardViewModel.pits[index];
|
||||
if (this.animationIndex === 0) {
|
||||
//This is one stone move case, TODO: beautify it later
|
||||
if (this.getGameMoveStepCount(this.currentHistoryItem) === 1) {
|
||||
const previousPitIndex = gameStep.index - 1;
|
||||
if (previousPitIndex > 0) {
|
||||
boardViewModel.pits[previousPitIndex].stoneCount = 0;
|
||||
}
|
||||
} else {
|
||||
pitViewModel.stoneCount = 0;
|
||||
}
|
||||
// The played pit empties before its stones are sown (a single stone goes on to the next pit).
|
||||
const { moveIndex } = this.currentHistoryItem as MoveHistoryItem;
|
||||
boardViewModel.pits[moveIndex].stoneCount = 0;
|
||||
}
|
||||
const theme = this.themeManager.theme;
|
||||
if (gameStep.type === GAME_STEP_GAME_MOVE) {
|
||||
|
||||
68
packages/core/tests/animation/PitAnimator.test.ts
Normal file
68
packages/core/tests/animation/PitAnimator.test.ts
Normal file
@ -0,0 +1,68 @@
|
||||
import { CommonMancalaGame, MancalaGame } from "mancala.js";
|
||||
import { PitAnimator } from "../../src/animation/PitAnimator";
|
||||
import { Game } from "../../src/models";
|
||||
import { ThemeManager } from "../../src/theme";
|
||||
import { BoardViewModel } from "../../src/viewmodel/BoardViewModel";
|
||||
|
||||
const P1 = "player-1";
|
||||
const P2 = "player-2";
|
||||
|
||||
const memoryStorage = () => {
|
||||
const values = new Map<string, string>();
|
||||
return {
|
||||
getString: (key: string) => values.get(key),
|
||||
setString: (key: string, value: string) => void values.set(key, value),
|
||||
deleteString: (key: string) => void values.delete(key),
|
||||
};
|
||||
};
|
||||
|
||||
const asGame = (mancalaGame: MancalaGame): Game => ({
|
||||
id: mancalaGame.id,
|
||||
mancalaGame,
|
||||
gameUsersConnectionInfo: {
|
||||
user1ConnectionInfo: { userId: P1, isOnline: true },
|
||||
user2ConnectionInfo: { userId: P2, isOnline: true },
|
||||
},
|
||||
});
|
||||
|
||||
// Plays the move on a copy of the game and returns the stones the animator shows after each step.
|
||||
const animateMove = (setUp: (game: MancalaGame) => void, playerId: string, pit: number): number[][] => {
|
||||
jest.useFakeTimers();
|
||||
const createGame = () => {
|
||||
const game = new CommonMancalaGame("game-1", P1, P2);
|
||||
game.turnPlayerId = playerId;
|
||||
setUp(game);
|
||||
return game;
|
||||
};
|
||||
const before = createGame();
|
||||
const after = createGame();
|
||||
after.moveByPlayerPit(playerId, pit);
|
||||
|
||||
const frames: number[][] = [];
|
||||
const animator = new PitAnimator(new ThemeManager(memoryStorage()), (boardViewModel: BoardViewModel) =>
|
||||
frames.push(boardViewModel.pits.map((pitViewModel) => pitViewModel.stoneCount)), 10);
|
||||
animator.setNewGame(asGame(before));
|
||||
frames.length = 0;
|
||||
animator.setUpdatedGame(asGame(after));
|
||||
jest.advanceTimersByTime(10 * (after.history[0].gameSteps.length + 1));
|
||||
jest.useRealTimers();
|
||||
return frames.slice(1);
|
||||
};
|
||||
|
||||
describe("PitAnimator", () => {
|
||||
it("empties the played pit when a single stone moves on", () => {
|
||||
for (const pit of [0, 3]) {
|
||||
const frames = animateMove((game) => {
|
||||
game.board.pits[pit].stoneCount = 1;
|
||||
}, P1, pit);
|
||||
expect(frames[0][pit]).toBe(0);
|
||||
expect(frames[0][pit + 1]).toBe(5);
|
||||
}
|
||||
});
|
||||
|
||||
it("empties the played pit and sows from it when several stones move", () => {
|
||||
const frames = animateMove(() => undefined, P1, 0);
|
||||
expect(frames[0].slice(0, 4)).toEqual([1, 4, 4, 4]);
|
||||
expect(frames[3].slice(0, 4)).toEqual([1, 5, 5, 5]);
|
||||
});
|
||||
});
|
||||
Loading…
Reference in New Issue
Block a user