mirror of
https://gitcode.com/gh_mirrors/hy/Hydro.git
synced 2026-10-20 01:38:19 +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 {
|
return {
|
||||||
countRelation: typeof res.hits.total === 'number' ? 'eq' : res.hits.total.relation,
|
countRelation: typeof res.hits.total === 'number' ? 'eq' : res.hits.total.relation,
|
||||||
total: typeof res.hits.total === 'number' ? res.hits.total : res.hits.total.value,
|
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 filter = { $or: [{ pid: { $regex } }, { title: { $regex } }, { tag: q }] };
|
||||||
const pdocs = await problem.getMulti(domainId, filter, ['domainId', 'docId', 'pid'])
|
const pdocs = await problem.getMulti(domainId, filter, ['domainId', 'docId', 'pid'])
|
||||||
.skip(options.skip || 0).limit(options.limit || system.get('pagination.problem')).toArray();
|
.skip(options.skip || 0).limit(options.limit || system.get('pagination.problem')).toArray();
|
||||||
if (!Number.isNaN(+q)) {
|
if (!options.skip) {
|
||||||
const pdoc = await problem.get(domainId, +q, ['domainId', 'docId', 'pid', 'title']);
|
const pdoc = await problem.get(domainId, +q || q, ['domainId', 'docId', 'pid', 'title']);
|
||||||
if (pdoc) pdocs.unshift(pdoc);
|
if (pdoc) pdocs.unshift(pdoc);
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
hits: pdocs.map((i) => `${i.domainId}/${i.docId}`),
|
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',
|
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 {
|
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('page', Types.PositiveInt, true)
|
||||||
@param('q', Types.Content, true)
|
@param('q', Types.Content, true)
|
||||||
@param('limit', Types.PositiveInt, 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) {
|
async get(domainId: string, page = 1, q = '', limit: number, pjax = false) {
|
||||||
this.response.template = 'problem_main.html';
|
this.response.template = 'problem_main.html';
|
||||||
if (!limit || limit > this.ctx.setting.get('pagination.problem') || page > 1) limit = this.ctx.setting.get('pagination.problem');
|
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
|
// eslint-disable-next-line @typescript-eslint/no-shadow
|
||||||
const query = buildQuery(this.user);
|
const query = this.queryContext.query;
|
||||||
const psdict = {};
|
const psdict = {};
|
||||||
const search = global.Hydro.lib.problemSearch || defaultSearch;
|
const search = global.Hydro.lib.problemSearch || defaultSearch;
|
||||||
let sort: string[] = [];
|
|
||||||
let fail = false;
|
|
||||||
let pcountRelation = 'eq';
|
|
||||||
const parsed = parser.parse(q, {
|
const parsed = parser.parse(q, {
|
||||||
keywords: ['category', 'difficulty'],
|
keywords: ['category', 'difficulty'],
|
||||||
offsets: false,
|
offsets: false,
|
||||||
@@ -162,8 +182,8 @@ export class ProblemMainHandler extends Handler {
|
|||||||
if (text) {
|
if (text) {
|
||||||
const result = await search(domainId, q, { skip: (page - 1) * limit, limit });
|
const result = await search(domainId, q, { skip: (page - 1) * limit, limit });
|
||||||
total = result.total;
|
total = result.total;
|
||||||
pcountRelation = result.countRelation;
|
this.queryContext.pcountRelation = result.countRelation;
|
||||||
if (!result.hits.length) fail = true;
|
if (!result.hits.length) this.queryContext.fail = true;
|
||||||
query.$and ||= [];
|
query.$and ||= [];
|
||||||
query.$and.push({
|
query.$and.push({
|
||||||
$or: result.hits.map((i) => {
|
$or: result.hits.map((i) => {
|
||||||
@@ -171,27 +191,19 @@ export class ProblemMainHandler extends Handler {
|
|||||||
return { domainId: did, docId: +docId };
|
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);
|
await this.ctx.parallel('problem/list', query, this, sort);
|
||||||
// eslint-disable-next-line prefer-const
|
// eslint-disable-next-line prefer-const
|
||||||
let [pdocs, ppcount, pcount] = fail
|
let [pdocs, ppcount, pcount] = this.queryContext.fail
|
||||||
? [[], 0, 0]
|
? [[], 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) {
|
if (total) {
|
||||||
pcount = total;
|
pcount = total;
|
||||||
ppcount = Math.ceil(total / limit);
|
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 (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 (text && pcount > pdocs.length) pcount = pdocs.length;
|
||||||
if (this.user.hasPriv(PRIV.PRIV_USER_PROFILE)) {
|
if (this.user.hasPriv(PRIV.PRIV_USER_PROFILE)) {
|
||||||
const domainIds = Array.from(new Set(pdocs.map((i) => i.domainId)));
|
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', {
|
this.renderHTML('partials/problem_list.html', {
|
||||||
page, ppcount, pcount, pdocs, psdict, qs: q,
|
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 }),
|
this.renderHTML('partials/problem_lucky.html', { qs: q }),
|
||||||
])).map((i) => ({ html: i })),
|
])).map((i) => ({ html: i })),
|
||||||
};
|
};
|
||||||
@@ -219,7 +231,7 @@ export class ProblemMainHandler extends Handler {
|
|||||||
page,
|
page,
|
||||||
pcount,
|
pcount,
|
||||||
ppcount,
|
ppcount,
|
||||||
pcountRelation,
|
pcountRelation: this.queryContext.pcountRelation,
|
||||||
pdocs,
|
pdocs,
|
||||||
psdict,
|
psdict,
|
||||||
qs: q,
|
qs: q,
|
||||||
@@ -595,7 +607,7 @@ export class ProblemHackHandler extends ProblemDetailHandler {
|
|||||||
const id = `${this.user._id}/${nanoid()}`;
|
const id = `${this.user._id}/${nanoid()}`;
|
||||||
if (this.request.files?.file?.size > 0) {
|
if (this.request.files?.file?.size > 0) {
|
||||||
const file = this.request.files.file;
|
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);
|
await storage.put(`submission/${id}`, file.filepath, this.user._id);
|
||||||
} else if (input) {
|
} else if (input) {
|
||||||
if (autoOrganizeInput) input = input.replace(/\s+\n/g, '\n').replace(/\s+ /g, ' ');
|
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` },
|
files: { hack: `${id}#input.txt` },
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
// TODO contest: update status;
|
|
||||||
this.response.body = { rid };
|
this.response.body = { rid };
|
||||||
this.response.redirect = this.url('record_detail', { rid });
|
this.response.redirect = this.url('record_detail', { rid });
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in new issue
Block a user