CoOp:Anything
Search any game and see how much of it you can play with friends: every co-op mod, its stage, quality and community rating.
A liga oficial de Beyblade de Londrina.
Translation pending
GamesTypeScript · PLpgSQLGitHub @JBento7OnlineOwner unconfirmed
Have you tried it? One tap is enough. No sign-in needed.
No updates detected yet. GitHub releases will appear here.
Owners of public repositories under a personal GitHub account can sign in to verify ownership and manage the introduction themselves. No administrator approval is needed.
Sign in, generate a verification file, and commit it to this repository’s default branch within 30 minutes. Files on other branches or forks do not count. Then check the file below to manage the project without administrator approval. Keep the file to retain your access.
If needed, you will go to sign-in. After signing in, return here and press your chosen verification button again.
Run /nomorevibe verify in your project folder to verify ownership and manage the introduction yourself.
Verify in one minuteAsk about other verification options
The maker's introduction consists of the line above. Read the repository README for more details. Repository README ↗
Loading the full README.
Read the full README ↗Aplicação web para gestão de torneios de Beyblade X: cadastro de jogadores e beyblades, torneios (Suíço/mata-mata/grupos), placar ao vivo nas arenas (telão), painel do juiz, estatísticas, tiers e comunidade.
Documentação de manutenção. Mantenha este arquivo atualizado ao mexer no app.
| Camada | Tecnologia |
|---|---|
| Framework | Next.js 14 (App Router, Server + Client Components), TypeScript |
| UI | React 18, Tailwind CSS |
| Banco | PostgreSQL (Supabase, via pooler) |
| ORM | Prisma 5 |
| Auth | NextAuth v4 (estratégia JWT, sem sessão em banco) |
| Nodemailer (SMTP) — verificação de conta e reset de senha | |
| Deploy | Vercel (atual) |
| Tempo real | Polling adaptativo + WebRTC P2P (LAN) + Service Worker (offline) |
npm install # instala deps (roda prisma generate no postinstall)
cp .env.example .env # crie o .env (veja variáveis abaixo)
npm run dev # http://localhost:3000
Scripts:
| Script | O que faz |
|---|---|
npm run dev | Servidor de desenvolvimento |
npm run build | prisma generate + build de produção |
npm run start | Sobe o build de produção (next start) |
npm run lint | ESLint |
npm run db:generate | Regenera o Prisma Client |
npm run db:push | Aplica o schema no banco (dev) |
Antes de commitar mudanças que possam quebrar o build, sempre rode
npx tsc --noEmit e npm run build.
| Variável | Obrigatória | Descrição |
|---|---|---|
DATABASE_URL | ✅ | String de conexão do Postgres (pooler do Supabase) |
NEXTAUTH_SECRET | ✅ | Segredo do NextAuth (JWT) |
NEXTAUTH_URL | ✅ | URL pública do app (ex.: https://seuapp.vercel.app) |
DB_CONNECTION_LIMIT | ⛔ opcional | Limite de conexões do Prisma |
DB_POOL_TIMEOUT | ⛔ opcional | Timeout do pool |
SMTP_HOST / SMTP_PORT / SMTP_USER / SMTP_PASS / SMTP_FROM / SMTP_SECURE | para e-mail | Envio de verificação de conta e reset de senha |
O schema fica em prisma/schema.prisma. A aplicação de mudanças em produção
NÃO usa prisma migrate — usa SQL idempotente na rota GET/POST /api/migrate
(src/app/api/migrate/route.ts), que roda ADD COLUMN IF NOT EXISTS,
CREATE TABLE IF NOT EXISTS, CREATE INDEX IF NOT EXISTS, etc.
Fluxo ao alterar o schema:
prisma/schema.prisma.migrations em /api/migrate.npx prisma generate (ou npm run db:generate)./api/migrate uma vez para aplicar no banco.As tabelas Match, MatchPoint, MatchSet e TournamentParticipant têm
índices declarados no schema e criados via /api/migrate
(Match_tournamentId_round_idx, MatchPoint_matchId_idx, etc.). Sem eles, os
endpoints de polling do placar fazem varredura completa das tabelas e o app fica
lento. Sempre rode /api/migrate após o deploy.
src/
├── app/
│ ├── arena/ArenaDisplay.tsx # TELÃO da arena (placar ao vivo, vídeos)
│ ├── tournaments/[id]/
│ │ ├── page.tsx # Página do torneio (auto-cura do suíço no load)
│ │ ├── ScoreModal.tsx # PAINEL DO JUIZ (marcar pontos, iniciar batalha)
│ │ └── AdminMatchEditor.tsx # Ferramentas de admin (editar placar, avançar, etc.)
│ └── api/ # Rotas de API (ver abaixo)
├── lib/
│ ├── tournament-engine.ts # Motor dos torneios (suíço, byes, mata-mata, standings)
│ ├── arena-schedule.ts # Distribui partidas por arena + juízes
│ ├── arenaLink.ts # WebRTC P2P (juiz ↔ telão na LAN)
│ ├── arenaLayout.ts # Layout/posições dos elementos do telão
│ ├── scoring.ts # Pontuação por tipo de finish
│ ├── tiers.ts / meta-tiers.ts # Tiers dos bladers / meta das peças
│ ├── auth.ts # Config do NextAuth
│ └── prisma.ts # Instância do Prisma
└── components/
├── ServiceWorkerRegister.tsx # Registra o /sw.js
└── TierBadge.tsx
public/
├── sw.js # Service worker (offline)
├── countdown.mp4 # Vídeo de contagem/lançamento
└── finish-videos/*.mp4 # Vídeos por tipo de finish
/arena)[email protected] … [email protected], senha padrão
Arena123456, criados por /api/seed-arenas). O número da arena vem do e-mail./arena?n=1.ArenaLayout via /api/arena-layout./api/arena (placar completo) e /api/arena/tick (sinais leves de
contagem/finish/lançamento) são consultados pelo telão.ArenaDisplay.tsx.ScoreModal.tsx)ref (não por estado) em addPoint,
startBattle, playLaunchVideo — evita ponto/vídeo em dobro./countdown.mp4) e finishes (/finish-videos/*.mp4) tocam no telão.ArenaDisplay.tsx): contagem/lançamento 8s,
finish 6s — impede replay quando o mesmo evento chega pelo P2P e pelo poll.preload="metadata" (os vídeos são "preparados" no gesto de iniciar o telão,
não no load).Três camadas (ver conversa de manutenção):
public/sw.js, cache lbl-cache-v2): cache-first para
página/mídia, network-only para /api/* (dados nunca ficam velhos).
Precache só de assets leves; vídeos são cacheados no primeiro uso.arenaLink.ts + /api/arena/rtc): juiz e telão na mesma
rede conectam direto; contagem/finish/lançamento/placar chegam instantâneos
e seguem funcionando se a internet oscilar. Sinalização (troca de SDP) via o
servidor; depois flui P2P. O telão faz backoff na busca por par (4s ativo
→ 30s quando não há juiz na LAN → 15s conectado).Limite: é continuidade de exibição. O ponto só é gravado no banco quando a conexão volta (o P2P mantém o placar certo na tela enquanto isso).
tournament-engine.ts)ROUND_ROBIN. Nº de rodadas = ceil(log2(participantes))
(swissRoundCount). O mata-mata começa na rodada swissRounds + 1 — esse é
o limite usado em todo o motor (avanço e ranking final).scoring.ts): Spin 1 · Over 2 · Burst 2 · Extreme 3 ·
Misslaunch 1. O set fecha quando alguém atinge pointsToWinSet.| Campo | Significado | Alimenta |
|---|---|---|
totalPoints | Suíço: vitórias + byes. Outros formatos: soma dos pontos de batalha | Classificação do torneio |
wins / losses | Só partidas realmente jogadas (bye NÃO conta) | Tiers, win-rate, ranking global, estatísticas de carreira |
totalPoints → pontos de
batalha marcados → saldo (marcados − sofridos).isWalkover), que soma no totalPoints para ele não ser penalizado por
folgar — mas não entra em wins (não é vitória de carreira). Rodízio justo:
ninguém recebe 2 byes antes de todos receberem 1.generateSwissRound) — validadas por simulação
(25/24/13/9/7 jogadores, 200 execuções cada):
finalizeTournamentRanking): define placement e distribui
rankingPoints ao top 5 (100/70/50/30/10). O /rankings global soma os
dos torneios .| Botão | Rota | O que faz |
|---|---|---|
| Editar Placar | /api/admin/matches/[id]/set-score | Corrige pontos direto (sem resetar, sem tocar nas arenas) |
| Resetar | /api/admin/matches/[id]/reset | Zera a partida para reinserir pelo placar |
| Avançar Rodada | /api/admin/tournaments/[id]/advance-round | Gera a próxima rodada se travou |
| Remover Duplicadas | /api/admin/tournaments/[id]/dedupe-matches | Remove partidas duplicadas |
| Recalcular Classificação | /api/admin/tournaments/[id]/recalc-standings | Recomputa V/pontos de todos |
| Recalcular Ranking Final | /api/admin/tournaments/[id]/recalc-ranking | Refaz colocação + pontos de ranking (funciona em torneio já encerrado) |
| Verificar Partidas | /api/admin/tournaments/[id]/balance-matches | Confere se todos jogaram o mesmo nº e gera partidas de reposição (refaz o mata-mata se preciso) |
auth/[...nextauth], auth/register, auth/verify-email,
auth/forgot-password, auth/reset-password.tournaments, tournaments/[id] (+ join, start, finish,
reset, participants, finals-deck).matches/[id]/point, undo-point, countdown,
launch-video, onair, sides, deck-order, sets, wo.arena, arena/tick, arena/rtc, arena-layout.admin/tournaments/[id]/*, admin/matches/[id]/*, admin/users,
admin/beyparts, admin/announcements, etc.migrate (migrações), seed-arenas, seed-test-users.main/branch → build automático. npm run build roda prisma generate./api/migrate./api/arena roda os resolvers independentes em paralelo (Promise.all) e
cacheia imagens de BeyPart por instância (120s).<img> cru (sem next/image); public/liga.png é grande (~5 MB)
e só usada no certificado — candidata a otimização futura.onair) e se /api/migrate foi rodado./api/migrate criou os índices.rankingPointsadvanceSwissTournament / ensureSwissProgress gera a
próxima rodada ou o mata-mata quando a rodada atual termina. A página do
torneio chama ensureSwissProgress no load (com throttle de 15s) para
auto-curar casos em que a última partida fechou por um caminho que não avançou.generateSwissRound é idempotente (não duplica rodada).generatePlayoffBracket (top-N) + advanceSingleElimination.