EvalDataAnalysisServiceImpl.java 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291
  1. package com.seecoder.dataanalysis.analysis.impl;
  2. import com.seecoder.dataanalysis.analysis.EvalDataAnalysisService;
  3. import com.seecoder.dataanalysis.data.dao.competency.CompetencyTreeDao;
  4. import com.seecoder.dataanalysis.data.dao.eval.EvalExamInfoDao;
  5. import com.seecoder.dataanalysis.data.dao.eval.EvalExamRecordDao;
  6. import com.seecoder.dataanalysis.data.dao.eval.QuestionDao;
  7. import com.seecoder.dataanalysis.data.entity.competency.*;
  8. import com.seecoder.dataanalysis.data.entity.eval.EvalExamInfo;
  9. import com.seecoder.dataanalysis.data.entity.eval.EvalExamRecord;
  10. import com.seecoder.dataanalysis.data.entity.eval.Question;
  11. import com.seecoder.dataanalysis.logic.question.QuestionService;
  12. import com.sun.xml.internal.bind.v2.TODO;
  13. import org.springframework.beans.factory.annotation.Autowired;
  14. import org.springframework.stereotype.Service;
  15. import java.text.DecimalFormat;
  16. import java.util.*;
  17. /**
  18. * @author Peng Yiyan
  19. * @since 2022/02/03
  20. */
  21. @Service
  22. public class EvalDataAnalysisServiceImpl implements EvalDataAnalysisService {
  23. @Autowired
  24. private EvalExamRecordDao evalExamRecordDao;
  25. @Autowired
  26. private EvalExamInfoDao evalExamInfoDao;
  27. @Autowired
  28. private CompetencyTreeDao competencyTreeDao;
  29. @Autowired
  30. private QuestionService questionService;
  31. @Override
  32. public CompetencyTree getTreeById(int userId){
  33. Competencies competencies = new Competencies();
  34. CompetencyTree modelTree = new CompetencyTree(competencies);
  35. Optional<CompetencyTree> result = competencyTreeDao.findById(userId);
  36. if(!result.isPresent()){
  37. System.out.println("该学生的能力树不存在");
  38. }
  39. CompetencyTree competencyTree = competencyTreeDao.findById(userId).get();
  40. modelTree.setUserId(userId);
  41. modelTree.setTreeScore(competencyTree.getTreeScore());
  42. List<KSDScore> modelKSD = modelTree.getSubCompetencyTree();
  43. List<KSDScore> tarKSD = competencyTree.getSubCompetencyTree();
  44. // for(KSDScore ksdScore : tarKSD){
  45. // String tarCom = ksdScore.getCompetency();
  46. // List<KSScore> tarKS = ksdScore.getKSScore();
  47. // List<DScore> tarD = ksdScore.getDScore();
  48. //
  49. // //找到对应的KSD树,开始进行KS和D的匹配
  50. // for(KSDScore KSDModel : modelKSD){
  51. // if(KSDModel.getCompetency().equals(tarCom)){
  52. // KSDModel.setTotalScore(ksdScore.getTotalScore());
  53. // //进行KS的匹配
  54. // List<KSScore> modelKS = KSDModel.getKSScore();
  55. // for(KSScore ksScore : tarKS){
  56. // String tarSub = ksScore.getKnowledge();
  57. // List<Double> tarSkillScore = ksScore.getSkillsAndScore();
  58. //
  59. // for(KSScore KSModel : modelKS){
  60. // if(KSModel.getKnowledge().equals(tarSub)){
  61. // List<Double> after = KSModel.getSkillsAndScore();
  62. // for(int i=0;i<tarSkillScore.size();i++){
  63. // after.set(i,tarSkillScore.get(i));
  64. // }
  65. // KSModel.setSkillsAndScore(after);
  66. // break;
  67. // }
  68. // }
  69. // }
  70. // KSDModel.setKSScore(modelKS);
  71. // //进行D的匹配
  72. // List<DScore> modelD = KSDModel.getDScore();
  73. // for(DScore dScore : tarD){
  74. // String tarName = dScore.getName();
  75. //
  76. // for(DScore DModel : modelD){
  77. // if(DModel.getName().equals(tarName)){
  78. // DModel.setScore(dScore.getScore());
  79. // break;
  80. // }
  81. // }
  82. // }
  83. // KSDModel.setDScore(modelD);
  84. // break;
  85. // }
  86. // }
  87. // }
  88. modelTree.setSubCompetencyTree(modelKSD);
  89. return modelTree;
  90. }
  91. @Override
  92. public CompetencyTree getTreeAfterExam(int recordId) {
  93. EvalExamRecord evalExamRecord = evalExamRecordDao.findById(recordId).get();
  94. Optional<EvalExamInfo> result1 = evalExamInfoDao.findById(evalExamRecord.getExamId());
  95. if (!result1.isPresent()) {
  96. System.out.println("考试信息不存在");
  97. return null;
  98. }
  99. EvalExamInfo evalExamInfo = evalExamInfoDao.findById(evalExamRecord.getExamId()).get();
  100. CompetencyTree competencyTree;
  101. Optional<CompetencyTree> result2 = competencyTreeDao.findById(evalExamRecord.getUserId());
  102. if (!result2.isPresent()) {
  103. //若查找不到能力树就新建一棵
  104. competencyTree = new CompetencyTree(evalExamRecord.getUserId());
  105. } else {
  106. competencyTree = competencyTreeDao.findById(evalExamRecord.getUserId()).get();
  107. }
  108. //数据取完,开始进行KSD分析和入库
  109. List<KSDScore> subTree = competencyTree.getSubCompetencyTree();
  110. //难度由1-5,分别对应1.0, 1.25, 1.5, 1.75, 2.0的得分系数
  111. Integer difficulty = evalExamInfo.getDifficulty();
  112. String disposition = evalExamInfo.getDisposition();
  113. // System.out.println(competencyTree);
  114. Double tree_Score = competencyTree.getTreeScore();
  115. double[] difficulty_percent = new double[]{1.0, 1.25, 1.5, 1.75, 2.0};
  116. //得到学生所有题目的得分
  117. Map<String, Double> studentScores = evalExamRecord.getErrorQuestions();
  118. Map<String, Double> questionAndScore = evalExamInfo.getQuestionAndScore();
  119. //修改成不初始化,而是逐条添加的模式,对每一题进行分析入库
  120. for (Map.Entry<String, Double> entry : studentScores.entrySet()) {
  121. String questionId = entry.getKey();
  122. Question question = questionService.getQuestionById(questionId);
  123. List<String> knowledgeList = question.getCompetencies();
  124. Integer weight = question.getWeight();
  125. //能力树中的加分 = 学生得分 * 试卷难度
  126. Double addScore = difficulty_percent[difficulty - 1] * studentScores.get(questionId);
  127. //增加能力树总分,注意,每个competency都会加分
  128. tree_Score += (addScore * knowledgeList.size());
  129. for(int i=0;i<knowledgeList.size();i++){
  130. String[] coms = knowledgeList.get(i).split("\\.");
  131. String com1 = coms[0];
  132. dfs(subTree,disposition,weight,addScore,"",com1);
  133. int index1 = 0;
  134. if(coms.length > 1){
  135. String com2 = coms[1];
  136. for(;index1<subTree.size();index1++){
  137. if(subTree.get(index1).getCompetency().equals(com1)){
  138. break;
  139. }
  140. }
  141. dfs(subTree.get(index1).getChildren(),disposition,weight,addScore,com1+".",com2);
  142. }
  143. if(coms.length > 2){
  144. String com2 = coms[1];
  145. String com3 = coms[2];
  146. // System.out.println(com1+com2+com3);
  147. int index2 = 0;
  148. for(;index2<subTree.get(index1).getChildren().size();index2++){
  149. // System.out.println(subTree.get(index1).getChildren().get(index2).getCompetency());
  150. if(subTree.get(index1).getChildren().get(index2).getCompetency().split("\\.")[1].equals(com2)){
  151. break;
  152. }
  153. }
  154. dfs(subTree.get(index1).getChildren().get(index2).getChildren(),disposition,weight,addScore,com1+"."+com2+".",com3);
  155. }
  156. }
  157. }
  158. //处理完考试中的每个问题后,更新能力树
  159. competencyTree.setTreeScore(tree_Score);
  160. competencyTree.setSubCompetencyTree(subTree);
  161. competencyTreeDao.save(competencyTree);
  162. return competencyTree;
  163. }
  164. public void dfs(List<KSDScore> sub,String disposition,Integer weight,Double addScore,String pre,String com){
  165. // System.out.println("start: "+com);
  166. boolean existCom = false;
  167. KSDScore changeKSD = new KSDScore();
  168. for (KSDScore ksdScore : sub) {
  169. System.out.println(ksdScore.getCompetency());
  170. if (ksdScore.getCompetency().equals(pre+com)) {
  171. existCom = true;
  172. changeKSD = ksdScore;
  173. break;
  174. }
  175. }
  176. if (!existCom) {
  177. List<DScore> addD = new ArrayList<>();
  178. Double[] ds = new Double[]{0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
  179. List<Double> addS = Arrays.asList(ds);
  180. List<KSDScore> addChild = new ArrayList<>();
  181. changeKSD.setCompetency(pre+com);
  182. changeKSD.setTotalScore(0.0);
  183. changeKSD.setSkillsAndScores(addS);
  184. changeKSD.setDScore(addD);
  185. changeKSD.setChildren(addChild);
  186. }
  187. Double totalScore = changeKSD.getTotalScore();
  188. totalScore += addScore;
  189. changeKSD.setTotalScore(totalScore);
  190. //增加Skills
  191. List<Double> skillsAndScore = changeKSD.getSkillsAndScores();
  192. Double skillScore = skillsAndScore.get(weight-1);
  193. skillScore += addScore;
  194. skillsAndScore.set(weight-1,skillScore);
  195. changeKSD.setSkillsAndScores(skillsAndScore);
  196. //增加Disposition
  197. if(disposition != null){
  198. boolean existD = false;
  199. List<DScore> subD = changeKSD.getDScore();
  200. DScore changeD = new DScore();
  201. for (DScore dScore : subD) {
  202. if (dScore.getName().equals(disposition)) {
  203. existD = true;
  204. changeD = dScore;
  205. break;
  206. }
  207. }
  208. if (!existD) {
  209. changeD.setName(disposition);
  210. changeD.setScore(0.0);
  211. }
  212. Double addDScore = addScore + changeD.getScore();
  213. changeD.setScore(addDScore);
  214. //需要增加新建的D子分支
  215. if (!existD) {
  216. subD.add(changeD);
  217. }
  218. changeKSD.setDScore(subD);
  219. }else {
  220. System.out.println("disposition信息不存在");
  221. }
  222. if (!existCom) {
  223. sub.add(changeKSD);
  224. }
  225. }
  226. @Override
  227. public Map<String, Double> getStudentErrorQuestions(int userId){
  228. List<EvalExamRecord> evalExamRecordList = evalExamRecordDao.findByUserId(userId);
  229. Map<String,Double> res = new HashMap<>();
  230. for(EvalExamRecord evalExamRecord : evalExamRecordList){
  231. Optional<EvalExamInfo> result = evalExamInfoDao.findById(evalExamRecord.getExamId());
  232. if(!result.isPresent()){
  233. System.out.println("找不到对应考试信息");
  234. continue;
  235. }
  236. EvalExamInfo evalExamInfo = evalExamInfoDao.findById(evalExamRecord.getExamId()).get();
  237. //获得题目ID和题目分数的对应关系
  238. Map<String,Double> questionAndScore = evalExamInfo.getQuestionAndScore();
  239. Map<String,Double> errorQuestions = evalExamRecord.getErrorQuestions();
  240. for(String questionId : errorQuestions.keySet()){
  241. // Optional<Question> result = questionDao.findById(questionId);
  242. // if(!result.isPresent()){
  243. // System.out.println("题号不存在");
  244. // continue;
  245. // }
  246. Question question = questionService.getQuestionById(questionId);
  247. //如果题目分数为0,则跳过该题不做分析
  248. if(questionAndScore.get(questionId) == 0){
  249. continue;
  250. }
  251. // System.out.println(errorQuestions.get(questionId));
  252. // System.out.println(question.getQuestionScore());
  253. //如果做过相同的题目,则取最高分
  254. DecimalFormat df = new DecimalFormat("#.00");
  255. Double scorePercent = errorQuestions.get(questionId)/questionAndScore.get(questionId);
  256. if(res.containsKey(questionId)){
  257. scorePercent = Math.max(scorePercent,res.get(questionId));
  258. }
  259. res.put(questionId,Double.valueOf(df.format(scorePercent)));
  260. }
  261. }
  262. return res;
  263. }
  264. }