From fa964125bca0cc1fb2e38d88e76c0d958194bccc Mon Sep 17 00:00:00 2001
From: bx <2936213174@qq.com>
Date: Fri, 3 Oct 2025 14:16:15 +0800
Subject: [PATCH 1/5] =?UTF-8?q?=E7=AC=AC=E4=B8=80=E7=89=88?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.gitignore | 38 ++++++
.idea/.gitignore | 8 ++
.idea/encodings.xml | 7 ++
.idea/misc.xml | 14 +++
.idea/vcs.xml | 6 +
pom.xml | 84 +++++++++++++
src/main/java/com/bx/MathQuiz/Main.java | 4 +
.../java/com/bx/model/ChoiceQuestion.java | 117 ++++++++++++++++++
src/main/java/com/bx/model/Grade.java | 49 ++++++++
src/main/java/com/bx/model/User.java | 95 ++++++++++++++
src/main/java/com/bx/util/RandomUtils.java | 83 +++++++++++++
11 files changed, 505 insertions(+)
create mode 100644 .gitignore
create mode 100644 .idea/.gitignore
create mode 100644 .idea/encodings.xml
create mode 100644 .idea/misc.xml
create mode 100644 .idea/vcs.xml
create mode 100644 pom.xml
create mode 100644 src/main/java/com/bx/MathQuiz/Main.java
create mode 100644 src/main/java/com/bx/model/ChoiceQuestion.java
create mode 100644 src/main/java/com/bx/model/Grade.java
create mode 100644 src/main/java/com/bx/model/User.java
create mode 100644 src/main/java/com/bx/util/RandomUtils.java
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..5ff6309
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,38 @@
+target/
+!.mvn/wrapper/maven-wrapper.jar
+!**/src/main/**/target/
+!**/src/test/**/target/
+
+### IntelliJ IDEA ###
+.idea/modules.xml
+.idea/jarRepositories.xml
+.idea/compiler.xml
+.idea/libraries/
+*.iws
+*.iml
+*.ipr
+
+### Eclipse ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+build/
+!**/src/main/**/build/
+!**/src/test/**/build/
+
+### VS Code ###
+.vscode/
+
+### Mac OS ###
+.DS_Store
\ No newline at end of file
diff --git a/.idea/.gitignore b/.idea/.gitignore
new file mode 100644
index 0000000..35410ca
--- /dev/null
+++ b/.idea/.gitignore
@@ -0,0 +1,8 @@
+# 默认忽略的文件
+/shelf/
+/workspace.xml
+# 基于编辑器的 HTTP 客户端请求
+/httpRequests/
+# Datasource local storage ignored files
+/dataSources/
+/dataSources.local.xml
diff --git a/.idea/encodings.xml b/.idea/encodings.xml
new file mode 100644
index 0000000..aa00ffa
--- /dev/null
+++ b/.idea/encodings.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 0000000..fdc35ea
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 0000000..94a25f7
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..dc0b01f
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,84 @@
+
+
+ 4.0.0
+
+ com.mathquiz
+ MathQuizApp
+ 1.0.0
+ jar
+
+ Math Quiz Application
+ 小初高数学学习软件 - Swing版本
+
+
+ UTF-8
+ 21
+ 21
+
+
+
+
+
+ com.google.code.gson
+ gson
+ 2.10.1
+
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ 3.11.0
+
+ 17
+ 17
+ UTF-8
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-jar-plugin
+ 3.3.0
+
+
+
+ com.mathquiz.Main
+ true
+
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-shade-plugin
+ 3.5.1
+
+
+ package
+
+ shade
+
+
+
+
+ com.mathquiz.Main
+
+
+ MathQuizApp
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/main/java/com/bx/MathQuiz/Main.java b/src/main/java/com/bx/MathQuiz/Main.java
new file mode 100644
index 0000000..17c5761
--- /dev/null
+++ b/src/main/java/com/bx/MathQuiz/Main.java
@@ -0,0 +1,4 @@
+package com.bx.MathQuiz;
+
+public class Main {
+}
diff --git a/src/main/java/com/bx/model/ChoiceQuestion.java b/src/main/java/com/bx/model/ChoiceQuestion.java
new file mode 100644
index 0000000..bc52c92
--- /dev/null
+++ b/src/main/java/com/bx/model/ChoiceQuestion.java
@@ -0,0 +1,117 @@
+package com.bx.model;
+
+import java.util.List;
+
+/**
+ * 选择题数据模型
+ * 包含题目内容、正确答案、四个选项
+ */
+public class ChoiceQuestion {
+ private String questionText; // 题目文本,如 "3 + 5"
+ private double correctAnswer; // 正确答案
+ private List options; // 四个选项(包含正确答案)
+ private Grade grade; // 所属学段
+
+ private int correctOptionIndex; // 正确答案在选项中的索引(0-3)
+
+ /**
+ * 无参构造函数
+ */
+ public ChoiceQuestion() {
+ }
+
+ /**
+ * 完整构造函数
+ */
+ public ChoiceQuestion(String questionText, double correctAnswer, List options, Grade grade) {
+ this.questionText = questionText;
+ this.correctAnswer = correctAnswer;
+ this.options = options;
+ this.grade = grade;
+
+ // 自动找到正确答案的索引
+ this.correctOptionIndex = findCorrectOptionIndex();
+ }
+
+ /**
+ * 查找正确答案在选项中的位置
+ */
+ private int findCorrectOptionIndex() {
+ for (int i = 0; i < options.size(); i++) {
+ if (Math.abs(options.get(i) - correctAnswer) < 0.01) {
+ return i;
+ }
+ }
+ return -1; // 理论上不会发生
+ }
+
+ /**
+ * 检查用户选择的选项是否正确
+ * @param optionIndex 用户选择的选项索引(0-3)
+ * @return true表示正确
+ */
+ public boolean checkAnswer(int optionIndex) {
+ return optionIndex == correctOptionIndex;
+ }
+
+ /**
+ * 检查用户输入的答案值是否正确
+ * @param answer 用户输入的答案值
+ * @return true表示正确
+ */
+ public boolean checkAnswerValue(double answer) {
+ return Math.abs(answer - correctAnswer) < 0.01;
+ }
+
+ // ========== Getter和Setter方法 ==========
+
+ public String getQuestionText() {
+ return questionText;
+ }
+
+ public void setQuestionText(String questionText) {
+ this.questionText = questionText;
+ }
+
+ public double getCorrectAnswer() {
+ return correctAnswer;
+ }
+
+ public void setCorrectAnswer(double correctAnswer) {
+ this.correctAnswer = correctAnswer;
+ }
+
+ public List getOptions() {
+ return options;
+ }
+
+ public void setOptions(List options) {
+ this.options = options;
+ this.correctOptionIndex = findCorrectOptionIndex();
+ }
+
+ public Grade getGrade() {
+ return grade;
+ }
+
+ public void setGrade(Grade grade) {
+ this.grade = grade;
+ }
+
+ public int getCorrectOptionIndex() {
+ return correctOptionIndex;
+ }
+
+ public void setCorrectOptionIndex(int correctOptionIndex) {
+ this.correctOptionIndex = correctOptionIndex;
+ }
+
+ @Override
+ public String toString() {
+ return "ChoiceQuestion{" +
+ "questionText='" + questionText + '\'' +
+ ", correctAnswer=" + correctAnswer +
+ ", grade=" + grade +
+ '}';
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/bx/model/Grade.java b/src/main/java/com/bx/model/Grade.java
new file mode 100644
index 0000000..8f878b2
--- /dev/null
+++ b/src/main/java/com/bx/model/Grade.java
@@ -0,0 +1,49 @@
+package com.bx.model;
+
+/**
+ * 学段枚举类
+ * 定义三个学段:小学、初中、高中
+ */
+public enum Grade {
+ ELEMENTARY("小学"),
+ MIDDLE("初中"),
+ HIGH("高中");
+
+ private final String displayName;
+
+ Grade(String displayName) {
+ this.displayName = displayName;
+ }
+
+ public String getDisplayName() {
+ return displayName;
+ }
+
+ //根据显示名称查找对应的枚举值
+ public static Grade fromDisplayName(String displayName) {
+ for (Grade grade : values()) {
+ if (grade.displayName.equals(displayName)) {
+ return grade;
+ }
+ }
+ throw new IllegalArgumentException("未知学段: " + displayName);
+ }
+
+ /**
+ * 获取所有学段的显示名称数组
+ * @return ["小学", "初中", "高中"]
+ */
+ public static String[] getDisplayNames() {
+ Grade[] grades = values();
+ String[] names = new String[grades.length];
+ for (int i = 0; i < grades.length; i++) {
+ names[i] = grades[i].displayName;
+ }
+ return names;
+ }
+
+ @Override
+ public String toString() {
+ return displayName;
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/bx/model/User.java b/src/main/java/com/bx/model/User.java
new file mode 100644
index 0000000..1557f2f
--- /dev/null
+++ b/src/main/java/com/bx/model/User.java
@@ -0,0 +1,95 @@
+package com.bx.model;
+
+public class User {
+ private String username; // 用户名,格式:小学-张三
+ private String password; // 密码(加密后)
+ private Grade grade; // 学段
+ private String email; // 邮箱
+ private String registrationCode; // 注册码(明文保存,用于用户查看)
+ private long createdTime; // 创建时间戳
+ private long lastLoginTime; // 最后登录时间戳
+
+ /**
+ * 无参构造函数(Gson反序列化需要)
+ */
+ public User() {
+ }
+
+ /**
+ * 完整构造函数
+ */
+ public User(String username, String password, Grade grade, String email) {
+ this.username = username;
+ this.password = password;
+ this.grade = grade;
+ this.email = email;
+ this.createdTime = System.currentTimeMillis();
+ }
+
+ // ========== Getter和Setter方法 ==========
+
+ public String getUsername() {
+ return username;
+ }
+
+ public void setUsername(String username) {
+ this.username = username;
+ }
+
+ public String getPassword() {
+ return password;
+ }
+
+ public void setPassword(String password) {
+ this.password = password;
+ }
+
+ public Grade getGrade() {
+ return grade;
+ }
+
+ public void setGrade(Grade grade) {
+ this.grade = grade;
+ }
+
+ public String getEmail() {
+ return email;
+ }
+
+ public void setEmail(String email) {
+ this.email = email;
+ }
+
+ public String getRegistrationCode() {
+ return registrationCode;
+ }
+
+ public void setRegistrationCode(String registrationCode) {
+ this.registrationCode = registrationCode;
+ }
+
+ public long getCreatedTime() {
+ return createdTime;
+ }
+
+ public void setCreatedTime(long createdTime) {
+ this.createdTime = createdTime;
+ }
+
+ public long getLastLoginTime() {
+ return lastLoginTime;
+ }
+
+ public void setLastLoginTime(long lastLoginTime) {
+ this.lastLoginTime = lastLoginTime;
+ }
+
+ @Override
+ public String toString() {
+ return "User{" +
+ "username='" + username + '\'' +
+ ", grade=" + grade +
+ ", email='" + email + '\'' +
+ '}';
+ }
+}
diff --git a/src/main/java/com/bx/util/RandomUtils.java b/src/main/java/com/bx/util/RandomUtils.java
new file mode 100644
index 0000000..8735980
--- /dev/null
+++ b/src/main/java/com/bx/util/RandomUtils.java
@@ -0,0 +1,83 @@
+package com.bx.util;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Random;
+
+//各种随机数生成
+public class RandomUtils {
+ private static final Random random = new Random();
+
+
+ //生成[min, max]范围内的随机整数(包含边界)
+ public static int nextInt(int min, int max) {
+ if (min > max) {
+ throw new IllegalArgumentException("min不能大于max");
+ }
+ return min + random.nextInt(max - min + 1);
+ }
+
+
+ //从数组中随机选择一个元素(模板类)
+ public static T randomChoice(T[] array) {
+ if (array == null || array.length == 0) {
+ throw new IllegalArgumentException("数组不能为空");
+ }
+ return array[random.nextInt(array.length)];
+ }
+
+ /**
+ * 从列表中随机选择一个元素
+ * @param list 列表
+ * @return 随机选中的元素
+ */
+ public static T randomChoice(List list) {
+ if (list == null || list.isEmpty()) {
+ throw new IllegalArgumentException("列表不能为空");
+ }
+ return list.get(random.nextInt(list.size()));
+ }
+
+ /**
+ * 打乱列表顺序
+ * @param list 要打乱的列表
+ */
+ public static void shuffle(List list) {
+ Collections.shuffle(list, random);
+ }
+
+ /**
+ * 生成指定范围内的随机双精度浮点数
+ * @param min 最小值
+ * @param max 最大值
+ * @return 随机浮点数
+ */
+ public static double nextDouble(double min, double max) {
+ if (min > max) {
+ throw new IllegalArgumentException("min不能大于max");
+ }
+ return min + (max - min) * random.nextDouble();
+ }
+
+ /**
+ * 生成随机布尔值
+ * @return true或false
+ */
+ public static boolean nextBoolean() {
+ return random.nextBoolean();
+ }
+
+ /**
+ * 按概率返回true
+ * @param probability 概率值(0.0 - 1.0)
+ * @return true或false
+ *
+ * 示例:probability(0.7) 有70%概率返回true
+ */
+ public static boolean probability(double probability) {
+ if (probability < 0.0 || probability > 1.0) {
+ throw new IllegalArgumentException("概率必须在0.0-1.0之间");
+ }
+ return random.nextDouble() < probability;
+ }
+}
\ No newline at end of file
--
2.34.1
From 06a4612ad6066a0a457209013cf4b0d2a3f8661b Mon Sep 17 00:00:00 2001
From: bx <2936213174@qq.com>
Date: Fri, 3 Oct 2025 14:54:13 +0800
Subject: [PATCH 2/5] =?UTF-8?q?=E7=AC=AC=E4=B8=80=E7=89=88?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/main/java/com/MathQuiz/Main.java | 4 +
src/main/java/com/bx/MathQuiz/Main.java | 4 -
.../com/{bx => }/model/ChoiceQuestion.java | 2 +-
src/main/java/com/{bx => }/model/Grade.java | 2 +-
src/main/java/com/{bx => }/model/User.java | 2 +-
src/main/java/com/util/EmailUtil.java | 109 +++++++++++++++++
src/main/java/com/util/FileUtils.java | 111 ++++++++++++++++++
src/main/java/com/util/PasswordValidator.java | 102 ++++++++++++++++
.../java/com/{bx => }/util/RandomUtils.java | 32 ++---
src/test/java/TestMain.java | 2 +
10 files changed, 340 insertions(+), 30 deletions(-)
create mode 100644 src/main/java/com/MathQuiz/Main.java
delete mode 100644 src/main/java/com/bx/MathQuiz/Main.java
rename src/main/java/com/{bx => }/model/ChoiceQuestion.java (99%)
rename src/main/java/com/{bx => }/model/Grade.java (98%)
rename src/main/java/com/{bx => }/model/User.java (99%)
create mode 100644 src/main/java/com/util/EmailUtil.java
create mode 100644 src/main/java/com/util/FileUtils.java
create mode 100644 src/main/java/com/util/PasswordValidator.java
rename src/main/java/com/{bx => }/util/RandomUtils.java (75%)
create mode 100644 src/test/java/TestMain.java
diff --git a/src/main/java/com/MathQuiz/Main.java b/src/main/java/com/MathQuiz/Main.java
new file mode 100644
index 0000000..49ac2f4
--- /dev/null
+++ b/src/main/java/com/MathQuiz/Main.java
@@ -0,0 +1,4 @@
+package com.MathQuiz;
+
+public class Main {
+}
diff --git a/src/main/java/com/bx/MathQuiz/Main.java b/src/main/java/com/bx/MathQuiz/Main.java
deleted file mode 100644
index 17c5761..0000000
--- a/src/main/java/com/bx/MathQuiz/Main.java
+++ /dev/null
@@ -1,4 +0,0 @@
-package com.bx.MathQuiz;
-
-public class Main {
-}
diff --git a/src/main/java/com/bx/model/ChoiceQuestion.java b/src/main/java/com/model/ChoiceQuestion.java
similarity index 99%
rename from src/main/java/com/bx/model/ChoiceQuestion.java
rename to src/main/java/com/model/ChoiceQuestion.java
index bc52c92..b71c59a 100644
--- a/src/main/java/com/bx/model/ChoiceQuestion.java
+++ b/src/main/java/com/model/ChoiceQuestion.java
@@ -1,4 +1,4 @@
-package com.bx.model;
+package com.model;
import java.util.List;
diff --git a/src/main/java/com/bx/model/Grade.java b/src/main/java/com/model/Grade.java
similarity index 98%
rename from src/main/java/com/bx/model/Grade.java
rename to src/main/java/com/model/Grade.java
index 8f878b2..7de066d 100644
--- a/src/main/java/com/bx/model/Grade.java
+++ b/src/main/java/com/model/Grade.java
@@ -1,4 +1,4 @@
-package com.bx.model;
+package com.model;
/**
* 学段枚举类
diff --git a/src/main/java/com/bx/model/User.java b/src/main/java/com/model/User.java
similarity index 99%
rename from src/main/java/com/bx/model/User.java
rename to src/main/java/com/model/User.java
index 1557f2f..eadfd17 100644
--- a/src/main/java/com/bx/model/User.java
+++ b/src/main/java/com/model/User.java
@@ -1,4 +1,4 @@
-package com.bx.model;
+package com.model;
public class User {
private String username; // 用户名,格式:小学-张三
diff --git a/src/main/java/com/util/EmailUtil.java b/src/main/java/com/util/EmailUtil.java
new file mode 100644
index 0000000..ff915ac
--- /dev/null
+++ b/src/main/java/com/util/EmailUtil.java
@@ -0,0 +1,109 @@
+package com.util;
+
+/**
+ * 邮件工具类
+ * 用于发送注册码邮件(可选功能)
+ * 注意:当前项目需求中,注册码是直接显示在界面上的,
+ * 不需要发送邮件,所以这个类暂时保留为空实现。
+ * 如果将来需要发送邮件,可以使用JavaMail库实现。
+ */
+public class EmailUtil {
+
+ /**
+ * 发送注册码邮件(预留接口)
+ * @param toEmail 收件人邮箱
+ * @param registrationCode 注册码
+ * @return true表示发送成功
+ */
+ public static boolean sendRegistrationCode(String toEmail, String registrationCode) {
+ // TODO: 暂不实现邮件发送功能
+ // 原因:项目需求是直接在界面显示注册码,不需要发邮件
+
+ System.out.println("【模拟】发送注册码邮件");
+ System.out.println("收件人: " + toEmail);
+ System.out.println("注册码: " + registrationCode);
+
+ return true;
+ }
+
+ /**
+ * 发送密码重置邮件(预留接口)
+ * @param toEmail 收件人邮箱
+ * @param newPassword 新密码
+ * @return true表示发送成功
+ */
+ public static boolean sendPasswordReset(String toEmail, String newPassword) {
+ // TODO: 将来如果需要"找回密码"功能,可以在这里实现
+
+ System.out.println("【模拟】发送密码重置邮件");
+ System.out.println("收件人: " + toEmail);
+ System.out.println("新密码: " + newPassword);
+
+ return true;
+ }
+
+ /**
+ * 验证邮箱格式
+ * @param email 邮箱地址
+ * @return true表示格式正确
+ */
+ public static boolean isValidEmail(String email) {
+ if (email == null || email.trim().isEmpty()) {
+ return false;
+ }
+
+ // 简单的邮箱格式验证
+ String emailRegex = "^[A-Za-z0-9+_.-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}$";
+ return email.matches(emailRegex);
+ }
+}
+
+/*
+ * 如果将来需要真正实现邮件发送,可以参考以下代码:
+ *
+ * 1. 在pom.xml添加依赖:
+ *
+ * javax.mail
+ * javax.mail-api
+ * 1.6.2
+ *
+ *
+ * com.sun.mail
+ * javax.mail
+ * 1.6.2
+ *
+ *
+ * 2. 实现代码示例:
+ *
+ * import javax.mail.*;
+ * import javax.mail.internet.*;
+ * import java.util.Properties;
+ *
+ * public static boolean sendEmail(String toEmail, String subject, String content) {
+ * try {
+ * Properties props = new Properties();
+ * props.put("mail.smtp.auth", "true");
+ * props.put("mail.smtp.starttls.enable", "true");
+ * props.put("mail.smtp.host", "smtp.qq.com");
+ * props.put("mail.smtp.port", "587");
+ *
+ * Session session = Session.getInstance(props, new Authenticator() {
+ * protected PasswordAuthentication getPasswordAuthentication() {
+ * return new PasswordAuthentication("your-email@qq.com", "your-password");
+ * }
+ * });
+ *
+ * Message message = new MimeMessage(session);
+ * message.setFrom(new InternetAddress("your-email@qq.com"));
+ * message.setRecipients(Message.RecipientType.TO, InternetAddress.parse(toEmail));
+ * message.setSubject(subject);
+ * message.setText(content);
+ *
+ * Transport.send(message);
+ * return true;
+ * } catch (Exception e) {
+ * e.printStackTrace();
+ * return false;
+ * }
+ * }
+ */
\ No newline at end of file
diff --git a/src/main/java/com/util/FileUtils.java b/src/main/java/com/util/FileUtils.java
new file mode 100644
index 0000000..d4daf9e
--- /dev/null
+++ b/src/main/java/com/util/FileUtils.java
@@ -0,0 +1,111 @@
+package com.util;
+
+import java.io.*;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.*;
+
+/**
+ * 文件操作工具类
+ * 提供文件读写、目录创建等常用操作
+ */
+public class FileUtils {
+
+ /**
+ * 读取文件内容为字符串
+ * @param filePath 文件路径
+ * @return 文件内容
+ * @throws IOException 读取失败时抛出
+ */
+ public static String readFileToString(String filePath) throws IOException {
+ return Files.readString(Paths.get(filePath), StandardCharsets.UTF_8);
+ }
+
+ /**
+ * 写入字符串到文件
+ * @param filePath 文件路径
+ * @param content 要写入的内容
+ * @throws IOException 写入失败时抛出
+ */
+ public static void writeStringToFile(String filePath, String content) throws IOException {
+ Files.writeString(Paths.get(filePath), content, StandardCharsets.UTF_8);
+ }
+
+ /**
+ * 创建目录(如果不存在)
+ * @param dirPath 目录路径
+ * @throws IOException 创建失败时抛出
+ */
+ public static void createDirectoryIfNotExists(String dirPath) throws IOException {
+ Path path = Paths.get(dirPath);
+ if (!Files.exists(path)) {
+ Files.createDirectories(path);
+ }
+ }
+
+ /**
+ * 检查文件是否存在
+ * @param filePath 文件路径
+ * @return true表示存在
+ */
+ public static boolean exists(String filePath) {
+ return Files.exists(Paths.get(filePath));
+ }
+
+ /**
+ * 删除文件
+ * @param filePath 文件路径
+ * @return true表示删除成功
+ */
+ public static boolean deleteFile(String filePath) {
+ try {
+ return Files.deleteIfExists(Paths.get(filePath));
+ } catch (IOException e) {
+ e.printStackTrace();
+ return false;
+ }
+ }
+
+ /**
+ * 获取目录下所有文件
+ * @param dirPath 目录路径
+ * @return 文件数组
+ */
+ public static File[] listFiles(String dirPath) {
+ File dir = new File(dirPath);
+ if (dir.exists() && dir.isDirectory()) {
+ return dir.listFiles();
+ }
+ return new File[0];
+ }
+
+ /**
+ * 追加内容到文件末尾
+ * @param filePath 文件路径
+ * @param content 要追加的内容
+ * @throws IOException 追加失败时抛出
+ */
+ public static void appendToFile(String filePath, String content) throws IOException {
+ Files.writeString(Paths.get(filePath), content, StandardCharsets.UTF_8,
+ StandardOpenOption.CREATE, StandardOpenOption.APPEND);
+ }
+
+ /**
+ * 复制文件
+ * @param sourcePath 源文件路径
+ * @param targetPath 目标文件路径
+ * @throws IOException 复制失败时抛出
+ */
+ public static void copyFile(String sourcePath, String targetPath) throws IOException {
+ Files.copy(Paths.get(sourcePath), Paths.get(targetPath), StandardCopyOption.REPLACE_EXISTING);
+ }
+
+ /**
+ * 获取文件大小(字节)
+ * @param filePath 文件路径
+ * @return 文件大小
+ * @throws IOException 获取失败时抛出
+ */
+ public static long getFileSize(String filePath) throws IOException {
+ return Files.size(Paths.get(filePath));
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/util/PasswordValidator.java b/src/main/java/com/util/PasswordValidator.java
new file mode 100644
index 0000000..40a26b5
--- /dev/null
+++ b/src/main/java/com/util/PasswordValidator.java
@@ -0,0 +1,102 @@
+package com.util;
+
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+
+/**
+ * 密码验证和加密工具类
+ * 提供密码格式验证、加密、匹配等功能
+ */
+public class PasswordValidator {
+
+ /**
+ * 验证密码格式:6-10位,包含字母和数字
+ * @param password 待验证的密码
+ * @return true表示格式正确
+ */
+ public static boolean isValid(String password) {
+ if (password == null || password.length() < 6 || password.length() > 10) {
+ return false;
+ }
+
+ boolean hasLetter = password.matches("^(?=.*[a-z])(?=.*[A-Z]).*$");
+ boolean hasDigit = password.matches(".*\\d.*");
+
+ return hasLetter && hasDigit;
+ }
+
+ /**
+ * 使用SHA-256加密密码
+ * @param password 明文密码
+ * @return 加密后的密码(16进制字符串)
+ */
+ public static String encrypt(String password) {
+ try {
+ MessageDigest digest = MessageDigest.getInstance("SHA-256");
+ byte[] hash = digest.digest(password.getBytes());
+ StringBuilder hexString = new StringBuilder();
+
+ for (byte b : hash) {
+ String hex = Integer.toHexString(0xff & b);
+ if (hex.length() == 1) {
+ hexString.append('0');
+ }
+ hexString.append(hex);
+ }
+
+ return hexString.toString();
+ } catch (NoSuchAlgorithmException e) {
+ throw new RuntimeException("SHA-256算法不可用", e);
+ }
+ }
+
+ /**
+ * 验证密码是否匹配
+ * @param plainPassword 明文密码
+ * @param encryptedPassword 加密后的密码
+ * @return true表示匹配
+ */
+ public static boolean matches(String plainPassword, String encryptedPassword) {
+ return encrypt(plainPassword).equals(encryptedPassword);
+ }
+
+ /**
+ * 生成6-10位随机注册码(包含字母和数字)
+ * @return 注册码
+ */
+ public static String generateRegistrationCode() {
+ String chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
+ int length = 6 + (int) (Math.random() * 5); // 6-10位
+
+ StringBuilder code = new StringBuilder();
+
+ // 确保至少有一个字母
+ code.append(chars.charAt((int) (Math.random() * 52)));
+ // 确保至少有一个数字
+ code.append(chars.charAt(52 + (int) (Math.random() * 10)));
+
+ // 填充剩余字符
+ for (int i = 2; i < length; i++) {
+ code.append(chars.charAt((int) (Math.random() * chars.length())));
+ }
+
+ // 打乱字符顺序
+ return shuffleString(code.toString());
+ }
+
+ /**
+ * 打乱字符串
+ * @param str 原字符串
+ * @return 打乱后的字符串
+ */
+ private static String shuffleString(String str) {
+ char[] chars = str.toCharArray();
+ for (int i = chars.length - 1; i > 0; i--) {
+ int j = (int) (Math.random() * (i + 1));
+ char temp = chars[i];
+ chars[i] = chars[j];
+ chars[j] = temp;
+ }
+ return new String(chars);
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/bx/util/RandomUtils.java b/src/main/java/com/util/RandomUtils.java
similarity index 75%
rename from src/main/java/com/bx/util/RandomUtils.java
rename to src/main/java/com/util/RandomUtils.java
index 8735980..f06a7ed 100644
--- a/src/main/java/com/bx/util/RandomUtils.java
+++ b/src/main/java/com/util/RandomUtils.java
@@ -1,4 +1,4 @@
-package com.bx.util;
+package com.util;
import java.util.Collections;
import java.util.List;
@@ -26,11 +26,8 @@ public class RandomUtils {
return array[random.nextInt(array.length)];
}
- /**
- * 从列表中随机选择一个元素
- * @param list 列表
- * @return 随机选中的元素
- */
+
+ //从列表中随机选择一个元素
public static T randomChoice(List list) {
if (list == null || list.isEmpty()) {
throw new IllegalArgumentException("列表不能为空");
@@ -46,12 +43,8 @@ public class RandomUtils {
Collections.shuffle(list, random);
}
- /**
- * 生成指定范围内的随机双精度浮点数
- * @param min 最小值
- * @param max 最大值
- * @return 随机浮点数
- */
+
+ //生成指定范围内的随机双精度浮点数
public static double nextDouble(double min, double max) {
if (min > max) {
throw new IllegalArgumentException("min不能大于max");
@@ -59,21 +52,14 @@ public class RandomUtils {
return min + (max - min) * random.nextDouble();
}
- /**
- * 生成随机布尔值
- * @return true或false
- */
+
+ //生成随机布尔值
public static boolean nextBoolean() {
return random.nextBoolean();
}
- /**
- * 按概率返回true
- * @param probability 概率值(0.0 - 1.0)
- * @return true或false
- *
- * 示例:probability(0.7) 有70%概率返回true
- */
+ //按概率返回true(题目生成概率)
+ //示例:probability(0.7) 有70%概率返回true
public static boolean probability(double probability) {
if (probability < 0.0 || probability > 1.0) {
throw new IllegalArgumentException("概率必须在0.0-1.0之间");
diff --git a/src/test/java/TestMain.java b/src/test/java/TestMain.java
new file mode 100644
index 0000000..d4c7da5
--- /dev/null
+++ b/src/test/java/TestMain.java
@@ -0,0 +1,2 @@
+public class TestMain {
+}
--
2.34.1
From c50774c43216d847be71728c1eecf5644be1f838 Mon Sep 17 00:00:00 2001
From: bx <2936213174@qq.com>
Date: Fri, 3 Oct 2025 20:06:47 +0800
Subject: [PATCH 3/5] =?UTF-8?q?=E7=AC=AC=E4=BA=8C=E7=89=88?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.idea/uiDesigner.xml | 124 +++++
src/main/java/com/model/ChoiceQuestion.java | 81 +--
src/main/java/com/model/Grade.java | 47 +-
src/main/java/com/model/QuizHistory.java | 82 +++
src/main/java/com/model/QuizResult.java | 66 +++
src/main/java/com/model/User.java | 89 +--
src/main/java/com/service/FileIOService.java | 242 +++++++++
src/main/java/com/service/QuizService.java | 432 +++++++++++++++
src/main/java/com/service/UserService.java | 321 +++++++++++
.../QuestionFactoryManager.java | 97 ++++
.../factory/ElementaryQuestionFactory.java | 41 ++
.../factory/HighQuestionFactory.java | 41 ++
.../factory/MiddleQuestionFactory.java | 41 ++
.../factory/QuestionFactory.java | 17 +
.../strategy/AbstractQuestionStrategy.java | 138 +++++
.../strategy/QuestionStrategy.java | 12 +
.../strategy/elementary/AdditionStrategy.java | 37 ++
.../strategy/elementary/DivisionStrategy.java | 39 ++
.../elementary/MultiplicationStrategy.java | 37 ++
.../elementary/ParenthesesAddStrategy.java | 40 ++
.../ParenthesesMultiplyStrategy.java | 41 ++
.../elementary/SubtractionStrategy.java | 40 ++
.../strategy/high/CosStrategy.java | 57 ++
.../strategy/high/SinStrategy.java | 56 ++
.../strategy/high/TanStrategy.java | 56 ++
.../strategy/high/TrigIdentityStrategy.java | 41 ++
.../middle/MixedSquareSqrtStrategy.java | 40 ++
.../strategy/middle/SqrtAddStrategy.java | 39 ++
.../strategy/middle/SqrtStrategy.java | 39 ++
.../strategy/middle/SquareAddStrategy.java | 37 ++
.../strategy/middle/SquareStrategy.java | 39 ++
src/main/java/com/util/FileUtils.java | 75 ++-
src/main/java/com/util/PasswordValidator.java | 261 ++++++++-
src/test/java/TestMain.java | 507 +++++++++++++++++-
34 files changed, 3195 insertions(+), 157 deletions(-)
create mode 100644 .idea/uiDesigner.xml
create mode 100644 src/main/java/com/model/QuizHistory.java
create mode 100644 src/main/java/com/model/QuizResult.java
create mode 100644 src/main/java/com/service/FileIOService.java
create mode 100644 src/main/java/com/service/QuizService.java
create mode 100644 src/main/java/com/service/UserService.java
create mode 100644 src/main/java/com/service/question_generator/QuestionFactoryManager.java
create mode 100644 src/main/java/com/service/question_generator/factory/ElementaryQuestionFactory.java
create mode 100644 src/main/java/com/service/question_generator/factory/HighQuestionFactory.java
create mode 100644 src/main/java/com/service/question_generator/factory/MiddleQuestionFactory.java
create mode 100644 src/main/java/com/service/question_generator/factory/QuestionFactory.java
create mode 100644 src/main/java/com/service/question_generator/strategy/AbstractQuestionStrategy.java
create mode 100644 src/main/java/com/service/question_generator/strategy/QuestionStrategy.java
create mode 100644 src/main/java/com/service/question_generator/strategy/elementary/AdditionStrategy.java
create mode 100644 src/main/java/com/service/question_generator/strategy/elementary/DivisionStrategy.java
create mode 100644 src/main/java/com/service/question_generator/strategy/elementary/MultiplicationStrategy.java
create mode 100644 src/main/java/com/service/question_generator/strategy/elementary/ParenthesesAddStrategy.java
create mode 100644 src/main/java/com/service/question_generator/strategy/elementary/ParenthesesMultiplyStrategy.java
create mode 100644 src/main/java/com/service/question_generator/strategy/elementary/SubtractionStrategy.java
create mode 100644 src/main/java/com/service/question_generator/strategy/high/CosStrategy.java
create mode 100644 src/main/java/com/service/question_generator/strategy/high/SinStrategy.java
create mode 100644 src/main/java/com/service/question_generator/strategy/high/TanStrategy.java
create mode 100644 src/main/java/com/service/question_generator/strategy/high/TrigIdentityStrategy.java
create mode 100644 src/main/java/com/service/question_generator/strategy/middle/MixedSquareSqrtStrategy.java
create mode 100644 src/main/java/com/service/question_generator/strategy/middle/SqrtAddStrategy.java
create mode 100644 src/main/java/com/service/question_generator/strategy/middle/SqrtStrategy.java
create mode 100644 src/main/java/com/service/question_generator/strategy/middle/SquareAddStrategy.java
create mode 100644 src/main/java/com/service/question_generator/strategy/middle/SquareStrategy.java
diff --git a/.idea/uiDesigner.xml b/.idea/uiDesigner.xml
new file mode 100644
index 0000000..2b63946
--- /dev/null
+++ b/.idea/uiDesigner.xml
@@ -0,0 +1,124 @@
+
+
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+
+
+
+ -
+
+
+
+
+
+ -
+
+
+
+
+
+ -
+
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+
+
+ -
+
+
+ -
+
+
+
+
+
\ No newline at end of file
diff --git a/src/main/java/com/model/ChoiceQuestion.java b/src/main/java/com/model/ChoiceQuestion.java
index b71c59a..897059e 100644
--- a/src/main/java/com/model/ChoiceQuestion.java
+++ b/src/main/java/com/model/ChoiceQuestion.java
@@ -3,67 +3,34 @@ package com.model;
import java.util.List;
/**
- * 选择题数据模型
- * 包含题目内容、正确答案、四个选项
+ * 选择题模型(纯数据)
*/
public class ChoiceQuestion {
- private String questionText; // 题目文本,如 "3 + 5"
- private double correctAnswer; // 正确答案
- private List options; // 四个选项(包含正确答案)
- private Grade grade; // 所属学段
- private int correctOptionIndex; // 正确答案在选项中的索引(0-3)
+ private String questionText; // 题目文本
+ private Object correctAnswer; // 正确答案
+ private List> options; // 选项列表
+ private Grade grade; // 所属学段
- /**
- * 无参构造函数
- */
- public ChoiceQuestion() {
- }
+ // ==================== 构造方法 ====================
- /**
- * 完整构造函数
- */
- public ChoiceQuestion(String questionText, double correctAnswer, List options, Grade grade) {
+ public ChoiceQuestion(String questionText, double correctAnswer,
+ List options, Grade grade) {
this.questionText = questionText;
this.correctAnswer = correctAnswer;
this.options = options;
this.grade = grade;
-
- // 自动找到正确答案的索引
- this.correctOptionIndex = findCorrectOptionIndex();
- }
-
- /**
- * 查找正确答案在选项中的位置
- */
- private int findCorrectOptionIndex() {
- for (int i = 0; i < options.size(); i++) {
- if (Math.abs(options.get(i) - correctAnswer) < 0.01) {
- return i;
- }
- }
- return -1; // 理论上不会发生
}
- /**
- * 检查用户选择的选项是否正确
- * @param optionIndex 用户选择的选项索引(0-3)
- * @return true表示正确
- */
- public boolean checkAnswer(int optionIndex) {
- return optionIndex == correctOptionIndex;
- }
-
- /**
- * 检查用户输入的答案值是否正确
- * @param answer 用户输入的答案值
- * @return true表示正确
- */
- public boolean checkAnswerValue(double answer) {
- return Math.abs(answer - correctAnswer) < 0.01;
+ public ChoiceQuestion(String questionText, String correctAnswer,
+ List options, Grade grade) {
+ this.questionText = questionText;
+ this.correctAnswer = correctAnswer;
+ this.options = options;
+ this.grade = grade;
}
- // ========== Getter和Setter方法 ==========
+ // ==================== Getters & Setters ====================
public String getQuestionText() {
return questionText;
@@ -73,21 +40,20 @@ public class ChoiceQuestion {
this.questionText = questionText;
}
- public double getCorrectAnswer() {
+ public Object getCorrectAnswer() {
return correctAnswer;
}
- public void setCorrectAnswer(double correctAnswer) {
+ public void setCorrectAnswer(Object correctAnswer) {
this.correctAnswer = correctAnswer;
}
- public List getOptions() {
+ public List> getOptions() {
return options;
}
- public void setOptions(List options) {
+ public void setOptions(List> options) {
this.options = options;
- this.correctOptionIndex = findCorrectOptionIndex();
}
public Grade getGrade() {
@@ -98,19 +64,12 @@ public class ChoiceQuestion {
this.grade = grade;
}
- public int getCorrectOptionIndex() {
- return correctOptionIndex;
- }
-
- public void setCorrectOptionIndex(int correctOptionIndex) {
- this.correctOptionIndex = correctOptionIndex;
- }
-
@Override
public String toString() {
return "ChoiceQuestion{" +
"questionText='" + questionText + '\'' +
", correctAnswer=" + correctAnswer +
+ ", options=" + options +
", grade=" + grade +
'}';
}
diff --git a/src/main/java/com/model/Grade.java b/src/main/java/com/model/Grade.java
index 7de066d..1d2729f 100644
--- a/src/main/java/com/model/Grade.java
+++ b/src/main/java/com/model/Grade.java
@@ -1,49 +1,10 @@
package com.model;
/**
- * 学段枚举类
- * 定义三个学段:小学、初中、高中
+ * 学段枚举
*/
public enum Grade {
- ELEMENTARY("小学"),
- MIDDLE("初中"),
- HIGH("高中");
-
- private final String displayName;
-
- Grade(String displayName) {
- this.displayName = displayName;
- }
-
- public String getDisplayName() {
- return displayName;
- }
-
- //根据显示名称查找对应的枚举值
- public static Grade fromDisplayName(String displayName) {
- for (Grade grade : values()) {
- if (grade.displayName.equals(displayName)) {
- return grade;
- }
- }
- throw new IllegalArgumentException("未知学段: " + displayName);
- }
-
- /**
- * 获取所有学段的显示名称数组
- * @return ["小学", "初中", "高中"]
- */
- public static String[] getDisplayNames() {
- Grade[] grades = values();
- String[] names = new String[grades.length];
- for (int i = 0; i < grades.length; i++) {
- names[i] = grades[i].displayName;
- }
- return names;
- }
-
- @Override
- public String toString() {
- return displayName;
- }
+ ELEMENTARY, // 小学
+ MIDDLE, // 初中
+ HIGH // 高中
}
\ No newline at end of file
diff --git a/src/main/java/com/model/QuizHistory.java b/src/main/java/com/model/QuizHistory.java
new file mode 100644
index 0000000..1d60028
--- /dev/null
+++ b/src/main/java/com/model/QuizHistory.java
@@ -0,0 +1,82 @@
+package com.model;
+
+
+import java.util.Date;
+import java.util.List;
+
+/**
+ * 答题历史记录模型(纯数据)
+ */
+public class QuizHistory {
+
+ private String username; // 用户名
+ private Date timestamp; // 答题时间
+ private List questions; // 题目列表
+ private List userAnswers; // 用户答案列表
+ private int score; // 得分
+
+ // ==================== 构造方法 ====================
+
+ public QuizHistory(String username, Date timestamp,
+ List questions,
+ List userAnswers,
+ int score) {
+ this.username = username;
+ this.timestamp = timestamp;
+ this.questions = questions;
+ this.userAnswers = userAnswers;
+ this.score = score;
+ }
+
+ // ==================== Getters & Setters ====================
+
+ public String getUsername() {
+ return username;
+ }
+
+ public void setUsername(String username) {
+ this.username = username;
+ }
+
+ public Date getTimestamp() {
+ return timestamp;
+ }
+
+ public void setTimestamp(Date timestamp) {
+ this.timestamp = timestamp;
+ }
+
+ public List getQuestions() {
+ return questions;
+ }
+
+ public void setQuestions(List questions) {
+ this.questions = questions;
+ }
+
+ public List getUserAnswers() {
+ return userAnswers;
+ }
+
+ public void setUserAnswers(List userAnswers) {
+ this.userAnswers = userAnswers;
+ }
+
+ public int getScore() {
+ return score;
+ }
+
+ public void setScore(int score) {
+ this.score = score;
+ }
+
+ @Override
+ public String toString() {
+ return "QuizHistory{" +
+ "username='" + username + '\'' +
+ ", timestamp=" + timestamp +
+ ", questions=" + (questions != null ? questions.size() : 0) +
+ ", score=" + score +
+ '}';
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/model/QuizResult.java b/src/main/java/com/model/QuizResult.java
new file mode 100644
index 0000000..7ce4e50
--- /dev/null
+++ b/src/main/java/com/model/QuizResult.java
@@ -0,0 +1,66 @@
+package com.model;
+
+
+/**
+ * 答题结果模型(纯数据)
+ */
+public class QuizResult {
+
+ private int totalQuestions; // 总题数
+ private int correctCount; // 正确题数
+ private int wrongCount; // 错误题数
+ private int score; // 得分
+
+ // ==================== 构造方法 ====================
+
+ public QuizResult(int totalQuestions, int correctCount, int wrongCount, int score) {
+ this.totalQuestions = totalQuestions;
+ this.correctCount = correctCount;
+ this.wrongCount = wrongCount;
+ this.score = score;
+ }
+
+ // ==================== Getters & Setters ====================
+
+ public int getTotalQuestions() {
+ return totalQuestions;
+ }
+
+ public void setTotalQuestions(int totalQuestions) {
+ this.totalQuestions = totalQuestions;
+ }
+
+ public int getCorrectCount() {
+ return correctCount;
+ }
+
+ public void setCorrectCount(int correctCount) {
+ this.correctCount = correctCount;
+ }
+
+ public int getWrongCount() {
+ return wrongCount;
+ }
+
+ public void setWrongCount(int wrongCount) {
+ this.wrongCount = wrongCount;
+ }
+
+ public int getScore() {
+ return score;
+ }
+
+ public void setScore(int score) {
+ this.score = score;
+ }
+
+ @Override
+ public String toString() {
+ return "QuizResult{" +
+ "totalQuestions=" + totalQuestions +
+ ", correctCount=" + correctCount +
+ ", wrongCount=" + wrongCount +
+ ", score=" + score +
+ '}';
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/model/User.java b/src/main/java/com/model/User.java
index eadfd17..288ce9b 100644
--- a/src/main/java/com/model/User.java
+++ b/src/main/java/com/model/User.java
@@ -1,32 +1,50 @@
package com.model;
+import java.util.Date;
+
+/**
+ * 用户模型(纯数据)
+ */
public class User {
- private String username; // 用户名,格式:小学-张三
+
+ private String username; // 用户名
private String password; // 密码(加密后)
- private Grade grade; // 学段
private String email; // 邮箱
- private String registrationCode; // 注册码(明文保存,用于用户查看)
- private long createdTime; // 创建时间戳
- private long lastLoginTime; // 最后登录时间戳
+ private Grade grade; // 学段
+ private int totalQuizzes; // 总答题次数
+ private double averageScore; // 平均分
+ private Date registrationDate; // 注册时间
+
+ // ==================== 构造方法 ====================
/**
- * 无参构造函数(Gson反序列化需要)
+ * 完整构造方法(用于从文件加载)
*/
- public User() {
+ public User(String username, String password, String email, Grade grade,
+ int totalQuizzes, double averageScore, Date registrationDate) {
+ this.username = username;
+ this.password = password;
+ this.email = email;
+ this.grade = grade;
+ this.totalQuizzes = totalQuizzes;
+ this.averageScore = averageScore;
+ this.registrationDate = registrationDate;
}
/**
- * 完整构造函数
+ * 简化构造方法(用于新用户注册)
*/
- public User(String username, String password, Grade grade, String email) {
+ public User(String username, String password, String email, Grade grade) {
this.username = username;
this.password = password;
- this.grade = grade;
this.email = email;
- this.createdTime = System.currentTimeMillis();
+ this.grade = grade;
+ this.totalQuizzes = 0;
+ this.averageScore = 0.0;
+ this.registrationDate = new Date();
}
- // ========== Getter和Setter方法 ==========
+ // ==================== Getters & Setters ====================
public String getUsername() {
return username;
@@ -44,14 +62,6 @@ public class User {
this.password = password;
}
- public Grade getGrade() {
- return grade;
- }
-
- public void setGrade(Grade grade) {
- this.grade = grade;
- }
-
public String getEmail() {
return email;
}
@@ -60,36 +70,47 @@ public class User {
this.email = email;
}
- public String getRegistrationCode() {
- return registrationCode;
+ public Grade getGrade() {
+ return grade;
+ }
+
+ public void setGrade(Grade grade) {
+ this.grade = grade;
}
- public void setRegistrationCode(String registrationCode) {
- this.registrationCode = registrationCode;
+ public int getTotalQuizzes() {
+ return totalQuizzes;
}
- public long getCreatedTime() {
- return createdTime;
+ public void setTotalQuizzes(int totalQuizzes) {
+ this.totalQuizzes = totalQuizzes;
}
- public void setCreatedTime(long createdTime) {
- this.createdTime = createdTime;
+ public double getAverageScore() {
+ return averageScore;
}
- public long getLastLoginTime() {
- return lastLoginTime;
+ public void setAverageScore(double averageScore) {
+ this.averageScore = averageScore;
}
- public void setLastLoginTime(long lastLoginTime) {
- this.lastLoginTime = lastLoginTime;
+ public Date getRegistrationDate() {
+ return registrationDate;
+ }
+
+ public void setRegistrationDate(Date registrationDate) {
+ this.registrationDate = registrationDate;
}
@Override
public String toString() {
return "User{" +
"username='" + username + '\'' +
- ", grade=" + grade +
", email='" + email + '\'' +
+ ", grade=" + grade +
+ ", totalQuizzes=" + totalQuizzes +
+ ", averageScore=" + String.format("%.1f", averageScore) +
+ ", registrationDate=" + registrationDate +
'}';
}
-}
+}
\ No newline at end of file
diff --git a/src/main/java/com/service/FileIOService.java b/src/main/java/com/service/FileIOService.java
new file mode 100644
index 0000000..4bfa68e
--- /dev/null
+++ b/src/main/java/com/service/FileIOService.java
@@ -0,0 +1,242 @@
+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> 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