Skip to content

Interactive extra time #3053

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

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
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
6 changes: 4 additions & 2 deletions etc/db-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -101,8 +101,10 @@
regex: /^[1-9]\d*$/
error_message: A positive number is required.
- name: timelimit_overshoot
type: string
default_value: 1s|10%
type: array_keyval
default_value:
default: "1s|10%"
interactive: "2s+20%"
public: false
description: Time that submissions are kept running beyond timelimit before being killed. Specify as `Xs` for X seconds, `Y%` as percentage, or a combination of both separated by one of `+|&` for the sum, maximum, or minimum of both.
regex: /^\d+[s%]([+|&]\d+[s%])?$/
Expand Down
7 changes: 1 addition & 6 deletions judge/judgedaemon.main.php
Original file line number Diff line number Diff line change
Expand Up @@ -1359,9 +1359,6 @@ function judge(array $judgeTask): bool
return false;
}

// TODO: How do we plan to handle these?
$overshoot = djconfig_get_value('timelimit_overshoot');

// Check whether we have received an exit signal (but not a graceful exit signal).
if (function_exists('pcntl_signal_dispatch')) {
pcntl_signal_dispatch();
Expand Down Expand Up @@ -1417,9 +1414,7 @@ function judge(array $judgeTask): bool
}
}

$hardtimelimit = $run_config['time_limit']
+ overshoot_time($run_config['time_limit'], $overshoot)
+ $run_config['overshoot'];
$hardtimelimit = $run_config['time_limit'] + $run_config['overshoot'];
if ($combined_run_compare) {
// This accounts for wall time spent in the validator. We may likely
// want to make this configurable in the future. The current factor is
Expand Down
3 changes: 2 additions & 1 deletion webapp/composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,8 @@
"App\\": "src/"
},
"files": [
"resources/functions.php"
"resources/functions.php",
"../lib/lib.misc.php"
]
},
"autoload-dev": {
Expand Down
18 changes: 13 additions & 5 deletions webapp/src/Entity/Problem.php
Original file line number Diff line number Diff line change
Expand Up @@ -112,14 +112,22 @@ class Problem extends BaseApiEntity implements
* @var array<int, string>
*/
#[Serializer\Exclude]
private array $typesToString = [
private static array $typesToString = [
self::TYPE_PASS_FAIL => 'pass-fail',
self::TYPE_SCORING => 'scoring',
self::TYPE_MULTI_PASS => 'multi-pass',
self::TYPE_INTERACTIVE => 'interactive',
self::TYPE_SUBMIT_ANSWER => 'submit-answer',
];

/**
* @return array<int, string>
*/
public static function getPossibleProblemTypes(): array
{
return self::$typesToString;
}

#[ORM\Column(options: ['comment' => 'Bitmask of problem types, default is pass-fail.'])]
#[Serializer\Exclude]
private int $types = self::TYPE_PASS_FAIL;
Expand Down Expand Up @@ -302,7 +310,7 @@ public function getSpecialCompareArgs(): ?string
public function setTypesAsString(array $types): Problem
{
/** @var array<string, int> $stringToTypes */
$stringToTypes = array_flip($this->typesToString);
$stringToTypes = array_flip(self::$typesToString);
$typeConstants = [];
foreach ($types as $type) {
if (!isset($stringToTypes[$type])) {
Expand All @@ -320,10 +328,10 @@ public function getTypesAsString(): string
$typeConstants = $this->getTypes();
$typeStrings = [];
foreach ($typeConstants as $type) {
if (!isset($this->typesToString[$type])) {
if (!isset(self::$typesToString[$type])) {
throw new Exception("Unknown problem type: '$type'");
}
$typeStrings[] = $this->typesToString[$type];
$typeStrings[] = self::$typesToString[$type];
}
return implode(', ', $typeStrings);
}
Expand All @@ -334,7 +342,7 @@ public function getTypesAsString(): string
public function getTypes(): array
{
$ret = [];
foreach (array_keys($this->typesToString) as $type) {
foreach (array_keys(self::$typesToString) as $type) {
if ($this->types & $type) {
$ret[] = $type;
}
Expand Down
3 changes: 3 additions & 0 deletions webapp/src/Service/CheckConfigService.php
Original file line number Diff line number Diff line change
Expand Up @@ -474,6 +474,9 @@ public function checkContestsValidate(): ConfigCheckItem
if (empty($cp->getColor())) {
$result = ($result === 'E' ? 'E' : 'W');
$cperrors[$cid] .= " - No color for problem `" . $cp->getShortname() . "` in contest c" . $cid . "\n";
} elseif (Utils::parseHexColor($cp->getColor())[3] !== 255) {
$result = ($result === 'E' ? 'E' : 'W');
$cperrors[$cid] .= " - Semi-transparent color for problem `" . $cp->getShortname() . "` in contest c" . $cid . "\n";
}
}
}
Expand Down
15 changes: 14 additions & 1 deletion webapp/src/Service/ConfigurationService.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use App\Entity\Configuration;
use App\Entity\Executable;
use App\Entity\Judging;
use App\Entity\Problem;
use App\Utils\Utils;
use BackedEnum;
use Doctrine\ORM\EntityManagerInterface;
Expand Down Expand Up @@ -215,7 +216,13 @@
}

if (isset($spec->regex)) {
if (preg_match($spec->regex, (string)$val) === 0) {
if ($spec->type === 'array_keyval') {
foreach($val as $val2) {

Check failure on line 220 in webapp/src/Service/ConfigurationService.php

View workflow job for this annotation

GitHub Actions / phpcs

Expected 1 space(s) after FOREACH keyword; 0 found
if (preg_match($spec->regex, (string)$val2) === 0) {
$errors[$specName] = $spec->errorMessage ?? 'This is not a valid value';
}
}
} elseif (preg_match($spec->regex, (string)$val) === 0) {
$errors[$specName] = $spec->errorMessage ?? 'This is not a valid value';
}
}
Expand Down Expand Up @@ -380,6 +387,12 @@
if ($item->name === 'results_remap') {
$item->valueOptions = $item->keyOptions;
}
break;
case 'timelimit_overshoot':
$problemTypes = array_merge(['default'], Problem::getPossibleProblemTypes());
foreach ($problemTypes as $type) {
$item->keyOptions[$type] = $type;
}
}

if ($item->type === 'enum') {
Expand Down
23 changes: 17 additions & 6 deletions webapp/src/Service/DOMJudgeService.php
Original file line number Diff line number Diff line change
Expand Up @@ -1419,26 +1419,37 @@ public function loadTeam(string $teamId, Contest $contest): Team
return $team;
}

public function getRunConfig(ContestProblem $problem, Submission $submission, int $overshoot = 0): string
public function getRunConfig(ContestProblem $contestProblem, Submission $submission, int $overshoot_extra = 0): string
{
$memoryLimit = $problem->getProblem()->getMemlimit();
$outputLimit = $problem->getProblem()->getOutputlimit();
$problem = $contestProblem->getProblem();
$memoryLimit = $problem->getMemlimit();
$outputLimit = $problem->getOutputlimit();
$overshootPerType = $this->config->get('timelimit_overshoot');
$overshoot = overshoot_time($problem->getTimeLimit(), $overshootPerType['default'] ?? "0s");
foreach ($problem->getTypes() as $problemTypeID) {
$problemType = $problem::getPossibleProblemTypes()[$problemTypeID];
$problemTypeOvershoot = $overshootPerType[$problemType] ?? false;
if (!$problemTypeOvershoot) {
continue;
}
$overshoot = max($overshoot, overshoot_time($problem->getTimelimit(), $problemTypeOvershoot));
}
if (empty($memoryLimit)) {
$memoryLimit = $this->config->get('memory_limit');
}
if (empty($outputLimit)) {
$outputLimit = $this->config->get('output_limit');
}
$runExecutable = $this->getImmutableRunExecutable($problem);
$runExecutable = $this->getImmutableRunExecutable($contestProblem);

return Utils::jsonEncode(
[
'time_limit' => $problem->getProblem()->getTimelimit() * $submission->getLanguage()->getTimeFactor(),
'time_limit' => $problem->getTimelimit() * $submission->getLanguage()->getTimeFactor(),
'memory_limit' => $memoryLimit,
'output_limit' => $outputLimit,
'process_limit' => $this->config->get('process_limit'),
'entry_point' => $submission->getEntryPoint(),
'pass_limit' => $problem->getProblem()->getMultipassLimit(),
'pass_limit' => $problem->getMultipassLimit(),
'hash' => $runExecutable->getHash(),
'overshoot' => $overshoot,
]
Expand Down
13 changes: 9 additions & 4 deletions webapp/src/Utils/Utils.php
Original file line number Diff line number Diff line change
Expand Up @@ -343,19 +343,24 @@ public static function convertToColor(string $hex): ?string
}

/**
* Parse a hex color into it's three RGB values.
* Parse a hex color into it's four RGBA values.
*
* @return array{int, int, int}
* @return array{int, int, int, int}
*/
public static function parseHexColor(string $hex): array
{
// Source: https://stackoverflow.com/a/21966100
$length = (strlen($hex) - 1) / 3;
$length = (strlen($hex) - 1) / 4;
if (((strlen($hex) - 1) % 3) == 0) {
$length = (strlen($hex) - 1) / 3;
$hex .= str_repeat('F', $length);
}
$fact = [17, 1, 0.062272][$length - 1];
return [
(int)round(hexdec(substr($hex, 1, $length)) * $fact),
(int)round(hexdec(substr($hex, 1 + $length, $length)) * $fact),
(int)round(hexdec(substr($hex, 1 + 2 * $length, $length)) * $fact)
(int)round(hexdec(substr($hex, 1 + 2 * $length, $length)) * $fact),
(int)round(hexdec(substr($hex, 1 + 3 * $length, $length)))
];
}

Expand Down
8 changes: 4 additions & 4 deletions webapp/tests/Unit/Utils/UtilsTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -321,10 +321,10 @@ public function testConvertToHexConvert(): void

public function testParseHexColor(): void
{
self::assertEquals([255, 255, 255], Utils::parseHexColor('#ffffff'));
self::assertEquals([0, 0, 0], Utils::parseHexColor('#000000'));
self::assertEquals([171, 205, 239], Utils::parseHexColor('#abcdef'));
self::assertEquals([254, 220, 186], Utils::parseHexColor('#FEDCBA'));
self::assertEquals([255, 255, 255, 255], Utils::parseHexColor('#ffffff'));
self::assertEquals([0, 0, 0, 255], Utils::parseHexColor('#000000'));
self::assertEquals([171, 205, 239, 255], Utils::parseHexColor('#abcdef'));
self::assertEquals([254, 220, 186, 255], Utils::parseHexColor('#FEDCBA'));
}

public function testComponentToHex(): void
Expand Down
Loading