Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 15 additions & 2 deletions packages/hydrooj/src/handler/problem.ts
Original file line number Diff line number Diff line change
Expand Up @@ -753,6 +753,7 @@ export class ProblemEditHandler extends ProblemManageHandler {
@post('hidden', Types.Boolean)
@post('tag', Types.Content, true, null, parseCategory)
@post('difficulty', Types.PositiveInt, (i) => +i <= 10, true)
@param('index', Types.PositiveInt, true)
async post(
domainId: string,
pid: string | number,
Expand All @@ -762,6 +763,7 @@ export class ProblemEditHandler extends ProblemManageHandler {
hidden = false,
tag: string[] = [],
difficulty = 0,
index = 0,
) {
if (typeof newPid !== 'string') newPid = `P${newPid}`;
if (newPid !== this.pdoc.pid && (await problem.get(domainId, newPid))) throw new ProblemAlreadyExistError(pid);
Expand All @@ -773,6 +775,7 @@ export class ProblemEditHandler extends ProblemManageHandler {
tag: tag ?? [],
difficulty,
html: false,
index,
};
const pdoc = await problem.edit(domainId, this.pdoc.docId, $update);
this.response.redirect = this.url('problem_detail', { pid: newPid || pdoc.docId });
Expand Down Expand Up @@ -1121,10 +1124,20 @@ export class ProblemCreateHandler extends Handler {
@post('hidden', Types.Boolean)
@post('difficulty', Types.PositiveInt, (i) => +i <= 10, true)
@post('tag', Types.Content, true, null, parseCategory)
async post(domainId: string, title: string, content: string, pid: string | number = '', hidden = false, difficulty = 0, tag: string[] = []) {
@post('index', Types.PositiveInt, true)
async post(
domainId: string,
title: string,
content: string,
pid: string | number = '',
hidden = false,
difficulty = 0,
tag: string[] = [],
index = 0,
) {
if (typeof pid !== 'string') pid = `P${pid}`;
if (pid && (await problem.get(domainId, pid))) throw new ProblemAlreadyExistError(pid);
const docId = await problem.add(domainId, pid, title, content, this.user._id, tag ?? [], { hidden, difficulty });
const docId = await problem.add(domainId, pid, title, content, this.user._id, tag ?? [], { hidden, difficulty, index });
const files = new Set(Array.from(content.matchAll(/file:\/\/([a-zA-Z0-9_-]+\.[a-zA-Z0-9]+)/g)).map((i) => i[1]));
const tasks = [];
for (const file of files) {
Expand Down
2 changes: 2 additions & 0 deletions packages/hydrooj/src/interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -296,6 +296,8 @@ declare module './model/problem' {

/** string (errormsg) */
config: string | ProblemConfig;

index?: number;
}
}
export type { ProblemDoc } from './model/problem';
Expand Down
35 changes: 20 additions & 15 deletions packages/hydrooj/src/model/problem.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,12 @@ export interface ProblemDoc extends Document {}

export type Field = keyof ProblemDoc;

export type ProblemMeta = {
difficulty?: number;
hidden?: boolean;
index?: number;
};

const logger = new Logger('problem');

function sortable(source: string) {
Expand Down Expand Up @@ -117,18 +123,9 @@ export class ProblemModel {
difficulty: 0,
};

static async add(
domainId: string,
pid: string = '',
title: string,
content: string,
owner: number,
tag: string[] = [],
meta: { difficulty?: number; hidden?: boolean } = {},
) {
static async add(domainId: string, pid: string = '', title: string, content: string, owner: number, tag: string[] = [], meta: ProblemMeta = {}) {
const [doc] = await ProblemModel.getMulti(domainId, {}).sort({ docId: -1 }).limit(1).project({ docId: 1 }).toArray();
const result = await ProblemModel.addWithId(domainId, (doc?.docId || 0) + 1, pid, title, content, owner, tag, meta);
return result;
return await ProblemModel.addWithId(domainId, (doc?.docId || 0) + 1, pid, title, content, owner, tag, meta);
}

static async addWithId(
Expand All @@ -139,7 +136,7 @@ export class ProblemModel {
content: string,
owner: number,
tag: string[] = [],
meta: { difficulty?: number; hidden?: boolean } = {},
meta: ProblemMeta = {},
) {
const args: Partial<ProblemDoc> = {
title,
Expand All @@ -151,6 +148,7 @@ export class ProblemModel {
};
if (pid) args.pid = pid;
if (meta.difficulty) args.difficulty = meta.difficulty;
if (meta.index) args.index = meta.index;
await bus.parallel('problem/before-add', domainId, content, owner, docId, args);
const result = await document.add(domainId, content, owner, document.TYPE_PROBLEM, docId, null, null, args);
args.content = content;
Expand Down Expand Up @@ -182,7 +180,7 @@ export class ProblemModel {
}

static getMulti(domainId: string, query: Filter<ProblemDoc>, projection = ProblemModel.PROJECTION_LIST) {
return document.getMulti(domainId, document.TYPE_PROBLEM, query, projection).sort({ sort: 1 });
return document.getMulti(domainId, document.TYPE_PROBLEM, query, projection).sort({ index: -1, sort: 1 });
}

static async list(
Expand All @@ -206,7 +204,14 @@ export class ProblemModel {
}
if (filter) {
// 当filter存在时做全文查询
let docs = await document.getMulti(id, document.TYPE_PROBLEM, query, projection).sort({ sort: 1, docId: 1 }).toArray();
let docs = await document
.getMulti(id, document.TYPE_PROBLEM, query, projection)
.sort({
index: -1,
sort: 1,
docId: 1,
})
.toArray();
docs = docs.filter(filter);
count += docs.length; // 查询到所有文档的数量
if (pdocs.length >= pageSize) continue;
Expand All @@ -221,7 +226,7 @@ export class ProblemModel {
pdocs.push(
...(await document
.getMulti(id, document.TYPE_PROBLEM, query, projection)
.sort({ sort: 1, docId: 1 })
.sort({ index: -1, sort: 1, docId: 1 })
.skip(Math.max((page - 1) * pageSize - count, 0))
.limit(pageSize - pdocs.length)
.toArray()),
Expand Down