public function testCoderOfTheMonthCalc() { $user = UserFactory::createUser(); $contest = ContestsFactory::createContest(); $problem = ProblemsFactory::createProblem(); ContestsFactory::addProblemToContest($problem, $contest); ContestsFactory::addUser($contest, $user); // Creating 10 AC runs for our user in the last month $n = 10; $lastMonth = intval(date('m')) - 1; $runCreationDate = null; if ($lastMonth == 0) { $runCreationDate = date(intval(date('Y') - 1) . '-12-01'); } else { $runCreationDate = date('Y-' . $lastMonth . '-01'); } for ($i = 0; $i < $n; $i++) { $runData = RunsFactory::createRun($problem, $contest, $user); RunsFactory::gradeRun($runData); // Force the run to be in last month $run = RunsDAO::getByAlias($runData['response']['guid']); $run->setTime($runCreationDate); RunsDAO::save($run); } $response = UserController::apiCoderOfTheMonth(new Request()); $this->assertEquals($user->getUsername(), $response['userinfo']['username']); }
/** * Validate a run * * @param type $r * @param type $response */ private function assertRun($r, $response) { // Validate $this->assertEquals("ok", $response["status"]); $this->assertArrayHasKey("guid", $response); // Get run from DB $run = RunsDAO::getByAlias($response["guid"]); $this->assertNotNull($run); // Get contest from DB to check times with respect to contest start $contest = ContestsDAO::getByAlias($r["contest_alias"]); // Validate data $this->assertEquals($r["language"], $run->getLanguage()); $this->assertNotNull($run->getGuid()); // Validate file created $filename = RunController::getSubmissionPath($run); $this->assertFileExists($filename); $fileContent = file_get_contents($filename); $this->assertEquals($r["source"], $fileContent); // Validate defaults $this->assertEquals("new", $run->getStatus()); $this->assertEquals(0, $run->getRuntime()); $this->assertEquals(0, $run->getMemory()); $this->assertEquals(0, $run->getScore()); $this->assertEquals(0, $run->getContestScore()); $this->assertEquals("127.0.0.1", $run->getIp()); if (!is_null($contest)) { $this->assertEquals((time() - intval(strtotime($contest->getStartTime()))) / 60, $run->penalty, '', 0.5); } $this->assertEquals("JE", $run->getVerdict()); }
/** * Validate a run * * @param type $r * @param type $response */ private function assertRun($r, $response) { // Validate $this->assertEquals('ok', $response['status']); $this->assertArrayHasKey('guid', $response); // Get run from DB $run = RunsDAO::getByAlias($response['guid']); $this->assertNotNull($run); // Get contest from DB to check times with respect to contest start $contest = ContestsDAO::getByAlias($r['contest_alias']); // Validate data $this->assertEquals($r['language'], $run->getLanguage()); $this->assertNotNull($run->getGuid()); // Validate file created $filename = RunController::getSubmissionPath($run); $this->assertFileExists($filename); $fileContent = file_get_contents($filename); $this->assertEquals($r['source'], $fileContent); // Validate defaults $this->assertEquals('new', $run->getStatus()); $this->assertEquals(0, $run->getRuntime()); $this->assertEquals(0, $run->getMemory()); $this->assertEquals(0, $run->getScore()); $this->assertEquals(0, $run->getContestScore()); $logs = SubmissionLogDAO::search(array('run_id' => $run->run_id)); $this->assertEquals(1, count($logs)); $this->assertEquals(ip2long('127.0.0.1'), $logs[0]->ip); if (!is_null($contest)) { $this->assertEquals((time() - intval(strtotime($contest->getStartTime()))) / 60, $run->penalty, '', 0.5); } $this->assertEquals('JE', $run->getVerdict()); }
public function testRunTotals() { // Get a problem $problemData = ProblemsFactory::createProblem(); // Get a contest $contestData = ContestsFactory::createContest(); // Add the problem to the contest ContestsFactory::addProblemToContest($problemData, $contestData); // Create our contestant $contestant = UserFactory::createUser(); // Create a run $runData = RunsFactory::createRun($problemData, $contestData, $contestant); $runDataOld = RunsFactory::createRun($problemData, $contestData, $contestant); $run = RunsDAO::getByAlias($runDataOld['response']['guid']); $run->setTime(date('Y-m-d H:i:s', strtotime('-72 hours'))); RunsDAO::save($run); $response = RunController::apiCounts(new Request()); $this->assertGreaterThan(1, count($response)); }
/** * Given a run id, set a score to a given run * * @param type $runData * @param int $points * @param string $verdict */ public static function gradeRun($runData, $points = 1, $verdict = 'AC', $submitDelay = null) { $run = RunsDAO::getByAlias($runData['response']['guid']); $run->setVerdict($verdict); $run->setScore($points); $run->setContestScore($points * 100); $run->setStatus('ready'); $run->judged_by = 'J1'; if (!is_null($submitDelay)) { $run->submit_delay = $submitDelay; $run->penalty = $submitDelay; } RunsDAO::save($run); }
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 stats * * @param Request $r */ public static function apiStats(Request $r) { self::authenticateOrAllowUnauthenticatedRequest($r); $user = self::resolveTargetUser($r); try { $totalRunsCount = RunsDAO::CountTotalRunsOfUser($user->getUserId()); // List of verdicts $verdict_counts = array(); foreach (self::$verdicts as $verdict) { $verdict_counts[$verdict] = RunsDAO::CountTotalRunsOfUserByVerdict($user->getUserId(), $verdict); } } catch (Exception $e) { throw new InvalidDatabaseOperationException($e); } return array('verdict_counts' => $verdict_counts, 'total_runs' => $totalRunsCount, 'status' => 'ok'); }
/** * Gets a list of latest runs overall * * @param Request $r * @return string * @throws InvalidDatabaseOperationException */ public static function apiList(Request $r) { // Authenticate request self::authenticateRequest($r); self::validateList($r); try { $runs = RunsDAO::GetAllRuns(null, $r['status'], $r['verdict'], !is_null($r['problem']) ? $r['problem']->getProblemId() : null, $r['language'], !is_null($r['user']) ? $r['user']->getUserId() : null, $r['offset'], $r['rowcount']); } catch (Exception $e) { // Operation failed in the data layer throw new InvalidDatabaseOperationException($e); } $result = array(); foreach ($runs as $run) { $run['time'] = (int) $run['time']; $run['score'] = round((double) $run['score'], 4); if ($run['contest_score'] != null) { $run['contest_score'] = round((double) $run['contest_score'], 2); } array_push($result, $run); } $response = array(); $response['runs'] = $result; $response['status'] = 'ok'; return $response; }
public static function apiDownload(Request $r) { self::authenticateRequest($r); self::validateStats($r); // Get our runs $relevant_columns = array("run_id", "guid", "language", "status", "verdict", "runtime", "penalty", "memory", "score", "contest_score", "time", "submit_delay", "Users.username", "Problems.alias"); try { $runs = RunsDAO::search(new Runs(array("contest_id" => $r["contest"]->getContestId())), "time", "DESC", $relevant_columns); } catch (Exception $e) { // Operation failed in the data layer throw new InvalidDatabaseOperationException($e); } $zip = new ZipStream($r["contest_alias"] . '.zip'); // Add runs to zip $table = "guid,user,problem,verdict,points\n"; foreach ($runs as $run) { $zip->add_file_from_path("runs/" . $run->getGuid(), RunController::getSubmissionPath($run)); $columns[0] = 'username'; $columns[1] = 'alias'; $usernameProblemData = $run->asFilteredArray($columns); $table .= $run->getGuid() . "," . $usernameProblemData['username'] . "," . $usernameProblemData['alias'] . "," . $run->getVerdict() . "," . $run->getContestScore(); $table .= "\n"; } $zip->add_file("summary.csv", $table); // Add problem cases to zip $contest_problems = ContestProblemsDAO::GetRelevantProblems($r["contest"]->getContestId()); foreach ($contest_problems as $problem) { $zip->add_file_from_path($problem->getAlias() . "_cases.zip", PROBLEMS_PATH . "/" . $problem->getAlias() . "/cases.zip"); } // Return zip $zip->finish(); die; }
public static function apiDownload(Request $r) { self::authenticateRequest($r); self::validateStats($r); // Get our runs $relevant_columns = array('run_id', 'guid', 'language', 'status', 'verdict', 'runtime', 'penalty', 'memory', 'score', 'contest_score', 'time', 'submit_delay', 'Users.username', 'Problems.alias'); try { $runs = RunsDAO::search(new Runs(array('contest_id' => $r['contest']->getContestId())), 'time', 'DESC', $relevant_columns); } catch (Exception $e) { // Operation failed in the data layer throw new InvalidDatabaseOperationException($e); } $zip = new ZipStream($r['contest_alias'] . '.zip'); // Add runs to zip $table = "guid,user,problem,verdict,points\n"; foreach ($runs as $run) { $zip->add_file_from_path('runs/' . $run->getGuid(), RunController::getSubmissionPath($run)); $columns[0] = 'username'; $columns[1] = 'alias'; $usernameProblemData = $run->asFilteredArray($columns); $table .= $run->getGuid() . ',' . $usernameProblemData['username'] . ',' . $usernameProblemData['alias'] . ',' . $run->getVerdict() . ',' . $run->getContestScore(); $table .= "\n"; } $zip->add_file('summary.csv', $table); // Add problem cases to zip $contest_problems = ContestProblemsDAO::GetRelevantProblems($r['contest']->getContestId()); foreach ($contest_problems as $problem) { $zip->add_file_from_path($problem->getAlias() . '_cases.zip', PROBLEMS_PATH . '/' . $problem->getAlias() . '/cases.zip'); } // Return zip $zip->finish(); die; }
/** * Returns the best score of a problem. * Problem must be loadad in $r["problem"] * Contest could be loadad in $r["contest"]. If set, will only look for * runs inside that contest. * * Authentication is expected to be performed earlier. * * @param Request $r * @return float * @throws InvalidDatabaseOperationException */ private static function bestScore(Request $r, Users $user = null) { $current_user_id = is_null($user) ? $r['current_user_id'] : $user->getUserId(); if (is_null($current_user_id)) { return 0; } $score = 0; try { // Add best score info if (is_null($r['contest'])) { $score = RunsDAO::GetBestScore($r['problem']->getProblemId(), $current_user_id); } else { $bestRun = RunsDAO::GetBestRun($r['contest']->getContestId(), $r['problem']->getProblemId(), $current_user_id, strtotime($r['contest']->getFinishTime()), false); $score = is_null($bestRun->getContestScore()) ? 0 : $bestRun->getContestScore(); } } catch (Exception $e) { throw new InvalidDatabaseOperationException($e); } return $score; }
/** * Given a run id, set a score to a given run * * @param type $runData * @param int $points * @param string $verdict */ public static function gradeRun($runData, $points = 1, $verdict = "AC", $submitDelay = null) { $run = RunsDAO::getByAlias($runData["response"]["guid"]); $run->setVerdict($verdict); $run->setScore($points); $run->setContestScore($points * 100); $run->setStatus("ready"); $run->judged_by = "J1"; if (!is_null($submitDelay)) { $run->submit_delay = $submitDelay; $run->penalty = $submitDelay; } RunsDAO::save($run); }