package ui.controller; import classes.*; import ui.model.IntermediateCableWithState; import ui.model.Consumer; import ui.model.DecoratedCable; import ui.model.DecoratedCable.CableState; import ui.model.DecoratedSwitch.SwitchState; import ui.model.DecoratedNetwork; import ui.model.DecoratedState; import ui.model.DecoratedSwitch; import ui.model.MinimumModel; import ui.model.MinimumNetwork; import ui.model.Model; import ui.model.Model.FairnessModel; import ui.model.Passiv; import ui.model.Supplier; import ui.model.VisualRepresentationalState; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedList; import java.util.List; import java.util.ListIterator; import java.util.stream.Collectors; /** * Controller for Simulation. * * @author Gruppe14 */ public class SimulationManager { int global = 0; private Model model; private HashMap saves = new HashMap(); private HashMap savesVisual = new HashMap(); private HashMap savesFlexManger = new HashMap(); private int timeStep; private HashMap> averagesPerHolon; private HashMap> mergesPerHolon; private HashMap> splitsPerHolon; private HashMap> flexesPerHolon; /** * Constructor. * * @param m * Model */ public SimulationManager(Model m) { model = m; this.averagesPerHolon = new HashMap>(); this.mergesPerHolon = new HashMap>(); this.splitsPerHolon = new HashMap>(); this.flexesPerHolon = new HashMap>(); } /** * calculates the flow of the edges and the supply for objects and consider old timesteps for burned cables. * * @param timeStep * current Iteration * @param updateVisual TODO */ public void calculateStateForTimeStep(int timeStep, boolean updateVisual) { // System.out.println("\n=========================================================================\n"); this.timeStep = timeStep; MinimumModel minimumModel = new MinimumModel(model.getObjectsOnCanvas(), model.getEdgesOnCanvas()); // HashMap map = new HashMap(); // if(timeStep > 0 && saves.containsKey(timeStep-1)) //if the state before exist // { //// System.out.println("---------------------------------------"); // //make cable hastmap // DecoratedState theStateBefore = saves.get(timeStep-1); // //edges without HolonObjects or burned // for(DecoratedCable edge : theStateBefore.getLeftOverEdges()) // { // map.put(edge.getModel(), edge.getState()); // } // } //set all the state before: for(IntermediateCableWithState cable : minimumModel.getEdgeList()) { // if(map.containsKey(cable.getModel()) && map.get(cable.getModel()) == CableState.Burned) { // cable.setState(CableState.Burned); //// System.out.println(cable.getModel()+" burnnnnnnn"); // cable.getModel().setBurned(true); // } if(cable.getModel().isBurned()) { cable.setState(CableState.Burned); } } //compute state of each holon List l = List.copyOf(this.model.getStateHolon().childHolons); for(Holon h : l) { h.holonControlUnit.computeState(timeStep); } // boolean doesFlexManagerExist = savesFlexManger.containsKey(timeStep); // boolean createNew = updateVisual || !doesFlexManagerExist; // FlexManager newFlexManager; // if(createNew) { // newFlexManager = new FlexManager(model, timeStep, savesFlexManger.get(timeStep-1)); // if(doesFlexManagerExist) newFlexManager.orderFlexFromList(savesFlexManger.get(timeStep).getAllFlexesOrderedThisTimeStep()); // savesFlexManger.put(timeStep, newFlexManager); // }else { // newFlexManager = savesFlexManger.get(timeStep); // } ArrayList list = new ArrayList(); //for each holarchy get minimum model ArrayList independentHolarchies = new ArrayList(); for(Holon h : model.getStateHolon().childHolons) { independentHolarchies.add(h.getMinimumModel()); } //set all edges that are not connecting holarchies unnused HashSet e = new HashSet(); for(MinimumModel minimumModel2 : independentHolarchies) { for(IntermediateCableWithState i : minimumModel2.getEdgeList()) { e.add(i.getModel()); } } for(IntermediateCableWithState cable : minimumModel.getEdgeList()) { if(!e.contains(cable.getModel())) { cable.setState(CableState.Unused); } } //set all BreakedManuel Cable Burned: for(IntermediateCableWithState cable : minimumModel.getEdgeList()) { if(cable.getModel().isBreakedManuel() || cable.getModel().isBurned()) cable.setState(CableState.Burned); } ArrayList leftOver = new ArrayList(); boolean doAnotherLoop = true; while(doAnotherLoop) { doAnotherLoop = false; list = calculateNetworks(minimumModel, timeStep, leftOver); for(MinimumNetwork net : list) { float energyOnCables = net.getHolonObjectList().stream().filter(object -> object.getEnergyAtTimeStepFlex(timeStep) > 0.0f).map(object -> object.getEnergyAtTimeStepFlex(timeStep)).reduce(0.0f, ((a,b) -> a + b)); // float energyOnCables = net.getHolonObjectList().stream().filter(object -> object.getEnergyAtTimeStepWithFlex(timeStep, newFlexManager) > 0.0f).map(object -> object.getEnergyAtTimeStepWithFlex(timeStep, newFlexManager)).reduce(0.0f, ((a,b) -> a + b)); // float energyOnCables = net.getHolonObjectList().stream().filter(object -> object.getEnergyAtTimeStepFlex(timeStep) > 0.0f).map(object -> object.getEnergyAtTimeStepFlex(timeStep)).reduce(0.0f, ((a,b) -> a + b)); // float energyOnCables = net.getHolonObjectList().stream().filter(object -> object.holon.holonControlUnit.getStateEstimator().getPowerUsage() > 0.0f).map(object -> object.getEnergyAtTimeStepWithFlex(timeStep, newFlexManager)).reduce(0.0f, ((a,b) -> a + b)); //find the cable with the energy supplied from his two connected objects are the biggest, from all cables that the network give more energy than the cablecapacity. IntermediateCableWithState cable = net.getEdgeList().stream().filter(aCable -> energyOnCables > aCable.getModel().getCapacity() && !aCable.getModel().isUnlimitedCapacity()).max((lhs,rhs) -> Float.compare(lhs.getEnergyFromConnetedAtTimestep(timeStep), rhs.getEnergyFromConnetedAtTimestep(timeStep))).orElse(null); if(cable != null) { cable.setState(CableState.Burned); cable.getModel().setBurned(true); doAnotherLoop = true; } else { net.getEdgeList().stream().forEach(c -> c.getModel().setThroughput(energyOnCables)); } } } //Create lookUpTableForHolonObjetcs HashMap holonObjectNetworkTable = new HashMap(); ArrayList decorNetworks = new ArrayList(); FairnessModel actualFairnessModel = model.getFairnessModel(); for (MinimumNetwork net : list) { // DecoratedNetwork decNetwork = new DecoratedNetwork(net, timeStep, actualFairnessModel, newFlexManager); DecoratedNetwork decNetwork = new DecoratedNetwork(net, timeStep, actualFairnessModel); decorNetworks.add(decNetwork); for(HolonObject obj : net.getHolonObjectList()) { holonObjectNetworkTable.put(obj, decNetwork); } } ArrayList leftOverDecoratedCables = new ArrayList(); for(IntermediateCableWithState cable: leftOver) { leftOverDecoratedCables.add(new DecoratedCable(cable.getModel(), cable.getState(), 0.0f)); } ArrayList listOfDecoratedSwitches = decorateSwitches(minimumModel, timeStep); DecoratedState stateFromThisTimestep = new DecoratedState(decorNetworks, leftOverDecoratedCables, listOfDecoratedSwitches, timeStep, holonObjectNetworkTable); saves.put(timeStep, stateFromThisTimestep); VisualRepresentationalState visualState = new VisualRepresentationalState(stateFromThisTimestep, minimumModel); if(updateVisual)savesVisual.put(timeStep, visualState); //Check Holarchy and split Holons if no physical connection is present. // List holonList = model.getStateHolon().childHolons; // for(int i = 0; i < holonList.size(); i++) { // holonList.get(i).checkRepairHolarchy(holonObjectNetworkTable, model.getStateHolon()); // } eval(visualState, independentHolarchies, timeStep >= 99); } private void eval(VisualRepresentationalState visualState, ArrayList independentHolarchies, boolean print) { if(print) System.out.println("\n=========================================================================\n"); //evaluate power usage in each holon object for(Consumer con : visualState.getConsumerList()) { evalPower(con.getModel().holon, con.getSupplyBarPercentage(), print); } HashMap map = new HashMap<>(); for(Supplier sup : visualState.getSupplierList()) { //find the holarchy where the sup is MinimumModel holarchy = null; for(MinimumModel mm : independentHolarchies) { if(mm.getHolonObjectList().contains(sup.getModel())) holarchy = mm; } //find out how much energy is produced and consumed in total inside this holarchy //c/p is satisfaction of supplier float sat = 0f; if(holarchy != null) { if(map.containsKey(holarchy)) { sat = map.get(holarchy); } else { float totalProd = 0f; float totalCon = 0f; for(HolonObject ho : holarchy.getHolonObjectList()) { float p = ho.getEnergyAtTimeStepFlex(model.getCurIteration()); if(p > 0) { totalProd += p; } else { totalCon -= p; } } sat = totalCon/totalProd; map.put(holarchy, sat); } } evalPower(sup.getModel().holon, sat, print); } for(Passiv pas : visualState.getPassivList()) { evalPower(pas.getModel().holon, pas.getEnergy(), print); } List holonObjects = this.model.getAllHolonObjectsOnCanvas(); // int totalMerges = holonObjects.stream().mapToInt(ho -> ho.holon.getMergeCounter()).sum(); // int totalSplits = holonObjects.stream().mapToInt(ho -> ho.holon.getSplitCounter()).sum(); // if(print) { // System.out.println("Total performed merge: "+totalMerges+"\tavg: "+((float)totalMerges)/((float)holonObjects.size())); // System.out.println("Total performed split: "+totalSplits+"\tavg: "+((float)totalSplits)/((float)holonObjects.size())); // } } private void evalPower(Holon h, float curr, boolean print) { ArrayList avgList = this.averagesPerHolon.getOrDefault(h, new ArrayList<>()); if(timeStep >= avgList.size()) { avgList.add(curr); } else { avgList.remove(timeStep); avgList.add(timeStep, curr); } this.averagesPerHolon.put(h, avgList); ArrayList mergeList = this.mergesPerHolon.getOrDefault(h, new ArrayList<>()); int merges = h.getMergeCounter();// - ((timeStep-1 >= 0 && mergeList.size() > timeStep-1) ? mergeList.get(timeStep-1) : 0); if(timeStep >= mergeList.size()) { mergeList.add(merges); } else { mergeList.remove(timeStep); mergeList.add(timeStep, merges); } this.mergesPerHolon.put(h, mergeList); ArrayList splitList = this.splitsPerHolon.getOrDefault(h, new ArrayList<>()); int splits = h.getSplitCounter();// - ((timeStep-1 >= 0 && splitList.size() > timeStep-1) ? splitList.get(timeStep-1) : 0); if(timeStep >= splitList.size()) { splitList.add(splits); } else { splitList.remove(timeStep); splitList.add(timeStep, splits); } this.splitsPerHolon.put(h, splitList); ArrayList flexList = this.flexesPerHolon.getOrDefault(h, new ArrayList<>()); int flexes = h.holonControlUnit.getFlexMan().getAppliedFlexCounter();// - ((timeStep-1 >= 0 && splitList.size() > timeStep-1) ? splitList.get(timeStep-1) : 0); if(timeStep >= flexList.size()) { flexList.add(flexes); } else { flexList.remove(timeStep); flexList.add(timeStep, flexes); } this.flexesPerHolon.put(h, flexList); // float avg = 0f; // for(float f:list) // avg += f; // avg = avg/list.size(); float dev = curr-1f; h.countState(dev); if(print) { // System.out.println("next: "+h.getUniqueID()+"\n\tpower stats: "+curr+"\tavg: "+avg+"\t"+list+"\n\tmerges: "+h.getMergeCounter() // +"\tsplits: "+h.getSplitCounter()+"\n\tDeviation: "+dev+"\t["+h.getStateCounter()[0]+", "+h.getStateCounter()[1]+", " // +h.getStateCounter()[2]+"]\n\tHolarchy: " // +h.getMinimumModel().getHolonObjectList().stream().map(ho -> ho.holon.getUniqueID()).collect(Collectors.toList())); System.out.println("next: "+h.getUniqueID() +"\n\tpower stats: "+avgList +"\n\tmerges: "+mergeList +"\n\tsplits: "+splitList +"\n\tflexes: "+flexList +"\n\tstates: ["+h.getStateCounter()[0]+", "+h.getStateCounter()[1]+", "+h.getStateCounter()[2]+"]"); } } /** * Decorate a switch * @param minModel * @param iteration * @return */ public static ArrayList decorateSwitches(MinimumModel minModel, int iteration) { ArrayList aListOfDecoratedSwitches = new ArrayList(); for(HolonSwitch hSwitch: minModel.getSwitchList()) { aListOfDecoratedSwitches.add(new DecoratedSwitch(hSwitch, hSwitch.getState(iteration) ? SwitchState.Closed : SwitchState.Open)); } return aListOfDecoratedSwitches; } /** * SubFunction to calculate the Networks from the model. * @param minModel * @param Iteration * @param leftOver * @return */ ArrayList calculateNetworks(MinimumModel minModel, int Iteration, ArrayList leftOver){ //Copy minModel ObjectList ArrayList holonObjectList = new ArrayList(); for(HolonObject holonObject: minModel.getHolonObjectList()) { holonObjectList.add(holonObject); } //Copy minModelEdgeList ArrayList edgeList = new ArrayList(); for(IntermediateCableWithState cable: minModel.getEdgeList()) { edgeList.add(cable); } ArrayList listOfNetworks = new ArrayList(); while(!holonObjectList.isEmpty()) { //lookAt the first holonObject and find his neighbors HolonObject lookAtObject = holonObjectList.get(0); //delete out of list holonObjectList.remove(0); //create a new Network MinimumNetwork actualNetwork = new MinimumNetwork(new ArrayList(), new ArrayList()); actualNetwork.getHolonObjectList().add(lookAtObject); //create List of neighbors LinkedList neighbors = new LinkedList(); populateListOfNeighbors(edgeList, lookAtObject, actualNetwork, neighbors); while(!neighbors.isEmpty()) { AbstractCanvasObject lookAtNeighbor = neighbors.getFirst(); if(lookAtNeighbor instanceof HolonObject) { actualNetwork.getHolonObjectList().add((HolonObject) lookAtNeighbor); holonObjectList.remove(lookAtNeighbor); }else { actualNetwork.getNodeAndSwitches().add(lookAtNeighbor); } //When HolonSwitch Check if closed if(!(lookAtNeighbor instanceof HolonSwitch) || ((HolonSwitch)lookAtNeighbor).getState(Iteration)) { populateListOfNeighbors(edgeList, lookAtNeighbor, actualNetwork, neighbors); } neighbors.removeFirst(); } listOfNetworks.add(actualNetwork); } if(leftOver!= null) { leftOver.clear(); for(IntermediateCableWithState cable: edgeList) { leftOver.add(cable); } } return listOfNetworks; } /** * Adds the neighbors. * @param edgeList * @param lookAtObject * @param actualNetwork * @param neighbors */ void populateListOfNeighbors(ArrayList edgeList, AbstractCanvasObject lookAtObject, MinimumNetwork actualNetwork, LinkedList neighbors) { ListIterator iter = edgeList.listIterator(); while(iter.hasNext()) { IntermediateCableWithState lookAtEdge = iter.next(); if(lookAtEdge.getState() == CableState.Working && lookAtEdge.getModel().isConnectedTo(lookAtObject)) { iter.remove(); actualNetwork.getEdgeList().add(lookAtEdge); //Add neighbar AbstractCanvasObject edgeNeighbor; if(lookAtEdge.getModel().getA().equals(lookAtObject)) { edgeNeighbor = lookAtEdge.getModel().getB(); }else { edgeNeighbor = lookAtEdge.getModel().getA(); } if(!neighbors.contains(edgeNeighbor)) { neighbors.add(edgeNeighbor); } } } } public DecoratedState getActualDecorState() { return getDecorState(timeStep); } public VisualRepresentationalState getActualVisualRepresentationalState(){ return savesVisual.getOrDefault(timeStep, null); } public FlexManager getActualFlexManager() { return savesFlexManger.getOrDefault(timeStep, null); } public void resetFlexManager(){ savesFlexManger.clear(); } public void resetFlexManagerForTimeStep(int timestep) { savesFlexManger.get(timestep).reset(); } public DecoratedState getDecorState(int timestep) { return saves.get(timestep); } public VisualRepresentationalState getVisualRepresentationalState(int timestep) { return savesVisual.getOrDefault(timestep, null); } }