@sudobility/sudojo_lib 0.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/hooks/index.d.ts +27 -0
- package/dist/hooks/index.d.ts.map +1 -0
- package/dist/hooks/index.js +27 -0
- package/dist/hooks/index.js.map +1 -0
- package/dist/hooks/useDailyGame.d.ts +64 -0
- package/dist/hooks/useDailyGame.d.ts.map +1 -0
- package/dist/hooks/useDailyGame.js +120 -0
- package/dist/hooks/useDailyGame.js.map +1 -0
- package/dist/hooks/useGame.d.ts +104 -0
- package/dist/hooks/useGame.d.ts.map +1 -0
- package/dist/hooks/useGame.js +546 -0
- package/dist/hooks/useGame.js.map +1 -0
- package/dist/hooks/useGamePersistence.d.ts +63 -0
- package/dist/hooks/useGamePersistence.d.ts.map +1 -0
- package/dist/hooks/useGamePersistence.js +124 -0
- package/dist/hooks/useGamePersistence.js.map +1 -0
- package/dist/hooks/useGameTeaching.d.ts +89 -0
- package/dist/hooks/useGameTeaching.d.ts.map +1 -0
- package/dist/hooks/useGameTeaching.js +230 -0
- package/dist/hooks/useGameTeaching.js.map +1 -0
- package/dist/hooks/useGameTimer.d.ts +43 -0
- package/dist/hooks/useGameTimer.d.ts.map +1 -0
- package/dist/hooks/useGameTimer.js +68 -0
- package/dist/hooks/useGameTimer.js.map +1 -0
- package/dist/hooks/useHint.d.ts +105 -0
- package/dist/hooks/useHint.d.ts.map +1 -0
- package/dist/hooks/useHint.js +179 -0
- package/dist/hooks/useHint.js.map +1 -0
- package/dist/hooks/useLearning.d.ts +100 -0
- package/dist/hooks/useLearning.d.ts.map +1 -0
- package/dist/hooks/useLearning.js +127 -0
- package/dist/hooks/useLearning.js.map +1 -0
- package/dist/hooks/useLevelGame.d.ts +68 -0
- package/dist/hooks/useLevelGame.d.ts.map +1 -0
- package/dist/hooks/useLevelGame.js +128 -0
- package/dist/hooks/useLevelGame.js.map +1 -0
- package/dist/hooks/useLevels.d.ts +93 -0
- package/dist/hooks/useLevels.d.ts.map +1 -0
- package/dist/hooks/useLevels.js +98 -0
- package/dist/hooks/useLevels.js.map +1 -0
- package/dist/hooks/useLocalStorage.d.ts +26 -0
- package/dist/hooks/useLocalStorage.d.ts.map +1 -0
- package/dist/hooks/useLocalStorage.js +75 -0
- package/dist/hooks/useLocalStorage.js.map +1 -0
- package/dist/hooks/useSudoku.d.ts +125 -0
- package/dist/hooks/useSudoku.d.ts.map +1 -0
- package/dist/hooks/useSudoku.js +655 -0
- package/dist/hooks/useSudoku.js.map +1 -0
- package/dist/hooks/useTechniques.d.ts +92 -0
- package/dist/hooks/useTechniques.d.ts.map +1 -0
- package/dist/hooks/useTechniques.js +108 -0
- package/dist/hooks/useTechniques.js.map +1 -0
- package/dist/index.d.ts +42 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +64 -0
- package/dist/index.js.map +1 -0
- package/dist/test/setup.d.ts +2 -0
- package/dist/test/setup.d.ts.map +1 -0
- package/dist/test/setup.js +35 -0
- package/dist/test/setup.js.map +1 -0
- package/dist/types/display.d.ts +142 -0
- package/dist/types/display.d.ts.map +1 -0
- package/dist/types/display.js +94 -0
- package/dist/types/display.js.map +1 -0
- package/dist/types/game.d.ts +201 -0
- package/dist/types/game.d.ts.map +1 -0
- package/dist/types/game.js +26 -0
- package/dist/types/game.js.map +1 -0
- package/dist/types/gamePersistence.d.ts +31 -0
- package/dist/types/gamePersistence.d.ts.map +1 -0
- package/dist/types/gamePersistence.js +15 -0
- package/dist/types/gamePersistence.js.map +1 -0
- package/dist/types/index.d.ts +18 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +11 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/progress.d.ts +43 -0
- package/dist/types/progress.d.ts.map +1 -0
- package/dist/types/progress.js +19 -0
- package/dist/types/progress.js.map +1 -0
- package/dist/types/settings.d.ts +19 -0
- package/dist/types/settings.d.ts.map +1 -0
- package/dist/types/settings.js +12 -0
- package/dist/types/settings.js.map +1 -0
- package/dist/types/subscription.d.ts +27 -0
- package/dist/types/subscription.d.ts.map +1 -0
- package/dist/types/subscription.js +8 -0
- package/dist/types/subscription.js.map +1 -0
- package/dist/types/sudoku.d.ts +147 -0
- package/dist/types/sudoku.d.ts.map +1 -0
- package/dist/types/sudoku.js +125 -0
- package/dist/types/sudoku.js.map +1 -0
- package/dist/utils/auth.d.ts +25 -0
- package/dist/utils/auth.d.ts.map +1 -0
- package/dist/utils/auth.js +47 -0
- package/dist/utils/auth.js.map +1 -0
- package/dist/utils/board.d.ts +116 -0
- package/dist/utils/board.d.ts.map +1 -0
- package/dist/utils/board.js +291 -0
- package/dist/utils/board.js.map +1 -0
- package/dist/utils/index.d.ts +18 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +23 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/progress.d.ts +44 -0
- package/dist/utils/progress.d.ts.map +1 -0
- package/dist/utils/progress.js +104 -0
- package/dist/utils/progress.js.map +1 -0
- package/dist/utils/scramble.d.ts +35 -0
- package/dist/utils/scramble.d.ts.map +1 -0
- package/dist/utils/scramble.js +270 -0
- package/dist/utils/scramble.js.map +1 -0
- package/dist/utils/subscription.d.ts +82 -0
- package/dist/utils/subscription.d.ts.map +1 -0
- package/dist/utils/subscription.js +117 -0
- package/dist/utils/subscription.js.map +1 -0
- package/dist/utils/sudokuPresenter.d.ts +62 -0
- package/dist/utils/sudokuPresenter.d.ts.map +1 -0
- package/dist/utils/sudokuPresenter.js +403 -0
- package/dist/utils/sudokuPresenter.js.map +1 -0
- package/dist/utils/sudokuScrambler.d.ts +61 -0
- package/dist/utils/sudokuScrambler.d.ts.map +1 -0
- package/dist/utils/sudokuScrambler.js +223 -0
- package/dist/utils/sudokuScrambler.js.map +1 -0
- package/dist/utils/technique.d.ts +41 -0
- package/dist/utils/technique.d.ts.map +1 -0
- package/dist/utils/technique.js +106 -0
- package/dist/utils/technique.js.map +1 -0
- package/dist/utils/theme.d.ts +31 -0
- package/dist/utils/theme.d.ts.map +1 -0
- package/dist/utils/theme.js +40 -0
- package/dist/utils/theme.js.map +1 -0
- package/dist/utils/time.d.ts +22 -0
- package/dist/utils/time.d.ts.map +1 -0
- package/dist/utils/time.js +41 -0
- package/dist/utils/time.js.map +1 -0
- package/dist/utils/validation.d.ts +107 -0
- package/dist/utils/validation.d.ts.map +1 -0
- package/dist/utils/validation.js +248 -0
- package/dist/utils/validation.js.map +1 -0
- package/package.json +79 -0
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Utility exports for Sudojo library
|
|
3
|
+
*/
|
|
4
|
+
// Board utilities (legacy - for useGame hook)
|
|
5
|
+
export { BLOCK_SIZE, BOARD_SIZE, cloneBoard, countFilledCells, createGameBoard, getBlockCells, getBlockIndex, getBoardStateString, getColumnCells, getEmptyCells, getPencilmarksString, getRelatedCells, getRowCells, isValidPlacement, parseBoardString, stringifyBoard, TOTAL_CELLS, } from './board';
|
|
6
|
+
// Scramble utilities (legacy - for useGame hook)
|
|
7
|
+
export { noScramble, scrambleBoard } from './scramble';
|
|
8
|
+
// Validation utilities (legacy - for useGame hook)
|
|
9
|
+
export { autoRemovePencilmarks, clearHighlights, countMistakes, getIncorrectCells, getProgressPercentage, isBoardFilled, isCellCorrect, isGameComplete, isValueCorrect, updateCellErrors, updateCellHighlights, validateGameState, } from './validation';
|
|
10
|
+
export { Scrambler, NonScrambler, scrambleBoard as scrambleSudokuBoard, parsePuzzleString, cellsToPuzzleString, cellsToStateString, cellsToInputString, cellsToPencilmarksString, } from './sudokuScrambler';
|
|
11
|
+
export { presentBoard, calculateCellHints, themeColorToCSS, getColorPalette, getCellsWithDigit, getSelectedDigit, computeSelectedDigitCells, } from './sudokuPresenter';
|
|
12
|
+
// Time utilities
|
|
13
|
+
export { formatTime, parseTime } from './time';
|
|
14
|
+
// Progress utilities
|
|
15
|
+
export { calculateStats, calculateStreak, isPuzzleCompleted, getCompletedLevelIds, getCompletedDailyDates, } from './progress';
|
|
16
|
+
// Auth utilities
|
|
17
|
+
export { getFirebaseErrorMessage, getFirebaseErrorCode, formatFirebaseError, } from './auth';
|
|
18
|
+
export { THEME_STORAGE_KEY, getSystemTheme, resolveTheme, isValidThemePreference, } from './theme';
|
|
19
|
+
// Subscription utilities
|
|
20
|
+
export { convertPackageToProduct, parseCustomerInfo, getPeriodDisplayName, isBestValuePlan, getRevenueCatErrorMessage, } from './subscription';
|
|
21
|
+
// Technique utilities
|
|
22
|
+
export { getTechniqueIconUrl, TECHNIQUE_TO_HELP_FILE, HELP_FILE_TO_TECHNIQUE, getHelpFileUrl, getTechniqueFromHelpFile, extractBodyContent, } from './technique';
|
|
23
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,8CAA8C;AAC9C,OAAO,EACL,UAAU,EACV,UAAU,EACV,UAAU,EACV,gBAAgB,EAChB,eAAe,EACf,aAAa,EACb,aAAa,EACb,mBAAmB,EACnB,cAAc,EACd,aAAa,EACb,oBAAoB,EACpB,eAAe,EACf,WAAW,EACX,gBAAgB,EAChB,gBAAgB,EAChB,cAAc,EACd,WAAW,GACZ,MAAM,SAAS,CAAC;AAEjB,iDAAiD;AACjD,OAAO,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAEvD,mDAAmD;AACnD,OAAO,EACL,qBAAqB,EACrB,eAAe,EACf,aAAa,EACb,iBAAiB,EACjB,qBAAqB,EACrB,aAAa,EACb,aAAa,EACb,cAAc,EACd,cAAc,EACd,gBAAgB,EAChB,oBAAoB,EACpB,iBAAiB,GAClB,MAAM,cAAc,CAAC;AAOtB,OAAO,EACL,SAAS,EACT,YAAY,EACZ,aAAa,IAAI,mBAAmB,EACpC,iBAAiB,EACjB,mBAAmB,EACnB,kBAAkB,EAClB,kBAAkB,EAClB,wBAAwB,GACzB,MAAM,mBAAmB,CAAC;AAI3B,OAAO,EACL,YAAY,EACZ,kBAAkB,EAClB,eAAe,EACf,eAAe,EACf,iBAAiB,EACjB,gBAAgB,EAChB,yBAAyB,GAC1B,MAAM,mBAAmB,CAAC;AAE3B,iBAAiB;AACjB,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AAE/C,qBAAqB;AACrB,OAAO,EACL,cAAc,EACd,eAAe,EACf,iBAAiB,EACjB,oBAAoB,EACpB,sBAAsB,GACvB,MAAM,YAAY,CAAC;AAEpB,iBAAiB;AACjB,OAAO,EACL,uBAAuB,EACvB,oBAAoB,EACpB,mBAAmB,GACpB,MAAM,QAAQ,CAAC;AAIhB,OAAO,EACL,iBAAiB,EACjB,cAAc,EACd,YAAY,EACZ,sBAAsB,GACvB,MAAM,SAAS,CAAC;AAEjB,yBAAyB;AACzB,OAAO,EACL,uBAAuB,EACvB,iBAAiB,EACjB,oBAAoB,EACpB,eAAe,EACf,yBAAyB,GAC1B,MAAM,gBAAgB,CAAC;AAExB,sBAAsB;AACtB,OAAO,EACL,mBAAmB,EACnB,sBAAsB,EACtB,sBAAsB,EACtB,cAAc,EACd,wBAAwB,EACxB,kBAAkB,GACnB,MAAM,aAAa,CAAC"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Progress calculation utilities
|
|
3
|
+
*/
|
|
4
|
+
import type { CompletedPuzzle, GameStats } from '../types/progress';
|
|
5
|
+
/**
|
|
6
|
+
* Calculate game statistics from completed puzzles
|
|
7
|
+
*
|
|
8
|
+
* @param completedPuzzles - Array of completed puzzle records
|
|
9
|
+
* @param newTime - Optional new time to include in calculations
|
|
10
|
+
* @returns Computed game statistics
|
|
11
|
+
*/
|
|
12
|
+
export declare function calculateStats(completedPuzzles: CompletedPuzzle[], newTime?: number): GameStats;
|
|
13
|
+
/**
|
|
14
|
+
* Calculate daily streak based on completions
|
|
15
|
+
*
|
|
16
|
+
* @param completedPuzzles - Array of completed puzzle records
|
|
17
|
+
* @param lastDailyDate - Date of last daily completion (YYYY-MM-DD)
|
|
18
|
+
* @returns Current streak count
|
|
19
|
+
*/
|
|
20
|
+
export declare function calculateStreak(completedPuzzles: CompletedPuzzle[], lastDailyDate: string | null): number;
|
|
21
|
+
/**
|
|
22
|
+
* Check if a specific puzzle is completed
|
|
23
|
+
*
|
|
24
|
+
* @param completedPuzzles - Array of completed puzzle records
|
|
25
|
+
* @param type - Puzzle type to check
|
|
26
|
+
* @param id - Puzzle ID to check
|
|
27
|
+
* @returns Whether the puzzle is completed
|
|
28
|
+
*/
|
|
29
|
+
export declare function isPuzzleCompleted(completedPuzzles: CompletedPuzzle[], type: 'daily' | 'level', id: string): boolean;
|
|
30
|
+
/**
|
|
31
|
+
* Get completed level IDs
|
|
32
|
+
*
|
|
33
|
+
* @param completedPuzzles - Array of completed puzzle records
|
|
34
|
+
* @returns Array of completed level IDs
|
|
35
|
+
*/
|
|
36
|
+
export declare function getCompletedLevelIds(completedPuzzles: CompletedPuzzle[]): string[];
|
|
37
|
+
/**
|
|
38
|
+
* Get completed daily dates
|
|
39
|
+
*
|
|
40
|
+
* @param completedPuzzles - Array of completed puzzle records
|
|
41
|
+
* @returns Array of completed daily dates (YYYY-MM-DD)
|
|
42
|
+
*/
|
|
43
|
+
export declare function getCompletedDailyDates(completedPuzzles: CompletedPuzzle[]): string[];
|
|
44
|
+
//# sourceMappingURL=progress.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"progress.d.ts","sourceRoot":"","sources":["../../src/utils/progress.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAEpE;;;;;;GAMG;AACH,wBAAgB,cAAc,CAC5B,gBAAgB,EAAE,eAAe,EAAE,EACnC,OAAO,CAAC,EAAE,MAAM,GACf,SAAS,CAqCX;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAC7B,gBAAgB,EAAE,eAAe,EAAE,EACnC,aAAa,EAAE,MAAM,GAAG,IAAI,GAC3B,MAAM,CAoCR;AAED;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAC/B,gBAAgB,EAAE,eAAe,EAAE,EACnC,IAAI,EAAE,OAAO,GAAG,OAAO,EACvB,EAAE,EAAE,MAAM,GACT,OAAO,CAET;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAClC,gBAAgB,EAAE,eAAe,EAAE,GAClC,MAAM,EAAE,CAEV;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CACpC,gBAAgB,EAAE,eAAe,EAAE,GAClC,MAAM,EAAE,CAEV"}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Progress calculation utilities
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Calculate game statistics from completed puzzles
|
|
6
|
+
*
|
|
7
|
+
* @param completedPuzzles - Array of completed puzzle records
|
|
8
|
+
* @param newTime - Optional new time to include in calculations
|
|
9
|
+
* @returns Computed game statistics
|
|
10
|
+
*/
|
|
11
|
+
export function calculateStats(completedPuzzles, newTime) {
|
|
12
|
+
const puzzlesWithTime = completedPuzzles.filter(p => p.timeSeconds !== undefined);
|
|
13
|
+
// Calculate total time
|
|
14
|
+
const totalTimePlayed = puzzlesWithTime.reduce((sum, p) => sum + (p.timeSeconds ?? 0), 0) +
|
|
15
|
+
(newTime ?? 0);
|
|
16
|
+
// Calculate average time
|
|
17
|
+
const count = puzzlesWithTime.length + (newTime !== undefined ? 1 : 0);
|
|
18
|
+
const averageTime = count > 0 ? Math.round(totalTimePlayed / count) : null;
|
|
19
|
+
// Calculate best times by type
|
|
20
|
+
const dailyTimes = completedPuzzles
|
|
21
|
+
.filter((p) => p.type === 'daily' && p.timeSeconds !== undefined)
|
|
22
|
+
.map(p => p.timeSeconds);
|
|
23
|
+
const levelTimes = completedPuzzles
|
|
24
|
+
.filter((p) => p.type === 'level' && p.timeSeconds !== undefined)
|
|
25
|
+
.map(p => p.timeSeconds);
|
|
26
|
+
const bestDailyTime = dailyTimes.length > 0 ? Math.min(...dailyTimes) : null;
|
|
27
|
+
const bestLevelTime = levelTimes.length > 0 ? Math.min(...levelTimes) : null;
|
|
28
|
+
return {
|
|
29
|
+
bestDailyTime,
|
|
30
|
+
bestLevelTime,
|
|
31
|
+
averageTime,
|
|
32
|
+
totalTimePlayed,
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Calculate daily streak based on completions
|
|
37
|
+
*
|
|
38
|
+
* @param completedPuzzles - Array of completed puzzle records
|
|
39
|
+
* @param lastDailyDate - Date of last daily completion (YYYY-MM-DD)
|
|
40
|
+
* @returns Current streak count
|
|
41
|
+
*/
|
|
42
|
+
export function calculateStreak(completedPuzzles, lastDailyDate) {
|
|
43
|
+
if (!lastDailyDate)
|
|
44
|
+
return 0;
|
|
45
|
+
const today = new Date().toISOString().split('T')[0];
|
|
46
|
+
const yesterday = new Date(Date.now() - 86400000).toISOString().split('T')[0];
|
|
47
|
+
// If last daily wasn't today or yesterday, streak is broken
|
|
48
|
+
if (lastDailyDate !== today && lastDailyDate !== yesterday) {
|
|
49
|
+
return 0;
|
|
50
|
+
}
|
|
51
|
+
// Count consecutive days
|
|
52
|
+
const dailyDates = completedPuzzles
|
|
53
|
+
.filter(p => p.type === 'daily')
|
|
54
|
+
.map(p => p.id)
|
|
55
|
+
.sort()
|
|
56
|
+
.reverse();
|
|
57
|
+
let streak = 0;
|
|
58
|
+
let currentDate = lastDailyDate === today ? today : yesterday;
|
|
59
|
+
for (const date of dailyDates) {
|
|
60
|
+
if (currentDate === undefined)
|
|
61
|
+
break;
|
|
62
|
+
if (date === currentDate) {
|
|
63
|
+
streak++;
|
|
64
|
+
// Go back one day
|
|
65
|
+
const previousDay = new Date(currentDate);
|
|
66
|
+
previousDay.setDate(previousDay.getDate() - 1);
|
|
67
|
+
currentDate = previousDay.toISOString().split('T')[0];
|
|
68
|
+
}
|
|
69
|
+
else if (date < currentDate) {
|
|
70
|
+
break;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
return streak;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Check if a specific puzzle is completed
|
|
77
|
+
*
|
|
78
|
+
* @param completedPuzzles - Array of completed puzzle records
|
|
79
|
+
* @param type - Puzzle type to check
|
|
80
|
+
* @param id - Puzzle ID to check
|
|
81
|
+
* @returns Whether the puzzle is completed
|
|
82
|
+
*/
|
|
83
|
+
export function isPuzzleCompleted(completedPuzzles, type, id) {
|
|
84
|
+
return completedPuzzles.some(p => p.type === type && p.id === id);
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Get completed level IDs
|
|
88
|
+
*
|
|
89
|
+
* @param completedPuzzles - Array of completed puzzle records
|
|
90
|
+
* @returns Array of completed level IDs
|
|
91
|
+
*/
|
|
92
|
+
export function getCompletedLevelIds(completedPuzzles) {
|
|
93
|
+
return completedPuzzles.filter(p => p.type === 'level').map(p => p.id);
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Get completed daily dates
|
|
97
|
+
*
|
|
98
|
+
* @param completedPuzzles - Array of completed puzzle records
|
|
99
|
+
* @returns Array of completed daily dates (YYYY-MM-DD)
|
|
100
|
+
*/
|
|
101
|
+
export function getCompletedDailyDates(completedPuzzles) {
|
|
102
|
+
return completedPuzzles.filter(p => p.type === 'daily').map(p => p.id);
|
|
103
|
+
}
|
|
104
|
+
//# sourceMappingURL=progress.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"progress.js","sourceRoot":"","sources":["../../src/utils/progress.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Board scrambling utilities for creating visually different but equivalent puzzles
|
|
3
|
+
*
|
|
4
|
+
* Scrambling preserves the logical structure of a Sudoku puzzle while making it
|
|
5
|
+
* appear different. This is useful for:
|
|
6
|
+
* - Preventing players from recognizing puzzles they've seen before
|
|
7
|
+
* - Creating variety from a limited puzzle database
|
|
8
|
+
* - Making it harder to look up solutions online
|
|
9
|
+
*/
|
|
10
|
+
import type { ScrambleConfig, ScrambleResult } from '../types';
|
|
11
|
+
/**
|
|
12
|
+
* Scrambles a Sudoku board while preserving its logical structure
|
|
13
|
+
*
|
|
14
|
+
* @param puzzle - 81-character puzzle string
|
|
15
|
+
* @param solution - 81-character solution string
|
|
16
|
+
* @param config - Scramble configuration (defaults to all transformations enabled)
|
|
17
|
+
* @returns Scramble result with scrambled puzzle, solution, and digit mapping
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* ```typescript
|
|
21
|
+
* const result = scrambleBoard(puzzle, solution);
|
|
22
|
+
* console.log(result.puzzle); // Scrambled puzzle
|
|
23
|
+
* console.log(result.solution); // Scrambled solution
|
|
24
|
+
* console.log(result.digitMapping); // Map from original to scrambled digits
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
27
|
+
export declare function scrambleBoard(puzzle: string, solution: string, config?: ScrambleConfig): ScrambleResult;
|
|
28
|
+
/**
|
|
29
|
+
* Creates an identity scramble result (no scrambling)
|
|
30
|
+
* @param puzzle - 81-character puzzle string
|
|
31
|
+
* @param solution - 81-character solution string
|
|
32
|
+
* @returns ScrambleResult with identity mapping
|
|
33
|
+
*/
|
|
34
|
+
export declare function noScramble(puzzle: string, solution: string): ScrambleResult;
|
|
35
|
+
//# sourceMappingURL=scramble.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scramble.d.ts","sourceRoot":"","sources":["../../src/utils/scramble.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AA2G/D;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,aAAa,CAC3B,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,EAChB,MAAM,GAAE,cAAwC,GAC/C,cAAc,CA4JhB;AAED;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,cAAc,CAY3E"}
|
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Board scrambling utilities for creating visually different but equivalent puzzles
|
|
3
|
+
*
|
|
4
|
+
* Scrambling preserves the logical structure of a Sudoku puzzle while making it
|
|
5
|
+
* appear different. This is useful for:
|
|
6
|
+
* - Preventing players from recognizing puzzles they've seen before
|
|
7
|
+
* - Creating variety from a limited puzzle database
|
|
8
|
+
* - Making it harder to look up solutions online
|
|
9
|
+
*/
|
|
10
|
+
import { DEFAULT_SCRAMBLE_CONFIG } from '../types';
|
|
11
|
+
import { BLOCK_SIZE, BOARD_SIZE, parseBoardString, stringifyBoard, } from './board';
|
|
12
|
+
/**
|
|
13
|
+
* Fisher-Yates shuffle algorithm for arrays
|
|
14
|
+
* @param array - Array to shuffle in place
|
|
15
|
+
* @returns The shuffled array
|
|
16
|
+
*/
|
|
17
|
+
function shuffleArray(array) {
|
|
18
|
+
for (let i = array.length - 1; i > 0; i--) {
|
|
19
|
+
const j = Math.floor(Math.random() * (i + 1));
|
|
20
|
+
const temp = array[i];
|
|
21
|
+
array[i] = array[j];
|
|
22
|
+
array[j] = temp;
|
|
23
|
+
}
|
|
24
|
+
return array;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Creates a random digit mapping (1-9 -> 1-9)
|
|
28
|
+
* @returns Map from original digit to scrambled digit
|
|
29
|
+
*/
|
|
30
|
+
function createDigitMapping() {
|
|
31
|
+
const digits = [1, 2, 3, 4, 5, 6, 7, 8, 9];
|
|
32
|
+
const shuffled = shuffleArray([...digits]);
|
|
33
|
+
const mapping = new Map();
|
|
34
|
+
for (let i = 0; i < digits.length; i++) {
|
|
35
|
+
mapping.set(digits[i], shuffled[i]);
|
|
36
|
+
}
|
|
37
|
+
return mapping;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Creates the reverse of a digit mapping
|
|
41
|
+
* @param mapping - Original digit mapping
|
|
42
|
+
* @returns Reverse mapping (scrambled -> original)
|
|
43
|
+
*/
|
|
44
|
+
function reverseDigitMapping(mapping) {
|
|
45
|
+
const reverse = new Map();
|
|
46
|
+
for (const [original, scrambled] of mapping) {
|
|
47
|
+
reverse.set(scrambled, original);
|
|
48
|
+
}
|
|
49
|
+
return reverse;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Applies digit mapping to a board
|
|
53
|
+
* @param board - 9x9 number array
|
|
54
|
+
* @param mapping - Digit mapping
|
|
55
|
+
* @returns New board with mapped digits
|
|
56
|
+
*/
|
|
57
|
+
function applyDigitMapping(board, mapping) {
|
|
58
|
+
return board.map(row => row.map(value => {
|
|
59
|
+
if (value === 0)
|
|
60
|
+
return 0;
|
|
61
|
+
return mapping.get(value) ?? value;
|
|
62
|
+
}));
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Rotates the board 90 degrees clockwise
|
|
66
|
+
* @param board - Board to rotate
|
|
67
|
+
* @returns New rotated board
|
|
68
|
+
*/
|
|
69
|
+
function rotateBoard90(board) {
|
|
70
|
+
const rotated = [];
|
|
71
|
+
for (let col = 0; col < BOARD_SIZE; col++) {
|
|
72
|
+
const newRow = [];
|
|
73
|
+
for (let row = BOARD_SIZE - 1; row >= 0; row--) {
|
|
74
|
+
newRow.push(board[row]?.[col] ?? 0);
|
|
75
|
+
}
|
|
76
|
+
rotated.push(newRow);
|
|
77
|
+
}
|
|
78
|
+
return rotated;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Mirrors the board horizontally (left-right)
|
|
82
|
+
* @param board - Board to mirror
|
|
83
|
+
* @returns New mirrored board
|
|
84
|
+
*/
|
|
85
|
+
function mirrorHorizontally(board) {
|
|
86
|
+
return board.map(row => [...row].reverse());
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Mirrors the board vertically (top-bottom)
|
|
90
|
+
* @param board - Board to mirror
|
|
91
|
+
* @returns New mirrored board
|
|
92
|
+
*/
|
|
93
|
+
function mirrorVertically(board) {
|
|
94
|
+
return [...board].reverse().map(row => [...row]);
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Scrambles a Sudoku board while preserving its logical structure
|
|
98
|
+
*
|
|
99
|
+
* @param puzzle - 81-character puzzle string
|
|
100
|
+
* @param solution - 81-character solution string
|
|
101
|
+
* @param config - Scramble configuration (defaults to all transformations enabled)
|
|
102
|
+
* @returns Scramble result with scrambled puzzle, solution, and digit mapping
|
|
103
|
+
*
|
|
104
|
+
* @example
|
|
105
|
+
* ```typescript
|
|
106
|
+
* const result = scrambleBoard(puzzle, solution);
|
|
107
|
+
* console.log(result.puzzle); // Scrambled puzzle
|
|
108
|
+
* console.log(result.solution); // Scrambled solution
|
|
109
|
+
* console.log(result.digitMapping); // Map from original to scrambled digits
|
|
110
|
+
* ```
|
|
111
|
+
*/
|
|
112
|
+
export function scrambleBoard(puzzle, solution, config = DEFAULT_SCRAMBLE_CONFIG) {
|
|
113
|
+
// Parse the boards
|
|
114
|
+
let puzzleBoard = parseBoardString(puzzle);
|
|
115
|
+
let solutionBoard = parseBoardString(solution);
|
|
116
|
+
// Create digit mapping (applied to both puzzle and solution)
|
|
117
|
+
let digitMapping = new Map();
|
|
118
|
+
for (let i = 1; i <= 9; i++) {
|
|
119
|
+
digitMapping.set(i, i); // Identity mapping by default
|
|
120
|
+
}
|
|
121
|
+
if (config.scrambleDigits) {
|
|
122
|
+
digitMapping = createDigitMapping();
|
|
123
|
+
puzzleBoard = applyDigitMapping(puzzleBoard, digitMapping);
|
|
124
|
+
solutionBoard = applyDigitMapping(solutionBoard, digitMapping);
|
|
125
|
+
}
|
|
126
|
+
// Scramble rows within blocks
|
|
127
|
+
if (config.scrambleRows) {
|
|
128
|
+
// We need to apply the same transformation to both boards
|
|
129
|
+
// Generate the permutation first, then apply to both
|
|
130
|
+
const rowPermutations = [];
|
|
131
|
+
for (let blockRow = 0; blockRow < BLOCK_SIZE; blockRow++) {
|
|
132
|
+
rowPermutations.push(shuffleArray([0, 1, 2]));
|
|
133
|
+
}
|
|
134
|
+
const applyRowPermutation = (board) => {
|
|
135
|
+
for (let blockRow = 0; blockRow < BLOCK_SIZE; blockRow++) {
|
|
136
|
+
const startRow = blockRow * BLOCK_SIZE;
|
|
137
|
+
const perm = rowPermutations[blockRow];
|
|
138
|
+
const rowsCopy = [
|
|
139
|
+
[...(board[startRow] ?? [])],
|
|
140
|
+
[...(board[startRow + 1] ?? [])],
|
|
141
|
+
[...(board[startRow + 2] ?? [])],
|
|
142
|
+
];
|
|
143
|
+
for (let i = 0; i < BLOCK_SIZE; i++) {
|
|
144
|
+
board[startRow + i] = rowsCopy[perm[i]];
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
};
|
|
148
|
+
applyRowPermutation(puzzleBoard);
|
|
149
|
+
applyRowPermutation(solutionBoard);
|
|
150
|
+
}
|
|
151
|
+
// Scramble columns within blocks
|
|
152
|
+
if (config.scrambleColumns) {
|
|
153
|
+
const colPermutations = [];
|
|
154
|
+
for (let blockCol = 0; blockCol < BLOCK_SIZE; blockCol++) {
|
|
155
|
+
colPermutations.push(shuffleArray([0, 1, 2]));
|
|
156
|
+
}
|
|
157
|
+
const applyColPermutation = (board) => {
|
|
158
|
+
for (let blockCol = 0; blockCol < BLOCK_SIZE; blockCol++) {
|
|
159
|
+
const startCol = blockCol * BLOCK_SIZE;
|
|
160
|
+
const perm = colPermutations[blockCol];
|
|
161
|
+
for (let row = 0; row < BOARD_SIZE; row++) {
|
|
162
|
+
const boardRow = board[row];
|
|
163
|
+
if (boardRow) {
|
|
164
|
+
const colsCopy = [
|
|
165
|
+
boardRow[startCol],
|
|
166
|
+
boardRow[startCol + 1],
|
|
167
|
+
boardRow[startCol + 2],
|
|
168
|
+
];
|
|
169
|
+
for (let i = 0; i < BLOCK_SIZE; i++) {
|
|
170
|
+
boardRow[startCol + i] = colsCopy[perm[i]];
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
};
|
|
176
|
+
applyColPermutation(puzzleBoard);
|
|
177
|
+
applyColPermutation(solutionBoard);
|
|
178
|
+
}
|
|
179
|
+
// Scramble row blocks
|
|
180
|
+
if (config.scrambleRowBlocks) {
|
|
181
|
+
const blockOrder = shuffleArray([0, 1, 2]);
|
|
182
|
+
const applyRowBlockPermutation = (board) => {
|
|
183
|
+
const allRows = board.map(row => [...row]);
|
|
184
|
+
const result = [];
|
|
185
|
+
for (let newBlockIndex = 0; newBlockIndex < BLOCK_SIZE; newBlockIndex++) {
|
|
186
|
+
const oldBlockIndex = blockOrder[newBlockIndex];
|
|
187
|
+
for (let i = 0; i < BLOCK_SIZE; i++) {
|
|
188
|
+
result.push(allRows[oldBlockIndex * BLOCK_SIZE + i]);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
return result;
|
|
192
|
+
};
|
|
193
|
+
puzzleBoard = applyRowBlockPermutation(puzzleBoard);
|
|
194
|
+
solutionBoard = applyRowBlockPermutation(solutionBoard);
|
|
195
|
+
}
|
|
196
|
+
// Scramble column blocks
|
|
197
|
+
if (config.scrambleColumnBlocks) {
|
|
198
|
+
const blockOrder = shuffleArray([0, 1, 2]);
|
|
199
|
+
const applyColBlockPermutation = (board) => {
|
|
200
|
+
const result = board.map(() => new Array(BOARD_SIZE).fill(0));
|
|
201
|
+
for (let newBlockIndex = 0; newBlockIndex < BLOCK_SIZE; newBlockIndex++) {
|
|
202
|
+
const oldBlockIndex = blockOrder[newBlockIndex];
|
|
203
|
+
for (let i = 0; i < BLOCK_SIZE; i++) {
|
|
204
|
+
const oldCol = oldBlockIndex * BLOCK_SIZE + i;
|
|
205
|
+
const newCol = newBlockIndex * BLOCK_SIZE + i;
|
|
206
|
+
for (let row = 0; row < BOARD_SIZE; row++) {
|
|
207
|
+
const resultRow = result[row];
|
|
208
|
+
if (resultRow) {
|
|
209
|
+
resultRow[newCol] = board[row]?.[oldCol] ?? 0;
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
return result;
|
|
215
|
+
};
|
|
216
|
+
puzzleBoard = applyColBlockPermutation(puzzleBoard);
|
|
217
|
+
solutionBoard = applyColBlockPermutation(solutionBoard);
|
|
218
|
+
}
|
|
219
|
+
// Rotate
|
|
220
|
+
if (config.rotate) {
|
|
221
|
+
const rotations = Math.floor(Math.random() * 4);
|
|
222
|
+
for (let i = 0; i < rotations; i++) {
|
|
223
|
+
puzzleBoard = rotateBoard90(puzzleBoard);
|
|
224
|
+
solutionBoard = rotateBoard90(solutionBoard);
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
// Mirror
|
|
228
|
+
if (config.mirror) {
|
|
229
|
+
const mirrorType = Math.floor(Math.random() * 4);
|
|
230
|
+
const applyMirror = (board) => {
|
|
231
|
+
switch (mirrorType) {
|
|
232
|
+
case 1:
|
|
233
|
+
return mirrorHorizontally(board);
|
|
234
|
+
case 2:
|
|
235
|
+
return mirrorVertically(board);
|
|
236
|
+
case 3:
|
|
237
|
+
return mirrorVertically(mirrorHorizontally(board));
|
|
238
|
+
default:
|
|
239
|
+
return board;
|
|
240
|
+
}
|
|
241
|
+
};
|
|
242
|
+
puzzleBoard = applyMirror(puzzleBoard);
|
|
243
|
+
solutionBoard = applyMirror(solutionBoard);
|
|
244
|
+
}
|
|
245
|
+
return {
|
|
246
|
+
puzzle: stringifyBoard(puzzleBoard),
|
|
247
|
+
solution: stringifyBoard(solutionBoard),
|
|
248
|
+
digitMapping,
|
|
249
|
+
reverseDigitMapping: reverseDigitMapping(digitMapping),
|
|
250
|
+
};
|
|
251
|
+
}
|
|
252
|
+
/**
|
|
253
|
+
* Creates an identity scramble result (no scrambling)
|
|
254
|
+
* @param puzzle - 81-character puzzle string
|
|
255
|
+
* @param solution - 81-character solution string
|
|
256
|
+
* @returns ScrambleResult with identity mapping
|
|
257
|
+
*/
|
|
258
|
+
export function noScramble(puzzle, solution) {
|
|
259
|
+
const identityMapping = new Map();
|
|
260
|
+
for (let i = 1; i <= 9; i++) {
|
|
261
|
+
identityMapping.set(i, i);
|
|
262
|
+
}
|
|
263
|
+
return {
|
|
264
|
+
puzzle,
|
|
265
|
+
solution,
|
|
266
|
+
digitMapping: identityMapping,
|
|
267
|
+
reverseDigitMapping: identityMapping,
|
|
268
|
+
};
|
|
269
|
+
}
|
|
270
|
+
//# sourceMappingURL=scramble.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scramble.js","sourceRoot":"","sources":["../../src/utils/scramble.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,EAAE,uBAAuB,EAAE,MAAM,UAAU,CAAC;AACnD,OAAO,EACL,UAAU,EACV,UAAU,EACV,gBAAgB,EAChB,cAAc,GACf,MAAM,SAAS,CAAC;AAEjB;;;;GAIG;AACH,SAAS,YAAY,CAAI,KAAU;IACjC,KAAK,IAAI,CAAC,GAAG,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QAC1C,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;QAC9C,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;QACtB,KAAK,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,CAAM,CAAC;QACzB,KAAK,CAAC,CAAC,CAAC,GAAG,IAAS,CAAC;IACvB,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;GAGG;AACH,SAAS,kBAAkB;IACzB,MAAM,MAAM,GAAG,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;IAC3C,MAAM,QAAQ,GAAG,YAAY,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC;IAE3C,MAAM,OAAO,GAAG,IAAI,GAAG,EAAkB,CAAC;IAC1C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACvC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAW,EAAE,QAAQ,CAAC,CAAC,CAAW,CAAC,CAAC;IAC1D,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;;;GAIG;AACH,SAAS,mBAAmB,CAC1B,OAA4B;IAE5B,MAAM,OAAO,GAAG,IAAI,GAAG,EAAkB,CAAC;IAC1C,KAAK,MAAM,CAAC,QAAQ,EAAE,SAAS,CAAC,IAAI,OAAO,EAAE,CAAC;QAC5C,OAAO,CAAC,GAAG,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;IACnC,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;;;;GAKG;AACH,SAAS,iBAAiB,CACxB,KAAiB,EACjB,OAA4B;IAE5B,OAAO,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CACrB,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE;QACd,IAAI,KAAK,KAAK,CAAC;YAAE,OAAO,CAAC,CAAC;QAC1B,OAAO,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC;IACrC,CAAC,CAAC,CACH,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,SAAS,aAAa,CAAC,KAAiB;IACtC,MAAM,OAAO,GAAe,EAAE,CAAC;IAC/B,KAAK,IAAI,GAAG,GAAG,CAAC,EAAE,GAAG,GAAG,UAAU,EAAE,GAAG,EAAE,EAAE,CAAC;QAC1C,MAAM,MAAM,GAAa,EAAE,CAAC;QAC5B,KAAK,IAAI,GAAG,GAAG,UAAU,GAAG,CAAC,EAAE,GAAG,IAAI,CAAC,EAAE,GAAG,EAAE,EAAE,CAAC;YAC/C,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC;QACtC,CAAC;QACD,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACvB,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;;;GAIG;AACH,SAAS,kBAAkB,CAAC,KAAiB;IAC3C,OAAO,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC;AAC9C,CAAC;AAED;;;;GAIG;AACH,SAAS,gBAAgB,CAAC,KAAiB;IACzC,OAAO,CAAC,GAAG,KAAK,CAAC,CAAC,OAAO,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC;AACnD,CAAC;AAED;;;;;;;;;;;;;;;GAeG;AACH,MAAM,UAAU,aAAa,CAC3B,MAAc,EACd,QAAgB,EAChB,SAAyB,uBAAuB;IAEhD,mBAAmB;IACnB,IAAI,WAAW,GAAG,gBAAgB,CAAC,MAAM,CAAC,CAAC;IAC3C,IAAI,aAAa,GAAG,gBAAgB,CAAC,QAAQ,CAAC,CAAC;IAE/C,6DAA6D;IAC7D,IAAI,YAAY,GAAG,IAAI,GAAG,EAAkB,CAAC;IAC7C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QAC5B,YAAY,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,8BAA8B;IACxD,CAAC;IAED,IAAI,MAAM,CAAC,cAAc,EAAE,CAAC;QAC1B,YAAY,GAAG,kBAAkB,EAAE,CAAC;QACpC,WAAW,GAAG,iBAAiB,CAAC,WAAW,EAAE,YAAY,CAAC,CAAC;QAC3D,aAAa,GAAG,iBAAiB,CAAC,aAAa,EAAE,YAAY,CAAC,CAAC;IACjE,CAAC;IAED,8BAA8B;IAC9B,IAAI,MAAM,CAAC,YAAY,EAAE,CAAC;QACxB,0DAA0D;QAC1D,qDAAqD;QACrD,MAAM,eAAe,GAAe,EAAE,CAAC;QACvC,KAAK,IAAI,QAAQ,GAAG,CAAC,EAAE,QAAQ,GAAG,UAAU,EAAE,QAAQ,EAAE,EAAE,CAAC;YACzD,eAAe,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;QAChD,CAAC;QAED,MAAM,mBAAmB,GAAG,CAAC,KAAiB,EAAQ,EAAE;YACtD,KAAK,IAAI,QAAQ,GAAG,CAAC,EAAE,QAAQ,GAAG,UAAU,EAAE,QAAQ,EAAE,EAAE,CAAC;gBACzD,MAAM,QAAQ,GAAG,QAAQ,GAAG,UAAU,CAAC;gBACvC,MAAM,IAAI,GAAG,eAAe,CAAC,QAAQ,CAAa,CAAC;gBACnD,MAAM,QAAQ,GAAG;oBACf,CAAC,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC;oBAC5B,CAAC,GAAG,CAAC,KAAK,CAAC,QAAQ,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;oBAChC,CAAC,GAAG,CAAC,KAAK,CAAC,QAAQ,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;iBACjC,CAAC;gBACF,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,UAAU,EAAE,CAAC,EAAE,EAAE,CAAC;oBACpC,KAAK,CAAC,QAAQ,GAAG,CAAC,CAAC,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAW,CAAa,CAAC;gBAChE,CAAC;YACH,CAAC;QACH,CAAC,CAAC;QAEF,mBAAmB,CAAC,WAAW,CAAC,CAAC;QACjC,mBAAmB,CAAC,aAAa,CAAC,CAAC;IACrC,CAAC;IAED,iCAAiC;IACjC,IAAI,MAAM,CAAC,eAAe,EAAE,CAAC;QAC3B,MAAM,eAAe,GAAe,EAAE,CAAC;QACvC,KAAK,IAAI,QAAQ,GAAG,CAAC,EAAE,QAAQ,GAAG,UAAU,EAAE,QAAQ,EAAE,EAAE,CAAC;YACzD,eAAe,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;QAChD,CAAC;QAED,MAAM,mBAAmB,GAAG,CAAC,KAAiB,EAAQ,EAAE;YACtD,KAAK,IAAI,QAAQ,GAAG,CAAC,EAAE,QAAQ,GAAG,UAAU,EAAE,QAAQ,EAAE,EAAE,CAAC;gBACzD,MAAM,QAAQ,GAAG,QAAQ,GAAG,UAAU,CAAC;gBACvC,MAAM,IAAI,GAAG,eAAe,CAAC,QAAQ,CAAa,CAAC;gBACnD,KAAK,IAAI,GAAG,GAAG,CAAC,EAAE,GAAG,GAAG,UAAU,EAAE,GAAG,EAAE,EAAE,CAAC;oBAC1C,MAAM,QAAQ,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC;oBAC5B,IAAI,QAAQ,EAAE,CAAC;wBACb,MAAM,QAAQ,GAAG;4BACf,QAAQ,CAAC,QAAQ,CAAC;4BAClB,QAAQ,CAAC,QAAQ,GAAG,CAAC,CAAC;4BACtB,QAAQ,CAAC,QAAQ,GAAG,CAAC,CAAC;yBACvB,CAAC;wBACF,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,UAAU,EAAE,CAAC,EAAE,EAAE,CAAC;4BACpC,QAAQ,CAAC,QAAQ,GAAG,CAAC,CAAC,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAW,CAAW,CAAC;wBACjE,CAAC;oBACH,CAAC;gBACH,CAAC;YACH,CAAC;QACH,CAAC,CAAC;QAEF,mBAAmB,CAAC,WAAW,CAAC,CAAC;QACjC,mBAAmB,CAAC,aAAa,CAAC,CAAC;IACrC,CAAC;IAED,sBAAsB;IACtB,IAAI,MAAM,CAAC,iBAAiB,EAAE,CAAC;QAC7B,MAAM,UAAU,GAAG,YAAY,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;QAE3C,MAAM,wBAAwB,GAAG,CAAC,KAAiB,EAAc,EAAE;YACjE,MAAM,OAAO,GAAG,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC;YAC3C,MAAM,MAAM,GAAe,EAAE,CAAC;YAC9B,KAAK,IAAI,aAAa,GAAG,CAAC,EAAE,aAAa,GAAG,UAAU,EAAE,aAAa,EAAE,EAAE,CAAC;gBACxE,MAAM,aAAa,GAAG,UAAU,CAAC,aAAa,CAAW,CAAC;gBAC1D,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,UAAU,EAAE,CAAC,EAAE,EAAE,CAAC;oBACpC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,aAAa,GAAG,UAAU,GAAG,CAAC,CAAa,CAAC,CAAC;gBACnE,CAAC;YACH,CAAC;YACD,OAAO,MAAM,CAAC;QAChB,CAAC,CAAC;QAEF,WAAW,GAAG,wBAAwB,CAAC,WAAW,CAAC,CAAC;QACpD,aAAa,GAAG,wBAAwB,CAAC,aAAa,CAAC,CAAC;IAC1D,CAAC;IAED,yBAAyB;IACzB,IAAI,MAAM,CAAC,oBAAoB,EAAE,CAAC;QAChC,MAAM,UAAU,GAAG,YAAY,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;QAE3C,MAAM,wBAAwB,GAAG,CAAC,KAAiB,EAAc,EAAE;YACjE,MAAM,MAAM,GAAe,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,IAAI,KAAK,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;YAC1E,KAAK,IAAI,aAAa,GAAG,CAAC,EAAE,aAAa,GAAG,UAAU,EAAE,aAAa,EAAE,EAAE,CAAC;gBACxE,MAAM,aAAa,GAAG,UAAU,CAAC,aAAa,CAAW,CAAC;gBAC1D,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,UAAU,EAAE,CAAC,EAAE,EAAE,CAAC;oBACpC,MAAM,MAAM,GAAG,aAAa,GAAG,UAAU,GAAG,CAAC,CAAC;oBAC9C,MAAM,MAAM,GAAG,aAAa,GAAG,UAAU,GAAG,CAAC,CAAC;oBAC9C,KAAK,IAAI,GAAG,GAAG,CAAC,EAAE,GAAG,GAAG,UAAU,EAAE,GAAG,EAAE,EAAE,CAAC;wBAC1C,MAAM,SAAS,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;wBAC9B,IAAI,SAAS,EAAE,CAAC;4BACd,SAAS,CAAC,MAAM,CAAC,GAAG,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;wBAChD,CAAC;oBACH,CAAC;gBACH,CAAC;YACH,CAAC;YACD,OAAO,MAAM,CAAC;QAChB,CAAC,CAAC;QAEF,WAAW,GAAG,wBAAwB,CAAC,WAAW,CAAC,CAAC;QACpD,aAAa,GAAG,wBAAwB,CAAC,aAAa,CAAC,CAAC;IAC1D,CAAC;IAED,SAAS;IACT,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;QAClB,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC;QAChD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,SAAS,EAAE,CAAC,EAAE,EAAE,CAAC;YACnC,WAAW,GAAG,aAAa,CAAC,WAAW,CAAC,CAAC;YACzC,aAAa,GAAG,aAAa,CAAC,aAAa,CAAC,CAAC;QAC/C,CAAC;IACH,CAAC;IAED,SAAS;IACT,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;QAClB,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC;QACjD,MAAM,WAAW,GAAG,CAAC,KAAiB,EAAc,EAAE;YACpD,QAAQ,UAAU,EAAE,CAAC;gBACnB,KAAK,CAAC;oBACJ,OAAO,kBAAkB,CAAC,KAAK,CAAC,CAAC;gBACnC,KAAK,CAAC;oBACJ,OAAO,gBAAgB,CAAC,KAAK,CAAC,CAAC;gBACjC,KAAK,CAAC;oBACJ,OAAO,gBAAgB,CAAC,kBAAkB,CAAC,KAAK,CAAC,CAAC,CAAC;gBACrD;oBACE,OAAO,KAAK,CAAC;YACjB,CAAC;QACH,CAAC,CAAC;QACF,WAAW,GAAG,WAAW,CAAC,WAAW,CAAC,CAAC;QACvC,aAAa,GAAG,WAAW,CAAC,aAAa,CAAC,CAAC;IAC7C,CAAC;IAED,OAAO;QACL,MAAM,EAAE,cAAc,CAAC,WAAW,CAAC;QACnC,QAAQ,EAAE,cAAc,CAAC,aAAa,CAAC;QACvC,YAAY;QACZ,mBAAmB,EAAE,mBAAmB,CAAC,YAAY,CAAC;KACvD,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,UAAU,CAAC,MAAc,EAAE,QAAgB;IACzD,MAAM,eAAe,GAAG,IAAI,GAAG,EAAkB,CAAC;IAClD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QAC5B,eAAe,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAC5B,CAAC;IAED,OAAO;QACL,MAAM;QACN,QAAQ;QACR,YAAY,EAAE,eAAe;QAC7B,mBAAmB,EAAE,eAAe;KACrC,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Subscription utilities
|
|
3
|
+
*
|
|
4
|
+
* These functions work with RevenueCat SDK types to convert to our domain models.
|
|
5
|
+
* The RevenueCat types are passed as generics to avoid direct SDK dependency.
|
|
6
|
+
*/
|
|
7
|
+
import type { Product, Subscription } from '../types/subscription';
|
|
8
|
+
/** RevenueCat Package shape (simplified) */
|
|
9
|
+
interface RevenueCatPackage {
|
|
10
|
+
identifier: string;
|
|
11
|
+
rcBillingProduct?: {
|
|
12
|
+
identifier?: string;
|
|
13
|
+
title?: string;
|
|
14
|
+
description?: string;
|
|
15
|
+
currentPrice?: {
|
|
16
|
+
amountMicros?: number;
|
|
17
|
+
formattedPrice?: string;
|
|
18
|
+
};
|
|
19
|
+
normalPeriodDuration?: string;
|
|
20
|
+
defaultSubscriptionOption?: {
|
|
21
|
+
introPrice?: {
|
|
22
|
+
price?: {
|
|
23
|
+
formattedPrice?: string;
|
|
24
|
+
};
|
|
25
|
+
periodDuration?: string;
|
|
26
|
+
};
|
|
27
|
+
trial?: {
|
|
28
|
+
periodDuration?: string;
|
|
29
|
+
};
|
|
30
|
+
};
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
/** RevenueCat CustomerInfo entitlement shape */
|
|
34
|
+
interface RevenueCatEntitlement {
|
|
35
|
+
expirationDate?: number | null;
|
|
36
|
+
latestPurchaseDate?: number | null;
|
|
37
|
+
productIdentifier?: string;
|
|
38
|
+
willRenew?: boolean;
|
|
39
|
+
}
|
|
40
|
+
/** RevenueCat CustomerInfo shape (simplified) */
|
|
41
|
+
interface RevenueCatCustomerInfo {
|
|
42
|
+
entitlements: {
|
|
43
|
+
active: Record<string, RevenueCatEntitlement>;
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Convert RevenueCat package to our Product interface
|
|
48
|
+
*
|
|
49
|
+
* @param pkg - RevenueCat package
|
|
50
|
+
* @returns Product object
|
|
51
|
+
*/
|
|
52
|
+
export declare function convertPackageToProduct(pkg: RevenueCatPackage): Product;
|
|
53
|
+
/**
|
|
54
|
+
* Parse RevenueCat CustomerInfo into our Subscription interface
|
|
55
|
+
*
|
|
56
|
+
* @param customerInfo - RevenueCat customer info
|
|
57
|
+
* @returns Subscription object
|
|
58
|
+
*/
|
|
59
|
+
export declare function parseCustomerInfo(customerInfo: RevenueCatCustomerInfo): Subscription;
|
|
60
|
+
/**
|
|
61
|
+
* Get display name for subscription period
|
|
62
|
+
*
|
|
63
|
+
* @param period - ISO 8601 duration string (e.g., "P1M", "P1Y")
|
|
64
|
+
* @returns Human-readable period name
|
|
65
|
+
*/
|
|
66
|
+
export declare function getPeriodDisplayName(period: string | undefined): string;
|
|
67
|
+
/**
|
|
68
|
+
* Check if a plan is the "best value" (typically annual plans)
|
|
69
|
+
*
|
|
70
|
+
* @param period - ISO 8601 duration string
|
|
71
|
+
* @returns Whether this is typically the best value option
|
|
72
|
+
*/
|
|
73
|
+
export declare function isBestValuePlan(period: string | undefined): boolean;
|
|
74
|
+
/**
|
|
75
|
+
* Get RevenueCat purchase error message
|
|
76
|
+
*
|
|
77
|
+
* @param errorCode - RevenueCat error code
|
|
78
|
+
* @returns User-friendly error message
|
|
79
|
+
*/
|
|
80
|
+
export declare function getRevenueCatErrorMessage(errorCode: number): string;
|
|
81
|
+
export {};
|
|
82
|
+
//# sourceMappingURL=subscription.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"subscription.d.ts","sourceRoot":"","sources":["../../src/utils/subscription.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAEnE,4CAA4C;AAC5C,UAAU,iBAAiB;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,gBAAgB,CAAC,EAAE;QACjB,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,YAAY,CAAC,EAAE;YACb,YAAY,CAAC,EAAE,MAAM,CAAC;YACtB,cAAc,CAAC,EAAE,MAAM,CAAC;SACzB,CAAC;QACF,oBAAoB,CAAC,EAAE,MAAM,CAAC;QAC9B,yBAAyB,CAAC,EAAE;YAC1B,UAAU,CAAC,EAAE;gBACX,KAAK,CAAC,EAAE;oBACN,cAAc,CAAC,EAAE,MAAM,CAAC;iBACzB,CAAC;gBACF,cAAc,CAAC,EAAE,MAAM,CAAC;aACzB,CAAC;YACF,KAAK,CAAC,EAAE;gBACN,cAAc,CAAC,EAAE,MAAM,CAAC;aACzB,CAAC;SACH,CAAC;KACH,CAAC;CACH;AAED,gDAAgD;AAChD,UAAU,qBAAqB;IAC7B,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,kBAAkB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,iDAAiD;AACjD,UAAU,sBAAsB;IAC9B,YAAY,EAAE;QACZ,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,qBAAqB,CAAC,CAAC;KAC/C,CAAC;CACH;AAED;;;;;GAKG;AACH,wBAAgB,uBAAuB,CAAC,GAAG,EAAE,iBAAiB,GAAG,OAAO,CA+BvE;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAC/B,YAAY,EAAE,sBAAsB,GACnC,YAAY,CA2Bd;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAavE;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAEnE;AAED;;;;;GAKG;AACH,wBAAgB,yBAAyB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAanE"}
|