SimulationManager.java 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463
  1. package ui.controller;
  2. import classes.*;
  3. import classes.comparator.EnergyMinToMaxComparator;
  4. import classes.comparator.MinEnergyComparator;
  5. import classes.comparator.WeakestBattery;
  6. import ui.model.IntermediateCableWithState;
  7. import ui.model.DecoratedCable;
  8. import ui.model.DecoratedCable.CableState;
  9. import ui.model.DecoratedSwitch.SwitchState;
  10. import ui.model.DecoratedNetwork;
  11. import ui.model.DecoratedState;
  12. import ui.model.DecoratedSwitch;
  13. import ui.model.MinimumModel;
  14. import ui.model.MinimumNetwork;
  15. import ui.model.Model;
  16. import ui.model.Model.FairnessModel;
  17. import ui.model.VisualRepresentationalState;
  18. import ui.view.FlexiblePane;
  19. import ui.view.GUI;
  20. import ui.view.MyCanvas;
  21. import ui.view.Outliner;
  22. import java.util.ArrayList;
  23. import java.util.Collections;
  24. import java.util.HashMap;
  25. import java.util.LinkedList;
  26. import java.util.ListIterator;
  27. import javax.swing.JPanel;
  28. /**
  29. * Controller for Simulation.
  30. *
  31. * @author Gruppe14
  32. */
  33. public class SimulationManager {
  34. int global = 0;
  35. private Model model;
  36. private ArrayList<AbstractCpsObject> objectsToHandle;
  37. private ArrayList<SubNet> subNets;
  38. private ArrayList<CpsEdge> brokenEdges;
  39. private HashMap<Integer, DecoratedState> saves = new HashMap<Integer, DecoratedState>();
  40. private HashMap<Integer, VisualRepresentationalState> savesVisual = new HashMap<Integer, VisualRepresentationalState>();
  41. private MyCanvas canvas;
  42. private int timeStep;
  43. private HashMap<Integer, Float> tagTable = new HashMap<>();
  44. private FlexiblePane flexPane;
  45. private GUI gui;
  46. private HashMap<HolonElement, Float> flexDevicesTurnedOnThisTurn = new HashMap<>();
  47. /**
  48. * Constructor.
  49. *
  50. * @param m
  51. * Model
  52. */
  53. SimulationManager(Model m) {
  54. canvas = null;
  55. model = m;
  56. subNets = new ArrayList<>();
  57. brokenEdges = new ArrayList<>();
  58. }
  59. /**
  60. * calculates the flow of the edges and the supply for objects and consider old timesteps for burned cables.
  61. *
  62. * @param timestep
  63. * current Iteration
  64. */
  65. void calculateStateForTimeStep(int timestep) {
  66. HashMap<CpsEdge, CableState> map = new HashMap<CpsEdge, CableState>();
  67. if(timestep > 0 && saves.containsKey(timestep-1)) //if the state before exist
  68. {
  69. //make cable hastmap
  70. DecoratedState theStateBefore = saves.get(timestep-1);
  71. for(DecoratedCable edge : theStateBefore.getLeftOverEdges())
  72. {
  73. map.put(edge.getModel(), edge.getState());
  74. }
  75. }
  76. timeStep = timestep;
  77. ArrayList<MinimumNetwork> list = new ArrayList<MinimumNetwork>();
  78. MinimumModel minimumModel = new MinimumModel(model.getObjectsOnCanvas(), model.getEdgesOnCanvas());
  79. //set all working:
  80. for(IntermediateCableWithState cable : minimumModel.getEdgeList()) {
  81. if(map.containsKey(cable.getModel())) cable.setState(map.get(cable.getModel()));
  82. }
  83. ArrayList<IntermediateCableWithState> leftOver = new ArrayList<IntermediateCableWithState>();
  84. boolean doAnotherLoop = true;
  85. while(doAnotherLoop) {
  86. doAnotherLoop = false;
  87. list = calculateNetworks(minimumModel, timestep, leftOver);
  88. for(MinimumNetwork net : list) {
  89. float energyOnCables = net.getHolonObjectList().stream().filter(object -> object.getEnergyAtTimeStep(timestep) > 0.0f).map(object -> object.getEnergyAtTimeStep(timestep)).reduce(0.0f, ((a,b) -> a + b));
  90. //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.
  91. IntermediateCableWithState cable = net.getEdgeList().stream().filter(aCable -> energyOnCables > aCable.getModel().getCapacity()).max((lhs,rhs) -> Float.compare(lhs.getEnergyFromConnetedAtTimestep(timestep), rhs.getEnergyFromConnetedAtTimestep(timestep))).orElse(null);
  92. if(cable != null) {
  93. cable.setState(CableState.Burned);
  94. doAnotherLoop = true;
  95. }
  96. }
  97. }
  98. ArrayList<DecoratedNetwork> decorNetworks = new ArrayList<DecoratedNetwork>();
  99. FairnessModel actualFairnessModel = model.getFairnessModel();
  100. for (MinimumNetwork net : list) {
  101. decorNetworks.add(new DecoratedNetwork(net, timestep, actualFairnessModel));
  102. }
  103. ArrayList<DecoratedCable> leftOverDecoratedCables = new ArrayList<DecoratedCable>();
  104. for(IntermediateCableWithState cable: leftOver) {
  105. leftOverDecoratedCables.add(new DecoratedCable(cable.getModel(), cable.getState(), 0.0f));
  106. }
  107. ArrayList<DecoratedSwitch> listOfDecoratedSwitches = decorateSwitches(minimumModel, timestep);
  108. DecoratedState stateFromThisTimestep = new DecoratedState(decorNetworks, leftOverDecoratedCables, listOfDecoratedSwitches, timestep);
  109. saves.put(timestep, stateFromThisTimestep);
  110. savesVisual.put(timestep, new VisualRepresentationalState(stateFromThisTimestep, minimumModel));
  111. canvas.repaint();
  112. gui.updateOutliners(getActualDecorState());//saves.getOrDefault(timestep, null);
  113. }
  114. /**
  115. * Decorate a switch
  116. * @param minModel
  117. * @param iteration
  118. * @return
  119. */
  120. public static ArrayList<DecoratedSwitch> decorateSwitches(MinimumModel minModel, int iteration) {
  121. ArrayList<DecoratedSwitch> aListOfDecoratedSwitches = new ArrayList<DecoratedSwitch>();
  122. for(HolonSwitch hSwitch: minModel.getSwitchList()) {
  123. aListOfDecoratedSwitches.add(new DecoratedSwitch(hSwitch, hSwitch.getState(iteration) ? SwitchState.Closed : SwitchState.Open));
  124. }
  125. return aListOfDecoratedSwitches;
  126. }
  127. /**
  128. * SubFunction to calculate the Networks from the model.
  129. * @param minModel
  130. * @param Iteration
  131. * @param leftOver
  132. * @return
  133. */
  134. ArrayList<MinimumNetwork> calculateNetworks(MinimumModel minModel, int Iteration, ArrayList<IntermediateCableWithState> leftOver){
  135. //Copy minModel ObjectList
  136. ArrayList<HolonObject> holonObjectList = new ArrayList<HolonObject>();
  137. for(HolonObject holonObject: minModel.getHolonObjectList()) {
  138. holonObjectList.add(holonObject);
  139. }
  140. //Copy minModelEdgeList
  141. ArrayList<IntermediateCableWithState> edgeList = new ArrayList<IntermediateCableWithState>();
  142. for(IntermediateCableWithState cable: minModel.getEdgeList()) {
  143. edgeList.add(cable);
  144. }
  145. ArrayList<MinimumNetwork> listOfNetworks = new ArrayList<MinimumNetwork>();
  146. while(!holonObjectList.isEmpty()) {
  147. //lookAt the first holonObject and find his neighbors
  148. HolonObject lookAtObject = holonObjectList.get(0);
  149. //delete out of list
  150. holonObjectList.remove(0);
  151. //create a new Network
  152. MinimumNetwork actualNetwork = new MinimumNetwork(new ArrayList<HolonObject>(), new ArrayList<IntermediateCableWithState>());
  153. actualNetwork.getHolonObjectList().add(lookAtObject);
  154. //create List of neighbors
  155. LinkedList<AbstractCpsObject> neighbors = new LinkedList<AbstractCpsObject>();
  156. populateListOfNeighbors(edgeList, lookAtObject, actualNetwork, neighbors);
  157. while(!neighbors.isEmpty()) {
  158. AbstractCpsObject lookAtNeighbor = neighbors.getFirst();
  159. if(lookAtNeighbor instanceof HolonObject) {
  160. actualNetwork.getHolonObjectList().add((HolonObject) lookAtNeighbor);
  161. holonObjectList.remove(lookAtNeighbor);
  162. }
  163. //When HolonSwitch Check if closed
  164. if(!(lookAtNeighbor instanceof HolonSwitch) || ((HolonSwitch)lookAtNeighbor).getState(Iteration)) {
  165. populateListOfNeighbors(edgeList, lookAtNeighbor, actualNetwork, neighbors);
  166. }
  167. neighbors.removeFirst();
  168. }
  169. listOfNetworks.add(actualNetwork);
  170. }
  171. if(leftOver!= null) {
  172. leftOver.clear();
  173. for(IntermediateCableWithState cable: edgeList) {
  174. leftOver.add(cable);
  175. }
  176. }
  177. return listOfNetworks;
  178. }
  179. /**
  180. * Adds the neighbors.
  181. * @param edgeList
  182. * @param lookAtObject
  183. * @param actualNetwork
  184. * @param neighbors
  185. */
  186. void populateListOfNeighbors(ArrayList<IntermediateCableWithState> edgeList, AbstractCpsObject lookAtObject,
  187. MinimumNetwork actualNetwork, LinkedList<AbstractCpsObject> neighbors) {
  188. ListIterator<IntermediateCableWithState> iter = edgeList.listIterator();
  189. while(iter.hasNext())
  190. {
  191. IntermediateCableWithState lookAtEdge = iter.next();
  192. if(lookAtEdge.getState() == CableState.Working && lookAtEdge.getModel().isConnectedTo(lookAtObject)) {
  193. iter.remove();
  194. actualNetwork.getEdgeList().add(lookAtEdge);
  195. //Add neighbar
  196. AbstractCpsObject edgeNeighbor;
  197. if(lookAtEdge.getModel().getA().equals(lookAtObject)) {
  198. edgeNeighbor = lookAtEdge.getModel().getB();
  199. }else {
  200. edgeNeighbor = lookAtEdge.getModel().getA();
  201. }
  202. if(!neighbors.contains(edgeNeighbor)) {
  203. neighbors.add(edgeNeighbor);
  204. }
  205. }
  206. }
  207. }
  208. /**
  209. * add all battries.getOut() from a list of battries and return them
  210. * @param aL a List of HolonBattries likely from subnet.getBatteries()
  211. * @param x TimeStep
  212. * @return
  213. *
  214. */
  215. private float GetOutAllBatteries(ArrayList<HolonBattery> aL, int x)
  216. {
  217. float OutEnergy = 0;
  218. for(HolonBattery hB : aL)
  219. {
  220. //System.out.println("Iteration: "+ x +"OutBattery: "+ hB.getOutAtTimeStep(x-1));
  221. OutEnergy += hB.getOutAtTimeStep(x-1);
  222. }
  223. //System.out.println("Iteration: "+ x +"GetOutAllBatteries: "+ OutEnergy);
  224. return OutEnergy;
  225. }
  226. /**
  227. * search for all flexible devices in the network and turn them on, until
  228. * energy surplus = 0 or all devices have been examined.
  229. *
  230. * This code could be compressed (cases inside over- and underproduction are
  231. * the same), but we decided that it is better readable this way
  232. *
  233. * @param subNet
  234. * the subnet
  235. * @param energySurplus
  236. * the current surplus of energy
  237. */
  238. private void turnOnFlexibleDevices(SubNet subNet, float energySurplus,
  239. int timestep) {
  240. for (HolonObject holonOb : subNet.getObjects()) {
  241. for (HolonElement holonEl : holonOb.getElements()) {
  242. // if this element is flexible and active (can be considered for
  243. // calculations)
  244. if (holonEl.isFlexible() && holonEl.isActive()) {
  245. float energyAvailableSingle = holonEl
  246. .getEnergyAtTimeStep(timestep);
  247. float energyAvailableMultiple = energyAvailableSingle
  248. * holonEl.getAmount();
  249. // ------------- flexible consumer / OVERPRODUCTION
  250. // -------------
  251. if (energyAvailableMultiple < 0 && energySurplus > 0) {
  252. // if there is more wasted energy than energy that this
  253. // device can give, give all energy available
  254. if (Math.abs(energyAvailableMultiple) <= Math
  255. .abs(energySurplus)) {
  256. energySurplus += energyAvailableMultiple;
  257. // set the new energy consumption to the maximum
  258. holonEl.setEnergyPerElement(energyAvailableSingle);
  259. flexDevicesTurnedOnThisTurn.put(holonEl,
  260. energyAvailableMultiple);
  261. }
  262. // else: we just need to turn on part of the flexible
  263. // energy available
  264. else {
  265. float energyNeeded = -energySurplus;
  266. energySurplus += energyNeeded; // should give 0, but
  267. // was kept this was
  268. // for consistency
  269. // the energy needed divided through the amount of
  270. // elements
  271. holonEl.setEnergyPerElement(energyNeeded
  272. / holonEl.getAmount());
  273. flexDevicesTurnedOnThisTurn.put(holonEl,
  274. energyNeeded);
  275. }
  276. }
  277. // ------------- flexible producer / UNDERPRODUCTION
  278. // -------------
  279. else if (energyAvailableMultiple > 0 && energySurplus < 0) {
  280. // if there is more energy needed than this device can
  281. // give, give all the energy available
  282. if (Math.abs(energyAvailableMultiple) <= Math
  283. .abs(energySurplus)) {
  284. energySurplus += energyAvailableMultiple;
  285. // set the new energy consumption to the maximum
  286. holonEl.setEnergyPerElement(energyAvailableSingle);
  287. flexDevicesTurnedOnThisTurn.put(holonEl,
  288. energyAvailableMultiple);
  289. }
  290. // else: we just need to turn on part of the flexible
  291. // energy available
  292. else {
  293. float energyNeeded = -energySurplus;
  294. int i = 0;
  295. energySurplus += energyNeeded; // should give 0, but
  296. // was kept this was
  297. // for consistency
  298. // the energy needed divided through the amount of
  299. // elements
  300. holonEl.setEnergyPerElement(energyNeeded
  301. / holonEl.getAmount());
  302. flexDevicesTurnedOnThisTurn.put(holonEl,
  303. energyNeeded);
  304. }
  305. }
  306. }
  307. if (energySurplus == 0) {
  308. break;
  309. }
  310. }
  311. if (energySurplus == 0) {
  312. break;
  313. }
  314. }
  315. }
  316. /**
  317. * Set Flow Simulation.
  318. *
  319. * @param sN
  320. * Subnet
  321. */
  322. /**
  323. * Set the Pseudo Tags.
  324. *
  325. * @param nodes
  326. * Array of AbstractCpsObjects
  327. */
  328. private void setPseudoTags(ArrayList<AbstractCpsObject> nodes,
  329. ArrayList<CpsEdge> edges) {
  330. for (AbstractCpsObject node : nodes) {
  331. node.recalculateTags();
  332. node.setPseudoTags(new ArrayList<>());
  333. }
  334. for (CpsEdge edge : edges) {
  335. edge.recalculateTags();
  336. edge.setPseudoTag(new ArrayList<>());
  337. }
  338. }
  339. /**
  340. * copies the data of an array of Objects.
  341. *
  342. * @param toCopy
  343. * the ArrayList of CpsObjects co Copy
  344. */
  345. private void copyObjects(ArrayList<AbstractCpsObject> toCopy) {
  346. for (AbstractCpsObject cps : toCopy) {
  347. if (cps instanceof CpsUpperNode) {
  348. copyObjects(((CpsUpperNode) cps).getNodes());
  349. } else {
  350. objectsToHandle.add(cps);
  351. }
  352. }
  353. }
  354. /**
  355. * Set the Canvas.
  356. *
  357. * @param can
  358. * the Canvas
  359. */
  360. public void setCanvas(MyCanvas can) {
  361. canvas = can;
  362. }
  363. /**
  364. * Should be a better way to update the canvas -.-
  365. * @param can
  366. */
  367. public void updateCanvas() {
  368. canvas.repaint();
  369. }
  370. /**
  371. * Reset all Data to the current state of the Model.
  372. */
  373. public void reset() {
  374. objectsToHandle = new ArrayList<>();
  375. copyObjects(model.getObjectsOnCanvas());
  376. flexDevicesTurnedOnThisTurn = new HashMap<>();
  377. }
  378. /**
  379. * Get all Subnets.Not functional.
  380. *
  381. * @return all Subnets
  382. */
  383. @Deprecated
  384. public ArrayList<SubNet> getSubNets() {
  385. return subNets;
  386. }
  387. /**
  388. * Get broken Edges
  389. */
  390. // public ArrayList<CpsEdge> getBrokenEdges() {
  391. // return brokenEdges;
  392. // }
  393. public FlexiblePane getFlexiblePane() {
  394. return flexPane;
  395. }
  396. void setFlexiblePane(FlexiblePane fp) {
  397. flexPane = fp;
  398. }
  399. public DecoratedState getActualDecorStateWithOffSet(int offSet) {
  400. return getDecorState(timeStep + offSet);
  401. }
  402. public DecoratedState getActualDecorState() {
  403. return getDecorState(timeStep);
  404. }
  405. public VisualRepresentationalState getActualVisualRepresentationalState(){
  406. return savesVisual.getOrDefault(timeStep, null);
  407. }
  408. public DecoratedState getDecorState(int timestep) {
  409. return saves.getOrDefault(timestep, null);
  410. }
  411. public void setGui(GUI gui) {
  412. this.gui = gui;
  413. }
  414. public HashMap<Integer, VisualRepresentationalState> getSavesVisual() {
  415. return savesVisual;
  416. }
  417. }