2016-07-18 16:39:37 +00:00
|
|
|
<?php
|
2022-11-06 02:26:21 +00:00
|
|
|
requirePHPLib('judger');
|
|
|
|
requirePHPLib('data');
|
|
|
|
|
|
|
|
if (!authenticateJudger()) {
|
|
|
|
UOJResponse::page404();
|
|
|
|
}
|
|
|
|
|
|
|
|
function submissionJudged() {
|
|
|
|
UOJSubmission::onJudged(UOJRequest::post('id'), UOJRequest::post('result'), UOJRequest::post('judge_time'));
|
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
$result = json_decode($_POST['result'], true);
|
|
|
|
$result['details'] = uojTextEncode($result['details']);
|
|
|
|
DB::update([
|
|
|
|
"update custom_test_submissions",
|
|
|
|
"set", [
|
|
|
|
'status' => $result['status'],
|
|
|
|
'status_details' => '',
|
|
|
|
'result' => json_encode($result, JSON_UNESCAPED_UNICODE)
|
|
|
|
], "where", ['id' => $_POST['id']]
|
|
|
|
]);
|
|
|
|
}
|
|
|
|
|
|
|
|
function hackJudged() {
|
|
|
|
$result = json_decode($_POST['result'], true);
|
|
|
|
|
|
|
|
UOJHack::init($_POST['id']);
|
|
|
|
UOJHack::cur()->setProblem();
|
|
|
|
UOJHack::cur()->setSubmission();
|
|
|
|
|
|
|
|
if ($result['score']) {
|
|
|
|
$status = 'Judged, Waiting';
|
|
|
|
} else {
|
|
|
|
$status = 'Judged';
|
|
|
|
}
|
|
|
|
|
|
|
|
$ok = DB::update([
|
|
|
|
"update hacks",
|
|
|
|
"set", [
|
|
|
|
'success' => $result['score'],
|
|
|
|
'status' => $status,
|
|
|
|
'details' => uojTextEncode($result['details'])
|
|
|
|
], "where", ['id' => $_POST['id']]
|
|
|
|
]);
|
|
|
|
|
|
|
|
if (!$result['score']) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (!$ok) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(validateUploadedFile('hack_input') && validateUploadedFile('std_output'))) {
|
|
|
|
UOJLog::error("hack successfully but received no data. id: {$_POST['id']}");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
$input = UOJContext::storagePath() . UOJHack::info('input');
|
|
|
|
$up_in = $_FILES["hack_input"]['tmp_name'];
|
|
|
|
$up_out = $_FILES["std_output"]['tmp_name'];
|
|
|
|
|
|
|
|
if (!UOJHack::cur()->problem->needToReviewHack()) {
|
|
|
|
$err = dataAddHackPoint(UOJHack::cur()->problem->info, $up_in, $up_out);
|
|
|
|
if ($err === '') {
|
|
|
|
unlink($input);
|
|
|
|
DB::update([
|
|
|
|
"update hacks",
|
|
|
|
"set", [
|
|
|
|
'status' => 'Judged'
|
|
|
|
], "where", ['id' => $_POST['id']]
|
|
|
|
]);
|
2016-07-18 16:39:37 +00:00
|
|
|
return;
|
2022-11-06 02:26:21 +00:00
|
|
|
} else {
|
|
|
|
UOJLog::error("hack successfully but failed to add an extra test: {$err}");
|
2016-07-18 16:39:37 +00:00
|
|
|
}
|
2022-11-06 02:26:21 +00:00
|
|
|
}
|
|
|
|
move_uploaded_file($up_in, "{$input}_in");
|
|
|
|
move_uploaded_file($up_out, "{$input}_out");
|
|
|
|
DB::update([
|
|
|
|
"update hacks",
|
|
|
|
"set", [
|
|
|
|
'status' => 'Judged, WaitingM'
|
|
|
|
], "where", ['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....");
|
|
|
|
}
|
|
|
|
|
|
|
|
$status_details = $_POST['status'];
|
|
|
|
if (isset($_POST['is_custom_test'])) {
|
|
|
|
DB::update([
|
|
|
|
"update custom_test_submissions",
|
|
|
|
"set", ["status_details" => $status_details],
|
|
|
|
"where", ["id" => $_POST['id']]
|
|
|
|
]);
|
|
|
|
} else {
|
|
|
|
DB::update([
|
|
|
|
"update submissions",
|
|
|
|
"set", ["status_details" => $status_details],
|
|
|
|
"where", ["id" => $_POST['id']]
|
|
|
|
]);
|
|
|
|
}
|
|
|
|
die();
|
|
|
|
}
|
|
|
|
|
2023-01-18 02:21:53 +00:00
|
|
|
$assignCond = [];
|
|
|
|
|
|
|
|
$problem_ban_list = array_map(fn ($x) => $x['id'], DB::selectAll([
|
2022-11-06 02:26:21 +00:00
|
|
|
"select id from problems",
|
|
|
|
"where", [
|
|
|
|
["assigned_to_judger", "!=", "any"],
|
|
|
|
["assigned_to_judger", "!=", $_POST['judger_name']]
|
|
|
|
]
|
2023-01-18 02:21:53 +00:00
|
|
|
]));
|
|
|
|
|
|
|
|
if ($problem_ban_list) {
|
|
|
|
$assignCond[] = ["problem_id", "not in", DB::rawtuple($problem_ban_list)];
|
|
|
|
}
|
|
|
|
|
|
|
|
if ($_POST['judger_name'] == "remote_judger") {
|
|
|
|
$problem_ban_list = array_map(fn ($x) => $x['id'], DB::selectAll([
|
|
|
|
"select id from problems",
|
|
|
|
"where", [
|
2023-01-18 08:20:12 +00:00
|
|
|
["type", "!=", "remote"],
|
2023-01-18 02:21:53 +00:00
|
|
|
],
|
|
|
|
]));
|
|
|
|
} else {
|
|
|
|
$problem_ban_list = array_map(fn ($x) => $x['id'], DB::selectAll([
|
|
|
|
"select id from problems",
|
|
|
|
"where", [
|
2023-01-18 08:20:12 +00:00
|
|
|
["type", "!=", "local"],
|
2023-01-18 02:21:53 +00:00
|
|
|
],
|
|
|
|
]));
|
|
|
|
}
|
|
|
|
|
|
|
|
if ($problem_ban_list) {
|
|
|
|
$assignCond[] = ["problem_id", "not in", DB::rawtuple($problem_ban_list)];
|
2022-11-06 02:26:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
$submission = null;
|
|
|
|
$hack = null;
|
|
|
|
function querySubmissionToJudge($status, $set_q) {
|
|
|
|
global $assignCond;
|
|
|
|
|
|
|
|
for ($times = 0; $times < 10; $times++) {
|
|
|
|
$submission = DB::selectFirst([
|
|
|
|
"select id from submissions",
|
|
|
|
"where", array_merge(["status" => $status], $assignCond),
|
|
|
|
"order by id limit 1"
|
|
|
|
]);
|
|
|
|
if (!$submission) {
|
|
|
|
return null;
|
2016-07-18 16:39:37 +00:00
|
|
|
}
|
2022-11-06 02:26:21 +00:00
|
|
|
|
|
|
|
$ok = DB::transaction(function () use (&$submission, $set_q, $status) {
|
|
|
|
DB::update([
|
|
|
|
"update submissions",
|
|
|
|
"set", $set_q,
|
|
|
|
"where", [
|
|
|
|
"id" => $submission['id'],
|
|
|
|
"status" => $status
|
|
|
|
]
|
|
|
|
]);
|
|
|
|
if (DB::affected_rows() == 1) {
|
|
|
|
$submission = DB::selectFirst([
|
|
|
|
"select id, problem_id, content, status, judge_time from submissions",
|
|
|
|
"where", ["id" => $submission['id']]
|
|
|
|
]);
|
|
|
|
return true;
|
2016-07-18 16:39:37 +00:00
|
|
|
} else {
|
2022-11-06 02:26:21 +00:00
|
|
|
return false;
|
2016-07-18 16:39:37 +00:00
|
|
|
}
|
2022-11-06 02:26:21 +00:00
|
|
|
});
|
|
|
|
if ($ok) {
|
|
|
|
return $submission;
|
2016-07-18 16:39:37 +00:00
|
|
|
}
|
|
|
|
}
|
2022-11-06 02:26:21 +00:00
|
|
|
}
|
|
|
|
function queryMinorSubmissionToJudge($status, $set_q) {
|
|
|
|
global $assignCond;
|
2016-07-18 16:39:37 +00:00
|
|
|
|
2022-11-06 02:26:21 +00:00
|
|
|
for ($times = 0; $times < 10; $times++) {
|
|
|
|
$submission = null;
|
|
|
|
$his = DB::selectFirst([
|
|
|
|
"select id, submission_id from submissions_history",
|
|
|
|
"where", ["status" => $status, "major" => 0], // $assignCond is removed!!! fix this bug in the future!
|
|
|
|
"order by id limit 1"
|
|
|
|
]);
|
|
|
|
if (!$his) {
|
|
|
|
return null;
|
2016-07-18 16:39:37 +00:00
|
|
|
}
|
2022-11-06 02:26:21 +00:00
|
|
|
|
|
|
|
$ok = DB::transaction(function () use (&$submission, &$his, $set_q, $status) {
|
|
|
|
$submission = DB::selectFirst([
|
|
|
|
"select id, problem_id, content from submissions",
|
|
|
|
"where", ["id" => $his['submission_id']], DB::for_share()
|
|
|
|
]);
|
|
|
|
if (!$submission) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
DB::update([
|
|
|
|
"update submissions_history",
|
|
|
|
"set", $set_q,
|
|
|
|
"where", [
|
|
|
|
"id" => $his['id'],
|
|
|
|
"status" => $status
|
|
|
|
]
|
|
|
|
]);
|
|
|
|
if (DB::affected_rows() == 1) {
|
|
|
|
$ret = DB::selectFirst([
|
|
|
|
"select status, judge_time from submissions_history",
|
|
|
|
"where", ["id" => $his['id']]
|
|
|
|
]);
|
|
|
|
if ($ret === false) {
|
|
|
|
return false;
|
2016-07-18 16:39:37 +00:00
|
|
|
}
|
2022-11-06 02:26:21 +00:00
|
|
|
$submission += $ret;
|
|
|
|
return true;
|
|
|
|
} else {
|
|
|
|
return false;
|
2016-07-18 16:39:37 +00:00
|
|
|
}
|
2022-11-06 02:26:21 +00:00
|
|
|
});
|
|
|
|
if ($ok) {
|
|
|
|
return $submission;
|
2016-07-18 16:39:37 +00:00
|
|
|
}
|
|
|
|
}
|
2022-11-06 02:26:21 +00:00
|
|
|
}
|
|
|
|
function queryCustomTestSubmissionToJudge() {
|
|
|
|
global $assignCond;
|
|
|
|
|
|
|
|
while (true) {
|
|
|
|
$submission = DB::selectFirst([
|
|
|
|
"select id, problem_id, content from custom_test_submissions",
|
|
|
|
"where", array_merge(["judge_time" => null], $assignCond),
|
|
|
|
"order by id limit 1"
|
|
|
|
]);
|
|
|
|
if (!$submission) {
|
|
|
|
return null;
|
2016-07-18 16:39:37 +00:00
|
|
|
}
|
2022-11-06 02:26:21 +00:00
|
|
|
$submission['is_custom_test'] = '';
|
|
|
|
|
|
|
|
DB::update([
|
|
|
|
"update custom_test_submissions",
|
|
|
|
"set", [
|
|
|
|
"judge_time" => DB::now(),
|
|
|
|
"status" => 'Judging'
|
|
|
|
], "where", [
|
|
|
|
"id" => $submission['id'],
|
|
|
|
"judge_time" => null
|
|
|
|
]
|
|
|
|
]);
|
|
|
|
if (DB::affected_rows() == 1) {
|
|
|
|
$submission['status'] = 'Judging';
|
|
|
|
return $submission;
|
2016-07-18 16:39:37 +00:00
|
|
|
}
|
|
|
|
}
|
2022-11-06 02:26:21 +00:00
|
|
|
}
|
|
|
|
function queryHackToJudge() {
|
|
|
|
global $assignCond;
|
|
|
|
|
|
|
|
while (true) {
|
|
|
|
if (DB::selectFirst([
|
|
|
|
"select 1 from hacks",
|
|
|
|
"where", [
|
|
|
|
["status", "!=", "Waiting"],
|
|
|
|
["status", "!=", "Judged"],
|
|
|
|
], "order by id limit 1"
|
|
|
|
])) {
|
|
|
|
return null;
|
2016-07-18 16:39:37 +00:00
|
|
|
}
|
2022-11-06 02:26:21 +00:00
|
|
|
|
|
|
|
$hack = DB::selectFirst([
|
|
|
|
"select id, submission_id, input, input_type from hacks",
|
|
|
|
"where", array_merge(["judge_time" => null], $assignCond),
|
|
|
|
"order by id limit 1"
|
|
|
|
]);
|
|
|
|
if (!$hack) {
|
|
|
|
return null;
|
2016-07-18 16:39:37 +00:00
|
|
|
}
|
2022-11-06 02:26:21 +00:00
|
|
|
|
|
|
|
DB::update([
|
|
|
|
"update hacks",
|
|
|
|
"set", [
|
|
|
|
"judge_time" => DB::now(),
|
|
|
|
"status" => 'Judging'
|
|
|
|
],
|
|
|
|
"where", [
|
|
|
|
"id" => $hack['id'],
|
|
|
|
"judge_time" => null
|
|
|
|
]
|
|
|
|
]);
|
|
|
|
if (DB::affected_rows() == 1) {
|
|
|
|
$hack['status'] = 'Judging';
|
|
|
|
return $hack;
|
2016-07-18 16:39:37 +00:00
|
|
|
}
|
|
|
|
}
|
2022-11-06 02:26:21 +00:00
|
|
|
}
|
|
|
|
function findSubmissionToJudge() {
|
|
|
|
global $submission, $hack;
|
|
|
|
$submission = querySubmissionToJudge('Waiting', [
|
|
|
|
"judge_time" => DB::now(),
|
|
|
|
"judger" => $_POST['judger_name'],
|
|
|
|
"status" => 'Judging'
|
|
|
|
]);
|
|
|
|
if ($submission) {
|
|
|
|
return true;
|
2016-07-18 16:39:37 +00:00
|
|
|
}
|
2022-11-06 02:26:21 +00:00
|
|
|
|
|
|
|
$submission = queryCustomTestSubmissionToJudge();
|
|
|
|
if ($submission) {
|
|
|
|
return true;
|
2016-07-18 16:39:37 +00:00
|
|
|
}
|
|
|
|
|
2022-11-06 02:26:21 +00:00
|
|
|
$submission = querySubmissionToJudge('Waiting Rejudge', [
|
|
|
|
"judge_time" => DB::now(),
|
|
|
|
"judger" => $_POST['judger_name'],
|
|
|
|
"status" => 'Judging'
|
|
|
|
]);
|
|
|
|
if ($submission) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
$submission = querySubmissionToJudge('Judged, Waiting', [
|
|
|
|
"status" => 'Judged, Judging'
|
|
|
|
]);
|
|
|
|
if ($submission) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
$submission = queryMinorSubmissionToJudge('Waiting Rejudge', [
|
|
|
|
"judge_time" => DB::now(),
|
|
|
|
"judger" => $_POST['judger_name'],
|
|
|
|
"status" => 'Judging'
|
|
|
|
]);
|
|
|
|
if ($submission) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
$submission = queryMinorSubmissionToJudge('Judged, Waiting', [
|
|
|
|
"status" => 'Judged, Judging'
|
|
|
|
]);
|
|
|
|
if ($submission) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
$hack = queryHackToJudge();
|
2016-07-18 16:39:37 +00:00
|
|
|
if ($hack) {
|
2022-11-06 02:26:21 +00:00
|
|
|
$submission = DB::selectFirst([
|
|
|
|
"select id, problem_id, content from submissions",
|
|
|
|
"where", [
|
|
|
|
"id" => $hack['submission_id'],
|
|
|
|
"score" => 100
|
|
|
|
]
|
|
|
|
]);
|
|
|
|
if (!$submission) {
|
|
|
|
$details = "<error>the score gained by the hacked submission is not 100.</error>";
|
|
|
|
DB::update([
|
|
|
|
"update hacks",
|
|
|
|
"set", [
|
|
|
|
'success' => 0,
|
|
|
|
'status' => 'Judged',
|
|
|
|
'details' => uojTextEncode($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'], true);
|
|
|
|
if (isset($submission['status']) && $submission['status'] == 'Judged, Judging' && isset($submission['content']['final_test_config'])) {
|
|
|
|
$submission['content']['config'] = $submission['content']['final_test_config'];
|
|
|
|
unset($submission['content']['final_test_config']);
|
|
|
|
}
|
|
|
|
|
|
|
|
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);
|