import { Grid2 as Grid, Skeleton, Stack, Typography } from "@mui/material"; import { useAtomValue } from "jotai"; import { boardAtom, currentPositionAtom } from "../../states"; import { useMemo } from "react"; import { moveLineUciToSan } from "@/lib/chess"; import { MoveClassification } from "@/types/enums"; import Image from "next/image"; export default function MoveInfo() { const position = useAtomValue(currentPositionAtom); const board = useAtomValue(boardAtom); const bestMove = position?.lastEval?.bestMove; const bestMoveSan = useMemo(() => { if (!bestMove) return undefined; const lastPosition = board.history({ verbose: true }).at(-1)?.before; if (!lastPosition) return undefined; return moveLineUciToSan(lastPosition)(bestMove); }, [bestMove, board]); if (board.history().length === 0) return null; if (!bestMoveSan) { return ( placeholder ); } const moveClassification = position.eval?.moveClassification; const moveLabel = moveClassification ? `${position.lastMove?.san} is ${moveClassificationLabels[moveClassification]}` : null; const bestMoveLabel = moveClassification === MoveClassification.Best || moveClassification === MoveClassification.Opening || moveClassification === MoveClassification.Forced || moveClassification === MoveClassification.Brilliant || moveClassification === MoveClassification.Perfect ? null : `${bestMoveSan} was the best move`; return ( {moveLabel && ( {moveClassification && ( move-icon )} {moveLabel} )} {bestMoveLabel && ( move-icon {bestMoveLabel} )} ); } const moveClassificationLabels: Record = { [MoveClassification.Opening]: "an opening move", [MoveClassification.Forced]: "forced", [MoveClassification.Brilliant]: "brilliant !!", [MoveClassification.Perfect]: "the only good move !", [MoveClassification.Best]: "the best move", [MoveClassification.Excellent]: "excellent", [MoveClassification.Okay]: "an okay move", [MoveClassification.Inaccuracy]: "an inaccuracy", [MoveClassification.Mistake]: "a mistake", [MoveClassification.Blunder]: "a blunder", };