diff --git a/web/app/controllers/new_remote_problem.php b/web/app/controllers/new_remote_problem.php index d76aecd..7fb3e9a 100644 --- a/web/app/controllers/new_remote_problem.php +++ b/web/app/controllers/new_remote_problem.php @@ -107,6 +107,7 @@ $new_remote_problem_form->runAtServer();

目前支持导入以下题库的题目作为远端评测题:

  • 在导入题目前请先搜索题库中是否已经存在相应题目,避免重复添加。
  • diff --git a/web/app/libs/uoj-validate-lib.php b/web/app/libs/uoj-validate-lib.php index adea031..426cc92 100644 --- a/web/app/libs/uoj-validate-lib.php +++ b/web/app/libs/uoj-validate-lib.php @@ -77,5 +77,5 @@ function is_short_string($str) { } function validateCodeforcesProblemId($str) { - return preg_match('/[1-9][0-9]{0,5}[A-Z][1-9]?/', $str) !== true; + return preg_match('/(|GYM)[1-9][0-9]{0,5}[A-Z][1-9]?/', $str) !== true; } diff --git a/web/app/models/UOJRemoteProblem.php b/web/app/models/UOJRemoteProblem.php index 6074faa..e152893 100644 --- a/web/app/models/UOJRemoteProblem.php +++ b/web/app/models/UOJRemoteProblem.php @@ -16,28 +16,16 @@ class UOJRemoteProblem { ]; static function getCodeforcesProblemUrl($id) { + if (str_starts_with($id, 'GYM')) { + return static::$providers['codeforces']['url'] . '/gym/' . preg_replace_callback('/GYM([1-9][0-9]{0,5})([A-Z][1-9]?)/', fn ($matches) => $matches[1] . '/problem/' . $matches[2], $id); + } + return static::$providers['codeforces']['url'] . '/problemset/problem/' . preg_replace_callback('/([1-9][0-9]{0,5})([A-Z][1-9]?)/', fn ($matches) => $matches[1] . '/' . $matches[2], $id); } - // 传入 ID 需确保有效 - static function getCodeforcesProblemBasicInfo($id) { - $curl = new Curl(); - $curl->setUserAgent('Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.0.0 Safari/537.36 S2OJ/3.1.0'); - + static function getCodeforcesProblemBasicInfoFromHtml($id, $html) { $remote_provider = static::$providers['codeforces']; - $html = retry_loop(function () use ($curl, $id) { - $curl->get(static::getCodeforcesProblemUrl($id)); - - if ($curl->error) { - return false; - } - - return $curl->response; - }); - - if (!$html) return null; - $html = preg_replace('/\$\$\$/', '$', $html); $dom = new \IvoPetkov\HTML5DOMDocument(); $dom->loadHTML($html); @@ -51,8 +39,9 @@ class UOJRemoteProblem { } $statement_dom = $dom->querySelector('.problem-statement'); + $title_prefix = str_starts_with($id, 'GYM') ? '' : 'CF'; $title = explode('. ', trim($statement_dom->querySelector('.title')->innerHTML))[1]; - $title = "【{$remote_provider['short_name']}{$id}】{$title}"; + $title = "【{$title_prefix}{$id}】{$title}"; $time_limit = intval(substr($statement_dom->querySelector('.time-limit')->innerHTML, 53)); $memory_limit = intval(substr($statement_dom->querySelector('.memory-limit')->innerHTML, 55)); $difficulty = -1; @@ -120,6 +109,7 @@ class UOJRemoteProblem { } return [ + 'type' => 'html', 'title' => $title, 'time_limit' => $time_limit, 'memory_limit' => $memory_limit, @@ -128,6 +118,52 @@ class UOJRemoteProblem { ]; } + // 传入 ID 需确保有效 + static function getCodeforcesProblemBasicInfo($id) { + $curl = new Curl(); + $curl->setUserAgent('Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.0.0 Safari/537.36 S2OJ/3.1.0'); + + $res = retry_loop(function () use (&$curl, $id) { + $curl->get(static::getCodeforcesProblemUrl($id)); + + if ($curl->error) { + return false; + } + + return [ + 'content-type' => $curl->response_headers['Content-Type'], + 'response' => $curl->response, + ]; + }); + + if (!$res) return null; + + if (str_starts_with($res['content-type'], 'text/html')) { + return static::getCodeforcesProblemBasicInfoFromHtml($id, $res['response']); + } else if (str_starts_with($res['content-type'], 'application/pdf')) { + $title_prefix = str_starts_with($id, 'GYM') ? '' : 'CF'; + $title = "【{$title_prefix}{$id}】{$title_prefix}{$id}"; + + return [ + 'type' => 'pdf', + 'title' => $title, + 'time_limit' => null, + 'memory_limit' => null, + 'difficulty' => -1, + 'statement' => HTML::tag('h3', [], '提示') . + HTML::tag( + 'p', + [], + '本题题面为 PDF 题面,请' . + HTML::tag('a', ['href' => static::getCodeforcesProblemUrl($id), 'target' => '_blank'], '点此') . + '以查看题面。' + ), + ]; + } else { + return null; + } + } + public static function getProblemRemoteUrl($oj, $id) { if ($oj === 'codeforces') { return static::getCodeforcesProblemUrl($id);