public static function CanEditClarification($user_id, Clarifications $clarification) { if (is_null($clarification) || !is_a($clarification, 'Clarifications')) { return false; } try { $contest = ContestsDAO::getByPK($clarification->getContestId()); $problem = ProblemsDAO::getByPK($clarification->getProblemId()); } catch (Exception $e) { throw new InvalidDatabaseOperationException($e); } if (is_null($contest) || is_null($problem)) { return false; } return $problem->getAuthorId() === $user_id || Authorization::IsContestAdmin($user_id, $contest); }
public static final function IsRunInsideSubmissionGap($contest_id, $problem_id, $user_id) { // Get last run $lastrun = self::GetLastRun($contest_id, $problem_id, $user_id); if (is_null($lastrun)) { return true; } $submission_gap = 0; if ($contest_id != null) { // Get submissions gap $contest = ContestsDAO::getByPK($contest_id); $submission_gap = (int) $contest->getSubmissionsGap(); } $submission_gap = max($submission_gap, RunController::$defaultSubmissionGap); return time() >= strtotime($lastrun->getTime()) + $submission_gap; }
public static function RefreshScoreboardCache($contest_id) { try { $contest = ContestsDAO::getByPK($contest_id); $contest_runs = RunsDAO::GetContestRuns($contest_id); // Get all distinct contestants participating in the contest given contest_id $raw_contest_users = RunsDAO::GetAllRelevantUsers($contest_id, true, null); // Get all problems given contest_id $raw_contest_problems = ContestProblemsDAO::GetRelevantProblems($contest_id); } catch (Exception $e) { throw new InvalidDatabaseOperationException($e); } $problem_mapping = array(); $order = 0; foreach ($raw_contest_problems as $problem) { $problem_mapping[$problem->problem_id] = array('order' => $order++, 'alias' => $problem->alias); } $scoreboardLimit = Scoreboard::getScoreboardTimeLimitUnixTimestamp($contest); // Cache scoreboard until the contest ends (or forever if it has already ended). $timeout = max(0, strtotime($contest->getFinishTime()) - time()); $contestantScoreboardCache = new Cache(Cache::CONTESTANT_SCOREBOARD_PREFIX, $contest_id); $contestantScoreboard = Scoreboard::getScoreboardFromRuns($contest_runs, $raw_contest_users, $problem_mapping, $contest->getPenalty(), $scoreboardLimit, $contest, false, false); $contestantScoreboardCache->set($contestantScoreboard, $timeout); $adminScoreboardCache = new Cache(Cache::ADMIN_SCOREBOARD_PREFIX, $contest_id); $scoreboardLimit = Scoreboard::getScoreboardTimeLimitUnixTimestamp($contest, true); $adminScoreboard = Scoreboard::getScoreboardFromRuns($contest_runs, $raw_contest_users, $problem_mapping, $contest->getPenalty(), $scoreboardLimit, $contest, true, false); $adminScoreboardCache->set($adminScoreboard, $timeout); $contestantEventCache = new Cache(Cache::CONTESTANT_SCOREBOARD_EVENTS_PREFIX, $contest_id); $contestantEventCache->set(Scoreboard::calculateEvents($contest, $contest_runs, $raw_contest_users, $problem_mapping, false), $timeout); $adminEventCache = new Cache(Cache::ADMIN_SCOREBOARD_EVENTS_PREFIX, $contest_id); $adminEventCache->set(Scoreboard::calculateEvents($contest, $contest_runs, $raw_contest_users, $problem_mapping, true), $timeout); // Try to broadcast the updated scoreboards: $log = Logger::getLogger('Scoreboard'); try { $grader = new Grader(); $log->debug('Sending updated scoreboards'); $grader->broadcast($contest->alias, json_encode(array('message' => '/scoreboard/update/', 'scoreboard' => $adminScoreboard)), false, -1, false); $grader->broadcast($contest->alias, json_encode(array('message' => '/scoreboard/update/', 'scoreboard' => $contestantScoreboard)), true, -1, true); } catch (Exception $e) { $log->error('Error broadcasting scoreboard: ' . $e); } }
/** * Get list of contests where the user has admin priviledges * * @param Request $r * @return string * @throws InvalidDatabaseOperationException */ public static function apiContests(Request $r) { self::authenticateRequest($r); $response = array(); $response['contests'] = array(); try { $contest_director_key = new Contests(array('director_id' => $r['current_user_id'])); $contests_director = ContestsDAO::search($contest_director_key); foreach ($contests_director as $contest) { $response['contests'][] = $contest->asArray(); } $contest_admin_key = new UserRoles(array('user_id' => $r['current_user_id'], 'role_id' => CONTEST_ADMIN_ROLE)); $contests_admin = UserRolesDAO::search($contest_admin_key); foreach ($contests_admin as $contest_key) { $contest = ContestsDAO::getByPK($contest_key->getContestId()); if (is_null($contest)) { self::$log->error("UserRoles has a invalid contest: {$contest->getContestId()}"); continue; } $response['contests'][] = $contest->asArray(); } usort($response['contests'], function ($a, $b) { return $a['contest_id'] > $b['contest_id'] ? -1 : 1; }); } catch (Exception $e) { throw new InvalidDatabaseOperationException($e); } $response['status'] = 'ok'; return $response; }
/** * Details of a scoreboard. Returns a list with all contests that belong to * the given scoreboard_alias * * @param Request $r */ public static function apiDetails(Request $r) { self::validateGroupScoreboard($r); $response = array(); // Fill contests $response["contests"] = array(); $response["ranking"] = array(); try { $groupScoreboardContestKey = new GroupsScoreboardsContests(array("group_scoreboard_id" => $r["scoreboard"]->group_scoreboard_id)); $r["gscs"] = GroupsScoreboardsContestsDAO::search($groupScoreboardContestKey); $i = 0; $contest_params = array(); foreach ($r["gscs"] as $gsc) { $contest = ContestsDAO::getByPK($gsc->contest_id); $response["contests"][$i] = $contest->asArray(); $response["contests"][$i]["only_ac"] = $gsc->only_ac; $response["contests"][$i]["weight"] = $gsc->weight; // Fill contest params to pass to scoreboardMerge $contest_params[$contest->alias] = array("only_ac" => $gsc->only_ac == 0 ? false : true, "weight" => $gsc->weight); $i++; } } catch (ApiException $ex) { throw $ex; } catch (Exception $ex) { throw new InvalidDatabaseOperationException($ex); } $r["contest_params"] = $contest_params; // Fill details of this scoreboard $response["scoreboard"] = $r["scoreboard"]->asArray(); // If we have contests, calculate merged&filtered scoreboard if (count($response["contests"]) > 0) { // Get merged scoreboard $r["contest_aliases"] = ""; foreach ($response["contests"] as $contest) { $r["contest_aliases"] .= $contest["alias"] . ","; } $r["contest_aliases"] = rtrim($r["contest_aliases"], ","); try { $groupUsers = GroupsUsersDAO::search(new GroupsUsers(array("group_id" => $r["scoreboard"]->group_id))); $r["usernames_filter"] = ""; foreach ($groupUsers as $groupUser) { $user = UsersDAO::getByPK($groupUser->user_id); $r["usernames_filter"] .= $user->username . ","; } $r["usernames_filter"] = rtrim($r["usernames_filter"], ","); } catch (Exception $ex) { throw new InvalidDatabaseOperationException($ex); } $mergedScoreboardResponse = ContestController::apiScoreboardMerge($r); $response["ranking"] = $mergedScoreboardResponse["ranking"]; } $response["status"] = "ok"; return $response; }
/** * Invalidates relevant caches on run rejudge * * @param RunsDAO $run */ public static function invalidateCacheOnRejudge(Runs $run) { try { // Expire details of the run Cache::deleteFromCache(Cache::RUN_ADMIN_DETAILS, $run->getRunId()); $contest = ContestsDAO::getByPK($run->getContestId()); // Now we need to invalidate problem stats $problem = ProblemsDAO::getByPK($run->getProblemId()); if (!is_null($problem)) { // Invalidar cache stats Cache::deleteFromCache(Cache::PROBLEM_STATS, $problem->getAlias()); } } catch (Exception $e) { // We did our best effort to invalidate the cache... self::$log->warn('Failed to invalidate cache on Rejudge, skipping: '); self::$log->warn($e); } }
/** * Details of a scoreboard. Returns a list with all contests that belong to * the given scoreboard_alias * * @param Request $r */ public static function apiDetails(Request $r) { self::validateGroupScoreboard($r); $response = array(); // Fill contests $response['contests'] = array(); $response['ranking'] = array(); try { $groupScoreboardContestKey = new GroupsScoreboardsContests(array('group_scoreboard_id' => $r['scoreboard']->group_scoreboard_id)); $r['gscs'] = GroupsScoreboardsContestsDAO::search($groupScoreboardContestKey); $i = 0; $contest_params = array(); foreach ($r['gscs'] as $gsc) { $contest = ContestsDAO::getByPK($gsc->contest_id); $response['contests'][$i] = $contest->asArray(); $response['contests'][$i]['only_ac'] = $gsc->only_ac; $response['contests'][$i]['weight'] = $gsc->weight; // Fill contest params to pass to scoreboardMerge $contest_params[$contest->alias] = array('only_ac' => $gsc->only_ac == 0 ? false : true, 'weight' => $gsc->weight); $i++; } } catch (ApiException $ex) { throw $ex; } catch (Exception $ex) { throw new InvalidDatabaseOperationException($ex); } $r['contest_params'] = $contest_params; // Fill details of this scoreboard $response['scoreboard'] = $r['scoreboard']->asArray(); // If we have contests, calculate merged&filtered scoreboard if (count($response['contests']) > 0) { // Get merged scoreboard $r['contest_aliases'] = ''; foreach ($response['contests'] as $contest) { $r['contest_aliases'] .= $contest['alias'] . ','; } $r['contest_aliases'] = rtrim($r['contest_aliases'], ','); try { $groupUsers = GroupsUsersDAO::search(new GroupsUsers(array('group_id' => $r['scoreboard']->group_id))); $r['usernames_filter'] = ''; foreach ($groupUsers as $groupUser) { $user = UsersDAO::getByPK($groupUser->user_id); $r['usernames_filter'] .= $user->username . ','; } $r['usernames_filter'] = rtrim($r['usernames_filter'], ','); } catch (Exception $ex) { throw new InvalidDatabaseOperationException($ex); } $mergedScoreboardResponse = ContestController::apiScoreboardMerge($r); $response['ranking'] = $mergedScoreboardResponse['ranking']; } $response['status'] = 'ok'; return $response; }