UNPKG

oicontest

Version:

OI Contest Management Tool

191 lines (179 loc) 6.34 kB
import { Command } from 'commander'; import inquirer from 'inquirer'; import { loadConfig, saveConfig } from '../lib/config'; import chalk from 'chalk'; import moment from 'moment'; import fs from 'fs-extra'; import path from 'path'; export const editCommand = new Command('edit') .description('Edit contest information or problem ID') .action(async () => { try { const config = await loadConfig(process.cwd()); console.log(chalk.bold.blue('\n✏️ Edit Menu\n')); const { editType } = await inquirer.prompt([ { type: 'list', name: 'editType', message: 'What do you want to edit?', choices: [ { name: 'Edit contest information', value: 'contest' }, { name: 'Edit problem ID', value: 'problemId' } ] } ]); if (editType === 'contest') { await editContestInfo(config); } else { await editProblemId(config); } } catch (err:unknown) { console.error(chalk.red(`Error editing: ${(err as Error).message}`)); process.exit(1); } }); async function editContestInfo(config: any) { const oldName = config.name; const currentDir = process.cwd(); const parentDir = path.dirname(currentDir); const answers = await inquirer.prompt([ { type: 'input', name: 'name', message: 'Contest directory name:', default: config.name }, { type: 'input', name: 'description', message: 'Contest description (for PDF):', default: config.description }, { type: 'input', name: 'startTime', message: 'Start time (YYYY-MM-DD HH:mm):', default: config.startTime, validate: input => { if (!moment(input, 'YYYY-MM-DD HH:mm', true).isValid()) { return 'Invalid date format. Use YYYY-MM-DD HH:mm (e.g. 2023-10-15 09:00)'; } return true; } }, { type: 'input', name: 'duration', message: 'Contest duration (minutes):', default: config.duration.toString(), validate: input => !isNaN(Number(input)) || 'Please enter a valid number' }, { type: 'input', name: 'author', message: 'Author:', default: config.author } ]); const newName = answers.name; const newDirPath = path.join(parentDir, newName); config.name = newName; config.description = answers.description; config.duration = parseInt(answers.duration); config.author = answers.author; config.startTime = moment(answers.startTime, 'YYYY-MM-DD HH:mm').format('YYYY-MM-DD HH:mm'); await saveConfig(currentDir, config); if (oldName !== newName) { try { if (await fs.pathExists(newDirPath)) { console.log(chalk.yellow(`\n⚠️ Directory "${newName}" already exists. Cannot rename.`)); console.log(chalk.cyan(` Keeping current directory name: ${oldName}`)); console.log(chalk.cyan(` Config updated with new name: ${newName}`)); } else { await fs.move(currentDir, newDirPath); console.log(chalk.green(`\n✅ Directory renamed from "${oldName}" to "${newName}"`)); console.log(chalk.cyan(` New path: ${newDirPath}`)); process.chdir(newDirPath); console.log(chalk.cyan(` Working directory changed to: ${newDirPath}`)); } } catch (renameError) { console.log(chalk.yellow(`\n⚠️ Failed to rename directory: ${(renameError as Error).message}`)); console.log(chalk.cyan(` Config updated with new name: ${newName}`)); console.log(chalk.cyan(` Directory remains: ${oldName}`)); } } console.log(chalk.green.bold('\n✅ Contest information updated successfully!')); console.log(chalk.cyan(` Directory Name: ${config.name}`)); console.log(chalk.cyan(` Description: ${config.description}`)); console.log(chalk.cyan(` Start Time: ${config.startTime}`)); console.log(chalk.cyan(` Duration: ${config.duration} minutes`)); console.log(chalk.cyan(` Author: ${config.author}`)); } async function editProblemId(config: any) { const contestDir = process.cwd(); if (!config.problems || config.problems.length === 0) { console.log(chalk.yellow('No problems found in this contest.')); return; } // 选择题目 const { selectedId } = await inquirer.prompt([ { type: 'list', name: 'selectedId', message: 'Select the problem to edit ID:', choices: config.problems.map((p: any) => ({ name: `[${p.id}] ${p.title}`, value: p.id })) } ]); const oldId = selectedId; const oldProblemDir = path.join(contestDir, 'problem', oldId); // 输入新ID const { newId } = await inquirer.prompt([ { type: 'input', name: 'newId', message: `Enter new ID for problem [${oldId}]:`, validate: (input: string) => { if (!input.trim()) return 'ID cannot be empty'; if (input === oldId) return 'New ID is the same as the old ID'; if (config.problems.some((p: any) => p.id === input)) return 'ID already exists!'; return true; } } ]); const newProblemDir = path.join(contestDir, 'problem', newId); // 重命名目录 try { await fs.move(oldProblemDir, newProblemDir); } catch (e) { console.error(chalk.red(`Failed to rename problem directory: ${(e as Error).message}`)); return; } // 修改 config.json const configJsonPath = path.join(newProblemDir, 'config.json'); if (await fs.pathExists(configJsonPath)) { const problemConfig = await fs.readJson(configJsonPath); problemConfig.id = newId; await fs.writeJson(configJsonPath, problemConfig, { spaces: 2 }); } // 修改 status.json const statusJsonPath = path.join(newProblemDir, 'status.json'); if (await fs.pathExists(statusJsonPath)) { try { const statusConfig = await fs.readJson(statusJsonPath); if (statusConfig.id) statusConfig.id = newId; await fs.writeJson(statusJsonPath, statusConfig, { spaces: 2 }); } catch {} } // 更新 oicontest.json for (const p of config.problems as any[]) { if (p.id === oldId) { p.id = newId; break; } } await saveConfig(contestDir, config); console.log(chalk.green.bold(`\n✅ Problem ID updated from "${oldId}" to "${newId}"!`)); }