Просмотр исходного кода

完善新活体检测接口代码

lideyin 5 лет назад
Родитель
Сommit
f75cea1480

+ 10 - 11
examcloud-core-oe-student-api-provider/src/main/java/cn/com/qmth/examcloud/core/oe/student/controller/FaceBiopsyController.java

@@ -4,21 +4,18 @@ import cn.com.qmth.examcloud.api.commons.security.bean.User;
 import cn.com.qmth.examcloud.commons.exception.StatusException;
 import cn.com.qmth.examcloud.core.oe.common.base.Constants;
 import cn.com.qmth.examcloud.core.oe.common.entity.ExamRecordDataEntity;
-import cn.com.qmth.examcloud.core.oe.common.entity.FaceBiopsyEntity;
-import cn.com.qmth.examcloud.core.oe.common.entity.FaceBiopsyItemEntity;
-import cn.com.qmth.examcloud.core.oe.common.entity.FaceBiopsyItemStepEntity;
+import cn.com.qmth.examcloud.core.oe.common.enums.ExamProperties;
 import cn.com.qmth.examcloud.core.oe.common.enums.FaceBiopsyType;
 import cn.com.qmth.examcloud.core.oe.common.repository.ExamRecordDataRepo;
 import cn.com.qmth.examcloud.core.oe.common.repository.FaceBiopsyItemRepo;
 import cn.com.qmth.examcloud.core.oe.common.repository.FaceBiopsyItemStepRepo;
-import cn.com.qmth.examcloud.core.oe.common.repository.FaceBiopsyRepo;
 import cn.com.qmth.examcloud.core.oe.student.bean.ExamSessionInfo;
 import cn.com.qmth.examcloud.core.oe.student.bean.FaceBiopsyInfo;
-import cn.com.qmth.examcloud.core.oe.student.bean.FaceBiopsyStepInfo;
-import cn.com.qmth.examcloud.core.oe.student.bean.SaveFaceBiopsyResultResp;
 import cn.com.qmth.examcloud.core.oe.student.bean.SaveFaceBiopsyResultReq;
+import cn.com.qmth.examcloud.core.oe.student.bean.SaveFaceBiopsyResultResp;
 import cn.com.qmth.examcloud.core.oe.student.service.ExamSessionInfoService;
 import cn.com.qmth.examcloud.core.oe.student.service.FaceBiopsyService;
+import cn.com.qmth.examcloud.support.cache.CacheHelper;
 import cn.com.qmth.examcloud.web.helpers.GlobalHelper;
 import cn.com.qmth.examcloud.web.helpers.SequenceLockHelper;
 import cn.com.qmth.examcloud.web.support.ControllerSupport;
@@ -27,9 +24,6 @@ import io.swagger.annotations.ApiOperation;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.*;
 
-import java.util.ArrayList;
-import java.util.List;
-
 /**
  * @Description 人脸活体检测接口
  * @Author lideyin
@@ -45,8 +39,6 @@ public class FaceBiopsyController extends ControllerSupport {
     @Autowired
     private FaceBiopsyService faceBiopsyService;
     @Autowired
-    private FaceBiopsyRepo faceBiopsyRepo;
-    @Autowired
     private FaceBiopsyItemRepo faceBiopsyItemRepo;
     @Autowired
     private FaceBiopsyItemStepRepo faceBiopsyItemStepRepo;
@@ -75,6 +67,13 @@ public class FaceBiopsyController extends ControllerSupport {
             throw new StatusException("200102", "考试会话已过期");
         }
 
+        //考试未开启人脸活体检测,不允许获取活检信息
+        String isFaceVerifyStr = CacheHelper.getExamOrgProperty(examRecordData.getExamId(), examRecordData.getOrgId(),
+                ExamProperties.IS_FACE_VERIFY.name()).getValue();
+        if (!Constants.isTrue.equals(isFaceVerifyStr)) {
+            throw new StatusException("200103", "本场考试未开启人脸活体检测");
+        }
+
         return faceBiopsyService.getFaceBiopsyInfo(user.getRootOrgId(), examRecordDataId, FaceBiopsyType.FACE_MOTION);
     }
 

+ 25 - 25
examcloud-core-oe-student-service/src/main/java/cn/com/qmth/examcloud/core/oe/student/bean/FaceBiopsyInfo.java

@@ -13,38 +13,38 @@ import java.util.List;
  * @Version 1.0
  */
 public class FaceBiopsyInfo implements JsonSerializable {
-	private static final long serialVersionUID = -8323306595159483818L;
+    private static final long serialVersionUID = -8323306595159483818L;
 
-	@ApiModelProperty(value = "活体检测开始时间",required = true)
-	private Date startTime;
+    @ApiModelProperty(value = "活体检测开始分钟数", required = true)
+    private Integer faceVerifyMinute;
 
-	@ApiModelProperty(value = "人脸活体检测明细id",required = true)
-	private Long faceBiopsyItemId;
+    @ApiModelProperty(value = "人脸活体检测明细id", required = true)
+    private Long faceBiopsyItemId;
 
-	@ApiModelProperty(value = "人脸活体检测步骤",required = true)
-	private List<FaceBiopsyStepInfo>  verifySteps;
+    @ApiModelProperty(value = "人脸活体检测步骤", required = true)
+    private List<FaceBiopsyStepInfo> verifySteps;
 
-	public Date getStartTime() {
-		return startTime;
-	}
+    public Integer getFaceVerifyMinute() {
+        return faceVerifyMinute;
+    }
 
-	public void setStartTime(Date startTime) {
-		this.startTime = startTime;
-	}
+    public void setFaceVerifyMinute(Integer faceVerifyMinute) {
+        this.faceVerifyMinute = faceVerifyMinute;
+    }
 
-	public Long getFaceBiopsyItemId() {
-		return faceBiopsyItemId;
-	}
+    public Long getFaceBiopsyItemId() {
+        return faceBiopsyItemId;
+    }
 
-	public void setFaceBiopsyItemId(Long faceBiopsyItemId) {
-		this.faceBiopsyItemId = faceBiopsyItemId;
-	}
+    public void setFaceBiopsyItemId(Long faceBiopsyItemId) {
+        this.faceBiopsyItemId = faceBiopsyItemId;
+    }
 
-	public List<FaceBiopsyStepInfo> getVerifySteps() {
-		return verifySteps;
-	}
+    public List<FaceBiopsyStepInfo> getVerifySteps() {
+        return verifySteps;
+    }
 
-	public void setVerifySteps(List<FaceBiopsyStepInfo> verifySteps) {
-		this.verifySteps = verifySteps;
-	}
+    public void setVerifySteps(List<FaceBiopsyStepInfo> verifySteps) {
+        this.verifySteps = verifySteps;
+    }
 }

+ 136 - 16
examcloud-core-oe-student-service/src/main/java/cn/com/qmth/examcloud/core/oe/student/service/impl/FaceBiopsyServiceImpl.java

@@ -1,17 +1,25 @@
 package cn.com.qmth.examcloud.core.oe.student.service.impl;
 
 import cn.com.qmth.examcloud.commons.exception.StatusException;
+import cn.com.qmth.examcloud.core.oe.common.base.Constants;
+import cn.com.qmth.examcloud.core.oe.common.base.utils.CommonUtil;
+import cn.com.qmth.examcloud.core.oe.common.entity.ExamRecordDataEntity;
 import cn.com.qmth.examcloud.core.oe.common.entity.FaceBiopsyEntity;
 import cn.com.qmth.examcloud.core.oe.common.entity.FaceBiopsyItemEntity;
 import cn.com.qmth.examcloud.core.oe.common.entity.FaceBiopsyItemStepEntity;
+import cn.com.qmth.examcloud.core.oe.common.enums.ExamProperties;
 import cn.com.qmth.examcloud.core.oe.common.enums.FaceBiopsyAction;
 import cn.com.qmth.examcloud.core.oe.common.enums.FaceBiopsyType;
+import cn.com.qmth.examcloud.core.oe.common.repository.ExamRecordDataRepo;
 import cn.com.qmth.examcloud.core.oe.common.repository.FaceBiopsyItemRepo;
 import cn.com.qmth.examcloud.core.oe.common.repository.FaceBiopsyItemStepRepo;
 import cn.com.qmth.examcloud.core.oe.common.repository.FaceBiopsyRepo;
+import cn.com.qmth.examcloud.core.oe.student.bean.ExamSessionInfo;
 import cn.com.qmth.examcloud.core.oe.student.bean.FaceBiopsyInfo;
 import cn.com.qmth.examcloud.core.oe.student.bean.FaceBiopsyStepInfo;
+import cn.com.qmth.examcloud.core.oe.student.service.ExamSessionInfoService;
 import cn.com.qmth.examcloud.core.oe.student.service.FaceBiopsyService;
+import cn.com.qmth.examcloud.support.cache.CacheHelper;
 import cn.com.qmth.examcloud.web.bootstrap.PropertyHolder;
 import cn.com.qmth.examcloud.web.helpers.GlobalHelper;
 import org.apache.commons.lang3.RandomUtils;
@@ -19,11 +27,8 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
-import java.util.Date;
-import java.util.List;
-
 import java.util.ArrayList;
-import java.util.Random;
+import java.util.List;
 
 /**
  * @Description 人脸活体检测接口实现类
@@ -40,9 +45,14 @@ public class FaceBiopsyServiceImpl implements FaceBiopsyService {
     private FaceBiopsyItemRepo faceBiopsyItemRepo;
     @Autowired
     private FaceBiopsyItemStepRepo faceBiopsyItemStepRepo;
+    @Autowired
+    private ExamRecordDataRepo examRecordDataRepo;
+    @Autowired
+    private ExamSessionInfoService examSessionInfoService;
 
     @Override
     public FaceBiopsyInfo getFaceBiopsyInfo(Long rootOrgId, Long examRecordDataId, FaceBiopsyType faceBiopsyType) {
+
         //如果是第一次进行人脸活体检测,则初始化相关信息保存并返回
         FaceBiopsyEntity faceBiopsyEntity = faceBiopsyRepo.findByExamRecordDataId(examRecordDataId);
         if (faceBiopsyEntity == null) {
@@ -59,7 +69,7 @@ public class FaceBiopsyServiceImpl implements FaceBiopsyService {
         if (unCompletedFaceBiopsyItemList != null && !unCompletedFaceBiopsyItemList.isEmpty()) {
             FaceBiopsyItemEntity faceBiopsyItemEntity = unCompletedFaceBiopsyItemList.get(0);
             result.setFaceBiopsyItemId(faceBiopsyItemEntity.getId());
-            result.setStartTime(calculateFaceBiopsyStartTime(examRecordDataId));
+            result.setFaceVerifyMinute(calculateFaceBiopsyStartMinute(examRecordDataId, faceBiopsyEntity.getVerifiedTimes()));
 
             List<FaceBiopsyItemStepEntity> faceBiopsyItemStepEntityList =
                     faceBiopsyItemStepRepo.findByFaceBiopsyItemId(faceBiopsyItemEntity.getId());
@@ -78,7 +88,7 @@ public class FaceBiopsyServiceImpl implements FaceBiopsyService {
 
         //没有超过,则追加活检次数
         verifiedTimes++;
-        return appendFirstFaceBiopsy(faceBiopsyEntity.getId(), verifiedTimes, examRecordDataId, faceBiopsyType);
+        return appendFaceBiopsy(faceBiopsyEntity.getId(), verifiedTimes, examRecordDataId, faceBiopsyType);
     }
 
     /**
@@ -98,7 +108,7 @@ public class FaceBiopsyServiceImpl implements FaceBiopsyService {
                 addFaceBiopsyItemStepList(examRecordDataId, faceBiopsyItemId);
 
         //构建业务实体
-        return buildFaceBiopsyInfo(examRecordDataId, faceBiopsyItemId, faceBiopsyItemStepEntityList);
+        return buildFaceBiopsyInfo(examRecordDataId, faceBiopsyItemId, 1, faceBiopsyItemStepEntityList);
     }
 
     /**
@@ -111,8 +121,8 @@ public class FaceBiopsyServiceImpl implements FaceBiopsyService {
      * @return
      */
     @Transactional
-    public FaceBiopsyInfo appendFirstFaceBiopsy(Long faceBiopsyId, Integer verifiedTimes, Long examRecordDataId,
-                                                FaceBiopsyType faceBiopsyType) {
+    public FaceBiopsyInfo appendFaceBiopsy(Long faceBiopsyId, Integer verifiedTimes, Long examRecordDataId,
+                                           FaceBiopsyType faceBiopsyType) {
         //更新人脸活体检测次数
         FaceBiopsyEntity faceBiopsyEntity = GlobalHelper.getEntity(faceBiopsyRepo, faceBiopsyId, FaceBiopsyEntity.class);
         faceBiopsyEntity.setVerifiedTimes(verifiedTimes);
@@ -123,7 +133,7 @@ public class FaceBiopsyServiceImpl implements FaceBiopsyService {
         List<FaceBiopsyItemStepEntity> faceBiopsyItemStepEntityList =
                 addFaceBiopsyItemStepList(examRecordDataId, faceBiopsyItemId);
 
-        return buildFaceBiopsyInfo(examRecordDataId, faceBiopsyItemId, faceBiopsyItemStepEntityList);
+        return buildFaceBiopsyInfo(examRecordDataId, faceBiopsyItemId, verifiedTimes, faceBiopsyItemStepEntityList);
 
     }
 
@@ -135,11 +145,12 @@ public class FaceBiopsyServiceImpl implements FaceBiopsyService {
      * @param faceBiopsyItemStepEntityList
      * @return
      */
-    private FaceBiopsyInfo buildFaceBiopsyInfo(Long examRecordDataId, Long faceBiopsyItemId, List<FaceBiopsyItemStepEntity> faceBiopsyItemStepEntityList) {
+    private FaceBiopsyInfo buildFaceBiopsyInfo(Long examRecordDataId, Long faceBiopsyItemId, Integer verifyTimes,
+                                               List<FaceBiopsyItemStepEntity> faceBiopsyItemStepEntityList) {
         //构建业务实体
         FaceBiopsyInfo faceBiopsyInfo = new FaceBiopsyInfo();
         faceBiopsyInfo.setFaceBiopsyItemId(faceBiopsyItemId);
-        faceBiopsyInfo.setStartTime(calculateFaceBiopsyStartTime(examRecordDataId));
+        faceBiopsyInfo.setFaceVerifyMinute(calculateFaceBiopsyStartMinute(examRecordDataId, verifyTimes));
         faceBiopsyInfo.setVerifySteps(copyFaceBiopsyStepDomainListFrom(faceBiopsyItemStepEntityList));
         return faceBiopsyInfo;
     }
@@ -227,13 +238,122 @@ public class FaceBiopsyServiceImpl implements FaceBiopsyService {
 
 
     /**
-     * 计算人脸活体检测开始时间
+     * 计算人脸活体检测开始分钟数
      *
      * @param examRecordDataId 考试记录id
      * @return
      */
-    private Date calculateFaceBiopsyStartTime(Long examRecordDataId) {
-        //TODO
-        return null;
+    private Integer calculateFaceBiopsyStartMinute(Long examRecordDataId, Integer verifyTimes) {
+        ExamRecordDataEntity examRecordData = GlobalHelper.getEntity(examRecordDataRepo, examRecordDataId,
+                ExamRecordDataEntity.class);
+        Long examId = examRecordData.getExamId();
+        Long orgId = examRecordData.getOrgId();
+        Long studentId = examRecordData.getStudentId();
+
+        //再次校验是否开启人脸活体校验
+        String isFaceVerifyStr = CacheHelper.getExamOrgProperty(examId, orgId,
+                ExamProperties.IS_FACE_VERIFY.name()).getValue();
+
+        //如果未开启人脸活体检测,则返回null
+        if (!Constants.isTrue.equals(isFaceVerifyStr)) {
+            return null;
+        }
+
+        ExamSessionInfo examSessionInfo = examSessionInfoService.getExamSessionInfo(studentId);
+        if (examSessionInfo == null) {
+            throw new StatusException("201002", "考试会话已过期");
+        }
+
+        Integer heartbeat = examSessionInfo.getHeartbeat();
+        //如果冻结时间内,使用冻结时间内的计算方式
+        if (heartbeat < examSessionInfo.getFreezeTime()) {
+            return generateInFreezeTimeFaceBiopsyStartMinute(examId, orgId, heartbeat, verifyTimes);
+        }
+        //如果超过冻结时间则使用冻结时间外的计算方式
+        else {
+            return generateOutFreezeTimeFaceBiopsyStartMinute(examId, orgId, heartbeat);
+        }
+    }
+
+    /**
+     * 冻结时间内生成人脸活体检测的开始时间
+     *
+     * @param examId
+     * @param orgId
+     * @param heartbeat
+     * @param verifyTimes
+     * @return
+     */
+    private Integer generateInFreezeTimeFaceBiopsyStartMinute(Long examId, Long orgId, Integer heartbeat,
+                                                              Integer verifyTimes) {
+        //如果没有进行过人脸检测(即第一次活体检测)
+        if (verifyTimes == 1) {
+            String faceVerifyStartMinuteStr = CacheHelper.getExamOrgProperty(examId, orgId,
+                    ExamProperties.FACE_VERIFY_START_MINUTE.name()).getValue();
+            Integer faceVerifyStartMinute = Integer.valueOf(faceVerifyStartMinuteStr);
+
+            String faceVerifyEndMinuteStr = CacheHelper.getExamOrgProperty(examId, orgId,
+                    ExamProperties.FACE_VERIFY_END_MINUTE.name()).getValue();
+            Integer faceVerifyEndMinute = Integer.valueOf(faceVerifyEndMinuteStr);
+            //	case1.如果考生已使用的考试时间(即心跳时间)还未达到系统设置的活体检测开始时间,
+            //	则实际活体检测时间=random(配置结束时间-配置结束时间)-考试已用时间
+            if (heartbeat < faceVerifyStartMinute) {
+                return CommonUtil.calculationRandomNumber(faceVerifyStartMinute, faceVerifyEndMinute) - heartbeat;
+            }
+            //	case2如果配置开始时间<考生已使用的考试时间<配置结束时间,
+            //	则实际活体检测时间=random(配置结束时间-考试已用时间)-考试已用时间,如果结果小于1分钟则默认1分钟
+            else if (heartbeat >= faceVerifyStartMinute && heartbeat < faceVerifyEndMinute) {
+                int verifyTime = CommonUtil.calculationRandomNumber(heartbeat, faceVerifyEndMinute) - heartbeat;
+                return verifyTime < 1 ? 1 : verifyTime;
+            }
+            //case3如果考试已用时间>配置结束时间,则默认1分钟后开始人脸检测
+            else {
+                return 1;
+            }
+        }
+        //如果是第二次人脸
+        else {
+            return CommonUtil.calculationRandomNumber(
+                    PropertyHolder.getInt("oe.faceBiopsy.minSecondFaceCheckMinute", 1),
+                    PropertyHolder.getInt("oe.faceBiopsy.maxSecondFaceCheckMinute", 4));
+        }
+    }
+
+    /**
+     * 冻结时间外生成人脸活体检测的开始时间
+     *
+     * @return
+     */
+    private Integer generateOutFreezeTimeFaceBiopsyStartMinute(Long examId, Long orgId, Integer heartbeat) {
+        //冻结时间外是否添加活体检测
+        String addFaceVerifyOutFreezeTime = CacheHelper.getExamOrgProperty(examId, orgId,
+                ExamProperties.ADD_FACE_VERIFY_OUT_FREEZE_TIME.name()).getValue();
+        //如果冻结时间外不添加活体检测,则直接返回null
+        if (!Constants.isTrue.equals(addFaceVerifyOutFreezeTime)) {
+            return null;
+        }
+
+        String strOutFreezeTimeFaceVerifyStartMinute = CacheHelper.getExamOrgProperty(examId, orgId,
+                ExamProperties.OUT_FREEZE_TIME_FACE_VERIFY_START_MINUTE.name()).getValue();
+        Integer faceVerifyStartMinute = Integer.valueOf(strOutFreezeTimeFaceVerifyStartMinute);
+
+        String strOutFreezeTimeFaceVerifyEndMinute = CacheHelper.getExamOrgProperty(examId, orgId,
+                ExamProperties.OUT_FREEZE_TIME_FACE_VERIFY_END_MINUTE.name()).getValue();
+        Integer faceVerifyEndMinute = Integer.valueOf(strOutFreezeTimeFaceVerifyEndMinute);
+        //	case1.如果考生已使用的考试时间(即心跳时间)还未达到系统设置的活体检测开始时间,
+        //	则实际活体检测时间=random(配置结束时间-配置结束时间)-考试已用时间
+        if (heartbeat < faceVerifyStartMinute) {
+            return CommonUtil.calculationRandomNumber(faceVerifyStartMinute, faceVerifyEndMinute) - heartbeat;
+        }
+        //	case2如果配置开始时间<考生已使用的考试时间<配置结束时间,
+        //	则实际活体检测时间=random(配置结束时间-考试已用时间)-考试已用时间,如果结果小于1分钟则默认1分钟
+        else if (heartbeat >= faceVerifyStartMinute && heartbeat < faceVerifyEndMinute) {
+            int verifyTime = CommonUtil.calculationRandomNumber(heartbeat, faceVerifyEndMinute) - heartbeat;
+            return verifyTime < 1 ? 1 : verifyTime;
+        }
+        //case3如果考试已用时间>配置结束时间,则默认1分钟后开始人脸检测
+        else {
+            return 1;
+        }
     }
 }