diff --git a/src/main/java/com/project/information/application/impl/KnowledgePointApplicationServiceImpl.java b/src/main/java/com/project/information/application/impl/KnowledgePointApplicationServiceImpl.java index 30aa484..cfb6ffe 100644 --- a/src/main/java/com/project/information/application/impl/KnowledgePointApplicationServiceImpl.java +++ b/src/main/java/com/project/information/application/impl/KnowledgePointApplicationServiceImpl.java @@ -122,7 +122,7 @@ public class KnowledgePointApplicationServiceImpl implements KnowledgePointAppli log.info("文件 [{}] 解析请求成功,返回结果:{}", fileName, response.getBody()); // 4. 解析 Python 返回的结果并入库 - List knowledgePointEntities = parseAnalysisResponse(response, id); + List knowledgePointEntities = parseAnalysisResponse(response, id,fileName); if (!CollectionUtils.isEmpty(knowledgePointEntities)) { knowledgePointBaseService.saveBatch(knowledgePointEntities); @@ -137,7 +137,7 @@ public class KnowledgePointApplicationServiceImpl implements KnowledgePointAppli /** * 解析返回数据 */ - public List parseAnalysisResponse(ResponseEntity response,Long id) throws JsonProcessingException { + public List parseAnalysisResponse(ResponseEntity response,Long id,String fileName) throws JsonProcessingException { if (response == null || response.getBody() == null) { return Collections.emptyList(); } @@ -188,7 +188,7 @@ public class KnowledgePointApplicationServiceImpl implements KnowledgePointAppli KnowledgePointEntity entity = new KnowledgePointEntity(); entity.setContent((String) item.get("knowledge")); - entity.setParseName((String) item.get("products")); + entity.setParseName(fileName); entity.setKnowledgeType(hasYellow ? 0 : 1); entity.setExamFocusList(focusList); entity.setInformationId(id); diff --git a/src/main/java/com/project/interaction/domain/dto/ProduceDTO.java b/src/main/java/com/project/interaction/domain/dto/ProduceDTO.java new file mode 100644 index 0000000..c4a7951 --- /dev/null +++ b/src/main/java/com/project/interaction/domain/dto/ProduceDTO.java @@ -0,0 +1,21 @@ +package com.project.interaction.domain.dto; + +import com.project.question.domain.enums.QuestionSourceTypeEnum; +import com.project.task.domain.enums.QuestionTypeEnum; +import lombok.Data; + +@Data +public class ProduceDTO { + Long sourceId; + QuestionSourceTypeEnum sourceType; + int needSingleCount; + int needMultipleCount; + int needJudgmentCount; + int generateCount = 0; + + public boolean isCompleted() { + int totalNeed = needSingleCount + needJudgmentCount + needMultipleCount; + // 已生成数量等于总需要数量,或总需要数量≤0时,视为完成 + return generateCount >= totalNeed || totalNeed <= 0; + } +} diff --git a/src/main/java/com/project/interaction/domain/service/impl/SaveClusterDomainServiceImpl.java b/src/main/java/com/project/interaction/domain/service/impl/SaveClusterDomainServiceImpl.java index 6c3c93f..ea76da7 100644 --- a/src/main/java/com/project/interaction/domain/service/impl/SaveClusterDomainServiceImpl.java +++ b/src/main/java/com/project/interaction/domain/service/impl/SaveClusterDomainServiceImpl.java @@ -5,6 +5,7 @@ import com.project.information.domain.dto.KnowledgePointDTO; import com.project.information.domain.entity.KnowledgePointEntity; import com.project.information.domain.service.KnowledgePointBaseService; import com.project.interaction.domain.dto.ClusterCallbackDTO; +import com.project.interaction.domain.dto.ProduceDTO; import com.project.interaction.domain.service.SaveClusterDomainService; import com.project.question.domain.entity.TaskKnowledgeClusterEntity; import com.project.question.domain.entity.TaskKnowledgePointEntity; @@ -19,10 +20,7 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Objects; +import java.util.*; @Service @Slf4j @@ -43,8 +41,10 @@ public class SaveClusterDomainServiceImpl implements SaveClusterDomainService { @Autowired private GenerateQuestionDomainService generateQuestionDomainService; + private final Integer ROUND_NUM = 2; + @Override - public void saveCluster(Long taskId, List clusters) throws Exception { + public void saveCluster(Long taskId, List clusters) { TaskEntity taskEntity = taskBaseService.getById(taskId); int u = 0; if (Objects.isNull(taskEntity) || Objects.isNull(taskEntity.getParticipantNum()) || taskEntity.getParticipantNum() <= 0) { @@ -52,6 +52,9 @@ public class SaveClusterDomainServiceImpl implements SaveClusterDomainService { } u = taskEntity.getParticipantNum(); log.info(">>> [回调处理] 开始持久化任务[{}]聚类结果,计划人数U={}", taskId, u); + + List produceDTOList = new ArrayList<>(); + for (ClusterCallbackDTO.ClusterItem cluster : clusters) { // 1.保存任务知识点簇 TaskKnowledgeClusterEntity clusterEntity = new TaskKnowledgeClusterEntity(); @@ -87,15 +90,92 @@ public class SaveClusterDomainServiceImpl implements SaveClusterDomainService { for (TaskKnowledgePointEntity kp : taskKpList) { // 调用题目生成方法 - for (QuestionTypeEnum value : QuestionTypeEnum.values()) { - generateQuestionDomainService.produce(kp.getId(), value , QuestionSourceTypeEnum.Single_Concept , (int) Math.ceil(targetNum * questionTypeMap.get(value.name()))); - } + produceDTOList.add(buildDTO(kp.getId() , QuestionSourceTypeEnum.Single_Concept, + (int) Math.ceil(targetNum * questionTypeMap.get(QuestionTypeEnum.TRUE_FALSE.name())), + (int) Math.ceil(targetNum * questionTypeMap.get(QuestionTypeEnum.SINGLE_CHOICE.name())), + (int) Math.ceil(targetNum * questionTypeMap.get(QuestionTypeEnum.MULTIPLE_CHOICE.name())))); } if (clusterEntity.getClusterSize() > 1) { // 簇生成目标量 int clusterTargetNum = (int) Math.ceil(1.2 * u * clusterEntity.getClusterSize() * questionTypeMap.get(QuestionTypeEnum.MULTIPLE_CHOICE.name())); - generateQuestionDomainService.produce(clusterEntity.getId(), QuestionTypeEnum.MULTIPLE_CHOICE , QuestionSourceTypeEnum.Multi_Concept , clusterTargetNum); + produceDTOList.add(buildDTO(clusterEntity.getId(), QuestionSourceTypeEnum.Multi_Concept ,0,0, clusterTargetNum)); + } + } + + //生成题目 + produce(produceDTOList); + } + + private void produce(List produceDTOList) { + if (produceDTOList == null || produceDTOList.isEmpty()) { + return; + } + + //打乱顺序 + Collections.shuffle(produceDTOList); + + boolean hasUnfinished; + do { + hasUnfinished = false; + // 遍历所有DTO,逐一生成 + for (ProduceDTO produceDTO : produceDTOList) { + // 跳过已完成的DTO,减少无效遍历 + if (produceDTO.isCompleted()) { + continue; + } + // 存在未完成的DTO,需要继续循环 + hasUnfinished = true; + + //生成单选题 + generateSingleTypeQuestion(produceDTO, QuestionTypeEnum.SINGLE_CHOICE, + produceDTO.getNeedSingleCount(), produceDTO::setNeedSingleCount); + + //生成判断题 + generateSingleTypeQuestion(produceDTO, QuestionTypeEnum.TRUE_FALSE, + produceDTO.getNeedJudgmentCount(), produceDTO::setNeedJudgmentCount); + + //生成多选题 + generateSingleTypeQuestion(produceDTO, QuestionTypeEnum.MULTIPLE_CHOICE, + produceDTO.getNeedMultipleCount(), produceDTO::setNeedMultipleCount); } + } while (hasUnfinished); + } + + /** + * 抽取通用方法:生成单种题型的题目,避免重复代码 + * @param dto DTO对象 + * @param type 题型 + * @param needCount 需生成数量 + * @param setNeedCount 设置剩余数量的方法 + */ + private void generateSingleTypeQuestion(ProduceDTO dto, QuestionTypeEnum type, + int needCount, java.util.function.Consumer setNeedCount) { + // 校验:需生成数量≤0时,直接返回 + if (needCount <= 0) { + return; } + + // 计算本轮生成数量:最多ROUND_NUM道,不超过剩余数量 + int generateNum = Math.min(ROUND_NUM, needCount); + + // 调用生成方法 + generateQuestionDomainService.produce(dto.getSourceId(), type, dto.getSourceType(), generateNum); + + // 更新剩余数量 + int remainCount = needCount - generateNum; + setNeedCount.accept(Math.max(0, remainCount)); // 确保剩余数量≥0 + + // 更新已生成总数量 + dto.setGenerateCount(dto.getGenerateCount() + generateNum); + } + + private ProduceDTO buildDTO(Long sourceId , QuestionSourceTypeEnum sourceType, int needJudgmentCount,int needSingleCount, int needMultipleCount) { + ProduceDTO produceDTO = new ProduceDTO(); + produceDTO.setSourceId(sourceId); + produceDTO.setSourceType(sourceType); + produceDTO.setNeedJudgmentCount(needJudgmentCount); + produceDTO.setNeedSingleCount(needSingleCount); + produceDTO.setNeedMultipleCount(needMultipleCount); + return produceDTO; } } diff --git a/src/main/resources/application-test.yml b/src/main/resources/application-test.yml index 496714e..12af9f8 100644 --- a/src/main/resources/application-test.yml +++ b/src/main/resources/application-test.yml @@ -83,7 +83,7 @@ jwt: question: generation: # 限流速率:每秒允许的API请求数 - rate-limit: 20 + rate-limit: 5 downgrade: false scheduled-task: