Skip to content

Commit def028c

Browse files
committed
Initial version to also display (public) global clarifications
To do this properly we need to think about how to get those cleanly, a lot of data gathering is now handled by DOMJudgeService so the function should be reachable from there. Cleaner would be a dedicated Service which would be better in a dedicated PR as it's currently unclear if we want this.
1 parent 98b0c3a commit def028c

4 files changed

Lines changed: 135 additions & 1 deletion

File tree

webapp/src/Controller/PublicController.php

Lines changed: 78 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,32 @@ public function __construct(
4949
parent::__construct($em, $eventLog, $dj, $kernel);
5050
}
5151

52+
/**
53+
* @return Clarification[]
54+
*/
55+
protected function getGlobalClarifications(?Contest $contest): array
56+
{
57+
if ($contest) {
58+
return $this->em->createQueryBuilder()
59+
->from(Clarification::class, 'c')
60+
->leftJoin('c.problem', 'p')
61+
->leftJoin('c.sender', 's')
62+
->leftJoin('c.recipient', 'r')
63+
->select('c', 'p')
64+
->andWhere('c.contest = :contest')
65+
->andWhere('c.sender IS NULL')
66+
->andWhere('c.recipient IS NULL')
67+
->andWhere('c.submittime <= :time')
68+
->andWhere('c.problem IS NULL')
69+
->setParameter('contest', $contest)
70+
->setparameter('time', time())
71+
->addOrderBy('c.submittime', 'DESC')
72+
->addOrderBy('c.clarid', 'DESC')
73+
->getQuery()->getResult();
74+
}
75+
return [];
76+
}
77+
5278
#[Route(path: '', name: 'public_index')]
5379
#[Route(path: '/scoreboard')]
5480
public function scoreboardAction(
@@ -68,7 +94,6 @@ public function scoreboardAction(
6894
return $this->redirectToRoute('register');
6995
}
7096

71-
7297
if ($static) {
7398
$refreshParams = [
7499
'static' => 1,
@@ -88,6 +113,8 @@ public function scoreboardAction(
88113

89114
if ($static) {
90115
$data['hide_menu'] = true;
116+
} else {
117+
$data['global_clarifications'] = $this->getGlobalClarifications($contest);
91118
}
92119

93120
$data['current_contest'] = $contest;
@@ -98,6 +125,51 @@ public function scoreboardAction(
98125
return $this->render('public/scoreboard.html.twig', $data, $response);
99126
}
100127

128+
#[Route(path: '/clarifications', name: 'public_clarifications')]
129+
public function clarificationsAction(
130+
RequestStack $requestStack,
131+
Request $request,
132+
#[MapQueryParameter(name: 'contest')]
133+
?string $contestId = null
134+
): Response {
135+
$contest = $this->getContestFromRequest($contestId) ?? $this->dj->getCurrentContest(onlyPublic: true);
136+
if (!$contest) {
137+
throw new NotFoundHttpException('No active contest');
138+
}
139+
140+
/** @var Clarification[] $clarifications */
141+
$clarifications = [];
142+
if ($contest->getStartTimeObject()?->getTimestamp() <= time()) {
143+
$clarifications = $this->em->createQueryBuilder()
144+
->from(Clarification::class, 'c')
145+
->leftJoin('c.problem', 'p')
146+
->leftJoin('c.sender', 's')
147+
->leftJoin('c.recipient', 'r')
148+
->select('c', 'p')
149+
->andWhere('c.contest = :contest')
150+
->andWhere('c.sender IS NULL')
151+
->andWhere('c.recipient IS NULL')
152+
->andWhere('c.problem IS NULL')
153+
->andWhere('c.submittime <= :time')
154+
->setParameter('contest', $contest)
155+
->setParameter('time', time())
156+
->addOrderBy('c.submittime', 'DESC')
157+
->addOrderBy('c.clarid', 'DESC')
158+
->getQuery()
159+
->getResult();
160+
}
161+
162+
$data = [
163+
'contest' => $contest,
164+
'global_clarifications' => $clarifications
165+
];
166+
if ($request->isXmlHttpRequest()) {
167+
return $this->render('public/clarifications_general_modal.html.twig', $data);
168+
} else {
169+
return $this->render('public/clarifications_general.html.twig', $data);
170+
}
171+
}
172+
101173
#[Route(path: '/scoreboard.zip', name: 'public_scoreboard_data_zip')]
102174
public function scoreboardDataZipAction(
103175
RequestStack $requestStack,
@@ -194,6 +266,7 @@ public function teamAction(Request $request, string $teamId): Response
194266
'team' => $team,
195267
'showFlags' => $showFlags,
196268
'showAffiliations' => $showAffiliations,
269+
'global_clarifications' => $this->getGlobalClarifications($this->dj->getCurrentContest()),
197270
];
198271

199272
if ($request->isXmlHttpRequest()) {
@@ -474,6 +547,10 @@ public function viewAction(Request $request, string $clarId): Response
474547
{
475548
$categories = $this->config->get('clar_categories');
476549
$contest = $this->dj->getCurrentContest();
550+
if (!$contest) {
551+
throw new NotFoundHttpException('No active contest');
552+
}
553+
477554
/** @var Clarification|null $clarification */
478555
$clarification = $this->em->createQueryBuilder()
479556
->from(Clarification::class, 'c')
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
{% extends 'public/base.html.twig' %}
2+
3+
{% import 'macros.html.twig' as macros %}
4+
5+
{% block title %}View announcements for {{ contest.name }}{% endblock %}
6+
7+
{% block extrahead %}
8+
{{ parent() }}
9+
{{ macros.mathjax_head() }}
10+
<style>
11+
.data-table td a, .data-table td a:hover {
12+
display: block;
13+
text-decoration: none;
14+
color: inherit;
15+
padding: 3px 5px;
16+
}
17+
18+
.data-table tr {
19+
border-bottom: 1px solid silver;
20+
}
21+
22+
.data-table tr:hover {
23+
background: #ffffcc !important;
24+
}
25+
</style>
26+
{% endblock %}
27+
28+
{% block content %}
29+
<h2 class="text-center mt-4">General announcements for {{ contest.name }}</h2>
30+
31+
{% if global_clarifications is empty %}
32+
<p class="nodata">No announcements.</p>
33+
{% else %}
34+
{% include 'partials/clarification_list.html.twig' with {clarifications: global_clarifications} %}
35+
{% endif %}
36+
{% endblock %}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{% extends "partials/modal.html.twig" %}
2+
3+
{% block title %}View announcements for {{ contest.name }}{% endblock %}
4+
5+
{% block content %}
6+
{% if general_clarifications is empty %}
7+
<p class="nodata">No announcements.</p>
8+
{% else %}
9+
{% include 'partials/clarification_list.html.twig' with {clarifications: general_clarifications} %}
10+
{% endif %}
11+
{% endblock %}

webapp/templates/public/menu.html.twig

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,16 @@
2525
{% endif %}
2626
</li>
2727

28+
{% if global_clarifications is defined and global_clarifications %}
29+
<li class="nav-item">
30+
<a class="nav-link{% if current_route starts with 'public_clarifications' %} active{% endif %}"
31+
href="{{ path('public_clarifications') }}"
32+
id="menu_clarifications">
33+
<i class="fas fa-comments"></i> Announcements
34+
</a>
35+
</li>
36+
{% endif %}
37+
2838
{% if is_granted('ROLE_TEAM') %}
2939
<li class="nav-item">
3040
<a class="nav-link" href="{{ path('team_index') }}">

0 commit comments

Comments
 (0)