|
@@ -1,9 +1,32 @@
|
|
|
package cn.com.qmth.examcloud.core.oe.student.service.impl;
|
|
|
|
|
|
+import java.math.BigDecimal;
|
|
|
+import java.text.DecimalFormat;
|
|
|
+import java.util.Comparator;
|
|
|
import java.util.Date;
|
|
|
import java.util.List;
|
|
|
import java.util.stream.Collectors;
|
|
|
|
|
|
+import cn.com.qmth.examcloud.core.oe.student.api.request.CalcExamScoreReq;
|
|
|
+import cn.com.qmth.examcloud.core.oe.student.api.request.CalcFaceBiopsyResultReq;
|
|
|
+import cn.com.qmth.examcloud.core.oe.student.api.response.CalcExamScoreResp;
|
|
|
+import cn.com.qmth.examcloud.core.oe.student.api.response.CalcFaceBiopsyResultResp;
|
|
|
+import cn.com.qmth.examcloud.core.oe.student.base.bean.ExamQuestion;
|
|
|
+import cn.com.qmth.examcloud.core.oe.student.base.bean.ExamRecordQuestions;
|
|
|
+import cn.com.qmth.examcloud.core.oe.student.base.utils.QuestionTypeUtil;
|
|
|
+import cn.com.qmth.examcloud.core.oe.student.dao.ExamFaceLivenessVerifyRepo;
|
|
|
+import cn.com.qmth.examcloud.core.oe.student.dao.FaceBiopsyRepo;
|
|
|
+import cn.com.qmth.examcloud.core.oe.student.dao.entity.ExamFaceLivenessVerifyEntity;
|
|
|
+import cn.com.qmth.examcloud.core.oe.student.dao.entity.FaceBiopsyEntity;
|
|
|
+import cn.com.qmth.examcloud.core.oe.student.dao.enums.FaceVerifyResult;
|
|
|
+import cn.com.qmth.examcloud.core.oe.student.service.ExamRecordQuestionsService;
|
|
|
+import cn.com.qmth.examcloud.support.cache.CacheHelper;
|
|
|
+import cn.com.qmth.examcloud.support.cache.bean.QuestionAnswerCacheBean;
|
|
|
+import cn.com.qmth.examcloud.support.enums.FaceBiopsyScheme;
|
|
|
+import cn.com.qmth.examcloud.support.enums.IsSuccess;
|
|
|
+import cn.com.qmth.examcloud.support.helper.FaceBiopsyHelper;
|
|
|
+import org.apache.commons.lang3.StringUtils;
|
|
|
+import org.assertj.core.internal.bytebuddy.asm.Advice;
|
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
|
import org.springframework.stereotype.Service;
|
|
|
import org.springframework.transaction.annotation.Transactional;
|
|
@@ -39,6 +62,18 @@ public class ExamRecordDataServiceImpl implements ExamRecordDataService {
|
|
|
@Autowired
|
|
|
private ExamRecordDataRepo examRecordDataRepo;
|
|
|
|
|
|
+ @Autowired
|
|
|
+ private FaceBiopsyRepo faceBiopsyRepo;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private ExamFaceLivenessVerifyRepo examFaceLivenessVerifyRepo;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private ExamRecordQuestionsService examRecordQuestionsService;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private ExamRecordDataService examRecordDataService;
|
|
|
+
|
|
|
@Transactional
|
|
|
@Override
|
|
|
public ExamRecordData createExamRecordData(ExamingSession examingSession, ExamSettingsCacheBean examBean,
|
|
@@ -76,19 +111,19 @@ public class ExamRecordDataServiceImpl implements ExamRecordDataService {
|
|
|
@Override
|
|
|
public void saveExamRecordDataCache(Long examRecordDataId, ExamRecordData data) {
|
|
|
String key = RedisKeyHelper.getBuilder().examRecordDataKey(examRecordDataId);
|
|
|
- redisClient.set(key + examRecordDataId, data, -1);
|
|
|
+ redisClient.set(key, data, -1);
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
public ExamRecordData getExamRecordDataCache(Long examRecordDataId) {
|
|
|
String key = RedisKeyHelper.getBuilder().examRecordDataKey(examRecordDataId);
|
|
|
- return redisClient.get(key + examRecordDataId, ExamRecordData.class);
|
|
|
+ return redisClient.get(key, ExamRecordData.class);
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
public void deleteExamRecordDataCache(Long examRecordDataId) {
|
|
|
String key = RedisKeyHelper.getBuilder().examRecordDataKey(examRecordDataId);
|
|
|
- redisClient.delete(key + examRecordDataId);
|
|
|
+ redisClient.delete(key);
|
|
|
}
|
|
|
|
|
|
private ExamRecordData of(ExamRecordDataEntity et) {
|
|
@@ -135,39 +170,166 @@ public class ExamRecordDataServiceImpl implements ExamRecordDataService {
|
|
|
|
|
|
@Override
|
|
|
public List<Long> getExamRecordDataIds(GetExamRecordDataIdsReq req) {
|
|
|
- Long startId=req.getStartId();
|
|
|
- Long batchNum=req.getBatchNum();
|
|
|
- Integer size=req.getSize();
|
|
|
- if(startId==null) {
|
|
|
- throw new StatusException("1001", "startId 不能为空");
|
|
|
+ Long startId = req.getStartId();
|
|
|
+ Long batchNum = req.getBatchNum();
|
|
|
+ Integer size = req.getSize();
|
|
|
+ if (startId == null) {
|
|
|
+ throw new StatusException("1001", "startId 不能为空");
|
|
|
}
|
|
|
- if(batchNum==null) {
|
|
|
- throw new StatusException("1002", "batchNum 不能为空");
|
|
|
+ if (batchNum == null) {
|
|
|
+ throw new StatusException("1002", "batchNum 不能为空");
|
|
|
}
|
|
|
- if(size==null) {
|
|
|
- throw new StatusException("1003", "size 不能为空");
|
|
|
+ if (size == null) {
|
|
|
+ throw new StatusException("1003", "size 不能为空");
|
|
|
}
|
|
|
- if(size>200) {
|
|
|
- throw new StatusException("1004", "size 最大为200");
|
|
|
+ if (size > 200) {
|
|
|
+ throw new StatusException("1004", "size 最大为200");
|
|
|
}
|
|
|
- List<ExamRecordDataEntity> list= examRecordDataRepo.getLimitExamRecordDataList(batchNum, startId, size);
|
|
|
- List<Long> ids=list.stream().map(et->et.getId()).collect(Collectors.toList());
|
|
|
+ List<ExamRecordDataEntity> list = examRecordDataRepo.getLimitExamRecordDataList(batchNum, startId, size);
|
|
|
+ List<Long> ids = list.stream().map(et -> et.getId()).collect(Collectors.toList());
|
|
|
return ids;
|
|
|
}
|
|
|
|
|
|
@Transactional
|
|
|
@Override
|
|
|
public void updateExamRecordDataBatchNum(UpdateExamRecordDataBatchNumReq req) {
|
|
|
- List<Long> ids=req.getIds();
|
|
|
- Long batchNum=req.getBatchNum();
|
|
|
- if(ids==null) {
|
|
|
- throw new StatusException("2001", "ids 不能为空");
|
|
|
+ List<Long> ids = req.getIds();
|
|
|
+ Long batchNum = req.getBatchNum();
|
|
|
+ if (ids == null) {
|
|
|
+ throw new StatusException("2001", "ids 不能为空");
|
|
|
}
|
|
|
- if(batchNum==null) {
|
|
|
- throw new StatusException("2002", "batchNum 不能为空");
|
|
|
+ if (batchNum == null) {
|
|
|
+ throw new StatusException("2002", "batchNum 不能为空");
|
|
|
}
|
|
|
- for(Long id:ids) {
|
|
|
+ for (Long id : ids) {
|
|
|
examRecordDataRepo.updateBatchNumById(batchNum, id);
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 计算活体检测结果
|
|
|
+ *
|
|
|
+ * @param req
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ public CalcFaceBiopsyResultResp calcFaceBiopsyResult(CalcFaceBiopsyResultReq req) {
|
|
|
+ ExamRecordData examRecordData = this.getExamRecordDataCache(req.getExamRecordDataId());
|
|
|
+
|
|
|
+ //如果活检结果不为空,且活检失败,则判定为违纪有警告
|
|
|
+ if (null != examRecordData.getFaceVerifyResult()) {
|
|
|
+ if (IsSuccess.FAILED == examRecordData.getFaceVerifyResult()) {
|
|
|
+ return new CalcFaceBiopsyResultResp(true, true, IsSuccess.FAILED);
|
|
|
+ }
|
|
|
+ return new CalcFaceBiopsyResultResp();
|
|
|
+ }
|
|
|
+
|
|
|
+ //如果考试记录中的活检记录为空,需要再次计算一次,并更新到考试记录中
|
|
|
+ else {
|
|
|
+ Long examId = examRecordData.getExamId();
|
|
|
+ Long rootOrgId = examRecordData.getRootOrgId();
|
|
|
+ Long studentId = examRecordData.getStudentId();
|
|
|
+
|
|
|
+ //是否进行活体检测
|
|
|
+ if (FaceBiopsyHelper.isFaceVerify(rootOrgId, examId, studentId)) {
|
|
|
+ FaceBiopsyScheme faceBiopsyScheme = FaceBiopsyHelper.getFaceBiopsyScheme(rootOrgId);
|
|
|
+ //新活体检测方案
|
|
|
+ if (faceBiopsyScheme == FaceBiopsyScheme.NEW) {
|
|
|
+ FaceBiopsyEntity faceBiopsy = faceBiopsyRepo.findByExamRecordDataId(examRecordData.getId());
|
|
|
+
|
|
|
+ //如果活检结果最终为true,只需要更新活检状态即可
|
|
|
+ if (faceBiopsy != null && faceBiopsy.getResult() != null && faceBiopsy.getResult()) {
|
|
|
+ return new CalcFaceBiopsyResultResp(IsSuccess.SUCCESS);
|
|
|
+ }
|
|
|
+
|
|
|
+ return new CalcFaceBiopsyResultResp(true, true, IsSuccess.FAILED);
|
|
|
+ }
|
|
|
+ //旧活体检测方案
|
|
|
+ else {
|
|
|
+ List<ExamFaceLivenessVerifyEntity> faceVerifies =
|
|
|
+ examFaceLivenessVerifyRepo.findByExamRecordDataIdOrderById(examRecordData.getId());
|
|
|
+
|
|
|
+ if (null != faceVerifies && faceVerifies.size() > 0) {
|
|
|
+ ExamFaceLivenessVerifyEntity latestFaceVerify = faceVerifies.get(faceVerifies.size() - 1);
|
|
|
+ //最后一次活检成功,则认为成功,并更新考试记录相关属性
|
|
|
+ if (latestFaceVerify != null && latestFaceVerify.getVerifyResult() != null &&
|
|
|
+ latestFaceVerify.getVerifyResult() == FaceVerifyResult.VERIFY_SUCCESS) {
|
|
|
+
|
|
|
+ return new CalcFaceBiopsyResultResp(IsSuccess.SUCCESS);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return new CalcFaceBiopsyResultResp(true, true, IsSuccess.FAILED);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return new CalcFaceBiopsyResultResp();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public CalcExamScoreResp calcExamScore(CalcExamScoreReq req) {
|
|
|
+
|
|
|
+ Long examRecordDataId = req.getExamRecordDataId();
|
|
|
+ //FIXME this is a bug .to be fix
|
|
|
+ ExamRecordQuestions examRecordQuestions = examRecordQuestionsService.getExamRecordQuestions(examRecordDataId,0);
|
|
|
+ // 考生作答记录明细
|
|
|
+ List<ExamQuestion> examQuestionList = examRecordQuestions.getExamQuestions();
|
|
|
+
|
|
|
+ double studentObjectiveScoreTotal = 0d;//客观题总分
|
|
|
+ int questionSuccessNum = 0;//答题正确数
|
|
|
+ int objectiveQuestionsNum = 0;//客观题总数
|
|
|
+
|
|
|
+ //计算客观题总得分和答题正确数
|
|
|
+ for (int i = 0; i < examQuestionList.size(); i++) {
|
|
|
+ ExamQuestion examQuestion = examQuestionList.get(i);
|
|
|
+
|
|
|
+ if (QuestionTypeUtil.isObjectiveQuestion(examQuestion.getQuestionType())) {
|
|
|
+ objectiveQuestionsNum++;
|
|
|
+
|
|
|
+ //如果标准答案为空,则更新标准答案
|
|
|
+ if (StringUtils.isEmpty(examQuestion.getCorrectAnswer())) {
|
|
|
+ updateCorrectAnswer(examRecordDataId, examQuestion);
|
|
|
+ }
|
|
|
+
|
|
|
+ //如果学生作答正确,则客观分累加,答题数累加
|
|
|
+ if (examQuestion.getStudentAnswer() != null
|
|
|
+ && examQuestion.getCorrectAnswer() != null
|
|
|
+ && examQuestion.getStudentAnswer().equals(examQuestion.getCorrectAnswer())) {
|
|
|
+ double questionScore = examQuestion.getQuestionScore().doubleValue();
|
|
|
+ BigDecimal bigDecimalQuestionScore = new BigDecimal(Double.toString(questionScore));
|
|
|
+ BigDecimal bigDecimalObjectiveScoreTotal = new BigDecimal(Double.toString(studentObjectiveScoreTotal));
|
|
|
+
|
|
|
+ studentObjectiveScoreTotal = bigDecimalQuestionScore.add(bigDecimalObjectiveScoreTotal).doubleValue();
|
|
|
+ questionSuccessNum++;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ //计算客观题答题正确率
|
|
|
+ double objectiveAccuracy = 0;
|
|
|
+ if (questionSuccessNum > 0 && objectiveQuestionsNum > 0) {
|
|
|
+ objectiveAccuracy = Double.valueOf(new DecimalFormat("#.00").format(questionSuccessNum * 100D / objectiveQuestionsNum));
|
|
|
+ }
|
|
|
+
|
|
|
+ CalcExamScoreResp resp = new CalcExamScoreResp();
|
|
|
+ resp.setObjectiveScore(studentObjectiveScoreTotal);
|
|
|
+ resp.setObjectiveAccuracy(objectiveAccuracy);
|
|
|
+ resp.setTotalScore(studentObjectiveScoreTotal);//交卷时,总分=客观分得分
|
|
|
+
|
|
|
+ return resp;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 更新客观题答案
|
|
|
+ *
|
|
|
+ * @param examRecordDataId
|
|
|
+ * @param examQuestion
|
|
|
+ */
|
|
|
+ private void updateCorrectAnswer(Long examRecordDataId, ExamQuestion examQuestion) {
|
|
|
+ QuestionAnswerCacheBean questionAnswerCache = CacheHelper.getQuestionAnswer(examQuestion.getQuestionId());
|
|
|
+ List<String> rightAnswerList = questionAnswerCache.getRightAnswers();
|
|
|
+ examQuestion.setCorrectAnswer(rightAnswerList.get(examQuestion.getOrder() - 1));
|
|
|
+
|
|
|
+ examRecordQuestionsService.saveExamQuestion(examRecordDataId, examQuestion.getOrder(), examQuestion);
|
|
|
+ }
|
|
|
}
|