learngraph 0.4.0 → 0.7.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/api/routes/analytics.js +288 -0
- package/dist/cjs/api/routes/analytics.js.map +1 -0
- package/dist/cjs/api/routes/assessments.js +269 -0
- package/dist/cjs/api/routes/assessments.js.map +1 -0
- package/dist/cjs/api/routes/curriculum.js +345 -0
- package/dist/cjs/api/routes/curriculum.js.map +1 -0
- package/dist/cjs/api/routes/edges.js +162 -0
- package/dist/cjs/api/routes/edges.js.map +1 -0
- package/dist/cjs/api/routes/explore.js +224 -0
- package/dist/cjs/api/routes/explore.js.map +1 -0
- package/dist/cjs/api/routes/learners.js +324 -0
- package/dist/cjs/api/routes/learners.js.map +1 -0
- package/dist/cjs/api/routes/me.js +404 -0
- package/dist/cjs/api/routes/me.js.map +1 -0
- package/dist/cjs/api/routes/skills.js +319 -0
- package/dist/cjs/api/routes/skills.js.map +1 -0
- package/dist/cjs/api/server.js +185 -0
- package/dist/cjs/api/server.js.map +1 -0
- package/dist/cjs/api/types.js +10 -0
- package/dist/cjs/api/types.js.map +1 -0
- package/dist/cjs/assessment/adaptive.js +390 -0
- package/dist/cjs/assessment/adaptive.js.map +1 -0
- package/dist/cjs/assessment/bkt.js +362 -0
- package/dist/cjs/assessment/bkt.js.map +1 -0
- package/dist/cjs/assessment/index.js +54 -0
- package/dist/cjs/assessment/index.js.map +1 -0
- package/dist/cjs/assessment/irt.js +420 -0
- package/dist/cjs/assessment/irt.js.map +1 -0
- package/dist/cjs/assessment/mastery-engine.js +411 -0
- package/dist/cjs/assessment/mastery-engine.js.map +1 -0
- package/dist/cjs/components/LearningPathView.js +320 -0
- package/dist/cjs/components/LearningPathView.js.map +1 -0
- package/dist/cjs/components/ProgressDashboard.js +308 -0
- package/dist/cjs/components/ProgressDashboard.js.map +1 -0
- package/dist/cjs/components/SkillCard.js +264 -0
- package/dist/cjs/components/SkillCard.js.map +1 -0
- package/dist/cjs/components/SkillExplorer.js +401 -0
- package/dist/cjs/components/SkillExplorer.js.map +1 -0
- package/dist/cjs/components/SkillGraph.js +435 -0
- package/dist/cjs/components/SkillGraph.js.map +1 -0
- package/dist/cjs/components/hooks.js +510 -0
- package/dist/cjs/components/hooks.js.map +1 -0
- package/dist/cjs/components/index.js +77 -0
- package/dist/cjs/components/index.js.map +1 -0
- package/dist/cjs/components/types.js +34 -0
- package/dist/cjs/components/types.js.map +1 -0
- package/dist/cjs/index.js +36 -2
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/llm/adapters/anthropic.js +91 -3
- package/dist/cjs/llm/adapters/anthropic.js.map +1 -1
- package/dist/cjs/llm/adapters/gemini.js +101 -8
- package/dist/cjs/llm/adapters/gemini.js.map +1 -1
- package/dist/cjs/llm/adapters/index.js +42 -1
- package/dist/cjs/llm/adapters/index.js.map +1 -1
- package/dist/cjs/llm/adapters/ollama.js +120 -3
- package/dist/cjs/llm/adapters/ollama.js.map +1 -1
- package/dist/cjs/llm/adapters/openai.js +108 -2
- package/dist/cjs/llm/adapters/openai.js.map +1 -1
- package/dist/cjs/mcp/cli.js +302 -0
- package/dist/cjs/mcp/cli.js.map +1 -0
- package/dist/cjs/mcp/index.js +79 -0
- package/dist/cjs/mcp/index.js.map +1 -0
- package/dist/cjs/mcp/prompts.js +425 -0
- package/dist/cjs/mcp/prompts.js.map +1 -0
- package/dist/cjs/mcp/resources.js +371 -0
- package/dist/cjs/mcp/resources.js.map +1 -0
- package/dist/cjs/mcp/server.js +410 -0
- package/dist/cjs/mcp/server.js.map +1 -0
- package/dist/cjs/mcp/tools.js +612 -0
- package/dist/cjs/mcp/tools.js.map +1 -0
- package/dist/cjs/mcp/types.js +10 -0
- package/dist/cjs/mcp/types.js.map +1 -0
- 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/cjs/types/assessment.js +46 -0
- package/dist/cjs/types/assessment.js.map +1 -0
- package/dist/cjs/types/bloom.js +12 -1
- package/dist/cjs/types/bloom.js.map +1 -1
- package/dist/cjs/types/index.js +7 -1
- package/dist/cjs/types/index.js.map +1 -1
- package/dist/esm/api/routes/analytics.js +285 -0
- package/dist/esm/api/routes/analytics.js.map +1 -0
- package/dist/esm/api/routes/assessments.js +266 -0
- package/dist/esm/api/routes/assessments.js.map +1 -0
- package/dist/esm/api/routes/curriculum.js +342 -0
- package/dist/esm/api/routes/curriculum.js.map +1 -0
- package/dist/esm/api/routes/edges.js +159 -0
- package/dist/esm/api/routes/edges.js.map +1 -0
- package/dist/esm/api/routes/explore.js +221 -0
- package/dist/esm/api/routes/explore.js.map +1 -0
- package/dist/esm/api/routes/learners.js +321 -0
- package/dist/esm/api/routes/learners.js.map +1 -0
- package/dist/esm/api/routes/me.js +401 -0
- package/dist/esm/api/routes/me.js.map +1 -0
- package/dist/esm/api/routes/skills.js +316 -0
- package/dist/esm/api/routes/skills.js.map +1 -0
- package/dist/esm/api/server.js +179 -0
- package/dist/esm/api/server.js.map +1 -0
- package/dist/esm/api/types.js +9 -0
- package/dist/esm/api/types.js.map +1 -0
- package/dist/esm/assessment/adaptive.js +384 -0
- package/dist/esm/assessment/adaptive.js.map +1 -0
- package/dist/esm/assessment/bkt.js +354 -0
- package/dist/esm/assessment/bkt.js.map +1 -0
- package/dist/esm/assessment/index.js +21 -0
- package/dist/esm/assessment/index.js.map +1 -0
- package/dist/esm/assessment/irt.js +406 -0
- package/dist/esm/assessment/irt.js.map +1 -0
- package/dist/esm/assessment/mastery-engine.js +406 -0
- package/dist/esm/assessment/mastery-engine.js.map +1 -0
- package/dist/esm/components/LearningPathView.js +316 -0
- package/dist/esm/components/LearningPathView.js.map +1 -0
- package/dist/esm/components/ProgressDashboard.js +304 -0
- package/dist/esm/components/ProgressDashboard.js.map +1 -0
- package/dist/esm/components/SkillCard.js +260 -0
- package/dist/esm/components/SkillCard.js.map +1 -0
- package/dist/esm/components/SkillExplorer.js +397 -0
- package/dist/esm/components/SkillExplorer.js.map +1 -0
- package/dist/esm/components/SkillGraph.js +398 -0
- package/dist/esm/components/SkillGraph.js.map +1 -0
- package/dist/esm/components/hooks.js +502 -0
- package/dist/esm/components/hooks.js.map +1 -0
- package/dist/esm/components/index.js +61 -0
- package/dist/esm/components/index.js.map +1 -0
- package/dist/esm/components/types.js +31 -0
- package/dist/esm/components/types.js.map +1 -0
- package/dist/esm/index.js +13 -1
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/llm/adapters/anthropic.js +88 -2
- package/dist/esm/llm/adapters/anthropic.js.map +1 -1
- package/dist/esm/llm/adapters/gemini.js +98 -7
- package/dist/esm/llm/adapters/gemini.js.map +1 -1
- package/dist/esm/llm/adapters/index.js +15 -4
- package/dist/esm/llm/adapters/index.js.map +1 -1
- package/dist/esm/llm/adapters/ollama.js +117 -2
- package/dist/esm/llm/adapters/ollama.js.map +1 -1
- package/dist/esm/llm/adapters/openai.js +105 -1
- package/dist/esm/llm/adapters/openai.js.map +1 -1
- package/dist/esm/mcp/cli.js +267 -0
- package/dist/esm/mcp/cli.js.map +1 -0
- package/dist/esm/mcp/index.js +39 -0
- package/dist/esm/mcp/index.js.map +1 -0
- package/dist/esm/mcp/prompts.js +419 -0
- package/dist/esm/mcp/prompts.js.map +1 -0
- package/dist/esm/mcp/resources.js +359 -0
- package/dist/esm/mcp/resources.js.map +1 -0
- package/dist/esm/mcp/server.js +372 -0
- package/dist/esm/mcp/server.js.map +1 -0
- package/dist/esm/mcp/tools.js +598 -0
- package/dist/esm/mcp/tools.js.map +1 -0
- package/dist/esm/mcp/types.js +9 -0
- package/dist/esm/mcp/types.js.map +1 -0
- 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/esm/types/assessment.js +40 -0
- package/dist/esm/types/assessment.js.map +1 -0
- package/dist/esm/types/bloom.js +11 -0
- package/dist/esm/types/bloom.js.map +1 -1
- package/dist/esm/types/index.js +2 -1
- package/dist/esm/types/index.js.map +1 -1
- package/dist/types/api/routes/analytics.d.ts +14 -0
- package/dist/types/api/routes/analytics.d.ts.map +1 -0
- package/dist/types/api/routes/assessments.d.ts +14 -0
- package/dist/types/api/routes/assessments.d.ts.map +1 -0
- package/dist/types/api/routes/curriculum.d.ts +14 -0
- package/dist/types/api/routes/curriculum.d.ts.map +1 -0
- package/dist/types/api/routes/edges.d.ts +14 -0
- package/dist/types/api/routes/edges.d.ts.map +1 -0
- package/dist/types/api/routes/explore.d.ts +14 -0
- package/dist/types/api/routes/explore.d.ts.map +1 -0
- package/dist/types/api/routes/learners.d.ts +14 -0
- package/dist/types/api/routes/learners.d.ts.map +1 -0
- package/dist/types/api/routes/me.d.ts +14 -0
- package/dist/types/api/routes/me.d.ts.map +1 -0
- package/dist/types/api/routes/skills.d.ts +14 -0
- package/dist/types/api/routes/skills.d.ts.map +1 -0
- package/dist/types/api/server.d.ts +147 -0
- package/dist/types/api/server.d.ts.map +1 -0
- package/dist/types/api/types.d.ts +443 -0
- package/dist/types/api/types.d.ts.map +1 -0
- package/dist/types/assessment/adaptive.d.ts +155 -0
- package/dist/types/assessment/adaptive.d.ts.map +1 -0
- package/dist/types/assessment/bkt.d.ts +185 -0
- package/dist/types/assessment/bkt.d.ts.map +1 -0
- package/dist/types/assessment/index.d.ts +18 -0
- package/dist/types/assessment/index.d.ts.map +1 -0
- package/dist/types/assessment/irt.d.ts +159 -0
- package/dist/types/assessment/irt.d.ts.map +1 -0
- package/dist/types/assessment/mastery-engine.d.ts +178 -0
- package/dist/types/assessment/mastery-engine.d.ts.map +1 -0
- package/dist/types/components/LearningPathView.d.ts +40 -0
- package/dist/types/components/LearningPathView.d.ts.map +1 -0
- package/dist/types/components/ProgressDashboard.d.ts +49 -0
- package/dist/types/components/ProgressDashboard.d.ts.map +1 -0
- package/dist/types/components/SkillCard.d.ts +34 -0
- package/dist/types/components/SkillCard.d.ts.map +1 -0
- package/dist/types/components/SkillExplorer.d.ts +39 -0
- package/dist/types/components/SkillExplorer.d.ts.map +1 -0
- package/dist/types/components/SkillGraph.d.ts +38 -0
- package/dist/types/components/SkillGraph.d.ts.map +1 -0
- package/dist/types/components/hooks.d.ts +187 -0
- package/dist/types/components/hooks.d.ts.map +1 -0
- package/dist/types/components/index.d.ts +59 -0
- package/dist/types/components/index.d.ts.map +1 -0
- package/dist/types/components/types.d.ts +410 -0
- package/dist/types/components/types.d.ts.map +1 -0
- package/dist/types/index.d.ts +2 -1
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/llm/adapters/anthropic.d.ts +84 -1
- package/dist/types/llm/adapters/anthropic.d.ts.map +1 -1
- package/dist/types/llm/adapters/gemini.d.ts +93 -6
- package/dist/types/llm/adapters/gemini.d.ts.map +1 -1
- package/dist/types/llm/adapters/index.d.ts +13 -4
- package/dist/types/llm/adapters/index.d.ts.map +1 -1
- package/dist/types/llm/adapters/ollama.d.ts +126 -1
- package/dist/types/llm/adapters/ollama.d.ts.map +1 -1
- package/dist/types/llm/adapters/openai.d.ts +104 -1
- package/dist/types/llm/adapters/openai.d.ts.map +1 -1
- package/dist/types/mcp/cli.d.ts +15 -0
- package/dist/types/mcp/cli.d.ts.map +1 -0
- package/dist/types/mcp/index.d.ts +32 -0
- package/dist/types/mcp/index.d.ts.map +1 -0
- package/dist/types/mcp/prompts.d.ts +27 -0
- package/dist/types/mcp/prompts.d.ts.map +1 -0
- package/dist/types/mcp/resources.d.ts +59 -0
- package/dist/types/mcp/resources.d.ts.map +1 -0
- package/dist/types/mcp/server.d.ts +136 -0
- package/dist/types/mcp/server.d.ts.map +1 -0
- package/dist/types/mcp/tools.d.ts +344 -0
- package/dist/types/mcp/tools.d.ts.map +1 -0
- package/dist/types/mcp/types.d.ts +137 -0
- package/dist/types/mcp/types.d.ts.map +1 -0
- 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/dist/types/types/assessment.d.ts +512 -0
- package/dist/types/types/assessment.d.ts.map +1 -0
- package/dist/types/types/bloom.d.ts +4 -0
- package/dist/types/types/bloom.d.ts.map +1 -1
- package/dist/types/types/index.d.ts +3 -1
- package/dist/types/types/index.d.ts.map +1 -1
- package/package.json +48 -3
|
@@ -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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"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Assessment Types
|
|
4
|
+
*
|
|
5
|
+
* Comprehensive type definitions for the assessment framework including:
|
|
6
|
+
* - Question types (multiple choice, free response, etc.)
|
|
7
|
+
* - Assessment structures
|
|
8
|
+
* - Item Response Theory (IRT) parameters
|
|
9
|
+
* - Bayesian Knowledge Tracing (BKT) parameters
|
|
10
|
+
* - Evidence of learning
|
|
11
|
+
*
|
|
12
|
+
* @packageDocumentation
|
|
13
|
+
*/
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.BKT_DEFAULTS = void 0;
|
|
16
|
+
exports.createQuestionId = createQuestionId;
|
|
17
|
+
exports.createAssessmentId = createAssessmentId;
|
|
18
|
+
exports.createResponseId = createResponseId;
|
|
19
|
+
/**
|
|
20
|
+
* Create a typed QuestionId from a string
|
|
21
|
+
*/
|
|
22
|
+
function createQuestionId(id) {
|
|
23
|
+
return id;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Create a typed AssessmentId from a string
|
|
27
|
+
*/
|
|
28
|
+
function createAssessmentId(id) {
|
|
29
|
+
return id;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Create a typed ResponseId from a string
|
|
33
|
+
*/
|
|
34
|
+
function createResponseId(id) {
|
|
35
|
+
return id;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Default BKT parameters (empirically derived)
|
|
39
|
+
*/
|
|
40
|
+
exports.BKT_DEFAULTS = {
|
|
41
|
+
pInit: 0.3, // 30% prior mastery
|
|
42
|
+
pLearn: 0.1, // 10% chance to learn per opportunity
|
|
43
|
+
pSlip: 0.1, // 10% slip rate
|
|
44
|
+
pGuess: 0.2, // 20% guess rate
|
|
45
|
+
};
|
|
46
|
+
//# sourceMappingURL=assessment.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"assessment.js","sourceRoot":"","sources":["../../../src/types/assessment.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;GAWG;;;AAiBH,4CAEC;AAsGD,gDAEC;AAkGD,4CAEC;AAjND;;GAEG;AACH,SAAgB,gBAAgB,CAAC,EAAU;IACzC,OAAO,EAAgB,CAAC;AAC1B,CAAC;AAmGD;;GAEG;AACH,SAAgB,kBAAkB,CAAC,EAAU;IAC3C,OAAO,EAAkB,CAAC;AAC5B,CAAC;AA+FD;;GAEG;AACH,SAAgB,gBAAgB,CAAC,EAAU;IACzC,OAAO,EAAgB,CAAC;AAC1B,CAAC;AAwJD;;GAEG;AACU,QAAA,YAAY,GAAkB;IACzC,KAAK,EAAE,GAAG,EAAK,oBAAoB;IACnC,MAAM,EAAE,GAAG,EAAI,sCAAsC;IACrD,KAAK,EAAE,GAAG,EAAK,gBAAgB;IAC/B,MAAM,EAAE,GAAG,EAAI,iBAAiB;CACjC,CAAC"}
|
package/dist/cjs/types/bloom.js
CHANGED
|
@@ -1,9 +1,20 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.BLOOM_VERBS = exports.BLOOM_LEVEL_ORDER = void 0;
|
|
3
|
+
exports.BLOOM_VERBS = exports.BLOOM_LEVEL_ORDER = exports.BLOOM_LEVELS = void 0;
|
|
4
4
|
exports.detectBloomLevel = detectBloomLevel;
|
|
5
5
|
exports.compareBloomLevels = compareBloomLevels;
|
|
6
6
|
exports.meetsBloomThreshold = meetsBloomThreshold;
|
|
7
|
+
/**
|
|
8
|
+
* All Bloom's levels as an ordered array
|
|
9
|
+
*/
|
|
10
|
+
exports.BLOOM_LEVELS = [
|
|
11
|
+
'remember',
|
|
12
|
+
'understand',
|
|
13
|
+
'apply',
|
|
14
|
+
'analyze',
|
|
15
|
+
'evaluate',
|
|
16
|
+
'create',
|
|
17
|
+
];
|
|
7
18
|
/**
|
|
8
19
|
* Numeric mapping for Bloom's levels (1-6 scale)
|
|
9
20
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bloom.js","sourceRoot":"","sources":["../../../src/types/bloom.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"bloom.js","sourceRoot":"","sources":["../../../src/types/bloom.ts"],"names":[],"mappings":"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"}
|
package/dist/cjs/types/index.js
CHANGED
|
@@ -5,8 +5,9 @@
|
|
|
5
5
|
* @packageDocumentation
|
|
6
6
|
*/
|
|
7
7
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
-
exports.GRAPH_VERSION = exports.masteryGap = exports.hasMastery = exports.MASTERY_THRESHOLDS = exports.suggestEdgeType = exports.isValidEdgeStrength = exports.EDGE_STRENGTH_THRESHOLDS = exports.createEdgeId = exports.isValidMasteryThreshold = exports.isValidDifficulty = exports.THRESHOLD_CONCEPT_MASTERY = exports.SKILL_DEFAULTS = exports.createSkillId = exports.meetsBloomThreshold = exports.compareBloomLevels = exports.detectBloomLevel = exports.BLOOM_VERBS = exports.BLOOM_LEVEL_ORDER = void 0;
|
|
8
|
+
exports.BKT_DEFAULTS = exports.createResponseId = exports.createAssessmentId = exports.createQuestionId = exports.GRAPH_VERSION = exports.masteryGap = exports.hasMastery = exports.MASTERY_THRESHOLDS = exports.suggestEdgeType = exports.isValidEdgeStrength = exports.EDGE_STRENGTH_THRESHOLDS = exports.createEdgeId = exports.isValidMasteryThreshold = exports.isValidDifficulty = exports.THRESHOLD_CONCEPT_MASTERY = exports.SKILL_DEFAULTS = exports.createSkillId = exports.meetsBloomThreshold = exports.compareBloomLevels = exports.detectBloomLevel = exports.BLOOM_VERBS = exports.BLOOM_LEVEL_ORDER = exports.BLOOM_LEVELS = void 0;
|
|
9
9
|
var bloom_js_1 = require("./bloom.js");
|
|
10
|
+
Object.defineProperty(exports, "BLOOM_LEVELS", { enumerable: true, get: function () { return bloom_js_1.BLOOM_LEVELS; } });
|
|
10
11
|
Object.defineProperty(exports, "BLOOM_LEVEL_ORDER", { enumerable: true, get: function () { return bloom_js_1.BLOOM_LEVEL_ORDER; } });
|
|
11
12
|
Object.defineProperty(exports, "BLOOM_VERBS", { enumerable: true, get: function () { return bloom_js_1.BLOOM_VERBS; } });
|
|
12
13
|
Object.defineProperty(exports, "detectBloomLevel", { enumerable: true, get: function () { return bloom_js_1.detectBloomLevel; } });
|
|
@@ -29,4 +30,9 @@ Object.defineProperty(exports, "hasMastery", { enumerable: true, get: function (
|
|
|
29
30
|
Object.defineProperty(exports, "masteryGap", { enumerable: true, get: function () { return mastery_js_1.masteryGap; } });
|
|
30
31
|
var graph_js_1 = require("./graph.js");
|
|
31
32
|
Object.defineProperty(exports, "GRAPH_VERSION", { enumerable: true, get: function () { return graph_js_1.GRAPH_VERSION; } });
|
|
33
|
+
var assessment_js_1 = require("./assessment.js");
|
|
34
|
+
Object.defineProperty(exports, "createQuestionId", { enumerable: true, get: function () { return assessment_js_1.createQuestionId; } });
|
|
35
|
+
Object.defineProperty(exports, "createAssessmentId", { enumerable: true, get: function () { return assessment_js_1.createAssessmentId; } });
|
|
36
|
+
Object.defineProperty(exports, "createResponseId", { enumerable: true, get: function () { return assessment_js_1.createResponseId; } });
|
|
37
|
+
Object.defineProperty(exports, "BKT_DEFAULTS", { enumerable: true, get: function () { return assessment_js_1.BKT_DEFAULTS; } });
|
|
32
38
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/types/index.ts"],"names":[],"mappings":";AAAA;;;;GAIG;;;AAMH,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/types/index.ts"],"names":[],"mappings":";AAAA;;;;GAIG;;;AAMH,uCAOoB;AANlB,wGAAA,YAAY,OAAA;AACZ,6GAAA,iBAAiB,OAAA;AACjB,uGAAA,WAAW,OAAA;AACX,4GAAA,gBAAgB,OAAA;AAChB,8GAAA,kBAAkB,OAAA;AAClB,+GAAA,mBAAmB,OAAA;AAOrB,uCAMoB;AALlB,yGAAA,aAAa,OAAA;AACb,0GAAA,cAAc,OAAA;AACd,qHAAA,yBAAyB,OAAA;AACzB,6GAAA,iBAAiB,OAAA;AACjB,mHAAA,uBAAuB,OAAA;AAOzB,qCAKmB;AAJjB,uGAAA,YAAY,OAAA;AACZ,mHAAA,wBAAwB,OAAA;AACxB,8GAAA,mBAAmB,OAAA;AACnB,0GAAA,eAAe,OAAA;AAOjB,2CAA0E;AAAjE,gHAAA,kBAAkB,OAAA;AAAE,wGAAA,UAAU,OAAA;AAAE,wGAAA,UAAU,OAAA;AAanD,uCAA2C;AAAlC,yGAAA,aAAa,OAAA;AAgItB,iDAKyB;AAJvB,iHAAA,gBAAgB,OAAA;AAChB,mHAAA,kBAAkB,OAAA;AAClB,iHAAA,gBAAgB,OAAA;AAChB,6GAAA,YAAY,OAAA"}
|
|
@@ -0,0 +1,285 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Analytics routes
|
|
3
|
+
*
|
|
4
|
+
* Endpoints for skill analytics and cohort analysis.
|
|
5
|
+
*
|
|
6
|
+
* @packageDocumentation
|
|
7
|
+
*/
|
|
8
|
+
import { Hono } from 'hono';
|
|
9
|
+
import { success, error, ErrorCodes } from '../server.js';
|
|
10
|
+
import { createSkillId } from '../../types/index.js';
|
|
11
|
+
/**
|
|
12
|
+
* Create analytics routes
|
|
13
|
+
*/
|
|
14
|
+
export function createAnalyticsRoutes(ctx) {
|
|
15
|
+
const app = new Hono();
|
|
16
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
17
|
+
// Skill Analytics
|
|
18
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
19
|
+
app.get('/skills/:skillId', async (c) => {
|
|
20
|
+
try {
|
|
21
|
+
const skillIdParam = c.req.param('skillId');
|
|
22
|
+
const skillId = createSkillId(skillIdParam);
|
|
23
|
+
const skill = await ctx.storage.getSkill(skillId);
|
|
24
|
+
if (!skill) {
|
|
25
|
+
return c.json(error(ErrorCodes.NOT_FOUND, `Skill not found: ${skillIdParam}`), 404);
|
|
26
|
+
}
|
|
27
|
+
// Get all learners and their mastery for this skill
|
|
28
|
+
if (!ctx.storage.getAllLearners || !ctx.storage.getMastery) {
|
|
29
|
+
return c.json(success({
|
|
30
|
+
skillId: skillIdParam,
|
|
31
|
+
skillName: skill.name,
|
|
32
|
+
learnerCount: 0,
|
|
33
|
+
averageMastery: 0,
|
|
34
|
+
masteryDistribution: new Array(10).fill(0),
|
|
35
|
+
averageTimeToMastery: skill.estimatedMinutes,
|
|
36
|
+
commonMistakes: [],
|
|
37
|
+
message: 'Learner analytics not available - storage does not support learner operations',
|
|
38
|
+
}));
|
|
39
|
+
}
|
|
40
|
+
const learners = await ctx.storage.getAllLearners();
|
|
41
|
+
const masteryLevels = [];
|
|
42
|
+
for (const learner of learners) {
|
|
43
|
+
const mastery = await ctx.storage.getMastery(learner.id, skillIdParam);
|
|
44
|
+
if (mastery) {
|
|
45
|
+
masteryLevels.push(mastery.mastery);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
// Calculate distribution (10 buckets: 0-10%, 10-20%, etc.)
|
|
49
|
+
const distribution = new Array(10).fill(0);
|
|
50
|
+
for (const level of masteryLevels) {
|
|
51
|
+
const bucket = Math.min(Math.floor(level * 10), 9);
|
|
52
|
+
distribution[bucket]++;
|
|
53
|
+
}
|
|
54
|
+
const averageMastery = masteryLevels.length > 0
|
|
55
|
+
? masteryLevels.reduce((a, b) => a + b, 0) / masteryLevels.length
|
|
56
|
+
: 0;
|
|
57
|
+
return c.json(success({
|
|
58
|
+
skillId: skillIdParam,
|
|
59
|
+
skillName: skill.name,
|
|
60
|
+
learnerCount: masteryLevels.length,
|
|
61
|
+
averageMastery,
|
|
62
|
+
masteryDistribution: distribution,
|
|
63
|
+
averageTimeToMastery: skill.estimatedMinutes,
|
|
64
|
+
commonMistakes: [],
|
|
65
|
+
}));
|
|
66
|
+
}
|
|
67
|
+
catch (err) {
|
|
68
|
+
console.error('Skill analytics error:', err);
|
|
69
|
+
return c.json(error(ErrorCodes.INTERNAL_ERROR, 'Failed to get skill analytics'), 500);
|
|
70
|
+
}
|
|
71
|
+
});
|
|
72
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
73
|
+
// Cohort Analytics
|
|
74
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
75
|
+
app.get('/cohort', async (c) => {
|
|
76
|
+
try {
|
|
77
|
+
const cohortTag = c.req.query('tag');
|
|
78
|
+
if (!ctx.storage.getAllLearners || !ctx.storage.getLearnerMastery) {
|
|
79
|
+
return c.json(success({
|
|
80
|
+
learnerCount: 0,
|
|
81
|
+
averageMastery: 0,
|
|
82
|
+
masteryDistribution: new Array(10).fill(0),
|
|
83
|
+
strugglingSkills: [],
|
|
84
|
+
topPerformers: [],
|
|
85
|
+
atRiskLearners: [],
|
|
86
|
+
message: 'Learner analytics not available - storage does not support learner operations',
|
|
87
|
+
}));
|
|
88
|
+
}
|
|
89
|
+
let learners = await ctx.storage.getAllLearners();
|
|
90
|
+
// Filter by cohort tag if provided
|
|
91
|
+
if (cohortTag) {
|
|
92
|
+
learners = learners.filter((l) => l.metadata?.cohort === cohortTag ||
|
|
93
|
+
l.metadata?.tags?.includes(cohortTag));
|
|
94
|
+
}
|
|
95
|
+
if (learners.length === 0) {
|
|
96
|
+
return c.json(success({
|
|
97
|
+
learnerCount: 0,
|
|
98
|
+
averageMastery: 0,
|
|
99
|
+
masteryDistribution: new Array(10).fill(0),
|
|
100
|
+
strugglingSkills: [],
|
|
101
|
+
topPerformers: [],
|
|
102
|
+
atRiskLearners: [],
|
|
103
|
+
}));
|
|
104
|
+
}
|
|
105
|
+
// Calculate overall mastery
|
|
106
|
+
const learnerMasteries = [];
|
|
107
|
+
const skillMasteries = new Map();
|
|
108
|
+
for (const learner of learners) {
|
|
109
|
+
const masteryStates = await ctx.storage.getLearnerMastery(learner.id);
|
|
110
|
+
const avgMastery = masteryStates.length > 0
|
|
111
|
+
? masteryStates.reduce((sum, m) => sum + m.mastery, 0) / masteryStates.length
|
|
112
|
+
: 0;
|
|
113
|
+
learnerMasteries.push({ id: learner.id, avgMastery });
|
|
114
|
+
for (const m of masteryStates) {
|
|
115
|
+
if (!skillMasteries.has(m.skillId)) {
|
|
116
|
+
skillMasteries.set(m.skillId, []);
|
|
117
|
+
}
|
|
118
|
+
skillMasteries.get(m.skillId).push(m.mastery);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
// Calculate distribution
|
|
122
|
+
const distribution = new Array(10).fill(0);
|
|
123
|
+
for (const { avgMastery } of learnerMasteries) {
|
|
124
|
+
const bucket = Math.min(Math.floor(avgMastery * 10), 9);
|
|
125
|
+
distribution[bucket]++;
|
|
126
|
+
}
|
|
127
|
+
const overallAverage = learnerMasteries.reduce((sum, l) => sum + l.avgMastery, 0) / learnerMasteries.length;
|
|
128
|
+
// Find struggling skills (low average mastery)
|
|
129
|
+
const skillAverages = [];
|
|
130
|
+
for (const [skillId, levels] of skillMasteries) {
|
|
131
|
+
const avg = levels.reduce((a, b) => a + b, 0) / levels.length;
|
|
132
|
+
skillAverages.push({ id: skillId, avg });
|
|
133
|
+
}
|
|
134
|
+
skillAverages.sort((a, b) => a.avg - b.avg);
|
|
135
|
+
const strugglingSkills = skillAverages.slice(0, 5).map((s) => s.id);
|
|
136
|
+
// Top performers and at-risk learners
|
|
137
|
+
learnerMasteries.sort((a, b) => b.avgMastery - a.avgMastery);
|
|
138
|
+
const topPerformers = learnerMasteries.slice(0, 5).map((l) => l.id);
|
|
139
|
+
const atRiskLearners = learnerMasteries
|
|
140
|
+
.filter((l) => l.avgMastery < 0.3)
|
|
141
|
+
.slice(0, 5)
|
|
142
|
+
.map((l) => l.id);
|
|
143
|
+
return c.json(success({
|
|
144
|
+
learnerCount: learners.length,
|
|
145
|
+
averageMastery: overallAverage,
|
|
146
|
+
masteryDistribution: distribution,
|
|
147
|
+
strugglingSkills,
|
|
148
|
+
topPerformers,
|
|
149
|
+
atRiskLearners,
|
|
150
|
+
}));
|
|
151
|
+
}
|
|
152
|
+
catch (err) {
|
|
153
|
+
console.error('Cohort analytics error:', err);
|
|
154
|
+
return c.json(error(ErrorCodes.INTERNAL_ERROR, 'Failed to get cohort analytics'), 500);
|
|
155
|
+
}
|
|
156
|
+
});
|
|
157
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
158
|
+
// Progress Over Time
|
|
159
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
160
|
+
app.get('/progress', async (c) => {
|
|
161
|
+
try {
|
|
162
|
+
const learnerId = c.req.query('learnerId');
|
|
163
|
+
const skillIdParam = c.req.query('skillId');
|
|
164
|
+
const days = Number(c.req.query('days')) || 30;
|
|
165
|
+
if (!learnerId) {
|
|
166
|
+
return c.json(error(ErrorCodes.BAD_REQUEST, 'learnerId is required'), 400);
|
|
167
|
+
}
|
|
168
|
+
if (!ctx.storage.getLearner || !ctx.storage.getLearnerMastery) {
|
|
169
|
+
return c.json(error(ErrorCodes.BAD_REQUEST, 'Learner operations not supported by storage'), 400);
|
|
170
|
+
}
|
|
171
|
+
const learner = await ctx.storage.getLearner(learnerId);
|
|
172
|
+
if (!learner) {
|
|
173
|
+
return c.json(error(ErrorCodes.NOT_FOUND, `Learner not found: ${learnerId}`), 404);
|
|
174
|
+
}
|
|
175
|
+
// Get mastery history
|
|
176
|
+
const masteryStates = await ctx.storage.getLearnerMastery(learnerId);
|
|
177
|
+
let filtered = masteryStates;
|
|
178
|
+
if (skillIdParam) {
|
|
179
|
+
filtered = filtered.filter((m) => m.skillId === skillIdParam);
|
|
180
|
+
}
|
|
181
|
+
// Generate daily progress (placeholder - would use actual historical data)
|
|
182
|
+
const now = Date.now();
|
|
183
|
+
const dayMs = 24 * 60 * 60 * 1000;
|
|
184
|
+
const dataPoints = [];
|
|
185
|
+
for (let i = days - 1; i >= 0; i--) {
|
|
186
|
+
const date = new Date(now - i * dayMs).toISOString().split('T')[0];
|
|
187
|
+
const avgMastery = filtered.length > 0
|
|
188
|
+
? filtered.reduce((sum, m) => sum + m.mastery, 0) / filtered.length
|
|
189
|
+
: 0;
|
|
190
|
+
// Simulate progression (in reality, would use historical data)
|
|
191
|
+
const progress = avgMastery * (1 - i / days / 2);
|
|
192
|
+
dataPoints.push({
|
|
193
|
+
date,
|
|
194
|
+
mastery: progress,
|
|
195
|
+
skillsWorked: Math.floor(Math.random() * 5),
|
|
196
|
+
});
|
|
197
|
+
}
|
|
198
|
+
return c.json(success({
|
|
199
|
+
learnerId,
|
|
200
|
+
skillId: skillIdParam || 'all',
|
|
201
|
+
days,
|
|
202
|
+
dataPoints,
|
|
203
|
+
}));
|
|
204
|
+
}
|
|
205
|
+
catch (err) {
|
|
206
|
+
console.error('Progress analytics error:', err);
|
|
207
|
+
return c.json(error(ErrorCodes.INTERNAL_ERROR, 'Failed to get progress'), 500);
|
|
208
|
+
}
|
|
209
|
+
});
|
|
210
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
211
|
+
// Graph Bottlenecks
|
|
212
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
213
|
+
app.get('/bottlenecks', async (c) => {
|
|
214
|
+
try {
|
|
215
|
+
const skills = await ctx.storage.findSkills({});
|
|
216
|
+
const edges = await ctx.storage.findPrerequisites({});
|
|
217
|
+
if (!ctx.storage.getAllLearners || !ctx.storage.getMastery) {
|
|
218
|
+
// Return graph-only analysis without learner data
|
|
219
|
+
const dependentCounts = new Map();
|
|
220
|
+
for (const edge of edges) {
|
|
221
|
+
const sourceStr = String(edge.sourceId);
|
|
222
|
+
dependentCounts.set(sourceStr, (dependentCounts.get(sourceStr) || 0) + 1);
|
|
223
|
+
}
|
|
224
|
+
const bottlenecks = skills
|
|
225
|
+
.map((skill) => ({
|
|
226
|
+
id: String(skill.id),
|
|
227
|
+
name: skill.name,
|
|
228
|
+
dependentCount: dependentCounts.get(String(skill.id)) || 0,
|
|
229
|
+
averageMastery: 0,
|
|
230
|
+
learnersStuck: 0,
|
|
231
|
+
}))
|
|
232
|
+
.filter((b) => b.dependentCount >= 2)
|
|
233
|
+
.sort((a, b) => b.dependentCount - a.dependentCount)
|
|
234
|
+
.slice(0, 10);
|
|
235
|
+
return c.json(success(bottlenecks));
|
|
236
|
+
}
|
|
237
|
+
const learners = await ctx.storage.getAllLearners();
|
|
238
|
+
// Find skills that are prerequisites for many others
|
|
239
|
+
const dependentCounts = new Map();
|
|
240
|
+
for (const edge of edges) {
|
|
241
|
+
const sourceStr = String(edge.sourceId);
|
|
242
|
+
dependentCounts.set(sourceStr, (dependentCounts.get(sourceStr) || 0) + 1);
|
|
243
|
+
}
|
|
244
|
+
// Calculate average mastery for high-dependency skills
|
|
245
|
+
const bottlenecks = [];
|
|
246
|
+
for (const skill of skills) {
|
|
247
|
+
const skillIdStr = String(skill.id);
|
|
248
|
+
const dependentCount = dependentCounts.get(skillIdStr) || 0;
|
|
249
|
+
if (dependentCount < 2)
|
|
250
|
+
continue; // Only consider skills with multiple dependents
|
|
251
|
+
let totalMastery = 0;
|
|
252
|
+
let stuckCount = 0;
|
|
253
|
+
let learnerCount = 0;
|
|
254
|
+
for (const learner of learners) {
|
|
255
|
+
const mastery = await ctx.storage.getMastery(learner.id, skillIdStr);
|
|
256
|
+
if (mastery) {
|
|
257
|
+
learnerCount++;
|
|
258
|
+
totalMastery += mastery.mastery;
|
|
259
|
+
if (mastery.mastery < skill.masteryThreshold && mastery.mastery > 0.1) {
|
|
260
|
+
stuckCount++;
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
if (learnerCount > 0) {
|
|
265
|
+
bottlenecks.push({
|
|
266
|
+
id: skillIdStr,
|
|
267
|
+
name: skill.name,
|
|
268
|
+
dependentCount,
|
|
269
|
+
averageMastery: totalMastery / learnerCount,
|
|
270
|
+
learnersStuck: stuckCount,
|
|
271
|
+
});
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
// Sort by impact (dependents * stuck learners)
|
|
275
|
+
bottlenecks.sort((a, b) => b.dependentCount * b.learnersStuck - a.dependentCount * a.learnersStuck);
|
|
276
|
+
return c.json(success(bottlenecks.slice(0, 10)));
|
|
277
|
+
}
|
|
278
|
+
catch (err) {
|
|
279
|
+
console.error('Bottlenecks error:', err);
|
|
280
|
+
return c.json(error(ErrorCodes.INTERNAL_ERROR, 'Failed to get bottlenecks'), 500);
|
|
281
|
+
}
|
|
282
|
+
});
|
|
283
|
+
return app;
|
|
284
|
+
}
|
|
285
|
+
//# sourceMappingURL=analytics.js.map
|