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