diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..5ff6309
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,38 @@
+target/
+!.mvn/wrapper/maven-wrapper.jar
+!**/src/main/**/target/
+!**/src/test/**/target/
+
+### IntelliJ IDEA ###
+.idea/modules.xml
+.idea/jarRepositories.xml
+.idea/compiler.xml
+.idea/libraries/
+*.iws
+*.iml
+*.ipr
+
+### Eclipse ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+build/
+!**/src/main/**/build/
+!**/src/test/**/build/
+
+### VS Code ###
+.vscode/
+
+### Mac OS ###
+.DS_Store
\ No newline at end of file
diff --git a/doc/README.md b/doc/README.md
new file mode 100644
index 0000000..9fcde7c
--- /dev/null
+++ b/doc/README.md
@@ -0,0 +1,60 @@
+### **项目概述:中小学数学卷子自动生成程序**
+
+这是一个面向中小学数学老师的命令行应用程序。其核心目标是根据教师的账户类型(小学、初中、高中),自动生成符合特定难度要求的数学练习题,并将其保存为文本文件,同时提供用户管理、难度切换和题目查重等辅助功能。
+
+本项目的设计思路均由本人完成,ai对于ui方面技术提供了意见支持。
+
+#### **一、 大概功能 **
+
+1. **用户认证系统 **
+ * 通过命令行输入用户名和密码进行登录。
+ * 系统预设了小学、初中、高中三类账户。
+ * 登录成功后,系统会根据账户类型自动设定默认的出题难度。
+
+2. **分级题目生成**
+ * 用户可指定生成题目的数量(10-30题)。
+ * 程序会根据当前选择的难度级别(小学、初中、高中)生成题目:
+ * **小学:** 包含 `+`, `-`, `*`, `/` 以及括号 `()` 的基本四则运算。
+ * **初中:** 在小学基础上,题目中至少包含一个**平方**或**开根号**运算。
+ * **高中:** 在初中基础上,题目中至少包含一个**三角函数**(`sin`, `cos`, `tan`)。
+
+3. **题目查重机制 **
+ * 为确保练习的新鲜度,系统会检查新生成的题目。
+ * 确保同一个老师账户下,新生成的卷子中的题目不与该老师历史上所有已生成文件中的题目重复。
+
+4. **动态难度切换**
+ * 登录后,用户可以通过特定命令(如 `切换为 高中`)临时改变出题的难度级别,而无需重新登录。
+
+5. **文件保存与管理**
+ * 生成的题目集将以 `年-月-日-时-分-秒.txt` 的格式命名,确保文件名唯一。
+ * 每个用户拥有一个独立的文件夹,用于存放其生成的所有题目文件,便于管理和查重。
+
+#### **二、 Java 相关技术栈 **
+
+1. **输入与输出 :**
+
+ * **`java.util.Scanner`:** 用于接收和解析来自命令行的用户输入(如用户名、密码、题目数量、切换指令等)。
+ * **`java.io` 或 `java.nio` API:** 用于文件操作。
+ * `File`: 创建用户目录、读写文件。
+ * `FileWriter` / `BufferedWriter`: 将生成的题目高效地写入 `.txt` 文件。
+ * `FileReader` / `BufferedReader`: 在执行查重功能时,读取历史题目文件。
+
+2. **数据结构与集合 **
+
+ * **`java.util.Map` (如 `HashMap`):** 非常适合用于存储和快速查找预设的用户账户信息(用户名 -> 密码,用户名 -> 账户类型)。
+ * **`java.util.Set` (如 `HashSet`):** 查重功能的核心。在生成新题目之前,将该用户历史文件中的所有题目加载到一个 `Set` 中,可以利用其 `O(1)` 的平均时间复杂度快速判断新题目是否已存在。
+ * **`java.util.List` (如 `ArrayList`):** 用于临时存储一轮新生成的题目,便于后续处理和写入文件。
+
+3. **数学与随机数 **
+
+ * **`java.util.Random`:** 用于生成随机数(作为题目中的操作数)和随机选择运算符,是题目多样性的关键。
+ * **`java.lang.Math`:** 提供 `Math.sqrt()` (开根号), `Math.pow()` (平方), 以及 `Math.sin()`, `Math.cos()`, `Math.tan()` 等三角函数运算。
+
+4. **日期与时间 (Date & Time):**
+ * **`java.time.LocalDateTime`:** 获取当前的精确年、月、日、时、分、秒。
+
+ * **`java.time.format.DateTimeFormatter`:** 将 `LocalDateTime` 对象格式化为需求中指定的文件名字符串(`"yyyy-MM-dd-HH-mm-ss"`)。
+
+
+
+
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..4900c0f
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,25 @@
+
+
+ 4.0.0
+
+ com.scapeSharing
+ Quiz_Generator_personal
+ 1.0-SNAPSHOT
+
+
+ 17
+ 17
+ UTF-8
+
+
+
+ org.projectlombok
+ lombok
+ 1.18.30
+ provided
+
+
+
+
\ No newline at end of file
diff --git a/src/main/java/com/quizgenerator/common/Level.java b/src/main/java/com/quizgenerator/common/Level.java
new file mode 100644
index 0000000..bea1f88
--- /dev/null
+++ b/src/main/java/com/quizgenerator/common/Level.java
@@ -0,0 +1,32 @@
+package com.quizgenerator.common;
+
+import lombok.Getter;
+
+/** 三种习题等级. */
+@Getter
+public enum Level {
+ PRIMARY("小学"),
+ JUNIOR_HIGH("初中"),
+ SENIOR_HIGH("高中");
+
+ private final String displayName;
+
+ Level(String displayName) {
+ this.displayName = displayName;
+ }
+
+ /**
+ * 获取等级.
+ *
+ * @param text s
+ * @return Level
+ */
+ public static Level fromString(String text) {
+ for (Level b : Level.values()) {
+ if (b.displayName.equalsIgnoreCase(text)) {
+ return b;
+ }
+ }
+ return null;
+ }
+}
diff --git a/src/main/java/com/quizgenerator/common/QuestionUtils.java b/src/main/java/com/quizgenerator/common/QuestionUtils.java
new file mode 100644
index 0000000..71a075c
--- /dev/null
+++ b/src/main/java/com/quizgenerator/common/QuestionUtils.java
@@ -0,0 +1,49 @@
+package com.quizgenerator.common;
+
+import java.util.Random;
+
+/** 一个用于题目生成的辅助工具类. 包含所有生成器可能共享的静态方法。 */
+public final class QuestionUtils {
+
+ private static final Random RANDOM = new Random();
+
+ private QuestionUtils() {}
+
+ /**
+ * 检查一个字符串是否可以被解析为整数.
+ *
+ * @param str 要检查的字符串
+ * @return 如果是数字则为 true, 否则为 false
+ */
+ public static boolean isNotNumeric(String str) {
+ if (str == null) {
+ return true; // null 不是数字,所以返回 true
+ }
+
+ try {
+ Integer.parseInt(str);
+ return false; // 能成功转换,说明是数字,所以返回 false
+ } catch (NumberFormatException e) {
+ return true; // 转换失败,说明不是数字,所以返回 true
+ }
+ }
+
+ /**
+ * 返回一个随机的四则运算符 (+, -, *, /).
+ *
+ * @return 随机的运算符字符
+ */
+ public static char getRandomOperator() {
+ char[] operators = {'+', '-', '*', '/'};
+ return operators[RANDOM.nextInt(operators.length)];
+ }
+
+ /**
+ * 返回一个1到100之间的随机操作数.
+ *
+ * @return 随机整数
+ */
+ public static int getRandomOperand() {
+ return RANDOM.nextInt(100) + 1;
+ }
+}
diff --git a/src/main/java/com/quizgenerator/dao/UserDataBase.java b/src/main/java/com/quizgenerator/dao/UserDataBase.java
new file mode 100644
index 0000000..88e91d9
--- /dev/null
+++ b/src/main/java/com/quizgenerator/dao/UserDataBase.java
@@ -0,0 +1,36 @@
+package com.quizgenerator.dao;
+
+import com.quizgenerator.common.Level;
+import com.quizgenerator.entity.User;
+import java.util.HashMap;
+import java.util.Map;
+
+/** 由于数据较少,且不好提交数据库,所以选择写死在代码里面. */
+public class UserDataBase {
+ private static final Map userDatabase = new HashMap<>();
+
+ static {
+ // 小学
+ userDatabase.put("张三1", new User("张三1", "123", Level.PRIMARY));
+ userDatabase.put("张三2", new User("张三2", "123", Level.PRIMARY));
+ userDatabase.put("张三3", new User("张三3", "123", Level.PRIMARY));
+ // 初中
+ userDatabase.put("李四1", new User("李四1", "123", Level.JUNIOR_HIGH));
+ userDatabase.put("李四2", new User("李四2", "123", Level.JUNIOR_HIGH));
+ userDatabase.put("李四3", new User("李四3", "123", Level.JUNIOR_HIGH));
+ // 高中
+ userDatabase.put("王五1", new User("王五1", "123", Level.SENIOR_HIGH));
+ userDatabase.put("王五2", new User("王五2", "123", Level.SENIOR_HIGH));
+ userDatabase.put("王五3", new User("王五3", "123", Level.SENIOR_HIGH));
+ }
+
+ /**
+ * 根据用户名查找用户.
+ *
+ * @param username 用户名
+ * @return 如果找到则返回User对象,否则返回null
+ */
+ public static User findByUsername(String username) {
+ return userDatabase.get(username);
+ }
+}
diff --git a/src/main/java/com/quizgenerator/entity/User.java b/src/main/java/com/quizgenerator/entity/User.java
new file mode 100644
index 0000000..7368bb2
--- /dev/null
+++ b/src/main/java/com/quizgenerator/entity/User.java
@@ -0,0 +1,30 @@
+package com.quizgenerator.entity;
+
+import com.quizgenerator.common.Level;
+import lombok.Data;
+
+/** User类. */
+@Data
+public class User {
+ private final String username;
+ private final String password;
+ private final Level level;
+
+ /*public User(String username, String password, Level level) {
+ this.username = username;
+ this.password = password;
+ this.level = level;
+ }
+
+ public String getUsername() {
+ return username;
+ }
+
+ public String getPassword() {
+ return password;
+ }
+
+ public Level getLevel() {
+ return level;
+ }*/
+}
diff --git a/src/main/java/com/quizgenerator/generator/QuestionGenerator.java b/src/main/java/com/quizgenerator/generator/QuestionGenerator.java
new file mode 100644
index 0000000..cdcb890
--- /dev/null
+++ b/src/main/java/com/quizgenerator/generator/QuestionGenerator.java
@@ -0,0 +1,12 @@
+package com.quizgenerator.generator;
+
+/** 题目生成接口. */
+public interface QuestionGenerator {
+
+ /**
+ * 核心方法.
+ *
+ * @return 生成的题目字符串
+ */
+ String generate();
+}
diff --git a/src/main/java/com/quizgenerator/generator/impl/JuniorHighGenerator.java b/src/main/java/com/quizgenerator/generator/impl/JuniorHighGenerator.java
new file mode 100644
index 0000000..47a186d
--- /dev/null
+++ b/src/main/java/com/quizgenerator/generator/impl/JuniorHighGenerator.java
@@ -0,0 +1,32 @@
+package com.quizgenerator.generator.impl;
+
+import com.quizgenerator.common.QuestionUtils;
+import com.quizgenerator.generator.QuestionGenerator;
+import java.util.Random;
+
+/** 初中题目生成. */
+public class JuniorHighGenerator implements QuestionGenerator {
+ private final Random random = new Random();
+ private final QuestionGenerator primaryGenerator = new PrimarySchoolGenerator();
+
+ @Override
+ public String generate() {
+ // 1.复用primary逻辑
+ // 可以优化,抽出复用逻辑,不应该让同层的类互相依赖
+ String baseQuestion = primaryGenerator.generate();
+ String[] parts = baseQuestion.split(" ");
+
+ int indexToModify;
+ do {
+ indexToModify = random.nextInt(parts.length);
+ } while (QuestionUtils.isNotNumeric(parts[indexToModify]));
+
+ if (random.nextBoolean()) {
+ parts[indexToModify] = parts[indexToModify] + "^2";
+ } else {
+ parts[indexToModify] = "sqrt(" + parts[indexToModify] + ")";
+ }
+
+ return String.join(" ", parts);
+ }
+}
diff --git a/src/main/java/com/quizgenerator/generator/impl/PrimarySchoolGenerator.java b/src/main/java/com/quizgenerator/generator/impl/PrimarySchoolGenerator.java
new file mode 100644
index 0000000..abc1840
--- /dev/null
+++ b/src/main/java/com/quizgenerator/generator/impl/PrimarySchoolGenerator.java
@@ -0,0 +1,31 @@
+package com.quizgenerator.generator.impl;
+
+import com.quizgenerator.common.QuestionUtils;
+import com.quizgenerator.generator.QuestionGenerator;
+import java.util.Random;
+
+/** 小学题目生成. */
+public class PrimarySchoolGenerator implements QuestionGenerator {
+ private final Random random = new Random();
+
+ @Override
+ public String generate() {
+ int operandCount = random.nextInt(4) + 2;
+ StringBuilder question = new StringBuilder();
+ question.append(QuestionUtils.getRandomOperand());
+
+ for (int i = 0; i < operandCount - 1; i++) {
+ question.append(" ").append(QuestionUtils.getRandomOperator()).append(" ");
+
+ if (random.nextBoolean() && i < operandCount - 2) {
+ question.append("( ").append(QuestionUtils.getRandomOperand()).append(" ");
+ question.append(QuestionUtils.getRandomOperator()).append(" ");
+ question.append(QuestionUtils.getRandomOperand()).append(" )");
+ i++;
+ } else {
+ question.append(QuestionUtils.getRandomOperand());
+ }
+ }
+ return question.toString();
+ }
+}
diff --git a/src/main/java/com/quizgenerator/generator/impl/SeniorHighGenerator.java b/src/main/java/com/quizgenerator/generator/impl/SeniorHighGenerator.java
new file mode 100644
index 0000000..a5671e9
--- /dev/null
+++ b/src/main/java/com/quizgenerator/generator/impl/SeniorHighGenerator.java
@@ -0,0 +1,32 @@
+package com.quizgenerator.generator.impl;
+
+import com.quizgenerator.common.QuestionUtils;
+import com.quizgenerator.generator.QuestionGenerator;
+import java.util.Random;
+
+/** 高中题目生成 */
+public class SeniorHighGenerator implements QuestionGenerator {
+ private final Random random = new Random();
+ private final QuestionGenerator primaryGenerator = new PrimarySchoolGenerator();
+
+ @Override
+ public String generate() {
+ String baseQuestion = primaryGenerator.generate();
+ String[] parts = baseQuestion.split(" ");
+
+ int indexToModify;
+ do {
+ indexToModify = random.nextInt(parts.length);
+ } while (QuestionUtils.isNotNumeric(parts[indexToModify]));
+
+ String[] trigFuncs = {"sin", "cos", "tan"};
+ String func = trigFuncs[random.nextInt(trigFuncs.length)];
+
+ int[] angles = {30, 45, 60, 90};
+ int angle = angles[random.nextInt(angles.length)];
+
+ parts[indexToModify] = func + "(" + angle + ")";
+
+ return String.join(" ", parts);
+ }
+}
diff --git a/src/main/java/com/quizgenerator/service/QuestionService.java b/src/main/java/com/quizgenerator/service/QuestionService.java
new file mode 100644
index 0000000..ef95f9e
--- /dev/null
+++ b/src/main/java/com/quizgenerator/service/QuestionService.java
@@ -0,0 +1,121 @@
+package com.quizgenerator.service;
+
+import com.quizgenerator.common.Level;
+import com.quizgenerator.generator.QuestionGenerator;
+import com.quizgenerator.generator.impl.JuniorHighGenerator;
+import com.quizgenerator.generator.impl.PrimarySchoolGenerator;
+import com.quizgenerator.generator.impl.SeniorHighGenerator;
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.stream.Stream;
+
+/** 问题核心处理逻辑. */
+public class QuestionService {
+ private final Map generators = new HashMap<>();
+
+ /** 构造函数,初始化题目生成器. */
+ public QuestionService() {
+ generators.put(Level.PRIMARY, new PrimarySchoolGenerator());
+ generators.put(Level.JUNIOR_HIGH, new JuniorHighGenerator());
+ generators.put(Level.SENIOR_HIGH, new SeniorHighGenerator());
+ }
+
+ /**
+ * 生成指定数量的不重复题目.
+ *
+ * @param level 题目等级
+ * @param count 题目数量
+ * @param username 用户名
+ * @return 包含不重复题目的列表
+ */
+ public List generateUniqueQuiz(Level level, int count, String username) {
+ QuestionGenerator generator = generators.get(level);
+ if (generator == null) {
+ throw new IllegalArgumentException("无效的等级代号");
+ }
+
+ Set existingQuestions = loadExistingQuestions(username);
+ List newQuestions = new ArrayList<>();
+
+ while (newQuestions.size() < count) {
+ String question = generator.generate();
+ if (!existingQuestions.contains(question)) {
+ newQuestions.add(question);
+ existingQuestions.add(question);
+ }
+ }
+ return newQuestions;
+ }
+
+ private Set loadExistingQuestions(String username) {
+ Set questions = new HashSet<>();
+ File userDir = new File(username);
+ if (!userDir.exists() || !userDir.isDirectory()) {
+ return questions;
+ }
+
+ try (Stream paths = Files.walk(Paths.get(username))) {
+ paths
+ .filter(Files::isRegularFile)
+ .filter(path -> path.toString().endsWith(".txt"))
+ .forEach(
+ path -> {
+ try {
+ Files.lines(path)
+ .forEach(
+ line -> {
+ // Extract question text, assuming format "1. question..."
+ if (line.matches("^\\d+\\.\\s.*")) {
+ questions.add(line.substring(line.indexOf('.') + 2));
+ }
+ });
+ } catch (IOException e) {
+ System.err.println("Error reading file: " + path);
+ }
+ });
+ } catch (IOException e) {
+ System.err.println("Error walking directory: " + username);
+ }
+ return questions;
+ }
+
+ /**
+ * 保存到文件.
+ *
+ * @param questions 问题
+ * @param username 用户
+ */
+ public void saveQuizToFile(List questions, String username) {
+ File userDir = new File(username);
+ if (!userDir.exists()) {
+ userDir.mkdirs(); // Create directory if it doesn't exist
+ }
+
+ String timestamp =
+ LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd-HH-mm-ss"));
+ String filename = username + "/" + timestamp + ".txt";
+
+ try (FileWriter writer = new FileWriter(filename)) {
+ for (int i = 0; i < questions.size(); i++) {
+ writer.write((i + 1) + ". " + questions.get(i) + "\n");
+ writer.write("\n"); // Blank line between questions
+ }
+ System.out.println("试卷已成功生成并保存至: " + filename);
+ } catch (IOException e) {
+ System.err.println("错误:无法保存文件 " + filename);
+ e.printStackTrace();
+ }
+ }
+}
diff --git a/src/main/java/com/quizgenerator/service/UserService.java b/src/main/java/com/quizgenerator/service/UserService.java
new file mode 100644
index 0000000..fe0a2a4
--- /dev/null
+++ b/src/main/java/com/quizgenerator/service/UserService.java
@@ -0,0 +1,30 @@
+package com.quizgenerator.service;
+
+import com.quizgenerator.dao.UserDataBase;
+import com.quizgenerator.entity.User;
+
+/** 用户服务. */
+public class UserService {
+
+ /**
+ * 用户登录验证.
+ *
+ * @param username 用户名
+ * @param password 密码
+ * @return 如果登录成功,返回对应的 User 对象;如果失败,返回 null
+ */
+ public User login(String username, String password) {
+ // 1. 调用修改后的 findByUsername。如果用户不存在,这里会得到 null
+ User user = UserDataBase.findByUsername(username);
+
+ // 2. 检查用户是否存在(user != null)并且密码是否匹配
+ // TODO 使用md5加密密码
+ if (user != null && user.getPassword().equals(password)) {
+ // 登录成功,返回找到的 user 对象
+ return user;
+ } else {
+ // 用户不存在或密码错误,返回 null
+ return null;
+ }
+ }
+}
diff --git a/src/main/java/com/quizgenerator/system/ConsoleUi.java b/src/main/java/com/quizgenerator/system/ConsoleUi.java
new file mode 100644
index 0000000..adc3940
--- /dev/null
+++ b/src/main/java/com/quizgenerator/system/ConsoleUi.java
@@ -0,0 +1,94 @@
+package com.quizgenerator.system;
+
+import com.quizgenerator.common.Level;
+import com.quizgenerator.entity.User;
+import java.util.Scanner;
+
+/** UI界面. */
+public class ConsoleUi {
+ private final Scanner scanner;
+
+ /** 输入. */
+ public ConsoleUi() {
+ this.scanner = new Scanner(System.in);
+ }
+
+ /** 主界面展示. */
+ public void displayWelcomeMessage() {
+ System.out.println("==========================================");
+ System.out.println("欢迎使用中小学数学卷子自动生成程序");
+ System.out.println("==========================================");
+ }
+
+ /**
+ * 类似Prompt,用于获取用户凭证.
+ *
+ * @return 包含用户名和密码的字符串数组.
+ */
+ public String[] promptForCredentials() {
+ System.out.print("请输入用户名和密码 (用空格隔开): ");
+ return scanner.nextLine().split(" ");
+ }
+
+ /** 错误信息. */
+ public void displayLoginError() {
+ System.out.println("用户名或密码错误,请重新输入。");
+ }
+
+ /** 格式错误. */
+ public void displayInvalidInputFormat() {
+ System.out.println("输入格式不正确,请输入 '用户名 密码'。");
+ }
+
+ /**
+ * 登录成功信息.
+ *
+ * @param user 用户对象.
+ */
+ public void displayLoginSuccess(User user) {
+ System.out.println("\n登录成功! 当前选择为 " + user.getLevel().getDisplayName() + " 出题。");
+ }
+
+ /**
+ * 主菜单操作提示.
+ *
+ * @param currentLevel 当前用户的等级.
+ * @return 用户的输入指令.
+ */
+ public String promptForMainMenuAction(Level currentLevel) {
+ System.out.print(
+ "\n准备生成"
+ + currentLevel.getDisplayName()
+ + "数学题目, 请输入生成题目数量(10-30, 或输入-1退出登录, 或输入'切换为 XX'): ");
+ return scanner.nextLine().trim();
+ }
+
+ /** 退出展示. */
+ public void displayLogoutMessage() {
+ System.out.println("已退出当前用户,返回登录界面。");
+ }
+
+ /**
+ * 成功信息.
+ *
+ * @param newLevel 修改后的等级.
+ */
+ public void displayLevelChangeSuccess(Level newLevel) {
+ System.out.println("切换成功! 当前难度已设置为: " + newLevel.getDisplayName());
+ }
+
+ /** 修改错误信息. */
+ public void displayInvalidLevelChangeCommand() {
+ System.out.println("无效的切换指令, 请输入'切换为 小学'、'切换为 初中'或'切换为 高中'。");
+ }
+
+ /** 显示无效数字范围的错误信息. */
+ public void displayInvalidNumberRange() {
+ System.out.println("输入无效, 题目数量必须在 10 到 30 之间。");
+ }
+
+ /** 显示通用无效输入错误信息. */
+ public void displayGenericInvalidInput() {
+ System.out.println("无效输入, 请输入数字、'-1'或切换指令。");
+ }
+}
diff --git a/src/main/java/com/quizgenerator/system/LoginHandler.java b/src/main/java/com/quizgenerator/system/LoginHandler.java
new file mode 100644
index 0000000..9270065
--- /dev/null
+++ b/src/main/java/com/quizgenerator/system/LoginHandler.java
@@ -0,0 +1,42 @@
+package com.quizgenerator.system;
+
+import com.quizgenerator.entity.User;
+import com.quizgenerator.service.UserService;
+
+/** 登录逻辑. */
+public class LoginHandler {
+ private final UserService userService;
+ private final ConsoleUi ui;
+
+ /**
+ * 构造一个新的登录处理器.
+ *
+ * @param userService 用户服务实例.
+ * @param ui 控制台UI实例.
+ */
+ public LoginHandler(UserService userService, ConsoleUi ui) {
+ this.userService = userService;
+ this.ui = ui;
+ }
+
+ /**
+ * 执行用户登录流程,直到成功为止.
+ *
+ * @return 登录成功的用户对象.
+ */
+ public User performLogin() {
+ User currentUser = null;
+ while (currentUser == null) {
+ String[] credentials = ui.promptForCredentials();
+ if (credentials.length == 2) {
+ currentUser = userService.login(credentials[0], credentials[1]);
+ if (currentUser == null) {
+ ui.displayLoginError();
+ }
+ } else {
+ ui.displayInvalidInputFormat();
+ }
+ }
+ return currentUser;
+ }
+}
diff --git a/src/main/java/com/quizgenerator/system/MainMenuHandler.java b/src/main/java/com/quizgenerator/system/MainMenuHandler.java
new file mode 100644
index 0000000..e17299e
--- /dev/null
+++ b/src/main/java/com/quizgenerator/system/MainMenuHandler.java
@@ -0,0 +1,88 @@
+package com.quizgenerator.system;
+
+import com.quizgenerator.common.Level;
+import com.quizgenerator.entity.User;
+import com.quizgenerator.service.QuestionService;
+import java.util.List;
+
+/** 主菜单处理器. */
+public class MainMenuHandler {
+ private final QuestionService questionService;
+ private final ConsoleUi ui;
+
+ /**
+ * 构造一个新的主菜单处理器.
+ *
+ * @param questionService 题目服务实例.
+ * @param ui 控制台UI实例.
+ */
+ public MainMenuHandler(QuestionService questionService, ConsoleUi ui) {
+ this.questionService = questionService;
+ this.ui = ui;
+ }
+
+ /**
+ * 处理主菜单的交互逻辑.
+ *
+ * @param currentUser 当前登录的用户.
+ */
+ public void handleMainMenu(User currentUser) {
+ Level currentLevel = currentUser.getLevel();
+
+ while (true) {
+ String input = ui.promptForMainMenuAction(currentLevel);
+
+ if ("-1".equals(input)) {
+ ui.displayLogoutMessage();
+ return; // 主菜单-1表示退出
+ }
+
+ if (input.startsWith("切换为")) {
+ currentLevel = handleChangeLevel(input, currentLevel);
+ continue;
+ }
+
+ handleQuizGeneration(input, currentLevel, currentUser.getUsername());
+ }
+ }
+
+ /**
+ * 处理用户切换难度的指令.
+ *
+ * @param input 用户的完整输入指令.
+ * @param defaultLevel 如果切换失败,返回的默认等级.
+ * @return 切换成功后的新等级或原始等级.
+ */
+ private Level handleChangeLevel(String input, Level defaultLevel) {
+ String targetLevelStr = input.substring(3).trim();
+ Level newLevel = Level.fromString(targetLevelStr);
+ if (newLevel != null) {
+ ui.displayLevelChangeSuccess(newLevel);
+ return newLevel;
+ } else {
+ ui.displayInvalidLevelChangeCommand();
+ return defaultLevel;
+ }
+ }
+
+ /**
+ * 根据用户输入的数量和当前等级生成题目.
+ *
+ * @param input 用户的输入,期望是题目数量.
+ * @param level 当前选择的题目难度等级.
+ * @param username 当前用户的用户名,用于保存文件.
+ */
+ private void handleQuizGeneration(String input, Level level, String username) {
+ try {
+ int count = Integer.parseInt(input);
+ if (count >= 10 && count <= 30) {
+ List quiz = questionService.generateUniqueQuiz(level, count, username);
+ questionService.saveQuizToFile(quiz, username);
+ } else {
+ ui.displayInvalidNumberRange();
+ }
+ } catch (NumberFormatException e) {
+ ui.displayGenericInvalidInput();
+ }
+ }
+}
diff --git a/src/main/java/com/quizgenerator/system/QuizApplication.java b/src/main/java/com/quizgenerator/system/QuizApplication.java
new file mode 100644
index 0000000..595d302
--- /dev/null
+++ b/src/main/java/com/quizgenerator/system/QuizApplication.java
@@ -0,0 +1,49 @@
+package com.quizgenerator.system;
+
+import com.quizgenerator.entity.User;
+import com.quizgenerator.service.QuestionService;
+import com.quizgenerator.service.UserService;
+
+/** 应用程序的主入口类,负责启动和协调整个问答流程. */
+public class QuizApplication {
+ private final LoginHandler loginHandler;
+ private final MainMenuHandler mainMenuHandler;
+ private final ConsoleUi consoleUi;
+
+ /** 构造 QuizApplication 实例. 负责初始化所有必要的服务和处理器. */
+ public QuizApplication() {
+ // 1. 初始化
+ UserService userService = new UserService();
+ QuestionService questionService = new QuestionService();
+ this.consoleUi = new ConsoleUi();
+
+ // 2. 初始化处理器
+ this.loginHandler = new LoginHandler(userService, consoleUi);
+ this.mainMenuHandler = new MainMenuHandler(questionService, consoleUi);
+ }
+
+ /** 启动并运行应用程序的主循环. 这个方法会持续运行,处理用户登录和主菜单交互. */
+ public void run() {
+ consoleUi.displayWelcomeMessage();
+ while (true) {
+ // 3. 处理登录流程
+ User currentUser = loginHandler.performLogin();
+
+ // 4. 进入主菜单循环
+ if (currentUser != null) {
+ consoleUi.displayLoginSuccess(currentUser);
+ mainMenuHandler.handleMainMenu(currentUser);
+ }
+ }
+ }
+
+ /**
+ * 应用程序的入口点.
+ *
+ * @param args 命令行参数 (未使用).
+ */
+ public static void main(String[] args) {
+ QuizApplication app = new QuizApplication();
+ app.run();
+ }
+}