Files
HealthTracking/docs/superpowers/plans/2026-06-09-fightrate-data-first-charts-history-redesign.md
T

7.0 KiB
Raw Blame History

FightRate — Plano Data-First para histórico, gráficos e UI profissional

Situação crítica

O feedback atual mostra dois bugs de produto, não apenas problema visual:

  1. O gráfico tem espaço vazio demais e exige rolar horizontalmente por muito tempo até encontrar leituras.
  2. O histórico não está confiável: dados parecem não salvar ou não ficam acessíveis depois.

Conclusão: dados e persistência devem voltar a ser prioridade absoluta antes de polimento visual.

Objetivo

Transformar o FightRate em um app data-first:

  • Cada batimento recebido deve ser persistido localmente.
  • Cada treino deve ter uma janela temporal confiável.
  • Histórico deve mostrar dados reais recuperáveis.
  • Gráficos devem usar domínio baseado apenas nas amostras reais disponíveis.
  • Não pode existir scroll infinito/área vazia até achar leitura.
  • Interface deve priorizar dados e navegação histórica, seguindo o design system Combat Lab.

Skills aplicadas

  • fightrate-quality-loop: spec → auditoria → implementação em fatias → build.
  • systematic-debugging: encontrar causa raiz antes de corrigir.
  • test-driven-development: criar testes de regressão para domínio de gráfico/histórico.
  • design-system e ui-ux-pro-max: estado vazio útil, chart/data UX, consistência visual.

Hipóteses a investigar

H1 — Domínio X do Vico está incluindo janela cheia, não amostras reais

Sintoma: usuário rola para a direita “para sempre” até encontrar leituras.

Possível causa:

  • O gráfico usa windowStartMillis/windowEndMillis grandes, mas as amostras estão concentradas em pequeno trecho.
  • O X é calculado relativo à janela selecionada, então se a leitura está no fim da janela, sobra um enorme vazio à esquerda/direita.
  • O scroll/zoom inicial pode estar mostrando início/fim errado.

Correção esperada:

  • Domínio padrão do gráfico deve ser min(sample.timestamp) → max(sample.timestamp).
  • A janela selecionada filtra dados, mas não força o domínio visual a incluir todo o período vazio.
  • Exibir texto com a janela consultada e o intervalo real encontrado.

H2 — Histórico busca janela errada ou estado não atualiza após persistência

Sintoma: dados históricos não aparecem/salvam.

Possíveis causas:

  • publishLiveSample salva, mas histórico não recarrega após cada nova amostra.
  • selectedPeriod usa uma janela curta ou errada.
  • Sessão finalizada tem samples com sessionId nulo.
  • finishCurrentSession não associa amostras sem sessão dentro da janela.
  • UI exibe historySamples, mas dados reais ficam apenas em visibleSamples/dailySamples.

Correções esperadas:

  • Confirmar que HeartRateSampleStore.save recebe sessionId ativo.
  • Confirmar que samplesForSession funciona depois do finish.
  • Confirmar que samplesBetween(start, end) recupera dados persistidos.
  • Atualizar estado de histórico depois de salvar amostra e depois de finalizar treino.

H3 — UI não oferece navegação histórica suficiente

Sintoma: “os dados devem poder ser vistos de qualquer maneira”.

Correção esperada:

  • Histórico com modos claros:
    • Últimos 10 min
    • Última hora
    • Hoje
    • Sessão atual/finalizada
  • Se janela consultada não tem dados, mostrar “nenhum dado nessa janela” e sugerir janela que tem dados.
  • Se existe sessão finalizada, exibir relatório e gráfico daquela sessão.

Arquitetura desejada

Domínio puro novo/revisado

Criar ChartDataWindow.kt se necessário.

Responsabilidades:

  • Receber samples + janela consultada.
  • Retornar:
    • visibleSamples: somente amostras reais e úteis.
    • dataStartMillis / dataEndMillis: domínio real do gráfico.
    • queryStartMillis / queryEndMillis: janela consultada.
    • status: Empty, SinglePoint, Ready.
    • resumo: duração real, média, min, max, densidade.
  • Não depender de Compose/Vico/Android.

Persistência

Reutilizar HeartRateSampleStore.

Necessário auditar/corrigir:

  • insert de samples;
  • active session id;
  • associação de sample com session id;
  • queries por sessão;
  • queries por período;
  • refresh após write.

Não fazer migração destrutiva.

ViewModel

  • Não mover BLE para ViewModel.
  • Garantir que o estado de histórico seja atualizado após persistência.
  • Expor chart windows já preparados para UI.
  • Evitar que UI calcule regras complexas.

UI / Gráfico

  • HeartRateLineChart deve receber domínio real de dados.
  • X deve ser relativo a dataStartMillis, não ao começo da janela vazia.
  • Se samples.size < 2, não chamar Vico.
  • Mostrar estado vazio editorial.
  • Mostrar uma linha de contexto:
    • “Consultado: Hoje”
    • “Dados encontrados: 14:03–14:17”
  • Zoom/scroll habilitado, mas sem espaço fantasma.
  • Não usar Canvas custom chart.

Testes obrigatórios

ChartDataWindowTest

  1. Janela grande com dados no fim não gera domínio vazio gigante.
  2. Sem dados retorna Empty.
  3. Um ponto retorna SinglePoint.
  4. Dados fora de ordem são ordenados.
  5. Dados filtrados preservam timestamp real.
  6. Downsampling mantém primeiro e último ponto.

Store/persistência

Se for viável em teste local unitário:

  1. Salvar sample e recuperar por período.
  2. Salvar sample em sessão ativa e recuperar por session id.
  3. Finalizar sessão e recuperar samples da sessão.

Se não for viável sem Robolectric/instrumented test, adicionar diagnóstico via código e validar pelo fluxo ViewModel/build.

Implementação em fatias

Fase 1 — Auditoria e causa raiz

  • Ler HeartRateSampleStore.
  • Ler LiveHeartRateViewModel.
  • Ler LiveHeartRateUiState.
  • Ler HomeScreen chart/history.
  • Localizar onde sample é salvo.
  • Localizar onde historySamples é atualizado.
  • Localizar como Vico define X/domain.

Fase 2 — Domínio de janela de gráfico

  • Criar ChartDataWindow.kt.
  • Criar ChartDataWindowTest.kt.
  • Garantir domínio real dataStartMillis→dataEndMillis.
  • Garantir estado Empty/SinglePoint/Ready.

Fase 3 — Persistência e refresh

  • Corrigir sample/session association se necessário.
  • Corrigir reload de histórico depois de salvar/finalizar.
  • Adicionar método de query se faltar.

Fase 4 — Gráfico profissional

  • Atualizar HeartRateLineChart para usar domínio real.
  • Remover scroll fantasma.
  • Adicionar zoom/scroll Vico com domínio real.
  • Remover render de gráfico vazio.
  • Mostrar resumo consultado vs encontrado.

Fase 5 — Interface data-first

  • Histórico como centro de dados, não card secundário.
  • Sessões e dados recentes com hierarquia clara.
  • Evitar dezenas de cards iguais.
  • Estados vazios úteis e específicos.

Fase 6 — Validação final

  • ./gradlew :app:testDebugUnitTest :app:assembleDebug
  • Atualizar Obsidian roadmap.
  • Enviar APK Telegram.

Critérios de sucesso

  • Usuário abre Histórico e vê dados reais sem procurar em espaço vazio.
  • O gráfico começa/termina no intervalo real dos dados encontrados.
  • Sem dados: nenhum gráfico é desenhado.
  • Dados salvos são recuperáveis por período e por sessão.
  • Testes de domínio passam.
  • Build completo passa.
  • APK enviado.