|
|
|
|
@ -0,0 +1,201 @@
|
|
|
|
|
import java.util.HashSet;
|
|
|
|
|
import java.util.Random;
|
|
|
|
|
import java.util.Set;
|
|
|
|
|
import java.io.File;
|
|
|
|
|
import java.io.IOException;
|
|
|
|
|
import java.nio.file.Files;
|
|
|
|
|
import java.nio.file.Paths;
|
|
|
|
|
|
|
|
|
|
public class QuestionGenerator {private Random random = new Random();
|
|
|
|
|
private Set<String> generatedQuestions = new HashSet<>();
|
|
|
|
|
private Set<String> userHistoryQuestions = new HashSet<>(); // 新增:用户历史题目
|
|
|
|
|
|
|
|
|
|
// 新增方法:加载用户历史题目
|
|
|
|
|
public void loadUserHistory(String username) {
|
|
|
|
|
userHistoryQuestions.clear();
|
|
|
|
|
String folderPath = "papers/" + username + "/";
|
|
|
|
|
File folder = new File(folderPath);
|
|
|
|
|
if (!folder.exists()) return;
|
|
|
|
|
|
|
|
|
|
File[] files = folder.listFiles((dir, name) -> name.endsWith(".txt"));
|
|
|
|
|
if (files == null) return;
|
|
|
|
|
|
|
|
|
|
for (File file : files) {
|
|
|
|
|
try {
|
|
|
|
|
String content = new String(Files.readAllBytes(Paths.get(file.getPath())));
|
|
|
|
|
// 提取题目(每行一个题目,格式如:1. 题目内容)
|
|
|
|
|
String[] lines = content.split("\n");
|
|
|
|
|
for (String line : lines) {
|
|
|
|
|
if (line.matches("^\\d+\\.\\s+.+")) {
|
|
|
|
|
String question = line.substring(line.indexOf(".") + 1).trim();
|
|
|
|
|
userHistoryQuestions.add(question);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} catch (IOException e) {
|
|
|
|
|
System.out.println("读取历史文件失败: " + file.getName());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public String generateQuestion(DifficultyLevel level) {
|
|
|
|
|
String question;
|
|
|
|
|
int attempt = 0;
|
|
|
|
|
do {
|
|
|
|
|
question = generateSingleQuestion(level);
|
|
|
|
|
attempt++;
|
|
|
|
|
if (attempt > 100) {
|
|
|
|
|
throw new RuntimeException("无法生成不重复的题目,请清除历史记录");
|
|
|
|
|
}
|
|
|
|
|
} while (generatedQuestions.contains(question) || userHistoryQuestions.contains(question)); // 修改:同时检查历史题目
|
|
|
|
|
|
|
|
|
|
generatedQuestions.add(question);
|
|
|
|
|
return question;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private String generateSingleQuestion(DifficultyLevel level) {
|
|
|
|
|
int operandCount = random.nextInt(3) + 2; // 2-4个操作数
|
|
|
|
|
StringBuilder question = new StringBuilder();
|
|
|
|
|
|
|
|
|
|
switch (level) {
|
|
|
|
|
case PRIMARY:
|
|
|
|
|
question.append(generatePrimaryQuestion(operandCount));
|
|
|
|
|
break;
|
|
|
|
|
case JUNIOR:
|
|
|
|
|
question.append(generateJuniorQuestion(operandCount));
|
|
|
|
|
break;
|
|
|
|
|
case SENIOR:
|
|
|
|
|
question.append(generateSeniorQuestion(operandCount));
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return question.toString();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private String generatePrimaryQuestion(int operandCount) {
|
|
|
|
|
String[] operators = {"+", "-", "*", "/"};
|
|
|
|
|
return generateBasicQuestion(operandCount, operators, false);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private String generateJuniorQuestion(int operandCount) {
|
|
|
|
|
String question;
|
|
|
|
|
int attempt = 0;
|
|
|
|
|
do {
|
|
|
|
|
String[] operators = {"+", "-", "*", "/"};
|
|
|
|
|
question = generateBasicQuestion(operandCount, operators, true);
|
|
|
|
|
|
|
|
|
|
// 强制添加平方或开根号(修改点1)
|
|
|
|
|
question = addPowerOrRoot(question);
|
|
|
|
|
attempt++;
|
|
|
|
|
} while ((!question.contains("²") && !question.contains("√")) && attempt < 10);
|
|
|
|
|
|
|
|
|
|
return question;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private String generateSeniorQuestion(int operandCount) {
|
|
|
|
|
String question;
|
|
|
|
|
int attempt = 0;
|
|
|
|
|
do {
|
|
|
|
|
String[] operators = {"+", "-", "*", "/"};
|
|
|
|
|
question = generateBasicQuestion(operandCount, operators, true);
|
|
|
|
|
|
|
|
|
|
// 强制添加三角函数(修改点2)
|
|
|
|
|
question = addTrigonometricFunction(question);
|
|
|
|
|
attempt++;
|
|
|
|
|
} while ((!question.contains("sin") && !question.contains("cos") && !question.contains("tan")) && attempt < 10);
|
|
|
|
|
|
|
|
|
|
return question;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private String generateBasicQuestion(int operandCount, String[] operators, boolean useParentheses) {
|
|
|
|
|
if (operandCount < 2) {
|
|
|
|
|
// 单操作数时直接返回数字(修改点3)
|
|
|
|
|
return String.valueOf(getRandomNumber());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
StringBuilder question = new StringBuilder();
|
|
|
|
|
int num = getRandomNumber();
|
|
|
|
|
question.append(num);
|
|
|
|
|
|
|
|
|
|
for (int i = 1; i < operandCount; i++) {
|
|
|
|
|
String operator = operators[random.nextInt(operators.length)];
|
|
|
|
|
num = getRandomNumber();
|
|
|
|
|
|
|
|
|
|
if (operator.equals("/")) {
|
|
|
|
|
num = Math.max(1, num);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
boolean needParentheses = useParentheses &&
|
|
|
|
|
(operator.equals("*") || operator.equals("/")) &&
|
|
|
|
|
i < operandCount - 1;
|
|
|
|
|
|
|
|
|
|
if (needParentheses) {
|
|
|
|
|
question.insert(0, "(");
|
|
|
|
|
question.append(") ").append(operator).append(" ").append(num);
|
|
|
|
|
} else {
|
|
|
|
|
question.append(" ").append(operator).append(" ").append(num);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return question.toString();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private String addPowerOrRoot(String originalQuestion) {
|
|
|
|
|
// 修改点4:移除长度限制,支持单操作数
|
|
|
|
|
String[] parts = originalQuestion.split(" ");
|
|
|
|
|
|
|
|
|
|
// 如果是单操作数表达式
|
|
|
|
|
if (parts.length == 1) {
|
|
|
|
|
if (random.nextBoolean()) {
|
|
|
|
|
return parts[0] + "²";
|
|
|
|
|
} else {
|
|
|
|
|
return "√(" + parts[0] + ")";
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 多操作数表达式
|
|
|
|
|
int position = random.nextInt(parts.length);
|
|
|
|
|
while (position % 2 != 0) {
|
|
|
|
|
position = random.nextInt(parts.length);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (random.nextBoolean()) {
|
|
|
|
|
parts[position] = parts[position] + "²";
|
|
|
|
|
} else {
|
|
|
|
|
parts[position] = "√(" + parts[position] + ")";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return String.join(" ", parts);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private String addTrigonometricFunction(String originalQuestion) {
|
|
|
|
|
// 修改点5:移除长度限制,支持单操作数
|
|
|
|
|
String[] parts = originalQuestion.split(" ");
|
|
|
|
|
|
|
|
|
|
// 如果是单操作数表达式
|
|
|
|
|
if (parts.length == 1) {
|
|
|
|
|
String[] trigFunctions = {"sin", "cos", "tan"};
|
|
|
|
|
String trigFunction = trigFunctions[random.nextInt(trigFunctions.length)];
|
|
|
|
|
return trigFunction + "(" + parts[0] + ")";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 多操作数表达式
|
|
|
|
|
int position = random.nextInt(parts.length);
|
|
|
|
|
while (position % 2 != 0) {
|
|
|
|
|
position = random.nextInt(parts.length);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
String[] trigFunctions = {"sin", "cos", "tan"};
|
|
|
|
|
String trigFunction = trigFunctions[random.nextInt(trigFunctions.length)];
|
|
|
|
|
parts[position] = trigFunction + "(" + parts[position] + ")";
|
|
|
|
|
|
|
|
|
|
return String.join(" ", parts);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private int getRandomNumber() {
|
|
|
|
|
return random.nextInt(100) + 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void clearHistory() {
|
|
|
|
|
generatedQuestions.clear();
|
|
|
|
|
}
|
|
|
|
|
}
|