@lssm/module.learning-journey 1.41.1 → 1.42.1

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.
Files changed (84) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +13 -0
  3. package/dist/contracts/index.d.ts +5 -0
  4. package/dist/contracts/index.js +6 -1
  5. package/dist/contracts/models.d.ts +451 -0
  6. package/dist/contracts/models.d.ts.map +1 -0
  7. package/dist/contracts/models.js +388 -1
  8. package/dist/contracts/models.js.map +1 -0
  9. package/dist/contracts/onboarding.d.ts +666 -0
  10. package/dist/contracts/onboarding.d.ts.map +1 -0
  11. package/dist/contracts/onboarding.js +402 -1
  12. package/dist/contracts/onboarding.js.map +1 -0
  13. package/dist/contracts/operations.d.ts +280 -0
  14. package/dist/contracts/operations.d.ts.map +1 -0
  15. package/dist/contracts/operations.js +151 -1
  16. package/dist/contracts/operations.js.map +1 -0
  17. package/dist/contracts/shared.d.ts +5 -0
  18. package/dist/contracts/shared.d.ts.map +1 -0
  19. package/dist/contracts/shared.js +6 -1
  20. package/dist/contracts/shared.js.map +1 -0
  21. package/dist/docs/index.d.ts +1 -0
  22. package/dist/docs/index.js +1 -1
  23. package/dist/docs/learning-journey.docblock.d.ts +1 -0
  24. package/dist/docs/learning-journey.docblock.js +61 -5
  25. package/dist/docs/learning-journey.docblock.js.map +1 -0
  26. package/dist/engines/index.d.ts +4 -0
  27. package/dist/engines/index.js +5 -1
  28. package/dist/engines/srs.d.ts +111 -0
  29. package/dist/engines/srs.d.ts.map +1 -0
  30. package/dist/engines/srs.js +219 -1
  31. package/dist/engines/srs.js.map +1 -0
  32. package/dist/engines/streak.d.ts +100 -0
  33. package/dist/engines/streak.d.ts.map +1 -0
  34. package/dist/engines/streak.js +194 -1
  35. package/dist/engines/streak.js.map +1 -0
  36. package/dist/engines/xp.d.ts +97 -0
  37. package/dist/engines/xp.d.ts.map +1 -0
  38. package/dist/engines/xp.js +213 -1
  39. package/dist/engines/xp.js.map +1 -0
  40. package/dist/entities/ai.d.ts +232 -0
  41. package/dist/entities/ai.d.ts.map +1 -0
  42. package/dist/entities/ai.js +376 -1
  43. package/dist/entities/ai.js.map +1 -0
  44. package/dist/entities/course.d.ts +184 -0
  45. package/dist/entities/course.d.ts.map +1 -0
  46. package/dist/entities/course.js +316 -1
  47. package/dist/entities/course.js.map +1 -0
  48. package/dist/entities/flashcard.d.ts +170 -0
  49. package/dist/entities/flashcard.d.ts.map +1 -0
  50. package/dist/entities/flashcard.js +249 -1
  51. package/dist/entities/flashcard.js.map +1 -0
  52. package/dist/entities/gamification.d.ts +238 -0
  53. package/dist/entities/gamification.d.ts.map +1 -0
  54. package/dist/entities/gamification.js +392 -1
  55. package/dist/entities/gamification.js.map +1 -0
  56. package/dist/entities/index.d.ts +629 -0
  57. package/dist/entities/index.d.ts.map +1 -0
  58. package/dist/entities/index.js +45 -1
  59. package/dist/entities/index.js.map +1 -0
  60. package/dist/entities/learner.d.ts +224 -0
  61. package/dist/entities/learner.d.ts.map +1 -0
  62. package/dist/entities/learner.js +365 -1
  63. package/dist/entities/learner.js.map +1 -0
  64. package/dist/entities/onboarding.d.ts +190 -0
  65. package/dist/entities/onboarding.d.ts.map +1 -0
  66. package/dist/entities/onboarding.js +307 -1
  67. package/dist/entities/onboarding.js.map +1 -0
  68. package/dist/entities/quiz.d.ts +220 -0
  69. package/dist/entities/quiz.d.ts.map +1 -0
  70. package/dist/entities/quiz.js +370 -1
  71. package/dist/entities/quiz.js.map +1 -0
  72. package/dist/events.d.ts +796 -0
  73. package/dist/events.d.ts.map +1 -0
  74. package/dist/events.js +690 -1
  75. package/dist/events.js.map +1 -0
  76. package/dist/index.d.ts +20 -0
  77. package/dist/index.js +22 -1
  78. package/dist/learning-journey.feature.d.ts +12 -0
  79. package/dist/learning-journey.feature.d.ts.map +1 -0
  80. package/dist/learning-journey.feature.js +150 -1
  81. package/dist/learning-journey.feature.js.map +1 -0
  82. package/dist/track-spec.d.ts +129 -0
  83. package/dist/track-spec.d.ts.map +1 -0
  84. package/package.json +37 -30
@@ -0,0 +1 @@
1
+ {"version":3,"file":"streak.js","names":["DEFAULT_STREAK_CONFIG: StreakConfig","result: StreakUpdateResult"],"sources":["../../src/engines/streak.ts"],"sourcesContent":["/**\n * Streak Tracking Engine\n *\n * Manages daily learning streaks with timezone support and freeze protection.\n */\n\n// ============ Types ============\n\nexport interface StreakState {\n /** Current streak days */\n currentStreak: number;\n /** Longest streak ever */\n longestStreak: number;\n /** Last activity timestamp */\n lastActivityAt: Date | null;\n /** Last activity date (YYYY-MM-DD) */\n lastActivityDate: string | null;\n /** Available streak freezes */\n freezesRemaining: number;\n /** When a freeze was last used */\n freezeUsedAt: Date | null;\n}\n\nexport interface StreakUpdateResult {\n /** Updated streak state */\n state: StreakState;\n /** Whether streak was maintained */\n streakMaintained: boolean;\n /** Whether streak was lost */\n streakLost: boolean;\n /** Whether a freeze was used */\n freezeUsed: boolean;\n /** Whether this activity started a new streak */\n newStreak: boolean;\n /** Days missed (if streak was lost) */\n daysMissed: number;\n}\n\nexport interface StreakConfig {\n /** Timezone for the user */\n timezone: string;\n /** How many streak freezes to give per month */\n freezesPerMonth: number;\n /** Maximum freezes that can be accumulated */\n maxFreezes: number;\n /** Grace period in hours after midnight */\n gracePeriodHours: number;\n}\n\n// ============ Default Configuration ============\n\nexport const DEFAULT_STREAK_CONFIG: StreakConfig = {\n timezone: 'UTC',\n freezesPerMonth: 2,\n maxFreezes: 5,\n gracePeriodHours: 4, // 4 hours grace period\n};\n\n// ============ Streak Engine ============\n\nexport class StreakEngine {\n private config: StreakConfig;\n\n constructor(config: Partial<StreakConfig> = {}) {\n this.config = { ...DEFAULT_STREAK_CONFIG, ...config };\n }\n\n /**\n * Update streak based on new activity.\n */\n update(state: StreakState, now: Date = new Date()): StreakUpdateResult {\n const todayDate = this.getDateString(now);\n const result: StreakUpdateResult = {\n state: { ...state },\n streakMaintained: false,\n streakLost: false,\n freezeUsed: false,\n newStreak: false,\n daysMissed: 0,\n };\n\n // If no previous activity, start new streak\n if (!state.lastActivityDate) {\n result.state.currentStreak = 1;\n result.state.longestStreak = Math.max(1, state.longestStreak);\n result.state.lastActivityAt = now;\n result.state.lastActivityDate = todayDate;\n result.newStreak = true;\n result.streakMaintained = true;\n return result;\n }\n\n // Check if activity is on the same day\n if (state.lastActivityDate === todayDate) {\n // Same day - just update timestamp, streak unchanged\n result.state.lastActivityAt = now;\n result.streakMaintained = true;\n return result;\n }\n\n // Calculate days since last activity\n const daysSinceActivity = this.getDaysBetween(\n state.lastActivityDate,\n todayDate\n );\n\n if (daysSinceActivity === 1) {\n // Perfect - activity on consecutive day\n result.state.currentStreak = state.currentStreak + 1;\n result.state.longestStreak = Math.max(\n result.state.currentStreak,\n state.longestStreak\n );\n result.state.lastActivityAt = now;\n result.state.lastActivityDate = todayDate;\n result.streakMaintained = true;\n return result;\n }\n\n // Streak was potentially broken\n result.daysMissed = daysSinceActivity - 1;\n\n // Check if we can use freezes\n const freezesNeeded = result.daysMissed;\n if (freezesNeeded <= state.freezesRemaining) {\n // Use freezes to maintain streak\n result.state.freezesRemaining = state.freezesRemaining - freezesNeeded;\n result.state.freezeUsedAt = now;\n result.state.currentStreak = state.currentStreak + 1; // Add today\n result.state.longestStreak = Math.max(\n result.state.currentStreak,\n state.longestStreak\n );\n result.state.lastActivityAt = now;\n result.state.lastActivityDate = todayDate;\n result.freezeUsed = true;\n result.streakMaintained = true;\n return result;\n }\n\n // Streak is lost\n result.streakLost = true;\n result.state.currentStreak = 1; // Start new streak\n result.state.lastActivityAt = now;\n result.state.lastActivityDate = todayDate;\n result.newStreak = true;\n return result;\n }\n\n /**\n * Check streak status without recording activity.\n */\n checkStatus(\n state: StreakState,\n now: Date = new Date()\n ): {\n isActive: boolean;\n willExpireAt: Date | null;\n canUseFreeze: boolean;\n daysUntilExpiry: number;\n } {\n if (!state.lastActivityDate) {\n return {\n isActive: false,\n willExpireAt: null,\n canUseFreeze: false,\n daysUntilExpiry: 0,\n };\n }\n\n const todayDate = this.getDateString(now);\n const daysSinceActivity = this.getDaysBetween(\n state.lastActivityDate,\n todayDate\n );\n\n if (daysSinceActivity === 0) {\n // Activity today - streak is active\n const tomorrow = this.addDays(now, 1);\n tomorrow.setHours(23, 59, 59, 999);\n return {\n isActive: true,\n willExpireAt: tomorrow,\n canUseFreeze: state.freezesRemaining > 0,\n daysUntilExpiry: 1,\n };\n }\n\n if (daysSinceActivity === 1) {\n // No activity today yet, but still within window\n const endOfDay = new Date(now);\n endOfDay.setHours(23 + this.config.gracePeriodHours, 59, 59, 999);\n return {\n isActive: true,\n willExpireAt: endOfDay,\n canUseFreeze: state.freezesRemaining > 0,\n daysUntilExpiry: 0,\n };\n }\n\n // Streak would be broken\n const missedDays = daysSinceActivity - 1;\n return {\n isActive: missedDays <= state.freezesRemaining,\n willExpireAt: null,\n canUseFreeze: missedDays <= state.freezesRemaining,\n daysUntilExpiry: -missedDays,\n };\n }\n\n /**\n * Manually use a freeze to protect streak.\n */\n useFreeze(state: StreakState, now: Date = new Date()): StreakState | null {\n if (state.freezesRemaining <= 0) {\n return null;\n }\n\n return {\n ...state,\n freezesRemaining: state.freezesRemaining - 1,\n freezeUsedAt: now,\n };\n }\n\n /**\n * Award monthly freezes.\n */\n awardMonthlyFreezes(state: StreakState): StreakState {\n return {\n ...state,\n freezesRemaining: Math.min(\n state.freezesRemaining + this.config.freezesPerMonth,\n this.config.maxFreezes\n ),\n };\n }\n\n /**\n * Get initial streak state.\n */\n getInitialState(): StreakState {\n return {\n currentStreak: 0,\n longestStreak: 0,\n lastActivityAt: null,\n lastActivityDate: null,\n freezesRemaining: this.config.freezesPerMonth,\n freezeUsedAt: null,\n };\n }\n\n /**\n * Calculate streak milestones.\n */\n getMilestones(currentStreak: number): {\n achieved: number[];\n next: number | null;\n } {\n const milestones = [3, 7, 14, 30, 60, 90, 180, 365, 500, 1000];\n const achieved = milestones.filter((m) => currentStreak >= m);\n const next = milestones.find((m) => currentStreak < m) ?? null;\n return { achieved, next };\n }\n\n // ============ Helpers ============\n\n /**\n * Get date string in YYYY-MM-DD format.\n */\n private getDateString(date: Date): string {\n // Simple implementation - for production, use a proper timezone library\n const year = date.getFullYear();\n const month = String(date.getMonth() + 1).padStart(2, '0');\n const day = String(date.getDate()).padStart(2, '0');\n return `${year}-${month}-${day}`;\n }\n\n /**\n * Get number of days between two date strings.\n */\n private getDaysBetween(dateStr1: string, dateStr2: string): number {\n const date1 = new Date(dateStr1);\n const date2 = new Date(dateStr2);\n const diffTime = date2.getTime() - date1.getTime();\n return Math.floor(diffTime / (1000 * 60 * 60 * 24));\n }\n\n /**\n * Add days to a date.\n */\n private addDays(date: Date, days: number): Date {\n return new Date(date.getTime() + days * 24 * 60 * 60 * 1000);\n }\n}\n\n/**\n * Default streak engine instance.\n */\nexport const streakEngine = new StreakEngine();\n"],"mappings":"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"}
@@ -0,0 +1,97 @@
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 };
97
+ //# sourceMappingURL=xp.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"xp.d.ts","names":[],"sources":["../../src/engines/xp.ts"],"sourcesContent":[],"mappings":";;AAQA;AAcA;AAiBA;AASA;AASiB,KAjDL,cAAA,GAmDS,iBAAP,GAAA,WAAM,GAAA,cAAA,GAAA,kBAAA,GAAA,iBAAA,GAAA,iBAAA,GAAA,cAAA,GAAA,oBAAA,GAAA,qBAAA,GAAA,cAAA,GAAA,iBAAA,GAAA,qBAAA;AAmBP,UAxDI,kBAAA,CAwDe;EAyCnB;EAGiB,QAAA,EAlGlB,cAkGkB;EAAR;EAcH,MAAA,CAAA,EAAA,MAAA;EAAqB;EAsFO,KAAA,CAAA,EAAA,MAAA;EAAQ;EA6E1C,aAAyB,CAAA,EAAA,MAAA;;;;;;;;UApQrB,QAAA;;;;;;aAMJ;;UAGI,WAAA;;;;;;;;UASA,QAAA;;cAEH,OAAO;;;;;;;;;;;;;;;;;;;;;;cAmBR,mBAAmB;cAyCnB,QAAA;;uBAGS,QAAQ;;;;mBAcX,qBAAqB;;;;+CAsFO;;;;;;;;;;;;;;;;;;;cA6ElC,UAAQ"}
@@ -1 +1,213 @@
1
- const e={baseValues:{lesson_complete:10,quiz_pass:20,quiz_perfect:50,flashcard_review:1,course_complete:200,module_complete:50,streak_bonus:5,achievement_unlock:0,daily_goal_complete:15,first_lesson:25,onboarding_step:5,onboarding_complete:50},scoreThresholds:[{min:90,multiplier:1.5},{min:80,multiplier:1.25},{min:70,multiplier:1},{min:60,multiplier:.75},{min:0,multiplier:.5}],streakTiers:[{days:365,bonus:50},{days:180,bonus:30},{days:90,bonus:20},{days:30,bonus:15},{days:14,bonus:10},{days:7,bonus:5},{days:3,bonus:2},{days:1,bonus:0}],perfectScoreMultiplier:1.5,firstAttemptBonus:10,retryPenalty:.5,speedBonusMultiplier:1.2,speedBonusThreshold:.8};var t=class{config;constructor(t={}){this.config={...e,...t,baseValues:{...e.baseValues,...t.baseValues},scoreThresholds:t.scoreThresholds||e.scoreThresholds,streakTiers:t.streakTiers||e.streakTiers}}calculate(e){let t=[],n=e.baseXp??this.config.baseValues[e.activity],r=n;if(t.push({source:`base`,amount:n}),e.score!==void 0){let i=this.getScoreMultiplier(e.score);if(i!==1){let e=Math.round(n*(i-1));r+=e,t.push({source:`score_bonus`,amount:e,multiplier:i})}if(e.score===100){let e=Math.round(n*(this.config.perfectScoreMultiplier-1));r+=e,t.push({source:`perfect_score`,amount:e,multiplier:this.config.perfectScoreMultiplier})}}if(e.attemptNumber===1&&!e.isRetry&&(r+=this.config.firstAttemptBonus,t.push({source:`first_attempt`,amount:this.config.firstAttemptBonus})),e.isRetry){let e=Math.round(r*(1-this.config.retryPenalty));r-=e,t.push({source:`retry_penalty`,amount:-e,multiplier:this.config.retryPenalty})}if(e.currentStreak&&e.currentStreak>0){let n=this.getStreakBonus(e.currentStreak);n>0&&(r+=n,t.push({source:`streak_bonus`,amount:n}))}return n>0&&(r=Math.max(1,r)),{totalXp:Math.round(r),baseXp:n,breakdown:t}}calculateStreakBonus(e){let t=this.getStreakBonus(e);return{totalXp:t,baseXp:t,breakdown:[{source:`streak_bonus`,amount:t}]}}getXpForLevel(e){return e<=1?0:Math.round(100*(e-1)**1.5)}getLevelFromXp(e){let t=1,n=this.getXpForLevel(t+1);for(;e>=n&&t<1e3;)t++,n=this.getXpForLevel(t+1);let r=this.getXpForLevel(t),i=this.getXpForLevel(t+1);return{level:t,xpInLevel:e-r,xpForNextLevel:i-r}}getScoreMultiplier(e){for(let t of this.config.scoreThresholds)if(e>=t.min)return t.multiplier;return 1}getStreakBonus(e){for(let t of this.config.streakTiers)if(e>=t.days)return t.bonus;return 0}};const n=new t;export{e as DEFAULT_XP_CONFIG,t as XPEngine,n as xpEngine};
1
+ //#region src/engines/xp.ts
2
+ const DEFAULT_XP_CONFIG = {
3
+ baseValues: {
4
+ lesson_complete: 10,
5
+ quiz_pass: 20,
6
+ quiz_perfect: 50,
7
+ flashcard_review: 1,
8
+ course_complete: 200,
9
+ module_complete: 50,
10
+ streak_bonus: 5,
11
+ achievement_unlock: 0,
12
+ daily_goal_complete: 15,
13
+ first_lesson: 25,
14
+ onboarding_step: 5,
15
+ onboarding_complete: 50
16
+ },
17
+ scoreThresholds: [
18
+ {
19
+ min: 90,
20
+ multiplier: 1.5
21
+ },
22
+ {
23
+ min: 80,
24
+ multiplier: 1.25
25
+ },
26
+ {
27
+ min: 70,
28
+ multiplier: 1
29
+ },
30
+ {
31
+ min: 60,
32
+ multiplier: .75
33
+ },
34
+ {
35
+ min: 0,
36
+ multiplier: .5
37
+ }
38
+ ],
39
+ streakTiers: [
40
+ {
41
+ days: 365,
42
+ bonus: 50
43
+ },
44
+ {
45
+ days: 180,
46
+ bonus: 30
47
+ },
48
+ {
49
+ days: 90,
50
+ bonus: 20
51
+ },
52
+ {
53
+ days: 30,
54
+ bonus: 15
55
+ },
56
+ {
57
+ days: 14,
58
+ bonus: 10
59
+ },
60
+ {
61
+ days: 7,
62
+ bonus: 5
63
+ },
64
+ {
65
+ days: 3,
66
+ bonus: 2
67
+ },
68
+ {
69
+ days: 1,
70
+ bonus: 0
71
+ }
72
+ ],
73
+ perfectScoreMultiplier: 1.5,
74
+ firstAttemptBonus: 10,
75
+ retryPenalty: .5,
76
+ speedBonusMultiplier: 1.2,
77
+ speedBonusThreshold: .8
78
+ };
79
+ var XPEngine = class {
80
+ config;
81
+ constructor(config = {}) {
82
+ this.config = {
83
+ ...DEFAULT_XP_CONFIG,
84
+ ...config,
85
+ baseValues: {
86
+ ...DEFAULT_XP_CONFIG.baseValues,
87
+ ...config.baseValues
88
+ },
89
+ scoreThresholds: config.scoreThresholds || DEFAULT_XP_CONFIG.scoreThresholds,
90
+ streakTiers: config.streakTiers || DEFAULT_XP_CONFIG.streakTiers
91
+ };
92
+ }
93
+ /**
94
+ * Calculate XP for an activity.
95
+ */
96
+ calculate(input) {
97
+ const breakdown = [];
98
+ const baseXp = input.baseXp ?? this.config.baseValues[input.activity];
99
+ let totalXp = baseXp;
100
+ breakdown.push({
101
+ source: "base",
102
+ amount: baseXp
103
+ });
104
+ if (input.score !== void 0) {
105
+ const scoreMultiplier = this.getScoreMultiplier(input.score);
106
+ if (scoreMultiplier !== 1) {
107
+ const scoreBonus = Math.round(baseXp * (scoreMultiplier - 1));
108
+ totalXp += scoreBonus;
109
+ breakdown.push({
110
+ source: "score_bonus",
111
+ amount: scoreBonus,
112
+ multiplier: scoreMultiplier
113
+ });
114
+ }
115
+ if (input.score === 100) {
116
+ const perfectBonus = Math.round(baseXp * (this.config.perfectScoreMultiplier - 1));
117
+ totalXp += perfectBonus;
118
+ breakdown.push({
119
+ source: "perfect_score",
120
+ amount: perfectBonus,
121
+ multiplier: this.config.perfectScoreMultiplier
122
+ });
123
+ }
124
+ }
125
+ if (input.attemptNumber === 1 && !input.isRetry) {
126
+ totalXp += this.config.firstAttemptBonus;
127
+ breakdown.push({
128
+ source: "first_attempt",
129
+ amount: this.config.firstAttemptBonus
130
+ });
131
+ }
132
+ if (input.isRetry) {
133
+ const penalty = Math.round(totalXp * (1 - this.config.retryPenalty));
134
+ totalXp -= penalty;
135
+ breakdown.push({
136
+ source: "retry_penalty",
137
+ amount: -penalty,
138
+ multiplier: this.config.retryPenalty
139
+ });
140
+ }
141
+ if (input.currentStreak && input.currentStreak > 0) {
142
+ const streakBonus = this.getStreakBonus(input.currentStreak);
143
+ if (streakBonus > 0) {
144
+ totalXp += streakBonus;
145
+ breakdown.push({
146
+ source: "streak_bonus",
147
+ amount: streakBonus
148
+ });
149
+ }
150
+ }
151
+ if (baseXp > 0) totalXp = Math.max(1, totalXp);
152
+ return {
153
+ totalXp: Math.round(totalXp),
154
+ baseXp,
155
+ breakdown
156
+ };
157
+ }
158
+ /**
159
+ * Calculate streak bonus XP.
160
+ */
161
+ calculateStreakBonus(currentStreak) {
162
+ const bonus = this.getStreakBonus(currentStreak);
163
+ return {
164
+ totalXp: bonus,
165
+ baseXp: bonus,
166
+ breakdown: [{
167
+ source: "streak_bonus",
168
+ amount: bonus
169
+ }]
170
+ };
171
+ }
172
+ /**
173
+ * Calculate XP needed for a level.
174
+ */
175
+ getXpForLevel(level) {
176
+ if (level <= 1) return 0;
177
+ return Math.round(100 * Math.pow(level - 1, 1.5));
178
+ }
179
+ /**
180
+ * Get level from total XP.
181
+ */
182
+ getLevelFromXp(totalXp) {
183
+ let level = 1;
184
+ let xpRequired = this.getXpForLevel(level + 1);
185
+ while (totalXp >= xpRequired && level < 1e3) {
186
+ level++;
187
+ xpRequired = this.getXpForLevel(level + 1);
188
+ }
189
+ const xpForCurrentLevel = this.getXpForLevel(level);
190
+ const xpForNextLevel = this.getXpForLevel(level + 1);
191
+ return {
192
+ level,
193
+ xpInLevel: totalXp - xpForCurrentLevel,
194
+ xpForNextLevel: xpForNextLevel - xpForCurrentLevel
195
+ };
196
+ }
197
+ getScoreMultiplier(score) {
198
+ for (const threshold of this.config.scoreThresholds) if (score >= threshold.min) return threshold.multiplier;
199
+ return 1;
200
+ }
201
+ getStreakBonus(streak) {
202
+ for (const tier of this.config.streakTiers) if (streak >= tier.days) return tier.bonus;
203
+ return 0;
204
+ }
205
+ };
206
+ /**
207
+ * Default XP engine instance.
208
+ */
209
+ const xpEngine = new XPEngine();
210
+
211
+ //#endregion
212
+ export { DEFAULT_XP_CONFIG, XPEngine, xpEngine };
213
+ //# sourceMappingURL=xp.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"xp.js","names":["DEFAULT_XP_CONFIG: XPConfig","breakdown: XPBreakdown[]"],"sources":["../../src/engines/xp.ts"],"sourcesContent":["/**\n * XP (Experience Points) Engine\n *\n * Calculates XP rewards for various learning activities.\n */\n\n// ============ Types ============\n\nexport type XPActivityType =\n | 'lesson_complete'\n | 'quiz_pass'\n | 'quiz_perfect'\n | 'flashcard_review'\n | 'course_complete'\n | 'module_complete'\n | 'streak_bonus'\n | 'achievement_unlock'\n | 'daily_goal_complete'\n | 'first_lesson'\n | 'onboarding_step'\n | 'onboarding_complete';\n\nexport interface XPCalculationInput {\n /** Type of activity */\n activity: XPActivityType;\n /** Base XP for the activity (from content config) */\n baseXp?: number;\n /** Score achieved (0-100) for scored activities */\n score?: number;\n /** Current streak (for streak bonuses) */\n currentStreak?: number;\n /** Time spent in seconds */\n timeSpent?: number;\n /** Attempt number (for quizzes) */\n attemptNumber?: number;\n /** Whether this is a retry */\n isRetry?: boolean;\n}\n\nexport interface XPResult {\n /** Total XP earned */\n totalXp: number;\n /** Base XP before bonuses */\n baseXp: number;\n /** Breakdown of XP sources */\n breakdown: XPBreakdown[];\n}\n\nexport interface XPBreakdown {\n /** Source of XP */\n source: string;\n /** XP amount */\n amount: number;\n /** Multiplier applied */\n multiplier?: number;\n}\n\nexport interface XPConfig {\n /** Base XP values for each activity */\n baseValues: Record<XPActivityType, number>;\n /** Score thresholds for bonus XP */\n scoreThresholds: { min: number; multiplier: number }[];\n /** Streak bonus tiers */\n streakTiers: { days: number; bonus: number }[];\n /** Perfect score bonus multiplier */\n perfectScoreMultiplier: number;\n /** First attempt bonus */\n firstAttemptBonus: number;\n /** Retry penalty multiplier */\n retryPenalty: number;\n /** Speed bonus (complete under expected time) */\n speedBonusMultiplier: number;\n /** Speed bonus threshold (percentage of expected time) */\n speedBonusThreshold: number;\n}\n\n// ============ Default Configuration ============\n\nexport const DEFAULT_XP_CONFIG: XPConfig = {\n baseValues: {\n lesson_complete: 10,\n quiz_pass: 20,\n quiz_perfect: 50,\n flashcard_review: 1,\n course_complete: 200,\n module_complete: 50,\n streak_bonus: 5,\n achievement_unlock: 0, // XP comes from achievement\n daily_goal_complete: 15,\n first_lesson: 25,\n onboarding_step: 5,\n onboarding_complete: 50,\n },\n scoreThresholds: [\n { min: 90, multiplier: 1.5 },\n { min: 80, multiplier: 1.25 },\n { min: 70, multiplier: 1.0 },\n { min: 60, multiplier: 0.75 },\n { min: 0, multiplier: 0.5 },\n ],\n streakTiers: [\n { days: 365, bonus: 50 },\n { days: 180, bonus: 30 },\n { days: 90, bonus: 20 },\n { days: 30, bonus: 15 },\n { days: 14, bonus: 10 },\n { days: 7, bonus: 5 },\n { days: 3, bonus: 2 },\n { days: 1, bonus: 0 },\n ],\n perfectScoreMultiplier: 1.5,\n firstAttemptBonus: 10,\n retryPenalty: 0.5,\n speedBonusMultiplier: 1.2,\n speedBonusThreshold: 0.8,\n};\n\n// ============ XP Engine ============\n\nexport class XPEngine {\n private config: XPConfig;\n\n constructor(config: Partial<XPConfig> = {}) {\n this.config = {\n ...DEFAULT_XP_CONFIG,\n ...config,\n baseValues: { ...DEFAULT_XP_CONFIG.baseValues, ...config.baseValues },\n scoreThresholds:\n config.scoreThresholds || DEFAULT_XP_CONFIG.scoreThresholds,\n streakTiers: config.streakTiers || DEFAULT_XP_CONFIG.streakTiers,\n };\n }\n\n /**\n * Calculate XP for an activity.\n */\n calculate(input: XPCalculationInput): XPResult {\n const breakdown: XPBreakdown[] = [];\n\n // Get base XP\n const baseXp = input.baseXp ?? this.config.baseValues[input.activity];\n let totalXp = baseXp;\n\n breakdown.push({\n source: 'base',\n amount: baseXp,\n });\n\n // Apply score-based multiplier\n if (input.score !== undefined) {\n const scoreMultiplier = this.getScoreMultiplier(input.score);\n if (scoreMultiplier !== 1.0) {\n const scoreBonus = Math.round(baseXp * (scoreMultiplier - 1));\n totalXp += scoreBonus;\n breakdown.push({\n source: 'score_bonus',\n amount: scoreBonus,\n multiplier: scoreMultiplier,\n });\n }\n\n // Perfect score bonus\n if (input.score === 100) {\n const perfectBonus = Math.round(\n baseXp * (this.config.perfectScoreMultiplier - 1)\n );\n totalXp += perfectBonus;\n breakdown.push({\n source: 'perfect_score',\n amount: perfectBonus,\n multiplier: this.config.perfectScoreMultiplier,\n });\n }\n }\n\n // First attempt bonus\n if (input.attemptNumber === 1 && !input.isRetry) {\n totalXp += this.config.firstAttemptBonus;\n breakdown.push({\n source: 'first_attempt',\n amount: this.config.firstAttemptBonus,\n });\n }\n\n // Retry penalty\n if (input.isRetry) {\n const penalty = Math.round(totalXp * (1 - this.config.retryPenalty));\n totalXp -= penalty;\n breakdown.push({\n source: 'retry_penalty',\n amount: -penalty,\n multiplier: this.config.retryPenalty,\n });\n }\n\n // Streak bonus\n if (input.currentStreak && input.currentStreak > 0) {\n const streakBonus = this.getStreakBonus(input.currentStreak);\n if (streakBonus > 0) {\n totalXp += streakBonus;\n breakdown.push({\n source: 'streak_bonus',\n amount: streakBonus,\n });\n }\n }\n\n // Ensure XP is at least 1 (if base was > 0)\n if (baseXp > 0) {\n totalXp = Math.max(1, totalXp);\n }\n\n return {\n totalXp: Math.round(totalXp),\n baseXp,\n breakdown,\n };\n }\n\n /**\n * Calculate streak bonus XP.\n */\n calculateStreakBonus(currentStreak: number): XPResult {\n const bonus = this.getStreakBonus(currentStreak);\n return {\n totalXp: bonus,\n baseXp: bonus,\n breakdown: [\n {\n source: 'streak_bonus',\n amount: bonus,\n },\n ],\n };\n }\n\n /**\n * Calculate XP needed for a level.\n */\n getXpForLevel(level: number): number {\n // Exponential growth formula\n // Level 1: 0 XP\n // Level 2: 100 XP\n // Level 3: 300 XP\n // etc.\n if (level <= 1) return 0;\n return Math.round(100 * Math.pow(level - 1, 1.5));\n }\n\n /**\n * Get level from total XP.\n */\n getLevelFromXp(totalXp: number): {\n level: number;\n xpInLevel: number;\n xpForNextLevel: number;\n } {\n let level = 1;\n let xpRequired = this.getXpForLevel(level + 1);\n\n while (totalXp >= xpRequired && level < 1000) {\n level++;\n xpRequired = this.getXpForLevel(level + 1);\n }\n\n const xpForCurrentLevel = this.getXpForLevel(level);\n const xpForNextLevel = this.getXpForLevel(level + 1);\n\n return {\n level,\n xpInLevel: totalXp - xpForCurrentLevel,\n xpForNextLevel: xpForNextLevel - xpForCurrentLevel,\n };\n }\n\n // ============ Helpers ============\n\n private getScoreMultiplier(score: number): number {\n for (const threshold of this.config.scoreThresholds) {\n if (score >= threshold.min) {\n return threshold.multiplier;\n }\n }\n return 1.0;\n }\n\n private getStreakBonus(streak: number): number {\n for (const tier of this.config.streakTiers) {\n if (streak >= tier.days) {\n return tier.bonus;\n }\n }\n return 0;\n }\n}\n\n/**\n * Default XP engine instance.\n */\nexport const xpEngine = new XPEngine();\n"],"mappings":"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"}
@@ -0,0 +1,232 @@
1
+ import * as _lssm_lib_schema747 from "@lssm/lib.schema";
2
+
3
+ //#region src/entities/ai.d.ts
4
+ /**
5
+ * Learning style enum.
6
+ */
7
+ declare const LearningStyleEnum: _lssm_lib_schema747.EntityEnumDef;
8
+ /**
9
+ * Recommendation type enum.
10
+ */
11
+ declare const RecommendationTypeEnum: _lssm_lib_schema747.EntityEnumDef;
12
+ /**
13
+ * LearnerProfile entity - AI personalization profile.
14
+ */
15
+ declare const LearnerProfileEntity: _lssm_lib_schema747.EntitySpec<{
16
+ id: _lssm_lib_schema747.EntityScalarField;
17
+ learnerId: _lssm_lib_schema747.EntityScalarField;
18
+ learningStyle: _lssm_lib_schema747.EntityEnumField;
19
+ preferredDifficulty: _lssm_lib_schema747.EntityScalarField;
20
+ preferredSessionLength: _lssm_lib_schema747.EntityScalarField;
21
+ interests: _lssm_lib_schema747.EntityScalarField;
22
+ goals: _lssm_lib_schema747.EntityScalarField;
23
+ pacePreference: _lssm_lib_schema747.EntityScalarField;
24
+ bestTimeOfDay: _lssm_lib_schema747.EntityScalarField;
25
+ averageSessionLength: _lssm_lib_schema747.EntityScalarField;
26
+ daysActivePerWeek: _lssm_lib_schema747.EntityScalarField;
27
+ avgQuizScore: _lssm_lib_schema747.EntityScalarField;
28
+ avgLessonCompletionTime: _lssm_lib_schema747.EntityScalarField;
29
+ strengths: _lssm_lib_schema747.EntityScalarField;
30
+ weaknesses: _lssm_lib_schema747.EntityScalarField;
31
+ lastAnalyzedAt: _lssm_lib_schema747.EntityScalarField;
32
+ metadata: _lssm_lib_schema747.EntityScalarField;
33
+ createdAt: _lssm_lib_schema747.EntityScalarField;
34
+ updatedAt: _lssm_lib_schema747.EntityScalarField;
35
+ learner: _lssm_lib_schema747.EntityRelationField;
36
+ }>;
37
+ /**
38
+ * SkillMap entity - tracks skill proficiency.
39
+ */
40
+ declare const SkillMapEntity: _lssm_lib_schema747.EntitySpec<{
41
+ id: _lssm_lib_schema747.EntityScalarField;
42
+ learnerId: _lssm_lib_schema747.EntityScalarField;
43
+ skillId: _lssm_lib_schema747.EntityScalarField;
44
+ skillName: _lssm_lib_schema747.EntityScalarField;
45
+ skillCategory: _lssm_lib_schema747.EntityScalarField;
46
+ level: _lssm_lib_schema747.EntityScalarField;
47
+ confidence: _lssm_lib_schema747.EntityScalarField;
48
+ lessonsCompleted: _lssm_lib_schema747.EntityScalarField;
49
+ quizzesCompleted: _lssm_lib_schema747.EntityScalarField;
50
+ practiceTime: _lssm_lib_schema747.EntityScalarField;
51
+ lastPracticedAt: _lssm_lib_schema747.EntityScalarField;
52
+ learningVelocity: _lssm_lib_schema747.EntityScalarField;
53
+ predictedTimeToMastery: _lssm_lib_schema747.EntityScalarField;
54
+ createdAt: _lssm_lib_schema747.EntityScalarField;
55
+ updatedAt: _lssm_lib_schema747.EntityScalarField;
56
+ learner: _lssm_lib_schema747.EntityRelationField;
57
+ }>;
58
+ /**
59
+ * LearningPath entity - AI-generated learning paths.
60
+ */
61
+ declare const LearningPathEntity: _lssm_lib_schema747.EntitySpec<{
62
+ id: _lssm_lib_schema747.EntityScalarField;
63
+ learnerId: _lssm_lib_schema747.EntityScalarField;
64
+ name: _lssm_lib_schema747.EntityScalarField;
65
+ description: _lssm_lib_schema747.EntityScalarField;
66
+ goal: _lssm_lib_schema747.EntityScalarField;
67
+ steps: _lssm_lib_schema747.EntityScalarField;
68
+ currentStepIndex: _lssm_lib_schema747.EntityScalarField;
69
+ progress: _lssm_lib_schema747.EntityScalarField;
70
+ completedSteps: _lssm_lib_schema747.EntityScalarField;
71
+ totalSteps: _lssm_lib_schema747.EntityScalarField;
72
+ generatedAt: _lssm_lib_schema747.EntityScalarField;
73
+ adaptedFrom: _lssm_lib_schema747.EntityScalarField;
74
+ generationParams: _lssm_lib_schema747.EntityScalarField;
75
+ adaptationHistory: _lssm_lib_schema747.EntityScalarField;
76
+ isActive: _lssm_lib_schema747.EntityScalarField;
77
+ isCompleted: _lssm_lib_schema747.EntityScalarField;
78
+ startedAt: _lssm_lib_schema747.EntityScalarField;
79
+ completedAt: _lssm_lib_schema747.EntityScalarField;
80
+ estimatedCompletionDate: _lssm_lib_schema747.EntityScalarField;
81
+ createdAt: _lssm_lib_schema747.EntityScalarField;
82
+ updatedAt: _lssm_lib_schema747.EntityScalarField;
83
+ learner: _lssm_lib_schema747.EntityRelationField;
84
+ }>;
85
+ /**
86
+ * Recommendation entity - AI-powered learning recommendations.
87
+ */
88
+ declare const RecommendationEntity: _lssm_lib_schema747.EntitySpec<{
89
+ id: _lssm_lib_schema747.EntityScalarField;
90
+ learnerId: _lssm_lib_schema747.EntityScalarField;
91
+ type: _lssm_lib_schema747.EntityEnumField;
92
+ itemId: _lssm_lib_schema747.EntityScalarField;
93
+ itemType: _lssm_lib_schema747.EntityScalarField;
94
+ score: _lssm_lib_schema747.EntityScalarField;
95
+ confidence: _lssm_lib_schema747.EntityScalarField;
96
+ reason: _lssm_lib_schema747.EntityScalarField;
97
+ factors: _lssm_lib_schema747.EntityScalarField;
98
+ status: _lssm_lib_schema747.EntityScalarField;
99
+ viewedAt: _lssm_lib_schema747.EntityScalarField;
100
+ acceptedAt: _lssm_lib_schema747.EntityScalarField;
101
+ dismissedAt: _lssm_lib_schema747.EntityScalarField;
102
+ feedback: _lssm_lib_schema747.EntityScalarField;
103
+ feedbackRating: _lssm_lib_schema747.EntityScalarField;
104
+ expiresAt: _lssm_lib_schema747.EntityScalarField;
105
+ createdAt: _lssm_lib_schema747.EntityScalarField;
106
+ updatedAt: _lssm_lib_schema747.EntityScalarField;
107
+ learner: _lssm_lib_schema747.EntityRelationField;
108
+ }>;
109
+ /**
110
+ * LearningGap entity - identified knowledge gaps.
111
+ */
112
+ declare const LearningGapEntity: _lssm_lib_schema747.EntitySpec<{
113
+ id: _lssm_lib_schema747.EntityScalarField;
114
+ learnerId: _lssm_lib_schema747.EntityScalarField;
115
+ skillId: _lssm_lib_schema747.EntityScalarField;
116
+ skillName: _lssm_lib_schema747.EntityScalarField;
117
+ severity: _lssm_lib_schema747.EntityScalarField;
118
+ confidence: _lssm_lib_schema747.EntityScalarField;
119
+ evidence: _lssm_lib_schema747.EntityScalarField;
120
+ relatedQuestions: _lssm_lib_schema747.EntityScalarField;
121
+ suggestedRemediation: _lssm_lib_schema747.EntityScalarField;
122
+ remediationProgress: _lssm_lib_schema747.EntityScalarField;
123
+ status: _lssm_lib_schema747.EntityScalarField;
124
+ resolvedAt: _lssm_lib_schema747.EntityScalarField;
125
+ detectedAt: _lssm_lib_schema747.EntityScalarField;
126
+ createdAt: _lssm_lib_schema747.EntityScalarField;
127
+ updatedAt: _lssm_lib_schema747.EntityScalarField;
128
+ learner: _lssm_lib_schema747.EntityRelationField;
129
+ }>;
130
+ declare const aiEntities: (_lssm_lib_schema747.EntitySpec<{
131
+ id: _lssm_lib_schema747.EntityScalarField;
132
+ learnerId: _lssm_lib_schema747.EntityScalarField;
133
+ learningStyle: _lssm_lib_schema747.EntityEnumField;
134
+ preferredDifficulty: _lssm_lib_schema747.EntityScalarField;
135
+ preferredSessionLength: _lssm_lib_schema747.EntityScalarField;
136
+ interests: _lssm_lib_schema747.EntityScalarField;
137
+ goals: _lssm_lib_schema747.EntityScalarField;
138
+ pacePreference: _lssm_lib_schema747.EntityScalarField;
139
+ bestTimeOfDay: _lssm_lib_schema747.EntityScalarField;
140
+ averageSessionLength: _lssm_lib_schema747.EntityScalarField;
141
+ daysActivePerWeek: _lssm_lib_schema747.EntityScalarField;
142
+ avgQuizScore: _lssm_lib_schema747.EntityScalarField;
143
+ avgLessonCompletionTime: _lssm_lib_schema747.EntityScalarField;
144
+ strengths: _lssm_lib_schema747.EntityScalarField;
145
+ weaknesses: _lssm_lib_schema747.EntityScalarField;
146
+ lastAnalyzedAt: _lssm_lib_schema747.EntityScalarField;
147
+ metadata: _lssm_lib_schema747.EntityScalarField;
148
+ createdAt: _lssm_lib_schema747.EntityScalarField;
149
+ updatedAt: _lssm_lib_schema747.EntityScalarField;
150
+ learner: _lssm_lib_schema747.EntityRelationField;
151
+ }> | _lssm_lib_schema747.EntitySpec<{
152
+ id: _lssm_lib_schema747.EntityScalarField;
153
+ learnerId: _lssm_lib_schema747.EntityScalarField;
154
+ skillId: _lssm_lib_schema747.EntityScalarField;
155
+ skillName: _lssm_lib_schema747.EntityScalarField;
156
+ skillCategory: _lssm_lib_schema747.EntityScalarField;
157
+ level: _lssm_lib_schema747.EntityScalarField;
158
+ confidence: _lssm_lib_schema747.EntityScalarField;
159
+ lessonsCompleted: _lssm_lib_schema747.EntityScalarField;
160
+ quizzesCompleted: _lssm_lib_schema747.EntityScalarField;
161
+ practiceTime: _lssm_lib_schema747.EntityScalarField;
162
+ lastPracticedAt: _lssm_lib_schema747.EntityScalarField;
163
+ learningVelocity: _lssm_lib_schema747.EntityScalarField;
164
+ predictedTimeToMastery: _lssm_lib_schema747.EntityScalarField;
165
+ createdAt: _lssm_lib_schema747.EntityScalarField;
166
+ updatedAt: _lssm_lib_schema747.EntityScalarField;
167
+ learner: _lssm_lib_schema747.EntityRelationField;
168
+ }> | _lssm_lib_schema747.EntitySpec<{
169
+ id: _lssm_lib_schema747.EntityScalarField;
170
+ learnerId: _lssm_lib_schema747.EntityScalarField;
171
+ name: _lssm_lib_schema747.EntityScalarField;
172
+ description: _lssm_lib_schema747.EntityScalarField;
173
+ goal: _lssm_lib_schema747.EntityScalarField;
174
+ steps: _lssm_lib_schema747.EntityScalarField;
175
+ currentStepIndex: _lssm_lib_schema747.EntityScalarField;
176
+ progress: _lssm_lib_schema747.EntityScalarField;
177
+ completedSteps: _lssm_lib_schema747.EntityScalarField;
178
+ totalSteps: _lssm_lib_schema747.EntityScalarField;
179
+ generatedAt: _lssm_lib_schema747.EntityScalarField;
180
+ adaptedFrom: _lssm_lib_schema747.EntityScalarField;
181
+ generationParams: _lssm_lib_schema747.EntityScalarField;
182
+ adaptationHistory: _lssm_lib_schema747.EntityScalarField;
183
+ isActive: _lssm_lib_schema747.EntityScalarField;
184
+ isCompleted: _lssm_lib_schema747.EntityScalarField;
185
+ startedAt: _lssm_lib_schema747.EntityScalarField;
186
+ completedAt: _lssm_lib_schema747.EntityScalarField;
187
+ estimatedCompletionDate: _lssm_lib_schema747.EntityScalarField;
188
+ createdAt: _lssm_lib_schema747.EntityScalarField;
189
+ updatedAt: _lssm_lib_schema747.EntityScalarField;
190
+ learner: _lssm_lib_schema747.EntityRelationField;
191
+ }> | _lssm_lib_schema747.EntitySpec<{
192
+ id: _lssm_lib_schema747.EntityScalarField;
193
+ learnerId: _lssm_lib_schema747.EntityScalarField;
194
+ type: _lssm_lib_schema747.EntityEnumField;
195
+ itemId: _lssm_lib_schema747.EntityScalarField;
196
+ itemType: _lssm_lib_schema747.EntityScalarField;
197
+ score: _lssm_lib_schema747.EntityScalarField;
198
+ confidence: _lssm_lib_schema747.EntityScalarField;
199
+ reason: _lssm_lib_schema747.EntityScalarField;
200
+ factors: _lssm_lib_schema747.EntityScalarField;
201
+ status: _lssm_lib_schema747.EntityScalarField;
202
+ viewedAt: _lssm_lib_schema747.EntityScalarField;
203
+ acceptedAt: _lssm_lib_schema747.EntityScalarField;
204
+ dismissedAt: _lssm_lib_schema747.EntityScalarField;
205
+ feedback: _lssm_lib_schema747.EntityScalarField;
206
+ feedbackRating: _lssm_lib_schema747.EntityScalarField;
207
+ expiresAt: _lssm_lib_schema747.EntityScalarField;
208
+ createdAt: _lssm_lib_schema747.EntityScalarField;
209
+ updatedAt: _lssm_lib_schema747.EntityScalarField;
210
+ learner: _lssm_lib_schema747.EntityRelationField;
211
+ }> | _lssm_lib_schema747.EntitySpec<{
212
+ id: _lssm_lib_schema747.EntityScalarField;
213
+ learnerId: _lssm_lib_schema747.EntityScalarField;
214
+ skillId: _lssm_lib_schema747.EntityScalarField;
215
+ skillName: _lssm_lib_schema747.EntityScalarField;
216
+ severity: _lssm_lib_schema747.EntityScalarField;
217
+ confidence: _lssm_lib_schema747.EntityScalarField;
218
+ evidence: _lssm_lib_schema747.EntityScalarField;
219
+ relatedQuestions: _lssm_lib_schema747.EntityScalarField;
220
+ suggestedRemediation: _lssm_lib_schema747.EntityScalarField;
221
+ remediationProgress: _lssm_lib_schema747.EntityScalarField;
222
+ status: _lssm_lib_schema747.EntityScalarField;
223
+ resolvedAt: _lssm_lib_schema747.EntityScalarField;
224
+ detectedAt: _lssm_lib_schema747.EntityScalarField;
225
+ createdAt: _lssm_lib_schema747.EntityScalarField;
226
+ updatedAt: _lssm_lib_schema747.EntityScalarField;
227
+ learner: _lssm_lib_schema747.EntityRelationField;
228
+ }>)[];
229
+ declare const aiEnums: _lssm_lib_schema747.EntityEnumDef[];
230
+ //#endregion
231
+ export { LearnerProfileEntity, LearningGapEntity, LearningPathEntity, LearningStyleEnum, RecommendationEntity, RecommendationTypeEnum, SkillMapEntity, aiEntities, aiEnums };
232
+ //# sourceMappingURL=ai.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ai.d.ts","names":[],"sources":["../../src/entities/ai.ts"],"sourcesContent":[],"mappings":";;;;;;AAKa,cAAA,iBAKX,EAAA,mBAAA,CAL4B,aAK5B;AAKF;AAiBA;;cAjBa,wBAYX,mBAAA,CAZiC;;;;cAiBtB,0CAAoB;MA2F/B,mBAAA,CAAA;;;;;;;;;;;;;;mDA3F+B;EAAA,cAAA,uCAAA;EAgGpB,QAAA,uCAoEX;EAAA,SAAA,uCAAA;;;;;;;cApEW,oCAAc;MAoEzB,mBAAA,CAAA;;;;;;;;yDApEyB;EAAA,YAAA,uCAAA;EAyEd,eAAA,uCAgFX;EAAA,gBAAA,uCAAA;;;;;;;;;cAhFW,wCAAkB;MAgF7B,mBAAA,CAAA;;;;;;;;;;;;yDAhF6B;EAAA,iBAAA,uCAAA;EAqFlB,QAAA,uCAwEX;EAAA,WAAA,uCAAA;;;;;;;;;;;cAxEW,0CAAoB;MAwE/B,mBAAA,CAAA;;;;;;;+CAxE+B;EAAA,OAAA,uCAAA;EA6EpB,MAAA,uCA8DX;EAAA,QAAA,uCAAA;;;;;;;;;;;;;cA9DW,uCAAiB;MA8D5B,mBAAA,CAAA;;gDA9D4B;EAAA,SAAA,uCAAA;EAgEjB,QAAA,uCAMZ;EAAA,UAAA,uCAAA;;;;;;;;;;;;cANY,iCAAU;MAMtB,mBAAA,CAAA;;;;;;;uDANsB;EAAA,aAAA,uCAAA;;;;;;;;;;;;;MAAA,mBAAA,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAQV,UAAqD,uCAA9C;;;;;;;;;;;;cAAP,SAAqD,mBAAA,CAA9C,aAAA"}