/** * Level system — 100 levels per game, deterministic seeds, graduated difficulty. * * Seed strategy: level N → synthetic date "LEVEL-{game}-{N:03d}" * Each generator uses date.split("-").reduce(…) to derive a numeric seed, * so we pass a date-shaped string that yields a unique seed per (game, level). * * Level N → date string: `${1900 + N}-01-01` * This stays far from real daily dates (2024+) and is unique per level. */ export const GAMES = ["queens", "tango", "zip", "sudoku", "patches"] as const; export type GameId = typeof GAMES[number]; export const TOTAL_LEVELS = 100; /** Convert level number (1–100) to the synthetic date fed to the generator. */ export function levelToDate(level: number): string { const n = Math.max(1, Math.min(TOTAL_LEVELS, level)); // e.g. level 1 → "1901-01-01", level 42 → "1942-01-01", level 100 → "2000-01-01" return `${1900 + n}-01-01`; } /** Queens: N scales 6→10 across 100 levels. */ export function queensSizeForLevel(level: number): number { if (level <= 15) return 6; if (level <= 35) return 7; if (level <= 60) return 8; if (level <= 80) return 9; return 10; } /** Zip: grid size scales with level. */ export function zipSizeForLevel(level: number): number { if (level <= 20) return 5; if (level <= 50) return 6; if (level <= 75) return 7; return 8; } export interface LevelMeta { level: number; difficulty: 1 | 2 | 3 | 4 | 5; // 1=easy … 5=expert difficultyLabel: string; } const DIFFICULTY_LABELS = ["", "Facile", "Normal", "Intermédiaire", "Difficile", "Expert"]; export function levelMeta(game: GameId, level: number): LevelMeta { let difficulty: 1 | 2 | 3 | 4 | 5; if (game === "queens") { if (level <= 15) difficulty = 1; else if (level <= 35) difficulty = 2; else if (level <= 60) difficulty = 3; else if (level <= 80) difficulty = 4; else difficulty = 5; } else if (game === "zip") { if (level <= 20) difficulty = 1; else if (level <= 50) difficulty = 2; else if (level <= 75) difficulty = 3; else if (level <= 90) difficulty = 4; else difficulty = 5; } else { // Tango, Sudoku, Patches: fixed size, difficulty is nominal if (level <= 20) difficulty = 1; else if (level <= 45) difficulty = 2; else if (level <= 65) difficulty = 3; else if (level <= 85) difficulty = 4; else difficulty = 5; } return { level, difficulty, difficultyLabel: DIFFICULTY_LABELS[difficulty] }; } export const GAME_META: Record = { queens: { name: "Queens", accent: "#d97706", desc: "Une couronne par ligne, colonne et zone colorée.", subtitle: "1 couronne par ligne, colonne et zone", duration: "≈ 3 min", symbol: "♛" }, tango: { name: "Tango", accent: "#ea580c", desc: "Équilibrez soleils et lunes selon les contraintes.", subtitle: "Équilibre soleils ☀ et lunes ◐ sur la grille", duration: "≈ 2 min", symbol: "☀" }, zip: { name: "Zip", accent: "#2563eb", desc: "Reliez les chiffres dans l'ordre en couvrant tout.", subtitle: "Relie les chiffres dans l'ordre en couvrant tout", duration: "≈ 2 min", symbol: "∞" }, sudoku: { name: "Sudoku", accent: "#16a34a", desc: "Chiffres 1–6 dans chaque ligne, colonne et bloc.", subtitle: "Chiffres 1–6 dans chaque ligne, colonne et bloc", duration: "≈ 4 min", symbol: "#" }, patches: { name: "Patches", accent: "#7c3aed", desc: "Remplissez chaque zone selon sa forme et sa taille.", subtitle: "Remplis chaque zone avec les bonnes pièces", duration: "≈ 3 min", symbol: "▦" }, };