@sudobility/sudojo_lib 0.0.70 → 0.0.75
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/config/authProviders.d.ts +18 -0
- package/dist/config/authProviders.d.ts.map +1 -0
- package/dist/config/authProviders.js +12 -0
- package/dist/config/authProviders.js.map +1 -0
- package/dist/config/index.d.ts +3 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +2 -0
- package/dist/config/index.js.map +1 -0
- package/dist/hooks/index.d.ts +4 -0
- package/dist/hooks/index.d.ts.map +1 -1
- package/dist/hooks/index.js +4 -0
- package/dist/hooks/index.js.map +1 -1
- package/dist/hooks/useBoardEntry.d.ts +45 -0
- package/dist/hooks/useBoardEntry.d.ts.map +1 -0
- package/dist/hooks/useBoardEntry.js +197 -0
- package/dist/hooks/useBoardEntry.js.map +1 -0
- package/dist/hooks/useGamePlay.d.ts.map +1 -1
- package/dist/hooks/useGamePlay.js +23 -13
- package/dist/hooks/useGamePlay.js.map +1 -1
- package/dist/hooks/useGameSession.d.ts +45 -0
- package/dist/hooks/useGameSession.d.ts.map +1 -0
- package/dist/hooks/useGameSession.js +108 -0
- package/dist/hooks/useGameSession.js.map +1 -0
- package/dist/hooks/useLevelGame.d.ts +2 -0
- package/dist/hooks/useLevelGame.d.ts.map +1 -1
- package/dist/hooks/useLevelGame.js +3 -2
- package/dist/hooks/useLevelGame.js.map +1 -1
- package/dist/index.d.ts +8 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +11 -1
- package/dist/index.js.map +1 -1
- package/dist/utils/digitDisplay.d.ts +14 -0
- package/dist/utils/digitDisplay.d.ts.map +1 -0
- package/dist/utils/digitDisplay.js +46 -0
- package/dist/utils/digitDisplay.js.map +1 -0
- package/dist/utils/hintExplanation.d.ts +18 -0
- package/dist/utils/hintExplanation.d.ts.map +1 -0
- package/dist/utils/hintExplanation.js +896 -0
- package/dist/utils/hintExplanation.js.map +1 -0
- package/dist/utils/index.d.ts +4 -0
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +5 -0
- package/dist/utils/index.js.map +1 -1
- package/dist/utils/localizedHint.d.ts +17 -0
- package/dist/utils/localizedHint.d.ts.map +1 -0
- package/dist/utils/localizedHint.js +35 -0
- package/dist/utils/localizedHint.js.map +1 -0
- package/package.json +5 -5
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared auth provider configuration
|
|
3
|
+
*
|
|
4
|
+
* Single source of truth for which authentication providers are enabled
|
|
5
|
+
* across all Sudojo apps (web and mobile).
|
|
6
|
+
*/
|
|
7
|
+
/** Available authentication provider types */
|
|
8
|
+
export type AuthProviderType = 'google' | 'apple' | 'email';
|
|
9
|
+
/** Configuration for enabled auth providers */
|
|
10
|
+
export interface AuthProvidersConfig {
|
|
11
|
+
/** Which providers to enable */
|
|
12
|
+
providers: AuthProviderType[];
|
|
13
|
+
/** Enable anonymous sign-in fallback */
|
|
14
|
+
enableAnonymous?: boolean;
|
|
15
|
+
}
|
|
16
|
+
/** Default auth providers config used by all apps */
|
|
17
|
+
export declare const DEFAULT_AUTH_PROVIDERS: AuthProvidersConfig;
|
|
18
|
+
//# sourceMappingURL=authProviders.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"authProviders.d.ts","sourceRoot":"","sources":["../../src/config/authProviders.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,8CAA8C;AAC9C,MAAM,MAAM,gBAAgB,GAAG,QAAQ,GAAG,OAAO,GAAG,OAAO,CAAC;AAE5D,+CAA+C;AAC/C,MAAM,WAAW,mBAAmB;IAClC,gCAAgC;IAChC,SAAS,EAAE,gBAAgB,EAAE,CAAC;IAC9B,wCAAwC;IACxC,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B;AAED,qDAAqD;AACrD,eAAO,MAAM,sBAAsB,EAAE,mBAGpC,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared auth provider configuration
|
|
3
|
+
*
|
|
4
|
+
* Single source of truth for which authentication providers are enabled
|
|
5
|
+
* across all Sudojo apps (web and mobile).
|
|
6
|
+
*/
|
|
7
|
+
/** Default auth providers config used by all apps */
|
|
8
|
+
export const DEFAULT_AUTH_PROVIDERS = {
|
|
9
|
+
providers: ['google', 'email'],
|
|
10
|
+
enableAnonymous: true,
|
|
11
|
+
};
|
|
12
|
+
//# sourceMappingURL=authProviders.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"authProviders.js","sourceRoot":"","sources":["../../src/config/authProviders.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAaH,qDAAqD;AACrD,MAAM,CAAC,MAAM,sBAAsB,GAAwB;IACzD,SAAS,EAAE,CAAC,QAAQ,EAAE,OAAO,CAAC;IAC9B,eAAe,EAAE,IAAI;CACtB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/config/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AAC7E,OAAO,EAAE,sBAAsB,EAAE,MAAM,iBAAiB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/config/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,sBAAsB,EAAE,MAAM,iBAAiB,CAAC"}
|
package/dist/hooks/index.d.ts
CHANGED
|
@@ -26,4 +26,8 @@ export { useHint } from './useHint';
|
|
|
26
26
|
export type { UseHintOptions, UseHintResult, HintBoardData, HintReceivedData, HintAccessError, } from './useHint';
|
|
27
27
|
export { useGamePlay } from './useGamePlay';
|
|
28
28
|
export type { UseGamePlayOptions, UseGamePlayResult } from './useGamePlay';
|
|
29
|
+
export { useBoardEntry } from './useBoardEntry';
|
|
30
|
+
export type { UseBoardEntryOptions, UseBoardEntryReturn, ValidatedPuzzle, } from './useBoardEntry';
|
|
31
|
+
export { useGameSession } from './useGameSession';
|
|
32
|
+
export type { UseGameSessionOptions, GameSessionResult, GameFinishResult, } from './useGameSession';
|
|
29
33
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/hooks/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAClD,YAAY,EACV,eAAe,EACf,cAAc,EACd,gBAAgB,EAChB,eAAe,GAChB,MAAM,aAAa,CAAC;AAGrB,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAC9D,YAAY,EACV,mBAAmB,EACnB,kBAAkB,EAClB,oBAAoB,EACpB,mBAAmB,GACpB,MAAM,iBAAiB,CAAC;AAGzB,OAAO,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAC7D,YAAY,EACV,sBAAsB,EACtB,qBAAqB,EACrB,kBAAkB,EAClB,iBAAiB,GAClB,MAAM,eAAe,CAAC;AAGvB,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,YAAY,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAG/D,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,YAAY,EACV,sBAAsB,EACtB,qBAAqB,GACtB,MAAM,mBAAmB,CAAC;AAG3B,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,YAAY,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAGrE,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,YAAY,EACV,mBAAmB,EACnB,kBAAkB,EAClB,eAAe,GAChB,MAAM,gBAAgB,CAAC;AAExB,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,YAAY,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AAG9E,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,YAAY,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AAG9E,OAAO,EAAE,kBAAkB,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACvE,YAAY,EACV,yBAAyB,EACzB,wBAAwB,GACzB,MAAM,sBAAsB,CAAC;AAG9B,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAGpD,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,YAAY,EACV,cAAc,EACd,aAAa,EACb,aAAa,EACb,gBAAgB,EAChB,eAAe,GAChB,MAAM,WAAW,CAAC;AAGnB,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,YAAY,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/hooks/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAClD,YAAY,EACV,eAAe,EACf,cAAc,EACd,gBAAgB,EAChB,eAAe,GAChB,MAAM,aAAa,CAAC;AAGrB,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAC9D,YAAY,EACV,mBAAmB,EACnB,kBAAkB,EAClB,oBAAoB,EACpB,mBAAmB,GACpB,MAAM,iBAAiB,CAAC;AAGzB,OAAO,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAC7D,YAAY,EACV,sBAAsB,EACtB,qBAAqB,EACrB,kBAAkB,EAClB,iBAAiB,GAClB,MAAM,eAAe,CAAC;AAGvB,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,YAAY,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAG/D,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,YAAY,EACV,sBAAsB,EACtB,qBAAqB,GACtB,MAAM,mBAAmB,CAAC;AAG3B,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,YAAY,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAGrE,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,YAAY,EACV,mBAAmB,EACnB,kBAAkB,EAClB,eAAe,GAChB,MAAM,gBAAgB,CAAC;AAExB,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,YAAY,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AAG9E,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,YAAY,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AAG9E,OAAO,EAAE,kBAAkB,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACvE,YAAY,EACV,yBAAyB,EACzB,wBAAwB,GACzB,MAAM,sBAAsB,CAAC;AAG9B,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAGpD,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,YAAY,EACV,cAAc,EACd,aAAa,EACb,aAAa,EACb,gBAAgB,EAChB,eAAe,GAChB,MAAM,WAAW,CAAC;AAGnB,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,YAAY,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAG3E,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,YAAY,EACV,oBAAoB,EACpB,mBAAmB,EACnB,eAAe,GAChB,MAAM,iBAAiB,CAAC;AAGzB,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,YAAY,EACV,qBAAqB,EACrB,iBAAiB,EACjB,gBAAgB,GACjB,MAAM,kBAAkB,CAAC"}
|
package/dist/hooks/index.js
CHANGED
|
@@ -26,4 +26,8 @@ export { useLocalStorage } from './useLocalStorage';
|
|
|
26
26
|
export { useHint } from './useHint';
|
|
27
27
|
// Game play hook (current game management)
|
|
28
28
|
export { useGamePlay } from './useGamePlay';
|
|
29
|
+
// Board entry hook
|
|
30
|
+
export { useBoardEntry } from './useBoardEntry';
|
|
31
|
+
// Game session hook
|
|
32
|
+
export { useGameSession } from './useGameSession';
|
|
29
33
|
//# sourceMappingURL=index.js.map
|
package/dist/hooks/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/hooks/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,eAAe;AACf,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAQlD,mBAAmB;AACnB,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAQ9D,iBAAiB;AACjB,OAAO,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAQ7D,sBAAsB;AACtB,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAGpC,iBAAiB;AACjB,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAMpD,wCAAwC;AACxC,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAGxC,wDAAwD;AACxD,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAO9C,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAG9C,kBAAkB;AAClB,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAG9C,yBAAyB;AACzB,OAAO,EAAE,kBAAkB,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAMvE,qBAAqB;AACrB,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAEpD,YAAY;AACZ,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AASpC,2CAA2C;AAC3C,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/hooks/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,eAAe;AACf,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAQlD,mBAAmB;AACnB,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAQ9D,iBAAiB;AACjB,OAAO,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAQ7D,sBAAsB;AACtB,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAGpC,iBAAiB;AACjB,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAMpD,wCAAwC;AACxC,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAGxC,wDAAwD;AACxD,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAO9C,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAG9C,kBAAkB;AAClB,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAG9C,yBAAyB;AACzB,OAAO,EAAE,kBAAkB,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAMvE,qBAAqB;AACrB,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAEpD,YAAY;AACZ,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AASpC,2CAA2C;AAC3C,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAG5C,mBAAmB;AACnB,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAOhD,oBAAoB;AACpB,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hook for managing Sudoku board entry mode state
|
|
3
|
+
* Allows users to enter given clues for a custom puzzle
|
|
4
|
+
*/
|
|
5
|
+
import type { SudokuCell } from '../types';
|
|
6
|
+
import type { NetworkClient } from '@sudobility/types';
|
|
7
|
+
export interface ValidatedPuzzle {
|
|
8
|
+
puzzle: string;
|
|
9
|
+
solution: string;
|
|
10
|
+
}
|
|
11
|
+
export interface UseBoardEntryOptions {
|
|
12
|
+
networkClient: NetworkClient;
|
|
13
|
+
baseUrl: string;
|
|
14
|
+
token: string;
|
|
15
|
+
}
|
|
16
|
+
export interface UseBoardEntryReturn {
|
|
17
|
+
/** 81 cells with given values only */
|
|
18
|
+
cells: SudokuCell[];
|
|
19
|
+
/** Currently selected cell index */
|
|
20
|
+
selectedIndex: number | null;
|
|
21
|
+
/** Whether validation is in progress */
|
|
22
|
+
isValidating: boolean;
|
|
23
|
+
/** Validation error message key */
|
|
24
|
+
validationError: string | null;
|
|
25
|
+
/** Validated puzzle data (puzzle + solution) */
|
|
26
|
+
validatedPuzzle: ValidatedPuzzle | null;
|
|
27
|
+
/** Select a cell by index */
|
|
28
|
+
selectCell: (index: number) => void;
|
|
29
|
+
/** Set a given value at the selected cell */
|
|
30
|
+
setGiven: (value: number) => void;
|
|
31
|
+
/** Erase the selected cell */
|
|
32
|
+
erase: () => void;
|
|
33
|
+
/** Get the puzzle as an 81-character string */
|
|
34
|
+
getPuzzleString: () => string;
|
|
35
|
+
/** Trigger validation */
|
|
36
|
+
validate: () => void;
|
|
37
|
+
/** Reset to empty board */
|
|
38
|
+
reset: () => void;
|
|
39
|
+
/** Number of clues entered */
|
|
40
|
+
clueCount: number;
|
|
41
|
+
/** Set cells from an 81-character puzzle string */
|
|
42
|
+
setCellsFromPuzzle: (puzzle: string) => void;
|
|
43
|
+
}
|
|
44
|
+
export declare function useBoardEntry({ networkClient, baseUrl, token, }: UseBoardEntryOptions): UseBoardEntryReturn;
|
|
45
|
+
//# sourceMappingURL=useBoardEntry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useBoardEntry.d.ts","sourceRoot":"","sources":["../../src/hooks/useBoardEntry.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAE3C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAEvD,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,oBAAoB;IACnC,aAAa,EAAE,aAAa,CAAC;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,mBAAmB;IAClC,sCAAsC;IACtC,KAAK,EAAE,UAAU,EAAE,CAAC;IACpB,oCAAoC;IACpC,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,wCAAwC;IACxC,YAAY,EAAE,OAAO,CAAC;IACtB,mCAAmC;IACnC,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,gDAAgD;IAChD,eAAe,EAAE,eAAe,GAAG,IAAI,CAAC;IACxC,6BAA6B;IAC7B,UAAU,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACpC,6CAA6C;IAC7C,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,8BAA8B;IAC9B,KAAK,EAAE,MAAM,IAAI,CAAC;IAClB,+CAA+C;IAC/C,eAAe,EAAE,MAAM,MAAM,CAAC;IAC9B,yBAAyB;IACzB,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,2BAA2B;IAC3B,KAAK,EAAE,MAAM,IAAI,CAAC;IAClB,8BAA8B;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,mDAAmD;IACnD,kBAAkB,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;CAC9C;AAsDD,wBAAgB,aAAa,CAAC,EAC5B,aAAa,EACb,OAAO,EACP,KAAK,GACN,EAAE,oBAAoB,GAAG,mBAAmB,CAoK5C"}
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hook for managing Sudoku board entry mode state
|
|
3
|
+
* Allows users to enter given clues for a custom puzzle
|
|
4
|
+
*/
|
|
5
|
+
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
6
|
+
import { useSolverValidate } from '@sudobility/sudojo_client';
|
|
7
|
+
/**
|
|
8
|
+
* Create an empty 81-cell board for entry mode
|
|
9
|
+
*/
|
|
10
|
+
function createEmptyBoard() {
|
|
11
|
+
return Array.from({ length: 81 }, (_, index) => ({
|
|
12
|
+
index,
|
|
13
|
+
solution: null,
|
|
14
|
+
given: null,
|
|
15
|
+
input: null,
|
|
16
|
+
pencilmarks: null,
|
|
17
|
+
}));
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Convert cells to 81-character puzzle string
|
|
21
|
+
* '0' for empty, '1'-'9' for given values
|
|
22
|
+
*/
|
|
23
|
+
function cellsToPuzzleString(cells) {
|
|
24
|
+
return cells.map(cell => cell.given?.toString() ?? '0').join('');
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Count the number of non-empty cells (clues)
|
|
28
|
+
*/
|
|
29
|
+
function countClues(cells) {
|
|
30
|
+
return cells.filter(cell => cell.given !== null).length;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Create a board from an 81-character puzzle string
|
|
34
|
+
* '0' or '.' for empty, '1'-'9' for given values
|
|
35
|
+
*/
|
|
36
|
+
function puzzleStringToCells(puzzle) {
|
|
37
|
+
if (puzzle.length !== 81) {
|
|
38
|
+
return createEmptyBoard();
|
|
39
|
+
}
|
|
40
|
+
return Array.from({ length: 81 }, (_, index) => {
|
|
41
|
+
const char = puzzle.charAt(index);
|
|
42
|
+
const value = parseInt(char, 10);
|
|
43
|
+
const given = value >= 1 && value <= 9 ? value : null;
|
|
44
|
+
return {
|
|
45
|
+
index,
|
|
46
|
+
solution: null,
|
|
47
|
+
given,
|
|
48
|
+
input: null,
|
|
49
|
+
pencilmarks: null,
|
|
50
|
+
};
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
export function useBoardEntry({ networkClient, baseUrl, token, }) {
|
|
54
|
+
const [cells, setCells] = useState(createEmptyBoard);
|
|
55
|
+
const [selectedIndex, setSelectedIndex] = useState(null);
|
|
56
|
+
const [validationError, setValidationError] = useState(null);
|
|
57
|
+
const [validatedPuzzle, setValidatedPuzzle] = useState(null);
|
|
58
|
+
const [shouldValidate, setShouldValidate] = useState(false);
|
|
59
|
+
// Compute puzzle string for validation
|
|
60
|
+
const puzzleString = useMemo(() => cellsToPuzzleString(cells), [cells]);
|
|
61
|
+
const clueCount = useMemo(() => countClues(cells), [cells]);
|
|
62
|
+
// Use the solver validate hook
|
|
63
|
+
const { data: validateData, isLoading: isValidating } = useSolverValidate(networkClient, baseUrl, token, { original: puzzleString }, {
|
|
64
|
+
enabled: shouldValidate && clueCount >= 17,
|
|
65
|
+
retry: false,
|
|
66
|
+
});
|
|
67
|
+
// Track whether we've already processed this validation result
|
|
68
|
+
const processedDataRef = useRef(null);
|
|
69
|
+
// Handle validation result
|
|
70
|
+
useEffect(() => {
|
|
71
|
+
if (!shouldValidate || isValidating)
|
|
72
|
+
return;
|
|
73
|
+
if (!validateData)
|
|
74
|
+
return;
|
|
75
|
+
// Avoid re-processing the same result
|
|
76
|
+
if (processedDataRef.current === validateData)
|
|
77
|
+
return;
|
|
78
|
+
processedDataRef.current = validateData;
|
|
79
|
+
// ValidateData has board.solution
|
|
80
|
+
const solution = validateData.data?.board?.solution;
|
|
81
|
+
if (validateData.success && solution) {
|
|
82
|
+
setValidatedPuzzle({
|
|
83
|
+
puzzle: puzzleString,
|
|
84
|
+
solution,
|
|
85
|
+
});
|
|
86
|
+
setValidationError(null);
|
|
87
|
+
}
|
|
88
|
+
else if (validateData.error) {
|
|
89
|
+
// Validation failed with specific error
|
|
90
|
+
const errorMsg = validateData.error.toLowerCase();
|
|
91
|
+
if (errorMsg.includes('multiple') || errorMsg.includes('not unique')) {
|
|
92
|
+
setValidationError('enter.errors.multipleSolutions');
|
|
93
|
+
}
|
|
94
|
+
else if (errorMsg.includes('cannot solve') ||
|
|
95
|
+
errorMsg.includes('no solution')) {
|
|
96
|
+
setValidationError('enter.errors.noSolution');
|
|
97
|
+
}
|
|
98
|
+
else {
|
|
99
|
+
setValidationError('enter.errors.validationFailed');
|
|
100
|
+
}
|
|
101
|
+
setValidatedPuzzle(null);
|
|
102
|
+
}
|
|
103
|
+
else {
|
|
104
|
+
// Unexpected response - success but no solution
|
|
105
|
+
console.error('Unexpected validation response:', validateData);
|
|
106
|
+
setValidationError('enter.errors.validationFailed');
|
|
107
|
+
setValidatedPuzzle(null);
|
|
108
|
+
}
|
|
109
|
+
setShouldValidate(false);
|
|
110
|
+
}, [validateData, shouldValidate, isValidating, puzzleString]);
|
|
111
|
+
// Select a cell
|
|
112
|
+
const selectCell = useCallback((index) => {
|
|
113
|
+
if (index >= 0 && index < 81) {
|
|
114
|
+
setSelectedIndex(index);
|
|
115
|
+
}
|
|
116
|
+
}, []);
|
|
117
|
+
// Set a given value at the selected cell
|
|
118
|
+
const setGiven = useCallback((value) => {
|
|
119
|
+
if (selectedIndex === null || value < 1 || value > 9)
|
|
120
|
+
return;
|
|
121
|
+
setCells(prevCells => {
|
|
122
|
+
const newCells = [...prevCells];
|
|
123
|
+
const existing = newCells[selectedIndex];
|
|
124
|
+
if (existing) {
|
|
125
|
+
newCells[selectedIndex] = { ...existing, given: value };
|
|
126
|
+
}
|
|
127
|
+
return newCells;
|
|
128
|
+
});
|
|
129
|
+
// Clear validation state when board changes
|
|
130
|
+
setValidationError(null);
|
|
131
|
+
setValidatedPuzzle(null);
|
|
132
|
+
}, [selectedIndex]);
|
|
133
|
+
// Erase the selected cell
|
|
134
|
+
const erase = useCallback(() => {
|
|
135
|
+
if (selectedIndex === null)
|
|
136
|
+
return;
|
|
137
|
+
setCells(prevCells => {
|
|
138
|
+
const newCells = [...prevCells];
|
|
139
|
+
const existing = newCells[selectedIndex];
|
|
140
|
+
if (existing) {
|
|
141
|
+
newCells[selectedIndex] = { ...existing, given: null };
|
|
142
|
+
}
|
|
143
|
+
return newCells;
|
|
144
|
+
});
|
|
145
|
+
// Clear validation state when board changes
|
|
146
|
+
setValidationError(null);
|
|
147
|
+
setValidatedPuzzle(null);
|
|
148
|
+
}, [selectedIndex]);
|
|
149
|
+
// Get puzzle string
|
|
150
|
+
const getPuzzleString = useCallback(() => {
|
|
151
|
+
return puzzleString;
|
|
152
|
+
}, [puzzleString]);
|
|
153
|
+
// Trigger validation
|
|
154
|
+
const validate = useCallback(() => {
|
|
155
|
+
// Check minimum clues
|
|
156
|
+
if (clueCount < 17) {
|
|
157
|
+
setValidationError('enter.errors.notEnoughClues');
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
// Clear previous state and trigger validation
|
|
161
|
+
setValidationError(null);
|
|
162
|
+
setValidatedPuzzle(null);
|
|
163
|
+
setShouldValidate(true);
|
|
164
|
+
}, [clueCount]);
|
|
165
|
+
// Reset to empty board
|
|
166
|
+
const reset = useCallback(() => {
|
|
167
|
+
setCells(createEmptyBoard());
|
|
168
|
+
setSelectedIndex(null);
|
|
169
|
+
setValidationError(null);
|
|
170
|
+
setValidatedPuzzle(null);
|
|
171
|
+
setShouldValidate(false);
|
|
172
|
+
}, []);
|
|
173
|
+
// Set cells from puzzle string
|
|
174
|
+
const setCellsFromPuzzle = useCallback((puzzle) => {
|
|
175
|
+
setCells(puzzleStringToCells(puzzle));
|
|
176
|
+
setSelectedIndex(null);
|
|
177
|
+
setValidationError(null);
|
|
178
|
+
setValidatedPuzzle(null);
|
|
179
|
+
setShouldValidate(false);
|
|
180
|
+
}, []);
|
|
181
|
+
return {
|
|
182
|
+
cells,
|
|
183
|
+
selectedIndex,
|
|
184
|
+
isValidating,
|
|
185
|
+
validationError,
|
|
186
|
+
validatedPuzzle,
|
|
187
|
+
selectCell,
|
|
188
|
+
setGiven,
|
|
189
|
+
erase,
|
|
190
|
+
getPuzzleString,
|
|
191
|
+
validate,
|
|
192
|
+
reset,
|
|
193
|
+
clueCount,
|
|
194
|
+
setCellsFromPuzzle,
|
|
195
|
+
};
|
|
196
|
+
}
|
|
197
|
+
//# sourceMappingURL=useBoardEntry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useBoardEntry.js","sourceRoot":"","sources":["../../src/hooks/useBoardEntry.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useGamePlay.d.ts","sourceRoot":"","sources":["../../src/hooks/useGamePlay.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAIH,OAAO,KAAK,EACV,WAAW,EACX,eAAe,EACf,QAAQ,EACR,UAAU,EACX,MAAM,sBAAsB,CAAC;AAE9B,MAAM,WAAW,kBAAkB;IACjC,+CAA+C;IAC/C,IAAI,CAAC,EAAE,QAAQ,CAAC;IAChB,yDAAyD;IACzD,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,iBAAiB;IAChC,wCAAwC;IACxC,WAAW,EAAE,WAAW,GAAG,IAAI,CAAC;IAChC,qCAAqC;IACrC,cAAc,EAAE,OAAO,CAAC;IACxB,uBAAuB;IACvB,SAAS,EAAE,CACT,MAAM,EAAE,UAAU,EAClB,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,EAChB,IAAI,CAAC,EAAE,eAAe,KACnB,IAAI,CAAC;IACV,6CAA6C;IAC7C,cAAc,EAAE,CACd,WAAW,EAAE,MAAM,EACnB,iBAAiB,EAAE,MAAM,EACzB,YAAY,EAAE,OAAO,EACrB,WAAW,EAAE,MAAM,KAChB,IAAI,CAAC;IACV,8CAA8C;IAC9C,SAAS,EAAE,MAAM,IAAI,CAAC;CACvB;AAED,wBAAgB,WAAW,CACzB,OAAO,GAAE,kBAAuB,GAC/B,iBAAiB,
|
|
1
|
+
{"version":3,"file":"useGamePlay.d.ts","sourceRoot":"","sources":["../../src/hooks/useGamePlay.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAIH,OAAO,KAAK,EACV,WAAW,EACX,eAAe,EACf,QAAQ,EACR,UAAU,EACX,MAAM,sBAAsB,CAAC;AAE9B,MAAM,WAAW,kBAAkB;IACjC,+CAA+C;IAC/C,IAAI,CAAC,EAAE,QAAQ,CAAC;IAChB,yDAAyD;IACzD,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,iBAAiB;IAChC,wCAAwC;IACxC,WAAW,EAAE,WAAW,GAAG,IAAI,CAAC;IAChC,qCAAqC;IACrC,cAAc,EAAE,OAAO,CAAC;IACxB,uBAAuB;IACvB,SAAS,EAAE,CACT,MAAM,EAAE,UAAU,EAClB,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,EAChB,IAAI,CAAC,EAAE,eAAe,KACnB,IAAI,CAAC;IACV,6CAA6C;IAC7C,cAAc,EAAE,CACd,WAAW,EAAE,MAAM,EACnB,iBAAiB,EAAE,MAAM,EACzB,YAAY,EAAE,OAAO,EACrB,WAAW,EAAE,MAAM,KAChB,IAAI,CAAC;IACV,8CAA8C;IAC9C,SAAS,EAAE,MAAM,IAAI,CAAC;CACvB;AAED,wBAAgB,WAAW,CACzB,OAAO,GAAE,kBAAuB,GAC/B,iBAAiB,CA6FnB"}
|
|
@@ -37,7 +37,9 @@ export function useGamePlay(options = {}) {
|
|
|
37
37
|
const clearGame = useCallback(() => {
|
|
38
38
|
useGamePlayStore.getState().clearGame(slot);
|
|
39
39
|
}, [slot]);
|
|
40
|
-
//
|
|
40
|
+
// Throttled update — saves at most every autoSaveDelay ms.
|
|
41
|
+
// Unlike debounce, throttle ensures periodic saves even when called
|
|
42
|
+
// continuously (e.g. every second from the game timer).
|
|
41
43
|
const updateProgress = useCallback((inputString, pencilmarksString, isPencilMode, elapsedTime) => {
|
|
42
44
|
pendingUpdate.current = [
|
|
43
45
|
inputString,
|
|
@@ -45,30 +47,38 @@ export function useGamePlay(options = {}) {
|
|
|
45
47
|
isPencilMode,
|
|
46
48
|
elapsedTime,
|
|
47
49
|
];
|
|
48
|
-
if (
|
|
49
|
-
|
|
50
|
+
// Only start a new timer if one isn't already running (throttle)
|
|
51
|
+
if (!timeoutRef.current) {
|
|
52
|
+
timeoutRef.current = setTimeout(() => {
|
|
53
|
+
if (pendingUpdate.current) {
|
|
54
|
+
useGamePlayStore
|
|
55
|
+
.getState()
|
|
56
|
+
.updateProgress(slot, ...pendingUpdate.current);
|
|
57
|
+
pendingUpdate.current = null;
|
|
58
|
+
}
|
|
59
|
+
timeoutRef.current = null;
|
|
60
|
+
}, autoSaveDelay);
|
|
50
61
|
}
|
|
51
|
-
timeoutRef.current = setTimeout(() => {
|
|
52
|
-
if (pendingUpdate.current) {
|
|
53
|
-
useGamePlayStore
|
|
54
|
-
.getState()
|
|
55
|
-
.updateProgress(slot, ...pendingUpdate.current);
|
|
56
|
-
pendingUpdate.current = null;
|
|
57
|
-
}
|
|
58
|
-
}, autoSaveDelay);
|
|
59
62
|
}, [slot, autoSaveDelay]);
|
|
60
|
-
// Flush pending updates on unmount
|
|
63
|
+
// Flush pending updates on unmount and beforeunload
|
|
61
64
|
useEffect(() => {
|
|
62
|
-
|
|
65
|
+
const flush = () => {
|
|
63
66
|
if (timeoutRef.current) {
|
|
64
67
|
clearTimeout(timeoutRef.current);
|
|
68
|
+
timeoutRef.current = null;
|
|
65
69
|
}
|
|
66
70
|
if (pendingUpdate.current) {
|
|
67
71
|
useGamePlayStore
|
|
68
72
|
.getState()
|
|
69
73
|
.updateProgress(slot, ...pendingUpdate.current);
|
|
74
|
+
pendingUpdate.current = null;
|
|
70
75
|
}
|
|
71
76
|
};
|
|
77
|
+
window.addEventListener('beforeunload', flush);
|
|
78
|
+
return () => {
|
|
79
|
+
window.removeEventListener('beforeunload', flush);
|
|
80
|
+
flush();
|
|
81
|
+
};
|
|
72
82
|
}, [slot]);
|
|
73
83
|
return {
|
|
74
84
|
currentGame,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useGamePlay.js","sourceRoot":"","sources":["../../src/hooks/useGamePlay.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,OAAO,CAAC;AACvD,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAsC3D,MAAM,UAAU,WAAW,CACzB,UAA8B,EAAE;IAEhC,MAAM,EAAE,IAAI,GAAG,MAAM,EAAE,aAAa,GAAG,IAAI,EAAE,GAAG,OAAO,CAAC;IAExD,yCAAyC;IACzC,MAAM,WAAW,GAAG,gBAAgB,CAAC,CAAC,CAAC,EAAE,CACvC,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAC5C,CAAC;IAEF,MAAM,UAAU,GAAG,MAAM,CAAuC,IAAI,CAAC,CAAC;IACtE,MAAM,aAAa,GAAG,MAAM,CAA2C,IAAI,CAAC,CAAC;IAE7E,+DAA+D;IAC/D,MAAM,SAAS,GAAG,WAAW,CAC3B,CACE,MAAkB,EAClB,MAAc,EACd,QAAgB,EAChB,IAAsB,EACtB,EAAE;QACF,gBAAgB;aACb,QAAQ,EAAE;aACV,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,CAAC,CAAC;IACrD,CAAC,EACD,CAAC,IAAI,CAAC,CACP,CAAC;IAEF,4BAA4B;IAC5B,MAAM,SAAS,GAAG,WAAW,CAAC,GAAG,EAAE;QACjC,gBAAgB,CAAC,QAAQ,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;IAC9C,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC;IAEX,
|
|
1
|
+
{"version":3,"file":"useGamePlay.js","sourceRoot":"","sources":["../../src/hooks/useGamePlay.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hook for managing game sessions with gamification
|
|
3
|
+
*
|
|
4
|
+
* Handles:
|
|
5
|
+
* - Starting game sessions on the server
|
|
6
|
+
* - Finishing game sessions and receiving rewards
|
|
7
|
+
* - Tracking achievement results for display
|
|
8
|
+
*/
|
|
9
|
+
import type { GameFinishResponse, GameStartRequest } from '@sudobility/sudojo_types';
|
|
10
|
+
import type { NetworkClient } from '@sudobility/types';
|
|
11
|
+
export interface UseGameSessionOptions {
|
|
12
|
+
networkClient: NetworkClient;
|
|
13
|
+
baseUrl: string;
|
|
14
|
+
token: string | null;
|
|
15
|
+
userId: string | null;
|
|
16
|
+
}
|
|
17
|
+
export interface GameSessionResult {
|
|
18
|
+
/** Whether a server session was started */
|
|
19
|
+
sessionStarted: boolean;
|
|
20
|
+
/** Session ID from server (if started) */
|
|
21
|
+
sessionId?: string;
|
|
22
|
+
}
|
|
23
|
+
export interface GameFinishResult {
|
|
24
|
+
/** The full response from the server */
|
|
25
|
+
response?: GameFinishResponse;
|
|
26
|
+
/** Whether the user leveled up */
|
|
27
|
+
leveledUp: boolean;
|
|
28
|
+
/** New badges earned */
|
|
29
|
+
newBadges: Array<{
|
|
30
|
+
badgeKey: string;
|
|
31
|
+
title: string;
|
|
32
|
+
description: string | null;
|
|
33
|
+
}>;
|
|
34
|
+
/** Total points earned */
|
|
35
|
+
totalPointsEarned: number;
|
|
36
|
+
}
|
|
37
|
+
export declare function useGameSession({ networkClient, baseUrl, token, userId, }: UseGameSessionOptions): {
|
|
38
|
+
startSession: (data: GameStartRequest) => Promise<GameSessionResult>;
|
|
39
|
+
finishSession: (elapsedTime: number) => Promise<GameFinishResult>;
|
|
40
|
+
isStarting: boolean;
|
|
41
|
+
isFinishing: boolean;
|
|
42
|
+
isAuthenticated: boolean;
|
|
43
|
+
sessionId: string | null;
|
|
44
|
+
};
|
|
45
|
+
//# sourceMappingURL=useGameSession.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useGameSession.d.ts","sourceRoot":"","sources":["../../src/hooks/useGameSession.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAOH,OAAO,KAAK,EACV,kBAAkB,EAClB,gBAAgB,EACjB,MAAM,0BAA0B,CAAC;AAClC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAEvD,MAAM,WAAW,qBAAqB;IACpC,aAAa,EAAE,aAAa,CAAC;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;CACvB;AAED,MAAM,WAAW,iBAAiB;IAChC,2CAA2C;IAC3C,cAAc,EAAE,OAAO,CAAC;IACxB,0CAA0C;IAC1C,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,gBAAgB;IAC/B,wCAAwC;IACxC,QAAQ,CAAC,EAAE,kBAAkB,CAAC;IAC9B,kCAAkC;IAClC,SAAS,EAAE,OAAO,CAAC;IACnB,wBAAwB;IACxB,SAAS,EAAE,KAAK,CAAC;QACf,QAAQ,EAAE,MAAM,CAAC;QACjB,KAAK,EAAE,MAAM,CAAC;QACd,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;KAC5B,CAAC,CAAC;IACH,0BAA0B;IAC1B,iBAAiB,EAAE,MAAM,CAAC;CAC3B;AAED,wBAAgB,cAAc,CAAC,EAC7B,aAAa,EACb,OAAO,EACP,KAAK,EACL,MAAM,GACP,EAAE,qBAAqB;yBAaP,gBAAgB,KAAG,OAAO,CAAC,iBAAiB,CAAC;iCAqCtC,MAAM,KAAG,OAAO,CAAC,gBAAgB,CAAC;;;;;EA4DzD"}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hook for managing game sessions with gamification
|
|
3
|
+
*
|
|
4
|
+
* Handles:
|
|
5
|
+
* - Starting game sessions on the server
|
|
6
|
+
* - Finishing game sessions and receiving rewards
|
|
7
|
+
* - Tracking achievement results for display
|
|
8
|
+
*/
|
|
9
|
+
import { useCallback, useRef, useState } from 'react';
|
|
10
|
+
import { useSudojoPlayFinish, useSudojoPlayStart, } from '@sudobility/sudojo_client';
|
|
11
|
+
export function useGameSession({ networkClient, baseUrl, token, userId, }) {
|
|
12
|
+
const [isStarting, setIsStarting] = useState(false);
|
|
13
|
+
const [isFinishing, setIsFinishing] = useState(false);
|
|
14
|
+
const sessionIdRef = useRef(null);
|
|
15
|
+
const playStartMutation = useSudojoPlayStart(networkClient, baseUrl);
|
|
16
|
+
const playFinishMutation = useSudojoPlayFinish(networkClient, baseUrl);
|
|
17
|
+
/**
|
|
18
|
+
* Start a game session on the server
|
|
19
|
+
* Only works if user is authenticated
|
|
20
|
+
*/
|
|
21
|
+
const startSession = useCallback(async (data) => {
|
|
22
|
+
// Skip if not authenticated
|
|
23
|
+
if (!userId || !token) {
|
|
24
|
+
return { sessionStarted: false };
|
|
25
|
+
}
|
|
26
|
+
setIsStarting(true);
|
|
27
|
+
try {
|
|
28
|
+
const response = await playStartMutation.mutateAsync({
|
|
29
|
+
token,
|
|
30
|
+
data,
|
|
31
|
+
});
|
|
32
|
+
if (response.success && response.data) {
|
|
33
|
+
sessionIdRef.current = response.data.sessionId;
|
|
34
|
+
return {
|
|
35
|
+
sessionStarted: true,
|
|
36
|
+
sessionId: response.data.sessionId,
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
return { sessionStarted: false };
|
|
40
|
+
}
|
|
41
|
+
catch (error) {
|
|
42
|
+
console.error('Failed to start game session:', error);
|
|
43
|
+
return { sessionStarted: false };
|
|
44
|
+
}
|
|
45
|
+
finally {
|
|
46
|
+
setIsStarting(false);
|
|
47
|
+
}
|
|
48
|
+
}, [userId, token, playStartMutation]);
|
|
49
|
+
/**
|
|
50
|
+
* Finish the game session and get rewards
|
|
51
|
+
* Only works if user is authenticated and session was started
|
|
52
|
+
*/
|
|
53
|
+
const finishSession = useCallback(async (elapsedTime) => {
|
|
54
|
+
// Skip if not authenticated
|
|
55
|
+
if (!userId || !token) {
|
|
56
|
+
return {
|
|
57
|
+
leveledUp: false,
|
|
58
|
+
newBadges: [],
|
|
59
|
+
totalPointsEarned: 0,
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
setIsFinishing(true);
|
|
63
|
+
try {
|
|
64
|
+
const response = await playFinishMutation.mutateAsync({
|
|
65
|
+
token,
|
|
66
|
+
data: { elapsedTime },
|
|
67
|
+
});
|
|
68
|
+
sessionIdRef.current = null;
|
|
69
|
+
if (response.success && response.data) {
|
|
70
|
+
return {
|
|
71
|
+
response: response.data,
|
|
72
|
+
leveledUp: !!response.data.level,
|
|
73
|
+
newBadges: response.data.badges ?? [],
|
|
74
|
+
totalPointsEarned: response.data.points.totalPoints,
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
return {
|
|
78
|
+
leveledUp: false,
|
|
79
|
+
newBadges: [],
|
|
80
|
+
totalPointsEarned: 0,
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
catch (error) {
|
|
84
|
+
console.error('Failed to finish game session:', error);
|
|
85
|
+
return {
|
|
86
|
+
leveledUp: false,
|
|
87
|
+
newBadges: [],
|
|
88
|
+
totalPointsEarned: 0,
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
finally {
|
|
92
|
+
setIsFinishing(false);
|
|
93
|
+
}
|
|
94
|
+
}, [userId, token, playFinishMutation]);
|
|
95
|
+
/**
|
|
96
|
+
* Check if user is authenticated (can use gamification)
|
|
97
|
+
*/
|
|
98
|
+
const isAuthenticated = !!userId && !!token;
|
|
99
|
+
return {
|
|
100
|
+
startSession,
|
|
101
|
+
finishSession,
|
|
102
|
+
isStarting,
|
|
103
|
+
isFinishing,
|
|
104
|
+
isAuthenticated,
|
|
105
|
+
sessionId: sessionIdRef.current,
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
//# sourceMappingURL=useGameSession.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useGameSession.js","sourceRoot":"","sources":["../../src/hooks/useGameSession.ts"],"names":[],"mappings":"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"}
|
|
@@ -15,6 +15,8 @@ export interface UseLevelGameOptions {
|
|
|
15
15
|
token: string;
|
|
16
16
|
/** Level number (1-12) to fetch game for */
|
|
17
17
|
level: number;
|
|
18
|
+
/** Whether to fetch only symmetrical puzzles */
|
|
19
|
+
symmetrical?: boolean;
|
|
18
20
|
/** Whether subscription is currently active */
|
|
19
21
|
subscriptionActive?: boolean;
|
|
20
22
|
/** Whether to enable the query */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useLevelGame.d.ts","sourceRoot":"","sources":["../../src/hooks/useLevelGame.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,0BAA0B,CAAC;AACtD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAIvD,uDAAuD;AACvD,MAAM,MAAM,eAAe,GACvB,SAAS,GACT,SAAS,GACT,eAAe,GACf,uBAAuB,GACvB,OAAO,CAAC;AAuDZ,MAAM,WAAW,mBAAmB;IAClC,mCAAmC;IACnC,aAAa,EAAE,aAAa,CAAC;IAC7B,kCAAkC;IAClC,OAAO,EAAE,MAAM,CAAC;IAChB,sCAAsC;IACtC,KAAK,EAAE,MAAM,CAAC;IACd,4CAA4C;IAC5C,KAAK,EAAE,MAAM,CAAC;IACd,+CAA+C;IAC/C,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,kCAAkC;IAClC,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,kBAAkB;IACjC,0BAA0B;IAC1B,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IACpB,uCAAuC;IACvC,MAAM,EAAE,eAAe,CAAC;IACxB,8BAA8B;IAC9B,SAAS,EAAE,OAAO,CAAC;IACnB,4BAA4B;IAC5B,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IACpB,6BAA6B;IAC7B,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,8CAA8C;IAC9C,UAAU,EAAE,MAAM,IAAI,CAAC;CACxB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,mBAAmB,GAAG,kBAAkB,
|
|
1
|
+
{"version":3,"file":"useLevelGame.d.ts","sourceRoot":"","sources":["../../src/hooks/useLevelGame.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,0BAA0B,CAAC;AACtD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAIvD,uDAAuD;AACvD,MAAM,MAAM,eAAe,GACvB,SAAS,GACT,SAAS,GACT,eAAe,GACf,uBAAuB,GACvB,OAAO,CAAC;AAuDZ,MAAM,WAAW,mBAAmB;IAClC,mCAAmC;IACnC,aAAa,EAAE,aAAa,CAAC;IAC7B,kCAAkC;IAClC,OAAO,EAAE,MAAM,CAAC;IAChB,sCAAsC;IACtC,KAAK,EAAE,MAAM,CAAC;IACd,4CAA4C;IAC5C,KAAK,EAAE,MAAM,CAAC;IACd,gDAAgD;IAChD,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,+CAA+C;IAC/C,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,kCAAkC;IAClC,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,kBAAkB;IACjC,0BAA0B;IAC1B,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IACpB,uCAAuC;IACvC,MAAM,EAAE,eAAe,CAAC;IACxB,8BAA8B;IAC9B,SAAS,EAAE,OAAO,CAAC;IACnB,4BAA4B;IAC5B,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IACpB,6BAA6B;IAC7B,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,8CAA8C;IAC9C,UAAU,EAAE,MAAM,IAAI,CAAC;CACxB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,mBAAmB,GAAG,kBAAkB,CA8F7E"}
|
|
@@ -63,7 +63,7 @@ function isSubscriptionRequired(response, error) {
|
|
|
63
63
|
* ```
|
|
64
64
|
*/
|
|
65
65
|
export function useLevelGame(options) {
|
|
66
|
-
const { networkClient, baseUrl, token, level, subscriptionActive = false, enabled = true, } = options;
|
|
66
|
+
const { networkClient, baseUrl, token, level, symmetrical, subscriptionActive = false, enabled = true, } = options;
|
|
67
67
|
const queryClient = useQueryClient();
|
|
68
68
|
// Track previous state to detect changes
|
|
69
69
|
const prevStateRef = useRef({
|
|
@@ -72,11 +72,12 @@ export function useLevelGame(options) {
|
|
|
72
72
|
});
|
|
73
73
|
const queryParams = useMemo(() => ({
|
|
74
74
|
level,
|
|
75
|
+
symmetrical: symmetrical || undefined,
|
|
75
76
|
limit: undefined,
|
|
76
77
|
offset: undefined,
|
|
77
78
|
techniques: undefined,
|
|
78
79
|
technique_bit: undefined,
|
|
79
|
-
}), [level]);
|
|
80
|
+
}), [level, symmetrical]);
|
|
80
81
|
const { data, isLoading, error, refetch } = useSudojoRandomBoard(networkClient, baseUrl, token, queryParams, { enabled: enabled && level >= 1 && level <= 12 });
|
|
81
82
|
// Determine status based on response
|
|
82
83
|
// Cast to SudojoApiResponse to check for action field
|