mirror of
https://gitcode.com/gh_mirrors/hy/Hydro.git
synced 2026-10-20 01:38:19 +08:00
core: rating&problemStat: performance enhancement
This commit is contained in:
1 parent
32e2ffc1db
commit
076e2097c0
2 files changed
+21
-30
No files matched your search
@@ -1,4 +1,3 @@
|
|||||||
/* eslint-disable no-constant-condition */
|
|
||||||
/* eslint-disable no-await-in-loop */
|
/* eslint-disable no-await-in-loop */
|
||||||
import { ObjectID } from 'mongodb';
|
import { ObjectID } from 'mongodb';
|
||||||
import Schema from 'schemastery';
|
import Schema from 'schemastery';
|
||||||
@@ -29,10 +28,8 @@ export async function udoc(report) {
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
let bulk = db.collection('domain.user').initializeUnorderedBulkOp();
|
let bulk = db.collection('domain.user').initializeUnorderedBulkOp();
|
||||||
const cursor = db.collection('record').aggregate(pipeline, { allowDiskUse: true });
|
const cursor = db.collection('record').aggregate<any>(pipeline, { allowDiskUse: true });
|
||||||
while (true) {
|
for await (const adoc of cursor) {
|
||||||
const adoc = await cursor.next() as any;
|
|
||||||
if (!adoc) break;
|
|
||||||
bulk.find({
|
bulk.find({
|
||||||
domainId: adoc._id.domainId,
|
domainId: adoc._id.domainId,
|
||||||
uid: adoc._id.uid,
|
uid: adoc._id.uid,
|
||||||
@@ -61,10 +58,8 @@ export async function psdoc(report) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
const data = db.collection('record').aggregate(pipeline, { allowDiskUse: true });
|
const data = db.collection('record').aggregate<any>(pipeline, { allowDiskUse: true });
|
||||||
while (true) {
|
for await (const adoc of data) {
|
||||||
const adoc = await data.next() as any;
|
|
||||||
if (!adoc) break;
|
|
||||||
await document.setStatus(adoc._id.domainId, document.TYPE_PROBLEM, adoc._id.pid, adoc._id.uid, { nSubmit: adoc.nSubmit });
|
await document.setStatus(adoc._id.domainId, document.TYPE_PROBLEM, adoc._id.pid, adoc._id.uid, { nSubmit: adoc.nSubmit });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -117,11 +112,9 @@ export async function pdoc(report) {
|
|||||||
pipeline[2].$group[`s${i}`] = { $sum: `$s${i}` };
|
pipeline[2].$group[`s${i}`] = { $sum: `$s${i}` };
|
||||||
}
|
}
|
||||||
let bulk = db.collection('document').initializeUnorderedBulkOp();
|
let bulk = db.collection('document').initializeUnorderedBulkOp();
|
||||||
const data = db.collection('record').aggregate(pipeline, { allowDiskUse: true });
|
const data = db.collection('record').aggregate<any>(pipeline, { allowDiskUse: true });
|
||||||
let cnt = 0;
|
let cnt = 0;
|
||||||
while (true) {
|
for await (const adoc of data) {
|
||||||
const adoc = await data.next() as any;
|
|
||||||
if (!adoc) break;
|
|
||||||
const $set = {
|
const $set = {
|
||||||
nSubmit: adoc.nSubmit,
|
nSubmit: adoc.nSubmit,
|
||||||
nAccept: adoc.nAccept,
|
nAccept: adoc.nAccept,
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
import { NumericDictionary, unionWith } from 'lodash';
|
import { NumericDictionary, unionWith } from 'lodash';
|
||||||
import { FilterQuery } from 'mongodb';
|
import { FilterQuery } from 'mongodb';
|
||||||
import Schema from 'schemastery';
|
import Schema from 'schemastery';
|
||||||
|
import { Counter } from '@hydrooj/utils';
|
||||||
import { Tdoc, Udoc } from '../interface';
|
import { Tdoc, Udoc } from '../interface';
|
||||||
import difficultyAlgorithm from '../lib/difficulty';
|
import difficultyAlgorithm from '../lib/difficulty';
|
||||||
import rating from '../lib/rating';
|
import rating from '../lib/rating';
|
||||||
@@ -100,21 +101,15 @@ export const RpTypes: Record<string, RpDef> = {
|
|||||||
global.Hydro.model.rp = RpTypes;
|
global.Hydro.model.rp = RpTypes;
|
||||||
|
|
||||||
export async function calcLevel(domainId: string, report: Function) {
|
export async function calcLevel(domainId: string, report: Function) {
|
||||||
const filter = { rp: { $gt: 0 } };
|
|
||||||
const ducnt = await domain.getMultiUserInDomain(domainId, filter).count();
|
|
||||||
await domain.setMultiUserInDomain(domainId, {}, { level: 0, rank: null });
|
await domain.setMultiUserInDomain(domainId, {}, { level: 0, rank: null });
|
||||||
if (!ducnt) return;
|
|
||||||
let last = { rp: null };
|
let last = { rp: null };
|
||||||
let rank = 0;
|
let rank = 0;
|
||||||
let count = 0;
|
let count = 0;
|
||||||
const coll = db.collection('domain.user');
|
const coll = db.collection('domain.user');
|
||||||
|
const filter = { rp: { $gt: 0 }, uid: { $nin: [0, 1], $gt: -1000 } };
|
||||||
const ducur = domain.getMultiUserInDomain(domainId, filter).project({ rp: 1 }).sort({ rp: -1 });
|
const ducur = domain.getMultiUserInDomain(domainId, filter).project({ rp: 1 }).sort({ rp: -1 });
|
||||||
let bulk = coll.initializeUnorderedBulkOp();
|
let bulk = coll.initializeUnorderedBulkOp();
|
||||||
// eslint-disable-next-line no-constant-condition
|
for await (const dudoc of ducur) {
|
||||||
while (true) {
|
|
||||||
const dudoc = await ducur.next();
|
|
||||||
if (!dudoc) break;
|
|
||||||
if ([0, 1].includes(dudoc.uid)) continue;
|
|
||||||
count++;
|
count++;
|
||||||
if (!dudoc.rp) dudoc.rp = null;
|
if (!dudoc.rp) dudoc.rp = null;
|
||||||
if (dudoc.rp !== last.rp) rank = count;
|
if (dudoc.rp !== last.rp) rank = count;
|
||||||
@@ -122,6 +117,7 @@ export async function calcLevel(domainId: string, report: Function) {
|
|||||||
last = dudoc;
|
last = dudoc;
|
||||||
if (count % 100 === 0) report({ message: `#${count}: Rank ${rank}` });
|
if (count % 100 === 0) report({ message: `#${count}: Rank ${rank}` });
|
||||||
}
|
}
|
||||||
|
if (!count) return;
|
||||||
await bulk.execute();
|
await bulk.execute();
|
||||||
const levels = global.Hydro.model.builtin.LEVELS;
|
const levels = global.Hydro.model.builtin.LEVELS;
|
||||||
bulk = coll.initializeUnorderedBulkOp();
|
bulk = coll.initializeUnorderedBulkOp();
|
||||||
@@ -136,28 +132,30 @@ export async function calcLevel(domainId: string, report: Function) {
|
|||||||
await bulk.execute();
|
await bulk.execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
async function runInDomain(id: string, report: Function) {
|
async function runInDomain(domainId: string, report: Function) {
|
||||||
const info = await domain.get(id);
|
const info = await domain.get(domainId);
|
||||||
const domainIds = [id, ...(info.union || [])];
|
const domainIds = [domainId, ...(info.union || [])];
|
||||||
const results: Record<keyof typeof RpTypes, ND> = {};
|
const results: Record<keyof typeof RpTypes, ND> = {};
|
||||||
const udict = new Proxy({}, { get: (self, key) => self[key] || 0 });
|
const udict = Counter();
|
||||||
for (const type in RpTypes) {
|
for (const type in RpTypes) {
|
||||||
results[type] = new Proxy({}, { get: (self, key) => self[key] || RpTypes[type].base });
|
results[type] = new Proxy({}, { get: (self, key) => self[key] || RpTypes[type].base });
|
||||||
await RpTypes[type].run(domainIds, results[type], report);
|
await RpTypes[type].run(domainIds, results[type], report);
|
||||||
|
const bulk = db.collection('domain.user').initializeUnorderedBulkOp();
|
||||||
for (const uid in results[type]) {
|
for (const uid in results[type]) {
|
||||||
const udoc = await UserModel.getById(id, +uid);
|
const udoc = await UserModel.getById(domainId, +uid);
|
||||||
if (!udoc?.hasPriv(PRIV.PRIV_USER_PROFILE)) continue;
|
if (!udoc?.hasPriv(PRIV.PRIV_USER_PROFILE)) continue;
|
||||||
await domain.updateUserInDomain(id, +uid, { $set: { [`rpInfo.${type}`]: results[type][uid] } });
|
bulk.find({ domainId, uid: +uid }).updateOne({ $set: { [`rpInfo.${type}`]: results[type][uid] } });
|
||||||
udict[+uid] += results[type][uid];
|
udict[+uid] += results[type][uid];
|
||||||
}
|
}
|
||||||
|
if (bulk.length) await bulk.execute();
|
||||||
}
|
}
|
||||||
await domain.setMultiUserInDomain(id, {}, { rp: 0 });
|
await domain.setMultiUserInDomain(domainId, {}, { rp: 0 });
|
||||||
const bulk = db.collection('domain.user').initializeUnorderedBulkOp();
|
const bulk = db.collection('domain.user').initializeUnorderedBulkOp();
|
||||||
for (const uid in udict) {
|
for (const uid in udict) {
|
||||||
bulk.find({ domainId: id, uid: +uid }).upsert().update({ $set: { rp: Math.max(0, udict[uid]) } });
|
bulk.find({ domainId, uid: +uid }).upsert().update({ $set: { rp: Math.max(0, udict[uid]) } });
|
||||||
}
|
}
|
||||||
if (bulk.length) await bulk.execute();
|
if (bulk.length) await bulk.execute();
|
||||||
await calcLevel(id, report);
|
await calcLevel(domainId, report);
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function run({ domainId }, report: Function) {
|
export async function run({ domainId }, report: Function) {
|
||||||
|
|||||||
Reference in new issue
Block a user