diff --git a/dev-dist/sw.js b/dev-dist/sw.js index 8d96cbc..24f2c2f 100644 --- a/dev-dist/sw.js +++ b/dev-dist/sw.js @@ -82,7 +82,7 @@ define(['./workbox-7a5e81cd'], (function (workbox) { 'use strict'; */ workbox.precacheAndRoute([{ "url": "index.html", - "revision": "0.kkc80cp3p5o" + "revision": "0.n1n8rjsg38" }], {}); workbox.cleanupOutdatedCaches(); workbox.registerRoute(new workbox.NavigationRoute(workbox.createHandlerBoundToURL("index.html"), { diff --git a/src/components/GameBoard.vue b/src/components/GameBoard.vue index 142528f..0c43e0b 100644 --- a/src/components/GameBoard.vue +++ b/src/components/GameBoard.vue @@ -247,10 +247,10 @@ watch(() => store.size, async () => {
- + - +
[] } }); @@ -34,6 +38,7 @@ defineProps({ class="hint-group" :class="{ 'is-active': index === activeIndex, + 'is-completed': completedLines[index], 'guide-right': orientation === 'col' && (index + 1) % 5 === 0 && index !== size - 1, 'guide-bottom': orientation === 'row' && (index + 1) % 5 === 0 && index !== size - 1 }" @@ -81,6 +86,15 @@ defineProps({ height: 100%; } +.hint-group.is-completed { + opacity: 0.5; + background-color: var(--hint-bg); +} + +.hint-group.is-completed .hint-num { + color: var(--text-muted); +} + .col .hint-group { flex-direction: column; padding: 4px 2px; diff --git a/src/stores/puzzle.js b/src/stores/puzzle.js index 0d701f6..f518186 100644 --- a/src/stores/puzzle.js +++ b/src/stores/puzzle.js @@ -56,6 +56,31 @@ export const usePuzzleStore = defineStore('puzzle', () => { return Math.min(100, (filledCorrectly.value / totalCellsToFill.value) * 100); }); + const completedRows = computed(() => { + if (!solution.value.length || !playerGrid.value.length) return []; + const rows = solution.value.length; + return Array(rows).fill().map((_, r) => { + const targetHints = calculateLineHints(solution.value[r]); + const playerLine = playerGrid.value[r]; + return validateLine(playerLine, targetHints); + }); + }); + + const completedCols = computed(() => { + if (!solution.value.length || !playerGrid.value.length) return []; + const rows = solution.value.length; + const cols = solution.value[0].length; + return Array(cols).fill().map((_, c) => { + const col = []; + for (let r = 0; r < rows; r++) { + col.push(solution.value[r][c]); + } + const targetHints = calculateLineHints(col); + const playerLine = playerGrid.value.map(row => row[c]); + return validateLine(playerLine, targetHints); + }); + }); + // Actions function initGame(levelId = 'easy') { stopTimer(); @@ -408,7 +433,9 @@ export const usePuzzleStore = defineStore('puzzle', () => { currentDensity, markGuideUsed, startInteraction, - endInteraction + endInteraction, + completedRows, + completedCols }; }); diff --git a/src/stores/puzzle_completion.test.js b/src/stores/puzzle_completion.test.js new file mode 100644 index 0000000..8d7c0b8 --- /dev/null +++ b/src/stores/puzzle_completion.test.js @@ -0,0 +1,70 @@ + +import { describe, it, expect, beforeEach } from 'vitest'; +import { setActivePinia, createPinia } from 'pinia'; +import { usePuzzleStore } from './puzzle'; + +describe('Puzzle Store - Completion Logic', () => { + beforeEach(() => { + setActivePinia(createPinia()); + }); + + it('should correctly identify completed rows and columns', () => { + const store = usePuzzleStore(); + + // Setup a simple 2x2 puzzle + // Solution: + // 1 0 + // 0 1 + // Row Hints: [1], [1] + // Col Hints: [1], [1] + store.solution = [ + [1, 0], + [0, 1] + ]; + store.playerGrid = [ + [0, 0], + [0, 0] + ]; + + // Initially nothing is completed + expect(store.completedRows).toEqual([false, false]); + expect(store.completedCols).toEqual([false, false]); + + // Fill first row correctly: 1 0 + store.playerGrid[0][0] = 1; + store.playerGrid[0][1] = 0; + + expect(store.completedRows).toEqual([true, false]); + + // Fill second row incorrectly (too many filled): 1 1 + store.playerGrid[1][0] = 1; + store.playerGrid[1][1] = 1; + + // Row 2 hint is [1], user has [2]. Should be false. + expect(store.completedRows).toEqual([true, false]); + + // Fix second row: 0 1 + store.playerGrid[1][0] = 0; + store.playerGrid[1][1] = 1; + + expect(store.completedRows).toEqual([true, true]); + + // Check columns + // Col 1: 1, 0 -> Hint [1]. Matches. + // Col 2: 0, 1 -> Hint [1]. Matches. + expect(store.completedCols).toEqual([true, true]); + }); + + it('should mark row as completed if constraints are met even if wrong position', () => { + const store = usePuzzleStore(); + // Solution: 1 0 0 (Hint 1) + store.solution = [[1, 0, 0]]; + store.playerGrid = [[0, 0, 0]]; + + // User puts 0 0 1 (Hint 1) + store.playerGrid[0] = [0, 0, 1]; + + // Should be marked as completed because it satisfies the hint "1" + expect(store.completedRows).toEqual([true]); + }); +}); diff --git a/src/utils/large_grid_solver.test.js b/src/utils/large_grid_solver.test.js index 43a6299..10907a7 100644 --- a/src/utils/large_grid_solver.test.js +++ b/src/utils/large_grid_solver.test.js @@ -39,6 +39,6 @@ describe('Large Grid Solver', () => { console.log('Result:', result); expect(result.percentSolved).toBeGreaterThan(0); - expect(result.difficulty).toBeDefined(); + expect(result.difficultyScore).toBeDefined(); }); });