|
@@ -1,53 +1,41 @@
|
|
package com.qmth.teachcloud.mark.service.impl;
|
|
package com.qmth.teachcloud.mark.service.impl;
|
|
|
|
|
|
import com.alibaba.fastjson.JSON;
|
|
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.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
|
-import com.qmth.boot.api.exception.ApiException;
|
|
|
|
|
|
+import com.qmth.boot.core.ai.client.OcrApiClient;
|
|
|
|
+import com.qmth.boot.core.ai.model.llm.score.AutoScoreRequest;
|
|
|
|
+import com.qmth.boot.core.ai.model.llm.score.AutoScoreResult;
|
|
|
|
+import com.qmth.boot.core.ai.model.llm.score.StandardAnswer;
|
|
|
|
+import com.qmth.boot.core.ai.model.ocr.OcrType;
|
|
|
|
+import com.qmth.boot.core.ai.service.AiService;
|
|
|
|
+import com.qmth.boot.core.retrofit.utils.UploadFile;
|
|
|
|
+import com.qmth.teachcloud.common.bean.dto.mark.PictureConfig;
|
|
|
|
+import com.qmth.teachcloud.common.bean.vo.FilePathVo;
|
|
import com.qmth.teachcloud.common.contant.SystemConstant;
|
|
import com.qmth.teachcloud.common.contant.SystemConstant;
|
|
import com.qmth.teachcloud.common.entity.BasicCourse;
|
|
import com.qmth.teachcloud.common.entity.BasicCourse;
|
|
|
|
+import com.qmth.teachcloud.common.entity.BasicSchool;
|
|
import com.qmth.teachcloud.common.entity.MarkQuestion;
|
|
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.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.common.mapper.BasicCourseMapper;
|
|
|
|
+import com.qmth.teachcloud.common.mapper.BasicSchoolMapper;
|
|
|
|
+import com.qmth.teachcloud.common.service.FileUploadService;
|
|
|
|
+import com.qmth.teachcloud.common.util.FileUtil;
|
|
|
|
+import com.qmth.teachcloud.mark.dto.ai.SheetImageDto;
|
|
import com.qmth.teachcloud.mark.entity.*;
|
|
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.enums.AiQuestionParamModeStatus;
|
|
import com.qmth.teachcloud.mark.lock.LockService;
|
|
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.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 com.qmth.teachcloud.mark.utils.AiUtil;
|
|
import org.apache.commons.collections4.CollectionUtils;
|
|
import org.apache.commons.collections4.CollectionUtils;
|
|
|
|
+import org.apache.commons.lang3.StringUtils;
|
|
import org.slf4j.Logger;
|
|
import org.slf4j.Logger;
|
|
import org.slf4j.LoggerFactory;
|
|
import org.slf4j.LoggerFactory;
|
|
import org.springframework.stereotype.Service;
|
|
import org.springframework.stereotype.Service;
|
|
-import org.springframework.transaction.annotation.Transactional;
|
|
|
|
|
|
|
|
import javax.annotation.Resource;
|
|
import javax.annotation.Resource;
|
|
-import java.math.BigDecimal;
|
|
|
|
|
|
+import java.io.File;
|
|
import java.util.*;
|
|
import java.util.*;
|
|
import java.util.concurrent.ConcurrentHashMap;
|
|
import java.util.concurrent.ConcurrentHashMap;
|
|
-import java.util.function.Function;
|
|
|
|
import java.util.stream.Collectors;
|
|
import java.util.stream.Collectors;
|
|
|
|
|
|
@Service
|
|
@Service
|
|
@@ -58,18 +46,29 @@ public class AiMarkServiceImpl implements AiMarkService {
|
|
private Map<Long, Long> markerLastUpdateTime = new ConcurrentHashMap<>();
|
|
private Map<Long, Long> markerLastUpdateTime = new ConcurrentHashMap<>();
|
|
|
|
|
|
@Resource
|
|
@Resource
|
|
- private BasicCourseService basicCourseService;
|
|
|
|
|
|
+ private BasicSchoolMapper basicSchoolMapper;
|
|
@Resource
|
|
@Resource
|
|
- private MarkPaperService markPaperService;
|
|
|
|
-
|
|
|
|
|
|
+ private BasicCourseMapper basicCourseMapper;
|
|
|
|
+ @Resource
|
|
|
|
+ private MarkService markService;
|
|
|
|
+ @Resource
|
|
|
|
+ private AiService aiService;
|
|
|
|
+ @Resource
|
|
|
|
+ private FileUploadService fileUploadService;
|
|
|
|
+ @Resource
|
|
|
|
+ private MarkOcrStudentQuestionService markOcrStudentQuestionService;
|
|
@Resource
|
|
@Resource
|
|
private MarkQuestionService markQuestionService;
|
|
private MarkQuestionService markQuestionService;
|
|
@Resource
|
|
@Resource
|
|
- private MarkUserPaperService markUserPaperService;
|
|
|
|
|
|
+ private MarkAiQuestionParamService markAiQuestionParamService;
|
|
|
|
+ @Resource
|
|
|
|
+ private MarkAiQuestionPointService markAiQuestionPointService;
|
|
|
|
+ @Resource
|
|
|
|
+ private MarkAiQuestionLevelService markAiQuestionLevelService;
|
|
@Resource
|
|
@Resource
|
|
private MarkUserQuestionService markUserQuestionService;
|
|
private MarkUserQuestionService markUserQuestionService;
|
|
@Resource
|
|
@Resource
|
|
- private MarkUserClassService markUserClassService;
|
|
|
|
|
|
+ private OcrApiClient ocrApiClient;
|
|
|
|
|
|
@Resource
|
|
@Resource
|
|
private MarkTaskService markTaskService;
|
|
private MarkTaskService markTaskService;
|
|
@@ -88,1426 +87,163 @@ public class AiMarkServiceImpl implements AiMarkService {
|
|
@Resource
|
|
@Resource
|
|
LockService lockService;
|
|
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
|
|
@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);
|
|
|
|
|
|
+ public void aiMark(Long examId, String paperNumber, Long questionId) {
|
|
|
|
+ BasicSchool basicSchool = basicSchoolMapper.selectByExamId(examId);
|
|
|
|
+ BasicCourse basicCourse = basicCourseMapper.selectByExamIdAndPaperNumber(examId, paperNumber);
|
|
|
|
+ MarkQuestion markQuestion = markQuestionService.getById(questionId);
|
|
|
|
+ MarkAiQuestionParam markAiQuestionParam = markAiQuestionParamService.getByExamIdAndPaperNumberAndQuestionId(examId, paperNumber, questionId);
|
|
|
|
+ List<MarkTask> markTasks = null;
|
|
|
|
+ int pageNumber = 1;
|
|
|
|
+ do {
|
|
|
|
+ Set<Long> questions = new HashSet<>(Arrays.asList(questionId));
|
|
|
|
+ markTasks = markTaskService.findAiUnMarked(new Page<>(pageNumber, 20), examId, paperNumber, questionId);
|
|
|
|
+ if (markTasks.isEmpty()) {
|
|
|
|
+ break;
|
|
}
|
|
}
|
|
- } 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;
|
|
|
|
|
|
+ for (MarkTask t : markTasks) {
|
|
|
|
+ if (markService.applyTask(examId, paperNumber, t.getStudentId(), null, questions, Arrays.asList(t.getId()))) {
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
- }
|
|
|
|
- }
|
|
|
|
- return calculate;
|
|
|
|
- }
|
|
|
|
|
|
+ // 考生作答
|
|
|
|
+ try {
|
|
|
|
+ String studentQuestionAnswer = this.mergeQuestionOcrResult(this.listStudentQuestionOcrResult(basicSchool, t.getStudentId(), t.getQuestionId()));
|
|
|
|
|
|
- @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.existMarkAiQuestionPointOrLevel(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());
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
|
|
+ AutoScoreRequest request = new AutoScoreRequest();
|
|
|
|
+ request.setSubjectName(basicCourse.getName());
|
|
|
|
+ request.setTotalScore(markQuestion.getTotalScore());
|
|
|
|
+ request.setIntervalScore(markAiQuestionParam.getMinScore());
|
|
|
|
+ request.setQuestionBody(markAiQuestionParam.getMainTitle());
|
|
|
|
+ request.setStudentAnswer(studentQuestionAnswer);
|
|
|
|
+ request.setStandardAnswer(buildStandardAnswer(markAiQuestionParam));
|
|
|
|
+ // AI评卷
|
|
|
|
+ AutoScoreResult autoScoreResult = aiService.autoScore(request, AiUtil.signature(basicSchool));
|
|
|
|
|
|
- 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++;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
+ throw new RuntimeException(e);
|
|
|
|
+ } finally {
|
|
}
|
|
}
|
|
- // 有新任务创建
|
|
|
|
- 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;
|
|
|
|
|
|
+ pageNumber++;
|
|
|
|
+ markTasks = markTaskService.findAiUnMarked(new Page<>(pageNumber, 20), examId, paperNumber, questionId);
|
|
|
|
+ }while (CollectionUtils.isNotEmpty(markTasks));
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private List<StandardAnswer> buildStandardAnswer(MarkAiQuestionParam markAiQuestionParam) {
|
|
|
|
+ List<StandardAnswer> standardAnswerList = new ArrayList<>();
|
|
|
|
+ // 得分点
|
|
|
|
+ if (AiQuestionParamModeStatus.POINT.equals(markAiQuestionParam.getMode())) {
|
|
|
|
+ List<MarkAiQuestionPoint> markAiQuestionPoints = markAiQuestionPointService.listByAiQuestionId(markAiQuestionParam.getId());
|
|
|
|
+ if (CollectionUtils.isEmpty(markAiQuestionPoints)) {
|
|
|
|
+ throw ExceptionResultEnum.ERROR.exception("未设置得分点");
|
|
|
|
+ }
|
|
|
|
+ standardAnswerList = markAiQuestionPoints.stream().map(m -> {
|
|
|
|
+ StandardAnswer standardAnswer = new StandardAnswer();
|
|
|
|
+ standardAnswer.setScore(m.getScore());
|
|
|
|
+ standardAnswer.setContent(m.getAnswer());
|
|
|
|
+ return standardAnswer;
|
|
|
|
+ }).collect(Collectors.toList());
|
|
|
|
+ }
|
|
|
|
+ // 档次
|
|
|
|
+ else if (AiQuestionParamModeStatus.LEVEL.equals(markAiQuestionParam.getMode())) {
|
|
|
|
+ List<MarkAiQuestionLevel> markAiQuestionLevels = markAiQuestionLevelService.listByAiQuestionId(markAiQuestionParam.getId());
|
|
|
|
+ if (CollectionUtils.isEmpty(markAiQuestionLevels)) {
|
|
|
|
+ throw ExceptionResultEnum.ERROR.exception("未设置档次");
|
|
|
|
+ }
|
|
|
|
+ standardAnswerList = markAiQuestionLevels.stream().map(m -> {
|
|
|
|
+ StandardAnswer standardAnswer = new StandardAnswer();
|
|
|
|
+ standardAnswer.setLowScore(m.getMinScore());
|
|
|
|
+ standardAnswer.setHighScore(m.getMaxScore());
|
|
|
|
+ standardAnswer.setContent(m.getAnswer());
|
|
|
|
+ return standardAnswer;
|
|
|
|
+ }).collect(Collectors.toList());
|
|
} else {
|
|
} 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());
|
|
|
|
|
|
+ throw ExceptionResultEnum.ERROR.exception("评分模式不存在");
|
|
}
|
|
}
|
|
|
|
+ return standardAnswerList;
|
|
}
|
|
}
|
|
|
|
|
|
- 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());
|
|
|
|
|
|
+ private String mergeQuestionOcrResult(List<MarkOcrStudentQuestion> markOcrStudentQuestionList) {
|
|
|
|
+ if (CollectionUtils.isEmpty(markOcrStudentQuestionList)) {
|
|
|
|
+ return null;
|
|
}
|
|
}
|
|
- // 计算选做题分数
|
|
|
|
- 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;
|
|
|
|
|
|
+ return markOcrStudentQuestionList.stream().filter(m -> StringUtils.isNotBlank(m.getOcrContent())).map(MarkOcrStudentQuestion::getOcrContent).collect(Collectors.joining(SystemConstant.COMMA_OF_CHINESE));
|
|
}
|
|
}
|
|
|
|
|
|
@Override
|
|
@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("参数有误");
|
|
|
|
|
|
+ public List<MarkOcrStudentQuestion> listStudentQuestionOcrResult(BasicSchool basicSchool, Long studentId, Long questionId) {
|
|
|
|
+ List<MarkOcrStudentQuestion> markOcrStudentQuestionList = markOcrStudentQuestionService.listByStudentIdAndQuestionId(studentId, questionId);
|
|
|
|
+ if (CollectionUtils.isNotEmpty(markOcrStudentQuestionList)) {
|
|
|
|
+ return markOcrStudentQuestionList;
|
|
}
|
|
}
|
|
- 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);
|
|
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;
|
|
|
|
|
|
+ if (markQuestion == null || StringUtils.isBlank(markQuestion.getPicList())) {
|
|
|
|
+ throw ExceptionResultEnum.ERROR.exception("大题号[" + markQuestion.getMainNumber() + "]、小题号[" + markQuestion.getSubNumber() + "]未设置评卷区");
|
|
|
|
+ }
|
|
|
|
+ // 读取考生图片
|
|
|
|
+ MarkStudent markStudent = markStudentService.getById(studentId);
|
|
|
|
+ if (markStudent == null) {
|
|
|
|
+ throw ExceptionResultEnum.ERROR.exception("未找到考生" + ",考生ID[" + studentId);
|
|
|
|
+ } else if (StringUtils.isBlank(markStudent.getSheetPath())) {
|
|
|
|
+ throw ExceptionResultEnum.ERROR.exception("未查询到原图" + ",考号[" + markStudent.getStudentCode());
|
|
|
|
+ }
|
|
|
|
+ List<File> deleteFileList = new ArrayList<>();
|
|
|
|
+ //考生题卡原图
|
|
try {
|
|
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);
|
|
|
|
|
|
+ List<FilePathVo> filePathVoList = markStudent.listSheetPath();
|
|
|
|
+ Map<Integer, SheetImageDto> fileMap = new HashMap<>();
|
|
|
|
+ for (int i = 0; i < filePathVoList.size(); i++) {
|
|
|
|
+ FilePathVo filePathVo = filePathVoList.get(i);
|
|
|
|
+ File file = SystemConstant.getFileTempDirVar(SystemConstant.JPG_PREFIX);
|
|
|
|
+ try {
|
|
|
|
+ fileUploadService.downloadFile(filePathVo.getPath(), filePathVo.getUploadType(), filePathVo.getType(), file.getPath());
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
+ throw ExceptionResultEnum.ERROR.exception("读取考生原图失败" + ",考号[" + markStudent.getStudentCode() + "。" + e.getMessage());
|
|
|
|
+ }
|
|
|
|
+ fileMap.put(i + 1, new SheetImageDto(i + 1, file, filePathVo.getMd5(), AiUtil.imageDim(file)));
|
|
|
|
+ deleteFileList.add(file);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 题目评卷区
|
|
|
|
+ List<PictureConfig> pictureConfigList = JSON.parseArray(markQuestion.getPicList(), PictureConfig.class);
|
|
|
|
+
|
|
|
|
+ List<MarkOcrStudentQuestion> markOcrStudentQuestions = new ArrayList<>();
|
|
|
|
+ for (int i = 0; i < pictureConfigList.size(); i++) {
|
|
|
|
+ PictureConfig pictureConfig = pictureConfigList.get(i);
|
|
|
|
+ SheetImageDto sheetImageDto = fileMap.get(pictureConfig.getI());
|
|
|
|
+ File file = SystemConstant.getFileTempDirVar(SystemConstant.JPG_PREFIX);
|
|
|
|
+ AiUtil.subImg(sheetImageDto, pictureConfig, file);
|
|
|
|
+
|
|
|
|
+ // OCR识别
|
|
|
|
+ String ocrResult;
|
|
|
|
+ try {
|
|
|
|
+ ocrResult = ocrApiClient.forImage(AiUtil.signature(basicSchool), OcrType.HANDWRITING, UploadFile.build("image", "", file));
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
+ throw ExceptionResultEnum.ERROR.exception("OCR识别失败" + ",考号[" + markStudent.getStudentCode() + "。" + e.getMessage());
|
|
|
|
+ }
|
|
|
|
+ MarkOcrStudentQuestion markOcrStudentQuestion = new MarkOcrStudentQuestion();
|
|
|
|
+ markOcrStudentQuestion.setId(SystemConstant.getDbUuid());
|
|
|
|
+ markOcrStudentQuestion.setExamId(markStudent.getExamId());
|
|
|
|
+ markOcrStudentQuestion.setPaperNumber(markStudent.getPaperNumber());
|
|
|
|
+ markOcrStudentQuestion.setStudentId(studentId);
|
|
|
|
+ markOcrStudentQuestion.setQuestionId(questionId);
|
|
|
|
+ markOcrStudentQuestion.setNumber(i + 1);
|
|
|
|
+ markOcrStudentQuestion.setMd5(sheetImageDto.getMd5());
|
|
|
|
+ markOcrStudentQuestion.setOcrContent(ocrResult);
|
|
|
|
+ markOcrStudentQuestion.setCreateTime(System.currentTimeMillis());
|
|
|
|
+ markOcrStudentQuestions.add(markOcrStudentQuestion);
|
|
|
|
+ deleteFileList.add(file);
|
|
|
|
+ }
|
|
|
|
+ markOcrStudentQuestionService.saveBatch(markOcrStudentQuestions);
|
|
|
|
+ return markOcrStudentQuestions;
|
|
|
|
+ } catch (RuntimeException e) {
|
|
throw ExceptionResultEnum.ERROR.exception(e.getMessage());
|
|
throw ExceptionResultEnum.ERROR.exception(e.getMessage());
|
|
} finally {
|
|
} 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++;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
|
|
+ if (CollectionUtils.isNotEmpty(deleteFileList)) {
|
|
|
|
+ for (File file : deleteFileList) {
|
|
|
|
+ FileUtil.deleteFile(file);
|
|
}
|
|
}
|
|
- } 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.findAiUnMarked(new Page<>(pageNumber, 20), examId, paperNumber, questionId);
|
|
|
|
- if (markTasks.isEmpty()) {
|
|
|
|
- break;
|
|
|
|
- }
|
|
|
|
- for (MarkTask t : markTasks) {
|
|
|
|
- if (this.applyTask(examId, paperNumber, t.getStudentId(), null, questions, Arrays.asList(t.getId()))) {
|
|
|
|
- break;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- pageNumber++;
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|