1
0
mirror of https://github.com/renbaoshuo/UOJ-Luogu-RemoteJudge.git synced 2024-12-12 22:26:28 +00:00

feat: patch "/judge/submit" handler

This commit is contained in:
Baoshuo Ren 2023-03-19 21:50:20 +08:00
parent 4fd3006e34
commit 91035c482a
Signed by: baoshuo
GPG Key ID: 00CB9680AB29F51A
2 changed files with 288 additions and 0 deletions

View File

@ -0,0 +1,226 @@
<?php
requirePHPLib('judger');
requirePHPLib('data');
if (!authenticateJudger()) {
become404Page();
}
function submissionJudged() {
$submission = DB::selectFirst("select submitter, status, content, result, problem_id from submissions where id = {$_POST['id']}");
if ($submission == null) {
return;
}
if ($submission['status'] != 'Judging' && $submission['status'] != 'Judged, Judging') {
return;
}
$content = json_decode($submission['content'], true);
if (isset($content['first_test_config'])) {
$result = json_decode($submission['result'], true);
$result['final_result'] = json_decode($_POST['result'], true);
$result['final_result']['details'] = uojTextEncode($result['final_result']['details']);
$esc_result = DB::escape(json_encode($result, JSON_UNESCAPED_UNICODE));
$content['final_test_config'] = $content['config'];
$content['config'] = $content['first_test_config'];
unset($content['first_test_config']);
$esc_content = DB::escape(json_encode($content));
DB::update("update submissions set status = 'Judged', result = '$esc_result', content = '$esc_content' where id = {$_POST['id']}");
} else {
$result = json_decode($_POST['result'], true);
$result['details'] = uojTextEncode($result['details']);
$esc_result = DB::escape(json_encode($result, JSON_UNESCAPED_UNICODE));
if (isset($result["error"])) {
DB::update("update submissions set status = '{$result['status']}', result_error = '{$result['error']}', result = '$esc_result', score = null, used_time = null, used_memory = null where id = {$_POST['id']}");
} else {
DB::update("update submissions set status = '{$result['status']}', result_error = null, result = '$esc_result', score = {$result['score']}, used_time = {$result['time']}, used_memory = {$result['memory']} where id = {$_POST['id']}");
}
if (isset($content['final_test_config'])) {
$content['first_test_config'] = $content['config'];
$content['config'] = $content['final_test_config'];
unset($content['final_test_config']);
$esc_content = DB::escape(json_encode($content));
DB::update("update submissions set status = 'Judged, Waiting', content = '$esc_content' where id = ${_POST['id']}");
}
}
DB::update("update submissions set status_details = '' where id = {$_POST['id']}");
updateBestACSubmissions($submission['submitter'], $submission['problem_id']);
}
function customTestSubmissionJudged() {
$submission = DB::selectFirst("select submitter, status, content, result, problem_id from custom_test_submissions where id = {$_POST['id']}");
if ($submission == null) {
return;
}
if ($submission['status'] != 'Judging') {
return;
}
$content = json_decode($submission['content'], true);
$result = json_decode($_POST['result'], true);
$result['details'] = uojTextEncode($result['details']);
$esc_result = DB::escape(json_encode($result, JSON_UNESCAPED_UNICODE));
if (isset($result["error"])) {
DB::update("update custom_test_submissions set status = '{$result['status']}', result = '$esc_result' where id = {$_POST['id']}");
} else {
DB::update("update custom_test_submissions set status = '{$result['status']}', result = '$esc_result' where id = {$_POST['id']}");
}
DB::update("update custom_test_submissions set status_details = '' where id = {$_POST['id']}");
}
function hackJudged() {
$result = json_decode($_POST['result'], true);
$esc_details = DB::escape(uojTextEncode($result['details']));
$ok = DB::update("update hacks set success = {$result['score']}, details = '$esc_details' where id = {$_POST['id']}");
if ($ok) {
list($hack_input) = DB::fetch(DB::query("select input from hacks where id = {$_POST['id']}"), MYSQLI_NUM);
unlink(UOJContext::storagePath().$hack_input);
if ($result['score']) {
list($problem_id) = DB::selectFirst("select problem_id from hacks where id = ${_POST['id']}", MYSQLI_NUM);
if (validateUploadedFile('hack_input') && validateUploadedFile('std_output')) {
dataAddExtraTest(queryProblemBrief($problem_id), $_FILES["hack_input"]["tmp_name"], $_FILES["std_output"]["tmp_name"]);
} else {
error_log("hack successfully but received no data. id: {$_POST['id']}");
}
}
}
}
if (isset($_POST['submit'])) {
if (!validateUInt($_POST['id'])) {
die("Wow! hacker! T_T....");
}
if (isset($_POST['is_hack'])) {
hackJudged();
} elseif (isset($_POST['is_custom_test'])) {
customTestSubmissionJudged();
} else {
submissionJudged();
}
}
if (isset($_POST['update-status'])) {
if (!validateUInt($_POST['id'])) {
die("Wow! hacker! T_T....");
}
$esc_status_details = DB::escape($_POST['status']);
if (isset($_POST['is_custom_test'])) {
DB::update("update custom_test_submissions set status_details = '$esc_status_details' where id = {$_POST['id']}");
} else {
DB::update("update submissions set status_details = '$esc_status_details' where id = {$_POST['id']}");
}
die();
}
$problem_ban_list = array();
if ($_POST['judger_name'] == "luogu_remote_judger") {
$problem_ban_list = array_map(function ($x) { return $x['id']; }, DB::selectAll("select id from problems where type != 'luogu'"));
} else {
$problem_ban_list = array_map(function ($x) { return $x['id']; }, DB::selectAll("select id from problems where type != 'local'"));
}
$conds = " (true) ";
if (!empty($problem_ban_list)) {
$conds .= " and problem_id not in (" . implode(",", $problem_ban_list) . ") ";
}
$submission = null;
$hack = null;
function querySubmissionToJudge($status, $set_q) {
global $submission, $conds;
$submission = DB::selectFirst("select id, problem_id, content from submissions where status = '$status' and $conds order by id limit 1");
if ($submission) {
DB::update("update submissions set $set_q where id = {$submission['id']} and status = '$status'");
if (DB::affected_rows() != 1) {
$submission = null;
}
}
}
function queryCustomTestSubmissionToJudge() {
global $submission, $conds;
$submission = DB::selectFirst("select id, problem_id, content from custom_test_submissions where judge_time is null and $conds order by id limit 1");
if ($submission) {
DB::update("update custom_test_submissions set judge_time = now(), status = 'Judging' where id = {$submission['id']} and judge_time is null");
if (DB::affected_rows() != 1) {
$submission = null;
}
}
if ($submission) {
$submission['is_custom_test'] = '';
}
}
function queryHackToJudge() {
global $hack, $conds;
$hack = DB::selectFirst("select id, submission_id, input, input_type from hacks where judge_time is null and $conds order by id limit 1");
if ($hack) {
DB::update("update hacks set judge_time = now() where id = {$hack['id']} and judge_time is null");
if (DB::affected_rows() != 1) {
$hack = null;
}
}
}
function findSubmissionToJudge() {
global $submission, $hack;
querySubmissionToJudge('Waiting', "judge_time = now(), status = 'Judging'");
if ($submission) {
return true;
}
queryCustomTestSubmissionToJudge();
if ($submission) {
return true;
}
querySubmissionToJudge('Waiting Rejudge', "judge_time = now(), status = 'Judging'");
if ($submission) {
return true;
}
querySubmissionToJudge('Judged, Waiting', "status = 'Judged, Judging'");
if ($submission) {
return true;
}
queryHackToJudge();
if ($hack) {
$submission = DB::selectFirst("select id, problem_id, content from submissions where id = {$hack['submission_id']} and score = 100");
if (!$submission) {
$details = "<error>the score gained by the hacked submission is not 100.\n</error>";
$esc_details = DB::escape(uojTextEncode($details));
DB::update("update hacks set success = 0, details = '$esc_details' where id = {$hack['id']}");
return false;
}
return true;
}
return false;
}
if (isset($_POST['fetch_new']) && !$_POST['fetch_new']) {
die("Nothing to judge");
}
if (!findSubmissionToJudge()) {
die("Nothing to judge");
}
$submission['id'] = (int)$submission['id'];
$submission['problem_id'] = (int)$submission['problem_id'];
$submission['problem_mtime'] = filemtime("/var/uoj_data/{$submission['problem_id']}");
$submission['content'] = json_decode($submission['content']);
if ($hack) {
$submission['is_hack'] = "";
$submission['hack']['id'] = (int)$hack['id'];
$submission['hack']['input'] = $hack['input'];
$submission['hack']['input_type'] = $hack['input_type'];
}
echo json_encode($submission);
?>

View File

@ -0,0 +1,62 @@
--- UOJ-System/web/app/controllers/judge/submit.php 2022-12-30 09:54:05.452022649 +0800
+++ UOJ-Luogu-RemoteJudge/web/app/controllers/judge/submit.php 2023-03-19 21:47:57.347852462 +0800
@@ -85,7 +85,7 @@
if (validateUploadedFile('hack_input') && validateUploadedFile('std_output')) {
dataAddExtraTest(queryProblemBrief($problem_id), $_FILES["hack_input"]["tmp_name"], $_FILES["std_output"]["tmp_name"]);
} else {
- error_log("hack successfully but received no data. id: ${_POST['id']}");
+ error_log("hack successfully but received no data. id: {$_POST['id']}");
}
}
}
@@ -115,12 +115,26 @@
}
die();
}
+
+ $problem_ban_list = array();
+
+ if ($_POST['judger_name'] == "luogu_remote_judger") {
+ $problem_ban_list = array_map(function ($x) { return $x['id']; }, DB::selectAll("select id from problems where type != 'luogu'"));
+ } else {
+ $problem_ban_list = array_map(function ($x) { return $x['id']; }, DB::selectAll("select id from problems where type != 'local'"));
+ }
+
+ $conds = " (true) ";
+
+ if (!empty($problem_ban_list)) {
+ $conds .= " and problem_id not in (" . implode(",", $problem_ban_list) . ") ";
+ }
$submission = null;
$hack = null;
function querySubmissionToJudge($status, $set_q) {
- global $submission;
- $submission = DB::selectFirst("select id, problem_id, content from submissions where status = '$status' order by id limit 1");
+ global $submission, $conds;
+ $submission = DB::selectFirst("select id, problem_id, content from submissions where status = '$status' and $conds order by id limit 1");
if ($submission) {
DB::update("update submissions set $set_q where id = {$submission['id']} and status = '$status'");
if (DB::affected_rows() != 1) {
@@ -129,8 +143,8 @@
}
}
function queryCustomTestSubmissionToJudge() {
- global $submission;
- $submission = DB::selectFirst("select id, problem_id, content from custom_test_submissions where judge_time is null order by id limit 1");
+ global $submission, $conds;
+ $submission = DB::selectFirst("select id, problem_id, content from custom_test_submissions where judge_time is null and $conds order by id limit 1");
if ($submission) {
DB::update("update custom_test_submissions set judge_time = now(), status = 'Judging' where id = {$submission['id']} and judge_time is null");
if (DB::affected_rows() != 1) {
@@ -142,8 +156,8 @@
}
}
function queryHackToJudge() {
- global $hack;
- $hack = DB::selectFirst("select id, submission_id, input, input_type from hacks where judge_time is null order by id limit 1");
+ global $hack, $conds;
+ $hack = DB::selectFirst("select id, submission_id, input, input_type from hacks where judge_time is null and $conds order by id limit 1");
if ($hack) {
DB::update("update hacks set judge_time = now() where id = {$hack['id']} and judge_time is null");
if (DB::affected_rows() != 1) {