mirror of
https://gitcode.com/gh_mirrors/hy/Hydro.git
synced 2026-10-17 09:36:08 +08:00
wiki
This commit is contained in:
1 parent
8c20c34d8b
commit
ca11d80776
45 files changed
+417
-443
No files matched your search
@@ -3,19 +3,10 @@
|
||||
Hydro是一个高效的信息学在线测评系统。
|
||||
特点: 易于部署,轻量,功能强大。
|
||||
|
||||
[中文文档](wiki/deploy.md)
|
||||
|
||||
Hydro 的界面基于 Vijos 二次开发。
|
||||
|
||||
## 使用方式
|
||||
|
||||
#### 使用 `docker-compose`(推荐)
|
||||
|
||||
// TODO(WIP)
|
||||
|
||||
#### 直接部署:
|
||||
|
||||
安装mongodb (省略)
|
||||
下载Github Actions自动编译的 app.js 直接运行即可。
|
||||
|
||||
## 鸣谢
|
||||
|
||||
排名不分先后,按照链接字典序
|
||||
|
||||
@@ -6,6 +6,7 @@ const yaml = require('js-yaml');
|
||||
const { root, ignoreFailure, rmdir } = require('./utils');
|
||||
const template = require('./template');
|
||||
const hack = require('./hack');
|
||||
const wikiBuild = require('./wiki');
|
||||
|
||||
const fsp = fs.promises;
|
||||
|
||||
@@ -42,6 +43,8 @@ async function build(type) {
|
||||
template: template('templates'),
|
||||
public: {},
|
||||
};
|
||||
const wiki = wikiBuild();
|
||||
builtin.lib = `Object.assign(global.Hydro.wiki,${JSON.stringify(wiki)})`;
|
||||
const files = getFiles('.uibuild');
|
||||
for (const f of files) {
|
||||
if (fs.statSync(root(`.uibuild/${f}`)).isDirectory()) {
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
const fs = require('fs');
|
||||
const { root } = require('./utils');
|
||||
|
||||
module.exports = () => {
|
||||
const pages = fs.readdirSync(root('wiki'));
|
||||
const res = {};
|
||||
for (const page of pages) {
|
||||
const c = fs.readFileSync(root(`wiki/${page}`)).toString().split('\n');
|
||||
const pagename = page.split('.')[0];
|
||||
res[pagename] = [];
|
||||
let content = null;
|
||||
for (let i = 0; i < c.length; i++) {
|
||||
const line = c[i];
|
||||
if (line.startsWith('# ')) {
|
||||
if (content) res[pagename].push(content);
|
||||
content = {};
|
||||
const t = line.split('# ')[1].split('|');
|
||||
[content.title, content.id] = t.map((q) => q.trim());
|
||||
content.content = '';
|
||||
} else {
|
||||
content.content = `${content.content}${line}\n`;
|
||||
}
|
||||
res[pagename].push(content);
|
||||
}
|
||||
}
|
||||
return res;
|
||||
};
|
||||
@@ -1,12 +1,10 @@
|
||||
const { Route, Handler } = global.Hydro.service.server;
|
||||
const { NotFoundError } = global.Hydro.error;
|
||||
// eslint-disable-next-line import/no-unresolved
|
||||
const pages = require('./__build.json');
|
||||
const { Route, Handler } = require('../service/server');
|
||||
const { NotFoundError } = require('../error');
|
||||
|
||||
class WikiHandler extends Handler {
|
||||
async get({ name }) {
|
||||
if (!pages[name]) throw new NotFoundError(name);
|
||||
const contents = pages[name];
|
||||
if (!global.Hydro.wiki[name]) throw new NotFoundError(name);
|
||||
const contents = global.Hydro.wiki[name];
|
||||
const path = [
|
||||
['Hydro', '/'],
|
||||
['wiki', '/wiki'],
|
||||
+8
-7
@@ -166,7 +166,7 @@ const builtinModel = [
|
||||
const builtinHandler = [
|
||||
'home', 'problem', 'record', 'judge', 'user',
|
||||
'contest', 'training', 'discussion', 'manage', 'import',
|
||||
'misc', 'homework', 'domain',
|
||||
'misc', 'homework', 'domain', 'wiki',
|
||||
];
|
||||
|
||||
const builtinScript = [
|
||||
@@ -297,23 +297,25 @@ async function terminate() {
|
||||
}
|
||||
|
||||
async function load() {
|
||||
global.nodeModules = {
|
||||
bson: require('bson'),
|
||||
'js-yaml': require('js-yaml'),
|
||||
mongodb: require('mongodb'),
|
||||
};
|
||||
global.Hydro = {
|
||||
handler: {},
|
||||
service: {},
|
||||
model: {},
|
||||
script: {},
|
||||
lib: {},
|
||||
nodeModules: {
|
||||
bson: require('bson'),
|
||||
'js-yaml': require('js-yaml'),
|
||||
mongodb: require('mongodb'),
|
||||
},
|
||||
wiki: {},
|
||||
template: {},
|
||||
ui: {},
|
||||
};
|
||||
global.onDestory = [];
|
||||
Error.stackTraceLimit = 50;
|
||||
process.on('unhandledRejection', (e) => console.error(e));
|
||||
process.on('SIGINT', terminate);
|
||||
if (cluster.isMaster) {
|
||||
console.log(`Master ${process.pid} Starting`);
|
||||
process.stdin.setEncoding('utf8');
|
||||
@@ -326,7 +328,6 @@ async function load() {
|
||||
console.warn(e);
|
||||
}
|
||||
});
|
||||
process.on('SIGINT', terminate);
|
||||
await loadAsMaster();
|
||||
cluster.on('exit', (worker, code, signal) => {
|
||||
console.log(`Worker ${worker.process.pid} exit: ${code} ${signal}`);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* eslint-disable no-await-in-loop */
|
||||
const { mongodb } = global.Hydro.nodeModules;
|
||||
const { mongodb } = global.nodeModules;
|
||||
const dst = global.Hydro.service.db;
|
||||
const { file, problem, discussion } = global.Hydro.model;
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
const assert = require('assert');
|
||||
|
||||
const { download } = global.Hydro.lib;
|
||||
const { axios } = global.Hydro.lib;
|
||||
const { download, axios } = global.Hydro.lib;
|
||||
const { ValidationError, RemoteOnlineJudgeError } = global.Hydro.error;
|
||||
|
||||
async function syzoj(url, handler) {
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
const root = (name) => path.resolve(__dirname, name);
|
||||
|
||||
exports.prebuild = async () => {
|
||||
const pages = fs.readdirSync(root('raw'));
|
||||
const res = {};
|
||||
for (const page of pages) {
|
||||
// eslint-disable-next-line import/no-dynamic-require
|
||||
const contents = require(root(`raw/${page}/contents.json`));
|
||||
res[page] = [];
|
||||
for (const id of contents) {
|
||||
const content = {};
|
||||
const c = fs.readFileSync(root(`raw/${page}/${id}.md`)).toString().split('\n');
|
||||
// eslint-disable-next-line prefer-destructuring
|
||||
content.title = c[0].split('# ')[1];
|
||||
content.id = id;
|
||||
content.content = c.splice(1, c.length - 1).join('\n');
|
||||
res[page].push(content);
|
||||
}
|
||||
}
|
||||
fs.writeFileSync(root('__build.json'), JSON.stringify(res));
|
||||
};
|
||||
@@ -1,5 +0,0 @@
|
||||
{
|
||||
"id": "wiki",
|
||||
"version": "1.0.0",
|
||||
"description": "Basic wiki module."
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
wiki_about: About
|
||||
wiki_help: Help
|
||||
wiki_development: Development
|
||||
@@ -1,7 +0,0 @@
|
||||
wiki_about: 关于
|
||||
wiki_help: 帮助
|
||||
wiki_development: 开发文档
|
||||
Basic: 基础
|
||||
Module: 模块
|
||||
Introduction: 介绍
|
||||
Deployment: 部署
|
||||
@@ -1,5 +0,0 @@
|
||||
[
|
||||
"privacy",
|
||||
"tos",
|
||||
"discuss"
|
||||
]
|
||||
@@ -1,23 +0,0 @@
|
||||
# Discussion: Terms Of Service
|
||||
|
||||
为了更好地发挥讨论、题解的积极作用,使广大用户学到知识、获得利益,进一步规范讨论和题解功能的使用,我们制定了《讨论和题解版规》(简称《版规》)。您在发布(或回复)讨论和题解时,即代表您已充分阅读、理解、接受并保证遵守此版规。
|
||||
您在发布(或回复)讨论和题解或使用相关功能时须遵守以下规定:
|
||||
|
||||
- 第一次使用编辑器前,要先阅读编辑器快速入门和 Markdown 详细帮助。
|
||||
- 不得将讨论、题解混淆。例如,不得将题解发布到讨论中,题解应发布在相应题目的题解区中。
|
||||
- 发布(或回复)的所有内容不得包含会干扰 Hydro 用户界面呈现的相关内容。
|
||||
- 发布(或回复)的所有内容不得包含恶意代码和指向恶意网站或 Hydro 明确禁止的网站的链接。
|
||||
- 特别地,发布(或回复)含有代码的内容时,应当将代码高亮。一个简单的方法是选中代码块然后按下 Tab 键。
|
||||
- 发布的题解禁止只包含无详细注释的代码。题解中难以理解的代码应当有尽可能详细的注释。
|
||||
- 打分、投票和评价应当客观。例如,对于题解的打分、投票和评价应当关注于题解本身的质量。
|
||||
- 我们欢迎原创作品,并会对其作者给予数量不等的 RP 奖励。
|
||||
|
||||
您在发布、回复讨论和题解时还须遵守法律法规,不得发布违法违规内容,包括但不限于:
|
||||
|
||||
- 危害国家安全统一、破坏社会稳定、违反公序良俗、侮辱、诽谤、淫秽、暴力以及任何违反国家法律法规的内容;
|
||||
- 侵害他人知识产权、商业秘密等合法权利的内容;
|
||||
- 恶意虚构事实、隐瞒真相以误导、欺骗他人的内容;
|
||||
- 广告信息及垃圾信息;
|
||||
- 其他法律法规禁止的内容。
|
||||
|
||||
对于违反《版规》的,我们将进行警告并删除相关内容、临时冻结用户、永久冻结用户等操作。
|
||||
@@ -1,23 +0,0 @@
|
||||
# Privacy
|
||||
|
||||
#### 1. 收集的信息
|
||||
|
||||
我们收集信息是为了向所有用户提供更好的服务。我们有两种信息收集方式:
|
||||
s
|
||||
- 您向我们提供信息。在您注册 Hydro 帐户时,我们会要求您提供个人信息,例如您的电子邮件地址、QQ号码等。
|
||||
- 我们在您使用服务的过程中获取信息。我们会收集关于您使用的服务以及使用方式的信息,例如您在何时使用了我们服务。
|
||||
|
||||
#### 2. 如何使用收集到的信息
|
||||
|
||||
我们利用从所有服务中收集的信息来提供、维护、保护和改进这些服务,同时开发新的服务并保护 Hydro 以及用户的隐私。
|
||||
当我们要将信息用于本隐私权政策未载明的其它用途时,则会事先征求您的同意。
|
||||
|
||||
#### 3. 访问和更新您的个人信息
|
||||
|
||||
无论您在何时使用我们的服务,我们都力求让您能够访问自己的个人信息。如果这些信息有误,我们会努力通过各种方式让您快速更新信息或删除信息。在更新您的个人信息时,我们可能会要求您先验证自己的身份,然后再处理您的请求。
|
||||
我们力求对服务进行完善的维护,以保护信息免遭意外或恶意的破坏。因此,当您从我们的服务中删除信息后,我们可能不会立即从在用的服务器中删除这些信息的残留副本,也可能不会从备份系统中删除相应的信息。
|
||||
|
||||
#### 4. 信息安全
|
||||
|
||||
我们为您提供SSL加密访问服务,您可以通过SSL(https)使用我们的服务,这可以很大程度上保障在传输过程中您信息的安全。
|
||||
对于敏感数据(如您的密码),我们承诺在存储时进行高强度不可逆加密。Hydro 的管理员、维护人员等均不能够访问到敏感数据的明文,所有操作均无人工介入。
|
||||
@@ -1,12 +0,0 @@
|
||||
# Basic
|
||||
|
||||
Hydro 后端使用 NodeJS 编写,前端使用 JQuery + React。
|
||||
代码风格遵循 airbnb 标准(详见 .eslintrc.js)。
|
||||
|
||||
由于模块中不能使用 require() 引入 Hydro 的文件,因此需要从 global.Hydro 中取出需要的模块。
|
||||
例:
|
||||
|
||||
```js
|
||||
const { db } = global.Hydro.service;
|
||||
const { problem } = global.Hydro.model;
|
||||
```
|
||||
@@ -1,11 +0,0 @@
|
||||
[
|
||||
"basic",
|
||||
"module",
|
||||
"hydro",
|
||||
"handler",
|
||||
"service",
|
||||
"lib",
|
||||
"file",
|
||||
"locale",
|
||||
"template"
|
||||
]
|
||||
@@ -1,3 +0,0 @@
|
||||
# File
|
||||
|
||||
file 文件夹下的所有文件将被自动解压到 `$TMPDIR/hydro/模块ID/路径` 的位置(权限755,通常用于启动子进程)。
|
||||
@@ -1,96 +0,0 @@
|
||||
# Handler
|
||||
|
||||
通常用于提供页面路由。
|
||||
|
||||
例:注册新路由:
|
||||
|
||||
```js
|
||||
const { Handler, Route } = global.Hydro.service.server;
|
||||
const { user } = global.Hydro.model;
|
||||
const { PERM_LOGGEDIN } = global.Hydro.permission;
|
||||
|
||||
class CustomHandler extends Handler {
|
||||
async prepare() {
|
||||
this.checkPassword(PERM_LOGGEDIN);
|
||||
}
|
||||
|
||||
async get({ username, password }) {
|
||||
const udoc = await user.getByUname(username);
|
||||
udoc.checkPassword(password);
|
||||
this.response.body = { udoc };
|
||||
}
|
||||
|
||||
async post() {
|
||||
// 当提交表单时会执行该函数
|
||||
}
|
||||
|
||||
async postConfirm() {
|
||||
// 当提交表单并存在 operation 值为 confirm 时执行。
|
||||
}
|
||||
}
|
||||
|
||||
async function apply() {
|
||||
Route('/route/:username', module.exports.CustomHandler);
|
||||
}
|
||||
|
||||
global.Hydro.handler.custom = module.exports = { CustomHandler, apply };
|
||||
```
|
||||
|
||||
在路由中定义所有的函数应均为异步函数,支持的函数如下:
|
||||
|
||||
_prepare, prepare, get, post, post[Operation], cleanup, _cleanup
|
||||
|
||||
具体流程如下:
|
||||
|
||||
先执行 _prepare(args) (如果存在)
|
||||
args 为传入的参数集合(包括 QueryString, Body, Path)中的全部参数,并对以下字段进行了校验:
|
||||
|
||||
| 名称 | 类型 |
|
||||
| :------: | :-----------: |
|
||||
| content | string |
|
||||
| title | string |
|
||||
| uid | number(int) |
|
||||
| password | string |
|
||||
| mail | string(mail) |
|
||||
| uname | string |
|
||||
| page | number(int) |
|
||||
| duration | number(float) |
|
||||
| role | string |
|
||||
| roles | string[] |
|
||||
| pids | string |
|
||||
| tid | bson.ObjectID |
|
||||
| rid | bson.ObjectID |
|
||||
| did | bson.ObjectID |
|
||||
| drid | bson.ObjectID |
|
||||
| drrid | bson.ObjectID |
|
||||
| psid | bson.ObjectID |
|
||||
| psrid | bson.ObjectID |
|
||||
| docId | bson.ObjectID |
|
||||
| mongoId | bson.ObjectID |
|
||||
|
||||
再执行 prepare(args) (如果存在)
|
||||
检查请求类型:
|
||||
|
||||
```
|
||||
为 GET ?
|
||||
-> 执行 get(args)
|
||||
为 POST ?
|
||||
-> 执行 post(args)
|
||||
-> 含有 operation 字段?
|
||||
-> 执行 post[Operation]
|
||||
```
|
||||
|
||||
执行 cleanup()
|
||||
执行 _cleanup()
|
||||
|
||||
如果在 this.response.template 指定模板则渲染,否则直接返回 this.response.body 中的内容。
|
||||
|
||||
* 在表单提交时的 operation 字段使用下划线,函数名使用驼峰命名。
|
||||
|
||||
如 `<input type="hidden" name="operation" value="confirm_delete">` 对应 `postConfirmDelete` 函数。
|
||||
|
||||
应当提供 `apply` 函数,并与定义的 Handler 一同挂载到 `global.Hydro.handler[模块名]` 位置。
|
||||
`apply` 函数将在初始化阶段被调用。
|
||||
|
||||
<blockquote class="note">请在 apply 函数中从 module.exports 引用,因为它们可能需要被其他模块修改。</blockquote>
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
# Hydro.json
|
||||
|
||||
Hydro.json 是模块的声明文件,格式如下。
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "模块ID",
|
||||
"version": "模块版本",
|
||||
"description": "模块描述"
|
||||
}
|
||||
```
|
||||
@@ -1,3 +0,0 @@
|
||||
# Lib
|
||||
|
||||
库文件。通常用于提供一些功能(废话)。
|
||||
@@ -1,3 +0,0 @@
|
||||
# Locale
|
||||
|
||||
用于提供多国翻译。格式与 Hydro 的 locale 文件夹格式相同。
|
||||
@@ -1,23 +0,0 @@
|
||||
# Module
|
||||
|
||||
## 文件架构
|
||||
|
||||
Hydro 的模块由以下几个部分组成:
|
||||
|
||||
service: 服务
|
||||
script: 脚本
|
||||
handler: 访问路由
|
||||
lib: 库
|
||||
model: 数据库模型
|
||||
file: 额外文件
|
||||
locale: 多国化
|
||||
template: UI 模板
|
||||
README.md: 介绍
|
||||
hydro.json: 声明文件(必须)
|
||||
|
||||
## 模块编译
|
||||
|
||||
使用 `hydro-build` 进行编译。
|
||||
安装:`yarn add hydro-build -D`
|
||||
编译:`hydro-build`
|
||||
如果命运的齿轮没有出差错,您应该可以找到生成的.hydro文件了。
|
||||
@@ -1,3 +0,0 @@
|
||||
# README.md
|
||||
|
||||
项目的说明文件。
|
||||
@@ -1,3 +0,0 @@
|
||||
# Service
|
||||
|
||||
通常用于提供与其他程序对接的接口。(如内置的 MongoDB 等)
|
||||
@@ -1,31 +0,0 @@
|
||||
# Template
|
||||
|
||||
页面模板,使用 nunjucks 语法。
|
||||
传入了 _ 翻译函数与 model 等。
|
||||
|
||||
```html
|
||||
{% set page_name = "page_name" %}
|
||||
{% extends "layout/basic.html" %}
|
||||
{% block content %}
|
||||
<div class="error__container clearfix">
|
||||
<div class="error__icon-container">
|
||||
<div class="error__twd2"></div>
|
||||
</div>
|
||||
<div class="error__text-container">
|
||||
<h1>{{ _('Oops!') }}</h1>
|
||||
<p>{{ _(error.message).format(error.params) }}</p>
|
||||
<p>{{ _('Technical Information') }}:</p>
|
||||
<p>{{ _('Type') }}: {{ error.code }}</p>
|
||||
<p>{{ _('Arguments') }}:
|
||||
<ol>
|
||||
{% for param in error.params %}
|
||||
<li>{{ param }}</li>
|
||||
{% endfor %}
|
||||
</ol>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
```
|
||||
|
||||
<blockquote class="note">请不要覆盖已有模板。</blockquote>
|
||||
@@ -1,4 +0,0 @@
|
||||
[
|
||||
"introduction",
|
||||
"deploy"
|
||||
]
|
||||
@@ -1,13 +0,0 @@
|
||||
# Deployment
|
||||
|
||||
Hydro 依赖于 MongoDB 与 NodeJS,您应该先安装它们。
|
||||
之后您可以下载最新版的 Hydro 程序,放置于一个空文件夹,使用如下命令启动 Hydro:
|
||||
|
||||
```sh
|
||||
node hydro.js
|
||||
```
|
||||
|
||||
Hydro 会自行初始化并监听 8888 端口。请用浏览器访问并进行相应配置。
|
||||
数据库配置完成后,会自动创建 Root 用户。(账号 `root` ,密码 `rootroot`),请及时修改。
|
||||
|
||||
之后的进阶配置可在 管理 面板进行。
|
||||
@@ -1,11 +0,0 @@
|
||||
# Introduction
|
||||
|
||||
为什么使用 Hydro ?
|
||||
|
||||
- 安全:使用 cgroup 进行隔离,杜绝卡评测;
|
||||
- 高效:Hydro 使用了沙箱复用技术,拥有极高的评测效率;
|
||||
- 扩展:Hydro 支持安装额外模块进行扩展;
|
||||
- 强大:配合 Judger 模块(或 HydroJudger 独立评测机),可支持 spj,交互题,提交答案题,文件IO等多种特性;
|
||||
- 简便:提供了多种迁移脚本,可从 Vijos 等快速升级至 Hydro;
|
||||
- 自定:所有权限节点均可自由设置;
|
||||
- 社区:Hydro 正在持续维护中;
|
||||
@@ -1,3 +0,0 @@
|
||||
# Accepted Ratio
|
||||
|
||||
通过率的影响极其恶劣,Hydro 不提供也不承认通过率。
|
||||
@@ -1,19 +0,0 @@
|
||||
# Compile Error
|
||||
|
||||
可能有以下情况:
|
||||
|
||||
- 递交时选错了编程语言
|
||||
- Java 的主类名没有使用 "Main"
|
||||
- 对于 C/C++:见下
|
||||
- 一般性的编译错误
|
||||
|
||||
<blockquote class="warn">
|
||||
对 C/C++ 选手的特别提醒:
|
||||
<ul>
|
||||
<li>1. __int64 在 GNU C++ 中应写成 long long 类型</li>
|
||||
<li>2. main() 返回值必须定义为 int ,而不是 void</li>
|
||||
<li>3. for 语句中的指标变量 i 将会在如"for (int i = 0...) {...}"语句之后变为无效</li>
|
||||
<li>4. itoa 不是一个通用 ANSI 函数(标准 C/C++ 中无此函数)</li>
|
||||
<li>5. printf 中使用 %lf 格式是不正确的</li>
|
||||
</ul>
|
||||
</blockquote>
|
||||
@@ -1,14 +0,0 @@
|
||||
# Compilers' Version and Parameters
|
||||
|
||||
Hydro使用 [HydroJudger](https://github.com/hydro-dev/HydroJudger) 进行评测,以docker镜像的形式安装至评测机。
|
||||
所使用的编译器均为创建镜像时 [debian testing](https://wiki.debian.org/DebianTesting) 分支的最新版。编译参数如下:
|
||||
|
||||
- Free Pascal `fpc -O2 -o/out/foo /in/foo.pas`
|
||||
- C `gcc -O2 -Wall -std=c99 -o /out/foo /in/foo.c -lm`
|
||||
- C++ `g++ -O2 -Wall -std=c++11 -o /out/foo /in/foo.cc -lm`
|
||||
- Java `javac Main.java`
|
||||
- Python `python foo.py`
|
||||
- Python 3 `python3 foo.py`
|
||||
- PHP `php foo.php`
|
||||
- Rust `rustc -O -o /out/foo /in/foo.rs`
|
||||
- Haskell `ghc -O -outputdir /tmp -o /out/foo /in/foo.hs`
|
||||
@@ -1,13 +0,0 @@
|
||||
[
|
||||
"compiler",
|
||||
"limits",
|
||||
"io",
|
||||
"status",
|
||||
"ce",
|
||||
"training",
|
||||
"contest",
|
||||
"acratio",
|
||||
"rp",
|
||||
"dataformat",
|
||||
"lostpass"
|
||||
]
|
||||
@@ -1,8 +0,0 @@
|
||||
# Contest
|
||||
|
||||
按照赛制不同,有不同的递交、排名规则。
|
||||
OI 赛制所有题目均以最后一次递交为准,特别地,请避免编译错误。
|
||||
OI 赛制排名规则为:总分高的排在前面,总分相等则排名相同。
|
||||
ACM/ICPC 赛制所有题目递交后立即评测,以是否通过为准。
|
||||
ACM/ICPC 赛制排名规则为:通过题目数多的排在前面,通过题目数相同的做题耗时(含罚时)少的排在前。
|
||||
时间与空间限制以题目说明为准,默认限制参见[Limitations](#Limits)。
|
||||
@@ -1,3 +0,0 @@
|
||||
# Dataset Format
|
||||
|
||||
TODO
|
||||
@@ -1,3 +0,0 @@
|
||||
# IO
|
||||
|
||||
若无特殊说明,Hydro 使用标准输入输出(控制台输入输出,屏幕输入输出,STD I/O)。
|
||||
@@ -1,4 +0,0 @@
|
||||
# Limitations
|
||||
|
||||
Hydro 评测机使用进程的CPU时间计算时间消耗,时间的限定为题目中评测点所指定的时间。
|
||||
Hydro 评测机使用进程虚拟内存与物理内存总和计算内存空间消耗。内存空间默认限定为256MiB,题目中特别指明的,限定为题目中评测点所指定的内存空间。
|
||||
@@ -1,4 +0,0 @@
|
||||
# Forgot Password and/or Username
|
||||
|
||||
如果您无法登录,请仔细想想,是不是用户名记错了。比如,自己原本想要注册的用户名已经被注册,所以使用了一个带有前和/或后缀的用户名。
|
||||
如果您确信您的账号被盗或者忘记了账号和/或密码,请及时[{{ _('Reset Password or Find Username') }}](/lostpass)。
|
||||
@@ -1,6 +0,0 @@
|
||||
# RP
|
||||
|
||||
Hydro RP 分为固定 RP 与浮动 RP ,固定 RP 可由活动、比赛等的奖励获得,浮动 RP 由一般性通过题目获得。
|
||||
浮动 RP 是一个动态的数值,每个用户在每道题上获得的 RP 都不一样,并且未来也不固定(即浮动之意)。
|
||||
|
||||
<blockquote class="note">每道题的浮动 RP 由该题通过总人数与该用户通过此题的名次计算得来。</blockquote>
|
||||
@@ -1,17 +0,0 @@
|
||||
# Judge Status
|
||||
|
||||
- <span class="record-status--text pending">Waiting</span> 评测:评测请求正在等待被评测机抓取
|
||||
- <span class="record-status--text progress">Fetched</span> 评测:评测请求已被评测机抓取,正在准备开始评测
|
||||
- <span class="record-status--text progress">Compiling</span> 评测:正在编译中
|
||||
- <span class="record-status--text progress">Judging</span> 评测:编译成功,正在评测中
|
||||
- <span class="record-status--text pass">Accepted</span> 通过:程序输出完全正确
|
||||
- <span class="record-status--text fail">Wrong Answer</span> 不通过:程序输出与标准答案不一致(不包括行末空格以及文件末空行)
|
||||
- <span class="record-status--text fail">Time Exceeded</span> 不通过:程序运行时间超过了题目限制
|
||||
- <span class="record-status--text fail">Memory Exceeded</span> 不通过:程序运行内存空间超过了题目限制
|
||||
- <span class="record-status--text fail">Runtime Error</span> 不通过:程序运行时错误(如数组越界、被零除、运算溢出、栈溢出、无效指针等)
|
||||
- <span class="record-status--text fail">Compile Error</span> 不通过:编译失败
|
||||
- <span class="record-status--text fail">System Error</span> 错误:系统错误(如果您遇到此问题,请及时在讨论区进行反馈)
|
||||
- <span class="record-status--text ignored">Canceled</span> 其他:评测被取消
|
||||
- <span class="record-status--text fail">Unknown Error</span> 其他:未知错误
|
||||
|
||||
<blockquote class="note">有“成绩取消”字样则说明管理员手动标记此记录为取消,可能违反了服务条款,比如代码被发现与其他用户的代码十分相似。</blockquote>
|
||||
@@ -1,3 +0,0 @@
|
||||
# Training
|
||||
|
||||
我们精心挑选了一些题目组成了训练计划。单击导航栏的“训练”即可进入!
|
||||
@@ -19,7 +19,7 @@
|
||||
<ol class="menu">
|
||||
{{ sidemenu.render_item('info', 'wiki_about', '/wiki/about') }}
|
||||
{{ sidemenu.render_item('help', 'wiki_help', '/wiki/help') }}
|
||||
{{ sidemenu.render_item('help', 'wiki_gettingstarted', '/wiki/gettingstarted') }}
|
||||
{{ sidemenu.render_item('help', 'wiki_deploy', '/wiki/deploy') }}
|
||||
{{ sidemenu.render_item('help', 'wiki_development', '/wiki/development') }}
|
||||
</ol>
|
||||
</div>
|
||||
@@ -1,4 +1,28 @@
|
||||
# Terms of Service
|
||||
# Privacy | privacy
|
||||
|
||||
#### 1. 收集的信息
|
||||
|
||||
我们收集信息是为了向所有用户提供更好的服务。我们有两种信息收集方式:
|
||||
s
|
||||
- 您向我们提供信息。在您注册 Hydro 帐户时,我们会要求您提供个人信息,例如您的电子邮件地址、QQ号码等。
|
||||
- 我们在您使用服务的过程中获取信息。我们会收集关于您使用的服务以及使用方式的信息,例如您在何时使用了我们服务。
|
||||
|
||||
#### 2. 如何使用收集到的信息
|
||||
|
||||
我们利用从所有服务中收集的信息来提供、维护、保护和改进这些服务,同时开发新的服务并保护 Hydro 以及用户的隐私。
|
||||
当我们要将信息用于本隐私权政策未载明的其它用途时,则会事先征求您的同意。
|
||||
|
||||
#### 3. 访问和更新您的个人信息
|
||||
|
||||
无论您在何时使用我们的服务,我们都力求让您能够访问自己的个人信息。如果这些信息有误,我们会努力通过各种方式让您快速更新信息或删除信息。在更新您的个人信息时,我们可能会要求您先验证自己的身份,然后再处理您的请求。
|
||||
我们力求对服务进行完善的维护,以保护信息免遭意外或恶意的破坏。因此,当您从我们的服务中删除信息后,我们可能不会立即从在用的服务器中删除这些信息的残留副本,也可能不会从备份系统中删除相应的信息。
|
||||
|
||||
#### 4. 信息安全
|
||||
|
||||
我们为您提供SSL加密访问服务,您可以通过SSL(https)使用我们的服务,这可以很大程度上保障在传输过程中您信息的安全。
|
||||
对于敏感数据(如您的密码),我们承诺在存储时进行高强度不可逆加密。Hydro 的管理员、维护人员等均不能够访问到敏感数据的明文,所有操作均无人工介入。
|
||||
|
||||
# Terms of Service | tos
|
||||
|
||||
#### 0. 欢迎使用 Hydro
|
||||
|
||||
@@ -58,3 +82,27 @@
|
||||
#### 9. 其他
|
||||
|
||||
如果您对这个协议或我们的服务有意见或建议,可与我们联系,我们会给予您必要的帮助。
|
||||
|
||||
# Discussion: Terms Of Service | discussion
|
||||
|
||||
为了更好地发挥讨论、题解的积极作用,使广大用户学到知识、获得利益,进一步规范讨论和题解功能的使用,我们制定了《讨论和题解版规》(简称《版规》)。您在发布(或回复)讨论和题解时,即代表您已充分阅读、理解、接受并保证遵守此版规。
|
||||
您在发布(或回复)讨论和题解或使用相关功能时须遵守以下规定:
|
||||
|
||||
- 第一次使用编辑器前,要先阅读编辑器快速入门和 Markdown 详细帮助。
|
||||
- 不得将讨论、题解混淆。例如,不得将题解发布到讨论中,题解应发布在相应题目的题解区中。
|
||||
- 发布(或回复)的所有内容不得包含会干扰 Hydro 用户界面呈现的相关内容。
|
||||
- 发布(或回复)的所有内容不得包含恶意代码和指向恶意网站或 Hydro 明确禁止的网站的链接。
|
||||
- 特别地,发布(或回复)含有代码的内容时,应当将代码高亮。一个简单的方法是选中代码块然后按下 Tab 键。
|
||||
- 发布的题解禁止只包含无详细注释的代码。题解中难以理解的代码应当有尽可能详细的注释。
|
||||
- 打分、投票和评价应当客观。例如,对于题解的打分、投票和评价应当关注于题解本身的质量。
|
||||
- 我们欢迎原创作品,并会对其作者给予数量不等的 RP 奖励。
|
||||
|
||||
您在发布、回复讨论和题解时还须遵守法律法规,不得发布违法违规内容,包括但不限于:
|
||||
|
||||
- 危害国家安全统一、破坏社会稳定、违反公序良俗、侮辱、诽谤、淫秽、暴力以及任何违反国家法律法规的内容;
|
||||
- 侵害他人知识产权、商业秘密等合法权利的内容;
|
||||
- 恶意虚构事实、隐瞒真相以误导、欺骗他人的内容;
|
||||
- 广告信息及垃圾信息;
|
||||
- 其他法律法规禁止的内容。
|
||||
|
||||
对于违反《版规》的,我们将进行警告并删除相关内容、临时冻结用户、永久冻结用户等操作。
|
||||
@@ -0,0 +1,33 @@
|
||||
# Introduction | introduction
|
||||
|
||||
为什么使用 Hydro ?
|
||||
|
||||
- 安全:使用 cgroup 进行隔离,杜绝卡评测;
|
||||
- 高效:Hydro 使用了沙箱复用技术,拥有极高的评测效率;
|
||||
- 扩展:Hydro 支持安装额外模块进行扩展;
|
||||
- 强大:配合 Judger 模块(或 HydroJudger 独立评测机),可支持 spj,交互题,提交答案题,文件IO等多种特性;
|
||||
- 简便:提供了多种迁移脚本,可从 Vijos 等快速升级至 Hydro;
|
||||
- 自定:所有权限节点均可自由设置;
|
||||
- 社区:Hydro 正在持续维护中;
|
||||
|
||||
# Deployment | deployment
|
||||
|
||||
Hydro 依赖于 MongoDB 与 NodeJS,您应该先安装它们。
|
||||
|
||||
提示:推荐使用 [nvm](https://nvm.sh/) 安装 NodeJS。
|
||||
|
||||
clone 本项目到一个空文件夹,并进行编译:
|
||||
|
||||
```sh
|
||||
git clone https://github.com/hydro-dev/Hydro.git
|
||||
cd Hydro
|
||||
yarn build:all
|
||||
node hydro/loader.js
|
||||
```
|
||||
|
||||
注意:单个Hydro实例需要约100MB的运行内存,但在载入时可能需要较多内存(取决于安装的模块数量与大小)
|
||||
|
||||
Hydro 会自行初始化并监听 8888 端口。请用浏览器访问并进行相应配置。
|
||||
数据库配置完成后,会自动创建 Root 用户。(账号 `root` ,密码 `rootroot`),请及时修改。
|
||||
|
||||
之后的进阶配置可在 管理 面板进行。
|
||||
@@ -0,0 +1,194 @@
|
||||
# Basic | basic
|
||||
|
||||
Hydro 后端使用 NodeJS 编写,前端使用 JQuery + React。
|
||||
代码风格遵循 airbnb 标准(详见 .eslintrc.js)。
|
||||
|
||||
由于模块中不能使用 require() 引入 Hydro 的文件,因此需要从 global.Hydro 中取出需要的模块。
|
||||
例:
|
||||
|
||||
```js
|
||||
const { db } = global.Hydro.service;
|
||||
const { problem } = global.Hydro.model;
|
||||
```
|
||||
|
||||
# Module | module
|
||||
|
||||
## 文件架构
|
||||
|
||||
Hydro 的模块由以下几个部分组成:
|
||||
|
||||
service: 服务
|
||||
script: 脚本
|
||||
handler: 访问路由
|
||||
lib: 库
|
||||
model: 数据库模型
|
||||
file: 额外文件
|
||||
locale: 多国化
|
||||
template: UI 模板
|
||||
README.md: 介绍
|
||||
hydro.json: 声明文件(必须)
|
||||
|
||||
## 模块编译
|
||||
|
||||
使用 `hydro-build` 进行编译。
|
||||
安装:`yarn add hydro-build -D`
|
||||
编译:`hydro-build`
|
||||
如果命运的齿轮没有出差错,您应该可以找到生成的.hydro文件了。
|
||||
|
||||
# Hydro.json | hydro
|
||||
|
||||
Hydro.json 是模块的声明文件,格式如下。
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "模块ID",
|
||||
"version": "模块版本",
|
||||
"description": "模块描述"
|
||||
}
|
||||
```
|
||||
|
||||
# Handler | handler
|
||||
|
||||
通常用于提供页面路由。
|
||||
|
||||
例:注册新路由:
|
||||
|
||||
```js
|
||||
const { Handler, Route } = global.Hydro.service.server;
|
||||
const { user } = global.Hydro.model;
|
||||
const { PERM_LOGGEDIN } = global.Hydro.permission;
|
||||
|
||||
class CustomHandler extends Handler {
|
||||
async prepare() {
|
||||
this.checkPassword(PERM_LOGGEDIN);
|
||||
}
|
||||
|
||||
async get({ username, password }) {
|
||||
const udoc = await user.getByUname(username);
|
||||
udoc.checkPassword(password);
|
||||
this.response.body = { udoc };
|
||||
}
|
||||
|
||||
async post() {
|
||||
// 当提交表单时会执行该函数
|
||||
}
|
||||
|
||||
async postConfirm() {
|
||||
// 当提交表单并存在 operation 值为 confirm 时执行。
|
||||
}
|
||||
}
|
||||
|
||||
async function apply() {
|
||||
Route('/route/:username', CustomHandler);
|
||||
}
|
||||
|
||||
global.Hydro.handler.handlerName = module.exports = apply;
|
||||
```
|
||||
|
||||
在路由中定义所有的函数应均为异步函数,支持的函数如下:
|
||||
|
||||
_prepare, prepare, get, post, post[Operation], cleanup, _cleanup
|
||||
|
||||
具体流程如下:
|
||||
|
||||
先执行 _prepare(args) (如果存在)
|
||||
args 为传入的参数集合(包括 QueryString, Body, Path)中的全部参数,并对以下字段进行了校验:
|
||||
|
||||
| 名称 | 类型 |
|
||||
| :------: | :-----------: |
|
||||
| content | string |
|
||||
| title | string |
|
||||
| uid | number(int) |
|
||||
| password | string |
|
||||
| mail | string(mail) |
|
||||
| uname | string |
|
||||
| page | number(int) |
|
||||
| duration | number(float) |
|
||||
| role | string |
|
||||
| roles | string[] |
|
||||
| pids | string |
|
||||
| tid | bson.ObjectID |
|
||||
| rid | bson.ObjectID |
|
||||
| did | bson.ObjectID |
|
||||
| drid | bson.ObjectID |
|
||||
| drrid | bson.ObjectID |
|
||||
| psid | bson.ObjectID |
|
||||
| psrid | bson.ObjectID |
|
||||
| docId | bson.ObjectID |
|
||||
| mongoId | bson.ObjectID |
|
||||
|
||||
再执行 prepare(args) (如果存在)
|
||||
检查请求类型:
|
||||
|
||||
```
|
||||
为 GET ?
|
||||
-> 执行 get(args)
|
||||
为 POST ?
|
||||
-> 执行 post(args)
|
||||
-> 含有 operation 字段?
|
||||
-> 执行 post[Operation]
|
||||
```
|
||||
|
||||
执行 cleanup()
|
||||
执行 _cleanup()
|
||||
|
||||
如果在 this.response.template 指定模板则渲染,否则直接返回 this.response.body 中的内容。
|
||||
|
||||
* 在表单提交时的 operation 字段使用下划线,函数名使用驼峰命名。
|
||||
|
||||
如 `<input type="hidden" name="operation" value="confirm_delete">` 对应 `postConfirmDelete` 函数。
|
||||
|
||||
应当提供 `apply` 函数,并与定义的 Handler 一同挂载到 `global.Hydro.handler[模块名]` 位置。
|
||||
`apply` 函数将在初始化阶段被调用。
|
||||
|
||||
# Service | service
|
||||
|
||||
通常用于提供与其他程序对接的接口或启动其他外部程序。(如内置的 MongoDB / 外置的沙箱模块等)
|
||||
|
||||
# Lib | lib
|
||||
|
||||
库文件。通常用于提供一些功能(废话)。
|
||||
|
||||
# File | file
|
||||
|
||||
file 文件夹下的所有文件将被自动解压到 `$TMPDIR/hydro/模块ID/路径` 的位置(权限755,通常用于启动子进程)。
|
||||
|
||||
# Locale | locale
|
||||
|
||||
用于提供多国翻译。格式与 Hydro 的 locale 文件夹格式相同。
|
||||
|
||||
# Template | template
|
||||
|
||||
页面模板,使用 [nunjucks](https://mozilla.github.io/nunjucks/cn/templating.html) 语法。
|
||||
传入了 _ 翻译函数与 model 等。
|
||||
|
||||
```html
|
||||
{% set page_name = "page_name" %}
|
||||
{% extends "layout/basic.html" %}
|
||||
{% block content %}
|
||||
<div class="error__container clearfix">
|
||||
<div class="error__icon-container">
|
||||
<div class="error__twd2"></div>
|
||||
</div>
|
||||
<div class="error__text-container">
|
||||
<h1>{{ _('Oops!') }}</h1>
|
||||
<p>{{ _(error.message).format(error.params) }}</p>
|
||||
<p>{{ _('Technical Information') }}:</p>
|
||||
<p>{{ _('Type') }}: {{ error.code }}</p>
|
||||
<p>{{ _('Arguments') }}:
|
||||
<ol>
|
||||
{% for param in error.params %}
|
||||
<li>{{ param }}</li>
|
||||
{% endfor %}
|
||||
</ol>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
```
|
||||
|
||||
<blockquote class="note">请不要覆盖已有模板。</blockquote>
|
||||
|
||||
# README.md | readme
|
||||
|
||||
项目的说明文件。
|
||||
@@ -0,0 +1,94 @@
|
||||
# Compilers' Version and Parameters
|
||||
|
||||
Hydro使用 [HydroJudger](https://github.com/hydro-dev/HydroJudger) 进行评测,以docker镜像的形式安装至评测机。
|
||||
所使用的编译器均为创建镜像时 [debian testing](https://wiki.debian.org/DebianTesting) 分支的最新版。编译参数如下:
|
||||
|
||||
- Free Pascal `fpc -O2 -o/out/foo /in/foo.pas`
|
||||
- C `gcc -O2 -Wall -std=c99 -o /out/foo /in/foo.c -lm`
|
||||
- C++ `g++ -O2 -Wall -std=c++11 -o /out/foo /in/foo.cc -lm`
|
||||
- Java `javac Main.java`
|
||||
- Python `python foo.py`
|
||||
- Python 3 `python3 foo.py`
|
||||
- PHP `php foo.php`
|
||||
- Rust `rustc -O -o /out/foo /in/foo.rs`
|
||||
- Haskell `ghc -O -outputdir /tmp -o /out/foo /in/foo.hs`
|
||||
|
||||
# Limitations
|
||||
|
||||
Hydro 评测机使用进程的CPU时间计算时间消耗,时间的限定为题目中评测点所指定的时间。
|
||||
Hydro 评测机使用进程虚拟内存与物理内存总和计算内存空间消耗。内存空间默认限定为256MiB,题目中特别指明的,限定为题目中评测点所指定的内存空间。
|
||||
|
||||
# IO
|
||||
|
||||
若无特殊说明,Hydro 使用标准输入输出(控制台输入输出,屏幕输入输出,STD I/O)。
|
||||
|
||||
# Judge Status
|
||||
|
||||
- <span class="record-status--text pending">Waiting</span> 评测:评测请求正在等待被评测机抓取
|
||||
- <span class="record-status--text progress">Fetched</span> 评测:评测请求已被评测机抓取,正在准备开始评测
|
||||
- <span class="record-status--text progress">Compiling</span> 评测:正在编译中
|
||||
- <span class="record-status--text progress">Judging</span> 评测:编译成功,正在评测中
|
||||
- <span class="record-status--text pass">Accepted</span> 通过:程序输出完全正确
|
||||
- <span class="record-status--text fail">Wrong Answer</span> 不通过:程序输出与标准答案不一致(不包括行末空格以及文件末空行)
|
||||
- <span class="record-status--text fail">Time Exceeded</span> 不通过:程序运行时间超过了题目限制
|
||||
- <span class="record-status--text fail">Memory Exceeded</span> 不通过:程序运行内存空间超过了题目限制
|
||||
- <span class="record-status--text fail">Runtime Error</span> 不通过:程序运行时错误(如数组越界、被零除、运算溢出、栈溢出、无效指针等)
|
||||
- <span class="record-status--text fail">Compile Error</span> 不通过:编译失败
|
||||
- <span class="record-status--text fail">System Error</span> 错误:系统错误(如果您遇到此问题,请及时在讨论区进行反馈)
|
||||
- <span class="record-status--text ignored">Canceled</span> 其他:评测被取消
|
||||
- <span class="record-status--text fail">Unknown Error</span> 其他:未知错误
|
||||
|
||||
<blockquote class="note">有“成绩取消”字样则说明管理员手动标记此记录为取消,可能违反了服务条款,比如代码被发现与其他用户的代码十分相似。</blockquote>
|
||||
|
||||
# Compile Error
|
||||
|
||||
可能有以下情况:
|
||||
|
||||
- 递交时选错了编程语言
|
||||
- Java 的主类名没有使用 "Main"
|
||||
- 对于 C/C++:见下
|
||||
- 一般性的编译错误
|
||||
|
||||
<blockquote class="warn">
|
||||
对 C/C++ 选手的特别提醒:
|
||||
<ul>
|
||||
<li>1. __int64 在 GNU C++ 中应写成 long long 类型</li>
|
||||
<li>2. main() 返回值必须定义为 int ,而不是 void</li>
|
||||
<li>3. for 语句中的指标变量 i 将会在如"for (int i = 0...) {...}"语句之后变为无效</li>
|
||||
<li>4. itoa 不是一个通用 ANSI 函数(标准 C/C++ 中无此函数)</li>
|
||||
<li>5. printf 中使用 %lf 格式是不正确的</li>
|
||||
</ul>
|
||||
</blockquote>
|
||||
|
||||
# Training
|
||||
|
||||
我们精心挑选了一些题目组成了训练计划。单击导航栏的“训练”即可进入!
|
||||
|
||||
# Contest
|
||||
|
||||
按照赛制不同,有不同的递交、排名规则。
|
||||
OI 赛制所有题目均以最后一次递交为准,特别地,请避免编译错误。
|
||||
OI 赛制排名规则为:总分高的排在前面,总分相等则排名相同。
|
||||
ACM/ICPC 赛制所有题目递交后立即评测,以是否通过为准。
|
||||
ACM/ICPC 赛制排名规则为:通过题目数多的排在前面,通过题目数相同的做题耗时(含罚时)少的排在前。
|
||||
时间与空间限制以题目说明为准,默认限制参见[Limitations](#Limits)。
|
||||
|
||||
# Accepted Ratio
|
||||
|
||||
通过率的影响极其恶劣,Hydro 不提供也不承认通过率。
|
||||
|
||||
# RP
|
||||
|
||||
Hydro RP 分为固定 RP 与浮动 RP ,固定 RP 可由活动、比赛等的奖励获得,浮动 RP 由一般性通过题目获得。
|
||||
浮动 RP 是一个动态的数值,每个用户在每道题上获得的 RP 都不一样,并且未来也不固定(即浮动之意)。
|
||||
|
||||
<blockquote class="note">每道题的浮动 RP 由该题通过总人数与该用户通过此题的名次计算得来。</blockquote>
|
||||
|
||||
# Dataset Format
|
||||
|
||||
TODO
|
||||
|
||||
# Forgot Password and/or Username
|
||||
|
||||
如果您无法登录,请仔细想想,是不是用户名记错了。比如,自己原本想要注册的用户名已经被注册,所以使用了一个带有前和/或后缀的用户名。
|
||||
如果您确信您的账号被盗或者忘记了账号和/或密码,请及时[{{ _('Reset Password or Find Username') }}](/lostpass)。
|
||||
Reference in new issue
Block a user