SimulateSimulator.java 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812
  1. package psoAlgoCode;
  2. import classes.*;
  3. import classes.comparator.EnergyMinToMaxComparator;
  4. import classes.comparator.MinEnergyComparator;
  5. import classes.comparator.WeakestBattery;
  6. import ui.model.Model;
  7. import java.util.ArrayList;
  8. import java.util.Collections;
  9. import java.util.HashMap;
  10. /**
  11. * Controller for Simulation.
  12. *
  13. * @author Gruppe14
  14. */
  15. public class SimulateSimulator {
  16. int global = 0;
  17. private Model model;
  18. private ArrayList<AbstractCpsObject> objectsToHandle;
  19. private ArrayList<SubNet> subNets;
  20. private ArrayList<CpsEdge> brokenEdges;
  21. private int timeStep;
  22. private HashMap<Integer, Float> tagTable = new HashMap<>();
  23. private HashMap<HolonElement, Float> flexDevicesTurnedOnThisTurn = new HashMap<>();
  24. /**
  25. * One Element of each HolonObject will be powered first, starting with the
  26. * smallest Demand. If ale HolonObjects have an active Element, the simulation
  27. * will try to fully supply as many HolonObjects as possible.
  28. */
  29. public static final short fairnessMininumDemandFirst = 0;
  30. /**
  31. * All HolonObjects will receive the same amount of energy.
  32. */
  33. public static final short fairnessAllEqual = 1;
  34. /**
  35. * Constructor.
  36. *
  37. * @param m
  38. * Model
  39. */
  40. SimulateSimulator(Model m) {
  41. model = m;
  42. subNets = new ArrayList<>();
  43. brokenEdges = new ArrayList<>();
  44. }
  45. /**
  46. * calculates the flow of the edges and the supply for objects.
  47. *
  48. * @param x
  49. * current Iteration
  50. */
  51. void calculateStateForTimeStep(int x) {
  52. reset();
  53. timeStep = x;
  54. searchForSubNets();
  55. /**
  56. * Some state reset stuff, seems to be very unnecessary.... COMMENT THIS IN IF STRANGE CALCULATION STUFF HAPPENS
  57. */
  58. for (SubNet singleSubNet : subNets) {
  59. if (singleSubNet.getObjects().size() == 0) {
  60. resetConnections(singleSubNet.getBatteries().get(0), new ArrayList<>(), new ArrayList<>());
  61. } else {
  62. resetConnections(singleSubNet.getObjects().get(0), new ArrayList<>(), new ArrayList<>());
  63. }
  64. }
  65. for (SubNet singleSubNet : subNets) {
  66. float production = calculateEnergyWithoutFlexDevices("prod", singleSubNet, timeStep);
  67. float consumption = calculateEnergyWithoutFlexDevices("cons", singleSubNet, timeStep);
  68. // surplus of energy is computed by sum, since consumption is a
  69. // negative value
  70. float energySurplus = production + consumption;
  71. // --------------- use flexible devices ---------------
  72. /*if (energySurplus != 0 && model.useFlexibleDevices()) {
  73. turnOnFlexibleDevices(singleSubNet, energySurplus, x);
  74. // recompute after having examined/turned on all flexible
  75. // devices
  76. production = calculateEnergyWithFlexDevices("prod", singleSubNet, timeStep);
  77. consumption = calculateEnergyWithFlexDevices("cons", singleSubNet, timeStep);
  78. energySurplus = production + consumption;
  79. }*/
  80. // --------------- set flow simulation ---------------
  81. setFlowSimulation(singleSubNet);
  82. // --------------- visualise graph ---------------
  83. /**
  84. * production of subnets, that might be partially turned on/off
  85. */
  86. float currentProduction = production;
  87. /**
  88. * energy each HolonObject receives in AlleEqualModus
  89. */
  90. if (energySurplus >= 0) {
  91. // Supply all consumer
  92. for (HolonObject hO : singleSubNet.getObjects()) {
  93. float neededEnergy = hO.getCurrentEnergyAtTimeStep(x);
  94. if (neededEnergy < 0) {
  95. hO.setCurrentSupply(-neededEnergy);
  96. currentProduction -= -neededEnergy; // Subtract the Energy from the Production
  97. }
  98. }
  99. // Supply all Batterys with the left currentProduction
  100. singleSubNet.getBatteries().sort(new WeakestBattery(x));// Sort all batteries by the Value of ther
  101. // StateOfCharge/Capasity
  102. for (HolonBattery hB : singleSubNet.getBatteries()) {
  103. float energyToCollect = hB.getInAtTimeStep(x - 1);
  104. if (currentProduction >= energyToCollect) {
  105. // change StateofCharge soc = soc + energyToCollect
  106. hB.setStateOfChargeAtTimeStep(hB.getStateOfChargeAtTimeStep(x - 1) + energyToCollect, x);
  107. currentProduction -= energyToCollect;
  108. } else {
  109. // change StateofCharge soc = soc + currentProduction
  110. hB.setStateOfChargeAtTimeStep(hB.getStateOfChargeAtTimeStep(x - 1) + currentProduction, x);
  111. currentProduction = 0;
  112. // no break must be calculatet for all break; //because no more energy
  113. }
  114. }
  115. // Over_Supply all consumer equal
  116. long nOConsumer = singleSubNet.getObjects().stream()
  117. .filter(hl -> (hl.getCurrentEnergyAtTimeStep(x) < 0)).count();
  118. if (nOConsumer != 0) {
  119. // energy to seperated equal
  120. float EnergyOverSupplyPerHolonObject = currentProduction / nOConsumer;
  121. for (HolonObject hO : singleSubNet.getObjects()) {
  122. float neededEnergy = hO.getCurrentEnergyAtTimeStep(x);
  123. if (neededEnergy < 0) {
  124. hO.setCurrentSupply(hO.getCurrentSupply() + EnergyOverSupplyPerHolonObject);
  125. }
  126. }
  127. currentProduction = 0;
  128. }
  129. } else {
  130. // Check all Battries what they can provide
  131. if (energySurplus + GetOutAllBatteries(singleSubNet.getBatteries(), x) >= 0) {
  132. singleSubNet.getBatteries().sort(new WeakestBattery(x));// .reverse();
  133. Collections.reverse(singleSubNet.getBatteries()); // most supplyed first
  134. // Get the NEEDED energy
  135. for (HolonBattery hB : singleSubNet.getBatteries()) {
  136. float neededEnergyFromBattery = currentProduction + consumption; // Energy is negativ
  137. float maxEnergyAvailable = hB.getOutAtTimeStep(x - 1); // energy is positiv
  138. if (maxEnergyAvailable >= -neededEnergyFromBattery) {
  139. // change StateofCharge soc = soc - -neededEnergyFromBattery
  140. hB.setStateOfChargeAtTimeStep(
  141. hB.getStateOfChargeAtTimeStep(x - 1) - -neededEnergyFromBattery, x);
  142. currentProduction += -neededEnergyFromBattery;
  143. // no break must be calculatet for all beabreak; //When a energy can supply the
  144. // last needed energy break;
  145. } else {
  146. // change StateofCharge soc = soc - maxEnergyAvailable
  147. hB.setStateOfChargeAtTimeStep(hB.getStateOfChargeAtTimeStep(x - 1) - maxEnergyAvailable, x);
  148. currentProduction += maxEnergyAvailable;
  149. }
  150. }
  151. // Supply all consumer all ar in state Supplied no one is oversupplied because
  152. // just the energy that is needed is gained from the batteries
  153. for (HolonObject hO : singleSubNet.getObjects()) {
  154. float neededEnergy = hO.getCurrentEnergyAtTimeStep(x);
  155. if (neededEnergy < 0) {
  156. hO.setCurrentSupply(-neededEnergy);
  157. currentProduction -= -neededEnergy; // Subtract the Energy from the Production
  158. }
  159. }
  160. } else // Objects have to be partially supplied
  161. {
  162. // Get all Energy out of battries as possible
  163. for (HolonBattery hB : singleSubNet.getBatteries()) {
  164. float maxEnergyAvailable = hB.getOutAtTimeStep(x - 1); // energy is positiv
  165. // change StateofCharge soc = soc - maxEnergyAvailable
  166. hB.setStateOfChargeAtTimeStep(hB.getStateOfChargeAtTimeStep(x - 1) - maxEnergyAvailable, x);
  167. currentProduction += maxEnergyAvailable;
  168. }
  169. // Calc
  170. singleSubNet.getObjects().stream().forEach(hl -> hl.setCurrentSupply(0));
  171. if (model.getFairnessModel() == fairnessAllEqual) {
  172. long nOConsumer = singleSubNet.getObjects().stream()
  173. .filter(hl -> (hl.getCurrentEnergyAtTimeStep(x) < 0)).count();
  174. float energyPerHolonObject = 0;
  175. if (nOConsumer != 0)
  176. energyPerHolonObject = currentProduction / nOConsumer;
  177. for (HolonObject hO : singleSubNet.getObjects()) {
  178. if (hO.getCurrentEnergyAtTimeStep(x) < 0) // Just Consumer need Energy
  179. {
  180. hO.setCurrentSupply(energyPerHolonObject);
  181. currentProduction -= energyPerHolonObject; // Subtract the Energy from the Production
  182. }
  183. }
  184. } else // (model.getFairnessModel() == fairnessMininumDemandFirst)
  185. {
  186. singleSubNet.getObjects().sort(new MinEnergyComparator(x));
  187. // SupplyAllMinimumEnergy
  188. for (HolonObject hO : singleSubNet.getObjects()) {
  189. if (hO.checkIfPartiallySupplied(x))
  190. continue;
  191. if (hO.getCurrentEnergyAtTimeStep(x) > 0)
  192. continue;
  193. float minEnergy = -hO.getMinEnergyNecessaryAtTimestep(x); // Energy from getMinEnergy is negative -> convert to
  194. // positive
  195. if (minEnergy <= currentProduction) {
  196. hO.setCurrentSupply(minEnergy);
  197. currentProduction -= minEnergy;
  198. } else {
  199. hO.setCurrentSupply(currentProduction);
  200. currentProduction = 0;
  201. break;
  202. }
  203. }
  204. singleSubNet.getObjects().sort(new EnergyMinToMaxComparator(x));
  205. // supplyFullytillEnd ... because its cant be fully supplied
  206. for (HolonObject hO : singleSubNet.getObjects()) {
  207. float actualSupplyEnergy = hO.getCurrentSupply();
  208. float neededEnergy = -hO.getCurrentEnergyAtTimeStep(x) - actualSupplyEnergy;
  209. if (neededEnergy <= 0)
  210. continue; // Producer or No EnergyNeeded
  211. if (neededEnergy <= currentProduction) {
  212. hO.setCurrentSupply(neededEnergy + actualSupplyEnergy);
  213. currentProduction -= neededEnergy;
  214. } else {
  215. hO.setCurrentSupply(currentProduction + actualSupplyEnergy);
  216. currentProduction = 0;
  217. break;
  218. }
  219. }
  220. }
  221. }
  222. }
  223. // Visualize the Color
  224. for (HolonObject hO : singleSubNet.getObjects()) {
  225. float neededEnergy = -hO.getCurrentEnergyAtTimeStep(x); // convert negative energy in positive for
  226. // calculations
  227. if (neededEnergy < 0) {
  228. hO.setState(HolonObject.PRODUCER);
  229. } else if (neededEnergy > 0) {
  230. float currentSupply = hO.getCurrentSupply();
  231. if (currentSupply > neededEnergy) {
  232. hO.setState(HolonObject.OVER_SUPPLIED);
  233. } else if (currentSupply == neededEnergy) {
  234. hO.setState(HolonObject.SUPPLIED);
  235. } else if (currentSupply < neededEnergy) {
  236. float minEnergy = -hO.getMinEnergyNecessaryAtTimestep(x);
  237. if (currentSupply >= minEnergy || hO.getSelfMadeEnergy(x) >= minEnergy) {
  238. hO.setState(HolonObject.PARTIALLY_SUPPLIED);
  239. } else {
  240. hO.setState(HolonObject.NOT_SUPPLIED);
  241. }
  242. }
  243. } else if (neededEnergy == 0) {
  244. hO.setState(HolonObject.NO_ENERGY);
  245. }
  246. }
  247. }
  248. }
  249. /**
  250. * add all battries.getOut() from a list of battries and return them
  251. *
  252. * @param aL
  253. * a List of HolonBattries likely from subnet.getBatteries()
  254. * @param x
  255. * TimeStep
  256. * @return
  257. *
  258. */
  259. private float GetOutAllBatteries(ArrayList<HolonBattery> aL, int x) {
  260. float OutEnergy = 0;
  261. for (HolonBattery hB : aL) {
  262. OutEnergy += hB.getOutAtTimeStep(x - 1);
  263. }
  264. return OutEnergy;
  265. }
  266. /**
  267. * search for all flexible devices in the network and turn them on, until energy
  268. * surplus = 0 or all devices have been examined.
  269. *
  270. * This code could be compressed (cases inside over- and underproduction are the
  271. * same), but we decided that it is better readable this way
  272. *
  273. * @param subNet
  274. * the subnet
  275. * @param energySurplus
  276. * the current surplus of energy
  277. */
  278. private void turnOnFlexibleDevices(SubNet subNet, float energySurplus, int timestep) {
  279. for (HolonObject holonOb : subNet.getObjects()) {
  280. for (HolonElement holonEl : holonOb.getElements()) {
  281. // if this element is flexible and active (can be considered for
  282. // calculations)
  283. if (holonEl.isFlexible() && holonEl.isActive()) {
  284. float energyAvailableSingle = holonEl.getAvailableEnergyAt(timestep);
  285. float energyAvailableMultiple = energyAvailableSingle * holonEl.getAmount();
  286. // ------------- flexible consumer / OVERPRODUCTION
  287. // -------------
  288. if (energyAvailableMultiple < 0 && energySurplus > 0) {
  289. // if there is more wasted energy than energy that this
  290. // device can give, give all energy available
  291. if (Math.abs(energyAvailableMultiple) <= Math.abs(energySurplus)) {
  292. energySurplus += energyAvailableMultiple;
  293. // set the new energy consumption to the maximum
  294. holonEl.setEnergyPerElement(energyAvailableSingle);
  295. flexDevicesTurnedOnThisTurn.put(holonEl, energyAvailableMultiple);
  296. }
  297. // else: we just need to turn on part of the flexible
  298. // energy available
  299. else {
  300. float energyNeeded = -energySurplus;
  301. energySurplus += energyNeeded; // should give 0, but
  302. // was kept this was
  303. // for consistency
  304. // the energy needed divided through the amount of
  305. // elements
  306. holonEl.setEnergyPerElement(energyNeeded / holonEl.getAmount());
  307. flexDevicesTurnedOnThisTurn.put(holonEl, energyNeeded);
  308. }
  309. }
  310. // ------------- flexible producer / UNDERPRODUCTION
  311. // -------------
  312. else if (energyAvailableMultiple > 0 && energySurplus < 0) {
  313. // if there is more energy needed than this device can
  314. // give, give all the energy available
  315. if (Math.abs(energyAvailableMultiple) <= Math.abs(energySurplus)) {
  316. energySurplus += energyAvailableMultiple;
  317. // set the new energy consumption to the maximum
  318. holonEl.setEnergyPerElement(energyAvailableSingle);
  319. flexDevicesTurnedOnThisTurn.put(holonEl, energyAvailableMultiple);
  320. }
  321. // else: we just need to turn on part of the flexible
  322. // energy available
  323. else {
  324. float energyNeeded = -energySurplus;
  325. int i = 0;
  326. energySurplus += energyNeeded; // should give 0, but
  327. // was kept this was
  328. // for consistency
  329. // the energy needed divided through the amount of
  330. // elements
  331. holonEl.setEnergyPerElement(energyNeeded / holonEl.getAmount());
  332. flexDevicesTurnedOnThisTurn.put(holonEl, energyNeeded);
  333. }
  334. }
  335. }
  336. if (energySurplus == 0) {
  337. break;
  338. }
  339. }
  340. if (energySurplus == 0) {
  341. break;
  342. }
  343. }
  344. }
  345. /**
  346. * Set Flow Simulation.
  347. *
  348. * @param sN
  349. * Subnet
  350. */
  351. private void setFlowSimulation(SubNet sN) {
  352. ArrayList<AbstractCpsObject> producers = new ArrayList<>();
  353. AbstractCpsObject tmp = null;
  354. tagTable = new HashMap<>();
  355. // traverse all objects in this subnet
  356. for (HolonObject hl : sN.getObjects()) {
  357. float energy = hl.getCurrentEnergyAtTimeStep(timeStep);
  358. // if their production is higher than their consumption
  359. if (energy > 0) {
  360. tagTable.put(hl.getId(), energy);
  361. hl.addTag(hl.getId());
  362. for (CpsEdge edge : hl.getConnections()) {
  363. if (edge.isWorking()) {
  364. // set other end of edge as tmp-object
  365. // and add this end to the other end's tag-list
  366. AbstractCpsObject a = edge.getA();
  367. AbstractCpsObject b = edge.getB();
  368. if (a.getId() == hl.getId()) {
  369. b.addTag(hl.getId());
  370. tmp = b;
  371. }
  372. if (b.getId() == hl.getId()) {
  373. a.addTag(hl.getId());
  374. tmp = a;
  375. }
  376. edge.setFlow(edge.getFlow() + energy);
  377. edge.calculateState();
  378. edge.addTag(hl.getId());
  379. if (edge.isWorking() && !producers.contains(tmp)) {
  380. if (tmp instanceof HolonSwitch) {
  381. if (((HolonSwitch) tmp).getState(timeStep)) {
  382. producers.add(tmp);
  383. }
  384. } else if (!(tmp instanceof CpsUpperNode)) {
  385. producers.add(tmp);
  386. }
  387. }
  388. }
  389. }
  390. }
  391. }
  392. setFlowSimRec(producers, 0);
  393. }
  394. /**
  395. * Set Flow Simulation Rec.
  396. *
  397. * @param nodes
  398. * the nodes
  399. * @param iter
  400. * the Iteration
  401. */
  402. private void setFlowSimRec(ArrayList<AbstractCpsObject> nodes, int iter) {
  403. ArrayList<AbstractCpsObject> newNodes = new ArrayList<>();
  404. ArrayList<CpsEdge> changedEdges = new ArrayList<>();
  405. AbstractCpsObject tmp;
  406. if (nodes.size() != 0) {
  407. for (AbstractCpsObject cps : nodes) {
  408. // check whether the cps is in a legit state if it is a switch
  409. if (legitState(cps)) {
  410. for (CpsEdge edge : cps.getConnections()) {
  411. // is edge working
  412. // and does the edge's tag-list not (yet) contain all
  413. // tags of the cps
  414. if (edge.isWorking() && (!(edge.containsTags(edge.getTags(), cps.getTag())))) {
  415. if (edge.getA().getId() == cps.getId()) {
  416. tmp = edge.getB();
  417. } else {
  418. tmp = edge.getA();
  419. }
  420. for (Integer tag : cps.getTag()) {
  421. if (!(edge.getTags().contains(tag)) && !(edge.getPseudoTags().contains(tag))) {
  422. edge.setFlow(edge.getFlow() + tagTable.get(tag));
  423. edge.addTag(tag);
  424. }
  425. }
  426. // uppernodes do not spread energy
  427. if (!(tmp instanceof CpsUpperNode)) {
  428. for (Integer tag : tmp.getTag()) {
  429. if (!(edge.getTags().contains(tag)) && tagTable.get(tag) != null
  430. && !(edge.getPseudoTags().contains(tag))) {
  431. edge.setFlow(edge.getFlow() + tagTable.get(tag));
  432. edge.addPseudoTag(tag);
  433. changedEdges.add(edge);
  434. }
  435. }
  436. }
  437. edge.calculateState();
  438. if (edge.isWorking() && !(tmp instanceof CpsUpperNode)) {
  439. tmp.addAllPseudoTags(cps.getTag());
  440. if (!newNodes.contains(tmp)) {
  441. newNodes.add(tmp);
  442. }
  443. }
  444. }
  445. }
  446. }
  447. }
  448. setPseudoTags(newNodes, changedEdges);
  449. setFlowSimRec(newNodes, iter + 1);
  450. }
  451. }
  452. /**
  453. * Set the Pseudo Tags.
  454. *
  455. * @param nodes
  456. * Array of AbstractCpsObjects
  457. */
  458. private void setPseudoTags(ArrayList<AbstractCpsObject> nodes, ArrayList<CpsEdge> edges) {
  459. for (AbstractCpsObject node : nodes) {
  460. node.recalculateTags();
  461. node.setPseudoTags(new ArrayList<>());
  462. }
  463. for (CpsEdge edge : edges) {
  464. edge.recalculateTags();
  465. edge.setPseudoTag(new ArrayList<>());
  466. }
  467. }
  468. /**
  469. * Reset the Connection.
  470. *
  471. * @param cps
  472. * CpsObject
  473. * @param visitedObj
  474. * the visited Objects
  475. * @param visitedEdges
  476. * the visited Edges
  477. */
  478. private void resetConnections(AbstractCpsObject cps, ArrayList<Integer> visitedObj,
  479. ArrayList<CpsEdge> visitedEdges) {
  480. visitedObj.add(cps.getId());
  481. cps.resetTags();
  482. for (CpsEdge e : cps.getConnections()) {
  483. if (!(visitedEdges.contains(e))) {
  484. e.setFlow(0);
  485. e.calculateState();
  486. e.setTags(new ArrayList<>());
  487. visitedEdges.add(e);
  488. if (!(visitedObj.contains(e.getA().getId()))) {
  489. resetConnections(e.getA(), visitedObj, visitedEdges);
  490. e.getA().resetTags();
  491. }
  492. if (!(visitedObj.contains(e.getB().getId()))) {
  493. resetConnections(e.getB(), visitedObj, visitedEdges);
  494. e.getB().resetTags();
  495. }
  496. }
  497. }
  498. }
  499. /**
  500. * calculates the energy of either all producers or consumers. Flexible devices
  501. * are filtered out
  502. *
  503. * @param type
  504. * Type
  505. * @param sN
  506. * Subnet
  507. * @param x
  508. * Integer
  509. * @return The Energy
  510. */
  511. private float calculateEnergyWithoutFlexDevices(String type, SubNet sN, int x) {
  512. float energy = 0;
  513. for (HolonObject hl : sN.getObjects()) {
  514. float currentEnergyWithoutFlexibles = hl.getCurrentEnergyAtTimeStepWithoutFlexiblesAndResetFlexibles(x);
  515. if (type.equals("prod")) {
  516. if (currentEnergyWithoutFlexibles > 0) {
  517. energy += currentEnergyWithoutFlexibles;
  518. hl.setState(HolonObject.PRODUCER);
  519. }
  520. }
  521. if (type.equals("cons")) {
  522. if (currentEnergyWithoutFlexibles < 0) {
  523. energy += currentEnergyWithoutFlexibles;
  524. hl.setState(HolonObject.NOT_SUPPLIED);
  525. }
  526. }
  527. if (currentEnergyWithoutFlexibles == 0) {
  528. hl.setState(HolonObject.NO_ENERGY);
  529. }
  530. }
  531. return energy;
  532. }
  533. /**
  534. * calculates the energy of either all producers or consumers. Flexible devices
  535. * are filtered out
  536. *
  537. * @param type
  538. * Type
  539. * @param sN
  540. * Subnet
  541. * @param x
  542. * Integer
  543. * @return The Energy
  544. */
  545. private float calculateEnergyWithFlexDevices(String type, SubNet sN, int x) {
  546. float energy = 0;
  547. for (HolonObject hl : sN.getObjects()) {
  548. float currentEnergy = hl.getCurrentEnergyAtTimeStep(x);
  549. if (type.equals("prod")) {
  550. if (currentEnergy > 0) {
  551. energy += currentEnergy;
  552. hl.setState(HolonObject.PRODUCER);
  553. }
  554. }
  555. if (type.equals("cons")) {
  556. if (currentEnergy < 0) {
  557. energy = energy + currentEnergy;
  558. hl.setState(HolonObject.NOT_SUPPLIED);
  559. }
  560. }
  561. if (currentEnergy == 0) {
  562. hl.setState(HolonObject.NO_ENERGY);
  563. }
  564. }
  565. return energy;
  566. }
  567. /**
  568. * generates all subNets from all objectsToHandle.
  569. */
  570. private void searchForSubNets() {
  571. subNets = new ArrayList<>();
  572. brokenEdges.clear();
  573. boolean end = false;
  574. int i = 0;
  575. AbstractCpsObject cps;
  576. if (objectsToHandle.size() > 0) {
  577. while (!end) {
  578. cps = objectsToHandle.get(i);
  579. //SubNet singleSubNet = new SubNet(new ArrayList<>(), new ArrayList<>(), new ArrayList<>(),
  580. // new ArrayList<>());
  581. SubNet singleSubNet = buildSubNet(cps, new ArrayList<>());
  582. if (singleSubNet.getObjects().size() + singleSubNet.getBatteries().size() != 0) {
  583. subNets.add(singleSubNet);
  584. }
  585. if (0 == objectsToHandle.size()) {
  586. end = true;
  587. }
  588. }
  589. }
  590. }
  591. /**
  592. * recursivly generates a subnet of all objects, that one specific object is
  593. * connected to.
  594. *
  595. * @param cps
  596. * AbstractCpsObject
  597. * @param visited
  598. * visited Array of Integer
  599. * @param sN
  600. * Subnets
  601. * @return Subnet
  602. */
  603. private SubNet buildSubNet(AbstractCpsObject cps, ArrayList<Integer> visited) {
  604. SubNet sN = new SubNet(new ArrayList<>(), new ArrayList<>(), new ArrayList<>(), new ArrayList<>());
  605. visited.add(cps.getId());
  606. if (cps instanceof HolonObject) {
  607. sN.getObjects().add((HolonObject) cps);
  608. }
  609. if (cps instanceof HolonSwitch) {
  610. sN.getSwitches().add((HolonSwitch) cps);
  611. }
  612. if (cps instanceof HolonBattery) {
  613. sN.getBatteries().add((HolonBattery) cps);
  614. }
  615. removeFromToHandle(cps.getId());
  616. AbstractCpsObject a;
  617. AbstractCpsObject b;
  618. for (CpsEdge edge : cps.getConnections()) {
  619. if (edge.isWorking()) {
  620. a = edge.getA();
  621. b = edge.getB();
  622. if (!(cps instanceof HolonSwitch)) {
  623. if (!(sN.getEdges().contains(edge))) {
  624. sN.getEdges().add(edge);
  625. }
  626. }
  627. if (cps instanceof HolonSwitch && ((HolonSwitch) cps).getState(timeStep)) {
  628. if (!(sN.getEdges().contains(edge))) {
  629. sN.getEdges().add(edge);
  630. }
  631. }
  632. if (!visited.contains(a.getId()) && legitState(cps) && !(a instanceof CpsUpperNode)) {
  633. sN = buildSubNet(a, visited);
  634. }
  635. if (!visited.contains(b.getId()) && legitState(cps) && !(b instanceof CpsUpperNode)) {
  636. sN = buildSubNet(b, visited);
  637. }
  638. if (a instanceof CpsUpperNode && a.getId() != cps.getId()) {
  639. edge.setConnected(CpsEdge.CON_UPPER_NODE_NOT_INSIDE);
  640. checkForConnectedStates(b, (CpsUpperNode) a, edge);
  641. }
  642. if (b instanceof CpsUpperNode && b.getId() != cps.getId()) {
  643. edge.setConnected(CpsEdge.CON_UPPER_NODE_NOT_INSIDE);
  644. checkForConnectedStates(a, (CpsUpperNode) b, edge);
  645. }
  646. } else {
  647. brokenEdges.add(edge);
  648. }
  649. }
  650. return sN;
  651. }
  652. /**
  653. * is the Switch in a legitimate State.
  654. *
  655. * @param current
  656. * AbstractCpsObject
  657. * @return boolean
  658. */
  659. private boolean legitState(AbstractCpsObject current) {
  660. return !(current instanceof HolonSwitch) || ((HolonSwitch) current).getState(timeStep);
  661. }
  662. // /**
  663. // * ensures that objectsToHandle only contains HolonObjects.
  664. // */
  665. // public void cleanObjectsToHandle() {
  666. // for (int i = 0; i < objectsToHandle.size(); i++) {
  667. // if (!(objectsToHandle.get(i) instanceof HolonObject)) {
  668. // objectsToHandle.remove(i);
  669. // }
  670. // }
  671. // }
  672. /**
  673. * removes an Object that already has been handled.
  674. *
  675. * @param id
  676. * the Object ID
  677. */
  678. private void removeFromToHandle(int id) {
  679. for (int i = 0; i < objectsToHandle.size(); i++) {
  680. if (objectsToHandle.get(i).getId() == id) {
  681. objectsToHandle.remove(i);
  682. }
  683. }
  684. }
  685. /**
  686. * copies the data of an array of Objects.
  687. *
  688. * @param toCopy
  689. * the ArrayList of CpsObjects co Copy
  690. */
  691. private void copyObjects(ArrayList<AbstractCpsObject> toCopy) {
  692. for (AbstractCpsObject cps : toCopy) {
  693. if (cps instanceof CpsUpperNode) {
  694. copyObjects(((CpsUpperNode) cps).getNodes());
  695. } else {
  696. objectsToHandle.add(cps);
  697. }
  698. }
  699. }
  700. /**
  701. * Reset all Data to the current state of the Model.
  702. */
  703. public void reset() {
  704. objectsToHandle = new ArrayList<>();
  705. copyObjects(model.getObjectsOnCanvas());
  706. flexDevicesTurnedOnThisTurn = new HashMap<>();
  707. }
  708. /**
  709. * Resets the State of all Edges
  710. */
  711. private void resetEdges() {
  712. for (CpsEdge e : brokenEdges) {
  713. e.setWorkingState(true);
  714. }
  715. }
  716. /**
  717. * Resets the State for the whole Simulation Model
  718. */
  719. void resetSimulation() {
  720. reset();
  721. resetEdges();
  722. }
  723. /**
  724. * Get all Subnets.
  725. *
  726. * @return all Subnets
  727. */
  728. public ArrayList<SubNet> getSubNets() {
  729. return subNets;
  730. }
  731. /**
  732. * Get broken Edges
  733. */
  734. public ArrayList<CpsEdge> getBrokenEdges() {
  735. return brokenEdges;
  736. }
  737. /**
  738. * checks whether a given object is connected to an object inside the upperNode.
  739. * if yes, the state for the edge is changed in "connected" or "not connected"
  740. */
  741. private void checkForConnectedStates(AbstractCpsObject cps, CpsUpperNode cUNode, CpsEdge theEdge) {
  742. AbstractCpsObject tmp;
  743. for (CpsEdge edge : cps.getConnections()) {
  744. if (edge.getA().getId() == cps.getId()) {
  745. tmp = edge.getB();
  746. } else {
  747. tmp = edge.getA();
  748. }
  749. if (cUNode.getNodes().contains(tmp)) {
  750. if (tmp instanceof CpsUpperNode) {
  751. checkForConnectedStates(cps, (CpsUpperNode) tmp, theEdge);
  752. } else {
  753. theEdge.setConnected(CpsEdge.CON_UPPER_NODE_AND_INSIDE);
  754. break;
  755. }
  756. }
  757. }
  758. }
  759. }