AdminController.java 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314
  1. package cn.com.qmth.am.controller;
  2. import java.io.File;
  3. import java.io.IOException;
  4. import java.io.InputStream;
  5. import java.io.PrintWriter;
  6. import java.math.BigDecimal;
  7. import java.util.ArrayList;
  8. import java.util.Comparator;
  9. import java.util.HashMap;
  10. import java.util.HashSet;
  11. import java.util.List;
  12. import java.util.Map;
  13. import java.util.Set;
  14. import javax.servlet.http.HttpServletResponse;
  15. import org.apache.commons.collections4.CollectionUtils;
  16. import org.apache.commons.io.FileUtils;
  17. import org.springframework.beans.factory.annotation.Autowired;
  18. import org.springframework.web.bind.annotation.RequestMapping;
  19. import org.springframework.web.bind.annotation.RequestMethod;
  20. import org.springframework.web.bind.annotation.RequestParam;
  21. import org.springframework.web.bind.annotation.RestController;
  22. import org.springframework.web.multipart.MultipartFile;
  23. import com.alibaba.fastjson.util.IOUtils;
  24. import com.qmth.boot.api.annotation.Aac;
  25. import com.qmth.boot.api.constant.ApiConstant;
  26. import com.qmth.boot.core.concurrent.service.ConcurrentService;
  27. import cn.com.qmth.am.bean.DataKey;
  28. import cn.com.qmth.am.config.SysProperty;
  29. import cn.com.qmth.am.entity.QuestionEntity;
  30. import cn.com.qmth.am.entity.StudentScoreEntity;
  31. import cn.com.qmth.am.enums.DataStatus;
  32. import cn.com.qmth.am.enums.ImportFileName;
  33. import cn.com.qmth.am.enums.LockType;
  34. import cn.com.qmth.am.service.QuestionService;
  35. import cn.com.qmth.am.service.StudentScoreService;
  36. import cn.com.qmth.am.service.StudentService;
  37. import cn.com.qmth.am.utils.Calculator;
  38. import io.swagger.annotations.ApiOperation;
  39. @RestController
  40. @RequestMapping(ApiConstant.DEFAULT_URI_PREFIX + "/admin")
  41. @Aac(strict = false, auth = false)
  42. public class AdminController {
  43. @Autowired
  44. private QuestionService questionService;
  45. @Autowired
  46. private StudentService studentService;
  47. @Autowired
  48. private StudentScoreService studentScoreService;
  49. @Autowired
  50. private SysProperty sysProperty;
  51. @Autowired
  52. private ConcurrentService concurrentService;
  53. @ApiOperation(value = "分析数据")
  54. @RequestMapping(value = "fenxi", method = RequestMethod.GET)
  55. public void fenxi(HttpServletResponse response, @RequestParam Long examId,
  56. @RequestParam(required = false) Boolean exZero,@RequestParam(required = false) Integer count) {
  57. StringBuilder sb = new StringBuilder();
  58. List<QuestionEntity> qs = questionService.findByExamId(examId);
  59. if (CollectionUtils.isEmpty(qs)) {
  60. sb.append("试题数:0");
  61. returnJson(sb.toString(), response);
  62. return;
  63. }
  64. sb.append("试题数:" + qs.size() + "\r\n");
  65. for (QuestionEntity q : qs) {
  66. List<StudentScoreEntity> scores = studentScoreService.findBy(examId, q.getSubjectCode(), q.getMainNumber(),
  67. q.getSubNumber(), exZero,count);
  68. if (CollectionUtils.isEmpty(scores)) {
  69. sb.append(q.getSubjectCode() + "|" + q.getMainNumber() + "|" + q.getSubNumber() + "| 相关系数:- \r\n");
  70. } else {
  71. double[] a = new double[scores.size()];
  72. double[] b = new double[scores.size()];
  73. int i = 0;
  74. for (StudentScoreEntity s : scores) {
  75. a[i] = s.getAiScore();
  76. b[i] = s.getMarkingScore();
  77. i++;
  78. }
  79. try {
  80. double ret = new BigDecimal(Calculator.correlation(a, b)).setScale(2, BigDecimal.ROUND_HALF_UP)
  81. .doubleValue();
  82. double avg1 = new BigDecimal(Calculator.mean(a)).setScale(2, BigDecimal.ROUND_HALF_UP)
  83. .doubleValue();
  84. double avg2 = new BigDecimal(Calculator.mean(b)).setScale(2, BigDecimal.ROUND_HALF_UP)
  85. .doubleValue();
  86. sb.append(q.getSubjectCode() + "|" + q.getMainNumber() + "|" + q.getSubNumber() + "| 相关系数:" + ret
  87. + "| 人评均分:" + avg2 + "| 机评均分:" + avg1 +"| 题数:"+scores.size()+ " \r\n");
  88. fill(scores, sb);
  89. } catch (Exception e) {
  90. sb.append(q.getSubjectCode() + "|" + q.getMainNumber() + "|" + q.getSubNumber() + "| 相关系数出错:- \r\n");
  91. }
  92. }
  93. }
  94. returnJson(sb.toString(), response);
  95. }
  96. private void fill(List<StudentScoreEntity> scores,StringBuilder sb) {
  97. int total=scores.size();
  98. int st=0;
  99. Map<DataKey,Integer> ret=new HashMap<>();
  100. for(StudentScoreEntity s:scores) {
  101. DataKey k=getKey(s.getAiScore()-s.getMarkingScore());
  102. Integer tem=ret.get(k);
  103. if(tem==null) {
  104. tem=0;
  105. }
  106. ret.put(k, tem+1);
  107. }
  108. List<DataKey> ks=new ArrayList<>(ret.keySet());
  109. ks.sort(new Comparator<DataKey>() {
  110. @Override
  111. public int compare(DataKey o1, DataKey o2) {
  112. int c1 = o1.getIndex();
  113. int c2 = o2.getIndex();
  114. if (c1 < c2) {
  115. return -1;
  116. } else if (c1 > c2) {
  117. return 1;
  118. } else {
  119. return 0;
  120. }
  121. }
  122. });
  123. for(DataKey k:ks) {
  124. Integer c=ret.get(k);
  125. if(k.getIndex()<=2) {
  126. st=st+c;
  127. }
  128. sb.append(" "+k.getKey()+" "+c+" "+Calculator.percentage(c, total, 2)+ " \r\n");
  129. }
  130. sb.append(" 3分差值:"+st+" "+Calculator.percentage(st, total, 2)+ " \r\n");
  131. }
  132. private static DataKey getKey(double s) {
  133. if(s<0) {
  134. s=0-s;
  135. }
  136. if(s==0) {
  137. DataKey r=new DataKey();
  138. r.setKey("[0,0]");
  139. r.setIndex(-1);
  140. return r;
  141. }
  142. int i=0;
  143. for(;;) {
  144. if(i<s&&s<=i+1) {
  145. DataKey r=new DataKey();
  146. r.setKey("("+i+","+(i+1)+"]");
  147. r.setIndex(i);
  148. return r;
  149. }
  150. i++;
  151. }
  152. }
  153. @ApiOperation(value = "进度详情")
  154. @RequestMapping(value = "info", method = RequestMethod.GET)
  155. public void info(HttpServletResponse response, @RequestParam Long examId) {
  156. StringBuilder sb = new StringBuilder();
  157. List<QuestionEntity> qs = questionService.findByExamId(examId);
  158. int qstotal = 0;
  159. int qsCourse = 0;
  160. if (CollectionUtils.isNotEmpty(qs)) {
  161. Set<String> cset = new HashSet<>();
  162. qstotal = qs.size();
  163. for (QuestionEntity q : qs) {
  164. cset.add(q.getSubjectCode());
  165. }
  166. qsCourse = cset.size();
  167. }
  168. sb.append("ocr任务是否开启:" + (sysProperty.getOcrTaskEnable() ? "是" : "否") + "\r\n");
  169. sb.append("评分任务是否开启:" + (sysProperty.getMarkingTaskEnable() ? "是" : "否") + "\r\n");
  170. sb.append("试卷科目总数:" + qsCourse + "\r\n");
  171. sb.append("试卷小题总数:" + qstotal + "\r\n");
  172. int total = studentService.countBy(examId, null);
  173. if (total == 0) {
  174. sb.append("考生总数:0");
  175. returnJson(sb.toString(), response);
  176. return;
  177. }
  178. sb.append("考生总数:" + total + "\r\n");
  179. int suc = studentService.countBy(examId, DataStatus.SUCCESS);
  180. sb.append("考生处理成功总数:" + suc + "\r\n");
  181. int failed = studentService.countBy(examId, DataStatus.FAILED);
  182. sb.append("考生处理失败总数:" + failed + "\r\n");
  183. int qtotal = studentScoreService.countBy(examId, null);
  184. if (qtotal == 0) {
  185. sb.append("试题总数:0");
  186. returnJson(sb.toString(), response);
  187. return;
  188. }
  189. sb.append("考生试题总数:" + qtotal + "\r\n");
  190. int qocrsuc = studentScoreService.countOcrBy(examId, DataStatus.SUCCESS);
  191. sb.append("考生试题OCR成功总数:" + qocrsuc + "\r\n");
  192. int qocrfailed = studentScoreService.countOcrBy(examId, DataStatus.FAILED);
  193. sb.append("考生试题OCR失败总数:" + qocrfailed + "\r\n");
  194. int qsuc = studentScoreService.countBy(examId, DataStatus.SUCCESS);
  195. sb.append("考生试题评分成功总数:" + qsuc + "\r\n");
  196. int qfailed = studentScoreService.countBy(examId, DataStatus.FAILED);
  197. sb.append("考生试题评分失败总数:" + qfailed + "\r\n");
  198. returnJson(sb.toString(), response);
  199. }
  200. @ApiOperation(value = "上传导入文件")
  201. @RequestMapping(value = "upload", method = RequestMethod.POST)
  202. public String upload(@RequestParam MultipartFile file) {
  203. if (ImportFileName.getByName(file.getOriginalFilename()) == null) {
  204. return "上传失败,文件名错误";
  205. }
  206. File old = new File(sysProperty.getDataDir() + "/" + file.getOriginalFilename());
  207. if (old.exists()) {
  208. return "上传失败,有正在处理的文件";
  209. }
  210. InputStream in = null;
  211. try {
  212. in = file.getInputStream();
  213. FileUtils.copyInputStreamToFile(file.getInputStream(), old);
  214. } catch (IOException e) {
  215. return "上传失败," + e.getMessage();
  216. } finally {
  217. if (in != null) {
  218. try {
  219. in.close();
  220. } catch (IOException e) {
  221. }
  222. }
  223. }
  224. return "上传成功";
  225. }
  226. @ApiOperation(value = "重置数据")
  227. @RequestMapping(value = "reset", method = RequestMethod.GET)
  228. public String reset(@RequestParam Long examId, @RequestParam(required = false) String subjectCode) {
  229. boolean lock1 = concurrentService.getReadWriteLock(LockType.AI_MARKING.name()).writeLock().tryLock();
  230. if (!lock1) {
  231. return "重置失败,有任务正在处理,请稍后 再试";
  232. }
  233. boolean lock2 = concurrentService.getReadWriteLock(LockType.OCR.name()).writeLock().tryLock();
  234. if (!lock2) {
  235. return "重置失败,有任务正在处理,请稍后 再试";
  236. }
  237. try {
  238. studentService.reset(examId, subjectCode);
  239. return "重置成功";
  240. } finally {
  241. if (lock2) {
  242. concurrentService.getReadWriteLock(LockType.OCR.name()).writeLock().unlock();
  243. }
  244. if (lock1) {
  245. concurrentService.getReadWriteLock(LockType.AI_MARKING.name()).writeLock().unlock();
  246. }
  247. }
  248. }
  249. @ApiOperation(value = "删除数据")
  250. @RequestMapping(value = "clear", method = RequestMethod.GET)
  251. public String clear(@RequestParam Long examId, @RequestParam(required = false) String subjectCode) {
  252. boolean lock1 = concurrentService.getReadWriteLock(LockType.AI_MARKING.name()).writeLock().tryLock();
  253. if (!lock1) {
  254. return "删除失败,有任务正在处理,请稍后 再试";
  255. }
  256. boolean lock2 = concurrentService.getReadWriteLock(LockType.OCR.name()).writeLock().tryLock();
  257. if (!lock2) {
  258. return "删除失败,有任务正在处理,请稍后 再试";
  259. }
  260. try {
  261. studentService.clear(examId, subjectCode);
  262. return "删除成功";
  263. } finally {
  264. if (lock2) {
  265. concurrentService.getReadWriteLock(LockType.OCR.name()).writeLock().unlock();
  266. }
  267. if (lock1) {
  268. concurrentService.getReadWriteLock(LockType.AI_MARKING.name()).writeLock().unlock();
  269. }
  270. }
  271. }
  272. @ApiOperation(value = "机评开关")
  273. @RequestMapping(value = "marking/status", method = RequestMethod.GET)
  274. public String markingStatus(@RequestParam Boolean enable) {
  275. sysProperty.setMarkingTaskEnable(enable);
  276. return "设置成功:" + enable;
  277. }
  278. @ApiOperation(value = "ocr开关")
  279. @RequestMapping(value = "ocr/status", method = RequestMethod.GET)
  280. public String ocrStatus(@RequestParam Boolean enable) {
  281. sysProperty.setOcrTaskEnable(enable);
  282. return "设置成功:" + enable;
  283. }
  284. private void returnJson(String body, HttpServletResponse response) {
  285. response.setContentType("application/json;charset=utf-8");
  286. PrintWriter writer = null;
  287. try {
  288. writer = response.getWriter();
  289. writer.write(body);
  290. } catch (IOException e) {
  291. } finally {
  292. IOUtils.close(writer);
  293. }
  294. }
  295. }