Como funciona um sorteio — um exemplo prático
Percorra um sorteio real do início ao fim: 1.000 comentários elegíveis, 3 vencedores, 9 reservas. Sem jargão, sem omissões.
O cenário
Imagine que o concurso terminou. Os comentários foram obtidos, os filtros do concurso foram aplicados e 1.000 participações são elegíveis. O prémio atribui 3 vencedores com 9 reservas, caso algum dos vencedores não possa ser contactado. Aqui está a probabilidade por participação — idêntica para cada um dos 1.000 comentários elegíveis, independentemente de quando foi publicado ou do comprimento do nome do participante.
| Resultado | Probabilidade para qualquer participação |
|---|---|
| Sorteado como vencedor principal (posições 1–3) | 3 em 1.000 — 0,30% |
| Sorteado como reserva (posições 4–12) | 9 em 1.000 — 0,90% |
| Sorteado para qualquer lugar vencedor | 12 em 1.000 — 1,20% |
Nada disto muda se o concurso tiver 444 comentários ou 444.444. O algoritmo é idêntico. Apenas o denominador varia.
Passo 1 — Recolher e filtrar as participações
A aplicação obtém todos os comentários da publicação do Facebook ou Instagram que ligou e aplica os filtros do concurso — duplicados, palavras bloqueadas, regras de antiguidade de conta, tudo o que foi configurado. O que sobrevive é o conjunto elegível. No nosso cenário são 1.000 comentários. Cada um tem uma linha na base de dados com um ID numérico único; esses 1.000 IDs são a base de todo o sorteio.
Passo 2 — Ordenar numa ordem canónica
Antes de qualquer aleatorização, a aplicação ordena os 1.000 IDs em ordem numérica crescente estrita — 17, 142, 203, 1058, 9941, … — e descarta a ordem em que chegaram. Porquê? Porque o Facebook pode devolver comentários em ordens diferentes consoante a paginação, hora do dia ou alterações no servidor. Se o sorteio utilizasse a ordem do Facebook, dois re-sorteios poderiam produzir vencedores diferentes a partir da mesma semente aleatória. Ordenar primeiro fixa a entrada numa lista canónica, de modo que a semente determina exclusivamente o resultado.
Passo 3 — Bloquear a lista de entrada com um hash SHA-256
A lista ordenada é processada pelo SHA-256 — uma função de hash criptográfico — produzindo uma impressão digital de 64 caracteres. A impressão digital, juntamente com a lista completa, é guardada no registo do concurso. A partir deste momento, qualquer pessoa que inspecione o concurso pode confirmar que a lista elegível não foi alterada: recalcule o hash da lista publicada, compare com a impressão digital guardada, e um único ID alterado produz um hash completamente diferente. Não existe forma de adicionar ou remover silenciosamente um comentário após este passo sem que fique visível.
Passo 4 — Gerar uma semente aleatória de 256 bits
A aplicação solicita à fonte de aleatoriedade criptográfica do sistema operativo (SecureRandom.hex(32)) 32 bytes de aleatoriedade imprevisível e armazena o resultado como uma cadeia hexadecimal de 64 caracteres — por exemplo a3f1…ce. 256 bits significa 2²⁵⁶ ≈ 10⁷⁷ sementes possíveis. Para contexto, o universo observável contém cerca de 10⁸⁰ átomos. Ninguém — nem o criador do concurso, nem o operador, nem um atacante externo — consegue prever ou adivinhar esta semente antes de ser gerada.
Passo 5 — Baralhar os 1.000 IDs e retirar os primeiros 12
A semente inicializa um motor de baralhamento determinístico, que executa um baralhamento de Fisher–Yates sobre os 1.000 IDs ordenados. Fisher–Yates é o algoritmo de baralhamento justo padrão — cada uma das 1.000 participações tem igual probabilidade de acabar em qualquer posição. Após o baralhamento, a aplicação retira as primeiras 12 participações do topo. Este é o passo de seleção na íntegra: baralhamento, corte em 12.
Passo 6 — Atribuir posições
As 12 participações selecionadas são percorridas em ordem. As três primeiras tornam-se vencedores 1, 2 e 3, e as nove seguintes tornam-se reservas 1 a 9. As restantes 988 participações elegíveis são registadas como não selecionadas. Os comentários filtrados anteriormente são marcados como desqualificados com o motivo específico pelo qual não eram elegíveis.
Passo 7 — Publicar tudo
Por fim, a aplicação guarda cinco elementos de evidência no registo do concurso — todos acessíveis publicamente. Sem eles, o resultado seria uma caixa negra. Com eles, qualquer pessoa pode reproduzir o sorteio completo em casa e confirmar que os vencedores publicados são os únicos vencedores que a semente poderia ter produzido.
O que é publicado em cada sorteio
Cada um destes elementos é armazenado no concurso e exposto através das páginas públicas de verificação. Em conjunto tornam o sorteio totalmente reproduzível — mesmas entradas, mesmas saídas, sempre.
- A semente aleatória de 256 bits — a cadeia hexadecimal de 64 caracteres do Passo 4.
- A lista ordenada de IDs elegíveis — todos os 1.000 IDs do Passo 2, em ordem canónica.
- A impressão digital SHA-256 dos IDs — o hash de 64 caracteres do Passo 3. Confirma que a lista publicada não foi adulterada.
- A versão do algoritmo — atualmente
v1. Fixa o algoritmo de seleção exato, para que melhorias futuras nunca alterem retroativamente resultados antigos. - A versão do Ruby — fixa o tempo de execução da linguagem, uma vez que a ordenação exata do baralhamento depende dela.
Refaça os cálculos você mesmo — em cinco linhas
Se tiver o Ruby instalado (vem incluído no macOS e na maioria das distribuições Linux), pode reproduzir o sorteio exato em casa. Cada concurso publica o seu próprio eligible-ids.txt na sua página de verificação (padrão de URL: /results/<token>/verify) — o guia de verificação explica passo a passo como descarregá-lo. Copie a semente publicada e cole isto no irb:
require "digest"
seed = "PASTE_THE_PUBLISHED_SEED_HERE"
ids = File.read("eligible-ids.txt").split("\n").map(&:to_i).sort
# (1) Sanity check the input: must equal the published SHA-256.
Digest::SHA256.hexdigest(ids.join("\n"))
# (2) Re-run the shuffle. First 3 items are winners 1..3 (in order);
# the next 9 items are reserves 1..9.
ids.shuffle(random: Random.new(seed.to_i(16))).first(12)
Os 12 IDs saem exatamente na mesma ordem que o concurso publicou. Três vencedores, nove reservas, bit a bit idênticos. É isto que torna um sorteio Pick a Winner verificável em vez de meramente prometido — a matemática faz o trabalho, não a palavra do operador.
Por que é difícil manipular isto
- A semente é impossível de adivinhar. 2²⁵⁶ possibilidades, geradas apenas após a lista elegível estar comprometida. Ninguém consegue pré-calcular quais os IDs que a semente favoreceria, porque a semente não existe até ao momento do sorteio.
- A entrada está bloqueada. A impressão digital SHA-256 significa que não é possível adicionar silenciosamente um comentário de um amigo após ver a semente — a impressão digital mudaria e o sorteio deixaria de ser reproduzível.
- O baralhamento é mecânico. Assim que a semente e a lista ordenada existem, os vencedores estão determinados. Nenhuma decisão humana se interpõe entre eles. Qualquer ajuste posterior seria detetável no momento em que alguém refizesse os cálculos.
- O recibo é público. Semente, lista, hash, versão do algoritmo, versão do Ruby — os cinco são publicados. Não existe nenhuma parte privada do sorteio que o operador pudesse alterar sem que todos pudessem ver.