diff --git a/webapp/src/Service/DOMJudgeService.php b/webapp/src/Service/DOMJudgeService.php index 5101285bf8..fad4c51c49 100644 --- a/webapp/src/Service/DOMJudgeService.php +++ b/webapp/src/Service/DOMJudgeService.php @@ -879,8 +879,64 @@ public function getSamplesZipStreamedResponse(ContestProblem $contestProblem): S return Utils::streamAsBinaryFile($zipFileContent, $outputFilename, 'zip'); } + public function checkIfSamplesZipForContest(Contest $contest): bool + { + // Note, we reload the contest with the problems and attachments, to reduce the number of queries + // We do not load the testcases here since addSamplesToZip loads them + $contestQuery = $this->em->createQueryBuilder() + ->from(Contest::class, 'c') + ->innerJoin('c.problems', 'cp') + ->innerJoin('cp.problem', 'p') + ->leftJoin('p.attachments', 'a') + ->leftJoin('p.problemStatementContent', 'content') + ->select('c', 'cp', 'p', 'a', 'content') + ->andWhere('c.cid = :cid') + ->andWhere('cp.allowSubmit = 1') // Do we need this... + ->setParameter('cid', $contest->getCid()); + + /** @var Contest $contest */ + $contest = $contestQuery->getQuery()->getOneOrNullResult(); + if ($contest->getContestProblemsetType()) { + return true; + } + + /** @var Problem[] $nonInteractiveProblems */ + $nonInteractiveProblems = $contestQuery + ->innerJoin('p.testcases', 'tc') + ->andWhere('tc.sample = 1') + ->andWhere('BIT_AND(p.types, :interactiveType) = 0') + ->setParameter('interactiveType', Problem::TYPE_INTERACTIVE) + ->getQuery() + ->getResult(); + if (!empty($nonInteractiveProblems)) { + return true; + } + + /** @var Problem[] $problemsWithProblemStatement */ + $problemsWithProblemStatement = $contestQuery + ->andWhere('p.problemstatementFile IS NOT NULL') + ->getQuery() + ->getResult(); + if (!empty($problemsWithProblemStatement)) { + return true; + } + + /** @var Problem[] $problemsWithAttachments */ + $problemsWithAttachments = $contestQuery + ->innerJoin('p.attachments', 'a') + ->getQuery() + ->getResult(); + if (!empty($problemsWithAttachments)) { + return true; + } + + return false; + } + public function getSamplesZipForContest(Contest $contest): StreamedResponse { + // When updating this, also update checkIfSamplesZipForContest. + // Note, we reload the contest with the problems and attachments, to reduce the number of queries // We do not load the testcases here since addSamplesToZip loads them /** @var Contest $contest */ @@ -1097,6 +1153,7 @@ public function getTwigDataForProblemsAction( 'problems' => $problems, 'samples' => $samples, 'showLimits' => $showLimits, + 'showSamples' => $contest && $this->checkIfSamplesZipForContest($contest), 'defaultMemoryLimit' => $defaultMemoryLimit, 'timeFactorDiffers' => $timeFactorDiffers, 'clarifications' => $clars, diff --git a/webapp/templates/partials/problem_list.html.twig b/webapp/templates/partials/problem_list.html.twig index b85f2437df..7c042652dc 100644 --- a/webapp/templates/partials/problem_list.html.twig +++ b/webapp/templates/partials/problem_list.html.twig @@ -4,17 +4,24 @@

{{ contest.name | default('Contest') }} problems - {% if contest and show_contest_problemset and contest.contestProblemsetType is not empty %} - {% if contest_problemset_add_cid %} - {% set contest_problemset_url = path(contest_problemset_path, {'cid': contest.cid}) %} - {% else %} - {% set contest_problemset_url = path(contest_problemset_path) %} + {% if contest and show_contest_problemset %} + {% if contest.contestProblemsetType is not empty %} + {% if contest_problemset_add_cid %} + {% set contest_problemset_url = path(contest_problemset_path, {'cid': contest.cid}) %} + {% else %} + {% set contest_problemset_url = path(contest_problemset_path) %} + {% endif %} + + + problemset + + {% endif %} + {% if showSamples %} + + samples + {% endif %} - - - problemset - {% endif %}