learngraph 0.4.0 → 0.5.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/dist/cjs/index.js +1 -1
- package/dist/cjs/query/index.js +23 -4
- package/dist/cjs/query/index.js.map +1 -1
- package/dist/cjs/query/path.js +313 -0
- package/dist/cjs/query/path.js.map +1 -0
- package/dist/cjs/query/spaced-repetition.js +298 -0
- package/dist/cjs/query/spaced-repetition.js.map +1 -0
- package/dist/cjs/query/zpd.js +216 -0
- package/dist/cjs/query/zpd.js.map +1 -0
- package/dist/esm/index.js +1 -1
- package/dist/esm/query/index.js +11 -5
- package/dist/esm/query/index.js.map +1 -1
- package/dist/esm/query/path.js +308 -0
- package/dist/esm/query/path.js.map +1 -0
- package/dist/esm/query/spaced-repetition.js +292 -0
- package/dist/esm/query/spaced-repetition.js.map +1 -0
- package/dist/esm/query/zpd.js +211 -0
- package/dist/esm/query/zpd.js.map +1 -0
- package/dist/types/index.d.ts +1 -1
- package/dist/types/query/index.d.ts +8 -0
- package/dist/types/query/index.d.ts.map +1 -1
- package/dist/types/query/path.d.ts +102 -0
- package/dist/types/query/path.d.ts.map +1 -0
- package/dist/types/query/spaced-repetition.d.ts +135 -0
- package/dist/types/query/spaced-repetition.d.ts.map +1 -0
- package/dist/types/query/zpd.d.ts +97 -0
- package/dist/types/query/zpd.d.ts.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"spaced-repetition.js","sourceRoot":"","sources":["../../../src/query/spaced-repetition.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Zone of Proximal Development (ZPD) Calculator
|
|
4
|
+
*
|
|
5
|
+
* Implements Vygotsky's Zone of Proximal Development theory to identify
|
|
6
|
+
* skills that are "just right" for a learner - challenging but achievable.
|
|
7
|
+
*
|
|
8
|
+
* @packageDocumentation
|
|
9
|
+
*/
|
|
10
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
11
|
+
exports.ZPDCalculator = exports.ZPD_DEFAULTS = void 0;
|
|
12
|
+
exports.createZPDCalculator = createZPDCalculator;
|
|
13
|
+
/**
|
|
14
|
+
* Default options for ZPD calculation
|
|
15
|
+
*/
|
|
16
|
+
exports.ZPD_DEFAULTS = {
|
|
17
|
+
difficultyTolerance: 0.2,
|
|
18
|
+
prioritizeThresholdConcepts: true,
|
|
19
|
+
maxResults: 50,
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* ZPD Calculator
|
|
23
|
+
*
|
|
24
|
+
* Calculates the Zone of Proximal Development for a learner based on:
|
|
25
|
+
* 1. Current mastery states
|
|
26
|
+
* 2. Prerequisite graph structure
|
|
27
|
+
* 3. Skill difficulty levels
|
|
28
|
+
*
|
|
29
|
+
* A skill is in the ZPD if:
|
|
30
|
+
* - All prerequisites are mastered
|
|
31
|
+
* - The skill is not yet mastered
|
|
32
|
+
* - The skill difficulty is within tolerance of learner ability
|
|
33
|
+
*/
|
|
34
|
+
class ZPDCalculator {
|
|
35
|
+
storage;
|
|
36
|
+
constructor(storage) {
|
|
37
|
+
this.storage = storage;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Calculate ZPD for a learner
|
|
41
|
+
*
|
|
42
|
+
* @param learner - Learner profile with mastery states
|
|
43
|
+
* @param options - Calculation options
|
|
44
|
+
* @returns ZPD result with ready skills and blocked skills
|
|
45
|
+
*
|
|
46
|
+
* @example
|
|
47
|
+
* ```typescript
|
|
48
|
+
* const calculator = new ZPDCalculator(storage);
|
|
49
|
+
*
|
|
50
|
+
* const learner = {
|
|
51
|
+
* masteryStates: new Map([
|
|
52
|
+
* ['skill-1', { skillId: 'skill-1', mastery: 0.9, ... }],
|
|
53
|
+
* ['skill-2', { skillId: 'skill-2', mastery: 0.3, ... }],
|
|
54
|
+
* ])
|
|
55
|
+
* };
|
|
56
|
+
*
|
|
57
|
+
* const zpd = await calculator.calculate(learner);
|
|
58
|
+
* console.log('Ready to learn:', zpd.ready.map(s => s.name));
|
|
59
|
+
* ```
|
|
60
|
+
*/
|
|
61
|
+
async calculate(learner, options = {}) {
|
|
62
|
+
const opts = { ...exports.ZPD_DEFAULTS, ...options };
|
|
63
|
+
// Get all skills from storage
|
|
64
|
+
let allSkills = await this.storage.findSkills({});
|
|
65
|
+
// Apply filters
|
|
66
|
+
if (opts.filterTags && opts.filterTags.length > 0) {
|
|
67
|
+
allSkills = allSkills.filter((skill) => opts.filterTags.some((tag) => skill.tags.includes(tag)));
|
|
68
|
+
}
|
|
69
|
+
if (opts.filterDomain) {
|
|
70
|
+
allSkills = allSkills.filter((skill) => skill.metadata?.domain === opts.filterDomain);
|
|
71
|
+
}
|
|
72
|
+
// Calculate learner ability level if not provided
|
|
73
|
+
const abilityLevel = learner.abilityLevel ?? this.calculateAbilityLevel(learner);
|
|
74
|
+
// Categorize skills
|
|
75
|
+
const zpd = [];
|
|
76
|
+
const ready = [];
|
|
77
|
+
const blocked = new Map();
|
|
78
|
+
let masteredCount = 0;
|
|
79
|
+
for (const skill of allSkills) {
|
|
80
|
+
const mastery = learner.masteryStates.get(skill.id);
|
|
81
|
+
const masteryLevel = mastery?.mastery ?? 0;
|
|
82
|
+
// Check if already mastered
|
|
83
|
+
if (masteryLevel >= skill.masteryThreshold) {
|
|
84
|
+
masteredCount++;
|
|
85
|
+
continue;
|
|
86
|
+
}
|
|
87
|
+
// Get prerequisites
|
|
88
|
+
const prerequisites = await this.storage.getPrerequisitesOf(skill.id);
|
|
89
|
+
const unmetPrereqs = [];
|
|
90
|
+
for (const prereq of prerequisites) {
|
|
91
|
+
const prereqMastery = learner.masteryStates.get(prereq.id);
|
|
92
|
+
const prereqLevel = prereqMastery?.mastery ?? 0;
|
|
93
|
+
if (prereqLevel < prereq.masteryThreshold) {
|
|
94
|
+
unmetPrereqs.push(prereq.name);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
if (unmetPrereqs.length > 0) {
|
|
98
|
+
// Skill is blocked
|
|
99
|
+
blocked.set(skill.id, unmetPrereqs);
|
|
100
|
+
}
|
|
101
|
+
else {
|
|
102
|
+
// Skill is in ZPD (prerequisites met, not yet mastered)
|
|
103
|
+
zpd.push(skill);
|
|
104
|
+
// Check if within difficulty tolerance
|
|
105
|
+
const difficultyDelta = skill.difficulty - abilityLevel;
|
|
106
|
+
if (difficultyDelta <= opts.difficultyTolerance) {
|
|
107
|
+
ready.push(skill);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
// Sort ready skills by priority
|
|
112
|
+
this.sortByPriority(ready, opts.prioritizeThresholdConcepts);
|
|
113
|
+
// Limit results
|
|
114
|
+
const limitedReady = opts.maxResults ? ready.slice(0, opts.maxResults) : ready;
|
|
115
|
+
const limitedZpd = opts.maxResults ? zpd.slice(0, opts.maxResults) : zpd;
|
|
116
|
+
return {
|
|
117
|
+
zpd: limitedZpd,
|
|
118
|
+
ready: limitedReady,
|
|
119
|
+
blocked,
|
|
120
|
+
stats: {
|
|
121
|
+
totalSkills: allSkills.length,
|
|
122
|
+
mastered: masteredCount,
|
|
123
|
+
inZPD: zpd.length,
|
|
124
|
+
blocked: blocked.size,
|
|
125
|
+
},
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Get the next recommended skill to learn
|
|
130
|
+
*
|
|
131
|
+
* @param learner - Learner profile
|
|
132
|
+
* @param options - ZPD options
|
|
133
|
+
* @returns The highest priority skill to learn next, or null if none available
|
|
134
|
+
*/
|
|
135
|
+
async getNextSkill(learner, options = {}) {
|
|
136
|
+
const zpd = await this.calculate(learner, { ...options, maxResults: 1 });
|
|
137
|
+
return zpd.ready[0] ?? zpd.zpd[0] ?? null;
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Check if a specific skill is in the learner's ZPD
|
|
141
|
+
*
|
|
142
|
+
* @param skillId - Skill to check
|
|
143
|
+
* @param learner - Learner profile
|
|
144
|
+
* @returns Object with inZPD status and blocking prerequisites if any
|
|
145
|
+
*/
|
|
146
|
+
async isInZPD(skillId, learner) {
|
|
147
|
+
const skill = await this.storage.getSkill(skillId);
|
|
148
|
+
if (!skill) {
|
|
149
|
+
return { inZPD: false, blocking: ['Skill not found'] };
|
|
150
|
+
}
|
|
151
|
+
// Check if already mastered
|
|
152
|
+
const mastery = learner.masteryStates.get(skillId);
|
|
153
|
+
if (mastery && mastery.mastery >= skill.masteryThreshold) {
|
|
154
|
+
return { inZPD: false, blocking: [] };
|
|
155
|
+
}
|
|
156
|
+
// Check prerequisites
|
|
157
|
+
const prerequisites = await this.storage.getPrerequisitesOf(skillId);
|
|
158
|
+
const blocking = [];
|
|
159
|
+
for (const prereq of prerequisites) {
|
|
160
|
+
const prereqMastery = learner.masteryStates.get(prereq.id);
|
|
161
|
+
const prereqLevel = prereqMastery?.mastery ?? 0;
|
|
162
|
+
if (prereqLevel < prereq.masteryThreshold) {
|
|
163
|
+
blocking.push(prereq.name);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
return {
|
|
167
|
+
inZPD: blocking.length === 0,
|
|
168
|
+
blocking,
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Calculate learner ability level from mastery states
|
|
173
|
+
*/
|
|
174
|
+
calculateAbilityLevel(learner) {
|
|
175
|
+
if (learner.masteryStates.size === 0) {
|
|
176
|
+
return 0.3; // Default starting ability
|
|
177
|
+
}
|
|
178
|
+
let totalWeighted = 0;
|
|
179
|
+
let totalWeight = 0;
|
|
180
|
+
for (const state of learner.masteryStates.values()) {
|
|
181
|
+
// Weight by mastery level (higher mastery = more confident estimate)
|
|
182
|
+
const weight = state.mastery;
|
|
183
|
+
totalWeighted += state.mastery * weight;
|
|
184
|
+
totalWeight += weight;
|
|
185
|
+
}
|
|
186
|
+
return totalWeight > 0 ? totalWeighted / totalWeight : 0.3;
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Sort skills by learning priority
|
|
190
|
+
*/
|
|
191
|
+
sortByPriority(skills, prioritizeThreshold) {
|
|
192
|
+
skills.sort((a, b) => {
|
|
193
|
+
// Threshold concepts first (if enabled)
|
|
194
|
+
if (prioritizeThreshold) {
|
|
195
|
+
if (a.isThresholdConcept && !b.isThresholdConcept)
|
|
196
|
+
return -1;
|
|
197
|
+
if (!a.isThresholdConcept && b.isThresholdConcept)
|
|
198
|
+
return 1;
|
|
199
|
+
}
|
|
200
|
+
// Then by difficulty (easier first for progressive learning)
|
|
201
|
+
if (a.difficulty !== b.difficulty) {
|
|
202
|
+
return a.difficulty - b.difficulty;
|
|
203
|
+
}
|
|
204
|
+
// Finally by estimated time (shorter first)
|
|
205
|
+
return a.estimatedMinutes - b.estimatedMinutes;
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
exports.ZPDCalculator = ZPDCalculator;
|
|
210
|
+
/**
|
|
211
|
+
* Create a ZPD calculator
|
|
212
|
+
*/
|
|
213
|
+
function createZPDCalculator(storage) {
|
|
214
|
+
return new ZPDCalculator(storage);
|
|
215
|
+
}
|
|
216
|
+
//# sourceMappingURL=zpd.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"zpd.js","sourceRoot":"","sources":["../../../src/query/zpd.ts"],"names":[],"mappings":"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"}
|
package/dist/esm/index.js
CHANGED
package/dist/esm/query/index.js
CHANGED
|
@@ -1,11 +1,17 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Query and traversal engines
|
|
3
3
|
*
|
|
4
|
+
* This module provides intelligent query engines for:
|
|
5
|
+
* - Zone of Proximal Development (ZPD) calculation
|
|
6
|
+
* - Learning path generation
|
|
7
|
+
* - Spaced repetition scheduling
|
|
8
|
+
*
|
|
4
9
|
* @packageDocumentation
|
|
5
10
|
*/
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
//
|
|
9
|
-
|
|
10
|
-
//
|
|
11
|
+
// ZPD Calculator
|
|
12
|
+
export { ZPDCalculator, createZPDCalculator, ZPD_DEFAULTS, } from './zpd.js';
|
|
13
|
+
// Learning Path Generator
|
|
14
|
+
export { PathGenerator, createPathGenerator, PATH_DEFAULTS, } from './path.js';
|
|
15
|
+
// Spaced Repetition Scheduler
|
|
16
|
+
export { SpacedRepetitionScheduler, createSpacedRepetitionScheduler, calculateSM2, REVIEW_DEFAULTS, SM2_CONSTANTS, } from './spaced-repetition.js';
|
|
11
17
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/query/index.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/query/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAmBH,iBAAiB;AACjB,OAAO,EACL,aAAa,EACb,mBAAmB,EACnB,YAAY,GAEb,MAAM,UAAU,CAAC;AAElB,0BAA0B;AAC1B,OAAO,EACL,aAAa,EACb,mBAAmB,EACnB,aAAa,GAEd,MAAM,WAAW,CAAC;AAEnB,8BAA8B;AAC9B,OAAO,EACL,yBAAyB,EACzB,+BAA+B,EAC/B,YAAY,EACZ,eAAe,EACf,aAAa,GAId,MAAM,wBAAwB,CAAC"}
|
|
@@ -0,0 +1,308 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Learning Path Generator
|
|
3
|
+
*
|
|
4
|
+
* Generates personalized learning paths from current state to target skills.
|
|
5
|
+
* Uses topological sorting and groups skills into manageable sessions.
|
|
6
|
+
*
|
|
7
|
+
* @packageDocumentation
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* Default options for path generation
|
|
11
|
+
*/
|
|
12
|
+
export const PATH_DEFAULTS = {
|
|
13
|
+
sessionMinutes: 30,
|
|
14
|
+
maxPathLength: 100,
|
|
15
|
+
includeReview: false,
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* Learning Path Generator
|
|
19
|
+
*
|
|
20
|
+
* Generates optimal learning paths to reach target skills by:
|
|
21
|
+
* 1. Finding all unmastered prerequisites
|
|
22
|
+
* 2. Topologically sorting based on dependencies
|
|
23
|
+
* 3. Grouping into sessions based on cognitive load
|
|
24
|
+
*
|
|
25
|
+
* @example
|
|
26
|
+
* ```typescript
|
|
27
|
+
* const generator = new PathGenerator(storage);
|
|
28
|
+
*
|
|
29
|
+
* const path = await generator.generatePath(
|
|
30
|
+
* 'advanced-skill',
|
|
31
|
+
* learnerState,
|
|
32
|
+
* { sessionMinutes: 45 }
|
|
33
|
+
* );
|
|
34
|
+
*
|
|
35
|
+
* console.log(`Path has ${path.skills.length} skills`);
|
|
36
|
+
* console.log(`Estimated time: ${path.totalMinutes} minutes`);
|
|
37
|
+
* ```
|
|
38
|
+
*/
|
|
39
|
+
export class PathGenerator {
|
|
40
|
+
storage;
|
|
41
|
+
constructor(storage) {
|
|
42
|
+
this.storage = storage;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Generate a learning path to a target skill
|
|
46
|
+
*
|
|
47
|
+
* @param targetId - The skill to learn
|
|
48
|
+
* @param learner - Current learner state
|
|
49
|
+
* @param options - Path generation options
|
|
50
|
+
* @returns Learning path with skills grouped into sessions
|
|
51
|
+
*/
|
|
52
|
+
async generatePath(targetId, learner, options = {}) {
|
|
53
|
+
const opts = { ...PATH_DEFAULTS, ...options };
|
|
54
|
+
const target = await this.storage.getSkill(targetId);
|
|
55
|
+
if (!target) {
|
|
56
|
+
return null;
|
|
57
|
+
}
|
|
58
|
+
// Check if already mastered
|
|
59
|
+
const targetMastery = learner.masteryStates.get(targetId);
|
|
60
|
+
if (targetMastery && targetMastery.mastery >= target.masteryThreshold) {
|
|
61
|
+
// Already mastered - return empty path
|
|
62
|
+
return {
|
|
63
|
+
target,
|
|
64
|
+
skills: [],
|
|
65
|
+
totalMinutes: 0,
|
|
66
|
+
sessions: [],
|
|
67
|
+
checkpoints: [],
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
// Get all prerequisites (transitive)
|
|
71
|
+
const allPrereqs = await this.getTransitivePrerequisites(targetId);
|
|
72
|
+
// Filter to unmastered skills
|
|
73
|
+
const skillsToLearn = await this.filterUnmastered([...allPrereqs, target], learner, opts.includeReview);
|
|
74
|
+
// Topologically sort
|
|
75
|
+
const sorted = await this.topologicalSort(skillsToLearn);
|
|
76
|
+
// Apply max length limit
|
|
77
|
+
const limited = opts.maxPathLength
|
|
78
|
+
? sorted.slice(0, opts.maxPathLength)
|
|
79
|
+
: sorted;
|
|
80
|
+
// Calculate total time
|
|
81
|
+
const totalMinutes = limited.reduce((sum, skill) => sum + skill.estimatedMinutes, 0);
|
|
82
|
+
// Group into sessions
|
|
83
|
+
const sessions = this.groupIntoSessions(limited, opts.sessionMinutes);
|
|
84
|
+
// Identify checkpoints (threshold concepts)
|
|
85
|
+
const checkpoints = limited.filter((skill) => skill.isThresholdConcept);
|
|
86
|
+
return {
|
|
87
|
+
target,
|
|
88
|
+
skills: limited,
|
|
89
|
+
totalMinutes,
|
|
90
|
+
sessions,
|
|
91
|
+
checkpoints,
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Generate paths to multiple target skills
|
|
96
|
+
*
|
|
97
|
+
* @param targetIds - Skills to learn
|
|
98
|
+
* @param learner - Current learner state
|
|
99
|
+
* @param options - Path generation options
|
|
100
|
+
* @returns Array of learning paths
|
|
101
|
+
*/
|
|
102
|
+
async generatePaths(targetIds, learner, options = {}) {
|
|
103
|
+
const paths = [];
|
|
104
|
+
for (const targetId of targetIds) {
|
|
105
|
+
const path = await this.generatePath(targetId, learner, options);
|
|
106
|
+
if (path) {
|
|
107
|
+
paths.push(path);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
return paths;
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Get a merged learning path for multiple targets
|
|
114
|
+
* Combines all required skills and eliminates duplicates
|
|
115
|
+
*/
|
|
116
|
+
async generateMergedPath(targetIds, learner, options = {}) {
|
|
117
|
+
const opts = { ...PATH_DEFAULTS, ...options };
|
|
118
|
+
// Get all target skills
|
|
119
|
+
const targets = [];
|
|
120
|
+
for (const id of targetIds) {
|
|
121
|
+
const skill = await this.storage.getSkill(id);
|
|
122
|
+
if (skill) {
|
|
123
|
+
targets.push(skill);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
if (targets.length === 0) {
|
|
127
|
+
return null;
|
|
128
|
+
}
|
|
129
|
+
// Collect all unmastered prerequisites from all targets
|
|
130
|
+
const allSkillsSet = new Set();
|
|
131
|
+
const allSkills = [];
|
|
132
|
+
for (const target of targets) {
|
|
133
|
+
const prereqs = await this.getTransitivePrerequisites(target.id);
|
|
134
|
+
const allForTarget = [...prereqs, target];
|
|
135
|
+
for (const skill of allForTarget) {
|
|
136
|
+
if (!allSkillsSet.has(skill.id)) {
|
|
137
|
+
allSkillsSet.add(skill.id);
|
|
138
|
+
allSkills.push(skill);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
// Filter to unmastered
|
|
143
|
+
const skillsToLearn = await this.filterUnmastered(allSkills, learner, opts.includeReview);
|
|
144
|
+
// Topologically sort
|
|
145
|
+
const sorted = await this.topologicalSort(skillsToLearn);
|
|
146
|
+
// Apply max length
|
|
147
|
+
const limited = opts.maxPathLength
|
|
148
|
+
? sorted.slice(0, opts.maxPathLength)
|
|
149
|
+
: sorted;
|
|
150
|
+
const totalMinutes = limited.reduce((sum, skill) => sum + skill.estimatedMinutes, 0);
|
|
151
|
+
const sessions = this.groupIntoSessions(limited, opts.sessionMinutes);
|
|
152
|
+
const checkpoints = limited.filter((skill) => skill.isThresholdConcept);
|
|
153
|
+
// Use first target as the primary target
|
|
154
|
+
return {
|
|
155
|
+
target: targets[0],
|
|
156
|
+
skills: limited,
|
|
157
|
+
totalMinutes,
|
|
158
|
+
sessions,
|
|
159
|
+
checkpoints,
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Get all transitive prerequisites of a skill
|
|
164
|
+
*/
|
|
165
|
+
async getTransitivePrerequisites(skillId) {
|
|
166
|
+
const visited = new Set();
|
|
167
|
+
const result = [];
|
|
168
|
+
const visit = async (id) => {
|
|
169
|
+
if (visited.has(id)) {
|
|
170
|
+
return;
|
|
171
|
+
}
|
|
172
|
+
visited.add(id);
|
|
173
|
+
const prereqs = await this.storage.getPrerequisitesOf(id);
|
|
174
|
+
for (const prereq of prereqs) {
|
|
175
|
+
await visit(prereq.id);
|
|
176
|
+
if (!result.some((s) => s.id === prereq.id)) {
|
|
177
|
+
result.push(prereq);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
};
|
|
181
|
+
await visit(skillId);
|
|
182
|
+
return result;
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Filter skills to only unmastered ones
|
|
186
|
+
*/
|
|
187
|
+
async filterUnmastered(skills, learner, includeReview) {
|
|
188
|
+
return skills.filter((skill) => {
|
|
189
|
+
const mastery = learner.masteryStates.get(skill.id);
|
|
190
|
+
const level = mastery?.mastery ?? 0;
|
|
191
|
+
if (includeReview) {
|
|
192
|
+
// Include if below 100% mastery
|
|
193
|
+
return level < 1.0;
|
|
194
|
+
}
|
|
195
|
+
// Include if below mastery threshold
|
|
196
|
+
return level < skill.masteryThreshold;
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
/**
|
|
200
|
+
* Topologically sort skills based on prerequisites
|
|
201
|
+
* Skills with no unmastered prerequisites come first
|
|
202
|
+
*/
|
|
203
|
+
async topologicalSort(skills) {
|
|
204
|
+
const skillMap = new Map(skills.map((s) => [s.id, s]));
|
|
205
|
+
const result = [];
|
|
206
|
+
const visited = new Set();
|
|
207
|
+
const visiting = new Set(); // For cycle detection
|
|
208
|
+
const visit = async (skill) => {
|
|
209
|
+
if (visited.has(skill.id)) {
|
|
210
|
+
return;
|
|
211
|
+
}
|
|
212
|
+
if (visiting.has(skill.id)) {
|
|
213
|
+
// Cycle detected - skip to avoid infinite loop
|
|
214
|
+
return;
|
|
215
|
+
}
|
|
216
|
+
visiting.add(skill.id);
|
|
217
|
+
// Visit prerequisites first (only those in our skill set)
|
|
218
|
+
const prereqs = await this.storage.getPrerequisitesOf(skill.id);
|
|
219
|
+
for (const prereq of prereqs) {
|
|
220
|
+
const prereqSkill = skillMap.get(prereq.id);
|
|
221
|
+
if (prereqSkill && !visited.has(prereq.id)) {
|
|
222
|
+
await visit(prereqSkill);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
visiting.delete(skill.id);
|
|
226
|
+
visited.add(skill.id);
|
|
227
|
+
result.push(skill);
|
|
228
|
+
};
|
|
229
|
+
// Visit all skills
|
|
230
|
+
for (const skill of skills) {
|
|
231
|
+
if (!visited.has(skill.id)) {
|
|
232
|
+
await visit(skill);
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
return result;
|
|
236
|
+
}
|
|
237
|
+
/**
|
|
238
|
+
* Group skills into learning sessions based on target duration
|
|
239
|
+
*/
|
|
240
|
+
groupIntoSessions(skills, targetMinutes) {
|
|
241
|
+
const sessions = [];
|
|
242
|
+
let currentSession = [];
|
|
243
|
+
let currentDuration = 0;
|
|
244
|
+
for (const skill of skills) {
|
|
245
|
+
// Start new session if current would exceed target
|
|
246
|
+
if (currentDuration + skill.estimatedMinutes > targetMinutes &&
|
|
247
|
+
currentSession.length > 0) {
|
|
248
|
+
sessions.push(this.createSession(sessions.length + 1, currentSession));
|
|
249
|
+
currentSession = [];
|
|
250
|
+
currentDuration = 0;
|
|
251
|
+
}
|
|
252
|
+
currentSession.push(skill);
|
|
253
|
+
currentDuration += skill.estimatedMinutes;
|
|
254
|
+
}
|
|
255
|
+
// Add final session if not empty
|
|
256
|
+
if (currentSession.length > 0) {
|
|
257
|
+
sessions.push(this.createSession(sessions.length + 1, currentSession));
|
|
258
|
+
}
|
|
259
|
+
return sessions;
|
|
260
|
+
}
|
|
261
|
+
/**
|
|
262
|
+
* Create a learning session from a group of skills
|
|
263
|
+
*/
|
|
264
|
+
createSession(sessionNumber, skills) {
|
|
265
|
+
const durationMinutes = skills.reduce((sum, s) => sum + s.estimatedMinutes, 0);
|
|
266
|
+
// Determine focus from most common tag or domain
|
|
267
|
+
const focus = this.determineFocus(skills);
|
|
268
|
+
// Build session object, only include focus if defined
|
|
269
|
+
const session = {
|
|
270
|
+
sessionNumber,
|
|
271
|
+
skills,
|
|
272
|
+
durationMinutes,
|
|
273
|
+
};
|
|
274
|
+
if (focus !== undefined) {
|
|
275
|
+
session.focus = focus;
|
|
276
|
+
}
|
|
277
|
+
return session;
|
|
278
|
+
}
|
|
279
|
+
/**
|
|
280
|
+
* Determine the focus/theme of a session
|
|
281
|
+
*/
|
|
282
|
+
determineFocus(skills) {
|
|
283
|
+
// Count tag occurrences
|
|
284
|
+
const tagCounts = new Map();
|
|
285
|
+
for (const skill of skills) {
|
|
286
|
+
for (const tag of skill.tags) {
|
|
287
|
+
tagCounts.set(tag, (tagCounts.get(tag) ?? 0) + 1);
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
// Find most common tag
|
|
291
|
+
let maxCount = 0;
|
|
292
|
+
let focus;
|
|
293
|
+
for (const [tag, count] of tagCounts) {
|
|
294
|
+
if (count > maxCount) {
|
|
295
|
+
maxCount = count;
|
|
296
|
+
focus = tag;
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
return focus;
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
/**
|
|
303
|
+
* Create a path generator
|
|
304
|
+
*/
|
|
305
|
+
export function createPathGenerator(storage) {
|
|
306
|
+
return new PathGenerator(storage);
|
|
307
|
+
}
|
|
308
|
+
//# sourceMappingURL=path.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"path.js","sourceRoot":"","sources":["../../../src/query/path.ts"],"names":[],"mappings":"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"}
|