import { Icon } from "@iconify/react"; import { engineDepthAtom, engineMultiPvAtom, engineNameAtom, engineWorkersNbAtom, evaluationProgressAtom, gameAtom, gameEvalAtom, savedEvalsAtom, } from "../states"; import { useAtom, useAtomValue, useSetAtom } from "jotai"; import { getEvaluateGameParams } from "@/lib/chess"; import { useGameDatabase } from "@/hooks/useGameDatabase"; import { LoadingButton } from "@mui/lab"; import { useEngine } from "@/hooks/useEngine"; import { logAnalyticsEvent } from "@/lib/firebase"; import { SavedEvals } from "@/types/eval"; import { useEffect, useCallback } from "react"; import { usePlayersData } from "@/hooks/usePlayersData"; import { Typography } from "@mui/material"; import { useCurrentPosition } from "../hooks/useCurrentPosition"; export default function AnalyzeButton() { const engineName = useAtomValue(engineNameAtom); const engine = useEngine(engineName); useCurrentPosition(engine); const engineWorkersNb = useAtomValue(engineWorkersNbAtom); const [evaluationProgress, setEvaluationProgress] = useAtom( evaluationProgressAtom ); const engineDepth = useAtomValue(engineDepthAtom); const engineMultiPv = useAtomValue(engineMultiPvAtom); const { setGameEval, gameFromUrl } = useGameDatabase(); const [gameEval, setEval] = useAtom(gameEvalAtom); const game = useAtomValue(gameAtom); const setSavedEvals = useSetAtom(savedEvalsAtom); const { white, black } = usePlayersData(gameAtom); const readyToAnalyse = engine?.getIsReady() && game.history().length > 0 && !evaluationProgress; const handleAnalyze = useCallback(async () => { const params = getEvaluateGameParams(game); if ( !engine?.getIsReady() || params.fens.length === 0 || evaluationProgress ) { return; } const newGameEval = await engine.evaluateGame({ ...params, depth: engineDepth, multiPv: engineMultiPv, setEvaluationProgress, playersRatings: { white: white?.rating, black: black?.rating, }, workersNb: engineWorkersNb, }); setEval(newGameEval); setEvaluationProgress(0); if (gameFromUrl) { setGameEval(gameFromUrl.id, newGameEval); } const gameSavedEvals: SavedEvals = params.fens.reduce((acc, fen, idx) => { acc[fen] = { ...newGameEval.positions[idx], engine: engineName }; return acc; }, {} as SavedEvals); setSavedEvals((prev) => ({ ...prev, ...gameSavedEvals, })); logAnalyticsEvent("analyze_game", { engine: engineName, depth: engineDepth, multiPv: engineMultiPv, nbPositions: params.fens.length, }); }, [ engine, engineName, engineWorkersNb, game, engineDepth, engineMultiPv, evaluationProgress, setEvaluationProgress, setEval, gameFromUrl, setGameEval, setSavedEvals, white.rating, black.rating, ]); useEffect(() => { setEvaluationProgress(0); }, [engine, setEvaluationProgress]); // Automatically analyze when a new game is loaded and ready to analyze useEffect(() => { if (!gameEval && readyToAnalyse) { handleAnalyze(); } }, [gameEval, readyToAnalyse, handleAnalyze]); if (evaluationProgress) return null; return ( } onClick={handleAnalyze} disabled={!readyToAnalyse} > {gameEval ? "Analyze again" : "Analyze"} ); }