Gameplay (legal moves, move application, pressure maps, PGN parsing) now runs entirely in the browser via a chess.js port of engine.py (static/engine.js + vendored chess.min.js). The app no longer calls the server during play, so it stays instant and works even when the backend is scaled to zero or offline. - engine.js: line-for-line port of engine.py; parity-verified identical output (pressure, FEN, status, SAN/UCI) across all 10 built-in games / 829 frames. - app.js: replace all /api fetches with local engine calls; graceful PGN parse errors; asset paths moved to root for static serving. - Save games to localStorage + load from the game dropdown; export any game as a .pgn file. Minimal additive UI in the existing export row. - games.json generated from games.py (scripts/export_games.py). - Production Dockerfile -> static-web-server (~9MB image, was ~150MB python). - make dev -> bun static server; add make games / make parity targets. - app.py kept as optional fallback (serves static app + /api routes). - parity/: automated JS-vs-python engine parity test. git diff stat: 16 files changed, 722 insertions(+), 128 deletions(-)
29 lines
704 B
Python
29 lines
704 B
Python
"""Export the built-in games to static/games.json for the client-side app.
|
|
|
|
The browser parses these PGNs locally (via chess.js) — the server is no longer
|
|
in the gameplay path. Re-run after editing games.py:
|
|
|
|
uv run python scripts/export_games.py
|
|
"""
|
|
|
|
import json
|
|
from pathlib import Path
|
|
|
|
from chess_pressure.games import GAMES
|
|
|
|
OUT = Path(__file__).resolve().parent.parent / "src" / "chess_pressure" / "static" / "games.json"
|
|
|
|
data = [
|
|
{
|
|
"id": g["id"],
|
|
"name": g["name"],
|
|
"white": g["white"],
|
|
"black": g["black"],
|
|
"pgn": g["pgn"],
|
|
}
|
|
for g in GAMES
|
|
]
|
|
|
|
OUT.write_text(json.dumps(data, indent=2) + "\n")
|
|
print(f"Wrote {len(data)} games to {OUT}")
|