From 2e052972617a13fb2ee34f0a49a71eff8e8f3184 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=99=88=E6=98=A0=E6=B1=9F?= <15547749+cyj-050209@user.noreply.gitee.com> Date: Sat, 11 Oct 2025 19:01:54 +0800 Subject: [PATCH] =?UTF-8?q?=E5=90=88=E5=B9=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ComputingUnit.java | 190 ++++++++++++++++++ .../MultipleChoiceGenerator.java | 90 +++++++++ .../MultipleChoiceGeneratorTest.java | 37 ++++ .../QuestionGenerator/PrimaryGenerator.java | 22 ++ .../QuestionGenerator/QuestionGenerator.java | 142 +++++++++++++ .../QuestionGenerator/highGenerator.java | 24 +++ .../QuestionGenerator/middleGenerator.java | 23 +++ 7 files changed, 528 insertions(+) create mode 100644 src/main/java/mathlearning/service/MultipleChoiceGenerator/ComputingUnit.java create mode 100644 src/main/java/mathlearning/service/MultipleChoiceGenerator/MultipleChoiceGenerator.java create mode 100644 src/main/java/mathlearning/service/MultipleChoiceGenerator/MultipleChoiceGeneratorTest.java create mode 100644 src/main/java/mathlearning/service/QuestionGenerator/PrimaryGenerator.java create mode 100644 src/main/java/mathlearning/service/QuestionGenerator/QuestionGenerator.java create mode 100644 src/main/java/mathlearning/service/QuestionGenerator/highGenerator.java create mode 100644 src/main/java/mathlearning/service/QuestionGenerator/middleGenerator.java diff --git a/src/main/java/mathlearning/service/MultipleChoiceGenerator/ComputingUnit.java b/src/main/java/mathlearning/service/MultipleChoiceGenerator/ComputingUnit.java new file mode 100644 index 0000000..33c4a37 --- /dev/null +++ b/src/main/java/mathlearning/service/MultipleChoiceGenerator/ComputingUnit.java @@ -0,0 +1,190 @@ + +package mathlearning.service.MultipleChoiceGenerator; + + +import java.util.ArrayList; +import java.util.List; +import java.util.Stack; + +public class ComputingUnit { + String expression; + Stack numbers = new Stack<>(); + Stack operators = new Stack<>(); + + ComputingUnit(String Question){ + expression = Question; + } + + private void SplitAndChange(){ + + String[] split = expression.split(" "); + split = separateParentheses(split); + for(int i = 0 ; i < split.length ; i++){ + if (split[i].charAt(0) == '√') { + String StrNum = split[i].substring(1); + double num = Math.sqrt(Double.parseDouble(StrNum)); + split[i] = String.valueOf(num); + } else if (split[i].charAt(split[i].length()-1) == '²') { + String StrNum = split[i].substring(0, split[i].length()-1); + double result = Math.pow(Double.parseDouble(StrNum), 2); + split[i] = String.valueOf(result); + } else if ((split[i].charAt(0) == 's' || split[i].charAt(0) == 'c' + || split[i].charAt(0) == 't' )) { + int index = split[i].indexOf(')'); + int index2 = split[i].indexOf('('); + String StrNum = split[i].substring(index2 + 1, index); + double num = Double.parseDouble(SquOrRoot(StrNum)); + double result = getFunc(split[i].charAt(0), num); + split[i] = String.valueOf(result); + } + } + this.expression = String.join(" ", split); + } + + public String[] separateParentheses(String[] originalArray) { + List result = new ArrayList<>(); + + for (String item : originalArray) { + if (item.startsWith("(") && item.length() > 1) { + // 如果字符串以(开头且长度大于1,分离出( + result.add("("); + result.add(item.substring(1).trim()); + } else if (item.endsWith(")") && item.length() > 1 && + (item.charAt(0) != 's' && item.charAt(0) != 'c' && item.charAt(0) != 't')) { + // 如果字符串以)结尾且长度大于1,分离出) + result.add(item.substring(0, item.length() - 1).trim()); + result.add(")"); + } else if ((item.charAt(0) == 's' || item.charAt(0) == 'c' || item.charAt(0) == 't') && + (item.endsWith(")") && item.charAt(item.length()-2) == ')')) { + result.add(item.substring(0, item.length() - 1).trim()); + result.add(")"); + } else { + // 其他情况保持不变 + result.add(item); + } + } + + return result.toArray(new String[0]); + } + + + private String SquOrRoot(String StrNum){ + if(StrNum.charAt(0) == '√'){ + return String.valueOf(Math.sqrt(Double.parseDouble(StrNum.substring(1)))); + } else if (StrNum.charAt(StrNum.length()-1) == '²') { + return String.valueOf(Math.pow(Double.parseDouble(StrNum.substring(0, StrNum.length()-1)), 2)); + }else { + return StrNum; + } + } + + private double getFunc(char func, double num){ + switch (func) { + case 's': + return Math.sin(num); + case 'c': + return Math.cos(num); + case 't': + return Math.tan(num); + default: + return 0; + } + } + + private void priority(String operator){ + if(operators.isEmpty() || operators.peek().equals("(")){ + operators.push(operator); + }else{ + if((operators.peek().equals("+")|| operators.peek().equals("-")) && + (operator.equals("×") || operator.equals("÷"))){ + operators.push(operator); + }else{ + CulAndPushOperator(operator); + } + } + } + + private void CulAndPushOperator(String operator){ + String num1 = numbers.pop(); + String num2 = numbers.pop(); + String operator1 = operators.pop(); + operators.push(operator); + String result = SingleCul(num2, operator1, num1); + numbers.push(result); + } + + private String Compute(){ + String[] spilt = expression.split(" "); + for (int i = 0; i < spilt.length; i++){ + if(spilt[i].equals("+") || spilt[i].equals("-") || + spilt[i].equals("×") || spilt[i].equals("÷") || + spilt[i].equals("(") ){//处理运算符 + if( spilt[i].equals("(")){ + operators.push(spilt[i]); + }else{ + priority(spilt[i]); + } + }else if(spilt[i].equals(")")){ + String tempResult = numbers.pop(); + while (!operators.peek().equals("(")){ + String operator = operators.pop(); + String num1 = numbers.pop(); + tempResult = SingleCul(num1, operator, tempResult); + } + if(operators.peek().equals("(")){ + operators.pop(); + } + numbers.push(tempResult); + } else { + numbers.push(spilt[i]); + } + } + return CulWithoutPriority(); + } + + private String CulWithoutPriority(){ + if(numbers.isEmpty()){ + return "0"; + } + String result = numbers.pop(); + while (!operators.isEmpty() && !numbers.isEmpty()){ + String num1 = numbers.pop(); + String operator = operators.pop(); + result = SingleCul(num1, operator, result); + } + return result; + } + + public String getAnswer(){ + SplitAndChange(); + return Compute(); + } + + private String SingleCul(String nowResult, String operator, String num){ + // 使用 trim() 去除首尾空格 + // 使用 split("\\s+") 按空格分割,只取第一个元素(数字) + String cleanNowResult = nowResult.trim().split("\\s+")[0]; + String cleanNum = num.trim().split("\\s+")[0]; + + // 现在可以安全地解析数字了 + Double result = Double.parseDouble(cleanNowResult); + switch (operator) { + case "+": + result += Double.parseDouble(cleanNum); + break; + case "-": + result -= Double.parseDouble(cleanNum); + break; + case "×": + result *= Double.parseDouble(cleanNum); + break; + case "÷": + result /= Double.parseDouble(cleanNum); + break; + } + return String.valueOf(result); + } + + +} + diff --git a/src/main/java/mathlearning/service/MultipleChoiceGenerator/MultipleChoiceGenerator.java b/src/main/java/mathlearning/service/MultipleChoiceGenerator/MultipleChoiceGenerator.java new file mode 100644 index 0000000..54f729a --- /dev/null +++ b/src/main/java/mathlearning/service/MultipleChoiceGenerator/MultipleChoiceGenerator.java @@ -0,0 +1,90 @@ +package mathlearning.service.MultipleChoiceGenerator; +import mathlearning.model.User; +import mathlearning.service.QuestionGenerator.*; + +import java.util.*; + +public class MultipleChoiceGenerator { + private static QuestionGenerator QuestionGenerator = new PrimaryGenerator(); + String[] QuestionList ; + String[] AnswerList ; + String[] ChoiceList ; + + MultipleChoiceGenerator(int count, User nowUser){// 如此声明MultipleChoiceGenerator实例,再调用下面三个接口 + this.QuestionList = new String[count]; + this.ChoiceList = new String[count]; + this.QuestionList = SetQuestionList(count, nowUser); + SetChoiceList(); + } + + public String[] GetQuestionList(){ + return this.QuestionList; + } + + public String[] GetChoiceList(){ + return this.ChoiceList; + } + + public String[] GetAnswerList(){ + return this.AnswerList; + } + + private void SetChoiceList(){ + for(int i = 0 ; i < this.AnswerList.length ; i++){ + Random random = new Random(); + String[] choices = new String[4]; + double correctChoice = Double.parseDouble(this.AnswerList[i]); + int position = random.nextInt(4); + choices[position] = String.format("%.2f", correctChoice); + + for(int j = 0 ; j < 4 ; j++){ + if(j != position){ + double choice = correctChoice; + double offset = random.nextInt(41) - 20; + choice += offset; + choices[j] = String.format("%.2f", choice); + } + } + + this.ChoiceList[i] = String.join("\n", choices); + } + } + + private String[] SetQuestionList(int count, User nowUser){ + String[] Questions= new String[count]; + if(nowUser.getType().equals("小学") ) { + QuestionGenerator = new PrimaryGenerator(); + } + else if( nowUser.getType().equals("初中") ) { + QuestionGenerator = new middleGenerator(); + } + else if( nowUser.getType().equals("高中") ) { + QuestionGenerator = new highGenerator(); + } + + List questions = new ArrayList<>(); + Set generatedQuestions = new HashSet<>(); + + for (int i = 0; i < count; i++) { + String question; + do { + question = QuestionGenerator.generateQuestion(); + } while ( generatedQuestions.contains(question )); + generatedQuestions.add(question); + questions.add(question); + } + + for(int i = 0 ; i< count ; i++){ + Questions[i] = questions.get(i); + } + this.AnswerList = new String[count]; + for(int i = 0 ; i< count ; i++){ + ComputingUnit computingUnit = new ComputingUnit(Questions[i]); + this.AnswerList[i] = computingUnit.getAnswer(); + } + return Questions; + } + + + +} diff --git a/src/main/java/mathlearning/service/MultipleChoiceGenerator/MultipleChoiceGeneratorTest.java b/src/main/java/mathlearning/service/MultipleChoiceGenerator/MultipleChoiceGeneratorTest.java new file mode 100644 index 0000000..260dd42 --- /dev/null +++ b/src/main/java/mathlearning/service/MultipleChoiceGenerator/MultipleChoiceGeneratorTest.java @@ -0,0 +1,37 @@ +package mathlearning.service.MultipleChoiceGenerator; + +import mathlearning.model.User; + +public class MultipleChoiceGeneratorTest { + public static void main(String[] args) { + // 创建一个模拟用户 + User testUser = new User(); + testUser.setType("小学"); // 可以分别测试"小学"、"初中"、"高中" + + // 测试生成10道题目 + int questionCount = 10; + MultipleChoiceGenerator generator = new MultipleChoiceGenerator(questionCount, testUser); + + // 获取生成的题目、答案和选项 + String[] questions = generator.GetQuestionList(); + String[] answers = generator.GetAnswerList(); + String[] choices = generator.GetChoiceList(); + + // 输出测试结果 + System.out.println("=== 数学题目生成测试 ==="); + System.out.println("用户类型: " + testUser.getType()); + System.out.println("生成题目数量: " + questionCount); + System.out.println(); + + for (int i = 0; i < questions.length; i++) { + System.out.println("题目 " + (i + 1) + ": " + questions[i]); + System.out.println("答案: " + answers[i]); + System.out.println("选项:"); + String[] choiceArray = choices[i].split("\n"); + for (int j = 0; j < choiceArray.length; j++) { + System.out.println(" " + (char)('A' + j) + ". " + choiceArray[j]); + } + System.out.println("----------------------------------------"); + } + } +} diff --git a/src/main/java/mathlearning/service/QuestionGenerator/PrimaryGenerator.java b/src/main/java/mathlearning/service/QuestionGenerator/PrimaryGenerator.java new file mode 100644 index 0000000..d4f73fc --- /dev/null +++ b/src/main/java/mathlearning/service/QuestionGenerator/PrimaryGenerator.java @@ -0,0 +1,22 @@ +package mathlearning.service.QuestionGenerator; + +public class PrimaryGenerator extends QuestionGenerator{ + public PrimaryGenerator() { + super("小学"); + } + + @Override + public String generateQuestion() { + + int operandCount = random.nextInt(4) + 2; + + // 生成操作数 + int[] operands = new int[operandCount]; + for (int i = 0; i < operandCount; i++) { + operands[i] = random.nextInt(100) + 1; // 1-100 + } + + String question = preForOper(operands); + return addParen(question); + } +} diff --git a/src/main/java/mathlearning/service/QuestionGenerator/QuestionGenerator.java b/src/main/java/mathlearning/service/QuestionGenerator/QuestionGenerator.java new file mode 100644 index 0000000..b41d315 --- /dev/null +++ b/src/main/java/mathlearning/service/QuestionGenerator/QuestionGenerator.java @@ -0,0 +1,142 @@ +package mathlearning.service.QuestionGenerator; + +import java.util.Random; + +public abstract class QuestionGenerator{ + protected Random random = new Random(); + public abstract String generateQuestion() ; + protected String type; + + public String getType() { + return type; + } + + QuestionGenerator() { + type = "无"; + } + + QuestionGenerator(String Type) { + type = Type; + } + + protected String preForOper(int[] operands) { + StringBuilder question = new StringBuilder(); + String[] operators = {"+", "-", "×", "÷"}; + question.append(operands[0]); + + for (int i = 1; i < operands.length; i++) { + String op = operators[ random.nextInt (operators.length)]; + question.append(" ").append(op).append(" ").append(operands[i]); + } + return question.toString(); + + } + + protected boolean Check_num(String expression) { + if(!(expression.equals("+") || expression.equals("-") || expression.equals("×") || expression.equals("÷"))) { + return true; + } + else{ + return false; + } + } + + protected String addParen(String expression) { + String[] parts = expression.split(" "); + StringBuilder result = new StringBuilder(); + boolean r_paren_needed = false; + + for (int i = 0; i < parts.length; i++) { + if(Check_num ( parts [i]) ) { + if( !r_paren_needed ) { + if(i <= parts.length -3 ) + { + if( random.nextBoolean() ) + { result.append("(");r_paren_needed = true;} + } + result.append(parts[i]); + } else { + result.append( parts [i]); + if( !random.nextBoolean()) { + result.append(")");r_paren_needed = false; + } + } + } else { + result.append( parts [i] ); + } + if( i < parts.length -1 ) { + result.append(" "); + } + } + + if( r_paren_needed ){ + result.append(")");r_paren_needed = false; + } + return result.toString(); + } + + protected String add_squs(String expression) { + String[] parts = expression.split(" "); + StringBuilder result = new StringBuilder(); + boolean has_squs = false; + + for (int i = 0; i < parts.length; i++) { + if( Check_num( parts [i] )) { + double Thres = 0.3; + if( !has_squs){ + Thres = 0.7; + } + if ( random.nextDouble() < Thres ||(i == parts.length -1 && !has_squs)) { + if ( random.nextBoolean() ) { + result.append(parts[i]); + result.append("²"); + has_squs = true; + } else { + result.append("√"); + result.append(parts[i]); + has_squs = true; + } + } else { + result.append(parts[i]); + } + } else { + result.append(parts[i]); + } + if( i < parts.length -1 ) { + result.append(" "); + } + } + return result.toString(); + } + + protected String add_sins(String expression) { + String[] parts = expression.split(" "); + StringBuilder result = new StringBuilder(); + String[] functions = {"sin", "cos", "tan"}; + boolean has_func = false; + + for (int i = 0; i < parts.length; i++) { + double Thres = 0.4; + if(!has_func){Thres = 0.8;} + if(Check_num(parts[i])) + { + if ( random.nextDouble() < Thres ||(i == parts.length-1 && !has_func) ) { + String func = functions[random.nextInt(functions.length)]; + result.append(func).append("(").append(parts[i]).append(")"); + } else { + result.append(parts[i]); + } + } else { + result.append(parts[i]); + } + if( i < parts.length-1 ) { + result.append(" "); + } + + } + + return result.toString(); + } +} + + diff --git a/src/main/java/mathlearning/service/QuestionGenerator/highGenerator.java b/src/main/java/mathlearning/service/QuestionGenerator/highGenerator.java new file mode 100644 index 0000000..bfc17fc --- /dev/null +++ b/src/main/java/mathlearning/service/QuestionGenerator/highGenerator.java @@ -0,0 +1,24 @@ +package mathlearning.service.QuestionGenerator; + +public class highGenerator extends QuestionGenerator{ + + public highGenerator() { + super("高中"); + } + + @Override + public String generateQuestion() { + int operandCount = random.nextInt(4) + 2; + + // 生成操作数 + int[] operands = new int[ operandCount ]; + for (int i = 0; i < operandCount; i++) { + operands[i] = random.nextInt(100) + 1; // 1-100 + } + + String question = preForOper( operands ); + question = add_squs( question ); + question = add_sins( question ); + return addParen( question ); + } +} diff --git a/src/main/java/mathlearning/service/QuestionGenerator/middleGenerator.java b/src/main/java/mathlearning/service/QuestionGenerator/middleGenerator.java new file mode 100644 index 0000000..b1d3b61 --- /dev/null +++ b/src/main/java/mathlearning/service/QuestionGenerator/middleGenerator.java @@ -0,0 +1,23 @@ +package mathlearning.service.QuestionGenerator; + +public class middleGenerator extends QuestionGenerator{ + + public middleGenerator() { + super("初中"); + } + + @Override + public String generateQuestion() { + int operandCount = random.nextInt(4) + 2; + + // 生成操作数 + int[] operands = new int [ operandCount ]; + for (int i = 0; i < operandCount; i++) { + operands[i] = random.nextInt(100) + 1; // 1-100 + } + + String question = preForOper(operands); + question = add_squs(question); + return addParen(question); + } +} \ No newline at end of file