} if (count($probs) == 0) { echo "No problems defined, doing nothing.</pre>\n\n"; continue; } // for each team, fetch the status of each problem foreach ($teams as $team) { echo "Team t" . specialchars($team['teamid']) . ":"; // for each problem fetch the result foreach ($probs as $pr) { echo " p" . specialchars($pr['probid']); calcScoreRow($pr['cid'], $team['teamid'], $pr['probid']); } // Now recompute the rank echo " rankcache"; updateRankCache($contest, $team['teamid']); echo "\n"; ob_flush(); } echo "</pre>\n\n"; } echo "<p>Deleting irrelevant data...</p>\n\n"; // Drop all teams and problems that do not exist in each contest foreach ($contests as $contest) { $probids = $DB->q('COLUMN SELECT probid FROM problem INNER JOIN contestproblem USING (probid) WHERE cid = %i ORDER BY shortname', $contest); $teamids = $DB->q('COLUMN SELECT t.teamid FROM team t INNER JOIN contest c ON c.cid = %i LEFT JOIN contestteam ct ON ct.teamid = t.teamid AND ct.cid = c.cid WHERE (c.public = 1 OR ct.teamid IS NOT NULL) ORDER BY teamid', $contest);
/** * 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; }
if (count($probs) == 0) { echo "No problems defined, doing nothing.</pre>\n\n"; continue; } // for each team, fetch the status of each problem foreach ($teams as $team) { echo "Team t" . specialchars($team['teamid']) . ":"; // for each problem fetch the result foreach ($probs as $pr) { echo " p" . specialchars($pr['probid']); calcScoreRow($pr['cid'], $team['teamid'], $pr['probid']); } // Now recompute the rank for both jury and public echo " rankcache"; updateRankCache($contest, $team['teamid'], true); updateRankCache($contest, $team['teamid'], false); echo "\n"; ob_flush(); } echo "</pre>\n\n"; } echo "<p>Deleting irrelevant data...</p>\n\n"; // Drop all teams and problems that do not exist in each contest foreach ($contests as $contest) { $probids = $DB->q('COLUMN SELECT probid FROM problem INNER JOIN contestproblem USING (probid) WHERE cid = %i ORDER BY shortname', $contest); $teamids = $DB->q('COLUMN SELECT t.teamid FROM team t INNER JOIN contest c ON c.cid = %i LEFT JOIN contestteam ct ON ct.teamid = t.teamid AND ct.cid = c.cid WHERE (c.public = 1 OR ct.teamid IS NOT NULL) ORDER BY teamid', $contest);