|
@@ -13,6 +13,8 @@ import com.ruoyi.enums.QuestionType;
|
|
|
import com.ruoyi.learn.domain.*;
|
|
import com.ruoyi.learn.domain.*;
|
|
|
import com.ruoyi.learn.mapper.*;
|
|
import com.ruoyi.learn.mapper.*;
|
|
|
import com.ruoyi.learn.service.ILearnQuestionsService;
|
|
import com.ruoyi.learn.service.ILearnQuestionsService;
|
|
|
|
|
+import com.ruoyi.syzy.domain.BBusiWishUniversities;
|
|
|
|
|
+import com.ruoyi.syzy.service.IBBusiWishUniversitiesService;
|
|
|
import lombok.Data;
|
|
import lombok.Data;
|
|
|
import org.apache.commons.collections4.CollectionUtils;
|
|
import org.apache.commons.collections4.CollectionUtils;
|
|
|
import org.apache.commons.lang3.tuple.Pair;
|
|
import org.apache.commons.lang3.tuple.Pair;
|
|
@@ -32,13 +34,18 @@ public class PaperService {
|
|
|
private final LearnPaperQuestionMapper paperQuestionMapper;
|
|
private final LearnPaperQuestionMapper paperQuestionMapper;
|
|
|
private final LearnQuestionsMapper questionsMapper;
|
|
private final LearnQuestionsMapper questionsMapper;
|
|
|
private final ILearnQuestionsService learnQuestionsService;
|
|
private final ILearnQuestionsService learnQuestionsService;
|
|
|
|
|
+ private final LearnDirectedKnowledgeMapper learnDirectedKnowledgeMapper;
|
|
|
|
|
+ private final IBBusiWishUniversitiesService wishUniversitiesService;
|
|
|
|
|
|
|
|
|
|
|
|
|
- PaperService(LearnPaperMapper paperMapper, LearnPaperQuestionMapper paperQuestionMapper, LearnQuestionsMapper questionsMapper, ILearnQuestionsService learnQuestionsService) {
|
|
|
|
|
|
|
+ PaperService(LearnPaperMapper paperMapper, LearnPaperQuestionMapper paperQuestionMapper, LearnQuestionsMapper questionsMapper, ILearnQuestionsService learnQuestionsService, LearnDirectedKnowledgeMapper learnDirectedKnowledgeMapper, IBBusiWishUniversitiesService wishUniversitiesService) {
|
|
|
this.paperMapper = paperMapper;
|
|
this.paperMapper = paperMapper;
|
|
|
this.paperQuestionMapper = paperQuestionMapper;
|
|
this.paperQuestionMapper = paperQuestionMapper;
|
|
|
this.questionsMapper = questionsMapper;
|
|
this.questionsMapper = questionsMapper;
|
|
|
this.learnQuestionsService = learnQuestionsService;
|
|
this.learnQuestionsService = learnQuestionsService;
|
|
|
|
|
+ this.learnDirectedKnowledgeMapper = learnDirectedKnowledgeMapper;
|
|
|
|
|
+ // buildSimulatedPaper(20154L, 11L);
|
|
|
|
|
+ this.wishUniversitiesService = wishUniversitiesService;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
public void test() {
|
|
public void test() {
|
|
@@ -139,6 +146,43 @@ public class PaperService {
|
|
|
* 根据院校专业要求生成模拟试卷
|
|
* 根据院校专业要求生成模拟试卷
|
|
|
* @return
|
|
* @return
|
|
|
*/
|
|
*/
|
|
|
|
|
+
|
|
|
|
|
+ public int buildSimulatedPaper(Long universityId, Long subjectId) {
|
|
|
|
|
+ LearnDirectedKnowledge dkCond = new LearnDirectedKnowledge();
|
|
|
|
|
+ dkCond.setUniversityId(universityId);
|
|
|
|
|
+ List<LearnDirectedKnowledge> directedKnowledgeList = learnDirectedKnowledgeMapper.selectLearnDirectedKnowledgeList(dkCond);
|
|
|
|
|
+ BBusiWishUniversities universities = wishUniversitiesService.selectBBusiWishUniversitiesById(universityId);
|
|
|
|
|
+ for(LearnDirectedKnowledge dk : directedKnowledgeList) {
|
|
|
|
|
+ TestPaperVO.PaperDef paperDef = new TestPaperVO.PaperDef();
|
|
|
|
|
+ paperDef.setTotal(120L); // 120题
|
|
|
|
|
+ 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("判断题", "判断题", 40, 3));
|
|
|
|
|
+ paperDef.setTypes(typeDefList);
|
|
|
|
|
+
|
|
|
|
|
+ LearnPaper paper = new LearnPaper();
|
|
|
|
|
+ paper.setSubjectId(subjectId);
|
|
|
|
|
+ paper.setPaperName(StringUtils.isNotBlank(dk.getDirectKey()) ? universities.getName() + "(" + dk.getDirectKey() + ")" : universities.getName());
|
|
|
|
|
+ paper.setPaperType(PaperType.Simulated.name());
|
|
|
|
|
+ paper.setRelateId(dk.getId()); // 定向ID
|
|
|
|
|
+ paper.setYear(dk.getYear());
|
|
|
|
|
+ paper.setStatus(PaperStatus.Valid.getVal());
|
|
|
|
|
+ paper.setDirectKey(universityId + "_" + dk.getExamineeTypes() + "_" + dk.getDirectKey());
|
|
|
|
|
+ paper.setNumber(120);
|
|
|
|
|
+ paper.setFenshu(360);
|
|
|
|
|
+ AnswerSheet.PaperCond info = new AnswerSheet.PaperCond();
|
|
|
|
|
+ info.setScore(360);
|
|
|
|
|
+ info.setTime(90 * 60);
|
|
|
|
|
+ info.setTypes(typeDefList.stream().map(t -> new AnswerSheet.PaperCondType(t.getType(), 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());
|
|
|
|
|
+ }
|
|
|
|
|
+ return 0;
|
|
|
|
|
+ }
|
|
|
public Pair<LearnPaper, List<LearnPaperQuestion>> buildSimulatedPaper(LearnDirectedKnowledge directedKnowledge) {
|
|
public Pair<LearnPaper, List<LearnPaperQuestion>> buildSimulatedPaper(LearnDirectedKnowledge directedKnowledge) {
|
|
|
LearnPaper paper = new LearnPaper();
|
|
LearnPaper paper = new LearnPaper();
|
|
|
paper.setPaperType(PaperType.Simulated.name());
|
|
paper.setPaperType(PaperType.Simulated.name());
|
|
@@ -176,7 +220,6 @@ public class PaperService {
|
|
|
*/
|
|
*/
|
|
|
public LearnPaper savePaper(LearnPaper paper, List<LearnPaperQuestion> pqList) {
|
|
public LearnPaper savePaper(LearnPaper paper, List<LearnPaperQuestion> pqList) {
|
|
|
paper.setNumber(pqList.size());
|
|
paper.setNumber(pqList.size());
|
|
|
- paper.setFenshu(0);
|
|
|
|
|
paperMapper.insertLearnPaper(paper);
|
|
paperMapper.insertLearnPaper(paper);
|
|
|
Long paperId = paper.getId();
|
|
Long paperId = paper.getId();
|
|
|
pqList.stream().forEach(t -> {
|
|
pqList.stream().forEach(t -> {
|
|
@@ -187,7 +230,7 @@ public class PaperService {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
|
- * 动态组卷查题
|
|
|
|
|
|
|
+ * 按知识点,题型平均分配组卷
|
|
|
* @param studentId
|
|
* @param studentId
|
|
|
* @param paperDef
|
|
* @param paperDef
|
|
|
* @return
|
|
* @return
|
|
@@ -195,27 +238,21 @@ public class PaperService {
|
|
|
public List<LearnPaperQuestion> getQuestions(Long studentId, TestPaperVO.PaperDef paperDef) {
|
|
public List<LearnPaperQuestion> getQuestions(Long studentId, TestPaperVO.PaperDef paperDef) {
|
|
|
// 题型分布定义, 知识点列表, 分值定义
|
|
// 题型分布定义, 知识点列表, 分值定义
|
|
|
// 统计知识点+类型的有效数量 TODO 总量可以缓存
|
|
// 统计知识点+类型的有效数量 TODO 总量可以缓存
|
|
|
- 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);
|
|
|
|
|
- setValue(knowTypeAssignMap, cond, 1); // 填充排除总量
|
|
|
|
|
- if (paperDef.getFillExclude()) {
|
|
|
|
|
- cond.remove("studentId");
|
|
|
|
|
- setValue(knowTypeAssignMap, cond, 2); // 按需填充总量
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ Map<String, KnowTypeAssign> knowTypeAssignMap = buildKnowTypeAssignMap(studentId, paperDef);
|
|
|
|
|
+ assignKnowFirst(paperDef, knowTypeAssignMap); // 知识优先,类型可变
|
|
|
|
|
+ return getQuestions(studentId, paperDef, knowTypeAssignMap);
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
|
|
+ private void assignKnowFirst(TestPaperVO.PaperDef paperDef, Map<String, KnowTypeAssign> knowTypeAssignMap) {
|
|
|
// 循环补充未做+已做,如果知识点总数不够时才填充其他知识点的
|
|
// 循环补充未做+已做,如果知识点总数不够时才填充其他知识点的
|
|
|
Long lackTotal = paperDef.getTotal();
|
|
Long lackTotal = paperDef.getTotal();
|
|
|
AtomicLong assignCount = new AtomicLong(0);
|
|
AtomicLong assignCount = new AtomicLong(0);
|
|
|
Map<Long, Integer> knowTypesMap = Maps.newHashMap();
|
|
Map<Long, Integer> knowTypesMap = Maps.newHashMap();
|
|
|
int typeCount = paperDef.getTypes().size();
|
|
int typeCount = paperDef.getTypes().size();
|
|
|
|
|
+ Set<Long> knowSet = knowTypeAssignMap.values().stream().map(KnowTypeAssign::getKnowId).collect(Collectors.toSet());
|
|
|
for (Long knowId : paperDef.getKnowIds()) {
|
|
for (Long knowId : paperDef.getKnowIds()) {
|
|
|
- knowTypesMap.put(knowId, typeCount);
|
|
|
|
|
|
|
+ knowTypesMap.put(knowId, knowSet.contains(knowId) ? typeCount : 0);
|
|
|
}
|
|
}
|
|
|
- Set<Long> knowSet = Sets.newHashSet(paperDef.getKnowIds());
|
|
|
|
|
Long minKnowTypeCount = Long.MAX_VALUE;
|
|
Long minKnowTypeCount = Long.MAX_VALUE;
|
|
|
do {
|
|
do {
|
|
|
Integer knowCount = knowSet.size();
|
|
Integer knowCount = knowSet.size();
|
|
@@ -245,12 +282,22 @@ public class PaperService {
|
|
|
break;
|
|
break;
|
|
|
}
|
|
}
|
|
|
} while (true);
|
|
} while (true);
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 根据计划的分配数生成题关系
|
|
|
|
|
+ * @param studentId
|
|
|
|
|
+ * @param paperDef
|
|
|
|
|
+ * @param knowTypeAssignMap
|
|
|
|
|
+ * @return
|
|
|
|
|
+ */
|
|
|
|
|
+ public List<LearnPaperQuestion> getQuestions(Long studentId, TestPaperVO.PaperDef paperDef, Map<String, KnowTypeAssign> knowTypeAssignMap) {
|
|
|
// 知识点已经分配,准备题型分配
|
|
// 知识点已经分配,准备题型分配
|
|
|
LearnQuestions qCond = new LearnQuestions();
|
|
LearnQuestions qCond = new LearnQuestions();
|
|
|
Random random = new Random();
|
|
Random random = new Random();
|
|
|
List<LearnPaperQuestion> pqList = Lists.newArrayList();
|
|
List<LearnPaperQuestion> pqList = Lists.newArrayList();
|
|
|
Set<Long> existQuestionIdSet = Sets.newHashSet();
|
|
Set<Long> existQuestionIdSet = Sets.newHashSet();
|
|
|
|
|
+ int total = paperDef.getTotal().intValue();
|
|
|
for (TestPaperVO.TypeDef typeDef : paperDef.getTypes()) {
|
|
for (TestPaperVO.TypeDef typeDef : paperDef.getTypes()) {
|
|
|
for (Long knowId : paperDef.getKnowIds()) {
|
|
for (Long knowId : paperDef.getKnowIds()) {
|
|
|
String key = knowId + "_" + typeDef.getType();
|
|
String key = knowId + "_" + typeDef.getType();
|
|
@@ -262,17 +309,25 @@ public class PaperService {
|
|
|
qCond.setQtpye(ktc.getType());
|
|
qCond.setQtpye(ktc.getType());
|
|
|
if(ktc.exclAssign > 0){
|
|
if(ktc.exclAssign > 0){
|
|
|
qCond.setId(studentId);
|
|
qCond.setId(studentId);
|
|
|
- qCond.setNumber(ktc.assign > 500 ? (long) random.nextInt(ktc.exclAssign.intValue() - 500) : 0L);
|
|
|
|
|
|
|
+ qCond.setNumber(ktc.exclAssign > 500 ? (long) random.nextInt(ktc.exclAssign.intValue() - 500) : 0L);
|
|
|
List<LearnQuestions> questions = questionsMapper.selectQuestionsForPaper(qCond);
|
|
List<LearnQuestions> questions = questionsMapper.selectQuestionsForPaper(qCond);
|
|
|
- addRandomList(knowId, questions, random, paperDef.getTotal(), ktc.exclAssign, typeDef.getScore(), existQuestionIdSet, pqList);
|
|
|
|
|
|
|
+ ktc.exclAssign = addRandomList(knowId, ktc.getType(), questions, random, paperDef.getTotal(), ktc.exclAssign, typeDef.getScore(), existQuestionIdSet, pqList);
|
|
|
|
|
+ if(pqList.size() == total) {
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
if(ktc.assign > 0L) {
|
|
if(ktc.assign > 0L) {
|
|
|
qCond.setId(null);
|
|
qCond.setId(null);
|
|
|
qCond.setNumber(ktc.assign > 500 ? (long) random.nextInt(ktc.assign.intValue() - 500) : 0L);
|
|
qCond.setNumber(ktc.assign > 500 ? (long) random.nextInt(ktc.assign.intValue() - 500) : 0L);
|
|
|
List<LearnQuestions> questions = questionsMapper.selectQuestionsForPaper(qCond);
|
|
List<LearnQuestions> questions = questionsMapper.selectQuestionsForPaper(qCond);
|
|
|
- addRandomList(knowId, questions, random, paperDef.getTotal(), ktc.exclAssign, typeDef.getScore(), existQuestionIdSet, pqList);
|
|
|
|
|
|
|
+ ktc.assign = addRandomList(knowId, ktc.getType(), questions, random, paperDef.getTotal(), ktc.assign, typeDef.getScore(), existQuestionIdSet, pqList);
|
|
|
|
|
+ if(pqList.size() == total) {
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
|
|
+ }
|
|
|
|
|
+ if(pqList.size() == total) {
|
|
|
|
|
+ break;
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
if(CollectionUtils.isEmpty(pqList)) {
|
|
if(CollectionUtils.isEmpty(pqList)) {
|
|
@@ -281,15 +336,50 @@ public class PaperService {
|
|
|
return pqList;
|
|
return pqList;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- private void addRandomList(Long knowId, List<LearnQuestions> questions, Random random, Long totalCount, Long count, Integer score, Set<Long> existQuestionIdSet, List<LearnPaperQuestion> pqList) {
|
|
|
|
|
- while(count > 0 && questions.size() > 0) {
|
|
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 初始化当前用户卷情况
|
|
|
|
|
+ * @param studentId
|
|
|
|
|
+ * @param paperDef
|
|
|
|
|
+ * @return
|
|
|
|
|
+ */
|
|
|
|
|
+ private Map<String, KnowTypeAssign> buildKnowTypeAssignMap(Long studentId, TestPaperVO.PaperDef paperDef) {
|
|
|
|
|
+ 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);
|
|
|
|
|
+ setValue(knowTypeAssignMap, cond, 1); // 填充排除后总量
|
|
|
|
|
+ if (null != studentId && paperDef.getFillExclude()) {
|
|
|
|
|
+ cond.remove("studentId");
|
|
|
|
|
+ setValue(knowTypeAssignMap, cond, 2); // 按需填充已做总量
|
|
|
|
|
+ }
|
|
|
|
|
+ return knowTypeAssignMap;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 随机从 knowId 题池中提取需要个数的题
|
|
|
|
|
+ * @param knowId 知识点
|
|
|
|
|
+ * @param type 类型
|
|
|
|
|
+ * @param questions 题池
|
|
|
|
|
+ * @param random 随机数
|
|
|
|
|
+ * @param totalCount 总题数
|
|
|
|
|
+ * @param count 本池分配数
|
|
|
|
|
+ * @param score 题分
|
|
|
|
|
+ * @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) {
|
|
|
|
|
+ while(count > 0L && !questions.isEmpty()) {
|
|
|
LearnQuestions q = questions.size() > 1 ? questions.remove(random.nextInt(questions.size() - 1)) : questions.remove(0);
|
|
LearnQuestions q = questions.size() > 1 ? questions.remove(random.nextInt(questions.size() - 1)) : questions.remove(0);
|
|
|
if(existQuestionIdSet.add(q.getId())) {
|
|
if(existQuestionIdSet.add(q.getId())) {
|
|
|
LearnPaperQuestion pq = new LearnPaperQuestion();
|
|
LearnPaperQuestion pq = new LearnPaperQuestion();
|
|
|
pq.setSeq(pqList.size() + 1);
|
|
pq.setSeq(pqList.size() + 1);
|
|
|
- pq.setKnowledgeId(q.getKnowledgeId());
|
|
|
|
|
|
|
+ pq.setKnowledgeId(knowId);
|
|
|
pq.setScore(score);
|
|
pq.setScore(score);
|
|
|
pq.setQuestionId(q.getId());
|
|
pq.setQuestionId(q.getId());
|
|
|
|
|
+ pq.setType(type);
|
|
|
pqList.add(pq);
|
|
pqList.add(pq);
|
|
|
count--;
|
|
count--;
|
|
|
if(pqList.size() == totalCount) {
|
|
if(pqList.size() == totalCount) {
|
|
@@ -297,6 +387,7 @@ public class PaperService {
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
+ return count;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
@@ -353,10 +444,10 @@ public class PaperService {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
|
- * 合并 排除总量和总量
|
|
|
|
|
- * @param knowTypeAssignMap
|
|
|
|
|
|
|
+ * 合并 未用总量和已有总量, 分配数置0
|
|
|
|
|
+ * @param knowTypeAssignMap key=knowId +"_" + qtype
|
|
|
* @param cond
|
|
* @param cond
|
|
|
- * @param index 1 free 2 total
|
|
|
|
|
|
|
+ * @param index 1 free 2 used
|
|
|
*/
|
|
*/
|
|
|
private void setValue(Map<String, KnowTypeAssign> knowTypeAssignMap, Map cond, Integer index) {
|
|
private void setValue(Map<String, KnowTypeAssign> knowTypeAssignMap, Map cond, Integer index) {
|
|
|
for (LearnQuestions q : questionsMapper.statByKnowledgeType(cond)) {
|
|
for (LearnQuestions q : questionsMapper.statByKnowledgeType(cond)) {
|
|
@@ -382,11 +473,11 @@ public class PaperService {
|
|
|
|
|
|
|
|
@Data
|
|
@Data
|
|
|
public static class KnowTypeAssign {
|
|
public static class KnowTypeAssign {
|
|
|
- Long knowId;
|
|
|
|
|
- String type;
|
|
|
|
|
- Long exclAssign; // 分配个数
|
|
|
|
|
- Long assign; // 全量分配个数
|
|
|
|
|
- Long exclCount; // 排除总数
|
|
|
|
|
- Long total; // 全量总数
|
|
|
|
|
|
|
+ Long knowId; // 知识点
|
|
|
|
|
+ String type; // 题类型
|
|
|
|
|
+ Long exclAssign; // 未用分配数
|
|
|
|
|
+ Long assign; // 已用分配数
|
|
|
|
|
+ Long exclCount; // 未用总量
|
|
|
|
|
+ Long total; // 已用总量
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|