package com.ruoyi.web.service; import com.alibaba.fastjson2.JSONArray; import com.alibaba.fastjson2.JSONException; import com.alibaba.fastjson2.JSONObject; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.DeserializationFeature; 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.content.VistorContextHolder; import com.ruoyi.common.core.domain.R; import com.ruoyi.common.core.domain.entity.SysUser; import com.ruoyi.common.core.page.TableDataInfo; import com.ruoyi.common.enums.ExamType; import com.ruoyi.common.enums.SubjectType; import com.ruoyi.common.exception.ServiceException; import com.ruoyi.common.utils.SecurityUtils; import com.ruoyi.common.utils.StringUtils; import com.ruoyi.common.utils.dz.SubjectScore; import com.ruoyi.ie.domain.*; import com.ruoyi.ie.mapper.*; import com.ruoyi.system.service.ISysConfigService; import com.ruoyi.syzy.domain.BBusiWishUniversities; import com.ruoyi.syzy.domain.BBusiWishUniversitiesProfession; import com.ruoyi.syzy.dto.UniversityDetailDTO; import com.ruoyi.syzy.mapper.BBusiWishRecordsMapper; import com.ruoyi.syzy.mapper.BBusiWishUniversitiesMapper; import com.ruoyi.syzy.mapper.BBusiWishUniversitiesProfessionMapper; import com.ruoyi.util.PageUtil; import com.ruoyi.web.domain.Constant; import com.ruoyi.web.domain.VoluntaryDto; import io.swagger.annotations.ApiModelProperty; import io.swagger.annotations.ApiParam; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.MapUtils; import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.lang3.math.NumberUtils; import org.apache.commons.lang3.tuple.MutablePair; import org.apache.commons.lang3.tuple.Pair; import org.springframework.stereotype.Service; import org.springframework.web.bind.annotation.RequestParam; import java.text.SimpleDateFormat; import java.util.*; import java.util.function.Function; import java.util.stream.Collectors; import java.util.stream.Stream; @Service public class VoluntaryService { private ObjectMapper mapper = new ObjectMapper(); private static TypeReference> wishDetailsTypeReference = new TypeReference>() { }; private static TypeReference> wishAiDetailsTypeReference = new TypeReference>() { }; Set NumberTypeSet = Sets.newHashSet(VoluntaryDto.EnumInputType.Number.name(), VoluntaryDto.EnumInputType.Eyesight.name(), VoluntaryDto.EnumInputType.Score.name()); private static VoluntaryRuleHelper voluntaryRuleHelper = new VoluntaryRuleHelper(); private final AWishRecordMapper aWishRecordMapper; private final AEnrollScoreMapper aEnrollScoreMapper; private final AEnrollSpecialMapper aEnrollSpecialMapper; private final AMarjorPlanMapper aMarjorPlanMapper; private final AMarjorSubmitMapper aMarjorSubmitMapper; private final AEnrollUniversityMapper aEnrollUniversityMapper; private final BBusiWishUniversitiesMapper bBusiWishUniversitiesMapper; private final BBusiWishUniversitiesProfessionMapper bBusiWishUniversitiesProfessionMapper; private final ISysConfigService sysConfigService; private final EnrollRateCalculator enrollRateCalculator; private final BBusiWishRecordsMapper busiWishRecordsMapper; public VoluntaryService(AWishRecordMapper aWishRecordMapper, AEnrollScoreMapper aEnrollScoreMapper, AEnrollSpecialMapper aEnrollSpecialMapper, AMarjorPlanMapper aMarjorPlanMapper, AMarjorSubmitMapper aMarjorSubmitMapper, AEnrollUniversityMapper aEnrollUniversityMapper, BBusiWishUniversitiesMapper bBusiWishUniversitiesMapper, BBusiWishUniversitiesProfessionMapper bBusiWishUniversitiesProfessionMapper, ISysConfigService sysConfigService, EnrollRateCalculator enrollRateCalculator, BBusiWishRecordsMapper busiWishRecordsMapper) { this.aWishRecordMapper = aWishRecordMapper; this.aEnrollScoreMapper = aEnrollScoreMapper; this.aEnrollSpecialMapper = aEnrollSpecialMapper; this.aMarjorPlanMapper = aMarjorPlanMapper; this.aMarjorSubmitMapper = aMarjorSubmitMapper; this.aEnrollUniversityMapper = aEnrollUniversityMapper; this.bBusiWishUniversitiesMapper = bBusiWishUniversitiesMapper; this.bBusiWishUniversitiesProfessionMapper = bBusiWishUniversitiesProfessionMapper; this.sysConfigService = sysConfigService; this.enrollRateCalculator = enrollRateCalculator; this.busiWishRecordsMapper = busiWishRecordsMapper; // mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); } public Pair, List> getUniversityHistory(Long universityId, String province, String examineType) { AMarjorPlan planCond = new AMarjorPlan(); planCond.setUniversityId(universityId); planCond.setExamineeType(examineType); List planList = aMarjorPlanMapper.selectAMarjorPlanList(planCond).stream().map(t -> { UniversityDetailDTO.WishPlan p = new UniversityDetailDTO.WishPlan(); p.setId(t.getId()); p.setCollegeCode(t.getEnrollCode()); p.setYear(String.valueOf(t.getYear())); p.setLevel(t.getLevel()); p.setType(""); p.setMarjorCode(t.getMajorCode()); p.setMarjorName(t.getMajorName()); p.setMarjorBelongs(t.getMajorEnrollCode()); p.setMarjorDirection(t.getMajorDirection()); p.setSpecialProject(""); p.setPlanCount(t.getPlanTotal()); p.setXuefei(String.valueOf(t.getXuefei())); p.setXuezhi(String.valueOf(t.getLengthOfSchooling())); p.setEnrollFormula(t.getEnrollFormula()); p.setGroupsName(t.getMajorGroup()); p.setAcceptanceRate(t.getAcceptanceRate()); p.setEnrollCount(t.getEnrollCount()); return p; }).collect(Collectors.toList()); AMarjorSubmit submitCond = new AMarjorSubmit(); submitCond.setUniversityId(universityId); submitCond.setEnrollType("初录"); submitCond.setExamineeType(examineType); List submitList = aMarjorSubmitMapper.selectAMarjorSubmitList(submitCond).stream().map(t -> { UniversityDetailDTO.WishSubmit s = new UniversityDetailDTO.WishSubmit(); s.setId(t.getId()); s.setYear(String.valueOf(t.getYear())); s.setLevel(t.getLevel()); s.setType(""); s.setMarjorCode(""); s.setMarjorName(t.getMajorName()); s.setMarjorBelongs(""); s.setMarjorDirection(t.getMajorDirection()); s.setSpecialProject(""); s.setScore(null != t.getScore() ? t.getScore().longValue() : null); s.setSeat(null); s.setNumReal(null != t.getEnrollTotal() ? t.getEnrollTotal().longValue() : null); s.setEnrollFormula(t.getEnrollFormula()); s.setGroupsName(t.getMajorGroup()); return s; }).collect(Collectors.toList()); return Pair.of(planList, submitList); } private void setOptionValue(VoluntaryDto.AIRenderRule r, String valueType, String valueRule, String options, Integer correctType, String correctValue, Integer scoreTotal) { r.setEnumInputType(VoluntaryDto.EnumInputType.valueOf(valueType)); if (VoluntaryDto.EnumInputType.Score.equals(r.getEnumInputType())) { r.setOptions(new String[]{null == scoreTotal ? "0" : String.valueOf(scoreTotal.intValue())}); } else if (StringUtils.isNotBlank(options) && (VoluntaryDto.EnumInputType.Checkbox.equals(r.getEnumInputType()) || VoluntaryDto.EnumInputType.Radio.equals(r.getEnumInputType()) || VoluntaryDto.EnumInputType.Picker.equals(r.getEnumInputType()))) { r.setOptions(options.split(",")); } // r.setRequired(); // 词典选项类选项 // 词典类选项的优先级最高 // String dictOptions; // 非词典选项 // 分制类规则,将多分制在此options中返回 // String[] options; } public Integer getPlanYear(SysUser u) { return 2025; } public Integer getSubmitYear() { return 2025; } public R postRenderResult(VoluntaryDto.SingleRequest req, Boolean isScoreOnly) { Integer planYear = getPlanYear(SecurityUtils.getLoginUser().getUser()); Integer submitYear = getSubmitYear(); String examType = VistorContextHolder.getExamType().title(); // TODO MF String gender = "0".equals(SecurityUtils.getLoginUser().getUser().getSex()) ? "男生" : "女生"; Map cond = new HashMap(); cond.put("universityCode", req.getUniversityCode()); cond.put("examineeType", examType); Map> currUniversityMajorPlansMap = Maps.newHashMap(); Map> historyUniversityMajorPlansMap = Maps.newHashMap(); List>> bothPlanList = Lists.newArrayList(currUniversityMajorPlansMap, historyUniversityMajorPlansMap); Set existSet = Sets.newHashSet(); Long planId = NumberUtils.toLong(req.getMajorEnrollCode(), 0L); for (AMarjorPlan mp : aMarjorPlanMapper.selectListByRuleCond(cond)) { String key = mp.getUniversityId() + mp.getMajorName() + StringUtils.trimToEmpty(mp.getMajorDirection()) + mp.getYear(); // TODO 考虑为什么会重的问题 examType ? if (!existSet.add(key)) { continue; } for(Map> tmpMap : bothPlanList) { boolean isCurrYear = mp.getYear().equals(planYear); if (tmpMap == currUniversityMajorPlansMap) { if(!isCurrYear || !mp.getId().equals(planId)) { continue; } } else if(mp.getYear() > submitYear) { continue; } List tmpMpList = tmpMap.get(mp.getUniversityId()); if (null == tmpMpList) { tmpMpList = Lists.newArrayList(mp); tmpMap.put(mp.getUniversityId(), tmpMpList); } else { tmpMpList.add(mp); } } } Map> universityMajorsMap = Maps.newHashMap(); // 有计划以计划为准的输出,无计划时则以所有专业输出为准 Map universitiesMap = null; if (MapUtils.isEmpty(currUniversityMajorPlansMap)) { Map> tmpUniversityMajorsMap = bBusiWishUniversitiesProfessionMapper.selectListByRuleCond(cond).stream().collect(Collectors.groupingBy(BBusiWishUniversitiesProfession::getCollegeCode)); if (MapUtils.isNotEmpty(tmpUniversityMajorsMap)) { Map uCond = Maps.newHashMap(); uCond.put("codes", tmpUniversityMajorsMap.keySet()); universitiesMap = Maps.newHashMap(); for (BBusiWishUniversities u : bBusiWishUniversitiesMapper.selectBBusiWishUniversitiesListSimpleByMap(uCond)) { universitiesMap.put(u.getId(), u); universityMajorsMap.put(u.getId(), tmpUniversityMajorsMap.get(u.getCode())); } } } else { cond.put("universityIds", currUniversityMajorPlansMap.keySet()); cond.put("examType", Constant.EXAM_TYPE_PG); Map> tmpUniversityMajorsMap = bBusiWishUniversitiesProfessionMapper.selectListByRuleCond(cond).stream().collect(Collectors.groupingBy(BBusiWishUniversitiesProfession::getCollegeCode)); cond.remove("universityIds"); if (MapUtils.isNotEmpty(tmpUniversityMajorsMap)) { Map uCond = new HashMap(); uCond.put("ids", currUniversityMajorPlansMap.keySet()); universitiesMap = Maps.newHashMap(); for (BBusiWishUniversities u : bBusiWishUniversitiesMapper.selectBBusiWishUniversitiesListSimpleByIds(uCond)) { universitiesMap.put(u.getId(), u); universityMajorsMap.put(u.getId(), tmpUniversityMajorsMap.get(u.getCode())); } } } // 无计划,也无院校专业 if(MapUtils.isEmpty(universitiesMap)) { return R.fail("无计划院校专业"); } // 查询涉及的规则 cond.put("year", planYear); cond.put("universityIds", universitiesMap.keySet()); Map> universityScoreListMap = aEnrollScoreMapper.selectListByRuleCond(cond).stream().collect(Collectors.groupingBy(AEnrollScore::getUniversityId)); cond.remove("universityIds"); cond.remove("year"); Map mutexOptionMap = getMutexOptionMap(); for (Long universityId : universitiesMap.keySet()) { List scoreList = universityScoreListMap.get(universityId); // 分数条件 List currPlanList = currUniversityMajorPlansMap.get(universityId);// 当年计划 List historyPlanList = historyUniversityMajorPlansMap.get(universityId);// 历年计划 BBusiWishUniversities u = universitiesMap.get(universityId);// 院校 List professionList = universityMajorsMap.get(u.getId()); // 所有专业 // 院校变更标志 AEnrollUniversity euCond = new AEnrollUniversity(); euCond.setUniversityId(u.getId()); euCond.setYear(planYear); List enrollUniversityList = aEnrollUniversityMapper.selectAEnrollUniversityList(euCond); // 院校历史情况 AMarjorSubmit submitCond = new AMarjorSubmit(); submitCond.setExamineeType(examType); submitCond.setUniversityId(universityId); List submitList = aMarjorSubmitMapper.selectAMarjorSubmitList(submitCond); VoluntaryDto.RenderMajorResult sr; if (CollectionUtils.isNotEmpty(currPlanList)) { Map professionMap = null == professionList ? Maps.newHashMap() : professionList.stream().collect(Collectors.toMap(BBusiWishUniversitiesProfession::getName, Function.identity())); for (AMarjorPlan mp : currPlanList) { // 只有一个 if (null != (sr = buildRenderResponse(submitYear, planYear, gender, mp, professionMap.get(mp.getMajorName()), enrollUniversityList, req.getForm(), u, historyPlanList, submitList, scoreList, mutexOptionMap, isScoreOnly))) { sr.setUniversityId(universityId); sr.setMajorId(planId); return R.ok(sr); } } } } return R.fail("无计划院校专业"); } private VoluntaryDto.RenderMajorResult buildRenderResponse(Integer submitYear, Integer planYear, String gender, AMarjorPlan currPlan, BBusiWishUniversitiesProfession prof, List enrollUniversityList, Map paramMap, BBusiWishUniversities u, List historyPlanList, List submitList, List scoreList, Map mutexOptionMap, boolean isScoreOnly) { submitList = voluntaryRuleHelper.sortSubmits(submitList); historyPlanList = voluntaryRuleHelper.sortPlans(historyPlanList); Boolean typeChange = false; VoluntaryDto.FormulaScoreStat formulaScoreStat = new VoluntaryDto.FormulaScoreStat(); String needGroup = StringUtils.trimToEmpty(null != currPlan && null != currPlan.getMajorGroup() ? currPlan.getMajorGroup() : ""); String needMajor = StringUtils.trimToEmpty(null != currPlan ? currPlan.getMajorName() : (null != prof ? prof.getName() : "")); String needDirect = StringUtils.trimToEmpty(null != currPlan ? currPlan.getMajorDirection() : ""); String needMajorDirect = needMajor + needDirect; // 判断是否政策变化情况 List validEuList = enrollUniversityList.stream() .filter(t -> needGroup.equals(StringUtils.trimToEmpty(t.getMajorGroups())) && t.getMajorNames().contains(needMajor)) .collect(Collectors.toList()); typeChange = CollectionUtils.isNotEmpty(validEuList) && new Integer(1).equals(validEuList.get(0).getTypeChange()); Set existSet = Sets.newHashSet(); List validSubmitList = voluntaryRuleHelper.filtValidSubmits(needMajorDirect, submitList, existSet); // 录取线 List histories = Lists.newArrayList(); // 历史录取情况 VoluntaryDto.RenderMajorResult sr = new VoluntaryDto.RenderMajorResult(); sr.setHistories(histories); if (null == scoreList) { throw new RuntimeException("无分数规则"); } Map> majorEnrollScoresMap = voluntaryRuleHelper.buildMajorEnrollScoresMap(scoreList, needGroup); existSet.clear(); List fEnrollScoreList = Lists.newArrayList(); Double inputScoreRate = NumberUtils.toInt(paramMap.get("ScoreRate"), 0) / 100.0; String inclMajorDirection = needMajor + "(" + needDirect + ")"; String exclMajorDirection = needMajor + "("; List tmpEnrollScoreList = majorEnrollScoresMap.get(Boolean.TRUE); if (null != tmpEnrollScoreList) { for (AEnrollScore r : tmpEnrollScoreList) { if(!voluntaryRuleHelper.isMatchMajor(r, needMajor, needMajorDirect, inclMajorDirection, exclMajorDirection)) { continue; } Boolean isSkillScore = isScoreOnly && r.getItemType().equals("ScoreSkill"); appendScoreRule(formulaScoreStat, existSet, r, fEnrollScoreList, false, paramMap, inputScoreRate, isSkillScore); } } if (fEnrollScoreList.size() == 0 && null != (tmpEnrollScoreList = majorEnrollScoresMap.get(Boolean.FALSE))) { for (AEnrollScore r : tmpEnrollScoreList) { Boolean isSkillScore = isScoreOnly && r.getItemType().equals("ScoreSkill"); appendScoreRule(formulaScoreStat, existSet, r, fEnrollScoreList, false, paramMap, inputScoreRate, isSkillScore); } } Double currTotal = formulaScoreStat.getTypeValue("StatRateScore", "", false); existSet.clear(); Map historyPlanMap = historyPlanList.stream().collect(Collectors.toMap(t -> t.getYear() + t.getMajorName() + StringUtils.trimToEmpty(t.getMajorDirection()), Function.identity())); AMarjorSubmit lastSubmit1 = null, lastSubmit2 = null; for (AMarjorSubmit s : validSubmitList) { if (s.getYear().equals(submitYear)) { if(s.getEnrollType().equals("初录")) { lastSubmit1 = s; } else { lastSubmit2 = s; } } VoluntaryDto.RenderMajorHistory h = new VoluntaryDto.RenderMajorHistory(); h.setYear(s.getYear()); AMarjorPlan p = historyPlanMap.get(s.getYear() + s.getMajorName() + StringUtils.trimToEmpty(s.getMajorDirection())); if(null != p) { h.setPlan(p.getPlanTotal()); } else { // System.out.println(s.getId()); } h.setEnroll(s.getEnrollTotal()); if(null != s.getScore()) { h.setScore(String.valueOf(s.getScore())); h.setDiff((int) Math.round(currTotal - s.getScore())); } else { h.setScore(""); h.setDiff(null); } h.setRuleContent(s.getEnrollFormula()); h.setApplication(""); h.setAdmission(""); histories.add(h); } AMarjorSubmit lastSubmit = null == lastSubmit1 ? lastSubmit2 : lastSubmit1; Double cultureScore = formulaScoreStat.getTypeValue("StatCategoryScore", "ScoreBase", false); VoluntaryDto.RenderMajorSkill skill = new VoluntaryDto.RenderMajorSkill(); skill.setYear(currPlan.getYear()); skill.setCultureScore(toString(cultureScore)); String[] formulas = fEnrollScoreList.get(0).getEnrollFormula().split("\\+职业技能"); if(formulas.length != 2) { throw new RuntimeException("错误定义考试规则" + fEnrollScoreList.get(0).getEnrollFormula()); } skill.setCultureRule(formulas[0]); // 拆分公式 skill.setEnrollScore(toString(lastSubmit.getScore())); // 计算概念或反算技能分 boolean isSameYear = planYear.equals(submitYear); Integer validScoreTotal = isSameYear ? formulaScoreStat.getAllTotal() : lastSubmit.getScoreTotal(); Double currScoreRate = isSameYear ? 1.0 : formulaScoreStat.getAllTotal() * 1.0 / lastSubmit.getScoreTotal(); Double needSkillScore = lastSubmit.getScore() * currScoreRate - cultureScore; if(isScoreOnly) { skill.setSkillScore(toString(formulaScoreStat.getImproveSkillScore(needSkillScore))); } else { Double skillScore = formulaScoreStat.getTypeValue("StatCategoryScore", "ScoreSkill", true); skill.setSkillScore(toString(needSkillScore)); skill.setDiff(toString(formulaScoreStat.getImproveSkillScore(skillScore - needSkillScore))); EnrollRateCalculator.RateLevel rl; if (currTotal != null && null != (rl = enrollRateCalculator.calSchoolEnrollRate(validScoreTotal, lastSubmit.getScore(), currTotal / currScoreRate))) { // 按去年标准算概率 sr.setEnrollRate(rl.rate); sr.setEnrollRateText(rl.typeLabel); sr.setEnumPickType(rl.type); } } sr.setSkill(skill); return sr; } public String toString(Double v) { return String.valueOf(v); } public R> getRenderRules(VoluntaryDto.RenderRequest req) { Map cond = new HashMap(); Integer planYear = getPlanYear(SecurityUtils.getLoginUser().getUser()); cond.put("year", planYear); AMarjorPlan plan = aMarjorPlanMapper.selectAMarjorPlanById(req.getMajorId()); cond.put("majorGroup", StringUtils.trimToEmpty(plan.getMajorGroup())); cond.put("majorGroupCodes", plan.getMajorCode()); cond.put("universityCode", req.getUniversityId()); return R.ok(findMatchRenderRules(cond, req.getRenderType() == 2)); } public R> getAIRenderRules(VoluntaryDto.AIRenderRequest req) { Map cond = new HashMap(); Integer planYear = getPlanYear(SecurityUtils.getLoginUser().getUser()); cond.put("year", planYear); Set majorCodeSet = null; String majorGroup = null; if (ArrayUtils.isNotEmpty(req.getMajorEnrollCodes()) && StringUtils.isNotBlank(req.getMajorEnrollCodes()[0])) { List majorEnrollCodes = Arrays.asList(req.getMajorEnrollCodes()).stream().map(t -> NumberUtils.toLong(t, 0L)).collect(Collectors.toList()); for(AMarjorPlan plan : aMarjorPlanMapper.selectMajorCodesByIds(majorEnrollCodes.toArray(new Long[majorEnrollCodes.size()]), planYear)) { majorGroup = StringUtils.trimToEmpty(plan.getMajorGroup()); majorCodeSet = Sets.newHashSet(plan.getMajorCode()); } } if(CollectionUtils.isNotEmpty(majorCodeSet)) { cond.put("majorGroup", majorGroup); cond.put("majorGroupCodes", majorCodeSet.toArray(new String[majorCodeSet.size()])); } else if (ArrayUtils.isNotEmpty(req.getMajorCodes()) && StringUtils.isNotBlank(req.getMajorCodes()[0])) { cond.put("majorCodes", req.getMajorCodes()); } else if (ArrayUtils.isNotEmpty(req.getMajorTypes()) && StringUtils.isNotBlank(req.getMajorTypes()[0])) { cond.put("majorTypes", req.getMajorTypes()); } else if (StringUtils.isNotBlank(req.getMajorCategory())) { cond.put("majorCategory", req.getMajorCategory()); } cond.put("universityCode", req.getUniversityCode()); return R.ok(findMatchRules(cond, req.getRenderType() == 1, req.getRenderType() == 2)); } public R postSingleResult(VoluntaryDto.SingleRequest req, Boolean isScoreOnly) { VoluntaryDto.MultipleRequest mr = new VoluntaryDto.MultipleRequest(); VoluntaryDto.CollegeMajorDto collegeMajor = new VoluntaryDto.CollegeMajorDto(); collegeMajor.setCode(req.getUniversityCode()); if (StringUtils.isNotBlank(req.getMajorCode())) { collegeMajor.setMajorCodes(Lists.newArrayList(req.getMajorCode())); } if (StringUtils.isNotBlank(req.getMajorEnrollCode())) { collegeMajor.setMajorEnrollCodes(Lists.newArrayList(req.getMajorEnrollCode())); } collegeMajor.setForm(req.getForm()); mr.setUniversities(Lists.newArrayList(collegeMajor)); List respList = postMultipleResult(mr, isScoreOnly).getData(); if (respList.size() > 0) { Optional optionalSingleResponse = respList.stream().filter(t -> StringUtils.isBlank(t.getMajorDirection())).findFirst(); if (optionalSingleResponse.isPresent()) { return R.ok(optionalSingleResponse.get()); } } return respList.size() > 0 ? R.ok(respList.get(0)) : null; } public R> postMultipleResult(VoluntaryDto.MultipleRequest req, boolean isScoreOnly) { List respList = Lists.newArrayList(); for (VoluntaryDto.CollegeMajorDto cm : req.getUniversities()) { Map cond = new HashMap(); if (CollectionUtils.isNotEmpty(cm.getMajorEnrollCodes()) && StringUtils.isNotBlank(cm.getMajorEnrollCodes().get(0))) { cond.put("majorEnrollCodes", cm.getMajorEnrollCodes()); // TODO 代替majorCodes更精准,只是现在没有,使用planId代替 } else if (CollectionUtils.isNotEmpty(cm.getMajorCodes()) && StringUtils.isNotBlank(cm.getMajorCodes().get(0))) { cond.put("majorCodes", cm.getMajorCodes()); } else if (StringUtils.isNotBlank(req.getMajorCategory())) { cond.put("majorCategory", req.getMajorCategory()); } cond.put("universityCode", StringUtils.trimToEmpty(cm.getCode())); List responses = findMajorSuggest(getPlanYear(SecurityUtils.getLoginUser().getUser()), getSubmitYear(), cond, cm.getForm(), false, isScoreOnly); if(CollectionUtils.isNotEmpty(responses)) { responses.stream().forEach(t -> respList.addAll(t.getMajorDetails())); } } return R.ok(respList); } public TableDataInfo postAIResult(VoluntaryDto.AIRequest req) { VoluntaryDto.AIRequestFilter filter = req.getFilter(); Map cond = new HashMap(); if (CollectionUtils.isNotEmpty(filter.getMajorTypes()) && StringUtils.isNotBlank(filter.getMajorTypes().get(0))) { cond.put("majorTypes", filter.getMajorTypes()); } else if (StringUtils.isNotBlank(req.getMajorCategory())) { cond.put("majorCategory", req.getMajorCategory()); } cond.put("universityName", filter.getKeyword());// 院校名称 if (CollectionUtils.isNotEmpty(filter.getLevel())) { cond.put("universityLevel", filter.getLevel());// 办学层次 } if (CollectionUtils.isNotEmpty(filter.getType())) { cond.put("universityType", filter.getType());// 院校类型 } if (CollectionUtils.isNotEmpty(filter.getNatureTypeCN())) { cond.put("universityNatureType", filter.getNatureTypeCN()); // 办学类型 } if (CollectionUtils.isNotEmpty(filter.getLocation())) { cond.put("universityLocation", filter.getLocation()); // 院校省份 } if (null != filter.getHasClearing()) { cond.put("hasClearing", filter.getHasClearing() ? "补录" : "初录"); } List responses = findMajorSuggest(getPlanYear(SecurityUtils.getLoginUser().getUser()), getSubmitYear(), cond, req.getForm(), true, false); if (CollectionUtils.isEmpty(responses)) { return new TableDataInfo(Lists.newArrayList(), 0); } if (null != filter.getEnumPickEmpty()) { responses = responses.stream().filter(t -> filter.getEnumPickEmpty().equals(t.getEnumPickEmpty())).collect(Collectors.toList()); } else if (null != filter.getEnumPickType() && !VoluntaryDto.EnumPickType.All.equals(filter.getEnumPickType())) { responses = responses.stream().filter(t -> filter.getEnumPickType().equals(t.getEnumPickType())).collect(Collectors.toList()); } Integer start = null != req.getPageNum() ? (req.getPageNum() - 1) * req.getPageSize() : 0; List finalList = responses.subList(start, Math.min(start + (null == req.getPageSize() ? 10 : req.getPageSize()), responses.size())); TableDataInfo tableDataInfo = new TableDataInfo(finalList, responses.size()); tableDataInfo.setCode(200); return tableDataInfo; } private List findMatchRenderRules(Map cond, boolean isScore) { String examType = VistorContextHolder.getExamType().title(); // TODO MF // String gender = "0".equals(SecurityUtils.getLoginUser().getUser().getSex()) ? "男生" : "女生"; cond.put("examineeType", examType); List cultureRuleList = Lists.newArrayList(); List skillRuleList = Lists.newArrayList(); List enrollScoreList = aEnrollScoreMapper.selectListByRuleCond(cond); if (CollectionUtils.isEmpty(enrollScoreList) && cond.containsKey("majorGroup")) { cond.put("majorGroup", ""); enrollScoreList = aEnrollScoreMapper.selectListByRuleCond(cond); } Set existItemSet = Sets.newHashSet(); String vt; SysUser sysUser = SecurityUtils.getLoginUser().getUser();; boolean isOHS = ExamType.OHS.equals(sysUser.getExamType()); SubjectScore subjectScore = sysUser.getScores(); for (AEnrollScore s : enrollScoreList) { // 跳过统计类和提示类的规则 boolean isSkill = "职业技能测试".equals(s.getItemCategory()); if (null == (vt = s.getValueType()) || vt.startsWith("Stat") || vt.equals("Notice")) { continue; } List ruleList = isSkill ? skillRuleList : cultureRuleList ; if (!existItemSet.add(s.getItemField())) { continue; } VoluntaryDto.AIRenderRule r = new VoluntaryDto.AIRenderRule(); r.setEnumRuleCategory(VoluntaryDto.EnumRuleCategory.Enroll); if (!isSkill && isOHS && !isScore && "Score".equals(s.getValueType())) { r.setReadonly(true); Double score = subjectScore.getSelectScore(s.getItemField()); if (null == score && SubjectType.Foreign.name().equals(s.getItemField())) { score = subjectScore.getSelectScore(SubjectType.English.name()); } r.setDefaultValue(null != score ? String.valueOf(score) : "0"); } else { r.setReadonly(false); r.setDefaultValue(s.getDefaultValue()); } r.setFieldName(s.getItemField()); setOptionValue(r, vt, s.getValueRule(), s.getValueOptional(), s.getCorrectType(), s.getCorrectValue(), s.getScoreTotal()); r.setRegex(s.getRegex()); r.setLabel(s.getItemName()); r.setDescription(s.getDescription()); r.setPlaceholder(s.getPlaceholder()); r.setTips(s.getTips()); r.setDotDisable(null != s.getDotDisable() && s.getDotDisable() > 0); r.setKeyboardMode(s.getKeyboardMode()); // number card car,默认number ruleList.add(r); } if(CollectionUtils.isEmpty(enrollScoreList)) { throw new RuntimeException("未定义考试规则" + StringUtils.join(cond.values(), ",")); } String[] formulas = enrollScoreList.get(0).getEnrollFormula().split("\\+职业技能"); if(formulas.length != 2) { throw new RuntimeException("错误定义考试规则" + enrollScoreList.get(0).getEnrollFormula()); } List allRenderRuleList = Lists.newArrayList(); allRenderRuleList.add(new VoluntaryDto.RenderRule("文化素质", formulas[0], cultureRuleList)); allRenderRuleList.add(new VoluntaryDto.RenderRule("职业技能", "职业技能" + formulas[1], isScore ? null : skillRuleList)); return allRenderRuleList; } private List findMatchRules(Map cond, boolean isAi, boolean isScore) { String examType = VistorContextHolder.getExamType().title(); // TODO MF String gender = "0".equals(SecurityUtils.getLoginUser().getUser().getSex()) ? "男生" : "女生"; cond.put("examineeType", examType); List enrollScoreList = aEnrollScoreMapper.selectListByRuleCond(cond); if (CollectionUtils.isEmpty(enrollScoreList) && cond.containsKey("majorGroup")) { cond.put("majorGroup", ""); enrollScoreList = aEnrollScoreMapper.selectListByRuleCond(cond); } List ruleList = Lists.newArrayList(); Set existItemSet = Sets.newHashSet(); String vt; VoluntaryDto.AIRenderRule scoreRateRule = null; for (AEnrollScore s : enrollScoreList) { // 跳过统计类和提示类的规则 if (null == (vt = s.getValueType()) || vt.startsWith("Stat") || vt.equals("Notice")) { continue; } else if(isScore && !"学考".equals(s.getItemCategory()) && !"校考".equals(s.getItemCategory())) { continue; } else if (vt.equals("ScoreRate")) { if (!isAi) { vt = "Score"; } else if (existItemSet.add("ScoreRate")) { scoreRateRule = new VoluntaryDto.AIRenderRule(); scoreRateRule.setEnumRuleCategory(VoluntaryDto.EnumRuleCategory.Enroll); scoreRateRule.setFieldName("ScoreRate"); scoreRateRule.setEnumInputType(VoluntaryDto.EnumInputType.Number); scoreRateRule.setMin(0); scoreRateRule.setMax(100); scoreRateRule.setLabel("技能测试得分率"); scoreRateRule.setDescription("%"); continue; } else { continue; } } if (!existItemSet.add(s.getItemField())) { continue; } VoluntaryDto.AIRenderRule r = new VoluntaryDto.AIRenderRule(); r.setEnumRuleCategory(VoluntaryDto.EnumRuleCategory.Enroll); r.setFieldName(s.getItemField()); setOptionValue(r, vt, s.getValueRule(), s.getValueOptional(), s.getCorrectType(), s.getCorrectValue(), s.getScoreTotal()); r.setRegex(s.getRegex()); r.setLabel(s.getItemName()); r.setDescription(s.getDescription()); r.setPlaceholder(s.getPlaceholder()); r.setTips(s.getTips()); r.setDefaultValue(s.getDefaultValue()); r.setDotDisable(null != s.getDotDisable() && s.getDotDisable() > 0); r.setKeyboardMode(s.getKeyboardMode()); // number card car,默认number ruleList.add(r); } if (null != scoreRateRule) { ruleList.add(scoreRateRule); } if(isScore) { return ruleList; } List enrollSpecialList = Lists.newArrayList(); Map mergeEnrollSpecialMap = Maps.newHashMap(); List oriErollSpecialList = aEnrollSpecialMapper.selectListByRuleCond(cond); for (AEnrollSpecial s : oriErollSpecialList) { if (VoluntaryDto.EnumRuleType.Readonly.name().equals(s.getItemType()) || StringUtils.isNotBlank(s.getGender()) && !s.getGender().equals(gender)) { continue; } if (null == s.getItemGroup() || !"Checkbox".equals(s.getValueType())) { enrollSpecialList.add(s); continue; } // String key = s.getItemGroup(); // s.getUniversityId() + "_" + s.getMajorName() + "_" + StringUtils.trimToEmpty(s.getMajorDirection()) + "_" + StringUtils.trimToEmpty(s.getGender()) + "_" + s.getItemCategory() + "_" + AEnrollSpecial exist = mergeEnrollSpecialMap.get(key); if (null == exist) { // 修正分组后的名称及字段名 String[] groupNameField = StringUtils.split(s.getItemGroup(), "_"); s.setValueOptional(s.getItemName()); s.setItemName(groupNameField[0]); s.setItemField(groupNameField[groupNameField.length > 1 ? 1 : 0]); mergeEnrollSpecialMap.put(key, s); enrollSpecialList.add(s); continue; } if(StringUtils.isBlank(exist.getValueOptional()) || !exist.getValueOptional().contains(s.getItemName())) { exist.setValueOptional(exist.getValueOptional() + "," + s.getItemName()); } } Map mutexOptionMap = getMutexOptionMap(); for (AEnrollSpecial s : enrollSpecialList) { if (null == (vt = s.getValueType()) || vt.startsWith("Stat") || vt.equals("Notice") || !existItemSet.add(s.getItemField())) { continue; } VoluntaryDto.AIRenderRule r = new VoluntaryDto.AIRenderRule(); r.setEnumRuleCategory(VoluntaryDto.EnumRuleCategory.Special); r.setFieldName(s.getItemField()); setOptionValue(r, s.getValueType(), s.getValueRule(), s.getValueOptional(), s.getCorrectType(), s.getCorrectValue(), null); if (VoluntaryDto.EnumInputType.Checkbox.equals(r.getEnumInputType())) { r.setMutexOption(mutexOptionMap.get(r.getFieldName())); } r.setRegex(s.getRegex()); r.setLabel(s.getItemName()); r.setDescription(s.getDescription()); r.setPlaceholder(s.getPlaceholder()); r.setTips(s.getTips()); r.setDefaultValue(s.getDefaultValue()); r.setDotDisable(null != s.getDotDisable() && s.getDotDisable() > 0); r.setKeyboardMode(s.getKeyboardMode()); // number card car,默认number ruleList.add(r); } return ruleList; } private Map getMutexOptionMap() { String mutexOptionConf = sysConfigService.selectConfigByKey("voluntary.rule.mutexOption"); Map mutexOptionMap = Maps.newHashMap(); if (StringUtils.isNotBlank(mutexOptionConf)) { try { JSONArray.parseArray(mutexOptionConf).forEach(l -> { JSONObject lo = (JSONObject) l; mutexOptionMap.put(lo.getString("n"), lo.getString("m")); }); } catch (JSONException e) { } } return mutexOptionMap; } // TODO 同一专业号有多个专业方向 private List findMajorSuggest(Integer planYear, Integer submitYear, Map cond, Map paramMap, boolean isAi, boolean isScoreOnly) { String examType = VistorContextHolder.getExamType().title(); // TODO MF String gender = "0".equals(SecurityUtils.getLoginUser().getUser().getSex()) ? "男生" : "女生"; cond.remove("year"); cond.put("examineeType", examType); Map> currUniversityMajorPlansMap = Maps.newHashMap(); Map> historyUniversityMajorPlansMap = Maps.newHashMap(); List>> bothPlanList = Lists.newArrayList(currUniversityMajorPlansMap, historyUniversityMajorPlansMap); Set existSet = Sets.newHashSet(); for (AMarjorPlan mp : aMarjorPlanMapper.selectListByRuleCond(cond)) { String key = mp.getUniversityId() + mp.getMajorName() + StringUtils.trimToEmpty(mp.getMajorDirection()) + mp.getYear(); // TODO 考虑为什么会重的问题 examType ? if (!existSet.add(key)) { continue; } for(Map> tmpMap : bothPlanList) { if (!mp.getYear().equals(planYear) && tmpMap == currUniversityMajorPlansMap) { continue; } List tmpMpList = tmpMap.get(mp.getUniversityId()); if (null == tmpMpList) { tmpMpList = Lists.newArrayList(mp); tmpMap.put(mp.getUniversityId(), tmpMpList); } else { tmpMpList.add(mp); } } } Map> universityMajorsMap = Maps.newHashMap(); // 有计划以计划为准的输出,无计划时则以所有专业输出为准 Map universitiesMap = null; if (MapUtils.isEmpty(currUniversityMajorPlansMap)) { Map> tmpUniversityMajorsMap = bBusiWishUniversitiesProfessionMapper.selectListByRuleCond(cond).stream().collect(Collectors.groupingBy(BBusiWishUniversitiesProfession::getCollegeCode)); if (MapUtils.isNotEmpty(tmpUniversityMajorsMap)) { Map uCond = Maps.newHashMap(); uCond.put("codes", tmpUniversityMajorsMap.keySet()); universitiesMap = Maps.newHashMap(); for (BBusiWishUniversities u : bBusiWishUniversitiesMapper.selectBBusiWishUniversitiesListSimpleByMap(uCond)) { universitiesMap.put(u.getId(), u); universityMajorsMap.put(u.getId(), tmpUniversityMajorsMap.get(u.getCode())); } } } else { cond.put("universityIds", currUniversityMajorPlansMap.keySet()); cond.put("examType", Constant.EXAM_TYPE_PG); Map> tmpUniversityMajorsMap = bBusiWishUniversitiesProfessionMapper.selectListByRuleCond(cond).stream().collect(Collectors.groupingBy(BBusiWishUniversitiesProfession::getCollegeCode)); cond.remove("universityIds"); if (MapUtils.isNotEmpty(tmpUniversityMajorsMap)) { Map uCond = new HashMap(); uCond.put("ids", currUniversityMajorPlansMap.keySet()); universitiesMap = Maps.newHashMap(); for (BBusiWishUniversities u : bBusiWishUniversitiesMapper.selectBBusiWishUniversitiesListSimpleByIds(uCond)) { universitiesMap.put(u.getId(), u); universityMajorsMap.put(u.getId(), tmpUniversityMajorsMap.get(u.getCode())); } } } // 无计划,也无院校专业 if(MapUtils.isEmpty(universitiesMap)) { return Lists.newArrayList(); } // 查询涉及的规则 cond.put("year", planYear); cond.put("universityIds", universitiesMap.keySet()); Map> universityScoreListMap = aEnrollScoreMapper.selectListByRuleCond(cond).stream().collect(Collectors.groupingBy(AEnrollScore::getUniversityId)); Map> universitySpecialListMap = aEnrollSpecialMapper.selectListByRuleCond(cond).stream().collect(Collectors.groupingBy(AEnrollSpecial::getUniversityId)); cond.remove("universityIds"); cond.remove("year"); Map mutexOptionMap = getMutexOptionMap(); List aiRespList = Lists.newArrayList(); for (Long universityId : universitiesMap.keySet()) { List scoreList = universityScoreListMap.get(universityId); // 分数条件 List specialList = universitySpecialListMap.get(universityId);// 专项条件 List currPlanList = currUniversityMajorPlansMap.get(universityId);// 当年计划 List historyPlanList = historyUniversityMajorPlansMap.get(universityId);// 历年计划 BBusiWishUniversities u = universitiesMap.get(universityId);// 院校 List professionList = universityMajorsMap.get(u.getId()); // 所有专业 // 院校变更标志 AEnrollUniversity euCond = new AEnrollUniversity(); euCond.setUniversityId(u.getId()); euCond.setYear(planYear); List enrollUniversityList = aEnrollUniversityMapper.selectAEnrollUniversityList(euCond); // 院校历史情况 AMarjorSubmit submitCond = new AMarjorSubmit(); submitCond.setExamineeType(examType); submitCond.setUniversityId(universityId); List submitList = aMarjorSubmitMapper.selectAMarjorSubmitList(submitCond); VoluntaryDto.AIResponse aiResp = new VoluntaryDto.AIResponse(); aiResp.setUniversity(u); VoluntaryDto.SingleResponse sr; List singleResponseList = Lists.newArrayList(); if (CollectionUtils.isNotEmpty(currPlanList)) { aiResp.setEnrollCode(currPlanList.get(0).getEnrollCode()); Map professionMap = null == professionList ? Maps.newHashMap() : professionList.stream().collect(Collectors.toMap(BBusiWishUniversitiesProfession::getName, Function.identity())); for (AMarjorPlan mp : currPlanList) { if (null != (sr = buildSingleResponse(submitYear, planYear, gender, mp, professionMap.get(mp.getMajorName()), enrollUniversityList, paramMap, u, historyPlanList, submitList, scoreList, specialList, mutexOptionMap, isAi, isScoreOnly))) { singleResponseList.add(sr); } } } else { for (BBusiWishUniversitiesProfession prof : professionList) { if (null != (sr = buildSingleResponse(submitYear, planYear, gender, null, prof, enrollUniversityList, paramMap, u, historyPlanList, submitList, scoreList, specialList, mutexOptionMap, isAi, isScoreOnly))) { singleResponseList.add(sr); } } } aiResp.setMajorDetails(singleResponseList); sortAndExtractEnroll(singleResponseList, aiResp); aiRespList.add(aiResp); } Collections.sort(aiRespList, new Comparator() { @Override public int compare(VoluntaryDto.AIResponse o1, VoluntaryDto.AIResponse o2) { Integer d1 = o1.getEnrollRate(); Integer d2 = o2.getEnrollRate(); d1 = null == d1 ? 999 : (d1 == 0 ? 998 : d1); d2 = null == d2 ? 999 : (d2 == 0 ? 998 : d2); return d1.compareTo(d2); } }); return aiRespList; } private VoluntaryDto.SingleResponse buildSingleResponse(Integer submitYear, Integer planYear, String gender, AMarjorPlan currPlan, BBusiWishUniversitiesProfession prof, List enrollUniversityList, Map paramMap, BBusiWishUniversities u, List historyPlanList, List submitList, List scoreList, List specialList, Map mutexOptionMap, boolean isAi, boolean isScoreOnly) { if (null != submitList) { Collections.sort(submitList, new Comparator() { @Override public int compare(AMarjorSubmit o1, AMarjorSubmit o2) { int iRet; if (0 != (iRet = o1.getYear().compareTo(o2.getYear()))) { return -iRet; } if (0 != (iRet = o1.getMajorName().compareTo(o2.getMajorName()))) { return -iRet; } if (null == o1.getMajorDirection()) { if (null != o2.getMajorDirection()) { return 1; } return 0; } else if (null == o2.getMajorDirection()) { return -1; } return 0; } }); } else { submitList = Lists.newArrayList(); } if (null != historyPlanList) { Collections.sort(historyPlanList, new Comparator() { @Override public int compare(AMarjorPlan o1, AMarjorPlan o2) { int iRet; if (0 != (iRet = o1.getYear().compareTo(o2.getYear()))) { return -iRet; } if (0 != (iRet = o1.getMajorName().compareTo(o2.getMajorName()))) { return -iRet; } if (null == o1.getMajorDirection()) { if (null != o2.getMajorDirection()) { return 1; } return 0; } else if (null == o2.getMajorDirection()) { return -1; } return o1.getMajorDirection().compareTo(o2.getMajorDirection()); } }); } else { historyPlanList = Lists.newArrayList(); } // 录取线 List clearings = Lists.newArrayList(); // 补录情况 List histories = Lists.newArrayList(); // 初录情况 List ruleMatchList = Lists.newArrayList(); List improveList = Lists.newArrayList(); Double tmpValue; // 总分,得分 AMarjorSubmit lastSubmit = null; Boolean typeChange = false; VoluntaryDto.FormulaScoreStat formulaScoreStat = new VoluntaryDto.FormulaScoreStat(); String needGroup = StringUtils.trimToEmpty(null != currPlan && null != currPlan.getMajorGroup() ? currPlan.getMajorGroup() : ""); String needMajor = StringUtils.trimToEmpty(null != currPlan ? currPlan.getMajorName() : (null != prof ? prof.getName() : "")); String needDirect = StringUtils.trimToEmpty(null != currPlan ? currPlan.getMajorDirection() : ""); String needMajorDirect = needMajor + needDirect; // 判断是否政策变化情况 List validEuList = enrollUniversityList.stream() .filter(t -> needGroup.equals(StringUtils.trimToEmpty(t.getMajorGroups())) && t.getMajorNames().contains(needMajor)) .collect(Collectors.toList()); typeChange = CollectionUtils.isNotEmpty(validEuList) && new Integer(1).equals(validEuList.get(0).getTypeChange()); Set existSet = Sets.newHashSet(); existSet.clear(); List validSubmitList = Lists.newArrayList(); if (null != submitList) { for (AMarjorSubmit s : submitList) { // 历年录取通过专业分来判断差别 String majorNameDirect = s.getMajorName() + StringUtils.trimToEmpty(s.getMajorDirection()); if (needMajorDirect.equals(majorNameDirect) && existSet.add(needMajorDirect + s.getYear() + s.getEnrollType())) { validSubmitList.add(s); if (s.getYear().equals(submitYear) && s.getEnrollType().equals("初录") ) { lastSubmit = s; // TODO 初录,补录与分数线的关系 要处理 } } } } // 分项规则检查 existSet.clear(); Double currTotal = null; if (null != scoreList) { Double inputScoreRate = NumberUtils.toInt(paramMap.get("ScoreRate"), 0) / 100.0; List fEnrollScoreList = Lists.newArrayList(); String inclMajorDirection = needMajor + "(" + needDirect + ")"; String exclMajorDirection = needMajor + "("; Map> majorEnrollScoresMap = scoreList.stream() .filter(t -> needGroup.equals(StringUtils.trimToEmpty(t.getMajorGroups()))) .collect(Collectors.groupingBy(t -> StringUtils.isNotBlank(t.getMajorNames()))); if(majorEnrollScoresMap.isEmpty() && StringUtils.isNotBlank(needGroup)) { majorEnrollScoresMap = scoreList.stream() .filter(t -> StringUtils.isBlank(t.getMajorGroups())) .collect(Collectors.groupingBy(t -> StringUtils.isNotBlank(t.getMajorNames()))); } List tmpEnrollScoreList = majorEnrollScoresMap.get(Boolean.TRUE); AEnrollScore skillEnrollScore = null; if (null != tmpEnrollScoreList) { for (AEnrollScore r : tmpEnrollScoreList) { if (StringUtils.isNotBlank(r.getMajorNames())) { if (!r.getMajorNames().contains(needMajor)) { continue; } if (StringUtils.isNotBlank(r.getMajorDirections())) { // 有单独的方向时,分开判断 if (StringUtils.isBlank(needDirect) || !r.getMajorDirections().contains(needDirect)) { continue; } } else if (StringUtils.isNotBlank(needDirect)) { // 有direct要求时,这里需要有 "<专业>(<方向>) if (!r.getMajorNames().contains(inclMajorDirection)) { continue; } } else if (r.getMajorNames().contains(exclMajorDirection)) { // 当无direct要求时,这时不能有 "<专业>(" continue; } } Boolean isSkillScore = isScoreOnly && r.getItemType().equals("ScoreSkill"); if(isSkillScore) { skillEnrollScore = r; } appendScoreRule(formulaScoreStat, existSet, r, fEnrollScoreList, isAi, paramMap, inputScoreRate, isSkillScore); } } if (fEnrollScoreList.size() == 0 && null != (tmpEnrollScoreList = majorEnrollScoresMap.get(Boolean.FALSE))) { for (AEnrollScore r : tmpEnrollScoreList) { Boolean isSkillScore = isScoreOnly && r.getItemType().equals("ScoreSkill"); if(isSkillScore) { skillEnrollScore = r; } appendScoreRule(formulaScoreStat, existSet, r, fEnrollScoreList, isAi, paramMap, inputScoreRate, isSkillScore); } } boolean isSameYear = null == lastSubmit || planYear.equals(lastSubmit.getYear()); currTotal = formulaScoreStat.getTypeValue("StatRateScore", "", false); for (AEnrollScore r : fEnrollScoreList) { VoluntaryDto.MajorEnrollRule mr = buildEnrollRule(r); mr.setContent(StringUtils.isNotBlank(r.getEqualFormula()) ? r.getEqualFormula() : r.getEnrollFormula()); if(isScoreOnly) { String vt; if (null != (vt = r.getValueType()) && vt.startsWith("Score")) { improveList.add(mr); mr.setCategory(VoluntaryDto.EnumRuleCategory.Enroll); mr.setType(VoluntaryDto.EnumRuleType.ScoreTotal); // mr.setValue(null != currTotal ? String.valueOf(currTotal.intValue()) : ""); if (null == lastSubmit || null == lastSubmit.getScore() || null == lastSubmit.getScoreTotal() && !isSameYear) { mr.setFailedMessage("缺历史录取数据"); continue; } mr.setYear(lastSubmit.getYear()); if (typeChange) { mr.setFailedMessage("规则变更,无法计算"); continue; } else if (!formulaScoreStat.isScoreValid() && (!isAi || inputScoreRate <= 0.0)) { mr.setFailedMessage("用户没有填写完整"); continue; } Integer validScoreTotal = isSameYear ? formulaScoreStat.getAllTotal() : lastSubmit.getScoreTotal(); Double currScoreRate = isSameYear ? 1.0 : formulaScoreStat.getAllTotal() * 1.0 / lastSubmit.getScoreTotal(); // 去年的分转成今年的分 EnrollRateCalculator.RateLevel rl; if (null != lastSubmit.getScore() && currTotal != null && null != (rl = enrollRateCalculator.satisfy(validScoreTotal, lastSubmit.getScore(), currTotal / currScoreRate))) { // 按去年标准算概率 Double skillRate = Double.parseDouble(skillEnrollScore.getValueRule()); mr.setValue(String.valueOf(Math.round((lastSubmit.getScore() * currScoreRate - currTotal) * 10 / skillRate) / 10.0)); mr.setValid(true); } else { mr.setFailedMessage("没有对应计算条件"); continue; } } else { ruleMatchList.add(mr); mr.setValid(true); } continue; } ruleMatchList.add(mr); String vt; if (null == (vt = r.getValueType())) { // 无值时相当于直接通过 mr.setValid(true); } else if (null != (vt = r.getValueType()) && vt.startsWith("Score")) { mr.setValue(null != currTotal ? String.valueOf(currTotal.intValue()) : ""); if (null == lastSubmit || null == lastSubmit.getScore() || null == lastSubmit.getScoreTotal() && !isSameYear) { mr.setFailedMessage("缺历史录取数据"); continue; } else if (typeChange) { mr.setFailedMessage("规则变更,无法计算"); continue; } else if (!formulaScoreStat.isValid() && (!isAi || inputScoreRate <= 0.0)) { mr.setFailedMessage("用户没有填写完整"); continue; } mr.setValid(true); Integer validScoreTotal = isSameYear ? formulaScoreStat.getAllTotal() : lastSubmit.getScoreTotal(); Double currScoreRate = isSameYear ? 1.0 : formulaScoreStat.getAllTotal() * 1.0 / lastSubmit.getScoreTotal(); // 去年的分转成今年的分 Double currScore = null; if (null != lastSubmit.getCulturalScore()) { if (null == (currScore = formulaScoreStat.getTypeValue("ScoreSingle", "", false))) { currScore = formulaScoreStat.getTypeValue("ScoreBase", "", false); } if (null != currScore && currScore < lastSubmit.getCulturalScore() * currScoreRate) { // mr.setValid(false); mr.setMissingValue(String.valueOf(Math.round(lastSubmit.getCulturalScore() * currScoreRate - currScore))); mr.setFailedMessage("校考分低于分数线"); } } if (null != lastSubmit.getProfScore() && null != (currScore = formulaScoreStat.getTypeValue("ScoreSkill", "", false)) && currScore < lastSubmit.getProfScore() * currScoreRate) { // mr.setValid(false); mr.setMissingValue(String.valueOf(Math.round(lastSubmit.getProfScore() * currScoreRate - currScore))); mr.setFailedMessage("技能测试分低于分数线"); } // 检查总分,学考(文化),专业(技能) EnrollRateCalculator.RateLevel rl; if (null != lastSubmit.getScore() && currTotal != null && null != (rl = enrollRateCalculator.calSchoolEnrollRate(validScoreTotal, lastSubmit.getScore(), currTotal / currScoreRate))) { // 按去年标准算概率 mr.setRl(rl); mr.setEnrollRate(rl.rate); mr.setEnrollRateText(rl.typeLabel); mr.setEnumPickType(rl.type); if (mr.getValid() && currTotal < lastSubmit.getScore() * currScoreRate) { // mr.setValid(false); mr.setMissingValue(String.valueOf(Math.round(lastSubmit.getScore() * currScoreRate - currTotal))); // 按今年的算差值 mr.setFailedMessage("综合分低于分数线"); } } } else { // 专项符合型 mr.setValid(processPassCheck(paramMap, formulaScoreStat, r.getValueRule(), mr, r.getValueType(), r.getItemField(), r.getValuePassRule())); } } } if (null != specialList) { existSet.clear(); List validSpecialList = Lists.newArrayList(); Map>> groupMutexOptionsMap = Maps.newHashMap(); for (AEnrollSpecial r : specialList) { if (StringUtils.isNotBlank(r.getGender()) && !r.getGender().equals(gender) || StringUtils.isNotBlank(r.getMajorName()) && !Sets.newHashSet(r.getMajorName().split(",")).contains(needMajor) || StringUtils.isNotBlank(r.getMajorDirection()) && !r.getMajorDirection().equals(needDirect)) { continue; } if(r.getValueType().startsWith("StatBMI")) { // TODO 身高体重的名称需要是固定的 String height = paramMap.get("身高"); String weight = paramMap.get("体重"); Integer iHeight; if (StringUtils.isNotBlank(height) && StringUtils.isNotBlank(weight) && (iHeight = NumberUtils.toInt(height, 0)) > 0) { paramMap.put(r.getItemField(), String.valueOf(NumberUtils.toInt(height, 0) * 100 / iHeight)); } } else if (null != r.getItemGroup() && "Checkbox".equals(r.getValueType())) { Pair> p = getGroupOptions(groupMutexOptionsMap, mutexOptionMap, paramMap, r.getItemGroup()); if (p.getRight().size() == 0) { // 无值时 paramMap.put(r.getItemField(), null); } else if (StringUtils.isNotBlank(p.getLeft()) && p.getRight().contains(p.getLeft())) { // 选中互斥时全是否 paramMap.put(r.getItemField(), !p.getLeft().contains("无") ? "[\"是\"]" : "[\"否\"]"); } else { paramMap.put(r.getItemField(), p.getRight().contains(r.getItemName()) ? "[\"是\"]" : "[\"否\"]"); } } validSpecialList.add(r); } for (AEnrollSpecial r : validSpecialList) { VoluntaryDto.MajorEnrollRule mr = new VoluntaryDto.MajorEnrollRule(); mr.setCategory(VoluntaryDto.EnumRuleCategory.Special); mr.setContent(r.getEnrollFormula()); mr.setDescription(r.getComment()); ruleMatchList.add(mr); if(isScoreOnly) { mr.setType(VoluntaryDto.EnumRuleType.Readonly); mr.setValid(true); continue; } mr.setType(itemType2RuleType(r.getItemType(), r.getValueType(), false)); if (VoluntaryDto.EnumRuleType.Readonly.equals(mr.getType())) { mr.setValid(true); } else { mr.setValid(processPassCheck(paramMap, formulaScoreStat, r.getValueRule(), mr, r.getValueType(), r.getItemField(), r.getValuePassRule())); } } } existSet.clear(); Map historyPlanMap = historyPlanList.stream().collect(Collectors.toMap(t -> t.getYear() + t.getMajorName() + StringUtils.trimToEmpty(t.getMajorDirection()), Function.identity())); for (AMarjorSubmit s : validSubmitList) { if ("初录".equals(s.getEnrollType())) { VoluntaryDto.MajorEnrollHistory h = new VoluntaryDto.MajorEnrollHistory(); h.setYear(s.getYear()); h.setScore(null != s.getScore() ? String.valueOf(s.getScore()) : ""); // TODO 240301 直接输出录取分 /*if (null != currTotal && null != s.getScore()) { Double diff = currTotal - s.getScore(); h.setScore(diff > 0 ? "+" + diff.intValue() : "" + diff.intValue()); // TODO 需要一个分来比较,综合分? } else { h.setScore(""); }*/ AMarjorPlan p = historyPlanMap.get(s.getYear() + s.getMajorName() + StringUtils.trimToEmpty(s.getMajorDirection())); if(null != p) { h.setPlan(p.getPlanTotal()); // TODO 估计输出录取人数 23.12.26 分开输入录取和计划 24.12.27 } else { // System.out.println(s.getId()); } h.setEnroll(s.getEnrollTotal()); histories.add(h); } else { /*VoluntaryDto.MajorClearingHistory c = new VoluntaryDto.MajorClearingHistory(); c.setYear(s.getYear()); if (null != currTotal && null != s.getScore()) { Double diff = currTotal - s.getScore(); c.setScore(diff > 0 ? "+" + diff.intValue() : "" + diff.intValue()); // TODO 需要一个分来比较,综合分? } else { c.setScore(""); } c.setRealNum(s.getEnrollTotal()); clearings.add(c);*/ // TODO 240301 关闭补录 } } VoluntaryDto.SingleResponse sr = new VoluntaryDto.SingleResponse(); sr.setUniversityCode(u.getCode()); sr.setMajorCode(null != prof ? prof.getCode() : ""); sr.setMajorName(needMajor); sr.setMajorDirection(needDirect); // 查找最高的专业 EnrollRule 为本专业的,理论上只有一个合并rule有此值 EnrollRateCalculator.RateLevel lastRl = null; boolean specialValid = true, specialPass = true; for (VoluntaryDto.MajorEnrollRule er : ruleMatchList) { if (null != er.getRl() && (null == lastRl || er.getRl().getRate() < lastRl.getRate())) { lastRl = er.getRl(); } if ((specialPass || specialValid) && VoluntaryDto.EnumRuleType.Special.equals(er.getType())) { if (null == er.getValid()) { specialValid = false; } else if (!er.getValid()) { specialPass = false; } } } if (!specialPass) { sr.setEnrollRate(0); sr.setEnrollRateText("零概率"); sr.setEnumPickEmpty(VoluntaryDto.EnumPickEmpty.EnrollPass); } else if (null != lastRl && specialValid) { sr.setEnumPickType(lastRl.getType()); sr.setEnrollRate(lastRl.getRate()); sr.setEnrollRateText(lastRl.getTypeLabel()); } else { sr.setEnrollRateText("无概率"); sr.setEnumPickEmpty(VoluntaryDto.EnumPickEmpty.New); } if (null != currPlan) { sr.setMajorGroup(currPlan.getMajorGroup()); // 没有MajorEnrollId, 暂时用这个 sr.setMajorEnrollCode(StringUtils.isBlank(currPlan.getMajorEnrollCode()) ? String.valueOf(currPlan.getId()) : currPlan.getMajorEnrollCode()); sr.setTips(null != currPlan ? currPlan.getComment() : ""); } sr.setHistories(histories); sr.setClearings(clearings); sr.setRules(ruleMatchList); sr.setImproves(improveList); sr.setScore(currTotal); if (!isScoreOnly && null != lastSubmit && null != lastSubmit.getScore() && null != currTotal && currTotal < lastSubmit.getScore()) { Double diffValue = lastSubmit.getScore() - currTotal; sr.setImproves(formulaScoreStat.getImproveScore(diffValue)); } return sr; } private void appendScoreRule(VoluntaryDto.FormulaScoreStat formulaScoreStat, Set existSet, AEnrollScore r, List fEnrollScoreList, Boolean isAi, Map paramMap, Double inputScoreRate, Boolean isSkillScore) { String vt, iv; Double currScore = null; Double scoreRate = null; Double tmpValue; // 总分,得分 if (null != (vt = r.getValueType()) && vt.startsWith("Score")) { //需要合并Score型(ScoreSingle, ScoreBase, ScoreSkill)的各类成绩, 其他为符合条件 if (existSet.add(r.getEnrollFormula())) { // 合并规则只留第一个 if (!existSet.add("_ScoreFormula_")) { existSet.remove(r.getEnrollFormula()); return; } fEnrollScoreList.add(r); } if (null != r.getValueRule() && (scoreRate = Double.parseDouble(r.getValueRule())) <= 0.0) { scoreRate = 1.0; } formulaScoreStat.addTypeTotal(r.getScoreTotal()); if (isAi && vt.equals("ScoreRate")) { // 根据得分率及总分计算分值 currScore = isSkillScore ? 0.0 : r.getScoreTotal() * inputScoreRate; formulaScoreStat.addGroup(r.getItemGroup(), currScore, r.getScoreTotal().doubleValue(), scoreRate); formulaScoreStat.addType(r.getItemType(), r.getItemField(), currScore, scoreRate); } else { currScore = (!isSkillScore && StringUtils.isNotBlank((iv = paramMap.get(r.getItemField())))) ? NumberUtils.toDouble(iv, 0.0) : 0.0; formulaScoreStat.addGroup(r.getItemGroup(), currScore, r.getScoreTotal().doubleValue(), scoreRate); formulaScoreStat.addType(r.getItemType(), r.getItemField(), currScore, scoreRate); } } else { fEnrollScoreList.add(r); } } private VoluntaryDto.MajorEnrollRule buildEnrollRule(AEnrollScore r) { VoluntaryDto.MajorEnrollRule mr = new VoluntaryDto.MajorEnrollRule(); mr.setCategory(VoluntaryDto.EnumRuleCategory.Enroll); mr.setType(itemType2RuleType(r.getItemType(), r.getValueType(), true)); // 学考 ScoreSingle 强转为 ScoreTotal, ScoreBase 校考, ScoreSkill 技能, Special 专项 mr.setContent(r.getEnrollFormula()); mr.setImproveType(r.getItemCategory()); mr.setDescription(r.getComment()); return mr; } private Pair> getGroupOptions(Map>> groupOptionsMap, Map mutexOptionMap, Map paramMap, String itemGroup) { String[] groupNameField = StringUtils.split(itemGroup, "_"); String groupFieldName = groupNameField[groupNameField.length > 1 ? 1 : 0]; Pair> pair = groupOptionsMap.get(groupFieldName); if(null == pair) { String iv = paramMap.get(groupFieldName); Set options = StringUtils.isNotBlank(iv) ? JSONArray.parseArray(iv).stream().map(t -> (String) t).collect(Collectors.toSet()) : Sets.newHashSet(); pair = new MutablePair<>(mutexOptionMap.get(groupFieldName), options); groupOptionsMap.put(groupFieldName, pair); } return pair; } private Boolean processPassCheck(Map paramMap, VoluntaryDto.FormulaScoreStat stat, String valueRule, VoluntaryDto.MajorEnrollRule mr, String valueType, String itemField, String passRule) { Boolean matched = null; Double tmpValue; boolean isStat = null != valueType && valueType.startsWith("Stat"); if (isStat || NumberTypeSet.contains(valueType)) { Double v = null; String iv; if (isStat) { // TODO 统计分 v = stat.getTypeValue(valueType, itemField, "0".equals(valueRule)); } else if(StringUtils.isNotBlank(passRule) && StringUtils.isNotBlank((iv = paramMap.get(itemField))) && (tmpValue = NumberUtils.toDouble(iv, 0.0)) > 0.01) { v = tmpValue; } if (v != null) { String[] range = passRule.split("-"); if (StringUtils.isNotBlank(range[0]) && (tmpValue = NumberUtils.toDouble(range[0], 0.0)) > 0.01 && v < tmpValue) { matched = false; mr.setFailedMessage("小于最大值"); } else if (range.length > 1 && StringUtils.isNotBlank(range[1]) && (tmpValue = NumberUtils.toDouble(range[1], 0.0)) > 0.01 && v > tmpValue) { matched = false; mr.setFailedMessage("超过最大值"); } else { matched = true; } } else { mr.setFailedMessage("未输入参数"); } } else if ("Radio".equals(valueType)) { String iv = paramMap.get(itemField); if (StringUtils.isNotBlank(iv)) { if (!(matched = StringUtils.isNotBlank(passRule) && passRule.contains(iv))) { mr.setFailedMessage("条件不满足"); } } else { mr.setFailedMessage("未输入参数"); } } else if ("Checkbox".equals(valueType) || "Picker".equals(valueType)) { String iv = paramMap.get(itemField); if(StringUtils.isBlank(passRule)) { if (!(matched = StringUtils.isBlank(iv))) { mr.setFailedMessage("选择条件不满足1"); } } else if (StringUtils.isNotBlank(iv)) { List valueList = Arrays.asList(passRule.split(",")); List inputList = JSONArray.parseArray(iv).stream().map(t -> (String) t).collect(Collectors.toList()); if (!(matched = CollectionUtils.intersection(valueList, inputList).size() == valueList.size())) { mr.setFailedMessage("选择条件不满足2"); } } } return matched; } private void sortAndExtractEnroll(List singleResponseList, VoluntaryDto.AIResponse aiResp) { if (CollectionUtils.isEmpty(singleResponseList)) { aiResp.setEnrollRate(null); aiResp.setEnrollRateText("无概率"); aiResp.setEnumPickEmpty(VoluntaryDto.EnumPickEmpty.EnrollPass); } Collections.sort(singleResponseList, new Comparator() { @Override public int compare(VoluntaryDto.SingleResponse o1, VoluntaryDto.SingleResponse o2) { Integer d1 = o1.getEnrollRate(); Integer d2 = o2.getEnrollRate(); if (null == d1) { if (null != d2) { return 1; } return 0; } else if (null == d2) { return -1; } return -d1.compareTo(d2); } }); for (VoluntaryDto.SingleResponse sr : singleResponseList) { aiResp.setEnrollRate(sr.getEnrollRate()); aiResp.setEnrollRateText(sr.getEnrollRateText()); aiResp.setEnumPickType(sr.getEnumPickType()); aiResp.setEnumPickEmpty(sr.getEnumPickEmpty()); break; } } public R getVoluntaryConfig() { // 如果有填报配置相关,放在这里 VoluntaryDto.VoluntaryConfig resp = new VoluntaryDto.VoluntaryConfig(); return R.ok(resp); } public List getVoluntaryList(@ApiParam @RequestParam VoluntaryDto.EnumVoluntaryType type) { // 我的志愿表 // 后台填充快照缺省 AWishRecord cond = new AWishRecord(); cond.setUserId(SecurityUtils.getLoginUser().getUserId()); if (null != type) { cond.setType(type.name()); } cond.setStatus(1); List aWishRecordList = aWishRecordMapper.selectAWishRecordList(cond); List dtoList = Lists.newArrayList(); aWishRecordList.stream().forEach(t -> { dtoList.add(toModel(t)); }); return PageUtil.getDtoListWithPageable(aWishRecordList, dtoList); } public R submitVoluntary(JSONObject model) { // 填报 // 前端+后台按需要剔除一些不需快照的信息(目前主要是院校信息) SysUser user = SecurityUtils.getLoginUser().getUser(); AWishRecord wishRecord = new AWishRecord(); VoluntaryDto.User userSnapshot = new VoluntaryDto.User(); userSnapshot.setName(user.getNickName()); userSnapshot.setSex(user.getSex()); userSnapshot.setExamType(user.getExamType().title()); // TODO MF userSnapshot.setProvinceName(user.getLocation()); Long modelId = null; String modelName = null; Integer year = null; VoluntaryDto.EnumVoluntaryType type = null; try { modelId = model.getLong("id"); modelName = model.getString("name"); year = model.getInteger("year"); type = VoluntaryDto.EnumVoluntaryType.valueOf(model.getString("voluntaryType")); wishRecord.setBatchName(model.getString("batchName")); wishRecord.setRequest(model.getString("request")); wishRecord.setDetails(model.getString("details")); wishRecord.setUserSnapshot(mapper.writeValueAsString(userSnapshot)); } catch (JsonProcessingException e) { return R.fail("格式错误: " + modelId); } wishRecord.setYear(null == year ? getPlanYear(user) : year); wishRecord.setType(type.name()); if (null != modelId) { wishRecord.setUpdateTime(new Date()); wishRecord.setId(modelId); wishRecord.setName(modelName); wishRecord.setUpdateTime(new Date()); aWishRecordMapper.updateAWishRecord(wishRecord); } else { wishRecord.setCreateTime(new Date()); wishRecord.setSeq(getWishSeq(wishRecord.getYear(), wishRecord.getType())); wishRecord.setName(StringUtils.isNotBlank(modelName) ? modelName : ("AI".equals(wishRecord.getType()) ? "AI志愿" : "模拟志愿") + wishRecord.getSeq()); wishRecord.setUserId(user.getUserId()); wishRecord.setStatus(1); aWishRecordMapper.insertAWishRecord(wishRecord); } return R.ok(wishRecord.getId()); } private Integer getWishSeq(Integer year, String type) { AWishRecord cond = new AWishRecord(); cond.setUserId(SecurityUtils.getLoginUser().getUserId()); cond.setYear(year); cond.setType(type); List aWishRecordList = aWishRecordMapper.selectAWishRecordList(cond); Integer newSeq = CollectionUtils.isNotEmpty(aWishRecordList) ? aWishRecordList.get(0).getSeq() + 1 : 1; return newSeq; } public void obsoleteWishRecord(Long userId) { aWishRecordMapper.updateObsoleteByUser(userId); busiWishRecordsMapper.updateObsoleteByUser(userId); } public R getVoluntary(Long id) { // 志愿表详情 // 后台填充快照缺省 SysUser user = SecurityUtils.getLoginUser().getUser(); AWishRecord wishRecord = aWishRecordMapper.selectAWishRecordById(id); if (null == wishRecord || !SecurityUtils.getUserId().equals(wishRecord.getUserId())) { return R.fail("错误id"); } if (null == wishRecord) { throw new ServiceException("无此志愿id"); } else if (!user.getUserId().equals(wishRecord.getUserId())) { throw new ServiceException("无此志愿id号"); } JSONObject resp = toModel(wishRecord); return R.ok(resp); } private JSONObject toModel(AWishRecord wishRecord) { SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); JSONObject model = new JSONObject(); model.put("id", wishRecord.getId()); model.put("year", wishRecord.getYear()); model.put("voluntaryType", VoluntaryDto.EnumVoluntaryType.valueOf(wishRecord.getType())); model.put("name", wishRecord.getName()); model.put("batchName", wishRecord.getBatchName()); model.put("createTime", sdf.format(wishRecord.getCreateTime())); try { model.put("userSnapshot", mapper.readValue(wishRecord.getUserSnapshot(), VoluntaryDto.User.class)); model.put("request", JSONObject.parseObject(wishRecord.getRequest())); model.put("details", JSONArray.parseArray(wishRecord.getDetails())); } catch (JsonProcessingException e) { e.printStackTrace(); } return model; } private VoluntaryDto.SingleResponse buildTestResp() { String json = sysConfigService.selectConfigByKey("demo.voluntary.single"); if (StringUtils.isNotBlank(json)) { try { return mapper.readValue(json, VoluntaryDto.SingleResponse.class); } catch (JsonProcessingException e) { e.printStackTrace(); } } return new VoluntaryDto.SingleResponse(); } private VoluntaryDto.AIResponse buildAiResp() { String json = sysConfigService.selectConfigByKey("demo.voluntary.ai"); if (StringUtils.isNotBlank(json)) { try { VoluntaryDto.AIResponse resp = mapper.readValue(json, VoluntaryDto.AIResponse.class); resp.setMajorDetails(Lists.newArrayList(buildTestResp())); return resp; } catch (JsonProcessingException e) { e.printStackTrace(); } } return new VoluntaryDto.AIResponse(); } private VoluntaryDto.VoluntaryModel buildModel() { String json = sysConfigService.selectConfigByKey("demo.voluntary.model"); if(StringUtils.isNotBlank(json)) { try { VoluntaryDto.VoluntaryModel model = mapper.readValue(json, VoluntaryDto.VoluntaryModel.class); model.setDetails(Lists.newArrayList(buildAiResp())); return model; } catch (JsonProcessingException e) { e.printStackTrace(); } } return new VoluntaryDto.VoluntaryModel(); } private VoluntaryDto.EnumRuleType itemType2RuleType(String itemType, String valueType, boolean foreSingleTotal) { if ("Notice".equals(valueType)) { return VoluntaryDto.EnumRuleType.Readonly; } else if (foreSingleTotal && VoluntaryDto.EnumRuleType.ScoreSingle.name().equals(itemType)) { return VoluntaryDto.EnumRuleType.ScoreTotal; } return VoluntaryDto.EnumRuleType.valueOf(itemType); } public List getVoluntaryList2() { // 我的志愿表 // 后台填充快照缺省 AWishRecord cond = new AWishRecord(); cond.setUserId(SecurityUtils.getLoginUser().getUserId()); cond.setStatus(1); List aWishRecordList = aWishRecordMapper.selectAWishRecordList(cond); if(CollectionUtils.isEmpty(aWishRecordList)) { return Collections.emptyList(); } return JSONArray.parseArray(aWishRecordList.get(0).getDetails(), VoluntaryDto.VoluntaryRecord.class); } public R addVoluntary2(JSONObject model) { // 填报 // 前端+后台按需要剔除一些不需快照的信息(目前主要是院校信息) SysUser user = SecurityUtils.getLoginUser().getUser(); AWishRecord wishRecord = getWishRecord(user.getUserId()); List voluntaryRecordList = (null == wishRecord.getId()) ? Lists.newArrayList() : JSONArray.parseArray(wishRecord.getDetails(), VoluntaryDto.VoluntaryRecord.class); Long universityId = model.getLong("universityId"); Long majorId = model.getLong("majorId"); Optional optionalVoluntary = voluntaryRecordList.stream().filter(t -> t.getUniversityId().equals(universityId)).findFirst(); VoluntaryDto.VoluntaryRecord voluntaryRecord; if(optionalVoluntary.isPresent()) { voluntaryRecord = optionalVoluntary.get(); if(null == voluntaryRecord.getMajors()) { voluntaryRecord.setMajors(Lists.newArrayList()); } } else { BBusiWishUniversities u = bBusiWishUniversitiesMapper.selectBBusiWishUniversitiesById(universityId); voluntaryRecord = new VoluntaryDto.VoluntaryRecord(); voluntaryRecord.setUniversityLogo(u.getLogo()); voluntaryRecord.setUniversityName(u.getName()); voluntaryRecord.setUniversityId(u.getId()); voluntaryRecord.setMajors(Lists.newArrayList()); voluntaryRecord.setRank(voluntaryRecordList.size() + 1); voluntaryRecordList.add(voluntaryRecord); } Optional optionalMajor = voluntaryRecord.getMajors().stream().filter( t -> t.getMajorId().equals(majorId)).findFirst(); if(!optionalMajor.isPresent()) { AMarjorPlan p = aMarjorPlanMapper.selectAMarjorPlanById(majorId); VoluntaryDto.VoluntaryMajorRecord major = new VoluntaryDto.VoluntaryMajorRecord(); major.setMajorId(p.getId()); major.setMajorGroup(p.getMajorGroup()); major.setMajorName(p.getMajorName()); major.setMajorAncestors(""); major.setRank(voluntaryRecord.getMajors().size() + 1); voluntaryRecord.getMajors().add(major); } wishRecord.setDetails(JSONArray.toJSONString(voluntaryRecordList)); wishRecord.setYear(getPlanYear(user)); if (null != wishRecord.getId()) { wishRecord.setUpdateTime(new Date()); wishRecord.setUpdateTime(new Date()); aWishRecordMapper.updateAWishRecord(wishRecord); } else { wishRecord.setCreateTime(new Date()); wishRecord.setUserId(user.getUserId()); wishRecord.setStatus(1); aWishRecordMapper.insertAWishRecord(wishRecord); } return R.ok(wishRecord.getId()); } public Boolean removeVoluntaryByUniversity(Long userId, Long universityId) { AWishRecord wishRecord = getWishRecord(userId); List voluntaryRecordList = JSONArray.parseArray(wishRecord.getDetails(), VoluntaryDto.VoluntaryRecord.class); List newRecordList = Lists.newArrayList(); for(VoluntaryDto.VoluntaryRecord r : voluntaryRecordList) { if(r.getUniversityId().equals(universityId)) { continue; } r.setRank(newRecordList.size()); newRecordList.add(r); } updateWishRecord(wishRecord, newRecordList); return true; } public Boolean removeVoluntaryByMajor(Long userId, Long majorId) { AMarjorPlan plan = aMarjorPlanMapper.selectAMarjorPlanById(majorId); if(null == plan) { throw new RuntimeException("错误的专业计划ID"); } AWishRecord wishRecord = getWishRecord(userId); List voluntaryRecordList = JSONArray.parseArray(wishRecord.getDetails(), VoluntaryDto.VoluntaryRecord.class); Optional optionalVoluntary = voluntaryRecordList.stream().filter(t -> t.getUniversityId().equals(plan.getUniversityId())).findFirst(); if(!optionalVoluntary.isPresent()) { throw new RuntimeException("错误的院校ID"); } VoluntaryDto.VoluntaryRecord voluntaryRecord = optionalVoluntary.get(); List newRecordList = Lists.newArrayList(); for(VoluntaryDto.VoluntaryMajorRecord r : voluntaryRecord.getMajors()) { if(r.getMajorId().equals(majorId)) { continue; } r.setRank(newRecordList.size()); newRecordList.add(r); } if(newRecordList.isEmpty()) { updateWishRecord(wishRecord, voluntaryRecordList.stream().filter(t -> !t.getUniversityId().equals(plan.getUniversityId())).collect(Collectors.toList())); } else { voluntaryRecord.setMajors(newRecordList); updateWishRecord(wishRecord, voluntaryRecordList); } return true; } public void sortVoluntaryByMajor(Long userId, Long universityId, Map majorRankMap) { AWishRecord wishRecord = getWishRecord(userId); List voluntaryRecordList = JSONArray.parseArray(wishRecord.getDetails(), VoluntaryDto.VoluntaryRecord.class); Optional optionalVoluntary = voluntaryRecordList.stream().filter(t -> t.getUniversityId().equals(universityId)).findFirst(); VoluntaryDto.VoluntaryRecord voluntaryRecord; if(!optionalVoluntary.isPresent()) { throw new RuntimeException("错误的院校ID"); } voluntaryRecord = optionalVoluntary.get(); Integer rank; for(VoluntaryDto.VoluntaryMajorRecord record : voluntaryRecord.getMajors()) { if(null == (rank = majorRankMap.remove(record.getMajorId()))) { throw new RuntimeException("错误的专业计划ID"); } record.setRank(rank); } Collections.sort(voluntaryRecord.getMajors(), new Comparator() { @Override public int compare(VoluntaryDto.VoluntaryMajorRecord o1, VoluntaryDto.VoluntaryMajorRecord o2) { return o1.getRank().compareTo(o2.getRank()); } }); updateWishRecord(wishRecord, voluntaryRecordList); } public void sortVoluntaryByUniversity(Long userId, Map universityRankMap) { AWishRecord wishRecord = getWishRecord(userId); List voluntaryRecordList = JSONArray.parseArray(wishRecord.getDetails(), VoluntaryDto.VoluntaryRecord.class); Integer rank; for(VoluntaryDto.VoluntaryRecord record : voluntaryRecordList) { if(null == (rank = universityRankMap.remove(record.getUniversityId()))) { throw new RuntimeException("错误的院校ID"); } record.setRank(rank); } Collections.sort(voluntaryRecordList, new Comparator() { @Override public int compare(VoluntaryDto.VoluntaryRecord o1, VoluntaryDto.VoluntaryRecord o2) { return o1.getRank().compareTo(o2.getRank()); } }); updateWishRecord(wishRecord, voluntaryRecordList); } private void updateWishRecord(AWishRecord wishRecord, List voluntaryRecordList) { wishRecord.setUpdateTime(new Date()); wishRecord.setUpdateTime(new Date()); wishRecord.setDetails(JSONArray.toJSONString(voluntaryRecordList)); aWishRecordMapper.updateAWishRecord(wishRecord); } private AWishRecord getWishRecord(Long userId) { AWishRecord wrCond = new AWishRecord(); wrCond.setUserId(userId); wrCond.setStatus(1); List wishList = aWishRecordMapper.selectAWishRecordList(wrCond); return wishList.isEmpty() ? new AWishRecord() : wishList.get(0); } }