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

17 KiB
Raw Blame History

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:

./gradlew :app:testDebugUnitTest :app:assembleDebug

Teste unitário focado:

./gradlew :app:testDebugUnitTest --tests "*AthleteInsights*"

Compilação rápida:

./gradlew :app:compileDebugKotlin

Instalação debug:

./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:

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:

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:

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:

./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:

Idle
Connecting
Connected
LostSignal
RetryWaiting
ManualDisconnected
Failed

Backoff conservador:

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.

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.