@@ -75,21 +75,25 @@ interface ProblemCreateOptions {
7575 reference ?: { domainId : string , pid : number } ;
7676}
7777
78+ const PROJECTION_BASE : Field [ ] = [
79+ '_id' , 'domainId' , 'docType' , 'docId' , 'pid' ,
80+ 'owner' , 'title' ,
81+ ] ;
82+
7883export class ProblemModel {
7984 static PROJECTION_CONTEST_LIST : Field [ ] = [
80- '_id' , 'domainId' , 'docType' , 'docId' , 'pid' ,
81- 'owner' , 'title' ,
85+ ...PROJECTION_BASE , 'config' ,
8286 ] ;
8387
8488 static PROJECTION_LIST : Field [ ] = [
85- ...ProblemModel . PROJECTION_CONTEST_LIST ,
89+ ...PROJECTION_BASE ,
8690 'nSubmit' , 'nAccept' , 'difficulty' , 'tag' , 'hidden' ,
8791 'stats' ,
8892 ] ;
8993
9094 static PROJECTION_CONTEST_DETAIL : Field [ ] = [
9195 ...ProblemModel . PROJECTION_CONTEST_LIST ,
92- 'content' , 'html' , 'data' , 'config' , ' additional_file',
96+ 'content' , 'html' , 'data' , 'additional_file' ,
9397 'reference' , 'maintainer' ,
9498 ] ;
9599
@@ -198,7 +202,7 @@ export class ProblemModel {
198202 . project ( buildProjection ( projection ) ) . limit ( 1 ) . toArray ( ) ) [ 0 ] ;
199203 if ( ! res ) return null ;
200204 try {
201- if ( ! rawConfig ) res . config = await parseConfig ( res . config ) ;
205+ if ( ! rawConfig ) res . config = await parseConfig ( res . config , res . data ?. map ( ( i ) => i . name ) || [ ] ) ;
202206 } catch ( e ) {
203207 res . config = `Cannot parse: ${ e . message } ` ;
204208 }
@@ -390,7 +394,7 @@ export class ProblemModel {
390394 }
391395 for ( const pdoc of pdocs ) {
392396 try {
393- pdoc . config = await parseConfig ( pdoc . config as string ) ;
397+ pdoc . config = await parseConfig ( pdoc . config as string , pdoc . data ?. map ( ( i ) => i . name ) || [ ] ) ;
394398 } catch ( e ) {
395399 pdoc . config = `Cannot parse: ${ e . message } ` ;
396400 }
@@ -552,16 +556,29 @@ export class ProblemModel {
552556 const tag = ( pdoc . tag || [ ] ) . map ( ( t ) => t . toString ( ) ) ;
553557 let configChanged = false ;
554558 let config : ProblemConfigFile = { } ;
555- if ( await fs . exists ( 'testdata/config.yaml' ) ) {
559+ if ( await fs . exists ( path . join ( tmpdir , i , 'testdata/config.yaml' ) ) ) {
556560 try {
557- config = yaml . load ( await fs . readFile ( 'testdata/config.yaml' , 'utf-8' ) ) ;
561+ config = yaml . load ( await fs . readFile ( path . join ( tmpdir , i , 'testdata/config.yaml' ) , 'utf-8' ) ) ;
558562 } catch ( e ) {
559563 // TODO: report this as a warning
560564 }
561565 }
566+ if ( await fs . exists ( path . join ( tmpdir , i , 'domjudge-problem.ini' ) ) ) {
567+ const djConfig = ( await fs . readFile ( path . join ( tmpdir , i , 'domjudge-problem.ini' ) , 'utf-8' ) as string )
568+ . split ( '\n' ) . map ( ( line : string ) => line . split ( '=' ) . map ( ( lines : string ) => lines . trim ( ) ) ) ;
569+ const djConfigJson : any = { } ;
570+ for ( const [ key , value ] of djConfig ) {
571+ djConfigJson [ key ] = value ;
572+ }
573+ if ( djConfigJson . timelimit ) {
574+ config . time = `${ djConfigJson . timelimit * 1000 } ms` ;
575+ configChanged = true ;
576+ }
577+ if ( djConfigJson . externalid ) pid = djConfigJson . externalid ;
578+ }
562579 if ( ( pdoc as any ) . limits ) {
563- config . time = ( pdoc as any ) . limits . time_limit ;
564- config . memory = ( pdoc as any ) . limits . memory ;
580+ config . time = ( pdoc as any ) . limits . time_limit ? ` ${ ( pdoc as any ) . limits . time_limit * 1000 } ms` : config . time || undefined ;
581+ config . memory = ( pdoc as any ) . limits . memory ? ` ${ ( pdoc as any ) . limits . memory } m` : config . memory || undefined ;
565582 configChanged = true ;
566583 }
567584 const docId = overridePid
@@ -587,9 +604,8 @@ export class ProblemModel {
587604 if ( ! f . isDirectory ( ) ) continue ;
588605 const sub = await fs . readdir ( loc ) ;
589606 for ( const file of sub ) {
590- await ( f . name === 'sample' ? ProblemModel . addAdditionalFile
591- : f . name === 'secret' ? ProblemModel . addTestdata
592- : null ) ?.( domainId , docId , file , path . join ( loc , file ) ) ;
607+ if ( f . name === 'sample' ) await ProblemModel . addAdditionalFile ( domainId , docId , file , path . join ( loc , file ) ) ;
608+ await ProblemModel . addTestdata ( domainId , docId , file , path . join ( loc , file ) ) ;
593609 }
594610 }
595611 for ( const [ f , loc ] of await getFiles ( 'output_validators' ) ) {
@@ -598,10 +614,10 @@ export class ProblemModel {
598614 for ( const file of sub ) {
599615 if ( file === 'testlib.h' ) continue ;
600616 await ProblemModel . addTestdata ( domainId , docId , file , path . join ( loc , file ) ) ;
601- if ( file === 'checker' ) {
617+ if ( f . name === 'checker' ) {
602618 config . checker_type = 'testlib' ;
603619 config . checker = file ;
604- } else if ( file === 'interactor' ) {
620+ } else if ( f . name === 'interactor' ) {
605621 config . type = ProblemType . Interactive ;
606622 config . interactor = file ;
607623 }
@@ -624,14 +640,24 @@ export class ProblemModel {
624640 config . judge_extra_files = Array . from ( new Set ( config . judge_extra_files . concat ( f . name ) ) ) ;
625641 configChanged = true ;
626642 }
643+ if ( configChanged ) await ProblemModel . addTestdata ( domainId , docId , 'config.yaml' , Buffer . from ( yaml . dump ( config ) ) ) ;
627644 let count = 0 ;
628645 for ( const [ f , loc ] of await getFiles ( 'std' ) ) {
629646 if ( ! f . isFile ( ) ) continue ;
630647 count ++ ;
631648 if ( count > 5 ) continue ;
632649 await RecordModel . add ( domainId , docId , operator , f . name . split ( '.' ) [ 1 ] , await fs . readFile ( loc , 'utf-8' ) , true ) ;
633650 }
634- if ( configChanged ) await ProblemModel . addTestdata ( domainId , docId , 'config.yaml' , yaml . dump ( config ) ) ;
651+ for ( const [ f , loc ] of await getFiles ( 'submissions' ) ) {
652+ if ( f . isFile ( ) ) continue ;
653+ const sub = await fs . readdir ( loc ) ;
654+ for ( const file of sub ) {
655+ if ( file . endsWith ( '.zip' ) ) continue ;
656+ const code = await fs . readFile ( path . join ( loc , file ) , 'utf-8' ) ;
657+ await RecordModel . add ( domainId , docId , operator , file . split ( '.' ) [ 1 ] , `// ${ file } : ${ loc } \n${ code } ` , true ) ;
658+ }
659+ }
660+ if ( configChanged ) await ProblemModel . addTestdata ( domainId , docId , 'config.yaml' , Buffer . from ( yaml . dump ( config ) ) ) ;
635661 const message = `${ overridePid ? 'Updated' : 'Imported' } problem ${ pdoc . pid || docId } (${ title } )` ;
636662 ( process . env . HYDRO_CLI ? logger . info : progress ) ?.( message ) ;
637663 } catch ( e ) {
0 commit comments