forked from bogdan2412/infoarena
-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathtask.php
More file actions
258 lines (224 loc) · 7.82 KB
/
task.php
File metadata and controls
258 lines (224 loc) · 7.82 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
<?php
require_once(Config::ROOT . "common/textblock.php");
// This module implements task and task-param related stuff.
// Get valid task types.
function task_get_types() {
return array(
'classic' => 'Clasică',
);
}
/**
* Get valid task security types
* @return array
*/
function task_get_security_types() {
return array(
'private' => 'Private',
'protected' => 'Protected',
'public' => 'Public',
);
}
// Get parameter infos.
function task_get_parameter_infos() {
return array(
'classic' => array(
'timelimit' => array(
'description' => 'Limita de timp (în secunde)',
'default' => 1,
'type' => 'float',
'name' => 'Limita de timp',
),
'memlimit' => array(
'description' => 'Limita de memorie (în kilobytes)',
'default' => 16384,
'type' => 'integer',
'name' => 'Limita de memorie',
),
),
);
}
// Initialize a task object
function task_init($task_id, $task_type, ?User $user = null) {
$task = array(
'id' => $task_id,
'type' => $task_type,
'title' => ucfirst($task_id),
'security' => 'private',
'source' => 'ad-hoc',
'page_name' => Config::TASK_TEXTBLOCK_PREFIX . $task_id,
'open_source' => 0,
'open_tests' => 0,
'test_count' => 10,
'test_groups' => NULL,
'public_tests' => NULL,
'evaluator' => '',
'use_ok_files' => 1,
'rating' => NULL,
);
// User stuff. ugly
$task['user_id'] = $user->id ?? 0;
log_assert_valid(task_validate($task));
return $task;
}
// Validates a task.
// NOTE: this might be incomplete, so don't rely on it exclusively.
// Use this to check for a valid model. It's also useful in controllers.
function task_validate($task) {
log_assert(is_array($task), "You didn't even pass an array");
$errors = array();
if (strlen(getattr($task, 'title', '')) < 1) {
$errors['title'] = 'Titlu prea scurt.';
}
if (!is_page_name(getattr($task, 'page_name'))) {
$errors['page_name'] = 'Pagină invalidă.';
}
if (!is_user_id(getattr($task, 'user_id'))) {
$errors['user_id'] = 'ID de utilizator invalid.';
}
if (!array_key_exists(getattr($task, 'security'),
task_get_security_types())) {
$errors['security'] = 'Tipul securității este invalid.';
}
$open_source = getattr($task, 'open_source');
if ($open_source != '0' && $open_source != '1') {
$errors['open_source'] = 'Se acceptă doar 0/1.';
}
$open_tests = getattr($task, 'open_tests');
if ($open_tests != '0' && $open_tests != '1') {
$errors['open_tests'] = 'Se acceptă doar 0/1.';
}
if (!array_key_exists(getattr($task, 'type'), task_get_types())) {
$errors['type'] = "Tipul task-ului este invalid.";
}
if (!is_task_id(getattr($task, 'id', ''))) {
$errors['id'] = 'ID de task invalid.';
}
if (!is_whole_number($task['test_count'])) {
$errors['test_count'] = "Numărul de teste trebuie să fie un număr.";
} else if ($task['test_count'] < 1) {
$errors['test_count'] = "Minimum 1 test.";
} else if ($task['test_count'] > 100) {
$errors['test_count'] = "Maximum 100 de teste.";
}
if ($task['use_ok_files'] != '0' && $task['use_ok_files'] != '1') {
$errors['use_ok_files'] = "0/1 only";
}
if ($task['evaluator'] === '') {
if (!$task['use_ok_files']) {
$errors['evaluator'] =
'Pentru evaluare cu diff e nevoie de fișiere .ok';
}
} else {
if (!is_attachment_name($task['evaluator'])) {
$errors['evaluator'] = 'Nume de fișier invalid pentru problema '
. $task['id'];
}
}
$stub = Model::factory('Task')->create();
$stub->test_count = $task['test_count'];
$stub->test_groups = $task['test_groups'];
try {
$ignored = new TaskTests($stub);
} catch (TestDescriptorException $e) {
$errors['test_groups'] = $e->getMessage();
}
$stub->test_groups = '';
$stub->public_tests = $task['public_tests'];
try {
$ignored = new TaskTests($stub);
} catch (TestDescriptorException $e) {
$errors['public_tests'] = $e->getMessage();
}
return $errors;
}
// Parse test grouping expression from task and returns groups as an array.
// If there is no grouping parameter defined it returns a group for each test
// by default.
// If the expression string contains errors the function returns false.
// Expression syntax:
// item: number | number-number
// group: item | item,group
// groups: group | group;groups
function task_parse_test_group($string, $test_count) {
if (!$string || strlen($string) == 0) {
return array();
}
$current_group = array();
$items = explode(',', $string);
$used_count = array();
for ($test = 1; $test <= $test_count; $test++) {
$used_count[$test] = 0;
}
foreach ($items as &$item) {
$tests = explode('-', $item);
if (count($tests) < 1 || count($tests) > 2) {
return false;
}
foreach ($tests as &$test_ref) {
$test_ref = trim($test_ref);
if (!is_whole_number($test_ref)) {
return false;
}
}
if (count($tests) == 1) {
if ($tests[0] < 1 || $tests[0] > $test_count) {
return false;
}
$current_group[] = $tests[0];
$used_count[$tests[0]] = 1;
} else {
$left = (int) $tests[0];
$right = (int) $tests[1];
if ($left < 1 || $right < 1 ||
$left > $test_count || $right > $test_count) {
return false;
}
for ($test = min($left, $right); $test <= max($left, $right);
$test++) {
$current_group[] = $test;
$used_count[$test]++;
}
}
}
for ($test = 1; $test <= $test_count; $test++) {
if ($used_count[$test] > 1) {
return false;
}
}
return $current_group;
}
// Validate parameters. Return errors as $form_errors
function task_validate_parameters($task_type, $parameters) {
$errors = array();
if ($task_type === 'classic') {
if (!is_numeric($parameters['timelimit'])) {
$errors['timelimit'] = "Limita de timp trebuie să fie un număr.";
} else if ($parameters['timelimit'] < 0.01) {
$errors['timelimit'] = "Minimum 10 milisecunde.";
} else if ($parameters['timelimit'] > 60) {
$errors['timelimit'] = "Maximum un minut.";
}
if (!is_whole_number($parameters['memlimit'])) {
$errors['memlimit'] = "Limita de memorie trebuie să fie un număr.";
} else if ($parameters['memlimit'] < 10) {
$errors['memlimit'] = "Minimum 10 kilobytes.";
} else if ($parameters['memlimit'] > 524288) {
$errors['memlimit'] = "Maximum 512 megabytes.";
}
}
return $errors;
}
// Receives a list of method and algorithm tag ids and links them to task_id
function task_update_tags($task_id, $method_tags_id, $algorithm_tags_id) {
log_assert(is_array($method_tags_id), 'method_tags must be an array');
log_assert(is_array($algorithm_tags_id), 'algorithm_tags must be an array');
log_assert(is_task_id($task_id), "Invalid task_id");
tag_clear('task', $task_id, 'method');
tag_clear('task', $task_id, 'algorithm');
foreach ($method_tags_id as $tag_id) {
tag_add('task', $task_id, $tag_id);
}
foreach ($algorithm_tags_id as $tag_id) {
tag_add('task', $task_id, $tag_id);
}
}