|
@@ -3,6 +3,7 @@ package cn.com.qmth.examcloud.core.oe.student.service.impl;
|
|
|
import cn.com.qmth.examcloud.commons.exception.StatusException;
|
|
|
import cn.com.qmth.examcloud.commons.util.JsonMapper;
|
|
|
import cn.com.qmth.examcloud.core.oe.student.base.utils.Check;
|
|
|
+import cn.com.qmth.examcloud.core.oe.student.base.utils.CommonUtil;
|
|
|
import cn.com.qmth.examcloud.core.oe.student.bean.client.FaceLiveVerifyInfo;
|
|
|
import cn.com.qmth.examcloud.core.oe.student.bean.client.FaceLiveVerifyResult;
|
|
|
import cn.com.qmth.examcloud.core.oe.student.dao.ExamFaceLiveVerifyRepo;
|
|
@@ -11,10 +12,18 @@ import cn.com.qmth.examcloud.core.oe.student.dao.enums.FaceLiveVerifyStatus;
|
|
|
import cn.com.qmth.examcloud.core.oe.student.service.ExamFaceLiveVerifyService;
|
|
|
import cn.com.qmth.examcloud.core.oe.student.service.ExamRecordDataService;
|
|
|
import cn.com.qmth.examcloud.core.oe.student.service.ExamingSessionService;
|
|
|
+import cn.com.qmth.examcloud.support.Constants;
|
|
|
+import cn.com.qmth.examcloud.support.cache.bean.ExamPropertyCacheBean;
|
|
|
+import cn.com.qmth.examcloud.support.enums.ExamProperties;
|
|
|
import cn.com.qmth.examcloud.support.enums.ExamRecordStatus;
|
|
|
import cn.com.qmth.examcloud.support.enums.IsSuccess;
|
|
|
import cn.com.qmth.examcloud.support.examing.ExamRecordData;
|
|
|
+import cn.com.qmth.examcloud.support.examing.ExamingHeartbeat;
|
|
|
import cn.com.qmth.examcloud.support.examing.ExamingSession;
|
|
|
+import cn.com.qmth.examcloud.support.helper.ExamCacheTransferHelper;
|
|
|
+import cn.com.qmth.examcloud.support.redis.RedisKeyHelper;
|
|
|
+import cn.com.qmth.examcloud.web.redis.RedisClient;
|
|
|
+import org.apache.commons.lang3.StringUtils;
|
|
|
import org.slf4j.Logger;
|
|
|
import org.slf4j.LoggerFactory;
|
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
@@ -37,6 +46,9 @@ public class ExamFaceLiveVerifyServiceImpl implements ExamFaceLiveVerifyService
|
|
|
@Autowired
|
|
|
private ExamFaceLiveVerifyRepo examFaceLiveVerifyRepo;
|
|
|
|
|
|
+ @Autowired
|
|
|
+ private RedisClient redisClient;
|
|
|
+
|
|
|
@Override
|
|
|
public FaceLiveVerifyInfo startFaceLiveVerify(Long examRecordDataId, Long studentId) {
|
|
|
Check.isNull(studentId, "学生ID不能为空");
|
|
@@ -119,8 +131,54 @@ public class ExamFaceLiveVerifyServiceImpl implements ExamFaceLiveVerifyService
|
|
|
|
|
|
@Override
|
|
|
public Integer calculateStartFaceVerifyMinute(Long examRecordDataId) {
|
|
|
- // todo
|
|
|
- return 1;
|
|
|
+ ExamRecordData examRecordData = examRecordDataService.getExamRecordDataCache(examRecordDataId);
|
|
|
+ if (examRecordData == null || ExamRecordStatus.EXAM_ING != examRecordData.getExamRecordStatus()) {
|
|
|
+ throw new StatusException("考试记录无效");
|
|
|
+ }
|
|
|
+
|
|
|
+ ExamingSession examingSession = examingSessionService.getExamingSession(examRecordData.getStudentId());
|
|
|
+ if (examingSession == null) {
|
|
|
+ throw new StatusException("考试会话已过期");
|
|
|
+ }
|
|
|
+
|
|
|
+ // 活体检测开始分钟数
|
|
|
+ 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);
|
|
|
+
|
|
|
+ String examingHeartbeatKey = RedisKeyHelper.getBuilder().examingHeartbeatKey(examRecordDataId);
|
|
|
+ ExamingHeartbeat examingHeartbeat = redisClient.get(examingHeartbeatKey, ExamingHeartbeat.class);
|
|
|
+
|
|
|
+ // 考试已用时间
|
|
|
+ int usedMinute = 0;
|
|
|
+ if (examingHeartbeat != null) {
|
|
|
+ usedMinute = Math.toIntExact(examingHeartbeat.getCost() / 60L);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (usedMinute < faceVerifyStartMinute) {
|
|
|
+ // 考试已用时间 尚未达到 配置的活体检测开始分钟数时,结果 = Random(开始分钟数-结束分钟数)-考试已用时间
|
|
|
+ return CommonUtil.calculationRandomNumber(faceVerifyStartMinute, faceVerifyEndMinute) - usedMinute;
|
|
|
+ } else if (usedMinute >= faceVerifyStartMinute && usedMinute < faceVerifyEndMinute) {
|
|
|
+ // 考试已用时间 介于 配置的活体检测开始和结束分钟数中间时,结果 = Random(考试已用时间-结束分钟数)-考试已用时间,默认最小1分钟
|
|
|
+ int faceVerifyMinute = CommonUtil.calculationRandomNumber(usedMinute, faceVerifyEndMinute) - usedMinute;
|
|
|
+ return faceVerifyMinute > 1 ? faceVerifyMinute : 1;
|
|
|
+ } else if (usedMinute >= faceVerifyEndMinute) {
|
|
|
+ // 考试已用时间 大于 配置的活体检测结束分钟数时,结果 = Random(1,4)
|
|
|
+ return CommonUtil.calculationRandomNumber(1, Constants.MAX_FACE_LIVE_VERIFY_MINUTE);
|
|
|
+ }
|
|
|
+
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+ private int getExamPropertyValue(Long examId, Long studentId, ExamProperties propKey) {
|
|
|
+ ExamPropertyCacheBean property = ExamCacheTransferHelper.getCachedExamProperty(examId, studentId, propKey.name());
|
|
|
+ if (property == null || StringUtils.isEmpty(property.getValue())) {
|
|
|
+ throw new StatusException(propKey.getDesc() + "未设置");
|
|
|
+ }
|
|
|
+ return Integer.parseInt(property.getValue());
|
|
|
}
|
|
|
|
|
|
}
|