Skip to content

migrate trainer + comparison + configurator

jedmund requested to merge jedmund/interval-trainer into main

Created by: jedmund

Re-lands the stuck work from PR #27 (closed without merging) and PR #28 (merged into the wrong base). Contents are unchanged from what was previously reviewed and approved; this PR exists so main actually receives it.

What's in here

Interval Trainer migration

  • Rebuilds Interval Trainer on the shared exercise architecture (`ExerciseState` + `ScoringOverlay` + `PickerWidget`), matching Interval Classifier's visual language.
  • Procedural prompt generation stays local to the exercise; streak-based interval unlocks preserved silently (no toast).
  • `IntervalTrainerConfig` gains a `context` field that was already in lesson JSON but silently dropped.

Interval Comparison migration

  • Same architecture with dual listen (Play A / Play B) and a per-prompt dynamic title ("Which is the Major 3rd?").
  • `IntervalComparisonConfig` gains optional `progressiveIntervals` and `progressionThreshold` for progressive-difficulty playground mode.

Configurator panel for Interval Comparison

  • Side panel with a vertical interval checklist, "None" button, progressive-difficulty toggle, total-questions stepper (6–20, step 2).
  • Card is a fixed 320pt frame with the title pinned top, centered feedback, Next button anchored at the bottom.
  • Nearest-foil pairing + last-target dedup so progressive mode trains fine discrimination and never repeats targets back-to-back.

Shared bits

  • `PickerWidget` grid columns are adaptive (2 for ≤4 choices, 3 for 5–9, 4 for 10+).
  • `ExerciseState.recordResult` split from `advance` so the final prompt's feedback isn't skipped.
  • `ProgressDotsView` wraps to two rows at 16+ prompts.
  • New app icon + build number bumped to 3.

Why this PR exists

Previous attempts used stacked PRs that ended up with the wrong base branch, so none of this reached main even though it was reviewed. This PR just carries the same commits straight to main.

Test plan

  • Interval Classifier still works end-to-end (unchanged here but regression-check it).
  • Interval Trainer standalone and lesson contexts; procedural prompts, progress persistence via `scoredExerciseState`.
  • Interval Comparison standalone: side panel toggles live; defaults are all intervals selected, progressive off, 8 questions; card is 320pt tall.
  • Interval Comparison lessons (3-ex3, 4-ex3, 5-ex3) still use their curated pairs.
  • App icon passes App Store Connect upload.

Merge request reports

Loading