1. O ciclo de vida de um problema
- Nasce privado dentro de uma ORG (o prefixo do id:
apc#fibonacci). Ninguém de fora da org o vê — nem que ele existe. Prova em elaboração não vaza, por construção. - Validar é o portão de qualidade: seções obrigatórias no enunciado, testes pareados, soluções good aceitas. Não publica nada — é exatamente o modo p/ provas.
- Calibrar: o juiz roda as SUAS soluções good em cada máquina e mede o time limit por máquina E por linguagem. Você nunca mais chuta TL.
- Publicar o coloca no treino livre (a org precisa permitir público — trava que protege provas). Em contests de turma você usa problemas ainda privados.
O Painel acompanha cada fase — e avisa, com os commits exatos, quando um problema mudou e precisa recalibrar.
2. A CLI em 60 segundos
curl -fsSL https://moj.naquadah.com.br/moj -o ~/.local/bin/moj && chmod +x ~/.local/bin/moj moj login # o MESMO login desta página — sem git, sem chave SSH
Requisitos: bash, curl, jq. Um arquivo só, auto-contido (a lib comum vem embutida). Quem gere contests ou o parque de juízes também tem /moj-contest e /moj-judges no mesmo endereço.
Dois jeitos de trabalhar, misture à vontade: moj edit abre um menu interativo com todos os campos (enunciado, exemplos, soluções, conf, publicar) — e o jeito arquivos-locais: o pacote é um diretório, você edita com as suas ferramentas e moj push envia.
moj test --run (julgamento local; também exige Linux com bubblewrap real), moj checker e moj interactive (instalam os drivers de correção especial). Para esses:
git clone https://github.com/cd-moj/mojtools ~/mojtools export MOJTOOLS_DIR=~/mojtools # no seu .bashrcTODO O RESTO da CLI só precisa de bash, curl e jq.
3. Passo a passo: do zero ao publicado
Passo 1 — o esqueleto
moj new minha-org fibonacci # scaffold completo em ./fibonacci cd fibonacci && ls # docs/enunciado.md tests/input/ tests/output/ sols/good/ conf author tags
O primeiro argumento é a ORG (o id vira minha-org#fibonacci). Sua org pessoal (seu login) sempre existe e é sempre privada — perfeita p/ rascunhos.
moj mv fibonacci apc2026 — muda o id, nada mais. Na web: “+ Novo problema” na gestão.Passo 2 — o enunciado (docs/enunciado.md)
Markdown com matemática ($O(n \log n)$ vira MathML). Duas regras que o validador cobra e uma que ele não tem como cobrar:
- As seções
## Entradae## Saídasão obrigatórias (## Input/## Outputtambém valem). - O título é um campo (definido no
moj new/editou no formulário web) —% Títulona primeira linha é legado e é removido. - Declare as restrições EXPLICITAMENTE (
1 ≤ N ≤ 10⁵, cabe em 64 bits…). O aluno resolve as restrições, não a estória.
moj preview renderiza EXATAMENTE o HTML que o aluno verá (mesmo renderizador do site). Deixe aberto enquanto escreve.Imagens no enunciado
Jogue a figura AO LADO do enunciado.md (o docs/ do pacote) e referencie por caminho relativo — o renderizador a embute em base64 (pandoc --embed-resources), então o HTML servido ao aluno é auto-contido:
cp ~/screenshots/grafo.png docs/ # no enunciado.md: 
moj preview mostra a imagem embutida; moj push a carrega (round-trip completo). Qualquer formato que o navegador renderiza (png/jpg/svg) funciona.
.vimrc) e emacs (init.el):" vim — :MojImg ~/screenshots/grafo.png (copia p/ o dir do arquivo atual e insere a linha)
command! -nargs=1 -complete=file MojImg
\ execute '!cp' shellescape(<q-args>) shellescape(expand('%:p:h')) |
\ execute 'normal! o . ')'
;; emacs — M-x moj-img (idem: copia p/ o dir do buffer e insere )
(defun moj-img (file)
(interactive "fImagem: ")
(let ((dest (expand-file-name (file-name-nondirectory file) default-directory)))
(copy-file file dest t)
(insert (format "" (file-name-nondirectory file)))))
Passo 3 — exemplos visíveis (samples)
printf '5\n1 2 3 4 5\n' > tests/input/sample1 # a saída de CADA teste você vai gerar com a sua solução no passo 5
Cada tests/input/sampleX casa com tests/output/sampleX e aparece no enunciado, em ordem. Tudo que NÃO se chama sample* é teste oculto.
docs/sample-notes.json. Grande e exaustivo é papel dos ocultos.Passo 4 — testes ocultos
É aqui que a nota se decide. Cubra: o menor caso válido, o MAIOR caso (limites das restrições — é ele que derruba o O(n²)), valores que estouram int, empates/duplicatas e formatos degenerados. Um gerador vale mais que arquivos à mão:
for i in $(seq 1 8); do python3 gen.py $i > tests/input/t$i; done
tests/output/* COM a sua solução good (passo 5) — nunca à mão. Uma saída digitada com espaço sobrando reprova a turma inteira.Nota parcial estilo OBI: tests/score passo a passo
- Nomeie os testes ocultos POR GRUPO — é o glob que os amarra:
tests/input/g1_pequeno1 g1_pequeno2 # casos N ≤ 100 tests/input/g2_medio1 g2_medio2 # N ≤ 10^4 tests/input/g3_grande1 g3_grande2 # N ≤ 10^6
- Uma linha por grupo no
tests/score: globs, depois-, depois o peso. O separador ENTRE globs é vírgula+espaço (", ") — o parser exige, dos dois lados (API e juiz):sample* - 0 pontos g1_* - 20 pontos g2_* - 30 pontos g3_* - 50 pontos
- Regras: grupo é tudo-ou-nada (um teste falhou = grupo vale 0); o valor do problema é a SOMA dos pesos (não precisa dar 100); os samples entram com peso 0 p/ aparecerem no relatório sem valer nota.
- O que o aluno vê embaixo do veredicto:
✓ Grupo 2 (30/30) · ✗ Grupo 3 (0/50)— feedback explícito por grupo; em contest modo OBI o placar também vira pontos.
Passo 5 — soluções de referência (sols/)
A extensão define a linguagem (sol.c, sol.cpp, sol.py, Main.java…). Cada subdiretório tem um PAPEL na conferência:
good/— obrigatório (≥1): as corretas. Geram as saídas esperadas, a validação exige que sejam aceitas, e o juiz as cronometra p/ calibrar o TL.wrong/— erradas de propósito: prova que seus testes PEGAM o erro clássico.slow/— lentas de propósito (o O(n²) que você quer reprovar): prova que o TL de fato as derruba.pass/— devem passar raspando: prova que o TL não ficou apertado demais.upcoming/— rascunhos; fora da conferência.
# gere as saídas com a good (exemplo em C): gcc -O2 sols/good/sol.c -o /tmp/sol for f in tests/input/*; do /tmp/sol < "$f" > "tests/output/$(basename "$f")"; done
Passo 6 — conf: limites e opções
MEMLIMITMB— limite de memória (a JVM/-Xmx se dimensiona por ele também).calibrafactor— a folga do aluno sobre o tempo medido da sua good. Mais generoso = mais justo com abordagens alternativas.languages— restringe as linguagens de submissão (vazio = todas as padrão).
MEMLIMITMB e a folga — ou forneça uma good em Python e deixe a calibração por linguagem fazer a justiça por você.Opcional — correção especial (checker próprio / interativo)
Quando o diff puro não basta: várias respostas válidas (qualquer ordem topológica, qualquer caminho máximo), tolerância numérica, ou problemas interativos. Dois caminhos:
A) testlib (recomendado) — escreva um checker.cpp testlib padrão e instale o driver normalizado:
moj checker ./fibonacci checker.cpp # instala scripts/ (stub canônico + seu checker) moj interactive ./meu-jogo arbitro.cpp # idem p/ problema INTERATIVO (árbitro via FIFOs)
B) na mão — um scripts/compare.sh com este CONTRATO:
#!/bin/bash
# $1 = saída do ALUNO $2 = saída ESPERADA $3 = ENTRADA do teste
# exit 4 = Accepted · 5 = Accepted (Presentation Error) · 6 = Wrong Answer
awk -v a="$1" -v b="$2" 'BEGIN{ ... }' && exit 4 || exit 6
chmod +x é OBRIGATÓRIO em todo scripts/*.sh (a jaula os executa direto — sem o bit, TUDO vira Compilation Error). E mexer em scripts/ muda o tl-checksum: o Painel vai pedir recalibração — está certo, aceite.Guias: checker-testlib.md, correcao-especial.md e problema-interativo.md nas docs do mojtools (cobrem também submissão-de-função e banimento de função).
Passo 7 — teste local, depois envie
moj preview # o HTML do aluno no navegador moj test # pré-voo: estrutura, pareamento, seções moj test --run # JULGA de verdade na sua máquina (Linux + bwrap) moj push # envia — cria/atualiza no servidor (round-trip completo)
Todo push/salvar é um commit git no servidor: a aba histórico do editor (e moj log/moj restore) permite inspecionar e voltar qualquer versão.
Passo 8 — validar, calibrar, publicar
moj validate minha-org#fibonacci # portão + calibração no juiz — CONTINUA PRIVADO moj check minha-org#fibonacci # QA: checks, TL por juiz, good sem TL moj publish minha-org#fibonacci # público no treino (a ORG precisa permitir)
validate é o modo prova: conferência completa, exposição zero. check mostra o veredicto do juiz sobre as SUAS soluções e os TLs calibrados. publish exige a trava de público da org aberta (aba Orgs) — a org pessoal implícita nunca publica.
4. Receitas de professor
Uma lista/prova do zero, em lote
moj mkdir apc2026 # org da disciplina (privada por padrão) for p in soma-vetores busca-bin pilha-min; do moj new apc2026 $p # três esqueletos done # ... edite cada um (moj edit ./$p ou seus arquivos) ... for p in soma-vetores busca-bin pilha-min; do (cd $p && moj push) && moj validate "apc2026#$p" done moj board # a saúde de tudo num tiro só
Os problemas ficam privados até você decidir o contrário; o contest da turma pode usá-los ainda privados. No dia da prova, nada nunca esteve exposto.
Reusar entre semestres
moj clone apc2026#fibonacci fib-2027 # o pacote inteiro, scripts incluídos # ajuste os testes / a estória / os limites ... (cd fib-2027 && moj push) # o histórico git guarda cada versão moj log apc2026#fibonacci -n 5 # e se algo der errado: moj restore apc2026#fibonacci <sha> # volta como um commit NOVO (nada se perde)
Delegar a monitores; organizar o acervo
moj share apc2026 monitor-joao # membro da org: edita TUDO da org moj collection create "APC 2026.1" # coleção = TAG de agrupamento (m:n, cross-org) moj collection add apc2026#fibonacci "APC 2026.1"
ORG = acesso (uma por problema, o prefixo do id). COLEÇÃO = rótulo de navegação/curadoria, várias por problema. O aluno filtra o treino por coleção.
De olho em tudo
moj board # seus problemas: validado? calibrado? precisa revisar? moj check apc2026#fibonacci # o porquê de cada estado, juiz por juiz moj calibrate --all-stale # recalibra TUDO que o painel marcou (lote seguro)
5. ⚡ Comandos rápidos
| Comando | O que faz |
|---|---|
| moj login · whoami | sessão (mostra se você pode criar problemas) |
| moj new <org> <prob> | scaffold completo do pacote em ./prob |
| moj clone <id> [dir] | baixa o pacote INTEIRO (testes, soluções, scripts) |
| moj edit <id|dir> | menu interativo com todos os campos |
| moj preview [dir] | o HTML exato do aluno, no navegador |
| moj test [dir] [--run] | pré-voo local; --run julga de verdade (bwrap) |
| moj push [dir] | envia (cria/atualiza; round-trip completo) |
| moj upload/download <id> | pacote inteiro via tarball (download --sha = versão antiga) |
| moj validate <id> | portão + calibração — CONTINUA privado (modo prova) |
| moj check <id> | QA: checks, TLs por juiz, o porquê da recalibração |
| moj publish <id> · public <id> on|off | público no treino (org precisa permitir) / alternar |
| moj ls · board · info <id> | listas · painel de saúde · tudo de um problema |
| moj log <id> · restore <id> <sha> | histórico git · volta como commit NOVO |
| moj mv <id> <org> | move rascunho p/ outra org (muda o id) |
| moj mkdir <org> · share <org> <login> | cria org · adiciona membro (quem edita) |
| moj collection … | cria/marca/navega coleções (tags de agrupamento) |
| moj calibrate <id> | --all-stale | enfileira calibração / recalibra tudo que precisa |
| moj checker · interactive | instala checker testlib / problema interativo (correção especial) |
6. 💡 Dicas & armadilhas (aprendidas na prática)
- Exemplos vivem em arquivos, nunca no texto do enunciado — o renderizador os injeta e mantém tudo consistente.
- Saídas esperadas são SEMPRE geradas por uma good. Edição à mão é WA futuro p/ a turma inteira.
- Mudou testes, soluções good, conf ou scripts de correção? O TL ficou velho — o Painel marca (com os commits causadores) e
moj calibrateresolve. Mudança SÓ de enunciado não recalibra. - Justiça por linguagem vem de good por linguagem. Se você permite Python, entregue uma good em Python.
- A privacidade é estrutural: problema privado não aparece em lugar nenhum (nem p/ admin global de fora da org). A trava de público é da ORG — fechá-la despublica tudo em cascata.
- Precisa de checker próprio (várias respostas válidas) ou problema interativo? Os dois são cidadãos de primeira classe:
moj checker/moj interactiveinstalam os drivers normalizados. moj test --runexige Linux com bubblewrap real; sem ele, a validação simplesmente adia a execução p/ o juiz — não é bug.
7. Referências
Formato do pacote (fonte única) · Documentação completa · API · ← voltar à Gestão de Problemas