Repository navigation
feat: recognise strength training as a sport without distance - #29
Merged
Merged
Conversation
What differs between sports lived in seven places: an alias table in each of the three parsers, and the pace list, cadence unit, labels, colours and order in the frontend. Adding a sport meant finding all of them. app/services/sports.py now holds one entry per sport: label, pace or speed, cadence unit, colour slot, and per-format file aliases. The parsers look sports up there, GET /api/sports serves it, and the dashboard loads it at startup and reads it everywhere. No behaviour change: the new lookup was checked against the old tables for every alias. A backend test keeps the frontend tests' copy of the catalogue in step.
Garmin records a strength session as FIT sport training, sub-sport strength_training, so it was stored as other and shown with the few metres of drift a wrist logs in a gym, and a pace for it. The catalogue gains has_distance and FIT sub-sport aliases, and a strength entry. A listed sub-sport now decides the sport. For a sport without distance the dashboard leaves out distance, pace, climb, the route, distance records, comparison and the distance bar, and keeps time, heart rate, zones and load. The FIT parser keeps the declared sport, and scripts/backfill_sports.py re-applies the catalogue to activities already stored.
# Conflicts: # README.md # backend/app/schemas/sport.py # backend/app/services/parsers/fit_parser.py # backend/app/services/sports.py # backend/tests/test_sports.py # docs/DESIGN.md # frontend/src/components/SportBreakdown.jsx # frontend/src/sports.js # frontend/src/utils/formatters.js # frontend/tests/sports.json # frontend/tests/sports.test.js
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Step 2. Stacked on #28 (the sport catalogue), so this PR targets that branch and its diff shows only step 2. GitHub retargets it to
mainwhen #28 is merged.Garmin records a strength session as FIT sport
training, sub-sportstrength_training. Until now it was stored asotherand shown with the few metres of drift a wrist logs in a gym, plus a pace for it.What changes
Catalogue (
app/services/sports.py)has_distance(defaultTrue) andfit_sub(FIT sub-sport aliases) on every sport.strengthentry:has_distance=False,fit_sub=("strength_training",).sport_from_file("fit", sport, sub_sport): a sub-sport the catalogue lists wins over the sport. Unlisted sub-sports change nothing, soindoor_rowingunderfitness_equipmentis stillother, androadundercyclingis stillcycling.GET /api/sportsnow includeshas_distance.FIT parser
sportmessage if the session has none, as it already did for the sport.raw_data.declared_sportbesidesub_sport. TCX and GPX already kept theirs.New
scripts/backfill_sports.pydeclared_sportexisted can still be moved by sub-sport.Other 2026-06-24becomesStrength 2026-06-24). A name from the file, or one you chose, stays.--dry-run, and is safe to re-run.Dashboard, for a sport without distance
formatPaceOrSpeedanswers—for such a sport, so every place that shows pace is covered.Docs: README (feature list, a backfill step under "Updating", "Adding a sport", test counts) and three new paragraphs in
docs/DESIGN.md.Verified
strength/Strength 2026-06-24, withdeclared_sport: trainingandsub_sport: strength_training.other, the backfill moves it back and renames it.tests/strength.test.jsx), eslint and build. All 6 new tests fail when run against the components without this change.Not covered
python-fitparseandfitdecodehave none), so this follows Garmin's documented sport and sub-sport values, tested on files built from the format spec.