Explorar o código

Merge remote-tracking branch 'origin/dev' into dev

# Conflicts:
#	themis-business/src/main/java/com/qmth/themis/business/service/impl/TOeExamRecordServiceImpl.java
wangliang %!s(int64=4) %!d(string=hai) anos
pai
achega
03993c02ae

+ 120 - 107
themis-business/src/main/java/com/qmth/themis/business/service/impl/TOeExamRecordServiceImpl.java

@@ -1,14 +1,49 @@
 package com.qmth.themis.business.service.impl;
 
+import java.io.File;
+import java.math.BigDecimal;
+import java.text.SimpleDateFormat;
+import java.time.LocalDateTime;
+import java.time.ZoneOffset;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.UUID;
+
+import javax.annotation.Resource;
+
+import org.apache.commons.lang3.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.BeanUtils;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
 import com.alibaba.fastjson.JSONArray;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-import com.qmth.themis.business.bean.backend.*;
+import com.qmth.themis.business.bean.backend.InvigilateListBean;
+import com.qmth.themis.business.bean.backend.InvigilateListHistoryBean;
+import com.qmth.themis.business.bean.backend.InvigilateListPatrolBean;
+import com.qmth.themis.business.bean.backend.InvigilateListProgressBean;
+import com.qmth.themis.business.bean.backend.InvigilateListProgressExcelBean;
+import com.qmth.themis.business.bean.backend.InvigilateListVideoBean;
+import com.qmth.themis.business.bean.backend.InvigilateListWarningBean;
+import com.qmth.themis.business.bean.backend.OpenRecordNeedMarkBean;
 import com.qmth.themis.business.cache.ExamActivityRecordCacheUtil;
 import com.qmth.themis.business.cache.ExamRecordCacheUtil;
 import com.qmth.themis.business.cache.RedisKeyHelper;
-import com.qmth.themis.business.cache.bean.*;
+import com.qmth.themis.business.cache.bean.ExamActivityCacheBean;
+import com.qmth.themis.business.cache.bean.ExamActivityRecordCacheBean;
+import com.qmth.themis.business.cache.bean.ExamCacheBean;
+import com.qmth.themis.business.cache.bean.ExamPaperCacheBean;
+import com.qmth.themis.business.cache.bean.ExamStudentAnswerCacheBean;
+import com.qmth.themis.business.cache.bean.ExamStudentCacheBean;
+import com.qmth.themis.business.cache.bean.ExamStudentPaperStructCacheBean;
+import com.qmth.themis.business.cache.bean.ObjectiveAnswerCacheBean;
 import com.qmth.themis.business.config.SystemConfig;
 import com.qmth.themis.business.constant.SpringContextHolder;
 import com.qmth.themis.business.constant.SystemConstant;
@@ -18,28 +53,29 @@ import com.qmth.themis.business.dto.response.MarkResultDto;
 import com.qmth.themis.business.dto.response.TEExamUnFinishDto;
 import com.qmth.themis.business.entity.TOeExamAnswer;
 import com.qmth.themis.business.entity.TOeExamRecord;
-import com.qmth.themis.business.enums.*;
-import com.qmth.themis.business.service.*;
+import com.qmth.themis.business.enums.ExamRecordFieldEnum;
+import com.qmth.themis.business.enums.ExamRecordStatusEnum;
+import com.qmth.themis.business.enums.ExamTypeEnum;
+import com.qmth.themis.business.enums.ExceptionEnum;
+import com.qmth.themis.business.enums.FinishTypeEnum;
+import com.qmth.themis.business.enums.LivenessTypeEnum;
+import com.qmth.themis.business.enums.MqTagEnum;
+import com.qmth.themis.business.enums.MqTopicEnum;
+import com.qmth.themis.business.enums.ObjectiveScorePolicyEnum;
+import com.qmth.themis.business.enums.RecordSelectStrategyEnum;
+import com.qmth.themis.business.enums.VerifyExceptionEnum;
+import com.qmth.themis.business.service.MqDtoService;
+import com.qmth.themis.business.service.TEExamActivityService;
+import com.qmth.themis.business.service.TEExamPaperService;
+import com.qmth.themis.business.service.TEExamService;
+import com.qmth.themis.business.service.TEExamStudentService;
+import com.qmth.themis.business.service.TOeExamAnswerService;
+import com.qmth.themis.business.service.TOeExamRecordService;
 import com.qmth.themis.business.util.OssUtil;
 import com.qmth.themis.business.util.RedisUtil;
 import com.qmth.themis.common.contanst.Constants;
-import com.qmth.themis.common.exception.BusinessException;
 import com.qmth.themis.common.util.FileUtil;
 import com.qmth.themis.common.util.SimpleBeanUtil;
-import org.apache.commons.lang3.StringUtils;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.BeanUtils;
-import org.springframework.stereotype.Service;
-import org.springframework.transaction.annotation.Transactional;
-
-import javax.annotation.Resource;
-import java.io.File;
-import java.math.BigDecimal;
-import java.text.SimpleDateFormat;
-import java.time.LocalDateTime;
-import java.time.ZoneOffset;
-import java.util.*;
 
 /**
  * @Description: 考试记录 服务实现类
@@ -180,7 +216,7 @@ public class TOeExamRecordServiceImpl extends ServiceImpl<TOeExamRecordMapper, T
         ExamStudentAnswerCacheBean answer = (ExamStudentAnswerCacheBean) redisUtil.get(
                 RedisKeyHelper.examAnswerKey(recordId), key);
         if (answer == null) {
-            log.error("no ExamStudentAnswerCacheBean for calculateObjectiveScore recordId:" + recordId + " key:" + key);
+            log.error("no ExamStudentAnswerCacheBean for calculateObjectiveScore recordId:"+recordId+" key:" + key);
 
             // 计算客观分总分
             calculateTotalObjectiveScore(param);
@@ -189,7 +225,7 @@ public class TOeExamRecordServiceImpl extends ServiceImpl<TOeExamRecordMapper, T
         //整卷客观题标答缓存集合
         Map<String, ObjectiveAnswerCacheBean> map = examPaperService.getObjectiveAnswerCacheBean(paperId);
         if (map == null || map.size() == 0) {
-            log.info("no ObjectiveAnswerCacheBean map for calculateObjectiveScore recordId:" + recordId + " paperId:" + paperId);
+            log.info("no ObjectiveAnswerCacheBean map for calculateObjectiveScore recordId:"+recordId+" paperId:" + paperId);
             // 更新分数
             answer.setScore(0.0);
             redisUtil.set(RedisKeyHelper.examAnswerKey(recordId), key, answer);
@@ -201,7 +237,7 @@ public class TOeExamRecordServiceImpl extends ServiceImpl<TOeExamRecordMapper, T
         //客观题标答缓存
         ObjectiveAnswerCacheBean cb = map.get(key);
         if (cb == null) {
-            log.info("no ObjectiveAnswerCacheBean for calculateObjectiveScore recordId:" + recordId + " key:" + key);
+            log.info("no ObjectiveAnswerCacheBean for calculateObjectiveScore recordId:"+recordId+" key:" + key);
             // 更新分数
             answer.setScore(0.0);
             redisUtil.set(RedisKeyHelper.examAnswerKey(recordId), key, answer);
@@ -266,14 +302,16 @@ public class TOeExamRecordServiceImpl extends ServiceImpl<TOeExamRecordMapper, T
 
     @SuppressWarnings("unchecked")
     private void calculateTotalObjectiveScore(Map<String, Object> param) {
-        Long recordId = (Long) param.get("recordId");
+    	Long recordId = (Long) param.get("recordId");
         Integer mainNumber = (Integer) param.get("mainNumber");
         Integer subNumber = (Integer) param.get("subNumber");
         Integer subIndex = (Integer) param.get("subIndex");
         String lockKey = SystemConstant.REDIS_LOCK_TOTAL_OBJECTIVE_SCORE_PREFIX + recordId;
         try {
+        	String key = RedisKeyHelper.examAnswerHashKey(mainNumber, subNumber, subIndex);
             Boolean lock = redisUtil.lock(lockKey, SystemConstant.REDIS_CACHE_TIME_OUT);
             if (lock) {
+            	log.info("calculateTotalObjectiveScore get lock sucss recordId:"+recordId+" key:"+key);
                 Map<String, ExamStudentAnswerCacheBean> as = redisUtil.getHashEntries(RedisKeyHelper.examAnswerKey(recordId));
                 if (as != null && as.size() > 0) {
                     Double total = 0.0;
@@ -282,6 +320,7 @@ public class TOeExamRecordServiceImpl extends ServiceImpl<TOeExamRecordMapper, T
                             if (sa.getScore() != null) {//有分值
                                 total = total + sa.getScore();
                             } else {
+                            	log.info("calculateTotalObjectiveScore ExamStudentAnswerCacheBean Score is null recordId:"+recordId+" key:"+RedisKeyHelper.examAnswerHashKey(sa.getMainNumber(), sa.getSubNumber(), sa.getSubIndex()));
                                 total = null;
                                 break;
                             }
@@ -289,16 +328,19 @@ public class TOeExamRecordServiceImpl extends ServiceImpl<TOeExamRecordMapper, T
                     }
                     if (total != null) {
                         ExamRecordCacheUtil.setObjectiveScore(recordId, total, true);
+                    }else {
+                    	log.info("calculateTotalObjectiveScore total Score is null recordId:"+recordId+" key:"+key);
                     }
                 }
-            } else {
-                calculateObjectiveScoreMsg(recordId, mainNumber, subNumber, subIndex);
+            }else {
+            	log.info("calculateTotalObjectiveScore get lock faild recordId:"+recordId+" key:"+key);
+            	calculateObjectiveScoreMsg(recordId, mainNumber, subNumber, subIndex);
             }
         } finally {
             redisUtil.releaseLock(lockKey);
         }
     }
-
+    
     //考试中计算客观分消息
     private void calculateObjectiveScoreMsg(Long recordId, Integer mainNumber, Integer subNumber, Integer subIndex) {
         Map<String, Object> transMap = new HashMap<String, Object>();
@@ -306,18 +348,18 @@ public class TOeExamRecordServiceImpl extends ServiceImpl<TOeExamRecordMapper, T
         transMap.put("mainNumber", mainNumber);
         transMap.put("subNumber", subNumber);
         transMap.put("subIndex", subIndex);
-
-        String level = "1s";
-        Integer time = SystemConstant.mqDelayLevel.get(level);
-        LocalDateTime dt = LocalDateTime.now();
-        dt = dt.plusSeconds(Long.parseLong(level.replace("s", "")));
-        Map<String, Object> propMap = new HashMap<String, Object>();
-        propMap.put("timeOut", time);
-        propMap.put("mqExecTime", dt.toInstant(ZoneOffset.of("+8")).toEpochMilli());
-        MqDto mqDto = new MqDto(MqTopicEnum.THEMIS_TOPIC.getCode(), MqTagEnum.CALCULATE_OBJECTIVE_SCORE.name(),
-                transMap, MqTagEnum.CALCULATE_OBJECTIVE_SCORE, recordId.toString(), propMap, recordId.toString());
-
-        mqDtoService.assembleSendAsyncDelayMsg(mqDto);
+        
+		String level = "1s";
+		Integer time = SystemConstant.mqDelayLevel.get(level);
+		LocalDateTime dt = LocalDateTime.now();
+		dt = dt.plusSeconds(Long.parseLong(level.replace("s", "")));
+		Map<String, Object> propMap = new HashMap<String, Object>();
+		propMap.put("timeOut", time);
+		propMap.put("mqExecTime", dt.toInstant(ZoneOffset.of("+8")).toEpochMilli());
+		MqDto mqDto = new MqDto(MqTopicEnum.THEMIS_TOPIC.getCode(), MqTagEnum.CALCULATE_OBJECTIVE_SCORE.name(),
+				transMap, MqTagEnum.CALCULATE_OBJECTIVE_SCORE, recordId.toString(), propMap, recordId.toString());
+
+		mqDtoService.assembleSendAsyncDelayMsg(mqDto);
     }
 
     private boolean checkSingleChoice(String answerArray, JSONArray ar) {
@@ -950,41 +992,26 @@ public class TOeExamRecordServiceImpl extends ServiceImpl<TOeExamRecordMapper, T
     @Override
     @Transactional
     public void setExamBreak(Integer alreadyBreakCount, Long recordId, Long examActivityId) {
-        try {
-            if (redisUtil.lock(SystemConstant.REDIS_LOCK_EXAM_BREAK_PREFIX + recordId, SystemConstant.REDIS_LOCK_EXAM_BREAK_TIME_OUT)) {
-                alreadyBreakCount++;
-                Long breakId = Constants.idGen.next();
-                ExamRecordCacheUtil.setLastBreakId(recordId, breakId, false);
-                ExamRecordCacheUtil.setStatus(recordId, ExamRecordStatusEnum.BREAK_OFF, false);
-                Long lastBreakTimeNow = System.currentTimeMillis();
-                ExamRecordCacheUtil.setLastBreakTime(recordId, lastBreakTimeNow, false);
-                ExamRecordCacheUtil.setAlreadyBreakCount(recordId, alreadyBreakCount, false);
-                Long lastStartTime = System.currentTimeMillis();
-                ExamRecordCacheUtil.setLastStartTime(recordId, lastStartTime, false);
-                String[] columns = new String[]{ExamRecordFieldEnum.last_break_id.name(), ExamRecordFieldEnum.status.name(), ExamRecordFieldEnum.last_break_time.name(), ExamRecordFieldEnum.already_break_count.name(), ExamRecordFieldEnum.last_start_time.name()};
-                Object[] values = new Object[]{breakId, ExamRecordStatusEnum.BREAK_OFF, lastBreakTimeNow, alreadyBreakCount, lastStartTime};
-                TOeExamRecordService tOeExamRecordService = SpringContextHolder.getBean(TOeExamRecordService.class);
-                tOeExamRecordService.dataUpdatesMq(recordId, columns, values);
-                //考试断点异常原因 发送mq start
-                MqDto mqDtoBreak = new MqDto(MqTopicEnum.THEMIS_TOPIC.getCode(), MqTagEnum.EXAM_BREAK.name(), ExceptionEnum.NET_TIME_OUT, MqTagEnum.EXAM_BREAK, String.valueOf(recordId), String.valueOf(recordId));
-                MqDtoService mqDtoService = SpringContextHolder.getBean(MqDtoService.class);
-                mqDtoService.assembleSendOneWayMsg(mqDtoBreak);
-                //考试断点异常原因 发送mq end
-                //更新场次-考试记录缓存
-                ExamActivityRecordCacheUtil.setExamRecordStatus(examActivityId, recordId, new ExamActivityRecordCacheBean(ExamRecordCacheUtil.getExamStudentId(recordId), ExamRecordCacheUtil.getStatus(recordId)));
-            }
-        } catch (Exception e) {
-            log.error("请求出错", e);
-            if (e instanceof BusinessException) {
-                throw new BusinessException(e.getMessage());
-            } else {
-                throw new RuntimeException(e);
-            }
-        } finally {
-            if (Objects.nonNull(recordId)) {
-                redisUtil.releaseLock(SystemConstant.REDIS_LOCK_EXAM_BREAK_PREFIX + recordId);
-            }
-        }
+        alreadyBreakCount++;
+        Long breakId = Constants.idGen.next();
+        ExamRecordCacheUtil.setLastBreakId(recordId, breakId, false);
+        ExamRecordCacheUtil.setStatus(recordId, ExamRecordStatusEnum.BREAK_OFF, false);
+        Long lastBreakTimeNow = System.currentTimeMillis();
+        ExamRecordCacheUtil.setLastBreakTime(recordId, lastBreakTimeNow, false);
+        ExamRecordCacheUtil.setAlreadyBreakCount(recordId, alreadyBreakCount, false);
+        Long lastStartTime = System.currentTimeMillis();
+        ExamRecordCacheUtil.setLastStartTime(recordId, lastStartTime, false);
+        String[] columns = new String[]{ExamRecordFieldEnum.last_break_id.name(), ExamRecordFieldEnum.status.name(), ExamRecordFieldEnum.last_break_time.name(), ExamRecordFieldEnum.already_break_count.name(), ExamRecordFieldEnum.last_start_time.name()};
+        Object[] values = new Object[]{breakId, ExamRecordStatusEnum.BREAK_OFF, lastBreakTimeNow, alreadyBreakCount, lastStartTime};
+        TOeExamRecordService tOeExamRecordService = SpringContextHolder.getBean(TOeExamRecordService.class);
+        tOeExamRecordService.dataUpdatesMq(recordId, columns, values);
+        //考试断点异常原因 发送mq start
+        MqDto mqDtoBreak = new MqDto(MqTopicEnum.THEMIS_TOPIC.getCode(), MqTagEnum.EXAM_BREAK.name(), ExceptionEnum.NET_TIME_OUT, MqTagEnum.EXAM_BREAK, String.valueOf(recordId), String.valueOf(recordId));
+        MqDtoService mqDtoService = SpringContextHolder.getBean(MqDtoService.class);
+        mqDtoService.assembleSendOneWayMsg(mqDtoBreak);
+        //考试断点异常原因 发送mq end
+        //更新场次-考试记录缓存
+        ExamActivityRecordCacheUtil.setExamRecordStatus(examActivityId, recordId, new ExamActivityRecordCacheBean(ExamRecordCacheUtil.getExamStudentId(recordId), ExamRecordCacheUtil.getStatus(recordId)));
     }
 
     /**
@@ -997,41 +1024,27 @@ public class TOeExamRecordServiceImpl extends ServiceImpl<TOeExamRecordMapper, T
     @Override
     public Boolean sendExamBreakMsg(Long recordId, boolean setBreak) {
         Boolean finished = false;
-        try {
-            if (redisUtil.lock(SystemConstant.REDIS_LOCK_EXAM_BREAK_LOGIC_PREFIX + recordId, SystemConstant.REDIS_LOCK_EXAM_BREAK_LOGIC_TIME_OUT)) {
-                Long examId = ExamRecordCacheUtil.getExamId(recordId);
-                Long examStudentId = ExamRecordCacheUtil.getExamStudentId(recordId);
-                ExamStudentCacheBean examStudentCacheBean = teExamStudentService.getExamStudentCacheBean(examStudentId);
-                ExamCacheBean ec = examService.getExamCacheBean(examId);//考试缓存
-                Long lastBreakTime = ExamRecordCacheUtil.getLastBreakTime(recordId);
-                Integer breakExpireSeconds = Objects.isNull(ec.getBreakExpireSeconds()) ? 0 : ec.getBreakExpireSeconds();
-                Integer durationSeconds = Objects.isNull(ExamRecordCacheUtil.getDurationSeconds(recordId)) ? 0 : ExamRecordCacheUtil.getDurationSeconds(recordId);
-                Integer alreadyBreakCount = Objects.isNull(ExamRecordCacheUtil.getAlreadyBreakCount(recordId)) ? 0 : ExamRecordCacheUtil.getAlreadyBreakCount(recordId);
-                Integer leftBreakResumeCount = ec.getBreakResumeCount() - alreadyBreakCount;
-                if (Objects.nonNull(lastBreakTime) && (System.currentTimeMillis() - lastBreakTime) / 1000 >= breakExpireSeconds) {
-                    finished = true;
-                    examService.finish(examStudentCacheBean.getStudentId(), recordId, FinishTypeEnum.AUTO.name(), durationSeconds);
-                } else {
-                    if (leftBreakResumeCount < 0) {
-                        finished = true;
-                        examService.finish(examStudentCacheBean.getStudentId(), recordId, FinishTypeEnum.AUTO.name(), durationSeconds);
-                    } else {
-                        if (setBreak) {
-                            this.setExamBreak(alreadyBreakCount, recordId, examStudentCacheBean.getExamActivityId());
-                        }
-                    }
-                }
-            }
-        } catch (Exception e) {
-            log.error("请求出错", e);
-            if (e instanceof BusinessException) {
-                throw new BusinessException(e.getMessage());
+        Long examId = ExamRecordCacheUtil.getExamId(recordId);
+        Long examStudentId = ExamRecordCacheUtil.getExamStudentId(recordId);
+        ExamStudentCacheBean examStudentCacheBean = teExamStudentService.getExamStudentCacheBean(examStudentId);
+        ExamCacheBean ec = examService.getExamCacheBean(examId);//考试缓存
+
+        Long lastBreakTime = ExamRecordCacheUtil.getLastBreakTime(recordId);
+        Integer breakExpireSeconds = Objects.isNull(ec.getBreakExpireSeconds()) ? 0 : ec.getBreakExpireSeconds();
+        Integer durationSeconds = Objects.isNull(ExamRecordCacheUtil.getDurationSeconds(recordId)) ? 0 : ExamRecordCacheUtil.getDurationSeconds(recordId);
+        Integer alreadyBreakCount = Objects.isNull(ExamRecordCacheUtil.getAlreadyBreakCount(recordId)) ? 0 : ExamRecordCacheUtil.getAlreadyBreakCount(recordId);
+        Integer leftBreakResumeCount = ec.getBreakResumeCount() - alreadyBreakCount;
+        if (Objects.nonNull(lastBreakTime) && (System.currentTimeMillis() - lastBreakTime) / 1000 >= breakExpireSeconds) {
+            finished = true;
+            examService.finish(examStudentCacheBean.getStudentId(), recordId, FinishTypeEnum.AUTO.name(), durationSeconds);
+        } else {
+            if (leftBreakResumeCount < 0) {
+                finished = true;
+                examService.finish(examStudentCacheBean.getStudentId(), recordId, FinishTypeEnum.AUTO.name(), durationSeconds);
             } else {
-                throw new RuntimeException(e);
-            }
-        } finally {
-            if (Objects.nonNull(recordId)) {
-                redisUtil.releaseLock(SystemConstant.REDIS_LOCK_EXAM_BREAK_LOGIC_PREFIX + recordId);
+                if (setBreak) {
+                    this.setExamBreak(alreadyBreakCount, recordId, examStudentCacheBean.getExamActivityId());
+                }
             }
         }
         return finished;