|
@@ -3,40 +3,74 @@ package cn.com.qmth.examcloud.core.oe.student.service.impl;
|
|
|
import java.util.ArrayList;
|
|
|
import java.util.Date;
|
|
|
import java.util.List;
|
|
|
+import java.util.concurrent.TimeUnit;
|
|
|
|
|
|
+import org.apache.commons.lang.StringUtils;
|
|
|
+import org.springframework.beans.BeanUtils;
|
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
|
import org.springframework.stereotype.Service;
|
|
|
|
|
|
+import com.google.common.cache.Cache;
|
|
|
+import com.google.common.cache.CacheBuilder;
|
|
|
+
|
|
|
+import cn.com.qmth.examcloud.api.commons.enums.ExamType;
|
|
|
+import cn.com.qmth.examcloud.commons.exception.StatusException;
|
|
|
+import cn.com.qmth.examcloud.commons.util.JsonUtil;
|
|
|
import cn.com.qmth.examcloud.core.oe.student.base.bean.ExamQuestion;
|
|
|
import cn.com.qmth.examcloud.core.oe.student.base.bean.ExamRecordQuestions;
|
|
|
+import cn.com.qmth.examcloud.core.oe.student.bean.ExamStudentQuestionInfo;
|
|
|
+import cn.com.qmth.examcloud.core.oe.student.dao.ExamRecordQuestionTempRepo;
|
|
|
+import cn.com.qmth.examcloud.core.oe.student.dao.entity.ExamQuestionTempEntity;
|
|
|
import cn.com.qmth.examcloud.core.oe.student.service.ExamRecordQuestionsService;
|
|
|
+import cn.com.qmth.examcloud.core.oe.student.service.ExamingSessionService;
|
|
|
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.DefaultQuestionStructureWrapper;
|
|
|
import cn.com.qmth.examcloud.question.commons.core.paper.DefaultQuestionUnitWrapper;
|
|
|
+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.support.cache.CacheHelper;
|
|
|
+import cn.com.qmth.examcloud.support.cache.bean.QuestionCacheBean;
|
|
|
+import cn.com.qmth.examcloud.support.examing.ExamingSession;
|
|
|
+import cn.com.qmth.examcloud.support.examing.ExamingStatus;
|
|
|
import cn.com.qmth.examcloud.support.redis.RedisKeyHelper;
|
|
|
import cn.com.qmth.examcloud.web.redis.RedisClient;
|
|
|
|
|
|
@Service("examRecordQuestionsService")
|
|
|
public class ExamRecordQuestionsServiceImpl implements ExamRecordQuestionsService {
|
|
|
|
|
|
+ /**
|
|
|
+ * 考生作答内容长度界限,超过此长度的答案内容存入mongo
|
|
|
+ */
|
|
|
+ private final static int ANWSER_LENGT = 20000;
|
|
|
+
|
|
|
+ // 本地题干缓存,最大200道题,默认缓存120秒
|
|
|
+ private Cache<String, String> questionContentCache = CacheBuilder.newBuilder().maximumSize(200)
|
|
|
+ .expireAfterWrite(120, TimeUnit.SECONDS).build();
|
|
|
+
|
|
|
@Autowired
|
|
|
private RedisClient redisClient;
|
|
|
|
|
|
+ @Autowired
|
|
|
+ private ExamRecordQuestionTempRepo examRecordQuestionTempRepo;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private ExamingSessionService examingSessionService;
|
|
|
+
|
|
|
@Override
|
|
|
- public void saveExamQuestion(Long examRecordDataId,Integer order, ExamQuestion question) {
|
|
|
+ public void saveExamQuestion(Long examRecordDataId, Integer order, ExamQuestion question) {
|
|
|
String key = RedisKeyHelper.getBuilder().studentAnswerKey(examRecordDataId, order);
|
|
|
- redisClient.set(key + examRecordDataId, question,-1);
|
|
|
+ redisClient.set(key + examRecordDataId, question, -1);
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
- public ExamQuestion getExamQuestion(Long examRecordDataId,Integer order) {
|
|
|
+ public ExamQuestion getExamQuestion(Long examRecordDataId, Integer order) {
|
|
|
String key = RedisKeyHelper.getBuilder().studentAnswerKey(examRecordDataId, order);
|
|
|
return redisClient.get(key + examRecordDataId, ExamQuestion.class);
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
- public void deleteExamQuestion(Long examRecordDataId,Integer order) {
|
|
|
+ public void deleteExamQuestion(Long examRecordDataId, Integer order) {
|
|
|
String key = RedisKeyHelper.getBuilder().studentAnswerKey(examRecordDataId, order);
|
|
|
redisClient.delete(key + examRecordDataId);
|
|
|
}
|
|
@@ -58,6 +92,7 @@ public class ExamRecordQuestionsServiceImpl implements ExamRecordQuestionsServic
|
|
|
for (DefaultQuestionUnitWrapper defaultQuestionUnitWrapper : questionUnitWrapperList) {
|
|
|
ExamQuestion examQuestionEntity = new ExamQuestion();
|
|
|
examQuestionEntity.setExamRecordDataId(examRecordDataId);
|
|
|
+ examQuestionEntity.setIsInMongo(false);
|
|
|
examQuestionEntity.setMainNumber(i + 1);
|
|
|
examQuestionEntity.setOrder(++order);
|
|
|
examQuestionEntity.setQuestionId(defaultQuestionStructureWrapper.getQuestionId());
|
|
@@ -75,10 +110,88 @@ public class ExamRecordQuestionsServiceImpl implements ExamRecordQuestionsServic
|
|
|
examRecordQuestions.setExamQuestions(examQuestionEntityList);
|
|
|
examRecordQuestions.setExamRecordDataId(examRecordDataId);
|
|
|
examRecordQuestions.setCreationTime(new Date());
|
|
|
- for(ExamQuestion eq:examRecordQuestions.getExamQuestions()) {
|
|
|
+ for (ExamQuestion eq : examRecordQuestions.getExamQuestions()) {
|
|
|
saveExamQuestion(eq.getExamRecordDataId(), eq.getOrder(), eq);
|
|
|
}
|
|
|
return examRecordQuestions;
|
|
|
}
|
|
|
|
|
|
+ @Override
|
|
|
+ public ExamRecordQuestions getExamRecordQuestions(Long examRecordDataId, Integer quesCount) {
|
|
|
+ ExamRecordQuestions erqs = new ExamRecordQuestions();
|
|
|
+ List<ExamQuestion> examQuestions = new ArrayList<ExamQuestion>();
|
|
|
+ erqs.setExamQuestions(examQuestions);
|
|
|
+ erqs.setExamRecordDataId(examRecordDataId);
|
|
|
+ for (int i = 1; i <= quesCount; i++) {
|
|
|
+ examQuestions.add(getExamQuestion(examRecordDataId, i));
|
|
|
+ }
|
|
|
+ return erqs;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public String getQuestionContent(Long studentId, String questionId) {
|
|
|
+ ExamingSession examSessionInfo = examingSessionService.getExamingSession(studentId);
|
|
|
+ if (examSessionInfo == null || examSessionInfo.getExamingStatus().equals(ExamingStatus.INFORMAL)
|
|
|
+ || examSessionInfo.getCost() >= examSessionInfo.getExamDuration()) {
|
|
|
+ throw new StatusException("1001", "考试已结束,不允许获取试题内容");
|
|
|
+ }
|
|
|
+
|
|
|
+ // 本地缓存key规则:examId_courseCode_paperType_questionId
|
|
|
+ String cacheKey = examSessionInfo.getExamId() + "_" + examSessionInfo.getCourseCode() + "_"
|
|
|
+ + examSessionInfo.getPaperType() + "_" + questionId;
|
|
|
+ String contentJson = questionContentCache.getIfPresent(cacheKey);
|
|
|
+
|
|
|
+ // 如果本地缓存中存在,则从本地缓存中获取
|
|
|
+ if (StringUtils.isNotEmpty(contentJson)) {
|
|
|
+ return contentJson;
|
|
|
+ }else {// 如果本地缓存不存在,则从redis中获取, 并在本地缓存存在存储一份
|
|
|
+ QuestionCacheBean getQuestionResp = CacheHelper.getQuestion(examSessionInfo.getExamId(),
|
|
|
+ examSessionInfo.getCourseCode(), examSessionInfo.getPaperType(), questionId);
|
|
|
+ DefaultQuestionStructure questionStructure = getQuestionResp.getDefaultQuestion().getMasterVersion();
|
|
|
+ List<DefaultQuestionUnit> questionUnits = questionStructure.getQuestionUnitList();
|
|
|
+
|
|
|
+ // 在线考试,清除答案
|
|
|
+ if (examSessionInfo.getExamType().equals(ExamType.ONLINE.name())) {
|
|
|
+ for (DefaultQuestionUnit questionUnit : questionUnits) {
|
|
|
+ questionUnit.setRightAnswer(null);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ String resultJson = JsonUtil.toJson(questionStructure);
|
|
|
+ questionContentCache.put(cacheKey, resultJson);
|
|
|
+ return resultJson;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void submitQuestionAnswer(Long studentId, List<ExamStudentQuestionInfo> examQuestionInfos) {
|
|
|
+ ExamingSession examSessionInfo = examingSessionService.getExamingSession(studentId);
|
|
|
+ if (examSessionInfo == null || examSessionInfo.getExamingStatus().equals(ExamingStatus.INFORMAL)
|
|
|
+ || examSessionInfo.getCost() >= examSessionInfo.getExamDuration()) {
|
|
|
+ throw new StatusException("2001", "考试会话已过期");
|
|
|
+ }
|
|
|
+ long examRecordDataId = examSessionInfo.getExamRecordDataId();
|
|
|
+
|
|
|
+ for (ExamStudentQuestionInfo examQuestionInfo : examQuestionInfos) {
|
|
|
+ ExamQuestion eq=getExamQuestion(examRecordDataId, examQuestionInfo.getOrder());
|
|
|
+ if(eq==null) {
|
|
|
+ throw new StatusException("2002", "试题不存在");
|
|
|
+ }
|
|
|
+ eq.setStudentAnswer(examQuestionInfo.getStudentAnswer());
|
|
|
+ eq.setIsSign(examQuestionInfo.getIsSign());
|
|
|
+ eq.setIsAnswer(StringUtils.isNotBlank(eq.getStudentAnswer()));
|
|
|
+ eq.setAudioPlayTimes(examQuestionInfo.getAudioPlayTimes());
|
|
|
+ //过长存入mongo
|
|
|
+ if(eq.getIsAnswer()&&eq.getStudentAnswer().length()>ANWSER_LENGT) {
|
|
|
+ eq.setIsInMongo(true);
|
|
|
+ ExamQuestionTempEntity temp=new ExamQuestionTempEntity();
|
|
|
+ BeanUtils.copyProperties(eq, temp);
|
|
|
+ temp.setId(null);
|
|
|
+ examRecordQuestionTempRepo.save(temp);
|
|
|
+ eq.setExamQuestionTempId(temp.getId());
|
|
|
+ }else {
|
|
|
+ eq.setIsInMongo(false);
|
|
|
+ }
|
|
|
+ saveExamQuestion(examRecordDataId, examQuestionInfo.getOrder(), eq);
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|