package com.shkpr.service.aimodelpower.bizmgr; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.global.base.log.LogLevelFlag; import com.global.base.log.LogPrintMgr; import com.global.base.tools.FastJsonUtil; import com.shkpr.service.aimodelpower.commtools.ProbabilityAlgorithm; import com.shkpr.service.aimodelpower.commtools.TimeTool; import com.shkpr.service.aimodelpower.constants.LogFlagBusiType; import com.shkpr.service.aimodelpower.dbdao.DBMgrProxy; import com.shkpr.service.aimodelpower.dbdao.shizilaishuiDataSource.WaterZILAISHUIDao; import com.shkpr.service.aimodelpower.dbdao.shizilaishuiDataSource.service.intef.WaterCollecationService; import com.shkpr.service.aimodelpower.dbdao.shizilaishuiDataSource.service.intef.WaterTapWaterService; import com.shkpr.service.aimodelpower.dto.ResponseCode; import com.shkpr.service.aimodelpower.dto.ResponseRes; import com.shkpr.service.aimodelpower.dto.TraceRunnable; import com.shkpr.service.aimodelpower.dto.zilaishuiModel.InPumpModel; import com.shkpr.service.aimodelpower.globalmgr.ThreadTaskMgr; import com.shkpr.service.aimodelpower.globalmgr.TraceLogMgr; import com.shkpr.service.aimodelpower.jsonbean.zilaishui.*; import com.shkpr.service.aimodelpower.services.ServiceMgrProxy; import org.apache.commons.collections.MapUtils; import org.springframework.util.CollectionUtils; import org.springframework.util.ObjectUtils; import org.springframework.util.StringUtils; import java.io.*; import java.time.LocalDateTime; import java.time.LocalTime; import java.time.YearMonth; import java.time.format.DateTimeFormatter; import java.time.temporal.TemporalAdjusters; import java.util.*; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.ThreadLocalRandom; import java.util.stream.Collectors; /** * @ClassName KprAimWaterCollecationBizFun * @Description: TODO * @Author LX * @Date 2024/5/27 * @Version V1.0 **/ public class KprAimWaterCollecationBizFun { private static final String MSG_SUCCESS = "success."; private static final String MSG_FAILED = "failed."; private static final String mStrClassName = "KprAimTapWaterBizFun"; private static final String EMPTY_NULL = "NULL"; static JSONObject pumpObj = JSONObject.parseObject("{\n" + " \"UZD299F12944DC10957HJ\": {\n" + " \"outRoom\": {\n" + " \"pumps\": [\n" + " {\n" + " \"label\": \"1\",\n" + " \"status\": 1,\n" + " \"forecastStatus\": 0\n" + " },\n" + " {\n" + " \"label\": \"2\",\n" + " \"status\": 1,\n" + " \"forecastStatus\": 1\n" + " },\n" + " {\n" + " \"label\": \"3\",\n" + " \"status\": 1,\n" + " \"forecastStatus\": 0\n" + " },\n" + " {\n" + " \"label\": \"4\",\n" + " \"status\": 1,\n" + " \"forecastStatus\": 1\n" + " },\n" + " {\n" + " \"label\": \"5\",\n" + " \"status\": 1,\n" + " \"forecastStatus\": 0\n" + " },\n" + " {\n" + " \"label\": \"6\",\n" + " \"status\": 1,\n" + " \"forecastStatus\": 1\n" + " },\n" + " {\n" + " \"label\": \"7\",\n" + " \"status\": 1,\n" + " \"forecastStatus\": 0\n" + " }\n" + " ]\n" + " }\n" + " },\n" + " \"UZD299F12DF5241082772\": {\n" + " \"outRoom\": {\n" + " \"pumps\": [\n" + " {\n" + " \"label\": \"1\",\n" + " \"status\": 1,\n" + " \"forecastStatus\": 1\n" + " },\n" + " {\n" + " \"label\": \"2\",\n" + " \"status\": 1,\n" + " \"forecastStatus\": 0\n" + " },\n" + " {\n" + " \"label\": \"3\",\n" + " \"status\": 1,\n" + " \"forecastStatus\": 0\n" + " },\n" + " {\n" + " \"label\": \"4\",\n" + " \"status\": 1,\n" + " \"forecastStatus\": 1\n" + " },\n" + " {\n" + " \"label\": \"5\",\n" + " \"status\": 1,\n" + " \"forecastStatus\": 0\n" + " },\n" + " {\n" + " \"label\": \"6\",\n" + " \"status\": 1,\n" + " \"forecastStatus\": 1\n" + " },\n" + " {\n" + " \"label\": \"7\",\n" + " \"status\": 1,\n" + " \"forecastStatus\": 0\n" + " },\n" + " {\n" + " \"label\": \"8\",\n" + " \"status\": 1,\n" + " \"forecastStatus\": 0\n" + " },\n" + " {\n" + " \"label\": \"9\",\n" + " \"status\": 1,\n" + " \"forecastStatus\": 1\n" + " },\n" + " {\n" + " \"label\": \"10\",\n" + " \"status\": 1,\n" + " \"forecastStatus\": 0\n" + " }\n" + " ]\n" + " }\n" + " },\n" + " \"UZD299F1301D04107668V\": {\n" + " \"outRoom\": {\n" + " \"pumps\": [\n" + " {\n" + " \"label\": \"1\",\n" + " \"status\": 1,\n" + " \"forecastStatus\": 0\n" + " },\n" + " {\n" + " \"label\": \"2\",\n" + " \"status\": 1,\n" + " \"forecastStatus\": 1\n" + " },\n" + " {\n" + " \"label\": \"3\",\n" + " \"status\": 1,\n" + " \"forecastStatus\": 1\n" + " },\n" + " {\n" + " \"label\": \"4\",\n" + " \"status\": 1,\n" + " \"forecastStatus\": 1\n" + " },\n" + " {\n" + " \"label\": \"5\",\n" + " \"status\": 1,\n" + " \"forecastStatus\": 1\n" + " },\n" + " {\n" + " \"label\": \"6\",\n" + " \"status\": 1,\n" + " \"forecastStatus\": 0\n" + " },\n" + " {\n" + " \"label\": \"7\",\n" + " \"status\": 1,\n" + " \"forecastStatus\": 0\n" + " },\n" + " {\n" + " \"label\": \"8\",\n" + " \"status\": 1,\n" + " \"forecastStatus\": 0\n" + " }\n" + " ]\n" + " }\n" + " },\n" + " \"UZD299F133DE5C1066A5L\": {\n" + " \"outRoom\": {\n" + " \"pumps\": [\n" + " {\n" + " \"label\": \"1\",\n" + " \"status\": 1,\n" + " \"forecastStatus\": 0\n" + " },\n" + " {\n" + " \"label\": \"2\",\n" + " \"status\": 1,\n" + " \"forecastStatus\": 1\n" + " },\n" + " {\n" + " \"label\": \"3\",\n" + " \"status\": 1,\n" + " \"forecastStatus\": 1\n" + " },\n" + " {\n" + " \"label\": \"4\",\n" + " \"status\": 1,\n" + " \"forecastStatus\": 1\n" + " },\n" + " {\n" + " \"label\": \"5\",\n" + " \"status\": 1,\n" + " \"forecastStatus\": 1\n" + " },\n" + " {\n" + " \"label\": \"6\",\n" + " \"status\": 1,\n" + " \"forecastStatus\": 0\n" + " }\n" + " ]\n" + " }\n" + " },\n" + " \"UZD299F1389E6010476AV\": {\n" + " \"outRoom\": {\n" + " \"pumps\": [\n" + " {\n" + " \"label\": \"1\",\n" + " \"status\": 1,\n" + " \"forecastStatus\": 0\n" + " },\n" + " {\n" + " \"label\": \"2\",\n" + " \"status\": 1,\n" + " \"forecastStatus\": 0\n" + " },\n" + " {\n" + " \"label\": \"3\",\n" + " \"status\": 1,\n" + " \"forecastStatus\": 1\n" + " },\n" + " {\n" + " \"label\": \"4\",\n" + " \"status\": 1,\n" + " \"forecastStatus\": 1\n" + " },\n" + " {\n" + " \"label\": \"5\",\n" + " \"status\": 1,\n" + " \"forecastStatus\": 1\n" + " },\n" + " {\n" + " \"label\": \"6\",\n" + " \"status\": 1,\n" + " \"forecastStatus\": 0\n" + " },\n" + " {\n" + " \"label\": \"7\",\n" + " \"status\": 1,\n" + " \"forecastStatus\": 1\n" + " }\n" + " ]\n" + " }\n" + " },\n" + " \"UZD299F139CB2410181HP\": {\n" + " \"outRoom\": {\n" + " \"pumps\": [\n" + " {\n" + " \"label\": \"1\",\n" + " \"status\": 1\n" + " },\n" + " {\n" + " \"label\": \"2\",\n" + " \"status\": 1\n" + " },\n" + " {\n" + " \"label\": \"3\"\n" + " },\n" + " {\n" + " \"label\": \"4\"\n" + " },\n" + " {\n" + " \"label\": \"5\"\n" + " },\n" + " {\n" + " \"label\": \"6\"\n" + " }\n" + " ]\n" + " }\n" + " }\n" + "}"); public static WaterCollecationService getWaterTapWaterApi(){ return DBMgrProxy.getInstance().applyWaterCollecationService(); } public static WaterTapWaterService getWaterTapApi(){ return DBMgrProxy.getInstance().applyWaterTapWaterService(); } static DateTimeFormatter formater = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); static DateTimeFormatter formater2 = DateTimeFormatter.ofPattern("yyyy-MM-dd"); public static String databaseName = ""; //TODO 获取数据库名 public static void initDatabaseName(){ Properties prop = new Properties(); InputStream input = null; try { input = new FileInputStream("./sql.properties"); // 加载properties文件 prop.load(input); // 根据属性名获取属性值 String databaseName = prop.getProperty("spring,database.name"); KprAimWaterCollecationBizFun.databaseName = databaseName; } catch (IOException ex) { ex.printStackTrace(); } finally { if (input != null) { try { input.close(); } catch (IOException e) { e.printStackTrace(); } } } } /** * 通过 orgId 查找对应的 orgName * * @param workZoneIds Map 集合 * @param orgId 指定的 orgId * @return Optional 对应的 orgName */ public static Optional findOrgNameByOrgId(Map workZoneIds, String orgId) { return workZoneIds.entrySet() .stream() .filter(entry -> orgId.equals(entry.getValue())) .map(Map.Entry::getKey) .findFirst(); // 找不到会自动返回 Optional.empty() } private static double parseDouble(Object value) { return value == null ? 0.0 : Double.parseDouble(value.toString()); } //TODO 查询日取水量预测接口 /** * 1.传入水厂Id及起止日期(日期格式为YYYY-MM-DD),返回日期内,每天的预测取水量数据和实际取水量数据 * 2.同时返回指定截止日期之后,未来4天的预测水量数据和实际水量(如没有,则返回为空数据) */ public static ResponseRes selectTbWaterList(JPTbMWater jpTbMWater,Integer level,Map>> result ,Map workZonIds){ ResponseRes responseRes = new ResponseRes(); List> list =new ArrayList<>(); Map map = new HashMap<>(); map.put("ID", null); map.put("Date", null); map.put("Max_temperature", null); map.put("Min_temperature", null); map.put("Weather", null); map.put("Month", null); map.put("Week", null); map.put("Holiday", null); map.put("LastActualWaterWithdrawals", null); map.put("LastActualWaterSupply", null); map.put("ActualWaterWithdrawals", null); map.put("ActualWaterSupply", null); map.put("ForecastWaterWithdrawals", null); map.put("ForecastActualWaterSupply", null); map.put("isAbnormal", null); map.put("isForecast", null); map.put("LastModifyTime", null); list.add(map); responseRes.setResdata(list); responseRes.setRescode(ResponseCode.RESULT_NORMAL.toStrCode()); responseRes.setResmsg(ResponseCode.RESULT_NORMAL.toStrMsg()); try { if ("water_volume_prediction".equals(databaseName)){ //TODO 自来水分了二级泵房,要做查询数据处理,点击水厂查询条件时,查询其下的泵房数据 再相加, //TODO 点击泵房则就查泵房的数据 ,无需做处理 List childList = new ArrayList<>();//要查询的组织机构名称集合 List childIdList = new ArrayList<>();//要查询的组织机构id集合 if (level==1){ //TODO 一级已经没有数据了(水厂), 查询一级的话则是将其下的供水数据相加 //TODO 查询二级,及其二级带的三级 Optional zoneNameOpt = findOrgNameByOrgId(workZonIds,jpTbMWater.getOrgId()); if(zoneNameOpt.isPresent()){ String zoneName = zoneNameOpt.get().toString(); Map> childMap = result.get(zoneName);//二级 Collection> child2Map = childMap.values();//三级 // 添加二级组织机构名称(childMap 的 keySet) childList.addAll(childMap.keySet()); // 添加三级组织机构名称(child2Map 的所有 List) for (List child2List : child2Map) { childList.addAll(child2List); } } }else if(level==2){ //TODO 如果是二级,就查询其自身,看看其下还有没有集合,有的话就查其下的所有集合,没有的话就查其自身 Optional zoneNameOpt = findOrgNameByOrgId(workZonIds,jpTbMWater.getOrgId()); if(zoneNameOpt.isPresent()) { String zoneName = zoneNameOpt.get().toString(); List childMap = new ArrayList<>();//三级 // 遍历第一级 Map for (Map.Entry>> entry : result.entrySet()) { Map> nestedMap = entry.getValue(); // 检查第二级键 if (nestedMap.containsKey(zoneName)) { childMap = nestedMap.get(zoneName); } } if(childMap.size()>0) { // 添三级组织机构名称(childMap 的 keySet) childList.addAll(childMap); }else{ childList.add(zoneName); } } }else if(level==3){ LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO, LogFlagBusiType.BUSI_INTERNAL.toStrValue(), mStrClassName, "" , "5555"); //TODO 如果是三级,就查询其自身 Optional zoneNameOpt = findOrgNameByOrgId(workZonIds,jpTbMWater.getOrgId()); if(zoneNameOpt.isPresent()) { String zoneName = zoneNameOpt.get().toString(); childList.add(zoneName); } }else if(level==-1){ List> orgConfig = getWaterTapWaterApi().getOrgConfig(false,0,0,""); Map objectMap = orgConfig.stream() .filter(mapX -> Objects.equals(jpTbMWater.getOrgId(), mapX.get("org_id"))) .findFirst().orElse(null); if(objectMap!=null) { childList.add(objectMap.get("org_name").toString()); childIdList.add(objectMap.get("org_id").toString()); } } //TODO 开始查询 // 结果集合,存储 childList 对应的组织机构 ID // 遍历 childList,从 workZonIds 中获取对应的 ID for (String orgName : childList) { String orgId = workZonIds.get(orgName); if (orgId != null) { // 避免空值 childIdList.add(orgId); } } List> newResList = new ArrayList<>(); int index = 0; for (String orgId:childIdList){ jpTbMWater.setOrgId(orgId); jpTbMWater.checkValid(); List> resList = getWaterTapWaterApi().getTbMWater(jpTbMWater.getIsPage(), jpTbMWater.getLimit(), jpTbMWater.getOffset(), jpTbMWater.getForDateStr() + " ORDER BY \"Date\" ASC "); if(!CollectionUtils.isEmpty(newResList)&&!CollectionUtils.isEmpty(resList)){ //TODO 说明要查询的分区不止一个,则把原来有的数据与新查的数据相加,因为按Date排了序所以一致 for (int i=0;i> resList = getWaterTapWaterApi().getTbMWater(jpTbMWater.getIsPage(), jpTbMWater.getLimit(), jpTbMWater.getOffset(), jpTbMWater.getForDateStr()); if (!CollectionUtils.isEmpty(resList)) { responseRes.setRescode(ResponseCode.RESULT_NORMAL.toStrCode()); responseRes.setResmsg(ResponseCode.RESULT_NORMAL.toStrMsg()); responseRes.setResdata(resList); } } return responseRes; }catch(Exception ex){ responseRes.setResdata(null); responseRes.setResmsg(ResponseCode.RESULT_BAD.toStrMsg()); responseRes.setRescode(ResponseCode.RESULT_BAD.toStrCode()); return responseRes; } } //TODO 获取15分钟实际水量数据 public static ResponseRes selectRealMinutesWaterList(JPRealHourWater jpTbMHourWater,Integer level,Map>> result ,Map workZonIds){ ResponseRes responseRes = new ResponseRes(); List> list = new ArrayList<>(); Map map = new HashMap<>(); // map.put("id", null); map.put("org_name", null); map.put("time", null); map.put("value", null); // map.put("value_tag", null); // map.put("collcation_tag_array", null); list.add(map); responseRes.setResdata(list); responseRes.setRescode(ResponseCode.RESULT_NORMAL.toStrCode()); responseRes.setResmsg(ResponseCode.RESULT_NORMAL.toStrMsg()); try { List> orgConfig = getWaterTapWaterApi().getOrgConfig(false, 0, 0, ""); if ("water_volume_prediction_jiangjin2".equals(databaseName)) { orgConfig = getWaterTapWaterApi().getOrgConfig(false, 0, 0, ""); } if(!CollectionUtils.isEmpty(orgConfig)){ //TODO 根据分区编号找到对应的名称 if(level==null||level!=1||level==-1) { Optional> mapOrg = orgConfig.stream() .filter(maps -> jpTbMHourWater.getOrgId().equals(maps.get("org_id"))) .findFirst(); if (mapOrg.isPresent()) { Map currentOrg = mapOrg.get(); List> recordAllRes = getWaterTapApi() .getWaterCollectionRecordAllListAllNew(" WHERE 1=1 " + " AND org_name = '" + currentOrg.get("org_name").toString() + "'" + jpTbMHourWater.getForDateStr()); recordAllRes.stream() .forEach(item -> { item.remove("id"); item.remove("value_tag"); item.remove("collcation_tag_array"); }); if (jpTbMHourWater.getDayData()) { responseRes.setResdata(aggregateByDay(recordAllRes)); } else { responseRes.setResdata(recordAllRes); } } }else if(level!=null&&level ==1){ //TODO 一级已经没有数据了(水厂), 查询一级的话则是将其下的供水数据相加 //TODO 查询二级,及其二级带的三级 List childList = new ArrayList<>();//要查询的组织机构名称集合 List childIdList = new ArrayList<>();//要查询的组织机构id集合 Optional zoneNameOpt = findOrgNameByOrgId(workZonIds,jpTbMHourWater.getOrgId()); if(zoneNameOpt.isPresent()){ String zoneName = zoneNameOpt.get().toString(); Map> childMap = result.get(zoneName);//二级 Collection> child2Map = childMap.values();//三级 // 添加二级组织机构名称(childMap 的 keySet) childList.addAll(childMap.keySet()); // 添加三级组织机构名称(child2Map 的所有 List) for (List child2List : child2Map) { childList.addAll(child2List); } } // 结果集合,存储 childList 对应的组织机构 ID // 遍历 childList,从 workZonIds 中获取对应的 ID for (String orgName : childList) { String orgId = workZonIds.get(orgName); if (orgId != null) { // 避免空值 childIdList.add(orgId); } } List> newResList = new ArrayList<>(); int index = 0; for (String orgName:childList){ List> resList = getWaterTapApi() .getWaterCollectionRecordAllListAllNew(" WHERE 1=1 " + " AND org_name = '"+orgName+"'" + jpTbMHourWater.getForDateStr() + " ORDER BY time ASC "); if(!CollectionUtils.isEmpty(newResList)&&!CollectionUtils.isEmpty(resList)){ //TODO 说明要查询的分区不止一个,则&把原来有的数据与新查的数据相加,因为按Date排了序所以一致 for (int i=0;i=resList.size()){ continue; } newResList.get(i).put("value", String.valueOf(parseDouble(newResList.get(i).get("value")) + parseDouble(resList.get(i).get("value")))); newResList.get(i).put("org_name",orgName); newResList.get(i).put("time",resList.get(i).get("time")); } }else { newResList.addAll(resList); } index++; } newResList.stream() .forEach(item -> { item.remove("id"); item.remove("value_tag"); item.remove("collcation_tag_array"); }); if(jpTbMHourWater.getDayData()){ responseRes.setResdata(aggregateByDay(newResList)); }else{ responseRes.setResdata(newResList); } } } return responseRes; }catch(Exception ex){ ex.printStackTrace(); responseRes.setResdata(null); responseRes.setResmsg(ResponseCode.RESULT_BAD.toStrMsg()); responseRes.setRescode(ResponseCode.RESULT_BAD.toStrCode()); return responseRes; } } //TODO 获取小时实际水量数据 public static ResponseRes selectRealHourWaterList(JPRealHourWater jpTbMHourWater,Integer level,Map>> result ,Map workZonIds){ ResponseRes responseRes = new ResponseRes(); List> list = new ArrayList<>(); Map map = new HashMap<>(); // map.put("id", null); map.put("org_name", null); map.put("time", null); map.put("value", null); // map.put("value_tag", null); // map.put("collcation_tag_array", null); list.add(map); responseRes.setResdata(list); responseRes.setRescode(ResponseCode.RESULT_NORMAL.toStrCode()); responseRes.setResmsg(ResponseCode.RESULT_NORMAL.toStrMsg()); try { List> orgConfig = getWaterTapWaterApi().getOrgConfig(false, 0, 0, ""); if ("water_volume_prediction_jiangjin2".equals(databaseName)) { orgConfig = getWaterTapWaterApi().getOrgConfig(false, 0, 0, ""); } if(!CollectionUtils.isEmpty(orgConfig)){ //TODO 根据分区编号找到对应的名称 if(level==null||level!=1||level==-1) { Optional> mapOrg = orgConfig.stream() .filter(maps -> jpTbMHourWater.getOrgId().equals(maps.get("org_id"))) .findFirst(); if (mapOrg.isPresent()) { Map currentOrg = mapOrg.get(); List> recordAllRes = getWaterTapApi() .getWaterCollectionRecordAllListAll(" WHERE 1=1 " + " AND org_name = '" + currentOrg.get("org_name").toString() + "'" + jpTbMHourWater.getForDateStr()); recordAllRes.stream() .forEach(item -> { item.remove("id"); item.remove("value_tag"); item.remove("collcation_tag_array"); }); if (jpTbMHourWater.getDayData()) { responseRes.setResdata(aggregateByDay(recordAllRes)); } else { responseRes.setResdata(recordAllRes); } } }else if(level!=null&&level ==1){ //TODO 一级已经没有数据了(水厂), 查询一级的话则是将其下的供水数据相加 //TODO 查询二级,及其二级带的三级 List childList = new ArrayList<>();//要查询的组织机构名称集合 List childIdList = new ArrayList<>();//要查询的组织机构id集合 Optional zoneNameOpt = findOrgNameByOrgId(workZonIds,jpTbMHourWater.getOrgId()); if(zoneNameOpt.isPresent()){ String zoneName = zoneNameOpt.get().toString(); Map> childMap = result.get(zoneName);//二级 Collection> child2Map = childMap.values();//三级 // 添加二级组织机构名称(childMap 的 keySet) childList.addAll(childMap.keySet()); // 添加三级组织机构名称(child2Map 的所有 List) for (List child2List : child2Map) { childList.addAll(child2List); } } // 结果集合,存储 childList 对应的组织机构 ID // 遍历 childList,从 workZonIds 中获取对应的 ID for (String orgName : childList) { String orgId = workZonIds.get(orgName); if (orgId != null) { // 避免空值 childIdList.add(orgId); } } List> newResList = new ArrayList<>(); int index = 0; for (String orgName:childList){ List> resList = getWaterTapApi() .getWaterCollectionRecordAllListAll(" WHERE 1=1 " + " AND org_name = '"+orgName+"'" + jpTbMHourWater.getForDateStr() + " ORDER BY time ASC "); if(!CollectionUtils.isEmpty(newResList)&&!CollectionUtils.isEmpty(resList)){ //TODO 说明要查询的分区不止一个,则&把原来有的数据与新查的数据相加,因为按Date排了序所以一致 for (int i=0;i { item.remove("id"); item.remove("value_tag"); item.remove("collcation_tag_array"); }); if(jpTbMHourWater.getDayData()){ responseRes.setResdata(aggregateByDay(newResList)); }else{ responseRes.setResdata(newResList); } } } return responseRes; }catch(Exception ex){ responseRes.setResdata(null); responseRes.setResmsg(ResponseCode.RESULT_BAD.toStrMsg()); responseRes.setRescode(ResponseCode.RESULT_BAD.toStrCode()); return responseRes; } } public static List> aggregateByDay(List> hourlyData) { // 定义日期格式 DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd 00:00:00"); // 按日期分组 Map>> groupedByDate = hourlyData.stream() .collect(Collectors.groupingBy( record -> { String timeStr = (String) record.get("time"); LocalDateTime dateTime = LocalDateTime.parse(timeStr, formatter); return dateTime.format(dateFormatter); } )); // 创建结果列表 List> dailyData = new ArrayList<>(); // 对每天的数据进行聚合 groupedByDate.forEach((date, records) -> { Map dailyRecord = new HashMap<>(); // 保留第一个记录的id和org_name dailyRecord.put("org_name", records.get(0).get("org_name")); dailyRecord.put("time", date); // 计算当天的总值(示例为求和) double sum = records.stream() .mapToDouble(record -> Double.parseDouble((String) record.get("value"))) .sum(); // 计算当天平均值 double average = sum / records.size(); // dailyRecord.put("total_value", String.valueOf(sum)); // dailyRecord.put("average_value", String.valueOf(average)); // dailyRecord.put("record_count", records.size()); dailyRecord.put("value", String.valueOf(sum)); dailyData.add(dailyRecord); }); return dailyData; } //TODO 15分钟水量预测接口 /** * 传入水厂id及日期,返回指定日期内的小时取水量预测数据和实际小时取水量数据 */ public static ResponseRes selectTbMinutesWaterList(JPTbMMinutesWater jpTbMHourWater,Integer level,Map>> result ,Map workZonIds){ ResponseRes responseRes = new ResponseRes(); List> list = new ArrayList<>(); Map map = new HashMap<>(); map.put("ID", null); map.put("Date", null); map.put("Hour", null); map.put("HourForecastWaterWithdrawals", null); map.put("HourForecastActualWaterSupply", null); map.put("WaterWithdrawalsEnergy", null); map.put("WaterSupplyEnergy", null); map.put("RealWaterWithdrawalsEnergy", null); map.put("RealWaterSupplyEnergy", null); map.put("LastModifyTime", null); map.put("HourActualWaterWithdrawals", null); map.put("HourActualWaterSupply ", null); list.add(map); responseRes.setResdata(list); responseRes.setRescode(ResponseCode.RESULT_NORMAL.toStrCode()); responseRes.setResmsg(ResponseCode.RESULT_NORMAL.toStrMsg()); try { if ("water_volume_prediction".equals(databaseName)){ //TODO 自来水分了二级泵房,要做查询数据处理,点击水厂查询条件时,查询其下的泵房数据 再相加, //TODO 点击泵房则就查泵房的数据 ,无需做处理 List childList = new ArrayList<>();//要查询的组织机构名称集合 List childIdList = new ArrayList<>();//要查询的组织机构id集合 if (level==1){ //TODO 一级已经没有数据了(水厂), 查询一级的话则是将其下的供水数据相加 //TODO 查询二级,及其二级带的三级 Optional zoneNameOpt = findOrgNameByOrgId(workZonIds,jpTbMHourWater.getOrgId()); if(zoneNameOpt.isPresent()){ String zoneName = zoneNameOpt.get().toString(); Map> childMap = result.get(zoneName);//二级 Collection> child2Map = childMap.values();//三级 // 添加二级组织机构名称(childMap 的 keySet) childList.addAll(childMap.keySet()); // 添加三级组织机构名称(child2Map 的所有 List) for (List child2List : child2Map) { childList.addAll(child2List); } } }else if(level==2){ //TODO 如果是二级,就查询其自身,看看其下还有没有集合,有的话就查其下的所有集合,没有的话就查其自身 Optional zoneNameOpt = findOrgNameByOrgId(workZonIds,jpTbMHourWater.getOrgId()); if(zoneNameOpt.isPresent()) { String zoneName = zoneNameOpt.get().toString(); List childMap = new ArrayList<>();//三级 // 遍历第一级 Map for (Map.Entry>> entry : result.entrySet()) { Map> nestedMap = entry.getValue(); // 检查第二级键 if (nestedMap.containsKey(zoneName)) { childMap = nestedMap.get(zoneName); } } if(childMap.size()>0) { // 添三级组织机构名称(childMap 的 keySet) childList.addAll(childMap); }else{ childList.add(zoneName); } } }else if(level==3){ //TODO 如果是三级,就查询其自身 Optional zoneNameOpt = findOrgNameByOrgId(workZonIds,jpTbMHourWater.getOrgId()); if(zoneNameOpt.isPresent()) { String zoneName = zoneNameOpt.get().toString(); childList.add(zoneName); } }else if(level==-1){ List> orgConfig = getWaterTapWaterApi().getOrgConfig(false,0,0,""); Map objectMap = orgConfig.stream() .filter(mapX -> Objects.equals(jpTbMHourWater.getOrgId(), mapX.get("org_id"))) .findFirst().orElse(null); if(objectMap!=null) { childList.add(objectMap.get("org_name").toString()); childIdList.add(objectMap.get("org_id").toString()); } } //TODO 开始查询 // 结果集合,存储 childList 对应的组织机构 ID // 遍历 childList,从 workZonIds 中获取对应的 ID for (String orgName : childList) { String orgId = workZonIds.get(orgName); if (orgId != null) { // 避免空值 childIdList.add(orgId); } } List> newResList = new ArrayList<>(); int index = 0; for (String orgId:childIdList){ jpTbMHourWater.setOrgId(orgId); jpTbMHourWater.checkValid(); List> resList = getWaterTapWaterApi().getTbMHourwaterNew(jpTbMHourWater.getIsPage(), jpTbMHourWater.getLimit(), jpTbMHourWater.getOffset(), jpTbMHourWater.getForDateStr()+ " ORDER BY \"Date\",\"Hour\" ASC "); if(!CollectionUtils.isEmpty(newResList)&&!CollectionUtils.isEmpty(resList)){ //TODO 说明要查询的分区不止一个,则&把原来有的数据与新查的数据相加,因为按Date排了序所以一致 for (int i=0;i> resList = getWaterTapWaterApi().getTbMHourwater(jpTbMHourWater.getIsPage(), jpTbMHourWater.getLimit(), jpTbMHourWater.getOffset(), jpTbMHourWater.getForDateStr()); if (!CollectionUtils.isEmpty(resList)) { responseRes.setRescode(ResponseCode.RESULT_NORMAL.toStrCode()); responseRes.setResmsg(ResponseCode.RESULT_NORMAL.toStrMsg()); responseRes.setResdata(resList); } } return responseRes; }catch(Exception ex){ responseRes.setResdata(null); responseRes.setResmsg(ResponseCode.RESULT_BAD.toStrMsg()); responseRes.setRescode(ResponseCode.RESULT_BAD.toStrCode()); return responseRes; } } //TODO 小时水量预测接口 /** * 传入水厂id及日期,返回指定日期内的小时取水量预测数据和实际小时取水量数据 */ public static ResponseRes selectTbHourWaterList(JPTbMHourWater jpTbMHourWater,Integer level,Map>> result ,Map workZonIds){ ResponseRes responseRes = new ResponseRes(); List> list = new ArrayList<>(); Map map = new HashMap<>(); map.put("ID", null); map.put("Date", null); map.put("Hour", null); map.put("HourForecastWaterWithdrawals", null); map.put("HourForecastActualWaterSupply", null); map.put("WaterWithdrawalsEnergy", null); map.put("WaterSupplyEnergy", null); map.put("RealWaterWithdrawalsEnergy", null); map.put("RealWaterSupplyEnergy", null); map.put("LastModifyTime", null); map.put("HourActualWaterWithdrawals", null); map.put("HourActualWaterSupply ", null); list.add(map); responseRes.setResdata(list); responseRes.setRescode(ResponseCode.RESULT_NORMAL.toStrCode()); responseRes.setResmsg(ResponseCode.RESULT_NORMAL.toStrMsg()); try { if ("water_volume_prediction".equals(databaseName)){ //TODO 自来水分了二级泵房,要做查询数据处理,点击水厂查询条件时,查询其下的泵房数据 再相加, //TODO 点击泵房则就查泵房的数据 ,无需做处理 List childList = new ArrayList<>();//要查询的组织机构名称集合 List childIdList = new ArrayList<>();//要查询的组织机构id集合 if (level==1){ //TODO 一级已经没有数据了(水厂), 查询一级的话则是将其下的供水数据相加 //TODO 查询二级,及其二级带的三级 Optional zoneNameOpt = findOrgNameByOrgId(workZonIds,jpTbMHourWater.getOrgId()); if(zoneNameOpt.isPresent()){ String zoneName = zoneNameOpt.get().toString(); Map> childMap = result.get(zoneName);//二级 Collection> child2Map = childMap.values();//三级 // 添加二级组织机构名称(childMap 的 keySet) childList.addAll(childMap.keySet()); // 添加三级组织机构名称(child2Map 的所有 List) for (List child2List : child2Map) { childList.addAll(child2List); } } }else if(level==2){ //TODO 如果是二级,就查询其自身,看看其下还有没有集合,有的话就查其下的所有集合,没有的话就查其自身 Optional zoneNameOpt = findOrgNameByOrgId(workZonIds,jpTbMHourWater.getOrgId()); if(zoneNameOpt.isPresent()) { String zoneName = zoneNameOpt.get().toString(); List childMap = new ArrayList<>();//三级 // 遍历第一级 Map for (Map.Entry>> entry : result.entrySet()) { Map> nestedMap = entry.getValue(); // 检查第二级键 if (nestedMap.containsKey(zoneName)) { childMap = nestedMap.get(zoneName); } } if(childMap.size()>0) { // 添三级组织机构名称(childMap 的 keySet) childList.addAll(childMap); }else{ childList.add(zoneName); } } }else if(level==3){ //TODO 如果是三级,就查询其自身 Optional zoneNameOpt = findOrgNameByOrgId(workZonIds,jpTbMHourWater.getOrgId()); if(zoneNameOpt.isPresent()) { String zoneName = zoneNameOpt.get().toString(); childList.add(zoneName); } }else if(level==-1){ List> orgConfig = getWaterTapWaterApi().getOrgConfig(false,0,0,""); Map objectMap = orgConfig.stream() .filter(mapX -> Objects.equals(jpTbMHourWater.getOrgId(), mapX.get("org_id"))) .findFirst().orElse(null); if(objectMap!=null) { childList.add(objectMap.get("org_name").toString()); childIdList.add(objectMap.get("org_id").toString()); } } //TODO 开始查询 // 结果集合,存储 childList 对应的组织机构 ID // 遍历 childList,从 workZonIds 中获取对应的 ID for (String orgName : childList) { String orgId = workZonIds.get(orgName); if (orgId != null) { // 避免空值 childIdList.add(orgId); } } List> newResList = new ArrayList<>(); int index = 0; for (String orgId:childIdList){ jpTbMHourWater.setOrgId(orgId); jpTbMHourWater.checkValid(); List> resList = getWaterTapWaterApi().getTbMHourwater(jpTbMHourWater.getIsPage(), jpTbMHourWater.getLimit(), jpTbMHourWater.getOffset(), jpTbMHourWater.getForDateStr()+ " ORDER BY \"Date\",\"Hour\" ASC "); if(!CollectionUtils.isEmpty(newResList)&&!CollectionUtils.isEmpty(resList)){ //TODO 说明要查询的分区不止一个,则&把原来有的数据与新查的数据相加,因为按Date排了序所以一致 for (int i=0;i> resList = getWaterTapWaterApi().getTbMHourwater(jpTbMHourWater.getIsPage(), jpTbMHourWater.getLimit(), jpTbMHourWater.getOffset(), jpTbMHourWater.getForDateStr()); if (!CollectionUtils.isEmpty(resList)) { responseRes.setRescode(ResponseCode.RESULT_NORMAL.toStrCode()); responseRes.setResmsg(ResponseCode.RESULT_NORMAL.toStrMsg()); responseRes.setResdata(resList); } } return responseRes; }catch(Exception ex){ responseRes.setResdata(null); responseRes.setResmsg(ResponseCode.RESULT_BAD.toStrMsg()); responseRes.setRescode(ResponseCode.RESULT_BAD.toStrCode()); return responseRes; } } //TODO 小时取水泵房电耗预测接口 /** * 传入水厂id及日期 */ public static ResponseRes selectTbMHourwaterWaterwithdrawals(JPTbMHourWater jpTbMHourWater,String subType){ ResponseRes responseRes = new ResponseRes(); //TODO 默认值 List defaultModels = new ArrayList<>(); InPumpModel entity = new InPumpModel(); entity.setOrgId(null); entity.setPumpId(null); entity.setSubType(subType); List> defaultRes = new ArrayList<>(); Map map = new HashMap<>(); map.put("ID", null); map.put("Date", null); map.put("Hour", null); map.put("PumpID", null); map.put("PumpStatus", null); map.put("HourForecastWaterWithdrawals", null); map.put("PumpWater", null); map.put("RealPumpStatus", null); map.put("PumpEnergy", null); map.put("RealPumpEnergy", null); map.put("LastModifyTime", null); map.put("orgId", null); defaultRes.add(map); defaultModels.add(entity); responseRes.setResdata(defaultModels); responseRes.setRescode(ResponseCode.RESULT_NORMAL.toStrCode()); responseRes.setResmsg(ResponseCode.RESULT_NORMAL.toStrMsg()); try { List> resList = getWaterTapWaterApi().getTbMHourwaterWaterwithdrawals(jpTbMHourWater.getIsPage(), jpTbMHourWater.getLimit(), jpTbMHourWater.getOffset(), jpTbMHourWater.getForDateStr()); //TODO 按水厂分组 Map>> groupedData = resList.stream().collect(Collectors.groupingBy(item -> item.get("orgId"))); //TODO 查询水厂的取水泵,然后将数据拼接 List inPumpModels = new ArrayList<>(); for (Object key:groupedData.keySet()) { InPumpModel model = new InPumpModel(); List> zoonList = getWaterTapWaterApi().getZoonInfoList(key.toString(),subType); if(!CollectionUtils.isEmpty(zoonList)){ model.setPumpId(zoonList.get(0).get("uid").toString()); } model.setOrgId(key.toString()); model.setSubType(subType); List> dataList = groupedData.get(key); //TODO 将年月日时作为分组条件 Map>> dataMap = dataList.stream() .collect(Collectors.groupingBy(emp -> emp.get("Date") + " " + emp.get("Hour") // 创建复合键 )); model.setDataList(dataMap); //TODO 查询相应方案数据 List> drawalsList = getWaterTapWaterApi().getTbMWaterwithdrawalspump(false, 20,0," AND \"orgId\" = '"+key.toString()+"'"); model.setDrawalsList(drawalsList); inPumpModels.add(model); } if(!CollectionUtils.isEmpty(inPumpModels)){ responseRes.setRescode(ResponseCode.RESULT_NORMAL.toStrCode()); responseRes.setResmsg(ResponseCode.RESULT_NORMAL.toStrMsg()); responseRes.setResdata(inPumpModels); } return responseRes; }catch(Exception ex){ responseRes.setResdata(null); responseRes.setResmsg(ResponseCode.RESULT_BAD.toStrMsg()); responseRes.setRescode(ResponseCode.RESULT_BAD.toStrCode()); return responseRes; } } //TODO 小时供水泵房电耗预测接口 /** * 传入水厂id及日期 */ public static ResponseRes selectTbMHourwaterWatersupply(JPTbMHourPump jpTbMHourWater,String subType){ ResponseRes responseRes = new ResponseRes(); //TODO 默认值 List defaultModels = new ArrayList<>(); InPumpModel entity = new InPumpModel(); entity.setOrgId(null); entity.setPumpId(null); entity.setSubType(subType); List> defaultRes = new ArrayList<>(); Map map = new HashMap<>(); map.put("ID", null); map.put("Date", null); map.put("Hour", null); map.put("PumpID", null); map.put("PumpStatus", null); map.put("HourForecastActualWaterSupply", null); map.put("PumpWater", null); map.put("RealPumpStatus", null); map.put("PumpEnergy", null); map.put("RealPumpEnergy", null); map.put("LastModifyTime", null); map.put("orgId", null); defaultRes.add(map); defaultModels.add(entity); responseRes.setResdata(defaultModels); responseRes.setRescode(ResponseCode.RESULT_NORMAL.toStrCode()); responseRes.setResmsg(ResponseCode.RESULT_NORMAL.toStrMsg()); try { // List> resList = getWaterTapWaterApi().getTbMHourwaterWatersupply(jpTbMHourWater.getIsPage(), jpTbMHourWater.getLimit(), jpTbMHourWater.getOffset(), jpTbMHourWater.getForDateStr()); if("water_volume_prediction_jiangjin2".equals(databaseName)){ //TODO 按水厂分组 Map>> groupedData = resList.stream().collect(Collectors.groupingBy(item -> item.get("orgId"))); //TODO 查询水厂的取水泵,然后将数据拼接 List inPumpModels = new ArrayList<>(); for (Object key : groupedData.keySet()) { InPumpModel model = new InPumpModel(); List> zoonList = getWaterTapWaterApi().getZoonInfoList(key.toString(), subType); if (!CollectionUtils.isEmpty(zoonList)) { model.setPumpId(zoonList.get(0).get("uid").toString()); } model.setOrgId(key.toString()); model.setSubType(subType); List> dataList = groupedData.get(key); //TODO 将年月日时作为分组条件 Map>> dataMap = dataList.stream() .collect(Collectors.groupingBy(emp -> emp.get("Date") + " " + emp.get("Hour") // 创建复合键 )); model.setDataList(dataMap); //TODO 查询相应方案数据 List> drawalsList = getWaterTapWaterApi().getTbMWatersupplypump(false, 20, 0, " AND \"orgId\" = '" + key.toString() + "'"); model.setDrawalsList(drawalsList); inPumpModels.add(model); } if (!CollectionUtils.isEmpty(inPumpModels)) { responseRes.setRescode(ResponseCode.RESULT_NORMAL.toStrCode()); responseRes.setResmsg(ResponseCode.RESULT_NORMAL.toStrMsg()); responseRes.setResdata(inPumpModels); } return responseRes; }else { Map>> groupedData = resList.stream().collect(Collectors.groupingBy(item -> item.get("orgId"))); //TODO 查询水厂的取水泵,然后将数据拼接 List inPumpModels = new ArrayList<>(); for (Object key : groupedData.keySet()) { InPumpModel model = new InPumpModel(); List> zoonList = getWaterTapWaterApi().getZoonInfoList(key.toString(), subType); if (!CollectionUtils.isEmpty(zoonList)) { model.setPumpId(zoonList.get(0).get("uid").toString()); } model.setOrgId(key.toString()); model.setSubType(subType); List> dataList = groupedData.get(key); //TODO 将年月日时作为分组条件 Map>> dataMap = dataList.stream() .collect(Collectors.groupingBy(emp -> emp.get("Date") + " " + emp.get("Hour") // 创建复合键 )); model.setDataList(dataMap); //TODO 查询相应方案数据 List> drawalsList = getWaterTapWaterApi().getTbMWatersupplypump(false, 20, 0, " AND \"orgId\" = '" + key.toString() + "'"); model.setDrawalsList(drawalsList); inPumpModels.add(model); } if (!CollectionUtils.isEmpty(inPumpModels)) { responseRes.setRescode(ResponseCode.RESULT_NORMAL.toStrCode()); responseRes.setResmsg(ResponseCode.RESULT_NORMAL.toStrMsg()); responseRes.setResdata(inPumpModels); } return responseRes; } }catch(Exception ex){ responseRes.setResdata(null); responseRes.setResmsg(ResponseCode.RESULT_BAD.toStrMsg()); responseRes.setRescode(ResponseCode.RESULT_BAD.toStrCode()); LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_ERROR , mStrClassName , mStrClassName , String.format("预测泵供水小时数据调用异常 ERROR:{%s} ", ex.getLocalizedMessage())); return responseRes; } } //TODO 定时任务 定时调用水力模型预测接口,截止今天 public static void insertYuceDayData(String monthNow){ LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO,mStrClassName, mStrClassName,"添加预测日数据正在进行"+ TimeTool.convertUTC2DateStr(TimeTool.getCurMsUTC(),TimeTool.TIMESTAMP_FORMAT)); try { String yearStr = ""; String monthStr = ""; if(!StringUtils.isEmpty(monthNow)){ yearStr = monthNow.split("-")[0]; monthStr = monthNow.split("-")[1]; } LocalDateTime startDate = LocalDateTime.now().withYear(Integer.valueOf(yearStr)) .withMonth(Integer.valueOf(monthStr)).withDayOfMonth(1).withHour(0).withMinute(0).withSecond(0).withNano(0); int days = LocalDateTime.now().getDayOfMonth();//获取月份天数 for (int i = 1;i<=days;i++) { LocalDateTime dateNow = startDate.withDayOfMonth(i);//当前循环时间 if (dateNow.isAfter(LocalDateTime.now())) { break; } //TODO 数据库操作 A 调用对应时间预测接口 B 在修改实际值 DateTimeFormatter formatter2 = DateTimeFormatter.ofPattern("yyyy-MM-dd"); String dateStr = dateNow.withYear(LocalDateTime.now().getYear()).toLocalDate().format(formatter2); //TODO A JP3TPDay tpDay = new JP3TPDay(); tpDay.setOrgId(""); tpDay.setSdate(dateStr); tpDay.setEndate(dateStr); try { LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO , mStrClassName , mStrClassName , String.format("执行预测日数据" + FastJsonUtil.toJSON(tpDay) + "调用")); ResponseRes tpRes = ServiceMgrProxy.getInstance() .applyCloud3tpServiceApi().dayDataPredictSupply(tpDay); if (ResponseCode.RESULT_BAD.toStrCode().equals(tpRes.getRescode())) { LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_ERROR , mStrClassName , mStrClassName , String.format("预测日数据" + dateStr + "调用失败 ERROR:{%s} ", tpRes.getResdata())); } } catch (Exception ex) { LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_ERROR , mStrClassName , mStrClassName , String.format("预测日数据" + dateStr + "调用异常 ERROR:{%s} ", ex.getLocalizedMessage())); } } LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO,mStrClassName, mStrClassName,"添加预测日数据结束"+ TimeTool.convertUTC2DateStr(TimeTool.getCurMsUTC(),TimeTool.TIMESTAMP_FORMAT)); }catch(Exception ex){ ex.printStackTrace(); } } //TODO 截止到未来的今天+3 public static void insertYuceDayAddData(String monthNow){ LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO,mStrClassName, mStrClassName,"添加预测日数据正在进行"+ TimeTool.convertUTC2DateStr(TimeTool.getCurMsUTC(),TimeTool.TIMESTAMP_FORMAT)); try { String yearStr = ""; String monthStr = ""; if(!StringUtils.isEmpty(monthNow)){ yearStr = monthNow.split("-")[0]; monthStr = monthNow.split("-")[1]; } LocalDateTime startDate = LocalDateTime.now().withYear(Integer.valueOf(yearStr)) .withMonth(Integer.valueOf(monthStr)).withHour(0).withMinute(0).withSecond(0).withNano(0); List> orgConfig = getWaterTapWaterApi().getOrgConfig(false,0,0," AND org_name != '井口水厂' AND org_name != '丰收坝水厂' AND org_name != '沙坪坝水厂' AND org_name != '北碚红工水厂' AND org_name != '大溪沟水厂' "); if("water_volume_prediction_jiangjin2".equals(databaseName)){ orgConfig = getWaterTapWaterApi().getOrgConfig(false,0,0,""); } LocalDateTime dateNow = startDate; //TODO 数据库操作 A 调用对应时间预测接口 B 在修改实际值 DateTimeFormatter formatter2 = DateTimeFormatter.ofPattern("yyyy-MM-dd"); String dateStr = dateNow.withYear(LocalDateTime.now().getYear()).toLocalDate().format(formatter2); //TODO A for (Map config:orgConfig) { JP3TPDay tpDay = new JP3TPDay(); tpDay.setOrgId(config.get("org_id").toString()); tpDay.setSdate(dateStr); // tpDay.setEndate(dateNow.minusDays(-3).toLocalDate().format(formatter2)); //TODO 预测模型的逻辑是预测当前天往后+3天 tpDay.setEndate(dateNow.minusDays(0).toLocalDate().format(formatter2)); try { LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO , mStrClassName , mStrClassName , String.format("执行预测未来日数据" + FastJsonUtil.toJSON(tpDay) + "调用")); ResponseRes tpRes = ServiceMgrProxy.getInstance() .applyCloud3tpServiceApi().dayDataPredictSupply(tpDay); if (ResponseCode.RESULT_BAD.toStrCode().equals(tpRes.getRescode())) { LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_ERROR , mStrClassName , mStrClassName , String.format("预测日数据" + dateStr + "调用失败 ERROR:{%s} ", tpRes.getResdata())); } } catch (Exception ex) { LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_ERROR , mStrClassName , mStrClassName , String.format("预测日数据" + dateStr + "调用异常 ERROR:{%s} ", ex.getLocalizedMessage())); } } LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO,mStrClassName, mStrClassName,"添加预测日数据结束"+ TimeTool.convertUTC2DateStr(TimeTool.getCurMsUTC(),TimeTool.TIMESTAMP_FORMAT)); }catch(Exception ex){ ex.printStackTrace(); } } //TODO 定时任务 定时调用水力模型小时预测接口,截止今天 public static void insertYuceHourData(String monthNow){ LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO,mStrClassName, mStrClassName,"添加预测小时数据正在进行"+ TimeTool.convertUTC2DateStr(TimeTool.getCurMsUTC(),TimeTool.TIMESTAMP_FORMAT)); try { //先获取配置项 根据配置项来进行逻辑添加 String yearStr = ""; String monthStr =""; if(!StringUtils.isEmpty(monthNow)){ yearStr = monthNow.split("-")[0]; monthStr = monthNow.split("-")[1]; } LocalDateTime startDate = LocalDateTime.now().withYear(Integer.valueOf(yearStr)) .withMonth(Integer.valueOf(monthStr)).withDayOfMonth(1).withHour(0).withMinute(0).withSecond(0).withNano(0); //TODO 总体逻辑: 先查询指定月上一年的每日平均值,再按平均值的上下啊百分比去插入指定的浮动百分比数据 int days = LocalDateTime.now().getDayOfMonth();//获取月份天数 for (int i = 1;i<=days;i++){ LocalDateTime dateNow = startDate.withDayOfMonth(i);//当前循环时间 if(dateNow.toLocalDate().isAfter(LocalDateTime.now().toLocalDate())){ break; } //TODO 数据库操作 A 调用对应时间预测接口 B 在修改实际值 DateTimeFormatter formatter2 = DateTimeFormatter.ofPattern("yyyy-MM-dd"); String dateStr = dateNow.withYear(LocalDateTime.now().getYear()).toLocalDate().format(formatter2); //TODO A JP3TPHour tpHour = new JP3TPHour(); tpHour.setOrgId(""); tpHour.setDate(dateStr); LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO , mStrClassName , mStrClassName , String.format("执行预测小时数据" + FastJsonUtil.toJSON(tpHour) + "调用")); try { ResponseRes tpRes = ServiceMgrProxy.getInstance() .applyCloud3tpServiceApi().dayHourPredictSupply(tpHour); if(ResponseCode.RESULT_BAD.toStrCode().equals(tpRes.getRescode())){ LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_ERROR , mStrClassName , mStrClassName , String.format("预测小时数据"+dateStr+"调用失败 ERROR:{%s} ", tpRes.getResdata())); } }catch(Exception ex){ LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_ERROR , mStrClassName , mStrClassName , String.format("预测小时数据"+dateStr+"调用异常 ERROR:{%s} ", ex.getLocalizedMessage())); } } LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO,mStrClassName, mStrClassName,"调用预测模型小时数据结束"+ TimeTool.convertUTC2DateStr(TimeTool.getCurMsUTC(),TimeTool.TIMESTAMP_FORMAT)); }catch(Exception ex){ ex.printStackTrace(); } } //TODO 截止到未来的今天+3 public static void insertYuceHourAddData(String monthNow,Integer days){ LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO,mStrClassName, mStrClassName,"添加预测小时数据正在进行"+ TimeTool.convertUTC2DateStr(TimeTool.getCurMsUTC(),TimeTool.TIMESTAMP_FORMAT)); try { //先获取配置项 根据配置项来进行逻辑添加 String yearStr = ""; String monthStr =""; if(!StringUtils.isEmpty(monthNow)){ yearStr = monthNow.split("-")[0]; monthStr = monthNow.split("-")[1]; } LocalDateTime startDate = LocalDateTime.now().withYear(Integer.valueOf(yearStr)) .withMonth(Integer.valueOf(monthStr)).withHour(0).withMinute(0).withSecond(0).withNano(0); //TODO 总体逻辑: 先查询指定月上一年的每日平均值,再按平均值的上下啊百分比去插入指定的浮动百分比数据 List> orgConfig = getWaterTapWaterApi().getOrgConfig(false,0,0," AND org_name != '井口水厂' AND org_name != '丰收坝水厂' AND org_name != '沙坪坝水厂' AND org_name != '北碚红工水厂' AND org_name != '大溪沟水厂' "); if("water_volume_prediction_jiangjin2".equals(databaseName)){ orgConfig = getWaterTapWaterApi().getOrgConfig(false,0,0,""); } for (int i = 0;i org : orgConfig) { JP3TPHour tpHour = new JP3TPHour(); tpHour.setOrgId(org.get("org_id").toString()); tpHour.setDate(dateStr); LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO , mStrClassName , mStrClassName , String.format("执行未来预测小时数据" + FastJsonUtil.toJSON(tpHour) + "调用")); try { ResponseRes tpRes = ServiceMgrProxy.getInstance() .applyCloud3tpServiceApi().dayHourPredictSupply(tpHour); if (ResponseCode.RESULT_BAD.toStrCode().equals(tpRes.getRescode())) { LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_ERROR , mStrClassName , mStrClassName , String.format("预测小时数据" + dateStr + "调用失败 ERROR:{%s} ", tpRes.getResdata())); } } catch (Exception ex) { LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_ERROR , mStrClassName , mStrClassName , String.format("预测小时数据" + dateStr + "调用异常 ERROR:{%s} ", ex.getLocalizedMessage())); } } } LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO,mStrClassName, mStrClassName,"调用预测模型小时数据结束"+ TimeTool.convertUTC2DateStr(TimeTool.getCurMsUTC(),TimeTool.TIMESTAMP_FORMAT)); }catch(Exception ex){ ex.printStackTrace(); } } //TODO 跑+1天 public static void insertYucePump(String monthNow){ LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO,mStrClassName, mStrClassName,"添加预测泵组优化小时数据正在进行"+ TimeTool.convertUTC2DateStr(TimeTool.getCurMsUTC(),TimeTool.TIMESTAMP_FORMAT)); try { //先获取配置项 根据配置项来进行逻辑添加 String yearStr = ""; String monthStr =""; if(!StringUtils.isEmpty(monthNow)){ yearStr = monthNow.split("-")[0]; monthStr = monthNow.split("-")[1]; } LocalDateTime startDate = LocalDateTime.now().withYear(Integer.valueOf(yearStr)) .withMonth(Integer.valueOf(monthStr)).withHour(0).withMinute(0).withSecond(0).withNano(0); List> orgConfig = getWaterTapWaterApi().getOrgConfig(false,0,0," AND org_name != '井口水厂' AND org_name != '丰收坝水厂' AND org_name != '沙坪坝水厂' AND org_name != '北碚红工水厂' AND org_name != '大溪沟水厂' "); if("water_volume_prediction_jiangjin2".equals(databaseName)) { orgConfig = getWaterTapWaterApi().getOrgConfig(false, 0, 0,""); } //TODO 总体逻辑: 先查询指定月上一年的每日平均值,再按平均值的上下啊百分比去插入指定的浮动百分比数据 for (int i = 0;i<2;i++){ LocalDateTime dateNow = startDate.minusDays(-i);//当前循环时间 //TODO 数据库操作 A 调用对应时间预测接口 B 在修改实际值 DateTimeFormatter formatter2 = DateTimeFormatter.ofPattern("yyyy-MM-dd"); String dateStr = dateNow.withYear(LocalDateTime.now().getYear()).toLocalDate().format(formatter2); //TODO A for (Map org : orgConfig) { JP3TPHour tpHour = new JP3TPHour(); tpHour.setOrgId(org.get("org_id").toString()); tpHour.setDate(dateStr); LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO , mStrClassName , mStrClassName , String.format("执行未来预测泵组优化小时数据" + FastJsonUtil.toJSON(tpHour) + "调用")); try { ResponseRes tpRes = ServiceMgrProxy.getInstance() .applyCloud3tpServiceApi().dayHourPump(tpHour); if (ResponseCode.RESULT_BAD.toStrCode().equals(tpRes.getRescode())) { LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_ERROR , mStrClassName , mStrClassName , String.format("预测泵小时数据" + dateStr + "调用失败 ERROR:{%s} ", tpRes.getResdata())); } } catch (Exception ex) { LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_ERROR , mStrClassName , mStrClassName , String.format("预测泵小时数据" + dateStr + "调用异常 ERROR:{%s} ", ex.getLocalizedMessage())); } } } LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO,mStrClassName, mStrClassName,"调用预测模型泵组优化小时数据结束"+ TimeTool.convertUTC2DateStr(TimeTool.getCurMsUTC(),TimeTool.TIMESTAMP_FORMAT)); }catch(Exception ex){ ex.printStackTrace(); } } //TODO 跑泵组数据插入预测实际值 public static void insertYucePumpReal(String monthNow,int monthDay){ DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO,mStrClassName, mStrClassName,"添加实际值"); try { //先获取配置项 根据配置项来进行逻辑添加 String yearStr = ""; String monthStr = ""; if (!StringUtils.isEmpty(monthNow)) { yearStr = monthNow.split("-")[0]; monthStr = monthNow.split("-")[1]; } LocalDateTime startDate = LocalDateTime.now().withYear(Integer.valueOf(yearStr)) .withMonth(Integer.valueOf(monthStr)).withDayOfMonth(monthDay).withHour(0).withMinute(0).withSecond(0).withNano(0); LocalDateTime endDate = LocalDateTime.now().withMinute(0).withSecond(0).withNano(0); //TODO 查询开始时间开始的原始数据 List> recordAllRes = getWaterTapApi() .getPumpCollectionRecordAllListAll(" WHERE 1=1 " + " AND \"time\"::timestamp BETWEEN '"+startDate.format(formatter)+"' "+"AND '"+endDate.format(formatter)+"'"); for (Map recordAll:recordAllRes){ //TODO 查询对应Day和hour对应的预测数据是否存在, 存在的话就修改实际值状态 List> resList = getWaterTapWaterApi().getTbMHourwaterWatersupply(true, 1, 0, "AND \"PumpID\" = '"+recordAll.get("device_code")+"' AND \"Date\" = '"+LocalDateTime.parse(recordAll.get("time").toString(), formatter).format(DateTimeFormatter.ofPattern("yyyy-MM-dd")) +"' AND \"Hour\" = '"+LocalDateTime.parse(recordAll.get("time").toString(), formatter).format(DateTimeFormatter.ofPattern("HH:mm:ss"))+"'"); if(!CollectionUtils.isEmpty(resList)){ //TODO 说明存在,则修改 Map oldMap = resList.get(0); if(!ObjectUtils.isEmpty(recordAll.get("startup_state"))){ oldMap.put("RealPumpStatus",recordAll.get("startup_state")); }else if (!ObjectUtils.isEmpty(recordAll.get("active_energy"))){ oldMap.put("RealPumpStatus",1); }else{ oldMap.put("RealPumpStatus",0); } oldMap.remove("ID"); int res = getWaterTapApi().insertOrUpdateTbmHourwaterWatersupply(oldMap); if(res<0){ LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_ERROR , mStrClassName , mStrClassName ,"修改泵实际状态数据失败"); } } } LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO,mStrClassName, mStrClassName,"泵数据实际值修改完成"); }catch(Exception ex){ ex.printStackTrace(); } } //TODO 定时任务 定时添加预测数据 废弃 public static void insertYuceDataScheduled(String monthNow){ LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO,mStrClassName, mStrClassName,"添加预测日数据正在进行"+ TimeTool.convertUTC2DateStr(TimeTool.getCurMsUTC(),TimeTool.TIMESTAMP_FORMAT)); try { //先获取配置项 根据配置项来进行逻辑添加 List> configRes = getWaterTapWaterApi().getWaterYuceConfig(false, 0, 0, ""); if(!CollectionUtils.isEmpty(configRes)){ Map config = configRes.get(0); Integer isMonth = Integer.valueOf(config.get("is_month").toString());//是否预测指定月份 0 是 1否(判定是否走自添加逻辑) String month = config.get("month").toString();//指定预测年月 yyyy-mm Double randomCode = Double.valueOf(config.get("random_code").toString());//上下随机石百分比范围 if(isMonth==0){ DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); String yearStr = month.split("-")[0]; String monthStr = month.split("-")[1]; if(!StringUtils.isEmpty(monthNow)){ yearStr = monthNow.split("-")[0]; monthStr = monthNow.split("-")[1]; } LocalDateTime startDate = LocalDateTime.now().withYear(Integer.valueOf(yearStr)) .withMonth(Integer.valueOf(monthStr)).withDayOfMonth(1).withHour(0).withMinute(0).withSecond(0).withNano(0); LocalDateTime endDate = startDate.with(TemporalAdjusters.lastDayOfMonth()); //TODO 总体逻辑: 先查询指定月上一年的每日平均值,再按平均值的上下啊百分比去插入指定的浮动百分比数据 List> configList = getWaterTapApi().getWaterCollectionConfigList(null); List> orgConfig = getWaterTapWaterApi().getOrgConfig(false,0,0,""); if (!CollectionUtils.isEmpty(configList)&&!CollectionUtils.isEmpty(orgConfig)) { //TODO 按照组织机构分组 Map>> groupedData = configList.stream().collect(Collectors.groupingBy(item -> item.get("org_name"))); final CountDownLatch latch = new CountDownLatch(groupedData.keySet().size()); for (Object key:groupedData.keySet()){ try { ThreadTaskMgr.runTask(new TraceRunnable(TraceLogMgr.getTraceId()) { @Override public void function() { //TODO ①计算水厂指定月每日平均值 List> recordAllRes = getWaterTapApi() .getWaterCollectionRecordAllListAll(" WHERE 1=1 " + " AND org_name = '"+key.toString()+"'" + " AND \"time\"::timestamp BETWEEN '"+startDate.format(formatter)+"' "+"AND '"+endDate.format(formatter)+"'"); if(!CollectionUtils.isEmpty(recordAllRes)){ int days = YearMonth.from(startDate).lengthOfMonth();//获取月份天数 Double numAge = 0.0;//日平均值 Double numMonthAll = null;//月总值 for (int i = 1;i<=days;i++){ LocalDateTime dateNow = startDate.withDayOfMonth(i);//当前循环时间 Double numAll = null;//日总值 //TODO 筛选成当前循环时间的集合 List> daysRecord = recordAllRes.stream().filter(item -> LocalDateTime.parse(item.get("time").toString(),formatter).toLocalDate().equals(dateNow.toLocalDate())) .collect(Collectors.toList()); for (Map mapEntity : daysRecord){ //TODO 筛选与当前天一样的数据在计算平均值,数据相加除以24小时 (recordAllRes内容为这天每小时的数据) if(numAll == null){ numAll = 0.0; } numAll += Double.valueOf(mapEntity.get("value").toString()); } if(numMonthAll==null){ numMonthAll = 0.0; } numMonthAll+= numAll==null?0.0:numAll; } if(numMonthAll!=null){ numAge = numMonthAll/days; } //TODO ②正式插入或修改日预测数据表 Optional orgIdOptional = orgConfig.stream() .filter(item -> key.toString().replace("(", "(").replace(")", ")") .equals(item.get("org_name").toString().replace("(", "(").replace(")", ")"))) .map(item -> item.get("org_id").toString()) .findFirst(); String orgId = orgIdOptional.orElse(null); if (!StringUtils.isEmpty(orgId)) { //预测比对时间如果不是今年,则变为今年的时间 for (int i = 1;i<=days;i++) { LocalDateTime dateNow = startDate.withDayOfMonth(i);//当前循环时间 if(dateNow.isAfter(LocalDateTime.now())){ break; } Double numAll = null;//日总值 //TODO 筛选成当前循环时间的集合 List> daysRecord = recordAllRes.stream().filter(item -> LocalDateTime.parse(item.get("time").toString(),formatter).toLocalDate().equals(dateNow.toLocalDate())) .collect(Collectors.toList()); for (Map mapEntity : daysRecord){ //TODO 筛选与当前天一样的数据在计算平均值,数据相加除以24小时 (recordAllRes内容为这天每小时的数据) if(numAll == null){ numAll = 0.0; } numAll += Double.valueOf(mapEntity.get("value").toString()); } //TODO 数据库操作 A 调用对应时间预测接口 B 在修改实际值 DateTimeFormatter formatter2 = DateTimeFormatter.ofPattern("yyyy-MM-dd"); String dateStr = dateNow.withYear(LocalDateTime.now().getYear()).toLocalDate().format(formatter2); // //TODO A // JP3TPDay tpDay = new JP3TPDay(); // tpDay.setOrgId(orgId); // tpDay.setSdate(dateStr); // tpDay.setEndate(dateStr); // try { // ResponseRes tpRes = ServiceMgrProxy.getInstance() // .applyCloud3tpServiceApi().dayDataPredictSupply(tpDay); // if(ResponseCode.RESULT_BAD.toStrCode().equals(tpRes.getRescode())){ // LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_ERROR // , mStrClassName // , mStrClassName // , String.format("预测日数据"+dateStr+"调用失败 ERROR:{%s} ", // tpRes.getResdata())); // break; // } // }catch(Exception ex){ // LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_ERROR // , mStrClassName // , mStrClassName // , String.format("预测日数据"+dateStr+"调用异常 ERROR:{%s} ", // ex.getLocalizedMessage())); // } //TODO B Map recordAllEntity = new LinkedHashMap<>();//需要添加的实体数据,此处要用有序map recordAllEntity.put("Date", dateStr); recordAllEntity.put("Month", dateNow.withYear(LocalDateTime.now().getYear()).getMonth().getValue()); recordAllEntity.put("Week", dateNow.withYear(LocalDateTime.now().getYear()).getDayOfWeek().getValue()); // recordAllEntity.put("ActualWaterWithdrawals", ""); //实际从该时间查询结果中得出(当前年当前日的实际数据) String newStartDate = dateNow.withYear(LocalDateTime.now().getYear()).format(formatter); String newEndDate = dateNow.withYear(LocalDateTime.now().getYear()).minusDays(-1).minusSeconds(1).format(formatter); List> newRecordAllRes = getWaterTapApi() .getWaterCollectionRecordAllListAll(" WHERE 1=1 " + " AND org_name = '"+key.toString()+"'" + " AND \"time\"::timestamp BETWEEN '"+newStartDate +"' "+"AND '"+newEndDate+"'"); String actualWaterSupply = null; if(!CollectionUtils.isEmpty(newRecordAllRes)){ actualWaterSupply = String.valueOf(newRecordAllRes.stream() .mapToDouble(record -> { Object value = record.get("value"); if (value instanceof Number) { return ((Number) value).doubleValue(); } else if (value instanceof String) { try { return Double.parseDouble((String) value); } catch (NumberFormatException e) { // 处理或记录错误,这里简单返回0 return 0; } } return 0; }) .sum()); } recordAllEntity.put("ActualWaterSupply", actualWaterSupply); // recordAllEntity.put("ForecastWaterWithdrawals", ""); //TODO 随机数逻辑 int randomUpOrDown = ThreadLocalRandom.current().nextInt(2);//随机向上或者向下 0表示向下 1表示向上 Double randomWater = randomUpOrDown == 0 ? numAge - (numAge * (randomCode / 100)) : numAge + (numAge * (randomCode / 100)); // recordAllEntity.put("ForecastActualWaterSupply", randomWater); recordAllEntity.put("isAbnormal", 0); recordAllEntity.put("isForecast", 1); recordAllEntity.put("LastModifyTime", LocalDateTime.now().format(formatter)); // 如果找到了org_id,就将其赋值给orgId,否则orgId为null recordAllEntity.put("orgId", orgId); //TODO 添加or修改 Integer insertRes = getWaterTapApi().insertOrUpdateTbmWater(recordAllEntity); if (insertRes < 1) { LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_ERROR , mStrClassName , mStrClassName , String.format("Batch insertYuceDataScheduled ERROR:{%s} ", "新增或修改失败")); } } } } latch.countDown(); } }); }catch(Exception ex){ LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_ERROR , mStrClassName , mStrClassName , String.format("Batch insertYuceDataScheduled ERROR:{%s} ", ex.getLocalizedMessage())); } } try{latch.await();}catch(Exception ex){} } LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO,mStrClassName, mStrClassName,"添加预测日数据结束"+ TimeTool.convertUTC2DateStr(TimeTool.getCurMsUTC(),TimeTool.TIMESTAMP_FORMAT)); }else{ } } }catch(Exception ex){ ex.printStackTrace(); } } //TODO 定时任务 定时添加小时预测数据 转变为之做假泵数据 public static void insertYuceHourDataScheduled(String monthNow){ LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO,mStrClassName, mStrClassName,"添加预测小时数据正在进行"+ TimeTool.convertUTC2DateStr(TimeTool.getCurMsUTC(),TimeTool.TIMESTAMP_FORMAT)); try { //先获取配置项 根据配置项来进行逻辑添加 List> configRes = getWaterTapWaterApi().getWaterYuceConfig(false, 0, 0, ""); if(!CollectionUtils.isEmpty(configRes)){ Map config = configRes.get(0); Integer isMonth = Integer.valueOf(config.get("is_month").toString());//是否预测指定月份 0 是 1否(判定是否走自添加逻辑) String month = config.get("month").toString();//指定预测年月 yyyy-mm Double randomCode = Double.valueOf(config.get("random_code").toString());//上下随机石百分比范围 if(isMonth==0){ DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); String yearStr = month.split("-")[0]; String monthStr = month.split("-")[1]; if(!StringUtils.isEmpty(monthNow)){ yearStr = monthNow.split("-")[0]; monthStr = monthNow.split("-")[1]; } LocalDateTime startDate = LocalDateTime.now().withYear(Integer.valueOf(yearStr)) .withMonth(Integer.valueOf(monthStr)).withDayOfMonth(1).withHour(0).withMinute(0).withSecond(0).withNano(0); LocalDateTime endDate = startDate.with(TemporalAdjusters.lastDayOfMonth()); //TODO 总体逻辑: 先查询指定月上一年的每日平均值,再按平均值的上下啊百分比去插入指定的浮动百分比数据 List> configList = getWaterTapApi().getWaterCollectionConfigList(null); List> orgConfig = getWaterTapWaterApi().getOrgConfig(false,0,0,""); if (!CollectionUtils.isEmpty(configList)&&!CollectionUtils.isEmpty(orgConfig)) { //TODO 按照组织机构分组 Map>> groupedData = configList.stream().collect(Collectors.groupingBy(item -> item.get("org_name"))); final CountDownLatch latch = new CountDownLatch(groupedData.keySet().size()); for (Object key:groupedData.keySet()){ try { ThreadTaskMgr.runTask(new TraceRunnable(TraceLogMgr.getTraceId()) { @Override public void function() { //TODO ①计算水厂指定月每日小时平均值 List> recordAllRes = getWaterTapApi() .getWaterCollectionRecordAllListAll(" WHERE 1=1 " + " AND org_name = '"+key.toString()+"'" + " AND \"time\"::timestamp BETWEEN '"+startDate.format(formatter)+"' "+"AND '"+endDate.format(formatter)+"'"); if(!CollectionUtils.isEmpty(recordAllRes)){ int days = YearMonth.from(startDate).lengthOfMonth();//获取月份天数 for (int i = 1;i<=days;i++){ LocalDateTime dateNow = startDate.withDayOfMonth(i);//当前循环时间 if(dateNow.isAfter(LocalDateTime.now().minusDays(-4))){ break; } Double numAll = null;//日总值 Double numAge = 0.0;//日小时平均值 //TODO 筛选成当前循环时间的集合 List> daysRecord = recordAllRes.stream().filter(item -> LocalDateTime.parse(item.get("time").toString(),formatter).toLocalDate().equals(dateNow.toLocalDate())) .collect(Collectors.toList()); for (Map mapEntity : daysRecord){ //TODO 筛选与当前天一样的数据在计算平均值,数据相加除以24小时 (recordAllRes内容为这天每小时的数据) if(numAll == null){ numAll = 0.0; } numAll += Double.valueOf(mapEntity.get("value").toString()); } if (numAll!=null){ numAge = numAll/24; } //TODO ②正式插入或修改日预测数据表 Optional orgIdOptional = orgConfig.stream() .filter(item -> key.toString().replace("(", "(").replace(")", ")") .equals(item.get("org_name").toString().replace("(", "(").replace(")", ")"))) .map(item -> item.get("org_id").toString()) .findFirst(); String orgId = orgIdOptional.orElse(null); if (!StringUtils.isEmpty(orgId)) { //预测比对时间如果不是今年,则变为今年的时间 //TODO 取泵号 JSONObject pumpItem = (JSONObject)pumpObj.get(orgId); JSONArray pumpArray = ((JSONObject)pumpItem.get("outRoom")).getJSONArray("pumps"); //TODO 一天24小时 for (int j = 0;j<24;j++) { //TODO 数据库操作 A 调用对应时间预测接口 B 在修改实际值 DateTimeFormatter formatter2 = DateTimeFormatter.ofPattern("yyyy-MM-dd"); DateTimeFormatter formatter3 = DateTimeFormatter.ofPattern("HH:mm:ss"); String dateStr = dateNow.withYear(LocalDateTime.now().getYear()).toLocalDate().format(formatter2); // 创建一个LocalTime实例,设置为指定小时,分钟和秒数为0 LocalTime time = LocalTime.of(j, 0, 0); // 创建一个DateTimeFormatter用于格式化时间 String timeStr = time.format(formatter3); // //TODO A // JP3TPHour tpHour = new JP3TPHour(); // tpHour.setOrgId(orgId); // tpHour.setDate(dateStr); // try { // ResponseRes tpRes = ServiceMgrProxy.getInstance() // .applyCloud3tpServiceApi().dayHourPredictSupply(tpHour); // if(ResponseCode.RESULT_BAD.toStrCode().equals(tpRes.getRescode())){ // LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_ERROR // , mStrClassName // , mStrClassName // , String.format("预测小时数据"+dateStr+"调用失败 ERROR:{%s} ", // tpRes.getResdata())); // break; // } // }catch(Exception ex){ // LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_ERROR // , mStrClassName // , mStrClassName // , String.format("预测小时数据"+dateStr+"调用异常 ERROR:{%s} ", // ex.getLocalizedMessage())); // } //TODO B Map recordAllEntity = new LinkedHashMap<>();//需要添加的实体数据,此处要用有序map recordAllEntity.put("Date", dateStr); recordAllEntity.put("Hour", timeStr); // recordAllEntity.put("HourForecastWaterWithdrawals", null); //TODO 随机数逻辑 int randomUpOrDown = ThreadLocalRandom.current().nextInt(2);//随机向上或者向下 0表示向下 1表示向上 Double randomWater = randomUpOrDown == 0 ? numAge - (numAge * (randomCode / 100)) : numAge + (numAge * (randomCode / 100)); // recordAllEntity.put("HourForecastActualWaterSupply", randomWater); // recordAllEntity.put("HourActualWaterWithdrawals", ""); //实际从该时间查询结果中得出 List> newRecordAllRes = getWaterTapApi() .getWaterCollectionRecordAllListAll(" WHERE 1=1 " + " AND org_name = '"+key.toString()+"'" + " AND \"time\" = '"+dateNow.withYear(LocalDateTime.now().getYear()).withHour(j).format(formatter)+"' "); String hourActualWaterSupply = null; if(!CollectionUtils.isEmpty(newRecordAllRes)){ hourActualWaterSupply = newRecordAllRes.get(0).get("value").toString(); } recordAllEntity.put("HourActualWaterSupply",hourActualWaterSupply); recordAllEntity.put("LastModifyTime", LocalDateTime.now().format(formatter)); // 如果找到了org_id,就将其赋值给orgId,否则orgId为null recordAllEntity.put("orgId", orgId); // //TODO 添加or修改 // Integer insertRes = getWaterTapApi().insertOrUpdateTbmHourWater(recordAllEntity); // if (insertRes < 1) { // LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_ERROR // , mStrClassName // , mStrClassName // , String.format("Batch insertYuceDataScheduled ERROR:{%s} ", // "新增或修改失败")); // } //TODO ③ 泵集合数据添加或修改 // 生成[1, pumpArray.size()]范围内的随机数 int randomNum = (int) (Math.random() * (pumpArray.size() - 1)) + 1; List splitRandom = splitValueRandomlyWithZeros(Double.valueOf((hourActualWaterSupply==null ?"0.0":hourActualWaterSupply)),pumpArray.size(),randomNum);//实际值随机数集合 List splitRandomYuce = splitValueRandomlyWithZeros((randomWater==null ?0.0:randomWater),pumpArray.size(),randomNum);//预测值随机数集合 //泵集合 int kIndex = 0; for (Object obj:pumpArray){ JSONObject itemObj = (JSONObject)obj; Map map = new LinkedHashMap<>(); //TODO 泵状态根据值是否为0设置 map.put("Date", dateNow.withYear(LocalDateTime.now().getYear()).toLocalDate() .format(DateTimeFormatter.ofPattern("yyyy-MM-dd"))); // 创建一个LocalTime实例,设置为指定小时,分钟和秒数为0 // 创建一个DateTimeFormatter用于格式化时间 map.put("Hour", time.format(formatter3)); map.put("PumpID",itemObj.get("label")); // 设置1的概率为0.7,0的概率为0.3 ProbabilityAlgorithm algorithm = new ProbabilityAlgorithm(0.7); // if(splitRandom.get(kIndex)==0){ // //TODO 说明泵实际值为0,状态为关 // map.put("PumpStatus",0); // }else{ // map.put("PumpStatus",1); // } // map.put("PumpStatus",algorithm.getNextValue()); // map.put("HourForecastActualWaterSupply",splitRandomYuce.get(kIndex));//预测泵的供水量/ // map.put("PumpWater",splitRandom.get(kIndex));//实际泵的供水量 // if(splitRandom.get(kIndex)==0){ // //TODO 说明泵实际值为0,状态为关 // map.put("RealPumpStatus",0); // }else{ // map.put("RealPumpStatus",1); // } // map.put("RealPumpStatus",algorithm.getNextValue()); map.put("PumpEnergy",splitRandomYuce.get(kIndex)/1000*180); map.put("RealPumpEnergy",splitRandom.get(kIndex)/1000*200); // map.put("LastModifyTime", LocalDateTime.now().format(formatter)); map.put("orgId", orgId); //TODO 添加or修改 暂时注释 Integer insertRes2 = getWaterTapApi().insertOrUpdateTbmHourwaterWatersupply(map); if (insertRes2 < 1) { LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_ERROR , mStrClassName , mStrClassName , String.format("Batch insertOrUpdateTbmHourwaterWatersupply ERROR:{%s} ", "新增或修改失败")); } kIndex++; } } } } } latch.countDown(); } }); }catch(Exception ex){ LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_ERROR , mStrClassName , mStrClassName , String.format("Batch insertYuceDataScheduled ERROR:{%s} ", ex.getLocalizedMessage())); } } try{latch.await();}catch(Exception ex){} } LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO,mStrClassName, mStrClassName,"添加预测小时数据结束"+ TimeTool.convertUTC2DateStr(TimeTool.getCurMsUTC(),TimeTool.TIMESTAMP_FORMAT)); }else{ } } }catch(Exception ex){ ex.printStackTrace(); } } //生成指定份额的随机数,并且带有0值 public static List splitValueRandomlyWithZeros(double totalValue, int parts, int zeroCount) { if (zeroCount >= parts) { throw new IllegalArgumentException("Zero count must be less than the number of parts."); } Random random = new Random(); List points = new ArrayList<>(); int nonZeroParts = parts - zeroCount; // 添加初始点 points.add(0.0); // 生成分割点 for (int i = 0; i < nonZeroParts - 1; i++) { points.add(random.nextDouble() * totalValue); } // 添加终点 points.add(totalValue); // 排序 Collections.sort(points); // 计算每份的大小 List splits = new ArrayList<>(); for (int i = 1; i < points.size(); i++) { splits.add(points.get(i) - points.get(i - 1)); } // 添加0值份额 for (int i = 0; i < zeroCount; i++) { splits.add(0.0); } // 打乱列表,以确保0值分布均匀 Collections.shuffle(splits); return splits; } /** * TODO 水位预测相关 */ //TODO 小时取水量预测接口 /** * 传入水厂id及日期,返回指定日期内的小时取水量预测数据和实际小时取水量数据 */ public static ResponseRes selectTbHourLevelList(JPTbLevelHourWater jpTbMHourWater){ ResponseRes responseRes = new ResponseRes(); List> list = new ArrayList<>(); Map map = new HashMap<>(); map.put("id",null); map.put("date",null); map.put("hour",null); map.put("hour_forecast_actual_level",null); map.put("hour_actual_water_level",null); map.put("last_modify_time",null); map.put("device_code",null); map.put("site_id",null); map.put("zone_id",null); list.add(map); responseRes.setResdata(list); responseRes.setRescode(ResponseCode.RESULT_NORMAL.toStrCode()); responseRes.setResmsg(ResponseCode.RESULT_NORMAL.toStrMsg()); try { // List> resList = getWaterTapWaterApi().getTbLevelHourwater(jpTbMHourWater.getIsPage(), jpTbMHourWater.getLimit(), jpTbMHourWater.getOffset(), jpTbMHourWater.getForDateStr()); if(!CollectionUtils.isEmpty(resList)){ responseRes.setRescode(ResponseCode.RESULT_NORMAL.toStrCode()); responseRes.setResmsg(ResponseCode.RESULT_NORMAL.toStrMsg()); responseRes.setResdata(resList); } return responseRes; }catch(Exception ex){ responseRes.setResdata(null); responseRes.setResmsg(ResponseCode.RESULT_BAD.toStrMsg()); responseRes.setRescode(ResponseCode.RESULT_BAD.toStrCode()); return responseRes; } } //TODO 重新计算原始小时数据的用电量 //TODO 逻辑:有小时读数的 按小时读数去算, 没有的话就按额定功率*1h去作为用电量 public static void initPumpPowerZero(){ DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); //TODO 首先查询出所有的设备 LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO,mStrClassName, mStrClassName,"计算原始小时数据的用电量...."); List> configList = getWaterTapApi().getWaterPumpCollectionConfigList(""); List> energyList = getWaterTapApi().getWatertPumpEnergy(""); if (!CollectionUtils.isEmpty(configList) && !CollectionUtils.isEmpty(energyList)) { // 按照设备分组 Map>> groupedData = configList.stream() .collect(Collectors.groupingBy(item -> item.get("device_code"))); final CountDownLatch latch = new CountDownLatch(groupedData.keySet().size()); ExecutorService executor = Executors.newFixedThreadPool(groupedData.keySet().size()); // 使用线程池 for (Object config : groupedData.keySet()) { try { List> recordAll = getWaterTapApi().getWaterPumpRecordAllListAll( "WHERE device_code ='" + config + "' " + " AND \"time\"::timestamp BETWEEN '" + LocalDateTime.now().minusDays(2).withHour(0).withMinute(0).withSecond(0).withNano(0).format(formatter) + "' " + "AND '" + LocalDateTime.now().format(formatter) + "'" + " ORDER BY time ASC "); if (CollectionUtils.isEmpty(recordAll)) { continue; // 如果设备没有数据,跳过 } // 遍历 recordAll 中的每条记录 for (int i = 1; i < recordAll.size(); i++) { Map currentRecord = recordAll.get(i); Map previousRecord = recordAll.get(i - 1); Double currentEnergy = (Double) currentRecord.get("active_energy"); Double previousEnergy = (Double) previousRecord.get("active_energy"); double powerConsumption = 0.0; if (currentEnergy != null && previousEnergy != null) { // 情况1:累计电量读数都非空 powerConsumption = currentEnergy - previousEnergy; } else { // 情况2:累计电量读数有一个为空 String deviceCode = (String) currentRecord.get("device_code"); Optional> targetMap = energyList.stream() .filter(map -> deviceCode.equals(map.get("PumpID"))) // 过滤条件 .findFirst(); if (targetMap.isPresent()) { Map resultMap = targetMap.get(); Object ratedPower = resultMap.get(deviceCode); if (ratedPower != null) { powerConsumption = Double.valueOf(ratedPower.toString()) * 1; // 用电量 = 额定功率 × 1 } else { powerConsumption = 0.0; // 额定功率未找到,用电量为 0 } } else { powerConsumption = 500 + (Math.random() - 0.5) * 200; // 额定功率未找到,用电量为 0 } } // 更新当前记录的用电量字段 currentRecord.put("power_cons", powerConsumption); int res = getWaterTapApi().insertOrUpdateWaterPumpRecordAll(currentRecord); if (res <= 0) { LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO,mStrClassName, mStrClassName,"修改小时用电量失败"); } } } catch (Exception ex) { } } LogPrintMgr.getInstance().printLogMsg(LogLevelFlag.LOG_INFO,mStrClassName, mStrClassName,"修改小时用电量完成"); } } }