|
@@ -0,0 +1,1514 @@
|
|
|
|
+package com.qmth.teachcloud.mark.service.impl;
|
|
|
|
+
|
|
|
|
+import com.alibaba.fastjson.JSON;
|
|
|
|
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
|
|
|
+import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
|
|
|
|
+import com.baomidou.mybatisplus.core.metadata.IPage;
|
|
|
|
+import com.baomidou.mybatisplus.core.metadata.OrderItem;
|
|
|
|
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
|
|
|
+import com.qmth.boot.api.exception.ApiException;
|
|
|
|
+import com.qmth.teachcloud.common.contant.SystemConstant;
|
|
|
|
+import com.qmth.teachcloud.common.entity.BasicCourse;
|
|
|
|
+import com.qmth.teachcloud.common.entity.MarkQuestion;
|
|
|
|
+import com.qmth.teachcloud.common.entity.SysUser;
|
|
|
|
+import com.qmth.teachcloud.common.enums.ExceptionResultEnum;
|
|
|
|
+import com.qmth.teachcloud.common.enums.ScorePolicy;
|
|
|
|
+import com.qmth.teachcloud.common.enums.mark.*;
|
|
|
|
+import com.qmth.teachcloud.common.service.BasicCourseService;
|
|
|
|
+import com.qmth.teachcloud.common.service.BasicOperationLogService;
|
|
|
|
+import com.qmth.teachcloud.common.service.SysUserService;
|
|
|
|
+import com.qmth.teachcloud.common.util.ServletUtil;
|
|
|
|
+import com.qmth.teachcloud.mark.dto.mark.ScoreItem;
|
|
|
|
+import com.qmth.teachcloud.mark.dto.mark.manage.Task;
|
|
|
|
+import com.qmth.teachcloud.mark.dto.mark.mark.MarkSettingDto;
|
|
|
|
+import com.qmth.teachcloud.mark.dto.mark.mark.MarkStatusDto;
|
|
|
|
+import com.qmth.teachcloud.mark.dto.mark.mark.SubmitResult;
|
|
|
|
+import com.qmth.teachcloud.mark.entity.*;
|
|
|
|
+import com.qmth.teachcloud.mark.enums.ExamType;
|
|
|
|
+import com.qmth.teachcloud.mark.enums.LockType;
|
|
|
|
+import com.qmth.teachcloud.mark.enums.MarkTaskStatus;
|
|
|
|
+import com.qmth.teachcloud.mark.enums.QuestionModel;
|
|
|
|
+import com.qmth.teachcloud.mark.lock.LockService;
|
|
|
|
+import com.qmth.teachcloud.mark.params.MarkArbitrateResult;
|
|
|
|
+import com.qmth.teachcloud.mark.params.MarkResult;
|
|
|
|
+import com.qmth.teachcloud.mark.params.MarkResultQuestion;
|
|
|
|
+import com.qmth.teachcloud.mark.service.*;
|
|
|
|
+import com.qmth.teachcloud.mark.utils.BigDecimalUtils;
|
|
|
|
+import com.qmth.teachcloud.mark.utils.TaskLock;
|
|
|
|
+import com.qmth.teachcloud.mark.utils.TaskLockUtil;
|
|
|
|
+import io.lettuce.core.GeoArgs.Sort;
|
|
|
|
+import org.apache.commons.collections4.CollectionUtils;
|
|
|
|
+import org.slf4j.Logger;
|
|
|
|
+import org.slf4j.LoggerFactory;
|
|
|
|
+import org.springframework.stereotype.Service;
|
|
|
|
+import org.springframework.transaction.annotation.Transactional;
|
|
|
|
+
|
|
|
|
+import javax.annotation.Resource;
|
|
|
|
+import java.math.BigDecimal;
|
|
|
|
+import java.util.*;
|
|
|
|
+import java.util.concurrent.ConcurrentHashMap;
|
|
|
|
+import java.util.function.Function;
|
|
|
|
+import java.util.stream.Collectors;
|
|
|
|
+
|
|
|
|
+@Service
|
|
|
|
+public class AiMarkServiceImpl implements AiMarkService {
|
|
|
|
+
|
|
|
|
+ private final static Logger log = LoggerFactory.getLogger(AiMarkServiceImpl.class);
|
|
|
|
+
|
|
|
|
+ private Map<Long, Long> markerLastUpdateTime = new ConcurrentHashMap<>();
|
|
|
|
+
|
|
|
|
+ @Resource
|
|
|
|
+ private BasicCourseService basicCourseService;
|
|
|
|
+ @Resource
|
|
|
|
+ private MarkPaperService markPaperService;
|
|
|
|
+
|
|
|
|
+ @Resource
|
|
|
|
+ private MarkQuestionService markQuestionService;
|
|
|
|
+ @Resource
|
|
|
|
+ private MarkUserPaperService markUserPaperService;
|
|
|
|
+ @Resource
|
|
|
|
+ private MarkUserQuestionService markUserQuestionService;
|
|
|
|
+ @Resource
|
|
|
|
+ private MarkUserClassService markUserClassService;
|
|
|
|
+
|
|
|
|
+ @Resource
|
|
|
|
+ private MarkTaskService markTaskService;
|
|
|
|
+
|
|
|
|
+ @Resource
|
|
|
|
+ private MarkStudentService markStudentService;
|
|
|
|
+
|
|
|
|
+ @Resource
|
|
|
|
+ private MarkProblemHistoryService markProblemHistoryService;
|
|
|
|
+
|
|
|
|
+ @Resource
|
|
|
|
+ private MarkArbitrateHistoryService markArbitrateHistoryService;
|
|
|
|
+
|
|
|
|
+ @Resource
|
|
|
|
+ private MarkSubjectiveScoreService markSubjectiveScoreService;
|
|
|
|
+ @Resource
|
|
|
|
+ LockService lockService;
|
|
|
|
+
|
|
|
|
+ @Resource
|
|
|
|
+ ScanAnswerCardService scanAnswerCardService;
|
|
|
|
+
|
|
|
|
+ @Resource
|
|
|
|
+ TaskService taskService;
|
|
|
|
+
|
|
|
|
+ @Resource
|
|
|
|
+ private MarkHeaderHistoryService markHeaderHistoryService;
|
|
|
|
+ @Resource
|
|
|
|
+ private SysUserService sysUserService;
|
|
|
|
+ @Resource
|
|
|
|
+ private MarkRejectHistoryService markRejectHistoryService;
|
|
|
|
+ @Resource
|
|
|
|
+ private BasicOperationLogService basicOperationLogService;
|
|
|
|
+ @Resource
|
|
|
|
+ private MarkAiQuestionParamService markAiQuestionParamService;
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 释放某个评卷员的考生
|
|
|
|
+ *
|
|
|
|
+ * @param exmId 考试ID
|
|
|
|
+ * @param paperNumber 试卷编号
|
|
|
|
+ * @param studentId 考生ID
|
|
|
|
+ * @param userId 用户ID
|
|
|
|
+ */
|
|
|
|
+ @Override
|
|
|
|
+ public void releaseStudent(Long exmId, String paperNumber, Long studentId, Long userId) {
|
|
|
|
+ if (studentId != null) {
|
|
|
|
+ TaskLock taskLock = TaskLockUtil.getFormalTask(getKey(exmId, paperNumber));
|
|
|
|
+ taskLock.remove(studentId, userId);
|
|
|
|
+ taskLock.refresh(userId);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 某个评卷分组已申请的评卷任务数量
|
|
|
|
+ *
|
|
|
|
+ * @return
|
|
|
|
+ */
|
|
|
|
+ @Override
|
|
|
|
+ public int applyCurrentCount(MarkQuestion markQuestion) {
|
|
|
|
+ TaskLock taskLock = getTaskLock(markQuestion);
|
|
|
|
+ int count = 0;
|
|
|
|
+ if (taskLock != null) {
|
|
|
|
+ count = taskLock.count(markQuestion.getId());
|
|
|
|
+ }
|
|
|
|
+ return count;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @Override
|
|
|
|
+ public Set<Long> listCurrentStudent(Long examId, String paperNumber) {
|
|
|
|
+ TaskLock taskLock = TaskLockUtil.getFormalTask(examId + "_" + paperNumber);
|
|
|
|
+ return taskLock.list().stream().map(m -> Long.valueOf(m.get("studentId").toString())).collect(Collectors.toSet());
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private TaskLock getTaskLock(MarkQuestion markQuestion) {
|
|
|
|
+ MarkPaper markPaper = markPaperService.getByExamIdAndPaperNumber(markQuestion.getExamId(),
|
|
|
|
+ markQuestion.getPaperNumber());
|
|
|
|
+ if (markPaper.getStatus() == MarkPaperStatus.FORMAL) {
|
|
|
|
+ return TaskLockUtil.getFormalTask(getKey(markQuestion.getExamId(), markQuestion.getPaperNumber()));
|
|
|
|
+ }
|
|
|
|
+ return null;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 释放某个评卷员的所有锁定任务
|
|
|
|
+ *
|
|
|
|
+ * @param markUserQuestion
|
|
|
|
+ */
|
|
|
|
+ @Override
|
|
|
|
+ public void releaseByMarkUserGroup(MarkUserQuestion markUserQuestion) {
|
|
|
|
+ TaskLock taskLock = TaskLockUtil.getFormalTask(getKey(markUserQuestion.getExamId(), markUserQuestion.getPaperNumber()));
|
|
|
|
+ taskLock.clear(markUserQuestion.getUserId());
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @Override
|
|
|
|
+ public int applyCurrentCount(MarkQuestion markQuestion, Long userId) {
|
|
|
|
+ int count = 0;
|
|
|
|
+ TaskLock taskLock = getTaskLock(markQuestion);
|
|
|
|
+ if (taskLock != null) {
|
|
|
|
+ count = taskLock.count(markQuestion.getId(), userId);
|
|
|
|
+ }
|
|
|
|
+ return count;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @Override
|
|
|
|
+ public void resetMarker(MarkUserQuestion markUserQuestion) {
|
|
|
|
+ Long examId = markUserQuestion.getExamId();
|
|
|
|
+ String paperNumber = markUserQuestion.getPaperNumber();
|
|
|
|
+ Long questionId = markUserQuestion.getQuestionId();
|
|
|
|
+ Long userId = markUserQuestion.getUserId();
|
|
|
|
+ MarkPaper markPaper = markPaperService.getByExamIdAndPaperNumber(examId, paperNumber);
|
|
|
|
+ if (markPaper == null || markUserQuestionService.getById(markUserQuestion.getId()) == null) {
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ if (markPaper.getStatus() == MarkPaperStatus.FORMAL) {
|
|
|
|
+ // 遍历相关评卷任务的模式
|
|
|
|
+ List<MarkTaskStatus> statusList = Arrays.asList(MarkTaskStatus.WAITING);
|
|
|
|
+ List<MarkTask> markTaskList = markTaskService.listByExamIdAndPaperNumberAndQuestionIdAndUserIdAndStatusNotIn(examId, paperNumber, questionId, userId, statusList);
|
|
|
|
+ for (MarkTask markTask : markTaskList) {
|
|
|
|
+ Long studentId = markTask.getStudentId();
|
|
|
|
+ if (MarkTaskStatus.ARBITRATED.equals(markTask.getStatus()) || MarkTaskStatus.WAIT_ARBITRATE.equals(markTask.getStatus())) {
|
|
|
|
+ markTaskService.resetArbitrateStatusByStudentIdAndQuestionIdAndTaskNumber(studentId, questionId, markTask.getTaskNumber());
|
|
|
|
+ }
|
|
|
|
+ markTaskService.resetById(markTask.getId(), null, null, null, null, MarkTaskStatus.WAITING);
|
|
|
|
+ markSubjectiveScoreService.deleteByStudentIdAndQuestionId(studentId, questionId);
|
|
|
|
+ markProblemHistoryService.deleteByExamIdAndPaperNumberAndTaskId(examId, paperNumber, markTask.getId());
|
|
|
|
+ markRejectHistoryService.deleteByTaskId(markTask.getId());
|
|
|
|
+ markArbitrateHistoryService.deleteByExamIdAndPaperNumberAndStudentIdAndQuestionId(examId, paperNumber, studentId, questionId);
|
|
|
|
+ lockService.waitlock(LockType.STUDENT, markTask.getStudentId());
|
|
|
|
+ markStudentService.updateSubjectiveStatusAndScore(studentId, SubjectiveStatus.UNMARK);
|
|
|
|
+ lockService.unlock(LockType.STUDENT, markTask.getStudentId());
|
|
|
|
+ }
|
|
|
|
+ markUserQuestionService.resetById(markUserQuestion.getId());
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+ this.updateMarkedCount(examId, paperNumber, questionId);
|
|
|
|
+ releaseByMarkUserGroup(markUserQuestion);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @Override
|
|
|
|
+ public void updateMarkedCount(Long examId, String paperNumber, Long questionId) {
|
|
|
|
+ List<MarkTaskStatus> markTaskStatuses = Arrays.asList(MarkTaskStatus.MARKED, MarkTaskStatus.ARBITRATED);
|
|
|
|
+ //查询已评和已仲裁的任务数
|
|
|
|
+ int count = markTaskService.countByExamIdAndPaperNumberAndQuestionIdAndStatusIn(examId, paperNumber,
|
|
|
|
+ questionId, markTaskStatuses);
|
|
|
|
+ //更新当前小题的已评数量
|
|
|
|
+ markQuestionService.updateMarkedCount(questionId, count);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @Override
|
|
|
|
+ public void updatePersonTask(Long examId, String paperNumber, Long questionId) {
|
|
|
|
+ QueryWrapper<MarkTask> queryWrapper = new QueryWrapper<>();
|
|
|
|
+ queryWrapper.lambda().eq(MarkTask::getExamId, examId)
|
|
|
|
+ .eq(MarkTask::getPaperNumber, paperNumber)
|
|
|
|
+ .eq(MarkTask::getQuestionId, questionId)
|
|
|
|
+ .last(" limit 1");
|
|
|
|
+ MarkTask markTask = markTaskService.getOne(queryWrapper);
|
|
|
|
+
|
|
|
|
+ UpdateWrapper<MarkQuestion> updateWrapper = new UpdateWrapper<>();
|
|
|
|
+ updateWrapper.lambda().set(MarkQuestion::getPersonTask, markTask != null)
|
|
|
|
+ .eq(MarkQuestion::getId, questionId);
|
|
|
|
+ markQuestionService.update(updateWrapper);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @Override
|
|
|
|
+ public boolean rejectMarkTask(MarkProblemHistory markProblemHistory, MarkTask markTask, Long userId) {
|
|
|
|
+ MarkPaper markPaper = markPaperService.getByExamIdAndPaperNumber(markTask.getExamId(), markTask.getPaperNumber());
|
|
|
|
+ if (markPaper.getStatus() == MarkPaperStatus.FINISH) {
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+ Long now = System.currentTimeMillis();
|
|
|
|
+ if (markTaskService.resetById(markTask.getId(), null, null, userId, now, MarkTaskStatus.WAITING)) {
|
|
|
|
+ resetStudentStatus(markTask.getStudentId());
|
|
|
|
+ markProblemHistoryService.resetByMarkProblemId(markProblemHistory.getId(), MarkProblemStatus.WAITING,
|
|
|
|
+ userId, MarkProblemStatus.BACK, now);
|
|
|
|
+ updateMarkedCount(markTask.getExamId(), markTask.getPaperNumber(), markTask.getQuestionId());
|
|
|
|
+ return true;
|
|
|
|
+ } else {
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private void resetStudentStatus(Long studentId) {
|
|
|
|
+ markStudentService.updateSubjectiveStatusAndScore(studentId, SubjectiveStatus.UNMARK);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ @Override
|
|
|
|
+ public String getGroupKey(MarkQuestion markQuestion) {
|
|
|
|
+ return getKey(markQuestion.getExamId(), markQuestion.getPaperNumber());
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @Override
|
|
|
|
+ public void updateQuality(MarkUserQuestion markUserQuestion) {
|
|
|
|
+ List<MarkTask> list = markTaskService.listByExamIdAndPaperNumberAndQuestionIdAndUserIdAndClassName(
|
|
|
|
+ markUserQuestion.getExamId(), markUserQuestion.getPaperNumber(), markUserQuestion.getQuestionId(),
|
|
|
|
+ markUserQuestion.getUserId(), null);
|
|
|
|
+ int finishCount = 0;
|
|
|
|
+ int validCount = 0;
|
|
|
|
+ int headerFinishCount = 0;
|
|
|
|
+ double sumScore = 0;
|
|
|
|
+ double sumScore2 = 0;
|
|
|
|
+ double avgScore = 0;
|
|
|
|
+ double stdevScore = 0;
|
|
|
|
+ double sumSpent = 0;
|
|
|
|
+ double avgSpent = 0;
|
|
|
|
+ double maxScore = 0;
|
|
|
|
+ double minScore = 0;
|
|
|
|
+ for (MarkTask markTask : list) {
|
|
|
|
+ if (!markTask.getStatus().equals(MarkTaskStatus.PROBLEM)) {
|
|
|
|
+ finishCount++;
|
|
|
|
+ }
|
|
|
|
+ if (markTask.getStatus() == MarkTaskStatus.MARKED && markTask.getHeaderScore() == null) {
|
|
|
|
+ validCount++;
|
|
|
|
+ }
|
|
|
|
+ // 管理员打分数量(主观题检查,仲裁)
|
|
|
|
+ if ((markTask.getStatus() == MarkTaskStatus.MARKED || markTask.getStatus() == MarkTaskStatus.ARBITRATED) && markTask.getHeaderScore() != null) {
|
|
|
|
+ headerFinishCount++;
|
|
|
|
+ }
|
|
|
|
+ double score = markTask.getMarkerScore() != null ? markTask.getMarkerScore() : 0;
|
|
|
|
+ int spent = markTask.getMarkerSpent() != null ? markTask.getMarkerSpent() : 0;
|
|
|
|
+
|
|
|
|
+ sumScore += score;
|
|
|
|
+ sumScore2 += Math.pow(score, 2);
|
|
|
|
+ sumSpent += spent;
|
|
|
|
+ if (finishCount > 0) {
|
|
|
|
+ avgScore = sumScore / finishCount;
|
|
|
|
+ avgSpent = sumSpent / finishCount;
|
|
|
|
+ // 递归法计算标准差
|
|
|
|
+ stdevScore = Math.sqrt(sumScore2 / finishCount - Math.pow(sumScore / finishCount, 2));
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 最高分
|
|
|
|
+ if (score > maxScore) {
|
|
|
|
+ maxScore = score;
|
|
|
|
+ }
|
|
|
|
+ // 最低分
|
|
|
|
+ if (finishCount == 1) {
|
|
|
|
+ minScore = score;
|
|
|
|
+ } else if (score < minScore) {
|
|
|
|
+ minScore = score;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ markUserQuestionService.updateQualityById(markUserQuestion.getId(), finishCount, headerFinishCount, validCount,
|
|
|
|
+ avgSpent / 1000, avgScore, stdevScore, maxScore, minScore);
|
|
|
|
+ markerLastUpdateTime.put(markUserQuestion.getId(), System.currentTimeMillis());
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @Override
|
|
|
|
+ public boolean needUpdateQuality(MarkUserQuestion markUserQuestion, int expireMinutes) {
|
|
|
|
+ if (markUserQuestion == null) {
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+ Long lastUpdateTime = markerLastUpdateTime.get(markUserQuestion.getId());
|
|
|
|
+ MarkTask markTask = markTaskService.getLastOneByUserIdAndStatus(markUserQuestion.getExamId(),
|
|
|
|
+ markUserQuestion.getPaperNumber(), markUserQuestion.getQuestionId(), markUserQuestion.getUserId(),
|
|
|
|
+ MarkTaskStatus.MARKED);
|
|
|
|
+ if (markTask != null && markTask.getMarkerTime() != null) {
|
|
|
|
+ long lastMarkTime = markTask.getMarkerTime();
|
|
|
|
+ if (lastUpdateTime != null && lastUpdateTime > lastMarkTime) {
|
|
|
|
+ return false;
|
|
|
|
+ } else {
|
|
|
|
+ return (System.currentTimeMillis() - lastMarkTime) < (expireMinutes * 60 * 1000);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 管理员/组长处理仲裁卷
|
|
|
|
+ *
|
|
|
|
+ * @param markResult
|
|
|
|
+ * @param userId
|
|
|
|
+ */
|
|
|
|
+ @Transactional
|
|
|
|
+ @Override
|
|
|
|
+ public void processArbitrate(MarkArbitrateResult markResult, Long userId) {
|
|
|
|
+ MarkArbitrateHistory markArbitrateHistory = markArbitrateHistoryService.getById(markResult.getArbitrateId());
|
|
|
|
+ markArbitrateHistory.setUpdateUserId(userId);
|
|
|
|
+ markArbitrateHistory.setTotalScore(markResult.getMarkerScore());
|
|
|
|
+// markArbitrateHistory.setScoreList(markResult.isUnselective() ? null : markResult.getScoreList());
|
|
|
|
+ markArbitrateHistory.setStatus(MarkArbitrateStatus.MARKED);
|
|
|
|
+ markArbitrateHistory.setUpdateTime(System.currentTimeMillis());
|
|
|
|
+// // 保存阅卷轨迹
|
|
|
|
+// if (markResult.getTrackList() != null && !markResult.isUnselective()) {
|
|
|
|
+// markHeaderTrackService.deleteByExamIdAndPaperNumberAndGroupNumberAndStudentId(
|
|
|
|
+// markArbitrateHistory.getExamId(), markArbitrateHistory.getPaperNumber(),
|
|
|
|
+// markArbitrateHistory.getGroupNumber(), markArbitrateHistory.getStudentId());
|
|
|
|
+// List<MarkHeaderTrack> tracks = markResult.getTrackList(markArbitrateHistory);
|
|
|
|
+// markHeaderTrackService.saveOrUpdateBatchByMultiId(tracks);
|
|
|
|
+// }
|
|
|
|
+// // 保存特殊标记
|
|
|
|
+// if (markResult.getSpecialTagList() != null) {
|
|
|
|
+// markHeaderTagService.deleteByStudentIdAndGroupNumber(markArbitrateHistory.getStudentId(),
|
|
|
|
+// markArbitrateHistory.getGroupNumber());
|
|
|
|
+// markHeaderTagService.saveBatch(markResult.getHeaderTagList(markArbitrateHistory));
|
|
|
|
+// }
|
|
|
|
+ markArbitrateHistoryService.saveOrUpdate(markArbitrateHistory);
|
|
|
|
+ markTaskService.updateHeaderResult(markArbitrateHistory.getExamId(), markArbitrateHistory.getPaperNumber(),
|
|
|
|
+ markArbitrateHistory.getQuestionId(), markArbitrateHistory.getStudentId(),
|
|
|
|
+ markArbitrateHistory.getUpdateUserId(), markResult.getMarkerScore(), markResult.getMarkerTrackList(), markResult.getMarkerTagList(), markArbitrateHistory.getUpdateTime(), MarkTaskStatus.ARBITRATED);
|
|
|
|
+ updateMarkedCount(markArbitrateHistory.getExamId(), markArbitrateHistory.getPaperNumber(),
|
|
|
|
+ markArbitrateHistory.getQuestionId());
|
|
|
|
+ MarkQuestion markQuestion = markQuestionService.getById(markArbitrateHistory.getQuestionId());
|
|
|
|
+ markQuestion.setMarkScore(markResult.getMarkerScore());
|
|
|
|
+ checkStudentQuestion(markArbitrateHistory.getStudentId(), markQuestion);
|
|
|
|
+ // 评卷质量重新统计
|
|
|
|
+ List<MarkUserQuestion> markUserGroups = markUserQuestionService.listByExamIdAndPaperNumberAndQuestionId(markArbitrateHistory.getExamId(), markArbitrateHistory.getPaperNumber(), markArbitrateHistory.getQuestionId());
|
|
|
|
+ markUserGroups.forEach(m -> this.updateQuality(m));
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 考生分组判断是否评卷完成,以及后续的统一处理动作
|
|
|
|
+ *
|
|
|
|
+ * @param studentId
|
|
|
|
+ * @param markQuestion
|
|
|
|
+ */
|
|
|
|
+ private void checkStudentQuestion(Long studentId, MarkQuestion markQuestion) {
|
|
|
|
+ if (calculateQuestion(markQuestion, studentId)) {
|
|
|
|
+ //更新考生分组分数
|
|
|
|
+ updateStudentQuestionScore(studentId, markQuestion, markQuestion.getMarkScore());
|
|
|
|
+// checkStudentSubjective(studentId, markQuestion.getExamId(), markQuestion.getPaperNumber(), version);
|
|
|
|
+ } else {
|
|
|
|
+ markStudentService.updateSubjectiveStatusAndScore(studentId, SubjectiveStatus.UNMARK);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private void checkStudentQuestionForInspect(MarkStudent markStudent, MarkQuestion markQuestion) {
|
|
|
|
+ Long studentId = markStudent.getId();
|
|
|
|
+ if (calculateQuestion(markQuestion, studentId)) {
|
|
|
|
+ //更新考生分组分数
|
|
|
|
+ updateStudentQuestionScore(studentId, markQuestion, markQuestion.getMarkScore());
|
|
|
|
+ checkStudentSubjective(studentId, markQuestion.getExamId(), markQuestion.getPaperNumber(), markStudent.getVersion(), false);
|
|
|
|
+ } else {
|
|
|
|
+ markStudentService.updateSubjectiveStatusAndScore(studentId, SubjectiveStatus.UNMARK);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @Override
|
|
|
|
+ @Transactional
|
|
|
|
+ public void checkStudentSubjective(Long studentId, Long examId, String paperNumber, Integer version, boolean autoCalc) {
|
|
|
|
+ try {
|
|
|
|
+ List<MarkQuestion> markQuestionList = markQuestionService.listByExamIdAndPaperNumberAndObjective(examId, paperNumber, false);
|
|
|
|
+ List<MarkSubjectiveScore> markSubjectiveScoreList = markSubjectiveScoreService.listByStudentIdAndExamIdAndPn(studentId, examId, paperNumber);
|
|
|
|
+ //校验阅卷题目和评分题目数量和题型是否一致
|
|
|
|
+ if (CollectionUtils.isNotEmpty(markQuestionList) && CollectionUtils.isNotEmpty(markSubjectiveScoreList)
|
|
|
|
+ && this.megreQuestion(markQuestionList, markSubjectiveScoreList)) {
|
|
|
|
+ scoreCalculate(studentId, version, autoCalc);
|
|
|
|
+ }
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
+ log.error(SystemConstant.LOG_ERROR, e);
|
|
|
|
+ throw ExceptionResultEnum.ERROR.exception(e.getMessage());
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 题型匹配
|
|
|
|
+ *
|
|
|
|
+ * @param markQuestionList
|
|
|
|
+ * @param markSubjectiveScoreList
|
|
|
|
+ * @return
|
|
|
|
+ */
|
|
|
|
+ protected boolean megreQuestion(List<MarkQuestion> markQuestionList, List<MarkSubjectiveScore> markSubjectiveScoreList) {
|
|
|
|
+ boolean calculate = true;
|
|
|
|
+ Map<String, MarkQuestion> markQuestionMap = markQuestionList.stream().collect(Collectors.toMap(k -> k.getMainNumber() + "-" + k.getSubNumber(), Function.identity(), (dto1, dto2) -> dto1));
|
|
|
|
+ Map<String, MarkSubjectiveScore> markSubjectiveScoreMap = markSubjectiveScoreList.stream().collect(Collectors.toMap(k -> k.getMainNumber() + "-" + k.getSubNumber(), Function.identity(), (dto1, dto2) -> dto1));
|
|
|
|
+ if (markQuestionMap.size() != markSubjectiveScoreMap.size()) {
|
|
|
|
+ calculate = false;
|
|
|
|
+ }
|
|
|
|
+ if (calculate) {
|
|
|
|
+ for (Map.Entry<String, MarkQuestion> entry : markQuestionMap.entrySet()) {
|
|
|
|
+ if (!markSubjectiveScoreMap.containsKey(entry.getKey())) {
|
|
|
|
+ calculate = false;
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ return calculate;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @Override
|
|
|
|
+ public void buildMarkTask(MarkPaper markPaper) {
|
|
|
|
+ try {
|
|
|
|
+ lockService.watch(LockType.EXAM_SUBJECT, markPaper.getExamId(), markPaper.getPaperNumber());
|
|
|
|
+ log.info("start create mark_task for examId=" + markPaper.getExamId() + ", paperNumber="
|
|
|
|
+ + markPaper.getPaperNumber());
|
|
|
|
+ // 清除缺考考生和违纪考生(违纪考生参与阅卷,update by 2024-10-17)
|
|
|
|
+ List<MarkStudent> markStudentList = markStudentService
|
|
|
|
+ .listAbsentOrBreachMarkTaskStudent(markPaper.getExamId(), markPaper.getPaperNumber());
|
|
|
|
+ if (CollectionUtils.isNotEmpty(markStudentList)) {
|
|
|
|
+ for (MarkStudent student : markStudentList) {
|
|
|
|
+ try {
|
|
|
|
+ lockService.waitlock(LockType.STUDENT, student.getId());
|
|
|
|
+ log.info("delete mark_task for studentId=" + student.getId());
|
|
|
|
+ this.deleteMarkTaskByStudent(student);
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
+ log.error("delete student mark_task error", e);
|
|
|
|
+ } finally {
|
|
|
|
+ lockService.unlock(LockType.STUDENT, student.getId());
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ // 处理正常考生
|
|
|
|
+ List<MarkQuestion> markQuestionList = markQuestionService.listByExamIdAndPaperNumberAndObjective(markPaper.getExamId(), markPaper.getPaperNumber(), false);
|
|
|
|
+ for (MarkQuestion markQuestion : markQuestionList) {
|
|
|
|
+ if (!MarkPaperAiMark.NONE.equals(markQuestion.getAiMark()) && !markAiQuestionParamService.existMarkAiQuestionScoreOrLevel(markQuestion.getExamId(), markQuestion.getPaperNumber(), markQuestion.getId())) {
|
|
|
|
+ continue;
|
|
|
|
+ }
|
|
|
|
+ // 生成正评任务
|
|
|
|
+ buildFormalTask(markQuestion);
|
|
|
|
+ if (markQuestion.getDoubleRate() != null && markQuestion.getDoubleRate() > 0) {
|
|
|
|
+ // 补双评任务
|
|
|
|
+ fillFormalTask(markQuestion);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ } finally {
|
|
|
|
+ lockService.unwatch(LockType.EXAM_SUBJECT, markPaper.getExamId(), markPaper.getPaperNumber());
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private void buildFormalTask(MarkQuestion markQuestion) {
|
|
|
|
+ int pageSize = 100;
|
|
|
|
+ try {
|
|
|
|
+ lockService.watch(LockType.QUESTION, markQuestion.getId());
|
|
|
|
+ // 上锁后重复验证分组状态
|
|
|
|
+ MarkPaper markPaper = markPaperService.getByExamIdAndPaperNumber(markQuestion.getExamId(), markQuestion.getPaperNumber());
|
|
|
|
+ if (MarkPaperStatus.FINISH.equals(markPaper.getStatus())) {
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ int count = 0;
|
|
|
|
+ List<MarkStudent> studentList = markStudentService.listUnMarkTaskStudent(markQuestion.getExamId(), markQuestion.getPaperNumber(), markQuestion.getId(), pageSize);
|
|
|
|
+ while (CollectionUtils.isNotEmpty(studentList)) {
|
|
|
|
+ // 已生成的双评任务总数的第一组任务数
|
|
|
|
+ int doubleMarkTaskCount1 = markTaskService.countByExamIdAndPaperNumberAndQuestionIdAndTaskNumber(
|
|
|
|
+ markQuestion.getExamId(), markQuestion.getPaperNumber(), markQuestion.getId(), 1);
|
|
|
|
+ // 已生成的双评任务总数的第二组任务数
|
|
|
|
+ int doubleMarkTaskCount2 = markTaskService.countByExamIdAndPaperNumberAndQuestionIdAndTaskNumber(
|
|
|
|
+ markQuestion.getExamId(), markQuestion.getPaperNumber(), markQuestion.getId(), 2);
|
|
|
|
+ List<MarkTask> taskList = new ArrayList<>();
|
|
|
|
+ int doubleCount = 0;
|
|
|
|
+ int studentCount = studentList.size();
|
|
|
|
+ for (MarkStudent student : studentList) {
|
|
|
|
+ MarkTask markTask = new MarkTask();
|
|
|
|
+ markTask.setId(SystemConstant.getDbUuid());
|
|
|
|
+ markTask.setExamId(student.getExamId());
|
|
|
|
+ markTask.setCourseId(student.getCourseId());
|
|
|
|
+ markTask.setPaperNumber(student.getPaperNumber());
|
|
|
|
+ markTask.setQuestionId(markQuestion.getId());
|
|
|
|
+ markTask.setMainNumber(markQuestion.getMainNumber());
|
|
|
|
+ markTask.setSubNumber(markQuestion.getSubNumber());
|
|
|
|
+ markTask.setStudentId(student.getId());
|
|
|
|
+ markTask.setBasicStudentId(student.getBasicStudentId());
|
|
|
|
+ markTask.setStudentCode(student.getStudentCode());
|
|
|
|
+ markTask.setSecretNumber(student.getSecretNumber());
|
|
|
|
+ markTask.setTaskNumber(1);
|
|
|
|
+ markTask.setAiMarked(getAiMarked(markQuestion, markTask.getTaskNumber()));
|
|
|
|
+ markTask.setStatus(MarkTaskStatus.WAITING);
|
|
|
|
+ taskList.add(markTask);
|
|
|
|
+ // 开启双评时需要判断是否生成第二份评卷任务
|
|
|
|
+ if (markQuestion.getDoubleRate() != null && markQuestion.getDoubleRate() > 0) {
|
|
|
|
+ boolean needDouble;
|
|
|
|
+ if (markQuestion.getDoubleRate() == 100) {
|
|
|
|
+ needDouble = true;
|
|
|
|
+ } else {
|
|
|
|
+ double libraryCount = taskList.size();
|
|
|
|
+ int expectCount = (int) ((doubleMarkTaskCount1 + studentCount) * markQuestion.getDoubleRate()
|
|
|
|
+ / 100);
|
|
|
|
+ // 随机数判断加入当前已经生成双评任务的比例加权
|
|
|
|
+ // 实际双评任务数小于理论生成数 &&(剩余未生成双评的考生数量小于剩余应生成的数量)
|
|
|
|
+ needDouble = (doubleMarkTaskCount2 + doubleCount) < expectCount
|
|
|
|
+ && ((studentCount - libraryCount + doubleCount) <= (expectCount
|
|
|
|
+ - doubleMarkTaskCount2 - doubleCount));
|
|
|
|
+ }
|
|
|
|
+ if (needDouble) {
|
|
|
|
+ markTask = new MarkTask();
|
|
|
|
+ markTask.setId(SystemConstant.getDbUuid());
|
|
|
|
+ markTask.setExamId(student.getExamId());
|
|
|
|
+ markTask.setCourseId(student.getCourseId());
|
|
|
|
+ markTask.setPaperNumber(student.getPaperNumber());
|
|
|
|
+ markTask.setQuestionId(markQuestion.getId());
|
|
|
|
+ markTask.setMainNumber(markQuestion.getMainNumber());
|
|
|
|
+ markTask.setSubNumber(markQuestion.getSubNumber());
|
|
|
|
+ markTask.setStudentId(student.getId());
|
|
|
|
+ markTask.setBasicStudentId(student.getBasicStudentId());
|
|
|
|
+ markTask.setStudentCode(student.getStudentCode());
|
|
|
|
+ markTask.setSecretNumber(student.getSecretNumber());
|
|
|
|
+ markTask.setTaskNumber(2);
|
|
|
|
+ markTask.setAiMarked(getAiMarked(markQuestion, markTask.getTaskNumber()));
|
|
|
|
+ markTask.setStatus(MarkTaskStatus.WAITING);
|
|
|
|
+ taskList.add(markTask);
|
|
|
|
+ doubleCount++;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ // 有新任务创建
|
|
|
|
+ if (CollectionUtils.isNotEmpty(taskList)) {
|
|
|
|
+ count += taskList.size();
|
|
|
|
+ // 任务乱序
|
|
|
|
+ Collections.shuffle(taskList);
|
|
|
|
+ // 批量保存
|
|
|
|
+ markTaskService.saveBatch(taskList);
|
|
|
|
+ // 正评状态才需要更新任务数量
|
|
|
|
+ if (MarkPaperStatus.FORMAL.equals(markPaper.getStatus())) {
|
|
|
|
+ this.updateMarkTaskCount(markQuestion.getExamId(), markQuestion.getPaperNumber(), markQuestion.getId());
|
|
|
|
+ this.updateMarkedCount(markQuestion.getExamId(), markQuestion.getPaperNumber(), markQuestion.getId());
|
|
|
|
+ this.updatePersonTask(markQuestion.getExamId(), markQuestion.getPaperNumber(), markQuestion.getId());
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ studentList = markStudentService.listUnMarkTaskStudent(markQuestion.getExamId(), markQuestion.getPaperNumber(), markQuestion.getId(), pageSize);
|
|
|
|
+ }
|
|
|
|
+ if (count != 0) {
|
|
|
|
+ log.info("finish create " + count + " markTask for examId=" + markQuestion.getExamId() + ", paperNumber="
|
|
|
|
+ + markQuestion.getPaperNumber() + ", questionId=" + markQuestion.getId());
|
|
|
|
+ }
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
+ log.error("build formal markTask error for examId=" + markQuestion.getExamId() + ", paperNumber="
|
|
|
|
+ + markQuestion.getPaperNumber() + ", questionId=" + markQuestion.getId(), e);
|
|
|
|
+ } finally {
|
|
|
|
+ lockService.unwatch(LockType.QUESTION, markQuestion.getId());
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private Boolean getAiMarked(MarkQuestion markQuestion, Integer taskNumber) {
|
|
|
|
+ if (MarkPaperAiMark.NONE.equals(markQuestion.getAiMark())) {
|
|
|
|
+ return false;
|
|
|
|
+ } else if (MarkPaperAiMark.AI_ONLY.equals(markQuestion.getAiMark()) || MarkPaperAiMark.MAN_MACHINE.equals(markQuestion.getAiMark())) {
|
|
|
|
+ return taskNumber == 1;
|
|
|
|
+ } else {
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private void fillFormalTask(MarkQuestion markQuestion) {
|
|
|
|
+ int pageSize = 100;
|
|
|
|
+ try {
|
|
|
|
+ lockService.watch(LockType.QUESTION, markQuestion.getId());
|
|
|
|
+ // 上锁后重复验证分组状态
|
|
|
|
+ MarkPaper markPaper = markPaperService.getByExamIdAndPaperNumber(markQuestion.getExamId(), markQuestion.getPaperNumber());
|
|
|
|
+ if (MarkPaperStatus.FINISH.equals(markPaper.getStatus())) {
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ int count = 0;
|
|
|
|
+ List<MarkStudent> studentList = markStudentService.listUnMarkDoubleTaskStudent(markQuestion.getExamId(), markQuestion.getPaperNumber(), markQuestion.getId(), pageSize);
|
|
|
|
+ while (CollectionUtils.isNotEmpty(studentList)) {
|
|
|
|
+ // 已生成的双评任务总数的第一组任务数
|
|
|
|
+ int doubleMarkTaskCount1 = markTaskService.countByExamIdAndPaperNumberAndQuestionIdAndTaskNumber(
|
|
|
|
+ markQuestion.getExamId(), markQuestion.getPaperNumber(), markQuestion.getId(), 1);
|
|
|
|
+ // 已生成的双评任务总数的第二组任务数
|
|
|
|
+ int doubleMarkTaskCount2 = markTaskService.countByExamIdAndPaperNumberAndQuestionIdAndTaskNumber(
|
|
|
|
+ markQuestion.getExamId(), markQuestion.getPaperNumber(), markQuestion.getId(), 2);
|
|
|
|
+ List<MarkTask> taskList = new ArrayList<>();
|
|
|
|
+ int doubleCount = 0;
|
|
|
|
+ int studentCount = studentList.size();
|
|
|
|
+ for (MarkStudent student : studentList) {
|
|
|
|
+ // 开启双评时需要判断是否生成第二份评卷任务
|
|
|
|
+ if (markQuestion.getDoubleRate() != null && markQuestion.getDoubleRate() > 0) {
|
|
|
|
+ boolean needDouble;
|
|
|
|
+ if (markQuestion.getDoubleRate() == 100) {
|
|
|
|
+ needDouble = true;
|
|
|
|
+ } else {
|
|
|
|
+ double libraryCount = taskList.size();
|
|
|
|
+ int expectCount = (int) ((doubleMarkTaskCount1 + studentCount) * markQuestion.getDoubleRate()
|
|
|
|
+ / 100);
|
|
|
|
+ // 随机数判断加入当前已经生成双评任务的比例加权
|
|
|
|
+ // 实际双评任务数小于理论生成数 &&(剩余未生成双评的考生数量小于剩余应生成的数量)
|
|
|
|
+ needDouble = (doubleMarkTaskCount2 + doubleCount) < expectCount
|
|
|
|
+ && ((studentCount - libraryCount + doubleCount) <= (expectCount
|
|
|
|
+ - doubleMarkTaskCount2 - doubleCount));
|
|
|
|
+ }
|
|
|
|
+ if (needDouble) {
|
|
|
|
+ MarkTask markTask = new MarkTask();
|
|
|
|
+ markTask.setId(SystemConstant.getDbUuid());
|
|
|
|
+ markTask.setExamId(student.getExamId());
|
|
|
|
+ markTask.setCourseId(student.getCourseId());
|
|
|
|
+ markTask.setPaperNumber(student.getPaperNumber());
|
|
|
|
+ markTask.setQuestionId(markQuestion.getId());
|
|
|
|
+ markTask.setMainNumber(markQuestion.getMainNumber());
|
|
|
|
+ markTask.setSubNumber(markQuestion.getSubNumber());
|
|
|
|
+ markTask.setStudentId(student.getId());
|
|
|
|
+ markTask.setBasicStudentId(student.getBasicStudentId());
|
|
|
|
+ markTask.setStudentCode(student.getStudentCode());
|
|
|
|
+ markTask.setSecretNumber(student.getSecretNumber());
|
|
|
|
+ markTask.setTaskNumber(2);
|
|
|
|
+ markTask.setAiMarked(getAiMarked(markQuestion, markTask.getTaskNumber()));
|
|
|
|
+ markTask.setStatus(MarkTaskStatus.WAITING);
|
|
|
|
+ taskList.add(markTask);
|
|
|
|
+ doubleCount++;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ // 有新任务创建
|
|
|
|
+ if (CollectionUtils.isNotEmpty(taskList)) {
|
|
|
|
+ count += taskList.size();
|
|
|
|
+ // 任务乱序
|
|
|
|
+ Collections.shuffle(taskList);
|
|
|
|
+ // 批量保存
|
|
|
|
+ markTaskService.saveBatch(taskList);
|
|
|
|
+ // 正评状态才需要更新任务数量
|
|
|
|
+ if (MarkPaperStatus.FORMAL.equals(markPaper.getStatus())) {
|
|
|
|
+ this.updateMarkTaskCount(markQuestion.getExamId(), markQuestion.getPaperNumber(), markQuestion.getId());
|
|
|
|
+ this.updateMarkedCount(markQuestion.getExamId(), markQuestion.getPaperNumber(), markQuestion.getId());
|
|
|
|
+ this.updatePersonTask(markQuestion.getExamId(), markQuestion.getPaperNumber(), markQuestion.getId());
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ studentList = markStudentService.listUnMarkTaskStudent(markQuestion.getExamId(), markQuestion.getPaperNumber(), markQuestion.getId(), pageSize);
|
|
|
|
+ }
|
|
|
|
+ if (count != 0) {
|
|
|
|
+ log.info("finish create " + count + " markTask for examId=" + markQuestion.getExamId() + ", paperNumber="
|
|
|
|
+ + markQuestion.getPaperNumber() + ", questionId=" + markQuestion.getId());
|
|
|
|
+ }
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
+ log.error("build formal markTask error for examId=" + markQuestion.getExamId() + ", paperNumber="
|
|
|
|
+ + markQuestion.getPaperNumber() + ", questionId=" + markQuestion.getId(), e);
|
|
|
|
+ } finally {
|
|
|
|
+ lockService.unwatch(LockType.QUESTION, markQuestion.getId());
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @Transactional
|
|
|
|
+ @Override
|
|
|
|
+ public void deleteMarkTaskByStudent(MarkStudent student) {
|
|
|
|
+ markStudentService.updateSubjectiveStatusAndScore(student.getId(), SubjectiveStatus.UNMARK);
|
|
|
|
+ // 正评相关数据
|
|
|
|
+ markArbitrateHistoryService.deleteByStudentId(student.getId());
|
|
|
|
+ markProblemHistoryService.deleteByStudentId(student.getId());
|
|
|
|
+ markTaskService.deleteByStudentId(student.getId());
|
|
|
|
+ // 主观状态与得分明细
|
|
|
|
+ markSubjectiveScoreService.deleteByStudentId(student.getId());
|
|
|
|
+ updateGroupAllCount(student.getExamId(), student.getPaperNumber());
|
|
|
|
+ // 复核记录
|
|
|
|
+ // inspectedService.clearByStudent(student.getId());
|
|
|
|
+ // 打回记录
|
|
|
|
+ // rejectHistoryDao.deleteByStudentId(student.getId());
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @Transactional
|
|
|
|
+ @Override
|
|
|
|
+ public void updateGroupAllCount(Long examId, String paperNumber) {
|
|
|
|
+ List<MarkQuestion> markQuestionList = markQuestionService.listByExamIdAndPaperNumberAndObjective(examId, paperNumber, false);
|
|
|
|
+ for (MarkQuestion markQuestion : markQuestionList) {
|
|
|
|
+ this.updateMarkedCount(markQuestion.getExamId(), markQuestion.getPaperNumber(), markQuestion.getId());
|
|
|
|
+ this.updateMarkTaskCount(markQuestion.getExamId(), markQuestion.getPaperNumber(), markQuestion.getId());
|
|
|
|
+ this.updatePersonTask(markQuestion.getExamId(), markQuestion.getPaperNumber(), markQuestion.getId());
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private void updateMarkTaskCount(Long examId, String paperNumber, Long questionId) {
|
|
|
|
+ int count = markTaskService.countByExamIdAndPaperNumberAndQuestionIdAndUserId(examId, paperNumber, questionId,
|
|
|
|
+ null);
|
|
|
|
+ markQuestionService.updateTaskCount(questionId, count);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private boolean calculateQuestion(MarkQuestion markQuestion, Long studentId) {
|
|
|
|
+ double score = 0;
|
|
|
|
+ int count = 0;
|
|
|
|
+ // 未设置算分策略的情况下,默认取平均分
|
|
|
|
+ ScorePolicy policy = markQuestion.getScorePolicy() != null ? markQuestion.getScorePolicy() : ScorePolicy.AVG;
|
|
|
|
+ List<MarkTask> list = markTaskService.listByExamIdAndPaperNumberAndQuestionIdAndStudentId(markQuestion.getExamId(),
|
|
|
|
+ markQuestion.getPaperNumber(), markQuestion.getId(), studentId);
|
|
|
|
+ if (list.isEmpty()) {
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+ for (MarkTask markTask : list) {
|
|
|
|
+ if (markTask.getStatus() != MarkTaskStatus.MARKED && markTask.getStatus() != MarkTaskStatus.ARBITRATED) {
|
|
|
|
+ // 有非完成状态的评卷任务,直接返回
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ for (MarkTask markTask : list) {
|
|
|
|
+ count++;
|
|
|
|
+ Double current = markTask.getHeaderScore() != null ? markTask.getHeaderScore() : markTask.getMarkerScore();
|
|
|
|
+ if (count == 1) {
|
|
|
|
+ // 首份评卷任务,直接取总分与明细
|
|
|
|
+ score = current;
|
|
|
|
+ } else {
|
|
|
|
+ switch (policy) {
|
|
|
|
+ case AVG:
|
|
|
|
+ // 直接累加
|
|
|
|
+ score = BigDecimalUtils.add(score, current);
|
|
|
|
+ break;
|
|
|
|
+ case MAX:
|
|
|
|
+ // 高分优先
|
|
|
|
+ if (current > score) {
|
|
|
|
+ score = current;
|
|
|
|
+ }
|
|
|
|
+ break;
|
|
|
|
+ case MIN:
|
|
|
|
+ // 低分优先
|
|
|
|
+ if (current < score) {
|
|
|
|
+ score = current;
|
|
|
|
+ }
|
|
|
|
+ break;
|
|
|
|
+ default:
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ // 取平均分策略下,累计分数需要重新计算一次
|
|
|
|
+ if (policy == ScorePolicy.AVG && count > 1) {
|
|
|
|
+ score = BigDecimalUtils.div(score, count);
|
|
|
|
+ }
|
|
|
|
+ markQuestion.setMarkScore(score);
|
|
|
|
+ return true;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private void updateStudentQuestionScore(Long studentId, MarkQuestion markQuestion, Double markScore) {
|
|
|
|
+ MarkSubjectiveScore ss = markSubjectiveScoreService.getByStudentIdAndQuestionId(studentId, markQuestion.getId());
|
|
|
|
+ if (ss == null) {
|
|
|
|
+ ss = new MarkSubjectiveScore();
|
|
|
|
+ }
|
|
|
|
+ ss.setStudentId(studentId);
|
|
|
|
+ ss.setExamId(markQuestion.getExamId());
|
|
|
|
+ ss.setPaperNumber(markQuestion.getPaperNumber());
|
|
|
|
+ ss.setQuestionId(markQuestion.getId());
|
|
|
|
+ ss.setMainNumber(markQuestion.getMainNumber());
|
|
|
|
+ ss.setSubNumber(markQuestion.getSubNumber());
|
|
|
|
+ ss.setScore(markScore);
|
|
|
|
+ ss.setMainScore(0.0);
|
|
|
|
+ markSubjectiveScoreService.saveOrUpdateByMultiId(ss);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private void scoreCalculate(Long studentId, Integer version, boolean autoCalc) {
|
|
|
|
+ List<ScoreItem> scoreList = new ArrayList<>();
|
|
|
|
+ Map<Integer, List<MarkSubjectiveScore>> mainScoreMap = new HashMap<>();
|
|
|
|
+ Map<Integer, Double> scoreMap = new HashMap<>();
|
|
|
|
+
|
|
|
|
+ // 循环所有主观得分明细
|
|
|
|
+ List<MarkSubjectiveScore> list = markSubjectiveScoreService.listByStudentId(studentId);
|
|
|
|
+ // list.sort(null);
|
|
|
|
+ for (MarkSubjectiveScore ss : list) {
|
|
|
|
+ List<MarkSubjectiveScore> mainScoreList = mainScoreMap.get(ss.getMainNumber());
|
|
|
|
+ if (mainScoreList == null) {
|
|
|
|
+ mainScoreList = new ArrayList<>();
|
|
|
|
+ }
|
|
|
|
+ mainScoreList.add(ss);
|
|
|
|
+ mainScoreMap.put(ss.getMainNumber(), mainScoreList);
|
|
|
|
+ scoreList.add(new ScoreItem(ss));
|
|
|
|
+ }
|
|
|
|
+ // 计算大题分
|
|
|
|
+ for (Integer mainNumber : mainScoreMap.keySet()) {
|
|
|
|
+ List<MarkSubjectiveScore> mainScoreList = mainScoreMap.get(mainNumber);
|
|
|
|
+ BigDecimal mainScore = BigDecimal.ZERO;
|
|
|
|
+ for (MarkSubjectiveScore subjectiveScore : mainScoreList) {
|
|
|
|
+ mainScore = mainScore.add(BigDecimal.valueOf(subjectiveScore.getScore()));
|
|
|
|
+ }
|
|
|
|
+ for (MarkSubjectiveScore subjectiveScore : mainScoreList) {
|
|
|
|
+ subjectiveScore.setMainScore(mainScore.doubleValue());
|
|
|
|
+ markSubjectiveScoreService.saveOrUpdateByMultiId(subjectiveScore);
|
|
|
|
+ }
|
|
|
|
+ scoreMap.put(mainNumber, mainScore.doubleValue());
|
|
|
|
+ }
|
|
|
|
+ // 计算选做题分数
|
|
|
|
+ BigDecimal totalScore = BigDecimal.ZERO;
|
|
|
|
+ // 计算非选做题总分
|
|
|
|
+ for (Integer mainNumber : scoreMap.keySet()) {
|
|
|
|
+ totalScore = totalScore.add(BigDecimal.valueOf(scoreMap.get(mainNumber)));
|
|
|
|
+ }
|
|
|
|
+ // 全部评完,更新考生主观题得分
|
|
|
|
+// markStudentService.updateSubjectiveStatusAndScore(studentId, SubjectiveStatus.MARKED, totalScore.doubleValue(),
|
|
|
|
+// MarkStudent.buildScoreList(scoreList));
|
|
|
|
+ markStudentService.updateSubjectiveScoreByVersion(studentId, SubjectiveStatus.MARKED, totalScore.doubleValue(), MarkStudent.buildScoreList(scoreList), version, autoCalc);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @Override
|
|
|
|
+ public MarkSettingDto getSetting(SysUser user, Long examId, String paperNumber) {
|
|
|
|
+ MarkUserPaper markUserPaper = markUserPaperService.getByExamIdAndPaperNumberAndUserId(examId, paperNumber, user.getId());
|
|
|
|
+ user = sysUserService.getById(user.getId());
|
|
|
|
+ MarkPaper markPaper = markPaperService.getByExamIdAndPaperNumber(examId, paperNumber);
|
|
|
|
+
|
|
|
|
+ MarkSettingDto dto = new MarkSettingDto();
|
|
|
|
+ dto.setExamType(ExamType.SCAN_IMAGE);//考试类型,默认SCAN_IMAGE
|
|
|
|
+ dto.setMode(markUserPaper != null && markUserPaper.getMode() != null ? markUserPaper.getMode()
|
|
|
|
+ : MarkMode.UNLIMITED.equals(markPaper.getMarkMode()) ? MarkMode.TRACK : markPaper.getMarkMode());//模式 TRACK/COMMON
|
|
|
|
+ dto.setQuestionModel(markUserPaper != null && markUserPaper.getQuestionModel() != null ? markUserPaper.getQuestionModel() : QuestionModel.MULTI);
|
|
|
|
+ dto.setForceMode(markPaper.getForceMode());//强制模式切换
|
|
|
|
+ dto.setSheetView(markPaper.getSheetView());//是否显示原图功能
|
|
|
|
+ dto.setSheetConfig(markPaper.getSheetConfig());//原图遮盖规则
|
|
|
|
+ dto.setEnableAllZore(false);//是否开启全零分(知学知考阅卷默认false)
|
|
|
|
+ dto.setFileServer(null);//图片服务地址
|
|
|
|
+ dto.setUserName(user.getRealName());//评卷员名称
|
|
|
|
+ dto.getSubject().setAnswerUrl(markQuestionService.previewAnswerFileByExamIdAndPaperNumber(examId, paperNumber));
|
|
|
|
+ dto.getSubject().setPaperUrl(markQuestionService.previewPaperFileByExamIdAndPaperNumber(examId, paperNumber));
|
|
|
|
+ BasicCourse basicCourse = basicCourseService.getById(markPaper.getCourseId());
|
|
|
|
+ dto.getSubject().setCode(markPaper.getPaperNumber());
|
|
|
|
+ dto.getSubject().setName(basicCourse != null ? basicCourse.getName() : null);
|
|
|
|
+ dto.setForceSpecialTag(false);//强制标记是否开启 必须要有标记(分数轨迹或特殊标记)(知学知考阅卷默认true)
|
|
|
|
+ dto.setUiSetting(user.getUiSetting());//新交互模式下,以下字段要重新定义或新增(初始值为空,按评卷员保存)
|
|
|
|
+ dto.setStatusValue(markPaper.getStatus());//只显示试评名称 FORMAL("正评"), FINISH("结束")
|
|
|
|
+ dto.setProblemTypes(MarkProblemType.listTypes());//问题卷类型
|
|
|
|
+// dto.setTopCount(markUserGroup != null && markUserGroup.getTopCount() != null ? markUserGroup.getTopCount() : 0);
|
|
|
|
+ dto.setSplitConfig(new Double[0]);//使用裁切整图时的裁切配置
|
|
|
|
+ dto.setPrefetchCount(3);//预加载任务数量
|
|
|
|
+ dto.setStartTime(markPaper.getMarkStartTime());//评卷开始时间
|
|
|
|
+ dto.setEndTime(markPaper.getMarkEndTime());//评卷结束时间
|
|
|
|
+ dto.setSelective(false);//是否为选做题(默认false)
|
|
|
|
+ dto.setAutoScroll(markPaper.getAutoScroll());//是否自动跳转
|
|
|
|
+ dto.setEnableSplit(false);//是否裁切(默认false)
|
|
|
|
+ dto.setShowObjectScore(markPaper.getShowObjectScore());//是否显示客观分
|
|
|
|
+ return dto;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @Override
|
|
|
|
+ public List<MarkStatusDto> getStatus(Long userId, Long examId, String paperNumber, QuestionModel questionModel, Long questionId) {
|
|
|
|
+ MarkPaper markPaper = markPaperService.getByExamIdAndPaperNumber(examId, paperNumber);
|
|
|
|
+
|
|
|
|
+ List<String> classNames = null;
|
|
|
|
+ //校验是否有分班阅
|
|
|
|
+ if (markPaper != null && markPaper.getClassMark() != null && markPaper.getClassMark().booleanValue()) {
|
|
|
|
+ List<MarkUserClass> markUserClassList = markUserClassService.listByExamIdAndPaperNumberAndUserId(examId, paperNumber, userId);
|
|
|
|
+ if (CollectionUtils.isNotEmpty(markUserClassList)) {
|
|
|
|
+ classNames = markUserClassList.stream().map(MarkUserClass::getClassName).collect(Collectors.toList());
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ List<MarkStatusDto> dtoList = new ArrayList<>();
|
|
|
|
+ List<MarkUserQuestion> markUserQuestionList = markUserQuestionService.listByExamIdAndPaperNumberAndUserIdAndEnableTure(examId, paperNumber, userId);
|
|
|
|
+ // 评卷方式
|
|
|
|
+ if (QuestionModel.SINGLE.equals(questionModel)) {
|
|
|
|
+ if (questionId != null) {
|
|
|
|
+ markUserQuestionList = markUserQuestionList.stream().filter(m -> m.getQuestionId().equals(questionId)).collect(Collectors.toList());
|
|
|
|
+ }
|
|
|
|
+ MarkUserPaper markUserPaper = markUserPaperService.getByExamIdAndPaperNumberAndUserId(examId, paperNumber, userId);
|
|
|
|
+ MarkStatusDto dto;
|
|
|
|
+ for (MarkUserQuestion question : markUserQuestionList) {
|
|
|
|
+ dto = new MarkStatusDto(markQuestionService.getById(question.getQuestionId()), markUserPaper.getMarkedQuestionId());
|
|
|
|
+ List<Long> questionIds = Arrays.asList(question.getQuestionId());
|
|
|
|
+ MarkStatusDto statusDto = getDto(dto, examId, paperNumber, userId, classNames, questionIds);
|
|
|
|
+ statusDto.setLeftCount(countLeftCountForSingle(examId, paperNumber, statusDto.getLeftCount(), question.getQuestionId(), userId, classNames));
|
|
|
|
+ dtoList.add(statusDto);
|
|
|
|
+ }
|
|
|
|
+ } else if (QuestionModel.MULTI.equals(questionModel)) {
|
|
|
|
+ MarkStatusDto dto = new MarkStatusDto();
|
|
|
|
+ List<Long> questionIds = markUserQuestionList.stream().filter(m -> m.getUserId().equals(userId)).map(MarkUserQuestion::getQuestionId).collect(Collectors.toList());
|
|
|
|
+ dtoList.add(getDto(dto, examId, paperNumber, userId, classNames, questionIds));
|
|
|
|
+ } else {
|
|
|
|
+ throw ExceptionResultEnum.ERROR.exception("参数有误");
|
|
|
|
+ }
|
|
|
|
+ dtoList.sort(Comparator.comparing(MarkStatusDto::getMainNumber).thenComparing(MarkStatusDto::getSubNumber));
|
|
|
|
+ return dtoList;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private int countLeftCountForSingle(Long examId, String paperNumber, int leftCount, Long questionId, Long userId, List<String> classNames) {
|
|
|
|
+ MarkQuestion markQuestion = markQuestionService.getById(questionId);
|
|
|
|
+ Set<Long> currentStudent = this.listCurrentStudent(examId, paperNumber);
|
|
|
|
+
|
|
|
|
+ int userCurrentCount = this.applyCurrentCount(markQuestion, userId);
|
|
|
|
+ if (CollectionUtils.isEmpty(classNames)) {
|
|
|
|
+ return leftCount - currentStudent.size() + userCurrentCount;
|
|
|
|
+ } else {
|
|
|
|
+// List<MarkUserClass> markUserClassList = markUserClassService.listByExamIdAndPaperNumber(markQuestion.getExamId(), markQuestion.getPaperNumber());
|
|
|
|
+// Set<MarkUserClass> markUserClasses = markUserClassList.stream().filter(m -> classNames.contains(m.getClassName()) && !m.getUserId().equals(userId)).collect(Collectors.toSet());
|
|
|
|
+// int count = 0;
|
|
|
|
+// for (MarkUserClass markUserClass : markUserClasses) {
|
|
|
|
+// count += this.applyCurrentCount(markQuestion, markUserClass.getUserId());
|
|
|
|
+// }
|
|
|
|
+// return leftCount - count;
|
|
|
|
+ Set<Long> studentIds = markStudentService.listStudentIds(examId, paperNumber, classNames);
|
|
|
|
+ Collection<Long> collection = CollectionUtils.intersection(currentStudent, studentIds);
|
|
|
|
+ return leftCount - collection.size() + userCurrentCount;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private MarkStatusDto getDto(MarkStatusDto dto, Long examId, String paperNumber, Long userId, List<String> classNames, List<Long> questionIds) {
|
|
|
|
+ //待仲裁卷数量
|
|
|
|
+ dto.setArbitrateCount(markArbitrateHistoryService.waitArbitrateCount(examId, paperNumber, null, classNames));
|
|
|
|
+ //总数量
|
|
|
|
+ dto.setTotalCount(markTaskService.countByExamIdAndPaperNumberAndUserIdAndAndClassNameAndQuestionIdIn(examId, paperNumber, null, classNames, questionIds));
|
|
|
|
+ // 未评
|
|
|
|
+ int unmarkCount = markTaskService.countByExamIdAndPaperNumberAndUserIdAndAndClassNameAndQuestionIdIn(examId, paperNumber, null, classNames, questionIds, MarkTaskStatus.WAITING, MarkTaskStatus.WAIT_ARBITRATE, MarkTaskStatus.REJECTED);
|
|
|
|
+ dto.setLeftCount(unmarkCount);
|
|
|
|
+ //总评卷数量(考生数)
|
|
|
|
+ dto.setMarkedCount(dto.getTotalCount() == 0 ? 0 : dto.getTotalCount() - unmarkCount);
|
|
|
|
+ //个人评卷数量
|
|
|
|
+ dto.setPersonCount(markTaskService.countByExamIdAndPaperNumberAndUserIdAndAndClassNameAndQuestionIdIn(examId, paperNumber, userId, classNames, questionIds, MarkTaskStatus.MARKED, MarkTaskStatus.ARBITRATED,
|
|
|
|
+ MarkTaskStatus.WAIT_ARBITRATE, MarkTaskStatus.PROBLEM));
|
|
|
|
+ //问题卷数量
|
|
|
|
+ dto.setProblemCount(markProblemHistoryService.countByExamIdAndPaperNumberAndStatusAndClassNameIn(examId, paperNumber, MarkProblemStatus.WAITING, classNames));
|
|
|
|
+ return dto;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @Override
|
|
|
|
+ public void clear(Long userId, Long examId, String paperNumber) {
|
|
|
|
+ TaskLock taskLock = TaskLockUtil.getFormalTask(getKey(examId, paperNumber));
|
|
|
|
+ taskLock.clear(userId);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @Override
|
|
|
|
+ public void releaseByStudent(MarkStudent student) {
|
|
|
|
+ TaskLock taskLock = TaskLockUtil.getInspectedStudentTask(getKey(student.getExamId(), student.getPaperNumber()));
|
|
|
|
+ taskLock.remove(student.getId());
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @Override
|
|
|
|
+ public boolean applyStudent(MarkStudent student, Long userId) {
|
|
|
|
+ TaskLock taskLock = TaskLockUtil.getInspectedStudentTask(getKey(student.getExamId(), student.getPaperNumber()));
|
|
|
|
+ boolean lock = taskLock.add(student.getId(), userId, new HashSet<>());
|
|
|
|
+ // 上锁失败直接返回
|
|
|
|
+ if (!lock) {
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+ // 重复校验任务状态
|
|
|
|
+ if (student.getSubjectiveStatus().equals(SubjectiveStatus.MARKED)) {
|
|
|
|
+ return true;
|
|
|
|
+ } else {
|
|
|
|
+ taskLock.remove(student.getId(), userId);
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @Override
|
|
|
|
+ public void submitHeaderTask(List<MarkResultQuestion> resultQuestions, MarkStudent markStudent) {
|
|
|
|
+ Long userId = ServletUtil.getRequestUserId();
|
|
|
|
+ for (MarkResultQuestion result : resultQuestions) {
|
|
|
|
+ try {
|
|
|
|
+ lockService.watch(LockType.QUESTION, result.getQuestionId());
|
|
|
|
+ Long currentTime = System.currentTimeMillis();
|
|
|
|
+ updateMarkSubjectScore(markStudent, result, userId);
|
|
|
|
+ markTaskService.updateHeaderResult(markStudent.getExamId(), markStudent.getPaperNumber(),
|
|
|
|
+ result.getQuestionId(), markStudent.getId(), userId, result.getMarkerScore(), result.getMarkerTrackList(), result.getMarkerTagList(), currentTime, MarkTaskStatus.MARKED);
|
|
|
|
+ updateMarkedCount(markStudent.getExamId(), markStudent.getPaperNumber(), result.getQuestionId());
|
|
|
|
+// resetStudentStatus(markStudent.getId());
|
|
|
|
+ markStudentService.updateCheckInfo(markStudent.getId(), userId);
|
|
|
|
+ MarkQuestion markQuestion = markQuestionService.getById(result.getQuestionId());
|
|
|
|
+ markQuestion.setMarkScore(result.getMarkerScore());
|
|
|
|
+ checkStudentQuestionForInspect(markStudent, markQuestion);
|
|
|
|
+ } catch (ApiException e) {
|
|
|
|
+ throw ExceptionResultEnum.ERROR.exception(e.getMessage());
|
|
|
|
+ } finally {
|
|
|
|
+ lockService.unwatch(LockType.QUESTION, result.getQuestionId());
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private void updateMarkSubjectScore(MarkStudent markStudent, MarkResultQuestion resultQuestion, Long userId) {
|
|
|
|
+ // 记录修改日志(按小题)
|
|
|
|
+// List<BasicOperationLog> basicOperationLogs = new ArrayList<>();
|
|
|
|
+ MarkSubjectiveScore markSubjectiveScore = markSubjectiveScoreService.getByStudentIdAndQuestionId(markStudent.getId(), resultQuestion.getQuestionId());
|
|
|
|
+ double score = resultQuestion.getMarkerScore();
|
|
|
|
+ // 分数有变动,记录日志
|
|
|
|
+ if (markSubjectiveScore.getScore() != score) {
|
|
|
|
+// MarkStudentVo markStudentVo = markStudentService.getDetailById(markStudent.getId());
|
|
|
|
+// String detail = String.format("%s(%s)课程%s试卷编号下,将%s(%s)的%s题从%s分修改为%s分", markStudentVo.getCourseName(), markStudentVo.getCourseCode(), markStudentVo.getPaperNumber(), markStudentVo.getStudentName(), markStudentVo.getStudentCode(), markSubjectiveScore.getMainNumber() + "-" + markSubjectiveScore.getSubNumber(), markSubjectiveScore.getScore(), score);
|
|
|
|
+// basicOperationLogs.add(new BasicOperationLog(Long.valueOf(ServletUtil.getRequestHeaderSchoolId().toString()), ServletUtil.getCurrentPrivilegeId(), OperationTypeEnum.SUBJECTIVE, OperationTypeEnum.SUBJECTIVE.getName(), ServletUtil.getRequest().getServletPath(), detail, String.valueOf(groupResult.getScore()), "成功", ServletUtil.getRequestUserId()));
|
|
|
|
+ MarkHeaderHistory headerHistory = new MarkHeaderHistory();
|
|
|
|
+ headerHistory.setId(SystemConstant.getDbUuid());
|
|
|
|
+ headerHistory.setExamId(markStudent.getExamId());
|
|
|
|
+ headerHistory.setPaperNumber(markStudent.getPaperNumber());
|
|
|
|
+ headerHistory.setStudentId(markStudent.getId());
|
|
|
|
+ headerHistory.setQuestionId(markSubjectiveScore.getQuestionId());
|
|
|
|
+ headerHistory.setMainNumber(markSubjectiveScore.getMainNumber());
|
|
|
|
+ headerHistory.setSubNumber(markSubjectiveScore.getSubNumber());
|
|
|
|
+ headerHistory.setUserId(userId);
|
|
|
|
+ headerHistory.setScore(score);
|
|
|
|
+ headerHistory.setTrackList(JSON.toJSONString(resultQuestion.getMarkerTrackList()));
|
|
|
|
+ headerHistory.setOriginalScore(markSubjectiveScore.getScore());
|
|
|
|
+// headerHistory.setOriginalTrackList();
|
|
|
|
+ headerHistory.setCreateTime(System.currentTimeMillis());
|
|
|
|
+ markHeaderHistoryService.save(headerHistory);
|
|
|
|
+ }
|
|
|
|
+// markSubjectiveScore.setScore(score);
|
|
|
|
+// markSubjectiveScoreService.saveOrUpdateByMultiId(markSubjectiveScore);
|
|
|
|
+
|
|
|
|
+ // 记录日志
|
|
|
|
+// if (CollectionUtils.isNotEmpty(basicOperationLogs)) {
|
|
|
|
+// basicOperationLogService.saveBatch(basicOperationLogs);
|
|
|
|
+// }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private String getKey(Long examId, String paperNumber) {
|
|
|
|
+ return examId + "_" + paperNumber;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @Override
|
|
|
|
+ public IPage<Task> getHistory(Long userId, int pageNumber, int pageSize, Sort sort, String order, Long examId,
|
|
|
|
+ String paperNumber, String secretNumber, Double markerScore) {
|
|
|
|
+ if (!"marker_time".equals(order) && !"marker_score".equals(order)) {
|
|
|
|
+ order = "marker_time";
|
|
|
|
+ }
|
|
|
|
+ Page<Long> page = new Page<>(pageNumber, pageSize);
|
|
|
|
+ OrderItem orderItem = new OrderItem(order, sort.equals(Sort.asc));
|
|
|
|
+ page.addOrder(orderItem);
|
|
|
|
+ IPage<MarkTask> list = markTaskService.listPageHistory(page, userId, examId, paperNumber, secretNumber, markerScore, MarkTaskStatus.MARKED, MarkTaskStatus.ARBITRATED, MarkTaskStatus.WAIT_ARBITRATE, MarkTaskStatus.PROBLEM);
|
|
|
|
+ List<Task> recordsDtos = new ArrayList<>();
|
|
|
|
+ List<MarkTaskStatus> markTaskStatuses = Arrays.asList(MarkTaskStatus.MARKED, MarkTaskStatus.ARBITRATED, MarkTaskStatus.WAIT_ARBITRATE, MarkTaskStatus.PROBLEM);
|
|
|
|
+ for (MarkTask markTask : list.getRecords()) {
|
|
|
|
+ List<MarkTask> markTaskList = markTaskService.listByStudentIdAndMarkerId(markTask.getStudentId(), userId, markTaskStatuses);
|
|
|
|
+ Task dto = taskService.build(userId, markTaskList);
|
|
|
|
+ dto.setMarkerTime(markTask.getMarkerTime());
|
|
|
|
+ recordsDtos.add(dto);
|
|
|
|
+ }
|
|
|
|
+ IPage<Task> result = new Page<>();
|
|
|
|
+ result.setCurrent(list.getCurrent());
|
|
|
|
+ result.setPages(list.getPages());
|
|
|
|
+ result.setRecords(recordsDtos);
|
|
|
|
+ result.setSize(list.getSize());
|
|
|
|
+ result.setTotal(list.getTotal());
|
|
|
|
+ return result;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @Override
|
|
|
|
+ public Task getTask(Long userId, Long examId, String paperNumber, QuestionModel questionModel, Long questionId) {
|
|
|
|
+ MarkPaper markPaper = markPaperService.getByExamIdAndPaperNumber(examId, paperNumber);
|
|
|
|
+ if (markPaper == null) {
|
|
|
|
+ throw ExceptionResultEnum.ERROR.exception("评卷试卷不存在");
|
|
|
|
+ }
|
|
|
|
+ int count = markUserQuestionService.countByExamIdAndPaperNumberAndAndUserId(examId, paperNumber, userId);
|
|
|
|
+ if (count == 0) {
|
|
|
|
+ throw ExceptionResultEnum.ERROR.exception("评卷任务被重置,请点击右上角返回按钮,重新在评卷入口菜单点击评卷");
|
|
|
|
+ }
|
|
|
|
+ List<MarkUserQuestion> markUserQuestions = markUserQuestionService.listByExamIdAndPaperNumberAndUserIdAndEnableTure(examId, paperNumber, userId);
|
|
|
|
+ if (markUserQuestions.isEmpty()) {
|
|
|
|
+ throw ExceptionResultEnum.ERROR.exception("评卷员未设置评卷题目");
|
|
|
|
+ }
|
|
|
|
+ List<String> classNames = null;
|
|
|
|
+ //校验是否有分班阅
|
|
|
|
+ if (markPaper != null && markPaper.getClassMark() != null && markPaper.getClassMark().booleanValue()) {
|
|
|
|
+ List<MarkUserClass> markUserClassList = markUserClassService.listByExamIdAndPaperNumberAndUserId(examId, paperNumber, userId);
|
|
|
|
+ if (CollectionUtils.isNotEmpty(markUserClassList)) {
|
|
|
|
+ classNames = markUserClassList.stream().map(MarkUserClass::getClassName).collect(Collectors.toList());
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ Task task = null;
|
|
|
|
+ List<Long> studentIds;
|
|
|
|
+ int pageNumber = 1;
|
|
|
|
+ while (task == null) {
|
|
|
|
+ if (questionModel.equals(QuestionModel.SINGLE)) {
|
|
|
|
+ Set<Long> questions = new HashSet<>(Arrays.asList(questionId));
|
|
|
|
+ List<MarkTask> list = markTaskService.findUnMarkedFilterClass(new Page<>(pageNumber, 20), examId, paperNumber, userId, questionId, classNames);
|
|
|
|
+ if (list.isEmpty()) {
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ for (MarkTask t : list) {
|
|
|
|
+ if (this.applyTask(examId, paperNumber, t.getStudentId(), userId, questions, Arrays.asList(t.getId()))) {
|
|
|
|
+ task = taskService.build(userId, Arrays.asList(t));
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ } else if (questionModel.equals(QuestionModel.MULTI)) {
|
|
|
|
+ Set<Long> questions = markUserQuestions.stream().map(MarkUserQuestion::getQuestionId).collect(Collectors.toSet());
|
|
|
|
+ studentIds = markStudentService.findUnMarked(new Page<>(pageNumber, 20), examId, paperNumber, questions, classNames);
|
|
|
|
+ if (studentIds.isEmpty()) {
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ for (Long studentId : studentIds) {
|
|
|
|
+ if (this.applyTask(examId, paperNumber, studentId, userId, questions)) {
|
|
|
|
+ List<MarkTask> markTaskList = markTaskService.listByStudentId(studentId);
|
|
|
|
+ if (markTaskList.isEmpty()) {
|
|
|
|
+ releaseStudent(examId, paperNumber, studentId, userId);
|
|
|
|
+ continue;
|
|
|
|
+ }
|
|
|
|
+ Map<Long, List<MarkTask>> map = markTaskList.stream().collect(Collectors.groupingBy(MarkTask::getQuestionId));
|
|
|
|
+ List<MarkTask> markTasks = new ArrayList<>();
|
|
|
|
+ for (MarkUserQuestion markUserQuestion : markUserQuestions) {
|
|
|
|
+ List<MarkTask> markTasks1 = map.get(markUserQuestion.getQuestionId());
|
|
|
|
+ if (markTasks1.size() == 1) {
|
|
|
|
+ markTasks.add(markTasks1.get(0));
|
|
|
|
+ } else {
|
|
|
|
+ MarkTask markTask = markTasks1.stream().filter(m -> userId.equals(m.getUserId())).findFirst().orElse(null);
|
|
|
|
+ if (markTask == null) {
|
|
|
|
+ markTask = markTasks1.stream().filter(m -> m.getUserId() == null).findFirst().orElse(null);
|
|
|
|
+ if (markTask == null) {
|
|
|
|
+ markTask = markTasks1.get(0);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ markTasks.add(markTask);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ // 所有题目都已评,跳过
|
|
|
|
+ if (markTasks.stream().filter(m -> m.getUserId() == null).count() == 0) {
|
|
|
|
+ releaseStudent(examId, paperNumber, studentId, userId);
|
|
|
|
+ continue;
|
|
|
|
+ }
|
|
|
|
+ markTasks.sort(Comparator.comparing(MarkTask::getMainNumber).thenComparing(MarkTask::getSubNumber));
|
|
|
|
+ task = taskService.build(userId, markTasks);
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ } else {
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (task == null) {
|
|
|
|
+ pageNumber++;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ return task;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @Override
|
|
|
|
+ public boolean applyTask(Long examId, String paperNumber, Long studentId, Long userId, Set<Long> questions, List<Long> taskIds) {
|
|
|
|
+ // 查询待领取任务时,已经做了多评同一studentId互斥处理
|
|
|
|
+ TaskLock taskLock = TaskLockUtil.getFormalTask(getKey(examId, paperNumber));
|
|
|
|
+ boolean lock = taskLock.add(studentId, userId, questions);
|
|
|
|
+ // 上锁失败直接返回
|
|
|
|
+ if (!lock) {
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+ // 检验是否有待评任务
|
|
|
|
+ if (markTaskService.countByStatusAndIdIn(taskIds, MarkTaskStatus.WAITING, MarkTaskStatus.REJECTED) > 0) {
|
|
|
|
+ return true;
|
|
|
|
+ } else {
|
|
|
|
+ taskLock.remove(studentId, userId);
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @Override
|
|
|
|
+ public boolean applyTask(Long examId, String paperNumber, Long studentId, Long userId, Set<Long> questions) {
|
|
|
|
+ // 查询待领取任务时,已经做了多评同一studentId互斥处理
|
|
|
|
+ TaskLock taskLock = TaskLockUtil.getFormalTask(getKey(examId, paperNumber));
|
|
|
|
+ boolean lock = taskLock.add(studentId, userId, questions);
|
|
|
|
+ // 上锁失败直接返回
|
|
|
|
+ if (!lock) {
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+// taskLock.remove(studentId, userId);
|
|
|
|
+ return true;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @Override
|
|
|
|
+ public boolean hasApplied(MarkTask t, Long userId) {
|
|
|
|
+ TaskLock taskLock = TaskLockUtil.getFormalTask(getKey(t.getExamId(), t.getPaperNumber()));
|
|
|
|
+ return taskLock.exist(t.getStudentId(), userId);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @Override
|
|
|
|
+ public void deleteInitMarkData(Long examId, String paperNumber) {
|
|
|
|
+ markPaperService.deleteByExamIdAndPaperNumber(examId, paperNumber);
|
|
|
|
+ markStudentService.deleteByExamIdAndPaperNumber(examId, paperNumber);
|
|
|
|
+ scanAnswerCardService.deleteByExamIdAndPaperNumber(examId, paperNumber);
|
|
|
|
+ markQuestionService.deleteByExamIdAndPaperNumber(examId, paperNumber);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @Override
|
|
|
|
+ public void calcObjectiveScore(MarkPaper markPaper) {
|
|
|
|
+ int pageNumber = 1;
|
|
|
|
+ int pageSize = 1000;
|
|
|
|
+ IPage<MarkStudent> iPage = markStudentService.pageByExamAndPaperNumber(markPaper.getExamId(),
|
|
|
|
+ markPaper.getPaperNumber(), pageNumber, pageSize);
|
|
|
|
+ while (CollectionUtils.isNotEmpty(iPage.getRecords())) {
|
|
|
|
+ for (MarkStudent student : iPage.getRecords()) {
|
|
|
|
+ calculate(student);
|
|
|
|
+ }
|
|
|
|
+ pageNumber++;
|
|
|
|
+ iPage = markStudentService.pageByExamAndPaperNumber(markPaper.getExamId(), markPaper.getPaperNumber(),
|
|
|
|
+ pageNumber, pageSize);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private void calculate(MarkStudent student) {
|
|
|
|
+ // 未上传、缺考的考生不统分
|
|
|
|
+ if (!student.getUpload() || student.getAbsent() || student.getOmrAbsent() || (student.getManualAbsent() != null && student.getManualAbsent())) {
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ try {
|
|
|
|
+ // 更新客观题得分
|
|
|
|
+ markStudentService.calculateObjectiveScore(student);
|
|
|
|
+ // 增加主观题总分统计
|
|
|
|
+ // markService.scoreCalculate(student,
|
|
|
|
+ // findMarkGroup(student.getSubjectCode()));
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
+ log.error("calculate error for studentId=" + student.getId(), e);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @Transactional
|
|
|
|
+ @Override
|
|
|
|
+ public SubmitResult saveTask(Long examId, String paperNumber, Long userId, MarkResult result) {
|
|
|
|
+ for (MarkResultQuestion question : result.getQuestionList()) {
|
|
|
|
+ MarkUserQuestion markUserQuestion = markUserQuestionService.getByExamIdAndPaperNumberAndQuestionIdAndUserId(examId, paperNumber, question.getQuestionId(), userId);
|
|
|
|
+ if (markUserQuestion == null) {
|
|
|
|
+ throw ExceptionResultEnum.ERROR.exception("评卷员未绑定题目" + question.getMainNumber() + "-" + question.getSubNumber());
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ SubmitResult sr;
|
|
|
|
+ try {
|
|
|
|
+ lockService.watch(LockType.EXAM_SUBJECT, examId, paperNumber);
|
|
|
|
+ lockService.watch(LockType.MARK_USER_QUESTION, userId);
|
|
|
|
+ lockService.waitlock(LockType.STUDENT, result.getStudentId());
|
|
|
|
+ sr = submitResult(examId, paperNumber, userId, result);
|
|
|
|
+ if (sr.isSuccess()) {
|
|
|
|
+ releaseStudent(examId, paperNumber, sr.getStudentId(), userId);
|
|
|
|
+ }
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
+ log.error("save task error", e);
|
|
|
|
+ throw ExceptionResultEnum.ERROR.exception(e.getMessage());
|
|
|
|
+ } finally {
|
|
|
|
+ lockService.unlock(LockType.STUDENT, result.getStudentId());
|
|
|
|
+ lockService.unwatch(LockType.MARK_USER_QUESTION, userId);
|
|
|
|
+ lockService.unwatch(LockType.EXAM_SUBJECT, examId, paperNumber);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (sr == null || !sr.isSuccess()) {
|
|
|
|
+ throw ExceptionResultEnum.ERROR.exception("评卷任务提交失败,请刷新页面");
|
|
|
|
+ }
|
|
|
|
+ return sr;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private SubmitResult submitResult(Long examId, String paperNumber, Long userId, MarkResult result) {
|
|
|
|
+ int spentAvg = result.getSpent() / result.getQuestionList().size();
|
|
|
|
+ int count = 0;
|
|
|
|
+ for (MarkResultQuestion markResultQuestion : result.getQuestionList()) {
|
|
|
|
+ try {
|
|
|
|
+ lockService.watch(LockType.QUESTION, markResultQuestion.getQuestionId());
|
|
|
|
+ markResultQuestion.setSpent(spentAvg);
|
|
|
|
+ MarkUserQuestion markUserQuestion = markUserQuestionService.getByExamIdAndPaperNumberAndQuestionIdAndUserId(examId, paperNumber, markResultQuestion.getQuestionId(), userId);
|
|
|
|
+ MarkQuestion markQuestion = markQuestionService.getById(markResultQuestion.getQuestionId());
|
|
|
|
+ MarkTask task = markTaskService.getById(markResultQuestion.getTaskId());
|
|
|
|
+ if (task != null && task.getExamId().equals(markUserQuestion.getExamId())
|
|
|
|
+ && task.getPaperNumber().equals(markUserQuestion.getPaperNumber())
|
|
|
|
+ && task.getQuestionId().equals(markUserQuestion.getQuestionId())) {
|
|
|
|
+ // 问题卷
|
|
|
|
+ Long now = System.currentTimeMillis();
|
|
|
|
+ if (markResultQuestion.isProblem()) {
|
|
|
|
+ // 状态更新
|
|
|
|
+ if (markTaskService.updateProblemResult(task.getId(), userId, now, markResultQuestion.getSpent())) {
|
|
|
|
+ saveProblemHistory(markResultQuestion, task, userId);
|
|
|
|
+ updateMarkedCount(markUserQuestion.getExamId(), markUserQuestion.getPaperNumber(), markUserQuestion.getQuestionId());
|
|
|
|
+ // 未评完
|
|
|
|
+ resetStudentStatus(task.getStudentId());
|
|
|
|
+ count++;
|
|
|
|
+ }
|
|
|
|
+ } else if (MarkTaskStatus.ARBITRATED.equals(task.getStatus()) || MarkTaskStatus.WAIT_ARBITRATE.equals(task.getStatus())) {
|
|
|
|
+ // 待仲裁、已仲裁,直接跳过
|
|
|
|
+ count++;
|
|
|
|
+ } else if (markResultQuestion.getMarkerScore() <= markQuestion.getTotalScore()) {//阅卷分是否小于等于该组总分
|
|
|
|
+ if (submitTask(task, userId, markQuestion, markResultQuestion)) {
|
|
|
|
+ updateMarkedCount(markUserQuestion.getExamId(), markUserQuestion.getPaperNumber(), markUserQuestion.getQuestionId());
|
|
|
|
+ count++;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
+ throw ExceptionResultEnum.ERROR.exception(e.getMessage());
|
|
|
|
+ } finally {
|
|
|
|
+ lockService.unwatch(LockType.QUESTION, markResultQuestion.getQuestionId());
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ if (CollectionUtils.size(result.getQuestionList()) == count) {
|
|
|
|
+ // 更新当前正在阅卷的questionId
|
|
|
|
+ markUserPaperService.update(examId, paperNumber, userId, null, null, result.getMarkedQuestionId());
|
|
|
|
+ return SubmitResult.success(result.getStudentId());
|
|
|
|
+ } else {
|
|
|
|
+ return SubmitResult.faile();
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private void saveProblemHistory(MarkResultQuestion result, MarkTask task, Long userId) {
|
|
|
|
+ MarkProblemHistory history = markProblemHistoryService.findByTaskIdAndStatus(task.getId(),
|
|
|
|
+ MarkProblemStatus.WAITING);
|
|
|
|
+ if (history == null) {
|
|
|
|
+ history = new MarkProblemHistory();
|
|
|
|
+ history.setId(SystemConstant.getDbUuid());
|
|
|
|
+ }
|
|
|
|
+ history.setExamId(task.getExamId());
|
|
|
|
+ history.setSecretNumber(task.getSecretNumber());
|
|
|
|
+ history.setStudentCode(task.getStudentCode());
|
|
|
|
+ history.setStudentId(task.getStudentId());
|
|
|
|
+ history.setTaskId(task.getId());
|
|
|
|
+ history.setPaperNumber(task.getPaperNumber());
|
|
|
|
+ history.setQuestionId(task.getQuestionId());
|
|
|
|
+ history.setType(result.getProblemType());
|
|
|
|
+ if (MarkProblemType.OTHER.equals(result.getProblemType())) {
|
|
|
|
+ history.setRemark(result.getProblemRemark());
|
|
|
|
+ }
|
|
|
|
+ history.setCreateTime(System.currentTimeMillis());
|
|
|
|
+ history.setStatus(MarkProblemStatus.WAITING);
|
|
|
|
+ history.setUserId(userId);
|
|
|
|
+ markProblemHistoryService.saveOrUpdate(history);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private boolean submitTask(MarkTask task, Long userId, MarkQuestion markQuestion, MarkResultQuestion result) {
|
|
|
|
+ // 非本人领取的待评任务
|
|
|
|
+ if ((task.getStatus() == MarkTaskStatus.WAITING || task.getStatus() == MarkTaskStatus.REJECTED)
|
|
|
|
+ && !hasApplied(task, userId)) {
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+ // 非本人的回评任务
|
|
|
|
+ if ((task.getStatus() == MarkTaskStatus.MARKED) && !task.getUserId().equals(userId)) {
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+ // 是否多评情况下已处理过该考生评卷任务
|
|
|
|
+ if (markTaskService.countByStudentIdAndMarkerIdAndIdNotEqual(task.getStudentId(), task.getExamId(),
|
|
|
|
+ task.getPaperNumber(), task.getQuestionId(), userId, task.getId()) > 0) {
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+ // 尝试提交评卷结果
|
|
|
|
+ Long now = System.currentTimeMillis();
|
|
|
|
+ //更新阅卷任务状态为已阅卷[阅卷分数,给分明细,阅卷时间,评卷时长]
|
|
|
|
+ if (!markTaskService.updateMarkerResult(task.getId(), MarkTaskStatus.MARKED, userId,
|
|
|
|
+ result, now, null, null, null, MarkTaskStatus.WAITING,
|
|
|
|
+ MarkTaskStatus.MARKED, MarkTaskStatus.REJECTED)) {
|
|
|
|
+ // 条件不符更新失败,直接返回
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+ // 判断多评模式下是否需要仲裁
|
|
|
|
+ MarkArbitrateHistory history = null;
|
|
|
|
+ if (markQuestion.getArbitrateThreshold() != null && markQuestion.getArbitrateThreshold() > 0) {
|
|
|
|
+ // 多评模式
|
|
|
|
+ List<MarkTask> list = markTaskService.findByStudentIdAndQuestionIdAndStatus(task.getStudentId(), task.getQuestionId(), MarkTaskStatus.MARKED);
|
|
|
|
+ for (MarkTask other : list) {
|
|
|
|
+ // 本评卷任务或组长已打分,则跳过该任务
|
|
|
|
+ if (other.getId().equals(task.getId()) || other.getHeaderScore() != null) {
|
|
|
|
+ continue;
|
|
|
|
+ }
|
|
|
|
+ // 分差超过阀值
|
|
|
|
+ if (Math.abs(other.getMarkerScore() - result.getMarkerScore()) > markQuestion.getArbitrateThreshold()) {
|
|
|
|
+ history = buildArbitrateHistory(task, now);
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ if (history != null) {
|
|
|
|
+ // 保存仲裁记录
|
|
|
|
+ markArbitrateHistoryService.save(history);
|
|
|
|
+ // 触发仲裁后续状态更新
|
|
|
|
+ markTaskService.updateStatusByStudentIdAndQuestionId(task.getStudentId(), task.getQuestionId(), MarkTaskStatus.WAIT_ARBITRATE);
|
|
|
|
+ // 未评完
|
|
|
|
+ resetStudentStatus(task.getStudentId());
|
|
|
|
+ } else {
|
|
|
|
+ // 回评时,分数不一致,需要重新统分
|
|
|
|
+ if (task.getMarkerScore() != null && !task.getMarkerScore().equals(result.getMarkerScore())) {
|
|
|
|
+ resetStudentStatus(task.getStudentId());
|
|
|
|
+ markTaskService.resetHeaderByStudentIdAndQuestionId(task.getStudentId(), task.getQuestionId());
|
|
|
|
+ markHeaderHistoryService.deleteByStudentIdAndQuestionId(task.getStudentId(), task.getQuestionId());
|
|
|
|
+ }
|
|
|
|
+ // 判断当前分组是否已完成评卷
|
|
|
|
+ markQuestion.setMarkScore(result.getMarkerScore());
|
|
|
|
+ checkStudentQuestion(task.getStudentId(), markQuestion);
|
|
|
|
+ }
|
|
|
|
+ return true;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private MarkArbitrateHistory buildArbitrateHistory(MarkTask task, Long now) {
|
|
|
|
+ MarkArbitrateHistory history = new MarkArbitrateHistory();
|
|
|
|
+ history.setId(SystemConstant.getDbUuid());
|
|
|
|
+ history.setExamId(task.getExamId());
|
|
|
|
+ history.setPaperNumber(task.getPaperNumber());
|
|
|
|
+ history.setQuestionId(task.getQuestionId());
|
|
|
|
+ history.setStudentId(task.getStudentId());
|
|
|
|
+ history.setStudentCode(task.getStudentCode());
|
|
|
|
+ history.setSecretNumber(task.getSecretNumber());
|
|
|
|
+ history.setStatus(MarkArbitrateStatus.WAITING);
|
|
|
|
+ history.setCreateTime(now);
|
|
|
|
+ return history;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @Override
|
|
|
|
+ public void checkStudentSubjectiveScore(Long examId, String coursePaperId) {
|
|
|
|
+ List<MarkStudent> markStudentList = markStudentService.listByExamIdAndCoursePaperId(examId, coursePaperId);
|
|
|
|
+ for (MarkStudent markStudent : markStudentList) {
|
|
|
|
+ resetStudentStatus(markStudent.getId());
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @Override
|
|
|
|
+ @Transactional
|
|
|
|
+ public boolean rejectMarkTask(MarkTask markTask, Long userId, String reason) {
|
|
|
|
+ MarkPaper markPaper = markPaperService.getByExamIdAndPaperNumber(markTask.getExamId(), markTask.getPaperNumber());
|
|
|
|
+ if (MarkPaperStatus.FINISH.equals(markPaper.getStatus())) {
|
|
|
|
+ throw ExceptionResultEnum.MARK_PAPER_FINISH.exception();
|
|
|
|
+ }
|
|
|
|
+ MarkRejectHistory history = new MarkRejectHistory(markTask);
|
|
|
|
+ MarkStudent markStudent = markStudentService.getById(markTask.getStudentId());
|
|
|
|
+ history.setBasicStudentId(markStudent.getBasicStudentId());
|
|
|
|
+ history.setRejectUserId(userId);
|
|
|
|
+ history.setRejectReason(reason);
|
|
|
|
+ Long now = System.currentTimeMillis();
|
|
|
|
+ if (markTaskService.resetById(markTask.getId(), null, reason, userId, now, MarkTaskStatus.REJECTED)) {
|
|
|
|
+ markUserQuestionService.updateRejectCountByExamIdAndPaperNumberAndQuestionIdAndUserId(markTask.getExamId(), markTask.getPaperNumber(), markTask.getQuestionId(), markTask.getUserId());
|
|
|
|
+ markRejectHistoryService.save(history);
|
|
|
|
+// markSubjectiveScoreService.updateRejected(markTask.getStudentId(), markTask.getQuestionId(), true);
|
|
|
|
+ markSubjectiveScoreService.deleteByStudentIdAndQuestionId(markTask.getStudentId(), markTask.getQuestionId());
|
|
|
|
+ resetStudentStatus(markTask.getStudentId());
|
|
|
|
+ markTaskService.resetHeaderByStudentIdAndQuestionId(markTask.getStudentId(), markTask.getQuestionId());
|
|
|
|
+ markHeaderHistoryService.deleteByStudentIdAndQuestionId(markTask.getStudentId(), markTask.getQuestionId());
|
|
|
|
+ updateMarkedCount(markTask.getExamId(), markTask.getPaperNumber(), markTask.getQuestionId());
|
|
|
|
+ return true;
|
|
|
|
+ } else {
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @Override
|
|
|
|
+ public void deleteMarkTask(MarkQuestion markQuestion, boolean b) {
|
|
|
|
+ // 正评相关数据
|
|
|
|
+ if (b) {
|
|
|
|
+ markArbitrateHistoryService.deleteByExamIdAndPaperNumberAndQuestionId(markQuestion.getExamId(), markQuestion.getPaperNumber(), markQuestion.getId());
|
|
|
|
+ markProblemHistoryService.deleteByExamIdAndPaperNumberAndQuestionId(markQuestion.getExamId(), markQuestion.getPaperNumber(), markQuestion.getId());
|
|
|
|
+ markTaskService.deleteByExamIdAndPaperNumberAndQuestionId(markQuestion.getExamId(), markQuestion.getPaperNumber(), markQuestion.getId());
|
|
|
|
+ markRejectHistoryService.deleteByExamIdAndPaperNumberAndQuestionId(markQuestion.getExamId(), markQuestion.getPaperNumber(), markQuestion.getId());
|
|
|
|
+ }
|
|
|
|
+ markSubjectiveScoreService.deleteByExamIdAndPaperNumberAndQuestionId(markQuestion.getExamId(), markQuestion.getPaperNumber(), markQuestion.getId());
|
|
|
|
+ // 释放本小题所有评卷员的任务
|
|
|
|
+ List<MarkUserQuestion> markUserQuestions = markUserQuestionService.listByExamIdAndPaperNumberAndQuestionId(markQuestion.getExamId(), markQuestion.getPaperNumber(), markQuestion.getId());
|
|
|
|
+ for (MarkUserQuestion markUserQuestion : markUserQuestions) {
|
|
|
|
+ releaseByMarkUserGroup(markUserQuestion);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @Override
|
|
|
|
+ public void releaseByMarkQuestion(MarkQuestion markQuestion) {
|
|
|
|
+ TaskLock taskLock = getTaskLock(markQuestion);
|
|
|
|
+ taskLock.clear();
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @Override
|
|
|
|
+ public void resetMarkedQuestionId(MarkUserQuestion markUserQuestion) {
|
|
|
|
+ List<MarkQuestion> markQuestionList = markQuestionService.listByExamIdAndPaperNumberAndObjective(markUserQuestion.getExamId(), markUserQuestion.getPaperNumber(), false);
|
|
|
|
+ List<Long> list = markQuestionList.stream().map(MarkQuestion::getId).collect(Collectors.toList());
|
|
|
|
+ MarkUserPaper markUserPaper = markUserPaperService.getByExamIdAndPaperNumberAndUserId(markUserQuestion.getExamId(), markUserQuestion.getPaperNumber(), markUserQuestion.getUserId());
|
|
|
|
+ if (markUserPaper != null && QuestionModel.SINGLE.equals(markUserPaper.getQuestionModel()) && markUserPaper.getMarkedQuestionId() != null) {
|
|
|
|
+ int currentQuestionIdIndex = list.indexOf(markUserQuestion.getQuestionId());
|
|
|
|
+ int oldQuestionIdIndex = list.indexOf(markUserPaper.getMarkedQuestionId());
|
|
|
|
+ if (currentQuestionIdIndex < oldQuestionIdIndex) {
|
|
|
|
+ markUserPaper.setMarkedQuestionId(markUserQuestion.getQuestionId());
|
|
|
|
+ markUserPaperService.updateById(markUserPaper);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @Override
|
|
|
|
+ public void aiMark(Long examId, String paperNumber, Long questionId) {
|
|
|
|
+ List<MarkTask> markTasks = null;
|
|
|
|
+ int pageNumber = 1;
|
|
|
|
+ while (CollectionUtils.isNotEmpty(markTasks)) {
|
|
|
|
+ Set<Long> questions = new HashSet<>(Arrays.asList(questionId));
|
|
|
|
+ markTasks = markTaskService.findUnMarkedFilterClass(new Page<>(pageNumber, 20), examId, paperNumber, null, questionId, null);
|
|
|
|
+ if (markTasks.isEmpty()) {
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ for (MarkTask t : markTasks) {
|
|
|
|
+ if (this.applyTask(examId, paperNumber, t.getStudentId(), null, questions, Arrays.asList(t.getId()))) {
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ pageNumber++;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+}
|