package cn.com.qmth.scancentral.service.impl; import cn.com.qmth.scancentral.dao.OmrGroupDao; import cn.com.qmth.scancentral.entity.OmrGroupEntity; import cn.com.qmth.scancentral.entity.OmrTaskEntity; import cn.com.qmth.scancentral.entity.SubjectEntity; import cn.com.qmth.scancentral.enums.ConditionType; import cn.com.qmth.scancentral.enums.LockType; import cn.com.qmth.scancentral.enums.Stage; import cn.com.qmth.scancentral.enums.TaskStatus; import cn.com.qmth.scancentral.model.OmrCondition; import cn.com.qmth.scancentral.service.OmrGroupService; import cn.com.qmth.scancentral.service.OmrTaskService; import cn.com.qmth.scancentral.service.StudentPaperService; import cn.com.qmth.scancentral.service.SubjectService; import cn.com.qmth.scancentral.util.BatchSetDataUtil; import cn.com.qmth.scancentral.util.PageUtil; import cn.com.qmth.scancentral.vo.OmrConditionVo; import cn.com.qmth.scancentral.vo.OmrGroupUpdateVo; import cn.com.qmth.scancentral.vo.OmrGroupVo; import cn.com.qmth.scancentral.vo.omr.OmrGroupQuery; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.qmth.boot.core.collection.PageResult; import com.qmth.boot.core.concurrent.service.ConcurrentService; import com.qmth.boot.core.exception.ParameterException; import com.qmth.boot.core.exception.ReentrantException; import com.qmth.boot.core.exception.StatusException; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; @Service public class OmrGroupServiceImpl extends ServiceImpl implements OmrGroupService { protected static Logger log = LoggerFactory.getLogger(OmrGroupService.class); @Autowired private ConcurrentService concurrentService; @Autowired private OmrTaskService taskService; @Autowired private StudentPaperService studentPaperService; @Autowired private SubjectService subjectService; @Transactional @Override public void deleteById(Long id) { taskService.deleteByGroupId(id); this.removeById(id); } @Transactional @Override public void resetById(Long id) { OmrGroupEntity group = this.getById(id); if (group == null) { throw new ParameterException("分组不存在"); } taskService.resetByGroup(group); } @Override public void buildTaskById(Long groupId) { OmrGroupEntity group = this.getById(groupId); long start = System.currentTimeMillis(); List studentIds = studentPaperService.findStudentIdByExamId(group.getExamId(), group.getSubjectCode()); long end = System.currentTimeMillis(); if (CollectionUtils.isEmpty(studentIds)) { log.info("OmrGroup[" + groupId + "] get studentIds finish | time cost(s):" + ((end - start) / 1000) + " | count:0"); return; } log.info("OmrGroup[" + groupId + "] get studentIds finish | time cost(s):" + ((end - start) / 1000) + " | count:" + studentIds.size()); new BatchSetDataUtil() { @Override protected void setData(List dataList) { buildTaskByStudent(group, dataList); } }.setDataForBatch(studentIds, 1000); } private void buildTaskByStudent(OmrGroupEntity group, List studentIds) { if (CollectionUtils.isEmpty(studentIds)) { return; } List saveList = new ArrayList(); for (Long studentId : studentIds) { try { concurrentService.getLock(LockType.STUDENT + "-" + studentId).lock(); List task = taskService.buildTask(group, studentId); if (task != null && !task.isEmpty()) { saveList.addAll(task); } } finally { concurrentService.getLock(LockType.STUDENT + "-" + studentId).unlock(); } } taskService.saveBatch(saveList); this.updateTotalCount(group.getId()); } @Override public PageResult list(OmrGroupQuery query) { if (query.getExamId() == null) { throw new ParameterException("examId不能为空"); } IPage page = baseMapper.queryPage(new Page<>(query.getPageNumber(), query.getPageSize()), query); for (OmrGroupVo omrGroup : page.getRecords()) { omrGroup.setBuilding( !concurrentService.getSemaphore(LockType.OMR_GROUP_BUILD + "-" + omrGroup.getId()).isAvailable()); omrGroup.setDeleting( !concurrentService.getSemaphore(LockType.OMR_GROUP_DELETE + "-" + omrGroup.getId()).isAvailable()); omrGroup.setReseting( !concurrentService.getSemaphore(LockType.OMR_GROUP_RESET + "-" + omrGroup.getId()).isAvailable()); omrGroup.setFinishCount( taskService.getCountByGroupAndStatus(omrGroup.getId(), TaskStatus.PROCESSED)); omrGroup.setUnarbitrateCount( taskService.getCountByGroupAndStatus(omrGroup.getId(), TaskStatus.WAIT_ARBITRATE)); omrGroup.setArbitratedCount( taskService.getCountByGroupAndStatus(omrGroup.getId(), TaskStatus.ARBITRATED)); } return PageUtil.of(page); } @Transactional @Override public void updateStage(Long id, Long userId) { OmrGroupEntity group = this.getById(id); if (group == null) { throw new ParameterException("分组不存在"); } if (!Stage.FIRST.equals(group.getStage())) { throw new StatusException("分组不在第一阶段,无法切换"); } if (group.getTotalCount() == 0) { throw new StatusException("分组下没有任务,无法切换"); } Integer finishCount = taskService.getCountByGroupAndStatus(id, TaskStatus.PROCESSED, TaskStatus.ARBITRATED); if (group.getTotalCount() - finishCount != 0) { throw new StatusException("识别对照任务未完成,无法切换"); } group.setStage(Stage.SECOND); group.setUpdaterId(userId); group.setUpdateTime(System.currentTimeMillis()); this.saveOrUpdate(group); taskService.waitingByGroupToggle(id); } @Override public void save(OmrGroupUpdateVo vo) { if (vo.getExamId() == null) { throw new ParameterException("examId不能为空"); } if (StringUtils.isBlank(vo.getSubjectCode())) { throw new ParameterException("subjectCode不能为空"); } List conditions = vo.getConditionList(); if (CollectionUtils.isEmpty(conditions)) { throw new ParameterException("识别对照条件不能为空"); } for (OmrCondition omrCondition : conditions) { // if (ConditionType.FILL_SUSPECT.equals(omrCondition.getCode())) { // throw new ParameterException("识别对照条件不能重复"); // } if (ConditionType.QUESTION_SINGLE_BLANK.equals(omrCondition.getCode()) || ConditionType.QUESTION_MULTI_BLANK.equals(omrCondition.getCode()) || ConditionType.SELECTIVE_EXCEED.equals(omrCondition.getCode()) || ConditionType.SELECTIVE_BLANK.equals(omrCondition.getCode())) { if (omrCondition.getValue() == null) { throw new ParameterException("参数不能为空"); } if (omrCondition.getValue() < 0) { throw new ParameterException("参数不能小于0"); } } } this.checkOmrCondition(vo.getId(), vo.getExamId(), vo.getSubjectCode(), conditions); if (vo.getId() != null) { OmrGroupEntity group = this.getById(vo.getId()); if (group.getFixed()) { throw new ParameterException("默认分组不能修改"); } if (group.getTotalCount() != null && group.getTotalCount() > 0) { throw new ParameterException("已生成任务的分组不能修改"); } if (concurrentService.getLock(LockType.OMR_GROUP + "-" + vo.getId()).tryLock()) { group.setConditions(conditions); group.setUpdaterId(vo.getUserId()); group.setUpdateTime(System.currentTimeMillis()); this.saveOrUpdate(group); log.info("修改识别对照任务分组!examId:{} subjectCode:{} id:{}", group.getExamId(), group.getSubjectCode(), group.getId()); concurrentService.getLock(LockType.OMR_GROUP + "-" + vo.getId()).unlock(); } else { throw new ReentrantException("该分组数据操作繁忙,请稍后重试"); } } else { OmrGroupEntity group = new OmrGroupEntity(); group.setExamId(vo.getExamId()); group.setSubjectCode(vo.getSubjectCode()); group.setConditions(conditions); group.setFixed(false); group.setStage(Stage.FIRST); group.setTotalCount(0); group.setCreatorId(vo.getUserId()); group.setUpdaterId(vo.getUserId()); group.setCreateTime(System.currentTimeMillis()); group.setUpdateTime(System.currentTimeMillis()); this.save(group); log.info("新增识别对照任务分组!examId:{} subjectCode:{} id:{}", group.getExamId(), group.getSubjectCode(), group.getId()); } } @Override public List findByExamIdAndSubjectCodeAndFixed(Long examId, String subjectCode, Boolean fixed) { QueryWrapper wrapper = new QueryWrapper<>(); LambdaQueryWrapper lw = wrapper.lambda(); lw.eq(OmrGroupEntity::getExamId, examId); lw.eq(OmrGroupEntity::getSubjectCode, subjectCode); lw.eq(OmrGroupEntity::getFixed, fixed); return baseMapper.selectList(wrapper); } private void checkOmrCondition(Long id, Long examId, String subjectCode, List conditions) { List list = findByExamIdAndSubjectCode(examId, subjectCode); if (CollectionUtils.isEmpty(list)) { return; } Set codes = new HashSet<>(); for (OmrCondition oc : conditions) { codes.add(oc.getCode().name()); } for (OmrGroupEntity g : list) { for (OmrCondition oc : g.getConditions()) { if (codes.contains(oc.getCode().name()) && (id == null || g.getId().longValue() != id.longValue())) { throw new ParameterException("已存在识别对照条件"); } } } } private List findByExamIdAndSubjectCode(Long examId, String subjectCode) { LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); wrapper.eq(OmrGroupEntity::getExamId, examId); wrapper.eq(OmrGroupEntity::getSubjectCode, subjectCode); return baseMapper.selectList(wrapper); } @Transactional @Override public void updateTotalCount(Long id) { if (id == null) { throw new ParameterException("Id不能为空"); } baseMapper.updateTotalCount(id); } @Transactional @Override public void updateTotalCount(Long examId, String subjectCode) { List list = this.findByExamIdAndSubjectCode(examId, subjectCode); for (OmrGroupEntity omrGroupEntity : list) { this.updateTotalCount(omrGroupEntity.getId()); } } @Override public void addFixOmrCondition(Long userId, Long examId, String subjectCode) { if (examId == null) { throw new ParameterException("examId不能为空"); } if (StringUtils.isBlank(subjectCode)) { throw new ParameterException("subjectCode不能为空"); } OmrGroupEntity group = new OmrGroupEntity(); group.setExamId(examId); group.setSubjectCode(subjectCode); List conditions = new ArrayList<>(); OmrCondition omrCondition = new OmrCondition(); omrCondition.setCode(ConditionType.FILL_SUSPECT); conditions.add(omrCondition); group.setConditions(conditions); group.setFixed(true); group.setStage(Stage.FIRST); group.setTotalCount(0); group.setCreatorId(userId); group.setUpdaterId(userId); group.setCreateTime(System.currentTimeMillis()); group.setUpdateTime(System.currentTimeMillis()); this.save(group); } @Override public List listByExamIdAndSubjectCode(Long examId, String subjectCode) { if (examId == null) { throw new ParameterException("examId不能为空"); } if (StringUtils.isBlank(subjectCode)) { throw new ParameterException("subjectCode不能为空"); } SubjectEntity subject = subjectService.findByExamIdAndCode(examId, subjectCode); if (subject == null) { throw new ParameterException("科目不存在"); } LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); wrapper.eq(OmrGroupEntity::getExamId, examId); wrapper.eq(OmrGroupEntity::getSubjectCode, subjectCode); List list = this.list(wrapper); List omrGroups = new ArrayList<>(); for (OmrGroupEntity omrGroup : list) { OmrGroupVo groupVo = new OmrGroupVo(); groupVo.setId(omrGroup.getId()); groupVo.setSubjectCode(omrGroup.getSubjectCode()); groupVo.setSubjectName(subject.getName()); List conditions = new ArrayList<>(); if (CollectionUtils.isNotEmpty(omrGroup.getConditions())) { for (OmrCondition c : omrGroup.getConditions()) { conditions.add(new OmrConditionVo(c)); } } groupVo.setConditions(conditions); groupVo.setStage(omrGroup.getStage()); groupVo.setFixed(omrGroup.getFixed()); omrGroups.add(groupVo); } return omrGroups; } }