|
@@ -1,37 +1,64 @@
|
|
package cn.com.qmth.examcloud.core.questions.service.impl;
|
|
package cn.com.qmth.examcloud.core.questions.service.impl;
|
|
|
|
|
|
|
|
+import java.util.ArrayList;
|
|
|
|
+import java.util.Collections;
|
|
|
|
+import java.util.HashMap;
|
|
|
|
+import java.util.List;
|
|
|
|
+import java.util.Map;
|
|
|
|
+import java.util.Random;
|
|
|
|
+import java.util.Set;
|
|
|
|
+import java.util.regex.Matcher;
|
|
|
|
+import java.util.regex.Pattern;
|
|
|
|
+import java.util.stream.Collectors;
|
|
|
|
+
|
|
|
|
+import org.apache.commons.collections.CollectionUtils;
|
|
|
|
+import org.apache.commons.lang3.StringUtils;
|
|
|
|
+import org.slf4j.Logger;
|
|
|
|
+import org.slf4j.LoggerFactory;
|
|
|
|
+import org.springframework.beans.factory.annotation.Autowired;
|
|
|
|
+import org.springframework.data.domain.Example;
|
|
|
|
+import org.springframework.stereotype.Service;
|
|
|
|
+
|
|
|
|
+import cn.com.qmth.examcloud.api.commons.enums.CallType;
|
|
import cn.com.qmth.examcloud.commons.exception.StatusException;
|
|
import cn.com.qmth.examcloud.commons.exception.StatusException;
|
|
import cn.com.qmth.examcloud.core.questions.base.CommonUtils;
|
|
import cn.com.qmth.examcloud.core.questions.base.CommonUtils;
|
|
import cn.com.qmth.examcloud.core.questions.base.Model;
|
|
import cn.com.qmth.examcloud.core.questions.base.Model;
|
|
import cn.com.qmth.examcloud.core.questions.base.question.enums.QuesStructType;
|
|
import cn.com.qmth.examcloud.core.questions.base.question.enums.QuesStructType;
|
|
-import cn.com.qmth.examcloud.core.questions.dao.*;
|
|
|
|
-import cn.com.qmth.examcloud.core.questions.dao.entity.*;
|
|
|
|
-import cn.com.qmth.examcloud.core.questions.service.*;
|
|
|
|
|
|
+import cn.com.qmth.examcloud.core.questions.dao.AudioTimeConfigRepo;
|
|
|
|
+import cn.com.qmth.examcloud.core.questions.dao.PaperDetailRepo;
|
|
|
|
+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.QuesRepo;
|
|
|
|
+import cn.com.qmth.examcloud.core.questions.dao.entity.AudioTimeConfig;
|
|
|
|
+import cn.com.qmth.examcloud.core.questions.dao.entity.ExamPaper;
|
|
|
|
+import cn.com.qmth.examcloud.core.questions.dao.entity.ExtractConfig;
|
|
|
|
+import cn.com.qmth.examcloud.core.questions.dao.entity.Paper;
|
|
|
|
+import cn.com.qmth.examcloud.core.questions.dao.entity.PaperDetail;
|
|
|
|
+import cn.com.qmth.examcloud.core.questions.dao.entity.PaperDetailUnit;
|
|
|
|
+import cn.com.qmth.examcloud.core.questions.dao.entity.QuesOption;
|
|
|
|
+import cn.com.qmth.examcloud.core.questions.dao.entity.Question;
|
|
|
|
+import cn.com.qmth.examcloud.core.questions.dao.entity.QuestionAudio;
|
|
|
|
+import cn.com.qmth.examcloud.core.questions.service.ExtractConfigProviderService;
|
|
|
|
+import cn.com.qmth.examcloud.core.questions.service.ExtractConfigService;
|
|
|
|
+import cn.com.qmth.examcloud.core.questions.service.PaperService;
|
|
|
|
+import cn.com.qmth.examcloud.core.questions.service.QuesService;
|
|
|
|
+import cn.com.qmth.examcloud.core.questions.service.QuestionAudioService;
|
|
import cn.com.qmth.examcloud.core.questions.service.bean.QuestionAnswerConvert;
|
|
import cn.com.qmth.examcloud.core.questions.service.bean.QuestionAnswerConvert;
|
|
import cn.com.qmth.examcloud.core.questions.service.bean.extract.ExtractConfigPaper;
|
|
import cn.com.qmth.examcloud.core.questions.service.bean.extract.ExtractConfigPaper;
|
|
import cn.com.qmth.examcloud.question.commons.core.paper.DefaultPaper;
|
|
import cn.com.qmth.examcloud.question.commons.core.paper.DefaultPaper;
|
|
import cn.com.qmth.examcloud.question.commons.core.paper.DefaultQuestionGroup;
|
|
import cn.com.qmth.examcloud.question.commons.core.paper.DefaultQuestionGroup;
|
|
import cn.com.qmth.examcloud.question.commons.core.paper.DefaultQuestionStructureWrapper;
|
|
import cn.com.qmth.examcloud.question.commons.core.paper.DefaultQuestionStructureWrapper;
|
|
import cn.com.qmth.examcloud.question.commons.core.paper.DefaultQuestionUnitWrapper;
|
|
import cn.com.qmth.examcloud.question.commons.core.paper.DefaultQuestionUnitWrapper;
|
|
|
|
+import cn.com.qmth.examcloud.question.commons.core.question.DefaultQuestion;
|
|
|
|
+import cn.com.qmth.examcloud.question.commons.core.question.DefaultQuestionOption;
|
|
|
|
+import cn.com.qmth.examcloud.question.commons.core.question.DefaultQuestionStructure;
|
|
|
|
+import cn.com.qmth.examcloud.question.commons.core.question.DefaultQuestionUnit;
|
|
import cn.com.qmth.examcloud.question.commons.core.question.QuestionType;
|
|
import cn.com.qmth.examcloud.question.commons.core.question.QuestionType;
|
|
-import cn.com.qmth.examcloud.question.commons.core.question.*;
|
|
|
|
import cn.com.qmth.examcloud.support.cache.CacheHelper;
|
|
import cn.com.qmth.examcloud.support.cache.CacheHelper;
|
|
import cn.com.qmth.examcloud.support.cache.bean.ExtractConfigCacheBean;
|
|
import cn.com.qmth.examcloud.support.cache.bean.ExtractConfigCacheBean;
|
|
import cn.com.qmth.examcloud.support.cache.bean.ExtractConfigDetailCacheBean;
|
|
import cn.com.qmth.examcloud.support.cache.bean.ExtractConfigDetailCacheBean;
|
|
import cn.com.qmth.examcloud.support.cache.bean.ExtractConfigPaperCacheBean;
|
|
import cn.com.qmth.examcloud.support.cache.bean.ExtractConfigPaperCacheBean;
|
|
import cn.com.qmth.examcloud.support.filestorage.FileStorageUtil;
|
|
import cn.com.qmth.examcloud.support.filestorage.FileStorageUtil;
|
|
-import org.apache.commons.collections.CollectionUtils;
|
|
|
|
-import org.apache.commons.lang3.StringUtils;
|
|
|
|
-import org.slf4j.Logger;
|
|
|
|
-import org.slf4j.LoggerFactory;
|
|
|
|
-import org.springframework.beans.factory.annotation.Autowired;
|
|
|
|
-import org.springframework.data.domain.Example;
|
|
|
|
-import org.springframework.stereotype.Service;
|
|
|
|
-
|
|
|
|
-import java.util.*;
|
|
|
|
-import java.util.regex.Matcher;
|
|
|
|
-import java.util.regex.Pattern;
|
|
|
|
-import java.util.stream.Collectors;
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
* @author weiwenhai
|
|
* @author weiwenhai
|
|
@@ -43,617 +70,639 @@ import java.util.stream.Collectors;
|
|
@Service("extractConfigCloudService")
|
|
@Service("extractConfigCloudService")
|
|
public class ExtractConfigProviderServiceImpl implements ExtractConfigProviderService {
|
|
public class ExtractConfigProviderServiceImpl implements ExtractConfigProviderService {
|
|
|
|
|
|
- private static final Logger LOG = LoggerFactory.getLogger(ExtractConfigProviderServiceImpl.class);
|
|
|
|
-
|
|
|
|
- @Autowired
|
|
|
|
- private ExtractConfigService extractConfigService;
|
|
|
|
-
|
|
|
|
- @Autowired
|
|
|
|
- private PaperRepo paperRepo;
|
|
|
|
-
|
|
|
|
- @Autowired
|
|
|
|
- private PaperDetailRepo paperDetailRepo;
|
|
|
|
-
|
|
|
|
- @Autowired
|
|
|
|
- private PaperDetailUnitRepo paperDetailUnitRepo;
|
|
|
|
-
|
|
|
|
- @Autowired
|
|
|
|
- private QuesRepo quesRepo;
|
|
|
|
-
|
|
|
|
- @Autowired
|
|
|
|
- private AudioTimeConfigRepo audioTimeConfigRepo;
|
|
|
|
-
|
|
|
|
- @Autowired
|
|
|
|
- private QuestionAudioService questionAudioService;
|
|
|
|
-
|
|
|
|
- @Autowired
|
|
|
|
- private QuesService quesService;
|
|
|
|
-
|
|
|
|
- @Autowired
|
|
|
|
- private PaperService paperService;
|
|
|
|
-
|
|
|
|
- // @Autowired
|
|
|
|
- // private SysProperty sysProperty;
|
|
|
|
-
|
|
|
|
- @Override
|
|
|
|
- public ExtractConfigCacheBean getExtractConfig(Long examId, String courseCode) {
|
|
|
|
- ExtractConfig extractConfig = extractConfigService.findConfig(new ExtractConfig(examId, courseCode));
|
|
|
|
- if (extractConfig == null) {
|
|
|
|
- throw new StatusException("500", "该课程调卷规则未制定,请联系学校!");
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- List<ExamPaper> examPapers = extractConfig.getExamPaperList();
|
|
|
|
- if (CollectionUtils.isEmpty(examPapers)) {
|
|
|
|
- throw new StatusException("500", "可供抽取的试卷集合为空!");
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- ExtractConfigCacheBean cacheBean = new ExtractConfigCacheBean();
|
|
|
|
- cacheBean.setId(extractConfig.getId());
|
|
|
|
- cacheBean.setExamId(examId);
|
|
|
|
- cacheBean.setCourseCode(courseCode);
|
|
|
|
- cacheBean.setRandomPaperId(extractConfig.getRandomPaperId());
|
|
|
|
- cacheBean.setPlayTime(extractConfig.getPlayTime());
|
|
|
|
- cacheBean.setSortQuestionOrder(extractConfig.getScrambling_the_question_order() != 0);
|
|
|
|
- cacheBean.setSortOptionOrder(extractConfig.getScrambling_the_option_order() != 0);
|
|
|
|
-
|
|
|
|
- List<ExtractConfigDetailCacheBean> details = new ArrayList<>();
|
|
|
|
- for (ExamPaper examPaper : examPapers) {
|
|
|
|
- details.add(new ExtractConfigDetailCacheBean(examPaper.getGroupCode(), examPaper.getPaper().getId(), examPaper.getWeight()));
|
|
|
|
- }
|
|
|
|
- cacheBean.setDetails(details);
|
|
|
|
-
|
|
|
|
- return cacheBean;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- @Override
|
|
|
|
- public ExtractConfigPaperCacheBean getExtractConfigPaper(Long examId, String courseCode, String groupCode, String paperId) {
|
|
|
|
- DefaultPaper defaultPaper = this.buildDefaultByBasePaper(paperId, examId, courseCode, groupCode);
|
|
|
|
-
|
|
|
|
- ExtractConfigPaperCacheBean cacheBean = new ExtractConfigPaperCacheBean();
|
|
|
|
- cacheBean.setDefaultPaper(defaultPaper);
|
|
|
|
- return cacheBean;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- @Override
|
|
|
|
- public ExtractConfigPaper getDefaultPaper(Long examId, String courseCode, String groupCode) {
|
|
|
|
- LOG.info("调卷开始...");
|
|
|
|
-
|
|
|
|
- ExtractConfigCacheBean extractConfigCache = CacheHelper.getExtractConfig(examId, courseCode);
|
|
|
|
- if (extractConfigCache == null) {
|
|
|
|
- throw new StatusException("500", "该课程调卷规则未制定,请联系学校!");
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- final String msg = "该考试和课程下调卷规则中试卷不存在,请重新制定调卷规则!";
|
|
|
|
- Map<String, String> paperTypeMaps = this.getExamPaperByProbability(extractConfigCache.getDetails());
|
|
|
|
- if (paperTypeMaps.isEmpty()) {
|
|
|
|
- throw new StatusException("500", msg);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- String basePaperId = paperTypeMaps.get(groupCode);
|
|
|
|
- if (StringUtils.isEmpty(basePaperId)) {
|
|
|
|
- throw new StatusException("500", msg);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- LOG.info("构建试卷结构..." + basePaperId);
|
|
|
|
- ExtractConfigPaperCacheBean extractConfigPaperCache = CacheHelper.getExtractConfigPaper(examId, courseCode, groupCode, basePaperId);
|
|
|
|
- if (extractConfigPaperCache == null) {
|
|
|
|
- throw new StatusException("500", msg);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- ExtractConfigPaper result = new ExtractConfigPaper();
|
|
|
|
- result.setDefaultPaper(extractConfigPaperCache.getDefaultPaper());
|
|
|
|
- result.setPaperId(basePaperId);
|
|
|
|
- result.setSortQuestionOrder(extractConfigCache.getSortQuestionOrder());
|
|
|
|
- result.setSortOptionOrder(extractConfigCache.getSortOptionOrder());
|
|
|
|
- return result;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /**
|
|
|
|
- * 每个试卷类型取出一套试卷
|
|
|
|
- * {A:paperId,B:paperId} A是试卷类型,paperId是A类型下选定的试卷ID
|
|
|
|
- */
|
|
|
|
- private Map<String, String> getExamPaperByProbability(List<ExtractConfigDetailCacheBean> examPapers) {
|
|
|
|
- if (CollectionUtils.isEmpty(examPapers)) {
|
|
|
|
- throw new StatusException("500", "可供抽取的试卷集合为空!");
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- Map<String, List<ExtractConfigDetailCacheBean>> examPaperMaps = new HashMap<>();
|
|
|
|
- for (ExtractConfigDetailCacheBean examPaper : examPapers) {
|
|
|
|
- if (examPaperMaps.containsKey(examPaper.getGroupCode())) {
|
|
|
|
- examPaperMaps.get(examPaper.getGroupCode()).add(examPaper);
|
|
|
|
- } else {
|
|
|
|
- List<ExtractConfigDetailCacheBean> list = new ArrayList<>();
|
|
|
|
- list.add(examPaper);
|
|
|
|
- examPaperMaps.put(examPaper.getGroupCode(), list);
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- Map<String, String> paperTypeMaps = new HashMap<>();
|
|
|
|
- for (Map.Entry<String, List<ExtractConfigDetailCacheBean>> entry : examPaperMaps.entrySet()) {
|
|
|
|
- List<ExtractConfigDetailCacheBean> list = examPaperMaps.get(entry.getKey());
|
|
|
|
-
|
|
|
|
- String paperId = this.getPaperByProbability(list);
|
|
|
|
- if (StringUtils.isEmpty(paperId)) {
|
|
|
|
- continue;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- paperTypeMaps.put(entry.getKey(), paperId);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- return paperTypeMaps;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /**
|
|
|
|
- * 根据设定几率取出一套试卷
|
|
|
|
- */
|
|
|
|
- private String getPaperByProbability(List<ExtractConfigDetailCacheBean> examPapers) {
|
|
|
|
- int sum = 0;
|
|
|
|
- for (ExtractConfigDetailCacheBean examPaper : examPapers) {
|
|
|
|
- sum += examPaper.getWeight();
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- // 从1开始
|
|
|
|
- int r = new Random().nextInt(sum) + 1;
|
|
|
|
- for (ExtractConfigDetailCacheBean examPaper : examPapers) {
|
|
|
|
- r -= examPaper.getWeight();
|
|
|
|
- if (r <= 0) {
|
|
|
|
- return examPaper.getPaperId();// 选中
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- return null;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /**
|
|
|
|
- * 根据paper对象构建DefaultPaper对象
|
|
|
|
- */
|
|
|
|
- public DefaultPaper buildDefaultByBasePaper(String basePaperId, Long examId, String courseCode, String groupCode) {
|
|
|
|
- Paper basePaper = Model.of(paperRepo.findById(basePaperId));
|
|
|
|
- return this.buildDefaultByBasePaper(basePaper, examId, courseCode, groupCode);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /**
|
|
|
|
- * 根据paper对象构建DefaultPaper对象
|
|
|
|
- */
|
|
|
|
- public DefaultPaper buildDefaultByBasePaper(Paper basePaper, Long examId, String courseCode, String groupCode) {
|
|
|
|
- LOG.debug("开始包装网考需要的试卷结构...");
|
|
|
|
-
|
|
|
|
- //获取大题
|
|
|
|
- List<PaperDetail> paperDetails = paperDetailRepo.findByPaper(basePaper);
|
|
|
|
-
|
|
|
|
- //排序大题
|
|
|
|
- Collections.sort(paperDetails);
|
|
|
|
-
|
|
|
|
- //将小题全部取出来,只取一次,减少对数据库的查询
|
|
|
|
- List<PaperDetailUnit> allPaperDetailUnits = paperDetailUnitRepo.findByPaper(basePaper);
|
|
|
|
- boolean fullyObjective = checkIsAllQbjectiveQuestion(allPaperDetailUnits);
|
|
|
|
-
|
|
|
|
- //根据大题id将小题归类
|
|
|
|
- Map<String, List<PaperDetailUnit>> pduMap = allPaperDetailUnits.stream().collect(Collectors.groupingBy(PaperDetailUnit::getDetailId));
|
|
|
|
-
|
|
|
|
- LOG.debug("循环大题,开始组装对象...");
|
|
|
|
-
|
|
|
|
- //生成新的分组集合
|
|
|
|
- List<DefaultQuestionGroup> questionGroupList = new ArrayList<>();
|
|
|
|
- for (int i = 0; i < paperDetails.size(); i++) {
|
|
|
|
- PaperDetail paperDetail = paperDetails.get(i);
|
|
|
|
- DefaultQuestionGroup defaultQuestionGroup = new DefaultQuestionGroup();
|
|
|
|
- defaultQuestionGroup.setGroupName(paperDetail.getName());
|
|
|
|
- defaultQuestionGroup.setGroupScore(paperDetail.getScore());
|
|
|
|
-
|
|
|
|
- //获取原小题的集合
|
|
|
|
- List<PaperDetailUnit> paperDetailUnits = pduMap.get(paperDetail.getId());
|
|
|
|
- if (CollectionUtils.isEmpty(paperDetailUnits)) {
|
|
|
|
- LOG.warn("试卷大题下面没有小题!");
|
|
|
|
- throw new StatusException("500", "考试试卷有误,请联系老师!");
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- //按题号顺序排序
|
|
|
|
- Collections.sort(paperDetailUnits);
|
|
|
|
-
|
|
|
|
- //生成新的题包装器集合
|
|
|
|
- List<DefaultQuestionStructureWrapper> questionWrapperList = new ArrayList<>();
|
|
|
|
- for (int j = 0; j < paperDetailUnits.size(); j++) {
|
|
|
|
- PaperDetailUnit paperDetailUnit = paperDetailUnits.get(j);
|
|
|
|
- DefaultQuestionStructureWrapper defaultQuestionStructureWrapper = new DefaultQuestionStructureWrapper();
|
|
|
|
- defaultQuestionStructureWrapper.setQuestionId(paperDetailUnit.getQuestion().getId());
|
|
|
|
- defaultQuestionStructureWrapper.setVersion(CommonUtils.QUESTION_VERSION);
|
|
|
|
- defaultQuestionStructureWrapper.setQuestionScore(paperDetailUnit.getScore());
|
|
|
|
- defaultQuestionStructureWrapper.setTimeLimit(paperDetailUnit.getTimeLimit());
|
|
|
|
-
|
|
|
|
- if (examId != null) {
|
|
|
|
- //设置音频播放次数
|
|
|
|
- if (paperDetailUnit.getQuestion().getHasAudio() != null && paperDetailUnit.getQuestion().getHasAudio()) {
|
|
|
|
- AudioTimeConfig find = new AudioTimeConfig(examId.toString(), courseCode, groupCode, paperDetailUnit.getQuestion().getId());
|
|
|
|
- AudioTimeConfig audioTimeConfig = Model.of(audioTimeConfigRepo.findOne(Example.of(find)));
|
|
|
|
- if (audioTimeConfig != null) {
|
|
|
|
- defaultQuestionStructureWrapper.setLimitedPlayTimes(audioTimeConfig.getPlayTime());
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- //生成新的题单元包装器
|
|
|
|
- List<DefaultQuestionUnitWrapper> defaultQuestionUnitWrappers = new ArrayList<>();
|
|
|
|
- if (paperDetailUnit.getQuestion().getQuestionType() == QuesStructType.NESTED_ANSWER_QUESTION) {
|
|
|
|
- List<Question> subQuesList = paperDetailUnit.getQuestion().getSubQuestions();
|
|
|
|
- List<Double> scoreList = paperDetailUnit.getSubScoreList();
|
|
|
|
- if (subQuesList != null && subQuesList.size() > 0) {
|
|
|
|
- for (int k = 0; k < subQuesList.size(); k++) {
|
|
|
|
- DefaultQuestionUnitWrapper defaultQuestionUnitWrapper = buildQuesUnitWrapper(subQuesList.get(k), scoreList.get(k));
|
|
|
|
- defaultQuestionUnitWrappers.add(defaultQuestionUnitWrapper);
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- } else {
|
|
|
|
- DefaultQuestionUnitWrapper defaultQuestionUnitWrapper = buildQuesUnitWrapper(paperDetailUnit.getQuestion(), paperDetailUnit.getScore());
|
|
|
|
- defaultQuestionUnitWrappers.add(defaultQuestionUnitWrapper);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- defaultQuestionStructureWrapper.setQuestionUnitWrapperList(defaultQuestionUnitWrappers);
|
|
|
|
- questionWrapperList.add(defaultQuestionStructureWrapper);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- defaultQuestionGroup.setQuestionWrapperList(questionWrapperList);
|
|
|
|
- questionGroupList.add(defaultQuestionGroup);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- DefaultPaper defaultPaper = new DefaultPaper();
|
|
|
|
- defaultPaper.setName(basePaper.getName());
|
|
|
|
- defaultPaper.setQuestionGroupList(questionGroupList);
|
|
|
|
- defaultPaper.setFullyObjective(fullyObjective);
|
|
|
|
-
|
|
|
|
- return defaultPaper;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /**
|
|
|
|
- * 根据question生成题单元包装器
|
|
|
|
- *
|
|
|
|
- * @param question
|
|
|
|
- * @param score
|
|
|
|
- * @return
|
|
|
|
- */
|
|
|
|
- private DefaultQuestionUnitWrapper buildQuesUnitWrapper(Question question, Double score) {
|
|
|
|
- Integer[] optionPermutation = null;
|
|
|
|
- if (question.getQuestionType() == QuesStructType.SINGLE_ANSWER_QUESTION || question.getQuestionType() == QuesStructType.MULTIPLE_ANSWER_QUESTION) {
|
|
|
|
- int length = question.getQuesOptions().size();
|
|
|
|
- optionPermutation = new Integer[length];
|
|
|
|
-
|
|
|
|
- for (int i = 0; i < length; i++) {
|
|
|
|
- optionPermutation[i] = i;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- DefaultQuestionUnitWrapper defaultQuestionUnitWrapper = new DefaultQuestionUnitWrapper();
|
|
|
|
- defaultQuestionUnitWrapper.setOptionPermutation(optionPermutation);
|
|
|
|
- defaultQuestionUnitWrapper.setQuestionScore(score);
|
|
|
|
- defaultQuestionUnitWrapper.setQuestionType(getByOldType(question.getQuestionType()));
|
|
|
|
- defaultQuestionUnitWrapper.setAnswerType(question.getAnswerType());//作答类型
|
|
|
|
- return defaultQuestionUnitWrapper;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /**
|
|
|
|
- * 题型转换方法
|
|
|
|
- *
|
|
|
|
- * @param quesStructType
|
|
|
|
- * @return
|
|
|
|
- */
|
|
|
|
- private QuestionType getByOldType(QuesStructType quesStructType) {
|
|
|
|
- if (quesStructType == QuesStructType.BOOL_ANSWER_QUESTION) {
|
|
|
|
- return QuestionType.TRUE_OR_FALSE;
|
|
|
|
- }
|
|
|
|
- if (quesStructType == QuesStructType.FILL_BLANK_QUESTION) {
|
|
|
|
- return QuestionType.FILL_UP;
|
|
|
|
- }
|
|
|
|
- if (quesStructType == QuesStructType.MULTIPLE_ANSWER_QUESTION) {
|
|
|
|
- return QuestionType.MULTIPLE_CHOICE;
|
|
|
|
- }
|
|
|
|
- if (quesStructType == QuesStructType.SINGLE_ANSWER_QUESTION) {
|
|
|
|
- return QuestionType.SINGLE_CHOICE;
|
|
|
|
- }
|
|
|
|
- if (quesStructType == QuesStructType.TEXT_ANSWER_QUESTION) {
|
|
|
|
- return QuestionType.ESSAY;
|
|
|
|
- }
|
|
|
|
- return null;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- @Override
|
|
|
|
- public DefaultQuestion getDefaultQuestion(Long examId, String courseCode, String groupCode, String questionId) {
|
|
|
|
- Question question = Model.of(quesRepo.findById(questionId));
|
|
|
|
- if (question == null) {
|
|
|
|
- throw new StatusException("500", "试题不存在!");
|
|
|
|
- }
|
|
|
|
- quesService.formatQues(question);
|
|
|
|
-
|
|
|
|
- //封装成新的题单元集合
|
|
|
|
- DefaultQuestionStructure defaultQuestionStructure = new DefaultQuestionStructure();
|
|
|
|
- if (question.getHasAudio() == null || false == question.getHasAudio()) {
|
|
|
|
- defaultQuestionStructure.setHasAudios(false);
|
|
|
|
- } else {
|
|
|
|
- defaultQuestionStructure.setHasAudios(true);
|
|
|
|
- }
|
|
|
|
- defaultQuestionStructure.setVersion(CommonUtils.QUESTION_VERSION);
|
|
|
|
-
|
|
|
|
- List<DefaultQuestionUnit> questionUnitList = new ArrayList<>();
|
|
|
|
- if (question.getQuestionType() == QuesStructType.NESTED_ANSWER_QUESTION) {
|
|
|
|
- defaultQuestionStructure.setBody(question.getQuesBody());
|
|
|
|
-
|
|
|
|
- //获取套题下面所有子题
|
|
|
|
- List<Question> subQuesList = question.getSubQuestions();
|
|
|
|
- if (CollectionUtils.isNotEmpty(subQuesList)) {
|
|
|
|
- for (int i = 0; i < subQuesList.size(); i++) {
|
|
|
|
- Question subQuestion = subQuesList.get(i);
|
|
|
|
- DefaultQuestionUnit defaultQuestionUnit = buildQuestionUnit(subQuestion);
|
|
|
|
- questionUnitList.add(defaultQuestionUnit);
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- } else {
|
|
|
|
- DefaultQuestionUnit defaultQuestionUnit = buildQuestionUnit(question);
|
|
|
|
- questionUnitList.add(defaultQuestionUnit);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- defaultQuestionStructure.setQuestionUnitList(questionUnitList);
|
|
|
|
- DefaultQuestion defaultQuestion = new DefaultQuestion();
|
|
|
|
- defaultQuestion.setId(questionId);
|
|
|
|
- defaultQuestion.setMasterVersion(defaultQuestionStructure);
|
|
|
|
-
|
|
|
|
- if (examId != null) {
|
|
|
|
- appendAudioFlag(defaultQuestion, String.valueOf(examId), courseCode, groupCode, question);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- // 获取试题信息带答案(敏感信息日志,用于排查调用者)
|
|
|
|
- LOG.warn("$$$getQuestionWithAnswer questionId:{} examId:{} courseCode:{} groupCode:{}",
|
|
|
|
- questionId, examId, courseCode, groupCode);
|
|
|
|
- return defaultQuestion;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /**
|
|
|
|
- * 构建试题单元
|
|
|
|
- *
|
|
|
|
- * @param question
|
|
|
|
- * @return
|
|
|
|
- */
|
|
|
|
- private DefaultQuestionUnit buildQuestionUnit(Question question) {
|
|
|
|
- DefaultQuestionUnit defaultQuestionUnit = new DefaultQuestionUnit();
|
|
|
|
- defaultQuestionUnit.setAnswerType(question.getAnswerType());//作答类型
|
|
|
|
- defaultQuestionUnit.setBody(question.getQuesBody());
|
|
|
|
- defaultQuestionUnit.setQuestionType(getByOldType(question.getQuestionType()));
|
|
|
|
-
|
|
|
|
- //如果是单选或者多选,添加选项和答案转换
|
|
|
|
- if (question.getQuestionType() == QuesStructType.SINGLE_ANSWER_QUESTION
|
|
|
|
- || question.getQuestionType() == QuesStructType.MULTIPLE_ANSWER_QUESTION) {
|
|
|
|
- List<DefaultQuestionOption> defaultQuestionOptions = new ArrayList<>();
|
|
|
|
- List<QuesOption> quesOptions = question.getQuesOptions();
|
|
|
|
-
|
|
|
|
- if (quesOptions != null && quesOptions.size() > 0) {
|
|
|
|
- for (int i = 0; i < quesOptions.size(); i++) {
|
|
|
|
- QuesOption quesOption = quesOptions.get(i);
|
|
|
|
- DefaultQuestionOption defaultQuestionOption = new DefaultQuestionOption();
|
|
|
|
- defaultQuestionOption.setBody(quesOption.getOptionBody());
|
|
|
|
- defaultQuestionOptions.add(defaultQuestionOption);
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- defaultQuestionUnit.setQuestionOptionList(defaultQuestionOptions);
|
|
|
|
- defaultQuestionUnit.setRightAnswer(QuestionAnswerConvert.parseQuestionOptionAnswers(quesOptions));
|
|
|
|
- } else {
|
|
|
|
- defaultQuestionUnit.setRightAnswer(QuestionAnswerConvert.parseQuestionAnswers(question));
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- return defaultQuestionUnit;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /**
|
|
|
|
- * html中添加音频标签
|
|
|
|
- *
|
|
|
|
- * @param defaultQuestion
|
|
|
|
- * @param examId
|
|
|
|
- * @param courseCode
|
|
|
|
- * @param groupCode
|
|
|
|
- * @param question
|
|
|
|
- */
|
|
|
|
- private void appendAudioFlag(DefaultQuestion defaultQuestion, String examId, String courseCode, String groupCode, Question question) {
|
|
|
|
- if (question.getHasAudio() != null && question.getHasAudio() == true) {
|
|
|
|
- //1.判断questionDto是否含有音频,如果有添加音频播放次数
|
|
|
|
- AudioTimeConfig audioTimeConfig = Model.of(audioTimeConfigRepo.findOne(Example.of(new AudioTimeConfig(examId, courseCode, groupCode, question.getId()))));
|
|
|
|
- if (audioTimeConfig != null) {
|
|
|
|
- //2.1 取到题干,给a标签添加url
|
|
|
|
- String quesBody = null;
|
|
|
|
- if (StringUtils.isNotBlank(defaultQuestion.getMasterVersion().getBody())) {
|
|
|
|
- //套题
|
|
|
|
- quesBody = defaultQuestion.getMasterVersion().getBody();
|
|
|
|
- defaultQuestion.getMasterVersion().setBody(buildBody(quesBody, audioTimeConfig.getPlayTime()));
|
|
|
|
- } else {
|
|
|
|
- DefaultQuestionUnit defaultQuestionUnit = (DefaultQuestionUnit) defaultQuestion.getMasterVersion().getQuestionUnitList().get(0);
|
|
|
|
- quesBody = defaultQuestionUnit.getBody();
|
|
|
|
- defaultQuestionUnit.setBody(buildBody(quesBody, audioTimeConfig.getPlayTime()));
|
|
|
|
- if (defaultQuestionUnit.getQuestionType() == QuestionType.SINGLE_CHOICE || defaultQuestionUnit.getQuestionType() == QuestionType.MULTIPLE_CHOICE) {
|
|
|
|
- List<DefaultQuestionOption> questionOptionList = defaultQuestionUnit.getQuestionOptionList();
|
|
|
|
- if (questionOptionList != null && questionOptionList.size() > 0) {
|
|
|
|
- for (int i = 0; i < questionOptionList.size(); i++) {
|
|
|
|
- DefaultQuestionOption defaultQuestionOption = questionOptionList.get(i);
|
|
|
|
- defaultQuestionOption.setBody(buildBody(defaultQuestionOption.getBody(), audioTimeConfig.getPlayTime()));
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- } else {
|
|
|
|
- String quesBody = null;
|
|
|
|
- if (StringUtils.isNotBlank(defaultQuestion.getMasterVersion().getBody())) {
|
|
|
|
- //套题
|
|
|
|
- quesBody = defaultQuestion.getMasterVersion().getBody();
|
|
|
|
- defaultQuestion.getMasterVersion().setBody(buildBody(quesBody, null));
|
|
|
|
- } else {
|
|
|
|
- DefaultQuestionUnit defaultQuestionUnit = (DefaultQuestionUnit) defaultQuestion.getMasterVersion().getQuestionUnitList().get(0);
|
|
|
|
- quesBody = defaultQuestionUnit.getBody();
|
|
|
|
- defaultQuestionUnit.setBody(buildBody(quesBody, null));
|
|
|
|
- if (defaultQuestionUnit.getQuestionType() == QuestionType.SINGLE_CHOICE || defaultQuestionUnit.getQuestionType() == QuestionType.MULTIPLE_CHOICE) {
|
|
|
|
- List<DefaultQuestionOption> questionOptionList = defaultQuestionUnit.getQuestionOptionList();
|
|
|
|
- if (questionOptionList != null && questionOptionList.size() > 0) {
|
|
|
|
- for (int i = 0; i < questionOptionList.size(); i++) {
|
|
|
|
- DefaultQuestionOption defaultQuestionOption = questionOptionList.get(i);
|
|
|
|
- defaultQuestionOption.setBody(buildBody(defaultQuestionOption.getBody(), null));
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /**
|
|
|
|
- * 给题目和选项添加url
|
|
|
|
- *
|
|
|
|
- * @param body
|
|
|
|
- * @param playTime
|
|
|
|
- * @return
|
|
|
|
- */
|
|
|
|
- public String buildBody(String body, Integer playTime) {
|
|
|
|
- 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 (playTime != null) {
|
|
|
|
- containAStr += " question-audio url=\"" + url + "\" playTime=\"" + playTime + "\"" + "></a>";
|
|
|
|
- } else {
|
|
|
|
- containAStr += " question-audio url=\"" + url + "\"" + "></a>";
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- resultBody += containAStr;
|
|
|
|
- }
|
|
|
|
- return resultBody;
|
|
|
|
- } else {
|
|
|
|
- return body;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /**
|
|
|
|
- * 获取一段html中某个标签的值
|
|
|
|
- *
|
|
|
|
- * @param source
|
|
|
|
- * @param element
|
|
|
|
- * @param attr
|
|
|
|
- * @return
|
|
|
|
- */
|
|
|
|
- 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 "";
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /**
|
|
|
|
- * 检查所有题目是否为客观题
|
|
|
|
- *
|
|
|
|
- * @param paperDetailUnits
|
|
|
|
- * @return
|
|
|
|
- */
|
|
|
|
- private boolean checkIsAllQbjectiveQuestion(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 DefaultPaper getBaseDefaultPaper(String paperId) {
|
|
|
|
- Paper basePaper = Model.of(paperRepo.findById(paperId));
|
|
|
|
- if (basePaper == null) {
|
|
|
|
- LOG.error("该考试和课程下调卷规则中该类型试卷不存在,请检查调卷规则,调卷程序退出");
|
|
|
|
- throw new StatusException("Q-020560", "该考试和课程下调卷规则中试卷不存在,请重新制定调卷规则");
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- //构建试卷结构
|
|
|
|
- DefaultPaper defaultPaper = this.buildDefaultByBasePaper(basePaper, null, null, null);
|
|
|
|
- return defaultPaper;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- @Override
|
|
|
|
- public Map<String, DefaultQuestion> getDefaultQuestions(Set<String> questionIds) {
|
|
|
|
- Map<String, DefaultQuestion> map = new HashMap<>();
|
|
|
|
- List<Question> questions = quesRepo.findByIdIn(questionIds);
|
|
|
|
- if (CollectionUtils.isEmpty(questions)) {
|
|
|
|
- LOG.error("根据试题id的集合没有查询到试题结合");
|
|
|
|
- throw new StatusException("Q-020572", "根据试题id的集合没有查询到试题结合");
|
|
|
|
- }
|
|
|
|
- for (Question question : questions) {
|
|
|
|
- DefaultQuestion defaultQuestion = getDefaultQuestion(null, null, null, question.getId());
|
|
|
|
- map.put(question.getId(), defaultQuestion);
|
|
|
|
- }
|
|
|
|
- return map;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- @Override
|
|
|
|
- public List<String> getAnswer(String questionId) {
|
|
|
|
- List<String> list = new ArrayList<>();
|
|
|
|
- Question question = Model.of(quesRepo.findById(questionId));
|
|
|
|
-
|
|
|
|
- if (question.getQuestionType() == QuesStructType.NESTED_ANSWER_QUESTION) {
|
|
|
|
- List<Question> subList = question.getSubQuestions();
|
|
|
|
- if (subList != null && subList.size() > 0) {
|
|
|
|
- String answer = "";
|
|
|
|
- for (Question subQuestion : subList) {
|
|
|
|
- if (subQuestion.getQuestionType() == QuesStructType.SINGLE_ANSWER_QUESTION || subQuestion.getQuestionType() == QuesStructType.MULTIPLE_ANSWER_QUESTION) {
|
|
|
|
- String[] answers = QuestionAnswerConvert.parseQuestionOptionAnswers(subQuestion.getQuesOptions());
|
|
|
|
- answer = StringUtils.join(answers, ",");
|
|
|
|
- } else if (subQuestion.getQuestionType() == QuesStructType.BOOL_ANSWER_QUESTION) {
|
|
|
|
- if (subQuestion.getQuesAnswer().endsWith("正确")) {
|
|
|
|
- answer = "true";
|
|
|
|
- } else {
|
|
|
|
- answer = "false";
|
|
|
|
- }
|
|
|
|
- } else {
|
|
|
|
- answer = subQuestion.getQuesAnswer();
|
|
|
|
- }
|
|
|
|
- list.add(answer);
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- } else {
|
|
|
|
- String answer = "";
|
|
|
|
- if (question.getQuestionType() == QuesStructType.SINGLE_ANSWER_QUESTION || question.getQuestionType() == QuesStructType.MULTIPLE_ANSWER_QUESTION) {
|
|
|
|
- String[] answers = QuestionAnswerConvert.parseQuestionOptionAnswers(question.getQuesOptions());
|
|
|
|
- answer = StringUtils.join(answers, ",");
|
|
|
|
- } else if (question.getQuestionType() == QuesStructType.BOOL_ANSWER_QUESTION) {
|
|
|
|
- if (question.getQuesAnswer().endsWith("正确")) {
|
|
|
|
- answer = "true";
|
|
|
|
- } else {
|
|
|
|
- answer = "false";
|
|
|
|
- }
|
|
|
|
- } else {
|
|
|
|
- answer = question.getQuesAnswer();
|
|
|
|
- }
|
|
|
|
- list.add(answer);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- return list;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- @Override
|
|
|
|
- public String getQuestionStructure(String paperId) throws Exception {
|
|
|
|
- String json = paperService.findQuestionStructure(paperId);
|
|
|
|
- return json;
|
|
|
|
- }
|
|
|
|
|
|
+ private static final Logger LOG = LoggerFactory.getLogger(ExtractConfigProviderServiceImpl.class);
|
|
|
|
+
|
|
|
|
+ @Autowired
|
|
|
|
+ private ExtractConfigService extractConfigService;
|
|
|
|
+
|
|
|
|
+ @Autowired
|
|
|
|
+ private PaperRepo paperRepo;
|
|
|
|
+
|
|
|
|
+ @Autowired
|
|
|
|
+ private PaperDetailRepo paperDetailRepo;
|
|
|
|
+
|
|
|
|
+ @Autowired
|
|
|
|
+ private PaperDetailUnitRepo paperDetailUnitRepo;
|
|
|
|
+
|
|
|
|
+ @Autowired
|
|
|
|
+ private QuesRepo quesRepo;
|
|
|
|
+
|
|
|
|
+ @Autowired
|
|
|
|
+ private AudioTimeConfigRepo audioTimeConfigRepo;
|
|
|
|
+
|
|
|
|
+ @Autowired
|
|
|
|
+ private QuestionAudioService questionAudioService;
|
|
|
|
+
|
|
|
|
+ @Autowired
|
|
|
|
+ private QuesService quesService;
|
|
|
|
+
|
|
|
|
+ @Autowired
|
|
|
|
+ private PaperService paperService;
|
|
|
|
+
|
|
|
|
+ // @Autowired
|
|
|
|
+ // private SysProperty sysProperty;
|
|
|
|
+
|
|
|
|
+ @Override
|
|
|
|
+ public ExtractConfigCacheBean getExtractConfig(Long examId, String courseCode) {
|
|
|
|
+ ExtractConfig extractConfig = extractConfigService.findConfig(new ExtractConfig(examId, courseCode));
|
|
|
|
+ if (extractConfig == null) {
|
|
|
|
+ throw new StatusException("500", "该课程调卷规则未制定,请联系学校!");
|
|
|
|
+ }
|
|
|
|
+ if (CallType.WHOLE_SET.equals(extractConfig.getCallType())) {
|
|
|
|
+ if (CollectionUtils.isEmpty(extractConfig.getExamPaperList())) {
|
|
|
|
+ throw new StatusException("500", "可供抽取的试卷集合为空!");
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ ExtractConfigCacheBean cacheBean = new ExtractConfigCacheBean();
|
|
|
|
+ cacheBean.setId(extractConfig.getId());
|
|
|
|
+ cacheBean.setExamId(examId);
|
|
|
|
+ cacheBean.setCallType(extractConfig.getCallType());
|
|
|
|
+ cacheBean.setCourseCode(courseCode);
|
|
|
|
+ cacheBean.setRandomPaperId(extractConfig.getRandomPaperId());
|
|
|
|
+ cacheBean.setPlayTime(extractConfig.getPlayTime());
|
|
|
|
+ cacheBean.setSortQuestionOrder(extractConfig.getScrambling_the_question_order() != 0);
|
|
|
|
+ cacheBean.setSortOptionOrder(extractConfig.getScrambling_the_option_order() != 0);
|
|
|
|
+
|
|
|
|
+ if (CallType.WHOLE_SET.equals(extractConfig.getCallType())) {
|
|
|
|
+ List<ExtractConfigDetailCacheBean> details = new ArrayList<>();
|
|
|
|
+ for (ExamPaper examPaper : extractConfig.getExamPaperList()) {
|
|
|
|
+ details.add(new ExtractConfigDetailCacheBean(examPaper.getGroupCode(), examPaper.getPaper().getId(),
|
|
|
|
+ examPaper.getWeight()));
|
|
|
|
+ }
|
|
|
|
+ cacheBean.setDetails(details);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return cacheBean;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @Override
|
|
|
|
+ public ExtractConfigPaperCacheBean getExtractConfigPaper(Long examId, String courseCode, String groupCode,
|
|
|
|
+ String paperId) {
|
|
|
|
+ DefaultPaper defaultPaper = this.buildDefaultByBasePaper(paperId, examId, courseCode, groupCode);
|
|
|
|
+
|
|
|
|
+ ExtractConfigPaperCacheBean cacheBean = new ExtractConfigPaperCacheBean();
|
|
|
|
+ cacheBean.setDefaultPaper(defaultPaper);
|
|
|
|
+ return cacheBean;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @Override
|
|
|
|
+ public ExtractConfigPaper getDefaultPaper(Long examId, String courseCode, String groupCode) {
|
|
|
|
+ LOG.info("调卷开始...");
|
|
|
|
+
|
|
|
|
+ ExtractConfigCacheBean extractConfigCache = CacheHelper.getExtractConfig(examId, courseCode);
|
|
|
|
+ if (extractConfigCache == null) {
|
|
|
|
+ throw new StatusException("500", "该课程调卷规则未制定,请联系学校!");
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ final String msg = "该考试和课程下调卷规则中试卷不存在,请重新制定调卷规则!";
|
|
|
|
+ Map<String, String> paperTypeMaps = this.getExamPaperByProbability(extractConfigCache.getDetails());
|
|
|
|
+ if (paperTypeMaps.isEmpty()) {
|
|
|
|
+ throw new StatusException("500", msg);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ String basePaperId = paperTypeMaps.get(groupCode);
|
|
|
|
+ if (StringUtils.isEmpty(basePaperId)) {
|
|
|
|
+ throw new StatusException("500", msg);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ LOG.info("构建试卷结构..." + basePaperId);
|
|
|
|
+ ExtractConfigPaperCacheBean extractConfigPaperCache = CacheHelper.getExtractConfigPaper(examId, courseCode,
|
|
|
|
+ groupCode, basePaperId);
|
|
|
|
+ if (extractConfigPaperCache == null) {
|
|
|
|
+ throw new StatusException("500", msg);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ ExtractConfigPaper result = new ExtractConfigPaper();
|
|
|
|
+ result.setDefaultPaper(extractConfigPaperCache.getDefaultPaper());
|
|
|
|
+ result.setPaperId(basePaperId);
|
|
|
|
+ result.setSortQuestionOrder(extractConfigCache.getSortQuestionOrder());
|
|
|
|
+ result.setSortOptionOrder(extractConfigCache.getSortOptionOrder());
|
|
|
|
+ return result;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 每个试卷类型取出一套试卷 {A:paperId,B:paperId} A是试卷类型,paperId是A类型下选定的试卷ID
|
|
|
|
+ */
|
|
|
|
+ private Map<String, String> getExamPaperByProbability(List<ExtractConfigDetailCacheBean> examPapers) {
|
|
|
|
+ if (CollectionUtils.isEmpty(examPapers)) {
|
|
|
|
+ throw new StatusException("500", "可供抽取的试卷集合为空!");
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ Map<String, List<ExtractConfigDetailCacheBean>> examPaperMaps = new HashMap<>();
|
|
|
|
+ for (ExtractConfigDetailCacheBean examPaper : examPapers) {
|
|
|
|
+ if (examPaperMaps.containsKey(examPaper.getGroupCode())) {
|
|
|
|
+ examPaperMaps.get(examPaper.getGroupCode()).add(examPaper);
|
|
|
|
+ } else {
|
|
|
|
+ List<ExtractConfigDetailCacheBean> list = new ArrayList<>();
|
|
|
|
+ list.add(examPaper);
|
|
|
|
+ examPaperMaps.put(examPaper.getGroupCode(), list);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ Map<String, String> paperTypeMaps = new HashMap<>();
|
|
|
|
+ for (Map.Entry<String, List<ExtractConfigDetailCacheBean>> entry : examPaperMaps.entrySet()) {
|
|
|
|
+ List<ExtractConfigDetailCacheBean> list = examPaperMaps.get(entry.getKey());
|
|
|
|
+
|
|
|
|
+ String paperId = this.getPaperByProbability(list);
|
|
|
|
+ if (StringUtils.isEmpty(paperId)) {
|
|
|
|
+ continue;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ paperTypeMaps.put(entry.getKey(), paperId);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return paperTypeMaps;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 根据设定几率取出一套试卷
|
|
|
|
+ */
|
|
|
|
+ private String getPaperByProbability(List<ExtractConfigDetailCacheBean> examPapers) {
|
|
|
|
+ int sum = 0;
|
|
|
|
+ for (ExtractConfigDetailCacheBean examPaper : examPapers) {
|
|
|
|
+ sum += examPaper.getWeight();
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 从1开始
|
|
|
|
+ int r = new Random().nextInt(sum) + 1;
|
|
|
|
+ for (ExtractConfigDetailCacheBean examPaper : examPapers) {
|
|
|
|
+ r -= examPaper.getWeight();
|
|
|
|
+ if (r <= 0) {
|
|
|
|
+ return examPaper.getPaperId();// 选中
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return null;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 根据paper对象构建DefaultPaper对象
|
|
|
|
+ */
|
|
|
|
+ public DefaultPaper buildDefaultByBasePaper(String basePaperId, Long examId, String courseCode, String groupCode) {
|
|
|
|
+ Paper basePaper = Model.of(paperRepo.findById(basePaperId));
|
|
|
|
+ return this.buildDefaultByBasePaper(basePaper, examId, courseCode, groupCode);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 根据paper对象构建DefaultPaper对象
|
|
|
|
+ */
|
|
|
|
+ public DefaultPaper buildDefaultByBasePaper(Paper basePaper, Long examId, String courseCode, String groupCode) {
|
|
|
|
+ LOG.debug("开始包装网考需要的试卷结构...");
|
|
|
|
+
|
|
|
|
+ // 获取大题
|
|
|
|
+ List<PaperDetail> paperDetails = paperDetailRepo.findByPaper(basePaper);
|
|
|
|
+
|
|
|
|
+ // 排序大题
|
|
|
|
+ Collections.sort(paperDetails);
|
|
|
|
+
|
|
|
|
+ // 将小题全部取出来,只取一次,减少对数据库的查询
|
|
|
|
+ List<PaperDetailUnit> allPaperDetailUnits = paperDetailUnitRepo.findByPaper(basePaper);
|
|
|
|
+ boolean fullyObjective = checkIsAllQbjectiveQuestion(allPaperDetailUnits);
|
|
|
|
+
|
|
|
|
+ // 根据大题id将小题归类
|
|
|
|
+ Map<String, List<PaperDetailUnit>> pduMap = allPaperDetailUnits.stream()
|
|
|
|
+ .collect(Collectors.groupingBy(PaperDetailUnit::getDetailId));
|
|
|
|
+
|
|
|
|
+ LOG.debug("循环大题,开始组装对象...");
|
|
|
|
+
|
|
|
|
+ // 生成新的分组集合
|
|
|
|
+ List<DefaultQuestionGroup> questionGroupList = new ArrayList<>();
|
|
|
|
+ for (int i = 0; i < paperDetails.size(); i++) {
|
|
|
|
+ PaperDetail paperDetail = paperDetails.get(i);
|
|
|
|
+ DefaultQuestionGroup defaultQuestionGroup = new DefaultQuestionGroup();
|
|
|
|
+ defaultQuestionGroup.setGroupName(paperDetail.getName());
|
|
|
|
+ defaultQuestionGroup.setGroupScore(paperDetail.getScore());
|
|
|
|
+
|
|
|
|
+ // 获取原小题的集合
|
|
|
|
+ List<PaperDetailUnit> paperDetailUnits = pduMap.get(paperDetail.getId());
|
|
|
|
+ if (CollectionUtils.isEmpty(paperDetailUnits)) {
|
|
|
|
+ LOG.warn("试卷大题下面没有小题!");
|
|
|
|
+ throw new StatusException("500", "考试试卷有误,请联系老师!");
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 按题号顺序排序
|
|
|
|
+ Collections.sort(paperDetailUnits);
|
|
|
|
+
|
|
|
|
+ // 生成新的题包装器集合
|
|
|
|
+ List<DefaultQuestionStructureWrapper> questionWrapperList = new ArrayList<>();
|
|
|
|
+ for (int j = 0; j < paperDetailUnits.size(); j++) {
|
|
|
|
+ PaperDetailUnit paperDetailUnit = paperDetailUnits.get(j);
|
|
|
|
+ DefaultQuestionStructureWrapper defaultQuestionStructureWrapper = new DefaultQuestionStructureWrapper();
|
|
|
|
+ defaultQuestionStructureWrapper.setQuestionId(paperDetailUnit.getQuestion().getId());
|
|
|
|
+ defaultQuestionStructureWrapper.setVersion(CommonUtils.QUESTION_VERSION);
|
|
|
|
+ defaultQuestionStructureWrapper.setQuestionScore(paperDetailUnit.getScore());
|
|
|
|
+ defaultQuestionStructureWrapper.setTimeLimit(paperDetailUnit.getTimeLimit());
|
|
|
|
+
|
|
|
|
+ if (examId != null) {
|
|
|
|
+ // 设置音频播放次数
|
|
|
|
+ if (paperDetailUnit.getQuestion().getHasAudio() != null
|
|
|
|
+ && paperDetailUnit.getQuestion().getHasAudio()) {
|
|
|
|
+ AudioTimeConfig find = new AudioTimeConfig(examId.toString(), courseCode, groupCode,
|
|
|
|
+ paperDetailUnit.getQuestion().getId());
|
|
|
|
+ AudioTimeConfig audioTimeConfig = Model.of(audioTimeConfigRepo.findOne(Example.of(find)));
|
|
|
|
+ if (audioTimeConfig != null) {
|
|
|
|
+ defaultQuestionStructureWrapper.setLimitedPlayTimes(audioTimeConfig.getPlayTime());
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 生成新的题单元包装器
|
|
|
|
+ List<DefaultQuestionUnitWrapper> defaultQuestionUnitWrappers = new ArrayList<>();
|
|
|
|
+ if (paperDetailUnit.getQuestion().getQuestionType() == QuesStructType.NESTED_ANSWER_QUESTION) {
|
|
|
|
+ List<Question> subQuesList = paperDetailUnit.getQuestion().getSubQuestions();
|
|
|
|
+ List<Double> scoreList = paperDetailUnit.getSubScoreList();
|
|
|
|
+ if (subQuesList != null && subQuesList.size() > 0) {
|
|
|
|
+ for (int k = 0; k < subQuesList.size(); k++) {
|
|
|
|
+ DefaultQuestionUnitWrapper defaultQuestionUnitWrapper = buildQuesUnitWrapper(
|
|
|
|
+ subQuesList.get(k), scoreList.get(k));
|
|
|
|
+ defaultQuestionUnitWrappers.add(defaultQuestionUnitWrapper);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ } else {
|
|
|
|
+ DefaultQuestionUnitWrapper defaultQuestionUnitWrapper = buildQuesUnitWrapper(
|
|
|
|
+ paperDetailUnit.getQuestion(), paperDetailUnit.getScore());
|
|
|
|
+ defaultQuestionUnitWrappers.add(defaultQuestionUnitWrapper);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ defaultQuestionStructureWrapper.setQuestionUnitWrapperList(defaultQuestionUnitWrappers);
|
|
|
|
+ questionWrapperList.add(defaultQuestionStructureWrapper);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ defaultQuestionGroup.setQuestionWrapperList(questionWrapperList);
|
|
|
|
+ questionGroupList.add(defaultQuestionGroup);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ DefaultPaper defaultPaper = new DefaultPaper();
|
|
|
|
+ defaultPaper.setName(basePaper.getName());
|
|
|
|
+ defaultPaper.setQuestionGroupList(questionGroupList);
|
|
|
|
+ defaultPaper.setFullyObjective(fullyObjective);
|
|
|
|
+
|
|
|
|
+ return defaultPaper;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 根据question生成题单元包装器
|
|
|
|
+ *
|
|
|
|
+ * @param question
|
|
|
|
+ * @param score
|
|
|
|
+ * @return
|
|
|
|
+ */
|
|
|
|
+ private DefaultQuestionUnitWrapper buildQuesUnitWrapper(Question question, Double score) {
|
|
|
|
+ Integer[] optionPermutation = null;
|
|
|
|
+ if (question.getQuestionType() == QuesStructType.SINGLE_ANSWER_QUESTION
|
|
|
|
+ || question.getQuestionType() == QuesStructType.MULTIPLE_ANSWER_QUESTION) {
|
|
|
|
+ int length = question.getQuesOptions().size();
|
|
|
|
+ optionPermutation = new Integer[length];
|
|
|
|
+
|
|
|
|
+ for (int i = 0; i < length; i++) {
|
|
|
|
+ optionPermutation[i] = i;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ DefaultQuestionUnitWrapper defaultQuestionUnitWrapper = new DefaultQuestionUnitWrapper();
|
|
|
|
+ defaultQuestionUnitWrapper.setOptionPermutation(optionPermutation);
|
|
|
|
+ defaultQuestionUnitWrapper.setQuestionScore(score);
|
|
|
|
+ defaultQuestionUnitWrapper.setQuestionType(getByOldType(question.getQuestionType()));
|
|
|
|
+ defaultQuestionUnitWrapper.setAnswerType(question.getAnswerType());// 作答类型
|
|
|
|
+ return defaultQuestionUnitWrapper;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 题型转换方法
|
|
|
|
+ *
|
|
|
|
+ * @param quesStructType
|
|
|
|
+ * @return
|
|
|
|
+ */
|
|
|
|
+ private QuestionType getByOldType(QuesStructType quesStructType) {
|
|
|
|
+ if (quesStructType == QuesStructType.BOOL_ANSWER_QUESTION) {
|
|
|
|
+ return QuestionType.TRUE_OR_FALSE;
|
|
|
|
+ }
|
|
|
|
+ if (quesStructType == QuesStructType.FILL_BLANK_QUESTION) {
|
|
|
|
+ return QuestionType.FILL_UP;
|
|
|
|
+ }
|
|
|
|
+ if (quesStructType == QuesStructType.MULTIPLE_ANSWER_QUESTION) {
|
|
|
|
+ return QuestionType.MULTIPLE_CHOICE;
|
|
|
|
+ }
|
|
|
|
+ if (quesStructType == QuesStructType.SINGLE_ANSWER_QUESTION) {
|
|
|
|
+ return QuestionType.SINGLE_CHOICE;
|
|
|
|
+ }
|
|
|
|
+ if (quesStructType == QuesStructType.TEXT_ANSWER_QUESTION) {
|
|
|
|
+ return QuestionType.ESSAY;
|
|
|
|
+ }
|
|
|
|
+ return null;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @Override
|
|
|
|
+ public DefaultQuestion getDefaultQuestion(Long examId, String courseCode, String groupCode, String questionId) {
|
|
|
|
+ Question question = Model.of(quesRepo.findById(questionId));
|
|
|
|
+ if (question == null) {
|
|
|
|
+ throw new StatusException("500", "试题不存在!");
|
|
|
|
+ }
|
|
|
|
+ quesService.formatQues(question);
|
|
|
|
+
|
|
|
|
+ // 封装成新的题单元集合
|
|
|
|
+ DefaultQuestionStructure defaultQuestionStructure = new DefaultQuestionStructure();
|
|
|
|
+ if (question.getHasAudio() == null || false == question.getHasAudio()) {
|
|
|
|
+ defaultQuestionStructure.setHasAudios(false);
|
|
|
|
+ } else {
|
|
|
|
+ defaultQuestionStructure.setHasAudios(true);
|
|
|
|
+ }
|
|
|
|
+ defaultQuestionStructure.setVersion(CommonUtils.QUESTION_VERSION);
|
|
|
|
+
|
|
|
|
+ List<DefaultQuestionUnit> questionUnitList = new ArrayList<>();
|
|
|
|
+ if (question.getQuestionType() == QuesStructType.NESTED_ANSWER_QUESTION) {
|
|
|
|
+ defaultQuestionStructure.setBody(question.getQuesBody());
|
|
|
|
+
|
|
|
|
+ // 获取套题下面所有子题
|
|
|
|
+ List<Question> subQuesList = question.getSubQuestions();
|
|
|
|
+ if (CollectionUtils.isNotEmpty(subQuesList)) {
|
|
|
|
+ for (int i = 0; i < subQuesList.size(); i++) {
|
|
|
|
+ Question subQuestion = subQuesList.get(i);
|
|
|
|
+ DefaultQuestionUnit defaultQuestionUnit = buildQuestionUnit(subQuestion);
|
|
|
|
+ questionUnitList.add(defaultQuestionUnit);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ } else {
|
|
|
|
+ DefaultQuestionUnit defaultQuestionUnit = buildQuestionUnit(question);
|
|
|
|
+ questionUnitList.add(defaultQuestionUnit);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ defaultQuestionStructure.setQuestionUnitList(questionUnitList);
|
|
|
|
+ DefaultQuestion defaultQuestion = new DefaultQuestion();
|
|
|
|
+ defaultQuestion.setId(questionId);
|
|
|
|
+ defaultQuestion.setMasterVersion(defaultQuestionStructure);
|
|
|
|
+
|
|
|
|
+ if (examId != null) {
|
|
|
|
+ appendAudioFlag(defaultQuestion, String.valueOf(examId), courseCode, groupCode, question);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 获取试题信息带答案(敏感信息日志,用于排查调用者)
|
|
|
|
+ LOG.warn("$$$getQuestionWithAnswer questionId:{} examId:{} courseCode:{} groupCode:{}", questionId, examId,
|
|
|
|
+ courseCode, groupCode);
|
|
|
|
+ return defaultQuestion;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 构建试题单元
|
|
|
|
+ *
|
|
|
|
+ * @param question
|
|
|
|
+ * @return
|
|
|
|
+ */
|
|
|
|
+ private DefaultQuestionUnit buildQuestionUnit(Question question) {
|
|
|
|
+ DefaultQuestionUnit defaultQuestionUnit = new DefaultQuestionUnit();
|
|
|
|
+ defaultQuestionUnit.setAnswerType(question.getAnswerType());// 作答类型
|
|
|
|
+ defaultQuestionUnit.setBody(question.getQuesBody());
|
|
|
|
+ defaultQuestionUnit.setQuestionType(getByOldType(question.getQuestionType()));
|
|
|
|
+
|
|
|
|
+ // 如果是单选或者多选,添加选项和答案转换
|
|
|
|
+ if (question.getQuestionType() == QuesStructType.SINGLE_ANSWER_QUESTION
|
|
|
|
+ || question.getQuestionType() == QuesStructType.MULTIPLE_ANSWER_QUESTION) {
|
|
|
|
+ List<DefaultQuestionOption> defaultQuestionOptions = new ArrayList<>();
|
|
|
|
+ List<QuesOption> quesOptions = question.getQuesOptions();
|
|
|
|
+
|
|
|
|
+ if (quesOptions != null && quesOptions.size() > 0) {
|
|
|
|
+ for (int i = 0; i < quesOptions.size(); i++) {
|
|
|
|
+ QuesOption quesOption = quesOptions.get(i);
|
|
|
|
+ DefaultQuestionOption defaultQuestionOption = new DefaultQuestionOption();
|
|
|
|
+ defaultQuestionOption.setBody(quesOption.getOptionBody());
|
|
|
|
+ defaultQuestionOptions.add(defaultQuestionOption);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ defaultQuestionUnit.setQuestionOptionList(defaultQuestionOptions);
|
|
|
|
+ defaultQuestionUnit.setRightAnswer(QuestionAnswerConvert.parseQuestionOptionAnswers(quesOptions));
|
|
|
|
+ } else {
|
|
|
|
+ defaultQuestionUnit.setRightAnswer(QuestionAnswerConvert.parseQuestionAnswers(question));
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return defaultQuestionUnit;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * html中添加音频标签
|
|
|
|
+ *
|
|
|
|
+ * @param defaultQuestion
|
|
|
|
+ * @param examId
|
|
|
|
+ * @param courseCode
|
|
|
|
+ * @param groupCode
|
|
|
|
+ * @param question
|
|
|
|
+ */
|
|
|
|
+ private void appendAudioFlag(DefaultQuestion defaultQuestion, String examId, String courseCode, String groupCode,
|
|
|
|
+ Question question) {
|
|
|
|
+ if (question.getHasAudio() != null && question.getHasAudio() == true) {
|
|
|
|
+ // 1.判断questionDto是否含有音频,如果有添加音频播放次数
|
|
|
|
+ AudioTimeConfig audioTimeConfig = Model.of(audioTimeConfigRepo
|
|
|
|
+ .findOne(Example.of(new AudioTimeConfig(examId, courseCode, groupCode, question.getId()))));
|
|
|
|
+ if (audioTimeConfig != null) {
|
|
|
|
+ // 2.1 取到题干,给a标签添加url
|
|
|
|
+ String quesBody = null;
|
|
|
|
+ if (StringUtils.isNotBlank(defaultQuestion.getMasterVersion().getBody())) {
|
|
|
|
+ // 套题
|
|
|
|
+ quesBody = defaultQuestion.getMasterVersion().getBody();
|
|
|
|
+ defaultQuestion.getMasterVersion().setBody(buildBody(quesBody, audioTimeConfig.getPlayTime()));
|
|
|
|
+ } else {
|
|
|
|
+ DefaultQuestionUnit defaultQuestionUnit = (DefaultQuestionUnit) defaultQuestion.getMasterVersion()
|
|
|
|
+ .getQuestionUnitList().get(0);
|
|
|
|
+ quesBody = defaultQuestionUnit.getBody();
|
|
|
|
+ defaultQuestionUnit.setBody(buildBody(quesBody, audioTimeConfig.getPlayTime()));
|
|
|
|
+ if (defaultQuestionUnit.getQuestionType() == QuestionType.SINGLE_CHOICE
|
|
|
|
+ || defaultQuestionUnit.getQuestionType() == QuestionType.MULTIPLE_CHOICE) {
|
|
|
|
+ List<DefaultQuestionOption> questionOptionList = defaultQuestionUnit.getQuestionOptionList();
|
|
|
|
+ if (questionOptionList != null && questionOptionList.size() > 0) {
|
|
|
|
+ for (int i = 0; i < questionOptionList.size(); i++) {
|
|
|
|
+ DefaultQuestionOption defaultQuestionOption = questionOptionList.get(i);
|
|
|
|
+ defaultQuestionOption.setBody(
|
|
|
|
+ buildBody(defaultQuestionOption.getBody(), audioTimeConfig.getPlayTime()));
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ } else {
|
|
|
|
+ String quesBody = null;
|
|
|
|
+ if (StringUtils.isNotBlank(defaultQuestion.getMasterVersion().getBody())) {
|
|
|
|
+ // 套题
|
|
|
|
+ quesBody = defaultQuestion.getMasterVersion().getBody();
|
|
|
|
+ defaultQuestion.getMasterVersion().setBody(buildBody(quesBody, null));
|
|
|
|
+ } else {
|
|
|
|
+ DefaultQuestionUnit defaultQuestionUnit = (DefaultQuestionUnit) defaultQuestion.getMasterVersion()
|
|
|
|
+ .getQuestionUnitList().get(0);
|
|
|
|
+ quesBody = defaultQuestionUnit.getBody();
|
|
|
|
+ defaultQuestionUnit.setBody(buildBody(quesBody, null));
|
|
|
|
+ if (defaultQuestionUnit.getQuestionType() == QuestionType.SINGLE_CHOICE
|
|
|
|
+ || defaultQuestionUnit.getQuestionType() == QuestionType.MULTIPLE_CHOICE) {
|
|
|
|
+ List<DefaultQuestionOption> questionOptionList = defaultQuestionUnit.getQuestionOptionList();
|
|
|
|
+ if (questionOptionList != null && questionOptionList.size() > 0) {
|
|
|
|
+ for (int i = 0; i < questionOptionList.size(); i++) {
|
|
|
|
+ DefaultQuestionOption defaultQuestionOption = questionOptionList.get(i);
|
|
|
|
+ defaultQuestionOption.setBody(buildBody(defaultQuestionOption.getBody(), null));
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 给题目和选项添加url
|
|
|
|
+ *
|
|
|
|
+ * @param body
|
|
|
|
+ * @param playTime
|
|
|
|
+ * @return
|
|
|
|
+ */
|
|
|
|
+ public String buildBody(String body, Integer playTime) {
|
|
|
|
+ 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 (playTime != null) {
|
|
|
|
+ containAStr += " question-audio url=\"" + url + "\" playTime=\"" + playTime + "\""
|
|
|
|
+ + "></a>";
|
|
|
|
+ } else {
|
|
|
|
+ containAStr += " question-audio url=\"" + url + "\"" + "></a>";
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ resultBody += containAStr;
|
|
|
|
+ }
|
|
|
|
+ return resultBody;
|
|
|
|
+ } else {
|
|
|
|
+ return body;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 获取一段html中某个标签的值
|
|
|
|
+ *
|
|
|
|
+ * @param source
|
|
|
|
+ * @param element
|
|
|
|
+ * @param attr
|
|
|
|
+ * @return
|
|
|
|
+ */
|
|
|
|
+ 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 "";
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 检查所有题目是否为客观题
|
|
|
|
+ *
|
|
|
|
+ * @param paperDetailUnits
|
|
|
|
+ * @return
|
|
|
|
+ */
|
|
|
|
+ private boolean checkIsAllQbjectiveQuestion(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 DefaultPaper getBaseDefaultPaper(String paperId) {
|
|
|
|
+ Paper basePaper = Model.of(paperRepo.findById(paperId));
|
|
|
|
+ if (basePaper == null) {
|
|
|
|
+ LOG.error("该考试和课程下调卷规则中该类型试卷不存在,请检查调卷规则,调卷程序退出");
|
|
|
|
+ throw new StatusException("Q-020560", "该考试和课程下调卷规则中试卷不存在,请重新制定调卷规则");
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 构建试卷结构
|
|
|
|
+ DefaultPaper defaultPaper = this.buildDefaultByBasePaper(basePaper, null, null, null);
|
|
|
|
+ return defaultPaper;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @Override
|
|
|
|
+ public Map<String, DefaultQuestion> getDefaultQuestions(Set<String> questionIds) {
|
|
|
|
+ Map<String, DefaultQuestion> map = new HashMap<>();
|
|
|
|
+ List<Question> questions = quesRepo.findByIdIn(questionIds);
|
|
|
|
+ if (CollectionUtils.isEmpty(questions)) {
|
|
|
|
+ LOG.error("根据试题id的集合没有查询到试题结合");
|
|
|
|
+ throw new StatusException("Q-020572", "根据试题id的集合没有查询到试题结合");
|
|
|
|
+ }
|
|
|
|
+ for (Question question : questions) {
|
|
|
|
+ DefaultQuestion defaultQuestion = getDefaultQuestion(null, null, null, question.getId());
|
|
|
|
+ map.put(question.getId(), defaultQuestion);
|
|
|
|
+ }
|
|
|
|
+ return map;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @Override
|
|
|
|
+ public List<String> getAnswer(String questionId) {
|
|
|
|
+ List<String> list = new ArrayList<>();
|
|
|
|
+ Question question = Model.of(quesRepo.findById(questionId));
|
|
|
|
+
|
|
|
|
+ if (question.getQuestionType() == QuesStructType.NESTED_ANSWER_QUESTION) {
|
|
|
|
+ List<Question> subList = question.getSubQuestions();
|
|
|
|
+ if (subList != null && subList.size() > 0) {
|
|
|
|
+ String answer = "";
|
|
|
|
+ for (Question subQuestion : subList) {
|
|
|
|
+ if (subQuestion.getQuestionType() == QuesStructType.SINGLE_ANSWER_QUESTION
|
|
|
|
+ || subQuestion.getQuestionType() == QuesStructType.MULTIPLE_ANSWER_QUESTION) {
|
|
|
|
+ String[] answers = QuestionAnswerConvert
|
|
|
|
+ .parseQuestionOptionAnswers(subQuestion.getQuesOptions());
|
|
|
|
+ answer = StringUtils.join(answers, ",");
|
|
|
|
+ } else if (subQuestion.getQuestionType() == QuesStructType.BOOL_ANSWER_QUESTION) {
|
|
|
|
+ if (subQuestion.getQuesAnswer().endsWith("正确")) {
|
|
|
|
+ answer = "true";
|
|
|
|
+ } else {
|
|
|
|
+ answer = "false";
|
|
|
|
+ }
|
|
|
|
+ } else {
|
|
|
|
+ answer = subQuestion.getQuesAnswer();
|
|
|
|
+ }
|
|
|
|
+ list.add(answer);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ } else {
|
|
|
|
+ String answer = "";
|
|
|
|
+ if (question.getQuestionType() == QuesStructType.SINGLE_ANSWER_QUESTION
|
|
|
|
+ || question.getQuestionType() == QuesStructType.MULTIPLE_ANSWER_QUESTION) {
|
|
|
|
+ String[] answers = QuestionAnswerConvert.parseQuestionOptionAnswers(question.getQuesOptions());
|
|
|
|
+ answer = StringUtils.join(answers, ",");
|
|
|
|
+ } else if (question.getQuestionType() == QuesStructType.BOOL_ANSWER_QUESTION) {
|
|
|
|
+ if (question.getQuesAnswer().endsWith("正确")) {
|
|
|
|
+ answer = "true";
|
|
|
|
+ } else {
|
|
|
|
+ answer = "false";
|
|
|
|
+ }
|
|
|
|
+ } else {
|
|
|
|
+ answer = question.getQuesAnswer();
|
|
|
|
+ }
|
|
|
|
+ list.add(answer);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return list;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @Override
|
|
|
|
+ public String getQuestionStructure(String paperId) throws Exception {
|
|
|
|
+ String json = paperService.findQuestionStructure(paperId);
|
|
|
|
+ return json;
|
|
|
|
+ }
|
|
|
|
|
|
}
|
|
}
|