/** * Scoreboard calculation * * Given a contestid, teamid and a problemid, * (re)calculate the values for one row in the scoreboard. * * Due to current transactions usage, this function MUST NOT contain * any START TRANSACTION or COMMIT statements. */ function calcScoreRow($cid, $team, $prob) { global $DB; logmsg(LOG_DEBUG, "calcScoreRow '{$cid}' '{$team}' '{$prob}'"); // First acquire an advisory lock to prevent other calls to // calcScoreRow() from interfering with our update. $lockstr = "domjudge.{$cid}.{$team}.{$prob}"; if ($DB->q("VALUE SELECT GET_LOCK('{$lockstr}',3)") != 1) { error("calcScoreRow failed to obtain lock '{$lockstr}'"); } // Note the clause 'submittime < c.endtime': this is used to // filter out TOO-LATE submissions from pending, but it also means // that these will not count as solved. Correct submissions with // submittime after contest end should never happen, unless one // resets the contest time after successful judging. $result = $DB->q('SELECT result, verified, submittime, (c.freezetime IS NOT NULL && submittime >= c.freezetime) AS afterfreeze FROM submission s LEFT JOIN judging j ON(s.submitid=j.submitid AND j.valid=1) LEFT OUTER JOIN contest c ON(c.cid=s.cid) WHERE teamid = %i AND probid = %i AND s.cid = %i AND s.valid = 1 ' . (dbconfig_get('compile_penalty', 1) ? "" : "AND j.result != 'compiler-error' ") . 'AND submittime < c.endtime ORDER BY submittime', $team, $prob, $cid); // reset vars $submitted_j = $pending_j = $time_j = $correct_j = 0; $submitted_p = $pending_p = $time_p = $correct_p = 0; // for each submission while ($row = $result->next()) { // Contest submit time in minutes for scoring. $submittime = (int) floor(calcContestTime($row['submittime'], $cid) / 60); // Check if this submission has a publicly visible judging result: if (dbconfig_get('verification_required', 0) && !$row['verified'] || empty($row['result'])) { $pending_j++; $pending_p++; // Don't do any more counting for this submission. continue; } $submitted_j++; if ($row['afterfreeze']) { // Show submissions after freeze as pending to the public // (if SHOW_PENDING is enabled): $pending_p++; } else { $submitted_p++; } // if correct, don't look at any more submissions after this one if ($row['result'] == 'correct') { $correct_j = 1; $time_j = $submittime; if (!$row['afterfreeze']) { $correct_p = 1; $time_p = $submittime; } // stop counting after a first correct submission break; } } // insert or update the values in the public/team scores table $DB->q('REPLACE INTO scorecache_public (cid, teamid, probid, submissions, pending, totaltime, is_correct) VALUES (%i,%i,%i,%i,%i,%i,%i)', $cid, $team, $prob, $submitted_p, $pending_p, $time_p, $correct_p); // insert or update the values in the jury scores table $DB->q('REPLACE INTO scorecache_jury (cid, teamid, probid, submissions, pending, totaltime, is_correct) VALUES (%i,%i,%i,%i,%i,%i,%i)', $cid, $team, $prob, $submitted_j, $pending_j, $time_j, $correct_j); if ($DB->q("VALUE SELECT RELEASE_LOCK('{$lockstr}')") != 1) { error("calcScoreRow failed to release lock '{$lockstr}'"); } // If we found a new correct result, update the rank cache too if ($correct_j > 0) { updateRankCache($cid, $team, true); } if ($correct_p > 0) { updateRankCache($cid, $team, false); } return; }
} elseif (isset($_POST['export'])) { // Fetch data from database and store in an associative array $cid = @$_POST['contest']; $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; }
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']]); XMLaddnode($run, 'team', $team_to_id[$data['teamid']]); XMLaddnode($run, 'timestamp', $row['eventtime']); XMLaddnode($run, 'time', calcContestTime($data['submittime'], $cid)); XMLaddnode($run, 'language', $data['langname']); if ($row['description'] == 'problem submitted') { XMLaddnode($run, 'judged', 'False'); XMLaddnode($run, 'status', 'fresh'); } else { $jdata = $DB->q('MAYBETUPLE SELECT result, starttime FROM judging j LEFT JOIN submission USING(submitid) WHERE j.valid = 1 AND judgingid = %i', $row['judgingid']); if (!isset($jdata['result'])) { continue; } $ntestcases = $DB->q('VALUE SELECT count(*) FROM testcase WHERE probid = %i', $data['probid']); $jruns = $DB->q('SELECT rank, runresult, runtime FROM judging_run