package com.ruoyi.web.service; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import com.google.common.collect.Sets; import com.ruoyi.common.core.domain.AjaxResult; import com.ruoyi.common.core.domain.entity.SysUser; import com.ruoyi.common.core.redis.RedisCache; import com.ruoyi.common.utils.DateUtils; import com.ruoyi.common.utils.SecurityUtils; import com.ruoyi.common.utils.StringUtils; import com.ruoyi.mxjb.domain.MxjbContants; import com.ruoyi.sy.domain.*; import com.ruoyi.sy.mapper.*; import com.ruoyi.web.domain.CategoryDto; import com.ruoyi.web.domain.PaperDto; import com.ruoyi.web.domain.QuestionDto; import com.ruoyi.web.domain.TestMarjorDto; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.math.NumberUtils; import org.springframework.stereotype.Service; import java.util.*; import java.util.function.Function; import java.util.stream.Collectors; @Service public class SyTestMajorService { private final SyMajorMapper majorMapper; private final SyKnowledgeInterstTypeMapper syKnowledgeInterstTypeMapper; private final SyMajorCategoryMapper syMajorCategoryMapper; private final SyMajorMajorMapper syMajorMajorMapper; private final SyOccupationInterstMajorMapper syOccupationInterstMajorMapper; private final SyOccupationInterstTypeMapper syOccupationInterstTypeMapper; private final SyPhilosophyViewMajorMapper syPhilosophyViewMajorMapper; private final SyPhilosophyViewTypeMapper syPhilosophyViewTypeMapper; private final SyTestAnswersMapper syTestAnswersMapper; private final SyTestExamineeMapper syTestExamineeMapper; private final SyTestPaperMapper syTestPaperMapper; private final SyTestQuestionMapper syTestQuestionMapper; private final SyTestSelectCategoryMapper syTestSelectCategoryMapper; private final SyTestSelectMajorMapper syTestSelectMajorMapper; private final ExamUtilService examUtilService; private final RedisCache redisCache; private Set marjorCodeSet; private ObjectMapper om = new ObjectMapper(); // key1 category, key2 value(RIA...) // key1 category, key2 value(喜欢, 擅长) private TypeReference>> keyCatValueTypeReference = new TypeReference>>() {}; private TypeReference> keyValueTypeReference = new TypeReference>() {}; public SyTestMajorService(SyMajorMapper majorMapper, SyKnowledgeInterstTypeMapper syKnowledgeInterstTypeMapper, SyMajorCategoryMapper syMajorCategoryMapper, SyMajorMajorMapper syMajorMajorMapper, SyOccupationInterstMajorMapper syOccupationInterstMajorMapper, SyOccupationInterstTypeMapper syOccupationInterstTypeMapper, SyPhilosophyViewMajorMapper syPhilosophyViewMajorMapper, SyPhilosophyViewTypeMapper syPhilosophyViewTypeMapper, SyTestAnswersMapper syTestAnswersMapper, SyTestExamineeMapper syTestExamineeMapper, SyTestPaperMapper syTestPaperMapper, SyTestQuestionMapper syTestQuestionMapper, SyTestSelectCategoryMapper syTestSelectCategoryMapper, SyTestSelectMajorMapper syTestSelectMajorMapper, ExamUtilService examUtilService, RedisCache redisCache) { this.majorMapper = majorMapper; this.syKnowledgeInterstTypeMapper = syKnowledgeInterstTypeMapper; this.syMajorCategoryMapper = syMajorCategoryMapper; this.syMajorMajorMapper = syMajorMajorMapper; this.syOccupationInterstMajorMapper = syOccupationInterstMajorMapper; this.syOccupationInterstTypeMapper = syOccupationInterstTypeMapper; this.syPhilosophyViewMajorMapper = syPhilosophyViewMajorMapper; this.syPhilosophyViewTypeMapper = syPhilosophyViewTypeMapper; this.syTestAnswersMapper = syTestAnswersMapper; this.syTestExamineeMapper = syTestExamineeMapper; this.syTestPaperMapper = syTestPaperMapper; this.syTestQuestionMapper = syTestQuestionMapper; this.syTestSelectCategoryMapper = syTestSelectCategoryMapper; this.syTestSelectMajorMapper = syTestSelectMajorMapper; this.examUtilService = examUtilService; this.redisCache = redisCache; } public Set loadMarjorCodes() { if(null == marjorCodeSet) { // marjorCodeSet = syMajorMajorMapper.selectSyMajorMajorList(new SyMajorMajor()).stream().map( t -> t.getMajorCode()).collect(Collectors.toSet()); marjorCodeSet = majorMapper.selectSyMajorList(new SyMajor()).stream().map( t -> t.getCode()).collect(Collectors.toSet()); } return marjorCodeSet; } public List getTestListWithStatus(Integer testType, Integer[] states) { Map cond = Maps.newHashMap(); cond.put("paperId", testType.longValue()); cond.put("customerCode", SecurityUtils.getLoginUser().getUser().getUserId().toString()); cond.put("states", states); return syTestExamineeMapper.selectSyTestExamineeLatest(cond); } public List getTestList(Integer testType) { SyTestExaminee cond = new SyTestExaminee(); cond.setPaperId(testType.longValue()); cond.setCustomerCode(SecurityUtils.getLoginUser().getUser().getUserId().toString()); return syTestExamineeMapper.selectSyTestExamineeList(cond); } public SyTestExaminee getTestExaminee(Integer testType, Long examineeId) { SyTestExaminee examinee = syTestExamineeMapper.selectSyTestExamineeById(examineeId); return examinee; } public List toTestMatchStats(SyTestExaminee examinee) { if (StringUtils.isNotBlank(examinee.getStats())) { TestMarjorDto.TestStats testStat = null; try { testStat = om.readValue(examinee.getStats(), TestMarjorDto.TestStats.class); return testStat.getMatchStats(); } catch (JsonProcessingException e) { e.printStackTrace(); } } return Lists.newArrayList(); } public AjaxResult saveUserSelectedCategory(CategoryDto.UserCategory params) { SysUser sysUser = SecurityUtils.getLoginUser().getUser(); SyTestExaminee examinee = null != params.getExamineeId() ? syTestExamineeMapper.selectSyTestExamineeById(params.getExamineeId()) : getLatestExaminee(params.getTestType(), sysUser.getCode()); SyTestSelectCategory categoryCond = new SyTestSelectCategory(); categoryCond.setExamineeId(examinee.getExamineeId()); List categoryList = syTestSelectCategoryMapper.selectSyTestSelectCategoryList(categoryCond); Map oldCategoryMap = categoryList.stream().collect(Collectors.toMap(SyTestSelectCategory::getMajorCategoryCode, Function.identity())); SyTestSelectCategory mxjbCategoryCond = new SyTestSelectCategory(); for(String code : Sets.newHashSet(params.getCodes())) { SyTestSelectCategory oldCategory = oldCategoryMap.remove(code); if (null != oldCategory) { mxjbCategoryCond.setId(oldCategory.getId()); mxjbCategoryCond.setState(1L); syTestSelectCategoryMapper.updateSyTestSelectCategory(mxjbCategoryCond); } else { mxjbCategoryCond.setId(null); mxjbCategoryCond.setState(1L); mxjbCategoryCond.setExamineeId(examinee.getExamineeId()); mxjbCategoryCond.setCustomerCode(examinee.getCustomerCode()); mxjbCategoryCond.setMajorCategoryCode(code); syTestSelectCategoryMapper.insertSyTestSelectCategory(mxjbCategoryCond); } } if (oldCategoryMap.size() > 0) { List oldIds = oldCategoryMap.values().stream().map(SyTestSelectCategory::getId).collect(Collectors.toList()); syTestSelectCategoryMapper.deleteSyTestSelectCategoryByIds(oldIds.toArray(new Long[oldIds.size()])); } return AjaxResult.success(); } public AjaxResult getUserSelectedMajor() { SysUser sysUser = SecurityUtils.getLoginUser().getUser(); Map categoryCond = Maps.newHashMap(); categoryCond.put("customerCode", sysUser.getCode()); List categoryList = syMajorCategoryMapper.selectUserSyMajorMajor(categoryCond); return AjaxResult.success(categoryList); } public AjaxResult saveUserSelectedMajor(CategoryDto.UserMajor param) { SysUser sysUser = SecurityUtils.getLoginUser().getUser(); SyTestSelectMajor categoryCond = new SyTestSelectMajor(); categoryCond.setCustomerCode(sysUser.getCode()); Map oldCategoryMap = Maps.newHashMap(); Set existCodeSet = Sets.newHashSet(); List deleteIdList = Lists.newArrayList(); for(SyTestSelectMajor major : syTestSelectMajorMapper.selectSyTestSelectMajorList(categoryCond)) { if (existCodeSet.add(major.getMajorCode())) { oldCategoryMap.put(major.getMajorCode(), major); } else { deleteIdList.add(major.getId()); } } if (deleteIdList.size() > 0) { syTestSelectMajorMapper.deleteSyTestSelectMajorByIds(deleteIdList.toArray(new Long[deleteIdList.size()])); } SyTestSelectMajor mxjbCategoryCond = new SyTestSelectMajor(); for(String code : Sets.newHashSet(param.getCodes())) { SyTestSelectMajor oldCategory = oldCategoryMap.remove(code); if (null != oldCategory) { mxjbCategoryCond.setId(oldCategory.getId()); mxjbCategoryCond.setState(1L); syTestSelectMajorMapper.updateSyTestSelectMajor(mxjbCategoryCond); } else { mxjbCategoryCond.setId(null); mxjbCategoryCond.setState(1L); mxjbCategoryCond.setCustomerCode(sysUser.getCode()); mxjbCategoryCond.setUserId(sysUser.getUserId()); mxjbCategoryCond.setMajorCode(code); syTestSelectMajorMapper.insertSyTestSelectMajor(mxjbCategoryCond); } } if (oldCategoryMap.size() > 0) { List oldIds = oldCategoryMap.values().stream().map(SyTestSelectMajor::getId).collect(Collectors.toList()); syTestSelectMajorMapper.deleteSyTestSelectMajorByIds(oldIds.toArray(new Long[oldIds.size()])); } return AjaxResult.success(); } public AjaxResult loadAllMajorSubjectTree() { Map cond = new HashMap(); List majorCategoryList = syMajorCategoryMapper.selectAllMajorList(cond);; return AjaxResult.success(buildTree(majorCategoryList)); } public AjaxResult loadSelectMajorSubjectTree() { SysUser sysUser = SecurityUtils.getLoginUser().getUser(); SyTestExaminee examineeCond = new SyTestExaminee(); examineeCond.setCustomerCode(sysUser.getCode()); examineeCond.setState(MxjbContants.ExamineeStatusPublish); List existList = syTestExamineeMapper.selectSyTestExamineeList(examineeCond); List examineeIds = existList.stream().map(t -> t.getExamineeId()).collect(Collectors.toList()); if (CollectionUtils.isEmpty(examineeIds)) { return AjaxResult.success(examineeIds); } Map cond = new HashMap(); cond.put("examineeIds", examineeIds); List majorCategoryList = syMajorCategoryMapper.selectSelectedMajorList(cond);; return AjaxResult.success(buildTree(majorCategoryList)); } private List buildTree(List majorCategoryList) { List categoryNodeList = Lists.newArrayList(); if (CollectionUtils.isEmpty(majorCategoryList)) { return categoryNodeList; } Map categoryNodeMap = Maps.newHashMap(); for(SyMajorCategory mc : majorCategoryList) { TestMarjorDto.CategoryNode n = categoryNodeMap.get(mc.getMajorSubjectCode()); if (null == n) { n = new TestMarjorDto.CategoryNode(mc.getMajorSubjectCode(), mc.getMajorSubjectName(), Lists.newArrayList()); categoryNodeMap.put(mc.getMajorSubjectCode(), n); categoryNodeList.add(n); } String snKey = mc.getMajorSubjectCode() + "_" + mc.getMajorCategoryCode(); TestMarjorDto.CategoryNode sn = categoryNodeMap.get(snKey); if (null == sn) { sn = new TestMarjorDto.CategoryNode(mc.getMajorCategoryCode(), mc.getMajorCategoryName(), Lists.newArrayList()); categoryNodeMap.put(snKey, sn); n.getNodes().add(sn); } TestMarjorDto.CategoryNode ssn = new TestMarjorDto.CategoryNode(mc.getMajorCode(), mc.getMajorName(), null); sn.getNodes().add(ssn); } return categoryNodeList.size() != 1 ? categoryNodeList : categoryNodeList.get(0).getNodes(); } private List findMatchCategoryList(Integer testType, String matchCode) { if (StringUtils.isBlank(matchCode)) { return Lists.newArrayList(); } Map cond = new HashMap(); List majorCategoryList = null; switch (testType) { case 1: cond.put("matchCodes", StringUtils.split(matchCode, ",")); majorCategoryList = syMajorCategoryMapper.selectSyMajorCategoryListByView(cond); break; case 2: cond.put("matchCodes", Lists.newArrayList(matchCode)); majorCategoryList = syMajorCategoryMapper.selectSyMajorCategoryListByOccupation(cond); break; case 3: cond.put("matchCodes", StringUtils.split(matchCode, ",")); majorCategoryList = syMajorCategoryMapper.selectSyMajorCategoryListByKnowledge(cond); break; default: majorCategoryList = Lists.newArrayList(); } return majorCategoryList; } public AjaxResult loadMatchCategoryTree(Integer testType, String matchCode, Integer level) { List majorCategoryList = findMatchCategoryList(testType, matchCode); Map categoryNodeMap = Maps.newHashMap(); List categoryNodeList = Lists.newArrayList(); for(SyMajorCategory mc : majorCategoryList) { TestMarjorDto.CategoryNode n = categoryNodeMap.get(mc.getMajorSubjectCode()); if (null == n) { n = new TestMarjorDto.CategoryNode(mc.getMajorSubjectCode(), mc.getMajorSubjectName(), Lists.newArrayList()); categoryNodeMap.put(mc.getMajorSubjectCode(), n); categoryNodeList.add(n); } TestMarjorDto.CategoryNode sn = new TestMarjorDto.CategoryNode(mc.getMajorCategoryCode(), mc.getMajorCategoryName(), null); n.getNodes().add(sn); } return AjaxResult.success(categoryNodeList); } public AjaxResult getAllTestMajorResult() throws JsonProcessingException { Map allResult = new HashMap(); SysUser sysUser = SecurityUtils.getLoginUser().getUser(); Map categoryCond = Maps.newHashMap(); categoryCond.put("customerCode", sysUser.getCode()); List categoryList = syMajorCategoryMapper.selectUserSyMajorMajor(categoryCond); allResult.put("selectedList", categoryList); allResult.put("philosophy", getTestResult(getLatestExaminee(1, sysUser.getCode()))); allResult.put("occupation", getTestResult(getLatestExaminee(2, sysUser.getCode()))); allResult.put("knowledge", getTestResult(getLatestExaminee(3, sysUser.getCode()))); return AjaxResult.success(allResult); } public AjaxResult loadTestMajorResult(Integer testType, String customerCode) throws JsonProcessingException { SyTestExaminee examinee = getLatestExaminee(testType, customerCode); return loadTestMajorResult(examinee); } public AjaxResult loadTestMajorResult(Long examineeId) throws JsonProcessingException { SyTestExaminee examinee = syTestExamineeMapper.selectSyTestExamineeById(examineeId); return loadTestMajorResult(examinee); } public AjaxResult loadTestMajorResult(SyTestExaminee examinee) throws JsonProcessingException { TestMarjorDto.TestResultDto dto; return null == (dto = getTestResult(examinee)) ? AjaxResult.success() : AjaxResult.success(dto); } private TestMarjorDto.TestResultDto getTestResult(SyTestExaminee examinee) throws JsonProcessingException { if (null == examinee) { return null; } boolean testCompleted = examinee.getState() >= MxjbContants.ExamineeStatusPublish; SyTestPaper paper = syTestPaperMapper.selectSyTestPaperById(examinee.getPaperId()); TestMarjorDto.TestStats testStat = null; Map categoryCountMap = Maps.newHashMap(); Map> catKeyValueMap = null; String matchCode = null; boolean noMatch = false; if (StringUtils.isNotBlank(examinee.getStats())) { testStat = om.readValue(examinee.getStats(), TestMarjorDto.TestStats.class); if (CollectionUtils.isNotEmpty(testStat.getMatchStats())) { for (TestMarjorDto.TestMatchStat ts : testStat.getMatchStats()) { categoryCountMap.put(ts.getCode(), ts); } } catKeyValueMap = testStat.getCatKeyValueMap(); matchCode = testStat.getMatchCode(); noMatch = testStat.isNoMatch(); } boolean selectCompleted = noMatch || isSelectCompleted(examinee.getExamineeId()); Map categoryCond = Maps.newHashMap(); categoryCond.put("examineeId", examinee.getExamineeId()); List selectedList = syMajorCategoryMapper.selectUserSyMajorCategory(categoryCond); switch (paper.getCategory()) { case 1: Map viewTypeMap = Maps.newHashMap(); List viewTypeList = syPhilosophyViewTypeMapper.selectSyPhilosophyViewTypeList(new SyPhilosophyViewType()); for (SyPhilosophyViewType type : viewTypeList) { type.setViewMajorList(Lists.newArrayList()); viewTypeMap.put(type.getCode(), type); TestMarjorDto.TestMatchStat ts = categoryCountMap.get(type.getCode()); if (null != ts) { Integer total = ts.getCount(); type.setTotal(null != total ? total : 0); type.setMatched(ts.isMatched()); } else { type.setTotal(0); type.setMatched(false); } if (null != catKeyValueMap) { type.setStats(catKeyValueMap.get(type.getCode())); } } for (SyPhilosophyViewMajor viewMajor : syPhilosophyViewMajorMapper.selectSyPhilosophyViewMajorList(new SyPhilosophyViewMajor())) { viewTypeMap.get(viewMajor.getMatchCode()).getViewMajorList().add(viewMajor); } Collections.sort(viewTypeList, new Comparator() { @Override public int compare(SyPhilosophyViewType o1, SyPhilosophyViewType o2) { int iRet = -o1.getTotal().compareTo(o2.getTotal()); if (0 == iRet) { iRet = o1.getCode().compareTo(o2.getCode()); } return iRet; } }); return new TestMarjorDto.TestResultDto(examinee.getExamineeId(), selectedList, viewTypeList, matchCode, testCompleted, selectCompleted, noMatch); case 2: List occupationTypeList = syOccupationInterstTypeMapper.selectSyOccupationInterstTypeList(new SyOccupationInterstType()); for (SyOccupationInterstType type : occupationTypeList) { TestMarjorDto.TestMatchStat ts = categoryCountMap.get(type.getCode()); if (null != ts) { Integer total = ts.getCount(); type.setTotal(null != total ? total : 0); type.setMatched(ts.isMatched()); } else { type.setTotal(0); type.setMatched(false); } if (null != catKeyValueMap) { type.setStats(catKeyValueMap.get(type.getCode())); } } Collections.sort(occupationTypeList, new Comparator() { @Override public int compare(SyOccupationInterstType o1, SyOccupationInterstType o2) { int iRet = -o1.getTotal().compareTo(o2.getTotal()); if (0 == iRet) { iRet = o1.getCode().compareTo(o2.getCode()); } return iRet; } }); return new TestMarjorDto.TestResultDto(examinee.getExamineeId(), selectedList, occupationTypeList, matchCode, testCompleted, selectCompleted, noMatch); case 3: List knowledgeTypeList = syKnowledgeInterstTypeMapper.selectSyKnowledgeInterstTypeList(new SyKnowledgeInterstType()); for (SyKnowledgeInterstType type : knowledgeTypeList) { TestMarjorDto.TestMatchStat ts = categoryCountMap.get(type.getId().toString()); if (null != ts) { Integer total = ts.getCount(); type.setTotal(null != total ? total : 0); type.setMatched(ts.isMatched()); } else { type.setTotal(0); type.setMatched(false); } } Collections.sort(knowledgeTypeList, new Comparator() { @Override public int compare(SyKnowledgeInterstType o1, SyKnowledgeInterstType o2) { int iRet = -o1.getTotal().compareTo(o2.getTotal()); if (0 == iRet) { iRet = o1.getCode().compareTo(o2.getCode()); } return iRet; } }); return new TestMarjorDto.TestResultDto(examinee.getExamineeId(), selectedList, knowledgeTypeList, matchCode, testCompleted, selectCompleted, noMatch); } return null; } private TestMarjorDto.TestStats getStats(Integer testType, Long paperId, List questionlist) { SyTestQuestion cond = new SyTestQuestion(); cond.setPaperId(paperId); Map stdQuestionMap = syTestQuestionMapper.selectSyTestQuestionList(cond).stream().collect(Collectors.toMap(SyTestQuestion::getQuestionId, Function.identity())); TestMarjorDto.TestStats testStats = new TestMarjorDto.TestStats(); // key1=category, key2=value, value=score Map> catKeyValueMap = null; List matchStats = null; String matchedCode = null; boolean noMatch = false; switch (testType) { case 1: // k1=value(A/B/D/F), k2=questionCategory, value=按answer求和, 复选总分(限制总分不重复, 3), 复选评价(限制总分不重复, 6) catKeyValueMap = Maps.newHashMap(); matchStats = Lists.newArrayList(); for (QuestionDto ques : questionlist) { String normalAnswer = MxjbContants.getNormalAnswer(ques.getAnswer(), ""); if (StringUtils.isBlank(normalAnswer)) { continue; } SyTestQuestion stdQuestion = stdQuestionMap.get(ques.getQuestionId()); if(StringUtils.isNotBlank(normalAnswer)) { String[] answerScores = normalAnswer.split(","); for (int i = 0; i < answerScores.length; i++) { Integer cnt = Integer.parseInt(answerScores[i]); String newValue = getAnswerValue(stdQuestion, i); if (StringUtils.isNotBlank(newValue)) { Map valueMap = catKeyValueMap.get(newValue); if (null == valueMap) { valueMap = Maps.newHashMap(); catKeyValueMap.put(newValue, valueMap); } Integer oldCount = valueMap.get(stdQuestion.getQuesitonCateogry()); valueMap.put(stdQuestion.getQuesitonCateogry(), null != oldCount ? oldCount + cnt : cnt); } } } } for (String category : catKeyValueMap.keySet()) { TestMarjorDto.TestMatchStat testMatchStat = new TestMarjorDto.TestMatchStat(); testMatchStat.setCode(category); Integer sum = 0; for (Integer v : catKeyValueMap.get(category).values()) { sum += v; } testMatchStat.setCount(sum); testMatchStat.setMatched(false); matchStats.add(testMatchStat); } Collections.sort(matchStats, new Comparator() { @Override public int compare(TestMarjorDto.TestMatchStat o1, TestMarjorDto.TestMatchStat o2) { return -o1.getCount().compareTo(o2.getCount()); } }); matchedCode = getMatchedCodeByTop(matchStats, 3); break; case 2: // k1=questionCategory, k2=value(Like/Familiar), value=对应个数 catKeyValueMap = Maps.newHashMap(); matchStats = Lists.newArrayList(); String newValue; for (QuestionDto ques : questionlist) { SyTestQuestion stdQuestion = stdQuestionMap.get(ques.getQuestionId()); String normalAnswer = MxjbContants.getNormalAnswer(ques.getAnswer(), ""); if (StringUtils.isNotBlank(normalAnswer) && StringUtils.isNotBlank((newValue = getAnswerValue(stdQuestion, normalAnswer.charAt(0) - 'A')))) {; Map valueMap = catKeyValueMap.get(stdQuestion.getQuesitonCateogry()); if (null == valueMap) { valueMap = Maps.newHashMap(); catKeyValueMap.put(stdQuestion.getQuesitonCateogry(), valueMap); } String valueName = "Like".equals(newValue) ? "喜欢" : "擅长"; // 最多7个 Integer oldCount = valueMap.get(valueName); valueMap.put(valueName, null != oldCount ? Math.min(oldCount + 1, 7) : 1); } } for (String category : catKeyValueMap.keySet()) { TestMarjorDto.TestMatchStat testMatchStat = new TestMarjorDto.TestMatchStat(); testMatchStat.setCode(category); Integer sum = 0; for (Integer v : catKeyValueMap.get(category).values()) { sum += v; } testMatchStat.setCount(sum); testMatchStat.setMatched(false); matchStats.add(testMatchStat); } Collections.sort(matchStats, new Comparator() { @Override public int compare(TestMarjorDto.TestMatchStat o1, TestMarjorDto.TestMatchStat o2) { return -o1.getCount().compareTo(o2.getCount()); } }); List matchCodeList = Lists.newArrayList(); noMatch = getMatchedCode(matchStats, matchCodeList); matchedCode = StringUtils.join(matchCodeList, ","); break; case 3: // id 对应 questionCategory, value 对应分值 Map keyValueMap = Maps.newHashMap(); for (QuestionDto ques : questionlist) { SyTestQuestion stdQuestion = stdQuestionMap.get(ques.getQuestionId()); Integer oldValue = keyValueMap.get(stdQuestion.getQuesitonCateogry()); String normalAnswer = MxjbContants.getNormalAnswer(ques.getAnswer(), ""); if (StringUtils.isNotBlank(normalAnswer)) { keyValueMap.put(stdQuestion.getQuesitonCateogry(), Integer.parseInt(getAnswerValue(stdQuestion, normalAnswer.charAt(0) - 'A')) + (null != oldValue ? oldValue : 0)); } } matchStats = Lists.newArrayList(); for (String category : keyValueMap.keySet()) { TestMarjorDto.TestMatchStat testMatchStat = new TestMarjorDto.TestMatchStat(); testMatchStat.setCode(category); testMatchStat.setCount(keyValueMap.get(category)); testMatchStat.setMatched(false); matchStats.add(testMatchStat); } Collections.sort(matchStats, new Comparator() { @Override public int compare(TestMarjorDto.TestMatchStat o1, TestMarjorDto.TestMatchStat o2) { return -o1.getCount().compareTo(o2.getCount()); } }); matchedCode = getMatchedCodeByTop(matchStats, 3); break; } testStats.setCatKeyValueMap(catKeyValueMap); testStats.setMatchStats(matchStats); testStats.setMatchCode(matchedCode); testStats.setNoMatch(StringUtils.isNotBlank(matchedCode) && (noMatch || CollectionUtils.isEmpty(findMatchCategoryList(testType, matchedCode)))); return testStats; } /** * 根据用户选择查询对应的值 * @param stdQuestion * @param optionIdx * @return */ private String getAnswerValue(SyTestQuestion stdQuestion, int optionIdx) { switch(optionIdx) { case 0: return stdQuestion.getValueA(); case 1: return stdQuestion.getValueB(); case 2: return stdQuestion.getValueC(); case 3: return stdQuestion.getValueD(); case 4: return stdQuestion.getValueE(); } return ""; } public List getPaperQuestions(Long paperId) { SyTestQuestion cond = new SyTestQuestion(); cond.setPaperId(paperId); List questionsList = syTestQuestionMapper.selectSyTestQuestionList(cond); return questionsList; } public AjaxResult saveTestPaper(PaperDto paperDto) { Long examineeId = paperDto.getExamineeId(); SyTestExaminee examinee = syTestExamineeMapper.selectSyTestExamineeById(examineeId); if (examinee.getState() >= MxjbContants.ExamineeStatusReview) { return AjaxResult.error(examineeId + " 已经在批阅的不可保存答案"); } String key = examUtilService.getExamineeAnswersKey(MxjbContants.ExamineeTypeTestKey, paperDto.getExamineeId()); if (CollectionUtils.isEmpty(paperDto.getQuestions())) { Map questionDtoMap = redisCache.getCacheMap(key); questionDtoMap.remove("0"); paperDto.setQuestions(Lists.newArrayList(questionDtoMap.values())); } if (CollectionUtils.isEmpty(paperDto.getQuestions()) || getPaperQuestions(examinee.getPaperId()).size() != paperDto.getQuestions().size()) { return AjaxResult.error(examineeId + "未答完题时不能保存"); } SyTestPaper paper = syTestPaperMapper.selectSyTestPaperById(examinee.getPaperId()); updateTestAnswers(paperDto.getQuestions(), paperDto.getExamineeId()); SyTestExaminee examineeCond = new SyTestExaminee(); examineeCond.setExamineeId(paperDto.getExamineeId()); examineeCond.setState(MxjbContants.ExamineeStatusPublish); examineeCond.setEndTime(new Date()); TestMarjorDto.TestStats testStats = examinee.getPaperId().equals(4L) ? getMentalHealth(paperDto.getQuestions()) : getStats(paper.getCategory(), paper.getPaperId(), paperDto.getQuestions()); try { examineeCond.setStats(om.writeValueAsString(testStats)); } catch (JsonProcessingException e) { return AjaxResult.error(examineeId + " 已经在批阅的不可保存答案"); } syTestExamineeMapper.updateSyTestExaminee(examineeCond); redisCache.deleteObject(key); return AjaxResult.success("成功"); } public AjaxResult updateExamineeStats(Long examineeId) { SyTestExaminee examinee = syTestExamineeMapper.selectSyTestExamineeById(examineeId); SyTestPaper paper = syTestPaperMapper.selectSyTestPaperById(examinee.getPaperId()); SyTestAnswers answerCond = new SyTestAnswers(); answerCond.setExamineeId(examineeId); List questionlist = Lists.newArrayList(); List answersList = syTestAnswersMapper.selectSyTestAnswersList(answerCond); for(SyTestAnswers a : answersList) { QuestionDto dto = new QuestionDto(); dto.setQuestionId(a.getQuestionId()); dto.setAnswer(a.getAnswer()); questionlist.add(dto); } SyTestExaminee examineeCond = new SyTestExaminee(); examineeCond.setExamineeId(examinee.getExamineeId()); TestMarjorDto.TestStats testStats = examinee.getPaperId().equals(4L) ? getMentalHealth(questionlist) : getStats(paper.getCategory(), paper.getPaperId(), questionlist); try { examineeCond.setStats(om.writeValueAsString(testStats)); } catch (JsonProcessingException e) { return AjaxResult.error(examineeId + " 统计序列化异常"); } syTestExamineeMapper.updateSyTestExaminee(examineeCond); return AjaxResult.success(); } private TestMarjorDto.TestStats getMentalHealth(List questionlist) { SyTestQuestion cond = new SyTestQuestion(); cond.setPaperId(4L); Map stdQuestionMap = Maps.newHashMap(); Map categoryValueMap = Maps.newLinkedHashMap(); for (SyTestQuestion q : syTestQuestionMapper.selectSyTestQuestionList(cond)) { stdQuestionMap.put(q.getQuestionId(), q); categoryValueMap.putIfAbsent(q.getQuesitonCateogry(), 0); } for (QuestionDto ques : questionlist) { String normalAnswer = MxjbContants.getNormalAnswer(ques.getAnswer(), ""); if (StringUtils.isBlank(normalAnswer)) { continue; } SyTestQuestion stdQuestion = stdQuestionMap.get(ques.getQuestionId()); if(StringUtils.isNotBlank(normalAnswer)) { String value = normalAnswer.equals("A") ? stdQuestion.getValueA() : stdQuestion.getValueB(); Integer v = NumberUtils.toInt(value, 0); String c = stdQuestion.getQuesitonCateogry(); Integer ov = categoryValueMap.get(c); categoryValueMap.put(c, null != ov ? ov + v : v); } } TestMarjorDto.TestStats testStats = new TestMarjorDto.TestStats(); List matchStats = Lists.newArrayList(); for (String name : categoryValueMap.keySet()) { matchStats.add(new TestMarjorDto.TestMatchStat(name, categoryValueMap.get(name), false)); } testStats.setMatchStats(matchStats); return testStats; } private String getMatchedCodeByTop(List matchStats, Integer top) { if (CollectionUtils.isEmpty(matchStats)) { return ""; } List matchCodeList = Lists.newArrayList(); for (TestMarjorDto.TestMatchStat ts : matchStats) { matchCodeList.add(ts.getCode()); ts.setMatched(true); if (matchCodeList.size() == top) { break; } } return StringUtils.join(matchCodeList, ","); } private boolean getMatchedCode(List matchStats, List codeList) { if (CollectionUtils.isEmpty(matchStats)) { return true; } Set validCodeSet = syOccupationInterstMajorMapper.selectSyOccupationInterstMajorList(new SyOccupationInterstMajor()).stream().map(t -> t.getMatchCode()).collect(Collectors.toSet()); TestMarjorDto.TestMatchStat ts1 = matchStats.get(0); TestMarjorDto.TestMatchStat ts2 = null ; String code; if (matchStats.size() == 1 || (ts1.getCount() - (ts2 = matchStats.get(1)).getCount()) > 4) { // 只有一个或可忽略第二个时 ts1.setMatched(true); code = ts1.getCode() + "**"; } else { TestMarjorDto.TestMatchStat ts3 = null ; String code2; if (matchStats.size() == 2 || (ts2.getCount() - (ts3 = matchStats.get(2)).getCount()) > 4) { // 只有两个或忽略第3个时 ts1.setMatched(true); ts2.setMatched(true); code = ts1.getCode() + ts2.getCode() + "*"; if (!validCodeSet.contains(code)) { if (ts1.getCount() == ts2.getCount() && validCodeSet.contains((code2 = ts2.getCode() + ts1.getCode() + "*"))) { matchStats.add(0, matchStats.remove(1)); // 交换 12位置 code = code2; } else if (validCodeSet.contains((code2 = ts1.getCode() + "**"))) { // 降级 code = code2; } else if (validCodeSet.contains((code2 = ts2.getCode() + "**"))) { matchStats.add(0, matchStats.remove(1)); code = code2; } } } else { code = ts1.getCode() + ts2.getCode() + ts3.getCode(); List needMatchStats = Lists.newArrayList(); List remainMatchStats; if (ts2.getCount() > ts3.getCount()) { // ts2 固定 remainMatchStats = splitStats(matchStats, 2, ts3.getCount(), needMatchStats); if (null != (code2 = matchStatsTry(validCodeSet, matchStats, needMatchStats))) { code = code2; } else { matchStats.addAll(needMatchStats); if (validCodeSet.contains((code2 = ts1.getCode() + ts2.getCode() + "*"))) { code = code2; } else if (validCodeSet.contains((code2 = ts1.getCode() + "**"))) { code = code2; } } matchStats.addAll(remainMatchStats); } else { // ts2 == ts3 remainMatchStats = splitStats(matchStats, 1, ts2.getCount(), needMatchStats); if (ts1.getCount() == ts2.getCount()) { // 3 of needMatchStats needMatchStats.add(0, matchStats.remove(0)); } // t1 + 2 of needMatchStats if (null != (code2 = matchStatsTry(validCodeSet, matchStats, needMatchStats))) { code = code2; } else { if (matchStats.size() == 0) { code = needMatchStats.get(0).getCode() + "**"; } else { code = matchStats.get(0).getCode() + "**"; } matchStats.addAll(needMatchStats); } matchStats.addAll(remainMatchStats); } } } codeList.add(code); return !validCodeSet.contains(code); } private String matchStatsTry(Set validCodeSet, List matchStats, List needMatchStats) { String code = null; if (matchStats.size() == 0) { // 任意组合3个 List> permutaionList = Lists.newArrayList(); buildPermutation(needMatchStats.toArray(new TestMarjorDto.TestMatchStat[needMatchStats.size()]), 3, Lists.newArrayList(), Sets.newHashSet(), permutaionList); for (List tsList : permutaionList) { TestMarjorDto.TestMatchStat ts1 = tsList.get(0); TestMarjorDto.TestMatchStat ts2 = tsList.get(1); TestMarjorDto.TestMatchStat ts3 = tsList.get(2); if (validCodeSet.contains((code = ts1.getCode() + ts2.getCode() + ts3.getCode()))) { matchStats.addAll(tsList); return combineMatch(code, ts1, ts2, ts3); } } } else if(matchStats.size() == 1) { // 任意组合2个 TestMarjorDto.TestMatchStat ts1 = matchStats.get(0); List> permutaionList = Lists.newArrayList(); buildPermutation(needMatchStats.toArray(new TestMarjorDto.TestMatchStat[needMatchStats.size()]), 2, Lists.newArrayList(), Sets.newHashSet(), permutaionList); for (List matchStatList : permutaionList) { TestMarjorDto.TestMatchStat ts2 = matchStatList.get(0); TestMarjorDto.TestMatchStat ts3 = matchStatList.get(1); if (validCodeSet.contains((code = ts1.getCode() + ts2.getCode() + ts3.getCode()))) { matchStats.addAll(matchStatList); return combineMatch(code, ts1, ts2, ts3); } } } else { // 前两个可能交换 TestMarjorDto.TestMatchStat ts1 = matchStats.get(0); TestMarjorDto.TestMatchStat ts2 = matchStats.get(1); for (TestMarjorDto.TestMatchStat ts3 : needMatchStats) { if (validCodeSet.contains((code = ts1.getCode() + ts2.getCode() + ts3.getCode()))) { matchStats.add(ts3); return combineMatch(code, ts1, ts2, ts3); } else if (ts1.getCount() == ts2.getCount()) { if (validCodeSet.contains((code = ts1.getCode() + ts2.getCode() + ts3.getCode()))) { matchStats.add(0, matchStats.remove(1)); // 交换 12位置 matchStats.add(ts3); return combineMatch(code, ts1, ts2, ts3); } } } } return null; } private String combineMatch(String code, TestMarjorDto.TestMatchStat ts1, TestMarjorDto.TestMatchStat ts2, TestMarjorDto.TestMatchStat ts3) { ts1.setMatched(true); ts2.setMatched(true); ts3.setMatched(true); return code; } private void buildPermutation(TestMarjorDto.TestMatchStat[] matchStats, Integer matchCount, List baseStats, Set usedIndexSet, List> permutaionList) { boolean lastCount = matchCount == baseStats.size() + 1; for (int i = 0; i < matchStats.length; i++) { if (usedIndexSet.add(i)) { List foundList = Lists.newArrayList(baseStats); foundList.add(matchStats[i]); if (lastCount) { permutaionList.add(foundList); } else { buildPermutation(matchStats, matchCount, foundList, usedIndexSet, permutaionList); } usedIndexSet.remove(i); } } } /** * 从除列中删除指定位置后的,并根据count分成两组 * @param matchStats * @param index * @param matchCount * @param needMatchStats * @return */ private List splitStats(List matchStats, Integer index, Integer matchCount, List needMatchStats) { List remainMatchStats = Lists.newArrayList(); for (int i = index; i < matchStats.size(); ) { TestMarjorDto.TestMatchStat ts = matchStats.remove(i); if (ts.getCount().equals(matchCount)) { needMatchStats.add(ts); } else { remainMatchStats.add(ts); } } return remainMatchStats; } public void updateTestAnswers(List questions, Long examineeId) { SyTestExaminee examinee = syTestExamineeMapper.selectSyTestExamineeById(examineeId); SyTestAnswers answerCond = new SyTestAnswers(); answerCond.setExamineeId(examineeId); List answersList = syTestAnswersMapper.selectSyTestAnswersList(answerCond); Map oldQuestionAnswersMap = answersList.stream().collect(Collectors.toMap(SyTestAnswers::getQuestionId, Function.identity())); Map newQuestionAnswerMap = questions.stream().collect(Collectors.toMap(QuestionDto::getQuestionId, Function.identity())); SyTestQuestion questionCond = new SyTestQuestion(); questionCond.setPaperId(examinee.getPaperId()); List stdQuestionList = syTestQuestionMapper.selectSyTestQuestionList(questionCond); SyTestAnswers mxjbAnswersCond = new SyTestAnswers(); stdQuestionList.forEach(t -> { SyTestAnswers oldAnswer = oldQuestionAnswersMap.remove(t.getQuestionId()); QuestionDto newAnswer = newQuestionAnswerMap.get(t.getQuestionId()); if (null != newAnswer) { mxjbAnswersCond.setAnswer(newAnswer.getAnswer() + "$@" + StringUtils.join(newAnswer.getAttachments(), "$@")); mxjbAnswersCond.setDuration(newAnswer.getDuration()); } else { mxjbAnswersCond.setAnswer(null); mxjbAnswersCond.setDuration(-1L); } if (null != oldAnswer) { mxjbAnswersCond.setAnswerId(oldAnswer.getAnswerId()); mxjbAnswersCond.setExamineeId(null); mxjbAnswersCond.setExamineeType(null); mxjbAnswersCond.setQuestionId(null); mxjbAnswersCond.setSeq(null); syTestAnswersMapper.updateSyTestAnswers(mxjbAnswersCond); } else { mxjbAnswersCond.setAnswerId(null); mxjbAnswersCond.setExamineeId(examineeId); mxjbAnswersCond.setExamineeType(MxjbContants.ExamineeTypeTest); mxjbAnswersCond.setQuestionId(t.getQuestionId()); mxjbAnswersCond.setSeq(t.getSeq()); syTestAnswersMapper.insertSyTestAnswers(mxjbAnswersCond); } }); if (oldQuestionAnswersMap.size() > 0) { List oldIds = oldQuestionAnswersMap.values().stream().map(SyTestAnswers::getAnswerId).collect(Collectors.toList()); syTestAnswersMapper.deleteSyTestAnswersByIds(oldIds.toArray(new Long[oldIds.size()])); } } public PaperDto loadPaperByTestMajorTypeId(Integer testType) { Long paperId = testType.longValue(); SysUser sysUser = SecurityUtils.getLoginUser().getUser(); SyTestExaminee mxjbExaminee = getLatestExaminee(testType, sysUser.getCode()); SyTestPaper syTestPaper = syTestPaperMapper.selectSyTestPaperById(paperId.longValue()); if (null != mxjbExaminee && (mxjbExaminee.getState() < MxjbContants.ExamineeStatusPublish)) { // 未测试完成的先继续测试 PaperDto paperDto = loadPaperDto(syTestPaper, mxjbExaminee, true); if (MxjbContants.ExamineeStatusExamine.equals(mxjbExaminee.getState())) { examUtilService.updateTempAnswerAndSave(paperDto, mxjbExaminee.getExamineeId(), MxjbContants.ExamineeTypeTest); } return paperDto; } if (null != mxjbExaminee) { if (4 != testType && !isSelectCompleted(mxjbExaminee)) { // 测试完成但未选择的先选择 throw new RuntimeException("请选选择专业类,完成本轮测试, 再进行下一轮"); } // 关闭上一轮的测试,进入下一轮 SyTestExaminee examineeUpdate = new SyTestExaminee(); examineeUpdate.setExamineeId(mxjbExaminee.getExamineeId()); examineeUpdate.setState(MxjbContants.ExamineeStatusClose); syTestExamineeMapper.updateSyTestExaminee(examineeUpdate); } SyTestExaminee examineeCond = new SyTestExaminee(); PaperDto paperDto = loadPaperDto(syTestPaper, null, false); if (MxjbContants.ExamineeStatusSign.equals(paperDto.getState())) { paperDto.setRemaining(paperDto.getMode() * 60); paperDto.setMinutes(paperDto.getRemaining() / 60); paperDto.setState(MxjbContants.ExamineeStatusExamine); examineeCond.setPaperId(paperId); examineeCond.setCustomerCode(sysUser.getCode()); examineeCond.setState(paperDto.getState()); examineeCond.setBeginTime(paperDto.getBeginTime()); examineeCond.setEndTime(paperDto.getEndTime()); examineeCond.setScoreLevel("W"); examineeCond.setScore(0L); examineeCond.setScoreRate(0.0); examineeCond.setRanking(0L); syTestExamineeMapper.insertSyTestExaminee(examineeCond); paperDto.setExamineeId(examineeCond.getExamineeId()); } paperDto.getQuestions().get(0).setCurrent(true); return paperDto; } public PaperDto loadPaperByExaminerId(Long examineeId) { SyTestExaminee mxjbExaminee = syTestExamineeMapper.selectSyTestExamineeById(examineeId); if (null == mxjbExaminee) { throw new RuntimeException("无测试人员"); } SyTestPaper syTestPaper = syTestPaperMapper.selectSyTestPaperById(mxjbExaminee.getPaperId()); PaperDto paperDto = loadPaperDto(syTestPaper, mxjbExaminee, true); return paperDto; } private PaperDto loadPaperDto(SyTestPaper syTestPaper, SyTestExaminee examinee, boolean loadParse) { PaperDto paperDto = new PaperDto(); SyTestQuestion cond = new SyTestQuestion(); cond.setPaperId(syTestPaper.getPaperId()); List questionsList = syTestQuestionMapper.selectSyTestQuestionList(cond); paperDto.setExamineeType(MxjbContants.ExamineeTypeTestValue); paperDto.setName(syTestPaper.getName()); paperDto.setPaperId(syTestPaper.getPaperId()); paperDto.setScoringType(MxjbContants.ScoringTypeAuto); paperDto.setPublish(true); paperDto.setMode(99*60L); // TODO 竞赛要设置时间 paperDto.setEvaluationState(MxjbContants.EvaluationStatusOpen); paperDto.setBeginTime(new Date()); paperDto.setEndTime(DateUtils.addMinutes(paperDto.getBeginTime(), paperDto.getMode().intValue())); if (null == examinee) { // 没有考生 paperDto.setMinutes(0L); paperDto.setRemaining(0L); paperDto.setState(MxjbContants.ExamineeStatusSign); } else { paperDto.setState(examinee.getState()); if (examinee.getState() >= MxjbContants.ExamineeStatusPublish) { paperDto.setBeginTime(examinee.getBeginTime()); paperDto.setEndTime(examinee.getEndTime()); paperDto.setRemaining(0L); } else { paperDto.setRemaining(paperDto.getMode() * 60); } paperDto.setMinutes(paperDto.getRemaining() / 60); paperDto.setExamineeId(examinee.getExamineeId()); } final Map questionAnswersMap; if(paperDto.getState() >= MxjbContants.ExamineeStatusExamine) { SyTestAnswers answerCond = new SyTestAnswers(); answerCond.setExamineeId(examinee.getExamineeId()); answerCond.setExamineeType(MxjbContants.ExamineeTypeTest); questionAnswersMap = syTestAnswersMapper.selectSyTestAnswersList(answerCond).stream().collect(Collectors.toMap(SyTestAnswers::getQuestionId, Function.identity())); } else { questionAnswersMap = null; } Boolean fillParseAndAnswer = loadParse || MxjbContants.ExamineeStatusPublish.equals(paperDto.getState()) // 自阅卷或发布时可显示成绩 || MxjbContants.ExamineeStatusReview.equals(paperDto.getState()); List questionDtoList = paperDto.getQuestions(); questionsList.forEach(t -> { QuestionDto dto = examUtilService.toQuestionDto(t, fillParseAndAnswer, questionAnswersMap); dto.setSeq(questionDtoList.size() + 1L); questionDtoList.add(dto); }); return paperDto; } public boolean isSelectCompleted(SyTestExaminee mxjbExaminee) { boolean noMatch = false; if (StringUtils.isNotBlank(mxjbExaminee.getStats())) { TestMarjorDto.TestStats testStat = null; try { testStat = om.readValue(mxjbExaminee.getStats(), TestMarjorDto.TestStats.class); noMatch = testStat.isNoMatch(); } catch (JsonProcessingException e) { e.printStackTrace(); } } return noMatch || isSelectCompleted(mxjbExaminee.getExamineeId()); } private boolean isSelectCompleted(Long examineeId) { SyTestSelectCategory selectCategoryCond = new SyTestSelectCategory(); selectCategoryCond.setExamineeId(examineeId); boolean selectCompleted = CollectionUtils.isNotEmpty(syTestSelectCategoryMapper.selectSyTestSelectCategoryList(selectCategoryCond)); return selectCompleted; } private SyTestExaminee getLatestExaminee(Integer testType, String customerCode) { Long paperId = testType.longValue(); Map cond = Maps.newHashMap(); cond.put("paperId", paperId); cond.put("customerCode", customerCode); cond.put("cnt", 1); List existList = syTestExamineeMapper.selectSyTestExamineeLatest(cond); return CollectionUtils.isNotEmpty(existList) ? existList.get(0) : null; } }