|
@@ -1,6 +1,5 @@
|
|
|
package cn.com.qmth.examcloud.core.questions.service.impl;
|
|
|
|
|
|
-
|
|
|
import static cn.com.qmth.examcloud.core.questions.service.cache.Constants.CACHE_KEY_PAPER_FOR_DTO;
|
|
|
import static cn.com.qmth.examcloud.core.questions.service.cache.Constants.DEFAULT_TIME_OUT;
|
|
|
|
|
@@ -17,6 +16,7 @@ import java.util.regex.Pattern;
|
|
|
import java.util.stream.Collectors;
|
|
|
|
|
|
import org.apache.commons.lang3.StringUtils;
|
|
|
+import org.bson.types.ObjectId;
|
|
|
import org.nlpcn.commons.lang.util.StringUtil;
|
|
|
import org.slf4j.Logger;
|
|
|
import org.slf4j.LoggerFactory;
|
|
@@ -29,12 +29,18 @@ import org.springframework.data.domain.PageRequest;
|
|
|
import org.springframework.data.mongodb.core.MongoTemplate;
|
|
|
import org.springframework.data.mongodb.core.query.Criteria;
|
|
|
import org.springframework.data.mongodb.core.query.Query;
|
|
|
+import org.springframework.data.mongodb.core.query.Update;
|
|
|
import org.springframework.stereotype.Service;
|
|
|
import org.springframework.util.Assert;
|
|
|
import org.springframework.util.CollectionUtils;
|
|
|
|
|
|
import cn.com.qmth.examcloud.api.commons.security.bean.User;
|
|
|
+import cn.com.qmth.examcloud.api.commons.security.bean.UserDataRule;
|
|
|
import cn.com.qmth.examcloud.commons.exception.StatusException;
|
|
|
+import cn.com.qmth.examcloud.core.oe.admin.api.ExamRecordCloudService;
|
|
|
+import cn.com.qmth.examcloud.core.oe.admin.api.request.CheckPaperInExamReq;
|
|
|
+import cn.com.qmth.examcloud.core.oe.admin.api.response.CheckPaperInExamResp;
|
|
|
+import cn.com.qmth.examcloud.core.oe.student.api.ExamRecordDataCloudService;
|
|
|
import cn.com.qmth.examcloud.core.questions.base.BeanCopierUtil;
|
|
|
import cn.com.qmth.examcloud.core.questions.base.CommonUtils;
|
|
|
import cn.com.qmth.examcloud.core.questions.base.Model;
|
|
@@ -50,7 +56,6 @@ import cn.com.qmth.examcloud.core.questions.base.question.enums.QuesStructType;
|
|
|
import cn.com.qmth.examcloud.core.questions.dao.AudioTimeConfigRepo;
|
|
|
import cn.com.qmth.examcloud.core.questions.dao.ExtractConfigRepo;
|
|
|
import cn.com.qmth.examcloud.core.questions.dao.PaperDetailRepo;
|
|
|
-import cn.com.qmth.examcloud.core.questions.dao.PaperDetailUnitNativeRepo;
|
|
|
import cn.com.qmth.examcloud.core.questions.dao.PaperDetailUnitRepo;
|
|
|
import cn.com.qmth.examcloud.core.questions.dao.PaperRepo;
|
|
|
import cn.com.qmth.examcloud.core.questions.dao.entity.AudioTimeConfig;
|
|
@@ -89,1135 +94,1241 @@ import cn.com.qmth.examcloud.web.redis.RedisClient;
|
|
|
*/
|
|
|
@Service("extractConfigService")
|
|
|
public class ExtractConfigServiceImpl implements ExtractConfigService {
|
|
|
- private static final Logger logger = LoggerFactory.getLogger(ExtractConfigServiceImpl.class);
|
|
|
+ private static final Logger LOG = LoggerFactory.getLogger(ExtractConfigServiceImpl.class);
|
|
|
|
|
|
- @Autowired
|
|
|
- private ExtractConfigRepo extractConfigRepo;
|
|
|
+ @Autowired
|
|
|
+ private ExtractConfigRepo extractConfigRepo;
|
|
|
|
|
|
- @Autowired
|
|
|
- private PaperDetailRepo paperDetailRepo;
|
|
|
+ @Autowired
|
|
|
+ private PaperDetailRepo paperDetailRepo;
|
|
|
|
|
|
- @Autowired
|
|
|
- private PaperDetailUnitRepo paperDetailUnitRepo;
|
|
|
+ @Autowired
|
|
|
+ private PaperDetailUnitRepo paperDetailUnitRepo;
|
|
|
|
|
|
- @Autowired
|
|
|
- private AudioTimeConfigRepo audioTimeConfigRepo;
|
|
|
+ @Autowired
|
|
|
+ private AudioTimeConfigRepo audioTimeConfigRepo;
|
|
|
|
|
|
- @Autowired
|
|
|
- private PaperRepo paperRepo;
|
|
|
+ @Autowired
|
|
|
+ private PaperRepo paperRepo;
|
|
|
|
|
|
- @Autowired
|
|
|
- private QuesService quesService;
|
|
|
+ @Autowired
|
|
|
+ private QuesService quesService;
|
|
|
|
|
|
- @Autowired
|
|
|
- private QuestionAudioService questionAudioService;
|
|
|
+ @Autowired
|
|
|
+ private QuestionAudioService questionAudioService;
|
|
|
|
|
|
- @Autowired
|
|
|
- private MongoTemplate mongoTemplate;
|
|
|
+ @Autowired
|
|
|
+ private MongoTemplate mongoTemplate;
|
|
|
|
|
|
- @Autowired
|
|
|
- private CourseService courseService;
|
|
|
+ @Autowired
|
|
|
+ private CourseService courseService;
|
|
|
//
|
|
|
// @Autowired
|
|
|
// private SysProperty sysProperty;
|
|
|
|
|
|
- @Autowired
|
|
|
- private PaperDtoAssembler paperDtoAssembler;
|
|
|
-
|
|
|
- @Autowired
|
|
|
- private PaperDetailDtoAssembler paperDetailDtoAssembler;
|
|
|
-
|
|
|
- @Autowired
|
|
|
- private PaperDetailUnitDtoAssembler paperDetailUnitDtoAssembler;
|
|
|
-
|
|
|
- @Autowired
|
|
|
- private SubQuestionDtoAssembler subQuestionDtoAssembler;
|
|
|
-
|
|
|
- @Autowired
|
|
|
- private RedisClient redisClient;
|
|
|
-
|
|
|
- @Autowired
|
|
|
- private PaperDetailUnitNativeRepo detailUnitNativeRepo;
|
|
|
-
|
|
|
- @Autowired
|
|
|
- private ExamCloudService examCloudService;
|
|
|
-
|
|
|
- @Override
|
|
|
- public ExtractConfig findConfig(ExtractConfig condition) {
|
|
|
- if (condition.getExamId() == null) {
|
|
|
- return null;
|
|
|
- }
|
|
|
- if (StringUtils.isBlank(condition.getCourseCode())) {
|
|
|
- return null;
|
|
|
- }
|
|
|
- Query query = new Query();
|
|
|
- if (!StringUtils.isBlank(condition.getOrgId())) {
|
|
|
- query.addCriteria(Criteria.where("orgId").is(condition.getOrgId()));
|
|
|
- }
|
|
|
- query.addCriteria(Criteria.where("examId").is(condition.getExamId()));
|
|
|
- query.addCriteria(Criteria.where("courseCode").is(condition.getCourseCode()));
|
|
|
- ExtractConfig tempConfig = this.mongoTemplate.findOne(query, ExtractConfig.class);
|
|
|
- return tempConfig;
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public Map<String, String> saveExtractConfig2(ExtractConfig extractConfig, User user) throws Exception {
|
|
|
- List<ExamPaper> examPapers = extractConfig.getExamPaperList();
|
|
|
- for (int i = 0; i < examPapers.size(); i++) {
|
|
|
- ExamPaper examPaper = examPapers.get(i);
|
|
|
- Paper paper = examPaper.getPaper();
|
|
|
- paper = Model.of(paperRepo.findById(paper.getId()));
|
|
|
- examPaper.setPaper(paper);
|
|
|
- }
|
|
|
- Course course = courseService.getCourse(Long.valueOf(extractConfig.getOrgId()), extractConfig.getCourseCode());
|
|
|
- extractConfig.setCourse(course);
|
|
|
- extractConfig.setCourseName(course.getName());
|
|
|
- Map<String, String> newFinishedPaperIdMap = makePaperByConfig(extractConfig);
|
|
|
- extractConfig.setFinishedPaperIdMap(newFinishedPaperIdMap);
|
|
|
- extractConfig.setIfFinish((short) 1);
|
|
|
- extractConfigRepo.save(extractConfig);
|
|
|
- return newFinishedPaperIdMap;
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public List<ExamPaper> saveExtractConfig(ExtractConfig extractConfig, User user) {
|
|
|
- List<ExamPaper> examPapers = extractConfig.getExamPaperList();
|
|
|
- for (int i = 0; i < examPapers.size(); i++) {
|
|
|
- ExamPaper examPaper = examPapers.get(i);
|
|
|
- Paper paper = examPaper.getPaper();
|
|
|
- paper = Model.of(paperRepo.findById(paper.getId()));
|
|
|
- examPaper.setPaper(paper);
|
|
|
- if(ExamType.OFFLINE.name().equals(extractConfig.getExamType())) {
|
|
|
- checkOfflinePaper(paper);
|
|
|
- }
|
|
|
- }
|
|
|
- Course course = courseService.getCourse(Long.valueOf(extractConfig.getOrgId()), extractConfig.getCourseCode());
|
|
|
- extractConfig.setCourse(course);
|
|
|
- extractConfig.setCourseName(course.getName());
|
|
|
- extractConfig.setIfFinish((short) 1);
|
|
|
- extractConfigRepo.save(extractConfig);
|
|
|
- return examPapers;
|
|
|
- }
|
|
|
-
|
|
|
- private void checkOfflinePaper(Paper paper) {
|
|
|
- List<PaperDetailUnit> pdus=paperDetailUnitRepo.findByPaper(paper);
|
|
|
- if(pdus==null||pdus.size()==0) {
|
|
|
- return;
|
|
|
- }
|
|
|
- for(PaperDetailUnit pdu:pdus) {
|
|
|
- if (pdu.getQuestionType() == QuesStructType.SINGLE_ANSWER_QUESTION
|
|
|
- || pdu.getQuestionType() == QuesStructType.MULTIPLE_ANSWER_QUESTION
|
|
|
- || pdu.getQuestionType() == QuesStructType.BOOL_ANSWER_QUESTION){
|
|
|
- throw new StatusException("500", "试卷包含客观题,无法保存规则");
|
|
|
- }else if(pdu.getQuestionType() == QuesStructType.NESTED_ANSWER_QUESTION&&!CollectionUtils.isEmpty(pdu.getQuestion().getSubQuestions())) {
|
|
|
- for(Question q:pdu.getQuestion().getSubQuestions()) {
|
|
|
- if (q.getQuestionType() == QuesStructType.SINGLE_ANSWER_QUESTION
|
|
|
- || q.getQuestionType() == QuesStructType.MULTIPLE_ANSWER_QUESTION
|
|
|
- || q.getQuestionType() == QuesStructType.BOOL_ANSWER_QUESTION){
|
|
|
- throw new StatusException("500", "试卷包含客观题,无法保存规则");
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- @Override
|
|
|
- public ExtractConfig findConfigById(String id) {
|
|
|
- if (StringUtils.isBlank(id)) {
|
|
|
- return null;
|
|
|
- }
|
|
|
- return Model.of(extractConfigRepo.findById(id));
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public Map<String, Object> extractExamPaper(Long exam_id, String course_code, String group_code) {
|
|
|
- Map<String, Object> returnMap = new HashMap<>();
|
|
|
- logger.info("调卷开始...");
|
|
|
- long beginTime = System.currentTimeMillis();
|
|
|
- logger.info("开始根据examId:" + exam_id + "和courseCode:" + course_code + "获取调卷规则");
|
|
|
- ExtractConfig extractConfig = this.findConfig(new ExtractConfig(exam_id, course_code));
|
|
|
- if (extractConfig == null) {
|
|
|
- logger.error("该考试和课程下调卷规则未制定,请先制定调卷规则,调卷程序退出");
|
|
|
- returnMap.put("errorMsg", "该考试和课程下调卷规则未制定,请先制定调卷规则");
|
|
|
- return returnMap;
|
|
|
- }
|
|
|
- long configFinishTime = System.currentTimeMillis();
|
|
|
- logger.info("获取调卷规则共耗时:" + (configFinishTime - beginTime) + "ms");
|
|
|
- logger.info("根据调卷规则中设置的概率获取类型为" + group_code + "的试卷");
|
|
|
- Map<String, Paper> paperMap = this.getExamPaperByProbability(extractConfig.getExamPaperList());
|
|
|
- if (paperMap.isEmpty()) {
|
|
|
- logger.error("该考试和课程下调卷规则中试卷不存在,请检查调卷规则,调卷程序退出");
|
|
|
- returnMap.put("errorMsg", "该考试和课程下调卷规则中试卷不存在,请重新制定调卷规则");
|
|
|
- return returnMap;
|
|
|
- }
|
|
|
-
|
|
|
- long paperMapFinishTime = System.currentTimeMillis();
|
|
|
- logger.info("获取类型为" + group_code + "的试卷共耗时:" + (paperMapFinishTime - configFinishTime) + "ms");
|
|
|
-
|
|
|
- Paper basePaper = paperMap.get(group_code);
|
|
|
- if (basePaper == null) {
|
|
|
- logger.error("该考试和课程下调卷规则中该类型试卷不存在,请检查调卷规则,调卷程序退出");
|
|
|
- returnMap.put("errorMsg", "该考试和课程下调卷规则中该类型试卷不存在,请重新制定调卷规则");
|
|
|
- return returnMap;
|
|
|
- }
|
|
|
- String basePaperId = basePaper.getId();
|
|
|
- logger.info("将原始试卷:" + basePaperId + "根据规则重新组卷");
|
|
|
- int upSetQuestionOrder = extractConfig.getScrambling_the_question_order();
|
|
|
- int upSetOptionOrder = extractConfig.getScrambling_the_option_order();
|
|
|
- //不乱序直接调卷
|
|
|
- if (upSetQuestionOrder == 0 && upSetOptionOrder == 0) {
|
|
|
- PaperDto paperDto = getPaperDtoByPaper(basePaper, basePaperId);
|
|
|
- long paperDtoFinishTime = System.currentTimeMillis();
|
|
|
- logger.info("获取试卷Dto共耗时:" + (paperDtoFinishTime - paperMapFinishTime) + "ms");
|
|
|
- returnMap.put("paperDto", paperDto);
|
|
|
- logger.info("调卷完成");
|
|
|
- logger.info("总共耗时:" + (System.currentTimeMillis() - beginTime) + "ms");
|
|
|
- } else {
|
|
|
- //乱序重新生成试卷
|
|
|
- Paper newPaper = this.recombinationPaper(basePaper, PaperType.STUDENT_EXAM, upSetQuestionOrder, upSetOptionOrder);
|
|
|
- logger.info("根据新试卷 paperId:" + newPaper.getId() + "组装PaperDto后返回");
|
|
|
-
|
|
|
- long genPaperFinishTime = System.currentTimeMillis();
|
|
|
- logger.info("组卷共耗时:" + (genPaperFinishTime - paperMapFinishTime) + "ms");
|
|
|
- PaperDto paperDto = getPaperDtoByPaper(newPaper, basePaperId);
|
|
|
-
|
|
|
- long paperDtoFinishTime = System.currentTimeMillis();
|
|
|
- logger.info("获取试卷Dto共耗时:" + (paperDtoFinishTime - genPaperFinishTime) + "ms");
|
|
|
-
|
|
|
- returnMap.put("paperDto", paperDto);
|
|
|
- logger.info("调卷完成");
|
|
|
- logger.info("总共耗时:" + (System.currentTimeMillis() - beginTime) + "ms");
|
|
|
- }
|
|
|
- return returnMap;
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public boolean checkIsAllQbjectiveQuestion(String paperId) {
|
|
|
- //优先从redis中获取缓存dto
|
|
|
- PaperDto cachePaperDto = redisClient.get(CACHE_KEY_PAPER_FOR_DTO + paperId, PaperDto.class, DEFAULT_TIME_OUT);
|
|
|
- if (cachePaperDto != null) {
|
|
|
- return cachePaperDto.isAllQbjectiveQuestion();
|
|
|
- }
|
|
|
-
|
|
|
- Paper paper = Model.of(paperRepo.findById(paperId));
|
|
|
- List<PaperDetailUnit> paperDetailUnits = paperDetailUnitRepo.findByPaperOrderByNumber(paper);
|
|
|
- for (PaperDetailUnit paperDetailUnit : paperDetailUnits) {
|
|
|
- Question question = paperDetailUnit.getQuestion();
|
|
|
- //填空或问答
|
|
|
- if (question.getQuestionType() == QuesStructType.FILL_BLANK_QUESTION
|
|
|
- || question.getQuestionType() == QuesStructType.TEXT_ANSWER_QUESTION) {
|
|
|
- return false;
|
|
|
- }
|
|
|
- if (question.getQuestionType() == QuesStructType.NESTED_ANSWER_QUESTION) {
|
|
|
- List<Question> subQuestions = question.getSubQuestions();
|
|
|
- for (Question subQuestion : subQuestions) {
|
|
|
- if (subQuestion.getQuestionType() == QuesStructType.FILL_BLANK_QUESTION
|
|
|
- || subQuestion.getQuestionType() == QuesStructType.TEXT_ANSWER_QUESTION) {
|
|
|
- return false;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- return true;
|
|
|
- }
|
|
|
-
|
|
|
- public boolean checkIsAllQbjectiveByPdu(List<PaperDetailUnit> paperDetailUnits) {
|
|
|
- for (PaperDetailUnit paperDetailUnit : paperDetailUnits) {
|
|
|
- Question question = paperDetailUnit.getQuestion();
|
|
|
- //填空或问答
|
|
|
- if (question.getQuestionType() == QuesStructType.FILL_BLANK_QUESTION
|
|
|
- || question.getQuestionType() == QuesStructType.TEXT_ANSWER_QUESTION) {
|
|
|
- return false;
|
|
|
- }
|
|
|
- if (question.getQuestionType() == QuesStructType.NESTED_ANSWER_QUESTION) {
|
|
|
- List<Question> subQuestions = question.getSubQuestions();
|
|
|
- for (Question subQuestion : subQuestions) {
|
|
|
- if (subQuestion.getQuestionType() == QuesStructType.FILL_BLANK_QUESTION
|
|
|
- || subQuestion.getQuestionType() == QuesStructType.TEXT_ANSWER_QUESTION) {
|
|
|
- return false;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- return true;
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public Map<String, String> makePaperByConfig(ExtractConfig extractConfig) {
|
|
|
- Map<String, String> finishedPaperIdMap = new HashMap<>();
|
|
|
- if (extractConfig == null) {
|
|
|
- throw new RuntimeException("调卷规则不存在");
|
|
|
- }
|
|
|
- //获得规则中设置的试卷
|
|
|
- Map<String, Paper> paperMap = this.getExamPaperByProbability(extractConfig.getExamPaperList());
|
|
|
- if (paperMap.isEmpty()) {
|
|
|
- throw new RuntimeException("抽取试卷失败");
|
|
|
- }
|
|
|
- for (Map.Entry<String, Paper> entry : paperMap.entrySet()) {
|
|
|
- String key = entry.getKey();
|
|
|
- //根据原有试卷重新组卷得到新试卷
|
|
|
- /*Paper newPaper = this.recombinationPaper(entry.getValue(),
|
|
|
- PaperType.PREVIEW,
|
|
|
- extractConfig.getScrambling_the_question_order(),
|
|
|
- extractConfig.getScrambling_the_option_order());*/
|
|
|
- finishedPaperIdMap.put(key, entry.getValue().getId());
|
|
|
- }
|
|
|
- return finishedPaperIdMap;
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 重组试卷,生成新的试卷
|
|
|
- *
|
|
|
- * @param paper 选中的试卷
|
|
|
- * @param upSetQuestionOrder 客观题小题乱序 1:乱序 0:不乱序
|
|
|
- * @param upSetOptionOrder 客观题选项乱序 1:乱序 0:不乱序
|
|
|
- * @return
|
|
|
- */
|
|
|
- public Paper recombinationPaper(Paper paper, PaperType paperType, int upSetQuestionOrder, int upSetOptionOrder) {
|
|
|
-
|
|
|
- //将小题全部取出来,只取一次
|
|
|
- List<PaperDetailUnit> allPaperDetailUnits = paperDetailUnitRepo.findByPaperOrderByNumber(paper);
|
|
|
- //获取大题
|
|
|
- List<PaperDetail> paperDetails = paperDetailRepo.findByPaperOrderByNumber(paper);
|
|
|
-
|
|
|
- //抽取大题号对应的小题
|
|
|
- Map<String, List<PaperDetailUnit>> pduMap = allPaperDetailUnits.stream()
|
|
|
- .collect(Collectors.groupingBy(PaperDetailUnit::getDetailId));
|
|
|
- //最终保存的所有小题
|
|
|
- List<PaperDetailUnit> savePaperDetailUnits = new ArrayList<>();
|
|
|
- //保存试卷信息
|
|
|
- paper.setId(null);
|
|
|
- paper.setPaperType(paperType);
|
|
|
- Paper newPaper = paperRepo.insert(paper);
|
|
|
-
|
|
|
- for (int i = 0; i < paperDetails.size(); i++) {
|
|
|
- PaperDetail paperDetail = paperDetails.get(i);
|
|
|
-
|
|
|
- List<PaperDetailUnit> paperDetailUnits = pduMap.get(paperDetail.getId());
|
|
|
- if (paperDetailUnits == null || paperDetailUnits.size() == 0) {
|
|
|
- continue;
|
|
|
- }
|
|
|
- Collections.sort(paperDetailUnits);
|
|
|
-
|
|
|
- //将大题中最小的number取出
|
|
|
- PaperDetailUnit topDetailUnit = paperDetailUnits.get(0);
|
|
|
- int minNumber = topDetailUnit.getNumber();
|
|
|
-
|
|
|
- //小题乱序
|
|
|
- if (paperDetailUnits != null && paperDetailUnits.size() > 0) {
|
|
|
- if ((topDetailUnit.getQuestionType() == QuesStructType.SINGLE_ANSWER_QUESTION
|
|
|
- || topDetailUnit.getQuestionType() == QuesStructType.MULTIPLE_ANSWER_QUESTION
|
|
|
- || topDetailUnit.getQuestionType() == QuesStructType.BOOL_ANSWER_QUESTION)
|
|
|
- && upSetQuestionOrder == 1) {
|
|
|
- Collections.shuffle(paperDetailUnits);//打乱小题List
|
|
|
- }
|
|
|
- }
|
|
|
- //设置大题信息
|
|
|
- paperDetail.setId(null);
|
|
|
- paperDetail.setPaper(newPaper);
|
|
|
-
|
|
|
- for (int j = 0; j < paperDetailUnits.size(); j++) {
|
|
|
- //重新设置保存PaperDetailUnit
|
|
|
- PaperDetailUnit paperDetailUnit = paperDetailUnits.get(j);
|
|
|
- paperDetailUnit.setPaperType(paperType);
|
|
|
- paperDetailUnit.setPaper(newPaper);
|
|
|
- paperDetailUnit.setPaperDetail(paperDetail);
|
|
|
- paperDetailUnit.setNumber(minNumber + j); //重新设置序号
|
|
|
- reSavePaperDetailUtilAndQuestion(paperDetailUnit, upSetOptionOrder);
|
|
|
- savePaperDetailUnits.add(paperDetailUnit);
|
|
|
- }
|
|
|
-
|
|
|
- }
|
|
|
- //保存大题信息
|
|
|
- paperDetailRepo.insert(paperDetails);
|
|
|
- //保存小题信息
|
|
|
- paperDetailUnitRepo.insert(savePaperDetailUnits);
|
|
|
-
|
|
|
-
|
|
|
- //清空所有list
|
|
|
- allPaperDetailUnits.clear();
|
|
|
- savePaperDetailUnits.clear();
|
|
|
- paperDetails.clear();
|
|
|
-
|
|
|
- return newPaper;
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 每个试卷类型取出一套试卷
|
|
|
- * {
|
|
|
- * A:Paper,
|
|
|
- * B:Paper
|
|
|
- * }
|
|
|
- * A是试卷类型 Paper是A类型下选定的试卷
|
|
|
- *
|
|
|
- * @param examPaperList
|
|
|
- * @return
|
|
|
- */
|
|
|
- private Map<String, Paper> getExamPaperByProbability(List<ExamPaper> examPaperList) {
|
|
|
- Map<String, Paper> paperByTypeMap = new HashMap<>();
|
|
|
- if (examPaperList == null || examPaperList.size() == 0) {
|
|
|
- throw new RuntimeException("可供抽取的试卷集合为空,无法抽取试卷");
|
|
|
- }
|
|
|
-
|
|
|
- Map<String, List<ExamPaper>> examPaperMap = new HashMap<>();
|
|
|
- for (int i = 0; i < examPaperList.size(); i++) {
|
|
|
- ExamPaper examPaper = examPaperList.get(i);
|
|
|
- if (!examPaperMap.containsKey(examPaper.getGroupCode())) {
|
|
|
- if (examPaper.getPaper() != null) {
|
|
|
- List<ExamPaper> epList = new ArrayList<>();
|
|
|
- epList.add(examPaper);
|
|
|
- examPaperMap.put(examPaper.getGroupCode(), epList);
|
|
|
- }
|
|
|
- } else {
|
|
|
- if (examPaper.getPaper() != null) {
|
|
|
- List<ExamPaper> epList = examPaperMap.get(examPaper.getGroupCode());
|
|
|
- epList.add(examPaper);
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- if (examPaperMap != null) {
|
|
|
- Set<String> keys = examPaperMap.keySet();
|
|
|
- Iterator<String> it = keys.iterator();
|
|
|
- while (it.hasNext()) {
|
|
|
- String key = it.next();
|
|
|
- Paper paper = this.getPaperByProbability(examPaperMap.get(key));
|
|
|
-
|
|
|
- if (paper == null) {
|
|
|
- continue;
|
|
|
- }
|
|
|
-
|
|
|
- //不能用原来的paper对象,否则examPaperList中的paper对象会被覆盖
|
|
|
- Paper newPaper = Model.of(paperRepo.findById(paper.getId()));
|
|
|
- paperByTypeMap.put(key, newPaper);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- return paperByTypeMap;
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 根据设定几率取出一套试卷
|
|
|
- *
|
|
|
- * @param examPaperList
|
|
|
- * @return
|
|
|
- */
|
|
|
- private Paper getPaperByProbability(List<ExamPaper> examPaperList) {
|
|
|
- int sum = 0;
|
|
|
- for (int i = 0; i < examPaperList.size(); i++) {
|
|
|
- sum += examPaperList.get(i).getWeight();
|
|
|
- }
|
|
|
-
|
|
|
- // 从1开始
|
|
|
- Integer rand = new Random().nextInt(sum) + 1;
|
|
|
- for (int i = 0; i < examPaperList.size(); i++) {
|
|
|
- rand -= examPaperList.get(i).getWeight();
|
|
|
- // 选中
|
|
|
- if (rand <= 0) {
|
|
|
- return examPaperList.get(i).getPaper();
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- return null;
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 重新设置并保存paperDetailUnit和question
|
|
|
- *
|
|
|
- * @param paperDetailUnit
|
|
|
- * @param upSetOptionOrder
|
|
|
- */
|
|
|
- private void reSavePaperDetailUtilAndQuestion(PaperDetailUnit paperDetailUnit, Integer upSetOptionOrder) {
|
|
|
- Question question = paperDetailUnit.getQuestion();
|
|
|
- //选项乱序
|
|
|
- if (upSetOptionOrder == 1) {
|
|
|
- //单选或多选
|
|
|
- if (question.getQuestionType() == QuesStructType.SINGLE_ANSWER_QUESTION ||
|
|
|
- question.getQuestionType() == QuesStructType.MULTIPLE_ANSWER_QUESTION) {
|
|
|
- List<String> numberList = new ArrayList<>();
|
|
|
- List<QuesOption> options = question.getQuesOptions();
|
|
|
- for (int k = 0; k < options.size(); k++) {
|
|
|
- QuesOption quesOption = options.get(k);
|
|
|
- numberList.add(quesOption.getNumber());
|
|
|
- }
|
|
|
- Collections.shuffle(numberList); //打乱number顺序
|
|
|
- paperDetailUnit.setOptionOrder(StringUtils.join(numberList.toArray(), ","));//设置option顺序
|
|
|
- }
|
|
|
- //套题,套题下小题不乱序,选择题选项乱序
|
|
|
- if (question.getQuestionType() == QuesStructType.NESTED_ANSWER_QUESTION) {
|
|
|
- List<Question> subQuestions = question.getSubQuestions();
|
|
|
- StringBuffer optionOrder = new StringBuffer();
|
|
|
- for (int m = 0; m < subQuestions.size(); m++) {
|
|
|
- Question subQuestion = subQuestions.get(m);
|
|
|
- if (subQuestion.getQuestionType() == QuesStructType.SINGLE_ANSWER_QUESTION ||
|
|
|
- subQuestion.getQuestionType() == QuesStructType.MULTIPLE_ANSWER_QUESTION) {
|
|
|
- List<String> numberList = new ArrayList<>();
|
|
|
- List<QuesOption> options = subQuestion.getQuesOptions();
|
|
|
- for (int n = 0; n < options.size(); n++) {
|
|
|
- QuesOption quesOption = options.get(n);
|
|
|
- numberList.add(quesOption.getNumber());
|
|
|
- }
|
|
|
- Collections.shuffle(numberList); //打乱number顺序
|
|
|
- optionOrder.append(StringUtils.join(numberList.toArray(), ",")).append(";");
|
|
|
- }
|
|
|
- }
|
|
|
- paperDetailUnit.setOptionOrder(optionOrder.toString()); //设置option顺序
|
|
|
- }
|
|
|
- }
|
|
|
- paperDetailUnit.setId(null);
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public List<String> getExamPaperId(String courseCode, String orgId) {
|
|
|
- Assert.hasLength(courseCode, "courseCode不能为空");
|
|
|
- Assert.hasLength(orgId, "orgId不能为空");
|
|
|
- List<String> paperIdList = new ArrayList<>();
|
|
|
- Query query = new Query();
|
|
|
- query.addCriteria(Criteria.where("courseCode").is(courseCode));
|
|
|
- query.addCriteria(Criteria.where("orgId").is(orgId));
|
|
|
- List<ExtractConfig> extractConfigList = this.mongoTemplate.find(query, ExtractConfig.class);
|
|
|
- for (ExtractConfig extractConfig : extractConfigList) {
|
|
|
- List<ExamPaper> examPaperList = extractConfig.getExamPaperList();
|
|
|
- if (examPaperList != null && examPaperList.size() > 0) {
|
|
|
- for (ExamPaper examPaper : examPaperList) {
|
|
|
- paperIdList.add(examPaper.getPaper().getId());
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- return paperIdList;
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 根据paper得到PaperDto
|
|
|
- *
|
|
|
- * @param paper
|
|
|
- * @return
|
|
|
- */
|
|
|
- @SuppressWarnings("unchecked")
|
|
|
- private PaperDto getPaperDtoByPaper(Paper paper, String basePaperId) {
|
|
|
- long beginTime = System.currentTimeMillis();
|
|
|
- //没有则重新组装
|
|
|
- PaperDto paperDto = paperDtoAssembler.toDto(paper);
|
|
|
- paperDto.setBasePaperId(basePaperId);
|
|
|
- paperDto.setAllQbjectiveQuestion(checkIsAllQbjectiveQuestion(basePaperId));
|
|
|
-
|
|
|
- long paperDtoEndTime = System.currentTimeMillis();
|
|
|
- logger.info("单独组装paperDto耗时:" + (paperDtoEndTime - beginTime) + "ms");
|
|
|
-
|
|
|
- //将小题全部取出来,只取一次
|
|
|
- List<PaperDetailUnit> allPaperDetailUnits = paperDetailUnitRepo.findByPaper(paper);
|
|
|
- long pduEndTime = System.currentTimeMillis();
|
|
|
- logger.info("数据库取小题耗时:" + (pduEndTime - paperDtoEndTime) + "ms");
|
|
|
- Collections.sort(allPaperDetailUnits);
|
|
|
- long pduSortEndTime = System.currentTimeMillis();
|
|
|
- logger.info("排序小题耗时:" + (pduSortEndTime - pduEndTime) + "ms");
|
|
|
-
|
|
|
- //获取大题
|
|
|
- List<PaperDetail> paperDetails = paperDetailRepo.findByPaper(paper);
|
|
|
- long pdEndTime = System.currentTimeMillis();
|
|
|
- logger.info("数据库取大题耗时:" + (pdEndTime - pduSortEndTime) + "ms");
|
|
|
- Collections.sort(paperDetails);
|
|
|
- long pdSortEndTime = System.currentTimeMillis();
|
|
|
- logger.info("排序大题耗时:" + (pdSortEndTime - pdEndTime) + "ms");
|
|
|
-
|
|
|
- //抽取大题Id对应的小题
|
|
|
- Map<String, List<PaperDetailUnit>> pduMap = allPaperDetailUnits.stream()
|
|
|
- .collect(Collectors.groupingBy(PaperDetailUnit::getDetailId));
|
|
|
- long pduMapEndTime = System.currentTimeMillis();
|
|
|
- logger.info("获取大题与小题对应关系耗时:" + (pduMapEndTime - pdSortEndTime) + "ms");
|
|
|
-
|
|
|
- // 获取大题Dto
|
|
|
- List<PaperDetailDto> paperDetailDtos = paperDetailDtoAssembler.toDtoList(paperDetails);
|
|
|
- paperDto.setPaperDetails(paperDetailDtos);
|
|
|
- long paperDetailDtoEndTime = System.currentTimeMillis();
|
|
|
- logger.info("单独组装paperDetailDto耗时:" + (paperDetailDtoEndTime - pduMapEndTime) + "ms");
|
|
|
-
|
|
|
- // 封装小题
|
|
|
- for (int i = 0; i < paperDetailDtos.size(); i++) {
|
|
|
- //根据大题查出大题下面的小题
|
|
|
- PaperDetail paperDetail = paperDetails.get(i);
|
|
|
-
|
|
|
- List<PaperDetailUnit> paperDetailUnits = pduMap.get(paperDetail.getId());
|
|
|
-
|
|
|
- List<PaperDetailUnitDto> paperDetailUnitDtos = new ArrayList<>();
|
|
|
- for (int j = 0; j < paperDetailUnits.size(); j++) {
|
|
|
- PaperDetailUnit paperDetailUnit = paperDetailUnits.get(j);
|
|
|
- if (paperDetailUnit == null || paperDetailUnit.getQuestion() == null) {
|
|
|
- break;
|
|
|
- }
|
|
|
- //设置答案
|
|
|
- setSelectQuestionAnswerUnit(paperDetailUnit);
|
|
|
-
|
|
|
- PaperDetailUnitDto unitDto = paperDetailUnitDtoAssembler.toDto(paperDetailUnit);
|
|
|
- /**
|
|
|
- * 此处不能传questionId,需要传paperDetailUnitId
|
|
|
- * 因为选项乱序在paperDetailUnit里
|
|
|
- * unitDto.setQuesId(paperDetailUnit.getQuestion().getId());
|
|
|
- */
|
|
|
- unitDto.setQuesId(paperDetailUnit.getId());
|
|
|
- String answer = paperDetailUnit.getQuestion().getQuesAnswer();
|
|
|
- if (StringUtils.isNotEmpty(answer)) {
|
|
|
- unitDto.setAnswer(answer);
|
|
|
- }
|
|
|
- if (unitDto.getQuestionType() == QuesStructType.NESTED_ANSWER_QUESTION) {// 假如是套题
|
|
|
- List<Question> subQuesList = paperDetailUnit.getQuestion().getSubQuestions();
|
|
|
- List<SubQuestionDto> subQuesDtos = subQuestionDtoAssembler.toDtoList(subQuesList);
|
|
|
- for (int m = 0; m < subQuesList.size(); m++) {
|
|
|
- List<QuesOptionDto> quesOptionDtos = subQuestionDtoAssembler.toOptionDtoList(subQuesList.get(m).getQuesOptions());
|
|
|
- subQuesDtos.get(m).setQuesOptions(quesOptionDtos);
|
|
|
- if (StringUtils.isNotEmpty(subQuesList.get(m).getQuesAnswer())) {
|
|
|
- subQuesDtos.get(m).setQuesAnswer(subQuesList.get(m).getQuesAnswer());
|
|
|
- }
|
|
|
- subQuesDtos.get(m).setNumber(m + 1);
|
|
|
- //套题分数从小题类中取值
|
|
|
- subQuesDtos.get(m).setScore(paperDetailUnit.getSubScoreList().get(m));
|
|
|
- }
|
|
|
- unitDto.setSubQuestions(subQuesDtos);
|
|
|
- }
|
|
|
- paperDetailUnitDtos.add(unitDto);
|
|
|
- }
|
|
|
- paperDetailDtos.get(i).setPaperDetailUnits(paperDetailUnitDtos);
|
|
|
- paperDetailDtos.get(i).setCnNum(CommonUtils.toCHNum(paperDetailDtos.get(i).getNumber()));
|
|
|
- }
|
|
|
- long paperDetailUnitDtoEndTime = System.currentTimeMillis();
|
|
|
- logger.info("单独组装paperDetailUnitDto耗时:" + (paperDetailUnitDtoEndTime - paperDetailDtoEndTime) + "ms");
|
|
|
-
|
|
|
- //将重新组装的dto放进缓存
|
|
|
- redisClient.set(CACHE_KEY_PAPER_FOR_DTO + paperDto.getId(), paperDto, DEFAULT_TIME_OUT);
|
|
|
- return paperDto;
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 测试获取paperDto
|
|
|
- *
|
|
|
- * @param basePaperId
|
|
|
- * @return
|
|
|
- */
|
|
|
- public PaperDto getPaperDtoByPaperNew(String basePaperId) {
|
|
|
-
|
|
|
- long beginTime = System.currentTimeMillis();
|
|
|
- //没有则重新组装
|
|
|
- Paper paper = Model.of(paperRepo.findById(basePaperId));
|
|
|
- PaperDto paperDto = paperDtoAssembler.toDto(paper);
|
|
|
- paperDto.setBasePaperId(basePaperId);
|
|
|
-
|
|
|
- long paperDtoEndTime = System.currentTimeMillis();
|
|
|
- logger.info("单独组装paperDto耗时:" + (paperDtoEndTime - beginTime) + "ms");
|
|
|
-
|
|
|
- //将小题全部取出来,只取一次
|
|
|
- List<PaperDetailUnit> allPaperDetailUnits = detailUnitNativeRepo.findByPaperId(paper.getId());
|
|
|
- long pduEndTime = System.currentTimeMillis();
|
|
|
- logger.info("数据库取小题耗时:" + (pduEndTime - paperDtoEndTime) + "ms");
|
|
|
- Collections.sort(allPaperDetailUnits);
|
|
|
- long pduSortEndTime = System.currentTimeMillis();
|
|
|
- logger.info("排序小题耗时:" + (pduSortEndTime - pduEndTime) + "ms");
|
|
|
-
|
|
|
-
|
|
|
- paperDto.setAllQbjectiveQuestion(checkIsAllQbjectiveByPdu(allPaperDetailUnits));
|
|
|
- long isAllObjEndtime = System.currentTimeMillis();
|
|
|
- logger.info("设置客观题耗时:" + (isAllObjEndtime - pduSortEndTime) + "ms");
|
|
|
-
|
|
|
-
|
|
|
- //获取大题
|
|
|
- List<PaperDetail> paperDetails = paperDetailRepo.findByPaper(paper);
|
|
|
- long pdEndTime = System.currentTimeMillis();
|
|
|
- logger.info("数据库取大题耗时:" + (pdEndTime - isAllObjEndtime) + "ms");
|
|
|
- Collections.sort(paperDetails);
|
|
|
- long pdSortEndTime = System.currentTimeMillis();
|
|
|
- logger.info("排序大题耗时:" + (pdSortEndTime - pdEndTime) + "ms");
|
|
|
-
|
|
|
- //抽取大题Id对应的小题
|
|
|
- Map<String, List<PaperDetailUnit>> pduMap = allPaperDetailUnits.stream()
|
|
|
- .collect(Collectors.groupingBy(PaperDetailUnit::getDetailId));
|
|
|
- long pduMapEndTime = System.currentTimeMillis();
|
|
|
- logger.info("获取大题与小题对应关系耗时:" + (pduMapEndTime - pdSortEndTime) + "ms");
|
|
|
-
|
|
|
- // 获取大题Dto
|
|
|
- List<PaperDetailDto> paperDetailDtos = paperDetailDtoAssembler.toDtoList(paperDetails);
|
|
|
- paperDto.setPaperDetails(paperDetailDtos);
|
|
|
- long paperDetailDtoEndTime = System.currentTimeMillis();
|
|
|
- logger.info("单独组装paperDetailDto耗时:" + (paperDetailDtoEndTime - pduMapEndTime) + "ms");
|
|
|
-
|
|
|
- // 封装小题
|
|
|
- for (int i = 0; i < paperDetailDtos.size(); i++) {
|
|
|
- //根据大题查出大题下面的小题
|
|
|
- PaperDetail paperDetail = paperDetails.get(i);
|
|
|
-
|
|
|
- List<PaperDetailUnit> paperDetailUnits = pduMap.get(paperDetail.getId());
|
|
|
-
|
|
|
- List<PaperDetailUnitDto> paperDetailUnitDtos = new ArrayList<>();
|
|
|
- for (int j = 0; j < paperDetailUnits.size(); j++) {
|
|
|
- PaperDetailUnit paperDetailUnit = paperDetailUnits.get(j);
|
|
|
- if (paperDetailUnit == null || paperDetailUnit.getQuestion() == null) {
|
|
|
- break;
|
|
|
- }
|
|
|
- //设置答案
|
|
|
- setSelectQuestionAnswerUnit(paperDetailUnit);
|
|
|
-
|
|
|
- PaperDetailUnitDto unitDto = paperDetailUnitDtoAssembler.toDto(paperDetailUnit);
|
|
|
- /**
|
|
|
- * 此处不能传questionId,需要传paperDetailUnitId
|
|
|
- * 因为选项乱序在paperDetailUnit里
|
|
|
- * unitDto.setQuesId(paperDetailUnit.getQuestion().getId());
|
|
|
- */
|
|
|
- unitDto.setQuesId(paperDetailUnit.getId());
|
|
|
- String answer = paperDetailUnit.getQuestion().getQuesAnswer();
|
|
|
- if (StringUtils.isNotEmpty(answer)) {
|
|
|
- unitDto.setAnswer(answer);
|
|
|
- }
|
|
|
- if (unitDto.getQuestionType() == QuesStructType.NESTED_ANSWER_QUESTION) {// 假如是套题
|
|
|
- List<Question> subQuesList = paperDetailUnit.getQuestion().getSubQuestions();
|
|
|
- List<SubQuestionDto> subQuesDtos = subQuestionDtoAssembler.toDtoList(subQuesList);
|
|
|
- for (int m = 0; m < subQuesList.size(); m++) {
|
|
|
- List<QuesOptionDto> quesOptionDtos = subQuestionDtoAssembler.toOptionDtoList(subQuesList.get(m).getQuesOptions());
|
|
|
- subQuesDtos.get(m).setQuesOptions(quesOptionDtos);
|
|
|
- if (StringUtils.isNotEmpty(subQuesList.get(m).getQuesAnswer())) {
|
|
|
- subQuesDtos.get(m).setQuesAnswer(subQuesList.get(m).getQuesAnswer());
|
|
|
- }
|
|
|
- subQuesDtos.get(m).setNumber(m + 1);
|
|
|
- //套题分数从小题类中取值
|
|
|
- subQuesDtos.get(m).setScore(paperDetailUnit.getSubScoreList().get(m));
|
|
|
- }
|
|
|
- unitDto.setSubQuestions(subQuesDtos);
|
|
|
- }
|
|
|
- paperDetailUnitDtos.add(unitDto);
|
|
|
- }
|
|
|
- paperDetailDtos.get(i).setPaperDetailUnits(paperDetailUnitDtos);
|
|
|
- paperDetailDtos.get(i).setCnNum(CommonUtils.toCHNum(paperDetailDtos.get(i).getNumber()));
|
|
|
- }
|
|
|
- long paperDetailUnitDtoEndTime = System.currentTimeMillis();
|
|
|
- logger.info("单独组装paperDetailUnitDto耗时:" + (paperDetailUnitDtoEndTime - paperDetailDtoEndTime) + "ms");
|
|
|
- return paperDto;
|
|
|
- }
|
|
|
-
|
|
|
- private void setSelectQuestoionAnswer(List<PaperDetailUnit> paperDetailUnits) {
|
|
|
- for (PaperDetailUnit paperDetailUnit : paperDetailUnits) {
|
|
|
- if (paperDetailUnit == null || paperDetailUnit.getQuestion() == null) {
|
|
|
- break;
|
|
|
- }
|
|
|
- String optionOrder = paperDetailUnit.getOptionOrder();
|
|
|
- Question question = paperDetailUnit.getQuestion();
|
|
|
- quesService.setSelectQuestionAnswer(question, optionOrder);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- private void setSelectQuestionAnswerUnit(PaperDetailUnit paperDetailUnit) {
|
|
|
- Question question = paperDetailUnit.getQuestion();
|
|
|
- if (paperDetailUnit == null || question == null) {
|
|
|
- return;
|
|
|
- }
|
|
|
- String optionOrder = paperDetailUnit.getOptionOrder();
|
|
|
- quesService.setSelectQuestionAnswer(question, optionOrder);
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- /**
|
|
|
- * 根据paperDetailUnitId抽取单个试题
|
|
|
- * 根据paperDetailUnitId中设置的option顺序对option排序
|
|
|
- */
|
|
|
- @Override
|
|
|
- public QuestionDto extractExamQuestion(String examId, String courseCode, String groupCode, String paperDetailUnitId) {
|
|
|
- PaperDetailUnit paperDetailUnit = Model.of(paperDetailUnitRepo.findById(paperDetailUnitId));
|
|
|
- List<PaperDetailUnit> paperDetailUnits = new ArrayList<>();
|
|
|
- paperDetailUnits.add(paperDetailUnit);
|
|
|
- //设置答案
|
|
|
- setSelectQuestoionAnswer(paperDetailUnits);
|
|
|
- //重新对选择题option进行排序(多选、单选、套题下选择题)
|
|
|
- reorderChoicequestionOption(paperDetailUnit);
|
|
|
- Question ques = paperDetailUnit.getQuestion();
|
|
|
- quesService.formatQues(ques);
|
|
|
- QuestionDto dto = BeanCopierUtil.copyProperties(ques, QuestionDto.class);
|
|
|
- dto.setScore(paperDetailUnit.getScore());
|
|
|
- dto.setQuesOptions(buildQuestionOptionDto(ques.getQuesOptions()));
|
|
|
- if (ques.getQuestionType() == QuesStructType.NESTED_ANSWER_QUESTION) {
|
|
|
- List<Question> subQuesList = ques.getSubQuestions();
|
|
|
- List<SubQuestionDto> subQuesDtos = new ArrayList<>();
|
|
|
- for (Question question : subQuesList) {
|
|
|
- SubQuestionDto subQuestionDto = new SubQuestionDto();
|
|
|
- BeanUtils.copyProperties(question, subQuestionDto);
|
|
|
- subQuesDtos.add(subQuestionDto);
|
|
|
- }
|
|
|
- for (int m = 0; m < subQuesList.size(); m++) {
|
|
|
- List<QuesOptionDto> quesOptionDtos = BeanCopierUtil
|
|
|
- .copyPropertiesOfList(subQuesList.get(m).getQuesOptions(), QuesOptionDto.class);
|
|
|
- subQuesDtos.get(m).setQuesOptions(quesOptionDtos);
|
|
|
- subQuesDtos.get(m).setQuesAnswer(subQuesList.get(m).getQuesAnswer());
|
|
|
- subQuesDtos.get(m).setNumber(m + 1);
|
|
|
- //套题分数从小题类中取值
|
|
|
- subQuesDtos.get(m).setScore(paperDetailUnit.getSubScoreList().get(m));
|
|
|
- dto.setSubQuestions(subQuesDtos);
|
|
|
- }
|
|
|
- }
|
|
|
- if (ques.getQuestionType() == QuesStructType.SINGLE_ANSWER_QUESTION
|
|
|
- || ques.getQuestionType() == QuesStructType.MULTIPLE_ANSWER_QUESTION) {
|
|
|
- dto.setQuesAnswer(ques.getQuesAnswer());
|
|
|
- }
|
|
|
- appendAudioFlag(dto, examId, courseCode, groupCode);
|
|
|
- return dto;
|
|
|
- }
|
|
|
-
|
|
|
- private List<QuesOptionDto> buildQuestionOptionDto(List<QuesOption> quesOptions) {
|
|
|
- if (quesOptions == null) {
|
|
|
- return null;
|
|
|
- }
|
|
|
- List<QuesOptionDto> optionDtos = new ArrayList<>();
|
|
|
- for (QuesOption option : quesOptions) {
|
|
|
- QuesOptionDto optionDto = new QuesOptionDto();
|
|
|
- optionDto.setNumber(option.getNumber());
|
|
|
- optionDto.setOptionBody(option.getOptionBody());
|
|
|
- optionDtos.add(optionDto);
|
|
|
- }
|
|
|
- return optionDtos;
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 1.给QuestionDto添加音频播放次数
|
|
|
- * 2.给试题音频中有a标签添加url
|
|
|
- *
|
|
|
- * @param questionDto
|
|
|
- */
|
|
|
- private void appendAudioFlag(QuestionDto questionDto, String examId, String courseCode, String groupCode) {
|
|
|
- if (questionDto.getHasAudio() != null && questionDto.getHasAudio() == true) {
|
|
|
- //1.判断questionDto是否含有音频,如果有添加音频播放次数
|
|
|
- AudioTimeConfig audioTimeConfig = Model.of(audioTimeConfigRepo.findOne(Example.of(new AudioTimeConfig(examId, courseCode, groupCode, questionDto.getId()))));
|
|
|
- questionDto.setPlayTime(audioTimeConfig != null ? audioTimeConfig.getPlayTime() : null);
|
|
|
- //2.1 取到题干,给a标签添加url
|
|
|
- String quesBody = questionDto.getQuesBody();
|
|
|
- questionDto.setQuesBody(buildBody(quesBody, questionDto));
|
|
|
- //2.2取到选项,给a标签添加url
|
|
|
- List<QuesOptionDto> quesOptionDtoList = questionDto.getQuesOptions();
|
|
|
- if (quesOptionDtoList != null && quesOptionDtoList.size() > 0) {
|
|
|
- for (QuesOptionDto quesOptionDto : quesOptionDtoList) {
|
|
|
- quesOptionDto.setOptionBody(buildBody(quesOptionDto.getOptionBody(), questionDto));
|
|
|
- }
|
|
|
- }
|
|
|
- } else {
|
|
|
- questionDto.setPlayTime(null);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- //给题目和选项添加url
|
|
|
- public String buildBody(String body, QuestionDto questionDto) {
|
|
|
- String[] bodyStrings = body.split("></a>");
|
|
|
- if (bodyStrings.length > 1) {
|
|
|
- String resultBody = "";
|
|
|
- for (int i = 0; i < bodyStrings.length; i++) {
|
|
|
- String containAStr = bodyStrings[i];
|
|
|
- if (containAStr.indexOf("<a") > -1) {
|
|
|
- String questionAudioId = matchAudioName(containAStr, "a", "id");
|
|
|
- QuestionAudio questionAudio = questionAudioService.findAudioById(questionAudioId);
|
|
|
- if (questionAudio != null) {
|
|
|
+ @Autowired
|
|
|
+ private PaperDtoAssembler paperDtoAssembler;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private PaperDetailDtoAssembler paperDetailDtoAssembler;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private PaperDetailUnitDtoAssembler paperDetailUnitDtoAssembler;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private SubQuestionDtoAssembler subQuestionDtoAssembler;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private RedisClient redisClient;
|
|
|
+
|
|
|
+ /*
|
|
|
+ * @Autowired private PaperDetailUnitNativeRepo detailUnitNativeRepo;
|
|
|
+ */
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private ExamCloudService examCloudService;
|
|
|
+ @Autowired
|
|
|
+ private ExamRecordCloudService adminExamRecordCloudService;
|
|
|
+ @Autowired
|
|
|
+ private ExamRecordDataCloudService studentExamRecordCloudService;
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public ExtractConfig findConfig(ExtractConfig condition) {
|
|
|
+ if (condition.getExamId() == null) {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ if (StringUtils.isBlank(condition.getCourseCode())) {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ Query query = new Query();
|
|
|
+ if (!StringUtils.isBlank(condition.getOrgId())) {
|
|
|
+ query.addCriteria(Criteria.where("orgId").is(condition.getOrgId()));
|
|
|
+ }
|
|
|
+ query.addCriteria(Criteria.where("examId").is(condition.getExamId()));
|
|
|
+ query.addCriteria(Criteria.where("courseCode").is(condition.getCourseCode()));
|
|
|
+ ExtractConfig tempConfig = this.mongoTemplate.findOne(query, ExtractConfig.class);
|
|
|
+ return tempConfig;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public Map<String, String> saveExtractConfig2(ExtractConfig extractConfig, User user) throws Exception {
|
|
|
+ List<ExamPaper> examPapers = extractConfig.getExamPaperList();
|
|
|
+ for (int i = 0; i < examPapers.size(); i++) {
|
|
|
+ ExamPaper examPaper = examPapers.get(i);
|
|
|
+ Paper paper = examPaper.getPaper();
|
|
|
+ paper = Model.of(paperRepo.findById(paper.getId()));
|
|
|
+ examPaper.setPaper(paper);
|
|
|
+ }
|
|
|
+ Course course = courseService.getCourse(Long.valueOf(extractConfig.getOrgId()), extractConfig.getCourseCode());
|
|
|
+ extractConfig.setCourse(course);
|
|
|
+ extractConfig.setCourseName(course.getName());
|
|
|
+ Map<String, String> newFinishedPaperIdMap = makePaperByConfig(extractConfig);
|
|
|
+ extractConfig.setFinishedPaperIdMap(newFinishedPaperIdMap);
|
|
|
+ extractConfig.setIfFinish((short) 1);
|
|
|
+ extractConfigRepo.save(extractConfig);
|
|
|
+ return newFinishedPaperIdMap;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public List<ExamPaper> saveExtractConfig(ExtractConfig extractConfig, User user) {
|
|
|
+ List<ExamPaper> examPapers = extractConfig.getExamPaperList();
|
|
|
+ for (int i = 0; i < examPapers.size(); i++) {
|
|
|
+ ExamPaper examPaper = examPapers.get(i);
|
|
|
+ Paper paper = examPaper.getPaper();
|
|
|
+ paper = Model.of(paperRepo.findById(paper.getId()));
|
|
|
+ examPaper.setPaper(paper);
|
|
|
+ if (ExamType.OFFLINE.name().equals(extractConfig.getExamType())) {
|
|
|
+ checkOfflinePaper(paper);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if(StringUtils.isNotBlank(extractConfig.getId())) {
|
|
|
+ disposeOldPaper(extractConfig.getId());
|
|
|
+ }
|
|
|
+ Course course = courseService.getCourse(Long.valueOf(extractConfig.getOrgId()), extractConfig.getCourseCode());
|
|
|
+ extractConfig.setCourse(course);
|
|
|
+ extractConfig.setCourseName(course.getName());
|
|
|
+ extractConfig.setIfFinish((short) 1);
|
|
|
+ extractConfigRepo.save(extractConfig);
|
|
|
+ disposeNowPaper(extractConfig.getId());
|
|
|
+ return examPapers;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**先处理原来绑定的试卷
|
|
|
+ * @param extractConfigId
|
|
|
+ */
|
|
|
+ private void disposeOldPaper(String extractConfigId) {
|
|
|
+ ExtractConfig ec = Model.of(extractConfigRepo.findById(extractConfigId));
|
|
|
+ for (ExamPaper paper : ec.getExamPaperList()) {
|
|
|
+ if(inExam(paper.getPaper().getId())) {//如果有考试记录
|
|
|
+ updatePaperInUse(paper.getPaper().getId(), 1);
|
|
|
+ }else {
|
|
|
+ if(!inOtherExtractConfig(extractConfigId, paper.getPaper().getId())) {//没有考试记录且不被其他调卷规则引用
|
|
|
+ updatePaperInUse(paper.getPaper().getId(), 0);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ /**处理当前绑定试卷
|
|
|
+ * @param extractConfigId
|
|
|
+ */
|
|
|
+ private void disposeNowPaper(String extractConfigId) {
|
|
|
+ ExtractConfig ec = Model.of(extractConfigRepo.findById(extractConfigId));
|
|
|
+ for (ExamPaper paper : ec.getExamPaperList()) {
|
|
|
+ updatePaperInUse(paper.getPaper().getId(), 1);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private void updatePaperInUse(String paperId, int inUse) {
|
|
|
+ Query query = null;
|
|
|
+ if(paperId.length()==24) {
|
|
|
+ query = Query.query(Criteria.where("_id").is(new ObjectId(paperId)));
|
|
|
+ }else {
|
|
|
+ query = Query.query(Criteria.where("_id").is(paperId));
|
|
|
+ }
|
|
|
+ Update update = new Update();
|
|
|
+ update.set("inUse", inUse);
|
|
|
+ mongoTemplate.updateFirst(query, update, "paper");
|
|
|
+ }
|
|
|
+
|
|
|
+ private boolean inExam(String paperId) {
|
|
|
+ CheckPaperInExamReq req1 = new CheckPaperInExamReq();
|
|
|
+ req1.setBasePaperId(paperId);
|
|
|
+ CheckPaperInExamResp res1 = adminExamRecordCloudService.checkPaperInExam(req1);
|
|
|
+ if (res1.getInExam()) {
|
|
|
+ return res1.getInExam();
|
|
|
+ }
|
|
|
+ cn.com.qmth.examcloud.core.oe.student.api.request.CheckPaperInExamReq req2 = new cn.com.qmth.examcloud.core.oe.student.api.request.CheckPaperInExamReq();
|
|
|
+ req2.setBasePaperId(paperId);
|
|
|
+ cn.com.qmth.examcloud.core.oe.student.api.response.CheckPaperInExamResp res2 = studentExamRecordCloudService
|
|
|
+ .checkPaperInExam(req2);
|
|
|
+ return res2.getInExam();
|
|
|
+ }
|
|
|
+
|
|
|
+ private boolean inOtherExtractConfig(String extractConfigId, String paperId) {
|
|
|
+ Criteria criteria = new Criteria();
|
|
|
+ criteria.and("examPaperList").elemMatch(Criteria.where("paper.$id").is(new ObjectId(paperId)));
|
|
|
+ Query query = Query.query(criteria);
|
|
|
+ List<ExtractConfig> list = mongoTemplate.find(query, ExtractConfig.class, "extractConfig");
|
|
|
+ if (list == null || list.size() == 0) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ if (list.size() == 1 && list.get(0).getId().equals(extractConfigId)) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ private void checkOfflinePaper(Paper paper) {
|
|
|
+ List<PaperDetailUnit> pdus = paperDetailUnitRepo.findByPaper(paper);
|
|
|
+ if (pdus == null || pdus.size() == 0) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ for (PaperDetailUnit pdu : pdus) {
|
|
|
+ if (pdu.getQuestionType() == QuesStructType.SINGLE_ANSWER_QUESTION
|
|
|
+ || pdu.getQuestionType() == QuesStructType.MULTIPLE_ANSWER_QUESTION
|
|
|
+ || pdu.getQuestionType() == QuesStructType.BOOL_ANSWER_QUESTION) {
|
|
|
+ throw new StatusException("500", "试卷包含客观题,无法保存规则");
|
|
|
+ } else if (pdu.getQuestionType() == QuesStructType.NESTED_ANSWER_QUESTION
|
|
|
+ && !CollectionUtils.isEmpty(pdu.getQuestion().getSubQuestions())) {
|
|
|
+ for (Question q : pdu.getQuestion().getSubQuestions()) {
|
|
|
+ if (q.getQuestionType() == QuesStructType.SINGLE_ANSWER_QUESTION
|
|
|
+ || q.getQuestionType() == QuesStructType.MULTIPLE_ANSWER_QUESTION
|
|
|
+ || q.getQuestionType() == QuesStructType.BOOL_ANSWER_QUESTION) {
|
|
|
+ throw new StatusException("500", "试卷包含客观题,无法保存规则");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public ExtractConfig findConfigById(String id) {
|
|
|
+ if (StringUtils.isBlank(id)) {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ return Model.of(extractConfigRepo.findById(id));
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public Map<String, Object> extractExamPaper(Long exam_id, String course_code, String group_code) {
|
|
|
+ Map<String, Object> returnMap = new HashMap<>();
|
|
|
+ LOG.info("调卷开始...");
|
|
|
+ long beginTime = System.currentTimeMillis();
|
|
|
+ LOG.info("开始根据examId:" + exam_id + "和courseCode:" + course_code + "获取调卷规则");
|
|
|
+ ExtractConfig extractConfig = this.findConfig(new ExtractConfig(exam_id, course_code));
|
|
|
+ if (extractConfig == null) {
|
|
|
+ LOG.error("该考试和课程下调卷规则未制定,请先制定调卷规则,调卷程序退出");
|
|
|
+ returnMap.put("errorMsg", "该考试和课程下调卷规则未制定,请先制定调卷规则");
|
|
|
+ return returnMap;
|
|
|
+ }
|
|
|
+ long configFinishTime = System.currentTimeMillis();
|
|
|
+ LOG.info("获取调卷规则共耗时:" + (configFinishTime - beginTime) + "ms");
|
|
|
+ LOG.info("根据调卷规则中设置的概率获取类型为" + group_code + "的试卷");
|
|
|
+ Map<String, Paper> paperMap = this.getExamPaperByProbability(extractConfig.getExamPaperList());
|
|
|
+ if (paperMap.isEmpty()) {
|
|
|
+ LOG.error("该考试和课程下调卷规则中试卷不存在,请检查调卷规则,调卷程序退出");
|
|
|
+ returnMap.put("errorMsg", "该考试和课程下调卷规则中试卷不存在,请重新制定调卷规则");
|
|
|
+ return returnMap;
|
|
|
+ }
|
|
|
+
|
|
|
+ long paperMapFinishTime = System.currentTimeMillis();
|
|
|
+ LOG.info("获取类型为" + group_code + "的试卷共耗时:" + (paperMapFinishTime - configFinishTime) + "ms");
|
|
|
+
|
|
|
+ Paper basePaper = paperMap.get(group_code);
|
|
|
+ if (basePaper == null) {
|
|
|
+ LOG.error("该考试和课程下调卷规则中该类型试卷不存在,请检查调卷规则,调卷程序退出");
|
|
|
+ returnMap.put("errorMsg", "该考试和课程下调卷规则中该类型试卷不存在,请重新制定调卷规则");
|
|
|
+ return returnMap;
|
|
|
+ }
|
|
|
+ String basePaperId = basePaper.getId();
|
|
|
+ LOG.info("将原始试卷:" + basePaperId + "根据规则重新组卷");
|
|
|
+ int upSetQuestionOrder = extractConfig.getScrambling_the_question_order();
|
|
|
+ int upSetOptionOrder = extractConfig.getScrambling_the_option_order();
|
|
|
+ // 不乱序直接调卷
|
|
|
+ if (upSetQuestionOrder == 0 && upSetOptionOrder == 0) {
|
|
|
+ PaperDto paperDto = getPaperDtoByPaper(basePaper, basePaperId);
|
|
|
+ long paperDtoFinishTime = System.currentTimeMillis();
|
|
|
+ LOG.info("获取试卷Dto共耗时:" + (paperDtoFinishTime - paperMapFinishTime) + "ms");
|
|
|
+ returnMap.put("paperDto", paperDto);
|
|
|
+ LOG.info("调卷完成");
|
|
|
+ LOG.info("总共耗时:" + (System.currentTimeMillis() - beginTime) + "ms");
|
|
|
+ } else {
|
|
|
+ // 乱序重新生成试卷
|
|
|
+ Paper newPaper = this.recombinationPaper(basePaper, PaperType.STUDENT_EXAM, upSetQuestionOrder,
|
|
|
+ upSetOptionOrder);
|
|
|
+ LOG.info("根据新试卷 paperId:" + newPaper.getId() + "组装PaperDto后返回");
|
|
|
+
|
|
|
+ long genPaperFinishTime = System.currentTimeMillis();
|
|
|
+ LOG.info("组卷共耗时:" + (genPaperFinishTime - paperMapFinishTime) + "ms");
|
|
|
+ PaperDto paperDto = getPaperDtoByPaper(newPaper, basePaperId);
|
|
|
+
|
|
|
+ long paperDtoFinishTime = System.currentTimeMillis();
|
|
|
+ LOG.info("获取试卷Dto共耗时:" + (paperDtoFinishTime - genPaperFinishTime) + "ms");
|
|
|
+
|
|
|
+ returnMap.put("paperDto", paperDto);
|
|
|
+ LOG.info("调卷完成");
|
|
|
+ LOG.info("总共耗时:" + (System.currentTimeMillis() - beginTime) + "ms");
|
|
|
+ }
|
|
|
+ return returnMap;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public boolean checkIsAllQbjectiveQuestion(String paperId) {
|
|
|
+ // 优先从redis中获取缓存dto
|
|
|
+ PaperDto cachePaperDto = redisClient.get(CACHE_KEY_PAPER_FOR_DTO + paperId, PaperDto.class, DEFAULT_TIME_OUT);
|
|
|
+ if (cachePaperDto != null) {
|
|
|
+ return cachePaperDto.isAllQbjectiveQuestion();
|
|
|
+ }
|
|
|
+
|
|
|
+ Paper paper = Model.of(paperRepo.findById(paperId));
|
|
|
+ List<PaperDetailUnit> paperDetailUnits = paperDetailUnitRepo.findByPaperOrderByNumber(paper);
|
|
|
+ for (PaperDetailUnit paperDetailUnit : paperDetailUnits) {
|
|
|
+ Question question = paperDetailUnit.getQuestion();
|
|
|
+ // 填空或问答
|
|
|
+ if (question.getQuestionType() == QuesStructType.FILL_BLANK_QUESTION
|
|
|
+ || question.getQuestionType() == QuesStructType.TEXT_ANSWER_QUESTION) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ if (question.getQuestionType() == QuesStructType.NESTED_ANSWER_QUESTION) {
|
|
|
+ List<Question> subQuestions = question.getSubQuestions();
|
|
|
+ for (Question subQuestion : subQuestions) {
|
|
|
+ if (subQuestion.getQuestionType() == QuesStructType.FILL_BLANK_QUESTION
|
|
|
+ || subQuestion.getQuestionType() == QuesStructType.TEXT_ANSWER_QUESTION) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ public boolean checkIsAllQbjectiveByPdu(List<PaperDetailUnit> paperDetailUnits) {
|
|
|
+ for (PaperDetailUnit paperDetailUnit : paperDetailUnits) {
|
|
|
+ Question question = paperDetailUnit.getQuestion();
|
|
|
+ // 填空或问答
|
|
|
+ if (question.getQuestionType() == QuesStructType.FILL_BLANK_QUESTION
|
|
|
+ || question.getQuestionType() == QuesStructType.TEXT_ANSWER_QUESTION) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ if (question.getQuestionType() == QuesStructType.NESTED_ANSWER_QUESTION) {
|
|
|
+ List<Question> subQuestions = question.getSubQuestions();
|
|
|
+ for (Question subQuestion : subQuestions) {
|
|
|
+ if (subQuestion.getQuestionType() == QuesStructType.FILL_BLANK_QUESTION
|
|
|
+ || subQuestion.getQuestionType() == QuesStructType.TEXT_ANSWER_QUESTION) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public Map<String, String> makePaperByConfig(ExtractConfig extractConfig) {
|
|
|
+ Map<String, String> finishedPaperIdMap = new HashMap<>();
|
|
|
+ if (extractConfig == null) {
|
|
|
+ throw new RuntimeException("调卷规则不存在");
|
|
|
+ }
|
|
|
+ // 获得规则中设置的试卷
|
|
|
+ Map<String, Paper> paperMap = this.getExamPaperByProbability(extractConfig.getExamPaperList());
|
|
|
+ if (paperMap.isEmpty()) {
|
|
|
+ throw new RuntimeException("抽取试卷失败");
|
|
|
+ }
|
|
|
+ for (Map.Entry<String, Paper> entry : paperMap.entrySet()) {
|
|
|
+ String key = entry.getKey();
|
|
|
+ // 根据原有试卷重新组卷得到新试卷
|
|
|
+ /*
|
|
|
+ * Paper newPaper = this.recombinationPaper(entry.getValue(), PaperType.PREVIEW,
|
|
|
+ * extractConfig.getScrambling_the_question_order(),
|
|
|
+ * extractConfig.getScrambling_the_option_order());
|
|
|
+ */
|
|
|
+ finishedPaperIdMap.put(key, entry.getValue().getId());
|
|
|
+ }
|
|
|
+ return finishedPaperIdMap;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 重组试卷,生成新的试卷
|
|
|
+ *
|
|
|
+ * @param paper 选中的试卷
|
|
|
+ * @param upSetQuestionOrder 客观题小题乱序 1:乱序 0:不乱序
|
|
|
+ * @param upSetOptionOrder 客观题选项乱序 1:乱序 0:不乱序
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ public Paper recombinationPaper(Paper paper, PaperType paperType, int upSetQuestionOrder, int upSetOptionOrder) {
|
|
|
+
|
|
|
+ // 将小题全部取出来,只取一次
|
|
|
+ List<PaperDetailUnit> allPaperDetailUnits = paperDetailUnitRepo.findByPaperOrderByNumber(paper);
|
|
|
+ // 获取大题
|
|
|
+ List<PaperDetail> paperDetails = paperDetailRepo.findByPaperOrderByNumber(paper);
|
|
|
+
|
|
|
+ // 抽取大题号对应的小题
|
|
|
+ Map<String, List<PaperDetailUnit>> pduMap = allPaperDetailUnits.stream()
|
|
|
+ .collect(Collectors.groupingBy(PaperDetailUnit::getDetailId));
|
|
|
+ // 最终保存的所有小题
|
|
|
+ List<PaperDetailUnit> savePaperDetailUnits = new ArrayList<>();
|
|
|
+ // 保存试卷信息
|
|
|
+ paper.setId(null);
|
|
|
+ paper.setPaperType(paperType);
|
|
|
+ Paper newPaper = paperRepo.insert(paper);
|
|
|
+
|
|
|
+ for (int i = 0; i < paperDetails.size(); i++) {
|
|
|
+ PaperDetail paperDetail = paperDetails.get(i);
|
|
|
+
|
|
|
+ List<PaperDetailUnit> paperDetailUnits = pduMap.get(paperDetail.getId());
|
|
|
+ if (paperDetailUnits == null || paperDetailUnits.size() == 0) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ Collections.sort(paperDetailUnits);
|
|
|
+
|
|
|
+ // 将大题中最小的number取出
|
|
|
+ PaperDetailUnit topDetailUnit = paperDetailUnits.get(0);
|
|
|
+ int minNumber = topDetailUnit.getNumber();
|
|
|
+
|
|
|
+ // 小题乱序
|
|
|
+ if (paperDetailUnits != null && paperDetailUnits.size() > 0) {
|
|
|
+ if ((topDetailUnit.getQuestionType() == QuesStructType.SINGLE_ANSWER_QUESTION
|
|
|
+ || topDetailUnit.getQuestionType() == QuesStructType.MULTIPLE_ANSWER_QUESTION
|
|
|
+ || topDetailUnit.getQuestionType() == QuesStructType.BOOL_ANSWER_QUESTION)
|
|
|
+ && upSetQuestionOrder == 1) {
|
|
|
+ Collections.shuffle(paperDetailUnits);// 打乱小题List
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // 设置大题信息
|
|
|
+ paperDetail.setId(null);
|
|
|
+ paperDetail.setPaper(newPaper);
|
|
|
+
|
|
|
+ for (int j = 0; j < paperDetailUnits.size(); j++) {
|
|
|
+ // 重新设置保存PaperDetailUnit
|
|
|
+ PaperDetailUnit paperDetailUnit = paperDetailUnits.get(j);
|
|
|
+ paperDetailUnit.setPaperType(paperType);
|
|
|
+ paperDetailUnit.setPaper(newPaper);
|
|
|
+ paperDetailUnit.setPaperDetail(paperDetail);
|
|
|
+ paperDetailUnit.setNumber(minNumber + j); // 重新设置序号
|
|
|
+ reSavePaperDetailUtilAndQuestion(paperDetailUnit, upSetOptionOrder);
|
|
|
+ savePaperDetailUnits.add(paperDetailUnit);
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+ // 保存大题信息
|
|
|
+ paperDetailRepo.insert(paperDetails);
|
|
|
+ // 保存小题信息
|
|
|
+ paperDetailUnitRepo.insert(savePaperDetailUnits);
|
|
|
+
|
|
|
+ // 清空所有list
|
|
|
+ allPaperDetailUnits.clear();
|
|
|
+ savePaperDetailUnits.clear();
|
|
|
+ paperDetails.clear();
|
|
|
+
|
|
|
+ return newPaper;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 每个试卷类型取出一套试卷 { A:Paper, B:Paper } A是试卷类型 Paper是A类型下选定的试卷
|
|
|
+ *
|
|
|
+ * @param examPaperList
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ private Map<String, Paper> getExamPaperByProbability(List<ExamPaper> examPaperList) {
|
|
|
+ Map<String, Paper> paperByTypeMap = new HashMap<>();
|
|
|
+ if (examPaperList == null || examPaperList.size() == 0) {
|
|
|
+ throw new RuntimeException("可供抽取的试卷集合为空,无法抽取试卷");
|
|
|
+ }
|
|
|
+
|
|
|
+ Map<String, List<ExamPaper>> examPaperMap = new HashMap<>();
|
|
|
+ for (int i = 0; i < examPaperList.size(); i++) {
|
|
|
+ ExamPaper examPaper = examPaperList.get(i);
|
|
|
+ if (!examPaperMap.containsKey(examPaper.getGroupCode())) {
|
|
|
+ if (examPaper.getPaper() != null) {
|
|
|
+ List<ExamPaper> epList = new ArrayList<>();
|
|
|
+ epList.add(examPaper);
|
|
|
+ examPaperMap.put(examPaper.getGroupCode(), epList);
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ if (examPaper.getPaper() != null) {
|
|
|
+ List<ExamPaper> epList = examPaperMap.get(examPaper.getGroupCode());
|
|
|
+ epList.add(examPaper);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (examPaperMap != null) {
|
|
|
+ Set<String> keys = examPaperMap.keySet();
|
|
|
+ Iterator<String> it = keys.iterator();
|
|
|
+ while (it.hasNext()) {
|
|
|
+ String key = it.next();
|
|
|
+ Paper paper = this.getPaperByProbability(examPaperMap.get(key));
|
|
|
+
|
|
|
+ if (paper == null) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 不能用原来的paper对象,否则examPaperList中的paper对象会被覆盖
|
|
|
+ Paper newPaper = Model.of(paperRepo.findById(paper.getId()));
|
|
|
+ paperByTypeMap.put(key, newPaper);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return paperByTypeMap;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 根据设定几率取出一套试卷
|
|
|
+ *
|
|
|
+ * @param examPaperList
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ private Paper getPaperByProbability(List<ExamPaper> examPaperList) {
|
|
|
+ int sum = 0;
|
|
|
+ for (int i = 0; i < examPaperList.size(); i++) {
|
|
|
+ sum += examPaperList.get(i).getWeight();
|
|
|
+ }
|
|
|
+
|
|
|
+ // 从1开始
|
|
|
+ Integer rand = new Random().nextInt(sum) + 1;
|
|
|
+ for (int i = 0; i < examPaperList.size(); i++) {
|
|
|
+ rand -= examPaperList.get(i).getWeight();
|
|
|
+ // 选中
|
|
|
+ if (rand <= 0) {
|
|
|
+ return examPaperList.get(i).getPaper();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 重新设置并保存paperDetailUnit和question
|
|
|
+ *
|
|
|
+ * @param paperDetailUnit
|
|
|
+ * @param upSetOptionOrder
|
|
|
+ */
|
|
|
+ private void reSavePaperDetailUtilAndQuestion(PaperDetailUnit paperDetailUnit, Integer upSetOptionOrder) {
|
|
|
+ Question question = paperDetailUnit.getQuestion();
|
|
|
+ // 选项乱序
|
|
|
+ if (upSetOptionOrder == 1) {
|
|
|
+ // 单选或多选
|
|
|
+ if (question.getQuestionType() == QuesStructType.SINGLE_ANSWER_QUESTION
|
|
|
+ || question.getQuestionType() == QuesStructType.MULTIPLE_ANSWER_QUESTION) {
|
|
|
+ List<String> numberList = new ArrayList<>();
|
|
|
+ List<QuesOption> options = question.getQuesOptions();
|
|
|
+ for (int k = 0; k < options.size(); k++) {
|
|
|
+ QuesOption quesOption = options.get(k);
|
|
|
+ numberList.add(quesOption.getNumber());
|
|
|
+ }
|
|
|
+ Collections.shuffle(numberList); // 打乱number顺序
|
|
|
+ paperDetailUnit.setOptionOrder(StringUtils.join(numberList.toArray(), ","));// 设置option顺序
|
|
|
+ }
|
|
|
+ // 套题,套题下小题不乱序,选择题选项乱序
|
|
|
+ if (question.getQuestionType() == QuesStructType.NESTED_ANSWER_QUESTION) {
|
|
|
+ List<Question> subQuestions = question.getSubQuestions();
|
|
|
+ StringBuffer optionOrder = new StringBuffer();
|
|
|
+ for (int m = 0; m < subQuestions.size(); m++) {
|
|
|
+ Question subQuestion = subQuestions.get(m);
|
|
|
+ if (subQuestion.getQuestionType() == QuesStructType.SINGLE_ANSWER_QUESTION
|
|
|
+ || subQuestion.getQuestionType() == QuesStructType.MULTIPLE_ANSWER_QUESTION) {
|
|
|
+ List<String> numberList = new ArrayList<>();
|
|
|
+ List<QuesOption> options = subQuestion.getQuesOptions();
|
|
|
+ for (int n = 0; n < options.size(); n++) {
|
|
|
+ QuesOption quesOption = options.get(n);
|
|
|
+ numberList.add(quesOption.getNumber());
|
|
|
+ }
|
|
|
+ Collections.shuffle(numberList); // 打乱number顺序
|
|
|
+ optionOrder.append(StringUtils.join(numberList.toArray(), ",")).append(";");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ paperDetailUnit.setOptionOrder(optionOrder.toString()); // 设置option顺序
|
|
|
+ }
|
|
|
+ }
|
|
|
+ paperDetailUnit.setId(null);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public List<String> getExamPaperId(String courseCode, String orgId) {
|
|
|
+ Assert.hasLength(courseCode, "courseCode不能为空");
|
|
|
+ Assert.hasLength(orgId, "orgId不能为空");
|
|
|
+ List<String> paperIdList = new ArrayList<>();
|
|
|
+ Query query = new Query();
|
|
|
+ query.addCriteria(Criteria.where("courseCode").is(courseCode));
|
|
|
+ query.addCriteria(Criteria.where("orgId").is(orgId));
|
|
|
+ List<ExtractConfig> extractConfigList = this.mongoTemplate.find(query, ExtractConfig.class);
|
|
|
+ for (ExtractConfig extractConfig : extractConfigList) {
|
|
|
+ List<ExamPaper> examPaperList = extractConfig.getExamPaperList();
|
|
|
+ if (examPaperList != null && examPaperList.size() > 0) {
|
|
|
+ for (ExamPaper examPaper : examPaperList) {
|
|
|
+ paperIdList.add(examPaper.getPaper().getId());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return paperIdList;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 根据paper得到PaperDto
|
|
|
+ *
|
|
|
+ * @param paper
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ @SuppressWarnings("unchecked")
|
|
|
+ private PaperDto getPaperDtoByPaper(Paper paper, String basePaperId) {
|
|
|
+ long beginTime = System.currentTimeMillis();
|
|
|
+ // 没有则重新组装
|
|
|
+ PaperDto paperDto = paperDtoAssembler.toDto(paper);
|
|
|
+ paperDto.setBasePaperId(basePaperId);
|
|
|
+ paperDto.setAllQbjectiveQuestion(checkIsAllQbjectiveQuestion(basePaperId));
|
|
|
+
|
|
|
+ long paperDtoEndTime = System.currentTimeMillis();
|
|
|
+ LOG.info("单独组装paperDto耗时:" + (paperDtoEndTime - beginTime) + "ms");
|
|
|
+
|
|
|
+ // 将小题全部取出来,只取一次
|
|
|
+ List<PaperDetailUnit> allPaperDetailUnits = paperDetailUnitRepo.findByPaper(paper);
|
|
|
+ long pduEndTime = System.currentTimeMillis();
|
|
|
+ LOG.info("数据库取小题耗时:" + (pduEndTime - paperDtoEndTime) + "ms");
|
|
|
+ Collections.sort(allPaperDetailUnits);
|
|
|
+ long pduSortEndTime = System.currentTimeMillis();
|
|
|
+ LOG.info("排序小题耗时:" + (pduSortEndTime - pduEndTime) + "ms");
|
|
|
+
|
|
|
+ // 获取大题
|
|
|
+ List<PaperDetail> paperDetails = paperDetailRepo.findByPaper(paper);
|
|
|
+ long pdEndTime = System.currentTimeMillis();
|
|
|
+ LOG.info("数据库取大题耗时:" + (pdEndTime - pduSortEndTime) + "ms");
|
|
|
+ Collections.sort(paperDetails);
|
|
|
+ long pdSortEndTime = System.currentTimeMillis();
|
|
|
+ LOG.info("排序大题耗时:" + (pdSortEndTime - pdEndTime) + "ms");
|
|
|
+
|
|
|
+ // 抽取大题Id对应的小题
|
|
|
+ Map<String, List<PaperDetailUnit>> pduMap = allPaperDetailUnits.stream()
|
|
|
+ .collect(Collectors.groupingBy(PaperDetailUnit::getDetailId));
|
|
|
+ long pduMapEndTime = System.currentTimeMillis();
|
|
|
+ LOG.info("获取大题与小题对应关系耗时:" + (pduMapEndTime - pdSortEndTime) + "ms");
|
|
|
+
|
|
|
+ // 获取大题Dto
|
|
|
+ List<PaperDetailDto> paperDetailDtos = paperDetailDtoAssembler.toDtoList(paperDetails);
|
|
|
+ paperDto.setPaperDetails(paperDetailDtos);
|
|
|
+ long paperDetailDtoEndTime = System.currentTimeMillis();
|
|
|
+ LOG.info("单独组装paperDetailDto耗时:" + (paperDetailDtoEndTime - pduMapEndTime) + "ms");
|
|
|
+
|
|
|
+ // 封装小题
|
|
|
+ for (int i = 0; i < paperDetailDtos.size(); i++) {
|
|
|
+ // 根据大题查出大题下面的小题
|
|
|
+ PaperDetail paperDetail = paperDetails.get(i);
|
|
|
+
|
|
|
+ List<PaperDetailUnit> paperDetailUnits = pduMap.get(paperDetail.getId());
|
|
|
+
|
|
|
+ List<PaperDetailUnitDto> paperDetailUnitDtos = new ArrayList<>();
|
|
|
+ for (int j = 0; j < paperDetailUnits.size(); j++) {
|
|
|
+ PaperDetailUnit paperDetailUnit = paperDetailUnits.get(j);
|
|
|
+ if (paperDetailUnit == null || paperDetailUnit.getQuestion() == null) {
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ // 设置答案
|
|
|
+ setSelectQuestionAnswerUnit(paperDetailUnit);
|
|
|
+
|
|
|
+ PaperDetailUnitDto unitDto = paperDetailUnitDtoAssembler.toDto(paperDetailUnit);
|
|
|
+ /**
|
|
|
+ * 此处不能传questionId,需要传paperDetailUnitId 因为选项乱序在paperDetailUnit里
|
|
|
+ * unitDto.setQuesId(paperDetailUnit.getQuestion().getId());
|
|
|
+ */
|
|
|
+ unitDto.setQuesId(paperDetailUnit.getId());
|
|
|
+ String answer = paperDetailUnit.getQuestion().getQuesAnswer();
|
|
|
+ if (StringUtils.isNotEmpty(answer)) {
|
|
|
+ unitDto.setAnswer(answer);
|
|
|
+ }
|
|
|
+ if (unitDto.getQuestionType() == QuesStructType.NESTED_ANSWER_QUESTION) {// 假如是套题
|
|
|
+ List<Question> subQuesList = paperDetailUnit.getQuestion().getSubQuestions();
|
|
|
+ List<SubQuestionDto> subQuesDtos = subQuestionDtoAssembler.toDtoList(subQuesList);
|
|
|
+ for (int m = 0; m < subQuesList.size(); m++) {
|
|
|
+ List<QuesOptionDto> quesOptionDtos = subQuestionDtoAssembler
|
|
|
+ .toOptionDtoList(subQuesList.get(m).getQuesOptions());
|
|
|
+ subQuesDtos.get(m).setQuesOptions(quesOptionDtos);
|
|
|
+ if (StringUtils.isNotEmpty(subQuesList.get(m).getQuesAnswer())) {
|
|
|
+ subQuesDtos.get(m).setQuesAnswer(subQuesList.get(m).getQuesAnswer());
|
|
|
+ }
|
|
|
+ subQuesDtos.get(m).setNumber(m + 1);
|
|
|
+ // 套题分数从小题类中取值
|
|
|
+ subQuesDtos.get(m).setScore(paperDetailUnit.getSubScoreList().get(m));
|
|
|
+ }
|
|
|
+ unitDto.setSubQuestions(subQuesDtos);
|
|
|
+ }
|
|
|
+ paperDetailUnitDtos.add(unitDto);
|
|
|
+ }
|
|
|
+ paperDetailDtos.get(i).setPaperDetailUnits(paperDetailUnitDtos);
|
|
|
+ paperDetailDtos.get(i).setCnNum(CommonUtils.toCHNum(paperDetailDtos.get(i).getNumber()));
|
|
|
+ }
|
|
|
+ long paperDetailUnitDtoEndTime = System.currentTimeMillis();
|
|
|
+ LOG.info("单独组装paperDetailUnitDto耗时:" + (paperDetailUnitDtoEndTime - paperDetailDtoEndTime) + "ms");
|
|
|
+
|
|
|
+ // 将重新组装的dto放进缓存
|
|
|
+ redisClient.set(CACHE_KEY_PAPER_FOR_DTO + paperDto.getId(), paperDto, DEFAULT_TIME_OUT);
|
|
|
+ return paperDto;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 测试获取paperDto
|
|
|
+ *
|
|
|
+ * @param basePaperId
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ @Deprecated
|
|
|
+ public PaperDto getPaperDtoByPaperNew(String basePaperId) {
|
|
|
+
|
|
|
+ long beginTime = System.currentTimeMillis();
|
|
|
+ // 没有则重新组装
|
|
|
+ Paper paper = Model.of(paperRepo.findById(basePaperId));
|
|
|
+ PaperDto paperDto = paperDtoAssembler.toDto(paper);
|
|
|
+ paperDto.setBasePaperId(basePaperId);
|
|
|
+
|
|
|
+ long paperDtoEndTime = System.currentTimeMillis();
|
|
|
+ LOG.info("单独组装paperDto耗时:" + (paperDtoEndTime - beginTime) + "ms");
|
|
|
+
|
|
|
+ // 将小题全部取出来,只取一次
|
|
|
+ // List<PaperDetailUnit> allPaperDetailUnits =
|
|
|
+ // detailUnitNativeRepo.findByPaperId(paper.getId());
|
|
|
+ List<PaperDetailUnit> allPaperDetailUnits = new ArrayList<>();
|
|
|
+
|
|
|
+ long pduEndTime = System.currentTimeMillis();
|
|
|
+ LOG.info("数据库取小题耗时:" + (pduEndTime - paperDtoEndTime) + "ms");
|
|
|
+ Collections.sort(allPaperDetailUnits);
|
|
|
+ long pduSortEndTime = System.currentTimeMillis();
|
|
|
+ LOG.info("排序小题耗时:" + (pduSortEndTime - pduEndTime) + "ms");
|
|
|
+
|
|
|
+ paperDto.setAllQbjectiveQuestion(checkIsAllQbjectiveByPdu(allPaperDetailUnits));
|
|
|
+ long isAllObjEndtime = System.currentTimeMillis();
|
|
|
+ LOG.info("设置客观题耗时:" + (isAllObjEndtime - pduSortEndTime) + "ms");
|
|
|
+
|
|
|
+ // 获取大题
|
|
|
+ List<PaperDetail> paperDetails = paperDetailRepo.findByPaper(paper);
|
|
|
+ long pdEndTime = System.currentTimeMillis();
|
|
|
+ LOG.info("数据库取大题耗时:" + (pdEndTime - isAllObjEndtime) + "ms");
|
|
|
+ Collections.sort(paperDetails);
|
|
|
+ long pdSortEndTime = System.currentTimeMillis();
|
|
|
+ LOG.info("排序大题耗时:" + (pdSortEndTime - pdEndTime) + "ms");
|
|
|
+
|
|
|
+ // 抽取大题Id对应的小题
|
|
|
+ Map<String, List<PaperDetailUnit>> pduMap = allPaperDetailUnits.stream()
|
|
|
+ .collect(Collectors.groupingBy(PaperDetailUnit::getDetailId));
|
|
|
+ long pduMapEndTime = System.currentTimeMillis();
|
|
|
+ LOG.info("获取大题与小题对应关系耗时:" + (pduMapEndTime - pdSortEndTime) + "ms");
|
|
|
+
|
|
|
+ // 获取大题Dto
|
|
|
+ List<PaperDetailDto> paperDetailDtos = paperDetailDtoAssembler.toDtoList(paperDetails);
|
|
|
+ paperDto.setPaperDetails(paperDetailDtos);
|
|
|
+ long paperDetailDtoEndTime = System.currentTimeMillis();
|
|
|
+ LOG.info("单独组装paperDetailDto耗时:" + (paperDetailDtoEndTime - pduMapEndTime) + "ms");
|
|
|
+
|
|
|
+ // 封装小题
|
|
|
+ for (int i = 0; i < paperDetailDtos.size(); i++) {
|
|
|
+ // 根据大题查出大题下面的小题
|
|
|
+ PaperDetail paperDetail = paperDetails.get(i);
|
|
|
+
|
|
|
+ List<PaperDetailUnit> paperDetailUnits = pduMap.get(paperDetail.getId());
|
|
|
+
|
|
|
+ List<PaperDetailUnitDto> paperDetailUnitDtos = new ArrayList<>();
|
|
|
+ for (int j = 0; j < paperDetailUnits.size(); j++) {
|
|
|
+ PaperDetailUnit paperDetailUnit = paperDetailUnits.get(j);
|
|
|
+ if (paperDetailUnit == null || paperDetailUnit.getQuestion() == null) {
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ // 设置答案
|
|
|
+ setSelectQuestionAnswerUnit(paperDetailUnit);
|
|
|
+
|
|
|
+ PaperDetailUnitDto unitDto = paperDetailUnitDtoAssembler.toDto(paperDetailUnit);
|
|
|
+ /**
|
|
|
+ * 此处不能传questionId,需要传paperDetailUnitId 因为选项乱序在paperDetailUnit里
|
|
|
+ * unitDto.setQuesId(paperDetailUnit.getQuestion().getId());
|
|
|
+ */
|
|
|
+ unitDto.setQuesId(paperDetailUnit.getId());
|
|
|
+ String answer = paperDetailUnit.getQuestion().getQuesAnswer();
|
|
|
+ if (StringUtils.isNotEmpty(answer)) {
|
|
|
+ unitDto.setAnswer(answer);
|
|
|
+ }
|
|
|
+ if (unitDto.getQuestionType() == QuesStructType.NESTED_ANSWER_QUESTION) {// 假如是套题
|
|
|
+ List<Question> subQuesList = paperDetailUnit.getQuestion().getSubQuestions();
|
|
|
+ List<SubQuestionDto> subQuesDtos = subQuestionDtoAssembler.toDtoList(subQuesList);
|
|
|
+ for (int m = 0; m < subQuesList.size(); m++) {
|
|
|
+ List<QuesOptionDto> quesOptionDtos = subQuestionDtoAssembler
|
|
|
+ .toOptionDtoList(subQuesList.get(m).getQuesOptions());
|
|
|
+ subQuesDtos.get(m).setQuesOptions(quesOptionDtos);
|
|
|
+ if (StringUtils.isNotEmpty(subQuesList.get(m).getQuesAnswer())) {
|
|
|
+ subQuesDtos.get(m).setQuesAnswer(subQuesList.get(m).getQuesAnswer());
|
|
|
+ }
|
|
|
+ subQuesDtos.get(m).setNumber(m + 1);
|
|
|
+ // 套题分数从小题类中取值
|
|
|
+ subQuesDtos.get(m).setScore(paperDetailUnit.getSubScoreList().get(m));
|
|
|
+ }
|
|
|
+ unitDto.setSubQuestions(subQuesDtos);
|
|
|
+ }
|
|
|
+ paperDetailUnitDtos.add(unitDto);
|
|
|
+ }
|
|
|
+ paperDetailDtos.get(i).setPaperDetailUnits(paperDetailUnitDtos);
|
|
|
+ paperDetailDtos.get(i).setCnNum(CommonUtils.toCHNum(paperDetailDtos.get(i).getNumber()));
|
|
|
+ }
|
|
|
+ long paperDetailUnitDtoEndTime = System.currentTimeMillis();
|
|
|
+ LOG.info("单独组装paperDetailUnitDto耗时:" + (paperDetailUnitDtoEndTime - paperDetailDtoEndTime) + "ms");
|
|
|
+ return paperDto;
|
|
|
+ }
|
|
|
+
|
|
|
+ private void setSelectQuestoionAnswer(List<PaperDetailUnit> paperDetailUnits) {
|
|
|
+ for (PaperDetailUnit paperDetailUnit : paperDetailUnits) {
|
|
|
+ if (paperDetailUnit == null || paperDetailUnit.getQuestion() == null) {
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ String optionOrder = paperDetailUnit.getOptionOrder();
|
|
|
+ Question question = paperDetailUnit.getQuestion();
|
|
|
+ quesService.setSelectQuestionAnswer(question, optionOrder);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private void setSelectQuestionAnswerUnit(PaperDetailUnit paperDetailUnit) {
|
|
|
+ Question question = paperDetailUnit.getQuestion();
|
|
|
+ if (paperDetailUnit == null || question == null) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ String optionOrder = paperDetailUnit.getOptionOrder();
|
|
|
+ quesService.setSelectQuestionAnswer(question, optionOrder);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 根据paperDetailUnitId抽取单个试题 根据paperDetailUnitId中设置的option顺序对option排序
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ public QuestionDto extractExamQuestion(String examId, String courseCode, String groupCode,
|
|
|
+ String paperDetailUnitId) {
|
|
|
+ PaperDetailUnit paperDetailUnit = Model.of(paperDetailUnitRepo.findById(paperDetailUnitId));
|
|
|
+ List<PaperDetailUnit> paperDetailUnits = new ArrayList<>();
|
|
|
+ paperDetailUnits.add(paperDetailUnit);
|
|
|
+ // 设置答案
|
|
|
+ setSelectQuestoionAnswer(paperDetailUnits);
|
|
|
+ // 重新对选择题option进行排序(多选、单选、套题下选择题)
|
|
|
+ reorderChoicequestionOption(paperDetailUnit);
|
|
|
+ Question ques = paperDetailUnit.getQuestion();
|
|
|
+ quesService.formatQues(ques);
|
|
|
+ QuestionDto dto = BeanCopierUtil.copyProperties(ques, QuestionDto.class);
|
|
|
+ dto.setScore(paperDetailUnit.getScore());
|
|
|
+ dto.setQuesOptions(buildQuestionOptionDto(ques.getQuesOptions()));
|
|
|
+ if (ques.getQuestionType() == QuesStructType.NESTED_ANSWER_QUESTION) {
|
|
|
+ List<Question> subQuesList = ques.getSubQuestions();
|
|
|
+ List<SubQuestionDto> subQuesDtos = new ArrayList<>();
|
|
|
+ for (Question question : subQuesList) {
|
|
|
+ SubQuestionDto subQuestionDto = new SubQuestionDto();
|
|
|
+ BeanUtils.copyProperties(question, subQuestionDto);
|
|
|
+ subQuesDtos.add(subQuestionDto);
|
|
|
+ }
|
|
|
+ for (int m = 0; m < subQuesList.size(); m++) {
|
|
|
+ List<QuesOptionDto> quesOptionDtos = BeanCopierUtil
|
|
|
+ .copyPropertiesOfList(subQuesList.get(m).getQuesOptions(), QuesOptionDto.class);
|
|
|
+ subQuesDtos.get(m).setQuesOptions(quesOptionDtos);
|
|
|
+ subQuesDtos.get(m).setQuesAnswer(subQuesList.get(m).getQuesAnswer());
|
|
|
+ subQuesDtos.get(m).setNumber(m + 1);
|
|
|
+ // 套题分数从小题类中取值
|
|
|
+ subQuesDtos.get(m).setScore(paperDetailUnit.getSubScoreList().get(m));
|
|
|
+ dto.setSubQuestions(subQuesDtos);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (ques.getQuestionType() == QuesStructType.SINGLE_ANSWER_QUESTION
|
|
|
+ || ques.getQuestionType() == QuesStructType.MULTIPLE_ANSWER_QUESTION) {
|
|
|
+ dto.setQuesAnswer(ques.getQuesAnswer());
|
|
|
+ }
|
|
|
+ appendAudioFlag(dto, examId, courseCode, groupCode);
|
|
|
+ return dto;
|
|
|
+ }
|
|
|
+
|
|
|
+ private List<QuesOptionDto> buildQuestionOptionDto(List<QuesOption> quesOptions) {
|
|
|
+ if (quesOptions == null) {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ List<QuesOptionDto> optionDtos = new ArrayList<>();
|
|
|
+ for (QuesOption option : quesOptions) {
|
|
|
+ QuesOptionDto optionDto = new QuesOptionDto();
|
|
|
+ optionDto.setNumber(option.getNumber());
|
|
|
+ optionDto.setOptionBody(option.getOptionBody());
|
|
|
+ optionDtos.add(optionDto);
|
|
|
+ }
|
|
|
+ return optionDtos;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 1.给QuestionDto添加音频播放次数 2.给试题音频中有a标签添加url
|
|
|
+ *
|
|
|
+ * @param questionDto
|
|
|
+ */
|
|
|
+ private void appendAudioFlag(QuestionDto questionDto, String examId, String courseCode, String groupCode) {
|
|
|
+ if (questionDto.getHasAudio() != null && questionDto.getHasAudio() == true) {
|
|
|
+ // 1.判断questionDto是否含有音频,如果有添加音频播放次数
|
|
|
+ AudioTimeConfig audioTimeConfig = Model.of(audioTimeConfigRepo
|
|
|
+ .findOne(Example.of(new AudioTimeConfig(examId, courseCode, groupCode, questionDto.getId()))));
|
|
|
+ questionDto.setPlayTime(audioTimeConfig != null ? audioTimeConfig.getPlayTime() : null);
|
|
|
+ // 2.1 取到题干,给a标签添加url
|
|
|
+ String quesBody = questionDto.getQuesBody();
|
|
|
+ questionDto.setQuesBody(buildBody(quesBody, questionDto));
|
|
|
+ // 2.2取到选项,给a标签添加url
|
|
|
+ List<QuesOptionDto> quesOptionDtoList = questionDto.getQuesOptions();
|
|
|
+ if (quesOptionDtoList != null && quesOptionDtoList.size() > 0) {
|
|
|
+ for (QuesOptionDto quesOptionDto : quesOptionDtoList) {
|
|
|
+ quesOptionDto.setOptionBody(buildBody(quesOptionDto.getOptionBody(), questionDto));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ questionDto.setPlayTime(null);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 给题目和选项添加url
|
|
|
+ public String buildBody(String body, QuestionDto questionDto) {
|
|
|
+ String[] bodyStrings = body.split("></a>");
|
|
|
+ if (bodyStrings.length > 1) {
|
|
|
+ String resultBody = "";
|
|
|
+ for (int i = 0; i < bodyStrings.length; i++) {
|
|
|
+ String containAStr = bodyStrings[i];
|
|
|
+ if (containAStr.indexOf("<a") > -1) {
|
|
|
+ String questionAudioId = matchAudioName(containAStr, "a", "id");
|
|
|
+ QuestionAudio questionAudio = questionAudioService.findAudioById(questionAudioId);
|
|
|
+ if (questionAudio != null) {
|
|
|
// String url = sysProperty.getDomain() + questionAudio.getFileUrl();
|
|
|
- //通用存储
|
|
|
- String url = FileStorageUtil.realPath(questionAudio.getFileUrl());
|
|
|
- if (questionDto.getPlayTime() != null) {
|
|
|
- containAStr += " question-audio url=\"" + url + "\" playTime=\"" + questionDto.getPlayTime() + "\"" + "></a>";
|
|
|
- } else {
|
|
|
- containAStr += " question-audio url=\"" + url + "\"" + "></a>";
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- resultBody += containAStr;
|
|
|
- }
|
|
|
- return resultBody;
|
|
|
- } else {
|
|
|
- return body;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- private String matchAudioName(String source, String element, String attr) {
|
|
|
- String reg = "<" + element + "[^<>]*?\\s" + attr + "=['\"]?(.*?)['\"]?(\\s.*?)";
|
|
|
- Matcher m = Pattern.compile(reg).matcher(source);
|
|
|
- if (m.find()) {
|
|
|
- return m.group(1);
|
|
|
- }
|
|
|
- return "";
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 重新对选择题option进行排序(多选、单选、套题下选择题)
|
|
|
- */
|
|
|
- private void reorderChoicequestionOption(PaperDetailUnit paperDetailUnit) {
|
|
|
- String optionOrder = paperDetailUnit.getOptionOrder();
|
|
|
- if (StringUtil.isNotBlank(optionOrder)) {
|
|
|
- Question question = paperDetailUnit.getQuestion();
|
|
|
- if (question.getQuestionType() == QuesStructType.SINGLE_ANSWER_QUESTION
|
|
|
- || question.getQuestionType() == QuesStructType.MULTIPLE_ANSWER_QUESTION) {
|
|
|
- question.setQuesOptions(reorderOptionCore(question.getQuesOptions(), optionOrder));
|
|
|
- }
|
|
|
- if (question.getQuestionType() == QuesStructType.NESTED_ANSWER_QUESTION) {
|
|
|
- List<Question> subQuestions = question.getSubQuestions();
|
|
|
- int index = 0;
|
|
|
- for (int k = 0; k < subQuestions.size(); k++) {
|
|
|
- Question subQuestion = subQuestions.get(k);
|
|
|
- if (subQuestion.getQuestionType() == QuesStructType.SINGLE_ANSWER_QUESTION
|
|
|
- || subQuestion.getQuestionType() == QuesStructType.MULTIPLE_ANSWER_QUESTION) {
|
|
|
- subQuestion.setQuesOptions(reorderOptionCore(subQuestion.getQuesOptions(), optionOrder.split(";")[index]));
|
|
|
- index++;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 对option排序
|
|
|
- *
|
|
|
- * @param quesOptions
|
|
|
- * @param optionOrder
|
|
|
- * @return
|
|
|
- */
|
|
|
- private List<QuesOption> reorderOptionCore(List<QuesOption> quesOptions, String optionOrder) {
|
|
|
- List<QuesOption> newQuesOptions = new ArrayList<>();
|
|
|
- if (StringUtil.isBlank(optionOrder) || quesOptions.isEmpty()) {
|
|
|
- return null;
|
|
|
- }
|
|
|
- String[] optionOrderArr = optionOrder.split(",");
|
|
|
- for (int j = 0; j < optionOrderArr.length; j++) {
|
|
|
- for (int k = 0; k < quesOptions.size(); k++) {
|
|
|
- if (optionOrderArr[j].equals(quesOptions.get(k).getNumber())) {
|
|
|
- newQuesOptions.add(quesOptions.get(k));
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- quesOptions = null;
|
|
|
- return newQuesOptions;
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public Page<ExtractConfig> findPageExtractConfig(int currentPage, int pageSize, Long examId, String courseCode, String orgId) {
|
|
|
- if (examId == null) {
|
|
|
- throw new StatusException("Q-", "examId is null");
|
|
|
- }
|
|
|
- Query query = new Query();
|
|
|
- query.addCriteria(Criteria.where("orgId").is(orgId));
|
|
|
- query.addCriteria(Criteria.where("examId").is(examId));
|
|
|
- query.addCriteria(Criteria.where("course.enable").is("true"));
|
|
|
- if (!StringUtils.isBlank(courseCode)) {
|
|
|
- query.addCriteria(Criteria.where("course.code").is(courseCode));
|
|
|
- }
|
|
|
-
|
|
|
- long count = this.mongoTemplate.count(query, ExtractConfig.class);
|
|
|
- query.limit(pageSize);
|
|
|
- query.skip((currentPage - 1L) * pageSize);
|
|
|
-
|
|
|
- List<ExtractConfig> extractConfigList = this.mongoTemplate.find(query, ExtractConfig.class);
|
|
|
- if (extractConfigList != null && extractConfigList.size() > 0) {
|
|
|
- //调用考务rmi,获取考试信息
|
|
|
- GetExamReq req = new GetExamReq();
|
|
|
- req.setId(examId);
|
|
|
- req.setRootOrgId(Long.valueOf(orgId));
|
|
|
- GetExamResp resp = examCloudService.getExam(req);
|
|
|
- ExamBean bean = resp.getExamBean();
|
|
|
- for (ExtractConfig extractConfig : extractConfigList) {
|
|
|
- extractConfig.setExamType(bean.getExamType());
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- return new PageImpl<>(extractConfigList, PageRequest.of(currentPage - 1, pageSize), count);
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public Map<String, Object> extractPaper(String paperId) {
|
|
|
- Map<String, Object> returnMap = new HashMap<>();
|
|
|
- Paper paper = Model.of(paperRepo.findById(paperId));
|
|
|
- if (paper == null) {
|
|
|
- returnMap.put("errorMsg", "该试卷不存在");
|
|
|
- return returnMap;
|
|
|
- }
|
|
|
- PaperDto paperDto = getPaperDtoByPaper(paper, paperId);
|
|
|
- returnMap.put("paperDto", paperDto);
|
|
|
- return returnMap;
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public String getAnswerHtml(String paperId) {
|
|
|
- //1.根据id查询试卷
|
|
|
- Paper paper = Model.of(paperRepo.findById(paperId));
|
|
|
- //2.定义html字符串
|
|
|
- StringBuffer answerHtml = new StringBuffer("<p style=\"text-align:center;font-size:20px;font-weight:bold\">" + paper.getCourse().getName() + "(" + paper.getCourse().getCode() + ")" + "</p>");
|
|
|
- //添加考试说明
|
|
|
- if (paper.getExamRemark() == null) {
|
|
|
- answerHtml.append("<p>考试说明:</p>");
|
|
|
- } else {
|
|
|
- answerHtml.append("<p>考试说明:</p>" + paper.getExamRemark());
|
|
|
- }
|
|
|
- //3.通过试卷获取考试端试卷结构
|
|
|
- PaperDto paperDto = getPaperDtoByPaper(paper, paper.getId());
|
|
|
- //4.获取试卷所有大题,并且循环
|
|
|
- List<PaperDetailDto> paperDetailDtos = paperDto.getPaperDetails();
|
|
|
- for (PaperDetailDto paperDetailDto : paperDetailDtos) {
|
|
|
- String title = "<p>" + paperDetailDto.getCnNum() + "、" + paperDetailDto.getName() + "(共" + paperDetailDto.getScore() + "分)" + "</p>";
|
|
|
- answerHtml.append(title);
|
|
|
- //5.获取大题下面的小题,并循环
|
|
|
- List<PaperDetailUnitDto> paperDetailUnitDtos = paperDetailDto.getPaperDetailUnits();
|
|
|
- for (PaperDetailUnitDto paperDetailUnitDto : paperDetailUnitDtos) {
|
|
|
- //定义题干
|
|
|
- String body = paperDetailUnitDto.getQuesBody().replaceAll("<span>", "").replaceAll("</span>", "").replaceAll("###", "___");
|
|
|
- ;
|
|
|
- //定义选项
|
|
|
- String option = "";
|
|
|
- //定义答案
|
|
|
- String answer = "";
|
|
|
- //6.如果为单选和多选
|
|
|
- if (paperDetailUnitDto.getQuestionType() == QuesStructType.SINGLE_ANSWER_QUESTION || paperDetailUnitDto.getQuestionType() == QuesStructType.MULTIPLE_ANSWER_QUESTION) {
|
|
|
- //获取选项
|
|
|
- List<QuesOptionDto> quesOptionDtos = paperDetailUnitDto.getQuesOptions();
|
|
|
- //添加题干
|
|
|
- body = startWithP(body, paperDetailUnitDto.getNumber(), false);
|
|
|
- answerHtml.append(body);
|
|
|
- //添加选项
|
|
|
- for (QuesOptionDto quesOptionDto : quesOptionDtos) {
|
|
|
- option = startWithP(quesOptionDto.getOptionBody(), Integer.parseInt(quesOptionDto.getNumber()), true);
|
|
|
- answerHtml.append(option);
|
|
|
- }
|
|
|
- answer = startWithP(paperDetailUnitDto.getAnswer(), -1, false);
|
|
|
- answerHtml.append(answer);
|
|
|
- }
|
|
|
- //7.如果为套题
|
|
|
- else if (paperDetailUnitDto.getSubQuestions() != null && paperDetailUnitDto.getSubQuestions().size() > 0) {
|
|
|
- //添加主题干
|
|
|
- String bigBody = CommonUtils.relaceQuestionIdx(paperDetailUnitDto.getQuesBody(), 0);
|
|
|
- bigBody = bigBody.replaceAll("<span>", "").replaceAll("</span>", "").replaceAll("###", "___");
|
|
|
- bigBody = startWithP(bigBody, -2, false);
|
|
|
- answerHtml.append(bigBody);
|
|
|
- List<SubQuestionDto> subQuestionDtos = paperDetailUnitDto.getSubQuestions();
|
|
|
- for (SubQuestionDto subQuestionDto : subQuestionDtos) {
|
|
|
- body = subQuestionDto.getQuesBody().replaceAll("<span>", "").replaceAll("</span>", "").replaceAll("###", "___");
|
|
|
- //如果子题为单选或者多选
|
|
|
- if (subQuestionDto.getQuestionType() == QuesStructType.SINGLE_ANSWER_QUESTION || subQuestionDto.getQuestionType() == QuesStructType.MULTIPLE_ANSWER_QUESTION) {
|
|
|
- //获取选项
|
|
|
- List<QuesOptionDto> quesOptionDtos = subQuestionDto.getQuesOptions();
|
|
|
- //添加题干
|
|
|
- body = startWithP(body, subQuestionDto.getNumber(), false);
|
|
|
- answerHtml.append(body);
|
|
|
- //添加选项
|
|
|
- for (QuesOptionDto quesOptionDto : quesOptionDtos) {
|
|
|
- option = startWithP(quesOptionDto.getOptionBody(), Integer.parseInt(quesOptionDto.getNumber()), true);
|
|
|
- answerHtml.append(option);
|
|
|
- }
|
|
|
- answer = startWithP(subQuestionDto.getQuesAnswer(), -1, false);
|
|
|
- answerHtml.append(answer);
|
|
|
- } else {
|
|
|
- //添加题干
|
|
|
- body = startWithP(body, subQuestionDto.getNumber(), false);
|
|
|
- answerHtml.append(body);
|
|
|
- //添加答案
|
|
|
- answer = startWithP(subQuestionDto.getQuesAnswer(), -1, false);
|
|
|
- answerHtml.append(answer);
|
|
|
- }
|
|
|
- }
|
|
|
- } else {
|
|
|
- //添加题干
|
|
|
- body = startWithP(body, paperDetailUnitDto.getNumber(), false);
|
|
|
- answerHtml.append(body);
|
|
|
- //添加答案
|
|
|
- answer = startWithP(paperDetailUnitDto.getAnswer(), -1, false);
|
|
|
- answerHtml.append(answer);
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- return answerHtml.toString();
|
|
|
- }
|
|
|
-
|
|
|
- public String startWithP(String s, Integer number, boolean option) {
|
|
|
- if (s == null) {
|
|
|
- s = "<p></p>";
|
|
|
- }
|
|
|
- if (number == -2) {
|
|
|
- if (s.startsWith("<p>")) {
|
|
|
- s = s.replaceAll("<p>", "<p style=\"margin-left:40px;\">").replaceAll("<p style=\"margin-left:40px;\">", "<p style=\"margin-left:20px;\">");
|
|
|
- } else {
|
|
|
- s = "<p style=\"margin-left:20px;color:red;\">" + s + "</p>";
|
|
|
- }
|
|
|
- } else if (number == -1) {
|
|
|
- if (s.startsWith("<p>")) {
|
|
|
- s = s.replaceAll("<p>", "<p style=\"margin-left:65px;\">").replaceFirst("<p style=\"margin-left:65px;\">", "<p style=\"margin-left:20px;color:red;\">" + "答案:").replace("<p style=\"margin-left:65px;\">", "<p style=\"margin-left:65px;color:red;\">");
|
|
|
- } else {
|
|
|
- s = "<p style=\"margin-left:20px;color:red;\">" + "答案:" + s + "</p>";
|
|
|
- }
|
|
|
- } else {
|
|
|
- if (option) {
|
|
|
- if (s.startsWith("<p>")) {
|
|
|
- s = s.replaceAll("<p>", "<p style=\"margin-left:40px;\">").replaceFirst("<p style=\"margin-left:40px;\">", "<p style=\"margin-left:20px;\">" + CommonUtils.getOptionNum(number - 1) + ".");
|
|
|
- } else {
|
|
|
- s = "<p style=\"margin-left:20px;\">" + CommonUtils.getOptionNum(number - 1) + "." + s + "</p>";
|
|
|
- }
|
|
|
- } else {
|
|
|
- if (s.startsWith("<p>")) {
|
|
|
- s = s.replaceAll("<p>", "<p style=\"margin-left:40px;\">").replaceFirst("<p style=\"margin-left:40px;\">", "<p style=\"margin-left:20px;\">" + number + ".");
|
|
|
- } else {
|
|
|
- s = "<p style=\"margin-left:20px;\">" + number + "." + s + "</p>";
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- return s;
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- @Override
|
|
|
- public List<CouresInfo> findCourseByExtractConfig(Long examId, String orgId) {
|
|
|
- if (examId == null) {
|
|
|
- throw new StatusException("Q-", "examId is null");
|
|
|
- }
|
|
|
- //从考务查询改考试下的所有开启课程
|
|
|
- List<CouresInfo> courseInfoList = new ArrayList<>();
|
|
|
- GetExamCourseListReq req = new GetExamCourseListReq();
|
|
|
- req.setExamId(examId);
|
|
|
- req.setCourseEnable(true);
|
|
|
- Long start = 1l;
|
|
|
- int count = 0;
|
|
|
- while (true) {
|
|
|
- req.setStart(start);
|
|
|
- GetExamCourseListResp resp = examCloudService.getExamCourseList(req);
|
|
|
- for (ExamCourseRelationBean bean : resp.getRelationList()) {
|
|
|
- CouresInfo info = new CouresInfo(bean);
|
|
|
- courseInfoList.add(info);
|
|
|
- }
|
|
|
- if (start.equals(resp.getNext())) {
|
|
|
- break;
|
|
|
- } else {
|
|
|
- start = resp.getNext();
|
|
|
- }
|
|
|
- count++;
|
|
|
- if (count > 1000) {
|
|
|
- throw new StatusException("Q-", "考试下课程的数据量过大");
|
|
|
- }
|
|
|
- }
|
|
|
- if (CollectionUtils.isEmpty(courseInfoList)) {
|
|
|
- return null;
|
|
|
- }
|
|
|
- //查询已经改考试下已经制定的课程的调卷规则
|
|
|
- Query query = new Query();
|
|
|
- query.addCriteria(Criteria.where("orgId").is(orgId));
|
|
|
- query.addCriteria(Criteria.where("examId").is(examId));
|
|
|
- List<ExtractConfig> extractConfigList = this.mongoTemplate.find(query, ExtractConfig.class);
|
|
|
- if (extractConfigList != null && extractConfigList.size() > 0) {
|
|
|
- for (ExtractConfig extractConfig : extractConfigList) {
|
|
|
- CouresInfo info = new CouresInfo();
|
|
|
- info.setCourseCode(extractConfig.getCourseCode());
|
|
|
- if (courseInfoList.contains(info)) {
|
|
|
- courseInfoList.remove(info);
|
|
|
- }
|
|
|
- }
|
|
|
- return courseInfoList;
|
|
|
- }
|
|
|
- return courseInfoList;
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public List<ExtractConfig> findExtractConfig(Long examId) {
|
|
|
- if (examId == null) {
|
|
|
- throw new StatusException("1001", "examId is null");
|
|
|
- }
|
|
|
- Query query = new Query();
|
|
|
- query.addCriteria(Criteria.where("examId").is(examId));
|
|
|
- query.addCriteria(Criteria.where("course.enable").is("true"));
|
|
|
-
|
|
|
- List<ExtractConfig> extractConfigList = this.mongoTemplate.find(query, ExtractConfig.class);
|
|
|
-
|
|
|
- return extractConfigList;
|
|
|
- }
|
|
|
+ // 通用存储
|
|
|
+ String url = FileStorageUtil.realPath(questionAudio.getFileUrl());
|
|
|
+ if (questionDto.getPlayTime() != null) {
|
|
|
+ containAStr += " question-audio url=\"" + url + "\" playTime=\"" + questionDto.getPlayTime()
|
|
|
+ + "\"" + "></a>";
|
|
|
+ } else {
|
|
|
+ containAStr += " question-audio url=\"" + url + "\"" + "></a>";
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ resultBody += containAStr;
|
|
|
+ }
|
|
|
+ return resultBody;
|
|
|
+ } else {
|
|
|
+ return body;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private String matchAudioName(String source, String element, String attr) {
|
|
|
+ String reg = "<" + element + "[^<>]*?\\s" + attr + "=['\"]?(.*?)['\"]?(\\s.*?)";
|
|
|
+ Matcher m = Pattern.compile(reg).matcher(source);
|
|
|
+ if (m.find()) {
|
|
|
+ return m.group(1);
|
|
|
+ }
|
|
|
+ return "";
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 重新对选择题option进行排序(多选、单选、套题下选择题)
|
|
|
+ */
|
|
|
+ private void reorderChoicequestionOption(PaperDetailUnit paperDetailUnit) {
|
|
|
+ String optionOrder = paperDetailUnit.getOptionOrder();
|
|
|
+ if (StringUtil.isNotBlank(optionOrder)) {
|
|
|
+ Question question = paperDetailUnit.getQuestion();
|
|
|
+ if (question.getQuestionType() == QuesStructType.SINGLE_ANSWER_QUESTION
|
|
|
+ || question.getQuestionType() == QuesStructType.MULTIPLE_ANSWER_QUESTION) {
|
|
|
+ question.setQuesOptions(reorderOptionCore(question.getQuesOptions(), optionOrder));
|
|
|
+ }
|
|
|
+ if (question.getQuestionType() == QuesStructType.NESTED_ANSWER_QUESTION) {
|
|
|
+ List<Question> subQuestions = question.getSubQuestions();
|
|
|
+ int index = 0;
|
|
|
+ for (int k = 0; k < subQuestions.size(); k++) {
|
|
|
+ Question subQuestion = subQuestions.get(k);
|
|
|
+ if (subQuestion.getQuestionType() == QuesStructType.SINGLE_ANSWER_QUESTION
|
|
|
+ || subQuestion.getQuestionType() == QuesStructType.MULTIPLE_ANSWER_QUESTION) {
|
|
|
+ subQuestion.setQuesOptions(
|
|
|
+ reorderOptionCore(subQuestion.getQuesOptions(), optionOrder.split(";")[index]));
|
|
|
+ index++;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 对option排序
|
|
|
+ *
|
|
|
+ * @param quesOptions
|
|
|
+ * @param optionOrder
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ private List<QuesOption> reorderOptionCore(List<QuesOption> quesOptions, String optionOrder) {
|
|
|
+ List<QuesOption> newQuesOptions = new ArrayList<>();
|
|
|
+ if (StringUtil.isBlank(optionOrder) || quesOptions.isEmpty()) {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ String[] optionOrderArr = optionOrder.split(",");
|
|
|
+ for (int j = 0; j < optionOrderArr.length; j++) {
|
|
|
+ for (int k = 0; k < quesOptions.size(); k++) {
|
|
|
+ if (optionOrderArr[j].equals(quesOptions.get(k).getNumber())) {
|
|
|
+ newQuesOptions.add(quesOptions.get(k));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ quesOptions = null;
|
|
|
+ return newQuesOptions;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public Page<ExtractConfig> findPageExtractConfig(int currentPage, int pageSize, Long examId, String courseCode,
|
|
|
+ String orgId, UserDataRule ud) {
|
|
|
+ if (ud.assertEmptyQueryResult()) {
|
|
|
+ return Page.empty();
|
|
|
+ }
|
|
|
+ if (examId == null) {
|
|
|
+ throw new StatusException("Q-", "examId is null");
|
|
|
+ }
|
|
|
+ Query query = new Query();
|
|
|
+ query.addCriteria(Criteria.where("orgId").is(orgId));
|
|
|
+ if (ud.assertNeedQueryRefIds()) {
|
|
|
+ query.addCriteria(Criteria.where("course.id").in(ud.stringRefIds()));
|
|
|
+ }
|
|
|
+ query.addCriteria(Criteria.where("examId").is(examId));
|
|
|
+ query.addCriteria(Criteria.where("course.enable").is("true"));
|
|
|
+ if (!StringUtils.isBlank(courseCode)) {
|
|
|
+ query.addCriteria(Criteria.where("course.code").is(courseCode));
|
|
|
+ }
|
|
|
+
|
|
|
+ long count = this.mongoTemplate.count(query, ExtractConfig.class);
|
|
|
+ query.limit(pageSize);
|
|
|
+ query.skip((currentPage - 1L) * pageSize);
|
|
|
+
|
|
|
+ List<ExtractConfig> extractConfigList = this.mongoTemplate.find(query, ExtractConfig.class);
|
|
|
+ if (extractConfigList != null && extractConfigList.size() > 0) {
|
|
|
+ // 调用考务rmi,获取考试信息
|
|
|
+ GetExamReq req = new GetExamReq();
|
|
|
+ req.setId(examId);
|
|
|
+ req.setRootOrgId(Long.valueOf(orgId));
|
|
|
+ GetExamResp resp = examCloudService.getExam(req);
|
|
|
+ ExamBean bean = resp.getExamBean();
|
|
|
+ for (ExtractConfig extractConfig : extractConfigList) {
|
|
|
+ extractConfig.setExamType(bean.getExamType());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return new PageImpl<>(extractConfigList, PageRequest.of(currentPage - 1, pageSize), count);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public Map<String, Object> extractPaper(String paperId) {
|
|
|
+ Map<String, Object> returnMap = new HashMap<>();
|
|
|
+ Paper paper = Model.of(paperRepo.findById(paperId));
|
|
|
+ if (paper == null) {
|
|
|
+ returnMap.put("errorMsg", "该试卷不存在");
|
|
|
+ return returnMap;
|
|
|
+ }
|
|
|
+ PaperDto paperDto = getPaperDtoByPaper(paper, paperId);
|
|
|
+ returnMap.put("paperDto", paperDto);
|
|
|
+ return returnMap;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public String getAnswerHtml(String paperId) {
|
|
|
+ // 1.根据id查询试卷
|
|
|
+ Paper paper = Model.of(paperRepo.findById(paperId));
|
|
|
+ // 2.定义html字符串
|
|
|
+ StringBuffer answerHtml = new StringBuffer("<p style=\"text-align:center;font-size:20px;font-weight:bold\">"
|
|
|
+ + paper.getCourse().getName() + "(" + paper.getCourse().getCode() + ")" + "</p>");
|
|
|
+ // 添加考试说明
|
|
|
+ if (paper.getExamRemark() == null) {
|
|
|
+ answerHtml.append("<p>考试说明:</p>");
|
|
|
+ } else {
|
|
|
+ answerHtml.append("<p>考试说明:</p>" + paper.getExamRemark());
|
|
|
+ }
|
|
|
+ // 3.通过试卷获取考试端试卷结构
|
|
|
+ PaperDto paperDto = getPaperDtoByPaper(paper, paper.getId());
|
|
|
+ // 4.获取试卷所有大题,并且循环
|
|
|
+ List<PaperDetailDto> paperDetailDtos = paperDto.getPaperDetails();
|
|
|
+ for (PaperDetailDto paperDetailDto : paperDetailDtos) {
|
|
|
+ String title = "<p>" + paperDetailDto.getCnNum() + "、" + paperDetailDto.getName() + "(共"
|
|
|
+ + paperDetailDto.getScore() + "分)" + "</p>";
|
|
|
+ answerHtml.append(title);
|
|
|
+ // 5.获取大题下面的小题,并循环
|
|
|
+ List<PaperDetailUnitDto> paperDetailUnitDtos = paperDetailDto.getPaperDetailUnits();
|
|
|
+ for (PaperDetailUnitDto paperDetailUnitDto : paperDetailUnitDtos) {
|
|
|
+ // 定义题干
|
|
|
+ String body = paperDetailUnitDto.getQuesBody().replaceAll("<span>", "").replaceAll("</span>", "")
|
|
|
+ .replaceAll("###", "___");
|
|
|
+ ;
|
|
|
+ // 定义选项
|
|
|
+ String option = "";
|
|
|
+ // 定义答案
|
|
|
+ String answer = "";
|
|
|
+ // 6.如果为单选和多选
|
|
|
+ if (paperDetailUnitDto.getQuestionType() == QuesStructType.SINGLE_ANSWER_QUESTION
|
|
|
+ || paperDetailUnitDto.getQuestionType() == QuesStructType.MULTIPLE_ANSWER_QUESTION) {
|
|
|
+ // 获取选项
|
|
|
+ List<QuesOptionDto> quesOptionDtos = paperDetailUnitDto.getQuesOptions();
|
|
|
+ // 添加题干
|
|
|
+ body = startWithP(body, paperDetailUnitDto.getNumber(), false);
|
|
|
+ answerHtml.append(body);
|
|
|
+ // 添加选项
|
|
|
+ for (QuesOptionDto quesOptionDto : quesOptionDtos) {
|
|
|
+ option = startWithP(quesOptionDto.getOptionBody(), Integer.parseInt(quesOptionDto.getNumber()),
|
|
|
+ true);
|
|
|
+ answerHtml.append(option);
|
|
|
+ }
|
|
|
+ answer = startWithP(paperDetailUnitDto.getAnswer(), -1, false);
|
|
|
+ answerHtml.append(answer);
|
|
|
+ }
|
|
|
+ // 7.如果为套题
|
|
|
+ else if (paperDetailUnitDto.getSubQuestions() != null
|
|
|
+ && paperDetailUnitDto.getSubQuestions().size() > 0) {
|
|
|
+ // 添加主题干
|
|
|
+ String bigBody = CommonUtils.relaceQuestionIdx(paperDetailUnitDto.getQuesBody(), 0);
|
|
|
+ bigBody = bigBody.replaceAll("<span>", "").replaceAll("</span>", "").replaceAll("###", "___");
|
|
|
+ bigBody = startWithP(bigBody, -2, false);
|
|
|
+ answerHtml.append(bigBody);
|
|
|
+ List<SubQuestionDto> subQuestionDtos = paperDetailUnitDto.getSubQuestions();
|
|
|
+ for (SubQuestionDto subQuestionDto : subQuestionDtos) {
|
|
|
+ body = subQuestionDto.getQuesBody().replaceAll("<span>", "").replaceAll("</span>", "")
|
|
|
+ .replaceAll("###", "___");
|
|
|
+ // 如果子题为单选或者多选
|
|
|
+ if (subQuestionDto.getQuestionType() == QuesStructType.SINGLE_ANSWER_QUESTION
|
|
|
+ || subQuestionDto.getQuestionType() == QuesStructType.MULTIPLE_ANSWER_QUESTION) {
|
|
|
+ // 获取选项
|
|
|
+ List<QuesOptionDto> quesOptionDtos = subQuestionDto.getQuesOptions();
|
|
|
+ // 添加题干
|
|
|
+ body = startWithP(body, subQuestionDto.getNumber(), false);
|
|
|
+ answerHtml.append(body);
|
|
|
+ // 添加选项
|
|
|
+ for (QuesOptionDto quesOptionDto : quesOptionDtos) {
|
|
|
+ option = startWithP(quesOptionDto.getOptionBody(),
|
|
|
+ Integer.parseInt(quesOptionDto.getNumber()), true);
|
|
|
+ answerHtml.append(option);
|
|
|
+ }
|
|
|
+ answer = startWithP(subQuestionDto.getQuesAnswer(), -1, false);
|
|
|
+ answerHtml.append(answer);
|
|
|
+ } else {
|
|
|
+ // 添加题干
|
|
|
+ body = startWithP(body, subQuestionDto.getNumber(), false);
|
|
|
+ answerHtml.append(body);
|
|
|
+ // 添加答案
|
|
|
+ answer = startWithP(subQuestionDto.getQuesAnswer(), -1, false);
|
|
|
+ answerHtml.append(answer);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ // 添加题干
|
|
|
+ body = startWithP(body, paperDetailUnitDto.getNumber(), false);
|
|
|
+ answerHtml.append(body);
|
|
|
+ // 添加答案
|
|
|
+ answer = startWithP(paperDetailUnitDto.getAnswer(), -1, false);
|
|
|
+ answerHtml.append(answer);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return answerHtml.toString();
|
|
|
+ }
|
|
|
+
|
|
|
+ public String startWithP(String s, Integer number, boolean option) {
|
|
|
+ if (s == null) {
|
|
|
+ s = "<p></p>";
|
|
|
+ }
|
|
|
+ if (number == -2) {
|
|
|
+ if (s.startsWith("<p>")) {
|
|
|
+ s = s.replaceAll("<p>", "<p style=\"margin-left:40px;\">").replaceAll("<p style=\"margin-left:40px;\">",
|
|
|
+ "<p style=\"margin-left:20px;\">");
|
|
|
+ } else {
|
|
|
+ s = "<p style=\"margin-left:20px;color:red;\">" + s + "</p>";
|
|
|
+ }
|
|
|
+ } else if (number == -1) {
|
|
|
+ if (s.startsWith("<p>")) {
|
|
|
+ s = s.replaceAll("<p>", "<p style=\"margin-left:65px;\">")
|
|
|
+ .replaceFirst("<p style=\"margin-left:65px;\">",
|
|
|
+ "<p style=\"margin-left:20px;color:red;\">" + "答案:")
|
|
|
+ .replace("<p style=\"margin-left:65px;\">", "<p style=\"margin-left:65px;color:red;\">");
|
|
|
+ } else {
|
|
|
+ s = "<p style=\"margin-left:20px;color:red;\">" + "答案:" + s + "</p>";
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ if (option) {
|
|
|
+ if (s.startsWith("<p>")) {
|
|
|
+ s = s.replaceAll("<p>", "<p style=\"margin-left:40px;\">").replaceFirst(
|
|
|
+ "<p style=\"margin-left:40px;\">",
|
|
|
+ "<p style=\"margin-left:20px;\">" + CommonUtils.getOptionNum(number - 1) + ".");
|
|
|
+ } else {
|
|
|
+ s = "<p style=\"margin-left:20px;\">" + CommonUtils.getOptionNum(number - 1) + "." + s + "</p>";
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ if (s.startsWith("<p>")) {
|
|
|
+ s = s.replaceAll("<p>", "<p style=\"margin-left:40px;\">").replaceFirst(
|
|
|
+ "<p style=\"margin-left:40px;\">", "<p style=\"margin-left:20px;\">" + number + ".");
|
|
|
+ } else {
|
|
|
+ s = "<p style=\"margin-left:20px;\">" + number + "." + s + "</p>";
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return s;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public List<CouresInfo> findCourseByExtractConfig(Long examId, String orgId, UserDataRule ud) {
|
|
|
+ if (ud.assertEmptyQueryResult()) {
|
|
|
+ return new ArrayList<>();
|
|
|
+ }
|
|
|
+ if (examId == null) {
|
|
|
+ throw new StatusException("500", "examId is null");
|
|
|
+ }
|
|
|
+ // 从考务查询改考试下的所有开启课程
|
|
|
+ List<CouresInfo> courseInfoList = new ArrayList<>();
|
|
|
+ GetExamCourseListReq req = new GetExamCourseListReq();
|
|
|
+ req.setExamId(examId);
|
|
|
+ req.setCourseEnable(true);
|
|
|
+ Long start = 1l;
|
|
|
+ int count = 0;
|
|
|
+ while (true) {
|
|
|
+ req.setStart(start);
|
|
|
+ GetExamCourseListResp resp = examCloudService.getExamCourseList(req);
|
|
|
+ for (ExamCourseRelationBean bean : resp.getRelationList()) {
|
|
|
+ CouresInfo info = new CouresInfo(bean);
|
|
|
+ courseInfoList.add(info);
|
|
|
+ }
|
|
|
+ if (start.equals(resp.getNext())) {
|
|
|
+ break;
|
|
|
+ } else {
|
|
|
+ start = resp.getNext();
|
|
|
+ }
|
|
|
+ count++;
|
|
|
+ if (count > 1000) {
|
|
|
+ throw new StatusException("Q-", "考试下课程的数据量过大");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (CollectionUtils.isEmpty(courseInfoList)) {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ // 查询已经改考试下已经制定的课程的调卷规则
|
|
|
+ Query query = new Query();
|
|
|
+ query.addCriteria(Criteria.where("orgId").is(orgId));
|
|
|
+ query.addCriteria(Criteria.where("examId").is(examId));
|
|
|
+ List<ExtractConfig> extractConfigList = this.mongoTemplate.find(query, ExtractConfig.class);
|
|
|
+ if (extractConfigList != null && extractConfigList.size() > 0) {
|
|
|
+ for (ExtractConfig extractConfig : extractConfigList) {
|
|
|
+ CouresInfo info = new CouresInfo();
|
|
|
+ info.setCourseCode(extractConfig.getCourseCode());
|
|
|
+ if (courseInfoList.contains(info)) {
|
|
|
+ courseInfoList.remove(info);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (ud.assertNeedQueryRefIds() && courseInfoList.size() > 0) {
|
|
|
+ List<CouresInfo> ret = new ArrayList<>();
|
|
|
+ for (CouresInfo info : courseInfoList) {
|
|
|
+ if (ud.getRefIds().contains(info.getCourseId())) {
|
|
|
+ ret.add(info);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return ret;
|
|
|
+ }
|
|
|
+ return courseInfoList;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public List<ExtractConfig> findExtractConfig(Long examId) {
|
|
|
+ if (examId == null) {
|
|
|
+ throw new StatusException("1001", "examId is null");
|
|
|
+ }
|
|
|
+ Query query = new Query();
|
|
|
+ query.addCriteria(Criteria.where("examId").is(examId));
|
|
|
+ query.addCriteria(Criteria.where("course.enable").is("true"));
|
|
|
+
|
|
|
+ List<ExtractConfig> extractConfigList = this.mongoTemplate.find(query, ExtractConfig.class);
|
|
|
+
|
|
|
+ return extractConfigList;
|
|
|
+ }
|
|
|
|
|
|
}
|