core: 保留比赛题目顺序

This commit is contained in:
undefined committed 2021-05-18 22:04:01 +08:00
1 parent 41219ef147
commit 6dfeede6d6
5 files changed
+25 -26

No files matched your search

+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "hydrooj", "name": "hydrooj",
"version": "2.26.11", "version": "2.26.12",
"bin": "bin/hydrooj.js", "bin": "bin/hydrooj.js",
"main": "dist/loader.js", "main": "dist/loader.js",
"typings": "dist/loader.d.ts", "typings": "dist/loader.d.ts",
+4 -4
View File
@@ -214,10 +214,11 @@ class ContestEditHandler extends Handler {
domainId: string, beginAtDate: string, beginAtTime: string, duration: number, domainId: string, beginAtDate: string, beginAtTime: string, duration: number,
title: string, content: string, rule: string, _pids: string, rated = false, title: string, content: string, rule: string, _pids: string, rated = false,
) { ) {
let pids = _pids.replace(/,/g, ',').split(',').map((i) => { const pids = _pids.replace(/,/g, ',').split(',').map((i) => {
if (isSafeInteger(parseInt(i, 10))) return parseInt(i, 10); if (isSafeInteger(parseInt(i, 10))) return parseInt(i, 10);
return i; return i;
}); });
await problem.getList(domainId, pids, this.user.hasPerm(PERM.PERM_VIEW_PROBLEM_HIDDEN), false);
const beginAtMoment = moment.tz(`${beginAtDate} ${beginAtTime}`, this.user.timeZone); const beginAtMoment = moment.tz(`${beginAtDate} ${beginAtTime}`, this.user.timeZone);
if (!beginAtMoment.isValid()) { if (!beginAtMoment.isValid()) {
throw new ValidationError('beginAtDate', 'beginAtTime'); throw new ValidationError('beginAtDate', 'beginAtTime');
@@ -225,7 +226,6 @@ class ContestEditHandler extends Handler {
const endAt = beginAtMoment.clone().add(duration, 'hours').toDate(); const endAt = beginAtMoment.clone().add(duration, 'hours').toDate();
if (beginAtMoment.isSameOrAfter(endAt)) throw new ValidationError('duration'); if (beginAtMoment.isSameOrAfter(endAt)) throw new ValidationError('duration');
const beginAt = beginAtMoment.toDate(); const beginAt = beginAtMoment.toDate();
pids = await contest.verifyProblems(domainId, pids);
await contest.edit(domainId, this.tdoc.docId, { await contest.edit(domainId, this.tdoc.docId, {
title, content, rule, beginAt, endAt, pids, rated, title, content, rule, beginAt, endAt, pids, rated,
}); });
@@ -429,7 +429,7 @@ class ContestCreateHandler extends Handler {
domainId: string, beginAtDate: string, beginAtTime: string, duration: number, domainId: string, beginAtDate: string, beginAtTime: string, duration: number,
title: string, content: string, rule: string, _pids: string, rated = false, title: string, content: string, rule: string, _pids: string, rated = false,
) { ) {
let pids = _pids.replace(/,/g, ',').split(',').map((i) => { const pids = _pids.replace(/,/g, ',').split(',').map((i) => {
if (isSafeInteger(parseInt(i, 10))) return parseInt(i, 10); if (isSafeInteger(parseInt(i, 10))) return parseInt(i, 10);
return i; return i;
}); });
@@ -438,7 +438,7 @@ class ContestCreateHandler extends Handler {
throw new ValidationError('beginAtDate', 'beginAtTime'); throw new ValidationError('beginAtDate', 'beginAtTime');
} }
const endAt = beginAt.clone().add(duration, 'hours'); const endAt = beginAt.clone().add(duration, 'hours');
pids = await contest.verifyProblems(domainId, pids); await problem.getList(domainId, pids, this.user.hasPerm(PERM.PERM_VIEW_PROBLEM_HIDDEN), false);
const tid = await contest.add( const tid = await contest.add(
domainId, title, content, domainId, title, content,
this.user._id, rule, beginAt.toDate(), endAt.toDate(), pids, rated, this.user._id, rule, beginAt.toDate(), endAt.toDate(), pids, rated,
+5 -5
View File
@@ -257,9 +257,9 @@ class HomeworkCreateHandler extends Handler {
const endAt = penaltySince.clone().add(extensionDays, 'days'); const endAt = penaltySince.clone().add(extensionDays, 'days');
if (beginAt.isSameOrAfter(penaltySince)) throw new ValidationError('endAtDate', 'endAtTime'); if (beginAt.isSameOrAfter(penaltySince)) throw new ValidationError('endAtDate', 'endAtTime');
if (penaltySince.isAfter(endAt)) throw new ValidationError('extensionDays'); if (penaltySince.isAfter(endAt)) throw new ValidationError('extensionDays');
const verified = await contest.verifyProblems(domainId, pids); await problem.getList(domainId, pids, this.user.hasPerm(PERM.PERM_VIEW_PROBLEM_HIDDEN), false);
const tid = await contest.add(domainId, title, content, this.user._id, const tid = await contest.add(domainId, title, content, this.user._id,
'homework', beginAt.toDate(), endAt.toDate(), verified, rated, 'homework', beginAt.toDate(), endAt.toDate(), pids, rated,
{ penaltySince: penaltySince.toDate(), penaltyRules }, document.TYPE_HOMEWORK); { penaltySince: penaltySince.toDate(), penaltyRules }, document.TYPE_HOMEWORK);
this.response.body = { tid }; this.response.body = { tid };
this.response.redirect = this.url('homework_detail', { tid }); this.response.redirect = this.url('homework_detail', { tid });
@@ -334,17 +334,17 @@ class HomeworkEditHandler extends Handler {
} }
let endAt = penaltySince.clone().add(extensionDays, 'days'); let endAt = penaltySince.clone().add(extensionDays, 'days');
if (beginAt.isSameOrAfter(penaltySince)) throw new ValidationError('endAtDate', 'endAtTime'); if (beginAt.isSameOrAfter(penaltySince)) throw new ValidationError('endAtDate', 'endAtTime');
const verified = await contest.verifyProblems(domainId, pids); await problem.getList(domainId, pids, this.user.hasPerm(PERM.PERM_VIEW_PROBLEM_HIDDEN), false);
beginAt = beginAt.toDate(); beginAt = beginAt.toDate();
endAt = endAt.toDate(); endAt = endAt.toDate();
penaltySince = penaltySince.toDate(); penaltySince = penaltySince.toDate();
await contest.edit(domainId, tid, { await contest.edit(domainId, tid, {
title, content, beginAt, endAt, pids: verified, penaltySince, penaltyRules, rated, title, content, beginAt, endAt, pids, penaltySince, penaltyRules, rated,
}, document.TYPE_HOMEWORK); }, document.TYPE_HOMEWORK);
if (tdoc.beginAt !== beginAt if (tdoc.beginAt !== beginAt
|| tdoc.endAt !== endAt || tdoc.endAt !== endAt
|| tdoc.penaltySince !== penaltySince || tdoc.penaltySince !== penaltySince
|| tdoc.pids.sort().join(' ') !== verified.sort().join(' ')) { || tdoc.pids.sort().join(' ') !== pids.sort().join(' ')) {
await contest.recalcStatus(domainId, tdoc.docId, document.TYPE_HOMEWORK); await contest.recalcStatus(domainId, tdoc.docId, document.TYPE_HOMEWORK);
} }
this.response.body = { tid }; this.response.body = { tid };
+2 -10
View File
@@ -569,22 +569,15 @@ export async function getScoreboard(
const tdoc = await get(domainId, tid, docType); const tdoc = await get(domainId, tid, docType);
if (!canShowScoreboard.call(this, tdoc)) throw new ContestScoreboardHiddenError(tid); if (!canShowScoreboard.call(this, tdoc)) throw new ContestScoreboardHiddenError(tid);
if (!canShowRecord.call(this, tdoc)) throw new ContestScoreboardHiddenError(tid); if (!canShowRecord.call(this, tdoc)) throw new ContestScoreboardHiddenError(tid);
const tsdocs = await getMultiStatus(domainId, { docId: tid }, docType).sort(RULES[tdoc.rule].statusSort); const tsdocsCursor = getMultiStatus(domainId, { docId: tid }, docType).sort(RULES[tdoc.rule].statusSort);
const pdict = await problem.getList(domainId, tdoc.pids, true); const pdict = await problem.getList(domainId, tdoc.pids, true);
const [rows, udict, nPages] = await RULES[tdoc.rule].scoreboard( const [rows, udict, nPages] = await RULES[tdoc.rule].scoreboard(
isExport, this.translate.bind(this), isExport, this.translate.bind(this),
tdoc, pdict, tsdocs, page, tdoc, pdict, tsdocsCursor, page,
); );
return [tdoc, rows, udict, pdict, nPages]; return [tdoc, rows, udict, pdict, nPages];
} }
export async function verifyProblems(domainId: string, pids: Array<number | string>) {
const pdict = await problem.getList(domainId, pids, true);
const _pids: Set<number> = new Set();
for (const i in pdict) _pids.add(pdict[i].docId);
return Array.from(_pids);
}
export const statusText = (tdoc: Tdoc) => ( export const statusText = (tdoc: Tdoc) => (
isNew(tdoc) isNew(tdoc)
? 'New' ? 'New'
@@ -621,7 +614,6 @@ global.Hydro.model.contest = {
canShowScoreboard, canShowScoreboard,
canViewHiddenScoreboard, canViewHiddenScoreboard,
getScoreboard, getScoreboard,
verifyProblems,
isNew, isNew,
isUpcoming, isUpcoming,
isNotStarted, isNotStarted,
+13 -6
View File
@@ -2,6 +2,7 @@ import { escapeRegExp } from 'lodash';
import { ItemBucketMetadata } from 'minio'; import { ItemBucketMetadata } from 'minio';
import moment from 'moment'; import moment from 'moment';
import type { Readable } from 'stream'; import type { Readable } from 'stream';
import TaskModel from './task';
import storage from '../service/storage'; import storage from '../service/storage';
import * as bus from '../service/bus'; import * as bus from '../service/bus';
import db from '../service/db'; import db from '../service/db';
@@ -76,19 +77,25 @@ export class StorageModel {
} }
} }
async function clean() { async function cleanFiles() {
let res = await StorageModel.coll.findOneAndDelete({ autoDelete: { $lte: new Date() } }); let res = await StorageModel.coll.findOneAndDelete({ autoDelete: { $lte: new Date() } });
while (res.value) { while (res.value) {
// eslint-disable-next-line no-await-in-loop // eslint-disable-next-line no-await-in-loop
// await storage.del(res.value._id); await storage.del(res.value._id);
// eslint-disable-next-line no-await-in-loop // eslint-disable-next-line no-await-in-loop
res = await StorageModel.coll.findOneAndDelete({ autoDelete: { $lte: new Date() } }); res = await StorageModel.coll.findOneAndDelete({ autoDelete: { $lte: new Date() } });
} }
setTimeout(clean, 10000);
} }
bus.on('app/started', () => { TaskModel.Worker.addHandler('storage.prune', cleanFiles);
clean(); bus.once('app/started', async () => {
return StorageModel.coll.createIndex({ path: 1 }, { unique: true }); if (!await TaskModel.count({ type: 'schedule', subType: 'storage.prune' })) {
await TaskModel.add({
type: 'schedule',
subType: 'storage.prune',
executeAfter: moment().minute(0).second(0).millisecond(0).toDate(),
interval: [1, 'hour'],
});
}
}); });
global.Hydro.model.storage = StorageModel; global.Hydro.model.storage = StorageModel;