71 lines
2.7 KiB
JavaScript
71 lines
2.7 KiB
JavaScript
|
|
/**
|
||
|
|
* Generate app/lib/fifa-2026-third-place-allocation.ts from the published FIFA
|
||
|
|
* 2026 World Cup Annex C third-place allocation table.
|
||
|
|
*
|
||
|
|
* Source: Wikipedia "Template:2026 FIFA World Cup third-place table".
|
||
|
|
* Run with: node scripts/gen-fifa-third-place.mjs
|
||
|
|
*/
|
||
|
|
import fs from "node:fs";
|
||
|
|
import path from "node:path";
|
||
|
|
import { fileURLToPath } from "node:url";
|
||
|
|
|
||
|
|
const SOURCE_URL =
|
||
|
|
"https://en.wikipedia.org/w/index.php?title=Template:2026_FIFA_World_Cup_third-place_table&action=raw";
|
||
|
|
|
||
|
|
const text = await (await fetch(SOURCE_URL)).text();
|
||
|
|
|
||
|
|
// Split into row blocks at each `! scope="row" | N`.
|
||
|
|
const parts = text.split(/!\s*scope="row"\s*\|/).slice(1);
|
||
|
|
if (parts.length !== 495) throw new Error(`expected 495 rows, got ${parts.length}`);
|
||
|
|
|
||
|
|
const out = {};
|
||
|
|
for (const part of parts) {
|
||
|
|
// Cut the block at the next row separator / table end.
|
||
|
|
const block = part.split(/\n\|\}|\n\|-/)[0];
|
||
|
|
const tokens = block.replace(/'''/g, "").split(/\|\||\||\n/).map((t) => t.trim());
|
||
|
|
|
||
|
|
const qualifying = tokens.filter((t) => /^[A-L]$/.test(t));
|
||
|
|
const assignments = tokens.filter((t) => /^3[A-L]$/.test(t)).map((t) => t[1]);
|
||
|
|
|
||
|
|
if (qualifying.length !== 8) throw new Error(`row qualifying != 8: ${qualifying}`);
|
||
|
|
if (assignments.length !== 8) throw new Error(`row assignments != 8: ${assignments}`);
|
||
|
|
|
||
|
|
const set = new Set(assignments);
|
||
|
|
if (set.size !== 8) throw new Error(`duplicate thirds: ${assignments}`);
|
||
|
|
for (const g of assignments) {
|
||
|
|
if (!qualifying.includes(g)) throw new Error(`third ${g} not qualifying`);
|
||
|
|
}
|
||
|
|
|
||
|
|
const key = [...qualifying].sort().join("");
|
||
|
|
if (out[key]) throw new Error(`duplicate key ${key}`);
|
||
|
|
out[key] = assignments.join(""); // thirds in winner-column order [A,B,D,E,G,I,K,L]
|
||
|
|
}
|
||
|
|
|
||
|
|
const keys = Object.keys(out).sort();
|
||
|
|
if (keys.length !== 495) throw new Error(`expected 495 keys, got ${keys.length}`);
|
||
|
|
|
||
|
|
const lines = keys.map((k) => ` ${k}: "${out[k]}",`).join("\n");
|
||
|
|
const ts = `// AUTO-GENERATED from FIFA 2026 World Cup Annex C third-place allocation.
|
||
|
|
// Source: Wikipedia "Template:2026 FIFA World Cup third-place table".
|
||
|
|
// Do not edit by hand — regenerate with scripts/gen-fifa-third-place.mjs.
|
||
|
|
//
|
||
|
|
// Key: the eight qualifying third-place group letters, sorted (e.g. "EFGHIJKL").
|
||
|
|
// Value: the qualifying third-place group facing each group winner, in the
|
||
|
|
// column order [1A, 1B, 1D, 1E, 1G, 1I, 1K, 1L].
|
||
|
|
export const THIRD_PLACE_WINNER_COLUMNS = ["A", "B", "D", "E", "G", "I", "K", "L"] as const;
|
||
|
|
|
||
|
|
export const ANNEX_C_THIRD_PLACE_ALLOCATION: Record<string, string> = {
|
||
|
|
${lines}
|
||
|
|
};
|
||
|
|
`;
|
||
|
|
|
||
|
|
const target = path.join(
|
||
|
|
path.dirname(fileURLToPath(import.meta.url)),
|
||
|
|
"..",
|
||
|
|
"app",
|
||
|
|
"lib",
|
||
|
|
"fifa-2026-third-place-allocation.ts"
|
||
|
|
);
|
||
|
|
fs.writeFileSync(target, ts);
|
||
|
|
console.log(`Wrote ${keys.length} rows to ${target}`);
|