|
@@ -1,40 +1,5 @@
|
|
package cn.com.qmth.examcloud.core.oe.student.service.impl;
|
|
package cn.com.qmth.examcloud.core.oe.student.service.impl;
|
|
|
|
|
|
-import java.io.UnsupportedEncodingException;
|
|
|
|
-import java.net.URLEncoder;
|
|
|
|
-import java.text.SimpleDateFormat;
|
|
|
|
-import java.util.ArrayList;
|
|
|
|
-import java.util.Collections;
|
|
|
|
-import java.util.Comparator;
|
|
|
|
-import java.util.Date;
|
|
|
|
-import java.util.HashMap;
|
|
|
|
-import java.util.HashSet;
|
|
|
|
-import java.util.List;
|
|
|
|
-import java.util.Locale;
|
|
|
|
-import java.util.Map;
|
|
|
|
-import java.util.Random;
|
|
|
|
-import java.util.Set;
|
|
|
|
-import java.util.TimeZone;
|
|
|
|
-import java.util.concurrent.TimeUnit;
|
|
|
|
-import java.util.stream.Collectors;
|
|
|
|
-
|
|
|
|
-import javax.validation.Valid;
|
|
|
|
-
|
|
|
|
-import org.apache.commons.collections.CollectionUtils;
|
|
|
|
-import org.apache.commons.lang.math.RandomUtils;
|
|
|
|
-import org.apache.commons.lang3.StringUtils;
|
|
|
|
-import org.apache.commons.lang3.time.DateUtils;
|
|
|
|
-import org.apache.commons.logging.Log;
|
|
|
|
-import org.apache.commons.logging.LogFactory;
|
|
|
|
-import org.slf4j.Logger;
|
|
|
|
-import org.slf4j.LoggerFactory;
|
|
|
|
-import org.springframework.beans.factory.annotation.Autowired;
|
|
|
|
-import org.springframework.beans.factory.annotation.Value;
|
|
|
|
-import org.springframework.stereotype.Service;
|
|
|
|
-import org.springframework.transaction.annotation.Transactional;
|
|
|
|
-
|
|
|
|
-import com.google.common.base.Splitter;
|
|
|
|
-
|
|
|
|
import cn.com.qmth.examcloud.api.commons.security.bean.User;
|
|
import cn.com.qmth.examcloud.api.commons.security.bean.User;
|
|
import cn.com.qmth.examcloud.commons.exception.StatusException;
|
|
import cn.com.qmth.examcloud.commons.exception.StatusException;
|
|
import cn.com.qmth.examcloud.commons.util.ByteUtil;
|
|
import cn.com.qmth.examcloud.commons.util.ByteUtil;
|
|
@@ -45,56 +10,13 @@ import cn.com.qmth.examcloud.core.basic.api.bean.CourseBean;
|
|
import cn.com.qmth.examcloud.core.oe.common.base.Constants;
|
|
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.base.utils.CommonUtil;
|
|
import cn.com.qmth.examcloud.core.oe.common.base.utils.QuestionTypeUtil;
|
|
import cn.com.qmth.examcloud.core.oe.common.base.utils.QuestionTypeUtil;
|
|
-import cn.com.qmth.examcloud.core.oe.common.entity.ExamFileAnswerTempEntity;
|
|
|
|
-import cn.com.qmth.examcloud.core.oe.common.entity.ExamQuestionEntity;
|
|
|
|
-import cn.com.qmth.examcloud.core.oe.common.entity.ExamRecordDataEntity;
|
|
|
|
-import cn.com.qmth.examcloud.core.oe.common.entity.ExamRecordEntity;
|
|
|
|
-import cn.com.qmth.examcloud.core.oe.common.entity.ExamRecordPaperStructEntity;
|
|
|
|
-import cn.com.qmth.examcloud.core.oe.common.entity.ExamRecordQuestionsEntity;
|
|
|
|
-import cn.com.qmth.examcloud.core.oe.common.entity.ExamScoreEntity;
|
|
|
|
-import cn.com.qmth.examcloud.core.oe.common.entity.ExamStudentEntity;
|
|
|
|
-import cn.com.qmth.examcloud.core.oe.common.entity.ExamingRecordEntity;
|
|
|
|
-import cn.com.qmth.examcloud.core.oe.common.entity.HandInExamRecordEntity;
|
|
|
|
-import cn.com.qmth.examcloud.core.oe.common.enums.ExamProperties;
|
|
|
|
-import cn.com.qmth.examcloud.core.oe.common.enums.ExamRecordStatus;
|
|
|
|
-import cn.com.qmth.examcloud.core.oe.common.enums.ExamType;
|
|
|
|
-import cn.com.qmth.examcloud.core.oe.common.enums.FileAnswerAcknowledgeStatus;
|
|
|
|
-import cn.com.qmth.examcloud.core.oe.common.enums.HandInExamType;
|
|
|
|
-import cn.com.qmth.examcloud.core.oe.common.repository.ExamCaptureQueueRepo;
|
|
|
|
-import cn.com.qmth.examcloud.core.oe.common.repository.ExamFileAnswerTempRepo;
|
|
|
|
-import cn.com.qmth.examcloud.core.oe.common.repository.ExamRecordDataRepo;
|
|
|
|
-import cn.com.qmth.examcloud.core.oe.common.repository.ExamRecordPaperStructRepo;
|
|
|
|
-import cn.com.qmth.examcloud.core.oe.common.repository.ExamRecordRepo;
|
|
|
|
-import cn.com.qmth.examcloud.core.oe.common.repository.ExamScoreRepo;
|
|
|
|
-import cn.com.qmth.examcloud.core.oe.common.repository.ExamStudentRepo;
|
|
|
|
-import cn.com.qmth.examcloud.core.oe.common.repository.ExamingRecordRepo;
|
|
|
|
|
|
+import cn.com.qmth.examcloud.core.oe.common.entity.*;
|
|
|
|
+import cn.com.qmth.examcloud.core.oe.common.enums.*;
|
|
|
|
+import cn.com.qmth.examcloud.core.oe.common.repository.*;
|
|
import cn.com.qmth.examcloud.core.oe.common.service.ExamScoreObtainQueueService;
|
|
import cn.com.qmth.examcloud.core.oe.common.service.ExamScoreObtainQueueService;
|
|
import cn.com.qmth.examcloud.core.oe.common.service.ExamScorePushQueueService;
|
|
import cn.com.qmth.examcloud.core.oe.common.service.ExamScorePushQueueService;
|
|
-import cn.com.qmth.examcloud.core.oe.student.bean.CalculateFaceCheckResultInfo;
|
|
|
|
-import cn.com.qmth.examcloud.core.oe.student.bean.CheckExamInProgressInfo;
|
|
|
|
-import cn.com.qmth.examcloud.core.oe.student.bean.CheckQrCodeInfo;
|
|
|
|
-import cn.com.qmth.examcloud.core.oe.student.bean.EndExamInfo;
|
|
|
|
-import cn.com.qmth.examcloud.core.oe.student.bean.EndExamPreInfo;
|
|
|
|
-import cn.com.qmth.examcloud.core.oe.student.bean.ExamSessionInfo;
|
|
|
|
-import cn.com.qmth.examcloud.core.oe.student.bean.GetQrCodeReq;
|
|
|
|
-import cn.com.qmth.examcloud.core.oe.student.bean.GetUploadedFileAcknowledgeStatusReq;
|
|
|
|
-import cn.com.qmth.examcloud.core.oe.student.bean.GetUploadedFileAnswerListReq;
|
|
|
|
-import cn.com.qmth.examcloud.core.oe.student.bean.GetUpyunSignatureReq;
|
|
|
|
-import cn.com.qmth.examcloud.core.oe.student.bean.SaveUploadedFileAcknowledgeStatusReq;
|
|
|
|
-import cn.com.qmth.examcloud.core.oe.student.bean.SaveUploadedFileReq;
|
|
|
|
-import cn.com.qmth.examcloud.core.oe.student.bean.StartExamInfo;
|
|
|
|
-import cn.com.qmth.examcloud.core.oe.student.bean.UploadedFileAnswerInfo;
|
|
|
|
-import cn.com.qmth.examcloud.core.oe.student.bean.UpyunSignatureInfo;
|
|
|
|
-import cn.com.qmth.examcloud.core.oe.student.service.ExamCacheTransferHelper;
|
|
|
|
-import cn.com.qmth.examcloud.core.oe.student.service.ExamControlService;
|
|
|
|
-import cn.com.qmth.examcloud.core.oe.student.service.ExamFaceLivenessVerifyService;
|
|
|
|
-import cn.com.qmth.examcloud.core.oe.student.service.ExamRecordDataService;
|
|
|
|
-import cn.com.qmth.examcloud.core.oe.student.service.ExamRecordForMarkingService;
|
|
|
|
-import cn.com.qmth.examcloud.core.oe.student.service.ExamRecordQuestionsService;
|
|
|
|
-import cn.com.qmth.examcloud.core.oe.student.service.ExamRecordService;
|
|
|
|
-import cn.com.qmth.examcloud.core.oe.student.service.ExamScoreService;
|
|
|
|
-import cn.com.qmth.examcloud.core.oe.student.service.ExamSessionInfoService;
|
|
|
|
-import cn.com.qmth.examcloud.core.oe.student.service.ExamStudentService;
|
|
|
|
|
|
+import cn.com.qmth.examcloud.core.oe.student.bean.*;
|
|
|
|
+import cn.com.qmth.examcloud.core.oe.student.service.*;
|
|
import cn.com.qmth.examcloud.core.oe.websocket.api.FileAnswerWebsocketCloudService;
|
|
import cn.com.qmth.examcloud.core.oe.websocket.api.FileAnswerWebsocketCloudService;
|
|
import cn.com.qmth.examcloud.core.oe.websocket.api.enums.WebSocketEventType;
|
|
import cn.com.qmth.examcloud.core.oe.websocket.api.enums.WebSocketEventType;
|
|
import cn.com.qmth.examcloud.core.oe.websocket.api.request.SendFileAnswerMessageReq;
|
|
import cn.com.qmth.examcloud.core.oe.websocket.api.request.SendFileAnswerMessageReq;
|
|
@@ -121,9 +43,30 @@ import cn.com.qmth.examcloud.web.exception.SequenceLockException;
|
|
import cn.com.qmth.examcloud.web.helpers.GlobalHelper;
|
|
import cn.com.qmth.examcloud.web.helpers.GlobalHelper;
|
|
import cn.com.qmth.examcloud.web.helpers.SequenceLockHelper;
|
|
import cn.com.qmth.examcloud.web.helpers.SequenceLockHelper;
|
|
import cn.com.qmth.examcloud.web.redis.RedisClient;
|
|
import cn.com.qmth.examcloud.web.redis.RedisClient;
|
|
|
|
+import com.google.common.base.Splitter;
|
|
import main.java.com.upyun.Base64Coder;
|
|
import main.java.com.upyun.Base64Coder;
|
|
import main.java.com.upyun.UpException;
|
|
import main.java.com.upyun.UpException;
|
|
import main.java.com.upyun.UpYunUtils;
|
|
import main.java.com.upyun.UpYunUtils;
|
|
|
|
+import org.apache.commons.collections.CollectionUtils;
|
|
|
|
+import org.apache.commons.lang.math.RandomUtils;
|
|
|
|
+import org.apache.commons.lang3.StringUtils;
|
|
|
|
+import org.apache.commons.lang3.time.DateUtils;
|
|
|
|
+import org.apache.commons.logging.Log;
|
|
|
|
+import org.apache.commons.logging.LogFactory;
|
|
|
|
+import org.slf4j.Logger;
|
|
|
|
+import org.slf4j.LoggerFactory;
|
|
|
|
+import org.springframework.beans.factory.annotation.Autowired;
|
|
|
|
+import org.springframework.beans.factory.annotation.Value;
|
|
|
|
+import org.springframework.stereotype.Service;
|
|
|
|
+import org.springframework.transaction.annotation.Transactional;
|
|
|
|
+
|
|
|
|
+import javax.validation.Valid;
|
|
|
|
+import java.io.UnsupportedEncodingException;
|
|
|
|
+import java.net.URLEncoder;
|
|
|
|
+import java.text.SimpleDateFormat;
|
|
|
|
+import java.util.*;
|
|
|
|
+import java.util.concurrent.TimeUnit;
|
|
|
|
+import java.util.stream.Collectors;
|
|
|
|
|
|
/**
|
|
/**
|
|
* @author chenken
|
|
* @author chenken
|
|
@@ -142,8 +85,6 @@ public class ExamControlServiceImpl implements ExamControlService {
|
|
private static final String OE_ANSWER_FILE_PATH = "oe-answer-file";
|
|
private static final String OE_ANSWER_FILE_PATH = "oe-answer-file";
|
|
private static final Logger log = LoggerFactory.getLogger(ExamControlServiceImpl.class);
|
|
private static final Logger log = LoggerFactory.getLogger(ExamControlServiceImpl.class);
|
|
private static final Log cleanExamRecordTaskLog = LogFactory.getLog("CLEAN_EXAM_RECORD_TASK_LOGGER");
|
|
private static final Log cleanExamRecordTaskLog = LogFactory.getLog("CLEAN_EXAM_RECORD_TASK_LOGGER");
|
|
- // 发送题目答案序号集合
|
|
|
|
-// private static ConcurrentHashMap<String,Integer> sendQuestionAnswerSequenceMap=new ConcurrentHashMap<String,Integer>();
|
|
|
|
@Autowired
|
|
@Autowired
|
|
private ExamStudentService examStudentService;
|
|
private ExamStudentService examStudentService;
|
|
@Autowired
|
|
@Autowired
|
|
@@ -355,7 +296,7 @@ public class ExamControlServiceImpl implements ExamControlService {
|
|
log.debug("12 合计 耗时:" + (System.currentTimeMillis() - st) + " ms");
|
|
log.debug("12 合计 耗时:" + (System.currentTimeMillis() - st) + " ms");
|
|
}
|
|
}
|
|
//在线考生开考打点
|
|
//在线考生开考打点
|
|
- ReportsUtil.report(new OnlineExamStudentReport(user.getRootOrgId(), user.getUserId(), examBean.getId(), examStudentId));
|
|
|
|
|
|
+ ReportsUtil.report(new OnlineExamStudentReport(user.getRootOrgId(), user.getUserId(), examBean.getId(), examStudentId));
|
|
return buildStartExamInfo(examRecordData.getId(), originalExamStudent, examBean, courseBean);
|
|
return buildStartExamInfo(examRecordData.getId(), originalExamStudent, examBean, courseBean);
|
|
// } finally {
|
|
// } finally {
|
|
//
|
|
//
|
|
@@ -649,9 +590,7 @@ public class ExamControlServiceImpl implements ExamControlService {
|
|
* @return
|
|
* @return
|
|
* @Param studentId
|
|
* @Param studentId
|
|
*/
|
|
*/
|
|
- private Long checkAndComputeExamDuration(ExamSessionInfo examSessionInfo, Long studentId) {
|
|
|
|
- long st = System.currentTimeMillis();
|
|
|
|
- long startTime = System.currentTimeMillis();
|
|
|
|
|
|
+ private Long checkAndComputeExamDuration(ExamSessionInfo examSessionInfo) {
|
|
|
|
|
|
long now = System.currentTimeMillis();
|
|
long now = System.currentTimeMillis();
|
|
Long lastHeartbeat = examSessionInfo.getLastHeartbeat();
|
|
Long lastHeartbeat = examSessionInfo.getLastHeartbeat();
|
|
@@ -667,11 +606,7 @@ public class ExamControlServiceImpl implements ExamControlService {
|
|
}
|
|
}
|
|
// 如果没有超过冻结时间,抛出异常
|
|
// 如果没有超过冻结时间,抛出异常
|
|
if (examSessionInfo.getExamType().equals(ExamType.ONLINE.name())) {
|
|
if (examSessionInfo.getExamType().equals(ExamType.ONLINE.name())) {
|
|
- startTime = System.currentTimeMillis();
|
|
|
|
ExamingRecordEntity rec = GlobalHelper.getEntity(examingRecordRepo, examSessionInfo.getExamRecordId(), ExamingRecordEntity.class);
|
|
ExamingRecordEntity rec = GlobalHelper.getEntity(examingRecordRepo, examSessionInfo.getExamRecordId(), ExamingRecordEntity.class);
|
|
- if (log.isDebugEnabled()) {
|
|
|
|
- log.debug("1.1 [CHECK_AND_COMPUTE_EXAMD_URATION]获取状态为examing的进行中的考试记录 耗时:" + (System.currentTimeMillis() - startTime) + " ms");
|
|
|
|
- }
|
|
|
|
|
|
|
|
if (rec != null && rec.getIsExceed() != null && rec.getIsExceed()) {// 超过断点最大次数的不校验冻结时间
|
|
if (rec != null && rec.getIsExceed() != null && rec.getIsExceed()) {// 超过断点最大次数的不校验冻结时间
|
|
return usedTime;
|
|
return usedTime;
|
|
@@ -683,61 +618,18 @@ public class ExamControlServiceImpl implements ExamControlService {
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
- if (log.isDebugEnabled()) {
|
|
|
|
- log.debug("1.2 [CHECK_AND_COMPUTE_EXAMD_URATION]合计 耗时:" + (System.currentTimeMillis() - st) + " ms");
|
|
|
|
- }
|
|
|
|
return usedTime;
|
|
return usedTime;
|
|
}
|
|
}
|
|
|
|
|
|
- @Override
|
|
|
|
- public EndExamPreInfo endExamPre(Long studentId) {
|
|
|
|
- long st = System.currentTimeMillis();
|
|
|
|
- long startTime = System.currentTimeMillis();
|
|
|
|
- // 获取考试会话,判断考生是否已结束考试
|
|
|
|
- ExamSessionInfo examSessionInfo = examSessionInfoService.getExamSessionInfo(studentId);
|
|
|
|
- if (examSessionInfo == null) {
|
|
|
|
- return null;
|
|
|
|
- }
|
|
|
|
- if (log.isDebugEnabled()) {
|
|
|
|
- log.debug("1 [END_EXAM_PRE]获取考试会话 耗时:" + (System.currentTimeMillis() - startTime) + " ms");
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- long examRecordDataId = examSessionInfo.getExamRecordDataId();
|
|
|
|
-
|
|
|
|
- startTime = System.currentTimeMillis();
|
|
|
|
- // 得到考试时长,校验是否达到冻结时间
|
|
|
|
- long usedExamTime = checkAndComputeExamDuration(examSessionInfo, studentId);
|
|
|
|
- if (log.isDebugEnabled()) {
|
|
|
|
- log.debug("2 [END_EXAM_PRE]校验是否达到冻结时间 耗时:" + (System.currentTimeMillis() - startTime) + " ms");
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- startTime = System.currentTimeMillis();
|
|
|
|
- // 查询考试记录
|
|
|
|
- ExamRecordDataEntity examRecordData = GlobalHelper.getEntity(examRecordDataRepo, examRecordDataId,
|
|
|
|
- ExamRecordDataEntity.class);
|
|
|
|
- examRecordData.setUsedExamTime(usedExamTime);
|
|
|
|
- EndExamPreInfo endExamPreInfo = new EndExamPreInfo();
|
|
|
|
- endExamPreInfo.setStudentId(studentId);
|
|
|
|
- endExamPreInfo.setExamRecordData(examRecordData);
|
|
|
|
- if (log.isDebugEnabled()) {
|
|
|
|
- log.debug("3 [END_EXAM_PRE]查询考试记录 耗时:" + (System.currentTimeMillis() - startTime) + " ms");
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- if (log.isDebugEnabled()) {
|
|
|
|
- log.debug("4 [END_EXAM_PRE]合计 耗时:" + (System.currentTimeMillis() - st) + " ms");
|
|
|
|
- }
|
|
|
|
- return endExamPreInfo;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
/**
|
|
/**
|
|
- * @param examRecordData 考试记录对象
|
|
|
|
- * @param handInExamType 交卷类型
|
|
|
|
|
|
+ * @param examRecordDataId 考试记录id
|
|
|
|
+ * @param handInExamType 交卷类型
|
|
*/
|
|
*/
|
|
@Override
|
|
@Override
|
|
@Transactional
|
|
@Transactional
|
|
- public void handInExam(ExamRecordDataEntity examRecordData, HandInExamType handInExamType) {
|
|
|
|
|
|
+ public void handInExam(Long examRecordDataId, HandInExamType handInExamType) {
|
|
//此锁是为了避免自动交卷服务与断点续考交卷或活检失败交卷,同一时刻交卷争抢资源导致死锁
|
|
//此锁是为了避免自动交卷服务与断点续考交卷或活检失败交卷,同一时刻交卷争抢资源导致死锁
|
|
- String sequenceLockKey = Constants.HAND_IN_EXAM_LOCK_PREFIX + examRecordData.getId();
|
|
|
|
|
|
+ String sequenceLockKey = Constants.HAND_IN_EXAM_LOCK_PREFIX + examRecordDataId;
|
|
//系统在请求结束后会,自动释放锁,无需手动解锁
|
|
//系统在请求结束后会,自动释放锁,无需手动解锁
|
|
SequenceLockHelper.getLock(sequenceLockKey);
|
|
SequenceLockHelper.getLock(sequenceLockKey);
|
|
|
|
|
|
@@ -748,6 +640,7 @@ public class ExamControlServiceImpl implements ExamControlService {
|
|
long st = System.currentTimeMillis();
|
|
long st = System.currentTimeMillis();
|
|
long startTime = System.currentTimeMillis();
|
|
long startTime = System.currentTimeMillis();
|
|
|
|
|
|
|
|
+ ExamRecordDataEntity examRecordData = GlobalHelper.getEntity(examRecordDataRepo, examRecordDataId, ExamRecordDataEntity.class);
|
|
ExamRecordEntity examRecord = GlobalHelper.getEntity(examRecordRepo, examRecordData.getExamRecordId(), ExamRecordEntity.class);
|
|
ExamRecordEntity examRecord = GlobalHelper.getEntity(examRecordRepo, examRecordData.getExamRecordId(), ExamRecordEntity.class);
|
|
if (log.isDebugEnabled()) {
|
|
if (log.isDebugEnabled()) {
|
|
log.debug("1 [HAND_IN_EXAM]获取考试记录耗时:" + (System.currentTimeMillis() - startTime) + " ms");
|
|
log.debug("1 [HAND_IN_EXAM]获取考试记录耗时:" + (System.currentTimeMillis() - startTime) + " ms");
|
|
@@ -755,6 +648,14 @@ public class ExamControlServiceImpl implements ExamControlService {
|
|
|
|
|
|
if (handInExamType == HandInExamType.MANUAL) {
|
|
if (handInExamType == HandInExamType.MANUAL) {
|
|
startTime = System.currentTimeMillis();
|
|
startTime = System.currentTimeMillis();
|
|
|
|
+ // 获取考试会话,判断考生是否已结束考试(二次校验)
|
|
|
|
+ ExamSessionInfo examSessionInfo = examSessionInfoService.getExamSessionInfo(examRecord.getStudentId());
|
|
|
|
+ if (examSessionInfo == null) {
|
|
|
|
+ throw new StatusException("oestudent-100100", "考试会话已过期");
|
|
|
|
+ }
|
|
|
|
+ // 得到考试时长,校验是否达到冻结时间
|
|
|
|
+ long usedExamTime = checkAndComputeExamDuration(examSessionInfo);
|
|
|
|
+ examRecordData.setUsedExamTime(usedExamTime);
|
|
examRecordData.setExamRecordStatus(ExamRecordStatus.EXAM_HAND_IN);
|
|
examRecordData.setExamRecordStatus(ExamRecordStatus.EXAM_HAND_IN);
|
|
examRecordData.setEndTime(new Date());
|
|
examRecordData.setEndTime(new Date());
|
|
|
|
|
|
@@ -889,11 +790,11 @@ public class ExamControlServiceImpl implements ExamControlService {
|
|
/**
|
|
/**
|
|
* 考试心跳每分钟调用一次
|
|
* 考试心跳每分钟调用一次
|
|
*
|
|
*
|
|
- * @param studentId 学生id
|
|
|
|
|
|
+ * @param user 学生
|
|
*/
|
|
*/
|
|
@Override
|
|
@Override
|
|
public long examHeartbeat(User user) {
|
|
public long examHeartbeat(User user) {
|
|
- Long studentId=user.getUserId();
|
|
|
|
|
|
+ Long studentId = user.getUserId();
|
|
ExamSessionInfo examSessionInfo = examSessionInfoService.getExamSessionInfo(studentId);
|
|
ExamSessionInfo examSessionInfo = examSessionInfoService.getExamSessionInfo(studentId);
|
|
if (examSessionInfo == null) {
|
|
if (examSessionInfo == null) {
|
|
throw new StatusException("ExamControlServiceImpl-examHeartbeat-exception", "会话已过期,请离开考试!");
|
|
throw new StatusException("ExamControlServiceImpl-examHeartbeat-exception", "会话已过期,请离开考试!");
|
|
@@ -973,12 +874,10 @@ public class ExamControlServiceImpl implements ExamControlService {
|
|
|
|
|
|
// 如果会话不存在,自动交卷
|
|
// 如果会话不存在,自动交卷
|
|
if (examSessionInfo == null) {
|
|
if (examSessionInfo == null) {
|
|
- // 查询考试记录
|
|
|
|
- ExamRecordDataEntity examRecordData = GlobalHelper.getEntity(examRecordDataRepo, examingRecord.getExamRecordDataId(),
|
|
|
|
- ExamRecordDataEntity.class);
|
|
|
|
- delayHandInExamIfLocked(examRecordData);
|
|
|
|
|
|
+ delayHandInExamIfLocked(examingRecord.getExamRecordDataId());
|
|
return null;
|
|
return null;
|
|
}
|
|
}
|
|
|
|
+
|
|
// 如果已经过了断点续考时间,清除考试记录,清除会话
|
|
// 如果已经过了断点续考时间,清除考试记录,清除会话
|
|
Long lastHeartbeat = examSessionInfo.getLastHeartbeat();
|
|
Long lastHeartbeat = examSessionInfo.getLastHeartbeat();
|
|
if (lastHeartbeat == null) {
|
|
if (lastHeartbeat == null) {
|
|
@@ -987,9 +886,7 @@ public class ExamControlServiceImpl implements ExamControlService {
|
|
long now = System.currentTimeMillis();
|
|
long now = System.currentTimeMillis();
|
|
if (now - lastHeartbeat >= examSessionInfo.getExamReconnectTime().intValue() * 60 * 1000) {
|
|
if (now - lastHeartbeat >= examSessionInfo.getExamReconnectTime().intValue() * 60 * 1000) {
|
|
examSessionInfoService.deleteExamSessionInfo(studentId);
|
|
examSessionInfoService.deleteExamSessionInfo(studentId);
|
|
- ExamRecordDataEntity examRecordDataEntity = GlobalHelper.getEntity(examRecordDataRepo,
|
|
|
|
- examingRecord.getExamRecordDataId(), ExamRecordDataEntity.class);
|
|
|
|
- delayHandInExamIfLocked(examRecordDataEntity);
|
|
|
|
|
|
+ delayHandInExamIfLocked(examingRecord.getExamRecordDataId());
|
|
return null;
|
|
return null;
|
|
}
|
|
}
|
|
return examingRecord;
|
|
return examingRecord;
|
|
@@ -998,18 +895,18 @@ public class ExamControlServiceImpl implements ExamControlService {
|
|
/**
|
|
/**
|
|
* 如果有序列化锁,则延迟交卷
|
|
* 如果有序列化锁,则延迟交卷
|
|
*
|
|
*
|
|
- * @param examRecordData
|
|
|
|
|
|
+ * @param examRecordDataId 考试记录id
|
|
* @return
|
|
* @return
|
|
*/
|
|
*/
|
|
- private void delayHandInExamIfLocked(ExamRecordDataEntity examRecordData) {
|
|
|
|
|
|
+ private void delayHandInExamIfLocked(Long examRecordDataId) {
|
|
try {
|
|
try {
|
|
- handInExam(examRecordData, HandInExamType.AUTO);
|
|
|
|
|
|
+ handInExam(examRecordDataId, HandInExamType.AUTO);
|
|
} catch (SequenceLockException e) {
|
|
} catch (SequenceLockException e) {
|
|
//如果发现自动服务正在交卷,则重试1500毫秒获取考试记录状态,判断是否已交卷
|
|
//如果发现自动服务正在交卷,则重试1500毫秒获取考试记录状态,判断是否已交卷
|
|
int loopTimes = 0;
|
|
int loopTimes = 0;
|
|
while (loopTimes <= 15) {
|
|
while (loopTimes <= 15) {
|
|
loopTimes++;
|
|
loopTimes++;
|
|
- examRecordData = GlobalHelper.getEntity(examRecordDataRepo, examRecordData.getId(),
|
|
|
|
|
|
+ ExamRecordDataEntity examRecordData = GlobalHelper.getEntity(examRecordDataRepo, examRecordDataId,
|
|
ExamRecordDataEntity.class);
|
|
ExamRecordDataEntity.class);
|
|
|
|
|
|
//1500毫秒内如果交卷成功,则退出循环
|
|
//1500毫秒内如果交卷成功,则退出循环
|
|
@@ -1032,15 +929,14 @@ public class ExamControlServiceImpl implements ExamControlService {
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
|
|
|
|
- ExamRecordDataEntity examRecordData = GlobalHelper.getEntity(examRecordDataRepo, examingRecord.getExamRecordDataId(), ExamRecordDataEntity.class);
|
|
|
|
|
|
|
|
//只有考试状态为考试中,系统才需要执行交卷动作,因为有可能已经手动交卷,所以这里再做一次判断
|
|
//只有考试状态为考试中,系统才需要执行交卷动作,因为有可能已经手动交卷,所以这里再做一次判断
|
|
// if (examRecordData.getExamRecordStatus() == ExamRecordStatus.EXAM_ING) {
|
|
// if (examRecordData.getExamRecordStatus() == ExamRecordStatus.EXAM_ING) {
|
|
- cleanExamRecordTaskLog.debug("[CLEAN_EXAMING_RECORD_" + examRecordData.getId() + "]状态为进行中考试,执行交卷[handInExam],.");
|
|
|
|
- handInExam(examRecordData, HandInExamType.AUTO);
|
|
|
|
|
|
+ cleanExamRecordTaskLog.debug("[CLEAN_EXAMING_RECORD_" + examingRecord.getExamRecordDataId() + "]状态为进行中考试,执行交卷[handInExam],.");
|
|
|
|
+ handInExam(examingRecord.getExamRecordDataId(), HandInExamType.AUTO);
|
|
// }
|
|
// }
|
|
|
|
|
|
- cleanExamRecordTaskLog.debug("[CLEAN_EXAMING_RECORD_" + examRecordData.getId() + "]考试记录交卷完成.");
|
|
|
|
|
|
+ cleanExamRecordTaskLog.debug("[CLEAN_EXAMING_RECORD_" + examingRecord.getExamRecordDataId() + "]考试记录交卷完成.");
|
|
}
|
|
}
|
|
|
|
|
|
@Override
|
|
@Override
|
|
@@ -1465,7 +1361,7 @@ public class ExamControlServiceImpl implements ExamControlService {
|
|
try {
|
|
try {
|
|
this.sendScanQrCodeToWebSocket(clientId, Long.valueOf(examRecordDataId), Integer.valueOf(order));
|
|
this.sendScanQrCodeToWebSocket(clientId, Long.valueOf(examRecordDataId), Integer.valueOf(order));
|
|
} catch (Exception e) {
|
|
} catch (Exception e) {
|
|
- throw new StatusException("100011", "消息通知失败", e);
|
|
|
|
|
|
+ throw new StatusException("100011", "消息通知失败", e);
|
|
}
|
|
}
|
|
if (log.isDebugEnabled()) {
|
|
if (log.isDebugEnabled()) {
|
|
log.debug("4 发websocket耗时:" + (System.currentTimeMillis() - startTime) + " ms");
|
|
log.debug("4 发websocket耗时:" + (System.currentTimeMillis() - startTime) + " ms");
|