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:
61
js/app.js
61
js/app.js
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user