From 105651f0052209f6f1cfbc2a27c08efddd4b9e11 Mon Sep 17 00:00:00 2001 From: Roman Priesol Date: Mon, 7 Sep 2026 13:38:49 +0200 Subject: [PATCH] Add activity type and a click-to-open track profile panel MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Track properties gain activity_type (FIT: sport enum from the session/sport message, Garmin's own table; GPX: passed through as-is) alongside the existing distance/elevation/duration. Clicking a track line now opens a bottom panel with a chart per metric the track actually has (elevation always; speed/cadence/heart rate only when present — FIT's record fields or GPX's device extensions). TrackStats.build_profile computes cumulative distance the same way for both formats so they're directly comparable. One pointermove listener drives a synchronized crosshair across every chart, a single tooltip listing all series, and a map marker at the hovered point's position — hovering the chart shows where on the track that moment was. --- docs/architecture.adoc | 69 +++++++++--- lib/maptool/fit.rb | 96 +++++++++++++--- lib/maptool/gpx.rb | 25 ++++- lib/maptool/track_stats.rb | 27 +++++ public/css/style.css | 112 +++++++++++++++++++ public/js/gpx.js | 21 +++- public/js/map.js | 5 +- public/js/track_profile.js | 218 +++++++++++++++++++++++++++++++++++++ test/fixtures/sample.gpx | 13 +++ test/test_fit.rb | 64 +++++++++++ test/test_gpx.rb | 13 +++ test/test_track_stats.rb | 22 ++++ views/index.erb | 9 ++ views/layout.erb | 3 +- 14 files changed, 655 insertions(+), 42 deletions(-) create mode 100644 public/js/track_profile.js diff --git a/docs/architecture.adoc b/docs/architecture.adoc index 408c206..de48cbe 100644 --- a/docs/architecture.adoc +++ b/docs/architecture.adoc @@ -234,21 +234,60 @@ matched URL can never break out of the `href="..."` attribute. Every other value is HTML-escaped before being handed to `Popup#setHTML`. Track properties:: Every track feature (both formats) also carries -`distance_meters`, `elevation_gain_meters`, `duration_secs` and -`point_count`, computed once server-side by `Maptool::TrackStats` -(`lib/maptool/track_stats.rb`, shared by `Gpx`/`Fit` so neither -duplicates the haversine formula) rather than in the browser — cheap -either way, but it means a GPX and a FIT file end up with the same -properties shape, so the frontend doesn't need to know which format it -got. Distance sums the haversine distance between consecutive points; -elevation gain sums only the positive deltas (descents don't -subtract); duration is the gap between the first and last known -timestamp, skipping unknown ones in between — `nil` for any of these -where the source data doesn't have enough to compute it (e.g. a GPX -file with no `