diff --git a/src/mathpuzzle/controller/StartController.java b/src/mathpuzzle/controller/StartController.java index e9a0b09..e915f7e 100644 --- a/src/mathpuzzle/controller/StartController.java +++ b/src/mathpuzzle/controller/StartController.java @@ -1,12 +1,21 @@ package mathpuzzle.controller; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.List; import java.util.Scanner; import mathpuzzle.entity.User; +import mathpuzzle.service.*; import mathpuzzle.system.LogSystem; public class StartController { + private LogSystem logSystem = new LogSystem(); + private QuestionDeduplicator deduplicator = new QuestionDeduplicator(); + private FileHandler fileHandler = new FileHandler(); + //private BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)); public void start() { - LogSystem logSystem = new LogSystem(); + logSystem.userHashMapInit(); Scanner scanner = new Scanner(System.in); while (true) { @@ -27,14 +36,13 @@ public class StartController { System.out.println("题目数量必须在10-30之间!"); continue; } - //handleQuestionGeneration(user, count); + handleQuestionGeneration(user, count); } catch (NumberFormatException e) { handleLevelSwitch(user, input); + } catch (IOException e) { + throw new RuntimeException(e); } - - } - } } private void handleLevelSwitch(User user, String input) { @@ -47,8 +55,42 @@ public class StartController { } } else { System.out.println("无效输入。请输入题目数量或'切换为 XX'指令。"); + } + } + private void handleQuestionGeneration(User user, int count) throws IOException { + // 根据用户级别创建生成器 + QuestionGenerator generator = createGenerator(user.getLevel()); + if (generator == null) { + System.out.println("不支持的题目类型: " + user.getLevel()); + return; + } + + // 加载历史题目用于查重 + deduplicator.loadExistingQuestions(user); + + // 生成题目 + List questions = generator.generateQuestions(count); + // 显示题目 + for (int i = 0; i < questions.size(); i++) { + System.out.println((i + 1) + ". " + questions.get(i)); + } + + // 保存到文件 + fileHandler.savePaper(user, questions); + System.out.println("试卷已成功保存!"); + } + private QuestionGenerator createGenerator(String level) { + switch (level) { + case "小学": + return new PrimarySchoolGenerator(); + case "初中": + return new JuniorHighGenerator(); + case "高中": + return new SeniorHighGenerator(); + default: + return null; } } } diff --git a/src/mathpuzzle/entity/User.java b/src/mathpuzzle/entity/User.java index 44f23e8..403fafd 100644 --- a/src/mathpuzzle/entity/User.java +++ b/src/mathpuzzle/entity/User.java @@ -18,7 +18,6 @@ public class User { public String getLevel() { return level; } - public void setLevel(String newLevel) { level = newLevel; } diff --git a/src/mathpuzzle/service/FileHandler.java b/src/mathpuzzle/service/FileHandler.java new file mode 100644 index 0000000..c9f5fe2 --- /dev/null +++ b/src/mathpuzzle/service/FileHandler.java @@ -0,0 +1,42 @@ +package mathpuzzle.service; +import mathpuzzle.entity.User; +import java.io.BufferedWriter; +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.List; + +/** + * 文件处理器 + * 负责创建用户目录和保存试卷文件 + */ +public class FileHandler { + + public void ensureUserDirectory(User user) throws IOException { + String dirPath = "./" + user.getName(); + Path path = Paths.get(dirPath); + if (!Files.exists(path)) { + Files.createDirectories(path); + } + } + + public void savePaper(User user, List questions) throws IOException { + ensureUserDirectory(user); + // 生成文件名:年-月-日-时-分-秒.txt + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd-HH-mm-ss"); + String fileName = LocalDateTime.now().format(formatter) + ".txt"; + String filePath = "./" + user.getName() + "/" + fileName; + + try (BufferedWriter writer = new BufferedWriter(new FileWriter(filePath))) { + for (int i = 0; i < questions.size(); i++) { + writer.write((i + 1) + ". " + questions.get(i)); // 添加题号 + writer.newLine(); + writer.newLine(); // 每题之间空一行 + } + } + } +} diff --git a/src/mathpuzzle/service/JuniorHighGenerator.java b/src/mathpuzzle/service/JuniorHighGenerator.java new file mode 100644 index 0000000..4e3bc59 --- /dev/null +++ b/src/mathpuzzle/service/JuniorHighGenerator.java @@ -0,0 +1,45 @@ +package mathpuzzle.service; +import java.util.*; + +/** + * 初中题目生成器 + * 题目必须包含至少一个平方或开根号运算符 + */ +public class JuniorHighGenerator implements QuestionGenerator { + private static final String[] ADVANCED_OPS = {"平方", "开根号"}; + private Random random = new Random(); + + @Override + public List generateQuestions(int count) { + List questions = new ArrayList<>(); + for (int i = 0; i < count; i++) { + String question = generateSingleQuestion(); + questions.add(question); + } + return questions; + } + + private String generateSingleQuestion() { + StringBuilder sb = new StringBuilder(); + int baseNum = random.nextInt(100) + 1; + sb.append(baseNum); + + // 强制加入一个高级运算符 + String advancedOp = ADVANCED_OPS[random.nextInt(ADVANCED_OPS.length)]; + if ("平方".equals(advancedOp)) { + sb.append(" ").append(advancedOp); + } else { // 开根号 + sb.insert(0, advancedOp + "(").append(")"); + } + + // 可能再附加一个基础运算 + if (random.nextBoolean()) { + String[] basicOps = {"+", "-", "*", "/"}; + String op = basicOps[random.nextInt(basicOps.length)]; + int anotherNum = random.nextInt(100) + 1; + sb.append(" ").append(op).append(" ").append(anotherNum); + } + + return sb.toString() + " ="; + } +} diff --git a/src/mathpuzzle/service/PrimarySchoolGenerator.java b/src/mathpuzzle/service/PrimarySchoolGenerator.java new file mode 100644 index 0000000..92fd757 --- /dev/null +++ b/src/mathpuzzle/service/PrimarySchoolGenerator.java @@ -0,0 +1,70 @@ +package mathpuzzle.service; +import java.util.*; + +/** + * 小学题目生成器 + * 题目仅包含 +, -, *, / 和 () + */ +public class PrimarySchoolGenerator implements QuestionGenerator { + private static final String[] OPERATORS = {"+", "-", "*", "/"}; + private Random random = new Random(); + + @Override + public List generateQuestions(int count) { + List questions = new ArrayList<>(); + for (int i = 0; i < count; i++) { + String question = generateSingleQuestion(); + questions.add(question); + } + return questions; + } + private String generateSingleQuestion() { + int operandCount = random.nextInt(4) + 2; // 2-5个操作数 + List parts = new ArrayList<>(); + + for (int i = 0; i < operandCount; i++) { + int num = random.nextInt(100) + 1; + parts.add(String.valueOf(num)); + if (i < operandCount - 1) { + parts.add(OPERATORS[random.nextInt(OPERATORS.length)]); + } + } + + // 简单添加括号逻辑:随机加一个括号 + if (operandCount > 2 && random.nextBoolean()) { + // 遍历查找左括号的合理位置 + for(int i = 0; i < parts.size() - 2; i++) { + // 该位置要为操作数且随机添加括号 + if (isNumeric(parts.get(i)) && random.nextBoolean()) { + parts.set(i, "(" + parts.get(i)); + // 为避免随机数上限出现0,此处要单独判断一下左括号正好括住倒数第二个操作数的情况 + if (i == parts.size() - 3) { + parts.set(parts.size() - 1, parts.get(parts.size() - 1) + ")"); + } else { + while(true) { + int i2 = random.nextInt(parts.size() - 3 - i) + 2; + if(isNumeric(parts.get(i + i2))) { + parts.set(i + i2, parts.get(i + i2) + ")"); + break; + } + } + } + break; + } + } + } + return String.join(" ", parts) + " ="; + } + + public static boolean isNumeric(String str) { + if (str == null || str.isEmpty()) { + return false; + } + try { + Double.parseDouble(str); + return true; + } catch (NumberFormatException e) { + return false; + } + } +} \ No newline at end of file diff --git a/src/mathpuzzle/service/QuestionDeduplicator.java b/src/mathpuzzle/service/QuestionDeduplicator.java new file mode 100644 index 0000000..c2e1fe1 --- /dev/null +++ b/src/mathpuzzle/service/QuestionDeduplicator.java @@ -0,0 +1,53 @@ +package mathpuzzle.service; + +import mathpuzzle.entity.User; + +import java.io.*; +import java.util.HashSet; +import java.util.Set; + +/** + * 题目查重器 + * 负责加载历史题目并检查新题目是否重复 + */ +public class QuestionDeduplicator { + private Set existingQuestions = new HashSet<>(); + + public void loadExistingQuestions(User user) { + existingQuestions.clear(); + String userDir = "./" + user.getName(); + File dir = new File(userDir); + + if (!dir.exists()) { + return; // 目录不存在,无历史题目 + } + + File[] files = dir.listFiles((d, name) -> name.endsWith(".txt")); + if (files == null) return; + + for (File file : files) { + try (BufferedReader br = new BufferedReader(new FileReader(file))) { + String line; + while ((line = br.readLine()) != null) { + // 只加载题目行,忽略题号和空行 + if (line.trim().isEmpty() || line.matches("\\d+\\. .*")) { + String questionContent = line.replaceFirst("\\d+\\. ", "").trim(); + if (!questionContent.isEmpty() && !questionContent.equals("=")) { + existingQuestions.add(questionContent); + } + } + } + } catch (IOException e) { + System.err.println("读取历史文件时出错: " + file.getName()); + } + } + } + + public boolean isDuplicate(String question) { + return existingQuestions.contains(question); + } + + public void addQuestion(String question) { + existingQuestions.add(question); + } +} diff --git a/src/mathpuzzle/service/QuestionGenerator.java b/src/mathpuzzle/service/QuestionGenerator.java new file mode 100644 index 0000000..8660559 --- /dev/null +++ b/src/mathpuzzle/service/QuestionGenerator.java @@ -0,0 +1,6 @@ +package mathpuzzle.service; +import java.util.List; + +public interface QuestionGenerator { + List generateQuestions(int count); +} diff --git a/src/mathpuzzle/service/SeniorHighGenerator.java b/src/mathpuzzle/service/SeniorHighGenerator.java new file mode 100644 index 0000000..3fde521 --- /dev/null +++ b/src/mathpuzzle/service/SeniorHighGenerator.java @@ -0,0 +1,39 @@ +package mathpuzzle.service; +import java.util.*; + +/** + * 高中题目生成器 + * 题目必须包含至少一个 sin, cos, tan 三角函数运算符 + */ +public class SeniorHighGenerator implements QuestionGenerator { + private static final String[] TRIG_FUNCS = {"sin", "cos", "tan"}; + private Random random = new Random(); + + @Override + public List generateQuestions(int count) { + List questions = new ArrayList<>(); + for (int i = 0; i < count; i++) { + String question = generateSingleQuestion(); + questions.add(question); + } + return questions; + } + + private String generateSingleQuestion() { + StringBuilder sb = new StringBuilder(); + String trigFunc = TRIG_FUNCS[random.nextInt(TRIG_FUNCS.length)]; + int angle = random.nextInt(360); // 角度0-359度 + + sb.append(trigFunc).append("(").append(angle).append("°)"); + + // 可能再附加一个基础运算 + if (random.nextBoolean()) { + String[] basicOps = {"+", "-", "*", "/"}; + String op = basicOps[random.nextInt(basicOps.length)]; + int anotherNum = random.nextInt(100) + 1; + sb.append(" ").append(op).append(" ").append(anotherNum); + } + + return sb.toString() + " ="; + } +}