| 1 | <?php |
|---|
| 2 | require_once(IA_ROOT_DIR . "common/textblock.php"); |
|---|
| 3 | |
|---|
| 4 | // This module implements task and task-param related stuff. |
|---|
| 5 | |
|---|
| 6 | // Get valid task types. |
|---|
| 7 | function task_get_types() { |
|---|
| 8 | return array( |
|---|
| 9 | 'classic' => 'Clasic', |
|---|
| 10 | 'output-only' => 'Doar de output', |
|---|
| 11 | ); |
|---|
| 12 | } |
|---|
| 13 | |
|---|
| 14 | /** |
|---|
| 15 | * Get valid task security types |
|---|
| 16 | * @return array |
|---|
| 17 | */ |
|---|
| 18 | function task_get_security_types() { |
|---|
| 19 | return array( |
|---|
| 20 | 'private' => 'Private', |
|---|
| 21 | 'protected' => 'Protected', |
|---|
| 22 | 'public' => 'Public'); |
|---|
| 23 | } |
|---|
| 24 | |
|---|
| 25 | // Get parameter infos. |
|---|
| 26 | function task_get_parameter_infos() { |
|---|
| 27 | return array( |
|---|
| 28 | 'classic' => array( |
|---|
| 29 | 'timelimit' => array( |
|---|
| 30 | 'description' => "Limita de timp (in secunde)", |
|---|
| 31 | 'default' => 1, |
|---|
| 32 | 'type' => 'float', |
|---|
| 33 | 'name' => 'Limita de timp', |
|---|
| 34 | ), |
|---|
| 35 | 'memlimit' => array( |
|---|
| 36 | 'description' => "Limita de memorie (in kilobytes)", |
|---|
| 37 | 'default' => 16384, |
|---|
| 38 | 'type' => 'integer', |
|---|
| 39 | 'name' => 'Limita de memorie', |
|---|
| 40 | ), |
|---|
| 41 | ), |
|---|
| 42 | 'output-only' => array( |
|---|
| 43 | ), |
|---|
| 44 | ); |
|---|
| 45 | } |
|---|
| 46 | |
|---|
| 47 | // Initialize a task object |
|---|
| 48 | function task_init($task_id, $task_type, $user = null) { |
|---|
| 49 | $task = array( |
|---|
| 50 | 'id' => $task_id, |
|---|
| 51 | 'type' => $task_type, |
|---|
| 52 | 'title' => ucfirst($task_id), |
|---|
| 53 | 'security' => 'private', |
|---|
| 54 | 'source' => 'ad-hoc', |
|---|
| 55 | 'page_name' => IA_TASK_TEXTBLOCK_PREFIX . $task_id, |
|---|
| 56 | 'open_source' => 0, |
|---|
| 57 | 'open_tests' => 0, |
|---|
| 58 | 'test_count' => 10, |
|---|
| 59 | 'test_groups' => NULL, |
|---|
| 60 | 'public_tests' => NULL, |
|---|
| 61 | 'evaluator' => NULL, |
|---|
| 62 | 'use_ok_files' => 1, |
|---|
| 63 | 'rating' => NULL, |
|---|
| 64 | ); |
|---|
| 65 | |
|---|
| 66 | // User stuff. ugly |
|---|
| 67 | if (is_null($user)) { |
|---|
| 68 | $task['user_id'] = 0; |
|---|
| 69 | } else { |
|---|
| 70 | $task['user_id'] = $user['id']; |
|---|
| 71 | } |
|---|
| 72 | |
|---|
| 73 | log_assert_valid(task_validate($task)); |
|---|
| 74 | return $task; |
|---|
| 75 | } |
|---|
| 76 | |
|---|
| 77 | // Validates a task. |
|---|
| 78 | // NOTE: this might be incomplete, so don't rely on it exclusively. |
|---|
| 79 | // Use this to check for a valid model. It's also usefull in controllers. |
|---|
| 80 | function task_validate($task) { |
|---|
| 81 | $errors = array(); |
|---|
| 82 | |
|---|
| 83 | // FIXME How to handle this? |
|---|
| 84 | log_assert(is_array($task), "You didn't even pass an array"); |
|---|
| 85 | |
|---|
| 86 | if (strlen(getattr($task, 'title', '')) < 1) { |
|---|
| 87 | $errors['title'] = 'Titlu prea scurt.'; |
|---|
| 88 | } |
|---|
| 89 | |
|---|
| 90 | if (!is_page_name(getattr($task, 'page_name'))) { |
|---|
| 91 | $errors['page_name'] = 'Homepage invalid'; |
|---|
| 92 | } |
|---|
| 93 | |
|---|
| 94 | if (!is_user_id(getattr($task, 'user_id'))) { |
|---|
| 95 | $errors['user_id'] = 'ID de utilizator invalid'; |
|---|
| 96 | } |
|---|
| 97 | |
|---|
| 98 | if (!array_key_exists(getattr($task, 'security'), |
|---|
| 99 | task_get_security_types())) { |
|---|
| 100 | $errors['security'] = 'Tipul securitatii este invalid'; |
|---|
| 101 | } |
|---|
| 102 | |
|---|
| 103 | $open_source = getattr($task, 'open_source'); |
|---|
| 104 | if ($open_source != '0' && $open_source != '1') { |
|---|
| 105 | $errors['open_source'] = 'Se accepta doar 0/1'; |
|---|
| 106 | } |
|---|
| 107 | |
|---|
| 108 | $open_tests = getattr($task, 'open_tests'); |
|---|
| 109 | if ($open_tests != '0' && $open_tests != '1') { |
|---|
| 110 | $errors['open_tests'] = 'Se accepta doar 0/1'; |
|---|
| 111 | } |
|---|
| 112 | |
|---|
| 113 | if (!array_key_exists(getattr($task, 'type'), task_get_types())) { |
|---|
| 114 | $errors['type'] = "Tipul task-ului este invalid"; |
|---|
| 115 | } |
|---|
| 116 | |
|---|
| 117 | if (!is_task_id(getattr($task, 'id', ''))) { |
|---|
| 118 | $errors['id'] = 'ID de task invalid'; |
|---|
| 119 | } |
|---|
| 120 | |
|---|
| 121 | if (!is_whole_number($task['test_count'])) { |
|---|
| 122 | $errors['test_count'] = "Numarul de teste trebuie sa fie un numar."; |
|---|
| 123 | } else if ($task['test_count'] < 1) { |
|---|
| 124 | $errors['test_count'] = "Minim 1 test."; |
|---|
| 125 | } else if ($task['test_count'] > 100) { |
|---|
| 126 | $errors['test_count'] = "Maxim 100 de teste."; |
|---|
| 127 | } |
|---|
| 128 | |
|---|
| 129 | if ($task['use_ok_files'] != '0' && $task['use_ok_files'] != '1') { |
|---|
| 130 | $errors['use_ok_files'] = "0/1 only"; |
|---|
| 131 | } |
|---|
| 132 | |
|---|
| 133 | if ($task['evaluator'] == "") { |
|---|
| 134 | if (!$task['use_ok_files']) { |
|---|
| 135 | $errors['evaluator'] = "Pentru evaluare cu diff e nevoie e fisiere .ok"; |
|---|
| 136 | } |
|---|
| 137 | } else { |
|---|
| 138 | if (!is_attachment_name($task['evaluator'])) { |
|---|
| 139 | $errors['evaluator'] = "Nume de fisier invalid."; |
|---|
| 140 | } |
|---|
| 141 | } |
|---|
| 142 | |
|---|
| 143 | if (strlen(getattr($task, 'test_groups', '')) > 256) { |
|---|
| 144 | $errors['test_groups'] = 'Expresia este prea lunga.'; |
|---|
| 145 | } else if (task_get_testgroups($task) === false) { |
|---|
| 146 | $errors['test_groups'] = "Eroare de sintaxa in expresie."; |
|---|
| 147 | } |
|---|
| 148 | |
|---|
| 149 | if (task_parse_test_group($task["public_tests"], $task["test_count"]) === false) { |
|---|
| 150 | $errors['public_tests'] = "Eroare de sintaxa in expresie."; |
|---|
| 151 | } |
|---|
| 152 | |
|---|
| 153 | return $errors; |
|---|
| 154 | } |
|---|
| 155 | |
|---|
| 156 | // Parse test grouping expression from task and returns groups as an array |
|---|
| 157 | // If there is no grouping parameter defined it returns a group for each test by default |
|---|
| 158 | // If the expression string contains errors the function returns false |
|---|
| 159 | // Expression syntax: |
|---|
| 160 | // item: number | number-number |
|---|
| 161 | // group: item | item,group |
|---|
| 162 | // groups: group | group;groups |
|---|
| 163 | function task_parse_test_group($string, $test_count) { |
|---|
| 164 | if (strlen($string) == 0) |
|---|
| 165 | return array(); |
|---|
| 166 | |
|---|
| 167 | $current_group = array(); |
|---|
| 168 | $items = explode(',', $string); |
|---|
| 169 | $used_count = array(); |
|---|
| 170 | for ($test = 1; $test <= $test_count; $test++) { |
|---|
| 171 | $used_count[$test] = 0; |
|---|
| 172 | } |
|---|
| 173 | |
|---|
| 174 | foreach ($items as &$item) { |
|---|
| 175 | $tests = explode('-', $item); |
|---|
| 176 | if (count($tests) < 1 || count($tests) > 2) { |
|---|
| 177 | return false; |
|---|
| 178 | } |
|---|
| 179 | foreach ($tests as &$test) { |
|---|
| 180 | $test = trim($test); |
|---|
| 181 | if (!is_whole_number($test)) { |
|---|
| 182 | return false; |
|---|
| 183 | } |
|---|
| 184 | } |
|---|
| 185 | if (count($tests) == 1) { |
|---|
| 186 | if ($tests[0] < 1 || $tests[0] > $test_count) { |
|---|
| 187 | return false; |
|---|
| 188 | } |
|---|
| 189 | $current_group[] = $tests[0]; |
|---|
| 190 | $used_count[$tests[0]] = 1; |
|---|
| 191 | } else { |
|---|
| 192 | $left = (int) $tests[0]; |
|---|
| 193 | $right = (int) $tests[1]; |
|---|
| 194 | if ($left < 1 || $right < 1 || $left > $test_count || $right > $test_count) { |
|---|
| 195 | return false; |
|---|
| 196 | } |
|---|
| 197 | for ($test = min($left, $right); $test <= max($left, $right); $test++) { |
|---|
| 198 | $current_group[] = $test; |
|---|
| 199 | $used_count[$test]++; |
|---|
| 200 | } |
|---|
| 201 | } |
|---|
| 202 | } |
|---|
| 203 | |
|---|
| 204 | for ($test = 1; $test <= $test_count; $test++) { |
|---|
| 205 | if ($used_count[$test] > 1) { |
|---|
| 206 | return false; |
|---|
| 207 | } |
|---|
| 208 | } |
|---|
| 209 | |
|---|
| 210 | return $current_group; |
|---|
| 211 | } |
|---|
| 212 | |
|---|
| 213 | function task_get_testgroups($task) { |
|---|
| 214 | $test_count = $task['test_count']; |
|---|
| 215 | if (!is_whole_number($test_count)) { |
|---|
| 216 | return false; |
|---|
| 217 | } |
|---|
| 218 | if (!getattr($task, 'test_groups')) { |
|---|
| 219 | $testgroups = array(); |
|---|
| 220 | for ($test = 1; $test <= $test_count; $test++) { |
|---|
| 221 | $group = array($test); |
|---|
| 222 | $testgroups[] = $group; |
|---|
| 223 | } |
|---|
| 224 | return $testgroups; |
|---|
| 225 | } |
|---|
| 226 | |
|---|
| 227 | $used_count = array(); |
|---|
| 228 | for ($test = 1; $test <= $test_count; $test++) { |
|---|
| 229 | $used_count[$test] = 0; |
|---|
| 230 | } |
|---|
| 231 | $testgroups = array(); |
|---|
| 232 | $groups = explode(';', $task['test_groups']); |
|---|
| 233 | foreach ($groups as &$group) { |
|---|
| 234 | $current_group = task_parse_test_group($group, $test_count); |
|---|
| 235 | if (!$current_group) { |
|---|
| 236 | return false; |
|---|
| 237 | } |
|---|
| 238 | foreach ($current_group as $test) { |
|---|
| 239 | $used_count[$test]++; |
|---|
| 240 | } |
|---|
| 241 | $testgroups[] = $current_group; |
|---|
| 242 | } |
|---|
| 243 | |
|---|
| 244 | for ($test = 1; $test <= $test_count; $test++) { |
|---|
| 245 | if ($used_count[$test] != 1) { |
|---|
| 246 | return false; |
|---|
| 247 | } |
|---|
| 248 | } |
|---|
| 249 | |
|---|
| 250 | return $testgroups; |
|---|
| 251 | } |
|---|
| 252 | |
|---|
| 253 | // Validate parameters. Return errors as $form_errors |
|---|
| 254 | function task_validate_parameters($task_type, $parameters) { |
|---|
| 255 | $errors = array(); |
|---|
| 256 | if ($task_type == 'classic') { |
|---|
| 257 | if (!is_numeric($parameters['timelimit'])) { |
|---|
| 258 | $errors['timelimit'] = "Limita de timp trebuie sa fie un numar."; |
|---|
| 259 | } else if ($parameters['timelimit'] < 0.01) { |
|---|
| 260 | $errors['timelimit'] = "Minim 10 milisecunde."; |
|---|
| 261 | } else if ($parameters['timelimit'] > 60) { |
|---|
| 262 | $errors['timelimit'] = "Maxim un minut."; |
|---|
| 263 | } |
|---|
| 264 | |
|---|
| 265 | if (!is_whole_number($parameters['memlimit'])) { |
|---|
| 266 | $errors['memlimit'] = "Limita de memorie trebuie sa fie un numar."; |
|---|
| 267 | } else if ($parameters['memlimit'] < 10) { |
|---|
| 268 | $errors['memlimit'] = "Minim 10 kilobytes."; |
|---|
| 269 | } else if ($parameters['memlimit'] > 131072) { |
|---|
| 270 | $errors['memlimit'] = "Maxim 128 megabytes."; |
|---|
| 271 | } |
|---|
| 272 | } else if ($task_type == 'output-only') { |
|---|
| 273 | // Nothing to validate |
|---|
| 274 | } else { |
|---|
| 275 | log_error("Bad task_type"); |
|---|
| 276 | } |
|---|
| 277 | return $errors; |
|---|
| 278 | } |
|---|
| 279 | |
|---|
| 280 | function task_get_topic($task_id) { |
|---|
| 281 | if (!is_task_id($task_id)) { |
|---|
| 282 | log_error("Invalid task id"); |
|---|
| 283 | } |
|---|
| 284 | |
|---|
| 285 | // Get task |
|---|
| 286 | $task = task_get($task_id); |
|---|
| 287 | $task_page = textblock_get_revision($task["page_name"]); |
|---|
| 288 | return $task_page["forum_topic"]; |
|---|
| 289 | } |
|---|
| 290 | |
|---|
| 291 | // Receives a list of method and algorithm tag ids and adds links them to task_id |
|---|
| 292 | function task_update_tags($task_id, $method_tags_id, $algorithm_tags_id) { |
|---|
| 293 | log_assert(is_array($method_tags_id), 'method_tags must be an array'); |
|---|
| 294 | log_assert(is_array($algorithm_tags_id), 'algorithm_tags must be an array'); |
|---|
| 295 | log_assert(is_task_id($task_id), "Invalid task_id"); |
|---|
| 296 | |
|---|
| 297 | tag_clear('task', $task_id, 'method'); |
|---|
| 298 | tag_clear('task', $task_id, 'algorithm'); |
|---|
| 299 | |
|---|
| 300 | foreach ($method_tags_id as $tag_id) { |
|---|
| 301 | tag_add('task', $task_id, $tag_id); |
|---|
| 302 | } |
|---|
| 303 | |
|---|
| 304 | foreach ($algorithm_tags_id as $tag_id) { |
|---|
| 305 | tag_add('task', $task_id, $tag_id); |
|---|
| 306 | } |
|---|
| 307 | } |
|---|