统计查询导出,功率曲线导出修改
This commit is contained in:
parent
72573c30c0
commit
846c49bc96
@ -6,9 +6,9 @@ package com.das.common.constant;
|
||||
public interface StatisticalAnalysisConstant {
|
||||
|
||||
|
||||
String TREND_ANALYSE = "趋势分析";
|
||||
String TREND_ANALYSE = "单机分析";
|
||||
|
||||
String POWER_CURVE = "功率曲线";
|
||||
|
||||
String TREND_CONTRAST = "趋势对比";
|
||||
String TREND_CONTRAST = "多机对比";
|
||||
}
|
||||
|
@ -0,0 +1,16 @@
|
||||
package com.das.common.constant;
|
||||
|
||||
/**
|
||||
* 统计分析
|
||||
*/
|
||||
public interface StatisticalAnalysisFunctionConstant {
|
||||
|
||||
|
||||
String INTERPOLATION = "interpolation";
|
||||
|
||||
String AVERAGE = "average";
|
||||
|
||||
String MAX = "max";
|
||||
|
||||
String min = "min";
|
||||
}
|
@ -26,7 +26,7 @@ public class StatisticalAnalysisController {
|
||||
|
||||
|
||||
/**
|
||||
* 趋势分析Excel导出
|
||||
* 趋势分析 (单机分析)Excel导出
|
||||
* @param param 查询条件
|
||||
*/
|
||||
@PostMapping("/trendAnalyseExport")
|
||||
@ -45,7 +45,7 @@ public class StatisticalAnalysisController {
|
||||
|
||||
|
||||
/**
|
||||
* 趋势对比Excel导出
|
||||
* 趋势对比(多机对比) Excel导出
|
||||
* @param param 查询条件
|
||||
*/
|
||||
@PostMapping("/trendContrastExport")
|
||||
|
@ -38,6 +38,7 @@ public class TrendAnalyseDto
|
||||
private String timeName;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 设备属性列表
|
||||
*/
|
||||
@ -52,4 +53,11 @@ public class TrendAnalyseDto
|
||||
* 模型
|
||||
*/
|
||||
private String model;
|
||||
|
||||
private String calFunction;
|
||||
|
||||
private String windSource;
|
||||
|
||||
//是否显示曲线,0不显示,1显示
|
||||
private int displayCurve;
|
||||
}
|
||||
|
@ -33,11 +33,12 @@ public class TrendContrastDto
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 设备属性列表
|
||||
*/
|
||||
private List<SnapshotValueQueryParam> devices;
|
||||
|
||||
private String calFunction;
|
||||
|
||||
|
||||
}
|
||||
|
@ -4,15 +4,16 @@ import cn.hutool.core.io.IoUtil;
|
||||
import cn.hutool.core.util.RandomUtil;
|
||||
import cn.hutool.poi.excel.ExcelUtil;
|
||||
import cn.hutool.poi.excel.ExcelWriter;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.das.common.constant.StatisticalAnalysisConstant;
|
||||
import com.das.common.constant.StatisticalAnalysisFunctionConstant;
|
||||
import com.das.common.exceptions.ServiceException;
|
||||
import com.das.common.utils.BeanCopyUtils;
|
||||
import com.das.modules.curve.domain.entity.CurveItemEntity;
|
||||
import com.das.modules.curve.service.TheoreticalPowerCurveService;
|
||||
import com.das.modules.data.domain.SnapshotValueQueryParam;
|
||||
import com.das.modules.data.domain.TSValueQueryParam;
|
||||
import com.das.modules.data.domain.WindowValueQueryParam;
|
||||
import com.das.modules.data.service.DataService;
|
||||
import com.das.modules.equipment.entity.SysIotModelField;
|
||||
import com.das.modules.equipment.mapper.SysIotModelFieldMapper;
|
||||
@ -22,6 +23,7 @@ import com.das.modules.page.service.StatisticalAnalysisService;
|
||||
import jakarta.servlet.ServletOutputStream;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.apache.poi.ss.usermodel.ClientAnchor;
|
||||
import org.apache.poi.ss.usermodel.HorizontalAlignment;
|
||||
@ -33,6 +35,7 @@ import org.apache.poi.xssf.usermodel.XSSFChart;
|
||||
import org.apache.poi.xssf.usermodel.XSSFClientAnchor;
|
||||
import org.apache.poi.xssf.usermodel.XSSFDrawing;
|
||||
import org.apache.poi.xssf.usermodel.XSSFSheet;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jfree.chart.ChartFactory;
|
||||
import org.jfree.chart.ChartUtils;
|
||||
import org.jfree.chart.JFreeChart;
|
||||
@ -56,7 +59,9 @@ import java.text.SimpleDateFormat;
|
||||
import java.util.List;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
public class StatisticalAnalysisServiceImpl implements StatisticalAnalysisService {
|
||||
|
||||
@ -81,10 +86,19 @@ public class StatisticalAnalysisServiceImpl implements StatisticalAnalysisServic
|
||||
//根据条件获取历史数据
|
||||
List<Map<String, Map<String, Map<String, Object>>>> mapsList = new ArrayList<>();
|
||||
for (TrendAnalyseDto trendAnalyseDto : param) {
|
||||
TSValueQueryParam tsValueQueryParam = new TSValueQueryParam();
|
||||
BeanCopyUtils.copy(trendAnalyseDto,tsValueQueryParam);
|
||||
Map<String, Map<String, Map<String, Object>>> resultMap = dataService.queryTimeSeriesValues(tsValueQueryParam);
|
||||
mapsList.add(resultMap);
|
||||
//瞬时值
|
||||
if (trendAnalyseDto.getCalFunction().equals(StatisticalAnalysisFunctionConstant.INTERPOLATION)){
|
||||
TSValueQueryParam tsValueQueryParam = new TSValueQueryParam();
|
||||
BeanCopyUtils.copy(trendAnalyseDto,tsValueQueryParam);
|
||||
Map<String, Map<String, Map<String, Object>>> resultMap = dataService.queryTimeSeriesValues(tsValueQueryParam);
|
||||
mapsList.add(resultMap);
|
||||
}else {
|
||||
//其他
|
||||
WindowValueQueryParam windowValueQueryParam = new WindowValueQueryParam();
|
||||
BeanCopyUtils.copy(trendAnalyseDto,windowValueQueryParam);
|
||||
Map<String, Map<String, Map<String, Object>>> stringMapMap = dataService.queryWindowsValues(windowValueQueryParam);
|
||||
mapsList.add(stringMapMap);
|
||||
}
|
||||
}
|
||||
//获取Excel的列
|
||||
LinkedHashMap<String, String> map = getTrendColumnName(param);
|
||||
@ -119,23 +133,43 @@ public class StatisticalAnalysisServiceImpl implements StatisticalAnalysisServic
|
||||
TSValueQueryParam tsValueQueryParam = new TSValueQueryParam();
|
||||
BeanCopyUtils.copy(param,tsValueQueryParam);
|
||||
Map<String, Map<String, Map<String, Object>>> resultMap = dataService.queryTimeSeriesValues(tsValueQueryParam);
|
||||
//显示曲线,需要计算功率的平均值
|
||||
if (param.getDisplayCurve()==1){
|
||||
try {
|
||||
List<Double> windSpeedList = new ArrayList<>();
|
||||
List<Double> powerList = new ArrayList<>();
|
||||
getPowerCurveValueList(resultMap, powerList, windSpeedList);
|
||||
List<Map<String, List<Double>>> maps = calculateAverages(windSpeedList, powerList);
|
||||
setPowerCurveValueList(resultMap, maps);
|
||||
} catch (Exception e) {
|
||||
log.error("计算功率曲线平均值失败:"+e.getMessage());
|
||||
}
|
||||
}
|
||||
List<Map<String, Object>> dataList = new ArrayList<>();
|
||||
//填充功率曲线,Excel的数据集
|
||||
setPowerCurveExcelValue(resultMap, dataList, curveItemEntitieList);
|
||||
//获取功率曲线的列
|
||||
LinkedHashMap<String, String> map = getPowerCurveColumnName();
|
||||
LinkedHashMap<String, String> map = getPowerCurveColumnName(param);
|
||||
//获取图表类别集
|
||||
List<String> chartKey = getCharKey(map);
|
||||
ExcelWriter writer = ExcelUtil.getWriter(RandomUtil.randomInt(100, 1000) + "statistics" + ".xlsx");
|
||||
//设置Excel样式
|
||||
setExcelStyle(writer, map, dataList);
|
||||
//生成折线图
|
||||
addChartToExcel(writer,dataList,StatisticalAnalysisConstant.POWER_CURVE,chartKey);
|
||||
if (param.getDisplayCurve()==1){
|
||||
addChartToExcel(writer,dataList,StatisticalAnalysisConstant.POWER_CURVE,chartKey);
|
||||
}else {
|
||||
//生成散点图
|
||||
addScattersChartToExcel(writer,dataList,StatisticalAnalysisConstant.POWER_CURVE,chartKey);
|
||||
}
|
||||
//下载Excel
|
||||
downloadExcel(response, writer,StatisticalAnalysisConstant.POWER_CURVE);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 趋势对比Excel导出
|
||||
* @param param 查询条件
|
||||
@ -143,10 +177,17 @@ public class StatisticalAnalysisServiceImpl implements StatisticalAnalysisServic
|
||||
*/
|
||||
@Override
|
||||
public void trendContrastExport(TrendContrastDto param, HttpServletRequest request, HttpServletResponse response) {
|
||||
//根据条件获取历史数据
|
||||
TSValueQueryParam tsValueQueryParam = new TSValueQueryParam();
|
||||
BeanCopyUtils.copy(param,tsValueQueryParam);
|
||||
Map<String, Map<String, Map<String, Object>>> maps = dataService.queryTimeSeriesValues(tsValueQueryParam);
|
||||
Map<String, Map<String, Map<String, Object>>> maps = null;
|
||||
//瞬时值,历史区间数据查询
|
||||
if (param.getCalFunction().equals(StatisticalAnalysisFunctionConstant.INTERPOLATION)){
|
||||
TSValueQueryParam tsValueQueryParam = new TSValueQueryParam();
|
||||
BeanCopyUtils.copy(param,tsValueQueryParam);
|
||||
maps = dataService.queryTimeSeriesValues(tsValueQueryParam);
|
||||
}else {
|
||||
WindowValueQueryParam windowparam = new WindowValueQueryParam();
|
||||
BeanCopyUtils.copy(param,windowparam);
|
||||
maps = dataService.queryWindowsValues(windowparam);
|
||||
}
|
||||
//自定义别名 别名的key和实体类中的名称要对应上!
|
||||
LinkedHashMap<String, String> map = gettrendContrastColumnName(param);
|
||||
List<Map<String, Object>> dataList = new ArrayList<>();
|
||||
@ -374,11 +415,15 @@ public class StatisticalAnalysisServiceImpl implements StatisticalAnalysisServic
|
||||
* 获取功率曲线的列
|
||||
* @return Excel的列
|
||||
*/
|
||||
private LinkedHashMap<String, String> getPowerCurveColumnName() {
|
||||
private LinkedHashMap<String, String> getPowerCurveColumnName(TrendAnalyseDto param) {
|
||||
LinkedHashMap<String, String> map = new LinkedHashMap<>();
|
||||
map.put("time", "时间");
|
||||
map.put("iWindSpeed", "风速");
|
||||
map.put("iGenPower", "功率");
|
||||
if (param.getWindSource().equals("原始风速")){
|
||||
map.put("AvgWindSpeed_10min", "原始风速");
|
||||
}else {
|
||||
map.put("AvgWindSpeedCal_10min", "处理后风速");
|
||||
}
|
||||
map.put("AvgActivePower_10min", "功率");
|
||||
map.put("theoryIWindSpeed", "理论风速");
|
||||
map.put("theoryIGenPower", "理论功率");
|
||||
return map;
|
||||
@ -607,6 +652,74 @@ public class StatisticalAnalysisServiceImpl implements StatisticalAnalysisServic
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成散点图,并插入到 Excel 中
|
||||
* @param writer Sheet 对象
|
||||
* @param data 测点数据集合
|
||||
* @param titleText 标题
|
||||
* @param chartKey 类别数据集
|
||||
*/
|
||||
private static void addScattersChartToExcel(ExcelWriter writer, List<Map<String, Object>> data,
|
||||
String titleText, List<String> chartKey) {
|
||||
try {
|
||||
if (CollectionUtils.isEmpty(data)) {
|
||||
return;
|
||||
}
|
||||
// 获取 Sheet 对象
|
||||
XSSFSheet sheet = (XSSFSheet) writer.getSheet();
|
||||
// 创建绘图区域
|
||||
XSSFDrawing drawing = sheet.createDrawingPatriarch();
|
||||
int columnCount = sheet.getRow(0).getPhysicalNumberOfCells() + 1;
|
||||
// 图表位置,插入到最后一列+1
|
||||
ClientAnchor anchor = drawing.createAnchor(0, 0, 0, 0, columnCount, 0, 15, 15);
|
||||
// 创建图表
|
||||
XSSFChart xssfChart = drawing.createChart(anchor);
|
||||
// 设置图表标题
|
||||
xssfChart.setTitleText(titleText);
|
||||
// 创建数据系列
|
||||
XDDFChartLegend legend = xssfChart.getOrAddLegend();
|
||||
legend.setPosition(LegendPosition.TOP_RIGHT);
|
||||
XDDFValueAxis bottomAxis = xssfChart.createValueAxis(AxisPosition.BOTTOM);
|
||||
XDDFValueAxis leftAxis = xssfChart.createValueAxis(AxisPosition.LEFT);
|
||||
leftAxis.setCrossBetween(AxisCrossBetween.BETWEEN);
|
||||
// 创建散点图数据
|
||||
XDDFScatterChartData chartData = (XDDFScatterChartData) xssfChart.createData(ChartTypes.SCATTER, bottomAxis, leftAxis);
|
||||
// 遍历每个系列并添加数据
|
||||
setChartDataForScatter(data, titleText, chartKey, chartData, sheet);
|
||||
// 确保散点图数据点之间不连线
|
||||
for (XDDFChartData.Series series : chartData.getSeries()) {
|
||||
if (series instanceof XDDFScatterChartData.Series) {
|
||||
XDDFScatterChartData.Series scatterSeries = (XDDFScatterChartData.Series) series;
|
||||
scatterSeries.setSmooth(false);
|
||||
scatterSeries.setMarkerStyle(MarkerStyle.CIRCLE);
|
||||
}
|
||||
}
|
||||
xssfChart.plot(chartData);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 为散点图设置数据系列
|
||||
* @param data 测点数据集合
|
||||
* @param titleText 标题
|
||||
* @param chartKey 类别数据集
|
||||
* @param chartData 散点图数据对象
|
||||
* @param sheet Excel Sheet 对象
|
||||
*/
|
||||
private static void setChartDataForScatter(List<Map<String, Object>> data, String titleText, List<String> chartKey,
|
||||
XDDFScatterChartData chartData, XSSFSheet sheet) {
|
||||
for (String key : chartKey) {
|
||||
XDDFDataSource<Double> xAxisData = XDDFDataSourcesFactory.fromNumericCellRange(sheet,
|
||||
new CellRangeAddress(1, data.size(), 0, 0));
|
||||
XDDFNumericalDataSource<Double> yAxisData = XDDFDataSourcesFactory.fromNumericCellRange(sheet,
|
||||
new CellRangeAddress(1, data.size(), chartKey.indexOf(key) + 1, chartKey.indexOf(key) + 1));
|
||||
XDDFScatterChartData.Series series = (XDDFScatterChartData.Series) chartData.addSeries(xAxisData, yAxisData);
|
||||
series.setTitle(key, null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 给每个类别,添加数据
|
||||
* @param data 测点数据
|
||||
@ -661,5 +774,138 @@ public class StatisticalAnalysisServiceImpl implements StatisticalAnalysisServic
|
||||
CellRangeAddress ref = new CellRangeAddress(startRow, endRow, startCol, endCol);
|
||||
return XDDFDataSourcesFactory.fromNumericCellRange(sheet, ref);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 计算平均功率
|
||||
*/
|
||||
public static List<Map<String,List<Double>>> calculateAverages(List<Double> windSpeeds, List<Double> powers) {
|
||||
// 找出最大的风速
|
||||
double maxWindSpeed = Double.MIN_VALUE;
|
||||
for (double windSpeed : windSpeeds) {
|
||||
if (windSpeed > maxWindSpeed) {
|
||||
maxWindSpeed = windSpeed;
|
||||
}
|
||||
}
|
||||
double interval = 0.5;
|
||||
List<Map<String,List<Double>>> result = new ArrayList<>();
|
||||
Map<String,List<Double>> dataMap = new HashMap<>();
|
||||
List<Double> windSpeedList = new ArrayList<>();
|
||||
List<Double> powerList = new ArrayList<>();
|
||||
// 从 0 开始,以 interval 为步长遍历风速
|
||||
for (double windSpeed = 0; windSpeed <= maxWindSpeed; windSpeed += interval) {
|
||||
double sumPower = 0;
|
||||
int count = 0;
|
||||
|
||||
// 遍历输入列表,计算满足风速范围的功率总和和计数
|
||||
for (int i = 0; i < windSpeeds.size(); i++) {
|
||||
double currentWindSpeed = windSpeeds.get(i);
|
||||
double currentPower = powers.get(i);
|
||||
|
||||
if (currentWindSpeed >= windSpeed && currentWindSpeed < windSpeed + interval) {
|
||||
sumPower += currentPower;
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
// 如果计数大于 0,计算平均值并添加到结果列表
|
||||
if (count > 0) {
|
||||
double averagePower = sumPower / count;
|
||||
windSpeedList.add(windSpeed + interval);
|
||||
powerList.add(averagePower);
|
||||
}
|
||||
}
|
||||
dataMap.put("windSpeed", windSpeedList);
|
||||
dataMap.put("power", powerList);
|
||||
result.add(dataMap);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据size删除List<String> value1的值
|
||||
*/
|
||||
@NotNull
|
||||
private static List<String> delTimes(Map.Entry<String, Object> stringObjectEntry, List<Map<String, List<Double>>> maps) {
|
||||
int powerSize = maps.get(0).get("power").size();
|
||||
List<String> value1 = (List<String>) stringObjectEntry.getValue();
|
||||
List<String> collect = IntStream.range(0, value1.size())
|
||||
.filter(i -> i < powerSize)
|
||||
.mapToObj(value1::get)
|
||||
.collect(Collectors.toList());
|
||||
return collect;
|
||||
}
|
||||
|
||||
private static void getPowerCurveValueList(Map<String, Map<String, Map<String, Object>>> resultMap,
|
||||
List<Double> powerList, List<Double> windSpeedList) {
|
||||
for (Map.Entry<String, Map<String, Map<String, Object>>> stringMapEntry : resultMap.entrySet()) {
|
||||
for (Map.Entry<String, Map<String, Object>> mapEntry : stringMapEntry.getValue().entrySet()) {
|
||||
String key = mapEntry.getKey();
|
||||
Map<String, Object> value = mapEntry.getValue();
|
||||
//功率
|
||||
if (key.equals("AvgActivePower_10min")) {
|
||||
for (Map.Entry<String, Object> stringObjectEntry : value.entrySet()) {
|
||||
if (stringObjectEntry.getKey().equals("values")) {
|
||||
List<Float> values = (List<Float>) stringObjectEntry.getValue();
|
||||
List<Double> doubleList = values.stream()
|
||||
.map(Float::doubleValue)
|
||||
.collect(Collectors.toList());
|
||||
powerList.addAll(doubleList);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (key.equals("AvgWindSpeed_10min") || key.equals("AvgWindSpeedCal_10min")){
|
||||
for (Map.Entry<String, Object> stringObjectEntry : value.entrySet()) {
|
||||
if (stringObjectEntry.getKey().equals("values")){
|
||||
List<Float> values = (List<Float>) stringObjectEntry.getValue();
|
||||
List<Double> doubleList = values.stream()
|
||||
.map(Float::doubleValue)
|
||||
.collect(Collectors.toList());
|
||||
windSpeedList.addAll(doubleList);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void setPowerCurveValueList(Map<String, Map<String, Map<String, Object>>> resultMap,
|
||||
List<Map<String, List<Double>>> maps) {
|
||||
if (CollectionUtils.isEmpty(maps)){
|
||||
return;
|
||||
}
|
||||
for (Map.Entry<String, Map<String, Map<String, Object>>> stringMapEntry : resultMap.entrySet()) {
|
||||
for (Map.Entry<String, Map<String, Object>> mapEntry : stringMapEntry.getValue().entrySet()) {
|
||||
String key = mapEntry.getKey();
|
||||
Map<String, Object> value = mapEntry.getValue();
|
||||
//功率
|
||||
if (key.equals("AvgActivePower_10min")) {
|
||||
for (Map.Entry<String, Object> stringObjectEntry : value.entrySet()) {
|
||||
if (stringObjectEntry.getKey().equals("values")) {
|
||||
stringObjectEntry.setValue(maps.get(0).get("power"));
|
||||
}
|
||||
if (stringObjectEntry.getKey().equals("times")){
|
||||
List<String> collect = delTimes(stringObjectEntry, maps);
|
||||
stringObjectEntry.setValue(collect);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (key.equals("AvgWindSpeed_10min") || key.equals("AvgWindSpeedCal_10min")){
|
||||
for (Map.Entry<String, Object> stringObjectEntry : value.entrySet()) {
|
||||
if (stringObjectEntry.getKey().equals("values")){
|
||||
stringObjectEntry.setValue(maps.get(0).get("windSpeed"));
|
||||
}
|
||||
if (stringObjectEntry.getKey().equals("times")){
|
||||
List<String> collect = delTimes(stringObjectEntry, maps);
|
||||
stringObjectEntry.setValue(collect);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user