Repository navigation
Pacote de resultados ao fim da prova, para alimentar um ranking nacional #271
Description
O que é
Um pacote de resultados gerado ao fim da competição, para ser enviado a um
site nacional que agrega as edições e produz um ranking.
Depende da #270 — sem afiliação institucional confiável, o agregado por
instituição fica sobre inferência.
Metade já existe
app/Services/IcpcReportBuilder.php produz o arquivo de standings da ICPC,
modelado no src/admin/report/icpc.php do BOCA, e o docblock diz exatamente o
que ele é:
"the ICPC standings file, the one an organiser sends in after the contest
is over (...) this one is the record of what happened, and its consumer is a
person filing results."
usericpcid, colocação, problemas resolvidos, tempo total, tempo do primeiro AC
Ordenação e tempos vêm de Leaderboard::getScoreboard() — a mesma fonte do
placar público. E teamsMissingIcpcId() já lista quem ficaria de fora por
falta de identificador.
O ClicsPresenter já sabe montar equipes, organizações, problemas e prêmios
no formato da Contest API.
O que falta para agregar nacionalmente
1. O contest não tem identidade fora desta instalação. contests não tem
uuid, nem edição, nem fase. Um site nacional recebendo trinta arquivos não
distingue qual é qual, nem reconhece o mesmo evento reenviado depois de um
rejulgamento.
2. Não há integridade. Um CSV sem verificação é um CSV editável, e um
ranking que aceita arquivo editável à mão não é um ranking.
3. Nada impede exportar resultado provisório. Exportar antes da
finalização — com rejulgamento pendente, ou com o placar ainda congelado —
envenena o agregado.
A forma proposta
Um ZIP, gerado somente de contest finalizado, seguindo o precedente que o
BackupService já estabeleceu (manifest.json, "what this archive is, for
whoever opens it later", com uma seção notes escrita para quem abre o
arquivo num dia ruim):
manifest.json identidade do contest, datas, finalização, versão do
exportador, e o SHA-256 de cada arquivo do pacote
standings.json formato CLICS: equipes (com icpc_id), organizações,
problemas, classificação e premiação
standings.csv as cinco colunas do BOCA, inalteradas
organizations.json as instituições referenciadas
Dois consumidores num pacote só: a ferramenta que lê CLICS, e quem já espera o
arquivo do BOCA.
A propriedade que sustenta a confiança
Exportar duas vezes o mesmo contest finalizado deve produzir saída idêntica
byte a byte, exceto o carimbo de tempo — que fica isolado num campo só do
manifesto, justamente para o resto ser comparável.
Com isso o site nacional não precisa confiar no arquivo: ele pode pedir a
reexportação e comparar. Adulteração aparece como divergência, não como
suspeita.
Isso exige cuidado com o que costuma quebrar reprodutibilidade — ordem de
iteração não determinística, json_encode de mapas sem ordenação estável,
caminhos absolutos, e o próprio relógio. É uma propriedade testável, e
deve ter guarda.
Identidade do contest
O manifesto precisa responder "que prova é esta" sem depender do banco de
origem:
- identificador estável do contest, gerado uma vez e imutável;
- nome, edição e fase, se houver — uma regional e uma final nacional não
são o mesmo tipo de evento no agregado; - datas de início, fim e finalização;
- sedes que participaram;
- versão do exportador, para o site nacional saber interpretar.
Privacidade — decisão a registrar no PR
A régua proposta: o pacote não exporta mais do que o placar público já
mostra, mais a chave de agregação.
Nome de equipe, colocação, problemas e tempos já são públicos. icpc_id
não é — é identificador pessoal, e é justamente o que torna a agregação
possível. Então ele entra por decisão explícita, escrita, e não por efeito
colateral.
Este sistema tem contas gerenciadas de menores com profile_visibility
privado por padrão (#47, ManagedAccountProvisioner). O que não deve
entrar no pacote em hipótese alguma: data de nascimento, e-mail, e qualquer
campo que a ProfilePrivacyPolicy proteja.
Como verificar
- Portão de finalização: tentar exportar contest não finalizado é
recusado, com motivo legível. - Reprodutibilidade: exportar duas vezes, comparar byte a byte ignorando
o campo de carimbo de tempo — idênticos. - Integridade: o SHA-256 de cada arquivo confere com o manifesto; alterar
um byte destandings.csvfaz a conferência falhar. - Fidelidade: a classificação do pacote bate com o placar final da tela,
inclusive empates e o corte de premiação. - Privacidade: nenhum campo protegido pela
ProfilePrivacyPolicyaparece
em nenhum arquivo do pacote — teste que varre o ZIP inteiro procurando por
eles. - Mutações, cada uma derrubando exatamente um teste: remover o portão de
finalização; introduzir ordenação não determinística; tirar um hash do
manifesto; incluir a data de nascimento. - Suítes completas, PHPStan e Pint.
Fora de escopo
- O site nacional que recebe — isto entrega o arquivo, não o receptor.
- Assinatura digital por sede. Foi considerada e adiada: resolve sede
maliciosa, mas traz distribuição, rotação e revogação de chaves, e só faz
sentido quando houver um receptor real com quem combinar o protocolo. O
checksum com reexportação cobre adulteração acidental e edição manual, que
é o risco de hoje. - Importar de volta um pacote de outra instalação.
Relacionado: #270 (afiliação, pré-requisito), #266 (licenciamento).
Activity
A instituição pela qual uma equipe compete deixa de ser inferida (issue
Pacote de resultados, para alimentar um ranking nacional (issue #271) (…