|
|
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();
|
|
|
}
|
|
|
}
|