@contractspec/module.learning-journey 1.44.0
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/LICENSE +21 -0
- package/README.md +200 -0
- package/dist/contracts/index.d.ts +5 -0
- package/dist/contracts/index.js +6 -0
- package/dist/contracts/models.d.ts +451 -0
- package/dist/contracts/models.d.ts.map +1 -0
- package/dist/contracts/models.js +388 -0
- package/dist/contracts/models.js.map +1 -0
- package/dist/contracts/onboarding.d.ts +666 -0
- package/dist/contracts/onboarding.d.ts.map +1 -0
- package/dist/contracts/onboarding.js +402 -0
- package/dist/contracts/onboarding.js.map +1 -0
- package/dist/contracts/operations.d.ts +280 -0
- package/dist/contracts/operations.d.ts.map +1 -0
- package/dist/contracts/operations.js +151 -0
- package/dist/contracts/operations.js.map +1 -0
- package/dist/contracts/shared.d.ts +5 -0
- package/dist/contracts/shared.d.ts.map +1 -0
- package/dist/contracts/shared.js +6 -0
- package/dist/contracts/shared.js.map +1 -0
- package/dist/docs/index.d.ts +1 -0
- package/dist/docs/index.js +1 -0
- package/dist/docs/learning-journey.docblock.d.ts +1 -0
- package/dist/docs/learning-journey.docblock.js +136 -0
- package/dist/docs/learning-journey.docblock.js.map +1 -0
- package/dist/engines/index.d.ts +4 -0
- package/dist/engines/index.js +5 -0
- package/dist/engines/srs.d.ts +111 -0
- package/dist/engines/srs.d.ts.map +1 -0
- package/dist/engines/srs.js +219 -0
- package/dist/engines/srs.js.map +1 -0
- package/dist/engines/streak.d.ts +100 -0
- package/dist/engines/streak.d.ts.map +1 -0
- package/dist/engines/streak.js +194 -0
- package/dist/engines/streak.js.map +1 -0
- package/dist/engines/xp.d.ts +97 -0
- package/dist/engines/xp.d.ts.map +1 -0
- package/dist/engines/xp.js +213 -0
- package/dist/engines/xp.js.map +1 -0
- package/dist/entities/ai.d.ts +232 -0
- package/dist/entities/ai.d.ts.map +1 -0
- package/dist/entities/ai.js +376 -0
- package/dist/entities/ai.js.map +1 -0
- package/dist/entities/course.d.ts +184 -0
- package/dist/entities/course.d.ts.map +1 -0
- package/dist/entities/course.js +316 -0
- package/dist/entities/course.js.map +1 -0
- package/dist/entities/flashcard.d.ts +170 -0
- package/dist/entities/flashcard.d.ts.map +1 -0
- package/dist/entities/flashcard.js +249 -0
- package/dist/entities/flashcard.js.map +1 -0
- package/dist/entities/gamification.d.ts +238 -0
- package/dist/entities/gamification.d.ts.map +1 -0
- package/dist/entities/gamification.js +392 -0
- package/dist/entities/gamification.js.map +1 -0
- package/dist/entities/index.d.ts +629 -0
- package/dist/entities/index.d.ts.map +1 -0
- package/dist/entities/index.js +45 -0
- package/dist/entities/index.js.map +1 -0
- package/dist/entities/learner.d.ts +224 -0
- package/dist/entities/learner.d.ts.map +1 -0
- package/dist/entities/learner.js +365 -0
- package/dist/entities/learner.js.map +1 -0
- package/dist/entities/onboarding.d.ts +190 -0
- package/dist/entities/onboarding.d.ts.map +1 -0
- package/dist/entities/onboarding.js +307 -0
- package/dist/entities/onboarding.js.map +1 -0
- package/dist/entities/quiz.d.ts +220 -0
- package/dist/entities/quiz.d.ts.map +1 -0
- package/dist/entities/quiz.js +370 -0
- package/dist/entities/quiz.js.map +1 -0
- package/dist/events.d.ts +796 -0
- package/dist/events.d.ts.map +1 -0
- package/dist/events.js +690 -0
- package/dist/events.js.map +1 -0
- package/dist/index.d.ts +20 -0
- package/dist/index.js +22 -0
- package/dist/learning-journey.feature.d.ts +12 -0
- package/dist/learning-journey.feature.d.ts.map +1 -0
- package/dist/learning-journey.feature.js +150 -0
- package/dist/learning-journey.feature.js.map +1 -0
- package/dist/track-spec.d.ts +129 -0
- package/dist/track-spec.d.ts.map +1 -0
- package/dist/track-spec.js +0 -0
- package/package.json +98 -0
|
@@ -0,0 +1,392 @@
|
|
|
1
|
+
import { defineEntity, defineEntityEnum, field, index } from "@contractspec/lib.schema";
|
|
2
|
+
|
|
3
|
+
//#region src/entities/gamification.ts
|
|
4
|
+
/**
|
|
5
|
+
* Achievement type enum.
|
|
6
|
+
*/
|
|
7
|
+
const AchievementTypeEnum = defineEntityEnum({
|
|
8
|
+
name: "AchievementType",
|
|
9
|
+
values: [
|
|
10
|
+
"MILESTONE",
|
|
11
|
+
"STREAK",
|
|
12
|
+
"SKILL",
|
|
13
|
+
"SOCIAL",
|
|
14
|
+
"SPECIAL",
|
|
15
|
+
"SEASONAL"
|
|
16
|
+
],
|
|
17
|
+
schema: "lssm_learning",
|
|
18
|
+
description: "Type of achievement."
|
|
19
|
+
});
|
|
20
|
+
/**
|
|
21
|
+
* Leaderboard period enum.
|
|
22
|
+
*/
|
|
23
|
+
const LeaderboardPeriodEnum = defineEntityEnum({
|
|
24
|
+
name: "LeaderboardPeriod",
|
|
25
|
+
values: [
|
|
26
|
+
"DAILY",
|
|
27
|
+
"WEEKLY",
|
|
28
|
+
"MONTHLY",
|
|
29
|
+
"ALL_TIME"
|
|
30
|
+
],
|
|
31
|
+
schema: "lssm_learning",
|
|
32
|
+
description: "Leaderboard time period."
|
|
33
|
+
});
|
|
34
|
+
/**
|
|
35
|
+
* Achievement entity - defines an achievement.
|
|
36
|
+
*/
|
|
37
|
+
const AchievementEntity = defineEntity({
|
|
38
|
+
name: "Achievement",
|
|
39
|
+
description: "An achievement that can be unlocked.",
|
|
40
|
+
schema: "lssm_learning",
|
|
41
|
+
map: "achievement",
|
|
42
|
+
fields: {
|
|
43
|
+
id: field.id({ description: "Unique achievement identifier" }),
|
|
44
|
+
key: field.string({
|
|
45
|
+
isUnique: true,
|
|
46
|
+
description: "Achievement key"
|
|
47
|
+
}),
|
|
48
|
+
name: field.string({ description: "Achievement name" }),
|
|
49
|
+
description: field.string({ description: "Achievement description" }),
|
|
50
|
+
icon: field.string({
|
|
51
|
+
isOptional: true,
|
|
52
|
+
description: "Icon name or URL"
|
|
53
|
+
}),
|
|
54
|
+
color: field.string({
|
|
55
|
+
isOptional: true,
|
|
56
|
+
description: "Display color"
|
|
57
|
+
}),
|
|
58
|
+
badgeUrl: field.string({
|
|
59
|
+
isOptional: true,
|
|
60
|
+
description: "Badge image URL"
|
|
61
|
+
}),
|
|
62
|
+
type: field.enum("AchievementType", {
|
|
63
|
+
default: "MILESTONE",
|
|
64
|
+
description: "Achievement type"
|
|
65
|
+
}),
|
|
66
|
+
category: field.string({
|
|
67
|
+
isOptional: true,
|
|
68
|
+
description: "Achievement category"
|
|
69
|
+
}),
|
|
70
|
+
rarity: field.string({
|
|
71
|
+
default: "\"common\"",
|
|
72
|
+
description: "Rarity: common, rare, epic, legendary"
|
|
73
|
+
}),
|
|
74
|
+
xpReward: field.int({
|
|
75
|
+
default: 50,
|
|
76
|
+
description: "XP awarded"
|
|
77
|
+
}),
|
|
78
|
+
condition: field.json({ description: "Unlock condition" }),
|
|
79
|
+
order: field.int({
|
|
80
|
+
default: 0,
|
|
81
|
+
description: "Display order"
|
|
82
|
+
}),
|
|
83
|
+
isHidden: field.boolean({
|
|
84
|
+
default: false,
|
|
85
|
+
description: "Hide until unlocked"
|
|
86
|
+
}),
|
|
87
|
+
isActive: field.boolean({
|
|
88
|
+
default: true,
|
|
89
|
+
description: "Whether achievement is active"
|
|
90
|
+
}),
|
|
91
|
+
orgId: field.string({
|
|
92
|
+
isOptional: true,
|
|
93
|
+
description: "Organization scope"
|
|
94
|
+
}),
|
|
95
|
+
metadata: field.json({
|
|
96
|
+
isOptional: true,
|
|
97
|
+
description: "Additional metadata"
|
|
98
|
+
}),
|
|
99
|
+
createdAt: field.createdAt(),
|
|
100
|
+
updatedAt: field.updatedAt(),
|
|
101
|
+
learnerAchievements: field.hasMany("LearnerAchievement")
|
|
102
|
+
},
|
|
103
|
+
indexes: [
|
|
104
|
+
index.on(["type"]),
|
|
105
|
+
index.on(["category"]),
|
|
106
|
+
index.on(["isActive"]),
|
|
107
|
+
index.on(["orgId"])
|
|
108
|
+
],
|
|
109
|
+
enums: [AchievementTypeEnum]
|
|
110
|
+
});
|
|
111
|
+
/**
|
|
112
|
+
* LearnerAchievement entity - unlocked achievements.
|
|
113
|
+
*/
|
|
114
|
+
const LearnerAchievementEntity = defineEntity({
|
|
115
|
+
name: "LearnerAchievement",
|
|
116
|
+
description: "An achievement unlocked by a learner.",
|
|
117
|
+
schema: "lssm_learning",
|
|
118
|
+
map: "learner_achievement",
|
|
119
|
+
fields: {
|
|
120
|
+
id: field.id({ description: "Unique record identifier" }),
|
|
121
|
+
learnerId: field.foreignKey({ description: "Learner" }),
|
|
122
|
+
achievementId: field.foreignKey({ description: "Achievement" }),
|
|
123
|
+
xpEarned: field.int({
|
|
124
|
+
default: 0,
|
|
125
|
+
description: "XP earned"
|
|
126
|
+
}),
|
|
127
|
+
progress: field.int({
|
|
128
|
+
default: 100,
|
|
129
|
+
description: "Progress percentage"
|
|
130
|
+
}),
|
|
131
|
+
currentValue: field.int({
|
|
132
|
+
isOptional: true,
|
|
133
|
+
description: "Current value towards goal"
|
|
134
|
+
}),
|
|
135
|
+
targetValue: field.int({
|
|
136
|
+
isOptional: true,
|
|
137
|
+
description: "Target value for completion"
|
|
138
|
+
}),
|
|
139
|
+
unlockedAt: field.dateTime({ description: "When unlocked" }),
|
|
140
|
+
createdAt: field.createdAt(),
|
|
141
|
+
learner: field.belongsTo("Learner", ["learnerId"], ["id"], { onDelete: "Cascade" }),
|
|
142
|
+
achievement: field.belongsTo("Achievement", ["achievementId"], ["id"], { onDelete: "Cascade" })
|
|
143
|
+
},
|
|
144
|
+
indexes: [
|
|
145
|
+
index.unique(["learnerId", "achievementId"], { name: "learner_achievement_unique" }),
|
|
146
|
+
index.on(["learnerId", "unlockedAt"]),
|
|
147
|
+
index.on(["achievementId"])
|
|
148
|
+
]
|
|
149
|
+
});
|
|
150
|
+
/**
|
|
151
|
+
* Streak entity - tracks daily learning streaks.
|
|
152
|
+
*/
|
|
153
|
+
const StreakEntity = defineEntity({
|
|
154
|
+
name: "Streak",
|
|
155
|
+
description: "Tracks daily learning streaks.",
|
|
156
|
+
schema: "lssm_learning",
|
|
157
|
+
map: "streak",
|
|
158
|
+
fields: {
|
|
159
|
+
id: field.id({ description: "Unique streak identifier" }),
|
|
160
|
+
learnerId: field.foreignKey({ description: "Learner" }),
|
|
161
|
+
currentStreak: field.int({
|
|
162
|
+
default: 0,
|
|
163
|
+
description: "Current streak days"
|
|
164
|
+
}),
|
|
165
|
+
longestStreak: field.int({
|
|
166
|
+
default: 0,
|
|
167
|
+
description: "Longest streak ever"
|
|
168
|
+
}),
|
|
169
|
+
lastActivityAt: field.dateTime({
|
|
170
|
+
isOptional: true,
|
|
171
|
+
description: "Last learning activity"
|
|
172
|
+
}),
|
|
173
|
+
lastActivityDate: field.string({
|
|
174
|
+
isOptional: true,
|
|
175
|
+
description: "Last activity date (YYYY-MM-DD)"
|
|
176
|
+
}),
|
|
177
|
+
freezesRemaining: field.int({
|
|
178
|
+
default: 0,
|
|
179
|
+
description: "Streak freezes available"
|
|
180
|
+
}),
|
|
181
|
+
freezeUsedAt: field.dateTime({
|
|
182
|
+
isOptional: true,
|
|
183
|
+
description: "When last freeze was used"
|
|
184
|
+
}),
|
|
185
|
+
streakHistory: field.json({
|
|
186
|
+
isOptional: true,
|
|
187
|
+
description: "Historical streak data"
|
|
188
|
+
}),
|
|
189
|
+
createdAt: field.createdAt(),
|
|
190
|
+
updatedAt: field.updatedAt(),
|
|
191
|
+
learner: field.belongsTo("Learner", ["learnerId"], ["id"], { onDelete: "Cascade" })
|
|
192
|
+
},
|
|
193
|
+
indexes: [
|
|
194
|
+
index.unique(["learnerId"], { name: "streak_learner_unique" }),
|
|
195
|
+
index.on(["currentStreak"]),
|
|
196
|
+
index.on(["longestStreak"])
|
|
197
|
+
]
|
|
198
|
+
});
|
|
199
|
+
/**
|
|
200
|
+
* DailyGoal entity - tracks daily XP goals.
|
|
201
|
+
*/
|
|
202
|
+
const DailyGoalEntity = defineEntity({
|
|
203
|
+
name: "DailyGoal",
|
|
204
|
+
description: "Daily XP goal tracking.",
|
|
205
|
+
schema: "lssm_learning",
|
|
206
|
+
map: "daily_goal",
|
|
207
|
+
fields: {
|
|
208
|
+
id: field.id({ description: "Unique goal identifier" }),
|
|
209
|
+
learnerId: field.foreignKey({ description: "Learner" }),
|
|
210
|
+
date: field.string({ description: "Date (YYYY-MM-DD)" }),
|
|
211
|
+
targetXp: field.int({ description: "Target XP for the day" }),
|
|
212
|
+
currentXp: field.int({
|
|
213
|
+
default: 0,
|
|
214
|
+
description: "XP earned today"
|
|
215
|
+
}),
|
|
216
|
+
isCompleted: field.boolean({
|
|
217
|
+
default: false,
|
|
218
|
+
description: "Whether goal was met"
|
|
219
|
+
}),
|
|
220
|
+
completedAt: field.dateTime({
|
|
221
|
+
isOptional: true,
|
|
222
|
+
description: "When goal was completed"
|
|
223
|
+
}),
|
|
224
|
+
xpBreakdown: field.json({
|
|
225
|
+
isOptional: true,
|
|
226
|
+
description: "XP sources breakdown"
|
|
227
|
+
}),
|
|
228
|
+
createdAt: field.createdAt(),
|
|
229
|
+
updatedAt: field.updatedAt(),
|
|
230
|
+
learner: field.belongsTo("Learner", ["learnerId"], ["id"], { onDelete: "Cascade" })
|
|
231
|
+
},
|
|
232
|
+
indexes: [index.unique(["learnerId", "date"], { name: "daily_goal_unique" }), index.on(["date", "isCompleted"])]
|
|
233
|
+
});
|
|
234
|
+
/**
|
|
235
|
+
* LeaderboardEntry entity - leaderboard rankings.
|
|
236
|
+
*/
|
|
237
|
+
const LeaderboardEntryEntity = defineEntity({
|
|
238
|
+
name: "LeaderboardEntry",
|
|
239
|
+
description: "Leaderboard entry for a learner.",
|
|
240
|
+
schema: "lssm_learning",
|
|
241
|
+
map: "leaderboard_entry",
|
|
242
|
+
fields: {
|
|
243
|
+
id: field.id({ description: "Unique entry identifier" }),
|
|
244
|
+
learnerId: field.foreignKey({ description: "Learner" }),
|
|
245
|
+
periodType: field.enum("LeaderboardPeriod", { description: "Period type" }),
|
|
246
|
+
periodKey: field.string({ description: "Period key (e.g., 2024-W01)" }),
|
|
247
|
+
xp: field.int({
|
|
248
|
+
default: 0,
|
|
249
|
+
description: "XP earned in period"
|
|
250
|
+
}),
|
|
251
|
+
rank: field.int({
|
|
252
|
+
isOptional: true,
|
|
253
|
+
description: "Rank in leaderboard"
|
|
254
|
+
}),
|
|
255
|
+
lessonsCompleted: field.int({
|
|
256
|
+
default: 0,
|
|
257
|
+
description: "Lessons completed"
|
|
258
|
+
}),
|
|
259
|
+
quizzesPassed: field.int({
|
|
260
|
+
default: 0,
|
|
261
|
+
description: "Quizzes passed"
|
|
262
|
+
}),
|
|
263
|
+
cardsReviewed: field.int({
|
|
264
|
+
default: 0,
|
|
265
|
+
description: "Cards reviewed"
|
|
266
|
+
}),
|
|
267
|
+
streakDays: field.int({
|
|
268
|
+
default: 0,
|
|
269
|
+
description: "Streak days in period"
|
|
270
|
+
}),
|
|
271
|
+
league: field.string({
|
|
272
|
+
isOptional: true,
|
|
273
|
+
description: "League tier"
|
|
274
|
+
}),
|
|
275
|
+
orgId: field.string({
|
|
276
|
+
isOptional: true,
|
|
277
|
+
description: "Organization scope"
|
|
278
|
+
}),
|
|
279
|
+
createdAt: field.createdAt(),
|
|
280
|
+
updatedAt: field.updatedAt(),
|
|
281
|
+
learner: field.belongsTo("Learner", ["learnerId"], ["id"], { onDelete: "Cascade" })
|
|
282
|
+
},
|
|
283
|
+
indexes: [
|
|
284
|
+
index.unique([
|
|
285
|
+
"learnerId",
|
|
286
|
+
"periodType",
|
|
287
|
+
"periodKey"
|
|
288
|
+
], { name: "leaderboard_entry_unique" }),
|
|
289
|
+
index.on([
|
|
290
|
+
"periodType",
|
|
291
|
+
"periodKey",
|
|
292
|
+
"xp"
|
|
293
|
+
]),
|
|
294
|
+
index.on([
|
|
295
|
+
"orgId",
|
|
296
|
+
"periodType",
|
|
297
|
+
"periodKey",
|
|
298
|
+
"xp"
|
|
299
|
+
])
|
|
300
|
+
],
|
|
301
|
+
enums: [LeaderboardPeriodEnum]
|
|
302
|
+
});
|
|
303
|
+
/**
|
|
304
|
+
* Heart entity - lives system (optional).
|
|
305
|
+
*/
|
|
306
|
+
const HeartEntity = defineEntity({
|
|
307
|
+
name: "Heart",
|
|
308
|
+
description: "Lives/hearts system for quiz attempts.",
|
|
309
|
+
schema: "lssm_learning",
|
|
310
|
+
map: "heart",
|
|
311
|
+
fields: {
|
|
312
|
+
id: field.id({ description: "Unique heart record identifier" }),
|
|
313
|
+
learnerId: field.foreignKey({ description: "Learner" }),
|
|
314
|
+
current: field.int({
|
|
315
|
+
default: 5,
|
|
316
|
+
description: "Current hearts"
|
|
317
|
+
}),
|
|
318
|
+
max: field.int({
|
|
319
|
+
default: 5,
|
|
320
|
+
description: "Maximum hearts"
|
|
321
|
+
}),
|
|
322
|
+
lastRefillAt: field.dateTime({
|
|
323
|
+
isOptional: true,
|
|
324
|
+
description: "Last refill time"
|
|
325
|
+
}),
|
|
326
|
+
nextRefillAt: field.dateTime({
|
|
327
|
+
isOptional: true,
|
|
328
|
+
description: "Next refill time"
|
|
329
|
+
}),
|
|
330
|
+
refillIntervalMinutes: field.int({
|
|
331
|
+
default: 240,
|
|
332
|
+
description: "Minutes between refills"
|
|
333
|
+
}),
|
|
334
|
+
infiniteUntil: field.dateTime({
|
|
335
|
+
isOptional: true,
|
|
336
|
+
description: "Infinite hearts until"
|
|
337
|
+
}),
|
|
338
|
+
createdAt: field.createdAt(),
|
|
339
|
+
updatedAt: field.updatedAt(),
|
|
340
|
+
learner: field.belongsTo("Learner", ["learnerId"], ["id"], { onDelete: "Cascade" })
|
|
341
|
+
},
|
|
342
|
+
indexes: [index.unique(["learnerId"], { name: "heart_learner_unique" }), index.on(["nextRefillAt"])]
|
|
343
|
+
});
|
|
344
|
+
/**
|
|
345
|
+
* XPTransaction entity - XP earning history.
|
|
346
|
+
*/
|
|
347
|
+
const XPTransactionEntity = defineEntity({
|
|
348
|
+
name: "XPTransaction",
|
|
349
|
+
description: "Record of XP earned or spent.",
|
|
350
|
+
schema: "lssm_learning",
|
|
351
|
+
map: "xp_transaction",
|
|
352
|
+
fields: {
|
|
353
|
+
id: field.id({ description: "Unique transaction identifier" }),
|
|
354
|
+
learnerId: field.foreignKey({ description: "Learner" }),
|
|
355
|
+
amount: field.int({ description: "XP amount (positive = earned, negative = spent)" }),
|
|
356
|
+
type: field.string({ description: "Transaction type (lesson, quiz, streak, achievement, etc.)" }),
|
|
357
|
+
sourceType: field.string({
|
|
358
|
+
isOptional: true,
|
|
359
|
+
description: "Source entity type"
|
|
360
|
+
}),
|
|
361
|
+
sourceId: field.string({
|
|
362
|
+
isOptional: true,
|
|
363
|
+
description: "Source entity ID"
|
|
364
|
+
}),
|
|
365
|
+
description: field.string({
|
|
366
|
+
isOptional: true,
|
|
367
|
+
description: "Human-readable description"
|
|
368
|
+
}),
|
|
369
|
+
balanceAfter: field.int({ description: "Total XP after transaction" }),
|
|
370
|
+
createdAt: field.createdAt(),
|
|
371
|
+
learner: field.belongsTo("Learner", ["learnerId"], ["id"], { onDelete: "Cascade" })
|
|
372
|
+
},
|
|
373
|
+
indexes: [
|
|
374
|
+
index.on(["learnerId", "createdAt"]),
|
|
375
|
+
index.on(["type"]),
|
|
376
|
+
index.on(["sourceType", "sourceId"])
|
|
377
|
+
]
|
|
378
|
+
});
|
|
379
|
+
const gamificationEntities = [
|
|
380
|
+
AchievementEntity,
|
|
381
|
+
LearnerAchievementEntity,
|
|
382
|
+
StreakEntity,
|
|
383
|
+
DailyGoalEntity,
|
|
384
|
+
LeaderboardEntryEntity,
|
|
385
|
+
HeartEntity,
|
|
386
|
+
XPTransactionEntity
|
|
387
|
+
];
|
|
388
|
+
const gamificationEnums = [AchievementTypeEnum, LeaderboardPeriodEnum];
|
|
389
|
+
|
|
390
|
+
//#endregion
|
|
391
|
+
export { AchievementEntity, AchievementTypeEnum, DailyGoalEntity, HeartEntity, LeaderboardEntryEntity, LeaderboardPeriodEnum, LearnerAchievementEntity, StreakEntity, XPTransactionEntity, gamificationEntities, gamificationEnums };
|
|
392
|
+
//# sourceMappingURL=gamification.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gamification.js","names":[],"sources":["../../src/entities/gamification.ts"],"sourcesContent":["import {\n defineEntity,\n defineEntityEnum,\n field,\n index,\n} from '@contractspec/lib.schema';\n\n/**\n * Achievement type enum.\n */\nexport const AchievementTypeEnum = defineEntityEnum({\n name: 'AchievementType',\n values: [\n 'MILESTONE',\n 'STREAK',\n 'SKILL',\n 'SOCIAL',\n 'SPECIAL',\n 'SEASONAL',\n ] as const,\n schema: 'lssm_learning',\n description: 'Type of achievement.',\n});\n\n/**\n * Leaderboard period enum.\n */\nexport const LeaderboardPeriodEnum = defineEntityEnum({\n name: 'LeaderboardPeriod',\n values: ['DAILY', 'WEEKLY', 'MONTHLY', 'ALL_TIME'] as const,\n schema: 'lssm_learning',\n description: 'Leaderboard time period.',\n});\n\n/**\n * Achievement entity - defines an achievement.\n */\nexport const AchievementEntity = defineEntity({\n name: 'Achievement',\n description: 'An achievement that can be unlocked.',\n schema: 'lssm_learning',\n map: 'achievement',\n fields: {\n id: field.id({ description: 'Unique achievement identifier' }),\n\n // Basic info\n key: field.string({ isUnique: true, description: 'Achievement key' }),\n name: field.string({ description: 'Achievement name' }),\n description: field.string({ description: 'Achievement description' }),\n\n // Display\n icon: field.string({ isOptional: true, description: 'Icon name or URL' }),\n color: field.string({ isOptional: true, description: 'Display color' }),\n badgeUrl: field.string({\n isOptional: true,\n description: 'Badge image URL',\n }),\n\n // Classification\n type: field.enum('AchievementType', {\n default: 'MILESTONE',\n description: 'Achievement type',\n }),\n category: field.string({\n isOptional: true,\n description: 'Achievement category',\n }),\n rarity: field.string({\n default: '\"common\"',\n description: 'Rarity: common, rare, epic, legendary',\n }),\n\n // Rewards\n xpReward: field.int({ default: 50, description: 'XP awarded' }),\n\n // Conditions (JSON DSL for checking)\n condition: field.json({ description: 'Unlock condition' }),\n\n // Ordering\n order: field.int({ default: 0, description: 'Display order' }),\n\n // Status\n isHidden: field.boolean({\n default: false,\n description: 'Hide until unlocked',\n }),\n isActive: field.boolean({\n default: true,\n description: 'Whether achievement is active',\n }),\n\n // Organization scope\n orgId: field.string({\n isOptional: true,\n description: 'Organization scope',\n }),\n\n // Metadata\n metadata: field.json({\n isOptional: true,\n description: 'Additional metadata',\n }),\n\n // Timestamps\n createdAt: field.createdAt(),\n updatedAt: field.updatedAt(),\n\n // Relations\n learnerAchievements: field.hasMany('LearnerAchievement'),\n },\n indexes: [\n index.on(['type']),\n index.on(['category']),\n index.on(['isActive']),\n index.on(['orgId']),\n ],\n enums: [AchievementTypeEnum],\n});\n\n/**\n * LearnerAchievement entity - unlocked achievements.\n */\nexport const LearnerAchievementEntity = defineEntity({\n name: 'LearnerAchievement',\n description: 'An achievement unlocked by a learner.',\n schema: 'lssm_learning',\n map: 'learner_achievement',\n fields: {\n id: field.id({ description: 'Unique record identifier' }),\n learnerId: field.foreignKey({ description: 'Learner' }),\n achievementId: field.foreignKey({ description: 'Achievement' }),\n\n // XP\n xpEarned: field.int({ default: 0, description: 'XP earned' }),\n\n // Progress (for multi-stage achievements)\n progress: field.int({ default: 100, description: 'Progress percentage' }),\n currentValue: field.int({\n isOptional: true,\n description: 'Current value towards goal',\n }),\n targetValue: field.int({\n isOptional: true,\n description: 'Target value for completion',\n }),\n\n // Timestamps\n unlockedAt: field.dateTime({ description: 'When unlocked' }),\n createdAt: field.createdAt(),\n\n // Relations\n learner: field.belongsTo('Learner', ['learnerId'], ['id'], {\n onDelete: 'Cascade',\n }),\n achievement: field.belongsTo('Achievement', ['achievementId'], ['id'], {\n onDelete: 'Cascade',\n }),\n },\n indexes: [\n index.unique(['learnerId', 'achievementId'], {\n name: 'learner_achievement_unique',\n }),\n index.on(['learnerId', 'unlockedAt']),\n index.on(['achievementId']),\n ],\n});\n\n/**\n * Streak entity - tracks daily learning streaks.\n */\nexport const StreakEntity = defineEntity({\n name: 'Streak',\n description: 'Tracks daily learning streaks.',\n schema: 'lssm_learning',\n map: 'streak',\n fields: {\n id: field.id({ description: 'Unique streak identifier' }),\n learnerId: field.foreignKey({ description: 'Learner' }),\n\n // Streak data\n currentStreak: field.int({\n default: 0,\n description: 'Current streak days',\n }),\n longestStreak: field.int({\n default: 0,\n description: 'Longest streak ever',\n }),\n\n // Activity tracking\n lastActivityAt: field.dateTime({\n isOptional: true,\n description: 'Last learning activity',\n }),\n lastActivityDate: field.string({\n isOptional: true,\n description: 'Last activity date (YYYY-MM-DD)',\n }),\n\n // Streak protection\n freezesRemaining: field.int({\n default: 0,\n description: 'Streak freezes available',\n }),\n freezeUsedAt: field.dateTime({\n isOptional: true,\n description: 'When last freeze was used',\n }),\n\n // History\n streakHistory: field.json({\n isOptional: true,\n description: 'Historical streak data',\n }),\n\n // Timestamps\n createdAt: field.createdAt(),\n updatedAt: field.updatedAt(),\n\n // Relations\n learner: field.belongsTo('Learner', ['learnerId'], ['id'], {\n onDelete: 'Cascade',\n }),\n },\n indexes: [\n index.unique(['learnerId'], { name: 'streak_learner_unique' }),\n index.on(['currentStreak']),\n index.on(['longestStreak']),\n ],\n});\n\n/**\n * DailyGoal entity - tracks daily XP goals.\n */\nexport const DailyGoalEntity = defineEntity({\n name: 'DailyGoal',\n description: 'Daily XP goal tracking.',\n schema: 'lssm_learning',\n map: 'daily_goal',\n fields: {\n id: field.id({ description: 'Unique goal identifier' }),\n learnerId: field.foreignKey({ description: 'Learner' }),\n\n // Date\n date: field.string({ description: 'Date (YYYY-MM-DD)' }),\n\n // Goal\n targetXp: field.int({ description: 'Target XP for the day' }),\n currentXp: field.int({ default: 0, description: 'XP earned today' }),\n\n // Status\n isCompleted: field.boolean({\n default: false,\n description: 'Whether goal was met',\n }),\n completedAt: field.dateTime({\n isOptional: true,\n description: 'When goal was completed',\n }),\n\n // Breakdown\n xpBreakdown: field.json({\n isOptional: true,\n description: 'XP sources breakdown',\n }),\n\n // Timestamps\n createdAt: field.createdAt(),\n updatedAt: field.updatedAt(),\n\n // Relations\n learner: field.belongsTo('Learner', ['learnerId'], ['id'], {\n onDelete: 'Cascade',\n }),\n },\n indexes: [\n index.unique(['learnerId', 'date'], { name: 'daily_goal_unique' }),\n index.on(['date', 'isCompleted']),\n ],\n});\n\n/**\n * LeaderboardEntry entity - leaderboard rankings.\n */\nexport const LeaderboardEntryEntity = defineEntity({\n name: 'LeaderboardEntry',\n description: 'Leaderboard entry for a learner.',\n schema: 'lssm_learning',\n map: 'leaderboard_entry',\n fields: {\n id: field.id({ description: 'Unique entry identifier' }),\n learnerId: field.foreignKey({ description: 'Learner' }),\n\n // Period\n periodType: field.enum('LeaderboardPeriod', { description: 'Period type' }),\n periodKey: field.string({ description: 'Period key (e.g., 2024-W01)' }),\n\n // Stats\n xp: field.int({ default: 0, description: 'XP earned in period' }),\n rank: field.int({ isOptional: true, description: 'Rank in leaderboard' }),\n\n // Breakdown\n lessonsCompleted: field.int({\n default: 0,\n description: 'Lessons completed',\n }),\n quizzesPassed: field.int({ default: 0, description: 'Quizzes passed' }),\n cardsReviewed: field.int({ default: 0, description: 'Cards reviewed' }),\n streakDays: field.int({ default: 0, description: 'Streak days in period' }),\n\n // League (optional grouping)\n league: field.string({ isOptional: true, description: 'League tier' }),\n\n // Organization scope\n orgId: field.string({\n isOptional: true,\n description: 'Organization scope',\n }),\n\n // Timestamps\n createdAt: field.createdAt(),\n updatedAt: field.updatedAt(),\n\n // Relations\n learner: field.belongsTo('Learner', ['learnerId'], ['id'], {\n onDelete: 'Cascade',\n }),\n },\n indexes: [\n index.unique(['learnerId', 'periodType', 'periodKey'], {\n name: 'leaderboard_entry_unique',\n }),\n index.on(['periodType', 'periodKey', 'xp']),\n index.on(['orgId', 'periodType', 'periodKey', 'xp']),\n ],\n enums: [LeaderboardPeriodEnum],\n});\n\n/**\n * Heart entity - lives system (optional).\n */\nexport const HeartEntity = defineEntity({\n name: 'Heart',\n description: 'Lives/hearts system for quiz attempts.',\n schema: 'lssm_learning',\n map: 'heart',\n fields: {\n id: field.id({ description: 'Unique heart record identifier' }),\n learnerId: field.foreignKey({ description: 'Learner' }),\n\n // Hearts\n current: field.int({ default: 5, description: 'Current hearts' }),\n max: field.int({ default: 5, description: 'Maximum hearts' }),\n\n // Refill\n lastRefillAt: field.dateTime({\n isOptional: true,\n description: 'Last refill time',\n }),\n nextRefillAt: field.dateTime({\n isOptional: true,\n description: 'Next refill time',\n }),\n\n // Settings\n refillIntervalMinutes: field.int({\n default: 240,\n description: 'Minutes between refills',\n }),\n infiniteUntil: field.dateTime({\n isOptional: true,\n description: 'Infinite hearts until',\n }),\n\n // Timestamps\n createdAt: field.createdAt(),\n updatedAt: field.updatedAt(),\n\n // Relations\n learner: field.belongsTo('Learner', ['learnerId'], ['id'], {\n onDelete: 'Cascade',\n }),\n },\n indexes: [\n index.unique(['learnerId'], { name: 'heart_learner_unique' }),\n index.on(['nextRefillAt']),\n ],\n});\n\n/**\n * XPTransaction entity - XP earning history.\n */\nexport const XPTransactionEntity = defineEntity({\n name: 'XPTransaction',\n description: 'Record of XP earned or spent.',\n schema: 'lssm_learning',\n map: 'xp_transaction',\n fields: {\n id: field.id({ description: 'Unique transaction identifier' }),\n learnerId: field.foreignKey({ description: 'Learner' }),\n\n // Transaction\n amount: field.int({\n description: 'XP amount (positive = earned, negative = spent)',\n }),\n type: field.string({\n description: 'Transaction type (lesson, quiz, streak, achievement, etc.)',\n }),\n\n // Source\n sourceType: field.string({\n isOptional: true,\n description: 'Source entity type',\n }),\n sourceId: field.string({\n isOptional: true,\n description: 'Source entity ID',\n }),\n\n // Description\n description: field.string({\n isOptional: true,\n description: 'Human-readable description',\n }),\n\n // Balance\n balanceAfter: field.int({ description: 'Total XP after transaction' }),\n\n // Timestamps\n createdAt: field.createdAt(),\n\n // Relations\n learner: field.belongsTo('Learner', ['learnerId'], ['id'], {\n onDelete: 'Cascade',\n }),\n },\n indexes: [\n index.on(['learnerId', 'createdAt']),\n index.on(['type']),\n index.on(['sourceType', 'sourceId']),\n ],\n});\n\nexport const gamificationEntities = [\n AchievementEntity,\n LearnerAchievementEntity,\n StreakEntity,\n DailyGoalEntity,\n LeaderboardEntryEntity,\n HeartEntity,\n XPTransactionEntity,\n];\n\nexport const gamificationEnums = [AchievementTypeEnum, LeaderboardPeriodEnum];\n"],"mappings":"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"}
|