|
|
|
|
@ -0,0 +1,469 @@
|
|
|
|
|
package com.mathpaper;
|
|
|
|
|
|
|
|
|
|
import com.mathpaper.model.User;
|
|
|
|
|
import com.mathpaper.generator.QuestionGenerator;
|
|
|
|
|
import com.mathpaper.generator.PrimaryGenerator;
|
|
|
|
|
import com.mathpaper.generator.JuniorGenerator;
|
|
|
|
|
import com.mathpaper.generator.SeniorGenerator;
|
|
|
|
|
import com.mathpaper.util.FileUtil;
|
|
|
|
|
import com.mathpaper.util.DuplicateChecker;
|
|
|
|
|
|
|
|
|
|
import java.util.ArrayList;
|
|
|
|
|
import java.util.HashMap;
|
|
|
|
|
import java.util.List;
|
|
|
|
|
import java.util.Map;
|
|
|
|
|
import java.util.Scanner;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 数学试卷生成程序主类
|
|
|
|
|
* 负责用户登录、交互和试卷生成的主要流程
|
|
|
|
|
*
|
|
|
|
|
* @author 系统
|
|
|
|
|
* @version 2.0
|
|
|
|
|
*/
|
|
|
|
|
public class Main {
|
|
|
|
|
|
|
|
|
|
// 常量定义
|
|
|
|
|
private static final int MIN_QUESTIONS = 1;
|
|
|
|
|
private static final int MAX_QUESTIONS = 100;
|
|
|
|
|
private static final int PREVIEW_COUNT = 5;
|
|
|
|
|
private static final int MAX_ATTEMPTS_MULTIPLIER = 10;
|
|
|
|
|
private static final String GRADE_SWITCH_PREFIX = "切换为";
|
|
|
|
|
private static final String EXIT_COMMAND = "-1";
|
|
|
|
|
|
|
|
|
|
// 当前年级(全局变量)
|
|
|
|
|
private static String currentGrade = "小学";
|
|
|
|
|
|
|
|
|
|
// 界面美化常量
|
|
|
|
|
private static final String SEPARATOR = "=" + "=".repeat(50);
|
|
|
|
|
private static final String MENU_SEPARATOR = "=" + "=".repeat(50);
|
|
|
|
|
private static final int PROGRESS_BAR_LENGTH = 30;
|
|
|
|
|
|
|
|
|
|
// 预设用户账号
|
|
|
|
|
private static final Map<String, User> USERS = new HashMap<>();
|
|
|
|
|
|
|
|
|
|
static {
|
|
|
|
|
initializeUsers();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 初始化用户账号
|
|
|
|
|
*/
|
|
|
|
|
private static void initializeUsers() {
|
|
|
|
|
// 小学用户(中文和英文用户名)
|
|
|
|
|
addUser("张三1", "123", "小学");
|
|
|
|
|
addUser("张三2", "123", "小学");
|
|
|
|
|
addUser("张三3", "123", "小学");
|
|
|
|
|
addUser("zhangsan1", "123", "小学");
|
|
|
|
|
addUser("zhangsan2", "123", "小学");
|
|
|
|
|
addUser("zhangsan3", "123", "小学");
|
|
|
|
|
addUser("primary1", "123", "小学");
|
|
|
|
|
addUser("primary2", "123", "小学");
|
|
|
|
|
|
|
|
|
|
// 初中用户(中文和英文用户名)
|
|
|
|
|
addUser("李四1", "123", "初中");
|
|
|
|
|
addUser("李四2", "123", "初中");
|
|
|
|
|
addUser("李四3", "123", "初中");
|
|
|
|
|
addUser("lisi1", "123", "初中");
|
|
|
|
|
addUser("lisi2", "123", "初中");
|
|
|
|
|
addUser("lisi3", "123", "初中");
|
|
|
|
|
addUser("junior1", "123", "初中");
|
|
|
|
|
addUser("junior2", "123", "初中");
|
|
|
|
|
|
|
|
|
|
// 高中用户(中文和英文用户名)
|
|
|
|
|
addUser("王五1", "123", "高中");
|
|
|
|
|
addUser("王五2", "123", "高中");
|
|
|
|
|
addUser("王五3", "123", "高中");
|
|
|
|
|
addUser("wangwu1", "123", "高中");
|
|
|
|
|
addUser("wangwu2", "123", "高中");
|
|
|
|
|
addUser("wangwu3", "123", "高中");
|
|
|
|
|
addUser("senior1", "123", "高中");
|
|
|
|
|
addUser("senior2", "123", "高中");
|
|
|
|
|
|
|
|
|
|
// 测试账号
|
|
|
|
|
addUser("test123", "123", "小学");
|
|
|
|
|
addUser("测试", "123", "小学");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 添加用户到系统
|
|
|
|
|
*/
|
|
|
|
|
private static void addUser(String username, String password, String grade) {
|
|
|
|
|
// 由于User类已简化,这里只存储用户名
|
|
|
|
|
try {
|
|
|
|
|
USERS.put(username, new User(username));
|
|
|
|
|
} catch (IllegalArgumentException e) {
|
|
|
|
|
System.err.println("添加用户失败: " + username + " - " + e.getMessage());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 程序主入口
|
|
|
|
|
*/
|
|
|
|
|
public static void main(String[] args) {
|
|
|
|
|
Scanner scanner = new Scanner(System.in);
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
// 定期清理过期缓存
|
|
|
|
|
DuplicateChecker.cleanupExpiredCache();
|
|
|
|
|
|
|
|
|
|
// 用户登录
|
|
|
|
|
User user = performLogin(scanner);
|
|
|
|
|
if (user == null) {
|
|
|
|
|
System.out.println("登录失败,程序退出");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 主交互循环
|
|
|
|
|
runMainLoop(scanner, user);
|
|
|
|
|
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
System.err.println("程序运行出现异常: " + e.getMessage());
|
|
|
|
|
} finally {
|
|
|
|
|
scanner.close();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 用户登录
|
|
|
|
|
*/
|
|
|
|
|
private static User performLogin(Scanner scanner) {
|
|
|
|
|
System.out.println("=== 用户登录 ===");
|
|
|
|
|
System.out.println("请输入用户名和密码进行登录");
|
|
|
|
|
System.out.println();
|
|
|
|
|
|
|
|
|
|
while (true) {
|
|
|
|
|
System.out.print("用户名: ");
|
|
|
|
|
String username = scanner.nextLine().trim();
|
|
|
|
|
|
|
|
|
|
// 验证用户名格式
|
|
|
|
|
String validationError = User.getValidationError(username);
|
|
|
|
|
if (validationError != null) {
|
|
|
|
|
System.out.println("❌ " + validationError);
|
|
|
|
|
System.out.println("请重新输入:");
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 检查用户是否存在
|
|
|
|
|
if (!USERS.containsKey(username)) {
|
|
|
|
|
System.out.println("❌ 用户名不存在,请检查输入或使用以下用户名:");
|
|
|
|
|
System.out.println("中文用户:张三1, 张三2, 张三3, 李四1, 李四2, 李四3, 王五1, 王五2, 王五3, 测试");
|
|
|
|
|
System.out.println("英文用户:zhangsan1, zhangsan2, zhangsan3, lisi1, lisi2, lisi3, wangwu1, wangwu2, wangwu3, test123");
|
|
|
|
|
System.out.println("请重新输入:");
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
System.out.print("密码: ");
|
|
|
|
|
String password = scanner.nextLine().trim();
|
|
|
|
|
|
|
|
|
|
// 验证密码(所有用户密码都是123)
|
|
|
|
|
if (!"123".equals(password)) {
|
|
|
|
|
System.out.println("❌ 密码错误!所有用户的密码都是 123");
|
|
|
|
|
System.out.println("请重新输入:");
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
User user = new User(username);
|
|
|
|
|
System.out.println("✅ 登录成功!欢迎," + username + "!");
|
|
|
|
|
System.out.println();
|
|
|
|
|
return user;
|
|
|
|
|
} catch (IllegalArgumentException e) {
|
|
|
|
|
System.out.println("❌ " + e.getMessage());
|
|
|
|
|
System.out.println("请重新输入:");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 验证登录信息(简化版本)
|
|
|
|
|
*/
|
|
|
|
|
private static User validateLogin(String input) {
|
|
|
|
|
String[] parts = input.split("\\s+");
|
|
|
|
|
|
|
|
|
|
if (parts.length != 2) {
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
String username = parts[0].trim();
|
|
|
|
|
String password = parts[1].trim();
|
|
|
|
|
|
|
|
|
|
// 简单验证:检查用户是否存在
|
|
|
|
|
User user = USERS.get(username);
|
|
|
|
|
if (user != null) {
|
|
|
|
|
return user;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 运行主交互循环
|
|
|
|
|
*/
|
|
|
|
|
private static void runMainLoop(Scanner scanner, User user) {
|
|
|
|
|
QuestionGenerator generator = getGenerator(currentGrade);
|
|
|
|
|
|
|
|
|
|
while (true) {
|
|
|
|
|
displayMainMenu(user);
|
|
|
|
|
String choice = scanner.nextLine().trim();
|
|
|
|
|
|
|
|
|
|
switch (choice) {
|
|
|
|
|
case "1":
|
|
|
|
|
handleGradeSwitch(scanner, user);
|
|
|
|
|
generator = getGenerator(currentGrade);
|
|
|
|
|
break;
|
|
|
|
|
case "2":
|
|
|
|
|
handleQuestionGeneration(scanner, user, generator);
|
|
|
|
|
break;
|
|
|
|
|
case "3":
|
|
|
|
|
displayExitMessage();
|
|
|
|
|
return;
|
|
|
|
|
default:
|
|
|
|
|
System.out.println("❌ 无效选择,请重新输入!");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 显示欢迎界面
|
|
|
|
|
*/
|
|
|
|
|
private static void displayWelcomeScreen(User user) {
|
|
|
|
|
System.out.println(SEPARATOR);
|
|
|
|
|
System.out.println("🎓 数学题目生成系统");
|
|
|
|
|
System.out.println("👤 用户:" + user.getUsername());
|
|
|
|
|
System.out.println("📚 当前年级:" + currentGrade);
|
|
|
|
|
System.out.println(SEPARATOR);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 显示主菜单
|
|
|
|
|
*/
|
|
|
|
|
private static void displayMainMenu(User user) {
|
|
|
|
|
System.out.println(MENU_SEPARATOR);
|
|
|
|
|
System.out.println("📚 当前年级:" + currentGrade);
|
|
|
|
|
System.out.println("👤 当前用户:" + user.getUsername());
|
|
|
|
|
System.out.println();
|
|
|
|
|
System.out.println("1. 切换年级");
|
|
|
|
|
System.out.println("2. 生成试卷");
|
|
|
|
|
System.out.println("3. 退出系统");
|
|
|
|
|
System.out.println(MENU_SEPARATOR);
|
|
|
|
|
System.out.print("\n🔹 请选择操作(当前:" + currentGrade + "):");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 显示分隔线
|
|
|
|
|
*/
|
|
|
|
|
private static void displaySeparator() {
|
|
|
|
|
System.out.println("\n" + "-".repeat(30) + "\n");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 显示退出消息
|
|
|
|
|
*/
|
|
|
|
|
private static void displayExitMessage() {
|
|
|
|
|
System.out.println("\n" + SEPARATOR);
|
|
|
|
|
System.out.println("👋 感谢使用数学题目生成系统!");
|
|
|
|
|
System.out.println("🎉 祝您学习愉快,再见!");
|
|
|
|
|
System.out.println(SEPARATOR);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 根据年级获取对应的题目生成器
|
|
|
|
|
*/
|
|
|
|
|
private static QuestionGenerator getGenerator(String grade) {
|
|
|
|
|
switch (grade) {
|
|
|
|
|
case "小学":
|
|
|
|
|
return new PrimaryGenerator();
|
|
|
|
|
case "初中":
|
|
|
|
|
return new JuniorGenerator();
|
|
|
|
|
case "高中":
|
|
|
|
|
return new SeniorGenerator();
|
|
|
|
|
default:
|
|
|
|
|
System.err.println("未知年级: " + grade + ",使用小学模式");
|
|
|
|
|
return new PrimaryGenerator();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 验证年级是否有效
|
|
|
|
|
*/
|
|
|
|
|
private static boolean isValidGrade(String grade) {
|
|
|
|
|
return "小学".equals(grade) || "初中".equals(grade) || "高中".equals(grade);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 生成并保存试卷
|
|
|
|
|
*/
|
|
|
|
|
private static void generateAndSavePaper(QuestionGenerator generator, int count, User user) {
|
|
|
|
|
try {
|
|
|
|
|
List<String> questions = generateQuestionsWithProgress(generator, count, user.getUsername());
|
|
|
|
|
|
|
|
|
|
if (questions.isEmpty()) {
|
|
|
|
|
System.out.println("❌ 生成失败:无法生成题目,请稍后重试");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (questions.size() < count) {
|
|
|
|
|
System.out.println("⚠️ 注意:由于查重限制,实际生成了 " + questions.size() + " 道题目");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
System.out.print("💾 正在保存试卷...");
|
|
|
|
|
String path = FileUtil.getSavePath(user.getUsername());
|
|
|
|
|
FileUtil.savePaper(path, questions);
|
|
|
|
|
System.out.println(" 完成!");
|
|
|
|
|
System.out.println("✅ 试卷已保存至:" + path);
|
|
|
|
|
|
|
|
|
|
displayQuestionPreview(questions);
|
|
|
|
|
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
System.err.println("❌ 生成试卷时出现错误: " + e.getMessage());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 带进度提示的题目生成
|
|
|
|
|
*/
|
|
|
|
|
private static List<String> generateQuestionsWithProgress(QuestionGenerator generator, int count, String username) {
|
|
|
|
|
List<String> questions = new ArrayList<>();
|
|
|
|
|
generator.clearCurrentQuestions();
|
|
|
|
|
|
|
|
|
|
int attempts = 0;
|
|
|
|
|
int maxAttempts = count * MAX_ATTEMPTS_MULTIPLIER;
|
|
|
|
|
|
|
|
|
|
System.out.println("📊 生成进度:");
|
|
|
|
|
|
|
|
|
|
while (questions.size() < count && attempts < maxAttempts) {
|
|
|
|
|
try {
|
|
|
|
|
String question = generator.generateUniqueQuestion();
|
|
|
|
|
|
|
|
|
|
if (question != null && !question.trim().isEmpty()) {
|
|
|
|
|
// 检查是否与历史题目重复
|
|
|
|
|
if (!DuplicateChecker.isDuplicate(question, username)) {
|
|
|
|
|
questions.add(question);
|
|
|
|
|
|
|
|
|
|
// 显示进度
|
|
|
|
|
displayProgress(questions.size(), count);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
System.err.println("⚠️ 生成题目时出现错误: " + e.getMessage());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
attempts++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (questions.size() < count && attempts >= maxAttempts) {
|
|
|
|
|
System.out.println("\n⚠️ 提示:已达到最大尝试次数,可能存在题目重复过多的情况");
|
|
|
|
|
} else if (questions.size() == count) {
|
|
|
|
|
System.out.println("\n🎉 题目生成完成!");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return questions;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 显示生成进度
|
|
|
|
|
*/
|
|
|
|
|
private static void displayProgress(int current, int total) {
|
|
|
|
|
int percentage = (int) ((double) current / total * 100);
|
|
|
|
|
int progressLength = (int) ((double) current / total * PROGRESS_BAR_LENGTH);
|
|
|
|
|
|
|
|
|
|
StringBuilder progressBar = new StringBuilder();
|
|
|
|
|
progressBar.append("[");
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < PROGRESS_BAR_LENGTH; i++) {
|
|
|
|
|
if (i < progressLength) {
|
|
|
|
|
progressBar.append("█");
|
|
|
|
|
} else {
|
|
|
|
|
progressBar.append("░");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
progressBar.append("]");
|
|
|
|
|
|
|
|
|
|
System.out.print("\r" + progressBar.toString() + " " + current + "/" + total + " (" + percentage + "%)");
|
|
|
|
|
|
|
|
|
|
if (current == total) {
|
|
|
|
|
System.out.println(); // 换行
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 显示题目预览
|
|
|
|
|
*/
|
|
|
|
|
private static void displayQuestionPreview(List<String> questions) {
|
|
|
|
|
System.out.println("\n📝 题目预览");
|
|
|
|
|
System.out.println("─".repeat(40));
|
|
|
|
|
|
|
|
|
|
int displayCount = Math.min(PREVIEW_COUNT, questions.size());
|
|
|
|
|
for (int i = 0; i < displayCount; i++) {
|
|
|
|
|
System.out.println((i + 1) + ". " + questions.get(i));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (questions.size() > PREVIEW_COUNT) {
|
|
|
|
|
System.out.println(" ... 还有 " + (questions.size() - PREVIEW_COUNT) + " 道题目");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
System.out.println("─".repeat(40));
|
|
|
|
|
System.out.println("📊 总计:" + questions.size() + " 道题目");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 处理年级切换
|
|
|
|
|
*/
|
|
|
|
|
private static void handleGradeSwitch(Scanner scanner, User user) {
|
|
|
|
|
System.out.println("\n📚 请选择年级:");
|
|
|
|
|
System.out.println("1. 小学");
|
|
|
|
|
System.out.println("2. 初中");
|
|
|
|
|
System.out.println("3. 高中");
|
|
|
|
|
System.out.print("请输入选择(1-3):");
|
|
|
|
|
|
|
|
|
|
String choice = scanner.nextLine().trim();
|
|
|
|
|
String newGrade = null;
|
|
|
|
|
|
|
|
|
|
switch (choice) {
|
|
|
|
|
case "1":
|
|
|
|
|
newGrade = "小学";
|
|
|
|
|
break;
|
|
|
|
|
case "2":
|
|
|
|
|
newGrade = "初中";
|
|
|
|
|
break;
|
|
|
|
|
case "3":
|
|
|
|
|
newGrade = "高中";
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
System.out.println("❌ 无效选择!");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!newGrade.equals(currentGrade)) {
|
|
|
|
|
currentGrade = newGrade;
|
|
|
|
|
System.out.println("✅ 已切换到" + currentGrade + "模式");
|
|
|
|
|
} else {
|
|
|
|
|
System.out.println("ℹ️ 当前已是" + currentGrade + "模式");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 处理题目生成
|
|
|
|
|
*/
|
|
|
|
|
private static void handleQuestionGeneration(Scanner scanner, User user, QuestionGenerator generator) {
|
|
|
|
|
System.out.print("\n📝 请输入要生成的题目数量(1-50):");
|
|
|
|
|
String input = scanner.nextLine().trim();
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
int count = Integer.parseInt(input);
|
|
|
|
|
if (count < 1 || count > 50) {
|
|
|
|
|
System.out.println("❌ 题目数量必须在1-50之间!");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
System.out.println("\n🔄 开始生成" + count + "道" + currentGrade + "数学题目...");
|
|
|
|
|
generateAndSavePaper(generator, count, user);
|
|
|
|
|
|
|
|
|
|
} catch (NumberFormatException e) {
|
|
|
|
|
System.out.println("❌ 请输入有效的数字!");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|