Switch to Long-Polling, add Turniertabellen-Anzeige für ODJM D 2026
This commit is contained in:
88
app.js
88
app.js
@@ -3,37 +3,40 @@
|
||||
* Haupt-Application
|
||||
*/
|
||||
|
||||
const PGN_URL = 'https://www.deutsche-schachjugend.de/2026/odjm-d/partien/gesamt-utf8.pgn';
|
||||
const REFRESH_INTERVAL = 10000; // 10 Sekunden
|
||||
const PLAYER_NAME = 'Kiesewetter, Lara';
|
||||
|
||||
let board = null;
|
||||
let chess = null;
|
||||
let currentGame = null;
|
||||
let allLaraGames = [];
|
||||
let refreshTimer = null;
|
||||
let countdown = 0;
|
||||
let serverLastFetch = null;
|
||||
let laraColor = null;
|
||||
let currentMoveIndex = -1;
|
||||
let userSelectedGame = false;
|
||||
let userScrolledMoves = false;
|
||||
let lastMtime = 0;
|
||||
let pollId = 0;
|
||||
|
||||
/**
|
||||
* Lädt die PGN-Datei und aktualisiert die Anzeige
|
||||
*/
|
||||
async function loadPGN(showOverlay = true) {
|
||||
const currentPollId = ++pollId;
|
||||
if (showOverlay) showLoading(true);
|
||||
hideError();
|
||||
|
||||
try {
|
||||
const [pgnResponse, statusResponse] = await Promise.all([
|
||||
fetch('http://localhost:8111/pgn'),
|
||||
fetch(`http://localhost:8111/pgn?since=${lastMtime}`),
|
||||
fetch('http://localhost:8111/status').catch(() => null)
|
||||
]);
|
||||
|
||||
if (currentPollId !== pollId) return;
|
||||
if (!pgnResponse.ok) throw new Error(`HTTP ${pgnResponse.status}`);
|
||||
|
||||
const mtimeHeader = pgnResponse.headers.get('X-Cache-Mtime');
|
||||
if (mtimeHeader) lastMtime = parseFloat(mtimeHeader);
|
||||
|
||||
if (statusResponse && statusResponse.ok) {
|
||||
const status = await statusResponse.json();
|
||||
serverLastFetch = status.last_fetch ? status.last_fetch * 1000 : null;
|
||||
@@ -62,10 +65,12 @@ async function loadPGN(showOverlay = true) {
|
||||
updateMovesList();
|
||||
updateAllGamesList();
|
||||
updateTimestamp();
|
||||
updateStandings();
|
||||
|
||||
showLoading(false);
|
||||
|
||||
} catch (error) {
|
||||
if (currentPollId !== pollId) return;
|
||||
console.error('Fehler beim Laden:', error);
|
||||
showError(`Fehler: ${error.message}`);
|
||||
showLoading(false);
|
||||
@@ -367,6 +372,49 @@ function updateAllGamesList() {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Lädt die Turniertabelle vom Proxy und zeigt Laras Platzierung an
|
||||
*/
|
||||
function updateStandings() {
|
||||
fetch('http://localhost:8111/standings')
|
||||
.then(res => {
|
||||
if (!res.ok) throw new Error('Fehler beim Laden');
|
||||
return res.json();
|
||||
})
|
||||
.then(data => {
|
||||
const container = document.getElementById('standings-content');
|
||||
if (!data || data.error) {
|
||||
container.innerHTML = '<div class="standings-loading">Daten nicht verfügbar</div>';
|
||||
return;
|
||||
}
|
||||
container.innerHTML = `
|
||||
<div class="standings-rank">${data.rank}.</div>
|
||||
<div class="standings-rank-label">Tabellenplatz</div>
|
||||
<div class="standings-header">${data.round_info || 'nach Runde 1'}</div>
|
||||
<div class="standings-row">
|
||||
<span class="standings-label">Punkte</span>
|
||||
<span class="standings-value">${data.points}</span>
|
||||
</div>
|
||||
<div class="standings-row">
|
||||
<span class="standings-label">Siege</span>
|
||||
<span class="standings-value">${data.wins}</span>
|
||||
</div>
|
||||
<div class="standings-row">
|
||||
<span class="standings-label">Unentschieden</span>
|
||||
<span class="standings-value">${data.draws}</span>
|
||||
</div>
|
||||
<div class="standings-row">
|
||||
<span class="standings-label">Niederlagen</span>
|
||||
<span class="standings-value">${data.losses}</span>
|
||||
</div>
|
||||
`;
|
||||
})
|
||||
.catch(err => {
|
||||
document.getElementById('standings-content').innerHTML =
|
||||
'<div class="standings-loading">Daten nicht verfügbar</div>';
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Format clock string
|
||||
*/
|
||||
@@ -386,25 +434,19 @@ function updateTimestamp() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Start auto-refresh
|
||||
* Start long-polling: nach jeder Antwort sofort die nächste Anfrage stellen
|
||||
*/
|
||||
function startAutoRefresh() {
|
||||
countdown = REFRESH_INTERVAL / 1000;
|
||||
document.getElementById('refresh-timer').textContent = '● Live';
|
||||
document.getElementById('refresh-timer').style.color = '#4ade80';
|
||||
|
||||
if (refreshTimer) clearInterval(refreshTimer);
|
||||
|
||||
refreshTimer = setInterval(() => {
|
||||
countdown--;
|
||||
const mins = Math.floor(countdown / 60);
|
||||
const secs = countdown % 60;
|
||||
document.getElementById('refresh-timer').textContent =
|
||||
`Nächstes Update in: ${String(mins).padStart(2, '0')}:${String(secs).padStart(2, '0')}`;
|
||||
|
||||
if (countdown <= 0) {
|
||||
countdown = REFRESH_INTERVAL / 1000;
|
||||
loadPGN(false);
|
||||
async function poll() {
|
||||
while (true) {
|
||||
await loadPGN(false);
|
||||
await new Promise(r => setTimeout(r, 30000));
|
||||
}
|
||||
}, 1000);
|
||||
}
|
||||
poll();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -424,11 +466,11 @@ function hideError() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Manual refresh button
|
||||
* Manual refresh button – startet neuen Long-Poll-Zyklus
|
||||
*/
|
||||
document.getElementById('refresh-btn').addEventListener('click', () => {
|
||||
countdown = REFRESH_INTERVAL / 1000;
|
||||
loadPGN();
|
||||
pollId++;
|
||||
loadPGN(true);
|
||||
});
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user