Files
HealthTracking/docs/FIGHTRATE_FULL_CONTEXT.md
T

23 KiB
Raw Blame History

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

# 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)

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)

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

# 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