This commit is contained in:
2026-07-04 10:17:41 -05:00
parent b727c110a2
commit 867d3c96b1

View File

@@ -670,18 +670,11 @@ function normMinuteStr(min: string | null | undefined): string {
return (min ?? "").replace(/'/g, "").replace(/\s+/g, "").trim();
}
const RECENT_FINISHED_MS = 60 * 60 * 1000; // 60 Minuten
const MATCH_DURATION_ESTIMATE = 2.5 * 60 * 60 * 1000; // 2.5h Puffer für Spiel + Pause + Nachspielzeit
function isRecentlyFinished(m: Match): boolean {
if (m.status !== "FINISHED") return false;
const kickoff = new Date(m.utcDate).getTime();
if (isNaN(kickoff)) return false;
return kickoff + MATCH_DURATION_ESTIMATE > Date.now() - RECENT_FINISHED_MS;
}
async function fetchFifaGoals(idStage: string, idMatch: string, locale: string = "de"): Promise<FifaGoalRaw[]> {
return cached(`fifa:detail:${locale}:${idMatch}`, 60_000, async () => {
async function fetchFifaGoals(
idStage: string, idMatch: string, locale: string = "de",
ttlMs: number = 60_000,
): Promise<FifaGoalRaw[]> {
return cached(`fifa:detail:${locale}:${idMatch}`, ttlMs, async () => {
const lang = locale === "en" ? "en" : "de";
const url = `${FIFA_BASE}/live/football/17/${FIFA_SEASON}/${idStage}/${idMatch}?language=${lang}`;
const res = await fetch(url, {
@@ -724,16 +717,16 @@ async function fetchFifaGoals(idStage: string, idMatch: string, locale: string =
});
}
// Lädt Tor-Details für laufende oder kürzlich beendete Spiele mit Toren.
// FINISHED-Matches werden nur innerhalb eines 60-Minuten-Fensters berücksichtigt,
// um die Request-Zahl bei 79+ Spielen im Turnierverlauf drastisch zu reduzieren.
// Lädt Tor-Details für laufende und alle beendeten Spiele mit Toren.
// Beendete Spiele werden über langlebiges Caching (24h) gespart, nicht über Ausschluss.
// Tore eines beendeten Spiels ändern sich nie mehr → einmal fetchen genügt.
export async function attachFifaGoals(
matches: Match[],
fifaData: { scores: Map<number, FifaScores>; fifaIdToAppCode: Map<string, string> },
locale: string = "de",
): Promise<Match[]> {
const targets = matches.filter(m =>
((m.status === "LIVE" || m.status === "IN_PLAY" || m.status === "PAUSED") || isRecentlyFinished(m)) &&
(m.status === "LIVE" || m.status === "IN_PLAY" || m.status === "PAUSED" || m.status === "FINISHED") &&
((m.homeScore ?? 0) + (m.awayScore ?? 0)) > 0,
);
if (targets.length === 0) return matches;
@@ -742,7 +735,9 @@ export async function attachFifaGoals(
const results = await Promise.allSettled(targets.map(async (m) => {
const fs = fifaData.scores.get(m.matchNumber);
if (!fs?.idMatch || !fs?.idStage) return;
const goals = await fetchFifaGoals(fs.idStage, fs.idMatch, locale);
const isFinished = m.status === "FINISHED";
const ttl = isFinished ? 24 * 60 * 60 * 1000 : 60_000;
const goals = await fetchFifaGoals(fs.idStage, fs.idMatch, locale, ttl);
if (goals.length) goalsByMatchId.set(m.id, goals);
}));
@@ -787,11 +782,14 @@ export async function attachFifaLiveData(
// --- Step 2: Scores auf Matches anwenden ---
const updated = applyFifaScores(matches, teams, fifaData);
// --- Step 3: Goal-Details nur für live + kürzlich beendete Matches mit Toren ---
// --- Step 3: Goal-Details für alle Spiele mit Toren (live + beendet) ---
// Requests werden durch differenzierte Cache-TTL gespart:
// beendete Spiele → 24h (Tore ändern sich nie)
// laufende Spiele → 60s (neue Tore erscheinen)
const targets = updated.filter(m => {
const fs = fifaData.scores.get(m.matchNumber);
return (
((m.status === "LIVE" || m.status === "IN_PLAY" || m.status === "PAUSED") || isRecentlyFinished(m)) &&
(m.status === "LIVE" || m.status === "IN_PLAY" || m.status === "PAUSED" || m.status === "FINISHED") &&
((m.homeScore ?? 0) + (m.awayScore ?? 0)) > 0 &&
fs?.idMatch != null &&
fs?.idStage != null
@@ -810,8 +808,10 @@ export async function attachFifaLiveData(
for (const m of targets) {
const fs = fifaData.scores.get(m.matchNumber)!;
if (!fs.idMatch || !fs.idStage) continue;
const isFinished = m.status === "FINISHED";
const ttl = isFinished ? 24 * 60 * 60 * 1000 : 60_000; // beendet: 24h, live: 60s
try {
const goals = await fetchFifaGoals(fs.idStage, fs.idMatch, locale);
const goals = await fetchFifaGoals(fs.idStage, fs.idMatch, locale, ttl);
fetched++;
if (goals.length) goalsByMatchId.set(m.id, goals);
} catch {