core: import: support solution and std

This commit is contained in:
undefined committed 2024-04-09 08:12:10 +08:00
1 parent 76befa7b2a
commit e207cb4194
1 file changed
+32 -23
+32 -23
View File
@@ -22,6 +22,8 @@ import { buildProjection } from '../utils';
import { PERM, STATUS } from './builtin';
import * as document from './document';
import DomainModel from './domain';
import RecordModel from './record';
import SolutionModel from './solution';
import storage from './storage';
import user from './user';
@@ -33,11 +35,11 @@ function sortable(source: string) {
return source.replace(/(\d+)/g, (str) => (str.length >= 6 ? str : ('0'.repeat(6 - str.length) + str)));
}
function findOverrideContent(dir: string) {
function findOverrideContent(dir: string, base: string) {
let files = fs.readdirSync(dir);
if (files.includes('problem.md')) return fs.readFileSync(path.join(dir, 'problem.md'), 'utf8');
if (files.includes(`${base}.md`)) return fs.readFileSync(path.join(dir, `${base}.md`), 'utf8');
const languages = {};
files = files.filter((i) => /^problem_[a-zA-Z_]+\.md$/.test(i));
files = files.filter((i) => new RegExp(`^${base}_[a-zA-Z_]+\\.md$`).test(i));
if (!files.length) return null;
for (const file of files) {
const lang = file.slice(8, -3);
@@ -470,8 +472,8 @@ export class ProblemModel {
if (process.env.HYDRO_CLI) logger.info(`Importing problem ${p.name}`);
const i = p.name;
if (!p.isDirectory()) continue;
const files = await fs.readdir(path.join(tmpdir, i));
if (!files.includes('problem.yaml')) continue;
const files = await fs.readdir(path.join(tmpdir, i), { withFileTypes: true });
if (!files.find((f) => f.name === 'problem.yaml')) continue;
const content = fs.readFileSync(path.join(tmpdir, i, 'problem.yaml'), 'utf-8');
const pdoc: ProblemDoc = yaml.load(content) as any;
if (!pdoc) continue;
@@ -482,6 +484,11 @@ export class ProblemModel {
if (await ProblemModel.get(domainId, id)) return false;
return true;
};
const getFiles = async (type: string) => {
if (!files.find((f) => f.name === type && f.isDirectory())) return [];
const rs = await fs.readdir(path.join(tmpdir, i, type), { withFileTypes: true });
return rs.map((r) => [r, path.join(tmpdir, i, type, r.name)] as [fs.Dirent, string]);
};
if (pid) {
if (preferredPrefix) {
@@ -490,31 +497,33 @@ export class ProblemModel {
}
if (!await isValidPid(pid)) pid = undefined;
}
const overrideContent = findOverrideContent(path.join(tmpdir, i));
const overrideContent = findOverrideContent(path.join(tmpdir, i), 'problem');
if (pdoc.difficulty && !Number.isSafeInteger(pdoc.difficulty)) delete pdoc.difficulty;
if (typeof pdoc.title !== 'string') throw new ValidationError('title', null, 'Invalid title');
const docId = await ProblemModel.add(
domainId, pid, pdoc.title.trim(), overrideContent || pdoc.content || 'No content',
operator || pdoc.owner, pdoc.tag || [], { hidden: pdoc.hidden, difficulty: pdoc.difficulty },
);
if (files.includes('testdata')) {
const datas = await fs.readdir(path.join(tmpdir, i, 'testdata'), { withFileTypes: true });
for (const f of datas) {
if (f.isDirectory()) {
const sub = await fs.readdir(path.join(tmpdir, i, 'testdata', f.name));
for (const s of sub) await ProblemModel.addTestdata(domainId, docId, s, path.join(tmpdir, i, 'testdata', f.name, s));
} else if (f.isFile()) {
await ProblemModel.addTestdata(domainId, docId, f.name, path.join(tmpdir, i, 'testdata', f.name));
}
}
for (const [f, loc] of await getFiles('testdata')) {
if (f.isDirectory()) {
const sub = await fs.readdir(loc);
for (const s of sub) await ProblemModel.addTestdata(domainId, docId, s, path.join(tmpdir, i, 'testdata', f.name, s));
} else if (f.isFile()) await ProblemModel.addTestdata(domainId, docId, f.name, loc);
}
if (files.includes('additional_file')) {
const datas = await fs.readdir(path.join(tmpdir, i, 'additional_file'), { withFileTypes: true });
for (const f of datas) {
if (f.isFile()) {
await ProblemModel.addAdditionalFile(domainId, docId, f.name, path.join(tmpdir, i, 'additional_file', f.name));
}
}
for (const [f, loc] of await getFiles('additional_file')) {
if (!f.isFile()) continue;
await ProblemModel.addAdditionalFile(domainId, docId, f.name, loc);
}
for (const [f, loc] of await getFiles('solution')) {
if (!f.isFile()) continue;
await SolutionModel.add(domainId, docId, operator, await fs.readFile(loc, 'utf-8'));
}
let count = 0;
for (const [f, loc] of await getFiles('std')) {
if (!f.isFile()) continue;
count++;
if (count > 5) continue;
await RecordModel.add(domainId, docId, operator, f.name.split('.')[1], await fs.readFile(loc, 'utf-8'), true);
}
if (process.env.HYDRO_CLI) logger.info(`Imported problem ${pdoc.pid} (${pdoc.title})`);
}