feat(components): ActionButton stopAlert + typography type fixes
This commit is contained in:
1 parent
2c51fd2623
commit
bbe2919c2c
89 files changed
+75993
-9961
No files matched your search
@@ -0,0 +1,691 @@
|
||||
# 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.
|
||||
Reference in new issue
Block a user