@ -0,0 +1,38 @@
|
|||||||
|
target/
|
||||||
|
!.mvn/wrapper/maven-wrapper.jar
|
||||||
|
!**/src/main/**/target/
|
||||||
|
!**/src/test/**/target/
|
||||||
|
|
||||||
|
### IntelliJ IDEA ###
|
||||||
|
.idea/modules.xml
|
||||||
|
.idea/jarRepositories.xml
|
||||||
|
.idea/compiler.xml
|
||||||
|
.idea/libraries/
|
||||||
|
*.iws
|
||||||
|
*.iml
|
||||||
|
*.ipr
|
||||||
|
|
||||||
|
### Eclipse ###
|
||||||
|
.apt_generated
|
||||||
|
.classpath
|
||||||
|
.factorypath
|
||||||
|
.project
|
||||||
|
.settings
|
||||||
|
.springBeans
|
||||||
|
.sts4-cache
|
||||||
|
|
||||||
|
### NetBeans ###
|
||||||
|
/nbproject/private/
|
||||||
|
/nbbuild/
|
||||||
|
/dist/
|
||||||
|
/nbdist/
|
||||||
|
/.nb-gradle/
|
||||||
|
build/
|
||||||
|
!**/src/main/**/build/
|
||||||
|
!**/src/test/**/build/
|
||||||
|
|
||||||
|
### VS Code ###
|
||||||
|
.vscode/
|
||||||
|
|
||||||
|
### Mac OS ###
|
||||||
|
.DS_Store
|
@ -0,0 +1,25 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<groupId>com.scapeSharing</groupId>
|
||||||
|
<artifactId>Quiz_Generator_personal</artifactId>
|
||||||
|
<version>1.0-SNAPSHOT</version>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<maven.compiler.source>17</maven.compiler.source>
|
||||||
|
<maven.compiler.target>17</maven.compiler.target>
|
||||||
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
|
</properties>
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.projectlombok</groupId>
|
||||||
|
<artifactId>lombok</artifactId>
|
||||||
|
<version>1.18.30</version>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
</project>
|
@ -0,0 +1,32 @@
|
|||||||
|
package com.quizgenerator.common;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
/** 三种习题等级. */
|
||||||
|
@Getter
|
||||||
|
public enum Level {
|
||||||
|
PRIMARY("小学"),
|
||||||
|
JUNIOR_HIGH("初中"),
|
||||||
|
SENIOR_HIGH("高中");
|
||||||
|
|
||||||
|
private final String displayName;
|
||||||
|
|
||||||
|
Level(String displayName) {
|
||||||
|
this.displayName = displayName;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取等级.
|
||||||
|
*
|
||||||
|
* @param text s
|
||||||
|
* @return Level
|
||||||
|
*/
|
||||||
|
public static Level fromString(String text) {
|
||||||
|
for (Level b : Level.values()) {
|
||||||
|
if (b.displayName.equalsIgnoreCase(text)) {
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,49 @@
|
|||||||
|
package com.quizgenerator.common;
|
||||||
|
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
/** 一个用于题目生成的辅助工具类. 包含所有生成器可能共享的静态方法。 */
|
||||||
|
public final class QuestionUtils {
|
||||||
|
|
||||||
|
private static final Random RANDOM = new Random();
|
||||||
|
|
||||||
|
private QuestionUtils() {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查一个字符串是否可以被解析为整数.
|
||||||
|
*
|
||||||
|
* @param str 要检查的字符串
|
||||||
|
* @return 如果是数字则为 true, 否则为 false
|
||||||
|
*/
|
||||||
|
public static boolean isNotNumeric(String str) {
|
||||||
|
if (str == null) {
|
||||||
|
return true; // null 不是数字,所以返回 true
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
Integer.parseInt(str);
|
||||||
|
return false; // 能成功转换,说明是数字,所以返回 false
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
return true; // 转换失败,说明不是数字,所以返回 true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 返回一个随机的四则运算符 (+, -, *, /).
|
||||||
|
*
|
||||||
|
* @return 随机的运算符字符
|
||||||
|
*/
|
||||||
|
public static char getRandomOperator() {
|
||||||
|
char[] operators = {'+', '-', '*', '/'};
|
||||||
|
return operators[RANDOM.nextInt(operators.length)];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 返回一个1到100之间的随机操作数.
|
||||||
|
*
|
||||||
|
* @return 随机整数
|
||||||
|
*/
|
||||||
|
public static int getRandomOperand() {
|
||||||
|
return RANDOM.nextInt(100) + 1;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,30 @@
|
|||||||
|
package com.quizgenerator.entity;
|
||||||
|
|
||||||
|
import com.quizgenerator.common.Level;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/** User类. */
|
||||||
|
@Data
|
||||||
|
public class User {
|
||||||
|
private final String username;
|
||||||
|
private final String password;
|
||||||
|
private final Level level;
|
||||||
|
|
||||||
|
/*public User(String username, String password, Level level) {
|
||||||
|
this.username = username;
|
||||||
|
this.password = password;
|
||||||
|
this.level = level;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUsername() {
|
||||||
|
return username;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPassword() {
|
||||||
|
return password;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Level getLevel() {
|
||||||
|
return level;
|
||||||
|
}*/
|
||||||
|
}
|
@ -0,0 +1,12 @@
|
|||||||
|
package com.quizgenerator.generator;
|
||||||
|
|
||||||
|
/** 题目生成接口. */
|
||||||
|
public interface QuestionGenerator {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 核心方法.
|
||||||
|
*
|
||||||
|
* @return 生成的题目字符串
|
||||||
|
*/
|
||||||
|
String generate();
|
||||||
|
}
|
@ -0,0 +1,32 @@
|
|||||||
|
package com.quizgenerator.generator.impl;
|
||||||
|
|
||||||
|
import com.quizgenerator.common.QuestionUtils;
|
||||||
|
import com.quizgenerator.generator.QuestionGenerator;
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
/** 初中题目生成. */
|
||||||
|
public class JuniorHighGenerator implements QuestionGenerator {
|
||||||
|
private final Random random = new Random();
|
||||||
|
private final QuestionGenerator primaryGenerator = new PrimarySchoolGenerator();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String generate() {
|
||||||
|
// 1.复用primary逻辑
|
||||||
|
// 可以优化,抽出复用逻辑,不应该让同层的类互相依赖
|
||||||
|
String baseQuestion = primaryGenerator.generate();
|
||||||
|
String[] parts = baseQuestion.split(" ");
|
||||||
|
|
||||||
|
int indexToModify;
|
||||||
|
do {
|
||||||
|
indexToModify = random.nextInt(parts.length);
|
||||||
|
} while (QuestionUtils.isNotNumeric(parts[indexToModify]));
|
||||||
|
|
||||||
|
if (random.nextBoolean()) {
|
||||||
|
parts[indexToModify] = parts[indexToModify] + "^2";
|
||||||
|
} else {
|
||||||
|
parts[indexToModify] = "sqrt(" + parts[indexToModify] + ")";
|
||||||
|
}
|
||||||
|
|
||||||
|
return String.join(" ", parts);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,31 @@
|
|||||||
|
package com.quizgenerator.generator.impl;
|
||||||
|
|
||||||
|
import com.quizgenerator.common.QuestionUtils;
|
||||||
|
import com.quizgenerator.generator.QuestionGenerator;
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
/** 小学题目生成. */
|
||||||
|
public class PrimarySchoolGenerator implements QuestionGenerator {
|
||||||
|
private final Random random = new Random();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String generate() {
|
||||||
|
int operandCount = random.nextInt(4) + 2;
|
||||||
|
StringBuilder question = new StringBuilder();
|
||||||
|
question.append(QuestionUtils.getRandomOperand());
|
||||||
|
|
||||||
|
for (int i = 0; i < operandCount - 1; i++) {
|
||||||
|
question.append(" ").append(QuestionUtils.getRandomOperator()).append(" ");
|
||||||
|
|
||||||
|
if (random.nextBoolean() && i < operandCount - 2) {
|
||||||
|
question.append("( ").append(QuestionUtils.getRandomOperand()).append(" ");
|
||||||
|
question.append(QuestionUtils.getRandomOperator()).append(" ");
|
||||||
|
question.append(QuestionUtils.getRandomOperand()).append(" )");
|
||||||
|
i++;
|
||||||
|
} else {
|
||||||
|
question.append(QuestionUtils.getRandomOperand());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return question.toString();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,32 @@
|
|||||||
|
package com.quizgenerator.generator.impl;
|
||||||
|
|
||||||
|
import com.quizgenerator.common.QuestionUtils;
|
||||||
|
import com.quizgenerator.generator.QuestionGenerator;
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
/** 高中题目生成 */
|
||||||
|
public class SeniorHighGenerator implements QuestionGenerator {
|
||||||
|
private final Random random = new Random();
|
||||||
|
private final QuestionGenerator primaryGenerator = new PrimarySchoolGenerator();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String generate() {
|
||||||
|
String baseQuestion = primaryGenerator.generate();
|
||||||
|
String[] parts = baseQuestion.split(" ");
|
||||||
|
|
||||||
|
int indexToModify;
|
||||||
|
do {
|
||||||
|
indexToModify = random.nextInt(parts.length);
|
||||||
|
} while (QuestionUtils.isNotNumeric(parts[indexToModify]));
|
||||||
|
|
||||||
|
String[] trigFuncs = {"sin", "cos", "tan"};
|
||||||
|
String func = trigFuncs[random.nextInt(trigFuncs.length)];
|
||||||
|
|
||||||
|
int[] angles = {30, 45, 60, 90};
|
||||||
|
int angle = angles[random.nextInt(angles.length)];
|
||||||
|
|
||||||
|
parts[indexToModify] = func + "(" + angle + ")";
|
||||||
|
|
||||||
|
return String.join(" ", parts);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,121 @@
|
|||||||
|
package com.quizgenerator.service;
|
||||||
|
|
||||||
|
import com.quizgenerator.common.Level;
|
||||||
|
import com.quizgenerator.generator.QuestionGenerator;
|
||||||
|
import com.quizgenerator.generator.impl.JuniorHighGenerator;
|
||||||
|
import com.quizgenerator.generator.impl.PrimarySchoolGenerator;
|
||||||
|
import com.quizgenerator.generator.impl.SeniorHighGenerator;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileWriter;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.nio.file.Paths;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.time.format.DateTimeFormatter;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
/** 问题核心处理逻辑. */
|
||||||
|
public class QuestionService {
|
||||||
|
private final Map<Level, QuestionGenerator> generators = new HashMap<>();
|
||||||
|
|
||||||
|
/** 构造函数,初始化题目生成器. */
|
||||||
|
public QuestionService() {
|
||||||
|
generators.put(Level.PRIMARY, new PrimarySchoolGenerator());
|
||||||
|
generators.put(Level.JUNIOR_HIGH, new JuniorHighGenerator());
|
||||||
|
generators.put(Level.SENIOR_HIGH, new SeniorHighGenerator());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生成指定数量的不重复题目.
|
||||||
|
*
|
||||||
|
* @param level 题目等级
|
||||||
|
* @param count 题目数量
|
||||||
|
* @param username 用户名
|
||||||
|
* @return 包含不重复题目的列表
|
||||||
|
*/
|
||||||
|
public List<String> generateUniqueQuiz(Level level, int count, String username) {
|
||||||
|
QuestionGenerator generator = generators.get(level);
|
||||||
|
if (generator == null) {
|
||||||
|
throw new IllegalArgumentException("无效的等级代号");
|
||||||
|
}
|
||||||
|
|
||||||
|
Set<String> existingQuestions = loadExistingQuestions(username);
|
||||||
|
List<String> newQuestions = new ArrayList<>();
|
||||||
|
|
||||||
|
while (newQuestions.size() < count) {
|
||||||
|
String question = generator.generate();
|
||||||
|
if (!existingQuestions.contains(question)) {
|
||||||
|
newQuestions.add(question);
|
||||||
|
existingQuestions.add(question);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return newQuestions;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Set<String> loadExistingQuestions(String username) {
|
||||||
|
Set<String> questions = new HashSet<>();
|
||||||
|
File userDir = new File(username);
|
||||||
|
if (!userDir.exists() || !userDir.isDirectory()) {
|
||||||
|
return questions;
|
||||||
|
}
|
||||||
|
|
||||||
|
try (Stream<Path> paths = Files.walk(Paths.get(username))) {
|
||||||
|
paths
|
||||||
|
.filter(Files::isRegularFile)
|
||||||
|
.filter(path -> path.toString().endsWith(".txt"))
|
||||||
|
.forEach(
|
||||||
|
path -> {
|
||||||
|
try {
|
||||||
|
Files.lines(path)
|
||||||
|
.forEach(
|
||||||
|
line -> {
|
||||||
|
// Extract question text, assuming format "1. question..."
|
||||||
|
if (line.matches("^\\d+\\.\\s.*")) {
|
||||||
|
questions.add(line.substring(line.indexOf('.') + 2));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} catch (IOException e) {
|
||||||
|
System.err.println("Error reading file: " + path);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} catch (IOException e) {
|
||||||
|
System.err.println("Error walking directory: " + username);
|
||||||
|
}
|
||||||
|
return questions;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 保存到文件.
|
||||||
|
*
|
||||||
|
* @param questions 问题
|
||||||
|
* @param username 用户
|
||||||
|
*/
|
||||||
|
public void saveQuizToFile(List<String> questions, String username) {
|
||||||
|
File userDir = new File(username);
|
||||||
|
if (!userDir.exists()) {
|
||||||
|
userDir.mkdirs(); // Create directory if it doesn't exist
|
||||||
|
}
|
||||||
|
|
||||||
|
String timestamp =
|
||||||
|
LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd-HH-mm-ss"));
|
||||||
|
String filename = username + "/" + timestamp + ".txt";
|
||||||
|
|
||||||
|
try (FileWriter writer = new FileWriter(filename)) {
|
||||||
|
for (int i = 0; i < questions.size(); i++) {
|
||||||
|
writer.write((i + 1) + ". " + questions.get(i) + "\n");
|
||||||
|
writer.write("\n"); // Blank line between questions
|
||||||
|
}
|
||||||
|
System.out.println("试卷已成功生成并保存至: " + filename);
|
||||||
|
} catch (IOException e) {
|
||||||
|
System.err.println("错误:无法保存文件 " + filename);
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,49 @@
|
|||||||
|
package com.quizgenerator.system;
|
||||||
|
|
||||||
|
import com.quizgenerator.entity.User;
|
||||||
|
import com.quizgenerator.service.QuestionService;
|
||||||
|
import com.quizgenerator.service.UserService;
|
||||||
|
|
||||||
|
/** 应用程序的主入口类,负责启动和协调整个问答流程. */
|
||||||
|
public class QuizApplication {
|
||||||
|
private final LoginHandler loginHandler;
|
||||||
|
private final MainMenuHandler mainMenuHandler;
|
||||||
|
private final ConsoleUi consoleUi;
|
||||||
|
|
||||||
|
/** 构造 QuizApplication 实例. 负责初始化所有必要的服务和处理器. */
|
||||||
|
public QuizApplication() {
|
||||||
|
// 1. 初始化
|
||||||
|
UserService userService = new UserService();
|
||||||
|
QuestionService questionService = new QuestionService();
|
||||||
|
this.consoleUi = new ConsoleUi();
|
||||||
|
|
||||||
|
// 2. 初始化处理器
|
||||||
|
this.loginHandler = new LoginHandler(userService, consoleUi);
|
||||||
|
this.mainMenuHandler = new MainMenuHandler(questionService, consoleUi);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 启动并运行应用程序的主循环. 这个方法会持续运行,处理用户登录和主菜单交互. */
|
||||||
|
public void run() {
|
||||||
|
consoleUi.displayWelcomeMessage();
|
||||||
|
while (true) {
|
||||||
|
// 3. 处理登录流程
|
||||||
|
User currentUser = loginHandler.performLogin();
|
||||||
|
|
||||||
|
// 4. 进入主菜单循环
|
||||||
|
if (currentUser != null) {
|
||||||
|
consoleUi.displayLoginSuccess(currentUser);
|
||||||
|
mainMenuHandler.handleMainMenu(currentUser);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 应用程序的入口点.
|
||||||
|
*
|
||||||
|
* @param args 命令行参数 (未使用).
|
||||||
|
*/
|
||||||
|
public static void main(String[] args) {
|
||||||
|
QuizApplication app = new QuizApplication();
|
||||||
|
app.run();
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in new issue