KO Bracket fixed

This commit is contained in:
2026-06-29 23:30:26 -05:00
parent 6811fc8161
commit d982ff1068
5 changed files with 110 additions and 10 deletions

View File

@@ -561,8 +561,25 @@ export function attachKOOdds(matches: Match[], teams: Team[], odds: ParsedOdds[]
const FIFA_BASE = "https://api.fifa.com/api/v3";
const FIFA_SEASON = "285023";
// FIFA-Code → App-Code (nur Abweichungen; sonst identisch)
const FIFA_CODE_OVERRIDE: Record<string, string> = {
CRO: "HRV", // Kroatien
POR: "PRT", // Portugal
SUI: "CHE", // Schweiz
};
function fifaCodeToAppCode(fifaCode: string): string {
return FIFA_CODE_OVERRIDE[fifaCode] ?? fifaCode;
}
interface FifaTeamBlock {
IdTeam: string; // FIFA-Team-ID
Abbreviation: string; // FIFA-Code (z.B. PAR, CRO)
}
interface FifaMatch {
MatchNumber: number;
Home: FifaTeamBlock | null;
Away: FifaTeamBlock | null;
HomeTeamScore: number | null;
AwayTeamScore: number | null;
HomeTeamPenaltyScore: number | null;
@@ -570,6 +587,7 @@ interface FifaMatch {
MatchStatus: number; // 0=finished, 1=scheduled, else=live
MatchTime: string | null; // z.B. "132'"
ResultType: number | null; // 1=regular, 2=penalties
Winner?: string | null; // Team-ID des Siegers
}
interface FifaScores {
@@ -580,10 +598,14 @@ interface FifaScores {
resultType: number | null;
status: MatchStatus;
matchTime: string | null;
winnerTeamId: string | null;
}
// Holt Live-Scores von der FIFA-API. Gibt Map MatchNumber → Scores zurück.
export async function fetchFifaScores(): Promise<Map<number, FifaScores>> {
// Holt Live-Scores von der FIFA-API. Gibt Map MatchNumber → Scores + FIFA-ID→App-Code-Map zurück.
export async function fetchFifaScores(): Promise<{
scores: Map<number, FifaScores>;
fifaIdToAppCode: Map<string, string>;
}> {
return cached("fifa:scores", 45_000, async () => {
const url = `${FIFA_BASE}/calendar/matches?language=de&count=500&idSeason=${FIFA_SEASON}`;
const res = await fetch(url, {
@@ -593,15 +615,24 @@ export async function fetchFifaScores(): Promise<Map<number, FifaScores>> {
});
if (!res.ok) throw new Error(`fifa ${res.status}`);
const data = (await res.json()) as { Results: FifaMatch[] };
const map = new Map<number, FifaScores>();
const scores = new Map<number, FifaScores>();
const fifaIdToAppCode = new Map<string, string>();
for (const fm of data.Results ?? []) {
// Team-Mapping sammeln
for (const tb of [fm.Home, fm.Away]) {
if (tb && !fifaIdToAppCode.has(tb.IdTeam)) {
fifaIdToAppCode.set(tb.IdTeam, fifaCodeToAppCode(tb.Abbreviation));
}
}
let status: MatchStatus;
switch (fm.MatchStatus) {
case 0: status = "FINISHED"; break;
case 1: status = "SCHEDULED"; break;
default: status = "LIVE"; break; // 2,3,... = läuft
default: status = "LIVE"; break;
}
map.set(fm.MatchNumber, {
scores.set(fm.MatchNumber, {
homeScore: fm.HomeTeamScore,
awayScore: fm.AwayTeamScore,
homePenalty: fm.HomeTeamPenaltyScore,
@@ -609,15 +640,25 @@ export async function fetchFifaScores(): Promise<Map<number, FifaScores>> {
resultType: fm.ResultType,
status,
matchTime: fm.MatchTime,
winnerTeamId: fm.Winner ?? null,
});
}
return map;
return { scores, fifaIdToAppCode };
});
}
// Wendet FIFA-Live-Scores auf Matches an (MatchNumber als exakter Schlüssel).
export function applyFifaScores(matches: Match[], fifaMap: Map<number, FifaScores>): Match[] {
export function applyFifaScores(
matches: Match[], teams: Team[],
fifaData: { scores: Map<number, FifaScores>; fifaIdToAppCode: Map<string, string> },
): Match[] {
const { scores: fifaMap, fifaIdToAppCode } = fifaData;
if (fifaMap.size === 0) return matches;
// Baue App-Code → App-Team-ID Map
const appCodeToId = new Map<string, string>();
for (const t of teams) {
if (t.code) appCodeToId.set(t.code.toLowerCase(), t.id);
}
let applied = 0;
const result = matches.map((m) => {
const fs = fifaMap.get(m.matchNumber);
@@ -627,6 +668,26 @@ export function applyFifaScores(matches: Match[], fifaMap: Map<number, FifaScore
if (fs.awayScore != null) r.awayScore = fs.awayScore;
if (fs.homePenalty != null) r.homePenalty = fs.homePenalty;
if (fs.awayPenalty != null) r.awayPenalty = fs.awayPenalty;
// FIFA-ID → App-Team-ID auflösen
if (fs.winnerTeamId) {
const appCode = fifaIdToAppCode.get(fs.winnerTeamId);
if (appCode) {
const appTeamId = appCodeToId.get(appCode.toLowerCase());
if (appTeamId) {
r.winnerTeamId = appTeamId;
} else {
console.warn("[fifa] Winner-Team-Code nicht in App-Teams:", appCode, "| matchNumber:", m.matchNumber);
}
} else {
console.warn("[fifa] FIFA-Winner-ID nicht in Team-Map:", fs.winnerTeamId, "| matchNumber:", m.matchNumber);
}
}
console.log("[FIFA-WINNER]", "matchNumber:", m.matchNumber,
"| fifa.Winner:", fs.winnerTeamId,
"| status:", r.status,
"| homeScore:", r.homeScore, "| awayScore:", r.awayScore,
"| homePenalty:", r.homePenalty, "| awayPenalty:", r.awayPenalty,
"| -> m.winnerTeamId gesetzt:", r.winnerTeamId);
if (fs.matchTime) {
const min = parseInt(fs.matchTime, 10);
if (!isNaN(min)) r.minute = min;