feat : init game eval
This commit is contained in:
@@ -1,14 +1,16 @@
|
||||
import { GameEval, MoveEval } from "@/types/eval";
|
||||
|
||||
export class Stockfish {
|
||||
private worker: Worker;
|
||||
private ready: boolean = false;
|
||||
|
||||
constructor() {
|
||||
this.worker = new Worker(
|
||||
this.isWasmSupported() ? "./stockfish.wasm.js" : "./stockfish.js"
|
||||
this.isWasmSupported()
|
||||
? "engines/stockfish.wasm.js"
|
||||
: "engines/stockfish.js"
|
||||
);
|
||||
|
||||
this.sendCommands(["uci"], "uciok");
|
||||
this.sendCommands(["setoption name MultiPV value 2", "isready"], "readyok");
|
||||
|
||||
console.log("Stockfish created");
|
||||
}
|
||||
|
||||
@@ -21,6 +23,25 @@ export class Stockfish {
|
||||
);
|
||||
}
|
||||
|
||||
public async init(): Promise<void> {
|
||||
await this.sendCommands(["uci"], "uciok");
|
||||
await this.sendCommands(
|
||||
["setoption name MultiPV value 2", "isready"],
|
||||
"readyok"
|
||||
);
|
||||
this.ready = true;
|
||||
}
|
||||
|
||||
public shutdown(): void {
|
||||
this.ready = false;
|
||||
this.worker.postMessage("quit");
|
||||
this.worker.terminate();
|
||||
}
|
||||
|
||||
public isReady(): boolean {
|
||||
return this.ready;
|
||||
}
|
||||
|
||||
private async sendCommands(
|
||||
commands: string[],
|
||||
finalMessage: string
|
||||
@@ -42,15 +63,20 @@ export class Stockfish {
|
||||
}
|
||||
|
||||
public async evaluateGame(fens: string[], depth = 16): Promise<GameEval> {
|
||||
this.ready = false;
|
||||
console.log("Evaluating game");
|
||||
await this.sendCommands(["ucinewgame", "isready"], "readyok");
|
||||
this.worker.postMessage("position startpos");
|
||||
|
||||
const moves: MoveEval[] = [];
|
||||
for (const fen of fens) {
|
||||
console.log(`Evaluating position: ${fen}`);
|
||||
const result = await this.evaluatePosition(fen, depth);
|
||||
moves.push(result);
|
||||
}
|
||||
|
||||
this.ready = true;
|
||||
console.log("Game evaluated");
|
||||
return { moves };
|
||||
}
|
||||
|
||||
File diff suppressed because one or more lines are too long
Binary file not shown.
File diff suppressed because one or more lines are too long
4
src/sections/index/index.state.ts
Normal file
4
src/sections/index/index.state.ts
Normal file
@@ -0,0 +1,4 @@
|
||||
import { GameEval } from "@/types/eval";
|
||||
import { atom } from "jotai";
|
||||
|
||||
export const gameReviewAtom = atom<GameEval | undefined>(undefined);
|
||||
@@ -1,8 +1,34 @@
|
||||
import { useEffect, useState } from "react";
|
||||
import ReviewResult from "./reviewResult";
|
||||
import SelectDepth from "./selectDepth";
|
||||
import SelectGameOrigin from "./selectGame/selectGameOrigin";
|
||||
import { Stockfish } from "@/lib/engine/stockfish";
|
||||
import { useAtomValue } from "jotai";
|
||||
import { gameFensAtom } from "./selectGame/gameOrigin.state";
|
||||
|
||||
export default function ReviewPanelBody() {
|
||||
const [engine, setEngine] = useState<Stockfish | null>(null);
|
||||
const gameFens = useAtomValue(gameFensAtom);
|
||||
|
||||
useEffect(() => {
|
||||
const engine = new Stockfish();
|
||||
engine.init().then(() => {
|
||||
console.log("Engine initialized");
|
||||
});
|
||||
setEngine(engine);
|
||||
|
||||
return () => {
|
||||
engine.shutdown();
|
||||
console.log("Engine shutdown");
|
||||
};
|
||||
}, []);
|
||||
|
||||
const handleAnalyse = () => {
|
||||
if (engine?.isReady() && gameFens) {
|
||||
engine.evaluateGame(gameFens);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div id="review-panel-main">
|
||||
<h1 id="review-panel-title" className="white">
|
||||
@@ -13,7 +39,7 @@ export default function ReviewPanelBody() {
|
||||
|
||||
<button id="review-button" className="std-btn success-btn white">
|
||||
<img src="analysis_icon.png" height="25" />
|
||||
<b>Analyse</b>
|
||||
<b onClick={handleAnalyse}>Analyse</b>
|
||||
</button>
|
||||
|
||||
<SelectDepth />
|
||||
|
||||
3
src/sections/index/selectGame/gameOrigin.state.ts
Normal file
3
src/sections/index/selectGame/gameOrigin.state.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
import { atom } from "jotai";
|
||||
|
||||
export const gameFensAtom = atom<string[]>([]);
|
||||
@@ -1,8 +1,27 @@
|
||||
import { GameOrigin } from "@/types/enums";
|
||||
import { useSetAtom } from "jotai";
|
||||
import { gameFensAtom } from "./gameOrigin.state";
|
||||
import { useEffect, useState } from "react";
|
||||
import { Chess } from "chess.js";
|
||||
|
||||
interface Props {
|
||||
gameOrigin: GameOrigin;
|
||||
placeholder?: string;
|
||||
}
|
||||
|
||||
export default function InputGame({ placeholder }: Props) {
|
||||
const [gamePgn, setGamePgn] = useState("");
|
||||
const setGameFens = useSetAtom(gameFensAtom);
|
||||
|
||||
useEffect(() => {
|
||||
const chess = new Chess();
|
||||
chess.loadPgn(gamePgn);
|
||||
const fens = chess.history({ verbose: true }).map((move) => {
|
||||
return move.after;
|
||||
});
|
||||
setGameFens(fens);
|
||||
}, [gamePgn]);
|
||||
|
||||
return (
|
||||
<textarea
|
||||
id="pgn"
|
||||
@@ -11,6 +30,8 @@ export default function InputGame({ placeholder }: Props) {
|
||||
rows={10}
|
||||
spellCheck="false"
|
||||
placeholder={placeholder}
|
||||
value={gamePgn}
|
||||
onChange={(e) => setGamePgn(e.target.value)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import { GameOrigin } from "@/types/enums";
|
||||
|
||||
export default function SelectGameOrigin() {
|
||||
const [gameOrigin, setGameOrigin] = useState(GameOrigin.Pgn);
|
||||
|
||||
return (
|
||||
<>
|
||||
<div id="load-type-dropdown-container" className="white">
|
||||
@@ -37,9 +38,13 @@ const gameOriginLabel: Record<GameOrigin, string> = {
|
||||
const renderSelectGameInfo = (gameOrigin: GameOrigin) => {
|
||||
switch (gameOrigin) {
|
||||
case GameOrigin.Pgn:
|
||||
return <InputGame placeholder="Enter PGN here..." />;
|
||||
return (
|
||||
<InputGame gameOrigin={gameOrigin} placeholder="Enter PGN here..." />
|
||||
);
|
||||
case GameOrigin.Json:
|
||||
return <InputGame placeholder="Enter JSON here..." />;
|
||||
return (
|
||||
<InputGame gameOrigin={gameOrigin} placeholder="Enter JSON here..." />
|
||||
);
|
||||
default:
|
||||
return <SelectGameAccount gameOrigin={gameOrigin} />;
|
||||
}
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
interface MoveEval {
|
||||
export interface MoveEval {
|
||||
bestMove: string;
|
||||
lines: LineEval[];
|
||||
}
|
||||
|
||||
interface LineEval {
|
||||
export interface LineEval {
|
||||
pv: string[];
|
||||
score?: number;
|
||||
mate?: number;
|
||||
}
|
||||
|
||||
interface GameEval {
|
||||
export interface GameEval {
|
||||
moves: MoveEval[];
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user