diff --git a/hydro/handler/training.js b/hydro/handler/training.js index bcfaf73d0..993fee713 100644 --- a/hydro/handler/training.js +++ b/hydro/handler/training.js @@ -73,8 +73,8 @@ class TrainingMainHandler extends TrainingHandler { $or: [{ _id: { $in: Array.from(tids) } }, { enroll: 1 }], }).toArray(); for (const tsdoc of tsdocs) { - tsdict[tsdoc._id] = tsdoc; - enrolledTids.add(tsdoc._id); + tsdict[tsdoc.tid] = tsdoc; + enrolledTids.add(tsdoc.tid); } for (const tid of tids) enrolledTids.delete(tid); if (enrolledTids.size) tdict = await training.getList(Array.from(enrolledTids)); @@ -117,7 +117,7 @@ class TrainingDetailHandler extends TrainingHandler { for (const node of tdoc.dag) { ndict[node._id] = node; const totalCount = node.pids.length; - const doneCount = Set.union(new Set(node.pids), new Set(donePids)); + const doneCount = Set.union(new Set(node.pids), new Set(donePids)).size; const nsdoc = { progress: totalCount ? parseInt(100 * (doneCount / totalCount)) : 100, isDone: training.isDone(node, doneNids, donePids), @@ -172,8 +172,6 @@ class TrainingCreateHandler extends TrainingHandler { }) { dag = await _parseDagJson(dag); const pids = training.getPids({ dag }); - console.log(pids); - console.log(pids.length, pids.size); assert(pids.length, new ValidationError('dag')); const pdocs = await problem.getMulti({ $or: [{ _id: { $in: pids } }, { pid: { $in: pids } }], diff --git a/hydro/model/training.js b/hydro/model/training.js index 15ce84bdb..782f0ab1b 100644 --- a/hydro/model/training.js +++ b/hydro/model/training.js @@ -37,7 +37,6 @@ async function setStatus(tid, uid, $set) { module.exports = { getPids(tdoc) { - console.log(tdoc.dag); const pids = new Set(); for (const node of tdoc.dag) { for (const pid of node.pids) pids.add(pid); diff --git a/hydro/service/server.js b/hydro/service/server.js index bca15a26d..1e4adb31f 100644 --- a/hydro/service/server.js +++ b/hydro/service/server.js @@ -303,19 +303,11 @@ class ConnectionHandler { * @param {import('sockjs').Connection} conn */ constructor(conn) { - const that = this; this.conn = conn; this.request = { - cookies: { - get(name) { - return that.request.cookies[name]; - }, - set() { }, - }, params: {}, headers: conn.headers, }; - this._handler = {}; const p = (conn.url.split('?')[1] || '').split('&'); for (const i in p) p[i] = p[i].split('='); for (const i in p) this.request.params[p[i][0]] = decodeURIComponent(p[i][1]); @@ -342,21 +334,14 @@ class ConnectionHandler { } async ___prepare() { - await new Promise((resolve, reject) => { - this.conn.once('data', (msg) => { - for (const i of msg.split(';')) { - const [k, v] = i.trim().split('='); - this.request.cookies[k] = v; - } - resolve(); - }); - setTimeout(reject, 5000); - }); - this._handler.sid = this.request.cookies.get('sid'); - this.session = this._handler.sid - ? await token.get(this._handler.sid, token.TYPE_SESSION) - : { uid: 1 }; - if (!this.session) this.session = { uid: 1 }; + try { + this.session = { + uid: await token.get(this.request.params.token, token.TYPE_CSRF_TOKEN), + }; + await token.delete(this.request.params.token, token.TYPE_CSRF_TOKEN); + } catch (e) { + this.session = { uid: 1 }; + } const bdoc = await blacklist.get(this.request.ip); if (bdoc) throw new BlacklistedError(this.request.ip); this.user = await user.getById(this.session.uid); diff --git a/module/html2md/lib.js b/module/html2md/lib.js index d1551c62c..b37cf973a 100644 --- a/module/html2md/lib.js +++ b/module/html2md/lib.js @@ -1,16 +1,26 @@ -global.Hydro.lib.html2md = module.exports = function html2md(str) { +const RE_IMG = /(.*?)<\/img>/i; +const RE_A = /(.*?)<\/a>/i; +const RE_BLOCKQUOTE = /(.*?)<\/blockquote>/i; + +function replacer(RE, cb) { // eslint-disable-line no-unused-vars + // eslint-disable-next-line no-eval + return eval(`(substr)=>{ + const s = RE.exec(substr); + return cb(s); + }`); +} + +function html2md(str) { return str.replace(/

/gmi, '').replace(/<\/p>/gmi, ' ') - .replace(/

/gmi, '# ') - .replace(/

/gmi, '## ') - .replace(/

/gmi, '### ') - .replace(/

/gmi, '#### ') - .replace(/

/gmi, '##### ') - .replace(/
/gmi, '###### ') - .replace(/<\/?code>/, '\n```\n') - .replace(/.*?<\/img>/gmi, (substr) => { - const RE_IMG = /(.*?)<\/img>/i; - const res = RE_IMG.exec(substr); - return `[${res[2]}](${res[1]})`; + .replace(//gmi, (substr) => { + const s = //i.exec(substr); + return `${'#'.repeat(parseInt(s[1]))} `; }) - .replace(/<\/h[0-6]>/, '\n'); -}; + .replace(/<\/h[0-6]>/, '\n') + .replace(/<\/?code>/, '\n```\n') + .replace(/.*?<\/img>/gmi, replacer(RE_IMG, (s) => `![${s[2]}](${s[1]})`)) + .replace(/.*?<\/a>/gmi, replacer(RE_A, (s) => `[${s[2]}](${s[1]})`)) + .replace(/.*?<\/blockquote>/gmi, replacer(RE_BLOCKQUOTE, (s) => `> ${s[1]}`)); +} + +global.Hydro.lib.html2md = module.exports = html2md; diff --git a/module/migrate-vijos/script.js b/module/migrate-vijos/script.js index 12def5757..d0c9680e8 100644 --- a/module/migrate-vijos/script.js +++ b/module/migrate-vijos/script.js @@ -2,6 +2,7 @@ const Mongo = global.Hydro.nodeModules.mongodb; const { ObjectID } = global.Hydro.nodeModules.bson; const dst = global.Hydro.service.db; +const { problem } = global.Hydro.model.problem; function parseSolution(doc) { return { @@ -12,72 +13,75 @@ function parseSolution(doc) { }; } -async function problem(src, report) { - let count = await src.collection('document').find({ doc_type: 10 }).count(); - await report({ progress: 1, message: `Found ${count} problems.` }); - for (let i = 0; i <= Math.floor(count / 50); i++) { - const docs = await src.collection('document').find({ doc_type: 10 }) - .skip(i * 50).limit(50) - .toArray(); - const problems = []; - for (const doc of docs) { - problems.push({ - _id: doc._id, - pid: doc.doc_id || new ObjectID(), - title: doc.title, - content: doc.content, - owner: doc.owner_uid, - data: doc.data, - category: doc.category, - tag: doc.tag, - nSubmit: doc.num_submit, - nAccept: doc.num_accept, - }); +const tasks = { + async problem(src, report) { + let count = await src.collection('document').find({ doc_type: 10 }).count(); + await report({ progress: 1, message: `Found ${count} problems.` }); + for (let i = 0; i <= Math.floor(count / 50); i++) { + const docs = await src.collection('document').find({ doc_type: 10 }) + .skip(i * 50).limit(50) + .toArray(); + const problems = []; + for (const doc of docs) { + problems.push({ + _id: doc._id, + pid: doc.doc_id || new ObjectID(), + title: doc.title, + content: doc.content, + owner: doc.owner_uid, + data: doc.data, + category: doc.category, + tag: doc.tag, + nSubmit: doc.num_submit, + nAccept: doc.num_accept, + }); + } + await dst.collection('problem').insertMany(problems); } - await dst.collection('problem').insertMany(problems); - } - count = await src.collection('document.status').find({ doc_type: 10 }).count(); - for (let i = 0; i <= Math.floor(count / 50); i++) { - const docs = await src.collection('document.status').find({ doc_type: 10 }) - .skip(i * 50).limit(50) - .toArray(); - const problems = []; - for (const doc of docs) { - problems.push({ - pid: doc.pid, - rid: doc.rid, - }); + count = await src.collection('document.status').find({ doc_type: 10 }).count(); + for (let i = 0; i <= Math.floor(count / 50); i++) { + const docs = await src.collection('document.status').find({ doc_type: 10 }) + .skip(i * 50).limit(50) + .toArray(); + const problems = []; + for (const doc of docs) { + problems.push({ + pid: await problem.get(doc.pid), + rid: doc.rid, + uid: doc.uid, + status: doc.status, + }); + } + await dst.collection('problem.status').insertMany(problems); } - await dst.collection('problem.status').insertMany(problems); - } - await report({ progress: 1, message: `Found ${count} problems.` }); -} - -async function contest(src, report) { - const RULES = ['', 'oi', 'acm']; - const count = await src.collection('document').find({ doc_type: 30 }).count(); - await report({ progress: 1, message: `Found ${count} contests.` }); - for (let i = 0; i <= Math.floor(count / 50); i++) { - const docs = await src.collection('document').find({ doc_type: 30 }) - .skip(i * 50).limit(50) - .toArray(); - const contests = []; - for (const doc of docs) { - contests.push({ - _id: doc._id, - title: doc.title, - content: doc.content, - owner: doc.owner_uid, - rule: RULES[doc.rule], - beginAt: doc.begin_at, - endAt: doc.end_at, - pids: doc.pids, - attend: doc.attend, - }); + await report({ progress: 1, message: `Found ${count} problems.` }); + }, + async contest(src, report) { + const RULES = ['', 'oi', 'acm']; + const count = await src.collection('document').find({ doc_type: 30 }).count(); + await report({ progress: 1, message: `Found ${count} contests.` }); + for (let i = 0; i <= Math.floor(count / 50); i++) { + const docs = await src.collection('document').find({ doc_type: 30 }) + .skip(i * 50).limit(50) + .toArray(); + const contests = []; + for (const doc of docs) { + contests.push({ + _id: doc._id, + title: doc.title, + content: doc.content, + owner: doc.owner_uid, + rule: RULES[doc.rule], + beginAt: doc.begin_at, + endAt: doc.end_at, + pids: doc.pids, + attend: doc.attend, + }); + } + await dst.collection('contest').insertMany(contests); } - await dst.collection('contests').insertMany(contests); - } -} + }, +}; async function migrateVijos({ host, port, name, username, password, @@ -95,8 +99,8 @@ async function migrateVijos({ value: (await src.collection('system').findOne({ _id: 'user_counter' })).value, }); await report({ progress: 1, message: 'Collection:system done.' }); - await problem(src, report); - await contest(src, report); + await tasks.problem(src, report); + await tasks.contest(src, report); } global.Hydro.script.migrateVijos = module.exports = migrateVijos; diff --git a/module/wiki/raw/gettingstarted/contents.json b/module/wiki/raw/gettingstarted/contents.json new file mode 100644 index 000000000..2a4c4f1f9 --- /dev/null +++ b/module/wiki/raw/gettingstarted/contents.json @@ -0,0 +1,3 @@ +[ + "introduction" +] \ No newline at end of file diff --git a/module/wiki/raw/gettingstarted/introduction.md b/module/wiki/raw/gettingstarted/introduction.md new file mode 100644 index 000000000..3331a8aae --- /dev/null +++ b/module/wiki/raw/gettingstarted/introduction.md @@ -0,0 +1,11 @@ +# Introduction + +为什么使用 Hydro ? + +- 安全:使用 cgroup 进行隔离,杜绝卡评测; +- 高效:Hydro 使用了沙箱复用技术,拥有极高的评测效率; +- 扩展:Hydro 支持安装额外模块进行扩展; +- 强大:配合 Judger 模块(或 HydroJudger 独立评测机),可支持 spj,交互题,提交答案题,文件IO等多种特性; +- 简便:提供了多种迁移脚本,可从 Vijos 等快速升级至 Hydro; +- 自定:所有权限节点均可自由设置; +- 社区:Hydro 正在持续维护中; diff --git a/module/wiki/template/wiki.html b/module/wiki/template/wiki.html index b61ae431c..1de4910d7 100644 --- a/module/wiki/template/wiki.html +++ b/module/wiki/template/wiki.html @@ -19,6 +19,7 @@ diff --git a/templates/record_detail.html b/templates/record_detail.html index 8d1ba6446..6f6b19a44 100644 --- a/templates/record_detail.html +++ b/templates/record_detail.html @@ -4,7 +4,7 @@ {% block content %}
diff --git a/templates/record_main.html b/templates/record_main.html index 1789b4ada..27ad2e5cc 100644 --- a/templates/record_main.html +++ b/templates/record_main.html @@ -3,7 +3,7 @@ {% block content %}