Skip to content

Commit 53bfad2

Browse files
Allow multiple categories per team
Part of #2937
1 parent 7d46e07 commit 53bfad2

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+363
-156
lines changed
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace DoctrineMigrations;
6+
7+
use Doctrine\DBAL\Schema\Schema;
8+
use Doctrine\Migrations\AbstractMigration;
9+
10+
/**
11+
* Auto-generated Migration: Please modify to your needs!
12+
*/
13+
final class Version20250620090108 extends AbstractMigration
14+
{
15+
public function getDescription(): string
16+
{
17+
return '';
18+
}
19+
20+
public function up(Schema $schema): void
21+
{
22+
// this up() migration is auto-generated, please modify it to your needs
23+
$this->addSql('CREATE TABLE team_category_team (categoryid INT UNSIGNED NOT NULL COMMENT \'Team category ID\', teamid INT UNSIGNED NOT NULL COMMENT \'Team ID\', INDEX IDX_3A19F9C99B32FD3 (categoryid), INDEX IDX_3A19F9C94DD6ABF3 (teamid), PRIMARY KEY(categoryid, teamid)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB');
24+
$this->addSql('ALTER TABLE team_category_team ADD CONSTRAINT FK_3A19F9C99B32FD3 FOREIGN KEY (categoryid) REFERENCES team_category (categoryid) ON DELETE CASCADE');
25+
$this->addSql('ALTER TABLE team_category_team ADD CONSTRAINT FK_3A19F9C94DD6ABF3 FOREIGN KEY (teamid) REFERENCES team (teamid) ON DELETE CASCADE');
26+
$this->addSql('INSERT INTO team_category_team (categoryid, teamid) SELECT categoryid, teamid FROM team');
27+
$this->addSql('ALTER TABLE team DROP FOREIGN KEY team_ibfk_1');
28+
$this->addSql('DROP INDEX categoryid ON team');
29+
$this->addSql('ALTER TABLE team DROP categoryid');
30+
}
31+
32+
public function down(Schema $schema): void
33+
{
34+
// this down() migration is auto-generated, please modify it to your needs
35+
$this->addSql('ALTER TABLE team ADD categoryid INT UNSIGNED DEFAULT NULL COMMENT \'Team category ID\'');
36+
$this->addSql('ALTER TABLE team ADD CONSTRAINT team_ibfk_1 FOREIGN KEY (categoryid) REFERENCES team_category (categoryid) ON DELETE CASCADE');
37+
$this->addSql('CREATE INDEX categoryid ON team (categoryid)');
38+
$this->addSql('UPDATE team SET categoryid = (SELECT MIN(categoryid) from team_category_team WHERE team_category_team.teamid = team.teamid)');
39+
$this->addSql('ALTER TABLE team_category_team DROP FOREIGN KEY FK_3A19F9C99B32FD3');
40+
$this->addSql('ALTER TABLE team_category_team DROP FOREIGN KEY FK_3A19F9C94DD6ABF3');
41+
$this->addSql('DROP TABLE team_category_team');
42+
}
43+
44+
public function isTransactional(): bool
45+
{
46+
return false;
47+
}
48+
}

webapp/src/Command/ScoreboardMergeCommand.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -213,7 +213,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int
213213
$teamObj->setAffiliation($affiliations[$organizationName]);
214214
}
215215

216-
$teamObj->setCategory($category);
216+
$teamObj->addCategory($category);
217217
$oldid = $team['id'];
218218
$newid = $nextTeamId++;
219219
$teamObj->setTeamid($newid);

webapp/src/Controller/API/MetricsController.php

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,8 @@ public function prometheusAction(): Response
7979
->select('t', 'u')
8080
->from(Team::class, 't')
8181
->leftJoin('t.users', 'u')
82-
->join('t.category', 'cat')
82+
// TODO: category type
83+
->join('t.categories', 'cat')
8384
->andWhere('cat.visible = true')
8485
->getQuery()
8586
->getResult();
@@ -89,7 +90,8 @@ public function prometheusAction(): Response
8990
->select('u')
9091
->from(User::class, 'u')
9192
->leftJoin('u.team', 't')
92-
->join('t.category', 'cat')
93+
// TODO: category type
94+
->join('t.categories', 'cat')
9395
->andWhere('cat.visible = true')
9496
->getQuery()
9597
->getResult();
@@ -134,7 +136,8 @@ public function prometheusAction(): Response
134136
->from(Team::class, 't')
135137
->leftJoin('t.users', 'u')
136138
->leftJoin('t.contests', 'c')
137-
->join('t.category', 'cat')
139+
// TODO: category type
140+
->join('t.categories', 'cat')
138141
->leftJoin('cat.contests', 'cc')
139142
->andWhere('c.cid = :cid OR cc.cid = :cid')
140143
->andWhere('cat.visible = true')
@@ -154,7 +157,8 @@ public function prometheusAction(): Response
154157
->from(User::class, 'u')
155158
->leftJoin('u.team', 't')
156159
->leftJoin('t.contests', 'c')
157-
->join('t.category', 'cat')
160+
// TODO: category type
161+
->join('t.categories', 'cat')
158162
->leftJoin('cat.contests', 'cc')
159163
->andWhere('c.cid = :cid OR cc.cid = :cid')
160164
->andWhere('cat.visible = true')
@@ -227,7 +231,8 @@ public function prometheusAction(): Response
227231
->join('b.submission', 's')
228232
->join('s.contest', 'c')
229233
->join('s.team', 't')
230-
->join('t.category', 'cat')
234+
// TODO: category type
235+
->join('t.categories', 'cat')
231236
->andWhere('b.done = false')
232237
->andWhere('c.cid = :cid')
233238
->andWhere('cat.visible = true')

webapp/src/Controller/API/ScoreboardController.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,7 @@ public function getScoreboardAction(
171171
$scoreIsInSeconds = (bool)$this->config->get('score_in_seconds');
172172

173173
foreach ($scoreboard->getScores() as $teamScore) {
174-
if ($teamScore->team->getCategory()->getSortorder() !== $sortorder) {
174+
if ($teamScore->team->getSortorder() !== $sortorder) {
175175
continue;
176176
}
177177

webapp/src/Controller/API/SubmissionController.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -461,7 +461,8 @@ protected function getQueryBuilder(Request $request): QueryBuilder
461461
if (!$this->dj->checkrole('api_reader') &&
462462
!$this->dj->checkrole('judgehost')) {
463463
$queryBuilder
464-
->join('t.category', 'cat');
464+
// TODO: category type
465+
->join('t.categories', 'cat');
465466
if ($this->dj->checkrole('team')) {
466467
$queryBuilder
467468
->andWhere('cat.visible = 1 OR s.team = :team')

webapp/src/Controller/API/TeamController.php

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -305,14 +305,15 @@ protected function getQueryBuilder(Request $request): QueryBuilder
305305
$queryBuilder = $this->em->createQueryBuilder()
306306
->from(Team::class, 't')
307307
->leftJoin('t.affiliation', 'ta')
308-
->leftJoin('t.category', 'tc')
308+
// TODO: category type
309+
->leftJoin('t.categories', 'tc')
309310
->leftJoin('t.contests', 'c')
310311
->leftJoin('tc.contests', 'cc')
311312
->select('t, ta');
312313

313314
if ($request->query->has('category')) {
314315
$queryBuilder
315-
->andWhere('t.category = :category')
316+
->andWhere('tc.categoryid = :category')
316317
->setParameter('category', $request->query->get('category'));
317318
}
318319

webapp/src/Controller/Jury/ContestController.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,7 @@ public function indexAction(Request $request): Response
216216
->select('COUNT(DISTINCT t.teamid)')
217217
->from(Team::class, 't')
218218
->leftJoin('t.contests', 'c')
219-
->join('t.category', 'cat')
219+
->join('t.categories', 'cat')
220220
->leftJoin('cat.contests', 'cc')
221221
->andWhere('c.cid = :cid OR cc.cid = :cid')
222222
->setParameter('cid', $contest->getCid())

webapp/src/Controller/Jury/ImportExportController.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -487,7 +487,7 @@ protected function getResultsHtml(
487487
'rank' => null,
488488
];
489489
foreach ($teams as $team) {
490-
if (!isset($categories[$team->getCategory()->getCategoryid()]) || $team->getCategory()->getSortorder() !== $sortOrder) {
490+
if ($team->getHidden() || $team->getSortorder() !== $sortOrder) {
491491
continue;
492492
}
493493

webapp/src/Controller/Jury/JudgeRemainingTrait.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ public function judgeRemaining(int $contestId = -1, string $categoryId = '', str
8080
->select('j')
8181
->join('j.submission', 's')
8282
->join('s.team', 't')
83-
->join('t.category', 'tc')
83+
->join('t.categories', 'tc')
8484
->andWhere('j.valid = true')
8585
->andWhere('j.result != :compiler_error')
8686
->setParameter('compiler_error', 'compiler-error');

webapp/src/Controller/Jury/SubmissionController.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1144,7 +1144,7 @@ public function verifyAction(
11441144
if (!$judging->getContest()->isOpenToAllTeams()) {
11451145
$teamsQueryBuilder
11461146
->leftJoin('t.contests', 'c')
1147-
->join('t.category', 'cat')
1147+
->join('t.categories', 'cat')
11481148
->leftJoin('cat.contests', 'cc')
11491149
->andWhere('c.cid = :cid OR cc.cid = :cid')
11501150
->setParameter('cid', $judging->getContest()->getCid());

webapp/src/Controller/Jury/TeamController.php

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ public function indexAction(): Response
5151
->from(Team::class, 't')
5252
->leftJoin('t.contests', 'c')
5353
->leftJoin('t.affiliation', 'a')
54-
->leftJoin('t.category', 'cat')
54+
->leftJoin('t.categories', 'cat')
5555
->leftJoin('cat.contests', 'cc')
5656
->orderBy('cat.sortorder', 'ASC')
5757
->addOrderBy('t.name', 'ASC')
@@ -93,7 +93,8 @@ public function indexAction(): Response
9393
'externalid' => ['title' => 'external ID', 'sort' => true],
9494
'label' => ['title' => 'label', 'sort' => true,],
9595
'effective_name' => ['title' => 'name', 'sort' => true,],
96-
'category' => ['title' => 'category', 'sort' => true,],
96+
'category' => ['title' => 'sort order category', 'sort' => true,],
97+
'num_categories' => ['title' => '# categories', 'sort' => true,],
9798
'affiliation' => ['title' => 'affiliation', 'sort' => true,],
9899
'num_contests' => ['title' => '# contests', 'sort' => true,],
99100
'ip_address' => ['title' => 'last IP', 'sort' => true,],
@@ -122,6 +123,9 @@ public function indexAction(): Response
122123
}
123124
}
124125

126+
$teamdata['category'] = ['value' => $t->getSortOrderCategory()];
127+
$teamdata['num_categories'] = ['value' => $t->getCategories()->count()];
128+
125129
// Add some elements for the solved status.
126130
$num_solved = 0;
127131
$num_submitted = 0;
@@ -189,8 +193,8 @@ public function indexAction(): Response
189193
foreach ($t->getContests() as $c) {
190194
$teamContests[$c->getCid()] = true;
191195
}
192-
if ($t->getCategory()) {
193-
foreach ($t->getCategory()->getContests() as $c) {
196+
foreach ($t->getCategories() as $category) {
197+
foreach ($category->getContests() as $c) {
194198
$teamContests[$c->getCid()] = true;
195199
}
196200
}
@@ -212,7 +216,8 @@ public function indexAction(): Response
212216
'data' => $teamdata,
213217
'actions' => $teamactions,
214218
'link' => $this->generateUrl('jury_team', ['teamId' => $t->getTeamId()]),
215-
'cssclass' => ($t->getCategory() ? ("category" . $t->getCategory()->getCategoryId()) : '') .
219+
// TODO: category type
220+
'cssclass' => ($t->getCategories()->first() ? ("category" . $t->getCategories()->first()->getCategoryId()) : '') .
216221
($t->getEnabled() ? '' : ' disabled'),
217222
];
218223
}

webapp/src/Controller/PublicController.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ public function teamAction(Request $request, int $teamId): Response
168168
{
169169
/** @var Team|null $team */
170170
$team = $this->em->getRepository(Team::class)->find($teamId);
171-
if ($team && $team->getCategory() && !$team->getCategory()->getVisible()) {
171+
if ($team?->getHidden()) {
172172
$team = null;
173173
}
174174
$showFlags = (bool)$this->config->get('show_flags');

webapp/src/Controller/SecurityController.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ public function registerAction(
133133
->setExternalid(Uuid::uuid4()->toString())
134134
->addUser($user)
135135
->setName($teamName)
136-
->setCategory($teamCategory)
136+
->addCategory($teamCategory)
137137
->setInternalComments('Registered by ' . $this->dj->getClientIp() . ' on ' . date('r'));
138138

139139
if ($this->config->get('show_affiliations')) {

webapp/src/Controller/Team/ScoreboardController.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ public function teamAction(Request $request, int $teamId): Response
6868

6969
/** @var Team|null $team */
7070
$team = $this->em->getRepository(Team::class)->find($teamId);
71-
if ($team && $team->getCategory() && !$team->getCategory()->getVisible() && $teamId !== $this->dj->getUser()->getTeamId()) {
71+
if ($team?->getHidden() && $teamId !== $this->dj->getUser()->getTeamId()) {
7272
$team = null;
7373
}
7474
$showFlags = (bool)$this->config->get('show_flags');

webapp/src/DataFixtures/DefaultData/TeamFixture.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ public function load(ObjectManager $manager): void
2323
->setName('DOMjudge')
2424
->setExternalid('domjudge')
2525
->setLabel('domjudge')
26-
->setCategory($this->getReference(TeamCategoryFixture::SYSTEM_REFERENCE, TeamCategory::class));
26+
->addCategory($this->getReference(TeamCategoryFixture::SYSTEM_REFERENCE, TeamCategory::class));
2727
$manager->persist($team);
2828
} else {
2929
$this->logger->info('Team DOMjudge already exists, not created');

webapp/src/DataFixtures/ExampleData/TeamFixture.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ public function load(ObjectManager $manager): void
2121
->setLabel('exteam')
2222
->setName('Example teamname')
2323
->setAffiliation($this->getReference(TeamAffiliationFixture::AFFILIATION_REFERENCE, TeamAffiliation::class))
24-
->setCategory($this->getReference(TeamCategoryFixture::PARTICIPANTS_REFERENCE, TeamCategory::class));
24+
->addCategory($this->getReference(TeamCategoryFixture::PARTICIPANTS_REFERENCE, TeamCategory::class));
2525

2626
$manager->persist($team);
2727
$manager->flush();
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<?php declare(strict_types=1);
2+
3+
namespace App\DataFixtures\Test;
4+
5+
use App\DataFixtures\ExampleData\TeamAffiliationFixture;
6+
use App\Entity\Team;
7+
use App\Entity\TeamAffiliation;
8+
use App\Entity\TeamCategory;
9+
use Doctrine\Persistence\ObjectManager;
10+
11+
class CreateTeamWithTwoTeamAffiliationsFixture extends AbstractTestDataFixture
12+
{
13+
public function load(ObjectManager $manager): void
14+
{
15+
$team = new Team();
16+
$team
17+
->setExternalid('teamwithtwogroups')
18+
->setIcpcid('teamwithtwogroups')
19+
->setLabel('teamwithtwogroups')
20+
->setName('Team with two groups')
21+
->setAffiliation($manager->getRepository(TeamAffiliation::class)->findOneBy(['externalid' => 'utrecht']))
22+
->addCategory($manager->getRepository(TeamCategory::class)->findOneBy(['externalid' => 'participants']))
23+
->addCategory($manager->getRepository(TeamCategory::class)->findOneBy(['externalid' => 'observers']));
24+
25+
$manager->persist($team);
26+
$manager->flush();
27+
}
28+
}

webapp/src/DataFixtures/Test/RejudgingFirstToSolveFixture.php

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,10 @@ public function load(ObjectManager $manager): void
1717
{
1818
$team1 = $manager->getRepository(Team::class)->findOneBy(['name' => 'Example teamname']);
1919
$team2 = (new Team())
20-
->setName('Another team')
21-
->setCategory($team1->getCategory());
20+
->setName('Another team');
21+
foreach ($team1->getCategories() as $category) {
22+
$team2->addCategory($category);
23+
}
2224

2325
$manager->persist($team2);
2426

0 commit comments

Comments
 (0)