gunshi-project-ss/src/main/java/com/gunshi/project/ss/service/GateValveRealService.java

413 lines
18 KiB
Java
Raw Normal View History

2025-12-29 17:13:09 +08:00
package com.gunshi.project.ss.service;
2024-07-08 17:47:02 +08:00
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
2024-07-08 17:47:02 +08:00
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
2025-12-29 17:13:09 +08:00
import com.gunshi.project.ss.entity.so.GateHisPageSo;
import com.gunshi.project.ss.entity.vo.AttResBaseVo;
import com.gunshi.project.ss.entity.vo.GateStautsVo;
import com.gunshi.project.ss.entity.vo.GateValveOplogVo;
import com.gunshi.project.ss.mapper.GateValveRealMapper;
import com.gunshi.project.ss.mapper.StWaterRRealMapper;
import com.gunshi.project.ss.mapper.TyYearRainfallMapper;
import com.gunshi.project.ss.model.*;
import com.gunshi.project.ss.util.DataHandleUtil;
import com.gunshi.project.ss.util.DateUtil;
import com.gunshi.project.ss.util.ExcelUtil;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletResponse;
2024-07-08 17:47:02 +08:00
import lombok.extern.slf4j.Slf4j;
2025-03-28 17:19:17 +08:00
import org.apache.commons.lang3.StringUtils;
2025-12-02 15:18:17 +08:00
import org.springframework.beans.factory.annotation.Autowired;
2024-07-08 17:47:02 +08:00
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.util.*;
2025-12-02 15:18:17 +08:00
import java.util.stream.Collectors;
2024-07-08 17:47:02 +08:00
/**
* :
* author: xusan
* date: 2024-07-08 17:30:37
*/
@Service
@Slf4j
@Transactional(rollbackFor = Exception.class)
public class GateValveRealService extends ServiceImpl<GateValveRealMapper, GateValveReal>
{
@Resource
2025-12-29 17:13:09 +08:00
private com.gunshi.project.ss.model.GateValveKeyAutoDao gateValveKeyAutoDao;
@Resource
2025-12-29 17:13:09 +08:00
private com.gunshi.project.ss.model.GateValveOplogAutoDao gateValveOplogAutoDao;
@Resource
private ReservoirWaterService reservoirWaterService;
@Resource
private StWaterRRealMapper stWaterRRealMapper;
@Resource
private TyYearRainfallMapper tyYearRainfallMapper;
2024-07-08 17:47:02 +08:00
public List<GateStautsVo> gateStatusList() {
List<GateStautsVo> list = baseMapper.gateStatusList();
for(GateStautsVo vo : list){
if(vo.getTm() != null && DateUtil.hoursBetweenDate(vo.getTm(), new Date()) > 2){
vo.setFlag(1);
}
}
return list;
}
public BigDecimal realQ(String valveCode) {
return baseMapper.realQ(valveCode);
}
public String control(GateValveKey gateValveKey) {
//先判断密码是否正确
String valveCode = gateValveKey.getValveCode();
String key = gateValveKey.getKey();
GateValveKey valveKey = gateValveKeyAutoDao.getById(valveCode);
if(valveKey == null || !key.equals(valveKey.getKey())){
throw new IllegalArgumentException("密码不正确");
}
//生成闸阀操作日志
GateValveOplog oplog = new GateValveOplog();
oplog.setId(IdWorker.getId());
oplog.setStatus(gateValveKey.getStatus());
oplog.setOpContent("设置闸阀开度为"+gateValveKey.getStatus());
oplog.setValveCode(valveCode);
oplog.setTm(new Date());
oplog.setOpUserId(1L);
oplog.setOpUserName("胡兵");
GateValveReal valveReal = this.getOne(new QueryWrapper<GateValveReal>().eq("valve_code", valveCode));
oplog.setBeforeStatus(valveReal == null ? "-" : valveReal.getStatus());
gateValveOplogAutoDao.save(oplog);
2024-07-24 09:11:20 +08:00
//todo 给闸阀下发调节指令
// GateValveR gateValveR = new GateValveR();
// BeanUtils.copyProperties(gateValveKey,gateValveR);
// gateValveR.setTm(new Date());
// gateValveRMapper.insert(gateValveR);
//
// GateValveReal real = new GateValveReal();
// BeanUtils.copyProperties(gateValveKey,real);
// real.setTm(new Date());
// this.remove(new QueryWrapper<GateValveReal>().eq("valve_code",valveCode));
// this.save(real);
return "调节闸阀成功";
}
public Page<GateValveOplogVo> logPage(GateHisPageSo so) {
return baseMapper.logPage(so.getPageSo().toPage(),so);
}
2025-03-28 17:19:17 +08:00
public GateValveOplog loginfo(String code) {
if(StringUtils.isBlank(code)){
return null;
}
LambdaQueryWrapper<GateValveOplog> qw = new LambdaQueryWrapper();
qw.eq(GateValveOplog::getValveCode,code);
qw.orderByDesc(GateValveOplog::getTm).last("LIMIT 1");
List<GateValveOplog> list = gateValveOplogAutoDao.list(qw);
2025-03-28 17:19:17 +08:00
return list.isEmpty() ? null : list.get(0);
}
public void logExport(GateHisPageSo so, HttpServletResponse response) {
List<GateValveOplogVo> logList = baseMapper.logList(so);
ExcelUtil.exportExcel(logList,"闸阀操作日志",GateValveOplogVo.class,response,"闸阀操作日志");
}
2025-12-02 15:18:17 +08:00
@Autowired
private StEvpoService stEvpoService;
@Autowired
private StFlowRService stFlowRService;
2025-12-15 17:07:01 +08:00
@Autowired
private StWaterRRealService stWaterRRealService;
public Map<BigDecimal, String> supplyTime(Integer year, Integer month) {
2025-12-02 15:18:17 +08:00
Map<BigDecimal, String> result = new HashMap<>();
// 获取所有月份的日蒸发量数据
List<StEvpo> allEvaporationData = stEvpoService.lambdaQuery().list();
Map<Integer, BigDecimal> evaporationMap = allEvaporationData.stream()
.collect(Collectors.toMap(StEvpo::getMonth, StEvpo::getEvaporation));
// 获取水库基础数据
List<AttResBaseVo> reservoirList = reservoirWaterService.list();
if (CollectionUtils.isEmpty(reservoirList)) {
return result;
}
2025-12-02 15:18:17 +08:00
AttResBaseVo reservoir = reservoirList.get(0);
// 初始可供水量 = 实时库容 - 死库容 (万m³)
BigDecimal nowCap = reservoir.getNowCap() == null ? BigDecimal.ZERO : reservoir.getNowCap();
BigDecimal deadCap = reservoir.getDeadCap() == null ? BigDecimal.ZERO : reservoir.getDeadCap();
BigDecimal availableWater = nowCap.subtract(deadCap);
2025-12-18 09:13:47 +08:00
Date tm = reservoir.getTm();
Calendar now = Calendar.getInstance();
now.set(Calendar.MINUTE, 0);
now.set(Calendar.SECOND, 0);
now.set(Calendar.MILLISECOND, 0);
Date currentHour = now.getTime();
if(tm.before(currentHour)){
2025-12-19 10:55:47 +08:00
result.put(BigDecimal.ZERO,"当前时间无最新水位数据");
2025-12-18 09:13:47 +08:00
return result;
}
2025-12-02 15:18:17 +08:00
// 如果初始可供水量就为0或负数直接返回
if (availableWater.compareTo(BigDecimal.ZERO) <= 0) {
result.put(BigDecimal.ZERO, "当前无可供水量");
return result;
}
2025-12-02 15:18:17 +08:00
// 获取当前流量数据
2025-12-15 17:07:01 +08:00
List<StWaterRReal> waterFlowList = stWaterRRealService.listNewData();
2025-12-02 15:18:17 +08:00
BigDecimal totalFlow = waterFlowList.stream()
2025-12-15 17:07:01 +08:00
.map(StWaterRReal::getQ)
2025-12-02 15:18:17 +08:00
.reduce(BigDecimal.ZERO, BigDecimal::add);
// 计算日供水量 (m³/d) 并转换为万m³/d
BigDecimal dailySupply = totalFlow.multiply(new BigDecimal(3600 * 24));
BigDecimal dailySupplyInTenThousand = dailySupply.divide(new BigDecimal(10000), 10, RoundingMode.HALF_UP);
// 从当前时间开始计算
Calendar calendar = Calendar.getInstance();
int currentYear = calendar.get(Calendar.YEAR);
int currentMonth = calendar.get(Calendar.MONTH) + 1;
// 计算当前月份剩余天数
calendar.set(Calendar.DAY_OF_MONTH, calendar.getActualMaximum(Calendar.DAY_OF_MONTH));
int daysInCurrentMonth = calendar.get(Calendar.DAY_OF_MONTH);
int currentDay = Calendar.getInstance().get(Calendar.DAY_OF_MONTH);
int remainingDaysInMonth = daysInCurrentMonth - currentDay + 1;
BigDecimal totalSupplyDays = BigDecimal.ZERO;
BigDecimal remainingWater = availableWater;
// 判断是否计算预测水量
boolean calculatePredictWater = (year != null && month != null);
// 逐月计算,直到可供水量耗尽
int calcYear = currentYear;
int calcMonth = currentMonth;
boolean waterExhausted = false;
while (remainingWater.compareTo(BigDecimal.ZERO) > 0 && !waterExhausted) {
// 获取当前计算月份的蒸发量
String monthKey = String.valueOf(calcMonth);
BigDecimal monthlyEvaporation = evaporationMap.getOrDefault(Integer.valueOf(monthKey), BigDecimal.ZERO);
// 计算当前月份的预测来水量(只有当传入年份和月份不为空,且当前月份在预测范围内时才计算)
BigDecimal monthlyPredictWater = BigDecimal.ZERO;
if (calculatePredictWater && isMonthInPredictRange(calcMonth, currentMonth, month)) {
monthlyPredictWater = calcMonthlyPredictV(year, calcMonth, reservoir.getWatShedArea());
}
// 当前月份总可用水量 = 剩余水量 + 预测来水量
BigDecimal monthlyTotalWater = remainingWater.add(monthlyPredictWater);
// 当前月份日消耗量 = 日供水量 + 日蒸发量 (万m³/d)
BigDecimal dailyConsumption = dailySupplyInTenThousand.add(monthlyEvaporation);
if (dailyConsumption.compareTo(BigDecimal.ZERO) <= 0) {
// 如果日消耗量为0或负数说明可以无限供水
totalSupplyDays = new BigDecimal("9999"); // 表示无限期
break;
}
// 计算当前月份可供水天数
int daysInMonth = getDaysInMonth(calcYear, calcMonth);
int daysToCalculate = (calcYear == currentYear && calcMonth == currentMonth) ?
remainingDaysInMonth : daysInMonth;
// 当前月份最大可供水量 = 日消耗量 * 当月剩余天数
BigDecimal monthlyMaxConsumption = dailyConsumption.multiply(new BigDecimal(daysToCalculate));
if (monthlyTotalWater.compareTo(monthlyMaxConsumption) >= 0) {
// 当前月份水量充足,可以支撑整个月
totalSupplyDays = totalSupplyDays.add(new BigDecimal(daysToCalculate));
remainingWater = monthlyTotalWater.subtract(monthlyMaxConsumption);
// 移动到下个月
calcMonth++;
if (calcMonth > 12) {
calcMonth = 1;
calcYear++;
}
} else {
// 当前月份水量不足,计算具体天数
BigDecimal remainingDays = monthlyTotalWater.divide(dailyConsumption, 1, RoundingMode.HALF_UP);
totalSupplyDays = totalSupplyDays.add(remainingDays);
waterExhausted = true;
}
}
// 计算结束日期
long totalDays = DataHandleUtil.BigDecimalIntegerPart(totalSupplyDays);
String endDate = DateUtil.getPlusDate(new Date(), totalDays);
result.put(totalSupplyDays, endDate);
return result;
}
2025-12-02 15:18:17 +08:00
/**
*
*
*/
private boolean isMonthInPredictRange(int calcMonth, int currentMonth, int endMonth) {
if (endMonth >= currentMonth) {
// 不跨年情况:当前月份 <= 计算月份 <= 截至月份
return calcMonth >= currentMonth && calcMonth <= endMonth;
} else {
// 跨年情况:计算月份 >= 当前月份 或者 计算月份 <= 截至月份
return calcMonth >= currentMonth || calcMonth <= endMonth;
}
}
/**
*
*/
private int getDaysInMonth(int year, int month) {
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.YEAR, year);
calendar.set(Calendar.MONTH, month - 1);
return calendar.getActualMaximum(Calendar.DAY_OF_MONTH);
}
// public Map<BigDecimal, String> supplyTime(Integer year, Integer month) {
// StEvpo stEvpo = stEvpoService.lambdaQuery().eq(StEvpo::getMonth, month.toString()).list().get(0);
// BigDecimal evpo = BigDecimal.ZERO; //蒸发量 (万m³
// if(stEvpo != null){
// evpo = stEvpo.getEvaporation();
// }
// Map<BigDecimal, String> map = new HashMap<>();
// /**
// * 可供水量= 实时库容 - 死库容
// * 小时水量= (输水管流量 + 放水管流量)*3600 ->改为 (输水管流量 + 放水管流量)*3600 + 蒸发量
// * 可供水小时数 = 可供水量 * 10000/ 小时水量 ->改为 (可供水量 + 预测水量如果有) * 10000 / 小时水量
// * 可供水天数 = 可供水小时数换算为天数
// */
// List<AttResBaseVo> list = reservoirWaterService.list();
// if(CollectionUtils.isEmpty(list)){
// return map;
// }
// AttResBaseVo attResBaseVo = list.get(0);
// BigDecimal nowCap = attResBaseVo.getNowCap() == null ? new BigDecimal(0) : attResBaseVo.getNowCap();
// BigDecimal deadCap = attResBaseVo.getDeadCap() == null ? new BigDecimal(0) : attResBaseVo.getDeadCap();
//
// BigDecimal supplyV = nowCap.subtract(deadCap);
// if(year != null){
// //计算预测来水量
// BigDecimal predictV = calcPredictV(year,month,attResBaseVo.getWatShedArea());
// supplyV = supplyV.add(predictV);
// }
// List<StWaterRReal> water = stWaterRRealMapper.listRelated();
// //小时水量
// BigDecimal hourQ = water.stream().map(StWaterRReal::getQ).reduce(BigDecimal.ZERO, BigDecimal::add).multiply(new BigDecimal(3600));
// BigDecimal day = supplyV.multiply(new BigDecimal(10000)).divide(hourQ.multiply(new BigDecimal(24)),1, RoundingMode.HALF_UP);
// long l = DataHandleUtil.BigDecimalIntegerPart(day);
// String date = DateUtil.getPlusDate(new Date(), l);
// map.put(day,date);
// return map;
// }
/**
*
* 10.14-10.304011.01-11.3060
*/
private BigDecimal calcMonthlyPredictV(Integer year, Integer month, BigDecimal watShedArea) {
LocalDate now = LocalDate.now();
Integer nowMonth = now.getMonthValue();
// 查询指定月份的降雨量数据
LambdaQueryWrapper<TyYearRainfall> queryWrapper = Wrappers.lambdaQuery();
queryWrapper.eq(TyYearRainfall::getYear, year)
.eq(TyYearRainfall::getMonth, month)
.eq(TyYearRainfall::getType, 2);
TyYearRainfall rainfall = tyYearRainfallMapper.selectOne(queryWrapper);
if (rainfall == null || rainfall.getDrp() == null) {
return BigDecimal.ZERO;
}
BigDecimal monthlyRainfall = rainfall.getDrp();
// 如果是当前月份,需要按剩余天数比例计算
if (month.equals(nowMonth)) {
int dayOfMonth = now.getDayOfMonth();
int totalDaysInMonth = now.lengthOfMonth();
int remainingDays = totalDaysInMonth - dayOfMonth + 1;
// 按剩余天数比例计算当月有效降雨量
monthlyRainfall = new BigDecimal(remainingDays)
.multiply(monthlyRainfall)
.divide(new BigDecimal(totalDaysInMonth), 2, RoundingMode.HALF_UP);
}
// 如果不是当前月份,则使用整月的降雨量(不需要按比例计算)
// 预测来水量 = 月降雨量 * 水库坝址控制流域面积 / 1000
BigDecimal sum = monthlyRainfall.divide(new BigDecimal(1000), 2, RoundingMode.HALF_UP);
return sum.multiply(watShedArea);
}
private BigDecimal calcPredictV(Integer year, Integer month,BigDecimal watShedArea) {
LocalDate now = LocalDate.now();
Integer nowMonth = now.getMonthValue();
LambdaQueryWrapper<TyYearRainfall> queryWrapper = Wrappers.lambdaQuery();
queryWrapper.eq(TyYearRainfall::getYear,year)
.eq(TyYearRainfall::getType,2)
.ge(TyYearRainfall::getMonth,nowMonth)
.le(TyYearRainfall::getMonth,month);
List<TyYearRainfall> list = tyYearRainfallMapper.selectList(queryWrapper);
//和当前月份相同的降雨量
Optional<TyYearRainfall> first = list.stream().filter(o -> nowMonth == o.getMonth()).findFirst();
BigDecimal drp = first.isPresent() ? first.get().getDrp() : new BigDecimal(0);
int dayOfMonth = now.getDayOfMonth();
int total = now.lengthOfMonth();
BigDecimal nowMonthDrp = new BigDecimal((total - dayOfMonth + 1)).multiply(drp).divide(new BigDecimal(total), 2, RoundingMode.HALF_UP);
//当前月到预测月份的降雨量
BigDecimal value = list.stream().filter(o -> nowMonth != o.getMonth()).map(TyYearRainfall::getDrp).reduce(BigDecimal.ZERO, BigDecimal::add);
//预测来水量 = 月降雨量和 * 水库坝址控制流域面积
2024-11-15 13:34:03 +08:00
BigDecimal sum = nowMonthDrp.add(value).divide(new BigDecimal(1000),2,RoundingMode.HALF_UP);
return sum.multiply(watShedArea);
}
2024-10-09 13:52:01 +08:00
public BigDecimal predictWater(Integer year, Integer month) {
List<AttResBaseVo> list = reservoirWaterService.list();
if(CollectionUtils.isEmpty(list)){
return new BigDecimal(0);
}
return calcPredictV(year,month,list.get(0).getWatShedArea());
}
2025-12-02 15:18:17 +08:00
public BigDecimal predictWaterMonth(Integer year, Integer month) {
List<AttResBaseVo> list = reservoirWaterService.list();
if(CollectionUtils.isEmpty(list)){
return new BigDecimal(0);
}
return calcMonthlyPredictV(year,month,list.get(0).getWatShedArea());
}
2024-07-08 17:47:02 +08:00
}