StatisticGraph.java 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519
  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. case TrackedDataSet.AMOUNT_SUBNETS:
  93. case TrackedDataSet.GROUP_CONSUMPTION:
  94. case TrackedDataSet.GROUP_PRODUCTION:
  95. createPathFloats(set);
  96. break;
  97. case TrackedDataSet.ON_OFF:
  98. createPathBooleans(set);
  99. break;
  100. case TrackedDataSet.PERCENT_SUPPLIED:
  101. case TrackedDataSet.PERCENT_NOT_SUPPLIED:
  102. case TrackedDataSet.PERCENT_PARTIAL_SUPPLIED:
  103. createPathPercent(set);
  104. break;
  105. default:
  106. break;
  107. }
  108. g2.setColor(set.getColor());
  109. g2.draw(path);
  110. }
  111. }
  112. }
  113. /**
  114. * Add an Object to the Graph if the maximum has not reached yet.
  115. *
  116. * @param obj
  117. * the Object to add
  118. */
  119. public void addObject(TrackedDataSet set) {
  120. objects.add(set);
  121. }
  122. /**
  123. * Removes an Object from the Graph.
  124. *
  125. * @param id
  126. * the id of the Object to remove
  127. */
  128. public void removeObject(int id) {
  129. objects.remove(id);
  130. }
  131. /**
  132. * converts the number to fit the canvas.
  133. *
  134. * @param d
  135. * the number to convert
  136. * @return the converted number
  137. */
  138. public double convertToCanvasY(float d) {
  139. return Math.abs((this.getHeight() - (d * (this.getHeight() / maximum))));
  140. }
  141. /**
  142. * Does take into account which timestep is watched, calculates the max
  143. * values.
  144. *
  145. * @return the currentEnergy
  146. */
  147. public float getEnergyAtCurrentTimeStep(HolonObject obj) {
  148. float temp = 0;
  149. for (HolonElement e : obj.getElements()) {
  150. if (e.getActive()) {
  151. temp = temp + e.getEnergyAt()[model.getCurIteration()];
  152. }
  153. }
  154. return temp;
  155. }
  156. /**
  157. * Calculate the Max Value of the Graph
  158. */
  159. public void calcMaximum() {
  160. maximum = 0;
  161. for (TrackedDataSet set : objects) {
  162. float val = 0;
  163. switch (set.getProperty()) {
  164. case TrackedDataSet.CONSUMPTION:
  165. for (HolonElement h : ((HolonObject) set.getCpsObject()).getElements()) {
  166. if (h.getEnergy() < 0) {
  167. val += h.getEnergy() * h.getAmount();
  168. }
  169. }
  170. val *= -1;
  171. break;
  172. case TrackedDataSet.PRODUCTION:
  173. for (HolonElement h : ((HolonObject) set.getCpsObject()).getElements()) {
  174. if (h.getEnergy() > 0) {
  175. val += h.getEnergy() * h.getAmount();
  176. }
  177. }
  178. break;
  179. case TrackedDataSet.ACTIVATED_ELEMENTS:
  180. for (HolonElement h : ((HolonObject) set.getCpsObject()).getElements()) {
  181. val += h.getAmount();
  182. }
  183. break;
  184. case TrackedDataSet.ON_OFF:
  185. val = 1;
  186. break;
  187. case TrackedDataSet.TOTAL_PRODUCTION:
  188. val = getMaxTotalProduction(model.getObjectsOnCanvas());
  189. break;
  190. case TrackedDataSet.TOTAL_CONSUMPTION:
  191. val = getMaxTotalConsumption(model.getObjectsOnCanvas());
  192. val *= -1;
  193. break;
  194. case TrackedDataSet.PERCENT_SUPPLIED:
  195. case TrackedDataSet.PERCENT_NOT_SUPPLIED:
  196. case TrackedDataSet.PERCENT_PARTIAL_SUPPLIED:
  197. val = 1;
  198. break;
  199. case TrackedDataSet.GROUP_PRODUCTION:
  200. val = getMaxTotalProduction(((CpsUpperNode) set.getCpsObject()).getNodes());
  201. break;
  202. case TrackedDataSet.GROUP_CONSUMPTION:
  203. val = getMaxTotalConsumption(((CpsUpperNode) set.getCpsObject()).getNodes());
  204. val *= -1;
  205. break;
  206. case TrackedDataSet.AMOUNT_SUBNETS:
  207. val = controller.getSimManager().getSubNets().size();
  208. for (int i = 0; i < model.getCurIteration(); i++) {
  209. if (val < set.getValues()[i]) {
  210. val = set.getValues()[i];
  211. }
  212. }
  213. break;
  214. default:
  215. maximum = 0;
  216. break;
  217. }
  218. if (val > maximum) {
  219. maximum = val;
  220. }
  221. }
  222. ((StatisticGraphPanel) this.getParent()).setMaximumLabel(maximum);
  223. }
  224. /**
  225. * Add the Current Values to each set
  226. */
  227. private void addValues() {
  228. for (TrackedDataSet set : objects) {
  229. float val = 0;
  230. switch (set.getProperty()) {
  231. case TrackedDataSet.CONSUMPTION:
  232. for (HolonElement h : ((HolonObject) set.getCpsObject()).getElements()) {
  233. if (h.getEnergy() < 0 && h.getActive()) {
  234. val += Math.abs(h.getEnergyAt()[model.getCurIteration()]) * h.getAmount();
  235. }
  236. set.setValAt(val, model.getCurIteration());
  237. }
  238. break;
  239. case TrackedDataSet.PRODUCTION:
  240. for (HolonElement h : ((HolonObject) set.getCpsObject()).getElements()) {
  241. if (h.getEnergy() > 0 && h.getActive()) {
  242. val += Math.abs(h.getEnergyAt()[model.getCurIteration()]) * h.getAmount();
  243. }
  244. set.setValAt(val, model.getCurIteration());
  245. }
  246. break;
  247. case TrackedDataSet.ACTIVATED_ELEMENTS:
  248. for (HolonElement h : ((HolonObject) set.getCpsObject()).getElements()) {
  249. if (h.getActive()) {
  250. val += h.getAmount();
  251. }
  252. set.setValAt(val, model.getCurIteration());
  253. }
  254. break;
  255. case TrackedDataSet.ON_OFF:
  256. if (((HolonSwitch) set.getCpsObject()).getManualMode()) {
  257. if (((HolonSwitch) set.getCpsObject()).getActiveManual()) {
  258. set.setValAt(1, model.getCurIteration());
  259. } else {
  260. set.setValAt(0, model.getCurIteration());
  261. }
  262. } else {
  263. if (((HolonSwitch) set.getCpsObject()).getActiveAt()[model.getCurIteration()]) {
  264. set.setValAt(1, model.getCurIteration());
  265. } else {
  266. set.setValAt(0, model.getCurIteration());
  267. }
  268. }
  269. break;
  270. case TrackedDataSet.TOTAL_PRODUCTION:
  271. set.setValAt(getTotalProductionAt(model.getObjectsOnCanvas(), model.getCurIteration()),
  272. model.getCurIteration());
  273. break;
  274. case TrackedDataSet.TOTAL_CONSUMPTION:
  275. set.setValAt(-getTotalConsumptionAt(model.getObjectsOnCanvas(), model.getCurIteration()),
  276. model.getCurIteration());
  277. break;
  278. case TrackedDataSet.PERCENT_SUPPLIED:
  279. set.setValAt(getPercentState(model.getObjectsOnCanvas(), HolonObject.SUPPLIED),
  280. model.getCurIteration());
  281. break;
  282. case TrackedDataSet.PERCENT_NOT_SUPPLIED:
  283. set.setValAt(getPercentState(model.getObjectsOnCanvas(), HolonObject.NOT_SUPPLIED),
  284. model.getCurIteration());
  285. break;
  286. case TrackedDataSet.PERCENT_PARTIAL_SUPPLIED:
  287. set.setValAt(getPercentState(model.getObjectsOnCanvas(), HolonObject.PARTIALLY_SUPPLIED),
  288. model.getCurIteration());
  289. break;
  290. case TrackedDataSet.GROUP_PRODUCTION:
  291. val = getTotalProductionAt(((CpsUpperNode) set.getCpsObject()).getNodes(),model.getCurIteration());
  292. break;
  293. case TrackedDataSet.GROUP_CONSUMPTION:
  294. val = getTotalConsumptionAt(((CpsUpperNode) set.getCpsObject()).getNodes(),model.getCurIteration());
  295. controller.addTextToConsole(val+"");
  296. val *= -1;
  297. break;
  298. case TrackedDataSet.AMOUNT_SUBNETS:
  299. set.setValAt(controller.getSimManager().getSubNets().size(), model.getCurIteration());
  300. break;
  301. default:
  302. break;
  303. }
  304. }
  305. }
  306. /**
  307. * create Path with floats
  308. *
  309. * @param set
  310. */
  311. private void createPathFloats(TrackedDataSet set) {
  312. boolean init = true;
  313. path.moveTo(0, 0);
  314. for (int i = 0; i < model.getCurIteration(); i++) {
  315. if (init && set.getValues()[i] != -1) {
  316. path.moveTo(i * this.getWidth() / model.getIterations() - 1, convertToCanvasY(set.getValues()[i]));
  317. init = false;
  318. }
  319. if (!init) {
  320. if (set.getValues()[i + 1] != -1) {
  321. path.lineTo((i + 1) * this.getWidth() / model.getIterations(),
  322. convertToCanvasY(set.getValues()[i + 1]));
  323. } else {
  324. break;
  325. }
  326. }
  327. }
  328. }
  329. /**
  330. * create Path with booleans(0 and 1)
  331. *
  332. * @param set
  333. */
  334. private void createPathBooleans(TrackedDataSet set) {
  335. boolean init = true;
  336. for (int i = 0; i < model.getCurIteration(); i++) {
  337. if (init && set.getValues()[i] != -1) {
  338. path.moveTo(i * this.getWidth() / model.getIterations() - 1,
  339. convertToCanvasY((float) (set.getValues()[i] * maximum)));
  340. init = false;
  341. }
  342. if (!init) {
  343. if (set.getValues()[i + 1] != -1) {
  344. path.lineTo((i + 1) * this.getWidth() / model.getIterations(),
  345. convertToCanvasY((float) (set.getValues()[i + 1] * maximum)));
  346. } else {
  347. break;
  348. }
  349. }
  350. }
  351. }
  352. /**
  353. * create Path for percent values
  354. *
  355. * @param set
  356. */
  357. private void createPathPercent(TrackedDataSet set) {
  358. boolean init = true;
  359. path.moveTo(0, 0);
  360. for (int i = 0; i < model.getCurIteration(); i++) {
  361. if (init && set.getValues()[i] != -1) {
  362. path.moveTo(i * this.getWidth() / model.getIterations() - 1,
  363. convertToCanvasY(set.getValues()[i] * maximum));
  364. init = false;
  365. }
  366. if (!init) {
  367. if (set.getValues()[i + 1] != -1) {
  368. path.lineTo((i + 1) * this.getWidth() / model.getIterations(),
  369. convertToCanvasY(set.getValues()[i + 1] * maximum));
  370. } else {
  371. break;
  372. }
  373. }
  374. }
  375. }
  376. /**
  377. * get the max total production of the given Objects
  378. *
  379. * @param objects
  380. * List of Objects
  381. */
  382. private float getMaxTotalProduction(ArrayList<AbstractCpsObject> objects) {
  383. float val = 0;
  384. for (AbstractCpsObject obj : objects) {
  385. if (obj instanceof HolonObject) {
  386. for (HolonElement ele : ((HolonObject) obj).getElements()) {
  387. if (ele.getEnergy() > 0) {
  388. val += ele.getEnergy() * ele.getAmount();
  389. }
  390. }
  391. } else if (obj instanceof CpsUpperNode) {
  392. val += getMaxTotalProduction(((CpsUpperNode) obj).getNodes());
  393. }
  394. }
  395. return val;
  396. }
  397. /**
  398. * get the max total consumption of the given Objects
  399. *
  400. * @param objects
  401. * List of Objects
  402. */
  403. private float getMaxTotalConsumption(ArrayList<AbstractCpsObject> objects) {
  404. float val = 0;
  405. for (AbstractCpsObject obj : objects) {
  406. if (obj instanceof HolonObject) {
  407. for (HolonElement ele : ((HolonObject) obj).getElements()) {
  408. if (ele.getEnergy() < 0) {
  409. val += ele.getEnergy() * ele.getAmount();
  410. }
  411. }
  412. } else if (obj instanceof CpsUpperNode) {
  413. val += getMaxTotalConsumption(((CpsUpperNode) obj).getNodes());
  414. }
  415. }
  416. return val;
  417. }
  418. /**
  419. * get the max total production of the given Objects
  420. *
  421. * @param objects
  422. * List of Objects
  423. * @param tStep
  424. */
  425. private float getTotalProductionAt(ArrayList<AbstractCpsObject> objects, int tStep) {
  426. float val = 0;
  427. for (AbstractCpsObject obj : objects) {
  428. if (obj instanceof HolonObject) {
  429. for (HolonElement ele : ((HolonObject) obj).getElements()) {
  430. if (ele.getEnergyAt()[tStep] > 0 && ele.getActive()) {
  431. val += ele.getEnergyAt()[tStep] * ele.getAmount();
  432. }
  433. }
  434. } else if (obj instanceof CpsUpperNode) {
  435. val += getTotalProductionAt(((CpsUpperNode) obj).getNodes(), tStep);
  436. }
  437. }
  438. return val;
  439. }
  440. /**
  441. * get the total consumption of the given Objects at the given timestep
  442. *
  443. * @param objects
  444. * List of Objects
  445. * @param tStep
  446. */
  447. private float getTotalConsumptionAt(ArrayList<AbstractCpsObject> objects, int tStep) {
  448. float val = 0;
  449. for (AbstractCpsObject obj : objects) {
  450. if (obj instanceof HolonObject) {
  451. for (HolonElement ele : ((HolonObject) obj).getElements()) {
  452. if (ele.getEnergyAt()[tStep] < 0 && ele.getActive()) {
  453. val += ele.getEnergyAt()[tStep] * ele.getAmount();
  454. }
  455. }
  456. } else if (obj instanceof CpsUpperNode) {
  457. val += getTotalConsumptionAt(((CpsUpperNode) obj).getNodes(), tStep);
  458. }
  459. }
  460. return val;
  461. }
  462. /**
  463. * get the Percentage of how many objects with the given state are in the
  464. * given List
  465. *
  466. * @param objects
  467. * List of Objects
  468. */
  469. private float getPercentState(ArrayList<AbstractCpsObject> objects, int state) {
  470. float count = controller.getNumberHolonObjects(objects);
  471. float stateObjectss = controller.getNumberStateObjects(objects, state);
  472. return stateObjectss / count;
  473. }
  474. }