@@ -42,12 +42,16 @@ function sortable(source: string, namespaces: Record<string, string>) {
4242function findOverrideContent ( dir : string , base : string ) {
4343 let files = fs . readdirSync ( dir ) ;
4444 if ( files . includes ( `${ base } .md` ) ) return fs . readFileSync ( path . join ( dir , `${ base } .md` ) , 'utf8' ) ;
45+ if ( files . includes ( `${ base } .pdf` ) ) return `@[PDF](file://${ base } .pdf)` ;
4546 const languages = { } ;
46- files = files . filter ( ( i ) => new RegExp ( `^${ base } _ [a-zA-Z_]+\\.md $` ) . test ( i ) ) ;
47+ files = files . filter ( ( i ) => new RegExp ( `^${ base } (?:_|.)( [a-zA-Z_]+) \\.(md|pdf) $` ) . test ( i ) ) ;
4748 if ( ! files . length ) return null ;
4849 for ( const file of files ) {
49- const lang = file . slice ( 8 , - 3 ) ;
50- languages [ lang ] = fs . readFileSync ( path . join ( dir , file ) , 'utf8' ) ;
50+ const match = file . match ( `^${ base } (?:_|.)([a-zA-Z_]+)\\.(md|pdf)$` ) ;
51+ const lang = match [ 1 ] ;
52+ const ext = match [ 2 ] ;
53+ if ( ext === 'pdf' ) languages [ lang ] = `@[PDF](file://${ file } )` ;
54+ else languages [ lang ] = fs . readFileSync ( path . join ( dir , file ) , 'utf8' ) ;
5155 }
5256 return JSON . stringify ( languages ) ;
5357}
@@ -511,13 +515,16 @@ export class ProblemModel {
511515 }
512516 if ( ! await isValidPid ( pid ) ) pid = undefined ;
513517 }
514- const overrideContent = findOverrideContent ( path . join ( tmpdir , i ) , 'problem' ) ;
518+ let overrideContent = findOverrideContent ( path . join ( tmpdir , i ) , 'problem' ) ;
519+ overrideContent ||= findOverrideContent ( path . join ( tmpdir , i , 'statement' ) , 'problem' ) ;
520+ overrideContent ||= findOverrideContent ( path . join ( tmpdir , i , 'problem_statement' ) , 'problem' ) ;
515521 if ( pdoc . difficulty && ! Number . isSafeInteger ( pdoc . difficulty ) ) delete pdoc . difficulty ;
516- if ( typeof pdoc . title !== 'string' ) throw new ValidationError ( 'title' , null , 'Invalid title' ) ;
522+ const title = pdoc . title || ( pdoc as any ) . name ;
523+ if ( typeof title !== 'string' ) throw new ValidationError ( 'title' , null , 'Invalid title' ) ;
517524 const allFiles = await getFiles (
518525 'testdata' , 'additional_file' ,
519526 // The following is from https://icpc.io/problem-package-format/spec/2023-07-draft.html
520- 'attachments' , 'generators' , 'include' , 'data' , 'statement' ,
527+ 'attachments' , 'generators' , 'include' , 'data' , 'statement' , 'problem_statement' ,
521528 ) ;
522529 const totalSize = allFiles . map ( ( f ) => fs . statSync ( f [ 1 ] ) . size ) . reduce ( ( a , b ) => a + b , 0 ) ;
523530 if ( allFiles . length > SystemModel . get ( 'limit.problem_files' ) ) throw new ValidationError ( 'files' , null , 'Too many files' ) ;
@@ -532,15 +539,19 @@ export class ProblemModel {
532539 // TODO: report this as a warning
533540 }
534541 }
542+ if ( ( pdoc as any ) . limits ) {
543+ config . time = ( pdoc as any ) . limits . time_limit ;
544+ config . memory = ( pdoc as any ) . limits . memory ;
545+ }
535546 const docId = overridePid
536547 ? ( await ProblemModel . edit ( domainId , overridePid , {
537- title : pdoc . title . trim ( ) ,
538- content : overrideContent || pdoc . content . toString ( ) || 'No content' ,
548+ title : title . trim ( ) ,
549+ content : overrideContent || pdoc . content ? .toString ( ) || 'No content' ,
539550 tag,
540551 difficulty : pdoc . difficulty ,
541552 } ) ) . docId
542553 : await ProblemModel . add (
543- domainId , pid , pdoc . title . trim ( ) , overrideContent || pdoc . content . toString ( ) || 'No content' ,
554+ domainId , pid , title . trim ( ) , overrideContent || pdoc . content ? .toString ( ) || 'No content' ,
544555 operator || pdoc . owner , tag , { hidden : pdoc . hidden , difficulty : pdoc . difficulty } ,
545556 ) ;
546557 // TODO delete unused file when updating pdoc
@@ -559,7 +570,7 @@ export class ProblemModel {
559570 : null ) ?.( domainId , docId , file , path . join ( loc , file ) ) ;
560571 }
561572 }
562- for ( const [ f , loc ] of await getFiles ( 'additional_file' , 'attachments' , 'statement' ) ) {
573+ for ( const [ f , loc ] of await getFiles ( 'additional_file' , 'attachments' , 'statement' , 'problem_statement' ) ) {
563574 if ( ! f . isFile ( ) ) continue ;
564575 await ProblemModel . addAdditionalFile ( domainId , docId , f . name , loc ) ;
565576 }
@@ -583,7 +594,7 @@ export class ProblemModel {
583594 await RecordModel . add ( domainId , docId , operator , f . name . split ( '.' ) [ 1 ] , await fs . readFile ( loc , 'utf-8' ) , true ) ;
584595 }
585596 if ( configChanged ) await ProblemModel . addTestdata ( domainId , docId , 'config.yaml' , yaml . dump ( config ) ) ;
586- const message = `${ overridePid ? 'Updated' : 'Imported' } problem ${ pdoc . pid } (${ pdoc . title } )` ;
597+ const message = `${ overridePid ? 'Updated' : 'Imported' } problem ${ pdoc . pid || docId } (${ title } )` ;
587598 ( process . env . HYDRO_CLI ? logger . info : progress ) ?.( message ) ;
588599 } catch ( e ) {
589600 ( process . env . HYDRO_CLI ? logger . info : progress ) ?.( `Error importing problem ${ i } : ${ e . message } ` ) ;
0 commit comments