Procházet zdrojové kódy

update 尚未做过活检,不作为违纪或异常。

deason před 1 rokem
rodič
revize
e311b7f9b4

+ 36 - 22
examcloud-core-oe-student-service/src/main/java/cn/com/qmth/examcloud/core/oe/student/service/impl/ExamFaceLiveVerifyServiceImpl.java

@@ -91,26 +91,31 @@ public class ExamFaceLiveVerifyServiceImpl implements ExamFaceLiveVerifyService
         }
 
         // 是否考中活体不通过强制退出
-        ExamPropertyCacheBean examProperty = CacheHelper.getExamProperty(examRecordData.getExamId(), ExamProperties.FACE_VERIFY_FORCE_EXIT.name());
+        ExamPropertyCacheBean examProperty = CacheHelper.getExamProperty(examRecordData.getExamId(),
+                ExamProperties.FACE_VERIFY_FORCE_EXIT.name());
         boolean isFaceVerifyForceExit = examProperty != null && StringUtil.isTrue(examProperty.getValue());
 
         FaceLiveVerifyInfo info = new FaceLiveVerifyInfo();
-        info.setTimes(finishCount);
+        info.setTimes(finishCount + 1);
         info.setHasSuccess(hasSuccess);
 
         if (!isFaceVerifyForceExit && finishCount == 1) {
             // 若“考中活体不通过强制退出为false”,则首次活体不通过时,不结束考试继续作答,也不再次活体检测
-            log.warn("[pcClient]活检已完成{}次,考中活体不通过强制退出未开启,不再继续活检!studentId:{} examRecordDataId:{} ", finishCount, studentId, examRecordDataId);
+            log.warn(
+                    "[pcClient]活检已完成{}次,考中活体不通过强制退出未开启,不再继续活检!studentId:{} examRecordDataId:{} ",
+                    finishCount, studentId, examRecordDataId);
             return info;
         }
 
         if (finishCount > 1) {
-            log.warn("[pcClient]活检已完成{}次,当前限制2次机会!studentId:{} examRecordDataId:{} ", finishCount, studentId, examRecordDataId);
+            log.warn("[pcClient]活检已完成{}次,当前限制2次机会!studentId:{} examRecordDataId:{} ", finishCount,
+                    studentId, examRecordDataId);
             return info;
         }
 
         if (hasSuccess) {
-            log.warn("[pcClient]活检已完成{}次,已成功过,不再继续活检!studentId:{} examRecordDataId:{} ", finishCount, studentId, examRecordDataId);
+            log.warn("[pcClient]活检已完成{}次,已成功过,不再继续活检!studentId:{} examRecordDataId:{} ", finishCount,
+                    studentId, examRecordDataId);
             return info;
         }
 
@@ -122,15 +127,14 @@ public class ExamFaceLiveVerifyServiceImpl implements ExamFaceLiveVerifyService
             entity.setStatus(FaceLiveVerifyStatus.ERROR);
             examFaceLiveVerifyRepo.save(entity);
             faceLiveVerifyId = entity.getId();
-            finishCount++;
         }
         info.setFaceLiveVerifyId(faceLiveVerifyId);
-        info.setTimes(finishCount);
 
         Integer startMinute = this.calculateStartFaceVerifyMinute(examRecordDataId);
         info.setStartMinute(startMinute);
 
-        log.warn("[pcClient]活检开始,当前第{}次!studentId:{} examRecordDataId:{}", finishCount, studentId, examRecordDataId);
+        log.warn("[pcClient]活检开始,当前第{}次!studentId:{} examRecordDataId:{}", info.getTimes(), studentId,
+                examRecordDataId);
         return info;
     }
 
@@ -144,30 +148,35 @@ public class ExamFaceLiveVerifyServiceImpl implements ExamFaceLiveVerifyService
 
         ExamRecordData examRecordData = examRecordDataService.getExamRecordDataCache(req.getExamRecordDataId());
         if (examRecordData == null || ExamRecordStatus.EXAM_ING != examRecordData.getExamRecordStatus()) {
-            log.warn("保存活检结果,考试记录无效!studentId:{} examRecordDataId:{}", req.getStudentId(), req.getExamRecordDataId());
+            log.warn("保存活检结果失败,考试记录无效!studentId:{} examRecordDataId:{} faceLiveVerifyId:{}",
+                    req.getStudentId(), req.getExamRecordDataId(), req.getFaceLiveVerifyId());
             return;
         }
 
         ExamingSession examingSession = examingSessionService.getExamingSession(req.getStudentId());
         if (examingSession == null || ExamingStatus.INFORMAL.equals(examingSession.getExamingStatus())) {
-            log.warn("保存活检结果,考试会话已过期!studentId:{} examRecordDataId:{}", req.getStudentId(), req.getExamRecordDataId());
+            log.warn("保存活检结果失败,考试会话已过期!studentId:{} examRecordDataId:{} faceLiveVerifyId:{}",
+                    req.getStudentId(), req.getExamRecordDataId(), req.getFaceLiveVerifyId());
             return;
         }
 
         Optional<ExamFaceLiveVerifyEntity> optional = examFaceLiveVerifyRepo.findById(req.getFaceLiveVerifyId());
         if (!optional.isPresent()) {
-            log.warn("当前活检记录不存在!examRecordDataId:{} faceLiveVerifyId:{}", req.getExamRecordDataId(), req.getFaceLiveVerifyId());
+            log.warn("保存活检结果失败,活检记录ID无效!studentId:{} examRecordDataId:{} faceLiveVerifyId:{}",
+                    req.getStudentId(), req.getExamRecordDataId(), req.getFaceLiveVerifyId());
             return;
         }
 
         ExamFaceLiveVerifyEntity entity = optional.get();
         if (entity.getFinished()) {
-            log.warn("当前活检记录已完成,跳过重复保存!examRecordDataId:{} faceLiveVerifyId:{}", req.getExamRecordDataId(), req.getFaceLiveVerifyId());
+            log.warn("保存活检结果失败,跳过重复保存!studentId:{} examRecordDataId:{} faceLiveVerifyId:{}",
+                    req.getStudentId(), req.getExamRecordDataId(), req.getFaceLiveVerifyId());
             return;
         }
 
         // 是否考中活体不通过强制退出
-        ExamPropertyCacheBean examProperty = CacheHelper.getExamProperty(examRecordData.getExamId(), ExamProperties.FACE_VERIFY_FORCE_EXIT.name());
+        ExamPropertyCacheBean examProperty = CacheHelper.getExamProperty(examRecordData.getExamId(),
+                ExamProperties.FACE_VERIFY_FORCE_EXIT.name());
         boolean isFaceVerifyForceExit = examProperty != null && StringUtil.isTrue(examProperty.getValue());
 
         entity.setFinished(true);
@@ -181,15 +190,18 @@ public class ExamFaceLiveVerifyServiceImpl implements ExamFaceLiveVerifyService
         entity.setUpdateTime(new Date());
         examFaceLiveVerifyRepo.save(entity);
 
-        examRecordData.setFaceVerifyResult(FaceLiveVerifyStatus.SUCCESS == req.getStatus() ? IsSuccess.SUCCESS : IsSuccess.FAILED);
+        examRecordData.setFaceVerifyResult(
+                FaceLiveVerifyStatus.SUCCESS == req.getStatus() ? IsSuccess.SUCCESS : IsSuccess.FAILED);
         if (isFaceVerifyForceExit && FaceLiveVerifyStatus.SUCCESS != req.getStatus()) {
             // 强制活检 且 活检失败,则认为违纪
             examRecordData.setIsIllegality(true);
         }
         examRecordDataService.saveExamRecordDataCache(req.getExamRecordDataId(), examRecordData);
 
-        log.warn("[pcClient]保存活检结果!examRecordDataId:{} faceLiveVerifyId:{} status:{} isIllegality:{} isFaceVerifyForceExit:{}",
-                req.getExamRecordDataId(), req.getFaceLiveVerifyId(), req.getStatus(), examRecordData.getIsIllegality(), isFaceVerifyForceExit);
+        log.warn(
+                "[pcClient]保存活检结果!examRecordDataId:{} faceLiveVerifyId:{} status:{} isIllegality:{} isFaceVerifyForceExit:{}",
+                req.getExamRecordDataId(), req.getFaceLiveVerifyId(), req.getStatus(), examRecordData.getIsIllegality(),
+                isFaceVerifyForceExit);
     }
 
     @Override
@@ -200,7 +212,8 @@ public class ExamFaceLiveVerifyServiceImpl implements ExamFaceLiveVerifyService
         }
 
         //开启了人脸检测
-        if (!FaceBiopsyHelper.isFaceVerify(examRecordData.getRootOrgId(), examRecordData.getExamId(), examRecordData.getStudentId())) {
+        if (!FaceBiopsyHelper.isFaceVerify(examRecordData.getRootOrgId(), examRecordData.getExamId(),
+                examRecordData.getStudentId())) {
             //如果未开启人脸活体检测,则返回null
             return null;
         }
@@ -211,12 +224,12 @@ public class ExamFaceLiveVerifyServiceImpl implements ExamFaceLiveVerifyService
         }
 
         // 活体检测开始分钟数
-        int faceVerifyStartMinute = this.getExamPropertyValue(examRecordData.getExamId(),
-                examRecordData.getStudentId(), ExamProperties.FACE_VERIFY_START_MINUTE);
+        int faceVerifyStartMinute = this.getExamPropertyValue(examRecordData.getExamId(), examRecordData.getStudentId(),
+                ExamProperties.FACE_VERIFY_START_MINUTE);
 
         // 活体检测结束分钟数(默认 <= 交卷冻结时间)
-        int faceVerifyEndMinute = this.getExamPropertyValue(examRecordData.getExamId(),
-                examRecordData.getStudentId(), ExamProperties.FACE_VERIFY_END_MINUTE);
+        int faceVerifyEndMinute = this.getExamPropertyValue(examRecordData.getExamId(), examRecordData.getStudentId(),
+                ExamProperties.FACE_VERIFY_END_MINUTE);
 
         String examingHeartbeatKey = RedisKeyHelper.getBuilder().examingHeartbeatKey(examRecordDataId);
         ExamingHeartbeat examingHeartbeat = redisClient.get(examingHeartbeatKey, ExamingHeartbeat.class);
@@ -243,7 +256,8 @@ public class ExamFaceLiveVerifyServiceImpl implements ExamFaceLiveVerifyService
     }
 
     private int getExamPropertyValue(Long examId, Long studentId, ExamProperties propKey) {
-        ExamPropertyCacheBean property = ExamCacheTransferHelper.getCachedExamProperty(examId, studentId, propKey.name());
+        ExamPropertyCacheBean property = ExamCacheTransferHelper.getCachedExamProperty(examId, studentId,
+                propKey.name());
         if (property == null || StringUtils.isEmpty(property.getValue())) {
             throw new StatusException(propKey.getDesc() + "未设置");
         }

+ 51 - 40
examcloud-core-oe-student-service/src/main/java/cn/com/qmth/examcloud/core/oe/student/service/impl/ExamRecordDataServiceImpl.java

@@ -98,15 +98,9 @@ public class ExamRecordDataServiceImpl implements ExamRecordDataService {
 
     @Transactional
     @Override
-    public ExamRecordData createExamRecordData(ExamingSession examingSession,
-                                               ExamSettingsCacheBean examBean,
-                                               CourseCacheBean courseBean,
-                                               String basePaperId,
-                                               boolean isFullyObjective,
-                                               Long examStageId,
-                                               Integer examStageOrder,
-                                               boolean randomPaper,
-                                               double paperScore) {
+    public ExamRecordData createExamRecordData(ExamingSession examingSession, ExamSettingsCacheBean examBean,
+            CourseCacheBean courseBean, String basePaperId, boolean isFullyObjective, Long examStageId,
+            Integer examStageOrder, boolean randomPaper, double paperScore) {
         ExamRecordDataEntity examRecordData = new ExamRecordDataEntity();
         examRecordData.setExamId(examBean.getId());
         examRecordData.setExamType(ExamType.valueOf(examBean.getExamType()));
@@ -162,7 +156,8 @@ public class ExamRecordDataServiceImpl implements ExamRecordDataService {
         //存入redis
         saveExamRecordDataCache(examRecordData.getId(), bean);
 
-        log.warn("createExamRecordData success! studentId:{}, examRecordDataId:{}", examRecordData.getStudentId(), examRecordData.getId());
+        log.warn("createExamRecordData success! studentId:{}, examRecordDataId:{}", examRecordData.getStudentId(),
+                examRecordData.getId());
         return bean;
     }
 
@@ -308,7 +303,8 @@ public class ExamRecordDataServiceImpl implements ExamRecordDataService {
         }
 
         // 是否考中活体不通过强制退出
-        ExamPropertyCacheBean examProperty = CacheHelper.getExamProperty(examId, ExamProperties.FACE_VERIFY_FORCE_EXIT.name());
+        ExamPropertyCacheBean examProperty = CacheHelper.getExamProperty(examId,
+                ExamProperties.FACE_VERIFY_FORCE_EXIT.name());
         boolean isFaceVerifyForceExit = examProperty != null && StringUtil.isTrue(examProperty.getValue());
 
         if (examRecordData.getFaceVerifyResult() != null) {
@@ -322,7 +318,7 @@ public class ExamRecordDataServiceImpl implements ExamRecordDataService {
                 return new CalcFaceBiopsyResultResp(true, true, IsSuccess.FAILED);
             }
 
-            //否则判定为异常、不违纪
+            // 否则判定为异常、不违纪
             return new CalcFaceBiopsyResultResp(true, false, IsSuccess.FAILED);
         }
 
@@ -330,38 +326,51 @@ public class ExamRecordDataServiceImpl implements ExamRecordDataService {
         FaceBiopsyScheme faceBiopsyScheme = FaceBiopsyHelper.getFaceBiopsyScheme(rootOrgId);
         if (FaceBiopsyScheme.FACE_CLIENT == faceBiopsyScheme) {
             // S3 C端活体检测方案
-            List<ExamFaceLiveVerifyEntity> verifies = examFaceLiveVerifyRepo.findByExamRecordDataId(examRecordData.getId());
+            List<ExamFaceLiveVerifyEntity> verifies = examFaceLiveVerifyRepo.findByExamRecordDataIdAndFinished(
+                    examRecordData.getId(), true);
 
-            if (!CollectionUtils.isEmpty(verifies)) {
-                // 最后一次活检成功,则认为成功
-                ExamFaceLiveVerifyEntity lastVerify = verifies.stream().max((a, b) -> {
-                    if (a.getId() > b.getId()) {
-                        return 1;
-                    }
-                    return -1;
-                }).get();
-                if (lastVerify.getStatus() != null && FaceLiveVerifyStatus.SUCCESS == lastVerify.getStatus()) {
-                    return new CalcFaceBiopsyResultResp(IsSuccess.SUCCESS);
+            if (CollectionUtils.isEmpty(verifies)) {
+                // 尚未做过活检,不作为违纪或异常。
+                return new CalcFaceBiopsyResultResp();
+            }
+
+            // 最后一次活检成功,则认为成功
+            ExamFaceLiveVerifyEntity lastVerify = verifies.stream().max((a, b) -> {
+                if (a.getId() > b.getId()) {
+                    return 1;
                 }
+                return -1;
+            }).get();
+            if (lastVerify.getStatus() != null && FaceLiveVerifyStatus.SUCCESS == lastVerify.getStatus()) {
+                return new CalcFaceBiopsyResultResp(IsSuccess.SUCCESS);
             }
         } else if (faceBiopsyScheme == FaceBiopsyScheme.FACE_MOTION) {
             // S2 自研活体检测方案
             FaceBiopsyEntity lastVerify = faceBiopsyRepo.findByExamRecordDataId(examRecordData.getId());
 
-            //如果活检结果最终为true,只需要更新活检状态即可
-            if (lastVerify != null && lastVerify.getResult() != null && lastVerify.getResult()) {
+            if (lastVerify == null) {
+                // 尚未做过活检,不作为违纪或异常。
+                return new CalcFaceBiopsyResultResp();
+            }
+
+            if (lastVerify.getResult() != null && lastVerify.getResult()) {
                 return new CalcFaceBiopsyResultResp(IsSuccess.SUCCESS);
             }
         } else {
             // S1 FaceID活体检测方案
-            List<ExamFaceLivenessVerifyEntity> verifies = examFaceLivenessVerifyRepo.findByExamRecordDataIdOrderById(examRecordData.getId());
+            List<ExamFaceLivenessVerifyEntity> verifies = examFaceLivenessVerifyRepo.findByExamRecordDataIdOrderById(
+                    examRecordData.getId());
 
-            if (!CollectionUtils.isEmpty(verifies)) {
-                // 最后一次活检成功,则认为成功
-                ExamFaceLivenessVerifyEntity lastVerify = verifies.get(verifies.size() - 1);
-                if (lastVerify.getVerifyResult() != null && FaceVerifyResult.VERIFY_SUCCESS == lastVerify.getVerifyResult()) {
-                    return new CalcFaceBiopsyResultResp(IsSuccess.SUCCESS);
-                }
+            if (CollectionUtils.isEmpty(verifies)) {
+                // 尚未做过活检,不作为违纪或异常。
+                return new CalcFaceBiopsyResultResp();
+            }
+
+            // 最后一次活检成功,则认为成功
+            ExamFaceLivenessVerifyEntity lastVerify = verifies.get(verifies.size() - 1);
+            if (lastVerify.getVerifyResult() != null
+                    && FaceVerifyResult.VERIFY_SUCCESS == lastVerify.getVerifyResult()) {
+                return new CalcFaceBiopsyResultResp(IsSuccess.SUCCESS);
             }
         }
 
@@ -370,7 +379,7 @@ public class ExamRecordDataServiceImpl implements ExamRecordDataService {
             return new CalcFaceBiopsyResultResp(true, true, IsSuccess.FAILED);
         }
 
-        //否则判定为异常、不违纪(包含未做活体情况)
+        // 否则判定为异常、不违纪
         return new CalcFaceBiopsyResultResp(true, false, IsSuccess.FAILED);
     }
 
@@ -383,7 +392,8 @@ public class ExamRecordDataServiceImpl implements ExamRecordDataService {
             long startTime = System.currentTimeMillis();
 
             // 考生作答记录明细
-            ExamRecordQuestions examRecordQuestions = examRecordQuestionsService.getExamRecordQuestions(req.getExamRecordDataId());
+            ExamRecordQuestions examRecordQuestions = examRecordQuestionsService.getExamRecordQuestions(
+                    req.getExamRecordDataId());
 
             double objectiveScore = 0d; // 客观题得分
             int totalObjective = 0; // 客观题总数
@@ -423,7 +433,8 @@ public class ExamRecordDataServiceImpl implements ExamRecordDataService {
             // 计算客观题答题正确率
             double objectiveAccuracy = 0;
             if (totalRightObjective > 0 && totalObjective > 0) {
-                objectiveAccuracy = Double.parseDouble(new DecimalFormat("#.00").format(totalRightObjective * 100D / totalObjective));
+                objectiveAccuracy = Double.parseDouble(
+                        new DecimalFormat("#.00").format(totalRightObjective * 100D / totalObjective));
             }
 
             CalcExamScoreResp resp = new CalcExamScoreResp();
@@ -491,12 +502,12 @@ public class ExamRecordDataServiceImpl implements ExamRecordDataService {
     /**
      * 更新客观题答案
      */
-    private void updateCorrectAnswer(Long examRecordDataId, List<ExamQuestion> examQuestions, ExamQuestion examQuestion) {
+    private void updateCorrectAnswer(Long examRecordDataId, List<ExamQuestion> examQuestions,
+            ExamQuestion examQuestion) {
         // 按题号由小到大提取相同题ID的小题列表(注:套题的子题ID相同)
-        List<ExamQuestion> questionUnits = examQuestions.stream().
-                filter(e -> e.getQuestionId().equals(examQuestion.getQuestionId())).
-                sorted(Comparator.comparingInt(ExamQuestion::getOrder))
-                .collect(Collectors.toList());
+        List<ExamQuestion> questionUnits = examQuestions.stream()
+                .filter(e -> e.getQuestionId().equals(examQuestion.getQuestionId()))
+                .sorted(Comparator.comparingInt(ExamQuestion::getOrder)).collect(Collectors.toList());
 
         // 获取当前题的正确答案
         QuestionAnswerCacheBean questionAnswerCache = CacheHelper.getQuestionAnswer(examQuestion.getQuestionId());