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.

164 lines
5.9 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.

import java.io.IOException;
import java.util.List;
import java.util.Optional;
import java.util.Scanner;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* 程序主入口和中央控制器。
* 负责管理应用生命周期、解析用户命令、协调各服务完成用户请求。
*/
public class Application {
// 依赖注入:在构造函数中初始化所有需要的服务
private final Scanner scanner;
private final AuthService authService;
private final SessionManager sessionManager;
private final IFileService fileService;
// 用于解析“切换为XX”命令的正则表达式
private static final Pattern SWITCH_COMMAND_PATTERN = Pattern.compile("^切换为(小学|初中|高中)$");
private static final int MIN_GENERATE_COUNT = 10;
private static final int MAX_GENERATE_COUNT = 30;
public Application() {
this.scanner = new Scanner(System.in, "UTF-8");
// --- 依赖注入与组件装配 ---
// 创建数据访问层的实例
UserRepository userRepository = new InMemoryUserRepository();
this.fileService = new TextFilePersistence();
// 创建应用服务层的实例,并注入依赖
this.authService = new AuthService(userRepository);
// 获取会话管理器的单例实例
this.sessionManager = SessionManager.getInstance();
}
/**
* 启动并运行应用程序的主循环。
*/
public void run() {
System.out.println("欢迎使用中小学数学卷子自动生成程序!");
while (true) {
if (!sessionManager.isUserLoggedIn()) {
handleLoggedOutState();
} else {
handleLoggedInState();
}
}
}
/**
* 处理用户未登录状态下的逻辑。
*/
private void handleLoggedOutState() {
System.out.print("请输入用户名和密码(以空格隔开,输入 'exit' 退出程序): ");
String input = scanner.nextLine();
if ("exit".equalsIgnoreCase(input.trim())) {
System.out.println("感谢使用,程序已退出。");
System.exit(0);
}
String[] credentials = input.split("\\s+");
if (credentials.length != 2) {
System.out.println("输入格式错误,请输入正确的用户名、密码。");
return;
}
Optional<User> userOptional = authService.login(credentials[0], credentials[1]);
if (userOptional.isPresent()) {
sessionManager.startSession(userOptional.get());
System.out.println("登录成功!欢迎您," + userOptional.get().getUsername() + "。");
} else {
System.out.println("用户名或密码错误,请重试。");
}
}
/**
* 处理用户已登录状态下的逻辑。
*/
private void handleLoggedInState() {
String currentLevelName = sessionManager.getCurrentLevelName();
System.out.printf(
"当前选择为%s出题。请输入生成题目数量%d-%d或输入 '切换为XX',或输入 '-1' 退出登录:%n",
currentLevelName, MIN_GENERATE_COUNT, MAX_GENERATE_COUNT);
String input = scanner.nextLine().trim();
try {
if ("-1".equals(input)) {
handleLogout();
} else if (isSwitchCommand(input)) {
handleSwitchLevel(input);
} else if (isNumeric(input)) {
int count = Integer.parseInt(input);
validateGenerateCount(count);
handleGenerateProblems(count);
} else {
throw new InvalidInputException(
String.format("请输入小学、初中和高中三个选项中的一个",
MIN_GENERATE_COUNT, MAX_GENERATE_COUNT));
}
} catch (InvalidInputException | IOException | NumberFormatException e) {
System.err.println("错误: " + e.getMessage());
}
}
private void handleLogout() {
System.out.println("用户 " + sessionManager.getCurrentUser().getUsername() + " 已退出登录。");
sessionManager.endSession();
}
private void handleSwitchLevel(String input) throws InvalidInputException {
Matcher matcher = SWITCH_COMMAND_PATTERN.matcher(input);
if (matcher.matches()) {
String levelName = matcher.group(1);
EducationLevel level = EducationLevel.fromLevelName(levelName);
if (level != null) {
sessionManager.setCurrentGenerator(level);
System.out.println("成功切换到 " + levelName + " 出题模式。");
} else {
// 这部分代码理论上不会执行,因为正则表达式已经限制了级别名称
throw new InvalidInputException("无效的切换目标级别。");
}
}
}
private void handleGenerateProblems(int count) throws IOException {
User currentUser = sessionManager.getCurrentUser();
System.out.println("正在加载历史题目,请稍候...");
Set<String> history = fileService.loadAllProblemHistory(currentUser);
System.out.println("历史题目加载完毕。共找到 " + history.size() + " 道历史题目。");
System.out.println("正在生成 " + count + " 道不重复的新题目...");
IProblemGenerator generator = sessionManager.getCurrentGenerator();
List<Equation> newProblems = generator.generate(count, history);
System.out.println("题目生成完毕,正在保存到文件...");
fileService.saveProblems(currentUser, newProblems);
System.out.println("保存成功!新的题目已存储在用户目录 " + currentUser.getStoragePath() + " 下。");
}
private boolean isSwitchCommand(String input) {
return SWITCH_COMMAND_PATTERN.matcher(input).matches();
}
private boolean isNumeric(String str) {
return str != null && str.matches("-?\\d+");
}
private void validateGenerateCount(int count) throws InvalidInputException {
if (count < MIN_GENERATE_COUNT || count > MAX_GENERATE_COUNT) {
throw new InvalidInputException(
String.format("生成数量必须在 %d 到 %d 之间。", MIN_GENERATE_COUNT, MAX_GENERATE_COUNT));
}
}
public static void main(String[] args) {
Application app = new Application();
app.run();
}
}