Skip to content

Pacote de resultados ao fim da prova, para alimentar um ranking nacional #271

Closed

Description

@matbrgz

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

  1. Portão de finalização: tentar exportar contest não finalizado é
    recusado, com motivo legível.
  2. Reprodutibilidade: exportar duas vezes, comparar byte a byte ignorando
    o campo de carimbo de tempo — idênticos.
  3. Integridade: o SHA-256 de cada arquivo confere com o manifesto; alterar
    um byte de standings.csv faz a conferência falhar.
  4. Fidelidade: a classificação do pacote bate com o placar final da tela,
    inclusive empates e o corte de premiação.
  5. Privacidade: nenhum campo protegido pela ProfilePrivacyPolicy aparece
    em nenhum arquivo do pacote — teste que varre o ZIP inteiro procurando por
    eles.
  6. 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.
  7. 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).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions