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.
PAIR/src/main/java/com/service/QuizService.java

445 lines
13 KiB

package com.service;
import com.model.*;
import com.service.question_generator.QuestionFactoryManager;
import java.io.IOException;
import java.util.*;
/**
* 答题服务(包含所有答题相关业务逻辑)
*/
public class QuizService {
private final FileIOService fileIOService;
private final UserService userService;
private List<ChoiceQuestion> currentQuestions;
private List<Integer> userAnswers;
private int currentQuestionIndex;
private int answerNumber;
// ==================== 构造方法 ====================
public QuizService() {
this.fileIOService = new FileIOService();
this.userService = new UserService(fileIOService);
this.currentQuestions = new ArrayList<>();
this.userAnswers = new ArrayList<>();
this.currentQuestionIndex = 0;
}
public QuizService(FileIOService fileIOService, UserService userService) {
this.fileIOService = fileIOService;
this.userService = userService;
this.currentQuestions = new ArrayList<>();
this.userAnswers = new ArrayList<>();
this.currentQuestionIndex = 0;
}
// ==================== 答题会话管理 ====================
public void startNewQuiz(User user, int questionCount) throws IOException {
currentQuestions.clear();
userAnswers.clear();
currentQuestionIndex = 0;
Set<String> historyQuestions = getRecentHistoryQuestions();
Grade grade = user.getGrade();
currentQuestions = QuestionFactoryManager.generateQuestions(
grade, questionCount, historyQuestions
);
for (int i = 0; i < currentQuestions.size(); i++) {
userAnswers.add(null);
}
System.out.println("✓ 已生成 " + currentQuestions.size() + " 道 " + grade + " 题目");
}
private Set<String> getRecentHistoryQuestions() throws IOException {
List<String> historyList = fileIOService.getHistoryQuestions();
return new HashSet<>(historyList);
}
// ==================== 题目访问 ====================
public ChoiceQuestion getCurrentQuestion() {
if (currentQuestionIndex >= 0 && currentQuestionIndex < currentQuestions.size()) {
return currentQuestions.get(currentQuestionIndex);
}
return null;
}
public ChoiceQuestion getQuestion(int index) {
if (index >= 0 && index < currentQuestions.size()) {
return currentQuestions.get(index);
}
return null;
}
public List<ChoiceQuestion> getAllQuestions() {
return new ArrayList<>(currentQuestions);
}
public boolean nextQuestion() {
if (currentQuestionIndex < currentQuestions.size() - 1) {
currentQuestionIndex++;
return true;
}
return false;
}
public boolean previousQuestion() {
if (currentQuestionIndex > 0) {
currentQuestionIndex--;
return true;
}
return false;
}
public boolean goToQuestion(int index) {
if (index >= 0 && index < currentQuestions.size()) {
currentQuestionIndex = index;
return true;
}
return false;
}
public int getCurrentQuestionIndex() {
return currentQuestionIndex;
}
public int getTotalQuestions() {
return currentQuestions.size();
}
public boolean isFirstQuestion() {
return currentQuestionIndex == 0;
}
public boolean isLastQuestion() {
return currentQuestionIndex == currentQuestions.size() - 1;
}
// ==================== 答题操作 ====================
public boolean submitAnswer(int questionIndex, int optionIndex) {
if (questionIndex < 0 || questionIndex >= currentQuestions.size()) {
throw new IllegalArgumentException("题目索引无效: " + questionIndex);
}
ChoiceQuestion question = currentQuestions.get(questionIndex);
if (optionIndex < 0 || optionIndex >= question.getOptions().size()) {
throw new IllegalArgumentException("选项索引无效: " + optionIndex);
}
userAnswers.set(questionIndex, optionIndex);
return checkAnswer(question, optionIndex);
}
public boolean submitCurrentAnswer(int optionIndex) {
return submitAnswer(currentQuestionIndex, optionIndex);
}
public Integer getUserAnswer(int questionIndex) {
if (questionIndex >= 0 && questionIndex < userAnswers.size()) {
return userAnswers.get(questionIndex);
}
return null;
}
public List<Integer> getAllUserAnswers() {
return new ArrayList<>(userAnswers);
}
public boolean isAllAnswered() {
for (Integer answer : userAnswers) {
if (answer == null) {
return false;
}
}
return true;
}
public int getAnsweredCount() {
int count = 0;
for (Integer answer : userAnswers) {
if (answer != null) {
count++;
}
}
return count;
}
public boolean isAnswered(int questionIndex) {
return userAnswers.get(questionIndex) != null ;
}
// ==================== 成绩计算 ====================
public QuizResult calculateResult() {
int correctCount = 0;
int totalQuestions = currentQuestions.size();
for (int i = 0; i < totalQuestions; i++) {
ChoiceQuestion question = currentQuestions.get(i);
Integer userAnswer = userAnswers.get(i);
if (userAnswer != null && checkAnswer(question, userAnswer)) {
correctCount++;
}
}
int wrongCount = totalQuestions - correctCount;
int score = totalQuestions > 0 ? (correctCount * 100) / totalQuestions : 0;
return new QuizResult(totalQuestions, correctCount, wrongCount, score);
}
public List<Integer> getCorrectQuestionIndices() {
List<Integer> correctIndices = new ArrayList<>();
for (int i = 0; i < currentQuestions.size(); i++) {
ChoiceQuestion question = currentQuestions.get(i);
Integer userAnswer = userAnswers.get(i);
if (userAnswer != null && checkAnswer(question, userAnswer)) {
correctIndices.add(i);
}
}
return correctIndices;
}
public List<Integer> getWrongQuestionIndices() {
List<Integer> wrongIndices = new ArrayList<>();
for (int i = 0; i < currentQuestions.size(); i++) {
ChoiceQuestion question = currentQuestions.get(i);
Integer userAnswer = userAnswers.get(i);
if (userAnswer != null && !checkAnswer(question, userAnswer)) {
wrongIndices.add(i);
}
}
return wrongIndices;
}
public List<Integer> getUnansweredQuestionIndices() {
List<Integer> unansweredIndices = new ArrayList<>();
for (int i = 0; i < userAnswers.size(); i++) {
if (userAnswers.get(i) == null) {
unansweredIndices.add(i);
}
}
return unansweredIndices;
}
// ==================== 业务逻辑方法(从 Model 移过来)====================
/**
* 检查答案是否正确
*/
public boolean checkAnswer(ChoiceQuestion question, int userAnswerIndex) {
if (userAnswerIndex < 0 || userAnswerIndex >= question.getOptions().size()) {
return false;
}
Object userAnswer = question.getOptions().get(userAnswerIndex);
return question.getCorrectAnswer().equals(userAnswer);
}
/**
* 获取题目的正确答案索引
*/
public int getCorrectAnswerIndex(ChoiceQuestion question) {
return question.getOptions().indexOf(question.getCorrectAnswer());
}
/**
* 获取正确答案的字母形式
*/
public String getCorrectAnswerLetter(ChoiceQuestion question) {
int index = getCorrectAnswerIndex(question);
if (index >= 0 && index < 4) {
return String.valueOf((char)('A' + index));
}
return "未知";
}
/**
* 获取答题结果的正确率
*/
public double getAccuracy(QuizResult result) {
if (result.getTotalQuestions() == 0) {
return 0.0;
}
return (result.getCorrectCount() * 100.0) / result.getTotalQuestions();
}
/**
* 判断是否及格
*/
public boolean isPassed(QuizResult result) {
return result.getScore() >= 60;
}
/**
* 获取评级
*/
public String getGrade(QuizResult result) {
int score = result.getScore();
if (score >= 90) return "优秀";
if (score >= 80) return "良好";
if (score >= 70) return "中等";
if (score >= 60) return "及格";
return "不及格";
}
/**
* 计算答题历史的正确数
*/
public int getCorrectCount(QuizHistory history) {
int count = 0;
List<ChoiceQuestion> questions = history.getQuestions();
List<Integer> userAnswers = history.getUserAnswers();
for (int i = 0; i < questions.size(); i++) {
ChoiceQuestion question = questions.get(i);
Integer userAnswer = userAnswers.get(i);
if (userAnswer != null && checkAnswer(question, userAnswer)) {
count++;
}
}
return count;
}
/**
* 计算答题历史的错误数
*/
public int getWrongCount(QuizHistory history) {
return history.getQuestions().size() - getCorrectCount(history);
}
// ==================== 格式化输出 ====================
public String formatQuestion(ChoiceQuestion question) {
StringBuilder sb = new StringBuilder();
sb.append(question.getQuestionText()).append("\n");
List<?> options = question.getOptions();
for (int i = 0; i < options.size(); i++) {
sb.append((char)('A' + i)).append(". ").append(options.get(i));
if (i % 2 == 1) {
sb.append("\n");
} else {
sb.append(" ");
}
}
return sb.toString();
}
public String formatCurrentQuestion() {
ChoiceQuestion question = getCurrentQuestion();
if (question == null) {
return "没有可用的题目";
}
StringBuilder sb = new StringBuilder();
sb.append("第 ").append(currentQuestionIndex + 1)
.append(" / ").append(currentQuestions.size()).append(" 题\n");
sb.append(formatQuestion(question));
return sb.toString();
}
public String formatQuestionWithAnswer(ChoiceQuestion question, Integer userAnswerIndex) {
StringBuilder sb = new StringBuilder();
sb.append(question.getQuestionText()).append("\n");
List<?> options = question.getOptions();
int correctIndex = getCorrectAnswerIndex(question);
for (int i = 0; i < options.size(); i++) {
sb.append((char)('A' + i)).append(". ").append(options.get(i));
if (i == correctIndex) {
sb.append(" ✓");
}
if (userAnswerIndex != null && i == userAnswerIndex) {
boolean isCorrect = checkAnswer(question, userAnswerIndex);
sb.append(isCorrect ? " [您的答案:正确]" : " [您的答案:错误]");
}
if (i % 2 == 1) {
sb.append("\n");
} else {
sb.append(" ");
}
}
return sb.toString();
}
public String formatResult(QuizResult result) {
StringBuilder sb = new StringBuilder();
sb.append("\n========== 答题结束 ==========\n");
sb.append("总题数:").append(result.getTotalQuestions()).append(" 题\n");
sb.append("正确:").append(result.getCorrectCount()).append(" 题\n");
sb.append("错误:").append(result.getWrongCount()).append(" 题\n");
sb.append("得分:").append(result.getScore()).append(" 分\n");
sb.append("正确率:").append(String.format("%.1f%%", getAccuracy(result))).append("\n");
sb.append("评级:").append(getGrade(result)).append("\n");
sb.append("===============================\n");
return sb.toString();
}
// ==================== 数据持久化 ====================
public void saveQuizHistory(User user) throws IOException {
QuizResult result = calculateResult();
QuizHistory history = new QuizHistory(
user.getUsername(),
new Date(),
currentQuestions,
userAnswers,
result.getScore()
);
fileIOService.saveQuizHistory(history);
userService.updateUserStatistics(user, result.getScore());
System.out.println("✓ 答题记录已保存");
}
// ==================== Getters ====================
public int getAnswerNumber() {
return answerNumber;
}
public void setAnswerNumber(int answerNumber) {
this.answerNumber = answerNumber;
}
public List<ChoiceQuestion> getCurrentQuestions() {
return new ArrayList<>(currentQuestions);
}
public List<Integer> getUserAnswers() {
return new ArrayList<>(userAnswers);
}
}