|
|
|
|
@ -18,7 +18,7 @@ import java.util.*;
|
|
|
|
|
* 考试进行界面控制器
|
|
|
|
|
*/
|
|
|
|
|
public class ExamTakingController {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 界面控件
|
|
|
|
|
@FXML private Label examInfoLabel;
|
|
|
|
|
@FXML private Label questionNumberLabel;
|
|
|
|
|
@ -34,7 +34,7 @@ public class ExamTakingController {
|
|
|
|
|
@FXML private Button exitExamButton;
|
|
|
|
|
@FXML private ProgressBar progressBar;
|
|
|
|
|
@FXML private Label progressLabel;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 数据成员
|
|
|
|
|
private List<Question> examQuestions;
|
|
|
|
|
private int currentQuestionIndex = 0;
|
|
|
|
|
@ -45,13 +45,13 @@ public class ExamTakingController {
|
|
|
|
|
private int totalQuestions;
|
|
|
|
|
private Timeline timer;
|
|
|
|
|
private int remainingSeconds;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@FXML
|
|
|
|
|
public void initialize() {
|
|
|
|
|
setupAnswerGroup();
|
|
|
|
|
setupTimer();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private void setupAnswerGroup() {
|
|
|
|
|
answerGroup = new ToggleGroup();
|
|
|
|
|
optionA.setToggleGroup(answerGroup);
|
|
|
|
|
@ -59,7 +59,7 @@ public class ExamTakingController {
|
|
|
|
|
optionC.setToggleGroup(answerGroup);
|
|
|
|
|
optionD.setToggleGroup(answerGroup);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private void setupTimer() {
|
|
|
|
|
// 设置30分钟倒计时
|
|
|
|
|
remainingSeconds = 30 * 60; // 30分钟 = 1800秒
|
|
|
|
|
@ -67,7 +67,7 @@ public class ExamTakingController {
|
|
|
|
|
timer.setCycleCount(Timeline.INDEFINITE);
|
|
|
|
|
timer.play();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private void updateTimer() {
|
|
|
|
|
remainingSeconds--;
|
|
|
|
|
if (remainingSeconds <= 0) {
|
|
|
|
|
@ -75,12 +75,12 @@ public class ExamTakingController {
|
|
|
|
|
handleTimeUp();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int minutes = remainingSeconds / 60;
|
|
|
|
|
int seconds = remainingSeconds % 60;
|
|
|
|
|
timeLabel.setText(String.format("⏰ 剩余时间: %02d:%02d", minutes, seconds));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private void handleTimeUp() {
|
|
|
|
|
Alert alert = new Alert(Alert.AlertType.WARNING);
|
|
|
|
|
alert.setTitle("时间到");
|
|
|
|
|
@ -89,37 +89,37 @@ public class ExamTakingController {
|
|
|
|
|
alert.showAndWait();
|
|
|
|
|
showResults();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public void setExamData(List<Question> questions, String username, String level) {
|
|
|
|
|
this.examQuestions = questions;
|
|
|
|
|
this.username = username;
|
|
|
|
|
this.level = level;
|
|
|
|
|
this.totalQuestions = questions.size();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
examInfoLabel.setText(String.format("👤 %s | 📚 %s | 📝 %d题", username, level, totalQuestions));
|
|
|
|
|
displayCurrentQuestion();
|
|
|
|
|
updateProgress();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private void displayCurrentQuestion() {
|
|
|
|
|
if (currentQuestionIndex >= examQuestions.size()) {
|
|
|
|
|
showResults();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Question question = examQuestions.get(currentQuestionIndex);
|
|
|
|
|
questionNumberLabel.setText(String.format("第 %d 题 / 共 %d 题",
|
|
|
|
|
questionNumberLabel.setText(String.format("第 %d 题 / 共 %d 题",
|
|
|
|
|
currentQuestionIndex + 1, examQuestions.size()));
|
|
|
|
|
questionTextLabel.setText(question.getQuestionText());
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
optionA.setText("A. " + question.getOptionA());
|
|
|
|
|
optionB.setText("B. " + question.getOptionB());
|
|
|
|
|
optionC.setText("C. " + question.getOptionC());
|
|
|
|
|
optionD.setText("D. " + question.getOptionD());
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 清除之前的选择
|
|
|
|
|
answerGroup.selectToggle(null);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 更新按钮状态
|
|
|
|
|
if (currentQuestionIndex == examQuestions.size() - 1) {
|
|
|
|
|
submitButton.setText("✅ 提交并完成考试");
|
|
|
|
|
@ -128,17 +128,17 @@ public class ExamTakingController {
|
|
|
|
|
submitButton.setText("✅ 提交答案");
|
|
|
|
|
nextButton.setVisible(true);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
updateProgress();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private void updateProgress() {
|
|
|
|
|
double progress = (double) currentQuestionIndex / examQuestions.size();
|
|
|
|
|
progressBar.setProgress(progress);
|
|
|
|
|
progressLabel.setText(String.format("进度: %d/%d (%.1f%%)",
|
|
|
|
|
progressLabel.setText(String.format("进度: %d/%d (%.1f%%)",
|
|
|
|
|
currentQuestionIndex + 1, examQuestions.size(), progress * 100));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@FXML
|
|
|
|
|
private void handleSubmitAnswer() {
|
|
|
|
|
RadioButton selectedOption = (RadioButton) answerGroup.getSelectedToggle();
|
|
|
|
|
@ -146,10 +146,10 @@ public class ExamTakingController {
|
|
|
|
|
showAlert("请选择一个答案", "请先选择答案再提交");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
String answer = selectedOption.getText().substring(0, 1); // 获取A、B、C、D
|
|
|
|
|
|
|
|
|
|
String answer = getAnswerValue(selectedOption.getText().substring(0, 1)); // 获取答案
|
|
|
|
|
userAnswers.put(currentQuestionIndex, answer);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (currentQuestionIndex == examQuestions.size() - 1) {
|
|
|
|
|
// 最后一题,显示结果
|
|
|
|
|
timer.stop();
|
|
|
|
|
@ -160,13 +160,23 @@ public class ExamTakingController {
|
|
|
|
|
displayCurrentQuestion();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 添加辅助方法获取选项对应的实际值
|
|
|
|
|
private String getAnswerValue(String optionLetter) {
|
|
|
|
|
Question currentQuestion = examQuestions.get(currentQuestionIndex);
|
|
|
|
|
switch (optionLetter) {
|
|
|
|
|
case "A": return currentQuestion.getOptionA();
|
|
|
|
|
case "B": return currentQuestion.getOptionB();
|
|
|
|
|
case "C": return currentQuestion.getOptionC();
|
|
|
|
|
case "D": return currentQuestion.getOptionD();
|
|
|
|
|
default: return "";
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
@FXML
|
|
|
|
|
private void handleNextQuestion() {
|
|
|
|
|
currentQuestionIndex++;
|
|
|
|
|
displayCurrentQuestion();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@FXML
|
|
|
|
|
private void handleExitExam() {
|
|
|
|
|
if (showExitConfirmation()) {
|
|
|
|
|
@ -174,7 +184,7 @@ public class ExamTakingController {
|
|
|
|
|
returnToMainMenu();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private boolean showExitConfirmation() {
|
|
|
|
|
Alert alert = new Alert(Alert.AlertType.CONFIRMATION);
|
|
|
|
|
alert.setTitle("确认退出");
|
|
|
|
|
@ -182,7 +192,7 @@ public class ExamTakingController {
|
|
|
|
|
alert.setContentText("退出后当前进度将丢失。");
|
|
|
|
|
return alert.showAndWait().orElse(ButtonType.CANCEL) == ButtonType.OK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private void showAlert(String title, String message) {
|
|
|
|
|
Alert alert = new Alert(Alert.AlertType.INFORMATION);
|
|
|
|
|
alert.setTitle(title);
|
|
|
|
|
@ -190,34 +200,34 @@ public class ExamTakingController {
|
|
|
|
|
alert.setContentText(message);
|
|
|
|
|
alert.showAndWait();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private void showResults() {
|
|
|
|
|
try {
|
|
|
|
|
// 停止计时器
|
|
|
|
|
timer.stop();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 计算成绩
|
|
|
|
|
int correctCount = 0;
|
|
|
|
|
StringBuilder resultDetails = new StringBuilder();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < examQuestions.size(); i++) {
|
|
|
|
|
Question question = examQuestions.get(i);
|
|
|
|
|
String userAnswer = userAnswers.get(i);
|
|
|
|
|
boolean isCorrect = question.isCorrect(userAnswer);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (isCorrect) {
|
|
|
|
|
correctCount++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
resultDetails.append("第").append(i + 1).append("题: ");
|
|
|
|
|
resultDetails.append(question.getQuestionText()).append("\n");
|
|
|
|
|
resultDetails.append("你的答案: ").append(userAnswer != null ? userAnswer : "未作答").append(" ");
|
|
|
|
|
resultDetails.append("正确答案: ").append(question.getCorrectAnswer()).append(" ");
|
|
|
|
|
resultDetails.append(isCorrect ? "✓" : "✗").append("\n\n");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int score = (int) Math.round((double) correctCount / examQuestions.size() * 100);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 显示结果对话框
|
|
|
|
|
Alert resultAlert = new Alert(Alert.AlertType.INFORMATION);
|
|
|
|
|
resultAlert.setTitle("考试完成");
|
|
|
|
|
@ -227,21 +237,21 @@ public class ExamTakingController {
|
|
|
|
|
score, correctCount, examQuestions.size(), (double) correctCount / examQuestions.size() * 100
|
|
|
|
|
));
|
|
|
|
|
resultAlert.showAndWait();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 返回主菜单
|
|
|
|
|
returnToMainMenu();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
showAlert("错误", "显示结果时出错:" + e.getMessage());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private void returnToMainMenu() {
|
|
|
|
|
try {
|
|
|
|
|
// 关闭当前窗口
|
|
|
|
|
Stage currentStage = (Stage) submitButton.getScene().getWindow();
|
|
|
|
|
currentStage.close();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 打开主菜单
|
|
|
|
|
FXMLLoader loader = new FXMLLoader(getClass().getResource("exam-view.fxml"));
|
|
|
|
|
Scene scene = new Scene(loader.load(), 1000, 900);
|
|
|
|
|
@ -249,7 +259,7 @@ public class ExamTakingController {
|
|
|
|
|
stage.setTitle("数学考试系统");
|
|
|
|
|
stage.setScene(scene);
|
|
|
|
|
stage.show();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
showAlert("错误", "返回主菜单时出错:" + e.getMessage());
|
|
|
|
|
}
|
|
|
|
|
|