1 #9

Merged
hnu202326010114 merged 1 commits from develop into main 2 months ago

@ -85,61 +85,86 @@ public class ChoiceQuestionGenerator {
// 30%概率生成纯平方/开方题目70%概率生成包含平方/开方的复合运算题目
if (random.nextDouble() < 0.3) {
// 生成纯平方或开方题目
if (random.nextBoolean()) {
// 平方题目
int a = MIN_OPERAND_VALUE + random.nextInt(MAX_OPERAND_VALUE);
String questionText = String.format("%d² = ?", a);
int correctAnswer = a * a;
List<Integer> options = generateWrongOptions(correctAnswer);
options.add(correctAnswer);
Collections.shuffle(options);
return new Question(questionText,
String.valueOf(options.get(0)),
String.valueOf(options.get(1)),
String.valueOf(options.get(2)),
String.valueOf(options.get(3)),
String.valueOf(correctAnswer),
questionNumber);
} else {
// 开方题目
int perfectSquare = (int) Math.pow(random.nextInt(10) + 1, 2);
String questionText = String.format("√%d = ?", perfectSquare);
int correctAnswer = (int) Math.sqrt(perfectSquare);
List<Integer> options = generateWrongOptions(correctAnswer);
options.add(correctAnswer);
Collections.shuffle(options);
return new Question(questionText,
String.valueOf(options.get(0)),
String.valueOf(options.get(1)),
String.valueOf(options.get(2)),
String.valueOf(options.get(3)),
String.valueOf(correctAnswer),
questionNumber);
}
return generatePureSquareOrRootQuestion(questionNumber);
} else {
// 生成包含平方/开方的复合运算表达式(确保包含平方或开方)
String[] expression = generateJuniorCompoundExpressionWithGuarantee(operatorCount);
String questionText = expression[0];
int correctAnswer = Integer.parseInt(expression[1]);
// 生成错误选项
List<Integer> options = generateWrongOptions(correctAnswer);
options.add(correctAnswer);
Collections.shuffle(options);
return generateJuniorCompoundQuestion(operatorCount, questionNumber);
}
}
return new Question(questionText,
String.valueOf(options.get(0)),
String.valueOf(options.get(1)),
String.valueOf(options.get(2)),
String.valueOf(options.get(3)),
String.valueOf(correctAnswer),
questionNumber);
/**
*
*/
private Question generatePureSquareOrRootQuestion(int questionNumber) {
if (random.nextBoolean()) {
return generateSquareQuestion(questionNumber);
} else {
return generateRootQuestion(questionNumber);
}
}
/**
*
*/
private Question generateSquareQuestion(int questionNumber) {
int a = MIN_OPERAND_VALUE + random.nextInt(MAX_OPERAND_VALUE);
String questionText = String.format("%d² = ?", a);
int correctAnswer = a * a;
List<Integer> options = generateWrongOptions(correctAnswer);
options.add(correctAnswer);
Collections.shuffle(options);
return new Question(questionText,
String.valueOf(options.get(0)),
String.valueOf(options.get(1)),
String.valueOf(options.get(2)),
String.valueOf(options.get(3)),
String.valueOf(correctAnswer),
questionNumber);
}
/**
*
*/
private Question generateRootQuestion(int questionNumber) {
int perfectSquare = (int) Math.pow(random.nextInt(10) + 1, 2);
String questionText = String.format("√%d = ?", perfectSquare);
int correctAnswer = (int) Math.sqrt(perfectSquare);
List<Integer> options = generateWrongOptions(correctAnswer);
options.add(correctAnswer);
Collections.shuffle(options);
return new Question(questionText,
String.valueOf(options.get(0)),
String.valueOf(options.get(1)),
String.valueOf(options.get(2)),
String.valueOf(options.get(3)),
String.valueOf(correctAnswer),
questionNumber);
}
/**
*
*/
private Question generateJuniorCompoundQuestion(int operatorCount, int questionNumber) {
// 生成包含平方/开方的复合运算表达式(确保包含平方或开方)
String[] expression = generateJuniorCompoundExpressionWithGuarantee(operatorCount);
String questionText = expression[0];
int correctAnswer = Integer.parseInt(expression[1]);
// 生成错误选项
List<Integer> options = generateWrongOptions(correctAnswer);
options.add(correctAnswer);
Collections.shuffle(options);
return new Question(questionText,
String.valueOf(options.get(0)),
String.valueOf(options.get(1)),
String.valueOf(options.get(2)),
String.valueOf(options.get(3)),
String.valueOf(correctAnswer),
questionNumber);
}
/**
*
*/
@ -149,50 +174,63 @@ public class ChoiceQuestionGenerator {
// 30%概率生成纯三角函数题目70%概率生成包含三角函数的复合运算题目
if (random.nextDouble() < 0.3) {
// 生成纯三角函数题目
int[] commonAngles = {0, 30, 45, 60, 90, 120, 135, 150, 180, 210, 225, 270, 300, 315, 330};
int angle = commonAngles[random.nextInt(commonAngles.length)];
String[] functions = {"sin", "cos", "tan"};
String function = functions[random.nextInt(functions.length)];
String questionText = String.format("%s(%d°) = ?", function, angle);
double result = calculateTrigFunction(function, angle);
// 生成选项
List<String> options = generateTrigOptions(result);
// 使用格式化后的值作为正确答案,确保与选项一致
String correctAnswer = formatTrigValue(result);
// 随机打乱选项
Collections.shuffle(options);
return new Question(questionText,
options.get(0),
options.get(1),
options.get(2),
options.get(3),
correctAnswer,
questionNumber);
return generatePureTrigQuestion(questionNumber);
} else {
// 生成包含三角函数的复合运算表达式(确保包含三角函数)
String[] expression = generateSeniorCompoundExpressionWithGuarantee(operatorCount);
String questionText = expression[0];
int correctAnswer = Integer.parseInt(expression[1]);
// 生成错误选项
List<Integer> options = generateWrongOptions(correctAnswer);
options.add(correctAnswer);
Collections.shuffle(options);
return new Question(questionText,
String.valueOf(options.get(0)),
String.valueOf(options.get(1)),
String.valueOf(options.get(2)),
String.valueOf(options.get(3)),
String.valueOf(correctAnswer),
questionNumber);
return generateSeniorCompoundQuestion(operatorCount, questionNumber);
}
}
}
/**
*
*/
private Question generatePureTrigQuestion(int questionNumber) {
int[] commonAngles = {0, 30, 45, 60, 90, 120, 135, 150, 180, 210, 225, 270, 300, 315, 330};
int angle = commonAngles[random.nextInt(commonAngles.length)];
String[] functions = {"sin", "cos", "tan"};
String function = functions[random.nextInt(functions.length)];
String questionText = String.format("%s(%d°) = ?", function, angle);
double result = calculateTrigFunction(function, angle);
// 生成选项
List<String> options = generateTrigOptions(result);
// 使用格式化后的值作为正确答案,确保与选项一致
String correctAnswer = formatTrigValue(result);
// 随机打乱选项
Collections.shuffle(options);
return new Question(questionText,
options.get(0),
options.get(1),
options.get(2),
options.get(3),
correctAnswer,
questionNumber);
}
/**
*
*/
private Question generateSeniorCompoundQuestion(int operatorCount, int questionNumber) {
// 生成包含三角函数的复合运算表达式(确保包含三角函数)
String[] expression = generateSeniorCompoundExpressionWithGuarantee(operatorCount);
String questionText = expression[0];
int correctAnswer = Integer.parseInt(expression[1]);
// 生成错误选项
List<Integer> options = generateWrongOptions(correctAnswer);
options.add(correctAnswer);
Collections.shuffle(options);
return new Question(questionText,
String.valueOf(options.get(0)),
String.valueOf(options.get(1)),
String.valueOf(options.get(2)),
String.valueOf(options.get(3)),
String.valueOf(correctAnswer),
questionNumber);
}
/**
*
@ -296,69 +334,90 @@ private String generateNearbyValue(double correctAnswer, Set<String> usedOptions
*
*/
private double calculateTrigFunction(String function, int angle) {
double radians = Math.toRadians(angle);
switch (function) {
case "sin":
// 对特定角度返回精确值
switch (angle) {
case 0: return 0;
case 30: return 0.5;
case 45: return Math.sqrt(2)/2;
case 60: return Math.sqrt(3)/2;
case 90: return 1;
case 120: return Math.sqrt(3)/2;
case 135: return Math.sqrt(2)/2;
case 150: return 0.5;
case 180: return 0;
case 210: return -0.5;
case 225: return -Math.sqrt(2)/2;
case 270: return -1;
case 300: return -Math.sqrt(3)/2;
case 315: return -Math.sqrt(2)/2;
case 330: return -0.5;
default: return Math.sin(radians);
}
return calculateSin(angle);
case "cos":
// 对特定角度返回精确值
switch (angle) {
case 0: return 1;
case 30: return Math.sqrt(3)/2;
case 45: return Math.sqrt(2)/2;
case 60: return 0.5;
case 90: return 0;
case 120: return -0.5;
case 135: return -Math.sqrt(2)/2;
case 150: return -Math.sqrt(3)/2;
case 180: return -1;
case 210: return -Math.sqrt(3)/2;
case 225: return -Math.sqrt(2)/2;
case 270: return 0;
case 300: return 0.5;
case 315: return Math.sqrt(2)/2;
case 330: return Math.sqrt(3)/2;
default: return Math.cos(radians);
}
return calculateCos(angle);
case "tan":
// 对特定角度返回精确值或未定义
switch (angle) {
case 0: return 0;
case 30: return Math.sqrt(3)/3;
case 45: return 1;
case 60: return Math.sqrt(3);
case 90: return Double.POSITIVE_INFINITY; // 未定义
case 120: return -Math.sqrt(3);
case 135: return -1;
case 150: return -Math.sqrt(3)/3;
case 180: return 0;
case 210: return Math.sqrt(3)/3;
case 225: return 1;
case 270: return Double.POSITIVE_INFINITY; // 未定义
case 300: return -Math.sqrt(3);
case 315: return -1;
case 330: return -Math.sqrt(3)/3;
default: return Math.tan(radians);
}
default: return 0;
return calculateTan(angle);
default:
return 0;
}
}
/**
*
*/
private double calculateSin(int angle) {
switch (angle) {
case 0: return 0;
case 30: return 0.5;
case 45: return Math.sqrt(2)/2;
case 60: return Math.sqrt(3)/2;
case 90: return 1;
case 120: return Math.sqrt(3)/2;
case 135: return Math.sqrt(2)/2;
case 150: return 0.5;
case 180: return 0;
case 210: return -0.5;
case 225: return -Math.sqrt(2)/2;
case 270: return -1;
case 300: return -Math.sqrt(3)/2;
case 315: return -Math.sqrt(2)/2;
case 330: return -0.5;
default:
return Math.sin(Math.toRadians(angle));
}
}
/**
*
*/
private double calculateCos(int angle) {
switch (angle) {
case 0: return 1;
case 30: return Math.sqrt(3)/2;
case 45: return Math.sqrt(2)/2;
case 60: return 0.5;
case 90: return 0;
case 120: return -0.5;
case 135: return -Math.sqrt(2)/2;
case 150: return -Math.sqrt(3)/2;
case 180: return -1;
case 210: return -Math.sqrt(3)/2;
case 225: return -Math.sqrt(2)/2;
case 270: return 0;
case 300: return 0.5;
case 315: return Math.sqrt(2)/2;
case 330: return Math.sqrt(3)/2;
default:
return Math.cos(Math.toRadians(angle));
}
}
/**
*
*/
private double calculateTan(int angle) {
switch (angle) {
case 0: return 0;
case 30: return Math.sqrt(3)/3;
case 45: return 1;
case 60: return Math.sqrt(3);
case 90: return Double.POSITIVE_INFINITY; // 未定义
case 120: return -Math.sqrt(3);
case 135: return -1;
case 150: return -Math.sqrt(3)/3;
case 180: return 0;
case 210: return Math.sqrt(3)/3;
case 225: return 1;
case 270: return Double.POSITIVE_INFINITY; // 未定义
case 300: return -Math.sqrt(3);
case 315: return -1;
case 330: return -Math.sqrt(3)/3;
default:
return Math.tan(Math.toRadians(angle));
}
}
@ -796,11 +855,23 @@ private double calculateTrigFunction(String function, int angle) {
* /
*/
private int calculateJuniorCompoundExpression(List<Integer> operands, List<String> operators) {
// 先处理平方和开方运算
List<Integer> numbers = new ArrayList<>(operands);
List<String> ops = new ArrayList<>(operators);
// 第一轮:处理平方和开方运算
processSquareAndRootOperations(numbers, ops);
// 第二轮:处理乘除法
processMultiplicationAndDivision(numbers, ops);
// 第三轮:处理加减法
return processAdditionAndSubtraction(numbers, ops);
}
/**
*
*/
private void processSquareAndRootOperations(List<Integer> numbers, List<String> ops) {
for (int i = 0; i < ops.size(); i++) {
if (ops.get(i).equals("²")) {
int result = numbers.get(i) * numbers.get(i);
@ -813,8 +884,12 @@ private double calculateTrigFunction(String function, int angle) {
i--; // 调整索引
}
}
}
// 第二轮:处理乘除法
/**
*
*/
private void processMultiplicationAndDivision(List<Integer> numbers, List<String> ops) {
for (int i = 0; i < ops.size(); i++) {
if (ops.get(i).equals("*")) {
int result = numbers.get(i) * numbers.get(i + 1);
@ -823,25 +898,35 @@ private double calculateTrigFunction(String function, int angle) {
ops.remove(i);
i--; // 调整索引
} else if (ops.get(i).equals("/")) {
if (numbers.get(i + 1) != 0) {
int result = numbers.get(i) / numbers.get(i + 1);
numbers.set(i, result);
numbers.remove(i + 1);
ops.remove(i);
i--; // 调整索引
} else {
// 避免除零错误,重新生成
numbers.set(i + 1, 1 + random.nextInt(MAX_OPERAND_VALUE));
int result = numbers.get(i) / numbers.get(i + 1);
numbers.set(i, result);
numbers.remove(i + 1);
ops.remove(i);
i--; // 调整索引
}
handleDivision(numbers, ops, i);
i--; // 调整索引
}
}
}
// 第三轮:处理加减法
/**
*
*/
private void handleDivision(List<Integer> numbers, List<String> ops, int i) {
if (numbers.get(i + 1) != 0) {
int result = numbers.get(i) / numbers.get(i + 1);
numbers.set(i, result);
numbers.remove(i + 1);
ops.remove(i);
} else {
// 避免除零错误,重新生成
numbers.set(i + 1, 1 + random.nextInt(MAX_OPERAND_VALUE));
int result = numbers.get(i) / numbers.get(i + 1);
numbers.set(i, result);
numbers.remove(i + 1);
ops.remove(i);
}
}
/**
*
*/
private int processAdditionAndSubtraction(List<Integer> numbers, List<String> ops) {
int result = numbers.get(0);
for (int i = 0; i < ops.size(); i++) {
if (ops.get(i).equals("+")) {
@ -850,7 +935,6 @@ private double calculateTrigFunction(String function, int angle) {
result -= numbers.get(i + 1);
}
}
return result;
}
@ -858,11 +942,25 @@ private double calculateTrigFunction(String function, int angle) {
*
*/
private int calculateSeniorCompoundExpression(List<Double> operands, List<String> operators) {
// 先处理三角函数运算
List<Double> numbers = new ArrayList<>(operands);
List<String> ops = new ArrayList<>(operators);
// 第一轮:处理三角函数运算
processTrigonometricOperations(numbers, ops);
// 第二轮:处理乘除法
processDoubleMultiplicationAndDivision(numbers, ops);
// 第三轮:处理加减法
double result = processDoubleAdditionAndSubtraction(numbers, ops);
return (int) Math.round(result);
}
/**
*
*/
private void processTrigonometricOperations(List<Double> numbers, List<String> ops) {
for (int i = 0; i < ops.size(); i++) {
if (ops.get(i).equals("sin") || ops.get(i).equals("cos") || ops.get(i).equals("tan")) {
// 三角函数运算已经在生成时处理了
@ -870,8 +968,12 @@ private double calculateTrigFunction(String function, int angle) {
i--; // 调整索引
}
}
}
// 第二轮:处理乘除法
/**
*
*/
private void processDoubleMultiplicationAndDivision(List<Double> numbers, List<String> ops) {
for (int i = 0; i < ops.size(); i++) {
if (ops.get(i).equals("*")) {
double result = numbers.get(i) * numbers.get(i + 1);
@ -880,25 +982,35 @@ private double calculateTrigFunction(String function, int angle) {
ops.remove(i);
i--; // 调整索引
} else if (ops.get(i).equals("/")) {
if (numbers.get(i + 1) != 0) {
double result = numbers.get(i) / numbers.get(i + 1);
numbers.set(i, result);
numbers.remove(i + 1);
ops.remove(i);
i--; // 调整索引
} else {
// 避免除零错误,重新生成
numbers.set(i + 1, 1.0 + random.nextInt(MAX_OPERAND_VALUE));
double result = numbers.get(i) / numbers.get(i + 1);
numbers.set(i, result);
numbers.remove(i + 1);
ops.remove(i);
i--; // 调整索引
}
handleDoubleDivision(numbers, ops, i);
i--; // 调整索引
}
}
}
// 第三轮:处理加减法
/**
*
*/
private void handleDoubleDivision(List<Double> numbers, List<String> ops, int i) {
if (numbers.get(i + 1) != 0) {
double result = numbers.get(i) / numbers.get(i + 1);
numbers.set(i, result);
numbers.remove(i + 1);
ops.remove(i);
} else {
// 避免除零错误,重新生成
numbers.set(i + 1, 1.0 + random.nextInt(MAX_OPERAND_VALUE));
double result = numbers.get(i) / numbers.get(i + 1);
numbers.set(i, result);
numbers.remove(i + 1);
ops.remove(i);
}
}
/**
*
*/
private double processDoubleAdditionAndSubtraction(List<Double> numbers, List<String> ops) {
double result = numbers.get(0);
for (int i = 0; i < ops.size(); i++) {
if (ops.get(i).equals("+")) {
@ -907,66 +1019,38 @@ private double calculateTrigFunction(String function, int angle) {
result -= numbers.get(i + 1);
}
}
return (int) Math.round(result);
return result;
}
/**
*
*/
private int calculateAdvancedCompoundExpression(List<Integer> operands, List<String> operators) {
// 先处理平方运算
List<Integer> numbers = new ArrayList<>(operands);
List<String> ops = new ArrayList<>(operators);
// 第一轮:处理平方运算
for (int i = 0; i < ops.size(); i++) {
if (ops.get(i).equals("²")) {
int result = numbers.get(i) * numbers.get(i);
numbers.set(i, result);
ops.remove(i);
i--; // 调整索引
}
}
processSquareOperations(numbers, ops);
// 第二轮:处理乘除法
processMultiplicationAndDivision(numbers, ops);
// 第三轮:处理加减法
return processAdditionAndSubtraction(numbers, ops);
}
/**
*
*/
private void processSquareOperations(List<Integer> numbers, List<String> ops) {
for (int i = 0; i < ops.size(); i++) {
if (ops.get(i).equals("*")) {
int result = numbers.get(i) * numbers.get(i + 1);
if (ops.get(i).equals("²")) {
int result = numbers.get(i) * numbers.get(i);
numbers.set(i, result);
numbers.remove(i + 1);
ops.remove(i);
i--; // 调整索引
} else if (ops.get(i).equals("/")) {
if (numbers.get(i + 1) != 0) {
int result = numbers.get(i) / numbers.get(i + 1);
numbers.set(i, result);
numbers.remove(i + 1);
ops.remove(i);
i--; // 调整索引
} else {
// 避免除零错误,重新生成
numbers.set(i + 1, 1 + random.nextInt(MAX_OPERAND_VALUE));
int result = numbers.get(i) / numbers.get(i + 1);
numbers.set(i, result);
numbers.remove(i + 1);
ops.remove(i);
i--; // 调整索引
}
}
}
// 第三轮:处理加减法
int result = numbers.get(0);
for (int i = 0; i < ops.size(); i++) {
if (ops.get(i).equals("+")) {
result += numbers.get(i + 1);
} else if (ops.get(i).equals("-")) {
result -= numbers.get(i + 1);
}
}
return result;
}
/**

@ -123,11 +123,27 @@ public class EmailService {
*/
private String createEmailContent(String verificationCode) {
StringBuilder html = new StringBuilder();
appendHtmlHeader(html);
appendHtmlStyles(html);
appendHtmlBody(html, verificationCode);
return html.toString();
}
/**
* HTML
*/
private void appendHtmlHeader(StringBuilder html) {
html.append("<!DOCTYPE html>");
html.append("<html>");
html.append("<head>");
html.append("<meta charset=\"UTF-8\">");
html.append("<title>邮箱验证码</title>");
}
/**
* HTML
*/
private void appendHtmlStyles(StringBuilder html) {
html.append("<style>");
html.append("body { font-family: Arial, sans-serif; background-color: #f5f5f5; margin: 0; padding: 20px; }");
html.append(".container { max-width: 600px; margin: 0 auto; background-color: white; border-radius: 10px; box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); overflow: hidden; }");
@ -140,19 +156,61 @@ public class EmailService {
html.append(".warning { background-color: #fff3cd; border: 1px solid #ffeaa7; border-radius: 5px; padding: 15px; margin: 20px 0; color: #856404; }");
html.append("</style>");
html.append("</head>");
}
/**
* HTML
*/
private void appendHtmlBody(StringBuilder html, String verificationCode) {
html.append("<body>");
html.append("<div class=\"container\">");
appendEmailHeader(html);
appendEmailContent(html, verificationCode);
appendEmailFooter(html);
html.append("</div>");
html.append("</body>");
html.append("</html>");
}
/**
*
*/
private void appendEmailHeader(StringBuilder html) {
html.append("<div class=\"header\">");
html.append("<h1>数学考试系统</h1>");
html.append("<p>邮箱验证码</p>");
html.append("</div>");
}
/**
*
*/
private void appendEmailContent(StringBuilder html, String verificationCode) {
html.append("<div class=\"content\">");
html.append("<h2>您好!</h2>");
html.append("<p>您正在注册数学考试系统,请使用以下验证码完成注册:</p>");
appendVerificationCode(html, verificationCode);
appendWarningSection(html);
html.append("<p>如果您没有注册数学考试系统,请忽略此邮件。</p>");
html.append("<p>祝您使用愉快!</p>");
html.append("<p><strong>数学考试系统团队</strong></p>");
html.append("</div>");
}
/**
*
*/
private void appendVerificationCode(StringBuilder html, String verificationCode) {
html.append("<div class=\"verification-code\">");
html.append("<p><strong>验证码:</strong></p>");
html.append("<div class=\"code\">").append(verificationCode).append("</div>");
html.append("</div>");
}
/**
*
*/
private void appendWarningSection(StringBuilder html) {
html.append("<div class=\"warning\">");
html.append("<p><strong>重要提示:</strong></p>");
html.append("<ul>");
@ -161,19 +219,16 @@ public class EmailService {
html.append("<li>如非本人操作,请忽略此邮件</li>");
html.append("</ul>");
html.append("</div>");
html.append("<p>如果您没有注册数学考试系统,请忽略此邮件。</p>");
html.append("<p>祝您使用愉快!</p>");
html.append("<p><strong>数学考试系统团队</strong></p>");
html.append("</div>");
}
/**
*
*/
private void appendEmailFooter(StringBuilder html) {
html.append("<div class=\"footer\">");
html.append("<p>此邮件由系统自动发送,请勿回复</p>");
html.append("<p>2024 数学考试系统. All rights reserved.</p>");
html.append("</div>");
html.append("</div>");
html.append("</body>");
html.append("</html>");
return html.toString();
}

@ -68,13 +68,42 @@ public class ExamDetailsController {
*
*/
private VBox createQuestionCard(int questionNumber, Question question, String userAnswer, boolean isCorrect) {
VBox card = createCardContainer(isCorrect);
// 题目编号和状态
HBox headerBox = createHeaderBox(questionNumber, isCorrect);
// 题目内容
Label questionLabel = createQuestionLabel(question);
// 选项
VBox optionsBox = createOptionsBox(question, userAnswer);
// 答案信息
HBox answerBox = createAnswerBox(userAnswer, question);
// 添加到卡片
card.getChildren().addAll(headerBox, questionLabel, optionsBox, answerBox);
return card;
}
/**
*
*/
private VBox createCardContainer(boolean isCorrect) {
VBox card = new VBox();
card.setSpacing(10);
card.setStyle("-fx-background-color: " + (isCorrect ? "rgba(144,238,144,0.3)" : "rgba(255,182,193,0.3)") +
"; -fx-background-radius: 10; -fx-padding: 15; -fx-border-color: " +
(isCorrect ? "#90EE90" : "#FFB6C1") + "; -fx-border-radius: 10; -fx-border-width: 2;");
return card;
}
// 题目编号和状态
/**
*
*/
private HBox createHeaderBox(int questionNumber, boolean isCorrect) {
HBox headerBox = new HBox();
headerBox.setSpacing(10);
@ -87,13 +116,23 @@ public class ExamDetailsController {
statusLabel.setTextFill(isCorrect ? Color.GREEN : Color.RED);
headerBox.getChildren().addAll(questionNumLabel, statusLabel);
return headerBox;
}
// 题目内容
/**
*
*/
private Label createQuestionLabel(Question question) {
Label questionLabel = new Label("题目: " + question.getQuestionText());
questionLabel.setFont(Font.font("System", 14));
questionLabel.setWrapText(true);
return questionLabel;
}
// 选项
/**
*
*/
private VBox createOptionsBox(Question question, String userAnswer) {
VBox optionsBox = new VBox();
optionsBox.setSpacing(5);
@ -109,8 +148,13 @@ public class ExamDetailsController {
highlightAnswer(optionDLabel, question.getOptionD(), userAnswer, question.getCorrectAnswer());
optionsBox.getChildren().addAll(optionALabel, optionBLabel, optionCLabel, optionDLabel);
return optionsBox;
}
// 答案信息
/**
*
*/
private HBox createAnswerBox(String userAnswer, Question question) {
HBox answerBox = new HBox();
answerBox.setSpacing(20);
@ -123,11 +167,7 @@ public class ExamDetailsController {
correctAnswerLabel.setTextFill(Color.GREEN);
answerBox.getChildren().addAll(userAnswerLabel, correctAnswerLabel);
// 添加到卡片
card.getChildren().addAll(headerBox, questionLabel, optionsBox, answerBox);
return card;
return answerBox;
}
/**

@ -262,35 +262,57 @@ public class ExamTakingController {
timer.stop();
// 准备用户答案列表
List<String> userAnswersList = new ArrayList<>();
for (int i = 0; i < examQuestions.size(); i++) {
String answer = userAnswers.get(i);
userAnswersList.add(answer != null ? answer : "");
}
List<String> userAnswersList = prepareUserAnswersList();
// 关闭当前考试窗口
Stage currentStage = (Stage) submitButton.getScene().getWindow();
currentStage.close();
closeCurrentExamWindow();
// 打开结果界面
FXMLLoader loader = new FXMLLoader(getClass().getResource("exam-result-view.fxml"));
Scene scene = new Scene(loader.load(), 600, 700);
Stage resultStage = new Stage();
resultStage.setTitle("考试结果");
resultStage.setScene(scene);
resultStage.setResizable(false);
// 传递数据给结果控制器
ExamResultController controller = loader.getController();
controller.setExamResult(examQuestions, userAnswersList, username, level);
resultStage.show();
openResultWindow(userAnswersList);
} catch (Exception e) {
showAlert("错误", "显示结果时出错:" + e.getMessage());
}
}
/**
*
*/
private List<String> prepareUserAnswersList() {
List<String> userAnswersList = new ArrayList<>();
for (int i = 0; i < examQuestions.size(); i++) {
String answer = userAnswers.get(i);
userAnswersList.add(answer != null ? answer : "");
}
return userAnswersList;
}
/**
*
*/
private void closeCurrentExamWindow() {
Stage currentStage = (Stage) submitButton.getScene().getWindow();
currentStage.close();
}
/**
*
*/
private void openResultWindow(List<String> userAnswersList) throws Exception {
FXMLLoader loader = new FXMLLoader(getClass().getResource("exam-result-view.fxml"));
Scene scene = new Scene(loader.load(), 600, 700);
Stage resultStage = new Stage();
resultStage.setTitle("考试结果");
resultStage.setScene(scene);
resultStage.setResizable(false);
// 传递数据给结果控制器
ExamResultController controller = loader.getController();
controller.setExamResult(examQuestions, userAnswersList, username, level);
resultStage.show();
}
private void returnToMainMenu() {
try {
// 关闭当前窗口

@ -82,22 +82,40 @@ public class RegisterController {
private void handleSendCode() {
String email = emailField.getText().trim();
if (!validateEmailInput(email)) {
return;
}
if (!emailService.isAvailable()) {
showStatus("❌ 邮件服务不可用,请检查配置", true);
return;
}
generateAndSendCode(email);
startSendCodeCountdown();
}
/**
*
*/
private boolean validateEmailInput(String email) {
if (email.isEmpty()) {
showStatus("请输入邮箱地址", true);
return;
return false;
}
if (!isValidEmail(email)) {
showStatus("请输入有效的邮箱地址", true);
return;
return false;
}
// 检查邮件服务是否可用
if (!emailService.isAvailable()) {
showStatus("❌ 邮件服务不可用,请检查配置", true);
return;
}
return true;
}
/**
*
*/
private void generateAndSendCode(String email) {
// 生成6位数字验证码
generatedCode = emailService.generateVerificationCode();
codeGenerationTime = System.currentTimeMillis();
@ -110,18 +128,30 @@ public class RegisterController {
boolean success = emailService.sendVerificationCode(email, generatedCode);
javafx.application.Platform.runLater(() -> {
if (success) {
showStatus("✅ 验证码已发送到邮箱:" + email + ",请查收邮件", false);
// 启用注册按钮
registerButton.setDisable(false);
} else {
showStatus("❌ 邮件发送失败,请检查邮箱地址或稍后重试", true);
// 显示验证码用于调试(仅开发环境)
showStatus("❌ 邮件发送失败,请检查邮箱地址或稍后重试。验证码:" + generatedCode + "(调试用)", true);
}
handleSendCodeResult(success, email);
});
}).start();
}
/**
*
*/
private void handleSendCodeResult(boolean success, String email) {
if (success) {
showStatus("✅ 验证码已发送到邮箱:" + email + ",请查收邮件", false);
// 启用注册按钮
registerButton.setDisable(false);
} else {
showStatus("❌ 邮件发送失败,请检查邮箱地址或稍后重试", true);
// 显示验证码用于调试(仅开发环境)
showStatus("❌ 邮件发送失败,请检查邮箱地址或稍后重试。验证码:" + generatedCode + "(调试用)", true);
}
}
/**
*
*/
private void startSendCodeCountdown() {
// 禁用发送按钮60秒
sendCodeButton.setDisable(true);
sendCodeButton.setText("60秒后可重发");
@ -140,72 +170,99 @@ public class RegisterController {
String level = levelComboBox.getValue();
// 验证输入
if (!validateInput(username, password, confirmPassword, email, verificationCode)) {
return;
}
// 验证验证码
if (!verifyCode(verificationCode)) {
showStatus("验证码错误或已过期", true);
return;
}
// 检查用户名和邮箱是否已存在
if (!checkUserAvailability(username, email)) {
return;
}
// 保存用户信息
if (saveUserData(username, password, email, level)) {
showStatus("注册成功!正在跳转到登录界面...", false);
scheduleRedirectToLogin();
} else {
showStatus("注册失败,请重试", true);
}
}
/**
*
*/
private boolean validateInput(String username, String password, String confirmPassword,
String email, String verificationCode) {
if (username.isEmpty() || password.isEmpty() || confirmPassword.isEmpty() ||
email.isEmpty() || verificationCode.isEmpty()) {
showStatus("请填写所有字段", true);
return;
return false;
}
if (username.length() < 3) {
showStatus("用户名至少需要3个字符", true);
return;
return false;
}
if (password.length() < 6) {
showStatus("密码至少需要6个字符", true);
return;
return false;
}
if (!isValidPassword(password)) {
showStatus("密码必须包含大小写字母和数字", true);
return;
return false;
}
if (!password.equals(confirmPassword)) {
showStatus("两次输入的密码不一致", true);
return;
return false;
}
if (!isValidEmail(email)) {
showStatus("请输入有效的邮箱地址", true);
return;
return false;
}
// 验证验证码
if (!verifyCode(verificationCode)) {
showStatus("验证码错误或已过期", true);
return;
}
return true;
}
// 检查用户名是否已存在
/**
*
*/
private boolean checkUserAvailability(String username, String email) {
if (isUserExists(username)) {
showStatus("用户名已存在,请选择其他用户名", true);
return;
return false;
}
// 检查邮箱是否已注册
if (isEmailExists(email)) {
showStatus("该邮箱已被注册", true);
return;
return false;
}
// 保存用户信息
if (saveUserData(username, password, email, level)) {
showStatus("注册成功!正在跳转到登录界面...", false);
return true;
}
// 延迟跳转到登录界面
Timer timer = new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
javafx.application.Platform.runLater(() -> {
handleBackToLogin();
});
}
}, 2000);
} else {
showStatus("注册失败,请重试", true);
}
/**
*
*/
private void scheduleRedirectToLogin() {
Timer timer = new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
javafx.application.Platform.runLater(() -> {
handleBackToLogin();
});
}
}, 2000);
}
@FXML

Loading…
Cancel
Save