Fix: Züge mit unnötiger SAN-Disambiguierung (Nge7) schlagen bei chess.js fehl; Auto-Advance bei neuen Zügen im Polling

This commit is contained in:
2026-05-27 10:22:52 +02:00
parent a42fe45812
commit 8d971dbef9
3 changed files with 48 additions and 18 deletions

View File

@@ -18,6 +18,7 @@ let roundPgns = {};
let pollId = 0;
let pollInterval = null;
let updateTimer = null;
let previousMoveCount = -1;
async function fetchRoundPGN(round) {
const res = await fetch(`https://www.deutsche-schachjugend.de/2026/odjm-d/partien/${round}.pgn?t=${Date.now()}`);
@@ -44,9 +45,11 @@ async function loadPGN(showOverlay = true) {
return;
}
// Alle Runden immer frisch von der DSJ laden (mit Cache-Busting)
// Nur aktuelle/live Runden neu laden, historische bleiben gecached
const maxRound = currentRound + 1;
for (let r = 1; r <= maxRound; r++) {
const isFirstLoad = Object.keys(roundPgns).length === 0;
const startRound = isFirstLoad ? 1 : currentRound;
for (let r = startRound; r <= maxRound; r++) {
const text = await fetchRoundPGN(r);
if (currentPollId !== pollId) return;
if (text !== null) roundPgns[r] = text;
@@ -94,19 +97,27 @@ function updateBoard() {
// Führe alle Züge aus
const nonResultMoves = currentGame.moves.filter(m => !m.isResult);
// Aktuellen Move beibehalten — nie automatisch zum letzten Zug springen
// Aktuellen Move beibehalten — nie automatisch zum letzten Zug springen,
// es sei denn der Nutzer war schon am Ende und neue Züge sind dazugekommen
if (currentMoveIndex >= nonResultMoves.length || currentMoveIndex < -1) {
currentMoveIndex = nonResultMoves.length - 1;
} else if (previousMoveCount >= 0 && currentMoveIndex === previousMoveCount - 1 && nonResultMoves.length > previousMoveCount) {
// Nutzer war am letzten Zug, neue Züge sind da → vorrücken
currentMoveIndex = nonResultMoves.length - 1;
}
previousMoveCount = nonResultMoves.length;
chess = new Chess();
if (currentMoveIndex >= 0) {
for (let i = 0; i <= currentMoveIndex && i < nonResultMoves.length; i++) {
try {
chess.move(nonResultMoves[i].san);
} catch {
break;
const san = nonResultMoves[i].san;
let result = chess.move(san);
if (!result) {
// chess.js lehnt unnötige Disambiguierung ab (z.B. Nge7 wenn Nc6 gepinnt)
const cleanSan = san.replace(/^([NBRQK])([a-h])?([1-8])?([a-h][1-8].*)$/, '$1$4');
result = chess.move(cleanSan);
}
if (!result) break;
}
}
@@ -246,11 +257,14 @@ function goToMove(index) {
chess = new Chess();
for (let i = 0; i <= index; i++) {
try {
chess.move(nonResultMoves[i].san);
} catch {
break;
const san = nonResultMoves[i].san;
let result = chess.move(san);
if (!result) {
// chess.js lehnt unnötige Disambiguierung ab (z.B. Nge7 wenn Nc6 gepinnt)
const cleanSan = san.replace(/^([NBRQK])([a-h])?([1-8])?([a-h][1-8].*)$/, '$1$4');
result = chess.move(cleanSan);
}
if (!result) break;
}
board.position(chess.fen(), true);
@@ -508,12 +522,23 @@ function updateAllGamesList() {
entry.className = 'game-entry';
if (currentGame && game === currentGame) entry.classList.add('active');
const laraIsWhite = game.white.toLowerCase().includes('kiesewetter');
const laraIsWhite = game.white.toLowerCase().includes('kiesewetter');
const opponent = laraIsWhite ? game.black : game.white;
const color = laraIsWhite ? '⬜ Weiß' : '⬛ Schwarz';
let resultIcon = '';
if (game.isLive) {
resultIcon = '⏳';
} else if (game.result === '1/2-1/2') {
resultIcon = '🤝';
} else if ((laraIsWhite && game.result === '1-0') || (!laraIsWhite && game.result === '0-1')) {
resultIcon = '✅';
} else {
resultIcon = '❌';
}
entry.innerHTML = `
<div class="game-round">Runde ${game.round}</div>
<div class="game-round">${resultIcon} Runde ${game.round}</div>
<div class="game-players">Lara ${color} vs ${opponent}</div>
<div class="game-result">${game.isLive ? '● Laufen' : game.result}</div>
`;
@@ -521,6 +546,8 @@ function updateAllGamesList() {
entry.addEventListener('click', () => {
userSelectedGame = true;
currentGame = game;
previousMoveCount = -1;
currentMoveIndex = Number.MAX_SAFE_INTEGER;
updateBoard();
updatePlayerInfo();
updateMovesList();
@@ -608,7 +635,7 @@ function updateTimestamp() {
}
/**
* Startet Auto-Refresh alle 30 Sekunden
* Startet Auto-Refresh alle 15 Sekunden
*/
function startAutoRefresh() {
clearInterval(pollInterval);
@@ -626,12 +653,12 @@ function startAutoRefresh() {
if (pollId !== myId) { clearInterval(pollInterval); clearInterval(updateTimer); return; }
loadPGN(false);
lastUpdate = Date.now();
}, 30000);
}, 15000);
updateTimer = setInterval(() => {
if (pollId !== myId) { clearInterval(pollInterval); clearInterval(updateTimer); return; }
const elapsed = Date.now() - lastUpdate;
const remaining = Math.max(0, 30000 - elapsed);
const remaining = Math.max(0, 15000 - elapsed);
const s = Math.floor(remaining / 1000);
document.getElementById('refresh-timer').textContent = `${s}s`;
}, 1000);