Files
hidden11/scripts/validate-puzzles.mjs
T
alexandrev-tibco 53214f96a5
Build and push image / build (push) Successful in 1m17s
Remove generic clues and document data sources
2026-05-07 08:13:28 +02:00

70 lines
2.2 KiB
JavaScript

import players from "../data/players.json" with { type: "json" };
import puzzles from "../data/puzzles.json" with { type: "json" };
const byId = new Map(players.map((player) => [player.id, player]));
const positions = ["GK", "DEF", "MID", "WING", "ST"];
const dates = [...new Set(puzzles.map((puzzle) => puzzle.date))].sort();
function solutionPlayers(puzzle) {
return Object.entries(puzzle.solution).map(([position, playerId]) => {
const player = byId.get(playerId);
if (!player) throw new Error(`${puzzle.id}: missing player ${playerId}`);
return { slot: position, ...player };
});
}
function toDateKey(date) {
return date.toISOString().slice(0, 10);
}
if (puzzles.length !== 365 * 3) {
throw new Error(`Expected ${365 * 3} puzzles, found ${puzzles.length}`);
}
if (dates.length !== 365) {
throw new Error(`Expected 365 unique dates, found ${dates.length}`);
}
for (let i = 1; i < dates.length; i += 1) {
const previous = new Date(`${dates[i - 1]}T00:00:00.000Z`);
previous.setUTCDate(previous.getUTCDate() + 1);
const expected = toDateKey(previous);
if (dates[i] !== expected) {
throw new Error(`Expected contiguous dates, got ${dates[i - 1]} then ${dates[i]}`);
}
}
const solutionSignatures = new Set();
const forbiddenClueFragments = ["top-flight football"];
for (const puzzle of puzzles) {
if (!positions.includes(puzzle.fixedPosition)) {
throw new Error(`${puzzle.id}: invalid fixed position ${puzzle.fixedPosition}`);
}
if (!Array.isArray(puzzle.clues) || puzzle.clues.length < 4) {
throw new Error(`${puzzle.id}: expected at least four clues`);
}
for (const clue of puzzle.clues) {
if (forbiddenClueFragments.some((fragment) => clue.includes(fragment))) {
throw new Error(`${puzzle.id}: forbidden clue "${clue}"`);
}
}
const lineup = solutionPlayers(puzzle);
const signature = JSON.stringify(puzzle.solution);
if (solutionSignatures.has(signature)) {
throw new Error(`${puzzle.id}: duplicate solution detected`);
}
solutionSignatures.add(signature);
for (const player of lineup) {
if (!player.id || !player.name) {
throw new Error(`${puzzle.id}: invalid player reference`);
}
}
}
console.log("Puzzle data OK");