@sudobility/sudojo_lib 0.0.203 → 0.0.204

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.
@@ -4,7 +4,7 @@
4
4
  */
5
5
  import type { SudokuCell } from '../types';
6
6
  import type { NetworkClient } from '@sudobility/types';
7
- import { type ScannedBoard } from '../utils/scannedBoard';
7
+ import type { ScannedBoard } from '../utils/scannedBoard';
8
8
  export interface ValidatedPuzzle {
9
9
  puzzle: string;
10
10
  solution: string;
@@ -23,12 +23,12 @@ export interface UseBoardEntryOptions {
23
23
  }
24
24
  /**
25
25
  * What the game should apply once the entered puzzle is validated: the
26
- * scanned player digits and/or the entry pencilmarks. Pass the fields to the
26
+ * entry pencilmarks (a scan's player digits are already givens). Pass the fields to the
27
27
  * game as initialInput / initialPencilmarks / initialAutoPencilmarks (or to
28
28
  * useSudoku's applyHintData).
29
29
  */
30
30
  export interface BoardEntryPlayState {
31
- /** 81-char player input ('0' = none). '0'.repeat(81) when only pencilmarks exist */
31
+ /** 81-char player input; always '0'.repeat(81) (only pencilmarks are restored) */
32
32
  input?: string;
33
33
  /** 81 comma-separated pencilmark entries */
34
34
  pencilmarks?: string;
@@ -60,7 +60,7 @@ export interface UseBoardEntryReturn {
60
60
  reset: () => void;
61
61
  /** Number of clues entered */
62
62
  clueCount: number;
63
- /** Set cells from an 81-character puzzle string (clears pencilmarks and scanned input) */
63
+ /** Set cells from an 81-character puzzle string (clears pencilmarks) */
64
64
  setCellsFromPuzzle: (puzzle: string) => void;
65
65
  /** Per-cell entry pencilmarks (81 sorted digit arrays; [] = none) */
66
66
  pencilmarks: number[][];
@@ -93,15 +93,18 @@ export interface UseBoardEntryReturn {
93
93
  /** Whether Validate may run (enough clues and not already validating) */
94
94
  canValidate: boolean;
95
95
  /**
96
- * Load a scanned board: givens from `original`, pencilmarks and autopencil
97
- * from the scan, and the player's digits as `scannedInput`.
96
+ * Load a scanned board: givens from `puzzle` (the printed givens merged
97
+ * with the player's digits), plus the scan's pencilmarks and autopencil.
98
98
  */
99
99
  applyScan: (scanned: ScannedBoard) => void;
100
- /** The scanned player digits (81 chars), or null when the scan had none */
101
- scannedInput: string | null;
102
100
  /**
103
- * What the game should apply once validated (scanned input and/or entry
104
- * pencilmarks), or undefined when there is nothing to restore.
101
+ * @deprecated Always null. A scan's player digits are merged into the
102
+ * givens (applyScan uses `ScannedBoard.puzzle`), not restored as input.
103
+ */
104
+ scannedInput: null;
105
+ /**
106
+ * What the game should apply once validated (the entry pencilmarks), or
107
+ * undefined when there are none.
105
108
  */
106
109
  initialPlayState: BoardEntryPlayState | undefined;
107
110
  }
@@ -1 +1 @@
1
- {"version":3,"file":"useBoardEntry.d.ts","sourceRoot":"","sources":["../../src/hooks/useBoardEntry.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"useBoardEntry.d.ts","sourceRoot":"","sources":["../../src/hooks/useBoardEntry.ts"],"names":[],"mappings":"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"}
@@ -8,7 +8,6 @@ import { useSolverValidate } from '@sudobility/sudojo_client';
8
8
  import { MIN_CLUES } from '@sudobility/sudojo_types';
9
9
  import { cellsToPuzzleString, countClues } from '../utils/sudokuScrambler';
10
10
  import { useResolvedSudojoApi } from '../context/SudojoApiContext';
11
- import { hasScannedInput } from '../utils/scannedBoard';
12
11
  import { parsePencilmarksString, pencilmarksToString, } from '../utils/techniqueWalkthrough';
13
12
  /**
14
13
  * Create an empty 81-cell board for entry mode
@@ -59,7 +58,6 @@ export function useBoardEntry(options = {}) {
59
58
  const [cells, setCells] = useState(createEmptyCells);
60
59
  const [pencilmarks, setPencilmarks] = useState(createEmptyPencilmarks);
61
60
  const [autopencil, setAutopencil] = useState(false);
62
- const [scannedInput, setScannedInput] = useState(null);
63
61
  const [isPencilMode, setIsPencilMode] = useState(false);
64
62
  const [selectedIndex, setSelectedIndex] = useState(null);
65
63
  const [validationError, setValidationError] = useState(null);
@@ -197,7 +195,6 @@ export function useBoardEntry(options = {}) {
197
195
  setCells(createEmptyCells());
198
196
  setPencilmarks(createEmptyPencilmarks());
199
197
  setAutopencil(false);
200
- setScannedInput(null);
201
198
  setIsPencilMode(false);
202
199
  setSelectedIndex(null);
203
200
  setValidationError(null);
@@ -211,7 +208,6 @@ export function useBoardEntry(options = {}) {
211
208
  setCells(puzzleStringToCells(puzzle));
212
209
  setPencilmarks(createEmptyPencilmarks());
213
210
  setAutopencil(false);
214
- setScannedInput(null);
215
211
  setSelectedIndex(null);
216
212
  setValidationError(null);
217
213
  setValidatedPuzzle(null);
@@ -256,15 +252,15 @@ export function useBoardEntry(options = {}) {
256
252
  setGiven(value);
257
253
  }
258
254
  }, [selectedIndex, cells, erase, setGiven]);
259
- // Load a scanned board (givens, pencilmarks, player digits)
255
+ // Load a scanned board: the merged board (givens + the player's digits)
256
+ // becomes the givens; pencilmarks carry over
260
257
  const applyScan = useCallback((scanned) => {
261
- setCellsFromPuzzle(scanned.original);
258
+ setCellsFromPuzzle(scanned.puzzle);
262
259
  const parsed = parsePencilmarksString(scanned.pencilmarks);
263
260
  setPencilmarks(parsed.length === 81
264
261
  ? parsed.map(pm => (pm ? [...pm].sort((a, b) => a - b) : []))
265
262
  : createEmptyPencilmarks());
266
263
  setAutopencil(scanned.autopencil);
267
- setScannedInput(hasScannedInput(scanned) ? scanned.user : null);
268
264
  }, [setCellsFromPuzzle]);
269
265
  // Entry cells with pencilmarks merged in (givens never show pencilmarks)
270
266
  const displayCells = useMemo(() => cells.map((cell, i) => {
@@ -275,20 +271,13 @@ export function useBoardEntry(options = {}) {
275
271
  }), [cells, pencilmarks]);
276
272
  const hasPencilmarks = useMemo(() => pencilmarks.some(pm => pm.length > 0), [pencilmarks]);
277
273
  const pencilmarksString = useMemo(() => pencilmarksToString(pencilmarks.map(pm => [...pm])), [pencilmarks]);
278
- const initialPlayState = useMemo(() => {
279
- if (!scannedInput && !hasPencilmarks)
280
- return undefined;
281
- // A given corrected after the scan wins over a scanned digit there.
282
- const input = scannedInput
283
- ? Array.from(scannedInput, (ch, i) => cells[i]?.given !== null ? '0' : ch).join('')
284
- : EMPTY_INPUT;
285
- const state = { input };
286
- if (hasPencilmarks) {
287
- state.pencilmarks = pencilmarksString;
288
- state.autopencil = autopencil;
274
+ const initialPlayState = useMemo(() => hasPencilmarks
275
+ ? {
276
+ input: EMPTY_INPUT,
277
+ pencilmarks: pencilmarksString,
278
+ autopencil,
289
279
  }
290
- return state;
291
- }, [scannedInput, hasPencilmarks, pencilmarksString, autopencil, cells]);
280
+ : undefined, [hasPencilmarks, pencilmarksString, autopencil]);
292
281
  const canValidate = clueCount >= MIN_CLUES && !isValidating;
293
282
  return {
294
283
  cells,
@@ -317,7 +306,7 @@ export function useBoardEntry(options = {}) {
317
306
  toggleGiven,
318
307
  canValidate,
319
308
  applyScan,
320
- scannedInput,
309
+ scannedInput: null,
321
310
  initialPlayState,
322
311
  };
323
312
  }
@@ -1 +1 @@
1
- {"version":3,"file":"useBoardEntry.js","sourceRoot":"","sources":["../../src/hooks/useBoardEntry.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Hook for managing Sudoku board entry mode state\n * Allows users to enter given clues for a custom puzzle\n */\n\nimport { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport type { SudokuCell } from '../types';\nimport { createEmptyBoard } from '../types';\nimport { useSolverValidate } from '@sudobility/sudojo_client';\nimport { MIN_CLUES } from '@sudobility/sudojo_types';\nimport { cellsToPuzzleString, countClues } from '../utils/sudokuScrambler';\nimport type { NetworkClient } from '@sudobility/types';\nimport { useResolvedSudojoApi } from '../context/SudojoApiContext';\nimport { hasScannedInput, type ScannedBoard } from '../utils/scannedBoard';\nimport {\n parsePencilmarksString,\n pencilmarksToString,\n} from '../utils/techniqueWalkthrough';\n\nexport interface ValidatedPuzzle {\n puzzle: string;\n solution: string;\n /** Difficulty level (1-12) the solver rated the puzzle at */\n level?: number;\n /** Solver's difficulty_score for the puzzle, when the API sends it */\n difficultyScore?: number | undefined;\n}\n\nexport interface UseBoardEntryOptions {\n /** Network client for API calls (default: SudojoApiProvider) */\n networkClient?: NetworkClient | undefined;\n /** Base URL for the Sudojo API (default: SudojoApiProvider) */\n baseUrl?: string | undefined;\n /** Access token (default: SudojoApiProvider) */\n token?: string | null | undefined;\n}\n\n/**\n * What the game should apply once the entered puzzle is validated: the\n * scanned player digits and/or the entry pencilmarks. Pass the fields to the\n * game as initialInput / initialPencilmarks / initialAutoPencilmarks (or to\n * useSudoku's applyHintData).\n */\nexport interface BoardEntryPlayState {\n /** 81-char player input ('0' = none). '0'.repeat(81) when only pencilmarks exist */\n input?: string;\n /** 81 comma-separated pencilmark entries */\n pencilmarks?: string;\n /** Whether the pencilmarks were auto-filled */\n autopencil?: boolean;\n}\n\nexport interface UseBoardEntryReturn {\n /** 81 cells with given values only */\n cells: SudokuCell[];\n /** Currently selected cell index */\n selectedIndex: number | null;\n /** Whether validation is in progress */\n isValidating: boolean;\n /** Validation error message key */\n validationError: string | null;\n /** Validated puzzle data (puzzle + solution + solver rating) */\n validatedPuzzle: ValidatedPuzzle | null;\n /** Select a cell by index */\n selectCell: (index: number) => void;\n /** Set a given value at the selected cell */\n setGiven: (value: number) => void;\n /** Erase the selected cell */\n erase: () => void;\n /** Get the puzzle as an 81-character string */\n getPuzzleString: () => string;\n /** Trigger validation */\n validate: () => void;\n /** Reset to empty board */\n reset: () => void;\n /** Number of clues entered */\n clueCount: number;\n /** Set cells from an 81-character puzzle string (clears pencilmarks and scanned input) */\n setCellsFromPuzzle: (puzzle: string) => void;\n\n // --- Entry pencilmarks ---------------------------------------------------\n /** Per-cell entry pencilmarks (81 sorted digit arrays; [] = none) */\n pencilmarks: number[][];\n /** Whether the pencilmarks were auto-filled (from a scan) */\n autopencil: boolean;\n /** Whether any cell has pencilmarks */\n hasPencilmarks: boolean;\n /** Pencilmarks as 81 comma-separated entries (e.g. \"12,,9,...\") */\n pencilmarksString: string;\n /** Toggle a pencilmark digit on the selected cell (ignored on givens) */\n togglePencilmark: (digit: number) => void;\n /** `cells` with the entry pencilmarks merged in, for display */\n displayCells: SudokuCell[];\n /** Whether digit input goes to pencilmarks instead of givens */\n isPencilMode: boolean;\n /** Toggle pencil mode */\n togglePencilMode: () => void;\n /** Set pencil mode */\n setPencilMode: (on: boolean) => void;\n /**\n * Route a digit: in pencil mode toggle a pencilmark, otherwise set a given\n * (web/RN entry keypad behavior).\n */\n enterDigit: (value: number) => void;\n\n // --- Givens --------------------------------------------------------------\n /**\n * Set a given at the selected cell, or erase it when the cell already holds\n * that digit (extension keypad behavior).\n */\n toggleGiven: (value: number) => void;\n /** Whether Validate may run (enough clues and not already validating) */\n canValidate: boolean;\n\n // --- Scans ---------------------------------------------------------------\n /**\n * Load a scanned board: givens from `original`, pencilmarks and autopencil\n * from the scan, and the player's digits as `scannedInput`.\n */\n applyScan: (scanned: ScannedBoard) => void;\n /** The scanned player digits (81 chars), or null when the scan had none */\n scannedInput: string | null;\n /**\n * What the game should apply once validated (scanned input and/or entry\n * pencilmarks), or undefined when there is nothing to restore.\n */\n initialPlayState: BoardEntryPlayState | undefined;\n}\n\n/**\n * Create an empty 81-cell board for entry mode\n */\nfunction createEmptyCells(): SudokuCell[] {\n return createEmptyBoard().cells;\n}\n\n/**\n * Create a board from an 81-character puzzle string\n * '0' or '.' for empty, '1'-'9' for given values\n */\nfunction puzzleStringToCells(puzzle: string): SudokuCell[] {\n if (puzzle.length !== 81) {\n return createEmptyCells();\n }\n\n return Array.from({ length: 81 }, (_, index) => {\n const char = puzzle.charAt(index);\n const value = parseInt(char, 10);\n const given = value >= 1 && value <= 9 ? value : null;\n\n return {\n index,\n solution: null,\n given,\n input: null,\n pencilmarks: null,\n };\n });\n}\n\n/**\n * Classify a validation error message into a translation key\n */\nfunction classifyValidationError(errorMsg: string): string {\n const lower = errorMsg.toLowerCase();\n if (lower.includes('multiple') || lower.includes('not unique')) {\n return 'enter.errors.multipleSolutions';\n }\n if (lower.includes('cannot solve') || lower.includes('no solution')) {\n return 'enter.errors.noSolution';\n }\n return 'enter.errors.validationFailed';\n}\n\nfunction createEmptyPencilmarks(): number[][] {\n return Array.from({ length: 81 }, () => []);\n}\n\nconst EMPTY_INPUT = '0'.repeat(81);\n\nexport function useBoardEntry(\n options: UseBoardEntryOptions = {}\n): UseBoardEntryReturn {\n const { networkClient, baseUrl, token } = useResolvedSudojoApi(\n options,\n 'useBoardEntry'\n );\n const [cells, setCells] = useState<SudokuCell[]>(createEmptyCells);\n const [pencilmarks, setPencilmarks] = useState<number[][]>(\n createEmptyPencilmarks\n );\n const [autopencil, setAutopencil] = useState(false);\n const [scannedInput, setScannedInput] = useState<string | null>(null);\n const [isPencilMode, setIsPencilMode] = useState(false);\n const [selectedIndex, setSelectedIndex] = useState<number | null>(null);\n const [validationError, setValidationError] = useState<string | null>(null);\n const [validatedPuzzle, setValidatedPuzzle] =\n useState<ValidatedPuzzle | null>(null);\n const [shouldValidate, setShouldValidate] = useState(false);\n\n // Compute puzzle string for validation\n const puzzleString = useMemo(() => cellsToPuzzleString(cells), [cells]);\n const clueCount = useMemo(() => countClues(cells), [cells]);\n\n // Use the solver validate hook\n const {\n data: validateData,\n error: validateError,\n isLoading: isValidating,\n } = useSolverValidate(\n networkClient,\n baseUrl,\n token,\n { original: puzzleString },\n {\n enabled: shouldValidate && clueCount >= MIN_CLUES,\n retry: false,\n }\n );\n\n // Track whether we've already processed this validation result\n const processedDataRef = useRef<typeof validateData | null>(null);\n const processedErrorRef = useRef<typeof validateError | null>(null);\n\n // Handle validation result\n useEffect(() => {\n if (!shouldValidate || isValidating) return;\n if (!validateData) return;\n // Avoid re-processing the same result\n if (processedDataRef.current === validateData) return;\n processedDataRef.current = validateData;\n\n // ValidateData has board.solution\n const board = validateData.data?.board;\n const solution = board?.solution;\n if (validateData.success && solution) {\n setValidatedPuzzle({\n puzzle: puzzleString,\n solution,\n level: board.level,\n difficultyScore: board.difficulty_score,\n });\n setValidationError(null);\n } else if (validateData.error) {\n // Validation failed with specific error\n setValidationError(classifyValidationError(validateData.error));\n setValidatedPuzzle(null);\n } else {\n // Unexpected response - success but no solution\n console.error('Unexpected validation response:', validateData);\n setValidationError('enter.errors.validationFailed');\n setValidatedPuzzle(null);\n }\n setShouldValidate(false);\n }, [validateData, shouldValidate, isValidating, puzzleString]);\n\n // Handle network/query errors (e.g. 400 responses throw NetworkError)\n useEffect(() => {\n if (!shouldValidate || isValidating) return;\n if (!validateError) return;\n if (processedErrorRef.current === validateError) return;\n processedErrorRef.current = validateError;\n\n // Extract error message from NetworkError response body or message\n const networkErr = validateError as {\n response?: { error?: string };\n message?: string;\n };\n const errorMsg = networkErr.response?.error ?? networkErr.message ?? '';\n setValidationError(classifyValidationError(errorMsg));\n setValidatedPuzzle(null);\n setShouldValidate(false);\n }, [validateError, shouldValidate, isValidating]);\n\n // Select a cell\n const selectCell = useCallback((index: number) => {\n if (index >= 0 && index < 81) {\n setSelectedIndex(index);\n }\n }, []);\n\n // Set a given value at the selected cell\n const setGiven = useCallback(\n (value: number) => {\n if (selectedIndex === null || value < 1 || value > 9) return;\n\n setCells(prevCells => {\n const newCells = [...prevCells];\n const existing = newCells[selectedIndex];\n if (existing) {\n newCells[selectedIndex] = { ...existing, given: value };\n }\n return newCells;\n });\n // A given replaces the cell's pencilmarks\n setPencilmarks(prev => {\n if (!prev[selectedIndex]?.length) return prev;\n const next = [...prev];\n next[selectedIndex] = [];\n return next;\n });\n\n // Clear validation state when board changes\n setValidationError(null);\n setValidatedPuzzle(null);\n },\n [selectedIndex]\n );\n\n // Erase the selected cell\n const erase = useCallback(() => {\n if (selectedIndex === null) return;\n\n setCells(prevCells => {\n const newCells = [...prevCells];\n const existing = newCells[selectedIndex];\n if (existing) {\n newCells[selectedIndex] = { ...existing, given: null };\n }\n return newCells;\n });\n\n // Clear validation state when board changes\n setValidationError(null);\n setValidatedPuzzle(null);\n }, [selectedIndex]);\n\n // Get puzzle string\n const getPuzzleString = useCallback(() => {\n return puzzleString;\n }, [puzzleString]);\n\n // Trigger validation\n const validate = useCallback(() => {\n // Check minimum clues\n if (clueCount < MIN_CLUES) {\n setValidationError('enter.errors.notEnoughClues');\n return;\n }\n\n // Clear previous state and trigger validation\n setValidationError(null);\n setValidatedPuzzle(null);\n // Clear processed refs so cached React Query results are re-processed\n processedDataRef.current = null;\n processedErrorRef.current = null;\n setShouldValidate(true);\n }, [clueCount]);\n\n // Reset to empty board\n const reset = useCallback(() => {\n setCells(createEmptyCells());\n setPencilmarks(createEmptyPencilmarks());\n setAutopencil(false);\n setScannedInput(null);\n setIsPencilMode(false);\n setSelectedIndex(null);\n setValidationError(null);\n setValidatedPuzzle(null);\n setShouldValidate(false);\n processedDataRef.current = null;\n processedErrorRef.current = null;\n }, []);\n\n // Set cells from puzzle string\n const setCellsFromPuzzle = useCallback((puzzle: string) => {\n setCells(puzzleStringToCells(puzzle));\n setPencilmarks(createEmptyPencilmarks());\n setAutopencil(false);\n setScannedInput(null);\n setSelectedIndex(null);\n setValidationError(null);\n setValidatedPuzzle(null);\n setShouldValidate(false);\n processedDataRef.current = null;\n processedErrorRef.current = null;\n }, []);\n\n // Toggle a pencilmark digit on the selected (non-given) cell\n const togglePencilmark = useCallback(\n (digit: number) => {\n if (selectedIndex === null || digit < 1 || digit > 9) return;\n if (cells[selectedIndex]?.given !== null) return;\n setPencilmarks(prev => {\n const next = [...prev];\n const current = next[selectedIndex] ?? [];\n next[selectedIndex] = current.includes(digit)\n ? current.filter(d => d !== digit)\n : [...current, digit].sort((a, b) => a - b);\n return next;\n });\n },\n [selectedIndex, cells]\n );\n\n const togglePencilMode = useCallback(() => {\n setIsPencilMode(prev => !prev);\n }, []);\n\n const setPencilMode = useCallback((on: boolean) => {\n setIsPencilMode(on);\n }, []);\n\n const enterDigit = useCallback(\n (value: number) => {\n if (isPencilMode) {\n togglePencilmark(value);\n } else {\n setGiven(value);\n }\n },\n [isPencilMode, togglePencilmark, setGiven]\n );\n\n const toggleGiven = useCallback(\n (value: number) => {\n if (selectedIndex !== null && cells[selectedIndex]?.given === value) {\n erase();\n } else {\n setGiven(value);\n }\n },\n [selectedIndex, cells, erase, setGiven]\n );\n\n // Load a scanned board (givens, pencilmarks, player digits)\n const applyScan = useCallback(\n (scanned: ScannedBoard) => {\n setCellsFromPuzzle(scanned.original);\n const parsed = parsePencilmarksString(scanned.pencilmarks);\n setPencilmarks(\n parsed.length === 81\n ? parsed.map(pm => (pm ? [...pm].sort((a, b) => a - b) : []))\n : createEmptyPencilmarks()\n );\n setAutopencil(scanned.autopencil);\n setScannedInput(hasScannedInput(scanned) ? scanned.user : null);\n },\n [setCellsFromPuzzle]\n );\n\n // Entry cells with pencilmarks merged in (givens never show pencilmarks)\n const displayCells = useMemo(\n () =>\n cells.map((cell, i) => {\n if (cell.given !== null) return cell;\n const pm = pencilmarks[i];\n return pm && pm.length > 0 ? { ...cell, pencilmarks: pm } : cell;\n }),\n [cells, pencilmarks]\n );\n\n const hasPencilmarks = useMemo(\n () => pencilmarks.some(pm => pm.length > 0),\n [pencilmarks]\n );\n\n const pencilmarksString = useMemo(\n () => pencilmarksToString(pencilmarks.map(pm => [...pm])),\n [pencilmarks]\n );\n\n const initialPlayState = useMemo((): BoardEntryPlayState | undefined => {\n if (!scannedInput && !hasPencilmarks) return undefined;\n // A given corrected after the scan wins over a scanned digit there.\n const input = scannedInput\n ? Array.from(scannedInput, (ch, i) =>\n cells[i]?.given !== null ? '0' : ch\n ).join('')\n : EMPTY_INPUT;\n const state: BoardEntryPlayState = { input };\n if (hasPencilmarks) {\n state.pencilmarks = pencilmarksString;\n state.autopencil = autopencil;\n }\n return state;\n }, [scannedInput, hasPencilmarks, pencilmarksString, autopencil, cells]);\n\n const canValidate = clueCount >= MIN_CLUES && !isValidating;\n\n return {\n cells,\n selectedIndex,\n isValidating,\n validationError,\n validatedPuzzle,\n selectCell,\n setGiven,\n erase,\n getPuzzleString,\n validate,\n reset,\n clueCount,\n setCellsFromPuzzle,\n pencilmarks,\n autopencil,\n hasPencilmarks,\n pencilmarksString,\n togglePencilmark,\n displayCells,\n isPencilMode,\n togglePencilMode,\n setPencilMode,\n enterDigit,\n toggleGiven,\n canValidate,\n applyScan,\n scannedInput,\n initialPlayState,\n };\n}\n"]}
1
+ {"version":3,"file":"useBoardEntry.js","sourceRoot":"","sources":["../../src/hooks/useBoardEntry.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Hook for managing Sudoku board entry mode state\n * Allows users to enter given clues for a custom puzzle\n */\n\nimport { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport type { SudokuCell } from '../types';\nimport { createEmptyBoard } from '../types';\nimport { useSolverValidate } from '@sudobility/sudojo_client';\nimport { MIN_CLUES } from '@sudobility/sudojo_types';\nimport { cellsToPuzzleString, countClues } from '../utils/sudokuScrambler';\nimport type { NetworkClient } from '@sudobility/types';\nimport { useResolvedSudojoApi } from '../context/SudojoApiContext';\nimport type { ScannedBoard } from '../utils/scannedBoard';\nimport {\n parsePencilmarksString,\n pencilmarksToString,\n} from '../utils/techniqueWalkthrough';\n\nexport interface ValidatedPuzzle {\n puzzle: string;\n solution: string;\n /** Difficulty level (1-12) the solver rated the puzzle at */\n level?: number;\n /** Solver's difficulty_score for the puzzle, when the API sends it */\n difficultyScore?: number | undefined;\n}\n\nexport interface UseBoardEntryOptions {\n /** Network client for API calls (default: SudojoApiProvider) */\n networkClient?: NetworkClient | undefined;\n /** Base URL for the Sudojo API (default: SudojoApiProvider) */\n baseUrl?: string | undefined;\n /** Access token (default: SudojoApiProvider) */\n token?: string | null | undefined;\n}\n\n/**\n * What the game should apply once the entered puzzle is validated: the\n * entry pencilmarks (a scan's player digits are already givens). Pass the fields to the\n * game as initialInput / initialPencilmarks / initialAutoPencilmarks (or to\n * useSudoku's applyHintData).\n */\nexport interface BoardEntryPlayState {\n /** 81-char player input; always '0'.repeat(81) (only pencilmarks are restored) */\n input?: string;\n /** 81 comma-separated pencilmark entries */\n pencilmarks?: string;\n /** Whether the pencilmarks were auto-filled */\n autopencil?: boolean;\n}\n\nexport interface UseBoardEntryReturn {\n /** 81 cells with given values only */\n cells: SudokuCell[];\n /** Currently selected cell index */\n selectedIndex: number | null;\n /** Whether validation is in progress */\n isValidating: boolean;\n /** Validation error message key */\n validationError: string | null;\n /** Validated puzzle data (puzzle + solution + solver rating) */\n validatedPuzzle: ValidatedPuzzle | null;\n /** Select a cell by index */\n selectCell: (index: number) => void;\n /** Set a given value at the selected cell */\n setGiven: (value: number) => void;\n /** Erase the selected cell */\n erase: () => void;\n /** Get the puzzle as an 81-character string */\n getPuzzleString: () => string;\n /** Trigger validation */\n validate: () => void;\n /** Reset to empty board */\n reset: () => void;\n /** Number of clues entered */\n clueCount: number;\n /** Set cells from an 81-character puzzle string (clears pencilmarks) */\n setCellsFromPuzzle: (puzzle: string) => void;\n\n // --- Entry pencilmarks ---------------------------------------------------\n /** Per-cell entry pencilmarks (81 sorted digit arrays; [] = none) */\n pencilmarks: number[][];\n /** Whether the pencilmarks were auto-filled (from a scan) */\n autopencil: boolean;\n /** Whether any cell has pencilmarks */\n hasPencilmarks: boolean;\n /** Pencilmarks as 81 comma-separated entries (e.g. \"12,,9,...\") */\n pencilmarksString: string;\n /** Toggle a pencilmark digit on the selected cell (ignored on givens) */\n togglePencilmark: (digit: number) => void;\n /** `cells` with the entry pencilmarks merged in, for display */\n displayCells: SudokuCell[];\n /** Whether digit input goes to pencilmarks instead of givens */\n isPencilMode: boolean;\n /** Toggle pencil mode */\n togglePencilMode: () => void;\n /** Set pencil mode */\n setPencilMode: (on: boolean) => void;\n /**\n * Route a digit: in pencil mode toggle a pencilmark, otherwise set a given\n * (web/RN entry keypad behavior).\n */\n enterDigit: (value: number) => void;\n\n // --- Givens --------------------------------------------------------------\n /**\n * Set a given at the selected cell, or erase it when the cell already holds\n * that digit (extension keypad behavior).\n */\n toggleGiven: (value: number) => void;\n /** Whether Validate may run (enough clues and not already validating) */\n canValidate: boolean;\n\n // --- Scans ---------------------------------------------------------------\n /**\n * Load a scanned board: givens from `puzzle` (the printed givens merged\n * with the player's digits), plus the scan's pencilmarks and autopencil.\n */\n applyScan: (scanned: ScannedBoard) => void;\n /**\n * @deprecated Always null. A scan's player digits are merged into the\n * givens (applyScan uses `ScannedBoard.puzzle`), not restored as input.\n */\n scannedInput: null;\n /**\n * What the game should apply once validated (the entry pencilmarks), or\n * undefined when there are none.\n */\n initialPlayState: BoardEntryPlayState | undefined;\n}\n\n/**\n * Create an empty 81-cell board for entry mode\n */\nfunction createEmptyCells(): SudokuCell[] {\n return createEmptyBoard().cells;\n}\n\n/**\n * Create a board from an 81-character puzzle string\n * '0' or '.' for empty, '1'-'9' for given values\n */\nfunction puzzleStringToCells(puzzle: string): SudokuCell[] {\n if (puzzle.length !== 81) {\n return createEmptyCells();\n }\n\n return Array.from({ length: 81 }, (_, index) => {\n const char = puzzle.charAt(index);\n const value = parseInt(char, 10);\n const given = value >= 1 && value <= 9 ? value : null;\n\n return {\n index,\n solution: null,\n given,\n input: null,\n pencilmarks: null,\n };\n });\n}\n\n/**\n * Classify a validation error message into a translation key\n */\nfunction classifyValidationError(errorMsg: string): string {\n const lower = errorMsg.toLowerCase();\n if (lower.includes('multiple') || lower.includes('not unique')) {\n return 'enter.errors.multipleSolutions';\n }\n if (lower.includes('cannot solve') || lower.includes('no solution')) {\n return 'enter.errors.noSolution';\n }\n return 'enter.errors.validationFailed';\n}\n\nfunction createEmptyPencilmarks(): number[][] {\n return Array.from({ length: 81 }, () => []);\n}\n\nconst EMPTY_INPUT = '0'.repeat(81);\n\nexport function useBoardEntry(\n options: UseBoardEntryOptions = {}\n): UseBoardEntryReturn {\n const { networkClient, baseUrl, token } = useResolvedSudojoApi(\n options,\n 'useBoardEntry'\n );\n const [cells, setCells] = useState<SudokuCell[]>(createEmptyCells);\n const [pencilmarks, setPencilmarks] = useState<number[][]>(\n createEmptyPencilmarks\n );\n const [autopencil, setAutopencil] = useState(false);\n const [isPencilMode, setIsPencilMode] = useState(false);\n const [selectedIndex, setSelectedIndex] = useState<number | null>(null);\n const [validationError, setValidationError] = useState<string | null>(null);\n const [validatedPuzzle, setValidatedPuzzle] =\n useState<ValidatedPuzzle | null>(null);\n const [shouldValidate, setShouldValidate] = useState(false);\n\n // Compute puzzle string for validation\n const puzzleString = useMemo(() => cellsToPuzzleString(cells), [cells]);\n const clueCount = useMemo(() => countClues(cells), [cells]);\n\n // Use the solver validate hook\n const {\n data: validateData,\n error: validateError,\n isLoading: isValidating,\n } = useSolverValidate(\n networkClient,\n baseUrl,\n token,\n { original: puzzleString },\n {\n enabled: shouldValidate && clueCount >= MIN_CLUES,\n retry: false,\n }\n );\n\n // Track whether we've already processed this validation result\n const processedDataRef = useRef<typeof validateData | null>(null);\n const processedErrorRef = useRef<typeof validateError | null>(null);\n\n // Handle validation result\n useEffect(() => {\n if (!shouldValidate || isValidating) return;\n if (!validateData) return;\n // Avoid re-processing the same result\n if (processedDataRef.current === validateData) return;\n processedDataRef.current = validateData;\n\n // ValidateData has board.solution\n const board = validateData.data?.board;\n const solution = board?.solution;\n if (validateData.success && solution) {\n setValidatedPuzzle({\n puzzle: puzzleString,\n solution,\n level: board.level,\n difficultyScore: board.difficulty_score,\n });\n setValidationError(null);\n } else if (validateData.error) {\n // Validation failed with specific error\n setValidationError(classifyValidationError(validateData.error));\n setValidatedPuzzle(null);\n } else {\n // Unexpected response - success but no solution\n console.error('Unexpected validation response:', validateData);\n setValidationError('enter.errors.validationFailed');\n setValidatedPuzzle(null);\n }\n setShouldValidate(false);\n }, [validateData, shouldValidate, isValidating, puzzleString]);\n\n // Handle network/query errors (e.g. 400 responses throw NetworkError)\n useEffect(() => {\n if (!shouldValidate || isValidating) return;\n if (!validateError) return;\n if (processedErrorRef.current === validateError) return;\n processedErrorRef.current = validateError;\n\n // Extract error message from NetworkError response body or message\n const networkErr = validateError as {\n response?: { error?: string };\n message?: string;\n };\n const errorMsg = networkErr.response?.error ?? networkErr.message ?? '';\n setValidationError(classifyValidationError(errorMsg));\n setValidatedPuzzle(null);\n setShouldValidate(false);\n }, [validateError, shouldValidate, isValidating]);\n\n // Select a cell\n const selectCell = useCallback((index: number) => {\n if (index >= 0 && index < 81) {\n setSelectedIndex(index);\n }\n }, []);\n\n // Set a given value at the selected cell\n const setGiven = useCallback(\n (value: number) => {\n if (selectedIndex === null || value < 1 || value > 9) return;\n\n setCells(prevCells => {\n const newCells = [...prevCells];\n const existing = newCells[selectedIndex];\n if (existing) {\n newCells[selectedIndex] = { ...existing, given: value };\n }\n return newCells;\n });\n // A given replaces the cell's pencilmarks\n setPencilmarks(prev => {\n if (!prev[selectedIndex]?.length) return prev;\n const next = [...prev];\n next[selectedIndex] = [];\n return next;\n });\n\n // Clear validation state when board changes\n setValidationError(null);\n setValidatedPuzzle(null);\n },\n [selectedIndex]\n );\n\n // Erase the selected cell\n const erase = useCallback(() => {\n if (selectedIndex === null) return;\n\n setCells(prevCells => {\n const newCells = [...prevCells];\n const existing = newCells[selectedIndex];\n if (existing) {\n newCells[selectedIndex] = { ...existing, given: null };\n }\n return newCells;\n });\n\n // Clear validation state when board changes\n setValidationError(null);\n setValidatedPuzzle(null);\n }, [selectedIndex]);\n\n // Get puzzle string\n const getPuzzleString = useCallback(() => {\n return puzzleString;\n }, [puzzleString]);\n\n // Trigger validation\n const validate = useCallback(() => {\n // Check minimum clues\n if (clueCount < MIN_CLUES) {\n setValidationError('enter.errors.notEnoughClues');\n return;\n }\n\n // Clear previous state and trigger validation\n setValidationError(null);\n setValidatedPuzzle(null);\n // Clear processed refs so cached React Query results are re-processed\n processedDataRef.current = null;\n processedErrorRef.current = null;\n setShouldValidate(true);\n }, [clueCount]);\n\n // Reset to empty board\n const reset = useCallback(() => {\n setCells(createEmptyCells());\n setPencilmarks(createEmptyPencilmarks());\n setAutopencil(false);\n setIsPencilMode(false);\n setSelectedIndex(null);\n setValidationError(null);\n setValidatedPuzzle(null);\n setShouldValidate(false);\n processedDataRef.current = null;\n processedErrorRef.current = null;\n }, []);\n\n // Set cells from puzzle string\n const setCellsFromPuzzle = useCallback((puzzle: string) => {\n setCells(puzzleStringToCells(puzzle));\n setPencilmarks(createEmptyPencilmarks());\n setAutopencil(false);\n setSelectedIndex(null);\n setValidationError(null);\n setValidatedPuzzle(null);\n setShouldValidate(false);\n processedDataRef.current = null;\n processedErrorRef.current = null;\n }, []);\n\n // Toggle a pencilmark digit on the selected (non-given) cell\n const togglePencilmark = useCallback(\n (digit: number) => {\n if (selectedIndex === null || digit < 1 || digit > 9) return;\n if (cells[selectedIndex]?.given !== null) return;\n setPencilmarks(prev => {\n const next = [...prev];\n const current = next[selectedIndex] ?? [];\n next[selectedIndex] = current.includes(digit)\n ? current.filter(d => d !== digit)\n : [...current, digit].sort((a, b) => a - b);\n return next;\n });\n },\n [selectedIndex, cells]\n );\n\n const togglePencilMode = useCallback(() => {\n setIsPencilMode(prev => !prev);\n }, []);\n\n const setPencilMode = useCallback((on: boolean) => {\n setIsPencilMode(on);\n }, []);\n\n const enterDigit = useCallback(\n (value: number) => {\n if (isPencilMode) {\n togglePencilmark(value);\n } else {\n setGiven(value);\n }\n },\n [isPencilMode, togglePencilmark, setGiven]\n );\n\n const toggleGiven = useCallback(\n (value: number) => {\n if (selectedIndex !== null && cells[selectedIndex]?.given === value) {\n erase();\n } else {\n setGiven(value);\n }\n },\n [selectedIndex, cells, erase, setGiven]\n );\n\n // Load a scanned board: the merged board (givens + the player's digits)\n // becomes the givens; pencilmarks carry over\n const applyScan = useCallback(\n (scanned: ScannedBoard) => {\n setCellsFromPuzzle(scanned.puzzle);\n const parsed = parsePencilmarksString(scanned.pencilmarks);\n setPencilmarks(\n parsed.length === 81\n ? parsed.map(pm => (pm ? [...pm].sort((a, b) => a - b) : []))\n : createEmptyPencilmarks()\n );\n setAutopencil(scanned.autopencil);\n },\n [setCellsFromPuzzle]\n );\n\n // Entry cells with pencilmarks merged in (givens never show pencilmarks)\n const displayCells = useMemo(\n () =>\n cells.map((cell, i) => {\n if (cell.given !== null) return cell;\n const pm = pencilmarks[i];\n return pm && pm.length > 0 ? { ...cell, pencilmarks: pm } : cell;\n }),\n [cells, pencilmarks]\n );\n\n const hasPencilmarks = useMemo(\n () => pencilmarks.some(pm => pm.length > 0),\n [pencilmarks]\n );\n\n const pencilmarksString = useMemo(\n () => pencilmarksToString(pencilmarks.map(pm => [...pm])),\n [pencilmarks]\n );\n\n const initialPlayState = useMemo(\n (): BoardEntryPlayState | undefined =>\n hasPencilmarks\n ? {\n input: EMPTY_INPUT,\n pencilmarks: pencilmarksString,\n autopencil,\n }\n : undefined,\n [hasPencilmarks, pencilmarksString, autopencil]\n );\n\n const canValidate = clueCount >= MIN_CLUES && !isValidating;\n\n return {\n cells,\n selectedIndex,\n isValidating,\n validationError,\n validatedPuzzle,\n selectCell,\n setGiven,\n erase,\n getPuzzleString,\n validate,\n reset,\n clueCount,\n setCellsFromPuzzle,\n pencilmarks,\n autopencil,\n hasPencilmarks,\n pencilmarksString,\n togglePencilmark,\n displayCells,\n isPencilMode,\n togglePencilMode,\n setPencilMode,\n enterDigit,\n toggleGiven,\n canValidate,\n applyScan,\n scannedInput: null,\n initialPlayState,\n };\n}\n"]}
@@ -10,7 +10,7 @@ import { type UseResumeGameResult } from './useResumeGame';
10
10
  export interface UseEnteredGameSessionOptions {
11
11
  /** useBoardEntry's validatedPuzzle (null until Validate succeeds) */
12
12
  validatedPuzzle: ValidatedPuzzle | null | undefined;
13
- /** useBoardEntry's initialPlayState (scanned input / entry pencilmarks) */
13
+ /** useBoardEntry's initialPlayState (entry pencilmarks) */
14
14
  initialPlayState?: BoardEntryPlayState | undefined;
15
15
  /** The resume decision (default: useResumeGame({ source: 'entered' })) */
16
16
  resume?: UseResumeGameResult | undefined;
@@ -1 +1 @@
1
- {"version":3,"file":"useEnteredGameSession.d.ts","sourceRoot":"","sources":["../../src/hooks/useEnteredGameSession.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,KAAK,EAAE,mBAAmB,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAE5E,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAC1D,OAAO,EAAiB,KAAK,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AAE1E,MAAM,WAAW,4BAA4B;IAC3C,qEAAqE;IACrE,eAAe,EAAE,eAAe,GAAG,IAAI,GAAG,SAAS,CAAC;IACpD,2EAA2E;IAC3E,gBAAgB,CAAC,EAAE,mBAAmB,GAAG,SAAS,CAAC;IACnD,0EAA0E;IAC1E,MAAM,CAAC,EAAE,mBAAmB,GAAG,SAAS,CAAC;IACzC,2EAA2E;IAC3E,eAAe,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IACtC;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;CACtB;AAED,MAAM,WAAW,2BAA2B;IAC1C,2DAA2D;IAC3D,OAAO,EAAE,OAAO,CAAC;IACjB,oDAAoD;IACpD,UAAU,EAAE,OAAO,CAAC;IACpB,2EAA2E;IAC3E,YAAY,EAAE,eAAe,GAAG,IAAI,CAAC;IACrC,4EAA4E;IAC5E,SAAS,EAAE,OAAO,CAAC;IACnB;;;;OAIG;IACH,SAAS,EAAE,eAAe,GAAG,IAAI,CAAC;IAClC,sEAAsE;IACtE,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,wEAAwE;IACxE,gBAAgB,EAAE,CAAC,KAAK,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;IACxE,6DAA6D;IAC7D,YAAY,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;IACzD,mDAAmD;IACnD,UAAU,EAAE,CACV,WAAW,EAAE,MAAM,EACnB,iBAAiB,EAAE,MAAM,EACzB,YAAY,EAAE,OAAO,EACrB,eAAe,EAAE,OAAO,EACxB,WAAW,EAAE,MAAM,KAChB,IAAI,CAAC;IACV,kEAAkE;IAClE,UAAU,EAAE,MAAM,IAAI,CAAC;IACvB,iEAAiE;IACjE,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,4BAA4B,GACpC,2BAA2B,CAsJ7B"}
1
+ {"version":3,"file":"useEnteredGameSession.d.ts","sourceRoot":"","sources":["../../src/hooks/useEnteredGameSession.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,KAAK,EAAE,mBAAmB,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAE5E,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAC1D,OAAO,EAAiB,KAAK,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AAE1E,MAAM,WAAW,4BAA4B;IAC3C,qEAAqE;IACrE,eAAe,EAAE,eAAe,GAAG,IAAI,GAAG,SAAS,CAAC;IACpD,2DAA2D;IAC3D,gBAAgB,CAAC,EAAE,mBAAmB,GAAG,SAAS,CAAC;IACnD,0EAA0E;IAC1E,MAAM,CAAC,EAAE,mBAAmB,GAAG,SAAS,CAAC;IACzC,2EAA2E;IAC3E,eAAe,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IACtC;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;CACtB;AAED,MAAM,WAAW,2BAA2B;IAC1C,2DAA2D;IAC3D,OAAO,EAAE,OAAO,CAAC;IACjB,oDAAoD;IACpD,UAAU,EAAE,OAAO,CAAC;IACpB,2EAA2E;IAC3E,YAAY,EAAE,eAAe,GAAG,IAAI,CAAC;IACrC,4EAA4E;IAC5E,SAAS,EAAE,OAAO,CAAC;IACnB;;;;OAIG;IACH,SAAS,EAAE,eAAe,GAAG,IAAI,CAAC;IAClC,sEAAsE;IACtE,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,wEAAwE;IACxE,gBAAgB,EAAE,CAAC,KAAK,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;IACxE,6DAA6D;IAC7D,YAAY,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;IACzD,mDAAmD;IACnD,UAAU,EAAE,CACV,WAAW,EAAE,MAAM,EACnB,iBAAiB,EAAE,MAAM,EACzB,YAAY,EAAE,OAAO,EACrB,eAAe,EAAE,OAAO,EACxB,WAAW,EAAE,MAAM,KAChB,IAAI,CAAC;IACV,kEAAkE;IAClE,UAAU,EAAE,MAAM,IAAI,CAAC;IACvB,iEAAiE;IACjE,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,4BAA4B,GACpC,2BAA2B,CAsJ7B"}
@@ -1 +1 @@
1
- {"version":3,"file":"useEnteredGameSession.js","sourceRoot":"","sources":["../../src/hooks/useEnteredGameSession.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Save / resume orchestration for an entered (typed-in or scanned) puzzle,\n * after useBoardEntry validated it. Port of the web EnterBoard's play-mode\n * logic. Entered puzzles get no server session (no gamification), and their\n * completion is not recorded in progress.\n */\n\nimport { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport type { CurrentGameMeta } from '../types/currentGame';\nimport type { BoardEntryPlayState, ValidatedPuzzle } from './useBoardEntry';\nimport { useGamePlay } from './useGamePlay';\nimport type { PuzzleGameProps } from './usePuzzleSession';\nimport { useResumeGame, type UseResumeGameResult } from './useResumeGame';\n\nexport interface UseEnteredGameSessionOptions {\n /** useBoardEntry's validatedPuzzle (null until Validate succeeds) */\n validatedPuzzle: ValidatedPuzzle | null | undefined;\n /** useBoardEntry's initialPlayState (scanned input / entry pencilmarks) */\n initialPlayState?: BoardEntryPlayState | undefined;\n /** The resume decision (default: useResumeGame({ source: 'entered' })) */\n resume?: UseResumeGameResult | undefined;\n /** Forwarded to the internal useResumeGame (RN: its onStoreReady state) */\n isStoreHydrated?: boolean | undefined;\n /**\n * Called by newGame() to reset the entry board (pass useBoardEntry's\n * `reset`), so the old validatedPuzzle does not start play again.\n */\n onReset?: () => void;\n}\n\nexport interface UseEnteredGameSessionResult {\n /** Whether the resume decision is made (store hydrated) */\n isReady: boolean;\n /** Whether a saved entered game is being resumed */\n isResuming: boolean;\n /** The puzzle to play (resumed, else validated), or null while entering */\n activePuzzle: ValidatedPuzzle | null;\n /** Whether to show the game (there is an active puzzle) instead of entry */\n isPlaying: boolean;\n /**\n * Props for the game component, or null while entering. Always\n * `scramble: false`. Initial state comes from the saved game when resuming,\n * else from initialPlayState.\n */\n gameProps: PuzzleGameProps | null;\n /** Remount key for the game component (the puzzle string), or null */\n gameKey: string | null;\n /** Web SudokuGame's onScrambledReady: saves the game once per puzzle */\n onScrambledReady: (board: { puzzle: string; solution: string }) => void;\n /** RN SudokuGame's onBoardReady: same as onScrambledReady */\n onBoardReady: (puzzle: string, solution: string) => void;\n /** The game's onProgressUpdate (throttled save) */\n onProgress: (\n inputString: string,\n pencilmarksString: string,\n isPencilMode: boolean,\n autoPencilmarks: boolean,\n elapsedTime: number\n ) => void;\n /** The game's onComplete: clears the saved game (nothing else) */\n onComplete: () => void;\n /** Back to entry: clear the save, stop resuming, call onReset */\n newGame: () => void;\n}\n\n/**\n * @example\n * ```tsx\n * const entry = useBoardEntry();\n * const session = useEnteredGameSession({\n * validatedPuzzle: entry.validatedPuzzle,\n * initialPlayState: entry.initialPlayState,\n * onReset: entry.reset,\n * });\n * if (session.isPlaying) {\n * return <SudokuGame key={session.gameKey} {...session.gameProps}\n * onScrambledReady={session.onScrambledReady} onProgressUpdate={session.onProgress}\n * onComplete={session.onComplete} onNewGame={session.newGame} />;\n * }\n * ```\n */\nexport function useEnteredGameSession(\n options: UseEnteredGameSessionOptions\n): UseEnteredGameSessionResult {\n const { validatedPuzzle, initialPlayState, onReset } = options;\n\n const internalResume = useResumeGame({\n source: 'entered',\n slot: 'play',\n ...(options.isStoreHydrated !== undefined && {\n isStoreHydrated: options.isStoreHydrated,\n }),\n });\n const resume = options.resume ?? internalResume;\n const resumeGame = resume.resumeGame;\n const isResuming = resumeGame !== null;\n\n const { startGame, updateProgress, clearGame } = useGamePlay({\n slot: 'play',\n });\n\n const resumedPuzzle = useMemo((): ValidatedPuzzle | null => {\n if (!resumeGame) return null;\n // Level and score were saved with the game, since resuming does not\n // validate again.\n const puzzle: ValidatedPuzzle = {\n puzzle: resumeGame.puzzle,\n solution: resumeGame.solution,\n };\n if (resumeGame.meta.level !== undefined) {\n puzzle.level = resumeGame.meta.level;\n }\n if (resumeGame.meta.difficultyScore !== undefined) {\n puzzle.difficultyScore = resumeGame.meta.difficultyScore;\n }\n return puzzle;\n }, [resumeGame]);\n\n const activePuzzle = resumedPuzzle ?? validatedPuzzle ?? null;\n const gameKey = activePuzzle?.puzzle ?? null;\n\n // --- Save the fresh game once the game reports its board -----------------\n const [reported, setReported] = useState<{\n key: string;\n puzzle: string;\n solution: string;\n } | null>(null);\n\n const onScrambledReady = useCallback(\n (board: { puzzle: string; solution: string }) => {\n if (!gameKey) return;\n if (board.puzzle.length !== 81 || board.solution.length !== 81) return;\n setReported(prev =>\n prev?.key === gameKey &&\n prev.puzzle === board.puzzle &&\n prev.solution === board.solution\n ? prev\n : { key: gameKey, ...board }\n );\n },\n [gameKey]\n );\n\n const onBoardReady = useCallback(\n (puzzle: string, solution: string) => {\n onScrambledReady({ puzzle, solution });\n },\n [onScrambledReady]\n );\n\n const startedRef = useRef('');\n const pencilmarks = initialPlayState?.pencilmarks;\n const autopencil = initialPlayState?.autopencil ?? false;\n useEffect(() => {\n if (isResuming || !activePuzzle || !reported) return;\n if (reported.key !== gameKey || startedRef.current === gameKey) return;\n startedRef.current = gameKey;\n const meta: CurrentGameMeta = {};\n if (activePuzzle.level !== undefined) meta.level = activePuzzle.level;\n if (activePuzzle.difficultyScore !== undefined) {\n meta.difficultyScore = activePuzzle.difficultyScore;\n }\n startGame(\n 'entered',\n {\n original: reported.puzzle,\n user: reported.puzzle,\n pencilmark: pencilmarks\n ? { numbers: pencilmarks, autopencil }\n : { numbers: '', autopencil: false },\n },\n reported.solution,\n meta\n );\n }, [\n isResuming,\n activePuzzle,\n reported,\n gameKey,\n pencilmarks,\n autopencil,\n startGame,\n ]);\n\n const discardResume = resume.discard;\n const onComplete = useCallback(() => {\n clearGame();\n }, [clearGame]);\n\n const newGame = useCallback(() => {\n clearGame();\n discardResume();\n setReported(null);\n startedRef.current = '';\n onReset?.();\n }, [clearGame, discardResume, onReset]);\n\n const gameProps = useMemo((): PuzzleGameProps | null => {\n if (!activePuzzle) return null;\n if (resumeGame) {\n return {\n puzzle: activePuzzle.puzzle,\n solution: activePuzzle.solution,\n scramble: false,\n initialInput: resumeGame.inputString,\n initialPencilmarks: resumeGame.pencilmarksString,\n initialElapsedTime: resumeGame.elapsedTime,\n initialAutoPencilmarks: resumeGame.autoPencilmarks,\n };\n }\n return {\n puzzle: activePuzzle.puzzle,\n solution: activePuzzle.solution,\n scramble: false,\n initialInput: initialPlayState?.input,\n initialPencilmarks: initialPlayState?.pencilmarks,\n initialAutoPencilmarks: initialPlayState?.autopencil,\n };\n }, [activePuzzle, resumeGame, initialPlayState]);\n\n return {\n isReady: resume.isReady,\n isResuming,\n activePuzzle,\n isPlaying: activePuzzle !== null,\n gameProps,\n gameKey,\n onScrambledReady,\n onBoardReady,\n onProgress: updateProgress,\n onComplete,\n newGame,\n };\n}\n"]}
1
+ {"version":3,"file":"useEnteredGameSession.js","sourceRoot":"","sources":["../../src/hooks/useEnteredGameSession.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Save / resume orchestration for an entered (typed-in or scanned) puzzle,\n * after useBoardEntry validated it. Port of the web EnterBoard's play-mode\n * logic. Entered puzzles get no server session (no gamification), and their\n * completion is not recorded in progress.\n */\n\nimport { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport type { CurrentGameMeta } from '../types/currentGame';\nimport type { BoardEntryPlayState, ValidatedPuzzle } from './useBoardEntry';\nimport { useGamePlay } from './useGamePlay';\nimport type { PuzzleGameProps } from './usePuzzleSession';\nimport { useResumeGame, type UseResumeGameResult } from './useResumeGame';\n\nexport interface UseEnteredGameSessionOptions {\n /** useBoardEntry's validatedPuzzle (null until Validate succeeds) */\n validatedPuzzle: ValidatedPuzzle | null | undefined;\n /** useBoardEntry's initialPlayState (entry pencilmarks) */\n initialPlayState?: BoardEntryPlayState | undefined;\n /** The resume decision (default: useResumeGame({ source: 'entered' })) */\n resume?: UseResumeGameResult | undefined;\n /** Forwarded to the internal useResumeGame (RN: its onStoreReady state) */\n isStoreHydrated?: boolean | undefined;\n /**\n * Called by newGame() to reset the entry board (pass useBoardEntry's\n * `reset`), so the old validatedPuzzle does not start play again.\n */\n onReset?: () => void;\n}\n\nexport interface UseEnteredGameSessionResult {\n /** Whether the resume decision is made (store hydrated) */\n isReady: boolean;\n /** Whether a saved entered game is being resumed */\n isResuming: boolean;\n /** The puzzle to play (resumed, else validated), or null while entering */\n activePuzzle: ValidatedPuzzle | null;\n /** Whether to show the game (there is an active puzzle) instead of entry */\n isPlaying: boolean;\n /**\n * Props for the game component, or null while entering. Always\n * `scramble: false`. Initial state comes from the saved game when resuming,\n * else from initialPlayState.\n */\n gameProps: PuzzleGameProps | null;\n /** Remount key for the game component (the puzzle string), or null */\n gameKey: string | null;\n /** Web SudokuGame's onScrambledReady: saves the game once per puzzle */\n onScrambledReady: (board: { puzzle: string; solution: string }) => void;\n /** RN SudokuGame's onBoardReady: same as onScrambledReady */\n onBoardReady: (puzzle: string, solution: string) => void;\n /** The game's onProgressUpdate (throttled save) */\n onProgress: (\n inputString: string,\n pencilmarksString: string,\n isPencilMode: boolean,\n autoPencilmarks: boolean,\n elapsedTime: number\n ) => void;\n /** The game's onComplete: clears the saved game (nothing else) */\n onComplete: () => void;\n /** Back to entry: clear the save, stop resuming, call onReset */\n newGame: () => void;\n}\n\n/**\n * @example\n * ```tsx\n * const entry = useBoardEntry();\n * const session = useEnteredGameSession({\n * validatedPuzzle: entry.validatedPuzzle,\n * initialPlayState: entry.initialPlayState,\n * onReset: entry.reset,\n * });\n * if (session.isPlaying) {\n * return <SudokuGame key={session.gameKey} {...session.gameProps}\n * onScrambledReady={session.onScrambledReady} onProgressUpdate={session.onProgress}\n * onComplete={session.onComplete} onNewGame={session.newGame} />;\n * }\n * ```\n */\nexport function useEnteredGameSession(\n options: UseEnteredGameSessionOptions\n): UseEnteredGameSessionResult {\n const { validatedPuzzle, initialPlayState, onReset } = options;\n\n const internalResume = useResumeGame({\n source: 'entered',\n slot: 'play',\n ...(options.isStoreHydrated !== undefined && {\n isStoreHydrated: options.isStoreHydrated,\n }),\n });\n const resume = options.resume ?? internalResume;\n const resumeGame = resume.resumeGame;\n const isResuming = resumeGame !== null;\n\n const { startGame, updateProgress, clearGame } = useGamePlay({\n slot: 'play',\n });\n\n const resumedPuzzle = useMemo((): ValidatedPuzzle | null => {\n if (!resumeGame) return null;\n // Level and score were saved with the game, since resuming does not\n // validate again.\n const puzzle: ValidatedPuzzle = {\n puzzle: resumeGame.puzzle,\n solution: resumeGame.solution,\n };\n if (resumeGame.meta.level !== undefined) {\n puzzle.level = resumeGame.meta.level;\n }\n if (resumeGame.meta.difficultyScore !== undefined) {\n puzzle.difficultyScore = resumeGame.meta.difficultyScore;\n }\n return puzzle;\n }, [resumeGame]);\n\n const activePuzzle = resumedPuzzle ?? validatedPuzzle ?? null;\n const gameKey = activePuzzle?.puzzle ?? null;\n\n // --- Save the fresh game once the game reports its board -----------------\n const [reported, setReported] = useState<{\n key: string;\n puzzle: string;\n solution: string;\n } | null>(null);\n\n const onScrambledReady = useCallback(\n (board: { puzzle: string; solution: string }) => {\n if (!gameKey) return;\n if (board.puzzle.length !== 81 || board.solution.length !== 81) return;\n setReported(prev =>\n prev?.key === gameKey &&\n prev.puzzle === board.puzzle &&\n prev.solution === board.solution\n ? prev\n : { key: gameKey, ...board }\n );\n },\n [gameKey]\n );\n\n const onBoardReady = useCallback(\n (puzzle: string, solution: string) => {\n onScrambledReady({ puzzle, solution });\n },\n [onScrambledReady]\n );\n\n const startedRef = useRef('');\n const pencilmarks = initialPlayState?.pencilmarks;\n const autopencil = initialPlayState?.autopencil ?? false;\n useEffect(() => {\n if (isResuming || !activePuzzle || !reported) return;\n if (reported.key !== gameKey || startedRef.current === gameKey) return;\n startedRef.current = gameKey;\n const meta: CurrentGameMeta = {};\n if (activePuzzle.level !== undefined) meta.level = activePuzzle.level;\n if (activePuzzle.difficultyScore !== undefined) {\n meta.difficultyScore = activePuzzle.difficultyScore;\n }\n startGame(\n 'entered',\n {\n original: reported.puzzle,\n user: reported.puzzle,\n pencilmark: pencilmarks\n ? { numbers: pencilmarks, autopencil }\n : { numbers: '', autopencil: false },\n },\n reported.solution,\n meta\n );\n }, [\n isResuming,\n activePuzzle,\n reported,\n gameKey,\n pencilmarks,\n autopencil,\n startGame,\n ]);\n\n const discardResume = resume.discard;\n const onComplete = useCallback(() => {\n clearGame();\n }, [clearGame]);\n\n const newGame = useCallback(() => {\n clearGame();\n discardResume();\n setReported(null);\n startedRef.current = '';\n onReset?.();\n }, [clearGame, discardResume, onReset]);\n\n const gameProps = useMemo((): PuzzleGameProps | null => {\n if (!activePuzzle) return null;\n if (resumeGame) {\n return {\n puzzle: activePuzzle.puzzle,\n solution: activePuzzle.solution,\n scramble: false,\n initialInput: resumeGame.inputString,\n initialPencilmarks: resumeGame.pencilmarksString,\n initialElapsedTime: resumeGame.elapsedTime,\n initialAutoPencilmarks: resumeGame.autoPencilmarks,\n };\n }\n return {\n puzzle: activePuzzle.puzzle,\n solution: activePuzzle.solution,\n scramble: false,\n initialInput: initialPlayState?.input,\n initialPencilmarks: initialPlayState?.pencilmarks,\n initialAutoPencilmarks: initialPlayState?.autopencil,\n };\n }, [activePuzzle, resumeGame, initialPlayState]);\n\n return {\n isReady: resume.isReady,\n isResuming,\n activePuzzle,\n isPlaying: activePuzzle !== null,\n gameProps,\n gameKey,\n onScrambledReady,\n onBoardReady,\n onProgress: updateProgress,\n onComplete,\n newGame,\n };\n}\n"]}
package/dist/index.d.ts CHANGED
@@ -889,7 +889,7 @@ UseProgressReporterOptions,
889
889
  ProgressUpdateCallback,
890
890
  /** Status reported after a hint action is processed. */
891
891
  HintActionStatus,
892
- /** What a validated entered puzzle should apply (scanned input, pencilmarks). */
892
+ /** What a validated entered puzzle should apply (entry pencilmarks). */
893
893
  BoardEntryPlayState,
894
894
  /** Options for useStrategies hook. */
895
895
  UseStrategiesOptions,
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8CG;AAqBH,gFAAgF;AAChF,OAAO,EAAE,qBAAqB,EAAE,MAAM,SAAS,CAAC;AA0BhD,kFAAkF;AAClF,OAAO;AACL,+EAA+E;AAC/E,qBAAqB;AACrB,4EAA4E;AAC5E,oBAAoB;AACpB,qDAAqD;AACrD,eAAe;AACf,2CAA2C;AAC3C,gBAAgB;AAChB,oEAAoE;AACpE,YAAY;AACZ,kDAAkD;AAClD,KAAK;AACL,qDAAqD;AACrD,QAAQ;AACR,oDAAoD;AACpD,OAAO;AACP,iDAAiD;AACjD,SAAS;AACT,+DAA+D;AAC/D,aAAa;AACb,kEAAkE;AAClE,gBAAgB;AAChB,iEAAiE;AACjE,eAAe;AACf,2FAA2F;AAC3F,iBAAiB,GAClB,MAAM,SAAS,CAAC;AA8BjB,iEAAiE;AACjE,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAgB7E,OAAO;AACL,yCAAyC;AACzC,gBAAgB;AAChB,8DAA8D;AAC9D,oBAAoB,GACrB,MAAM,SAAS,CAAC;AAcjB,OAAO;AACL,oCAAoC;AACpC,gBAAgB;AAChB,yDAAyD;AACzD,oBAAoB,GACrB,MAAM,SAAS,CAAC;AAcjB,2CAA2C;AAC3C,OAAO,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAC;AAc/C,OAAO;AACL,+DAA+D;AAC/D,mBAAmB;AACnB,6DAA6D;AAC7D,iBAAiB,GAClB,MAAM,SAAS,CAAC;AAkBjB,+EAA+E;AAC/E,kCAAkC;AAClC,+EAA+E;AAE/E;;;;GAIG;AACH,OAAO;AACL,iFAAiF;AACjF,UAAU;AACV,wDAAwD;AACxD,gBAAgB;AAChB,sEAAsE;AACtE,eAAe;AACf,gEAAgE;AAChE,aAAa;AACb,gFAAgF;AAChF,aAAa;AACb,kFAAkF;AAClF,mBAAmB;AACnB,kFAAkF;AAClF,cAAc;AACd,uDAAuD;AACvD,aAAa;AACb,oGAAoG;AACpG,oBAAoB;AACpB,+EAA+E;AAC/E,eAAe;AACf,4EAA4E;AAC5E,WAAW;AACX,wDAAwD;AACxD,gBAAgB;AAChB,uFAAuF;AACvF,qBAAqB;AACrB,wFAAwF;AACxF,eAAe;AACf,+EAA+E;AAC/E,aAAa;AACb,oFAAoF;AACpF,iBAAiB;AACjB,sFAAsF;AACtF,qBAAqB;AACrB,qDAAqD;AACrD,aAAa;AACb,iFAAiF;AACjF,aAAa;AACb,2FAA2F;AAC3F,cAAc;AACd,sDAAsD;AACtD,cAAc;AACd,qFAAqF;AACrF,gBAAgB;AAChB,+EAA+E;AAC/E,oBAAoB;AACpB,uDAAuD;AACvD,iBAAiB,GAClB,MAAM,SAAS,CAAC;AAcjB,+DAA+D;AAC/D,OAAO;AACL,kFAAkF;AAClF,SAAS;AACT,2DAA2D;AAC3D,YAAY;AACZ,iEAAiE;AACjE,mBAAmB;AACnB,iEAAiE;AACjE,iBAAiB;AACjB,qEAAqE;AACrE,mBAAmB;AACnB,uEAAuE;AACvE,kBAAkB;AAClB,qDAAqD;AACrD,kBAAkB;AAClB,sEAAsE;AACtE,wBAAwB;AACxB,uEAAuE;AACvE,qBAAqB;AACrB,sDAAsD;AACtD,UAAU,GACX,MAAM,SAAS,CAAC;AAEjB,gFAAgF;AAChF,OAAO;AACL,kDAAkD;AAClD,SAAS;AACT,mCAAmC;AACnC,SAAS;AACT,qCAAqC;AACrC,SAAS;AACT,mEAAmE;AACnE,YAAY;AACZ,wCAAwC;AACxC,UAAU,GACX,MAAM,0BAA0B,CAAC;AAYlC,mFAAmF;AACnF,OAAO;AACL,qFAAqF;AACrF,YAAY;AACZ,2EAA2E;AAC3E,kBAAkB;AAClB,0EAA0E;AAC1E,eAAe;AACf,qDAAqD;AACrD,eAAe;AACf,yEAAyE;AACzE,iBAAiB;AACjB,sFAAsF;AACtF,gBAAgB;AAChB,gFAAgF;AAChF,yBAAyB;AACzB,8EAA8E;AAC9E,iBAAiB;AACjB,qEAAqE;AACrE,sBAAsB;AACtB,mDAAmD;AACnD,kBAAkB;AAClB,mFAAmF;AACnF,wBAAwB;AACxB,2DAA2D;AAC3D,eAAe;AACf,4EAA4E;AAC5E,qBAAqB;AACrB,sEAAsE;AACtE,kBAAkB,GACnB,MAAM,SAAS,CAAC;AAEjB,+EAA+E;AAC/E,iBAAiB;AACjB,+EAA+E;AAE/E,6CAA6C;AAC7C,OAAO;AACL,oDAAoD;AACpD,UAAU;AACV,8DAA8D;AAC9D,SAAS,GACV,MAAM,SAAS,CAAC;AAEjB,+EAA+E;AAC/E,qBAAqB;AACrB,+EAA+E;AAE/E,2CAA2C;AAC3C,OAAO;AACL,+EAA+E;AAC/E,cAAc;AACd,8DAA8D;AAC9D,eAAe;AACf,sEAAsE;AACtE,iBAAiB;AACjB,2DAA2D;AAC3D,oBAAoB;AACpB,0EAA0E;AAC1E,sBAAsB;AACtB,+EAA+E;AAC/E,qBAAqB,GACtB,MAAM,SAAS,CAAC;AAiBjB,gDAAgD;AAChD,OAAO;AACL,8DAA8D;AAC9D,iBAAiB;AACjB,sEAAsE;AACtE,qBAAqB;AACrB,8DAA8D;AAC9D,cAAc;AACd,2EAA2E;AAC3E,YAAY;AACZ,+DAA+D;AAC/D,sBAAsB,GACvB,MAAM,SAAS,CAAC;AAEjB,+EAA+E;AAC/E,yBAAyB;AACzB,+EAA+E;AAE/E,gEAAgE;AAChE,OAAO;AACL,8DAA8D;AAC9D,uBAAuB;AACvB,sEAAsE;AACtE,iBAAiB;AACjB,8FAA8F;AAC9F,oBAAoB;AACpB,gFAAgF;AAChF,eAAe;AACf,qEAAqE;AACrE,yBAAyB;AACzB,6EAA6E;AAC7E,iBAAiB;AACjB,kEAAkE;AAClE,cAAc;AACd,oFAAoF;AACpF,kBAAkB;AAClB,oEAAoE;AACpE,0BAA0B;AAC1B,mEAAmE;AACnE,uBAAuB;AACvB,8EAA8E;AAC9E,2BAA2B;AAC3B,iGAAiG;AACjG,gBAAgB;AAChB,gFAAgF;AAChF,qBAAqB;AACrB,iFAAiF;AACjF,qBAAqB;AACrB,uFAAuF;AACvF,qBAAqB,GACtB,MAAM,SAAS,CAAC;AAgCjB,wCAAwC;AACxC,OAAO;AACL,iEAAiE;AACjE,mBAAmB;AACnB,2EAA2E;AAC3E,wBAAwB;AACxB,wEAAwE;AACxE,kBAAkB;AAClB,6EAA6E;AAC7E,mBAAmB;AACnB,sDAAsD;AACtD,mBAAmB;AACnB,qEAAqE;AACrE,0BAA0B;AAC1B,sDAAsD;AACtD,wBAAwB;AACxB,6DAA6D;AAC7D,sBAAsB;AACtB,uDAAuD;AACvD,qBAAqB;AACrB,8EAA8E;AAC9E,sBAAsB;AACtB,4DAA4D;AAC5D,wBAAwB;AACxB,uCAAuC;AACvC,kBAAkB;AAClB,kEAAkE;AAClE,eAAe;AACf,qDAAqD;AACrD,cAAc;AACd,yDAAyD;AACzD,yBAAyB;AACzB,0EAA0E;AAC1E,wBAAwB;AACxB,sEAAsE;AACtE,mBAAmB;AACnB,sEAAsE;AACtE,qBAAqB,GACtB,MAAM,SAAS,CAAC;AAEjB,+EAA+E;AAC/E,8BAA8B;AAC9B,+EAA+E;AAE/E,2EAA2E;AAC3E,OAAO;AACL,4EAA4E;AAC5E,qBAAqB;AACrB,6DAA6D;AAC7D,sBAAsB;AACtB,sEAAsE;AACtE,iBAAiB,GAClB,MAAM,SAAS,CAAC;AASjB,oFAAoF;AACpF,OAAO;AACL,uEAAuE;AACvE,sBAAsB;AACtB,4EAA4E;AAC5E,mBAAmB;AACnB,wEAAwE;AACxE,kBAAkB;AAClB,qCAAqC;AACrC,gBAAgB;AAChB,mEAAmE;AACnE,aAAa;AACb,sDAAsD;AACtD,aAAa;AACb,+DAA+D;AAC/D,gBAAgB;AAChB,sEAAsE;AACtE,qBAAqB,GACtB,MAAM,SAAS,CAAC;AAEjB,+EAA+E;AAC/E,6BAA6B;AAC7B,+EAA+E;AAE/E,mFAAmF;AACnF,OAAO;AACL,8EAA8E;AAC9E,2BAA2B;AAC3B,4EAA4E;AAC5E,oBAAoB,GACrB,MAAM,SAAS,CAAC;AAgBjB,mCAAmC;AACnC,OAAO;AACL,uEAAuE;AACvE,oBAAoB;AACpB,wEAAwE;AACxE,qBAAqB;AACrB,oEAAoE;AACpE,cAAc;AACd,6DAA6D;AAC7D,uBAAuB;AACvB,4EAA4E;AAC5E,0BAA0B;AAC1B,iDAAiD;AACjD,uBAAuB;AACvB,wDAAwD;AACxD,qBAAqB;AACrB,6EAA6E;AAC7E,sBAAsB;AACtB,gFAAgF;AAChF,0BAA0B,GAC3B,MAAM,SAAS,CAAC;AAgBjB,+DAA+D;AAC/D,OAAO;AACL,+EAA+E;AAC/E,yBAAyB;AACzB,4EAA4E;AAC5E,oBAAoB;AACpB,iFAAiF;AACjF,mBAAmB;AACnB,oFAAoF;AACpF,wBAAwB;AACxB,2EAA2E;AAC3E,kBAAkB;AAClB,6EAA6E;AAC7E,mBAAmB;AACnB,yFAAyF;AACzF,uBAAuB,GACxB,MAAM,SAAS,CAAC;AAEjB,+EAA+E;AAC/E,qBAAqB;AACrB,+EAA+E;AAE/E,sEAAsE;AACtE,OAAO;AACL,2DAA2D;AAC3D,UAAU;AACV,4DAA4D;AAC5D,oBAAoB;AACpB,6DAA6D;AAC7D,eAAe;AACf,qDAAqD;AACrD,qBAAqB;AACrB,yDAAyD;AACzD,WAAW;AACX,8DAA8D;AAC9D,sBAAsB;AACtB,+EAA+E;AAC/E,eAAe;AACf,iEAAiE;AACjE,yBAAyB,GAC1B,MAAM,SAAS,CAAC;AAEjB,+EAA+E;AAC/E,0BAA0B;AAC1B,+EAA+E;AAE/E,uCAAuC;AACvC,OAAO;AACL,gGAAgG;AAChG,YAAY,GACb,MAAM,SAAS,CAAC;AASjB,OAAO;AACL,gDAAgD;AAChD,cAAc;AACd,8EAA8E;AAC9E,cAAc;AACd,8EAA8E;AAC9E,cAAc;AACd,yDAAyD;AACzD,eAAe;AACf,+EAA+E;AAC/E,wBAAwB,GACzB,MAAM,SAAS,CAAC;AAkBjB,yCAAyC;AACzC,OAAO,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAExC,wDAAwD;AACxD,OAAO,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAE3C,4CAA4C;AAC5C,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AASpC,qFAAqF;AACrF,OAAO,EAAE,mBAAmB,EAAE,MAAM,SAAS,CAAC;AAE9C,mEAAmE;AACnE,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAcrC,wEAAwE;AACxE,OAAO;AACL,qCAAqC;AACrC,mBAAmB;AACnB,wCAAwC;AACxC,wBAAwB;AACxB,gCAAgC;AAChC,gBAAgB;AAChB,qEAAqE;AACrE,oBAAoB;AACpB,4EAA4E;AAC5E,2BAA2B;AAC3B,mDAAmD;AACnD,mBAAmB;AACnB,mFAAmF;AACnF,qBAAqB;AACrB,+DAA+D;AAC/D,eAAe;AACf,wDAAwD;AACxD,aAAa;AACb,+CAA+C;AAC/C,qBAAqB,GACtB,MAAM,SAAS,CAAC;AASjB,2CAA2C;AAC3C,OAAO;AACL,kDAAkD;AAClD,mBAAmB;AACnB,+DAA+D;AAC/D,oBAAoB;AACpB,2DAA2D;AAC3D,sBAAsB,GACvB,MAAM,SAAS,CAAC;AAcjB,yDAAyD;AACzD,OAAO;AACL,2DAA2D;AAC3D,wBAAwB;AACxB,yDAAyD;AACzD,uBAAuB;AACvB,0EAA0E;AAC1E,kBAAkB,GACnB,MAAM,SAAS,CAAC;AAgBjB,uCAAuC;AACvC,OAAO;AACL,8DAA8D;AAC9D,oBAAoB;AACpB,yEAAyE;AACzE,mBAAmB;AACnB,sDAAsD;AACtD,wBAAwB,GACzB,MAAM,SAAS,CAAC;AAEjB,+EAA+E;AAC/E,uBAAuB;AACvB,+EAA+E;AAE/E,2EAA2E;AAC3E,OAAO;AACL,sDAAsD;AACtD,gBAAgB;AAChB,8EAA8E;AAC9E,kBAAkB;AAClB,+DAA+D;AAC/D,eAAe;AACf,wDAAwD;AACxD,YAAY,GACb,MAAM,SAAS,CAAC;AASjB,iEAAiE;AACjE,OAAO;AACL,6EAA6E;AAC7E,sBAAsB;AACtB,oFAAoF;AACpF,8BAA8B;AAC9B,iDAAiD;AACjD,kBAAkB;AAClB,2EAA2E;AAC3E,kBAAkB;AAClB,qEAAqE;AACrE,sBAAsB,GACvB,MAAM,SAAS,CAAC;AAmBjB,2EAA2E;AAC3E,OAAO,EAAE,yBAAyB,EAAE,MAAM,SAAS,CAAC;AAEpD,+EAA+E;AAC/E,QAAQ;AACR,+EAA+E;AAE/E,OAAO;AACL,aAAa;AACb,iDAAiD;AACjD,QAAQ;AACR,wEAAwE;AACxE,SAAS;AACT,kDAAkD;AAClD,YAAY;AACZ,4DAA4D;AAC5D,aAAa;AACb,wEAAwE;AACxE,cAAc;AACd,yEAAyE;AACzE,WAAW;AACX,4CAA4C;AAC5C,eAAe;AAEf;;;;GAIG;AACH,OAAO;AAEP,oFAAoF;AACpF,SAAS;AAET,8EAA8E;AAC9E,eAAe;AAEf,iFAAiF;AACjF,YAAY;AACZ,kEAAkE;AAClE,YAAY;AAEZ,8DAA8D;AAC9D,YAAY;AAEZ,wDAAwD;AACxD,kBAAkB;AAClB,4CAA4C;AAC5C,WAAW;AAEX,uDAAuD;AACvD,eAAe;AAEf,uEAAuE;AACvE,OAAO;AAEP,qEAAqE;AACrE,WAAW;AAEX,0DAA0D;AAC1D,eAAe;AAEf,uDAAuD;AACvD,aAAa;AAEb,yEAAyE;AACzE,YAAY;AAEZ,6EAA6E;AAC7E,cAAc;AAEd,4EAA4E;AAC5E,eAAe;AACf,gFAAgF;AAChF,mBAAmB;AAEnB,oFAAoF;AACpF,eAAe;AAEf,uEAAuE;AACvE,qBAAqB;AAErB,+DAA+D;AAC/D,kBAAkB;AAElB,2DAA2D;AAC3D,WAAW;AAEX,qDAAqD;AACrD,mBAAmB;AAEnB,gEAAgE;AAChE,0BAA0B;AAE1B,yDAAyD;AACzD,cAAc;AACd,0DAA0D;AAC1D,gBAAgB;AAChB,wCAAwC;AACxC,YAAY;AACZ,qEAAqE;AACrE,qBAAqB;AAErB,oFAAoF;AACpF,oBAAoB;AACpB,4DAA4D;AAC5D,aAAa;AACb,mFAAmF;AACnF,eAAe;AACf,0DAA0D;AAC1D,aAAa;AACb,8EAA8E;AAC9E,cAAc;AACd,2EAA2E;AAC3E,kBAAkB;AAClB,oEAAoE;AACpE,mBAAmB;AACnB,uEAAuE;AACvE,uBAAuB;AACvB,oFAAoF;AACpF,iBAAiB;AACjB,+DAA+D;AAC/D,gBAAgB;AAChB,+EAA+E;AAC/E,aAAa;AACb,kEAAkE;AAClE,aAAa;AACb,iFAAiF;AACjF,gBAAgB;AAChB,uEAAuE;AACvE,qBAAqB,GACtB,MAAM,SAAS,CAAC;AAgOjB,+EAA+E;AAC/E,SAAS;AACT,+EAA+E;AAE/E,+FAA+F;AAC/F,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAgB1D,iFAAiF;AACjF,OAAO,EAAE,sBAAsB,EAAE,MAAM,UAAU,CAAC;AAElD,+EAA+E;AAC/E,sBAAsB;AACtB,+EAA+E;AAE/E,oFAAoF;AACpF,OAAO,EAAE,mBAAmB,EAAE,MAAM,WAAW,CAAC;AAChD,yDAAyD;AACzD,OAAO,EAAE,kBAAkB,EAAE,qBAAqB,EAAE,MAAM,WAAW,CAAC;AAEtE,+EAA+E;AAC/E,qBAAqB;AACrB,+EAA+E;AAE/E,6EAA6E;AAC7E,OAAO,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAC9C,oEAAoE;AACpE,OAAO;AACL,mEAAmE;AACnE,gBAAgB;AAChB,iEAAiE;AACjE,YAAY;AACZ,8CAA8C;AAC9C,oBAAoB;AACpB,gFAAgF;AAChF,gBAAgB;AAChB,uEAAuE;AACvE,oBAAoB,GACrB,MAAM,WAAW,CAAC;AAWnB,+EAA+E;AAC/E,wDAAwD;AACxD,+EAA+E;AAE/E,gEAAgE;AAChE,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAE7D,gEAAgE;AAChE,OAAO,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAElE,+EAA+E;AAC/E,uEAAuE;AACvE,+EAA+E;AAE/E;;;;;;;;;GASG;AACH,cAAc,SAAS,CAAC","sourcesContent":["/**\n * @sudobility/sudojo_lib - Business logic library for Sudojo app\n *\n * This library provides:\n * - Game state management with useSudoku hook (ported from renderable)\n * - Board scrambling utilities\n * - Game validation (mistakes, completion)\n * - Level, technique, and learning data hooks\n * - Teaching/hint integration with solver\n * - Legacy useGame hook for backward compatibility\n *\n * ## Hook Architecture\n *\n * The hooks form a layered composition pattern:\n *\n * **Data hooks** (fetch and cache server data):\n * - `useLevels` / `useLevel` - Difficulty level data\n * - `useTechniques` / `useTechnique` - Solving technique data\n * - `useLearning` / `useLearningItem` - Learning material data\n *\n * **Game fetching hooks** (handle auth, subscription, and puzzle loading):\n * - `useLevelGame` - Fetch a random board for a specific level\n * - `useDailyGame` - Fetch today's daily puzzle\n *\n * **Game state hooks** (manage board state and user interaction):\n * - `useSudoku` - Primary game state (flat 81-cell array, modern API)\n * - `useGame` - Legacy game state (2D array, deprecated)\n * - `useBoardEntry` - Manual puzzle entry mode\n * - `useBoardScan` - Read givens, player digits and pencilmarks from a photo\n *\n * **Feature hooks** (provide specific game features):\n * - `useHint` - Solver integration for hints (matches Kotlin HintInteractor)\n * - `useGameTeaching` - Step-by-step teaching with solver\n * - `useGameTimer` - Elapsed time tracking via ref (no re-renders)\n * - `useGamePersistence` / `useAutoSave` - localStorage game save/restore\n * - `useLocalStorage` - Generic typed localStorage hook\n *\n * **Orchestration hooks** (combine multiple hooks for app-level features):\n * - `useGamePlay` - Current game management with Zustand store (daily/play slots)\n * - `useGameSession` - Server-side gamification (start/finish, points, badges)\n *\n * ## Migration Guide\n *\n * Legacy exports (prefixed with \"Legacy\" comments) use the 2D `GameBoard` type\n * from `useGame`. New code should use `useSudoku` with its flat 81-cell\n * `SudokuBoard` type. See `@deprecated` tags on legacy exports.\n */\n\n// ============================================================================\n// Legacy Types (useGame hook)\n// ============================================================================\n\n/**\n * @deprecated Use `SudokuCell` instead. Part of the legacy `useGame` 2D board API.\n */\nexport type {\n CellPosition,\n CellState,\n GameBoard,\n GameHint,\n GameMove,\n GameSettings,\n GameState,\n GameStatus,\n TeachingState,\n} from './types';\n\n/** @deprecated Use `DEFAULT_APP_SETTINGS` / `DEFAULT_PLAY_SETTINGS` instead. */\nexport { DEFAULT_GAME_SETTINGS } from './types';\n\n// ============================================================================\n// Sudoku Types (useSudoku hook - ported from renderable)\n// ============================================================================\n\n/** Core Sudoku cell and board types using flat 81-cell array representation. */\nexport type {\n /** A single cell in the Sudoku board (indexed 0-80). */\n SudokuCell,\n /** The Sudoku board containing all 81 cells. */\n SudokuBoard,\n /** Current play state including board, settings, and selection. */\n SudokuPlay,\n /** Session settings that can change during play (pencilmarking, auto-pencilmarks). */\n SudokuPlaySettings,\n /** App-level settings persisted across sessions (showErrors, display format). */\n SudokuAppSettings,\n /** Full game state including source, history, and digit mapping. */\n SudokuGameState,\n /** Display modes for Sudoku digits ('NUMERIC' | 'KANJI' | 'COLORS' | 'EMOJIS'). */\n SudokuDisplay,\n /** Source of the puzzle ('DAILY' | 'CHALLENGE' | 'LEVEL' | 'ENTERED'). */\n PlayingSource,\n} from './types';\n\n/** Default settings and cell/board helper functions for the modern Sudoku API. */\nexport {\n /** Default session play settings (pencilmarking off, auto-pencilmarks off). */\n DEFAULT_PLAY_SETTINGS,\n /** Default app settings (showErrors on, animations on, numeric display). */\n DEFAULT_APP_SETTINGS,\n /** Create an empty SudokuCell at the given index. */\n createEmptyCell,\n /** Create an empty 81-cell SudokuBoard. */\n createEmptyBoard,\n /** Check if a cell has an error (input does not match solution). */\n cellHasError,\n /** Get row index (0-8) from cell index (0-80). */\n rowOf,\n /** Get column index (0-8) from cell index (0-80). */\n columnOf,\n /** Get block index (0-8) from cell index (0-80). */\n blockOf,\n /** Get cell index (0-80) from row and column. */\n cellIndex,\n /** Get all cell indices in the same row as the given index. */\n getRowIndices,\n /** Get all cell indices in the same column as the given index. */\n getColumnIndices,\n /** Get all cell indices in the same block as the given index. */\n getBlockIndices,\n /** Get all related cell indices (same row, column, or block) excluding the cell itself. */\n getRelatedIndices,\n} from './types';\n\n// ============================================================================\n// Display types (for rendering - matches Kotlin renderable)\n// ============================================================================\n\n/** Display and hint visualization types matching the Kotlin renderable layer. */\nexport type {\n /** Highlighted area in a hint (row, column, or block). */\n HintArea,\n /** Cell display information in a hint step. */\n HintCell,\n /** Actions to perform on a cell during hint visualization. */\n HintCellActions,\n /** A single hint step with title, text, areas, cells, links, and groups. */\n DisplayHintStep,\n /** Complete display state for a single cell (colors, digit, pencilmarks). */\n CellDisplayState,\n /** Display state for a single pencilmark (digit and color). */\n PencilmarkDisplayState,\n /** UI color palette with system colors for light or dark mode. */\n UIColorPalette,\n /** Link type for chain visualization ('strong' | 'weak'). */\n LinkType,\n /** A link between two cells in a chain (display format). */\n DisplayLink,\n /** A group of cells for pattern visualization (display format). */\n DisplayCellGroup,\n} from './types';\n\n/** Theme and color enums plus predefined light/dark palettes. */\nexport { ThemeColor, SudokuColor, UIColorLight, UIColorDark } from './types';\n\n// ============================================================================\n// Progress Types (for user progress tracking)\n// ============================================================================\n\n/** Types for tracking user puzzle completion and statistics. */\nexport type {\n /** Record of a completed puzzle (id, type, time). */\n CompletedPuzzle,\n /** Computed game statistics (best times, averages). */\n GameStats,\n /** Full user progress data (completed puzzles, streak, stats). */\n UserProgress,\n} from './types';\n\nexport {\n /** Default empty user progress state. */\n DEFAULT_PROGRESS,\n /** localStorage key for progress data ('sudojo-progress'). */\n PROGRESS_STORAGE_KEY,\n} from './types';\n\n// ============================================================================\n// Settings Types (for app settings)\n// ============================================================================\n\n/** Types for application settings. */\nexport type {\n /** Digit display format ('numeric' | 'kanji' | 'emojis'). */\n DigitDisplay,\n /** Application settings (showErrors, symmetrical, display). */\n AppSettings,\n} from './types';\n\nexport {\n /** Default application settings. */\n DEFAULT_SETTINGS,\n /** localStorage key for settings ('sudojo-settings'). */\n SETTINGS_STORAGE_KEY,\n} from './types';\n\n// ============================================================================\n// Subscription Types (for subscription management)\n// ============================================================================\n\n/** Types for RevenueCat subscription management. */\nexport type {\n /** Subscription product information (price, period, trial). */\n Product,\n /** User subscription status (active, expiration, renewal). */\n Subscription,\n} from './types';\n\n/** Default inactive subscription state. */\nexport { DEFAULT_SUBSCRIPTION } from './types';\n\n// ============================================================================\n// Game Persistence Types (for saving/loading game state)\n// ============================================================================\n\n/** Types for saving and restoring game progress to localStorage. */\nexport type {\n /** Saved game state (input, pencilmarks, mode, timestamp). */\n SavedGameState,\n /** Key identifying a game to persist (type + id). */\n GamePersistenceKey,\n} from './types';\n\nexport {\n /** localStorage key prefix for game saves ('sudojo_game_'). */\n GAME_STORAGE_PREFIX,\n /** Generate a localStorage key from a GamePersistenceKey. */\n getGameStorageKey,\n} from './types';\n\n// ============================================================================\n// Current Game Types (for current game feature)\n// ============================================================================\n\n/** Types for the Zustand-backed current game store. */\nexport type {\n /** Source of the current game ('daily' | 'level' | 'entered'). */\n GameSource,\n /** Navigation metadata for resuming a game (date, level, board info). */\n CurrentGameMeta,\n /** Full current game state stored in Zustand (puzzle, progress, timing). */\n CurrentGame,\n /** Which store slot a game lives in ('daily' | 'play'). */\n GameSlot,\n} from './types';\n\n// ============================================================================\n// Legacy Utilities (useGame hook)\n// ============================================================================\n\n/**\n * @deprecated These utilities work with the legacy 2D `GameBoard` type.\n * For new code, use `useSudoku` with its flat 81-cell board and the\n * scrambler/presenter utilities below.\n */\nexport {\n /** @deprecated Clone a 2D GameBoard. Use useSudoku's immutable state instead. */\n cloneBoard,\n /** @deprecated Count filled cells in a 2D GameBoard. */\n countFilledCells,\n /** @deprecated Create a 2D GameBoard from puzzle/solution strings. */\n createGameBoard,\n /** @deprecated Get cells in a block by block index (2D API). */\n getBlockCells,\n /** @deprecated Get block index from row/col (2D API). Use blockOf() instead. */\n getBlockIndex,\n /** @deprecated Get 2D board state as string. Use cellsToStateString() instead. */\n getBoardStateString,\n /** @deprecated Get cells in a column (2D API). Use getColumnIndices() instead. */\n getColumnCells,\n /** @deprecated Get empty cells from a 2D GameBoard. */\n getEmptyCells,\n /** @deprecated Get pencilmarks string from 2D GameBoard. Use cellsToPencilmarksString() instead. */\n getPencilmarksString,\n /** @deprecated Get related cells (2D API). Use getRelatedIndices() instead. */\n getRelatedCells,\n /** @deprecated Get cells in a row (2D API). Use getRowIndices() instead. */\n getRowCells,\n /** @deprecated Check if placement is valid (2D API). */\n isValidPlacement,\n /** @deprecated Auto-remove pencilmarks (2D API). useSudoku handles this internally. */\n autoRemovePencilmarks,\n /** @deprecated Clear highlights (2D API). useSudoku handles this via presentBoard(). */\n clearHighlights,\n /** @deprecated Count mistakes (2D API). Use useSudoku's errorCount instead. */\n countMistakes,\n /** @deprecated Get incorrect cells (2D API). Use useSudoku's errorCells instead. */\n getIncorrectCells,\n /** @deprecated Get progress percentage (2D API). Use useSudoku's progress instead. */\n getProgressPercentage,\n /** @deprecated Check if board is filled (2D API). */\n isBoardFilled,\n /** @deprecated Check if cell is correct (2D API). Use cellHasError() instead. */\n isCellCorrect,\n /** @deprecated Check if game is complete (2D API). Use useSudoku's isCompleted instead. */\n isGameComplete,\n /** @deprecated Check if value is correct (2D API). */\n isValueCorrect,\n /** @deprecated Update cell errors (2D API). useSudoku handles this automatically. */\n updateCellErrors,\n /** @deprecated Update cell highlights (2D API). Use presentBoard() instead. */\n updateCellHighlights,\n /** @deprecated Validate entire game state (2D API). */\n validateGameState,\n} from './utils';\n\n// ============================================================================\n// Sudoku Utilities (useSudoku hook - ported from renderable)\n// ============================================================================\n\n/** Types for board scrambling. */\nexport type {\n /** Protocol for board scramblers (Scrambler and NonScrambler implement this). */\n ScramblerProtocol,\n /** Result of scrambling a board (cells + digit mappings). */\n SudokuScrambleResult,\n} from './utils';\n\n/** Board scrambling and puzzle string conversion utilities. */\nexport {\n /** Scrambler that permutes rows, columns, and digits to create unique puzzles. */\n Scrambler,\n /** Identity scrambler that returns the board unchanged. */\n NonScrambler,\n /** Scramble a board using a ScramblerProtocol implementation. */\n scrambleSudokuBoard,\n /** Parse an 81-character puzzle string into SudokuCell array. */\n parsePuzzleString,\n /** Convert SudokuCell array to puzzle string (given values only). */\n cellsToPuzzleString,\n /** Convert SudokuCell array to state string (given + input values). */\n cellsToStateString,\n /** Convert SudokuCell array to input-only string. */\n cellsToInputString,\n /** Convert SudokuCell array to comma-separated pencilmarks string. */\n cellsToPencilmarksString,\n /** Convert SudokuCell array to solution string ('0' where unknown). */\n cellsToSolutionString,\n /** Count the givens (clues) in a SudokuCell array. */\n countClues,\n} from './utils';\n\n/** Board and level constants from sudojo_types, re-exported for convenience. */\nexport {\n /** Fewest givens a valid Sudoku can have (17). */\n MIN_CLUES,\n /** Lowest difficulty level (1). */\n MIN_LEVEL,\n /** Highest difficulty level (12). */\n MAX_LEVEL,\n /** Whether a value is an integer level in MIN_LEVEL..MAX_LEVEL. */\n isValidLevel,\n /** All levels, MIN_LEVEL..MAX_LEVEL. */\n ALL_LEVELS,\n} from '@sudobility/sudojo_types';\n\n// ============================================================================\n// Presenter utilities (for rendering - matches Kotlin renderable)\n// ============================================================================\n\n/** Options type for the presentBoard function. */\nexport type {\n /** Options for generating cell display states (cells, selection, errors, hints). */\n PresentBoardOptions,\n} from './utils';\n\n/** Board presentation and color utilities matching the Kotlin renderable layer. */\nexport {\n /** Generate display states for all 81 cells (colors, digits, pencilmarks, hints). */\n presentBoard,\n /** Process hint step areas and cells into a map of cell hints by index. */\n calculateCellHints,\n /** Convert a ThemeColor to an actual CSS color string using a palette. */\n themeColorToCSS,\n /** Get the UIColorPalette for light or dark mode. */\n getColorPalette,\n /** Get indices of cells containing a specific digit (given or input). */\n getCellsWithDigit,\n /** Get the digit to highlight based on the selected cell (given or correct input). */\n getSelectedDigit,\n /** Compute the set of cell indices with the same digit as the selected cell. */\n computeSelectedDigitCells,\n /** Convert a solver link (row/col pairs) to display format (flat indices). */\n convertSolverLink,\n /** Convert a solver cell group to display format with ThemeColor. */\n convertSolverCellGroup,\n /** Convert SudokuColor enum to ThemeColor enum. */\n sudokuColorToTheme,\n /** Map a solver color string to SudokuColor (case-insensitive; unknown → null). */\n solverColorToSudokuColor,\n /** Parse a solver digit string (\"125\") into digits 1-9. */\n parseHintDigits,\n /** Convert a SolverHintStep into the DisplayHintStep presentBoard takes. */\n convertSolverHintStep,\n /** Whether a hint step is a conflict hint (has a 'conflict' link). */\n isConflictHintStep,\n} from './utils';\n\n// ============================================================================\n// Time Utilities\n// ============================================================================\n\n/** Time formatting and parsing utilities. */\nexport {\n /** Format seconds into MM:SS or HH:MM:SS string. */\n formatTime,\n /** Parse a MM:SS or HH:MM:SS string back to total seconds. */\n parseTime,\n} from './utils';\n\n// ============================================================================\n// Progress Utilities\n// ============================================================================\n\n/** User progress calculation utilities. */\nexport {\n /** Calculate game statistics (best times, averages) from completed puzzles. */\n calculateStats,\n /** Calculate current daily streak from completion history. */\n calculateStreak,\n /** Check if a specific puzzle (by type and id) has been completed. */\n isPuzzleCompleted,\n /** Get all completed level IDs from completion history. */\n getCompletedLevelIds,\n /** Get all completed daily dates (YYYY-MM-DD) from completion history. */\n getCompletedDailyDates,\n /** Record a puzzle completion in UserProgress (pure markCompleted reducer). */\n applyPuzzleCompletion,\n} from './utils';\n\n/** A puzzle completion to record (CompletedPuzzle without completedAt). */\nexport type { PuzzleCompletion } from './utils';\n\n// ============================================================================\n// Theme Utilities\n// ============================================================================\n\n/** Types for theme preference management. */\nexport type {\n /** Theme preference: 'light' | 'dark' | 'system'. */\n ThemePreference,\n /** Resolved theme without system option: 'light' | 'dark'. */\n ResolvedTheme,\n} from './utils';\n\n/** Theme detection and resolution utilities. */\nexport {\n /** localStorage key for theme preference ('sudojo-theme'). */\n THEME_STORAGE_KEY,\n /** localStorage key for font size preference ('sudojo-font-size'). */\n FONT_SIZE_STORAGE_KEY,\n /** Detect the system color scheme preference (light/dark). */\n getSystemTheme,\n /** Resolve a ThemePreference to an actual theme using the system theme. */\n resolveTheme,\n /** Type guard: check if a value is a valid ThemePreference. */\n isValidThemePreference,\n} from './utils';\n\n// ============================================================================\n// Subscription Utilities\n// ============================================================================\n\n/** RevenueCat subscription conversion and display utilities. */\nexport {\n /** Convert a RevenueCat package to a Product domain model. */\n convertPackageToProduct,\n /** Parse RevenueCat CustomerInfo into a Subscription domain model. */\n parseCustomerInfo,\n /** Get human-readable name for an ISO 8601 subscription period (e.g., 'P1M' -> 'Monthly'). */\n getPeriodDisplayName,\n /** Check if a subscription period is the \"best value\" option (annual plans). */\n isBestValuePlan,\n /** Get a user-friendly error message for a RevenueCat error code. */\n getRevenueCatErrorMessage,\n /** i18n key for a period's unit (e.g. 'P1M' -> 'periods.month'), or null. */\n getPeriodLabelKey,\n /** Localized price suffix for a period (e.g. '/month'), or ''. */\n getPeriodLabel,\n /** Whether a product is the best-value plan (annual period or annual/yearly id). */\n isBestValueProduct,\n /** Months in a subscription period (named or ISO 8601), or null. */\n subscriptionPeriodToMonths,\n /** Percent saved per month by one plan versus another, or null. */\n calculateSavingsPercent,\n /** Whether a subscription was bought on another platform than this client. */\n isCrossPlatformSubscription,\n /** Whether the account can be deleted now (signed in, not anonymous, no active subscription). */\n canDeleteAccount,\n /** Fraction (0-1) of puzzles an offer unlocks, from the levels' percentages. */\n getPuzzleDistribution,\n /** The plan the savings badge compares with (shortest known period), or null. */\n selectSavingsBasePlan,\n /** Percent a plan saves per month against the products' savings base plan, or null. */\n getPlanSavingsPercent,\n} from './utils';\n\n/** Types for subscription display and account deletion helpers. */\nexport type {\n /** Price and period of a plan (for calculateSavingsPercent). */\n PricedPeriod,\n /** A paywall plan (price as number or string, period). */\n PaywallPlan,\n /** Why an account cannot be deleted ('not_signed_in' | 'anonymous' | 'active_subscription'). */\n DeleteAccountBlocker,\n /** Result of canDeleteAccount. */\n DeleteAccountCheck,\n} from './utils';\n\n// ============================================================================\n// Technique Utilities\n// ============================================================================\n\n/** Types for technique and strategy utilities. */\nexport type {\n /** A public technique slug (member of TECHNIQUE_SLUGS). */\n TechniqueSlug,\n /** A strategy stub (member of STRATEGY_SLUGS). */\n StrategySlug,\n /** Strategy difficulty tier ('beginner' ... 'master'). */\n StrategyDifficultyTier,\n /** One localized section of a strategy description. */\n StrategySection,\n /** A technique's localized overview, steps and tips. */\n TechniqueContent,\n} from './utils';\n\n/** Technique and strategy utilities. */\nexport {\n /** Get the icon URL for a solving technique by its path slug. */\n getTechniqueIconUrl,\n /** Public slug for a technique path ('3d-medusa' -> 'medusa-coloring'). */\n toCanonicalTechniquePath,\n /** API path for a technique slug ('medusa-coloring' -> '3d-medusa'). */\n toApiTechniquePath,\n /** Whether two technique paths name the same technique, aliases included. */\n isSameTechniquePath,\n /** Find a technique by API path or canonical slug. */\n findTechniqueByPath,\n /** Parse a comma-separated dependencies field into technique ids. */\n parseTechniqueDependencies,\n /** Techniques a technique depends on (\"Requires\"). */\n getTechniqueDependencies,\n /** Techniques that depend on a technique (\"Learn after\"). */\n getDependentTechniques,\n /** Sort techniques by level, then technique number. */\n sortTechniquesByLevel,\n /** Group techniques by level (Map, each group sorted by technique number). */\n groupTechniquesByLevel,\n /** Techniques of a strategy, sorted by technique number. */\n getTechniquesForStrategy,\n /** Find a strategy by its URL stub. */\n findStrategyByStub,\n /** Public slugs of all 60 techniques (footer / sitemap order). */\n TECHNIQUE_SLUGS,\n /** Stubs of the 17 strategies (difficulty order). */\n STRATEGY_SLUGS,\n /** Difficulty tier for a strategy's difficulty value. */\n getStrategyDifficultyTier,\n /** i18n key for a strategy's difficulty tier (e.g. 'strategy.expert'). */\n getStrategyDifficultyKey,\n /** Localized sections of a strategy from the strategies namespace. */\n getStrategySections,\n /** Localized overview, how-it-works steps and tips of a technique. */\n parseTechniqueContent,\n} from './utils';\n\n// ============================================================================\n// Technique Bitmask Utilities\n// ============================================================================\n\n/** Exact (bigint) technique bitmasks for boards, dailies and game meta. */\nexport {\n /** Exact bitmask of a board/daily/meta; never throws (falls back to 0n). */\n exactTechniqueBitmask,\n /** Exact bitmask as the base-10 string API requests take. */\n techniqueBitmaskString,\n /** The techniques / techniques_bitmask pair to store on game meta. */\n techniqueFieldsOf,\n} from './utils';\n\n// ============================================================================\n// Technique Walkthrough Utilities\n// ============================================================================\n\n/** A single step in a technique walkthrough (board + hint overlay + text). */\nexport type { WalkthroughStep } from './utils';\n\n/** Shared logic for building step-by-step technique examples from practice data. */\nexport {\n /** Parse a comma-delimited pencilmarks string into per-cell arrays. */\n parsePencilmarksString,\n /** Convert per-cell pencilmarks arrays back to a comma-delimited string. */\n pencilmarksToString,\n /** Parse board/pencilmarks/solution strings into a SudokuCell array. */\n parsePracticeBoard,\n /** Deep clone a SudokuCell array. */\n cloneSudokuBoard,\n /** Apply a hint step's actions to a board, returning new state. */\n applyHintStep,\n /** Parse a hint_data JSON string into SolverHints. */\n parseHintData,\n /** Resolve localised title and text for a single hint step. */\n localizeHintStep,\n /** Build the full walkthrough step array from board and hint data. */\n buildWalkthroughSteps,\n} from './utils';\n\n// ============================================================================\n// Hint Explanation Utilities\n// ============================================================================\n\n/** Hint explanation generation utilities for teaching users solving techniques. */\nexport {\n /** Generate a detailed explanation for a hint step based on the technique. */\n generateDetailedExplanation,\n /** Get a short action summary for a hint step (e.g., 'Place 5 in R1C3'). */\n getHintActionSummary,\n} from './utils';\n\n// ============================================================================\n// Localized Hint Utilities\n// ============================================================================\n\n/** Types for hint text localization. */\nexport type {\n /** Translation function compatible with i18next's `t` function. */\n TranslateFunction,\n /** Nested heading tree (the `headings` object of hints.json). */\n HintHeadingTree,\n /** Text/title/heading resolvers returned by createLocalizedHintHelpers. */\n LocalizedHintHelpers,\n} from './utils';\n\n/** Hint localization utilities. */\nexport {\n /** Get localized text for a hint step using a translation function. */\n getLocalizedHintText,\n /** Get localized title for a hint step using a translation function. */\n getLocalizedHintTitle,\n /** Resolve a localized API field, falling back to the raw value. */\n localizedField,\n /** Key prefix of the per-step heading tree ('headings.'). */\n HINT_HEADING_KEY_PREFIX,\n /** Heading localization (headings.<path>) for a hint step, or undefined. */\n getStepHeadingLocalization,\n /** Translated heading for a hint step, or ''. */\n getLocalizedHintHeading,\n /** Fill {{valueN}} placeholders from a values array. */\n interpolateHintValues,\n /** Heading for a hint step looked up in a heading tree (no i18n library). */\n getStepHeadingFromTree,\n /** Build the text/title/heading resolvers behind the apps' useLocalizedHint. */\n createLocalizedHintHelpers,\n} from './utils';\n\n// ============================================================================\n// Entity Translation Utilities\n// ============================================================================\n\n/** Shapes the entity display helpers read. */\nexport type {\n /** Level fields used by getLevelDisplayTitle / getLevelDisplayText. */\n LevelDisplaySource,\n /** Technique fields used by getTechniqueDisplayTitle. */\n TechniqueDisplaySource,\n /** Strategy fields used by getStrategyDisplayTitle. */\n StrategyDisplaySource,\n} from './utils';\n\n/** Translation of API entities (levels, techniques, belts). */\nexport {\n /** Route prefixed entity keys (levels.*, techniques.*) to their namespaces. */\n createNamespacedTranslate,\n /** Display title of a level (localization, levels namespace, raw title). */\n getLevelDisplayTitle,\n /** Display description of a level (localization, levels namespace, raw text). */\n getLevelDisplayText,\n /** Display title of a technique (localization, techniques namespace, raw title). */\n getTechniqueDisplayTitle,\n /** Localized belt name for a level ('belts' namespace `${level}.name`). */\n getBeltDisplayName,\n /** Localized belt label for a level ('belts' namespace `${level}.label`). */\n getBeltDisplayLabel,\n /** Display title of a strategy (localization, strategies namespace, raw title, stub). */\n getStrategyDisplayTitle,\n} from './utils';\n\n// ============================================================================\n// i18n Key Utilities\n// ============================================================================\n\n/** Internationalization key generation and localization utilities. */\nexport {\n /** Get i18n key for a belt name (e.g., 'belts.1.name'). */\n getBeltKey,\n /** Get localized belt name using a translation function. */\n getLocalizedBeltName,\n /** Get i18n key for a belt label (e.g., 'belts.1.label'). */\n getBeltLabelKey,\n /** Get localized belt label (e.g., 'White Belt'). */\n getLocalizedBeltLabel,\n /** Get i18n key for a level title (e.g., 'levels.3'). */\n getLevelKey,\n /** Get localized level title using a translation function. */\n getLocalizedLevelTitle,\n /** Get i18n key for a technique name (e.g., 'techniques.full-house.title'). */\n getTechniqueKey,\n /** Get localized technique name using a translation function. */\n getLocalizedTechniqueName,\n} from './utils';\n\n// ============================================================================\n// Digit Display Utilities\n// ============================================================================\n\n/** Digit display format conversion. */\nexport {\n /** Convert a digit (1-9) to its display string based on the format (numeric, kanji, emojis). */\n displayDigit,\n} from './utils';\n\n// ============================================================================\n// Scanned Board (OCR) Utilities\n// ============================================================================\n\n/** A board read from an image, and the error a scan can fail with. */\nexport type { ScannedBoard, ScanBoardErrorCode } from './utils';\n\nexport {\n /** Fewest givens a scanned board needs (17). */\n MIN_SCAN_CLUES,\n /** Error thrown by scannedBoardFromResponse / useBoardScan, with a `code`. */\n ScanBoardError,\n /** Normalize an OCR API result into givens, player digits and pencilmarks. */\n toScannedBoard,\n /** Whether a scanned board carries any player digits. */\n hasScannedInput,\n /** Turn the OCR endpoint's response into a ScannedBoard (or throw why not). */\n scannedBoardFromResponse,\n} from './utils';\n\n// ============================================================================\n// Share URL Utilities\n// ============================================================================\n\n/** Types for share URL building and parsing. */\nexport type {\n /** Options for buildShareUrl. */\n ShareUrlParams,\n /** Game state parsed from a puzzle share URL. */\n ParsedShareParams,\n /** What a share URL points at ('daily' | 'puzzle' | 'technique' | ...). */\n ShareUrlType,\n /** URLSearchParams or a plain object of route params. */\n ShareParamsSource,\n} from './utils';\n\n/** Build a share URL from game state. */\nexport { buildShareUrl } from './utils';\n\n/** Parse share URL query parameters into game state. */\nexport { parseShareParams } from './utils';\n\n/** Derive web app URL from API base URL. */\nexport { getWebUrl } from './utils';\n\n// ============================================================================\n// Auth Utilities\n// ============================================================================\n\n/** Minimal user shape for auth checks. */\nexport type { AuthUser } from './utils';\n\n/** Check if user-specific API calls should be enabled (non-anonymous, has token). */\nexport { isAuthenticatedUser } from './utils';\n\n/** Whether a user is a real (signed-in, non-anonymous) account. */\nexport { isRealUser } from './utils';\n\n// ============================================================================\n// Language Utilities\n// ============================================================================\n\n/** Types for supported languages. */\nexport type {\n /** A supported language (code, native name, flag). */\n SupportedLanguageInfo,\n /** A supported language code (lowercase, e.g. 'zh-hant'). */\n SupportedLanguageCode,\n} from './utils';\n\n/** Supported languages, locale resolution and language storage keys. */\nexport {\n /** The 15 supported UI languages. */\n SUPPORTED_LANGUAGES,\n /** Codes of the supported languages. */\n SUPPORTED_LANGUAGE_CODES,\n /** Fallback language ('en'). */\n DEFAULT_LANGUAGE,\n /** Web localStorage key for the language preference ('language'). */\n LANGUAGE_STORAGE_KEY,\n /** RN AsyncStorage key for the language preference ('@sudojo/language'). */\n NATIVE_LANGUAGE_STORAGE_KEY,\n /** Whether a code is a supported language code. */\n isSupportedLanguage,\n /** Map a code or locale tag to a supported code (zh-TW/HK -> zh-hant), or null. */\n normalizeLanguageCode,\n /** Supported language for a locale tag, defaulting to 'en'. */\n resolveLanguage,\n /** BCP 47 casing of a code ('zh-hant' -> 'zh-Hant'). */\n toLanguageTag,\n /** Native name of a language, or undefined. */\n getLanguageNativeName,\n} from './utils';\n\n// ============================================================================\n// Community Utilities\n// ============================================================================\n\n/** A known community platform (id, label key, English label). */\nexport type { CommunityPlatformInfo } from './utils';\n\n/** Community platform order and labels. */\nexport {\n /** Known community platforms in display order. */\n COMMUNITY_PLATFORMS,\n /** Info for a platform id (case-insensitive), or undefined. */\n getCommunityPlatform,\n /** Sort platform ids into display order (unknown last). */\n sortCommunityPlatforms,\n} from './utils';\n\n// ============================================================================\n// Gamification Utilities\n// ============================================================================\n\n/** Types for badge progress. */\nexport type {\n /** Badge definitions split into level/game lists with an earned lookup. */\n BadgeProgress,\n /** Badge definition fields groupBadgeProgress reads. */\n BadgeDefinitionLike,\n} from './utils';\n\n/** Badge grouping for profile and statistics screens. */\nexport {\n /** badgeType of level mastery badges ('level_mastery'). */\n LEVEL_MASTERY_BADGE_TYPE,\n /** badgeType of games-played badges ('games_played'). */\n GAMES_PLAYED_BADGE_TYPE,\n /** Split badge definitions into sorted level/game lists with isEarned. */\n groupBadgeProgress,\n} from './utils';\n\n// ============================================================================\n// Hint Access Utilities\n// ============================================================================\n\n/** Types for the hint access panel. */\nexport type {\n /** What the hint access panel's button does. */\n HintAccessAction,\n /** Which message the hint access panel shows. */\n HintAccessVariant,\n /** Action and message variant for a hint access state. */\n HintAccessPresentation,\n} from './utils';\n\n/** Client-side hint gating helpers. */\nexport {\n /** Hint steps visible without the level's entitlement (2). */\n FREE_HINT_STEP_LIMIT,\n /** Map a hint access state to the panel's action and message variant. */\n getHintAccessAction,\n /** i18n key suffixes for the hint access messages. */\n HINT_ACCESS_KEY_SUFFIXES,\n} from './utils';\n\n// ============================================================================\n// Daily Date Utilities\n// ============================================================================\n\n/** Calendar-date helpers for daily puzzles (UTC \"today\", like the API). */\nexport {\n /** UTC date of a Date (default now) as YYYY-MM-DD. */\n getUtcDateString,\n /** Normalize a daily date to YYYY-MM-DD without a timezone shift, or null. */\n normalizeDailyDate,\n /** Format a YYYY-MM-DD daily date as a local calendar date. */\n formatDailyDate,\n /** Whether a saved daily is not today's (UTC) daily. */\n isStaleDaily,\n} from './utils';\n\n// ============================================================================\n// Game Fetch Status Utilities\n// ============================================================================\n\n/** Response shape (with the legacy action field) read by getGameFetchStatus. */\nexport type { GameFetchResponse } from './utils';\n\n/** Status derivation shared by useLevelGame and useDailyGame. */\nexport {\n /** Whether a response/error says sign-in is required (legacy API signal). */\n isAuthRequiredResponse,\n /** Whether a response/error says a subscription is required (legacy API signal). */\n isSubscriptionRequiredResponse,\n /** Derive a GameFetchStatus from query state. */\n getGameFetchStatus,\n /** HTTP status carried by an error (NetworkError.status), or undefined. */\n getErrorHttpStatus,\n /** Derive a PracticeFetchStatus (401/402 aware) from query state. */\n getPracticeFetchStatus,\n} from './utils';\n\n/** Status of a practice fetch ('loading' | 'ready' | 'auth_required' | 'subscription_required' | 'no_practices' | 'error'). */\nexport type { PracticeFetchStatus } from './utils';\n\n// ============================================================================\n// Technique Example Utilities\n// ============================================================================\n\n/** Types for technique example walkthroughs. */\nexport type {\n /** Stored example/practice fields a walkthrough is built from. */\n TechniqueExampleSource,\n /** Translation functions (hints, techniques, default namespaces). */\n TechniqueWalkthroughTranslations,\n /** Walkthrough cards and their headings. */\n TechniqueWalkthrough,\n} from './utils';\n\n/** Build walkthrough cards and headings for a stored technique example. */\nexport { buildTechniqueWalkthrough } from './utils';\n\n// ============================================================================\n// Hooks\n// ============================================================================\n\nexport {\n // Data hooks\n /** Fetch a single difficulty level by number. */\n useLevel,\n /** Fetch all difficulty levels with sorting and filtering utilities. */\n useLevels,\n /** Fetch a single solving technique by number. */\n useTechnique,\n /** Fetch all solving techniques with grouping utilities. */\n useTechniques,\n /** Fetch communities for a specific language with platform grouping. */\n useCommunities,\n /** Fetch learning materials with filtering by technique and language. */\n useLearning,\n /** Fetch a single learning item by UUID. */\n useLearningItem,\n\n /**\n * @deprecated Use `useSudoku` instead. `useGame` uses a legacy 2D array board\n * representation, while `useSudoku` uses a flat 81-cell array consistent with\n * the Kotlin renderable layer and the rest of the codebase.\n */\n useGame,\n\n /** Primary game state hook with flat 81-cell board, pencil mode, and scrambling. */\n useSudoku,\n\n /** Teaching/hint integration with the solver API (legacy GameHint format). */\n useGameTeaching,\n\n /** Fetch a random board for a specific level with auth/subscription handling. */\n useLevelGame,\n /** Fetch today's daily puzzle with auth/subscription handling. */\n useDailyGame,\n\n /** Game timer using refs to avoid re-renders every second. */\n useGameTimer,\n\n /** Persist individual game progress to localStorage. */\n useGamePersistence,\n /** Auto-save game state with debouncing. */\n useAutoSave,\n\n /** Generic typed localStorage hook with SSR safety. */\n useLocalStorage,\n\n /** Solver hint integration matching Kotlin HintInteractor behavior. */\n useHint,\n\n /** Current game management with Zustand store (daily/play slots). */\n useGamePlay,\n\n /** Shared \"Continue Last Sudoku\" logic for web and RN. */\n useContinueGame,\n\n /** Manual puzzle entry mode with solver validation. */\n useBoardEntry,\n\n /** Scan a board from an image: givens, player digits and pencilmarks. */\n useBoardScan,\n\n /** Server-side game session management for gamification (points, badges). */\n useGameSession,\n\n /** Check whether a level is enabled for the current user's entitlements. */\n useLevelEnabled,\n /** Check whether a technique is enabled for the current user's entitlements. */\n useTechniqueEnabled,\n\n /** Convert internal user level (0-indexed) to display values (1-indexed + belt). */\n useDisplayLevel,\n\n /** Compute cumulative puzzle distribution across entitlement tiers. */\n usePuzzleDistribution,\n\n /** Shared hint step tracker for game screens (ref + state). */\n useHintStepTracker,\n\n /** Auto-hint orchestration for shared links/deep links. */\n useAutoHint,\n\n /** Progress reporting for game state persistence. */\n useProgressReporter,\n\n /** Regenerate hint_data for all stored practices via solver. */\n useRegeneratePracticeHints,\n\n /** Emit a hint action event to the active SudokuGame. */\n emitHintAction,\n /** Report hint status back after processing an action. */\n reportHintStatus,\n /** Subscribe to hint status updates. */\n onHintStatus,\n /** Hook for SudokuGame to listen for external hint action events. */\n useHintActionListener,\n\n /** Fire a callback once each time a puzzle becomes completed (re-arms on false). */\n useCompletionTrigger,\n /** Fetch strategies (unwrapped) with findStrategyByStub. */\n useStrategies,\n /** Fetch a random practice for a technique with auth/subscription/empty status. */\n usePracticeGame,\n /** Whether the user is a real (non-anonymous) account. */\n useIsRealUser,\n /** Whether the signed-in user is a site admin (GET /users/:uid siteAdmin). */\n useIsSiteAdmin,\n /** Look up a technique by path or alias (list first, then GET by path). */\n useTechniqueByPath,\n /** Fetch a technique's worked example and build its walkthrough. */\n useTechniqueExample,\n /** Build (memoized) the walkthrough for a stored technique example. */\n useTechniqueWalkthrough,\n /** Player's puzzle progress in localStorage (markCompleted, isCompleted, stats). */\n usePuzzleProgress,\n /** Account deletion rule and delete-then-sign-out sequence. */\n useDeleteAccount,\n /** Saved game to resume for a play screen (snapshot; clears stale dailies). */\n useResumeGame,\n /** The saved game a play screen should resume, or null (pure). */\n getResumeGame,\n /** Daily/Level play screen orchestration (resume, save, session, completion). */\n usePuzzleSession,\n /** Entered-puzzle save/resume after validation (no server session). */\n useEnteredGameSession,\n} from './hooks';\n\nexport type {\n // Data hook types\n /** Options for useLevel hook. */\n UseLevelOptions,\n /** Result type for useLevel hook. */\n UseLevelResult,\n /** Options for useLevels hook. */\n UseLevelsOptions,\n /** Result type for useLevels hook. */\n UseLevelsResult,\n /** Options for useTechnique hook. */\n UseTechniqueOptions,\n /** Result type for useTechnique hook. */\n UseTechniqueResult,\n /** Options for useTechniques hook. */\n UseTechniquesOptions,\n /** Result type for useTechniques hook. */\n UseTechniquesResult,\n /** Options for useCommunities hook. */\n UseCommunitiesOptions,\n /** Result type for useCommunities hook. */\n UseCommunitiesResult,\n /** Options for useLearningItem hook. */\n UseLearningItemOptions,\n /** Result type for useLearningItem hook. */\n UseLearningItemResult,\n /** Options for useLearning hook. */\n UseLearningOptions,\n /** Result type for useLearning hook. */\n UseLearningResult,\n\n // Game hook types (legacy)\n /** @deprecated Options for legacy useGame hook. Use UseSudokuOptions instead. */\n UseGameOptions,\n /** @deprecated Result type for legacy useGame hook. Use UseSudokuResult instead. */\n UseGameResult,\n\n // Sudoku hook types\n /** Options for useSudoku hook (initial app settings). */\n UseSudokuOptions,\n /** Result type for useSudoku hook (state, computed values, actions, utilities). */\n UseSudokuResult,\n\n // Teaching hook types\n /** Options for useGameTeaching hook (network client, URL, token). */\n UseGameTeachingOptions,\n /** Result type for useGameTeaching hook (teaching state, hint actions). */\n UseGameTeachingResult,\n\n // Game fetching hook types\n /** Options for useLevelGame hook (network, auth, level number). */\n UseLevelGameOptions,\n /** Result type for useLevelGame hook (board data, fetch status). */\n UseLevelGameResult,\n /** Options for useDailyGame hook (network, auth). */\n UseDailyGameOptions,\n /** Result type for useDailyGame hook (daily data, fetch status). */\n UseDailyGameResult,\n /** Status of a game fetch: 'loading' | 'success' | 'auth_required' | 'subscription_required' | 'entitlement_required' | 'error'. */\n GameFetchStatus,\n\n // Timer hook types\n /** Options for useGameTimer hook (autoStart, initialTime). */\n UseGameTimerOptions,\n /** Result type for useGameTimer hook (elapsedRef, controls). */\n UseGameTimerResult,\n\n // Persistence hook types\n /** Options for useGamePersistence hook (puzzleKey, autoSave). */\n UseGamePersistenceOptions,\n /** Result type for useGamePersistence hook (load, save, clear, hasSaved). */\n UseGamePersistenceResult,\n\n // Hint hook types\n /** Options for useHint hook (network, puzzle state, technique filter). */\n UseHintOptions,\n /** Result type for useHint hook (hint steps, navigation, apply). */\n UseHintResult,\n /** Board data returned when applying a hint (user input, pencilmarks). */\n HintBoardData,\n /** Data passed to onHintReceived callback (hint, board data, technique info). */\n HintReceivedData,\n /** Access denied error info when hint level exceeds subscription tier. */\n HintAccessError,\n\n // Game play hook types\n /** Options for useGamePlay hook (slot selection, auto-save delay). */\n UseGamePlayOptions,\n /** Result type for useGamePlay hook (current game, start, update, clear). */\n UseGamePlayResult,\n\n // Continue game hook types\n /** Options for useContinueGame hook. */\n UseContinueGameOptions,\n /** Result type for useContinueGame hook. */\n UseContinueGameResult,\n /** Navigation target returned by useContinueGame. */\n ContinueTarget,\n\n // Board entry hook types\n /** Options for useBoardEntry hook (network client, URL, token). */\n UseBoardEntryOptions,\n /** Result type for useBoardEntry hook (cells, validation, actions). */\n UseBoardEntryReturn,\n /** Validated puzzle data from solver (puzzle + solution strings). */\n ValidatedPuzzle,\n\n // Board scan hook types\n /** Options for useBoardScan hook (network client, URL). */\n UseBoardScanOptions,\n /** Result type for useBoardScan hook (scan, isScanning). */\n UseBoardScanReturn,\n\n // Game session hook types\n /** Options for useGameSession hook (network, auth, userId). */\n UseGameSessionOptions,\n /** Result of starting a game session (sessionStarted, sessionId). */\n GameSessionResult,\n /** Result of finishing a game session (leveledUp, badges, points). */\n GameFinishResult,\n\n // Display level hook types\n /** Result type for useDisplayLevel hook. */\n UseDisplayLevelResult,\n\n // Hint step tracker types\n /** Result type for useHintStepTracker hook. */\n UseHintStepTrackerResult,\n\n // Auto-hint types\n /** Options for useAutoHint hook. */\n UseAutoHintOptions,\n\n // Practice admin types\n UseRegeneratePracticeHintsOptions,\n UseRegeneratePracticeHintsResult,\n\n // Progress reporter types\n /** Options for useProgressReporter hook. */\n UseProgressReporterOptions,\n /** Callback type for progress updates. */\n ProgressUpdateCallback,\n\n // Hint action types\n /** Status reported after a hint action is processed. */\n HintActionStatus,\n\n // Board entry play state\n /** What a validated entered puzzle should apply (scanned input, pencilmarks). */\n BoardEntryPlayState,\n\n // Strategies hook types\n /** Options for useStrategies hook. */\n UseStrategiesOptions,\n /** Result type for useStrategies hook. */\n UseStrategiesResult,\n\n // Practice game hook types\n /** Options for usePracticeGame hook. */\n UsePracticeGameOptions,\n /** Result type for usePracticeGame hook. */\n UsePracticeGameResult,\n\n // User status hook types\n /** Options for useIsSiteAdmin hook. */\n UseIsSiteAdminOptions,\n /** Result type for useIsSiteAdmin hook. */\n UseIsSiteAdminResult,\n\n // Technique lookup / example hook types\n /** Options for useTechniqueByPath hook. */\n UseTechniqueByPathOptions,\n /** Result type for useTechniqueByPath hook. */\n UseTechniqueByPathResult,\n /** Where a technique example comes from ('example' | 'practice'). */\n TechniqueExampleSourceKind,\n /** Options for useTechniqueExample hook. */\n UseTechniqueExampleOptions,\n /** Result type for useTechniqueExample hook. */\n UseTechniqueExampleResult,\n\n // Puzzle progress hook types\n /** Options for usePuzzleProgress hook. */\n UsePuzzleProgressOptions,\n /** Result type for usePuzzleProgress hook. */\n UsePuzzleProgressResult,\n\n // Account deletion hook types\n /** What deleteAccount did ('deleted' | 'blocked' | 'failed'). */\n DeleteAccountOutcome,\n /** Provider tokens for account deletion (Google/Apple revocation). */\n DeleteAccountProviderTokens,\n /** Options for useDeleteAccount hook. */\n UseDeleteAccountOptions,\n /** Result type for useDeleteAccount hook. */\n UseDeleteAccountResult,\n\n // Play session hook types\n /** Play screen kind ('daily' | 'level'). */\n PuzzleSessionSource,\n /** Saved game kind useResumeGame can resume ('daily' | 'level' | 'entered'). */\n ResumeGameSource,\n /** Options for useEnteredGameSession hook. */\n UseEnteredGameSessionOptions,\n /** Result type for useEnteredGameSession hook. */\n UseEnteredGameSessionResult,\n /** Options for useResumeGame hook. */\n UseResumeGameOptions,\n /** Result type for useResumeGame hook. */\n UseResumeGameResult,\n /** The puzzle a play screen shows (fetched or resumed). */\n ActivePuzzle,\n /** Props for the game component from usePuzzleSession. */\n PuzzleGameProps,\n /** Fetched Daily/Board shape usePuzzleSession accepts. */\n SessionPuzzleInput,\n /** Options for usePuzzleSession hook. */\n UsePuzzleSessionOptions,\n /** Result type for usePuzzleSession hook. */\n UsePuzzleSessionResult,\n} from './hooks';\n\n// ============================================================================\n// Stores\n// ============================================================================\n\n/** Zustand store for current game state with daily/play slots and localStorage persistence. */\nexport { useGamePlayStore } from './stores/gamePlayStore';\n/** State shape for the game play Zustand store. */\nexport type { GamePlayState } from './stores/gamePlayStore';\n\n// ============================================================================\n// Config\n// ============================================================================\n\n/** Authentication provider configuration types. */\nexport type {\n /** Available auth provider types: 'google' | 'apple' | 'email'. */\n AuthProviderType,\n /** Configuration for which auth providers are enabled. */\n AuthProvidersConfig,\n} from './config';\n\n/** Default auth providers configuration (Google + Email, anonymous fallback). */\nexport { DEFAULT_AUTH_PROVIDERS } from './config';\n\n// ============================================================================\n// Entitlement Context\n// ============================================================================\n\n/** Provider that supplies entitlements to useLevelEnabled / useTechniqueEnabled. */\nexport { EntitlementProvider } from './context';\n/** React context for entitlements (for advanced use). */\nexport { EntitlementContext, useEntitlementContext } from './context';\n\n// ============================================================================\n// Sudojo API Context\n// ============================================================================\n\n/** Optional provider of networkClient/baseUrl/token for sudojo_lib hooks. */\nexport { SudojoApiProvider } from './context';\n/** API context, its hooks, and the option-over-context resolver. */\nexport {\n /** React context holding the API connection (for advanced use). */\n SudojoApiContext,\n /** The provider's API connection (throws without a provider). */\n useSudojoApi,\n /** The provider's API connection, or null. */\n useOptionalSudojoApi,\n /** Merge explicit options over a context value (pure; throws if incomplete). */\n resolveSudojoApi,\n /** Resolve a hook's API connection from options, then the provider. */\n useResolvedSudojoApi,\n} from './context';\n/** Types for the Sudojo API context. */\nexport type {\n /** The API connection the provider supplies. */\n SudojoApiValue,\n /** Optional networkClient/baseUrl/token fields of hook options. */\n SudojoApiOptions,\n /** An API connection with every field resolved (token '' when none). */\n ResolvedSudojoApi,\n} from './context';\n\n// ============================================================================\n// Entitlement Utilities (re-exported from sudojo_types)\n// ============================================================================\n\n/** Parse a comma-delimited entitlement string into an array. */\nexport { parseEntitlements } from '@sudobility/sudojo_types';\n\n/** Check if a user has the required entitlement for a level. */\nexport { hasRequiredEntitlement } from '@sudobility/sudojo_types';\n\n// ============================================================================\n// Admin (batch jobs + stats; see src/admin/index.ts for the full list)\n// ============================================================================\n\n/**\n * Admin module: board generation, technique extraction, example creation and\n * admin stats as hooks (`useBoardGenerator`, `useTechniqueExtractor`,\n * `useExampleCreator`, `useSingleBoardExtractor`, `useBoardTechniquesUpdater`,\n * `useAdminStats`), the framework-agnostic jobs behind them\n * (`runBoardGeneration`, `runTechniqueExtraction`, `runExampleCreation`) and\n * their pure rules (`mergeBoardWithUserInput`, `adjustPracticeSolution`,\n * `extractBoardTechniques`, `levelsToSearchForTechnique`, …). Network calls go\n * only through sudojo_client hooks (`useAdminApi`).\n */\nexport * from './admin';\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * @sudobility/sudojo_lib - Business logic library for Sudojo app\n *\n * This library provides:\n * - Game state management with useSudoku hook (ported from renderable)\n * - Board scrambling utilities\n * - Game validation (mistakes, completion)\n * - Level, technique, and learning data hooks\n * - Teaching/hint integration with solver\n * - Legacy useGame hook for backward compatibility\n *\n * ## Hook Architecture\n *\n * The hooks form a layered composition pattern:\n *\n * **Data hooks** (fetch and cache server data):\n * - `useLevels` / `useLevel` - Difficulty level data\n * - `useTechniques` / `useTechnique` - Solving technique data\n * - `useLearning` / `useLearningItem` - Learning material data\n *\n * **Game fetching hooks** (handle auth, subscription, and puzzle loading):\n * - `useLevelGame` - Fetch a random board for a specific level\n * - `useDailyGame` - Fetch today's daily puzzle\n *\n * **Game state hooks** (manage board state and user interaction):\n * - `useSudoku` - Primary game state (flat 81-cell array, modern API)\n * - `useGame` - Legacy game state (2D array, deprecated)\n * - `useBoardEntry` - Manual puzzle entry mode\n * - `useBoardScan` - Read givens, player digits and pencilmarks from a photo\n *\n * **Feature hooks** (provide specific game features):\n * - `useHint` - Solver integration for hints (matches Kotlin HintInteractor)\n * - `useGameTeaching` - Step-by-step teaching with solver\n * - `useGameTimer` - Elapsed time tracking via ref (no re-renders)\n * - `useGamePersistence` / `useAutoSave` - localStorage game save/restore\n * - `useLocalStorage` - Generic typed localStorage hook\n *\n * **Orchestration hooks** (combine multiple hooks for app-level features):\n * - `useGamePlay` - Current game management with Zustand store (daily/play slots)\n * - `useGameSession` - Server-side gamification (start/finish, points, badges)\n *\n * ## Migration Guide\n *\n * Legacy exports (prefixed with \"Legacy\" comments) use the 2D `GameBoard` type\n * from `useGame`. New code should use `useSudoku` with its flat 81-cell\n * `SudokuBoard` type. See `@deprecated` tags on legacy exports.\n */\n\n// ============================================================================\n// Legacy Types (useGame hook)\n// ============================================================================\n\n/**\n * @deprecated Use `SudokuCell` instead. Part of the legacy `useGame` 2D board API.\n */\nexport type {\n CellPosition,\n CellState,\n GameBoard,\n GameHint,\n GameMove,\n GameSettings,\n GameState,\n GameStatus,\n TeachingState,\n} from './types';\n\n/** @deprecated Use `DEFAULT_APP_SETTINGS` / `DEFAULT_PLAY_SETTINGS` instead. */\nexport { DEFAULT_GAME_SETTINGS } from './types';\n\n// ============================================================================\n// Sudoku Types (useSudoku hook - ported from renderable)\n// ============================================================================\n\n/** Core Sudoku cell and board types using flat 81-cell array representation. */\nexport type {\n /** A single cell in the Sudoku board (indexed 0-80). */\n SudokuCell,\n /** The Sudoku board containing all 81 cells. */\n SudokuBoard,\n /** Current play state including board, settings, and selection. */\n SudokuPlay,\n /** Session settings that can change during play (pencilmarking, auto-pencilmarks). */\n SudokuPlaySettings,\n /** App-level settings persisted across sessions (showErrors, display format). */\n SudokuAppSettings,\n /** Full game state including source, history, and digit mapping. */\n SudokuGameState,\n /** Display modes for Sudoku digits ('NUMERIC' | 'KANJI' | 'COLORS' | 'EMOJIS'). */\n SudokuDisplay,\n /** Source of the puzzle ('DAILY' | 'CHALLENGE' | 'LEVEL' | 'ENTERED'). */\n PlayingSource,\n} from './types';\n\n/** Default settings and cell/board helper functions for the modern Sudoku API. */\nexport {\n /** Default session play settings (pencilmarking off, auto-pencilmarks off). */\n DEFAULT_PLAY_SETTINGS,\n /** Default app settings (showErrors on, animations on, numeric display). */\n DEFAULT_APP_SETTINGS,\n /** Create an empty SudokuCell at the given index. */\n createEmptyCell,\n /** Create an empty 81-cell SudokuBoard. */\n createEmptyBoard,\n /** Check if a cell has an error (input does not match solution). */\n cellHasError,\n /** Get row index (0-8) from cell index (0-80). */\n rowOf,\n /** Get column index (0-8) from cell index (0-80). */\n columnOf,\n /** Get block index (0-8) from cell index (0-80). */\n blockOf,\n /** Get cell index (0-80) from row and column. */\n cellIndex,\n /** Get all cell indices in the same row as the given index. */\n getRowIndices,\n /** Get all cell indices in the same column as the given index. */\n getColumnIndices,\n /** Get all cell indices in the same block as the given index. */\n getBlockIndices,\n /** Get all related cell indices (same row, column, or block) excluding the cell itself. */\n getRelatedIndices,\n} from './types';\n\n// ============================================================================\n// Display types (for rendering - matches Kotlin renderable)\n// ============================================================================\n\n/** Display and hint visualization types matching the Kotlin renderable layer. */\nexport type {\n /** Highlighted area in a hint (row, column, or block). */\n HintArea,\n /** Cell display information in a hint step. */\n HintCell,\n /** Actions to perform on a cell during hint visualization. */\n HintCellActions,\n /** A single hint step with title, text, areas, cells, links, and groups. */\n DisplayHintStep,\n /** Complete display state for a single cell (colors, digit, pencilmarks). */\n CellDisplayState,\n /** Display state for a single pencilmark (digit and color). */\n PencilmarkDisplayState,\n /** UI color palette with system colors for light or dark mode. */\n UIColorPalette,\n /** Link type for chain visualization ('strong' | 'weak'). */\n LinkType,\n /** A link between two cells in a chain (display format). */\n DisplayLink,\n /** A group of cells for pattern visualization (display format). */\n DisplayCellGroup,\n} from './types';\n\n/** Theme and color enums plus predefined light/dark palettes. */\nexport { ThemeColor, SudokuColor, UIColorLight, UIColorDark } from './types';\n\n// ============================================================================\n// Progress Types (for user progress tracking)\n// ============================================================================\n\n/** Types for tracking user puzzle completion and statistics. */\nexport type {\n /** Record of a completed puzzle (id, type, time). */\n CompletedPuzzle,\n /** Computed game statistics (best times, averages). */\n GameStats,\n /** Full user progress data (completed puzzles, streak, stats). */\n UserProgress,\n} from './types';\n\nexport {\n /** Default empty user progress state. */\n DEFAULT_PROGRESS,\n /** localStorage key for progress data ('sudojo-progress'). */\n PROGRESS_STORAGE_KEY,\n} from './types';\n\n// ============================================================================\n// Settings Types (for app settings)\n// ============================================================================\n\n/** Types for application settings. */\nexport type {\n /** Digit display format ('numeric' | 'kanji' | 'emojis'). */\n DigitDisplay,\n /** Application settings (showErrors, symmetrical, display). */\n AppSettings,\n} from './types';\n\nexport {\n /** Default application settings. */\n DEFAULT_SETTINGS,\n /** localStorage key for settings ('sudojo-settings'). */\n SETTINGS_STORAGE_KEY,\n} from './types';\n\n// ============================================================================\n// Subscription Types (for subscription management)\n// ============================================================================\n\n/** Types for RevenueCat subscription management. */\nexport type {\n /** Subscription product information (price, period, trial). */\n Product,\n /** User subscription status (active, expiration, renewal). */\n Subscription,\n} from './types';\n\n/** Default inactive subscription state. */\nexport { DEFAULT_SUBSCRIPTION } from './types';\n\n// ============================================================================\n// Game Persistence Types (for saving/loading game state)\n// ============================================================================\n\n/** Types for saving and restoring game progress to localStorage. */\nexport type {\n /** Saved game state (input, pencilmarks, mode, timestamp). */\n SavedGameState,\n /** Key identifying a game to persist (type + id). */\n GamePersistenceKey,\n} from './types';\n\nexport {\n /** localStorage key prefix for game saves ('sudojo_game_'). */\n GAME_STORAGE_PREFIX,\n /** Generate a localStorage key from a GamePersistenceKey. */\n getGameStorageKey,\n} from './types';\n\n// ============================================================================\n// Current Game Types (for current game feature)\n// ============================================================================\n\n/** Types for the Zustand-backed current game store. */\nexport type {\n /** Source of the current game ('daily' | 'level' | 'entered'). */\n GameSource,\n /** Navigation metadata for resuming a game (date, level, board info). */\n CurrentGameMeta,\n /** Full current game state stored in Zustand (puzzle, progress, timing). */\n CurrentGame,\n /** Which store slot a game lives in ('daily' | 'play'). */\n GameSlot,\n} from './types';\n\n// ============================================================================\n// Legacy Utilities (useGame hook)\n// ============================================================================\n\n/**\n * @deprecated These utilities work with the legacy 2D `GameBoard` type.\n * For new code, use `useSudoku` with its flat 81-cell board and the\n * scrambler/presenter utilities below.\n */\nexport {\n /** @deprecated Clone a 2D GameBoard. Use useSudoku's immutable state instead. */\n cloneBoard,\n /** @deprecated Count filled cells in a 2D GameBoard. */\n countFilledCells,\n /** @deprecated Create a 2D GameBoard from puzzle/solution strings. */\n createGameBoard,\n /** @deprecated Get cells in a block by block index (2D API). */\n getBlockCells,\n /** @deprecated Get block index from row/col (2D API). Use blockOf() instead. */\n getBlockIndex,\n /** @deprecated Get 2D board state as string. Use cellsToStateString() instead. */\n getBoardStateString,\n /** @deprecated Get cells in a column (2D API). Use getColumnIndices() instead. */\n getColumnCells,\n /** @deprecated Get empty cells from a 2D GameBoard. */\n getEmptyCells,\n /** @deprecated Get pencilmarks string from 2D GameBoard. Use cellsToPencilmarksString() instead. */\n getPencilmarksString,\n /** @deprecated Get related cells (2D API). Use getRelatedIndices() instead. */\n getRelatedCells,\n /** @deprecated Get cells in a row (2D API). Use getRowIndices() instead. */\n getRowCells,\n /** @deprecated Check if placement is valid (2D API). */\n isValidPlacement,\n /** @deprecated Auto-remove pencilmarks (2D API). useSudoku handles this internally. */\n autoRemovePencilmarks,\n /** @deprecated Clear highlights (2D API). useSudoku handles this via presentBoard(). */\n clearHighlights,\n /** @deprecated Count mistakes (2D API). Use useSudoku's errorCount instead. */\n countMistakes,\n /** @deprecated Get incorrect cells (2D API). Use useSudoku's errorCells instead. */\n getIncorrectCells,\n /** @deprecated Get progress percentage (2D API). Use useSudoku's progress instead. */\n getProgressPercentage,\n /** @deprecated Check if board is filled (2D API). */\n isBoardFilled,\n /** @deprecated Check if cell is correct (2D API). Use cellHasError() instead. */\n isCellCorrect,\n /** @deprecated Check if game is complete (2D API). Use useSudoku's isCompleted instead. */\n isGameComplete,\n /** @deprecated Check if value is correct (2D API). */\n isValueCorrect,\n /** @deprecated Update cell errors (2D API). useSudoku handles this automatically. */\n updateCellErrors,\n /** @deprecated Update cell highlights (2D API). Use presentBoard() instead. */\n updateCellHighlights,\n /** @deprecated Validate entire game state (2D API). */\n validateGameState,\n} from './utils';\n\n// ============================================================================\n// Sudoku Utilities (useSudoku hook - ported from renderable)\n// ============================================================================\n\n/** Types for board scrambling. */\nexport type {\n /** Protocol for board scramblers (Scrambler and NonScrambler implement this). */\n ScramblerProtocol,\n /** Result of scrambling a board (cells + digit mappings). */\n SudokuScrambleResult,\n} from './utils';\n\n/** Board scrambling and puzzle string conversion utilities. */\nexport {\n /** Scrambler that permutes rows, columns, and digits to create unique puzzles. */\n Scrambler,\n /** Identity scrambler that returns the board unchanged. */\n NonScrambler,\n /** Scramble a board using a ScramblerProtocol implementation. */\n scrambleSudokuBoard,\n /** Parse an 81-character puzzle string into SudokuCell array. */\n parsePuzzleString,\n /** Convert SudokuCell array to puzzle string (given values only). */\n cellsToPuzzleString,\n /** Convert SudokuCell array to state string (given + input values). */\n cellsToStateString,\n /** Convert SudokuCell array to input-only string. */\n cellsToInputString,\n /** Convert SudokuCell array to comma-separated pencilmarks string. */\n cellsToPencilmarksString,\n /** Convert SudokuCell array to solution string ('0' where unknown). */\n cellsToSolutionString,\n /** Count the givens (clues) in a SudokuCell array. */\n countClues,\n} from './utils';\n\n/** Board and level constants from sudojo_types, re-exported for convenience. */\nexport {\n /** Fewest givens a valid Sudoku can have (17). */\n MIN_CLUES,\n /** Lowest difficulty level (1). */\n MIN_LEVEL,\n /** Highest difficulty level (12). */\n MAX_LEVEL,\n /** Whether a value is an integer level in MIN_LEVEL..MAX_LEVEL. */\n isValidLevel,\n /** All levels, MIN_LEVEL..MAX_LEVEL. */\n ALL_LEVELS,\n} from '@sudobility/sudojo_types';\n\n// ============================================================================\n// Presenter utilities (for rendering - matches Kotlin renderable)\n// ============================================================================\n\n/** Options type for the presentBoard function. */\nexport type {\n /** Options for generating cell display states (cells, selection, errors, hints). */\n PresentBoardOptions,\n} from './utils';\n\n/** Board presentation and color utilities matching the Kotlin renderable layer. */\nexport {\n /** Generate display states for all 81 cells (colors, digits, pencilmarks, hints). */\n presentBoard,\n /** Process hint step areas and cells into a map of cell hints by index. */\n calculateCellHints,\n /** Convert a ThemeColor to an actual CSS color string using a palette. */\n themeColorToCSS,\n /** Get the UIColorPalette for light or dark mode. */\n getColorPalette,\n /** Get indices of cells containing a specific digit (given or input). */\n getCellsWithDigit,\n /** Get the digit to highlight based on the selected cell (given or correct input). */\n getSelectedDigit,\n /** Compute the set of cell indices with the same digit as the selected cell. */\n computeSelectedDigitCells,\n /** Convert a solver link (row/col pairs) to display format (flat indices). */\n convertSolverLink,\n /** Convert a solver cell group to display format with ThemeColor. */\n convertSolverCellGroup,\n /** Convert SudokuColor enum to ThemeColor enum. */\n sudokuColorToTheme,\n /** Map a solver color string to SudokuColor (case-insensitive; unknown → null). */\n solverColorToSudokuColor,\n /** Parse a solver digit string (\"125\") into digits 1-9. */\n parseHintDigits,\n /** Convert a SolverHintStep into the DisplayHintStep presentBoard takes. */\n convertSolverHintStep,\n /** Whether a hint step is a conflict hint (has a 'conflict' link). */\n isConflictHintStep,\n} from './utils';\n\n// ============================================================================\n// Time Utilities\n// ============================================================================\n\n/** Time formatting and parsing utilities. */\nexport {\n /** Format seconds into MM:SS or HH:MM:SS string. */\n formatTime,\n /** Parse a MM:SS or HH:MM:SS string back to total seconds. */\n parseTime,\n} from './utils';\n\n// ============================================================================\n// Progress Utilities\n// ============================================================================\n\n/** User progress calculation utilities. */\nexport {\n /** Calculate game statistics (best times, averages) from completed puzzles. */\n calculateStats,\n /** Calculate current daily streak from completion history. */\n calculateStreak,\n /** Check if a specific puzzle (by type and id) has been completed. */\n isPuzzleCompleted,\n /** Get all completed level IDs from completion history. */\n getCompletedLevelIds,\n /** Get all completed daily dates (YYYY-MM-DD) from completion history. */\n getCompletedDailyDates,\n /** Record a puzzle completion in UserProgress (pure markCompleted reducer). */\n applyPuzzleCompletion,\n} from './utils';\n\n/** A puzzle completion to record (CompletedPuzzle without completedAt). */\nexport type { PuzzleCompletion } from './utils';\n\n// ============================================================================\n// Theme Utilities\n// ============================================================================\n\n/** Types for theme preference management. */\nexport type {\n /** Theme preference: 'light' | 'dark' | 'system'. */\n ThemePreference,\n /** Resolved theme without system option: 'light' | 'dark'. */\n ResolvedTheme,\n} from './utils';\n\n/** Theme detection and resolution utilities. */\nexport {\n /** localStorage key for theme preference ('sudojo-theme'). */\n THEME_STORAGE_KEY,\n /** localStorage key for font size preference ('sudojo-font-size'). */\n FONT_SIZE_STORAGE_KEY,\n /** Detect the system color scheme preference (light/dark). */\n getSystemTheme,\n /** Resolve a ThemePreference to an actual theme using the system theme. */\n resolveTheme,\n /** Type guard: check if a value is a valid ThemePreference. */\n isValidThemePreference,\n} from './utils';\n\n// ============================================================================\n// Subscription Utilities\n// ============================================================================\n\n/** RevenueCat subscription conversion and display utilities. */\nexport {\n /** Convert a RevenueCat package to a Product domain model. */\n convertPackageToProduct,\n /** Parse RevenueCat CustomerInfo into a Subscription domain model. */\n parseCustomerInfo,\n /** Get human-readable name for an ISO 8601 subscription period (e.g., 'P1M' -> 'Monthly'). */\n getPeriodDisplayName,\n /** Check if a subscription period is the \"best value\" option (annual plans). */\n isBestValuePlan,\n /** Get a user-friendly error message for a RevenueCat error code. */\n getRevenueCatErrorMessage,\n /** i18n key for a period's unit (e.g. 'P1M' -> 'periods.month'), or null. */\n getPeriodLabelKey,\n /** Localized price suffix for a period (e.g. '/month'), or ''. */\n getPeriodLabel,\n /** Whether a product is the best-value plan (annual period or annual/yearly id). */\n isBestValueProduct,\n /** Months in a subscription period (named or ISO 8601), or null. */\n subscriptionPeriodToMonths,\n /** Percent saved per month by one plan versus another, or null. */\n calculateSavingsPercent,\n /** Whether a subscription was bought on another platform than this client. */\n isCrossPlatformSubscription,\n /** Whether the account can be deleted now (signed in, not anonymous, no active subscription). */\n canDeleteAccount,\n /** Fraction (0-1) of puzzles an offer unlocks, from the levels' percentages. */\n getPuzzleDistribution,\n /** The plan the savings badge compares with (shortest known period), or null. */\n selectSavingsBasePlan,\n /** Percent a plan saves per month against the products' savings base plan, or null. */\n getPlanSavingsPercent,\n} from './utils';\n\n/** Types for subscription display and account deletion helpers. */\nexport type {\n /** Price and period of a plan (for calculateSavingsPercent). */\n PricedPeriod,\n /** A paywall plan (price as number or string, period). */\n PaywallPlan,\n /** Why an account cannot be deleted ('not_signed_in' | 'anonymous' | 'active_subscription'). */\n DeleteAccountBlocker,\n /** Result of canDeleteAccount. */\n DeleteAccountCheck,\n} from './utils';\n\n// ============================================================================\n// Technique Utilities\n// ============================================================================\n\n/** Types for technique and strategy utilities. */\nexport type {\n /** A public technique slug (member of TECHNIQUE_SLUGS). */\n TechniqueSlug,\n /** A strategy stub (member of STRATEGY_SLUGS). */\n StrategySlug,\n /** Strategy difficulty tier ('beginner' ... 'master'). */\n StrategyDifficultyTier,\n /** One localized section of a strategy description. */\n StrategySection,\n /** A technique's localized overview, steps and tips. */\n TechniqueContent,\n} from './utils';\n\n/** Technique and strategy utilities. */\nexport {\n /** Get the icon URL for a solving technique by its path slug. */\n getTechniqueIconUrl,\n /** Public slug for a technique path ('3d-medusa' -> 'medusa-coloring'). */\n toCanonicalTechniquePath,\n /** API path for a technique slug ('medusa-coloring' -> '3d-medusa'). */\n toApiTechniquePath,\n /** Whether two technique paths name the same technique, aliases included. */\n isSameTechniquePath,\n /** Find a technique by API path or canonical slug. */\n findTechniqueByPath,\n /** Parse a comma-separated dependencies field into technique ids. */\n parseTechniqueDependencies,\n /** Techniques a technique depends on (\"Requires\"). */\n getTechniqueDependencies,\n /** Techniques that depend on a technique (\"Learn after\"). */\n getDependentTechniques,\n /** Sort techniques by level, then technique number. */\n sortTechniquesByLevel,\n /** Group techniques by level (Map, each group sorted by technique number). */\n groupTechniquesByLevel,\n /** Techniques of a strategy, sorted by technique number. */\n getTechniquesForStrategy,\n /** Find a strategy by its URL stub. */\n findStrategyByStub,\n /** Public slugs of all 60 techniques (footer / sitemap order). */\n TECHNIQUE_SLUGS,\n /** Stubs of the 17 strategies (difficulty order). */\n STRATEGY_SLUGS,\n /** Difficulty tier for a strategy's difficulty value. */\n getStrategyDifficultyTier,\n /** i18n key for a strategy's difficulty tier (e.g. 'strategy.expert'). */\n getStrategyDifficultyKey,\n /** Localized sections of a strategy from the strategies namespace. */\n getStrategySections,\n /** Localized overview, how-it-works steps and tips of a technique. */\n parseTechniqueContent,\n} from './utils';\n\n// ============================================================================\n// Technique Bitmask Utilities\n// ============================================================================\n\n/** Exact (bigint) technique bitmasks for boards, dailies and game meta. */\nexport {\n /** Exact bitmask of a board/daily/meta; never throws (falls back to 0n). */\n exactTechniqueBitmask,\n /** Exact bitmask as the base-10 string API requests take. */\n techniqueBitmaskString,\n /** The techniques / techniques_bitmask pair to store on game meta. */\n techniqueFieldsOf,\n} from './utils';\n\n// ============================================================================\n// Technique Walkthrough Utilities\n// ============================================================================\n\n/** A single step in a technique walkthrough (board + hint overlay + text). */\nexport type { WalkthroughStep } from './utils';\n\n/** Shared logic for building step-by-step technique examples from practice data. */\nexport {\n /** Parse a comma-delimited pencilmarks string into per-cell arrays. */\n parsePencilmarksString,\n /** Convert per-cell pencilmarks arrays back to a comma-delimited string. */\n pencilmarksToString,\n /** Parse board/pencilmarks/solution strings into a SudokuCell array. */\n parsePracticeBoard,\n /** Deep clone a SudokuCell array. */\n cloneSudokuBoard,\n /** Apply a hint step's actions to a board, returning new state. */\n applyHintStep,\n /** Parse a hint_data JSON string into SolverHints. */\n parseHintData,\n /** Resolve localised title and text for a single hint step. */\n localizeHintStep,\n /** Build the full walkthrough step array from board and hint data. */\n buildWalkthroughSteps,\n} from './utils';\n\n// ============================================================================\n// Hint Explanation Utilities\n// ============================================================================\n\n/** Hint explanation generation utilities for teaching users solving techniques. */\nexport {\n /** Generate a detailed explanation for a hint step based on the technique. */\n generateDetailedExplanation,\n /** Get a short action summary for a hint step (e.g., 'Place 5 in R1C3'). */\n getHintActionSummary,\n} from './utils';\n\n// ============================================================================\n// Localized Hint Utilities\n// ============================================================================\n\n/** Types for hint text localization. */\nexport type {\n /** Translation function compatible with i18next's `t` function. */\n TranslateFunction,\n /** Nested heading tree (the `headings` object of hints.json). */\n HintHeadingTree,\n /** Text/title/heading resolvers returned by createLocalizedHintHelpers. */\n LocalizedHintHelpers,\n} from './utils';\n\n/** Hint localization utilities. */\nexport {\n /** Get localized text for a hint step using a translation function. */\n getLocalizedHintText,\n /** Get localized title for a hint step using a translation function. */\n getLocalizedHintTitle,\n /** Resolve a localized API field, falling back to the raw value. */\n localizedField,\n /** Key prefix of the per-step heading tree ('headings.'). */\n HINT_HEADING_KEY_PREFIX,\n /** Heading localization (headings.<path>) for a hint step, or undefined. */\n getStepHeadingLocalization,\n /** Translated heading for a hint step, or ''. */\n getLocalizedHintHeading,\n /** Fill {{valueN}} placeholders from a values array. */\n interpolateHintValues,\n /** Heading for a hint step looked up in a heading tree (no i18n library). */\n getStepHeadingFromTree,\n /** Build the text/title/heading resolvers behind the apps' useLocalizedHint. */\n createLocalizedHintHelpers,\n} from './utils';\n\n// ============================================================================\n// Entity Translation Utilities\n// ============================================================================\n\n/** Shapes the entity display helpers read. */\nexport type {\n /** Level fields used by getLevelDisplayTitle / getLevelDisplayText. */\n LevelDisplaySource,\n /** Technique fields used by getTechniqueDisplayTitle. */\n TechniqueDisplaySource,\n /** Strategy fields used by getStrategyDisplayTitle. */\n StrategyDisplaySource,\n} from './utils';\n\n/** Translation of API entities (levels, techniques, belts). */\nexport {\n /** Route prefixed entity keys (levels.*, techniques.*) to their namespaces. */\n createNamespacedTranslate,\n /** Display title of a level (localization, levels namespace, raw title). */\n getLevelDisplayTitle,\n /** Display description of a level (localization, levels namespace, raw text). */\n getLevelDisplayText,\n /** Display title of a technique (localization, techniques namespace, raw title). */\n getTechniqueDisplayTitle,\n /** Localized belt name for a level ('belts' namespace `${level}.name`). */\n getBeltDisplayName,\n /** Localized belt label for a level ('belts' namespace `${level}.label`). */\n getBeltDisplayLabel,\n /** Display title of a strategy (localization, strategies namespace, raw title, stub). */\n getStrategyDisplayTitle,\n} from './utils';\n\n// ============================================================================\n// i18n Key Utilities\n// ============================================================================\n\n/** Internationalization key generation and localization utilities. */\nexport {\n /** Get i18n key for a belt name (e.g., 'belts.1.name'). */\n getBeltKey,\n /** Get localized belt name using a translation function. */\n getLocalizedBeltName,\n /** Get i18n key for a belt label (e.g., 'belts.1.label'). */\n getBeltLabelKey,\n /** Get localized belt label (e.g., 'White Belt'). */\n getLocalizedBeltLabel,\n /** Get i18n key for a level title (e.g., 'levels.3'). */\n getLevelKey,\n /** Get localized level title using a translation function. */\n getLocalizedLevelTitle,\n /** Get i18n key for a technique name (e.g., 'techniques.full-house.title'). */\n getTechniqueKey,\n /** Get localized technique name using a translation function. */\n getLocalizedTechniqueName,\n} from './utils';\n\n// ============================================================================\n// Digit Display Utilities\n// ============================================================================\n\n/** Digit display format conversion. */\nexport {\n /** Convert a digit (1-9) to its display string based on the format (numeric, kanji, emojis). */\n displayDigit,\n} from './utils';\n\n// ============================================================================\n// Scanned Board (OCR) Utilities\n// ============================================================================\n\n/** A board read from an image, and the error a scan can fail with. */\nexport type { ScannedBoard, ScanBoardErrorCode } from './utils';\n\nexport {\n /** Fewest givens a scanned board needs (17). */\n MIN_SCAN_CLUES,\n /** Error thrown by scannedBoardFromResponse / useBoardScan, with a `code`. */\n ScanBoardError,\n /** Normalize an OCR API result into givens, player digits and pencilmarks. */\n toScannedBoard,\n /** Whether a scanned board carries any player digits. */\n hasScannedInput,\n /** Turn the OCR endpoint's response into a ScannedBoard (or throw why not). */\n scannedBoardFromResponse,\n} from './utils';\n\n// ============================================================================\n// Share URL Utilities\n// ============================================================================\n\n/** Types for share URL building and parsing. */\nexport type {\n /** Options for buildShareUrl. */\n ShareUrlParams,\n /** Game state parsed from a puzzle share URL. */\n ParsedShareParams,\n /** What a share URL points at ('daily' | 'puzzle' | 'technique' | ...). */\n ShareUrlType,\n /** URLSearchParams or a plain object of route params. */\n ShareParamsSource,\n} from './utils';\n\n/** Build a share URL from game state. */\nexport { buildShareUrl } from './utils';\n\n/** Parse share URL query parameters into game state. */\nexport { parseShareParams } from './utils';\n\n/** Derive web app URL from API base URL. */\nexport { getWebUrl } from './utils';\n\n// ============================================================================\n// Auth Utilities\n// ============================================================================\n\n/** Minimal user shape for auth checks. */\nexport type { AuthUser } from './utils';\n\n/** Check if user-specific API calls should be enabled (non-anonymous, has token). */\nexport { isAuthenticatedUser } from './utils';\n\n/** Whether a user is a real (signed-in, non-anonymous) account. */\nexport { isRealUser } from './utils';\n\n// ============================================================================\n// Language Utilities\n// ============================================================================\n\n/** Types for supported languages. */\nexport type {\n /** A supported language (code, native name, flag). */\n SupportedLanguageInfo,\n /** A supported language code (lowercase, e.g. 'zh-hant'). */\n SupportedLanguageCode,\n} from './utils';\n\n/** Supported languages, locale resolution and language storage keys. */\nexport {\n /** The 15 supported UI languages. */\n SUPPORTED_LANGUAGES,\n /** Codes of the supported languages. */\n SUPPORTED_LANGUAGE_CODES,\n /** Fallback language ('en'). */\n DEFAULT_LANGUAGE,\n /** Web localStorage key for the language preference ('language'). */\n LANGUAGE_STORAGE_KEY,\n /** RN AsyncStorage key for the language preference ('@sudojo/language'). */\n NATIVE_LANGUAGE_STORAGE_KEY,\n /** Whether a code is a supported language code. */\n isSupportedLanguage,\n /** Map a code or locale tag to a supported code (zh-TW/HK -> zh-hant), or null. */\n normalizeLanguageCode,\n /** Supported language for a locale tag, defaulting to 'en'. */\n resolveLanguage,\n /** BCP 47 casing of a code ('zh-hant' -> 'zh-Hant'). */\n toLanguageTag,\n /** Native name of a language, or undefined. */\n getLanguageNativeName,\n} from './utils';\n\n// ============================================================================\n// Community Utilities\n// ============================================================================\n\n/** A known community platform (id, label key, English label). */\nexport type { CommunityPlatformInfo } from './utils';\n\n/** Community platform order and labels. */\nexport {\n /** Known community platforms in display order. */\n COMMUNITY_PLATFORMS,\n /** Info for a platform id (case-insensitive), or undefined. */\n getCommunityPlatform,\n /** Sort platform ids into display order (unknown last). */\n sortCommunityPlatforms,\n} from './utils';\n\n// ============================================================================\n// Gamification Utilities\n// ============================================================================\n\n/** Types for badge progress. */\nexport type {\n /** Badge definitions split into level/game lists with an earned lookup. */\n BadgeProgress,\n /** Badge definition fields groupBadgeProgress reads. */\n BadgeDefinitionLike,\n} from './utils';\n\n/** Badge grouping for profile and statistics screens. */\nexport {\n /** badgeType of level mastery badges ('level_mastery'). */\n LEVEL_MASTERY_BADGE_TYPE,\n /** badgeType of games-played badges ('games_played'). */\n GAMES_PLAYED_BADGE_TYPE,\n /** Split badge definitions into sorted level/game lists with isEarned. */\n groupBadgeProgress,\n} from './utils';\n\n// ============================================================================\n// Hint Access Utilities\n// ============================================================================\n\n/** Types for the hint access panel. */\nexport type {\n /** What the hint access panel's button does. */\n HintAccessAction,\n /** Which message the hint access panel shows. */\n HintAccessVariant,\n /** Action and message variant for a hint access state. */\n HintAccessPresentation,\n} from './utils';\n\n/** Client-side hint gating helpers. */\nexport {\n /** Hint steps visible without the level's entitlement (2). */\n FREE_HINT_STEP_LIMIT,\n /** Map a hint access state to the panel's action and message variant. */\n getHintAccessAction,\n /** i18n key suffixes for the hint access messages. */\n HINT_ACCESS_KEY_SUFFIXES,\n} from './utils';\n\n// ============================================================================\n// Daily Date Utilities\n// ============================================================================\n\n/** Calendar-date helpers for daily puzzles (UTC \"today\", like the API). */\nexport {\n /** UTC date of a Date (default now) as YYYY-MM-DD. */\n getUtcDateString,\n /** Normalize a daily date to YYYY-MM-DD without a timezone shift, or null. */\n normalizeDailyDate,\n /** Format a YYYY-MM-DD daily date as a local calendar date. */\n formatDailyDate,\n /** Whether a saved daily is not today's (UTC) daily. */\n isStaleDaily,\n} from './utils';\n\n// ============================================================================\n// Game Fetch Status Utilities\n// ============================================================================\n\n/** Response shape (with the legacy action field) read by getGameFetchStatus. */\nexport type { GameFetchResponse } from './utils';\n\n/** Status derivation shared by useLevelGame and useDailyGame. */\nexport {\n /** Whether a response/error says sign-in is required (legacy API signal). */\n isAuthRequiredResponse,\n /** Whether a response/error says a subscription is required (legacy API signal). */\n isSubscriptionRequiredResponse,\n /** Derive a GameFetchStatus from query state. */\n getGameFetchStatus,\n /** HTTP status carried by an error (NetworkError.status), or undefined. */\n getErrorHttpStatus,\n /** Derive a PracticeFetchStatus (401/402 aware) from query state. */\n getPracticeFetchStatus,\n} from './utils';\n\n/** Status of a practice fetch ('loading' | 'ready' | 'auth_required' | 'subscription_required' | 'no_practices' | 'error'). */\nexport type { PracticeFetchStatus } from './utils';\n\n// ============================================================================\n// Technique Example Utilities\n// ============================================================================\n\n/** Types for technique example walkthroughs. */\nexport type {\n /** Stored example/practice fields a walkthrough is built from. */\n TechniqueExampleSource,\n /** Translation functions (hints, techniques, default namespaces). */\n TechniqueWalkthroughTranslations,\n /** Walkthrough cards and their headings. */\n TechniqueWalkthrough,\n} from './utils';\n\n/** Build walkthrough cards and headings for a stored technique example. */\nexport { buildTechniqueWalkthrough } from './utils';\n\n// ============================================================================\n// Hooks\n// ============================================================================\n\nexport {\n // Data hooks\n /** Fetch a single difficulty level by number. */\n useLevel,\n /** Fetch all difficulty levels with sorting and filtering utilities. */\n useLevels,\n /** Fetch a single solving technique by number. */\n useTechnique,\n /** Fetch all solving techniques with grouping utilities. */\n useTechniques,\n /** Fetch communities for a specific language with platform grouping. */\n useCommunities,\n /** Fetch learning materials with filtering by technique and language. */\n useLearning,\n /** Fetch a single learning item by UUID. */\n useLearningItem,\n\n /**\n * @deprecated Use `useSudoku` instead. `useGame` uses a legacy 2D array board\n * representation, while `useSudoku` uses a flat 81-cell array consistent with\n * the Kotlin renderable layer and the rest of the codebase.\n */\n useGame,\n\n /** Primary game state hook with flat 81-cell board, pencil mode, and scrambling. */\n useSudoku,\n\n /** Teaching/hint integration with the solver API (legacy GameHint format). */\n useGameTeaching,\n\n /** Fetch a random board for a specific level with auth/subscription handling. */\n useLevelGame,\n /** Fetch today's daily puzzle with auth/subscription handling. */\n useDailyGame,\n\n /** Game timer using refs to avoid re-renders every second. */\n useGameTimer,\n\n /** Persist individual game progress to localStorage. */\n useGamePersistence,\n /** Auto-save game state with debouncing. */\n useAutoSave,\n\n /** Generic typed localStorage hook with SSR safety. */\n useLocalStorage,\n\n /** Solver hint integration matching Kotlin HintInteractor behavior. */\n useHint,\n\n /** Current game management with Zustand store (daily/play slots). */\n useGamePlay,\n\n /** Shared \"Continue Last Sudoku\" logic for web and RN. */\n useContinueGame,\n\n /** Manual puzzle entry mode with solver validation. */\n useBoardEntry,\n\n /** Scan a board from an image: givens, player digits and pencilmarks. */\n useBoardScan,\n\n /** Server-side game session management for gamification (points, badges). */\n useGameSession,\n\n /** Check whether a level is enabled for the current user's entitlements. */\n useLevelEnabled,\n /** Check whether a technique is enabled for the current user's entitlements. */\n useTechniqueEnabled,\n\n /** Convert internal user level (0-indexed) to display values (1-indexed + belt). */\n useDisplayLevel,\n\n /** Compute cumulative puzzle distribution across entitlement tiers. */\n usePuzzleDistribution,\n\n /** Shared hint step tracker for game screens (ref + state). */\n useHintStepTracker,\n\n /** Auto-hint orchestration for shared links/deep links. */\n useAutoHint,\n\n /** Progress reporting for game state persistence. */\n useProgressReporter,\n\n /** Regenerate hint_data for all stored practices via solver. */\n useRegeneratePracticeHints,\n\n /** Emit a hint action event to the active SudokuGame. */\n emitHintAction,\n /** Report hint status back after processing an action. */\n reportHintStatus,\n /** Subscribe to hint status updates. */\n onHintStatus,\n /** Hook for SudokuGame to listen for external hint action events. */\n useHintActionListener,\n\n /** Fire a callback once each time a puzzle becomes completed (re-arms on false). */\n useCompletionTrigger,\n /** Fetch strategies (unwrapped) with findStrategyByStub. */\n useStrategies,\n /** Fetch a random practice for a technique with auth/subscription/empty status. */\n usePracticeGame,\n /** Whether the user is a real (non-anonymous) account. */\n useIsRealUser,\n /** Whether the signed-in user is a site admin (GET /users/:uid siteAdmin). */\n useIsSiteAdmin,\n /** Look up a technique by path or alias (list first, then GET by path). */\n useTechniqueByPath,\n /** Fetch a technique's worked example and build its walkthrough. */\n useTechniqueExample,\n /** Build (memoized) the walkthrough for a stored technique example. */\n useTechniqueWalkthrough,\n /** Player's puzzle progress in localStorage (markCompleted, isCompleted, stats). */\n usePuzzleProgress,\n /** Account deletion rule and delete-then-sign-out sequence. */\n useDeleteAccount,\n /** Saved game to resume for a play screen (snapshot; clears stale dailies). */\n useResumeGame,\n /** The saved game a play screen should resume, or null (pure). */\n getResumeGame,\n /** Daily/Level play screen orchestration (resume, save, session, completion). */\n usePuzzleSession,\n /** Entered-puzzle save/resume after validation (no server session). */\n useEnteredGameSession,\n} from './hooks';\n\nexport type {\n // Data hook types\n /** Options for useLevel hook. */\n UseLevelOptions,\n /** Result type for useLevel hook. */\n UseLevelResult,\n /** Options for useLevels hook. */\n UseLevelsOptions,\n /** Result type for useLevels hook. */\n UseLevelsResult,\n /** Options for useTechnique hook. */\n UseTechniqueOptions,\n /** Result type for useTechnique hook. */\n UseTechniqueResult,\n /** Options for useTechniques hook. */\n UseTechniquesOptions,\n /** Result type for useTechniques hook. */\n UseTechniquesResult,\n /** Options for useCommunities hook. */\n UseCommunitiesOptions,\n /** Result type for useCommunities hook. */\n UseCommunitiesResult,\n /** Options for useLearningItem hook. */\n UseLearningItemOptions,\n /** Result type for useLearningItem hook. */\n UseLearningItemResult,\n /** Options for useLearning hook. */\n UseLearningOptions,\n /** Result type for useLearning hook. */\n UseLearningResult,\n\n // Game hook types (legacy)\n /** @deprecated Options for legacy useGame hook. Use UseSudokuOptions instead. */\n UseGameOptions,\n /** @deprecated Result type for legacy useGame hook. Use UseSudokuResult instead. */\n UseGameResult,\n\n // Sudoku hook types\n /** Options for useSudoku hook (initial app settings). */\n UseSudokuOptions,\n /** Result type for useSudoku hook (state, computed values, actions, utilities). */\n UseSudokuResult,\n\n // Teaching hook types\n /** Options for useGameTeaching hook (network client, URL, token). */\n UseGameTeachingOptions,\n /** Result type for useGameTeaching hook (teaching state, hint actions). */\n UseGameTeachingResult,\n\n // Game fetching hook types\n /** Options for useLevelGame hook (network, auth, level number). */\n UseLevelGameOptions,\n /** Result type for useLevelGame hook (board data, fetch status). */\n UseLevelGameResult,\n /** Options for useDailyGame hook (network, auth). */\n UseDailyGameOptions,\n /** Result type for useDailyGame hook (daily data, fetch status). */\n UseDailyGameResult,\n /** Status of a game fetch: 'loading' | 'success' | 'auth_required' | 'subscription_required' | 'entitlement_required' | 'error'. */\n GameFetchStatus,\n\n // Timer hook types\n /** Options for useGameTimer hook (autoStart, initialTime). */\n UseGameTimerOptions,\n /** Result type for useGameTimer hook (elapsedRef, controls). */\n UseGameTimerResult,\n\n // Persistence hook types\n /** Options for useGamePersistence hook (puzzleKey, autoSave). */\n UseGamePersistenceOptions,\n /** Result type for useGamePersistence hook (load, save, clear, hasSaved). */\n UseGamePersistenceResult,\n\n // Hint hook types\n /** Options for useHint hook (network, puzzle state, technique filter). */\n UseHintOptions,\n /** Result type for useHint hook (hint steps, navigation, apply). */\n UseHintResult,\n /** Board data returned when applying a hint (user input, pencilmarks). */\n HintBoardData,\n /** Data passed to onHintReceived callback (hint, board data, technique info). */\n HintReceivedData,\n /** Access denied error info when hint level exceeds subscription tier. */\n HintAccessError,\n\n // Game play hook types\n /** Options for useGamePlay hook (slot selection, auto-save delay). */\n UseGamePlayOptions,\n /** Result type for useGamePlay hook (current game, start, update, clear). */\n UseGamePlayResult,\n\n // Continue game hook types\n /** Options for useContinueGame hook. */\n UseContinueGameOptions,\n /** Result type for useContinueGame hook. */\n UseContinueGameResult,\n /** Navigation target returned by useContinueGame. */\n ContinueTarget,\n\n // Board entry hook types\n /** Options for useBoardEntry hook (network client, URL, token). */\n UseBoardEntryOptions,\n /** Result type for useBoardEntry hook (cells, validation, actions). */\n UseBoardEntryReturn,\n /** Validated puzzle data from solver (puzzle + solution strings). */\n ValidatedPuzzle,\n\n // Board scan hook types\n /** Options for useBoardScan hook (network client, URL). */\n UseBoardScanOptions,\n /** Result type for useBoardScan hook (scan, isScanning). */\n UseBoardScanReturn,\n\n // Game session hook types\n /** Options for useGameSession hook (network, auth, userId). */\n UseGameSessionOptions,\n /** Result of starting a game session (sessionStarted, sessionId). */\n GameSessionResult,\n /** Result of finishing a game session (leveledUp, badges, points). */\n GameFinishResult,\n\n // Display level hook types\n /** Result type for useDisplayLevel hook. */\n UseDisplayLevelResult,\n\n // Hint step tracker types\n /** Result type for useHintStepTracker hook. */\n UseHintStepTrackerResult,\n\n // Auto-hint types\n /** Options for useAutoHint hook. */\n UseAutoHintOptions,\n\n // Practice admin types\n UseRegeneratePracticeHintsOptions,\n UseRegeneratePracticeHintsResult,\n\n // Progress reporter types\n /** Options for useProgressReporter hook. */\n UseProgressReporterOptions,\n /** Callback type for progress updates. */\n ProgressUpdateCallback,\n\n // Hint action types\n /** Status reported after a hint action is processed. */\n HintActionStatus,\n\n // Board entry play state\n /** What a validated entered puzzle should apply (entry pencilmarks). */\n BoardEntryPlayState,\n\n // Strategies hook types\n /** Options for useStrategies hook. */\n UseStrategiesOptions,\n /** Result type for useStrategies hook. */\n UseStrategiesResult,\n\n // Practice game hook types\n /** Options for usePracticeGame hook. */\n UsePracticeGameOptions,\n /** Result type for usePracticeGame hook. */\n UsePracticeGameResult,\n\n // User status hook types\n /** Options for useIsSiteAdmin hook. */\n UseIsSiteAdminOptions,\n /** Result type for useIsSiteAdmin hook. */\n UseIsSiteAdminResult,\n\n // Technique lookup / example hook types\n /** Options for useTechniqueByPath hook. */\n UseTechniqueByPathOptions,\n /** Result type for useTechniqueByPath hook. */\n UseTechniqueByPathResult,\n /** Where a technique example comes from ('example' | 'practice'). */\n TechniqueExampleSourceKind,\n /** Options for useTechniqueExample hook. */\n UseTechniqueExampleOptions,\n /** Result type for useTechniqueExample hook. */\n UseTechniqueExampleResult,\n\n // Puzzle progress hook types\n /** Options for usePuzzleProgress hook. */\n UsePuzzleProgressOptions,\n /** Result type for usePuzzleProgress hook. */\n UsePuzzleProgressResult,\n\n // Account deletion hook types\n /** What deleteAccount did ('deleted' | 'blocked' | 'failed'). */\n DeleteAccountOutcome,\n /** Provider tokens for account deletion (Google/Apple revocation). */\n DeleteAccountProviderTokens,\n /** Options for useDeleteAccount hook. */\n UseDeleteAccountOptions,\n /** Result type for useDeleteAccount hook. */\n UseDeleteAccountResult,\n\n // Play session hook types\n /** Play screen kind ('daily' | 'level'). */\n PuzzleSessionSource,\n /** Saved game kind useResumeGame can resume ('daily' | 'level' | 'entered'). */\n ResumeGameSource,\n /** Options for useEnteredGameSession hook. */\n UseEnteredGameSessionOptions,\n /** Result type for useEnteredGameSession hook. */\n UseEnteredGameSessionResult,\n /** Options for useResumeGame hook. */\n UseResumeGameOptions,\n /** Result type for useResumeGame hook. */\n UseResumeGameResult,\n /** The puzzle a play screen shows (fetched or resumed). */\n ActivePuzzle,\n /** Props for the game component from usePuzzleSession. */\n PuzzleGameProps,\n /** Fetched Daily/Board shape usePuzzleSession accepts. */\n SessionPuzzleInput,\n /** Options for usePuzzleSession hook. */\n UsePuzzleSessionOptions,\n /** Result type for usePuzzleSession hook. */\n UsePuzzleSessionResult,\n} from './hooks';\n\n// ============================================================================\n// Stores\n// ============================================================================\n\n/** Zustand store for current game state with daily/play slots and localStorage persistence. */\nexport { useGamePlayStore } from './stores/gamePlayStore';\n/** State shape for the game play Zustand store. */\nexport type { GamePlayState } from './stores/gamePlayStore';\n\n// ============================================================================\n// Config\n// ============================================================================\n\n/** Authentication provider configuration types. */\nexport type {\n /** Available auth provider types: 'google' | 'apple' | 'email'. */\n AuthProviderType,\n /** Configuration for which auth providers are enabled. */\n AuthProvidersConfig,\n} from './config';\n\n/** Default auth providers configuration (Google + Email, anonymous fallback). */\nexport { DEFAULT_AUTH_PROVIDERS } from './config';\n\n// ============================================================================\n// Entitlement Context\n// ============================================================================\n\n/** Provider that supplies entitlements to useLevelEnabled / useTechniqueEnabled. */\nexport { EntitlementProvider } from './context';\n/** React context for entitlements (for advanced use). */\nexport { EntitlementContext, useEntitlementContext } from './context';\n\n// ============================================================================\n// Sudojo API Context\n// ============================================================================\n\n/** Optional provider of networkClient/baseUrl/token for sudojo_lib hooks. */\nexport { SudojoApiProvider } from './context';\n/** API context, its hooks, and the option-over-context resolver. */\nexport {\n /** React context holding the API connection (for advanced use). */\n SudojoApiContext,\n /** The provider's API connection (throws without a provider). */\n useSudojoApi,\n /** The provider's API connection, or null. */\n useOptionalSudojoApi,\n /** Merge explicit options over a context value (pure; throws if incomplete). */\n resolveSudojoApi,\n /** Resolve a hook's API connection from options, then the provider. */\n useResolvedSudojoApi,\n} from './context';\n/** Types for the Sudojo API context. */\nexport type {\n /** The API connection the provider supplies. */\n SudojoApiValue,\n /** Optional networkClient/baseUrl/token fields of hook options. */\n SudojoApiOptions,\n /** An API connection with every field resolved (token '' when none). */\n ResolvedSudojoApi,\n} from './context';\n\n// ============================================================================\n// Entitlement Utilities (re-exported from sudojo_types)\n// ============================================================================\n\n/** Parse a comma-delimited entitlement string into an array. */\nexport { parseEntitlements } from '@sudobility/sudojo_types';\n\n/** Check if a user has the required entitlement for a level. */\nexport { hasRequiredEntitlement } from '@sudobility/sudojo_types';\n\n// ============================================================================\n// Admin (batch jobs + stats; see src/admin/index.ts for the full list)\n// ============================================================================\n\n/**\n * Admin module: board generation, technique extraction, example creation and\n * admin stats as hooks (`useBoardGenerator`, `useTechniqueExtractor`,\n * `useExampleCreator`, `useSingleBoardExtractor`, `useBoardTechniquesUpdater`,\n * `useAdminStats`), the framework-agnostic jobs behind them\n * (`runBoardGeneration`, `runTechniqueExtraction`, `runExampleCreation`) and\n * their pure rules (`mergeBoardWithUserInput`, `adjustPracticeSolution`,\n * `extractBoardTechniques`, `levelsToSearchForTechnique`, …). Network calls go\n * only through sudojo_client hooks (`useAdminApi`).\n */\nexport * from './admin';\n"]}
@@ -17,19 +17,25 @@ import type { BaseResponse } from '@sudobility/types';
17
17
  export declare const MIN_SCAN_CLUES = 17;
18
18
  /** A scanned board, normalized and ready to load into entry or play. */
19
19
  export interface ScannedBoard {
20
- /** The givens, 81 chars, '0' = empty. Goes into the entry grid. */
20
+ /**
21
+ * The board to enter and validate: the printed givens with the player's
22
+ * digits merged in (81 chars, '0' = empty). Goes into the entry grid as
23
+ * givens: the photo need not be a game in progress, and entry/validate only
24
+ * knows givens.
25
+ */
26
+ puzzle: string;
27
+ /** The printed givens as read, 81 chars, '0' = empty (diagnostics). */
21
28
  original: string;
22
29
  /**
23
- * Digits the player had entered, 81 chars, '0' = no input. Given cells are
24
- * always '0', the same shape as the game's input string, so it can be passed
25
- * straight to `initialInput` / `applyHintData`.
30
+ * Digits the player had entered, 81 chars, '0' = no input; given cells are
31
+ * always '0' (diagnostics; already merged into `puzzle`).
26
32
  */
27
33
  user: string;
28
34
  /** 81 comma-separated pencilmark entries (e.g. "126"), or '' when none. */
29
35
  pencilmarks: string;
30
36
  /** Whether the pencilmarks were auto-filled in the scanned game. */
31
37
  autopencil: boolean;
32
- /** Number of givens in `original`. */
38
+ /** Number of givens in `puzzle` (the merged board that will be validated). */
33
39
  clueCount: number;
34
40
  /** OCR confidence, 0-100. */
35
41
  confidence: number;
@@ -63,7 +69,10 @@ export declare class ScanBoardError extends Error {
63
69
  * @throws ScanBoardError `INVALID_BOARD` when `original` is not 81 digits
64
70
  */
65
71
  export declare function toScannedBoard(data: OCRExtractData | null | undefined): ScannedBoard;
66
- /** Whether the scan recorded any player digits. */
72
+ /**
73
+ * Whether the scan recorded any player digits. Informational only: the digits
74
+ * are already merged into `puzzle`, so nothing needs restoring.
75
+ */
67
76
  export declare function hasScannedInput(board: ScannedBoard): boolean;
68
77
  /**
69
78
  * Turn the OCR endpoint's response into a playable ScannedBoard.
@@ -1 +1 @@
1
- {"version":3,"file":"scannedBoard.d.ts","sourceRoot":"","sources":["../../src/utils/scannedBoard.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAE/D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEtD;;;;GAIG;AACH,eAAO,MAAM,cAAc,KAAY,CAAC;AAIxC,wEAAwE;AACxE,MAAM,WAAW,YAAY;IAC3B,mEAAmE;IACnE,QAAQ,EAAE,MAAM,CAAC;IACjB;;;;OAIG;IACH,IAAI,EAAE,MAAM,CAAC;IACb,2EAA2E;IAC3E,WAAW,EAAE,MAAM,CAAC;IACpB,oEAAoE;IACpE,UAAU,EAAE,OAAO,CAAC;IACpB,sCAAsC;IACtC,SAAS,EAAE,MAAM,CAAC;IAClB,6BAA6B;IAC7B,UAAU,EAAE,MAAM,CAAC;IACnB,uDAAuD;IACvD,MAAM,CAAC,EAAE,cAAc,CAAC,QAAQ,CAAC,CAAC;CACnC;AAED,MAAM,MAAM,kBAAkB;AAC5B,uDAAuD;AACrD,gBAAgB;AAClB,uDAAuD;GACrD,eAAe;AACjB,sDAAsD;GACpD,eAAe,CAAC;AAEpB,qBAAa,cAAe,SAAQ,KAAK;IACvC,QAAQ,CAAC,IAAI,EAAE,kBAAkB,CAAC;IAClC,qEAAqE;IACrE,QAAQ,CAAC,KAAK,CAAC,EAAE,YAAY,CAAC;gBAG5B,IAAI,EAAE,kBAAkB,EACxB,OAAO,EAAE,MAAM,EACf,OAAO,GAAE;QAAE,KAAK,CAAC,EAAE,YAAY,CAAC;QAAC,KAAK,CAAC,EAAE,OAAO,CAAA;KAAO;CAU1D;AAED;;;;;;;;;GASG;AACH,wBAAgB,cAAc,CAC5B,IAAI,EAAE,cAAc,GAAG,IAAI,GAAG,SAAS,GACtC,YAAY,CAyCd;AAED,mDAAmD;AACnD,wBAAgB,eAAe,CAAC,KAAK,EAAE,YAAY,GAAG,OAAO,CAE5D;AAED;;;;;;;;;GASG;AACH,wBAAgB,wBAAwB,CACtC,QAAQ,EAAE,YAAY,CAAC,cAAc,CAAC,GACrC,YAAY,CAiBd"}
1
+ {"version":3,"file":"scannedBoard.d.ts","sourceRoot":"","sources":["../../src/utils/scannedBoard.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAE/D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEtD;;;;GAIG;AACH,eAAO,MAAM,cAAc,KAAY,CAAC;AAIxC,wEAAwE;AACxE,MAAM,WAAW,YAAY;IAC3B;;;;;OAKG;IACH,MAAM,EAAE,MAAM,CAAC;IACf,uEAAuE;IACvE,QAAQ,EAAE,MAAM,CAAC;IACjB;;;OAGG;IACH,IAAI,EAAE,MAAM,CAAC;IACb,2EAA2E;IAC3E,WAAW,EAAE,MAAM,CAAC;IACpB,oEAAoE;IACpE,UAAU,EAAE,OAAO,CAAC;IACpB,8EAA8E;IAC9E,SAAS,EAAE,MAAM,CAAC;IAClB,6BAA6B;IAC7B,UAAU,EAAE,MAAM,CAAC;IACnB,uDAAuD;IACvD,MAAM,CAAC,EAAE,cAAc,CAAC,QAAQ,CAAC,CAAC;CACnC;AAED,MAAM,MAAM,kBAAkB;AAC5B,uDAAuD;AACrD,gBAAgB;AAClB,uDAAuD;GACrD,eAAe;AACjB,sDAAsD;GACpD,eAAe,CAAC;AAEpB,qBAAa,cAAe,SAAQ,KAAK;IACvC,QAAQ,CAAC,IAAI,EAAE,kBAAkB,CAAC;IAClC,qEAAqE;IACrE,QAAQ,CAAC,KAAK,CAAC,EAAE,YAAY,CAAC;gBAG5B,IAAI,EAAE,kBAAkB,EACxB,OAAO,EAAE,MAAM,EACf,OAAO,GAAE;QAAE,KAAK,CAAC,EAAE,YAAY,CAAC;QAAC,KAAK,CAAC,EAAE,OAAO,CAAA;KAAO;CAU1D;AAED;;;;;;;;;GASG;AACH,wBAAgB,cAAc,CAC5B,IAAI,EAAE,cAAc,GAAG,IAAI,GAAG,SAAS,GACtC,YAAY,CA8Cd;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,YAAY,GAAG,OAAO,CAE5D;AAED;;;;;;;;;GASG;AACH,wBAAgB,wBAAwB,CACtC,QAAQ,EAAE,YAAY,CAAC,cAAc,CAAC,GACrC,YAAY,CAiBd"}
@@ -57,19 +57,24 @@ export function toScannedBoard(data) {
57
57
  pencilmarks = cleaned.join(',');
58
58
  }
59
59
  }
60
+ const puzzle = Array.from(original, (ch, i) => ch !== '0' ? ch : (user[i] ?? '0')).join('');
60
61
  const result = {
62
+ puzzle,
61
63
  original,
62
64
  user,
63
65
  pencilmarks,
64
66
  autopencil: pencilmarks !== '' && board.pencilmark?.autopencil === true,
65
- clueCount: original.replace(/0/g, '').length,
67
+ clueCount: puzzle.replace(/0/g, '').length,
66
68
  confidence: data?.confidence ?? 0,
67
69
  };
68
70
  if (data?.engine)
69
71
  result.engine = data.engine;
70
72
  return result;
71
73
  }
72
- /** Whether the scan recorded any player digits. */
74
+ /**
75
+ * Whether the scan recorded any player digits. Informational only: the digits
76
+ * are already merged into `puzzle`, so nothing needs restoring.
77
+ */
73
78
  export function hasScannedInput(board) {
74
79
  return /[1-9]/.test(board.user);
75
80
  }
@@ -1 +1 @@
1
- {"version":3,"file":"scannedBoard.js","sourceRoot":"","sources":["../../src/utils/scannedBoard.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AAGrD;;;;GAIG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,SAAS,CAAC;AAExC,MAAM,aAAa,GAAG,aAAa,CAAC;AAgCpC,MAAM,OAAO,cAAe,SAAQ,KAAK;IAKvC,YACE,IAAwB,EACxB,OAAe,EACf,UAAqD,EAAE;QAEvD,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,gBAAgB,CAAC;QAC7B,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,OAAO,CAAC,KAAK;YAAE,IAAI,CAAC,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC;QAC9C,IAAI,OAAO,CAAC,KAAK,KAAK,SAAS,EAAE,CAAC;YAC/B,IAA4B,CAAC,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC;QACtD,CAAC;IACH,CAAC;CACF;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,cAAc,CAC5B,IAAuC;IAEvC,MAAM,KAAK,GAAG,IAAI,EAAE,KAAK,CAAC;IAC1B,MAAM,QAAQ,GAAG,KAAK,EAAE,QAAQ,CAAC;IACjC,IAAI,CAAC,QAAQ,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC/C,MAAM,IAAI,cAAc,CACtB,eAAe,EACf,qCAAqC,CACtC,CAAC;IACJ,CAAC;IAED,MAAM,OAAO,GACX,KAAK,CAAC,IAAI,IAAI,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;IACnE,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAC/C,OAAO,IAAI,QAAQ,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAClD,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAEX,MAAM,OAAO,GAAG,KAAK,CAAC,UAAU,EAAE,OAAO,EAAE,KAAK,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC;IAC5D,IAAI,WAAW,GAAG,EAAE,CAAC;IACrB,IAAI,OAAO,CAAC,MAAM,KAAK,EAAE,EAAE,CAAC;QAC1B,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,CAAC,EAAE,EAAE,CACvC,QAAQ,CAAC,CAAC,CAAC,KAAK,GAAG,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,GAAG;YACpC,CAAC,CAAC,EAAE;YACJ,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC,CAAC;iBAC9C,IAAI,EAAE;iBACN,IAAI,CAAC,EAAE,CAAC,CAChB,CAAC;QACF,IAAI,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,KAAK,EAAE,CAAC,EAAE,CAAC;YACxC,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAClC,CAAC;IACH,CAAC;IAED,MAAM,MAAM,GAAiB;QAC3B,QAAQ;QACR,IAAI;QACJ,WAAW;QACX,UAAU,EAAE,WAAW,KAAK,EAAE,IAAI,KAAK,CAAC,UAAU,EAAE,UAAU,KAAK,IAAI;QACvE,SAAS,EAAE,QAAQ,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,MAAM;QAC5C,UAAU,EAAE,IAAI,EAAE,UAAU,IAAI,CAAC;KAClC,CAAC;IACF,IAAI,IAAI,EAAE,MAAM;QAAE,MAAM,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;IAC9C,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,mDAAmD;AACnD,MAAM,UAAU,eAAe,CAAC,KAAmB;IACjD,OAAO,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;AAClC,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,wBAAwB,CACtC,QAAsC;IAEtC,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC;QACtB,MAAM,IAAI,cAAc,CACtB,gBAAgB,EAChB,QAAQ,CAAC,KAAK,IAAI,oBAAoB,CACvC,CAAC;IACJ,CAAC;IAED,MAAM,KAAK,GAAG,cAAc,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;IAC5C,IAAI,KAAK,CAAC,SAAS,GAAG,cAAc,EAAE,CAAC;QACrC,MAAM,IAAI,cAAc,CACtB,eAAe,EACf,2BAA2B,KAAK,CAAC,SAAS,IAAI,cAAc,WAAW,EACvE,EAAE,KAAK,EAAE,CACV,CAAC;IACJ,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC","sourcesContent":["/**\n * Scanned board - turn an OCR result from sudojo_api into game state.\n *\n * A photo of a game in progress shows three things: the puzzle's givens, the\n * digits a player had already entered (drawn in another color), and\n * pencilmarks. `POST /api/v1/ocr/extract` returns them as a SolverBoard\n * (`original`, `user`, `pencilmark`). Every client that scans a board goes\n * through here, so they all keep the same parts of it.\n */\n\nimport type { OCRExtractData } from '@sudobility/sudojo_types';\nimport { MIN_CLUES } from '@sudobility/sudojo_types';\nimport type { BaseResponse } from '@sudobility/types';\n\n/**\n * Fewest givens a scanned board needs: MIN_CLUES (17) from sudojo_types, the\n * fewest a Sudoku can have and still be solvable to a unique answer. Kept as an\n * alias so existing imports keep working.\n */\nexport const MIN_SCAN_CLUES = MIN_CLUES;\n\nconst BOARD_PATTERN = /^[0-9]{81}$/;\n\n/** A scanned board, normalized and ready to load into entry or play. */\nexport interface ScannedBoard {\n /** The givens, 81 chars, '0' = empty. Goes into the entry grid. */\n original: string;\n /**\n * Digits the player had entered, 81 chars, '0' = no input. Given cells are\n * always '0', the same shape as the game's input string, so it can be passed\n * straight to `initialInput` / `applyHintData`.\n */\n user: string;\n /** 81 comma-separated pencilmark entries (e.g. \"126\"), or '' when none. */\n pencilmarks: string;\n /** Whether the pencilmarks were auto-filled in the scanned game. */\n autopencil: boolean;\n /** Number of givens in `original`. */\n clueCount: number;\n /** OCR confidence, 0-100. */\n confidence: number;\n /** Which backend read the image, when the API says. */\n engine?: OCRExtractData['engine'];\n}\n\nexport type ScanBoardErrorCode =\n /** The request failed or the API reported an error. */\n | 'REQUEST_FAILED'\n /** The API answered without a usable 81-cell board. */\n | 'INVALID_BOARD'\n /** The board has fewer than MIN_SCAN_CLUES givens. */\n | 'TOO_FEW_CLUES';\n\nexport class ScanBoardError extends Error {\n readonly code: ScanBoardErrorCode;\n /** The board as read, when there was one (set for TOO_FEW_CLUES). */\n readonly board?: ScannedBoard;\n\n constructor(\n code: ScanBoardErrorCode,\n message: string,\n options: { board?: ScannedBoard; cause?: unknown } = {}\n ) {\n super(message);\n this.name = 'ScanBoardError';\n this.code = code;\n if (options.board) this.board = options.board;\n if (options.cause !== undefined) {\n (this as { cause?: unknown }).cause = options.cause;\n }\n }\n}\n\n/**\n * Normalize an OCR result into a ScannedBoard.\n *\n * - `user` keeps only the player's digits: given cells are blanked, so a given\n * can never be overwritten by a misread input digit.\n * - Pencilmarks are dropped from cells that hold a digit, and kept only when\n * there are 81 entries.\n *\n * @throws ScanBoardError `INVALID_BOARD` when `original` is not 81 digits\n */\nexport function toScannedBoard(\n data: OCRExtractData | null | undefined\n): ScannedBoard {\n const board = data?.board;\n const original = board?.original;\n if (!original || !BOARD_PATTERN.test(original)) {\n throw new ScanBoardError(\n 'INVALID_BOARD',\n 'OCR did not return an 81-cell board'\n );\n }\n\n const rawUser =\n board.user && BOARD_PATTERN.test(board.user) ? board.user : null;\n const user = Array.from({ length: 81 }, (_, i) =>\n rawUser && original[i] === '0' ? rawUser[i] : '0'\n ).join('');\n\n const entries = board.pencilmark?.numbers?.split(',') ?? [];\n let pencilmarks = '';\n if (entries.length === 81) {\n const cleaned = entries.map((entry, i) =>\n original[i] !== '0' || user[i] !== '0'\n ? ''\n : Array.from(new Set(entry.replace(/[^1-9]/g, '')))\n .sort()\n .join('')\n );\n if (cleaned.some(entry => entry !== '')) {\n pencilmarks = cleaned.join(',');\n }\n }\n\n const result: ScannedBoard = {\n original,\n user,\n pencilmarks,\n autopencil: pencilmarks !== '' && board.pencilmark?.autopencil === true,\n clueCount: original.replace(/0/g, '').length,\n confidence: data?.confidence ?? 0,\n };\n if (data?.engine) result.engine = data.engine;\n return result;\n}\n\n/** Whether the scan recorded any player digits. */\nexport function hasScannedInput(board: ScannedBoard): boolean {\n return /[1-9]/.test(board.user);\n}\n\n/**\n * Turn the OCR endpoint's response into a playable ScannedBoard.\n *\n * The request itself belongs to sudojo_client (`useSudojoOcrExtract`); this\n * only interprets what came back.\n *\n * @throws ScanBoardError `REQUEST_FAILED` when the API reported an error,\n * `INVALID_BOARD` when there is no 81-cell board, `TOO_FEW_CLUES` when the\n * board has fewer than MIN_SCAN_CLUES givens (the error carries the board)\n */\nexport function scannedBoardFromResponse(\n response: BaseResponse<OCRExtractData>\n): ScannedBoard {\n if (!response.success) {\n throw new ScanBoardError(\n 'REQUEST_FAILED',\n response.error || 'OCR request failed'\n );\n }\n\n const board = toScannedBoard(response.data);\n if (board.clueCount < MIN_SCAN_CLUES) {\n throw new ScanBoardError(\n 'TOO_FEW_CLUES',\n `Too few clues detected (${board.clueCount}/${MIN_SCAN_CLUES} minimum)`,\n { board }\n );\n }\n return board;\n}\n"]}
1
+ {"version":3,"file":"scannedBoard.js","sourceRoot":"","sources":["../../src/utils/scannedBoard.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Scanned board - turn an OCR result from sudojo_api into game state.\n *\n * A photo of a game in progress shows three things: the puzzle's givens, the\n * digits a player had already entered (drawn in another color), and\n * pencilmarks. `POST /api/v1/ocr/extract` returns them as a SolverBoard\n * (`original`, `user`, `pencilmark`). Every client that scans a board goes\n * through here, so they all keep the same parts of it.\n */\n\nimport type { OCRExtractData } from '@sudobility/sudojo_types';\nimport { MIN_CLUES } from '@sudobility/sudojo_types';\nimport type { BaseResponse } from '@sudobility/types';\n\n/**\n * Fewest givens a scanned board needs: MIN_CLUES (17) from sudojo_types, the\n * fewest a Sudoku can have and still be solvable to a unique answer. Kept as an\n * alias so existing imports keep working.\n */\nexport const MIN_SCAN_CLUES = MIN_CLUES;\n\nconst BOARD_PATTERN = /^[0-9]{81}$/;\n\n/** A scanned board, normalized and ready to load into entry or play. */\nexport interface ScannedBoard {\n /**\n * The board to enter and validate: the printed givens with the player's\n * digits merged in (81 chars, '0' = empty). Goes into the entry grid as\n * givens: the photo need not be a game in progress, and entry/validate only\n * knows givens.\n */\n puzzle: string;\n /** The printed givens as read, 81 chars, '0' = empty (diagnostics). */\n original: string;\n /**\n * Digits the player had entered, 81 chars, '0' = no input; given cells are\n * always '0' (diagnostics; already merged into `puzzle`).\n */\n user: string;\n /** 81 comma-separated pencilmark entries (e.g. \"126\"), or '' when none. */\n pencilmarks: string;\n /** Whether the pencilmarks were auto-filled in the scanned game. */\n autopencil: boolean;\n /** Number of givens in `puzzle` (the merged board that will be validated). */\n clueCount: number;\n /** OCR confidence, 0-100. */\n confidence: number;\n /** Which backend read the image, when the API says. */\n engine?: OCRExtractData['engine'];\n}\n\nexport type ScanBoardErrorCode =\n /** The request failed or the API reported an error. */\n | 'REQUEST_FAILED'\n /** The API answered without a usable 81-cell board. */\n | 'INVALID_BOARD'\n /** The board has fewer than MIN_SCAN_CLUES givens. */\n | 'TOO_FEW_CLUES';\n\nexport class ScanBoardError extends Error {\n readonly code: ScanBoardErrorCode;\n /** The board as read, when there was one (set for TOO_FEW_CLUES). */\n readonly board?: ScannedBoard;\n\n constructor(\n code: ScanBoardErrorCode,\n message: string,\n options: { board?: ScannedBoard; cause?: unknown } = {}\n ) {\n super(message);\n this.name = 'ScanBoardError';\n this.code = code;\n if (options.board) this.board = options.board;\n if (options.cause !== undefined) {\n (this as { cause?: unknown }).cause = options.cause;\n }\n }\n}\n\n/**\n * Normalize an OCR result into a ScannedBoard.\n *\n * - `user` keeps only the player's digits: given cells are blanked, so a given\n * can never be overwritten by a misread input digit.\n * - Pencilmarks are dropped from cells that hold a digit, and kept only when\n * there are 81 entries.\n *\n * @throws ScanBoardError `INVALID_BOARD` when `original` is not 81 digits\n */\nexport function toScannedBoard(\n data: OCRExtractData | null | undefined\n): ScannedBoard {\n const board = data?.board;\n const original = board?.original;\n if (!original || !BOARD_PATTERN.test(original)) {\n throw new ScanBoardError(\n 'INVALID_BOARD',\n 'OCR did not return an 81-cell board'\n );\n }\n\n const rawUser =\n board.user && BOARD_PATTERN.test(board.user) ? board.user : null;\n const user = Array.from({ length: 81 }, (_, i) =>\n rawUser && original[i] === '0' ? rawUser[i] : '0'\n ).join('');\n\n const entries = board.pencilmark?.numbers?.split(',') ?? [];\n let pencilmarks = '';\n if (entries.length === 81) {\n const cleaned = entries.map((entry, i) =>\n original[i] !== '0' || user[i] !== '0'\n ? ''\n : Array.from(new Set(entry.replace(/[^1-9]/g, '')))\n .sort()\n .join('')\n );\n if (cleaned.some(entry => entry !== '')) {\n pencilmarks = cleaned.join(',');\n }\n }\n\n const puzzle = Array.from(original, (ch, i) =>\n ch !== '0' ? ch : (user[i] ?? '0')\n ).join('');\n\n const result: ScannedBoard = {\n puzzle,\n original,\n user,\n pencilmarks,\n autopencil: pencilmarks !== '' && board.pencilmark?.autopencil === true,\n clueCount: puzzle.replace(/0/g, '').length,\n confidence: data?.confidence ?? 0,\n };\n if (data?.engine) result.engine = data.engine;\n return result;\n}\n\n/**\n * Whether the scan recorded any player digits. Informational only: the digits\n * are already merged into `puzzle`, so nothing needs restoring.\n */\nexport function hasScannedInput(board: ScannedBoard): boolean {\n return /[1-9]/.test(board.user);\n}\n\n/**\n * Turn the OCR endpoint's response into a playable ScannedBoard.\n *\n * The request itself belongs to sudojo_client (`useSudojoOcrExtract`); this\n * only interprets what came back.\n *\n * @throws ScanBoardError `REQUEST_FAILED` when the API reported an error,\n * `INVALID_BOARD` when there is no 81-cell board, `TOO_FEW_CLUES` when the\n * board has fewer than MIN_SCAN_CLUES givens (the error carries the board)\n */\nexport function scannedBoardFromResponse(\n response: BaseResponse<OCRExtractData>\n): ScannedBoard {\n if (!response.success) {\n throw new ScanBoardError(\n 'REQUEST_FAILED',\n response.error || 'OCR request failed'\n );\n }\n\n const board = toScannedBoard(response.data);\n if (board.clueCount < MIN_SCAN_CLUES) {\n throw new ScanBoardError(\n 'TOO_FEW_CLUES',\n `Too few clues detected (${board.clueCount}/${MIN_SCAN_CLUES} minimum)`,\n { board }\n );\n }\n return board;\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sudobility/sudojo_lib",
3
- "version": "0.0.203",
3
+ "version": "0.0.204",
4
4
  "description": "Business logic library for Sudojo app",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",