|
|
|
|
@ -1,10 +1,9 @@
|
|
|
|
|
package com.mathgenerator.ui;
|
|
|
|
|
|
|
|
|
|
import com.mathgenerator.auth.Authenticator;
|
|
|
|
|
import com.mathgenerator.auth.User;
|
|
|
|
|
import com.mathgenerator.model.User;
|
|
|
|
|
import com.mathgenerator.model.Level;
|
|
|
|
|
import com.mathgenerator.service.PaperService;
|
|
|
|
|
|
|
|
|
|
import com.mathgenerator.service.UserService;
|
|
|
|
|
import java.util.Optional;
|
|
|
|
|
import java.util.Scanner;
|
|
|
|
|
|
|
|
|
|
@ -13,12 +12,19 @@ import java.util.Scanner;
|
|
|
|
|
*/
|
|
|
|
|
public class ConsoleUI {
|
|
|
|
|
private final Scanner scanner = new Scanner(System.in);
|
|
|
|
|
private final Authenticator authenticator;
|
|
|
|
|
private final UserService userService;
|
|
|
|
|
private final PaperService paperService;
|
|
|
|
|
|
|
|
|
|
// 通过构造函数接收依赖的服务,这是一种常见的设计模式(依赖注入)
|
|
|
|
|
public ConsoleUI(Authenticator authenticator, PaperService paperService) {
|
|
|
|
|
this.authenticator = authenticator;
|
|
|
|
|
/**
|
|
|
|
|
* ConsoleUI的构造函数。
|
|
|
|
|
* 通过构造函数接收依赖的服务,这是一种常见的设计模式(依赖注入),
|
|
|
|
|
* 使得UI层不负责创建服务,只负责使用。
|
|
|
|
|
*
|
|
|
|
|
* @param userService 用户服务实例。
|
|
|
|
|
* @param paperService 试卷服务实例。
|
|
|
|
|
*/
|
|
|
|
|
public ConsoleUI(UserService userService, PaperService paperService) {
|
|
|
|
|
this.userService = userService;
|
|
|
|
|
this.paperService = paperService;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@ -26,36 +32,107 @@ public class ConsoleUI {
|
|
|
|
|
* 启动并运行整个用户界面主循环。
|
|
|
|
|
*/
|
|
|
|
|
public void run() {
|
|
|
|
|
//TODO:警告:(29, 9) 'while' 语句不能在未抛出异常的情况下完成
|
|
|
|
|
while (true) {
|
|
|
|
|
Optional<User> userOptional = handleLogin();
|
|
|
|
|
userOptional.ifPresent(this::showUserMenu);
|
|
|
|
|
// 在主循环中加入注册选项
|
|
|
|
|
printHeader("欢迎使用中小学数学卷子自动生成程序");
|
|
|
|
|
System.out.println("1. 用户登录");
|
|
|
|
|
System.out.println("2. 新用户注册");
|
|
|
|
|
System.out.println("3. 退出程序");
|
|
|
|
|
printSeparator();
|
|
|
|
|
System.out.print("请选择操作 (1-3): ");
|
|
|
|
|
String choice = scanner.nextLine().trim();
|
|
|
|
|
|
|
|
|
|
switch (choice) {
|
|
|
|
|
case "1" -> handleLogin().ifPresent(this::showUserMenu);
|
|
|
|
|
case "2" -> handleRegistration();
|
|
|
|
|
case "3" -> {
|
|
|
|
|
System.out.println("感谢使用,程序已退出。");
|
|
|
|
|
return; // 退出run()方法,结束程序
|
|
|
|
|
}
|
|
|
|
|
default -> System.out.println("无效输入,请输入 1-3 之间的数字。");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 私有辅助方法,处理用户登录流程。
|
|
|
|
|
*
|
|
|
|
|
* @return 登录成功的用户Optional,如果登录失败或格式错误则返回空Optional。
|
|
|
|
|
*/
|
|
|
|
|
private Optional<User> handleLogin() {
|
|
|
|
|
printHeader("用户登录"); // 统一标题格式
|
|
|
|
|
System.out.print("请输入用户名和密码 (用空格隔开): (输入 exit 退出程序)\n> ");
|
|
|
|
|
String line = scanner.nextLine();
|
|
|
|
|
|
|
|
|
|
if ("exit".equalsIgnoreCase(line.trim())) {
|
|
|
|
|
System.out.println("感谢使用,程序已退出。");
|
|
|
|
|
System.exit(0);
|
|
|
|
|
}
|
|
|
|
|
printHeader("用户登录");
|
|
|
|
|
System.out.print("请输入用户名和密码 (用空格隔开): \n> ");
|
|
|
|
|
String[] credentials = scanner.nextLine().split("\\s+");
|
|
|
|
|
|
|
|
|
|
String[] credentials = line.split("\\s+");
|
|
|
|
|
if (credentials.length != 2) {
|
|
|
|
|
System.out.println("输入格式错误,请重新输入。");
|
|
|
|
|
System.out.println("输入格式错误。");
|
|
|
|
|
return Optional.empty();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Optional<User> userOptional = authenticator.login(credentials[0], credentials[1]);
|
|
|
|
|
// 调用新的UserService进行登录
|
|
|
|
|
Optional<User> userOptional = userService.login(credentials[0], credentials[1]);
|
|
|
|
|
if (userOptional.isEmpty()) {
|
|
|
|
|
System.out.println("用户名或密码错误,请重新输入。");
|
|
|
|
|
System.out.println("用户名或密码错误。");
|
|
|
|
|
}
|
|
|
|
|
return userOptional;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 新增方法:处理用户注册流程。
|
|
|
|
|
*/
|
|
|
|
|
private void handleRegistration() {
|
|
|
|
|
printHeader("新用户注册");
|
|
|
|
|
System.out.print("请输入新用户名: ");
|
|
|
|
|
String username = scanner.nextLine().trim();
|
|
|
|
|
|
|
|
|
|
if (userService.findUserByUsername(username).isPresent()) {
|
|
|
|
|
System.out.println("注册失败:该用户名已被占用。");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
System.out.print("请输入密码: ");
|
|
|
|
|
String password = scanner.nextLine().trim();
|
|
|
|
|
|
|
|
|
|
Level level = selectLevelForRegistration();
|
|
|
|
|
if (level == null) {
|
|
|
|
|
System.out.println("操作已取消。");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (userService.register(username, password, level)) {
|
|
|
|
|
System.out.println("注册成功!现在您可以使用新账户登录了。");
|
|
|
|
|
} else {
|
|
|
|
|
// 理论上,这里的失败分支不会被触发,因为我们已经提前检查了用户名
|
|
|
|
|
System.out.println("注册失败,发生未知错误。");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 新增辅助方法:让用户在注册时选择学段。
|
|
|
|
|
*/
|
|
|
|
|
private Level selectLevelForRegistration() {
|
|
|
|
|
while (true) {
|
|
|
|
|
printHeader("请为新用户选择默认的学段");
|
|
|
|
|
System.out.println("1. 小学");
|
|
|
|
|
System.out.println("2. 初中");
|
|
|
|
|
System.out.println("3. 高中");
|
|
|
|
|
System.out.println("0. 取消注册");
|
|
|
|
|
printSeparator();
|
|
|
|
|
System.out.print("请选择 (0-3): ");
|
|
|
|
|
String choice = scanner.nextLine().trim();
|
|
|
|
|
switch (choice) {
|
|
|
|
|
case "1": return Level.PRIMARY;
|
|
|
|
|
case "2": return Level.JUNIOR_HIGH;
|
|
|
|
|
case "3": return Level.SENIOR_HIGH;
|
|
|
|
|
case "0": return null; // 用户取消
|
|
|
|
|
default: System.out.println("无效输入,请重新选择。");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
/**
|
|
|
|
|
* 私有辅助方法,显示登录后的用户主菜单和处理用户操作。
|
|
|
|
|
*
|
|
|
|
|
* @param user 当前已登录的用户对象。
|
|
|
|
|
*/
|
|
|
|
|
private void showUserMenu(User user) {
|
|
|
|
|
Level currentLevel = user.level();
|
|
|
|
|
System.out.println("\n登录成功! 欢迎 " + user.username());
|
|
|
|
|
@ -88,7 +165,10 @@ public class ConsoleUI {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 处理切换难度的子菜单,加入循环以处理无效输入。
|
|
|
|
|
* 私有辅助方法,处理切换难度的子菜单,加入循环以处理无效输入。
|
|
|
|
|
*
|
|
|
|
|
* @param currentLevel 当前的难度级别。
|
|
|
|
|
* @return 用户选择的新的难度级别,如果选择返回则为原级别。
|
|
|
|
|
*/
|
|
|
|
|
private Level handleLevelSwitchMenu(Level currentLevel) {
|
|
|
|
|
while (true) { // <-- 增加循环
|
|
|
|
|
@ -100,7 +180,6 @@ public class ConsoleUI {
|
|
|
|
|
printSeparator();
|
|
|
|
|
System.out.print("请选择 (0-3): ");
|
|
|
|
|
String choice = scanner.nextLine().trim();
|
|
|
|
|
|
|
|
|
|
switch (choice) {
|
|
|
|
|
case "1":
|
|
|
|
|
System.out.println("难度已成功切换为 " + Level.PRIMARY.getChineseName() + "。");
|
|
|
|
|
@ -115,37 +194,51 @@ public class ConsoleUI {
|
|
|
|
|
System.out.println("已返回主菜单。");
|
|
|
|
|
return currentLevel; // 返回当前难度,退出循环
|
|
|
|
|
default:
|
|
|
|
|
// 如果输入无效,打印提示信息,循环将继续,要求用户重新输入
|
|
|
|
|
System.out.println("无效输入,请输入 0-3 之间的数字。");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 私有辅助方法,处理生成题目的逻辑。
|
|
|
|
|
*
|
|
|
|
|
* @param user 当前登录的用户。
|
|
|
|
|
* @param currentLevel 当前选择的难度级别。
|
|
|
|
|
*/
|
|
|
|
|
private void handleGeneration(User user, Level currentLevel) {
|
|
|
|
|
printHeader("生成 " + currentLevel.getChineseName() + " 题目");
|
|
|
|
|
System.out.print("请输入生成题目数量 (10-30,输入 0 返回主菜单): ");
|
|
|
|
|
try {
|
|
|
|
|
int count = Integer.parseInt(scanner.nextLine().trim());
|
|
|
|
|
if (count == 0) {
|
|
|
|
|
System.out.println("已取消生成,返回主菜单。");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if (count >= 10 && count <= 30) {
|
|
|
|
|
paperService.createAndSavePaper(user, count, currentLevel);
|
|
|
|
|
} else {
|
|
|
|
|
System.out.println("输入无效,题目数量必须在 10 到 30 之间。");
|
|
|
|
|
while (true) {
|
|
|
|
|
printHeader("生成 " + currentLevel.getChineseName() + " 题目");
|
|
|
|
|
System.out.print("请输入生成题目数量 (10-30,输入 0 返回主菜单): ");
|
|
|
|
|
String input = scanner.nextLine().trim();
|
|
|
|
|
try {
|
|
|
|
|
int count = Integer.parseInt(input);
|
|
|
|
|
if (count == 0) {
|
|
|
|
|
System.out.println("已取消生成,返回主菜单。");
|
|
|
|
|
break; // 退出循环,返回主菜单
|
|
|
|
|
}
|
|
|
|
|
if (count >= 10 && count <= 30) {
|
|
|
|
|
paperService.createAndSavePaper(user, count, currentLevel);
|
|
|
|
|
break; // 成功生成,退出循环,返回主菜单
|
|
|
|
|
} else {
|
|
|
|
|
System.out.println("无效输入,题目数量必须在 10 到 30 之间。请重新输入。");
|
|
|
|
|
}
|
|
|
|
|
} catch (NumberFormatException e) {
|
|
|
|
|
System.out.println("无效输入,请输入一个有效的数字。请重新输入。");
|
|
|
|
|
}
|
|
|
|
|
} catch (NumberFormatException e) {
|
|
|
|
|
System.out.println("输入无效,请输入一个有效的数字。");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 私有辅助方法,打印美化后的标题行。
|
|
|
|
|
*
|
|
|
|
|
* @param title 要显示的标题文本。
|
|
|
|
|
*/
|
|
|
|
|
private void printHeader(String title) {
|
|
|
|
|
printSeparator();
|
|
|
|
|
System.out.println(title);
|
|
|
|
|
printSeparator();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 私有辅助方法,打印分割线。
|
|
|
|
|
*/
|
|
|
|
|
private void printSeparator() {
|
|
|
|
|
System.out.println("======================================================");
|
|
|
|
|
}
|
|
|
|
|
|