|
@@ -10,7 +10,6 @@ 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.service.bean.extract.ExtractConfigPaper;
|
|
|
-import cn.com.qmth.examcloud.core.questions.service.cache.Constants;
|
|
|
import cn.com.qmth.examcloud.core.questions.service.config.SysProperty;
|
|
|
import cn.com.qmth.examcloud.question.commons.core.paper.DefaultPaper;
|
|
|
import cn.com.qmth.examcloud.question.commons.core.paper.DefaultQuestionGroup;
|
|
@@ -18,9 +17,10 @@ import cn.com.qmth.examcloud.question.commons.core.paper.DefaultQuestionStructur
|
|
|
import cn.com.qmth.examcloud.question.commons.core.paper.DefaultQuestionUnitWrapper;
|
|
|
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.bean.ExtractConfigCacheBean;
|
|
|
+import cn.com.qmth.examcloud.support.cache.bean.ExtractConfigDetailCacheBean;
|
|
|
import cn.com.qmth.examcloud.support.cache.bean.ExtractConfigPaperCacheBean;
|
|
|
-import cn.com.qmth.examcloud.web.redis.RedisClient;
|
|
|
import org.apache.commons.collections.CollectionUtils;
|
|
|
import org.apache.commons.lang3.StringUtils;
|
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
@@ -71,140 +71,130 @@ public class ExtractConfigProviderServiceImpl implements ExtractConfigProviderSe
|
|
|
@Autowired
|
|
|
private PaperService paperService;
|
|
|
|
|
|
- @Autowired
|
|
|
- private RedisClient redisClient;
|
|
|
-
|
|
|
@Autowired
|
|
|
private SysProperty sysProperty;
|
|
|
|
|
|
@Override
|
|
|
public ExtractConfigCacheBean getExtractConfig(Long examId, String courseCode, String groupCode) {
|
|
|
- return null;
|
|
|
+ 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.setSortQuestionOrder(extractConfig.getScrambling_the_question_order() == 0 ? false : true);
|
|
|
+ cacheBean.setSortOptionOrder(extractConfig.getScrambling_the_option_order() == 0 ? false : true);
|
|
|
+
|
|
|
+ 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) {
|
|
|
- return null;
|
|
|
+ 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.debug("调卷开始...");
|
|
|
+ log.info("调卷开始...");
|
|
|
|
|
|
- log.debug("开始根据examId:" + examId + "和courseCode:" + courseCode + "获取调卷规则");
|
|
|
- ExtractConfig extractConfig = extractConfigService.findConfig(new ExtractConfig(examId, courseCode));
|
|
|
- if (extractConfig == null) {
|
|
|
- log.error("该课程调卷规则未制定,请联系学校");
|
|
|
- throw new StatusException("Q-020101", "该课程调卷规则未制定,请联系学校");
|
|
|
+ ExtractConfigCacheBean extractConfigCache = CacheHelper.getExtractConfig(examId, courseCode, groupCode);
|
|
|
+ if (extractConfigCache == null) {
|
|
|
+ throw new StatusException("500", "该课程调卷规则未制定,请联系学校!");
|
|
|
}
|
|
|
|
|
|
-
|
|
|
- log.debug("根据调卷规则中设置的概率获取类型为" + groupCode + "的试卷");
|
|
|
- Map<String, Paper> paperMap = this.getExamPaperByProbability(extractConfig.getExamPaperList());
|
|
|
- if (paperMap.isEmpty()) {
|
|
|
- log.error("该考试和课程下调卷规则中试卷不存在,请检查调卷规则,调卷程序退出");
|
|
|
- throw new StatusException("Q-020109", "该考试和课程下调卷规则中试卷不存在,请重新制定调卷规则");
|
|
|
+ final String msg = "该考试和课程下调卷规则中试卷不存在,请重新制定调卷规则!";
|
|
|
+ Map<String, String> paperTypeMaps = this.getExamPaperByProbability(extractConfigCache.getDetails());
|
|
|
+ if (paperTypeMaps.isEmpty()) {
|
|
|
+ throw new StatusException("500", msg);
|
|
|
}
|
|
|
|
|
|
- Paper basePaper = paperMap.get(groupCode);
|
|
|
- if (basePaper == null) {
|
|
|
- log.error("该考试和课程下调卷规则中该类型试卷不存在,请检查调卷规则,调卷程序退出");
|
|
|
- throw new StatusException("Q-020116", "该考试和课程下调卷规则中试卷不存在,请重新制定调卷规则");
|
|
|
+ String basePaperId = paperTypeMaps.get(groupCode);
|
|
|
+ if (StringUtils.isEmpty(basePaperId)) {
|
|
|
+ throw new StatusException("500", msg);
|
|
|
}
|
|
|
|
|
|
- log.debug("将原始试卷:" + basePaper.getId() + "根据规则构建试卷结构");
|
|
|
-
|
|
|
- //优先从缓存中取
|
|
|
- String cacheKey = Constants.CACHE_KEY_PAPER_FOR_EXTRACT_CONFIG + String.format("%s_%s_%s_%s", examId, courseCode, groupCode, basePaper.getId());
|
|
|
- DefaultPaper defaultPaper = redisClient.get(cacheKey, DefaultPaper.class, Constants.DEFAULT_TIME_OUT);
|
|
|
- if (defaultPaper == null) {
|
|
|
- defaultPaper = this.buildDefaultByBasePaper(basePaper, String.valueOf(examId), courseCode, groupCode);
|
|
|
+ log.info("构建试卷结构..." + basePaperId);
|
|
|
+ ExtractConfigPaperCacheBean extractConfigPaperCache = CacheHelper.getExtractConfigPaper(examId, courseCode, groupCode, basePaperId);
|
|
|
+ if (extractConfigPaperCache == null) {
|
|
|
+ throw new StatusException("500", msg);
|
|
|
}
|
|
|
|
|
|
- Short questionOrder = extractConfig.getScrambling_the_question_order();
|
|
|
- Short optionOrder = extractConfig.getScrambling_the_option_order();
|
|
|
-
|
|
|
ExtractConfigPaper result = new ExtractConfigPaper();
|
|
|
- result.setPaperId(basePaper.getId());
|
|
|
- result.setSortQuestionOrder(questionOrder == 0 ? false : true);
|
|
|
- result.setSortOptionOrder(optionOrder == 0 ? false : true);
|
|
|
- result.setDefaultPaper(defaultPaper);
|
|
|
+ result.setDefaultPaper(extractConfigPaperCache.getDefaultPaper());
|
|
|
+ result.setPaperId(basePaperId);
|
|
|
+ result.setSortQuestionOrder(extractConfigCache.getSortQuestionOrder());
|
|
|
+ result.setSortOptionOrder(extractConfigCache.getSortOptionOrder());
|
|
|
return result;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 每个试卷类型取出一套试卷
|
|
|
- * {
|
|
|
- * A:Paper,
|
|
|
- * B:Paper
|
|
|
- * }
|
|
|
- * A是试卷类型 Paper是A类型下选定的试卷
|
|
|
- *
|
|
|
- * @param examPaperList
|
|
|
- * @return
|
|
|
+ * {A:paperId,B:paperId} A是试卷类型,paperId是A类型下选定的试卷ID
|
|
|
*/
|
|
|
- private Map<String, Paper> getExamPaperByProbability(List<ExamPaper> examPaperList) {
|
|
|
- Map<String, Paper> paperByTypeMap = new HashMap<>();
|
|
|
- if (examPaperList == null || examPaperList.size() == 0) {
|
|
|
- throw new StatusException("Q-020114", "可供抽取的试卷集合为空,无法抽取试卷");
|
|
|
- }
|
|
|
-
|
|
|
- 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);
|
|
|
- }
|
|
|
+ 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 {
|
|
|
- if (examPaper.getPaper() != null) {
|
|
|
- List<ExamPaper> epList = examPaperMap.get(examPaper.getGroupCode());
|
|
|
- epList.add(examPaper);
|
|
|
- }
|
|
|
+ List<ExtractConfigDetailCacheBean> list = new ArrayList<>();
|
|
|
+ list.add(examPaper);
|
|
|
+ examPaperMaps.put(examPaper.getGroupCode(), list);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- 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));
|
|
|
+ Map<String, String> paperTypeMaps = new HashMap<>();
|
|
|
+ for (Map.Entry<String, List<ExtractConfigDetailCacheBean>> entry : examPaperMaps.entrySet()) {
|
|
|
+ List<ExtractConfigDetailCacheBean> list = examPaperMaps.get(entry.getKey());
|
|
|
|
|
|
- if (paper == null) {
|
|
|
- continue;
|
|
|
- }
|
|
|
-
|
|
|
- //不能用原来的paper对象,否则examPaperList中的paper对象会被覆盖
|
|
|
- Paper newPaper = Model.of(paperRepo.findById(paper.getId()));
|
|
|
- paperByTypeMap.put(key, newPaper);
|
|
|
+ String paperId = this.getPaperByProbability(list);
|
|
|
+ if (StringUtils.isEmpty(paperId)) {
|
|
|
+ continue;
|
|
|
}
|
|
|
+
|
|
|
+ paperTypeMaps.put(entry.getKey(), paperId);
|
|
|
}
|
|
|
|
|
|
- return paperByTypeMap;
|
|
|
+ return paperTypeMaps;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 根据设定几率取出一套试卷
|
|
|
- *
|
|
|
- * @param examPaperList
|
|
|
- * @return
|
|
|
*/
|
|
|
- private Paper getPaperByProbability(List<ExamPaper> examPaperList) {
|
|
|
+ private String getPaperByProbability(List<ExtractConfigDetailCacheBean> examPapers) {
|
|
|
int sum = 0;
|
|
|
- for (int i = 0; i < examPaperList.size(); i++) {
|
|
|
- sum += examPaperList.get(i).getWeight();
|
|
|
+ for (ExtractConfigDetailCacheBean examPaper : examPapers) {
|
|
|
+ sum += examPaper.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();
|
|
|
+ int r = new Random().nextInt(sum) + 1;
|
|
|
+ for (ExtractConfigDetailCacheBean examPaper : examPapers) {
|
|
|
+ r -= examPaper.getWeight();
|
|
|
+ if (r <= 0) {
|
|
|
+ return examPaper.getPaperId();// 选中
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -213,33 +203,33 @@ public class ExtractConfigProviderServiceImpl implements ExtractConfigProviderSe
|
|
|
|
|
|
/**
|
|
|
* 根据paper对象构建DefaultPaper对象
|
|
|
- *
|
|
|
- * @param basePaper
|
|
|
- * @return
|
|
|
*/
|
|
|
- public DefaultPaper buildDefaultByBasePaper(Paper basePaper, String examId, String courseCode, String groupCode) {
|
|
|
+ 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("开始包装网考需要的试卷结构...");
|
|
|
- long beginTime = System.currentTimeMillis();
|
|
|
|
|
|
//获取大题
|
|
|
List<PaperDetail> paperDetails = paperDetailRepo.findByPaper(basePaper);
|
|
|
- log.debug("数据库取大题耗时:" + (System.currentTimeMillis() - beginTime) + "ms");
|
|
|
|
|
|
//排序大题
|
|
|
Collections.sort(paperDetails);
|
|
|
|
|
|
//将小题全部取出来,只取一次,减少对数据库的查询
|
|
|
- beginTime = System.currentTimeMillis();
|
|
|
List<PaperDetailUnit> allPaperDetailUnits = paperDetailUnitRepo.findByPaper(basePaper);
|
|
|
boolean fullyObjective = checkIsAllQbjectiveQuestion(allPaperDetailUnits);
|
|
|
- log.debug("数据库取所有小题耗时:" + (System.currentTimeMillis() - beginTime) + "ms");
|
|
|
|
|
|
//根据大题id将小题归类
|
|
|
- beginTime = System.currentTimeMillis();
|
|
|
Map<String, List<PaperDetailUnit>> pduMap = allPaperDetailUnits.stream().collect(Collectors.groupingBy(PaperDetailUnit::getDetailId));
|
|
|
- log.debug("获取大题与小题对应关系耗时:" + (System.currentTimeMillis() - beginTime) + "ms");
|
|
|
|
|
|
log.debug("循环大题,开始组装对象...");
|
|
|
+
|
|
|
//生成新的分组集合
|
|
|
List<DefaultQuestionGroup> questionGroupList = new ArrayList<>();
|
|
|
for (int i = 0; i < paperDetails.size(); i++) {
|
|
@@ -250,9 +240,9 @@ public class ExtractConfigProviderServiceImpl implements ExtractConfigProviderSe
|
|
|
|
|
|
//获取原小题的集合
|
|
|
List<PaperDetailUnit> paperDetailUnits = pduMap.get(paperDetail.getId());
|
|
|
- if (paperDetailUnits == null || paperDetailUnits.size() < 1) {
|
|
|
- log.error("试卷大题下面,没有小题");
|
|
|
- throw new StatusException("Q-020241", "考试试卷有误,请联系老师");
|
|
|
+ if (CollectionUtils.isEmpty(paperDetailUnits)) {
|
|
|
+ log.warn("试卷大题下面没有小题!");
|
|
|
+ throw new StatusException("500", "考试试卷有误,请联系老师!");
|
|
|
}
|
|
|
|
|
|
//按题号顺序排序
|
|
@@ -270,8 +260,9 @@ public class ExtractConfigProviderServiceImpl implements ExtractConfigProviderSe
|
|
|
|
|
|
if (examId != null) {
|
|
|
//设置音频播放次数
|
|
|
- if (paperDetailUnit.getQuestion().getHasAudio() != null && paperDetailUnit.getQuestion().getHasAudio() == true) {
|
|
|
- AudioTimeConfig audioTimeConfig = Model.of(audioTimeConfigRepo.findOne(Example.of(new AudioTimeConfig(examId, courseCode, groupCode, paperDetailUnit.getQuestion().getId()))));
|
|
|
+ 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());
|
|
|
}
|
|
@@ -307,12 +298,6 @@ public class ExtractConfigProviderServiceImpl implements ExtractConfigProviderSe
|
|
|
defaultPaper.setQuestionGroupList(questionGroupList);
|
|
|
defaultPaper.setFullyObjective(fullyObjective);
|
|
|
|
|
|
- if (examId != null) {
|
|
|
- //存入缓存
|
|
|
- String cacheKey = Constants.CACHE_KEY_PAPER_FOR_EXTRACT_CONFIG + String.format("%s_%s_%s_%s", examId, courseCode, groupCode, basePaper.getId());
|
|
|
- redisClient.set(cacheKey, defaultPaper, Constants.DEFAULT_TIME_OUT);
|
|
|
- }
|
|
|
-
|
|
|
return defaultPaper;
|
|
|
}
|
|
|
|
|
@@ -374,8 +359,9 @@ public class ExtractConfigProviderServiceImpl implements ExtractConfigProviderSe
|
|
|
|
|
|
Question question = Model.of(quesRepo.findById(questionId));
|
|
|
if (question == null) {
|
|
|
- throw new StatusException("Q-020330", "question is null");
|
|
|
+ throw new StatusException("500", "试题不存在!");
|
|
|
}
|
|
|
+
|
|
|
quesService.formatQues(question);
|
|
|
log.debug("查询单个试题耗时:" + (System.currentTimeMillis() - beginTime) + "ms");
|
|
|
|