feat: deployment support and production readiness
- Add deployment section to README (systemd, Docker, nginx reverse proxy) - Add environment variable support to server.py (PORT, PGN_URL, CACHE_TTL) - Update .gitignore for Python artifacts and lara-chess directory - Improve board/navigation UX in app.js (userScrolledMoves tracking, updateClocks function, better game switching)
This commit is contained in:
72
app.js
72
app.js
@@ -4,7 +4,7 @@
|
||||
*/
|
||||
|
||||
const PGN_URL = 'https://www.deutsche-schachjugend.de/2026/odjm-d/partien/gesamt-utf8.pgn';
|
||||
const REFRESH_INTERVAL = 60000; // 60 Sekunden
|
||||
const REFRESH_INTERVAL = 10000; // 10 Sekunden
|
||||
const PLAYER_NAME = 'Kiesewetter, Lara';
|
||||
|
||||
let board = null;
|
||||
@@ -17,12 +17,13 @@ let serverLastFetch = null;
|
||||
let laraColor = null;
|
||||
let currentMoveIndex = -1;
|
||||
let userSelectedGame = false;
|
||||
let userScrolledMoves = false;
|
||||
|
||||
/**
|
||||
* Lädt die PGN-Datei und aktualisiert die Anzeige
|
||||
*/
|
||||
async function loadPGN() {
|
||||
showLoading(true);
|
||||
async function loadPGN(showOverlay = true) {
|
||||
if (showOverlay) showLoading(true);
|
||||
hideError();
|
||||
|
||||
try {
|
||||
@@ -50,7 +51,11 @@ async function loadPGN() {
|
||||
// Nur automatisch wechseln, wenn der Benutzer keine andere Partie ausgewählt hat
|
||||
if (!userSelectedGame) {
|
||||
const liveGame = getLiveGame(allLaraGames);
|
||||
currentGame = liveGame || getLatestGame(allLaraGames);
|
||||
const newGame = liveGame || getLatestGame(allLaraGames);
|
||||
if (newGame !== currentGame) {
|
||||
userScrolledMoves = false;
|
||||
}
|
||||
currentGame = newGame;
|
||||
}
|
||||
updateBoard();
|
||||
updatePlayerInfo();
|
||||
@@ -89,7 +94,19 @@ function updateBoard() {
|
||||
// Ignoriere ungültige Züge
|
||||
}
|
||||
}
|
||||
currentMoveIndex = nonResultMoves.length - 1;
|
||||
if (!userScrolledMoves) {
|
||||
currentMoveIndex = nonResultMoves.length - 1;
|
||||
} else if (currentMoveIndex >= 0) {
|
||||
// Benutzer hat navigiert – zeige Brett an seinem ausgewählten Zug
|
||||
chess = new Chess();
|
||||
for (let i = 0; i <= currentMoveIndex && i < nonResultMoves.length; i++) {
|
||||
try {
|
||||
chess.move(nonResultMoves[i].san);
|
||||
} catch (e) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (board) {
|
||||
board.position(chess.fen(), true);
|
||||
@@ -122,6 +139,7 @@ function goToMove(index) {
|
||||
if (index < -1) index = -1;
|
||||
if (index >= nonResultMoves.length) index = nonResultMoves.length - 1;
|
||||
|
||||
userScrolledMoves = index < nonResultMoves.length - 1;
|
||||
currentMoveIndex = index;
|
||||
|
||||
chess = new Chess();
|
||||
@@ -135,6 +153,7 @@ function goToMove(index) {
|
||||
|
||||
board.position(chess.fen(), true);
|
||||
highlightActivePlayer();
|
||||
updateClocks(index);
|
||||
|
||||
document.querySelectorAll('#moves-list .move').forEach(el => el.classList.remove('current'));
|
||||
if (index >= 0) {
|
||||
@@ -153,26 +172,24 @@ function updatePlayerInfo() {
|
||||
|
||||
const laraPlayer = laraIsWhite ? currentGame.white : currentGame.black;
|
||||
const laraElo = laraIsWhite ? currentGame.whiteElo : currentGame.blackElo;
|
||||
const laraClock = laraIsWhite ? currentGame.whiteClock : currentGame.blackClock;
|
||||
const laraEmoji = laraIsWhite ? '⬜' : '⬛';
|
||||
|
||||
const oppPlayer = laraIsWhite ? currentGame.black : currentGame.white;
|
||||
const oppElo = laraIsWhite ? currentGame.blackElo : currentGame.whiteElo;
|
||||
const oppClock = laraIsWhite ? currentGame.blackClock : currentGame.whiteClock;
|
||||
const oppEmoji = laraIsWhite ? '⬛' : '⬜';
|
||||
|
||||
// Top-Panel (player-black) = Gegner
|
||||
document.getElementById('black-name').textContent = oppPlayer;
|
||||
document.getElementById('black-elo').textContent = oppElo ? `(ELO: ${oppElo})` : '';
|
||||
document.getElementById('black-clock').textContent = formatClock(oppClock);
|
||||
document.querySelector('#player-black .player-avatar').textContent = oppEmoji;
|
||||
|
||||
// Bottom-Panel (player-white) = Lara
|
||||
document.getElementById('white-name').textContent = laraPlayer;
|
||||
document.getElementById('white-elo').textContent = laraElo ? `(ELO: ${laraElo})` : '';
|
||||
document.getElementById('white-clock').textContent = formatClock(laraClock);
|
||||
document.querySelector('#player-white .player-avatar').textContent = laraEmoji;
|
||||
|
||||
updateClocks(currentMoveIndex);
|
||||
|
||||
// Round info
|
||||
const roundInfo = `Runde ${currentGame.round} – ${currentGame.event || 'Turnier'}`;
|
||||
document.getElementById('round-info').textContent = roundInfo;
|
||||
@@ -186,6 +203,34 @@ function updatePlayerInfo() {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Aktualisiert die Uhrenanzeige basierend auf dem aktuellen Zugindex
|
||||
*/
|
||||
function updateClocks(moveIndex) {
|
||||
if (!currentGame) return;
|
||||
|
||||
const laraIsWhite = currentGame.white.toLowerCase().includes('kiesewetter');
|
||||
|
||||
let whiteClock, blackClock;
|
||||
|
||||
if (moveIndex < 0) {
|
||||
whiteClock = currentGame.whiteClock;
|
||||
blackClock = currentGame.blackClock;
|
||||
} else {
|
||||
const nonResultMoves = currentGame.moves.filter(m => !m.isResult);
|
||||
if (moveIndex < nonResultMoves.length) {
|
||||
whiteClock = nonResultMoves[moveIndex].whiteClock;
|
||||
blackClock = nonResultMoves[moveIndex].blackClock;
|
||||
}
|
||||
}
|
||||
|
||||
const laraClock = laraIsWhite ? whiteClock : blackClock;
|
||||
const oppClock = laraIsWhite ? blackClock : whiteClock;
|
||||
|
||||
document.getElementById('black-clock').textContent = formatClock(oppClock);
|
||||
document.getElementById('white-clock').textContent = formatClock(laraClock);
|
||||
}
|
||||
|
||||
/**
|
||||
* Highlight den Spieler, der gerade am Zug ist
|
||||
*/
|
||||
@@ -267,8 +312,10 @@ function updateMovesList() {
|
||||
if (curMove) curMove.classList.add('current');
|
||||
}
|
||||
|
||||
// Scroll to bottom
|
||||
movesList.scrollTop = movesList.scrollHeight;
|
||||
// Scroll to bottom nur wenn Benutzer nicht manuell navigiert hat
|
||||
if (!userScrolledMoves) {
|
||||
movesList.scrollTop = movesList.scrollHeight;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -308,6 +355,7 @@ function updateAllGamesList() {
|
||||
|
||||
entry.addEventListener('click', () => {
|
||||
userSelectedGame = true;
|
||||
userScrolledMoves = false;
|
||||
currentGame = game;
|
||||
updateBoard();
|
||||
updatePlayerInfo();
|
||||
@@ -354,7 +402,7 @@ function startAutoRefresh() {
|
||||
|
||||
if (countdown <= 0) {
|
||||
countdown = REFRESH_INTERVAL / 1000;
|
||||
loadPGN();
|
||||
loadPGN(false);
|
||||
}
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user