|
|
@@ -6,7 +6,6 @@ import java.time.Instant;
|
|
|
import java.time.LocalDate;
|
|
|
import java.time.LocalDateTime;
|
|
|
import java.time.YearMonth;
|
|
|
-import java.time.ZoneId;
|
|
|
import java.time.ZonedDateTime;
|
|
|
import java.time.format.DateTimeFormatter;
|
|
|
import java.time.format.DateTimeParseException;
|
|
|
@@ -43,7 +42,7 @@ import lombok.extern.slf4j.Slf4j;
|
|
|
*/
|
|
|
@Slf4j
|
|
|
@Service
|
|
|
-public class ShortTermPowerForecastReportServiceImpl implements IShortTermPowerForecastReportService
|
|
|
+public class ShortTermPowerForecastReportServiceImpl extends AbstractPowerForecastReportServiceImpl implements IShortTermPowerForecastReportService
|
|
|
{
|
|
|
/** Dict类型:短期预测误差阈值 */
|
|
|
private static final String DICT_TYPE_SHORT_TERM_ERROR_THRESHOLD = "short_term_error_threshold";
|
|
|
@@ -51,7 +50,6 @@ public class ShortTermPowerForecastReportServiceImpl implements IShortTermPowerF
|
|
|
private static final DateTimeFormatter DATE_FMT = DateTimeFormatter.ofPattern("yyyy-MM-dd");
|
|
|
private static final DateTimeFormatter MONTH_FMT = DateTimeFormatter.ofPattern("yyyy-MM");
|
|
|
private static final DateTimeFormatter DATE_TIME_FMT = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
|
|
|
- private static final ZoneId ZONE_SHANGHAI = ZoneId.of("Asia/Shanghai");
|
|
|
|
|
|
@Autowired
|
|
|
private IDataElectricityLocalService electricityLocalService;
|
|
|
@@ -97,11 +95,11 @@ public class ShortTermPowerForecastReportServiceImpl implements IShortTermPowerF
|
|
|
switch (type)
|
|
|
{
|
|
|
case "daily":
|
|
|
- return buildDailyReport(actualList, pureForecastList, forecastList);
|
|
|
+ return buildDailyReport(entityId, actualList, pureForecastList, forecastList);
|
|
|
case "monthly":
|
|
|
- return buildMonthlyReport(actualList, pureForecastList, forecastList);
|
|
|
+ return buildMonthlyReport(entityId, actualList, pureForecastList, forecastList);
|
|
|
case "yearly":
|
|
|
- return buildYearlyReport(actualList, pureForecastList, forecastList);
|
|
|
+ return buildYearlyReport(entityId, actualList, pureForecastList, forecastList);
|
|
|
default:
|
|
|
return Collections.emptyList();
|
|
|
}
|
|
|
@@ -172,7 +170,7 @@ public class ShortTermPowerForecastReportServiceImpl implements IShortTermPowerF
|
|
|
/**
|
|
|
* 构建日报
|
|
|
*/
|
|
|
- private List<ShortTermPowerForecastReportVO> buildDailyReport(List<DataElectricityLocal> actualList,
|
|
|
+ private List<ShortTermPowerForecastReportVO> buildDailyReport(String entityId, List<DataElectricityLocal> actualList,
|
|
|
List<ForecastPowerAverage> forecastList, List<DataShortTermPowerForecastReport> rawForecastList)
|
|
|
{
|
|
|
Map<String, List<DataElectricityLocal>> dailyMap = groupByDay(actualList);
|
|
|
@@ -187,7 +185,7 @@ public class ShortTermPowerForecastReportServiceImpl implements IShortTermPowerF
|
|
|
|
|
|
ShortTermPowerForecastReportVO vo = new ShortTermPowerForecastReportVO();
|
|
|
vo.setTime(day);
|
|
|
- computeDailyMetrics(vo, records, forecastRecords, rawForecastList);
|
|
|
+ computeDailyMetrics(entityId, vo, records, forecastRecords, rawForecastList);
|
|
|
result.add(vo);
|
|
|
}
|
|
|
return result;
|
|
|
@@ -196,7 +194,7 @@ public class ShortTermPowerForecastReportServiceImpl implements IShortTermPowerF
|
|
|
/**
|
|
|
* 构建月报
|
|
|
*/
|
|
|
- private List<ShortTermPowerForecastReportVO> buildMonthlyReport(List<DataElectricityLocal> actualList,
|
|
|
+ private List<ShortTermPowerForecastReportVO> buildMonthlyReport(String entityId, List<DataElectricityLocal> actualList,
|
|
|
List<ForecastPowerAverage> forecastList, List<DataShortTermPowerForecastReport> rawForecastList)
|
|
|
{
|
|
|
Map<String, List<DataElectricityLocal>> monthlyMap = groupByMonth(actualList);
|
|
|
@@ -212,7 +210,7 @@ public class ShortTermPowerForecastReportServiceImpl implements IShortTermPowerF
|
|
|
|
|
|
ShortTermPowerForecastReportVO vo = new ShortTermPowerForecastReportVO();
|
|
|
vo.setTime(month);
|
|
|
- computeDailyMetrics(vo, records, forecastRecords, rawForecastList);
|
|
|
+ computeDailyMetrics(entityId, vo, records, forecastRecords, rawForecastList);
|
|
|
result.add(vo);
|
|
|
}
|
|
|
return result;
|
|
|
@@ -221,7 +219,7 @@ public class ShortTermPowerForecastReportServiceImpl implements IShortTermPowerF
|
|
|
/**
|
|
|
* 构建年报
|
|
|
*/
|
|
|
- private List<ShortTermPowerForecastReportVO> buildYearlyReport(List<DataElectricityLocal> actualList,
|
|
|
+ private List<ShortTermPowerForecastReportVO> buildYearlyReport(String entityId, List<DataElectricityLocal> actualList,
|
|
|
List<ForecastPowerAverage> forecastList, List<DataShortTermPowerForecastReport> rawForecastList)
|
|
|
{
|
|
|
Map<String, List<DataElectricityLocal>> yearlyMap = groupByYear(actualList);
|
|
|
@@ -237,7 +235,7 @@ public class ShortTermPowerForecastReportServiceImpl implements IShortTermPowerF
|
|
|
|
|
|
ShortTermPowerForecastReportVO vo = new ShortTermPowerForecastReportVO();
|
|
|
vo.setTime(year);
|
|
|
- computeDailyMetrics(vo, records, forecastRecords, rawForecastList);
|
|
|
+ computeDailyMetrics(entityId, vo, records, forecastRecords, rawForecastList);
|
|
|
result.add(vo);
|
|
|
}
|
|
|
return result;
|
|
|
@@ -246,15 +244,15 @@ public class ShortTermPowerForecastReportServiceImpl implements IShortTermPowerF
|
|
|
/**
|
|
|
* 计算指标(日报/月报/年报通用)
|
|
|
*/
|
|
|
- private void computeDailyMetrics(ShortTermPowerForecastReportVO vo,
|
|
|
+ private void computeDailyMetrics(String entityId, ShortTermPowerForecastReportVO vo,
|
|
|
List<DataElectricityLocal> actualRecords, List<ForecastPowerAverage> forecastRecords, List<DataShortTermPowerForecastReport> rawForecastList)
|
|
|
{
|
|
|
// 预先构建预测数据映射(避免各方法重复调用 buildForecastMap)
|
|
|
Map<Long, BigDecimal> forecastMap = buildForecastMap(forecastRecords);
|
|
|
|
|
|
// 1. operatingCapacity: 筛选 device_status = 0 AND grid_status = 1, MAX(actual_power) / 1000
|
|
|
- BigDecimal operatingCapacity = computeOperatingCapacity(actualRecords);
|
|
|
- vo.setOperatingCapacity(operatingCapacity);
|
|
|
+ BigDecimal operatingCapacity = computeOperatingCapacity(entityId, actualRecords);
|
|
|
+ vo.setOperatingCapacity(operatingCapacity.divide(new BigDecimal(1000), SCALE, RoundingMode.HALF_UP));
|
|
|
|
|
|
// 2. actualPower: 筛选 grid_status = 1, AVG(actual_power) / 1000
|
|
|
BigDecimal actualPower = computeActualPower(actualRecords);
|
|
|
@@ -265,11 +263,11 @@ public class ShortTermPowerForecastReportServiceImpl implements IShortTermPowerF
|
|
|
vo.setForecastPower(forecastPower);
|
|
|
|
|
|
// 4. RMSE
|
|
|
- BigDecimal rmse = computeRmse(actualRecords, forecastMap);
|
|
|
+ BigDecimal rmse = computeRmse(operatingCapacity, actualRecords, forecastMap);
|
|
|
vo.setRootMeanSquareError(rmse);
|
|
|
|
|
|
// 5. MAE
|
|
|
- BigDecimal mae = computeMae(actualRecords, forecastMap);
|
|
|
+ BigDecimal mae = computeMae(operatingCapacity, actualRecords, forecastMap);
|
|
|
vo.setMeanAbsoluteError(mae);
|
|
|
|
|
|
// 6. correlationCoefficientR
|
|
|
@@ -285,302 +283,17 @@ public class ShortTermPowerForecastReportServiceImpl implements IShortTermPowerF
|
|
|
vo.setMaximumErrorPassRate(passRate);
|
|
|
|
|
|
// 8. acc: 合格率
|
|
|
- BigDecimal acc = computeAccuracy(actualRecords, forecastMap, operatingCapacity, rawForecastList);
|
|
|
+ BigDecimal acc = computeAccuracy(actualRecords, forecastMap, operatingCapacity, rawForecastList, this::getAccForecastReportPower);
|
|
|
vo.setAcc(acc);
|
|
|
}
|
|
|
|
|
|
- /**
|
|
|
- * 计算开机容量
|
|
|
- */
|
|
|
- private BigDecimal computeOperatingCapacity(List<DataElectricityLocal> records)
|
|
|
- {
|
|
|
- double maxPower = 0.0;
|
|
|
- for (DataElectricityLocal r : records)
|
|
|
- {
|
|
|
- if (r.getDeviceStatus() != null && r.getDeviceStatus() == 0
|
|
|
- && r.getGridStatus() != null && r.getGridStatus() == 1)
|
|
|
- {
|
|
|
- Double ap = r.getActualPower();
|
|
|
- if (ap != null && ap > maxPower)
|
|
|
- {
|
|
|
- maxPower = ap;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- return BigDecimal.valueOf(maxPower / 1000.0).setScale(3, RoundingMode.HALF_UP);
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 计算实发功率
|
|
|
- */
|
|
|
- private BigDecimal computeActualPower(List<DataElectricityLocal> records)
|
|
|
- {
|
|
|
- BigDecimal sum = BigDecimal.ZERO;
|
|
|
- int count = 0;
|
|
|
- for (DataElectricityLocal r : records)
|
|
|
- {
|
|
|
- if (r.getGridStatus() != null && r.getGridStatus() == 1)
|
|
|
- {
|
|
|
- Double ap = r.getActualPower();
|
|
|
- if (ap != null)
|
|
|
- {
|
|
|
- sum = sum.add(BigDecimal.valueOf(ap));
|
|
|
- count++;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- if (count == 0)
|
|
|
- {
|
|
|
- return BigDecimal.ZERO;
|
|
|
- }
|
|
|
- return sum.divide(new BigDecimal(1000)).divide(BigDecimal.valueOf(count), 3, RoundingMode.HALF_UP);
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 计算预测功率
|
|
|
- */
|
|
|
- private BigDecimal computeForecastPower(Map<Long, BigDecimal> forecastMap)
|
|
|
- {
|
|
|
- if (forecastMap == null || forecastMap.isEmpty())
|
|
|
- {
|
|
|
- return BigDecimal.ZERO;
|
|
|
- }
|
|
|
- BigDecimal sum = forecastMap.values().stream().reduce(BigDecimal.ZERO, BigDecimal::add);
|
|
|
- BigDecimal avg = sum.divide(BigDecimal.valueOf(forecastMap.size()), 10, RoundingMode.HALF_UP);
|
|
|
- return avg.divide(new BigDecimal(1000), 3, RoundingMode.HALF_UP);
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 计算RMSE
|
|
|
- */
|
|
|
- private BigDecimal computeRmse(List<DataElectricityLocal> actualRecords,
|
|
|
- Map<Long, BigDecimal> forecastMap)
|
|
|
- {
|
|
|
- if (forecastMap.isEmpty())
|
|
|
- {
|
|
|
- return BigDecimal.ZERO;
|
|
|
- }
|
|
|
-
|
|
|
- BigDecimal sumSquaredError = BigDecimal.ZERO;
|
|
|
- int count = 0;
|
|
|
- BigDecimal thousand = BigDecimal.valueOf(1000);
|
|
|
-
|
|
|
- for (DataElectricityLocal r : actualRecords)
|
|
|
- {
|
|
|
- if (r.getTm() == null || r.getActualPower() == null) continue;
|
|
|
-
|
|
|
- Long ts = r.getTm().getTime() / 1000;
|
|
|
- BigDecimal fp = forecastMap.get(ts);
|
|
|
- if (fp == null) continue;
|
|
|
-
|
|
|
- BigDecimal ap = BigDecimal.valueOf(r.getActualPower());
|
|
|
- BigDecimal diffMW = ap.subtract(fp).divide(thousand, 10, RoundingMode.HALF_UP);
|
|
|
- sumSquaredError = sumSquaredError.add(diffMW.multiply(diffMW));
|
|
|
- count++;
|
|
|
- }
|
|
|
-
|
|
|
- if (count == 0)
|
|
|
- {
|
|
|
- return BigDecimal.ZERO;
|
|
|
- }
|
|
|
-
|
|
|
- BigDecimal meanSquaredError = sumSquaredError.divide(BigDecimal.valueOf(count), 10, RoundingMode.HALF_UP);
|
|
|
- // 用 Math.sqrt 开方(平方根无法用 BigDecimal 精确表示,转为 double 计算后格式化)
|
|
|
- double rmse = Math.sqrt(meanSquaredError.doubleValue());
|
|
|
- return BigDecimal.valueOf(rmse).setScale(3, RoundingMode.HALF_UP);
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 计算MAE
|
|
|
- */
|
|
|
- private BigDecimal computeMae(List<DataElectricityLocal> actualRecords,
|
|
|
- Map<Long, BigDecimal> forecastMap)
|
|
|
- {
|
|
|
- if (forecastMap.isEmpty())
|
|
|
- {
|
|
|
- return BigDecimal.ZERO;
|
|
|
- }
|
|
|
-
|
|
|
- BigDecimal sumAbsError = BigDecimal.ZERO;
|
|
|
- int count = 0;
|
|
|
- BigDecimal thousand = BigDecimal.valueOf(1000);
|
|
|
-
|
|
|
- for (DataElectricityLocal r : actualRecords)
|
|
|
- {
|
|
|
- if (r.getTm() == null || r.getActualPower() == null) continue;
|
|
|
-
|
|
|
- Long ts = r.getTm().getTime() / 1000;
|
|
|
- BigDecimal fp = forecastMap.get(ts);
|
|
|
- if (fp == null) continue;
|
|
|
-
|
|
|
- BigDecimal ap = BigDecimal.valueOf(r.getActualPower());
|
|
|
- BigDecimal absErrorMW = ap.subtract(fp).abs().divide(thousand, 10, RoundingMode.HALF_UP);
|
|
|
- sumAbsError = sumAbsError.add(absErrorMW);
|
|
|
- count++;
|
|
|
- }
|
|
|
-
|
|
|
- if (count == 0)
|
|
|
- {
|
|
|
- return BigDecimal.ZERO;
|
|
|
- }
|
|
|
-
|
|
|
- BigDecimal mae = sumAbsError.divide(BigDecimal.valueOf(count), 3, RoundingMode.HALF_UP);
|
|
|
- return mae;
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 计算相关性系数 R
|
|
|
- */
|
|
|
- private BigDecimal computeCorrelation(List<DataElectricityLocal> actualRecords,
|
|
|
- Map<Long, BigDecimal> forecastMap)
|
|
|
- {
|
|
|
- if (forecastMap.isEmpty())
|
|
|
- {
|
|
|
- return BigDecimal.ZERO;
|
|
|
- }
|
|
|
-
|
|
|
- // 收集成对数据(MW)
|
|
|
- List<BigDecimal> xList = new ArrayList<>();
|
|
|
- List<BigDecimal> yList = new ArrayList<>();
|
|
|
- BigDecimal thousand = BigDecimal.valueOf(1000);
|
|
|
-
|
|
|
- for (DataElectricityLocal r : actualRecords)
|
|
|
- {
|
|
|
- if (r.getTm() == null || r.getActualPower() == null) continue;
|
|
|
-
|
|
|
- Long ts = r.getTm().getTime() / 1000;
|
|
|
- BigDecimal fp = forecastMap.get(ts);
|
|
|
- if (fp == null) continue;
|
|
|
-
|
|
|
- BigDecimal ap = BigDecimal.valueOf(r.getActualPower()).divide(thousand, 10, RoundingMode.HALF_UP);
|
|
|
- BigDecimal fy = fp.divide(thousand, 10, RoundingMode.HALF_UP);
|
|
|
- xList.add(ap);
|
|
|
- yList.add(fy);
|
|
|
- }
|
|
|
-
|
|
|
- int n = xList.size();
|
|
|
- if (n < 2)
|
|
|
- {
|
|
|
- return BigDecimal.ZERO;
|
|
|
- }
|
|
|
-
|
|
|
- BigDecimal nBd = BigDecimal.valueOf(n);
|
|
|
- // 计算均值
|
|
|
- BigDecimal sumX = xList.stream().reduce(BigDecimal.ZERO, BigDecimal::add);
|
|
|
- BigDecimal sumY = yList.stream().reduce(BigDecimal.ZERO, BigDecimal::add);
|
|
|
- BigDecimal meanX = sumX.divide(nBd, 10, RoundingMode.HALF_UP);
|
|
|
- BigDecimal meanY = sumY.divide(nBd, 10, RoundingMode.HALF_UP);
|
|
|
-
|
|
|
- // 计算相关系数:逐步累加,保持精度
|
|
|
- BigDecimal numerator = BigDecimal.ZERO;
|
|
|
- BigDecimal sumSqX = BigDecimal.ZERO;
|
|
|
- BigDecimal sumSqY = BigDecimal.ZERO;
|
|
|
-
|
|
|
- for (int i = 0; i < n; i++)
|
|
|
- {
|
|
|
- BigDecimal dx = xList.get(i).subtract(meanX);
|
|
|
- BigDecimal dy = yList.get(i).subtract(meanY);
|
|
|
- numerator = numerator.add(dx.multiply(dy));
|
|
|
- sumSqX = sumSqX.add(dx.multiply(dx));
|
|
|
- sumSqY = sumSqY.add(dy.multiply(dy));
|
|
|
- }
|
|
|
-
|
|
|
- BigDecimal denominatorSquared = sumSqX.multiply(sumSqY);
|
|
|
- if (denominatorSquared.compareTo(BigDecimal.ZERO) == 0)
|
|
|
- {
|
|
|
- return BigDecimal.ZERO;
|
|
|
- }
|
|
|
-
|
|
|
- // 用 Math.sqrt 开方(平方根无法用 BigDecimal 精确表示)
|
|
|
- double denominator = Math.sqrt(denominatorSquared.doubleValue());
|
|
|
- double r = numerator.doubleValue() / denominator;
|
|
|
- return BigDecimal.valueOf(r).setScale(3, RoundingMode.HALF_UP);
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 计算准确率 acc = (1 - sqrt(ΣSi / N)) * 100
|
|
|
- *
|
|
|
- * <p>其中:
|
|
|
- * <ul>
|
|
|
- * <li>阈值 = 开机容量 * 0.5</li>
|
|
|
- * <li>Si = ((Pmi - Ppi) / Pmi)² 当 Pmi >= 阈值</li>
|
|
|
- * <li>Si = ((Pmi - Ppi) / 阈值)² 当 Pmi < 阈值</li>
|
|
|
- * </ul>
|
|
|
- */
|
|
|
- private BigDecimal computeAccuracy(List<DataElectricityLocal> actualRecords,
|
|
|
- Map<Long, BigDecimal> forecastMap,
|
|
|
- BigDecimal operatingCapacity,
|
|
|
- List<DataShortTermPowerForecastReport> rawForecastList)
|
|
|
- {
|
|
|
- if (forecastMap == null || forecastMap.isEmpty() || operatingCapacity == null
|
|
|
- || operatingCapacity.compareTo(BigDecimal.ZERO) == 0)
|
|
|
- {
|
|
|
- return BigDecimal.ZERO;
|
|
|
- }
|
|
|
-
|
|
|
- // 阈值 = 开机容量(MW) * 0.25
|
|
|
- BigDecimal baseThreshold = new BigDecimal("0.25");
|
|
|
- BigDecimal threshold = operatingCapacity.multiply(baseThreshold).setScale(3, RoundingMode.HALF_UP);
|
|
|
-
|
|
|
- BigDecimal stotal = BigDecimal.ZERO;
|
|
|
- int n = 0;
|
|
|
- int precisionLength = 20;
|
|
|
-
|
|
|
- for (DataElectricityLocal r : actualRecords)
|
|
|
- {
|
|
|
- if (r.getTm() == null || r.getActualPower() == null) continue;
|
|
|
-
|
|
|
- Long ts = r.getTm().getTime() / 1000;
|
|
|
- BigDecimal fp = getAccForecastReportPower(ts, rawForecastList);
|
|
|
- if (fp == null) continue;
|
|
|
-
|
|
|
- BigDecimal pmiMW = BigDecimal.valueOf(r.getActualPower()).divide(BigDecimal.valueOf(1000), precisionLength, RoundingMode.HALF_UP);
|
|
|
- BigDecimal ppiMW = fp.divide(BigDecimal.valueOf(1000), precisionLength, RoundingMode.HALF_UP);
|
|
|
-
|
|
|
- BigDecimal diff = pmiMW.subtract(ppiMW);
|
|
|
- BigDecimal si;
|
|
|
- if (pmiMW.compareTo(threshold) >= 0)
|
|
|
- {
|
|
|
- BigDecimal tmpSi = diff.divide(pmiMW, precisionLength, RoundingMode.HALF_UP);
|
|
|
- si = tmpSi.multiply(tmpSi);
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- BigDecimal tmpSi = diff.divide(threshold, precisionLength, RoundingMode.HALF_UP);
|
|
|
- si = tmpSi.multiply(tmpSi);
|
|
|
- }
|
|
|
-
|
|
|
- stotal = stotal.add(si);
|
|
|
- n++;
|
|
|
- }
|
|
|
-
|
|
|
- if (n == 0)
|
|
|
- {
|
|
|
- return BigDecimal.ZERO;
|
|
|
- }
|
|
|
-
|
|
|
- // acc = (1 - sqrt(stotal / n)) * 100
|
|
|
- double meanSquare = stotal.divide(BigDecimal.valueOf(n), precisionLength, RoundingMode.HALF_UP).doubleValue();
|
|
|
- log.debug("meanSquare: {}", meanSquare);
|
|
|
- double deviation = Math.sqrt(meanSquare);
|
|
|
- log.debug("deviation: {}", deviation);
|
|
|
- double acc = deviation * 100.0;
|
|
|
- log.debug("acc: {}", acc);
|
|
|
-
|
|
|
- // 边界处理
|
|
|
- if (acc < 0) acc = 0;
|
|
|
- if (acc > 100) acc = 100;
|
|
|
-
|
|
|
- return BigDecimal.valueOf(acc).setScale(3, RoundingMode.HALF_UP);
|
|
|
- }
|
|
|
-
|
|
|
/**
|
|
|
* 获取日前timestamp预报数据
|
|
|
* @param timestamp
|
|
|
* @param rawForecastList
|
|
|
* @return
|
|
|
*/
|
|
|
- private BigDecimal getAccForecastReportPower(long timestamp, List<DataShortTermPowerForecastReport> rawForecastList)
|
|
|
+ private BigDecimal getAccForecastReportPower(List<DataShortTermPowerForecastReport> rawForecastList, long timestamp)
|
|
|
{
|
|
|
return rawForecastList.stream()
|
|
|
.filter(r -> null != r.getPower() && r.getForecastTime() != null && r.getStartTime() != null && r.getForecastTime() == timestamp && isYesterday(timestamp, r.getStartTime()))
|
|
|
@@ -602,32 +315,6 @@ public class ShortTermPowerForecastReportServiceImpl implements IShortTermPowerF
|
|
|
.equals(LocalDateTime.ofInstant(Instant.ofEpochSecond(datTimestamp), ZONE_SHANGHAI).toLocalDate());
|
|
|
}
|
|
|
|
|
|
- /**
|
|
|
- * 构建预测数据映射:时间戳(秒) -> power(kW)
|
|
|
- */
|
|
|
- private Map<Long, BigDecimal> buildForecastMap(List<ForecastPowerAverage> records)
|
|
|
- {
|
|
|
- Map<Long, BigDecimal> map = new LinkedHashMap<>();
|
|
|
- if (records == null) return map;
|
|
|
-
|
|
|
- for (ForecastPowerAverage r : records)
|
|
|
- {
|
|
|
- if (r.getForecastTime() == null) continue;
|
|
|
- BigDecimal power = r.getAvgPower();
|
|
|
- if (power == null) continue;
|
|
|
-
|
|
|
- try
|
|
|
- {
|
|
|
- map.put(r.getForecastTime(), power);
|
|
|
- }
|
|
|
- catch (NumberFormatException e)
|
|
|
- {
|
|
|
- // skip
|
|
|
- }
|
|
|
- }
|
|
|
- return map;
|
|
|
- }
|
|
|
-
|
|
|
/**
|
|
|
* 按日分组
|
|
|
*/
|