VoluntaryService.java 65 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188
  1. package com.ruoyi.web.service;
  2. import com.alibaba.fastjson2.JSONArray;
  3. import com.alibaba.fastjson2.JSONException;
  4. import com.alibaba.fastjson2.JSONObject;
  5. import com.fasterxml.jackson.core.JsonProcessingException;
  6. import com.fasterxml.jackson.core.type.TypeReference;
  7. import com.fasterxml.jackson.databind.DeserializationFeature;
  8. import com.fasterxml.jackson.databind.ObjectMapper;
  9. import com.google.common.collect.Lists;
  10. import com.google.common.collect.Maps;
  11. import com.google.common.collect.Sets;
  12. import com.ruoyi.common.core.content.VistorContextHolder;
  13. import com.ruoyi.common.core.domain.R;
  14. import com.ruoyi.common.core.domain.entity.SysUser;
  15. import com.ruoyi.common.core.page.TableDataInfo;
  16. import com.ruoyi.common.exception.ServiceException;
  17. import com.ruoyi.common.utils.SecurityUtils;
  18. import com.ruoyi.common.utils.StringUtils;
  19. import com.ruoyi.ie.domain.*;
  20. import com.ruoyi.ie.mapper.*;
  21. import com.ruoyi.system.service.ISysConfigService;
  22. import com.ruoyi.syzy.domain.BBusiWishUniversities;
  23. import com.ruoyi.syzy.domain.BBusiWishUniversitiesProfession;
  24. import com.ruoyi.syzy.dto.UniversityDetailDTO;
  25. import com.ruoyi.syzy.mapper.BBusiWishRecordsMapper;
  26. import com.ruoyi.syzy.mapper.BBusiWishUniversitiesMapper;
  27. import com.ruoyi.syzy.mapper.BBusiWishUniversitiesProfessionMapper;
  28. import com.ruoyi.util.PageUtil;
  29. import com.ruoyi.web.domain.Constant;
  30. import com.ruoyi.web.domain.VoluntaryDto;
  31. import io.swagger.annotations.ApiParam;
  32. import org.apache.commons.collections.CollectionUtils;
  33. import org.apache.commons.collections.MapUtils;
  34. import org.apache.commons.lang3.ArrayUtils;
  35. import org.apache.commons.lang3.math.NumberUtils;
  36. import org.apache.commons.lang3.tuple.MutablePair;
  37. import org.apache.commons.lang3.tuple.Pair;
  38. import org.springframework.stereotype.Service;
  39. import org.springframework.web.bind.annotation.RequestParam;
  40. import java.text.SimpleDateFormat;
  41. import java.util.*;
  42. import java.util.function.Function;
  43. import java.util.stream.Collectors;
  44. @Service
  45. public class VoluntaryService {
  46. private ObjectMapper mapper = new ObjectMapper();
  47. private static TypeReference<List<VoluntaryDto.SingleResponse>> wishDetailsTypeReference = new TypeReference<List<VoluntaryDto.SingleResponse>>() { };
  48. private static TypeReference<List<VoluntaryDto.AIResponse>> wishAiDetailsTypeReference = new TypeReference<List<VoluntaryDto.AIResponse>>() { };
  49. Set<String> NumberTypeSet = Sets.newHashSet(VoluntaryDto.EnumInputType.Number.name(), VoluntaryDto.EnumInputType.Eyesight.name(), VoluntaryDto.EnumInputType.Score.name());
  50. private final AWishRecordMapper aWishRecordMapper;
  51. private final AEnrollScoreMapper aEnrollScoreMapper;
  52. private final AEnrollSpecialMapper aEnrollSpecialMapper;
  53. private final AMarjorPlanMapper aMarjorPlanMapper;
  54. private final AMarjorSubmitMapper aMarjorSubmitMapper;
  55. private final AEnrollUniversityMapper aEnrollUniversityMapper;
  56. private final BBusiWishUniversitiesMapper bBusiWishUniversitiesMapper;
  57. private final BBusiWishUniversitiesProfessionMapper bBusiWishUniversitiesProfessionMapper;
  58. private final ISysConfigService sysConfigService;
  59. private final EnrollRateCalculator enrollRateCalculator;
  60. private final BBusiWishRecordsMapper busiWishRecordsMapper;
  61. public VoluntaryService(AWishRecordMapper aWishRecordMapper, AEnrollScoreMapper aEnrollScoreMapper, AEnrollSpecialMapper aEnrollSpecialMapper, AMarjorPlanMapper aMarjorPlanMapper, AMarjorSubmitMapper aMarjorSubmitMapper, AEnrollUniversityMapper aEnrollUniversityMapper, BBusiWishUniversitiesMapper bBusiWishUniversitiesMapper, BBusiWishUniversitiesProfessionMapper bBusiWishUniversitiesProfessionMapper, ISysConfigService sysConfigService, EnrollRateCalculator enrollRateCalculator, BBusiWishRecordsMapper busiWishRecordsMapper) {
  62. this.aWishRecordMapper = aWishRecordMapper;
  63. this.aEnrollScoreMapper = aEnrollScoreMapper;
  64. this.aEnrollSpecialMapper = aEnrollSpecialMapper;
  65. this.aMarjorPlanMapper = aMarjorPlanMapper;
  66. this.aMarjorSubmitMapper = aMarjorSubmitMapper;
  67. this.aEnrollUniversityMapper = aEnrollUniversityMapper;
  68. this.bBusiWishUniversitiesMapper = bBusiWishUniversitiesMapper;
  69. this.bBusiWishUniversitiesProfessionMapper = bBusiWishUniversitiesProfessionMapper;
  70. this.sysConfigService = sysConfigService;
  71. this.enrollRateCalculator = enrollRateCalculator;
  72. this.busiWishRecordsMapper = busiWishRecordsMapper;
  73. // mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
  74. mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
  75. }
  76. public Pair<List<UniversityDetailDTO.WishPlan>, List<UniversityDetailDTO.WishSubmit>> getUniversityHistory(Long universityId, String province, String examineType) {
  77. AMarjorPlan planCond = new AMarjorPlan();
  78. planCond.setUniversityId(universityId);
  79. planCond.setExamineeType(examineType);
  80. List<UniversityDetailDTO.WishPlan> planList = aMarjorPlanMapper.selectAMarjorPlanList(planCond).stream().map(t -> {
  81. UniversityDetailDTO.WishPlan p = new UniversityDetailDTO.WishPlan();
  82. p.setId(t.getId());
  83. p.setCollegeCode(t.getEnrollCode());
  84. p.setYear(String.valueOf(t.getYear()));
  85. p.setLevel(t.getLevel());
  86. p.setType("");
  87. p.setMarjorCode(t.getMajorCode());
  88. p.setMarjorName(t.getMajorName());
  89. p.setMarjorBelongs(t.getMajorEnrollCode());
  90. p.setMarjorDirection(t.getMajorDirection());
  91. p.setSpecialProject("");
  92. p.setPlanCount(t.getPlanTotal());
  93. p.setXuefei(String.valueOf(t.getXuefei()));
  94. p.setXuezhi(String.valueOf(t.getLengthOfSchooling()));
  95. p.setEnrollFormula(t.getEnrollFormula());
  96. p.setGroupsName(t.getMajorGroup());
  97. return p;
  98. }).collect(Collectors.toList());
  99. AMarjorSubmit submitCond = new AMarjorSubmit();
  100. submitCond.setUniversityId(universityId);
  101. submitCond.setEnrollType("初录");
  102. submitCond.setExamineeType(examineType);
  103. List<UniversityDetailDTO.WishSubmit> submitList = aMarjorSubmitMapper.selectAMarjorSubmitList(submitCond).stream().map(t -> {
  104. UniversityDetailDTO.WishSubmit s = new UniversityDetailDTO.WishSubmit();
  105. s.setId(t.getId());
  106. s.setYear(String.valueOf(t.getYear()));
  107. s.setLevel(t.getLevel());
  108. s.setType("");
  109. s.setMarjorCode("");
  110. s.setMarjorName(t.getMajorName());
  111. s.setMarjorBelongs("");
  112. s.setMarjorDirection(t.getMajorDirection());
  113. s.setSpecialProject("");
  114. s.setScore(null != t.getScore() ? t.getScore().longValue() : null);
  115. s.setSeat(null);
  116. s.setNumReal(null != t.getEnrollTotal() ? t.getEnrollTotal().longValue() : null);
  117. s.setEnrollFormula(t.getEnrollFormula());
  118. s.setGroupsName(t.getMajorGroup());
  119. return s;
  120. }).collect(Collectors.toList());
  121. return Pair.of(planList, submitList);
  122. }
  123. private void setOptionValue(VoluntaryDto.AIRenderRule r, String valueType, String valueRule, String options, Integer correctType, String correctValue, Integer scoreTotal) {
  124. r.setEnumInputType(VoluntaryDto.EnumInputType.valueOf(valueType));
  125. if (VoluntaryDto.EnumInputType.Score.equals(r.getEnumInputType())) {
  126. r.setOptions(new String[]{null == scoreTotal ? "0" : String.valueOf(scoreTotal.intValue())});
  127. } else if (StringUtils.isNotBlank(options) && (VoluntaryDto.EnumInputType.Checkbox.equals(r.getEnumInputType())
  128. || VoluntaryDto.EnumInputType.Radio.equals(r.getEnumInputType()) || VoluntaryDto.EnumInputType.Picker.equals(r.getEnumInputType()))) {
  129. r.setOptions(options.split(","));
  130. }
  131. // r.setRequired();
  132. // 词典选项类选项 // 词典类选项的优先级最高
  133. // String dictOptions;
  134. // 非词典选项 // 分制类规则,将多分制在此options中返回
  135. // String[] options;
  136. }
  137. public Integer getPlanYear(SysUser u) {
  138. return 2025;
  139. }
  140. public Integer getSubmitYear() {
  141. return 2025;
  142. }
  143. public R<List<VoluntaryDto.AIRenderRule>> getAIRenderRules(VoluntaryDto.AIRenderRequest req) {
  144. Map cond = new HashMap();
  145. Integer planYear = getPlanYear(SecurityUtils.getLoginUser().getUser());
  146. cond.put("year", planYear);
  147. Set<String> majorCodeSet = null;
  148. String majorGroup = null;
  149. if (ArrayUtils.isNotEmpty(req.getMajorEnrollCodes()) && StringUtils.isNotBlank(req.getMajorEnrollCodes()[0])) {
  150. List<Long> majorEnrollCodes = Arrays.asList(req.getMajorEnrollCodes()).stream().map(t -> NumberUtils.toLong(t, 0L)).collect(Collectors.toList());
  151. for(AMarjorPlan plan : aMarjorPlanMapper.selectMajorCodesByIds(majorEnrollCodes.toArray(new Long[majorEnrollCodes.size()]), planYear)) {
  152. majorGroup = StringUtils.trimToEmpty(plan.getMajorGroup());
  153. majorCodeSet = Sets.newHashSet(plan.getMajorCode());
  154. }
  155. }
  156. if(CollectionUtils.isNotEmpty(majorCodeSet)) {
  157. cond.put("majorGroup", majorGroup);
  158. cond.put("majorGroupCodes", majorCodeSet.toArray(new String[majorCodeSet.size()]));
  159. } else if (ArrayUtils.isNotEmpty(req.getMajorCodes()) && StringUtils.isNotBlank(req.getMajorCodes()[0])) {
  160. cond.put("majorCodes", req.getMajorCodes());
  161. } else if (ArrayUtils.isNotEmpty(req.getMajorTypes()) && StringUtils.isNotBlank(req.getMajorTypes()[0])) {
  162. cond.put("majorTypes", req.getMajorTypes());
  163. } else if (StringUtils.isNotBlank(req.getMajorCategory())) {
  164. cond.put("majorCategory", req.getMajorCategory());
  165. }
  166. cond.put("universityCode", req.getUniversityCode());
  167. return R.ok(findMatchRules(cond, req.getRenderType() == 1, req.getRenderType() == 2));
  168. }
  169. public R<VoluntaryDto.SingleResponse> postSingleResult(VoluntaryDto.SingleRequest req, Boolean isScoreOnly) {
  170. VoluntaryDto.MultipleRequest mr = new VoluntaryDto.MultipleRequest();
  171. VoluntaryDto.CollegeMajorDto collegeMajor = new VoluntaryDto.CollegeMajorDto();
  172. collegeMajor.setCode(req.getUniversityCode());
  173. if (StringUtils.isNotBlank(req.getMajorCode())) {
  174. collegeMajor.setMajorCodes(Lists.newArrayList(req.getMajorCode()));
  175. }
  176. if (StringUtils.isNotBlank(req.getMajorEnrollCode())) {
  177. collegeMajor.setMajorEnrollCodes(Lists.newArrayList(req.getMajorEnrollCode()));
  178. }
  179. collegeMajor.setForm(req.getForm());
  180. mr.setUniversities(Lists.newArrayList(collegeMajor));
  181. List<VoluntaryDto.SingleResponse> respList = postMultipleResult(mr, isScoreOnly).getData();
  182. if (respList.size() > 0) {
  183. Optional<VoluntaryDto.SingleResponse> optionalSingleResponse = respList.stream().filter(t -> StringUtils.isBlank(t.getMajorDirection())).findFirst();
  184. if (optionalSingleResponse.isPresent()) {
  185. return R.ok(optionalSingleResponse.get());
  186. }
  187. }
  188. return respList.size() > 0 ? R.ok(respList.get(0)) : null;
  189. }
  190. public R<List<VoluntaryDto.SingleResponse>> postMultipleResult(VoluntaryDto.MultipleRequest req, boolean isScoreOnly) {
  191. List<VoluntaryDto.SingleResponse> respList = Lists.newArrayList();
  192. for (VoluntaryDto.CollegeMajorDto cm : req.getUniversities()) {
  193. Map cond = new HashMap();
  194. if (CollectionUtils.isNotEmpty(cm.getMajorEnrollCodes()) && StringUtils.isNotBlank(cm.getMajorEnrollCodes().get(0))) {
  195. cond.put("majorEnrollCodes", cm.getMajorEnrollCodes()); // TODO 代替majorCodes更精准,只是现在没有,使用planId代替
  196. } else if (CollectionUtils.isNotEmpty(cm.getMajorCodes()) && StringUtils.isNotBlank(cm.getMajorCodes().get(0))) {
  197. cond.put("majorCodes", cm.getMajorCodes());
  198. } else if (StringUtils.isNotBlank(req.getMajorCategory())) {
  199. cond.put("majorCategory", req.getMajorCategory());
  200. }
  201. cond.put("universityCode", StringUtils.trimToEmpty(cm.getCode()));
  202. List<VoluntaryDto.AIResponse> responses = findMajorSuggest(getPlanYear(SecurityUtils.getLoginUser().getUser()), getSubmitYear(), cond, cm.getForm(), false, isScoreOnly);
  203. if(CollectionUtils.isNotEmpty(responses)) {
  204. responses.stream().forEach(t -> respList.addAll(t.getMajorDetails()));
  205. }
  206. }
  207. return R.ok(respList);
  208. }
  209. public TableDataInfo postAIResult(VoluntaryDto.AIRequest req) {
  210. VoluntaryDto.AIRequestFilter filter = req.getFilter();
  211. Map cond = new HashMap();
  212. if (CollectionUtils.isNotEmpty(filter.getMajorTypes()) && StringUtils.isNotBlank(filter.getMajorTypes().get(0))) {
  213. cond.put("majorTypes", filter.getMajorTypes());
  214. } else if (StringUtils.isNotBlank(req.getMajorCategory())) {
  215. cond.put("majorCategory", req.getMajorCategory());
  216. }
  217. cond.put("universityName", filter.getKeyword());// 院校名称
  218. if (CollectionUtils.isNotEmpty(filter.getLevel())) {
  219. cond.put("universityLevel", filter.getLevel());// 办学层次
  220. }
  221. if (CollectionUtils.isNotEmpty(filter.getType())) {
  222. cond.put("universityType", filter.getType());// 院校类型
  223. }
  224. if (CollectionUtils.isNotEmpty(filter.getNatureTypeCN())) {
  225. cond.put("universityNatureType", filter.getNatureTypeCN()); // 办学类型
  226. }
  227. if (CollectionUtils.isNotEmpty(filter.getLocation())) {
  228. cond.put("universityLocation", filter.getLocation()); // 院校省份
  229. }
  230. if (null != filter.getHasClearing()) {
  231. cond.put("hasClearing", filter.getHasClearing() ? "补录" : "初录");
  232. }
  233. List<VoluntaryDto.AIResponse> responses = findMajorSuggest(getPlanYear(SecurityUtils.getLoginUser().getUser()), getSubmitYear(), cond, req.getForm(), true, false);
  234. if (CollectionUtils.isEmpty(responses)) {
  235. return new TableDataInfo(Lists.newArrayList(), 0);
  236. }
  237. if (null != filter.getEnumPickEmpty()) {
  238. responses = responses.stream().filter(t -> filter.getEnumPickEmpty().equals(t.getEnumPickEmpty())).collect(Collectors.toList());
  239. } else if (null != filter.getEnumPickType() && !VoluntaryDto.EnumPickType.All.equals(filter.getEnumPickType())) {
  240. responses = responses.stream().filter(t -> filter.getEnumPickType().equals(t.getEnumPickType())).collect(Collectors.toList());
  241. }
  242. Integer start = null != req.getPageNum() ? (req.getPageNum() - 1) * req.getPageSize() : 0;
  243. List<VoluntaryDto.AIResponse> finalList = responses.subList(start, Math.min(start + (null == req.getPageSize() ? 10 : req.getPageSize()), responses.size()));
  244. TableDataInfo tableDataInfo = new TableDataInfo(finalList, responses.size());
  245. tableDataInfo.setCode(200);
  246. return tableDataInfo;
  247. }
  248. private List<VoluntaryDto.AIRenderRule> findMatchRules(Map cond, boolean isAi, boolean isScore) {
  249. String examType = VistorContextHolder.getExamType().title(); // TODO MF
  250. String gender = "0".equals(SecurityUtils.getLoginUser().getUser().getSex()) ? "男生" : "女生";
  251. cond.put("examineeType", examType);
  252. List<AEnrollScore> enrollScoreList = aEnrollScoreMapper.selectListByRuleCond(cond);
  253. if (CollectionUtils.isEmpty(enrollScoreList) && cond.containsKey("majorGroup")) {
  254. cond.put("majorGroup", "");
  255. enrollScoreList = aEnrollScoreMapper.selectListByRuleCond(cond);
  256. }
  257. List<VoluntaryDto.AIRenderRule> ruleList = Lists.newArrayList();
  258. Set<String> existItemSet = Sets.newHashSet();
  259. String vt;
  260. VoluntaryDto.AIRenderRule scoreRateRule = null;
  261. for (AEnrollScore s : enrollScoreList) { // 跳过统计类和提示类的规则
  262. if (null == (vt = s.getValueType()) || vt.startsWith("Stat") || vt.equals("Notice")) {
  263. continue;
  264. } else if(isScore && !"学考".equals(s.getItemCategory()) && !"校考".equals(s.getItemCategory())) {
  265. continue;
  266. } else if (vt.equals("ScoreRate")) {
  267. if (!isAi) {
  268. vt = "Score";
  269. } else if (existItemSet.add("ScoreRate")) {
  270. scoreRateRule = new VoluntaryDto.AIRenderRule();
  271. scoreRateRule.setEnumRuleCategory(VoluntaryDto.EnumRuleCategory.Enroll);
  272. scoreRateRule.setFieldName("ScoreRate");
  273. scoreRateRule.setEnumInputType(VoluntaryDto.EnumInputType.Number);
  274. scoreRateRule.setMin(0);
  275. scoreRateRule.setMax(100);
  276. scoreRateRule.setLabel("技能测试得分率");
  277. scoreRateRule.setDescription("%");
  278. continue;
  279. } else {
  280. continue;
  281. }
  282. }
  283. if (!existItemSet.add(s.getItemField())) {
  284. continue;
  285. }
  286. VoluntaryDto.AIRenderRule r = new VoluntaryDto.AIRenderRule();
  287. r.setEnumRuleCategory(VoluntaryDto.EnumRuleCategory.Enroll);
  288. r.setFieldName(s.getItemField());
  289. setOptionValue(r, vt, s.getValueRule(), s.getValueOptional(), s.getCorrectType(), s.getCorrectValue(), s.getScoreTotal());
  290. r.setRegex(s.getRegex());
  291. r.setLabel(s.getItemName());
  292. r.setDescription(s.getDescription());
  293. r.setPlaceholder(s.getPlaceholder());
  294. r.setTips(s.getTips());
  295. r.setDefaultValue(s.getDefaultValue());
  296. r.setDotDisable(null != s.getDotDisable() && s.getDotDisable() > 0);
  297. r.setKeyboardMode(s.getKeyboardMode()); // number card car,默认number
  298. ruleList.add(r);
  299. }
  300. if (null != scoreRateRule) {
  301. ruleList.add(scoreRateRule);
  302. }
  303. if(isScore) {
  304. return ruleList;
  305. }
  306. List<AEnrollSpecial> enrollSpecialList = Lists.newArrayList();
  307. Map<String, AEnrollSpecial> mergeEnrollSpecialMap = Maps.newHashMap();
  308. List<AEnrollSpecial> oriErollSpecialList = aEnrollSpecialMapper.selectListByRuleCond(cond);
  309. for (AEnrollSpecial s : oriErollSpecialList) {
  310. if (VoluntaryDto.EnumRuleType.Readonly.name().equals(s.getItemType()) || StringUtils.isNotBlank(s.getGender()) && !s.getGender().equals(gender)) {
  311. continue;
  312. }
  313. if (null == s.getItemGroup() || !"Checkbox".equals(s.getValueType())) {
  314. enrollSpecialList.add(s);
  315. continue;
  316. }
  317. //
  318. String key = s.getItemGroup(); // s.getUniversityId() + "_" + s.getMajorName() + "_" + StringUtils.trimToEmpty(s.getMajorDirection()) + "_" + StringUtils.trimToEmpty(s.getGender()) + "_" + s.getItemCategory() + "_" +
  319. AEnrollSpecial exist = mergeEnrollSpecialMap.get(key);
  320. if (null == exist) {
  321. // 修正分组后的名称及字段名
  322. String[] groupNameField = StringUtils.split(s.getItemGroup(), "_");
  323. s.setValueOptional(s.getItemName());
  324. s.setItemName(groupNameField[0]);
  325. s.setItemField(groupNameField[groupNameField.length > 1 ? 1 : 0]);
  326. mergeEnrollSpecialMap.put(key, s);
  327. enrollSpecialList.add(s);
  328. continue;
  329. }
  330. if(StringUtils.isBlank(exist.getValueOptional()) || !exist.getValueOptional().contains(s.getItemName())) {
  331. exist.setValueOptional(exist.getValueOptional() + "," + s.getItemName());
  332. }
  333. }
  334. Map<String,String> mutexOptionMap = getMutexOptionMap();
  335. for (AEnrollSpecial s : enrollSpecialList) {
  336. if (null == (vt = s.getValueType()) || vt.startsWith("Stat") || vt.equals("Notice") || !existItemSet.add(s.getItemField())) {
  337. continue;
  338. }
  339. VoluntaryDto.AIRenderRule r = new VoluntaryDto.AIRenderRule();
  340. r.setEnumRuleCategory(VoluntaryDto.EnumRuleCategory.Special);
  341. r.setFieldName(s.getItemField());
  342. setOptionValue(r, s.getValueType(), s.getValueRule(), s.getValueOptional(), s.getCorrectType(), s.getCorrectValue(), null);
  343. if (VoluntaryDto.EnumInputType.Checkbox.equals(r.getEnumInputType())) {
  344. r.setMutexOption(mutexOptionMap.get(r.getFieldName()));
  345. }
  346. r.setRegex(s.getRegex());
  347. r.setLabel(s.getItemName());
  348. r.setDescription(s.getDescription());
  349. r.setPlaceholder(s.getPlaceholder());
  350. r.setTips(s.getTips());
  351. r.setDefaultValue(s.getDefaultValue());
  352. r.setDotDisable(null != s.getDotDisable() && s.getDotDisable() > 0);
  353. r.setKeyboardMode(s.getKeyboardMode()); // number card car,默认number
  354. ruleList.add(r);
  355. }
  356. return ruleList;
  357. }
  358. private Map<String, String> getMutexOptionMap() {
  359. String mutexOptionConf = sysConfigService.selectConfigByKey("voluntary.rule.mutexOption");
  360. Map<String, String> mutexOptionMap = Maps.newHashMap();
  361. if (StringUtils.isNotBlank(mutexOptionConf)) {
  362. try {
  363. JSONArray.parseArray(mutexOptionConf).forEach(l -> {
  364. JSONObject lo = (JSONObject) l;
  365. mutexOptionMap.put(lo.getString("n"), lo.getString("m"));
  366. });
  367. } catch (JSONException e) {
  368. }
  369. }
  370. return mutexOptionMap;
  371. }
  372. // TODO 同一专业号有多个专业方向
  373. private List<VoluntaryDto.AIResponse> findMajorSuggest(Integer planYear, Integer submitYear, Map cond, Map<String, String> paramMap, boolean isAi, boolean isScoreOnly) {
  374. String examType = VistorContextHolder.getExamType().title(); // TODO MF
  375. String gender = "0".equals(SecurityUtils.getLoginUser().getUser().getSex()) ? "男生" : "女生";
  376. cond.remove("year");
  377. cond.put("examineeType", examType);
  378. Map<Long, List<AMarjorPlan>> currUniversityMajorPlansMap = Maps.newHashMap();
  379. Map<Long, List<AMarjorPlan>> historyUniversityMajorPlansMap = Maps.newHashMap();
  380. List<Map<Long, List<AMarjorPlan>>> bothPlanList = Lists.newArrayList(currUniversityMajorPlansMap, historyUniversityMajorPlansMap);
  381. Set<String> existSet = Sets.newHashSet();
  382. for (AMarjorPlan mp : aMarjorPlanMapper.selectListByRuleCond(cond)) {
  383. String key = mp.getUniversityId() + mp.getMajorName() + StringUtils.trimToEmpty(mp.getMajorDirection()) + mp.getYear(); // TODO 考虑为什么会重的问题 examType ?
  384. if (!existSet.add(key)) {
  385. continue;
  386. }
  387. for(Map<Long, List<AMarjorPlan>> tmpMap : bothPlanList) {
  388. if (!mp.getYear().equals(planYear) && tmpMap == currUniversityMajorPlansMap) {
  389. continue;
  390. }
  391. List<AMarjorPlan> tmpMpList = tmpMap.get(mp.getUniversityId());
  392. if (null == tmpMpList) {
  393. tmpMpList = Lists.newArrayList(mp);
  394. tmpMap.put(mp.getUniversityId(), tmpMpList);
  395. } else {
  396. tmpMpList.add(mp);
  397. }
  398. }
  399. }
  400. Map<Long, List<BBusiWishUniversitiesProfession>> universityMajorsMap = Maps.newHashMap();
  401. // 有计划以计划为准的输出,无计划时则以所有专业输出为准
  402. Map<Long, BBusiWishUniversities> universitiesMap = null;
  403. if (MapUtils.isEmpty(currUniversityMajorPlansMap)) {
  404. Map<String, List<BBusiWishUniversitiesProfession>> tmpUniversityMajorsMap = bBusiWishUniversitiesProfessionMapper.selectListByRuleCond(cond).stream().collect(Collectors.groupingBy(BBusiWishUniversitiesProfession::getCollegeCode));
  405. if (MapUtils.isNotEmpty(tmpUniversityMajorsMap)) {
  406. Map uCond = Maps.newHashMap();
  407. uCond.put("codes", tmpUniversityMajorsMap.keySet());
  408. universitiesMap = Maps.newHashMap();
  409. for (BBusiWishUniversities u : bBusiWishUniversitiesMapper.selectBBusiWishUniversitiesListSimpleByMap(uCond)) {
  410. universitiesMap.put(u.getId(), u);
  411. universityMajorsMap.put(u.getId(), tmpUniversityMajorsMap.get(u.getCode()));
  412. }
  413. }
  414. } else {
  415. cond.put("universityIds", currUniversityMajorPlansMap.keySet());
  416. cond.put("examType", Constant.EXAM_TYPE_PG);
  417. Map<String, List<BBusiWishUniversitiesProfession>> tmpUniversityMajorsMap = bBusiWishUniversitiesProfessionMapper.selectListByRuleCond(cond).stream().collect(Collectors.groupingBy(BBusiWishUniversitiesProfession::getCollegeCode));
  418. cond.remove("universityIds");
  419. if (MapUtils.isNotEmpty(tmpUniversityMajorsMap)) {
  420. Map uCond = new HashMap();
  421. uCond.put("ids", currUniversityMajorPlansMap.keySet());
  422. universitiesMap = Maps.newHashMap();
  423. for (BBusiWishUniversities u : bBusiWishUniversitiesMapper.selectBBusiWishUniversitiesListSimpleByIds(uCond)) {
  424. universitiesMap.put(u.getId(), u);
  425. universityMajorsMap.put(u.getId(), tmpUniversityMajorsMap.get(u.getCode()));
  426. }
  427. }
  428. }
  429. // 无计划,也无院校专业
  430. if(MapUtils.isEmpty(universitiesMap)) {
  431. return Lists.newArrayList();
  432. }
  433. // 查询涉及的规则
  434. cond.put("year", planYear);
  435. cond.put("universityIds", universitiesMap.keySet());
  436. Map<Long, List<AEnrollScore>> universityScoreListMap = aEnrollScoreMapper.selectListByRuleCond(cond).stream().collect(Collectors.groupingBy(AEnrollScore::getUniversityId));
  437. Map<Long, List<AEnrollSpecial>> universitySpecialListMap = aEnrollSpecialMapper.selectListByRuleCond(cond).stream().collect(Collectors.groupingBy(AEnrollSpecial::getUniversityId));
  438. cond.remove("universityIds");
  439. cond.remove("year");
  440. Map<String, String> mutexOptionMap = getMutexOptionMap();
  441. List<VoluntaryDto.AIResponse> aiRespList = Lists.newArrayList();
  442. for (Long universityId : universitiesMap.keySet()) {
  443. List<AEnrollScore> scoreList = universityScoreListMap.get(universityId); // 分数条件
  444. List<AEnrollSpecial> specialList = universitySpecialListMap.get(universityId);// 专项条件
  445. List<AMarjorPlan> currPlanList = currUniversityMajorPlansMap.get(universityId);// 当年计划
  446. List<AMarjorPlan> historyPlanList = historyUniversityMajorPlansMap.get(universityId);// 历年计划
  447. BBusiWishUniversities u = universitiesMap.get(universityId);// 院校
  448. List<BBusiWishUniversitiesProfession> professionList = universityMajorsMap.get(u.getId()); // 所有专业
  449. // 院校变更标志
  450. AEnrollUniversity euCond = new AEnrollUniversity();
  451. euCond.setUniversityId(u.getId());
  452. euCond.setYear(planYear);
  453. List<AEnrollUniversity> enrollUniversityList = aEnrollUniversityMapper.selectAEnrollUniversityList(euCond);
  454. // 院校历史情况
  455. AMarjorSubmit submitCond = new AMarjorSubmit();
  456. submitCond.setExamineeType(examType);
  457. submitCond.setUniversityId(universityId);
  458. List<AMarjorSubmit> submitList = aMarjorSubmitMapper.selectAMarjorSubmitList(submitCond);
  459. VoluntaryDto.AIResponse aiResp = new VoluntaryDto.AIResponse();
  460. aiResp.setUniversity(u);
  461. VoluntaryDto.SingleResponse sr;
  462. List<VoluntaryDto.SingleResponse> singleResponseList = Lists.newArrayList();
  463. if (CollectionUtils.isNotEmpty(currPlanList)) {
  464. aiResp.setEnrollCode(currPlanList.get(0).getEnrollCode());
  465. Map<String, BBusiWishUniversitiesProfession> professionMap = null == professionList ? Maps.newHashMap() : professionList.stream().collect(Collectors.toMap(BBusiWishUniversitiesProfession::getName, Function.identity()));
  466. for (AMarjorPlan mp : currPlanList) {
  467. if (null != (sr = buildSingleResponse(submitYear, planYear, gender, mp, professionMap.get(mp.getMajorName()), enrollUniversityList, paramMap, u,
  468. historyPlanList, submitList, scoreList, specialList, mutexOptionMap, isAi, isScoreOnly))) {
  469. singleResponseList.add(sr);
  470. }
  471. }
  472. } else {
  473. for (BBusiWishUniversitiesProfession prof : professionList) {
  474. if (null != (sr = buildSingleResponse(submitYear, planYear, gender, null, prof, enrollUniversityList, paramMap, u,
  475. historyPlanList, submitList, scoreList, specialList, mutexOptionMap, isAi, isScoreOnly))) {
  476. singleResponseList.add(sr);
  477. }
  478. }
  479. }
  480. aiResp.setMajorDetails(singleResponseList);
  481. sortAndExtractEnroll(singleResponseList, aiResp);
  482. aiRespList.add(aiResp);
  483. }
  484. Collections.sort(aiRespList, new Comparator<VoluntaryDto.AIResponse>() {
  485. @Override
  486. public int compare(VoluntaryDto.AIResponse o1, VoluntaryDto.AIResponse o2) {
  487. Integer d1 = o1.getEnrollRate();
  488. Integer d2 = o2.getEnrollRate();
  489. d1 = null == d1 ? 999 : (d1 == 0 ? 998 : d1);
  490. d2 = null == d2 ? 999 : (d2 == 0 ? 998 : d2);
  491. return d1.compareTo(d2);
  492. }
  493. });
  494. return aiRespList;
  495. }
  496. private VoluntaryDto.SingleResponse buildSingleResponse(Integer submitYear, Integer planYear, String gender, AMarjorPlan currPlan, BBusiWishUniversitiesProfession prof,
  497. List<AEnrollUniversity> enrollUniversityList, Map<String, String> paramMap, BBusiWishUniversities u,
  498. List<AMarjorPlan> historyPlanList, List<AMarjorSubmit> submitList,
  499. List<AEnrollScore> scoreList, List<AEnrollSpecial> specialList, Map<String,String> mutexOptionMap, boolean isAi, boolean isScoreOnly) {
  500. if (null != submitList) {
  501. Collections.sort(submitList, new Comparator<AMarjorSubmit>() {
  502. @Override
  503. public int compare(AMarjorSubmit o1, AMarjorSubmit o2) {
  504. int iRet;
  505. if (0 != (iRet = o1.getYear().compareTo(o2.getYear()))) {
  506. return -iRet;
  507. }
  508. if (0 != (iRet = o1.getMajorName().compareTo(o2.getMajorName()))) {
  509. return -iRet;
  510. }
  511. if (null == o1.getMajorDirection()) {
  512. if (null != o2.getMajorDirection()) {
  513. return 1;
  514. }
  515. return 0;
  516. } else if (null == o2.getMajorDirection()) {
  517. return -1;
  518. }
  519. return 0;
  520. }
  521. });
  522. } else {
  523. submitList = Lists.newArrayList();
  524. }
  525. if (null != historyPlanList) {
  526. Collections.sort(historyPlanList, new Comparator<AMarjorPlan>() {
  527. @Override
  528. public int compare(AMarjorPlan o1, AMarjorPlan o2) {
  529. int iRet;
  530. if (0 != (iRet = o1.getYear().compareTo(o2.getYear()))) {
  531. return -iRet;
  532. }
  533. if (0 != (iRet = o1.getMajorName().compareTo(o2.getMajorName()))) {
  534. return -iRet;
  535. }
  536. if (null == o1.getMajorDirection()) {
  537. if (null != o2.getMajorDirection()) {
  538. return 1;
  539. }
  540. return 0;
  541. } else if (null == o2.getMajorDirection()) {
  542. return -1;
  543. }
  544. return o1.getMajorDirection().compareTo(o2.getMajorDirection());
  545. }
  546. });
  547. } else {
  548. historyPlanList = Lists.newArrayList();
  549. }
  550. // 录取线
  551. List<VoluntaryDto.MajorClearingHistory> clearings = Lists.newArrayList(); // 补录情况
  552. List<VoluntaryDto.MajorEnrollHistory> histories = Lists.newArrayList(); // 初录情况
  553. List<VoluntaryDto.MajorEnrollRule> ruleMatchList = Lists.newArrayList();
  554. List<VoluntaryDto.MajorEnrollRule> improveList = Lists.newArrayList();
  555. Double tmpValue; // 总分,得分
  556. AMarjorSubmit lastSubmit = null;
  557. Boolean typeChange = false;
  558. VoluntaryDto.FormulaScoreStat formulaScoreStat = new VoluntaryDto.FormulaScoreStat();
  559. String needGroup = StringUtils.trimToEmpty(null != currPlan && null != currPlan.getMajorGroup() ? currPlan.getMajorGroup() : "");
  560. String needMajor = StringUtils.trimToEmpty(null != currPlan ? currPlan.getMajorName() : (null != prof ? prof.getName() : ""));
  561. String needDirect = StringUtils.trimToEmpty(null != currPlan ? currPlan.getMajorDirection() : "");
  562. String needMajorDirect = needMajor + needDirect;
  563. // 判断是否政策变化情况
  564. List<AEnrollUniversity> validEuList = enrollUniversityList.stream()
  565. .filter(t -> needGroup.equals(StringUtils.trimToEmpty(t.getMajorGroups())) && t.getMajorNames().contains(needMajor))
  566. .collect(Collectors.toList());
  567. typeChange = CollectionUtils.isNotEmpty(validEuList) && new Integer(1).equals(validEuList.get(0).getTypeChange());
  568. Set<String> existSet = Sets.newHashSet();
  569. existSet.clear();
  570. List<AMarjorSubmit> validSubmitList = Lists.newArrayList();
  571. if (null != submitList) {
  572. for (AMarjorSubmit s : submitList) { // 历年录取通过专业分来判断差别
  573. String majorNameDirect = s.getMajorName() + StringUtils.trimToEmpty(s.getMajorDirection());
  574. if (needMajorDirect.equals(majorNameDirect) && existSet.add(needMajorDirect + s.getYear() + s.getEnrollType())) {
  575. validSubmitList.add(s);
  576. if (s.getYear().equals(submitYear) && s.getEnrollType().equals("初录") ) {
  577. lastSubmit = s; // TODO 初录,补录与分数线的关系 要处理
  578. }
  579. }
  580. }
  581. }
  582. // 分项规则检查
  583. existSet.clear();
  584. Double currTotal = null;
  585. if (null != scoreList) {
  586. Double inputScoreRate = NumberUtils.toInt(paramMap.get("ScoreRate"), 0) / 100.0;
  587. List<AEnrollScore> fEnrollScoreList = Lists.newArrayList();
  588. String inclMajorDirection = needMajor + "(" + needDirect + ")";
  589. String exclMajorDirection = needMajor + "(";
  590. Map<Boolean, List<AEnrollScore>> majorEnrollScoresMap = scoreList.stream()
  591. .filter(t -> needGroup.equals(StringUtils.trimToEmpty(t.getMajorGroups())))
  592. .collect(Collectors.groupingBy(t -> StringUtils.isNotBlank(t.getMajorNames())));
  593. List<AEnrollScore> tmpEnrollScoreList = majorEnrollScoresMap.get(Boolean.TRUE);
  594. AEnrollScore skillEnrollScore = null;
  595. if (null != tmpEnrollScoreList) {
  596. for (AEnrollScore r : tmpEnrollScoreList) {
  597. if (StringUtils.isNotBlank(r.getMajorNames())) {
  598. if (!r.getMajorNames().contains(needMajor)) {
  599. continue;
  600. }
  601. if (StringUtils.isNotBlank(r.getMajorDirections())) { // 有单独的方向时,分开判断
  602. if (StringUtils.isBlank(needDirect) || !r.getMajorDirections().contains(needDirect)) {
  603. continue;
  604. }
  605. } else if (StringUtils.isNotBlank(needDirect)) { // 有direct要求时,这里需要有 "<专业>(<方向>)
  606. if (!r.getMajorNames().contains(inclMajorDirection)) {
  607. continue;
  608. }
  609. } else if (r.getMajorNames().contains(exclMajorDirection)) { // 当无direct要求时,这时不能有 "<专业>("
  610. continue;
  611. }
  612. }
  613. Boolean isSkillScore = isScoreOnly && r.getItemType().equals("ScoreSkill");
  614. if(isSkillScore) {
  615. skillEnrollScore = r;
  616. }
  617. appendScoreRule(formulaScoreStat, existSet, r, fEnrollScoreList, isAi, paramMap, inputScoreRate, isSkillScore);
  618. }
  619. }
  620. if (fEnrollScoreList.size() == 0 && null != (tmpEnrollScoreList = majorEnrollScoresMap.get(Boolean.FALSE))) {
  621. for (AEnrollScore r : tmpEnrollScoreList) {
  622. Boolean isSkillScore = isScoreOnly && r.getItemType().equals("ScoreSkill");
  623. if(isSkillScore) {
  624. skillEnrollScore = r;
  625. }
  626. appendScoreRule(formulaScoreStat, existSet, r, fEnrollScoreList, isAi, paramMap, inputScoreRate, isSkillScore);
  627. }
  628. }
  629. boolean isSameYear = null == lastSubmit || planYear.equals(lastSubmit.getYear());
  630. currTotal = formulaScoreStat.getTypeValue("StatRateScore", "", false);
  631. for (AEnrollScore r : fEnrollScoreList) {
  632. VoluntaryDto.MajorEnrollRule mr = buildEnrollRule(r);
  633. mr.setContent(StringUtils.isNotBlank(r.getEqualFormula()) ? r.getEqualFormula() : r.getEnrollFormula());
  634. if(isScoreOnly) {
  635. String vt;
  636. if (null != (vt = r.getValueType()) && vt.startsWith("Score")) {
  637. improveList.add(mr);
  638. mr.setCategory(VoluntaryDto.EnumRuleCategory.Enroll);
  639. mr.setType(VoluntaryDto.EnumRuleType.ScoreTotal);
  640. // mr.setValue(null != currTotal ? String.valueOf(currTotal.intValue()) : "");
  641. if (null == lastSubmit || null == lastSubmit.getScore() || null == lastSubmit.getScoreTotal() && !isSameYear) {
  642. mr.setFailedMessage("缺历史录取数据");
  643. continue;
  644. }
  645. mr.setYear(lastSubmit.getYear());
  646. if (typeChange) {
  647. mr.setFailedMessage("规则变更,无法计算");
  648. continue;
  649. } else if (!formulaScoreStat.isScoreValid() && (!isAi || inputScoreRate <= 0.0)) {
  650. mr.setFailedMessage("用户没有填写完整");
  651. continue;
  652. }
  653. Integer validScoreTotal = isSameYear ? formulaScoreStat.getAllTotal() : lastSubmit.getScoreTotal();
  654. Double currScoreRate = isSameYear ? 1.0 : formulaScoreStat.getAllTotal() * 1.0 / lastSubmit.getScoreTotal(); // 去年的分转成今年的分
  655. EnrollRateCalculator.RateLevel rl;
  656. if (null != lastSubmit.getScore() && currTotal != null && null != (rl = enrollRateCalculator.satisfy(validScoreTotal, lastSubmit.getScore(), currTotal / currScoreRate))) { // 按去年标准算概率
  657. Double skillRate = Double.parseDouble(skillEnrollScore.getValueRule());
  658. mr.setValue(String.valueOf(Math.round((lastSubmit.getScore() * currScoreRate - currTotal) * 10 / skillRate) / 10.0));
  659. mr.setValid(true);
  660. } else {
  661. mr.setFailedMessage("没有对应计算条件");
  662. continue;
  663. }
  664. } else {
  665. ruleMatchList.add(mr);
  666. mr.setValid(true);
  667. }
  668. continue;
  669. }
  670. ruleMatchList.add(mr);
  671. String vt;
  672. if (null == (vt = r.getValueType())) { // 无值时相当于直接通过
  673. mr.setValid(true);
  674. } else if (null != (vt = r.getValueType()) && vt.startsWith("Score")) {
  675. mr.setValue(null != currTotal ? String.valueOf(currTotal.intValue()) : "");
  676. if (null == lastSubmit || null == lastSubmit.getScore() || null == lastSubmit.getScoreTotal() && !isSameYear) {
  677. mr.setFailedMessage("缺历史录取数据");
  678. continue;
  679. } else if (typeChange) {
  680. mr.setFailedMessage("规则变更,无法计算");
  681. continue;
  682. } else if (!formulaScoreStat.isValid() && (!isAi || inputScoreRate <= 0.0)) {
  683. mr.setFailedMessage("用户没有填写完整");
  684. continue;
  685. }
  686. mr.setValid(true);
  687. Integer validScoreTotal = isSameYear ? formulaScoreStat.getAllTotal() : lastSubmit.getScoreTotal();
  688. Double currScoreRate = isSameYear ? 1.0 : formulaScoreStat.getAllTotal() * 1.0 / lastSubmit.getScoreTotal(); // 去年的分转成今年的分
  689. Double currScore = null;
  690. if (null != lastSubmit.getCulturalScore()) {
  691. if (null == (currScore = formulaScoreStat.getTypeValue("ScoreSingle", "", false))) {
  692. currScore = formulaScoreStat.getTypeValue("ScoreBase", "", false);
  693. }
  694. if (null != currScore && currScore < lastSubmit.getCulturalScore() * currScoreRate) {
  695. // mr.setValid(false);
  696. mr.setMissingValue(String.valueOf(Math.round(lastSubmit.getCulturalScore() * currScoreRate - currScore)));
  697. mr.setFailedMessage("校考分低于分数线");
  698. }
  699. }
  700. if (null != lastSubmit.getProfScore() && null != (currScore = formulaScoreStat.getTypeValue("ScoreSkill", "", false)) && currScore < lastSubmit.getProfScore() * currScoreRate) {
  701. // mr.setValid(false);
  702. mr.setMissingValue(String.valueOf(Math.round(lastSubmit.getProfScore() * currScoreRate - currScore)));
  703. mr.setFailedMessage("技能测试分低于分数线");
  704. }
  705. // 检查总分,学考(文化),专业(技能)
  706. EnrollRateCalculator.RateLevel rl;
  707. if (null != lastSubmit.getScore() && currTotal != null && null != (rl = enrollRateCalculator.calSchoolEnrollRate(validScoreTotal, lastSubmit.getScore(), currTotal / currScoreRate))) { // 按去年标准算概率
  708. mr.setRl(rl);
  709. mr.setEnrollRate(rl.rate);
  710. mr.setEnrollRateText(rl.typeLabel);
  711. mr.setEnumPickType(rl.type);
  712. if (mr.getValid() && currTotal < lastSubmit.getScore() * currScoreRate) {
  713. // mr.setValid(false);
  714. mr.setMissingValue(String.valueOf(Math.round(lastSubmit.getScore() * currScoreRate - currTotal))); // 按今年的算差值
  715. mr.setFailedMessage("综合分低于分数线");
  716. }
  717. }
  718. } else { // 专项符合型
  719. mr.setValid(processPassCheck(paramMap, formulaScoreStat, r.getValueRule(), mr, r.getValueType(), r.getItemField(), r.getValuePassRule()));
  720. }
  721. }
  722. }
  723. if (null != specialList) {
  724. existSet.clear();
  725. List<AEnrollSpecial> validSpecialList = Lists.newArrayList();
  726. Map<String, Pair<String, Set<String>>> groupMutexOptionsMap = Maps.newHashMap();
  727. for (AEnrollSpecial r : specialList) {
  728. if (StringUtils.isNotBlank(r.getGender()) && !r.getGender().equals(gender)
  729. || StringUtils.isNotBlank(r.getMajorName()) && !Sets.newHashSet(r.getMajorName().split(",")).contains(needMajor)
  730. || StringUtils.isNotBlank(r.getMajorDirection()) && !r.getMajorDirection().equals(needDirect)) {
  731. continue;
  732. }
  733. if(r.getValueType().startsWith("StatBMI")) { // TODO 身高体重的名称需要是固定的
  734. String height = paramMap.get("身高");
  735. String weight = paramMap.get("体重");
  736. Integer iHeight;
  737. if (StringUtils.isNotBlank(height) && StringUtils.isNotBlank(weight) && (iHeight = NumberUtils.toInt(height, 0)) > 0) {
  738. paramMap.put(r.getItemField(), String.valueOf(NumberUtils.toInt(height, 0) * 100 / iHeight));
  739. }
  740. } else if (null != r.getItemGroup() && "Checkbox".equals(r.getValueType())) {
  741. Pair<String, Set<String>> p = getGroupOptions(groupMutexOptionsMap, mutexOptionMap, paramMap, r.getItemGroup());
  742. if (p.getRight().size() == 0) { // 无值时
  743. paramMap.put(r.getItemField(), null);
  744. } else if (StringUtils.isNotBlank(p.getLeft()) && p.getRight().contains(p.getLeft())) { // 选中互斥时全是否
  745. paramMap.put(r.getItemField(), !p.getLeft().contains("无") ? "[\"是\"]" : "[\"否\"]");
  746. } else {
  747. paramMap.put(r.getItemField(), p.getRight().contains(r.getItemName()) ? "[\"是\"]" : "[\"否\"]");
  748. }
  749. }
  750. validSpecialList.add(r);
  751. }
  752. for (AEnrollSpecial r : validSpecialList) {
  753. VoluntaryDto.MajorEnrollRule mr = new VoluntaryDto.MajorEnrollRule();
  754. mr.setCategory(VoluntaryDto.EnumRuleCategory.Special);
  755. mr.setContent(r.getEnrollFormula());
  756. mr.setDescription(r.getComment());
  757. ruleMatchList.add(mr);
  758. if(isScoreOnly) {
  759. mr.setType(VoluntaryDto.EnumRuleType.Readonly);
  760. mr.setValid(true);
  761. continue;
  762. }
  763. mr.setType(itemType2RuleType(r.getItemType(), r.getValueType(), false));
  764. if (VoluntaryDto.EnumRuleType.Readonly.equals(mr.getType())) {
  765. mr.setValid(true);
  766. } else {
  767. mr.setValid(processPassCheck(paramMap, formulaScoreStat, r.getValueRule(), mr, r.getValueType(), r.getItemField(), r.getValuePassRule()));
  768. }
  769. }
  770. }
  771. existSet.clear();
  772. Map<String, AMarjorPlan> historyPlanMap = historyPlanList.stream().collect(Collectors.toMap(t -> t.getYear() + t.getMajorName() + StringUtils.trimToEmpty(t.getMajorDirection()), Function.identity()));
  773. for (AMarjorSubmit s : validSubmitList) {
  774. if ("初录".equals(s.getEnrollType())) {
  775. VoluntaryDto.MajorEnrollHistory h = new VoluntaryDto.MajorEnrollHistory();
  776. h.setYear(s.getYear());
  777. h.setScore(null != s.getScore() ? String.valueOf(s.getScore()) : ""); // TODO 240301 直接输出录取分
  778. /*if (null != currTotal && null != s.getScore()) {
  779. Double diff = currTotal - s.getScore();
  780. h.setScore(diff > 0 ? "+" + diff.intValue() : "" + diff.intValue()); // TODO 需要一个分来比较,综合分?
  781. } else {
  782. h.setScore("");
  783. }*/
  784. AMarjorPlan p = historyPlanMap.get(s.getYear() + s.getMajorName() + StringUtils.trimToEmpty(s.getMajorDirection()));
  785. if(null != p) {
  786. h.setPlan(p.getPlanTotal()); // TODO 估计输出录取人数 23.12.26 分开输入录取和计划 24.12.27
  787. } else {
  788. // System.out.println(s.getId());
  789. }
  790. h.setEnroll(s.getEnrollTotal());
  791. histories.add(h);
  792. } else {
  793. /*VoluntaryDto.MajorClearingHistory c = new VoluntaryDto.MajorClearingHistory();
  794. c.setYear(s.getYear());
  795. if (null != currTotal && null != s.getScore()) {
  796. Double diff = currTotal - s.getScore();
  797. c.setScore(diff > 0 ? "+" + diff.intValue() : "" + diff.intValue()); // TODO 需要一个分来比较,综合分?
  798. } else {
  799. c.setScore("");
  800. }
  801. c.setRealNum(s.getEnrollTotal());
  802. clearings.add(c);*/ // TODO 240301 关闭补录
  803. }
  804. }
  805. VoluntaryDto.SingleResponse sr = new VoluntaryDto.SingleResponse();
  806. sr.setUniversityCode(u.getCode());
  807. sr.setMajorCode(null != prof ? prof.getCode() : "");
  808. sr.setMajorName(needMajor);
  809. sr.setMajorDirection(needDirect);
  810. // 查找最高的专业 EnrollRule 为本专业的,理论上只有一个合并rule有此值
  811. EnrollRateCalculator.RateLevel lastRl = null;
  812. boolean specialValid = true, specialPass = true;
  813. for (VoluntaryDto.MajorEnrollRule er : ruleMatchList) {
  814. if (null != er.getRl() && (null == lastRl || er.getRl().getRate() < lastRl.getRate())) {
  815. lastRl = er.getRl();
  816. }
  817. if ((specialPass || specialValid) && VoluntaryDto.EnumRuleType.Special.equals(er.getType())) {
  818. if (null == er.getValid()) {
  819. specialValid = false;
  820. } else if (!er.getValid()) {
  821. specialPass = false;
  822. }
  823. }
  824. }
  825. if (!specialPass) {
  826. sr.setEnrollRate(0);
  827. sr.setEnrollRateText("零概率");
  828. sr.setEnumPickEmpty(VoluntaryDto.EnumPickEmpty.EnrollPass);
  829. } else if (null != lastRl && specialValid) {
  830. sr.setEnumPickType(lastRl.getType());
  831. sr.setEnrollRate(lastRl.getRate());
  832. sr.setEnrollRateText(lastRl.getTypeLabel());
  833. } else {
  834. sr.setEnrollRateText("无概率");
  835. sr.setEnumPickEmpty(VoluntaryDto.EnumPickEmpty.New);
  836. }
  837. if (null != currPlan) {
  838. sr.setMajorGroup(currPlan.getMajorGroup()); // 没有MajorEnrollId, 暂时用这个
  839. sr.setMajorEnrollCode(StringUtils.isBlank(currPlan.getMajorEnrollCode()) ? String.valueOf(currPlan.getId()) : currPlan.getMajorEnrollCode());
  840. sr.setTips(null != currPlan ? currPlan.getComment() : "");
  841. }
  842. sr.setHistories(histories);
  843. sr.setClearings(clearings);
  844. sr.setRules(ruleMatchList);
  845. sr.setImproves(improveList);
  846. sr.setScore(currTotal);
  847. if (!isScoreOnly && null != lastSubmit && null != lastSubmit.getScore() && null != currTotal && currTotal < lastSubmit.getScore()) {
  848. Double diffValue = lastSubmit.getScore() - currTotal;
  849. sr.setImproves(formulaScoreStat.getImproveScore(diffValue));
  850. }
  851. return sr;
  852. }
  853. private void appendScoreRule(VoluntaryDto.FormulaScoreStat formulaScoreStat, Set<String> existSet, AEnrollScore r, List<AEnrollScore> fEnrollScoreList,
  854. Boolean isAi, Map<String, String> paramMap, Double inputScoreRate, Boolean isSkillScore) {
  855. String vt, iv;
  856. Double currScore = null;
  857. Double scoreRate = null;
  858. Double tmpValue; // 总分,得分
  859. if (null != (vt = r.getValueType()) && vt.startsWith("Score")) { //需要合并Score型(ScoreSingle, ScoreBase, ScoreSkill)的各类成绩, 其他为符合条件
  860. if (existSet.add(r.getEnrollFormula())) { // 合并规则只留第一个
  861. if (!existSet.add("_ScoreFormula_")) {
  862. existSet.remove(r.getEnrollFormula());
  863. return;
  864. }
  865. fEnrollScoreList.add(r);
  866. }
  867. if (null != r.getValueRule() && (scoreRate = Double.parseDouble(r.getValueRule())) <= 0.0) {
  868. scoreRate = 1.0;
  869. }
  870. formulaScoreStat.addTypeTotal(r.getScoreTotal());
  871. if (isAi && vt.equals("ScoreRate")) { // 根据得分率及总分计算分值
  872. currScore = isSkillScore ? 0.0 : r.getScoreTotal() * inputScoreRate;
  873. formulaScoreStat.addGroup(r.getItemGroup(), currScore, r.getScoreTotal().doubleValue(), scoreRate);
  874. formulaScoreStat.addType(r.getItemType(), r.getItemField(), currScore, scoreRate);
  875. } else {
  876. currScore = (!isSkillScore && StringUtils.isNotBlank((iv = paramMap.get(r.getItemField())))) ? NumberUtils.toDouble(iv, 0.0) : 0.0;
  877. formulaScoreStat.addGroup(r.getItemGroup(), currScore, r.getScoreTotal().doubleValue(), scoreRate);
  878. formulaScoreStat.addType(r.getItemType(), r.getItemField(), currScore, scoreRate);
  879. }
  880. } else {
  881. fEnrollScoreList.add(r);
  882. }
  883. }
  884. private VoluntaryDto.MajorEnrollRule buildEnrollRule(AEnrollScore r) {
  885. VoluntaryDto.MajorEnrollRule mr = new VoluntaryDto.MajorEnrollRule();
  886. mr.setCategory(VoluntaryDto.EnumRuleCategory.Enroll);
  887. mr.setType(itemType2RuleType(r.getItemType(), r.getValueType(), true)); // 学考 ScoreSingle 强转为 ScoreTotal, ScoreBase 校考, ScoreSkill 技能, Special 专项
  888. mr.setContent(r.getEnrollFormula());
  889. mr.setImproveType(r.getItemCategory());
  890. mr.setDescription(r.getComment());
  891. return mr;
  892. }
  893. private Pair<String, Set<String>> getGroupOptions(Map<String, Pair<String, Set<String>>> groupOptionsMap, Map<String, String> mutexOptionMap, Map<String, String> paramMap, String itemGroup) {
  894. String[] groupNameField = StringUtils.split(itemGroup, "_");
  895. String groupFieldName = groupNameField[groupNameField.length > 1 ? 1 : 0];
  896. Pair<String, Set<String>> pair = groupOptionsMap.get(groupFieldName);
  897. if(null == pair) {
  898. String iv = paramMap.get(groupFieldName);
  899. Set<String> options = StringUtils.isNotBlank(iv) ? JSONArray.parseArray(iv).stream().map(t -> (String) t).collect(Collectors.toSet()) : Sets.newHashSet();
  900. pair = new MutablePair<>(mutexOptionMap.get(groupFieldName), options);
  901. groupOptionsMap.put(groupFieldName, pair);
  902. }
  903. return pair;
  904. }
  905. private Boolean processPassCheck(Map<String, String> paramMap, VoluntaryDto.FormulaScoreStat stat, String valueRule,
  906. VoluntaryDto.MajorEnrollRule mr, String valueType, String itemField, String passRule) {
  907. Boolean matched = null;
  908. Double tmpValue;
  909. boolean isStat = null != valueType && valueType.startsWith("Stat");
  910. if (isStat || NumberTypeSet.contains(valueType)) {
  911. Double v = null;
  912. String iv;
  913. if (isStat) { // TODO 统计分
  914. v = stat.getTypeValue(valueType, itemField, "0".equals(valueRule));
  915. } else if(StringUtils.isNotBlank(passRule) && StringUtils.isNotBlank((iv = paramMap.get(itemField)))
  916. && (tmpValue = NumberUtils.toDouble(iv, 0.0)) > 0.01) {
  917. v = tmpValue;
  918. }
  919. if (v != null) {
  920. String[] range = passRule.split("-");
  921. if (StringUtils.isNotBlank(range[0]) && (tmpValue = NumberUtils.toDouble(range[0], 0.0)) > 0.01 && v < tmpValue) {
  922. matched = false;
  923. mr.setFailedMessage("小于最大值");
  924. } else if (range.length > 1 && StringUtils.isNotBlank(range[1]) && (tmpValue = NumberUtils.toDouble(range[1], 0.0)) > 0.01 && v > tmpValue) {
  925. matched = false;
  926. mr.setFailedMessage("超过最大值");
  927. } else {
  928. matched = true;
  929. }
  930. } else {
  931. mr.setFailedMessage("未输入参数");
  932. }
  933. } else if ("Radio".equals(valueType)) {
  934. String iv = paramMap.get(itemField);
  935. if (StringUtils.isNotBlank(iv)) {
  936. if (!(matched = StringUtils.isNotBlank(passRule) && passRule.contains(iv))) {
  937. mr.setFailedMessage("条件不满足");
  938. }
  939. } else {
  940. mr.setFailedMessage("未输入参数");
  941. }
  942. } else if ("Checkbox".equals(valueType) || "Picker".equals(valueType)) {
  943. String iv = paramMap.get(itemField);
  944. if(StringUtils.isBlank(passRule)) {
  945. if (!(matched = StringUtils.isBlank(iv))) {
  946. mr.setFailedMessage("选择条件不满足1");
  947. }
  948. } else if (StringUtils.isNotBlank(iv)) {
  949. List<String> valueList = Arrays.asList(passRule.split(","));
  950. List<String> inputList = JSONArray.parseArray(iv).stream().map(t -> (String) t).collect(Collectors.toList());
  951. if (!(matched = CollectionUtils.intersection(valueList, inputList).size() == valueList.size())) {
  952. mr.setFailedMessage("选择条件不满足2");
  953. }
  954. }
  955. }
  956. return matched;
  957. }
  958. private void sortAndExtractEnroll(List<VoluntaryDto.SingleResponse> singleResponseList, VoluntaryDto.AIResponse aiResp) {
  959. if (CollectionUtils.isEmpty(singleResponseList)) {
  960. aiResp.setEnrollRate(null);
  961. aiResp.setEnrollRateText("无概率");
  962. aiResp.setEnumPickEmpty(VoluntaryDto.EnumPickEmpty.EnrollPass);
  963. }
  964. Collections.sort(singleResponseList, new Comparator<VoluntaryDto.SingleResponse>() {
  965. @Override
  966. public int compare(VoluntaryDto.SingleResponse o1, VoluntaryDto.SingleResponse o2) {
  967. Integer d1 = o1.getEnrollRate();
  968. Integer d2 = o2.getEnrollRate();
  969. if (null == d1) {
  970. if (null != d2) {
  971. return 1;
  972. }
  973. return 0;
  974. } else if (null == d2) {
  975. return -1;
  976. }
  977. return -d1.compareTo(d2);
  978. }
  979. });
  980. for (VoluntaryDto.SingleResponse sr : singleResponseList) {
  981. aiResp.setEnrollRate(sr.getEnrollRate());
  982. aiResp.setEnrollRateText(sr.getEnrollRateText());
  983. aiResp.setEnumPickType(sr.getEnumPickType());
  984. aiResp.setEnumPickEmpty(sr.getEnumPickEmpty());
  985. break;
  986. }
  987. }
  988. public R<VoluntaryDto.VoluntaryConfig> getVoluntaryConfig() { // 如果有填报配置相关,放在这里
  989. VoluntaryDto.VoluntaryConfig resp = new VoluntaryDto.VoluntaryConfig();
  990. return R.ok(resp);
  991. }
  992. public List<JSONObject> getVoluntaryList(@ApiParam @RequestParam VoluntaryDto.EnumVoluntaryType type) { // 我的志愿表 // 后台填充快照缺省
  993. AWishRecord cond = new AWishRecord();
  994. cond.setUserId(SecurityUtils.getLoginUser().getUserId());
  995. if (null != type) {
  996. cond.setType(type.name());
  997. }
  998. cond.setStatus(1);
  999. List<AWishRecord> aWishRecordList = aWishRecordMapper.selectAWishRecordList(cond);
  1000. List<JSONObject> dtoList = Lists.newArrayList();
  1001. aWishRecordList.stream().forEach(t -> {
  1002. dtoList.add(toModel(t));
  1003. });
  1004. return PageUtil.getDtoListWithPageable(aWishRecordList, dtoList);
  1005. }
  1006. public R<Long> submitVoluntary(JSONObject model) { // 填报 // 前端+后台按需要剔除一些不需快照的信息(目前主要是院校信息)
  1007. SysUser user = SecurityUtils.getLoginUser().getUser();
  1008. AWishRecord wishRecord = new AWishRecord();
  1009. VoluntaryDto.User userSnapshot = new VoluntaryDto.User();
  1010. userSnapshot.setName(user.getNickName());
  1011. userSnapshot.setSex(user.getSex());
  1012. userSnapshot.setExamType(user.getExamType().title()); // TODO MF
  1013. userSnapshot.setProvinceName(user.getLocation());
  1014. Long modelId = null;
  1015. String modelName = null;
  1016. Integer year = null;
  1017. VoluntaryDto.EnumVoluntaryType type = null;
  1018. try {
  1019. modelId = model.getLong("id");
  1020. modelName = model.getString("name");
  1021. year = model.getInteger("year");
  1022. type = VoluntaryDto.EnumVoluntaryType.valueOf(model.getString("voluntaryType"));
  1023. wishRecord.setBatchName(model.getString("batchName"));
  1024. wishRecord.setRequest(model.getString("request"));
  1025. wishRecord.setDetails(model.getString("details"));
  1026. wishRecord.setUserSnapshot(mapper.writeValueAsString(userSnapshot));
  1027. } catch (JsonProcessingException e) {
  1028. return R.fail("格式错误: " + modelId);
  1029. }
  1030. wishRecord.setYear(null == year ? getPlanYear(user) : year);
  1031. wishRecord.setType(type.name());
  1032. if (null != modelId) {
  1033. wishRecord.setUpdateTime(new Date());
  1034. wishRecord.setId(modelId);
  1035. wishRecord.setName(modelName);
  1036. wishRecord.setUpdateTime(new Date());
  1037. aWishRecordMapper.updateAWishRecord(wishRecord);
  1038. } else {
  1039. wishRecord.setCreateTime(new Date());
  1040. wishRecord.setSeq(getWishSeq(wishRecord.getYear(), wishRecord.getType()));
  1041. wishRecord.setName(StringUtils.isNotBlank(modelName) ? modelName : ("AI".equals(wishRecord.getType()) ? "AI志愿" : "模拟志愿") + wishRecord.getSeq());
  1042. wishRecord.setUserId(user.getUserId());
  1043. wishRecord.setStatus(1);
  1044. aWishRecordMapper.insertAWishRecord(wishRecord);
  1045. }
  1046. return R.ok(wishRecord.getId());
  1047. }
  1048. private Integer getWishSeq(Integer year, String type) {
  1049. AWishRecord cond = new AWishRecord();
  1050. cond.setUserId(SecurityUtils.getLoginUser().getUserId());
  1051. cond.setYear(year);
  1052. cond.setType(type);
  1053. List<AWishRecord> aWishRecordList = aWishRecordMapper.selectAWishRecordList(cond);
  1054. Integer newSeq = CollectionUtils.isNotEmpty(aWishRecordList) ? aWishRecordList.get(0).getSeq() + 1 : 1;
  1055. return newSeq;
  1056. }
  1057. public void obsoleteWishRecord(Long userId) {
  1058. aWishRecordMapper.updateObsoleteByUser(userId);
  1059. busiWishRecordsMapper.updateObsoleteByUser(userId);
  1060. }
  1061. public R<JSONObject> getVoluntary(Long id) { // 志愿表详情 // 后台填充快照缺省
  1062. SysUser user = SecurityUtils.getLoginUser().getUser();
  1063. AWishRecord wishRecord = aWishRecordMapper.selectAWishRecordById(id);
  1064. if (null == wishRecord || !SecurityUtils.getUserId().equals(wishRecord.getUserId())) {
  1065. return R.fail("错误id");
  1066. }
  1067. if (null == wishRecord) {
  1068. throw new ServiceException("无此志愿id");
  1069. } else if (!user.getUserId().equals(wishRecord.getUserId())) {
  1070. throw new ServiceException("无此志愿id号");
  1071. }
  1072. JSONObject resp = toModel(wishRecord);
  1073. return R.ok(resp);
  1074. }
  1075. private JSONObject toModel(AWishRecord wishRecord) {
  1076. SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
  1077. JSONObject model = new JSONObject();
  1078. model.put("id", wishRecord.getId());
  1079. model.put("year", wishRecord.getYear());
  1080. model.put("voluntaryType", VoluntaryDto.EnumVoluntaryType.valueOf(wishRecord.getType()));
  1081. model.put("name", wishRecord.getName());
  1082. model.put("batchName", wishRecord.getBatchName());
  1083. model.put("createTime", sdf.format(wishRecord.getCreateTime()));
  1084. try {
  1085. model.put("userSnapshot", mapper.readValue(wishRecord.getUserSnapshot(), VoluntaryDto.User.class));
  1086. model.put("request", JSONObject.parseObject(wishRecord.getRequest()));
  1087. model.put("details", JSONArray.parseArray(wishRecord.getDetails()));
  1088. } catch (JsonProcessingException e) {
  1089. e.printStackTrace();
  1090. }
  1091. return model;
  1092. }
  1093. private VoluntaryDto.SingleResponse buildTestResp() {
  1094. String json = sysConfigService.selectConfigByKey("demo.voluntary.single");
  1095. if (StringUtils.isNotBlank(json)) {
  1096. try {
  1097. return mapper.readValue(json, VoluntaryDto.SingleResponse.class);
  1098. } catch (JsonProcessingException e) {
  1099. e.printStackTrace();
  1100. }
  1101. }
  1102. return new VoluntaryDto.SingleResponse();
  1103. }
  1104. private VoluntaryDto.AIResponse buildAiResp() {
  1105. String json = sysConfigService.selectConfigByKey("demo.voluntary.ai");
  1106. if (StringUtils.isNotBlank(json)) {
  1107. try {
  1108. VoluntaryDto.AIResponse resp = mapper.readValue(json, VoluntaryDto.AIResponse.class);
  1109. resp.setMajorDetails(Lists.newArrayList(buildTestResp()));
  1110. return resp;
  1111. } catch (JsonProcessingException e) {
  1112. e.printStackTrace();
  1113. }
  1114. }
  1115. return new VoluntaryDto.AIResponse();
  1116. }
  1117. private VoluntaryDto.VoluntaryModel buildModel() {
  1118. String json = sysConfigService.selectConfigByKey("demo.voluntary.model");
  1119. if(StringUtils.isNotBlank(json)) {
  1120. try {
  1121. VoluntaryDto.VoluntaryModel model = mapper.readValue(json, VoluntaryDto.VoluntaryModel.class);
  1122. model.setDetails(Lists.newArrayList(buildAiResp()));
  1123. return model;
  1124. } catch (JsonProcessingException e) {
  1125. e.printStackTrace();
  1126. }
  1127. }
  1128. return new VoluntaryDto.VoluntaryModel();
  1129. }
  1130. private VoluntaryDto.EnumRuleType itemType2RuleType(String itemType, String valueType, boolean foreSingleTotal) {
  1131. if ("Notice".equals(valueType)) {
  1132. return VoluntaryDto.EnumRuleType.Readonly;
  1133. } else if (foreSingleTotal && VoluntaryDto.EnumRuleType.ScoreSingle.name().equals(itemType)) {
  1134. return VoluntaryDto.EnumRuleType.ScoreTotal;
  1135. }
  1136. return VoluntaryDto.EnumRuleType.valueOf(itemType);
  1137. }
  1138. }