fix(practice): correct five complement skill detection for addition and subtraction
Fix bugs where five complement skills were incorrectly detected when the heaven bead was already active: Addition: When adding 1-4 results in 6-9 and currentDigit >= 5, no five complement is needed - just add earth beads directly. Subtraction: When ten complement addition crosses 5 boundary but currentDigit >= 5, no five complement is needed for the addition part. Also includes UX improvements from previous session: - Dream sequence: show target value for 1s then fade out after help completion - Clear answer boxes on help abacus dismiss - Handle typing during help mode Add comprehensive unit tests for column analysis functions. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
bcb1c7a173
commit
1139c4d1a1
|
|
@ -82,8 +82,8 @@ export function PracticeClient({ studentId, player, initialSession }: PracticeCl
|
|||
<main
|
||||
data-component="practice-page"
|
||||
className={css({
|
||||
minHeight: '100vh',
|
||||
paddingTop: '80px', // Nav height only, no extra padding for practice
|
||||
minHeight: 'calc(100vh - 80px)', // Full height minus nav
|
||||
marginTop: '80px', // Push below nav
|
||||
})}
|
||||
>
|
||||
<PracticeErrorBoundary studentName={player.name}>
|
||||
|
|
|
|||
|
|
@ -237,6 +237,7 @@ export function ActiveSession({
|
|||
enterHelpMode,
|
||||
exitHelpMode,
|
||||
clearAnswer,
|
||||
setAnswer,
|
||||
startSubmit,
|
||||
completeSubmit,
|
||||
startTransition,
|
||||
|
|
@ -253,12 +254,15 @@ export function ActiveSession({
|
|||
// These reset when entering a new help session (helpContext changes)
|
||||
const [helpAbacusDismissed, setHelpAbacusDismissed] = useState(false)
|
||||
const [helpPanelDismissed, setHelpPanelDismissed] = useState(false)
|
||||
// Track when answer is fading out (for dream sequence)
|
||||
const [answerFadingOut, setAnswerFadingOut] = useState(false)
|
||||
|
||||
// Reset dismissed states when help context changes (new help session)
|
||||
useEffect(() => {
|
||||
if (helpContext) {
|
||||
setHelpAbacusDismissed(false)
|
||||
setHelpPanelDismissed(false)
|
||||
setAnswerFadingOut(false)
|
||||
}
|
||||
}, [helpContext])
|
||||
|
||||
|
|
@ -390,12 +394,32 @@ export function ActiveSession({
|
|||
}, [phase, matchedPrefixIndex, prefixSums.length, enterHelpMode])
|
||||
|
||||
// Handle when student reaches target value on help abacus
|
||||
// Sequence: show target value → dismiss abacus → show value in answer boxes → fade to empty → exit
|
||||
const handleTargetReached = useCallback(() => {
|
||||
if (phase.phase !== 'helpMode') return
|
||||
if (phase.phase !== 'helpMode' || !helpContext) return
|
||||
|
||||
// Step 1: Set the answer to the target value (shows in answer boxes behind abacus)
|
||||
setAnswer(String(helpContext.targetValue))
|
||||
|
||||
// Step 2: After a brief moment, dismiss the help abacus to reveal the answer
|
||||
setTimeout(() => {
|
||||
exitHelpMode()
|
||||
}, 800)
|
||||
}, [phase.phase, exitHelpMode])
|
||||
setHelpAbacusDismissed(true)
|
||||
|
||||
// Step 3: After abacus fades out (300ms), answer boxes are visible with target value
|
||||
// Wait 1 second to let user see the result
|
||||
setTimeout(() => {
|
||||
// Step 4: Start fading out the answer
|
||||
setAnswerFadingOut(true)
|
||||
|
||||
// Step 5: After fade-out completes (300ms), clear and exit
|
||||
setTimeout(() => {
|
||||
clearAnswer()
|
||||
setAnswerFadingOut(false)
|
||||
exitHelpMode()
|
||||
}, 300) // Match fade-out duration
|
||||
}, 1000) // Show target value in answer boxes for 1 second
|
||||
}, 600) // Brief pause to see success state on abacus
|
||||
}, [phase.phase, helpContext, setAnswer, clearAnswer, exitHelpMode])
|
||||
|
||||
// Handle submit
|
||||
const handleSubmit = useCallback(async () => {
|
||||
|
|
@ -971,6 +995,7 @@ export function ActiveSession({
|
|||
helpOverlayVisible={showHelpOverlay && !helpAbacusDismissed}
|
||||
helpOverlayTransitionMs={helpAbacusDismissed ? 300 : 1000}
|
||||
onHelpOverlayTransitionEnd={clearAnswer}
|
||||
answerFadingOut={answerFadingOut}
|
||||
generationTrace={attempt.problem.generationTrace}
|
||||
complexityBudget={currentSlot?.constraints?.maxComplexityBudgetPerTerm}
|
||||
/>
|
||||
|
|
|
|||
|
|
@ -135,7 +135,7 @@ export function PlanReview({ plan, studentName, onApprove, onCancel }: PlanRevie
|
|||
borderColor: isDark ? 'gray.700' : 'gray.200',
|
||||
})}
|
||||
>
|
||||
{/* Time and problem count */}
|
||||
{/* Time and focus */}
|
||||
<div
|
||||
className={css({
|
||||
display: 'flex',
|
||||
|
|
@ -157,14 +157,6 @@ export function PlanReview({ plan, studentName, onApprove, onCancel }: PlanRevie
|
|||
>
|
||||
~{summary.estimatedMinutes} min
|
||||
</div>
|
||||
<div
|
||||
className={css({
|
||||
fontSize: '0.875rem',
|
||||
color: isDark ? 'gray.400' : 'gray.500',
|
||||
})}
|
||||
>
|
||||
{summary.totalProblemCount} problems
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className={css({
|
||||
|
|
|
|||
|
|
@ -34,6 +34,8 @@ interface VerticalProblemProps {
|
|||
helpOverlayTransitionMs?: number
|
||||
/** Called when help overlay transition completes (useful for clearing answer after fade-in) */
|
||||
onHelpOverlayTransitionEnd?: () => void
|
||||
/** Whether the answer row is fading out (for dream sequence after help mode) */
|
||||
answerFadingOut?: boolean
|
||||
/** Generation trace with per-term skills and complexity (for debug overlay) */
|
||||
generationTrace?: GenerationTrace
|
||||
/** Complexity budget constraint (for debug overlay) */
|
||||
|
|
@ -63,6 +65,7 @@ export function VerticalProblem({
|
|||
helpOverlayVisible = false,
|
||||
helpOverlayTransitionMs = 1000,
|
||||
onHelpOverlayTransitionEnd,
|
||||
answerFadingOut = false,
|
||||
generationTrace,
|
||||
complexityBudget,
|
||||
}: VerticalProblemProps) {
|
||||
|
|
@ -372,7 +375,11 @@ export function VerticalProblem({
|
|||
})}
|
||||
onTransitionEnd={(e) => {
|
||||
// Only fire for opacity transition on this element, and only when becoming visible
|
||||
if (e.propertyName === 'opacity' && e.target === e.currentTarget && helpOverlayVisible) {
|
||||
if (
|
||||
e.propertyName === 'opacity' &&
|
||||
e.target === e.currentTarget &&
|
||||
helpOverlayVisible
|
||||
) {
|
||||
onHelpOverlayTransitionEnd?.()
|
||||
}
|
||||
}}
|
||||
|
|
@ -384,6 +391,7 @@ export function VerticalProblem({
|
|||
{/* Answer row layer - fades out when help mode active (inverse opacity) */}
|
||||
<div
|
||||
data-element="answer-row"
|
||||
data-fading-out={answerFadingOut ? 'true' : undefined}
|
||||
className={css({
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
|
|
@ -392,9 +400,11 @@ export function VerticalProblem({
|
|||
top: helpOverlay ? 0 : undefined,
|
||||
left: helpOverlay ? 0 : undefined,
|
||||
right: helpOverlay ? 0 : undefined,
|
||||
// Fade out when help mode active (inverse of help overlay)
|
||||
transition: `opacity ${helpOverlayTransitionMs}ms ease-out`,
|
||||
opacity: helpOverlayVisible ? 0 : 1,
|
||||
// Fade out when help mode active (inverse of help overlay) OR when answer is fading out
|
||||
transition: answerFadingOut
|
||||
? 'opacity 300ms ease-out'
|
||||
: `opacity ${helpOverlayTransitionMs}ms ease-out`,
|
||||
opacity: helpOverlayVisible || answerFadingOut ? 0 : 1,
|
||||
pointerEvents: helpOverlayVisible ? 'none' : 'auto',
|
||||
})}
|
||||
>
|
||||
|
|
|
|||
|
|
@ -369,6 +369,8 @@ export interface UseInteractionPhaseReturn {
|
|||
exitHelpMode: () => void
|
||||
/** Clear the current answer (used after help overlay transition completes) */
|
||||
clearAnswer: () => void
|
||||
/** Set the answer to a specific value (used when showing target reached value) */
|
||||
setAnswer: (value: string) => void
|
||||
/** Submit answer (inputting/helpMode → submitting) */
|
||||
startSubmit: () => void
|
||||
/** Handle submit result (submitting → showingFeedback) */
|
||||
|
|
@ -767,6 +769,17 @@ export function useInteractionPhase(
|
|||
})
|
||||
}, [])
|
||||
|
||||
const setAnswer = useCallback((value: string) => {
|
||||
setPhase((prev) => {
|
||||
if (prev.phase !== 'helpMode' && prev.phase !== 'inputting') return prev
|
||||
const updatedAttempt = { ...prev.attempt, userAnswer: value }
|
||||
if (prev.phase === 'helpMode') {
|
||||
return { phase: 'helpMode', attempt: updatedAttempt, helpContext: prev.helpContext }
|
||||
}
|
||||
return { phase: 'inputting', attempt: updatedAttempt }
|
||||
})
|
||||
}, [])
|
||||
|
||||
const startSubmit = useCallback(() => {
|
||||
setPhase((prev) => {
|
||||
// Allow submitting from inputting, awaitingDisambiguation, or helpMode
|
||||
|
|
@ -868,6 +881,7 @@ export function useInteractionPhase(
|
|||
enterHelpMode,
|
||||
exitHelpMode,
|
||||
clearAnswer,
|
||||
setAnswer,
|
||||
startSubmit,
|
||||
completeSubmit,
|
||||
startTransition,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,213 @@
|
|||
import { describe, expect, it } from 'vitest'
|
||||
import { analyzeColumnAddition, analyzeColumnSubtraction } from '../problemGenerator'
|
||||
|
||||
// Helper to simplify calls - the function takes (currentDigit, termDigit, resultDigit, column)
|
||||
// For these unit tests, resultDigit and column are not used in the logic we're testing
|
||||
const testAddition = (currentDigit: number, termDigit: number) => {
|
||||
const resultDigit = (currentDigit + termDigit) % 10
|
||||
return analyzeColumnAddition(currentDigit, termDigit, resultDigit, 0)
|
||||
}
|
||||
|
||||
describe('analyzeColumnAddition', () => {
|
||||
describe('five complement detection', () => {
|
||||
it('detects five complement when heaven bead NOT active and result crosses 5', () => {
|
||||
// 3 + 4 = 7: heaven bead not active (3 < 5), result needs heaven bead
|
||||
// Correct technique: +5, -1 (five complement)
|
||||
const skills = testAddition(3, 4)
|
||||
expect(skills).toContain('fiveComplements.4=5-1')
|
||||
})
|
||||
|
||||
it('detects five complement when adding 3 to 4', () => {
|
||||
// 4 + 3 = 7: heaven bead not active (4 < 5), result needs heaven bead
|
||||
// Correct technique: +5, -2 (five complement)
|
||||
const skills = testAddition(4, 3)
|
||||
expect(skills).toContain('fiveComplements.3=5-2')
|
||||
})
|
||||
|
||||
it('does NOT detect five complement when heaven bead already active', () => {
|
||||
// This is the bug fix: 52 + 37 ones column = 2 + 7 = 9
|
||||
// But when adding term 37 to running sum 52, the ones column sees:
|
||||
// currentDigit = 2 (from 52), termDigit = 7
|
||||
// Result = 9, which is > 5 but heaven bead is NOT active yet
|
||||
// So this SHOULD use five complement
|
||||
|
||||
// The ACTUAL buggy case was: currentDigit >= 5 (heaven bead active)
|
||||
// When adding 1-4 results in 6-9, should NOT use five complement
|
||||
// Example: 7 + 2 = 9
|
||||
// currentDigit = 7 (heaven bead active), termDigit = 2
|
||||
// Just add 2 earth beads directly - no five complement needed
|
||||
const skills = testAddition(7, 2)
|
||||
expect(skills).not.toContain('fiveComplements.2=5-3')
|
||||
expect(skills).toContain('basic.heavenBead')
|
||||
expect(skills).toContain('basic.simpleCombinations')
|
||||
})
|
||||
|
||||
it('does NOT detect five complement when 5 + 3 = 8', () => {
|
||||
// 5 + 3 = 8: heaven bead already active (5 >= 5)
|
||||
// Just add 3 earth beads - no five complement needed
|
||||
const skills = testAddition(5, 3)
|
||||
expect(skills).not.toContain('fiveComplements.3=5-2')
|
||||
expect(skills).toContain('basic.heavenBead')
|
||||
expect(skills).toContain('basic.simpleCombinations')
|
||||
})
|
||||
|
||||
it('does NOT detect five complement when 6 + 3 = 9', () => {
|
||||
// 6 + 3 = 9: heaven bead already active (6 >= 5)
|
||||
// Just add 3 earth beads - no five complement needed
|
||||
const skills = testAddition(6, 3)
|
||||
expect(skills).not.toContain('fiveComplements.3=5-2')
|
||||
expect(skills).toContain('basic.heavenBead')
|
||||
expect(skills).toContain('basic.simpleCombinations')
|
||||
})
|
||||
|
||||
it('does NOT detect five complement when 8 + 1 = 9', () => {
|
||||
// 8 + 1 = 9: heaven bead already active (8 >= 5)
|
||||
// Just add 1 earth bead - no five complement needed
|
||||
const skills = testAddition(8, 1)
|
||||
expect(skills).not.toContain('fiveComplements.1=5-4')
|
||||
expect(skills).toContain('basic.heavenBead')
|
||||
expect(skills).toContain('basic.simpleCombinations')
|
||||
})
|
||||
})
|
||||
|
||||
describe('direct addition (1-4 earth beads)', () => {
|
||||
it('detects direct addition when adding 1-4 and staying under 5', () => {
|
||||
// 1 + 2 = 3: just add earth beads
|
||||
const skills = testAddition(1, 2)
|
||||
expect(skills).toContain('basic.directAddition')
|
||||
})
|
||||
|
||||
it('detects direct addition when adding to 0', () => {
|
||||
// 0 + 4 = 4: just add earth beads
|
||||
const skills = testAddition(0, 4)
|
||||
expect(skills).toContain('basic.directAddition')
|
||||
})
|
||||
})
|
||||
|
||||
describe('heaven bead addition (5)', () => {
|
||||
it('detects heaven bead when adding exactly 5', () => {
|
||||
// 0 + 5 = 5: activate heaven bead
|
||||
const skills = testAddition(0, 5)
|
||||
expect(skills).toContain('basic.heavenBead')
|
||||
})
|
||||
|
||||
it('detects heaven bead + simple combinations for 6-9', () => {
|
||||
// 0 + 7 = 7: activate heaven bead + 2 earth beads
|
||||
const skills = testAddition(0, 7)
|
||||
expect(skills).toContain('basic.heavenBead')
|
||||
expect(skills).toContain('basic.simpleCombinations')
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('analyzeColumnSubtraction', () => {
|
||||
describe('five complement in ten complement subtraction', () => {
|
||||
it('does NOT detect five complement when heaven bead already active during ten complement', () => {
|
||||
// Subtracting when currentDigit >= 5 and adding ten complement crosses 5 boundary
|
||||
// Example: currentDigit = 7, termDigit = 9, needs borrow
|
||||
// Ten complement: -9 = +1 - 10
|
||||
// 7 + 1 = 8 (crosses 5 boundary but heaven bead already active)
|
||||
// Should NOT push five complement for the +1 part
|
||||
const skills = analyzeColumnSubtraction(7, 9, true)
|
||||
expect(skills).toContain('tenComplementsSub.-9=+1-10')
|
||||
expect(skills).not.toContain('fiveComplements.1=5-4')
|
||||
})
|
||||
|
||||
it('does NOT detect five complement when 6 + 3 during ten complement', () => {
|
||||
// currentDigit = 6, termDigit = 7, needs borrow
|
||||
// Ten complement: -7 = +3 - 10
|
||||
// 6 + 3 = 9 (crosses 5 boundary but heaven bead already active at 6)
|
||||
const skills = analyzeColumnSubtraction(6, 7, true)
|
||||
expect(skills).toContain('tenComplementsSub.-7=+3-10')
|
||||
expect(skills).not.toContain('fiveComplements.3=5-2')
|
||||
})
|
||||
|
||||
it('DOES detect five complement when heaven bead NOT active during ten complement', () => {
|
||||
// currentDigit = 3, termDigit = 7, needs borrow
|
||||
// Ten complement: -7 = +3 - 10
|
||||
// 3 + 3 = 6 (crosses 5 boundary and heaven bead NOT active)
|
||||
// SHOULD push five complement for the +3 part
|
||||
const skills = analyzeColumnSubtraction(3, 7, true)
|
||||
expect(skills).toContain('tenComplementsSub.-7=+3-10')
|
||||
expect(skills).toContain('fiveComplements.3=5-2')
|
||||
})
|
||||
|
||||
it('DOES detect five complement when 4 + 2 during ten complement', () => {
|
||||
// currentDigit = 4, termDigit = 8, needs borrow
|
||||
// Ten complement: -8 = +2 - 10
|
||||
// 4 + 2 = 6 (crosses 5 boundary and heaven bead NOT active at 4)
|
||||
const skills = analyzeColumnSubtraction(4, 8, true)
|
||||
expect(skills).toContain('tenComplementsSub.-8=+2-10')
|
||||
expect(skills).toContain('fiveComplements.2=5-3')
|
||||
})
|
||||
})
|
||||
|
||||
describe('direct subtraction', () => {
|
||||
it('detects direct subtraction when enough earth beads available', () => {
|
||||
// 7 - 2 = 5: have 2 earth beads (7 % 5 = 2), can subtract 2 directly
|
||||
const skills = analyzeColumnSubtraction(7, 2, false)
|
||||
expect(skills).toContain('basic.directSubtraction')
|
||||
})
|
||||
|
||||
it('detects five complement subtraction when not enough earth beads', () => {
|
||||
// 6 - 3 = 3: have 1 earth bead (6 % 5 = 1), need 3
|
||||
// Use five complement: -3 = -5 + 2
|
||||
const skills = analyzeColumnSubtraction(6, 3, false)
|
||||
expect(skills).toContain('fiveComplementsSub.-3=-5+2')
|
||||
expect(skills).toContain('basic.heavenBeadSubtraction')
|
||||
})
|
||||
})
|
||||
|
||||
describe('heaven bead subtraction', () => {
|
||||
it('detects heaven bead subtraction when subtracting exactly 5', () => {
|
||||
// 7 - 5 = 2: just remove heaven bead
|
||||
const skills = analyzeColumnSubtraction(7, 5, false)
|
||||
expect(skills).toContain('basic.heavenBeadSubtraction')
|
||||
})
|
||||
|
||||
it('detects combination subtraction for 6-9', () => {
|
||||
// 9 - 7 = 2: remove heaven bead and 2 earth beads
|
||||
const skills = analyzeColumnSubtraction(9, 7, false)
|
||||
expect(skills).toContain('basic.heavenBeadSubtraction')
|
||||
expect(skills).toContain('basic.simpleCombinationsSub')
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('real-world problem: 52 + 37 = 89', () => {
|
||||
it('ones column (2 + 7 = 9) should use heaven bead pattern, NOT five complement', () => {
|
||||
// This is the exact bug scenario from the user report
|
||||
// Running sum = 52, adding term = 37
|
||||
// Ones column: currentDigit = 2, termDigit = 7
|
||||
// 2 + 7 = 9, no carry needed
|
||||
// Result is 9, heaven bead NOT active initially (2 < 5)
|
||||
// Need to activate heaven bead and add 4 earth beads
|
||||
|
||||
// The bug was in detecting fiveComplements.3=5-2 incorrectly
|
||||
// Let's verify the correct behavior:
|
||||
const skills = testAddition(2, 7)
|
||||
|
||||
// Result 9 requires heaven bead + 4 earth beads
|
||||
// Adding 7 is in the 6-9 range, so it uses heaven bead + earth beads pattern
|
||||
expect(skills).toContain('basic.heavenBead')
|
||||
expect(skills).toContain('basic.simpleCombinations')
|
||||
|
||||
// Should NOT incorrectly detect five complement
|
||||
// Adding 7 doesn't use five complement - it's direct heaven bead + earth beads
|
||||
expect(skills).not.toContain('fiveComplements.3=5-2')
|
||||
})
|
||||
|
||||
it('tens column (5 + 3 = 8) should NOT use five complement since heaven bead active', () => {
|
||||
// Running sum = 52, adding term = 37
|
||||
// Tens column: currentDigit = 5, termDigit = 3
|
||||
// 5 + 3 = 8, heaven bead already active (5 >= 5)
|
||||
// Just add 3 earth beads - no five complement needed
|
||||
const skills = testAddition(5, 3)
|
||||
|
||||
expect(skills).toContain('basic.heavenBead')
|
||||
expect(skills).toContain('basic.simpleCombinations')
|
||||
|
||||
// Should NOT detect five complement since heaven bead is already active
|
||||
expect(skills).not.toContain('fiveComplements.3=5-2')
|
||||
})
|
||||
})
|
||||
|
|
@ -199,7 +199,7 @@ export function analyzeStepSkills(currentValue: number, term: number, newValue:
|
|||
/**
|
||||
* Analyzes skills needed for addition in a single column
|
||||
*/
|
||||
function analyzeColumnAddition(
|
||||
export function analyzeColumnAddition(
|
||||
currentDigit: number,
|
||||
termDigit: number,
|
||||
_resultDigit: number,
|
||||
|
|
@ -221,10 +221,17 @@ function analyzeColumnAddition(
|
|||
skills.push('basic.heavenBead')
|
||||
}
|
||||
} else if (currentDigit + termDigit > 5 && currentDigit + termDigit <= 9) {
|
||||
// Results in 6-9: use five complement + simple combination
|
||||
skills.push(`fiveComplements.${termDigit}=5-${5 - termDigit}`)
|
||||
skills.push('basic.heavenBead')
|
||||
skills.push('basic.simpleCombinations')
|
||||
// Results in 6-9
|
||||
// If heaven bead already active (currentDigit >= 5), just add earth beads directly
|
||||
if (currentDigit >= 5) {
|
||||
skills.push('basic.heavenBead')
|
||||
skills.push('basic.simpleCombinations')
|
||||
} else {
|
||||
// Heaven bead NOT active - need five complement to bring it down
|
||||
skills.push(`fiveComplements.${termDigit}=5-${5 - termDigit}`)
|
||||
skills.push('basic.heavenBead')
|
||||
skills.push('basic.simpleCombinations')
|
||||
}
|
||||
} else if (currentDigit + termDigit >= 10) {
|
||||
// Ten complement needed
|
||||
const complement = 10 - termDigit
|
||||
|
|
@ -323,18 +330,18 @@ export function analyzeColumnSubtraction(
|
|||
|
||||
if (tenComplement >= 1 && tenComplement <= 4) {
|
||||
// Adding 1-4 to currentDigit
|
||||
if (currentDigit + tenComplement <= 4) {
|
||||
// Direct addition of complement
|
||||
skills.push(`tenComplementsSub.-${termDigit}=+${tenComplement}-10`)
|
||||
} else if (currentDigit + tenComplement >= 5 && afterAddition <= 9) {
|
||||
// Adding complement crosses 5 boundary - need five complement for the addition part
|
||||
// Combined technique: use five complement to add the ten complement
|
||||
skills.push(`tenComplementsSub.-${termDigit}=+${tenComplement}-10`)
|
||||
skills.push(`fiveComplements.${tenComplement}=5-${5 - tenComplement}`)
|
||||
} else {
|
||||
// Simple ten complement
|
||||
skills.push(`tenComplementsSub.-${termDigit}=+${tenComplement}-10`)
|
||||
skills.push(`tenComplementsSub.-${termDigit}=+${tenComplement}-10`)
|
||||
|
||||
if (currentDigit + tenComplement >= 5 && afterAddition <= 9) {
|
||||
// Adding complement crosses 5 boundary
|
||||
if (currentDigit < 5) {
|
||||
// Heaven bead NOT active - need five complement for the addition part
|
||||
// Combined technique: use five complement to add the ten complement
|
||||
skills.push(`fiveComplements.${tenComplement}=5-${5 - tenComplement}`)
|
||||
}
|
||||
// If currentDigit >= 5, heaven bead already active - just add earth beads directly
|
||||
}
|
||||
// If result <= 4, just direct addition of earth beads
|
||||
} else if (tenComplement === 5) {
|
||||
// -5 = +5-10
|
||||
skills.push(`tenComplementsSub.-5=+5-10`)
|
||||
|
|
|
|||
Loading…
Reference in New Issue