KO round
This commit is contained in:
80
lib/feeds.ts
80
lib/feeds.ts
@@ -568,6 +568,8 @@ interface Wc26Game {
|
||||
home_score?: string;
|
||||
away_score?: string;
|
||||
time_elapsed?: string;
|
||||
goals?: Array<{ name?: string; minute?: string; team?: string }>;
|
||||
current_minute?: string;
|
||||
}
|
||||
|
||||
interface LiveScore {
|
||||
@@ -667,4 +669,82 @@ export function applyLiveScores(
|
||||
}
|
||||
if (applied > 0) console.log("[worldcup26] auf matches angewandt:", applied);
|
||||
return result;
|
||||
}
|
||||
|
||||
// Holt KO-Live-Daten von worldcup26 (Tore, Minute) und hängt sie an die Feed-Matches.
|
||||
export async function fetchKOLiveData(): Promise<Wc26Game[]> {
|
||||
try {
|
||||
const res = await fetch(`${WC26_BASE}/get/games`, {
|
||||
cache: "no-store",
|
||||
headers: { "User-Agent": "wm2026-board/1.0" },
|
||||
signal: AbortSignal.timeout(5000),
|
||||
});
|
||||
if (!res.ok) throw new Error(`worldcup26 ${res.status}`);
|
||||
const data = (await res.json()) as { games: Wc26Game[] };
|
||||
return (data.games ?? []).filter(g => {
|
||||
const grp = (g.group ?? "").toUpperCase();
|
||||
return grp === "" || grp === "R32" || grp === "R16" || grp === "QF" || grp === "SF" || grp === "3RD" || grp === "FINAL" || grp === "FINALIST";
|
||||
});
|
||||
} catch {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
// Hängt worldcup26-KO-Live-Daten an die Matches an (Tore, Minute, Scores).
|
||||
export function attachKOLiveData(matches: Match[], teams: Team[], koGames: Wc26Game[]): Match[] {
|
||||
if (koGames.length === 0) return matches;
|
||||
|
||||
const nameById = new Map<string, string>();
|
||||
for (const t of teams) {
|
||||
const nn = normName(t.name);
|
||||
if (!nameById.has(nn)) nameById.set(nn, t.id);
|
||||
}
|
||||
|
||||
return matches.map((m) => {
|
||||
if (m.group != null) return m; // nur K.o.-Spiele
|
||||
|
||||
const hId = m.homeTeamId;
|
||||
const aId = m.awayTeamId;
|
||||
const hName = hId ? teams.find(t => t.id === hId)?.name : null;
|
||||
const aName = aId ? teams.find(t => t.id === aId)?.name : null;
|
||||
|
||||
// Finde worldcup26-Spiel über Teamnamen
|
||||
const wm = koGames.find(g => {
|
||||
if (!hName || !aName) return false;
|
||||
const gh = normName(g.home_team_name_en ?? "");
|
||||
const ga = normName(g.away_team_name_en ?? "");
|
||||
return (gh === normName(hName) && ga === normName(aName)) ||
|
||||
(gh === normName(aName) && ga === normName(hName));
|
||||
});
|
||||
|
||||
if (!wm) return m;
|
||||
|
||||
const result = { ...m };
|
||||
|
||||
// Live-Score + Status
|
||||
if (wm.time_elapsed === "live" || wm.time_elapsed === "finished") {
|
||||
result.status = wm.time_elapsed === "finished" ? "FINISHED" : "IN_PLAY";
|
||||
const hs = parseScore(wm.home_score);
|
||||
const as = parseScore(wm.away_score);
|
||||
if (hs != null) result.homeScore = hs;
|
||||
if (as != null) result.awayScore = as;
|
||||
}
|
||||
|
||||
// Spielminute
|
||||
if (wm.current_minute) {
|
||||
const min = parseInt(wm.current_minute, 10);
|
||||
if (!isNaN(min)) result.minute = min;
|
||||
}
|
||||
|
||||
// Torereignisse
|
||||
if (wm.goals && wm.goals.length > 0) {
|
||||
result.goals = wm.goals.map(g => ({
|
||||
scorer: g.name ?? "?",
|
||||
minute: parseInt(g.minute ?? "0", 10) || 0,
|
||||
team: g.team?.toLowerCase() === "away" ? "away" as const : "home" as const,
|
||||
}));
|
||||
}
|
||||
|
||||
return result;
|
||||
});
|
||||
}
|
||||
@@ -21,6 +21,12 @@ export interface Team {
|
||||
export type MatchStatus =
|
||||
| "SCHEDULED" | "LIVE" | "IN_PLAY" | "PAUSED" | "FINISHED";
|
||||
|
||||
export interface GoalEvent {
|
||||
scorer: string; // Torschützen-Name
|
||||
minute: number; // Spielminute
|
||||
team: "home" | "away";
|
||||
}
|
||||
|
||||
export interface Match {
|
||||
id: string;
|
||||
group: GroupId | null; // null = K.o.-Spiel
|
||||
@@ -37,6 +43,7 @@ export interface Match {
|
||||
prob?: { home: number; draw: number; away: number } | null;
|
||||
venue?: string | null; // Austragungsort
|
||||
attendance?: number | null; // Zuschauerzahl, falls verfügbar
|
||||
goals?: GoalEvent[] | null; // Torereignisse von worldcup26.ir
|
||||
}
|
||||
|
||||
// Eine berechnete Tabellenzeile innerhalb einer Gruppe.
|
||||
|
||||
Reference in New Issue
Block a user