|  |  |  | @ -0,0 +1,626 @@ | 
			
		
	
		
			
				
					|  |  |  |  | import java.io.*; | 
			
		
	
		
			
				
					|  |  |  |  | import java.text.SimpleDateFormat; | 
			
		
	
		
			
				
					|  |  |  |  | import java.util.*; | 
			
		
	
		
			
				
					|  |  |  |  | import java.util.regex.Pattern; | 
			
		
	
		
			
				
					|  |  |  |  | import java.util.regex.Matcher; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | /** | 
			
		
	
		
			
				
					|  |  |  |  |  * 中小学数学卷子自动生成程序主类 | 
			
		
	
		
			
				
					|  |  |  |  |  */ | 
			
		
	
		
			
				
					|  |  |  |  | public class MathExamGenerator { | 
			
		
	
		
			
				
					|  |  |  |  |     public static void main(String[] args) { | 
			
		
	
		
			
				
					|  |  |  |  |         try { | 
			
		
	
		
			
				
					|  |  |  |  |             ApplicationController controller = new ApplicationController(); | 
			
		
	
		
			
				
					|  |  |  |  |             controller.run(); | 
			
		
	
		
			
				
					|  |  |  |  |         } catch (Exception e) { | 
			
		
	
		
			
				
					|  |  |  |  |             System.out.println("程序启动失败: " + e.getMessage()); | 
			
		
	
		
			
				
					|  |  |  |  |             e.printStackTrace(); | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | /** | 
			
		
	
		
			
				
					|  |  |  |  |  * 应用程序控制器 - 负责协调各个模块 | 
			
		
	
		
			
				
					|  |  |  |  |  */ | 
			
		
	
		
			
				
					|  |  |  |  | class ApplicationController { | 
			
		
	
		
			
				
					|  |  |  |  |     private AccountManager accountManager; | 
			
		
	
		
			
				
					|  |  |  |  |     private String currentUser; | 
			
		
	
		
			
				
					|  |  |  |  |     private String currentType; | 
			
		
	
		
			
				
					|  |  |  |  |     private DuplicateChecker duplicateChecker; | 
			
		
	
		
			
				
					|  |  |  |  |     private FileSaver fileSaver; | 
			
		
	
		
			
				
					|  |  |  |  |     private Map<String, QuestionGenerator> generatorMap; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     public ApplicationController() { | 
			
		
	
		
			
				
					|  |  |  |  |         this.accountManager = new AccountManager(); | 
			
		
	
		
			
				
					|  |  |  |  |         this.generatorMap = new HashMap<>(); | 
			
		
	
		
			
				
					|  |  |  |  |         generatorMap.put("小学", new PrimarySchoolGenerator()); | 
			
		
	
		
			
				
					|  |  |  |  |         generatorMap.put("初中", new JuniorHighGenerator()); | 
			
		
	
		
			
				
					|  |  |  |  |         generatorMap.put("高中", new SeniorHighGenerator()); | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     public void run() { | 
			
		
	
		
			
				
					|  |  |  |  |         System.out.println("=== 中小学数学卷子自动生成程序 ==="); | 
			
		
	
		
			
				
					|  |  |  |  |         Scanner scanner = new Scanner(System.in); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         while (true) { | 
			
		
	
		
			
				
					|  |  |  |  |             // 登录
 | 
			
		
	
		
			
				
					|  |  |  |  |             if (!login(scanner)) { | 
			
		
	
		
			
				
					|  |  |  |  |                 break; | 
			
		
	
		
			
				
					|  |  |  |  |             } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |             // 登录后直接进入出题流程
 | 
			
		
	
		
			
				
					|  |  |  |  |             boolean stayLoggedIn = true; | 
			
		
	
		
			
				
					|  |  |  |  |             while (stayLoggedIn) { | 
			
		
	
		
			
				
					|  |  |  |  |                 System.out.print("准备生成" + currentType + "数学题目,请输入生成题目数量(输入-1将退出当前用户,重新登录): "); | 
			
		
	
		
			
				
					|  |  |  |  |                 String input = scanner.nextLine().trim(); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |                 // 处理切换类型命令
 | 
			
		
	
		
			
				
					|  |  |  |  |                 if (input.startsWith("切换为")) { | 
			
		
	
		
			
				
					|  |  |  |  |                     String newType = input.substring(3).trim(); | 
			
		
	
		
			
				
					|  |  |  |  |                     if (switchType(newType)) { | 
			
		
	
		
			
				
					|  |  |  |  |                         // 切换成功后继续循环,会显示新的提示
 | 
			
		
	
		
			
				
					|  |  |  |  |                         continue; | 
			
		
	
		
			
				
					|  |  |  |  |                     } else { | 
			
		
	
		
			
				
					|  |  |  |  |                         // 切换失败,继续当前循环
 | 
			
		
	
		
			
				
					|  |  |  |  |                         continue; | 
			
		
	
		
			
				
					|  |  |  |  |                     } | 
			
		
	
		
			
				
					|  |  |  |  |                 } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |                 // 处理退出命令
 | 
			
		
	
		
			
				
					|  |  |  |  |                 if ("-1".equals(input)) { | 
			
		
	
		
			
				
					|  |  |  |  |                     stayLoggedIn = false; | 
			
		
	
		
			
				
					|  |  |  |  |                     continue; | 
			
		
	
		
			
				
					|  |  |  |  |                 } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |                 // 处理题目数量输入
 | 
			
		
	
		
			
				
					|  |  |  |  |                 try { | 
			
		
	
		
			
				
					|  |  |  |  |                     int numQuestions = Integer.parseInt(input); | 
			
		
	
		
			
				
					|  |  |  |  |                     if (numQuestions < 10 || numQuestions > 30) { | 
			
		
	
		
			
				
					|  |  |  |  |                         System.out.println("题目数量范围应为10-30"); | 
			
		
	
		
			
				
					|  |  |  |  |                         continue; | 
			
		
	
		
			
				
					|  |  |  |  |                     } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |                     // 生成题目
 | 
			
		
	
		
			
				
					|  |  |  |  |                     QuestionGenerator generator = generatorMap.get(currentType); | 
			
		
	
		
			
				
					|  |  |  |  |                     List<String> questions = new ArrayList<>(); | 
			
		
	
		
			
				
					|  |  |  |  |                     int attempts = 0; | 
			
		
	
		
			
				
					|  |  |  |  |                     int maxAttempts = numQuestions * 10; // 防止无限循环
 | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |                     while (questions.size() < numQuestions && attempts < maxAttempts) { | 
			
		
	
		
			
				
					|  |  |  |  |                         String newQuestion = generator.generateQuestion(); | 
			
		
	
		
			
				
					|  |  |  |  |                         if (!duplicateChecker.isDuplicate(newQuestion)) { | 
			
		
	
		
			
				
					|  |  |  |  |                             questions.add(newQuestion); | 
			
		
	
		
			
				
					|  |  |  |  |                             duplicateChecker.addQuestion(newQuestion); | 
			
		
	
		
			
				
					|  |  |  |  |                         } | 
			
		
	
		
			
				
					|  |  |  |  |                         attempts++; | 
			
		
	
		
			
				
					|  |  |  |  |                     } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |                     if (questions.size() < numQuestions) { | 
			
		
	
		
			
				
					|  |  |  |  |                         System.out.println("警告:只生成了" + questions.size() + "道不重复的题目(历史题目过多)"); | 
			
		
	
		
			
				
					|  |  |  |  |                     } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |                     // 保存文件
 | 
			
		
	
		
			
				
					|  |  |  |  |                     String filename = fileSaver.saveExam(questions, currentType); | 
			
		
	
		
			
				
					|  |  |  |  |                     System.out.println("试卷已生成并保存为: " + filename); | 
			
		
	
		
			
				
					|  |  |  |  |                     System.out.println("题目生成完成,可以继续生成新试卷或输入-1退出当前用户"); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |                 } catch (NumberFormatException e) { | 
			
		
	
		
			
				
					|  |  |  |  |                     System.out.println("请输入有效的数字或'切换为小学/初中/高中'"); | 
			
		
	
		
			
				
					|  |  |  |  |                 } catch (Exception e) { | 
			
		
	
		
			
				
					|  |  |  |  |                     System.out.println("生成题目出错: " + e.getMessage()); | 
			
		
	
		
			
				
					|  |  |  |  |                     e.printStackTrace(); // 添加详细错误信息
 | 
			
		
	
		
			
				
					|  |  |  |  |                 } | 
			
		
	
		
			
				
					|  |  |  |  |             } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |             // 退出当前用户,准备重新登录
 | 
			
		
	
		
			
				
					|  |  |  |  |             logout(); | 
			
		
	
		
			
				
					|  |  |  |  |             System.out.println("已退出当前用户"); | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         scanner.close(); | 
			
		
	
		
			
				
					|  |  |  |  |         System.out.println("程序结束"); | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     private boolean login(Scanner scanner) { | 
			
		
	
		
			
				
					|  |  |  |  |         while (true) { | 
			
		
	
		
			
				
					|  |  |  |  |             System.out.print("请输入用户名和密码(用空格隔开): "); | 
			
		
	
		
			
				
					|  |  |  |  |             String input = scanner.nextLine().trim(); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |             if (input.isEmpty()) { | 
			
		
	
		
			
				
					|  |  |  |  |                 continue; | 
			
		
	
		
			
				
					|  |  |  |  |             } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |             String[] parts = input.split("\\s+"); | 
			
		
	
		
			
				
					|  |  |  |  |             if (parts.length != 2) { | 
			
		
	
		
			
				
					|  |  |  |  |                 System.out.println("请输入正确的用户名、密码格式"); | 
			
		
	
		
			
				
					|  |  |  |  |                 continue; | 
			
		
	
		
			
				
					|  |  |  |  |             } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |             String username = parts[0]; | 
			
		
	
		
			
				
					|  |  |  |  |             String password = parts[1]; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |             LoginResult result = accountManager.validateAccount(username, password); | 
			
		
	
		
			
				
					|  |  |  |  |             if (result.isSuccess()) { | 
			
		
	
		
			
				
					|  |  |  |  |                 currentUser = username; | 
			
		
	
		
			
				
					|  |  |  |  |                 currentType = result.getUserType(); | 
			
		
	
		
			
				
					|  |  |  |  |                 duplicateChecker = new DuplicateChecker(username); | 
			
		
	
		
			
				
					|  |  |  |  |                 fileSaver = new FileSaver(username); | 
			
		
	
		
			
				
					|  |  |  |  |                 System.out.println("当前选择为" + currentType + "出题"); | 
			
		
	
		
			
				
					|  |  |  |  |                 return true; | 
			
		
	
		
			
				
					|  |  |  |  |             } else { | 
			
		
	
		
			
				
					|  |  |  |  |                 System.out.println("请输入正确的用户名、密码"); | 
			
		
	
		
			
				
					|  |  |  |  |             } | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     private boolean switchType(String newType) { | 
			
		
	
		
			
				
					|  |  |  |  |         if ("小学".equals(newType) || "初中".equals(newType) || "高中".equals(newType)) { | 
			
		
	
		
			
				
					|  |  |  |  |             currentType = newType; | 
			
		
	
		
			
				
					|  |  |  |  |             System.out.println("已切换为" + newType + "出题"); | 
			
		
	
		
			
				
					|  |  |  |  |             return true; | 
			
		
	
		
			
				
					|  |  |  |  |         } else { | 
			
		
	
		
			
				
					|  |  |  |  |             System.out.println("请输入小学、初中和高中三个选项中的一个"); | 
			
		
	
		
			
				
					|  |  |  |  |             return false; | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     private void logout() { | 
			
		
	
		
			
				
					|  |  |  |  |         currentUser = null; | 
			
		
	
		
			
				
					|  |  |  |  |         currentType = null; | 
			
		
	
		
			
				
					|  |  |  |  |         duplicateChecker = null; | 
			
		
	
		
			
				
					|  |  |  |  |         fileSaver = null; | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | /** | 
			
		
	
		
			
				
					|  |  |  |  |  * 登录结果封装类 | 
			
		
	
		
			
				
					|  |  |  |  |  */ | 
			
		
	
		
			
				
					|  |  |  |  | class LoginResult { | 
			
		
	
		
			
				
					|  |  |  |  |     private boolean success; | 
			
		
	
		
			
				
					|  |  |  |  |     private String userType; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     public LoginResult(boolean success, String userType) { | 
			
		
	
		
			
				
					|  |  |  |  |         this.success = success; | 
			
		
	
		
			
				
					|  |  |  |  |         this.userType = userType; | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     public boolean isSuccess() { | 
			
		
	
		
			
				
					|  |  |  |  |         return success; | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     public String getUserType() { | 
			
		
	
		
			
				
					|  |  |  |  |         return userType; | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | /** | 
			
		
	
		
			
				
					|  |  |  |  |  * 账户管理类 | 
			
		
	
		
			
				
					|  |  |  |  |  */ | 
			
		
	
		
			
				
					|  |  |  |  | class AccountManager { | 
			
		
	
		
			
				
					|  |  |  |  |     private Map<String, List<Account>> accounts; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     public AccountManager() { | 
			
		
	
		
			
				
					|  |  |  |  |         accounts = new HashMap<>(); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         // 小学账户
 | 
			
		
	
		
			
				
					|  |  |  |  |         List<Account> primaryAccounts = Arrays.asList( | 
			
		
	
		
			
				
					|  |  |  |  |                 new Account("张三1", "123"), | 
			
		
	
		
			
				
					|  |  |  |  |                 new Account("张三2", "123"), | 
			
		
	
		
			
				
					|  |  |  |  |                 new Account("张三3", "123") | 
			
		
	
		
			
				
					|  |  |  |  |         ); | 
			
		
	
		
			
				
					|  |  |  |  |         accounts.put("小学", primaryAccounts); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         // 初中账户
 | 
			
		
	
		
			
				
					|  |  |  |  |         List<Account> juniorAccounts = Arrays.asList( | 
			
		
	
		
			
				
					|  |  |  |  |                 new Account("李四1", "123"), | 
			
		
	
		
			
				
					|  |  |  |  |                 new Account("李四2", "123"), | 
			
		
	
		
			
				
					|  |  |  |  |                 new Account("李四3", "123") | 
			
		
	
		
			
				
					|  |  |  |  |         ); | 
			
		
	
		
			
				
					|  |  |  |  |         accounts.put("初中", juniorAccounts); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         // 高中账户
 | 
			
		
	
		
			
				
					|  |  |  |  |         List<Account> seniorAccounts = Arrays.asList( | 
			
		
	
		
			
				
					|  |  |  |  |                 new Account("王五1", "123"), | 
			
		
	
		
			
				
					|  |  |  |  |                 new Account("王五2", "123"), | 
			
		
	
		
			
				
					|  |  |  |  |                 new Account("王五3", "123") | 
			
		
	
		
			
				
					|  |  |  |  |         ); | 
			
		
	
		
			
				
					|  |  |  |  |         accounts.put("高中", seniorAccounts); | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     public LoginResult validateAccount(String username, String password) { | 
			
		
	
		
			
				
					|  |  |  |  |         for (Map.Entry<String, List<Account>> entry : accounts.entrySet()) { | 
			
		
	
		
			
				
					|  |  |  |  |             for (Account account : entry.getValue()) { | 
			
		
	
		
			
				
					|  |  |  |  |                 if (account.getUsername().equals(username) && account.getPassword().equals(password)) { | 
			
		
	
		
			
				
					|  |  |  |  |                     return new LoginResult(true, entry.getKey()); | 
			
		
	
		
			
				
					|  |  |  |  |                 } | 
			
		
	
		
			
				
					|  |  |  |  |             } | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  |         return new LoginResult(false, null); | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     /** | 
			
		
	
		
			
				
					|  |  |  |  |      * 账户信息封装类 | 
			
		
	
		
			
				
					|  |  |  |  |      */ | 
			
		
	
		
			
				
					|  |  |  |  |     private static class Account { | 
			
		
	
		
			
				
					|  |  |  |  |         private String username; | 
			
		
	
		
			
				
					|  |  |  |  |         private String password; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         public Account(String username, String password) { | 
			
		
	
		
			
				
					|  |  |  |  |             this.username = username; | 
			
		
	
		
			
				
					|  |  |  |  |             this.password = password; | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         public String getUsername() { | 
			
		
	
		
			
				
					|  |  |  |  |             return username; | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         public String getPassword() { | 
			
		
	
		
			
				
					|  |  |  |  |             return password; | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | /** | 
			
		
	
		
			
				
					|  |  |  |  |  * 题目生成器接口 | 
			
		
	
		
			
				
					|  |  |  |  |  */ | 
			
		
	
		
			
				
					|  |  |  |  | interface QuestionGenerator { | 
			
		
	
		
			
				
					|  |  |  |  |     String generateQuestion(); | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | /** | 
			
		
	
		
			
				
					|  |  |  |  |  * 小学题目生成器 | 
			
		
	
		
			
				
					|  |  |  |  |  */ | 
			
		
	
		
			
				
					|  |  |  |  | class PrimarySchoolGenerator implements QuestionGenerator { | 
			
		
	
		
			
				
					|  |  |  |  |     private Random random = new Random(); | 
			
		
	
		
			
				
					|  |  |  |  |     private List<String> operators = Arrays.asList("+", "-", "*", "/"); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     @Override | 
			
		
	
		
			
				
					|  |  |  |  |     public String generateQuestion() { | 
			
		
	
		
			
				
					|  |  |  |  |         try { | 
			
		
	
		
			
				
					|  |  |  |  |             // 确保每道题目最少有两个操作数(2-5个)
 | 
			
		
	
		
			
				
					|  |  |  |  |             int numOperands = random.nextInt(4) + 2; // 2-5个操作数
 | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |             // 生成操作数
 | 
			
		
	
		
			
				
					|  |  |  |  |             int[] operands = new int[numOperands]; | 
			
		
	
		
			
				
					|  |  |  |  |             for (int i = 0; i < numOperands; i++) { | 
			
		
	
		
			
				
					|  |  |  |  |                 operands[i] = random.nextInt(100) + 1; // 1-100
 | 
			
		
	
		
			
				
					|  |  |  |  |             } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |             // 生成运算符
 | 
			
		
	
		
			
				
					|  |  |  |  |             String[] operatorArray = new String[numOperands - 1]; | 
			
		
	
		
			
				
					|  |  |  |  |             for (int i = 0; i < numOperands - 1; i++) { | 
			
		
	
		
			
				
					|  |  |  |  |                 operatorArray[i] = operators.get(random.nextInt(operators.size())); | 
			
		
	
		
			
				
					|  |  |  |  |             } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |             // 构建表达式并确保结果非负
 | 
			
		
	
		
			
				
					|  |  |  |  |             String expression; | 
			
		
	
		
			
				
					|  |  |  |  |             do { | 
			
		
	
		
			
				
					|  |  |  |  |                 // 重新生成操作数和运算符(如果之前的结果为负)
 | 
			
		
	
		
			
				
					|  |  |  |  |                 for (int i = 0; i < numOperands; i++) { | 
			
		
	
		
			
				
					|  |  |  |  |                     operands[i] = random.nextInt(100) + 1; | 
			
		
	
		
			
				
					|  |  |  |  |                 } | 
			
		
	
		
			
				
					|  |  |  |  |                 for (int i = 0; i < numOperands - 1; i++) { | 
			
		
	
		
			
				
					|  |  |  |  |                     operatorArray[i] = operators.get(random.nextInt(operators.size())); | 
			
		
	
		
			
				
					|  |  |  |  |                 } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |                 // 构建表达式
 | 
			
		
	
		
			
				
					|  |  |  |  |                 StringBuilder exprBuilder = new StringBuilder(); | 
			
		
	
		
			
				
					|  |  |  |  |                 exprBuilder.append(operands[0]); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |                 for (int i = 1; i < numOperands; i++) { | 
			
		
	
		
			
				
					|  |  |  |  |                     // 如果是减法,确保不会产生负数
 | 
			
		
	
		
			
				
					|  |  |  |  |                     if ("-".equals(operatorArray[i-1])) { | 
			
		
	
		
			
				
					|  |  |  |  |                         // 计算当前部分表达式的值
 | 
			
		
	
		
			
				
					|  |  |  |  |                         int currentValue = calculatePartialExpression(exprBuilder.toString()); | 
			
		
	
		
			
				
					|  |  |  |  |                         if (currentValue < operands[i]) { | 
			
		
	
		
			
				
					|  |  |  |  |                             // 如果减法会产生负数,改为加法
 | 
			
		
	
		
			
				
					|  |  |  |  |                             operatorArray[i-1] = "+"; | 
			
		
	
		
			
				
					|  |  |  |  |                         } | 
			
		
	
		
			
				
					|  |  |  |  |                     } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |                     exprBuilder.append(" ").append(operatorArray[i-1]).append(" ").append(operands[i]); | 
			
		
	
		
			
				
					|  |  |  |  |                 } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |                 expression = exprBuilder.toString(); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |                 // 计算整个表达式的结果
 | 
			
		
	
		
			
				
					|  |  |  |  |                 double result = evaluateExpression(expression); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |                 // 如果结果为负,重新生成
 | 
			
		
	
		
			
				
					|  |  |  |  |                 if (result < 0) { | 
			
		
	
		
			
				
					|  |  |  |  |                     continue; | 
			
		
	
		
			
				
					|  |  |  |  |                 } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |                 // 随机添加括号(只在有3个及以上操作数时)
 | 
			
		
	
		
			
				
					|  |  |  |  |                 if (numOperands >= 3 && random.nextDouble() < 0.3) { | 
			
		
	
		
			
				
					|  |  |  |  |                     // 只在表达式开头和结尾添加括号,避免复杂计算
 | 
			
		
	
		
			
				
					|  |  |  |  |                     expression = "(" + expression + ")"; | 
			
		
	
		
			
				
					|  |  |  |  |                 } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |                 break; | 
			
		
	
		
			
				
					|  |  |  |  |             } while (true); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |             // 在表达式末尾添加等号
 | 
			
		
	
		
			
				
					|  |  |  |  |             return expression + " ="; | 
			
		
	
		
			
				
					|  |  |  |  |         } catch (Exception e) { | 
			
		
	
		
			
				
					|  |  |  |  |             // 如果生成题目出错,返回一个简单的默认题目
 | 
			
		
	
		
			
				
					|  |  |  |  |             return "10 + 20 ="; | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     /** | 
			
		
	
		
			
				
					|  |  |  |  |      * 计算部分表达式的值(简化版,只处理简单的加减乘除) | 
			
		
	
		
			
				
					|  |  |  |  |      */ | 
			
		
	
		
			
				
					|  |  |  |  |     private int calculatePartialExpression(String expression) { | 
			
		
	
		
			
				
					|  |  |  |  |         try { | 
			
		
	
		
			
				
					|  |  |  |  |             // 简单的表达式计算,只处理没有括号的情况
 | 
			
		
	
		
			
				
					|  |  |  |  |             String[] tokens = expression.split(" "); | 
			
		
	
		
			
				
					|  |  |  |  |             int result = Integer.parseInt(tokens[0]); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |             for (int i = 1; i < tokens.length; i += 2) { | 
			
		
	
		
			
				
					|  |  |  |  |                 String operator = tokens[i]; | 
			
		
	
		
			
				
					|  |  |  |  |                 int operand = Integer.parseInt(tokens[i+1]); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |                 switch (operator) { | 
			
		
	
		
			
				
					|  |  |  |  |                     case "+": | 
			
		
	
		
			
				
					|  |  |  |  |                         result += operand; | 
			
		
	
		
			
				
					|  |  |  |  |                         break; | 
			
		
	
		
			
				
					|  |  |  |  |                     case "-": | 
			
		
	
		
			
				
					|  |  |  |  |                         result -= operand; | 
			
		
	
		
			
				
					|  |  |  |  |                         break; | 
			
		
	
		
			
				
					|  |  |  |  |                     case "*": | 
			
		
	
		
			
				
					|  |  |  |  |                         result *= operand; | 
			
		
	
		
			
				
					|  |  |  |  |                         break; | 
			
		
	
		
			
				
					|  |  |  |  |                     case "/": | 
			
		
	
		
			
				
					|  |  |  |  |                         if (operand != 0) result /= operand; | 
			
		
	
		
			
				
					|  |  |  |  |                         break; | 
			
		
	
		
			
				
					|  |  |  |  |                 } | 
			
		
	
		
			
				
					|  |  |  |  |             } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |             return result; | 
			
		
	
		
			
				
					|  |  |  |  |         } catch (Exception e) { | 
			
		
	
		
			
				
					|  |  |  |  |             return 0; // 如果计算出错,返回0
 | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     /** | 
			
		
	
		
			
				
					|  |  |  |  |      * 评估表达式的结果(简化版) | 
			
		
	
		
			
				
					|  |  |  |  |      */ | 
			
		
	
		
			
				
					|  |  |  |  |     private double evaluateExpression(String expression) { | 
			
		
	
		
			
				
					|  |  |  |  |         try { | 
			
		
	
		
			
				
					|  |  |  |  |             // 移除括号(简化处理)
 | 
			
		
	
		
			
				
					|  |  |  |  |             String cleanExpression = expression.replace("(", "").replace(")", ""); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |             // 简单的表达式计算
 | 
			
		
	
		
			
				
					|  |  |  |  |             String[] tokens = cleanExpression.split(" "); | 
			
		
	
		
			
				
					|  |  |  |  |             double result = Double.parseDouble(tokens[0]); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |             for (int i = 1; i < tokens.length; i += 2) { | 
			
		
	
		
			
				
					|  |  |  |  |                 String operator = tokens[i]; | 
			
		
	
		
			
				
					|  |  |  |  |                 double operand = Double.parseDouble(tokens[i+1]); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |                 switch (operator) { | 
			
		
	
		
			
				
					|  |  |  |  |                     case "+": | 
			
		
	
		
			
				
					|  |  |  |  |                         result += operand; | 
			
		
	
		
			
				
					|  |  |  |  |                         break; | 
			
		
	
		
			
				
					|  |  |  |  |                     case "-": | 
			
		
	
		
			
				
					|  |  |  |  |                         result -= operand; | 
			
		
	
		
			
				
					|  |  |  |  |                         break; | 
			
		
	
		
			
				
					|  |  |  |  |                     case "*": | 
			
		
	
		
			
				
					|  |  |  |  |                         result *= operand; | 
			
		
	
		
			
				
					|  |  |  |  |                         break; | 
			
		
	
		
			
				
					|  |  |  |  |                     case "/": | 
			
		
	
		
			
				
					|  |  |  |  |                         if (operand != 0) result /= operand; | 
			
		
	
		
			
				
					|  |  |  |  |                         break; | 
			
		
	
		
			
				
					|  |  |  |  |                 } | 
			
		
	
		
			
				
					|  |  |  |  |             } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |             return result; | 
			
		
	
		
			
				
					|  |  |  |  |         } catch (Exception e) { | 
			
		
	
		
			
				
					|  |  |  |  |             return 0; // 如果计算出错,返回0
 | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | /** | 
			
		
	
		
			
				
					|  |  |  |  |  * 初中题目生成器 | 
			
		
	
		
			
				
					|  |  |  |  |  */ | 
			
		
	
		
			
				
					|  |  |  |  | class JuniorHighGenerator implements QuestionGenerator { | 
			
		
	
		
			
				
					|  |  |  |  |     private Random random = new Random(); | 
			
		
	
		
			
				
					|  |  |  |  |     private List<String> baseOperators = Arrays.asList("+", "-", "*", "/"); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     @Override | 
			
		
	
		
			
				
					|  |  |  |  |     public String generateQuestion() { | 
			
		
	
		
			
				
					|  |  |  |  |         try { | 
			
		
	
		
			
				
					|  |  |  |  |             // 确保每道题目最少有两个操作数(2-5个)
 | 
			
		
	
		
			
				
					|  |  |  |  |             int numOperands = random.nextInt(4) + 2; // 2-5个操作数
 | 
			
		
	
		
			
				
					|  |  |  |  |             StringBuilder expression = new StringBuilder(); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |             boolean hasSpecialOperator = false; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |             for (int i = 0; i < numOperands; i++) { | 
			
		
	
		
			
				
					|  |  |  |  |                 // 确保至少有一个特殊运算符
 | 
			
		
	
		
			
				
					|  |  |  |  |                 if (!hasSpecialOperator && (i == numOperands - 1 || random.nextDouble() < 0.3)) { | 
			
		
	
		
			
				
					|  |  |  |  |                     if (random.nextBoolean()) { | 
			
		
	
		
			
				
					|  |  |  |  |                         // 平方
 | 
			
		
	
		
			
				
					|  |  |  |  |                         int num = random.nextInt(10) + 1; // 平方的数不宜太大
 | 
			
		
	
		
			
				
					|  |  |  |  |                         expression.append(num).append("²"); | 
			
		
	
		
			
				
					|  |  |  |  |                     } else { | 
			
		
	
		
			
				
					|  |  |  |  |                         // 开根号
 | 
			
		
	
		
			
				
					|  |  |  |  |                         int num = random.nextInt(100) + 1; | 
			
		
	
		
			
				
					|  |  |  |  |                         expression.append("√").append(num); | 
			
		
	
		
			
				
					|  |  |  |  |                     } | 
			
		
	
		
			
				
					|  |  |  |  |                     hasSpecialOperator = true; | 
			
		
	
		
			
				
					|  |  |  |  |                 } else { | 
			
		
	
		
			
				
					|  |  |  |  |                     expression.append(random.nextInt(100) + 1); | 
			
		
	
		
			
				
					|  |  |  |  |                 } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |                 if (i < numOperands - 1) { | 
			
		
	
		
			
				
					|  |  |  |  |                     String operator = baseOperators.get(random.nextInt(baseOperators.size())); | 
			
		
	
		
			
				
					|  |  |  |  |                     expression.append(" ").append(operator).append(" "); | 
			
		
	
		
			
				
					|  |  |  |  |                 } | 
			
		
	
		
			
				
					|  |  |  |  |             } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |             // 如果还没有特殊运算符,强制添加一个
 | 
			
		
	
		
			
				
					|  |  |  |  |             if (!hasSpecialOperator) { | 
			
		
	
		
			
				
					|  |  |  |  |                 if (random.nextBoolean()) { | 
			
		
	
		
			
				
					|  |  |  |  |                     expression.insert(0, random.nextInt(10) + 1 + "² + "); | 
			
		
	
		
			
				
					|  |  |  |  |                 } else { | 
			
		
	
		
			
				
					|  |  |  |  |                     expression.insert(0, "√" + (random.nextInt(100) + 1) + " + "); | 
			
		
	
		
			
				
					|  |  |  |  |                 } | 
			
		
	
		
			
				
					|  |  |  |  |             } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |             // 在表达式末尾添加等号
 | 
			
		
	
		
			
				
					|  |  |  |  |             return expression.toString() + " ="; | 
			
		
	
		
			
				
					|  |  |  |  |         } catch (Exception e) { | 
			
		
	
		
			
				
					|  |  |  |  |             // 如果生成题目出错,返回一个简单的默认题目
 | 
			
		
	
		
			
				
					|  |  |  |  |             return "√25 + 10 ="; | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | /** | 
			
		
	
		
			
				
					|  |  |  |  |  * 高中题目生成器 | 
			
		
	
		
			
				
					|  |  |  |  |  */ | 
			
		
	
		
			
				
					|  |  |  |  | class SeniorHighGenerator implements QuestionGenerator { | 
			
		
	
		
			
				
					|  |  |  |  |     private Random random = new Random(); | 
			
		
	
		
			
				
					|  |  |  |  |     private List<String> baseOperators = Arrays.asList("+", "-", "*", "/"); | 
			
		
	
		
			
				
					|  |  |  |  |     private List<String> trigFunctions = Arrays.asList("sin", "cos", "tan"); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     @Override | 
			
		
	
		
			
				
					|  |  |  |  |     public String generateQuestion() { | 
			
		
	
		
			
				
					|  |  |  |  |         try { | 
			
		
	
		
			
				
					|  |  |  |  |             // 确保每道题目最少有两个操作数(2-5个)
 | 
			
		
	
		
			
				
					|  |  |  |  |             int numOperands = random.nextInt(4) + 2; // 2-5个操作数
 | 
			
		
	
		
			
				
					|  |  |  |  |             StringBuilder expression = new StringBuilder(); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |             boolean hasTrigFunction = false; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |             for (int i = 0; i < numOperands; i++) { | 
			
		
	
		
			
				
					|  |  |  |  |                 // 确保至少有一个三角函数
 | 
			
		
	
		
			
				
					|  |  |  |  |                 if (!hasTrigFunction && (i == numOperands - 1 || random.nextDouble() < 0.3)) { | 
			
		
	
		
			
				
					|  |  |  |  |                     String trigFunc = trigFunctions.get(random.nextInt(trigFunctions.size())); | 
			
		
	
		
			
				
					|  |  |  |  |                     int angle = random.nextInt(360); // 角度0-359
 | 
			
		
	
		
			
				
					|  |  |  |  |                     expression.append(trigFunc).append("(").append(angle).append("°)"); | 
			
		
	
		
			
				
					|  |  |  |  |                     hasTrigFunction = true; | 
			
		
	
		
			
				
					|  |  |  |  |                 } else { | 
			
		
	
		
			
				
					|  |  |  |  |                     expression.append(random.nextInt(100) + 1); | 
			
		
	
		
			
				
					|  |  |  |  |                 } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |                 if (i < numOperands - 1) { | 
			
		
	
		
			
				
					|  |  |  |  |                     String operator = baseOperators.get(random.nextInt(baseOperators.size())); | 
			
		
	
		
			
				
					|  |  |  |  |                     expression.append(" ").append(operator).append(" "); | 
			
		
	
		
			
				
					|  |  |  |  |                 } | 
			
		
	
		
			
				
					|  |  |  |  |             } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |             // 如果还没有三角函数,强制添加一个
 | 
			
		
	
		
			
				
					|  |  |  |  |             if (!hasTrigFunction) { | 
			
		
	
		
			
				
					|  |  |  |  |                 String trigFunc = trigFunctions.get(random.nextInt(trigFunctions.size())); | 
			
		
	
		
			
				
					|  |  |  |  |                 int angle = random.nextInt(360); | 
			
		
	
		
			
				
					|  |  |  |  |                 expression.insert(0, trigFunc + "(" + angle + "°) + "); | 
			
		
	
		
			
				
					|  |  |  |  |             } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |             // 在表达式末尾添加等号
 | 
			
		
	
		
			
				
					|  |  |  |  |             return expression.toString() + " ="; | 
			
		
	
		
			
				
					|  |  |  |  |         } catch (Exception e) { | 
			
		
	
		
			
				
					|  |  |  |  |             // 如果生成题目出错,返回一个简单的默认题目
 | 
			
		
	
		
			
				
					|  |  |  |  |             return "sin(30°) + 10 ="; | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | /** | 
			
		
	
		
			
				
					|  |  |  |  |  * 查重管理器 | 
			
		
	
		
			
				
					|  |  |  |  |  */ | 
			
		
	
		
			
				
					|  |  |  |  | class DuplicateChecker { | 
			
		
	
		
			
				
					|  |  |  |  |     private String username; | 
			
		
	
		
			
				
					|  |  |  |  |     private Set<String> historyQuestions; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     public DuplicateChecker(String username) { | 
			
		
	
		
			
				
					|  |  |  |  |         this.username = username; | 
			
		
	
		
			
				
					|  |  |  |  |         this.historyQuestions = new HashSet<>(); | 
			
		
	
		
			
				
					|  |  |  |  |         loadHistoryQuestions(); | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     private void loadHistoryQuestions() { | 
			
		
	
		
			
				
					|  |  |  |  |         File userFolder = new File("exams/" + username); | 
			
		
	
		
			
				
					|  |  |  |  |         if (!userFolder.exists() || !userFolder.isDirectory()) { | 
			
		
	
		
			
				
					|  |  |  |  |             userFolder.mkdirs(); | 
			
		
	
		
			
				
					|  |  |  |  |             return; | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         File[] files = userFolder.listFiles((dir, name) -> name.endsWith(".txt")); | 
			
		
	
		
			
				
					|  |  |  |  |         if (files == null) return; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         Pattern questionPattern = Pattern.compile("\\d+\\.\\s*(.+)"); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         for (File file : files) { | 
			
		
	
		
			
				
					|  |  |  |  |             try (BufferedReader reader = new BufferedReader(new FileReader(file))) { | 
			
		
	
		
			
				
					|  |  |  |  |                 String line; | 
			
		
	
		
			
				
					|  |  |  |  |                 while ((line = reader.readLine()) != null) { | 
			
		
	
		
			
				
					|  |  |  |  |                     Matcher matcher = questionPattern.matcher(line); | 
			
		
	
		
			
				
					|  |  |  |  |                     if (matcher.find()) { | 
			
		
	
		
			
				
					|  |  |  |  |                         String question = matcher.group(1).trim(); | 
			
		
	
		
			
				
					|  |  |  |  |                         historyQuestions.add(normalizeQuestion(question)); | 
			
		
	
		
			
				
					|  |  |  |  |                     } | 
			
		
	
		
			
				
					|  |  |  |  |                 } | 
			
		
	
		
			
				
					|  |  |  |  |             } catch (IOException e) { | 
			
		
	
		
			
				
					|  |  |  |  |                 System.out.println("读取历史文件出错: " + e.getMessage()); | 
			
		
	
		
			
				
					|  |  |  |  |             } | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     private String normalizeQuestion(String question) { | 
			
		
	
		
			
				
					|  |  |  |  |         // 移除多余空格和等号
 | 
			
		
	
		
			
				
					|  |  |  |  |         return question.replaceAll("\\s+", " ").replace(" =", "").trim(); | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     public boolean isDuplicate(String question) { | 
			
		
	
		
			
				
					|  |  |  |  |         // 移除等号后再进行比较
 | 
			
		
	
		
			
				
					|  |  |  |  |         String normalized = normalizeQuestion(question.replace(" =", "")); | 
			
		
	
		
			
				
					|  |  |  |  |         return historyQuestions.contains(normalized); | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     public void addQuestion(String question) { | 
			
		
	
		
			
				
					|  |  |  |  |         // 移除等号后再保存
 | 
			
		
	
		
			
				
					|  |  |  |  |         String normalized = normalizeQuestion(question.replace(" =", "")); | 
			
		
	
		
			
				
					|  |  |  |  |         historyQuestions.add(normalized); | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | /** | 
			
		
	
		
			
				
					|  |  |  |  |  * 文件保存器 | 
			
		
	
		
			
				
					|  |  |  |  |  */ | 
			
		
	
		
			
				
					|  |  |  |  | class FileSaver { | 
			
		
	
		
			
				
					|  |  |  |  |     private String username; | 
			
		
	
		
			
				
					|  |  |  |  |     private File userFolder; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     public FileSaver(String username) { | 
			
		
	
		
			
				
					|  |  |  |  |         this.username = username; | 
			
		
	
		
			
				
					|  |  |  |  |         this.userFolder = new File("exams/" + username); | 
			
		
	
		
			
				
					|  |  |  |  |         this.userFolder.mkdirs(); | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     public String saveExam(List<String> questions, String questionType) { | 
			
		
	
		
			
				
					|  |  |  |  |         SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss"); | 
			
		
	
		
			
				
					|  |  |  |  |         String timestamp = dateFormat.format(new Date()); | 
			
		
	
		
			
				
					|  |  |  |  |         String filename = timestamp + ".txt"; | 
			
		
	
		
			
				
					|  |  |  |  |         File file = new File(userFolder, filename); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         try (PrintWriter writer = new PrintWriter(new FileWriter(file))) { | 
			
		
	
		
			
				
					|  |  |  |  |             writer.println(questionType + "数学试卷"); | 
			
		
	
		
			
				
					|  |  |  |  |             writer.println("=============================="); | 
			
		
	
		
			
				
					|  |  |  |  |             writer.println(); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |             for (int i = 0; i < questions.size(); i++) { | 
			
		
	
		
			
				
					|  |  |  |  |                 writer.println((i + 1) + ". " + questions.get(i)); | 
			
		
	
		
			
				
					|  |  |  |  |                 writer.println(); | 
			
		
	
		
			
				
					|  |  |  |  |             } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |             return file.getAbsolutePath(); | 
			
		
	
		
			
				
					|  |  |  |  |         } catch (IOException e) { | 
			
		
	
		
			
				
					|  |  |  |  |             System.out.println("保存文件出错: " + e.getMessage()); | 
			
		
	
		
			
				
					|  |  |  |  |             return null; | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  | } |