From daaf145fa991c539f8eaf9abea213f6ab5a30537 Mon Sep 17 00:00:00 2001 From: GuillaumeSD Date: Fri, 12 Apr 2024 02:49:48 +0200 Subject: [PATCH] Squashed commit of the following: commit c769a4d3bfbd22804ea4eeb324e7afeaaaa55f82 Author: GuillaumeSD Date: Fri Apr 12 02:49:21 2024 +0200 style : capturedPieces UI final touches commit 838ad95bfa1746a3a8de38ace2520fe93ec6a0af Author: GuillaumeSD Date: Thu Apr 11 03:00:01 2024 +0200 feat : captured pieces wip commit e4bb4dcc346aa5dea5527fef4389b01673645e76 Merge: 785dba2 e9e772c Author: GuillaumeSD Date: Thu Apr 11 01:15:31 2024 +0200 Merge branch 'main' into feat/add-board-captured-pieces commit 785dba28509ac04655d4cab736a18a821ca52433 Author: GuillaumeSD Date: Tue Apr 9 02:25:29 2024 +0200 feat : add board captured pieces init --- public/captured-pieces.png | Bin 0 -> 19937 bytes src/components/board/capturedPieces.tsx | 167 ++++++++++++++++++++++++ src/components/board/index.tsx | 14 +- src/hooks/usePlayerNames.ts | 4 +- src/lib/chess.ts | 28 ++++ src/sections/analysis/board/index.tsx | 4 +- 6 files changed, 211 insertions(+), 6 deletions(-) create mode 100644 public/captured-pieces.png create mode 100644 src/components/board/capturedPieces.tsx diff --git a/public/captured-pieces.png b/public/captured-pieces.png new file mode 100644 index 0000000000000000000000000000000000000000..9caaad9e36f43a1dbb9a8f0c159e3471fd4e6b60 GIT binary patch literal 19937 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 XB>MR)(_Wq@J|kGs?JP=YZqdI3eivGN literal 0 HcmV?d00001 diff --git a/src/components/board/capturedPieces.tsx b/src/components/board/capturedPieces.tsx new file mode 100644 index 0000000..137b510 --- /dev/null +++ b/src/components/board/capturedPieces.tsx @@ -0,0 +1,167 @@ +import { getCapturedPieces, getMaterialDifference } from "@/lib/chess"; +import { Color } from "@/types/enums"; +import { Grid, Typography } from "@mui/material"; +import { Chess } from "chess.js"; +import { PrimitiveAtom, useAtomValue } from "jotai"; +import { CSSProperties, useMemo } from "react"; + +export interface Props { + gameAtom: PrimitiveAtom; + color: Color; +} + +const PIECE_SCALE = 0.6; + +export default function CapturedPieces({ gameAtom, color }: Props) { + const game = useAtomValue(gameAtom); + const cssProps = useMemo(() => { + const capturedPieces = getCapturedPieces(game.fen(), color); + console.log(capturedPieces, color); + return getCapturedPiecesCSSProps(capturedPieces, color); + }, [game, color]); + + const materialDiff = useMemo(() => { + const materialDiff = getMaterialDifference(game.fen()); + return color === Color.White ? materialDiff : -materialDiff; + }, [game, color]); + + return ( + + {cssProps.map((cssProp, i) => ( + + ))} + + {materialDiff > 0 && ( + + +{materialDiff} + + )} + + ); +} + +const getCapturedPiecesCSSProps = ( + capturedPieces: Record, + color: Color +): CSSProperties[] => { + const cssProps: CSSProperties[] = []; + + if (color === Color.Black) { + if (capturedPieces.P) { + cssProps.push({ + backgroundPositionX: `-${18 * PIECE_SCALE}rem`, + backgroundPositionY: `${ + -20.1 * PIECE_SCALE + capturedPieces.P * 2.5 * PIECE_SCALE + }rem`, + width: `${0.6 * PIECE_SCALE + capturedPieces.P * 0.7 * PIECE_SCALE}rem`, + height: `${1.7 * PIECE_SCALE}rem`, + }); + } + + if (capturedPieces.B) { + cssProps.push({ + backgroundPosition: `-${24.7 * PIECE_SCALE}rem ${ + -5.1 * PIECE_SCALE + capturedPieces.B * 2.6 * PIECE_SCALE + }rem`, + width: `${0.7 * PIECE_SCALE + capturedPieces.B * 0.8 * PIECE_SCALE}rem`, + height: `${ + 1.7 * PIECE_SCALE + capturedPieces.B * 0.1 * PIECE_SCALE + }rem`, + }); + } + + if (capturedPieces.N) { + cssProps.push({ + backgroundPosition: `-${27.5 * PIECE_SCALE}rem ${ + -4.9 * PIECE_SCALE + capturedPieces.N * 2.5 * PIECE_SCALE + }rem`, + width: `${0.9 * PIECE_SCALE + capturedPieces.N * 0.7 * PIECE_SCALE}rem`, + height: `${1.9 * PIECE_SCALE}rem`, + }); + } + + if (capturedPieces.R) { + cssProps.push({ + backgroundPosition: `${ + -30.2 * PIECE_SCALE + capturedPieces.R * 0.1 * PIECE_SCALE + }rem ${-5.1 * PIECE_SCALE + capturedPieces.R * 2.5 * PIECE_SCALE}rem`, + width: `${0.7 * PIECE_SCALE + capturedPieces.R * 0.8 * PIECE_SCALE}rem`, + height: `${1.7 * PIECE_SCALE}rem`, + }); + } + + if (capturedPieces.Q) { + cssProps.push({ + backgroundPosition: `-${32.5 * PIECE_SCALE}rem ${0.1 * PIECE_SCALE}rem`, + width: `${1.8 * PIECE_SCALE}rem`, + height: `${1.9 * PIECE_SCALE}rem`, + }); + } + } else { + if (capturedPieces.p) { + cssProps.push({ + backgroundPositionX: 0, + backgroundPositionY: `${ + -20.1 * PIECE_SCALE + capturedPieces.p * 2.5 * PIECE_SCALE + }rem`, + width: `${0.6 * PIECE_SCALE + capturedPieces.p * 0.7 * PIECE_SCALE}rem`, + height: `${1.7 * PIECE_SCALE}rem`, + }); + } + + if (capturedPieces.b) { + cssProps.push({ + backgroundPosition: `-${6.7 * PIECE_SCALE}rem ${ + -5.1 * PIECE_SCALE + capturedPieces.b * 2.6 * PIECE_SCALE + }rem`, + width: `${0.7 * PIECE_SCALE + capturedPieces.b * 0.8 * PIECE_SCALE}rem`, + height: `${ + 1.7 * PIECE_SCALE + capturedPieces.b * 0.1 * PIECE_SCALE + }rem`, + }); + } + + if (capturedPieces.n) { + cssProps.push({ + backgroundPosition: `-${9.5 * PIECE_SCALE}rem ${ + -4.9 * PIECE_SCALE + capturedPieces.n * 2.5 * PIECE_SCALE + }rem`, + width: `${0.9 * PIECE_SCALE + capturedPieces.n * 0.7 * PIECE_SCALE}rem`, + height: `${1.9 * PIECE_SCALE}rem`, + }); + } + + if (capturedPieces.r) { + cssProps.push({ + backgroundPosition: `${ + -12.2 * PIECE_SCALE + capturedPieces.r * 0.1 * PIECE_SCALE + }rem ${-5.1 * PIECE_SCALE + capturedPieces.r * 2.5 * PIECE_SCALE}rem`, + width: `${0.7 * PIECE_SCALE + capturedPieces.r * 0.8 * PIECE_SCALE}rem`, + height: `${1.7 * PIECE_SCALE}rem`, + }); + } + + if (capturedPieces.q) { + cssProps.push({ + backgroundPosition: `-${14.5 * PIECE_SCALE}rem ${0.1 * PIECE_SCALE}rem`, + width: `${1.8 * PIECE_SCALE}rem`, + height: `${1.9 * PIECE_SCALE}rem`, + }); + } + } + + return cssProps; +}; diff --git a/src/components/board/index.tsx b/src/components/board/index.tsx index 32b4ccb..85514fc 100644 --- a/src/components/board/index.tsx +++ b/src/components/board/index.tsx @@ -14,6 +14,7 @@ import { Chess } from "chess.js"; import { getSquareRenderer, moveClassificationColors } from "./squareRenderer"; import { CurrentPosition } from "@/types/eval"; import EvaluationBar from "./evaluationBar"; +import CapturedPieces from "./capturedPieces"; export interface Props { id: string; @@ -230,10 +231,16 @@ export default function Board({ xs={12} justifyContent="center" alignItems="center" + columnGap={2} > - + {boardOrientation === Color.White ? blackPlayer : whitePlayer} + + - + {boardOrientation === Color.White ? whitePlayer : blackPlayer} + + diff --git a/src/hooks/usePlayerNames.ts b/src/hooks/usePlayerNames.ts index 4dd40ae..31cb6ad 100644 --- a/src/hooks/usePlayerNames.ts +++ b/src/hooks/usePlayerNames.ts @@ -12,10 +12,10 @@ export const usePlayersNames = (gameAtom: PrimitiveAtom) => { gameFromUrl?.black?.name || game.header()["Black"] || "Black"; const whiteElo = - gameFromUrl?.white?.rating || game.header()["WhiteElo"] || "?"; + gameFromUrl?.white?.rating || game.header()["WhiteElo"] || undefined; const blackElo = - gameFromUrl?.black?.rating || game.header()["BlackElo"] || "?"; + gameFromUrl?.black?.rating || game.header()["BlackElo"] || undefined; return { whiteName, diff --git a/src/lib/chess.ts b/src/lib/chess.ts index 8392e4a..10835de 100644 --- a/src/lib/chess.ts +++ b/src/lib/chess.ts @@ -267,3 +267,31 @@ export const isCheck = (fen: string): boolean => { const game = new Chess(fen); return game.inCheck(); }; + +export const getCapturedPieces = ( + fen: string, + color: Color +): Record => { + const capturedPieces: Record = {}; + if (color === Color.White) { + capturedPieces.p = 8; + capturedPieces.r = 2; + capturedPieces.n = 2; + capturedPieces.b = 2; + capturedPieces.q = 1; + } else { + capturedPieces.P = 8; + capturedPieces.R = 2; + capturedPieces.N = 2; + capturedPieces.B = 2; + capturedPieces.Q = 1; + } + + const fenPiecePlacement = fen.split(" ")[0]; + for (const piece of Object.keys(capturedPieces)) { + const count = fenPiecePlacement.match(new RegExp(piece, "g"))?.length; + if (count) capturedPieces[piece] = (capturedPieces[piece] ?? 0) - count; + } + + return capturedPieces; +}; diff --git a/src/sections/analysis/board/index.tsx b/src/sections/analysis/board/index.tsx index bfb313d..e943b7e 100644 --- a/src/sections/analysis/board/index.tsx +++ b/src/sections/analysis/board/index.tsx @@ -38,8 +38,8 @@ export default function BoardContainer() { boardSize={boardSize} canPlay={true} gameAtom={boardAtom} - whitePlayer={`${whiteName} (${whiteElo})`} - blackPlayer={`${blackName} (${blackElo})`} + whitePlayer={whiteElo ? `${whiteName} (${whiteElo})` : whiteName} + blackPlayer={blackElo ? `${blackName} (${blackElo})` : blackName} boardOrientation={boardOrientation ? Color.White : Color.Black} currentPositionAtom={currentPositionAtom} showBestMoveArrow={showBestMoveArrow}