package com.gunshi.project.ss.timetask; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.gunshi.project.ss.common.model.StRiverRReal; import com.gunshi.project.ss.common.model.StRsvrRReal; import com.gunshi.project.ss.common.model.StStbprpB; import com.gunshi.project.ss.common.util.LocalDateTimeConverter; import com.gunshi.project.ss.entity.so.WeatherSo; import com.gunshi.project.ss.entity.vo.*; import com.gunshi.project.ss.model.*; import com.gunshi.project.ss.service.*; import jakarta.annotation.Resource; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Profile; import org.springframework.scheduling.annotation.EnableScheduling; import org.springframework.stereotype.Component; import java.math.BigDecimal; import java.math.RoundingMode; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.ZoneId; import java.time.format.DateTimeFormatter; import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors; @EnableScheduling//开启定时任务 @Component @Slf4j @Profile({"prod","dev","local"}) public class WarningRuleTask { @Autowired private WarningRuleService warningRuleService; @Autowired private WarningRuleInfoService warningRuleInfoService; //河道水位 @Autowired private RiverWaterService riverWaterService; @Autowired private StRiverRRealService stRiverRRealService; //水库水位 @Autowired private ReservoirWaterService reservoirWaterService; @Autowired private StRsvrRRealService stRsvrRRealService; @Autowired private ForecastResultsService forecastResultsService; @Resource private ForecastService forecastService; @Autowired private RainBasinDivisionService rainBasinDivisionService; // @Scheduled(fixedDelay = 60 * 60 * 1000) // 75分钟,单位毫秒 // @Async public void warningRuleExecute(){ //获取配置的预警规则 List warningRules = warningRuleService.listData(); //过滤出启动了的预警规则 warningRules = warningRules.stream().filter(o ->{ return o.getStatus() != null && o.getStatus() == 1; }).collect(Collectors.toList()); for (WarningRule warningRule : warningRules) { //获取预警类型 String warningType = warningRule.getWarningType(); //获取预警的规则细节 List conditions = warningRule.getConditions(); if (conditions == null || conditions.isEmpty()) { continue; } // 为每个条件计算实际值并设置是否满足 for (WarningCondition condition : conditions) { BigDecimal actualValue = calculateActualValue(condition, warningType); condition.setIsEnjoy(compareValue(actualValue, condition)); } // 根据条件关系判断整个规则是否满足 boolean isRuleSatisfied = evaluateConditions(conditions); // 这里可以根据 isRuleSatisfied 进行后续处理,比如触发预警等 if (isRuleSatisfied) { log.info("预警规则 {} 满足条件,触发预警", warningRule.getId()); // 生成规则信息 String ruleInfo = generateRuleInfo(conditions); WarningRuleInfo warningRuleInfo = new WarningRuleInfo(); // warningRuleInfo.setCreateName(warningRule.getCreateName()); warningRuleInfo.setRuleId(warningRule.getId()); // warningRuleInfo.setRuleName(warningRule.getRuleName()); warningRuleInfo.setConditions(conditions); warningRuleInfo.setCreateTime(LocalDateTime.now()); warningRuleInfo.setRuleInfo(ruleInfo); warningRuleInfo.setWarningType(warningType); warningRuleInfo.setWarningLevel(warningRule.getWarningLevel()); warningRuleInfo.setStatus(warningRule.getStatus()); warningRuleInfoService.save(warningRuleInfo); } } } /** * 生成规则信息描述 */ private String generateRuleInfo(List conditions) { List conditionInfos = new ArrayList<>(); for (WarningCondition condition : conditions) { if (condition.getIsEnjoy()) { // 只记录满足条件的报警信息 String conditionInfo = generateSingleConditionInfo(condition); if (conditionInfo != null && !conditionInfo.isEmpty()) { conditionInfos.add(conditionInfo); } } } return String.join(";", conditionInfos); } @Autowired private StStbprpBService stStbprpBService; /** * 生成单个条件的描述信息 - 修改格式 */ private String generateSingleConditionInfo(WarningCondition condition) { // String indicatorType = condition.getIndicatorType(); // String stcd = condition.getStcd(); String indicatorType = null; String stcd = null; String stnm=""; List stStbprpBS = stStbprpBService.lambdaQuery().eq(StStbprpB::getStcd, stcd).last("limit 1").list(); if(stStbprpBS != null && !stStbprpBS.isEmpty()){ stnm = stStbprpBS.get(0).getStnm(); } BigDecimal thresholdValue = condition.getThresholdValue(); Integer durationHours = condition.getDurationHours(); switch (indicatorType) { case "REAL_WATER_LEVEL": BigDecimal currentWaterLevel = getRzByStcd(stcd); return String.format("%s测点监测水位%sm %s %sm", stnm, currentWaterLevel, condition.getOperator(), thresholdValue); case "PEAK_FLOW": return String.format("未来%dh预报洪峰流量 %s %s m³/s", durationHours != null ? durationHours : 24, condition.getOperator(), thresholdValue); case "RAINFALL": BigDecimal currentRainfall = getRealRainFall(stcd, durationHours); return String.format("%s测点过去%dh降雨量%smm %s %smm", stnm, durationHours != null ? durationHours : 24, currentRainfall, condition.getOperator(), thresholdValue); // case "WATER_STORAGE": // BigDecimal currentStoragePercent = getWaterStorage(condition.getYear()); // return String.format("蓄水量 %s 同期%s%%", // condition.getOperator(), thresholdValue); case "FORECAST_RAINFALL": return String.format("%s测点未来%dh降雨量 %s %smm", stnm, durationHours != null ? durationHours : 24, condition.getOperator(), thresholdValue); default: return String.format("未知指标类型%s %s %s", stcd, condition.getOperator(), thresholdValue); } } /** * 计算条件的实际值 */ private BigDecimal calculateActualValue(WarningCondition condition, String warningType) { // String indicatorType = condition.getIndicatorType(); // String stcd = condition.getStcd(); String indicatorType = null; String stcd = null; Integer durationHours = condition.getDurationHours(); switch (indicatorType) { case "REAL_WATER_LEVEL": return getRzByStcd(stcd); case "PEAK_FLOW": return getFloowMaxQ(durationHours); case "RAINFALL": return getRealRainFall(stcd, durationHours); case "WATER_STORAGE": // return getWaterStorage(condition.getYear()); case "FORECAST_RAINFALL": return getForecastRainFall(stcd, durationHours); default: return BigDecimal.ZERO; } } /** * 比较实际值和阈值 */ private boolean compareValue(BigDecimal actualValue, WarningCondition condition) { if (actualValue == null || condition.getThresholdValue() == null) { return false; } String operator = condition.getOperator(); BigDecimal threshold = condition.getThresholdValue(); switch (operator) { case ">": return actualValue.compareTo(threshold) > 0; case ">=": return actualValue.compareTo(threshold) >= 0; case "<": return actualValue.compareTo(threshold) < 0; case "<=": return actualValue.compareTo(threshold) <= 0; default: return false; } } /** * 评估条件组合是否满足 * 处理 AND/OR 逻辑关系 */ private boolean evaluateConditions(List conditions) { if (conditions.isEmpty()) { return false; } boolean result = false; boolean currentGroup = conditions.get(0).getIsEnjoy(); for (int i = 0; i < conditions.size() - 1; i++) { WarningCondition current = conditions.get(i); WarningCondition next = conditions.get(i + 1); String relation = current.getRelationType(); if ("AND".equals(relation)) { // AND 关系:当前组与下一个条件进行与运算 currentGroup = currentGroup && next.getIsEnjoy(); } else if ("OR".equals(relation)) { // OR 关系:当前结果与当前组进行或运算,然后开始新的组 result = result || currentGroup; currentGroup = next.getIsEnjoy(); } } // 处理最后一个条件 result = result || currentGroup; return result; } //获取实时水位 private BigDecimal getRzByStcd(String stcd){ //获取河道水位的站点编码 List riverStcd = riverWaterService.getRiverStcd(); if(riverStcd.contains(stcd)){ LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); queryWrapper.eq(StRiverRReal::getStcd,stcd); StRiverRReal stRiverRReal = stRiverRRealService.getBaseMapper().selectOne(queryWrapper); if(stRiverRReal != null){ return stRiverRReal.getZ(); } return BigDecimal.ZERO; }else{ LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); queryWrapper.eq(StRsvrRReal::getStcd,stcd); StRsvrRReal stRsvrRReal = stRsvrRRealService.getBaseMapper().selectOne(queryWrapper); if(stRsvrRReal != null){ return stRsvrRReal.getRz(); } return BigDecimal.ZERO; } } //获取预报洪峰流量 private BigDecimal getFloowMaxQ(Integer durationHours){ ForecastTask forecastTask = new ForecastTask(); // 设置当前时间整点 LocalDateTime now = LocalDateTime.now(); LocalDateTime nowHour = now.withMinute(0).withSecond(0).withNano(0); forecastTask.setNowTime(LocalDateTimeConverter.toDate(nowHour)); // 设置开始时间(当前时间减去一天) LocalDateTime startTime = nowHour.minusDays(1); forecastTask.setStartTime(LocalDateTimeConverter.toDate(startTime)); // 设置结束时间(当前时间加上durationHours) LocalDateTime endTime = nowHour.plusHours(durationHours); forecastTask.setEndTime(LocalDateTimeConverter.toDate(endTime)); forecastTask.setForecastWarm(1); forecastTask.setForecastPeriod(durationHours); // 设置预报时长 List humanForecastResult = forecastResultsService.getHumanForecastResult(forecastTask); //过滤出预报的数据 humanForecastResult = humanForecastResult.stream().filter(o ->{ return o.getIspreDrp().equals("1") && o.getYcRkQValue() != null; }).collect(Collectors.toList()); BigDecimal totalQ = BigDecimal.ZERO; for (ForecastResultVo forecastResultVo : humanForecastResult) { totalQ = totalQ.add(forecastResultVo.getYcRkQValue()); } return totalQ; } //获取降雨量的值 public BigDecimal getRealRainFall(String stcd,Integer durationHours){ StPptnDetailsVo stPptnDetailsVo = rainBasinDivisionService.queryStPptnDetailsByStcd(stcd); if (stPptnDetailsVo == null) { return BigDecimal.ZERO; // 或返回 BigDecimal.ZERO,根据业务需求调整 } BigDecimal result = switch (durationHours) { case 1 -> stPptnDetailsVo.getH1(); case 3 -> stPptnDetailsVo.getH3(); case 6 -> stPptnDetailsVo.getH6(); case 12 -> stPptnDetailsVo.getH12(); case 24 -> stPptnDetailsVo.getH24(); case 48 -> stPptnDetailsVo.getH48(); // 3. 未匹配的时长(如2、5等),返回null或默认值 default -> BigDecimal.ZERO; // 或 throw new IllegalArgumentException("不支持的时长:" + durationHours); }; return result == null?BigDecimal.ZERO:result; } @Autowired private HisWaterDataService hisWaterDataService; //获取蓄水量 - 修改后的逻辑 private BigDecimal getWaterStorage(String year){ List list = reservoirWaterService.list(); if (list == null || list.isEmpty()) { return BigDecimal.ZERO; } AttResBaseVo reservoir = list.get(0); BigDecimal nowCap = reservoir.getNowCap() == null ? BigDecimal.ZERO : reservoir.getNowCap(); BigDecimal deadCap = reservoir.getDeadCap() == null ? BigDecimal.ZERO : reservoir.getDeadCap(); BigDecimal availableWater = nowCap.subtract(deadCap); // 当前可用水量 // 获取当前月份 int currentMonth = LocalDateTime.now().getMonthValue(); String month = String.valueOf(currentMonth); // 获取某年同月的蓄水量作为基准值 List hisWaterDataList = hisWaterDataService.lambdaQuery() .eq(HisWaterData::getYear, year) .eq(HisWaterData::getMonth, month) .eq(HisWaterData::getType,2) .list(); BigDecimal baseWaterStorage = BigDecimal.ZERO; if (!hisWaterDataList.isEmpty()) { HisWaterData hisWaterData = hisWaterDataList.get(0); baseWaterStorage = hisWaterData.getAvgWater() == null ? BigDecimal.ZERO : hisWaterData.getAvgWater(); } // 如果基准值为0,避免除零错误,返回0 if (baseWaterStorage.compareTo(BigDecimal.ZERO) == 0) { return BigDecimal.ZERO; } // 计算当前可用水量占同期蓄水量的百分比 BigDecimal percentage = availableWater.divide(baseWaterStorage, 4, RoundingMode.HALF_UP) .multiply(new BigDecimal("100")); return percentage; } //获取预测降雨量 private BigDecimal getForecastRainFall(String stcd,Integer durationHours) { DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("yyyyMMdd"); // 获取当前日期(默认系统时区,可指定时区如:ZoneId.of("UTC")) LocalDate today = LocalDate.now(ZoneId.systemDefault()); String todayDateStr = today.format(dateFormatter); // 结果示例:20251120 String tm = todayDateStr + "08"; // 拼接固定小时,最终格式:2025112008 WeatherSo weatherSo = new WeatherSo(); weatherSo.setTm(tm); List fore = forecastService.fore(weatherSo); for (ForeRainVo foreRainVo : fore) { if (stcd.equals(foreRainVo.getStcd())) { BigDecimal forecastRain = BigDecimal.ZERO; switch (durationHours) { case 1: forecastRain = foreRainVo.getH1(); return forecastRain; case 3: forecastRain = foreRainVo.getH3(); return forecastRain; case 6: forecastRain = foreRainVo.getH6(); return forecastRain; case 12: forecastRain = foreRainVo.getH12(); return forecastRain; case 24: forecastRain = new BigDecimal(foreRainVo.getH24()); return forecastRain; default: return BigDecimal.ZERO; } } } return BigDecimal.ZERO; } }