feat(train): each km announced on foot, each 5 km by bike (ADR 0030, D49)

Step 11 takes up what OpenTracks does that Train didn't (D49). 11a: a
recording announces each kilometre on foot and each 5 km by bike, never
on a rower, where the Record sheet's switch is on for the activity
(remembered in the person's announce.json, off at first): the distance,
the moving time, the split's pace or speed and the heart rate. The app
hands the recorder the words in its language; Announcer.kt counts the
moving time and the distance, Cues.kt speaks the line after a cue still
speaking.

Not tried on a phone yet.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
This commit is contained in:
Tizian 「ティツィアーン」 2026-10-29 14:25:13 +01:00
commit db7e0b7bcd
Signed by: raisondetredev
GPG key ID: 07F6FCF405488B64

View file

@ -1100,6 +1100,43 @@ Strava. What was found, 27 Oct:
phone no longer keeps a track with a tempo shows and plays nothing. Not tried on a
phone yet: the crossfade, the ducking under the cues, the metronome's click, how
steady the cadence feels.
- **D49 What OpenTracks does that Train didn't** (recommended, the developer's; 29 Oct;
step 11, D1's "at least what OpenTracks does"):
- **Announcements every km on foot, every 5 km by bike** (11a), never on a rower: the
time, the distance, the last split's pace or speed and the heart rate where a strap
or the Loop sends one, switched on the Record sheet and remembered for each activity;
one due while a plan's or a route's cue speaks waits for it (over an interval chosen
on the sheet, or the figures chosen on a settings page Train doesn't have).
- **A workout goes out as GPX, TCX or FIT** (11b) from its page through the share
sheet: GPX 1.1 with Garmin's TrackPointExtension (heart rate, cadence), TCX (laps,
heart rate, cadence, power, a row's distance) and FIT (binary, what Strava, Garmin
and intervals.icu read best, laps and power included), each written in Dart and
tested against the formats' specifications (over text formats alone, which lose
FIT's readers' best import).
- **The barometer's air pressure is kept raw** (11c) as a series of its own,
`pressure`, where the phone has a barometer; the page works out elevation from it,
its changes from the pressure, its level from the GPS altitudes' median, and the
climb from that elevation (over correcting each fix as it is recorded, which would
lose the readings a better filter could use later).
- **A bike's speed and cadence sensor (CSC, 0x1816) and power meter (CPS, 0x1818)**
(11d), one of each chosen on the Record sheet as the strap is and remembered: the
wheel's speed gives the distance where GPS can't (a turbo trainer, a tunnel), the
wheel's circumference learnt from GPS on the first rides or typed in; the crank's
cadence and the watts are series (`bikeCadence`, `power`), live and on the page with
average and normalised power.
- Built: 11a. The words come from the app (`recorderAnnouncementsOf`, in
`announce_speech.dart`) in its language: the first hundred distances spelled out
(further on as digits), what each count of hours, minutes and seconds is said as,
and each sentence with its placeholder; the service (`Announcer.kt`, tested on the
JVM) counts the moving time and the distance the plan's measures keep (paused fixes
left out), and on each distance passed says it, the moving time (hours and minutes
after the first hour, else minutes and seconds), the split's pace or speed (the
number in the app's language) and the heart rate of the last 5 s; a jump past
several (GPS lost in a tunnel) says the last. Spoken without a tone, queued after a
cue that speaks; a cue that comes meanwhile cuts it short, as cues come first. Off
for every activity until switched on (`announce.json`, `AnnounceStore`, never
synced). Not tried on a phone yet: how it sounds over music, eSpeak's and
RHVoice's reading of the German sentences.
## Consequences