soroban-abacus-flashcards/DESIGN.md

190 lines
4.8 KiB
Markdown

# Design Notes
## Soroban Representation
### Number Encoding
The soroban uses a bi-quinary system where each column represents a decimal digit:
- **Heaven bead**: 1 bead worth 5 when active
- **Earth beads**: 4 beads worth 1 each when active
For any digit 0-9:
- Heaven bead is active if digit ≥ 5
- Number of active earth beads = digit mod 5
### Visual Conventions
1. **Active beads**: Solid black, positioned against the reckoning bar
- Heaven beads move down when active
- Earth beads move up when active
2. **Inactive beads**: Light gray, positioned away from the bar
- Heaven beads rest at top when inactive
- Earth beads rest at bottom when inactive
3. **Column ordering**: Right-to-left place values (ones, tens, hundreds)
- Matches traditional soroban layout
- Rightmost column is always ones place
### Rendering Algorithm
```python
for each digit in number:
heaven_active = 1 if digit >= 5 else 0
earth_active = digit % 5
draw_rod()
draw_heaven_bead(active=heaven_active)
for i in range(4):
draw_earth_bead(active=(i < earth_active))
draw_reckoning_bar()
```
## Duplex Printing Alignment
### Challenge
Double-sided printing must align front and back cards precisely when using long-edge binding (standard for portrait orientation).
### Solution
1. **Page mirroring**: Back side cards are arranged in reverse column order
2. **Grid consistency**: Same grid dimensions on both sides
3. **Registration marks**: Optional alignment dots in trim area
4. **Safe margins**: 5mm default buffer inside each card
### Implementation
```typst
// Front side: normal left-to-right layout
grid(columns: 2, rows: 3,
card1, card2,
card3, card4,
card5, card6)
// Back side: columns reversed for long-edge flip
grid(columns: 2, rows: 3,
card2_back, card1_back, // Note reversed
card4_back, card3_back,
card6_back, card5_back)
```
## Vector Graphics Strategy
### Why Typst?
1. **Native vector support**: Built-in drawing primitives
2. **Font embedding**: Automatic TTF/OTF embedding
3. **Lightweight**: ~30MB install vs. 3GB+ for TeX
4. **Deterministic**: Same input → same output
### Drawing Primitives Used
- `circle()`: Beads (with fill and stroke)
- `rect()`: Rods and reckoning bar
- `place()`: Absolute positioning within card
- `box()`: Layout containers with margins
### No Rasterization
All elements remain vectors through the entire pipeline:
- Typst → PDF (vector primitives)
- qpdf linearization (preserves vectors)
- No image assets or bitmaps
## Configuration System
### Hierarchy
1. **Built-in defaults**: Hardcoded in Python
2. **Config file**: YAML/JSON overrides
3. **CLI arguments**: Highest priority
### Merge strategy
```python
final_config = defaults
final_config.update(file_config)
final_config.update(cli_args)
```
## Build Determinism
### Sources of Non-determinism
1. **Random shuffling**: Controlled via `--seed`
2. **File timestamps**: Not embedded in PDF
3. **Font subsetting**: Consistent with bundled fonts
### Ensuring Reproducibility
- Fixed random seed produces identical shuffle
- Bundled fonts prevent system font variations
- Typst's deterministic rendering
- No external network calls or timestamps
## Performance Considerations
### Optimizations
1. **Single-pass rendering**: Generate all cards in one Typst run
2. **Batched operations**: Group all cards per page
3. **Minimal dependencies**: No heavy frameworks
4. **Direct PDF generation**: No intermediate formats
### Scalability
Tested ranges:
- 0-9: ~0.5 seconds
- 0-99: ~1 second
- 0-999: ~3 seconds
- 0-9999: ~15 seconds
Memory usage remains constant regardless of range size.
## Font Selection
### DejaVu Sans Choice
1. **Open source**: Free license, redistributable
2. **Complete coverage**: Full ASCII + extended Latin
3. **Clear numerals**: Distinct digit shapes
4. **Cross-platform**: Renders identically everywhere
### Embedding Strategy
- Fonts copied to `fonts/` directory
- Typst uses `--font-path` flag
- Full embedding (not subsetting) for consistency
## Future Enhancements
Potential improvements while maintaining core simplicity:
1. **Additional layouts**: 12-up, 16-up for smaller cards
2. **Color coding**: Optional colored beads by place value
3. **Mixed practice**: Combine different number ranges
4. **Answer variations**: Show decomposition (e.g., "20 + 3")
5. **Export formats**: SVG individual cards, PNG previews
## Testing Methodology
### Validation Steps
1. **PDF integrity**: `qpdf --check` validates structure
2. **Vector verification**: No embedded images
3. **Font embedding**: All fonts included
4. **Print testing**: Physical duplex print alignment
5. **Cross-platform**: Tested on multiple macOS versions
### Edge Cases Handled
- Empty number list → Error message
- Invalid range → Clear error
- Missing dependencies → Helpful install instructions
- Printer margin variations → Configurable margins