replica(rechner): architecture and schema
Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
@@ -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.
|
||||
@@ -0,0 +1,9 @@
|
||||
-- Local SQLite (Room). No network, no accounts.
|
||||
CREATE TABLE history (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
expression TEXT NOT NULL CHECK (length(expression) > 0),
|
||||
result TEXT NOT NULL,
|
||||
created_at INTEGER NOT NULL -- epoch ms UTC; grouped by local day in the UI
|
||||
);
|
||||
CREATE INDEX history_created ON history(created_at);
|
||||
-- Memory value, angle unit, theme and the current (unfinished) expression live in DataStore.
|
||||
Reference in New Issue
Block a user