Сервис составления недельной программы тренировок на основе базы упражнений ExerciseDB. Считает нагрузку по группам мышц, показывает баланс и недотренированные группы на анатомической карте тела, формирует план по дням и экспортирует его в PDF.
- Backend: FastAPI, SQLModel (SQLite), Uvicorn
- Frontend: Streamlit
- Данные: ExerciseDB (RapidAPI) с кэшем в SQLite; офлайн-снапшот как фолбэк
- ML: scikit-learn (NearestNeighbors)
- PDF: fpdf2
- Запуск: Docker / docker-compose
Разделение фронтенд/бэкенд: Streamlit ходит в FastAPI только по HTTP, бизнес-логика и данные — на бэкенде.
Поток данных:
- Старт бэкенда: init_db -> seed (из ExerciseDB при наличии ключа, иначе снапшот) -> localize_images (подмена gif_url на локальные пути, если картинки скачаны).
- Frontend отправляет настройки -> POST /plans/generate -> план.
- Упражнения текущего плана -> POST /analysis и POST /recommendations -> нагрузка по группам, статусы, подсказки.
- Карта тела и таблица раскрашиваются одними и теми же значениями нагрузки.
- GET /plans/{id}/export/pdf (или POST /export/pdf) -> PDF.
Модули бэкенда:
- muscles.py — маппинг target / secondaryMuscles / bodyPart в канонические группы; веса (основная 1.0, вспомогательная 0.5).
- balance.py — недельная нагрузка (вес * подходы), коридоры объёма по интенсивности/цели, статусы under/ok/over, итоговый балл.
- planner.py — сплит по числу дней (full-body / upper-lower / push-pull-legs) и проход добивки недогруженных групп.
- recommender.py — подбор упражнений под дефицит (правила) и похожие упражнения (kNN по one-hot мышц/инвентаря/категории).
- seed.py / exercisedb.py — загрузка и кэш упражнений.
- pdf.py — таблица плана и сводка нагрузки (шрифт DejaVu для кириллицы).
Модули фронтенда: settings_form, plan_view, body_map (SVG-контуры мышц), api_client.
- База: https://exercisedb.p.rapidapi.com
- Авторизация: заголовки X-RapidAPI-Key, X-RapidAPI-Host
- Используется: GET /exercises?limit&offset (постранично; бесплатный тариф — 10 записей за запрос)
- Поля записи: id, name, bodyPart, target, secondaryMuscles[], equipment, instructions[], category, difficulty, gifUrl
- Применение: seed.py разово выкачивает упражнения в SQLite. При отсутствии ключа или ошибке используется встроенный снапшот backend/data/exercises_seed.json.
| Метод | Путь | Назначение |
|---|---|---|
| GET | /health | проверка |
| GET | /exercises | список; фильтры bodyPart,target,equipment,search,limit,offset |
| GET | /exercises/{id} | упражнение |
| GET | /exercises/{id}/similar | похожие упражнения (ML) |
| GET | /meta/bodyparts /meta/targets /meta/equipment | справочники значений |
| POST | /plans/generate | сгенерировать план (без сохранения) |
| POST | /plans | сохранить план |
| GET | /plans /plans/{id} | список / план |
| PUT | /plans/{id} | обновить |
| DELETE | /plans/{id} | удалить |
| GET | /plans/{id}/analysis | баланс нагрузки |
| GET | /plans/{id}/recommendations | подсказки |
| GET | /plans/{id}/export/pdf | |
| POST | /analysis /recommendations /export/pdf | то же для несохранённого плана |
| GET | /static/exercise_images/{id}.jpg | изображения упражнений |
Swagger: http://localhost:8000/docs
Docker:
docker compose up --build
UI — http://localhost:8501, API — http://localhost:8000/docs
Локально (Python 3.11+):
cd backend && pip install -r requirements.txt && uvicorn app.main:app --port 8000
cd frontend && pip install -r requirements.txt && streamlit run app.py
- Без ключа приложение работает на снапшоте (~870 упражнений).
- С ключом: .env -> RAPIDAPI_KEY=..., затем python -m app.seed --force --source api.
- Картинки: python backend/scripts/download_images.py (локально в backend/data/exercise_images/, иначе используются удалённые ссылки).
- Упражнения и изображения — free-exercise-db: https://github.com/yuhonas/free-exercise-db
- Контуры карты мышц — react-native-body-highlighter: https://github.com/HichamELBSI/react-native-body-highlighter