package exampleAlgorithms; 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.Set; import java.util.concurrent.TimeUnit; 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.JFormattedTextField; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JProgressBar; import javax.swing.JScrollPane; import javax.swing.JSplitPane; import javax.swing.JTextArea; import javax.swing.text.NumberFormatter; import api.Algorithm; import classes.AbstractCpsObject; import classes.CpsUpperNode; import classes.HolonElement; import classes.HolonElement.Priority; import classes.HolonObject; import classes.HolonSwitch; import ui.controller.Control; import ui.controller.FlexManager; import ui.controller.FlexManager.FlexState; import ui.controller.FlexManager.FlexWrapper; import ui.model.DecoratedGroupNode; import ui.model.DecoratedNetwork; import ui.model.DecoratedState; import ui.model.Model; import ui.model.DecoratedHolonObject.HolonObjectState; public class FlexExample implements Algorithm { //Parameter for Algo with default Values: private boolean closeSwitches = true; //Settings For GroupNode using and cancel private boolean useGroupNode = false; private DecoratedGroupNode dGroupNode = null; 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 JProgressBar progressBar = new JProgressBar(); private int progressBarCount = 0; private long startTime; private Thread runThread; public static void main(String[] args) { JFrame newFrame = new JFrame("exampleWindow"); DemoAlgo instance = new DemoAlgo(); newFrame.setContentPane(instance.getAlgorithmPanel()); 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; progressBar.setValue(0); } 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.setCurIteration(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.setCurIteration(0); updateVisual(); }else { println("No run inistialized."); } } private void disableGuiInput(boolean bool) { control.guiDiable(bool); } @Override public JPanel getAlgorithmPanel() { return content; } @Override public void setController(Control control) { this.control = control; } private void clear() { textArea.setText(""); } private void print(String message) { textArea.append(message); } private void println(String message) { textArea.append(message + "\n"); } private void selectGroupNode() { Object[] possibilities = control.getSimManager().getActualVisualRepresentationalState().getCreatedGroupNodes().values().stream().map(aCps -> new Handle(aCps)).toArray(); @SuppressWarnings("unchecked") Handle selected = (Handle) 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); dGroupNode = selected.object; } } private void progressBarStep(){ progressBar.setValue(++progressBarCount); } private void calculateProgressBarParameter() { int max = 100; progressBarCount = 0; progressBar.setValue(0); progressBar.setMaximum(max); } 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().getCurIteration(); println("TimeStep:" + actualIteration); control.calculateStateOnlyForCurrentTimeStep(); List priorityListASC = createPriorityListASC(); DecoratedState actualstate = control.getSimManager().getActualDecorState(); 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); FlexManager flexManager = control.getSimManager().getActualFlexManager(); List allOfferedFlex = flexManager.getAllFlexWrapperWithState(FlexState.OFFERED).stream().filter(flexWrapper -> allHolonElemntsInThisNetwork.contains(flexWrapper.getFlex().getElement())).collect(Collectors.toList()); List allFlexThatGetMeEnergy = allOfferedFlex.stream().filter(flexWrapper -> (flexWrapper.getFlex().bringtmir() > 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(flexManager, allHolonElemntsInThisNetwork, emergencyShutDownPriority, result); } //SortFlexes allFlexThatGetMeEnergy.sort((flex1, flex2) -> Float.compare(flex1.getFlex().cost / flex1.getFlex().bringtmir(), flex2.getFlex().cost / flex2.getFlex().bringtmir())); //OrderFlexes float costForThisTimeStep = 0f; int amountflexActivated = 0; for(FlexWrapper flexWrapper : allFlexThatGetMeEnergy) { if(!flexWrapper.canOrder()) continue; float energy = flexWrapper.getFlex().bringtmir(); if(energy <= difference) { println("energyGained:" + energy); difference -= energy; costForThisTimeStep += flexWrapper.getFlex().cost; flexWrapper.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().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(FlexManager flexManager, Set allHolonElemntsInThisNetwork, Priority emergencyShutDownPriority, RunResult result) { List elementsOfPriorityToShutdown = allHolonElemntsInThisNetwork.stream().filter(hElement -> hElement.isConsumer() && hElement.getPriority() == emergencyShutDownPriority && !hElement.isFlexActive(flexManager) && hElement.isActive()).collect(Collectors.toList()); //.forEach(hElement -> hElement.setActive(false)); float energyGained = elementsOfPriorityToShutdown.stream().map(hElement -> -hElement.getEnergyPerElement() * hElement.getAmount()).reduce(0.0f, (a, b) -> a + b); elementsOfPriorityToShutdown.forEach(hElement -> hElement.setActive(false)); int shutdownCount = elementsOfPriorityToShutdown.size(); result.deactivatedElements += shutdownCount; println("Gained " + energyGained + "Energy from Shutdown with Priority:" + emergencyShutDownPriority + " AmountOfShutDowned HolonElements: " + shutdownCount); return energyGained; } private Set createListOfAllHolonElemnts(DecoratedNetwork net) { Set allHolonElemntsInThisNetwork = new HashSet(); allHolonElemntsInThisNetwork.addAll(net.getConsumerList().stream().flatMap(con -> con.getModel().getElements().stream()).collect(Collectors.toList())); allHolonElemntsInThisNetwork.addAll(net.getConsumerSelfSuppliedList().stream().flatMap(con -> con.getModel().getElements().stream()).collect(Collectors.toList())); allHolonElemntsInThisNetwork.addAll(net.getSupplierList().stream().flatMap(con -> con.getModel().getElements().stream()).collect(Collectors.toList())); return allHolonElemntsInThisNetwork; } private float sumEnergyAvailable(List flexList) { HashMap dublicateFilter = new HashMap(); flexList.stream().forEach(flexWrapper -> dublicateFilter.put(flexWrapper.getFlex().getElement(), flexWrapper)); return dublicateFilter.values().stream().map(flexWrapper -> flexWrapper.getFlex().bringtmir()).reduce(0.0f,(a, b) -> a + b); } 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 model * @return */ private List extractPositionAndAccess() { Model model = control.getModel(); switchList = new ArrayList(); objectList = new ArrayList(); initialState = new ArrayList(); access= new HashMap(); rollOutNodes((useGroupNode && (dGroupNode != null))? dGroupNode.getModel().getNodes() :model.getObjectsOnCanvas(), initialState, model.getCurIteration()); resetChain.add(initialState); return initialState; } /** * Method to extract the Informations recursively out of the Model. * @param nodes * @param positionToInit * @param timeStep */ private void rollOutNodes(List nodes, List positionToInit, int timeStep) { for(AbstractCpsObject aCps : nodes) { if (aCps instanceof HolonObject) { for (HolonElement hE : ((HolonObject) aCps).getElements()) { positionToInit.add(hE.isActive()); access.put(positionToInit.size() - 1 , new AccessWrapper(hE)); } objectList.add((HolonObject) aCps); } else if (aCps instanceof HolonSwitch) { HolonSwitch sw = (HolonSwitch) aCps; positionToInit.add(sw.getState(timeStep)); switchList.add(sw); access.put(positionToInit.size() - 1 , new AccessWrapper(sw)); } else if(aCps instanceof CpsUpperNode) { rollOutNodes(((CpsUpperNode)aCps).getNodes(), positionToInit ,timeStep ); } } } /** * 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 listToSearch, List listToAdd){ for (AbstractCpsObject aCps : listToSearch) { if (aCps instanceof HolonObject) listToAdd.add((HolonObject) aCps); else if(aCps instanceof CpsUpperNode) { addObjectToList(((CpsUpperNode)aCps).getNodes(),listToAdd); } } } /** * A Wrapper Class for Access HolonElement and HolonSwitch in one Element and not have to split the List. */ private class AccessWrapper { public static final int HOLONELEMENT = 0; public static final int SWITCH = 1; private int type; private HolonSwitch hSwitch; private HolonElement hElement; public AccessWrapper(HolonSwitch hSwitch){ type = SWITCH; this.hSwitch = hSwitch; } public AccessWrapper(HolonElement hElement){ type = HOLONELEMENT; this.hElement = hElement; } public void setState(boolean state) { if(type == HOLONELEMENT) { hElement.setActive(state); }else{//is switch hSwitch.setManualMode(true); hSwitch.setManualState(state); } } public boolean getState(int timeStep) { return (type == HOLONELEMENT)?hElement.isActive():hSwitch.getState(timeStep); } public int getType() { return type; } } private class RunResult { public int activatedFlex = 0; public int deactivatedElements = 0; public float totalCost = 0; public LinkedList 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(); } } }