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 | 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 140x 140x 140x 140x 77x 140x 140x 34x 140x 140x 29x 29x 22x 7x 140x 140x 140x 140x 140x 140x 1x 1x 1x 1x 1x 1x 17x 17x 17x 17x 17x 17x 17x 17x 17x 17x 17x 17x 17x 17x | // Display rules for conditional per-problem scaffolding
import type { ProblemMeta, SubtractionProblemMeta } from './problemAnalysis'
export type AnyProblemMeta = ProblemMeta | SubtractionProblemMeta
export type RuleMode =
| 'auto' // Defer to mastery progression (should be resolved before rendering)
| 'always' // Always show this display option
| 'never' // Never show this display option
| 'whenRegrouping' // Show when problem requires any regrouping
| 'whenMultipleRegroups' // Show when 2+ place values regroup
| 'when3PlusDigits' // Show when maxDigits >= 3
export interface DisplayRules {
carryBoxes: RuleMode
answerBoxes: RuleMode
placeValueColors: RuleMode
tenFrames: RuleMode
problemNumbers: RuleMode
cellBorders: RuleMode
borrowNotation: RuleMode // Subtraction: scratch boxes showing borrowed 10s
borrowingHints: RuleMode // Subtraction: arrows and visual hints
}
export interface ResolvedDisplayOptions {
showCarryBoxes: boolean
showAnswerBoxes: boolean
showPlaceValueColors: boolean
showTenFrames: boolean
showProblemNumbers: boolean
showCellBorder: boolean
showBorrowNotation: boolean // Subtraction: scratch work boxes in minuend
showBorrowingHints: boolean // Subtraction: hints with arrows
}
/**
* Evaluate a single display rule against a problem's metadata
* Works for both addition (regrouping = carrying) and subtraction (regrouping = borrowing)
*/
export function evaluateRule(mode: RuleMode, problem: AnyProblemMeta): boolean {
switch (mode) {
case 'auto':
// 'auto' should have been resolved to a concrete value in validation
// If it reaches here, something went wrong - default to 'always' to avoid breaking
console.error(
'[evaluateRule] BUG: "auto" mode should have been resolved before rendering. Defaulting to "always".'
)
return true
case 'always':
return true
case 'never':
return false
case 'whenRegrouping':
// Works for both: requiresRegrouping (addition) or requiresBorrowing (subtraction)
return 'requiresRegrouping' in problem
? problem.requiresRegrouping
: problem.requiresBorrowing
case 'whenMultipleRegroups':
// Works for both: regroupCount (addition) or borrowCount (subtraction)
return 'regroupCount' in problem ? problem.regroupCount >= 2 : problem.borrowCount >= 2
case 'when3PlusDigits':
return problem.maxDigits >= 3
}
}
/**
* Resolve all display rules for a specific problem
* Returns concrete boolean flags for rendering
*/
export function resolveDisplayForProblem(
rules: DisplayRules,
problem: AnyProblemMeta
): ResolvedDisplayOptions {
return {
showCarryBoxes: evaluateRule(rules.carryBoxes, problem),
showAnswerBoxes: evaluateRule(rules.answerBoxes, problem),
showPlaceValueColors: evaluateRule(rules.placeValueColors, problem),
showTenFrames: evaluateRule(rules.tenFrames, problem),
showProblemNumbers: evaluateRule(rules.problemNumbers, problem),
showCellBorder: evaluateRule(rules.cellBorders, problem),
showBorrowNotation: evaluateRule(rules.borrowNotation, problem),
showBorrowingHints: evaluateRule(rules.borrowingHints, problem),
}
}
|