Pitch: Como fiz um júri cego de memes que não dá pra comprar com seguidor (Bradley-Terry, Next.js e Stripe)
Há alguns meses comecei um projeto com uma pergunta simples: dá pra fazer uma competição de humor em que seguidor não ajuda? Em toda rede social, quem tem mais alcance ganha mais curtida, e isso não diz nada sobre quem é engraçado de verdade.
O resultado é o Fame War, um jogo diário de memes. Quero compartilhar as decisões técnicas, porque algumas foram menos óbvias do que eu esperava.
A mecânica
- Todo dia às 12h (horário de Brasília) sai um tema.
- Até as 20h, cada pessoa posta um meme (imagem, texto ou vídeo de até 60s).
- Um júri avalia os memes um por vez, sem nome e sem perfil: 😐, 🔥 ou 🤣.
- Às 23h sai o ranking nacional e cada um recebe seu percentil (top X%).
Problema 1: transformar "notas" em ranking justo
A média de notas não funciona. Tem jurado que dá 🔥 pra tudo e jurado que só dá 😐, e cada meme é visto por um subconjunto diferente de pessoas.
A solução foi tratar as notas como comparações. Dentro dos votos de cada jurado, um meme com nota maior "vence" os de nota menor (🤣 vence 🔥, que vence 😐). Com isso, quem marca tudo igual não gera comparação nenhuma, então não influencia o resultado, por construção, sem precisar de regra especial.
Essas vitórias alimentam um modelo Bradley-Terry, ajustado pelo algoritmo
P(i vence j) = s_i / (s_i + s_j)
a cada iteração:
s_i ← W_i / Σ_j ( n_ij / (s_i + s_j) )
W_i = vitórias ponderadas de i
n_ij = comparações entre i e j
Dois detalhes que fizeram diferença:
- Prior pequeno: um "empate virtual" contra um meme médio impede que quemu) vá para o infinito.
- Duas passadas: na primeira, calculo o consenso. Depois, meço quanto cada jurado concordou com ele e transformo isso num peso (de 0,5 a 1,5). Na segunda passada, o voto de quem
vota no aleatório pesa menos.
Por que três botões e não dois? Simulei as duas opções: com três níveis, 8 dosem no top 10; com dois, só 5. O 🤣 é o que separa o bom do genial no topo.
Problema 2: fraude
Num jogo com ranking, alguém sempre tenta combinar voto. As defesas que mais a
- Pares de controle: de vez em quando aparece um "meme" propositalmente ruiado naquele Drop.
- Voto rápido demais vale zero.
- Várias contas no mesmo aparelho dividem um único voto.
- Grupos na mesma rede que empurram o mesmo meme contra o consenso do resto do júri têm os votos anulados e revisados.
Problema 3: moderação de conteúdo gerado por usuário
Toda imagem, texto e quadro de vídeo passa por um modelo de linguagem (Claude Haiku) com saída estruturada antes de entrar no júri.
Uma lição: no começo eu pedia { allow, reason }, e o modelo às vezes recusava por motivos que eu tinha proibido explicitamente no prompt ("a foto não prova que a pessoa cumpriu o desafio"). O que resolveu foi trocar por um enum fechado de categorias. Se, o modelo não consegue recusar por ele. Restringir a saída funcionou melhor do que insistir na instrução.
Problema 4: dinheiro sem virar aposta
Eu queria que as pessoas pudessem ganhar dinheiro sem transformar o jogo em aposta. A regra que adotei: dinheiro nunca compra voto nem chance de vitória. Ele só circula em três lugares:
- Desafios pagos: um fã paga pra alguém fazer um desafio. A cobrança e o re Connect, e o valor fica retido até a prova. Se o fã contesta, um júri cegodecide: o criador ou o fã recebe 70%, a plataforma 20% e os jurados que votaram com a maioria 10%. - Presentes entre usuários.
- Fundo do Júri: 10% da parte da plataforma é dividido toda semana entre quem julgou, na proporção dos votos úteis (que passaram nos controles).
Testar isso me deu mais trabalho do que o resto. Tenho uma suíte que confere centavo por centavo cada fluxo: reembolso parcial, estorno, chargeback e semana paga duas vezes. Também tenho testes ponta a ponta que rodam contra produção com contas temporárias apagadas
Stack
- Next.js 16 (App Router) como PWA, MongoDB Atlas, S3
- Stripe com Connect
- Claude Haiku para moderação
- Resend para e-mail
- ffmpeg no container, para converter vídeo e gerar automaticamente o vídeo "T
- Tudo em Docker Compose numa instância EC2, com Caddy na frente
O que eu ainda não resolvi
Partida a frio. Um jogo de júri precisa de gente pra postar e gente pra julgar no mesmo dia. Meu atalho foi:
- encurtar a janela de postagem;
- criar contas oficiais identificadas ("Equipe Fame War") que postam memes, ma.
Pensei em bots que se passassem por pessoas e descartei: num lugar com dinheiro real envolvido, isso seria enganar quem joga.
Se você tiver experiência com partida a frio em produto social, ou críticas aoto ouvir.
O projeto está em famewar.com.br/?utm_source=tabnews&utm_medium=community