StatisticGraph.java 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479
  1. package ui.view;
  2. import java.awt.BasicStroke;
  3. import java.awt.Color;
  4. import java.awt.Graphics;
  5. import java.awt.Graphics2D;
  6. import java.awt.Image;
  7. import java.awt.RenderingHints;
  8. import java.awt.event.ActionEvent;
  9. import java.awt.event.ActionListener;
  10. import java.awt.geom.GeneralPath;
  11. import java.util.ArrayList;
  12. import javax.swing.ImageIcon;
  13. import javax.swing.JPanel;
  14. import javax.swing.Timer;
  15. import classes.AbstractCpsObject;
  16. import classes.CpsUpperNode;
  17. import classes.HolonElement;
  18. import classes.HolonObject;
  19. import classes.HolonSwitch;
  20. import classes.TrackedDataSet;
  21. import ui.controller.Control;
  22. import ui.model.Model;
  23. public class StatisticGraph extends JPanel {
  24. /**
  25. *
  26. */
  27. private static final long serialVersionUID = 1L;
  28. // Maximum y Value
  29. float maximum = 0;
  30. // is the Simulation running?
  31. private boolean isSimRunning;
  32. // model and controller
  33. private Model model;
  34. private Control controller;
  35. // Graphics2D
  36. private Graphics2D g2;
  37. GeneralPath path = new GeneralPath();
  38. // Data
  39. public ArrayList<TrackedDataSet> objects = new ArrayList<>();
  40. /**
  41. * Constructor.
  42. *
  43. * @param model
  44. * the Model
  45. * @param control
  46. * the Controller
  47. */
  48. public StatisticGraph(final Model model, Control control) {
  49. this.controller = control;
  50. this.model = model;
  51. this.setBackground(Color.WHITE);
  52. }
  53. /**
  54. * Paints all Components on the Canvas.
  55. *
  56. * @param g
  57. * Graphics
  58. *
  59. */
  60. public void paintComponent(Graphics g) {
  61. super.paintComponent(g);
  62. // Graphics2D init
  63. g2 = (Graphics2D) g;
  64. RenderingHints rh = new RenderingHints(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
  65. g2.setRenderingHints(rh);
  66. // Paint the Grid
  67. g2.setStroke(new BasicStroke(0));
  68. g2.setColor(Color.BLACK);
  69. for (int i = 0; i <= this.getWidth(); i += 10) {
  70. g2.drawLine(i, 0, i, this.getHeight());
  71. }
  72. for (int i = 0; i <= this.getHeight(); i += 5) {
  73. g2.drawLine(0, i, this.getWidth(), i);
  74. }
  75. isSimRunning = model.getIsSimulation();
  76. // if sim is on
  77. if (isSimRunning) {
  78. g2.setStroke(new BasicStroke(3));
  79. // Calculate the Maximum
  80. calcMaximum();
  81. // Calculate values for each set and add them
  82. addValues();
  83. // Create Paths and draw them
  84. for (TrackedDataSet set : objects) {
  85. path.reset();
  86. switch (set.getProperty()) {
  87. case TrackedDataSet.CONSUMPTION:
  88. case TrackedDataSet.PRODUCTION:
  89. case TrackedDataSet.ACTIVATED_ELEMENTS:
  90. case TrackedDataSet.TOTAL_PRODUCTION:
  91. case TrackedDataSet.TOTAL_CONSUMPTION:
  92. createPathFloats(set);
  93. break;
  94. case TrackedDataSet.ON_OFF:
  95. createPathBooleans(set);
  96. break;
  97. case TrackedDataSet.PERCENT_SUPPLIED:
  98. case TrackedDataSet.PERCENT_NOT_SUPPLIED:
  99. case TrackedDataSet.PERCENT_PARTIAL_SUPPLIED:
  100. createPathPercent(set);
  101. break;
  102. default:
  103. break;
  104. }
  105. g2.setColor(set.getColor());
  106. g2.draw(path);
  107. }
  108. }
  109. }
  110. /**
  111. * Add an Object to the Graph if the maximum has not reached yet.
  112. *
  113. * @param obj
  114. * the Object to add
  115. */
  116. public void addObject(TrackedDataSet set) {
  117. objects.add(set);
  118. }
  119. /**
  120. * Removes an Object from the Graph.
  121. *
  122. * @param id
  123. * the id of the Object to remove
  124. */
  125. public void removeObject(int id) {
  126. objects.remove(id);
  127. }
  128. /**
  129. * converts the number to fit the canvas.
  130. *
  131. * @param d
  132. * the number to convert
  133. * @return the converted number
  134. */
  135. public double convertToCanvasY(float d) {
  136. return Math.abs((this.getHeight() - (d * (this.getHeight() / maximum))));
  137. }
  138. /**
  139. * Does take into account which timestep is watched, calculates the max
  140. * values.
  141. *
  142. * @return the currentEnergy
  143. */
  144. public float getEnergyAtCurrentTimeStep(HolonObject obj) {
  145. float temp = 0;
  146. for (HolonElement e : obj.getElements()) {
  147. if (e.getActive()) {
  148. temp = temp + e.getEnergyAt()[model.getCurIteration()];
  149. }
  150. }
  151. return temp;
  152. }
  153. /**
  154. * Calculate the Max Value of the Graph
  155. */
  156. public void calcMaximum() {
  157. maximum = 0;
  158. for (TrackedDataSet set : objects) {
  159. float val = 0;
  160. switch (set.getProperty()) {
  161. case TrackedDataSet.CONSUMPTION:
  162. for (HolonElement h : ((HolonObject) set.getCpsObject()).getElements()) {
  163. if (h.getEnergy() < 0) {
  164. val += h.getEnergy() * h.getAmount();
  165. }
  166. }
  167. val *= -1;
  168. break;
  169. case TrackedDataSet.PRODUCTION:
  170. for (HolonElement h : ((HolonObject) set.getCpsObject()).getElements()) {
  171. if (h.getEnergy() > 0) {
  172. val += h.getEnergy() * h.getAmount();
  173. }
  174. }
  175. break;
  176. case TrackedDataSet.ACTIVATED_ELEMENTS:
  177. for (HolonElement h : ((HolonObject) set.getCpsObject()).getElements()) {
  178. val += h.getAmount();
  179. }
  180. break;
  181. case TrackedDataSet.ON_OFF:
  182. val = 1;
  183. break;
  184. case TrackedDataSet.TOTAL_PRODUCTION:
  185. val = getMaxTotalProduction(model.getObjectsOnCanvas());
  186. break;
  187. case TrackedDataSet.TOTAL_CONSUMPTION:
  188. val = getMaxTotalConsumption(model.getObjectsOnCanvas());
  189. val *= -1;
  190. break;
  191. case TrackedDataSet.PERCENT_SUPPLIED:
  192. case TrackedDataSet.PERCENT_NOT_SUPPLIED:
  193. case TrackedDataSet.PERCENT_PARTIAL_SUPPLIED:
  194. val = 1;
  195. break;
  196. default:
  197. break;
  198. }
  199. if (val > maximum) {
  200. maximum = val;
  201. }
  202. }
  203. ((StatisticGraphPanel) this.getParent()).setMaximumLabel(maximum);
  204. }
  205. /**
  206. * Add the Current Values to each set
  207. */
  208. private void addValues() {
  209. for (TrackedDataSet set : objects) {
  210. int val = 0;
  211. switch (set.getProperty()) {
  212. case TrackedDataSet.CONSUMPTION:
  213. for (HolonElement h : ((HolonObject) set.getCpsObject()).getElements()) {
  214. if (h.getEnergy() < 0 && h.getActive()) {
  215. val += Math.abs(h.getEnergyAt()[model.getCurIteration()]) * h.getAmount();
  216. }
  217. set.setValAt(val, model.getCurIteration());
  218. }
  219. break;
  220. case TrackedDataSet.PRODUCTION:
  221. for (HolonElement h : ((HolonObject) set.getCpsObject()).getElements()) {
  222. if (h.getEnergy() > 0 && h.getActive()) {
  223. val += Math.abs(h.getEnergyAt()[model.getCurIteration()]) * h.getAmount();
  224. }
  225. set.setValAt(val, model.getCurIteration());
  226. }
  227. break;
  228. case TrackedDataSet.ACTIVATED_ELEMENTS:
  229. for (HolonElement h : ((HolonObject) set.getCpsObject()).getElements()) {
  230. if (h.getActive()) {
  231. val += h.getAmount();
  232. }
  233. set.setValAt(val, model.getCurIteration());
  234. }
  235. break;
  236. case TrackedDataSet.ON_OFF:
  237. if (((HolonSwitch) set.getCpsObject()).getManualMode()) {
  238. if (((HolonSwitch) set.getCpsObject()).getActiveManual()) {
  239. set.setValAt(1, model.getCurIteration());
  240. } else {
  241. set.setValAt(0, model.getCurIteration());
  242. }
  243. } else {
  244. if (((HolonSwitch) set.getCpsObject()).getActiveAt()[model.getCurIteration()]) {
  245. set.setValAt(1, model.getCurIteration());
  246. } else {
  247. set.setValAt(0, model.getCurIteration());
  248. }
  249. }
  250. break;
  251. case TrackedDataSet.TOTAL_PRODUCTION:
  252. set.setValAt(getTotalProductionAt(model.getObjectsOnCanvas(), model.getCurIteration()), model.getCurIteration());
  253. break;
  254. case TrackedDataSet.TOTAL_CONSUMPTION:
  255. set.setValAt(-getTotalConsumptionAt(model.getObjectsOnCanvas(), model.getCurIteration()), model.getCurIteration());
  256. break;
  257. case TrackedDataSet.PERCENT_SUPPLIED:
  258. set.setValAt(getPercentState(model.getObjectsOnCanvas(), HolonObject.SUPPLIED), model.getCurIteration());
  259. break;
  260. case TrackedDataSet.PERCENT_NOT_SUPPLIED:
  261. set.setValAt(getPercentState(model.getObjectsOnCanvas(), HolonObject.NOT_SUPPLIED), model.getCurIteration());
  262. break;
  263. case TrackedDataSet.PERCENT_PARTIAL_SUPPLIED:
  264. set.setValAt(getPercentState(model.getObjectsOnCanvas(), HolonObject.PARTIALLY_SUPPLIED), model.getCurIteration());
  265. break;
  266. default:
  267. break;
  268. }
  269. }
  270. }
  271. /**
  272. * create Path with floats
  273. *
  274. * @param set
  275. */
  276. private void createPathFloats(TrackedDataSet set) {
  277. boolean init = true;
  278. path.moveTo(0, 0);
  279. for (int i = 0; i < model.getCurIteration(); i++) {
  280. if (init && set.getValues()[i] != -1) {
  281. path.moveTo(i * this.getWidth() / model.getIterations() - 1, convertToCanvasY(set.getValues()[i]));
  282. init = false;
  283. }
  284. if (!init) {
  285. if (set.getValues()[i + 1] != -1) {
  286. path.lineTo((i + 1) * this.getWidth() / model.getIterations(),
  287. convertToCanvasY(set.getValues()[i + 1]));
  288. } else {
  289. break;
  290. }
  291. }
  292. }
  293. }
  294. /**
  295. * create Path with booleans(0 and 1)
  296. *
  297. * @param set
  298. */
  299. private void createPathBooleans(TrackedDataSet set) {
  300. boolean init = true;
  301. for (int i = 0; i < model.getCurIteration(); i++) {
  302. if (init && set.getValues()[i] != -1) {
  303. path.moveTo(i * this.getWidth() / model.getIterations() - 1,
  304. convertToCanvasY((float) (set.getValues()[i] * maximum)));
  305. init = false;
  306. }
  307. if (!init) {
  308. if (set.getValues()[i + 1] != -1) {
  309. path.lineTo((i + 1) * this.getWidth() / model.getIterations(),
  310. convertToCanvasY((float) (set.getValues()[i + 1] * maximum)));
  311. } else {
  312. break;
  313. }
  314. }
  315. }
  316. }
  317. /**
  318. * create Path for percent values
  319. *
  320. * @param set
  321. */
  322. private void createPathPercent(TrackedDataSet set) {
  323. boolean init = true;
  324. path.moveTo(0, 0);
  325. for (int i = 0; i < model.getCurIteration(); i++) {
  326. if (init && set.getValues()[i] != -1) {
  327. path.moveTo(i * this.getWidth() / model.getIterations() - 1, convertToCanvasY(set.getValues()[i]*maximum));
  328. init = false;
  329. }
  330. if (!init) {
  331. if (set.getValues()[i + 1] != -1) {
  332. path.lineTo((i + 1) * this.getWidth() / model.getIterations(),
  333. convertToCanvasY(set.getValues()[i + 1]*maximum));
  334. } else {
  335. break;
  336. }
  337. }
  338. }
  339. }
  340. /**
  341. * get the max total production of the given Objects
  342. *
  343. * @param objects List of Objects
  344. */
  345. private float getMaxTotalProduction(ArrayList<AbstractCpsObject> objects) {
  346. float val = 0;
  347. for (AbstractCpsObject obj: objects) {
  348. if (obj instanceof HolonObject) {
  349. for (HolonElement ele: ((HolonObject) obj).getElements()) {
  350. if (ele.getEnergy() > 0) {
  351. val += ele.getEnergy() * ele.getAmount();
  352. }
  353. }
  354. } else if (obj instanceof CpsUpperNode) {
  355. val += getMaxTotalProduction(((CpsUpperNode) obj).getNodes());
  356. }
  357. }
  358. return val;
  359. }
  360. /**
  361. * get the max total consumption of the given Objects
  362. *
  363. * @param objects List of Objects
  364. */
  365. private float getMaxTotalConsumption(ArrayList<AbstractCpsObject> objects) {
  366. float val = 0;
  367. for (AbstractCpsObject obj: objects) {
  368. if (obj instanceof HolonObject) {
  369. for (HolonElement ele: ((HolonObject) obj).getElements()) {
  370. if (ele.getEnergy() < 0) {
  371. val += ele.getEnergy() * ele.getAmount();
  372. }
  373. }
  374. } else if (obj instanceof CpsUpperNode) {
  375. val += getMaxTotalConsumption(((CpsUpperNode) obj).getNodes());
  376. }
  377. }
  378. return val;
  379. }
  380. /**
  381. * get the max total production of the given Objects
  382. *
  383. * @param objects List of Objects
  384. * @param tStep
  385. */
  386. private float getTotalProductionAt(ArrayList<AbstractCpsObject> objects, int tStep) {
  387. float val = 0;
  388. for (AbstractCpsObject obj: objects) {
  389. if (obj instanceof HolonObject) {
  390. for (HolonElement ele: ((HolonObject) obj).getElements()) {
  391. if (ele.getEnergyAt()[tStep] > 0 && ele.getActive()) {
  392. val += ele.getEnergyAt()[tStep] * ele.getAmount();
  393. }
  394. }
  395. } else if (obj instanceof CpsUpperNode) {
  396. val += getTotalProductionAt(((CpsUpperNode) obj).getNodes(), tStep);
  397. }
  398. }
  399. return val;
  400. }
  401. /**
  402. * get the total consumption of the given Objects at the given timestep
  403. *
  404. * @param objects List of Objects
  405. * @param tStep
  406. */
  407. private float getTotalConsumptionAt(ArrayList<AbstractCpsObject> objects, int tStep) {
  408. float val = 0;
  409. for (AbstractCpsObject obj: objects) {
  410. if (obj instanceof HolonObject) {
  411. for (HolonElement ele: ((HolonObject) obj).getElements()) {
  412. if (ele.getEnergyAt()[tStep] < 0 && ele.getActive()) {
  413. val += ele.getEnergyAt()[tStep] * ele.getAmount();
  414. }
  415. }
  416. } else if (obj instanceof CpsUpperNode) {
  417. val += getTotalConsumptionAt(((CpsUpperNode) obj).getNodes(), tStep);
  418. }
  419. }
  420. return val;
  421. }
  422. /**
  423. * get the Percentage of how many objects with the given state are in the given List
  424. *
  425. * @param objects List of Objects
  426. */
  427. private float getPercentState(ArrayList<AbstractCpsObject> objects, int state) {
  428. float count = controller.getNumberHolonObjects(objects);
  429. float stateObjectss= controller.getNumberStateObjects(objects, state);
  430. return stateObjectss/count;
  431. }
  432. }