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 | 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 9x 9x 9x 9x 9x 9x 9x 9x 9x 9x 9x 9x 9x 9x 9x 9x 9x 9x 9x 9x 9x 9x 9x 9x 9x 9x 9x 9x 9x 9x 9x 9x 9x 9x 9x 9x 9x 9x 9x 9x 9x 9x 9x 9x 9x 9x 9x 9x 9x 9x 9x 9x 9x 9x 9x 9x 9x 9x 9x 9x 9x 9x 9x 9x 9x 9x 9x 9x 9x 9x 9x 9x 9x 9x 9x 9x 9x 9x 9x 9x 9x 9x 9x 9x 9x 9x 9x | // Borrow boxes row rendering for subtraction problems
// This row shows where borrows occur (FROM higher place TO lower place)
import type { CellDimensions } from '../shared/types'
import { TYPST_CONSTANTS } from '../shared/types'
/**
* Generate Typst code for the borrow boxes row
*
* Borrow boxes indicate where a borrow operation occurs:
* - Source: The place value we're borrowing FROM (giving)
* - Destination: The place value we're borrowing TO (receiving)
*
* Design decision: Borrow boxes NEVER use place value colors (always stroke-only)
* to avoid arrow layering issues where arrows get covered by adjacent cell backgrounds.
*
* @param cellDimensions - Cell sizing information
* @returns Typst code for borrow boxes row
*/
export function generateBorrowBoxesRow(cellDimensions: CellDimensions): string {
const { cellSize, cellSizeIn, cellSizePt } = cellDimensions
const hintTextSize = (cellSizePt * TYPST_CONSTANTS.HINT_TEXT_SIZE_FACTOR).toFixed(1)
const arrowheadSize = (cellSizePt * TYPST_CONSTANTS.ARROWHEAD_SIZE_FACTOR).toFixed(1)
const arrowStartDx = (cellSize * TYPST_CONSTANTS.ARROW_START_DX).toFixed(2)
const arrowStartDy = (cellSize * TYPST_CONSTANTS.ARROW_START_DY).toFixed(2)
const arrowEndX = (cellSize * 0.24).toFixed(2)
const arrowEndY = (cellSize * 0.7).toFixed(2)
const arrowControlX = (cellSize * 0.11).toFixed(2)
const arrowControlY = (cellSize * -0.5).toFixed(2)
const arrowheadDx = (cellSize * TYPST_CONSTANTS.ARROWHEAD_DX).toFixed(2)
const arrowheadDy = (cellSize * TYPST_CONSTANTS.ARROWHEAD_DY).toFixed(2)
return String.raw`
// Borrow boxes row (shows borrows FROM higher place TO lower place)
[], // Empty cell for operator column
..for i in range(0, grid-digits).rev() {
// Show borrow box if enabled (display rules already handle "whenRegrouping" logic in TypeScript)
// Note: Borrowing occurs FROM position i TO position i-1 (when m-digits.at(i-1) < s-digits.at(i-1))
let shows-borrow = show-borrows and i > 0
let column-needs-borrow = i > 0 and (m-digits.at(i - 1) < s-digits.at(i - 1))
if shows-borrow {
// This place borrowed FROM to give to lower place
let source-color = place-colors.at(i) // This place (giving)
let dest-color = place-colors.at(i - 1) // Lower place (receiving)
// When showing hints, determine what to display based on cascading
// Only show hints where borrowing actually occurs (even if boxes show everywhere)
if show-borrowing-hints and column-needs-borrow and i <= m-highest {
// Determine the actual value to show in the hint
// For cascading: if this digit is 0, it received 10 from left and gives 1 to right
// So it shows "10 - 1". Otherwise it shows "original - 1"
let original-digit = m-digits.at(i)
// Check if this is part of a cascade (is it 0 and needs to borrow?)
let is-cascade = original-digit == 0
// The display value is either the original digit or 10 (if cascading)
let display-value = if is-cascade { 10 } else { original-digit }
// Borrow boxes never use place value colors (always stroke-only)
// to avoid arrow layering issues
(box(width: ${cellSizeIn}, height: ${cellSizeIn}, stroke: ${TYPST_CONSTANTS.CELL_STROKE_WIDTH}pt)[
#place(
top + center,
dy: 2pt,
text(size: ${hintTextSize}pt, fill: gray.darken(30%), weight: "bold")[
#display-value#h(0.1em)−#h(0.1em)1
]
)
// Draw curved line using Typst bezier with control point
// Note: path() is deprecated but curve() has different API - needs investigation
#place(
top + left,
dx: ${arrowStartDx}in,
dy: ${arrowStartDy}in,
path(
stroke: (paint: gray.darken(30%), thickness: ${TYPST_CONSTANTS.ARROW_STROKE_WIDTH}pt),
// Start vertex (near the "1" in borrow box)
(0pt, 0pt),
// End vertex adjusted up and left to align with arrowhead (vertex, relative-control-point)
((${arrowEndX}in, ${arrowEndY}in), (${arrowControlX}in, ${arrowControlY}in)),
)
)
// Arrowhead pointing down at the top edge of borrowed 10s box
#place(
top + left,
dx: ${arrowheadDx}in,
dy: ${arrowheadDy}in,
text(size: ${arrowheadSize}pt, fill: gray.darken(30%))[▼]
)
],)
} else {
// No hints - just show stroke box
(box(width: ${cellSizeIn}, height: ${cellSizeIn}, stroke: ${TYPST_CONSTANTS.CELL_STROKE_WIDTH}pt)[],)
}
} else {
// No borrow from this position
(box(width: ${cellSizeIn}, height: ${cellSizeIn})[
#v(${cellSizeIn})
],)
}
},
`
}
|