|
|
@@ -16,6 +16,7 @@ import com.ruoyi.learn.service.ILearnQuestionsService;
|
|
|
import com.ruoyi.syzy.domain.BBusiWishUniversities;
|
|
|
import com.ruoyi.syzy.service.IBBusiWishUniversitiesService;
|
|
|
import lombok.Data;
|
|
|
+import lombok.extern.slf4j.Slf4j;
|
|
|
import org.apache.commons.collections4.CollectionUtils;
|
|
|
import org.apache.commons.lang3.tuple.Pair;
|
|
|
import org.springframework.stereotype.Service;
|
|
|
@@ -29,6 +30,7 @@ import java.util.stream.Stream;
|
|
|
* 考卷服务
|
|
|
*/
|
|
|
@Service
|
|
|
+@Slf4j
|
|
|
public class PaperService {
|
|
|
Set<QuestionType> chooseTypes = Sets.newHashSet(QuestionType.Judgment, QuestionType.Multiple, QuestionType.Single);
|
|
|
private final LearnPaperMapper paperMapper;
|
|
|
@@ -46,7 +48,8 @@ public class PaperService {
|
|
|
this.learnQuestionsService = learnQuestionsService;
|
|
|
this.learnDirectedKnowledgeMapper = learnDirectedKnowledgeMapper;
|
|
|
this.wishUniversitiesService = wishUniversitiesService;
|
|
|
- // buildSimulatedPaper(20154L, 11L);
|
|
|
+ // buildSimulatedPaper(20154L, 1001L);
|
|
|
+ // buildSimulatedPaper(20950L, 1001L);
|
|
|
// test2();
|
|
|
}
|
|
|
|
|
|
@@ -98,7 +101,7 @@ public class PaperService {
|
|
|
QuestionType qt = QuestionType.of(lqs.getQtpye());
|
|
|
qs.setTypeId(qt.getVal());
|
|
|
qs.setType(qt.getTitle());
|
|
|
- if (chooseTypes.contains(qt)) {
|
|
|
+ if (!chooseTypes.contains(qt)) {
|
|
|
qs.setOptions(Lists.newArrayList("会", "不会"));
|
|
|
} else {
|
|
|
qs.setOptions(StringUtils.getOptions(lqs.getOptionA(), lqs.getOptionB(), lqs.getOptionC(), lqs.getOptionD(), lqs.getOptionE(), lqs.getOptionF(), lqs.getOptionG()));
|
|
|
@@ -176,15 +179,11 @@ public class PaperService {
|
|
|
List<LearnDirectedKnowledge> directedKnowledgeList = learnDirectedKnowledgeMapper.selectLearnDirectedKnowledgeList(dkCond);
|
|
|
BBusiWishUniversities universities = wishUniversitiesService.selectBBusiWishUniversitiesById(universityId);
|
|
|
for(LearnDirectedKnowledge dk : directedKnowledgeList) {
|
|
|
- TestPaperVO.PaperDef paperDef = new TestPaperVO.PaperDef();
|
|
|
- paperDef.setTotal(100L); // 120题
|
|
|
+ if(StringUtils.isBlank(dk.getConditions())) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ TestPaperVO.PaperDef2 paperDef = new TestPaperVO.PaperDef2(dk.getKnowledges(), dk.getConditions());
|
|
|
paperDef.setFillExclude(false);
|
|
|
- paperDef.setKnowIds(Stream.of(dk.getKnowledges().split(",")).map(Long::parseLong).collect(Collectors.toList()));
|
|
|
- List<TestPaperVO.TypeDef> typeDefList= Lists.newArrayList();
|
|
|
- typeDefList.add(new TestPaperVO.TypeDef("单选题", "单选题", 40, 3));
|
|
|
- typeDefList.add(new TestPaperVO.TypeDef("多选题", "多选题", 40, 3));
|
|
|
- typeDefList.add(new TestPaperVO.TypeDef("判断题", "判断题", 20, 3));
|
|
|
- paperDef.setTypes(typeDefList);
|
|
|
|
|
|
LearnPaper paper = new LearnPaper();
|
|
|
paper.setSubjectId(subjectId);
|
|
|
@@ -194,15 +193,19 @@ public class PaperService {
|
|
|
paper.setYear(dk.getYear());
|
|
|
paper.setStatus(PaperStatus.Valid.getVal());
|
|
|
paper.setDirectKey(universityId + "_" + dk.getExamineeTypes() + "_" + dk.getDirectKey());
|
|
|
- paper.setNumber(100);
|
|
|
- paper.setFenshu(300);
|
|
|
+ paper.setNumber(paperDef.getTotal());
|
|
|
+ paper.setFenshu(paperDef.getScore().intValue());
|
|
|
AnswerSheet.PaperCond info = new AnswerSheet.PaperCond();
|
|
|
- info.setScore(300);
|
|
|
- info.setTime(90 * 60);
|
|
|
- info.setTypes(typeDefList.stream().map(t -> new AnswerSheet.PaperCondType(t.getType(), t.getCount(), t.getScore())).collect(Collectors.toList()));
|
|
|
+ info.setScore(paper.getFenshu());
|
|
|
+ info.setTime(dk.getTime() * 60);
|
|
|
+ info.setTypes(paperDef.getTypes().stream().map(t -> new AnswerSheet.PaperCondType(t.getType().getTitle(), t.getCount(), t.getScore())).collect(Collectors.toList()));
|
|
|
paper.setPaperInfo(JSONObject.toJSONString(info));
|
|
|
- Pair<LearnPaper, List<LearnPaperQuestion>> paperResult = buildPaper(null, paper, paperDef);
|
|
|
- savePaper(paperResult.getKey(), paperResult.getValue());
|
|
|
+ try {
|
|
|
+ Pair<LearnPaper, List<LearnPaperQuestion>> paperResult = buildPaper2(null, paper, paperDef);
|
|
|
+ savePaper(paperResult.getKey(), paperResult.getValue());
|
|
|
+ } catch(RuntimeException e) {
|
|
|
+ log.error(e.getMessage());
|
|
|
+ }
|
|
|
}
|
|
|
return 0;
|
|
|
}
|
|
|
@@ -220,6 +223,12 @@ public class PaperService {
|
|
|
return buildPaper(null, paper, paperDef);
|
|
|
}
|
|
|
|
|
|
+ public Pair<LearnPaper, List<LearnPaperQuestion>> buildPaper2(Long studentId, LearnPaper paper, TestPaperVO.PaperDef2 paperDef) {
|
|
|
+ paperDef.setFillExclude(null != studentId);
|
|
|
+ List<LearnPaperQuestion> pqList = getQuestions2(studentId, paperDef);
|
|
|
+ return Pair.of(paper, pqList);
|
|
|
+ }
|
|
|
+
|
|
|
/**
|
|
|
* 根据试卷定义生成试卷
|
|
|
* @param studentId
|
|
|
@@ -245,10 +254,8 @@ public class PaperService {
|
|
|
paper.setNumber(pqList.size());
|
|
|
paperMapper.insertLearnPaper(paper);
|
|
|
Long paperId = paper.getId();
|
|
|
- pqList.stream().forEach(t -> {
|
|
|
- t.setPaperId(paperId);
|
|
|
- paperQuestionMapper.insertLearnPaperQuestion(t);
|
|
|
- });
|
|
|
+ pqList.stream().forEach(t -> t.setPaperId(paperId));
|
|
|
+ paperQuestionMapper.batchInsert(pqList);
|
|
|
return paper;
|
|
|
}
|
|
|
|
|
|
@@ -265,6 +272,17 @@ public class PaperService {
|
|
|
return getQuestions(studentId, paperDef, knowTypeAssignMap);
|
|
|
}
|
|
|
|
|
|
+ public List<LearnPaperQuestion> getQuestions2(Long studentId, TestPaperVO.PaperDef2 paperDef) {
|
|
|
+ List<LearnPaperQuestion> pqList = Lists.newArrayList();
|
|
|
+ Set<Long> existQuestionIdSet = Sets.newHashSet();
|
|
|
+ for(TestPaperVO.KnowledgeTypeDef2 ktd : paperDef.getKnowTypes()) {
|
|
|
+ Map<String, KnowTypeAssign> knowTypeAssignMap = buildKnowTypeAssignMap(studentId, ktd.getTypes().stream().map(t -> t.getType().getTitle()).collect(Collectors.toList()), ktd.getKnowledges(), paperDef.getFillExclude());
|
|
|
+ assignTypeFirst(paperDef.getFillExclude(), ktd, knowTypeAssignMap);
|
|
|
+ pqList.addAll(getQuestions2(studentId, ktd.getCount(), ktd, knowTypeAssignMap, existQuestionIdSet));
|
|
|
+ }
|
|
|
+ return pqList;
|
|
|
+ }
|
|
|
+
|
|
|
/**
|
|
|
* 按知识点,题型平均分配组卷
|
|
|
* @param studentId
|
|
|
@@ -461,6 +479,41 @@ public class PaperService {
|
|
|
} while(doneSet.size() < needCount);
|
|
|
}
|
|
|
|
|
|
+ private void assignTypeFirst(Boolean fillExclude, TestPaperVO.KnowledgeTypeDef2 knowledgeTypeDef, Map<String, KnowTypeAssign> knowTypeAssignMap) {
|
|
|
+ Map<String, Set<Long>> typeKnownIdsMap = knowTypeAssignMap.values().stream().collect(Collectors.groupingBy(KnowTypeAssign::getType, Collectors.mapping(KnowTypeAssign::getKnowId, Collectors.toSet())));
|
|
|
+ AtomicLong assignCount = new AtomicLong(0);
|
|
|
+ for(TestPaperVO.TypeDef2 typeDef : knowledgeTypeDef.getTypes()) { // 每个类型,让所有知识先平均补充,补充的由后面填充
|
|
|
+ Long minKnowTypeCount = Long.MAX_VALUE;
|
|
|
+ Long lackTotal = typeDef.getCount().longValue();
|
|
|
+ String typeTitle = typeDef.getType().getTitle();
|
|
|
+ Set<Long> knownIdSet = typeKnownIdsMap.get(typeTitle);
|
|
|
+ if(CollectionUtils.isEmpty(knownIdSet)) {
|
|
|
+ log.error("Invalid knowledge type: " + typeTitle);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ assignCount.set(0L);
|
|
|
+ do {
|
|
|
+ Long avgKnowTypeCount = (lackTotal - assignCount.get()) / knownIdSet.size();
|
|
|
+ if (avgKnowTypeCount <= 0L) {
|
|
|
+ avgKnowTypeCount = 1L;
|
|
|
+ }
|
|
|
+ knownIdSet.clear();
|
|
|
+ for(Long knowId : knowledgeTypeDef.getKnowledges()) {
|
|
|
+ if(avgKnowTypeCount > 0) {
|
|
|
+ Long tmpMinKnowTypeCount = assignKnownCount(knowId, typeTitle, knowTypeAssignMap, avgKnowTypeCount, fillExclude, assignCount);
|
|
|
+ if (tmpMinKnowTypeCount > 0) {
|
|
|
+ minKnowTypeCount = Math.min(minKnowTypeCount, tmpMinKnowTypeCount);
|
|
|
+ knownIdSet.add(knowId);
|
|
|
+ }
|
|
|
+ if(assignCount.get() >= lackTotal) {
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } while(lackTotal != assignCount.get() && knownIdSet.size() > 0);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
private void assignKnowFirst(TestPaperVO.PaperDef paperDef, Map<String, KnowTypeAssign> knowTypeAssignMap) {
|
|
|
// 循环补充未做+已做,如果知识点总数不够时才填充其他知识点的
|
|
|
Long lackTotal = paperDef.getTotal();
|
|
|
@@ -529,7 +582,7 @@ public class PaperService {
|
|
|
qCond.setId(studentId);
|
|
|
qCond.setNumber(ktc.exclAssign > 500 ? (long) random.nextInt(ktc.exclAssign.intValue() - 500) : 0L);
|
|
|
List<LearnQuestions> questions = questionsMapper.selectQuestionsForPaper(qCond);
|
|
|
- ktc.exclAssign = addRandomList(knowId, ktc.getType(), questions, random, paperDef.getTotal(), ktc.exclAssign, typeDef.getScore(), existQuestionIdSet, pqList);
|
|
|
+ ktc.exclAssign = addRandomList(knowId, ktc.getType(), questions, random, paperDef.getTotal(), ktc.exclAssign, typeDef.getScore().doubleValue(), existQuestionIdSet, pqList);
|
|
|
if(pqList.size() == total) {
|
|
|
break;
|
|
|
}
|
|
|
@@ -538,7 +591,51 @@ public class PaperService {
|
|
|
qCond.setId(null);
|
|
|
qCond.setNumber(ktc.assign > 500 ? (long) random.nextInt(ktc.assign.intValue() - 500) : 0L);
|
|
|
List<LearnQuestions> questions = questionsMapper.selectQuestionsForPaper(qCond);
|
|
|
- ktc.assign = addRandomList(knowId, ktc.getType(), questions, random, paperDef.getTotal(), ktc.assign, typeDef.getScore(), existQuestionIdSet, pqList);
|
|
|
+ ktc.assign = addRandomList(knowId, ktc.getType(), questions, random, paperDef.getTotal(), ktc.assign, typeDef.getScore().doubleValue(), existQuestionIdSet, pqList);
|
|
|
+ if(pqList.size() == total) {
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if(pqList.size() == total) {
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if(CollectionUtils.isEmpty(pqList)) {
|
|
|
+ throw new RuntimeException("题数不足");
|
|
|
+ }
|
|
|
+ return pqList;
|
|
|
+ }
|
|
|
+
|
|
|
+ public List<LearnPaperQuestion> getQuestions2(Long studentId, Integer total, TestPaperVO.KnowledgeTypeDef2 knowledgeTypeDef2, Map<String, KnowTypeAssign> knowTypeAssignMap, Set<Long> existQuestionIdSet) {
|
|
|
+ // 知识点已经分配,准备题型分配
|
|
|
+ LearnQuestions qCond = new LearnQuestions();
|
|
|
+ Random random = new Random();
|
|
|
+ List<LearnPaperQuestion> pqList = Lists.newArrayList();
|
|
|
+ for (TestPaperVO.TypeDef2 typeDef : knowledgeTypeDef2.getTypes()) {
|
|
|
+ String typeTitle = typeDef.getType().getTitle();
|
|
|
+ for (Long knowId : knowledgeTypeDef2.getKnowledges()) {
|
|
|
+ String key = knowId + "_" + typeTitle;
|
|
|
+ KnowTypeAssign ktc = knowTypeAssignMap.get(key);
|
|
|
+ if(null == ktc) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ qCond.setKnowledgeId(ktc.getKnowId());
|
|
|
+ qCond.setQtpye(typeTitle);
|
|
|
+ if(ktc.exclAssign > 0){
|
|
|
+ qCond.setId(studentId);
|
|
|
+ qCond.setNumber(ktc.exclAssign > 500 ? (long) random.nextInt(ktc.exclAssign.intValue() - 500) : 0L);
|
|
|
+ List<LearnQuestions> questions = questionsMapper.selectQuestionsForPaper(qCond);
|
|
|
+ ktc.exclAssign = addRandomList(knowId, typeTitle, questions, random, typeDef.getCount().longValue(), ktc.exclAssign, typeDef.getScore(), existQuestionIdSet, pqList);
|
|
|
+ if(pqList.size() == total) {
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if(ktc.assign > 0L) {
|
|
|
+ qCond.setId(null);
|
|
|
+ qCond.setNumber(ktc.assign > 500 ? (long) random.nextInt(ktc.assign.intValue() - 500) : 0L);
|
|
|
+ List<LearnQuestions> questions = questionsMapper.selectQuestionsForPaper(qCond);
|
|
|
+ ktc.assign = addRandomList(knowId, typeTitle, questions, random, typeDef.getCount().longValue(), ktc.assign, typeDef.getScore(), existQuestionIdSet, pqList);
|
|
|
if(pqList.size() == total) {
|
|
|
break;
|
|
|
}
|
|
|
@@ -562,14 +659,25 @@ public class PaperService {
|
|
|
* @return
|
|
|
*/
|
|
|
private Map<String, KnowTypeAssign> buildKnowTypeAssignMap(Long studentId, TestPaperVO.PaperDef paperDef) {
|
|
|
+ return buildKnowTypeAssignMap(studentId, paperDef.getTypes().stream().map(TestPaperVO.TypeDef::getType).collect(Collectors.toList()), paperDef.getKnowIds(), paperDef.getFillExclude());
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 初始化当前用户知识点的情况
|
|
|
+ * @param studentId
|
|
|
+ * @param types
|
|
|
+ * @param knownIds
|
|
|
+ * @param fillExclude
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ private Map<String, KnowTypeAssign> buildKnowTypeAssignMap(Long studentId, List<String> types, List<Long> knownIds, Boolean fillExclude) {
|
|
|
Map<String, KnowTypeAssign> knowTypeAssignMap = Maps.newHashMap();
|
|
|
- List<String> typeSet = paperDef.getTypes().stream().map(TestPaperVO.TypeDef::getType).collect(Collectors.toList());
|
|
|
Map cond = Maps.newHashMap();
|
|
|
cond.put("studentId", studentId);
|
|
|
- cond.put("knowIds", paperDef.getKnowIds());
|
|
|
- cond.put("types", typeSet);
|
|
|
+ cond.put("knowIds", knownIds);
|
|
|
+ cond.put("types", types);
|
|
|
setValue(knowTypeAssignMap, cond, 1); // 填充排除后总量
|
|
|
- if (null != studentId && paperDef.getFillExclude()) {
|
|
|
+ if (null != studentId && fillExclude) {
|
|
|
cond.remove("studentId");
|
|
|
setValue(knowTypeAssignMap, cond, 2); // 按需填充已做总量
|
|
|
}
|
|
|
@@ -588,7 +696,7 @@ public class PaperService {
|
|
|
* @param existQuestionIdSet 不能使用的题
|
|
|
* @param pqList 卷题关系
|
|
|
*/
|
|
|
- private Long addRandomList(Long knowId, String type, List<LearnQuestions> questions, Random random, Long totalCount, Long count, Integer score, Set<Long> existQuestionIdSet, List<LearnPaperQuestion> pqList) {
|
|
|
+ private Long addRandomList(Long knowId, String type, List<LearnQuestions> questions, Random random, Long totalCount, Long count, Double score, Set<Long> existQuestionIdSet, List<LearnPaperQuestion> pqList) {
|
|
|
while(count > 0L && !questions.isEmpty()) {
|
|
|
LearnQuestions q = questions.size() > 1 ? questions.remove(random.nextInt(questions.size() - 1)) : questions.remove(0);
|
|
|
if(existQuestionIdSet.add(q.getId())) {
|