sqf_branch
宋奇峰 2 months ago
parent 7b468e720c
commit d31cb6fd5a

Binary file not shown.

@ -22,8 +22,8 @@ src/
├─ ExamFrame.java
└─ ResultFrame.java
lib/
├─ Main.java
└─ view/
├─ jakarta.activation-2.0.1.jar
└─ jakarta.mail-2.0.1.jar
---

@ -13,105 +13,82 @@ import javax.script.ScriptException;
*/
public class Create {
// 评估表达式数值double若失败抛异常
private static double evalExpression(String expr) throws ScriptException {
return ExpressionEvaluator.evaluate(expr);
}
/**
* Paper questions, options, correctIndex
*/
public static Paper create(int n, Login.Level currentLevel, Login.Account user) {
List<String> existing = LoadFile.loadExistingQuestions(user.username);
Generator qg = new Generator(currentLevel, existing);
List<String> paper = qg.generatePaper(n);
if (paper.isEmpty()) {
return null;
}
List<String> paper = generatePaper(n, currentLevel, existing);
if (paper.isEmpty()) return null;
// 为每道题生成 4 个选项:一个正确值(三位有效数)加上 3 个干扰项
List<String[]> optionsList = new ArrayList<>();
int[] correctIdx = new int[paper.size()];
for (int i = 0; i < paper.size(); i++) {
String q = paper.get(i);
double correctVal;
try {
correctVal = evalExpression(q);
} catch (Exception ex) {
// 如果无法精确计算(如复杂表达式),我们退而使用字符串匹配:将题目文本作为正确选项,生成三个变体文本
String[] opts = new String[4];
opts[0] = q;
opts[1] = q + " + 1";
opts[2] = q + " - 1";
opts[3] = "错误:" + q;
shuffleArray(opts);
int idx = findIndex(opts, q);
optionsList.add(opts);
correctIdx[i] = idx;
continue;
}
// 格式化正确值为保留3位小数若为整数则不显示小数
String correctStr = formatNumber(correctVal);
// 判断是否为整数答案
boolean isIntAnswer = Math.abs(correctVal - Math.round(correctVal)) < 1e-6;
// 产生三个干扰值
Set<String> optsSet = new LinkedHashSet<>();
optsSet.add(correctStr);
Random r = new Random();
int attempts = 0;
while (optsSet.size() < 4 && attempts < 50) {
attempts++;
double delta;
if (isIntAnswer) {
// 整数题:干扰项也是整数(偏差 ±1~±10
delta = r.nextInt(10) + 1;
if (r.nextBoolean()) {
delta = -delta;
}
} else {
// 小数题:随机偏差比例
delta = (Math.abs(correctVal) < 1e-6)
? (r.nextDouble() * 5 + 1)
: (r.nextGaussian() * Math.max(1, Math.abs(correctVal) * 0.15));
}
double cand = correctVal + delta;
String s = formatNumber(cand);
optsSet.add(s);
}
// 不足 4 个时补齐
while (optsSet.size() < 4) {
double cand = isIntAnswer
? correctVal + (r.nextInt(10) - 5)
: correctVal + (r.nextDouble() * 2 - 1);
optsSet.add(formatNumber(cand));
}
String[] optsArr = optsSet.toArray(new String[0]);
// 随机打乱并记录正确项位置
shuffleArray(optsArr);
int idx = findIndex(optsArr, correctStr);
optionsList.add(optsArr);
correctIdx[i] = idx;
optionsList.add(generateOptions(q, correctIdx, i));
}
savePaper(user.username, paper);
return new Paper(paper, optionsList, correctIdx);
}
private static List<String> generatePaper(int n, Login.Level level, List<String> existing) {
Generator qg = new Generator(level, existing);
return qg.generatePaper(n);
}
private static String[] generateOptions(String question, int[] correctIdx, int i) {
double correctVal;
try {
correctVal = evalExpression(question);
return generateNumericOptions(correctVal, correctIdx, i);
} catch (Exception e) {
return generateTextOptions(question, correctIdx, i);
}
}
private static String[] generateTextOptions(String question, int[] correctIdx, int i) {
String[] opts = new String[]{question, question + " + 1", question + " - 1", "错误:" + question};
shuffleArray(opts);
correctIdx[i] = findIndex(opts, question);
return opts;
}
private static String[] generateNumericOptions(double correctVal, int[] correctIdx, int i) {
String correctStr = formatNumber(correctVal);
boolean isInt = Math.abs(correctVal - Math.round(correctVal)) < 1e-6;
Set<String> optsSet = new LinkedHashSet<>();
optsSet.add(correctStr);
Random r = new Random();
int attempts = 0;
while (optsSet.size() < 4 && attempts < 50) {
attempts++;
double delta = isInt ? r.nextInt(10) + 1 : (r.nextGaussian() * Math.max(1, Math.abs(correctVal) * 0.15));
if (isInt && r.nextBoolean()) delta = -delta;
optsSet.add(formatNumber(correctVal + delta));
}
// 保存试卷原文本(题干)到文件(按你的 Save 实现)
while (optsSet.size() < 4) {
double delta = isInt ? r.nextInt(10) - 5 : r.nextDouble() * 2 - 1;
optsSet.add(formatNumber(correctVal + delta));
}
String[] optsArr = optsSet.toArray(new String[0]);
shuffleArray(optsArr);
correctIdx[i] = findIndex(optsArr, correctStr);
return optsArr;
}
private static void savePaper(String username, List<String> paper) {
try {
// 为保存,我们保存原题干列表(文本)
java.util.List<String> raw = new ArrayList<>();
for (String s : paper) {
raw.add(s);
}
Save.savePaper(user.username, raw);
Save.savePaper(username, new ArrayList<>(paper));
} catch (RuntimeException re) {
// 抛给 UI 处理(但仍返回 Paper
System.err.println("保存试卷时出错: " + re.getMessage());
}
return new Paper(paper, optionsList, correctIdx);
}
private static void shuffleArray(String[] arr) {
@ -125,19 +102,13 @@ public class Create {
}
private static int findIndex(String[] arr, String target) {
for (int i = 0; i < arr.length; i++) {
if (arr[i].equals(target)) {
return i;
}
}
for (int i = 0; i < arr.length; i++) if (arr[i].equals(target)) return i;
return 0;
}
private static String formatNumber(double v) {
if (Math.abs(v - Math.round(v)) < 1e-6) {
return String.valueOf((long) Math.round(v));
} else {
return String.format("%.3f", v);
}
if (Math.abs(v - Math.round(v)) < 1e-6) return String.valueOf((long) Math.round(v));
return String.format("%.3f", v);
}
}

Loading…
Cancel
Save