mirror of
https://github.com/renbaoshuo/S2OJ.git
synced 2024-11-21 12:08:41 +00:00
feat(remote_judger): init
This commit is contained in:
parent
1689c34aa3
commit
3a2e3ce1db
@ -3,7 +3,12 @@ root = true
|
||||
[*]
|
||||
indent_style = tab
|
||||
indent_size = 4
|
||||
end_of_line = lf
|
||||
|
||||
[*.y{,a}ml]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
|
||||
[remote_judger/**.{js,ts}]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
|
@ -42,6 +42,20 @@ services:
|
||||
- SOCKET_PORT=2333
|
||||
- SOCKET_PASSWORD=_judger_socket_password_
|
||||
|
||||
uoj-remote-judger:
|
||||
build:
|
||||
context: ./remote_judger/
|
||||
dockerfile: Dockerfile
|
||||
args:
|
||||
- USE_MIRROR=1
|
||||
container_name: uoj-remote-judger
|
||||
restart: always
|
||||
volumes:
|
||||
- ./uoj_data/judger/log:/opt/uoj_judger/log
|
||||
environment:
|
||||
- UOJ_PROTOCOL=http
|
||||
- UOJ_HOST=uoj-web
|
||||
|
||||
uoj-web:
|
||||
build:
|
||||
context: ./
|
||||
|
3
remote_judger/.gitignore
vendored
Normal file
3
remote_judger/.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
dist/
|
||||
node_modules/
|
||||
*-error.log
|
14
remote_judger/.prettierrc
Normal file
14
remote_judger/.prettierrc
Normal file
@ -0,0 +1,14 @@
|
||||
{
|
||||
"arrowParens": "avoid",
|
||||
"bracketSpacing": true,
|
||||
"endOfLine": "lf",
|
||||
"jsxSingleQuote": false,
|
||||
"printWidth": 80,
|
||||
"proseWrap": "preserve",
|
||||
"quoteProps": "as-needed",
|
||||
"semi": true,
|
||||
"singleQuote": true,
|
||||
"tabWidth": 2,
|
||||
"useTabs": false,
|
||||
"organizeImportsSkipDestructiveCodeActions": true
|
||||
}
|
12
remote_judger/Dockerfile
Normal file
12
remote_judger/Dockerfile
Normal file
@ -0,0 +1,12 @@
|
||||
FROM node:18
|
||||
|
||||
WORKDIR /opt/s2oj_remote_judger
|
||||
COPY package*.json ./
|
||||
|
||||
RUN npm ci --only=production
|
||||
|
||||
COPY . .
|
||||
|
||||
RUN npm run build
|
||||
|
||||
CMD [ "node", "dist/entrypoint.js" ]
|
2545
remote_judger/package-lock.json
generated
Normal file
2545
remote_judger/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
32
remote_judger/package.json
Normal file
32
remote_judger/package.json
Normal file
@ -0,0 +1,32 @@
|
||||
{
|
||||
"name": "s2oj-remote-judger",
|
||||
"version": "0.0.0",
|
||||
"description": "Remote judger of S2OJ.",
|
||||
"scripts": {
|
||||
"build": "tsc -p .",
|
||||
"start": "node dist/entrypoint.js"
|
||||
},
|
||||
"type": "module",
|
||||
"repository": "https://github.com/renbaoshuo/S2OJ",
|
||||
"author": "Baoshuo <i@baoshuo.ren>",
|
||||
"license": "AGPL-3.0",
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"jsdom": "^21.0.0",
|
||||
"math-sum": "^2.0.0",
|
||||
"reggol": "^1.3.4",
|
||||
"superagent": "^8.0.6",
|
||||
"superagent-prefix": "^0.0.2",
|
||||
"superagent-proxy": "^3.0.0",
|
||||
"xml-js": "^1.6.11"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/js-yaml": "^4.0.5",
|
||||
"@types/jsdom": "^20.0.1",
|
||||
"@types/node": "^18.11.18",
|
||||
"@types/superagent": "^4.1.16",
|
||||
"@types/superagent-proxy": "^3.0.0",
|
||||
"js-yaml": "^4.1.0",
|
||||
"typescript": "^4.9.4"
|
||||
}
|
||||
}
|
62
remote_judger/src/daemon.ts
Normal file
62
remote_judger/src/daemon.ts
Normal file
@ -0,0 +1,62 @@
|
||||
import fs from 'fs';
|
||||
import superagent from 'superagent';
|
||||
import proxy from 'superagent-proxy';
|
||||
import prefix from 'superagent-prefix';
|
||||
import Logger from '@/utils/logger';
|
||||
import sleep from '@/utils/sleep';
|
||||
import * as TIME from '@/utils/time';
|
||||
|
||||
proxy(superagent);
|
||||
|
||||
const logger = new Logger('daemon');
|
||||
|
||||
interface UOJConfig {
|
||||
server_url: string;
|
||||
judger_name: string;
|
||||
password: string;
|
||||
}
|
||||
|
||||
interface UOJSubmission {
|
||||
id: number;
|
||||
problem_id: number;
|
||||
problem_mtime: number;
|
||||
content: any;
|
||||
status: string;
|
||||
}
|
||||
|
||||
export default async function daemon(config: UOJConfig) {
|
||||
const agent = superagent
|
||||
.agent()
|
||||
.use(prefix(`${this.config.server_url}/judge`))
|
||||
.type('application/x-www-form-urlencoded')
|
||||
.serialize(data =>
|
||||
new URLSearchParams({
|
||||
judger_name: config.judger_name,
|
||||
password: config.password,
|
||||
...data,
|
||||
}).toString()
|
||||
);
|
||||
|
||||
while (true) {
|
||||
try {
|
||||
const { body, error } = await agent.post('/submit');
|
||||
|
||||
if (error) {
|
||||
logger.error(error.message);
|
||||
|
||||
await sleep(TIME.second);
|
||||
} else if (body === 'Nothing to judge') {
|
||||
await sleep(2 * TIME.second);
|
||||
} else {
|
||||
const data: UOJSubmission = JSON.parse(body);
|
||||
|
||||
logger.info('Start judging', data.id);
|
||||
|
||||
// TODO: judge
|
||||
}
|
||||
} catch (err) {
|
||||
logger.error(err);
|
||||
await sleep(TIME.second);
|
||||
}
|
||||
}
|
||||
}
|
15
remote_judger/src/entrypoint.ts
Normal file
15
remote_judger/src/entrypoint.ts
Normal file
@ -0,0 +1,15 @@
|
||||
import daemon from './daemon';
|
||||
|
||||
const {
|
||||
UOJ_PROTOCOL = 'http',
|
||||
UOJ_HOST = 'uoj-web',
|
||||
UOJ_JUDGER_NAME = 'remote_judger',
|
||||
UOJ_JUDGER_PASSWORD = '',
|
||||
} = process.env;
|
||||
const UOJ_BASEURL = `${UOJ_PROTOCOL}://${UOJ_HOST}`;
|
||||
|
||||
daemon({
|
||||
server_url: UOJ_BASEURL,
|
||||
judger_name: UOJ_JUDGER_NAME,
|
||||
password: UOJ_JUDGER_PASSWORD,
|
||||
});
|
7
remote_judger/src/proxy.ts
Normal file
7
remote_judger/src/proxy.ts
Normal file
@ -0,0 +1,7 @@
|
||||
declare module 'superagent' {
|
||||
interface Request {
|
||||
proxy(url: string): this;
|
||||
}
|
||||
}
|
||||
|
||||
export default {};
|
11
remote_judger/src/utils/logger.ts
Normal file
11
remote_judger/src/utils/logger.ts
Normal file
@ -0,0 +1,11 @@
|
||||
import Logger from 'reggol';
|
||||
|
||||
Logger.levels.base = process.env.DEV ? 3 : 2;
|
||||
Logger.targets[0].showTime = 'dd hh:mm:ss';
|
||||
Logger.targets[0].label = {
|
||||
align: 'right',
|
||||
width: 9,
|
||||
margin: 1,
|
||||
};
|
||||
|
||||
export default Logger;
|
5
remote_judger/src/utils/sleep.ts
Normal file
5
remote_judger/src/utils/sleep.ts
Normal file
@ -0,0 +1,5 @@
|
||||
export default function sleep(timeout: number) {
|
||||
return new Promise(resolve => {
|
||||
setTimeout(() => resolve(true), timeout);
|
||||
});
|
||||
}
|
5
remote_judger/src/utils/time.ts
Normal file
5
remote_judger/src/utils/time.ts
Normal file
@ -0,0 +1,5 @@
|
||||
export const second = 1000;
|
||||
export const minute = second * 60;
|
||||
export const hour = minute * 60;
|
||||
export const day = hour * 24;
|
||||
export const week = day * 7;
|
23
remote_judger/tsconfig.json
Normal file
23
remote_judger/tsconfig.json
Normal file
@ -0,0 +1,23 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "esnext",
|
||||
"lib": ["esnext"],
|
||||
"allowJs": true,
|
||||
"skipLibCheck": true,
|
||||
// "strict": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"esModuleInterop": true,
|
||||
"module": "esnext",
|
||||
"moduleResolution": "node",
|
||||
"resolveJsonModule": true,
|
||||
"isolatedModules": true,
|
||||
"incremental": true,
|
||||
"baseUrl": ".",
|
||||
"paths": {
|
||||
"@/*": ["src/*"]
|
||||
},
|
||||
"outDir": "./dist"
|
||||
},
|
||||
"include": ["**/*.ts"],
|
||||
"exclude": ["node_modules"]
|
||||
}
|
@ -64,21 +64,21 @@ class UOJLang {
|
||||
return [];
|
||||
}
|
||||
$is_avail = [];
|
||||
$dep_list = [
|
||||
['C++98', 'C++03', 'C++11', 'C++', 'C++17', 'C++20'],
|
||||
['Java8', 'Java11', 'Java17']
|
||||
];
|
||||
// $dep_list = [
|
||||
// ['C++98', 'C++03', 'C++11', 'C++', 'C++17', 'C++20'],
|
||||
// ['Java8', 'Java11', 'Java17']
|
||||
// ];
|
||||
foreach ($list as $lang) {
|
||||
$lang = static::getUpgradedLangCode($lang);
|
||||
foreach ($dep_list as $dep) {
|
||||
$ok = false;
|
||||
foreach ($dep as $d) {
|
||||
if ($ok || $d == $lang) {
|
||||
$is_avail[$d] = true;
|
||||
$ok = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
// foreach ($dep_list as $dep) {
|
||||
// $ok = false;
|
||||
// foreach ($dep as $d) {
|
||||
// if ($ok || $d == $lang) {
|
||||
// $is_avail[$d] = true;
|
||||
// $ok = true;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
$is_avail[$lang] = true;
|
||||
}
|
||||
|
||||
|
@ -86,9 +86,6 @@ Route::group(
|
||||
|
||||
Route::any('/super_manage(?:/{tab})?', '/super_manage.php');
|
||||
|
||||
Route::any('/download/problem/{id}/data.zip', '/download.php?type=problem');
|
||||
Route::any('/download/problem/{id}/attachment.zip', '/download.php?type=attachment');
|
||||
|
||||
Route::any('/check-notice', '/check_notice.php');
|
||||
Route::any('/click-zan', '/click_zan.php');
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user