package holeg.ui.controller; import holeg.model.AbstractCanvasObject; import holeg.model.Edge; import holeg.model.Edge.EdgeState; import holeg.model.HolonObject; import holeg.model.HolonSwitch; import holeg.model.HolonSwitch.SwitchState; import holeg.model.Holon; import holeg.model.Model; import java.util.*; import java.util.logging.Logger; import java.util.stream.Collectors; public class SimulationManager { private static final Logger log = Logger.getLogger(SimulationManager.class.getName()); private final Control control; public SimulationManager(Control control) { log.fine("Construct SimulationManager"); this.control = control; } public void calculateStateForTimeStep(int timeStep) { log.fine("Calculate"); long start = System.currentTimeMillis(); Model model = control.getModel(); model.getCanvas().getAllSwitchObjectsRecursive().forEach(sw -> sw.calculateState(timeStep)); List holonObjectList = model.getCanvas().getAllHolonObjectsRecursive().collect(Collectors.toList()); List edgeList = new ArrayList<>(model.getEdgesOnCanvas()); Set holons = getHolons(holonObjectList, edgeList, timeStep); holons.forEach(holon -> holon.calculate(timeStep)); model.holons = holons; log.info("Holons:" + holons.stream().map(Object::toString).collect(Collectors.joining("\n"))); long end = System.currentTimeMillis(); log.finer("Simulation: " + (end - start) + "ms"); } private Set getHolons(List holonObjectList, List edgeList, int timeStep) { log.info(System.lineSeparator() + "Supplier [" + holonObjectList.stream().map(AbstractCanvasObject::getName).collect(Collectors.joining(", ")) + "]" + System.lineSeparator() + "Consumer [" + edgeList.stream().map(Object::toString).collect(Collectors.joining(", ")) + "]" + System.lineSeparator() ); Set holons = new HashSet<>(); for (Holon holon : calculateHolonStructure(holonObjectList, edgeList)) { final float energyOnCables = holon.holonObjects.stream().map(hO -> { hO.calculateEnergy(timeStep); return hO.getActualEnergy(); }) .filter(energy -> energy > 0.0f).reduce(0.0f, (Float::sum)); // find the edge with the energy supplied from his two connected objects are // the biggest, from all cables that the network give more energy than the // edge capacity. Optional edge = holon.edges.stream() .filter(e -> energyOnCables > e.maxCapacity && e.mode == Edge.EdgeMode.Normal) .max((lhs, rhs) -> Float.compare(lhs.getEnergyFromConneted(), rhs.getEnergyFromConneted())); edge.ifPresentOrElse(e -> { //Burn Cable e.setState(EdgeState.Burned); e.setActualFlow(0.0f); //Split Holon holons.addAll(getHolons(new ArrayList<>(holon.holonObjects), new ArrayList<>(holon.edges), timeStep)); }, () -> { holon.edges.forEach(e -> e.setActualFlow(energyOnCables)); holons.add(holon); }); } return holons; } Set calculateHolonStructure(List holonObjectList, List edgeList) { Set holons = new HashSet<>(); 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 Holon actualNetwork = new Holon(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) { holonObjectList.remove(lookAtNeighbor); } actualNetwork.add(lookAtNeighbor); // When HolonSwitch Check if closed if (!(lookAtNeighbor instanceof HolonSwitch sw) || sw.getState() == SwitchState.Closed) { populateListOfNeighbors(edgeList, lookAtNeighbor, actualNetwork, neighbors); } neighbors.removeFirst(); } holons.add(actualNetwork); } for (Edge e : edgeList) { e.setActualFlow(0.0f); } return holons; } /** * Adds neighbors. */ void populateListOfNeighbors(List edgeList, AbstractCanvasObject lookAtObject, Holon actualNetwork, LinkedList neighbors) { ListIterator iter = edgeList.listIterator(); while (iter.hasNext()) { Edge lookAtEdge = iter.next(); if (lookAtEdge.getState() == EdgeState.Working && lookAtEdge.isConnectedTo(lookAtObject)) { iter.remove(); actualNetwork.edges.add(lookAtEdge); // Add neighbor AbstractCanvasObject edgeNeighbor; if (lookAtEdge.getA().equals(lookAtObject)) { edgeNeighbor = lookAtEdge.getB(); } else { edgeNeighbor = lookAtEdge.getA(); } if (!neighbors.contains(edgeNeighbor)) { neighbors.add(edgeNeighbor); } } } } }