package com.rk.energy5.util;
import com.rk.energy5.core.SystemConstant;
import com.rk.energy5.core.exception.BaseException;
import com.rk.energy5.core.exception.BaseExceptionEnum;
import com.rk.energy5.entity.DiagramItem;
import com.rk.energy5.entity.historian.DiagramPoint;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.io.IOUtils;
import org.jfree.chart.*;
import org.jfree.chart.axis.*;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.XYItemRenderer;
import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;
import org.jfree.data.time.Minute;
import org.jfree.data.time.TimeSeries;
import org.jfree.data.time.TimeSeriesCollection;
import org.jfree.data.xy.XYDataset;
import org.jfree.ui.RectangleInsets;
import org.springframework.stereotype.Component;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.List;
import java.util.stream.Collectors;
@Component
public class TimeSeriesUtils {
private static String logoPicture;
private static float backGroundAlpha = 0.001f;
private static int PPTWidth = 1120;
private static int PPTHeight = 630;
private static int ExcelWidth = 1120;
private static int ExcelHeight = 630;
private static int rightPadding = 50;
private static int leftPadding = 25;
private static int topAndBottomPadding = 12;
private static final Color red = new Color(255, 0, 0);
private static final Color yellow = new Color(228, 216, 0);
private static final Color cyan = new Color(5, 156, 126);
private static final Color green_stander = new Color(0, 255, 0);
private static final Color blue = new Color(0, 0, 255);
private static final Color black = new Color(0, 0, 0);
private static final Color brown = new Color(94, 38, 18);
private static final Color pansy = new Color(138, 43, 226);
private static final Color cobalt = new Color(61, 89, 171);
private static final Color strawberry = new Color(135, 38, 87);
private static final Color chocolate = new Color(205, 107, 29);
private static final Color magenta = new Color(255, 0, 255);
private static final Color green = new Color(110, 139, 61);
private static final Color darkCyan = new Color(64, 109, 112);
private static Color[] colorOfLineSeries = new Color[10];
private static String[] limitNames = new String[4];
public static String[] lineOfSPCTarget = new String[6];
private static Map<String, Color> colorMap = new HashMap<>();
public TimeSeriesUtils() {
lineOfSPCTarget[0] = "XBAR_USL";
lineOfSPCTarget[1] = "XBAR_UCL";
lineOfSPCTarget[2] = "XBAR_LCL";
lineOfSPCTarget[3] = "XBAR_LSL";
lineOfSPCTarget[4] = "XBB";
lineOfSPCTarget[5] = "SampleMean";
limitNames[0] = "USL";
limitNames[1] = "UCL";
limitNames[2] = "LCL";
limitNames[3] = "LSL";
colorOfLineSeries[0] = blue;
colorOfLineSeries[1] = pansy;
colorOfLineSeries[2] = black;
colorOfLineSeries[3] = strawberry;
colorOfLineSeries[4] = brown;
colorOfLineSeries[5] = chocolate;
colorOfLineSeries[6] = magenta;
colorOfLineSeries[7] = cyan;
colorOfLineSeries[8] = cobalt;
colorOfLineSeries[9] = green;
for (int i = 0; i < 4; i++) {
colorMap.put(limitNames[i], i == 0 || i == 3 ? red : yellow);
}
}
public static synchronized byte[] getByte(DiagramItem item, Map<String, List<DiagramPoint>> lines, Calendar nowCal) {
Calendar start = getStart(item, nowCal);
repairLine(lines, getDefault(item));
addLimitValue(item, lines, start, nowCal);
XYDataset xydataset = createDataset(lines);
JFreeChart jfreechart = createLineChartByTimeStampDIY(xydataset, item.getGroupName(), getS2E(start, nowCal), start, nowCal, item.getLsl().doubleValue(), item.getUsl().doubleValue());
XYPlot plot = (XYPlot) jfreechart.getPlot();
plot.setBackgroundAlpha(backGroundAlpha);
renderBold(plot.getRenderer(), lines.size());
XYLineAndShapeRenderer xyLineRender = (XYLineAndShapeRenderer) plot.getRenderer();
paintRender(xyLineRender, getColors(item));
return saveAsByte(jfreechart, "PPT", 1120, 630);
}
private static String getDefault(DiagramItem item) {
if (item.getUcl() != null && item.getLcl() != null)
return item.getUcl().subtract(item.getLcl()).subtract(new BigDecimal(2)).add(item.getLcl()).toString();
if (item.getUsl() != null && item.getLsl() != null)
return item.getUsl().subtract(item.getLsl()).subtract(new BigDecimal(2)).add(item.getLsl()).toString();
throw new BaseException(BaseExceptionEnum.ILLEGAL_ARGUMENT, "上下限缺失,无法绘制曲线!");
}
private static Map<String, Color> getColors(Set<String> lineNames) {
Map<String, Color> lineColors = new HashMap<>();
for (String name : lineNames) {
switch (name.substring(name.lastIndexOf(".") + 1)) {
case "XBAR_USL":
lineColors.put("XBAR_USL", red);
break;
case "XBAR_UCL":
lineColors.put("XBAR_UCL", yellow);
break;
case "XBAR_LCL":
lineColors.put("XBAR_LCL", yellow);
break;
case "XBAR_LSL":
lineColors.put("XBAR_LSL", red);
break;
case "XBB":
lineColors.put("XBB", green_stander);
break;
case "SampleMean":
lineColors.put("SampleMean", blue);
break;
}
}
return lineColors;
}
private static Map<String, Color> getColors(DiagramItem item) {
Map<String, Color> tagNameColorMap = new HashMap<>();
int index = 0;
for (String name : item.getTagNameGroup().split(",")) {
if (index < 10)
tagNameColorMap.put(name, colorOfLineSeries[index++]);
else
tagNameColorMap.put(name, getRandomColor());
}
tagNameColorMap.putAll(colorMap);
return tagNameColorMap;
}
private static Color getRandomColor() {
Random rand = new Random();
float r = rand.nextFloat();
float g = rand.nextFloat();
float b = rand.nextFloat();
return new Color(r, g, b);
}
private static Calendar getStart(DiagramItem item, Calendar nowCal) {
Calendar start = Calendar.getInstance();
start.setTimeInMillis(nowCal.getTimeInMillis());
start.add(Calendar.DAY_OF_MONTH, -item.getDaySpan());
return start;
}
private static String getS2E(Calendar start, Calendar nowCal) {
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(nowCal.getTimeInMillis());
return SystemConstant.dayFormat.format(start.getTime()) + "至" + SystemConstant.dayFormat.format(calendar.getTime());
}
private static void addLimitValue(DiagramItem item, Map<String, List<DiagramPoint>> lines, Calendar start, Calendar nowCal) {
BigDecimal[] limitValues = new BigDecimal[4];
limitValues[0] = item.getUsl();
limitValues[1] = item.getUcl();
limitValues[2] = item.getLcl();
limitValues[3] = item.getLsl();
for (int i = 0; i < 4; i++) {
List<DiagramPoint> diagramPoints = new ArrayList<>();
DiagramPoint diagramPointStart = new DiagramPoint();
diagramPointStart.setTagName(limitNames[i]);
diagramPointStart.setValue(limitValues[i].toString());
diagramPointStart.setTime(start.getTime());
diagramPoints.add(diagramPointStart);
DiagramPoint diagramPointEnd = new DiagramPoint();
diagramPointEnd.setTagName(limitNames[i]);
diagramPointEnd.setValue(limitValues[i].toString());
diagramPointEnd.setTime(nowCal.getTime());
diagramPoints.add(diagramPointEnd);
lines.put(limitNames[i], diagramPoints);
}
}
public static synchronized byte[] getByte(DiagramItem item, Map<String, List<DiagramPoint>> lines, Calendar nowCal, String watermark) {
if (watermark == null || "".equals(watermark))
return getByte(item, lines, nowCal, watermark);
else
return addImageLogo(getByte(item, lines, nowCal), watermark);
}
public static byte[] getSPCByte(String p, Map<String, List<DiagramPoint>> diagramPointMap, String S2EStr) {
XYDataset xydataset = createDataset(diagramPointMap);
JFreeChart jfreechart = createSPCChart(xydataset, p, S2EStr);
XYPlot plot = (XYPlot) jfreechart.getPlot();
plot.setBackgroundAlpha(backGroundAlpha);
renderBold(plot.getRenderer(), diagramPointMap.size());
XYLineAndShapeRenderer xyLineRender = (XYLineAndShapeRenderer) plot.getRenderer();
paintRender(xyLineRender, getColors(diagramPointMap.keySet()));
return saveAsByte(jfreechart, "EXCEL", 1120, 630);
}
public static byte[] getSPCByte(String p, Map<String, List<DiagramPoint>> diagramPointMap, String S2EStr, String watermark) {
if (watermark == null || "".equals(watermark))
return getSPCByte(p, diagramPointMap, S2EStr, watermark);
else
return addImageLogo(getSPCByte(p, diagramPointMap, S2EStr), watermark);
}
/**
* 把因为通讯质量为bad的曲线,用前后数据填补过来(需求来源:长存一期)
* @param lines
* @param defaultValue
*/
private static void repairLine(Map<String, List<DiagramPoint>> lines, String defaultValue) {
lines.forEach((k, v) -> {
if (v.stream().anyMatch(p -> p.getQuality() == 1)) {
Boolean foreboding = null; // 是否为先序
if (v.get(0) != null && v.get(0).getQuality() == 0)
foreboding = true;
if (foreboding == null && v.get(v.size() - 1) != null && v.get(v.size() - 1).getQuality() == 0)
foreboding = false;
if (foreboding == null) {
v.forEach(p -> p.setValue(defaultValue));
} else if (foreboding) {
for (int i = 0; i < v.size(); i++) {
if (v.get(i).getQuality() == 1) {
v.get(i).setValue(v.get(i-1).getValue());
}
}
} else {
for (int i = v.size()-1; i >= 0; i--) {
if (v.get(i).getQuality() == 1) {
v.get(i).setValue(v.get(i+1).getValue());
}
}
}
}
});
}
private static byte[] addImageLogo(byte[] picture, String watermark) {
if (picture != null && picture.length > 0) {
BufferedImage bufferedImage = null;
ByteArrayOutputStream byteArrayOutputStream = null;
try {
ByteArrayInputStream in = new ByteArrayInputStream(picture);
Image image = ImageIO.read(in);
int width = image.getWidth(null);
int height = image.getHeight(null);
bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
Graphics2D graphics2D = bufferedImage.createGraphics();
graphics2D.drawImage(image, 0, 0, width, height, null);
byte[] logo = Base64.decodeBase64(watermark);
ByteArrayInputStream logoIn = new ByteArrayInputStream(logo);
Image logoImage = ImageIO.read(logoIn);
int logoWidth = logoImage.getWidth(null);
int logoHeight = logoImage.getHeight(null);
graphics2D.drawImage(logoImage, 0, 0, logoWidth, logoHeight, null);
graphics2D.dispose();
byteArrayOutputStream = new ByteArrayOutputStream();
ImageIO.write(bufferedImage, "png", byteArrayOutputStream);
return byteArrayOutputStream.toByteArray();
} catch (Exception e) {
e.printStackTrace();
} finally {
if (bufferedImage != null) {
bufferedImage.flush();
bufferedImage = null;
}
IOUtils.closeQuietly(byteArrayOutputStream);
System.gc();
}
}
return picture;
}
private static void renderBold(XYItemRenderer renderer, int loop) {
for (int i = 0; i < loop; i++)
renderer.setSeriesStroke(i, new BasicStroke(1.0f));
}
private static void paintRender(XYLineAndShapeRenderer xyLineRender, Map<String, Color> lineColors) {
for (int i = 0; i < lineColors.size(); i++) {
LegendItem legendItem = xyLineRender.getLegendItem(0, i);
String label = legendItem.getLabel();
for (Map.Entry<String, Color> entry : lineColors.entrySet()) {
if (label.contains(entry.getKey()))
xyLineRender.setSeriesPaint(i, lineColors.get(entry.getKey()));
}
}
}
private static byte[] saveAsByte(JFreeChart chart, String sizeType, int weight, int height) {
ByteArrayOutputStream out = new ByteArrayOutputStream();
int _weight;
int _height;
try {
if ("PPT".equals(sizeType)) {
_weight = weight == 0 ? PPTWidth : weight;
_height = height == 0 ? PPTHeight : height;
ChartUtilities.writeChartAsPNG(out, chart, _weight, _height);//16:9 1120 630
} else if ("EXCEL".equals(sizeType)) {
_weight = weight == 0 ? ExcelWidth : weight;
_height = height == 0 ? ExcelHeight : height;
ChartUtilities.writeChartAsPNG(out, chart, _weight, _height);//16:9 1120 630
}
out.flush();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return out.toByteArray();
}
private static JFreeChart createLineChartByTimeStampDIY(XYDataset xydataset, String lineGroupName, String dateOfBeginToEnd, Calendar beginCal, Calendar endCal, double lower, double upper) {
// 创建主题样式
StandardChartTheme standardChartTheme = new StandardChartTheme("CN");
// 设置标题字体
standardChartTheme.setExtraLargeFont(new Font("宋书", Font.BOLD, 20));
// 设置图例的字体
standardChartTheme.setRegularFont(new Font("宋书", Font.PLAIN, 15));
// 设置轴向的字体
standardChartTheme.setLargeFont(new Font("宋书", Font.PLAIN, 15));
ChartFactory.setChartTheme(standardChartTheme);// 应用主题样式
JFreeChart jfreechart = ChartFactory.createTimeSeriesChart(
lineGroupName + " (" + dateOfBeginToEnd + ")",
null,
null,
xydataset,
true,
true,
false);
jfreechart.setPadding(new RectangleInsets(topAndBottomPadding, leftPadding, topAndBottomPadding, rightPadding));
XYPlot xyplot = jfreechart.getXYPlot();
ValueAxis valueAxis = xyplot.getRangeAxis();
double padding = (upper - lower) * 0.1;
valueAxis.setRange(lower - padding, upper + padding);
DateAxis dateAxis = (DateAxis) xyplot.getDomainAxis();
dateAxis.setLowerBound(beginCal.getTimeInMillis());
dateAxis.setUpperBound(endCal.getTimeInMillis());
if (endCal.getTimeInMillis() - beginCal.getTimeInMillis() <= 600000) {
dateAxis.setTickUnit(new DateTickUnit(DateTickUnitType.MINUTE, 1));
dateAxis.setDateFormatOverride(new SimpleDateFormat("HH:mm"));
} else if (endCal.getTimeInMillis() - beginCal.getTimeInMillis() <= 1800000) {
dateAxis.setTickUnit(new DateTickUnit(DateTickUnitType.MINUTE, 3));
dateAxis.setDateFormatOverride(new SimpleDateFormat("HH:mm"));
} else if (endCal.getTimeInMillis() - beginCal.getTimeInMillis() <= 3600000) {
dateAxis.setTickUnit(new DateTickUnit(DateTickUnitType.MINUTE, 4));
dateAxis.setDateFormatOverride(new SimpleDateFormat("HH:mm"));
} else if (endCal.getTimeInMillis() - beginCal.getTimeInMillis() <= 43200000) {
dateAxis.setTickUnit(new DateTickUnit(DateTickUnitType.HOUR, 1));
dateAxis.setDateFormatOverride(new SimpleDateFormat("HH:mm"));
} else if (endCal.getTimeInMillis() - beginCal.getTimeInMillis() <= 86400000) {
dateAxis.setTickUnit(new DateTickUnit(DateTickUnitType.HOUR, 6));
dateAxis.setDateFormatOverride(new SimpleDateFormat("M月d号 HH:mm"));
} else if (endCal.getTimeInMillis() - beginCal.getTimeInMillis() <= 259200000) {
dateAxis.setTickUnit(new DateTickUnit(DateTickUnitType.HOUR, 12));
dateAxis.setDateFormatOverride(new SimpleDateFormat("MM-dd HH:mm"));
} else if (endCal.getTimeInMillis() - beginCal.getTimeInMillis() <= 604800000) {
dateAxis.setTickUnit(new DateTickUnit(DateTickUnitType.DAY, 1));
dateAxis.setDateFormatOverride(new SimpleDateFormat("MM/dd"));
} else {
dateAxis.setTickUnit(new DateTickUnit(DateTickUnitType.DAY, 10));
dateAxis.setDateFormatOverride(new SimpleDateFormat("MM/dd"));
}
return jfreechart;
}
private static JFreeChart createSPCChart(XYDataset xydataset, String SPCName, String dateOfBeginToEnd) {
// 创建主题样式
StandardChartTheme standardChartTheme = new StandardChartTheme("CN");
// 设置标题字体
standardChartTheme.setExtraLargeFont(new Font("宋书", Font.BOLD, 20));
// 设置图例的字体
standardChartTheme.setRegularFont(new Font("宋书", Font.PLAIN, 15));
// 设置轴向的字体
standardChartTheme.setLargeFont(new Font("宋书", Font.PLAIN, 15));
ChartFactory.setChartTheme(standardChartTheme);// 应用主题样式
JFreeChart jfreechart = ChartFactory.createTimeSeriesChart(
"Facility OCAP Record Form\n" + SPCName + " (" + dateOfBeginToEnd + ")",
null,
null,
xydataset,
true,
true,
false);
jfreechart.setPadding(new RectangleInsets(topAndBottomPadding, leftPadding, topAndBottomPadding, rightPadding));
Calendar beginCal = Calendar.getInstance();
beginCal.set(Calendar.HOUR_OF_DAY, 0);
beginCal.set(Calendar.MINUTE, 0);
beginCal.set(Calendar.MILLISECOND, 0);
Calendar endCal = Calendar.getInstance();
endCal.setTime(beginCal.getTime());
beginCal.add(Calendar.HOUR_OF_DAY, -17);
endCal.add(Calendar.HOUR_OF_DAY, 7);
XYPlot xyplot = jfreechart.getXYPlot();
DateAxis dateAxis = (DateAxis) xyplot.getDomainAxis();
dateAxis.setLowerBound(beginCal.getTimeInMillis());
dateAxis.setUpperBound(endCal.getTimeInMillis());
dateAxis.setTickUnit(new DateTickUnit(DateTickUnitType.HOUR, 2));
dateAxis.setDateFormatOverride(new SimpleDateFormat("HH:mm"));
return jfreechart;
}
private static XYDataset createDataset(Map<String, List<DiagramPoint>> lines) {
TimeSeriesCollection timeseriescollection = new TimeSeriesCollection();
lines.forEach((k, v) -> {
TimeSeries timeseries = new TimeSeries(k);
v = v.stream().distinct().collect(Collectors.toList());
v.forEach(p -> {
timeseries.addOrUpdate(new Minute(p.getTime()), p.getDValue());
});
timeseriescollection.addSeries(timeseries);
});
return timeseriescollection;
}
private static JFreeChart createLineChart(XYDataset xydataset, String lineGroupName, String dateOfBeginToEnd, int daySize, Calendar end, double lower, double upper) {
// 创建主题样式
StandardChartTheme standardChartTheme = new StandardChartTheme("CN");
// 设置标题字体
standardChartTheme.setExtraLargeFont(new Font("宋书", Font.BOLD, 20));
// 设置图例的字体
standardChartTheme.setRegularFont(new Font("宋书", Font.PLAIN, 15));
// 设置轴向的字体
standardChartTheme.setLargeFont(new Font("宋书", Font.PLAIN, 15));
ChartFactory.setChartTheme(standardChartTheme);// 应用主题样式
JFreeChart jfreechart = ChartFactory.createTimeSeriesChart(
lineGroupName + " (" + dateOfBeginToEnd + ")",
null,
null,
xydataset,
true,
true,
false);
jfreechart.setPadding(new RectangleInsets(topAndBottomPadding, leftPadding, topAndBottomPadding, rightPadding));
XYPlot xyplot = jfreechart.getXYPlot();
ValueAxis valueAxis = xyplot.getRangeAxis();
double padding = (upper - lower) * 0.1;
valueAxis.setRange(lower - padding, upper + padding);
DateAxis dateAxis = (DateAxis) xyplot.getDomainAxis();
Calendar begin = Calendar.getInstance();
begin.setTime(end.getTime());
begin.add(Calendar.DAY_OF_MONTH, -1 * daySize);
dateAxis.setLowerBound(begin.getTimeInMillis());
dateAxis.setUpperBound(end.getTimeInMillis());
switch (daySize) {
case 1:
case 2:
dateAxis.setTickUnit(new DateTickUnit(DateTickUnitType.HOUR, 2));
dateAxis.setDateFormatOverride(new SimpleDateFormat("HH:mm"));
break;
case 3:
case 4:
case 5:
case 6:
dateAxis.setTickUnit(new DateTickUnit(DateTickUnitType.HOUR, 12));
dateAxis.setDateFormatOverride(new SimpleDateFormat("MM/dd HH:mm"));
break;
case 7:
dateAxis.setTickUnit(new DateTickUnit(DateTickUnitType.DAY, 1));
dateAxis.setDateFormatOverride(new SimpleDateFormat("MM-dd"));
break;
case 90:
dateAxis.setTickUnit(new DateTickUnit(DateTickUnitType.DAY, 15));
dateAxis.setDateFormatOverride(new SimpleDateFormat("yyyy/MM/dd"));
break;
default:
dateAxis.setTickUnit(new DateTickUnit(DateTickUnitType.DAY, 1));
dateAxis.setDateFormatOverride(new SimpleDateFormat("MM/dd"));
break;
}
return jfreechart;
}
}
——Cannot resolve symbol 'jfree'是什么意思
最新发布