// 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 = { // 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(); 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 = { // 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 = { 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 = { "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; }