|
@@ -0,0 +1,551 @@
|
|
|
|
+package cn.com.qmth.examcloud.core.questions.service.impl;
|
|
|
|
+
|
|
|
|
+import java.util.ArrayList;
|
|
|
|
+import java.util.Collections;
|
|
|
|
+import java.util.HashMap;
|
|
|
|
+import java.util.Iterator;
|
|
|
|
+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.lang3.StringUtils;
|
|
|
|
+import org.springframework.beans.factory.annotation.Autowired;
|
|
|
|
+import org.springframework.beans.factory.annotation.Value;
|
|
|
|
+import org.springframework.data.domain.Example;
|
|
|
|
+import org.springframework.stereotype.Service;
|
|
|
|
+
|
|
|
|
+import com.netflix.infix.lang.infix.antlr.EventFilterParser.boolean_expr_return;
|
|
|
|
+
|
|
|
|
+import cn.com.qmth.examcloud.commons.base.exception.StatusException;
|
|
|
|
+import cn.com.qmth.examcloud.commons.base.logging.ExamCloudLog;
|
|
|
|
+import cn.com.qmth.examcloud.commons.base.logging.ExamCloudLogFactory;
|
|
|
|
+import cn.com.qmth.examcloud.core.questions.base.CommonUtils;
|
|
|
|
+import cn.com.qmth.examcloud.core.questions.base.question.PaperDto;
|
|
|
|
+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.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.QuestionAudioService;
|
|
|
|
+import cn.com.qmth.examcloud.question.core.paper.DefaultPaper;
|
|
|
|
+import cn.com.qmth.examcloud.question.core.paper.DefaultQuestionGroup;
|
|
|
|
+import cn.com.qmth.examcloud.question.core.paper.DefaultQuestionStructureWrapper;
|
|
|
|
+import cn.com.qmth.examcloud.question.core.paper.DefaultQuestionUnitWrapper;
|
|
|
|
+import cn.com.qmth.examcloud.question.core.question.DefaultQuestion;
|
|
|
|
+import cn.com.qmth.examcloud.question.core.question.DefaultQuestionOption;
|
|
|
|
+import cn.com.qmth.examcloud.question.core.question.DefaultQuestionStructure;
|
|
|
|
+import cn.com.qmth.examcloud.question.core.question.DefaultQuestionUnit;
|
|
|
|
+import cn.com.qmth.examcloud.question.core.question.QuestionType;
|
|
|
|
+
|
|
|
|
+/**
|
|
|
|
+ * @author weiwenhai
|
|
|
|
+ * @date 2018.8.15
|
|
|
|
+ * @company qmth
|
|
|
|
+ * @describle provider中的service方法
|
|
|
|
+ * @code 020
|
|
|
|
+ */
|
|
|
|
+@Service("extractConfigCloudService")
|
|
|
|
+public class ExtractConfigProviderServiceImpl implements ExtractConfigProviderService{
|
|
|
|
+
|
|
|
|
+ protected ExamCloudLog log = ExamCloudLogFactory.getLog(this.getClass());
|
|
|
|
+
|
|
|
|
+ @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;
|
|
|
|
+
|
|
|
|
+ @Value("${upyun.downloadUrl}")
|
|
|
|
+ private String downloadUrl;
|
|
|
|
+
|
|
|
|
+ @Override
|
|
|
|
+ public Map<String, Object> getDefaultPaper(Long examId,String courseCode,String groupCode) {
|
|
|
|
+ Map<String,Object> map = new HashMap<String, Object>();
|
|
|
|
+ log.debug("调卷开始...");
|
|
|
|
+ long startTime = System.currentTimeMillis();
|
|
|
|
+ log.debug("开始根据examId:"+ examId +"和courseCode:"+ courseCode +"获取调卷规则");
|
|
|
|
+ ExtractConfig extractConfig = extractConfigService.findConfig(new ExtractConfig(examId,courseCode));
|
|
|
|
+ if(extractConfig == null){
|
|
|
|
+ log.error("该考试和课程下调卷规则未制定,请先制定调卷规则,调卷程序退出");
|
|
|
|
+ throw new StatusException("Q-020033","该考试和课程下调卷规则未制定,请先制定调卷规则,调卷程序退出");
|
|
|
|
+ }
|
|
|
|
+ long configFinishTime = System.currentTimeMillis();
|
|
|
|
+ log.debug("获取调卷规则共耗时:"+ (configFinishTime - startTime)+"ms");
|
|
|
|
+ log.debug("根据调卷规则中设置的概率获取类型为"+ groupCode +"的试卷");
|
|
|
|
+ Map<String,Paper> paperMap = this.getExamPaperByProbability(extractConfig.getExamPaperList());
|
|
|
|
+ if(paperMap.isEmpty()){
|
|
|
|
+ log.error("该考试和课程下调卷规则中试卷不存在,请检查调卷规则,调卷程序退出");
|
|
|
|
+ throw new StatusException("Q-020061","该考试和课程下调卷规则中试卷不存在,请重新制定调卷规则");
|
|
|
|
+ }
|
|
|
|
+ long paperMapFinishTime = System.currentTimeMillis();
|
|
|
|
+ log.debug("获取类型为"+ groupCode +"的试卷共耗时:"+ (paperMapFinishTime - configFinishTime)+"ms");
|
|
|
|
+ Paper basePaper = paperMap.get(groupCode);
|
|
|
|
+ if(basePaper==null){
|
|
|
|
+ log.error("该考试和课程下调卷规则中该类型试卷不存在,请检查调卷规则,调卷程序退出");
|
|
|
|
+ throw new StatusException("Q-020068","该考试和课程下调卷规则中试卷不存在,请重新制定调卷规则");
|
|
|
|
+ }
|
|
|
|
+ log.debug("将原始试卷:"+ basePaper.getId() +"根据规则重新组卷");
|
|
|
|
+ Short upSetQuestionOrder = extractConfig.getScrambling_the_question_order();
|
|
|
|
+ Short upSetOptionOrder = extractConfig.getScrambling_the_option_order();
|
|
|
|
+ map.put("upSetQuestionOrder", upSetQuestionOrder);
|
|
|
|
+ map.put("upSetOptionOrder", upSetOptionOrder);
|
|
|
|
+ //构建试卷结构
|
|
|
|
+ DefaultPaper defaultPaper = buildDefaultByBasePaper(basePaper,String.valueOf(examId),courseCode,groupCode);
|
|
|
|
+ map.put("defaultPaper", defaultPaper);
|
|
|
|
+ return map;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 每个试卷类型取出一套试卷
|
|
|
|
+ * {
|
|
|
|
+ * A:Paper,
|
|
|
|
+ * B:Paper
|
|
|
|
+ * }
|
|
|
|
+ * A是试卷类型 Paper是A类型下选定的试卷
|
|
|
|
+ * @param examPaperList
|
|
|
|
+ * @return
|
|
|
|
+ */
|
|
|
|
+ private Map<String,Paper> getExamPaperByProbability(List<ExamPaper> examPaperList){
|
|
|
|
+ Map<String,Paper> paperByTypeMap = new HashMap<String,Paper>();
|
|
|
|
+ if(examPaperList == null || examPaperList.size() == 0) {
|
|
|
|
+ throw new StatusException("Q-020114","可供抽取的试卷集合为空,无法抽取试卷");
|
|
|
|
+ }
|
|
|
|
+ Map<String,List<ExamPaper>> examPaperMap = new HashMap<String,List<ExamPaper>>();
|
|
|
|
+ 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<ExamPaper>();
|
|
|
|
+ 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));
|
|
|
|
+ //不能用原来的paper对象,否则examPaperList中的paper对象会被覆盖
|
|
|
|
+ Paper newPaper =paperRepo.findOne(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;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 根据paper对象构建DefaultPaper对象
|
|
|
|
+ * @param basePaper
|
|
|
|
+ * @return
|
|
|
|
+ */
|
|
|
|
+ private DefaultPaper buildDefaultByBasePaper(Paper basePaper,String examId,String courseCode,String groupCode){
|
|
|
|
+ log.debug("开始包装网考需要的试卷结构...");
|
|
|
|
+ long beginTime = System.currentTimeMillis();
|
|
|
|
+ //获取大题
|
|
|
|
+ List<PaperDetail> paperDetails = paperDetailRepo.findByPaper(basePaper);
|
|
|
|
+ long pdTime = System.currentTimeMillis();
|
|
|
|
+ log.debug("数据库取大题耗时:"+(pdTime - beginTime)+"ms");
|
|
|
|
+ Collections.sort(paperDetails);
|
|
|
|
+ long pdSortEndTime = System.currentTimeMillis();
|
|
|
|
+ log.debug("排序大题耗时:"+(pdSortEndTime - pdTime)+"ms");
|
|
|
|
+ //将小题全部取出来,只取一次,减少对数据库的查询
|
|
|
|
+ List<PaperDetailUnit> allPaperDetailUnits = paperDetailUnitRepo.findByPaper(basePaper);
|
|
|
|
+ boolean fullyObjective = checkIsAllQbjectiveQuestion(allPaperDetailUnits);
|
|
|
|
+ long pduEndTime = System.currentTimeMillis();
|
|
|
|
+ log.debug("数据库取所有小题耗时:"+(pduEndTime - pdSortEndTime)+"ms");
|
|
|
|
+ //根据大题id将小题归类
|
|
|
|
+ Map<String,List<PaperDetailUnit>> pduMap = allPaperDetailUnits.stream().collect(Collectors.groupingBy(PaperDetailUnit::getDetailId));
|
|
|
|
+ long pduMapEndTime = System.currentTimeMillis();
|
|
|
|
+ log.debug("获取大题与小题对应关系耗时:"+(pduMapEndTime - pduEndTime)+"ms");
|
|
|
|
+ log.debug("循环大题,开始组装对象...");
|
|
|
|
+ //生成新的分组集合
|
|
|
|
+ List<DefaultQuestionGroup> questionGroupList = new ArrayList<DefaultQuestionGroup>();
|
|
|
|
+ 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().floatValue());
|
|
|
|
+ //生成新的题包装器集合
|
|
|
|
+ List<DefaultQuestionStructureWrapper> questionWrapperList = new ArrayList<DefaultQuestionStructureWrapper>();
|
|
|
|
+ //获取原小题的集合
|
|
|
|
+ List<PaperDetailUnit> paperDetailUnits = pduMap.get(paperDetail.getId());
|
|
|
|
+ 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().floatValue());
|
|
|
|
+ //设置音频播放次数
|
|
|
|
+ if(paperDetailUnit.getQuestion().getHasAudio() != null && paperDetailUnit.getQuestion().getHasAudio() == true){
|
|
|
|
+ AudioTimeConfig audioTimeConfig = audioTimeConfigRepo.findOne(Example.of(new AudioTimeConfig(examId,courseCode,groupCode,paperDetailUnit.getQuestion().getId())));
|
|
|
|
+ defaultQuestionStructureWrapper.setPlayedTimes(audioTimeConfig.getPlayTime());
|
|
|
|
+ }
|
|
|
|
+ //生成新的题单元包装器
|
|
|
|
+ List<DefaultQuestionUnitWrapper> defaultQuestionUnitWrappers = new ArrayList<DefaultQuestionUnitWrapper>();
|
|
|
|
+ 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.setQuestionGroupList(questionGroupList);
|
|
|
|
+ defaultPaper.setFullyObjective(fullyObjective);
|
|
|
|
+ return defaultPaper;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 根据question生成题单元包装器
|
|
|
|
+ * @param question
|
|
|
|
+ * @param score
|
|
|
|
+ * @return
|
|
|
|
+ */
|
|
|
|
+ private DefaultQuestionUnitWrapper buildQuesUnitWrapper(Question question,Double score){
|
|
|
|
+ DefaultQuestionUnitWrapper defaultQuestionUnitWrapper = new DefaultQuestionUnitWrapper();
|
|
|
|
+ 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.setOptionPermutation(optionPermutation);
|
|
|
|
+ defaultQuestionUnitWrapper.setQuestionScore(score.floatValue());
|
|
|
|
+ defaultQuestionUnitWrapper.setQuestionType(getByOldType(question.getQuestionType()));
|
|
|
|
+ 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) {
|
|
|
|
+ log.debug("网考根据调卷规则中试题id:"+ questionId +"获取单个试题...");
|
|
|
|
+ long beginTime = System.currentTimeMillis();
|
|
|
|
+ Question question = quesRepo.findOne(questionId);
|
|
|
|
+ long oldQuesTime = System.currentTimeMillis();
|
|
|
|
+ log.debug("查询单个试题耗时:"+(oldQuesTime - beginTime)+"ms");
|
|
|
|
+ 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<DefaultQuestionUnit>();
|
|
|
|
+ if(question.getQuestionType() == QuesStructType.NESTED_ANSWER_QUESTION){
|
|
|
|
+ defaultQuestionStructure.setBody(question.getQuesBody());
|
|
|
|
+ //获取套题下面所有子题
|
|
|
|
+ List<Question> subQuesList = question.getSubQuestions();
|
|
|
|
+ if(subQuesList!=null && subQuesList.size()>0){
|
|
|
|
+ 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);
|
|
|
|
+ long newQuesTime = System.currentTimeMillis();
|
|
|
|
+ log.debug("构建一个新的试题单元耗时:"+(newQuesTime - oldQuesTime)+"ms");
|
|
|
|
+ //替换试题单元中的音频路径
|
|
|
|
+ log.debug("给新的试题替换音频标签...");
|
|
|
|
+ appendAudioFlag(defaultQuestion,String.valueOf(examId),courseCode,groupCode,question);
|
|
|
|
+ long finishTime = System.currentTimeMillis();
|
|
|
|
+ log.debug("给新的试题替换音频标签耗时:"+(finishTime- newQuesTime)+"ms");
|
|
|
|
+ return defaultQuestion;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 构建试题单元
|
|
|
|
+ * @param question
|
|
|
|
+ * @return
|
|
|
|
+ */
|
|
|
|
+ private DefaultQuestionUnit buildQuestionUnit(Question question){
|
|
|
|
+ DefaultQuestionUnit defaultQuestionUnit = new DefaultQuestionUnit();
|
|
|
|
+ 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<DefaultQuestionOption>();
|
|
|
|
+ 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(getSelectQuestionAnswer(quesOptions));
|
|
|
|
+ }else {
|
|
|
|
+ defaultQuestionUnit.setRightAnswer(getAnswer(question));
|
|
|
|
+ }
|
|
|
|
+ return defaultQuestionUnit;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 设置单选题和多选题 答案
|
|
|
|
+ * @param quesOptions
|
|
|
|
+ * @return
|
|
|
|
+ */
|
|
|
|
+ private String[] getSelectQuestionAnswer(List<QuesOption> quesOptions){
|
|
|
|
+ String[] rightAnswer = null;
|
|
|
|
+ List<String> list = new ArrayList<String>();
|
|
|
|
+ if(quesOptions != null && quesOptions.size()>0){
|
|
|
|
+ for(int i=0;i<quesOptions.size();i++){
|
|
|
|
+ QuesOption quesOption = quesOptions.get(i);
|
|
|
|
+ if(quesOption.getIsCorrect() == 1){
|
|
|
|
+ list.add(String.valueOf(i));
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ rightAnswer = list.toArray(new String[list.size()]);
|
|
|
|
+ return rightAnswer;
|
|
|
|
+ }
|
|
|
|
+ return rightAnswer;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 设置试题答案
|
|
|
|
+ * @param question
|
|
|
|
+ * @return
|
|
|
|
+ */
|
|
|
|
+ private String[] getAnswer(Question question){
|
|
|
|
+ String[] rightAnswer = null;
|
|
|
|
+ //判断题答案
|
|
|
|
+ if(question.getQuestionType() == QuesStructType.BOOL_ANSWER_QUESTION){
|
|
|
|
+ if(question.getQuesAnswer().equals("正确")){
|
|
|
|
+ rightAnswer = new String[1];
|
|
|
|
+ rightAnswer[0] = "true";
|
|
|
|
+ return rightAnswer;
|
|
|
|
+ }
|
|
|
|
+ if(question.getQuesAnswer().equals("错误")){
|
|
|
|
+ rightAnswer = new String[1];
|
|
|
|
+ rightAnswer[0] = "false";
|
|
|
|
+ return rightAnswer;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ //填空题答案
|
|
|
|
+ if(question.getQuestionType() == QuesStructType.BOOL_ANSWER_QUESTION){
|
|
|
|
+ rightAnswer = question.getQuesAnswer().split("##");
|
|
|
|
+ return rightAnswer;
|
|
|
|
+ }
|
|
|
|
+ rightAnswer = new String[1];
|
|
|
|
+ rightAnswer[0] = question.getQuesAnswer();
|
|
|
|
+ return rightAnswer;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * html中添加音频标签
|
|
|
|
+ * @param defaultQuestion
|
|
|
|
+ * @param examId
|
|
|
|
+ * @param courseCode
|
|
|
|
+ * @param groupCode
|
|
|
|
+ * @param question
|
|
|
|
+ */
|
|
|
|
+ @SuppressWarnings("unchecked")
|
|
|
|
+ private void appendAudioFlag(DefaultQuestion defaultQuestion,String examId,String courseCode,String groupCode,Question question){
|
|
|
|
+ if(question.getHasAudio() != null && question.getHasAudio() == true){
|
|
|
|
+ //1.判断questionDto是否含有音频,如果有添加音频播放次数
|
|
|
|
+ AudioTimeConfig audioTimeConfig = audioTimeConfigRepo.findOne(Example.of(new AudioTimeConfig(examId,courseCode,groupCode,question.getId())));
|
|
|
|
+ //2.1 取到题干,给a标签添加url
|
|
|
|
+ String quesBody = null;
|
|
|
|
+ if(StringUtils.isNoneBlank(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 = (List<DefaultQuestionOption>) 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()));
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 给题目和选项添加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 = downloadUrl + 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);
|
|
|
|
+ while (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;
|
|
|
|
+ }
|
|
|
|
+}
|