From 653f3f1de4a3a9fbe295f1b0237e374b7a2fde1a Mon Sep 17 00:00:00 2001 From: GuillaumeSD Date: Fri, 16 May 2025 13:24:17 +0200 Subject: [PATCH] fix : analyze game stuck on 1% progress --- src/components/board/index.tsx | 9 ++++---- src/lib/engine/uciEngine.ts | 21 +++++++++---------- .../analysis/hooks/useCurrentPosition.ts | 2 +- .../analysis/panelHeader/analyzeButton.tsx | 4 ++++ src/sections/play/board.tsx | 2 +- 5 files changed, 20 insertions(+), 18 deletions(-) diff --git a/src/components/board/index.tsx b/src/components/board/index.tsx index b5dc01e..0b8174b 100644 --- a/src/components/board/index.tsx +++ b/src/components/board/index.tsx @@ -10,7 +10,7 @@ import { Square, } from "react-chessboard/dist/chessboard/types"; import { useChessActions } from "@/hooks/useChessActions"; -import { useCallback, useMemo, useRef, useState } from "react"; +import { useCallback, useEffect, useMemo, useRef, useState } from "react"; import { Color, MoveClassification } from "@/types/enums"; import { Chess } from "chess.js"; import { getSquareRenderer } from "./squareRenderer"; @@ -64,11 +64,10 @@ export default function Board({ const boardHue = useAtomValue(boardHueAtom); const gameFen = game.fen(); - const [previousFen, setPreviousFen] = useState(gameFen); - if (gameFen !== previousFen) { - setPreviousFen(gameFen); + + useEffect(() => { setClickedSquares([]); - } + }, [gameFen, setClickedSquares]); const isPiecePlayable = useCallback( ({ piece }: { piece: string }): boolean => { diff --git a/src/lib/engine/uciEngine.ts b/src/lib/engine/uciEngine.ts index 37754f5..ef0a259 100644 --- a/src/lib/engine/uciEngine.ts +++ b/src/lib/engine/uciEngine.ts @@ -84,8 +84,6 @@ export class UciEngine { private async setMultiPv(multiPv: number) { if (multiPv === this.multiPv) return; - this.throwErrorIfNotReady(); - if (multiPv < 2 || multiPv > 6) { throw new Error(`Invalid MultiPV value : ${multiPv}`); } @@ -101,8 +99,6 @@ export class UciEngine { private async setElo(elo: number) { if (elo === this.elo) return; - this.throwErrorIfNotReady(); - if (elo < 1320 || elo > 3190) { throw new Error(`Invalid Elo value : ${elo}`); } @@ -142,12 +138,12 @@ export class UciEngine { private terminateWorker(worker: EngineWorker) { console.log(`Terminating worker from ${this.enginePath}`); - worker.uci("quit"); - worker.terminate?.(); worker.isReady = false; + worker.uci("quit"); + worker.terminate(); } - public async stopSearch(): Promise { + public async stopAllCurrentJobs(): Promise { this.workerQueue = []; await this.sendCommandsToEachWorker(["stop", "isready"], "readyok"); @@ -255,10 +251,10 @@ export class UciEngine { workersNb = 1, }: EvaluateGameParams): Promise { this.throwErrorIfNotReady(); - setEvaluationProgress?.(1); - await this.setMultiPv(multiPv); this.isReady = false; + setEvaluationProgress?.(1); + await this.setMultiPv(multiPv); await this.sendCommandsToEachWorker(["ucinewgame", "isready"], "readyok"); this.setWorkersNb(workersNb); @@ -308,7 +304,9 @@ export class UciEngine { updateEval(i, result); }) ); + await this.setWorkersNb(1); + this.isReady = true; const positionsWithClassification = getMovesClassification( positions, @@ -322,7 +320,6 @@ export class UciEngine { playersRatings?.black ); - this.isReady = true; return { positions: positionsWithClassification, estimatedElo, @@ -369,7 +366,7 @@ export class UciEngine { const lichessEvalPromise = getLichessEval(fen, multiPv); - await this.stopSearch(); + await this.stopAllCurrentJobs(); await this.setMultiPv(multiPv); const onNewMessage = (messages: string[]) => { @@ -404,6 +401,8 @@ export class UciEngine { depth = 16 ): Promise { this.throwErrorIfNotReady(); + + await this.stopAllCurrentJobs(); await this.setElo(elo); console.log(`Evaluating position: ${fen}`); diff --git a/src/sections/analysis/hooks/useCurrentPosition.ts b/src/sections/analysis/hooks/useCurrentPosition.ts index 3c18ba3..61bcc77 100644 --- a/src/sections/analysis/hooks/useCurrentPosition.ts +++ b/src/sections/analysis/hooks/useCurrentPosition.ts @@ -165,7 +165,7 @@ export const useCurrentPosition = (engine: UciEngine | null) => { return () => { if (engine?.getIsReady()) { - engine?.stopSearch(); + engine?.stopAllCurrentJobs(); } }; // eslint-disable-next-line react-hooks/exhaustive-deps diff --git a/src/sections/analysis/panelHeader/analyzeButton.tsx b/src/sections/analysis/panelHeader/analyzeButton.tsx index 7eeb627..eebc29d 100644 --- a/src/sections/analysis/panelHeader/analyzeButton.tsx +++ b/src/sections/analysis/panelHeader/analyzeButton.tsx @@ -101,6 +101,10 @@ export default function AnalyzeButton() { black.rating, ]); + useEffect(() => { + setEvaluationProgress(0); + }, [engine, setEvaluationProgress]); + // Automatically analyze when a new game is loaded and ready to analyze useEffect(() => { if (!gameEval && readyToAnalyse) { diff --git a/src/sections/play/board.tsx b/src/sections/play/board.tsx index d49c634..5f35da0 100644 --- a/src/sections/play/board.tsx +++ b/src/sections/play/board.tsx @@ -46,7 +46,7 @@ export default function BoardContainer() { playEngineMove(); return () => { - engine?.stopSearch(); + engine?.stopAllCurrentJobs(); }; }, [gameFen, isGameInProgress]); // eslint-disable-line react-hooks/exhaustive-deps