(domainId: string, page = 1, q = '', limit: number, pjax = false, quick = false, sortStrategy = 'default')
| 107 | @param('quick', Types.Boolean) |
| 108 | @param('sort', Types.Range(['default', 'recent']), true) |
| 109 | async get(domainId: string, page = 1, q = '', limit: number, pjax = false, quick = false, sortStrategy = 'default') { |
| 110 | this.response.template = 'problem_main.html'; |
| 111 | if (!limit || limit > this.ctx.setting.get('pagination.problem') || page > 1) limit = this.ctx.setting.get('pagination.problem'); |
| 112 | this.queryContext.query = buildQuery(this.user); |
| 113 | if (sortStrategy === 'recent') this.queryContext.hint = 'basic'; |
| 114 | // eslint-disable-next-line ts/no-shadow |
| 115 | const query = this.queryContext.query; |
| 116 | const psdict = {}; |
| 117 | const search = Object.values(global.Hydro.module.problemSearch)[0] || defaultSearch; |
| 118 | const parsed = parser.parse(q, { |
| 119 | keywords: ['category', 'difficulty', 'namespace'], |
| 120 | offsets: false, |
| 121 | alwaysArray: true, |
| 122 | tokenize: true, |
| 123 | }); |
| 124 | const category = parsed.category || []; |
| 125 | const text = (parsed.text || []).join(' '); |
| 126 | if (parsed.difficulty?.every((i) => Number.isSafeInteger(+i))) { |
| 127 | query.difficulty = { $in: parsed.difficulty.flatMap((i) => +i === 0 ? [0, undefined] : [+i]) }; |
| 128 | } |
| 129 | if (category.length) query.$and = category.map((tag) => ({ tag })); |
| 130 | if (parsed.namespace?.length) { |
| 131 | const mappedPrefix = this.domain.namespaces?.[parsed.namespace[0]]; |
| 132 | query.$and ||= []; |
| 133 | if (mappedPrefix) query.$and.push({ sort: new RegExp(`^${mappedPrefix}-`) }); |
| 134 | else query.$and.push({ tag: parsed.namespace[0] }); |
| 135 | } |
| 136 | if (text) category.push(text); |
| 137 | if (category.length) this.UiContext.extraTitleContent = category.join(','); |
| 138 | let total = 0; |
| 139 | if (text) { |
| 140 | const result = await search(domainId, q, { skip: (page - 1) * limit, limit }); |
| 141 | total = result.total; |
| 142 | this.queryContext.pcountRelation = result.countRelation; |
| 143 | if (!result.hits.length) this.queryContext.fail = true; |
| 144 | query.docId = { $in: result.hits.map((t) => +t.split('/')[1]) }; |
| 145 | this.queryContext.hint = 'basic'; |
| 146 | this.queryContext.sort = result.hits; |
| 147 | } |
| 148 | const sort = this.queryContext.sort; |
| 149 | await this.ctx.parallel('problem/list', query, this, sort); |
| 150 | const sortKey = ({ |
| 151 | default: { sort: 1, docId: 1 }, |
| 152 | recent: { docId: -1 }, |
| 153 | } as const)[sortStrategy]; |
| 154 | let [pdocs, ppcount, pcount] = this.queryContext.fail |
| 155 | ? [[], 0, 0] |
| 156 | : await this.paginate( |
| 157 | problem.getMulti(domainId, query, quick ? ['title', 'pid', 'domainId', 'docId'] : undefined) |
| 158 | .sort(sortKey).hint(this.queryContext.hint), |
| 159 | sort.length ? 1 : page, limit, |
| 160 | ); |
| 161 | if (total) { |
| 162 | pcount = total; |
| 163 | ppcount = Math.ceil(total / limit); |
| 164 | } |
| 165 | if (sort.length) pdocs = pdocs.sort((a, b) => sort.indexOf(`${a.domainId}/${a.docId}`) - sort.indexOf(`${b.domainId}/${b.docId}`)); |
| 166 | if (text && pcount > pdocs.length) pcount = pdocs.length; |
no test coverage detected