mirror of
https://gitcode.com/gh_mirrors/hy/Hydro.git
synced 2026-10-17 09:36:08 +08:00
core: problem_list: move getByPid to search side
This commit is contained in:
2 files changed
+45
-26
No files matched your search
@@ -38,10 +38,18 @@ global.Hydro.lib.problemSearch = async (domainId, q, opts) => {
|
||||
},
|
||||
},
|
||||
});
|
||||
let hits = res.hits.hits.map((i) => i._id);
|
||||
if (!opts.skip) {
|
||||
const pdoc = await ProblemModel.get(domainId, +q || q, ProblemModel.PROJECTION_LIST);
|
||||
if (pdoc) {
|
||||
hits = hits.filter((i) => i !== `${pdoc.domainId}/${pdoc.docId}`);
|
||||
hits.unshift(`${pdoc.domainId}/${pdoc.docId}`);
|
||||
}
|
||||
}
|
||||
return {
|
||||
countRelation: typeof res.hits.total === 'number' ? 'eq' : res.hits.total.relation,
|
||||
total: typeof res.hits.total === 'number' ? res.hits.total : res.hits.total.value,
|
||||
hits: res.hits.hits.map((i) => i._id),
|
||||
hits,
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -118,18 +118,40 @@ const defaultSearch = async (domainId: string, q: string, options?: ProblemSearc
|
||||
const filter = { $or: [{ pid: { $regex } }, { title: { $regex } }, { tag: q }] };
|
||||
const pdocs = await problem.getMulti(domainId, filter, ['domainId', 'docId', 'pid'])
|
||||
.skip(options.skip || 0).limit(options.limit || system.get('pagination.problem')).toArray();
|
||||
if (!Number.isNaN(+q)) {
|
||||
const pdoc = await problem.get(domainId, +q, ['domainId', 'docId', 'pid', 'title']);
|
||||
if (!options.skip) {
|
||||
const pdoc = await problem.get(domainId, +q || q, ['domainId', 'docId', 'pid', 'title']);
|
||||
if (pdoc) pdocs.unshift(pdoc);
|
||||
}
|
||||
return {
|
||||
hits: pdocs.map((i) => `${i.domainId}/${i.docId}`),
|
||||
total: await problem.count(domainId, filter),
|
||||
total: Math.max(pdocs.length, await problem.count(domainId, filter)),
|
||||
countRelation: 'eq',
|
||||
};
|
||||
};
|
||||
|
||||
export interface QueryContext {
|
||||
query: Filter<ProblemDoc>;
|
||||
sort: string[];
|
||||
pcountRelation: string;
|
||||
parsed: ReturnType<typeof parser.parse>;
|
||||
category: string[];
|
||||
text: string;
|
||||
total: number;
|
||||
fail: boolean;
|
||||
}
|
||||
|
||||
export class ProblemMainHandler extends Handler {
|
||||
queryContext: QueryContext = {
|
||||
query: {},
|
||||
sort: [],
|
||||
pcountRelation: 'eq',
|
||||
parsed: null,
|
||||
category: [],
|
||||
text: '',
|
||||
total: 0,
|
||||
fail: false,
|
||||
};
|
||||
|
||||
@param('page', Types.PositiveInt, true)
|
||||
@param('q', Types.Content, true)
|
||||
@param('limit', Types.PositiveInt, true)
|
||||
@@ -137,13 +159,11 @@ export class ProblemMainHandler extends Handler {
|
||||
async get(domainId: string, page = 1, q = '', limit: number, pjax = false) {
|
||||
this.response.template = 'problem_main.html';
|
||||
if (!limit || limit > this.ctx.setting.get('pagination.problem') || page > 1) limit = this.ctx.setting.get('pagination.problem');
|
||||
this.queryContext.query = buildQuery(this.user);
|
||||
// eslint-disable-next-line @typescript-eslint/no-shadow
|
||||
const query = buildQuery(this.user);
|
||||
const query = this.queryContext.query;
|
||||
const psdict = {};
|
||||
const search = global.Hydro.lib.problemSearch || defaultSearch;
|
||||
let sort: string[] = [];
|
||||
let fail = false;
|
||||
let pcountRelation = 'eq';
|
||||
const parsed = parser.parse(q, {
|
||||
keywords: ['category', 'difficulty'],
|
||||
offsets: false,
|
||||
@@ -162,8 +182,8 @@ export class ProblemMainHandler extends Handler {
|
||||
if (text) {
|
||||
const result = await search(domainId, q, { skip: (page - 1) * limit, limit });
|
||||
total = result.total;
|
||||
pcountRelation = result.countRelation;
|
||||
if (!result.hits.length) fail = true;
|
||||
this.queryContext.pcountRelation = result.countRelation;
|
||||
if (!result.hits.length) this.queryContext.fail = true;
|
||||
query.$and ||= [];
|
||||
query.$and.push({
|
||||
$or: result.hits.map((i) => {
|
||||
@@ -171,27 +191,19 @@ export class ProblemMainHandler extends Handler {
|
||||
return { domainId: did, docId: +docId };
|
||||
}),
|
||||
});
|
||||
sort = result.hits;
|
||||
this.queryContext.sort = result.hits;
|
||||
}
|
||||
const sort = this.queryContext.sort;
|
||||
await this.ctx.parallel('problem/list', query, this, sort);
|
||||
// eslint-disable-next-line prefer-const
|
||||
let [pdocs, ppcount, pcount] = fail
|
||||
let [pdocs, ppcount, pcount] = this.queryContext.fail
|
||||
? [[], 0, 0]
|
||||
: await problem.list(domainId, query, sort?.length ? 1 : page, limit, undefined, this.user._id);
|
||||
: await problem.list(domainId, query, sort.length ? 1 : page, limit, undefined, this.user._id);
|
||||
if (total) {
|
||||
pcount = total;
|
||||
ppcount = Math.ceil(total / limit);
|
||||
}
|
||||
if (sort.length) pdocs = pdocs.sort((a, b) => sort.indexOf(`${a.domainId}/${a.docId}`) - sort.indexOf(`${b.domainId}/${b.docId}`));
|
||||
if (q && page === 1) {
|
||||
const pdoc = await problem.get(domainId, +q || q, problem.PROJECTION_LIST);
|
||||
if (pdoc && problem.canViewBy(pdoc, this.user)) {
|
||||
const count = pdocs.length;
|
||||
pdocs = pdocs.filter((doc) => doc.docId !== pdoc.docId);
|
||||
pdocs.unshift(pdoc);
|
||||
pcount = pcount - count + pdocs.length;
|
||||
}
|
||||
}
|
||||
if (text && pcount > pdocs.length) pcount = pdocs.length;
|
||||
if (this.user.hasPriv(PRIV.PRIV_USER_PROFILE)) {
|
||||
const domainIds = Array.from(new Set(pdocs.map((i) => i.domainId)));
|
||||
@@ -210,7 +222,7 @@ export class ProblemMainHandler extends Handler {
|
||||
this.renderHTML('partials/problem_list.html', {
|
||||
page, ppcount, pcount, pdocs, psdict, qs: q,
|
||||
}),
|
||||
this.renderHTML('partials/problem_stat.html', { pcount, pcountRelation }),
|
||||
this.renderHTML('partials/problem_stat.html', { pcount, pcountRelation: this.queryContext.pcountRelation }),
|
||||
this.renderHTML('partials/problem_lucky.html', { qs: q }),
|
||||
])).map((i) => ({ html: i })),
|
||||
};
|
||||
@@ -219,7 +231,7 @@ export class ProblemMainHandler extends Handler {
|
||||
page,
|
||||
pcount,
|
||||
ppcount,
|
||||
pcountRelation,
|
||||
pcountRelation: this.queryContext.pcountRelation,
|
||||
pdocs,
|
||||
psdict,
|
||||
qs: q,
|
||||
@@ -595,7 +607,7 @@ export class ProblemHackHandler extends ProblemDetailHandler {
|
||||
const id = `${this.user._id}/${nanoid()}`;
|
||||
if (this.request.files?.file?.size > 0) {
|
||||
const file = this.request.files.file;
|
||||
if (!file || file.size > 128 * 1024 * 1024) throw new ValidationError('input');
|
||||
if (!file || file.size > 2 * 1024 * 1024) throw new ValidationError('input');
|
||||
await storage.put(`submission/${id}`, file.filepath, this.user._id);
|
||||
} else if (input) {
|
||||
if (autoOrganizeInput) input = input.replace(/\s+\n/g, '\n').replace(/\s+ /g, ' ');
|
||||
@@ -611,7 +623,6 @@ export class ProblemHackHandler extends ProblemDetailHandler {
|
||||
files: { hack: `${id}#input.txt` },
|
||||
},
|
||||
);
|
||||
// TODO contest: update status;
|
||||
this.response.body = { rid };
|
||||
this.response.redirect = this.url('record_detail', { rid });
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user