feat : add move classification icons
This commit is contained in:
@@ -1,7 +1,11 @@
|
||||
import { Box, Grid, Typography } from "@mui/material";
|
||||
import { useAtomValue } from "jotai";
|
||||
import { useEffect, useState } from "react";
|
||||
import { boardAtom, boardOrientationAtom, currentMoveAtom } from "../states";
|
||||
import {
|
||||
boardAtom,
|
||||
boardOrientationAtom,
|
||||
currentPositionAtom,
|
||||
} from "../states";
|
||||
import { getEvaluationBarValue } from "@/lib/chess";
|
||||
|
||||
interface Props {
|
||||
@@ -15,17 +19,17 @@ export default function EvaluationBar({ height }: Props) {
|
||||
});
|
||||
const board = useAtomValue(boardAtom);
|
||||
const boardOrientation = useAtomValue(boardOrientationAtom);
|
||||
const currentMove = useAtomValue(currentMoveAtom);
|
||||
const position = useAtomValue(currentPositionAtom);
|
||||
|
||||
const isWhiteToPlay = board.turn() === "w";
|
||||
|
||||
useEffect(() => {
|
||||
const bestLine = currentMove?.eval?.lines[0];
|
||||
const bestLine = position?.eval?.lines[0];
|
||||
if (!bestLine || bestLine.depth < 6) return;
|
||||
|
||||
const evalBar = getEvaluationBarValue(bestLine, isWhiteToPlay);
|
||||
setEvalBar(evalBar);
|
||||
}, [currentMove, isWhiteToPlay]);
|
||||
}, [position, isWhiteToPlay]);
|
||||
|
||||
return (
|
||||
<Grid
|
||||
|
||||
@@ -4,9 +4,8 @@ import { useAtomValue } from "jotai";
|
||||
import {
|
||||
boardAtom,
|
||||
boardOrientationAtom,
|
||||
currentMoveAtom,
|
||||
currentPositionAtom,
|
||||
showBestMoveArrowAtom,
|
||||
showPlayerMoveArrowAtom,
|
||||
} from "../states";
|
||||
import { Arrow, Square } from "react-chessboard/dist/chessboard/types";
|
||||
import { useChessActions } from "@/hooks/useChessActions";
|
||||
@@ -15,6 +14,10 @@ import PlayerInfo from "./playerInfo";
|
||||
import EvaluationBar from "./evaluationBar";
|
||||
import { useScreenSize } from "@/hooks/useScreenSize";
|
||||
import { MoveClassification } from "@/types/enums";
|
||||
import {
|
||||
moveClassificationColors,
|
||||
useSquareRenderer,
|
||||
} from "@/hooks/useSquareRenderer";
|
||||
|
||||
export default function Board() {
|
||||
const boardRef = useRef<HTMLDivElement>(null);
|
||||
@@ -22,9 +25,9 @@ export default function Board() {
|
||||
const board = useAtomValue(boardAtom);
|
||||
const boardOrientation = useAtomValue(boardOrientationAtom);
|
||||
const showBestMoveArrow = useAtomValue(showBestMoveArrowAtom);
|
||||
const showPlayerMoveArrow = useAtomValue(showPlayerMoveArrowAtom);
|
||||
const { makeMove: makeBoardMove } = useChessActions(boardAtom);
|
||||
const currentMove = useAtomValue(currentMoveAtom);
|
||||
const position = useAtomValue(currentPositionAtom);
|
||||
const squareRenderer = useSquareRenderer(position);
|
||||
|
||||
const onPieceDrop = (
|
||||
source: Square,
|
||||
@@ -45,9 +48,8 @@ export default function Board() {
|
||||
};
|
||||
|
||||
const customArrows: Arrow[] = useMemo(() => {
|
||||
const arrows: Arrow[] = [];
|
||||
const bestMove = currentMove?.lastEval?.bestMove;
|
||||
const moveClassification = currentMove?.eval?.moveClassification;
|
||||
const bestMove = position?.lastEval?.bestMove;
|
||||
const moveClassification = position?.eval?.moveClassification;
|
||||
|
||||
if (
|
||||
bestMove &&
|
||||
@@ -60,36 +62,11 @@ export default function Board() {
|
||||
moveClassificationColors[MoveClassification.Best],
|
||||
] as Arrow;
|
||||
|
||||
arrows.push(bestMoveArrow);
|
||||
return [bestMoveArrow];
|
||||
}
|
||||
|
||||
if (
|
||||
currentMove.from &&
|
||||
currentMove.to &&
|
||||
showPlayerMoveArrow &&
|
||||
moveClassification !== MoveClassification.Best
|
||||
) {
|
||||
const arrowColor = moveClassification
|
||||
? moveClassificationColors[moveClassification]
|
||||
: "#ffaa00";
|
||||
const playerMoveArrow: Arrow = [
|
||||
currentMove.from,
|
||||
currentMove.to,
|
||||
arrowColor,
|
||||
];
|
||||
|
||||
if (
|
||||
arrows.every(
|
||||
(arrow) =>
|
||||
arrow[0] !== playerMoveArrow[0] || arrow[1] !== playerMoveArrow[1]
|
||||
)
|
||||
) {
|
||||
arrows.push(playerMoveArrow);
|
||||
}
|
||||
}
|
||||
|
||||
return arrows;
|
||||
}, [currentMove, showBestMoveArrow, showPlayerMoveArrow]);
|
||||
return [];
|
||||
}, [position, showBestMoveArrow]);
|
||||
|
||||
return (
|
||||
<Grid
|
||||
@@ -131,6 +108,7 @@ export default function Board() {
|
||||
borderRadius: "5px",
|
||||
boxShadow: "0 2px 10px rgba(0, 0, 0, 0.5)",
|
||||
}}
|
||||
customSquare={squareRenderer}
|
||||
/>
|
||||
</Grid>
|
||||
|
||||
@@ -139,13 +117,3 @@ export default function Board() {
|
||||
</Grid>
|
||||
);
|
||||
}
|
||||
|
||||
const moveClassificationColors: Record<MoveClassification, string> = {
|
||||
[MoveClassification.Best]: "#26c2a3",
|
||||
[MoveClassification.Book]: "#d5a47d",
|
||||
[MoveClassification.Excellent]: "#3aab18",
|
||||
[MoveClassification.Good]: "#81b64c",
|
||||
[MoveClassification.Inaccuracy]: "#f7c631",
|
||||
[MoveClassification.Mistake]: "#ffa459",
|
||||
[MoveClassification.Blunder]: "#fa412d",
|
||||
};
|
||||
|
||||
@@ -3,7 +3,7 @@ import { Grid, List, Typography } from "@mui/material";
|
||||
import { useAtomValue } from "jotai";
|
||||
import { boardAtom, engineMultiPvAtom, gameAtom } from "../states";
|
||||
import LineEvaluation from "./lineEvaluation";
|
||||
import { useCurrentMove } from "@/hooks/useCurrentMove";
|
||||
import { useCurrentPosition } from "@/hooks/useCurrentPosition";
|
||||
import { LineEval } from "@/types/eval";
|
||||
import { EngineName } from "@/types/enums";
|
||||
import EngineSettingsButton from "@/sections/engineSettings/engineSettingsButton";
|
||||
@@ -13,7 +13,7 @@ import Opening from "./opening";
|
||||
|
||||
export default function ReviewPanelBody() {
|
||||
const linesNumber = useAtomValue(engineMultiPvAtom);
|
||||
const move = useCurrentMove(EngineName.Stockfish16);
|
||||
const position = useCurrentPosition(EngineName.Stockfish16);
|
||||
const game = useAtomValue(gameAtom);
|
||||
const board = useAtomValue(boardAtom);
|
||||
|
||||
@@ -30,8 +30,8 @@ export default function ReviewPanelBody() {
|
||||
(_, i) => ({ pv: [`${i}`], depth: 0, multiPv: i + 1 })
|
||||
);
|
||||
|
||||
const engineLines = move?.eval?.lines?.length
|
||||
? move.eval.lines
|
||||
const engineLines = position?.eval?.lines?.length
|
||||
? position.eval.lines
|
||||
: linesSkeleton;
|
||||
|
||||
return (
|
||||
|
||||
@@ -1,16 +1,15 @@
|
||||
import { useCurrentMove } from "@/hooks/useCurrentMove";
|
||||
import { Grid, Typography } from "@mui/material";
|
||||
import { useAtomValue } from "jotai";
|
||||
import { boardAtom } from "../states";
|
||||
import { boardAtom, currentPositionAtom } from "../states";
|
||||
import { useMemo } from "react";
|
||||
import { moveLineUciToSan } from "@/lib/chess";
|
||||
import { MoveClassification } from "@/types/enums";
|
||||
|
||||
export default function MoveInfo() {
|
||||
const move = useCurrentMove();
|
||||
const position = useAtomValue(currentPositionAtom);
|
||||
const board = useAtomValue(boardAtom);
|
||||
|
||||
const bestMove = move?.lastEval?.bestMove;
|
||||
const bestMove = position?.lastEval?.bestMove;
|
||||
|
||||
const bestMoveSan = useMemo(() => {
|
||||
if (!bestMove) return undefined;
|
||||
@@ -23,9 +22,9 @@ export default function MoveInfo() {
|
||||
|
||||
if (!bestMoveSan) return null;
|
||||
|
||||
const moveClassification = move.eval?.moveClassification;
|
||||
const moveClassification = position.eval?.moveClassification;
|
||||
const moveLabel = moveClassification
|
||||
? `${move.san} is ${moveClassificationLabels[moveClassification]}`
|
||||
? `${position.lastMove?.san} is ${moveClassificationLabels[moveClassification]}`
|
||||
: null;
|
||||
|
||||
const bestMoveLabel =
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { useCurrentMove } from "@/hooks/useCurrentMove";
|
||||
import { useCurrentPosition } from "@/hooks/useCurrentPosition";
|
||||
import { Grid, Typography } from "@mui/material";
|
||||
|
||||
export default function Opening() {
|
||||
const move = useCurrentMove();
|
||||
const position = useCurrentPosition();
|
||||
|
||||
const opening = move?.eval?.opening;
|
||||
const opening = position?.eval?.opening;
|
||||
if (!opening) return null;
|
||||
|
||||
return (
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
import { CurrentMove, GameEval } from "@/types/eval";
|
||||
import { CurrentPosition, GameEval } from "@/types/eval";
|
||||
import { Chess } from "chess.js";
|
||||
import { atom } from "jotai";
|
||||
|
||||
export const gameEvalAtom = atom<GameEval | undefined>(undefined);
|
||||
export const gameAtom = atom(new Chess());
|
||||
export const boardAtom = atom(new Chess());
|
||||
export const currentMoveAtom = atom<CurrentMove>({});
|
||||
export const currentPositionAtom = atom<CurrentPosition>({});
|
||||
|
||||
export const boardOrientationAtom = atom(true);
|
||||
export const showBestMoveArrowAtom = atom(true);
|
||||
export const showPlayerMoveArrowAtom = atom(true);
|
||||
export const showPlayerMoveIconAtom = atom(true);
|
||||
|
||||
export const engineDepthAtom = atom(16);
|
||||
export const engineMultiPvAtom = atom(3);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Checkbox, FormControlLabel, Grid } from "@mui/material";
|
||||
import {
|
||||
showBestMoveArrowAtom,
|
||||
showPlayerMoveArrowAtom,
|
||||
showPlayerMoveIconAtom,
|
||||
} from "../analysis/states";
|
||||
import { useAtomLocalStorage } from "@/hooks/useAtomLocalStorage";
|
||||
|
||||
@@ -10,9 +10,9 @@ export default function ArrowOptions() {
|
||||
"show-arrow-best-move",
|
||||
showBestMoveArrowAtom
|
||||
);
|
||||
const [showPlayerMove, setShowPlayerMove] = useAtomLocalStorage(
|
||||
"show-arrow-player-move",
|
||||
showPlayerMoveArrowAtom
|
||||
const [showPlayerMoveIcon, setShowPlayerMoveIcon] = useAtomLocalStorage(
|
||||
"show-icon-player-move",
|
||||
showPlayerMoveIconAtom
|
||||
);
|
||||
|
||||
return (
|
||||
@@ -37,11 +37,11 @@ export default function ArrowOptions() {
|
||||
<FormControlLabel
|
||||
control={
|
||||
<Checkbox
|
||||
checked={showPlayerMove}
|
||||
onChange={(_, checked) => setShowPlayerMove(checked)}
|
||||
checked={showPlayerMoveIcon}
|
||||
onChange={(_, checked) => setShowPlayerMoveIcon(checked)}
|
||||
/>
|
||||
}
|
||||
label="Show played move arrow"
|
||||
label="Show played move icon"
|
||||
sx={{ marginX: 0 }}
|
||||
/>
|
||||
</Grid>
|
||||
|
||||
Reference in New Issue
Block a user