OmrGroupServiceImpl.java 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366
  1. package cn.com.qmth.scancentral.service.impl;
  2. import cn.com.qmth.scancentral.dao.OmrGroupDao;
  3. import cn.com.qmth.scancentral.entity.OmrGroupEntity;
  4. import cn.com.qmth.scancentral.entity.OmrTaskEntity;
  5. import cn.com.qmth.scancentral.entity.SubjectEntity;
  6. import cn.com.qmth.scancentral.enums.ConditionType;
  7. import cn.com.qmth.scancentral.enums.LockType;
  8. import cn.com.qmth.scancentral.enums.Stage;
  9. import cn.com.qmth.scancentral.enums.TaskStatus;
  10. import cn.com.qmth.scancentral.model.OmrCondition;
  11. import cn.com.qmth.scancentral.service.OmrGroupService;
  12. import cn.com.qmth.scancentral.service.OmrTaskService;
  13. import cn.com.qmth.scancentral.service.StudentPaperService;
  14. import cn.com.qmth.scancentral.service.SubjectService;
  15. import cn.com.qmth.scancentral.util.BatchSetDataUtil;
  16. import cn.com.qmth.scancentral.util.PageUtil;
  17. import cn.com.qmth.scancentral.vo.OmrConditionVo;
  18. import cn.com.qmth.scancentral.vo.OmrGroupUpdateVo;
  19. import cn.com.qmth.scancentral.vo.OmrGroupVo;
  20. import cn.com.qmth.scancentral.vo.omr.OmrGroupQuery;
  21. import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
  22. import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
  23. import com.baomidou.mybatisplus.core.metadata.IPage;
  24. import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
  25. import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
  26. import com.qmth.boot.core.collection.PageResult;
  27. import com.qmth.boot.core.concurrent.service.ConcurrentService;
  28. import com.qmth.boot.core.exception.ParameterException;
  29. import com.qmth.boot.core.exception.ReentrantException;
  30. import com.qmth.boot.core.exception.StatusException;
  31. import org.apache.commons.collections4.CollectionUtils;
  32. import org.apache.commons.lang3.StringUtils;
  33. import org.slf4j.Logger;
  34. import org.slf4j.LoggerFactory;
  35. import org.springframework.beans.factory.annotation.Autowired;
  36. import org.springframework.stereotype.Service;
  37. import org.springframework.transaction.annotation.Transactional;
  38. import java.util.ArrayList;
  39. import java.util.HashSet;
  40. import java.util.List;
  41. import java.util.Set;
  42. @Service
  43. public class OmrGroupServiceImpl extends ServiceImpl<OmrGroupDao, OmrGroupEntity> implements OmrGroupService {
  44. protected static Logger log = LoggerFactory.getLogger(OmrGroupService.class);
  45. @Autowired
  46. private ConcurrentService concurrentService;
  47. @Autowired
  48. private OmrTaskService taskService;
  49. @Autowired
  50. private StudentPaperService studentPaperService;
  51. @Autowired
  52. private SubjectService subjectService;
  53. @Transactional
  54. @Override
  55. public void deleteById(Long id) {
  56. taskService.deleteByGroupId(id);
  57. this.removeById(id);
  58. }
  59. @Transactional
  60. @Override
  61. public void resetById(Long id) {
  62. OmrGroupEntity group = this.getById(id);
  63. if (group == null) {
  64. throw new ParameterException("分组不存在");
  65. }
  66. taskService.resetByGroup(group);
  67. }
  68. @Override
  69. public void buildTaskById(Long groupId) {
  70. OmrGroupEntity group = this.getById(groupId);
  71. long start = System.currentTimeMillis();
  72. List<Long> studentIds = studentPaperService.findStudentIdByExamId(group.getExamId(), group.getSubjectCode());
  73. long end = System.currentTimeMillis();
  74. if (CollectionUtils.isEmpty(studentIds)) {
  75. log.info("OmrGroup[" + groupId + "] get studentIds finish | time cost(s):" + ((end - start) / 1000)
  76. + " | count:0");
  77. return;
  78. }
  79. log.info("OmrGroup[" + groupId + "] get studentIds finish | time cost(s):" + ((end - start) / 1000)
  80. + " | count:" + studentIds.size());
  81. new BatchSetDataUtil<Long>() {
  82. @Override
  83. protected void setData(List<Long> dataList) {
  84. buildTaskByStudent(group, dataList);
  85. }
  86. }.setDataForBatch(studentIds, 1000);
  87. }
  88. private void buildTaskByStudent(OmrGroupEntity group, List<Long> studentIds) {
  89. if (CollectionUtils.isEmpty(studentIds)) {
  90. return;
  91. }
  92. List<OmrTaskEntity> saveList = new ArrayList<OmrTaskEntity>();
  93. for (Long studentId : studentIds) {
  94. try {
  95. concurrentService.getLock(LockType.STUDENT + "-" + studentId).lock();
  96. List<OmrTaskEntity> task = taskService.buildTask(group, studentId);
  97. if (task != null && !task.isEmpty()) {
  98. saveList.addAll(task);
  99. }
  100. } finally {
  101. concurrentService.getLock(LockType.STUDENT + "-" + studentId).unlock();
  102. }
  103. }
  104. taskService.saveBatch(saveList);
  105. this.updateTotalCount(group.getId());
  106. }
  107. @Override
  108. public PageResult<OmrGroupVo> list(OmrGroupQuery query) {
  109. if (query.getExamId() == null) {
  110. throw new ParameterException("examId不能为空");
  111. }
  112. IPage<OmrGroupVo> page = baseMapper.queryPage(new Page<>(query.getPageNumber(), query.getPageSize()), query);
  113. for (OmrGroupVo omrGroup : page.getRecords()) {
  114. omrGroup.setBuilding(
  115. !concurrentService.getSemaphore(LockType.OMR_GROUP_BUILD + "-" + omrGroup.getId()).isAvailable());
  116. omrGroup.setDeleting(
  117. !concurrentService.getSemaphore(LockType.OMR_GROUP_DELETE + "-" + omrGroup.getId()).isAvailable());
  118. omrGroup.setReseting(
  119. !concurrentService.getSemaphore(LockType.OMR_GROUP_RESET + "-" + omrGroup.getId()).isAvailable());
  120. omrGroup.setFinishCount(
  121. taskService.getCountByGroupAndStatus(omrGroup.getId(), TaskStatus.PROCESSED));
  122. omrGroup.setUnarbitrateCount(
  123. taskService.getCountByGroupAndStatus(omrGroup.getId(), TaskStatus.WAIT_ARBITRATE));
  124. omrGroup.setArbitratedCount(
  125. taskService.getCountByGroupAndStatus(omrGroup.getId(), TaskStatus.ARBITRATED));
  126. }
  127. return PageUtil.of(page);
  128. }
  129. @Transactional
  130. @Override
  131. public void updateStage(Long id, Long userId) {
  132. OmrGroupEntity group = this.getById(id);
  133. if (group == null) {
  134. throw new ParameterException("分组不存在");
  135. }
  136. if (!Stage.FIRST.equals(group.getStage())) {
  137. throw new StatusException("分组不在第一阶段,无法切换");
  138. }
  139. if (group.getTotalCount() == 0) {
  140. throw new StatusException("分组下没有任务,无法切换");
  141. }
  142. Integer finishCount = taskService.getCountByGroupAndStatus(id, TaskStatus.PROCESSED,
  143. TaskStatus.ARBITRATED);
  144. if (group.getTotalCount() - finishCount != 0) {
  145. throw new StatusException("识别对照任务未完成,无法切换");
  146. }
  147. group.setStage(Stage.SECOND);
  148. group.setUpdaterId(userId);
  149. group.setUpdateTime(System.currentTimeMillis());
  150. this.saveOrUpdate(group);
  151. taskService.waitingByGroupToggle(id);
  152. }
  153. @Override
  154. public void save(OmrGroupUpdateVo vo) {
  155. if (vo.getExamId() == null) {
  156. throw new ParameterException("examId不能为空");
  157. }
  158. if (StringUtils.isBlank(vo.getSubjectCode())) {
  159. throw new ParameterException("subjectCode不能为空");
  160. }
  161. List<OmrCondition> conditions = vo.getConditionList();
  162. if (CollectionUtils.isEmpty(conditions)) {
  163. throw new ParameterException("识别对照条件不能为空");
  164. }
  165. for (OmrCondition omrCondition : conditions) {
  166. // if (ConditionType.FILL_SUSPECT.equals(omrCondition.getCode())) {
  167. // throw new ParameterException("识别对照条件不能重复");
  168. // }
  169. if (ConditionType.QUESTION_SINGLE_BLANK.equals(omrCondition.getCode())
  170. || ConditionType.QUESTION_MULTI_BLANK.equals(omrCondition.getCode())
  171. || ConditionType.SELECTIVE_EXCEED.equals(omrCondition.getCode())
  172. || ConditionType.SELECTIVE_BLANK.equals(omrCondition.getCode())) {
  173. if (omrCondition.getValue() == null) {
  174. throw new ParameterException("参数不能为空");
  175. }
  176. if (omrCondition.getValue() < 0) {
  177. throw new ParameterException("参数不能小于0");
  178. }
  179. }
  180. }
  181. this.checkOmrCondition(vo.getId(), vo.getExamId(), vo.getSubjectCode(), conditions);
  182. if (vo.getId() != null) {
  183. OmrGroupEntity group = this.getById(vo.getId());
  184. if (group.getFixed()) {
  185. throw new ParameterException("默认分组不能修改");
  186. }
  187. if (group.getTotalCount() != null && group.getTotalCount() > 0) {
  188. throw new ParameterException("已生成任务的分组不能修改");
  189. }
  190. if (concurrentService.getLock(LockType.OMR_GROUP + "-" + vo.getId()).tryLock()) {
  191. group.setConditions(conditions);
  192. group.setUpdaterId(vo.getUserId());
  193. group.setUpdateTime(System.currentTimeMillis());
  194. this.saveOrUpdate(group);
  195. log.info("修改识别对照任务分组!examId:{} subjectCode:{} id:{}", group.getExamId(), group.getSubjectCode(), group.getId());
  196. concurrentService.getLock(LockType.OMR_GROUP + "-" + vo.getId()).unlock();
  197. } else {
  198. throw new ReentrantException("该分组数据操作繁忙,请稍后重试");
  199. }
  200. } else {
  201. OmrGroupEntity group = new OmrGroupEntity();
  202. group.setExamId(vo.getExamId());
  203. group.setSubjectCode(vo.getSubjectCode());
  204. group.setConditions(conditions);
  205. group.setFixed(false);
  206. group.setStage(Stage.FIRST);
  207. group.setTotalCount(0);
  208. group.setCreatorId(vo.getUserId());
  209. group.setUpdaterId(vo.getUserId());
  210. group.setCreateTime(System.currentTimeMillis());
  211. group.setUpdateTime(System.currentTimeMillis());
  212. this.save(group);
  213. log.info("新增识别对照任务分组!examId:{} subjectCode:{} id:{}", group.getExamId(), group.getSubjectCode(), group.getId());
  214. }
  215. }
  216. @Override
  217. public List<OmrGroupEntity> findByExamIdAndSubjectCodeAndFixed(Long examId, String subjectCode, Boolean fixed) {
  218. QueryWrapper<OmrGroupEntity> wrapper = new QueryWrapper<>();
  219. LambdaQueryWrapper<OmrGroupEntity> lw = wrapper.lambda();
  220. lw.eq(OmrGroupEntity::getExamId, examId);
  221. lw.eq(OmrGroupEntity::getSubjectCode, subjectCode);
  222. lw.eq(OmrGroupEntity::getFixed, fixed);
  223. return baseMapper.selectList(wrapper);
  224. }
  225. private void checkOmrCondition(Long id, Long examId, String subjectCode, List<OmrCondition> conditions) {
  226. List<OmrGroupEntity> list = findByExamIdAndSubjectCode(examId, subjectCode);
  227. if (CollectionUtils.isEmpty(list)) {
  228. return;
  229. }
  230. Set<String> codes = new HashSet<>();
  231. for (OmrCondition oc : conditions) {
  232. codes.add(oc.getCode().name());
  233. }
  234. for (OmrGroupEntity g : list) {
  235. for (OmrCondition oc : g.getConditions()) {
  236. if (codes.contains(oc.getCode().name()) && (id == null || g.getId().longValue() != id.longValue())) {
  237. throw new ParameterException("已存在识别对照条件");
  238. }
  239. }
  240. }
  241. }
  242. private List<OmrGroupEntity> findByExamIdAndSubjectCode(Long examId, String subjectCode) {
  243. LambdaQueryWrapper<OmrGroupEntity> wrapper = new LambdaQueryWrapper<>();
  244. wrapper.eq(OmrGroupEntity::getExamId, examId);
  245. wrapper.eq(OmrGroupEntity::getSubjectCode, subjectCode);
  246. return baseMapper.selectList(wrapper);
  247. }
  248. @Transactional
  249. @Override
  250. public void updateTotalCount(Long id) {
  251. if (id == null) {
  252. throw new ParameterException("Id不能为空");
  253. }
  254. baseMapper.updateTotalCount(id);
  255. }
  256. @Transactional
  257. @Override
  258. public void updateTotalCount(Long examId, String subjectCode) {
  259. List<OmrGroupEntity> list = this.findByExamIdAndSubjectCode(examId, subjectCode);
  260. for (OmrGroupEntity omrGroupEntity : list) {
  261. this.updateTotalCount(omrGroupEntity.getId());
  262. }
  263. }
  264. @Override
  265. public void addFixOmrCondition(Long userId, Long examId, String subjectCode) {
  266. if (examId == null) {
  267. throw new ParameterException("examId不能为空");
  268. }
  269. if (StringUtils.isBlank(subjectCode)) {
  270. throw new ParameterException("subjectCode不能为空");
  271. }
  272. OmrGroupEntity group = new OmrGroupEntity();
  273. group.setExamId(examId);
  274. group.setSubjectCode(subjectCode);
  275. List<OmrCondition> conditions = new ArrayList<>();
  276. OmrCondition omrCondition = new OmrCondition();
  277. omrCondition.setCode(ConditionType.FILL_SUSPECT);
  278. conditions.add(omrCondition);
  279. group.setConditions(conditions);
  280. group.setFixed(true);
  281. group.setStage(Stage.FIRST);
  282. group.setTotalCount(0);
  283. group.setCreatorId(userId);
  284. group.setUpdaterId(userId);
  285. group.setCreateTime(System.currentTimeMillis());
  286. group.setUpdateTime(System.currentTimeMillis());
  287. this.save(group);
  288. }
  289. @Override
  290. public List<OmrGroupVo> listByExamIdAndSubjectCode(Long examId, String subjectCode) {
  291. if (examId == null) {
  292. throw new ParameterException("examId不能为空");
  293. }
  294. if (StringUtils.isBlank(subjectCode)) {
  295. throw new ParameterException("subjectCode不能为空");
  296. }
  297. SubjectEntity subject = subjectService.findByExamIdAndCode(examId, subjectCode);
  298. if (subject == null) {
  299. throw new ParameterException("科目不存在");
  300. }
  301. LambdaQueryWrapper<OmrGroupEntity> wrapper = new LambdaQueryWrapper<>();
  302. wrapper.eq(OmrGroupEntity::getExamId, examId);
  303. wrapper.eq(OmrGroupEntity::getSubjectCode, subjectCode);
  304. List<OmrGroupEntity> list = this.list(wrapper);
  305. List<OmrGroupVo> omrGroups = new ArrayList<>();
  306. for (OmrGroupEntity omrGroup : list) {
  307. OmrGroupVo groupVo = new OmrGroupVo();
  308. groupVo.setId(omrGroup.getId());
  309. groupVo.setSubjectCode(omrGroup.getSubjectCode());
  310. groupVo.setSubjectName(subject.getName());
  311. List<OmrConditionVo> conditions = new ArrayList<>();
  312. if (CollectionUtils.isNotEmpty(omrGroup.getConditions())) {
  313. for (OmrCondition c : omrGroup.getConditions()) {
  314. conditions.add(new OmrConditionVo(c));
  315. }
  316. }
  317. groupVo.setConditions(conditions);
  318. groupVo.setStage(omrGroup.getStage());
  319. groupVo.setFixed(omrGroup.getFixed());
  320. omrGroups.add(groupVo);
  321. }
  322. return omrGroups;
  323. }
  324. }