package com.gkhy.fourierSpecialGasMonitor.utils;
|
|
import com.alibaba.druid.util.StringUtils;
|
import com.gkhy.fourierSpecialGasMonitor.commons.enums.ResultCode;
|
import com.gkhy.fourierSpecialGasMonitor.commons.exception.BusinessException;
|
import com.gkhy.fourierSpecialGasMonitor.entity.GasConcentration;
|
import com.gkhy.fourierSpecialGasMonitor.entity.SummaryStats;
|
import com.gkhy.fourierSpecialGasMonitor.entity.req.SummaryStatsReqDTO;
|
import com.gkhy.fourierSpecialGasMonitor.entity.resp.SummaryStatsPageRespDTO;
|
import com.gkhy.fourierSpecialGasMonitor.enums.StatsTypeEnum;
|
import org.slf4j.Logger;
|
import org.slf4j.LoggerFactory;
|
import org.springframework.beans.BeanUtils;
|
|
import java.lang.reflect.Field;
|
import java.time.LocalDate;
|
import java.time.Year;
|
import java.time.YearMonth;
|
import java.time.format.DateTimeParseException;
|
import java.util.Arrays;
|
|
public class SummaryUtils {
|
|
private final Logger logger = LoggerFactory.getLogger(this.getClass());
|
|
|
|
/**
|
* 初始化统计数据(当当天无数据时,用新数据作为初始值)
|
*/
|
public static void initSummaryStats(SummaryStats stats, GasConcentration data) {
|
// 初始化 temp 相关统计(min/max/avg 均为当前数据值)
|
stats.setTempMin(data.getTemp());
|
stats.setTempMax(data.getTemp());
|
stats.setTempAvg(data.getTemp());
|
|
// 初始化 humidity 相关统计
|
stats.setHumidityMin(data.getHumidity());
|
stats.setHumidityMax(data.getHumidity());
|
stats.setHumidityAvg(data.getHumidity());
|
|
// 初始化 windSpeed 相关统计
|
Double windSpeed = data.getWindSpeed();
|
stats.setWindSpeedMin(windSpeed);
|
stats.setWindSpeedMax(windSpeed);
|
stats.setWindSpeedAvg(windSpeed);
|
|
// 初始化 windDirection 相关统计(处理可能的 null)
|
Integer windDirection = data.getWindDirection();
|
stats.setWindDirectionMin(windDirection);
|
stats.setWindDirectionMax(windDirection);
|
stats.setWindDirectionAvg(windDirection != null ? windDirection.doubleValue() : null);
|
|
// 初始化 pressure 相关统计
|
Double pressure = data.getPressure();
|
stats.setPressureMin(pressure);
|
stats.setPressureMax(pressure);
|
stats.setPressureAvg(pressure);
|
}
|
|
/**
|
* 更新统计数据(根据新数据重新计算 min/max/avg)
|
*/
|
public static void updateSummaryStats(SummaryStats stats, GasConcentration newData) {
|
// 更新 temp:min 取更小值,max 取更大值,avg 重新计算(需注意:avg 不能直接用当前 avg 计算,需累计总和/数量)
|
// 注意:此处简化处理,实际 avg 需基于总样本数计算(建议在数据库查询时直接聚合,而非内存中更新)
|
Double newTemp = newData.getTemp();
|
stats.setTempMin(min(stats.getTempMin(), newTemp));
|
stats.setTempMax(max(stats.getTempMax(), newTemp));
|
|
// 更新 humidity
|
Double newHumidity = newData.getHumidity();
|
stats.setHumidityMin(min(stats.getHumidityMin(), newHumidity));
|
stats.setHumidityMax(max(stats.getHumidityMax(), newHumidity));
|
|
// 更新 windSpeed
|
Double newWindSpeed = newData.getWindSpeed();
|
stats.setWindSpeedMin(min(stats.getWindSpeedMin(), newWindSpeed));
|
stats.setWindSpeedMax(max(stats.getWindSpeedMax(), newWindSpeed));
|
|
// 更新 windDirection
|
Integer newWindDir = newData.getWindDirection();
|
stats.setWindDirectionMin(min(stats.getWindDirectionMin(), newWindDir));
|
stats.setWindDirectionMax(max(stats.getWindDirectionMax(), newWindDir));
|
|
// 更新 pressure
|
Double newPressure = newData.getPressure();
|
stats.setPressureMin(min(stats.getPressureMin(), newPressure));
|
stats.setPressureMax(max(stats.getPressureMax(), newPressure));
|
}
|
|
/**
|
* 安全计算两个 Double 的最小值(处理 null)
|
*/
|
private static Double min(Double a, Double b) {
|
if (a == null) return b;
|
if (b == null) return a;
|
return Math.min(a, b);
|
}
|
|
/**
|
* 安全计算两个 Integer 的最小值(处理 null)
|
*/
|
private static Integer min(Integer a, Integer b) {
|
if (a == null) return b;
|
if (b == null) return a;
|
return Math.min(a, b);
|
}
|
|
// 同理实现 max 方法(Double 和 Integer 版本)
|
private static Double max(Double a, Double b) {
|
if (a == null) return b;
|
if (b == null) return a;
|
return Math.max(a, b);
|
}
|
|
private static Integer max(Integer a, Integer b) {
|
if (a == null) return b;
|
if (b == null) return a;
|
return Math.max(a, b);
|
}
|
|
public void validateParams(SummaryStatsReqDTO reqDTO) {
|
if (reqDTO == null) {
|
throw new BusinessException(this.getClass(), ResultCode.PARAM_ERROR_NULL.getCode(),"请求参数不能为空");
|
}
|
if (StringUtils.isEmpty(reqDTO.getType())) {
|
throw new BusinessException(this.getClass(), ResultCode.PARAM_ERROR_NULL.getCode(),"气体类型(type)不能为空");
|
}
|
if (reqDTO.getDateType() == null || !Arrays.asList(1, 2, 3).contains(reqDTO.getDateType())) {
|
throw new BusinessException(this.getClass(), ResultCode.PARAM_ERROR_ILLEGAL.getCode(),"dateType必须为1(日)、2(月)、3(年)");
|
}
|
if (StringUtils.isEmpty(reqDTO.getDate())) {
|
throw new BusinessException(this.getClass(), ResultCode.PARAM_ERROR_NULL.getCode(),"日期(date)不能为空");
|
}
|
// 校验date格式(根据dateType)
|
try {
|
switch (reqDTO.getDateType()) {
|
case 1:
|
LocalDate.parse(reqDTO.getDate()); // 校验 yyyy-MM-dd
|
break;
|
case 2:
|
YearMonth.parse(reqDTO.getDate()); // 校验 yyyy-MM
|
break;
|
case 3:
|
Year.parse(reqDTO.getDate()); // 校验 yyyy
|
break;
|
}
|
} catch (DateTimeParseException e) {
|
throw new BusinessException(this.getClass(), ResultCode.PARAM_ERROR_ILLEGAL.getCode(),"日期格式错误,dateType=" + reqDTO.getDateType() + "时,date应为" +
|
(reqDTO.getDateType() == 1 ? "yyyy-MM-dd" : reqDTO.getDateType() == 2 ? "yyyy-MM" : "yyyy"));
|
}
|
}
|
|
|
public SummaryStatsPageRespDTO convertToResp(SummaryStats stats, String type) {
|
SummaryStatsPageRespDTO respDTO = new SummaryStatsPageRespDTO();
|
BeanUtils.copyProperties(stats, respDTO); // 复制公共字段(如 time)
|
|
if (type == null) {
|
return respDTO; // 若 type 为 null,不设置指标相关字段
|
}
|
|
StatsTypeEnum mapper = StatsTypeEnum.getByType(type);
|
if (mapper == null) {
|
return respDTO; // 无效 type(理论上已在参数校验时拦截)
|
}
|
|
try {
|
// 反射获取字段值(通过枚举映射的字段名)
|
Field valueField = SummaryStats.class.getDeclaredField(mapper.getValueField());
|
Field minField = SummaryStats.class.getDeclaredField(mapper.getMinField());
|
Field maxField = SummaryStats.class.getDeclaredField(mapper.getMaxField());
|
Field avgField = SummaryStats.class.getDeclaredField(mapper.getAvgField());
|
|
valueField.setAccessible(true);
|
minField.setAccessible(true);
|
maxField.setAccessible(true);
|
avgField.setAccessible(true);
|
|
// 设置到响应 DTO
|
respDTO.setValue(valueField.get(stats));
|
respDTO.setMin(minField.get(stats));
|
respDTO.setMax(maxField.get(stats));
|
respDTO.setAvg(avgField.get(stats));
|
} catch (NoSuchFieldException | IllegalAccessException e) {
|
logger.error("转换 SummaryStats 到 DTO 失败,type={}, stats={}", type, stats, e);
|
}
|
return respDTO;
|
}
|
}
|