mirror of
https://gitcode.com/gh_mirrors/hy/Hydro.git
synced 2026-10-20 01:38:19 +08:00
core: 更改nSubmit, nAccept计算逻辑 (#76)
This commit is contained in:
1 parent
4e846a906e
commit
775605f812
15 files changed
+117
-57
No files matched your search
Vendored
+5
-1
@@ -5,5 +5,9 @@
|
|||||||
"editor.detectIndentation": true,
|
"editor.detectIndentation": true,
|
||||||
"editor.formatOnSave": true,
|
"editor.formatOnSave": true,
|
||||||
"editor.renderWhitespace": "boundary",
|
"editor.renderWhitespace": "boundary",
|
||||||
"typescript.tsdk": "node_modules/typescript/lib"
|
"typescript.tsdk": "node_modules/typescript/lib",
|
||||||
|
"[json]": {
|
||||||
|
"files.insertFinalNewline": true,
|
||||||
|
"files.trimFinalNewlines": false,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
+2
-2
@@ -31,8 +31,8 @@
|
|||||||
"@types/jest": "^26.0.22",
|
"@types/jest": "^26.0.22",
|
||||||
"@types/node": "^14.14.37",
|
"@types/node": "^14.14.37",
|
||||||
"@types/semver": "^7.3.4",
|
"@types/semver": "^7.3.4",
|
||||||
"@typescript-eslint/eslint-plugin": "^4.20.0",
|
"@typescript-eslint/eslint-plugin": "^4.21.0",
|
||||||
"@typescript-eslint/parser": "^4.20.0",
|
"@typescript-eslint/parser": "^4.21.0",
|
||||||
"cross-spawn": "^7.0.3",
|
"cross-spawn": "^7.0.3",
|
||||||
"eslint": "^7.23.0",
|
"eslint": "^7.23.0",
|
||||||
"eslint-config-airbnb-typescript": "^12.0.0",
|
"eslint-config-airbnb-typescript": "^12.0.0",
|
||||||
|
|||||||
@@ -24,7 +24,7 @@
|
|||||||
"license": "AGPL-3.0-only",
|
"license": "AGPL-3.0-only",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/bson": "^4.0.2",
|
"@types/bson": "^4.0.2",
|
||||||
"@types/fs-extra": "^9.0.9",
|
"@types/fs-extra": "^9.0.10",
|
||||||
"@types/js-yaml": "^4.0.0",
|
"@types/js-yaml": "^4.0.0",
|
||||||
"@types/shell-quote": "^1.7.0"
|
"@types/shell-quote": "^1.7.0"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "hydrooj",
|
"name": "hydrooj",
|
||||||
"version": "2.21.8",
|
"version": "2.21.9",
|
||||||
"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",
|
||||||
@@ -38,8 +38,8 @@
|
|||||||
"yargs": "^16.2.0"
|
"yargs": "^16.2.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/adm-zip": "^0.4.33",
|
"@types/adm-zip": "^0.4.34",
|
||||||
"@types/fs-extra": "^9.0.9",
|
"@types/fs-extra": "^9.0.10",
|
||||||
"@types/inquirer": "^7.3.1",
|
"@types/inquirer": "^7.3.1",
|
||||||
"@types/js-yaml": "^4.0.0",
|
"@types/js-yaml": "^4.0.0",
|
||||||
"@types/koa": "^2.13.1",
|
"@types/koa": "^2.13.1",
|
||||||
@@ -47,7 +47,7 @@
|
|||||||
"@types/koa-static-cache": "^5.1.0",
|
"@types/koa-static-cache": "^5.1.0",
|
||||||
"@types/lodash": "^4.14.168",
|
"@types/lodash": "^4.14.168",
|
||||||
"@types/minio": "^7.0.7",
|
"@types/minio": "^7.0.7",
|
||||||
"@types/mongodb": "^3.6.11",
|
"@types/mongodb": "^3.6.12",
|
||||||
"@types/nodemailer": "^6.4.1",
|
"@types/nodemailer": "^6.4.1",
|
||||||
"@types/serialize-javascript": "^5.0.0",
|
"@types/serialize-javascript": "^5.0.0",
|
||||||
"@types/sockjs": "^0.3.32",
|
"@types/sockjs": "^0.3.32",
|
||||||
|
|||||||
@@ -32,6 +32,8 @@ async function _postJudge(rdoc: Rdoc) {
|
|||||||
? await problem.inc(rdoc.domainId, rdoc.pid, 'nAccept', 1)
|
? await problem.inc(rdoc.domainId, rdoc.pid, 'nAccept', 1)
|
||||||
: await problem.get(rdoc.domainId, rdoc.pid);
|
: await problem.get(rdoc.domainId, rdoc.pid);
|
||||||
const difficulty = difficultyAlgorithm(pdoc.nSubmit, pdoc.nAccept);
|
const difficulty = difficultyAlgorithm(pdoc.nSubmit, pdoc.nAccept);
|
||||||
|
if (!updated) await record.updateMulti(rdoc.domainId, { uid: rdoc.uid, status: builtin.STATUS.STATUS_ACCEPTED }, { effective: false });
|
||||||
|
await record.update(rdoc.domainId, rdoc._id, { effective: true });
|
||||||
await problem.edit(pdoc.domainId, pdoc.docId, { difficulty });
|
await problem.edit(pdoc.domainId, pdoc.docId, { difficulty });
|
||||||
await bus.serial('record/judge', rdoc, updated);
|
await bus.serial('record/judge', rdoc, updated);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -247,6 +247,7 @@ export interface Rdoc {
|
|||||||
progress?: number,
|
progress?: number,
|
||||||
input?: string,
|
input?: string,
|
||||||
contest?: ContestInfo,
|
contest?: ContestInfo,
|
||||||
|
effective?: boolean,
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ScoreboardNode {
|
export interface ScoreboardNode {
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
import {
|
import {
|
||||||
ObjectID, Collection, UpdateQuery, PushOperator, MatchKeysAndValues, OnlyFieldsOfType,
|
ObjectID, Collection, UpdateQuery,
|
||||||
|
PushOperator, MatchKeysAndValues, OnlyFieldsOfType,
|
||||||
|
FilterQuery,
|
||||||
} from 'mongodb';
|
} from 'mongodb';
|
||||||
import { Dictionary } from 'lodash';
|
import { Dictionary } from 'lodash';
|
||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
@@ -113,6 +115,20 @@ class RecordModel {
|
|||||||
return await RecordModel.get(domainId, _id);
|
return await RecordModel.get(domainId, _id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static async updateMulti(
|
||||||
|
domainId: string, $match: FilterQuery<Rdoc>,
|
||||||
|
$set?: MatchKeysAndValues<Rdoc>,
|
||||||
|
$push?: PushOperator<Rdoc>,
|
||||||
|
$unset?: OnlyFieldsOfType<Rdoc, any, true | '' | 1>,
|
||||||
|
) {
|
||||||
|
const $update: UpdateQuery<Rdoc> = {};
|
||||||
|
if ($set && Object.keys($set).length) $update.$set = $set;
|
||||||
|
if ($push && Object.keys($push).length) $update.$push = $push;
|
||||||
|
if ($unset && Object.keys($unset).length) $update.$unset = $unset;
|
||||||
|
const res = await RecordModel.coll.updateMany({ domainId, ...$match }, $update);
|
||||||
|
return res.modifiedCount;
|
||||||
|
}
|
||||||
|
|
||||||
static reset(domainId: string, rid: ObjectID, isRejudge: boolean) {
|
static reset(domainId: string, rid: ObjectID, isRejudge: boolean) {
|
||||||
const upd: any = {
|
const upd: any = {
|
||||||
score: 0,
|
score: 0,
|
||||||
|
|||||||
@@ -0,0 +1,40 @@
|
|||||||
|
/* eslint-disable no-await-in-loop */
|
||||||
|
import { DomainDoc } from './loader';
|
||||||
|
import domain from './model/domain';
|
||||||
|
import problem, { Field, Pdoc } from './model/problem';
|
||||||
|
|
||||||
|
export async function iterateAllDomain(cb: (ddoc: DomainDoc, current?: number, total?: number) => Promise<any>) {
|
||||||
|
const ddocs = await domain.getMulti().project({ _id: 1, owner: 1 }).toArray();
|
||||||
|
for (const i in ddocs) await cb(ddocs[i], +i, ddocs.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
interface PartialPdoc extends Pdoc {
|
||||||
|
[key: string]: any,
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function iterateAllProblemInDomain(
|
||||||
|
domainId: string,
|
||||||
|
fields: (Field | string)[],
|
||||||
|
cb: (pdoc: PartialPdoc, current?: number, total?: number) => Promise<any>,
|
||||||
|
) {
|
||||||
|
if (!fields.includes('domainId')) fields.push('domainId');
|
||||||
|
if (!fields.includes('docId')) fields.push('docId');
|
||||||
|
const cursor = problem.getMulti(domainId, {}, fields as any);
|
||||||
|
const total = await problem.getMulti(domainId, {}).count();
|
||||||
|
let i = 0;
|
||||||
|
while (await cursor.hasNext()) {
|
||||||
|
const doc = await cursor.next();
|
||||||
|
i++;
|
||||||
|
const res = await cb(doc, i, total);
|
||||||
|
if (res) await problem.edit(doc.domainId, doc.docId, res);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function iterateAllProblem(
|
||||||
|
fields: (Field | string)[],
|
||||||
|
cb: (pdoc: PartialPdoc, current?: number, total?: number) => Promise<any>,
|
||||||
|
) {
|
||||||
|
await iterateAllDomain(async (d) => {
|
||||||
|
await iterateAllProblemInDomain(d._id, fields, cb);
|
||||||
|
});
|
||||||
|
}
|
||||||
@@ -50,7 +50,7 @@ export async function udoc() {
|
|||||||
|
|
||||||
export async function pdoc() {
|
export async function pdoc() {
|
||||||
const pipeline = [
|
const pipeline = [
|
||||||
{ $match: { hidden: false, type: { $ne: 'run' } } },
|
{ $match: { hidden: false, type: { $ne: 'run' } }, effective: true },
|
||||||
{
|
{
|
||||||
$group: {
|
$group: {
|
||||||
_id: { domainId: '$domainId', pid: '$pid', uid: '$uid' },
|
_id: { domainId: '$domainId', pid: '$pid', uid: '$uid' },
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import storage from '../service/storage';
|
import storage from '../service/storage';
|
||||||
import { iterateAllProblem, iterateAllProblemInDomain } from '../upgrade';
|
import { iterateAllProblem, iterateAllProblemInDomain } from '../pipelineUtils';
|
||||||
|
|
||||||
export const description = 'Sync problem filelist from s3 service';
|
export const description = 'Sync problem filelist from s3 service';
|
||||||
|
|
||||||
|
|||||||
@@ -1,61 +1,28 @@
|
|||||||
/* eslint-disable @typescript-eslint/no-unused-vars */
|
/* eslint-disable @typescript-eslint/no-unused-vars */
|
||||||
/* eslint-disable no-await-in-loop */
|
/* eslint-disable no-await-in-loop */
|
||||||
import { ObjectID } from 'mongodb';
|
import { FilterQuery, ObjectID } from 'mongodb';
|
||||||
import AdmZip from 'adm-zip';
|
import AdmZip from 'adm-zip';
|
||||||
import Queue from 'p-queue';
|
import Queue from 'p-queue';
|
||||||
import yaml from 'js-yaml';
|
import yaml from 'js-yaml';
|
||||||
import { Progress } from './ui';
|
import { Progress } from './ui';
|
||||||
import { Logger } from './logger';
|
import { Logger } from './logger';
|
||||||
import { DomainDoc } from './loader';
|
|
||||||
import { streamToBuffer } from './utils';
|
import { streamToBuffer } from './utils';
|
||||||
|
import { iterateAllDomain, iterateAllProblem } from './pipelineUtils';
|
||||||
import gridfs from './service/gridfs';
|
import gridfs from './service/gridfs';
|
||||||
import storage from './service/storage';
|
import storage from './service/storage';
|
||||||
import db from './service/db';
|
import db from './service/db';
|
||||||
import problem, { Field, Pdoc } from './model/problem';
|
import problem from './model/problem';
|
||||||
import domain from './model/domain';
|
import domain from './model/domain';
|
||||||
import * as document from './model/document';
|
import * as document from './model/document';
|
||||||
import * as system from './model/system';
|
import * as system from './model/system';
|
||||||
import difficultyAlgorithm from './lib/difficulty';
|
import difficultyAlgorithm from './lib/difficulty';
|
||||||
|
import { STATUS } from './model/builtin';
|
||||||
|
import RecordModel from './model/record';
|
||||||
|
import { Rdoc } from './interface';
|
||||||
|
|
||||||
const logger = new Logger('upgrade');
|
const logger = new Logger('upgrade');
|
||||||
type UpgradeScript = void | (() => Promise<boolean | void>);
|
type UpgradeScript = void | (() => Promise<boolean | void>);
|
||||||
|
|
||||||
export async function iterateAllDomain(cb: (ddoc: DomainDoc, current?: number, total?: number) => Promise<any>) {
|
|
||||||
const ddocs = await domain.getMulti().project({ _id: 1, owner: 1 }).toArray();
|
|
||||||
for (const i in ddocs) await cb(ddocs[i], +i, ddocs.length);
|
|
||||||
}
|
|
||||||
|
|
||||||
interface PartialPdoc extends Pdoc {
|
|
||||||
[key: string]: any,
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function iterateAllProblemInDomain(
|
|
||||||
domainId: string,
|
|
||||||
fields: (Field | string)[],
|
|
||||||
cb: (pdoc: PartialPdoc, current?: number, total?: number) => Promise<any>,
|
|
||||||
) {
|
|
||||||
if (!fields.includes('domainId')) fields.push('domainId');
|
|
||||||
if (!fields.includes('docId')) fields.push('docId');
|
|
||||||
const cursor = problem.getMulti(domainId, {}, fields as any);
|
|
||||||
const total = await problem.getMulti(domainId, {}).count();
|
|
||||||
let i = 0;
|
|
||||||
while (await cursor.hasNext()) {
|
|
||||||
const doc = await cursor.next();
|
|
||||||
i++;
|
|
||||||
const res = await cb(doc, i, total);
|
|
||||||
if (res) await problem.edit(doc.domainId, doc.docId, res);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function iterateAllProblem(
|
|
||||||
fields: (Field | string)[],
|
|
||||||
cb: (pdoc: PartialPdoc, current?: number, total?: number) => Promise<any>,
|
|
||||||
) {
|
|
||||||
await iterateAllDomain(async (d) => {
|
|
||||||
await iterateAllProblemInDomain(d._id, fields, cb);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
const scripts: UpgradeScript[] = [
|
const scripts: UpgradeScript[] = [
|
||||||
// Mark as used
|
// Mark as used
|
||||||
null,
|
null,
|
||||||
@@ -262,6 +229,36 @@ const scripts: UpgradeScript[] = [
|
|||||||
});
|
});
|
||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
|
async function _19_20() {
|
||||||
|
const data = db.collection('record').aggregate([
|
||||||
|
{ $match: { hidden: false, type: { $ne: 'run' } } },
|
||||||
|
{
|
||||||
|
$group: {
|
||||||
|
_id: { domainId: '$domainId', pid: '$pid', uid: '$uid' },
|
||||||
|
nAccept: {
|
||||||
|
$sum: {
|
||||||
|
$cond: [{ $eq: ['$status', STATUS.STATUS_ACCEPTED] }, 1, 0],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
while (await data.hasNext()) {
|
||||||
|
const d: any = await data.next();
|
||||||
|
logger.info('%o', d);
|
||||||
|
const filter: FilterQuery<Rdoc> = { domainId: d._id.domainId, pid: d._id.pid, uid: d._id.uid };
|
||||||
|
if (d.nAccept) {
|
||||||
|
const [first] = await db.collection('record')
|
||||||
|
.find({ ...filter, status: STATUS.STATUS_ACCEPTED })
|
||||||
|
.sort({ _id: 1 }).limit(1)
|
||||||
|
.project({ _id: 1 })
|
||||||
|
.toArray();
|
||||||
|
filter._id = { $lte: first._id };
|
||||||
|
}
|
||||||
|
await db.collection('record').updateMany(filter, { $set: { effective: true } });
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
export default scripts;
|
export default scripts;
|
||||||
@@ -6,7 +6,7 @@
|
|||||||
"author": "undefined <i@undefined.moe>",
|
"author": "undefined <i@undefined.moe>",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/mongodb": "^3.6.11"
|
"@types/mongodb": "^3.6.12"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"mongodb": "^3.6.5"
|
"mongodb": "^3.6.5"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@hydrooj/sonic",
|
"name": "@hydrooj/sonic",
|
||||||
"version": "1.0.0",
|
"version": "1.0.1",
|
||||||
"description": "Sonic search service",
|
"description": "Sonic search service",
|
||||||
"main": "service.js",
|
"main": "service.js",
|
||||||
"typings": "service.d.ts",
|
"typings": "service.d.ts",
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { iterateAllProblem, iterateAllProblemInDomain } from 'hydrooj/dist/upgrade';
|
import { iterateAllProblem, iterateAllProblemInDomain } from 'hydrooj/dist/pipelineUtils';
|
||||||
import sonic from './service';
|
import sonic from './service';
|
||||||
|
|
||||||
export const description = 'Sonic problem search re-index';
|
export const description = 'Sonic problem search re-index';
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/cli": "^7.13.14",
|
"@babel/cli": "^7.13.14",
|
||||||
"@babel/core": "^7.13.14",
|
"@babel/core": "^7.13.14",
|
||||||
"@babel/eslint-parser": "7.13.10",
|
"@babel/eslint-parser": "7.13.14",
|
||||||
"@babel/plugin-proposal-class-properties": "^7.13.0",
|
"@babel/plugin-proposal-class-properties": "^7.13.0",
|
||||||
"@babel/plugin-proposal-export-namespace-from": "^7.12.13",
|
"@babel/plugin-proposal-export-namespace-from": "^7.12.13",
|
||||||
"@babel/plugin-proposal-function-sent": "^7.12.13",
|
"@babel/plugin-proposal-function-sent": "^7.12.13",
|
||||||
@@ -26,14 +26,14 @@
|
|||||||
"acorn": "^8.0.5",
|
"acorn": "^8.0.5",
|
||||||
"acorn-stage3": "^4.0.0",
|
"acorn-stage3": "^4.0.0",
|
||||||
"acorn-walk": "^8.0.2",
|
"acorn-walk": "^8.0.2",
|
||||||
"astring": "^1.6.2",
|
"astring": "^1.7.3",
|
||||||
"autoprefixer": "^9.8.6",
|
"autoprefixer": "^9.8.6",
|
||||||
"babel-loader": "^8.2.2",
|
"babel-loader": "^8.2.2",
|
||||||
"babel-plugin-lodash": "^3.3.4",
|
"babel-plugin-lodash": "^3.3.4",
|
||||||
"babel-plugin-prismjs": "^2.0.1",
|
"babel-plugin-prismjs": "^2.0.1",
|
||||||
"base-64": "^1.0.0",
|
"base-64": "^1.0.0",
|
||||||
"chalk": "^4.1.0",
|
"chalk": "^4.1.0",
|
||||||
"classnames": "^2.3.0",
|
"classnames": "^2.3.1",
|
||||||
"clipboard": "^2.0.8",
|
"clipboard": "^2.0.8",
|
||||||
"codemirror": "^5.59.4",
|
"codemirror": "^5.59.4",
|
||||||
"copy-webpack-plugin": "^6.1.1",
|
"copy-webpack-plugin": "^6.1.1",
|
||||||
@@ -105,7 +105,7 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"98.css": "^0.1.16",
|
"98.css": "^0.1.16",
|
||||||
"js-yaml": "^4.0.0",
|
"js-yaml": "^4.0.0",
|
||||||
"katex": "^0.13.0",
|
"katex": "^0.13.1",
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
"markdown-it": "^12.0.4",
|
"markdown-it": "^12.0.4",
|
||||||
"markdown-it-anchor": "^7.1.0",
|
"markdown-it-anchor": "^7.1.0",
|
||||||
|
|||||||
Reference in new issue
Block a user