From 01b01b727f705e4ca87bc43985df80330c74476e Mon Sep 17 00:00:00 2001 From: Grzegorz Kucmierz Date: Thu, 19 Feb 2026 11:20:27 +0100 Subject: [PATCH] refactor: cleanup unused files, consolidate tests, optimize worker pool --- src/components/ImageImportModal.vue | 1 + src/utils/debug_solver.test.js | 27 ------- src/utils/large_grid_solver.test.js | 44 ------------ src/utils/repro_solver.test.js | 49 ------------- src/utils/solver.test.js | 82 +++++++++++++++++++++ verify_i18n.js | 107 ---------------------------- 6 files changed, 83 insertions(+), 227 deletions(-) delete mode 100644 src/utils/debug_solver.test.js delete mode 100644 src/utils/large_grid_solver.test.js delete mode 100644 src/utils/repro_solver.test.js delete mode 100644 verify_i18n.js diff --git a/src/components/ImageImportModal.vue b/src/components/ImageImportModal.vue index e62cab0..a398d85 100644 --- a/src/components/ImageImportModal.vue +++ b/src/components/ImageImportModal.vue @@ -387,6 +387,7 @@ const capturePhoto = () => { onUnmounted(() => { stopCameraStream(); + getWorkerPool().cancelAll(); }); diff --git a/src/utils/debug_solver.test.js b/src/utils/debug_solver.test.js deleted file mode 100644 index 3ec605b..0000000 --- a/src/utils/debug_solver.test.js +++ /dev/null @@ -1,27 +0,0 @@ - -import { describe, it, expect } from 'vitest'; -import { solvePuzzle } from './solver'; -import { calculateHints } from './puzzleUtils'; - -describe('Debug Solver', () => { - it('should solve the broken grid', () => { - const grid = [ - [0,1,1,1,0,0,1,0,1,1], - [1,1,1,0,0,1,1,1,0,0], - [1,0,1,0,1,0,0,1,0,0], - [1,0,0,0,1,1,1,1,0,1], - [1,1,0,1,0,0,0,1,0,1], - [1,0,1,0,1,0,0,0,1,0], - [1,1,1,0,0,1,1,0,0,0], - [0,1,0,0,1,0,1,0,0,0], - [0,0,0,1,1,0,0,0,1,0], - [1,0,1,1,0,0,1,0,1,1] - ]; - - const { rowHints, colHints } = calculateHints(grid); - const result = solvePuzzle(rowHints, colHints); - - console.log('Solve Result:', result); - expect(result.percentSolved).toBe(100); - }); -}); diff --git a/src/utils/large_grid_solver.test.js b/src/utils/large_grid_solver.test.js deleted file mode 100644 index 10907a7..0000000 --- a/src/utils/large_grid_solver.test.js +++ /dev/null @@ -1,44 +0,0 @@ - -import { describe, it, expect } from 'vitest'; -import { solvePuzzle } from './solver.js'; - -describe('Large Grid Solver', () => { - it('should solve a large 55x28 grid without crashing', () => { - const rows = 28; - const cols = 55; - // Create a simple pattern: checkerboard or lines - const grid = Array(rows).fill().map((_, r) => - Array(cols).fill().map((_, c) => (r + c) % 2 === 0 ? 1 : 0) - ); - - // Calculate hints - const rowHints = grid.map(row => { - const hints = []; - let current = 0; - row.forEach(cell => { - if (cell === 1) current++; - else if (current > 0) { hints.push(current); current = 0; } - }); - if (current > 0) hints.push(current); - return hints.length ? hints : [0]; - }); - - const colHints = Array(cols).fill().map((_, c) => { - const hints = []; - let current = 0; - for(let r=0; r 0) { hints.push(current); current = 0; } - } - if (current > 0) hints.push(current); - return hints.length ? hints : [0]; - }); - - console.log('Starting solve...'); - const result = solvePuzzle(rowHints, colHints, (p) => console.log(`Progress: ${p}%`)); - console.log('Result:', result); - - expect(result.percentSolved).toBeGreaterThan(0); - expect(result.difficultyScore).toBeDefined(); - }); -}); diff --git a/src/utils/repro_solver.test.js b/src/utils/repro_solver.test.js deleted file mode 100644 index 58a4472..0000000 --- a/src/utils/repro_solver.test.js +++ /dev/null @@ -1,49 +0,0 @@ - -import { describe, it, expect } from 'vitest'; -import { solvePuzzle } from './solver'; -import { calculateHints } from './puzzleUtils'; - -describe('Solver Repro', () => { - it('should solve a simple generated puzzle', () => { - const grid = [ - [1, 0, 1, 1, 0], - [1, 1, 0, 0, 1], - [0, 0, 1, 0, 0], - [1, 1, 1, 1, 1], - [0, 1, 0, 1, 0] - ]; - const { rowHints, colHints } = calculateHints(grid); - - const result = solvePuzzle(rowHints, colHints); - expect(result.percentSolved).toBe(100); - }); - - it('should not fail on random valid lines', () => { - // Test solveLine indirectly via solvePuzzle on small grids - for (let i = 0; i < 100; i++) { - const size = 10; - const grid = []; - for(let r=0; r 0.5 ? 1 : 0); - grid.push(row); - } - - const { rowHints, colHints } = calculateHints(grid); - const result = solvePuzzle(rowHints, colHints); - - // It might not be 100% solvable without guessing (logic only), - // but since our solver HAS backtracking, it MUST be 100% solvable - // (unless timeout/max depth reached, but for 10x10 it should solve). - - // If it returns 0% or low %, it implies it failed to find the solution - // or found a contradiction (which shouldn't happen for valid hints). - - if (result.percentSolved < 100) { - console.log('Failed Grid:', JSON.stringify(grid)); - console.log('Result:', result); - } - expect(result.percentSolved).toBe(100); - } - }); -}); diff --git a/src/utils/solver.test.js b/src/utils/solver.test.js index bcdd272..70143e7 100644 --- a/src/utils/solver.test.js +++ b/src/utils/solver.test.js @@ -1,3 +1,8 @@ +import { describe, it, expect } from 'vitest'; +import { solvePuzzle } from './solver'; +import { calculateHints, generateRandomGrid } from './puzzleUtils'; + +describe('Solver', () => { it('solves a puzzle requiring guessing (Backtracking)', () => { // A puzzle that logic alone cannot start usually has multiple solutions or requires a guess. // Example: The "domino" or "ambiguous" pattern, but we need a unique solution that requires lookahead. @@ -61,4 +66,81 @@ expect(result.percentSolved).toBe(100); } }); + + // Merged from repro_solver.test.js + it('should solve a simple generated puzzle', () => { + const grid = [ + [1, 0, 1, 1, 0], + [1, 1, 0, 0, 1], + [0, 0, 1, 0, 0], + [1, 1, 1, 1, 1], + [0, 1, 0, 1, 0] + ]; + const { rowHints, colHints } = calculateHints(grid); + + const result = solvePuzzle(rowHints, colHints); + expect(result.percentSolved).toBe(100); + }); + + // Merged from debug_solver.test.js + it('should solve the broken grid (debug case)', () => { + const grid = [ + [0,1,1,1,0,0,1,0,1,1], + [1,1,1,0,0,1,1,1,0,0], + [1,0,1,0,1,0,0,1,0,0], + [1,0,0,0,1,1,1,1,0,1], + [1,1,0,1,0,0,0,1,0,1], + [1,0,1,0,1,0,0,0,1,0], + [1,1,1,0,0,1,1,0,0,0], + [0,1,0,0,1,0,1,0,0,0], + [0,0,0,1,1,0,0,0,1,0], + [1,0,1,1,0,0,1,0,1,1] + ]; + + const { rowHints, colHints } = calculateHints(grid); + const result = solvePuzzle(rowHints, colHints); + + // console.log('Solve Result:', result); + expect(result.percentSolved).toBe(100); + }); + + // Merged from large_grid_solver.test.js + it('should solve a large 55x28 grid without crashing', () => { + const rows = 28; + const cols = 55; + // Create a simple pattern: checkerboard or lines + const grid = Array(rows).fill().map((_, r) => + Array(cols).fill().map((_, c) => (r + c) % 2 === 0 ? 1 : 0) + ); + + // Calculate hints + const rowHints = grid.map(row => { + const hints = []; + let current = 0; + row.forEach(cell => { + if (cell === 1) current++; + else if (current > 0) { hints.push(current); current = 0; } + }); + if (current > 0) hints.push(current); + return hints.length ? hints : [0]; + }); + + const colHints = Array(cols).fill().map((_, c) => { + const hints = []; + let current = 0; + for(let r=0; r 0) { hints.push(current); current = 0; } + } + if (current > 0) hints.push(current); + return hints.length ? hints : [0]; + }); + + // console.log('Starting solve...'); + const result = solvePuzzle(rowHints, colHints); // Removed console.log callback to reduce noise + // console.log('Result:', result); + + expect(result.percentSolved).toBeGreaterThan(0); + expect(result.difficultyScore).toBeDefined(); + }); }); diff --git a/verify_i18n.js b/verify_i18n.js deleted file mode 100644 index e3f163e..0000000 --- a/verify_i18n.js +++ /dev/null @@ -1,107 +0,0 @@ - -import fs from 'fs'; -import path from 'path'; -import { fileURLToPath } from 'url'; -import { execSync } from 'child_process'; - -const __filename = fileURLToPath(import.meta.url); -const __dirname = path.dirname(__filename); - -// 1. Parse useI18n.js to get keys -const i18nPath = path.join(__dirname, 'src/composables/useI18n.js'); -const i18nContent = fs.readFileSync(i18nPath, 'utf8'); - -function extractKeys(lang) { - // Find start of lang block: " en: {" - const startRegex = new RegExp(`\\s+${lang}:\\s*\\{`); - const startMatch = i18nContent.match(startRegex); - if (!startMatch) return new Set(); - - const startIndex = startMatch.index + startMatch[0].length; - let braceCount = 1; - let inString = false; - let stringChar = ''; - let endIndex = -1; - - for (let i = startIndex; i < i18nContent.length; i++) { - const char = i18nContent[i]; - - if (inString) { - if (char === stringChar && i18nContent[i-1] !== '\\') { - inString = false; - } - } else { - if (char === "'" || char === '"' || char === '`') { - inString = true; - stringChar = char; - } else if (char === '{') { - braceCount++; - } else if (char === '}') { - braceCount--; - if (braceCount === 0) { - endIndex = i; - break; - } - } - } - } - - if (endIndex === -1) return new Set(); - - const block = i18nContent.substring(startIndex, endIndex); - const keys = new Set(); - const keyRegex = /['"]([\w.-]+)['"]\s*:/g; - let match; - while ((match = keyRegex.exec(block)) !== null) { - keys.add(match[1]); - } - return keys; -} - -const enKeys = extractKeys('en'); -console.log(`Found ${enKeys.size} keys in en block.`); - -if (enKeys.has('image.title')) { - console.log("'image.title' IS present in en block."); -} else { - console.log("'image.title' is MISSING in en block."); -} - -// 2. Scan src for usages -try { - const grepOutput = execSync(`grep -r "t(['\\"]" src | grep -v "node_modules"`, { encoding: 'utf8' }); - - const usedKeys = new Set(); - const usageRegex = /t\(['"]([\w.-]+)['"]/g; - - const lines = grepOutput.split('\n'); - for (const line of lines) { - let m; - while ((m = usageRegex.exec(line)) !== null) { - usedKeys.add(m[1]); - } - } - - console.log(`Found ${usedKeys.size} used keys in src.`); - - // 3. Compare - const missingKeys = []; - for (const key of usedKeys) { - // Skip dynamic keys or composed keys if any (heuristic) - if (key.includes('${')) continue; - - if (!enKeys.has(key)) { - missingKeys.push(key); - } - } - - if (missingKeys.length > 0) { - console.log("Missing translations in en:"); - missingKeys.forEach(k => console.log(` - ${k}`)); - } else { - console.log("No missing translations found in en."); - } - -} catch (e) { - console.error("Error running grep:", e); -}