diff --git a/.gitignore b/.gitignore index 6dde01110..14c1d85f6 100644 --- a/.gitignore +++ b/.gitignore @@ -1,8 +1,10 @@ node_modules/ config.yaml .build/ +*.build .uibuild/ .cache/ +*.cache __* ui/misc/.iconfont ui/static/locale diff --git a/build/buildModule.js b/build/buildModule.js index f5679bfd8..0f3e95efe 100644 --- a/build/buildModule.js +++ b/build/buildModule.js @@ -44,6 +44,12 @@ const build = async (type) => { } } const compiler = webpack(config); + for (const i of modules) { + if (exist(`module/${i}/build.js`)) { + const builder = require(root(`module/${i}/build.js`)); + if (builder.prebuild) await builder.prebuild(); + } + } await new Promise((resolve, reject) => { compiler.run((err, stats) => { if (err) { @@ -67,11 +73,7 @@ const build = async (type) => { } current.locale = lang; } - if (exist(`module/${i}/template.build.js`)) { - const builder = require(root(`module/${i}/template.build.js`)); - const [templates, exclude] = await builder.prebuild(); - current.template = template(templates, exclude); - } else if (exist(`module/${i}/template`)) { + if (exist(`module/${i}/template`)) { current.template = template(`module/${i}/template`); } if (exist(`module/${i}/model.js`)) { @@ -80,31 +82,12 @@ const build = async (type) => { if (exist(`module/${i}/handler.js`)) { current.handler = fs.readFileSync(root(`.build/module/${i}/handler.js`)).toString(); } + const m = require(root(`module/${i}/hydro.json`)); + current.description = m.description || ''; + current.requirements = m.requirements || []; + current.version = m.version || 'unknown'; const data = zlib.gzipSync(Buffer.from(yaml.safeDump(current)), { level: 3 }); - fs.writeFileSync(root(`.build/module/${i}.hydro-module`), data); - } - } - for (const i of modules) { - if (!i.startsWith('.')) { - if (exist(`module/${i}/locale`)) { - const locales = fs.readdirSync(root(`module/${i}/locale`)); - const lang = {}; - for (const j of locales) { - const content = fs.readFileSync(root(`module/${i}/locale/${j}`)).toString(); - lang[j.split('.')[0]] = yaml.safeLoad(content); - } - const file = root(`.build/module/${i}/locale.json`); - fs.writeFileSync(file, JSON.stringify(lang)); - } - if (exist(`module/${i}/template.build.js`)) { - const builder = require(root(`module/${i}/template.build.js`)); - const [templates, exclude] = await builder.prebuild(); - const file = root(`.build/module/${i}/template.yaml`); - fs.writeFileSync(file, yaml.safeDump(template(templates, exclude))); - } else if (exist(`module/${i}/template`)) { - const file = root(`.build/module/${i}/template.yaml`); - fs.writeFileSync(file, yaml.safeDump(template(`module/${i}/template`))); - } + fs.writeFileSync(root(`.build/module/${i}.hydro`), data); } } }; diff --git a/build/index.js b/build/index.js index d9b266e59..3e2b80090 100644 --- a/build/index.js +++ b/build/index.js @@ -23,7 +23,7 @@ async function build(type) { builtin.locale = lang; builtin.template = template('templates', exclude); const data = zlib.gzipSync(Buffer.from(yaml.safeDump(builtin)), { level: 3 }); - fs.writeFileSync(root('.build/module/builtin.hydro-module'), data); + fs.writeFileSync(root('.build/module/builtin.hydro'), data); await require('./buildModule')(type); await require('./webpack')(type); } diff --git a/hydro/lib/hpm.js b/hydro/lib/hpm.js index 8c1d60da6..74e337572 100644 --- a/hydro/lib/hpm.js +++ b/hydro/lib/hpm.js @@ -15,7 +15,7 @@ async function getInstalled() { const files = fs.readdirSync(root('.build/module')); const installed = []; for (const file of files) { - if (file.endsWith('.hydro-module')) { + if (file.endsWith('.hydro')) { const f = fs.readFileSync(root(`.build/module/${file}`)); const s = fs.statSync(root(`.build/module/${file}`)); installed.push({ @@ -29,11 +29,11 @@ async function getInstalled() { } async function del(id) { - fs.unlinkSync(root(`.build/module/${id}.hydro-module`)); + fs.unlinkSync(root(`.build/module/${id}.hydro`)); } async function install(id, url) { - await download(url, root(`module/${id}.hydro-module`)); + await download(url, root(`module/${id}.hydro`)); } module.exports = { getInstalled, del, install }; diff --git a/hydro/lib/i18n.js b/hydro/lib/i18n.js index 6dd42558a..c707f318d 100644 --- a/hydro/lib/i18n.js +++ b/hydro/lib/i18n.js @@ -1,4 +1,4 @@ -const locales = require('../../.build/locales.json'); +const locales = {}; String.prototype.format = function formatStr(...args) { let result = this; diff --git a/hydro/lib/markdown.js b/hydro/lib/markdown.js index b3e8ccfc0..cb67876df 100644 --- a/hydro/lib/markdown.js +++ b/hydro/lib/markdown.js @@ -7,7 +7,7 @@ const loadLanguages = require('prismjs/components/'); loadLanguages(['js', 'javascript', 'go', 'c', 'pascal', 'hs', 'java', 'cs', 'cpp', 'py', 'ruby']); class Markdown extends MarkdownIt { - constructor() { + constructor(safe) { super({ linkify: true, highlight(str, lang) { @@ -18,9 +18,13 @@ class Markdown extends MarkdownIt { } return ''; }, + html: !safe, }); this.linkify.tlds('.py', false); this.use(katex); } } -module.exports = new Markdown(); +module.exports = { + unsafe: new Markdown(false), + safe: new Markdown(true), +}; diff --git a/hydro/lib/template.js b/hydro/lib/template.js index 05aab58f8..622b0c37b 100644 --- a/hydro/lib/template.js +++ b/hydro/lib/template.js @@ -19,7 +19,10 @@ class Nunjucks extends nunjucks.Environment { super(new Loader(), { autoescape: true, trimBlocks: true }); this.addFilter('json', (self) => JSON.stringify(self), false); this.addFilter('assign', (self, data) => Object.assign(self, data)); - this.addFilter('markdown', (self) => markdown.render(self)); + this.addFilter('markdown', (self, safe = true) => { + if (safe) return markdown.safe.render(self); + return markdown.unsafe.render(self); + }); this.addFilter('base64_encode', (s) => Buffer.from(s).toString('base64')); } } diff --git a/hydro/loader.js b/hydro/loader.js index 24a7c2430..f2250a0a4 100644 --- a/hydro/loader.js +++ b/hydro/loader.js @@ -15,7 +15,7 @@ const active = []; async function preload() { const files = fs.readdirSync(root('.build/module')); for (const file of files) { - if (file.endsWith('.hydro-module')) { + if (file.endsWith('.hydro')) { const f = fs.readFileSync(root(`.build/module/${file}`)); active.push({ ...yaml.safeLoad(zlib.gunzipSync(f)), id: file.split('.')[0] }); } diff --git a/module/contest-rule-basic/hydro.json b/module/contest-rule-basic/hydro.json index 1260c440b..f1f7c1d84 100644 --- a/module/contest-rule-basic/hydro.json +++ b/module/contest-rule-basic/hydro.json @@ -1,4 +1,5 @@ { "name": "contest-rule-basic", - "version": "1.0.0" + "version": "1.0.0", + "description": "Provide contest rules: ACM/ICPC and OI." } \ No newline at end of file diff --git a/module/contest-rule-basic/locale/zh_CN.yaml b/module/contest-rule-basic/locale/zh_CN.yaml new file mode 100644 index 000000000..102f39267 --- /dev/null +++ b/module/contest-rule-basic/locale/zh_CN.yaml @@ -0,0 +1 @@ +'Provide contest rules: ACM/ICPC and OI.': 提供ACM和OI赛制。 \ No newline at end of file diff --git a/module/module-pastebin/hydro.json b/module/module-pastebin/hydro.json index f16925e6a..5150b533d 100644 --- a/module/module-pastebin/hydro.json +++ b/module/module-pastebin/hydro.json @@ -1,4 +1,5 @@ { "name": "module-pastebin", - "version": "1.0.0" + "version": "1.0.0", + "description": "Provide pastebin service." } \ No newline at end of file diff --git a/module/module-pastebin/locale/zh_CN.yaml b/module/module-pastebin/locale/zh_CN.yaml index 353817be6..463340a17 100644 --- a/module/module-pastebin/locale/zh_CN.yaml +++ b/module/module-pastebin/locale/zh_CN.yaml @@ -1,3 +1,4 @@ pastebin: 剪贴板 paste_create: 创建新内容 paste_show: 查看内容 +Provide pastebin service.: 提供云剪贴板服务。 diff --git a/module/problem-import-syzoj/README.md b/module/problem-import-syzoj/README.md new file mode 100644 index 000000000..0e32aed8f --- /dev/null +++ b/module/problem-import-syzoj/README.md @@ -0,0 +1,5 @@ +# Problem-Import-Syzoj + +从运行 syzoj 系统的 OJ 导入题目。 + +使用方式:题目->导入题目(`/problem/import`)->选择类型:syzoj diff --git a/module/problem-import-syzoj/hydro.json b/module/problem-import-syzoj/hydro.json index 4e49ed6b6..2a1f604ed 100644 --- a/module/problem-import-syzoj/hydro.json +++ b/module/problem-import-syzoj/hydro.json @@ -1,4 +1,5 @@ { "name": "problem-import-syzoj", - "version": "1.0.0" + "version": "1.0.0", + "description": "Import problem from syzoj." } \ No newline at end of file diff --git a/module/problem-import-syzoj/locale/zh_CN.yaml b/module/problem-import-syzoj/locale/zh_CN.yaml new file mode 100644 index 000000000..af79dab04 --- /dev/null +++ b/module/problem-import-syzoj/locale/zh_CN.yaml @@ -0,0 +1 @@ +Import problem from syzoj.: 从运行 syzoj 系统的 OJ 导入题目。 \ No newline at end of file diff --git a/module/wiki/build.js b/module/wiki/build.js new file mode 100644 index 000000000..af71ce6a5 --- /dev/null +++ b/module/wiki/build.js @@ -0,0 +1,24 @@ +const fs = require('fs'); +const path = require('path'); + +const root = (name) => path.resolve(__dirname, name); + +exports.prebuild = () => { + 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)); +}; diff --git a/module/wiki/handler.js b/module/wiki/handler.js index 1ee29bc85..f655ca37a 100644 --- a/module/wiki/handler.js +++ b/module/wiki/handler.js @@ -1,34 +1,28 @@ const { Route, Handler } = global.Hydro.service.server; +const { NotFoundError } = global.Hydro.error; +// eslint-disable-next-line import/no-unresolved +const pages = require('./__build.json'); -class WikiHelpHandler extends Handler { - async get() { +class WikiHandler extends Handler { + async get({ name }) { + if (!pages[name]) throw new NotFoundError(name); + const contents = pages[name]; const path = [ ['Hydro', '/'], ['wiki', '/wiki'], - ['wiki_help', null], + [`wiki_${name}`, null], ]; - this.response.body = { path }; - this.response.template = 'wiki_help.html'; - } -} - -class WikiAboutHandler extends Handler { - async get() { - const path = [ - ['Hydro', '/'], - ['wiki', '/wiki'], - ['wiki_about', null], - ]; - this.response.body = { path }; - this.response.template = 'wiki_about.html'; + this.response.body = { + path, contents, page_name: `wiki_${name}`, + }; + this.response.template = 'wiki.html'; } } async function apply() { - Route('/wiki/help', module.exports.WikiHelpHandler); - Route('/wiki/about', module.exports.WikiAboutHandler); + Route('/wiki/:name', module.exports.WikiHandler); } global.Hydro.handler.wiki = module.exports = { - WikiHelpHandler, WikiAboutHandler, apply, + WikiHandler, apply, }; diff --git a/module/wiki/hydro.json b/module/wiki/hydro.json new file mode 100644 index 000000000..edab1e0e8 --- /dev/null +++ b/module/wiki/hydro.json @@ -0,0 +1,5 @@ +{ + "name": "wiki", + "version": "1.0.0", + "description": "Basic wiki module." +} \ No newline at end of file diff --git a/module/wiki/raw/about.yaml b/module/wiki/raw/about.yaml deleted file mode 100644 index 6ea844721..000000000 --- a/module/wiki/raw/about.yaml +++ /dev/null @@ -1,97 +0,0 @@ -data-heading-extract-to: '#menu-item-wiki_about' -section: -- id: privacy - title: Privacy - content: | - {{ _('no_translation_warn')|safe }} -
我们收集信息是为了向所有用户提供更好的服务。我们有两种信息收集方式:
-您向我们提供信息。在您注册 Hydro 帐户时,我们会要求您提供个人信息,例如您的电子邮件地址、QQ号码等。
-我们在您使用服务的过程中获取信息。我们会收集关于您使用的服务以及使用方式的信息,例如您在何时使用了我们服务。
-我们利用从所有服务中收集的信息来提供、维护、保护和改进这些服务,同时开发新的服务并保护 Hydro 以及用户的隐私。
-当我们要将信息用于本隐私权政策未载明的其它用途时,则会事先征求您的同意。
-无论您在何时使用我们的服务,我们都力求让您能够访问自己的个人信息。如果这些信息有误,我们会努力通过各种方式让您快速更新信息或删除信息。在更新您的个人信息时,我们可能会要求您先验证自己的身份,然后再处理您的请求。
-我们力求对服务进行完善的维护,以保护信息免遭意外或恶意的破坏。因此,当您从我们的服务中删除信息后,我们可能不会立即从在用的服务器中删除这些信息的残留副本,也可能不会从备份系统中删除相应的信息。
-我们为您提供SSL加密访问服务,您可以通过SSL(https)使用我们的服务,这可以很大程度上保障在传输过程中您信息的安全。
-对于敏感数据(如您的密码),我们承诺在存储时进行高强度不可逆加密。Hydro 的管理员、维护人员等均不能够访问到敏感数据的明文,所有操作均无人工介入。
-- id: tos - title: Terms of Service - content: | -注册 Hydro 帐户和/或使用 Hydro 提供的服务(包括网页提供的在线服务和题目评测的非在线服务等),即表示您已同意本条款。请您务必审慎阅读,充分理解条款各项内容。
-您必须遵守各项服务中提供的所有政策(包括但不限于讨论和题解的版规)。
-请勿滥用我们的服务。如,请勿干扰我们的服务,或尝试使用除我们提供的界面和指示以外的方法访问这些服务,或使用我们服务中出现的缺陷干扰其他网站或设施的正常运行。您仅能在法律允许的范围内使用我们的服务。
-您在使用我们服务时须遵守我们服务器所在地的法律法规,不得利用我们服务从事违法违规行为,包括但不限于:
-如果您违反了约定,相关国家相关机关或机构可能会对您提起诉讼、进行行政处罚或采取其他制裁措施,Hydro 将给于协助。造成损害的,您应依法予以赔偿,Hydro 不承担任何责任。
-如果 Hydro 发现或收到他人举报您发布的信息违反约定,Hydro 有权进行独立判断并采取技术手段予以删除、屏蔽或断开链接。同时,Hydro 有权视用户的行为性质,采取包括但不限于暂停或终止服务,限制、冻结或终止账户使用,追究法律责任等措施。
-使用我们的服务并不代表您拥有我们的服务或您所访问的内容的任何知识产权。网站上的所有材料(包括但不限于题目内容、用户界面、Wiki)版权均受保护,归 Hydro 所有。除非另有说明,本网站上的材料和服务仅用于个人和非商业用途,未经 Hydro 书面许可,不得复制、修改、创建衍生作品、传播、出版、公开演示、公开展示和分发从本网站获得的任何信息、文件、产品或服务。
-我们的某些服务允许您提交内容。您保留对该内容持有的任何知识产权的所有权。
-当您上传内容或通过其他方式向我们的服务提交内容时,您授予 Hydro 使用、持有、存储、复制、修改、创建衍生作品、传播、出版、公开演示、公开展示和分发此内容等权利。您在此许可中授予的权限,仅能用于运营、宣传和改进我们的服务,以及开发新的服务。该项许可在您停止使用我们的服务后依然有效。某些服务可能会向您提供一些方法,用于访问和删除您提供给该服务的内容。对于您提交至我们服务的任何内容,请确保您拥有向我们授予此许可的必要权利。我们有权在未通知您的情况下删除我们认为侵犯了知识产权或违反了相关法律法规的内容。
-您可以在 Hydro 上创建新题目。您上传到 Hydro 的题目,除了适用于本协议第三条(即“您在我们服务中发布的内容”)条款,还包含以下附加条款(若有冲突的条款,以附加条款中的优先):
-您上传到 Hydro 上的题目版权为 Hydro 和您共同拥有,我们会在相关页面或在对其进行分发、传播等操作时标明版权所有者。 -
Hydro 尊重他人知识产权和合法权益,请您在上传题目前确保拥有题目内容(包括但不限于题目描述、数据、图片等)的著作权及信息网络传播权或者已经取得上述全部权利人的许可并不存在任何著作权纠纷。Hydro有权在不通知的情况下删除被认为侵权的题目。 -
您可以申请将自己上传的优质题目合并到题库主干。我们的管理员会对您创建的题目的内容(包括但不限于评测数据等对用户不可见的信息)进行人工审核和适当修改以确认其符合国家基本法律法规。出于质量的考虑,我们也可能会拒绝您完全合法的合并到题库主干的请求。 -
我们会维护服务的稳定,并对数据(包括您递交的题目)进行定期的备份,并尽量在关闭服务前通知您,但我们仍然不对任何题目(包括主干和非主干)提供永久存储或保留的承诺,出于安全的考虑推荐您自行保留题目的内容。 -
您有权决定 Hydro 是否公开您上传的题目的数据。公开题目数据意味着 Hydro 上的用户均有权利获取到您递交的题目的所有评测数据,但相关版权协议仍然生效。
-Hydro 隐私声明介绍了您在使用我们的服务时,我们会如何处理您的个人数据和保护您的隐私。使用我们的服务即表示您同意 Hydro 可以按照我们的隐私权政策使用您的个人数据。
-我们始终在不断更改和改进我们的服务。我们可能会增加或删除功能,也可能暂停或彻底停止某项服务。
-您可以随时停止使用我们的服务,尽管我们对此表示非常遗憾。Hydro 也可能随时停止向您提供服务,或随时对我们的服务增加或设置新的限制。
-我们对服务内容、服务的具体功能,或其可靠性、可用性或满足您需要的能力不作任何承诺。我们的服务是按照现有技术和条件所能达到的现状提供的。我们会尽最大努力向您提供服务,确保服务的连贯性和安全性。但我们不能随时预见和防范法律、技术以及其他风险,包括但不限于不可抗力、病毒、木马、黑客攻击、系统不稳定、第三方服务瑕疵、政府行为等原因可能导致的服务中断、数据丢失以及其他的损失和风险。
-我们可以修改上述条款或任何适用于某项服务的附加条款,您应当定期查阅本条款。所有修改的适用不具有追溯力,且会在公布十四天或更长时间后方始生效。但是,对服务新功能的特别修改或由于法律原因所作的修改将立即生效。如果您不同意服务的修改条款,应停止使用服务。
-如果您对这个协议或我们的服务有意见或建议,可与我们联系,我们会给予您必要的帮助。
-- id: discuss - title: 'Discussion: Terms Of Service' - content: | -为了更好地发挥讨论、题解的积极作用,使广大用户学到知识、获得利益,进一步规范讨论和题解功能的使用,我们制定了《讨论和题解版规》(简称《版规》)。您在发布(或回复)讨论和题解时,即代表您已充分阅读、理解、接受并保证遵守此版规。
-您在发布(或回复)讨论和题解或使用相关功能时须遵守以下规定:
---第一次使用编辑器前,要先阅读编辑器快速入门和 Markdown 详细帮助。
-不得将讨论、题解混淆。例如,不得将题解发布到讨论中,题解应发布在相应题目的题解区中。
-发布(或回复)的所有内容不得包含会干扰 Hydro 用户界面呈现的相关内容。
-发布(或回复)的所有内容不得包含恶意代码和指向恶意网站或 Hydro 明确禁止的网站的链接。
-特别地,发布(或回复)含有代码的内容时,应当将代码高亮。一个简单的方法是选中代码块然后按下 Tab 键。
-发布的题解禁止只包含无详细注释的代码。题解中难以理解的代码应当有尽可能详细的注释。
-打分、投票和评价应当客观。例如,对于题解的打分、投票和评价应当关注于题解本身的质量。
-我们欢迎原创作品,并会对其作者给予数量不等的 RP 奖励。
-
您在发布、回复讨论和题解时还须遵守法律法规,不得发布违法违规内容,包括但不限于:
---危害国家安全统一、破坏社会稳定、违反公序良俗、侮辱、诽谤、淫秽、暴力以及任何违反国家法律法规的内容;
-侵害他人知识产权、商业秘密等合法权利的内容;
-恶意虚构事实、隐瞒真相以误导、欺骗他人的内容;
-广告信息及垃圾信息;
-其他法律法规禁止的内容。
-
对于违反《版规》的,我们将进行警告并删除相关内容、临时冻结用户、永久冻结用户等操作。
\ No newline at end of file diff --git a/module/wiki/raw/about/contents.json b/module/wiki/raw/about/contents.json new file mode 100644 index 000000000..8d99104f4 --- /dev/null +++ b/module/wiki/raw/about/contents.json @@ -0,0 +1,5 @@ +[ + "privacy", + "tos", + "discuss" +] \ No newline at end of file diff --git a/module/wiki/raw/about/discuss.md b/module/wiki/raw/about/discuss.md new file mode 100644 index 000000000..950b8ac83 --- /dev/null +++ b/module/wiki/raw/about/discuss.md @@ -0,0 +1,23 @@ +# Discussion: Terms Of Service + +为了更好地发挥讨论、题解的积极作用,使广大用户学到知识、获得利益,进一步规范讨论和题解功能的使用,我们制定了《讨论和题解版规》(简称《版规》)。您在发布(或回复)讨论和题解时,即代表您已充分阅读、理解、接受并保证遵守此版规。 +您在发布(或回复)讨论和题解或使用相关功能时须遵守以下规定: + +- 第一次使用编辑器前,要先阅读编辑器快速入门和 Markdown 详细帮助。 +- 不得将讨论、题解混淆。例如,不得将题解发布到讨论中,题解应发布在相应题目的题解区中。 +- 发布(或回复)的所有内容不得包含会干扰 Hydro 用户界面呈现的相关内容。 +- 发布(或回复)的所有内容不得包含恶意代码和指向恶意网站或 Hydro 明确禁止的网站的链接。 +- 特别地,发布(或回复)含有代码的内容时,应当将代码高亮。一个简单的方法是选中代码块然后按下 Tab 键。 +- 发布的题解禁止只包含无详细注释的代码。题解中难以理解的代码应当有尽可能详细的注释。 +- 打分、投票和评价应当客观。例如,对于题解的打分、投票和评价应当关注于题解本身的质量。 +- 我们欢迎原创作品,并会对其作者给予数量不等的 RP 奖励。 + +您在发布、回复讨论和题解时还须遵守法律法规,不得发布违法违规内容,包括但不限于: + +- 危害国家安全统一、破坏社会稳定、违反公序良俗、侮辱、诽谤、淫秽、暴力以及任何违反国家法律法规的内容; +- 侵害他人知识产权、商业秘密等合法权利的内容; +- 恶意虚构事实、隐瞒真相以误导、欺骗他人的内容; +- 广告信息及垃圾信息; +- 其他法律法规禁止的内容。 + +对于违反《版规》的,我们将进行警告并删除相关内容、临时冻结用户、永久冻结用户等操作。 \ No newline at end of file diff --git a/module/wiki/raw/about/privacy.md b/module/wiki/raw/about/privacy.md new file mode 100644 index 000000000..dfc47e071 --- /dev/null +++ b/module/wiki/raw/about/privacy.md @@ -0,0 +1,23 @@ +# Privacy + +#### 1. 收集的信息 + +我们收集信息是为了向所有用户提供更好的服务。我们有两种信息收集方式: +s +- 您向我们提供信息。在您注册 Hydro 帐户时,我们会要求您提供个人信息,例如您的电子邮件地址、QQ号码等。 +- 我们在您使用服务的过程中获取信息。我们会收集关于您使用的服务以及使用方式的信息,例如您在何时使用了我们服务。 + +#### 2. 如何使用收集到的信息 + +我们利用从所有服务中收集的信息来提供、维护、保护和改进这些服务,同时开发新的服务并保护 Hydro 以及用户的隐私。 +当我们要将信息用于本隐私权政策未载明的其它用途时,则会事先征求您的同意。 + +#### 3. 访问和更新您的个人信息 + +无论您在何时使用我们的服务,我们都力求让您能够访问自己的个人信息。如果这些信息有误,我们会努力通过各种方式让您快速更新信息或删除信息。在更新您的个人信息时,我们可能会要求您先验证自己的身份,然后再处理您的请求。 +我们力求对服务进行完善的维护,以保护信息免遭意外或恶意的破坏。因此,当您从我们的服务中删除信息后,我们可能不会立即从在用的服务器中删除这些信息的残留副本,也可能不会从备份系统中删除相应的信息。 + +#### 4. 信息安全 + +我们为您提供SSL加密访问服务,您可以通过SSL(https)使用我们的服务,这可以很大程度上保障在传输过程中您信息的安全。 +对于敏感数据(如您的密码),我们承诺在存储时进行高强度不可逆加密。Hydro 的管理员、维护人员等均不能够访问到敏感数据的明文,所有操作均无人工介入。 \ No newline at end of file diff --git a/module/wiki/raw/about/tos.md b/module/wiki/raw/about/tos.md new file mode 100644 index 000000000..590cb21b9 --- /dev/null +++ b/module/wiki/raw/about/tos.md @@ -0,0 +1,60 @@ +# Terms of Service + +#### 0. 欢迎使用 Hydro + +注册 Hydro 帐户和/或使用 Hydro 提供的服务(包括网页提供的在线服务和题目评测的非在线服务等),即表示您已同意本条款。请您务必审慎阅读,充分理解条款各项内容。 + +#### 1. 使用服务 + +您必须遵守各项服务中提供的所有政策(包括但不限于讨论和题解的版规)。 +请勿滥用我们的服务。如,请勿干扰我们的服务,或尝试使用除我们提供的界面和指示以外的方法访问这些服务,或使用我们服务中出现的缺陷干扰其他网站或设施的正常运行。您仅能在法律允许的范围内使用我们的服务。 +您在使用我们服务时须遵守我们服务器所在地的法律法规,不得利用我们服务从事违法违规行为,包括但不限于: + +- 发布、传送、传播、储存危害国家安全统一、破坏社会稳定、违反公序良俗、侮辱、诽谤、淫秽、暴力以及任何违反国家法律法规的内容; +- 发布、传送、传播、储存侵害他人知识产权、商业秘密等合法权利的内容; +- 恶意虚构事实、隐瞒真相以误导、欺骗他人; +- 发布、传送、传播广告信息及垃圾信息; +- 其他法律法规禁止的行为。 + +如果您违反了约定,相关国家相关机关或机构可能会对您提起诉讼、进行行政处罚或采取其他制裁措施,Hydro 将给于协助。造成损害的,您应依法予以赔偿,Hydro 不承担任何责任。 +如果 Hydro 发现或收到他人举报您发布的信息违反约定,Hydro 有权进行独立判断并采取技术手段予以删除、屏蔽或断开链接。同时,Hydro 有权视用户的行为性质,采取包括但不限于暂停或终止服务,限制、冻结或终止账户使用,追究法律责任等措施。 + +#### 2. 版权 + +使用我们的服务并不代表您拥有我们的服务或您所访问的内容的任何知识产权。网站上的所有材料(包括但不限于题目内容、用户界面、Wiki)版权均受保护,归 Hydro 所有。除非另有说明,本网站上的材料和服务仅用于个人和非商业用途,未经 Hydro 书面许可,不得复制、修改、创建衍生作品、传播、出版、公开演示、公开展示和分发从本网站获得的任何信息、文件、产品或服务。 + +#### 3. 您在我们服务中发布的内容 + +我们的某些服务允许您提交内容。您保留对该内容持有的任何知识产权的所有权。 +当您上传内容或通过其他方式向我们的服务提交内容时,您授予 Hydro 使用、持有、存储、复制、修改、创建衍生作品、传播、出版、公开演示、公开展示和分发此内容等权利。您在此许可中授予的权限,仅能用于运营、宣传和改进我们的服务,以及开发新的服务。该项许可在您停止使用我们的服务后依然有效。某些服务可能会向您提供一些方法,用于访问和删除您提供给该服务的内容。对于您提交至我们服务的任何内容,请确保您拥有向我们授予此许可的必要权利。我们有权在未通知您的情况下删除我们认为侵犯了知识产权或违反了相关法律法规的内容。 + +#### 4. 对于发布题目的附加条款 + +您可以在 Hydro 上创建新题目。您上传到 Hydro 的题目,除了适用于本协议第三条(即“您在我们服务中发布的内容”)条款,还包含以下附加条款(若有冲突的条款,以附加条款中的优先): + +- 您上传到 Hydro 上的题目版权为 Hydro 和您共同拥有,我们会在相关页面或在对其进行分发、传播等操作时标明版权所有者。 +- Hydro 尊重他人知识产权和合法权益,请您在上传题目前确保拥有题目内容(包括但不限于题目描述、数据、图片等)的著作权及信息网络传播权或者已经取得上述全部权利人的许可并不存在任何著作权纠纷。Hydro有权在不通知的情况下删除被认为侵权的题目。 +- 您可以申请将自己上传的优质题目合并到题库主干。我们的管理员会对您创建的题目的内容(包括但不限于评测数据等对用户不可见的信息)进行人工审核和适当修改以确认其符合国家基本法律法规。出于质量的考虑,我们也可能会拒绝您完全合法的合并到题库主干的请求。 +- 我们会维护服务的稳定,并对数据(包括您递交的题目)进行定期的备份,并尽量在关闭服务前通知您,但我们仍然不对任何题目(包括主干和非主干)提供永久存储或保留的承诺,出于安全的考虑推荐您自行保留题目的内容。 +- 您有权决定 Hydro 是否公开您上传的题目的数据。公开题目数据意味着 Hydro 上的用户均有权利获取到您递交的题目的所有评测数据,但相关版权协议仍然生效。 + +#### 5. 隐私保护 + +[Hydro 隐私声明](/wiki/about#privacy) 介绍了您在使用我们的服务时,我们会如何处理您的个人数据和保护您的隐私。使用我们的服务即表示您同意 Hydro 可以按照我们的隐私权政策使用您的个人数据。 + +#### 6. 修改和终止服务 + +我们始终在不断更改和改进我们的服务。我们可能会增加或删除功能,也可能暂停或彻底停止某项服务。 +您可以随时停止使用我们的服务,尽管我们对此表示非常遗憾。Hydro 也可能随时停止向您提供服务,或随时对我们的服务增加或设置新的限制。 + +#### 7. 保证和免责声明 + +我们对服务内容、服务的具体功能,或其可靠性、可用性或满足您需要的能力不作任何承诺。我们的服务是按照现有技术和条件所能达到的现状提供的。我们会尽最大努力向您提供服务,确保服务的连贯性和安全性。但我们不能随时预见和防范法律、技术以及其他风险,包括但不限于不可抗力、病毒、木马、黑客攻击、系统不稳定、第三方服务瑕疵、政府行为等原因可能导致的服务中断、数据丢失以及其他的损失和风险。 + +#### 8. 关于本条款 + +我们可以修改上述条款或任何适用于某项服务的附加条款,您应当定期查阅本条款。所有修改的适用不具有追溯力,且会在公布十四天或更长时间后方始生效。但是,对服务新功能的特别修改或由于法律原因所作的修改将立即生效。如果您不同意服务的修改条款,应停止使用服务。 + +#### 9. 其他 + +如果您对这个协议或我们的服务有意见或建议,可与我们联系,我们会给予您必要的帮助。 \ No newline at end of file diff --git a/module/wiki/raw/development/contents.json b/module/wiki/raw/development/contents.json new file mode 100644 index 000000000..437d862da --- /dev/null +++ b/module/wiki/raw/development/contents.json @@ -0,0 +1,3 @@ +[ + "gettingstarted" +] \ No newline at end of file diff --git a/module/wiki/raw/development/gettingstarted.md b/module/wiki/raw/development/gettingstarted.md new file mode 100644 index 000000000..30c34aaeb --- /dev/null +++ b/module/wiki/raw/development/gettingstarted.md @@ -0,0 +1,23 @@ +# Getting Started + +欢迎使用 Hydro ! + +#### 部署 Hydro + +1. 安装 MongoDB 。MongoDB 是 Hydro 所使用的数据库程序。 +2. 下载打包完成的 javascript 文件并放置于一个**有读写权限**的空文件夹运行。 +3. 访问 127.0.0.1:8888 并以 root 账户登录 Hydro。(默认密码为 rootroot ,请及时修改) +4. 打开管理面板进行相应配置。 +5. 完成! + +#### 模块安装与卸载 + +TODO + +#### 模块开发 + +TODO + +#### 项目架构 + +TODO diff --git a/module/wiki/raw/help.yaml b/module/wiki/raw/help.yaml deleted file mode 100644 index 6fd3f8433..000000000 --- a/module/wiki/raw/help.yaml +++ /dev/null @@ -1,93 +0,0 @@ -data-heading-extract-to: '#menu-item-wiki_help' -section: -- id: compiler - title: Compilers' Version and Parameters - content: | -Hydro使用HydroJudger进行评测,以docker镜像的形式安装至评测机。所使用的编译器均为创建镜像时debian testing分支的最新版。编译参数如下:
--- id: limits - title: Limitations - content: | --
- 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
Hydro 评测机使用进程的CPU时间计算时间消耗,时间的限定为题目中评测点所指定的时间。
-Hydro 评测机使用进程虚拟内存与物理内存总和计算内存空间消耗。内存空间默认限定为256MiB,题目中特别指明的,限定为题目中评测点所指定的内存空间。
-- id: io - title: IO - content:若无特殊说明,Hydro 使用标准输入输出(控制台输入输出,屏幕输入输出,STD I/O)。
-- id: status - title: Judge Status - content: | -有“成绩取消”字样则说明管理员手动标记此记录为取消,可能违反了服务条款,比如代码被发现与其他用户的代码十分相似。-- id: ce - title: Compile Error - content: | -
可能有以下情况:
---
- 1. 递交时选错了编程语言
-- 2. Java 的主类名没有使用 "Main"
-- 3. 对于 C/C++:见下
-- 4. 一般性的编译错误
-
--- id: training - title: Training - content:对 C/C++ 选手的特别提醒:
--
-- 1. __int64 在 GNU C++ 中应写成 long long 类型
-- 2. main() 返回值必须定义为 int ,而不是 void
-- 3. for 语句中的指标变量 i 将会在如"for (int i = 0...) {...}"语句之后变为无效
-- 4. itoa 不是一个通用 ANSI 函数(标准 C/C++ 中无此函数)
-- 5. printf 中使用 %lf 格式是不正确的
-
我们精心挑选了一些题目组成了训练计划。单击导航栏的“训练”即可进入!
-- id: contest - title: Contest - content: | -按照赛制不同,有不同的递交、排名规则。 -
OI 赛制所有题目均以最后一次递交为准,特别地,请避免编译错误。
-OI 赛制排名规则为:总分高的排在前面,总分相等则排名相同。
-ACM/ICPC 赛制所有题目递交后立即评测,以是否通过为准。
-ACM/ICPC 赛制排名规则为:通过题目数多的排在前面,通过题目数相同的做题耗时(含罚时)少的排在前。
-时间与空间限制以题目说明为准,默认限制参见{{ _('Limitations') }}。
-- id: acratio - title: Accepted Ratio - content:通过率的影响极其恶劣,现在 Hydro 不提供也不承认通过率。
-- id: rp - title: RP - content: | -Hydro RP 分为固定 RP 与浮动 RP ,固定 RP 可由活动、比赛等的奖励获得,浮动 RP 由一般性通过题目获得。
-浮动 RP 是一个动态的数值,每个用户在每道题上获得的 RP 都不一样,并且未来也不固定(即浮动之意)。
-每道题的浮动 RP 由该题通过总人数与该用户通过此题的名次计算得来。-- id: upload - title: Dataset Format - content: TODO -- id: lostpass - title: Forgot Password and/or Username - content: | -
如果您无法登录,请仔细想想,是不是用户名记错了。比如,自己原本想要注册的用户名已经被注册,所以使用了一个带有前和/或后缀的用户名。
-如果您确信您的账号被盗或者忘记了账号和/或密码,请及时{{ _('Reset Password or Find Username') }}。
\ No newline at end of file diff --git a/module/wiki/raw/help/acratio.md b/module/wiki/raw/help/acratio.md new file mode 100644 index 000000000..54c20d8aa --- /dev/null +++ b/module/wiki/raw/help/acratio.md @@ -0,0 +1,3 @@ +# Accepted Ratio + +通过率的影响极其恶劣,Hydro 不提供也不承认通过率。 \ No newline at end of file diff --git a/module/wiki/raw/help/ce.md b/module/wiki/raw/help/ce.md new file mode 100644 index 000000000..b9a51bb6b --- /dev/null +++ b/module/wiki/raw/help/ce.md @@ -0,0 +1,19 @@ +# Compile Error + +可能有以下情况: + +- 递交时选错了编程语言 +- Java 的主类名没有使用 "Main" +- 对于 C/C++:见下 +- 一般性的编译错误 + ++ 对 C/C++ 选手的特别提醒: +diff --git a/module/wiki/raw/help/compiler.md b/module/wiki/raw/help/compiler.md new file mode 100644 index 000000000..6d4bf1d7d --- /dev/null +++ b/module/wiki/raw/help/compiler.md @@ -0,0 +1,14 @@ +# 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` diff --git a/module/wiki/raw/help/contents.json b/module/wiki/raw/help/contents.json new file mode 100644 index 000000000..4330fa883 --- /dev/null +++ b/module/wiki/raw/help/contents.json @@ -0,0 +1,13 @@ +[ + "compiler", + "limits", + "io", + "status", + "ce", + "training", + "contest", + "acratio", + "rp", + "dataformat", + "lostpass" +] \ No newline at end of file diff --git a/module/wiki/raw/help/contest.md b/module/wiki/raw/help/contest.md new file mode 100644 index 000000000..3a7fef3cd --- /dev/null +++ b/module/wiki/raw/help/contest.md @@ -0,0 +1,8 @@ +# Contest + +按照赛制不同,有不同的递交、排名规则。 +OI 赛制所有题目均以最后一次递交为准,特别地,请避免编译错误。 +OI 赛制排名规则为:总分高的排在前面,总分相等则排名相同。 +ACM/ICPC 赛制所有题目递交后立即评测,以是否通过为准。 +ACM/ICPC 赛制排名规则为:通过题目数多的排在前面,通过题目数相同的做题耗时(含罚时)少的排在前。 +时间与空间限制以题目说明为准,默认限制参见[Limitations](#Limits)。 \ No newline at end of file diff --git a/module/wiki/raw/help/dataformat.md b/module/wiki/raw/help/dataformat.md new file mode 100644 index 000000000..d60b42513 --- /dev/null +++ b/module/wiki/raw/help/dataformat.md @@ -0,0 +1,3 @@ +# Dataset Format + +TODO \ No newline at end of file diff --git a/module/wiki/raw/help/io.md b/module/wiki/raw/help/io.md new file mode 100644 index 000000000..6617847ec --- /dev/null +++ b/module/wiki/raw/help/io.md @@ -0,0 +1,3 @@ +# IO + +若无特殊说明,Hydro 使用标准输入输出(控制台输入输出,屏幕输入输出,STD I/O)。 \ No newline at end of file diff --git a/module/wiki/raw/help/limits.md b/module/wiki/raw/help/limits.md new file mode 100644 index 000000000..3dd2a0e12 --- /dev/null +++ b/module/wiki/raw/help/limits.md @@ -0,0 +1,4 @@ +# Limitations + +Hydro 评测机使用进程的CPU时间计算时间消耗,时间的限定为题目中评测点所指定的时间。 +Hydro 评测机使用进程虚拟内存与物理内存总和计算内存空间消耗。内存空间默认限定为256MiB,题目中特别指明的,限定为题目中评测点所指定的内存空间。 \ No newline at end of file diff --git a/module/wiki/raw/help/lostpass.md b/module/wiki/raw/help/lostpass.md new file mode 100644 index 000000000..548f5ab57 --- /dev/null +++ b/module/wiki/raw/help/lostpass.md @@ -0,0 +1,4 @@ +# Forgot Password and/or Username + +如果您无法登录,请仔细想想,是不是用户名记错了。比如,自己原本想要注册的用户名已经被注册,所以使用了一个带有前和/或后缀的用户名。 +如果您确信您的账号被盗或者忘记了账号和/或密码,请及时[{{ _('Reset Password or Find Username') }}](/lostpass)。 \ No newline at end of file diff --git a/module/wiki/raw/help/rp.md b/module/wiki/raw/help/rp.md new file mode 100644 index 000000000..a958b81ab --- /dev/null +++ b/module/wiki/raw/help/rp.md @@ -0,0 +1,6 @@ +# RP + +Hydro RP 分为固定 RP 与浮动 RP ,固定 RP 可由活动、比赛等的奖励获得,浮动 RP 由一般性通过题目获得。 +浮动 RP 是一个动态的数值,每个用户在每道题上获得的 RP 都不一样,并且未来也不固定(即浮动之意)。 + ++
+- 1. __int64 在 GNU C++ 中应写成 long long 类型
+- 2. main() 返回值必须定义为 int ,而不是 void
+- 3. for 语句中的指标变量 i 将会在如"for (int i = 0...) {...}"语句之后变为无效
+- 4. itoa 不是一个通用 ANSI 函数(标准 C/C++ 中无此函数)
+- 5. printf 中使用 %lf 格式是不正确的
+
每道题的浮动 RP 由该题通过总人数与该用户通过此题的名次计算得来。\ No newline at end of file diff --git a/module/wiki/raw/help/status.md b/module/wiki/raw/help/status.md new file mode 100644 index 000000000..d2e521d07 --- /dev/null +++ b/module/wiki/raw/help/status.md @@ -0,0 +1,17 @@ +# Judge Status + +- Waiting 评测:评测请求正在等待被评测机抓取 +- Fetched 评测:评测请求已被评测机抓取,正在准备开始评测 +- Compiling 评测:正在编译中 +- Judging 评测:编译成功,正在评测中 +- Accepted 通过:程序输出完全正确 +- Wrong Answer 不通过:程序输出与标准答案不一致(不包括行末空格以及文件末空行) +- Time Exceeded 不通过:程序运行时间超过了题目限制 +- Memory Exceeded 不通过:程序运行内存空间超过了题目限制 +- Runtime Error 不通过:程序运行时错误(如数组越界、被零除、运算溢出、栈溢出、无效指针等) +- Compile Error 不通过:编译失败 +- System Error 错误:系统错误(如果您遇到此问题,请及时在讨论区进行反馈) +- Canceled 其他:评测被取消 +- Unknown Error 其他:未知错误 + +
有“成绩取消”字样则说明管理员手动标记此记录为取消,可能违反了服务条款,比如代码被发现与其他用户的代码十分相似。\ No newline at end of file diff --git a/module/wiki/raw/help/training.md b/module/wiki/raw/help/training.md new file mode 100644 index 000000000..8ef3a8ceb --- /dev/null +++ b/module/wiki/raw/help/training.md @@ -0,0 +1,3 @@ +# Training + +我们精心挑选了一些题目组成了训练计划。单击导航栏的“训练”即可进入! \ No newline at end of file diff --git a/module/wiki/template.build.js b/module/wiki/template.build.js deleted file mode 100644 index 8a25adb2e..000000000 --- a/module/wiki/template.build.js +++ /dev/null @@ -1,29 +0,0 @@ -const yaml = require('js-yaml'); -const fs = require('fs'); -const path = require('path'); - -exports.prebuild = () => { - const templates = {}; - templates['layout/wiki_base.html'] = fs.readFileSync(`${__dirname}/wiki_base.html`).toString(); - const pages = fs.readdirSync(path.resolve(__dirname, 'raw')); - for (const page of pages) { - const f = fs.readFileSync(path.resolve(__dirname, 'raw', page)).toString(); - const file = yaml.safeLoad(f); - let template = ` - {% set page_name="wiki_${page.split('.')[0]}" %} - {% extends "layout/wiki_base.html" %} - {% block wiki_content %}`; - for (const section of file.section) { - template += ` -