From b5730e1b183e670c3c591d404ee7b791de54cde1 Mon Sep 17 00:00:00 2001 From: i23007 Date: Sun, 7 Jul 2024 19:49:31 +0200 Subject: [PATCH] Added option to chose between methods --- OurApplication/OurAlgorithm.java | 12 +- OurApplication/OurApplication.java | 5 +- OurApplication/OurHybridWindow.java | 291 +++++++++++++++++- OurApplication/OurMethodButtons.java | 73 +++++ .../OurApplication/OurAlgorithm.class | Bin 2564 -> 2989 bytes .../OurApplication/OurApplication.class | Bin 2844 -> 3072 bytes .../OurApplication/OurHybridWindow.class | Bin 1095 -> 14650 bytes 7 files changed, 368 insertions(+), 13 deletions(-) create mode 100644 OurApplication/OurMethodButtons.java diff --git a/OurApplication/OurAlgorithm.java b/OurApplication/OurAlgorithm.java index e0a5a82..095cb97 100644 --- a/OurApplication/OurAlgorithm.java +++ b/OurApplication/OurAlgorithm.java @@ -20,6 +20,7 @@ import java.util.Vector; public class OurAlgorithm extends Algorithm { private graph.Graph currentGraph; + private OurMethodButtons methodButtons; public OurAlgorithm() { super(); @@ -28,8 +29,9 @@ public class OurAlgorithm extends Algorithm { * Creates a sum up algorithm. * @param parameterArea the sum up parameter area the algorithm gets its parameters from */ - public OurAlgorithm(OurParameterArea parameterArea){ + public OurAlgorithm(OurParameterArea parameterArea, OurMethodButtons methodButtons){ super(parameterArea,"GraphAlgorithm"); + this.methodButtons = methodButtons; } /** @@ -40,6 +42,7 @@ public class OurAlgorithm extends Algorithm { * @return a LogElementList containing the algorithm processing single steps */ public LogElementList run() { + OurParameterArea currentParameterArea = (OurParameterArea) this.getParameterArea(); this.setCurrentGraph(currentParameterArea.getSelectedGraph()); @@ -50,7 +53,11 @@ public class OurAlgorithm extends Algorithm { MarkedVertex end = this.currentGraph.getAllVertexes().get(random.nextInt(this.currentGraph.getAllVertexes().size())); System.out.println(start.getName() + " to " + end.getName()); - this.currentGraph.getShortestPathDijkstra(start, end); + if(this.methodButtons.getSelectedMethod()){ + this.currentGraph.getShortestPathDijkstra(start, end); + }else{ + this.currentGraph.getShortestPathAStar(start, end); + } return this.currentGraph.getLogList(); } @@ -59,6 +66,5 @@ public class OurAlgorithm extends Algorithm { public void setCurrentGraph(graph.Graph graph) { this.currentGraph = graph; } - } diff --git a/OurApplication/OurApplication.java b/OurApplication/OurApplication.java index 78749e8..fbf771d 100644 --- a/OurApplication/OurApplication.java +++ b/OurApplication/OurApplication.java @@ -52,11 +52,12 @@ public class OurApplication { LogElementList logList=new LogElementList(); OurParameterArea parameterArea = new OurParameterArea(); + OurMethodButtons methodButtons = new OurMethodButtons(); OurDrawArea drawArea = new OurDrawArea(logList,"GraphVisualization"); OurTextArea textArea = new OurTextArea(logList); - OurAlgorithm algorithm = new OurAlgorithm(parameterArea); + OurAlgorithm algorithm = new OurAlgorithm(parameterArea, methodButtons); OurLegendArea legendArea = new OurLegendArea(); - HybridWindow applet = new HybridWindow(drawArea, textArea, parameterArea, algorithm, logList, legendArea); + OurHybridWindow applet = new OurHybridWindow(drawArea, textArea, parameterArea, algorithm, logList, legendArea, methodButtons); diff --git a/OurApplication/OurHybridWindow.java b/OurApplication/OurHybridWindow.java index caee326..2e76b6d 100644 --- a/OurApplication/OurHybridWindow.java +++ b/OurApplication/OurHybridWindow.java @@ -1,7 +1,19 @@ package OurApplication; +import logging.Algorithm; +import logging.LogElement; import logging.LogElementList; -import visualisation.HybridWindow; +import visualisation.*; +import visualisation.TextArea; + +import javax.swing.*; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; /** * This class provides an example for using visualization.HybridWindow. @@ -13,7 +25,36 @@ import visualisation.HybridWindow; * DHBW Stuttgart/Campus Horb AI2008
*
*/ -public class OurHybridWindow extends HybridWindow{ +public class OurHybridWindow extends HybridWindow{ + + protected METHODBUTTONS methodButtons; + protected StartListener startListener; + /** Action listener for stop button. */ + protected StopListener stopListener; + /** Action listener for previous button. */ + protected PrevListener prevListener; + /** Action listener for next button. */ + protected NextListener nextListener; + /** Action listener for first button. */ + protected FirstListener firstListener; + /** Action listener for last button. */ + protected LastListener lastListener; + /** Item listener for auto button. */ + protected AutoButtonListener autoButtonListener; + /** Change listener for auto slider. */ + protected AutoSliderListener autoSliderListener; + /** Item listener for forward button. */ + protected AutoForwardListener autoForwardListener; + /** Item listener for backward button. */ + protected AutoBackwardListener autoBackwardListener; + /** Item listener for pause button. */ + protected PauseButtonListener pauseButtonListener; /** * Overwritten standard constructor. @@ -23,11 +64,245 @@ public class OurHybridWindow extends HybridWindow{ */ public OurHybridWindow() { super(); - logList = new LogElementList(); - parameterArea = new OurParameterArea(); - drawArea = new OurDrawArea(logList,"visualization"); - textArea = new OurTextArea(logList); - legendArea = new OurLegendArea(); - algorithm = new OurAlgorithm((OurParameterArea) parameterArea); + } + public OurHybridWindow(DRAW drawArea, TEXT textArea, PARAM parameterArea, ALGORITHM algorithm, LogElementListlogList, LEGEND legendArea, METHODBUTTONS methodButtons) { + super(drawArea, textArea, parameterArea, algorithm, logList, legendArea); + this.methodButtons = methodButtons; + } + public void init(){ + startButton=new JButton("start"); + stopButton=new JButton("stop"); + nextButton=new JButton("next"); + prevButton=new JButton("prev"); + lastButton=new JButton("last"); + firstButton=new JButton("first"); + autoButton=new JToggleButton("automatc"); + autoSlider=new JSlider(1,100,1); + autoForwardButton=new JRadioButton("forward"); + autoBackwardButton=new JRadioButton("backward"); + pauseButton=new JButton("pause"); + + ButtonGroup autoDirection=new ButtonGroup(); + autoDirection.add(autoForwardButton); + autoDirection.add(autoBackwardButton); + autoForwardButton.setSelected(true); + + JPanel panelStartStopControls=new JPanel(); + panelStartStopControls.setLayout(new GridLayout(4,1,5,5)); + panelStartStopControls.add(startButton); + panelStartStopControls.add(stopButton); + panelStartStopControls.add(pauseButton); + panelStartStopControls.add(methodButtons); + panelStartStopControls.setBorder(BorderFactory.createTitledBorder("Start / Stop")); + + JPanel panelStepwiseExecutionControls=new JPanel(); + panelStepwiseExecutionControls.setLayout(new GridLayout(4,1,5,5)); + panelStepwiseExecutionControls.add(firstButton); + panelStepwiseExecutionControls.add(nextButton); + panelStepwiseExecutionControls.add(prevButton); + panelStepwiseExecutionControls.add(lastButton); + panelStepwiseExecutionControls.setBorder(BorderFactory.createTitledBorder("Stepwise execution")); + + JPanel panelAutomaticExecutionControls=new JPanel(); + panelAutomaticExecutionControls.setLayout(new GridLayout(5,1,5,5)); + panelAutomaticExecutionControls.add(autoButton); + panelAutomaticExecutionControls.add(autoSlider); + panelAutomaticExecutionControls.add(autoForwardButton); + panelAutomaticExecutionControls.add(autoBackwardButton); + panelAutomaticExecutionControls.setBorder(BorderFactory.createTitledBorder("Automatic execution")); + + JPanel buttonLine=new JPanel(); + buttonLine.setLayout(new GridLayout(3,1,5,5)); + buttonLine.setBorder(BorderFactory.createEmptyBorder(5,5,5,5)); + buttonLine.add(panelStartStopControls); + buttonLine.add(panelStepwiseExecutionControls); + buttonLine.add(panelAutomaticExecutionControls); + + JLabel headline=new JLabel(algorithm.getTitle()); + headline.setBorder(BorderFactory.createEmptyBorder(5,5,5,5)); + headline.setFont(new Font("SansSerif",Font.PLAIN,20)); + + JScrollPane parameterAreaScrollPane = parameterArea.getScrollPane(); + JScrollPane legendAreaScrollPane = legendArea.getScrollPane(); + + parameterAreaScrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); + legendAreaScrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); + + JSplitPane hybridWindowSplitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT,parameterAreaScrollPane, legendAreaScrollPane); + hybridWindowSplitPane.setOneTouchExpandable(true); + hybridWindowSplitPane.setResizeWeight(0.465); + tabbedPane.insertTab(drawArea.getDrawAreaName(),null, drawArea.getScrollPane(),drawArea.getDrawAreaName(),0); + tabbedPane.setSelectedIndex(0); + + setLayout(new BorderLayout(10,10)); + + add(headline,BorderLayout.NORTH); + add(hybridWindowSplitPane,BorderLayout.WEST); + add(tabbedPane,BorderLayout.CENTER); + add(textArea.getScrollPane(),BorderLayout.SOUTH); + add(buttonLine,BorderLayout.EAST); + + setState(PARAMETERSTATE); + + startListener= new StartListener(); + stopListener=new StopListener(); + prevListener=new PrevListener(); + nextListener=new NextListener(); + firstListener=new FirstListener(); + lastListener=new LastListener(); + autoButtonListener=new AutoButtonListener(); + autoSliderListener=new AutoSliderListener(); + autoForwardListener=new AutoForwardListener(); + autoBackwardListener=new AutoBackwardListener(); + pauseButtonListener=new PauseButtonListener(); + + startButton.addActionListener(startListener); + stopButton.addActionListener(stopListener); + prevButton.addActionListener(prevListener); + nextButton.addActionListener(nextListener); + firstButton.addActionListener(firstListener); + lastButton.addActionListener(lastListener); + autoButton.addItemListener(autoButtonListener); + autoSlider.addChangeListener(autoSliderListener); + autoForwardButton.addItemListener(autoForwardListener); + autoBackwardButton.addItemListener(autoBackwardListener); + pauseButton.addActionListener(pauseButtonListener); + + autoTimer=new Timer(1,nextListener); + } + + class StartListener implements ActionListener{ + public void actionPerformed(ActionEvent event){ + Component[]bComponents=methodButtons.getComponents(); + setState(RUNSTATE); + for(Component c:bComponents){ + c.setEnabled(false); + } + logList=algorithm.run(); + drawArea.setLogList(logList); + textArea.setLogList(logList); + } + } + + class StopListener implements ActionListener{ + public void actionPerformed(ActionEvent event){ + Component[]bComponents=methodButtons.getComponents(); + setState(PARAMETERSTATE); + for(Component c:bComponents){ + c.setEnabled(true); + } + logList.clear(); + drawArea.clear(); + textArea.clear(); + } + } + + class PrevListener implements ActionListener{ + public void actionPerformed(ActionEvent event){ + if(logList.isInitialized()){ + if(logList.get()==logList.firstElement()){ + autoButton.setSelected(false); + } + else{ + logList.prev(); + drawArea.drawStep(); + textArea.printStep(); + } + } + else{ + logList.prev(); + drawArea.drawStep(); + textArea.printStep(); + } + } + } + + class NextListener implements ActionListener{ + public void actionPerformed(ActionEvent event){ + if(logList.isInitialized()){ + if(logList.get()==logList.lastElement()){ + autoButton.setSelected(false); + } + else{ + logList.next(); + drawArea.drawStep(); + textArea.printStep(); + } + } + else{ + logList.next(); + drawArea.drawStep(); + textArea.printStep(); + } + } + } + + class FirstListener implements ActionListener{ + public void actionPerformed(ActionEvent event){ + logList.first(); + drawArea.drawStep(); + textArea.printStep(); + } + } + + class LastListener implements ActionListener{ + public void actionPerformed(ActionEvent event){ + logList.last(); + drawArea.drawStep(); + textArea.printStep(); + } + } + + class AutoButtonListener implements ItemListener { + public void itemStateChanged(ItemEvent event){ + if(event.getStateChange()==ItemEvent.SELECTED){ + setState(AUTOSTATE); + autoTimer.setDelay(10000/((int)Math.pow(autoSlider.getValue(),2))); + autoTimer.start(); + }else{ + setState(RUNSTATE); + autoTimer.stop(); + } + } + } + + class AutoSliderListener implements ChangeListener { + public void stateChanged(ChangeEvent event){ + if(autoTimer.isRunning()){ + autoTimer.stop(); + autoTimer.setInitialDelay(10000/((int)Math.pow(autoSlider.getValue(),2))); + autoTimer.setDelay(10000/((int)Math.pow(autoSlider.getValue(),2))); + autoTimer.start(); + autoTimer.setInitialDelay(1); + } + } + } + + class AutoForwardListener implements ItemListener{ + public void itemStateChanged(ItemEvent event){ + if(event.getStateChange()==ItemEvent.SELECTED){ + autoTimer.removeActionListener(prevListener); + autoTimer.addActionListener(nextListener); + } + } + } + + class AutoBackwardListener implements ItemListener{ + public void itemStateChanged(ItemEvent event){ + if(event.getStateChange()==ItemEvent.SELECTED){ + autoTimer.removeActionListener(nextListener); + autoTimer.addActionListener(prevListener); + } + } + } + + class PauseButtonListener implements ActionListener{ + public void actionPerformed(ActionEvent event){ + if(autoButton.isSelected()){ + setState(RUNSTATE); + autoTimer.stop(); + autoButton.setSelected(false); + } + } } } diff --git a/OurApplication/OurMethodButtons.java b/OurApplication/OurMethodButtons.java new file mode 100644 index 0000000..b834787 --- /dev/null +++ b/OurApplication/OurMethodButtons.java @@ -0,0 +1,73 @@ +package OurApplication; + +import visualisation.ParameterArea; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +/** + * This class provides an example for using visualization.ParameterArea. + * @see ParameterArea + * @author MSch�fer + * DHBW Stuttgart/Campus Horb AI2008
+ *
+ */ +public class OurMethodButtons extends ParameterArea{ + + private static final long serialVersionUID = 1L; + + protected JRadioButton button1; + protected JRadioButton button2; + private boolean isDjikstra; + + + /** TextField containing maximum sum up value. */ + protected JTextField maxValue; + + /** + * Standard constructor. + * Creates SumUpMethodArea with an empty JTextField. + */ + public OurMethodButtons() { + super(); + + isDjikstra = true; // Standardmäßig Djikstra + + // Layout-Manager setzen, um die Buttons vertikal anzuordnen + setLayout(new GridLayout(1, 2, 5, 5)); // 1 Zeile, 2 Spalten, 5 Pixel Abstand + + // Buttons erstellen + button1 = new JRadioButton("Djikstra", true); + button2 = new JRadioButton("A-Stern"); + + // ButtonGroup erstellen und Buttons hinzufügen, um die gegenseitige Ausschließung zu gewährleisten + ButtonGroup group = new ButtonGroup(); + group.add(button1); + group.add(button2); + + // ActionListener hinzufügen + button1.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + isDjikstra = true; + } + }); + + button2.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + isDjikstra = false; + } + }); + + // Buttons zum Panel hinzufügen + this.add(button1); + this.add(button2); + } + + public boolean getSelectedMethod() { + return isDjikstra; + } +} diff --git a/out/production/ProjektGraph/OurApplication/OurAlgorithm.class b/out/production/ProjektGraph/OurApplication/OurAlgorithm.class index 9b8dbabd4ed8603e2b2371ccbbe76c893d1e1fff..f21e85eb562ccc6f427d23bc3fcc7e7bd8acab9f 100644 GIT binary patch delta 1351 zcmah}+jA3D82_EkX1Cp*)ZQqK#hNq)l5I;YEp2H~EH^1O&=RCl5nYnCDNU1@Zn0j2 zf{N%k#^VbQ`s$1`&R7Sw49qyZIq>2GPrmsd*k>Qq@9fr&I?OPeJ(utMefQtyO568a zjr)Jz{t3W1KC2m*S$*yEzI~xZ+sT)52bLYDR9s?+PM%n`3qYYbXw?^33+Iml2JHi}~qf=~S1KJZDU3gMt*v?p#q3MEk(Mm2m^M&L|tC%Y- z8i*iJPd<7$wqu9*nnfGpNa!#*deJBDvC)QINa}csV*tAaSGr>n3~}tiFoRySSDcBW z!=T0|5)%e?VU%Mp#>BJ|iS1)(nX6dkd@^lS7VO+_yRbv(3MEs&`*N$>b;F$PBnQ5FvTE}sY6PRLX6{||Cs04Z%P9me@6vqoVU0dHW@Sk=t zG|$;i#xB@d$IkgGhCnm$39M@txjMRiMa; zg5f-oOhK03CN$GINU|U_T61(8q@78rxdyiCL2X(Mf`eG3q7$#tiTfbTAx}5yV4ha# zAcFusK*;QE(brIK_T2evC`HyZ) z{Si<1yEqtDX}OK(02j}b0e3Nd9nI3TU+QLNzD48a?WGyt=eZv!Db*{|q=td$Uxy?W zup1p!4AHX((-ks+U1-zv-c)q za{2+U9Dn);DaS)zwlXH6Hs__`4UbwfADpWsu3{{|jK0qy_* delta 924 zcmZWnOHUI~6#nkabY_@dBB?+rAe0saro{>rK?Fs`M-dPZLGVQtL=XyUL3|`l)HSBw zjWOd%knOdtPt+PYbQDzc)SuIEqJE>j|^6 ztI_PQ7Peb#sYT+OC*QK*LlH+Y{9>Fn>H&^Yl!+{>4ewznm`yGxV@v6ox!6!LHMuZv zp&V)+@)6{yLP-2%Ro-gU7}(2Ei#lN_ZC)D@15u6!>=QjoC|r*H9F1sVFj7-1=|n2c zpw%Vn6Bca5Ia+W)JX3QeECxi4)Jl7wKJ|kYXz@W2W zdLhVm>9}p-4(=LAOYSA{%J{)n#G+|y4;U&0GyP)AFvKU*mtjz3(O@`F9aS&_jcgBe zlB48lCe28D>~*lWxsVGaEeZt!6kLiivbY1El3pbUX3^m9ouln(nAND2dL$x~#kD^vVaA$t{5V m(4C|7j1al|%`6e!B22*?=1H4`EYe9~nQj(Y_i!H%5%>c@rjBI* diff --git a/out/production/ProjektGraph/OurApplication/OurApplication.class b/out/production/ProjektGraph/OurApplication/OurApplication.class index cdf059b81d8083cd3b2e1087bc7a9e7a074f5297..dce61fe768d9c0b1644841c0b54b97499cd61c03 100644 GIT binary patch delta 1011 zcmZXR%X3q86vscmXo5&Xq3b zmpiw91ctb_>fBV1ub)_~43*0Z!Aw33O2w@L4;I4t(rjii3`@nT!$zVBwkX!>mH65X zHro^(Bb9u4eln;o<`;sc=0}Ik^tr^?uK!Yf>PfvNvOcwgr%Y&<;z4~!d9mKf1in5O zNvHbRZ8C$3Vf{s9gAVOAop-4wwx}6StjEaonq5tb0y>O}$%uWTx+0uDO z2HR&k4=ZkHFRJx;w7bbWqF192^o%Kz|LCq39J1^;#Sa_rpvxg9^zYF}>@3f@JkMc$ zzqKiK6j3teGEGh&u*Rpeyx{U8afMaR&zv!gCtO}?27+P`nn2#=lnKPDVZI`fEVC{J zURETkh465&RFK?bV`IIOCO7XAa9aOiby^FGZha!w{oSLnL#n;)?7vT;=+P>%rtPjh z>2my*N}IU$6Svi$P46E2C$rK2RQ_uBo;*WDj*nOoKwRuuLEGh3^2RpSQLD{#QLNJ} zPGiwSNwC{0qRcCTl2oX+8mQj{wMp!@KAId{uCvLHH`tu>td6a9p70Y5b_l4m)3+P+ z=e(E~uQT8$8|=x|dB%4d4CTCpXG3F*mX*VY{?~0hDh&sZ1yf53o%pe~~ mgOmvD<0C$n3tSQMv{1BYuL^C8>=Pkt)qg7WN`9Cl>%RfsCe@Ju delta 892 zcmZ8fSx*yD7(LTYJ4+`9Xhfz#Q=&1&fGjG@AP5x7A})Xw3T}l~8Nn9X0#cQNiW@F5 zH}ay1_+WfgqG^py^hIBM(m$a70)K+>yR9$!a_7!D-#zF1&b`YePm9$rzu$iV(1wSb z>RUl@F}LK}Eu&IEQCBQDGwCAU^(qKcifJzU0WG`WDmSVA1fQ$W< zU8;&2?C1Oema@2odbVM4YjtSkkRf1~hdq~^?1yEGT<(`}P(UeLk)3QxQEF8*!7AYp zNzLai<2lQ!?#1z#85%Ytq3D8&7PN7(b^(vsq?OsYP6yjAZY%Q%Q2sU>53BH^n-}in zyIu{4(Z`0wU9uNPH5|inwjx$I1~4e$goYvb**mc}>cxnL0PF(9nc&0}cN^1iG6$Fu zGr@t=8qRRQ7Ec6Ygm@9uFpdcUQaqd(G?QWCJUu<-e$It8oWpqmDsj}DIX+Fa=o#g0 zn{Q@q5rH|SOhIYizcaJ%(x-y2|AT4yBU@KI&PiD4#y~4s!A|Q1_Dw0SpCU}nac+nx z!!-SC#Dc0WB0^sUQOxjqK==%qSRli8sLd%|EUL(0uVK%kCZLNM>@%b+>H@kgg9by+ zqA8F;v!P_s6433sq}y~^7j-3rRzuCg8z}0`pv!RR4tp9sx+9Gvx|&A+Fy9XI?I>SP z>5f9HyU;R{##!AVrV-kt7OaqX?|y7$ztpmn4-M!?BL#0DOwS^TR;<;0zSM(7t$EZ&6>>5gIUB#O~xz4k)UY{@Dg*Fr({a-3=6nKhSj)*MN$^YX9<^a zg);Kd$*WijQKbEJZ7D26q9(?$f@>rf#sIG428EbJGc|OR!d^u!3EhSRcgWIB!g;g1 VWR|yBBa3|fJ*pRQpXw}l@CUNqwch{$ diff --git a/out/production/ProjektGraph/OurApplication/OurHybridWindow.class b/out/production/ProjektGraph/OurApplication/OurHybridWindow.class index f1c6e2e77ff04f3609f4ce79f1242c96cae57e09..5020c0a7ec99f7362325fa30951520015d14dadc 100644 GIT binary patch literal 14650 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 Lx7c>DeH-{+)Itri literal 1095 zcmZ`&ZEw<06n-w?3bhl2xlP8)#-{S(hR*jfH&JK&(5T54=00Aa>8>d)DP>cCjQ_#J zhC~zNXMdFObOjuirOD|z_uTV5&pG$r-+#XU1W?Cw86kuvL=;@Y3`6=v^!nToJ?;q0 ztiJx#v_<<+m~HEnVP;#H!r5U67fTHZQHFWL(sg0#Rn^k>46UP?jw*VN3<=>FE<=$p ztKbUa47s;`yWZ^@qUA$VIEgM1mRHQMs7{BiNw~_84+6d8Ht%STX4h?v%Sia-a|*6u zo?*6oKFyF-C!3t8CXPiKLy+U8%}+h}DAEKuMEHExi;M+iya8qz){7U3S3mF*UNtyP zYu~YHXth$qn^9iDGFBL(?ID9VfJucTZW6aTRosF0(eZmP;D)EkNy7ydzlRz0Hsb4n@^;&20P36@Thg1$S_lK{m!YlKfvo|LO?(9%&6i*A3mWg>&4I zv55y>PY)T^ifVA@