WC26 Pool
Bolão da Copa com dois modos de jogo — palpites por partida e bracket do mata-mata — que substituiu um fluxo manual inteiro no WhatsApp.

Visão Geral
Seis amigos gerenciavam um bolão da Copa no WhatsApp: alguém postava os jogos do dia, cada um respondia com seus palpites e outra pessoa calculava os pontos na mão após cada partida. O WC26 Pool substituiu esse processo inteiro com um app web e dois modos de jogo: palpites de placar por partida com submissão imutável, e um bracket Pick'em onde cada participante escolhe os vencedores de cada fase eliminatória até o campeão — tudo alimentando um ranking unificado.
Funcionalidades
- Agenda de jogos do dia com placar ao vivo atualizado em tempo real
- Palpites por partida com submissão imutável — bloqueado após envio
- Lógica de revelação: palpites ficam ocultos até todos os 6 enviarem ou o jogo começar
- Pick'em bracket: escolha o vencedor de cada rodada do mata-mata até o campeão antes de um prazo fixo
- Validação de consistência do bracket: um time só pode avançar se foi escolhido na rodada anterior
- Pontuação lazy por slot: cada pick é avaliado apenas quando a partida específica daquele time encerra
- Ranking ao vivo unindo pontos dos dois modos em uma única tabela
- Calendário dos próximos 7 dias de jogos agrupados por data
- Suporte a fase eliminatória com palpites de prorrogação e pênaltis
- Design mobile-first
O Desafio
Os dois maiores desafios foram o gerenciamento de rate limit — seis usuários consultando uma API de futebol gratuita simultaneamente consumiriam a cota em minutos — e adaptar o sistema de pontuação no meio do torneio quando o grupo adicionou regras para a fase eliminatória que exigiam rastrear duração da partida e resultado nos pênaltis separadamente do tempo normal. O bracket Pick'em introduziu uma terceira restrição: pontuar os picks de forma lazy por slot, e não todos de uma vez, para refletir com precisão que o destino de cada time é determinado por uma partida diferente em um momento diferente.
Regras de Pontuação
Fase de Grupos
| 2 pts | Placar exato |
| 1 pt | Resultado correto (vitória / empate / derrota) |
| 0 pts | Resultado errado |
Fase Eliminatória (Oitavas em diante)
| 3 pts | Placar exato (tempo normal + prorrogação) + vencedor nos pênaltis correto |
| 2 pts | Placar exato (tempo normal + prorrogação) |
| 1 pt | Time classificado correto, independente de como |
| 0 pts | Time classificado errado |
Apenas o nível mais alto aplicável é concedido por partida — não é cumulativo. Ao palpitar empate na fase eliminatória, selecionar o vencedor nos pênaltis é obrigatório.
Principais Decisões Técnicas
Sem sistema de login
Seis participantes conhecidos tornam a autenticação desnecessária — gerenciar senhas ou fluxos OAuth seria exagero para um grupo fechado. A solução foi seleção de nome na primeira visita, persistida no localStorage com opção de troca. Zero fricção, zero cadastro.
Backend como gateway para dados de futebol
O frontend nunca chama a API de futebol diretamente. Um BackgroundService do ASP.NET Core faz polling da API externa em um intervalo inteligente e armazena tudo no PostgreSQL. Os seis usuários consultam o backend, não a API com rate limit. Os intervalos se adaptam ao contexto: a cada 20 minutos quando não há jogo próximo, a cada 2 minutos quando o kickoff está em menos de 30 minutos, e a cada 1 minuto com jogo em andamento.
Palpites imutáveis
Após enviado, um palpite não pode ser alterado — replicando a dinâmica do WhatsApp. Garantido no banco com uma constraint única em (ParticipantId, MatchId). Submissões duplicadas retornam 409. A interface bloqueia o formulário imediatamente no envio.
Adaptação da fase eliminatória no meio do torneio
As regras de pontuação foram estendidas durante o torneio sem quebrar dados existentes. O sistema foi atualizado para rastrear duração (REGULAR / EXTRA_TIME / PENALTY_SHOOTOUT), regularTimeScore e penaltyScore como campos separados. O serviço de pontuação divide a lógica pelo campo stage da partida, então jogos da fase de grupos e eliminatórios são calculados independentemente.
Pick'em bracket com pontuação lazy por slot
O bracket armazena 7 picks por participante (4 times das quartas, 2 semifinalistas, 1 campeão). Cada pick é avaliado de forma independente quando o time que ele referencia joga — não quando o bracket é fechado. O PickemScoringService é acionado após cada resultado confirmado, verifica quais picks referenciam aquele time e aquela rodada, e propaga apenas o delta para o TotalPoints. Isso evita dupla-contagem entre chamadas sucessivas de scoring e mantém o ranking preciso em qualquer momento do torneio.
Resultados
O app foi usado ativamente por todos os 6 participantes durante toda a Copa do Mundo de 2026. Os palpites por partida rodaram da fase de grupos até a final; o bracket Pick'em foi lançado nas quartas de final com prazo e pontuação progressiva. Os dois modos alimentaram o mesmo ranking sem conflitos.