Skip to content

Phase 2 — calibration: card calibration, accuracy screen, accuracy tooling - #4

Merged
hupcus merged 6 commits into
mainfrom
phase-2-calibration
Sep 24, 2026
Merged

hupcus merged 6 commits into
mainfrom
phase-2-calibration

Conversation

@hupcus

@hupcus hupcus commented Sep 24, 2026 •

Copy link
Copy Markdown
Owner

Phase 2 per PLAN.md — the most accurate px → mm scale available, with its method and confidence stored.

What is in it

  • CalibrationRepository (DataStore Preferences): card calibration + calibrationVersion (counts the user's changes). Implausible or incomplete values read as "no card" (ADR-024).
  • PhysicalScaleProvider.resolve: card (HIGH) over xdpi/ydpi (MEDIUM) — the card only on the phone and panel resolution it was made on.
  • Service: loads the stored calibration before converting the first sample, follows changes live; every MeasurementResult carries its calibration version, nothing is recomputed (spec §65).
  • Screens Kalibrace displeje (vertical bar drawn in raw px, slider + 1 px steps — ADR-023) and Přesnost měření (spec §33), reachable from home.
  • Debug test list: MAE / MAPE over a series of runs on screen; TESTLIST line and debug CSV header carry the calibration in force.
  • tools/accuracy.py (ground truth CSV vs measured CSV → MAE, MAPE); device_accuracy.py --csv-out.
  • ADR-023, ADR-024; measurement-model.md, architecture.md, accuracy-testing.md, README updated.

Definition of Done (PLAN Phase 2)

  • Manual calibration saved and used — on the test phone the engine converted 544 px → 34.265 mm = 85.60 / 1359 px, cv=1
  • Automatic fallback — no card → xdpi/ydpi; card from another resolution → xdpi/ydpi (unit test); "Přeskočit – použít automatický odhad" switched the running service live (cv=2, 25.4 / ydpi, no reconnect)
  • Accuracy screen (Přesnost měření) — checked on the phone
  • ⏸ Card calibration by Honza on the test phone → mm/px near 0.0630 — deferred to the verification debt (handoff.md V2), Honza's decision 2026-09-24
  • ⏸ MAPE on the own test list < 5 % with the card calibration — deferred (V3); the pixel pipeline measured 0.00 % with a synthetic calibration

Reviews

  • /topshit 7/10 over the cumulative diff — 3 findings fixed and verified on the phone
  • Stage 2 security read: manifests and accessibility config unchanged, DataStore app-private, release APK without debug classes, only the signature-level permission

Tests

  • Unit: card math (85.60 mm / known px), xdpi/ydpi, method + confidence selection, recalibration keeps old results (§65), DataStore round trip / version / implausible values, MAE/MAPE — 91 JVM tests green
  • Python tools: 19 tests green
  • On device (OnePlus CPH2399): the drawn bar measured from a screenshot = exactly the shown px (1356, 1359); landscape disables Save; back/save navigation; double tap saves once

🤖 Generated with Claude Code

hupcus and others added 4 commits September 24, 2026 06:44
…engine

- CalibrationRepository (DataStore Preferences) stores the card calibration and a
  calibrationVersion that counts every user change; implausible or incomplete values
  read as no calibration (ADR-024).
- PhysicalScaleProvider.resolve: the card over xdpi/ydpi, only on the phone and panel
  resolution it was made on; the scale carries the version.
- The service loads the stored calibration before converting the first sample and follows
  changes live; every MeasurementResult carries its calibrationVersion (spec §65).
- New screens Kalibrace displeje (vertical bar in raw px, slider + 1 px steps, ADR-023)
  and Přesnost měření (spec §33), reachable from home.
- Debug test list: runs form a series with MAE / MAPE on screen; TESTLIST line and debug
  CSV header carry the calibration in force.
- tools/accuracy.py: ground truth CSV vs measured CSV -> MAE, MAPE;
  device_accuracy.py --csv-out writes that pair.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…en's limit

Measured on the OnePlus CPH2399: the bar area allowed only 1219 px while the card
needs ~1356 px. Title and instructions now sit beside the bar (the card covers them
once placed) and the controls are compact — the area now allows ~1600 px.

In landscape the bar could only reach ~400 px and a nonsense calibration (+222 %)
could be saved. A bar pinned at the screen's limit cannot have matched a longer
card: Save is disabled and the hint says to hold the phone upright.

Debug logcat lines carry the calibration version (cv=) the distance used.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
- Back from Kalibrace displeje returns to where it was opened (home or Přesnost);
  only a save or "use the automatic estimate" lands on Přesnost.
- Save / skip act once: a double tap bumped the calibration version twice
  (verified on the test phone: v2 -> v3 after a double tap).
- The instruction text scrolls when the bar area is short (landscape).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 933d342a2c

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +75 to +77
scope.launch {
change()
onSaved()

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Recover from calibration write failures

If DataStore.edit fails—for example because storage is full or an I/O error occurs—change() throws from this launch, so onSaved() is never called and committing remains true; the uncaught coroutine exception may also terminate the app. This affects both saving a card and selecting the automatic estimate. Catch the failure, re-enable the controls, and report it so the user can retry.

Useful? React with 👍 / 👎.

hupcus and others added 2 commits September 24, 2026 07:09
…one, what remains

The continue prompt now resumes an in-progress phase on its existing branch
instead of starting a new one from main.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…app"

Honza (2026-09-24): keep developing, decide autonomously, finish the whole app.
Manual on-phone checks move to "Dluh ověření" in handoff.md (V1 Instagram/TikTok,
V2 card calibration, V3 MAPE with the card); the continue prompt merges each phase
after its gates and uses an emulator instead of Honza's phone.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@hupcus
hupcus merged commit 47d624b into main Sep 24, 2026
1 check passed
@hupcus
hupcus deleted the phase-2-calibration branch September 24, 2026 05:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant