Skip to content

Commit

Permalink
Add config option to disable ranking information for teams.
Browse files Browse the repository at this point in the history
You likely still want to make the contest non-public to also 'hide' any
ranking information from the public.
  • Loading branch information
meisterT committed Mar 26, 2024
1 parent dd3244f commit 4684bb6
Show file tree
Hide file tree
Showing 7 changed files with 80 additions and 39 deletions.
5 changes: 5 additions & 0 deletions etc/db-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -318,6 +318,11 @@
2: After first submission
regex: /^\d+$/
error_message: A value between 0 and 2 is required.
- name: enable_ranking
type: bool
default_value: true
public: true
description: If disabled, no ranking information is shown to contestants.
- category: Authentication
description: Options related to authentication.
items:
Expand Down
5 changes: 5 additions & 0 deletions webapp/src/Controller/API/ScoreboardController.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
use OpenApi\Attributes as OA;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Attribute\MapQueryParameter;
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;

#[Rest\Route('/contests/{cid}/scoreboard')]
#[OA\Tag(name: 'Scoreboard')]
Expand Down Expand Up @@ -106,6 +107,10 @@ public function getScoreboardAction(
#[MapQueryParameter]
bool $strict = false,
): Scoreboard {
if (!$this->config->get('enable_ranking') && !$this->dj->checkrole('jury')) {
throw new BadRequestHttpException('Scoreboard is not available.');
}

$filter = new Filter();
if ($category) {
$filter->categories = [$category];
Expand Down
9 changes: 9 additions & 0 deletions webapp/src/Controller/Team/ScoreboardController.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
use App\Service\ScoreboardService;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\ExpressionLanguage\Expression;
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
use Symfony\Component\Security\Http\Attribute\IsGranted;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
Expand All @@ -32,6 +33,10 @@ public function __construct(
#[Route(path: '/scoreboard', name: 'team_scoreboard')]
public function scoreboardAction(Request $request): Response
{
if ($this->config->get('enable_ranking')) {
throw new BadRequestHttpException('Scoreboard is not available.');
}

$user = $this->dj->getUser();
$response = new Response();
$contest = $this->dj->getCurrentContest($user->getTeam()->getTeamid());
Expand All @@ -51,6 +56,10 @@ public function scoreboardAction(Request $request): Response
#[Route(path: '/team/{teamId<\d+>}', name: 'team_team')]
public function teamAction(Request $request, int $teamId): Response
{
if ($this->config->get('enable_ranking')) {
throw new BadRequestHttpException('Scoreboard is not available.');
}

/** @var Team|null $team */
$team = $this->em->getRepository(Team::class)->find($teamId);
if ($team && $team->getCategory() && !$team->getCategory()->getVisible() && $teamId !== $this->dj->getUser()->getTeamId()) {
Expand Down
1 change: 1 addition & 0 deletions webapp/src/Twig/TwigExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,7 @@ public function getGlobals(): array
$this->config->get('data_source') === DOMJudgeService::DATA_SOURCE_CONFIGURATION_AND_LIVE_EXTERNAL,
'doc_links' => $this->dj->getDocLinks(),
'allow_registration' => $selfRegistrationCategoriesCount !== 0,
'enable_ranking' => $this->config->get('enable_ranking'),
];
}

Expand Down
19 changes: 12 additions & 7 deletions webapp/templates/partials/scoreboard_summary.html.twig
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,20 @@
{% if showAffiliationLogos %}
{% set summaryColspan = summaryColspan + 1 %}
{% endif %}
{% if not enable_ranking %}
{% set summaryColspan = summaryColspan - 1 %}
{% endif %}
<td class="scoresummary" title="Summary" colspan="{{ summaryColspan }}">Summary</td>
{% if scoreboard.showPoints %}
<td class="scorenc"></td>
{% else %}
<td title="total solved" class="scorenc">
{{ scoreboard.summary.numberOfPoints(sortOrder) }}
</td>
{% if enable_ranking %}
{% if scoreboard.showPoints %}
<td class="scorenc"></td>
{% else %}
<td title="total solved" class="scorenc">
{{ scoreboard.summary.numberOfPoints(sortOrder) }}
</td>
{% endif %}
<td></td>
{% endif %}
<td></td>
{% for problem in scoreboard.problems %}
{% set summary = scoreboard.summary.problem(problem.probid) %}
<td style="text-align: left;">
Expand Down
70 changes: 42 additions & 28 deletions webapp/templates/partials/scoreboard_table.html.twig
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,9 @@
{# output table column groups (for the styles) #}
<colgroup>
<col id="scorerank"/>
{% if enable_ranking %}
<col id="scorerank"/>
{% endif %}
{% if showFlags %}
<col id="scoreflags"/>
{% else %}
Expand All @@ -43,10 +45,12 @@
{% endif %}
<col id="scoreteamname"/>
</colgroup>
<colgroup>
<col id="scoresolv"/>
<col id="scoretotal"/>
</colgroup>
{% if enable_ranking %}
<colgroup>
<col id="scoresolv"/>
<col id="scoretotal"/>
</colgroup>
{% endif %}
<colgroup>
{% if showTeamSubmissions or jury %}
{% for problem in problems %}
Expand All @@ -62,9 +66,13 @@
<thead>
<tr class="scoreheader" data-static="{{ static }}">
<th title="rank" scope="col">rank</th>
{% if enable_ranking %}
<th title="rank" scope="col">rank</th>
{% endif %}
<th title="team name" scope="col" colspan="{{ teamColspan }}">team</th>
<th title="# solved / penalty time" colspan="2" scope="col">score</th>
{% if enable_ranking %}
<th title="# solved / penalty time" colspan="2" scope="col">score</th>
{% endif %}
{% if showTeamSubmissions or jury %}
{% for problem in problems %}
{% set link = null %}
Expand Down Expand Up @@ -127,16 +135,18 @@
{% set color = score.team.category.color %}
{% endif %}
<tr class="{{ classes | join(' ') }}" id="team:{{ score.team.teamid }}">
<td class="scorepl {{medalColor}}">
{# Only print rank when score is different from the previous team #}
{% if not displayRank %}
?
{% elseif previousTeam is null or scoreboard.scores[previousTeam.teamid].rank != score.rank %}
{{ score.rank }}
{% else %}
{% endif %}
{% set previousTeam = score.team %}
</td>
{% if enable_ranking %}
<td class="scorepl {{medalColor}}">
{# Only print rank when score is different from the previous team #}
{% if not displayRank %}
?
{% elseif previousTeam is null or scoreboard.scores[previousTeam.teamid].rank != score.rank %}
{{ score.rank }}
{% else %}
{% endif %}
{% set previousTeam = score.team %}
</td>
{% endif %}
<td class="scoreaf">
{% if showFlags %}
{% if score.team.affiliation %}
Expand Down Expand Up @@ -220,12 +230,14 @@
{% if scoreInSeconds %}
{% set totalTime = totalTime | printTimeRelative %}
{% endif %}
{% set totalPoints = score.numPoints %}
<td class="scorenc">{{ totalPoints }}</td>
{% if scoreboard.getRuntimeAsScoreTiebreaker() %}
<td class="scorett">{{ "%0.3f s" | format(score.totalRuntime/1000.0) }}</td>
{% else %}
<td class="scorett">{{ totalTime }}</td>
{% if enable_ranking %}
{% set totalPoints = score.numPoints %}
<td class="scorenc">{{ totalPoints }}</td>
{% if scoreboard.getRuntimeAsScoreTiebreaker() %}
<td class="scorett">{{ "%0.3f s" | format(score.totalRuntime/1000.0) }}</td>
{% else %}
<td class="scorett">{{ totalTime }}</td>
{% endif %}
{% endif %}
{% if showTeamSubmissions or jury %}
Expand All @@ -235,11 +247,13 @@
{% set matrixItem = scoreboard.matrix[score.team.teamid][problem.probid] %}
{% if matrixItem.isCorrect %}
{% set scoreCssClass = 'score_correct' %}
{% if not scoreboard.getRuntimeAsScoreTiebreaker() and scoreboard.solvedFirst(score.team, problem) %}
{% set scoreCssClass = scoreCssClass ~ ' score_first' %}
{% endif %}
{% if scoreboard.getRuntimeAsScoreTiebreaker() and scoreboard.isFastestSubmission(score.team, problem) %}
{% set scoreCssClass = scoreCssClass ~ ' score_first' %}
{% if enable_ranking %}
{% if not scoreboard.getRuntimeAsScoreTiebreaker() and scoreboard.solvedFirst(score.team, problem) %}
{% set scoreCssClass = scoreCssClass ~ ' score_first' %}
{% endif %}
{% if scoreboard.getRuntimeAsScoreTiebreaker() and scoreboard.isFastestSubmission(score.team, problem) %}
{% set scoreCssClass = scoreCssClass ~ ' score_first' %}
{% endif %}
{% endif %}
{% elseif showPending and matrixItem.numSubmissionsPending > 0 %}
{% set scoreCssClass = 'score_pending' %}
Expand Down
10 changes: 6 additions & 4 deletions webapp/templates/team/menu.html.twig
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,12 @@
href="{{ path('team_print') }}"><i class="fas fa-file-alt"></i> Print</a>
</li>
{% endif %}
<li class="nav-item">
<a class="nav-link{% if current_route in ['team_scoreboard', 'team_team'] %} active{% endif %}"
href="{{ path('team_scoreboard') }}"><i class="fas fa-list-ol"></i> Scoreboard</a>
</li>
{% if enable_ranking %}
<li class="nav-item">
<a class="nav-link{% if current_route in ['team_scoreboard', 'team_team'] %} active{% endif %}"
href="{{ path('team_scoreboard') }}"><i class="fas fa-list-ol"></i> Scoreboard</a>
</li>
{% endif %}
{% if doc_links is not empty %}
<li class="nav-item">
<a class="nav-link{% if current_route in ['team_docs'] %} active{% endif %}"
Expand Down

0 comments on commit 4684bb6

Please sign in to comment.