const _ = require('lodash'); const { ObjectID } = require('bson'); const { STATUS_WAITING } = require('./builtin').STATUS; const task = require('./task'); const problem = require('./problem'); const { RecordNotFoundError, PermissionError } = require('../error'); const db = require('../service/db'); const coll = db.collection('record'); /** * @param {string} domainId * @param {import('../interface').Record} data */ async function add(domainId, data) { _.defaults(data, { status: STATUS_WAITING, domainId, score: 0, time: 0, memory: 0, rejudged: false, judgeTexts: [], compilerTexts: [], testCases: [], judger: null, judgeAt: null, }); const [pdoc, res] = await Promise.all([ problem.get(domainId, data.pid), coll.insertOne(data), ]); await task.add({ type: 'judge', rid: res.insertedId, domainId, pid: data.pid, data: pdoc.data, lang: data.lang, code: data.code, }); return res.insertedId; } /** * @param {string} domainId * @param {ObjectID} rid * @returns {import('../interface').Record} */ async function get(domainId, rid) { const _id = new ObjectID(rid); const rdoc = await coll.findOne({ domainId, _id }); if (!rdoc) throw new RecordNotFoundError(rid); return rdoc; } function getMany(domainId, query, sort, page, limit) { return coll.find({ ...query, domainId }).sort(sort).skip((page - 1) * limit).limit(limit) .toArray(); } async function update(domainId, rid, $set, $push) { const _id = new ObjectID(rid); const upd = {}; if ($set && Object.keys($set).length) upd.$set = $set; if ($push && Object.keys($push).length) upd.$push = $push; await coll.findOneAndUpdate({ domainId, _id }, upd); const rdoc = await coll.findOne({ _id }); if (!rdoc) throw new RecordNotFoundError(rid); return rdoc; } function reset(domainId, rid) { return update(domainId, rid, { score: 0, status: STATUS_WAITING, time: 0, memory: 0, testCases: [], judgeTexts: [], compilerTexts: [], judgeAt: null, judger: null, rejudged: true, }); } function count(domainId, query) { return coll.find({ domainId, ...query }).count(); } async function getList(domainId, rids, showHidden = false) { const r = {}; // eslint-disable-next-line no-await-in-loop for (const rid of rids) r[rid] = await get(domainId, rid, showHidden); return r; } function getUserInProblemMulti(domainId, uid, pid, getHidden = false) { if (getHidden) return coll.find({ domainId, owner: uid, pid }); return coll.find({ domainId, owner: uid, pid, hidden: false, }); } async function judge(domainId, rid) { const rdoc = await get(domainId, rid); const pdoc = await problem.get(domainId, rdoc.pid); await task.add({ type: 'judge', rid, domainId, pid: rdoc.pid, data: pdoc.data, lang: rdoc.lang, code: rdoc.code, }); } async function rejudge(domainId, rid) { await reset(domainId, rid); const rdoc = await get(domainId, rid); const pdoc = await problem.get(domainId, rdoc.pid); await task.add({ type: 'judge', rid, domainId, pid: rdoc.pid, data: pdoc.data, lang: rdoc.lang, code: rdoc.code, }); } global.Hydro.model.record = module.exports = { add, get, getMany, update, count, reset, getList, getUserInProblemMulti, judge, rejudge, };