From 0ec85727876f43d51f85f2fb09d1f6fb43a5c5d7 Mon Sep 17 00:00:00 2001 From: cubercsl <2014cais01@gmail.com> Date: Tue, 30 Jul 2024 22:57:35 +0800 Subject: [PATCH 1/4] feat: follow medal categories when export results When export the result, follow medal categories in contest setting. This will be consistent with the results generated by the award API. Signed-off-by: cubercsl <2014cais01@gmail.com> --- webapp/src/Service/ImportExportService.php | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/webapp/src/Service/ImportExportService.php b/webapp/src/Service/ImportExportService.php index 399c1a4c66..bf91a56cb0 100644 --- a/webapp/src/Service/ImportExportService.php +++ b/webapp/src/Service/ImportExportService.php @@ -510,6 +510,10 @@ public function getResultsData( $data = []; $lowestMedalPoints = 0; + // For every team that we skip because it is not in a medal category, we need to include one + // additional rank. So keep track of the number of skipped teams + $skippedTeams = 0; + foreach ($scoreboard->getScores() as $teamScore) { if ($teamScore->team->getCategory()->getSortorder() !== $sortOrder) { continue; @@ -522,13 +526,20 @@ public function getResultsData( $rank = $teamScore->rank; $numPoints = $teamScore->numPoints; - if ($rank <= $contest->getGoldMedals()) { + $skip = false; + + if (!$contest->getMedalCategories()->contains($teamScore->team->getCategory())) { + $skip = true; + $skippedTeams++; + } + + if (!$skip && $rank - $skippedTeams <= $contest->getGoldMedals()) { $awardString = 'Gold Medal'; $lowestMedalPoints = $teamScore->numPoints; - } elseif ($rank <= $contest->getGoldMedals() + $contest->getSilverMedals()) { + } elseif (!$skip && $rank - $skippedTeams <= $contest->getGoldMedals() + $contest->getSilverMedals()) { $awardString = 'Silver Medal'; $lowestMedalPoints = $teamScore->numPoints; - } elseif ($rank <= $contest->getGoldMedals() + $contest->getSilverMedals() + $contest->getBronzeMedals() + $contest->getB()) { + } elseif (!$skip && $rank - $skippedTeams <= $contest->getGoldMedals() + $contest->getSilverMedals() + $contest->getBronzeMedals() + $contest->getB()) { $awardString = 'Bronze Medal'; $lowestMedalPoints = $teamScore->numPoints; } elseif ($numPoints >= $median) { @@ -540,7 +551,8 @@ public function getResultsData( $rank = $ranks[$numPoints]; } if ($honors) { - if ($numPoints === $lowestMedalPoints) { + if ($numPoints >= $lowestMedalPoints) { + // Some teams out of the medal categories may get more points than the lowest medalist. $awardString = 'Highest Honors'; } elseif ($numPoints === $lowestMedalPoints - 1) { $awardString = 'High Honors'; From eb83d00a76747a92796879b24050ba463bfa8c68 Mon Sep 17 00:00:00 2001 From: cubercsl <2014cais01@gmail.com> Date: Wed, 31 Jul 2024 00:07:54 +0800 Subject: [PATCH 2/4] test: fix testGetResultsData Add every group in medal category --- webapp/tests/Unit/Service/ImportExportServiceTest.php | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/webapp/tests/Unit/Service/ImportExportServiceTest.php b/webapp/tests/Unit/Service/ImportExportServiceTest.php index 63958d1d04..a057ee3ac4 100644 --- a/webapp/tests/Unit/Service/ImportExportServiceTest.php +++ b/webapp/tests/Unit/Service/ImportExportServiceTest.php @@ -1181,8 +1181,6 @@ public function testGetResultsData(bool $full, bool $honors, string $expectedRes ->setShortname('wf47') ->setStarttimeString($startTime->format(DateTimeInterface::ATOM)) ->setEndtimeString($startTime->add(new DateInterval('PT5H'))->format(DateTimeInterface::ATOM)); - $em->persist($contest); - $em->flush(); $groupsById = []; $groupsData = json_decode(file_get_contents(__DIR__ . '/../Fixtures/sample-groups.json'), true); @@ -1194,7 +1192,12 @@ public function testGetResultsData(bool $full, bool $honors, string $expectedRes $em->persist($group); $em->flush(); $groupsById[$group->getExternalid()] = $group; + $contest->addMedalCategory($group); } + + $em->persist($contest); + $em->flush(); + $teamsData = json_decode(file_get_contents(__DIR__ . '/../Fixtures/sample-teams.json'), true); /** @var array $teamsById */ $teamsById = []; From 613d388ea1faf63a589dea367701160fc7f1977d Mon Sep 17 00:00:00 2001 From: cubercsl <2014cais01@gmail.com> Date: Tue, 6 Aug 2024 22:32:43 +0800 Subject: [PATCH 3/4] test(export): add test for medal medal categories Signed-off-by: cubercsl <2014cais01@gmail.com> --- webapp/src/Service/ImportExportService.php | 20 +- .../Fixtures/sample/results-full-honors.tsv | 10 + .../Fixtures/sample/results-full-ranked.tsv | 10 + .../Fixtures/sample/results-wf-honors.tsv | 10 + .../Fixtures/sample/results-wf-ranked.tsv | 10 + .../Unit/Fixtures/sample/sample-groups.json | 32 +++ .../Unit/Fixtures/sample/sample-medals.json | 11 + .../Unit/Fixtures/sample/sample-problems.json | 78 +++++++ .../Fixtures/sample/sample-scoreboard.json | 202 ++++++++++++++++++ .../Unit/Fixtures/sample/sample-teams.json | 128 +++++++++++ .../Fixtures/{ => wf}/results-full-honors.tsv | 0 .../Fixtures/{ => wf}/results-full-ranked.tsv | 0 .../Fixtures/{ => wf}/results-wf-honors.tsv | 0 .../Fixtures/{ => wf}/results-wf-ranked.tsv | 0 .../Unit/Fixtures/{ => wf}/sample-groups.json | 0 .../tests/Unit/Fixtures/wf/sample-medals.json | 17 ++ .../Fixtures/{ => wf}/sample-problems.json | 0 .../Fixtures/{ => wf}/sample-scoreboard.json | 0 .../Unit/Fixtures/{ => wf}/sample-teams.json | 0 .../Unit/Service/ImportExportServiceTest.php | 36 ++-- 20 files changed, 550 insertions(+), 14 deletions(-) create mode 100644 webapp/tests/Unit/Fixtures/sample/results-full-honors.tsv create mode 100644 webapp/tests/Unit/Fixtures/sample/results-full-ranked.tsv create mode 100644 webapp/tests/Unit/Fixtures/sample/results-wf-honors.tsv create mode 100644 webapp/tests/Unit/Fixtures/sample/results-wf-ranked.tsv create mode 100644 webapp/tests/Unit/Fixtures/sample/sample-groups.json create mode 100644 webapp/tests/Unit/Fixtures/sample/sample-medals.json create mode 100644 webapp/tests/Unit/Fixtures/sample/sample-problems.json create mode 100644 webapp/tests/Unit/Fixtures/sample/sample-scoreboard.json create mode 100644 webapp/tests/Unit/Fixtures/sample/sample-teams.json rename webapp/tests/Unit/Fixtures/{ => wf}/results-full-honors.tsv (100%) rename webapp/tests/Unit/Fixtures/{ => wf}/results-full-ranked.tsv (100%) rename webapp/tests/Unit/Fixtures/{ => wf}/results-wf-honors.tsv (100%) rename webapp/tests/Unit/Fixtures/{ => wf}/results-wf-ranked.tsv (100%) rename webapp/tests/Unit/Fixtures/{ => wf}/sample-groups.json (100%) create mode 100644 webapp/tests/Unit/Fixtures/wf/sample-medals.json rename webapp/tests/Unit/Fixtures/{ => wf}/sample-problems.json (100%) rename webapp/tests/Unit/Fixtures/{ => wf}/sample-scoreboard.json (100%) rename webapp/tests/Unit/Fixtures/{ => wf}/sample-teams.json (100%) diff --git a/webapp/src/Service/ImportExportService.php b/webapp/src/Service/ImportExportService.php index bf91a56cb0..6d60164766 100644 --- a/webapp/src/Service/ImportExportService.php +++ b/webapp/src/Service/ImportExportService.php @@ -533,6 +533,21 @@ public function getResultsData( $skippedTeams++; } + if ($numPoints === 0) { + // Teams with 0 points won't get a medal, a rank or an honor. + // They will always get an honorable mention. + $data[] = new ResultRow( + $teamScore->team->getIcpcId(), + null, + 'Honorable', + $teamScore->numPoints, + $teamScore->totalTime, + $maxTime, + null + ); + continue; + } + if (!$skip && $rank - $skippedTeams <= $contest->getGoldMedals()) { $awardString = 'Gold Medal'; $lowestMedalPoints = $teamScore->numPoints; @@ -551,8 +566,9 @@ public function getResultsData( $rank = $ranks[$numPoints]; } if ($honors) { - if ($numPoints >= $lowestMedalPoints) { - // Some teams out of the medal categories may get more points than the lowest medalist. + if ($numPoints === $lowestMedalPoints + || $rank - $skippedTeams <= $contest->getGoldMedals() + $contest->getSilverMedals() + $contest->getBronzeMedals() + $contest->getB()) { + // Some teams out of the medal categories but ranked higher than bronze medallists may get more points. $awardString = 'Highest Honors'; } elseif ($numPoints === $lowestMedalPoints - 1) { $awardString = 'High Honors'; diff --git a/webapp/tests/Unit/Fixtures/sample/results-full-honors.tsv b/webapp/tests/Unit/Fixtures/sample/results-full-honors.tsv new file mode 100644 index 0000000000..44c8950ffd --- /dev/null +++ b/webapp/tests/Unit/Fixtures/sample/results-full-honors.tsv @@ -0,0 +1,10 @@ +results 1 +10001 1 Gold Medal 4 36 20 Sample Group A +10002 2 Gold Medal 2 5 3 +10003 2 Gold Medal 2 5 3 +10004 4 Highest Honors 1 12 12 Sample Group B +10005 5 Highest Honors 1 13 13 +10006 6 Highest Honors 1 14 14 +10007 7 Bronze Medal 1 15 15 Sample Group C +10008 Honorable 0 0 0 +10009 Honorable 0 0 0 diff --git a/webapp/tests/Unit/Fixtures/sample/results-full-ranked.tsv b/webapp/tests/Unit/Fixtures/sample/results-full-ranked.tsv new file mode 100644 index 0000000000..02167ced5a --- /dev/null +++ b/webapp/tests/Unit/Fixtures/sample/results-full-ranked.tsv @@ -0,0 +1,10 @@ +results 1 +10001 1 Gold Medal 4 36 20 Sample Group A +10002 2 Gold Medal 2 5 3 +10003 2 Gold Medal 2 5 3 +10004 4 Ranked 1 12 12 Sample Group B +10005 5 Ranked 1 13 13 +10006 6 Ranked 1 14 14 +10007 7 Bronze Medal 1 15 15 Sample Group C +10008 Honorable 0 0 0 +10009 Honorable 0 0 0 diff --git a/webapp/tests/Unit/Fixtures/sample/results-wf-honors.tsv b/webapp/tests/Unit/Fixtures/sample/results-wf-honors.tsv new file mode 100644 index 0000000000..e1b6deee07 --- /dev/null +++ b/webapp/tests/Unit/Fixtures/sample/results-wf-honors.tsv @@ -0,0 +1,10 @@ +results 1 +10001 1 Gold Medal 4 36 20 Sample Group A +10002 2 Gold Medal 2 5 3 +10003 2 Gold Medal 2 5 3 +10004 4 Highest Honors 1 12 12 Sample Group B +10005 4 Highest Honors 1 13 13 +10006 4 Highest Honors 1 14 14 +10007 7 Bronze Medal 1 15 15 Sample Group C +10008 Honorable 0 0 0 +10009 Honorable 0 0 0 diff --git a/webapp/tests/Unit/Fixtures/sample/results-wf-ranked.tsv b/webapp/tests/Unit/Fixtures/sample/results-wf-ranked.tsv new file mode 100644 index 0000000000..1b4985f273 --- /dev/null +++ b/webapp/tests/Unit/Fixtures/sample/results-wf-ranked.tsv @@ -0,0 +1,10 @@ +results 1 +10001 1 Gold Medal 4 36 20 Sample Group A +10002 2 Gold Medal 2 5 3 +10003 2 Gold Medal 2 5 3 +10004 4 Ranked 1 12 12 Sample Group B +10005 4 Ranked 1 13 13 +10006 4 Ranked 1 14 14 +10007 7 Bronze Medal 1 15 15 Sample Group C +10008 Honorable 0 0 0 +10009 Honorable 0 0 0 diff --git a/webapp/tests/Unit/Fixtures/sample/sample-groups.json b/webapp/tests/Unit/Fixtures/sample/sample-groups.json new file mode 100644 index 0000000000..9a1b000069 --- /dev/null +++ b/webapp/tests/Unit/Fixtures/sample/sample-groups.json @@ -0,0 +1,32 @@ +[ + { + "hidden": false, + "categoryid": 5, + "id": "10001", + "icpc_id": "10001", + "name": "Sample Group A", + "sortorder": 0, + "color": null, + "allow_self_registration": false + }, + { + "hidden": false, + "categoryid": 6, + "id": "10002", + "icpc_id": "10002", + "name": "Sample Group B", + "sortorder": 0, + "color": null, + "allow_self_registration": false + }, + { + "hidden": false, + "categoryid": 7, + "id": "10003", + "icpc_id": "10003", + "name": "Sample Group C", + "sortorder": 0, + "color": null, + "allow_self_registration": false + } +] diff --git a/webapp/tests/Unit/Fixtures/sample/sample-medals.json b/webapp/tests/Unit/Fixtures/sample/sample-medals.json new file mode 100644 index 0000000000..6336011001 --- /dev/null +++ b/webapp/tests/Unit/Fixtures/sample/sample-medals.json @@ -0,0 +1,11 @@ +{ + "medals": { + "gold": 2, + "silver": 1, + "bronze": 1 + }, + "medal_categories": [ + "10001", + "10003" + ] +} diff --git a/webapp/tests/Unit/Fixtures/sample/sample-problems.json b/webapp/tests/Unit/Fixtures/sample/sample-problems.json new file mode 100644 index 0000000000..9b851ebe06 --- /dev/null +++ b/webapp/tests/Unit/Fixtures/sample/sample-problems.json @@ -0,0 +1,78 @@ +[ + { + "ordinal": 0, + "probid": 1, + "short_name": "A", + "rgb": "#FF0000", + "color": "red", + "label": "A", + "time_limit": 1.0, + "statement": [ + { + "href": "contests/sample_contests/problems/sample-problem-a/statement", + "mime": "application/pdf", + "filename": "A.pdf" + } + ], + "id": "sample-problem-a", + "name": "Sample Problem A", + "test_data_count": 50 + }, + { + "ordinal": 1, + "probid": 2, + "short_name": "B", + "rgb": "#00FF00", + "color": "lime", + "label": "B", + "time_limit": 2.0, + "statement": [ + { + "href": "contests/sample_contests/problems/sample-problem-b/statement", + "mime": "application/pdf", + "filename": "B.pdf" + } + ], + "id": "sample-problem-b", + "name": "Sample Problem B", + "test_data_count": 32 + }, + { + "ordinal": 2, + "probid": 3, + "short_name": "C", + "rgb": "#0000FF", + "color": "blue", + "label": "C", + "time_limit": 3.0, + "statement": [ + { + "href": "contests/sample_contests/problems/sample-problem-c/statement", + "mime": "application/pdf", + "filename": "C.pdf" + } + ], + "id": "sample-problem-c", + "name": "Sample Problem C", + "test_data_count": 78 + }, + { + "ordinal": 3, + "probid": 4, + "short_name": "D", + "rgb": "#FFFF00", + "color": "yellow", + "label": "D", + "time_limit": 4.0, + "statement": [ + { + "href": "contests/sample_contests/problems/sample-problem-d/statement", + "mime": "application/pdf", + "filename": "D.pdf" + } + ], + "id": "sample-problem-d", + "name": "Sample Problem D", + "test_data_count": 100 + } +] diff --git a/webapp/tests/Unit/Fixtures/sample/sample-scoreboard.json b/webapp/tests/Unit/Fixtures/sample/sample-scoreboard.json new file mode 100644 index 0000000000..458042dc9d --- /dev/null +++ b/webapp/tests/Unit/Fixtures/sample/sample-scoreboard.json @@ -0,0 +1,202 @@ +{ + "event_id": "88478", + "time": "2024-04-18T16:48:58.897+02:00", + "contest_time": "5:00:59.897", + "state": { + "started": "2024-04-18T11:47:59.000+02:00", + "ended": "2024-04-18T16:47:59.000+02:00", + "frozen": "2024-04-18T15:47:59.000+02:00", + "thawed": null, + "finalized": null, + "end_of_updates": null + }, + "rows": [ + { + "rank": 1, + "team_id": "A", + "score": { + "total_time": 36 + }, + "problems": [ + { + "label": "A", + "problem_id": "sample-problem-a", + "num_judged": 1, + "num_pending": 0, + "solved": true, + "time": 1, + "first_to_solve": true + }, + { + "label": "B", + "problem_id": "sample-problem-b", + "num_judged": 1, + "num_pending": 0, + "solved": true, + "time": 5, + "first_to_solve": false + }, + { + "label": "C", + "problem_id": "sample-problem-c", + "num_judged": 1, + "num_pending": 0, + "solved": true, + "time": 10, + "first_to_solve": false + }, + { + "label": "D", + "problem_id": "sample-problem-d", + "num_judged": 1, + "num_pending": 0, + "solved": true, + "time": 20, + "first_to_solve": false + } + ] + }, + { + "rank": 2, + "team_id": "B", + "score": { + "total_time": 5 + }, + "problems": [ + { + "label": "B", + "problem_id": "sample-problem-b", + "num_judged": 1, + "num_pending": 0, + "solved": true, + "time": 2, + "first_to_solve": true + }, + { + "label": "C", + "problem_id": "sample-problem-c", + "num_judged": 1, + "num_pending": 0, + "solved": true, + "time": 3, + "first_to_solve": true + } + ] + }, + { + "rank": 3, + "team_id": "C", + "score": { + "total_time": 5 + }, + "problems": [ + { + "label": "B", + "problem_id": "sample-problem-b", + "num_judged": 1, + "num_pending": 0, + "solved": true, + "time": 2, + "first_to_solve": true + }, + { + "label": "C", + "problem_id": "sample-problem-c", + "num_judged": 1, + "num_pending": 0, + "solved": true, + "time": 3, + "first_to_solve": true + } + ] + }, + { + "rank": 4, + "team_id": "D", + "score": { + "total_time": 12 + }, + "problems": [ + { + "label": "D", + "problem_id": "sample-problem-d", + "num_judged": 1, + "num_pending": 0, + "solved": true, + "time": 12, + "first_to_solve": true + } + ] + }, + { + "rank": 5, + "team_id": "E", + "score": { + "total_time": 13 + }, + "problems": [ + { + "label": "D", + "problem_id": "sample-problem-d", + "num_judged": 1, + "num_pending": 0, + "solved": true, + "time": 13, + "first_to_solve": false + } + ] + }, + { + "rank": 6, + "team_id": "F", + "score": { + "total_time": 14 + }, + "problems": [ + { + "label": "D", + "problem_id": "sample-problem-d", + "num_judged": 1, + "num_pending": 0, + "solved": true, + "time": 14, + "first_to_solve": false + } + ] + }, + { + "rank": 7, + "team_id": "G", + "score": { + "total_time": 15 + }, + "problems": [ + { + "label": "D", + "problem_id": "sample-problem-d", + "num_judged": 1, + "num_pending": 0, + "solved": true, + "time": 15, + "first_to_solve": false + } + ] + }, + { + "rank": 8, + "team_id": "H", + "score": { + "total_time": 0 + }, + "problems": [] + }, + { + "rank": 9, + "team_id": "I", + "score": { + "total_time": 0 + }, + "problems": [] + } + ] +} diff --git a/webapp/tests/Unit/Fixtures/sample/sample-teams.json b/webapp/tests/Unit/Fixtures/sample/sample-teams.json new file mode 100644 index 0000000000..49fc9e2584 --- /dev/null +++ b/webapp/tests/Unit/Fixtures/sample/sample-teams.json @@ -0,0 +1,128 @@ +[ + { + "location": null, + "organization_id": "1", + "hidden": false, + "group_ids": ["10001"], + "affiliation": "", + "teamid": 2, + "id": "A", + "icpc_id": "10001", + "label": "A", + "name": "Team A", + "display_name": "Team A", + "public_description": "" + }, + { + "location": null, + "organization_id": "2", + "hidden": false, + "group_ids": ["10001"], + "affiliation": "", + "teamid": 3, + "id": "B", + "icpc_id": "10002", + "label": "B", + "name": "Team B", + "display_name": "Team B", + "public_description": "" + }, + { + "location": null, + "organization_id": "3", + "hidden": false, + "group_ids": ["10001"], + "affiliation": "", + "teamid": 4, + "id": "C", + "icpc_id": "10003", + "label": "C", + "name": "Team C", + "display_name": "Team C", + "public_description": "" + }, + { + "location": null, + "organization_id": "4", + "hidden": false, + "group_ids": ["10002"], + "affiliation": "", + "teamid": 5, + "id": "D", + "icpc_id": "10004", + "label": "D", + "name": "Team D", + "display_name": "Team D", + "public_description": "" + }, + { + "location": null, + "organization_id": "5", + "hidden": false, + "group_ids": ["10002"], + "affiliation": "", + "teamid": 6, + "id": "E", + "icpc_id": "10005", + "label": "E", + "name": "Team E", + "display_name": "Team E", + "public_description": "" + }, + { + "location": null, + "organization_id": "6", + "hidden": false, + "group_ids": ["10002"], + "affiliation": "", + "teamid": 7, + "id": "F", + "icpc_id": "10006", + "label": "F", + "name": "Team F", + "display_name": "Team F", + "public_description": "" + }, + { + "location": null, + "organization_id": "7", + "hidden": false, + "group_ids": ["10003"], + "affiliation": "", + "teamid": 8, + "id": "G", + "icpc_id": "10007", + "label": "G", + "name": "Team G", + "display_name": "Team G", + "public_description": "" + }, + { + "location": null, + "organization_id": "8", + "hidden": false, + "group_ids": ["10003"], + "affiliation": "", + "teamid": 9, + "id": "H", + "icpc_id": "10008", + "label": "H", + "name": "Team H", + "display_name": "Team H", + "public_description": "" + }, + { + "location": null, + "organization_id": "9", + "hidden": false, + "group_ids": ["10003"], + "affiliation": "", + "teamid": 10, + "id": "I", + "icpc_id": "10009", + "label": "I", + "name": "Team I", + "display_name": "Team I", + "public_description": "" + } +] diff --git a/webapp/tests/Unit/Fixtures/results-full-honors.tsv b/webapp/tests/Unit/Fixtures/wf/results-full-honors.tsv similarity index 100% rename from webapp/tests/Unit/Fixtures/results-full-honors.tsv rename to webapp/tests/Unit/Fixtures/wf/results-full-honors.tsv diff --git a/webapp/tests/Unit/Fixtures/results-full-ranked.tsv b/webapp/tests/Unit/Fixtures/wf/results-full-ranked.tsv similarity index 100% rename from webapp/tests/Unit/Fixtures/results-full-ranked.tsv rename to webapp/tests/Unit/Fixtures/wf/results-full-ranked.tsv diff --git a/webapp/tests/Unit/Fixtures/results-wf-honors.tsv b/webapp/tests/Unit/Fixtures/wf/results-wf-honors.tsv similarity index 100% rename from webapp/tests/Unit/Fixtures/results-wf-honors.tsv rename to webapp/tests/Unit/Fixtures/wf/results-wf-honors.tsv diff --git a/webapp/tests/Unit/Fixtures/results-wf-ranked.tsv b/webapp/tests/Unit/Fixtures/wf/results-wf-ranked.tsv similarity index 100% rename from webapp/tests/Unit/Fixtures/results-wf-ranked.tsv rename to webapp/tests/Unit/Fixtures/wf/results-wf-ranked.tsv diff --git a/webapp/tests/Unit/Fixtures/sample-groups.json b/webapp/tests/Unit/Fixtures/wf/sample-groups.json similarity index 100% rename from webapp/tests/Unit/Fixtures/sample-groups.json rename to webapp/tests/Unit/Fixtures/wf/sample-groups.json diff --git a/webapp/tests/Unit/Fixtures/wf/sample-medals.json b/webapp/tests/Unit/Fixtures/wf/sample-medals.json new file mode 100644 index 0000000000..554639ba08 --- /dev/null +++ b/webapp/tests/Unit/Fixtures/wf/sample-medals.json @@ -0,0 +1,17 @@ +{ + "medals": { + "gold": 4, + "silver": 4, + "bronze": 4 + }, + "medal_categories": [ + "21496", + "21497", + "21500", + "21501", + "21502", + "21513", + "21514", + "21517" + ] +} diff --git a/webapp/tests/Unit/Fixtures/sample-problems.json b/webapp/tests/Unit/Fixtures/wf/sample-problems.json similarity index 100% rename from webapp/tests/Unit/Fixtures/sample-problems.json rename to webapp/tests/Unit/Fixtures/wf/sample-problems.json diff --git a/webapp/tests/Unit/Fixtures/sample-scoreboard.json b/webapp/tests/Unit/Fixtures/wf/sample-scoreboard.json similarity index 100% rename from webapp/tests/Unit/Fixtures/sample-scoreboard.json rename to webapp/tests/Unit/Fixtures/wf/sample-scoreboard.json diff --git a/webapp/tests/Unit/Fixtures/sample-teams.json b/webapp/tests/Unit/Fixtures/wf/sample-teams.json similarity index 100% rename from webapp/tests/Unit/Fixtures/sample-teams.json rename to webapp/tests/Unit/Fixtures/wf/sample-teams.json diff --git a/webapp/tests/Unit/Service/ImportExportServiceTest.php b/webapp/tests/Unit/Service/ImportExportServiceTest.php index a057ee3ac4..1808ccb316 100644 --- a/webapp/tests/Unit/Service/ImportExportServiceTest.php +++ b/webapp/tests/Unit/Service/ImportExportServiceTest.php @@ -1167,7 +1167,7 @@ protected function getContest(int|string $cid): Contest /** * @dataProvider provideGetResultsData */ - public function testGetResultsData(bool $full, bool $honors, string $expectedResultsFile): void + public function testGetResultsData(bool $full, bool $honors, string $dataSet, string $expectedResultsFile): void { // Set up some results we can test with // This data is based on the ICPC World Finals 47 @@ -1176,14 +1176,20 @@ public function testGetResultsData(bool $full, bool $honors, string $expectedRes $startTime = new DateTimeImmutable('2023-05-01 08:00:00'); + $medalData = json_decode(file_get_contents(__DIR__ . '/../Fixtures/' . $dataSet . '/sample-medals.json'), true); + $contest = (new Contest()) ->setName('ICPC World Finals 47') ->setShortname('wf47') ->setStarttimeString($startTime->format(DateTimeInterface::ATOM)) - ->setEndtimeString($startTime->add(new DateInterval('PT5H'))->format(DateTimeInterface::ATOM)); + ->setEndtimeString($startTime->add(new DateInterval('PT5H'))->format(DateTimeInterface::ATOM)) + ->setMedalsEnabled(true) + ->setGoldMedals($medalData['medals']['gold']) + ->SetSilverMedals($medalData['medals']['silver']) + ->setBronzeMedals($medalData['medals']['bronze']); $groupsById = []; - $groupsData = json_decode(file_get_contents(__DIR__ . '/../Fixtures/sample-groups.json'), true); + $groupsData = json_decode(file_get_contents(__DIR__ . '/../Fixtures/' . $dataSet . '/sample-groups.json'), true); foreach ($groupsData as $groupData) { $group = (new TeamCategory()) ->setExternalid($groupData['id']) @@ -1192,13 +1198,15 @@ public function testGetResultsData(bool $full, bool $honors, string $expectedRes $em->persist($group); $em->flush(); $groupsById[$group->getExternalid()] = $group; - $contest->addMedalCategory($group); + if (in_array($group->getExternalid(), $medalData['medal_categories'], true)) { + $contest->addMedalCategory($group); + } } $em->persist($contest); $em->flush(); - $teamsData = json_decode(file_get_contents(__DIR__ . '/../Fixtures/sample-teams.json'), true); + $teamsData = json_decode(file_get_contents(__DIR__ . '/../Fixtures/'. $dataSet . '/sample-teams.json'), true); /** @var array $teamsById */ $teamsById = []; /** @var array $teamsByIcpcId */ @@ -1216,7 +1224,7 @@ public function testGetResultsData(bool $full, bool $honors, string $expectedRes $teamsByIcpcId[$team->getIcpcId()] = $team; } - $problemsData = json_decode(file_get_contents(__DIR__ . '/../Fixtures/sample-problems.json'), true); + $problemsData = json_decode(file_get_contents(__DIR__ . '/../Fixtures/'. $dataSet . '/sample-problems.json'), true); $contestProblemsById = []; foreach ($problemsData as $problemData) { $problem = (new Problem()) @@ -1242,7 +1250,7 @@ public function testGetResultsData(bool $full, bool $honors, string $expectedRes $submissionInsertQuery->bindValue('cid', $contest->getCid()); $submissionInsertQuery->bindValue('langid', $cpp->getLangid()); - $scoreboardData = json_decode(file_get_contents(__DIR__ . '/../Fixtures/sample-scoreboard.json'), true); + $scoreboardData = json_decode(file_get_contents(__DIR__ . '/../Fixtures/'. $dataSet . '/sample-scoreboard.json'), true); foreach ($scoreboardData['rows'] as $scoreboardRow) { $team = $teamsById[$scoreboardRow['team_id']]; $submissionInsertQuery->bindValue('teamid', $team->getTeamid()); @@ -1293,7 +1301,7 @@ public function testGetResultsData(bool $full, bool $honors, string $expectedRes $results = $importExportService->getResultsData(37, $full, $honors); - $resultsContents = file_get_contents(__DIR__ . '/../Fixtures/' . $expectedResultsFile); + $resultsContents = file_get_contents(__DIR__ . '/../Fixtures/' . $dataSet . '/' . $expectedResultsFile); $resultsContents = substr($resultsContents, strpos($resultsContents, "\n") + 1); // Prefix file with a fake header, so we can deserialize them $resultsContents = "team_id\trank\taward\tnum_solved\ttotal_time\ttime_of_last_submission\tgroup_winner\n" . $resultsContents; @@ -1309,9 +1317,13 @@ public function testGetResultsData(bool $full, bool $honors, string $expectedRes public function provideGetResultsData(): Generator { - yield [true, true, 'results-full-honors.tsv']; - yield [false, true, 'results-wf-honors.tsv']; - yield [true, false, 'results-full-ranked.tsv']; - yield [false, false, 'results-wf-ranked.tsv']; + yield [true, true, 'wf', 'results-full-honors.tsv']; + yield [false, true, 'wf', 'results-wf-honors.tsv']; + yield [true, false, 'wf', 'results-full-ranked.tsv']; + yield [false, false, 'wf', 'results-wf-ranked.tsv']; + yield [true, true, 'sample', 'results-full-honors.tsv']; + yield [false, true, 'sample', 'results-wf-honors.tsv']; + yield [true, false, 'sample', 'results-full-ranked.tsv']; + yield [false, true, 'sample', 'results-wf-honors.tsv']; } } From 384eb883789a7d8691397952a2a31462c437bf29 Mon Sep 17 00:00:00 2001 From: cubercsl <2014cais01@gmail.com> Date: Thu, 8 Aug 2024 21:04:41 +0800 Subject: [PATCH 4/4] team didn't solve anything shouldn't get any medals It is a rare situation that medals cannot be distributed completely. It is almost impossible for medals to be awarded to a team didn't solve anything in a real contest. However, this is indeed the case in the test data. Signed-off-by: cubercsl <2014cais01@gmail.com> --- .../Controller/Jury/ImportExportControllerTest.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/webapp/tests/Unit/Controller/Jury/ImportExportControllerTest.php b/webapp/tests/Unit/Controller/Jury/ImportExportControllerTest.php index 4ccd4717db..c81d532efa 100644 --- a/webapp/tests/Unit/Controller/Jury/ImportExportControllerTest.php +++ b/webapp/tests/Unit/Controller/Jury/ImportExportControllerTest.php @@ -177,8 +177,8 @@ public function testResultsHtmlExport(bool $individuallyRanked, bool $honors, st 'export_results[format]' => $format, ]); self::assertSelectorExists('h1:contains("Results for Demo contest")'); - self::assertSelectorExists('th:contains("Example teamname")'); self::assertSelectorExists('th:contains("A: Hello World")'); + self::assertSelectorExists('td:contains("Example teamname")'); } public function provideResultsHtmlExport(): Generator @@ -219,16 +219,16 @@ public function testResultsTsvExport( public function provideResultsTsvExport(): Generator { yield [0, true, true, 'results 1 -exteam 1 Gold Medal 0 0 0 Participants +exteam Honorable 0 0 0 ']; yield [0, true, false, 'results 1 -exteam 1 Gold Medal 0 0 0 Participants +exteam Honorable 0 0 0 ']; yield [0, false, true, 'results 1 -exteam 1 Gold Medal 0 0 0 Participants +exteam Honorable 0 0 0 ']; yield [0, false, true, 'results 1 -exteam 1 Gold Medal 0 0 0 Participants +exteam Honorable 0 0 0 ']; yield [1, true, true, 'results 1 '];