|
|
package com.mathlearning.model;
|
|
|
|
|
|
import java.util.ArrayList;
|
|
|
import java.util.List;
|
|
|
|
|
|
public class PrimaryQuestionGenerator extends BaseQuestionGenerator {
|
|
|
|
|
|
@Override
|
|
|
public Question generateQuestion(int index) {
|
|
|
int operandCount = random.nextInt(4) + 2;
|
|
|
int[] operands = new int[operandCount];
|
|
|
int[] operations = new int[operandCount - 1];
|
|
|
|
|
|
String questionText;
|
|
|
double answer;
|
|
|
|
|
|
do {
|
|
|
generateOperands(operands, 1, 100);
|
|
|
generateOperations(operations, 4);
|
|
|
|
|
|
boolean useParentheses = random.nextDouble() < 0.3 && operandCount >= 3;
|
|
|
int[] parenthesesPositions = findParenthesesPositions(operations, useParentheses);
|
|
|
|
|
|
questionText = buildQuestionText(operands, operations,
|
|
|
parenthesesPositions[0], parenthesesPositions[1]);
|
|
|
answer = calculateAnswer(operands, operations,
|
|
|
parenthesesPositions[0], parenthesesPositions[1]);
|
|
|
|
|
|
} while (!isValidAnswer(answer));
|
|
|
|
|
|
return generateOptions(questionText, answer, "小学");
|
|
|
}
|
|
|
|
|
|
private int[] findParenthesesPositions(int[] operations, boolean useParentheses) {
|
|
|
int parenStart = -1;
|
|
|
int parenEnd = -1;
|
|
|
|
|
|
if (useParentheses) {
|
|
|
parenStart = findSuitableParenthesesPosition(operations);
|
|
|
if (parenStart != -1) {
|
|
|
parenEnd = parenStart + 1;
|
|
|
if (parenEnd < operations.length && random.nextBoolean()) {
|
|
|
parenEnd++;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
return new int[]{parenStart, parenEnd};
|
|
|
}
|
|
|
|
|
|
private int findSuitableParenthesesPosition(int[] operations) {
|
|
|
List<Integer> suitablePositions = new ArrayList<>();
|
|
|
|
|
|
for (int i = 0; i < operations.length; i++) {
|
|
|
if ((operations[i] == 0 || operations[i] == 1) && i > 0) {
|
|
|
suitablePositions.add(i);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
if (suitablePositions.isEmpty()) {
|
|
|
return operations.length > 1 ? random.nextInt(operations.length - 1) : -1;
|
|
|
}
|
|
|
|
|
|
return suitablePositions.get(random.nextInt(suitablePositions.size()));
|
|
|
}
|
|
|
|
|
|
private String buildQuestionText(int[] operands, int[] operations, int parenStart, int parenEnd) {
|
|
|
StringBuilder sb = new StringBuilder();
|
|
|
|
|
|
for (int i = 0; i < operands.length; i++) {
|
|
|
if (i == parenStart) sb.append("(");
|
|
|
sb.append(operands[i]);
|
|
|
if (i == parenEnd) sb.append(")");
|
|
|
if (i < operations.length) appendOperator(sb, operations[i]);
|
|
|
}
|
|
|
|
|
|
sb.append(" = ?");
|
|
|
return sb.toString();
|
|
|
}
|
|
|
|
|
|
private double calculateAnswer(int[] operands, int[] operations, int parenStart, int parenEnd) {
|
|
|
if (parenStart == -1 || parenEnd == -1) {
|
|
|
return calculateWithoutParentheses(operands, operations);
|
|
|
}
|
|
|
|
|
|
return calculateWithParentheses(operands, operations, parenStart, parenEnd);
|
|
|
}
|
|
|
|
|
|
private double calculateWithParentheses(int[] operands, int[] operations, int parenStart, int parenEnd) {
|
|
|
// 修改:使用Double列表
|
|
|
List<Double> numbers = new ArrayList<>();
|
|
|
List<Integer> ops = new ArrayList<>();
|
|
|
|
|
|
for (int operand : operands) numbers.add((double) operand);
|
|
|
for (int operation : operations) ops.add(operation);
|
|
|
|
|
|
double parenthesesResult = calculateParenthesesContent(numbers, ops, parenStart, parenEnd);
|
|
|
|
|
|
if (!isValidAnswer(parenthesesResult)) return -1;
|
|
|
|
|
|
replaceWithParenthesesResult(numbers, ops, parenStart, parenEnd, parenthesesResult);
|
|
|
// 修改:调用新的方法名
|
|
|
return calculateDoubleList(numbers, ops);
|
|
|
}
|
|
|
|
|
|
private double calculateParenthesesContent(List<Double> numbers, List<Integer> ops, int start, int end) {
|
|
|
List<Double> parenNumbers = new ArrayList<>();
|
|
|
List<Integer> parenOps = new ArrayList<>();
|
|
|
|
|
|
for (int i = start; i <= end; i++) parenNumbers.add(numbers.get(i));
|
|
|
for (int i = start; i < end; i++) parenOps.add(ops.get(i));
|
|
|
|
|
|
// 修改:调用新的方法名
|
|
|
return calculateDoubleList(parenNumbers, parenOps);
|
|
|
}
|
|
|
|
|
|
private void replaceWithParenthesesResult(List<Double> numbers, List<Integer> ops,
|
|
|
int start, int end, double result) {
|
|
|
int numCountToRemove = end - start + 1;
|
|
|
int opCountToRemove = end - start;
|
|
|
|
|
|
for (int i = 0; i < numCountToRemove; i++) numbers.remove(start);
|
|
|
for (int i = 0; i < opCountToRemove; i++) ops.remove(start);
|
|
|
|
|
|
// 修改:直接添加double结果,不转换为int
|
|
|
numbers.add(start, result);
|
|
|
}
|
|
|
|
|
|
// 修改:重命名方法,避免与父类冲突
|
|
|
private double calculateDoubleList(List<Double> numbers, List<Integer> ops) {
|
|
|
double[] doubleNumbers = new double[numbers.size()];
|
|
|
for (int i = 0; i < numbers.size(); i++) {
|
|
|
doubleNumbers[i] = numbers.get(i);
|
|
|
}
|
|
|
|
|
|
int[] intOps = new int[ops.size()];
|
|
|
for (int i = 0; i < ops.size(); i++) {
|
|
|
intOps[i] = ops.get(i);
|
|
|
}
|
|
|
|
|
|
return calculateExpression(doubleNumbers, intOps);
|
|
|
}
|
|
|
} |