mirror of
https://github.com/renbaoshuo/UOJ-Luogu-RemoteJudge.git
synced 2024-11-23 19:58:42 +00:00
Compare commits
9 Commits
c7c006bd3d
...
2ae6494230
Author | SHA1 | Date | |
---|---|---|---|
2ae6494230 | |||
12b2e11e1f | |||
00c6e7bd0d | |||
8fc2642078 | |||
80b578b0fc | |||
b60d06a98d | |||
01dbc95da0 | |||
b67f2e505e | |||
0cd9b4c5da |
16
FAQ.md
16
FAQ.md
@ -1,3 +1,17 @@
|
|||||||
# 常见问题
|
# 常见问题
|
||||||
|
|
||||||
_TODO_
|
### 评测时显示 `Unauthorized`
|
||||||
|
|
||||||
|
请检查评测机处配置的洛谷开放平台用户信息是否正确。
|
||||||
|
|
||||||
|
### 评测时显示 `Payment Required`
|
||||||
|
|
||||||
|
您的评测额度剩余量不足,请充值后再重新评测。
|
||||||
|
|
||||||
|
### 评测时显示 `Internal Server Error`
|
||||||
|
|
||||||
|
请联系洛谷管理员。
|
||||||
|
|
||||||
|
### 评测时显示 `Bad Gateway`、`Service Unavailable` 或 `Gateway Timeout`
|
||||||
|
|
||||||
|
可能是网络波动造成的。如果长时间出现此情况,请联系洛谷管理员。
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
# 安装
|
# 安装
|
||||||
|
|
||||||
|
**我们强烈建议您在安装前对网站、数据库进行备份,以免修改过程中出错造成数据丢失。**
|
||||||
|
|
||||||
## 前期准备
|
## 前期准备
|
||||||
|
|
||||||
请先在服务器上安装以下软件/模块:
|
请先在服务器上安装以下软件/模块:
|
||||||
@ -15,4 +17,95 @@ sed -i -e '912a\extension=v8js.so\nextension=yaml.so' /etc/php/7.4/cli/php.ini
|
|||||||
|
|
||||||
## 修改源码
|
## 修改源码
|
||||||
|
|
||||||
_TODO_
|
### 修改数据库
|
||||||
|
|
||||||
|
先进入 MySQL CLI(将 `-u` 后的 `root` 替换为你的 MySQL 用户名,将 `-p` 后的 `root` 替换为你的 MySQL 密码):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
mysql -uroot -proot app_uoj233
|
||||||
|
```
|
||||||
|
|
||||||
|
然后运行以下 SQL 语句以修改数据库中 `problems` 表结构:
|
||||||
|
|
||||||
|
```sql
|
||||||
|
ALTER TABLE `problems` ADD `type` varchar(20) NOT NULL DEFAULT 'local';
|
||||||
|
ALTER TABLE `problems` ADD KEY `type` (`type`);
|
||||||
|
```
|
||||||
|
|
||||||
|
然后输入 `exit;` 退出 MySQL CLI。
|
||||||
|
|
||||||
|
### 应用补丁
|
||||||
|
|
||||||
|
如果您没有对 UOJ 的源码进行过修改,可以尝试直接使用 `patch -p1` 命令应用提供的补丁。否则,请对照 `<filename>.patch` 逐一修改本仓库的 `web` 目录中给出的每个文件。
|
||||||
|
|
||||||
|
如果某个文件并未给出补丁,则该文件为新增文件,您需要将其复制到 UOJ 的对应目录中。
|
||||||
|
|
||||||
|
## 配置桥接评测机
|
||||||
|
|
||||||
|
### 增加评测机
|
||||||
|
|
||||||
|
先进入 MySQL CLI(将 `-u` 后的 `root` 替换为你的 MySQL 用户名,将 `-p` 后的 `root` 替换为你的 MySQL 密码):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
mysql -uroot -proot app_uoj233
|
||||||
|
```
|
||||||
|
|
||||||
|
然后执行下面的 SQL 语句以添加评测机(请将密码修改为一个随机值,以防被攻击;切勿改变评测机名称):
|
||||||
|
|
||||||
|
```sql
|
||||||
|
insert into judger_info (judger_name, password) values ('luogu_remote_judger', '_judger_password_');
|
||||||
|
```
|
||||||
|
|
||||||
|
然后输入 `exit;` 退出 MySQL CLI。
|
||||||
|
|
||||||
|
接下来的两种运行方式任选其一即可。
|
||||||
|
|
||||||
|
### 直接运行
|
||||||
|
|
||||||
|
切换到 `luogu_remote_judger` 目录,运行以下命令:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm ci
|
||||||
|
```
|
||||||
|
|
||||||
|
之后使用以下命令启动桥接评测机(将 `_judger_password_` 修改为上方配置的密码):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
UOJ_HOST="127.0.0.1" UOJ_JUDGER_PASSWORD="_judger_password_" LUOGU_API_USERNAME="洛谷开放平台用户 ID" LUOGU_API_PASSWORD="洛谷开放平台用户密码" npm run start
|
||||||
|
```
|
||||||
|
|
||||||
|
您需要通过自己的方式保证桥接评测机一直在运行。可以使用 `pm2` 等程序来进行进程守护。
|
||||||
|
|
||||||
|
### Docker
|
||||||
|
|
||||||
|
当然,您也可以使用 Docker 来启动桥接评测机,请使用以下命令构建镜像:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker build -t uoj-luogu-remote-judger .
|
||||||
|
```
|
||||||
|
|
||||||
|
然后使用以下命令来启动容器(将 `uoj-web` 修改为 Docker 宿主机 IP,`_judger_password_` 修改为上方配置的密码):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker run -d -e UOJ_HOST="uoj-web" -e UOJ_JUDGER_PASSWORD="_judger_password_" -e LUOGU_API_USERNAME="洛谷开放平台用户 ID" -e LUOGU_API_PASSWORD="洛谷开放平台用户密码" --name uoj-luogu-remote-judger --restart always uoj-luogu-remote-judger
|
||||||
|
```
|
||||||
|
|
||||||
|
## CLI 使用教程
|
||||||
|
|
||||||
|
### 导入题目
|
||||||
|
|
||||||
|
如果您需要批量导入题目,可以使用 CLI 来完成这项操作:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
php cli.php luogu:add-problem P1000 P1001
|
||||||
|
```
|
||||||
|
|
||||||
|
上面的命令将会导入洛谷题目 P1000 和 P1001。
|
||||||
|
|
||||||
|
如果您有下载好的离线数据库文件(可以在 [评测能力](https://docs.lgapi.cn/open/judge/) 页面下载),可以使用 `--file` 选项指定,以加快导入进度:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
php cli.php luogu:add-problem --file latest.ndjson P1000 P1001
|
||||||
|
```
|
||||||
|
|
||||||
|
注:请使用由洛谷提供的 `latest.ndjson.gz` 解压出的 `latest.ndjson` 文件,而非洛谷提供的压缩包本身。
|
||||||
|
21
LICENSE
Normal file
21
LICENSE
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2023 Baoshuo Ren
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
10
README.md
10
README.md
@ -1,8 +1,10 @@
|
|||||||
# 适用于 UniversalOJ 的洛谷 Remote Judge 模块
|
# 适用于 UniversalOJ 的洛谷 Remote Judge 模块
|
||||||
|
|
||||||
> 为 UniversalOJ 编写的洛谷 Remote Judge 模块,修改自 [S2OJ](https://github.com/renbaoshuo/S2OJ)。
|
> 为 UniversalOJ 编写的洛谷 Remote Judge 模块,修改自 [S2OJ](https://github.com/renbaoshuo/S2OJ) 的 Remote Judge 模块。
|
||||||
|
|
||||||
本模块依托于 [洛谷开放平台](https://docs.lgapi.cn) 的强大能力,为由 [UniversalOJ 社区版](https://github.com/UniversalOJ/UOJ-System) 驱动的在线评测系统提供 Remote Judge 支持。
|
## 介绍
|
||||||
|
|
||||||
|
本模块依托于 [洛谷开放平台](https://docs.lgapi.cn/open/) 的强大能力,为由 [UniversalOJ 社区版](https://github.com/UniversalOJ/UOJ-System) 驱动的在线评测系统提供 Remote Judge 支持。
|
||||||
|
|
||||||
如果您现有的评测系统是基于 [UniversalOJ 官网版](https://github.com/vfleaking/uoj) 搭建的,也可参考本仓库进行集成。
|
如果您现有的评测系统是基于 [UniversalOJ 官网版](https://github.com/vfleaking/uoj) 搭建的,也可参考本仓库进行集成。
|
||||||
|
|
||||||
@ -22,7 +24,9 @@
|
|||||||
|
|
||||||
## Author
|
## Author
|
||||||
|
|
||||||
**UOJ-Luogu-RemoteJudge** © [Baoshuo](https://github.com/renbaoshuo), Released under the [_(to be filled)_](./LICENSE) License.<br>
|
**UOJ-Luogu-RemoteJudge** © [Baoshuo](https://github.com/renbaoshuo), Released under the [MIT](./LICENSE) License.<br>
|
||||||
Authored and maintained by Baoshuo with help from [contributors](https://github.com/renbaoshuo/UOJ-Luogu-RemoteJudge/contributors).
|
Authored and maintained by Baoshuo with help from [contributors](https://github.com/renbaoshuo/UOJ-Luogu-RemoteJudge/contributors).
|
||||||
|
|
||||||
|
本模块在开发过程中得到了来自洛谷开发组和 HydroOJ 开发组的帮助,在此表示感谢。
|
||||||
|
|
||||||
> [Personal Website](https://baoshuo.ren) · [Blog](https://blog.baoshuo.ren) · GitHub [@renbaoshuo](https://github.com/renbaoshuo) · Twitter [@renbaoshuo](https://twitter.com/renbaoshuo)
|
> [Personal Website](https://baoshuo.ren) · [Blog](https://blog.baoshuo.ren) · GitHub [@renbaoshuo](https://github.com/renbaoshuo) · Twitter [@renbaoshuo](https://twitter.com/renbaoshuo)
|
||||||
|
@ -1,9 +1,3 @@
|
|||||||
ALTER TABLE
|
ALTER TABLE `problems` ADD `type` varchar(20) NOT NULL DEFAULT 'local';
|
||||||
`problems`
|
ALTER TABLE `problems` ADD KEY `type` (`type`);
|
||||||
ADD
|
insert into judger_info (judger_name, password) values ('luogu_remote_judger', '_judger_password_');
|
||||||
`type` varchar(20) NOT NULL DEFAULT 'local';
|
|
||||||
|
|
||||||
ALTER TABLE
|
|
||||||
`problems`
|
|
||||||
ADD
|
|
||||||
KEY `type` (`type`);
|
|
||||||
|
11
luogu_remote_judger/Dockerfile
Normal file
11
luogu_remote_judger/Dockerfile
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
FROM node:18.15.0
|
||||||
|
|
||||||
|
WORKDIR /opt/s2oj_remote_judger
|
||||||
|
COPY package*.json ./
|
||||||
|
|
||||||
|
RUN npm ci
|
||||||
|
|
||||||
|
COPY . .
|
||||||
|
|
||||||
|
ENV LANG=C.UTF-8 TZ="Asia/Shanghai"
|
||||||
|
CMD [ "node", "dist/entrypoint.js" ]
|
@ -31,7 +31,7 @@ const STATUS_MAP = [
|
|||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
'Judgment Failed',
|
'Judgement Failed',
|
||||||
'Accepted',
|
'Accepted',
|
||||||
0,
|
0,
|
||||||
'Wrong Answer', // WA
|
'Wrong Answer', // WA
|
||||||
@ -160,7 +160,7 @@ export default class Luogu {
|
|||||||
if (HTTP_ERROR_MAP[result.status]) {
|
if (HTTP_ERROR_MAP[result.status]) {
|
||||||
await end({
|
await end({
|
||||||
error: true,
|
error: true,
|
||||||
status: 'Judgment Failed',
|
status: 'Judgement Failed',
|
||||||
message: `[Luogu] ${HTTP_ERROR_MAP[result.status]}.`,
|
message: `[Luogu] ${HTTP_ERROR_MAP[result.status]}.`,
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -187,7 +187,7 @@ export default class Luogu {
|
|||||||
if (HTTP_ERROR_MAP[result.status]) {
|
if (HTTP_ERROR_MAP[result.status]) {
|
||||||
await end({
|
await end({
|
||||||
error: true,
|
error: true,
|
||||||
status: 'Judgment Failed',
|
status: 'Judgement Failed',
|
||||||
message: `[Luogu] ${HTTP_ERROR_MAP[result.status]}.`,
|
message: `[Luogu] ${HTTP_ERROR_MAP[result.status]}.`,
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -207,7 +207,7 @@ export default class Luogu {
|
|||||||
return await end({
|
return await end({
|
||||||
error: true,
|
error: true,
|
||||||
id,
|
id,
|
||||||
status: 'Judgment Failed',
|
status: 'Judgement Failed',
|
||||||
message: 'Failed to fetch submission details.',
|
message: 'Failed to fetch submission details.',
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -289,7 +289,7 @@ export default class Luogu {
|
|||||||
return await end({
|
return await end({
|
||||||
error: true,
|
error: true,
|
||||||
id,
|
id,
|
||||||
status: 'Judgment Failed',
|
status: 'Judgement Failed',
|
||||||
message: 'Failed to fetch submission details.',
|
message: 'Failed to fetch submission details.',
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -354,7 +354,7 @@ export default class Luogu {
|
|||||||
|
|
||||||
await end({
|
await end({
|
||||||
error: true,
|
error: true,
|
||||||
status: 'Judgment Failed',
|
status: 'Judgement Failed',
|
||||||
message: e.message,
|
message: e.message,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
4
luogu_remote_judger/package-lock.json
generated
4
luogu_remote_judger/package-lock.json
generated
@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "s2oj-luogu-remote-judger",
|
"name": "s2oj-luogu-remote-judger",
|
||||||
"version": "0.0.0",
|
"version": "0.0.1",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "s2oj-luogu-remote-judger",
|
"name": "s2oj-luogu-remote-judger",
|
||||||
"version": "0.0.0",
|
"version": "0.0.1",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"fs-extra": "^11.1.1",
|
"fs-extra": "^11.1.1",
|
||||||
"reggol": "^1.3.5",
|
"reggol": "^1.3.5",
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "s2oj-luogu-remote-judger",
|
"name": "s2oj-luogu-remote-judger",
|
||||||
"version": "0.0.0",
|
"version": "0.0.1",
|
||||||
"description": "Luogu remote judger for S2OJ.",
|
"description": "Luogu remote judger for S2OJ.",
|
||||||
"private": true,
|
"private": true,
|
||||||
"main": "entrypoint.js",
|
"main": "entrypoint.js",
|
||||||
|
23
web/app/libs/uoj-html-lib.php.patch
Normal file
23
web/app/libs/uoj-html-lib.php.patch
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
--- UOJ-System/web/app/libs/uoj-html-lib.php 2022-12-30 09:54:05.452022649 +0800
|
||||||
|
+++ UOJ-Luogu-RemoteJudge/web/app/libs/uoj-html-lib.php 2023-03-21 21:22:31.783213786 +0800
|
||||||
|
@@ -989,3 +989,20 @@
|
||||||
|
$config['get_row_index'] = '';
|
||||||
|
echoLongTable($col_names, 'user_info', '1', $tail, $header_row, $print_row, $config);
|
||||||
|
}
|
||||||
|
+
|
||||||
|
+function renderMarkdown($content_md) {
|
||||||
|
+ $purifier = HTML::pruifier();
|
||||||
|
+
|
||||||
|
+ try {
|
||||||
|
+ $v8 = new V8Js();
|
||||||
|
+ $v8->content_md = $content_md;
|
||||||
|
+ $v8->executeString(file_get_contents($_SERVER['DOCUMENT_ROOT'] . '/js/marked.js'), 'marked.js');
|
||||||
|
+ $content = $v8->executeString('marked(PHP.content_md)');
|
||||||
|
+ } catch (V8JsException $e) {
|
||||||
|
+ throw new Exception('V8Js error: ' . $e->getMessage());
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ $content = $purifier->purify($content);
|
||||||
|
+
|
||||||
|
+ return $content;
|
||||||
|
+}
|
10
web/app/libs/uoj-validate-lib.php.patch
Normal file
10
web/app/libs/uoj-validate-lib.php.patch
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
--- UOJ-System/web/app/libs/uoj-validate-lib.php 2022-12-30 09:54:05.452022649 +0800
|
||||||
|
+++ UOJ-Luogu-RemoteJudge/web/app/libs/uoj-validate-lib.php 2023-03-21 21:23:42.635610391 +0800
|
||||||
|
@@ -47,3 +47,7 @@
|
||||||
|
function validateIP($ip) {
|
||||||
|
return filter_var($ip, FILTER_VALIDATE_IP) !== false;
|
||||||
|
}
|
||||||
|
+
|
||||||
|
+function validateLuoguProblemId($str) {
|
||||||
|
+ return preg_match('/^(P|B)[1-9][0-9]{3,5}$/', $str);
|
||||||
|
+}
|
Loading…
Reference in New Issue
Block a user