From 4dc677f5549035a5fb5871d75f65b1aaada358f9 Mon Sep 17 00:00:00 2001 From: Nicky Gerritsen Date: Tue, 16 Dec 2025 12:19:52 +0200 Subject: [PATCH 1/2] Also show memory limit for samples on team submission page This was requested at SEERC and I think it makes sense in general. Also updated the logic to only show these limits when `show_limits_on_team_page` is set. --- etc/db-config.yaml | 2 +- .../Controller/Team/SubmissionController.php | 15 ++++++++++++++- .../team/partials/submission.html.twig | 18 +++++++++++++----- 3 files changed, 28 insertions(+), 7 deletions(-) diff --git a/etc/db-config.yaml b/etc/db-config.yaml index f5625dbaf6..76ebf25420 100644 --- a/etc/db-config.yaml +++ b/etc/db-config.yaml @@ -281,7 +281,7 @@ type: bool default_value: true public: true - description: Show time and memory limit on the team problems page. + description: Show time and memory limit on the team problems and submission details page. - name: allow_team_submission_download type: bool default_value: false diff --git a/webapp/src/Controller/Team/SubmissionController.php b/webapp/src/Controller/Team/SubmissionController.php index 9957883054..36f5269047 100644 --- a/webapp/src/Controller/Team/SubmissionController.php +++ b/webapp/src/Controller/Team/SubmissionController.php @@ -4,6 +4,7 @@ use App\Controller\BaseController; use App\Entity\Judging; +use App\Entity\JudgingRun; use App\Entity\Language; use App\Entity\Problem; use App\Entity\Submission; @@ -14,6 +15,7 @@ use App\Service\DOMJudgeService; use App\Service\EventLogService; use App\Service\SubmissionService; +use App\Utils\Utils; use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\NonUniqueResultException; use Doctrine\ORM\Query\Expr\Join; @@ -159,7 +161,7 @@ public function viewAction(Request $request, int $submitId): Response ->join('t.content', 'tc') ->leftJoin('t.judging_runs', 'jr', Join::WITH, 'jr.judging = :judging') ->leftJoin('jr.output', 'jro') - ->select('t', 'jr', 'tc') + ->select('t', 'jr', 'jro', 'tc') ->andWhere('t.problem = :problem') ->andWhere('t.sample = 1') ->setParameter('judging', $judging) @@ -191,6 +193,15 @@ public function viewAction(Request $request, int $submitId): Response ->getResult(); } + $metadata = []; + foreach ($runs as $index => $runData) { + /** @var JudgingRun|null $run */ + $run = $runData[0]->getJudgingRuns()->first(); + if ($run?->getOutput()?->getMetadata()) { + $metadata[$index] = Utils::parseMetadata($run->getOutput()->getMetadata()); + } + } + $actuallyShowCompile = $showCompile == self::ALWAYS_SHOW_COMPILE_OUTPUT || ($showCompile == self::ONLY_SHOW_COMPILE_OUTPUT_ON_ERROR && $judging->getResult() === 'compiler-error'); @@ -201,8 +212,10 @@ public function viewAction(Request $request, int $submitId): Response 'allowDownload' => $allowDownload, 'showSampleOutput' => $showSampleOutput, 'runs' => $runs, + 'metadata' => $metadata, 'showTooLateResult' => $showTooLateResult, 'thumbnailSize' => $this->config->get('thumbnail_size'), + 'showLimits' => (bool)$this->config->get('show_limits_on_team_page') ]; if ($actuallyShowCompile) { $data['size'] = 'xl'; diff --git a/webapp/templates/team/partials/submission.html.twig b/webapp/templates/team/partials/submission.html.twig index c5c3d9445b..8008de11a0 100644 --- a/webapp/templates/team/partials/submission.html.twig +++ b/webapp/templates/team/partials/submission.html.twig @@ -85,7 +85,7 @@ {% if runs is empty %}

No sample cases available.

{% else %} - {% for run in runs %} + {% for idx, run in runs %}
Run {{ run.0.rank }}
{% set judgingRun = run.0.judgingRuns.first %} @@ -99,10 +99,18 @@ Description {{ run.0.description(true) }} - - Runtime - {{ judgingRun.runtime }} sec - + {% if showLimits %} + + Runtime + {{ judgingRun.runtime }} sec + + {% if metadata[idx] is defined %} + + Memory usage + {{ metadata[idx]['memory-bytes'] | printSize }} + + {% endif %} + {% endif %} Result From 67e7cf045dc4f51e1813c2f1092635985becd233 Mon Sep 17 00:00:00 2001 From: Nicky Gerritsen Date: Tue, 16 Dec 2025 13:01:05 +0200 Subject: [PATCH 2/2] Add option to show verdict for all testcases Algotester does this so we needed it for SEERC and I think having this as an option can make sense. --- etc/db-config.yaml | 7 ++ .../Controller/Team/SubmissionController.php | 6 +- .../team/partials/submission.html.twig | 89 +++++-------------- .../partials/submission_testcase.html.twig | 69 ++++++++++++++ 4 files changed, 100 insertions(+), 71 deletions(-) create mode 100644 webapp/templates/team/partials/submission_testcase.html.twig diff --git a/etc/db-config.yaml b/etc/db-config.yaml index 76ebf25420..b0e65f720c 100644 --- a/etc/db-config.yaml +++ b/etc/db-config.yaml @@ -250,6 +250,13 @@ default_value: false public: true description: Should teams be able to view a diff of their and the reference output on sample testcases? + - name: show_all_testcase_verdicts + type: bool + default_value: false + public: true + description: | + Show verdicts for all testcases on the team interface. + If `show_limits_on_team_page` is also set, also display runtime and memory usage. - name: show_too_late_result type: bool default_value: false diff --git a/webapp/src/Controller/Team/SubmissionController.php b/webapp/src/Controller/Team/SubmissionController.php index 36f5269047..b3093372d1 100644 --- a/webapp/src/Controller/Team/SubmissionController.php +++ b/webapp/src/Controller/Team/SubmissionController.php @@ -123,6 +123,7 @@ public function viewAction(Request $request, int $submitId): Response $verificationRequired = (bool)$this->config->get('verification_required'); $showCompile = $this->config->get('show_compile'); $showSampleOutput = $this->config->get('show_sample_output'); + $showAllTestcases = $this->config->get('show_all_testcase_verdicts'); $allowDownload = (bool)$this->config->get('allow_team_submission_download'); $showTooLateResult = $this->config->get('show_too_late_result'); $user = $this->dj->getUser(); @@ -152,7 +153,7 @@ public function viewAction(Request $request, int $submitId): Response } $runs = []; - if ($showSampleOutput && $judging && $judging->getResult() !== 'compiler-error') { + if (($showSampleOutput || $showAllTestcases) && $judging && $judging->getResult() !== 'compiler-error') { $outputDisplayLimit = (int)$this->config->get('output_display_limit'); $outputTruncateMessage = sprintf("\n[output display truncated after %d B]\n", $outputDisplayLimit); @@ -163,7 +164,7 @@ public function viewAction(Request $request, int $submitId): Response ->leftJoin('jr.output', 'jro') ->select('t', 'jr', 'jro', 'tc') ->andWhere('t.problem = :problem') - ->andWhere('t.sample = 1') + ->andWhere('jr.runresult IS NOT NULL') ->setParameter('judging', $judging) ->setParameter('problem', $judging->getSubmission()->getProblem()) ->orderBy('t.ranknumber'); @@ -211,6 +212,7 @@ public function viewAction(Request $request, int $submitId): Response 'showCompile' => $actuallyShowCompile, 'allowDownload' => $allowDownload, 'showSampleOutput' => $showSampleOutput, + 'showAllTestcases' => $showAllTestcases, 'runs' => $runs, 'metadata' => $metadata, 'showTooLateResult' => $showTooLateResult, diff --git a/webapp/templates/team/partials/submission.html.twig b/webapp/templates/team/partials/submission.html.twig index 8008de11a0..d1a80bea67 100644 --- a/webapp/templates/team/partials/submission.html.twig +++ b/webapp/templates/team/partials/submission.html.twig @@ -78,83 +78,34 @@ {% endif %} {% endif %} - {% if showSampleOutput and judging.result != 'compiler-error' %} + {% if (showSampleOutput or showAllTestcases) and judging.result != 'compiler-error' %}
-

Run(s) on the provided sample data

+

+ {% if not showAllTestcases %} + Run(s) on the provided sample data + {% else %} + Runs + {% endif %} +

{% if runs is empty %} -

No sample cases available.

+

No {% if not showAllTestcases %}sample {% endif %}cases available.

{% else %} + {% set stop = false %} {% for idx, run in runs %} -
Run {{ run.0.rank }}
- - {% set judgingRun = run.0.judgingRuns.first %} - {% if judgingRun == null or judgingRun.runresult == null %} -

Run not finished yet.

- {% else %} -
-
- - - - - - {% if showLimits %} - - - - - {% if metadata[idx] is defined %} - - - - - {% endif %} - {% endif %} - - - - -
Description{{ run.0.description(true) }}
Runtime{{ judgingRun.runtime }} sec
Memory usage{{ metadata[idx]['memory-bytes'] | printSize }}
Result - {{ judgingRun.runresult | printResult }} -
-
-
- - {% if judging.submission.problem.interactiveProblem %} -
Jury/Submission interaction
- {% if run.output_run is empty %} -

There was no interaction log.

- {% else %} - {{ run.output_run | interactiveLog(true) }} - {% endif %} - {% if run.team_message is not empty %} -
Judge message
-
-{{  run.team_message }}
- {% endif %} - {% else %} -
Program output
- {% if run.output_run is not empty %} -
-{{ run.output_run }}
- {% else %} -

There was no program output.

+ {% if not stop and ((showSampleOutput and run.0.sample) or showAllTestcases) %} +
+ Run {{ run.0.rank }} + {% if showAllTestcases and run.0.sample %} + (sample) {% endif %} +
- {% if run.team_message is not empty %} -
Judge message
-
-{{  run.team_message }}
- {% endif %} + {% include 'team/partials/submission_testcase.html.twig' %} -
Error output (info/debug/errors)
- {% if run.output_error is not empty %} -
-{{ run.output_error }}
- {% else %} -

There was no stderr output.

- {% endif %} + {% set judgingRun = run.0.judgingRuns.first %} + {% if judgingRun.runresult != 'correct' %} + {% set stop = true %} {% endif %} {% endif %} {% endfor %} diff --git a/webapp/templates/team/partials/submission_testcase.html.twig b/webapp/templates/team/partials/submission_testcase.html.twig new file mode 100644 index 0000000000..3f7382aa00 --- /dev/null +++ b/webapp/templates/team/partials/submission_testcase.html.twig @@ -0,0 +1,69 @@ +{% set judgingRun = run.0.judgingRuns.first %} +
+
+ + {% if run.0.description(true) %} + + + + + {% endif %} + {% if showLimits %} + + + + + {% if metadata[idx] is defined %} + + + + + {% endif %} + {% endif %} + + + + +
Description{{ run.0.description(true) }}
Runtime{{ judgingRun.runtime }} sec
Memory usage{{ metadata[idx]['memory-bytes'] | printSize }}
Result + {{ judgingRun.runresult | printResult }} +
+
+
+ +{% if showSampleOutput and run.0.sample %} + {% if judging.submission.problem.interactiveProblem %} +
Jury/Submission interaction
+ {% if run.output_run is empty %} +

There was no interaction log.

+ {% else %} + {{ run.output_run | interactiveLog(true) }} + {% endif %} + {% if run.team_message is not empty %} +
Judge message
+
+{{  run.team_message }}
+ {% endif %} + {% else %} +
Program output
+ {% if run.output_run is not empty %} +
+{{ run.output_run }}
+ {% else %} +

There was no program output.

+ {% endif %} + + {% if run.team_message is not empty %} +
Judge message
+
+{{  run.team_message }}
+ {% endif %} + +
Error output (info/debug/errors)
+ {% if run.output_error is not empty %} +
+{{ run.output_error }}
+ {% else %} +

There was no stderr output.

+ {% endif %} + {% endif %} +{% endif %}