123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600 |
- package ui.controller;
- import classes.*;
- import ui.model.Model;
- import ui.view.FlexiblePane;
- import ui.view.MyCanvas;
- import java.util.ArrayList;
- import java.util.HashMap;
- /**
- * Controller for Simulation.
- *
- * @author Gruppe14
- */
- public class SimulationManager {
- int global = 0;
- private Model model;
- private ArrayList<AbstractCpsObject> objectsToHandle;
- // private ArrayList<CpsEdge> allConnections;
- private ArrayList<SubNet> subNets;
- private ArrayList<CpsEdge> brokenEdges;
- private MyCanvas canvas;
- private int timeStep;
- private HashMap<Integer, Float> tagTable = new HashMap<>();
- private FlexiblePane flexPane;
- private HashMap<HolonElement, Float> flexDevicesTurnedOnThisTurn = new HashMap<>();
- /**
- * 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) {
- resetConnections(singleSubNet.getObjects().get(0), new ArrayList<>(), new ArrayList<>());
- }
- for (SubNet singleSubNet : subNets) {
- float production = calculateEnergy("prod", singleSubNet, timeStep);
- float consumption = calculateEnergy("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 = calculateEnergy("prod", singleSubNet, timeStep);
- consumption = calculateEnergy("cons", singleSubNet, timeStep);
- energySurplus = production + consumption;
- }
- // --------------- set flow simulation ---------------
- setFlowSimulation(singleSubNet);
- // --------------- visualise graph ---------------
- for (HolonObject hl : singleSubNet.getObjects()) {
- 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 ((production + consumption) >= 0) {
- if (energySurplus > 0) {
- hl.setState(HolonObject.OVER_SUPPLIED);
- } else {
- hl.setState(HolonObject.SUPPLIED);
- }
- } else {
- if ((production + minConsumption) >= 0) {
- hl.setState(HolonObject.PARTIALLY_SUPPLIED);
- } else if (hl.checkIfPartiallySupplied(timeStep)) {
- hl.setState(HolonObject.PARTIALLY_SUPPLIED);
- } else {
- hl.setState(HolonObject.NOT_SUPPLIED);
- }
- }
- break;
- }
- }
- if (hl.checkIfPartiallySupplied(timeStep)
- && hl.getState() != HolonObject.SUPPLIED
- && hl.getState() != HolonObject.OVER_SUPPLIED) {
- hl.setState(HolonObject.PARTIALLY_SUPPLIED);
- }
- }
- }
- }
- canvas.repaint();
- flexPane.recalculate();
- }
- /**
- * search for all flexible devices in the network and turn them on, until wasted energy = 0
- * or all devices have been examined
- *
- * @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 (holonEl.isFlexible() && holonEl.isActive()) {
- // if this element is flexible
- float actuallyUsedEnergy = holonEl.getEnergyPerElement();
- float energyAvailable = holonEl.getAvailableEnergyAt(timestep) - actuallyUsedEnergy;
- // ------------- flexible consumer -------------
- if (energyAvailable < 0 && energySurplus > 0) {
- // System.out.println("flexible consumer in " + subNet.toString(timestep));
- // if there is more wasted Energy than energy that this device can give
- if (Math.abs(energyAvailable) <= Math.abs(energySurplus)) {
- energySurplus += energyAvailable;
- // set the new energy consumption to the maximum
- holonEl.setEnergyPerElement(holonEl.getAvailableEnergyAt(timestep));
- flexDevicesTurnedOnThisTurn.put(holonEl, energyAvailable);
- }
- // else if 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
- // add to the currently used energy the energy needed divided through the amount of elements
- float newEnergyConsumption = holonEl.getEnergyPerElement() + energyNeeded / holonEl.getAmount();
- holonEl.setEnergyPerElement(newEnergyConsumption);
- flexDevicesTurnedOnThisTurn.put(holonEl, energyNeeded);
- }
- System.out.println("One element was turned on, wastedEnergy after: " + energySurplus + "\n");
- }
- // ------------- flexible producer -------------
- else if (energyAvailable > 0 && energySurplus < 0) {
- // System.out.println("flexible producer in " + subNet.toString(timestep));
- // TODO
- }
- }
- }
- }
- }
- /**
- * Set Flow Simulation.
- *
- * @param sN Subnet
- */
- private void setFlowSimulation(SubNet sN) {
- ArrayList<AbstractCpsObject> 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<AbstractCpsObject> nodes, int iter) {
- ArrayList<AbstractCpsObject> newNodes = new ArrayList<>();
- ArrayList<CpsEdge> 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<AbstractCpsObject> nodes, ArrayList<CpsEdge> 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<Integer> visitedObj,
- ArrayList<CpsEdge> 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.
- *
- * @param type Type
- * @param sN Subnet
- * @param x Integer
- * @return The Energy
- */
- private float calculateEnergy(String type, SubNet sN, int x) {
- float energy = 0;
- for (HolonObject hl : sN.getObjects()) {
- if (type.equals("prod")) {
- if (hl.getCurrentEnergyAtTimeStep(x) > 0) {
- energy = energy + hl.getCurrentEnergyAtTimeStep(x);
- hl.setState(HolonObject.PRODUCER);
- }
- }
- if (type.equals("cons")) {
- if (hl.getCurrentEnergyAtTimeStep(x) < 0) {
- energy = energy + hl.getCurrentEnergyAtTimeStep(x);
- hl.setState(HolonObject.NOT_SUPPLIED);
- }
- }
- if (hl.getCurrentEnergyAtTimeStep(x) == 0) {
- hl.setState(HolonObject.NO_ENERGY);
- }
- }
- return energy;
- }
- /**
- * Calculate the Minimum Energy.
- *
- * @param sN Subnet
- * @param x Integer
- * @return the Calculated minimum Energy
- */
- private float calculateMinimumEnergy(SubNet sN, int x) {
- float min = 0;
- float minElement = 0;
- for (HolonObject hl : sN.getObjects()) {
- if (hl.getElements().size() > 0 && hl.getElements().get(0).getOverallEnergyAtTimeStep(x) < 0) {
- minElement = hl.getElements().get(0).getOverallEnergyAtTimeStep(x);
- }
- for (HolonElement he : hl.getElements()) {
- float overallEnergy = he.getOverallEnergyAtTimeStep(x);
- if (minElement < overallEnergy && overallEnergy < 0) {
- minElement = overallEnergy;
- }
- }
- min = min + minElement;
- }
- return min;
- }
- /**
- * 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<>());
- singleSubNet = buildSubNet(cps, new ArrayList<>(), singleSubNet);
- if (singleSubNet.getObjects().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<Integer> 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);
- }
- 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<AbstractCpsObject> 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<SubNet> getSubNets() {
- return subNets;
- }
- /**
- * Get broken Edges
- */
- // public ArrayList<CpsEdge> 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;
- }
- }
|