Summary
The application ships two entirely disconnected data models and code paths for contests/problems/submissions. The legacy one is wired to every screen a user actually clicks; the real, BOCA-compatible one (with a working auto-judge service) is only reachable through the JSON API and has no UI at all. As a result, a contestant cannot get a real judged submission through the web app today — the visible "Submit" flow is a non-functional stub.
This is the most important finding of the BOCA-parity audit: schema-level parity is high (see prior audit / issues #18-#21), but the wired, user-facing system does not actually execute a judged run end-to-end.
Evidence — legacy path (wired to every screen)
- Contest creation:
/wizard and the "Nova Maratona" button under Configurações are handled by Backend\ContestWizardController and inline closures in routes/web.php (around line 249, 274, 283, 310) that all read/write the hackathons table (DB::table('hackathons')...), a leftover from the original 2017 migration (2017_06_17_011431_create_hackathons_table). This table has no relationship to sites, languages, answers, or problems at all.
- Problem management: "Gerenciar Problemas" (
/backend/exercises) and the participant-facing "Problemas" list (/exercises, App\Http\Controllers\ExerciseController) both read/write the exercises table (exerciseName, category, difficulty, score, expectedOutcome — see routes/web.php lines 153-171 and app/Http/Controllers/ExerciseController.php). This table has no time/memory limits, no test cases, no language bindings — nothing an auto-judge could use.
- Submission:
GET/POST /submit/{id} (routes/web.php lines 39-63) is a stub — the POST handler's own comment says "This would integrate with the auto-judge system" and then just does:
DB::table('exercise_team')->insert([... 'result' => 'pending', ...]);
It never creates a runs row, never calls AutoJudgeService, and nothing ever updates that 'pending' result — the submission is judged never.
Evidence — real BOCA-compatible engine (API-only, no UI reaches it)
contests, sites, languages, answers, problems, test_cases, runs, clarifications, tasks, backups, logs, scores — the full 2025-11-25 migration set — model BOCA closely and are used consistently by App\Http\Controllers\SubmissionController (joins runs → problems/answers/languages), App\Services\AutoJudgeService (406 lines, compiles/runs/compares using safeexec, real implementation), and App\Http\Controllers\Api\RunController (store, judge, rejudge, downloadSource).
- These are exposed only via
routes/api.php (Route::apiResource('runs', RunController::class), /runs/{run}/rejudge, /runs/{run}/judge).
grep -rl "api/runs" resources/js/ returns nothing — the Vue frontend never calls this API. There is no admin screen to create a Contest, Site, Language, or Problem row either — the only way data gets into these tables today is the import-boca route (zip import) and the demo seeder added in this PR.
Impact
Following the README end-to-end (register a team, browse problems, submit a solution, get judged, see the scoreboard update) does not work: the submission a contestant makes is written to a table (exercise_team) that nothing reads back, so it sits as 'pending' forever, and none of the sandboxed compile/run/compare logic in AutoJudgeService ever executes for it. The judging engine itself appears complete and reasonably faithful to BOCA's approach (uses safeexec, per-answer configurable verdicts, etc.) — it's just not connected to anything a contestant can click.
Suggested scope
This needs a product decision, not just a patch:
- Decide whether
hackathons/exercises/exercise_team should be deleted (they predate the BOCA-compatible rewrite and appear to be dead weight now that contests/problems/runs exist), or whether the intent is to keep a simpler "hackathon mode" alongside full BOCA-style contests.
- Wire the participant Problems/Submit UI to
problems/languages and POST /api/runs (or an equivalent web route that creates a real Run and triggers AutoJudgeService), instead of the exercises/exercise_team stub.
- Add an admin UI (or fix the existing wizard) to create/edit
Contest, Site, Language, and Problem (with test cases) — right now the only way to populate the real schema is the BOCA-zip import or direct API/DB access.
Found via a functional, hands-on audit (actually logging in, seeding data, and tracing the submission flow through the code) as part of verifying microHelium can execute everything BOCA does — not just a schema comparison.
Summary
The application ships two entirely disconnected data models and code paths for contests/problems/submissions. The legacy one is wired to every screen a user actually clicks; the real, BOCA-compatible one (with a working auto-judge service) is only reachable through the JSON API and has no UI at all. As a result, a contestant cannot get a real judged submission through the web app today — the visible "Submit" flow is a non-functional stub.
This is the most important finding of the BOCA-parity audit: schema-level parity is high (see prior audit / issues #18-#21), but the wired, user-facing system does not actually execute a judged run end-to-end.
Evidence — legacy path (wired to every screen)
/wizardand the "Nova Maratona" button under Configurações are handled byBackend\ContestWizardControllerand inline closures inroutes/web.php(around line 249, 274, 283, 310) that all read/write thehackathonstable (DB::table('hackathons')...), a leftover from the original 2017 migration (2017_06_17_011431_create_hackathons_table). This table has no relationship tosites,languages,answers, orproblemsat all./backend/exercises) and the participant-facing "Problemas" list (/exercises,App\Http\Controllers\ExerciseController) both read/write theexercisestable (exerciseName,category,difficulty,score,expectedOutcome— seeroutes/web.phplines 153-171 andapp/Http/Controllers/ExerciseController.php). This table has no time/memory limits, no test cases, no language bindings — nothing an auto-judge could use.GET/POST /submit/{id}(routes/web.phplines 39-63) is a stub — the POST handler's own comment says "This would integrate with the auto-judge system" and then just does:runsrow, never callsAutoJudgeService, and nothing ever updates that'pending'result — the submission is judged never.Evidence — real BOCA-compatible engine (API-only, no UI reaches it)
contests,sites,languages,answers,problems,test_cases,runs,clarifications,tasks,backups,logs,scores— the full 2025-11-25 migration set — model BOCA closely and are used consistently byApp\Http\Controllers\SubmissionController(joinsruns→problems/answers/languages),App\Services\AutoJudgeService(406 lines, compiles/runs/compares usingsafeexec, real implementation), andApp\Http\Controllers\Api\RunController(store,judge,rejudge,downloadSource).routes/api.php(Route::apiResource('runs', RunController::class),/runs/{run}/rejudge,/runs/{run}/judge).grep -rl "api/runs" resources/js/returns nothing — the Vue frontend never calls this API. There is no admin screen to create aContest,Site,Language, orProblemrow either — the only way data gets into these tables today is theimport-bocaroute (zip import) and the demo seeder added in this PR.Impact
Following the README end-to-end (register a team, browse problems, submit a solution, get judged, see the scoreboard update) does not work: the submission a contestant makes is written to a table (
exercise_team) that nothing reads back, so it sits as'pending'forever, and none of the sandboxed compile/run/compare logic inAutoJudgeServiceever executes for it. The judging engine itself appears complete and reasonably faithful to BOCA's approach (usessafeexec, per-answer configurable verdicts, etc.) — it's just not connected to anything a contestant can click.Suggested scope
This needs a product decision, not just a patch:
hackathons/exercises/exercise_teamshould be deleted (they predate the BOCA-compatible rewrite and appear to be dead weight now thatcontests/problems/runsexist), or whether the intent is to keep a simpler "hackathon mode" alongside full BOCA-style contests.problems/languagesandPOST /api/runs(or an equivalent web route that creates a realRunand triggersAutoJudgeService), instead of theexercises/exercise_teamstub.Contest,Site,Language, andProblem(with test cases) — right now the only way to populate the real schema is the BOCA-zip import or direct API/DB access.Found via a functional, hands-on audit (actually logging in, seeding data, and tracing the submission flow through the code) as part of verifying microHelium can execute everything BOCA does — not just a schema comparison.