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 | 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 1x 5x 5x 5x 5x 5x 5x 5x 8x 8x 8x 8x 8x 8x 8x 8x 8x 8x 8x 5x 5x 5x 5x 1x 1x 1x 1x 1x 1x 1x 8x 8x 8x 8x 8x 8x 8x 8x 8x 8x 7x 7x 7x 7x 7x 3x 3x 7x 1x 1x 8x 8x 8x 8x 8x 8x 8x 1x 1x 8x 8x 8x 8x 8x 23x 23x 7x 7x 23x 23x 23x 8x 8x 8x | // Re-export core bead diff functionality from abacus-react
// App-specific extensions for multi-step tutorials and validation
export {
type BeadDiffResult,
type BeadDiffOutput,
calculateBeadDiff,
calculateBeadDiffFromValues,
areStatesEqual,
type AbacusState,
type BeadState,
} from '@soroban/abacus-react'
import type { BeadDiffOutput, BeadDiffResult, AbacusState } from '@soroban/abacus-react'
import { calculateBeadDiffFromValues } from '@soroban/abacus-react'
// Local type for use in filter callbacks when BeadDiffResult can't resolve from package
type BeadChange = {
placeValue: number
beadType: 'heaven' | 'earth'
position?: number
direction: 'activate' | 'deactivate'
order: number
}
/** A single step in a multi-step bead diff sequence */
type StepDiff = {
stepIndex: number
instruction: string
diff: BeadDiffOutput
fromValue: number
toValue: number
}
/**
* Calculate step-by-step bead diffs for multi-step operations
* This is used for tutorial multi-step instructions where we want to show
* the progression through intermediate states
*
* APP-SPECIFIC FUNCTION - not in core abacus-react
*/
export function calculateMultiStepBeadDiffs(
startValue: number,
steps: Array<{ expectedValue: number; instruction: string }>
): StepDiff[] {
const stepDiffs: StepDiff[] = []
let currentValue = startValue
steps.forEach((step, index) => {
const diff = calculateBeadDiffFromValues(currentValue, step.expectedValue)
stepDiffs.push({
stepIndex: index,
instruction: step.instruction,
diff,
fromValue: currentValue,
toValue: step.expectedValue,
})
currentValue = step.expectedValue
})
return stepDiffs
}
/**
* Validate that a bead diff is feasible (no impossible bead states)
*
* APP-SPECIFIC FUNCTION - not in core abacus-react
*/
export function validateBeadDiff(diff: BeadDiffOutput): {
isValid: boolean
errors: string[]
} {
const errors: string[] = []
// Check for impossible earth bead counts
const earthChanges = diff.changes.filter((c: BeadChange) => c.beadType === 'earth')
const earthByPlace = groupByPlace(earthChanges)
Object.entries(earthByPlace).forEach(([place, changes]) => {
const activations = changes.filter((c) => c.direction === 'activate').length
const deactivations = changes.filter((c) => c.direction === 'deactivate').length
const netChange = activations - deactivations
if (netChange > 4) {
errors.push(`Place ${place}: Cannot have more than 4 earth beads`)
}
if (netChange < 0) {
errors.push(`Place ${place}: Cannot have negative earth beads`)
}
})
return {
isValid: errors.length === 0,
errors,
}
}
// Helper function for validation
function groupByPlace(changes: BeadDiffResult[]): {
[place: string]: BeadDiffResult[]
} {
return changes.reduce(
(groups, change) => {
const place = change.placeValue.toString()
if (!groups[place]) {
groups[place] = []
}
groups[place].push(change)
return groups
},
{} as { [place: string]: BeadDiffResult[] }
)
}
|