Files
HealthTracking/docs/FIGHTRATE_FULL_CONTEXT.md

552 lines
23 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# FightRate — Full Project Context for AI Successor
## Author: Evandro
## Stack: Android Native (Kotlin, Jetpack Compose, Material3)
---
## 1. DEV ENVIRONMENT
| Item | Value |
|------|-------|
| Project root | `D:/Documents/Github/HealthTracking` |
| Package | `com.healthtracking.fightrate` |
| Gradle | Wrapper 8.11.1 |
| AGP | 8.9.1 |
| Kotlin | 2.3.21 |
| Compose BOM | 2024.12.01 |
| compileSdk | 36 |
| targetSdk | 36 |
| minSdk | 26 |
| Android SDK | `C:\Users\Evandro\AppData\Local\Android\Sdk` |
| Java | JDK 17 (jvmToolchain) |
| App name | **FightRate** |
| APK naming | `FightRate-YYYY-MM-DD-HH-mm-ss-debug.apk` |
| No git repo | Project directory is NOT a git repository |
### Key dependencies
- `navigation-compose:2.8.5`
- `compose.material3`
- `icons-lucide-android:2.2.1` (via `com.composables:icons-lucide-android`)
- **IMPORTANT**: Non-transitive R; access Lucide icons via `import com.composables.icons.lucide.R as LucideR`
- `vico:compose:3.2.2` + `vico:compose-m3:3.2.2` (charting)
- `coil-compose:3.0.4`
- `lottie-compose:6.6.2`
- `fastexcel:0.18.4` (XLSX export)
- `junit:4.13.2` (testing)
### Build commands
```bash
# Full build + test
./gradlew :app:testDebugUnitTest :app:assembleDebug
# Quick compile
./gradlew :app:compileDebugKotlin
# Unit test focused
./gradlew :app:testDebugUnitTest --tests "*AthleteInsightsTest*"
# Install on device
./gradlew :app:installDebug
```
---
## 2. PROJECT VISION
**FightRate** is a native Android app for tracking heart rate during combat/fighting sports using a **Magene H003** chest strap (BLE Heart Rate Service 0x180D).
### Core pillars
1. **Real-time BLE heart rate tracking** — even with screen off, even in background
2. **Workout sessions** — start/pause/resume/finish with round timer
3. **Athlete profile & cardiac zones** — personalized by age, sex, resting HR, measured max HR
4. **Data insights** — readiness, effort, hydration, recovery, fight zone time
5. **Rich history & charts** — time-based Vico charts with compaction, export (CSV/JSON/XLSX)
6. **Scientific cardiac analytics** — statistical and clinical-grade metrics from raw HR data
### UI conventions
- All visible text in **PT-BR** (Portuguese Brazilian)
- All code identifiers in **English**
- Dark theme with signature orange accent (`FightOrange = #FF5733`)
- Bottom navigation tabs: Ao vivo | Sensor | Histórico | Insights | Perfil
- Cards use `FightCard` composable (dark panels with rounded corners)
---
## 3. FILE STRUCTURE
```
app/src/main/java/com/healthtracking/fightrate/
├── MainActivity.kt # Entry point, permission requests
├── ble/
│ ├── AndroidHeartRateBleClient.kt # Concrete BLE GATT client implementation
│ ├── AndroidHeartRateBleScanner.kt # Concrete BLE scanner implementation
│ ├── HeartRateBleClient.kt # BLE client interface
│ ├── HeartRateBleConstants.kt # BLE UUIDs (0x180D, 0x2A37, 0x2A38, 0x180F, 0x2A19)
│ ├── HeartRateBleScanner.kt # BLE scanner interface
│ ├── HeartRateBleStatus.kt # Status sealed class (Connecting/Connected/etc.)
│ ├── HeartRateDevice.kt # Device data class
│ ├── HeartRateParser.kt # BLE heart rate measurement parser
│ └── HeartRateSensorMetadata.kt # Battery level + body sensor location
├── data/
│ ├── HeartRateSampleStore.kt # SQLite DB (heart_rate_samples + workout_sessions)
│ └── HeartRateExporter.kt # CSV/JSON/XLSX export via FileProvider
├── domain/
│ ├── AthleteInsights.kt # BMI, Karvonen, readiness, effort, hydration, fight zone, alerts
│ ├── HeartRateAlertSettings.kt # Alert config + evaluator
│ ├── HeartRateStats.kt # Stats (avg/min/max/stdDev)
│ ├── HeartRateWindows.kt # Rolling time window filter
│ ├── HeartRateZones.kt # Zone calculation (6 zones by % max HR)
│ ├── RoundTimer.kt # Round/rest timer logic
│ ├── WorkoutSession.kt # Session + summary models + calculations
│ └── model/
│ ├── AthleteProfile.kt # Age, sex, height, weight, maxHR, restingHR, sport, class, goal
│ ├── FightSport.kt # Boxing, MuayThai, MMA, BJJ, Wrestling, FreeTraining
│ ├── HeartRateMeasurement.kt # Measurement model
│ └── HeartRateSample.kt # Core sample (timestampMillis, bpm, sport, source, deviceName, sessionId)
├── service/
│ └── HeartRateForegroundService.kt # Foreground BLE service with auto-reconnect + backoff
├── system/
│ ├── BackgroundRunPermission.kt # Battery optimization settings opener
│ └── HeartRateAlertNotifier.kt # Vibration + sound alert dispatcher
└── ui/
├── live/
│ ├── BleConnectionStatus.kt # Connection status enum
│ ├── HistoryPeriod.kt # Time window enum (Last10min/30min/1h/3h/6h/Today)
│ ├── LiveHeartRateUiState.kt # Single source of truth state data class
│ └── LiveHeartRateViewModel.kt # Central AndroidViewModel (~729 lines)
├── screens/
│ └── HomeScreen.kt # ALL UI in one file (~1700+ lines of Compose)
└── theme/
├── Color.kt # Dark theme color palette
└── FightRateTheme.kt # Material3 theme configuration
Tests:
app/src/test/java/com/healthtracking/fightrate/
├── ble/HeartRateParserTest.kt
├── domain/
│ ├── AthleteInsightsTest.kt
│ ├── HeartRateAlertEvaluatorTest.kt
│ ├── HeartRateStatsCalculatorTest.kt
│ ├── HeartRateWindowsTest.kt
│ ├── HeartRateZonesTest.kt
│ ├── RoundTimerTest.kt
│ └── WorkoutSessionSummaryTest.kt
```
---
## 4. DATABASE SCHEMA
### Table: heart_rate_samples (version 4)
```sql
id INTEGER PRIMARY KEY AUTOINCREMENT
timestamp_millis INTEGER NOT NULL
day_key TEXT NOT NULL
bpm INTEGER NOT NULL
sport TEXT NOT NULL
source TEXT NOT NULL
device_name TEXT
session_id INTEGER
```
Indexed on `day_key`, `timestamp_millis`, `(session_id, timestamp_millis)`.
### Table: workout_sessions (created at v3, expanded at v4)
```sql
id INTEGER PRIMARY KEY AUTOINCREMENT
started_at_millis INTEGER NOT NULL
ended_at_millis INTEGER
status TEXT NOT NULL DEFAULT 'Active'
sport TEXT NOT NULL DEFAULT 'Treino livre'
round_duration_seconds INTEGER NOT NULL DEFAULT 180
rest_duration_seconds INTEGER NOT NULL DEFAULT 60
rounds INTEGER NOT NULL DEFAULT 3
accumulated_active_seconds INTEGER NOT NULL DEFAULT 0
last_resumed_at_millis INTEGER
-- v4 columns:
pre_workout_energy INTEGER
pre_workout_fatigue INTEGER
muscle_soreness INTEGER
sleep_hours REAL
sleep_quality INTEGER
pre_workout_weight_kg REAL
water_intake_ml INTEGER
symptoms_note TEXT NOT NULL DEFAULT ''
post_workout_rpe INTEGER
post_workout_fatigue INTEGER
post_workout_soreness INTEGER
post_workout_weight_kg REAL
post_workout_note TEXT NOT NULL DEFAULT ''
```
---
## 5. DATA FLOW
### BLE → Service → ViewModel → UI
```
Magene H003 (BLE)
↓ Heart Rate Service 0x180D / Measurement 0x2A37
AndroidHeartRateBleClient (GATT)
↓ Flow<HeartRateMeasurement>
HeartRateForegroundService
↓ BroadcastReceiver (ActionSample, ActionStatus, ActionMetadata)
LiveHeartRateViewModel.handleServiceSample() / handleServiceStatus() / handleSensorMetadata()
↓ StateFlow<LiveHeartRateUiState>
HomeScreen.kt (@Composable)
```
### Session lifecycle
1. User fills **Check-in** (mandatory dialog) → `startWorkoutSessionWithCheckIn()`
2. SQLite `workout_sessions` inserted, sample `session_id` auto-assigned
3. Round timer runs in ViewModel ticker
4. User can Pause / Resume
5. User taps Finish → **Post-workout** dialog → `finishWorkoutSessionWithPostWorkout()`
6. Session status = Finished, `ended_at_millis` set
---
## 6. CARDIAC ZONES SYSTEM
### Zone thresholds based on % of max heart rate
| Zone | % Max HR | Label (PT-BR) | Usage |
|------|----------|----------------|-------|
| Recovery | 1–59% | Recuperação | Recovery/active rest |
| Base | 60–69% | Base | Aerobic base |
| Vigorous | 70–85% | Vigorosa | Moderate-high intensity |
| Fight | 86–89% | Luta intensa | Fight zone specific |
| RedLine | 90–95% | Muito intensa | Very high intensity |
| Limit | 96–200% | Limite | Maximum effort |
### Max HR formula
- Estimated: `208 - (0.7 × age)` (Tanaka formula)
- Overrideable with `measuredMaxHeartRate` (campo: "limite cardíaco real")
### Karvonen zones (reserve-based)
When resting HR is available, zones shift upward using:
`TargetHR = RestingHR + Reserve × %Intensity`
where `Reserve = MaxHR - RestingHR`
---
## 7. CURRENT METRICS / CALCULATIONS
### Already implemented
1. **BMI** — from weight + height, with category (abaixo do peso / peso adequado / sobrepeso / obesidade)
2. **Heart Rate Reserve** (Karvonen) — MaxHR − RestingHR
3. **Zones by Karvonen** — personalized zone ranges
4. **Readiness Score** (0–100) — based on sleep hours, sleep quality, energy, fatigue, soreness
5. **Workout Effort Score** (0–100) — based on avg%BPM, peak%BPM, duration, RPE, with session load (RPE×min)
6. **Hydration Estimate** — pre/post weight difference + water intake, with fluid loss warning
7. **Fight Zone Time** — seconds and % of session spent in Fight/RedLine/Limit zones
8. **Athlete Insights Alerts** — combined warnings from readiness, hydration, effort, symptoms
9. **Heart Rate Stats** — avg, min, max, standard deviation
10. **Zone Breakdown** — % of session in each zone
11. **Rolling 60s average** — main display; instant BPM shown as "Agora"
---
## 8. BLE RESILIENCE SYSTEM
### Reconnection strategy
- Service runs as foreground with `foregroundServiceType="connectedDevice"`
- `START_STICKY` — Android restarts if killed
- On unexpected disconnect (distance/signal loss), auto-reconnect with backoff:
- 1st: 2s → 2nd: 5s → 3rd: 10s → 4th+: 30s
- Manual disconnect sets `manualDisconnect = true` flag in SharedPreferences
- When `manualDisconnect = true`, no auto-reconnect
- Reconnection state persisted: last device ID, device name, manual flag
- On service restart (START_STICKY), reads persisted state and auto-reconnects if not manual
- No aggressive continuous scanning; reconnects by known device ID first
### Battery optimization
- Single foreground service during session (no persistent background service when idle)
- Notification updates throttled: max every 15s OR >3 BPM delta
- No SQLite polling on every beat from service
- ViewModel polls DB at 5s intervals only when connected
- Rolling 60s average computed in-memory in service
- Guide user to battery optimization settings via `BackgroundRunPermission`
---
## 9. CURRENT UI STRUCTURE (HomeScreen.kt)
Single massive file with all composable functions (~1700+ lines):
### Screens (tabs)
- **LiveScreen** — rolling 10-min chart, instant BPM, 60s avg, zone, Muay Thai comparison
- **SensorScreen** — scan button, device list, battery chip, body sensor location, connection status, background toggle
- **HistoryScreen** — period selector, stats cards, zone breakdown, Vico chart (time-based) with empty state
- **InsightsScreen** — BMI, reserve, readiness, effort, hydration, fight zone, alerts
- **ProfileScreen** — expandable sections (básico, cardiovascular, luta), choice chips for sex/sport, save button
### Key composables
- `FightCard` — dark panel wrapper
- `MetricTile` — stat label+value pair
- `LiveMetricPill` — compact live stat pill
- `HeartRateLineChart` — Vico chart with time-based x-axis
- `EmptyTimeWindowChart` — placeholder when no data
- `RoundSessionCard` — session controls + round timer
- `ExpandedSessionCard` — session metrics
- `AlertSettingsCard` — alert configuration
---
## 10. WHAT DOCTORS CONSIDER FROM HEART RATE DATA (Scientific Foundation)
Below is a structured compilation of medical-grade metrics that can be calculated from the data types FightRate already collects (raw HR timestamps, profile data, session data, sleep, subjective scales). These are well-established in sports cardiology, exercise physiology, and clinical practice.
### 10.1 Resting Heart Rate (RHR)
- **Clinical significance**: Lower RHR = better cardiovascular fitness. Resting tachycardia (>100 bpm) flags medical concern.
- **Can trend**: Weekly RHR average from morning readings. Spike of +5-7 bpm signals possible illness, overtraining, or poor recovery.
- **Calculation**: Mean of lowest 5 readings during rest periods (early morning before rising is gold standard).
### 10.2 Heart Rate Recovery (HRR)
- **Clinical gold standard**: Drop in BPM 1-minute and 2-minutes post-exercise cessation.
- **Normal**: >22 bpm drop at 1 min (adults). Drop <12 bpm = elevated cardiovascular mortality risk (Cole et al., NEJM 1999).
- **Athlete context**: Faster recovery = better conditioning. Slowing recovery trend = functional overreaching or detraining.
- **Can calculate from existing data**: After session ends, look at first 60s and 120s of BPM decline.
### 10.3 Heart Rate Variability (HRV)
- **Key clinical parameters**:
- **RMSSD** (Root Mean Square of Successive Differences): Parasympathetic activity marker. Gold standard for daily monitoring.
- **SDNN** (Standard Deviation of NN intervals): Overall HRV. Clinical risk predictor.
- **LF/HF Ratio**: Sympathetic/parasympathetic balance.
- **From our data**: HRV requires beat-to-beat R-R intervals (ms). **BLE HR Service 0x2A37 can provide RR intervals** if the sensor sends them (Magene H003 does). We already have `HeartRateMeasurement` with potential RR data.
- **Clinical use**: Low HRV = stress, illness risk, overtraining. High HRV = recovery, readiness.
- **Training application**: Morning HRV guides daily training intensity (Daneshvar, 2024).
### 10.4 Cardiac Drift (Cardiovascular Drift)
- **Definition**: Progressive rise in HR during steady-state exercise despite constant workload.
- **Causes**: Dehydration, electrolyte loss, thermoregulatory strain, blood volume shift.
- **Clinical marker**: Drift >10% of starting HR = significant heat/dehydration stress.
- **Can calculate**: Linear regression slope of HR over session duration at constant intensity.
### 10.5 Chronotropic Response / Chronotropic Incompetence
- **Definition**: Inability of HR to rise appropriately with exercise intensity.
- **Calculation**: `%HeartRateReserve achieved / %MetabolicReserve achieved`
- **Clinical threshold**: CI = failure to reach 85% of age-predicted max HR at peak exercise.
- **Detection from data**: Slope of HR increase in first 3 minutes of session.
### 10.6 Heart Rate Deflection Point (HRDP / Conconi Test)
- **Definition**: The point at which HR stops increasing linearly with running speed/workload.
- **Use**: Non-invasive anaerobic threshold estimation.
- **Calculation**: Piecewise linear regression of HR × workload curve.
### 10.7 TRIMP (Training Impulse)
- **Banister's TRIMP**: `duration × (ΔHR/ΔHRmax) × 0.64e^(1.92×ΔHR/ΔHRmax)`
- **MICT TRIMP**: `duration × %MaxHR`
- **Edwards TRIMP (our approach)**: Sum of minutes in each zone × zone coefficient.
- **Clinical use**: Quantifies internal training load. Correlates with adaptation and injury risk.
### 10.8 Training Monotony & Strain (Foster, 1998)
- **Monotony**: `WeeklyMeanLoad / WeeklySDLoad`. High monotony (>2.0) + high strain = overtraining risk.
- **Strain**: `WeeklySumLoad × Monotony`.
- **Data requirement**: Daily session load over 7+ days.
### 10.9 Excess Post-Exercise Oxygen Consumption (EPOC) Estimate
- **Correlation**: Higher HR during session → higher EPOC → more post-workout calorie burn.
- **Proxy metric**: Time above 70% max HR correlates with EPOC duration.
### 10.10 Aerobic Efficiency / Cardiac Economy
- **Metric**: HR at a given perceived exertion level over time. If HR at same RPE decreases, athlete is fitter.
- **Calculation**: Match sessions with same RPE → compare average HR.
### 10.11 Relative VO2max Estimation
- **Astrand-Ryhming nomogram**: Based on HR at submaximal workload with age/sex correction.
- **Uth-Sørensen-Overgaard formula**: `VO2max = 15.3 × (MaxHR / RestingHR)` (approximate).
### 10.12 Heart Rate Turbulence (HRT)
- **Clinical**: Post-premature-ventricular-contraction HR response. Not feasible without ECG.
### 10.13 Summary of actionable clinical-grade metrics from our data
| Metric | Data needed | Clinical value | Feasibility |
|--------|-----------|----------------|-------------|
| Resting HR trend | Morning readings | Overtraining, illness | ✅ Already have |
| HR Recovery (1min, 2min) | Post-session BPM | CV risk, conditioning | ✅ Easy add |
| Cardiac Drift | Session BPM trend | Hydration, heat stress | ✅ Easy add |
| Chronotropic Response | Session onset BPM | CV fitness, beta-blocker effect | ✅ Easy add |
| TRIMP (Edwards) | Zone time | Training load | ✅ Already have zone breakdown |
| TRIMP (Banister) | Duration, avgHR, maxHR | Training load | ⚡ Medium effort |
| Weekly Monotony & Strain | 7d load history | Overtraining risk | ⚡ Need 7d history UI |
| VO2max estimation | MaxHR, RestingHR, sex | Aerobic fitness estimate | ✅ Ready (formula exists) |
| HRV RMSSD/SDNN | RR intervals | Recovery, readiness | ⚡ Need RR parser |
| HR Deflection Point | Incremental test BPM | Anaerobic threshold | ❌ Requires protocol |
| Fatigue slope | HR per minute over session | Pacing, fatigue onset | ✅ Easy add |
---
## 11. WHAT USER WANTS NOW (Pre-approved)
### A. Charts improvement
Make charts more informative and interactive:
- Better tooltips/markers
- Zone-colored areas
- Callout for min/max/avg points
- Session overlay with round/rest phases
- Smoother pan/zoom
- Multiple time ranges
### B. Session-based detailed report
A system that:
1. User can start/stop a **recording time window**
2. All HR samples within that window are collected
3. At stop, a **detailed report** is generated with:
- Full session statistics
- Zone breakdown
- HR Recovery
- Cardiac drift analysis
- Chronotropic response
- TRIMP score
- Readiness context (from pre-session check-in)
- Hydration estimate
- Fight zone time
- Trend compared to past sessions
### C. Scientific/clinical analytics
Research-backed metrics that doctors consider from HR data (section 10 above).
This is now **approved** to implement:
- HR Recovery (1min, 2min)
- Cardiac Drift
- Chronotropic Response
- TRIMP (Banister + Edwards)
- VO2max estimation
- Weekly monotony & strain
- Fatigue slope
- HRV when RR data available
---
## 12. APPROVED DECISIONS (Perfil/Insights P0)
| Item | Decision |
|------|----------|
| Check-in | **Mandatory** before starting session |
| Insights location | **New tab** in bottom navigation |
| Biological sex | **Collected** as Masculino/Feminino |
| Scale range | **0–10** for energy, fatigue, soreness, sleep quality |
| Advanced fields | **Collapsible** sections (expand/hide) |
---
## 13. IMPORTANT CODE PATTERNS & PITFALLS
### Don'ts (from previous learnings)
1. DON'T create custom Canvas charts — use Vico (`com.patrykandpatrick.vico`)
2. DON'T move BLE ownership from foreground service to ViewModel
3. DON'T add new dependencies without asking
4. DON'T use `lineSeries` — Vico API: use `lineModel` instead
5. DON'T add fragil custom Canvas gauges
6. DON'T mix business rules in Compose — keep domain pure Kotlin
7. DON'T make destructive SQLite migrations without approval
8. DON'T add unused code or placeholder features
### Do's
1. DO use `LucideR.drawable.lucide_ic_xxx` for Lucide icons
2. DO test domain with JUnit before UI
3. DO implement in slices: domain → persistence → ViewModel/state → UI → BLE
4. DO use `HeartRateForegroundService.ActionConnect` / `ActionDisconnect` for BLE control
5. DO preserve PT-BR in UI, English in code
6. DO run `./gradlew :app:testDebugUnitTest :app:assembleDebug` before claiming completion
7. DO save data locally first (SQLite source of truth)
8. DO write `collect` calls with explicit `{ }` braces around the when-body in service
9. DO use `ChoiceChipButton`, `ExpandableSectionHeader`, `ProfileNumberField` for consistent UI
### Known non-blocking warnings
- `lineSeries` deprecated → use `lineModel` (low priority)
- BLE `writeDescriptor` deprecated in SDK 36 (non-blocking)
- No LSP client for Kotlin in this environment; rely on `compileDebugKotlin` output
---
## 14. IMMEDIATE NEXT TASK
### Priority: Implement session-based detailed report + scientific analytics
1. **Enhance chart**: Session overlay with round phases, zone colors, better tooltips
2. **Session report system**:
- Start/stop recording independent of session (or same)
- Collect all samples in range
- Generate report at stop with medical-grade metrics
3. **Add new domain calculations**:
- HR Recovery (1min, 2min)
- Cardiac Drift
- Chronotropic Response
- TRIMP (Banister + Edwards)
- VO2max estimation
4. **Report UI**: Dedicated report screen or dialog with full metrics
5. **After done**: send APK via Telegram
### Workflow to follow
```
→ Search web if needed
→ Write/update spec
→ Audit existing code
→ Implement domain + tests (new calculations)
→ Implement persistence if needed
→ Implement ViewModel/state
→ Implement UI (chart + report)
→ Build & test
→ Send APK
→ Update Obsidian roadmap
```
---
## 15. WORKFLOW DOCUMENT
Path: `D:/Documents/Github/HealthTracking/docs/FIGHTRATE_DEVELOPMENT_WORKFLOW.md`
### Project skill: `fightrate-quality-loop`
Scope: project:HealthTracking
### Skill path
`C:\Users\Evandro\.pi\agent\projects-memory\HealthTracking\skills\fightrate-quality-loop\SKILL.md`
### Obsidian vault
Path: `D:\Documents\Obsidian Vault`
Roadmap file: `Projetos/FightRate - Auditoria e Roadmap.md`
---
## 16. COMMANDS QUICK REFERENCE
```bash
# Full verification
./gradlew :app:testDebugUnitTest :app:assembleDebug
# Quick compile
./gradlew :app:compileDebugKotlin
# Domain tests
./gradlew :app:testDebugUnitTest --tests "*AthleteInsightsTest*"
./gradlew :app:testDebugUnitTest --tests "*WorkoutSessionSummary*"
./gradlew :app:testDebugUnitTest --tests "*HeartRateZonesTest*"
# Install APK
./gradlew :app:installDebug
# Latest APK path
app/build/outputs/apk/debug/FightRate-*-debug.apk
```
---
## 17. TELEGRAM CONTEXT
- User delivers messages via Telegram bridge
- `[telegram]` prefix → deliver replies via Telegram
- When sending APK: call `telegram_attach(localPath)`
- The user says: "Ao terminar me mande o apk no telegram"
---
## 18. FINAL NOTES
- This document was built by reading all source files, build files, specs, and tests
- Everything described here is **already implemented** unless marked as "new" or "next"
- The user has **pre-approved** the scientific analytics implementation + session report
- The user wants **continuous improvement** — no stop until done
- Focus on **charts**, **session-based reporting**, and **scientific-grade metrics**