Files
HealthTracking/docs/superpowers/specs/2026-06-08-fightrate-athlete-profile-insights.md
T

691 lines
17 KiB
Markdown
Raw 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.
# Spec: FightRate P0 — Perfil Avançado e Insights do Lutador
## Objective
Criar a primeira versão do Perfil Avançado do Lutador para coletar dados pessoais, cardiovasculares, subjetivos e de recuperação suficientes para gerar insights úteis de treino sem deixar o app inchado.
O objetivo não é diagnóstico médico. O objetivo é apoio esportivo: entender carga, recuperação, hidratação, intensidade e evolução do atleta usando os batimentos reais do sensor BLE somados a dados simples informados pelo usuário.
Usuário principal: lutador ou praticante de treino de combate que usa o FightRate para acompanhar batimentos durante treinos, rounds e sessões.
## Scope P0
Implementar somente o núcleo inicial:
1. Perfil do Lutador.
2. Check-in pré-treino.
3. Registro pós-treino.
4. Insights básicos do treino e recuperação.
Não implementar neste P0:
- exames médicos avançados;
- integração com wearable externo além do sensor BLE atual;
- Health Connect;
- prescrição médica;
- VO2max avançado;
- IA generativa para recomendação clínica;
- dashboard muito complexo.
## Assumptions
1. O app continua Android nativo Kotlin + Jetpack Compose.
2. Textos visíveis continuam em PT-BR.
3. Identificadores de código continuam em inglês.
4. SQLite local-first continua como fonte de verdade.
5. O sensor BLE continua sendo fonte dos batimentos em tempo real.
6. Cálculos de saúde serão apresentados como estimativas esportivas, não diagnósticos.
7. O P0 deve priorizar campos que geram cálculos imediatos.
## Tech Stack
- Kotlin
- Jetpack Compose Material3
- SQLite via `SQLiteOpenHelper` existente em `HeartRateSampleStore`
- Gradle Kotlin DSL
- JUnit 4 para testes unitários
- Vico para gráficos existentes
- Lucide para ícones existentes
## Commands
Build completo:
```bash
./gradlew :app:testDebugUnitTest :app:assembleDebug
```
Teste unitário focado:
```bash
./gradlew :app:testDebugUnitTest --tests "*AthleteInsights*"
```
Compilação rápida:
```bash
./gradlew :app:compileDebugKotlin
```
Instalação debug:
```bash
./gradlew :app:installDebug
```
## Existing Code to Reuse
Reaproveitar antes de criar novo:
- `AthleteProfile.kt`
- `HeartRateZones.kt`
- `WorkoutSession.kt`
- `HeartRateStats.kt`
- `HeartRateSampleStore.kt`
- `LiveHeartRateViewModel.kt`
- `LiveHeartRateUiState.kt`
- `HomeScreen.kt`
- `FightCard`
- `MetricTile`
- `LiveMetricPill`
- cards de Perfil existentes
- SQLite `fightrate.db`
## Data Model — P0 Fields
### 1. Perfil básico
Campos:
- `age`
- `biologicalSex`
- `heightCm`
- `weightKg`
- `fightSport`
- `weightClassKg`
- `trainingGoal`
Uso:
- personalizar zonas;
- calcular IMC;
- acompanhar categoria de peso;
- contextualizar insights.
### 2. Perfil cardiovascular
Campos:
- `restingHeartRate`
- `measuredMaxHeartRate`
Uso:
- limite cardíaco personalizado;
- zonas por percentual;
- reserva cardíaca;
- alertas de esforço.
### 3. Check-in pré-treino
Campos por sessão:
- `preWorkoutEnergy` escala 1–5
- `preWorkoutFatigue` escala 1–5
- `muscleSoreness` escala 1–5
- `sleepHours`
- `sleepQuality` escala 1–5
- `preWorkoutWeightKg`
- `waterIntakeMl`
- `symptomsNote`
Uso:
- prontidão;
- risco de fadiga;
- contexto para batimentos altos;
- hidratação estimada.
### 4. Pós-treino
Campos por sessão:
- `postWorkoutRpe` escala 1–10
- `postWorkoutFatigue` escala 1–5
- `postWorkoutSoreness` escala 1–5
- `postWorkoutWeightKg`
- `postWorkoutNote`
Uso:
- carga subjetiva;
- perda hídrica;
- recuperação;
- comparação entre percepção e batimentos.
## Calculations — P0
### 1. IMC
Entrada:
- peso
- altura
Resultado:
- `bmi`
- faixa textual simples
### 2. Reserva cardíaca
Entrada:
- limite cardíaco real ou estimado
- FC repouso
Resultado:
- `heartRateReserve`
### 3. Zonas por Karvonen
Entrada:
- limite cardíaco
- FC repouso
Resultado:
- zonas mais personalizadas para o atleta.
### 4. Score de treino
Entrada:
- duração da sessão
- BPM médio
- BPM pico
- tempo em zonas
- RPE pós-treino
Resultado:
- score 0–100
- rótulo: leve, moderado, intenso, extremo
### 5. Carga subjetiva
Entrada:
- RPE pós-treino
- duração em minutos
Resultado:
- `sessionLoad = RPE × durationMinutes`
### 6. Score de recuperação
Entrada:
- sono
- qualidade do sono
- energia antes
- fadiga antes
- dor muscular
- FC repouso opcional
Resultado:
- score 0–100
- rótulo: baixa, ok, boa, excelente
### 7. Hidratação estimada
Entrada:
- peso antes
- peso depois
- água ingerida
Resultado:
- perda de peso no treino
- perda hídrica estimada
- alerta se perda relativa for alta
### 8. Tempo em zona de luta
Entrada:
- samples de BPM da sessão
- zonas cardíacas
Resultado:
- tempo em zona alta/intensa
- percentual do treino em zona de luta
### 9. Alertas de segurança esportiva
Entrada:
- sintomas
- fadiga alta
- sono ruim
- dor alta
- esforço cardíaco alto
Resultado:
- mensagens de atenção no app.
Exemplos:
- “Sono baixo + fadiga alta: considere treino técnico ou leve.”
- “Perda de peso alta no treino: reponha líquidos.”
- “Esforço muito alto para uma recuperação baixa.”
## UI/UX
### Tela Perfil
Adicionar seções recolhíveis ou cards:
1. Básico
2. Cardiovascular
3. Luta
Evitar formulário gigante em uma tela só.
### Tela Check-in
Fluxo simples antes de iniciar sessão:
- energia
- fadiga
- dor
- sono
- peso
- água
- sintomas
Pode ser card ou bottom sheet antes de iniciar treino.
### Tela Pós-treino
Após encerrar sessão:
- RPE
- fadiga
- dor
- peso pós
- observação
### Tela Insights do Lutador
Primeira versão com cards:
- Score do treino
- Recuperação
- Hidratação
- Tempo em zona de luta
- Carga subjetiva
- Alertas
## Project Structure
Novos arquivos prováveis:
```text
app/src/main/java/com/healthtracking/fightrate/domain/AthleteInsights.kt
app/src/main/java/com/healthtracking/fightrate/domain/ReadinessScore.kt
app/src/main/java/com/healthtracking/fightrate/domain/HydrationEstimate.kt
app/src/test/java/com/healthtracking/fightrate/domain/AthleteInsightsTest.kt
```
Arquivos existentes a alterar:
```text
AthleteProfile.kt
WorkoutSession.kt
HeartRateSampleStore.kt
LiveHeartRateUiState.kt
LiveHeartRateViewModel.kt
HomeScreen.kt
```
A criação de novos arquivos deve ser mínima e justificada por responsabilidade clara.
## Code Style
Exemplo esperado:
```kotlin
data class ReadinessInput(
val sleepHours: Double?,
val sleepQuality: Int?,
val energy: Int?,
val fatigue: Int?,
val soreness: Int?,
)
object ReadinessScoreCalculator {
fun calculate(input: ReadinessInput): ReadinessScore {
val score = 100
.minus(input.fatigue.orDefaultPenalty(multiplier = 8))
.minus(input.soreness.orDefaultPenalty(multiplier = 6))
.plus(input.energy.orDefaultBonus(multiplier = 5))
.coerceIn(0, 100)
return ReadinessScore(value = score)
}
}
```
Convenções:
- código em inglês;
- UI em PT-BR;
- cálculo puro no domínio;
- Compose apenas renderiza estado;
- evitar mágica sem teste.
## Testing Strategy
Testar com JUnit:
- IMC
- reserva cardíaca
- Karvonen
- score de recuperação
- carga subjetiva
- hidratação estimada
- tempo em zona de luta
- alertas esportivos
Comandos:
```bash
./gradlew :app:testDebugUnitTest --tests "*AthleteInsights*"
./gradlew :app:testDebugUnitTest :app:assembleDebug
```
## Boundaries
### Always
- Criar cálculo no domínio antes da UI.
- Usar testes para cálculo.
- Manter campos opcionais quando possível.
- Explicar que cálculos são estimativas esportivas.
- Reaproveitar `AthleteProfile`, `WorkoutSession`, `HeartRateSampleStore`.
- Salvar dados localmente.
### Ask first
- Adicionar dependência nova.
- Adicionar Health Connect.
- Criar tela nova separada se puder ser card inicialmente.
- Fazer alteração destrutiva no banco.
- Criar cálculo médico sensível.
- Coletar dados muito pessoais sem justificativa.
### Never
- Apresentar diagnóstico médico.
- Bloquear treino como decisão médica.
- Criar formulário gigante difícil de usar.
- Adicionar campos que não alimentam nenhum cálculo.
- Criar código morto para métricas futuras.
- Misturar todos os cálculos dentro da UI.
## Success Criteria
- Usuário consegue preencher dados P0 sem fricção excessiva.
- App calcula pelo menos:
- IMC;
- reserva cardíaca;
- score de treino;
- carga subjetiva;
- score de recuperação;
- hidratação estimada;
- tempo em zona de luta.
- Dados ficam persistidos localmente.
- Insights aparecem em PT-BR.
- Cálculos puros têm testes.
- Build final passa.
- Nenhuma dependência nova é adicionada sem aprovação.
## Decisions Approved
1. Check-in pré-treino será obrigatório antes de iniciar uma sessão.
2. Insights será uma nova aba no menu inferior.
3. Sexo biológico será coletado como `Masculino` ou `Feminino`.
4. Energia, fadiga, dor e sono usarão escala 0–10.
5. Campos avançados devem poder ficar ocultos/expandidos para manter a interface limpa.
## BLE Reliability and Battery Plan
### Objective
A leitura do sensor deve continuar enquanto o app estiver em treino, inclusive com tela bloqueada, salvo quando:
1. o usuário desconectar manualmente;
2. o usuário encerrar o treino;
3. o Android remover o processo por condição extrema fora do controle do app.
Quando houver queda por distância/sinal, o serviço deve tentar reconectar automaticamente quando o usuário se aproximar novamente. Se o usuário desconectar manualmente, o app não deve reconectar sozinho.
### BLE Rules
- O `HeartRateForegroundService` continua sendo dono da conexão BLE.
- O ViewModel não deve abrir conexão direta com o sensor.
- Toda queda inesperada deve ser registrada como estado de conexão e mensagem visível.
- Desconexão manual deve salvar uma flag `manualDisconnect = true`.
- Queda inesperada deve salvar `manualDisconnect = false` e iniciar retry/backoff.
- O último sensor selecionado deve ser preservado para reconexão automática.
### Reconnect Strategy
Estados sugeridos:
```text
Idle
Connecting
Connected
LostSignal
RetryWaiting
ManualDisconnected
Failed
```
Backoff conservador:
```text
1ª tentativa: 2s
2ª tentativa: 5s
3ª tentativa: 10s
4ª tentativa em diante: 30s
```
Regras:
- Não tentar reconectar se `manualDisconnect = true`.
- Não tentar reconectar se Bluetooth estiver desligado; aguardar próximo ciclo.
- Não tentar reconectar sem permissão Bluetooth.
- Não fazer scan agressivo contínuo.
- Para sensor já conhecido, tentar reconectar por `deviceId` direto antes de scan.
- Scan só deve ser usado quando não houver deviceId válido.
### Battery Strategy
Para menor consumo:
- Foreground service único durante sessão.
- Sem polling pesado no ViewModel a cada batimento.
- SQLite insert apenas por amostra recebida.
- Notificação com throttle.
- Reconexão com backoff, nunca loop apertado.
- Metadata do sensor lida na conexão e depois em intervalo longo, não a cada amostra.
- Gráficos atualizam pelo estado recebido, sem reconsultar o banco inteiro.
- Evitar wake locks permanentes. Usar foreground service e orientação de ignorar otimização de bateria.
### Acceptance BLE
- Tela bloqueada não interrompe leitura durante treino.
- Distância/sinal perdido mostra status de sensor perdido.
- Ao aproximar novamente, o app tenta reconectar sozinho.
- Se usuário tocar em Desconectar, reconexão automática fica desativada.
- Se usuário escolher o sensor/iniciar novamente, reconexão automática volta a valer.
- Build passa.
## Recommended First Implementation Plan
Após aprovação desta spec:
1. Criar domínio puro de insights e testes.
2. Expandir modelo de perfil e sessão com campos P0.
3. Adicionar migração SQLite aditiva.
4. Criar UI de Perfil Avançado com seções expansíveis.
5. Criar check-in pré-treino obrigatório antes de iniciar sessão.
6. Criar pós-treino ao encerrar sessão.
7. Criar nova aba Insights com cards básicos.
8. Melhorar BLE com desconexão manual vs queda inesperada, reconexão automática e backoff.
9. Rodar build/test completo.
---
# Spec Expansion: Gráficos, Janela de Treino e Relatório Científico
## Objective
Transformar a sessão do FightRate em uma janela de coleta confiável com relatório pós-treino detalhado, gráficos Vico mais legíveis/interativos e métricas esportivas fundamentadas em frequência cardíaca real do sensor BLE.
O objetivo é interpretação esportiva para lutas, não diagnóstico médico. Toda métrica estimada deve ser rotulada como estimativa.
## Research Summary
Fontes consultadas antes da implementação:
1. Cole et al., NEJM 1999, PubMed: `https://pubmed.ncbi.nlm.nih.gov/10536127/`
- HR Recovery é queda da FC do pico para 1 minuto pós-exercício.
- Queda <= 12 bpm em 1 min foi considerada anormal no estudo clínico.
2. Brubaker & Kitzman, Circulation review, PMC: `https://pmc.ncbi.nlm.nih.gov/articles/PMC3065291/`
- Resposta cronotrópica é capacidade de aumentar FC com demanda.
- Critérios clínicos exigem teste progressivo e contexto; no app usar só interpretação esportiva.
- HRR 1 min < 12 bpm, 2 min < 42 bpm aparecem como thresholds de risco em contexto clínico, mas o app não diagnostica.
3. Uth et al., Eur J Appl Physiol 2004, PubMed: `https://pubmed.ncbi.nlm.nih.gov/14624296/`
- VO2max estimado pode usar `15.3 * (HRmax / HRrest)` em população treinada.
- Aplicabilidade fora desse perfil deve ser tratada como aproximação.
4. Boxing HR response, PMC: `https://pmc.ncbi.nlm.nih.gov/articles/PMC3871409/`
- Boxe simulado passou grande parte acima de VT2; HR aumenta por round.
- Reforça foco em tempo em zonas altas, recuperação entre rounds e drift.
5. Muay Thai physiological response, Ingenta: `https://www.ingentaconnect.com/content/uwic/ujpa/2012/00000012/00000003/art00004`
- Muay Thai competitivo teve FC média próxima do máximo e alto estresse cardiovascular.
6. Edwards/TRIMP summaries: `https://www.trainingimpulse.com/edwards-trimp` e `https://journals.lww.com/nsca-scj/fulltext/2018/04000/quantification_of_training_load_in_endurance.12.aspx`
- Edwards TRIMP é prático por zonas, mas coeficientes são arbitrários.
- Banister usa reserva cardíaca e ponderação exponencial; ambos devem ser apresentados como carga interna estimada.
7. HRV em Muay Thai, PMC: `https://pmc.ncbi.nlm.nih.gov/articles/PMC12143277/`
- RMSSD/SDNN exigem RR/NN intervals confiáveis. O app hoje coleta BPM, portanto HRV fica fora do escopo até o parser/persistência salvarem RR intervals.
## Implementable Metrics From Current Data
Viáveis agora:
- duração total da sessão;
- duração ativa aproximada e pausada;
- BPM inicial/final/mínimo/médio/máximo;
- desvio padrão;
- qualidade dos dados por densidade, gaps e duração;
- tempo e percentual por zona;
- tempo em zona de luta, RedLine e Limite;
- maior sequência contínua em zona intensa;
- picos e quedas relevantes;
- HR Recovery 1min/2min quando houver amostras pós-pico;
- drift primeira metade vs segunda metade;
- slope de BPM por minuto;
- resposta cronotrópica inicial aproximada;
- tempo até zona vigorosa/luta;
- Edwards TRIMP;
- Banister TRIMP quando houver FC repouso e limite cardíaco;
- carga subjetiva RPE x duração;
- VO2max estimado quando houver FC repouso e limite cardíaco;
- hidratação estimada com peso pré/pós e água;
- interpretação cruzada com energy/fatigue/soreness/sleep/symptoms/RPE.
Não viável agora sem novos dados:
- HRV RMSSD/SDNN/pNN50 real;
- diagnóstico de arritmia;
- limiar ventilatório real;
- VO2 real;
- economia cardíaca precisa entre sessões sem normalizar tipo/duração/intensidade.
## Data Collection / Time Window
Reaproveitar `workout_sessions`:
- `startedAtMillis` define início do range.
- `endedAtMillis` define fim do range.
- `session_id` em `heart_rate_samples` associa amostra à sessão ativa.
- Ao finalizar, buscar amostras por `session_id`; fallback por intervalo se necessário.
- Foreground service continua dono do BLE.
- ViewModel não assume BLE.
- Migração SQLite só aditiva se relatório persistido exigir cache.
## Domain Design
Criar ou expandir domínio puro para relatório:
- `TrainingReportMetrics`
- `SessionReportBuilder`
- `DataQualityAnalyzer`
- `ZoneDistributionCalculator`
- `HeartRateRecoveryCalculator`
- `CardiacDriftCalculator`
- `ChronotropicResponseCalculator`
- `TrainingLoadCalculator`
- `HydrationTrainingInterpreter`
Business rules fora do Compose.
## UI / Charts
Reaproveitar `HeartRateLineChart`, `FightCard`, `MetricTile`.
Adicionar:
- chart summary pills de mínimo/médio/máximo;
- legenda de zonas;
- destaque textual para tempo em zona de luta/limite;
- estados profissionais para poucos dados;
- leitura de eixo X por tempo real;
- relatório em seções expansíveis:
1. Resumo do treino;
2. Gráfico principal;
3. Zonas cardíacas;
4. Recuperação;
5. Carga de treino;
6. Drift e fadiga;
7. Hidratação;
8. Comparação com histórico;
9. Alertas e interpretação.
Evitar Canvas customizado e dependências novas.
## Success Criteria
- Spec atualizada antes do código.
- Código existente auditado e reaproveitado.
- Testes JUnit cobrem todos os cálculos de domínio novos.
- Sessão finalizada gera relatório com amostras do range correto.
- Histórico permite abrir relatório de sessão.
- UI deixa claro estimativa esportiva vs dado medido.
- BLE continua no foreground service.
- Sem migração destrutiva.
- `./gradlew :app:testDebugUnitTest :app:assembleDebug` termina com `BUILD SUCCESSFUL`.
- APK gerado e tentativa de `telegram_attach(localPath)` realizada.