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.

245 lines
9.7 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.

package com.mathgenerator.ui;
import com.mathgenerator.auth.User;
import com.mathgenerator.model.Level;
import com.mathgenerator.service.PaperService;
import com.mathgenerator.service.UserService;
import java.util.Optional;
import java.util.Scanner;
/**
* 负责所有控制台用户界面的显示和交互。
*/
public class ConsoleUI {
private final Scanner scanner = new Scanner(System.in);
private final UserService userService;
private final PaperService paperService;
/**
* ConsoleUI的构造函数。
* 通过构造函数接收依赖的服务,这是一种常见的设计模式(依赖注入),
* 使得UI层不负责创建服务只负责使用。
*
* @param userService 用户服务实例。
* @param paperService 试卷服务实例。
*/
public ConsoleUI(UserService userService, PaperService paperService) {
this.userService = userService;
this.paperService = paperService;
}
/**
* 启动并运行整个用户界面主循环。
*/
public void run() {
while (true) {
// 在主循环中加入注册选项
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("请输入用户名和密码 (用空格隔开): \n> ");
String[] credentials = scanner.nextLine().split("\\s+");
if (credentials.length != 2) {
System.out.println("输入格式错误。");
return Optional.empty();
}
// 调用新的UserService进行登录
Optional<User> userOptional = userService.login(credentials[0], credentials[1]);
if (userOptional.isEmpty()) {
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());
System.out.println("当前选择为 " + currentLevel.getChineseName() + " 出题");
while (true) {
printHeader("当前用户: " + user.username() + " | 当前难度: " + currentLevel.getChineseName());
System.out.println("1. 生成题目");
System.out.println("2. 切换难度级别");
System.out.println("3. 退出当前用户");
System.out.println("4. 退出程序");
printSeparator();
System.out.print("请选择操作 (1-4): ");
String choice = scanner.nextLine().trim();
switch (choice) {
case "1" -> handleGeneration(user, currentLevel);
case "2" -> currentLevel = handleLevelSwitchMenu(currentLevel);
case "3" -> {
System.out.println("用户 " + user.username() + " 已退出。");
return;
}
case "4" -> {
System.out.println("感谢使用,程序已退出。");
System.exit(0);
}
default -> System.out.println("无效输入,请输入 1-4 之间的数字。");
}
}
}
/**
* 私有辅助方法,处理切换难度的子菜单,加入循环以处理无效输入。
*
* @param currentLevel 当前的难度级别。
* @return 用户选择的新的难度级别,如果选择返回则为原级别。
*/
private Level handleLevelSwitchMenu(Level currentLevel) {
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":
System.out.println("难度已成功切换为 " + Level.PRIMARY.getChineseName() + "。");
return Level.PRIMARY; // 直接返回,退出循环
case "2":
System.out.println("难度已成功切换为 " + Level.JUNIOR_HIGH.getChineseName() + "。");
return Level.JUNIOR_HIGH; // 直接返回,退出循环
case "3":
System.out.println("难度已成功切换为 " + Level.SENIOR_HIGH.getChineseName() + "。");
return Level.SENIOR_HIGH; // 直接返回,退出循环
case "0":
System.out.println("已返回主菜单。");
return currentLevel; // 返回当前难度,退出循环
default:
System.out.println("无效输入,请输入 0-3 之间的数字。");
}
}
}
/**
* 私有辅助方法,处理生成题目的逻辑。
*
* @param user 当前登录的用户。
* @param currentLevel 当前选择的难度级别。
*/
private void handleGeneration(User user, Level currentLevel) {
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("无效输入,请输入一个有效的数字。请重新输入。");
}
}
}
/**
* 私有辅助方法,打印美化后的标题行。
*
* @param title 要显示的标题文本。
*/
private void printHeader(String title) {
printSeparator();
System.out.println(title);
printSeparator();
}
/**
* 私有辅助方法,打印分割线。
*/
private void printSeparator() {
System.out.println("======================================================");
}
}