replica(rechner): architecture and schema

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
2026-10-17 15:51:27 +02:00
co-authored by Claude Opus 5.5
parent f25e10d217
commit 021f7106cc
2 changed files with 52 additions and 0 deletions
+43
View File
@@ -0,0 +1,43 @@
# Architecture: Rechner (Android, ohne Google)
Same conventions as `wetter/` and `uhr/`: one native app, no server, **no network permission**.
## Stack
| Schicht | Wahl | warum |
| --- | --- | --- |
| UI | Kotlin + Compose, Material 3 Expressive, dynamic colour | same look and pipeline as the other apps |
| Rechenkern | own recursive-descent parser → AST → evaluator on `BigDecimal` (MathContext 50 digits), integers stay exact `BigInteger` | no floating-point surprises (0.1+0.2 = 0.3), 100! exact; pure Kotlin, unit-tested on the JVM |
| Funktionen | sin/cos/tan/ln/log/eˣ/√/^ via `Math` on doubles only where unavoidable, results rounded to 15 significant digits, exact values snapped (sin 30° = 0.5, cos π = −1) | readable answers without fake precision |
| Persistenz | Room (history) + DataStore (memory, angle unit, current expression) | – |
| Build/Verteilung | minSdk 29, `scripts/release.sh rechner` (Obtainium) | – |
## Schema
`schema.sql`: 1 table `history`. Single user, app-private storage.
## Interne API
| Aufruf | macht | Flow |
| --- | --- | --- |
| `Engine.evaluate(expr, angle)` | parse + evaluate, tolerant of unfinished input (auto-closes parentheses, ignores a trailing operator) | F01, F02 |
| `Editor.input(key)` | cursor-aware editing: digits, operators (replace a trailing operator), smart parentheses, %, functions insert `sin(`, backspace removes whole tokens | F01, F02 |
| `Calc.equals()` | evaluate, store history row, result becomes the expression | F01 |
| `History.observe()/clear()` | grouped by local day | F03 |
| `Memory.store(value)/recall()` | DataStore | F05 |
| `Clipboard.copy/paste` | system clipboard; paste is sanitised to calculator tokens | F04 |
## Was beißt
- **Precision:** division keeps 50 digits internally; display rounds to fit and strips trailing zeros; repeating decimals shown truncated with an ellipsis rather than rounded up wrongly.
- **Percent:** `50+10%` = 55 (percent of the left operand for + and −), `50×10%` = 5; standalone `10%` = 0.1.
- **Locale:** German uses comma decimal and dot grouping; the parser accepts the locale separator only.
- **Big results:** 100! has 158 digits; display shows them scientifically (1,5E157) and the full value on scroll.
- **Domain errors:** √(−1), ln 0, tan 90°, 0÷0, factorial of non-integers → error text, never a crash.
## Build-Reihenfolge
1. Vertical slice (S01): engine + keypad + live result + equals; engine unit tests.
2. Must: scientific row and panel (S02), Deg/Rad, Inv, errors, auto-shrinking display, history (S03), copy/paste (S04), expressive keys, dynamic colour.
3. Should: memory, implicit multiplication, pull-down history, haptics, big numbers, locale separators, clear history.
4. Could: landscape layout with all functions.