diff --git a/web/app/controllers/contest_inside.php b/web/app/controllers/contest_inside.php index 3b47fe4..5bccfb5 100644 --- a/web/app/controllers/contest_inside.php +++ b/web/app/controllers/contest_inside.php @@ -54,25 +54,24 @@ if ($is_manager) { isset($tabs_info[$cur_tab]) || UOJResponse::page404(); if (UOJContest::cur()->userCanStartFinalTest(Auth::user())) { - if (CONTEST_PENDING_FINAL_TEST <= $contest['cur_progress']) { - $start_test_form = new UOJBs4Form('start_test'); + if (CONTEST_PENDING_FINAL_TEST == $contest['cur_progress']) { + $start_test_form = new UOJForm('start_test'); $start_test_form->handle = function () { - UOJContest::finalTest(); + UOJContest::cur()->finalTest(); }; - $start_test_form->submit_button_config['class_str'] = 'btn btn-danger d-block w-100'; - $start_test_form->submit_button_config['smart_confirm'] = ''; - $start_test_form->submit_button_config['text'] = UOJContest::cur()->labelForFinalTest(); + $start_test_form->config['submit_button']['class'] = 'btn btn-danger d-block w-100'; + $start_test_form->config['submit_button']['text'] = UOJContest::cur()->labelForFinalTest(); + $start_test_form->config['confirm']['smart'] = true; $start_test_form->runAtServer(); } - if ($contest['cur_progress'] >= CONTEST_TESTING) { - $publish_result_form = new UOJBs4Form('publish_result'); + if ($contest['cur_progress'] >= CONTEST_TESTING && UOJContest::cur()->queryJudgeProgress()['fully_judged']) { + $publish_result_form = new UOJForm('publish_result'); $publish_result_form->handle = function () { UOJContest::announceOfficialResults(); }; - $publish_result_form->submit_button_config['class_str'] = 'btn btn-danger d-block w-100'; - $publish_result_form->submit_button_config['smart_confirm'] = ''; - $publish_result_form->submit_button_config['text'] = '公布成绩'; - + $publish_result_form->config['submit_button']['class'] = 'btn btn-danger d-block w-100'; + $publish_result_form->config['submit_button']['text'] = '公布成绩'; + $publish_result_form->config['confirm']['smart'] = true; $publish_result_form->runAtServer(); } } diff --git a/web/app/models/UOJContest.php b/web/app/models/UOJContest.php index e7496d9..41cb363 100644 --- a/web/app/models/UOJContest.php +++ b/web/app/models/UOJContest.php @@ -53,65 +53,6 @@ class UOJContest { return isSuperUser($user) || UOJUser::checkPermission($user, 'contests.create'); } - public static function finalTest() { - $contest = self::info(); - - $res = DB::selectAll([ - "select id, problem_id, content, submitter, hide_score_to_others from submissions", - "where", ["contest_id" => $contest['id']] - ]); - foreach ($res as $submission) { - $content = json_decode($submission['content'], true); - if (isset($content['final_test_config'])) { - $content['config'] = $content['final_test_config']; - unset($content['final_test_config']); - } - if (isset($content['first_test_config'])) { - unset($content['first_test_config']); - } - UOJSubmission::rejudgeById($submission['id'], [ - 'reason_text' => HTML::stripTags($contest['name']) . ' 最终测试', - 'reason_url' => HTML::url(UOJContest::cur()->getUri()), - 'set_q' => [ - "content" => json_encode($content) - ] - ]); - } - - // warning: check if this command works well when the database is not MySQL - DB::update([ - "update submissions", - "set", [ - "score = hidden_score", - "hidden_score = NULL", - "hide_score_to_others = 0" - ], "where", [ - "contest_id" => $contest['id'], - "hide_score_to_others" => 1 - ] - ]); - - $updated = []; - foreach ($res as $submission) { - $submitter = $submission['submitter']; - $pid = $submission['problem_id']; - if (isset($updated[$submitter]) && isset($updated[$submitter][$pid])) { - continue; - } - updateBestACSubmissions($submitter, $pid); - if (!isset($updated[$submitter])) { - $updated[$submitter] = []; - } - $updated[$submitter][$pid] = true; - } - - DB::update([ - "update contests", - "set", ["status" => 'testing'], - "where", ["id" => $contest['id']] - ]); - } - public static function announceOfficialResults() { // time config set_time_limit(0); @@ -246,17 +187,128 @@ class UOJContest { $label = '开始最终测试'; } - if ($this->progress() >= CONTEST_TESTING) { - $label = '重新' . $label; + return $label; + } + + public function finalTest() { + ignore_user_abort(true); + set_time_limit(0); + + DB::update([ + "update contests", + "set", ["status" => 'testing'], + "where", ["id" => $this->info['id']] + ]); + + if (DB::affected_rows() !== 1) { + // 已经有其他人开始评测了,不进行任何操作 + return; } - return $label; + $res = DB::selectAll([ + "select id, problem_id, content, result, submitter, hide_score_to_others from submissions", + "where", ["contest_id" => $this->info['id']] + ]); + foreach ($res as $submission) { + $content = json_decode($submission['content'], true); + + if (isset($content['final_test_config'])) { + $content['config'] = $content['final_test_config']; + unset($content['final_test_config']); + } + + if (isset($content['first_test_config'])) { + unset($content['first_test_config']); + } + + $q = [ + 'content' => json_encode($content), + ]; + + $problem_judge_type = $this->info['extra_config']["problem_{$submission['problem_id']}"] ?: $this->defaultProblemJudgeType(); + $result = json_decode($submission['result'], true); + + switch ($problem_judge_type) { + case 'sample': + if (isset($result['final_result']) && $result['final_result']['status'] == 'Judged') { + $q += [ + 'result' => json_encode($result['final_result']), + 'score' => $result['final_result']['score'], + 'used_time' => $result['final_result']['time'], + 'used_memory' => $result['final_result']['memory'], + 'judge_time' => $this->info['end_time_str'], + 'status' => 'Judged', + ]; + + if ($submission['hide_score_to_others']) { + $q['hidden_score'] = $q['score']; + $q['score'] = null; + } + } + + break; + + case 'no-details': + case 'full': + if ($result['status'] == 'Judged') { + $q += [ + 'result' => $submission['result'], + 'score' => $result['score'], + 'used_time' => $result['time'], + 'used_memory' => $result['memory'], + 'judge_time' => $this->info['end_time_str'], + 'status' => 'Judged', + ]; + + if ($submission['hide_score_to_others']) { + $q['hidden_score'] = $q['score']; + $q['score'] = null; + } + } + + break; + } + + UOJSubmission::rejudgeById($submission['id'], [ + 'reason_text' => HTML::stripTags($this->info['name']) . ' 最终测试', + 'reason_url' => HTML::url(UOJContest::cur()->getUri()), + 'set_q' => $q, + ]); + } + + // warning: check if this command works well when the database is not MySQL + DB::update([ + "update submissions", + "set", [ + "score = hidden_score", + "hidden_score = NULL", + "hide_score_to_others = 0" + ], "where", [ + "contest_id" => $this->info['id'], + "hide_score_to_others" => 1 + ] + ]); + + $updated = []; + foreach ($res as $submission) { + $submitter = $submission['submitter']; + $pid = $submission['problem_id']; + if (isset($updated[$submitter]) && isset($updated[$submitter][$pid])) { + continue; + } + updateBestACSubmissions($submitter, $pid); + if (!isset($updated[$submitter])) { + $updated[$submitter] = []; + } + $updated[$submitter][$pid] = true; + } } public function queryJudgeProgress() { if ($this->basicRule() == 'OI' && $this->progress() < CONTEST_TESTING) { $rop = 0; $title = UOJLocale::get('contests::contest pending final test'); + $fully_judged = false; } else { $total = DB::selectCount([ "select count(*) from submissions", @@ -272,13 +324,15 @@ class UOJContest { $rop = $total == 0 ? 100 : (int)($n_judged / $total * 100); $title = UOJLocale::get('contests::contest final testing'); - if ($this->basicRule() != 'OI' && $n_judged == $total) { + $fully_judged = $n_judged == $total; + if ($this->basicRule() != 'OI' && $fully_judged) { $title = UOJLocale::get('contests::contest official results to be announced'); } } return [ 'rop' => $rop, - 'title' => $title + 'title' => $title, + 'fully_judged' => $fully_judged, ]; }