diff --git a/src/main/java/com/example/myapp/service/HighQueSeting.java b/src/main/java/com/example/myapp/service/HighQueSeting.java new file mode 100644 index 0000000..a8b9a9e --- /dev/null +++ b/src/main/java/com/example/myapp/service/HighQueSeting.java @@ -0,0 +1,139 @@ +// HighQueSeting.java +package com.example.myapp.service; + +import com.example.myapp.model.Expression; + +public class HighQueSeting extends AbstractQuestionSeting { + + @Override + public String addParenthesesIfNeeded(Expression child, String parentOp, boolean isRightChild) { + if (child.mainOperator == null + || child.mainOperator.equals("²") || child.mainOperator.equals("√") + || child.mainOperator.equals("sin") || child.mainOperator.equals("cos") + || child.mainOperator.equals("tan")) { + return child.expression; + } + + int parentPriority = getPriority(parentOp); + int childPriority = getPriority(child.mainOperator); + + if (childPriority < parentPriority) { + return "(" + child.expression + ")"; + } + + if (isRightChild && (parentOp.equals("-") || parentOp.equals("/"))) { + if (parentPriority == childPriority) { + return "(" + child.expression + ")"; + } + } + + return child.expression; + } + + public Expression applyUnary(Expression child, String op) { + switch (op) { + case "²": + if (child.mainOperator == null) { + return new Expression(child.expression + "²", child.value * child.value, "²"); + } + return new Expression("(" + child.expression + ")²", child.value * child.value, "²"); + case "√": + String numStr = getNumberForSqrt(); + child = new Expression(numStr, parseNumber(numStr), null); + + double sqrtValue = Math.sqrt(child.value); + if (child.mainOperator == null) { + return new Expression("√" + child.expression, sqrtValue, "√"); + } + return new Expression("√(" + child.expression + ")", sqrtValue, "√"); + case "sin": + int[] sinAngles = {0, 30, 45, 60, 90, 120, 135, 150, 180}; + int sinAngle = sinAngles[rand.nextInt(sinAngles.length)]; + child = new Expression(String.valueOf(sinAngle), sinAngle, null); + return new Expression("sin(" + child.expression + "°)", + Math.sin(Math.toRadians(child.value)), "sin"); + case "cos": + int[] cosAngles = {0, 30, 45, 60, 90, 120, 135, 150, 180}; + int cosAngle = cosAngles[rand.nextInt(cosAngles.length)]; + child = new Expression(String.valueOf(cosAngle), cosAngle, null); + return new Expression("cos(" + child.expression + "°)", + Math.cos(Math.toRadians(child.value)), "cos"); + case "tan": + int[] tanAngles = {0, 30, 45, 60, 120, 135, 150, 180}; + int tanAngle = tanAngles[rand.nextInt(tanAngles.length)]; + child = new Expression(String.valueOf(tanAngle), tanAngle, null); + double tanValue = Math.tan(Math.toRadians(child.value)); + if (Math.abs(tanValue) > 1000) { + tanValue = tanValue > 0 ? 1000 : -1000; + } + return new Expression("tan(" + child.expression + "°)", tanValue, "tan"); + default: + return child; + } + } + + @Override + public Expression setQuestion(int count) { + Expression result = firstSetQuestion(count); + // 确保高中题目包含至少一个三角函数 + int attempts = 0; + while (!result.expression.contains("sin") && !result.expression.contains("cos") + && !result.expression.contains("tan") && attempts < 10) { + result = firstSetQuestion(count); + attempts++; + } + return result; + } + + public Expression probability(Expression result) { + // 高中阶段:40%概率添加一元运算 + if (rand.nextDouble() < 0.4) { + String[] unaryOps = {"²", "√", "sin", "cos", "tan"}; + String unaryOp = unaryOps[rand.nextInt(unaryOps.length)]; + result = applyUnary(result, unaryOp); + result.mainOperator = unaryOp; + } + return result; + } + + public Expression firstSetQuestion(int count) { + if (count == 1) { + String numStr = getRandomNumber(); + Expression expr = new Expression(numStr, parseNumber(numStr), null); + expr = probability(expr); + return expr; + } + int leftCount = 1 + rand.nextInt(count - 1); + int rightCount = count - leftCount; + + Expression left = firstSetQuestion(leftCount); + Expression right = firstSetQuestion(rightCount); + + String op = getRandomOperator(); + double value = 0; + switch (op) { + case "+": + value = left.value + right.value; + break; + case "-": + value = left.value - right.value; + break; + case "*": + value = left.value * right.value; + break; + case "/": + if (Math.abs(right.value) < 1e-10) { + return firstSetQuestion(count); + } + value = left.value / right.value; + break; + } + + String leftExpr = addParenthesesIfNeeded(left, op, false); + String rightExpr = addParenthesesIfNeeded(right, op, true); + + Expression result = new Expression(leftExpr + " " + op + " " + rightExpr, value, op); + result = probability(result); + return result; + } +} \ No newline at end of file