Java tutorial
/* ************************************************************************************************* * OrganicSmartHome [Version 2.0] is a framework for energy management in intelligent buildings * Copyright (C) 2014 Florian Allerding (florian.allerding@kit.edu) and Kaibin Bao and * Ingo Mauser and Till Schuberth * * * This file is part of the OrganicSmartHome. * * OrganicSmartHome is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free Software Foundation, * either version 3 of the License, or (at your option) any later version. * * OrganicSmartHome is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with OrganicSmartHome. * * If not, see <http://www.gnu.org/licenses/>. * ************************************************************************************************* */ package osh.comdriver.simulation.cruisecontrol; import java.awt.BasicStroke; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Dimension; import java.awt.Stroke; import java.io.BufferedOutputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.util.HashMap; import java.util.List; import java.util.Map.Entry; import javax.swing.JFrame; import javax.swing.JPanel; import org.jfree.chart.ChartFactory; import org.jfree.chart.ChartPanel; import org.jfree.chart.ChartUtilities; import org.jfree.chart.JFreeChart; import org.jfree.chart.StandardChartTheme; import org.jfree.chart.axis.DateAxis; import org.jfree.chart.axis.NumberAxis; import org.jfree.chart.plot.XYPlot; import org.jfree.chart.renderer.xy.StandardXYItemRenderer; import org.jfree.data.xy.XYDataset; import org.jfree.data.xy.XYSeries; import org.jfree.data.xy.XYSeriesCollection; import org.jfree.ui.RectangleInsets; import org.jfree.ui.RefineryUtilities; import osh.datatypes.Commodity; import osh.datatypes.VirtualCommodity; import osh.datatypes.appliance.LoadProfile; import osh.datatypes.appliance.SparseLoadProfile; import osh.datatypes.ea.Schedule; import osh.datatypes.limit.PowerLimitSignal; import osh.datatypes.limit.PriceSignal; /** * * @author Till Schuberth * */ public class ScheduleDrawer extends JPanel { private ChartPanel panel; private static final Dimension preferredSize = new Dimension(500, 270); private static final long serialVersionUID = 1L; private int counter = 0; { // set a theme using the new shadow generator feature available in // 1.0.14 - for backwards compatibility it is not enabled by default ChartFactory.setChartTheme(new StandardChartTheme("JFree/Shadow", true)); } /** * A demonstration application showing how to create a simple time series * chart. This example uses monthly data. * * @param title the frame title. */ public ScheduleDrawer(List<Schedule> schedules, HashMap<VirtualCommodity, PriceSignal> ps, HashMap<VirtualCommodity, PowerLimitSignal> pls, long currentTime) { super(new BorderLayout()); panel = (ChartPanel) createDemoPanel(schedules, ps, pls, currentTime); panel.setPreferredSize(preferredSize); this.add(panel, BorderLayout.CENTER); } /** * CONSTUCTOR */ public ScheduleDrawer() { super(new BorderLayout()); panel = (ChartPanel) createDemoPanel(); panel.setPreferredSize(preferredSize); this.add(panel, BorderLayout.CENTER); } /** * Creates a chart. * * @param dataset1 a dataset. * @return A chart. */ private static JFreeChart createChart(XYDataset dataset1, //power XYDataset dataset2, //costs XYDataset dataset3, long time) { JFreeChart chart = ChartFactory.createTimeSeriesChart("schedule", // title "time", // x-axis label "power", // y-axis label dataset1, // data true, // create legend? true, // generate tooltips? false // generate URLs? ); chart.setBackgroundPaint(Color.white); XYPlot plot = (XYPlot) chart.getPlot(); NumberAxis axis1 = new NumberAxis("power"); NumberAxis axis2 = new NumberAxis("costs"); axis1.setAutoRangeIncludesZero(true); axis1.setUpperBound(5000); axis1.setLowerBound(-5000); axis2.setAutoRangeIncludesZero(true); axis2.setUpperBound(50); axis2.setLowerBound(0); plot.setRangeAxis(0, axis1); plot.setRangeAxis(1, axis2); plot.setDataset(1, dataset2); plot.mapDatasetToRangeAxis(1, 1); plot.setDataset(2, dataset3); plot.mapDatasetToRangeAxis(2, 0); plot.setBackgroundPaint(Color.lightGray); plot.setDomainGridlinePaint(Color.white); plot.setRangeGridlinePaint(Color.white); plot.setAxisOffset(new RectangleInsets(5.0, 5.0, 5.0, 5.0)); plot.setDomainCrosshairVisible(true); plot.setRangeCrosshairVisible(true); //TODO: SHADOWS OFF final StandardXYItemRenderer r1 = new StandardXYItemRenderer(); final StandardXYItemRenderer r2 = new StandardXYItemRenderer(); final StandardXYItemRenderer r3 = new StandardXYItemRenderer(); final StandardXYItemRenderer r4 = new StandardXYItemRenderer(); plot.setRenderer(0, r1); plot.setRenderer(1, r2); plot.setRenderer(2, r3); plot.setRenderer(3, r4); int numberOfSeries = 0; numberOfSeries += dataset1.getSeriesCount(); numberOfSeries += dataset2.getSeriesCount(); numberOfSeries += dataset3.getSeriesCount(); Color[] color = new Color[numberOfSeries]; for (int i = 0; i < numberOfSeries / 2; i++) { color[i] = Color.getHSBColor(i * 1.0f / (numberOfSeries / 2), 1.0f, 1.0f); } int i = 0; for (int j = 0; j < dataset1.getSeriesCount() / 2; j++) { float[] rgbcolor = Color.RGBtoHSB(color[i].getRed(), color[i].getGreen(), color[i].getBlue(), null); plot.getRendererForDataset(dataset1).setSeriesPaint(2 * j, Color.getHSBColor(rgbcolor[0], 1.0f, 1.0f)); plot.getRendererForDataset(dataset1).setSeriesPaint(2 * j + 1, Color.getHSBColor(rgbcolor[0], 1.0f, 0.6f)); i++; } for (int j = 0; j < dataset2.getSeriesCount() / 2; j++) { float[] rgbcolor = Color.RGBtoHSB(color[i].getRed(), color[i].getGreen(), color[i].getBlue(), null); plot.getRendererForDataset(dataset2).setSeriesPaint(2 * j, Color.getHSBColor(rgbcolor[0], 1.0f, 1.0f)); plot.getRendererForDataset(dataset2).setSeriesPaint(2 * j + 1, Color.getHSBColor(rgbcolor[0], 1.0f, 0.6f)); i++; } for (int j = 0; j < dataset3.getSeriesCount() / 2; j++) { float[] rgbcolor = Color.RGBtoHSB(color[i].getRed(), color[i].getGreen(), color[i].getBlue(), null); plot.getRendererForDataset(dataset3).setSeriesPaint(2 * j, Color.getHSBColor(rgbcolor[0], 1.0f, 1.0f)); plot.getRendererForDataset(dataset3).setSeriesPaint(2 * j + 1, Color.getHSBColor(rgbcolor[0], 1.0f, 0.6f)); i++; } // NOW line double upperBound = plot.getRangeAxis(1).getUpperBound(); double lowerBound = plot.getRangeAxis(1).getLowerBound(); XYSeries nowLine = new XYSeries("now"); nowLine.add(time * 1000, lowerBound); nowLine.add(time * 1000, upperBound); XYSeriesCollection nowColl = new XYSeriesCollection(); //power axis nowColl.addSeries(nowLine); XYDataset nowSet = nowColl; plot.setDataset(3, nowSet); plot.mapDatasetToRangeAxis(3, 1); plot.getRendererForDataset(nowSet).setSeriesPaint(0, Color.DARK_GRAY); plot.getRendererForDataset(nowSet).setSeriesStroke(0, (Stroke) new BasicStroke(2.0f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND, 1.0f, new float[] { 6.0f, 6.0f }, 0.0f)); plot.setDomainAxis(new DateAxis()); plot.getDomainAxis().setAutoRange(false); long begin = (time / 86400) * 86400 * 1000; //beginning of day long end = begin + 86400 * 2 * 1000; plot.getDomainAxis().setRange(begin, end); return chart; } /** * Creates a dataset, consisting of two series of monthly data. * * @return The dataset. */ private static XYDataset[] createDataset(List<Schedule> schedules, HashMap<VirtualCommodity, PriceSignal> ps, HashMap<VirtualCommodity, PowerLimitSignal> pls, long currentTime) { XYSeriesCollection dataset1 = new XYSeriesCollection(); //power axis if (pls != null) { for (Entry<VirtualCommodity, PowerLimitSignal> e : pls.entrySet()) { long time = (long) ((currentTime / 86400.0) * 86400); PowerLimitSignal currentPls = e.getValue(); XYSeries upperLimit = new XYSeries(e.getKey().getCommodity() + "_upper_limit"); XYSeries lowerLimit = new XYSeries(e.getKey().getCommodity() + "_lower_limit"); while (currentPls != null && currentPls.getNextPowerLimitChange(time) != null) { upperLimit.add(time * 1000, currentPls.getPowerUpperLimit(time)); lowerLimit.add(time * 1000, currentPls.getPowerLowerLimit(time)); time = currentPls.getNextPowerLimitChange(time); upperLimit.add((time - 1) * 1000, currentPls.getPowerUpperLimit(time - 1)); lowerLimit.add((time - 1) * 1000, currentPls.getPowerLowerLimit(time - 1)); } dataset1.addSeries(upperLimit); dataset1.addSeries(lowerLimit); } } XYSeriesCollection dataset2 = new XYSeriesCollection(); //costs axis if (ps != null) { for (Entry<VirtualCommodity, PriceSignal> e : ps.entrySet()) { long time = (long) ((currentTime / 86400.0) * 86400); PriceSignal currentPs = e.getValue(); XYSeries currentxySeries = new XYSeries(e.getKey().getCommodity() + "_price"); while (currentPs != null && currentPs.getNextPriceChange(time) != null) { currentxySeries.add(time * 1000, currentPs.getPrice(time)); time = currentPs.getNextPriceChange(time); currentxySeries.add((time - 1) * 1000, currentPs.getPrice(time - 1)); } dataset2.addSeries(currentxySeries); } } XYSeriesCollection dataset3 = new XYSeriesCollection(); if (schedules != null) { int cntr = 1; SparseLoadProfile powerSum = new SparseLoadProfile(); if (schedules != null) { for (Schedule i : schedules) { XYSeries[] powerProfile = (XYSeries[]) renderSeries(i.getProfile(), Integer.toString(cntr++), currentTime); for (int j = 0; j < powerProfile.length; j++) { dataset3.addSeries(powerProfile[j]); } powerSum = (SparseLoadProfile) powerSum.merge(i.getProfile(), 0); } } XYSeries[] powerProfileSum = (XYSeries[]) renderSeries(powerSum, "sum", currentTime); for (int j = 0; j < powerProfileSum.length; j++) { dataset3.addSeries(powerProfileSum[j]); } } return new XYDataset[] { dataset1, dataset2, dataset3 }; } private static XYSeries[] renderSeries(LoadProfile i, String name, long currentTime) { XYSeries[] profileSeries = new XYSeries[2]; profileSeries[0] = new XYSeries(name + "_P"); profileSeries[1] = new XYSeries(name + "_Q"); long time = (long) ((currentTime / 86400.0) * 86400); while (i.getNextLoadChange(Commodity.ACTIVEPOWER, time) != null) { profileSeries[0].add(time * 1000, i.getLoadAt(Commodity.ACTIVEPOWER, time)); time = i.getNextLoadChange(Commodity.ACTIVEPOWER, time); profileSeries[0].add((time - 1) * 1000, i.getLoadAt(Commodity.ACTIVEPOWER, time - 1)); } if (time < i.getEndingTimeOfProfile() - 1) { profileSeries[0].add(time * 1000, i.getLoadAt(Commodity.ACTIVEPOWER, time)); } profileSeries[0].add((i.getEndingTimeOfProfile() - 1) * 1000, i.getLoadAt(Commodity.ACTIVEPOWER, i.getEndingTimeOfProfile() - 1)); profileSeries[0].add(i.getEndingTimeOfProfile() * 1000, 0); time = (long) ((currentTime / 86400.0) * 86400); while (i.getNextLoadChange(Commodity.REACTIVEPOWER, time) != null) { profileSeries[1].add(time * 1000, i.getLoadAt(Commodity.REACTIVEPOWER, time)); time = i.getNextLoadChange(Commodity.REACTIVEPOWER, time); profileSeries[1].add((time - 1) * 1000, i.getLoadAt(Commodity.REACTIVEPOWER, time - 1)); } if (time < i.getEndingTimeOfProfile() - 1) { profileSeries[1].add(time * 1000, i.getLoadAt(Commodity.REACTIVEPOWER, time)); } profileSeries[1].add((i.getEndingTimeOfProfile() - 1) * 1000, i.getLoadAt(Commodity.REACTIVEPOWER, i.getEndingTimeOfProfile() - 1)); profileSeries[1].add(i.getEndingTimeOfProfile() * 1000, 0); return profileSeries; } /** * Creates a panel for the demo (used by SuperDemo.java). * * @return A panel. */ private static ChartPanel createDemoPanel(List<Schedule> schedules, HashMap<VirtualCommodity, PriceSignal> ps, HashMap<VirtualCommodity, PowerLimitSignal> pls, long currentTime) { ChartPanel panel = new ChartPanel(createStuffForPanel(schedules, ps, pls, currentTime)); panel.setFillZoomRectangle(true); panel.setMouseWheelEnabled(true); return panel; } private static ChartPanel createDemoPanel() { ChartPanel panel = new ChartPanel(createStuffForPanel()); panel.setFillZoomRectangle(true); panel.setMouseWheelEnabled(true); return panel; } @SuppressWarnings("unused") private static void showSchedule(List<Schedule> schedules, HashMap<VirtualCommodity, PriceSignal> ps, HashMap<VirtualCommodity, PowerLimitSignal> pls, long currentTime) { ScheduleDrawer demo = new ScheduleDrawer(schedules, ps, pls, currentTime); JFrame frame = new JFrame("Schedule"); frame.setContentPane(demo); frame.pack(); RefineryUtilities.centerFrameOnScreen(frame); frame.setVisible(true); } public static void showScheduleAndWait(List<Schedule> schedules, HashMap<VirtualCommodity, PriceSignal> ps, HashMap<VirtualCommodity, PowerLimitSignal> pls, long currentTime) { final Object sync = new Object(); ScheduleDrawer demo = new ScheduleDrawer(schedules, ps, pls, currentTime); JFrame frame = new JFrame("Schedule"); frame.setContentPane(demo); frame.pack(); RefineryUtilities.centerFrameOnScreen(frame); frame.setVisible(true); synchronized (sync) { try { sync.wait(); } catch (InterruptedException e) { } } frame.dispose(); } public void refreshDiagram(List<Schedule> schedules, HashMap<VirtualCommodity, PriceSignal> ps, HashMap<VirtualCommodity, PowerLimitSignal> pls, long time, boolean saveGraph) { JFreeChart chart = createStuffForPanel(schedules, ps, pls, time); if (!saveGraph) { panel.setChart(chart); } else { BufferedOutputStream out; try { out = new BufferedOutputStream(new FileOutputStream("logs/graphic_" + counter + ".png")); ChartUtilities.writeChartAsPNG(out, chart, 1024, 768); out.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } counter++; } } private static JFreeChart createStuffForPanel(List<Schedule> schedules, HashMap<VirtualCommodity, PriceSignal> ps, HashMap<VirtualCommodity, PowerLimitSignal> pls, long time) { XYDataset[] datasets = createDataset(schedules, ps, pls, time); JFreeChart chart = createChart(datasets[0], datasets[1], datasets[2], time); return chart; } private static JFreeChart createStuffForPanel() { return createChart(new XYSeriesCollection(), new XYSeriesCollection(), new XYSeriesCollection(), 0L); } public void updateTime(long timestamp) { // } }