/** * Lara Kiesewetter – Live Schachturnier * Data fetching, PGN loading, standings, auto-refresh */ /* global parsePGN, filterLaraGames, getLiveGame, getTodaysGames, getLatestGame */ async function fetchRoundPGN(round) { const res = await fetch(`https://www.deutsche-schachjugend.de/2026/odjm-d/partien/${round}.pgn?t=${Date.now()}`); if (!res.ok) return null; const buf = await res.arrayBuffer(); let text = new TextDecoder('utf-8').decode(buf); if (text.includes('\uFFFD')) { text = new TextDecoder('iso-8859-1').decode(buf); } return text; } async function loadPGN(showOverlay = true) { const currentPollId = pollId; if (showOverlay) showLoading(true); hideError(); try { if (currentRound === 0) { if (showOverlay) showLoading(false); return; } const maxRound = currentRound + 1; 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; } const combinedPgn = Object.values(roundPgns).join('\n\n'); const allGames = parsePGN(combinedPgn); allLaraGames = filterLaraGames(allGames); if (allLaraGames.length === 0) { return; } if (!userSelectedGame) { const liveGame = getLiveGame(allLaraGames); const todaysGames = getTodaysGames(allLaraGames); currentGame = liveGame || (todaysGames.length > 0 ? getLatestGame(todaysGames) : getLatestGame(allLaraGames)); } updateBoard(); updatePlayerInfo(); updateMovesList(); updateAllGamesList(); updatePGNDisplay(); updateTimestamp(); showLoading(false); } catch (error) { if (currentPollId !== pollId) return; console.error('Fehler beim Laden:', error); showLoading(false); } } async function updateStandings() { try { const res = await fetch(`https://www.deutsche-schachjugend.de/2026/odjm-d/tabelle/?t=${Date.now()}`); if (!res.ok) throw new Error('Fehler beim Laden'); const html = await res.text(); const roundMatch = html.match(/Tabellenstand\s+nach\s+der\s+(\d+)\.\s*Runde/); if (roundMatch) { currentRound = parseInt(roundMatch[1]); } const rows = html.matchAll(/]*>(.*?)<\/tr>/gs); for (const row of rows) { if (!row[1].includes('Lara Kiesewetter')) continue; const cells = row[1].matchAll(/]*>(.*?)<\/td>/gs); const clean = []; for (const cell of cells) { clean.push(cell[1].replace(/<[^>]+>/g, '').trim()); } if (clean.length >= 9) { const data = { rank: clean[0], player: 'Lara Kiesewetter', wins: clean[5], draws: clean[6], losses: clean[7], points: clean[8], round_info: roundMatch ? `nach der ${roundMatch[1]}. Runde` : '', round: currentRound, }; const container = document.getElementById('standings-content'); container.innerHTML = `
${data.rank}.
${data.round_info || 'nach Runde 1'}
Punkte ${data.points}
Siege ${data.wins}
Unentschieden ${data.draws}
Niederlagen ${data.losses}
`; return; } } document.getElementById('standings-content').innerHTML = '
Daten nicht verfügbar
'; } catch { document.getElementById('standings-content').innerHTML = '
Daten nicht verfügbar
'; } } function updateTimestamp() { const time = new Date(); document.getElementById('last-update').textContent = `Letztes Update: ${time.toLocaleTimeString('de-DE')}`; } async function startAutoRefresh() { clearInterval(pollInterval); clearInterval(updateTimer); clearInterval(standingsInterval); const myId = ++pollId; let lastUpdate = Date.now(); document.getElementById('refresh-timer').textContent = '0s'; document.getElementById('refresh-timer').style.color = '#4ade80'; await updateStandings(); loadPGN(true); pollInterval = setInterval(() => { if (pollId !== myId) { clearInterval(pollInterval); clearInterval(updateTimer); clearInterval(standingsInterval); return; } loadPGN(false); lastUpdate = Date.now(); }, 15000); updateTimer = setInterval(() => { if (pollId !== myId) { clearInterval(pollInterval); clearInterval(updateTimer); clearInterval(standingsInterval); return; } const elapsed = Date.now() - lastUpdate; const remaining = Math.max(0, 15000 - elapsed); const s = Math.floor(remaining / 1000); document.getElementById('refresh-timer').textContent = `${s}s`; }, 1000); standingsInterval = setInterval(() => { if (pollId !== myId) { clearInterval(pollInterval); clearInterval(updateTimer); clearInterval(standingsInterval); return; } updateStandings(); }, 1800000); }