diff --git a/src/main/java/com/project/exam/domain/service/impl/AssemblePaperDomainServiceImpl.java b/src/main/java/com/project/exam/domain/service/impl/AssemblePaperDomainServiceImpl.java index c5e65ca..16a9cc7 100644 --- a/src/main/java/com/project/exam/domain/service/impl/AssemblePaperDomainServiceImpl.java +++ b/src/main/java/com/project/exam/domain/service/impl/AssemblePaperDomainServiceImpl.java @@ -19,6 +19,7 @@ import com.project.question.domain.service.TaskKnowledgePointBaseService; import com.project.question.mapper.QuestionKpRelMapper; import com.project.question.mapper.QuestionMapper; import com.project.exam.domain.dto.ExamRecordDTO; +import com.project.question.mapper.TaskKnowledgePointMapper; import com.project.task.domain.dto.TaskDTO; import com.project.task.domain.dto.TaskUserDTO; import com.project.exam.domain.entity.ExamRecordEntity; @@ -55,6 +56,9 @@ public class AssemblePaperDomainServiceImpl implements AssemblePaperDomainServic @Autowired private TaskKnowledgePointBaseService taskKnowledgePointBaseService; + @Autowired + private TaskKnowledgePointMapper taskKnowledgePointMapper; + @Autowired private TaskBaseService taskBaseService; @@ -115,10 +119,12 @@ public class AssemblePaperDomainServiceImpl implements AssemblePaperDomainServic Set coveredKpPool = new HashSet<>(); // 最终选定题目 List selectedQuestionList = new ArrayList<>(); - // 分配种子:前N3个多选,中间N1个单选,最后N2个判断 + // 分配种子:前N3个多选 List mcSeeds = seedKpList.subList(0, taskDTO.getMultipleChoiceNum()); - List scSeeds = seedKpList.subList(taskDTO.getMultipleChoiceNum() , taskDTO.getMultipleChoiceNum() + taskDTO.getSingleChoiceNum()); - List tfSeeds = seedKpList.subList(taskDTO.getMultipleChoiceNum() + taskDTO.getSingleChoiceNum() , totalQuestionNum); + //重新根据库存选取单选、判断 + List seedKpListBySupply = selectBySupply(taskDTO); + List scSeeds = seedKpListBySupply.subList(0,taskDTO.getSingleChoiceNum()); + List tfSeeds = seedKpListBySupply.subList(taskDTO.getSingleChoiceNum() , taskDTO.getSingleChoiceNum() + taskDTO.getTrueFalseNum()); // 选择单选题 pickWithLock(scSeeds, QuestionTypeEnum.SINGLE_CHOICE , selectedQuestionList, coveredKpPool); // 选择判断题 @@ -219,6 +225,14 @@ public class AssemblePaperDomainServiceImpl implements AssemblePaperDomainServic .toList(); } + /** + * 根据单选题库存选取 + */ + private List selectBySupply(TaskDTO dto){ + return taskKnowledgePointMapper.selectKpOrderBySingle(dto.getId()); + } + + /** * 通用的普通题抽取逻辑(锁 KP 级别) */ diff --git a/src/main/java/com/project/interaction/application/impl/AlgorithmApplicationServiceImpl.java b/src/main/java/com/project/interaction/application/impl/AlgorithmApplicationServiceImpl.java index 0e96ade..1f00d39 100644 --- a/src/main/java/com/project/interaction/application/impl/AlgorithmApplicationServiceImpl.java +++ b/src/main/java/com/project/interaction/application/impl/AlgorithmApplicationServiceImpl.java @@ -41,7 +41,7 @@ public class AlgorithmApplicationServiceImpl implements AlgorithmApplicationServ @Override public void postToGenerateQuestion(List dtoList, QuestionTypeEnum questionType, int num) throws Exception { - postToGenerateQuestionDomainService.postToGenerateQuestion(dtoList , questionType , num); + postToGenerateQuestionDomainService.postToGenerateQuestion(dtoList , questionType , num, false); } diff --git a/src/main/java/com/project/interaction/domain/dto/GenerateQuestionQueueDTO.java b/src/main/java/com/project/interaction/domain/dto/GenerateQuestionQueueDTO.java index 0e04c5b..99b51a5 100644 --- a/src/main/java/com/project/interaction/domain/dto/GenerateQuestionQueueDTO.java +++ b/src/main/java/com/project/interaction/domain/dto/GenerateQuestionQueueDTO.java @@ -44,5 +44,9 @@ public class GenerateQuestionQueueDTO implements Serializable { /** 最后一次重试的时间 */ private LocalDateTime lastRetryTime; + + /**权重*/ + private Integer weight; + } diff --git a/src/main/java/com/project/interaction/domain/service/PostToGenerateQuestionDomainService.java b/src/main/java/com/project/interaction/domain/service/PostToGenerateQuestionDomainService.java index 2910d9b..61db3d9 100644 --- a/src/main/java/com/project/interaction/domain/service/PostToGenerateQuestionDomainService.java +++ b/src/main/java/com/project/interaction/domain/service/PostToGenerateQuestionDomainService.java @@ -10,7 +10,7 @@ public interface PostToGenerateQuestionDomainService { /** * 生成题目 */ - void postToGenerateQuestion(List dtoList, QuestionTypeEnum questionType, int num) throws Exception; + void postToGenerateQuestion(List dtoList, QuestionTypeEnum questionType, int num, Boolean flage) throws Exception; /** * 处理队列中的待重试项 diff --git a/src/main/java/com/project/interaction/domain/service/impl/GenerateQuestionQueueServiceImpl.java b/src/main/java/com/project/interaction/domain/service/impl/GenerateQuestionQueueServiceImpl.java index 26e28a3..b9d9ec8 100644 --- a/src/main/java/com/project/interaction/domain/service/impl/GenerateQuestionQueueServiceImpl.java +++ b/src/main/java/com/project/interaction/domain/service/impl/GenerateQuestionQueueServiceImpl.java @@ -26,11 +26,13 @@ public class GenerateQuestionQueueServiceImpl implements GenerateQuestionQueueSe private PriorityBlockingQueue queue; + /*按照权限降序、时间升序*/ @PostConstruct public void init() { this.queue = new PriorityBlockingQueue<>( 10000, - Comparator.comparing(GenerateQuestionQueueDTO::getAddTime) + Comparator.comparing(GenerateQuestionQueueDTO::getWeight, Comparator.reverseOrder()) + .thenComparing(GenerateQuestionQueueDTO::getAddTime) .thenComparing(GenerateQuestionQueueDTO::getItemId) ); } diff --git a/src/main/java/com/project/interaction/domain/service/impl/PostToGenerateQuestionDomainServiceImpl.java b/src/main/java/com/project/interaction/domain/service/impl/PostToGenerateQuestionDomainServiceImpl.java index ecd3c3c..484eced 100644 --- a/src/main/java/com/project/interaction/domain/service/impl/PostToGenerateQuestionDomainServiceImpl.java +++ b/src/main/java/com/project/interaction/domain/service/impl/PostToGenerateQuestionDomainServiceImpl.java @@ -80,7 +80,7 @@ public class PostToGenerateQuestionDomainServiceImpl implements PostToGenerateQu * 3. 如果算法服务失败,使用熔断降级方案生成默认题目 */ @Override - public void postToGenerateQuestion(List dtoList, QuestionTypeEnum questionType, int num) throws Exception { + public void postToGenerateQuestion(List dtoList, QuestionTypeEnum questionType, int num, Boolean flage) throws Exception { Long taskId = Optional.of(dtoList.stream().findFirst()) .get().orElse(new TaskKnowledgePointDTO()).getTaskId(); Long clusterId = Optional.of(dtoList.stream().findFirst()) @@ -127,6 +127,7 @@ public class PostToGenerateQuestionDomainServiceImpl implements PostToGenerateQu generateQuestionQueueItem.setNum(num); generateQuestionQueueItem.setDtoList(dtoList); generateQuestionQueueItem.setTaskId(dtoList.get(0).getTaskId()); + generateQuestionQueueItem.setWeight(flage ? 1 : 0); generateQuestionQueueService.addItem(generateQuestionQueueItem); return; } @@ -137,7 +138,7 @@ public class PostToGenerateQuestionDomainServiceImpl implements PostToGenerateQu taskId); //消息提醒 -// notifyUtil.notify(taskId, clusterId); + notifyUtil.notify(taskId, clusterId); } /** @@ -275,8 +276,8 @@ public class PostToGenerateQuestionDomainServiceImpl implements PostToGenerateQu int statusCode = exception.getStatusCode().value(); if (statusCode == REJECT_STATUS) { - log.warn(">>> [队列管理] 重试仍被拒绝, ItemId: {}", - item.getItemId(), exception.getMessage()); + log.warn(">>> [队列管理] 重试仍被拒绝, ItemId: {},TaskId: {}", + item.getItemId(), item.getTaskId()); item.setLastRetryTime(LocalDateTime.now()); item.setRetryCount(item.getRetryCount() + 1); return true; 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 daab2d6..ac3c794 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 @@ -215,7 +215,7 @@ public class SaveClusterDomainServiceImpl implements SaveClusterDomainService { int generateNum = Math.min(ROUND_NUM, needCount); // 调用生成方法 - generateQuestionDomainService.produce(dto.getSourceId(), type, dto.getSourceType(), generateNum); + generateQuestionDomainService.produce(dto.getSourceId(), type, dto.getSourceType(), generateNum, false); // 更新剩余数量 int remainCount = needCount - generateNum; diff --git a/src/main/java/com/project/question/config/QuestionReplenishProperties.java b/src/main/java/com/project/question/config/QuestionReplenishProperties.java index fe1fba6..7978d17 100644 --- a/src/main/java/com/project/question/config/QuestionReplenishProperties.java +++ b/src/main/java/com/project/question/config/QuestionReplenishProperties.java @@ -13,7 +13,7 @@ public class QuestionReplenishProperties { // 闲时结束 private int offPeakEnd = 8; // 忙时间隔 - private int busyInterval = 30; + private int busyInterval = 60; // 闲时间隔 private int offPeakInterval = 180; } \ No newline at end of file diff --git a/src/main/java/com/project/question/domain/service/GenerateQuestionDomainService.java b/src/main/java/com/project/question/domain/service/GenerateQuestionDomainService.java index 6e8b3bc..4086a4b 100644 --- a/src/main/java/com/project/question/domain/service/GenerateQuestionDomainService.java +++ b/src/main/java/com/project/question/domain/service/GenerateQuestionDomainService.java @@ -5,5 +5,5 @@ import com.project.task.domain.enums.QuestionTypeEnum; public interface GenerateQuestionDomainService { - void produce(Long sourceId, QuestionTypeEnum questionType , QuestionSourceTypeEnum sourceType, int needCount); + void produce(Long sourceId, QuestionTypeEnum questionType , QuestionSourceTypeEnum sourceType, int needCount, Boolean flage); } diff --git a/src/main/java/com/project/question/domain/service/impl/GenerateQuestionDomainServiceImpl.java b/src/main/java/com/project/question/domain/service/impl/GenerateQuestionDomainServiceImpl.java index 112c536..5098caa 100644 --- a/src/main/java/com/project/question/domain/service/impl/GenerateQuestionDomainServiceImpl.java +++ b/src/main/java/com/project/question/domain/service/impl/GenerateQuestionDomainServiceImpl.java @@ -35,32 +35,32 @@ public class GenerateQuestionDomainServiceImpl implements GenerateQuestionDomain private PostToGenerateQuestionDomainService postToGenerateQuestionDomainService; @Override - public void produce(Long sourceId, QuestionTypeEnum questionType , QuestionSourceTypeEnum sourceType, int needCount) { + public void produce(Long sourceId, QuestionTypeEnum questionType , QuestionSourceTypeEnum sourceType, int needCount, Boolean flage) { if (needCount <= 0) { return; } CompletableFuture.runAsync(() -> { log.info(">>> [题库预生成] 准备生产任务: SourceID={}, Type={}, Count={}", sourceId, sourceType, needCount); - Try.run(() -> processBatch(sourceId,questionType , sourceType , needCount)); + Try.run(() -> processBatch(sourceId,questionType , sourceType , needCount, flage)); }, questionGenExecutor); } - private void processBatch(Long sourceId, QuestionTypeEnum questionType , QuestionSourceTypeEnum sourceType, int count) throws Exception{ + private void processBatch(Long sourceId, QuestionTypeEnum questionType , QuestionSourceTypeEnum sourceType, int count, Boolean flage) throws Exception{ // 如果是簇复合题,执行随机采样 2-4 个知识点 List kpList; if (QuestionSourceTypeEnum.Multi_Concept.equals(sourceType)) { for (int i = 0; i < count; i++) { kpList = samplingStrategy.sample(sourceId); // 获取随机组合的 KPs - postToGenerateQuestionDomainService.postToGenerateQuestion(kpList , questionType , 1); + postToGenerateQuestionDomainService.postToGenerateQuestion(kpList , questionType , 1, flage); } } else { // 单 KP 逻辑:直接查出对应 KP 的内容 kpList = Collections.singletonList(taskKnowledgePointBaseService.getById(sourceId) .toDTO(TaskKnowledgePointDTO::new)); - postToGenerateQuestionDomainService.postToGenerateQuestion(kpList , questionType , count); + postToGenerateQuestionDomainService.postToGenerateQuestion(kpList , questionType , count, flage); } } } diff --git a/src/main/java/com/project/question/domain/service/impl/QuestionInventoryDomainServiceImpl.java b/src/main/java/com/project/question/domain/service/impl/QuestionInventoryDomainServiceImpl.java index f67bf9d..2ba8825 100644 --- a/src/main/java/com/project/question/domain/service/impl/QuestionInventoryDomainServiceImpl.java +++ b/src/main/java/com/project/question/domain/service/impl/QuestionInventoryDomainServiceImpl.java @@ -150,7 +150,7 @@ public class QuestionInventoryDomainServiceImpl implements QuestionInventoryDoma int gap = targetLine - currentStock; log.info(">>> [自动补库] KP: {}, 题型: {}, 当前库存: {}, 需补货: {}", kpId, type.getDescription(), currentStock, gap); // 触发异步生产逻辑 (内部带 30 分钟冷却锁) - generateQuestionDomainService.produce(kpId , type , QuestionSourceTypeEnum.Single_Concept , gap); + generateQuestionDomainService.produce(kpId , type , QuestionSourceTypeEnum.Single_Concept , gap,true); } } @@ -164,7 +164,7 @@ public class QuestionInventoryDomainServiceImpl implements QuestionInventoryDoma int gap = targetLine - currentStock; log.info(">>> [自动补库] 簇: {}, 类型: 复合多选, 当前库存: {}, 需补货: {}", clusterId, currentStock, gap); // 簇维度触发,触发异步生产逻辑 - generateQuestionDomainService.produce(clusterId , QuestionTypeEnum.MULTIPLE_CHOICE , QuestionSourceTypeEnum.Multi_Concept , gap); + generateQuestionDomainService.produce(clusterId , QuestionTypeEnum.MULTIPLE_CHOICE , QuestionSourceTypeEnum.Multi_Concept , gap,true); } } diff --git a/src/main/java/com/project/question/mapper/TaskKnowledgePointMapper.java b/src/main/java/com/project/question/mapper/TaskKnowledgePointMapper.java index a31c833..c337d4f 100644 --- a/src/main/java/com/project/question/mapper/TaskKnowledgePointMapper.java +++ b/src/main/java/com/project/question/mapper/TaskKnowledgePointMapper.java @@ -1,9 +1,31 @@ package com.project.question.mapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.project.question.domain.dto.TaskKnowledgePointDTO; import com.project.question.domain.entity.TaskKnowledgePointEntity; import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Select; + +import java.util.List; @Mapper public interface TaskKnowledgePointMapper extends BaseMapper { + @Select("SELECT kp.* " + + "FROM evaluator_task_knowledge_point kp " + + "INNER JOIN ( " + + " SELECT " + + " e.kp_id," + + " COUNT(DISTINCT CASE WHEN e.question_type = 1 THEN e.question_id END) AS single," + + " COUNT(DISTINCT CASE WHEN e.question_type = 2 THEN e.question_id END) AS multiple," + + " COUNT(DISTINCT CASE WHEN e.question_type = 3 THEN e.question_id END) AS judgment " + + " FROM evaluator_question_kp_rel e " + + " INNER JOIN evaluator_question q ON e.question_id = q.id " + + " WHERE e.task_id = #{id} " + + " AND q.use_status = 0 " + + " AND q.deleted = 0 AND e.deleted = 0" + + " GROUP BY e.kp_id " + + ") AS kp_stats ON kp.id = kp_stats.kp_id " + + "ORDER BY kp_stats.single DESC;") + List selectKpOrderBySingle(@Param("id") Long id); }