@sudobility/sudojo_lib 0.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (141) hide show
  1. package/dist/hooks/index.d.ts +27 -0
  2. package/dist/hooks/index.d.ts.map +1 -0
  3. package/dist/hooks/index.js +27 -0
  4. package/dist/hooks/index.js.map +1 -0
  5. package/dist/hooks/useDailyGame.d.ts +64 -0
  6. package/dist/hooks/useDailyGame.d.ts.map +1 -0
  7. package/dist/hooks/useDailyGame.js +120 -0
  8. package/dist/hooks/useDailyGame.js.map +1 -0
  9. package/dist/hooks/useGame.d.ts +104 -0
  10. package/dist/hooks/useGame.d.ts.map +1 -0
  11. package/dist/hooks/useGame.js +546 -0
  12. package/dist/hooks/useGame.js.map +1 -0
  13. package/dist/hooks/useGamePersistence.d.ts +63 -0
  14. package/dist/hooks/useGamePersistence.d.ts.map +1 -0
  15. package/dist/hooks/useGamePersistence.js +124 -0
  16. package/dist/hooks/useGamePersistence.js.map +1 -0
  17. package/dist/hooks/useGameTeaching.d.ts +89 -0
  18. package/dist/hooks/useGameTeaching.d.ts.map +1 -0
  19. package/dist/hooks/useGameTeaching.js +230 -0
  20. package/dist/hooks/useGameTeaching.js.map +1 -0
  21. package/dist/hooks/useGameTimer.d.ts +43 -0
  22. package/dist/hooks/useGameTimer.d.ts.map +1 -0
  23. package/dist/hooks/useGameTimer.js +68 -0
  24. package/dist/hooks/useGameTimer.js.map +1 -0
  25. package/dist/hooks/useHint.d.ts +105 -0
  26. package/dist/hooks/useHint.d.ts.map +1 -0
  27. package/dist/hooks/useHint.js +179 -0
  28. package/dist/hooks/useHint.js.map +1 -0
  29. package/dist/hooks/useLearning.d.ts +100 -0
  30. package/dist/hooks/useLearning.d.ts.map +1 -0
  31. package/dist/hooks/useLearning.js +127 -0
  32. package/dist/hooks/useLearning.js.map +1 -0
  33. package/dist/hooks/useLevelGame.d.ts +68 -0
  34. package/dist/hooks/useLevelGame.d.ts.map +1 -0
  35. package/dist/hooks/useLevelGame.js +128 -0
  36. package/dist/hooks/useLevelGame.js.map +1 -0
  37. package/dist/hooks/useLevels.d.ts +93 -0
  38. package/dist/hooks/useLevels.d.ts.map +1 -0
  39. package/dist/hooks/useLevels.js +98 -0
  40. package/dist/hooks/useLevels.js.map +1 -0
  41. package/dist/hooks/useLocalStorage.d.ts +26 -0
  42. package/dist/hooks/useLocalStorage.d.ts.map +1 -0
  43. package/dist/hooks/useLocalStorage.js +75 -0
  44. package/dist/hooks/useLocalStorage.js.map +1 -0
  45. package/dist/hooks/useSudoku.d.ts +125 -0
  46. package/dist/hooks/useSudoku.d.ts.map +1 -0
  47. package/dist/hooks/useSudoku.js +655 -0
  48. package/dist/hooks/useSudoku.js.map +1 -0
  49. package/dist/hooks/useTechniques.d.ts +92 -0
  50. package/dist/hooks/useTechniques.d.ts.map +1 -0
  51. package/dist/hooks/useTechniques.js +108 -0
  52. package/dist/hooks/useTechniques.js.map +1 -0
  53. package/dist/index.d.ts +42 -0
  54. package/dist/index.d.ts.map +1 -0
  55. package/dist/index.js +64 -0
  56. package/dist/index.js.map +1 -0
  57. package/dist/test/setup.d.ts +2 -0
  58. package/dist/test/setup.d.ts.map +1 -0
  59. package/dist/test/setup.js +35 -0
  60. package/dist/test/setup.js.map +1 -0
  61. package/dist/types/display.d.ts +142 -0
  62. package/dist/types/display.d.ts.map +1 -0
  63. package/dist/types/display.js +94 -0
  64. package/dist/types/display.js.map +1 -0
  65. package/dist/types/game.d.ts +201 -0
  66. package/dist/types/game.d.ts.map +1 -0
  67. package/dist/types/game.js +26 -0
  68. package/dist/types/game.js.map +1 -0
  69. package/dist/types/gamePersistence.d.ts +31 -0
  70. package/dist/types/gamePersistence.d.ts.map +1 -0
  71. package/dist/types/gamePersistence.js +15 -0
  72. package/dist/types/gamePersistence.js.map +1 -0
  73. package/dist/types/index.d.ts +18 -0
  74. package/dist/types/index.d.ts.map +1 -0
  75. package/dist/types/index.js +11 -0
  76. package/dist/types/index.js.map +1 -0
  77. package/dist/types/progress.d.ts +43 -0
  78. package/dist/types/progress.d.ts.map +1 -0
  79. package/dist/types/progress.js +19 -0
  80. package/dist/types/progress.js.map +1 -0
  81. package/dist/types/settings.d.ts +19 -0
  82. package/dist/types/settings.d.ts.map +1 -0
  83. package/dist/types/settings.js +12 -0
  84. package/dist/types/settings.js.map +1 -0
  85. package/dist/types/subscription.d.ts +27 -0
  86. package/dist/types/subscription.d.ts.map +1 -0
  87. package/dist/types/subscription.js +8 -0
  88. package/dist/types/subscription.js.map +1 -0
  89. package/dist/types/sudoku.d.ts +147 -0
  90. package/dist/types/sudoku.d.ts.map +1 -0
  91. package/dist/types/sudoku.js +125 -0
  92. package/dist/types/sudoku.js.map +1 -0
  93. package/dist/utils/auth.d.ts +25 -0
  94. package/dist/utils/auth.d.ts.map +1 -0
  95. package/dist/utils/auth.js +47 -0
  96. package/dist/utils/auth.js.map +1 -0
  97. package/dist/utils/board.d.ts +116 -0
  98. package/dist/utils/board.d.ts.map +1 -0
  99. package/dist/utils/board.js +291 -0
  100. package/dist/utils/board.js.map +1 -0
  101. package/dist/utils/index.d.ts +18 -0
  102. package/dist/utils/index.d.ts.map +1 -0
  103. package/dist/utils/index.js +23 -0
  104. package/dist/utils/index.js.map +1 -0
  105. package/dist/utils/progress.d.ts +44 -0
  106. package/dist/utils/progress.d.ts.map +1 -0
  107. package/dist/utils/progress.js +104 -0
  108. package/dist/utils/progress.js.map +1 -0
  109. package/dist/utils/scramble.d.ts +35 -0
  110. package/dist/utils/scramble.d.ts.map +1 -0
  111. package/dist/utils/scramble.js +270 -0
  112. package/dist/utils/scramble.js.map +1 -0
  113. package/dist/utils/subscription.d.ts +82 -0
  114. package/dist/utils/subscription.d.ts.map +1 -0
  115. package/dist/utils/subscription.js +117 -0
  116. package/dist/utils/subscription.js.map +1 -0
  117. package/dist/utils/sudokuPresenter.d.ts +62 -0
  118. package/dist/utils/sudokuPresenter.d.ts.map +1 -0
  119. package/dist/utils/sudokuPresenter.js +403 -0
  120. package/dist/utils/sudokuPresenter.js.map +1 -0
  121. package/dist/utils/sudokuScrambler.d.ts +61 -0
  122. package/dist/utils/sudokuScrambler.d.ts.map +1 -0
  123. package/dist/utils/sudokuScrambler.js +223 -0
  124. package/dist/utils/sudokuScrambler.js.map +1 -0
  125. package/dist/utils/technique.d.ts +41 -0
  126. package/dist/utils/technique.d.ts.map +1 -0
  127. package/dist/utils/technique.js +106 -0
  128. package/dist/utils/technique.js.map +1 -0
  129. package/dist/utils/theme.d.ts +31 -0
  130. package/dist/utils/theme.d.ts.map +1 -0
  131. package/dist/utils/theme.js +40 -0
  132. package/dist/utils/theme.js.map +1 -0
  133. package/dist/utils/time.d.ts +22 -0
  134. package/dist/utils/time.d.ts.map +1 -0
  135. package/dist/utils/time.js +41 -0
  136. package/dist/utils/time.js.map +1 -0
  137. package/dist/utils/validation.d.ts +107 -0
  138. package/dist/utils/validation.d.ts.map +1 -0
  139. package/dist/utils/validation.js +248 -0
  140. package/dist/utils/validation.js.map +1 -0
  141. package/package.json +79 -0
@@ -0,0 +1,125 @@
1
+ /**
2
+ * Sudoku game types - ported from renderable/sudokuschool
3
+ *
4
+ * Uses flat 81-cell array (indexed 0-80) matching Kotlin implementation
5
+ */
6
+ /**
7
+ * Get row index (0-8) from cell index (0-80)
8
+ */
9
+ export function rowOf(index) {
10
+ return Math.floor(index / 9);
11
+ }
12
+ /**
13
+ * Get column index (0-8) from cell index (0-80)
14
+ */
15
+ export function columnOf(index) {
16
+ return index % 9;
17
+ }
18
+ /**
19
+ * Get block index (0-8) from cell index (0-80)
20
+ */
21
+ export function blockOf(index) {
22
+ const blockY = Math.floor(rowOf(index) / 3);
23
+ const blockX = Math.floor(columnOf(index) / 3);
24
+ return blockY * 3 + blockX;
25
+ }
26
+ /**
27
+ * Get cell index from row and column
28
+ */
29
+ export function cellIndex(row, column) {
30
+ return row * 9 + column;
31
+ }
32
+ // =============================================================================
33
+ // Defaults
34
+ // =============================================================================
35
+ export const DEFAULT_PLAY_SETTINGS = {
36
+ pencilmarking: false,
37
+ autoPencilmarks: false,
38
+ };
39
+ export const DEFAULT_APP_SETTINGS = {
40
+ showErrors: true,
41
+ enableAnimations: true,
42
+ symmetrical: false,
43
+ display: 'NUMERIC',
44
+ };
45
+ // =============================================================================
46
+ // Helper Functions
47
+ // =============================================================================
48
+ /**
49
+ * Create an empty cell
50
+ */
51
+ export function createEmptyCell(index) {
52
+ return {
53
+ index,
54
+ solution: null,
55
+ given: null,
56
+ input: null,
57
+ pencilmarks: null,
58
+ };
59
+ }
60
+ /**
61
+ * Create an empty board (81 empty cells)
62
+ */
63
+ export function createEmptyBoard() {
64
+ return {
65
+ cells: Array.from({ length: 81 }, (_, i) => createEmptyCell(i)),
66
+ completed: false,
67
+ entering: false,
68
+ enteringError: null,
69
+ };
70
+ }
71
+ /**
72
+ * Check if a cell has an error (input doesn't match solution)
73
+ */
74
+ export function cellHasError(cell) {
75
+ if (cell.given !== null)
76
+ return false; // Clue cells can't have errors
77
+ if (cell.input === null)
78
+ return false; // Empty cells can't have errors
79
+ if (cell.solution === null)
80
+ return false; // No solution to compare
81
+ return cell.input !== cell.solution;
82
+ }
83
+ /**
84
+ * Get all cell indices in the same row
85
+ */
86
+ export function getRowIndices(index) {
87
+ const row = rowOf(index);
88
+ return Array.from({ length: 9 }, (_, col) => row * 9 + col);
89
+ }
90
+ /**
91
+ * Get all cell indices in the same column
92
+ */
93
+ export function getColumnIndices(index) {
94
+ const col = columnOf(index);
95
+ return Array.from({ length: 9 }, (_, row) => row * 9 + col);
96
+ }
97
+ /**
98
+ * Get all cell indices in the same block
99
+ */
100
+ export function getBlockIndices(index) {
101
+ const blockIndex = blockOf(index);
102
+ const blockX = blockIndex % 3;
103
+ const blockY = Math.floor(blockIndex / 3);
104
+ const indices = [];
105
+ for (let i = 0; i < 9; i++) {
106
+ const cellX = i % 3;
107
+ const cellY = Math.floor(i / 3);
108
+ const x = blockX * 3 + cellX;
109
+ const y = blockY * 3 + cellY;
110
+ indices.push(y * 9 + x);
111
+ }
112
+ return indices;
113
+ }
114
+ /**
115
+ * Get all related cell indices (same row, column, or block)
116
+ */
117
+ export function getRelatedIndices(index) {
118
+ const rowIndices = getRowIndices(index);
119
+ const colIndices = getColumnIndices(index);
120
+ const blockIndices = getBlockIndices(index);
121
+ const allIndices = new Set([...rowIndices, ...colIndices, ...blockIndices]);
122
+ allIndices.delete(index); // Remove the cell itself
123
+ return Array.from(allIndices);
124
+ }
125
+ //# sourceMappingURL=sudoku.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sudoku.js","sourceRoot":"","sources":["../../src/types/sudoku.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Authentication utilities
3
+ */
4
+ /**
5
+ * Get user-friendly error message from Firebase error code
6
+ *
7
+ * @param code - Firebase error code (e.g., 'auth/user-not-found')
8
+ * @returns User-friendly error message
9
+ */
10
+ export declare function getFirebaseErrorMessage(code: string): string;
11
+ /**
12
+ * Extract error code from Firebase error
13
+ *
14
+ * @param error - Error object from Firebase
15
+ * @returns Error code string or empty string if not found
16
+ */
17
+ export declare function getFirebaseErrorCode(error: unknown): string;
18
+ /**
19
+ * Get user-friendly message from Firebase error object
20
+ *
21
+ * @param error - Error object from Firebase
22
+ * @returns User-friendly error message
23
+ */
24
+ export declare function formatFirebaseError(error: unknown): string;
25
+ //# sourceMappingURL=auth.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/utils/auth.ts"],"names":[],"mappings":"AAAA;;GAEG;AAeH;;;;;GAKG;AACH,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAI5D;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAK3D;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAG1D"}
@@ -0,0 +1,47 @@
1
+ /**
2
+ * Authentication utilities
3
+ */
4
+ /** Map of Firebase auth error codes to user-friendly messages */
5
+ const FIREBASE_ERROR_MESSAGES = {
6
+ 'auth/user-not-found': 'No account found with this email',
7
+ 'auth/wrong-password': 'Incorrect password',
8
+ 'auth/invalid-email': 'Invalid email address',
9
+ 'auth/invalid-credential': 'Invalid email or password',
10
+ 'auth/email-already-in-use': 'An account with this email already exists',
11
+ 'auth/weak-password': 'Password must be at least 6 characters',
12
+ 'auth/too-many-requests': 'Too many attempts. Please try again later.',
13
+ 'auth/network-request-failed': 'Network error. Please check your connection.',
14
+ 'auth/popup-closed-by-user': 'Sign in cancelled',
15
+ };
16
+ /**
17
+ * Get user-friendly error message from Firebase error code
18
+ *
19
+ * @param code - Firebase error code (e.g., 'auth/user-not-found')
20
+ * @returns User-friendly error message
21
+ */
22
+ export function getFirebaseErrorMessage(code) {
23
+ return (FIREBASE_ERROR_MESSAGES[code] ?? 'Something went wrong. Please try again.');
24
+ }
25
+ /**
26
+ * Extract error code from Firebase error
27
+ *
28
+ * @param error - Error object from Firebase
29
+ * @returns Error code string or empty string if not found
30
+ */
31
+ export function getFirebaseErrorCode(error) {
32
+ if (error && typeof error === 'object' && 'code' in error) {
33
+ return error.code;
34
+ }
35
+ return '';
36
+ }
37
+ /**
38
+ * Get user-friendly message from Firebase error object
39
+ *
40
+ * @param error - Error object from Firebase
41
+ * @returns User-friendly error message
42
+ */
43
+ export function formatFirebaseError(error) {
44
+ const code = getFirebaseErrorCode(error);
45
+ return getFirebaseErrorMessage(code);
46
+ }
47
+ //# sourceMappingURL=auth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/utils/auth.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,iEAAiE;AACjE,MAAM,uBAAuB,GAA2B;IACtD,qBAAqB,EAAE,kCAAkC;IACzD,qBAAqB,EAAE,oBAAoB;IAC3C,oBAAoB,EAAE,uBAAuB;IAC7C,yBAAyB,EAAE,2BAA2B;IACtD,2BAA2B,EAAE,2CAA2C;IACxE,oBAAoB,EAAE,wCAAwC;IAC9D,wBAAwB,EAAE,4CAA4C;IACtE,6BAA6B,EAAE,8CAA8C;IAC7E,2BAA2B,EAAE,mBAAmB;CACjD,CAAC;AAEF;;;;;GAKG;AACH,MAAM,UAAU,uBAAuB,CAAC,IAAY;IAClD,OAAO,CACL,uBAAuB,CAAC,IAAI,CAAC,IAAI,yCAAyC,CAC3E,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,oBAAoB,CAAC,KAAc;IACjD,IAAI,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,MAAM,IAAI,KAAK,EAAE,CAAC;QAC1D,OAAQ,KAA0B,CAAC,IAAI,CAAC;IAC1C,CAAC;IACD,OAAO,EAAE,CAAC;AACZ,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,mBAAmB,CAAC,KAAc;IAChD,MAAM,IAAI,GAAG,oBAAoB,CAAC,KAAK,CAAC,CAAC;IACzC,OAAO,uBAAuB,CAAC,IAAI,CAAC,CAAC;AACvC,CAAC"}
@@ -0,0 +1,116 @@
1
+ /**
2
+ * Board utilities for parsing, stringifying, and manipulating Sudoku boards
3
+ */
4
+ import type { GameBoard } from '../types';
5
+ /**
6
+ * Board size constants
7
+ */
8
+ export declare const BOARD_SIZE = 9;
9
+ export declare const BLOCK_SIZE = 3;
10
+ export declare const TOTAL_CELLS: number;
11
+ /**
12
+ * Parses an 81-character board string into a 2D array of numbers
13
+ * @param boardString - 81-character string where '0' or '.' represents empty cells
14
+ * @returns 9x9 array of numbers (0 = empty, 1-9 = filled)
15
+ */
16
+ export declare function parseBoardString(boardString: string): number[][];
17
+ /**
18
+ * Converts a 2D number array back to an 81-character string
19
+ * @param board - 9x9 array of numbers
20
+ * @returns 81-character string
21
+ */
22
+ export declare function stringifyBoard(board: number[][]): string;
23
+ /**
24
+ * Creates an initial GameBoard from puzzle and solution strings
25
+ * @param puzzle - 81-character puzzle string
26
+ * @param solution - 81-character solution string
27
+ * @returns GameBoard with initialized cell states
28
+ */
29
+ export declare function createGameBoard(puzzle: string, solution: string): GameBoard;
30
+ /**
31
+ * Gets the current board state as a string (user's current progress)
32
+ * @param board - GameBoard
33
+ * @returns 81-character string representing current state
34
+ */
35
+ export declare function getBoardStateString(board: GameBoard): string;
36
+ /**
37
+ * Gets the pencilmarks as a comma-separated string for the solver API
38
+ * @param board - GameBoard
39
+ * @returns Comma-separated string of pencilmarks for each cell
40
+ */
41
+ export declare function getPencilmarksString(board: GameBoard): string;
42
+ /**
43
+ * Gets the block index (0-8) for a cell position
44
+ * @param row - Row index (0-8)
45
+ * @param col - Column index (0-8)
46
+ * @returns Block index (0-8)
47
+ */
48
+ export declare function getBlockIndex(row: number, col: number): number;
49
+ /**
50
+ * Gets all cells in the same row
51
+ * @param row - Row index (0-8)
52
+ * @returns Array of {row, column} positions
53
+ */
54
+ export declare function getRowCells(row: number): Array<{
55
+ row: number;
56
+ column: number;
57
+ }>;
58
+ /**
59
+ * Gets all cells in the same column
60
+ * @param col - Column index (0-8)
61
+ * @returns Array of {row, column} positions
62
+ */
63
+ export declare function getColumnCells(col: number): Array<{
64
+ row: number;
65
+ column: number;
66
+ }>;
67
+ /**
68
+ * Gets all cells in the same block
69
+ * @param blockIndex - Block index (0-8)
70
+ * @returns Array of {row, column} positions
71
+ */
72
+ export declare function getBlockCells(blockIndex: number): Array<{
73
+ row: number;
74
+ column: number;
75
+ }>;
76
+ /**
77
+ * Gets all related cells (same row, column, or block)
78
+ * @param row - Row index
79
+ * @param col - Column index
80
+ * @returns Array of {row, column} positions (excluding the cell itself)
81
+ */
82
+ export declare function getRelatedCells(row: number, col: number): Array<{
83
+ row: number;
84
+ column: number;
85
+ }>;
86
+ /**
87
+ * Checks if a value is valid for a cell position (not checking solution, just Sudoku rules)
88
+ * @param board - GameBoard
89
+ * @param row - Row index
90
+ * @param col - Column index
91
+ * @param value - Value to check (1-9)
92
+ * @returns true if the value doesn't conflict with existing values
93
+ */
94
+ export declare function isValidPlacement(board: GameBoard, row: number, col: number, value: number): boolean;
95
+ /**
96
+ * Clones a GameBoard (deep copy)
97
+ * @param board - GameBoard to clone
98
+ * @returns New GameBoard with copied values
99
+ */
100
+ export declare function cloneBoard(board: GameBoard): GameBoard;
101
+ /**
102
+ * Gets all empty cells in the board
103
+ * @param board - GameBoard
104
+ * @returns Array of {row, column} positions
105
+ */
106
+ export declare function getEmptyCells(board: GameBoard): Array<{
107
+ row: number;
108
+ column: number;
109
+ }>;
110
+ /**
111
+ * Counts the number of filled cells
112
+ * @param board - GameBoard
113
+ * @returns Number of filled cells
114
+ */
115
+ export declare function countFilledCells(board: GameBoard): number;
116
+ //# sourceMappingURL=board.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"board.d.ts","sourceRoot":"","sources":["../../src/utils/board.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAa,SAAS,EAAE,MAAM,UAAU,CAAC;AAErD;;GAEG;AACH,eAAO,MAAM,UAAU,IAAI,CAAC;AAC5B,eAAO,MAAM,UAAU,IAAI,CAAC;AAC5B,eAAO,MAAM,WAAW,QAA0B,CAAC;AAEnD;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,EAAE,EAAE,CAyBhE;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,GAAG,MAAM,CAuBxD;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,SAAS,CA0B3E;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,SAAS,GAAG,MAAM,CAS5D;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,SAAS,GAAG,MAAM,CAc7D;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAI9D;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CACzB,GAAG,EAAE,MAAM,GACV,KAAK,CAAC;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CAMxC;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAC5B,GAAG,EAAE,MAAM,GACV,KAAK,CAAC;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CAMxC;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAC3B,UAAU,EAAE,MAAM,GACjB,KAAK,CAAC;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CAaxC;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAC7B,GAAG,EAAE,MAAM,EACX,GAAG,EAAE,MAAM,GACV,KAAK,CAAC;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CA0BxC;AAED;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,SAAS,EAChB,GAAG,EAAE,MAAM,EACX,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,MAAM,GACZ,OAAO,CA+BT;AAED;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,SAAS,GAAG,SAAS,CAOtD;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAC3B,KAAK,EAAE,SAAS,GACf,KAAK,CAAC;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CAUxC;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,SAAS,GAAG,MAAM,CAUzD"}
@@ -0,0 +1,291 @@
1
+ /**
2
+ * Board utilities for parsing, stringifying, and manipulating Sudoku boards
3
+ */
4
+ /**
5
+ * Board size constants
6
+ */
7
+ export const BOARD_SIZE = 9;
8
+ export const BLOCK_SIZE = 3;
9
+ export const TOTAL_CELLS = BOARD_SIZE * BOARD_SIZE;
10
+ /**
11
+ * Parses an 81-character board string into a 2D array of numbers
12
+ * @param boardString - 81-character string where '0' or '.' represents empty cells
13
+ * @returns 9x9 array of numbers (0 = empty, 1-9 = filled)
14
+ */
15
+ export function parseBoardString(boardString) {
16
+ if (boardString.length !== TOTAL_CELLS) {
17
+ throw new Error(`Invalid board string length: expected ${TOTAL_CELLS}, got ${boardString.length}`);
18
+ }
19
+ const board = [];
20
+ for (let row = 0; row < BOARD_SIZE; row++) {
21
+ const rowArray = [];
22
+ for (let col = 0; col < BOARD_SIZE; col++) {
23
+ const index = row * BOARD_SIZE + col;
24
+ const char = boardString[index];
25
+ if (char === undefined) {
26
+ throw new Error(`Missing character at position ${index}`);
27
+ }
28
+ const value = char === '.' ? 0 : parseInt(char, 10);
29
+ if (isNaN(value) || value < 0 || value > 9) {
30
+ throw new Error(`Invalid character at position ${index}: '${char}'`);
31
+ }
32
+ rowArray.push(value);
33
+ }
34
+ board.push(rowArray);
35
+ }
36
+ return board;
37
+ }
38
+ /**
39
+ * Converts a 2D number array back to an 81-character string
40
+ * @param board - 9x9 array of numbers
41
+ * @returns 81-character string
42
+ */
43
+ export function stringifyBoard(board) {
44
+ if (board.length !== BOARD_SIZE) {
45
+ throw new Error(`Invalid board rows: expected ${BOARD_SIZE}, got ${board.length}`);
46
+ }
47
+ let result = '';
48
+ for (let row = 0; row < BOARD_SIZE; row++) {
49
+ if (board[row]?.length !== BOARD_SIZE) {
50
+ throw new Error(`Invalid row ${row} length: expected ${BOARD_SIZE}, got ${board[row]?.length}`);
51
+ }
52
+ for (let col = 0; col < BOARD_SIZE; col++) {
53
+ const value = board[row]?.[col];
54
+ if (value === undefined || value < 0 || value > 9) {
55
+ throw new Error(`Invalid value at (${row}, ${col}): ${value}`);
56
+ }
57
+ result += value.toString();
58
+ }
59
+ }
60
+ return result;
61
+ }
62
+ /**
63
+ * Creates an initial GameBoard from puzzle and solution strings
64
+ * @param puzzle - 81-character puzzle string
65
+ * @param solution - 81-character solution string
66
+ * @returns GameBoard with initialized cell states
67
+ */
68
+ export function createGameBoard(puzzle, solution) {
69
+ const puzzleArray = parseBoardString(puzzle);
70
+ // Validate solution string (will throw if invalid)
71
+ parseBoardString(solution);
72
+ const board = [];
73
+ for (let row = 0; row < BOARD_SIZE; row++) {
74
+ const rowArray = [];
75
+ for (let col = 0; col < BOARD_SIZE; col++) {
76
+ const puzzleValue = puzzleArray[row]?.[col] ?? 0;
77
+ const isClue = puzzleValue !== 0;
78
+ rowArray.push({
79
+ row,
80
+ column: col,
81
+ value: isClue ? puzzleValue : null,
82
+ isClue,
83
+ isError: false,
84
+ pencilmarks: new Set(),
85
+ isSelected: false,
86
+ isHighlighted: false,
87
+ isSameValue: false,
88
+ });
89
+ }
90
+ board.push(rowArray);
91
+ }
92
+ return board;
93
+ }
94
+ /**
95
+ * Gets the current board state as a string (user's current progress)
96
+ * @param board - GameBoard
97
+ * @returns 81-character string representing current state
98
+ */
99
+ export function getBoardStateString(board) {
100
+ let result = '';
101
+ for (let row = 0; row < BOARD_SIZE; row++) {
102
+ for (let col = 0; col < BOARD_SIZE; col++) {
103
+ const cell = board[row]?.[col];
104
+ result += cell?.value?.toString() ?? '0';
105
+ }
106
+ }
107
+ return result;
108
+ }
109
+ /**
110
+ * Gets the pencilmarks as a comma-separated string for the solver API
111
+ * @param board - GameBoard
112
+ * @returns Comma-separated string of pencilmarks for each cell
113
+ */
114
+ export function getPencilmarksString(board) {
115
+ const pencilmarks = [];
116
+ for (let row = 0; row < BOARD_SIZE; row++) {
117
+ for (let col = 0; col < BOARD_SIZE; col++) {
118
+ const cell = board[row]?.[col];
119
+ if (cell && cell.pencilmarks.size > 0) {
120
+ const sorted = Array.from(cell.pencilmarks).sort((a, b) => a - b);
121
+ pencilmarks.push(sorted.join(''));
122
+ }
123
+ else {
124
+ pencilmarks.push('');
125
+ }
126
+ }
127
+ }
128
+ return pencilmarks.join(',');
129
+ }
130
+ /**
131
+ * Gets the block index (0-8) for a cell position
132
+ * @param row - Row index (0-8)
133
+ * @param col - Column index (0-8)
134
+ * @returns Block index (0-8)
135
+ */
136
+ export function getBlockIndex(row, col) {
137
+ const blockRow = Math.floor(row / BLOCK_SIZE);
138
+ const blockCol = Math.floor(col / BLOCK_SIZE);
139
+ return blockRow * BLOCK_SIZE + blockCol;
140
+ }
141
+ /**
142
+ * Gets all cells in the same row
143
+ * @param row - Row index (0-8)
144
+ * @returns Array of {row, column} positions
145
+ */
146
+ export function getRowCells(row) {
147
+ const cells = [];
148
+ for (let col = 0; col < BOARD_SIZE; col++) {
149
+ cells.push({ row, column: col });
150
+ }
151
+ return cells;
152
+ }
153
+ /**
154
+ * Gets all cells in the same column
155
+ * @param col - Column index (0-8)
156
+ * @returns Array of {row, column} positions
157
+ */
158
+ export function getColumnCells(col) {
159
+ const cells = [];
160
+ for (let row = 0; row < BOARD_SIZE; row++) {
161
+ cells.push({ row, column: col });
162
+ }
163
+ return cells;
164
+ }
165
+ /**
166
+ * Gets all cells in the same block
167
+ * @param blockIndex - Block index (0-8)
168
+ * @returns Array of {row, column} positions
169
+ */
170
+ export function getBlockCells(blockIndex) {
171
+ const cells = [];
172
+ const blockRow = Math.floor(blockIndex / BLOCK_SIZE);
173
+ const blockCol = blockIndex % BLOCK_SIZE;
174
+ const startRow = blockRow * BLOCK_SIZE;
175
+ const startCol = blockCol * BLOCK_SIZE;
176
+ for (let r = 0; r < BLOCK_SIZE; r++) {
177
+ for (let c = 0; c < BLOCK_SIZE; c++) {
178
+ cells.push({ row: startRow + r, column: startCol + c });
179
+ }
180
+ }
181
+ return cells;
182
+ }
183
+ /**
184
+ * Gets all related cells (same row, column, or block)
185
+ * @param row - Row index
186
+ * @param col - Column index
187
+ * @returns Array of {row, column} positions (excluding the cell itself)
188
+ */
189
+ export function getRelatedCells(row, col) {
190
+ const related = new Map();
191
+ // Add row cells
192
+ for (const cell of getRowCells(row)) {
193
+ if (cell.row !== row || cell.column !== col) {
194
+ related.set(`${cell.row},${cell.column}`, cell);
195
+ }
196
+ }
197
+ // Add column cells
198
+ for (const cell of getColumnCells(col)) {
199
+ if (cell.row !== row || cell.column !== col) {
200
+ related.set(`${cell.row},${cell.column}`, cell);
201
+ }
202
+ }
203
+ // Add block cells
204
+ const blockIndex = getBlockIndex(row, col);
205
+ for (const cell of getBlockCells(blockIndex)) {
206
+ if (cell.row !== row || cell.column !== col) {
207
+ related.set(`${cell.row},${cell.column}`, cell);
208
+ }
209
+ }
210
+ return Array.from(related.values());
211
+ }
212
+ /**
213
+ * Checks if a value is valid for a cell position (not checking solution, just Sudoku rules)
214
+ * @param board - GameBoard
215
+ * @param row - Row index
216
+ * @param col - Column index
217
+ * @param value - Value to check (1-9)
218
+ * @returns true if the value doesn't conflict with existing values
219
+ */
220
+ export function isValidPlacement(board, row, col, value) {
221
+ if (value < 1 || value > 9) {
222
+ return false;
223
+ }
224
+ // Check row
225
+ for (let c = 0; c < BOARD_SIZE; c++) {
226
+ if (c !== col && board[row]?.[c]?.value === value) {
227
+ return false;
228
+ }
229
+ }
230
+ // Check column
231
+ for (let r = 0; r < BOARD_SIZE; r++) {
232
+ if (r !== row && board[r]?.[col]?.value === value) {
233
+ return false;
234
+ }
235
+ }
236
+ // Check block
237
+ const blockStartRow = Math.floor(row / BLOCK_SIZE) * BLOCK_SIZE;
238
+ const blockStartCol = Math.floor(col / BLOCK_SIZE) * BLOCK_SIZE;
239
+ for (let r = blockStartRow; r < blockStartRow + BLOCK_SIZE; r++) {
240
+ for (let c = blockStartCol; c < blockStartCol + BLOCK_SIZE; c++) {
241
+ if ((r !== row || c !== col) && board[r]?.[c]?.value === value) {
242
+ return false;
243
+ }
244
+ }
245
+ }
246
+ return true;
247
+ }
248
+ /**
249
+ * Clones a GameBoard (deep copy)
250
+ * @param board - GameBoard to clone
251
+ * @returns New GameBoard with copied values
252
+ */
253
+ export function cloneBoard(board) {
254
+ return board.map(row => row.map(cell => ({
255
+ ...cell,
256
+ pencilmarks: new Set(cell.pencilmarks),
257
+ })));
258
+ }
259
+ /**
260
+ * Gets all empty cells in the board
261
+ * @param board - GameBoard
262
+ * @returns Array of {row, column} positions
263
+ */
264
+ export function getEmptyCells(board) {
265
+ const emptyCells = [];
266
+ for (let row = 0; row < BOARD_SIZE; row++) {
267
+ for (let col = 0; col < BOARD_SIZE; col++) {
268
+ if (board[row]?.[col]?.value === null) {
269
+ emptyCells.push({ row, column: col });
270
+ }
271
+ }
272
+ }
273
+ return emptyCells;
274
+ }
275
+ /**
276
+ * Counts the number of filled cells
277
+ * @param board - GameBoard
278
+ * @returns Number of filled cells
279
+ */
280
+ export function countFilledCells(board) {
281
+ let count = 0;
282
+ for (let row = 0; row < BOARD_SIZE; row++) {
283
+ for (let col = 0; col < BOARD_SIZE; col++) {
284
+ if (board[row]?.[col]?.value !== null) {
285
+ count++;
286
+ }
287
+ }
288
+ }
289
+ return count;
290
+ }
291
+ //# sourceMappingURL=board.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"board.js","sourceRoot":"","sources":["../../src/utils/board.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Utility exports for Sudojo library
3
+ */
4
+ export { BLOCK_SIZE, BOARD_SIZE, cloneBoard, countFilledCells, createGameBoard, getBlockCells, getBlockIndex, getBoardStateString, getColumnCells, getEmptyCells, getPencilmarksString, getRelatedCells, getRowCells, isValidPlacement, parseBoardString, stringifyBoard, TOTAL_CELLS, } from './board';
5
+ export { noScramble, scrambleBoard } from './scramble';
6
+ export { autoRemovePencilmarks, clearHighlights, countMistakes, getIncorrectCells, getProgressPercentage, isBoardFilled, isCellCorrect, isGameComplete, isValueCorrect, updateCellErrors, updateCellHighlights, validateGameState, } from './validation';
7
+ export type { ScramblerProtocol, ScrambleResult as SudokuScrambleResult, } from './sudokuScrambler';
8
+ export { Scrambler, NonScrambler, scrambleBoard as scrambleSudokuBoard, parsePuzzleString, cellsToPuzzleString, cellsToStateString, cellsToInputString, cellsToPencilmarksString, } from './sudokuScrambler';
9
+ export type { PresentBoardOptions } from './sudokuPresenter';
10
+ export { presentBoard, calculateCellHints, themeColorToCSS, getColorPalette, getCellsWithDigit, getSelectedDigit, computeSelectedDigitCells, } from './sudokuPresenter';
11
+ export { formatTime, parseTime } from './time';
12
+ export { calculateStats, calculateStreak, isPuzzleCompleted, getCompletedLevelIds, getCompletedDailyDates, } from './progress';
13
+ export { getFirebaseErrorMessage, getFirebaseErrorCode, formatFirebaseError, } from './auth';
14
+ export type { ThemePreference, ResolvedTheme } from './theme';
15
+ export { THEME_STORAGE_KEY, getSystemTheme, resolveTheme, isValidThemePreference, } from './theme';
16
+ export { convertPackageToProduct, parseCustomerInfo, getPeriodDisplayName, isBestValuePlan, getRevenueCatErrorMessage, } from './subscription';
17
+ export { getTechniqueIconUrl, TECHNIQUE_TO_HELP_FILE, HELP_FILE_TO_TECHNIQUE, getHelpFileUrl, getTechniqueFromHelpFile, extractBodyContent, } from './technique';
18
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,EACL,UAAU,EACV,UAAU,EACV,UAAU,EACV,gBAAgB,EAChB,eAAe,EACf,aAAa,EACb,aAAa,EACb,mBAAmB,EACnB,cAAc,EACd,aAAa,EACb,oBAAoB,EACpB,eAAe,EACf,WAAW,EACX,gBAAgB,EAChB,gBAAgB,EAChB,cAAc,EACd,WAAW,GACZ,MAAM,SAAS,CAAC;AAGjB,OAAO,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAGvD,OAAO,EACL,qBAAqB,EACrB,eAAe,EACf,aAAa,EACb,iBAAiB,EACjB,qBAAqB,EACrB,aAAa,EACb,aAAa,EACb,cAAc,EACd,cAAc,EACd,gBAAgB,EAChB,oBAAoB,EACpB,iBAAiB,GAClB,MAAM,cAAc,CAAC;AAGtB,YAAY,EACV,iBAAiB,EACjB,cAAc,IAAI,oBAAoB,GACvC,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,SAAS,EACT,YAAY,EACZ,aAAa,IAAI,mBAAmB,EACpC,iBAAiB,EACjB,mBAAmB,EACnB,kBAAkB,EAClB,kBAAkB,EAClB,wBAAwB,GACzB,MAAM,mBAAmB,CAAC;AAG3B,YAAY,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAC7D,OAAO,EACL,YAAY,EACZ,kBAAkB,EAClB,eAAe,EACf,eAAe,EACf,iBAAiB,EACjB,gBAAgB,EAChB,yBAAyB,GAC1B,MAAM,mBAAmB,CAAC;AAG3B,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AAG/C,OAAO,EACL,cAAc,EACd,eAAe,EACf,iBAAiB,EACjB,oBAAoB,EACpB,sBAAsB,GACvB,MAAM,YAAY,CAAC;AAGpB,OAAO,EACL,uBAAuB,EACvB,oBAAoB,EACpB,mBAAmB,GACpB,MAAM,QAAQ,CAAC;AAGhB,YAAY,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAC9D,OAAO,EACL,iBAAiB,EACjB,cAAc,EACd,YAAY,EACZ,sBAAsB,GACvB,MAAM,SAAS,CAAC;AAGjB,OAAO,EACL,uBAAuB,EACvB,iBAAiB,EACjB,oBAAoB,EACpB,eAAe,EACf,yBAAyB,GAC1B,MAAM,gBAAgB,CAAC;AAGxB,OAAO,EACL,mBAAmB,EACnB,sBAAsB,EACtB,sBAAsB,EACtB,cAAc,EACd,wBAAwB,EACxB,kBAAkB,GACnB,MAAM,aAAa,CAAC"}