function handle_print_upload() { global $DB, $username; ini_set("upload_max_filesize", dbconfig_get('sourcesize_limit') * 1024); checkFileUpload($_FILES['code']['error']); $filename = $_FILES['code']['name']; $realfilename = $_FILES['code']['tmp_name']; /* Determine the language */ $langid = @$_POST['langid']; /* sanity check only */ if ($langid != "") { $lang = $DB->q('MAYBETUPLE SELECT langid FROM language WHERE langid = %s AND allow_submit = 1', $langid); if (!isset($lang)) { error("Unable to find language '{$langid}'"); } } if (IS_JURY) { $whoami = 'JURY/' . $username; } else { $whoami = $username; } $ret = send_print($realfilename, $langid, $whoami, $filename); echo "<p>" . nl2br(htmlspecialchars($ret[1])) . "</p>\n\n"; if ($ret[0]) { echo "<p>Print successful.</p>"; } else { error("Error while printing. Contact staff."); } }
/** * Returns the list of clarification categories as a key,value array. * Keys should be non-numeric to distinguish them from problem IDs. */ function getClarCategories() { $categs = dbconfig_get('clar_categories'); $clarcategories = array(); foreach ($categs as $key => $val) { $clarcategories[$key] = $val; } return $clarcategories; }
/** * Print a time in default configured time_format, or formatted as * specified. The format is according to strftime(). * FIXME: reintroduce contest relative time: show time from start of * contest, after removing ignored intervals. */ function printtime($datetime, $format = NULL) { if (empty($datetime)) { return ''; } if (is_null($format)) { $format = dbconfig_get('time_format', '%H:%M'); } return htmlspecialchars(strftime($format, floor($datetime))); }
$contest_row = $DB->q("MAYBETUPLE SELECT * FROM contest WHERE cid = %i", $cid); if (!$contest_row) { echo "<p>Contest not found.</p>\n"; require LIBWWWDIR . '/footer.php'; exit; } $contest_data = array(); $contest_data['name'] = $contest_row['name']; $contest_data['short-name'] = $contest_row['name']; $contest_data['start-time'] = date('c', $contest_row['starttime']); $contest_data['duration'] = printtimerel(calcContestTime($contest_row['endtime'], $contest_row['cid'])); if (!is_null($contest_row['freezetime'])) { $contest_data['scoreboard-freeze'] = printtimerel(calcContestTime($contest_row['freezetime'], $contest_row['cid'])); } // TODO: event-feed-port $contest_data['penaltytime'] = dbconfig_get('penalty_time'); /* $contest_data['default-clars'] = dbconfig_get('clar_answers'); $contest_data['clar-categories'] = array_values(dbconfig_get('clar_categories')); */ $contest_data['languages'] = array(); $q = $DB->q("SELECT * FROM language"); while ($lang = $q->next()) { $language = array(); $language['name'] = $lang['name']; // TODO: compiler, -flags, runner, -flags? $contest_data['languages'][] = $language; } $contest_data['problems'] = array(); $contests = getCurContests(FALSE); if (!empty($contests)) {
/** * DB configuration */ function config($args) { if (isset($args['name'])) { return array($args['name'] => dbconfig_get($args['name'], null, false)); } return dbconfig_get(null, null, false); }
\tvar matches = location.hash.match(/submitted=(\\d+)/); \tif (matches) { \t\tvar \$p = \$('<p class="submissiondone" />').html('submission done <a href="#">x</a>'); \t\t\$('#submitlist > .teamoverview').after(\$p); \t\t\$('table.submissions tr[data-submission-id=' + matches[1] + ']').addClass('highlight'); \t\t\$('.submissiondone a').on('click', function() { \t\t\t\$(this).parent().remove(); \t\t\t\$('table.submissions tr.highlight').removeClass('highlight'); \t\t\treloadLocation = 'index.php'; \t\t}); \t} }); </script> HTML; $maxfiles = dbconfig_get('sourcefiles_limit', 100); echo addForm('upload.php', 'post', null, 'multipart/form-data', null, ' onreset="resetUploadForm(' . $refreshtime . ', ' . $maxfiles . ');"') . "<p id=\"submitform\">\n\n"; echo "<input type=\"file\" name=\"code[]\" id=\"maincode\" required"; if ($maxfiles > 1) { echo " multiple"; } echo " />\n"; $probs = array(); foreach ($probdata as $probinfo) { $probs[$probinfo['probid']] = $probinfo['shortname']; } $probs[''] = 'problem'; echo addSelect('probid', $probs, '', true); $langs = array(); foreach ($langdata as $langid => $langdata) { $langs[$langid] = $langdata['name'];
// judging would be marked as "claimed". $cnt = $DB->q('RETURNAFFECTED UPDATE judging SET verified = %i, jury_member = ' . ($val ? '%s ' : 'NULL %_ ') . ', verify_comment = %s WHERE judgingid = %i', $val, $jury_member, $comment, $id); auditlog('judging', $id, $val ? 'set verified' : 'set unverified'); if ($cnt == 0) { error("Judging '{$id}' not found or nothing changed."); } else { if ($cnt > 1) { error("Validated more than one judging."); } } $jdata = $DB->q('TUPLE SELECT j.result, s.submitid, s.cid, s.teamid, s.probid, s.langid FROM judging j LEFT JOIN submission s USING (submitid) WHERE judgingid = %i', $id); if (dbconfig_get('verification_required', 0)) { calcScoreRow($jdata['cid'], $jdata['teamid'], $jdata['probid']); // log to event table (case of no verification required is handled // in the REST API function judging_runs_POST) $DB->q('INSERT INTO event (eventtime, cid, teamid, langid, probid, submitid, description) VALUES (%s, %i, %s, %s, %s, %i, "problem judged")', now(), $jdata['cid'], $jdata['teamid'], $jdata['langid'], $jdata['probid'], $jdata['submitid']); if ($jdata['result'] == 'correct') { $balloons_enabled = (bool) $DB->q("VALUE SELECT process_balloons FROM contest WHERE cid = %i", $jdata['cid']); if ($balloons_enabled) { $DB->q('INSERT INTO balloon (submitid) VALUES(%i)', $jdata['submitid']); } } } /* redirect to referrer page after verification * or back to submission page when unverifying. */ if ($val) {
echo "<table>\n{$tclist}"; if ($lastjud !== NULL) { echo $lasttclist; } echo "</table>\n"; } // Show JS toggle of previous submission results. if ($lastjud !== NULL) { echo "<span class=\"testcases_prev\">" . "<a href=\"javascript:togglelastruns();\">show/hide</a> results of previous " . "<a href=\"submission.php?id={$lastsubmitid}\">submission s{$lastsubmitid}</a>" . (empty($lastjud['verify_comment']) ? '' : "<span class=\"prevsubmit\"> (verify comment: '" . $lastjud['verify_comment'] . "')</span>") . "</span>"; } // display following data only when the judging has been completed if ($judging_ended) { // display verification data: verified, by whom, and comment. // only if this is a valid judging, otherwise irrelevant if ($jud['valid'] || isset($jud['rejudgingid']) && $jud['rvalid']) { $verification_required = dbconfig_get('verification_required', 0); if (!($verification_required && $jud['verified'])) { $val = !$jud['verified']; echo addForm('verify.php') . addHidden('id', $jud['judgingid']) . addHidden('val', $val) . addHidden('redirect', @$_SERVER['HTTP_REFERER']); } echo "<p>Verified: " . "<strong>" . printyn($jud['verified']) . "</strong>"; if ($jud['verified'] && !empty($jud['jury_member'])) { echo ", by " . specialchars($jud['jury_member']); if (!empty($jud['verify_comment'])) { echo ' with comment "' . specialchars($jud['verify_comment']) . '"'; } } if (!($verification_required && $jud['verified'])) { echo '; ' . addSubmit(($val ? '' : 'un') . 'mark verified', 'verify'); if ($val) { echo ' with comment ' . addInput('comment', '', 25);
echo "<p class=\"nodata\">No judgehosts defined</p>\n\n"; } else { echo "<table class=\"list sortable\">\n<thead>\n" . "<tr><th scope=\"col\">hostname</th>" . "<th scope=\"col\">active</th>" . "<th class=\"sorttable_nosort\">status</th>" . "<th class=\"sorttable_nosort\">restriction</th>" . "<th class=\"sorttable_nosort\">load</th></tr>\n" . "</thead>\n<tbody>\n"; while ($row = $res->next()) { $link = '<a href="judgehost.php?id=' . urlencode($row['hostname']) . '">'; echo "<tr" . ($row['active'] ? '' : ' class="disabled"') . "><td>" . $link . printhost($row['hostname']) . '</a>' . "</td><td class=\"tdcenter\">" . $link . printyn($row['active']) . "</a></td>"; echo "<td class=\"tdcenter "; if (empty($row['polltime'])) { echo "judgehost-nocon"; echo "\" title =\"never checked in\">"; } else { $reltime = floor(difftime($now, $row['polltime'])); if ($reltime < dbconfig_get('judgehost_warning', 30)) { echo "judgehost-ok"; } else { if ($reltime < dbconfig_get('judgehost_critical', 120)) { echo "judgehost-warn"; } else { echo "judgehost-crit"; } } echo "\" title =\"last checked in {$reltime} seconds ago\">"; } echo $link . CIRCLE_SYM . "</a></td>"; echo "<td>" . $link . (is_null($row['name']) ? '<i>none</i>' : $row['name']) . '</a></td>'; echo "<td title=\"load during the last 2 and 10 minutes and the whole contest\">" . $link . sprintf('%.2f %.2f %.2f', @$work2min[$row['hostname']] / (2 * 60), @$work10min[$row['hostname']] / (10 * 60), @$workcontest[$row['hostname']] / $clen) . "</a></td>"; if (IS_ADMIN) { if ($row['active']) { $activepicto = "pause"; $activecmd = "deactivate"; } else {
/** * Read problem description file and testdata from zip archive * and update problem with it, or insert new problem when probid=NULL. * Returns probid on success, or generates error on failure. */ function importZippedProblem($zip, $probid = NULL, $cid = -1) { global $DB, $teamid, $cdatas, $matchstrings; $prop_file = 'domjudge-problem.ini'; $yaml_file = 'problem.yaml'; $ini_keys_problem = array('name', 'timelimit', 'special_run', 'special_compare'); $ini_keys_contest_problem = array('probid', 'allow_submit', 'allow_judge', 'points', 'color'); $def_timelimit = 10; // Read problem properties $ini_array = parse_ini_string($zip->getFromName($prop_file)); if (empty($ini_array)) { if ($probid === NULL) { error("Need '" . $prop_file . "' file when adding a new problem."); } } else { // Only preserve valid keys: $ini_array_problem = array_intersect_key($ini_array, array_flip($ini_keys_problem)); $ini_array_contest_problem = array_intersect_key($ini_array, array_flip($ini_keys_contest_problem)); // Set default of 1 point for a problem if not specified if (!isset($ini_array_contest_problem['points'])) { $ini_array_contest_problem['points'] = 1; } if ($probid === NULL) { if (!isset($ini_array_contest_problem['probid'])) { error("Need 'probid' in '" . $prop_file . "' when adding a new problem."); } // Set sensible defaults for name and timelimit if not specified: if (!isset($ini_array_problem['name'])) { $ini_array_problem['name'] = $ini_array_contest_problem['probid']; } if (!isset($ini_array_problem['timelimit'])) { $ini_array_problem['timelimit'] = $def_timelimit; } // rename probid to shortname $shortname = $ini_array_contest_problem['probid']; unset($ini_array_contest_problem['probid']); $ini_array_contest_problem['shortname'] = $shortname; $probid = $DB->q('RETURNID INSERT INTO problem (' . implode(', ', array_keys($ini_array_problem)) . ') VALUES (%As)', $ini_array_problem); if ($cid != -1) { $ini_array_contest_problem['cid'] = $cid; $ini_array_contest_problem['probid'] = $probid; $DB->q('INSERT INTO contestproblem (' . implode(', ', array_keys($ini_array_contest_problem)) . ') VALUES (%As)', $ini_array_contest_problem); } } else { if (count($ini_array_problem) > 0) { $DB->q('UPDATE problem SET %S WHERE probid = %i', $ini_array_problem, $probid); } if ($cid != -1) { if ($DB->q("MAYBEVALUE SELECT probid FROM contestproblem\n\t\t\t\t WHERE probid = %i AND cid = %i", $probid, $cid)) { // Remove keys that cannot be modified: unset($ini_array_contest_problem['probid']); if (count($ini_array_contest_problem) != 0) { $DB->q('UPDATE contestproblem SET %S WHERE probid = %i AND cid = %i', $ini_array_contest_problem, $probid, $cid); } } else { $shortname = $ini_array_contest_problem['probid']; unset($ini_array_contest_problem['probid']); $ini_array_contest_problem['shortname'] = $shortname; $ini_array_contest_problem['cid'] = $cid; $ini_array_contest_problem['probid'] = $probid; $DB->q('INSERT INTO contestproblem (' . implode(', ', array_keys($ini_array_contest_problem)) . ') VALUES (%As)', $ini_array_contest_problem); } } } } // parse problem.yaml $problem_yaml = $zip->getFromName($yaml_file); if ($problem_yaml !== FALSE) { $problem_yaml_data = spyc_load($problem_yaml); if (!empty($problem_yaml_data)) { if (isset($problem_yaml_data['uuid']) && $cid != -1) { $DB->q('UPDATE contestproblem SET shortname=%s WHERE cid=%i AND probid=%i', $problem_yaml_data['uuid'], $cid, $probid); } $yaml_array_problem = array(); if (isset($problem_yaml_data['name'])) { if (is_array($problem_yaml_data['name'])) { foreach ($problem_yaml_data['name'] as $lang => $name) { // TODO: select a specific instead of the first language $yaml_array_problem['name'] = $name; break; } } else { $yaml_array_problem['name'] = $problem_yaml_data['name']; } } if (isset($problem_yaml_data['validator_flags'])) { $yaml_array_problem['special_compare_args'] = $problem_yaml_data['validator_flags']; } if (isset($problem_yaml_data['validation']) && $problem_yaml_data['validation'] == 'custom') { // search for validator $validator_files = array(); for ($j = 0; $j < $zip->numFiles; $j++) { $filename = $zip->getNameIndex($j); if (starts_with($filename, "output_validators/") && !ends_with($filename, "/")) { $validator_files[] = $filename; } } if (sizeof($validator_files) == 0) { echo "<p>Custom validator specified but not found.</p>\n"; } else { // file(s) have to share common directory $validator_dir = mb_substr($validator_files[0], 0, mb_strrpos($validator_files[0], "/")) . "/"; $same_dir = TRUE; foreach ($validator_files as $validator_file) { if (!starts_with($validator_file, $validator_dir)) { $same_dir = FALSE; echo "<p>{$validator_file} does not start with {$validator_dir}</p>\n"; break; } } if (!$same_dir) { echo "<p>Found multiple custom output validators.</p>\n"; } else { $tmpzipfiledir = exec("mktemp -d --tmpdir=" . TMPDIR, $dontcare, $retval); if ($retval != 0) { error("failed to create temporary directory"); } chmod($tmpzipfiledir, 0700); foreach ($validator_files as $validator_file) { $content = $zip->getFromName($validator_file); $filebase = basename($validator_file); $newfilename = $tmpzipfiledir . "/" . $filebase; file_put_contents($newfilename, $content); if ($filebase === 'build' || $filebase === 'run') { // mark special files as executable chmod($newfilename, 0755); } } exec("zip -r -j '{$tmpzipfiledir}/outputvalidator.zip' '{$tmpzipfiledir}'", $dontcare, $retval); if ($retval != 0) { error("failed to create zip file for output validator."); } $ovzip = file_get_contents("{$tmpzipfiledir}/outputvalidator.zip"); $probname = $DB->q("VALUE SELECT name FROM problem\n\t\t\t\t\t\t WHERE probid=%i", $probid); $ovname = preg_replace('/[^a-zA-Z0-9]/', '_', $probname) . "_cmp"; if ($DB->q("MAYBEVALUE SELECT execid FROM executable\n\t\t\t\t\t\t WHERE execid=%s", $ovname)) { // avoid name clash $clashcnt = 2; while ($DB->q("MAYBEVALUE SELECT execid FROM executable\n\t\t\t\t\t\t\t WHERE execid=%s", $ovname . "_" . $clashcnt)) { $clashcnt++; } $ovname = $ovname . "_" . $clashcnt; } $DB->q("INSERT INTO executable (execid, md5sum, zipfile,\n\t\t\t\t\t\t description, type) VALUES (%s, %s, %s, %s, %s)", $ovname, md5($ovzip), $ovzip, 'output validator for ' . $probname, 'compare'); $DB->q("UPDATE problem SET special_compare=%s\n\t\t\t\t\t\t WHERE probid=%i", $ovname, $probid); echo "<p>Added output validator '{$ovname}'.</p>\n"; } } } if (isset($problem_yaml_data['limits'])) { if (isset($problem_yaml_data['limits']['memory'])) { $yaml_array_problem['memlimit'] = 1024 * $problem_yaml_data['limits']['memory']; } if (isset($problem_yaml_data['limits']['output'])) { $yaml_array_problem['outputlimit'] = 1024 * $problem_yaml_data['limits']['output']; } } if (sizeof($yaml_array_problem) > 0) { $DB->q('UPDATE problem SET %S WHERE probid = %i', $yaml_array_problem, $probid); } } } // Add problem statement foreach (array('pdf', 'html', 'txt') as $type) { $text = $zip->getFromName('problem.' . $type); if ($text !== FALSE) { $DB->q('UPDATE problem SET problemtext = %s, problemtext_type = %s WHERE probid = %i', $text, $type, $probid); echo "<p>Added problem statement from: <tt>problem.{$type}</tt></p>\n"; break; } } // Insert/update testcases $maxrank = 1 + $DB->q('VALUE SELECT max(rank) FROM testcase WHERE probid = %i', $probid); // first insert sample, then secret data in alphabetical order foreach (array('sample', 'secret') as $type) { $ncases = 0; $datafiles = array(); for ($j = 0; $j < $zip->numFiles; $j++) { $filename = $zip->getNameIndex($j); if (starts_with($filename, "data/{$type}/") && ends_with($filename, ".in")) { $basename = basename($filename, ".in"); $fileout = "data/{$type}/" . $basename . ".ans"; if ($zip->locateName($fileout) !== FALSE) { $datafiles[] = $basename; } } } asort($datafiles); echo "<ul>\n"; foreach ($datafiles as $datafile) { $testin = $zip->getFromName("data/{$type}/{$datafile}.in"); $testout = $zip->getFromName("data/{$type}/{$datafile}.ans"); $description = $datafile; if (($descfile = $zip->getFromName("data/{$type}/{$datafile}.desc")) !== FALSE) { $description .= ": \n" . $descfile; } $image_file = $image_type = $image_thumb = FALSE; foreach (array('png', 'jpg', 'jpeg', 'gif') as $img_ext) { if (($image_file = $zip->getFromName("data/{$type}/{$datafile}" . "." . $img_ext)) !== FALSE) { list($image_thumb, $image_type) = get_image_thumb_type($image_file); break; } } $md5in = md5($testin); $md5out = md5($testout); // Skip testcases that already exist identically $id = $DB->q('MAYBEVALUE SELECT testcaseid FROM testcase WHERE md5sum_input = %s AND md5sum_output = %s AND description = %s AND sample = %i AND probid = %i', $md5in, $md5out, $description, $type == 'sample' ? 1 : 0, $probid); if (isset($id)) { echo "<li>Skipped {$type} testcase <tt>{$datafile}</tt>: already exists</li>\n"; continue; } $DB->q('INSERT INTO testcase (probid, rank, sample, md5sum_input, md5sum_output, input, output, description' . ($image_file !== FALSE ? ', image, image_thumb, image_type' : '') . ')' . 'VALUES (%i, %i, %i, %s, %s, %s, %s, %s' . ($image_file !== FALSE ? ', %s, %s, %s' : '%_ %_ %_') . ')', $probid, $maxrank, $type == 'sample' ? 1 : 0, $md5in, $md5out, $testin, $testout, $description, $image_file, $image_thumb, $image_type); $maxrank++; $ncases++; echo "<li>Added {$type} testcase from: <tt>{$datafile}.{in,ans}</tt></li>\n"; } echo "</ul>\n<p>Added {$ncases} {$type} testcase(s).</p>\n"; } // submit reference solutions if ($cid == -1) { echo "<p>No jury solutions added: problem is not linked to a contest (yet).</p>\n"; } else { if (empty($teamid)) { echo "<p>No jury solutions added: must associate team with your user first.</p>\n"; } else { if ($DB->q('VALUE SELECT allow_submit FROM problem INNER JOIN contestproblem using (probid) WHERE probid = %i AND cid = %i', $probid, $cid)) { // First find all submittable languages: $langs = $DB->q('KEYVALUETABLE SELECT langid, extensions FROM language WHERE allow_submit = 1'); $njurysols = 0; echo "<ul>\n"; for ($j = 0; $j < $zip->numFiles; $j++) { $filename = $zip->getNameIndex($j); $filename_parts = explode(".", $filename); $extension = end($filename_parts); if (!starts_with($filename, 'submissions/') || ends_with($filename, '/')) { // skipping non-submission files and directories silently continue; } unset($langid); foreach ($langs as $key => $exts) { if (in_array($extension, json_decode($exts))) { $langid = $key; break; } } if (empty($langid)) { echo "<li>Could not add jury solution <tt>{$filename}</tt>: unknown language.</li>\n"; } else { if (!($tmpfname = tempnam(TMPDIR, "ref_solution-"))) { error("Could not create temporary file in directory " . TMPDIR); } $offset = mb_strlen('submissions/'); $expectedResult = normalizeExpectedResult(mb_substr($filename, $offset, mb_strpos($filename, '/', $offset) - $offset)); $source = $zip->getFromIndex($j); $results = getExpectedResults($source); if ($results === NULL) { // annotate source code with expected result $source = "// added by import: " . $matchstrings[0] . $expectedResult . "\n" . $source; } else { if (!in_array($expectedResult, $results)) { warning("annotated result '" . implode(', ', $results) . "' does not match directory for {$filename}"); } } file_put_contents($tmpfname, $source); if (filesize($tmpfname) <= dbconfig_get('sourcesize_limit') * 1024) { submit_solution($teamid, $probid, $cid, $langid, array($tmpfname), array(basename($filename))); echo "<li>Added jury solution from: <tt>{$filename}</tt></li>\n"; $njurysols++; } else { echo "<li>Could not add jury solution <tt>{$filename}</tt>: too large.</li>\n"; } unlink($tmpfname); } } echo "</ul>\n<p>Added {$njurysols} jury solution(s).</p>\n"; } else { echo "<p>No jury solutions added: problem not submittable</p>\n"; } } } if (!in_array($cid, array_keys($cdatas))) { echo "<p>The corresponding contest is not activated yet." . "To view the submissions in the submissions list, you have to activate the contest first.</p>\n"; } return $probid; }
warning("No {$file} file specified for new testcase, ignoring."); } else { checkFileUpload($_FILES['add_' . $file]['error']); $content[$file] = file_get_contents($_FILES['add_' . $file]['tmp_name']); } } $DB->q("INSERT INTO testcase\n\t\t (probid,rank,md5sum_input,md5sum_output,input,output,description,sample)\n\t\t VALUES (%i,%i,%s,%s,%s,%s,%s,%i)", $probid, $rank, md5(@$content['input']), md5(@$content['output']), @$content['input'], @$content['output'], @$_POST['add_desc'], @$_POST['add_sample']); if (!empty($content['image'])) { list($thumb, $type) = get_image_thumb_type($content['image']); $DB->q('UPDATE testcase SET image = %s, image_thumb = %s, image_type = %s WHERE probid = %i AND rank = %i', @$content['image'], $thumb, $type, $probid, $rank); } auditlog('testcase', $probid, 'added', "rank {$rank}"); $result .= "<li>Added new testcase {$rank} from files " . htmlspecialchars($_FILES['add_input']['name']) . " (" . printsize($_FILES['add_input']['size']) . ") and " . htmlspecialchars($_FILES['add_output']['name']) . " (" . printsize($_FILES['add_output']['size']) . ")."; if ($_FILES['add_output']['size'] > dbconfig_get('output_limit') * 1024) { $result .= "<br /><b>Warning: output file size exceeds " . "<code>output_limit</code> of " . dbconfig_get('output_limit') . " kB. This will always result in wrong answers!</b>"; } if (empty($content['input']) || empty($content['output'])) { $result .= "<br /><b>Warning: empty testcase file(s)!</b>"; } $result .= "</li>\n"; } } if (!empty($result)) { echo "<ul>\n{$result}</ul>\n\n"; // Reload testcase data after updates get_testcase_data(); } // Check if ranks must be renumbered (if test cases have been deleted). // There is no need to run this within one MySQL transaction since // nothing depends on the ranks being sequential, and we do preserve
if ($data['type'] == 'compile') { $res = $DB->q('SELECT langid AS id FROM language WHERE compile_script = %s ORDER BY langid', $data['execid']); $page = "language"; $prefix = ""; } else { if ($data['type'] == 'run') { $res = $DB->q('SELECT probid AS id FROM problem WHERE special_run = %s ORDER BY probid', $data['execid']); $page = "problem"; $prefix = "p"; } } } $used = FALSE; if (($data['type'] == 'compare' || $data['type'] == 'run') && dbconfig_get('default_' . $data['type']) == $data['execid']) { $used = TRUE; echo '<em>default ' . $data['type'] . '</em> '; } while ($row = $res->next()) { $used = TRUE; echo '<a href="' . $page . '.php?id=' . $row['id'] . '">' . $prefix . $row['id'] . '</a> '; } if (!$used) { echo "<span class=\"nodata\">none</span>"; } ?> </td></tr> <?php if (IS_ADMIN && class_exists("ZipArchive")) { echo '<tr>' . '<td>Executable archive:</td>' . '<td>' . addFileField('executable_archive[]') . addSubmit('Upload', 'upload') . '</td>' . "</tr>\n";
/** * Print a list of submissions from contests contained in the $cdatas * contest data array, either all or only those that match * <key> [= <value>] pairs specified in $restrictions: * - 'verified' if set, only list submissions that are verified * - 'judged' if set, only list submissions with completed judgings * - 'teamid', 'probid', 'langid', 'categoryid', 'judgehost' can be * set to an ID to filter on that respective team, language, etc. * Output is limited to the number $limit, or unlimited by default. * If $highlight is a submission ID, then that one is highlighted. */ function putSubmissions($cdatas, $restrictions, $limit = 0, $highlight = null) { global $DB, $username; /* We need two kind of queries: one for all submissions, and one * with the results for the valid ones. */ $cids = array_keys($cdatas); $verifyclause = ''; if (isset($restrictions['verified'])) { if ($restrictions['verified']) { $verifyclause = 'AND (j.verified = 1) '; } else { $verifyclause = 'AND (j.verified = 0 OR (j.verified IS NULL AND s.judgehost IS NULL)) '; } } $judgedclause = ''; if (isset($restrictions['judged'])) { if ($restrictions['judged']) { $judgedclause = 'AND (j.result IS NOT NULL) '; } else { $judgedclause = 'AND (j.result IS NULL) '; } } $rejudgingclause = ''; if (isset($restrictions['rejudgingdiff'])) { if ($restrictions['rejudgingdiff']) { $rejudgingclause = 'AND (j.result != jold.result) '; } else { $rejudgingclause = 'AND (j.result = jold.result) '; } } if (isset($restrictions['old_result']) && !isset($restrictions['rejudgingid'])) { error('cannot specify restriction on old_result without specifying a rejudgingid'); } // Special case the rejudgingid restriction by showing the // corresponding judging and the old (active) judging result: $sqlbody = 'FROM submission s LEFT JOIN team t USING (teamid) LEFT JOIN problem p USING (probid) LEFT JOIN contestproblem cp USING (probid, cid) LEFT JOIN language l USING (langid) ' . (isset($restrictions['rejudgingid']) ? 'LEFT JOIN judging j ON (s.submitid = j.submitid AND j.rejudgingid = %i) LEFT JOIN judging jold ON (j.prevjudgingid IS NULL AND s.submitid = jold.submitid AND jold.valid = 1 OR j.prevjudgingid = jold.judgingid) ' : 'LEFT JOIN judging j ON (s.submitid = j.submitid AND j.valid = 1) %_ ') . 'WHERE s.cid IN (%Ai) ' . $verifyclause . $judgedclause . $rejudgingclause . (isset($restrictions['teamid']) ? 'AND s.teamid = %i ' : '%_ ') . (isset($restrictions['categoryid']) ? 'AND t.categoryid = %i ' : '%_ ') . (isset($restrictions['probid']) ? 'AND s.probid = %i ' : '%_ ') . (isset($restrictions['langid']) ? 'AND s.langid = %s ' : '%_ ') . (isset($restrictions['judgehost']) ? 'AND s.judgehost = %s ' : '%_ ') . (isset($restrictions['rejudgingid']) ? 'AND (s.rejudgingid = %i OR ' . ' j.rejudgingid = %i) ' : '%_ %_ ') . (isset($restrictions['old_result']) ? 'AND jold.result = %s ' : '%_ ') . (isset($restrictions['result']) ? 'AND j.result = %s ' : '%_ '); // No contests; automatically nothing found and the query can not be run... if (empty($cids)) { echo "<p class=\"nodata\">No submissions</p>\n\n"; return; } $res = $DB->q('SELECT s.submitid, s.teamid, s.probid, s.langid, s.cid, s.submittime, s.judgehost, s.valid, t.name AS teamname, cp.shortname, p.name AS probname, l.name AS langname, j.result, j.judgehost, j.verified, j.jury_member, j.seen ' . (isset($restrictions['rejudgingid']) ? ', jold.result AS oldresult ' : '') . $sqlbody . 'ORDER BY s.submittime DESC, s.submitid DESC ' . ($limit > 0 ? 'LIMIT 0, %i' : '%_'), @$restrictions['rejudgingid'], $cids, @$restrictions['teamid'], @$restrictions['categoryid'], @$restrictions['probid'], @$restrictions['langid'], @$restrictions['judgehost'], @$restrictions['rejudgingid'], @$restrictions['rejudgingid'], @$restrictions['old_result'], @$restrictions['result'], $limit); // nothing found... if ($res->count() == 0) { echo "<p class=\"nodata\">No submissions</p>\n\n"; return; } if (IS_JURY) { echo addForm('submission.php'); } // print the table with the submissions. // table header echo "<table class=\"list sortable\">\n<thead>\n<tr>" . (IS_JURY ? "<th scope=\"col\" class=\"sorttable_numeric\">ID</th>" : '') . (IS_JURY && count($cids) > 1 ? "<th scope=\"col\" class=\"sorttable_numeric\">contest</th>" : '') . "<th scope=\"col\">time</th>" . (IS_JURY ? "<th scope=\"col\">team</th>" : '') . "<th scope=\"col\">problem</th>" . "<th scope=\"col\">lang</th>" . "<th scope=\"col\">result</th>" . (IS_JURY ? "<th scope=\"col\">verified</th><th scope=\"col\">by</th>" : '') . (IS_JURY && isset($restrictions['rejudgingid']) ? "<th scope=\"col\">old result</th>" : '') . "</tr>\n</thead>\n<tbody>\n"; // print each row with links to detailed information $iseven = $subcnt = $corcnt = $igncnt = $vercnt = $quecnt = 0; while ($row = $res->next()) { $sid = (int) $row['submitid']; // always provide link if this is Jury. For team, provide link // to a different page, provided that the result is actually // present and valid. if (IS_JURY) { // If rejudging list, link to the new rejudging: $linkurl = 'submission.php?id=' . $sid . (isset($restrictions['rejudgingid']) ? '&rejudgingid=' . $restrictions['rejudgingid'] : ''); $link = ' href="' . $linkurl . '"'; } elseif ($row['submittime'] < $cdatas[$row['cid']]['endtime'] && $row['result'] && $row['valid'] && (!dbconfig_get('verification_required', 0) || $row['verified'])) { $link = ' href="submission_details.php?id=' . $sid . '"'; } else { $link = ''; } echo "<tr class=\"" . ($iseven ? 'roweven' : 'rowodd'); $iseven = !$iseven; if ($row['valid']) { $subcnt++; } else { $igncnt++; echo ' sub_ignore'; } if ($sid == $highlight) { echo ' highlight'; } if (!IS_JURY && !$row['seen']) { echo ' unseen'; } echo '">'; if (IS_JURY) { echo "<td><a{$link}>s{$sid}</a></td>"; } if (IS_JURY && count($cids) > 1) { echo "<td><a{$link}>c{$row['cid']}</a></td>"; } echo "<td><a{$link}>" . printtime($row['submittime']) . "</a></td>"; if (IS_JURY) { echo '<td title="t' . htmlspecialchars($row['teamid']) . '">' . "<a{$link}>" . htmlspecialchars(str_cut($row['teamname'], 30)) . '</a></td>'; } echo '<td class="probid" title="' . htmlspecialchars($row['probname']) . '">' . "<a{$link}>" . htmlspecialchars($row['shortname']) . '</a></td>'; echo '<td class="langid" title="' . htmlspecialchars($row['langname']) . '">' . "<a{$link}>" . htmlspecialchars($row['langid']) . '</a></td>'; echo "<td class=\"result\"><a{$link}>"; if (difftime($row['submittime'], $cdatas[$row['cid']]['endtime']) >= 0) { echo printresult('too-late'); if (IS_JURY && $row['result']) { echo " (" . printresult($row['result']) . ")"; } } else { if (!$row['result'] || !IS_JURY && !$row['verified'] && dbconfig_get('verification_required', 0)) { echo printresult($row['judgehost'] || !IS_JURY ? '' : 'queued'); } else { echo printresult($row['result']); } } echo "</a></td>"; if (IS_JURY) { // only display verification if we're done with judging unset($verified, $jury_member); $claim = FALSE; if (empty($row['result'])) { $verified = ' '; $jury_member = ' '; } else { $verified = printyn($row['verified']); if (empty($row['jury_member'])) { $jury_member = ' '; } else { $jury_member = htmlspecialchars($row['jury_member']); } if (!$row['verified']) { $vercnt++; if (empty($row['jury_member'])) { $claim = TRUE; } else { $verified = 'claimed'; } } } echo "<td><a{$link}>{$verified}</a></td><td>"; if ($claim) { echo "<a class=\"button\" href=\"{$linkurl}&claim=1\">claim</a>"; } else { if (!$row['verified'] && $jury_member == $username) { echo "<a class=\"button\" href=\"{$linkurl}&unclaim=1\">unclaim</a>"; } else { echo "<a{$link}>{$jury_member}</a>"; } } echo "</td>"; if (isset($restrictions['rejudgingid'])) { echo "<td class=\"result\"><a href=\"submission.php?id={$sid}\">" . printresult($row['oldresult']) . "</a></td>"; } } echo "</tr>\n"; if ($row['result'] == 'correct') { $corcnt++; } } echo "</tbody>\n</table>\n\n"; if (IS_JURY) { echo addEndForm(); if ($limit > 0) { $query_extras = array('subcnt' => '', 'corcnt' => ' AND j.result LIKE \'correct\'', 'igncnt' => ' AND s.valid = 0', 'vercnt' => ' AND verified = 0 AND result IS NOT NULL', 'quecnt' => ' AND result IS NULL'); foreach ($query_extras as $cnt => $query_extra) { ${$cnt} = $DB->q('VALUE SELECT count(s.submitid) ' . $sqlbody . $query_extra, @$restrictions['rejudgingid'], $cids, @$restrictions['teamid'], @$restrictions['categoryid'], @$restrictions['probid'], @$restrictions['langid'], @$restrictions['judgehost'], @$restrictions['rejudgingid'], @$restrictions['rejudgingid'], @$restrictions['old_result'], @$restrictions['result']); } } echo "<p>Total correct: {$corcnt}, submitted: {$subcnt}"; if ($vercnt > 0) { echo ", unverified: {$vercnt}"; } if ($igncnt > 0) { echo ", ignored: {$igncnt}"; } if ($quecnt > 0) { echo ", judgement pending: {$quecnt}"; } echo "</p>\n\n"; } return; }
XMLaddnode($node, 'id', $row['clarid']); XMLaddnode($node, 'team', $team_to_id[$row['sender']]); XMLaddnode($node, 'problem', $row['probid']); // FIXME: probid is shortname? XMLaddnode($node, 'time', calcContestTime($row['submittime'], $cid)); XMLaddnode($node, 'timestamp', $row['submittime']); XMLaddnode($node, 'question', $row['question']); if (isset($row['answer'])) { XMLaddnode($node, 'answer', $row['answer']); XMLaddnode($node, 'answered', 'True'); XMLaddnode($node, 'to-all', isset($row['recipient']) ? 'False' : 'True'); } else { XMLaddnode($node, 'answered', 'False'); } } $compile_penalty = dbconfig_get('compile_penalty', 0); // write out runs while ($row = $events->next()) { if ($row['description'] != 'problem submitted' && $row['description'] != 'problem judged') { continue; } $data = $DB->q('MAYBETUPLE SELECT submittime, teamid, probid, name AS langname, valid FROM submission LEFT JOIN language USING (langid) WHERE valid = 1 AND submitid = %i', $row['submitid']); if (empty($data) || difftime($data['submittime'], $cdata['endtime']) >= 0 || !isset($prob_to_id[$data['probid']]) || !isset($team_to_id[$data['teamid']])) { continue; } $run = XMLaddnode($root, 'run'); XMLaddnode($run, 'id', $row['submitid']); XMLaddnode($run, 'problem', $prob_to_id[$data['probid']]);
} if (!$allowed) { error("You do not have permission to perform that action (Missing role(s): " . implode($REQUIRED_ROLES, ',') . ")"); } require_once LIBWWWDIR . '/common.jury.php'; if ($_SERVER['REQUEST_METHOD'] == 'POST' && empty($_POST) && empty($_FILES) && isset($_SERVER['CONTENT_LENGTH']) && $_SERVER['CONTENT_LENGTH'] > 0) { error("POST data exceeded php.ini's 'post_max_size' directive."); } $cdatas = getCurContests(TRUE, null, TRUE); $cids = array_keys($cdatas); // List of executable script types, used in various places: $executable_types = array('compare' => 'compare', 'compile' => 'compile', 'run' => 'run'); // If the cookie has a existing contest, use it if (isset($_COOKIE['domjudge_cid'])) { if (isset($cdatas[$_COOKIE['domjudge_cid']])) { $cid = $_COOKIE['domjudge_cid']; $cdata = $cdatas[$cid]; } } elseif (count($cids) >= 1) { // Otherwise, select the first contest $cid = $cids[0]; $cdata = $cdatas[$cid]; } // Data to be sent as AJAX updates: $updates = array('clarifications' => empty($cids) ? array() : $DB->q('TABLE SELECT clarid, submittime, sender, recipient, probid, body FROM clarification WHERE sender IS NOT NULL AND cid IN (%Ai) AND answered = 0', $cids), 'judgehosts' => $DB->q('TABLE SELECT hostname, polltime FROM judgehost WHERE active = 1 AND unix_timestamp()-polltime >= %i', dbconfig_get('judgehost_critical', 120)), 'rejudgings' => $DB->q('TABLE SELECT rejudgingid FROM rejudging WHERE endtime IS NULL'));
} if (!isset($data['memlimit'])) { $defaultmemlimit = TRUE; $data['memlimit'] = dbconfig_get('memory_limit'); } if (!isset($data['outputlimit'])) { $defaultoutputlimit = TRUE; $data['outputlimit'] = dbconfig_get('output_limit'); } if (!isset($data['special_run'])) { $defaultrun = TRUE; $data['special_run'] = dbconfig_get('default_run'); } if (!isset($data['special_compare'])) { $defaultcompare = TRUE; $data['special_compare'] = dbconfig_get('default_compare'); } echo "<h1>Problem " . specialchars($data['name']) . "</h1>\n\n"; echo addForm($pagename . '?id=' . urlencode($id), 'post', null, 'multipart/form-data') . "<p>\n" . addHidden('id', $id) . "</p>\n"; ?> <table> <tr><td>ID: </td><td>p<?php echo specialchars($data['probid']); ?> </td></tr> <tr><td>Name: </td><td><?php echo specialchars($data['name']); ?> </td></tr> <tr><td>Testcases: </td><td><?php if ($data['ntestcases'] == 0) {
if (count($CHECKER_ERRORS) > 0) { foreach ($CHECKER_ERRORS as $chk_err) { $details .= $row['langid'] . ': ' . $chk_err; // if this language is set to 'submittable', it's an error if ($row['allow_submit'] == 1) { $langseverity = 'E'; } else { $details .= ' (but is not submittable)'; } $details .= "\n"; } } } result('problems, languages, teams', 'Languages integrity', $details == '' ? 'O' : $langseverity, $details); $details = ''; if (dbconfig_get('show_affiliations', 1)) { $res = $DB->q('SELECT affilid FROM team_affiliation ORDER BY affilid'); while ($row = $res->next()) { $CHECKER_ERRORS = array(); check_affiliation($row); if (count($CHECKER_ERRORS) > 0) { foreach ($CHECKER_ERRORS as $chk_err) { $details .= $row['affilid'] . ': ' . $chk_err . "\n"; } } } $res = $DB->q('SELECT DISTINCT country FROM team_affiliation WHERE country IS NOT NULL ORDER BY country'); while ($row = $res->next()) { $cflag = '../images/countries/' . urlencode($row['country']) . '.png'; if (!file_exists($cflag)) {
/** * This function takes a (set of) temporary file(s) of a submission, * validates it and puts it into the database. Additionally it * moves it to a backup storage. */ function submit_solution($team, $prob, $contest, $lang, $files, $filenames, $origsubmitid = NULL) { global $DB; if (empty($team)) { error("No value for Team."); } if (empty($prob)) { error("No value for Problem."); } if (empty($contest)) { error("No value for Contest."); } if (empty($lang)) { error("No value for Language."); } if (!is_array($files) || count($files) == 0) { error("No files specified."); } if (count($files) > dbconfig_get('sourcefiles_limit', 100)) { error("Tried to submit more than the allowed number of source files."); } if (!is_array($filenames) || count($filenames) != count($files)) { error("Nonmatching (number of) filenames specified."); } if (count($filenames) != count(array_unique($filenames))) { error("Duplicate filenames detected."); } $sourcesize = dbconfig_get('sourcesize_limit'); // If no contest has started yet, refuse submissions. $now = now(); $contestdata = $DB->q('MAYBETUPLE SELECT starttime,endtime FROM contest WHERE cid = %i', $contest); if (!isset($contestdata)) { error("Contest c{$contest} not found."); } if (difftime($contestdata['starttime'], $now) > 0) { error("The contest is closed, no submissions accepted. [c{$contest}]"); } // Check 2: valid parameters? if (!($langid = $DB->q('MAYBEVALUE SELECT langid FROM language WHERE langid = %s AND allow_submit = 1', $lang))) { error("Language '{$lang}' not found in database or not submittable."); } if (!($teamid = $DB->q('MAYBEVALUE SELECT teamid FROM team WHERE teamid = %i AND enabled = 1', $team))) { error("Team '{$team}' not found in database or not enabled."); } $probdata = $DB->q('MAYBETUPLE SELECT probid, points FROM problem INNER JOIN contestproblem USING (probid) WHERE probid = %s AND cid = %i AND allow_submit = 1', $prob, $contest); if (empty($probdata)) { error("Problem p{$prob} not found in database or not submittable [c{$contest}]."); } else { $points = $probdata['points']; $probid = $probdata['probid']; } // Reindex arrays numerically to allow simultaneously iterating // over both $files and $filenames. $files = array_values($files); $filenames = array_values($filenames); $totalsize = 0; for ($i = 0; $i < count($files); $i++) { if (!is_readable($files[$i])) { error("File '" . $files[$i] . "' not found (or not readable)."); } if (!preg_match(FILENAME_REGEX, $filenames[$i])) { error("Illegal filename '" . $filenames[$i] . "'."); } $totalsize += filesize($files[$i]); } if ($totalsize > $sourcesize * 1024) { error("Submission file(s) are larger than {$sourcesize} kB."); } logmsg(LOG_INFO, "input verified"); // Insert submission into the database $id = $DB->q('RETURNID INSERT INTO submission (cid, teamid, probid, langid, submittime, origsubmitid) VALUES (%i, %i, %i, %s, %s, %i)', $contest, $teamid, $probid, $langid, $now, $origsubmitid); for ($rank = 0; $rank < count($files); $rank++) { $DB->q('INSERT INTO submission_file (submitid, filename, rank, sourcecode) VALUES (%i, %s, %i, %s)', $id, $filenames[$rank], $rank, getFileContents($files[$rank], false)); } // Recalculate scoreboard cache for pending submissions calcScoreRow($contest, $teamid, $probid); // Log to event table $DB->q('INSERT INTO event (eventtime, cid, teamid, langid, probid, submitid, description) VALUES(%s, %i, %i, %s, %i, %i, "problem submitted")', now(), $contest, $teamid, $langid, $probid, $id); if (is_writable(SUBMITDIR)) { // Copy the submission to SUBMITDIR for safe-keeping for ($rank = 0; $rank < count($files); $rank++) { $fdata = array('cid' => $contest, 'submitid' => $id, 'teamid' => $teamid, 'probid' => $probid, 'langid' => $langid, 'rank' => $rank, 'filename' => $filenames[$rank]); $tofile = SUBMITDIR . '/' . getSourceFilename($fdata); if (!@copy($files[$rank], $tofile)) { warning("Could not copy '" . $files[$rank] . "' to '" . $tofile . "'"); } } } else { logmsg(LOG_DEBUG, "SUBMITDIR not writable, skipping"); } if (difftime($contestdata['endtime'], $now) <= 0) { logmsg(LOG_INFO, "The contest is closed, submission stored but not processed. [c{$contest}]"); } return $id; }
if ($show_compile == 2 || $show_compile == 1 && $row['result'] == 'compiler-error') { echo "<h2>Compilation output</h2>\n\n"; if (strlen(@$row['output_compile']) > 0) { echo "<pre class=\"output_text\">\n" . htmlspecialchars(@$row['output_compile']) . "\n</pre>\n\n"; } else { echo "<p class=\"nodata\">There were no compiler errors or warnings.</p>\n"; } if ($row['result'] == 'compiler-error') { echo "<p class=\"compilation-error\">Compilation failed.</p>\n"; } else { echo "<p class=\"compilation-success\">Compilation successful.</p>\n"; } } else { echo "<p class=\"nodata\">Compilation output is disabled.</p>\n"; } $show_sample = dbconfig_get('show_sample_output', 0); if ($show_sample && @$row['result'] != 'compiler-error') { $runs = $DB->q('TABLE SELECT r.*, t.rank, t.description FROM testcase t LEFT JOIN judging_run r ON ( r.testcaseid = t.testcaseid AND r.judgingid = %i ) WHERE t.probid = %i AND t.sample = 1 ORDER BY rank', $row['judgingid'], $row['probid']); echo '<h3>Run(s) on the provided sample data</h3>'; if (count($runs) == 0) { echo "<p class=\"nodata\">No sample cases available.</p>\n"; } foreach ($runs as $run) { echo "<h4 id=\"run-{$run['rank']}\">Run {$run['rank']}</h4>\n\n"; if ($run['runresult'] === NULL) { echo "<p class=\"nodata\">Run not finished yet.</p>\n"; continue; }
error("You do not have a team associated with your account. Please contact a staff member."); } if ($teamdata['enabled'] != 1) { error("Team is not enabled."); } $cdatas = getCurContests(TRUE, $teamdata['teamid']); $cids = array_keys($cdatas); // If the cookie has a existing contest, use it if (isset($_COOKIE['domjudge_cid']) && isset($cdatas[$_COOKIE['domjudge_cid']])) { $cid = $_COOKIE['domjudge_cid']; $cdata = $cdatas[$cid]; } elseif (count($cids) >= 1) { // Otherwise, select the first contest $cid = $cids[0]; $cdata = $cdatas[$cid]; } // Data to be sent as AJAX updates: $updates = array('clarifications' => array(), 'judgings' => array()); if (count($cids)) { $updates['clarifications'] = $DB->q('TABLE SELECT clarid, submittime, sender, recipient, probid, body FROM team_unread LEFT JOIN clarification ON(mesgid=clarid) WHERE teamid = %i AND cid IN (%Ai)', $teamid, $cids); } if (!empty($cid)) { $updates['judgings'] = $DB->q('TABLE SELECT s.submitid, j.judgingid, j.result, s.submittime FROM judging j LEFT JOIN submission s USING(submitid) WHERE s.teamid = %i AND j.cid = %i AND j.seen = 0 AND j.valid=1 AND s.submittime < %i' . (dbconfig_get('verification_required', 0) ? ' AND j.verified = 1' : ''), $teamid, $cid, $cdata['endtime']); }
/** * Output the general scoreboard based on the cached data in table * 'scorecache_{team,jury}'. $myteamid can be passed to highlight a * specific row. * If this function is called while IS_JURY is defined, the scoreboard * will always be current, regardless of the freezetime setting in the * contesttable. * $static generates output suitable for standalone static html pages, * that is without references/links to other parts of the DOMjudge * interface. * $limitteams is an array of teamid's whose rows will be the only * ones displayed. The function still needs the complete scoreboard * data or it will not know the rank. * if $displayrank is false the first column will not display the * team's current rank but a question mark. */ function renderScoreBoardTable($sdata, $myteamid = null, $static = FALSE, $limitteams = null, $displayrank = TRUE, $center = FALSE, $showlegends = TRUE) { // 'unpack' the scoreboard data: $scores = $sdata['scores']; $matrix = $sdata['matrix']; $summary = $sdata['summary']; $teams = $sdata['teams']; $probs = $sdata['problems']; $categs = $sdata['categories']; unset($sdata); // configuration $SHOW_AFFILIATIONS = dbconfig_get('show_affiliations', 1); $SHOW_PENDING = dbconfig_get('show_pending', 0); // Do not show points if they are all 1 $showpoints = FALSE; foreach ($probs as $pr) { if ($pr['points'] != 1) { $showpoints = TRUE; break; } } echo '<div class="tableContainer">'; echo '<table class="scoreboard' . (IS_JURY ? ' scoreboard_jury' : '') . ($center ? ' center' : '') . "\">\n"; // output table column groups (for the styles) echo '<colgroup><col id="scorerank" />' . ($SHOW_AFFILIATIONS ? '<col id="scoreaffil" />' : '') . '<col id="scoreteamname" /></colgroup><colgroup><col id="scoresolv" />' . "<col id=\"scoretotal\" /></colgroup>\n<colgroup>" . str_repeat('<col class="scoreprob" />', count($probs)) . "</colgroup>\n"; // column headers echo "<thead>\n"; echo '<tr class="scoreheader">' . '<th title="rank" scope="col">' . jurylink(null, 'rank') . '</th>' . '<th title="team name" scope="col"' . ($SHOW_AFFILIATIONS ? ' colspan="2"' : '') . '>' . jurylink(null, 'team') . '</th>' . '<th title="# solved / penalty time" colspan="2" scope="col">' . jurylink(null, 'score') . '</th>' . "\n"; foreach ($probs as $pr) { echo '<th title="problem \'' . htmlspecialchars($pr['name']) . '\'" scope="col">'; $str = htmlspecialchars($pr['shortname']) . (!empty($pr['color']) ? ' <div class="circle" style="background: ' . htmlspecialchars($pr['color']) . ';"></div>' : ''); if (!$static && (IS_JURY || $pr['hastext'] > 0)) { echo '<a href="problem.php?id=' . urlencode($pr['probid']) . '">' . $str . '</a>'; } else { echo '<a>' . $str . '</a>'; } if ($showpoints) { $points = $pr['points']; $pts = $points == 1 ? '1 point' : "{$points} points"; echo "<span class='problempoints'>[{$pts}]</span>"; } echo '</th>'; } echo "</tr>\n</thead>\n\n<tbody>\n"; // print the main scoreboard rows $prevsortorder = -1; foreach ($scores as $team => $totals) { // skip if we have limitteams and the team is not listed if (!empty($limitteams) && !in_array($team, $limitteams)) { continue; } // rank, team name, total points, total time echo '<tr'; $classes = array(); if ($totals['sortorder'] != $prevsortorder) { $classes[] = "sortorderswitch"; $prevsortorder = $totals['sortorder']; $prevteam = null; } // check whether this is us, otherwise use category colour if (@$myteamid == $team) { $classes[] = "scorethisisme"; unset($color); } else { $color = $teams[$team]['color']; } if (count($classes) > 0) { echo ' class="' . implode(' ', $classes) . '"'; } echo ' id="team:' . $teams[$team]['teamid'] . '"'; echo '><td class="scorepl">'; // Only print rank when score is different from the previous team if (!$displayrank) { echo jurylink(null, '?'); } elseif (!isset($prevteam) || $scores[$prevteam]['rank'] != $totals['rank']) { echo jurylink(null, $totals['rank']); } else { echo jurylink(null, ''); } $prevteam = $team; echo '</td>'; if ($SHOW_AFFILIATIONS) { echo '<td class="scoreaf">'; if (isset($teams[$team]['affilid'])) { if (IS_JURY) { echo '<a href="team_affiliation.php?id=' . urlencode($teams[$team]['affilid']) . '">'; } if (isset($teams[$team]['country'])) { $countryflag = '../images/countries/' . urlencode($teams[$team]['country']) . '.png'; echo ' '; if (is_readable($countryflag)) { echo '<img src="' . $countryflag . '"' . ' alt="' . htmlspecialchars($teams[$team]['country']) . '"' . ' title="' . htmlspecialchars($teams[$team]['country']) . '" />'; } else { echo htmlspecialchars($teams[$team]['country']); } } if (IS_JURY) { echo '</a>'; } } echo '</td>'; } $affilname = ''; if ($SHOW_AFFILIATIONS && isset($teams[$team]['affilid'])) { $affilname = htmlspecialchars($teams[$team]['affilname']); } echo '<td class="scoretn"' . (!empty($color) ? ' style="background: ' . $color . ';"' : '') . (IS_JURY ? ' title="' . htmlspecialchars($team) . '"' : '') . '>' . ($static ? '' : '<a href="team.php?id=' . urlencode($team) . '">') . htmlspecialchars($teams[$team]['name']) . ($SHOW_AFFILIATIONS ? '<br /><span class="univ">' . $affilname . '</span>' : '') . ($static ? '' : '</a>') . '</td>'; echo '<td class="scorenc">' . jurylink(null, $totals['num_points']) . '</td>' . '<td class="scorett">' . jurylink(null, $totals['total_time']) . '</td>'; // for each problem foreach (array_keys($probs) as $prob) { echo '<td class='; // CSS class for correct/incorrect/neutral results if ($matrix[$team][$prob]['is_correct']) { // The best times for each problem may not have been // calculated (if called from putTeamRow()), so we // have to suppress an undefined index here. echo '"score_correct' . (@$summary['problems'][$prob]['best_time_sort'][$totals['sortorder']] === $matrix[$team][$prob]['time'] ? ' score_first' : '') . '"'; } elseif ($matrix[$team][$prob]['num_pending'] > 0 && $SHOW_PENDING) { echo '"score_pending"'; } elseif ($matrix[$team][$prob]['num_submissions'] > 0) { echo '"score_incorrect"'; } else { echo '"score_neutral"'; } // number of submissions for this problem $str = $matrix[$team][$prob]['num_submissions']; // add pending submissions if ($matrix[$team][$prob]['num_pending'] > 0 && $SHOW_PENDING) { $str .= ' + ' . $matrix[$team][$prob]['num_pending']; } // if correct, print time scored if ($matrix[$team][$prob]['is_correct']) { $str .= '/' . $matrix[$team][$prob]['time']; } echo '>' . jurylink('team.php?id=' . urlencode($team) . '&restrict=probid:' . urlencode($prob), $str) . '</td>'; } echo "</tr>\n"; } echo "</tbody>\n\n"; if (empty($limitteams)) { // print a summaryline. Exclude the "total solved" cell if using // perproblem points as it's actually total points and not useful if (!$showpoints) { $totalCell = '<td title="total solved" class="scorenc">' . jurylink(null, $summary['num_points']) . '</td>'; } else { $totalCell = '<td class="scorenc" title=" "></td>'; // Empty } echo '<tbody><tr id="scoresummary" title="#submitted / #correct">' . '<td title="total teams">' . jurylink(null, count($matrix)) . '</td>' . ($SHOW_AFFILIATIONS ? '<td class="scoreaffil" title="#affiliations / #countries">' . jurylink('team_affiliations.php', count($summary['affils']) . ' / ' . count($summary['countries'])) . '</td>' : '') . '<td title=" ">' . jurylink(null, 'Summary') . '</td>' . $totalCell . '<td title=" "></td>'; foreach (array_keys($probs) as $prob) { $str = $summary['problems'][$prob]['num_submissions'] . '/' . $summary['problems'][$prob]['num_correct']; echo '<td>' . jurylink('problem.php?id=' . urlencode($prob), $str) . '</td>'; } echo "</tr>\n</tbody>\n"; } echo "</table>\n\n"; echo "</div>\n\n"; if ($showlegends) { echo "<p><br /><br /></p>\n"; // only print legend when there's more than one category if (empty($limitteams) && count($categs) > 1) { echo "<table id=\"categ_legend\" class=\"scoreboard scorelegend" . (IS_JURY ? ' scoreboard_jury' : '') . "\">\n" . "<thead><tr><th scope=\"col\">" . jurylink('team_categories.php', 'Categories') . "</th></tr></thead>\n<tbody>\n"; foreach ($categs as $cat) { echo '<tr' . (!empty($cat['color']) ? ' style="background: ' . $cat['color'] . ';"' : '') . '>' . '<td>' . jurylink('team_category.php?id=' . urlencode($cat['categoryid']), htmlspecialchars($cat['name'])) . "</td></tr>\n"; } echo "</tbody>\n</table>\n \n"; } // print legend of scorecell colors $cellcolors = array('first' => 'Solved first', 'correct' => 'Solved', 'incorrect' => 'Tried, incorrect', 'pending' => 'Tried, pending', 'neutral' => 'Untried'); echo "<table id=\"cell_legend\" class=\"scoreboard scorelegend" . (IS_JURY ? ' scoreboard_jury' : '') . "\">\n" . "<thead><tr><th scope=\"col\">" . jurylink(null, 'Cell colours') . "</th></tr></thead>\n<tbody>\n"; foreach ($cellcolors as $color => $desc) { if ($color == 'pending' && !dbconfig_get('show_pending', 0)) { continue; } echo '<tr class="score_' . $color . '">' . '<td>' . jurylink(null, $desc) . "</td></tr>\n"; } echo "</tbody>\n</table>\n\n"; } return; }
echo addForm($pagename, 'get') . "<p>\n" . addHidden('viewall', $viewall ? 0 : 1) . addSubmit($viewall ? 'view unsent only' : 'view all') . "</p>\n" . addEndForm(); $contestids = $cids; if ($cid !== null) { $contestids = array($cid); } // Problem metadata: colours and names. if (empty($cids)) { $probs_data = array(); } else { $probs_data = $DB->q('KEYTABLE SELECT probid AS ARRAYKEY,name,color,cid FROM problem INNER JOIN contestproblem USING (probid) WHERE cid IN (%Ai)', $contestids); } $freezecond = array(); if (!dbconfig_get('show_balloons_postfreeze', 0)) { foreach ($cdatas as $cdata) { if (isset($cdata['freezetime'])) { $freezecond[] = '(submittime <= "' . $cdata['freezetime'] . '" AND s.cid = ' . $cdata['cid'] . ')'; } else { $freezecond[] = '(s.cid = ' . $cdata['cid'] . ')'; } } } if (empty($freezecond)) { $freezecond = ''; } else { $freezecond = 'AND (' . implode(' OR ', $freezecond) . ')'; } // Get all relevant info from the balloon table. // Order by done, so we have the unsent balloons at the top.
function do_register() { global $DB, $ip; if (!dbconfig_get('allow_registration', false)) { error("Self-Registration is disabled."); } if (AUTH_METHOD != "PHP_SESSIONS") { error("You can only register if the site is using PHP Sessions for authentication."); } $login = trim($_POST['login']); $pass = trim($_POST['passwd']); $pass2 = trim($_POST['passwd2']); if ($login == '' || $pass == '') { error("You must enter all fields"); } if (!ctype_alnum($login)) { error("Username must consist of only alphanumeric characters."); } if ($pass != $pass2) { error("Your passwords do not match. Please go back and try registering again."); } $user = $DB->q('MAYBETUPLE SELECT * FROM user WHERE username = %s', $login); if ($user) { error("That login is already taken."); } $team = $DB->q('MAYBETUPLE SELECT * FROM team WHERE name = %s', $login); if ($team) { error("That login is already taken."); } // Create the team object $i = array(); $i['name'] = $login; $i['categoryid'] = 2; // Self-registered category id $i['enabled'] = 1; $i['comments'] = "Registered by {$ip} on " . date('r'); $teamid = $DB->q("RETURNID INSERT INTO team SET %S", $i); auditlog('team', $teamid, 'registered by ' . $ip); // Associate a user with the team we just made $i = array(); $i['username'] = $login; $i['password'] = md5($login . "#" . $pass); $i['name'] = $login; $i['teamid'] = $teamid; $newid = $DB->q("RETURNID INSERT INTO user SET %S", $i); auditlog('user', $newid, 'registered by ' . $ip); $DB->q("INSERT INTO `userrole` (`userid`, `roleid`) VALUES ({$newid}, 3)"); $title = 'Account Registered'; $menu = false; require LIBWWWDIR . '/header.php'; echo "<h1>Account registered</h1>\n\n<p><a href=\"./\">Click here to login.</a></p>\n\n"; require LIBWWWDIR . '/footer.php'; exit; }
function check_add($probid, $rank, $FILES) { global $DB; $result = ''; if (!empty($_FILES['add_input']['name']) || !empty($_FILES['add_output']['name'])) { $content = array(); foreach ($FILES as $file) { if (empty($_FILES['add_' . $file]['name'])) { warning("No {$file} file specified for new testcase, ignoring."); } else { checkFileUpload($_FILES['add_' . $file]['error']); $content[$file] = file_get_contents($_FILES['add_' . $file]['tmp_name']); } } $DB->q("INSERT INTO testcase\n\t\t (probid,rank,md5sum_input,md5sum_output,input,output,description,sample)\n\t\t VALUES (%i,%i,%s,%s,%s,%s,%s,%i)", $probid, $rank, md5(@$content['input']), md5(@$content['output']), @$content['input'], @$content['output'], @$_POST['add_desc'], isset($_POST['add_sample'])); if (!empty($content['image'])) { list($thumb, $type) = get_image_thumb_type($content['image']); $DB->q('UPDATE testcase SET image = %s, image_thumb = %s, image_type = %s WHERE probid = %i AND rank = %i', @$content['image'], $thumb, $type, $probid, $rank); } auditlog('testcase', $probid, 'added', "rank {$rank}"); $result .= "<li>Added new testcase {$rank} from files " . specialchars($_FILES['add_input']['name']) . " (" . printsize($_FILES['add_input']['size']) . ") and " . specialchars($_FILES['add_output']['name']) . " (" . printsize($_FILES['add_output']['size']) . ")."; if ($_FILES['add_output']['size'] > dbconfig_get('output_limit') * 1024) { $result .= "<br /><b>Warning: output file size exceeds " . "<code>output_limit</code> of " . dbconfig_get('output_limit') . " kB. This will always result in wrong answers!</b>"; } if (empty($content['input']) || empty($content['output'])) { $result .= "<br /><b>Warning: empty testcase file(s)!</b>"; } $result .= "</li>\n"; } return $result; }