Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion etc/db-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -281,7 +288,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
Expand Down
21 changes: 18 additions & 3 deletions webapp/src/Controller/Team/SubmissionController.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -121,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();
Expand Down Expand Up @@ -150,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);

Expand All @@ -159,9 +162,9 @@ 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')
->andWhere('jr.runresult IS NOT NULL')
->setParameter('judging', $judging)
->setParameter('problem', $judging->getSubmission()->getProblem())
->orderBy('t.ranknumber');
Expand Down Expand Up @@ -191,6 +194,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');

Expand All @@ -200,9 +212,12 @@ public function viewAction(Request $request, int $submitId): Response
'showCompile' => $actuallyShowCompile,
'allowDownload' => $allowDownload,
'showSampleOutput' => $showSampleOutput,
'showAllTestcases' => $showAllTestcases,
'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';
Expand Down
83 changes: 21 additions & 62 deletions webapp/templates/team/partials/submission.html.twig
Original file line number Diff line number Diff line change
Expand Up @@ -78,75 +78,34 @@
{% endif %}
{% endif %}

{% if showSampleOutput and judging.result != 'compiler-error' %}
{% if (showSampleOutput or showAllTestcases) and judging.result != 'compiler-error' %}
<hr/>
<h4 class="text-center">Run(s) on the provided sample data</h4>
<h4 class="text-center">
{% if not showAllTestcases %}
Run(s) on the provided sample data
{% else %}
Runs
{% endif %}
</h4>

{% if runs is empty %}
<p class="nodata">No sample cases available.</p>
<p class="nodata">No {% if not showAllTestcases %}sample {% endif %}cases available.</p>
{% else %}
{% for run in runs %}
<h5 id="run-{{ run.0.rank }}" class="text-center mt-4">Run {{ run.0.rank }}</h5>

{% set judgingRun = run.0.judgingRuns.first %}
{% if judgingRun == null or judgingRun.runresult == null %}
<p class="nodata">Run not finished yet.</p>
{% else %}
<div class="row">
<div class="col-md-{{ size|default(4) }}">
<table class="table table-sm table-striped">
<tr>
<th>Description</th>
<td>{{ run.0.description(true) }}</td>
</tr>
<tr>
<th>Runtime</th>
<td>{{ judgingRun.runtime }} sec</td>
</tr>
<tr>
<th>Result</th>
<td>
{{ judgingRun.runresult | printResult }}
</td>
</tr>
</table>
</div>
</div>

{% if judging.submission.problem.interactiveProblem %}
<h6 class="mt-3">Jury/Submission interaction</h6>
{% if run.output_run is empty %}
<p class="nodata">There was no interaction log.</p>
{% else %}
{{ run.output_run | interactiveLog(true) }}
{% endif %}
{% if run.team_message is not empty %}
<h6 class="mt-3">Judge message</h6>
<pre class="output_text">
{{ run.team_message }}</pre>
{% endif %}
{% else %}
<h6 class="mt-3">Program output</h6>
{% if run.output_run is not empty %}
<pre class="output_text">
{{ run.output_run }}</pre>
{% else %}
<p class="nodata">There was no program output.</p>
{% set stop = false %}
{% for idx, run in runs %}
{% if not stop and ((showSampleOutput and run.0.sample) or showAllTestcases) %}
<h5 id="run-{{ run.0.rank }}" class="text-center mt-4">
Run {{ run.0.rank }}
{% if showAllTestcases and run.0.sample %}
(sample)
{% endif %}
</h5>

{% if run.team_message is not empty %}
<h6 class="mt-3">Judge message</h6>
<pre class="output_text">
{{ run.team_message }}</pre>
{% endif %}
{% include 'team/partials/submission_testcase.html.twig' %}

<h6 class="mt-3">Error output (info/debug/errors)</h6>
{% if run.output_error is not empty %}
<pre class="output_text">
{{ run.output_error }}</pre>
{% else %}
<p class="nodata">There was no stderr output.</p>
{% endif %}
{% set judgingRun = run.0.judgingRuns.first %}
{% if judgingRun.runresult != 'correct' %}
{% set stop = true %}
{% endif %}
{% endif %}
{% endfor %}
Expand Down
69 changes: 69 additions & 0 deletions webapp/templates/team/partials/submission_testcase.html.twig
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
{% set judgingRun = run.0.judgingRuns.first %}
<div class="row">
<div class="col-md-{{ size|default(4) }}">
<table class="table table-sm table-striped">
{% if run.0.description(true) %}
<tr>
<th>Description</th>
<td>{{ run.0.description(true) }}</td>
</tr>
{% endif %}
{% if showLimits %}
<tr>
<th>Runtime</th>
<td>{{ judgingRun.runtime }} sec</td>
</tr>
{% if metadata[idx] is defined %}
<tr>
<th>Memory usage</th>
<td>{{ metadata[idx]['memory-bytes'] | printSize }}</td>
</tr>
{% endif %}
{% endif %}
<tr>
<th>Result</th>
<td>
{{ judgingRun.runresult | printResult }}
</td>
</tr>
</table>
</div>
</div>

{% if showSampleOutput and run.0.sample %}
{% if judging.submission.problem.interactiveProblem %}
<h6 class="mt-3">Jury/Submission interaction</h6>
{% if run.output_run is empty %}
<p class="nodata">There was no interaction log.</p>
{% else %}
{{ run.output_run | interactiveLog(true) }}
{% endif %}
{% if run.team_message is not empty %}
<h6 class="mt-3">Judge message</h6>
<pre class="output_text">
{{ run.team_message }}</pre>
{% endif %}
{% else %}
<h6 class="mt-3">Program output</h6>
{% if run.output_run is not empty %}
<pre class="output_text">
{{ run.output_run }}</pre>
{% else %}
<p class="nodata">There was no program output.</p>
{% endif %}

{% if run.team_message is not empty %}
<h6 class="mt-3">Judge message</h6>
<pre class="output_text">
{{ run.team_message }}</pre>
{% endif %}

<h6 class="mt-3">Error output (info/debug/errors)</h6>
{% if run.output_error is not empty %}
<pre class="output_text">
{{ run.output_error }}</pre>
{% else %}
<p class="nodata">There was no stderr output.</p>
{% endif %}
{% endif %}
{% endif %}
Loading