From f7e212dc8d6bd58b6eb608af861150cdd5c2a733 Mon Sep 17 00:00:00 2001 From: relentless <2464869638@qq.com> Date: Mon, 29 Sep 2025 12:08:56 +0800 Subject: [PATCH] modify9.29 --- src/FileUtils.java | 58 ++++++--- src/Main.java | 216 ++++++++++++++++++++----------- src/QuestionStrategyFactory.java | 16 +-- 3 files changed, 186 insertions(+), 104 deletions(-) diff --git a/src/FileUtils.java b/src/FileUtils.java index 8c89b9b..4bdad82 100644 --- a/src/FileUtils.java +++ b/src/FileUtils.java @@ -13,45 +13,58 @@ import java.util.Set; /** * 文件工具类:用于生成文件名、保存题目、读取已有题目。 */ -public class FileUtils { +public final class FileUtils { + + /** 文件后缀名常量。 */ + private static final String FILE_SUFFIX = ".txt"; + + private FileUtils() { + // 工具类不允许实例化 + } /** * 生成基于时间戳的文件名。 * - * @return 文件名,格式为 yyyy-MM-dd-HH-mm-ss.txt + * @return 文件名,格式为 {@code yyyy-MM-dd-HH-mm-ss.txt} */ public static String generateFileName() { SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss"); - return sdf.format(new Date()) + ".txt"; + return sdf.format(new Date()) + FILE_SUFFIX; } /** * 将题目保存到用户目录下的指定文件中。 * - * @param userId 用户 ID(作为文件夹名) + * @param userId 用户 ID(作为文件夹名) * @param fileName 文件名 * @param questions 要保存的题目列表 + * @throws IOException 当创建目录或写文件失败时抛出 */ public static void saveQuestionsToFile( - String userId, String fileName, List questions) { + String userId, String fileName, List questions) throws IOException { + File userFolder = new File(userId); - if (!userFolder.exists()) { - userFolder.mkdirs(); + if (!userFolder.exists() && !userFolder.mkdirs()) { + throw new IOException( + String.format("无法创建用户目录: %s", userFolder.getAbsolutePath())); } File file = new File(userFolder, fileName); try (BufferedWriter writer = new BufferedWriter(new FileWriter(file))) { for (MathQuestion question : questions) { writer.write( - "题号 " + question.getQuestionNumber() + ": " - + question.getQuestionText()); + String.format("题号 %d: %s", + question.getQuestionNumber(), + question.getQuestionText())); writer.newLine(); writer.newLine(); } - writer.flush(); } catch (IOException e) { - throw new RuntimeException("写文件失败: " + file.getAbsolutePath(), e); + throw new IOException( + String.format("写文件失败: %s", file.getAbsolutePath()), e); } + + System.out.printf("题目已生成并保存到: %s%n%n", file.getAbsolutePath()); } /** @@ -59,22 +72,26 @@ public class FileUtils { * * @param userId 用户 ID(作为文件夹名) * @return 已存在的题目集合(按题目内容去重) + * @throws IOException 当读取文件失败时抛出 */ - public static Set loadExistingQuestions(String userId) { + public static Set loadExistingQuestions(String userId) throws IOException { Set existingQuestions = new HashSet<>(); File userFolder = new File(userId); + if (!userFolder.exists() || !userFolder.isDirectory()) { return existingQuestions; } - File[] files = userFolder.listFiles( - (dir, name) -> name != null && name.endsWith(".txt")); + File[] files = + userFolder.listFiles( + (dir, name) -> name != null && name.endsWith(FILE_SUFFIX)); + if (files == null) { return existingQuestions; } - for (File f : files) { - try (BufferedReader reader = new BufferedReader(new FileReader(f))) { + for (File file : files) { + try (BufferedReader reader = new BufferedReader(new FileReader(file))) { String line; while ((line = reader.readLine()) != null) { line = line.trim(); @@ -82,14 +99,15 @@ public class FileUtils { continue; } if (line.startsWith("题号")) { - int idx = line.indexOf(":"); - if (idx != -1 && idx + 1 < line.length()) { - existingQuestions.add(line.substring(idx + 1).trim()); + int colonIndex = line.indexOf(":"); + if (colonIndex != -1 && colonIndex + 1 < line.length()) { + existingQuestions.add(line.substring(colonIndex + 1).trim()); } } } } catch (IOException e) { - e.printStackTrace(); + throw new IOException( + String.format("读取文件失败: %s", file.getAbsolutePath()), e); } } return existingQuestions; diff --git a/src/Main.java b/src/Main.java index 57b714e..7cf360d 100644 --- a/src/Main.java +++ b/src/Main.java @@ -2,9 +2,14 @@ import java.io.IOException; import java.util.Scanner; /** - * 程序入口类。负责用户登录和题目生成。 + * 程序入口类,负责用户登录和题目生成。 */ public class Main { + + private static final String ROLE_PRIMARY = "小学"; + private static final String ROLE_JUNIOR = "初中"; + private static final String ROLE_SENIOR = "高中"; + /** * 程序入口。 * @@ -12,89 +17,152 @@ public class Main { * @throws IOException 文件写入失败时抛出 */ public static void main(String[] args) throws IOException { - Scanner scanner = new Scanner(System.in); + clearScreen(); + System.out.println( + "-----------------欢迎来到中小学数学卷子自动生成程序-----------------"); + + try (Scanner scanner = new Scanner(System.in)) { + while (true) { + // 登录流程 + User currentUser = loginProcess(scanner); + // 题目生成流程 + generateProcess(scanner, currentUser); + } + } + } + + /** + * 用户登录流程。 + * + * @param scanner 输入流 + * @return 登录成功的用户对象 + */ + private static User loginProcess(Scanner scanner) { User currentUser = null; - System.out.println("-----------------欢迎来到中小学数学卷子自动生成程序-----------------"); + while (currentUser == null) { + System.out.print("请输入用户名和密码,用空格分隔:"); + String username = scanner.next(); + String password = scanner.next(); + + currentUser = User.login(username, password); + if (currentUser == null) { + System.out.println("请输入正确的用户名、密码"); + } else { + clearScreen(); + System.out.println("当前选择为 " + currentUser.getRole() + " 出题"); + } + } + return currentUser; + } + + /** + * 题目生成流程。 + * + * @param scanner 输入流 + * @param currentUser 当前登录用户 + * @throws IOException 文件写入失败时抛出 + */ + private static void generateProcess(Scanner scanner, User currentUser) + throws IOException { + String currentRole = currentUser.getRole(); - // 登录流程 while (true) { - while (currentUser == null) { - System.out.print("请输入用户名和密码,用空格分隔:"); - String username = scanner.next(); - String password = scanner.next(); - - currentUser = User.login(username, password); - - if (currentUser == null) { - System.out.println("请输入正确的用户名、密码"); - } else { - clearScreen(); // 登录成功清屏 - System.out.println("当前选择为 " + currentUser.getRole() + " 出题"); - } + System.out.println( + "准备生成 " + currentRole + + " 数学题目,请输入生成题目数量(输入 -1 将退出当前用户,重新登录):"); + + String input = scanner.next(); + + if (handleExit(input)) { + return; // 返回上一级,重新登录 } - // 每次登录后初始化当前出题类型(账号默认类型) - String currentRole = currentUser.getRole(); + if (handleRoleSwitch(input, currentRole)) { + currentRole = input.substring(3).trim(); + continue; + } - // 题目生成流程 - while (true) { - System.out.println( - "准备生成 " + currentRole - + " 数学题目,请输入生成题目数量(输入 -1 将退出当前用户,重新登录):"); - - String input = scanner.next(); - - // 退出登录 - if (input.equals("-1")) { - currentUser = null; - clearScreen(); - System.out.println("已退出当前用户,重新登录..."); - break; - } - - // 检测切换命令 - if (input.startsWith("切换为")) { - String newRole = input.substring(3).trim(); - if (!newRole.equals("小学") - && !newRole.equals("初中") - && !newRole.equals("高中")) { - System.out.println( - "请输入小学、初中和高中三个选项中的一个" - + " (当前类型为 " + currentRole + ")"); - continue; - } - currentRole = newRole; - clearScreen(); - System.out.println( - "系统提示:准备生成 " + currentRole + " 数学题目,请输入生成题目数量"); - continue; - } - - // 输入题目数量 - int questionCount; - try { - questionCount = Integer.parseInt(input); - } catch (NumberFormatException e) { - System.out.println( - "请输入有效的数字或使用“切换为小学/初中/高中”命令" - + " (当前类型为 " + currentRole + ")"); - continue; - } - - if (questionCount < 10 || questionCount > 30) { - System.out.println("请输入有效的题目数量 (10-30) 或 -1 退出"); - continue; - } + Integer questionCount = parseQuestionCount(input, currentRole); + if (questionCount == null) { + continue; + } - clearScreen(); + clearScreen(); + QuestionGenerator generator = + new QuestionGenerator(currentUser, currentRole); + generator.generateQuestions(questionCount); + } + } + + /** + * 处理退出指令。 + * + * @param input 用户输入 + * @return 如果用户输入退出指令则返回 true + */ + private static boolean handleExit(String input) { + if (input.equals("-1")) { + clearScreen(); + System.out.println("已退出当前用户,重新登录..."); + return true; + } + return false; + } - // 生成题目 - QuestionGenerator generator = - new QuestionGenerator(currentUser, currentRole); - generator.generateQuestions(questionCount); - System.out.println("题目已生成并保存!\n"); + /** + * 处理角色切换指令。 + * + * @param input 用户输入 + * @param currentRole 当前角色 + * @return 如果成功切换角色返回 true,否则返回 false + */ + private static boolean handleRoleSwitch(String input, String currentRole) { + if (input.startsWith("切换为")) { + String newRole = input.substring(3).trim(); + if (!isValidRole(newRole)) { + System.out.println( + "请输入小学、初中和高中三个选项中的一个 (当前类型为 " + currentRole + ")"); + return false; } + clearScreen(); + System.out.println( + "系统提示:准备生成 " + newRole + " 数学题目,请输入生成题目数量"); + return true; + } + return false; + } + + /** + * 判断是否为有效角色。 + */ + private static boolean isValidRole(String role) { + return role.equals(ROLE_PRIMARY) + || role.equals(ROLE_JUNIOR) + || role.equals(ROLE_SENIOR); + } + + /** + * 解析题目数量。 + * + * @param input 用户输入 + * @param currentRole 当前角色 + * @return 返回题目数量,如果输入非法则返回 null + */ + private static Integer parseQuestionCount(String input, String currentRole) { + int questionCount; + try { + questionCount = Integer.parseInt(input); + } catch (NumberFormatException e) { + System.out.println( + "请输入有效的数字或使用“切换为小学/初中/高中”命令 (当前类型为 " + currentRole + ")"); + return null; + } + + if (questionCount < 10 || questionCount > 30) { + System.out.println("请输入有效的题目数量 (10-30) 或 -1 退出"); + return null; } + return questionCount; } /** diff --git a/src/QuestionStrategyFactory.java b/src/QuestionStrategyFactory.java index fbae552..9f7ab68 100644 --- a/src/QuestionStrategyFactory.java +++ b/src/QuestionStrategyFactory.java @@ -11,15 +11,11 @@ public class QuestionStrategyFactory { * @throws IllegalArgumentException 如果角色未知 */ public static QuestionStrategy getStrategy(String role) { - switch (role) { - case "小学": - return new ElementaryQuestionStrategy(); - case "初中": - return new MiddleSchoolQuestionStrategy(); - case "高中": - return new HighSchoolQuestionStrategy(); - default: - throw new IllegalArgumentException("未知的角色: " + role); - } + return switch (role) { + case "小学" -> new ElementaryQuestionStrategy(); + case "初中" -> new MiddleSchoolQuestionStrategy(); + case "高中" -> new HighSchoolQuestionStrategy(); + default -> throw new IllegalArgumentException("未知的角色: " + role); + }; } } -- 2.34.1