# 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 HeartRateForegroundService ↓ BroadcastReceiver (ActionSample, ActionStatus, ActionMetadata) LiveHeartRateViewModel.handleServiceSample() / handleServiceStatus() / handleSensorMetadata() ↓ StateFlow 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**