207 lines
7.8 KiB
TypeScript
207 lines
7.8 KiB
TypeScript
// Stadion-Zuordnung — die alleinige Quelle für Spielorte (Feed-venue wird ignoriert).
|
|
//
|
|
// Gruppenphase: über die Teampaarung (Ländercodes). Eindeutig, da jede Paarung
|
|
// im Turnier genau einmal vorkommt — unabhängig von Heim/Auswärts-Reihenfolge
|
|
// und von gleichzeitigen Anstößen.
|
|
// K.o.-Phase: über die FIFA-Spielnummer (dort sind die Anstöße eindeutig).
|
|
|
|
import { GroupId, Match, Team } from "./types";
|
|
|
|
// --- GRUPPENPHASE: "CODE1-CODE2" -> Stadion ---
|
|
export const FIXTURES_GROUP_STAGE: Record<string, string> = {
|
|
// Gruppe A
|
|
"MEX-RSA": "Estadio Azteca, Mexiko-Stadt",
|
|
"KOR-CZE": "Estadio Akron, Guadalajara",
|
|
"CZE-RSA": "Mercedes-Benz Stadium, Atlanta",
|
|
"MEX-KOR": "Estadio Akron, Guadalajara",
|
|
"CZE-MEX": "Estadio Azteca, Mexiko-Stadt",
|
|
"RSA-KOR": "Estadio BBVA, Monterrey",
|
|
// Gruppe B
|
|
"CAN-BIH": "BMO Field, Toronto",
|
|
"QAT-SUI": "Levi's Stadium, San Francisco Bay Area",
|
|
"SUI-BIH": "SoFi Stadium, Los Angeles",
|
|
"CAN-QAT": "BC Place, Vancouver",
|
|
"SUI-CAN": "BC Place, Vancouver",
|
|
"BIH-QAT": "Lumen Field, Seattle",
|
|
// Gruppe C
|
|
"BRA-MAR": "Gillette Stadium, Boston",
|
|
"HAI-SCO": "MetLife Stadium, New York/New Jersey",
|
|
"BRA-HAI": "Lincoln Financial Field, Philadelphia",
|
|
"SCO-MAR": "Gillette Stadium, Boston",
|
|
"SCO-BRA": "Hard Rock Stadium, Miami",
|
|
"MAR-HAI": "Mercedes-Benz Stadium, Atlanta",
|
|
// Gruppe D
|
|
"USA-PAR": "SoFi Stadium, Los Angeles",
|
|
"AUS-TUR": "BC Place, Vancouver",
|
|
"TUR-PAR": "Levi's Stadium, San Francisco Bay Area",
|
|
"USA-AUS": "Lumen Field, Seattle",
|
|
"TUR-USA": "SoFi Stadium, Los Angeles",
|
|
"PAR-AUS": "Levi's Stadium, San Francisco Bay Area",
|
|
// Gruppe E
|
|
"CIV-ECU": "Lincoln Financial Field, Philadelphia",
|
|
"GER-CUR": "NRG Stadium, Houston",
|
|
"GER-CIV": "BMO Field, Toronto",
|
|
"ECU-CUR": "Arrowhead Stadium, Kansas City",
|
|
"CUR-CIV": "Lincoln Financial Field, Philadelphia",
|
|
"ECU-GER": "MetLife Stadium, New York/New Jersey",
|
|
// Gruppe F
|
|
"NED-JPN": "AT&T Stadium, Dallas",
|
|
"SWE-TUN": "Estadio BBVA, Monterrey",
|
|
"NED-SWE": "NRG Stadium, Houston",
|
|
"TUN-JPN": "Estadio BBVA, Monterrey",
|
|
"JPN-SWE": "AT&T Stadium, Dallas",
|
|
"TUN-NED": "Arrowhead Stadium, Kansas City",
|
|
// Gruppe G
|
|
"IRN-NZL": "SoFi Stadium, Los Angeles",
|
|
"BEL-EGY": "Lumen Field, Seattle",
|
|
"BEL-IRN": "SoFi Stadium, Los Angeles",
|
|
"NZL-EGY": "BC Place, Vancouver",
|
|
"NZL-BEL": "Lumen Field, Seattle",
|
|
"EGY-IRN": "BC Place, Vancouver",
|
|
// Gruppe H
|
|
"KSA-URU": "Hard Rock Stadium, Miami",
|
|
"ESP-CPV": "Mercedes-Benz Stadium, Atlanta",
|
|
"URU-CPV": "Mercedes-Benz Stadium, Atlanta",
|
|
"ESP-KSA": "Hard Rock Stadium, Miami",
|
|
"URU-ESP": "Estadio Akron, Guadalajara",
|
|
"CPV-KSA": "NRG Stadium, Houston",
|
|
// Gruppe I
|
|
"FRA-SEN": "MetLife Stadium, New York/New Jersey",
|
|
"IRQ-NOR": "Gillette Stadium, Boston",
|
|
"NOR-SEN": "Lincoln Financial Field, Philadelphia",
|
|
"FRA-IRQ": "MetLife Stadium, New York/New Jersey",
|
|
"NOR-FRA": "Gillette Stadium, Boston",
|
|
"SEN-IRQ": "BMO Field, Toronto",
|
|
// Gruppe J
|
|
"ARG-ALG": "Arrowhead Stadium, Kansas City",
|
|
"AUT-JOR": "Levi's Stadium, San Francisco Bay Area",
|
|
"ARG-AUT": "AT&T Stadium, Dallas",
|
|
"JOR-ALG": "Levi's Stadium, San Francisco Bay Area",
|
|
"JOR-ARG": "Arrowhead Stadium, Kansas City",
|
|
"ALG-AUT": "NRG Stadium, Houston",
|
|
// Gruppe K
|
|
"UZB-COL": "Estadio Azteca, Mexiko-Stadt",
|
|
"POR-COD": "NRG Stadium, Houston",
|
|
"POR-UZB": "NRG Stadium, Houston",
|
|
"COL-COD": "Estadio Akron, Guadalajara",
|
|
"COL-POR": "Hard Rock Stadium, Miami",
|
|
"COD-UZB": "Estadio BBVA, Monterrey",
|
|
// Gruppe L
|
|
"GHA-PAN": "BMO Field, Toronto",
|
|
"ENG-CRO": "AT&T Stadium, Dallas",
|
|
"ENG-GHA": "Gillette Stadium, Boston",
|
|
"PAN-CRO": "BMO Field, Toronto",
|
|
"PAN-ENG": "MetLife Stadium, New York/New Jersey",
|
|
"CRO-GHA": "Arrowhead Stadium, Kansas City",
|
|
};
|
|
|
|
// Reihenfolge-unabhängiger Lookup: baut beide Schlüsselrichtungen.
|
|
const PAIR_VENUE = new Map<string, string>();
|
|
for (const [key, venue] of Object.entries(FIXTURES_GROUP_STAGE)) {
|
|
const [a, b] = key.split("-");
|
|
PAIR_VENUE.set(`${a}-${b}`, venue);
|
|
PAIR_VENUE.set(`${b}-${a}`, venue);
|
|
}
|
|
|
|
// --- K.O.-PHASE: FIFA-Spielnummer -> Stadion ---
|
|
export const VENUE_BY_KO_MATCH: Record<number, string> = {
|
|
// Sechzehntelfinale (R32)
|
|
73: "SoFi Stadium, Los Angeles",
|
|
74: "Gillette Stadium, Boston",
|
|
75: "Estadio Azteca, Mexiko-Stadt",
|
|
76: "Hard Rock Stadium, Miami",
|
|
77: "Mercedes-Benz Stadium, Atlanta",
|
|
78: "AT&T Stadium, Dallas",
|
|
79: "Levi's Stadium, San Francisco Bay Area",
|
|
80: "Lumen Field, Seattle",
|
|
81: "MetLife Stadium, New York/New Jersey",
|
|
82: "Lincoln Financial Field, Philadelphia",
|
|
83: "BMO Field, Toronto",
|
|
84: "NRG Stadium, Houston",
|
|
85: "BC Place, Vancouver",
|
|
86: "Estadio BBVA, Monterrey",
|
|
87: "Arrowhead Stadium, Kansas City",
|
|
88: "AT&T Stadium, Dallas",
|
|
// Achtelfinale (R16)
|
|
89: "MetLife Stadium, New York/New Jersey",
|
|
90: "Hard Rock Stadium, Miami",
|
|
91: "NRG Stadium, Houston",
|
|
92: "Mercedes-Benz Stadium, Atlanta",
|
|
93: "AT&T Stadium, Dallas",
|
|
94: "Lumen Field, Seattle",
|
|
95: "BC Place, Vancouver",
|
|
96: "Estadio Azteca, Mexiko-Stadt",
|
|
// Viertelfinale
|
|
97: "Gillette Stadium, Boston",
|
|
98: "SoFi Stadium, Los Angeles",
|
|
99: "Hard Rock Stadium, Miami",
|
|
100: "Arrowhead Stadium, Kansas City",
|
|
// Halbfinale
|
|
101: "AT&T Stadium, Dallas",
|
|
102: "Mercedes-Benz Stadium, Atlanta",
|
|
// Spiel um Platz 3
|
|
103: "Hard Rock Stadium, Miami",
|
|
// Finale
|
|
104: "MetLife Stadium, New York/New Jersey",
|
|
};
|
|
|
|
// Manche Feeds nutzen abweichende 3-Buchstaben-Codes als die Map oben.
|
|
// Diese Tabelle übersetzt bekannte Feed-Codes auf den Map-Code.
|
|
// (Beispiel: FIFA/ISO nutzt CUW für Curaçao, die Map verwendet CUR.)
|
|
const CODE_ALIAS: Record<string, string> = {
|
|
CUW: "CUR", // Curaçao
|
|
CRC: "CRC", // (Platzhalter, falls weitere auftauchen)
|
|
};
|
|
|
|
// Fallback über den Teamnamen, falls ein Code unbekannt/abweichend ist.
|
|
// Schlüssel: normalisierter Name -> Map-Code.
|
|
const NAME_TO_CODE: Record<string, string> = {
|
|
"curacao": "CUR", "curaçao": "CUR",
|
|
"uruguay": "URU",
|
|
"cape verde": "CPV", "cape verde islands": "CPV", "cabo verde": "CPV",
|
|
"saudi arabia": "KSA",
|
|
"ivory coast": "CIV", "côte d'ivoire": "CIV", "cote d'ivoire": "CIV",
|
|
"south korea": "KOR", "korea republic": "KOR",
|
|
"south africa": "RSA",
|
|
"czechia": "CZE", "czech republic": "CZE",
|
|
"bosnia and herzegovina": "BIH", "bosnia-herzegovina": "BIH",
|
|
"dr congo": "COD", "congo dr": "COD", "democratic republic of the congo": "COD",
|
|
};
|
|
|
|
// Normalisiert den Code eines Teams auf den in der Map verwendeten Code.
|
|
function canonicalCode(team: Team | undefined): string | null {
|
|
if (!team) return null;
|
|
if (team.code) {
|
|
const c = team.code.toUpperCase();
|
|
if (CODE_ALIAS[c]) return CODE_ALIAS[c];
|
|
// Wenn der Code direkt in der Map vorkommt, nimm ihn.
|
|
return c;
|
|
}
|
|
// kein Code -> über den Namen versuchen
|
|
const n = team.name?.toLowerCase().trim();
|
|
return n ? (NAME_TO_CODE[n] ?? null) : null;
|
|
}
|
|
|
|
// Liefert das Stadion eines Spiels.
|
|
// Gruppenspiel -> über Teampaarung (Codes, mit Alias/Namen-Fallback),
|
|
// K.o.-Spiel -> über Spielnummer.
|
|
export function venueFor(m: Match, teams: Team[]): string | null {
|
|
if (m.group != null) {
|
|
const home = teams.find((t) => t.id === m.homeTeamId);
|
|
const away = teams.find((t) => t.id === m.awayTeamId);
|
|
let hc = canonicalCode(home);
|
|
let ac = canonicalCode(away);
|
|
// Erstversuch mit Codes
|
|
let venue = hc && ac ? PAIR_VENUE.get(`${hc}-${ac}`) : undefined;
|
|
// Falls kein Treffer: über die Namen normalisieren und erneut probieren.
|
|
if (!venue) {
|
|
const hn = home?.name?.toLowerCase().trim();
|
|
const an = away?.name?.toLowerCase().trim();
|
|
hc = (hn && NAME_TO_CODE[hn]) || hc;
|
|
ac = (an && NAME_TO_CODE[an]) || ac;
|
|
venue = hc && ac ? PAIR_VENUE.get(`${hc}-${ac}`) : undefined;
|
|
}
|
|
return venue ?? null;
|
|
}
|
|
return VENUE_BY_KO_MATCH[m.matchNumber] ?? null;
|
|
} |