You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
math-learing/src/main/java/com/personalproject/model/ExamSession.java

256 lines
6.5 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

package com.personalproject.model;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
* 表示用户的考试会话.
*/
public final class ExamSession {
private final String username;
private final DifficultyLevel difficultyLevel;
private final List<QuizQuestion> questions;
private final List<Integer> userAnswers;
private final LocalDateTime startTime;
private int currentQuestionIndex;
/**
* 创建新的考试会话.
*
* @param username 考生的用户名
* @param difficultyLevel 考试的难度级别
* @param questions 考试题目列表
*/
public ExamSession(String username, DifficultyLevel difficultyLevel,
List<QuizQuestion> questions) {
if (username == null || username.trim().isEmpty()) {
throw new IllegalArgumentException("Username cannot be null or empty");
}
if (difficultyLevel == null) {
throw new IllegalArgumentException("Difficulty level cannot be null");
}
if (questions == null || questions.isEmpty()) {
throw new IllegalArgumentException("Questions list cannot be null or empty");
}
this.username = username;
this.difficultyLevel = difficultyLevel;
this.questions = List.copyOf(questions); // 题目的不可变副本
this.userAnswers = new ArrayList<>(Collections.nCopies(questions.size(), -1));
this.startTime = LocalDateTime.now();
this.currentQuestionIndex = 0;
}
/**
* 获取考生的用户名.
*
* @return 用户名
*/
public String getUsername() {
return username;
}
/**
* 获取考试的难度级别.
*
* @return 考试难度级别
*/
public DifficultyLevel getDifficultyLevel() {
return difficultyLevel;
}
/**
* 获取考试中的题目列表.
*
* @return 不可修改的题目列表
*/
public List<QuizQuestion> getQuestions() {
return questions;
}
/**
* 获取用户对各题的作答.
*
* @return 答案索引列表(-1 表示未选择)
*/
public List<Integer> getUserAnswers() {
return List.copyOf(userAnswers); // 返回副本以防止被修改
}
/**
* 获取当前题目的索引.
*
* @return 当前题目索引
*/
public int getCurrentQuestionIndex() {
return currentQuestionIndex;
}
/**
* 为当前题目记录用户的答案.
*
* @param answerIndex 选中答案的索引
*/
public void setAnswer(int answerIndex) {
if (currentQuestionIndex < 0 || currentQuestionIndex >= questions.size()) {
throw new IllegalStateException("No valid question at current index");
}
int optionCount = questions.get(currentQuestionIndex).getOptions().size();
if (answerIndex < 0 || answerIndex >= optionCount) {
throw new IllegalArgumentException("Invalid answer index");
}
userAnswers.set(currentQuestionIndex, answerIndex);
}
/**
* 跳转到下一题.
*
* @return 若成功跳转则返回 true若已是最后一题则返回 false
*/
public boolean goToNextQuestion() {
if (currentQuestionIndex < questions.size() - 1) {
currentQuestionIndex++;
return true;
}
return false;
}
/**
* 返回上一题.
*
* @return 若成功返回则返回 true若已是第一题则返回 false
*/
public boolean goToPreviousQuestion() {
if (currentQuestionIndex > 0) {
currentQuestionIndex--;
return true;
}
return false;
}
/**
* 检查考试是否完成(所有题目已作答或到达最后一题).
*
* @return 若考试已完成则返回 true否则返回 false
*/
public boolean isComplete() {
return userAnswers.stream().allMatch(answer -> answer != -1);
}
/**
* 获取当前题目.
*
* @return 当前的测验题
*/
public QuizQuestion getCurrentQuestion() {
if (currentQuestionIndex < 0 || currentQuestionIndex >= questions.size()) {
throw new IllegalStateException("No valid question at current index");
}
return questions.get(currentQuestionIndex);
}
/**
* 获取指定题目的用户答案.
*
* @param questionIndex 题目索引
* @return 用户答案的索引(未选择时为 -1
*/
public int getUserAnswer(int questionIndex) {
if (questionIndex < 0 || questionIndex >= questions.size()) {
throw new IllegalArgumentException("Question index out of bounds");
}
return userAnswers.get(questionIndex);
}
/**
* 计算得分百分比.
*
* @return 0-100 范围内的得分百分比
*/
public double calculateScore() {
int correctCount = 0;
for (int i = 0; i < questions.size(); i++) {
QuizQuestion question = questions.get(i);
int userAnswer = userAnswers.get(i);
if (userAnswer != -1 && question.isAnswerCorrect(userAnswer)) {
correctCount++;
}
}
return questions.isEmpty() ? 0.0 : (double) correctCount / questions.size() * 100.0;
}
/**
* 获取考试中的题目总数.
*
* @return 题目总数
*/
public int getTotalQuestions() {
return questions.size();
}
/**
* 检查指定题目是否已作答.
*
* @param questionIndex 题目索引
* @return 若已作答则返回 true否则返回 false
*/
public boolean hasAnswered(int questionIndex) {
if (questionIndex < 0 || questionIndex >= questions.size()) {
throw new IllegalArgumentException("Question index out of bounds");
}
return userAnswers.get(questionIndex) != -1;
}
/**
* 获取考试开始时间.
*
* @return 开始时间
*/
public LocalDateTime getStartTime() {
return startTime;
}
/**
* 获取答对的题目数量.
*
* @return 正确题目数量
*/
public int getCorrectAnswersCount() {
int correctCount = 0;
for (int i = 0; i < questions.size(); i++) {
QuizQuestion question = questions.get(i);
int userAnswer = userAnswers.get(i);
if (userAnswer != -1 && question.isAnswerCorrect(userAnswer)) {
correctCount++;
}
}
return correctCount;
}
/**
* 获取答错的题目数量.
*
* @return 错误题目数量
*/
public int getIncorrectAnswersCount() {
int totalAnswered = 0;
int correctCount = 0;
for (int i = 0; i < questions.size(); i++) {
int userAnswer = userAnswers.get(i);
if (userAnswer != -1) {
totalAnswered++;
QuizQuestion question = questions.get(i);
if (question.isAnswerCorrect(userAnswer)) {
correctCount++;
}
}
}
return totalAnswered - correctCount;
}
}