package holeg.algorithm.example; import java.awt.BorderLayout; import java.awt.Component; import java.awt.Dimension; import java.awt.FlowLayout; import java.awt.image.BufferedImage; import java.text.NumberFormat; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedList; import java.util.List; import java.util.Optional; import java.util.Set; import java.util.stream.Collectors; import java.util.stream.Stream; import javax.swing.BorderFactory; import javax.swing.ImageIcon; import javax.swing.JButton; import javax.swing.JCheckBox; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JSplitPane; import javax.swing.JTextArea; import javax.swing.text.NumberFormatter; import holeg.api.AddOn; import holeg.model.AbstractCanvasObject; import holeg.model.Flexibility; import holeg.model.GroupNode; import holeg.model.HolonElement; import holeg.model.HolonObject; import holeg.model.HolonObject.HolonObjectState; import holeg.model.HolonSwitch.SwitchMode; import holeg.model.HolonSwitch.SwitchState; import holeg.model.HolonSwitch; import holeg.model.Flexibility.FlexState; import holeg.model.HolonElement.Priority; import holeg.ui.controller.Control; import holeg.ui.model.Model; public class FlexExample implements AddOn { //Settings For GroupNode using and cancel private boolean useGroupNode = false; private Optional groupnode = Optional.empty(); private boolean cancel = false; private boolean overAllTimeSteps = false; //Parameter defined by Algo private HashMap access; LinkedList> resetChain = new LinkedList>(); private List initialState; private List switchList; private List objectList; //Gui Part: private Control control; private JTextArea textArea; private JPanel content = new JPanel(); //ProgressBar private long startTime; private Thread runThread; public static void main(String[] args) { JFrame newFrame = new JFrame("exampleWindow"); DemoAlgo instance = new DemoAlgo(); newFrame.setContentPane(instance.getPanel()); newFrame.pack(); newFrame.setVisible(true); newFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); } public FlexExample() { content.setLayout(new BorderLayout()); textArea = new JTextArea(); textArea.setEditable(false); JScrollPane scrollPane = new JScrollPane(textArea); JSplitPane splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, createOptionPanel() , scrollPane); splitPane.setResizeWeight(0.0); content.add(splitPane, BorderLayout.CENTER); content.setPreferredSize(new Dimension(800,800)); } public JPanel createOptionPanel() { JPanel optionPanel = new JPanel(new BorderLayout()); JScrollPane scrollPane = new JScrollPane(createParameterPanel()); scrollPane.setBorder(BorderFactory.createTitledBorder("Parameter")); optionPanel.add(scrollPane, BorderLayout.CENTER); optionPanel.add(createButtonPanel(), BorderLayout.PAGE_END); return optionPanel; } private Component createParameterPanel() { JPanel parameterPanel = new JPanel(null); parameterPanel.setPreferredSize(new Dimension(510,300)); // JLabel showDiagnosticsLabel = new JLabel("Set all switches closed:"); // showDiagnosticsLabel.setBounds(200, 60, 170, 20); // parameterPanel.add(showDiagnosticsLabel); JPanel borderPanel = new JPanel(null); borderPanel.setBounds(200, 85, 185, 50); borderPanel.setBorder(BorderFactory.createTitledBorder("")); parameterPanel.add(borderPanel); JLabel showGroupNodeLabel = new JLabel("Use Group Node:"); showGroupNodeLabel.setBounds(10, 1, 170, 20); borderPanel.add(showGroupNodeLabel); JButton selectGroupNodeButton = new JButton("Select GroupNode"); selectGroupNodeButton.setEnabled(false); selectGroupNodeButton.setBounds(10, 25, 165, 20); selectGroupNodeButton.addActionListener(actionEvent -> selectGroupNode()); borderPanel.add(selectGroupNodeButton); JCheckBox useGroupNodeCheckBox = new JCheckBox(); useGroupNodeCheckBox.setSelected(false); useGroupNodeCheckBox.setBounds(155, 1, 25, 20); useGroupNodeCheckBox.addActionListener(actionEvent -> { useGroupNode = useGroupNodeCheckBox.isSelected(); selectGroupNodeButton.setEnabled(useGroupNode); }); borderPanel.add(useGroupNodeCheckBox); JCheckBox overAllTimeStepsCheckbox = new JCheckBox("overAllTimeSteps"); overAllTimeStepsCheckbox.setSelected(false); overAllTimeStepsCheckbox.setBounds(20, 30, 250, 30); overAllTimeStepsCheckbox.addActionListener(actionEvent -> { overAllTimeSteps = overAllTimeStepsCheckbox.isSelected(); }); parameterPanel.add(overAllTimeStepsCheckbox); NumberFormat format = NumberFormat.getIntegerInstance(); format.setGroupingUsed(false); format.setParseIntegerOnly(true); NumberFormatter integerFormatter = new NumberFormatter(format); integerFormatter.setMinimum(0); integerFormatter.setCommitsOnValidEdit(true); JLabel portLabel = new JLabel("between:"); portLabel.setBounds(10, 330, 70, 30); parameterPanel.add(portLabel); JLabel afterLabel = new JLabel("after:"); afterLabel.setBounds(10, 360, 70, 30); parameterPanel.add(afterLabel); return parameterPanel; } public JPanel createButtonPanel() { JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT)); JButton resetButton = new JButton("ResetAll"); resetButton.setToolTipText("Resets the State to before the Algorithm has runed."); resetButton.addActionListener(actionEvent -> resetAll()); buttonPanel.add(resetButton); JButton cancelButton = new JButton("Cancel Run"); cancelButton.addActionListener(actionEvent -> cancel()); buttonPanel.add(cancelButton); JButton clearButton = new JButton("Clear Console"); clearButton.addActionListener(actionEvent -> clear()); buttonPanel.add(clearButton); JButton undoButton = new JButton("Undo"); undoButton.setToolTipText("One Algo Step Back."); undoButton.addActionListener(actionEvent -> resetLast()); buttonPanel.add(undoButton); JButton runButton = new JButton("Run"); runButton.addActionListener(actionEvent -> { Runnable task = () -> { if(this.overAllTimeSteps)runAll(); else run(); }; runThread = new Thread(task); runThread.start(); }); buttonPanel.add(runButton); return buttonPanel; } private void cancel() { if(runThread.isAlive()) { println(""); println("Cancel run."); cancel = true; } else { println("Nothing to cancel."); } } private void runAll() { cancel = false; disableGuiInput(true); startTimer(); control.resetSimulation(); RunResult result= new RunResult(); for(int i = 0; i < 100; i++) { control.getModel().setCurrentIteration(i); executeDemoAlgo(result); if(cancel) { resetLast(); disableGuiInput(false); return; } } updateVisual(); calculateAllResults(result); println("Amount of activatedFlex:" + result.activatedFlex + " Amount of deactivatedElements:"+ result.deactivatedElements + " TotalCost:"+result.totalCost); printElapsedTime(); disableGuiInput(false); } private void run() { disableGuiInput(true); startTimer(); executeDemoAlgo(new RunResult()); updateVisual(); printElapsedTime(); disableGuiInput(false); } private void resetLast() { if(!resetChain.isEmpty()) { println("Resetting.."); resetState(); resetChain.removeLast(); control.resetSimulation(); updateVisual(); }else { println("No run inistialized."); } } private void resetAll() { if(!resetChain.isEmpty()) { println("Resetting.."); setState(resetChain.getFirst()); resetChain.clear(); control.resetSimulation(); control.getModel().setCurrentIteration(0); updateVisual(); }else { println("No run inistialized."); } } private void disableGuiInput(boolean bool) { control.guiSetEnabled(bool); } @Override public JPanel getPanel() { return content; } @Override public void setController(Control control) { this.control = control; } private void clear() { textArea.setText(""); } private void println(String message) { textArea.append(message + "\n"); } private void selectGroupNode() { Object[] possibilities = control.getModel().getCanvas().getAllGroupNodeObjectsRecursive().toArray(); @SuppressWarnings("unchecked") GroupNode selected = (GroupNode) JOptionPane.showInputDialog(content, "Select GroupNode:", "GroupNode?", JOptionPane.OK_OPTION,new ImageIcon(new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB)) , possibilities, ""); if(selected != null) { println("Selected: " + selected); groupnode = Optional.of(selected); } } private void startTimer(){ startTime = System.currentTimeMillis(); } private void printElapsedTime(){ long elapsedMilliSeconds = System.currentTimeMillis() - startTime; println("Execution Time of Algo in Milliseconds:" + elapsedMilliSeconds); } //Algo Part: /** * The Execution of the FlexAlgo. * * * Begin * for(All Networks) do * * if(not (production < consumption)) continue; * * * for(Priority emergencyShutDownPriority: priorityListASC) do * difference = Math.abs(production - consumption); * amountOfAllEnergyOffered = sumEnergyAvailable(flexList); * if(amountOfAllEnergyOffered > difference) break; * shutDownAllConsumerWithPriority(emergencyShutDownPriority) * end for * * takeAKombinationOfOffers(); (nach welchem Kriterium) * * * end for * End * */ private void executeDemoAlgo(RunResult result) { extractPositionAndAccess(); int actualIteration = control.getModel().getCurrentIteration(); println("TimeStep:" + actualIteration); control.calculateStateOnlyForCurrentTimeStep(); List priorityListASC = createPriorityListASC(); // DecoratedState actualstate = control.getSimManager().getActualDecorState().get(); // for(DecoratedNetwork net : actualstate.getNetworkList()) { // float production = net.getSupplierList().stream().map(supplier -> supplier.getEnergyToSupplyNetwork()).reduce(0.0f, (a, b) -> a + b); // float consumption = net.getConsumerList().stream().map(con -> con.getEnergyNeededFromNetwork()).reduce(0.0f, (a, b) -> a + b); // float difference = Math.abs(production - consumption); // println("production: " + production); // println("consumption: " + consumption); // println("difference: " + difference); // if(production > consumption) continue; // if(difference == 0)continue; // Set allHolonElemntsInThisNetwork = createListOfAllHolonElemnts(net); // List flexList = control.getModel().getAllFlexibilities(); // List allOfferedFlex = flexList.stream().filter(flex -> flex.getState().equals(FlexState.OFFERED)).toList(); // List allFlexThatGetMeEnergy = allOfferedFlex.stream().filter(flexWrapper -> (flexWrapper.energyReleased() > 0)).collect(Collectors.toList()); // float amountOfAllEnergyOffered = sumEnergyAvailable(allFlexThatGetMeEnergy); // println("amountOfAllFlexEnergyOffered:" + amountOfAllEnergyOffered); // //ShuddownPriorities // for(Priority emergencyShutDownPriority: priorityListASC) { // if(amountOfAllEnergyOffered >= difference) break; // println("ShutDown: " + emergencyShutDownPriority); // difference -= shutDownAllConsumerElementsWithPriority(allHolonElemntsInThisNetwork, emergencyShutDownPriority, result); // } // // //SortFlexes // allFlexThatGetMeEnergy.sort((flex1, flex2) -> Float.compare(flex1.cost / flex1.energyReleased(), flex2.cost / flex2.energyReleased())); // //OrderFlexes // float costForThisTimeStep = 0f; // int amountflexActivated = 0; // for(Flexibility flex : allFlexThatGetMeEnergy) { // if(!flex.canOrder()) continue; // float energy = flex.energyReleased(); // if(energy <= difference) { // println("energyGained:" + energy); // difference -= energy; // costForThisTimeStep += flex.cost; // flex.order(); // amountflexActivated++; // continue; // } // } // result.activatedFlex += amountflexActivated; // // println("Activated FlexThisTimeStep: "+ amountflexActivated+" CostForThisTimeStep:" + costForThisTimeStep); // result.totalCost += costForThisTimeStep; // } calculateStateResult(result); } private void calculateStateResult(RunResult result) { control.calculateStateOnlyForCurrentTimeStep(); // RunResult.TimeStepStateResult timeStepState = result.addTimeStepStateResult(); // // for(DecoratedNetwork network: control.getSimManager().getActualDecorState().get().getNetworkList()) { // timeStepState.amountOfConsumer += network.getAmountOfConsumer(); // timeStepState.amountOfConsumerOverSupplied += network.getAmountOfConsumerWithState(HolonObjectState.OVER_SUPPLIED); // timeStepState.amountOfConsumerPartiallySupplied += network.getAmountOfConsumerWithState(HolonObjectState.PARTIALLY_SUPPLIED); // timeStepState.amountOfConsumerSupplied += network.getAmountOfConsumerWithState(HolonObjectState.SUPPLIED); // timeStepState.amountOfConsumerUnSupplied += network.getAmountOfConsumerWithState(HolonObjectState.NOT_SUPPLIED); // timeStepState.amountOfPassiv += network.getAmountOfPassiv(); // timeStepState.amountOfProducer += network.getAmountOfSupplier(); // } // println("Producer: " + timeStepState.amountOfProducer); // println("Consumer: " + timeStepState.amountOfConsumer); // println("ConsumerOverSupplied: " + timeStepState.amountOfConsumerOverSupplied); // println("ConsumerSupplied: " + timeStepState.amountOfConsumerSupplied); // println("ConsumerPartiallySupplied: " + timeStepState.amountOfConsumerPartiallySupplied); // println("ConsumerUnSupplied: " + timeStepState.amountOfConsumerUnSupplied); // println("ConsumerUnSupplied: " + timeStepState.amountOfPassiv); } private void calculateAllResults(RunResult result) { println("----------"); println("Average producer proportion: " + result.getAvergaeProportionWithState(HolonObjectState.PRODUCER)); println("Average producer OverSupplied: " + result.getAvergaeProportionWithState(HolonObjectState.OVER_SUPPLIED)); println("Average producer Supplied: " + result.getAvergaeProportionWithState(HolonObjectState.SUPPLIED)); println("Average producer PartiallySupplied: " + result.getAvergaeProportionWithState(HolonObjectState.PARTIALLY_SUPPLIED)); println("Average producer NotSupplied: " + result.getAvergaeProportionWithState(HolonObjectState.NOT_SUPPLIED)); println("Average producer NoEnergy: " + result.getAvergaeProportionWithState(HolonObjectState.NO_ENERGY)); } private float shutDownAllConsumerElementsWithPriority(Set allHolonElemntsInThisNetwork, Priority emergencyShutDownPriority, RunResult result) { List elementsOfPriorityToShutdown = allHolonElemntsInThisNetwork.stream().filter(hElement -> hElement.isConsumer() && hElement.getPriority() == emergencyShutDownPriority && !hElement.isFlexActive() && hElement.active).collect(Collectors.toList()); //.forEach(hElement -> hElement.setActive(false)); float energyGained = elementsOfPriorityToShutdown.stream().map(hElement -> -hElement.getEnergy()).reduce(0.0f, (a, b) -> a + b); elementsOfPriorityToShutdown.forEach(hElement -> hElement.active = false); int shutdownCount = elementsOfPriorityToShutdown.size(); result.deactivatedElements += shutdownCount; println("Gained " + energyGained + "Energy from Shutdown with Priority:" + emergencyShutDownPriority + " AmountOfShutDowned HolonElements: " + shutdownCount); return energyGained; } private float sumEnergyAvailable(List flexList) { HashMap dublicateFilter = new HashMap(); flexList.stream().forEach(flex -> dublicateFilter.put(flex.getElement(), flex)); return dublicateFilter.values().stream().map(flex -> flex.energyReleased()).reduce(0.0f,Float::sum); } private List createPriorityListASC() { List priorityASC = new ArrayList(); priorityASC.add(Priority.Low); priorityASC.add(Priority.Medium); priorityASC.add(Priority.High); priorityASC.add(Priority.Essential); return priorityASC; } /** * Method to get the current Position alias a ListOf Booleans for aktive settings on the Objects on the Canvas. * Also initialize the Access Hashmap to swap faster positions. * @param ModelTest * @return */ private List extractPositionAndAccess() { Model model = control.getModel(); switchList = new ArrayList(); objectList = new ArrayList(); initialState = new ArrayList(); access= new HashMap(); rollOutNodes((useGroupNode && (groupnode.isPresent()))? groupnode.get().getObjectsInThisLayer() :model.getCanvas().getObjectsInThisLayer(), initialState, model.getCurrentIteration()); resetChain.add(initialState); return initialState; } /** * Method to extract the Informations recursively out of the Model. * @param nodes * @param positionToInit * @param timeStep */ private void rollOutNodes(Stream nodes, List positionToInit, int timeStep) { nodes.forEach(aCps -> { if (aCps instanceof HolonObject hO) { hO.getElements().forEach(hE -> { positionToInit.add(hE.active); access.put(positionToInit.size() - 1 , new AccessWrapper(hE)); }); objectList.add(hO); } else if (aCps instanceof HolonSwitch sw) { positionToInit.add(sw.getState().isClosed()); switchList.add(sw); access.put(positionToInit.size() - 1 , new AccessWrapper(sw)); } else if(aCps instanceof GroupNode groupnode) { rollOutGroupNode(groupnode, positionToInit ,timeStep); } }); } private void rollOutGroupNode (GroupNode groupNode, List positionToInit, int timeStep) { groupNode.getAllHolonObjectsRecursive().forEach(hObject -> { hObject.getElements().forEach(hE -> { positionToInit.add(hE.active); access.put(positionToInit.size() - 1 , new AccessWrapper(hE)); }); objectList.add(hObject); }); groupNode.getAllSwitchObjectsRecursive().forEach(sw -> { positionToInit.add(sw.getState().isClosed()); switchList.add(sw); access.put(positionToInit.size() - 1 , new AccessWrapper(sw)); }); } /** * To let the User See the current state without touching the Canvas. */ private void updateVisual() { control.calculateStateAndVisualForCurrentTimeStep(); //control.updateCanvas(); //control.getGui().triggerUpdateController(null); } /** * Sets the Model back to its original State before the LAST run. */ private void resetState() { setState(resetChain.getLast()); } /** * Sets the State out of the given position for calculation or to show the user. * @param position */ private void setState(List position) { for(int i = 0;i timeStepList = new LinkedList(); public TimeStepStateResult addTimeStepStateResult(){ TimeStepStateResult aResult = new TimeStepStateResult(); timeStepList.add(aResult); return aResult; } public class TimeStepStateResult{ public int amountOfProducer = 0; public int amountOfConsumer = 0; public int amountOfPassiv = 0; public int amountOfConsumerOverSupplied = 0; public int amountOfConsumerSupplied = 0; public int amountOfConsumerPartiallySupplied = 0; public int amountOfConsumerUnSupplied= 0; public float getProportionWithState(HolonObjectState state) { float amountOfObjects = amountOfProducer + amountOfConsumer + amountOfPassiv; switch(state) { case NOT_SUPPLIED: return (float) amountOfConsumerUnSupplied / amountOfObjects; case NO_ENERGY: return (float) amountOfPassiv / amountOfObjects; case OVER_SUPPLIED: return (float) amountOfConsumerOverSupplied / amountOfObjects; case PARTIALLY_SUPPLIED: return (float) amountOfConsumerPartiallySupplied / amountOfObjects; case PRODUCER: return (float) amountOfProducer / amountOfObjects; case SUPPLIED: return (float) amountOfConsumerSupplied / amountOfObjects; default: return 0.f; } } } public float getAvergaeProportionWithState(HolonObjectState state) { return timeStepList.stream().map(step -> step.getProportionWithState(state)).reduce((a,b) -> (a + b)).orElse(0.f) / (float) 100; } } private class Handle{ public T object; Handle(T object){ this.object = object; } public String toString() { return object.toString(); } } }