@fgv/ts-sudoku-lib 5.0.1-1 → 5.0.1-2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (82) hide show
  1. package/debug_killer.js +50 -0
  2. package/debug_test.js +88 -0
  3. package/dist/ts-sudoku-lib.d.ts +1505 -42
  4. package/lib/index.d.ts +3 -2
  5. package/lib/index.js +5 -3
  6. package/lib/packlets/collections/collections.d.ts +15 -8
  7. package/lib/packlets/collections/collections.js +41 -11
  8. package/lib/packlets/collections/data/puzzles.json +28 -33
  9. package/lib/packlets/common/common.d.ts +15 -0
  10. package/lib/packlets/common/common.js +25 -0
  11. package/lib/packlets/common/converters.d.ts +0 -6
  12. package/lib/packlets/common/converters.js +17 -22
  13. package/lib/packlets/common/ids.d.ts +8 -1
  14. package/lib/packlets/common/ids.js +83 -10
  15. package/lib/packlets/common/index.d.ts +3 -2
  16. package/lib/packlets/common/index.js +5 -2
  17. package/lib/packlets/common/logging.d.ts +7 -0
  18. package/lib/packlets/common/logging.js +35 -0
  19. package/lib/packlets/common/puzzle.d.ts +23 -13
  20. package/lib/packlets/common/puzzle.js +51 -25
  21. package/lib/packlets/common/puzzleDefinitions.d.ts +127 -0
  22. package/lib/packlets/common/puzzleDefinitions.js +251 -0
  23. package/lib/packlets/common/puzzleSession.d.ts +8 -0
  24. package/lib/packlets/common/puzzleSession.js +12 -0
  25. package/lib/packlets/common/puzzleState.js +3 -0
  26. package/lib/packlets/files/converters.d.ts +27 -0
  27. package/lib/packlets/files/converters.js +71 -0
  28. package/lib/packlets/{file/converters.d.ts → files/filesystem.d.ts} +3 -8
  29. package/lib/packlets/{file/converters.js → files/filesystem.js} +5 -14
  30. package/lib/packlets/files/index.d.ts +5 -0
  31. package/lib/packlets/{file → files}/index.js +3 -1
  32. package/lib/packlets/files/model.d.ts +32 -0
  33. package/lib/packlets/hints/baseHintProvider.d.ts +103 -0
  34. package/lib/packlets/hints/baseHintProvider.js +203 -0
  35. package/lib/packlets/hints/explanations.d.ts +105 -0
  36. package/lib/packlets/hints/explanations.js +276 -0
  37. package/lib/packlets/hints/hiddenSingles.d.ts +81 -0
  38. package/lib/packlets/hints/hiddenSingles.js +237 -0
  39. package/lib/packlets/hints/hintRegistry.d.ts +95 -0
  40. package/lib/packlets/hints/hintRegistry.js +226 -0
  41. package/lib/packlets/hints/hints.d.ts +144 -0
  42. package/lib/packlets/hints/hints.js +316 -0
  43. package/lib/packlets/hints/index.d.ts +10 -0
  44. package/lib/packlets/hints/index.js +55 -0
  45. package/lib/packlets/hints/interfaces.d.ts +121 -0
  46. package/lib/packlets/{file/model.js → hints/interfaces.js} +1 -1
  47. package/lib/packlets/hints/nakedSingles.d.ts +57 -0
  48. package/lib/packlets/hints/nakedSingles.js +202 -0
  49. package/lib/packlets/hints/puzzleSessionHints.d.ts +306 -0
  50. package/lib/packlets/hints/puzzleSessionHints.js +499 -0
  51. package/lib/packlets/hints/types.d.ts +102 -0
  52. package/lib/packlets/hints/types.js +46 -0
  53. package/lib/packlets/puzzles/anyPuzzle.d.ts +3 -3
  54. package/lib/packlets/puzzles/anyPuzzle.js +1 -1
  55. package/lib/packlets/puzzles/index.d.ts +4 -2
  56. package/lib/packlets/puzzles/index.js +20 -3
  57. package/lib/packlets/puzzles/internal/combinationCache.d.ts +29 -0
  58. package/lib/packlets/puzzles/internal/combinationCache.js +79 -0
  59. package/lib/packlets/puzzles/internal/combinationGenerator.d.ts +34 -0
  60. package/lib/packlets/puzzles/internal/combinationGenerator.js +146 -0
  61. package/lib/packlets/puzzles/internal/possibilityAnalyzer.d.ts +25 -0
  62. package/lib/packlets/puzzles/internal/possibilityAnalyzer.js +125 -0
  63. package/lib/packlets/puzzles/killerCombinations.d.ts +90 -0
  64. package/lib/packlets/puzzles/killerCombinations.js +226 -0
  65. package/lib/packlets/puzzles/killerCombinationsTypes.d.ts +17 -0
  66. package/lib/packlets/puzzles/killerCombinationsTypes.js +26 -0
  67. package/lib/packlets/puzzles/killerSudokuPuzzle.d.ts +2 -2
  68. package/lib/packlets/puzzles/killerSudokuPuzzle.js +15 -11
  69. package/lib/packlets/puzzles/sudokuPuzzle.d.ts +2 -2
  70. package/lib/packlets/puzzles/sudokuXPuzzle.d.ts +2 -2
  71. package/lib/packlets/puzzles/sudokuXPuzzle.js +8 -4
  72. package/package.json +5 -5
  73. package/sample-12x12-puzzle.js +72 -0
  74. package/sample-4x4-puzzles.js +68 -0
  75. package/sample-6x6-puzzle.js +61 -0
  76. package/temp_12x12_cells.txt +12 -0
  77. package/temp_correct.txt +12 -0
  78. package/test-grid-sizes.js +132 -0
  79. package/lib/packlets/common/model.d.ts +0 -15
  80. package/lib/packlets/file/index.d.ts +0 -4
  81. package/lib/packlets/file/model.d.ts +0 -9
  82. /package/lib/packlets/{common → files}/model.js +0 -0
@@ -0,0 +1,499 @@
1
+ "use strict";
2
+ /*
3
+ * MIT License
4
+ *
5
+ * Copyright (c) 2023 Erik Fortune
6
+ *
7
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
8
+ * of this software and associated documentation files (the "Software"), to deal
9
+ * in the Software without restriction, including without limitation the rights
10
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11
+ * copies of the Software, and to permit persons to whom the Software is
12
+ * furnished to do so, subject to the following conditions:
13
+ *
14
+ * The above copyright notice and this permission notice shall be included in all
15
+ * copies or substantial portions of the Software.
16
+ *
17
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23
+ * SOFTWARE.
24
+ */
25
+ Object.defineProperty(exports, "__esModule", { value: true });
26
+ exports.PuzzleSessionHints = void 0;
27
+ const ts_utils_1 = require("@fgv/ts-utils");
28
+ const common_1 = require("../common");
29
+ const hints_1 = require("./hints");
30
+ /**
31
+ * Wrapper class that integrates hint functionality with PuzzleSession.
32
+ * Provides hint generation, application, and explanation capabilities while
33
+ * maintaining integration with existing state management and undo/redo functionality.
34
+ * @public
35
+ */
36
+ class PuzzleSessionHints {
37
+ /**
38
+ * @internal
39
+ */
40
+ constructor(session, hintSystem, config) {
41
+ this._session = session;
42
+ this._hintSystem = hintSystem;
43
+ this._config = config;
44
+ this._hintCache = undefined;
45
+ }
46
+ /**
47
+ * Creates a new PuzzleSessionHints wrapper for an existing PuzzleSession.
48
+ * @param session - The PuzzleSession to wrap
49
+ * @param config - Optional configuration for the hint system
50
+ * @returns Result containing the new PuzzleSessionHints wrapper
51
+ */
52
+ static create(session, config) {
53
+ const finalConfig = Object.assign({ enableNakedSingles: true, enableHiddenSingles: true, defaultExplanationLevel: 'detailed', cacheTimeoutMs: 5000, maxCacheEntries: 1 }, config);
54
+ return hints_1.HintSystem.create(finalConfig).onSuccess((hintSystem) => {
55
+ return (0, ts_utils_1.succeed)(new PuzzleSessionHints(session, hintSystem, finalConfig));
56
+ });
57
+ }
58
+ /**
59
+ * Gets the wrapped PuzzleSession instance.
60
+ * @returns The underlying PuzzleSession
61
+ */
62
+ get session() {
63
+ return this._session;
64
+ }
65
+ /**
66
+ * Gets the HintSystem instance.
67
+ * @returns The hint system
68
+ */
69
+ get hintSystem() {
70
+ return this._hintSystem;
71
+ }
72
+ /**
73
+ * Gets the configuration.
74
+ * @returns The configuration
75
+ */
76
+ get config() {
77
+ return this._config;
78
+ }
79
+ // Delegate all PuzzleSession methods for transparent access
80
+ /**
81
+ * Gets the puzzle ID.
82
+ * @returns The puzzle ID
83
+ */
84
+ get id() {
85
+ return this._session.id;
86
+ }
87
+ /**
88
+ * Gets the puzzle description.
89
+ * @returns The puzzle description
90
+ */
91
+ get description() {
92
+ return this._session.description;
93
+ }
94
+ /**
95
+ * Gets the number of rows in the puzzle.
96
+ * @returns The number of rows
97
+ */
98
+ get numRows() {
99
+ return this._session.numRows;
100
+ }
101
+ /**
102
+ * Gets the number of columns in the puzzle.
103
+ * @returns The number of columns
104
+ */
105
+ get numColumns() {
106
+ return this._session.numColumns;
107
+ }
108
+ /**
109
+ * Gets the current puzzle state.
110
+ * @returns The current state
111
+ */
112
+ get state() {
113
+ return this._session.state;
114
+ }
115
+ /**
116
+ * Gets whether undo is possible.
117
+ * @returns true if undo is possible
118
+ */
119
+ get canUndo() {
120
+ return this._session.canUndo;
121
+ }
122
+ /**
123
+ * Gets whether redo is possible.
124
+ * @returns true if redo is possible
125
+ */
126
+ get canRedo() {
127
+ return this._session.canRedo;
128
+ }
129
+ /**
130
+ * Checks if the puzzle is solved.
131
+ * @returns true if the puzzle is solved
132
+ */
133
+ checkIsSolved() {
134
+ return this._session.checkIsSolved();
135
+ }
136
+ /**
137
+ * Checks if the puzzle is valid.
138
+ * @returns true if the puzzle is valid
139
+ */
140
+ checkIsValid() {
141
+ return this._session.checkIsValid();
142
+ }
143
+ /**
144
+ * Updates a cell value.
145
+ * @param spec - Cell specification
146
+ * @param value - New value
147
+ * @returns Result with this instance
148
+ */
149
+ updateCellValue(spec, value) {
150
+ return this._session.updateCellValue(spec, value).onSuccess(() => {
151
+ this._invalidateCache();
152
+ return (0, ts_utils_1.succeed)(this);
153
+ });
154
+ }
155
+ /**
156
+ * Updates cell notes.
157
+ * @param spec - Cell specification
158
+ * @param notes - New notes
159
+ * @returns Result with this instance
160
+ */
161
+ updateCellNotes(spec, notes) {
162
+ return this._session.updateCellNotes(spec, notes).onSuccess(() => {
163
+ this._invalidateCache();
164
+ return (0, ts_utils_1.succeed)(this);
165
+ });
166
+ }
167
+ /**
168
+ * Updates multiple cells.
169
+ * @param updates - Array of cell updates
170
+ * @returns Result with this instance
171
+ */
172
+ updateCells(updates) {
173
+ return this._session.updateCells(updates).onSuccess(() => {
174
+ this._invalidateCache();
175
+ return (0, ts_utils_1.succeed)(this);
176
+ });
177
+ }
178
+ /**
179
+ * Performs an undo operation.
180
+ * @returns Result with this instance
181
+ */
182
+ undo() {
183
+ return this._session.undo().onSuccess(() => {
184
+ this._invalidateCache();
185
+ return (0, ts_utils_1.succeed)(this);
186
+ });
187
+ }
188
+ /**
189
+ * Performs a redo operation.
190
+ * @returns Result with this instance
191
+ */
192
+ redo() {
193
+ return this._session.redo().onSuccess(() => {
194
+ this._invalidateCache();
195
+ return (0, ts_utils_1.succeed)(this);
196
+ });
197
+ }
198
+ // Hint-specific functionality
199
+ /**
200
+ * Gets the best available hint for the current puzzle state.
201
+ * @param options - Optional hint generation options
202
+ * @returns Result containing the best hint
203
+ */
204
+ getHint(options) {
205
+ return this._hintSystem.getBestHint(this._session.puzzle, this._session.state, options);
206
+ }
207
+ /**
208
+ * Gets all available hints for the current puzzle state.
209
+ * @param options - Optional hint generation options
210
+ * @returns Result containing array of hints
211
+ */
212
+ getAllHints(options) {
213
+ // Check cache first
214
+ const cachedHints = this._getCachedHints(options);
215
+ if (cachedHints) {
216
+ return (0, ts_utils_1.succeed)(cachedHints);
217
+ }
218
+ // Generate new hints
219
+ return this._hintSystem
220
+ .generateHints(this._session.puzzle, this._session.state, options)
221
+ .onSuccess((hints) => {
222
+ this._updateCache(hints, options);
223
+ return (0, ts_utils_1.succeed)(hints);
224
+ });
225
+ }
226
+ /**
227
+ * Applies a hint to the puzzle, updating the state and adding to undo history.
228
+ * @param hint - The hint to apply
229
+ * @returns Result with this instance if successful
230
+ */
231
+ applyHint(hint) {
232
+ return this._hintSystem
233
+ .applyHint(hint, this._session.puzzle, this._session.state)
234
+ .onSuccess((updates) => {
235
+ // Convert readonly array to mutable array for PuzzleSession.updateCells
236
+ const mutableUpdates = [...updates];
237
+ return this._session.updateCells(mutableUpdates).onSuccess(() => {
238
+ this._invalidateCache();
239
+ return (0, ts_utils_1.succeed)(this);
240
+ });
241
+ });
242
+ }
243
+ /**
244
+ * Gets hints that specifically affect a given cell.
245
+ * @param spec - Cell specification (ID, row/column, or cell object)
246
+ * @param options - Optional hint generation options
247
+ * @returns Result containing hints affecting the specified cell
248
+ */
249
+ getHintsForCell(spec, options) {
250
+ const cellIdResult = common_1.Ids.cellId(spec);
251
+ return cellIdResult.onSuccess((cellId) => {
252
+ return this.getAllHints(options).onSuccess((allHints) => {
253
+ const relevantHints = allHints.filter((hint) => {
254
+ // Check if the hint affects this specific cell
255
+ return (hint.cellActions.some((action) => action.cellId === cellId) ||
256
+ hint.relevantCells.primary.includes(cellId) ||
257
+ hint.relevantCells.secondary.includes(cellId) ||
258
+ hint.relevantCells.affected.includes(cellId));
259
+ });
260
+ return (0, ts_utils_1.succeed)(relevantHints);
261
+ });
262
+ });
263
+ }
264
+ /**
265
+ * Gets a formatted explanation for a hint.
266
+ * @param hint - The hint to explain
267
+ * @param level - The explanation level (defaults to configured default)
268
+ * @returns Formatted explanation string
269
+ */
270
+ getExplanation(hint, level) {
271
+ return this._hintSystem.formatHintExplanation(hint, level);
272
+ }
273
+ /**
274
+ * Validates that a hint can be applied to the current state.
275
+ * @param hint - The hint to validate
276
+ * @returns Result indicating validation success or failure
277
+ */
278
+ validateHint(hint) {
279
+ return this._hintSystem.validateHint(hint, this._session.puzzle, this._session.state);
280
+ }
281
+ /**
282
+ * Checks if hints are available for the current state.
283
+ * @param options - Optional hint generation options
284
+ * @returns Result containing boolean indicating availability
285
+ */
286
+ hasHints(options) {
287
+ return this._hintSystem.hasHints(this._session.puzzle, this._session.state);
288
+ }
289
+ /**
290
+ * Gets statistics about available hints.
291
+ * @param options - Optional hint generation options
292
+ * @returns Result containing hint statistics
293
+ */
294
+ getHintStatistics(options) {
295
+ return this._hintSystem.getHintStatistics(this._session.puzzle, this._session.state);
296
+ }
297
+ /**
298
+ * Gets a summary of the hint system capabilities.
299
+ * @returns System capabilities summary
300
+ */
301
+ getSystemSummary() {
302
+ return this._hintSystem.getSystemSummary();
303
+ }
304
+ // Delegate remaining PuzzleSession methods for complete transparency
305
+ /**
306
+ * Gets the rows.
307
+ * @returns Array of row cages
308
+ */
309
+ get rows() {
310
+ return this._session.rows;
311
+ }
312
+ /**
313
+ * Gets the columns.
314
+ * @returns Array of column cages
315
+ */
316
+ get cols() {
317
+ return this._session.cols;
318
+ }
319
+ /**
320
+ * Gets the sections.
321
+ * @returns Array of section cages
322
+ */
323
+ get sections() {
324
+ return this._session.sections;
325
+ }
326
+ /**
327
+ * Gets all cages.
328
+ * @returns Array of all cages
329
+ */
330
+ get cages() {
331
+ return this._session.cages;
332
+ }
333
+ /**
334
+ * Gets all cells.
335
+ * @returns Array of all cells
336
+ */
337
+ get cells() {
338
+ return this._session.cells;
339
+ }
340
+ /**
341
+ * Gets the next step index.
342
+ * @returns Next step index
343
+ */
344
+ get nextStep() {
345
+ return this._session.nextStep;
346
+ }
347
+ /**
348
+ * Gets the number of steps.
349
+ * @returns Number of steps
350
+ */
351
+ get numSteps() {
352
+ return this._session.numSteps;
353
+ }
354
+ /**
355
+ * Gets empty cells.
356
+ * @returns Array of empty cells
357
+ */
358
+ getEmptyCells() {
359
+ return this._session.getEmptyCells();
360
+ }
361
+ /**
362
+ * Gets invalid cells.
363
+ * @returns Array of invalid cells
364
+ */
365
+ getInvalidCells() {
366
+ return this._session.getInvalidCells();
367
+ }
368
+ /**
369
+ * Checks if a cell is valid.
370
+ * @param spec - Cell specification
371
+ * @returns true if valid
372
+ */
373
+ cellIsValid(spec) {
374
+ return this._session.cellIsValid(spec);
375
+ }
376
+ /**
377
+ * Checks if a cell has a value.
378
+ * @param spec - Cell specification
379
+ * @returns true if cell has value
380
+ */
381
+ cellHasValue(spec) {
382
+ return this._session.cellHasValue(spec);
383
+ }
384
+ /**
385
+ * Checks if a value is valid for a cell.
386
+ * @param spec - Cell specification
387
+ * @param value - Value to check
388
+ * @returns true if valid
389
+ */
390
+ isValidForCell(spec, value) {
391
+ return this._session.isValidForCell(spec, value);
392
+ }
393
+ /**
394
+ * Gets a cell neighbor.
395
+ * @param spec - Cell specification
396
+ * @param direction - Navigation direction
397
+ * @param wrap - Wrap behavior
398
+ * @returns Result containing neighbor cell
399
+ */
400
+ getCellNeighbor(spec, direction, wrap) {
401
+ return this._session.getCellNeighbor(spec, direction, wrap);
402
+ }
403
+ /**
404
+ * Gets cell contents.
405
+ * @param spec - Cell specification
406
+ * @returns Result containing cell and contents
407
+ */
408
+ getCellContents(spec) {
409
+ return this._session.getCellContents(spec);
410
+ }
411
+ /**
412
+ * Checks if a cage contains a value.
413
+ * @param spec - Cage specification
414
+ * @param value - Value to check
415
+ * @returns true if cage contains value
416
+ */
417
+ cageContainsValue(spec, value) {
418
+ return this._session.cageContainsValue(spec, value);
419
+ }
420
+ /**
421
+ * Gets contained values in a cage.
422
+ * @param spec - Cage specification
423
+ * @returns Set of contained values
424
+ */
425
+ cageContainedValues(spec) {
426
+ return this._session.cageContainedValues(spec);
427
+ }
428
+ /**
429
+ * Gets string representation of the puzzle.
430
+ * @returns Array of strings representing puzzle rows
431
+ */
432
+ toStrings() {
433
+ return this._session.toStrings();
434
+ }
435
+ // Private cache management methods
436
+ /**
437
+ * Generates a cache key for the current state and options.
438
+ * @param options - Hint generation options
439
+ * @returns Cache key
440
+ */
441
+ _generateCacheKey(options) {
442
+ // Simple state hash based on cell values and notes
443
+ const stateString = this._session.toStrings().join('|');
444
+ const notesString = this._session.cells
445
+ .map((cell) => {
446
+ const contents = this._session
447
+ .getCellContents(cell.id)
448
+ .orDefault({ cell, contents: { value: undefined, notes: [] } });
449
+ return `${cell.id}:${contents.contents.notes.join(',')}`;
450
+ })
451
+ .join('|');
452
+ const stateHash = `${stateString}#${notesString}`;
453
+ const optionsString = options ? JSON.stringify(options) : '';
454
+ return { stateHash, options: optionsString };
455
+ }
456
+ /**
457
+ * Gets cached hints if valid.
458
+ * @param options - Hint generation options
459
+ * @returns Cached hints or undefined
460
+ */
461
+ _getCachedHints(options) {
462
+ var _a;
463
+ if (!this._hintCache) {
464
+ return undefined;
465
+ }
466
+ const cacheKey = this._generateCacheKey(options);
467
+ /* c8 ignore next 1 - ?? is defense in depth */
468
+ const timeoutMs = (_a = this._config.cacheTimeoutMs) !== null && _a !== void 0 ? _a : 5000;
469
+ const now = Date.now();
470
+ // Check if cache is still valid
471
+ if (this._hintCache.cacheKey.stateHash === cacheKey.stateHash &&
472
+ this._hintCache.cacheKey.options === cacheKey.options &&
473
+ now - this._hintCache.generatedAt < timeoutMs) {
474
+ return this._hintCache.hints;
475
+ }
476
+ return undefined;
477
+ }
478
+ /**
479
+ * Updates the cache with new hints.
480
+ * @param hints - Generated hints
481
+ * @param options - Generation options
482
+ */
483
+ _updateCache(hints, options) {
484
+ const cacheKey = this._generateCacheKey(options);
485
+ this._hintCache = {
486
+ hints,
487
+ generatedAt: Date.now(),
488
+ cacheKey
489
+ };
490
+ }
491
+ /**
492
+ * Invalidates the current hint cache.
493
+ */
494
+ _invalidateCache() {
495
+ this._hintCache = undefined;
496
+ }
497
+ }
498
+ exports.PuzzleSessionHints = PuzzleSessionHints;
499
+ //# sourceMappingURL=puzzleSessionHints.js.map
@@ -0,0 +1,102 @@
1
+ import { Brand } from '@fgv/ts-utils';
2
+ import { CellId } from '../common';
3
+ /**
4
+ * Nominal identifier for a hint generation technique.
5
+ * @public
6
+ */
7
+ export type TechniqueId = Brand<string, 'TechniqueId'>;
8
+ /**
9
+ * Confidence level for a generated hint, ranging from 1 (low) to 5 (high).
10
+ * @public
11
+ */
12
+ export type ConfidenceLevel = Brand<1 | 2 | 3 | 4 | 5, 'ConfidenceLevel'>;
13
+ /**
14
+ * The type of action that should be taken on a cell as part of a hint.
15
+ * @public
16
+ */
17
+ export type CellAction = 'set-value' | 'eliminate-candidate' | 'add-candidate' | 'highlight';
18
+ /**
19
+ * The level of detail for hint explanations.
20
+ * @public
21
+ */
22
+ export type ExplanationLevel = 'brief' | 'detailed' | 'educational';
23
+ /**
24
+ * Standard difficulty classifications for Sudoku techniques.
25
+ * @public
26
+ */
27
+ export type DifficultyLevel = 'beginner' | 'intermediate' | 'advanced' | 'expert';
28
+ /**
29
+ * Describes an action to be taken on a specific cell as part of a hint.
30
+ * @public
31
+ */
32
+ export interface ICellAction {
33
+ readonly cellId: CellId;
34
+ readonly action: CellAction;
35
+ readonly value?: number;
36
+ readonly reason?: string;
37
+ }
38
+ /**
39
+ * Information about the cells that are relevant to understanding a hint.
40
+ * @public
41
+ */
42
+ export interface IRelevantCells {
43
+ readonly primary: readonly CellId[];
44
+ readonly secondary: readonly CellId[];
45
+ readonly affected: readonly CellId[];
46
+ }
47
+ /**
48
+ * A hint explanation at a specific level of detail.
49
+ * @public
50
+ */
51
+ export interface IHintExplanation {
52
+ readonly level: ExplanationLevel;
53
+ readonly title: string;
54
+ readonly description: string;
55
+ readonly steps?: readonly string[];
56
+ readonly tips?: readonly string[];
57
+ }
58
+ /**
59
+ * A complete hint with all necessary information for display and application.
60
+ * @public
61
+ */
62
+ export interface IHint {
63
+ readonly techniqueId: TechniqueId;
64
+ readonly techniqueName: string;
65
+ readonly difficulty: DifficultyLevel;
66
+ readonly confidence: ConfidenceLevel;
67
+ readonly cellActions: readonly ICellAction[];
68
+ readonly relevantCells: IRelevantCells;
69
+ readonly explanations: readonly IHintExplanation[];
70
+ readonly priority: number;
71
+ }
72
+ /**
73
+ * Configuration options for hint generation.
74
+ * @public
75
+ */
76
+ export interface IHintGenerationOptions {
77
+ readonly maxHints?: number;
78
+ readonly minConfidence?: ConfidenceLevel;
79
+ readonly preferredDifficulty?: DifficultyLevel;
80
+ readonly enabledTechniques?: readonly TechniqueId[];
81
+ readonly explanationLevel?: ExplanationLevel;
82
+ }
83
+ /**
84
+ * Standard technique identifiers for built-in solving techniques.
85
+ * @public
86
+ */
87
+ export declare const TechniqueIds: {
88
+ readonly NAKED_SINGLES: TechniqueId;
89
+ readonly HIDDEN_SINGLES: TechniqueId;
90
+ };
91
+ /**
92
+ * Standard confidence levels as branded types.
93
+ * @public
94
+ */
95
+ export declare const ConfidenceLevels: {
96
+ readonly LOW: ConfidenceLevel;
97
+ readonly MEDIUM_LOW: ConfidenceLevel;
98
+ readonly MEDIUM: ConfidenceLevel;
99
+ readonly MEDIUM_HIGH: ConfidenceLevel;
100
+ readonly HIGH: ConfidenceLevel;
101
+ };
102
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1,46 @@
1
+ "use strict";
2
+ /*
3
+ * MIT License
4
+ *
5
+ * Copyright (c) 2023 Erik Fortune
6
+ *
7
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
8
+ * of this software and associated documentation files (the "Software"), to deal
9
+ * in the Software without restriction, including without limitation the rights
10
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11
+ * copies of the Software, and to permit persons to whom the Software is
12
+ * furnished to do so, subject to the following conditions:
13
+ *
14
+ * The above copyright notice and this permission notice shall be included in all
15
+ * copies or substantial portions of the Software.
16
+ *
17
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23
+ * SOFTWARE.
24
+ */
25
+ Object.defineProperty(exports, "__esModule", { value: true });
26
+ exports.ConfidenceLevels = exports.TechniqueIds = void 0;
27
+ /**
28
+ * Standard technique identifiers for built-in solving techniques.
29
+ * @public
30
+ */
31
+ exports.TechniqueIds = {
32
+ NAKED_SINGLES: 'naked-singles',
33
+ HIDDEN_SINGLES: 'hidden-singles'
34
+ };
35
+ /**
36
+ * Standard confidence levels as branded types.
37
+ * @public
38
+ */
39
+ exports.ConfidenceLevels = {
40
+ LOW: 1,
41
+ MEDIUM_LOW: 2,
42
+ MEDIUM: 3,
43
+ MEDIUM_HIGH: 4,
44
+ HIGH: 5
45
+ };
46
+ //# sourceMappingURL=types.js.map
@@ -1,10 +1,10 @@
1
1
  import { Result } from '@fgv/ts-utils';
2
- import { IPuzzleDescription, Puzzle } from '../common';
2
+ import { IPuzzleDefinition, Puzzle } from '../common';
3
3
  /**
4
- * Static class to instantiate any puzzle from a {@link PuzzleDescription | puzzle description}.
4
+ * Static class to instantiate any puzzle from a {@link IPuzzleDefinition | puzzle definition}.
5
5
  * @internal
6
6
  */
7
7
  export declare class AnyPuzzle {
8
- static create(puzzle: IPuzzleDescription): Result<Puzzle>;
8
+ static create(puzzle: IPuzzleDefinition): Result<Puzzle>;
9
9
  }
10
10
  //# sourceMappingURL=anyPuzzle.d.ts.map
@@ -29,7 +29,7 @@ const killerSudokuPuzzle_1 = require("./killerSudokuPuzzle");
29
29
  const sudokuPuzzle_1 = require("./sudokuPuzzle");
30
30
  const sudokuXPuzzle_1 = require("./sudokuXPuzzle");
31
31
  /**
32
- * Static class to instantiate any puzzle from a {@link PuzzleDescription | puzzle description}.
32
+ * Static class to instantiate any puzzle from a {@link IPuzzleDefinition | puzzle definition}.
33
33
  * @internal
34
34
  */
35
35
  class AnyPuzzle {
@@ -1,6 +1,8 @@
1
- import { AnyPuzzle as Any } from './anyPuzzle';
2
1
  import { KillerSudokuPuzzle as Killer } from './killerSudokuPuzzle';
3
2
  import { SudokuPuzzle as Sudoku } from './sudokuPuzzle';
4
3
  import { SudokuXPuzzle as SudokuX } from './sudokuXPuzzle';
5
- export { Any, Killer, Sudoku, SudokuX };
4
+ import { KillerCombinations } from './killerCombinations';
5
+ import { AnyPuzzle as Any } from './anyPuzzle';
6
+ export * from './killerCombinationsTypes';
7
+ export { Any, Killer, KillerCombinations, Sudoku, SudokuX };
6
8
  //# sourceMappingURL=index.d.ts.map