migration to new feed source
This commit is contained in:
50
scripts/download-flags.ts
Normal file
50
scripts/download-flags.ts
Normal file
@@ -0,0 +1,50 @@
|
||||
// download-flags.ts — Lädt circle-flags SVGs für alle Teams aus TLA_TO_ISO2.
|
||||
// Ausführung: npx tsx scripts/download-flags.ts
|
||||
|
||||
import { TLA_TO_ISO2 } from "../lib/flags";
|
||||
import * as fs from "fs";
|
||||
import * as path from "path";
|
||||
|
||||
const BASE = "https://hatscripts.github.io/circle-flags/flags";
|
||||
const OUT = path.join(__dirname, "..", "public", "flags");
|
||||
|
||||
async function main() {
|
||||
const codes = Object.values(TLA_TO_ISO2);
|
||||
const unique = [...new Set(codes)];
|
||||
console.log(`Lade ${unique.length} Flaggen (${codes.length} Team-Codes)...`);
|
||||
|
||||
if (!fs.existsSync(OUT)) fs.mkdirSync(OUT, { recursive: true });
|
||||
|
||||
let ok = 0;
|
||||
let failed = 0;
|
||||
for (const iso2 of unique) {
|
||||
const url = `${BASE}/${iso2}.svg`;
|
||||
try {
|
||||
const res = await fetch(url, {
|
||||
headers: { "User-Agent": "circle-flags-download/1.0" },
|
||||
});
|
||||
if (!res.ok) {
|
||||
console.warn(` ❌ ${iso2}: HTTP ${res.status}`);
|
||||
failed++;
|
||||
continue;
|
||||
}
|
||||
const svg = await res.text();
|
||||
// Prüfen: keine leere/Fehler-SVG (<10 Bytes = kaputt)
|
||||
if (svg.trim().length < 10) {
|
||||
console.warn(` ❌ ${iso2}: leere SVG (${svg.length} Bytes)`);
|
||||
failed++;
|
||||
continue;
|
||||
}
|
||||
fs.writeFileSync(path.join(OUT, `${iso2}.svg`), svg);
|
||||
ok++;
|
||||
} catch (err) {
|
||||
console.warn(` ❌ ${iso2}: ${err instanceof Error ? err.message : err}`);
|
||||
failed++;
|
||||
}
|
||||
}
|
||||
|
||||
console.log(`\n✅ ${ok} OK, ❌ ${failed} fehlgeschlagen`);
|
||||
if (failed > 0) process.exit(1);
|
||||
}
|
||||
|
||||
main();
|
||||
119
scripts/fifa-eval.ts
Normal file
119
scripts/fifa-eval.ts
Normal file
@@ -0,0 +1,119 @@
|
||||
// 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);
|
||||
Reference in New Issue
Block a user