diff --git a/src/components/slider.tsx b/src/components/slider.tsx index 117a227..a32188d 100644 --- a/src/components/slider.tsx +++ b/src/components/slider.tsx @@ -7,6 +7,7 @@ export interface Props { max: number; label: string; size?: number; + marksFilter?: number; step?: number; } @@ -17,6 +18,7 @@ export default function Slider({ value, setValue, size, + marksFilter, step = 1, }: Props) { return ( @@ -27,14 +29,22 @@ export default function Slider({ size={size ?? 11} > - {`${label}: ${value}`} + {step === 1 && marksFilter ? label : `${label}: ${value}`} ({ + value: i + min, + label: `${i + min}`, + })).filter((_, i) => i % marksFilter === 0) + : undefined + } step={step} - valueLabelDisplay="auto" + valueLabelDisplay="off" value={value} onChange={(_, value) => setValue(value as number)} aria-labelledby={`input-${label}`} diff --git a/src/hooks/useChessActions.ts b/src/hooks/useChessActions.ts index 6c0156c..6c8cf0f 100644 --- a/src/hooks/useChessActions.ts +++ b/src/hooks/useChessActions.ts @@ -4,14 +4,15 @@ import { playIllegalMoveSound, playSoundFromMove, } from "@/lib/sounds"; +import { Player } from "@/types/game"; import { Chess, Move } from "chess.js"; import { PrimitiveAtom, useAtom } from "jotai"; import { useCallback } from "react"; export interface resetGameParams { fen?: string; - whiteName?: string; - blackName?: string; + white?: Player; + black?: Player; noHeaders?: boolean; } diff --git a/src/hooks/usePlayerNames.ts b/src/hooks/usePlayersData.ts similarity index 100% rename from src/hooks/usePlayerNames.ts rename to src/hooks/usePlayersData.ts diff --git a/src/lib/chess.ts b/src/lib/chess.ts index 753299a..e8eb446 100644 --- a/src/lib/chess.ts +++ b/src/lib/chess.ts @@ -1,5 +1,5 @@ import { EvaluateGameParams, LineEval, PositionEval } from "@/types/eval"; -import { Game } from "@/types/game"; +import { Game, Player } from "@/types/game"; import { Chess, PieceSymbol, Square } from "chess.js"; import { getPositionWinPercentage } from "./engine/helpers/winPercentage"; import { Color, MoveClassification } from "@/types/enums"; @@ -54,19 +54,22 @@ export const getGameToSave = (game: Chess, board: Chess): Chess => { export const setGameHeaders = ( game: Chess, - params: { whiteName?: string; blackName?: string; resigned?: Color } = {} + params: { white?: Player; black?: Player; resigned?: Color } = {} ): Chess => { game.setHeader("Event", "Chesskit Game"); - game.setHeader("Site", "Chesskit"); + game.setHeader("Site", "Chesskit.org"); game.setHeader( "Date", new Date().toISOString().split("T")[0].replaceAll("-", ".") ); - const { whiteName, blackName, resigned } = params; + const { white, black, resigned } = params; - if (whiteName) game.setHeader("White", whiteName); - if (blackName) game.setHeader("Black", blackName); + if (white?.name) game.setHeader("White", white.name); + if (black?.name) game.setHeader("Black", black.name); + + if (white?.rating) game.setHeader("WhiteElo", `${white.rating}`); + if (black?.rating) game.setHeader("BlackElo", `${black.rating}`); const whiteNameToUse = game.getHeaders().White || "White"; const blackNameToUse = game.getHeaders().Black || "Black"; diff --git a/src/lib/engine/uciEngine.ts b/src/lib/engine/uciEngine.ts index 27bdd60..8469705 100644 --- a/src/lib/engine/uciEngine.ts +++ b/src/lib/engine/uciEngine.ts @@ -21,7 +21,7 @@ export class UciEngine { private isReady = false; private engineName: EngineName; private multiPv = 3; - private skillLevel: number | undefined = undefined; + private elo: number | undefined = undefined; private constructor(engineName: EngineName, workers: EngineWorker[]) { this.engineName = engineName; @@ -92,37 +92,28 @@ export class UciEngine { this.multiPv = multiPv; } - private async setLimitStrength(on: boolean) { - await this.broadcastCommands( - [`setoption name UCI_LimitStrength value ${on}`, "isready"], - "readyok" - ); - } - - private async setElo(elo: number) { - await this.broadcastCommands( - [`setoption name UCI_Elo value ${elo}`, "isready"], - "readyok" - ); - } - - private async setSkillLevel(skillLevel: number, initCase = false) { + private async setElo(elo: number, initCase = false) { if (!initCase) { - if (skillLevel === this.skillLevel) return; + if (elo === this.elo) return; this.throwErrorIfNotReady(); } - if (skillLevel < 0 || skillLevel > 20) { - throw new Error(`Invalid SkillLevel value : ${skillLevel}`); + if (elo < 1320 || elo > 3190) { + throw new Error(`Invalid Elo value : ${elo}`); } await this.broadcastCommands( - [`setoption name Skill Level value ${skillLevel}`, "isready"], + ["setoption name UCI_LimitStrength value true", "isready"], "readyok" ); - this.skillLevel = skillLevel; + await this.broadcastCommands( + [`setoption name UCI_Elo value ${elo}`, "isready"], + "readyok" + ); + + this.elo = elo; } private throwErrorIfNotReady() { @@ -370,7 +361,6 @@ export class UciEngine { depth = 16 ): Promise { this.throwErrorIfNotReady(); - await this.setLimitStrength(true); await this.setElo(elo); console.log(`Evaluating position: ${fen}`); diff --git a/src/sections/analysis/board/index.tsx b/src/sections/analysis/board/index.tsx index 6bb99c0..edaf427 100644 --- a/src/sections/analysis/board/index.tsx +++ b/src/sections/analysis/board/index.tsx @@ -11,7 +11,7 @@ import { useMemo } from "react"; import { useScreenSize } from "@/hooks/useScreenSize"; import { Color } from "@/types/enums"; import Board from "@/components/board"; -import { usePlayersData } from "@/hooks/usePlayerNames"; +import { usePlayersData } from "@/hooks/usePlayersData"; export default function BoardContainer() { const screenSize = useScreenSize(); diff --git a/src/sections/analysis/panelBody/classificationTab/movesClassificationsRecap/index.tsx b/src/sections/analysis/panelBody/classificationTab/movesClassificationsRecap/index.tsx index 58106da..730086d 100644 --- a/src/sections/analysis/panelBody/classificationTab/movesClassificationsRecap/index.tsx +++ b/src/sections/analysis/panelBody/classificationTab/movesClassificationsRecap/index.tsx @@ -1,4 +1,4 @@ -import { usePlayersData } from "@/hooks/usePlayerNames"; +import { usePlayersData } from "@/hooks/usePlayersData"; import { Grid2 as Grid, Typography } from "@mui/material"; import { gameAtom, gameEvalAtom } from "../../../states"; import { MoveClassification } from "@/types/enums"; diff --git a/src/sections/analysis/panelHeader/loadGame.tsx b/src/sections/analysis/panelHeader/loadGame.tsx index fc3d4ff..d3a737b 100644 --- a/src/sections/analysis/panelHeader/loadGame.tsx +++ b/src/sections/analysis/panelHeader/loadGame.tsx @@ -43,7 +43,11 @@ export default function LoadGame() { resetAndSetGamePgn(gameFromUrl.pgn); setEval(gameFromUrl.eval); - setBoardOrientation(true); + setBoardOrientation( + gameFromUrl.black.name === "You" && gameFromUrl.site === "Chesskit.org" + ? false + : true + ); }; loadGame(); diff --git a/src/sections/engineSettings/engineSettingsDialog.tsx b/src/sections/engineSettings/engineSettingsDialog.tsx index 0271d6a..ce9dbf9 100644 --- a/src/sections/engineSettings/engineSettingsDialog.tsx +++ b/src/sections/engineSettings/engineSettingsDialog.tsx @@ -114,6 +114,7 @@ export default function EngineSettingsDialog({ open, onClose }: Props) { setValue={setMultiPv} min={2} max={6} + marksFilter={1} size={6} /> diff --git a/src/sections/play/board.tsx b/src/sections/play/board.tsx index 1f39114..9867069 100644 --- a/src/sections/play/board.tsx +++ b/src/sections/play/board.tsx @@ -14,7 +14,7 @@ import { useEngine } from "@/hooks/useEngine"; import { uciMoveParams } from "@/lib/chess"; import Board from "@/components/board"; import { useGameData } from "@/hooks/useGameData"; -import { usePlayersData } from "@/hooks/usePlayerNames"; +import { usePlayersData } from "@/hooks/usePlayersData"; export default function BoardContainer() { const screenSize = useScreenSize(); diff --git a/src/sections/play/gameSettings/gameSettingsDialog.tsx b/src/sections/play/gameSettings/gameSettingsDialog.tsx index e1c6dfc..8102d7d 100644 --- a/src/sections/play/gameSettings/gameSettingsDialog.tsx +++ b/src/sections/play/gameSettings/gameSettingsDialog.tsx @@ -55,10 +55,16 @@ export default function GameSettingsDialog({ open, onClose }: Props) { const handleGameStart = () => { onClose(); resetGame({ - whiteName: - playerColor === Color.White ? "You" : engineLabel[engineName].small, - blackName: - playerColor === Color.Black ? "You" : engineLabel[engineName].small, + white: { + name: + playerColor === Color.White ? "You" : engineLabel[engineName].small, + rating: playerColor === Color.White ? undefined : engineElo, + }, + black: { + name: + playerColor === Color.Black ? "You" : engineLabel[engineName].small, + rating: playerColor === Color.Black ? undefined : engineElo, + }, }); playGameStartSound(); setIsGameInProgress(true); @@ -129,9 +135,10 @@ export default function GameSettingsDialog({ open, onClose }: Props) { label="Bot Elo rating" value={engineElo} setValue={setEngineElo} - min={100} - max={3200} - step={100} + min={1320} + max={3190} + step={10} + marksFilter={374} /> diff --git a/src/sections/play/states.ts b/src/sections/play/states.ts index e5f5394..edfe070 100644 --- a/src/sections/play/states.ts +++ b/src/sections/play/states.ts @@ -7,6 +7,5 @@ export const gameAtom = atom(new Chess()); export const gameDataAtom = atom({}); export const playerColorAtom = atom(Color.White); export const enginePlayNameAtom = atom(EngineName.Stockfish17Lite); -export const engineSkillLevelAtom = atom(1); -export const engineEloAtom = atom(1200); +export const engineEloAtom = atom(1320); export const isGameInProgressAtom = atom(false);