many many fixes

This commit is contained in:
2026-10-26 10:06:30 -04:00
parent 79e15cb8c3
commit f1a13a3065
25 changed files with 642 additions and 9964 deletions

View File

@@ -1,6 +1,5 @@
import fs from 'node:fs';
import path from 'node:path';
import { solveBoard } from './solver.mjs';
import { extraWords } from './extra-words.mjs';
import { DICTIONARY_SET } from '../src/data/lexicon.js';
@@ -228,210 +227,9 @@ for (const item of targetWordsPool) {
console.log('Target words pool verified! Total words:', targetWordsPool.length);
const dailyPuzzlesDefs = [
{
id: '2026-10-23',
date: '2026-10-23',
title: 'Daily Puzzle — Oct 23, 2026',
theme: 'Discovery & Wonder',
difficulty: 'Normal',
words: ['remarkable', 'unforgettable', 'photography', 'adventurous', 'inspiration']
},
{
id: '2026-10-24',
date: '2026-10-24',
title: 'Daily Puzzle — Oct 24, 2026',
theme: 'Cosmic Horizons',
difficulty: 'Challenging',
words: ['astronomy', 'gravitation', 'atmosphere', 'interstellar', 'telescopic']
},
{
id: '2026-10-25',
date: '2026-10-25',
title: 'Daily Puzzle — Oct 25, 2026',
theme: 'Mind & Memory',
difficulty: 'Normal',
words: ['imagination', 'understanding', 'psychology', 'intelligence', 'consciousness']
},
{
id: '2026-10-26',
date: '2026-10-26',
title: 'Daily Puzzle — Oct 26, 2026',
theme: 'Urban Pulse',
difficulty: 'Challenging',
words: ['architecture', 'metropolitan', 'construction', 'neighborhood', 'skyscraper']
},
{
id: '2026-10-27',
date: '2026-10-27',
title: 'Daily Puzzle — Oct 27, 2026',
theme: 'Harmony & Arts',
difficulty: 'Normal',
words: ['saxophone', 'masterpiece', 'calligraphy', 'exhibition', 'creativity']
},
{
id: '2026-10-28',
date: '2026-10-28',
title: 'Daily Puzzle — Oct 28, 2026',
theme: 'Digital Future',
difficulty: 'Normal',
words: ['technology', 'electronic', 'automation', 'computer', 'cybersecurity']
},
{
id: '2026-10-29',
date: '2026-10-29',
title: 'Daily Puzzle — Oct 29, 2026',
theme: 'Celebrations',
difficulty: 'Easy',
words: ['celebration', 'fellowship', 'generosity', 'opportunity', 'marshmallow']
},
{
id: '2026-10-30',
date: '2026-10-30',
title: 'Daily Puzzle — Oct 30, 2026',
theme: 'Wild Kingdom',
difficulty: 'Normal',
words: ['biodiversity', 'environment', 'caterpillar', 'wilderness', 'chameleon']
},
{
id: '2026-10-31',
date: '2026-10-31',
title: 'Daily Puzzle — Oct 31, 2026',
theme: 'Mysteries & Legends',
difficulty: 'Challenging',
words: ['mysterious', 'supernatural', 'legendary', 'enchanted', 'miraculous']
},
{
id: '2026-10-22',
date: '2026-10-22',
title: 'Daily Puzzle — Oct 22, 2026',
theme: 'Scientific Insight',
difficulty: 'Normal',
words: ['equivalent', 'hypothesis', 'laboratory', 'microscope', 'phenomenon']
},
{
id: '2026-10-21',
date: '2026-10-21',
title: 'Daily Puzzle — Oct 21, 2026',
theme: 'Wordsmith Almanac',
difficulty: 'Normal',
words: ['dictionary', 'manuscript', 'encyclopedia', 'literature', 'vocabulary']
},
{
id: '2026-10-20',
date: '2026-10-20',
title: 'Daily Puzzle — Oct 20, 2026',
theme: 'Globe Trekker',
difficulty: 'Normal',
words: ['backpacker', 'locomotive', 'continental', 'navigation', 'voyagers']
},
{
id: '2026-10-19',
date: '2026-10-19',
title: 'Daily Puzzle — Oct 19, 2026',
theme: 'Atmospheric Skies',
difficulty: 'Challenging',
words: ['meteorology', 'temperatures', 'precipitation', 'stratosphere', 'cloudburst']
},
{
id: '2026-10-18',
date: '2026-10-18',
title: 'Daily Puzzle — Oct 18, 2026',
theme: 'Green Oasis',
difficulty: 'Normal',
words: ['photosynthesis', 'marigold', 'evergreen', 'germination', 'sunflowers']
},
{
id: '2026-10-17',
date: '2026-10-17',
title: 'Daily Puzzle — Oct 17, 2026',
theme: 'Grit & Glory',
difficulty: 'Normal',
words: ['determination', 'courageous', 'championship', 'achievement', 'perseverance']
},
{
id: '2026-10-16',
date: '2026-10-16',
title: 'Daily Puzzle — Oct 16, 2026',
theme: 'Oceanic Depths',
difficulty: 'Challenging',
words: ['oceanography', 'submarine', 'underwater', 'jellyfish', 'exploration']
},
{
id: '2026-10-15',
date: '2026-10-15',
title: 'Daily Puzzle — Oct 15, 2026',
theme: 'Energy & Waves',
difficulty: 'Expert',
words: ['electricity', 'spectrum', 'frequency', 'radioactive', 'magnetism']
}
];
// Map target words for quick lookup
const wordMap = new Map();
for (const item of targetWordsPool) {
wordMap.set(item.word, item);
}
const solvedPuzzles = [];
for (const def of dailyPuzzlesDefs) {
const quartets = def.words.map(w => {
const found = wordMap.get(w);
if (!found) throw new Error('Missing word in pool: ' + w);
return found.tiles;
});
const allTiles = quartets.flat();
// STRICT ASSERTIONS
if (new Set(allTiles).size !== 20) {
const counts = {};
allTiles.forEach(t => counts[t] = (counts[t] || 0) + 1);
const dupes = Object.entries(counts).filter(([_, c]) => c > 1);
throw new Error(`Puzzle ${def.id} has duplicate tiles: ${JSON.stringify(dupes)}`);
}
if (allTiles.some(t => t.length < 2)) {
throw new Error(`Puzzle ${def.id} has a tile < 2 chars: ${JSON.stringify(allTiles)}`);
}
const solved = solveBoard(quartets, 30);
if (solved.wordCount > 30) {
throw new Error(`Puzzle ${def.id} exceeds 30 words: ${solved.wordCount}`);
}
// Add clues to target quartiles
const quartileDetails = def.words.map(w => {
const item = wordMap.get(w);
return {
word: item.word,
tiles: item.tiles,
clue: item.clue
};
});
solvedPuzzles.push({
id: def.id,
date: def.date,
title: def.title,
theme: def.theme,
difficulty: def.difficulty,
quartets,
tiles: solved.tiles,
targetQuartiles: solved.targetQuartiles,
quartileDetails,
words: solved.words,
wordCount: solved.wordCount,
maxPossibleScore: solved.maxPossibleScore
});
console.log(`Generated: ${def.id} [${def.theme}] -> ${solved.wordCount} words, max score: ${solved.maxPossibleScore}`);
}
// Write solved puzzles to src/data/puzzles.js
const puzzlesFileContent = `// Pre-computed solved daily and themed puzzles for Quartiles
export const CURATED_PUZZLES = ${JSON.stringify(solvedPuzzles, null, 2)};
// Puzzles are generated from this pool at runtime (src/engine/generator.js):
// daily puzzles are seeded by date, unlimited puzzles are random.
const puzzlesFileContent = `// Target word pool for generated Quartiles puzzles (built by scripts/build-all-data.mjs)
export const TARGET_WORDS_POOL = ${JSON.stringify(targetWordsPool, null, 2)};
`;