From 5280235c16a7e1644f72b48844c0d0c9f1a5efca Mon Sep 17 00:00:00 2001 From: Daniel Abrahamsen Date: Sat, 26 Oct 2024 15:43:44 +0200 Subject: [PATCH 1/4] Add analysis event to the socket --- backend/chessLogic/chessLogic.py | 5 +++++ backend/server.py | 6 ++++++ 2 files changed, 11 insertions(+) diff --git a/backend/chessLogic/chessLogic.py b/backend/chessLogic/chessLogic.py index ce7948e..e5fbfef 100644 --- a/backend/chessLogic/chessLogic.py +++ b/backend/chessLogic/chessLogic.py @@ -39,6 +39,11 @@ def getBestMove(self, board): self.last_move = best_move return best_move + def getBoardAnalysis(self, board): + analysisDict = self.engine.analyse(board, chess.engine.Limit(time=0.3)) + povScore = analysisDict["score"] + return povScore.relative + def getOutcome(self, board): #.winner returns true for white win, false for black, None for draw if board.outcome(): diff --git a/backend/server.py b/backend/server.py index 8312a1e..be85d11 100644 --- a/backend/server.py +++ b/backend/server.py @@ -52,6 +52,7 @@ def newGame(arg): mycertabo.new_game() emitFen() startGame(arg) + emitAnalysis() @socket_io.on('stop-game') def stopGame(): @@ -145,11 +146,16 @@ def handleStockfishMove(): def doMove(move): mycertabo.moves.append(move) emitFen() + emitAnalysis() def emitFen(): fen = mycertabo.chessboard.board_fen() message = {"fen": fen, "color": mycertabo.color, 'moves': mycertabo.moves} socket_io.emit("get-fen", message) +def emitAnalysis(): + analysis = chess_logic.getBoardAnalysis(mycertabo.chessboard) + socket_io.emit("analysis", { "relativeScore": analysis }) + if __name__ == '__main__': socket_io.run(app, port=5000) From 9c0bf64a0fcdc75a0f1c00792bc32a289c51f73b Mon Sep 17 00:00:00 2001 From: Henrik Hermansen Date: Sat, 26 Oct 2024 15:56:30 +0200 Subject: [PATCH 2/4] Started development on eval gauge --- .../src/Components/EvalGauge/EvalGauge.tsx | 35 +++++++++++++++++++ frontend/src/Components/PreGame/PreGame.tsx | 9 ++--- frontend/src/pages/Game/index.tsx | 12 ++++--- 3 files changed, 45 insertions(+), 11 deletions(-) create mode 100644 frontend/src/Components/EvalGauge/EvalGauge.tsx diff --git a/frontend/src/Components/EvalGauge/EvalGauge.tsx b/frontend/src/Components/EvalGauge/EvalGauge.tsx new file mode 100644 index 0000000..119fefc --- /dev/null +++ b/frontend/src/Components/EvalGauge/EvalGauge.tsx @@ -0,0 +1,35 @@ +const toCentipawn = (score: number) => Math.round(score / 10) / 10; + +interface EvalGaugeProps { + score: number +} + +export const EvalGauge = ({score}: EvalGaugeProps) => { + + // TODO calculate gaugePosition from score + const gaugePosition = 20; + + return ( +
+
{toCentipawn(score)}
+
 
+
 
+
 
+
 
+
 
+
 
+
 
+
 
+
 
+
 
+
 
+
 
+
+ ) +} diff --git a/frontend/src/Components/PreGame/PreGame.tsx b/frontend/src/Components/PreGame/PreGame.tsx index ef3a3f4..e9d4337 100644 --- a/frontend/src/Components/PreGame/PreGame.tsx +++ b/frontend/src/Components/PreGame/PreGame.tsx @@ -53,7 +53,7 @@ export default function PreGame(props: alertProps) { ) => ( - - {renderCard("assets/images/king_w.png", "White piece", "White", true)} - - + {renderCard( "assets/images/king_b.png", "Black piece", "Black", false )} - + Set stockfish level (1-20) diff --git a/frontend/src/pages/Game/index.tsx b/frontend/src/pages/Game/index.tsx index ec32856..fea4fbe 100644 --- a/frontend/src/pages/Game/index.tsx +++ b/frontend/src/pages/Game/index.tsx @@ -1,4 +1,4 @@ -import { Box, Button } from "@mui/material"; +import {Box, Button, Stack} from "@mui/material"; import { useEffect, useState } from "react"; import { Socket } from "socket.io-client"; import AlertComponent from "../../Components/Alert/Notification"; @@ -7,6 +7,7 @@ import GameStatus from "../../Components/GameStatus/GameStatus"; import { default as PreGame } from "../../Components/PreGame/PreGame"; import { useGameContext, GameState } from "./GameContext"; import "./index.css"; +import {EvalGauge} from "../../Components/EvalGauge/EvalGauge.tsx"; interface gameProps { socket: Socket; } @@ -185,7 +186,7 @@ export default function Game(props: gameProps) { } }; - const handleValidMoves = (validMoves: string[]) => { + const handleValidMoves = (validMoves: string[]) => { setValidMoves(validMoves); }; @@ -225,9 +226,10 @@ export default function Game(props: gameProps) { )} - + + - + {result === undefined && !gameState && ( - + ) : <> } From 52fa39ddcc88e659162858ce27f067abf4dbaead Mon Sep 17 00:00:00 2001 From: Daniel Abrahamsen Date: Sat, 26 Oct 2024 16:26:26 +0200 Subject: [PATCH 3/4] Fix povScore value --- backend/chessLogic/chessLogic.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/chessLogic/chessLogic.py b/backend/chessLogic/chessLogic.py index e5fbfef..094958e 100644 --- a/backend/chessLogic/chessLogic.py +++ b/backend/chessLogic/chessLogic.py @@ -42,7 +42,7 @@ def getBestMove(self, board): def getBoardAnalysis(self, board): analysisDict = self.engine.analyse(board, chess.engine.Limit(time=0.3)) povScore = analysisDict["score"] - return povScore.relative + return povScore.white().score(mate_score=10000) def getOutcome(self, board): #.winner returns true for white win, false for black, None for draw From 30c0510183f88954c57d7628d529ef4f5056b104 Mon Sep 17 00:00:00 2001 From: Daniel Wenner Date: Sat, 26 Oct 2024 17:04:13 +0200 Subject: [PATCH 4/4] Connect arrow to backend socket message --- .../src/Components/EvalGauge/EvalGauge.tsx | 41 ++++++++++------- frontend/src/pages/Game/index.tsx | 44 ++++++++++++------- 2 files changed, 52 insertions(+), 33 deletions(-) diff --git a/frontend/src/Components/EvalGauge/EvalGauge.tsx b/frontend/src/Components/EvalGauge/EvalGauge.tsx index 119fefc..b20742e 100644 --- a/frontend/src/Components/EvalGauge/EvalGauge.tsx +++ b/frontend/src/Components/EvalGauge/EvalGauge.tsx @@ -4,10 +4,18 @@ interface EvalGaugeProps { score: number } -export const EvalGauge = ({score}: EvalGaugeProps) => { +function clamp(num: number, min: number, max: number) { + return num <= min + ? min + : num >= max + ? max + : num +} + +export const EvalGauge = ({ score }: EvalGaugeProps) => { - // TODO calculate gaugePosition from score - const gaugePosition = 20; + const nomalized = (((score ?? 0) + 1000) / 2000) * 100 + const gaugePosition = clamp(nomalized, 0, 100); return (
{ position: "relative", paddingTop: "1em" }}> -
{toCentipawn(score)}
-
 
-
 
-
 
-
 
-
 
-
 
-
 
-
 
-
 
-
 
-
 
-
 
+
{toCentipawn(score)}
+
 
+
 
+
 
+
 
+
 
+
 
+
 
+
 
+
 
+
 
+
 
+
 
) } + diff --git a/frontend/src/pages/Game/index.tsx b/frontend/src/pages/Game/index.tsx index fea4fbe..44ee47c 100644 --- a/frontend/src/pages/Game/index.tsx +++ b/frontend/src/pages/Game/index.tsx @@ -1,4 +1,4 @@ -import {Box, Button, Stack} from "@mui/material"; +import { Box, Button, Stack } from "@mui/material"; import { useEffect, useState } from "react"; import { Socket } from "socket.io-client"; import AlertComponent from "../../Components/Alert/Notification"; @@ -7,11 +7,15 @@ import GameStatus from "../../Components/GameStatus/GameStatus"; import { default as PreGame } from "../../Components/PreGame/PreGame"; import { useGameContext, GameState } from "./GameContext"; import "./index.css"; -import {EvalGauge} from "../../Components/EvalGauge/EvalGauge.tsx"; +import { EvalGauge } from "../../Components/EvalGauge/EvalGauge.tsx"; interface gameProps { socket: Socket; } +interface Analysis { + relativeScore: number; +} + export default function Game(props: gameProps) { const [FEN, setFEN] = useState("start"); const [moves, setMoves] = useState(); @@ -28,6 +32,7 @@ export default function Game(props: gameProps) { const [promotion, setPromotion] = useState(""); const [player, setPlayer] = useState(); const [not_valid, setNotValid] = useState(false); + const [relativeScore, setRelativeScore] = useState(0); useEffect(() => { props.socket.on("invalid-move", handleInvalidMove); @@ -35,6 +40,7 @@ export default function Game(props: gameProps) { props.socket.on("get-fen", handleFEN); props.socket.on("game-over", handleResultMessage); props.socket.on("promotion", handlePromotion); + props.socket.on("analysis", handleAnalysis); return () => { // Cleanup the props.socket listener when the component unmounts props.socket.off("invalid-move", handleInvalidMove); @@ -75,7 +81,11 @@ export default function Game(props: gameProps) { } }; - function startGame() { + function handleAnalysis({ relativeScore }: Analysis): void { + setRelativeScore(relativeScore); + } + + function startGame() { if (props.socket.connected) { const preferences = { skill_level: stockfishlevel, @@ -104,7 +114,7 @@ export default function Game(props: gameProps) { } const handleInvalidMove = () => { - setNotValid(true); + setNotValid(true); }; const handleOK = () => { @@ -187,7 +197,7 @@ export default function Game(props: gameProps) { }; const handleValidMoves = (validMoves: string[]) => { - setValidMoves(validMoves); + setValidMoves(validMoves); }; return ( @@ -227,7 +237,7 @@ export default function Game(props: gameProps) { - + @@ -254,17 +264,17 @@ export default function Game(props: gameProps) { player={undefined} /> - )} - {(not_valid ) ? ( - - - - ) : <> - } + )} + {(not_valid) ? ( + + + + ) : <> + } )}