mirror of
https://gitcode.com/gh_mirrors/hy/Hydro.git
synced 2026-10-20 01:38:19 +08:00
core: contest: scoreboard-view: add advanced checker
This commit is contained in:
1 parent
aba8d9c755
commit
06640c90fb
2 files changed
+24
-9
No files matched your search
@@ -825,6 +825,7 @@ export interface ScoreboardView<T extends { [key: string]: keyof BuiltinInput |
|
|||||||
cacheTime?: number; // in seconds
|
cacheTime?: number; // in seconds
|
||||||
args: T;
|
args: T;
|
||||||
display: (this: ContestScoreboardHandler, args: ParseArgs<T>) => Promise<void>;
|
display: (this: ContestScoreboardHandler, args: ParseArgs<T>) => Promise<void>;
|
||||||
|
checker?: (this: ContestScoreboardHandler) => boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class ContestScoreboardHandler extends ContestDetailBaseHandler {
|
export class ContestScoreboardHandler extends ContestDetailBaseHandler {
|
||||||
@@ -884,16 +885,17 @@ class ScoreboardService extends Service {
|
|||||||
|
|
||||||
addView<T extends { [key: string]: keyof BuiltinInput | AnyFunction | Type<any> }>(
|
addView<T extends { [key: string]: keyof BuiltinInput | AnyFunction | Type<any> }>(
|
||||||
id: string, name: string, args: T,
|
id: string, name: string, args: T,
|
||||||
{ display, supportedRules, cacheTime }: {
|
{ display, supportedRules, cacheTime, checker }: {
|
||||||
display: (this: ContestScoreboardHandler, args: ParseArgs<T>) => Promise<void>;
|
display: (this: ContestScoreboardHandler, args: ParseArgs<T>) => Promise<void>;
|
||||||
supportedRules: string[];
|
supportedRules: string[];
|
||||||
cacheTime?: number;
|
cacheTime?: number;
|
||||||
|
checker?: (this: ContestScoreboardHandler) => boolean;
|
||||||
},
|
},
|
||||||
) {
|
) {
|
||||||
if (this.views[id]) throw new Error(`View ${id} already exists`);
|
if (this.views[id]) throw new Error(`View ${id} already exists`);
|
||||||
this.ctx.effect(() => {
|
this.ctx.effect(() => {
|
||||||
this.views[id] = {
|
this.views[id] = {
|
||||||
id, name, args, display, supportedRules, cacheTime,
|
id, name, args, display, supportedRules, cacheTime, checker,
|
||||||
};
|
};
|
||||||
return () => {
|
return () => {
|
||||||
delete this.views[id];
|
delete this.views[id];
|
||||||
@@ -901,9 +903,11 @@ class ScoreboardService extends Service {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
getAvailableViews(rule: string) {
|
getAvailableViews(rule: string, handler: ContestScoreboardHandler) {
|
||||||
return Object.fromEntries(Object.values(this.views).filter((i) => i.supportedRules.includes(rule) || i.supportedRules.includes('*'))
|
return Object.fromEntries(Object.values(this.views).filter((i) => (
|
||||||
.map((i) => [i.id, i.name]));
|
(i.supportedRules.includes(rule) || i.supportedRules.includes('*'))
|
||||||
|
&& (!i.checker || i.checker.call(handler))
|
||||||
|
)).map((i) => [i.id, i.name]));
|
||||||
}
|
}
|
||||||
|
|
||||||
getView(id: string) {
|
getView(id: string) {
|
||||||
@@ -963,7 +967,7 @@ export async function apply(ctx: Context) {
|
|||||||
const page_name = tdoc.rule === 'homework'
|
const page_name = tdoc.rule === 'homework'
|
||||||
? 'homework_scoreboard'
|
? 'homework_scoreboard'
|
||||||
: 'contest_scoreboard';
|
: 'contest_scoreboard';
|
||||||
const availableViews = scoreboard.getAvailableViews(tdoc.rule);
|
const availableViews = scoreboard.getAvailableViews(tdoc.rule, this);
|
||||||
this.response.body = {
|
this.response.body = {
|
||||||
tdoc: this.tdoc, tsdoc: this.tsdocAsPublic(), rows, udict, pdict, page_name, groups, availableViews,
|
tdoc: this.tdoc, tsdoc: this.tsdocAsPublic(), rows, udict, pdict, page_name, groups, availableViews,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -144,6 +144,7 @@ export function apply(ctx: Context, config: ReturnType<typeof Config>) {
|
|||||||
...lockDuration && {
|
...lockDuration && {
|
||||||
scoreboard_freeze_duration: moment().startOf('day').seconds(lockDuration).format('HH:mm:ss.SSS'),
|
scoreboard_freeze_duration: moment().startOf('day').seconds(lockDuration).format('HH:mm:ss.SSS'),
|
||||||
},
|
},
|
||||||
|
scoreboard_type: tdoc.rule === 'acm' ? 'pass-fail' : 'score',
|
||||||
penalty_time: 20,
|
penalty_time: 20,
|
||||||
}),
|
}),
|
||||||
...Object.keys(STATUS_SHORT_TEXTS).map((i) => getFeed('judgement-types', {
|
...Object.keys(STATUS_SHORT_TEXTS).map((i) => getFeed('judgement-types', {
|
||||||
@@ -265,7 +266,12 @@ export function apply(ctx: Context, config: ReturnType<typeof Config>) {
|
|||||||
if (!ContestModel.isDone(tdoc)) throw new ContestNotEndedError();
|
if (!ContestModel.isDone(tdoc)) throw new ContestNotEndedError();
|
||||||
this.binary(await generateCdpZip(tdoc), `contest-${tdoc._id}-cdp.zip`);
|
this.binary(await generateCdpZip(tdoc), `contest-${tdoc._id}-cdp.zip`);
|
||||||
},
|
},
|
||||||
supportedRules: ['acm', 'oi'],
|
checker() {
|
||||||
|
return ContestModel.isDone(this.tdoc)
|
||||||
|
&& !!this.tdoc.lockAt
|
||||||
|
&& (this.user.own(this.tdoc) || this.user.hasPerm(PERM.PERM_EDIT_CONTEST));
|
||||||
|
},
|
||||||
|
supportedRules: ['acm', 'oi', 'ioi'],
|
||||||
});
|
});
|
||||||
|
|
||||||
scoreboard.addView('resolver', 'Resolver', { tdoc: 'tdoc' }, {
|
scoreboard.addView('resolver', 'Resolver', { tdoc: 'tdoc' }, {
|
||||||
@@ -279,10 +285,15 @@ export function apply(ctx: Context, config: ReturnType<typeof Config>) {
|
|||||||
const source = new URL(`/d/${tdoc.domainId}/contest/${tdoc._id}/resolver-cdp/${tokenId}`, SystemModel.get('server.url')).toString();
|
const source = new URL(`/d/${tdoc.domainId}/contest/${tdoc._id}/resolver-cdp/${tokenId}`, SystemModel.get('server.url')).toString();
|
||||||
const target = new URL('https://resolver.hydrooj.com');
|
const target = new URL('https://resolver.hydrooj.com');
|
||||||
target.searchParams.set('source', source);
|
target.searchParams.set('source', source);
|
||||||
target.searchParams.set('mode', tdoc.rule === 'oi' ? 'oi' : 'acm');
|
target.searchParams.set('mode', tdoc.rule === 'acm' ? 'acm' : 'oi');
|
||||||
this.response.redirect = target.toString();
|
this.response.redirect = target.toString();
|
||||||
},
|
},
|
||||||
supportedRules: ['acm', 'oi'],
|
checker() {
|
||||||
|
return ContestModel.isDone(this.tdoc)
|
||||||
|
&& !!this.tdoc.lockAt
|
||||||
|
&& (this.user.own(this.tdoc) || this.user.hasPerm(PERM.PERM_EDIT_CONTEST));
|
||||||
|
},
|
||||||
|
supportedRules: ['acm', 'oi', 'ioi'],
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user