@@ -2,13 +2,19 @@ import { exec } from 'child_process';
22import { inspect } from 'util' ;
33import * as yaml from 'js-yaml' ;
44import { omit } from 'lodash' ;
5+ import moment from 'moment' ;
6+ import { Filter , ObjectId } from 'mongodb' ;
57import Schema from 'schemastery' ;
8+ import { Time } from '@hydrooj/utils' ;
69import {
7- CannotEditSuperAdminError , NotLaunchedByPM2Error , UserNotFoundError , ValidationError ,
10+ CannotEditSuperAdminError , ContestNotFoundError , NotLaunchedByPM2Error , ProblemNotFoundError , RecordNotFoundError , UserNotFoundError , ValidationError ,
811} from '../error' ;
12+ import { RecordDoc } from '../interface' ;
913import { Logger } from '../logger' ;
10- import { PRIV , STATUS } from '../model/builtin' ;
14+ import { NORMAL_STATUS , PRIV , STATUS } from '../model/builtin' ;
15+ import * as contest from '../model/contest' ;
1116import domain from '../model/domain' ;
17+ import problem from '../model/problem' ;
1218import record from '../model/record' ;
1319import * as setting from '../model/setting' ;
1420import * as system from '../model/system' ;
@@ -359,33 +365,99 @@ class SystemUserPrivHandler extends SystemHandler {
359365
360366class SystemRejudgeHandler extends SystemHandler {
361367 async get ( ) {
362- const rrdocs = await record . getMultiRejudgeTask ( { } ) ;
363- this . response . body . rrdocs = rrdocs ;
368+ this . response . body = {
369+ rrdocs : await record . getMultiRejudgeTask ( { } ) ,
370+ apply : true ,
371+ status : NORMAL_STATUS . filter ( ( i : STATUS ) => ! [ STATUS . STATUS_COMPILE_ERROR , STATUS . STATUS_ACCEPTED ] . includes ( i ) ) . join ( ',' ) ,
372+ } ;
364373 this . response . template = 'manage_rejudge.html' ;
365374 }
366375
367- @param ( 'domainId' , Types . String , true )
368- @param ( 'pid' , Types . Int , true )
369- @param ( 'uid' , Types . Int , true )
370- @param ( 'contest' , Types . String , true )
371- @param ( 'lang' , Types . String , true )
372- @param ( 'status' , Types . Int , true )
376+ @param ( 'uidOrName' , Types . UidOrName , true )
377+ @param ( 'pid' , Types . ProblemId , true )
378+ @param ( 'tid' , Types . ObjectId , true )
379+ @param ( 'langs' , Types . CommaSeperatedArray , true )
380+ @param ( 'beginAtDate' , Types . Date , true )
381+ @param ( 'beginAtTime' , Types . Time , true )
382+ @param ( 'endAtDate' , Types . Date , true )
383+ @param ( 'endAtTime' , Types . Time , true )
384+ @param ( 'status' , Types . CommaSeperatedArray , true )
385+ @param ( 'type' , Types . Range ( [ 'preview' , 'rejudge' ] ) )
386+ @param ( 'high_priority' , Types . Boolean )
373387 @param ( 'apply' , Types . Boolean )
374- async post ( domainId : string , pid : number , uid : number , contest : string , lang : string , status : number , _apply = false ) {
388+ async post (
389+ domainId : string , uidOrName ?: string , pid ?: string | number , tid ?: ObjectId ,
390+ langs : string [ ] = [ ] , beginAtDate ?: string , beginAtTime ?: string , endAtDate ?: string ,
391+ endAtTime ?: string , status : string [ ] = [ ] , _type = 'rejudge' , highPriority = false , _apply = false ,
392+ ) {
393+ const q : Filter < RecordDoc > = { } ;
394+ if ( uidOrName ) {
395+ const udoc = await user . getById ( domainId , + uidOrName )
396+ || await user . getByUname ( domainId , uidOrName )
397+ || await user . getByEmail ( domainId , uidOrName ) ;
398+ if ( udoc ) q . uid = udoc . _id ;
399+ else throw new UserNotFoundError ( uidOrName ) ;
400+ }
401+ if ( tid ) {
402+ const tdoc = await contest . get ( domainId , tid ) ;
403+ if ( ! tdoc ) throw new ContestNotFoundError ( domainId , tid ) ;
404+ q . contest = tdoc . _id ;
405+ }
406+ if ( pid ) {
407+ const pdoc = await problem . get ( domainId , pid ) ;
408+ if ( pdoc ) q . pid = pdoc . docId ;
409+ else throw new ProblemNotFoundError ( domainId , pid ) ;
410+ }
411+ if ( langs . length ) q . lang = { $in : langs . filter ( ( i ) => setting . langs [ i ] ) } ;
412+ let beginAt = null ;
413+ let endAt = null ;
414+ if ( beginAtDate ) {
415+ beginAt = moment ( `${ beginAtDate } ${ beginAtTime || '00:00' } ` ) ;
416+ if ( ! beginAt . isValid ( ) ) throw new ValidationError ( 'beginAtDate' , 'beginAtTime' ) ;
417+ q . _id ||= { } ;
418+ q . _id = { ...q . _id , $gte : Time . getObjectID ( beginAt ) } ;
419+ }
420+ if ( endAtDate ) {
421+ endAt = moment ( `${ endAtDate } ${ endAtTime || '23:59' } ` ) ;
422+ if ( ! endAt . isValid ( ) ) throw new ValidationError ( 'endAtDate' , 'endAtTime' ) ;
423+ q . _id ||= { } ;
424+ q . _id = { ...q . _id , $lte : Time . getObjectID ( endAt ) } ;
425+ }
426+ if ( beginAt && endAt && beginAt . isSameOrAfter ( endAt ) ) throw new ValidationError ( 'duration' ) ;
427+ const rids = await record . getMulti ( domainId , q ) . project ( { _id : 1 } ) . toArray ( ) ;
428+ if ( _type === 'preview' ) {
429+ this . response . body = {
430+ uidOrName,
431+ pid,
432+ tid,
433+ langs : langs . join ( ',' ) ,
434+ beginAtDate,
435+ beginAtTime,
436+ endAtDate,
437+ endAtTime,
438+ status : status . join ( ',' ) ,
439+ highPriority,
440+ apply : _apply ,
441+ recordLength : rids . length ,
442+ rrdocs : await record . getMultiRejudgeTask ( { } ) ,
443+ } ;
444+ this . response . template = 'manage_rejudge.html' ;
445+ return ;
446+ }
375447 const rid = await record . add ( domainId , - 1 , this . user . _id , '-' , 'rejudge' , false , {
376448 input : JSON . stringify ( {
377- pid, uid, contest, lang, status, apply : _apply ,
449+ domainId,
450+ rids : rids . map ( ( i ) => i . _id . toString ( ) ) ,
451+ highPriority,
452+ apply : _apply ,
378453 } ) ,
379454 type : 'rejudge' ,
380455 } ) ;
381456 const args = global . Hydro . script [ 'rejudge' ] . validate ( {
382457 rrid : rid . toHexString ( ) ,
383458 domainId,
384- uid,
385- pid,
386- contest,
387- lang,
388- status,
459+ rids : rids . map ( ( i ) => i . _id . toString ( ) ) ,
460+ highPriority,
389461 apply : _apply ,
390462 } ) ;
391463 const report = ( data ) => judge . next ( { domainId, rid, ...data } ) ;
@@ -419,7 +491,17 @@ class SystemRejudgeHandler extends SystemHandler {
419491 } ) ;
420492 } ) ;
421493 this . response . body = { rid } ;
422- this . response . redirect = this . url ( 'record_detail' , { rid } ) ;
494+ this . response . redirect = this . url ( 'manage_rejudge_detail' , { rid : rid . toHexString ( ) } ) ;
495+ }
496+ }
497+
498+ class SystemRejudgeDetailHandler extends SystemHandler {
499+ @param ( 'rid' , Types . ObjectId )
500+ async get ( domainId : string , rid : ObjectId ) {
501+ const rrdoc = await record . getRejudgeTask ( rid ) ;
502+ if ( ! rrdoc ) throw new RecordNotFoundError ( domainId , rid ) ;
503+ this . response . body = { rrdoc } ;
504+ this . response . template = 'manage_rejudge_detail.html' ;
423505 }
424506}
425507
@@ -433,5 +515,6 @@ export async function apply(ctx) {
433515 ctx . Route ( 'manage_user_import' , '/manage/userimport' , SystemUserImportHandler ) ;
434516 ctx . Route ( 'manage_user_priv' , '/manage/userpriv' , SystemUserPrivHandler ) ;
435517 ctx . Route ( 'manage_rejudge' , '/manage/rejudge' , SystemRejudgeHandler ) ;
518+ ctx . Route ( 'manage_rejudge_detail' , '/manage/rejudge/:rid' , SystemRejudgeDetailHandler ) ;
436519 ctx . Connection ( 'manage_check' , '/manage/check-conn' , SystemCheckConnHandler ) ;
437520}
0 commit comments