|
@@ -0,0 +1,366 @@
|
|
|
|
+package com.qmth.cqb.genpaper.service;
|
|
|
|
+
|
|
|
|
+import java.util.ArrayList;
|
|
|
|
+import java.util.Collections;
|
|
|
|
+import java.util.LinkedList;
|
|
|
|
+import java.util.List;
|
|
|
|
+import java.util.Map;
|
|
|
|
+import java.util.Set;
|
|
|
|
+
|
|
|
|
+import org.springframework.beans.factory.annotation.Autowired;
|
|
|
|
+import org.springframework.stereotype.Service;
|
|
|
|
+
|
|
|
|
+import com.qmth.cqb.genpaper.condition.Condition;
|
|
|
|
+import com.qmth.cqb.genpaper.context.DetailContext;
|
|
|
|
+import com.qmth.cqb.genpaper.context.PaperContext;
|
|
|
|
+import com.qmth.cqb.genpaper.context.UnitContext;
|
|
|
|
+import com.qmth.cqb.paper.dao.PaperDetailRepo;
|
|
|
|
+import com.qmth.cqb.paper.dao.PaperDetailUnitRepo;
|
|
|
|
+import com.qmth.cqb.paper.dao.PaperRepo;
|
|
|
|
+import com.qmth.cqb.paper.dao.PaperStructRepo;
|
|
|
|
+import com.qmth.cqb.paper.model.Paper;
|
|
|
|
+import com.qmth.cqb.paper.model.PaperDetail;
|
|
|
|
+import com.qmth.cqb.paper.model.PaperDetailUnit;
|
|
|
|
+import com.qmth.cqb.paper.model.PaperStruct;
|
|
|
|
+import com.qmth.cqb.question.model.Question;
|
|
|
|
+import com.qmth.cqb.utils.CommonUtils;
|
|
|
|
+import com.qmth.cqb.utils.enums.QuesStructType;
|
|
|
|
+
|
|
|
|
+@Service
|
|
|
|
+public class GenPaperService {
|
|
|
|
+
|
|
|
|
+ @Autowired
|
|
|
|
+ PaperRepo paperRepo;
|
|
|
|
+
|
|
|
|
+ @Autowired
|
|
|
|
+ PaperDetailRepo paperDetailRepo;
|
|
|
|
+
|
|
|
|
+ @Autowired
|
|
|
|
+ PaperDetailUnitRepo unitRepo;
|
|
|
|
+
|
|
|
|
+ @Autowired
|
|
|
|
+ PaperStructRepo paperStructRepo;
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 按分数在选定的试卷中随机抽取题,组成一套新的试卷
|
|
|
|
+ *
|
|
|
|
+ * @param paperMap
|
|
|
|
+ * key:指定的试卷Id,value:需要抽取的分数
|
|
|
|
+ * @return 试卷
|
|
|
|
+ */
|
|
|
|
+ public Paper genPaperByScore(Map<String, Double> paperMap, String paperName) {
|
|
|
|
+ List<PaperDetailUnit> selectedUnits = new ArrayList<PaperDetailUnit>();// 选中的小题
|
|
|
|
+ if (paperMap != null && paperMap.size() > 0) {
|
|
|
|
+ for (String paperId : paperMap.keySet()) {
|
|
|
|
+ Double totalScore = paperMap.get(paperId);
|
|
|
|
+ Paper oldPaper = paperRepo.findOne(paperId);
|
|
|
|
+ List<PaperDetailUnit> unitList = unitRepo.findByPaper(oldPaper);
|
|
|
|
+ Collections.shuffle(unitList);// 随机乱序之后再根据分数取题
|
|
|
|
+ double sum = 0;
|
|
|
|
+ for (PaperDetailUnit pdu : unitList) {
|
|
|
|
+ sum += pdu.getScore();
|
|
|
|
+ if (sum <= totalScore) {// 5 10 15 20 25 30
|
|
|
|
+ selectedUnits.add(pdu);// 1 2 3 4 5 6
|
|
|
|
+ } else {
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return this.constuctPaper(selectedUnits, paperName);
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 按每套试卷需要抽取的题目数量随机抽取题,组成一套新的试卷
|
|
|
|
+ *
|
|
|
|
+ * @param paperMap
|
|
|
|
+ * key:指定的试卷Id,value:需要抽取试题数量
|
|
|
|
+ * @param paperName
|
|
|
|
+ * 试卷名称
|
|
|
|
+ * @return
|
|
|
|
+ */
|
|
|
|
+ public Paper genPaperByQuestionNum(Map<String, Integer> paperMap, String paperName) {
|
|
|
|
+ List<PaperDetailUnit> selectedUnits = new ArrayList<PaperDetailUnit>();// 选中的小题
|
|
|
|
+ if (paperMap != null && paperMap.size() > 0) {
|
|
|
|
+ for (String paperId : paperMap.keySet()) {
|
|
|
|
+ int unitNum = paperMap.get(paperId);
|
|
|
|
+ Paper oldPaper = paperRepo.findOne(paperId);
|
|
|
|
+ List<PaperDetailUnit> unitList = unitRepo.findByPaper(oldPaper);
|
|
|
|
+ Collections.shuffle(unitList);// 随机乱序之后再取题
|
|
|
|
+ if (unitList.size() >= unitNum) {
|
|
|
|
+ for (int i = 0; i < unitNum; i++) {
|
|
|
|
+ selectedUnits.add(unitList.get(i));
|
|
|
|
+ unitList.remove(i);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ for (PaperDetailUnit pdu : selectedUnits) {
|
|
|
|
+ if (pdu.getQuestionType().getId() == 6L && pdu.getQuestion().getSubQuestions().size() > 1) {// 假如是套题,要计算下面小题数量
|
|
|
|
+ selectedUnits.remove(pdu);// 删除掉这道套题
|
|
|
|
+ for (PaperDetailUnit oldPdu : unitList) {
|
|
|
|
+ if (pdu.getQuestionType().getId() != 6L) {// 从原来的集合中取一个不是套题的加进去
|
|
|
|
+ selectedUnits.add(oldPdu);
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return this.constuctPaper(selectedUnits, paperName);
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 构造大题
|
|
|
|
+ *
|
|
|
|
+ * @param units
|
|
|
|
+ * @param number
|
|
|
|
+ * @param detailName
|
|
|
|
+ * 大题名称
|
|
|
|
+ * @return
|
|
|
|
+ */
|
|
|
|
+ public PaperDetail constuctPaperDeatil(List<PaperDetailUnit> units, int number, String detailName) {
|
|
|
|
+ PaperDetail pd = new PaperDetail();
|
|
|
|
+ if (units != null && units.size() > 0) {
|
|
|
|
+ Double score = 0d;
|
|
|
|
+ for (PaperDetailUnit pdu : units) {
|
|
|
|
+ score += pdu.getScore();
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+ pd.setName(detailName);
|
|
|
|
+ pd.setUnitCount(units.size());
|
|
|
|
+ pd.setScore(score);
|
|
|
|
+ pd.setNumber(number);
|
|
|
|
+ pd.setCreateTime(CommonUtils.getCurDateTime());
|
|
|
|
+ for (PaperDetailUnit pdu : units) {
|
|
|
|
+ pdu.setPaperDetail(pd);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ return pd;
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 根据大题集合构造paper
|
|
|
|
+ *
|
|
|
|
+ * @param details
|
|
|
|
+ * @return
|
|
|
|
+ */
|
|
|
|
+ public Paper constuctPaperByPaperDetails(List<PaperDetail> details, String paperName) {
|
|
|
|
+ Paper paper = new Paper();
|
|
|
|
+ if (details != null && details.size() > 0) {
|
|
|
|
+ Double score = 0d;
|
|
|
|
+ for (PaperDetail pd : details) {
|
|
|
|
+ score += pd.getScore();
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+ paper.setName(paperName);
|
|
|
|
+ paper.setPaperDetailCount(details.size());
|
|
|
|
+ paper.setTotalScore(score);
|
|
|
|
+ paper.setCreateTime(CommonUtils.getCurDateTime());
|
|
|
|
+ for (PaperDetail pdu : details) {
|
|
|
|
+ pdu.setPaper(paper);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ return paper;
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 随机构造试卷,根据小题类型 没有定义试卷结构
|
|
|
|
+ *
|
|
|
|
+ * @param units
|
|
|
|
+ * @param number
|
|
|
|
+ * @param quesName
|
|
|
|
+ * @return
|
|
|
|
+ */
|
|
|
|
+ public Paper constuctPaper(List<PaperDetailUnit> selectedUnits, String paperName) {
|
|
|
|
+ Paper paper = new Paper();
|
|
|
|
+ List<PaperDetailUnit> singUnits = new ArrayList<PaperDetailUnit>();
|
|
|
|
+ List<PaperDetailUnit> multipleUnits = new ArrayList<PaperDetailUnit>();
|
|
|
|
+ List<PaperDetailUnit> boolUnits = new ArrayList<PaperDetailUnit>();
|
|
|
|
+ List<PaperDetailUnit> blankUnits = new ArrayList<PaperDetailUnit>();
|
|
|
|
+ List<PaperDetailUnit> textUnits = new ArrayList<PaperDetailUnit>();
|
|
|
|
+ List<PaperDetailUnit> nestUnits = new ArrayList<PaperDetailUnit>();
|
|
|
|
+ for (PaperDetailUnit pdu : selectedUnits) {
|
|
|
|
+ switch (pdu.getQuestionType()) {
|
|
|
|
+ case SINGLE_ANSWER_QUESTION:
|
|
|
|
+ singUnits.add(pdu);
|
|
|
|
+ break;
|
|
|
|
+ case MULTIPLE_ANSWER_QUESTION:
|
|
|
|
+ multipleUnits.add(pdu);
|
|
|
|
+ break;
|
|
|
|
+ case BOOL_ANSWER_QUESTION:
|
|
|
|
+ boolUnits.add(pdu);
|
|
|
|
+ break;
|
|
|
|
+ case FILL_BLANK_QUESTION:
|
|
|
|
+ blankUnits.add(pdu);
|
|
|
|
+ break;
|
|
|
|
+ case TEXT_ANSWER_QUESTION:
|
|
|
|
+ textUnits.add(pdu);
|
|
|
|
+ break;
|
|
|
|
+ case NESTED_ANSWER_QUESTION:
|
|
|
|
+ nestUnits.add(pdu);
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ PaperDetail singPd = this.constuctPaperDeatil(singUnits, 1, QuesStructType.SINGLE_ANSWER_QUESTION.getName());
|
|
|
|
+ PaperDetail multipePd = this.constuctPaperDeatil(multipleUnits, 2,
|
|
|
|
+ QuesStructType.MULTIPLE_ANSWER_QUESTION.getName());
|
|
|
|
+ PaperDetail boolPd = this.constuctPaperDeatil(boolUnits, 3, QuesStructType.BOOL_ANSWER_QUESTION.getName());
|
|
|
|
+ PaperDetail blankPd = this.constuctPaperDeatil(blankUnits, 4, QuesStructType.FILL_BLANK_QUESTION.getName());
|
|
|
|
+ PaperDetail textPd = this.constuctPaperDeatil(textUnits, 5, QuesStructType.TEXT_ANSWER_QUESTION.getName());
|
|
|
|
+ PaperDetail nestPd = this.constuctPaperDeatil(nestUnits, 6, QuesStructType.NESTED_ANSWER_QUESTION.getName());
|
|
|
|
+ selectedUnits.clear();
|
|
|
|
+ List<PaperDetail> pds = new ArrayList<PaperDetail>();
|
|
|
|
+ int paperDetailCount = 0;// 大题数量
|
|
|
|
+ Double totalScore = 0d;
|
|
|
|
+ if (singPd.getUnitCount() > 0) {
|
|
|
|
+ paperDetailCount = paperDetailCount + 1;
|
|
|
|
+ totalScore += singPd.getScore();
|
|
|
|
+ pds.add(singPd);
|
|
|
|
+ selectedUnits.addAll(singUnits);
|
|
|
|
+ } else if (multipePd.getUnitCount() > 0) {
|
|
|
|
+ paperDetailCount = paperDetailCount + 1;
|
|
|
|
+ totalScore += singPd.getScore();
|
|
|
|
+ pds.add(multipePd);
|
|
|
|
+ selectedUnits.addAll(multipleUnits);
|
|
|
|
+ } else if (boolPd.getUnitCount() > 0) {
|
|
|
|
+ paperDetailCount = paperDetailCount + 1;
|
|
|
|
+ totalScore += singPd.getScore();
|
|
|
|
+ pds.add(boolPd);
|
|
|
|
+ selectedUnits.addAll(boolUnits);
|
|
|
|
+ } else if (blankPd.getUnitCount() > 0) {
|
|
|
|
+ paperDetailCount = paperDetailCount + 1;
|
|
|
|
+ totalScore += singPd.getScore();
|
|
|
|
+ pds.add(blankPd);
|
|
|
|
+ selectedUnits.addAll(blankUnits);
|
|
|
|
+ } else if (textPd.getUnitCount() > 0) {
|
|
|
|
+ paperDetailCount = paperDetailCount + 1;
|
|
|
|
+ totalScore += singPd.getScore();
|
|
|
|
+ pds.add(textPd);
|
|
|
|
+ selectedUnits.addAll(textUnits);
|
|
|
|
+ } else if (nestPd.getUnitCount() > 0) {
|
|
|
|
+ paperDetailCount = nestPd.getUnitCount() + paperDetailCount;
|
|
|
|
+ totalScore += singPd.getScore();
|
|
|
|
+ pds.add(nestPd);
|
|
|
|
+ selectedUnits.addAll(nestUnits);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ paper.setName(paperName);
|
|
|
|
+ paper.setTotalScore(totalScore);
|
|
|
|
+ paper.setPaperDetailCount(paperDetailCount);
|
|
|
|
+ // 数据入库
|
|
|
|
+ paper = this.persistentPaper(pds, selectedUnits, paper);
|
|
|
|
+ return paper;
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 数据入库
|
|
|
|
+ *
|
|
|
|
+ * @param details
|
|
|
|
+ * @param selectedUnits
|
|
|
|
+ * @param paper
|
|
|
|
+ * @return
|
|
|
|
+ */
|
|
|
|
+ public Paper persistentPaper(List<PaperDetail> details, List<PaperDetailUnit> selectedUnits, Paper paper) {
|
|
|
|
+ for (PaperDetail pd : details) {
|
|
|
|
+ pd.setPaper(paper);
|
|
|
|
+ }
|
|
|
|
+ for (PaperDetailUnit pdu : selectedUnits) {
|
|
|
|
+ pdu.setPaper(paper);
|
|
|
|
+ }
|
|
|
|
+ unitRepo.save(selectedUnits);
|
|
|
|
+ paperDetailRepo.save(details);
|
|
|
|
+ paperRepo.save(paper);
|
|
|
|
+ return paper;
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 精确组卷,根据设定试卷结构组卷
|
|
|
|
+ *
|
|
|
|
+ * @param paperIds
|
|
|
|
+ * 取题范围
|
|
|
|
+ * @param paperStruct
|
|
|
|
+ * 设定的试卷结构
|
|
|
|
+ * @param conditions
|
|
|
|
+ * 筛选条件
|
|
|
|
+ * @return
|
|
|
|
+ */
|
|
|
|
+ public Paper genPaper(List<String> paperIds, PaperStruct paperStruct, List<Condition> conditions) {
|
|
|
|
+ LinkedList<Question> questions = new LinkedList<Question>();// 所有试题集合
|
|
|
|
+ PaperContext paperContext = new PaperContext(paperStruct, conditions);
|
|
|
|
+ List<UnitContext> unitContexts = new LinkedList<UnitContext>();
|
|
|
|
+ List<DetailContext> detailContexts = paperContext.getDetails();
|
|
|
|
+ for (DetailContext dc : detailContexts) {
|
|
|
|
+ unitContexts.addAll(dc.getUnits());
|
|
|
|
+ }
|
|
|
|
+ List<Paper> papers = (List<Paper>) paperRepo.findAll(paperIds);
|
|
|
|
+ for (Paper oldPaper : papers) {
|
|
|
|
+ List<PaperDetailUnit> unitList = unitRepo.findByPaper(oldPaper);
|
|
|
|
+ for (PaperDetailUnit unit : unitList) {
|
|
|
|
+ questions.add(unit.getQuestion());
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+ Collections.shuffle(questions);
|
|
|
|
+ int maxLoopCount = questions.size() * 2;
|
|
|
|
+ int selectCount = 0;
|
|
|
|
+ int maxCount = unitContexts.size();
|
|
|
|
+ int loopCount = 0;
|
|
|
|
+ while (questions.size() > 0 && (selectCount < maxCount) && loopCount < maxLoopCount) {
|
|
|
|
+ Question question = questions.removeFirst();
|
|
|
|
+ boolean structTypeMatch = false;
|
|
|
|
+ boolean selected = false;
|
|
|
|
+ for (UnitContext uc : unitContexts) {
|
|
|
|
+ if (uc.getUnitStruct().getQuestionType() == question.getQuestionType() && !uc.finish()) {
|
|
|
|
+ structTypeMatch = true;
|
|
|
|
+ if (uc.check(question)) {
|
|
|
|
+ uc.select(question);
|
|
|
|
+ selected = true;
|
|
|
|
+ selectCount++;
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ if (structTypeMatch && !selected) {
|
|
|
|
+ questions.addLast(question);
|
|
|
|
+ }
|
|
|
|
+ loopCount++;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ Set<Question> quesSet = paperContext.getSelectQues();
|
|
|
|
+ List<PaperDetail> paperDetails = new ArrayList<PaperDetail>();
|
|
|
|
+ List<PaperDetailUnit> paperDetailunits = new ArrayList<PaperDetailUnit>();
|
|
|
|
+ for (DetailContext dc : detailContexts) {
|
|
|
|
+ List<PaperDetailUnit> unitsTemp = new ArrayList<PaperDetailUnit>();
|
|
|
|
+ List<UnitContext> units = dc.getUnits();
|
|
|
|
+ for (UnitContext uc : units) {
|
|
|
|
+ for (Question ques : quesSet) {
|
|
|
|
+ if (uc.getUnitStruct().getQuestionType() == ques.getQuestionType()) {
|
|
|
|
+ PaperDetailUnit pdu = new PaperDetailUnit();
|
|
|
|
+ pdu.setCreateTime(CommonUtils.getCurDateTime());
|
|
|
|
+ pdu.setQuestion(ques);
|
|
|
|
+ pdu.setQuestionType(ques.getQuestionType());
|
|
|
|
+ pdu.setScore(uc.getUnitStruct().getScore());
|
|
|
|
+ unitsTemp.add(pdu);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+ paperDetails.add(this.constuctPaperDeatil(unitsTemp, dc.getDetailStruct().getNumber(),
|
|
|
|
+ dc.getDetailStruct().getName()));
|
|
|
|
+ paperDetailunits.addAll(unitsTemp);
|
|
|
|
+ }
|
|
|
|
+ Paper paper = this.constuctPaperByPaperDetails(paperDetails, paperStruct.getName());
|
|
|
|
+ this.persistentPaper(paperDetails, paperDetailunits, paper);
|
|
|
|
+ return paper;
|
|
|
|
+ }
|
|
|
|
+}
|