From 7cdb39267a71f4a4e66e627aa10b8b8d239e6442 Mon Sep 17 00:00:00 2001 From: Baoshuo Date: Thu, 2 Feb 2023 20:07:35 +0800 Subject: [PATCH] feat(problem/remote): prepare for luogu --- web/app/controllers/new_remote_problem.php | 9 +- .../controllers/problem_statement_manage.php | 13 +- web/app/libs/uoj-form-lib.php | 141 ++++++++++++++++-- web/app/libs/uoj-html-lib.php | 18 ++- web/app/models/UOJForm.php | 1 + web/app/models/UOJProblem.php | 2 + web/app/models/UOJRemoteProblem.php | 28 ++++ web/app/models/UOJSubmission.php | 7 +- web/app/models/UOJSubmissionLikeTrait.php | 18 +++ 9 files changed, 201 insertions(+), 36 deletions(-) diff --git a/web/app/controllers/new_remote_problem.php b/web/app/controllers/new_remote_problem.php index 63cf369..e7af67d 100644 --- a/web/app/controllers/new_remote_problem.php +++ b/web/app/controllers/new_remote_problem.php @@ -73,14 +73,7 @@ $new_remote_problem_form->handle = function (&$vdata) { UOJResponse::page500('题目抓取失败,可能是题目不存在或者没有题面!如果题目没有问题,请稍后再试。返回'); } - $submission_requirement = [ - [ - "name" => "answer", - "type" => "source code", - "file_name" => "answer.code", - "languages" => $remote_provider['languages'], - ] - ]; + $submission_requirement = UOJRemoteProblem::getSubmissionRequirements($remote_online_judge); $enc_submission_requirement = json_encode($submission_requirement); $extra_config = [ diff --git a/web/app/controllers/problem_statement_manage.php b/web/app/controllers/problem_statement_manage.php index 3ccc75b..3b3353a 100644 --- a/web/app/controllers/problem_statement_manage.php +++ b/web/app/controllers/problem_statement_manage.php @@ -118,7 +118,7 @@ if (UOJProblem::info('type') == 'remote') { EOD); $re_crawl_form->config['submit_button']['text'] = '重新爬取'; - $re_crawl_form->handle = function () use ($remote_online_judge, $remote_problem_id, $remote_provider) { + $re_crawl_form->handle = function () use ($remote_online_judge, $remote_problem_id) { try { $data = UOJRemoteProblem::getProblemBasicInfo($remote_online_judge, $remote_problem_id); } catch (Exception $e) { @@ -134,16 +134,9 @@ if (UOJProblem::info('type') == 'remote') { $data['difficulty'] = UOJProblem::info('difficulty'); } - $submission_requirement = [ - [ - "name" => "answer", - "type" => "source code", - "file_name" => "answer.code", - "languages" => $remote_provider['languages'], - ] - ]; + $submission_requirement = UOJRemoteProblem::getSubmissionRequirements($remote_online_judge); $enc_submission_requirement = json_encode($submission_requirement); - + $extra_config = [ 'remote_online_judge' => $remote_online_judge, 'remote_problem_id' => $remote_problem_id, diff --git a/web/app/libs/uoj-form-lib.php b/web/app/libs/uoj-form-lib.php index aef5409..41a3efa 100644 --- a/web/app/libs/uoj-form-lib.php +++ b/web/app/libs/uoj-form-lib.php @@ -46,6 +46,7 @@ function newAddDelCmdForm($form_name, $validate, $handle, $final = null) { function newSubmissionForm($form_name, $requirement, $zip_file_name_gen, $handle) { $form = new UOJForm($form_name); + foreach ($requirement as $req) { if ($req['type'] == "source code") { $languages = UOJLang::getAvailableLanguages(isset($req['languages']) ? $req['languages'] : null); @@ -57,6 +58,101 @@ function newSubmissionForm($form_name, $requirement, $zip_file_name_gen, $handle $form->addTextFileInput("{$form_name}_{$req['name']}", [ 'filename' => $req['file_name'], ]); + } else if ($req['type'] == "remote submission") { + if ($req['name'] == 'luogu') { + $form->appendHTML(HTML::tag_begin('div', ['class' => 'row'])); + $form->appendHTML(HTML::tag( + 'div', + [ + 'class' => 'col-sm-2', + ], + HTML::tag('label', [ + 'class' => 'form-col-label', + ], '_uid') + )); + $form->addInput("{$form_name}_{$req['name']}_uid", [ + 'div_class' => 'col-sm-4', + 'validator_php' => function ($x) { + if (!validateUInt($x)) { + return 'ID 不合法'; + } + + return ''; + }, + ]); + $form->appendHTML(HTML::tag( + 'div', + [ + 'class' => 'col-sm-6', + ], + HTML::tag('div', [ + 'class' => 'form-text', + ], '请在 Cookie 中找到 _uid,然后填入框中。') + )); + $form->appendHTML(HTML::tag_end('div')); + + $form->appendHTML(HTML::tag_begin('div', ['class' => 'row mt-3'])); + $form->appendHTML(HTML::tag( + 'div', + [ + 'class' => 'col-sm-2', + ], + HTML::tag('label', [ + 'class' => 'form-col-label', + ], '__clientid') + )); + $form->addInput("{$form_name}_{$req['name']}_clientid", [ + 'div_class' => 'col-sm-4', + 'validator_php' => function ($x) { + if (!validateString($x)) { + return 'ID 不合法'; + } + + return ''; + }, + ]); + $form->appendHTML(HTML::tag( + 'div', + [ + 'class' => 'col-sm-6', + ], + HTML::tag('div', [ + 'class' => 'form-text', + ], '请在 Cookie 中找到 __clientid,然后填入框中。') + )); + $form->appendHTML(HTML::tag_end('div')); + + $form->appendHTML(HTML::tag_begin('div', ['class' => 'row mt-3'])); + $form->appendHTML(HTML::tag( + 'div', + [ + 'class' => 'col-sm-2', + ], + HTML::tag('label', [ + 'class' => 'form-col-label', + ], '提交记录 ID') + )); + $form->addInput("{$form_name}_{$req['name']}_submission_id", [ + 'div_class' => 'col-sm-4', + 'validator_php' => function ($x) { + if (!validateUInt($x)) { + return 'ID 不合法'; + } + + return ''; + }, + ]); + $form->appendHTML(HTML::tag( + 'div', + [ + 'class' => 'col-sm-6', + ], + HTML::tag('div', [ + 'class' => 'form-text', + ], '请填入提交记录 ID(不带开头的字母 R)。') + )); + $form->appendHTML(HTML::tag_end('div')); + } } } @@ -74,35 +170,48 @@ function newSubmissionForm($form_name, $requirement, $zip_file_name_gen, $handle $content = []; $content['file_name'] = $zip_file_name; $content['config'] = []; + foreach ($requirement as $req) { if ($req['type'] == "source code") { $content['config'][] = ["{$req['name']}_language", $_POST["{$form_name}_{$req['name']}_language"]]; + } else if ($req['type'] == "remote submission") { + $content['no_rejudge'] = true; + + if ($req['name'] == "luogu") { + $content['config'][] = ["{$req['name']}_uid", $_POST["{$form_name}_{$req['name']}_uid"]]; + $content['config'][] = ["{$req['name']}_clientid", $_POST["{$form_name}_{$req['name']}_clientid"]]; + $content['config'][] = ["{$req['name']}_submission_id", $_POST["{$form_name}_{$req['name']}_submission_id"]]; + } } } foreach ($requirement as $req) { - if ($_POST["{$form_name}_{$req['name']}_upload_type"] == 'editor') { - $zip_file->addFromString($req['file_name'], $_POST["{$form_name}_{$req['name']}_editor"]); + if ($req['type'] == "remote submission") { + $zip_file->addFromString($req['name'], ''); } else { - $tmp_name = UOJForm::uploadedFileTmpName("{$form_name}_{$req['name']}_file"); - if ($tmp_name == null) { - $zip_file->addFromString($req['file_name'], ''); + if ($_POST["{$form_name}_{$req['name']}_upload_type"] == 'editor') { + $zip_file->addFromString($req['file_name'], $_POST["{$form_name}_{$req['name']}_editor"]); } else { - $zip_file->addFile($tmp_name, $req['file_name']); + $tmp_name = UOJForm::uploadedFileTmpName("{$form_name}_{$req['name']}_file"); + if ($tmp_name == null) { + $zip_file->addFromString($req['file_name'], ''); + } else { + $zip_file->addFile($tmp_name, $req['file_name']); + } } - } - $stat = $zip_file->statName($req['file_name']); + $stat = $zip_file->statName($req['file_name']); - if ($req['type'] == 'source code') { - $max_size = isset($req['size']) ? (int)$req['size'] : 100; - if ($stat['size'] > $max_size * 1024) { - $zip_file->close(); - unlink(UOJContext::storagePath() . $zip_file_name); - UOJResponse::message("源代码长度不能超过 {$max_size} kB。"); + if ($req['type'] == 'source code') { + $max_size = isset($req['size']) ? (int)$req['size'] : 100; + if ($stat['size'] > $max_size * 1024) { + $zip_file->close(); + unlink(UOJContext::storagePath() . $zip_file_name); + UOJResponse::message("源代码长度不能超过 {$max_size} kB。"); + } } - } - $tot_size += $stat['size']; + $tot_size += $stat['size']; + } } $zip_file->close(); diff --git a/web/app/libs/uoj-html-lib.php b/web/app/libs/uoj-html-lib.php index 0fa2ddb..d6b5157 100644 --- a/web/app/libs/uoj-html-lib.php +++ b/web/app/libs/uoj-html-lib.php @@ -403,7 +403,7 @@ function echoSubmissionContent($submission, $requirement) { echo ''; echo ''; echo ''; - } elseif ($req['type'] == "text") { + } else if ($req['type'] == "text") { $file_content = $zip_file->getFromName("{$req['file_name']}", 504); $file_content = strOmit($file_content, 500); $file_content = uojTextEncode($file_content, array('allow_CR' => true, 'html_escape' => true)); @@ -417,6 +417,22 @@ function echoSubmissionContent($submission, $requirement) { echo ''; echo ''; echo ''; + } else if ($req['type'] == "remote submission") { + $remote_provider = UOJRemoteProblem::$providers[$req['name']]; + $content = ''; + + if ($req['name'] == 'luogu') { + $content .= '

远端评测 ID:' . + HTML::tag( + 'a', + [ + 'href' => $remote_provider['url'] . '/record/' . $config['luogu_submission_id'] + ], + 'R' . $config['luogu_submission_id'] + ) . '

'; + } + + HTML::echoPanel('', '远端评测记录', $content); } } diff --git a/web/app/models/UOJForm.php b/web/app/models/UOJForm.php index 55882e4..ad3a541 100644 --- a/web/app/models/UOJForm.php +++ b/web/app/models/UOJForm.php @@ -665,6 +665,7 @@ class UOJForm { EOD; } else { echo <<form_name}").addClass('disabled'); return ok; EOD; } diff --git a/web/app/models/UOJProblem.php b/web/app/models/UOJProblem.php index ee0da7d..2db8eb6 100644 --- a/web/app/models/UOJProblem.php +++ b/web/app/models/UOJProblem.php @@ -562,6 +562,8 @@ class UOJProblem { foreach ($submission_requirement as $req) { if ($req['type'] == 'source code') { return false; + } else if ($req['type'] == 'remote submission') { + return false; } } diff --git a/web/app/models/UOJRemoteProblem.php b/web/app/models/UOJRemoteProblem.php index 11e5fe8..cf9c74a 100644 --- a/web/app/models/UOJRemoteProblem.php +++ b/web/app/models/UOJRemoteProblem.php @@ -40,6 +40,12 @@ class UOJRemoteProblem { 'url' => 'https://loj.ac', 'languages' => ['C', 'C++03', 'C++11', 'C++', 'C++17', 'C++20', 'Python3', 'Python2.7', 'Java17', 'Pascal'], ], + 'luogu' => [ + 'name' => '洛谷', + 'short_name' => '洛谷', + 'url' => 'https://www.luogu.com.cn', + 'languages' => [], + ], ]; static function curl_get($url) { @@ -394,6 +400,28 @@ class UOJRemoteProblem { ]; } + public static function getSubmissionRequirements($oj) { + $remote_provider = UOJRemoteProblem::$providers[$oj]; + + if ($oj == 'luogu') { + return [ + [ + "name" => "luogu", + "type" => "remote submission", + ] + ]; + } + + return [ + [ + "name" => "answer", + "type" => "source code", + "file_name" => "answer.code", + "languages" => $remote_provider['languages'], + ] + ]; + } + public static function getProblemRemoteUrl($oj, $id) { if ($oj === 'codeforces') { return static::getCodeforcesProblemUrl($id); diff --git a/web/app/models/UOJSubmission.php b/web/app/models/UOJSubmission.php index 8f5e341..ad9f20f 100644 --- a/web/app/models/UOJSubmission.php +++ b/web/app/models/UOJSubmission.php @@ -89,7 +89,8 @@ class UOJSubmission { $content['config'][] = ['problem_id', UOJProblem::info('id')]; if (UOJProblem::info('type') == 'remote') { - $content['config'][] = ['remote_online_judge', UOJProblem::cur()->getExtraConfig('remote_online_judge')]; + $remote_online_judge = UOJProblem::cur()->getExtraConfig('remote_online_judge'); + $content['config'][] = ['remote_online_judge', $remote_online_judge]; $content['config'][] = ['remote_problem_id', UOJProblem::cur()->getExtraConfig('remote_problem_id')]; } @@ -418,6 +419,10 @@ class UOJSubmission { } public function userCanRejudge(array $user = null) { + if ($this->getContent('no_rejudge')) { + return false; + } + if (isSuperUser($user)) { return true; } diff --git a/web/app/models/UOJSubmissionLikeTrait.php b/web/app/models/UOJSubmissionLikeTrait.php index 5166ff6..c4126eb 100644 --- a/web/app/models/UOJSubmissionLikeTrait.php +++ b/web/app/models/UOJSubmissionLikeTrait.php @@ -210,6 +210,24 @@ trait UOJSubmissionLikeTrait { EOD; + } else if ($req['type'] == "remote submission") { + $remote_provider = UOJRemoteProblem::$providers[$req['name']]; + $content = ''; + + if ($req['name'] == 'luogu') { + $content .= HTML::tag('div', [], [ + '远端评测 ID:', + HTML::tag( + 'a', + [ + 'href' => "{$remote_provider['url']}/record/{$config['luogu_submission_id']}" + ], + 'R' . $config['luogu_submission_id'] + ), + ]); + } + + HTML::echoPanel('mb-3', '远端评测记录', $content); } } $zip_file->close();