Files
on_the_level/README.md
T
thejayman77 99c2b12192 Address Codex measurement-core review
- Calibration: still derived in angle space via the 180-degree flip, but now
  APPLIED in vector space as a reference-orientation rotation (Rodrigues
  alignment for Surface, Z-rotation for Edge), exact away from zero; tests
  at 30 degrees, cross-axis, and edge-polarity cases.
- Angle relative zero: stores the gravity direction vector; relative reading
  is the angle between directions, so cross-axis movement is honest.
- Edge mode: precise geometry documented (either long edge down, gravity
  along +/-X), placement-validity guard so e.g. Edge mode never locks on a
  phone lying flat; UI shows repositioning hints.
- Lock/readout coherence: locked label states the tolerance (exit threshold)
  so the rounded readout can never contradict it; pipeline acceptance tests
  pin the invariant.
- Sensor-vector contract: documented and pinned by SensorContractTest. The
  suggested negation of gravity/accelerometer fallbacks is NOT applied: per
  Android SensorEvent docs, a stationary flat device reads +9.81 on Z (the
  gravity reaction), matching the rotation-vector path as-is. The contract
  tests prove all paths agree.

38 tests passing.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-11 19:45:53 -04:00

49 lines
2.3 KiB
Markdown

# On the Level
Offline-first Android pocket toolset: a trustworthy level, angle meter, and
calibrated screen ruler (Pro). Kotlin + Jetpack Compose, single module, no backend.
- **[BRIEF.md](BRIEF.md)** — the authoritative v1 product & technical brief
- **[AUDIT.md](AUDIT.md)** — audit of the brief; the amendments it lists are incorporated
- **resources/** — concept board (visual direction)
## Building
Open in Android Studio, or:
```sh
./gradlew assembleDebug # build
./gradlew testDebugUnitTest # measurement-math unit tests
```
## Scaffold status
The project skeleton follows BRIEF.md §Sensor and measurement architecture.
Implemented and tested:
- `core/sensors` — sensor selection (game rotation vector → gravity → low-passed
accelerometer), device-frame gravity stream, and the pure measurement math:
orientation mapping, two-sample per-mode calibration (derived in angle space,
**applied in vector space** so it stays correct away from zero), EMA smoothing,
lock hysteresis/dwell/debounce, display deadband, placement validity, and the
sensor-vector contract (all sources emit device-frame world-up; flat = +9.81 on Z,
pinned by `SensorContractTest`). All unit-tested.
- `core/settings` — DataStore preferences and per-mode calibration persistence.
- `core/billing` — entitlement interface with a stub (free-tier) implementation.
- `feature/level`, `feature/angle` — live numeric scaffolds wired to the real
sensor pipeline, with manual Surface|Edge selection, placement-validity hints,
lock state (locked label states the tolerance so it can never contradict the
rounded readout), and directional hold-to-zero (vector reference, not magnitude
subtraction).
- `feature/ruler`, `feature/tools` — static placeholders.
Not yet implemented (deliberately — see TODO markers):
- The tactile vial visuals and the spring-animated **display value** (value 3 of 3
in the brief); scaffold screens render the deadbanded stable value directly.
- Guided calibration flow UI (math and persistence are done).
- Edge-mode readout counter-rotation on the portrait-locked activity.
- Play Billing implementation of `ProEntitlementRepository`.
- Screen ruler measurement UI and per-display scale persistence.
- Audio cue, reduced-motion behaviors, preferences UI.