120 lines
5.2 KiB
TypeScript
120 lines
5.2 KiB
TypeScript
// fifa-eval.ts — Analyse-Skript: IdGroup, MatchNumber, Attendance, MatchStatus
|
||
// Ausführung: npx ts-node --compiler-options '{"module":"commonjs","target":"es2020"}' scripts/fifa-eval.ts
|
||
// Oder mit Deno, Bun: bun run scripts/fifa-eval.ts
|
||
|
||
const FIFA_BASE = "https://api.fifa.com/api/v3";
|
||
const FIFA_SEASON = "285023";
|
||
|
||
interface RawMatch {
|
||
MatchNumber: number;
|
||
MatchStatus: number;
|
||
IdGroup: string | null;
|
||
IdStage: string;
|
||
StageName: Array<{ Locale: string; Description: string }>;
|
||
GroupName?: Array<{ Locale: string; Description: string }>;
|
||
Home: { IdTeam: string; Abbreviation: string; TeamName?: Array<{ Locale: string; Description: string }> } | null;
|
||
Away: { IdTeam: string; Abbreviation: string; TeamName?: Array<{ Locale: string; Description: string }> } | null;
|
||
HomeTeamScore: number | null;
|
||
AwayTeamScore: number | null;
|
||
Attendance: string | null;
|
||
Date: string;
|
||
LocalDate: string;
|
||
}
|
||
|
||
async function main() {
|
||
console.log("📡 Rufe FIFA Calendar-Endpoint ab...");
|
||
const res = await fetch(
|
||
`${FIFA_BASE}/calendar/matches?language=de&count=500&idSeason=${FIFA_SEASON}`,
|
||
{ headers: { "User-Agent": "fifa-eval/1.0" } },
|
||
);
|
||
if (!res.ok) { console.error("Fehler:", res.status, res.statusText); process.exit(1); }
|
||
const data = (await res.json()) as { Results: RawMatch[] };
|
||
const matches = data.Results ?? [];
|
||
console.log(`✅ ${matches.length} Matches geladen\n`);
|
||
|
||
// ── A) IdGroup → GroupName Mapping ──
|
||
console.log("═══ A) IdGroup → Gruppe (A-L) ═══");
|
||
const groupMap = new Map<string, string>();
|
||
for (const m of matches) {
|
||
if (!m.IdGroup || !m.GroupName) continue;
|
||
const desc = m.GroupName.find(g => g.Locale === "de-DE")?.Description
|
||
?? m.GroupName[0]?.Description
|
||
?? `ID:${m.IdGroup}`;
|
||
if (!groupMap.has(m.IdGroup)) groupMap.set(m.IdGroup, desc);
|
||
}
|
||
console.log(`Anzahl distinct IdGroup-Werte: ${groupMap.size}`);
|
||
const sorted = [...groupMap.entries()].sort((a, b) => parseInt(a[0]) - parseInt(b[0]));
|
||
for (const [id, name] of sorted) {
|
||
console.log(` ${id} → "${name}"`);
|
||
}
|
||
// Als kopierbare Konstante
|
||
console.log("\n// Kopierbare Konstante:");
|
||
console.log("const FIFA_IDGROUP_TO_GROUP: Record<string, string> = {");
|
||
for (const [id, name] of sorted) {
|
||
const letter = name.replace(/^Gruppe\s+/, "");
|
||
console.log(` "${id}": "${letter}", // ${name}`);
|
||
}
|
||
console.log("};");
|
||
|
||
// ── B) MatchNumber-Konsistenz ──
|
||
console.log("\n═══ B) MatchNumber-Konsistenz ═══");
|
||
const groupMatches = matches.filter(m => m.IdGroup != null).sort((a, b) => a.MatchNumber - b.MatchNumber);
|
||
const koMatches = matches.filter(m => m.IdGroup == null).sort((a, b) => a.MatchNumber - b.MatchNumber);
|
||
console.log(`Gruppenspiele: ${groupMatches.length} (MatchNumber ${groupMatches[0]?.MatchNumber}–${groupMatches[groupMatches.length-1]?.MatchNumber})`);
|
||
console.log(`K.o.-Spiele: ${koMatches.length} (MatchNumber ${koMatches[0]?.MatchNumber}–${koMatches[koMatches.length-1]?.MatchNumber})`);
|
||
|
||
// Stichproben für K.o.-Slots
|
||
const checkNums = [73, 74, 76, 89, 104];
|
||
for (const n of checkNums) {
|
||
const m = matches.find(x => x.MatchNumber === n);
|
||
if (m) {
|
||
const home = m.Home?.Abbreviation ?? "?";
|
||
const away = m.Away?.Abbreviation ?? "?";
|
||
console.log(` #${n}: ${home} vs ${away} | Stage=${m.StageName?.[0]?.Description ?? "?"} | Status=${m.MatchStatus}`);
|
||
} else {
|
||
console.log(` #${n}: NICHT GEFUNDEN`);
|
||
}
|
||
}
|
||
|
||
// ── C) Attendance + Scheduled ──
|
||
console.log("\n═══ C) Attendance + Scheduled-Matches ═══");
|
||
const withAttendance = matches.filter(m => m.Attendance != null);
|
||
console.log(`Matches mit Attendance: ${withAttendance.length}`);
|
||
if (withAttendance.length > 0) {
|
||
const ex = withAttendance[0];
|
||
console.log(` Beispiel: #${ex.MatchNumber} → ${ex.Attendance}`);
|
||
}
|
||
const scheduled = matches.filter(m => m.MatchStatus === 1);
|
||
console.log(`Scheduled-Matches (Status=1): ${scheduled.length}`);
|
||
if (scheduled.length > 0) {
|
||
const ex = scheduled[0];
|
||
console.log(` Beispiel: #${ex.MatchNumber} ${ex.Home?.Abbreviation ?? "?"} vs ${ex.Away?.Abbreviation ?? "?"} | Date=${ex.Date}`);
|
||
}
|
||
|
||
// ── D) MatchStatus-Werte ──
|
||
console.log("\n═══ D) Distinct MatchStatus-Werte ═══");
|
||
const statuses = new Map<number, number>();
|
||
for (const m of matches) {
|
||
statuses.set(m.MatchStatus, (statuses.get(m.MatchStatus) ?? 0) + 1);
|
||
}
|
||
const statusLabels: Record<number, string> = { 0: "finished", 1: "scheduled", 10: "postponed", 3: "live?" };
|
||
for (const [s, c] of [...statuses.entries()].sort((a, b) => a[0] - b[0])) {
|
||
console.log(` MatchStatus ${s}: ${c} Matches ${statusLabels[s] ? `(${statusLabels[s]})` : ""}`);
|
||
}
|
||
|
||
// ── E) Stage-Werte ──
|
||
console.log("\n═══ E) Distinct Stages ═══");
|
||
const stages = new Map<string, number>();
|
||
for (const m of matches) {
|
||
const sn = m.StageName?.[0]?.Description ?? String(m.IdStage);
|
||
stages.set(sn, (stages.get(sn) ?? 0) + 1);
|
||
}
|
||
for (const [s, c] of stages.entries()) {
|
||
console.log(` "${s}" (IdStage=${matches.find(m => (m.StageName?.[0]?.Description ?? "") === s)?.IdStage}): ${c}`);
|
||
}
|
||
|
||
console.log("\n✅ Analyse abgeschlossen.");
|
||
}
|
||
|
||
main().catch(console.error);
|