@vue-skuilder/db 0.1.18 → 0.1.21
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/CLAUDE.md +2 -2
- package/dist/{classroomDB-BgfrVb8d.d.ts → contentSource-BP9hznNV.d.ts} +220 -197
- package/dist/{classroomDB-CTOenngH.d.cts → contentSource-DsJadoBU.d.cts} +220 -197
- package/dist/core/index.d.cts +80 -6
- package/dist/core/index.d.ts +80 -6
- package/dist/core/index.js +735 -1560
- package/dist/core/index.js.map +1 -1
- package/dist/core/index.mjs +708 -1539
- package/dist/core/index.mjs.map +1 -1
- package/dist/{dataLayerProvider-D6PoCwS6.d.cts → dataLayerProvider-CHYrQ5pB.d.cts} +1 -1
- package/dist/{dataLayerProvider-CZxC9GtB.d.ts → dataLayerProvider-MDTxXq2l.d.ts} +1 -1
- package/dist/impl/couch/index.d.cts +8 -23
- package/dist/impl/couch/index.d.ts +8 -23
- package/dist/impl/couch/index.js +723 -1578
- package/dist/impl/couch/index.js.map +1 -1
- package/dist/impl/couch/index.mjs +692 -1552
- package/dist/impl/couch/index.mjs.map +1 -1
- package/dist/impl/static/index.d.cts +25 -8
- package/dist/impl/static/index.d.ts +25 -8
- package/dist/impl/static/index.js +700 -1400
- package/dist/impl/static/index.js.map +1 -1
- package/dist/impl/static/index.mjs +688 -1393
- package/dist/impl/static/index.mjs.map +1 -1
- package/dist/{index-D-Fa4Smt.d.cts → index-B_j6u5E4.d.cts} +1 -1
- package/dist/{index-CD8BZz2k.d.ts → index-Dj0SEgk3.d.ts} +1 -1
- package/dist/index.d.cts +71 -63
- package/dist/index.d.ts +71 -63
- package/dist/index.js +1162 -1996
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1124 -1955
- package/dist/index.mjs.map +1 -1
- package/dist/pouch/index.js +3 -0
- package/dist/pouch/index.js.map +1 -1
- package/dist/pouch/index.mjs +3 -0
- package/dist/pouch/index.mjs.map +1 -1
- package/dist/{types-CzPDLAK6.d.cts → types-Bn0itutr.d.cts} +1 -1
- package/dist/{types-CewsN87z.d.ts → types-DQaXnuoc.d.ts} +1 -1
- package/dist/{types-legacy-6ettoclI.d.cts → types-legacy-DDY4N-Uq.d.cts} +3 -1
- package/dist/{types-legacy-6ettoclI.d.ts → types-legacy-DDY4N-Uq.d.ts} +3 -1
- package/dist/util/packer/index.d.cts +3 -3
- package/dist/util/packer/index.d.ts +3 -3
- package/docs/navigators-architecture.md +115 -17
- package/package.json +4 -4
- package/src/core/index.ts +1 -0
- package/src/core/interfaces/classroomDB.ts +5 -13
- package/src/core/interfaces/contentSource.ts +6 -66
- package/src/core/interfaces/courseDB.ts +15 -7
- package/src/core/interfaces/userDB.ts +32 -0
- package/src/core/navigators/Pipeline.ts +136 -52
- package/src/core/navigators/PipelineAssembler.ts +1 -1
- package/src/core/navigators/defaults.ts +84 -0
- package/src/core/navigators/{hierarchyDefinition.ts → filters/hierarchyDefinition.ts} +15 -29
- package/src/core/navigators/filters/index.ts +3 -0
- package/src/core/navigators/filters/inferredPreferenceStub.ts +107 -0
- package/src/core/navigators/{interferenceMitigator.ts → filters/interferenceMitigator.ts} +11 -37
- package/src/core/navigators/{relativePriority.ts → filters/relativePriority.ts} +12 -38
- package/src/core/navigators/filters/userGoalStub.ts +136 -0
- package/src/core/navigators/filters/userTagPreference.ts +217 -0
- package/src/core/navigators/{CompositeGenerator.ts → generators/CompositeGenerator.ts} +15 -64
- package/src/core/navigators/{elo.ts → generators/elo.ts} +13 -63
- package/src/core/navigators/{srs.ts → generators/srs.ts} +11 -40
- package/src/core/navigators/generators/types.ts +1 -1
- package/src/core/navigators/index.ts +95 -91
- package/src/core/types/strategyState.ts +84 -0
- package/src/core/types/types-legacy.ts +2 -0
- package/src/impl/common/BaseUserDB.ts +74 -7
- package/src/impl/couch/adminDB.ts +1 -2
- package/src/impl/couch/classroomDB.ts +100 -103
- package/src/impl/couch/courseDB.ts +35 -91
- package/src/impl/couch/pouchdb-setup.ts +7 -0
- package/src/impl/static/StaticDataUnpacker.ts +50 -1
- package/src/impl/static/courseDB.ts +87 -37
- package/src/study/SessionController.ts +122 -202
- package/src/study/SourceMixer.ts +65 -0
- package/src/study/TagFilteredContentSource.ts +49 -92
- package/src/study/index.ts +1 -0
- package/src/study/services/CardHydrationService.ts +165 -81
- package/src/util/dataDirectory.ts +1 -1
- package/src/util/index.ts +0 -1
- package/tests/core/navigators/CompositeGenerator.test.ts +44 -168
- package/tests/core/navigators/Pipeline.test.ts +6 -72
- package/tests/core/navigators/PipelineAssembler.test.ts +8 -58
- package/tests/core/navigators/navigators.test.ts +118 -151
- package/docs/todo-pipeline-optimization.md +0 -117
- package/docs/todo-strategy-state-storage.md +0 -278
- package/src/core/navigators/hardcodedOrder.ts +0 -163
- package/src/util/tuiLogger.ts +0 -139
package/CLAUDE.md
CHANGED
|
@@ -6,7 +6,7 @@ Database abstraction layer providing unified interfaces for CouchDB/PouchDB and
|
|
|
6
6
|
- Build: `yarn workspace @vue-skuilder/db build`
|
|
7
7
|
- Dev (watch): `yarn workspace @vue-skuilder/db dev`
|
|
8
8
|
- Lint: `yarn workspace @vue-skuilder/db lint:fix`
|
|
9
|
-
-
|
|
9
|
+
- Test: `yarn workspace @vue-skuilder/db test`
|
|
10
10
|
|
|
11
11
|
## Build System
|
|
12
12
|
Uses **tsup** for dual CommonJS/ESM output:
|
|
@@ -40,4 +40,4 @@ Multiple entry points for different use cases:
|
|
|
40
40
|
- **Provider Pattern**: Switchable backend implementations
|
|
41
41
|
- **Dual Export**: Works in both Node.js and browser environments
|
|
42
42
|
- **Type Safety**: Full TypeScript coverage with strict mode
|
|
43
|
-
- **Sync Strategy**: Configurable online/offline data synchronization
|
|
43
|
+
- **Sync Strategy**: Configurable online/offline data synchronization
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { CourseConfig, ClassroomConfig,
|
|
1
|
+
import { CourseConfig, ClassroomConfig, Status, SkuilderCourseData as SkuilderCourseData$1, CourseElo, DataShape, TagFilter } from '@vue-skuilder/common';
|
|
2
2
|
import { Moment } from 'moment';
|
|
3
|
-
import { S as SkuilderCourseData, b as DocTypePrefixes, D as DocType, Q as QualifiedCardID, T as TagStub, a as Tag, C as CardHistory, c as CardRecord } from './types-legacy-
|
|
3
|
+
import { S as SkuilderCourseData, b as DocTypePrefixes, D as DocType, Q as QualifiedCardID, T as TagStub, a as Tag, C as CardHistory, c as CardRecord } from './types-legacy-DDY4N-Uq.js';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* Admin functionality
|
|
@@ -26,82 +26,63 @@ interface AdminDBInterface {
|
|
|
26
26
|
})[]>;
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
firstSessionDate: string;
|
|
34
|
-
lastSessionDate: string;
|
|
35
|
-
signupPrompted: boolean;
|
|
36
|
-
promptDismissalCount: number;
|
|
37
|
-
studyModeAcknowledged: boolean;
|
|
38
|
-
}
|
|
39
|
-
interface UserConfig {
|
|
40
|
-
darkMode: boolean;
|
|
41
|
-
likesConfetti: boolean;
|
|
42
|
-
sessionTimeLimit: number;
|
|
43
|
-
email?: string;
|
|
44
|
-
sessionTracking?: Record<string, SessionTrackingData>;
|
|
45
|
-
}
|
|
46
|
-
interface ActivityRecord {
|
|
47
|
-
timeStamp: number | string;
|
|
48
|
-
[key: string]: any;
|
|
49
|
-
}
|
|
50
|
-
interface CourseRegistration {
|
|
51
|
-
status?: 'active' | 'dropped' | 'maintenance-mode' | 'preview';
|
|
52
|
-
courseID: string;
|
|
53
|
-
admin: boolean;
|
|
54
|
-
moderator: boolean;
|
|
55
|
-
user: boolean;
|
|
56
|
-
settings?: {
|
|
57
|
-
[setting: string]: string | number | boolean;
|
|
58
|
-
};
|
|
59
|
-
elo: number | CourseElo;
|
|
60
|
-
}
|
|
61
|
-
interface StudyWeights {
|
|
62
|
-
[courseID: string]: number;
|
|
63
|
-
}
|
|
64
|
-
interface CourseRegistrationDoc {
|
|
65
|
-
courses: CourseRegistration[];
|
|
66
|
-
studyWeight: StudyWeights;
|
|
67
|
-
}
|
|
68
|
-
interface ScheduledCard {
|
|
69
|
-
_id: PouchDB.Core.DocumentId;
|
|
29
|
+
/**
|
|
30
|
+
* Classroom management
|
|
31
|
+
*/
|
|
32
|
+
interface ClassroomDBInterface {
|
|
70
33
|
/**
|
|
71
|
-
*
|
|
34
|
+
* Get classroom config
|
|
72
35
|
*/
|
|
73
|
-
|
|
36
|
+
getConfig(): ClassroomConfig;
|
|
74
37
|
/**
|
|
75
|
-
*
|
|
38
|
+
* Get assigned content
|
|
76
39
|
*/
|
|
77
|
-
|
|
40
|
+
getAssignedContent(): Promise<AssignedContent[]>;
|
|
41
|
+
}
|
|
42
|
+
interface TeacherClassroomDBInterface extends ClassroomDBInterface {
|
|
78
43
|
/**
|
|
79
|
-
*
|
|
80
|
-
*
|
|
81
|
-
* (Should probably be UTC adjusted so that performance is
|
|
82
|
-
* not wonky across time zones)
|
|
83
|
-
*
|
|
84
|
-
* Note: Stored as ISO string for PouchDB serialization compatibility,
|
|
85
|
-
* but can be consumed as Moment objects via moment.utc(reviewTime)
|
|
44
|
+
* For teacher interfaces: assign content
|
|
86
45
|
*/
|
|
87
|
-
|
|
46
|
+
assignContent?(content: AssignedContent): Promise<boolean>;
|
|
88
47
|
/**
|
|
89
|
-
*
|
|
90
|
-
*
|
|
91
|
-
* Note: Stored as ISO string for PouchDB serialization compatibility,
|
|
92
|
-
* but can be consumed as Moment objects via moment.utc(scheduledAt)
|
|
48
|
+
* For teacher interfaces: remove content
|
|
93
49
|
*/
|
|
94
|
-
|
|
50
|
+
removeContent?(content: AssignedContent): Promise<void>;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Student-facing classroom interface.
|
|
54
|
+
* Content is accessed via StudyContentSource.getWeightedCards().
|
|
55
|
+
*/
|
|
56
|
+
type StudentClassroomDBInterface = ClassroomDBInterface;
|
|
57
|
+
type AssignedContent = AssignedCourse | AssignedTag | AssignedCard;
|
|
58
|
+
interface AssignedTag extends ContentBase {
|
|
59
|
+
type: 'tag';
|
|
60
|
+
tagID: string;
|
|
61
|
+
}
|
|
62
|
+
interface AssignedCourse extends ContentBase {
|
|
63
|
+
type: 'course';
|
|
64
|
+
}
|
|
65
|
+
interface AssignedCard extends ContentBase {
|
|
66
|
+
type: 'card';
|
|
67
|
+
cardID: string;
|
|
68
|
+
}
|
|
69
|
+
interface ContentBase {
|
|
70
|
+
type: 'course' | 'tag' | 'card';
|
|
95
71
|
/**
|
|
96
|
-
*
|
|
97
|
-
* user-registered course or by as assigned content from a
|
|
98
|
-
* user-registered classroom
|
|
72
|
+
* Username of the assigning teacher.
|
|
99
73
|
*/
|
|
100
|
-
|
|
74
|
+
assignedBy: string;
|
|
101
75
|
/**
|
|
102
|
-
*
|
|
76
|
+
* Date the content was assigned.
|
|
103
77
|
*/
|
|
104
|
-
|
|
78
|
+
assignedOn: moment.Moment;
|
|
79
|
+
/**
|
|
80
|
+
* A 'due' date for this assigned content, for scheduling content
|
|
81
|
+
* in advance. Content will not be actively pushed to students until
|
|
82
|
+
* this date.
|
|
83
|
+
*/
|
|
84
|
+
activeOn: moment.Moment;
|
|
85
|
+
courseID: string;
|
|
105
86
|
}
|
|
106
87
|
|
|
107
88
|
interface DataLayerResult {
|
|
@@ -178,7 +159,7 @@ interface CourseInfo {
|
|
|
178
159
|
cardCount: number;
|
|
179
160
|
registeredUsers: number;
|
|
180
161
|
}
|
|
181
|
-
interface CourseDBInterface extends NavigationStrategyManager {
|
|
162
|
+
interface CourseDBInterface extends NavigationStrategyManager, StudyContentSource {
|
|
182
163
|
/**
|
|
183
164
|
* Get course config
|
|
184
165
|
*/
|
|
@@ -207,10 +188,6 @@ interface CourseDBInterface extends NavigationStrategyManager {
|
|
|
207
188
|
* Update card ELO rating
|
|
208
189
|
*/
|
|
209
190
|
updateCardElo(cardId: string, elo: CourseElo): Promise<PouchDB.Core.Response>;
|
|
210
|
-
/**
|
|
211
|
-
* Get new cards for study
|
|
212
|
-
*/
|
|
213
|
-
getNewCards(limit?: number): Promise<StudySessionNewItem[]>;
|
|
214
191
|
/**
|
|
215
192
|
* Get cards centered at a particular ELO rating
|
|
216
193
|
*/
|
|
@@ -222,6 +199,18 @@ interface CourseDBInterface extends NavigationStrategyManager {
|
|
|
222
199
|
* Get tags for a card
|
|
223
200
|
*/
|
|
224
201
|
getAppliedTags(cardId: string): Promise<PouchDB.Query.Response<TagStub>>;
|
|
202
|
+
/**
|
|
203
|
+
* Get tags for multiple cards in a single batch query.
|
|
204
|
+
* More efficient than calling getAppliedTags() for each card.
|
|
205
|
+
*
|
|
206
|
+
* This method reduces redundant database operations when multiple filters
|
|
207
|
+
* need tag data for the same cards. The Pipeline uses this to pre-hydrate
|
|
208
|
+
* tags on WeightedCard objects before filters run.
|
|
209
|
+
*
|
|
210
|
+
* @param cardIds - Array of card IDs to fetch tags for
|
|
211
|
+
* @returns Map from cardId to array of tag names
|
|
212
|
+
*/
|
|
213
|
+
getAppliedTagsBatch(cardIds: string[]): Promise<Map<string, string[]>>;
|
|
225
214
|
/**
|
|
226
215
|
* Add a tag to a card
|
|
227
216
|
*/
|
|
@@ -273,6 +262,84 @@ interface CourseDBInterface extends NavigationStrategyManager {
|
|
|
273
262
|
find(request: PouchDB.Find.FindRequest<any>): Promise<PouchDB.Find.FindResponse<any>>;
|
|
274
263
|
}
|
|
275
264
|
|
|
265
|
+
interface SessionTrackingData {
|
|
266
|
+
peekSessionCount: number;
|
|
267
|
+
studySessionCount: number;
|
|
268
|
+
sessionCount: number;
|
|
269
|
+
firstSessionDate: string;
|
|
270
|
+
lastSessionDate: string;
|
|
271
|
+
signupPrompted: boolean;
|
|
272
|
+
promptDismissalCount: number;
|
|
273
|
+
studyModeAcknowledged: boolean;
|
|
274
|
+
}
|
|
275
|
+
interface UserConfig {
|
|
276
|
+
darkMode: boolean;
|
|
277
|
+
likesConfetti: boolean;
|
|
278
|
+
sessionTimeLimit: number;
|
|
279
|
+
email?: string;
|
|
280
|
+
sessionTracking?: Record<string, SessionTrackingData>;
|
|
281
|
+
}
|
|
282
|
+
interface ActivityRecord {
|
|
283
|
+
timeStamp: number | string;
|
|
284
|
+
[key: string]: any;
|
|
285
|
+
}
|
|
286
|
+
interface CourseRegistration {
|
|
287
|
+
status?: 'active' | 'dropped' | 'maintenance-mode' | 'preview';
|
|
288
|
+
courseID: string;
|
|
289
|
+
admin: boolean;
|
|
290
|
+
moderator: boolean;
|
|
291
|
+
user: boolean;
|
|
292
|
+
settings?: {
|
|
293
|
+
[setting: string]: string | number | boolean;
|
|
294
|
+
};
|
|
295
|
+
elo: number | CourseElo;
|
|
296
|
+
}
|
|
297
|
+
interface StudyWeights {
|
|
298
|
+
[courseID: string]: number;
|
|
299
|
+
}
|
|
300
|
+
interface CourseRegistrationDoc {
|
|
301
|
+
courses: CourseRegistration[];
|
|
302
|
+
studyWeight: StudyWeights;
|
|
303
|
+
}
|
|
304
|
+
interface ScheduledCard {
|
|
305
|
+
_id: PouchDB.Core.DocumentId;
|
|
306
|
+
/**
|
|
307
|
+
* The docID of the card to be reviewed
|
|
308
|
+
*/
|
|
309
|
+
cardId: PouchDB.Core.DocumentId;
|
|
310
|
+
/**
|
|
311
|
+
* The ID of the course
|
|
312
|
+
*/
|
|
313
|
+
courseId: string;
|
|
314
|
+
/**
|
|
315
|
+
* The time at which the card becomes eligible for review.
|
|
316
|
+
*
|
|
317
|
+
* (Should probably be UTC adjusted so that performance is
|
|
318
|
+
* not wonky across time zones)
|
|
319
|
+
*
|
|
320
|
+
* Note: Stored as ISO string for PouchDB serialization compatibility,
|
|
321
|
+
* but can be consumed as Moment objects via moment.utc(reviewTime)
|
|
322
|
+
*/
|
|
323
|
+
reviewTime: string | Moment;
|
|
324
|
+
/**
|
|
325
|
+
* The time at which this scheduled event was created.
|
|
326
|
+
*
|
|
327
|
+
* Note: Stored as ISO string for PouchDB serialization compatibility,
|
|
328
|
+
* but can be consumed as Moment objects via moment.utc(scheduledAt)
|
|
329
|
+
*/
|
|
330
|
+
scheduledAt: string | Moment;
|
|
331
|
+
/**
|
|
332
|
+
* Classifying whether this card is scheduled on behalf of a
|
|
333
|
+
* user-registered course or by as assigned content from a
|
|
334
|
+
* user-registered classroom
|
|
335
|
+
*/
|
|
336
|
+
scheduledFor: 'course' | 'classroom';
|
|
337
|
+
/**
|
|
338
|
+
* The ID of the course or classroom that requested this card
|
|
339
|
+
*/
|
|
340
|
+
schedulingAgentId: string;
|
|
341
|
+
}
|
|
342
|
+
|
|
276
343
|
type Update<T> = Partial<T> | ((x: T) => T);
|
|
277
344
|
|
|
278
345
|
interface DocumentUpdater {
|
|
@@ -323,6 +390,17 @@ interface UserDBReader {
|
|
|
323
390
|
*/
|
|
324
391
|
getPendingReviews(courseId?: string): Promise<ScheduledCard[]>;
|
|
325
392
|
getActivityRecords(): Promise<ActivityRecord[]>;
|
|
393
|
+
/**
|
|
394
|
+
* Get strategy-specific state for a course.
|
|
395
|
+
*
|
|
396
|
+
* Strategies use this to persist preferences, learned patterns, or temporal
|
|
397
|
+
* tracking data across sessions. Each strategy owns its own namespace.
|
|
398
|
+
*
|
|
399
|
+
* @param courseId - The course this state applies to
|
|
400
|
+
* @param strategyKey - Unique key identifying the strategy (typically class name)
|
|
401
|
+
* @returns The strategy's data payload, or null if no state exists
|
|
402
|
+
*/
|
|
403
|
+
getStrategyState<T>(courseId: string, strategyKey: string): Promise<T | null>;
|
|
326
404
|
/**
|
|
327
405
|
* Get user's classroom registrations
|
|
328
406
|
*/
|
|
@@ -387,6 +465,24 @@ interface UserDBWriter extends DocumentUpdater {
|
|
|
387
465
|
status: Status;
|
|
388
466
|
error?: string;
|
|
389
467
|
}>;
|
|
468
|
+
/**
|
|
469
|
+
* Store strategy-specific state for a course.
|
|
470
|
+
*
|
|
471
|
+
* Strategies use this to persist preferences, learned patterns, or temporal
|
|
472
|
+
* tracking data across sessions. Each strategy owns its own namespace.
|
|
473
|
+
*
|
|
474
|
+
* @param courseId - The course this state applies to
|
|
475
|
+
* @param strategyKey - Unique key identifying the strategy (typically class name)
|
|
476
|
+
* @param data - The strategy's data payload to store
|
|
477
|
+
*/
|
|
478
|
+
putStrategyState<T>(courseId: string, strategyKey: string, data: T): Promise<void>;
|
|
479
|
+
/**
|
|
480
|
+
* Delete strategy-specific state for a course.
|
|
481
|
+
*
|
|
482
|
+
* @param courseId - The course this state applies to
|
|
483
|
+
* @param strategyKey - Unique key identifying the strategy (typically class name)
|
|
484
|
+
*/
|
|
485
|
+
deleteStrategyState(courseId: string, strategyKey: string): Promise<void>;
|
|
390
486
|
}
|
|
391
487
|
/**
|
|
392
488
|
* Authentication and account management operations
|
|
@@ -524,6 +620,17 @@ interface WeightedCard {
|
|
|
524
620
|
* First entry is from the generator, subsequent entries from filters.
|
|
525
621
|
*/
|
|
526
622
|
provenance: StrategyContribution[];
|
|
623
|
+
/**
|
|
624
|
+
* Pre-fetched tags. Populated by Pipeline before filters run.
|
|
625
|
+
* Filters should use this instead of querying getAppliedTags() individually.
|
|
626
|
+
*/
|
|
627
|
+
tags?: string[];
|
|
628
|
+
/**
|
|
629
|
+
* Review document ID (_id from ScheduledCard).
|
|
630
|
+
* Present when this card originated from SRS review scheduling.
|
|
631
|
+
* Used by SessionController to track review outcomes and maintain review state.
|
|
632
|
+
*/
|
|
633
|
+
reviewID?: string;
|
|
527
634
|
}
|
|
528
635
|
/**
|
|
529
636
|
* Extract card origin from provenance trail.
|
|
@@ -539,10 +646,10 @@ declare function getCardOrigin(card: WeightedCard): 'new' | 'review' | 'failed';
|
|
|
539
646
|
declare enum Navigators {
|
|
540
647
|
ELO = "elo",
|
|
541
648
|
SRS = "srs",
|
|
542
|
-
HARDCODED = "hardcodedOrder",
|
|
543
649
|
HIERARCHY = "hierarchyDefinition",
|
|
544
650
|
INTERFERENCE = "interferenceMitigator",
|
|
545
|
-
RELATIVE_PRIORITY = "relativePriority"
|
|
651
|
+
RELATIVE_PRIORITY = "relativePriority",
|
|
652
|
+
USER_TAG_PREFERENCE = "userTagPreference"
|
|
546
653
|
}
|
|
547
654
|
/**
|
|
548
655
|
* Role classification for navigation strategies.
|
|
@@ -584,9 +691,9 @@ declare function isFilter(impl: string): boolean;
|
|
|
584
691
|
*/
|
|
585
692
|
declare abstract class ContentNavigator implements StudyContentSource {
|
|
586
693
|
/** User interface for this navigation session */
|
|
587
|
-
protected user
|
|
694
|
+
protected user: UserDBInterface;
|
|
588
695
|
/** Course interface for this navigation session */
|
|
589
|
-
protected course
|
|
696
|
+
protected course: CourseDBInterface;
|
|
590
697
|
/** Human-readable name for this strategy instance (from ContentNavigationStrategyData.name) */
|
|
591
698
|
protected strategyName?: string;
|
|
592
699
|
/** Unique document ID for this strategy instance (from ContentNavigationStrategyData._id) */
|
|
@@ -595,34 +702,41 @@ declare abstract class ContentNavigator implements StudyContentSource {
|
|
|
595
702
|
* Constructor for standard navigators.
|
|
596
703
|
* Call this from subclass constructors to initialize common fields.
|
|
597
704
|
*
|
|
598
|
-
* Note: CompositeGenerator
|
|
705
|
+
* Note: CompositeGenerator and Pipeline call super() without args, then set
|
|
706
|
+
* user/course fields directly if needed.
|
|
599
707
|
*/
|
|
600
708
|
constructor(user?: UserDBInterface, course?: CourseDBInterface, strategyData?: ContentNavigationStrategyData);
|
|
601
709
|
/**
|
|
602
|
-
*
|
|
710
|
+
* Unique key identifying this strategy for state storage.
|
|
603
711
|
*
|
|
604
|
-
*
|
|
605
|
-
*
|
|
606
|
-
*
|
|
607
|
-
* @returns the runtime object used to steer a study session.
|
|
712
|
+
* Defaults to the constructor name (e.g., "UserTagPreferenceFilter").
|
|
713
|
+
* Override in subclasses if multiple instances of the same strategy type
|
|
714
|
+
* need separate state storage.
|
|
608
715
|
*/
|
|
609
|
-
|
|
716
|
+
protected get strategyKey(): string;
|
|
610
717
|
/**
|
|
611
|
-
* Get
|
|
718
|
+
* Get this strategy's persisted state for the current course.
|
|
612
719
|
*
|
|
613
|
-
* @
|
|
614
|
-
*
|
|
720
|
+
* @returns The strategy's data payload, or null if no state exists
|
|
721
|
+
* @throws Error if user or course is not initialized
|
|
615
722
|
*/
|
|
616
|
-
|
|
723
|
+
protected getStrategyState<T>(): Promise<T | null>;
|
|
617
724
|
/**
|
|
618
|
-
*
|
|
725
|
+
* Persist this strategy's state for the current course.
|
|
619
726
|
*
|
|
620
|
-
* @
|
|
621
|
-
*
|
|
727
|
+
* @param data - The strategy's data payload to store
|
|
728
|
+
* @throws Error if user or course is not initialized
|
|
729
|
+
*/
|
|
730
|
+
protected putStrategyState<T>(data: T): Promise<void>;
|
|
731
|
+
/**
|
|
732
|
+
* Factory method to create navigator instances dynamically.
|
|
622
733
|
*
|
|
623
|
-
* @param
|
|
734
|
+
* @param user - User interface
|
|
735
|
+
* @param course - Course interface
|
|
736
|
+
* @param strategyData - Strategy configuration document
|
|
737
|
+
* @returns the runtime object used to steer a study session.
|
|
624
738
|
*/
|
|
625
|
-
|
|
739
|
+
static create(user: UserDBInterface, course: CourseDBInterface, strategyData: ContentNavigationStrategyData): Promise<ContentNavigator>;
|
|
626
740
|
/**
|
|
627
741
|
* Get cards with suitability scores and provenance trails.
|
|
628
742
|
*
|
|
@@ -632,25 +746,23 @@ declare abstract class ContentNavigator implements StudyContentSource {
|
|
|
632
746
|
* better candidates for presentation. Each card includes a provenance trail
|
|
633
747
|
* documenting how strategies contributed to the final score.
|
|
634
748
|
*
|
|
749
|
+
* ## Implementation Required
|
|
750
|
+
* All navigation strategies MUST override this method. The base class does
|
|
751
|
+
* not provide a default implementation.
|
|
752
|
+
*
|
|
635
753
|
* ## For Generators
|
|
636
754
|
* Override this method to generate candidates and compute scores based on
|
|
637
755
|
* your strategy's logic (e.g., ELO proximity, review urgency). Create the
|
|
638
756
|
* initial provenance entry with action='generated'.
|
|
639
757
|
*
|
|
640
|
-
* ##
|
|
641
|
-
*
|
|
642
|
-
*
|
|
643
|
-
* 2. Assigns score=1.0 to all cards
|
|
644
|
-
* 3. Creates minimal provenance from legacy methods
|
|
645
|
-
* 4. Returns combined results up to limit
|
|
646
|
-
*
|
|
647
|
-
* This allows existing strategies to work without modification while
|
|
648
|
-
* new strategies can override with proper scoring and provenance.
|
|
758
|
+
* ## For Filters
|
|
759
|
+
* Filters should implement the CardFilter interface instead and be composed
|
|
760
|
+
* via Pipeline. Filters do not directly implement getWeightedCards().
|
|
649
761
|
*
|
|
650
762
|
* @param limit - Maximum cards to return
|
|
651
763
|
* @returns Cards sorted by score descending, with provenance trails
|
|
652
764
|
*/
|
|
653
|
-
getWeightedCards(
|
|
765
|
+
getWeightedCards(_limit: number): Promise<WeightedCard[]>;
|
|
654
766
|
}
|
|
655
767
|
|
|
656
768
|
type StudySessionFailedItem = StudySessionFailedNewItem | StudySessionFailedReviewItem;
|
|
@@ -688,112 +800,23 @@ interface ContentSourceID {
|
|
|
688
800
|
/**
|
|
689
801
|
* Interface for sources that provide study content to SessionController.
|
|
690
802
|
*
|
|
691
|
-
*
|
|
692
|
-
*
|
|
693
|
-
* strategies. The new API returns unified WeightedCard[] with scores.
|
|
803
|
+
* Content sources return scored candidates via getWeightedCards(), which
|
|
804
|
+
* SessionController uses to populate study queues.
|
|
694
805
|
*
|
|
695
|
-
*
|
|
696
|
-
* - Implement ContentNavigator instead of StudyContentSource directly
|
|
697
|
-
* - Override getWeightedCards() as the primary method
|
|
698
|
-
* - Legacy methods can delegate to getWeightedCards() or be left as-is
|
|
699
|
-
*
|
|
700
|
-
* See: packages/db/src/core/navigators/ARCHITECTURE.md
|
|
806
|
+
* See: packages/db/docs/navigators-architecture.md
|
|
701
807
|
*/
|
|
702
808
|
interface StudyContentSource {
|
|
703
|
-
/**
|
|
704
|
-
* Get cards scheduled for review based on SRS algorithm.
|
|
705
|
-
*
|
|
706
|
-
* @deprecated Will be replaced by getWeightedCards() which returns scored candidates.
|
|
707
|
-
* Review urgency will be expressed as a score rather than a separate method.
|
|
708
|
-
*/
|
|
709
|
-
getPendingReviews(): Promise<(StudySessionReviewItem & ScheduledCard)[]>;
|
|
710
|
-
/**
|
|
711
|
-
* Get new cards for introduction, typically ordered by ELO proximity.
|
|
712
|
-
*
|
|
713
|
-
* @deprecated Will be replaced by getWeightedCards() which returns scored candidates.
|
|
714
|
-
* New card selection and scoring will be unified with review scoring.
|
|
715
|
-
*
|
|
716
|
-
* @param n - Maximum number of new cards to return
|
|
717
|
-
*/
|
|
718
|
-
getNewCards(n?: number): Promise<StudySessionNewItem[]>;
|
|
719
809
|
/**
|
|
720
810
|
* Get cards with suitability scores for presentation.
|
|
721
811
|
*
|
|
722
|
-
*
|
|
723
|
-
*
|
|
724
|
-
*
|
|
725
|
-
* The `source` field on WeightedCard indicates origin ('new' | 'review' | 'failed')
|
|
726
|
-
* for queue routing purposes during the migration period.
|
|
812
|
+
* Returns unified scored candidates that can be sorted and selected by SessionController.
|
|
813
|
+
* The card origin ('new' | 'review' | 'failed') is determined by provenance metadata.
|
|
727
814
|
*
|
|
728
815
|
* @param limit - Maximum number of cards to return
|
|
729
816
|
* @returns Cards sorted by score descending
|
|
730
817
|
*/
|
|
731
|
-
getWeightedCards
|
|
818
|
+
getWeightedCards(limit: number): Promise<WeightedCard[]>;
|
|
732
819
|
}
|
|
733
820
|
declare function getStudySource(source: ContentSourceID, user: UserDBInterface): Promise<StudyContentSource>;
|
|
734
821
|
|
|
735
|
-
|
|
736
|
-
* Classroom management
|
|
737
|
-
*/
|
|
738
|
-
interface ClassroomDBInterface {
|
|
739
|
-
/**
|
|
740
|
-
* Get classroom config
|
|
741
|
-
*/
|
|
742
|
-
getConfig(): ClassroomConfig;
|
|
743
|
-
/**
|
|
744
|
-
* Get assigned content
|
|
745
|
-
*/
|
|
746
|
-
getAssignedContent(): Promise<AssignedContent[]>;
|
|
747
|
-
}
|
|
748
|
-
interface TeacherClassroomDBInterface extends ClassroomDBInterface {
|
|
749
|
-
/**
|
|
750
|
-
* For teacher interfaces: assign content
|
|
751
|
-
*/
|
|
752
|
-
assignContent?(content: AssignedContent): Promise<boolean>;
|
|
753
|
-
/**
|
|
754
|
-
* For teacher interfaces: remove content
|
|
755
|
-
*/
|
|
756
|
-
removeContent?(content: AssignedContent): Promise<void>;
|
|
757
|
-
}
|
|
758
|
-
interface StudentClassroomDBInterface extends ClassroomDBInterface {
|
|
759
|
-
/**
|
|
760
|
-
* For student interfaces: get pending reviews
|
|
761
|
-
*/
|
|
762
|
-
getPendingReviews?(): Promise<(StudySessionReviewItem & ScheduledCard)[]>;
|
|
763
|
-
/**
|
|
764
|
-
* For student interfaces: get new cards
|
|
765
|
-
*/
|
|
766
|
-
getNewCards?(limit?: number): Promise<StudySessionNewItem[]>;
|
|
767
|
-
}
|
|
768
|
-
type AssignedContent = AssignedCourse | AssignedTag | AssignedCard;
|
|
769
|
-
interface AssignedTag extends ContentBase {
|
|
770
|
-
type: 'tag';
|
|
771
|
-
tagID: string;
|
|
772
|
-
}
|
|
773
|
-
interface AssignedCourse extends ContentBase {
|
|
774
|
-
type: 'course';
|
|
775
|
-
}
|
|
776
|
-
interface AssignedCard extends ContentBase {
|
|
777
|
-
type: 'card';
|
|
778
|
-
cardID: string;
|
|
779
|
-
}
|
|
780
|
-
interface ContentBase {
|
|
781
|
-
type: 'course' | 'tag' | 'card';
|
|
782
|
-
/**
|
|
783
|
-
* Username of the assigning teacher.
|
|
784
|
-
*/
|
|
785
|
-
assignedBy: string;
|
|
786
|
-
/**
|
|
787
|
-
* Date the content was assigned.
|
|
788
|
-
*/
|
|
789
|
-
assignedOn: moment.Moment;
|
|
790
|
-
/**
|
|
791
|
-
* A 'due' date for this assigned content, for scheduling content
|
|
792
|
-
* in advance. Content will not be actively pushed to students until
|
|
793
|
-
* this date.
|
|
794
|
-
*/
|
|
795
|
-
activeOn: moment.Moment;
|
|
796
|
-
courseID: string;
|
|
797
|
-
}
|
|
798
|
-
|
|
799
|
-
export { type AdminDBInterface as A, type UsrCrsDataInterface as B, type CourseDBInterface as C, type DataLayerResult as D, type ClassroomRegistrationDesignation as E, type ClassroomRegistration as F, type ClassroomRegistrationDoc as G, type SessionTrackingData as H, type UserConfig as I, type ActivityRecord as J, type CourseRegistration as K, type StrategyContribution as L, getCardOrigin as M, Navigators as N, NavigatorRole as O, NavigatorRoles as P, isGenerator as Q, isFilter as R, type StudySessionNewItem as S, type TeacherClassroomDBInterface as T, type UserDBInterface as U, type DocumentUpdater as V, type WeightedCard as W, newInterval as X, type UserDBReader as a, type CoursesDBInterface as b, type ClassroomDBInterface as c, type CourseInfo as d, type ContentNavigationStrategyData as e, type StudySessionReviewItem as f, type ScheduledCard as g, type AssignedContent as h, type StudyContentSource as i, type StudentClassroomDBInterface as j, ContentNavigator as k, type StudySessionItem as l, type StudySessionFailedItem as m, type StudySessionFailedNewItem as n, type StudySessionFailedReviewItem as o, isReview as p, type ContentSourceID as q, getStudySource as r, type CourseRegistrationDoc as s, type AssignedTag as t, type AssignedCourse as u, type AssignedCard as v, type UserDBWriter as w, type UserDBAuthenticator as x, type UserCourseSettings as y, type UserCourseSetting as z };
|
|
822
|
+
export { type AdminDBInterface as A, type UsrCrsDataInterface as B, type CourseDBInterface as C, type DataLayerResult as D, type ClassroomRegistrationDesignation as E, type ClassroomRegistration as F, type ClassroomRegistrationDoc as G, type SessionTrackingData as H, type UserConfig as I, type ActivityRecord as J, type CourseRegistration as K, type StrategyContribution as L, getCardOrigin as M, Navigators as N, NavigatorRole as O, NavigatorRoles as P, isGenerator as Q, isFilter as R, type StudySessionItem as S, type TeacherClassroomDBInterface as T, type UserDBInterface as U, type DocumentUpdater as V, type WeightedCard as W, newInterval as X, type UserDBReader as a, type CoursesDBInterface as b, type ClassroomDBInterface as c, type CourseInfo as d, type ContentNavigationStrategyData as e, ContentNavigator as f, type AssignedContent as g, type StudyContentSource as h, type StudentClassroomDBInterface as i, type ScheduledCard as j, type StudySessionFailedItem as k, type StudySessionFailedNewItem as l, type StudySessionFailedReviewItem as m, type StudySessionNewItem as n, type StudySessionReviewItem as o, isReview as p, type ContentSourceID as q, getStudySource as r, type CourseRegistrationDoc as s, type AssignedTag as t, type AssignedCourse as u, type AssignedCard as v, type UserDBWriter as w, type UserDBAuthenticator as x, type UserCourseSettings as y, type UserCourseSetting as z };
|