RandomOfferdFlexibility.java 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376
  1. package holeg.addon;
  2. import holeg.api.AddOn;
  3. import holeg.model.Flexibility;
  4. import holeg.model.Flexibility.FlexState;
  5. import holeg.model.HolonElement.Priority;
  6. import holeg.ui.controller.Control;
  7. import java.awt.BorderLayout;
  8. import java.awt.ComponentOrientation;
  9. import java.awt.Dimension;
  10. import java.awt.FlowLayout;
  11. import java.awt.GridBagConstraints;
  12. import java.awt.GridBagLayout;
  13. import java.math.RoundingMode;
  14. import java.text.NumberFormat;
  15. import java.util.ArrayList;
  16. import java.util.Collections;
  17. import java.util.Hashtable;
  18. import java.util.List;
  19. import java.util.Locale;
  20. import java.util.Random;
  21. import java.util.logging.Logger;
  22. import java.util.stream.Collectors;
  23. import javax.swing.BorderFactory;
  24. import javax.swing.JButton;
  25. import javax.swing.JCheckBox;
  26. import javax.swing.JFormattedTextField;
  27. import javax.swing.JFrame;
  28. import javax.swing.JLabel;
  29. import javax.swing.JPanel;
  30. import javax.swing.JSlider;
  31. import javax.swing.text.NumberFormatter;
  32. /**
  33. * A short algorithm to distribute the Priorities for the whole Canvas.
  34. *
  35. * @author tom
  36. */
  37. public class RandomOfferdFlexibility implements AddOn {
  38. private static final Logger log = Logger.getLogger(RandomOfferdFlexibility.class.getName());
  39. PriorityDependeces low = new PriorityDependeces("low");
  40. PriorityDependeces medium = new PriorityDependeces("medium");
  41. PriorityDependeces high = new PriorityDependeces("high");
  42. PriorityDependeces essential = new PriorityDependeces("essential");
  43. private Control control;
  44. private JPanel content = new JPanel();
  45. public RandomOfferdFlexibility() {
  46. low.offer.positive.maximumOffered = low.offer.positive.actualOffered = 1000;
  47. low.offer.negative.maximumOffered = low.offer.negative.actualOffered = 2000;
  48. double distribution = 0.8;
  49. low.offer.updateTarget(distribution);
  50. log.info("distribution:" + distribution + " Positive:" + low.offer.positive.targetOffered
  51. + " Negative:" + low.offer.negative.targetOffered);
  52. log.info("actualDistribution:" + low.offer.getActualProportion());
  53. content.setLayout(new BorderLayout());
  54. content.add(createFlexPanel(), BorderLayout.CENTER);
  55. JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.TRAILING));
  56. JButton buttonReload = new JButton("Reload");
  57. buttonReload.setToolTipText("Press to relaod all canvas changes.");
  58. buttonReload.addActionListener(actionEvent -> update());
  59. buttonPanel.add(buttonReload);
  60. JButton buttonRun = new JButton("Run");
  61. buttonRun.setToolTipText(
  62. "Changes the actual offered flex to the random target amount of selected prioritys.");
  63. buttonRun.addActionListener(actionEvent -> run());
  64. buttonPanel.add(buttonRun);
  65. content.add(buttonPanel, BorderLayout.PAGE_END);
  66. //content.setPreferredSize(new Dimension(300,500));
  67. }
  68. public static void main(String[] args) {
  69. JFrame newFrame = new JFrame("exampleWindow");
  70. RandomOfferdFlexibility instance = new RandomOfferdFlexibility();
  71. newFrame.setContentPane(instance.getPanel());
  72. newFrame.pack();
  73. newFrame.setVisible(true);
  74. newFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  75. }
  76. private JPanel createFlexPanel() {
  77. JPanel flexPanel = new JPanel();
  78. flexPanel.setBorder(BorderFactory.createTitledBorder("Flexibility"));
  79. flexPanel.setLayout(new GridBagLayout());
  80. GridBagConstraints c = new GridBagConstraints();
  81. c.fill = GridBagConstraints.HORIZONTAL;
  82. c.gridx = 0;
  83. c.gridy = 0;
  84. c.ipadx = 10;
  85. //c.ipady = 100;
  86. //Label
  87. flexPanel.add(new JLabel("Priority:"), c);
  88. c.gridx++;
  89. flexPanel.add(new JLabel("Target:"), c);
  90. c.gridx++;
  91. flexPanel.add(new JLabel("Positive#(Available):"), c);
  92. c.gridx++;
  93. flexPanel.add(new JLabel("Negative#(Available):"), c);
  94. c.gridx = 0;
  95. c.gridy = 1;
  96. flexPanel.add(low.checkbox, c);
  97. c.gridx++;
  98. c.weightx = 1;
  99. flexPanel.add(createTargetSetterPanel(this.low), c);
  100. c.gridx++;
  101. c.weightx = 0;
  102. flexPanel.add(this.low.positive, c);
  103. c.gridx++;
  104. flexPanel.add(this.low.negative, c);
  105. c.gridx = 0;
  106. c.gridy = 2;
  107. flexPanel.add(medium.checkbox, c);
  108. c.gridx++;
  109. flexPanel.add(createTargetSetterPanel(this.medium), c);
  110. c.gridx++;
  111. flexPanel.add(this.medium.positive, c);
  112. c.gridx++;
  113. flexPanel.add(this.medium.negative, c);
  114. c.gridx = 0;
  115. c.gridy = 3;
  116. flexPanel.add(high.checkbox, c);
  117. c.gridx++;
  118. flexPanel.add(createTargetSetterPanel(this.high), c);
  119. c.gridx++;
  120. flexPanel.add(this.high.positive, c);
  121. c.gridx++;
  122. flexPanel.add(this.high.negative, c);
  123. c.gridx = 0;
  124. c.gridy = 4;
  125. flexPanel.add(essential.checkbox, c);
  126. c.gridx++;
  127. flexPanel.add(createTargetSetterPanel(this.essential), c);
  128. c.gridx++;
  129. flexPanel.add(this.essential.positive, c);
  130. c.gridx++;
  131. flexPanel.add(this.essential.negative, c);
  132. return flexPanel;
  133. }
  134. private JPanel createTargetSetterPanel(PriorityDependeces priorityD) {
  135. JPanel panel = new JPanel();
  136. panel.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 10));
  137. panel.setLayout(new GridBagLayout());
  138. GridBagConstraints c = new GridBagConstraints();
  139. c.fill = GridBagConstraints.HORIZONTAL;
  140. c.gridx = 0;
  141. c.gridy = 0;
  142. c.weightx = 0;
  143. c.anchor = GridBagConstraints.NORTH;
  144. panel.setComponentOrientation(ComponentOrientation.LEFT_TO_RIGHT);
  145. NumberFormat doubleFormat = NumberFormat.getNumberInstance(Locale.US);
  146. doubleFormat.setMinimumFractionDigits(0);
  147. doubleFormat.setMaximumFractionDigits(2);
  148. doubleFormat.setRoundingMode(RoundingMode.HALF_UP);
  149. NumberFormatter doubleFormatter = new NumberFormatter(doubleFormat);
  150. doubleFormatter.setMinimum(0.0);
  151. doubleFormatter.setMaximum(1.0);
  152. //doubleFormatter.setCommitsOnValidEdit(true);
  153. JFormattedTextField change = new JFormattedTextField(doubleFormatter);
  154. change.addActionListener(ChangeEvent -> priorityD.slider.setValue(
  155. (int) (Double.parseDouble(change.getValue().toString()) * 100.0)));
  156. change.setText("0.1");
  157. change.setPreferredSize(new Dimension(40, 20));
  158. panel.add(change, c);
  159. c.fill = GridBagConstraints.HORIZONTAL;
  160. c.gridx = 1;
  161. c.weightx = 1;
  162. priorityD.slider.setMajorTickSpacing(50);
  163. priorityD.slider.setMinorTickSpacing(5);
  164. priorityD.slider.setPaintTicks(true);
  165. Hashtable<Integer, JLabel> labelTable = new Hashtable<Integer, JLabel>();
  166. labelTable.put(Integer.valueOf(0), new JLabel("Positiv"));
  167. labelTable.put(Integer.valueOf(100), new JLabel("Negativ"));
  168. priorityD.slider.addChangeListener(changeEvent -> {
  169. priorityD.offer.proportion = (double) priorityD.slider.getValue() / 100.0;
  170. priorityD.slider.setToolTipText("" + priorityD.offer.proportion);
  171. change.setText("" + priorityD.offer.proportion);
  172. priorityD.setTarget(priorityD.offer.proportion);
  173. });
  174. priorityD.slider.setLabelTable(labelTable);
  175. priorityD.slider.setPaintLabels(true);
  176. panel.add(priorityD.slider, c);
  177. return panel;
  178. }
  179. private void run() {
  180. if (control == null) {
  181. return;
  182. }
  183. if (low.checkbox.isSelected()) {
  184. low.updateCanvasToTargetAmounts();
  185. }
  186. if (medium.checkbox.isSelected()) {
  187. medium.updateCanvasToTargetAmounts();
  188. }
  189. if (high.checkbox.isSelected()) {
  190. high.updateCanvasToTargetAmounts();
  191. }
  192. if (essential.checkbox.isSelected()) {
  193. essential.updateCanvasToTargetAmounts();
  194. }
  195. }
  196. public void update() {
  197. if (control == null) {
  198. return;
  199. }
  200. control.calculateStateForCurrentIteration();
  201. List<Flexibility> flexList = control.getModel().getAllFlexibilities();
  202. List<Flexibility> allOfferedFlex = flexList.stream()
  203. .filter(flex -> flex.getState().equals(FlexState.OFFERED)).toList();
  204. low.flexList = allOfferedFlex.stream()
  205. .filter(flex -> flex.getElement().getPriority() == Priority.Low)
  206. .collect(Collectors.toList());
  207. medium.flexList = allOfferedFlex.stream()
  208. .filter(flex -> flex.getElement().getPriority() == Priority.Medium)
  209. .collect(Collectors.toList());
  210. high.flexList = allOfferedFlex.stream()
  211. .filter(flex -> flex.getElement().getPriority() == Priority.High)
  212. .collect(Collectors.toList());
  213. essential.flexList = allOfferedFlex.stream()
  214. .filter(flex -> flex.getElement().getPriority() == Priority.Essential)
  215. .collect(Collectors.toList());
  216. low.update();
  217. medium.update();
  218. high.update();
  219. essential.update();
  220. }
  221. @Override
  222. public JPanel getPanel() {
  223. return content;
  224. }
  225. @Override
  226. public void setController(Control control) {
  227. this.control = control;
  228. update();
  229. }
  230. private class PriorityDependeces {
  231. public JCheckBox checkbox;
  232. public JSlider slider = new JSlider(JSlider.HORIZONTAL, 0, 100, 50);
  233. public JLabel positive = new JLabel("0 \u2192 0(0)");
  234. public JLabel negative = new JLabel("0 \u2192 0(0)");
  235. public FlexOffered offer = new FlexOffered();
  236. public List<Flexibility> flexList = new ArrayList<Flexibility>();
  237. public PriorityDependeces(String name) {
  238. checkbox = new JCheckBox(name, true);
  239. }
  240. public void update() {
  241. List<Flexibility> positiveList = flexList.stream().filter(flex -> flex.isPositive())
  242. .collect(Collectors.toList());
  243. offer.positive.maximumOffered = positiveList.size();
  244. offer.positive.actualOffered = (int) positiveList.stream().filter(flex -> (flex.offered))
  245. .count();
  246. List<Flexibility> negativeList = flexList.stream().filter(flex -> flex.isNegative())
  247. .collect(Collectors.toList());
  248. offer.negative.maximumOffered = negativeList.size();
  249. offer.negative.actualOffered = (int) negativeList.stream().filter(flex -> (flex.offered))
  250. .count();
  251. offer.updateActualProportion();
  252. setTarget(offer.proportion);
  253. }
  254. public void setTarget(double proprotion) {
  255. offer.updateTarget(proprotion);
  256. //Update slider
  257. slider.setValue((int) (offer.proportion * 100.0));
  258. //Update Label
  259. positive.setText(
  260. offer.positive.actualOffered + " \u2192 " + offer.positive.targetOffered + "("
  261. + offer.positive.maximumOffered + ")");
  262. negative.setText(
  263. offer.negative.actualOffered + " \u2192 " + offer.negative.targetOffered + "("
  264. + offer.negative.maximumOffered + ")");
  265. }
  266. public void updateCanvasToTargetAmounts() {
  267. List<Flexibility> positiveList = flexList.stream().filter(flex -> flex.isPositive())
  268. .collect(Collectors.toList());
  269. Collections.shuffle(positiveList, new Random());
  270. for (int i = 0; i < positiveList.size(); i++) {
  271. positiveList.get(i).offered = (i < offer.positive.targetOffered);
  272. }
  273. List<Flexibility> negativeList = flexList.stream().filter(flex -> flex.isNegative())
  274. .collect(Collectors.toList());
  275. Collections.shuffle(negativeList, new Random());
  276. for (int i = 0; i < negativeList.size(); i++) {
  277. negativeList.get(i).offered = (i < offer.negative.targetOffered);
  278. }
  279. if (control != null) {
  280. control.calculateStateForCurrentIteration();
  281. }
  282. }
  283. }
  284. private class FlexOffered {
  285. public double proportion = 0.5;
  286. public FlexTypeOffered positive = new FlexTypeOffered();
  287. public FlexTypeOffered negative = new FlexTypeOffered();
  288. public void updateTarget(double proportion) {
  289. //Clamp between 0 and 1
  290. proportion = Math.min(1, Math.max(0, proportion));
  291. if (1 == proportion) {
  292. negative.targetOffered = 0;
  293. positive.targetOffered = positive.maximumOffered;
  294. } else if (0 == proportion) {
  295. positive.targetOffered = 0;
  296. negative.targetOffered = negative.maximumOffered;
  297. } else {
  298. //x * proportion = positive.maximumOffered
  299. int maximumAmountBothA = (int) ((double) positive.maximumOffered / proportion);
  300. int amountOtherSide = maximumAmountBothA - positive.maximumOffered;
  301. if (amountOtherSide <= negative.maximumOffered) {
  302. negative.targetOffered = amountOtherSide;
  303. positive.targetOffered = positive.maximumOffered;
  304. } else {
  305. int maximumAmountBothB = (int) ((double) negative.maximumOffered / (1.0 - proportion));
  306. int amountOtherSideB = maximumAmountBothB - negative.maximumOffered;
  307. positive.targetOffered = amountOtherSideB;
  308. negative.targetOffered = negative.maximumOffered;
  309. }
  310. }
  311. }
  312. public void updateActualProportion() {
  313. if (positive.actualOffered + negative.actualOffered == 0) {
  314. proportion = 0.5;
  315. } else {
  316. proportion = (double) positive.actualOffered / (double) (positive.actualOffered
  317. + negative.actualOffered);
  318. }
  319. }
  320. public double getActualProportion() {
  321. if (positive.actualOffered + negative.actualOffered == 0) {
  322. return 0.5;
  323. }
  324. return (double) positive.actualOffered / (double) (positive.actualOffered
  325. + negative.actualOffered);
  326. }
  327. }
  328. private class FlexTypeOffered {
  329. int actualOffered = 0;
  330. int maximumOffered = 0;
  331. int targetOffered = 0;
  332. }
  333. }