DemoAlgo.java 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509
  1. package holeg.algorithm.example;
  2. import holeg.api.AddOn;
  3. import holeg.model.AbstractCanvasObject;
  4. import holeg.model.GroupNode;
  5. import holeg.model.HolonElement;
  6. import holeg.model.HolonObject;
  7. import holeg.model.HolonSwitch;
  8. import holeg.model.HolonSwitch.SwitchMode;
  9. import holeg.model.HolonSwitch.SwitchState;
  10. import holeg.model.Model;
  11. import holeg.ui.controller.Control;
  12. import java.awt.BorderLayout;
  13. import java.awt.Component;
  14. import java.awt.Dimension;
  15. import java.awt.FlowLayout;
  16. import java.awt.image.BufferedImage;
  17. import java.text.NumberFormat;
  18. import java.util.ArrayList;
  19. import java.util.HashMap;
  20. import java.util.List;
  21. import java.util.Optional;
  22. import java.util.concurrent.TimeUnit;
  23. import java.util.stream.Stream;
  24. import javax.swing.BorderFactory;
  25. import javax.swing.ImageIcon;
  26. import javax.swing.JButton;
  27. import javax.swing.JCheckBox;
  28. import javax.swing.JFormattedTextField;
  29. import javax.swing.JFrame;
  30. import javax.swing.JLabel;
  31. import javax.swing.JOptionPane;
  32. import javax.swing.JPanel;
  33. import javax.swing.JScrollPane;
  34. import javax.swing.JSplitPane;
  35. import javax.swing.JTextArea;
  36. import javax.swing.text.NumberFormatter;
  37. public class DemoAlgo implements AddOn {
  38. //Parameter for Algo with default Values:
  39. int counter;
  40. //Settings For GroupNode using and cancel
  41. private boolean useGroupNode = false;
  42. private Optional<GroupNode> groupNode = Optional.empty();
  43. private boolean cancel = false;
  44. //Parameter defined by Algo
  45. private HashMap<Integer, AccessWrapper> access;
  46. private List<Boolean> initialState;
  47. private List<HolonSwitch> switchList;
  48. private List<HolonObject> objectList;
  49. //Gui Part:
  50. private Control control;
  51. private JTextArea textArea;
  52. private JPanel content = new JPanel();
  53. private long startTime;
  54. private Thread runThread;
  55. //Windrad
  56. private HolonObject windrad;
  57. private int waitDurationWindradStep = 400;
  58. private int waitDurationEnd = 1000;
  59. public DemoAlgo() {
  60. content.setLayout(new BorderLayout());
  61. textArea = new JTextArea();
  62. textArea.setEditable(false);
  63. JScrollPane scrollPane = new JScrollPane(textArea);
  64. JSplitPane splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT,
  65. createOptionPanel(), scrollPane);
  66. splitPane.setResizeWeight(0.0);
  67. content.add(splitPane, BorderLayout.CENTER);
  68. content.setPreferredSize(new Dimension(800, 800));
  69. }
  70. public static void main(String[] args) {
  71. JFrame newFrame = new JFrame("exampleWindow");
  72. DemoAlgo instance = new DemoAlgo();
  73. newFrame.setContentPane(instance.getPanel());
  74. newFrame.pack();
  75. newFrame.setVisible(true);
  76. newFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  77. }
  78. public JPanel createOptionPanel() {
  79. JPanel optionPanel = new JPanel(new BorderLayout());
  80. JScrollPane scrollPane = new JScrollPane(createParameterPanel());
  81. scrollPane.setBorder(BorderFactory.createTitledBorder("Parameter"));
  82. optionPanel.add(scrollPane, BorderLayout.CENTER);
  83. optionPanel.add(createButtonPanel(), BorderLayout.PAGE_END);
  84. return optionPanel;
  85. }
  86. private Component createParameterPanel() {
  87. JPanel parameterPanel = new JPanel(null);
  88. parameterPanel.setPreferredSize(new Dimension(510, 300));
  89. // JLabel showDiagnosticsLabel = new JLabel("Set all switches closed:");
  90. // showDiagnosticsLabel.setBounds(200, 60, 170, 20);
  91. // parameterPanel.add(showDiagnosticsLabel);
  92. JPanel borderPanel = new JPanel(null);
  93. borderPanel.setBounds(200, 85, 185, 50);
  94. borderPanel.setBorder(BorderFactory.createTitledBorder(""));
  95. parameterPanel.add(borderPanel);
  96. JLabel showGroupNodeLabel = new JLabel("Use Group Node:");
  97. showGroupNodeLabel.setBounds(10, 1, 170, 20);
  98. borderPanel.add(showGroupNodeLabel);
  99. JButton selectGroupNodeButton = new JButton("Select GroupNode");
  100. selectGroupNodeButton.setEnabled(false);
  101. selectGroupNodeButton.setBounds(10, 25, 165, 20);
  102. selectGroupNodeButton.addActionListener(actionEvent -> selectGroupNode());
  103. borderPanel.add(selectGroupNodeButton);
  104. JCheckBox useGroupNodeCheckBox = new JCheckBox();
  105. useGroupNodeCheckBox.setSelected(false);
  106. useGroupNodeCheckBox.setBounds(155, 1, 25, 20);
  107. useGroupNodeCheckBox.addActionListener(actionEvent -> {
  108. useGroupNode = useGroupNodeCheckBox.isSelected();
  109. selectGroupNodeButton.setEnabled(useGroupNode);
  110. });
  111. borderPanel.add(useGroupNodeCheckBox);
  112. // JCheckBox switchesCheckBox = new JCheckBox();
  113. // switchesCheckBox.setSelected(closeSwitches);
  114. // switchesCheckBox.setBounds(370, 60, 25, 20);
  115. // switchesCheckBox.addActionListener(actionEvent -> closeSwitches = switchesCheckBox.isSelected());
  116. // parameterPanel.add(switchesCheckBox);
  117. JButton selectRoom1Button = new JButton("Select");
  118. selectRoom1Button.setBounds(10, 300, 90, 20);
  119. selectRoom1Button.addActionListener(actionEvent -> this.selectHolonObject());
  120. parameterPanel.add(selectRoom1Button);
  121. NumberFormat format = NumberFormat.getIntegerInstance();
  122. format.setGroupingUsed(false);
  123. format.setParseIntegerOnly(true);
  124. NumberFormatter integerFormatter = new NumberFormatter(format);
  125. integerFormatter.setMinimum(0);
  126. integerFormatter.setCommitsOnValidEdit(true);
  127. JLabel portLabel = new JLabel("between:");
  128. portLabel.setBounds(10, 330, 70, 30);
  129. parameterPanel.add(portLabel);
  130. JFormattedTextField betweenTF = new JFormattedTextField(integerFormatter);
  131. betweenTF.setText("" + waitDurationWindradStep);
  132. betweenTF.setBounds(80, 330, 80, 30);
  133. betweenTF.addPropertyChangeListener(propertyChange -> {
  134. String text = betweenTF.getValue().toString();
  135. text = text.replaceAll("\\s", "");
  136. waitDurationWindradStep = Integer.parseInt((text));
  137. });
  138. parameterPanel.add(betweenTF);
  139. JLabel afterLabel = new JLabel("after:");
  140. afterLabel.setBounds(10, 360, 70, 30);
  141. parameterPanel.add(afterLabel);
  142. JFormattedTextField afterTF = new JFormattedTextField(integerFormatter);
  143. afterTF.setText("" + waitDurationEnd);
  144. afterTF.setBounds(80, 360, 80, 30);
  145. afterTF.addPropertyChangeListener(propertyChange -> {
  146. String text = afterTF.getValue().toString();
  147. text = text.replaceAll("\\s", "");
  148. waitDurationEnd = Integer.parseInt((text));
  149. });
  150. parameterPanel.add(afterTF);
  151. return parameterPanel;
  152. }
  153. public JPanel createButtonPanel() {
  154. JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT));
  155. JButton cancelButton = new JButton("Cancel Run");
  156. cancelButton.addActionListener(actionEvent -> cancel());
  157. buttonPanel.add(cancelButton);
  158. JButton clearButton = new JButton("Clear Console");
  159. clearButton.addActionListener(actionEvent -> clear());
  160. buttonPanel.add(clearButton);
  161. JButton resetButton = new JButton("Reset");
  162. resetButton.setToolTipText("Resets the State to before the Algorithm has runed.");
  163. resetButton.addActionListener(actionEvent -> reset());
  164. buttonPanel.add(resetButton);
  165. JButton runButton = new JButton("Run");
  166. runButton.addActionListener(actionEvent -> {
  167. Runnable task = () -> run();
  168. runThread = new Thread(task);
  169. runThread.start();
  170. });
  171. buttonPanel.add(runButton);
  172. return buttonPanel;
  173. }
  174. private void cancel() {
  175. if (runThread.isAlive()) {
  176. println("");
  177. println("Cancel run.");
  178. cancel = true;
  179. } else {
  180. println("Nothing to cancel.");
  181. }
  182. }
  183. private void run() {
  184. cancel = false;
  185. disableGuiInput(true);
  186. startTimer();
  187. executeDemoAlgo();
  188. if (cancel) {
  189. reset();
  190. disableGuiInput(false);
  191. return;
  192. }
  193. printElapsedTime();
  194. disableGuiInput(false);
  195. }
  196. private void reset() {
  197. if (initialState != null) {
  198. println("Resetting..");
  199. resetState();
  200. updateVisual();
  201. } else {
  202. println("No run inistialized.");
  203. }
  204. }
  205. private void disableGuiInput(boolean bool) {
  206. control.guiSetEnabled(bool);
  207. }
  208. @Override
  209. public JPanel getPanel() {
  210. return content;
  211. }
  212. @Override
  213. public void setController(Control control) {
  214. this.control = control;
  215. }
  216. private void clear() {
  217. textArea.setText("");
  218. }
  219. private void println(String message) {
  220. textArea.append(message + "\n");
  221. }
  222. private void selectGroupNode() {
  223. Object[] possibilities = control.getModel().getCanvas().getAllGroupNodeObjectsRecursive()
  224. .toArray();
  225. GroupNode selected = (GroupNode) JOptionPane.showInputDialog(content, "Select GroupNode:",
  226. "GroupNode?", JOptionPane.OK_OPTION,
  227. new ImageIcon(new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB)), possibilities, "");
  228. if (selected != null) {
  229. println("Selected: " + selected);
  230. groupNode = Optional.of(selected);
  231. }
  232. }
  233. private void startTimer() {
  234. startTime = System.currentTimeMillis();
  235. }
  236. private void printElapsedTime() {
  237. long elapsedMilliSeconds = System.currentTimeMillis() - startTime;
  238. println("Execution Time of Algo in Milliseconds:" + elapsedMilliSeconds);
  239. }
  240. //Algo Part:
  241. private void executeDemoAlgo() {
  242. extractPositionAndAccess();
  243. counter = 0;
  244. int actualIteration = control.getModel().getCurrentIteration();
  245. deactivateWindrad();
  246. setAllSwitchesClosed();
  247. updateVisual();
  248. try {
  249. //Schalte Slow das Windrad Ein
  250. if (windrad == null) {
  251. return;
  252. }
  253. windrad.elementsStream().forEach(hE -> {
  254. hE.active = true;
  255. try {
  256. TimeUnit.MILLISECONDS.sleep(waitDurationWindradStep);
  257. } catch (InterruptedException e) {
  258. }
  259. updateVisual();
  260. });
  261. TimeUnit.MILLISECONDS.sleep(waitDurationEnd);
  262. } catch (InterruptedException e) {
  263. }
  264. setHolonElemntsAktiv(actualIteration);
  265. println("Changed Elements: " + counter);
  266. updateVisual();
  267. }
  268. private void deactivateWindrad() {
  269. if (windrad == null) {
  270. return;
  271. }
  272. windrad.elementsStream().forEach(ele -> ele.active = false);
  273. }
  274. private void setHolonElemntsAktiv(int actualIteration) {
  275. for (int i = 0; i < access.size(); i++) {
  276. AccessWrapper aw = access.get(i);
  277. if (aw.getState(actualIteration) == false) {
  278. counter++;
  279. }
  280. if (aw.getType() == AccessWrapper.HOLONELEMENT) {
  281. aw.setState(true);
  282. }
  283. }
  284. }
  285. private void setAllSwitchesClosed() {
  286. for (HolonSwitch hSwitch : switchList) {
  287. if (hSwitch.getManualState().isOpen()) {
  288. counter++;
  289. }
  290. hSwitch.setMode(SwitchMode.Manual);
  291. hSwitch.setManualState(SwitchState.Closed);
  292. }
  293. }
  294. /**
  295. * Method to get the current Position alias a ListOf Booleans for aktive settings on the Objects
  296. * on the Canvas. Also initialize the Access Hashmap to swap faster positions.
  297. *
  298. * @return
  299. */
  300. private List<Boolean> extractPositionAndAccess() {
  301. Model model = control.getModel();
  302. switchList = new ArrayList<HolonSwitch>();
  303. objectList = new ArrayList<HolonObject>();
  304. initialState = new ArrayList<Boolean>();
  305. access = new HashMap<Integer, AccessWrapper>();
  306. rollOutNodes((useGroupNode && groupNode.isPresent()) ? groupNode.get().getObjectsInThisLayer()
  307. : model.getCanvas().getObjectsInThisLayer(), initialState, model.getCurrentIteration());
  308. return initialState;
  309. }
  310. /**
  311. * Method to extract the Informations recursively out of the Model.
  312. *
  313. * @param nodes
  314. * @param positionToInit
  315. * @param timeStep
  316. */
  317. private void rollOutNodes(Stream<AbstractCanvasObject> nodes, List<Boolean> positionToInit,
  318. int timeStep) {
  319. nodes.forEach(aCps -> {
  320. if (aCps instanceof HolonObject hO) {
  321. hO.elementsStream().forEach(hE -> {
  322. positionToInit.add(hE.active);
  323. access.put(positionToInit.size() - 1, new AccessWrapper(hE));
  324. });
  325. objectList.add(hO);
  326. } else if (aCps instanceof HolonSwitch sw) {
  327. positionToInit.add(sw.getState().isClosed());
  328. switchList.add(sw);
  329. access.put(positionToInit.size() - 1, new AccessWrapper(sw));
  330. } else if (aCps instanceof GroupNode groupnode) {
  331. rollOutGroupNode(groupnode, positionToInit, timeStep);
  332. }
  333. });
  334. }
  335. private void rollOutGroupNode(GroupNode groupNode, List<Boolean> positionToInit, int timeStep) {
  336. groupNode.getAllHolonObjectsRecursive().forEach(hObject -> {
  337. hObject.elementsStream().forEach(hE -> {
  338. positionToInit.add(hE.active);
  339. access.put(positionToInit.size() - 1, new AccessWrapper(hE));
  340. });
  341. objectList.add(hObject);
  342. });
  343. groupNode.getAllSwitchObjectsRecursive().forEach(sw -> {
  344. positionToInit.add(sw.getState().isClosed());
  345. switchList.add(sw);
  346. access.put(positionToInit.size() - 1, new AccessWrapper(sw));
  347. });
  348. }
  349. /**
  350. * To let the User See the current state without touching the Canvas.
  351. */
  352. private void updateVisual() {
  353. control.calculateStateForCurrentIteration();
  354. }
  355. /**
  356. * Sets the Model back to its original State before the LAST run.
  357. */
  358. private void resetState() {
  359. setState(initialState);
  360. }
  361. /**
  362. * Sets the State out of the given position for calculation or to show the user.
  363. *
  364. * @param position
  365. */
  366. private void setState(List<Boolean> position) {
  367. for (int i = 0; i < position.size(); i++) {
  368. access.get(i).setState(position.get(i));
  369. }
  370. }
  371. private void selectHolonObject() {
  372. List<HolonObject> holonObjectList = new ArrayList<HolonObject>();
  373. addObjectToList(control.getModel().getCanvas().getObjectsInThisLayer().toList(),
  374. holonObjectList);
  375. Object[] possibilities = holonObjectList.stream().map(aCps -> new Handle<HolonObject>(aCps))
  376. .toArray();
  377. @SuppressWarnings("unchecked")
  378. Handle<HolonObject> selected = (Handle<HolonObject>) JOptionPane.showInputDialog(content,
  379. "Select HolonObject:", "HolonObject?", JOptionPane.OK_OPTION,
  380. new ImageIcon(new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB)), possibilities, "");
  381. if (selected != null) {
  382. //println("Selected: " + selected);
  383. windrad = selected.object;
  384. }
  385. }
  386. private void addObjectToList(List<AbstractCanvasObject> listToSearch,
  387. List<HolonObject> listToAdd) {
  388. for (AbstractCanvasObject aCps : listToSearch) {
  389. if (aCps instanceof HolonObject hO) {
  390. listToAdd.add(hO);
  391. } else if (aCps instanceof GroupNode groupNode) {
  392. listToAdd.addAll(groupNode.getAllHolonObjectsRecursive().toList());
  393. }
  394. }
  395. }
  396. /**
  397. * A Wrapper Class for Access HolonElement and HolonSwitch in one Element and not have to split
  398. * the List.
  399. */
  400. private class AccessWrapper {
  401. public static final int HOLONELEMENT = 0;
  402. public static final int SWITCH = 1;
  403. private int type;
  404. private HolonSwitch hSwitch;
  405. private HolonElement hElement;
  406. public AccessWrapper(HolonSwitch hSwitch) {
  407. type = SWITCH;
  408. this.hSwitch = hSwitch;
  409. }
  410. public AccessWrapper(HolonElement hElement) {
  411. type = HOLONELEMENT;
  412. this.hElement = hElement;
  413. }
  414. public void setState(boolean state) {
  415. if (type == HOLONELEMENT) {
  416. hElement.active = state;
  417. } else {//is switch
  418. hSwitch.setMode(SwitchMode.Manual);
  419. hSwitch.setManualState(state ? SwitchState.Closed : SwitchState.Open);
  420. }
  421. }
  422. public boolean getState(int timeStep) {
  423. return (type == HOLONELEMENT) ? hElement.active : hSwitch.getState().isClosed();
  424. }
  425. public int getType() {
  426. return type;
  427. }
  428. }
  429. private class Handle<T> {
  430. public T object;
  431. Handle(T object) {
  432. this.object = object;
  433. }
  434. public String toString() {
  435. return object.toString();
  436. }
  437. }
  438. }