Remove proxy - load data directly from DSJ

This commit is contained in:
2026-05-24 17:37:22 +02:00
parent 3944c7d5bb
commit 20a59166a8
2 changed files with 127 additions and 324 deletions

141
app.js
View File

@@ -19,7 +19,7 @@ let roundPgns = {};
let pollId = 0;
async function fetchRoundPGN(round) {
const res = await fetch(`http://localhost:8111/pgn/${round}`);
const res = await fetch(`https://www.deutsche-schachjugend.de/2026/odjm-d/partien/${round}.pgn`);
if (!res.ok) return null;
return await res.text();
}
@@ -28,7 +28,7 @@ async function loadPGN(showOverlay = true) {
const currentPollId = pollId;
if (showOverlay) showLoading(true);
hideError();
try {
await updateStandings();
@@ -45,8 +45,6 @@ async function loadPGN(showOverlay = true) {
}
}
const statusResponse = await fetch('http://localhost:8111/status').catch(() => null);
// Aktuelle Runde immer frisch holen
const pgnText = await fetchRoundPGN(currentRound);
if (currentPollId !== pollId) return;
@@ -59,21 +57,16 @@ async function loadPGN(showOverlay = true) {
if (text) roundPgns[nextRound] = text;
}
if (statusResponse && statusResponse.ok) {
const status = await statusResponse.json();
serverLastFetch = status.last_fetch ? status.last_fetch * 1000 : null;
}
// Alle PGNs kombinieren
const combinedPgn = Object.values(roundPgns).join('\n\n');
const allGames = parsePGN(combinedPgn);
allLaraGames = filterLaraGames(allGames);
if (allLaraGames.length === 0) {
showError('Keine Partien von Lara gefunden.');
return;
}
if (!userSelectedGame) {
const liveGame = getLiveGame(allLaraGames);
const newGame = liveGame || getLatestGame(allLaraGames);
@@ -89,7 +82,7 @@ async function loadPGN(showOverlay = true) {
updateTimestamp();
showLoading(false);
} catch (error) {
if (currentPollId !== pollId) return;
console.error('Fehler beim Laden:', error);
@@ -137,6 +130,7 @@ function updateBoard() {
if (board) {
board.position(chess.fen(), true);
board.orientation(orientation);
highlightLastMove();
} else {
board = Chessboard('board', {
position: chess.fen(),
@@ -179,6 +173,7 @@ function goToMove(index) {
board.position(chess.fen(), true);
highlightActivePlayer();
highlightLastMove();
updateClocks(index);
document.querySelectorAll('#moves-list .move').forEach(el => el.classList.remove('current'));
@@ -279,6 +274,28 @@ function highlightActivePlayer() {
}
}
/**
* Highlight den letzten Zug auf dem Brett
*/
function highlightLastMove() {
if (!board || !chess) return;
const nonResultMoves = currentGame.moves.filter(m => !m.isResult);
if (currentMoveIndex >= 0 && currentMoveIndex < nonResultMoves.length) {
const lastMove = nonResultMoves[currentMoveIndex];
// Parse die SAN-Züge, um Start- und Zielfelder zu finden
const moves = chess.history({ verbose: true });
if (moves.length > 0) {
const lastMoveData = moves[moves.length - 1];
board.highlightSquare(lastMoveData.from, lastMoveData.to);
}
} else {
board.clearHighlights();
}
}
/**
* Aktualisiert die Zugliste
*/
@@ -394,43 +411,73 @@ function updateAllGamesList() {
}
/**
* Lädt die Turniertabelle vom Proxy und zeigt Laras Platzierung an
* Lädt die Turniertabelle vom DSJ und zeigt Laras Platzierung an
*/
async function updateStandings() {
try {
const res = await fetch('http://localhost:8111/standings');
const res = await fetch('https://www.deutsche-schachjugend.de/2026/odjm-d/tabelle/');
if (!res.ok) throw new Error('Fehler beim Laden');
const data = await res.json();
if (data && data.round) currentRound = data.round;
const container = document.getElementById('standings-content');
if (!data || data.error) {
container.innerHTML = '<div class="standings-loading">Daten nicht verfügbar</div>';
return;
const html = await res.text();
const roundMatch = html.match(/Tabellenstand\s+nach\s+der\s+(\d+)\.\s*Runde/);
if (roundMatch) {
currentRound = parseInt(roundMatch[1]);
}
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>
`;
const rows = html.matchAll(/<tr[^>]*>(.*?)<\/tr>/gs);
for (const row of rows) {
if (!row[1].includes('Lara Kiesewetter')) continue;
const cells = row[1].matchAll(/<td[^>]*>(.*?)<\/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');
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>
`;
serverLastFetch = Date.now();
return;
}
}
document.getElementById('standings-content').innerHTML = '<div class="standings-loading">Daten nicht verfügbar</div>';
} catch (err) {
document.getElementById('standings-content').innerHTML =
'<div class="standings-loading">Daten nicht verfügbar</div>';
document.getElementById('standings-content').innerHTML = '<div class="standings-loading">Daten nicht verfügbar</div>';
}
}
@@ -447,8 +494,8 @@ function formatClock(clockStr) {
* Update timestamp
*/
function updateTimestamp() {
const time = serverLastFetch ? new Date(serverLastFetch) : new Date();
document.getElementById('last-update').textContent =
const time = new Date();
document.getElementById('last-update').textContent =
`Letztes Update: ${time.toLocaleTimeString('de-DE')}`;
}
@@ -473,7 +520,9 @@ function startAutoRefresh() {
timer = setInterval(() => {
if (pollId !== myId) { clearInterval(pollInterval); clearInterval(timer); return; }
const s = Math.floor((Date.now() - lastUpdate) / 1000);
const elapsed = Date.now() - lastUpdate;
const remaining = Math.max(0, 30000 - elapsed);
const s = Math.floor(remaining / 1000);
document.getElementById('refresh-timer').textContent = `${s}s`;
}, 1000);
}