diff --git a/build/ignoreFailure.js b/build/ignoreFailure.js deleted file mode 100644 index 9e53982ef..000000000 --- a/build/ignoreFailure.js +++ /dev/null @@ -1,5 +0,0 @@ -module.exports = function ignoreFailure(func, ...params) { - try { - func(...params); - } catch (e) { } // eslint-disable-line no-empty -}; diff --git a/hydro/handler/judge.js b/hydro/handler/judge.js index aed47e278..971a13c76 100644 --- a/hydro/handler/judge.js +++ b/hydro/handler/judge.js @@ -19,14 +19,12 @@ async function _postJudge(rdoc) { contest.updateStatus(rdoc.tid, rdoc.uid, rdoc._id, rdoc.pid, accept, rdoc.score), ); } - if (!rdoc.rejudged) { - if (await problem.updateStatus(rdoc.pid, rdoc.uid, rdoc._id, rdoc.status)) { - if (accept) { - tasks.push( - problem.inc(rdoc.pid, 'nAccept', 1), - user.inc(rdoc.uid, 'nAccept', 1), - ); - } + if (await problem.updateStatus(rdoc.pid, rdoc.uid, rdoc._id, rdoc.status)) { + if (accept && !rdoc.rejudged) { + tasks.push( + problem.inc(rdoc.pid, 'nAccept', 1), + user.inc(rdoc.uid, 'nAccept', 1), + ); } } await Promise.all(tasks); diff --git a/hydro/interface.js b/hydro/interface.js index 30db5c4cf..be9363d85 100644 --- a/hydro/interface.js +++ b/hydro/interface.js @@ -19,20 +19,22 @@ exports.udoc = { loginat: new Date(), loginip: '0.0.0.0', }; + +exports.pdoc = { + _id: new ObjectID(), + pid: 'P1000', + owner: 0, + title: 'No Title', + content: 'No Content', + nSubmit: 0, + nAccept: 0, + tag: [], + category: [], + data: null, + hidden: false, +}; + /* -export interface Pdoc { - _id: ObjectID - pid: string - owner: number - title: string - content: string - nSubmit: number - nAccept: number - tag: string[] - category: string[], - data: ObjectID | null - hidden: boolean -} export interface TestCase { time: number, memory: number, diff --git a/hydro/model/problem.js b/hydro/model/problem.js index 1743508bd..a00d68d74 100644 --- a/hydro/model/problem.js +++ b/hydro/model/problem.js @@ -1,8 +1,9 @@ const { ObjectID } = require('bson'); -const gridfs = require('../service/gridfs'); +const { STATUS_ACCEPTED } = require('./builtin').STATUS; const { ProblemNotFoundError } = require('../error'); const validator = require('../lib/validator'); const db = require('../service/db.js'); +const gridfs = require('../service/gridfs'); const coll = db.collection('problem'); const collStatus = db.collection('problem.status'); @@ -141,12 +142,16 @@ async function getListStatus(uid, pids) { return r; } async function updateStatus(pid, uid, rid, status) { - const res = await collStatus.findOneAndUpdate( + const cur = collStatus.findOne({ pid, uid }); + if (cur && status !== STATUS_ACCEPTED) { + if (cur.status !== STATUS_ACCEPTED) return false; + } + await collStatus.updateOne( { pid, uid }, { $set: { rid, status } }, { upsert: true }, ); - return res.value; + return true; } async function setTestdata(_id, readStream) { const pdoc = await getById(_id); diff --git a/module/migrate-vijos/script.js b/module/migrate-vijos/script.js index d0c9680e8..b6feae7ee 100644 --- a/module/migrate-vijos/script.js +++ b/module/migrate-vijos/script.js @@ -4,85 +4,82 @@ const { ObjectID } = global.Hydro.nodeModules.bson; const dst = global.Hydro.service.db; const { problem } = global.Hydro.model.problem; -function parseSolution(doc) { - return { +const RULES = ['', 'oi', 'acm']; + +const tasks = { + user: async (docs) => docs.map((doc) => ({ + _id: doc._id, + uname: doc.uname, + unameLower: doc.uname_lower, + salt: doc.salt, + hash: doc.hash.split('|')[1], + hashType: doc.hash.split('|')[0] === 'vj4' ? 'hydro' : doc.hash.split('|')[0], + gravatar: doc.gravatar, + email: doc.mail, + emailLower: doc.mail_lower, + + })), + problem: async (docs) => docs.map((doc) => ({ + _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, + })), + 'problem.status': async (docs) => { + const problems = []; + for (const doc of docs) { + problems.push({ + pid: await problem.get(doc.pid), + rid: doc.rid, + uid: doc.uid, + status: doc.status, + }); + } + return problems; + }, + contest: async (docs) => docs.map((doc) => ({ + _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, + })), + solution: async (docs) => docs.map((doc) => ({ _id: doc._id, title: doc.title, content: doc.content, vote: doc.vote, - }; -} - -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); - } - 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 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); - } - }, + })), }; +const cursor = { + problem: (s) => s.collection('document').find({ doc_type: 10 }), + 'problem.status': (s) => s.collection('document.status').find({ doc_type: 10 }), + contest: (s) => s.collection('document').find({ doc_type: 30 }), + user: (s) => s.collection('user').find(), +}; + +async function task(name, src, report) { + const count = await cursor[name](src).count(); + await report({ progress: 1, message: `${name}: ${count}` }); + const total = Math.floor(count / 50); + for (let i = 0; i <= total; i++) { + const docs = await cursor[name](src).skip(i * 50).limit(50).toArray(); + await dst.collection(name).insertMany(await tasks[name](docs)); + await report({ progress: Math.round(100 * (i / total)) }); + } +} + async function migrateVijos({ host, port, name, username, password, }, report = () => { }) { @@ -99,8 +96,9 @@ async function migrateVijos({ value: (await src.collection('system').findOne({ _id: 'user_counter' })).value, }); await report({ progress: 1, message: 'Collection:system done.' }); - await tasks.problem(src, report); - await tasks.contest(src, report); + await task('problem', src, report); + await task('problem.status', src, report); + await task('contest', src, report); } global.Hydro.script.migrateVijos = module.exports = migrateVijos; diff --git a/ui/pages/judge_playground.page.js b/ui/pages/judge_playground.page.js index 1cb2e4890..7ea87a7ec 100644 --- a/ui/pages/judge_playground.page.js +++ b/ui/pages/judge_playground.page.js @@ -5,7 +5,7 @@ import * as recordEnum from 'vj/constant/record'; const page = new NamedPage('judge_playground', async () => { const { default: SockJs } = await import('sockjs-client'); - const sock = new SockJs(`/judge/consume-conn?token=${ UIContext.csrfToken }`); + const sock = new SockJs(`/judge/consume-conn?token=${UiContext.csrfToken}`); sock.onopen = () => { const div = $('
').appendTo('#messages'); $('

Connection opened.

')