package ui.controller; import classes.*; import classes.comparator.EnergyMinToMaxComparator; import classes.comparator.MinEnergyComparator; import classes.comparator.WeakestBattery; import ui.model.Model; import ui.view.FlexiblePane; import ui.view.MyCanvas; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; /** * Controller for Simulation. * * @author Gruppe14 */ public class SimulationManager { int global = 0; private Model model; private ArrayList objectsToHandle; // private ArrayList allConnections; private ArrayList subNets; private ArrayList brokenEdges; private MyCanvas canvas; private int timeStep; private HashMap tagTable = new HashMap<>(); private FlexiblePane flexPane; private HashMap flexDevicesTurnedOnThisTurn = new HashMap<>(); /** * One Element of each HolonObject will be powered first, starting with the * smallest Demand. If ale HolonObjects have an active Element, the * simulation will try to fully supply as many HolonObjects as possible. */ public static final short fairnessMininumDemandFirst = 0; /** * All HolonObjects will receive the same amount of energy. */ public static final short fairnessAllEqual = 1; /** * Constructor. * * @param m * Model */ SimulationManager(Model m) { canvas = null; model = m; subNets = new ArrayList<>(); brokenEdges = new ArrayList<>(); } /** * calculates the flow of the edges and the supply for objects. * * @param x * current Iteration */ void calculateStateForTimeStep(int x) { reset(); timeStep = x; searchForSubNets(); for (SubNet singleSubNet : subNets) { if(singleSubNet.getObjects().size() == 0) { resetConnections(singleSubNet.getBatteries().get(0), new ArrayList<>(), new ArrayList<>()); }else { resetConnections(singleSubNet.getObjects().get(0), new ArrayList<>(), new ArrayList<>()); } } for (SubNet singleSubNet : subNets) { float production = calculateEnergyWithoutFlexDevices("prod", singleSubNet, timeStep); float consumption = calculateEnergyWithoutFlexDevices("cons", singleSubNet, timeStep); // surplus of energy is computed by sum, since consumption is a // negative value float energySurplus = production + consumption; //float minConsumption = calculateMinimumEnergy(singleSubNet, timeStep); // --------------- use flexible devices --------------- if (energySurplus != 0 && model.useFlexibleDevices()) { turnOnFlexibleDevices(singleSubNet, energySurplus, x); // if (!flexDevicesTurnedOnThisTurn.isEmpty()) { // System.out.println("The following devices were turned on in this turn: "); // System.out.println(flexDevicesTurnedOnThisTurn.toString()); // } // recompute after having examined/turned on all flexible // devices production = calculateEnergyWithFlexDevices("prod", singleSubNet, timeStep); consumption = calculateEnergyWithFlexDevices("cons", singleSubNet, timeStep); energySurplus = production + consumption; } // --------------- set flow simulation --------------- setFlowSimulation(singleSubNet); // --------------- visualise graph --------------- /** * production of subnets, that might be partially turned on/off */ float currentProduction = production; /** * HolonObjects that can be partially Supplied but might be fully * Supplied */ /* ArrayList partiallySuppliedList = new ArrayList(); /** * HolonObjects that can get the spare energy */ // // ArrayList notSuppliedList = new ArrayList(); /** * Number of HolonObjects that need to be supplied */ // long numberOfConsumers = singleSubNet.getObjects().stream() // .filter(hl -> (hl.getState() != HolonObject.NO_ENERGY // && hl.getState() != HolonObject.PRODUCER && hl // .getConnectedTo().stream() // .filter(e -> (e.getFlow() > 0)).count() > 0)) // .count(); /** * energy each HolonObject receives in AlleEqualModus */ if(energySurplus >= 0) { //Supply all consumer for(HolonObject hO : singleSubNet.getObjects()) { float neededEnergy = hO.getCurrentEnergyAtTimeStep(x); if(neededEnergy < 0) { hO.setCurrentSupply(-neededEnergy); currentProduction -= -neededEnergy; //Subtract the Energy from the Production } } //Supply all Batterys with the left currentProduction singleSubNet.getBatteries().sort(new WeakestBattery(x));//Sort all batteries by the Value of ther StateOfCharge/Capasity for(HolonBattery hB : singleSubNet.getBatteries()) { float energyToCollect = hB.getInAtTimeStep(x-1); if(currentProduction >= energyToCollect) { //change StateofCharge soc = soc + energyToCollect hB.setStateOfChargeAtTimeStep(hB.getStateOfChargeAtTimeStep(x-1) + energyToCollect, x); currentProduction -= energyToCollect; }else { //change StateofCharge soc = soc + currentProduction hB.setStateOfChargeAtTimeStep(hB.getStateOfChargeAtTimeStep(x-1) + currentProduction, x); currentProduction = 0; //no break must be calculatet for all break; //because no more energy } } //Over_Supply all consumer equal long nOConsumer = singleSubNet.getObjects().stream().filter(hl -> (hl.getCurrentEnergyAtTimeStep(x) < 0)).count(); if(nOConsumer != 0) { //energy to seperated equal float EnergyOverSupplyPerHolonObject = currentProduction / nOConsumer; for(HolonObject hO : singleSubNet.getObjects()) { float neededEnergy = hO.getCurrentEnergyAtTimeStep(x); if(neededEnergy < 0) { hO.setCurrentSupply(hO.getCurrentSupply() + EnergyOverSupplyPerHolonObject); } } currentProduction = 0; } } else { //Check all Battries what they can provide if(energySurplus + GetOutAllBatteries(singleSubNet.getBatteries(), x) >= 0) { singleSubNet.getBatteries().sort(new WeakestBattery(x));//.reverse(); Collections.reverse(singleSubNet.getBatteries()); //most supplyed first //Get the NEEDED energy for(HolonBattery hB : singleSubNet.getBatteries()) { float neededEnergyFromBattery = currentProduction + consumption; //Energy is negativ float maxEnergyAvailable = hB.getOutAtTimeStep(x-1); //energy is positiv if(maxEnergyAvailable >= -neededEnergyFromBattery) { //change StateofCharge soc = soc - -neededEnergyFromBattery hB.setStateOfChargeAtTimeStep(hB.getStateOfChargeAtTimeStep(x-1) - -neededEnergyFromBattery, x); currentProduction += -neededEnergyFromBattery; //no break must be calculatet for all beabreak; //When a energy can supply the last needed energy break; } else { //change StateofCharge soc = soc - maxEnergyAvailable hB.setStateOfChargeAtTimeStep(hB.getStateOfChargeAtTimeStep(x-1) - maxEnergyAvailable, x); currentProduction += maxEnergyAvailable; } } //Supply all consumer all ar in state Supplied no one is oversupplied because // just the energy that is needed is gained from the batteries for(HolonObject hO : singleSubNet.getObjects()) { float neededEnergy = hO.getCurrentEnergyAtTimeStep(x); if(neededEnergy < 0) { hO.setCurrentSupply(-neededEnergy); currentProduction -= -neededEnergy; //Subtract the Energy from the Production } } } else //Objects have to be partially supplied { //Get all Energy out of battries as possible for(HolonBattery hB : singleSubNet.getBatteries()) { float maxEnergyAvailable = hB.getOutAtTimeStep(x-1); //energy is positiv //change StateofCharge soc = soc - maxEnergyAvailable hB.setStateOfChargeAtTimeStep(hB.getStateOfChargeAtTimeStep(x-1) - maxEnergyAvailable, x); currentProduction += maxEnergyAvailable; } //Calc singleSubNet.getObjects().stream().forEach(hl -> hl.setCurrentSupply(0)); if(model.getFairnessModel() == fairnessAllEqual) { long nOConsumer = singleSubNet.getObjects().stream().filter(hl -> (hl.getCurrentEnergyAtTimeStep(x) < 0)).count(); float energyPerHolonObject = 0; if (nOConsumer != 0) energyPerHolonObject = currentProduction / nOConsumer; for(HolonObject hO : singleSubNet.getObjects()) { if(hO.getCurrentEnergyAtTimeStep(x) < 0) //Just Consumer need Energy { hO.setCurrentSupply(energyPerHolonObject); currentProduction -= energyPerHolonObject; //Subtract the Energy from the Production } } } else //(model.getFairnessModel() == fairnessMininumDemandFirst) { singleSubNet.getObjects().sort(new MinEnergyComparator(x)); //SupplyAllMinimumEnergy for(HolonObject hO : singleSubNet.getObjects()) { if(hO.checkIfPartiallySupplied(x))continue; if(hO.getCurrentEnergyAtTimeStep(x) > 0)continue; float minEnergy = -hO.getMinEnergyNecessaryAtTimestep(x); //Energy from getMinEnergy is negative -> convert to positive if(minEnergy <= currentProduction) { hO.setCurrentSupply(minEnergy); currentProduction -= minEnergy; }else { hO.setCurrentSupply(currentProduction); currentProduction = 0; break; } } singleSubNet.getObjects().sort(new EnergyMinToMaxComparator(x)); //supplyFullytillEnd ... because its cant be fully supplied for(HolonObject hO : singleSubNet.getObjects()) { float actualSupplyEnergy = hO.getCurrentSupply(); float neededEnergy = -hO.getCurrentEnergyAtTimeStep(x) - actualSupplyEnergy; if(neededEnergy <= 0)continue; //Producer or No EnergyNeeded if(neededEnergy <= currentProduction) { hO.setCurrentSupply(neededEnergy+actualSupplyEnergy); currentProduction -= neededEnergy; }else { hO.setCurrentSupply(currentProduction+actualSupplyEnergy); currentProduction = 0; break; } } } } } //Visualize the Color for(HolonObject hO : singleSubNet.getObjects()) { float neededEnergy = -hO.getCurrentEnergyAtTimeStep(x); // convert negative energy in positive for calculations if(neededEnergy < 0) { hO.setState(HolonObject.PRODUCER); } else if(neededEnergy > 0) { float currentSupply = hO.getCurrentSupply() ; if(currentSupply > neededEnergy) { hO.setState(HolonObject.OVER_SUPPLIED); }else if (currentSupply == neededEnergy) { hO.setState(HolonObject.SUPPLIED); }else if (currentSupply < neededEnergy) { float minEnergy = -hO.getMinEnergyNecessaryAtTimestep(x); if(currentSupply >= minEnergy || hO.getSelfMadeEnergy(x) >= minEnergy ) { hO.setState(HolonObject.PARTIALLY_SUPPLIED); }else { hO.setState(HolonObject.NOT_SUPPLIED); } } } else if(neededEnergy == 0) { hO.setState(HolonObject.NO_ENERGY); } } } canvas.repaint(); flexPane.recalculate(); } private void calculation(int x, SubNet singleSubNet, float production, float consumption, float energySurplus, float currentProduction, ArrayList partiallySuppliedList, ArrayList notSuppliedList, float energyPerHolonObject) { long numberOfConsumers; if (model.getFairnessModel() == fairnessMininumDemandFirst) { /** * supply Buildings with minimal Energy first, if conflicts * happen */ singleSubNet.getObjects().sort(new MinEnergyComparator(x)); } else if (model.getFairnessModel() == fairnessAllEqual) { /* * give every building (just consumer) the same energy */ numberOfConsumers = singleSubNet .getObjects() .stream() .filter(hl -> (hl.getState() != HolonObject.NO_ENERGY && hl.getState() != HolonObject.PRODUCER && hl .getConnectedTo().stream() .filter(e -> (e.getFlow() > 0)).count() > 0)) .count(); if (numberOfConsumers != 0) energyPerHolonObject = currentProduction / numberOfConsumers; } for (HolonObject hl : singleSubNet.getObjects()) { hl.setCurrentSupply(0); if (hl.getState() != HolonObject.NO_ENERGY && hl.getState() != HolonObject.PRODUCER) { for (int i = 0; i < hl.getConnections().size(); i++) { CpsEdge edge = hl.getConnectedTo().get(i); if (edge.isWorking() && edge.getFlow() > 0 || edge.getCapacity() == CpsEdge.CAPACITY_INFINITE) { if (model.getFairnessModel() == fairnessAllEqual) { /* fairness: everyone receives the Same Energy */ float neededEnergy = hl .getCurrentEnergyAtTimeStep(x); if (neededEnergy > 0) { hl.setState(HolonObject.PRODUCER); } else if (energyPerHolonObject > -neededEnergy) { hl.setState(HolonObject.OVER_SUPPLIED); } else if (energyPerHolonObject == -neededEnergy) { hl.setState(HolonObject.SUPPLIED); } else if (energyPerHolonObject >= -hl .getMinEnergyNecessaryAtTimestep(x)) { hl.setState(HolonObject.PARTIALLY_SUPPLIED); } else { hl.setState(HolonObject.NOT_SUPPLIED); } hl.setCurrentSupply(energyPerHolonObject); } else if (model.getFairnessModel() == fairnessMininumDemandFirst) { /* fairness: minimum demand gets Energy first */ if ((production + consumption) >= 0) { if (energySurplus > 0) { hl.setState(HolonObject.OVER_SUPPLIED); hl.setCurrentSupply((-energySurplus / consumption + 1) * hl.getCurrentEnergyAtTimeStep(x)); } else { hl.setState(HolonObject.SUPPLIED); hl.setCurrentSupply(-hl .getCurrentEnergyAtTimeStep(x)); } } else { float minEnergy = hl.getMinEnergyNecessaryAtTimestep(x); if (hl.checkIfPartiallySupplied(timeStep)) { hl.setState(HolonObject.PARTIALLY_SUPPLIED); currentProduction += minEnergy; hl.setCurrentSupply(-minEnergy); partiallySuppliedList.add(hl); } else { /** * Case that only some HolonObjects can * be supplied */ if (-hl.getCurrentEnergyAtTimeStep(x) <= currentProduction) { hl.setState(HolonObject.PARTIALLY_SUPPLIED); currentProduction += minEnergy; hl.setCurrentSupply(-minEnergy); partiallySuppliedList.add(hl); } else if (-hl.getMinEnergyNecessaryAtTimestep(x) <= currentProduction) { hl.setState(HolonObject.PARTIALLY_SUPPLIED); currentProduction += minEnergy; hl.setCurrentSupply(-minEnergy); partiallySuppliedList.add(hl); } else { hl.setState(HolonObject.NOT_SUPPLIED); hl.setCurrentSupply(0.0f); notSuppliedList.add(hl); // currentProduction += // hl.getCurrentEnergyAtTimeStep(x); } } } } hl.getCurrentEnergyAtTimeStep(x); break; } } /** * check if some object cn self supply itself */ if (hl.checkIfPartiallySupplied(timeStep) && hl.getState() != HolonObject.SUPPLIED && hl.getState() != HolonObject.OVER_SUPPLIED) { hl.setState(HolonObject.PARTIALLY_SUPPLIED); } } } if (model.getFairnessModel() == fairnessMininumDemandFirst) { /** * check if some partially supplied building might be fully * supplied. */ partiallySuppliedList.sort(new EnergyMinToMaxComparator(x)); for (HolonObject hl : partiallySuppliedList) { float minEnergy = hl.getMinEnergyNecessaryAtTimestep(x); currentProduction -= minEnergy; /* * if possible, supply fully */ float currentEnergyAtTimeStep = hl .getCurrentEnergyAtTimeStep(x); if (-currentEnergyAtTimeStep <= currentProduction) { hl.setState(HolonObject.SUPPLIED); currentProduction += currentEnergyAtTimeStep; hl.setCurrentSupply(-currentEnergyAtTimeStep); hl.getCurrentEnergyAtTimeStep(x); } else { currentProduction += minEnergy; notSuppliedList.add(hl); } } if (!notSuppliedList.isEmpty() && currentProduction > 0) { float energyPerHolon = currentProduction / notSuppliedList.size(); for (HolonObject hl : notSuppliedList) { hl.setCurrentSupply(hl.getCurrentSupply() + energyPerHolon); hl.getCurrentEnergyAtTimeStep(x); } } } } /** * add all battries.getOut() from a list of battries and return them * @param aL a List of HolonBattries likely from subnet.getBatteries() * @param x TimeStep * @return * */ private float GetOutAllBatteries(ArrayList aL, int x) { float OutEnergy = 0; for(HolonBattery hB : aL) { //System.out.println("Iteration: "+ x +"OutBattery: "+ hB.getOutAtTimeStep(x-1)); OutEnergy += hB.getOutAtTimeStep(x-1); } //System.out.println("Iteration: "+ x +"GetOutAllBatteries: "+ OutEnergy); return OutEnergy; } /** * search for all flexible devices in the network and turn them on, until * energy surplus = 0 or all devices have been examined. * * This code could be compressed (cases inside over- and underproduction are * the same), but we decided that it is better readable this way * * @param subNet * the subnet * @param energySurplus * the current surplus of energy */ private void turnOnFlexibleDevices(SubNet subNet, float energySurplus, int timestep) { for (HolonObject holonOb : subNet.getObjects()) { for (HolonElement holonEl : holonOb.getElements()) { // if this element is flexible and active (can be considered for // calculations) if (holonEl.isFlexible() && holonEl.isActive()) { float energyAvailableSingle = holonEl .getAvailableEnergyAt(timestep); float energyAvailableMultiple = energyAvailableSingle * holonEl.getAmount(); // ------------- flexible consumer / OVERPRODUCTION // ------------- if (energyAvailableMultiple < 0 && energySurplus > 0) { // if there is more wasted energy than energy that this // device can give, give all energy available if (Math.abs(energyAvailableMultiple) <= Math .abs(energySurplus)) { energySurplus += energyAvailableMultiple; // set the new energy consumption to the maximum holonEl.setEnergyPerElement(energyAvailableSingle); flexDevicesTurnedOnThisTurn.put(holonEl, energyAvailableMultiple); } // else: we just need to turn on part of the flexible // energy available else { float energyNeeded = -energySurplus; energySurplus += energyNeeded; // should give 0, but // was kept this was // for consistency // the energy needed divided through the amount of // elements holonEl.setEnergyPerElement(energyNeeded / holonEl.getAmount()); flexDevicesTurnedOnThisTurn.put(holonEl, energyNeeded); } } // ------------- flexible producer / UNDERPRODUCTION // ------------- else if (energyAvailableMultiple > 0 && energySurplus < 0) { // if there is more energy needed than this device can // give, give all the energy available if (Math.abs(energyAvailableMultiple) <= Math .abs(energySurplus)) { energySurplus += energyAvailableMultiple; // set the new energy consumption to the maximum holonEl.setEnergyPerElement(energyAvailableSingle); flexDevicesTurnedOnThisTurn.put(holonEl, energyAvailableMultiple); } // else: we just need to turn on part of the flexible // energy available else { float energyNeeded = -energySurplus; int i = 0; energySurplus += energyNeeded; // should give 0, but // was kept this was // for consistency // the energy needed divided through the amount of // elements holonEl.setEnergyPerElement(energyNeeded / holonEl.getAmount()); flexDevicesTurnedOnThisTurn.put(holonEl, energyNeeded); } } } if (energySurplus == 0) { break; } } if (energySurplus == 0) { break; } } } /** * Set Flow Simulation. * * @param sN * Subnet */ private void setFlowSimulation(SubNet sN) { ArrayList producers = new ArrayList<>(); AbstractCpsObject tmp = null; tagTable = new HashMap<>(); // traverse all objects in this subnet for (HolonObject hl : sN.getObjects()) { float energy = hl.getCurrentEnergyAtTimeStep(timeStep); // if their production is higher than their consumption if (energy > 0) { tagTable.put(hl.getId(), energy); hl.addTag(hl.getId()); for (CpsEdge edge : hl.getConnections()) { if (edge.isWorking()) { // set other end of edge as tmp-object // and add this end to the other end's tag-list AbstractCpsObject a = edge.getA(); AbstractCpsObject b = edge.getB(); if (a.getId() == hl.getId()) { b.addTag(hl.getId()); tmp = b; } if (b.getId() == hl.getId()) { a.addTag(hl.getId()); tmp = a; } edge.setFlow(edge.getFlow() + energy); edge.calculateState(); edge.addTag(hl.getId()); if (edge.isWorking() && !producers.contains(tmp)) { if (tmp instanceof HolonSwitch) { if (((HolonSwitch) tmp).getState(timeStep)) { producers.add(tmp); } } else if (!(tmp instanceof CpsUpperNode)) { producers.add(tmp); } } } } } } setFlowSimRec(producers, 0); } /** * Set Flow Simulation Rec. * * @param nodes * the nodes * @param iter * the Iteration */ private void setFlowSimRec(ArrayList nodes, int iter) { ArrayList newNodes = new ArrayList<>(); ArrayList changedEdges = new ArrayList<>(); AbstractCpsObject tmp; if (nodes.size() != 0) { for (AbstractCpsObject cps : nodes) { // check whether the cps is in a legit state if it is a switch if (legitState(cps)) { for (CpsEdge edge : cps.getConnections()) { // is edge working // and does the edge's tag-list not (yet) contain all // tags of the cps if (edge.isWorking() && (!(edge.containsTags(edge.getTags(), cps.getTag())))) { if (edge.getA().getId() == cps.getId()) { tmp = edge.getB(); } else { tmp = edge.getA(); } for (Integer tag : cps.getTag()) { if (!(edge.getTags().contains(tag)) && !(edge.getPseudoTags().contains(tag))) { edge.setFlow(edge.getFlow() + tagTable.get(tag)); edge.addTag(tag); } } // uppernodes do not spread energy if (!(tmp instanceof CpsUpperNode)) { for (Integer tag : tmp.getTag()) { if (!(edge.getTags().contains(tag)) && tagTable.get(tag) != null && !(edge.getPseudoTags() .contains(tag))) { edge.setFlow(edge.getFlow() + tagTable.get(tag)); edge.addPseudoTag(tag); changedEdges.add(edge); } } } edge.calculateState(); if (edge.isWorking() && !(tmp instanceof CpsUpperNode)) { tmp.addAllPseudoTags(cps.getTag()); if (!newNodes.contains(tmp)) { newNodes.add(tmp); } } } } } } setPseudoTags(newNodes, changedEdges); setFlowSimRec(newNodes, iter + 1); } } /** * Set the Pseudo Tags. * * @param nodes * Array of AbstractCpsObjects */ private void setPseudoTags(ArrayList nodes, ArrayList edges) { for (AbstractCpsObject node : nodes) { node.recalculateTags(); node.setPseudoTags(new ArrayList<>()); } for (CpsEdge edge : edges) { edge.recalculateTags(); edge.setPseudoTag(new ArrayList<>()); } } /** * Reset the Connection. * * @param cps * CpsObject * @param visitedObj * the visited Objects * @param visitedEdges * the visited Edges */ private void resetConnections(AbstractCpsObject cps, ArrayList visitedObj, ArrayList visitedEdges) { visitedObj.add(cps.getId()); cps.resetTags(); for (CpsEdge e : cps.getConnections()) { if (!(visitedEdges.contains(e))) { e.setFlow(0); e.calculateState(); e.setTags(new ArrayList<>()); visitedEdges.add(e); if (!(visitedObj.contains(e.getA().getId()))) { resetConnections(e.getA(), visitedObj, visitedEdges); e.getA().resetTags(); } if (!(visitedObj.contains(e.getB().getId()))) { resetConnections(e.getB(), visitedObj, visitedEdges); e.getB().resetTags(); } } } } /** * calculates the energy of either all producers or consumers. Flexible * devices are filtered out * * @param type * Type * @param sN * Subnet * @param x * Integer * @return The Energy */ public float calculateEnergyWithoutFlexDevices(String type, SubNet sN, int x) { float energy = 0; for (HolonObject hl : sN.getObjects()) { float currentEnergyWithoutFlexibles = hl .getCurrentEnergyAtTimeStepWithoutFlexiblesAndResetFlexibles(x); if (type.equals("prod")) { if (currentEnergyWithoutFlexibles > 0) { energy += currentEnergyWithoutFlexibles; hl.setState(HolonObject.PRODUCER); } } if (type.equals("cons")) { if (currentEnergyWithoutFlexibles < 0) { energy += currentEnergyWithoutFlexibles; hl.setState(HolonObject.NOT_SUPPLIED); } } if (currentEnergyWithoutFlexibles == 0) { hl.setState(HolonObject.NO_ENERGY); } } return energy; } /** * calculates the energy of either all producers or consumers. Flexible * devices are filtered out * * @param type * Type * @param sN * Subnet * @param x * Integer * @return The Energy */ public float calculateEnergyWithFlexDevices(String type, SubNet sN, int x) { float energy = 0; for (HolonObject hl : sN.getObjects()) { float currentEnergy = hl.getCurrentEnergyAtTimeStep(x); if (type.equals("prod")) { if (currentEnergy > 0) { energy += currentEnergy; hl.setState(HolonObject.PRODUCER); } } if (type.equals("cons")) { if (currentEnergy < 0) { energy = energy + currentEnergy; hl.setState(HolonObject.NOT_SUPPLIED); } } if (currentEnergy == 0) { hl.setState(HolonObject.NO_ENERGY); } } return energy; } /** * Calculate the Minimum Energy of a Subnet. * * @param sN * Subnet * @param x * Integer * @return the Calculated minimum Energy of a Subnet */ private float calculateMinimumEnergy(SubNet sN, int x) { float minimummConsumptionSubnet = 0; for (HolonObject hl : sN.getObjects()) { float minElement = 0; // Search for a activ element for (HolonElement he : hl.getElements()) { if (he.isActive()) { float overallEnergy = he.getOverallEnergyAtTimeStep(x); if (overallEnergy < 0) { // Is a consumer minElement = overallEnergy; } } } for (HolonElement he : hl.getElements()) { if (he.isActive()) { float overallEnergy = he.getOverallEnergyAtTimeStep(x); if (minElement < overallEnergy && overallEnergy < 0) { // is a smaller consumer minElement = overallEnergy; } } } minimummConsumptionSubnet += minElement; } System.out.println("MinimumEnergy = "+ minimummConsumptionSubnet); return minimummConsumptionSubnet; } /** * generates all subNets from all objectsToHandle. */ private void searchForSubNets() { subNets = new ArrayList<>(); brokenEdges.clear(); boolean end = false; int i = 0; AbstractCpsObject cps; if (objectsToHandle.size() > 0) { while (!end) { cps = objectsToHandle.get(i); SubNet singleSubNet = new SubNet(new ArrayList<>(), new ArrayList<>(), new ArrayList<>(), new ArrayList<>()); singleSubNet = buildSubNet(cps, new ArrayList<>(), singleSubNet); if (singleSubNet.getObjects().size() + singleSubNet.getBatteries().size() != 0 ) { subNets.add(singleSubNet); } if (0 == objectsToHandle.size()) { end = true; } } } } /** * recursivly generates a subnet of all objects, that one specific object is * connected to. * * @param cps * AbstractCpsObject * @param visited * visited Array of Integer * @param sN * Subnets * @return Subnet */ private SubNet buildSubNet(AbstractCpsObject cps, ArrayList visited, SubNet sN) { visited.add(cps.getId()); if (cps instanceof HolonObject) { sN.getObjects().add((HolonObject) cps); } if (cps instanceof HolonSwitch) { sN.getSwitches().add((HolonSwitch) cps); } if (cps instanceof HolonBattery) { sN.getBatteries().add((HolonBattery) cps); } removeFromToHandle(cps.getId()); AbstractCpsObject a; AbstractCpsObject b; for (CpsEdge edge : cps.getConnections()) { if (edge.isWorking()) { a = edge.getA(); b = edge.getB(); if (!(cps instanceof HolonSwitch)) { if (!(sN.getEdges().contains(edge))) { sN.getEdges().add(edge); } } if (cps instanceof HolonSwitch && ((HolonSwitch) cps).getState(timeStep)) { if (!(sN.getEdges().contains(edge))) { sN.getEdges().add(edge); } } if (!visited.contains(a.getId()) && legitState(cps) && !(a instanceof CpsUpperNode)) { sN = buildSubNet(a, visited, sN); } if (!visited.contains(b.getId()) && legitState(cps) && !(b instanceof CpsUpperNode)) { sN = buildSubNet(b, visited, sN); } if (a instanceof CpsUpperNode && a.getId() != cps.getId()) { edge.setConnected(CpsEdge.CON_UPPER_NODE_NOT_INSIDE); checkForConnectedStates(b, (CpsUpperNode) a, edge); } if (b instanceof CpsUpperNode && b.getId() != cps.getId()) { edge.setConnected(CpsEdge.CON_UPPER_NODE_NOT_INSIDE); checkForConnectedStates(a, (CpsUpperNode) b, edge); } } else { brokenEdges.add(edge); } } return sN; } /** * is the Switch in a legitimate State. * * @param current * AbstractCpsObject * @return boolean */ private boolean legitState(AbstractCpsObject current) { return !(current instanceof HolonSwitch) || ((HolonSwitch) current).getState(timeStep); } // /** // * ensures that objectsToHandle only contains HolonObjects. // */ // public void cleanObjectsToHandle() { // for (int i = 0; i < objectsToHandle.size(); i++) { // if (!(objectsToHandle.get(i) instanceof HolonObject)) { // objectsToHandle.remove(i); // } // } // } /** * removes an Object that already has been handled. * * @param id * the Object ID */ private void removeFromToHandle(int id) { for (int i = 0; i < objectsToHandle.size(); i++) { if (objectsToHandle.get(i).getId() == id) { objectsToHandle.remove(i); } } } /** * copies the data of an array of Objects. * * @param toCopy * the ArrayList of CpsObjects co Copy */ private void copyObjects(ArrayList toCopy) { for (AbstractCpsObject cps : toCopy) { if (cps instanceof CpsUpperNode) { copyObjects(((CpsUpperNode) cps).getNodes()); } else { objectsToHandle.add(cps); } } } /** * Prints the Components auf all subnets. */ private void printNetsToConsole() { for (int i = 0; i < subNets.size(); i++) { SubNet subNet = subNets.get(i); System.out.println("SUBNET NR:" + i); subNet.toString(timeStep); } } /** * Set the Canvas. * * @param can * the Canvas */ public void setCanvas(MyCanvas can) { canvas = can; } /** * Reset all Data to the current state of the Model. */ public void reset() { objectsToHandle = new ArrayList<>(); copyObjects(model.getObjectsOnCanvas()); flexDevicesTurnedOnThisTurn = new HashMap<>(); } /** * Resets the State of all Edges */ private void resetEdges() { for (CpsEdge e : brokenEdges) { e.setWorkingState(true); } } /** * Resets the State for the whole Simulation Model */ void resetSimulation() { reset(); resetEdges(); } /** * Get all Subnets. * * @return all Subnets */ public ArrayList getSubNets() { return subNets; } /** * Get broken Edges */ // public ArrayList getBrokenEdges() { // return brokenEdges; // } /** * checks whether a given object is connected to an object inside the * upperNode. if yes, the state for the edge is changed in "connected" or * "not connected" */ private void checkForConnectedStates(AbstractCpsObject cps, CpsUpperNode cUNode, CpsEdge theEdge) { AbstractCpsObject tmp; for (CpsEdge edge : cps.getConnections()) { if (edge.getA().getId() == cps.getId()) { tmp = edge.getB(); } else { tmp = edge.getA(); } if (cUNode.getNodes().contains(tmp)) { if (tmp instanceof CpsUpperNode) { checkForConnectedStates(cps, (CpsUpperNode) tmp, theEdge); } else { theEdge.setConnected(CpsEdge.CON_UPPER_NODE_AND_INSIDE); break; } } } } public FlexiblePane getFlexiblePane() { return flexPane; } void setFlexiblePane(FlexiblePane fp) { flexPane = fp; } }