|
|
|
|
@ -1,35 +1,239 @@
|
|
|
|
|
#类的设计
|
|
|
|
|
##User(用户实体)
|
|
|
|
|
###作用:
|
|
|
|
|
存储用户账户信息,包括用户名、密码和用户类型
|
|
|
|
|
###属性:
|
|
|
|
|
private String username; // 用户名
|
|
|
|
|
private String password; // 密码
|
|
|
|
|
private String userType; // 用户类型(小学/初中/高中)
|
|
|
|
|
###方法:
|
|
|
|
|
public boolean validateCredentials(String inputUsername, String inputPassword)
|
|
|
|
|
// 验证用户名和密码是否匹配
|
|
|
|
|
|
|
|
|
|
// Getter和Setter方法
|
|
|
|
|
public String getUsername()
|
|
|
|
|
public void setUsername(String username)
|
|
|
|
|
public String getPassword()
|
|
|
|
|
public void setPassword(String password)
|
|
|
|
|
public UserType getUserType()
|
|
|
|
|
public void setUserType(String userType)
|
|
|
|
|
|
|
|
|
|
##UserManager(用户管理类)
|
|
|
|
|
###作用:
|
|
|
|
|
管理用户登录状态、类型切换和用户认证
|
|
|
|
|
###属性:
|
|
|
|
|
private Map<String, User> users; // 存储所有用户信息
|
|
|
|
|
private User currentUser; // 当前登录用户
|
|
|
|
|
private String currentType; // 当前题目类型
|
|
|
|
|
###方法:
|
|
|
|
|
public boolean login(String username, String password)
|
|
|
|
|
public void logout()
|
|
|
|
|
public boolean switchUserType(String newType)
|
|
|
|
|
public boolean isLoggedIn()
|
|
|
|
|
public User getCurrentUser()
|
|
|
|
|
private void initializeUsers()
|
|
|
|
|
public UserManager()
|
|
|
|
|
# 试卷生成系统类设计说明文档
|
|
|
|
|
|
|
|
|
|
本说明文档详细描述系统中各个核心类的设计目的、职责、关键属性及方法实现逻辑,帮助开发者理解系统内部结构并进行维护或扩展。
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
## 1. User 类
|
|
|
|
|
|
|
|
|
|
### 功能概述
|
|
|
|
|
User 是用户信息的封装类,用于存储单个用户的登录凭证和所属学段类型。
|
|
|
|
|
|
|
|
|
|
### 属性
|
|
|
|
|
- `username`:字符串类型,表示用户名。
|
|
|
|
|
- `password`:字符串类型,表示用户密码(明文存储,仅用于演示)。
|
|
|
|
|
- `userType`:字符串类型,表示用户类型,取值为“小学”、“初中”或“高中”。
|
|
|
|
|
|
|
|
|
|
### 方法
|
|
|
|
|
- **构造方法** `User(String username, String password, String userType)`
|
|
|
|
|
初始化用户对象,设置用户名、密码和用户类型。
|
|
|
|
|
|
|
|
|
|
- `getUsername()` / `setUsername(String username)`
|
|
|
|
|
获取或设置用户名。
|
|
|
|
|
|
|
|
|
|
- `getPassword()` / `setPassword(String password)`
|
|
|
|
|
获取或设置密码。
|
|
|
|
|
|
|
|
|
|
- `getUserType()` / `setUserType(String userType)`
|
|
|
|
|
获取或设置用户类型。
|
|
|
|
|
|
|
|
|
|
- `validateCredentials(String inputUsername, String inputPassword)`
|
|
|
|
|
验证输入的用户名和密码是否与当前用户匹配。返回布尔值,用于登录判断。
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
## 2. UserManager 类
|
|
|
|
|
|
|
|
|
|
### 功能概述
|
|
|
|
|
UserManager 负责管理所有用户账户、处理登录逻辑,并维护当前登录用户状态。
|
|
|
|
|
|
|
|
|
|
### 属性
|
|
|
|
|
- `users`:`Map<String, User>` 类型,以用户名为键存储所有预设用户。
|
|
|
|
|
- `currentUser`:`User` 类型,表示当前已登录的用户。
|
|
|
|
|
- `currentType`:`String` 类型,缓存当前用户类型(冗余字段,可由 currentUser 推导)。
|
|
|
|
|
|
|
|
|
|
### 方法
|
|
|
|
|
- **构造方法** `UserManager()`
|
|
|
|
|
调用 `initializeUsers()` 初始化9个预设用户(3小学 + 3初中 + 3高中)。
|
|
|
|
|
|
|
|
|
|
- `initializeUsers()`
|
|
|
|
|
向 users 映射中添加预设用户对象,用户名如“张三1”,密码均为“123”,类型按学段分配。
|
|
|
|
|
|
|
|
|
|
- `login(String username, String password)`
|
|
|
|
|
实现登录逻辑:
|
|
|
|
|
- 若用户名不存在,提示“该账号不存在”;
|
|
|
|
|
- 若密码错误,提示“密码错误”;
|
|
|
|
|
- 验证成功,设置 `currentUser` 和 `currentType`,返回 true。
|
|
|
|
|
|
|
|
|
|
- `logout()`
|
|
|
|
|
清空当前用户状态(设为 null)。
|
|
|
|
|
|
|
|
|
|
- `switchUserType(String newType)`
|
|
|
|
|
允许在已登录状态下切换用户类型(实际项目中此方法未被使用,主流程通过重新获取 QuestionSetting 实现切换)。
|
|
|
|
|
|
|
|
|
|
- `isLoggedIn()`
|
|
|
|
|
判断是否有用户登录(检查 `currentUser != null`)。
|
|
|
|
|
|
|
|
|
|
- `getCurrentUser()`
|
|
|
|
|
返回当前登录的 `User` 对象,供其他模块获取用户信息。
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
## 3. QuestionSetting 接口
|
|
|
|
|
|
|
|
|
|
### 功能概述
|
|
|
|
|
定义题目生成器的统一契约,确保所有学段题目生成器具有相同调用方式。
|
|
|
|
|
|
|
|
|
|
### 方法
|
|
|
|
|
- `Expression setQuestion(int count)`
|
|
|
|
|
根据指定的操作数数量 `count`(通常为3),生成一个符合当前学段要求的数学表达式对象。返回 `Expression` 实例。
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
## 4. AbstractQuestionSetting 抽象类
|
|
|
|
|
|
|
|
|
|
### 功能概述
|
|
|
|
|
作为所有题目生成器的基类,提供通用工具方法,减少代码重复。
|
|
|
|
|
|
|
|
|
|
### 属性
|
|
|
|
|
- `RANDOM`:静态 Random 实例,用于生成随机数,保证线程安全且全局一致。
|
|
|
|
|
|
|
|
|
|
### 方法
|
|
|
|
|
- `getRandomOperator()`
|
|
|
|
|
从 `{"+", "-", "*", "/"}` 中随机返回一个四则运算符。
|
|
|
|
|
|
|
|
|
|
- `getRandomNumber()`
|
|
|
|
|
生成 1 到 99 的随机整数(含1和99),并返回其字符串形式。
|
|
|
|
|
|
|
|
|
|
- `getPriority(String operator)`
|
|
|
|
|
返回运算符的优先级数值,用于括号判断:
|
|
|
|
|
- 三角函数、平方、开方:优先级 3
|
|
|
|
|
- 乘、除:优先级 2
|
|
|
|
|
- 加、减:优先级 1
|
|
|
|
|
- 其他或 null:返回 0 或 -1
|
|
|
|
|
|
|
|
|
|
- `addParenthesesIfNeeded(Expression child, String parentOperator, boolean isRightChild)`
|
|
|
|
|
根据运算优先级决定是否为子表达式添加括号:
|
|
|
|
|
- 子表达式无主运算符(即为纯数字),不加括号
|
|
|
|
|
- 子优先级 < 父优先级,加括号
|
|
|
|
|
- 若为右子表达式,且父运算符为 - 或 /,即使优先级相等也加括号(如 a - (b - c) 而非 a - b - c)
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
## 5. PrimaryQuestionSetting 类(小学)
|
|
|
|
|
|
|
|
|
|
### 功能概述
|
|
|
|
|
实现小学阶段的题目生成逻辑,仅包含四则运算,并保证题目合理性。
|
|
|
|
|
|
|
|
|
|
### 方法
|
|
|
|
|
- `setQuestion(int count)`
|
|
|
|
|
递归生成表达式:
|
|
|
|
|
- 若 count == 1,返回一个随机数字;
|
|
|
|
|
- 否则将操作数拆分为左右两部分,递归生成左右子表达式;
|
|
|
|
|
- 随机选择运算符;
|
|
|
|
|
- 若为除法且右值为0,重新生成右子表达式;
|
|
|
|
|
- 若为减法且左值 < 右值,交换左右子表达式以保证结果非负;
|
|
|
|
|
- 使用 `addParenthesesIfNeeded` 处理括号;
|
|
|
|
|
- 返回最终表达式对象。
|
|
|
|
|
|
|
|
|
|
小学题目不包含任何一元运算符(如平方、三角函数),也不强制包含特定符号。
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
## 6. MiddleQuestionSetting 类(初中)
|
|
|
|
|
|
|
|
|
|
### 功能概述
|
|
|
|
|
在小学基础上增加平方(²)和平方根(√)运算,并确保每道题至少包含其中一种。
|
|
|
|
|
|
|
|
|
|
### 新增方法
|
|
|
|
|
- `applyUnaryOperator(Expression child, String operator)`
|
|
|
|
|
对子表达式应用一元运算符:
|
|
|
|
|
- 平方(²):若子表达式为纯数字,则直接拼接“²”;否则加括号后拼接,如 `(a + b)²`
|
|
|
|
|
- 平方根(√):若子值为负,替换为新随机正数;若为纯数字,前缀“√”;否则写为 `√(表达式)`
|
|
|
|
|
|
|
|
|
|
- `applyProbability(Expression result)`
|
|
|
|
|
以 30% 概率对表达式应用平方或平方根运算,并更新主运算符。
|
|
|
|
|
|
|
|
|
|
- `generateFirstQuestion(int count)`
|
|
|
|
|
与小学类似,但每次生成后调用 `applyProbability` 尝试添加一元运算。
|
|
|
|
|
|
|
|
|
|
- `setQuestion(int count)`
|
|
|
|
|
循环调用 `generateFirstQuestion`,直到生成的表达式包含“²”或“√”,确保题目符合初中要求。
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
## 7. HighQuestionSetting 类(高中)
|
|
|
|
|
|
|
|
|
|
### 功能概述
|
|
|
|
|
在初中基础上增加三角函数(sin、cos、tan),并确保每道题至少包含一个三角函数。
|
|
|
|
|
|
|
|
|
|
### 新增方法
|
|
|
|
|
- `applyUnaryOperator(Expression child, String operator)`
|
|
|
|
|
扩展支持三角函数:
|
|
|
|
|
- `sin`/`cos`:直接包裹为 `sin(表达式)` 或 `cos(表达式)`,值为 `Math.round(Math.sin(Math.toRadians(value)))`
|
|
|
|
|
- `tan`:若输入角度为 90 + 180k(无定义点),则替换为新随机数,避免异常
|
|
|
|
|
|
|
|
|
|
- `applyProbability(Expression result)`
|
|
|
|
|
以 30% 概率从 `{"²", "√", "sin", "cos", "tan"}` 中随机选择一元运算符应用。
|
|
|
|
|
|
|
|
|
|
- `generateFirstQuestion(int count)`
|
|
|
|
|
逻辑同初中,但支持更多运算符。
|
|
|
|
|
|
|
|
|
|
- `setQuestion(int count)`
|
|
|
|
|
循环生成,直到表达式包含 `sin`、`cos` 或 `tan` 中的任意一个。
|
|
|
|
|
⚠️ 三角函数结果被强制转换为整数,可能损失精度,但简化了题目形式。
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
## 8. Expression 类
|
|
|
|
|
|
|
|
|
|
### 功能概述
|
|
|
|
|
封装一个数学表达式的文本形式、计算值及其主运算符,用于递归构建和值传递。
|
|
|
|
|
|
|
|
|
|
### 属性
|
|
|
|
|
- `expression`:表达式的字符串表示(如 `"5 + 3"` 或 `"√(16)"`)
|
|
|
|
|
- `value`:表达式计算结果的整数值
|
|
|
|
|
- `mainOperator`:表达式的主运算符(如 `"+"`、`"²"`、`"sin"`),若为纯数字则为 null
|
|
|
|
|
|
|
|
|
|
### 方法
|
|
|
|
|
- 构造方法 `Expression(String expression, int value, String mainOperator)`
|
|
|
|
|
初始化表达式对象
|
|
|
|
|
|
|
|
|
|
- `getExpression()` / `setExpression(String expression)`
|
|
|
|
|
获取或设置表达式字符串
|
|
|
|
|
|
|
|
|
|
- `getValue()` / `setValue(int value)`
|
|
|
|
|
获取或设置计算值
|
|
|
|
|
|
|
|
|
|
- `getMainOperator()` / `setMainOperator(String mainOperator)`
|
|
|
|
|
获取或设置主运算符
|
|
|
|
|
|
|
|
|
|
> 该类是表达式树的节点,支持在生成过程中传递结构与值。
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
## 9. QuestionSettingFactory 类
|
|
|
|
|
|
|
|
|
|
### 功能概述
|
|
|
|
|
工厂类,根据用户类型字符串动态创建对应的题目生成器实例。
|
|
|
|
|
|
|
|
|
|
### 方法
|
|
|
|
|
- `getQuestionSetting(String type)`
|
|
|
|
|
使用 switch 表达式:
|
|
|
|
|
- `"小学"` → 返回 `new PrimaryQuestionSetting()`
|
|
|
|
|
- `"初中"` → 返回 `new MiddleQuestionSetting()`
|
|
|
|
|
- `"高中"` → 返回 `new HighQuestionSetting()`
|
|
|
|
|
- 其他 → 打印“类型错误”,返回 `null`
|
|
|
|
|
|
|
|
|
|
> 该类解耦了用户类型与具体实现,便于扩展新学段。
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
## 10. FileManager 类
|
|
|
|
|
|
|
|
|
|
### 功能概述
|
|
|
|
|
负责试卷的本地存储与题目重复性检查。
|
|
|
|
|
|
|
|
|
|
### 常量
|
|
|
|
|
- `ROOT_PATH`:根目录路径,值为 `"./试卷/"`
|
|
|
|
|
|
|
|
|
|
### 方法
|
|
|
|
|
- `savePaper(User user, List<String> questions)`
|
|
|
|
|
- 创建用户专属目录(如 `./试卷/张三1/`)
|
|
|
|
|
- 生成时间戳文件名(格式:`yyyy-MM-dd-HH-mm-ss.txt`)
|
|
|
|
|
- 以 UTF-8 编码写入题目,格式为 `1. 表达式\n\n2. 表达式\n\n...`
|
|
|
|
|
|
|
|
|
|
- `checkQuestion(String question, User user)`
|
|
|
|
|
- 若用户目录不存在,返回 true(无需去重)
|
|
|
|
|
- 遍历该用户所有历史试卷文件
|
|
|
|
|
- 对每行去除题号
|
|
|
|
|
|