Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 | 1x 1x 1x 1x 1x 1x 1x 7x 2x 2x 5x 5x 5x 5x 5x 5x 5x 7x 10x 10x 10x 10x 10x 10x 10x 5x 5x 5x 5x 6x 6x 5x 2x 2x 2x 2x 2x 5x 10x 5x 5x 5x 1x 1x 1x 1x 1x 13x 13x 13x 13x 13x 13x 13x 13x 13x 13x 13x 13x 12x 12x 13x 13x 13x 13x 13x 13x 13x 13x 13x 13x 13x 13x 13x 13x 13x 2x 2x 2x 2x 1x 1x 1x 1x 2x 2x 2x 2x 13x 13x 13x 3x 3x 3x 3x 3x 3x 13x 13x 3x 3x 3x 3x 3x 3x 13x 13x 4x 4x 6x 6x 4x 4x 13x 13x 13x 13x 13x 1x 1x 13x 13x 13x | import type { SkillBktResult } from '../curriculum/bkt'
import type { TestStudentProfile, TuningRound } from './types'
/**
* Format tuning history for notes
*/
export function formatTuningHistory(history: TuningRound[]): string {
if (history.length <= 1) {
return '' // No tuning needed
}
const lines: string[] = []
lines.push('')
lines.push('───────────────────────────────────────────────────────────')
lines.push('TUNING HISTORY')
lines.push('───────────────────────────────────────────────────────────')
for (const round of history) {
lines.push('')
lines.push(`Round ${round.round}:`)
lines.push(
` Classifications: 🔴 ${round.classifications.weak} weak, 📚 ${round.classifications.developing} developing, ✅ ${round.classifications.strong} strong`
)
if (round.success) {
lines.push(` Result: ✅ Success`)
} else {
lines.push(` Result: ❌ Failed`)
for (const reason of round.failureReasons) {
lines.push(` - ${reason}`)
}
if (round.adjustmentsApplied.length > 0) {
lines.push(` Adjustments applied for next round:`)
for (const adj of round.adjustmentsApplied) {
lines.push(` - ${adj}`)
}
}
}
}
return lines.join('\n')
}
/**
* Format BKT results into a human-readable summary for notes
*/
export function formatActualOutcomes(
bktResult: { skills: SkillBktResult[] },
profile: TestStudentProfile,
tuningHistory?: TuningRound[]
): string {
const skillsByClassification: Record<string, SkillBktResult[]> = {
weak: [],
developing: [],
strong: [],
}
for (const skill of bktResult.skills) {
if (skill.masteryClassification) {
skillsByClassification[skill.masteryClassification].push(skill)
}
}
const lines: string[] = []
lines.push('')
lines.push('═══════════════════════════════════════════════════════════')
lines.push('ACTUAL OUTCOMES (generated by seeder)')
lines.push('═══════════════════════════════════════════════════════════')
lines.push('')
lines.push(`BKT Classification Counts:`)
lines.push(` 🔴 Weak: ${skillsByClassification.weak.length}`)
lines.push(` 📚 Developing: ${skillsByClassification.developing.length}`)
lines.push(` ✅ Strong: ${skillsByClassification.strong.length}`)
lines.push('')
if (profile.expectedSessionMode) {
lines.push(`Expected Session Mode: ${profile.expectedSessionMode.toUpperCase()}`)
// Determine actual mode based on BKT
let actualMode = 'maintenance'
if (skillsByClassification.weak.length > 0) {
actualMode = 'remediation'
} else if (skillsByClassification.strong.length === profile.practicingSkills.length) {
actualMode = 'progression'
}
const matches = actualMode === profile.expectedSessionMode ? '✅' : '⚠️'
lines.push(`Actual Session Mode: ${actualMode.toUpperCase()} ${matches}`)
lines.push('')
}
// List skills by classification with pKnown values
if (skillsByClassification.weak.length > 0) {
lines.push('Weak Skills (pKnown < 0.5):')
for (const skill of skillsByClassification.weak) {
lines.push(` - ${skill.skillId}: ${(skill.pKnown * 100).toFixed(0)}%`)
}
lines.push('')
}
if (skillsByClassification.developing.length > 0) {
lines.push('Developing Skills (0.5 ≤ pKnown < 0.8):')
for (const skill of skillsByClassification.developing) {
lines.push(` - ${skill.skillId}: ${(skill.pKnown * 100).toFixed(0)}%`)
}
lines.push('')
}
if (skillsByClassification.strong.length > 0) {
lines.push('Strong Skills (pKnown ≥ 0.8):')
for (const skill of skillsByClassification.strong) {
lines.push(` - ${skill.skillId}: ${(skill.pKnown * 100).toFixed(0)}%`)
}
lines.push('')
}
lines.push(`Generated: ${new Date().toISOString()}`)
// Add tuning history if present
if (tuningHistory && tuningHistory.length > 0) {
lines.push(formatTuningHistory(tuningHistory))
}
return lines.join('\n')
}
|