Skip to content

Commit 537c6d2

Browse files
authored
migrate: hustoj: fix bugs (#1013)
1 parent a3226f7 commit 537c6d2

1 file changed

Lines changed: 38 additions & 13 deletions

File tree

packages/migrate/scripts/hustoj.ts

Lines changed: 38 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -43,12 +43,6 @@ const langMap = {
4343
16: 'js',
4444
17: 'go',
4545
};
46-
const nameMap: Record<string, string> = {
47-
'sample.in': 'sample0.in',
48-
'sample.out': 'sample0.out',
49-
'test.in': 'test0.in',
50-
'test.out': 'test0.out',
51-
};
5246

5347
async function addContestFile(domainId: string, tid: ObjectId, filename: string, filepath: string) {
5448
const tdoc = await ContestModel.get(domainId, tid);
@@ -60,6 +54,18 @@ async function addContestFile(domainId: string, tid: ObjectId, filename: string,
6054
return true;
6155
}
6256

57+
function fixFileName(fileName: string) {
58+
if (fileName.endsWith('.in') || fileName.endsWith('.out')) {
59+
const dotAt = fileName.lastIndexOf('.');
60+
const name = fileName.slice(0, dotAt);
61+
const suffix = fileName.slice(dotAt + 1);
62+
if (!name.match(/[0-9]/)) {
63+
fileName = `${name}0.${suffix}`;
64+
}
65+
}
66+
return fileName.replace(/[\\/?#~!|*]/g, '_');
67+
}
68+
6369
export async function run({
6470
host = 'localhost', port = 3306, name = 'jol',
6571
username, password, domainId, contestType = 'oi',
@@ -186,11 +192,13 @@ export async function run({
186192
hint: pdoc.hint,
187193
source: pdoc.source,
188194
}, 'html').replace(/<math xm<x>lns=/g, '<math xmlns=').replace(/\[\/?md]/g, '');
189-
const uploadFiles = content.matchAll(/(?:src|href)="\/upload\/([^"]+\/([^"]+))"/g);
195+
const uploadFiles = content.matchAll(/(?:src|href)="\/upload\/([^"/]+)(?:\/([^"/]+))?\/([^"/]+\.[^"/.]+)"/g);
190196
for (const file of uploadFiles) {
191197
try {
192-
files[file[2]] = await fs.readFile(path.join(uploadDir, file[1]));
193-
content = content.replace(`/upload/${file[1]}`, `file://${file[2]}`);
198+
const filename = fixFileName(file[3]);
199+
const fileWithPath = [file[1], ...(file[2] ? [file[2]] : []), file[3]].join('/');
200+
files[filename] = await fs.readFile(path.join(uploadDir, fileWithPath));
201+
content = content.replace(`/upload/${fileWithPath}`, `file://${filename}`);
194202
} catch (e) {
195203
report({ message: `failed to read file: ${path.join(uploadDir, file[1])}` });
196204
}
@@ -265,13 +273,19 @@ hydrooj install https://hydro.ac/hydroac-client.zip
265273
const pids = pdocs.map((i) => pidMap[i.problem_id]).filter((i) => i);
266274
const files = {};
267275
let description = tdoc.description;
268-
const uploadFiles = description.matchAll(/(?:src|href)="\/upload\/([^"]+\/([^"]+))"/g);
276+
const uploadFiles = description.matchAll(/(?:src|href)="\/upload\/([^"/]+)(?:\/([^"/]+))?\/([^"/]+\.[^"/.]+)"/g);
269277
for (const file of uploadFiles) {
270-
files[file[2]] = await fs.readFile(path.join(uploadDir, file[1]));
271-
description = description.replace(`/upload/${file[1]}`, `file://${file[2]}`);
278+
const filename = fixFileName(file[3]);
279+
const fileWithPath = [file[1], ...(file[2] ? [file[2]] : []), file[3]].join('/');
280+
files[filename] = await fs.readFile(path.join(uploadDir, fileWithPath));
281+
description = description.replace(`/upload/${fileWithPath}`, `file://${filename}`);
272282
}
273283
// WHY you allow contest with end time BEFORE start time? WHY???
274284
const endAt = moment(tdoc.end_time).isSameOrBefore(tdoc.start_time) ? moment(tdoc.end_time).add(1, 'minute').toDate() : tdoc.end_time;
285+
let isAssignMode = false;
286+
if (tdoc.private === 1 && tdoc.password === '') {
287+
isAssignMode = true;
288+
}
275289
const tid = await ContestModel.add(
276290
domainId, tdoc.title, description || 'Description',
277291
adminUids[0], contestType, tdoc.start_time, endAt, pids, true,
@@ -281,6 +295,17 @@ hydrooj install https://hydro.ac/hydroac-client.zip
281295
await Promise.all(Object.keys(files).map((filename) => addContestFile(domainId, tid, filename, files[filename])));
282296
if (Object.keys(files).length) report({ message: `move ${Object.keys(files).length} file for contest ${tidMap[tdoc.contest_id]}` });
283297

298+
const allowedUser:{ user_id:string }[] = await query(`SELECT * FROM privilege WHERE rightstr = 'c${tdoc.contest_id}';`);
299+
const assignUserList = allowedUser.map((i) => uidMap[i.user_id]).filter((i) => i);
300+
if (isAssignMode) {
301+
await ContestModel.edit(domainId, tid, {
302+
assign: assignUserList.map((uid) => uid.toString()),
303+
});
304+
} else {
305+
for (let i = 0; i < assignUserList.length; i++) {
306+
await ContestModel.attend(domainId, tid, assignUserList[i]).catch(noop);
307+
}
308+
}
284309
if (tidx % 100 === 0) {
285310
const progress = Math.round(((tidx + 1) / tdocs.length) * 100);
286311
report({
@@ -374,7 +399,7 @@ hydrooj install https://hydro.ac/hydroac-client.zip
374399
report({ message: `Syncing testdata for ${file.name}` });
375400
for (const data of datas) {
376401
if (data.isDirectory()) continue;
377-
const filename = nameMap[data.name] || data.name;
402+
const filename = fixFileName(data.name);
378403
await ProblemModel.addTestdata(domainId, pdoc.docId, filename, `${dataDir}/${file.name}/${data.name}`);
379404
}
380405
await ProblemModel.addTestdata(domainId, pdoc.docId, 'config.yaml', Buffer.from(pdoc.config as string));

0 commit comments

Comments
 (0)