feat(components): ActionButton stopAlert + typography type fixes

This commit is contained in:
fightrate-bot committed 2026-06-16 01:50:26 -03:00
1 parent 2c51fd2623
commit bbe2919c2c
89 files changed
+75993 -9961

No files matched your search

+551
View File
@@ -0,0 +1,551 @@
# 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**