From 13f024401eff2f20751abff5ec5500f657560ecd Mon Sep 17 00:00:00 2001 From: f-hejazi Date: Mon, 15 Sep 2025 16:46:49 +0100 Subject: [PATCH 1/2] Remove tracked root .DS_Store and clean up untracked .DS_Store files --- .DS_Store | Bin 8196 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 .DS_Store diff --git a/.DS_Store b/.DS_Store deleted file mode 100644 index fedb5f8d71983afafcc96ed9506fcc5ff69e2609..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8196 zcmeHM-A)rh6h2d`-P)iSB|wN~6B8~BMbHo=-ju%!5`Pkk8l$Fey9HL3-KM*3qlBcl z>J#_|UYL04oA@qX>33!p*lCNwaG}u|vU6s4=Q}^&oU_|mh)68A+&Q9gBC>F>94Vk1 z(D*(deJzt*VXy$6$R~%IRHQc)_02XH3GHFkl$?8yLVlo11mQdtco(yyVq0p&z40mDE)1H5;iz^*-@ZE9)z_n7LmC-1ma zqaB<@_$yL~S?;zC+IZkWHGH)DSfwJm3S0fp22u;QrxwD>)0PscX$_ z_h>Dow5}ZM)KRnq)aR5hX;c}uo7CpM2lb@~H40nGQ|6%pZ=3M5jW{BlaV%|&W^nB2 znj{x#`@`gdvl`glleidqV(1Ae(2+9UG%`o`X`NPRjUG~&*7Vsj&NSy2px=Wn7tGYD z11s>qA0uw2xVbn818X6)^kTt~hP^DYoD(t@tgMGC4)UlDUK*THx^*!Hjz6ZX57Q$= zxC%Zu5aSX?4_1SK~QjK;Kdqu>|9Pa}C8Xom=D?apSxRR`{%0vEMH89`x z2#B*J&G{*{R69{4sg|$RhVMo3?Cdv@8OokJpR;mS!FpNV2|MN3iCfXK(|pcnn_=iz z564dRiC6DbMy{@eLF{-zy(s~nTgQ|aPrbkmJIi4!a3hH=s~c9{%2!6l_V;fu%um~k z^9R%R{@pu^)AqvL!ofk_8ohDr-bQ8D-wVQb2n$qZN;MP3st9<6^H+67Y{Fl3*bp|Xd From cd351a73ecf0ad87b87785d9aeb4667b8c0054be Mon Sep 17 00:00:00 2001 From: f-hejazi Date: Wed, 24 Sep 2025 13:01:35 +0100 Subject: [PATCH 2/2] chore(stockfish): remove legacy HTTP, fix binaries, update frontend socket --- .../hooks/useSocketChessEngine.ts | 3 +- stockfishServer/StockfishManager.js | 6 +- stockfishServer/bin/stockfish_11_linux | Bin stockfishServer/bin/stockfish_11_mac | Bin stockfishServer/index.js | 113 +++++--------- stockfishServer/index_new.js | 35 ----- stockfishServer/index_refactor.js | 139 ------------------ 7 files changed, 39 insertions(+), 257 deletions(-) mode change 100644 => 100755 stockfishServer/bin/stockfish_11_linux mode change 100644 => 100755 stockfishServer/bin/stockfish_11_mac delete mode 100644 stockfishServer/index_new.js delete mode 100644 stockfishServer/index_refactor.js diff --git a/react-ystemandchess/src/Pages/piece-lessons/lesson-overlay/hooks/useSocketChessEngine.ts b/react-ystemandchess/src/Pages/piece-lessons/lesson-overlay/hooks/useSocketChessEngine.ts index ada4ef1c..3e37be23 100644 --- a/react-ystemandchess/src/Pages/piece-lessons/lesson-overlay/hooks/useSocketChessEngine.ts +++ b/react-ystemandchess/src/Pages/piece-lessons/lesson-overlay/hooks/useSocketChessEngine.ts @@ -1,3 +1,4 @@ +import { environment } from "../../../../environments/environment"; import { useEffect, useRef } from "react"; import io from "socket.io-client"; @@ -5,7 +6,7 @@ export function useSocketChessEngine(onEvaluationComplete: (data: any) => void) const socketRef = useRef(null); useEffect(() => { - const socket = io("http://localhost:8080", { transports: ["websocket"] }); + const socket = io(environment.urls.stockFishURL, { transports: ["websocket"] }); socketRef.current = socket; socket.on("connect", () => { diff --git a/stockfishServer/StockfishManager.js b/stockfishServer/StockfishManager.js index 46027c9c..875241df 100644 --- a/stockfishServer/StockfishManager.js +++ b/stockfishServer/StockfishManager.js @@ -6,13 +6,13 @@ let enginePath; switch (process.platform) { case 'win32': - enginePath = "./bin/stockfish.exe"; + enginePath = "./bin/stockfish_11_win.exe"; break; case 'darwin': - enginePath = "./bin/stockfish-macos"; + enginePath = "./bin/stockfish_11_mac"; break; case 'linux': - enginePath = "./bin/stockfish-ubuntu"; + enginePath = "./bin/stockfish_11_linux"; break; default: throw new Error(`Unsupported platform: ${process.platform}`); diff --git a/stockfishServer/bin/stockfish_11_linux b/stockfishServer/bin/stockfish_11_linux old mode 100644 new mode 100755 diff --git a/stockfishServer/bin/stockfish_11_mac b/stockfishServer/bin/stockfish_11_mac old mode 100644 new mode 100755 diff --git a/stockfishServer/index.js b/stockfishServer/index.js index 069ba4e6..c38caea2 100644 --- a/stockfishServer/index.js +++ b/stockfishServer/index.js @@ -1,88 +1,43 @@ require("dotenv").config(); - const express = require("express"); +const http = require("http"); +const socketIo = require("socket.io"); +const cors = require("cors"); const rateLimit = require("express-rate-limit"); -const { Chess } = require("chess.js"); -const Stockfish = require("stockfish"); -const querystring = require("querystring"); -const url = require("url"); -const { SSL_OP_SSLEAY_080_CLIENT_DH_BUG } = require("constants"); -const app = express(); +// Import the socket handlers that use StockfishManager +const initializeSocket = require("./socket"); -// Set rate limit - 30 requests/minute per IP -const limiter = rateLimit({ - windowMs: 60 * 1000, - max: 30, - message: { error: "Too many requests! Please try again." }, +const app = express(); +const server = http.createServer(app); + +// Socket.io with CORS +const io = socketIo(server, { + cors: { + origin: "*", + methods: ["GET", "POST"], + }, }); -app.use(limiter); - -// CORS headers -app.use((req, res, next) => { - // WARNING: allow only selected access for production - res.setHeader("Access-Control-Allow-Origin", "*"); - res.setHeader("Content-Type", "application/json"); - next(); +// Middleware +app.use(cors()); +app.use(express.json()); +app.use( + rateLimit({ + windowMs: 60 * 1000, // 1 minute + max: 30, + message: { error: "Too many requests!" }, + }) +); + +app.get("/health", (req, res) => res.json({ status: "OK" })); + +// Socket.io connection handling +io.on("connection", (socket) => { + console.log(`New client (${socket.id}) connected!`); + initializeSocket(io, socket); // StockfishManager handles all session events }); -// Main API route -app.get("/", (req, res) => { - const params = querystring.parse(url.parse(req.url, true).search?.substring(1)); - const { fen, move = "", level = 10, info = false } = params; - - // Validate input - if (!fen || isNaN(level)) { - return res.status(400).json({ error: "Missing or invalid parameters!" }); - } - - const maxLevel = 30; - var lines = []; - var depth = Math.min(parseInt(level), maxLevel); - const engine = Stockfish(); - - const game = new Chess(fen); - - engine.onmessage = (line) => { - if (info) { - - lines.push(line); - if (line.startsWith("bestmove")) { - res.json({ output: lines }); - } - } - else if (line.startsWith("bestmove")) { - const moveResult = game.move(line.split(" ")[1], { sloppy: true }); - - if (moveResult) { - const color = moveResult.color; - const piece = moveResult.piece.toUpperCase(); - const move = color + piece; - const target = moveResult.to; - res.end(`${game.fen()} move:${move} target:${target}`); - } - else { - res.end("Invalid move or game state"); - } - } - } - - // Send position + evaluation command to the engine - engine.postMessage(`position fen ${fen} moves ${move}`); - engine.postMessage(`go depth ${depth}`); - - // Set timeout for safety - setTimeout(() => { - if (!res.writableEnded) { - res.status(504).json({ error: "Engine timeout!" }); - } - }, 5000); -}); - - -// Start the server -const PORT = process.env.PORT || 5001; -app.listen(PORT, () => { - console.log(`Stockfish server running on port ${PORT}`); -}); \ No newline at end of file +// Start server +const PORT = process.env.PORT || 8080; +server.listen(PORT, () => console.log(`Stockfish server running on port ${PORT}`)); diff --git a/stockfishServer/index_new.js b/stockfishServer/index_new.js deleted file mode 100644 index efd05f86..00000000 --- a/stockfishServer/index_new.js +++ /dev/null @@ -1,35 +0,0 @@ -require('dotenv').config() - -const express = require('express'); -const socketIo = require('socket.io'); -const { Chess } = require('chess.js'); -const cors = require('cors'); -const http = require('http'); -const initializeSocket = require('./socket'); - -const app = express(); -const server = http.createServer(app); - -const io = socketIo(server, { - cors: { - origin: "*", - methods: ["GET", "POST"] - } -}); - -app.use(cors()); -app.use(express.json()); - -app.get("/health", (req, res) => { - return res.json({ status: "OK" }); -}); - -io.on("connection", (socket) => { - console.log(`New client (${socket.id}) connected!`); - initializeSocket(io, socket); -}); - -const PORT = process.env.PORT || 5001; -server.listen(PORT, () => { - console.log(`Stockfish server running on port ${PORT}`); -}); \ No newline at end of file diff --git a/stockfishServer/index_refactor.js b/stockfishServer/index_refactor.js deleted file mode 100644 index 10c2edaa..00000000 --- a/stockfishServer/index_refactor.js +++ /dev/null @@ -1,139 +0,0 @@ -const http = require("http"); -const { spawn } = require("child_process"); -const chess = require("chess.js"); -const querystring = require("querystring"); -const url = require("url"); - -const maxLevel = 99; - -http.createServer((req, res) => { - res.setHeader("Access-Control-Allow-Origin", "*"); - res.setHeader("Content-Type", "application/json"); - - // Parse params from URL - const params = querystring.parse(url.parse(req.url, true).search?.substring(1)); - if (!params.fen || !params.level) { - res.statusCode = 400; - res.end(JSON.stringify({ error: "Missing fen or level parameter" })); - return; - } - - // Cap the level - let level = parseInt(params.level); - if (isNaN(level) || level > maxLevel) level = maxLevel; - - let enginePath; - - switch (process.platform) { - case 'win32': - enginePath = "./bin/stockfish_11_win.exe"; - break; - case 'darwin': - enginePath = "./bin/stockfish_11_mac"; - break; - case 'linux': - enginePath = "./bin/stockfish_11_linux"; - break; - default: - throw new Error(`Unsupported platform: ${process.platform}`); -} - - // Spawn the stockfish engine process - const engine = spawn(enginePath); - - engine.stdout.on("data", (data) => { - const line = data.toString().trim(); - console.log("engine output:", line) - - if (line.includes("bestmove")) { - let move = getBestMove(line); - - if(params.fen == "5k2/3q2pp/8/4N3/8/8/6PP/5RK1 b - - 1 1") { - move = "f8e7"; - } else if (params.fen == "r4k2/2r2pp1/3P3p/8/4B3/5N2/6PP/5RK1 b - - 0 1"){ - move = "c7d7"; - } else if (params.fen == "8/1b1Q1ppk/p3p2p/1p1q4/3Ppb2/1P2B1P1/P6P/2R3K1 w - - 1 2"){ - move = "d7d5"; - } else if (params.fen == "r6r/2q2P1p/p1k3p1/1p1Bp3/8/2P1B3/P1PR2PP/5RK1 b - - 0 24"){ - move = "c6d7"; - } else if (params.fen == "2b5/7p/3k2pP/1p1p1pPB/1P1P1K2/8/5P2/8 b - - 1 1"){ - move = "c8e6"; - } else if (params.fen == "2r2r1k/1pN1Qpbp/p3Bpp1/qb6/8/8/PP3PPP/2RR2K1 b - - 11 23"){ - move = "b5e2"; - } else if (params.fen == "8/6p1/5p1k/BP1B4/5P1p/7P/2R3P1/r5Kn w - - 1 2") { - move = "a5e1"; - } else if (params.fen == "5q2/1b4pk/1p2p1n1/1PNpPp2/P2P1P1p/rB3R1P/1Q4PK/8 b - - 3 46") { - move = "a3b3"; - } else if (params.fen == "rnb2r1k/pp1n1ppB/4p3/3pP3/3p3Q/2N4N/PPP2PP1/R3K2R b KQ - 0 12"){ - move = "g7g5"; - } else if (params.fen == "8/5pk1/4p3/1p6/6P1/4P2p/PR2KP2/3r4 w - - 1 2"){ - move = "e2d1"; - } else if (params.fen == "r6k/ppN2pPp/6p1/5q2/1p3Rn1/1P6/P5PP/3R1K2 b - - 0 2"){ - move = "h8g8"; - } else if (params.fen == "1q2rk2/1p3ppp/p4R2/2N5/1P6/6P1/P1Q3KP/8 b - - 0 1"){ - move = "b8c8"; - } else if (params.fen == "8/2k5/3r1Np1/1p4K1/5P2/8/1n2R3/8 b - - 4 57"){ - move = "d6d1"; - } else if (params.fen == "8/8/8/8/1k6/p7/8/1K6 b - - 1 2"){ - move = "a3a2"; - } else if (params.fen == "8/8/8/4p3/4k3/8/4K3/8 b - - 1 1"){ - move = "e4d4"; - } else if (params.fen == "8/8/8/8/3k4/4p3/8/4K3 b - - 1 4"){ - move = "e3e2"; - } else if (params.fen == "8/8/8/5kp1/8/8/8/5K2 b - - 1 1"){ - move = "g5g4"; - } else if (params.fen == "8/8/8/5k2/6p1/8/5K2/8 b - - 1 2"){ - move = 'g4g3'; - } else if (params.fen == "8/8/8/5k2/8/6p1/6K1/8 b - - 1 3"){ - move = 'f5e4'; - } else if (params.fen == "6N1/7K/5k2/8/8/8/8/6r1 b - - 0 1"){ - move = "g1g8"; - } - - const game = new chess.Chess(params.fen); - const result = game.move(move, { sloppy: true }); - - if (result) { - const response = { - fen: game.fen(), - move: move, - piece: result.piece.toUpperCase(), - color: result.color, - from: result.from, - to: result.to, - }; - res.end(JSON.stringify(response)); - } else { - res.end(JSON.stringify({ error: "Invalid move from engine" })); - } - engine.kill(); - } - }); - - engine.stderr.on("data", (data) => { - console.error(`Engine error: ${data.toString()}`); - }); - - engine.on("error", (err) => { - console.error("Failed to start engine:", err); - res.statusCode = 500; - res.end(JSON.stringify({ error: "Engine start failure" })); - }); - - // Send commands to engine - engine.stdin.write(`position fen ${params.fen}\n`); - engine.stdin.write(`go depth ${level}\n`); -}).listen(process.env.PORT || 8080, () => { - console.log(`Stockfish server listening on port ${process.env.PORT || 8080}`); -}); - -function getBestMove(output) { - const lines = output.split('\n'); - for (const line of lines) { - if (line.startsWith('bestmove')) { - const parts = line.split(' '); - return parts[1]; - } - } - return null; -} \ No newline at end of file