Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add location to team API. #2296

Merged
merged 2 commits into from
Jan 19, 2024
Merged
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
1 change: 1 addition & 0 deletions ChangeLog
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ Version 8.3.0DEV
- Fix medal awards when skipping categories.
- Add direct button to public page for registering when enabled.
- Scale batch size of judge tasks dynamically.
- Rename room to location for teams.

Version 8.2.0 - 6 March 2023
----------------------------
Expand Down
4 changes: 2 additions & 2 deletions doc/manual/import.rst
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ fields:
- ``display_name`` (optional): the team display name. If provided, will display
this instead of the team name in certain places, like the scoreboard
- ``organization_id``: the ID of the team affiliation this team belongs to
- ``room`` (optional): the room of the team
- ``location.description`` (optional): the location of the team

If the ``data_source`` setting of DOMjudge is set to external, the ``id`` field will be the
ID used for the team and the ``group_ids`` and ``organization_id`` fields are the values as
Expand All @@ -183,7 +183,7 @@ Example ``teams.json``::
"group_ids": ["24"],
"name": "¡i¡i¡",
"organization_id": "INST-42",
"room": "AUD 10"
"location": {"description": "AUD 10"}
}, {
"id": "2",
"icpc_id": "447837",
Expand Down
36 changes: 36 additions & 0 deletions webapp/migrations/Version20240112100916.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<?php

declare(strict_types=1);

namespace DoctrineMigrations;

use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;

/**
* Auto-generated Migration: Please modify to your needs!
*/
final class Version20240112100916 extends AbstractMigration
{
public function getDescription(): string
{
return 'Change room to location for teams.';
}

public function up(Schema $schema): void
{
// this up() migration is auto-generated, please modify it to your needs
$this->addSql('ALTER TABLE team CHANGE room location VARCHAR(255) DEFAULT NULL COMMENT \'Physical location of team\'');
}

public function down(Schema $schema): void
{
// this down() migration is auto-generated, please modify it to your needs
$this->addSql('ALTER TABLE team CHANGE location room VARCHAR(255) DEFAULT NULL COMMENT \'Physical location of team\'');
}

public function isTransactional(): bool
{
return false;
}
}
2 changes: 1 addition & 1 deletion webapp/public/js/domjudge.js
Original file line number Diff line number Diff line change
Expand Up @@ -658,7 +658,7 @@ function updateMenuBalloons(data)
$("#num-alerts-balloons").html(num);
$("#num-alerts-balloons").show();
for (var i=0; i<num; i++) {
var text = (data[i].room !== null) ? data[i].room+': ' : '';
var text = (data[i].location !== null) ? data[i].location+': ' : '';
text += data[i].pname + ' ' + data[i].name;
sendNotification('New balloon:',
{'tag': 'ball_' + data[i].baloonid,
Expand Down
6 changes: 3 additions & 3 deletions webapp/src/Controller/Jury/BalloonController.php
Original file line number Diff line number Diff line change
Expand Up @@ -91,10 +91,10 @@ public function indexAction(BalloonService $balloonService): Response
if (isset($filters['location-str'])) {
/** @var Team[] $filteredLocations */
$filteredLocations = $this->em->createQueryBuilder()
->from(Team::class, 'a', 'a.room')
->from(Team::class, 'a', 'a.location')
->select('a')
->where('a.room IN (:rooms)')
->setParameter('rooms', $filters['location-str'])
->where('a.location IN (:locations)')
->setParameter('locations', $filters['location-str'])
->getQuery()
->getResult();
}
Expand Down
10 changes: 5 additions & 5 deletions webapp/src/Controller/Jury/JuryMiscController.php
Original file line number Diff line number Diff line change
Expand Up @@ -83,15 +83,15 @@ public function ajaxDataAction(Request $request, string $datatype): JsonResponse
}, $affiliations);
} elseif ($datatype === 'locations') {
$locations = $qb->from(Team::class, 'a')
->select('DISTINCT a.room')
->where($qb->expr()->like('a.room', '?1'))
->orderBy('a.room', 'ASC')
->select('DISTINCT a.location')
->where($qb->expr()->like('a.location', '?1'))
->orderBy('a.location', 'ASC')
->getQuery()->setParameter(1, '%' . $q . '%')
->getResult();

$results = array_map(fn(array $location) => [
'id' => $location['room'],
'text' => $location['room']
'id' => $location['location'],
'text' => $location['location']
], $locations);
} elseif (!$this->isGranted('ROLE_JURY')) {
throw new AccessDeniedHttpException('Permission denied');
Expand Down
2 changes: 1 addition & 1 deletion webapp/src/Controller/Jury/TeamController.php
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ public function indexAction(): Response
'affiliation' => ['title' => 'affiliation', 'sort' => true,],
'num_contests' => ['title' => '# contests', 'sort' => true,],
'ip_address' => ['title' => 'last IP', 'sort' => true,],
'room' => ['title' => 'room', 'sort' => true,],
'location' => ['title' => 'location', 'sort' => true,],
'status' => ['title' => '', 'sort' => false,],
'stats' => ['title' => 'stats', 'sort' => true,],
];
Expand Down
2 changes: 1 addition & 1 deletion webapp/src/Controller/Team/MiscController.php
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ public function printAction(Request $request): Response
$teamId = (string)$team->getTeamid();
}
$ret = $this->dj->printFile($realfile, $originalfilename, $langid,
$username, $team->getEffectiveName(), $teamId, $team->getRoom());
$username, $team->getEffectiveName(), $teamId, $team->getLocation());

return $this->render('team/print_result.html.twig', [
'success' => $ret[0],
Expand Down
16 changes: 16 additions & 0 deletions webapp/src/DataFixtures/Test/AddLocationToTeamFixture.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?php declare(strict_types=1);

namespace App\DataFixtures\Test;

use App\Entity\Team;
use Doctrine\Persistence\ObjectManager;

class AddLocationToTeamFixture extends AbstractTestDataFixture
{
public function load(ObjectManager $manager): void
{
$team = $manager->getRepository(Team::class)->findOneBy(['name' => 'Example teamname']);
$team->setLocation('Utrecht');
$manager->flush();
}
}
20 changes: 15 additions & 5 deletions webapp/src/Entity/Team.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace App\Entity;

use App\Controller\API\AbstractRestController as ARC;
use App\Helpers\TeamLocation;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
Expand Down Expand Up @@ -87,8 +88,9 @@ class Team extends BaseApiEntity implements ExternalRelationshipEntityInterface,
private ?string $publicDescription = null;

#[ORM\Column(nullable: true, options: ['comment' => 'Physical location of team'])]
#[OA\Property(nullable: true)]
#[Serializer\Exclude]
private ?string $room = null;
private ?string $location = null;

#[ORM\Column(
name: 'internalcomments',
Expand Down Expand Up @@ -285,15 +287,23 @@ public function getPublicDescription(): ?string
return $this->publicDescription;
}

public function setRoom(?string $room): Team
public function setLocation(?string $location): Team
{
$this->room = $room;
$this->location = $location;
return $this;
}

public function getRoom(): ?string
public function getLocation(): ?string
{
return $this->location;
}

#[Serializer\Groups([ARC::GROUP_NONSTRICT])]
#[Serializer\VirtualProperty]
#[Serializer\SerializedName('location')]
public function getLocationForApi(): ?TeamLocation
{
return $this->room;
return $this->location ? new TeamLocation($this->location) : null;
}

public function setInternalComments(?string $comments): Team
Expand Down
2 changes: 1 addition & 1 deletion webapp/src/Form/Type/TeamType.php
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ public function buildForm(FormBuilderInterface $builder, array $options): void
$builder->add('penalty', IntegerType::class, [
'label' => 'Penalty time',
]);
$builder->add('room', TextType::class, [
$builder->add('location', TextType::class, [
'label' => 'Location',
'required' => false,
]);
Expand Down
10 changes: 10 additions & 0 deletions webapp/src/Helpers/TeamLocation.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?php declare(strict_types=1);

namespace App\Helpers;

class TeamLocation
{
public function __construct(
public readonly string $description
) {}
}
4 changes: 2 additions & 2 deletions webapp/src/Service/BalloonService.php
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ public function collectBalloonTable(Contest $contest, bool $todo = false): array

$query = $em->createQueryBuilder()
->select('b', 's.submittime', 'p.probid',
't.teamid', 's', 't', 't.room',
't.teamid', 's', 't', 't.location',
'c.categoryid AS categoryid', 'c.name AS catname',
'co.cid', 'co.shortname',
'cp.shortname AS probshortname', 'cp.color',
Expand Down Expand Up @@ -159,7 +159,7 @@ public function collectBalloonTable(Contest $contest, bool $todo = false): array
$balloondata['contestproblem'] = $balloon->getSubmission()->getContestProblem();
$balloondata['team'] = $balloon->getSubmission()->getTeam();
$balloondata['teamid'] = $balloonsData['teamid'];
$balloondata['location'] = $balloonsData['room'];
$balloondata['location'] = $balloonsData['location'];
$balloondata['affiliation'] = $balloonsData['affilshort'];
$balloondata['affiliationid'] = $balloonsData['affilid'];
$balloondata['category'] = $balloonsData['catname'];
Expand Down
4 changes: 2 additions & 2 deletions webapp/src/Service/DOMJudgeService.php
Original file line number Diff line number Diff line change
Expand Up @@ -410,7 +410,7 @@ public function getUpdates(): array

if ($this->checkrole('balloon')) {
$balloonsQuery = $this->em->createQueryBuilder()
->select('b.balloonid', 't.name', 't.room', 'p.name AS pname')
->select('b.balloonid', 't.name', 't.location', 'p.name AS pname')
->from(Balloon::class, 'b')
->leftJoin('b.submission', 's')
->leftJoin('s.problem', 'p')
Expand Down Expand Up @@ -714,7 +714,7 @@ public function openZipFile(string $filename): ZipArchive
* @param string $username Username of the print job submitter
* @param string|null $teamname Teamname of the team this user belongs to, if any
* @param string|null $teamid Teamid of the team this user belongs to, if any
* @param string|null $location Room/place of the team, if any.
* @param string|null $location Location of the team, if any.
*/
public function printFile(
string $filename,
Expand Down
4 changes: 2 additions & 2 deletions webapp/src/Service/ICPCCmsService.php
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ public function importTeams(string $token, string $contest, ?string &$message =
->setEnabled($enabled)
->setInternalComments('Status: ' . $teamData['status'])
->setIcpcid($teamData['teamId'])
->setRoom($siteName);
->setLocation($siteName);
$this->em->persist($team);
$this->em->flush();
$username = sprintf("team%04d", $team->getTeamid());
Expand All @@ -137,7 +137,7 @@ public function importTeams(string $token, string $contest, ?string &$message =
->setEnabled($enabled)
->setInternalComments('Status: ' . $teamData['status'])
->setIcpcid($teamData['teamId'])
->setRoom($siteName);
->setLocation($siteName);

$user = $this->em->getRepository(User::class)->findOneBy(['username' => $username]);
$user?->setName($teamData['teamName']);
Expand Down
2 changes: 1 addition & 1 deletion webapp/src/Service/ImportExportService.php
Original file line number Diff line number Diff line change
Expand Up @@ -854,7 +854,7 @@ public function importTeamsJson(array $data, ?string &$message = null, ?array &$
'name' => @$team['name'],
'display_name' => @$team['display_name'],
'publicdescription' => $team['public_description'] ?? @$team['members'],
'room' => @$team['room'],
'location' => @$team['location']['description'],
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a way how we can now just if unset pick the x,y,rot and put it as a string?

Copy link
Contributor

@cubercsl cubercsl Jan 17, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Usually we use the seat number (such as B05) for the location here, but x, y, rot in the ccs spec represent distance and rotation angle. I don't think they correspond well directly.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can already use the description field, so for your usecase you would put the seat number there (or would you still need more?)

I'm suggesting the situation where that field is not set and the spec is followed. During the ICPC WF we would get the information in DOMjudge without much extra effort so we know where a team would be located in case of problems.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But then if you import + export you get something else, while it would be nice if it's idempotent?

Copy link
Contributor

@cubercsl cubercsl Jan 17, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can already use the description field, so for your usecase you would put the seat number there (or would you still need more?)

AFAIK, the room is formally used in built-in printing and balloon service.

],
'team_affiliation' => [
'externalid' => $team['organization_id'] ?? null,
Expand Down
4 changes: 2 additions & 2 deletions webapp/templates/jury/balloons.html.twig
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,8 @@
<select id="location-filter" class="select2 form-control" multiple data-filter-field="location-str"
data-ajax-url="{{ path('jury_ajax_data', {datatype: 'locations', select2: true}) }}">
{%- for location in filteredLocations %}
<option value="{{ location.room }}" selected>
{{ location.room }}
<option value="{{ location.location }}" selected>
{{ location.location }}
</option>
{%- endfor %}
</select>
Expand Down
2 changes: 1 addition & 1 deletion webapp/templates/jury/partials/team_form.html.twig
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
{{ form_row(form.publicdescription) }}
{{ form_row(form.affiliation) }}
{{ form_row(form.penalty) }}
{{ form_row(form.room) }}
{{ form_row(form.location) }}
{{ form_row(form.internalcomments) }}
{{ form_row(form.contests) }}
{{ form_row(form.enabled) }}
Expand Down
4 changes: 2 additions & 2 deletions webapp/templates/jury/team.html.twig
Original file line number Diff line number Diff line change
Expand Up @@ -85,10 +85,10 @@
<td>{{ team.penalty }}</td>
</tr>
{% endif %}
{% if team.room %}
{% if team.location %}
<tr>
<th>Location</th>
<td>{{ team.room }}</td>
<td>{{ team.location }}</td>
</tr>
{% endif %}
<tr>
Expand Down
4 changes: 2 additions & 2 deletions webapp/templates/partials/team.html.twig
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,10 @@
</tr>
{% endif %}
{% endif %}
{% if team.room is not empty %}
{% if team.location is not empty %}
<tr>
<th>Location</th>
<td>{{ team.room }}</td>
<td>{{ team.location }}</td>
</tr>
{% endif %}
</table>
Expand Down
4 changes: 4 additions & 0 deletions webapp/tests/Unit/Controller/API/TeamControllerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace App\Tests\Unit\Controller\API;

use App\DataFixtures\Test\AddLocationToTeamFixture;
use Symfony\Component\HttpFoundation\BinaryFileResponse;
use Symfony\Component\HttpFoundation\File\UploadedFile;

Expand All @@ -21,9 +22,12 @@ class TeamControllerTest extends BaseTestCase
'display_name' => null,
'members' => null,
'photo' => null,
'location' => ['description' => 'Utrecht'],
],
];

protected static array $fixtures = [AddLocationToTeamFixture::class];

protected array $expectedAbsent = ['4242', 'nonexistent'];

public function testLogoManagement(): void
Expand Down
12 changes: 6 additions & 6 deletions webapp/tests/Unit/Controller/Jury/TeamControllerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ class TeamControllerTest extends JuryControllerTestCase
protected static string $className = Team::class;
protected static array $DOM_elements = ['h1' => ['Teams']];
protected static string $addForm = 'team[';
protected static array $addEntitiesShown = ['icpcid', 'label', 'displayName', 'room'];
protected static array $addEntitiesShown = ['icpcid', 'label', 'displayName', 'location'];
protected static array $overviewSingleNotShown = ['addUserForTeam'];
protected static array $overviewGeneralNotShown = ['icpcid'];
protected static array $addEntitiesCount = ['contests'];
Expand All @@ -27,7 +27,7 @@ class TeamControllerTest extends JuryControllerTestCase
'category' => '3',
'publicdescription' => 'Some members',
'penalty' => '0',
'room' => 'The first room',
'location' => 'The first room',
'internalcomments' => 'This is a team without a user',
'contests' => [],
'enabled' => '1',
Expand All @@ -38,7 +38,7 @@ class TeamControllerTest extends JuryControllerTestCase
'category' => '1',
'publicdescription' => 'More members',
'penalty' => '20',
'room' => 'Another room',
'location' => 'Another room',
'internalcomments' => 'This is a team with a user',
'enabled' => '1',
'addUserForTeam' => Team::CREATE_NEW_USER,
Expand All @@ -57,9 +57,9 @@ class TeamControllerTest extends JuryControllerTestCase
['name' => 'no_members',
'publicdescription' => '',
'displayName' => 'Team without members'],
['name' => 'no_room',
'room' => '',
'displayName' => 'Team without a room'],
['name' => 'no_location',
'location' => '',
'displayName' => 'Team without a location'],
['name' => 'no_comments',
'internalcomments' => '',
'displayName' => 'Team without comments'],
Expand Down
Loading
Loading