From 7cdb39267a71f4a4e66e627aa10b8b8d239e6442 Mon Sep 17 00:00:00 2001 From: Baoshuo Date: Thu, 2 Feb 2023 20:07:35 +0800 Subject: [PATCH 1/7] 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(); From dcbe7691a2be5f223e0a44a14ce91c02cf4e17b1 Mon Sep 17 00:00:00 2001 From: Baoshuo Date: Thu, 2 Feb 2023 21:53:36 +0800 Subject: [PATCH 2/7] feat(problem/remote): add luogu --- web/app/controllers/new_remote_problem.php | 10 ++++ web/app/libs/uoj-form-lib.php | 1 + web/app/libs/uoj-validate-lib.php | 4 ++ web/app/models/UOJRemoteProblem.php | 61 ++++++++++++++++++++++ 4 files changed, 76 insertions(+) diff --git a/web/app/controllers/new_remote_problem.php b/web/app/controllers/new_remote_problem.php index e7af67d..cd4f4b3 100644 --- a/web/app/controllers/new_remote_problem.php +++ b/web/app/controllers/new_remote_problem.php @@ -51,6 +51,16 @@ $new_remote_problem_form->addInput('remote_problem_id', [ $vdata['remote_problem_id'] = $id; + return ''; + } else if ($remote_oj === 'luogu') { + $id = trim(strtoupper($id)); + + if (!validateLuoguProblemId($id)) { + return '不合法的题目 ID'; + } + + $vdata['remote_problem_id'] = $id; + return ''; } diff --git a/web/app/libs/uoj-form-lib.php b/web/app/libs/uoj-form-lib.php index 41a3efa..f2c4355 100644 --- a/web/app/libs/uoj-form-lib.php +++ b/web/app/libs/uoj-form-lib.php @@ -176,6 +176,7 @@ function newSubmissionForm($form_name, $requirement, $zip_file_name_gen, $handle $content['config'][] = ["{$req['name']}_language", $_POST["{$form_name}_{$req['name']}_language"]]; } else if ($req['type'] == "remote submission") { $content['no_rejudge'] = true; + $content['manual_submit'] = true; if ($req['name'] == "luogu") { $content['config'][] = ["{$req['name']}_uid", $_POST["{$form_name}_{$req['name']}_uid"]]; diff --git a/web/app/libs/uoj-validate-lib.php b/web/app/libs/uoj-validate-lib.php index 426cc92..82b2d95 100644 --- a/web/app/libs/uoj-validate-lib.php +++ b/web/app/libs/uoj-validate-lib.php @@ -79,3 +79,7 @@ function is_short_string($str) { function validateCodeforcesProblemId($str) { return preg_match('/(|GYM)[1-9][0-9]{0,5}[A-Z][1-9]?/', $str) !== true; } + +function validateLuoguProblemId($str) { + return preg_match('/P[1-9][0-9]{4,5}/', $str) !== true; +} diff --git a/web/app/models/UOJRemoteProblem.php b/web/app/models/UOJRemoteProblem.php index cf9c74a..caeb50a 100644 --- a/web/app/models/UOJRemoteProblem.php +++ b/web/app/models/UOJRemoteProblem.php @@ -96,6 +96,10 @@ class UOJRemoteProblem { return static::$providers['loj']['url'] . '/p/' . $id; } + static function getLuoguProblemUrl($id) { + return static::$providers['luogu']['url'] . '/problem/' . $id; + } + static function getCodeforcesProblemBasicInfoFromHtml($id, $html) { $remote_provider = static::$providers['codeforces']; @@ -400,6 +404,59 @@ class UOJRemoteProblem { ]; } + static function getLuoguProblemBasicInfo($id) { + $remote_provider = static::$providers['luogu']; + $res = static::curl_get(static::getLuoguProblemUrl($id) . '?_contentOnly=1'); + + if (!$res) return null; + + // Convert stdClass to array + $res = json_decode(json_encode($res['response']), true); + + if (!isset($res['code']) || $res['code'] != 200) return null; + + $problem = $res['currentData']['problem']; + $statement = ''; + + if ($problem['background']) { + $statement .= "\n### 题目背景\n\n"; + $statement .= $problem['background'] . "\n"; + } + + $statement .= "\n### 题目描述\n\n"; + $statement .= $problem['description'] . "\n"; + + $statement .= "\n### 输入格式\n\n"; + $statement .= $problem['inputFormat'] . "\n"; + + $statement .= "\n### 输出格式\n\n"; + $statement .= $problem['outputFormat'] . "\n"; + + $statement .= "\n### 输入输出样例\n\n"; + + foreach ($problem['samples'] as $id => $sample) { + $display_sample_id = $id + 1; + + $statement .= "\n#### 样例输入 #{$display_sample_id}\n\n"; + $statement .= "\n```text\n{$sample[0]}\n```\n\n"; + + $statement .= "\n#### 样例输出 #{$display_sample_id}\n\n"; + $statement .= "\n```text\n{$sample[1]}\n```\n\n"; + } + + $statement .= "\n### 说明/提示\n\n"; + $statement .= $problem['hint'] . "\n"; + + return [ + 'type' => 'html', + 'title' => "【{$remote_provider['short_name']}{$problem['pid']}】{$problem['title']}", + 'time_limit' => (float)max($problem['limits']['time']) / 1000.0, + 'memory_limit' => (float)max($problem['limits']['memory']) / 1024.0, + 'difficulty' => -1, + 'statement' => HTML::parsedown()->text($statement), + ]; + } + public static function getSubmissionRequirements($oj) { $remote_provider = UOJRemoteProblem::$providers[$oj]; @@ -431,6 +488,8 @@ class UOJRemoteProblem { return static::getUojProblemUrl($id); } else if ($oj === 'loj') { return static::getLojProblemUrl($id); + } else if ($oj === 'luogu') { + return static::getLuoguProblemUrl($id); } return null; @@ -446,6 +505,8 @@ class UOJRemoteProblem { return static::getUojProblemBasicInfo($id); } else if ($oj === 'loj') { return static::getLojProblemBasicInfo($id); + } else if ($oj === 'luogu') { + return static::getLuoguProblemBasicInfo($id); } return null; From 2ab8d076833c3cbb5b64b2195e6da8784891e9ad Mon Sep 17 00:00:00 2001 From: Baoshuo Date: Fri, 3 Feb 2023 09:06:47 +0800 Subject: [PATCH 3/7] refactor(problem/remote): custom account field --- web/app/controllers/problem.php | 31 ++++- web/app/libs/uoj-form-lib.php | 144 +++------------------- web/app/libs/uoj-html-lib.php | 16 --- web/app/models/UOJProblem.php | 2 - web/app/models/UOJRemoteProblem.php | 16 +-- web/app/models/UOJSubmission.php | 3 +- web/app/models/UOJSubmissionLikeTrait.php | 18 --- web/js/uoj.js | 102 +++++++++++++++ 8 files changed, 157 insertions(+), 175 deletions(-) diff --git a/web/app/controllers/problem.php b/web/app/controllers/problem.php index 8e289e3..29d2e00 100644 --- a/web/app/controllers/problem.php +++ b/web/app/controllers/problem.php @@ -104,6 +104,17 @@ $custom_test_enabled = $custom_test_requirement && $pre_submit_check_ret === tru function handleUpload($zip_file_name, $content, $tot_size) { global $is_participating; + + $remote_oj = UOJProblem::cur()->getExtraConfig('remote_online_judge'); + $remote_provider = UOJRemoteProblem::$providers[$remote_oj]; + + if (UOJProblem::info('type') == 'remote') { + $submit_type = in_array($_POST['answer_remote_submit_type'], $remote_provider['submit_type']) ? $_POST['answer_remote_submit_type'] : $remote_provider['submit_type'][0]; + $content['no_rejudge'] = true; + $content['config'][] = ['remote_submit_type', $submit_type]; + $content['config'][] = ['remote_account_data', $_POST['answer_remote_account_data']]; + } + UOJSubmission::onUpload($zip_file_name, $content, $tot_size, $is_participating); } function handleCustomTestUpload($zip_file_name, $content, $tot_size) { @@ -182,7 +193,7 @@ if ($pre_submit_check_ret === true && !$no_more_submission) { if (UOJProblem::cur()->userCanUploadSubmissionViaZip(Auth::user())) { $zip_answer_form = newZipSubmissionForm( - 'zip-answer', + 'zip_answer', $submission_requirement, 'FS::randomAvailableSubmissionFileName', 'handleUpload' @@ -198,6 +209,24 @@ if ($pre_submit_check_ret === true && !$no_more_submission) { 'FS::randomAvailableSubmissionFileName', 'handleUpload' ); + + if (UOJProblem::info('type') == 'remote') { + $remote_oj = UOJProblem::cur()->getExtraConfig('remote_online_judge'); + $remote_pid = UOJProblem::cur()->getExtraConfig('remote_problem_id'); + $remote_url = UOJRemoteProblem::getProblemRemoteUrl($remote_oj, $remote_pid); + $submit_type = json_encode(UOJRemoteProblem::$providers[$remote_oj]['submit_type']); + + $answer_form->addNoVal('answer_remote_submit_type', ''); + $answer_form->addNoVal('answer_remote_account_data', ''); + $answer_form->appendHTML(<<Remote Judge 配置 +
+ + EOD); + } + $answer_form->extra_validator = $submission_extra_validator; $answer_form->succ_href = $is_participating ? '/contest/' . UOJContest::info('id') . '/submissions' : '/submissions'; $answer_form->runAtServer(); diff --git a/web/app/libs/uoj-form-lib.php b/web/app/libs/uoj-form-lib.php index f2c4355..ddde655 100644 --- a/web/app/libs/uoj-form-lib.php +++ b/web/app/libs/uoj-form-lib.php @@ -58,101 +58,6 @@ 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')); - } } } @@ -174,45 +79,32 @@ function newSubmissionForm($form_name, $requirement, $zip_file_name_gen, $handle 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; - $content['manual_submit'] = 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 ($req['type'] == "remote submission") { - $zip_file->addFromString($req['name'], ''); + if ($_POST["{$form_name}_{$req['name']}_upload_type"] == 'editor') { + $zip_file->addFromString($req['file_name'], $_POST["{$form_name}_{$req['name']}_editor"]); } else { - if ($_POST["{$form_name}_{$req['name']}_upload_type"] == 'editor') { - $zip_file->addFromString($req['file_name'], $_POST["{$form_name}_{$req['name']}_editor"]); + $tmp_name = UOJForm::uploadedFileTmpName("{$form_name}_{$req['name']}_file"); + if ($tmp_name == null) { + $zip_file->addFromString($req['file_name'], ''); } else { - $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']); - } + $zip_file->addFile($tmp_name, $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。"); - } - } - - $tot_size += $stat['size']; } + $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。"); + } + } + + $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 d6b5157..c874368 100644 --- a/web/app/libs/uoj-html-lib.php +++ b/web/app/libs/uoj-html-lib.php @@ -417,22 +417,6 @@ 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/UOJProblem.php b/web/app/models/UOJProblem.php index 2db8eb6..ee0da7d 100644 --- a/web/app/models/UOJProblem.php +++ b/web/app/models/UOJProblem.php @@ -562,8 +562,6 @@ 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 caeb50a..636984a 100644 --- a/web/app/models/UOJRemoteProblem.php +++ b/web/app/models/UOJRemoteProblem.php @@ -14,6 +14,7 @@ class UOJRemoteProblem { 'ограничение по времени на тест', ], 'languages' => ['C', 'C++', 'C++17', 'C++20', 'Java17', 'Pascal', 'Python2', 'Python3'], + 'submit_type' => ['bot'], ], 'atcoder' => [ 'name' => 'AtCoder', @@ -24,6 +25,7 @@ class UOJRemoteProblem { '指定されたタスクが見つかりません', ], 'languages' => ['C', 'C++', 'Java11', 'Python3', 'Pascal'], + 'submit_type' => ['bot'], ], 'uoj' => [ 'name' => 'UniversalOJ', @@ -33,18 +35,21 @@ class UOJRemoteProblem { '未找到该页面', ], 'languages' => ['C', 'C++03', 'C++11', 'C++', 'C++17', 'C++20', 'Python3', 'Python2.7', 'Java8', 'Java11', 'Java17', 'Pascal'], + 'submit_type' => ['bot'], ], 'loj' => [ 'name' => 'LibreOJ', 'short_name' => 'LOJ', 'url' => 'https://loj.ac', 'languages' => ['C', 'C++03', 'C++11', 'C++', 'C++17', 'C++20', 'Python3', 'Python2.7', 'Java17', 'Pascal'], + 'submit_type' => ['bot'], ], 'luogu' => [ 'name' => '洛谷', 'short_name' => '洛谷', 'url' => 'https://www.luogu.com.cn', - 'languages' => [], + 'languages' => ['C', 'C++98', 'C++11', 'C++', 'C++17', 'C++20', 'Python3', 'Java8', 'Pascal'], + 'submit_type' => ['my'], ], ]; @@ -460,15 +465,6 @@ class UOJRemoteProblem { public static function getSubmissionRequirements($oj) { $remote_provider = UOJRemoteProblem::$providers[$oj]; - if ($oj == 'luogu') { - return [ - [ - "name" => "luogu", - "type" => "remote submission", - ] - ]; - } - return [ [ "name" => "answer", diff --git a/web/app/models/UOJSubmission.php b/web/app/models/UOJSubmission.php index ad9f20f..6ae9327 100644 --- a/web/app/models/UOJSubmission.php +++ b/web/app/models/UOJSubmission.php @@ -89,8 +89,7 @@ class UOJSubmission { $content['config'][] = ['problem_id', UOJProblem::info('id')]; if (UOJProblem::info('type') == 'remote') { - $remote_online_judge = UOJProblem::cur()->getExtraConfig('remote_online_judge'); - $content['config'][] = ['remote_online_judge', $remote_online_judge]; + $content['config'][] = ['remote_online_judge', UOJProblem::cur()->getExtraConfig('remote_online_judge')]; $content['config'][] = ['remote_problem_id', UOJProblem::cur()->getExtraConfig('remote_problem_id')]; } diff --git a/web/app/models/UOJSubmissionLikeTrait.php b/web/app/models/UOJSubmissionLikeTrait.php index c4126eb..5166ff6 100644 --- a/web/app/models/UOJSubmissionLikeTrait.php +++ b/web/app/models/UOJSubmissionLikeTrait.php @@ -210,24 +210,6 @@ 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(); diff --git a/web/js/uoj.js b/web/js/uoj.js index 41bf66a..652b357 100644 --- a/web/js/uoj.js +++ b/web/js/uoj.js @@ -947,6 +947,108 @@ $.fn.text_file_form_group = function(name, text) { }); } +// remote judge submit type group +$.fn.remote_submit_type_group = function(oj, pid, url, submit_type) { + return this.each(function() { + var input_submit_type_bot_id = 'input-submit_type_bot'; + var input_submit_type_my_id = 'input-submit_type_my'; + var div_submit_type_bot_id = 'div-submit_type_bot'; + var div_submit_type_my_id = 'div-submit_type_my'; + + var input_submit_type_bot = $(''); + var input_submit_type_my = $(''); + var input_my_account_data = $(''); + + var div_submit_type_bot = $('
') + .append('
将使用公用账号提交本题。
'); + var div_submit_type_my = $('
') + .append('
将使用您的账号提交本题。
'); + + input_submit_type_bot.click(function() { + div_submit_type_my.hide('fast'); + div_submit_type_bot.show('fast'); + }); + input_submit_type_my.click(function() { + div_submit_type_bot.hide('fast'); + div_submit_type_my.show('fast'); + }); + + if (submit_type[0] == 'bot') { + div_submit_type_my.hide(); + input_submit_type_bot[0].checked = true; + } else if (submit_type[0] == 'my') { + div_submit_type_bot.hide(); + input_submit_type_my[0].checked = true; + } + + if (submit_type.indexOf('bot') == -1) { + input_submit_type_bot.attr('disabled', 'disabled'); + } + if (submit_type.indexOf('my') == -1) { + input_submit_type_my.attr('disabled', 'disabled'); + } + + if (oj == 'luogu') { + var luogu_account_data = {"_uid": "", "__clientid": ""}; + var input_luogu_uid = $(''); + var input_luogu_clientid = $(''); + + if ('localStorage' in window) { + try { + var luogu_account_data_str = localStorage.getItem('uoj_remote_judge_luogu_account_data'); + if (luogu_account_data_str) { + luogu_account_data = JSON.parse(luogu_account_data_str); + } + } catch (e) {} + + var save_luogu_account_data = function() { + localStorage.setItem('uoj_remote_judge_luogu_account_data', JSON.stringify(luogu_account_data)); + } + } else { + var save_luogu_account_data = function() {}; + } + + input_luogu_uid.change(function() { + luogu_account_data._uid = $(this).val(); + input_my_account_data.val(JSON.stringify(luogu_account_data)); + save_luogu_account_data(); + }); + + input_luogu_clientid.change(function() { + luogu_account_data.__clientid = $(this).val(); + input_my_account_data.val(JSON.stringify(luogu_account_data)); + save_luogu_account_data(); + }); + + input_my_account_data.val(JSON.stringify(luogu_account_data)); + + div_submit_type_my.append( + $('
') + .append($('
').append('')) + .append($('
').append(input_luogu_uid)) + .append($('
').append($('
').append('请填入 Cookie 中的 _uid。'))) + ).append( + $('
') + .append($('
').append('')) + .append($('
').append(input_luogu_clientid)) + .append($('
').append($('
').append('请填入 Cookie 中的 __clientid。'))) + ).append(input_my_account_data); + } + + $(this).append( + $('
').append( + $('
') + .append(input_submit_type_bot) + .append($('