package addOns; import java.awt.BorderLayout; import java.awt.ComponentOrientation; import java.awt.Dimension; import java.awt.FlowLayout; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.math.RoundingMode; import java.text.NumberFormat; import java.util.ArrayList; import java.util.Collections; import java.util.Hashtable; import java.util.List; import java.util.Locale; import java.util.Random; import java.util.stream.Collectors; import javax.swing.BorderFactory; import javax.swing.JButton; import javax.swing.JCheckBox; import javax.swing.JFormattedTextField; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JSlider; import javax.swing.text.NumberFormatter; import api.AddOn; import classes.Flexibility; import classes.HolonElement.Priority; import ui.controller.Control; /** * A short algorithm to distribute the Priorities for the whole Canvas. * @author tom * */ public class RandomOfferdFlexibility implements AddOn { private Control control; private JPanel content = new JPanel(); private class PriorityDependeces{ public JCheckBox checkbox; public JSlider slider = new JSlider(JSlider.HORIZONTAL,0, 100, 50); public JLabel positive = new JLabel("0 \u2192 0(0)"); public JLabel negative = new JLabel("0 \u2192 0(0)"); public FlexOffered offer = new FlexOffered(); public List flexList = new ArrayList(); public PriorityDependeces(String name){ checkbox = new JCheckBox(name, true); } public void update() { List positiveList = flexList.stream().filter(flex -> flex.isPositive()).collect(Collectors.toList()); offer.positive.maximumOffered = positiveList.size(); offer.positive.actualOffered = (int)positiveList.stream().filter(flex -> (flex.offered)).count(); List negativeList = flexList.stream().filter(flex -> flex.isNegative()).collect(Collectors.toList()); offer.negative.maximumOffered = negativeList.size(); offer.negative.actualOffered = (int)negativeList.stream().filter(flex -> (flex.offered)).count(); offer.updateActualProportion(); setTarget(offer.proportion); } public void setTarget(double proprotion) { offer.updateTarget(proprotion); //Update slider slider.setValue((int)(offer.proportion * 100.0)); //Update Label positive.setText(offer.positive.actualOffered + " \u2192 " + offer.positive.targetOffered + "(" + offer.positive.maximumOffered + ")"); negative.setText(offer.negative.actualOffered + " \u2192 " + offer.negative.targetOffered + "(" + offer.negative.maximumOffered + ")"); } public void updateCanvasToTargetAmounts() { List positiveList = flexList.stream().filter(flex -> flex.isPositive()).collect(Collectors.toList()); Collections.shuffle(positiveList, new Random()); for(int i = 0; i < positiveList.size(); i++){ positiveList.get(i).offered = (i < offer.positive.targetOffered); } List negativeList = flexList.stream().filter(flex -> flex.isNegative()).collect(Collectors.toList()); Collections.shuffle(negativeList, new Random()); for(int i = 0; i < negativeList.size(); i++){ negativeList.get(i).offered = (i < offer.negative.targetOffered); } if(control != null) { control.calculateStateAndVisualForCurrentTimeStep(); } } } private class FlexOffered{ public double proportion = 0.5; public FlexTypeOffered positive = new FlexTypeOffered(); public FlexTypeOffered negative = new FlexTypeOffered(); public void updateTarget(double proportion) { //Clamp between 0 and 1 proportion = Math.min(1, Math.max(0, proportion)); if(1 == proportion) { negative.targetOffered = 0; positive.targetOffered = positive.maximumOffered; }else if(0 == proportion) { positive.targetOffered = 0; negative.targetOffered = negative.maximumOffered; }else { //x * proportion = positive.maximumOffered int maximumAmountBothA = (int)((double)positive.maximumOffered /proportion); int amountOtherSide = maximumAmountBothA - positive.maximumOffered; if(amountOtherSide <= negative.maximumOffered) { negative.targetOffered = amountOtherSide; positive.targetOffered = positive.maximumOffered; }else { int maximumAmountBothB = (int)((double)negative.maximumOffered / (1.0 -proportion)); int amountOtherSideB = maximumAmountBothB - negative.maximumOffered; positive.targetOffered = amountOtherSideB; negative.targetOffered = negative.maximumOffered; } } } public void updateActualProportion() { if(positive.actualOffered + negative.actualOffered == 0) { proportion = 0.5; }else { proportion = (double)positive.actualOffered / (double)(positive.actualOffered + negative.actualOffered); } } public double getActualProportion() { if(positive.actualOffered + negative.actualOffered == 0) { return 0.5; } return (double)positive.actualOffered / (double)(positive.actualOffered + negative.actualOffered); } } private class FlexTypeOffered{ int actualOffered = 0; int maximumOffered = 0; int targetOffered = 0; } PriorityDependeces low = new PriorityDependeces("low"); PriorityDependeces medium = new PriorityDependeces("medium"); PriorityDependeces high = new PriorityDependeces("high"); PriorityDependeces essential = new PriorityDependeces("essential"); public static void main(String[] args) { JFrame newFrame = new JFrame("exampleWindow"); RandomOfferdFlexibility instance = new RandomOfferdFlexibility(); newFrame.setContentPane(instance.getPanel()); newFrame.pack(); newFrame.setVisible(true); newFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); } public RandomOfferdFlexibility(){ low.offer.positive.maximumOffered = low.offer.positive.actualOffered = 1000; low.offer.negative.maximumOffered = low.offer.negative.actualOffered = 2000; double distribution = 0.8; low.offer.updateTarget(distribution); System.out.println("distribution:" + distribution + " Positive:" + low.offer.positive.targetOffered + " Negative:" + low.offer.negative.targetOffered); System.out.println("actualDistribution:" + low.offer.getActualProportion()); content.setLayout(new BorderLayout()); content.add(createFlexPanel(), BorderLayout.CENTER); JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.TRAILING)); JButton buttonReload = new JButton("Reload"); buttonReload.setToolTipText("Press to relaod all canvas changes."); buttonReload.addActionListener(actionEvent -> update()); buttonPanel.add(buttonReload); JButton buttonRun = new JButton("Run"); buttonRun.setToolTipText("Changes the actual offered flex to the random target amount of selected prioritys."); buttonRun.addActionListener(actionEvent -> run()); buttonPanel.add(buttonRun); content.add(buttonPanel, BorderLayout.PAGE_END); //content.setPreferredSize(new Dimension(300,500)); } private JPanel createFlexPanel() { JPanel flexPanel = new JPanel(); flexPanel.setBorder(BorderFactory.createTitledBorder("Flexibility")); flexPanel.setLayout(new GridBagLayout()); GridBagConstraints c = new GridBagConstraints(); c.fill = GridBagConstraints.HORIZONTAL; c.gridx = 0; c.gridy = 0; c.ipadx = 10; //c.ipady = 100; //Label flexPanel.add(new JLabel("Priority:"), c); c.gridx++; flexPanel.add(new JLabel("Target:"), c); c.gridx++; flexPanel.add(new JLabel("Positive#(Available):"), c); c.gridx++; flexPanel.add(new JLabel("Negative#(Available):"), c); c.gridx = 0; c.gridy = 1; flexPanel.add(low.checkbox, c);c.gridx++; c.weightx = 1; flexPanel.add(createTargetSetterPanel(this.low), c);c.gridx++; c.weightx = 0; flexPanel.add(this.low.positive, c);c.gridx++; flexPanel.add(this.low.negative, c); c.gridx = 0; c.gridy = 2; flexPanel.add(medium.checkbox, c);c.gridx++; flexPanel.add(createTargetSetterPanel(this.medium), c);c.gridx++; flexPanel.add(this.medium.positive, c);c.gridx++; flexPanel.add(this.medium.negative, c); c.gridx = 0; c.gridy = 3; flexPanel.add(high.checkbox, c);c.gridx++; flexPanel.add(createTargetSetterPanel(this.high), c);c.gridx++; flexPanel.add(this.high.positive, c);c.gridx++; flexPanel.add(this.high.negative, c); c.gridx = 0; c.gridy = 4; flexPanel.add(essential.checkbox, c);c.gridx++; flexPanel.add(createTargetSetterPanel(this.essential), c);c.gridx++; flexPanel.add(this.essential.positive, c);c.gridx++; flexPanel.add(this.essential.negative, c); return flexPanel; } private JPanel createTargetSetterPanel(PriorityDependeces priorityD) { JPanel panel = new JPanel(); panel.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 10)); panel.setLayout(new GridBagLayout()); GridBagConstraints c = new GridBagConstraints(); c.fill = GridBagConstraints.HORIZONTAL; c.gridx = 0; c.gridy = 0; c.weightx = 0; c.anchor = GridBagConstraints.NORTH; panel.setComponentOrientation(ComponentOrientation.LEFT_TO_RIGHT); NumberFormat doubleFormat = NumberFormat.getNumberInstance(Locale.US); doubleFormat.setMinimumFractionDigits(0); doubleFormat.setMaximumFractionDigits(2); doubleFormat.setRoundingMode(RoundingMode.HALF_UP); NumberFormatter doubleFormatter = new NumberFormatter(doubleFormat); doubleFormatter.setMinimum(0.0); doubleFormatter.setMaximum(1.0); //doubleFormatter.setCommitsOnValidEdit(true); JFormattedTextField change = new JFormattedTextField(doubleFormatter); change.addActionListener(ChangeEvent -> priorityD.slider.setValue((int)(Double.parseDouble(change.getValue().toString()) * 100.0))); change.setText("0.1"); change.setPreferredSize(new Dimension(40,20)); panel.add(change, c); c.fill = GridBagConstraints.HORIZONTAL; c.gridx = 1; c.weightx = 1; priorityD.slider.setMajorTickSpacing(50); priorityD.slider.setMinorTickSpacing(5); priorityD.slider.setPaintTicks(true); Hashtable labelTable = new Hashtable(); labelTable.put( Integer.valueOf( 0 ), new JLabel("Positiv") ); labelTable.put( Integer.valueOf( 100 ), new JLabel("Negativ") ); priorityD.slider.addChangeListener(changeEvent -> { priorityD.offer.proportion = (double)priorityD.slider.getValue()/100.0; priorityD.slider.setToolTipText("" + priorityD.offer.proportion); change.setText("" +priorityD.offer.proportion); priorityD.setTarget(priorityD.offer.proportion); }); priorityD.slider.setLabelTable( labelTable ); priorityD.slider.setPaintLabels(true); panel.add(priorityD.slider, c); return panel; } private void run() { //control.getModel().getObjectsOnCanvas().stream().filter(aCps -> aCps instanceof HolonObject) if(control == null) { System.out.println("Nothing to do"); return; } if(low.checkbox.isSelected()) low.updateCanvasToTargetAmounts(); if(medium.checkbox.isSelected()) medium.updateCanvasToTargetAmounts(); if(high.checkbox.isSelected()) high.updateCanvasToTargetAmounts(); if(essential.checkbox.isSelected()) essential.updateCanvasToTargetAmounts(); } public void update() { if(control == null) { return; } control.calculateStateAndVisualForCurrentTimeStep(); control.updateCanvas(); List flexList = control.getSimManager().getActualFlexManager().getAllFlexWrapper().stream().filter(flexwrapper -> flexwrapper.getFlex().offered).map(flex -> flex.getFlex()).collect(Collectors.toList()); low.flexList = flexList.stream().filter(flex -> flex.getElement().getPriority() == Priority.Low && flex.fulfillsConstrains()).collect(Collectors.toList()); medium.flexList = flexList.stream().filter(flex -> flex.getElement().getPriority() == Priority.Medium && flex.fulfillsConstrains()).collect(Collectors.toList()); high.flexList = flexList.stream().filter(flex -> flex.getElement().getPriority() == Priority.High && flex.fulfillsConstrains()).collect(Collectors.toList()); essential.flexList = flexList.stream().filter(flex -> flex.getElement().getPriority() == Priority.Essential && flex.fulfillsConstrains()).collect(Collectors.toList()); low.update(); medium.update(); high.update(); essential.update(); } @Override public JPanel getPanel() { return content; } @Override public void setController(Control control) { this.control = control; update(); } }