|
@@ -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;
|
|
|
+ }
|
|
|
}
|
|
|
}
|