EvalDataAnalysisServiceImpl.java 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268
  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.sun.xml.internal.bind.v2.TODO;
  12. import org.springframework.beans.factory.annotation.Autowired;
  13. import org.springframework.stereotype.Service;
  14. import java.util.*;
  15. /**
  16. * @author Peng Yiyan
  17. * @since 2022/02/03
  18. */
  19. @Service
  20. public class EvalDataAnalysisServiceImpl implements EvalDataAnalysisService {
  21. @Autowired
  22. private EvalExamRecordDao evalExamRecordDao;
  23. @Autowired
  24. private EvalExamInfoDao evalExamInfoDao;
  25. @Autowired
  26. private CompetencyTreeDao competencyTreeDao;
  27. @Autowired
  28. private QuestionDao questionDao;
  29. @Override
  30. public CompetencyTree getTreeById(int userId){
  31. Competencies competencies = new Competencies();
  32. CompetencyTree modelTree = new CompetencyTree(competencies);
  33. Optional<CompetencyTree> result = competencyTreeDao.findById(userId);
  34. if(!result.isPresent()){
  35. System.out.println("该学生的能力树不存在");
  36. }
  37. CompetencyTree competencyTree = competencyTreeDao.findById(userId).get();
  38. modelTree.setTreeScore(competencyTree.getTreeScore());
  39. List<KSDScore> modelKSD = modelTree.getSubCompetencyTree();
  40. List<KSDScore> tarKSD = competencyTree.getSubCompetencyTree();
  41. for(KSDScore ksdScore : tarKSD){
  42. String tarCom = ksdScore.getCompetency();
  43. List<KSScore> tarKS = ksdScore.getKSScore();
  44. List<DScore> tarD = ksdScore.getDScore();
  45. //找到对应的KSD树,开始进行KS和D的匹配
  46. for(KSDScore KSDModel : modelKSD){
  47. if(KSDModel.getCompetency().equals(tarCom)){
  48. KSDModel.setTotalScore(ksdScore.getTotalScore());
  49. //进行KS的匹配
  50. List<KSScore> modelKS = KSDModel.getKSScore();
  51. for(KSScore ksScore : tarKS){
  52. String tarSub = ksScore.getKnowledge();
  53. List<Double> tarSkillScore = ksScore.getSkillsAndScore();
  54. for(KSScore KSModel : modelKS){
  55. if(KSModel.getKnowledge().equals(tarSub)){
  56. List<Double> after = KSModel.getSkillsAndScore();
  57. for(int i=0;i<tarSkillScore.size();i++){
  58. after.set(i,tarSkillScore.get(i));
  59. }
  60. KSModel.setSkillsAndScore(after);
  61. break;
  62. }
  63. }
  64. }
  65. KSDModel.setKSScore(modelKS);
  66. //进行D的匹配
  67. List<DScore> modelD = KSDModel.getDScore();
  68. for(DScore dScore : tarD){
  69. String tarName = dScore.getName();
  70. for(DScore DModel : modelD){
  71. if(DModel.getName().equals(tarName)){
  72. DModel.setScore(dScore.getScore());
  73. break;
  74. }
  75. }
  76. }
  77. KSDModel.setDScore(modelD);
  78. break;
  79. }
  80. }
  81. }
  82. modelTree.setSubCompetencyTree(modelKSD);
  83. return modelTree;
  84. }
  85. @Override
  86. public CompetencyTree getTreeAfterExam(int recordId){
  87. //TODO 测试检查
  88. EvalExamRecord evalExamRecord = evalExamRecordDao.findById(recordId).get();
  89. Optional<EvalExamInfo> result1 = evalExamInfoDao.findById(evalExamRecord.getExamId());
  90. if(!result1.isPresent()){
  91. System.out.println("考试信息不存在");
  92. return null;
  93. }
  94. EvalExamInfo evalExamInfo = evalExamInfoDao.findById(evalExamRecord.getExamId()).get();
  95. CompetencyTree competencyTree;
  96. Optional<CompetencyTree> result2 = competencyTreeDao.findById(evalExamRecord.getUserId());
  97. if(!result2.isPresent()){
  98. competencyTree = new CompetencyTree(evalExamRecord.getUserId());
  99. }else {
  100. competencyTree = competencyTreeDao.findById(evalExamRecord.getUserId()).get();
  101. }
  102. //数据取完,开始进行KSD分析和入库
  103. List<KSDScore> subTree = competencyTree.getSubCompetencyTree();
  104. //难度由1-5,分别对应1.0, 1.25, 1.5, 1.75, 2.0的得分系数
  105. Integer difficulty = evalExamInfo.getDifficulty();
  106. String disposition = evalExamInfo.getDisposition();
  107. System.out.println(competencyTree);
  108. Double tree_Score = competencyTree.getTreeScore();
  109. double[] difficulty_percent = new double[]{1.0,1.25,1.5,1.75,2.0};
  110. //得到学生所有题目的得分
  111. Map<String, Double> studentScores = evalExamRecord.getErrorQuestions();
  112. // Map<String,Double> questionAndScore = evalExamInfo.getQuestionAndScore();
  113. //修改成不初始化,而是逐条添加的模式
  114. for(Map.Entry<String,Double> entry : studentScores.entrySet()){
  115. String questionId = entry.getKey();
  116. Question question = questionDao.findById(questionId).get();
  117. //能力树中的加分 = 学生得分 * 试卷难度
  118. Double addScore = difficulty_percent[difficulty-1] * studentScores.get(questionId);
  119. //增加能力树总分,注意,每个competency都会加分
  120. tree_Score += (addScore*question.getCompetencies().size());
  121. for(int i=0;i<question.getCompetencies().size();i++){
  122. String competency = question.getCompetencies().get(i);
  123. KSScore ksScoreMessage = question.getKsScores().get(i);
  124. //判定当前的subTree中是否添加过该分支,若添加过则直接修改,否则要新建分支
  125. boolean existCom = false;
  126. KSDScore changeKSDScore = new KSDScore();
  127. //根据competency找大分类
  128. for(KSDScore ksdScore : subTree){
  129. //competency大分支存在
  130. if(ksdScore.getCompetency().equals(competency)){
  131. existCom = true;
  132. changeKSDScore = ksdScore;
  133. break;
  134. }
  135. }
  136. //competency大分支不存在,需要添加
  137. if(existCom == false){
  138. changeKSDScore.setCompetency(competency);
  139. changeKSDScore.setTotalScore(0.0);
  140. List<KSScore> addKs = new ArrayList<>();
  141. List<DScore> addD = new ArrayList<>();
  142. changeKSDScore.setKSScore(addKs);
  143. changeKSDScore.setDScore(addD);
  144. }
  145. //增加该KSD子树的分数
  146. Double total_score = changeKSDScore.getTotalScore();
  147. total_score += addScore;
  148. changeKSDScore.setTotalScore(total_score);
  149. //开始处理KSScore,记录子分支是否存在
  150. boolean existSubCom = false;
  151. //在对应的competency下进行下一步小分类
  152. List<KSScore> subKS = changeKSDScore.getKSScore();
  153. KSScore changeKSScore = new KSScore();
  154. for(KSScore ksScore : subKS){
  155. if(ksScore.getKnowledge().equals(ksScoreMessage.getKnowledge())){
  156. existSubCom = true;
  157. changeKSScore = ksScore;
  158. break;
  159. }
  160. }
  161. //sub小分支不存在,需要添加并对分支名称和分数进行初始化
  162. if(existSubCom == false){
  163. changeKSScore.setKnowledge(ksScoreMessage.getKnowledge());
  164. changeKSScore.setSkillsAndScore(Arrays.asList(new Double[]{0.0,0.0,0.0,0.0,0.0,0.0}));
  165. }
  166. List<Double> skills = changeKSScore.getSkillsAndScore();
  167. for(int j=0;j<skills.size();j++){
  168. Double score = ksScoreMessage.getSkillsAndScore().get(j) * addScore + skills.get(j);
  169. skills.set(j,score);
  170. }
  171. changeKSScore.setSkillsAndScore(skills);
  172. //需要增加新建的KS子分支
  173. if(existSubCom == false){
  174. subKS.add(changeKSScore);
  175. }
  176. //开始处理DScore,记录该品质是否存在
  177. boolean existD = false;
  178. List<DScore> subD = changeKSDScore.getDScore();
  179. DScore changeDScore = new DScore();
  180. for(DScore dScore : subD){
  181. if(dScore.getName().equals(disposition)){
  182. existD = true;
  183. changeDScore = dScore;
  184. break;
  185. }
  186. }
  187. if(existD == false){
  188. changeDScore.setName(disposition);
  189. changeDScore.setScore(0.0);
  190. }
  191. Double addDScore = addScore + changeDScore.getScore();
  192. changeDScore.setScore(addDScore);
  193. //需要增加新建的D子分支
  194. if(existD == false){
  195. subD.add(changeDScore);
  196. }
  197. //处理完KS分支和D分支
  198. changeKSDScore.setKSScore(subKS);
  199. changeKSDScore.setDScore(subD);
  200. if(existCom == false){
  201. subTree.add(changeKSDScore);
  202. }
  203. }
  204. }
  205. //处理完考试中的每个问题后,更新能力树
  206. competencyTree.setTreeScore(tree_Score);
  207. competencyTree.setSubCompetencyTree(subTree);
  208. competencyTreeDao.save(competencyTree);
  209. return competencyTree;
  210. }
  211. @Override
  212. public Map<String, Double> getStudentErrorQuestions(int userId){
  213. List<EvalExamRecord> evalExamRecordList = evalExamRecordDao.findByUserId(userId);
  214. Map<String,Double> res = new HashMap<>();
  215. for(EvalExamRecord evalExamRecord : evalExamRecordList){
  216. Map<String,Double> errorQuestions = evalExamRecord.getErrorQuestions();
  217. for(String questionId : errorQuestions.keySet()){
  218. Optional<Question> result = questionDao.findById(questionId);
  219. if(!result.isPresent()){
  220. System.out.println("题号不存在");
  221. continue;
  222. }
  223. Question question = questionDao.findById(questionId).get();
  224. //如果题目分数为0,则跳过该题不做分析
  225. if(question.getQuestionScore() == 0){
  226. continue;
  227. }
  228. Double scorePercent = errorQuestions.get(questionId) / question.getQuestionScore();
  229. res.put(questionId,res.getOrDefault(questionId,0.0)+scorePercent);
  230. }
  231. }
  232. return res;
  233. }
  234. }