Skip to content

Commit 6f91416

Browse files
committed
Allow for different timelimits per problem type
Currently interactive problems need more time due to the pipeline handling. Other problemtypes shouldn't have such requirements but if someone has a slower interactor or compare script for some types this can be helpful. So we both do this to not have `interactive` as special case and to provide people with the option due to unforseen setups.
1 parent 71eae08 commit 6f91416

File tree

6 files changed

+51
-21
lines changed

6 files changed

+51
-21
lines changed

etc/db-config.yaml

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -101,8 +101,10 @@
101101
regex: /^[1-9]\d*$/
102102
error_message: A positive number is required.
103103
- name: timelimit_overshoot
104-
type: string
105-
default_value: 1s|10%
104+
type: array_keyval
105+
default_value:
106+
default: "1s|10%"
107+
interactive: "2s+20%"
106108
public: false
107109
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.
108110
regex: /^\d+[s%]([+|&]\d+[s%])?$/

judge/judgedaemon.main.php

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1359,9 +1359,6 @@ function judge(array $judgeTask): bool
13591359
return false;
13601360
}
13611361

1362-
// TODO: How do we plan to handle these?
1363-
$overshoot = djconfig_get_value('timelimit_overshoot');
1364-
13651362
// Check whether we have received an exit signal (but not a graceful exit signal).
13661363
if (function_exists('pcntl_signal_dispatch')) {
13671364
pcntl_signal_dispatch();
@@ -1417,9 +1414,7 @@ function judge(array $judgeTask): bool
14171414
}
14181415
}
14191416

1420-
$hardtimelimit = $run_config['time_limit']
1421-
+ overshoot_time($run_config['time_limit'], $overshoot)
1422-
+ $run_config['overshoot'];
1417+
$hardtimelimit = $run_config['time_limit'] + $run_config['overshoot'];
14231418
if ($combined_run_compare) {
14241419
// This accounts for wall time spent in the validator. We may likely
14251420
// want to make this configurable in the future. The current factor is

webapp/composer.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,8 @@
131131
"App\\": "src/"
132132
},
133133
"files": [
134-
"resources/functions.php"
134+
"resources/functions.php",
135+
"../lib/lib.misc.php"
135136
]
136137
},
137138
"autoload-dev": {

webapp/src/Entity/Problem.php

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -112,14 +112,22 @@ class Problem extends BaseApiEntity implements
112112
* @var array<int, string>
113113
*/
114114
#[Serializer\Exclude]
115-
private array $typesToString = [
115+
private static array $typesToString = [
116116
self::TYPE_PASS_FAIL => 'pass-fail',
117117
self::TYPE_SCORING => 'scoring',
118118
self::TYPE_MULTI_PASS => 'multi-pass',
119119
self::TYPE_INTERACTIVE => 'interactive',
120120
self::TYPE_SUBMIT_ANSWER => 'submit-answer',
121121
];
122122

123+
/**
124+
* @return array<int, string>
125+
*/
126+
public static function getPossibleProblemTypes(): array
127+
{
128+
return self::$typesToString;
129+
}
130+
123131
#[ORM\Column(options: ['comment' => 'Bitmask of problem types, default is pass-fail.'])]
124132
#[Serializer\Exclude]
125133
private int $types = self::TYPE_PASS_FAIL;
@@ -302,7 +310,7 @@ public function getSpecialCompareArgs(): ?string
302310
public function setTypesAsString(array $types): Problem
303311
{
304312
/** @var array<string, int> $stringToTypes */
305-
$stringToTypes = array_flip($this->typesToString);
313+
$stringToTypes = array_flip(self::$typesToString);
306314
$typeConstants = [];
307315
foreach ($types as $type) {
308316
if (!isset($stringToTypes[$type])) {
@@ -320,10 +328,10 @@ public function getTypesAsString(): string
320328
$typeConstants = $this->getTypes();
321329
$typeStrings = [];
322330
foreach ($typeConstants as $type) {
323-
if (!isset($this->typesToString[$type])) {
331+
if (!isset(self::$typesToString[$type])) {
324332
throw new Exception("Unknown problem type: '$type'");
325333
}
326-
$typeStrings[] = $this->typesToString[$type];
334+
$typeStrings[] = self::$typesToString[$type];
327335
}
328336
return implode(', ', $typeStrings);
329337
}
@@ -334,7 +342,7 @@ public function getTypesAsString(): string
334342
public function getTypes(): array
335343
{
336344
$ret = [];
337-
foreach (array_keys($this->typesToString) as $type) {
345+
foreach (array_keys(self::$typesToString) as $type) {
338346
if ($this->types & $type) {
339347
$ret[] = $type;
340348
}

webapp/src/Service/ConfigurationService.php

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
use App\Entity\Configuration;
88
use App\Entity\Executable;
99
use App\Entity\Judging;
10+
use App\Entity\Problem;
1011
use App\Utils\Utils;
1112
use BackedEnum;
1213
use Doctrine\ORM\EntityManagerInterface;
@@ -215,7 +216,13 @@ public function saveChanges(
215216
}
216217

217218
if (isset($spec->regex)) {
218-
if (preg_match($spec->regex, (string)$val) === 0) {
219+
if ($spec->type === 'array_keyval') {
220+
foreach($val as $val2) {
221+
if (preg_match($spec->regex, (string)$val2) === 0) {
222+
$errors[$specName] = $spec->errorMessage ?? 'This is not a valid value';
223+
}
224+
}
225+
} elseif (preg_match($spec->regex, (string)$val) === 0) {
219226
$errors[$specName] = $spec->errorMessage ?? 'This is not a valid value';
220227
}
221228
}
@@ -380,6 +387,12 @@ public function addOptions(ConfigurationSpecification $item): ConfigurationSpeci
380387
if ($item->name === 'results_remap') {
381388
$item->valueOptions = $item->keyOptions;
382389
}
390+
break;
391+
case 'timelimit_overshoot':
392+
$problemTypes = array_merge(['default'], Problem::getPossibleProblemTypes());
393+
foreach (array_values($problemTypes) as $type) {
394+
$item->keyOptions[$type] = $type;
395+
}
383396
}
384397

385398
if ($item->type === 'enum') {

webapp/src/Service/DOMJudgeService.php

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1419,26 +1419,37 @@ public function loadTeam(string $teamId, Contest $contest): Team
14191419
return $team;
14201420
}
14211421

1422-
public function getRunConfig(ContestProblem $problem, Submission $submission, int $overshoot = 0): string
1422+
public function getRunConfig(ContestProblem $contestProblem, Submission $submission, int $overshoot_extra = 0): string
14231423
{
1424-
$memoryLimit = $problem->getProblem()->getMemlimit();
1425-
$outputLimit = $problem->getProblem()->getOutputlimit();
1424+
$problem = $contestProblem->getProblem();
1425+
$memoryLimit = $problem->getMemlimit();
1426+
$outputLimit = $problem->getOutputlimit();
1427+
$overshootPerType = $this->config->get('timelimit_overshoot');
1428+
$overshoot = overshoot_time($problem->getTimeLimit(), $overshootPerType['default'] ?? "0s");
1429+
foreach ($problem->getTypes() as $problemTypeID) {
1430+
$problemType = $problem::getPossibleProblemTypes()[$problemTypeID];
1431+
$problemTypeOvershoot = $overshootPerType[$problemType] ?? false;
1432+
if (!$problemTypeOvershoot) {
1433+
continue;
1434+
}
1435+
$overshoot = max($overshoot, overshoot_time($problem->getTimelimit(), $problemTypeOvershoot));
1436+
}
14261437
if (empty($memoryLimit)) {
14271438
$memoryLimit = $this->config->get('memory_limit');
14281439
}
14291440
if (empty($outputLimit)) {
14301441
$outputLimit = $this->config->get('output_limit');
14311442
}
1432-
$runExecutable = $this->getImmutableRunExecutable($problem);
1443+
$runExecutable = $this->getImmutableRunExecutable($contestProblem);
14331444

14341445
return Utils::jsonEncode(
14351446
[
1436-
'time_limit' => $problem->getProblem()->getTimelimit() * $submission->getLanguage()->getTimeFactor(),
1447+
'time_limit' => $problem->getTimelimit() * $submission->getLanguage()->getTimeFactor(),
14371448
'memory_limit' => $memoryLimit,
14381449
'output_limit' => $outputLimit,
14391450
'process_limit' => $this->config->get('process_limit'),
14401451
'entry_point' => $submission->getEntryPoint(),
1441-
'pass_limit' => $problem->getProblem()->getMultipassLimit(),
1452+
'pass_limit' => $problem->getMultipassLimit(),
14421453
'hash' => $runExecutable->getHash(),
14431454
'overshoot' => $overshoot,
14441455
]

0 commit comments

Comments
 (0)