package cn.com.qmth.scancentral.service.impl; import cn.com.qmth.scancentral.bean.OmrTaskDto; import cn.com.qmth.scancentral.bean.OmrTaskPageDto; import cn.com.qmth.scancentral.bean.User; import cn.com.qmth.scancentral.dao.OmrTaskDao; import cn.com.qmth.scancentral.entity.*; import cn.com.qmth.scancentral.enums.*; import cn.com.qmth.scancentral.exception.NotFoundExceptions; import cn.com.qmth.scancentral.model.OmrCondition; import cn.com.qmth.scancentral.model.OmrTaskItem; import cn.com.qmth.scancentral.model.OmrTaskPage; import cn.com.qmth.scancentral.service.*; import cn.com.qmth.scancentral.support.TaskLock; import cn.com.qmth.scancentral.support.TaskLockUtil; import cn.com.qmth.scancentral.vo.omr.OmrTaskOverview; import cn.com.qmth.scancentral.vo.paperstructureinfo.PaperStructure; import cn.com.qmth.scancentral.vo.task.*; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.qmth.boot.core.concurrent.service.ConcurrentService; import com.qmth.boot.core.exception.ParameterException; import org.apache.commons.collections4.CollectionUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import javax.validation.constraints.NotNull; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; @Service public class OmrTaskServiceImpl extends ServiceImpl implements OmrTaskService { @Autowired private PaperService paperService; @Autowired private OmrGroupService groupService; @Autowired private PaperPageService pageService; @Autowired private StudentService studentService; @Autowired private SubjectService subjectService; @Autowired private StudentPaperService studentPaperService; @Autowired private PaperStructureService structureService; @Autowired private ConcurrentService concurrentService; private static final String OMR_SUSPECT = "?"; private static final String OMR_BLANK = "#"; @Override public int getCountByExamAndStatus(Long examId, TaskStatus... status) { QueryWrapper wrapper = new QueryWrapper<>(); LambdaQueryWrapper lw = wrapper.lambda(); lw.and(param -> { for (TaskStatus taskStatus : status) { param.or().eq(OmrTaskEntity::getStatus, taskStatus); } }); lw.eq(OmrTaskEntity::getExamId, examId); return this.count(wrapper); } @Override public int getCountByGroupAndStatus(Long groupId, TaskStatus... status) { QueryWrapper wrapper = new QueryWrapper<>(); LambdaQueryWrapper lw = wrapper.lambda(); lw.and(param -> { for (TaskStatus taskStatus : status) { param.or().eq(OmrTaskEntity::getStatus, taskStatus); } }); lw.eq(OmrTaskEntity::getGroupId, groupId); return this.count(wrapper); } @Override public int getCountByExamAndStatusAndDevice(Long examId, String device, TaskStatus... status) { QueryWrapper wrapper = new QueryWrapper<>(); LambdaQueryWrapper lw = wrapper.lambda(); lw.and(param -> { for (TaskStatus taskStatus : status) { param.or().eq(OmrTaskEntity::getStatus, taskStatus); } }); lw.eq(OmrTaskEntity::getExamId, examId); lw.eq(OmrTaskEntity::getDevice, device); return this.count(wrapper); } @Override public int getCountByGroupAndStatusAndDevice(Long groupId, String device, TaskStatus... status) { QueryWrapper wrapper = new QueryWrapper<>(); LambdaQueryWrapper lw = wrapper.lambda(); lw.and(param -> { for (TaskStatus taskStatus : status) { param.or().eq(OmrTaskEntity::getStatus, taskStatus); } }); lw.eq(OmrTaskEntity::getGroupId, groupId); lw.eq(OmrTaskEntity::getDevice, device); return this.count(wrapper); } @Transactional @Override public void deleteByGroupId(Long groupId) { UpdateWrapper wrapper = new UpdateWrapper<>(); LambdaUpdateWrapper lw = wrapper.lambda(); lw.eq(OmrTaskEntity::getGroupId, groupId); this.baseMapper.delete(wrapper); } @Transactional @Override public void waitingByGroupToggle(Long groupId) { UpdateWrapper wrapper = new UpdateWrapper<>(); LambdaUpdateWrapper lw = wrapper.lambda(); lw.set(OmrTaskEntity::getStatus, TaskStatus.WAITING); lw.eq(OmrTaskEntity::getGroupId, groupId); lw.eq(OmrTaskEntity::getStatus, TaskStatus.PROCESSED); this.update(wrapper); } @Transactional @Override public void resetByGroup(OmrGroupEntity group) { QueryWrapper wrapper = new QueryWrapper<>(); LambdaQueryWrapper lw = wrapper.lambda(); lw.eq(OmrTaskEntity::getGroupId, group.getId()); List list = this.list(wrapper); if (Stage.FIRST.equals(group.getStage())) { for (OmrTaskEntity omrTaskEntity : list) { concurrentService.getReadWriteLock(LockType.STUDENT + "-" + omrTaskEntity.getStudentId()).writeLock() .lock(); for (OmrTaskPage page : omrTaskEntity.getPages()) { for (OmrTaskItem item : page.getItems()) { item.setFirstResult(null); item.setSecondResult(null); item.setArbitrateResult(null); } } omrTaskEntity.setStatus(TaskStatus.WAITING); this.saveOrUpdate(omrTaskEntity); concurrentService.getReadWriteLock(LockType.STUDENT + "-" + omrTaskEntity.getStudentId()).writeLock() .unlock(); } } if (Stage.SECOND.equals(group.getStage())) { for (OmrTaskEntity omrTaskEntity : list) { concurrentService.getReadWriteLock(LockType.STUDENT + "-" + omrTaskEntity.getStudentId()).writeLock() .lock(); for (OmrTaskPage page : omrTaskEntity.getPages()) { for (OmrTaskItem item : page.getItems()) { item.setSecondResult(null); item.setArbitrateResult(null); } } omrTaskEntity.setStatus(TaskStatus.WAITING); this.saveOrUpdate(omrTaskEntity); concurrentService.getReadWriteLock(LockType.STUDENT + "-" + omrTaskEntity.getStudentId()).writeLock() .unlock(); } } } private boolean onlyFillSuspect(OmrGroupEntity group) { if (group.getConditions().size() > 1) { return false; } if (ConditionType.FILL_SUSPECT.equals(group.getConditions().get(0).getCode())) { return true; } return false; } private void delete(Long groupId, Long studentId) { UpdateWrapper wrapper = new UpdateWrapper<>(); LambdaUpdateWrapper lw = wrapper.lambda(); lw.eq(OmrTaskEntity::getGroupId, groupId); lw.eq(OmrTaskEntity::getStudentId, studentId); this.baseMapper.delete(wrapper); } private void delete(Long groupId, Long studentId, Long paperId) { UpdateWrapper wrapper = new UpdateWrapper<>(); LambdaUpdateWrapper lw = wrapper.lambda(); lw.eq(OmrTaskEntity::getGroupId, groupId); lw.eq(OmrTaskEntity::getStudentId, studentId); lw.eq(OmrTaskEntity::getPaperId, paperId); this.baseMapper.delete(wrapper); } private List getByStudent(Long groupId, Long studentId) { QueryWrapper wrapper = new QueryWrapper<>(); LambdaQueryWrapper lw = wrapper.lambda(); lw.eq(OmrTaskEntity::getGroupId, groupId); lw.eq(OmrTaskEntity::getStudentId, studentId); return baseMapper.selectList(wrapper); } private List clearAndToDispose(OmrGroupEntity group, Long studentId) { List spes = studentPaperService.findByStudentId(studentId); if (CollectionUtils.isEmpty(spes)) { return spes; } List tasks = getByStudent(group.getId(), studentId); if (CollectionUtils.isEmpty(tasks)) { return spes; } Map speMap = new HashMap<>(); for (StudentPaperEntity spe : spes) { speMap.put(spe.getPaperNumber(), spe.getPaperId()); } Map taskMap = new HashMap<>(); for (OmrTaskEntity t : tasks) { taskMap.put(t.getPaperNumber(), t.getPaperId()); } boolean onlyFillSuspect = onlyFillSuspect(group); if (onlyFillSuspect) { List ret = new ArrayList<>(); for (StudentPaperEntity spe : spes) { Long paperId = taskMap.get(spe.getPaperNumber()); if (paperId == null) {// 没有task的直接创建 ret.add(spe); } else if (paperId.longValue() != spe.getPaperId().longValue()) {// 和task不一致的删除并创建 delete(group.getId(), studentId, paperId); ret.add(spe); } } for (OmrTaskEntity t : tasks) { if (speMap.get(t.getPaperNumber()) == null) {// 不在绑定关系的task删除 delete(group.getId(), studentId, t.getPaperId()); } } return ret; } else { if (spes.size() != tasks.size()) {// 数量不一致的删除重建 delete(group.getId(), studentId); return spes; } for (OmrTaskEntity t : tasks) { if (!t.getPaperId().equals(speMap.get(t.getPaperNumber()))) {// 有一个不一致的删除重建 delete(group.getId(), studentId); return spes; } } return null;// 完全一致的不处理 } } @Override public List buildTask(OmrGroupEntity group, Long studentId) { List paperIds = clearAndToDispose(group, studentId); if (CollectionUtils.isEmpty(paperIds)) { return null; } StudentEntity student = studentService.getById(studentId); // 所有客观题空白 boolean allObjectiveBlank = isAllBlank(paperIds); List retList = new ArrayList<>(); boolean multi_blank = false; boolean single_blank = false; int multi_blank_count = 0; int single_blank_count = 0; for (StudentPaperEntity spe : paperIds) { PaperEntity paper = paperService.getById(spe.getPaperId()); if (paper == null) { throw new ParameterException("paper不存在"); } Long paperId = spe.getPaperId(); OmrTaskEntity task = new OmrTaskEntity(); task.setCardNumber(paper.getCardNumber()); task.setExamId(paper.getExamId()); task.setGroupId(group.getId()); task.setPaperId(paperId); task.setPaperNumber(spe.getPaperNumber()); task.setStatus(TaskStatus.WAITING); task.setStudentId(spe.getStudentId()); task.setPages(new ArrayList<>()); List pageList = pageService.listByPaperId(paperId); OmrTaskDto taskDto = new OmrTaskDto(task); retList.add(taskDto); // 循环试卷 for (PaperPageEntity pageEntity : pageList) { OmrTaskPageDto pageDto = new OmrTaskPageDto(pageEntity.getPageIndex()); taskDto.getPage().add(pageDto); List items = pageDto.getItems(); // 分组类型 for (OmrCondition condition : group.getConditions()) { // 识别嫌疑 if (ConditionType.FILL_SUSPECT.equals(condition.getCode())) { for (int i = 0; pageEntity.getQuestion() != null && pageEntity.getQuestion().getResult() != null && i < pageEntity.getQuestion().getResult().size(); i++) { String result = pageEntity.getQuestion().getResult().get(i); if (result != null && result.startsWith(OMR_SUSPECT)) { OmrTaskItem item = new OmrTaskItem(); item.setIndex(i + 1); item.setField(OmrField.QUESTION); item.setOmrResult(result); items.add(item); } } } // 卷型空选 if (ConditionType.PAPER_TYPE_BLANK.equals(condition.getCode())) { if (pageEntity.getPaperType() != null && pageEntity.getPaperType().getResult().contains(OMR_BLANK)) { OmrTaskItem item = new OmrTaskItem(); item.setIndex(1); item.setField(OmrField.PAPER_TYPE); item.setOmrResult(pageEntity.getPaperType().getResult()); items.add(item); } } // 卷型多选 if (ConditionType.PAPER_TYPE_EXCEED.equals(condition.getCode())) { if ((!pageEntity.getPaperType().getResult().contains(OMR_SUSPECT) && pageEntity.getPaperType().getResult().length() > 2) || (pageEntity.getPaperType().getResult().contains(OMR_SUSPECT) && pageEntity.getPaperType().getResult().length() > 1)) { OmrTaskItem item = new OmrTaskItem(); item.setField(OmrField.PAPER_TYPE); item.setOmrResult(pageEntity.getPaperType().getResult()); items.add(item); } } if (ConditionType.QUESTION_MULTI_BLANK.equals(condition.getCode())) { for (int i = 0; pageEntity.getQuestion() != null && pageEntity.getQuestion().getResult() != null && i < pageEntity.getQuestion().getResult().size(); i++) { String result = pageEntity.getQuestion().getResult().get(i); PaperStructure question = structureService.getPaperStructure(paper.getExamId(), paper.getCardNumber(), spe.getPaperNumber(), pageEntity.getPageIndex(), i + 1, OmrField.QUESTION); if (!question.getSingle() && result != null && result.contains(OMR_BLANK)) { OmrTaskItem item = new OmrTaskItem(); item.setIndex(i + 1); item.setField(OmrField.QUESTION); item.setOmrResult(result); pageDto.getPageMultiBlankItems().add(item); multi_blank_count++; if (multi_blank_count > condition.getValue()) { multi_blank = true; } } } } if (ConditionType.QUESTION_SINGLE_BLANK.equals(condition.getCode()) && ScanStatus.SCANNED.equals(student.getStatus()) && !allObjectiveBlank) { for (int i = 0; pageEntity.getQuestion() != null && pageEntity.getQuestion().getResult() != null && i < pageEntity.getQuestion().getResult().size(); i++) { String result = pageEntity.getQuestion().getResult().get(i); PaperStructure question = structureService.getPaperStructure(paper.getExamId(), paper.getCardNumber(), spe.getPaperNumber(), pageEntity.getPageIndex(), i + 1, OmrField.QUESTION); if (question.getSingle() && result != null && result.contains(OMR_BLANK)) { OmrTaskItem item = new OmrTaskItem(); item.setIndex(i + 1); item.setField(OmrField.QUESTION); item.setOmrResult(result); pageDto.getPageSingleBlankItems().add(item); single_blank_count++; multi_blank_count++; if (single_blank_count > condition.getValue()) { single_blank = true; } } } } if (ConditionType.QUESTION_SINGLE_EXCEED.equals(condition.getCode()) && ScanStatus.SCANNED.equals(student.getStatus()) && !allObjectiveBlank) { for (int i = 0; pageEntity.getQuestion() != null && pageEntity.getQuestion().getResult() != null && i < pageEntity.getQuestion().getResult().size(); i++) { String result = pageEntity.getQuestion().getResult().get(i); PaperStructure question = structureService.getPaperStructure(paper.getExamId(), paper.getCardNumber(), spe.getPaperNumber(), pageEntity.getPageIndex(), i + 1, OmrField.QUESTION); String newStr = result.replace(OMR_SUSPECT, ""); if (question.getSingle() && result != null && newStr.length() > 1) { OmrTaskItem item = new OmrTaskItem(); item.setIndex(i + 1); item.setField(OmrField.QUESTION); item.setOmrResult(result); items.add(item); } } } } } } if (retList.size() == 0) { return null; } List result = new ArrayList<>(); for (OmrTaskDto dto : retList) { for (OmrTaskPageDto pageDto : dto.getPage()) { if (multi_blank) { pageDto.getItems().addAll(pageDto.getPageMultiBlankItems()); } if (single_blank) { pageDto.getItems().addAll(pageDto.getPageSingleBlankItems()); } if (pageDto.getItems().size() > 0) { OmrTaskPage page = new OmrTaskPage(); page.setItems(pageDto.getItems()); page.setIndex(pageDto.getPageIndex()); dto.getTask().getPages().add(page); } } if (dto.getTask().getPages().size() > 0) { result.add(dto.getTask()); } } return result; } @Transactional @Override public void saveTask(OmrGroupEntity group, Long studentId) { List list = this.buildTask(group, studentId); if (list != null && !list.isEmpty()) { this.saveBatch(list); groupService.updateTotalCount(group.getId()); } } private boolean isAllBlank(List paperIds) { for (StudentPaperEntity spe : paperIds) { PaperEntity paper = paperService.getById(spe.getPaperId()); if (paper == null) { throw new ParameterException("paper不存在"); } List pageList = pageService.listByPaperId(spe.getPaperId()); for (PaperPageEntity pageEntity : pageList) { for (int i = 0; pageEntity.getQuestion() != null && pageEntity.getQuestion().getResult() != null && i < pageEntity.getQuestion().getResult().size(); i++) { String result = pageEntity.getQuestion().getResult().get(i); if (!"#".equals(result)) { return false; } } } } return true; } @Override public TaskVo getTask(Long groupId, String account) { return findWaitingTask(groupId, account, false); } private TaskVo findWaitingTask(Long groupId, String account, boolean isArbitrate) { int retry = 0; TaskVo task = null; while (task == null) { List list = this.findUnMarked(groupId, retry * 20, 20, isArbitrate ? TaskStatus.WAIT_ARBITRATE : TaskStatus.WAITING); if (list.isEmpty()) { break; } for (OmrTaskEntity t : list) { if (this.apply(t, account)) { task = toTaskVo(t, isArbitrate, false); break; } } if (task == null) { retry++; } } if (task == null) { throw NotFoundExceptions.NO_OMR_ARBITRATE_TASK; } return task; } private TaskVo toTaskVo(OmrTaskEntity task, boolean isArbitrate, boolean history) { TaskVo vo = new TaskVo(); StudentEntity student = studentService.getById(task.getStudentId()); vo.setCardNumber(task.getCardNumber()); vo.setId(task.getId()); vo.setName(student.getName()); vo.setPaperId(task.getPaperId()); vo.setPaperNumber(task.getPaperNumber()); vo.setSubjectCode(student.getSubjectCode()); SubjectEntity subject = subjectService.findByExamIdAndCode(student.getExamId(), student.getSubjectCode()); vo.setSubjectName(subject.getName()); List pages = new ArrayList<>(); for (OmrTaskPage taskPage : task.getPages()) { TaskPageVo page = new TaskPageVo(); Map> question = new HashMap<>(); Map> selective = new HashMap<>(); for (OmrTaskItem item : taskPage.getItems()) { if (OmrField.ABSENT.equals(item.getField())) { page.setAbsent(getBooleanItem(isArbitrate, item, history)); } if (OmrField.BREACH.equals(item.getField())) { page.setBreach(getBooleanItem(isArbitrate, item, history)); } if (OmrField.PAPER_TYPE.equals(item.getField())) { page.setPaperType(getStringItem(isArbitrate, item, history)); } if (OmrField.QUESTION.equals(item.getField())) { List content = getStringItem(isArbitrate, item, history); if (content != null) { question.put(item.getIndex(), content); } } if (OmrField.SELECTIVE.equals(item.getField())) { List content = getStringItem(isArbitrate, item, history); if (content != null) { selective.put(item.getIndex(), content); } } } if (question.size() > 0) { page.setQuestion(question); } if (selective.size() > 0) { page.setSelective(selective); } // 有需要仲裁的数据才返回结构 if (page.getAbsent() != null || page.getBreach() != null || page.getPaperType() != null || page.getQuestion() != null || page.getSelective() != null) { page.setIndex(taskPage.getIndex()); PaperPageEntity p = pageService.findPaperIdAndIndex(task.getPaperId(), taskPage.getIndex()); page.setRecogData(p.getRecogData()); page.setUri(p.getSheetPath()); pages.add(page); } } vo.setPages(pages); return vo; } private List getStringItem(boolean isArbitrate, OmrTaskItem item, boolean history) { List value = new ArrayList<>(); if (isArbitrate) { if (item.getFirstResult().equals(item.getSecondResult())) { return null; } value.add(item.getFirstResult()); value.add(item.getSecondResult()); if (history) { value.add(item.getArbitrateResult()); } } else { value.add(item.getOmrResult()); if (history && item.getFirstResult() != null && item.getSecondResult() == null) { value.add(item.getFirstResult()); } else if (history && item.getSecondResult() != null) { value.add(item.getSecondResult()); } } return value; } private List getBooleanItem(boolean isArbitrate, OmrTaskItem item, boolean history) { List value = new ArrayList<>(); if (isArbitrate) { if (item.getFirstResult().equals(item.getSecondResult())) { return null; } value.add(Boolean.valueOf(item.getFirstResult())); value.add(Boolean.valueOf(item.getSecondResult())); if (history) { value.add(Boolean.valueOf(item.getArbitrateResult())); } } else { value.add(Boolean.valueOf(item.getOmrResult())); if (history && item.getFirstResult() != null && item.getSecondResult() == null) { value.add(Boolean.valueOf(item.getFirstResult())); } else if (history && item.getSecondResult() != null) { value.add(Boolean.valueOf(item.getSecondResult())); } } return value; } @Transactional @Override public TaskSaveVo submitTask(@NotNull TaskResultVo result, @NotNull User user) { OmrTaskEntity task = this.getById(result.getId()); if (task == null) { throw new ParameterException("任务不存在"); } // if (TaskStatus.PROCESSED.equals(task.getStatus())) { // throw new ParameterException("任务已处理"); // } if (TaskStatus.ARBITRATED.equals(task.getStatus()) && !task.getDevice().equalsIgnoreCase(user.getAccount())) { throw new ParameterException("任务非本人领取"); } if (TaskStatus.WAITING.equals(task.getStatus()) && !hasApplied(task, user.getAccount())) { throw new ParameterException("任务非本人领取"); } concurrentService.getReadWriteLock(LockType.OMR_GROUP + "-" + task.getGroupId()).readLock().lock(); concurrentService.getReadWriteLock(LockType.STUDENT + "-" + task.getStudentId()).writeLock().lock(); // 仲裁任务提交 if (TaskStatus.WAIT_ARBITRATE.equals(task.getStatus()) || TaskStatus.ARBITRATED.equals(task.getStatus())) { for (OmrTaskPage page : task.getPages()) { TaskResultPageVo pageVo = result.findPage(page.getIndex()); if (pageVo == null) { continue; } for (OmrTaskItem item : page.getItems()) { Object content = null; switch (item.getField()) { case ABSENT: content = pageVo.getAbsent(); break; case BREACH: content = pageVo.getBreach(); break; case PAPER_TYPE: content = pageVo.getPaperType(); break; case QUESTION: content = pageVo.getQuestion() != null ? pageVo.getQuestion().get(item.getIndex()) : null; break; case SELECTIVE: content = pageVo.getSelective() != null ? pageVo.getSelective().get(item.getIndex()) : null; break; } if (content != null) { item.setArbitrateResult(content.toString()); } } } task.setStatus(TaskStatus.ARBITRATED); } // 正常任务提交 else { OmrGroupEntity group = groupService.getById(task.getGroupId()); boolean needArbitrate = false; for (OmrTaskPage page : task.getPages()) { TaskResultPageVo pageVo = result.findPage(page.getIndex()); if (pageVo == null) { throw new ParameterException("page[" + page.getIndex() + "]不存在"); } for (OmrTaskItem item : page.getItems()) { if (OmrField.ABSENT.equals(item.getField())) { if (pageVo.getAbsent() == null) { throw new ParameterException("page[" + page.getIndex() + "].absent不存在"); } needArbitrate = setResult(group, item, pageVo.getAbsent().toString()) || needArbitrate; } if (OmrField.BREACH.equals(item.getField())) { if (pageVo.getBreach() == null) { throw new ParameterException("page[" + page.getIndex() + "].breach不存在"); } needArbitrate = setResult(group, item, pageVo.getBreach().toString()) || needArbitrate; } if (OmrField.PAPER_TYPE.equals(item.getField())) { if (pageVo.getPaperType() == null) { throw new ParameterException("page[" + page.getIndex() + "].paperType不存在"); } needArbitrate = setResult(group, item, pageVo.getPaperType()) || needArbitrate; } if (OmrField.QUESTION.equals(item.getField())) { String content = pageVo.getQuestion() != null ? pageVo.getQuestion().get(item.getIndex()) : null; if (content == null) { throw new ParameterException( "page[" + page.getIndex() + "].question[" + item.getIndex() + "]不存在"); } needArbitrate = setResult(group, item, content) || needArbitrate; } if (OmrField.SELECTIVE.equals(item.getField())) { String content = pageVo.getSelective() != null ? pageVo.getSelective().get(item.getIndex()) : null; if (content == null) { throw new ParameterException( "page[" + page.getIndex() + "].selective[" + item.getIndex() + "]不存在"); } needArbitrate = setResult(group, item, content) || needArbitrate; } } } if (needArbitrate) { task.setStatus(TaskStatus.WAIT_ARBITRATE); } else if (Stage.SECOND.equals(group.getStage()) && task.getDevice() == null) { task.setStatus(TaskStatus.WAITING); } else { task.setStatus(TaskStatus.PROCESSED); } } updatePaperResult(result, task.getPaperId(), user); task.setDevice(user.getAccount()); task.setUpdateTime(System.currentTimeMillis()); this.saveOrUpdate(task); this.releaseByTask(task); concurrentService.getReadWriteLock(LockType.STUDENT + "-" + task.getStudentId()).writeLock().unlock(); concurrentService.getReadWriteLock(LockType.OMR_GROUP + "-" + task.getGroupId()).readLock().unlock(); TaskSaveVo vo = new TaskSaveVo(); vo.setId(result.getId()); vo.setUpdateTime(System.currentTimeMillis()); vo.setStatus( this.getStatus(task.getGroupId(), task.getStatus().equals(TaskStatus.ARBITRATED), user.getAccount())); vo.setArbitrate(TaskStatus.WAIT_ARBITRATE.equals(task.getStatus())); return vo; } private void updatePaperResult(TaskResultVo result, Long paperId, User user) { PaperEntity paper = paperService.getById(paperId); StudentPaperEntity sp = studentPaperService.findByPaperId(paperId); if (paper == null) { throw new ParameterException("未找到paper信息"); } if (sp == null) { throw new ParameterException("paper未绑定考生"); } List pages = pageService.listByPaperId(paperId); if (CollectionUtils.isEmpty(pages)) { throw new ParameterException("未找到page信息"); } for (PaperPageEntity page : pages) { TaskResultPageVo vo = result.findPage(page.getPageIndex()); if (vo != null) { vo.update(page); } } paperService.savePaperAndPages(paper, pages); studentService.updateStudentByPaper(user, sp.getStudentId(), false); } private boolean setResult(OmrGroupEntity group, OmrTaskItem item, String result) { if (Stage.FIRST.equals(group.getStage()) || item.getFirstResult() == null) { item.setFirstResult(result); return false; } else { item.setSecondResult(result); return !item.getSecondResult().equals(item.getFirstResult()); } } @Override public TaskVo getArbitrateTask(Long groupId, String account) { return findWaitingTask(groupId, account, true); } @Override public TaskStatusVo getStatus(Long groupId, Boolean isArbitrate, String account) { TaskStatusVo status = new TaskStatusVo(); if (isArbitrate) { status.setFinishCount(this.getCountByGroupAndStatusAndDevice(groupId, account, TaskStatus.ARBITRATED)); status.setTodoCount(this.getCountByGroupAndStatus(groupId, TaskStatus.WAIT_ARBITRATE)); } else { status.setFinishCount(this.getCountByGroupAndStatusAndDevice(groupId, account, TaskStatus.PROCESSED)); status.setTodoCount(this.getCountByGroupAndStatus(groupId, TaskStatus.WAITING)); } return status; } @Override public boolean apply(OmrTaskEntity t, String account) { TaskLock taskLock = TaskLockUtil.getOmrTask(t.getGroupId().toString()); boolean lock = taskLock.add(t.getId(), account); // 上锁失败直接返回 if (!lock) { return false; } // 重复校验任务状态 if (t.getStatus().equals(TaskStatus.WAITING) || t.getStatus().equals(TaskStatus.WAIT_ARBITRATE)) { return true; } else { taskLock.remove(t.getId()); return false; } } @Override public void releaseByUser(Long groupId, String account) { TaskLock taskLock = TaskLockUtil.getOmrTask(groupId.toString()); taskLock.clear(account); } @Override public void releaseByTask(OmrTaskEntity t) { TaskLock taskLock = TaskLockUtil.getOmrTask(t.getGroupId().toString()); taskLock.remove(t.getId()); } @Override public boolean hasApplied(OmrTaskEntity t, String account) { TaskLock taskLock = TaskLockUtil.getOmrTask(t.getGroupId().toString()); return taskLock.exist(t.getId(), account); } @Override public List findUnMarked(Long groupId, int pageNumber, int pageSize, TaskStatus status) { return this.baseMapper.findUnMarked(groupId, pageNumber, pageSize, status); } @Override public OmrTaskEntity getByPaperId(Long groupId, Long paperId) { QueryWrapper wrapper = new QueryWrapper<>(); LambdaQueryWrapper lw = wrapper.lambda(); lw.eq(OmrTaskEntity::getGroupId, groupId); lw.eq(OmrTaskEntity::getPaperId, paperId); return baseMapper.selectOne(wrapper); } @Override public int getCountByExam(Long examId) { QueryWrapper wrapper = new QueryWrapper<>(); LambdaQueryWrapper lw = wrapper.lambda(); lw.eq(OmrTaskEntity::getExamId, examId); return this.count(wrapper); } @Transactional @Override public void deleteByStudentIdAndGroupId(Long groupId, Long studentId) { QueryWrapper wrapper = new QueryWrapper<>(); LambdaQueryWrapper lw = wrapper.lambda(); lw.eq(OmrTaskEntity::getStudentId, studentId); lw.eq(OmrTaskEntity::getGroupId, groupId); this.remove(lw); groupService.updateTotalCount(groupId); } @Transactional @Override public void updateStudentId(Long studentId, Long paperId) { UpdateWrapper wrapper = new UpdateWrapper<>(); LambdaUpdateWrapper lw = wrapper.lambda(); lw.set(OmrTaskEntity::getStudentId, studentId); lw.eq(OmrTaskEntity::getPaperId, paperId); this.update(wrapper); } @Override public TaskVo history(Long groupId, Long taskId, String account, Boolean next) { return getHistory(groupId, taskId, account, next, false); } private TaskVo getHistory(Long groupId, Long taskId, String account, Boolean next, boolean isArbitrate) { OmrTaskEntity cur = null; if (taskId != null) { cur = this.getById(taskId); } QueryWrapper wrapper = new QueryWrapper<>(); LambdaQueryWrapper lw = wrapper.lambda(); lw.eq(OmrTaskEntity::getGroupId, groupId); lw.eq(OmrTaskEntity::getDevice, account); if (isArbitrate) { lw.eq(OmrTaskEntity::getStatus, TaskStatus.ARBITRATED); } else { lw.eq(OmrTaskEntity::getStatus, TaskStatus.PROCESSED); } if (next != null && next) { if (taskId != null) { lw.gt(OmrTaskEntity::getId, cur.getId()); } lw.orderByAsc(OmrTaskEntity::getId); } else { if (taskId != null) { lw.lt(OmrTaskEntity::getId, cur.getId()); } lw.orderByDesc(OmrTaskEntity::getId); } wrapper.last("LIMIT 1"); OmrTaskEntity task = this.baseMapper.selectOne(wrapper); if (task == null) { if (isArbitrate) { throw NotFoundExceptions.NO_OMR_ARBITRATE_TASK; } else { throw NotFoundExceptions.NO_OMR_TASK; } } return toTaskVo(task, isArbitrate, true); } @Override public TaskVo getArbitrateHistory(Long groupId, Long taskId, String account, Boolean next) { return getHistory(groupId, taskId, account, next, true); } @Override public OmrTaskOverview countByExamIdAndFixed(Long examId, Boolean fixed) { return baseMapper.countByExamIdAndFixed(examId, fixed); } @Override public List findByGroupIdAndStudentId(Long groupId, Long studentId) { QueryWrapper wrapper = new QueryWrapper<>(); LambdaQueryWrapper lw = wrapper.lambda(); lw.eq(OmrTaskEntity::getGroupId, groupId); lw.eq(OmrTaskEntity::getStudentId, studentId); return baseMapper.selectList(wrapper); } }