## PR-3 — Ranking geral do bolão

**PRD:** `docs/prd/pontuacao-e-ranking.md`

**Como** participante, **quero** ver a classificação geral do bolão, **para**
saber onde eu estou sem depender de o admin publicar a planilha.

**Prioridade:** Must — é o segundo item da prioridade declarada na Fase 1.

**Critérios de aceite:**

- Dado que existem rodadas apuradas, quando abro o ranking geral, então vejo
  os participantes ordenados pela soma dos pontos, com a posição de cada um.
- Dado que abro o ranking, então **minha posição fica identificável sem eu
  rolar a lista** até me achar.
- Dado que o bolão tem muitos participantes, quando abro o ranking, então ele
  carrega paginado ou com scroll, sem travar.
- Dado que nenhuma rodada foi apurada ainda, então o ranking mostra todos com
  zero e uma mensagem útil, não uma tela vazia.
- Dado que tento ver o ranking de um bolão do qual não participo, então a
  requisição é recusada.

**Tasks:**

_Backend_
- [x] `BE-1` Endpoint de ranking geral com soma de pontos por participante e posição (depende de PR-1 BE-3)
- [x] `BE-2` Paginação do ranking (depende de BE-1)
- [x] `BE-3` Autorização: só participante do bolão vê o ranking (depende de BE-1)
- [x] `BE-4` Evitar consulta N+1 ao montar o ranking com dados do participante

_Mobile_
- [x] `FE-1` Tela de ranking geral com destaque da minha posição (depende de BE-1)
- [x] `FE-2` Estados: carregando, bolão sem rodada apurada, erro com retry
- [x] `FE-3` Paginação ou scroll infinito (depende de BE-2)

_QA_
- [x] `QA-1` Escrever o plano de casos de teste a partir desta story
- [x] `QA-2` Executar o plano com 0, 1 e muitos participantes, e conferindo que o total bate com PR-2

**Riscos/Dependências:**

- Depende de PR-1 e do desempate (PR-5) para ordenar empatados corretamente —
  **até PR-5 existir, empate no ranking fica com ordem indefinida.**
- Ranking é endpoint agregado: não pode trazer palpite de jogo não terminado
  (PP-7 BE-3).

- **06/08:** scroll infinito, buscando a página seguinte um pouco **antes** do
  fim para a rolagem não parar em branco esperando rede. O app pedia sempre a
  primeira página (50), então num bolão de empresa quem estava da metade para
  baixo simplesmente não aparecia.
- Dois cuidados com teste: a lista **não** pede página quando já está completa
  (pedir página vazia para sempre é o erro clássico de scroll infinito), e falha
  ao paginar mostra o motivo **sem apagar** o que já está na tela.

- **07/08 — QA:** plano em `docs/testes/PR-3-plano.md`, execução em
  `docs/testes/PR-3-execucao.md` (**12/12 ✅**). Três casos novos.
- **`BE-4` (sem N+1) passou a ter teste de verdade:** asserir o resultado do
  ranking nunca pega N+1 — a lista sai idêntica, só mais devagar. O caso monta o
  serviço com um Prisma que **conta chamadas** e compara 3 × 60 participantes:
  mesmo número de consultas, e ≤ 4. Acrescentar uma busca de nome por linha fica
  vermelho na hora (`src/ranking/pr-3-plano.spec.ts`).
