PaperServiceImpl.java 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760
  1. package cn.com.qmth.mps.service.impl;
  2. import java.io.IOException;
  3. import java.io.InputStream;
  4. import java.util.*;
  5. import java.util.stream.Collectors;
  6. import cn.com.qmth.mps.bean.*;
  7. import cn.com.qmth.mps.enums.ArbitrateMethod;
  8. import org.apache.commons.collections4.CollectionUtils;
  9. import org.apache.commons.lang3.StringUtils;
  10. import org.springframework.beans.BeanUtils;
  11. import org.springframework.beans.factory.annotation.Autowired;
  12. import org.springframework.dao.DuplicateKeyException;
  13. import org.springframework.stereotype.Service;
  14. import org.springframework.transaction.annotation.Transactional;
  15. import org.springframework.transaction.interceptor.TransactionAspectSupport;
  16. import org.springframework.web.multipart.MultipartFile;
  17. import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
  18. import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
  19. import com.baomidou.mybatisplus.core.metadata.IPage;
  20. import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
  21. import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
  22. import com.qmth.boot.core.collection.PageResult;
  23. import com.qmth.boot.core.exception.StatusException;
  24. import com.qmth.boot.tools.excel.ExcelReader;
  25. import com.qmth.boot.tools.excel.enums.ExcelType;
  26. import com.qmth.boot.tools.excel.model.DataMap;
  27. import cn.com.qmth.mps.dao.PaperDao;
  28. import cn.com.qmth.mps.entity.CourseEntity;
  29. import cn.com.qmth.mps.entity.ExamEntity;
  30. import cn.com.qmth.mps.entity.PaperEntity;
  31. import cn.com.qmth.mps.enums.ExamStatus;
  32. import cn.com.qmth.mps.enums.Role;
  33. import cn.com.qmth.mps.service.*;
  34. import cn.com.qmth.mps.util.BatchSetDataUtil;
  35. import cn.com.qmth.mps.util.Calculator;
  36. import cn.com.qmth.mps.util.PageUtil;
  37. import cn.com.qmth.mps.vo.exam.ExamPaperCountVo;
  38. import cn.com.qmth.mps.vo.paper.*;
  39. @Service
  40. public class PaperServiceImpl extends ServiceImpl<PaperDao, PaperEntity> implements PaperService {
  41. private static final String[] SUBJECT_EXCEL_HEADER = new String[] {"科目代码", "科目名称"};
  42. private static final String[] SUBJECT_STRUCT_EXCEL_HEADER = new String[] {"科目代码*","科目名称","大题名称*","题目昵称","大题号(只能用小写数字)*","小题号(只能用小写数字)*","小题满分*","间隔分*","评卷分组(只能用小写数字)*","图片序号(用英文逗号分割)","仲裁方式(0-分组,1-小题)","双评比例(0~1)","仲裁阀值","合分策略(1-平均,2-最高,3-最低)","评卷模式(common-普通,track-轨迹)","试评数量(0-跳过试评)","选做题数量"};
  43. @Autowired
  44. private ExamService examService;
  45. @Autowired
  46. private CourseService courseService;
  47. @Autowired
  48. private PaperGroupService paperGroupService;
  49. @Autowired
  50. private PaperDetailService paperDetailService;
  51. @Transactional
  52. @Override
  53. public List<String> importPaper(Long examId, User user, MultipartFile file) {
  54. ExamEntity exam = examService.getById(examId);
  55. if (exam == null) {
  56. throw new StatusException("未找到考试批次");
  57. }
  58. if(!ExamStatus.EDIT.equals(exam.getExamStatus())) {
  59. throw new StatusException("考试未开放上报,不能设置结构信息或分组信息");
  60. }
  61. if (!user.getRole().equals(Role.SUPER_ADMIN) && !user.getSchoolId().equals(exam.getSchoolId())) {
  62. throw new StatusException("没有权限");
  63. }
  64. InputStream inputStream = null;
  65. try {
  66. inputStream = file.getInputStream();
  67. ExcelReader reader=ExcelReader.create(ExcelType.XLSX, inputStream, 0);
  68. List<DataMap> lineList = reader.getDataMapList();
  69. if(!Arrays.equals(SUBJECT_EXCEL_HEADER,reader.getColumnNames())) {
  70. throw new StatusException("Excel表头错误");
  71. }
  72. if (CollectionUtils.isEmpty(lineList)) {
  73. throw new StatusException("Excel无内容");
  74. }
  75. if (1001 < lineList.size()) {
  76. throw new StatusException("数据行数不能超过1000");
  77. }
  78. List<String> failRecords = new ArrayList<>();
  79. List<PaperEntity> ret = new ArrayList<>();
  80. for (int i = 0; i < lineList.size(); i++) {
  81. DataMap line = lineList.get(i);
  82. StringBuilder msg = new StringBuilder();
  83. PaperEntity imp = new PaperEntity();
  84. imp.setTotalScore(0.0);
  85. imp.setObjectiveScore(0.0);
  86. imp.setSubjectiveScore(0.0);
  87. imp.setSchoolId(exam.getSchoolId());
  88. imp.setGroupFinish(false);
  89. imp.setStructFinish(false);
  90. imp.setExamId(examId);
  91. String code = trimAndNullIfBlank(line.get(SUBJECT_EXCEL_HEADER[0]));
  92. if (StringUtils.isBlank(code)) {
  93. msg.append(" 科目代码不能为空");
  94. } else if (code.length() > 50) {
  95. msg.append(" 科目代码不能超过50个字符");
  96. }
  97. String name = trimAndNullIfBlank(line.get(SUBJECT_EXCEL_HEADER[1]));
  98. if (StringUtils.isBlank(name)) {
  99. msg.append(" 科目名称不能为空");
  100. } else if (name.length() > 50) {
  101. msg.append(" 科目名称不能超过50个字符");
  102. }
  103. if (msg.length() == 0) {
  104. CourseEntity course = courseService.saveOrGet(exam.getSchoolId(), code, name);
  105. imp.setCourseId(course.getId());
  106. }
  107. if (msg.length() > 0) {
  108. failRecords.add(newError(i + 1, msg.toString()));
  109. } else {
  110. ret.add(imp);
  111. }
  112. }
  113. if (CollectionUtils.isNotEmpty(failRecords)) {
  114. TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
  115. return failRecords;
  116. }
  117. for (int i = 0; i < ret.size(); i++) {
  118. PaperEntity cur = ret.get(i);
  119. try {
  120. this.save(cur);
  121. } catch (DuplicateKeyException e) {
  122. // failRecords.add(newError(i + 1, "科目已存在"));
  123. } catch (Exception e) {
  124. failRecords.add(newError(i + 1, "系统异常"));
  125. log.error("科目导入系统异常", e);
  126. }
  127. }
  128. if (CollectionUtils.isNotEmpty(failRecords)) {
  129. TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
  130. }
  131. return failRecords;
  132. } catch (StatusException e) {
  133. throw e;
  134. } catch (Exception e) {
  135. throw new RuntimeException("系统错误", e);
  136. } finally {
  137. if (inputStream != null) {
  138. try {
  139. inputStream.close();
  140. } catch (IOException e) {
  141. }
  142. }
  143. }
  144. }
  145. private String trimAndNullIfBlank(String s) {
  146. if (StringUtils.isBlank(s)) {
  147. return null;
  148. }
  149. return s.trim();
  150. }
  151. private String newError(int lineNum, String msg) {
  152. return "第" + lineNum + "行" + msg;
  153. }
  154. @Override
  155. public List<ExamPaperCountVo> findPaperCount(List<Long> examIds) {
  156. return this.baseMapper.findPaperCount(examIds);
  157. }
  158. @Override
  159. public Integer findPaperCount(Long examId) {
  160. QueryWrapper<PaperEntity> wrapper = new QueryWrapper<>();
  161. LambdaQueryWrapper<PaperEntity> lw = wrapper.lambda();
  162. lw.eq(PaperEntity::getExamId, examId);
  163. return this.count(wrapper);
  164. }
  165. private PaperEntity findByExamAndCourse(Long examId, Long courseId) {
  166. QueryWrapper<PaperEntity> wrapper = new QueryWrapper<>();
  167. LambdaQueryWrapper<PaperEntity> lw = wrapper.lambda();
  168. lw.eq(PaperEntity::getExamId, examId);
  169. lw.eq(PaperEntity::getCourseId, courseId);
  170. return this.getOne(wrapper);
  171. }
  172. private PaperEntity saveOrGet(Long schoolId, Long examId, Long courseId) {
  173. PaperEntity ret = findByExamAndCourse(examId, courseId);
  174. if (ret != null) {
  175. return ret;
  176. }
  177. PaperEntity imp = new PaperEntity();
  178. imp.setTotalScore(0.0);
  179. imp.setObjectiveScore(0.0);
  180. imp.setSubjectiveScore(0.0);
  181. imp.setSchoolId(schoolId);
  182. imp.setGroupFinish(false);
  183. imp.setCourseId(courseId);
  184. imp.setExamId(examId);
  185. imp.setStructFinish(true);
  186. this.save(imp);
  187. return imp;
  188. }
  189. @Override
  190. public PageResult<PaperVo> page(PaperQuery query, User user) {
  191. if (query.getSchoolId() == null) {
  192. throw new StatusException("学校不能为空");
  193. }
  194. if (!user.getRole().equals(Role.SUPER_ADMIN) && !user.getSchoolId().equals(query.getSchoolId())) {
  195. throw new StatusException("没有权限");
  196. }
  197. IPage<PaperVo> iPage = this.baseMapper.page(new Page<>(query.getPageNumber(), query.getPageSize()),
  198. query);
  199. if (CollectionUtils.isNotEmpty(iPage.getRecords())) {
  200. new BatchSetDataUtil<PaperVo>() {
  201. @Override
  202. protected void setData(List<PaperVo> dataList) {
  203. List<Long> paperIds = dataList.stream().map(PaperVo::getId).distinct()
  204. .collect(Collectors.toList());
  205. List<GroupCountVo> ret = paperGroupService.findGroupCount(paperIds);
  206. if (ret != null && ret.size() > 0) {
  207. Map<Long, Integer> countMap = new HashMap<>();
  208. Map<Long, Boolean> doubleEnableMap = new HashMap<>();
  209. for (GroupCountVo item : ret) {
  210. countMap.put(item.getPaperId(), item.getGroupCount());
  211. doubleEnableMap.put(item.getPaperId(), item.getDoubleEnable());
  212. }
  213. for (PaperVo vo : dataList) {
  214. vo.setGroupCount(countMap.get(vo.getId()));
  215. vo.setDoubleEnable(doubleEnableMap.get(vo.getId()));
  216. }
  217. }
  218. }
  219. }.setDataForBatch(iPage.getRecords(), 20);
  220. for (PaperVo vo : iPage.getRecords()) {
  221. if (vo.getGroupCount() == null) {
  222. vo.setGroupCount(0);
  223. }
  224. }
  225. }
  226. return PageUtil.of(iPage);
  227. }
  228. @Override
  229. public List<PaperVo> list(Long examId, User user) {
  230. ExamEntity exam = examService.getById(examId);
  231. if (exam == null) {
  232. throw new StatusException("未找到考试批次");
  233. }
  234. if (!user.getRole().equals(Role.SUPER_ADMIN) && !user.getSchoolId().equals(exam.getSchoolId())) {
  235. throw new StatusException("没有权限");
  236. }
  237. List<PaperVo> ret=this.baseMapper.myPaperlist(examId,user.getId());
  238. if (CollectionUtils.isNotEmpty(ret)) {
  239. new BatchSetDataUtil<PaperVo>() {
  240. @Override
  241. protected void setData(List<PaperVo> dataList) {
  242. List<Long> paperIds = dataList.stream().map(dto -> dto.getId()).distinct()
  243. .collect(Collectors.toList());
  244. List<GroupCountVo> ret = paperGroupService.findGroupCount(paperIds);
  245. if (ret != null && ret.size() > 0) {
  246. Map<Long, Integer> countMap = new HashMap<>();
  247. for (GroupCountVo item : ret) {
  248. countMap.put(item.getPaperId(), item.getGroupCount());
  249. }
  250. for (PaperVo vo : dataList) {
  251. vo.setGroupCount(countMap.get(vo.getId()));
  252. }
  253. }
  254. }
  255. }.setDataForBatch(ret, 20);
  256. }
  257. return ret;
  258. }
  259. @Override
  260. public PaperInfoVo info(Long id, User user) {
  261. PaperEntity paper = this.getById(id);
  262. if (paper == null) {
  263. throw new StatusException("未找到试卷结构信息");
  264. }
  265. if (!user.getRole().equals(Role.SUPER_ADMIN) && !user.getSchoolId().equals(paper.getSchoolId())) {
  266. throw new StatusException("没有权限");
  267. }
  268. PaperInfoVo vo = new PaperInfoVo();
  269. BeanUtils.copyProperties(paper, vo);
  270. CourseEntity course = courseService.getById(vo.getCourseId());
  271. vo.setCourseCode(course.getCode());
  272. vo.setCourseName(course.getName());
  273. vo.setStructInfo(paperDetailService.getStructInfo(vo.getId()));
  274. vo.setGroupInfo(paperGroupService.getGroupInfo(vo.getId()));
  275. return vo;
  276. }
  277. @Transactional
  278. @Override
  279. public List<String> importSubjectStruct(Long examId, User user, MultipartFile file) {
  280. ExamEntity exam = examService.getById(examId);
  281. if (exam == null) {
  282. throw new StatusException("未找到考试批次");
  283. }
  284. if(!ExamStatus.EDIT.equals(exam.getExamStatus())) {
  285. throw new StatusException("考试未开放上报,不能设置结构信息或分组信息");
  286. }
  287. if (!user.getRole().equals(Role.SUPER_ADMIN) && !user.getSchoolId().equals(exam.getSchoolId())) {
  288. throw new StatusException("没有权限");
  289. }
  290. InputStream inputStream = null;
  291. try {
  292. inputStream = file.getInputStream();
  293. ExcelReader reader=ExcelReader.create(ExcelType.XLSX, inputStream, 1);
  294. List<DataMap> lineList = reader.getDataMapList();
  295. if(!Arrays.equals(SUBJECT_STRUCT_EXCEL_HEADER,reader.getColumnNames())) {
  296. throw new StatusException("Excel表头错误");
  297. }
  298. if (CollectionUtils.isEmpty(lineList)) {
  299. throw new StatusException("Excel无内容");
  300. }
  301. if (10001 < lineList.size()) {
  302. throw new StatusException("数据行数不能超过10000");
  303. }
  304. List<String> failRecords = new ArrayList<>();
  305. List<PaperStructInfoVo> ret = new ArrayList<>();
  306. // 双评设置
  307. Map<String, DoubleMarkImportParam> doubleMarkSettingMap = new HashMap<>();
  308. for (int i = 0; i < lineList.size(); i++) {
  309. DataMap line = lineList.get(i);
  310. StringBuilder msg = new StringBuilder();
  311. PaperStructInfoVo imp = new PaperStructInfoVo();
  312. String code = trimAndNullIfBlank(line.get(SUBJECT_STRUCT_EXCEL_HEADER[0]));
  313. if (StringUtils.isBlank(code)) {
  314. msg.append(" 科目代码不能为空");
  315. } else if (code.length() > 50) {
  316. msg.append(" 科目代码不能超过50个字符");
  317. }
  318. imp.setCourseCode(code);
  319. String name = trimAndNullIfBlank(line.get(SUBJECT_STRUCT_EXCEL_HEADER[1]));
  320. if (StringUtils.isBlank(name)) {
  321. msg.append(" 科目名称不能为空");
  322. } else if (name.length() > 50) {
  323. msg.append(" 科目名称不能超过50个字符");
  324. }
  325. if (msg.length() == 0) {
  326. CourseEntity course = courseService.saveOrGet(exam.getSchoolId(), code, name);
  327. PaperEntity paper = saveOrGet(exam.getSchoolId(), examId, course.getId());
  328. imp.setPaperId(paper.getId());
  329. }
  330. String detailName = trimAndNullIfBlank(line.get(SUBJECT_STRUCT_EXCEL_HEADER[2]));
  331. if (StringUtils.isBlank(detailName)) {
  332. msg.append(" 大题名称不能为空");
  333. } else if (detailName.length() > 50) {
  334. msg.append(" 大题名称不能超过50个字符");
  335. }
  336. imp.setDetailName(detailName);
  337. //第4列不处理
  338. String detailNumber = trimAndNullIfBlank(line.get(SUBJECT_STRUCT_EXCEL_HEADER[4]));
  339. if (StringUtils.isBlank(detailNumber)) {
  340. msg.append(" 大题号不能为空");
  341. } else {
  342. try {
  343. int n = Integer.valueOf(detailNumber);
  344. if (n <= 0) {
  345. msg.append(" 大题号不能小于0");
  346. } else {
  347. imp.setDetailNumber(n);
  348. }
  349. } catch (Exception e) {
  350. msg.append(" 大题号只能是整数");
  351. }
  352. }
  353. String unitNumber = trimAndNullIfBlank(line.get(SUBJECT_STRUCT_EXCEL_HEADER[5]));
  354. if (StringUtils.isBlank(unitNumber)) {
  355. msg.append(" 小题号不能为空");
  356. } else {
  357. try {
  358. int n = Integer.valueOf(unitNumber);
  359. if (n <= 0) {
  360. msg.append(" 小题号不能小于0");
  361. } else {
  362. imp.setUnitNumber(n);
  363. }
  364. } catch (Exception e) {
  365. msg.append(" 小题号只能是整数");
  366. }
  367. }
  368. String score = trimAndNullIfBlank(line.get(SUBJECT_STRUCT_EXCEL_HEADER[6]));
  369. if (StringUtils.isBlank(score)) {
  370. msg.append(" 小题满分不能为空");
  371. } else {
  372. try {
  373. Double n = Double.valueOf(score);
  374. if (n <= 0) {
  375. msg.append(" 小题满分不能小于0");
  376. } else {
  377. if (score.indexOf(".")>=0&&score.indexOf(".") < score.length() - 2) {
  378. msg.append("小题满分只能有一位小数");
  379. } else {
  380. imp.setScore(n);
  381. }
  382. }
  383. } catch (Exception e) {
  384. msg.append(" 小题满分格式错误");
  385. }
  386. }
  387. String scoreStep = trimAndNullIfBlank(line.get(SUBJECT_STRUCT_EXCEL_HEADER[7]));
  388. if (StringUtils.isBlank(scoreStep)) {
  389. msg.append(" 间隔分不能为空");
  390. } else {
  391. try {
  392. Double n = Double.valueOf(scoreStep);
  393. if (n <= 0) {
  394. msg.append(" 间隔分不能小于0");
  395. } else {
  396. if (scoreStep.indexOf(".")>=0&&scoreStep.indexOf(".") < scoreStep.length() - 2) {
  397. msg.append("小间隔分只能有一位小数");
  398. } else {
  399. imp.setScoreStep(n);
  400. }
  401. }
  402. } catch (Exception e) {
  403. msg.append(" 间隔分格式错误");
  404. }
  405. }
  406. String groupNumberStr = trimAndNullIfBlank(line.get(SUBJECT_STRUCT_EXCEL_HEADER[8]));
  407. if (StringUtils.isNotBlank(groupNumberStr)) {
  408. try {
  409. Integer n = Integer.valueOf(groupNumberStr);
  410. if (n <= 0) {
  411. msg.append(" 评卷分组不能小于0");
  412. } else {
  413. imp.setGroupNumber(n);
  414. }
  415. } catch (Exception e) {
  416. msg.append(" 评卷分组格式错误");
  417. }
  418. }
  419. Long paperId = imp.getPaperId();
  420. Integer groupNumber = imp.getGroupNumber();
  421. if (Objects.nonNull(paperId) && Objects.nonNull(groupNumber)){
  422. // 有分组信息才解析双评信息
  423. String groupKey = paperId + "-" + groupNumber;
  424. ArbitrateMethod arbitrateMethod = null;
  425. Double doubleRate = null;
  426. Double arbitrateThreshold = null;
  427. if (doubleMarkSettingMap.containsKey(groupKey)){
  428. DoubleMarkImportParam doubleMarkImportParam = doubleMarkSettingMap.get(groupKey);
  429. arbitrateMethod = doubleMarkImportParam.getArbitrateMethod();
  430. doubleRate = doubleMarkImportParam.getDoubleRate();
  431. arbitrateThreshold = doubleMarkImportParam.getArbitrateThreshold();
  432. }
  433. String arbitrateMethodStr = trimAndNullIfBlank(line.get(SUBJECT_STRUCT_EXCEL_HEADER[10]));
  434. String doubleRateStr = trimAndNullIfBlank(line.get(SUBJECT_STRUCT_EXCEL_HEADER[11]));
  435. String arbitrateThresholdStr = trimAndNullIfBlank(line.get(SUBJECT_STRUCT_EXCEL_HEADER[12]));
  436. // 双评比例
  437. if (StringUtils.isNotBlank(doubleRateStr)) {
  438. try {
  439. double n = Double.parseDouble(doubleRateStr);
  440. if (n < 0 || n > 1){
  441. msg.append(" 双评比例只能在(0~1)");
  442. } else {
  443. if (Objects.nonNull(doubleRate) && !doubleRate.equals(n)){
  444. msg.append(" 同分组的双评比例必须相同");
  445. } else {
  446. doubleRate = n;
  447. imp.setDoubleRate(doubleRate);
  448. }
  449. }
  450. } catch (Exception e) {
  451. msg.append(" 双评比例格式错误");
  452. }
  453. }
  454. if (Objects.nonNull(doubleRate) && doubleRate > 0){
  455. // 开启双评才继续解析 仲裁方式和仲裁值
  456. // 仲裁方式(0-分组,1-小题)
  457. if (StringUtils.isNotBlank(arbitrateMethodStr)) {
  458. try {
  459. int n = Integer.parseInt(arbitrateMethodStr);
  460. List<ArbitrateMethod> arbitrateMethodList = Arrays.stream(ArbitrateMethod.values()).filter(e -> e.getValue().equals(n)).collect(
  461. Collectors.toList());
  462. if (arbitrateMethodList.size() != 1){
  463. msg.append(" 仲裁方式只能选择0或1");
  464. } else {
  465. if (Objects.nonNull(arbitrateMethod) && !arbitrateMethod.equals(arbitrateMethodList.get(0))){
  466. msg.append(" 同分组的仲裁方式必须相同");
  467. } else {
  468. arbitrateMethod = arbitrateMethodList.get(0);
  469. imp.setArbitrateMethod(arbitrateMethod);
  470. }
  471. }
  472. } catch (Exception e) {
  473. msg.append(" 仲裁方式格式错误");
  474. }
  475. } else {
  476. msg.append(" 仲裁方式不能为空");
  477. }
  478. if (Objects.nonNull(arbitrateMethod)){
  479. // 仲裁方式不为空才解析
  480. // 仲裁阀值
  481. if (StringUtils.isNotBlank(arbitrateThresholdStr)) {
  482. try {
  483. double n = Double.parseDouble(arbitrateThresholdStr);
  484. if (n < 0){
  485. msg.append(" 仲裁阀值不能小于0");
  486. }
  487. if (ArbitrateMethod.QUESTION_ARBITRATE.equals(arbitrateMethod)){
  488. Double questionScore = imp.getScore();
  489. if (Objects.nonNull(questionScore) && n > questionScore){
  490. msg.append(" 仲裁阀值不能超过小题满分");
  491. }
  492. } else if (ArbitrateMethod.GROUP_ARBITRATE.equals(arbitrateMethod)) {
  493. if (Objects.nonNull(arbitrateThreshold) && !arbitrateThreshold.equals(n)) {
  494. msg.append(" 同分组的仲裁阀值必须相同");
  495. }
  496. }
  497. arbitrateThreshold = n;
  498. imp.setArbitrateThreshold(n);
  499. } catch (Exception e) {
  500. msg.append(" 仲裁阀值格式错误");
  501. }
  502. } else {
  503. msg.append(" 仲裁阀值不能为空");
  504. }
  505. }
  506. }
  507. if (!doubleMarkSettingMap.containsKey(groupKey)){
  508. doubleMarkSettingMap.put(groupKey, new DoubleMarkImportParam(arbitrateMethod, doubleRate, arbitrateThreshold));
  509. }
  510. }
  511. if (msg.length() > 0) {
  512. failRecords.add(newError(i + 3, msg.toString()));
  513. } else {
  514. ret.add(imp);
  515. }
  516. }
  517. if (CollectionUtils.isNotEmpty(failRecords)) {
  518. TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
  519. return failRecords;
  520. }
  521. this.saveStruct(ret, user, failRecords);
  522. if (CollectionUtils.isNotEmpty(failRecords)) {
  523. TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
  524. }
  525. return failRecords;
  526. } catch (StatusException e) {
  527. throw e;
  528. } catch (Exception e) {
  529. throw new RuntimeException("系统错误", e);
  530. } finally {
  531. if (inputStream != null) {
  532. try {
  533. inputStream.close();
  534. } catch (IOException e) {
  535. }
  536. }
  537. }
  538. }
  539. private void saveStruct(List<PaperStructInfoVo> cards, User user, List<String> failRecords) {
  540. Map<Long,String> map=new HashMap<>();
  541. for(PaperStructInfoVo vo:cards) {
  542. map.put(vo.getPaperId(), vo.getCourseCode());
  543. }
  544. List<StructDomain> ces = getBeans(cards);
  545. // checkStruct(ces, failRecords,map);
  546. if (CollectionUtils.isNotEmpty(failRecords)) {
  547. return;
  548. }
  549. for (StructDomain domain : ces) {
  550. try {
  551. paperDetailService.structImport(domain, user);
  552. } catch (StatusException e) {
  553. failRecords.add("科目:"+map.get(domain.getPaperId())+" "+e.getMessage());
  554. } catch (Exception e) {
  555. throw new RuntimeException("系统错误", e);
  556. }
  557. }
  558. List<PaperGroupDomain> list = getPaperGroups(cards);
  559. for (PaperGroupDomain domain : list) {
  560. try {
  561. paperGroupService.groupSave(domain, user);
  562. } catch (StatusException e) {
  563. failRecords.add("科目:"+map.get(domain.getPaperId())+" "+e.getMessage());
  564. } catch (Exception e) {
  565. throw new RuntimeException("系统错误", e);
  566. }
  567. }
  568. }
  569. private List<PaperGroupDomain> getPaperGroups(List<PaperStructInfoVo> cards) {
  570. Map<String,PaperGroupDomain> map = new HashMap<>();
  571. for (PaperStructInfoVo info : cards) {
  572. if(info.getGroupNumber()!=null){
  573. PaperGroupDomain curGroup =map.get(getKey(info));
  574. if(curGroup==null){
  575. curGroup = new PaperGroupDomain();
  576. curGroup.setPaperId(info.getPaperId());
  577. curGroup.setNumber(info.getGroupNumber());
  578. if (Objects.nonNull(info.getDoubleRate()) && info.getDoubleRate()>0){
  579. curGroup.setDoubleEnable(true);
  580. curGroup.setDoubleRate(info.getDoubleRate());
  581. if (Objects.nonNull(info.getArbitrateMethod())){
  582. curGroup.setArbitrateMethod(info.getArbitrateMethod());
  583. }
  584. if (Objects.nonNull(info.getArbitrateThreshold())){
  585. curGroup.setArbitrateThreshold(info.getArbitrateThreshold());
  586. }
  587. } else {
  588. curGroup.setDoubleEnable(false);
  589. }
  590. curGroup.setGroupUnits(new ArrayList<>());
  591. }
  592. PaperGroupUnit unit = new PaperGroupUnit();
  593. unit.setDetailNumber(info.getDetailNumber());
  594. unit.setDetailUnitNumber(info.getUnitNumber());
  595. if (Objects.equals(ArbitrateMethod.QUESTION_ARBITRATE, info.getArbitrateMethod()) && Objects.nonNull(info.getArbitrateThreshold())){
  596. unit.setArbitrateThreshold(info.getArbitrateThreshold());
  597. }
  598. curGroup.getGroupUnits().add(unit);
  599. map.put(getKey(info),curGroup);
  600. }
  601. }
  602. List<PaperGroupDomain> list = map.values().stream().collect(Collectors.toList());
  603. return list;
  604. }
  605. private String getKey(PaperStructInfoVo p) {
  606. return p.getPaperId()+"-"+p.getCourseCode()+"-"+p.getGroupNumber();
  607. }
  608. // private void checkStruct(List<StructDomain> ces, List<String> failRecords,Map<Long,String> courseMap) {
  609. // for (StructDomain card : ces) {
  610. // int lastDetailNum = 0;
  611. // for (PaperDetail detail : card.getStructInfo()) {
  612. // if (detail.getNumber() - lastDetailNum != 1) {
  613. // failRecords.add(
  614. // "科目:" + courseMap.get(card.getPaperId()) + ",大题号" + detail.getNumber() + "错误");
  615. // }
  616. // lastDetailNum = detail.getNumber();
  617. // int lastUnitNum = 0;
  618. // for (PaperDetailUnit unit : detail.getUnits()) {
  619. // if (unit.getNumber() - lastUnitNum != 1) {
  620. // failRecords.add("科目:" + courseMap.get(card.getPaperId()) + ",大题号:"
  621. // + detail.getNumber() + ",小题号" + unit.getNumber() + "错误");
  622. // }
  623. // lastUnitNum = unit.getNumber();
  624. // }
  625. // }
  626. // }
  627. // }
  628. private List<StructDomain> getBeans(List<PaperStructInfoVo> cards) {
  629. cards.sort(new Comparator<PaperStructInfoVo>() {
  630. @Override
  631. public int compare(PaperStructInfoVo o1, PaperStructInfoVo o2) {
  632. long c1 = o1.getPaperId();
  633. long c2 = o2.getPaperId();
  634. if (c1 < c2) {
  635. return -1;
  636. } else if (c1 > c2) {
  637. return 1;
  638. } else {
  639. int indx1 = o1.getDetailNumber();
  640. int indx2 = o2.getDetailNumber();
  641. if (indx1 < indx2) {
  642. return -1;
  643. } else if (indx1 > indx2) {
  644. return 1;
  645. } else {
  646. int u1 = o1.getUnitNumber();
  647. int u2 = o2.getUnitNumber();
  648. if (u1 < u2) {
  649. return -1;
  650. } else if (u1 > u2) {
  651. return 1;
  652. } else {
  653. return 0;
  654. }
  655. }
  656. }
  657. }
  658. });
  659. List<StructDomain> ces = new ArrayList<>();
  660. StructDomain curCard = null;
  661. PaperDetail curDetail = null;
  662. for (PaperStructInfoVo info : cards) {
  663. if (curCard == null || !info.getPaperId().equals(curCard.getPaperId())) {
  664. curCard = new StructDomain();
  665. curCard.setPaperId(info.getPaperId());
  666. curCard.setStructInfo(new ArrayList<>());
  667. ces.add(curCard);
  668. curDetail = null;
  669. }
  670. if (curDetail == null || !info.getDetailNumber().equals(curDetail.getNumber())) {
  671. curDetail = new PaperDetail();
  672. curDetail.setName(info.getDetailName());
  673. curDetail.setNumber(info.getDetailNumber());
  674. curDetail.setUnits(new ArrayList<>());
  675. curCard.getStructInfo().add(curDetail);
  676. }
  677. PaperDetailUnit unit = new PaperDetailUnit();
  678. curDetail.getUnits().add(unit);
  679. unit.setNumber(info.getUnitNumber());
  680. unit.setScore(info.getScore());
  681. unit.setScoreStep(info.getScoreStep());
  682. }
  683. for (StructDomain sd : ces) {
  684. setTotalScore(sd);
  685. }
  686. return ces;
  687. }
  688. private void setTotalScore(StructDomain domain) {
  689. double total = 0.0;
  690. for (PaperDetail detial : domain.getStructInfo()) {
  691. for (PaperDetailUnit unit : detial.getUnits()) {
  692. total = Calculator.add(total, unit.getScore(), 1);
  693. }
  694. }
  695. domain.setTotalScore(total);
  696. }
  697. @Override
  698. public List<PaperStructInfoVo> subjectiveList(PaperQuery query, User user) {
  699. if (query.getSchoolId() == null) {
  700. throw new StatusException("学校不能为空");
  701. }
  702. if (!user.getRole().equals(Role.SUPER_ADMIN) && !user.getSchoolId().equals(query.getSchoolId())) {
  703. throw new StatusException("没有权限");
  704. }
  705. return this.baseMapper.subjectiveList(query,ArbitrateMethod.GROUP_ARBITRATE);
  706. }
  707. }