Skip to content

Practice/Fatia 3 — Contra seu ghost (PB): replay do melhor run em localStorage #83

Open

Description

@caioross

Contexto

Fatia 3 do epic #24 (Practice/Solo mode §V.5). Depois do Treino Livre (#25) e do modo contra bots (fatia 2), o próximo degrau de retenção é competir contra o próprio recorde — sem precisar de login/servidor (produto é sem cadastro), um "ghost" replica o melhor run já feito naquela combinação linguagem+dificuldade.

Escopo

  • Ao terminar um treino em PracticeView.tsx com um resultado melhor que o PB salvo (ou sem PB ainda) para a combinação language+difficulty, gravar um replay leve em localStorage: sequência de amostras { tMs, progress } do run (não precisa ser frame-a-frame — poucas amostras por segundo bastam para reconstituir uma curva suave).
  • Nos treinos seguintes na mesma combinação, se existir PB salvo, reproduzir o ghost como uma segunda barra/trilha de progresso avançando conforme o replay gravado, em paralelo ao jogador (mesmo startedAt).
  • Tela de conclusão mostra jogador vs ghost (bateu o PB? por quanto?) e, se bateu, substitui o PB salvo.
  • Chave de storage isolada por language+difficulty (ex.: coderacer:pb:<language>:<difficulty>); sem PII, só métricas + curva de progresso.

Acceptance criteria (verificáveis)

  • Primeiro treino numa combinação nova → grava PB automaticamente (sem UI extra, best-effort).
  • Segundo treino na mesma combinação → ghost do PB visível e sincronizado ao startedAt do jogador.
  • Run que bate o PB → localStorage atualizado com o novo replay; run que não bate → PB antigo preservado.
  • Tela de conclusão comunica claramente o resultado (bateu/não bateu o PB, diferença de WPM/tempo).
  • Falha de localStorage (indisponível/quota) é best-effort silencioso — nunca quebra o treino (mesmo padrão defensivo de localStorage.getItem já usado em RoomView.tsx/NameForm).
  • Zero chamada a /api/rooms/Supabase — dado fica só no navegador do jogador.
  • pnpm typecheck + pnpm build verdes.

Dica de abordagem

Reuse o formato de progresso que a fatia 2 (bot) já vai estabelecer para a "segunda trilha" visual, se a fatia 2 for puxada antes — dá pra compartilhar o componente de trilha fantasma entre bot e ghost (progresso ao longo do tempo é a mesma forma de dado). Funções de amostragem/reconstrução do replay devem ser puras e testáveis (Vitest), como os builders de src/lib/room.ts.

Refs: spec docs/UI-AAA-OVERHAUL.md §V.5 (modo 2, "contra seu ghost (PB)"); epic #24; Treino Livre atual em src/components/PracticeView.tsx.

Activity

  1. added
    P2Prioridade normal
    area:engineMotor de digitação, WPM, precisão, anti-cheat
    area:uiInterface, design system, animação, game feel
    on Jul 26, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    P2Prioridade normalarea:engineMotor de digitação, WPM, precisão, anti-cheatarea:uiInterface, design system, animação, game feel

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions