m06 (Server.WatchBody.Import + --mode import): FitParser на официальном Garmin FIT SDK 21.218.0 (Dynastream.Fit; события Decode, типы по Mesg.Num) → канонический факт workout-facts/1 (+avg_hr, hr_recovery_s, fit_file_id); TcxGpxParser (упрощённый факт); WorkoutImporter — дедуп fit_file_id, сопоставление телефонной тренировке ±15 мин (Ф-8.4), иначе строка «только .fit»; ProgramPackageImporter — пакет program-import.json по external_id (повтор → новая версия max+1, отсутствующие упражнения создаются); ImportService — подпапки-атлеты, архив, коды 0/1/2. Errata З-35: program_select/get rev.2 (+external_id, DROP старой сигнатуры), маппинг ProgramRepository. m07 (Server.WatchBody.Fetch + --mode fetch): GarminClient — SSO по контракту garminconnect (embed→csrf→signin→ticket→OAuth1→Bearer), список активностей, скачивание .fit; FitFetcher — атлет по Garmin.AthleteName, фильтр strength_training, дедуп 2 рубежей (кэш activityId + fit_file_id в БД); коды 0/1/2, auth-fail → подсказка про m06-fallback. Против живого Garmin — ручная валидация прототипа; тесты — FakeGarminHandler + .fit-энкодер SDK. Тесты: Web 98/98 (m06 — 12, m07 — 5), Core 56/56, psql 123/123. Конфиг: Import.Dir/ArchiveDir, Garmin.* (в т.ч. новый AthleteName — tech-req 4.2). Эксплуатационные файлы в коммит не включены. |
||
|---|---|---|
| .. | ||
| api_specs | ||
| SKILL.md | ||
| module_reqs.md | ||
| readme.md | ||
readme.md
m06-fit-import — план работ (d-dev)
Модуль:
Server.WatchBody.Import(FitParser/TcxGpxParser/ WorkoutImporter/ProgramPackageImporter/ImportService) + режим--mode importв единой точке входа CLI. Алгоритм:std1\_rules\d\d-dev.md(итерационная разработка по модулям). Требования: module_reqs.md. Зависимости: m01 (репозитории, DONE), m02 (единая точка входа CLI — DONE), m03 (ProgramStore — создание версий пакета, DONE).
| Шаг | Что делаем | Статус |
|---|---|---|
| 0 | Модульные документы: module_reqs.md / readme.md / SKILL.md | ✅ 2026-10-18 |
| 1 | Список единиц (классы/методы/конфиг/тесты) | ✅ 2026-10-18 |
| 1.3 | Пользователь! утверждение списка | ⬜ |
| 2 | Спецификации: api_specs (facts-схема, сопоставление, пакет) | ✅ 2026-10-18 |
| 2.4 | Пользователь! утверждение спецификаций | ✅ 2026-10-18 |
| 3 | Реализация + тесты | ✅ 2026-10-18 (тесты Web 93/93, из них m06 — 12; Core 56/56; psql 123/123; CLI-смок --mode import пройден) |
| 3.4 | Пользователь! утверждение реализации (закрытие модуля) | ✅ 2026-10-18 |
| 4 | Завершение: план, примечания | ✅ 2026-10-18 — Модуль завершён (2026-10-18). Следующий по плану этапа 7 — m07-fit-fetch (итерация 2). |
Статусы: ⬜ не начат · 🔄 в работе · ✅ готов.
Примечания по ходу работ
- SDK: NuGet
Garmin.FIT.Sdk21.218.0, namespaceDynastream.Fit(неGarmin.Fit.*); API потоковый:Decode.IsFIT/CheckIntegrity/Read(Stream), событияMesgEventдоставляют базовыйMesg— типы конструируются из него поMesg.Num(new SessionMesg(mesg)); уSetMesg—GetRepetitions(не NumReps);Encodeдля .fit-фикстур тестов. - Errata З-35 (доведение):
program_select/program_getне возвращалиexternal_id— rev. 2 обеих функций (+ DROP прежней row-типной сигнатуры), маппинг вProgramRepository.Select/Get, синхронизированы func_specs и mock-колонки Core.Tests; psql-тесты перегнаны — PASS. - Errata m01:
workout_insertfit-полей не принимает (дизайн db-m-8) — строка «только .fit» пишется Insert + Update (как sync, errata m02). - Устройство в .fit:
garmin_productу тестового файла декодируется вnull, фактическое устройство — числом вproduct(Fenix6sAsia = 3513) —deviceпишет идентификатор как есть. external_idпакета уникален глобально (З-35): один пакет (program_id) назначается одному атлету — повтор тому же атлету даёт новую версию, повтор другому — UNIQUE-ошибку (файл остаётся, лог; формат program-import-format.md §3.4 соблюдён).Sportв TCX — атрибутActivity[@Sport], не элемент.