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.
242 lines
8.1 KiB
242 lines
8.1 KiB
package com.service;
|
|
|
|
|
|
import com.model.*;
|
|
import com.util.FileUtils;
|
|
import com.google.gson.Gson;
|
|
import com.google.gson.GsonBuilder;
|
|
import com.google.gson.reflect.TypeToken;
|
|
|
|
import java.io.File;
|
|
import java.io.IOException;
|
|
import java.lang.reflect.Type;
|
|
import java.text.SimpleDateFormat;
|
|
import java.util.*;
|
|
|
|
/**
|
|
* 文件IO服务
|
|
* 负责所有数据的读写操作
|
|
*/
|
|
public class FileIOService {
|
|
|
|
private static final String DATA_DIR = "data";
|
|
private static final String USERS_DIR = DATA_DIR + "/users";
|
|
private static final String HISTORY_DIR = DATA_DIR + "/history";
|
|
|
|
private static final String USERS_FILE = DATA_DIR + "/users.json";
|
|
private static final String CURRENT_USER_FILE = DATA_DIR + "/current_user.json";
|
|
|
|
private static final Gson gson = new GsonBuilder()
|
|
.setPrettyPrinting()
|
|
.setDateFormat("yyyy-MM-dd HH:mm:ss")
|
|
.create();
|
|
|
|
// ==================== 初始化 ====================
|
|
|
|
public void initDataDirectory() throws IOException {
|
|
FileUtils.createDirectoryIfNotExists(DATA_DIR);
|
|
FileUtils.createDirectoryIfNotExists(USERS_DIR);
|
|
FileUtils.createDirectoryIfNotExists(HISTORY_DIR);
|
|
|
|
if (!FileUtils.exists(USERS_FILE)) {
|
|
Map<String, List<User>> data = new HashMap<>();
|
|
data.put("users", new ArrayList<>());
|
|
FileUtils.saveAsJson(data, USERS_FILE);
|
|
}
|
|
|
|
System.out.println("✓ 数据目录初始化完成");
|
|
}
|
|
|
|
// ==================== 用户操作 ====================
|
|
|
|
public void saveUser(User user) throws IOException {
|
|
Type type = new TypeToken<Map<String, List<User>>>(){}.getType();
|
|
Map<String, List<User>> data = FileUtils.readJsonToObject(USERS_FILE, type);
|
|
|
|
List<User> users = data.get("users");
|
|
|
|
boolean found = false;
|
|
for (int i = 0; i < users.size(); i++) {
|
|
if (users.get(i).getUsername().equals(user.getUsername())) {
|
|
users.set(i, user);
|
|
found = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!found) {
|
|
users.add(user);
|
|
}
|
|
|
|
FileUtils.saveAsJson(data, USERS_FILE);
|
|
}
|
|
|
|
public List<User> loadAllUsers() throws IOException {
|
|
if (!FileUtils.exists(USERS_FILE)) {
|
|
return new ArrayList<>();
|
|
}
|
|
|
|
Type type = new TypeToken<Map<String, List<User>>>(){}.getType();
|
|
Map<String, List<User>> data = FileUtils.readJsonToObject(USERS_FILE, type);
|
|
|
|
return data.get("users");
|
|
}
|
|
|
|
public User findUserByUsername(String username) throws IOException {
|
|
List<User> users = loadAllUsers();
|
|
|
|
for (User user : users) {
|
|
if (user.getUsername().equals(username)) {
|
|
return user;
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
public boolean isUsernameExists(String username) throws IOException {
|
|
return findUserByUsername(username) != null;
|
|
}
|
|
|
|
public void saveCurrentUser(User user) throws IOException {
|
|
FileUtils.saveAsJson(user, CURRENT_USER_FILE);
|
|
}
|
|
|
|
public User loadCurrentUser() throws IOException {
|
|
if (!FileUtils.exists(CURRENT_USER_FILE)) {
|
|
return null;
|
|
}
|
|
return FileUtils.readJsonToObject(CURRENT_USER_FILE, User.class);
|
|
}
|
|
|
|
public void clearCurrentUser() {
|
|
FileUtils.deleteFile(CURRENT_USER_FILE);
|
|
}
|
|
|
|
// ==================== 答题历史操作 ====================
|
|
|
|
public void saveQuizHistory(QuizHistory history) throws IOException {
|
|
String filename = HISTORY_DIR + "/" +
|
|
sanitizeFilename(history.getUsername()) + "_" +
|
|
System.currentTimeMillis() + ".txt";
|
|
|
|
StringBuilder content = new StringBuilder();
|
|
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
|
|
|
content.append("========== 答题记录 ==========\n");
|
|
content.append("用户:").append(history.getUsername()).append("\n");
|
|
content.append("时间:").append(dateFormat.format(history.getTimestamp())).append("\n");
|
|
content.append("总分:").append(history.getScore()).append(" 分\n");
|
|
|
|
// 调用 QuizService 的业务方法计算正确数和错误数
|
|
int correctCount = calculateCorrectCount(history);
|
|
int wrongCount = history.getQuestions().size() - correctCount;
|
|
|
|
content.append("正确:").append(correctCount).append(" 题 ");
|
|
content.append("错误:").append(wrongCount).append(" 题\n");
|
|
content.append("=============================\n\n");
|
|
|
|
List<ChoiceQuestion> questions = history.getQuestions();
|
|
List<Integer> userAnswers = history.getUserAnswers();
|
|
|
|
for (int i = 0; i < questions.size(); i++) {
|
|
ChoiceQuestion q = questions.get(i);
|
|
Integer userAnswer = userAnswers.get(i);
|
|
|
|
content.append("【题目 ").append(i + 1).append("】\n");
|
|
content.append(q.getQuestionText()).append("\n");
|
|
|
|
List<?> options = q.getOptions();
|
|
for (int j = 0; j < options.size(); j++) {
|
|
content.append((char)('A' + j)).append(". ")
|
|
.append(options.get(j)).append(" ");
|
|
}
|
|
content.append("\n");
|
|
|
|
int correctIndex = getCorrectAnswerIndex(q);
|
|
content.append("正确答案:").append((char)('A' + correctIndex)).append("\n");
|
|
|
|
content.append("用户答案:");
|
|
if (userAnswer != null) {
|
|
content.append((char)('A' + userAnswer));
|
|
} else {
|
|
content.append("未作答");
|
|
}
|
|
content.append("\n");
|
|
|
|
boolean isCorrect = (userAnswer != null && userAnswer == correctIndex);
|
|
content.append("结果:").append(isCorrect ? "✓ 正确" : "✗ 错误").append("\n\n");
|
|
}
|
|
|
|
FileUtils.writeStringToFile(filename, content.toString());
|
|
}
|
|
|
|
public List<String> getHistoryQuestions() throws IOException {
|
|
List<String> historyQuestions = new ArrayList<>();
|
|
File[] files = FileUtils.listFiles(HISTORY_DIR);
|
|
|
|
Arrays.sort(files, (f1, f2) -> Long.compare(f2.lastModified(), f1.lastModified()));
|
|
|
|
int count = 0;
|
|
for (File file : files) {
|
|
if (count++ >= 20) break;
|
|
|
|
try {
|
|
String content = FileUtils.readFileToString(file.getAbsolutePath());
|
|
String[] lines = content.split("\n");
|
|
|
|
for (int i = 0; i < lines.length; i++) {
|
|
if (lines[i].startsWith("【题目")) {
|
|
if (i + 1 < lines.length) {
|
|
String questionText = lines[i + 1].trim();
|
|
if (!questionText.isEmpty()) {
|
|
historyQuestions.add(questionText);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} catch (IOException e) {
|
|
System.err.println("读取历史文件失败: " + file.getName());
|
|
}
|
|
}
|
|
|
|
return historyQuestions;
|
|
}
|
|
|
|
// ==================== 业务逻辑方法(从 Model 移过来)====================
|
|
|
|
/**
|
|
* 计算答题历史的正确数
|
|
*/
|
|
private int calculateCorrectCount(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 && userAnswer == getCorrectAnswerIndex(question)) {
|
|
count++;
|
|
}
|
|
}
|
|
return count;
|
|
}
|
|
|
|
/**
|
|
* 获取题目的正确答案索引
|
|
*/
|
|
private int getCorrectAnswerIndex(ChoiceQuestion question) {
|
|
return question.getOptions().indexOf(question.getCorrectAnswer());
|
|
}
|
|
|
|
// ==================== 工具方法 ====================
|
|
|
|
private String sanitizeFilename(String filename) {
|
|
if (filename == null) {
|
|
return "unknown";
|
|
}
|
|
return filename.replaceAll("[\\\\/:*?\"<>|]", "_");
|
|
}
|
|
} |