|
@@ -89,10 +89,13 @@ public class TEExamServiceImpl extends ServiceImpl<TEExamMapper, TEExam> impleme
|
|
|
|
|
|
@Resource
|
|
|
private TBTaskHistoryService tbTaskHistoryService;
|
|
|
-
|
|
|
+
|
|
|
@Resource
|
|
|
TEExamPaperService examPaperService;
|
|
|
|
|
|
+ @Resource
|
|
|
+ TEExamService teExamService;
|
|
|
+
|
|
|
/**
|
|
|
* 查询考试批次
|
|
|
*
|
|
@@ -188,7 +191,7 @@ public class TEExamServiceImpl extends ServiceImpl<TEExamMapper, TEExam> impleme
|
|
|
throw new BusinessException("考生Id和当前登录用户不一致");
|
|
|
}
|
|
|
ExamCacheBean examCache = getExamCacheBean(es.getExamId());
|
|
|
- Long unFinishedRecordId=ExamingDataCacheUtil.getUnFinishedRecordId(studentId);
|
|
|
+ Long unFinishedRecordId = ExamingDataCacheUtil.getUnFinishedRecordId(studentId);
|
|
|
if (unFinishedRecordId != null) {
|
|
|
Long recordId = unFinishedRecordId;
|
|
|
if (examStudentId.equals(ExamRecordCacheUtil.getExamStudentId(recordId))) {//当前考生已存在候考的考试记录
|
|
@@ -293,7 +296,7 @@ public class TEExamServiceImpl extends ServiceImpl<TEExamMapper, TEExam> impleme
|
|
|
redisUtil.set(RedisKeyHelper.examStudentCacheKey(examStudentId), es);
|
|
|
//更新场次-考试记录缓存
|
|
|
ExamActivityRecordCacheUtil.setExamRecordStatus(activityId, recordId, ExamRecordCacheUtil.getStatus(recordId));
|
|
|
- ExamingDataCacheUtil.setUnFinishedRecordId(studentId,recordId);
|
|
|
+ ExamingDataCacheUtil.setUnFinishedRecordId(studentId, recordId);
|
|
|
//mq发送消息start
|
|
|
TEStudentCacheDto teStudentCacheDto = (TEStudentCacheDto) redisUtil.getStudent(studentId);
|
|
|
MqDto mqDto = new MqDto(MqTopicEnum.THEMIS_TOPIC.getCode(), MqTagEnum.STUDENT.name(), SystemOperationEnum.FIRST_PREPARE, MqTagEnum.STUDENT, String.valueOf(teStudentCacheDto.getId()), teStudentCacheDto.getIdentity());
|
|
@@ -384,6 +387,46 @@ public class TEExamServiceImpl extends ServiceImpl<TEExamMapper, TEExam> impleme
|
|
|
throw new BusinessException("未找到试卷");
|
|
|
}
|
|
|
|
|
|
+ WebsocketStatusEnum websocketStatusEnum = ExamRecordCacheUtil.getClientWebsocketStatus(recordId);
|
|
|
+ if (Objects.isNull(websocketStatusEnum) || Objects.equals(WebsocketStatusEnum.OFF_LINE, websocketStatusEnum)) {
|
|
|
+ throw new BusinessException("客户端网络离线");
|
|
|
+ }
|
|
|
+ MonitorStatusSourceEnum clientCameraStatus = ExamRecordCacheUtil.getMonitorStatus(recordId, MonitorVideoSourceEnum.CLIENT_CAMERA.name());
|
|
|
+ if (Objects.nonNull(clientCameraStatus) || Objects.equals(MonitorStatusSourceEnum.STOP, clientCameraStatus)) {
|
|
|
+ throw new BusinessException("客户端摄像头离线");
|
|
|
+ }
|
|
|
+ MonitorStatusSourceEnum clientScreenStatus = ExamRecordCacheUtil.getMonitorStatus(recordId, MonitorVideoSourceEnum.CLIENT_SCREEN.name());
|
|
|
+ if (Objects.nonNull(clientScreenStatus) || Objects.equals(MonitorStatusSourceEnum.STOP, clientScreenStatus)) {
|
|
|
+ throw new BusinessException("客户端屏幕离线");
|
|
|
+ }
|
|
|
+ MonitorStatusSourceEnum mobileFirstStatus = ExamRecordCacheUtil.getMonitorStatus(recordId, MonitorVideoSourceEnum.MOBILE_FIRST.name());
|
|
|
+ if (Objects.nonNull(mobileFirstStatus) || Objects.equals(MonitorStatusSourceEnum.STOP, mobileFirstStatus)) {
|
|
|
+ throw new BusinessException("移动端第一机位离线");
|
|
|
+ }
|
|
|
+ MonitorStatusSourceEnum mobileSecondStatus = ExamRecordCacheUtil.getMonitorStatus(recordId, MonitorVideoSourceEnum.MOBILE_SECOND.name());
|
|
|
+ if (Objects.nonNull(mobileSecondStatus) || Objects.equals(MonitorStatusSourceEnum.STOP, mobileSecondStatus)) {
|
|
|
+ throw new BusinessException("移动端第二机位离线");
|
|
|
+ }
|
|
|
+
|
|
|
+ Long examId = ExamRecordCacheUtil.getExamId(recordId);
|
|
|
+ ExamCacheBean ec = teExamService.getExamCacheBean(examId);//考试缓存
|
|
|
+ ExamStudentCacheBean examStudentCacheBean = teExamStudentService.getExamStudentCacheBean(examStudentId);
|
|
|
+ Integer durationSeconds = Objects.isNull(ExamRecordCacheUtil.getDurationSeconds(recordId)) ? 0 : ExamRecordCacheUtil.getDurationSeconds(recordId);
|
|
|
+ //获取断点时间
|
|
|
+ Date lastBreakTime = ExamRecordCacheUtil.getLastBreakTime(recordId);
|
|
|
+ //获取剩余断点次数
|
|
|
+ Integer alreadyBreakCount = Objects.isNull(ExamRecordCacheUtil.getAlreadyBreakCount(recordId)) ? 0 : ExamRecordCacheUtil.getAlreadyBreakCount(recordId);
|
|
|
+ Integer leftBreakResumeCount = ec.getBreakResumeCount() - alreadyBreakCount;
|
|
|
+ Integer breakExpireSeconds = Objects.isNull(ec.getBreakExpireSeconds()) ? 0 : ec.getBreakExpireSeconds();
|
|
|
+ //如果断点时间大于整体断点时间,则强制交卷
|
|
|
+ if (Objects.nonNull(lastBreakTime) && (System.currentTimeMillis() - lastBreakTime.getTime()) / 1000 > breakExpireSeconds) {
|
|
|
+ teExamService.finish(examStudentCacheBean.getStudentId(), recordId, FinishTypeEnum.AUTO.name(), durationSeconds);
|
|
|
+ } else {
|
|
|
+ //如果断点次数小于0,也强制交卷
|
|
|
+ if (leftBreakResumeCount < 0) {
|
|
|
+ teExamService.finish(examStudentCacheBean.getStudentId(), recordId, FinishTypeEnum.AUTO.name(), durationSeconds);
|
|
|
+ }
|
|
|
+ }
|
|
|
ret = new ExamStartBean();
|
|
|
ret.setPaperDecryptSecret(ep.getDecryptSecret());
|
|
|
ret.setPaperDecryptVector(ep.getDecryptVector());
|
|
@@ -392,8 +435,10 @@ public class TEExamServiceImpl extends ServiceImpl<TEExamMapper, TEExam> impleme
|
|
|
Date firstStartTime = new Date();
|
|
|
ExamRecordCacheUtil.setFirstStartTime(recordId, firstStartTime, false);
|
|
|
ExamRecordCacheUtil.setStatus(recordId, ExamRecordStatusEnum.ANSWERING, false);
|
|
|
- String[] columns = new String[]{ExamRecordFieldEnum.first_start_time.name(), ExamRecordFieldEnum.status.name()};
|
|
|
- Object[] values = new Object[]{firstStartTime, ExamRecordStatusEnum.ANSWERING};
|
|
|
+ Date lastStartTime = new Date();
|
|
|
+ ExamRecordCacheUtil.setLastStartTime(recordId, lastStartTime, false);
|
|
|
+ String[] columns = new String[]{ExamRecordFieldEnum.first_start_time.name(), ExamRecordFieldEnum.status.name(), ExamRecordFieldEnum.last_start_time.name()};
|
|
|
+ Object[] values = new Object[]{firstStartTime, ExamRecordStatusEnum.ANSWERING, lastStartTime};
|
|
|
toeExamRecordService.dataUpdatesMq(recordId, columns, values);
|
|
|
//更新场次-考试记录缓存
|
|
|
ExamActivityRecordCacheUtil.setExamRecordStatus(activityId, recordId, ExamRecordCacheUtil.getStatus(recordId));
|
|
@@ -468,8 +513,8 @@ public class TEExamServiceImpl extends ServiceImpl<TEExamMapper, TEExam> impleme
|
|
|
answerCache.setAnswer(answer);
|
|
|
answerCache.setVersion(version);
|
|
|
answerCache.setDurationSeconds(durationSeconds);
|
|
|
- answerCache.setObjective(checkIsObjective(ExamRecordCacheUtil.getPaperId(recordId), mainNumber, subNumber, subIndex));
|
|
|
-
|
|
|
+ answerCache.setObjective(checkIsObjective(ExamRecordCacheUtil.getPaperId(recordId), mainNumber, subNumber, subIndex));
|
|
|
+
|
|
|
} else {
|
|
|
if (version.longValue() > answerCache.getVersion().longValue()) {
|
|
|
answerCache.setAnswer(answer);
|
|
@@ -483,18 +528,18 @@ public class TEExamServiceImpl extends ServiceImpl<TEExamMapper, TEExam> impleme
|
|
|
redisUtil.set(RedisKeyHelper.examAnswerKey(recordId),
|
|
|
RedisKeyHelper.examAnswerHashKey(mainNumber, subNumber, subIndex), answerCache);
|
|
|
// 如果是客观题,重置考试记录客观题得分
|
|
|
- if(answerCache.getObjective()) {
|
|
|
- ExamRecordCacheUtil.setObjectiveScore(recordId, null, false);
|
|
|
+ if (answerCache.getObjective()) {
|
|
|
+ ExamRecordCacheUtil.setObjectiveScore(recordId, null, false);
|
|
|
// 发消息计算客观分
|
|
|
calculateObjectiveScore(recordId, mainNumber, subNumber, subIndex);
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
AnswerSubmitBean ret = new AnswerSubmitBean();
|
|
|
ret.setVersion(version);
|
|
|
|
|
|
return ret;
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
private boolean checkIsObjective(Long paperId, Integer mainNumber, Integer subNumber, Integer subIndex) {
|
|
|
Map<String, ObjectiveAnswerCacheBean> map = examPaperService.getObjectiveAnswerCacheBean(paperId);
|
|
|
if (map == null || map.size() == 0) {
|
|
@@ -634,6 +679,25 @@ public class TEExamServiceImpl extends ServiceImpl<TEExamMapper, TEExam> impleme
|
|
|
if (ExamRecordStatusEnum.FINISHED.equals(sta) || ExamRecordStatusEnum.PERSISTED.equals(sta)) {
|
|
|
throw new BusinessException("该考试已结束");
|
|
|
}
|
|
|
+ Long examId = ExamRecordCacheUtil.getExamId(recordId);
|
|
|
+ ExamCacheBean ec = teExamService.getExamCacheBean(examId);//考试缓存
|
|
|
+ ExamStudentCacheBean examStudentCacheBean = teExamStudentService.getExamStudentCacheBean(examStudentId);
|
|
|
+ Integer durationSeconds = Objects.isNull(ExamRecordCacheUtil.getDurationSeconds(recordId)) ? 0 : ExamRecordCacheUtil.getDurationSeconds(recordId);
|
|
|
+ //获取断点时间
|
|
|
+ Date lastBreakTime = ExamRecordCacheUtil.getLastBreakTime(recordId);
|
|
|
+ //获取剩余断点次数
|
|
|
+ Integer alreadyBreakCount = Objects.isNull(ExamRecordCacheUtil.getAlreadyBreakCount(recordId)) ? 0 : ExamRecordCacheUtil.getAlreadyBreakCount(recordId);
|
|
|
+ Integer leftBreakResumeCount = ec.getBreakResumeCount() - alreadyBreakCount;
|
|
|
+ Integer breakExpireSeconds = Objects.isNull(ec.getBreakExpireSeconds()) ? 0 : ec.getBreakExpireSeconds();
|
|
|
+ //如果断点时间大于整体断点时间,则强制交卷
|
|
|
+ if (Objects.nonNull(lastBreakTime) && (System.currentTimeMillis() - lastBreakTime.getTime()) / 1000 > breakExpireSeconds) {
|
|
|
+ teExamService.finish(examStudentCacheBean.getStudentId(), recordId, FinishTypeEnum.AUTO.name(), durationSeconds);
|
|
|
+ } else {
|
|
|
+ //如果断点次数小于0,也强制交卷
|
|
|
+ if (leftBreakResumeCount < 0) {
|
|
|
+ teExamService.finish(examStudentCacheBean.getStudentId(), recordId, FinishTypeEnum.AUTO.name(), durationSeconds);
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
ExamResumeBean ret = new ExamResumeBean();
|
|
|
ret.setDurationSeconds(ExamRecordCacheUtil.getDurationSeconds(recordId));
|
|
@@ -660,6 +724,7 @@ public class TEExamServiceImpl extends ServiceImpl<TEExamMapper, TEExam> impleme
|
|
|
if (audioLeftPlayCounts != null && audioLeftPlayCounts.size() > 0) {
|
|
|
ret.setAudioLeftPlayCount(audioLeftPlayCounts);
|
|
|
}
|
|
|
+ ExamRecordCacheUtil.setLastPrepareTime(recordId, new Date(), true);
|
|
|
return ret;
|
|
|
}
|
|
|
|