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 | 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 4820x 4820x 4820x 4820x 4820x 4820x 4820x 4820x 4820x 4820x 4820x 4820x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 4820x 4820x 4820x 4820x 4820x 4820x 4820x 4820x 4820x 4820x 2x 2x 2x 2x 2x 2x 2x 2x 2x | /**
* Confidence and Uncertainty Calculations
*
* BKT gives us a point estimate of P(known), but we should also
* communicate how confident we are in that estimate.
*
* More data = more confidence
* Consistent observations = more confidence
*/
/**
* Calculate confidence in pKnown estimate.
*
* Based on:
* - Number of opportunities (more data = more confidence)
* - Consistency of observations (extreme success rates = more confidence)
*
* @param opportunities - Number of problems involving this skill
* @param successRate - Proportion of correct answers (0 to 1)
* @returns Confidence value in [0, 1] where 1 = highly confident
*/
export function calculateConfidence(opportunities: number, successRate: number): number {
// More data = more confidence (asymptotic to 1)
// With 20 opportunities, we're ~63% confident from data alone
// With 50 opportunities, we're ~92% confident from data alone
const dataConfidence = 1 - Math.exp(-opportunities / 20)
// Extreme success rates (very high or very low) = more confidence
// A 95% success rate is more informative than a 50% success rate
const extremity = Math.abs(successRate - 0.5) * 2 // 0 at 50%, 1 at 0% or 100%
const consistencyBonus = extremity * 0.2
return Math.min(1, dataConfidence + consistencyBonus)
}
/**
* Get human-readable confidence label for display.
*/
export function getConfidenceLabel(confidence: number): 'confident' | 'moderate' | 'uncertain' {
if (confidence > 0.7) return 'confident'
if (confidence > 0.4) return 'moderate'
return 'uncertain'
}
/**
* Calculate uncertainty range around pKnown estimate.
*
* When confidence is low, we should show a wider range.
* This helps communicate that the estimate is uncertain.
*
* @param pKnown - Point estimate of P(known)
* @param confidence - Confidence in the estimate
* @returns Low and high bounds of the uncertainty range
*/
export function getUncertaintyRange(
pKnown: number,
confidence: number
): { low: number; high: number } {
// Max uncertainty is ±30% when confidence = 0
const uncertainty = (1 - confidence) * 0.3
return {
low: Math.max(0, pKnown - uncertainty),
high: Math.min(1, pKnown + uncertainty),
}
}
/**
* Get staleness warning based on days since last practice.
* This is shown separately from P(known) - we don't apply decay.
*
* @param daysSinceLastPractice - Number of days since the skill was practiced
* @returns Warning message or null if recent enough
*/
export function getStalenessWarning(daysSinceLastPractice: number | null): string | null {
if (daysSinceLastPractice === null) return null
if (daysSinceLastPractice < 7) return null
if (daysSinceLastPractice < 14) return 'Not practiced recently'
if (daysSinceLastPractice < 30) return 'Getting rusty'
return 'Very stale - may need review'
}
|