feat : add click on engine lines
This commit is contained in:
Binary file not shown.
@@ -1,15 +1,23 @@
|
||||
import { LineEval } from "@/types/eval";
|
||||
import { ListItem, Skeleton, Typography } from "@mui/material";
|
||||
import { Box, ListItem, Skeleton, Typography, useTheme } from "@mui/material";
|
||||
import { useAtomValue } from "jotai";
|
||||
import { boardAtom } from "../../states";
|
||||
import { getLineEvalLabel, moveLineUciToSan } from "@/lib/chess";
|
||||
import localFont from "next/font/local";
|
||||
import { useChessActions } from "@/hooks/useChessActions";
|
||||
|
||||
const myFont = localFont({
|
||||
src: "./chess_merida_unicode.ttf",
|
||||
});
|
||||
|
||||
interface Props {
|
||||
line: LineEval;
|
||||
}
|
||||
|
||||
export default function LineEvaluation({ line }: Props) {
|
||||
const theme = useTheme();
|
||||
const board = useAtomValue(boardAtom);
|
||||
const { addMoves } = useChessActions(boardAtom);
|
||||
const lineLabel = getLineEvalLabel(line);
|
||||
|
||||
const isBlackCp =
|
||||
@@ -18,6 +26,26 @@ export default function LineEvaluation({ line }: Props) {
|
||||
|
||||
const showSkeleton = line.depth < 6;
|
||||
|
||||
const uciToSan = moveLineUciToSan(board.fen());
|
||||
const initialTurn = board.turn();
|
||||
const isDarkMode = theme.palette.mode === "dark";
|
||||
|
||||
const formatSan = (
|
||||
san: string,
|
||||
moveIdx: number
|
||||
): { icon?: string; text: string } => {
|
||||
const firstChar = san.charAt(0);
|
||||
|
||||
const isPiece = ["K", "Q", "R", "B", "N"].includes(firstChar);
|
||||
if (!isPiece) return { text: san };
|
||||
|
||||
const turn = isDarkMode ? initialTurn : initialTurn === "w" ? "b" : "w";
|
||||
const moveColor = moveIdx % 2 === 0 ? turn : turn === "w" ? "b" : "w";
|
||||
const icon = unicodeMap[firstChar][moveColor];
|
||||
|
||||
return { icon, text: san.slice(1) };
|
||||
};
|
||||
|
||||
return (
|
||||
<ListItem disablePadding>
|
||||
<Typography
|
||||
@@ -58,9 +86,52 @@ export default function LineEvaluation({ line }: Props) {
|
||||
{showSkeleton ? (
|
||||
<Skeleton variant="rounded" animation="wave" width="15em" />
|
||||
) : (
|
||||
line.pv.map(moveLineUciToSan(board.fen())).join(", ")
|
||||
line.pv.map((uci, i) => {
|
||||
const san = uciToSan(uci);
|
||||
const { icon, text } = formatSan(san, i);
|
||||
|
||||
return (
|
||||
<Box
|
||||
component="span"
|
||||
key={i}
|
||||
onClick={() => {
|
||||
addMoves(line.pv.slice(0, i + 1));
|
||||
}}
|
||||
sx={{
|
||||
cursor: "pointer",
|
||||
ml: i ? 0.5 : 0,
|
||||
transition: "opacity 0.2s ease-in-out",
|
||||
"&:hover": {
|
||||
opacity: 0.5,
|
||||
},
|
||||
}}
|
||||
>
|
||||
{icon && (
|
||||
<Typography
|
||||
component="span"
|
||||
fontFamily={myFont.style.fontFamily}
|
||||
>
|
||||
{icon}
|
||||
</Typography>
|
||||
)}
|
||||
|
||||
<Typography component="span">
|
||||
{text}
|
||||
{i < line.pv.length - 1 && ","}
|
||||
</Typography>
|
||||
</Box>
|
||||
);
|
||||
})
|
||||
)}
|
||||
</Typography>
|
||||
</ListItem>
|
||||
);
|
||||
}
|
||||
|
||||
const unicodeMap: Record<string, Record<"w" | "b", string>> = {
|
||||
K: { w: "♚", b: "♔" },
|
||||
Q: { w: "♛", b: "♕" },
|
||||
R: { w: "♜", b: "♖" },
|
||||
B: { w: "♝", b: "♗" },
|
||||
N: { w: "♞", b: "♘" },
|
||||
};
|
||||
|
||||
@@ -6,7 +6,7 @@ import { useMemo } from "react";
|
||||
import Image from "next/image";
|
||||
import { capitalize } from "@/lib/helpers";
|
||||
import { useChessActions } from "@/hooks/useChessActions";
|
||||
import { moveClassificationColors } from "@/lib/chess";
|
||||
import { CLASSIFICATION_COLORS } from "@/constants";
|
||||
|
||||
interface Props {
|
||||
classification: MoveClassification;
|
||||
@@ -74,7 +74,7 @@ export default function ClassificationRow({ classification }: Props) {
|
||||
justifyContent="space-evenly"
|
||||
alignItems="center"
|
||||
wrap="nowrap"
|
||||
color={moveClassificationColors[classification]}
|
||||
color={CLASSIFICATION_COLORS[classification]}
|
||||
size={12}
|
||||
>
|
||||
<Grid
|
||||
|
||||
@@ -6,7 +6,7 @@ import { boardAtom, currentPositionAtom, gameAtom } from "../../../states";
|
||||
import { useChessActions } from "@/hooks/useChessActions";
|
||||
import { useEffect } from "react";
|
||||
import { isInViewport } from "@/lib/helpers";
|
||||
import { moveClassificationColors } from "@/lib/chess";
|
||||
import { CLASSIFICATION_COLORS } from "@/constants";
|
||||
|
||||
interface Props {
|
||||
san: string;
|
||||
@@ -89,7 +89,7 @@ const getMoveColor = (moveClassification?: MoveClassification) => {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return moveClassificationColors[moveClassification];
|
||||
return CLASSIFICATION_COLORS[moveClassification];
|
||||
};
|
||||
|
||||
const moveClassificationsToIgnore: MoveClassification[] = [
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { DotProps } from "recharts";
|
||||
import { ChartItemData } from "./types";
|
||||
import { moveClassificationColors } from "@/lib/chess";
|
||||
import { CLASSIFICATION_COLORS } from "@/constants";
|
||||
|
||||
export default function CustomDot({
|
||||
cx,
|
||||
@@ -9,7 +9,7 @@ export default function CustomDot({
|
||||
payload,
|
||||
}: DotProps & { payload?: ChartItemData }) {
|
||||
const moveColor = payload?.moveClassification
|
||||
? moveClassificationColors[payload.moveClassification]
|
||||
? CLASSIFICATION_COLORS[payload.moveClassification]
|
||||
: "grey";
|
||||
|
||||
return (
|
||||
|
||||
@@ -21,7 +21,7 @@ import type { ReactElement } from "react";
|
||||
import CustomTooltip from "./tooltip";
|
||||
import { ChartItemData } from "./types";
|
||||
import { PositionEval } from "@/types/eval";
|
||||
import { moveClassificationColors } from "@/lib/chess";
|
||||
import { CLASSIFICATION_COLORS } from "@/constants";
|
||||
import CustomDot from "./dot";
|
||||
import { MoveClassification } from "@/types/enums";
|
||||
import { useChessActions } from "@/hooks/useChessActions";
|
||||
@@ -51,7 +51,7 @@ export default function GraphTab(props: GridProps) {
|
||||
}, [chartData]);
|
||||
|
||||
const boardMoveColor = currentPosition.eval?.moveClassification
|
||||
? moveClassificationColors[currentPosition.eval.moveClassification]
|
||||
? CLASSIFICATION_COLORS[currentPosition.eval.moveClassification]
|
||||
: "grey";
|
||||
|
||||
// Render a dot only on selected classifications (always returns an element)
|
||||
|
||||
@@ -6,7 +6,7 @@ import { useChessActions } from "@/hooks/useChessActions";
|
||||
import { useCallback, useEffect } from "react";
|
||||
|
||||
export default function NextMoveButton() {
|
||||
const { makeMove: makeBoardMove } = useChessActions(boardAtom);
|
||||
const { playMove: playBoardMove } = useChessActions(boardAtom);
|
||||
const game = useAtomValue(gameAtom);
|
||||
const board = useAtomValue(boardAtom);
|
||||
|
||||
@@ -27,14 +27,14 @@ export default function NextMoveButton() {
|
||||
.find((c) => c.fen === nextMove.after)?.comment;
|
||||
|
||||
if (nextMove) {
|
||||
makeBoardMove({
|
||||
playBoardMove({
|
||||
from: nextMove.from,
|
||||
to: nextMove.to,
|
||||
promotion: nextMove.promotion,
|
||||
comment,
|
||||
});
|
||||
}
|
||||
}, [isButtonEnabled, boardHistory, game, makeBoardMove]);
|
||||
}, [isButtonEnabled, boardHistory, game, playBoardMove]);
|
||||
|
||||
useEffect(() => {
|
||||
const onKeyDown = (e: KeyboardEvent) => {
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { DEFAULT_ENGINE } from "@/constants";
|
||||
import { EngineName } from "@/types/enums";
|
||||
import { CurrentPosition, GameEval, SavedEvals } from "@/types/eval";
|
||||
import { Chess } from "chess.js";
|
||||
@@ -12,7 +13,7 @@ export const boardOrientationAtom = atom(true);
|
||||
export const showBestMoveArrowAtom = atom(true);
|
||||
export const showPlayerMoveIconAtom = atom(true);
|
||||
|
||||
export const engineNameAtom = atom<EngineName>(EngineName.Stockfish17Lite);
|
||||
export const engineNameAtom = atom<EngineName>(DEFAULT_ENGINE);
|
||||
export const engineDepthAtom = atom(14);
|
||||
export const engineMultiPvAtom = atom(3);
|
||||
export const evaluationProgressAtom = atom(0);
|
||||
|
||||
Reference in New Issue
Block a user