FormulaUtils.java 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414
  1. package com.mixsmart.utils;
  2. import com.alibaba.fastjson.JSONArray;
  3. import com.alibaba.fastjson.JSONObject;
  4. import org.apache.commons.text.similarity.JaccardSimilarity;
  5. import org.springblade.core.tool.utils.BeanUtil;
  6. import org.springblade.core.tool.utils.Func;
  7. import org.springblade.manager.bean.TableInfo;
  8. import org.springblade.manager.dto.Coords;
  9. import org.springblade.manager.dto.ElementData;
  10. import org.springblade.manager.dto.FormData;
  11. import org.springblade.manager.entity.Formula;
  12. import java.io.*;
  13. import java.math.BigDecimal;
  14. import java.nio.charset.StandardCharsets;
  15. import java.util.*;
  16. import java.util.regex.Matcher;
  17. import java.util.regex.Pattern;
  18. import java.util.stream.Collectors;
  19. import java.util.zip.Deflater;
  20. import java.util.zip.DeflaterOutputStream;
  21. import java.util.zip.Inflater;
  22. import java.util.zip.InflaterInputStream;
  23. /**
  24. * @author yangyj
  25. * @Date 2022/7/14 15:55
  26. * @description TODO
  27. */
  28. public class FormulaUtils {
  29. public static Map<String,Object> triangleSquare(Object ranges){
  30. Map<String,Object> map =new HashMap<>();
  31. if(StringUtils.isEmpty(ranges)){
  32. //z的默认取值范围
  33. ranges="(0,15)";
  34. }
  35. Matcher m = RegexUtils.matcher("(\\-?\\d+)(\\D)(\\+?\\d+)",ranges.toString());
  36. if(m.find()) {
  37. System.out.println();
  38. int min = StringUtils.handObj2Integer(m.group(1));
  39. int max = StringUtils.handObj2Integer(m.group(3));
  40. Integer[] r = pythagorean(min, max);
  41. map.put("X", String.valueOf(r[0]));
  42. map.put("Y", String.valueOf(r[1]));
  43. map.put("Z", String.valueOf(r[2]));
  44. }
  45. return map;
  46. }
  47. /**
  48. * @Description 字符串相似度
  49. * @Param [s1, s2]
  50. * @return double
  51. * @Author yangyj
  52. * @Date 2023.04.12 18:01
  53. **/
  54. public static double getJaccardSimilarity(String s1, String s2) {
  55. Set<Character> set1 = new HashSet<>();
  56. Set<Character> set2 = new HashSet<>();
  57. for (char c : s1.toCharArray()) {
  58. set1.add(c);
  59. }
  60. for (char c : s2.toCharArray()) {
  61. set2.add(c);
  62. }
  63. Set<Character> intersection = new HashSet<>(set1);
  64. intersection.retainAll(set2);
  65. Set<Character> union = new HashSet<>(set1);
  66. union.addAll(set2);
  67. return (double) intersection.size() / union.size();
  68. }
  69. public static Double similarity(String s1,String s2){
  70. return getJaccardSimilarity(parseItemName(s1),parseItemName(s2));
  71. }
  72. /**
  73. * result[0]^2+result[1]^2=result[2]^2 result[] 元素均为正整数
  74. */
  75. public static Integer[] pythagorean(Integer min,Integer max){
  76. Integer[] result = null;
  77. List<Integer[]> list = new ArrayList<>();
  78. for(int i=1;i<=max;i++){
  79. for(int j=1;j<=max;j++){
  80. double tmp = Math.sqrt(Math.pow(i,2)+Math.pow(j,2));
  81. int z= (int) Math.round(tmp);
  82. if(min<z&&z<=max){
  83. Integer[] arr = new Integer[]{ i,j,z};
  84. list.add(arr);
  85. }
  86. }
  87. }
  88. if(ListUtils.isNotEmpty(list)){
  89. Random rm = new Random();
  90. result = list.get(rm.nextInt(list.size()));
  91. }
  92. return result;
  93. }
  94. public static void write(FormData fd, Object data,Boolean nullOrBlank ){
  95. if(Func.isEmpty(fd.getValues())){
  96. /*无定位信息不写入*/
  97. return;
  98. }
  99. /*写入前清空内容*/
  100. fd.getValues().forEach(t->t.setValue(null));
  101. if(data instanceof List){
  102. List<Object> values = (List<Object>) data;
  103. if(!nullOrBlank){
  104. values=values.stream().filter(StringUtils::isNotEmpty).collect(Collectors.toList());
  105. }
  106. if(values.size()>fd.getValues().size()){
  107. /*当生成的数据超过实际容量的时候,会自动追加页数*/
  108. if(fd.getCoordsList().size()==1){
  109. if(values.stream().filter(CustomFunction::containsZH).anyMatch(e->e.toString().contains("\n"))){
  110. fd.getValues().get(0).setValue(values.stream().filter(Objects::nonNull).map(Object::toString).collect(Collectors.joining()));
  111. }else{
  112. fd.getValues().get(0).setValue(values.stream().map(StringUtils::handleNull).collect(Collectors.joining("、")));
  113. }
  114. }else{
  115. // copy(fd,values);
  116. for(int n=0;n<fd.getValues().size();n++){
  117. fd.getValues().get(n).setValue(values.get(n));
  118. }
  119. List<Object> overList=values.stream().skip(fd.getValues().size()).collect(Collectors.toList());
  120. List<Coords> coordsList = fd.getCoordsList();
  121. int addPage=(int)Math.ceil((double)overList.size()/(double)coordsList.size());
  122. fd.setAddPages(addPage);
  123. ElementData last =fd.getValues().get(fd.getValues().size()-1);
  124. int indexBase=last.getIndex()+1;
  125. List<ElementData> addList= new ArrayList<>();
  126. for(int i=0;i<addPage;i++){
  127. for(int j=0;j<coordsList.size();j++){
  128. /*超页就尽管写进去,格式化阶段再加表*/
  129. Coords coords = coordsList.get(j);
  130. Object v=null;
  131. int st=i*coordsList.size()+j;
  132. if(st<overList.size()){
  133. v= overList.get(st);
  134. }
  135. addList.add(new ElementData(indexBase+i,last.getGroupId(),v,coords.getX(),coords.getY()));
  136. }
  137. }
  138. fd.getValues().addAll(addList);
  139. }
  140. }else{
  141. for(int n=0;n<values.size();n++){
  142. fd.getValues().get(n).setValue(values.get(n));
  143. }
  144. }
  145. }else{
  146. if(Formula.FULL.equals(fd.getFormula().getOutm())){
  147. /*填充策略*/
  148. fd.getValues().forEach(e->e.setValue(data));
  149. }else{
  150. fd.getValues().get(0).setValue(data);
  151. }
  152. }
  153. }
  154. public static List<TableInfo> getTableInfoList(JSONArray dataArray) {
  155. if (dataArray != null && !dataArray.isEmpty()) {
  156. List<TableInfo> result = new ArrayList<>();
  157. for (int m = 0; m < dataArray.size(); m++) {
  158. TableInfo tableInfo = new TableInfo();
  159. JSONObject dataInfo2 = dataArray.getJSONObject(m);
  160. //
  161. tableInfo.setContractId(dataInfo2.getString("contractId"));
  162. tableInfo.setPkeyId(dataInfo2.getString("pkeyId"));
  163. tableInfo.setProjectId(dataInfo2.getString("projectId"));
  164. //huangjn 填报的类型,施工或监理
  165. tableInfo.setClassify(dataInfo2.getString("classify"));
  166. //设置首件信息
  167. setFirstData(dataInfo2, tableInfo);
  168. // //设置日志信息
  169. setTheLogData(dataInfo2, tableInfo);
  170. dataInfo2.fluentRemove("contractId")
  171. .fluentRemove("pkeyId")
  172. .fluentRemove("p_key_id")
  173. .fluentRemove("projectId")
  174. .fluentRemove("classify")
  175. .fluentRemove("pickerKey")
  176. .fluentRemove("id")
  177. .fluentRemove("isFirst")
  178. .fluentRemove("firstNodeId")
  179. .fluentRemove("isTheLog")
  180. .fluentRemove("theLogId")
  181. .fluentRemove("linkTabIds")
  182. .fluentRemove("recordTime")
  183. .fluentRemove("businessId")
  184. .fluentRemove("sourceUrl")
  185. .fluentRemove("pdfUrl")
  186. .fluentRemove("firstFileName")
  187. .fluentRemove("");
  188. // 计算数据
  189. LinkedHashMap<String, List<String>> dataMap = dataInfo2.keySet().stream().filter(e -> e.contains("__")).collect(Collectors.groupingBy(e -> e.split("__")[0], LinkedHashMap<String, List<String>>::new, Collectors.toList()));
  190. LinkedHashMap<String, String> dataMap2 = new LinkedHashMap<>();
  191. // 字段组合
  192. for (String k : dataMap.keySet()) {
  193. if (dataMap.get(k).size() > 1 && !dataMap.get(k).contains("000Z")) {
  194. String[] ziduan = dataMap.get(k).toArray(new String[]{});
  195. String temp = "";
  196. for (int i = 0; i < ziduan.length - 1; i++) {
  197. for (int j = 0; j < ziduan.length - i - 1; j++) {
  198. Integer tr = Integer.parseInt((ziduan[j].split("__")[1]).split("_")[0]);
  199. Integer td = Integer.parseInt(ziduan[j].split("__")[1].split("_")[1]);
  200. Integer tr_1 = Integer.parseInt(ziduan[j + 1].split("__")[1].split("_")[0]);
  201. Integer td_1 = Integer.parseInt(ziduan[j + 1].split("__")[1].split("_")[1]);
  202. if (tr > tr_1 && td == td_1) { //纵向排序
  203. temp = ziduan[j];
  204. ziduan[j] = ziduan[j + 1];
  205. ziduan[j + 1] = temp;
  206. }
  207. }
  208. }
  209. String lastStr = dataInfo2.getString(ziduan[0]) + "_^_" + ziduan[0].split("__")[1];
  210. for (int i = 1; i < ziduan.length; i++) {
  211. String keyData = dataInfo2.getString(ziduan[i]);
  212. if (!keyData.equals("")) {
  213. lastStr += "☆" + dataInfo2.getString(ziduan[i]) + "_^_" + ziduan[i].split("__")[1];
  214. }
  215. }
  216. dataMap2.put(k, lastStr);
  217. } else {
  218. String dataVal = dataInfo2.getString(dataMap.get(k).get(0));
  219. dataMap2.put(k, dataVal + "_^_" + dataMap.get(k).get(0).split("__")[1]);
  220. }
  221. }
  222. dataMap2.put("p_key_id", tableInfo.getPkeyId());
  223. tableInfo.setDataMap(dataMap2);
  224. result.add(tableInfo);
  225. }
  226. return result;
  227. }
  228. return null;
  229. }
  230. public static void setFirstData(JSONObject dataInfo2, TableInfo tableInfo) {
  231. //huangjn 判断是否是首件
  232. if (dataInfo2.containsKey("isFirst")) {
  233. tableInfo.setIsFirst(dataInfo2.getString("isFirst"));
  234. }
  235. //huangjn 判断是否是首件
  236. //首件资料绑定的节点
  237. if (dataInfo2.containsKey("firstNodeId")) {
  238. tableInfo.setFirstNodeId(dataInfo2.getString("firstNodeId"));
  239. }
  240. //首件ID(编辑时有值,新增时为空)
  241. if (dataInfo2.containsKey("firstId")) {
  242. tableInfo.setFirstId(dataInfo2.getString("firstId"));
  243. }
  244. //源文件
  245. if (dataInfo2.containsKey("sourceUrl")) {
  246. tableInfo.setSourceUrl(dataInfo2.getString("sourceUrl"));
  247. }
  248. //pdfUrl
  249. if (dataInfo2.containsKey("pdfUrl")) {
  250. tableInfo.setPdfUrl(dataInfo2.getString("pdfUrl"));
  251. }
  252. //文件名称
  253. if (dataInfo2.containsKey("firstFileName")) {
  254. tableInfo.setFirstFileName(dataInfo2.getString("firstFileName"));
  255. }
  256. //关联的信息
  257. if (dataInfo2.containsKey("linkProcessList")) {
  258. tableInfo.setLinkProcessList(dataInfo2.getJSONArray("linkProcessList"));
  259. }
  260. }
  261. /**
  262. * 设置日志信息
  263. */
  264. public static void setTheLogData(JSONObject dataInfo2, TableInfo tableInfo) {
  265. //huangjn 判断是否是日志
  266. if (dataInfo2.containsKey("isTheLog")) {
  267. tableInfo.setIsTheLog(dataInfo2.getString("isTheLog"));
  268. }
  269. //huangjn 判断是否是日志
  270. //huangjn 日志ID
  271. if (dataInfo2.containsKey("theLogId")) {
  272. tableInfo.setTheLogId(dataInfo2.getString("theLogId"));
  273. }
  274. //huangjn 日志ID
  275. //huangjn 日志勾选的工序
  276. if (dataInfo2.containsKey("linkTabIds")) {
  277. tableInfo.setLinkTabIds(dataInfo2.getJSONArray("linkTabIds"));
  278. }
  279. //huangjn 日志勾选的工序
  280. //huangjn 日志所选时间
  281. if (dataInfo2.containsKey("recordTime")) {
  282. tableInfo.setRecordTime(dataInfo2.getString("recordTime"));
  283. }
  284. //huangjn 日志所选时间
  285. //huangjn 每份填报数据的id,目前日志专用
  286. if (dataInfo2.containsKey("id")) {
  287. tableInfo.setBusinessId(dataInfo2.getString("id"));
  288. }
  289. //huangjn 每份填报数据的id,目前日志专用
  290. }
  291. /**从元素名称中解析项目名称*/
  292. public static String parseItemName(String eName){
  293. if (StringUtils.isEmpty(eName)) {
  294. return eName;
  295. }
  296. String str = eName.replaceAll("\\s", "");
  297. Pattern pattern = Pattern.compile("[((_]");
  298. String[] candidate = pattern.split(str);
  299. String regex = "[^\\u4e00-\\u9fa5]+";
  300. Pattern p = Pattern.compile(regex);
  301. return Arrays.stream(candidate)
  302. .map(s -> filterString(s, p))
  303. .filter(s -> !isContainKeywords(s))
  304. .collect(Collectors.joining());
  305. }
  306. private static String filterString(String s, Pattern p) {
  307. Matcher matcher = p.matcher(s);
  308. return matcher.replaceAll("").replaceAll(getRegex(), "");
  309. }
  310. private static String getRegex() {
  311. return "(在合格标准内|满足设计要求|质量评定|评定|判定|项目|总数|抽测|实测|偏差|设计|合格)[率值]?";
  312. }
  313. private static boolean isContainKeywords(String s) {
  314. List<String> keywords = Arrays.asList("或", "每", "个","附录");
  315. return keywords.stream().anyMatch(s::contains);
  316. }
  317. /**
  318. * @Description 深度拷贝
  319. * @Param [originalList]
  320. * @return java.util.List<T>
  321. * @Author yangyj
  322. * @Date 2023.04.28 14:18
  323. **/
  324. public static <T extends Serializable> List<T> copyList(List<T> originalList) {
  325. try {
  326. ByteArrayOutputStream baos = new ByteArrayOutputStream();
  327. ObjectOutputStream oos = new ObjectOutputStream(baos);
  328. oos.writeObject(originalList);
  329. oos.close();
  330. ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
  331. ObjectInputStream ois = new ObjectInputStream(bais);
  332. @SuppressWarnings("unchecked")
  333. List<T> copiedList = (List<T>) ois.readObject();
  334. ois.close();
  335. return copiedList;
  336. } catch (Exception e) {
  337. e.printStackTrace();
  338. }
  339. return null;
  340. }
  341. // public static void main(String[] args) {
  342. // List<String> list =Arrays.asList(
  343. // ""
  344. // ,"压 实 度 (%)下路床 特重、极重交通荷载等级 设计值"
  345. // ,"1△_压 实 度 (%)_下路床_轻、中及重交通 荷载等级_0.3m~0.8m_≧96_≧95_≧94_实测值或实测偏差值"
  346. // ,"1△_压 实 度 (%)_下路提_轻、中及重交通 荷载等级_&gt;1.5m_≧93_≧92_≧90_实测值或实测偏差值"
  347. // ,"1△_压 实 度 (%)_上路提_轻、中及重交通 荷载等级_0.8m~1.5m_≧94_≧94_≧93_实测值或实测偏差值"
  348. // ,"压 实 度 (%)下路提 轻、中及重交通荷载等级 设计值"
  349. // ,"压 实 度 (%)下路床 特重、极重交通荷载等级 合格率"
  350. // ,"压 实 度 (%)下路提 轻、中及重交通荷载等级\t合格率"
  351. // ,"5△_保护层 厚度 (mm)_基础、锚碇、墩台身、墩柱_±10_实测值或实测偏差值"
  352. // ,"钢筋骨架尺寸宽、高或直径 (mm)_尺量:按骨架总数30%抽测_±5_实测值或实测偏差值"
  353. // ,"钢筋骨架尺寸长 (mm)_±10_尺量:按骨架总数30%抽测_实测值或实测偏差值"
  354. // , "受力钢筋间距 (mm)同排 梁、板、拱肋及拱上建筑 设计值"
  355. // ,"受力钢筋间距 (mm)同排 梁、板、拱肋及拱上建筑 合格率"
  356. // ," 箍筋、构造钢筋、螺旋筋间距(mm) 设计值"
  357. // ,"箍筋、构造钢筋、螺旋筋间距(mm) 合格率"
  358. // ,"实测项目_桩位 (mm)_群桩_≤100_质量评定_合格判定"
  359. // ,"实测项目_桩位 (mm)_群桩_≤100_实测值或实测偏差值"
  360. // ,"实测项目_桩位 (mm)_排架桩_实测值或实测偏差值"
  361. // ,"实测项目_桩位 (mm)_排架桩_质量评定_合格判定"
  362. // ,"实测项目_桩位 (mm)_群桩_≤100_质量评定_合格率(%)"
  363. // ,"实测项目_桩位 (mm)_排架桩_质量评定_合格率(%)"
  364. // );
  365. // list.stream().map(FormulaUtils::parseItemName).forEach(System.out::println);
  366. // }
  367. }