package ui.view; import java.awt.BasicStroke; import java.awt.Color; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Image; import java.awt.RenderingHints; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.geom.GeneralPath; import java.util.ArrayList; import javax.swing.ImageIcon; import javax.swing.JPanel; import javax.swing.Timer; import classes.HolonElement; import classes.HolonObject; import classes.HolonSwitch; import classes.TrackedDataSet; import ui.controller.Control; import ui.model.Model; public class StatisticGraph extends JPanel { /** * */ private static final long serialVersionUID = 1L; // Maximum y Value double maximum = 0; // is the Simulation running? private boolean isSimRunning; // model and controller private Model model; private Control controller; // Graphics2D private Graphics2D g2; GeneralPath path = new GeneralPath(); // Data public ArrayList objects = new ArrayList<>(); /** * Constructor. * * @param model * the Model * @param control * the Controller */ public StatisticGraph(final Model model, Control control) { this.controller = control; this.model = model; this.setBackground(Color.WHITE); } /** * Paints all Components on the Canvas. * * @param g * Graphics * */ public void paintComponent(Graphics g) { super.paintComponent(g); // Graphics2D init g2 = (Graphics2D) g; RenderingHints rh = new RenderingHints(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); g2.setRenderingHints(rh); // Paint the Grid g2.setStroke(new BasicStroke(0)); g2.setColor(Color.BLACK); for (int i = 0; i <= this.getWidth(); i += 10) { g2.drawLine(i, 0, i, this.getHeight()); } for (int i = 0; i <= this.getHeight(); i += 5) { g2.drawLine(0, i, this.getWidth(), i); } isSimRunning = model.getIsSimulation(); // if sim is on if (isSimRunning) { g2.setStroke(new BasicStroke(3)); // Calculate the Maximum calcMaximum(); // Calculate values for each set and add them addValues(); // Create Paths and draw them for (TrackedDataSet set : objects) { path.reset(); switch (set.getProperty()) { case TrackedDataSet.CONSUMPTION: case TrackedDataSet.PRODUCTION: case TrackedDataSet.ACTIVATED_ELEMENTS: case TrackedDataSet.TOTAL_PRODUCTION: case TrackedDataSet.TOTAL_CONSUMPTION: createPathFloats(set); break; case TrackedDataSet.ON_OFF: createPathBooleans(set); break; case TrackedDataSet.PERCENT_SUPPLIED: case TrackedDataSet.PERCENT_NOT_SUPPLIED: case TrackedDataSet.PERCENT_PARTIAL_SUPPLIED: //TODO Percentage Method break; default: break; } g2.setColor(set.getColor()); g2.draw(path); } } } /** * Add an Object to the Graph if the maximum has not reached yet. * * @param obj * the Object to add */ public void addObject(TrackedDataSet set) { objects.add(set); } /** * Removes an Object from the Graph. * * @param id * the id of the Object to remove */ public void removeObject(int id) { objects.remove(id); } /** * converts the number to fit the canvas. * * @param d * the number to convert * @return the converted number */ public double convertToCanvasY(float d) { return Math.abs((this.getHeight() - (d * (this.getHeight() / maximum)))); } /** * Does take into account which timestep is watched, calculates the max * values. * * @return the currentEnergy */ public float getEnergyAtCurrentTimeStep(HolonObject obj) { float temp = 0; for (HolonElement e : obj.getElements()) { if (e.getActive()) { temp = temp + e.getEnergyAt()[model.getCurIteration()]; } } return temp; } /** * Calculate the Max Value of the Graph */ public void calcMaximum() { maximum = 0; for (TrackedDataSet set : objects) { int val = 0; switch (set.getProperty()) { case TrackedDataSet.CONSUMPTION: for (HolonElement h : ((HolonObject) set.getCpsObject()).getElements()) { if (h.getEnergy() < 0) { val += h.getEnergy() * h.getAmount(); } } val *= -1; break; case TrackedDataSet.PRODUCTION: for (HolonElement h : ((HolonObject) set.getCpsObject()).getElements()) { if (h.getEnergy() > 0) { val += h.getEnergy() * h.getAmount(); } } break; case TrackedDataSet.ACTIVATED_ELEMENTS: for (HolonElement h : ((HolonObject) set.getCpsObject()).getElements()) { val += h.getAmount(); } break; case TrackedDataSet.ON_OFF: val = 1; break; case TrackedDataSet.TOTAL_PRODUCTION: //TODO break; case TrackedDataSet.TOTAL_CONSUMPTION: //TODO break; case TrackedDataSet.PERCENT_SUPPLIED: case TrackedDataSet.PERCENT_NOT_SUPPLIED: case TrackedDataSet.PERCENT_PARTIAL_SUPPLIED: val = 1; break; default: break; } if (val > maximum) { maximum = val; } } ((StatisticGraphPanel) this.getParent()).setMaximumLabel(maximum); } /** * Add the Current Values to each set */ private void addValues() { for (TrackedDataSet set : objects) { int val = 0; switch (set.getProperty()) { case TrackedDataSet.CONSUMPTION: for (HolonElement h : ((HolonObject) set.getCpsObject()).getElements()) { if (h.getEnergy() < 0 && h.getActive()) { val += Math.abs(h.getEnergyAt()[model.getCurIteration()]) * h.getAmount(); } set.setValAt(val, model.getCurIteration()); } break; case TrackedDataSet.PRODUCTION: for (HolonElement h : ((HolonObject) set.getCpsObject()).getElements()) { if (h.getEnergy() > 0 && h.getActive()) { val += Math.abs(h.getEnergyAt()[model.getCurIteration()]) * h.getAmount(); } set.setValAt(val, model.getCurIteration()); } break; case TrackedDataSet.ACTIVATED_ELEMENTS: for (HolonElement h : ((HolonObject) set.getCpsObject()).getElements()) { if (h.getActive()) { val += h.getAmount(); } set.setValAt(val, model.getCurIteration()); } break; case TrackedDataSet.ON_OFF: if (((HolonSwitch) set.getCpsObject()).getManualMode()) { if (((HolonSwitch) set.getCpsObject()).getActiveManual()) { set.setValAt(1, model.getCurIteration()); } else { set.setValAt(0, model.getCurIteration()); } } else { if (((HolonSwitch) set.getCpsObject()).getActiveAt()[model.getCurIteration()]) { set.setValAt(1, model.getCurIteration()); } else { set.setValAt(0, model.getCurIteration()); } } break; case TrackedDataSet.TOTAL_PRODUCTION: break; case TrackedDataSet.TOTAL_CONSUMPTION: break; case TrackedDataSet.PERCENT_SUPPLIED: break; case TrackedDataSet.PERCENT_NOT_SUPPLIED: break; case TrackedDataSet.PERCENT_PARTIAL_SUPPLIED: break; default: break; } } } /** * create Path with floats * * @param set */ private void createPathFloats(TrackedDataSet set) { boolean init = true; path.moveTo(0, 0); for (int i = 0; i < model.getCurIteration(); i++) { if (init && set.getValues()[i] != -1) { path.moveTo(i * this.getWidth() / model.getIterations() - 1, convertToCanvasY(set.getValues()[i])); init = false; } if (!init) { if (set.getValues()[i + 1] != -1) { path.lineTo((i + 1) * this.getWidth() / model.getIterations(), convertToCanvasY(set.getValues()[i + 1])); } else { break; } } } } /** * create Path with booleans(0 and 1) * * @param set */ private void createPathBooleans(TrackedDataSet set) { boolean init = true; for (int i = 0; i < model.getCurIteration(); i++) { if (init && set.getValues()[i] != -1) { path.moveTo(i * this.getWidth() / model.getIterations() - 1, convertToCanvasY((float) (set.getValues()[i] * maximum))); init = false; } if (!init) { if (set.getValues()[i + 1] != -1) { path.lineTo((i + 1) * this.getWidth() / model.getIterations(), convertToCanvasY((float) (set.getValues()[i + 1] * maximum))); } else { break; } } } } }