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.
72 lines
2.3 KiB
72 lines
2.3 KiB
package com.personalproject.service;
|
|
|
|
import com.personalproject.generator.QuestionGenerator;
|
|
import com.personalproject.model.DifficultyLevel;
|
|
import java.security.SecureRandom;
|
|
import java.util.ArrayList;
|
|
import java.util.EnumMap;
|
|
import java.util.HashSet;
|
|
import java.util.List;
|
|
import java.util.Map;
|
|
import java.util.Random;
|
|
import java.util.Set;
|
|
|
|
/**
|
|
* 负责批量生成题目并避免与历史题库重复.
|
|
*/
|
|
public final class QuestionGenerationService {
|
|
|
|
private static final int MAX_ATTEMPTS = 10_000;
|
|
private final Map<DifficultyLevel, QuestionGenerator> generators;
|
|
private final Random random = new SecureRandom();
|
|
|
|
/**
|
|
* 构造函数:复制难度与生成器的映射,保留内部安全副本.
|
|
*
|
|
* @param generatorMap 难度到题目生成器的外部映射.
|
|
*/
|
|
public QuestionGenerationService(Map<DifficultyLevel, QuestionGenerator> generatorMap) {
|
|
generators = new EnumMap<>(DifficultyLevel.class);
|
|
generators.putAll(generatorMap);
|
|
}
|
|
|
|
/**
|
|
* 根据指定难度批量生成不与历史题目重复的新题目.
|
|
*
|
|
* @param level 目标题目难度.
|
|
* @param count 需要生成的题目数量.
|
|
* @param existingQuestions 已存在的题目集合,用于查重.
|
|
* @return 生成的题目列表.
|
|
* @throws IllegalArgumentException 当难度未配置时抛出.
|
|
* @throws IllegalStateException 当达到最大尝试次数仍无法生成足够题目时抛出.
|
|
*/
|
|
public List<String> generateUniqueQuestions(
|
|
DifficultyLevel level, int count, Set<String> existingQuestions) {
|
|
QuestionGenerator generator = generators.get(level);
|
|
if (generator == null) {
|
|
throw new IllegalArgumentException("Unsupported difficulty level: " + level);
|
|
}
|
|
Set<String> produced = new HashSet<>();
|
|
List<String> results = new ArrayList<>();
|
|
int attempts = 0;
|
|
while (results.size() < count) {
|
|
if (attempts >= MAX_ATTEMPTS) {
|
|
throw new IllegalStateException("Unable to generate enough unique questions.");
|
|
}
|
|
attempts++;
|
|
String question = generator.generateQuestion(random).trim();
|
|
if (question.isEmpty()) {
|
|
continue;
|
|
}
|
|
if (existingQuestions.contains(question)) {
|
|
continue;
|
|
}
|
|
if (!produced.add(question)) {
|
|
continue;
|
|
}
|
|
results.add(question);
|
|
}
|
|
return results;
|
|
}
|
|
}
|