1
0
mirror of https://github.com/renbaoshuo/UOJ-Luogu-RemoteJudge.git synced 2024-11-23 22:58:43 +00:00

Compare commits

...

9 Commits

Author SHA1 Message Date
2ae6494230
chore: release v0.0.1 2023-03-21 22:18:12 +08:00
12b2e11e1f
fix: doc for added files 2023-03-21 22:09:04 +08:00
00c6e7bd0d
chore: thanks to luogu-dev & hydro-dev 2023-03-21 22:06:52 +08:00
8fc2642078
chore: add some faqs 2023-03-21 22:04:13 +08:00
80b578b0fc
fix: "Judgement Failed" 2023-03-21 22:03:45 +08:00
b60d06a98d
feat: installation docs 2023-03-21 21:36:05 +08:00
01dbc95da0
chore: add some patch files 2023-03-21 21:25:06 +08:00
b67f2e505e
feat: use MIT license 2023-03-21 21:24:45 +08:00
0cd9b4c5da
feat: add dockerfile 2023-03-21 20:13:51 +08:00
12 changed files with 193 additions and 23 deletions

16
FAQ.md
View File

@ -1,3 +1,17 @@
# 常见问题 # 常见问题
_TODO_ ### 评测时显示 `Unauthorized`
请检查评测机处配置的洛谷开放平台用户信息是否正确。
### 评测时显示 `Payment Required`
您的评测额度剩余量不足,请充值后再重新评测。
### 评测时显示 `Internal Server Error`
请联系洛谷管理员。
### 评测时显示 `Bad Gateway`、`Service Unavailable` 或 `Gateway Timeout`
可能是网络波动造成的。如果长时间出现此情况,请联系洛谷管理员。

View File

@ -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
View 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.

View File

@ -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)

View File

@ -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`);

View 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" ]

View File

@ -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,
}); });
} }

View File

@ -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",

View File

@ -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",

View 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;
+}

View 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);
+}