|
@@ -1,5 +1,40 @@
|
|
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;
|
|
@@ -10,20 +45,60 @@ 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.*;
|
|
|
|
-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.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.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.common.service.GainBaseDataService;
|
|
|
|
-import cn.com.qmth.examcloud.core.oe.student.bean.*;
|
|
|
|
-import cn.com.qmth.examcloud.core.oe.student.face.api.ExamCaptureQueueCloudService;
|
|
|
|
-import cn.com.qmth.examcloud.core.oe.student.service.*;
|
|
|
|
|
|
+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.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;
|
|
import cn.com.qmth.examcloud.core.oe.websocket.api.request.SendScanQrCodeMessageReq;
|
|
import cn.com.qmth.examcloud.core.oe.websocket.api.request.SendScanQrCodeMessageReq;
|
|
-import cn.com.qmth.examcloud.core.questions.api.ExtractConfigCloudService;
|
|
|
|
import cn.com.qmth.examcloud.examwork.api.ExamCloudService;
|
|
import cn.com.qmth.examcloud.examwork.api.ExamCloudService;
|
|
import cn.com.qmth.examcloud.examwork.api.bean.ExamBean;
|
|
import cn.com.qmth.examcloud.examwork.api.bean.ExamBean;
|
|
import cn.com.qmth.examcloud.examwork.api.request.GetExamPropertyReq;
|
|
import cn.com.qmth.examcloud.examwork.api.request.GetExamPropertyReq;
|
|
@@ -33,6 +108,9 @@ import cn.com.qmth.examcloud.question.commons.core.paper.DefaultQuestionGroup;
|
|
import cn.com.qmth.examcloud.question.commons.core.paper.DefaultQuestionStructureWrapper;
|
|
import cn.com.qmth.examcloud.question.commons.core.paper.DefaultQuestionStructureWrapper;
|
|
import cn.com.qmth.examcloud.question.commons.core.paper.DefaultQuestionUnitWrapper;
|
|
import cn.com.qmth.examcloud.question.commons.core.paper.DefaultQuestionUnitWrapper;
|
|
import cn.com.qmth.examcloud.question.commons.core.question.QuestionType;
|
|
import cn.com.qmth.examcloud.question.commons.core.question.QuestionType;
|
|
|
|
+import cn.com.qmth.examcloud.reports.commons.bean.OnlineExamStudentReport;
|
|
|
|
+import cn.com.qmth.examcloud.reports.commons.bean.OnlineStudentReport;
|
|
|
|
+import cn.com.qmth.examcloud.reports.commons.util.ReportsUtil;
|
|
import cn.com.qmth.examcloud.support.cache.CacheHelper;
|
|
import cn.com.qmth.examcloud.support.cache.CacheHelper;
|
|
import cn.com.qmth.examcloud.support.cache.bean.ExtractConfigCacheBean;
|
|
import cn.com.qmth.examcloud.support.cache.bean.ExtractConfigCacheBean;
|
|
import cn.com.qmth.examcloud.support.cache.bean.ExtractConfigDetailCacheBean;
|
|
import cn.com.qmth.examcloud.support.cache.bean.ExtractConfigDetailCacheBean;
|
|
@@ -43,30 +121,9 @@ 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
|
|
@@ -106,18 +163,12 @@ public class ExamControlServiceImpl implements ExamControlService {
|
|
@Autowired
|
|
@Autowired
|
|
private ExamScoreService examScoreService;
|
|
private ExamScoreService examScoreService;
|
|
|
|
|
|
- @Autowired
|
|
|
|
- private ExamCaptureQueueCloudService examCaptureQueueCloudService;
|
|
|
|
-
|
|
|
|
@Autowired
|
|
@Autowired
|
|
private ExamFaceLivenessVerifyService examFaceLivenessVerifyService;
|
|
private ExamFaceLivenessVerifyService examFaceLivenessVerifyService;
|
|
|
|
|
|
@Autowired
|
|
@Autowired
|
|
private ExamRecordForMarkingService examRecordForMarkingService;
|
|
private ExamRecordForMarkingService examRecordForMarkingService;
|
|
|
|
|
|
- @Autowired
|
|
|
|
- private GainBaseDataService gainBaseDataService;
|
|
|
|
-
|
|
|
|
@Autowired
|
|
@Autowired
|
|
private ExamStudentRepo examStudentRepo;
|
|
private ExamStudentRepo examStudentRepo;
|
|
|
|
|
|
@@ -132,9 +183,6 @@ public class ExamControlServiceImpl implements ExamControlService {
|
|
@Autowired
|
|
@Autowired
|
|
private ExamRecordPaperStructRepo examRecordPaperStructRepo;
|
|
private ExamRecordPaperStructRepo examRecordPaperStructRepo;
|
|
|
|
|
|
- @Autowired
|
|
|
|
- private ExamFaceLivenessVerifyRepo examFaceLivenessVerifyRepo;
|
|
|
|
-
|
|
|
|
@Autowired
|
|
@Autowired
|
|
private RedisClient redisClient;
|
|
private RedisClient redisClient;
|
|
|
|
|
|
@@ -153,8 +201,6 @@ public class ExamControlServiceImpl implements ExamControlService {
|
|
@Autowired
|
|
@Autowired
|
|
private ExamRecordRepo examRecordRepo;
|
|
private ExamRecordRepo examRecordRepo;
|
|
|
|
|
|
- @Autowired
|
|
|
|
- private ExtractConfigCloudService extractConfigCloudService;
|
|
|
|
@Value("${audio.app.url}")
|
|
@Value("${audio.app.url}")
|
|
private String audioAppUrl;
|
|
private String audioAppUrl;
|
|
@Value("${$upyun.site.1.bucketName}")
|
|
@Value("${$upyun.site.1.bucketName}")
|
|
@@ -170,8 +216,6 @@ public class ExamControlServiceImpl implements ExamControlService {
|
|
@Value("${$upyun.site.1.domain}")
|
|
@Value("${$upyun.site.1.domain}")
|
|
private String upyunFileUrl;
|
|
private String upyunFileUrl;
|
|
|
|
|
|
- private Object lock = new Object();
|
|
|
|
-
|
|
|
|
@Transactional
|
|
@Transactional
|
|
@Override
|
|
@Override
|
|
public StartExamInfo startExam(Long examStudentId, User user) {
|
|
public StartExamInfo startExam(Long examStudentId, User user) {
|
|
@@ -310,6 +354,8 @@ public class ExamControlServiceImpl implements ExamControlService {
|
|
if (log.isDebugEnabled()) {
|
|
if (log.isDebugEnabled()) {
|
|
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));
|
|
return buildStartExamInfo(examRecordData.getId(), originalExamStudent, examBean, courseBean);
|
|
return buildStartExamInfo(examRecordData.getId(), originalExamStudent, examBean, courseBean);
|
|
// } finally {
|
|
// } finally {
|
|
//
|
|
//
|
|
@@ -846,7 +892,8 @@ public class ExamControlServiceImpl implements ExamControlService {
|
|
* @param studentId 学生id
|
|
* @param studentId 学生id
|
|
*/
|
|
*/
|
|
@Override
|
|
@Override
|
|
- public long examHeartbeat(Long studentId) {
|
|
|
|
|
|
+ public long examHeartbeat(User user) {
|
|
|
|
+ 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", "会话已过期,请离开考试!");
|
|
@@ -867,6 +914,10 @@ public class ExamControlServiceImpl implements ExamControlService {
|
|
int expireTime = (examSessionInfo.getExamReconnectTime() + 1) * 60;
|
|
int expireTime = (examSessionInfo.getExamReconnectTime() + 1) * 60;
|
|
// 更新考试会话过期时间
|
|
// 更新考试会话过期时间
|
|
examSessionInfoService.saveExamSessionInfo(studentId, examSessionInfo, expireTime);
|
|
examSessionInfoService.saveExamSessionInfo(studentId, examSessionInfo, expireTime);
|
|
|
|
+ //在线考生心跳打点
|
|
|
|
+ ReportsUtil.report(new OnlineExamStudentReport(user.getRootOrgId(), user.getUserId(), examSessionInfo.getExamId(), examSessionInfo.getExamStudentId()));
|
|
|
|
+ //在线学生心跳打点
|
|
|
|
+ ReportsUtil.report(new OnlineStudentReport(user.getRootOrgId(), user.getUserId()));
|
|
// 返回考试剩余时间 :考试时长-心跳次数*60000
|
|
// 返回考试剩余时间 :考试时长-心跳次数*60000
|
|
return examSessionInfo.getExamDuration() - (examSessionInfo.getHeartbeat() * 60 * 1000);
|
|
return examSessionInfo.getExamDuration() - (examSessionInfo.getHeartbeat() * 60 * 1000);
|
|
}
|
|
}
|