diff --git a/AGENTS.md b/AGENTS.md index de8047d..5f4992b 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -3,3 +3,5 @@ - Nach jeder Änderung am Proxy (server.py) oder an den Requests (app.js) muss der Proxy neu gestartet werden: erst alten Prozess killen (`Get-Process -Name python | Stop-Process -Force`), dann unsichtbar starten. - Commits und Push erfolgen nur durch expliziten Befehl des Nutzers. - Der Server (server.py) wird immer unsichtbar gestartet: `Start-Process -NoNewWindow -FilePath "python" -ArgumentList "server.py"` +- **LESS-Workflow**: CSS-Quelldatei ist `style.less`. Bei Serverstart wird automatisch `style.css` via `node build-less.js` kompiliert. Bei manuellen Änderungen an `style.less`: `node build-less.js` ausführen, dann Server neustarten. +- `style.css` ist auto-generiert – keine manuellen Änderungen dort vornehmen. diff --git a/README.md b/README.md index ec4c347..63baebe 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ Live-Überwachung von Lara Kiesewetters Partien bei der **ODJM (Offene Deutsche ## Projektstruktur -``` +```text ├── app.js # Hauptlogik (Brett, UI, Auto-Refresh) ├── index.html # HTML-Grundgerüst ├── style.css # Dark-Theme-Styling @@ -42,7 +42,7 @@ Live-Überwachung von Lara Kiesewetters Partien bei der **ODJM (Offene Deutsche Der Server läuft auf `http://localhost:8111`. 2. **Öffne die App im Browser:** - ``` + ```text http://localhost:8111 ``` (Der Server serviert auch die statischen Dateien.) diff --git a/app.js b/app.js index 6258cbd..ae73105 100644 --- a/app.js +++ b/app.js @@ -3,14 +3,12 @@ * Haupt-Application */ -const PLAYER_NAME = 'Kiesewetter, Lara'; +/* global $, parsePGN, filterLaraGames, getLiveGame, getLatestGame, Chess, Chessboard */ let board = null; let chess = null; let currentGame = null; let allLaraGames = []; -let serverLastFetch = null; -let laraColor = null; let currentMoveIndex = -1; let userSelectedGame = false; let userScrolledMoves = false; @@ -89,14 +87,13 @@ function updateBoard() { // Spiegele das Brett, wenn Lara Schwarz hat const laraIsBlack = currentGame.black.toLowerCase().includes('kiesewetter'); const orientation = laraIsBlack ? 'black' : 'white'; - laraColor = laraIsBlack ? 'b' : 'w'; // Führe alle Züge aus const nonResultMoves = currentGame.moves.filter(m => !m.isResult); for (const move of nonResultMoves) { try { chess.move(move.san); - } catch (e) { + } catch { // Ignoriere ungültige Züge } } @@ -108,7 +105,7 @@ function updateBoard() { for (let i = 0; i <= currentMoveIndex && i < nonResultMoves.length; i++) { try { chess.move(nonResultMoves[i].san); - } catch (e) { + } catch { break; } } @@ -153,7 +150,7 @@ function goToMove(index) { for (let i = 0; i <= index; i++) { try { chess.move(nonResultMoves[i].san); - } catch (err) { + } catch { break; } } @@ -265,21 +262,19 @@ function highlightActivePlayer() { * Highlight den letzten Zug auf dem Brett */ function highlightLastMove() { - if (!board || !chess) return; + if (!board || !chess || !currentGame) return; + + $('#board [data-square]').removeClass('last-move-highlight'); const nonResultMoves = currentGame.moves.filter(m => !m.isResult); if (currentMoveIndex >= 0 && currentMoveIndex < nonResultMoves.length) { - const lastMove = nonResultMoves[currentMoveIndex]; - - // Parse die SAN-Züge, um Start- und Zielfelder zu finden const moves = chess.history({ verbose: true }); if (moves.length > 0) { const lastMoveData = moves[moves.length - 1]; - board.highlightSquare(lastMoveData.from, lastMoveData.to); + $(`#board [data-square="${lastMoveData.from}"]`).addClass('last-move-highlight'); + $(`#board [data-square="${lastMoveData.to}"]`).addClass('last-move-highlight'); } - } else { - board.clearHighlights(); } } @@ -501,12 +496,11 @@ async function updateStandings() { ${data.losses} `; - serverLastFetch = Date.now(); return; } } document.getElementById('standings-content').innerHTML = '