gunshi-project-ss/src/main/java/com/gunshi/project/ss/timetask/WarningRuleTask.java

425 lines
16 KiB
Java
Raw Normal View History

2025-12-29 17:13:09 +08:00
package com.gunshi.project.ss.timetask;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
2025-12-29 17:13:09 +08:00
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<WarningRule> 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<WarningCondition> 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.getRuleName());
// 生成规则信息
String ruleInfo = generateRuleInfo(conditions);
WarningRuleInfo warningRuleInfo = new WarningRuleInfo();
2025-11-27 17:59:12 +08:00
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);
2025-11-21 10:53:44 +08:00
warningRuleInfo.setWarningLevel(warningRule.getWarningLevel());
2025-11-27 17:59:12 +08:00
warningRuleInfo.setStatus(warningRule.getStatus());
warningRuleInfoService.save(warningRuleInfo);
}
}
}
/**
*
*/
private String generateRuleInfo(List<WarningCondition> conditions) {
List<String> 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);
}
2025-11-26 18:00:57 +08:00
@Autowired
private StStbprpBService stStbprpBService;
/**
* -
*/
private String generateSingleConditionInfo(WarningCondition condition) {
String indicatorType = condition.getIndicatorType();
String stcd = condition.getStcd();
2025-11-26 18:00:57 +08:00
String stnm="";
List<StStbprpB> 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",
2025-11-26 18:00:57 +08:00
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",
2025-11-26 18:00:57 +08:00
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",
2025-11-26 18:00:57 +08:00
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();
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<WarningCondition> 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<String> riverStcd = riverWaterService.getRiverStcd();
if(riverStcd.contains(stcd)){
LambdaQueryWrapper<StRiverRReal> 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<StRsvrRReal> 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<ForecastResultVo> 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<AttResBaseVo> 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<HisWaterData> hisWaterDataList = hisWaterDataService.lambdaQuery()
.eq(HisWaterData::getYear, year)
.eq(HisWaterData::getMonth, month)
2025-11-25 13:28:32 +08:00
.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<ForeRainVo> 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;
}
}