@lssm/module.learning-journey 0.0.0-canary-20251217052941 → 0.0.0-canary-20251217060433

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.
@@ -0,0 +1,279 @@
1
+ import * as _lssm_lib_schema211 from "@lssm/lib.schema";
2
+ import * as _lssm_lib_contracts31 from "@lssm/lib.contracts";
3
+
4
+ //#region src/contracts/operations.d.ts
5
+ /**
6
+ * Enroll in a course.
7
+ */
8
+ declare const EnrollInCourseContract: _lssm_lib_contracts31.ContractSpec<_lssm_lib_schema211.SchemaModel<{
9
+ courseId: {
10
+ type: _lssm_lib_schema211.FieldType<string, string>;
11
+ isOptional: false;
12
+ };
13
+ }>, _lssm_lib_schema211.SchemaModel<{
14
+ id: {
15
+ type: _lssm_lib_schema211.FieldType<string, string>;
16
+ isOptional: false;
17
+ };
18
+ learnerId: {
19
+ type: _lssm_lib_schema211.FieldType<string, string>;
20
+ isOptional: false;
21
+ };
22
+ courseId: {
23
+ type: _lssm_lib_schema211.FieldType<string, string>;
24
+ isOptional: false;
25
+ };
26
+ status: {
27
+ type: _lssm_lib_schema211.FieldType<string, string>;
28
+ isOptional: false;
29
+ };
30
+ progress: {
31
+ type: _lssm_lib_schema211.FieldType<number, number>;
32
+ isOptional: false;
33
+ };
34
+ startedAt: {
35
+ type: _lssm_lib_schema211.FieldType<Date, string>;
36
+ isOptional: true;
37
+ };
38
+ completedAt: {
39
+ type: _lssm_lib_schema211.FieldType<Date, string>;
40
+ isOptional: true;
41
+ };
42
+ }>, undefined>;
43
+ /**
44
+ * Complete a lesson.
45
+ */
46
+ declare const CompleteLessonContract: _lssm_lib_contracts31.ContractSpec<_lssm_lib_schema211.SchemaModel<{
47
+ lessonId: {
48
+ type: _lssm_lib_schema211.FieldType<string, string>;
49
+ isOptional: false;
50
+ };
51
+ score: {
52
+ type: _lssm_lib_schema211.FieldType<number, number>;
53
+ isOptional: true;
54
+ };
55
+ timeSpent: {
56
+ type: _lssm_lib_schema211.FieldType<number, number>;
57
+ isOptional: false;
58
+ };
59
+ }>, _lssm_lib_schema211.SchemaModel<{
60
+ success: {
61
+ type: _lssm_lib_schema211.FieldType<boolean, boolean>;
62
+ isOptional: false;
63
+ };
64
+ xpEarned: {
65
+ type: _lssm_lib_schema211.FieldType<number, number>;
66
+ isOptional: true;
67
+ };
68
+ }>, undefined>;
69
+ /**
70
+ * Submit a card review.
71
+ */
72
+ declare const SubmitCardReviewContract: _lssm_lib_contracts31.ContractSpec<_lssm_lib_schema211.SchemaModel<{
73
+ cardId: {
74
+ type: _lssm_lib_schema211.FieldType<string, string>;
75
+ isOptional: false;
76
+ };
77
+ rating: {
78
+ type: _lssm_lib_schema211.FieldType<string, string>;
79
+ isOptional: false;
80
+ };
81
+ responseTimeMs: {
82
+ type: _lssm_lib_schema211.FieldType<number, number>;
83
+ isOptional: true;
84
+ };
85
+ }>, _lssm_lib_schema211.SchemaModel<{
86
+ success: {
87
+ type: _lssm_lib_schema211.FieldType<boolean, boolean>;
88
+ isOptional: false;
89
+ };
90
+ xpEarned: {
91
+ type: _lssm_lib_schema211.FieldType<number, number>;
92
+ isOptional: true;
93
+ };
94
+ }>, undefined>;
95
+ /**
96
+ * Get cards due for review.
97
+ */
98
+ declare const GetDueCardsContract: _lssm_lib_contracts31.ContractSpec<_lssm_lib_schema211.SchemaModel<{
99
+ deckId: {
100
+ type: _lssm_lib_schema211.FieldType<string, string>;
101
+ isOptional: true;
102
+ };
103
+ limit: {
104
+ type: _lssm_lib_schema211.FieldType<number, number>;
105
+ isOptional: true;
106
+ };
107
+ }>, _lssm_lib_schema211.SchemaModel<{
108
+ cards: {
109
+ type: _lssm_lib_schema211.SchemaModel<{
110
+ id: {
111
+ type: _lssm_lib_schema211.FieldType<string, string>;
112
+ isOptional: false;
113
+ };
114
+ deckId: {
115
+ type: _lssm_lib_schema211.FieldType<string, string>;
116
+ isOptional: false;
117
+ };
118
+ front: {
119
+ type: _lssm_lib_schema211.FieldType<string, string>;
120
+ isOptional: false;
121
+ };
122
+ back: {
123
+ type: _lssm_lib_schema211.FieldType<string, string>;
124
+ isOptional: false;
125
+ };
126
+ hints: {
127
+ type: _lssm_lib_schema211.FieldType<unknown, unknown>;
128
+ isOptional: true;
129
+ };
130
+ isDue: {
131
+ type: _lssm_lib_schema211.FieldType<boolean, boolean>;
132
+ isOptional: false;
133
+ };
134
+ nextReviewAt: {
135
+ type: _lssm_lib_schema211.FieldType<Date, string>;
136
+ isOptional: true;
137
+ };
138
+ }>;
139
+ isArray: true;
140
+ isOptional: false;
141
+ };
142
+ total: {
143
+ type: _lssm_lib_schema211.FieldType<number, number>;
144
+ isOptional: false;
145
+ };
146
+ }>, undefined>;
147
+ /**
148
+ * Get learner dashboard.
149
+ */
150
+ declare const GetLearnerDashboardContract: _lssm_lib_contracts31.ContractSpec<_lssm_lib_schema211.SchemaModel<{
151
+ learnerId: {
152
+ type: _lssm_lib_schema211.FieldType<string, string>;
153
+ isOptional: true;
154
+ };
155
+ }>, _lssm_lib_schema211.SchemaModel<{
156
+ learner: {
157
+ type: _lssm_lib_schema211.SchemaModel<{
158
+ id: {
159
+ type: _lssm_lib_schema211.FieldType<string, string>;
160
+ isOptional: false;
161
+ };
162
+ userId: {
163
+ type: _lssm_lib_schema211.FieldType<string, string>;
164
+ isOptional: false;
165
+ };
166
+ displayName: {
167
+ type: _lssm_lib_schema211.FieldType<string, string>;
168
+ isOptional: true;
169
+ };
170
+ level: {
171
+ type: _lssm_lib_schema211.FieldType<number, number>;
172
+ isOptional: false;
173
+ };
174
+ totalXp: {
175
+ type: _lssm_lib_schema211.FieldType<number, number>;
176
+ isOptional: false;
177
+ };
178
+ currentStreak: {
179
+ type: _lssm_lib_schema211.FieldType<number, number>;
180
+ isOptional: false;
181
+ };
182
+ longestStreak: {
183
+ type: _lssm_lib_schema211.FieldType<number, number>;
184
+ isOptional: false;
185
+ };
186
+ createdAt: {
187
+ type: _lssm_lib_schema211.FieldType<Date, string>;
188
+ isOptional: false;
189
+ };
190
+ }>;
191
+ isOptional: false;
192
+ };
193
+ currentStreak: {
194
+ type: _lssm_lib_schema211.FieldType<number, number>;
195
+ isOptional: false;
196
+ };
197
+ dailyXpGoal: {
198
+ type: _lssm_lib_schema211.FieldType<number, number>;
199
+ isOptional: false;
200
+ };
201
+ dailyXpProgress: {
202
+ type: _lssm_lib_schema211.FieldType<number, number>;
203
+ isOptional: false;
204
+ };
205
+ activeEnrollments: {
206
+ type: _lssm_lib_schema211.SchemaModel<{
207
+ id: {
208
+ type: _lssm_lib_schema211.FieldType<string, string>;
209
+ isOptional: false;
210
+ };
211
+ learnerId: {
212
+ type: _lssm_lib_schema211.FieldType<string, string>;
213
+ isOptional: false;
214
+ };
215
+ courseId: {
216
+ type: _lssm_lib_schema211.FieldType<string, string>;
217
+ isOptional: false;
218
+ };
219
+ status: {
220
+ type: _lssm_lib_schema211.FieldType<string, string>;
221
+ isOptional: false;
222
+ };
223
+ progress: {
224
+ type: _lssm_lib_schema211.FieldType<number, number>;
225
+ isOptional: false;
226
+ };
227
+ startedAt: {
228
+ type: _lssm_lib_schema211.FieldType<Date, string>;
229
+ isOptional: true;
230
+ };
231
+ completedAt: {
232
+ type: _lssm_lib_schema211.FieldType<Date, string>;
233
+ isOptional: true;
234
+ };
235
+ }>;
236
+ isArray: true;
237
+ isOptional: false;
238
+ };
239
+ recentAchievements: {
240
+ type: _lssm_lib_schema211.SchemaModel<{
241
+ id: {
242
+ type: _lssm_lib_schema211.FieldType<string, string>;
243
+ isOptional: false;
244
+ };
245
+ key: {
246
+ type: _lssm_lib_schema211.FieldType<string, string>;
247
+ isOptional: false;
248
+ };
249
+ name: {
250
+ type: _lssm_lib_schema211.FieldType<string, string>;
251
+ isOptional: false;
252
+ };
253
+ description: {
254
+ type: _lssm_lib_schema211.FieldType<string, string>;
255
+ isOptional: false;
256
+ };
257
+ icon: {
258
+ type: _lssm_lib_schema211.FieldType<string, string>;
259
+ isOptional: true;
260
+ };
261
+ xpReward: {
262
+ type: _lssm_lib_schema211.FieldType<number, number>;
263
+ isOptional: false;
264
+ };
265
+ unlockedAt: {
266
+ type: _lssm_lib_schema211.FieldType<Date, string>;
267
+ isOptional: true;
268
+ };
269
+ }>;
270
+ isArray: true;
271
+ isOptional: false;
272
+ };
273
+ dueCardCount: {
274
+ type: _lssm_lib_schema211.FieldType<number, number>;
275
+ isOptional: false;
276
+ };
277
+ }>, undefined>;
278
+ //#endregion
279
+ export { CompleteLessonContract, EnrollInCourseContract, GetDueCardsContract, GetLearnerDashboardContract, SubmitCardReviewContract };
@@ -0,0 +1,4 @@
1
+ //#region src/contracts/shared.d.ts
2
+ declare const LEARNING_JOURNEY_OWNERS: readonly ["modules.learning-journey"];
3
+ //#endregion
4
+ export { LEARNING_JOURNEY_OWNERS };
@@ -0,0 +1 @@
1
+ export { };
@@ -0,0 +1 @@
1
+ export { };
@@ -0,0 +1,4 @@
1
+ import { CardRating, DEFAULT_SRS_CONFIG, ReviewResult, SRSConfig, SRSEngine, SRSState, srsEngine } from "./srs.js";
2
+ import { DEFAULT_XP_CONFIG, XPActivityType, XPBreakdown, XPCalculationInput, XPConfig, XPEngine, XPResult, xpEngine } from "./xp.js";
3
+ import { DEFAULT_STREAK_CONFIG, StreakConfig, StreakEngine, StreakState, StreakUpdateResult, streakEngine } from "./streak.js";
4
+ export { CardRating, DEFAULT_SRS_CONFIG, DEFAULT_STREAK_CONFIG, DEFAULT_XP_CONFIG, ReviewResult, SRSConfig, SRSEngine, SRSState, StreakConfig, StreakEngine, StreakState, StreakUpdateResult, XPActivityType, XPBreakdown, XPCalculationInput, XPConfig, XPEngine, XPResult, srsEngine, streakEngine, xpEngine };
@@ -0,0 +1,110 @@
1
+ //#region src/engines/srs.d.ts
2
+ /**
3
+ * Spaced Repetition System (SRS) Engine
4
+ *
5
+ * Implements the SM-2 algorithm variant for optimal flashcard scheduling.
6
+ *
7
+ * The algorithm calculates the optimal time to review a card based on:
8
+ * - User's rating of recall difficulty (again, hard, good, easy)
9
+ * - Current interval between reviews
10
+ * - Ease factor (how easy the card is for this user)
11
+ * - Number of successful repetitions
12
+ */
13
+ type CardRating = 'AGAIN' | 'HARD' | 'GOOD' | 'EASY';
14
+ interface SRSState {
15
+ /** Current interval in days */
16
+ interval: number;
17
+ /** Ease factor (typically 1.3 to 2.5+) */
18
+ easeFactor: number;
19
+ /** Number of successful repetitions */
20
+ repetitions: number;
21
+ /** Current learning step (for new cards) */
22
+ learningStep: number;
23
+ /** Whether card has graduated to review phase */
24
+ isGraduated: boolean;
25
+ /** Whether card is being relearned after a lapse */
26
+ isRelearning: boolean;
27
+ /** Number of times card was forgotten */
28
+ lapses: number;
29
+ }
30
+ interface ReviewResult {
31
+ /** New interval in days */
32
+ interval: number;
33
+ /** New ease factor */
34
+ easeFactor: number;
35
+ /** New repetition count */
36
+ repetitions: number;
37
+ /** Next review date */
38
+ nextReviewAt: Date;
39
+ /** New learning step */
40
+ learningStep: number;
41
+ /** Whether card has graduated */
42
+ isGraduated: boolean;
43
+ /** Whether card is being relearned */
44
+ isRelearning: boolean;
45
+ /** Updated lapse count */
46
+ lapses: number;
47
+ }
48
+ interface SRSConfig {
49
+ /** Learning steps in minutes [1, 10] = 1 min, 10 min */
50
+ learningSteps: number[];
51
+ /** Graduating interval in days */
52
+ graduatingInterval: number;
53
+ /** Easy interval (for easy button on new cards) */
54
+ easyInterval: number;
55
+ /** Relearning steps in minutes */
56
+ relearningSteps: number[];
57
+ /** Minimum ease factor */
58
+ minEaseFactor: number;
59
+ /** Maximum interval in days */
60
+ maxInterval: number;
61
+ /** Interval modifier (1.0 = 100%) */
62
+ intervalModifier: number;
63
+ /** New cards interval modifier */
64
+ newIntervalModifier: number;
65
+ /** Hard interval modifier */
66
+ hardIntervalModifier: number;
67
+ /** Easy bonus modifier */
68
+ easyBonus: number;
69
+ }
70
+ declare const DEFAULT_SRS_CONFIG: SRSConfig;
71
+ declare class SRSEngine {
72
+ private config;
73
+ constructor(config?: Partial<SRSConfig>);
74
+ /**
75
+ * Calculate the next review state based on rating.
76
+ */
77
+ calculateNextReview(state: SRSState, rating: CardRating, now?: Date): ReviewResult;
78
+ /**
79
+ * Handle learning phase (new cards).
80
+ */
81
+ private handleLearningCard;
82
+ /**
83
+ * Handle relearning phase (lapsed cards).
84
+ */
85
+ private handleRelearningCard;
86
+ /**
87
+ * Handle review phase (graduated cards).
88
+ */
89
+ private handleReviewCard;
90
+ /**
91
+ * Get initial SRS state for a new card.
92
+ */
93
+ getInitialState(): SRSState;
94
+ /**
95
+ * Check if a card is due for review.
96
+ */
97
+ isDue(nextReviewAt: Date, now?: Date): boolean;
98
+ /**
99
+ * Calculate overdue days (negative if not yet due).
100
+ */
101
+ getOverdueDays(nextReviewAt: Date, now?: Date): number;
102
+ private addMinutes;
103
+ private addDays;
104
+ }
105
+ /**
106
+ * Default SRS engine instance.
107
+ */
108
+ declare const srsEngine: SRSEngine;
109
+ //#endregion
110
+ export { CardRating, DEFAULT_SRS_CONFIG, ReviewResult, SRSConfig, SRSEngine, SRSState, srsEngine };
@@ -0,0 +1,99 @@
1
+ //#region src/engines/streak.d.ts
2
+ /**
3
+ * Streak Tracking Engine
4
+ *
5
+ * Manages daily learning streaks with timezone support and freeze protection.
6
+ */
7
+ interface StreakState {
8
+ /** Current streak days */
9
+ currentStreak: number;
10
+ /** Longest streak ever */
11
+ longestStreak: number;
12
+ /** Last activity timestamp */
13
+ lastActivityAt: Date | null;
14
+ /** Last activity date (YYYY-MM-DD) */
15
+ lastActivityDate: string | null;
16
+ /** Available streak freezes */
17
+ freezesRemaining: number;
18
+ /** When a freeze was last used */
19
+ freezeUsedAt: Date | null;
20
+ }
21
+ interface StreakUpdateResult {
22
+ /** Updated streak state */
23
+ state: StreakState;
24
+ /** Whether streak was maintained */
25
+ streakMaintained: boolean;
26
+ /** Whether streak was lost */
27
+ streakLost: boolean;
28
+ /** Whether a freeze was used */
29
+ freezeUsed: boolean;
30
+ /** Whether this activity started a new streak */
31
+ newStreak: boolean;
32
+ /** Days missed (if streak was lost) */
33
+ daysMissed: number;
34
+ }
35
+ interface StreakConfig {
36
+ /** Timezone for the user */
37
+ timezone: string;
38
+ /** How many streak freezes to give per month */
39
+ freezesPerMonth: number;
40
+ /** Maximum freezes that can be accumulated */
41
+ maxFreezes: number;
42
+ /** Grace period in hours after midnight */
43
+ gracePeriodHours: number;
44
+ }
45
+ declare const DEFAULT_STREAK_CONFIG: StreakConfig;
46
+ declare class StreakEngine {
47
+ private config;
48
+ constructor(config?: Partial<StreakConfig>);
49
+ /**
50
+ * Update streak based on new activity.
51
+ */
52
+ update(state: StreakState, now?: Date): StreakUpdateResult;
53
+ /**
54
+ * Check streak status without recording activity.
55
+ */
56
+ checkStatus(state: StreakState, now?: Date): {
57
+ isActive: boolean;
58
+ willExpireAt: Date | null;
59
+ canUseFreeze: boolean;
60
+ daysUntilExpiry: number;
61
+ };
62
+ /**
63
+ * Manually use a freeze to protect streak.
64
+ */
65
+ useFreeze(state: StreakState, now?: Date): StreakState | null;
66
+ /**
67
+ * Award monthly freezes.
68
+ */
69
+ awardMonthlyFreezes(state: StreakState): StreakState;
70
+ /**
71
+ * Get initial streak state.
72
+ */
73
+ getInitialState(): StreakState;
74
+ /**
75
+ * Calculate streak milestones.
76
+ */
77
+ getMilestones(currentStreak: number): {
78
+ achieved: number[];
79
+ next: number | null;
80
+ };
81
+ /**
82
+ * Get date string in YYYY-MM-DD format.
83
+ */
84
+ private getDateString;
85
+ /**
86
+ * Get number of days between two date strings.
87
+ */
88
+ private getDaysBetween;
89
+ /**
90
+ * Add days to a date.
91
+ */
92
+ private addDays;
93
+ }
94
+ /**
95
+ * Default streak engine instance.
96
+ */
97
+ declare const streakEngine: StreakEngine;
98
+ //#endregion
99
+ export { DEFAULT_STREAK_CONFIG, StreakConfig, StreakEngine, StreakState, StreakUpdateResult, streakEngine };
@@ -0,0 +1,96 @@
1
+ //#region src/engines/xp.d.ts
2
+ /**
3
+ * XP (Experience Points) Engine
4
+ *
5
+ * Calculates XP rewards for various learning activities.
6
+ */
7
+ type XPActivityType = 'lesson_complete' | 'quiz_pass' | 'quiz_perfect' | 'flashcard_review' | 'course_complete' | 'module_complete' | 'streak_bonus' | 'achievement_unlock' | 'daily_goal_complete' | 'first_lesson' | 'onboarding_step' | 'onboarding_complete';
8
+ interface XPCalculationInput {
9
+ /** Type of activity */
10
+ activity: XPActivityType;
11
+ /** Base XP for the activity (from content config) */
12
+ baseXp?: number;
13
+ /** Score achieved (0-100) for scored activities */
14
+ score?: number;
15
+ /** Current streak (for streak bonuses) */
16
+ currentStreak?: number;
17
+ /** Time spent in seconds */
18
+ timeSpent?: number;
19
+ /** Attempt number (for quizzes) */
20
+ attemptNumber?: number;
21
+ /** Whether this is a retry */
22
+ isRetry?: boolean;
23
+ }
24
+ interface XPResult {
25
+ /** Total XP earned */
26
+ totalXp: number;
27
+ /** Base XP before bonuses */
28
+ baseXp: number;
29
+ /** Breakdown of XP sources */
30
+ breakdown: XPBreakdown[];
31
+ }
32
+ interface XPBreakdown {
33
+ /** Source of XP */
34
+ source: string;
35
+ /** XP amount */
36
+ amount: number;
37
+ /** Multiplier applied */
38
+ multiplier?: number;
39
+ }
40
+ interface XPConfig {
41
+ /** Base XP values for each activity */
42
+ baseValues: Record<XPActivityType, number>;
43
+ /** Score thresholds for bonus XP */
44
+ scoreThresholds: {
45
+ min: number;
46
+ multiplier: number;
47
+ }[];
48
+ /** Streak bonus tiers */
49
+ streakTiers: {
50
+ days: number;
51
+ bonus: number;
52
+ }[];
53
+ /** Perfect score bonus multiplier */
54
+ perfectScoreMultiplier: number;
55
+ /** First attempt bonus */
56
+ firstAttemptBonus: number;
57
+ /** Retry penalty multiplier */
58
+ retryPenalty: number;
59
+ /** Speed bonus (complete under expected time) */
60
+ speedBonusMultiplier: number;
61
+ /** Speed bonus threshold (percentage of expected time) */
62
+ speedBonusThreshold: number;
63
+ }
64
+ declare const DEFAULT_XP_CONFIG: XPConfig;
65
+ declare class XPEngine {
66
+ private config;
67
+ constructor(config?: Partial<XPConfig>);
68
+ /**
69
+ * Calculate XP for an activity.
70
+ */
71
+ calculate(input: XPCalculationInput): XPResult;
72
+ /**
73
+ * Calculate streak bonus XP.
74
+ */
75
+ calculateStreakBonus(currentStreak: number): XPResult;
76
+ /**
77
+ * Calculate XP needed for a level.
78
+ */
79
+ getXpForLevel(level: number): number;
80
+ /**
81
+ * Get level from total XP.
82
+ */
83
+ getLevelFromXp(totalXp: number): {
84
+ level: number;
85
+ xpInLevel: number;
86
+ xpForNextLevel: number;
87
+ };
88
+ private getScoreMultiplier;
89
+ private getStreakBonus;
90
+ }
91
+ /**
92
+ * Default XP engine instance.
93
+ */
94
+ declare const xpEngine: XPEngine;
95
+ //#endregion
96
+ export { DEFAULT_XP_CONFIG, XPActivityType, XPBreakdown, XPCalculationInput, XPConfig, XPEngine, XPResult, xpEngine };