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();
});
});