From 4be259b76bea6c59fb1b2d4e1b39eb63564af100 Mon Sep 17 00:00:00 2001 From: Douglas Gillespie <50671166+douggillespie@users.noreply.github.com> Date: Wed, 29 Mar 2023 20:57:54 +0100 Subject: [PATCH] GUI Play Experimenting with GUI components --- .../output/xml/PamguardXMLWriter.java | 14 +- .../RawDataUnavailableException.java | 2 +- .../dataSelector/DataSelector.java | 56 +++- src/tethys/TethysControl.java | 19 +- src/tethys/TethysTimeFuncs.java | 4 + src/tethys/dbxml/DBXMLConnect.java | 185 ++++++++---- src/tethys/dbxml/DBXMLQueries.java | 43 ++- src/tethys/images/Tethys-200.png | Bin 0 -> 100644 bytes src/tethys/niluswraps/PDeployment.java | 4 + src/tethys/niluswraps/PGranularityType.java | 58 ++++ src/tethys/output/StreamExportParams.java | 14 + src/tethys/output/TethysExporter.java | 1 - .../swing/DatablockDetectionsPanel.java | 89 ++++++ src/tethys/swing/DatablockSynchPanel.java | 48 ++++ src/tethys/swing/DeploymentExportPanel.java | 268 ++++++++++++++++++ src/tethys/swing/DeploymentTableObserver.java | 7 + src/tethys/swing/DeploymentsPanel.java | 31 +- src/tethys/swing/DetectionsExportPanel.java | 64 +++++ src/tethys/swing/Images.java | 24 ++ src/tethys/swing/NewProjectDialog.java | 2 +- .../swing/PAMGuardDeploymentsTable.java | 70 ++++- .../swing/ProjectDeploymentsDialog.java | 57 ++++ src/tethys/swing/StreamTableObserver.java | 9 + src/tethys/swing/TethysConnectionPanel.java | 13 + src/tethys/swing/TethysImagePanel.java | 50 ++++ src/tethys/swing/TethysMainPanel.java | 22 +- src/tethys/swing/export/DescriptionCard.java | 30 ++ .../swing/export/DescriptionTypePanel.java | 104 +++++++ .../swing/export/DetectionsExportWizard.java | 146 ++++++++++ src/tethys/swing/export/ExportWizardCard.java | 43 +++ src/tethys/swing/export/GranularityCard.java | 144 ++++++++++ 31 files changed, 1522 insertions(+), 99 deletions(-) create mode 100644 src/tethys/images/Tethys-200.png create mode 100644 src/tethys/niluswraps/PGranularityType.java create mode 100644 src/tethys/swing/DatablockDetectionsPanel.java create mode 100644 src/tethys/swing/DeploymentExportPanel.java create mode 100644 src/tethys/swing/DeploymentTableObserver.java create mode 100644 src/tethys/swing/DetectionsExportPanel.java create mode 100644 src/tethys/swing/Images.java create mode 100644 src/tethys/swing/ProjectDeploymentsDialog.java create mode 100644 src/tethys/swing/StreamTableObserver.java create mode 100644 src/tethys/swing/TethysImagePanel.java create mode 100644 src/tethys/swing/export/DescriptionCard.java create mode 100644 src/tethys/swing/export/DescriptionTypePanel.java create mode 100644 src/tethys/swing/export/DetectionsExportWizard.java create mode 100644 src/tethys/swing/export/ExportWizardCard.java create mode 100644 src/tethys/swing/export/GranularityCard.java diff --git a/src/PamController/settings/output/xml/PamguardXMLWriter.java b/src/PamController/settings/output/xml/PamguardXMLWriter.java index b943f2d6..ec656589 100644 --- a/src/PamController/settings/output/xml/PamguardXMLWriter.java +++ b/src/PamController/settings/output/xml/PamguardXMLWriter.java @@ -520,6 +520,14 @@ public class PamguardXMLWriter implements PamSettings { private Element writeSettings(Document doc, PamSettings pamSettings, ArrayList objectHierarchy) { return writeSettings(doc, pamSettings, pamSettings.getSettingsReference(), objectHierarchy); } + + public Document writeOneObject(Object data) { + Document doc = XMLUtils.createBlankDoc(); + Element el = doc.createElement("Settings"); + Element newel = writeObjectData(doc, el, data, new ArrayList()); + doc.appendChild(newel); + return doc; + } /** * Write settings using an object of choice instead of the standard one from PamSettings. @@ -567,8 +575,10 @@ public class PamguardXMLWriter implements PamSettings { if (parameterSet == null) { return null; } - - objectHierarchy.add(data); + + if (objectHierarchy != null) { + objectHierarchy.add(data); + } for (PamParameterData pamParam:parameterSet.getParameterCollection()) { try { Object paramData = pamParam.getData(); diff --git a/src/PamguardMVC/RawDataUnavailableException.java b/src/PamguardMVC/RawDataUnavailableException.java index 581f981d..37e4275a 100644 --- a/src/PamguardMVC/RawDataUnavailableException.java +++ b/src/PamguardMVC/RawDataUnavailableException.java @@ -61,7 +61,7 @@ public class RawDataUnavailableException extends Exception { return String.format("Samples %d length %d requested from %s have not yet arrived", startSample, duration, rawDataBlock.getDataName()); case INVALID_CHANNEL_LIST: - return String.format("Samples %d length %d requested from %s do not contain the reqeusted channels %s", + return String.format("Samples %d length %d requested from %s do not contain the reqeusted channels", startSample, duration, rawDataBlock.getDataName()); case NEGATIVE_DURATION: return String.format("Negative data duration request for %d samples" , duration); diff --git a/src/PamguardMVC/dataSelector/DataSelector.java b/src/PamguardMVC/dataSelector/DataSelector.java index 0503479f..a91712b5 100644 --- a/src/PamguardMVC/dataSelector/DataSelector.java +++ b/src/PamguardMVC/dataSelector/DataSelector.java @@ -9,7 +9,10 @@ import javax.swing.ImageIcon; import javax.swing.JButton; import javax.swing.JMenuItem; +import org.w3c.dom.Document; + import PamController.PamController; +import PamController.settings.output.xml.PamguardXMLWriter; import PamView.dialog.PamDialogPanel; import PamView.dialog.SettingsButton; import PamguardMVC.PamDataBlock; @@ -39,7 +42,7 @@ public abstract class DataSelector { private String selectorTitle; private boolean allowScores; - + /** * Create a data selector for a DataBlock. If allowScores is * true, then the selector MAY (but may not) offer a more complicated @@ -104,18 +107,8 @@ public abstract class DataSelector { if (parentFrame == null) { parentFrame = PamController.getMainFrame(); } - Window localWin = parentFrame; - DataSelectorChangeListener localChangeListener = changeListener; JMenuItem menuItem = new JMenuItem("Data selection ..."); - menuItem.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - boolean ok = showSelectDialog(localWin); - if (ok && changeListener != null) { - changeListener.selectorChange(DataSelector.this); - } - } - }); + menuItem.addActionListener(new ShowSettingsButton(parentFrame, changeListener)); return menuItem; } @@ -129,6 +122,24 @@ public abstract class DataSelector { return ok; } + /** + * Get descriptive text about the data selector which can be + * added to dialogs and other information panels. + * @return descriptive text. Default is a xml dump of params. + */ + public String getDescription() { + if (getParams() == null) { + return null; + } + PamguardXMLWriter xmlWriter = PamguardXMLWriter.getXMLWriter(); + Document doc = xmlWriter.writeOneObject(getParams()); + if (doc != null) { + String str = xmlWriter.getAsString(doc, true); + return str; + } + return null; + } + /** * Score a PAMDataUnit. this is used in preference * to a boolean select function so that the user can add different @@ -228,25 +239,40 @@ public abstract class DataSelector { * @param parentWindow */ public JButton getDialogButton(Window parentWindow) { + return getDialogButton(parentWindow, null); + } + /** + * Create a settings type button that can be inserted into a + * larger dialog. + * @param parentWindow + */ + + public JButton getDialogButton(Window parentWindow, DataSelectorChangeListener changeListener) { JButton button = new SettingsButton(); - button.addActionListener(new ShowSettingsButton(parentWindow)); + button.addActionListener(new ShowSettingsButton(parentWindow, changeListener)); button.setToolTipText("Data selection options for " + getSelectorTitle()); return button; } private class ShowSettingsButton implements ActionListener { private Window parentWindow; + private DataSelectorChangeListener changeListener; /** * @param parentWindow + * @param changeListener */ - public ShowSettingsButton(Window parentWindow) { + public ShowSettingsButton(Window parentWindow, DataSelectorChangeListener changeListener) { super(); this.parentWindow = parentWindow; + this.changeListener = changeListener; } @Override public void actionPerformed(ActionEvent e) { - showSelectDialog(parentWindow); + boolean ok = showSelectDialog(parentWindow); + if (ok && changeListener != null) { + changeListener.selectorChange(DataSelector.this); + } } } diff --git a/src/tethys/TethysControl.java b/src/tethys/TethysControl.java index b5ef662d..7fe79466 100644 --- a/src/tethys/TethysControl.java +++ b/src/tethys/TethysControl.java @@ -38,6 +38,7 @@ import tethys.output.DatablockSynchInfo; import tethys.output.TethysExportParams; import tethys.output.TethysExporter; import tethys.output.swing.TethysExportDialog; +import tethys.swing.ProjectDeploymentsDialog; import tethys.swing.TethysTabPanel; /** @@ -75,7 +76,7 @@ public class TethysControl extends PamControlledUnit implements PamSettings, Tet super(unitType, unitName); stateObservers = new ArrayList(); dbxmlConnect = new DBXMLConnect(this); - dbxmlQueries = new DBXMLQueries(this); + dbxmlQueries = new DBXMLQueries(this, dbxmlConnect); deploymentHandler = new DeploymentHandler(this); serverCheckTimer = new Timer(10000, new ActionListener() { @Override @@ -126,9 +127,21 @@ public class TethysControl extends PamControlledUnit implements PamSettings, Tet } }); tethysMenu.add(openClient); + JMenuItem showDeps = new JMenuItem("Show project deployments"); + showDeps.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + showProjectDeploymentsDialog(); + } + }); + tethysMenu.add(showDeps); return tethysMenu; } + public void showProjectDeploymentsDialog() { + ProjectDeploymentsDialog.showDialog(getGuiFrame(), this); + } + public ArrayList getExportableDataBlocks() { ArrayList sets = new ArrayList<>(); ArrayList allDataBlocks = PamController.getInstance().getDataBlocks(); @@ -182,7 +195,7 @@ public class TethysControl extends PamControlledUnit implements PamSettings, Tet /** * open client in the default web browser */ - protected void openTethysClient() { + public void openTethysClient() { String urlString = tethysExportParams.getFullServerName() + "/Client"; System.out.println("Opening url " + urlString); URL url = null; @@ -340,7 +353,7 @@ public class TethysControl extends PamControlledUnit implements PamSettings, Tet private void initializationStuff() { deploymentHandler.createPamguardOverview(); serverCheckTimer.start(); - updateState(new TethysState(StateType.NEWPAMGUARDSELECTION)); + sendStateUpdate(new TethysState(StateType.NEWPAMGUARDSELECTION)); } /** diff --git a/src/tethys/TethysTimeFuncs.java b/src/tethys/TethysTimeFuncs.java index 922ebd1f..569f6f3d 100644 --- a/src/tethys/TethysTimeFuncs.java +++ b/src/tethys/TethysTimeFuncs.java @@ -14,6 +14,8 @@ import javax.xml.datatype.XMLGregorianCalendar; import PamUtils.PamCalendar; public class TethysTimeFuncs { + + private static TimeZone timeZone = TimeZone.getTimeZone("UTC"); /* * Copied from http://www.java2s.com/Code/Java/Development-Class/ConvertsagiventimeinmillisecondsintoaXMLGregorianCalendarobject.htm @@ -21,6 +23,7 @@ public class TethysTimeFuncs { public static XMLGregorianCalendar xmlGregCalFromMillis(long millis) { try { final GregorianCalendar calendar = new GregorianCalendar(); + calendar.setTimeZone(timeZone); calendar.setTimeInMillis(millis); return DatatypeFactory.newInstance().newXMLGregorianCalendar( calendar); @@ -41,6 +44,7 @@ public class TethysTimeFuncs { return null; } GregorianCalendar gc2 = xmlGregorian.toGregorianCalendar(); + gc2.setTimeZone(timeZone); return gc2.getTimeInMillis(); } diff --git a/src/tethys/dbxml/DBXMLConnect.java b/src/tethys/dbxml/DBXMLConnect.java index 55884926..f1347d99 100644 --- a/src/tethys/dbxml/DBXMLConnect.java +++ b/src/tethys/dbxml/DBXMLConnect.java @@ -33,6 +33,12 @@ public class DBXMLConnect { private TethysControl tethysControl; private File tempDirectory; + + private JerseyClient jerseyClient; + + private Queries queries; + + private String currentSiteURL; public DBXMLConnect(TethysControl tethysControl) { this.tethysControl = tethysControl; @@ -41,20 +47,97 @@ public class DBXMLConnect { } + /** + * Check the jersey client and the queries. Need to recreate + * if the url has changed. + * @return + */ + private boolean checkClient() { + if (jerseyClient == null || queries == null || currentSiteURL == null) { + return false; + } + TethysExportParams params = tethysControl.getTethysExportParams(); + if (currentSiteURL.equalsIgnoreCase(params.getFullServerName()) == false) { + return false; + } + return true; + } /** - * take list of nilus objects loaded with PamGuard data and post them to the Tethys database - * all objects must be of the same nilus object - * TethysExportParams obj used from UI inputs + * Get the client. The client will only be recreated if the url changes + * @return Jersy client + */ + public synchronized JerseyClient getJerseyClient() { + if (checkClient() == false) { + openConnections(); + } + return jerseyClient; + } + + /** + * Get the Queries object. This will only be recreated if the client changes. + * @return + */ + public synchronized Queries getTethysQueries() { + if (checkClient() == false) { + openConnections(); + } + return queries; + } + + /** + * Update a document within Tethys. We're assuming that a + * document with the same name in the same collection already + * exists. If it doesn't / has a different name, then use + * the removedocument function + * @param nilusDocument + * @return + */ + public String updateDocument(Object nilusDocument) { + deleteDocument(nilusDocument); + return postToTethys(nilusDocument); + } + + /** + * Delete a nilus document from the database. The only field which + * needs to be populated here is the Id. The code also uses the object + * class to identify the correct collection. + * @param nilusDocument + * @return + */ + public boolean deleteDocument(Object nilusDocument) { + + Class objClass = nilusDocument.getClass(); + String collection = getTethysCollection(objClass.getName()); + String docId = getDocumentId(nilusDocument); + String result = null; + try { + result = jerseyClient.removeDocument(collection, docId ); + /** + * Return from a sucessful delete is something like + * + deployment = getTethysControl().getDeploymentHandler().createDeploymentDocument(freeId++, recordPeriod); + + ['ECoastNARW0'] + + */ + } + catch (Exception e) { + System.out.printf("Error deleting %s %s: %s\n", collection, docId, e.getMessage()); + } + return result == null; + } + + /** + * take a nilus object loaded with PamGuard data and post it to the Tethys database * - * @param pamGuardObjs all nilus objects loaded with PamGuard data + * @param pamGuardObjs a nilus object loaded with PamGuard data * @return error string, null string means there are no errors */ public String postToTethys(Object nilusObject) { Class objClass = nilusObject.getClass(); String collection = getTethysCollection(objClass.getName()); - PamDataBlock defaultPamBlock = null; TethysExportParams params = new TethysExportParams(); String fileError = null; String tempName = getTempFileName(nilusObject); @@ -95,63 +178,57 @@ public class DBXMLConnect { File tempDir = new File(javaTmpDirs); if (tempDir.exists() == false) { - if (tempDir.mkdirs()) { - tempDirectory = tempDir; - }; + tempDir.mkdirs(); } + if (tempDir.exists()) { + tempDirectory = tempDir; + }; if (tempDirectory == null) { tempDirectory = new File(System.getProperty("java.io.tmpdir")); } } - /** - * needs to be based on the document id, but the getter for this can vary by type, so time - * to start casting ! + * Get a document Id string. All Document objects should have a getId() function + * however they do not have a type hierarchy, so it can't be accessed directly. + * instead go via the class.getDeclaredMethod function and it should be possible to find + * it. * @param nilusObject - * @return + * @return document Id for any type of document, or null if the document doesn't have a getID function */ - private String getTempFileName(Object nilusObject) { - /** - * While all nilus objects should have a getId function, they have no - * common root, so try to get the function via the class declared methods. - */ - String tempName = "PamguardTethys"; + private String getDocumentId(Object nilusObject) { + String tempName = null; Class nilusClass = nilusObject.getClass(); + Method getId; try { - Method getId = nilusClass.getDeclaredMethod("getId", null); + getId = nilusClass.getDeclaredMethod("getId", null); Object[] inputs = new Object[0]; Object res = getId.invoke(nilusObject, inputs); if (res instanceof String) { tempName = (String) res; return tempName; } - } catch (NoSuchMethodException e) { - // TODO Auto-generated catch block + } catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { e.printStackTrace(); - } catch (SecurityException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } catch (IllegalAccessException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } catch (IllegalArgumentException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } catch (InvocationTargetException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - if (nilusObject instanceof nilus.Deployment) { - tempName = ((Deployment) nilusObject).getId(); - } - else if (nilusObject instanceof nilus.Detections) { - tempName = ((nilus.Detections) nilusObject).getId(); } return tempName; } + /** + * needs to be based on the document id, + * @param nilusObject + * @return + */ + private String getTempFileName(Object nilusObject) { + + String docId = getDocumentId(nilusObject); + if (docId == null || docId.length() == 0) { + docId = "PamguardTethys"; + } + return docId; + } + /** * get Tethys collection name from nilus collection objects @@ -190,16 +267,8 @@ public class DBXMLConnect { */ public boolean deleteDeployment(String deploymentId) { ArrayList detDocNames = tethysControl.getDbxmlQueries().getDetectionsDocsIds(deploymentId); - JerseyClient jerseyClient = null; + JerseyClient jerseyClient = getJerseyClient(); Queries queries = null; - try { - jerseyClient = new JerseyClient(tethysControl.getTethysExportParams().getFullServerName()); - queries = new Queries(jerseyClient); - } - catch (Exception e) { - e.printStackTrace(); - return false; - } String result; // for (int i = 0; i < detDocNames.size(); i++) { // try { @@ -225,13 +294,19 @@ public class DBXMLConnect { } - public boolean openDatabase() { - - return true; + public synchronized boolean openConnections() { + TethysExportParams params = tethysControl.getTethysExportParams(); + currentSiteURL = params.getFullServerName(); + jerseyClient = new JerseyClient(currentSiteURL); + queries = new Queries(jerseyClient); + ServerStatus state = pingServer(); + return state.ok; } - public void closeDatabase() { - + public synchronized void closeConnections() { + jerseyClient = null; + queries = null; + currentSiteURL = null; } /** @@ -239,10 +314,10 @@ public class DBXMLConnect { * @return Server state ? */ public ServerStatus pingServer() { - JerseyClient jerseyClient = new JerseyClient(tethysControl.getTethysExportParams().getFullServerName()); + boolean ok = false; try { - ok = jerseyClient.ping(); + ok = getJerseyClient().ping(); } catch (Exception ex) { return new ServerStatus(false, ex); diff --git a/src/tethys/dbxml/DBXMLQueries.java b/src/tethys/dbxml/DBXMLQueries.java index 6eb81359..76b236a0 100644 --- a/src/tethys/dbxml/DBXMLQueries.java +++ b/src/tethys/dbxml/DBXMLQueries.java @@ -36,10 +36,12 @@ import tethys.output.TethysExportParams; public class DBXMLQueries { private TethysControl tethysControl; - - public DBXMLQueries(TethysControl tethysControl) { + private DBXMLConnect dbXMLConnect; + + public DBXMLQueries(TethysControl tethysControl, DBXMLConnect dbXMLConnect) { super(); this.tethysControl = tethysControl; + this.dbXMLConnect = dbXMLConnect; } /** @@ -64,7 +66,8 @@ public class DBXMLQueries { TethysExportParams params = tethysControl.getTethysExportParams(); try { - JerseyClient jerseyClient = new JerseyClient(params.getFullServerName()); + JerseyClient jerseyClient = dbxmlConnect.getJerseyClient(); +// String url = jerseyClient.getURL(); Queries queries = new Queries(jerseyClient); @@ -210,6 +213,9 @@ public class DBXMLQueries { } public int countData(PamDataBlock dataBlock, String deploymentId) { + /** + * first query for Detections documents associated with this deployment and datablock. + */ String queryNoDepl = "{\"species\":{\"query\":{\"op\":\"lib:abbrev2tsn\",\"optype\":\"function\",\"operands\":[\"%s\",\"SIO.SWAL.v1\"]},\"return\":{\"op\":\"lib:tsn2abbrev\",\"optype\":\"function\",\"operands\":[\"%s\",\"SIO.SWAL.v1\"]}},\"return\":[\"Detections/Id\"],\"select\":[{\"op\":\"=\",\"operands\":[\"Detections/Description/Method\",\"LongDataName\"],\"optype\":\"binary\"}],\"enclose\":1}"; String queryWithDepl = "{\"species\":{\"query\":{\"op\":\"lib:abbrev2tsn\",\"optype\":\"function\",\"operands\":[\"%s\",\"SIO.SWAL.v1\"]},\"return\":{\"op\":\"lib:tsn2abbrev\",\"optype\":\"function\",\"operands\":[\"%s\",\"SIO.SWAL.v1\"]}},\"return\":[\"Detections/Id\"],\"select\":[{\"op\":\"=\",\"operands\":[\"Detections/Description/Method\",\"LongDataName\"],\"optype\":\"binary\"},{\"op\":\"=\",\"operands\":[\"Detections/DataSource/DeploymentId\",\"TheDeploymentId\"],\"optype\":\"binary\"}],\"enclose\":1}"; String query; @@ -235,11 +241,40 @@ public class DBXMLQueries { Node aNode = returns.item(i); String docName = aNode.getTextContent(); // System.out.println(aNode.getTextContent()); - count += countDetecionsData(docName); + int count2 = countDetections2(docName); + count += count2; //countDetecionsData(docName); + } return count; } + private int countDetections2(String docName) { + TethysExportParams params = tethysControl.getTethysExportParams(); + String queryBase = "count(collection(\"Detections\")/Detections[Id=\"ReplaceDocumentId\"]/OnEffort/Detection)"; + String query = queryBase.replace("ReplaceDocumentId", docName); + + String result = null; + try { + Queries queries = dbXMLConnect.getTethysQueries(); + result = queries.QueryTethys(query); +// System.out.println(result); + } + catch (Exception e) { + System.out.println("Error executing " + query); +// e.printStackTrace(); + return -1; + } + int count = 0; + try { + count = Integer.valueOf(result); + } + catch (NumberFormatException e) { + System.out.println("Unable to interpret count data " + result); + return 0; + } + return count; + } + /** * Count the data in a detections document. * @param detectionDocId diff --git a/src/tethys/images/Tethys-200.png b/src/tethys/images/Tethys-200.png new file mode 100644 index 0000000000000000000000000000000000000000..19e3c48fc825cbfb723b51f983c21a978946c8d9 GIT binary patch literal 100644 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%0Asr9zLHk<$Oqbdf)nwk8ky@(=x^?f zmC!>DN2jz}cn%8RHNr5?ts@T_>*6p?82vf9v*APJrBnDiz_Sad|Fp@X3KQ0Ltg*4R zbr+=mKBnlUlPRYMOSU(J^N*gPOL}~_U7TH634e}2>?w%$%I#+OmYJxcUp1jV2leUj zAf&})L=Rxr%sU?07=67$kS$KuHksH36PnQifRo@?kJ(aE>#3RvF}5=9LT)k28D zYrMw$eJ$nt6X2U|2yTszx=qD$*39Tp{T`RGY;v~9a0!gfFb zkgQgeTpn)_mFg$g`Zg;^pAO^SA@y-?-Az|lppHpUy{2gU;>5V)hL2&=j1&qXcR~l< z?#d32w_onQSM>nB5qss#g;mgP3Qn_>>zL9X zbjqqSA_^NVQHv)wJFZ(8c|e@{IfuaeIEk)i1rP@>c7$9m_Vi&3AlE`%=n zJ?b+d8CNETiu=mb>-I}JI@(+ABx%fXL{R;#suZZ?uVgH?nFMz2nmqQf{lY#u?9>ft zyF7T#(w977j6aHg((KJk#CHHdS04Zc z!s0THW59wZN{drm_{ZUIjMl)*?UKU%iN^hloqIpy7L9`z z$ID+0Zg}BHwZDUuICDSp_2+IclWABxCmI&WOQ! zDPXj}P381Pz7zta_Fhiu#NWsCo_L;lcert-Lv`Ju5lGi31&qba`C&wC0Q1G)t^SwB z(_iJTI&M#ICQKhi^xdAZ-h^Ab=G^OI6~hJ@l@Y=TucVH8!b7gL&BlU3L~Lr+YE3bP z*5<~i{XXh6vHuVzTo46x8Fu5EIvYQntrqj^ijk)JBu&tk-1x-^4Fd2nCP%KN&eb-C z%IEfImClscI3U?KM`pY-uC?{@%A?v`9vE2-@T~XI+D~H>EoFV-T0%KO~z&yEI=2*CP!PXZ3^3;#U zk@Kgwr7hVPpUag6GPi_SNHkzNlI-Z4mD`r{#W~iGLnrpXFEeP`v4Uz=inPn?gQ@Js zPN^8do)Jj_EYBaL?UDB_;PdHNxn6powEu5${Uk{sH6x7KyU-Ir)4y4^%| z%lz|Qhq-00n4=H9ie5^C;pI+a-dgQBp*GLUZfF3H=;*{3{B-lxkP7P-&e;>6KiQxj z?)zYU(33u{$CRXW*|K;m_CzOZrBc#WApT*v9bn={k5yrg$|!gi+*-axqN%18Fn^?> zSx_Www%d>dG1yBWw{)U_zDNav->*YK6YN@Fg`UX!d%gF9??U2v=z`}0{{6|gI>aY6 z?mlK)`f71&SL>D?STXfeLNQior7`qs7sI;9rT(|B{r&A@jriL$x%2B?_kkK5$1qwf zqcDHR&6S@ap7zh@zdxBz=t(ZjEjf1dlaY137sjyhAHe5$i(ZKjPaLcz#bs z=XiWfA%=D_Dw_VFA}NsHQWt#9DWWyxpSqshqiox<(}L^UF5Tc(^kixy$0G_mkzB`< zFA|fs0zdZD48UP5iuBfBO-%Q~RYXS^96Pad*x+1yyTvM2IjmDRWP(#Ls?85Vj>w7e z0Q{QTd3eVq`RfIw?P_x-91jNLw@;=-?rHbambZE{c?Eq7Z4N&EZL$+l+S1jXW4M{l zx>%Lh{<_aoOfFqxT-Qi|q5Rt6G@4+GC$_ewkTK19=Vxft`x^3+zO+5F-(wHyM-_;R z$!PF7-sr);6dY5|;;%63Cm=o;!?j;gz=SxBOx=21+cG8b=hqCSEvcTe;|_RUam*Ti zeZ|4zExT1~NQ=~V`}t^I&ys-O`>k%6blrhK9&}59g}N%B`}6ibkBM zB0?-XQe;4iK%k;0){P>P$2_Wu(YHgYc>;(#K~j6c`-rA62yD7cF62^oJWuBR*?yOV zUqG;gR$0b5Jjt>4WiNcNKrc~yzSq9!N}f^^=vH1B3HxK)(lm}6A#$mglisNnEpL%o z^VYwfZ@EJ}sp$L#79*N7X+*?F%5GR|%<{%Qx?vbkPsT9?e^UCTfo10;VaiB*sQHPl z6UrT-q}-&B6For+4gIQkZ8yi05eHX*_|DS-?C95HXx;MfcEhqB3^ZZ|sWQMi=NlWQ z^Tr5-?<F zW#4l3nJO_|5Nr&--ilrY&-U>?t$n?1&itu%^+N**2tu2ITAe&m z{5tjP$NO0B%i)f5mt-zK)=)O?=Ig14rBYu;K6lQzbwmw3l=;2bA+AxwtxvO=hb5dBG_JS8p zH|{Afg*0kIbpA+Ca*vh@3!7wf1f=z$Xk9oRw$M>Xsb5@C(loJDEbpbKW~ z;EP8tUvc!1LTw*w1X0>MFKvBKqU$CRR<0J_ePAOxwd&318la?Cd!x7Ps0GnT3s7^0a@wJw=v<%o4g*)A; z9Puf~u9*Iv+FCjtQg7v@C26G$08mhnh&&n7=}*b*pojC_63F9Oi?6*}&8})A&s%KM zT!GO3O!RCpS1ky-#V5rF#F{Wa)_jXH@(Gsi9F&}32>1g-{m_sIy6`_eJSOz^-HAcc z4Z-EM%%sGZ-%Z5(YE2V=?Ve3a-Gy#Z`JndWx3+#!DoK=8o95)ya!VbhL3P1L6WQ=T zZ~2DJEAm*@xEM$W5{w|#t?-@8ao%tujV=2r<|?;JTH1&9IAQ9aRKX%g*J~bpTtYna z&s@y-K?(*ldAYfgZf$-oSQp|I2b`MU_Uy^GIkLNXGNG4o%OT80!>jXHzm}a{{QPBl zm6h1BtfuA)Z}0xb0nw`>lmqIqv``piE)^=n_R-^Akcf`9+t`E0G#vhp?-M}JIH3>n zEX~adbDm)sFt3nc-2@7QnIx>y`}>a>$mQ>xP!M6BIChq zU1FvNo!Y910MKvMd4O)+7MJ-U0&d*?hpw5^lwpFWthKb7MVcresY0Q%FbrZpLEUAt z_=*~Izq*Eu7|Tu!c*tkeHpVu@1C%`ldFYT^5D|R+PO^C?di5P|XKm`UM)BODO!5kX ztVX^bODO600fl^Ky*ym994|IM7S-Bk9tTH*w?Bo4(YhTAstWm-C~<(4 z!Avno5;93^&WB*8A0AAN(tj4-0GfW7p~pOW$2a)GfVM#%!6e~C2T^MbUruw>9W2XlB~y0fkJRSiDS}!?21xr>4Z}`Q~BSfPb33(JW>(dWNB+z*}r2 z3X5rh#|kcwTef}2iONaoO{=!_cw8cGM?;Sny@RQRC;-=oxTMkiS7+V zTxh`UN|KzkwDj-AVCSS!xvS;9o886RoeP_LVHeADayK~En9b(0%m5PegQ+`V!iC`I2Jui34 zJyM2K-wp+cZ-3e)k`I|&5kwXWvzQK)biK$r2dg;ca?+f-*FRaW9pF~yF_@+u`vcG9 zTkCg1OgJ}XMODkP)bctolYr6Hvq+R(e{v^4LOUGOMM0b_zTjN=3?#V5EZ@ma6@D=0 zyu)J?@PK3}DY~pQ5k$mvca;*@&Z`LlAu`-;ypsqx3@#^UbYmFzR=yWyPgr;LW_h5z zma@kmB4|ujmuGi8QY0$-JG574-PAPBH1myi+O8>hbP5s(XYJ5qM9n|qht zLqLMgK$drKg?bOjoj>J7H4oSUY`O3ngRsN?=ph=~?=~@zXQu?^7m5kh? zo2+J}gK1zpFE?AqO|6vy4Zs_-K0YRpXS##q#ZVfJCQHSH3B+x0EPLS|QLqEMqUR;8 za!f=j^H`#~_|i4^{%sk%3Gi0}6pW(fZt#sCfyI|VUec~PI{KYjsZ5nlngAJbAO27lSF+6v^B~)qeui1L&(JylACdej(T;ob6u+I zj6LZUqKG9Cqq&gd(51t?3=i9{rEYya|P9RnF9Qs&q_etne zhE?Jg4>ztYZdC-Y=fP&#WaRFJPG(~A63r<{V_w%YY&j4`E8^i9lGYcSA{=L{X1l|< zwh>LRx1KZ-c3b|ayH^yZk~}r*EbdLhSuok}To6#U4GNQifRUCHX8`7oo`vDwP| zsSYJZlkJ1=)V&#J>;Szz*}mq0F0+?39KSg%O zR1UqKsl!2G)$yilXeKTvh2DUQX0EKU_KJsFpWqEbt7gMJ9*<1686U$UOycRCow(^x zA5Dtvs;IEXqIKzxjt)$aBXQ&OaKe};%CBddnkt*3YdIWlQEi5Kl|?(mza_v)SflI!cmB@c{jWE`O^m?MiD2O z$tjc9<;}ZRZ2^~utH!WzNvv`d$xuLEt{B?h!@TYq!nJWcHMO~YbUsX2p&~w(jjO%i z?b~LVzPhoodJhiJ^%#mQBG|o~_PZX`0%y^1vri7e?NPVws9J;#sC2uy8pd;nh6_UXOk15^37NPf^we&h9%$K%wx*7l z(g<`3p9u?tYqnCGrqT6FByHIxKqZ->P3 zg%_NIshH!Qce2#rkh3#ap{EqFVc5Ne>u++~=I-Xo_U$zb3Lxt2oGg@n^ILMeksbV8 z0WVvZT=3OWcpi%JQWd1b&GwsasA2{b@OBwD|LA7%CjGXJJI#39l2^yLf1@v`OJZ5k zS}VSQaN^H@p>XUA%Iy6nIZ0r3#L|UD9uBpi*DhKtE=U$Wa9meU_Q%Xs=A=K~51TkU z-eQR9=8k0;CUxWmW;j$=k0!~5%$yYda7CB6GBGMB%{+E$mF6MEx-3%SCQe;^DkixV z-1~L9UPNpq#^^srl+Zx9zD)@7XwNF*-|Fdl$Oa9qP!}R-=}qFRjUPqrIB}S11Do8HD6-#XS~qH;Fvzu07fMXD^edZxhCbM%KaiR$ZIPobPFUa%zkApTbEBRu+ z#0zrsto>pY{FT(vqrP|()KgY;uBwEFjQTTVt*1@h&Bpp(*@_UYEpry;k}w7)=r^Z} zGBUEqZK`4Zj;o>yj@f00ve18dEV7Op+vo9fHCn4bsUscO`p_T3%7Yn*b5SP?w%e&} zJt)TVQh9ugD$p=Eona%$5R9k^5|fe>nSQqO(xLXhk-d%}#uhREyy|yNCb>D4L(=`A zv0-64rzt%UX_ zd=5L50!yu~pH*3N+wIlSZck6M6Bnr7tN*75q%CsJn$NL{M+R2Bac~5^!-w})h8fMIG#=i7RExfPQTu*00ln%A+26pSxWe+l#iczWTMgx~rR0jW&R|KBBDiy=LL26G zXB|3USchG-_kf4=5>^N|AHd(PNLYHPK=f6G1J>?SQM_$HTt-ZRznEO`$seD&dNA!< z=9L56>UWpB9<^B1Xu67_aeN;IJ7F0BWzW%CA7KF?eo@)uV9V;ZnKy-3+Yx^bSGR|% zzPUV;NVG#HzrEm-`lm;wlA`9wtP7=KLX2x_q%A2e@vhn*{)?-vjHou%anJbAiA7R$a?TB zTQQpEU%twK4dusJ$jA?3=#%<>$`96#_EbozcMWXXZPd{#VxuC(^ed7e^>YHKJU)TNKX)I4Q2zz5_%!R?|p+RHWC7;Zadf@dIrfc}s6v017U(XLk>~f#0 zgh6BfRZG4YimHByrGj~OEG*rghhEEBwg%RkBt2Hw%yMR{rv>Vsz+yn~=Yys0+1Upo^0(UIpq#48a0C(UD;x@T~Mg8i$+ zq?5j-OiM9Z?HNV?m+x}dXLerFI)#Hnf3|~YRF0zMu3s2NR_E`vc>HViUFZfBMN$F( z%SlxJ%d9BMsVC_a&6qn`1Y@4{l^AcM7=zhOtq#Vr^oy?cZuR)=_NQHqmF)0bE$; zRpIAT3!FJR@1C7h0v{LH#IY`q@F|Az9xuRAfOquvdio76Uyh&z4-;UCB;rAn-e#RS zjP{XKF_K`p+fVV59Qsc5P6jZ*cgR6Y*$sdZz{5zeJFZBuK)|ZQ44pHY?%4H>R}(;) zC)+MQlr=bYxia`mU1<27ydUdcZhO#cN}WQ+IlbdZ;pSAkHYr+w?_~lrb}4caCZAhG zQSy_h7yfiuG~o}oZFJeav1d~{+K0>d^rmf*j{kcBDnB9mwk~x+-`cZ_P^W%*y2h9S zWaM2A+R1>spPz#y!@hj7*o!3D5rjrifb8a|3uk3rE9$$ltw(-(i`p-cZ^=v)rWG1B zY-Kgbh-!~lRnc@h(Mx?fg6jjYt|&XdiZa000TH{`2KAT6uGR3SZ$T0QUWJzeNz_>O zV=}(+%Ei{}O@DLU;0V4HBhoO%&k&+`K8G-nb8!i?NqK#46b(wfRc(;yU#&`M0+y1> z!0*<-RnoLNgVB+EJ~vOmFM9s9&HQlX&X-zBgJcF5T#;S@XHgM8HfliyjZ#qs^g=0v zza%L9kEXN!Yr_5d@PGkB5k?53Qy7RaLKxjCtsvdq-R0Ov5Jm_Sk?sy@r5mY%AT3=| z(jfip`@^$;V6XkK`#$$M=Y3t#TXQ1@`3?HD&rlTo^_Pw1I!73Mra#99O?PPOxxjh(Rx+RtaC$b3s2=kqp2b zt*rVtgB9KX0T#3$Ocy<%jmq~Eb}$X5Y`yFZ7)tf;!v8v_X)4XDf3aH+Xy1QYLjoA* zmosZ?4GEdo^Cbx^r+Fw1B z5cs7?FK_iPOy7TsoeK2Wi&~S10e6o=zY3hn7!i4(?&ASK%bfOm1J-Y%XVE)a` z`s&W{DW6@Er%5ziw57Emm!kl5uIoy~2V!SpuOzdKJEF=){df<;kk{K9vE+r!`8np*fOu>HsoirSb|dJV(^_bf0q~Ct zYy!!i_OUalBO4VM^m~A-hSt`T6*Q52hNCUVUkecg2@!nX!Ln*4>ca$5U!NTV&#H&B?kY&Si0fsZOS8ac;(MSTJn<^WL+fL2#>{pYn2 z%tyf0c1M)(5|{OcmUJjK3-t8aRRKGDXW;1=R#Yf5^R_iw?LEmluS_JYD(zs`$FaT( z7Jz$dsIK^(GtmNNdGupb@t*IViuHPRQfv5BFUd}eN!tI0aIbKJhK1jf_0`Vi)n-^r zR;8V)SWh&q^{Td^@j7;Cc4{^~ea{}W&@R1YDd%KTkEQwggBQW#@@c!TG-PF|SoYy)$I{ldss>R6uyS-)~baQ7*L_KwF>DokPh%A5g>)biZrc+b5)k{7C56)+P_`_vHBGwwp$w4#7So z-o%m_@YUBSBVW@gwFHt}CK@i8#On?gwzn+b6n;C| z$OtgvM^ck(#~~2eX>@q;nbU((W?2s4?Z6woEwA7omAo=_}W3Xa=xP zoN8&D`*r8k{%>oKdeXo)HF$)B)J3ESSAIJsHo3e!eRPYiVYY>{(+-Zl=Y%^LR2xPYn5=zY^!F zw$Ucn%p&*l^=>eD(Qu;pT_p*w+Gm9&VPVGjs%R3*%kaU9h?xOw*Sdg{j)!Ahj1Wub z4_=XcG$Gy#EaU-dwdS*chvEd0f-4ot>jlaY$1si1Nh(9M9ocqXHhV;(XDYQ~#z^7* zrz{7wK$Zo`Jszjs_kOZoMhjFJmW+;DF;*~ zqz(H$8T;l=MLN_@3{$rIDom<0hpwL7H$7a0TM>uepOw0aBY)p_qugj-)cIFH_&FJbf_!v7XLUX8RnjF)xQ3=|4HHDvkH_?FkDs0a6A{g_^ z)pWtfcS=DA8`aL-`k=FQanX0x=SV5&ytr50Zb$6=vf_{_e#-N%o}GkaNcFOj^b>h}0PaY1r`1ObU{tO-c0a2( zFexj`R2zfvU(_C}_3pQ9c;Ferx`xkZm38dvLc(sl_>o`$7-WmNYMgUn zoY6{1w-;&p{C4JaYIn!;b^mdgF`*!>)({2k#z(#}(>L{V&&pK^nA*|Ec8qr+U+*pbYYtR+0=3B$Rj}rLN04t zPY|GPSNyh-2|)b%^^=1{+wbfEM*#o(2%w;y&foes?FrDIPPrzE(35m)+o}suck`SS(_J%xp*C?{)Tk*UfVtnq*VS-b3P3?u>^b=1bf7xjJ78 z<|Zer4l}df=oa-^5%Ci;7SuP*CHS*E^630has&TF*{KnIE9;-^@KYok{i zmqs+l3f|oGtOmGPWx)9Bpja)EE#aJNlg~$cqRAwKYpq+ zyy3n=&twC-zV*dvv%(0P|eqq4fX(?J!kCkUi20dA0=w|Mr` zjNGcfW~~8+7(2!Y_Vnyb(*nbZC!s0!cfatrC$VJxu#n64QYYsFuRt+X>kzOfF%iQj z#}>04X3p(MxAedJHnRM3%-Z{rnaxF3AX`tXxR3H<_-)OBRLqJB4zcuGr>EX2y{xfh z&qSzSaV?D6F=?YWU;X)cnx0ccfK6|c(V2B zSxa+SOR>El0Rom!WB!B5z_@+LEivGu!Y18Z7Hy>%{8&2up8-`-Rq|*yQ zF1uAPH8ahyjl~vicv7Wxqa-5ddOSX*^a`&ve9z=l}CVL)SnN>6c6=wHaBJ zutzro%7v61zv%pDUHIQmJJ3rUF+b-(TdTFbZ2WAbKyMBC00M#q-+>+8ld;)%oot+){Sr;zc1-F;6LAMfWy@lurGN8i zX%Utp1nu@CC$U9YvDO67Yqe?&rYM$T{e<{ryB31hp-39(F@&8iQ=A6j?iUani5z@KpcmRvfI{MG2*T**HVkyImMUPVJoCAyUe?IWV+EJiJen0bIb zhQt{?06N!vxZLc51#$&N@r)4s%SyDV(>js#4g=lHz~mdOAQgW?#jE=rzi>h-vP_?H zmHWxpE%zGECD0NsJjqX^=*Tf^V?Tbipr+jAPV zSg`b9f&CvG7k+8@{+LX%Dr-9)C+dP0va=_ow?$DA*rQ{uMbg>R%jh!QZNr;QI1rK* zA_KAs7Rk@ZBm({z2tw7?Wgs~}XmJ?;T}x)+TP>!-UsTvKMdqD8MsKbeie*m4g_u-p zY3Zx7)-yi+b&hV2 z1sdW~lic`vBVnCRZ$l$U$O#Z4ns09+@d_BkDIHRtk`-&1+S}5KHZJQKN_|+{*}9($ zZ5zx}KW~`M`q+zi*vbhc!>#m3=Ya|*R#{dI*;^T9Jh%7NaD07r_s%S6GE6j-UiwY~mq+uB~O^&P;dZZ*G zzsC%eWk06JSD}H~$xQS_P}PZcJ3y{gz1Bj$wO@TRFw-#k5vyW|M}~s%Q}XjpNbI#> zd_u!3K9^HC+R`d-R?yE+L+6ABibTcixvXLTWCmf3nS#1QtQxH|Bm#@)ZEi%=N{046 zUpz`}GPWoK4)NAJ0)@Y~1#jq_UAYOqSgS_?wtej#iA9NYX%V=@N~N9FIM|hqM8H7R z^CIucdcBi7K55sP;AiO@JEGg)oo+_2ix!zGjxl@C(eh@Th>Or0zVO?(i>mQ|{F=l? zzwG?Hzv;MD1%-u$c?E^h0KzUO`DUZM1XSyA+1Ryv0}@1ehd{~1%;BfUk~n!~7pOHW z-D@I2*pIL}gQ_1P!m$cj#iD@sH7l;+68r8|?$C9OwwCW<2AL*SA`X?=tpPPAl^|>B z+ke*lFVObv{P4=8R0cn_f6MEiD~cyQ)Xy!5=yUZXDYd=uc{oq z`nqJ%PTwE}piQV&>{paV`boF(De1$J|8mHwE4}9-dUqhVlwS^qnHviLNJ^U8DJ2AS zTV%YB;ttS0Af=4jGARFGEo3>zBW_4g$i!5|Pb?jJxy`Dj{8D{LHEYXtQFDlh>+^u? z%L`W~hGxH!HHb26f&wcQ2moT?K(KNv6nxrH5I`zFBkF=bHz6%=uLHBFc|D;r$W z)<@4Z(rkLhv#K!Ij~slRHSqL$!QwhWWTt`MaKW(BcNweuoRgK=U>yRz2UwF+Y$~Bj zKCRD+sM5-6u*hV@81%}0txze{TQXGWauIzw52MVHZ#iG|;%5OREFN8a&MpC`@4`@$ zELn=gmh=(6*n}!uSH|WKdE%1Dh%l$FKBe-cfXJF*H8uO|K3Ia3WTA0cCD@?u1;3(r^P$I-y5FqmM=f}N_=s7K0wY-uN=+diGze0XOx6AFDwN* z^II&<`oXU)GM{wZo~>%n41`+OXY){-ivL~|O24adEMyL8m#}8V2fI#_-Z(9j8fj0w z5#L)ZCe7xDEm_}A?JfT;=Z;xp1v%OLh>V1nz{R0O*Q8G*)Iy2AlkK_o;T zr>oD&7rq}n=gh_?yStvd$Q0EhOL{j;=RDfCqo>1DH2Fm(wQ<+RHy$>8Is&iEO!4wi zDy_1P7S?!KuS`F_YT$cN;@cU41jB4qGw`F{*C;PF>lkl?1*no`uPt86V~qDg0pRi) zd9aeF(ie~EFS(~(0&6Lg-NuCU%+bJY(1irKL2tss?)|FgpZVC+SEY;R+c!=#%nAv< zEzJ_X0Ewz5-3wCx8BMO2Kd_2kCv$9tF0UtgaJe9_cQ9la7UZY-70Pi{x2>i1_W9oV zFrRr=w)s}_&fG5h+F;n*Omov91=OkkOm;Hzwff$!$KCO|kG@HUdE6cIr|yTn@T=vA z6TSzp8WVOhI@{RNaFgZxqdP65>pmNdB{L{nD$q<_4Rq^Pm#zNTm2giZqmU$m{X^No zx@FyWiIxI%`_=BKPa`t1J>=L{-v)$Z?V7eJ6%nc@8@&#%nSY~qx4Acisw;E4-*Uen z5`Xp00?kmqNX=)a`{@2(LU=X7C~Pl^1yB+v*zXe>%Wp-d6${icXD_4|FC2*e*vEd^ zNhcW8i8?hLAtzu{*DKcK#T1=BQ}Efpwxow!)~v|SRLvwvXuKWEvZi`w__N7c^ow6J z)3tuWbZ~-IS=>fyP(Bgy5c|GqQz?vQu|U@_uSzuEO@ygs>dz)cw=%Q z!G5ediN{%Zs*aj(9a=LT!!9W<_@&Gvz`fU+D>14&|%`i%jUE0BUQ}3+oqFAMOd$?iU3D za6myL;9f2n$m$9LZ~Oy~NGEBTYV1Dg|K_7ocdQzME4S+hiwVnj;{7X49S`#2(Ei?o zMN{+3G2U#Vq05AX&(!uysebf)*-~G|?3P-#`OKcy^|`g+Eb&plicY*#>g6hwd;av9 zD!}JYv(T0&nm#@MaS~V^gw>4pU2$u^Mt%jm`1<{2af(;&XZfN@u@cAl>-by8{aKZB z8enDbv$+>0AIK&!r>Eheq*@pJd%$yg+O=VM$z-`bNJDF^8uCQmyH(<$r$lMI0V1c8 zI5ELSZ2@x|DOUWV1&ByLw-b25^>oV87_De#0~STGu!6d^Dd$=#-8*iu7QR~mSvR{C zB^Y?-kY52Dmv_gZ0N`4`tLvqeqrqj|@LX%d$KX2XRpV*abcTwccdUX0ri{EX{{H?P zvvAwVx*gb%=Q#D4SzQSLYOqZeyIC{;YoKRxdn}jPZvW#GO-Hu#k^&cH@>@$|M@I)R zC4M2HN~^b$0zc~rUN*%&(*FE4>CYH&Q4H_G`0Kr#)`-#-4%oScsLlA?n8LT*xZ@pjkqc z%&-?7aIsr>;#NXCLrNLZ=**|NB?iY${7ZrR@@UD3Ii%F&cIy_ zM#T@l0A?@xYgv*$A6#bjty3?tIcX_W=xeIdT^mN_rl#zhs?)!W0O?=WErx8s!@ECYY-VnC3?7kdEEBHF?Na} zMzz_q_yU35WRKwQ6@VY`Knh|6Uf8EkJ0Td z-9R-Wl=OU&kpGz9PI?(>CQQ}LOF-O*lPUTQbrrhG57yaiyT6T3TW6q=xjkVb=DdOI zaM@;e(SDLV+2)>$hzuOw4a1*43=u#I0SC5;5VYNQtSf{}0ae?$S1~E)!Ga{^eN|g@ zP&>!|oYPvwh+@8RNovXPMV*ALCwjBbr}>10cCTQ+jfM-@6)79flNZR3m-@|O%|Jbd z2p1Z^W>SzZU?m`nD$_BhkO81|P?pcdcLpRV#sis{pM7`&17;Ty$+3Je=+1|8&o>`j zwLDX; zU166&V~uUTW~0G^NG|FS&*q3|#s#OwR2WCW1R&sKtGpUGP?M7_9j1Txbx~T(dZ6cM zYtJ2*Zh|yTT0KdR>wW8j2TaR(URXdkn|JL=05Jv5(e(x?wz$>ys`CvyM4Cw zM502|^WT2NA|DQx@6A&uYM~=1?Ae&HtcJS^zy zq%ftYT@1@j&aCEbedK>woeT{;*)a5lZ#iNV*rPmMS{@zB1LT8yd85&mN@Kj$Y0avv zC+q&p1FRqNp;jgCr2XeI@|!jyB&imZGT1P_M@;F@py1yEvU}HncZVc|uS8)Sn7qWo zQBCy|u6~8`oWkTPTgYfEimjvEh8fNkGZ^AI>u&Rw+K^=JTbUn56tI}PWd9Q=M=uBS zLTmJ_^Qd`k{~nKv^qQ~DD1t&eamm?zI%Qn|w#a#lPmdF!C`q4`$M8W>;vb@aTD4AC zhrJo?L5QkS;3folI{fr0IyNBOpRSciTksJV%SUG16P0MV=41t|Ul9?k0Pt`e!RdBT z-?N15Ct|lu*BhNVCwsX|`)iz|%A^qDLh0u5x^bZiP#s<2ffQZx9A1w92sIr)u+Tm+3KI7QmN#@Kr0UY)GUF7Nq$daF0{jM zXPM%IB}w>;4SC(duY5a9l^sv^r(*MdFdhEg4P9hvVI2c28HmS3_uxSJ9ClHYLBE!Q zo}wG%mt`EFg9hYr=a@1XM=@?+|M1hk*w5400ys7_R7Td#jRXdOc!WC4SG|Zq3nT#E zfk&t)s9R^)YD;FS-mZrQlZMXH4+y-PWdDSHpS?bOoS84yH{REGHj zK?PK2jZ7K&5|hw8G9XKUwdgtyP+g`|me!i!wSd$sa;86F6-4V0OHv_3e2vOQk{}LC z5y}$vUuRA9CwvSyv4d`OIbZew&#RadkJ*mUn>z2Jox)1&W!KwTHNRvMuAg6(o+j7% zpG@a@=$OK<1TVAzvk>u%dIsCyDzh&S#+JjS%}p0Wg3MFCcw06Z23r?4sHU~uuIT|J zG#7EY^Puq9w5o^g@aw4IVrtc-yDRCiP7ps89>5BdH><2#F+llHJj2IWeHa3=|NNX0 zEByYu8u8I=Sz6-vlK%mJfcS-J)+YaY7n@w3#3+FybK!8^snB!YY?D#y$M!EM$Z~;V zuMhnUvz%TWy1UiuWYkrO{$BpAORJ;Fbm&gfV!hB1RpvF+WNPY)CHluH`TOtHW=I4c z->&WErP?I-*=U~(SDVomD`pVI*e>IcW@7ncP(V)QjFR?5(>e4Uh62IaG}3y*k6YX` z7`giGeyu~34St)2iy2pCNe0jVaBDPx=F5VN%G_FtaTIhm3W8eO#M{IOaiXI&Qv?qi zKIPL+!G$6vYz#*fdllul-s)=EQMiNqD_rMu52))L>3=p>_Sd|ydj`1wdo6edhAcE5 z)Hvc4_1SE-;s5}}@l(R1Cn`2e695b8Y2jHOzRYta=ZKGb^J30&VAY~bP85Wg>_7cM zfl*P*{<5l_0W<9Qy~s1I5QlZMf@W%V%CTPs1PY2L#(BrD%dpw*r_f8*1Cm!j=u<^} zHQ?Q!M4JndBi%{RgO=V(kWZ-35t{ z4K<7T4b0P>o@@?_V6&@~eX70o<%&k?69IBiVx{uBQ$g3wuv7RK&G4&DY^@5#HgOA2 zsg9wnAN*IY@Abty6@*Fd(yPri?S`$I|D@$+*l4`X2fvvi^__g9m)6Vc@Z#lm#gE4b zSaDwJNG)r!F8N2vU|->M>Z$wV} zw6b?^;#3~ZH4$NPgcf)L7+qRhGA)LB0JAe&MM5R&g#An5G$dMEr(ntW*{4Ro#*B?X zM$Y5aZ-i=Cj|!mzw%w=*x>VBmEJ*0;JIjwqNU!`=^!aZ6`lGg&Z=j{+)JtDV4b+n^ zCy;z-N$$(3bv#f6k$T`h%Wl8ro7L67yc8~#ahEtOe-gj&QhmQjoX~gT4FFj$`g8$G zu`Ww)QA!hf!a|k=h&KyR4Z>+MUL-{T3CQ4HUs%WaO^HB8eOac6{#70zGG$+}*3p+wW_u7JeH$j@H?a zWlMxl?ij#OdO8_ozV;`$o%LOd^ zApz=!X`53QL2KKfTG=P;>3r_h(yqcYhs)tH4na5fc#nVjd_U@XdG6UDmOK&7)AId0 zW5qZlapiwh{^!sDb0%j|$ds1GILn_P=)+%SQSNmXR*B?atowXPR(x<5=!f|r#ov`yn>Shv+r9hX-9s-;SD(*(Gllw1zz#&rzFeZ4r&-A3mH*`z%u@Us)N3wYDEm zsMo2}xn^Dh9Jy%vHIBfME5v7DgMs{ieUr~c<841WzO<5iN6L9B%FGxM0a}t|#FB#x z8ybh5fwvd;T{kkYCzuN9@UIxg^uO3{5^;C#Yr+Pp{lk7uF^vmA(NKLD%;Bc7E4m?)Au5a< zyU9%Fq4xx7{gU<&st^N%ej;ZdjjhP2lmifLZ-%7x{x%K`4)v}eRPSps4-Yxs9i193 zUi#0!qkYoJ1IK5P`BM}?7Zl%e7gi@)!NiYykju~L7aBfW%@3%ZiR!@~iKdc)S0{7S zGfYw(hNW@M0oN6&TB9Wz)w`zu1==)}B`A~as1(2wd;aPuT=g6T?Hi+rx*Y^eKML_` zV&n{MfUDOY;Gf-4yjE_n7@}#XUQmlgY$^_^@Bs;HqlEOP&U@AIe6=BofXBHDu9t`b zM67j#o3M!V{>5Hm4CjUqnhQz$jPjRgPDJ}I3mopV2X)(;lAE1n_-Y9TAg{g@1gN=^V0&2u6J zEoVAx0_w6vC%XxAg$LdAxHQ|a_NAUerRfXl=iylNFfO5V`(40=4GltFm-|!GLXiIr z1uiAT6=kD6RTk&r)}Nx=Wq|Ga?vgK7H<6~FPuUW)!2eDMW}OeL8Lfn0XL${(ePB~ z;=l^#Xll^ckYuOVcu3*3t4=WW|*O5i-Sg zn@%lKU@sJY58!ZSbRc`_kdaY8_H0l3)~;m%ojid9ckuNKY&XF);7dQ8<-cT8ERc+6 z`Byx~%VGX-alcyR*yt!=+a>-?3o~|ruA+MG8ioCCvVkJZkRj#f%#1YC-Vj}N8~>8M z&dJ%%>G}F%Z1ETwg@E4tdFuF7-&L_cA(FXpBq|=fKVQXrf*rsbS1P?I6fUOL3cG8d z(b2cnu{;9mqHlp)S zc29Qu_4O;;b6ETmV$NkJGT6kusM(?A`gD8Do|+nr%S8v6T3mFMCV?6t)=3YmGCxg) z?X^Y%3mi#uviYlqlssGb*eSCj^ zRlfbkgS5LM!)kMu0_#>X&#R9om?y$=B~C$$ zk)2O+Sc=f=00bujyWH$f_~MC1iOO0%&)e;7vaWeiTaBzulDxbOr)Sd3CXbb9@^#DM z!v#siJ#I}(C@M$nK>9Hj(@`CWz9<KITSGshm*nOT>hkQeM_D; zro;Wpnv3a#^Cq+~66i5KUvpJib1-)`mw0fh3Bv6(k_d zUUbdC!{BW)E7TB%&G^2vH%x-hd16XcaxJ4-HF4#z+;rZ!-ufTm_p1XtgRH{>Dqr7t zL4uel3EcQqH#)U6w_6T;WuZ~SWA4k<;aF7I9kFt+m<%qn8B^KC-&{Kc>w8=mElv9m zFtj2{7f*s6D7R6$*HYsgoMr2oQPL>fZvp79@?OFYV`a6S70Im0>OcZRFeNPO9s95Z zIn3>ujhSk^^A#$CK=XQDG%%^D;Ja<2|!8l@r2V z5&Xg>E0u*Xp6zFQHI>Q^{1;0<$jBmK8S2AuO)xHq8E8Q1P1;&Z;OWW#;1}9K(z&#> zL>XwAp`#lsX^ZR!nrnVm+JW*7w0ln+0kf-84svVnN-BTd~{{m7W%CNe~B`=Z)a}PvT088_iJ9BdWoV>lyAHI_VSVyS{i=X<^l}sD$9}hRY>J`u!R>h##Q%lkp~oLvD~(EJ4+# zwPw1TOu|hhI_Gqfdd`N!*H{-WExvpxY_Z>%kglT&0Yp07c|7dz4Erq`;a4@aY&zZV z@`Z`qA1@D|yuq_gb3#8+5KBLLOvy!vm+!j1YbpXW5fMQT>v$vZ?!JnxOzX(&I+7u#OnD=(5K6zk4Tq8mzlW92iyt2Q16_a zp$hRQ(jXg8oyw{l`^`wguV=#bOtU{LeosZNTsPPBSBi)OS=NbhDwMouXVggMi9OL) z@mTxB?!HhaUkocJ)I>5k=4;}-U}-6Ma?`{xE{7153>`f+5gNT-Ysn ztUk1xoZGxgzMr+&Fqa5^#H@=oENHV9_zZ9IX#ShqnY&yL9U~f=WMBRBcPlbFIbG}U zQy2CkTS~(Tl&EL8@Tie^ny5R0{oU1+?_zRD@XaxK%}dVm^$nzDYpUcG#+i~|H1+%P zeoItjzC=ejb!-d8eKAlkBC{k3aCKz`YNghs@YDAlQ&*eQ**|P%KU5lI1paC1$$iVv zLlv}6RG8dJuTl4g?_bFm{J-@X)H@0aWUC*~X{~+$`HGX-U)AQJ*P}tDH}AZJopy-c zqXM@J>U5IKJi1`&wLZbKlM!O2=qE%8Z|lnCjYXm~JwEpnk@wQzq3oeVFfg#KVOkZ1 zn~!3vbt}_Y{Gmfr${Dyt7A=Y(sO{V|pyupbJTP7G2lq#?;^7g22vvwA!>@V9?7(>! zFprq`&FwpBZV>a3E6Q;hYqMISr@tvq(mSs9Tm&kGgUNrgXG1F8q*}*PCf)CkZhG2> zVtRwMsZMvih$Mq9?`P)rZ*5d7ycb5Tvp7?KYPm04cW1YSm`Y;#)mNdSOfc)N>y;Pp zyTle6&r9_{-62wj>M<2iv{Lp`d)@U%PgyI(JMXKV0>cs$%+GKOlgyypV$1br@&xy z5e^s+iKs)9lgjE)4TMsBo_yTRq4>8o^!j#i@I;}pO%eU2NXo7L*;gEJ60*N`o2m{z znt4egCgVxjCmeu?)^lq5et2EQtxxVzMSWh z{sZUxeEJ$i)TjO=pAd(9``vk>sB0U}Kxi_Gci0*wNlYMEBq0|osB%sEm;l-V^00FDe+}1BG-&W2a^Xce8K@`CSEtN00NL8{OCka0(_1< zcH5uh=WR*bT2(RFjd?mQ@Y2*!==-xilI z9y4!7d}Ml$WBs>b6UC1NAsH>)N8H-+4<((T~h3%drfOip%t=VkyG3*nZVXXsb&jX ztO$IeOiUY;dzq@e@m+tM1_3b0;ED4STY(PUG<#2jWlew=J@1wIb97P)4O4^GnO&dAH@j2M7shar&u}e{;C+{fLO;k zc78oheD)!Es6;QuGM? zJ`@>2gyJn1I=ziGUeev9mVbbSh!=m|j_;MhEj`ka=u}5?H3+W3z z4z0)E4Pa^vb%{|cDE~h`zG0r8*IyUIu5$>cG&y47W3gBCZ2J|i1??>@bPJ7#H|Ie! zjZX@HsT`VqRT`r%Zu0jppXAiak{}#6TQ<=uK80>AxO%pWdH3HA_=m^TdP#{(>Mz>8 zO&DbfxEaHGOZ_kRB0O|5z-u_Yph%~t1JVVRuMS3HlzMH*PRG)IrFq6U8PO6yy}m#N zexQK|85=p9bVaGZ~V*X1};uiO5^C5Wm4sO{Q@vac?Gxhrl5vx{JRfcdU@-X~b z5Lq_J5j*u7HNIDEChDHY{`g&nlxXnP^>h2%pf-(KAq_$6{hrZnM}9oy?`6G~gJx)* z|DhC?Vmh-NVvD=KdwqN2^y@Fv!@|Q&RL8Z3sNp_i)ghB~`0*}X|Bg*#z(=iwsL0)^ z@t0WWoQz)_6C}3Tjve%F1>X|-Z!=_zxvS5mrH$J0{lm$gNEuVcjL4qGR21N&uIZ2` zS&hPx(5O6U(?`sdC&qCHhqoy9%4)9Odg1&I{(Euhu<@pfNvb_~&otmJT}0}ih zAitNHSdSY6uVG88E?@j2fsH3}`+1nxwy#|^{8UQglG4L5bf-DcGkMNF= z>CBV-DK@(oy=tJIUd9{jdM&Z!QcZZ@7i6qSM+`tz9ndCtJ6AT6dm>;Ip@&!Pik&3BqoFk`E z&99RGtnIv9m+B7i^;P|{Tt6Bhu_g=ohtn^hDp2W@q-0P1dEua+6nChHmG2XMDwBE< zMRwhf(+L}7;%91GF#Ghk9>2O)6Yx-mSEd7|`YrpH0{?`lHTF*_oe+BnZtH;_rAnp3 za>M7Dv9XloGO5MoikXC~*lK|YQ<=GPYQArW+kvY$?fiDagE@GX^snFdjT6_#C1C~M zA9$r1%LPPgA5PsLENdk4M+B+ZRkzPm(bQ>a-(s01xPW+1;t1xbBl^cYC< z6$Y}hCGPyQwM77VIY@4kQ#XDY;%Wm10su+|;NCW;gs4#{-Bf6KLlH^`!@!=UT#2ts zqoVQ{`i}MJ!vupOO7_>5hM)>a6re(Mppz5?R|#F29LHjm`ys%u4D;)b$#F$`hQT<7 zrqT_MM5BpL%c`1;Tg=^?n~TtIuG*{UayRy7wy=qVefS{{2V23UqPp3|BIB!GF>B=5I^*_NRLf30-|C6`u}J;&uBLP z{|^U2j1sEEjvf6{qiCqTirTf+-h1y&jM^h=Qxq+=M_ar0Ua4K9_Eu7q82|hp{2%9> zoSc*U+@JA&y{>EQ)1W&g{?y2Modkm?8-7I-uOqJWtT4D(Oo}od!m(r-nmrDEqCKPPNps;baD^d8hq@dPZ!NDQ2Q^4a9+$=vnljr@yh z`_UVn{LAH6|LKC+ZM1kMv6R`?MdoCWEe%dPxs_LFdvS@jW9+rrx9CK&5nlyH;2DPe ztFCUxznj-i1=!~0I3%rw5D1WO^6i6LDpXvU3T!QTAS@1H=#MSMLUk6J*x_-+1#TyY96|@7>{=1B{Wf zdoau2LJ18X;Ap_N5^>r?hz%I0SjWQsV?+uA2nK}l(W@GmiY!#}BqMwX=s$Z&5iu5b zi#^P37kESTQ^IueX98Pev?ePb#|AQ^P+iA?U9a%wv{xxXLPH#3kvSzEdLyD3Gf z7%X*wxxc)(Xn>hj~8m3h9xK1C{O_WRbXu56>`IB=+n5{WDDwp3X{rUQU z?&=6V|9DuLavEwNg&kXlj8`-s2VR|5)e1yHO3(?fRgT8nzWSg9V+eQ$P@g@FNDGeC zjDLPNdW?I}aM(A6oV6x~WL-PZ_~nCboAKu;NU!>3vhOzn%aR6wf{LvzuDPXJxH3Qk z5WlyPC^r46m5M<2E{M2-U9@y6;IpmvIgLDV(LeJyDmcySLF+-PwXN4m+Y1p#bU)>@1(MN9ilYjIe_vdUkHtxsP_WB~|A z&7|mVN}81PPzbnRT&YQ``>7pi1yfm?9%U4<=(2E#$!MAzfS=Tel%a3N@RfAT6CZVp zn4nVJB2Pr~&pEnH=ti72Q(rxEihpDZfQW8xnfpTS;%^N{Haxp`q5Zo-S$wcD@( zy0Wcv%l#BiFl>4@p^>}6;E~>cc8O7OEMpWU7RW%!eTCwn?x?MebI)jhJ6SmdPu9ANfom}p@#^V$QXf~byQK_^c}$VBTsjsEUGv-^y&5z&{% zZ?SRL!A1Lk0G4J_IkFEO9UWG`^2Tiw`Yj<_=jVd-9ANtj4z_HHlIHOSfzqZL6+0Jj zppRBys5HEKB*yDur#J86JnWvUv^u@gX$eZ2Nr&7E83_0B$Yob{WL#j3pS|`$JyLt~ zaM^X&F)c=1iq(f+?NiHDDs;UagR?09S61L_RQcXQK8K@_5IRy-$%shD!yUNlsSyqk z_*gn@jkMf_TPUZ41i-SrP{*p)VKh`3vY9^xf49`2(!j&_+RA0#NBiAWY2`CG=b1fm zYLcZST|e+~PsmQJAtk^?oX%Ut5s$(%4p5zR`U+r)7+YL~5zEC9k)ynY7!fi+@)E*1 zaQKObMge!nEYW}N9KnV}zSLdjMs7!^{# zqE(#IFCx0S|4G>MHqTgO^XSnyh=`rcPj>w~+89Qa)8u<1(ipZ}yCw%3YcgZ+j1H42 zLKjY}4uqPH9lr9Zzmg)28+_50wA;u!$$WYWA~5=nvWVhgKsb(Ud|T_n>{p{?FGJ=N zj!!~`)gG{KZFI$?nRX8^AmcjzeCvL5oFCZ-Uq}DDaqI`BQs(ncN(Beojeo3t`QKk} zK`W+%<==H7!DqAc1Pib{Q;QVo>-~z;3kHw&mGb!6a?bxI;ckIVzpOyYa)X*}&a-jqj7a@W@0BZ0FSH4Kl+yJy|gYOUK^9 zc^v$u1t_~W)A_`t%A>oU#yu{-*@)~tK^){P1F+9%~BW%``z^;r?GCv#a%!C*- zRxp;b7P4EhFH|7D>h{lG%#a;RivplSh;vdx0JC;{HRqLi9Be2_qNs%g%M=zwDrMlO z^Hv8)!cDPD6&;>Pxq}@kf)4P3Vipv`BqJ31tGZTiR47geI&42fMxWA91B+>?${V?g zYDCZ4i~CGq@92$EqQ|a!yuYsT@l6V_OIBnH%74Zia$sv!B*WXK!h3|Z!FG@7x4JFQ zy+TB5S|X}v)QSQ-e|N)~wV#fEps?=i1px4%3UP8N@^fjeHMVGuZvQr^twHQm*Klps z^1zrd^iDsFVxYLO#&vn$QuME!5EJ2|61{cv#bZ83jVSxeljB4F%cyLE>CqP6JN`(> zaf@GRRfSmyCV^E73!eYz(}hJ%-|b)Ug z78aYt5+?&nX9xTYV39atqTpEi7Vc3*fI-zi={V{y`K87rK*Qx; zs_%53u9F%+T3FZOd&?ulVUxqGAq-W0T~T+O`P)KJDQXJ4A)h1!7V@!&ys&WxP9APrcC_-0!cNecIY2YRJNuoW(}aBPF@9 zonY+6p%qAAg!3_$u9y|3Td3Z**m4597;PZ?tijupDlY?VJ3m7$*NCqKzkNA6LH#C9 z2ZaQe%x*VArUSve?H*S&92&B;rCv zbiGDzmu%t9?2QHR%MHpcEU5Eayj5-WD7jPzuln}BKe(hcpO`}c7vyg;&-w|(F1cH= zF`dIC`}66O0n>CuKDvdPX&2F|X#YAGG+i5Z?}Ci6psHc^+s&GMziVefnKZb`4%&o@ zZF3+->_v-;R#wHmS2W*OK>t+ZsLfieAKW&D1b;bDF23aQ7MJ8sCcW>t9)P%1ju~0He}2^NZOm=EIc6G1(*FYa!UM2 zrIlFFIKcvZhj(&~<^#)=9LgIf6st7^==xmW8*E?Ob~r30L(^%>=&1O2jt^h>eSI;A z`ux<`N%sY5>|Mm;rv%kWWkCAFkrHv&7R@{?vh?!s*tKKj^eeKY#jSmakcwq&xwTo3 z-YLIja9r#U?WSoce08n;G`Ga@KgFmsYievg6ko-tCl1fGYf)sD=;1;?>~}N{Ne)%P zbPElxh1ZzZ0jg4J&cq>Y7~NYBn;HIhGc1gdb`UO_?0|}$T%oUX>cgL}HcR}l?^=$x zm@;znTRww7t_%wH7nka?lqBhO&rkZFs%$`j)4DU;*v<~!Sm~s{tB>8Xdp}K4KysW) zwYPPIm911LY{%m*XkH1=`7d+u8=a!$pXl1IfB#F7Mmr#F9xsks?DfD( z!2EW>J@Tf_73szai3*9vvavGS2cjh5QFBid8JlE(R8OYsY$nd>Q!(>Z)Pq`W2?G>qWl8urm&uF?0uWN<-?DEgUeeDBdw*he(OC3lsk$*7!!0P+5>x+u^C1&yv z)Y}P~JANIXf_{f}!o)yO+cG(GTVSdzQ%WrRYgoU@+W3x_?B_iUESXj=)~XY39Dwr* zM2$_*zfska0+}Z<#I!z%*i{?cgcBEdMK#oR-uwD^IPj#(DvAD8qwxQUGuE--SdqE) z>-p07ge~w*b=n@`x^#L{aoCYdN z7i44lyU1@X+^sc_RYa{0Z*{Uba6dUEZ0@^P8nNi;<|829d=isf5GRn<`x$=m9UE{g zG6)F^enip8i**Lv;h$Y~fxmKZ^vg z8oX$hgO~%s{IW&>e%m?OoqE?#Wdo_&ppJ5Gza7s#(B^E8JLr-ArXl z{((d-pxn;1jBvKWNqsl^(_jfZcF6%WZx9}yB=g%IK-$XXCo{B~{AH=?(QDJR7h8X4$dfc5ry>>@p=Wq^rz zze-~-sv+#Vl7ikyf{;l(f}Ggs=it$c%Ni$D!Cch|&fR%^V49X#XIo|!mUqMfi~-^t z-iFg$?~iMQ=~2$AJ!i0P*|I?CRFPBxx0ZYbt&*6U%Kuc`gW*Y&wHy4}CC}Bl zP!15g_DZA(yHXMrq!GFkbzm7*LQkB;24qe2P{p+B9}}6ESddc4nnMWoQ+q&^xNOuA z0PEyvTg_3B6VEnN(ziFPXTPR&Wa2){$vRd%YWm66DO}@x$aAp4GWLn@+OE5(!>hEm+tIwhD|c4;PCWugaKR;J$TK2`+p@92d3V-z1wx&#zCOBWX% zh0P`kigk4}116NXmvH2w9(u8kJZ)~PW-rDcsRl=g9NzNkqeLw%C7#=^P?Okl5{-u| zAp382vQup!$A^HGN@4o`+oKJL^uL|)W$b&T(qiFMLsz#e_}Wsua8{RIF*LUy-FV%| zXBK0aUN(HQv$=w~k~W$o7qyf2>B0^un3ELsMlqN?alVdjIV#V!T^^>u|JqD*TaK1n zv$8Ee({IzQL(7P|`(!u}J$my#rH=;Z%CyW2uyl~Q<`ep4MjP)=17Tf5;j)<hWQqvMKNlc~d3_DXwL$_5n z-O1xf%{8P&_d(@EN&r<~H!CngtAolVeSin_c^B_dKmQ-7JJ_%)`&ENC@guP>^Ha1F z+=^3%FGwBt=y{i?{jHn+BYWlKy>c~DTynyz2m){kr)tL+GdarQ0o&o1xXc#z-$>kfL#e3DzvQ>9J+_XJy^gz3$xlztw}t!bXno~W>E+^EZR>H2Qw z7jn_B&sRGA@lec8XXO&R7{rb5{wJ$sdR(!2hCa;lQ z9MVuLE$!oiGX+`{i$KV8?>6`zM7=joPM)IcJDi} z6TeM(=(mn}GQ`V6a35*zbE!$U|wro>A!7-$5U`|FA;Q@Lsn9n@X=sKRQRBw|8GD0!zw8S31I8!O;Qc zq8XOie7lx$DX}ZuwF4QnXoJvCgdCLbDde4|TYQqL@h7eso}XOFD!brGoxj_K`|!XH z)nO5zd=QW0%YX|kx)&o}WMn`b!akUa=o!?V8nFLKlbu8yz>5GV(Oy#^=EN#^?+$ir zcdDvtPUkSENH6rFv#+n@-^l3S2M1!x&v}on#RdP^AtI;H6gwl8?D66!FP*<}Vhs(F zCepy_%oi`xdL6~-DOA7srjUPasJ27Tp18Mnb(j^HA$3>vf=GWjdxXMINJ!0s(O4jA zP0c*H-^4!b^)o)bxp43I%64tO(&~>Rd!Q;aLt>f?V(0fOu@#eHq4$4rS@;VkxCsZx zYaD(oo)ZDnHQQe@^iI9v*~3@n@=}7z?EF1r;?CQ>-rR9*?8Fb3Cd}HU+1y8X#6ZpS z6_kIqnCJ@s+SP6ltCi|_$UZ&Xo-KnAoM7W+(KGAkHydFvLK#bzqu5pZulbYYgQ)Y3 zcb4{iEz3>c%JsM$%lJ4vtp({=!+g_w1402+Gf- z?yg7}l@aJp|Ta0*_{ODOQ-Jr>YgYwT+oFF-M|20w-QrSyz1nRz< z2rVmFFp(Vl5+Jnu&XbO{fW1?=5=Mge%RirXTRm3r^()z^ZYz}w5T4?98KtL3F_O?u zt;%C!)dDXsmpC0wWqhKab4FYdp1_K@68J?;VW=$*JHkXNK&;T3$?hw&6!zA9$F3_f z&dDawFi@Je_8IwdHJ;K-ee%2YkFsDo*60W_xP5-q#EiF~Mv3`VT|ZLufZIYL@42c- z+wr^<#@BX=IPBUcWt{(Y`_G-!Jxe?sh`pV835pOt+21w8 zt!7aiTH3tSWb(U%wzaULwhywxE;Im4zRO92-&>w4bNO^lOZ%#YRXWM1f<67dl5Af4 zHVO|_yREuNN&uv1*o;nSn zxJfi${B#7T1h`b^^rOao!$L3QjlIMf7)my;qvw2olIf2=2dv-OG7?hwF3`PB{Tw4n zKmP4iTkD)&3MywR_v7$y?>?UVq{;IY5n`M(IC90eEpJ@U!#9Q&Y2rpy9Cz%C(e?bz zzhxm$B%AsapC=q-sZyVmI9Cp5YC7TvyM)O9R;B$9$vQ>An zATBKc(=SjDF$tUq@KEIcsbYA{U%X_v7$-Bl?@uZoBcPEnZSjb_LM}U*(Ru=R;QC+i zy}ws3-;PF6*gFeNUiEZbnRNl10_KLc~Nti65wvPWrvY(Ra|i!hVPH%#QZJn%y-Kxw$4`iP$^9OH-`P0?Zq zyS~NWb^dB*=S^%3$Q1eiEI@QGh)|1;Kp-U+E9YBXlK@nd2xX7ckbN*UDo;W^9TrsV z=ymlQNvLt4;IuKdkS_|kfBRG`izC5u~LM12GACOWJ(rqRC=kkOC2M`?& z5|r{xmOfOsQRXKgpe<{1h1->XRcaYfj{bnOXBY%SOniT#Q43Z;vGtF2GX}D8DWB6E zTi&Wxcul6{b|$=9w9CKUKYhTUCp#ep;|Z++=uP@*A#{H}%X72B;qS}h;>o*g;s1u- zLc2fUXG}A&4cs9Jl&l`h%P^!gPgNX0Q#BVKkU}2JNVgroKGz8-kDyB)C3A7IN z^$55Yq)!TvR!Pb8&3uYTHlb2g>UampMtL2g2QI_1fHO={o1pyLzY zQP6T!$ge>X)sZg zCfV%2NDf*}uzKOEOW_||2FU&30a$V8m3|oJYxdOI-TcGG;6AqEeD6U*(Ffv3w6zR? zuNYPda2ZYO79wpiN6yRoGYQA{r8n&nnN@zIEe)V~?1!R?lS^XlxBjiV{yNknk1%7BdNhN+1 z4k+|z4a-k_&!uZterQz(o*z1YZedq;E8!EXs5o6}vqcm(uKx1BT# zo@?$U54(|wxkP92LF{}&zo=tiq!5x;^~<}|qVtxj1XjLtR;dE<6c*{&mY{Fn&+y1u z{FhEyyiK_B6u;C^lXc(vgCyKSuD}Do9Rpmym`HYTitpv#W2Elyz2ABz_w!4W{Dmfd zF>S{hYBu{F@kKQT*yP=FvL@)H{^0bfwBCBF^h}ZC-ui`Iox=OO?#A8nn=`zH;^kOk z_{@Tzi{?EZ0F;|jy-`1G_QD zHU_a{YMjuqd7h&N_+JBi+_pmoECWPu{Oc{cCk4#SNlLDU1YSv=m)5ud04{c4ys*b9 z;eJix@ep!z`Hl~aI;gKE%PP-dWB6nYvY;I2bjH>QK`CpXkpPo|LvC{U8>>X^7-&kp zG~Ite0UiN1)oDwrb_uiB*S=l4D)GfH6tNI%B3QBdOU1a!Pbf~Z$d%2gr+KZPHm2h= z^=N!3qkE@LTk={Q61`mJZM908t8*J%uo;lx{cF?r2t7PtTC}?1iy}U5qL11TSzh4o z+yAN*Qa*Tf$9TwoUlSGvCWGI;$P{d?_A%6H z2v;h9!d3?CKsbONwiby3#VRula3j7wjeisRm$l0=x8&0n{}^ZK-DSNavC2R4u-nJ= z>MHMu^7DBqtW1_2SvoPBr+Mc?u#ZT5Q=MI#t?5M}vYx*uCpcDp0aP5Nuwh)jkBO$@ zAv>>VOMiIy@lRZ8Q`#M4zsKv1Zr9CdmuiLna6aBSO47CPSXos-qw z;k8?h2V4((Bo?1r`^-)`UHn)3DiIXg?sQ-vw9d}% zd8v(|Zlzyhjx|!JjG>-USBBX>m9W^!WE8eRXA(P2oyLe1o}DT8lY=V2+lz$}GXB(LREK?*djX<6`IYbb{q zR7Oj1?RyG+YnrdsgTeappxxid(I~CIQOpBz_1zV-zX1#iiH$J!39<1q23Z7vl_!q- zY-F?L)R&SaPC%x-c4YB74)}|4u5}ovVZ!|o%F*QXv93qins<&E4&v_?KbH!+u=Mf3 zVMup`ceM(ET4skGccBg1wO3Aw>t?qXW`=zSt>5pDa(u`jYy$E)jR0>GHic2;c#3zj z8c(AEh#~t=<)hbFJl5Rh#EO2!_{|w!%;ieT>4aVajadhKHi4Fo?lp5LCU5^>V{qQB zwY&!?U%H@N(L^x^r$fp$s_xQ3!!Pc7V;h_%`<~LPEr+HCYU<%g$JF3VusTab{*k&n zG<%~cz9waCn#lFs=5GZ#wu-&neYISkree=~|2KAx!$L$wJMx#aphx$B;Z}eJ6&Hdc z(cNSY@}b6IwADGcl6O>aa-RIEBnufton6jNtC$yyVJD^;4G_s0o1n=qS=nr@t%9zD zb1zo7)=C4?PW^(MJk~z99>%s5CUGX!O~|Og?Z%9FlhOtp%aW#5;#wvo)NKtN5x#m} zk(2|IyNwo_WZzKt#V-r2QNp?f>Vw&oRn2<@R?S+D`AM!)q42J6aN~kUA*i4DGGHrN z*t-n_67FRJJi>gJDkEcjXsUKV;>3W1anXrX@XuasiUN=!^tv5t5&9|V3{NVNjay+^ zD2k3>Zi22tb?uS1qY6>^PqE#^Sy_t_uq>dvm>IH-d_(v}M?yaNO+1b}08{$C|BJ(c zxYT+0b3U*N_u^w!Fb4q(DMe$rl`6<8KN=^kK@NQ6iy3wGtKVa~vnB&{LFGOX3Y+q+qch={qM`$gLFaGm_jWn#+2$t4=M^J?qU-@mh$WUDWB#yH-o30%t;kmbZ>B9kY8EQ zsVtV2o;iCAfG%>n3``JbTM7DRB#T}X8$w?WZ`-8q>wmcvH|IBOvS2@DwMuC#on0bb zfmwy_xuGkC8IO+H3vpvVdXS~pIOVm$8!Vgcy|_82{tm7gXinMm0<7nAKM z5#?Mlr{3->6kp2iI?&V^)San+b0v`a-f|OsFTCi{AO<7FgbEZM7(ljha+>Ws! z+`tN#`JZG~!<&XO@bezd&Bc8KgI)eJah0kD(#<#l4dt?+WxpiI61Hs>g2httAq%?;&R$^o^pd>D72SJ3N@Er?+~gY5LeGh6>}JM+ z1p8lkggg`<8(TaA==rI2N$DM~?E5#QDiwdw3o*fUfov{V93ka~q~ArzP7#%n2LwIT zJ-ckILtIaS>~?oYZ*^`GpUdm4F&;)r$5A{R-MB&90dPb~ zT@1ZTUUX}z&~kX>|Fdv*AR&q-XbE9!dff~0Sc_GDL(~0J8A4UvlByj;L~faab(S`g zNJlLXhM4L!J`|N*88sZKfDc>NF#o(vR-1IO5)#0Qz4zDL4PgI=7?!Iq>$l;u6godS$zF|@xxqt9Zpy3yq4E`#q@a{n!+J(>iZ5_P>*RHW|3+2U;-bN!kGy0 z-+{&TP3g=Jr{6GLe7)#(RQRF`=$>7PEnb`-6jNE)?-!t)YyGSkteP+TnUllDCY|rk!&Yv;8F&r9UeSorNI0BZOOa6l%dRq_=`qkq<|Eeuy0MGJU~wwB{n6j zJ1>M<9JWA%1ZFsqXyq48n2V>A3Bh8Av!HOW@-K1~a=Bxd@8VWMa^OD0lBRk9w-r%^ zkFl{EBx1%tyw0Qh+Fe{PS#uq)u5kLF_YWG>xq(wS$XeCVF;@MOIBi{a`t_4RWdIK4 z04m>unj?+tlc-RL$=XV%gx=w4DEeh#AIOth0YMb$FKEm#5NiKFurFEAk%VnrnfP?b zDL5QVK}smmoh|HQVtwry5P%8bh%Fv!MvZ=*-iItN8Ihtunk6gS%KxLJ~6_s@vx5xi!ZsYs_n|3h%e5_(lCRnF#I8lgsHKRDUv0I$6{Ur!2tg- zaii*Ja~s3<;Om3_Dn9Cp3IuxJS+HO`G3|QeD52Jjyw^Q6G?O|&mzfOXLRB`ENA9*t zmw=2-xNy!ZuORG=i^>ch>jfUU+VA5)L71cS zFJeqtyIHlJ!2~Sd+5_jvAN7D^pvx04m-S2-cA4t5f|$W9Lj+tK43q>!s`8OI46U5W zo8qsVXmV6mgYmFK ze(Qh^e@&5dalL-euJY0?YMlqZi9E`UAu*kQ#f<@o%S5v7Nc2IRDh52v!Gx!Itue?T z)yn%%413K7gVbUO>D1D`zA70;-@#TfV8!6h`rEh}A$52JocFv{EY+OW5>he43UQxL zVF8FH0Xq5BaJ?(`dh_gPR-Y^D^#Co00Bap{tOr9Q`{ji5 z{NdtJd-m9Bdr(mYEuy&kP>?UV4GRmsKl4Cc5XgOLWindVSxeCs80Sg7o1*eik^R(a zt0RG6NKfQ2J@8AF`Q&j%oLoo=7Y=?;WuPtdZ*ZLuE*^#0B^3>!H;CJOA3#d#922BG)C_f)ti&+`K4>Re`#jRw2 zs^v{mC!j}Loc_XP0TqqcFh(nZ%_DdJqg=e0aKV_*01z7pvkA5t*yBp(+_d0yBscT!_Qfk7tm z?VrXBd@G{gJ#a()*jS7P=Hjm6s_RpzDs}-bjcr>#SReplb&3t_9e00O)Mij9H0$f- zniUsvWd?`E#BnWAmvBYu=ST<*j1{37$+FoOR7p{&J__9QG*aby9;Z5gA|MUcte(}c z?Fzm;8b0}!qdL>S5!~5sl+PpQ?$P(b#}g7HA-0#TL}aU-Z1gA}s`y<`@*flu1(sE( z7>MiBl5Fgz0K#nAU{_acSGG|7j7v%;60uH(G}C(Q@$H zR~X5FF2lizFk58LdVX^+zqf9$=oN!(e3>3Re4Ugv4jkzY00zZ%kg!OfMraQNt>+7> zYvq17uk@v9%4(p=hodG`w5XJMrV{wNvdzR9>6&l;41X8Mp(dkz3V+fQln~*1RW-Yk zq~qC|9Y6!z>|odwA_s9QATx=|`+^p9T;6MFc89FQXFHYt{IHvVZ&gn>cD$>hP}rw+ z)X~*-2MJf3*|Idf*I(=C47_p17&N!J6cWhdzoU?@;h~(+D$M%977mU?&S3RVsZT!> zA+DXdA6-f!xuRdi&BS?@L{K8qq;8M946B*7USrX?oq=aqQ4Cgu)cB&(fsys-V)W^n38UN2-bV%s5%&J_mn253dYILQ& zozdUhYorq5dr1Y1rOn~lq3+dtgiRk#847zZEvhfCtFGvwuge&$5yeV~SnsCQo&^P9 zUWBwwb)n637+ipztX<-SBAtS>f{Uy4AR&0b&@-&<{-&)=&?KPYr)RK#`xEgzbqd$7 zdZRU>O(y!PyCAJy?A4q9uc1qW_vmj*c$#3A6fC4ddd7YqDDG`stCss@&Y+@L>9P5C z%gblAg%ROa>JT!aae(#QB@%}!QAg!cE>{&da^=k6_ytmcm|qPW2E)a9vsXO0`jW!} zfK*u3BANd12q%{X8e0fuE$M^XHIZc}htT9R#{72eNU!esndM=BP>A!yj>f?hE?gdv zqp{Nn6p207@49>PBmng3(0FsoGoZOOtY{Joyl{|u$^cR%mEml|+2!c{C@MnQs71ec zcvJWCNY8`H&`ytjy&xf=o$CY7&Op=KR1XGP8=p73sEiWTqMhM!jNe_aMUs!Yaq&sd#?}V0!Wdo1uM@T9kidsz{_LHM%Khdg>~r+E zw1i9LlCe7n_I$k>s3dkOBMtUS^D$v-?(<-^aT^qqy}!PAY_|E7L zz`Pb4h7#O;cvi&I<~lDTTwF55#X6o(&aN3zs`tq7I}E$@K&lHaOFbt3+oWI`U~%G# z+=P_@pHQUOG%g>_rJg&8?uvTaG9>1jN$gwy2iJh5I(|%TapWm~z8jwLRGF1GHc-Dm zfO@yAK^7R>i8Z=N(Nrow7iqW7B{rqAZgl>1NKInqtDdkL@(J ze*Z>*0(ZlDtrEVo(&+tcGl`WQ-R3rxI~0pVMYgem7^ug-_PIfp_doKi7K?i$rfMAcn#kGi|EKa%&Mssr~2ql!GugzQ~ZTF+j zN>NJI+ZK%-n1A0TE+@?-G2R#t%(uY%bKMVhPHiX@$u7IQ;6FgxYs=t(`~J<%z(7yx zvTgX&SeEeh%bjG+vx7XhrIzd4fV+b%zd0nNzp z?cWVY?gh-(u5K`lO$!->+kPeEU~Y^^*TRdeyDHQYNpx9zxk~awx98o_;kG439RI{i zb{U;P=VpT}l_^^!_sJme~Mlt00hUWvITj&=94R!LHtTy|Hz& z`D$c8*kh?lI1FBv~wyr(iL0@jR_Svgk$y%s$Z+__%_vQ6B`2+-39rwCQXMX7?NK`VvrVb zzw3CQI%Ehfhx59n3ZjRDLo=Uaci%wAvAw2f&3rS-=dR!GydNu^1vaa1z?8ASi5t!W zu~8sPU6c@a6zy|}EdFq&bPjcMG>dKFlsAT z_bj1L)L`ek$43colNF@l96kDAcJyQZ7ZKyV=Gi+BKk>QaQGLD_%XG3(OZ5fk4kzR; z=cjBI(l`%dR&761!$ohrzcpa)g!EQPK*e&UVSa&3BpYNCoZkO7Fw8#ou2?;RVSn1` z;!j=tOrmCaGwu&o`82>CfA3V8GLL}~7OGF|@<D-*BOs&cAUu>Re|BrRqZpt)Ru$OyfWf+PZ48-SeK`yq_?{V}&qzKPQSm%3 zxX`9CBV*r_?v+4)uwcP}2M~uLQ@epNZ%*{Iqv|ksaN0Rg(LT7L9k%N=A}^YQ%Y5E0 zej*Y(esg=&6ZPk;H%K;mjtt%v(B9E@2hiG*wQr>`?}ooo$uwMQ9{{RMi&up4xo;&w!uO_0Evu%E$0Vr05q=G~Y8$?AaeaIvV!k=H1nLZwo3u@E=3LVVHmW8M=%hCaaA^#zBw9 z#p)B+gB6J=$)wE}QV;$<0mISYdUr|hjv2>2U(Dv+T|1QrB}HUqD>3LVmbzhd)Nf$O z<${z4;sIset2bH`;0Uh{Yo$c7l9H>4f?)#zW3({<8BR+XdxYGWL;CwAgHn!OarIGH zZhE;XGnp^iKP(929&oX7ZrN&78_3OtYT((!n635#z_?m{kzey>3mRJ_^fLAl?my&% zueY88;AB?$WsnGyW;+ich4v~=IOzBCvF~^B6#4Tzaw)8d(d^;iW#pgDyWQC33oOnn zUEyWR(mz1-8F3(+<;~e;$4}qT>k*)gG(=ayA{&|ZAysQCn~4P%7Y%KiT0Kfm96mPqibdoNA8P>@V@`_bO3 zNH{GL2s7sq?dcX{7P3jZcyDe?6qEh*^cYU}InsC4VZwm_?lQFMm4s9dl|rQQlxN+X zpbT6D9LNkJ1sO1YXa*ci^T&y@AUyWc1PHnTk>t+|=y?DRl3Zyx0Q$}5jN>VPc{s;v z%x1lpj773#IH`2rF@J<=ROh0;%^w69^kYF-?McusQAI>r_x{;bo|aVb?UZolUo3F? z?5?edZEX2Y&kw;>e_4c$@AN6-7BJJQ$7f_TzEQGlUGhp}H$2JzjST;w>*Th2iytkZ zQf?ArAmxfRKuY#0*N`s*NC9L(;BabEX zCXLD@JKKz{zdIPK!zSZR+txp(R1>WlzdmtuyKHk5;|@h1*3MVW_PT`m2ADiEnfF00 zawL>~bqjr$z&iR^6+njVVc%cWhRM-#BE3805kp$%Fk&XBWh>$rm~rpUy&JM`{NBCJ zl27X6ET`v=ojr2o;bl(4LzHc86f@qaQeJVzYSkWpmsDlm5c9>f&%G?l?*jzSOcqH^5C1Uv5M{rBhCBGbKdwK;^K} z4#f-=OhuN5a;DW&5Bjndtgokiw|TBLD6P&n!=i%e2zT3&X7Qr9yFoQA7Dr<*E))I! z^HZVxQiYJ8e<~*cdg#`#7Y3RC7LeaoE;jd%9<|5AKh(i>tDgyS-iW-sT8?BDL@HPm z7d+qMd#9r?ru~8w*on8K1t@{<@yEUG+pM3C##0EC?p;>R&B`>LvRU5%P_xg^&v^!M zD2!^t+XSq+QNFPBVJg8i{0wa-P-SIRSyZO>arQbxKw{A*not*lh7Jh%dKY(J;90G zS0&@D_h)nJ5-kzKAx1=i3+0l~+bGUHbqLpbtFYL;HL^~@*`V5IQn>28F4 zpL%JXQ*l9AH}zn`@D!L)nZGyJ$ao2EpT0wb~uuz(l(dIkik${^#)+eE@;<>;0RNZt&0@SyeBf{a0_T6-NF;Z;{WN!6obakG9ogWU zK)pLYIj&sk!%UB3pUmG1Au)4W{6f0M7) z-X5F6Fi=p$lN^LO*MIEf=(_DM(VQPOX)jTSG75h$E~+yHmblA`yQf$6`(n1&{_V%S zGnKs+D*bET`UW)rtr(|z%R*eeu9(($anN&CAbgkvzYT0lz9JkbASXz^$8LCO5Z)b*z8neI_gg&nc( zsq1j>!Ft|ioReJJc{JY_<_ElABLGRzxIHHTZY^eLG7_U5vG_z&C-Q?a!Q~_%BJnje z+Oytw$@24Ngam46dFpx4#K}>4k#T?AA4!fs8%wsoBg>7wrUt5v^IDqx_3kLMEPJ!j z^&3v?tPQR199&wrea;BA&g>odSu31J7AiebCtJHhmQys zAxA{gR;e6ERk{1=_VG}e%s@!);z|P0rqpQ}^^ndwoqCssyW_O!1w^Ti7W_1}g_+e- z_(mG?$CN5V*efHYssnlNvadFOtnR<)0Rdz`Ch`R$pG*VDXk99+bF@+xD3QD-+W=@p zww`6J7nP+_DK^JdR;#e}o8`G1E9vFIlzOfu=zP&!7+G$A|Leqr22I}1_RNi|Fy;cEq6Zu zaLIJNe=?fW%1*pPjYICJhFniQYRF-aD;?77q2VC5%_Qiwo$+k-N*{6kve+~!iTNRX6?CMbxGVBqn z)BJ!4OP`;mbF*^5gal`qtaXe<+r_?d%0@IbLGt8kI}*(mG_M_tXNDS|S^OBhZxhD${8<)Z zC>d?QQ5;he^MN@~&O*BRbFqD}h|ZvO>vYyzJ}vXv`4ExnyAi={&tyZ6+@XwI!^7O+ zXjFrRT!CqAi4Q-IjdnlO~ z9h$b!AC?J$@b5~*wCJg@ehohm{7q&JRO~>a0oY0v>N_-=ma~)a+ko5g?i{=>SZObD1qOj{0r?*mF_jnKAKBFbxhle`?DtI0!cQ2NeWNw5jmBQ ze{in}5P}Uh5wzDe3-rC-%c!srB4}q6NSRuUaYq2$Q(v;XnF&bSo|20w_$9*^X!Zr( z#GU{o=mS9u2azXQ6Ls5*zKr^$nKj{Ls~`JULy|?wEgt0+l>W}|*-G?=b6pwiaPCVj z;$-XmB;;&ptiiOe8m?3Q{*fp0Ki-aj=Xj4LaC8ldfv{D-_krxnV0Q_kMSh9%MuQi*)I`nAgQuag%me9QU(Hh_{9f&mvDIEJn_!1Ow{=LM-zuD%G750`m60Gv)7NjoQldOuaB%yM-O(ZpMNU$M(GDu9D^yY7 z)tQUy^BGTdMI(@(?0Nv!C~E?%hTlYO+E}=7g|i2Wq#++D@)@LxVOC&=)7s9D9~n7 zcebo);Q5GX1X_~|2Z;FR`|<}$daf;cIS}vOJ{x@HX=CMseTyZ0jzTE~ic_p`L#t(6 zD1f>mlj^On5u9lW)9-HA- zj{vz_Y*n4^MefdD9u-RGAR&+>=`X==XxP%@J=Ww+T-j+9m6O~F2@_U&wq_)L^8r0z zoIArhoF>xU(Iijz5uR%jGUw*V>ZrPar! z;~Zj=`C=JDQIYru1VOg0gXv#SZ?`OK0v(un^27wzJGC)u!<>8~qquuI&e>mQ^_`_C`A z0MKalGUgNBoWw)h;AqvS`z`<83Mw>Ou1O>-lQfLP6-7~%wTck#NfiqW@ZU0uD}J%r zv~yCjy<^oBcyGz`$j$iE9!K!Oysv{?$Q6jJB`sJTDR%R6V|?9sYLsqy@o>qKwre=5U;^MMS>Iz5K)`Gcy@XA);>s|9OD11qFN+QN#Oj$3V3Im|o`h-G(!dP3R4d%6((=}sJ2xZ|h0e^I_=NM!3C z`@sU|>z}@3FHii^S+~sH=-|5-m+L;d_;tT;KLY5T%~HXXWvsD*Xj=b{$|G(4!h+TC z4j4i_mhoE`)vKhjYMpVYek^k@H`Sb6uvt#3jz@N2qo16FDNKXkig*;!Tjn8OJZU<; z^Qd{0f{3x#vR8_qSYm#|^k4lCG;IFL(2@Py7sF2GjHc(?RB=K4FGv?r}X*_p0CN(cuiL zpV@iy-pCu&n-m0l+$AaY4T@VC+cip1;pd@#10e?k7w{~^vqsZvQXtwV(k62i49`>L z2`DM`sC1SJ?}Z{3e@H$gnSIa1goL>W{1tCSXNm;XJ?@EsggfCV-}+~P=UYOq^X<-5 zqH^!!tEcjQRrq8~_)F$wXXfxbz+l~uz{UU$ zQQy;*vnwkte)YV@-9CZGO&@4FA+!KqL7ax$#OSykHtNn+2JZDhGyp2Yjx#kUEZYR z{iQAAiac(J(#4Tbh=e#b0ciE9Jfq5)lJr5)J(4}b9~;d7{TI~7+fP`7#u+)uR3q}l zzLm0rs|Nrdv69L74`V^DwzDHE=XYi6=j~E@{|&!=moEoQn(fiJJ3IL?LCuhh0TlD7 z`4)EvwVcLl8hOnpntg5ED9=mbXy!0701#ZfrE!$S9=YiT7;`F8dtT>s&)kI*xa^4h zo!@jsr)3|r%X{kL(c*ii(DSV@VOP9lRHr;AAPN~*?0@lZjXG~)=-qPxZ5{lE&(_08 zr_05{0wNf`U}hRTl8)2Ch))>Ec?^~Z$Rk_X;=C{2D%Nsx8y!)Q;B)tPF*cmulU9EZXCOr8D z3=Ko7D1^xdHae#VvyB8F04zJgEu{SvWc*FaA~lM2>Ei^G^@zC{lg(pdsuT)1Mw?uN ze&1&k-NDT|q7Vhdc7r($O?zOIrv4xNaN%vcKc}^0c{6ueI5d+*Xrsr? z;%5AMO$_jbAnHP%2=38p?mJEf|K=~7+dTmF&f{z)d^#01rdP+8M7}AZHNMAc9p3Hz zVoR8%S8eT=D3XQ-d*FLM@bn#b4^@cQWtb`r8VpEZ-&p+HNObjm_8nCZemU8{`~l1I zB%5|dqfE6#yt%*4Re~uB{E(KdOH4a7X%@>t+rjRKwgu>sf)>7~OJ^tT=MQf<{nxXGd^qoe4E}h zH8UscxZ9B}U5GH>78Ky;H{sn%Y3b+3uCO5XQRzvi@CQc9U1}RVJ(WBYEOAmkf%!sc zrMQ)X@s=XfLG9hGPVY2uS*$m>52Eu?U<9Ncp}S4r-)5}NqN^cID+mM?McFvV-V|52 z4o_ToCUw(~u|-u|o-~~sYyMCntpd9F#_H(=h*HB69j;vEK_$8q_w-<_o-TZP32(h)@b7R#rU0y4HD|ExUqk%m|GO|I z-*86idBf%9GQ}sgxc%d9p&E4!RLHY3!E9L>2^k-DP7*VZrZ3_A?lP94SKEs~`)++5 z&d@m>6LTOGa!DNG6M~U$3l@fV-Q2~^|DuR5IRvwxuh&S}f6jcX^eOAR!;~>;=c%@= zXjp_jRN+!WegNObJos|8bf54W+brvn;3r)7^M7AF{s>s?GKuMeCH6CuS4N-~)` z&@?xpcpxV}C(im6I~>Ld4aDu@%m;MD|MD{RoZd>s?>p-L1%`odyT*pfu3-9m(`hV z8lO2&W>$ApPdIr6XOU}Aa?y5YBxLjkZYchpi?42&>wgA-mL5%>f}a_?lF;8MDiX~x z{yQC&dk@S$jV_1}r~{4P2cc$;9=d14{@@xqP-;jkyzuV_Zj+HX8U+N5Bas@L?za%> z;%4OE)1nN9Ya;FDOesu1-o^JhJsA4a!+D$b?eg5y*9czW(Hcf{BavM&8?~D`K>=Jl zGOmF2oX}^Gz~$P5dg8O^4I$1=)6)|*tJ4^^1Ma+MN-7erFVpQv8k(~`2m}T#G*Pt7 ziyf-7&y2vOFtT|kXwVyNo_f}&jnwIazUn5R;>po7uP|(6+@-3xgPMaau?_DMRt`&| zr@7R{#k+ReJo91Rmf&B~76K|7Wh^J_)1QZG(KhC{Ox^9NGEVCY-CQoXua^$9gZQK$=AM z8LJ*ODh2Y~e(y>g)eHE_hboXl7uN=kT?R-OAT{y^47*dcb8n$+PgfKQ44s;t7CS$S z2{~VidAB>?x91%zot>x|^8al;7<{^zl1v?A!|~+ln)5sfCyCla;sHu<74S`h ztWC>Pxy<1^dIPgn(=I2Y;FhhwLT>X4Sjq`7wIlSImV@sBYkNo z_oK6@EhT(xwS^me(w$qXkOo)lR(pFRvhp@|;2&@i7XAjrLmRM*26aSg*Tb`Xl}z!z zCHdkXzrL(AdJJ{^3sqPV2%AH)M1Mv{9U870sMUlaZ@E$2?c)7s3E+-WaLwO5_ivyJ z&c!vD^MrQ*Ie!M@18e(!-ZVQ-{6cJEv(`1gRk*I&bLopgU`=D zf5qJlJMcI5DTy;^Rc&KevvyF=l$)!tf2_iMlMW3a157>!@&ne6*JcMw5rv{J?xF$K zn{1mUf-&QYUZ3eorUkmbVk$U~kFZ;82#4|0Kz5^=)<=K9`V?!%tmI(qR0(5VN?2>4*X91!l-KOL6#gz!b?_o4nqR?g70lGi5b4D8b%Y*8P~e$J$GNDk+czFh(+Km?nU!=OD{=xNk`zN z9OxoReji0q5rzSDe(falUBqA5KNu>X_Q@b%2?hh0R|u$x#YZ38RNjE1=z@rKiIq&x zTe3$S`kS;5qA6e|PdVt6b&;b5j7cRDW3l1>= zIfdFMj~zHdf|-&a%$VZp`_09X+16_xDf1xOQIGx6uySw<;K02@?bVMl8RsE8JKLZ0 z9PO7D!PrpW#9gVEK3}B@v%axVt1G3IDHVJ^Vj{c z>=(=Twq%yR<@Q-KTyHeY0}DAh4mQdio9 z^)R>PkYGc5=os1bN|RUFw#>_Dt14q;?U~Z$7;^{0O8Zv$lT2lUM1X-nCA~@FN;i?7 z&TO83<`nz~<+S}{cHPH$;>Y?`zmMDk?A-xk=wPa%U7$cef21~(Z=hCEyfYris=9!$ z0NRWu_;in54O9dVEdAJWD-C%Stu?+8DDj^#V{HCv51H@WPTd51+5cw&0v%10(VWAd z356cxncoFsQfRG{S0M6ZX0u|q(69kswnJ}{W(_&75MoIjR zE@SkQ%GFb`c9Y2?>a1QH@K1yGMf-{qj zie`+7qj15uCv(6a+FL3oBmPwuf_JLr+Dqd7pJ3VV=CBhFOrsjpQZ?$nGLv-cBkydC zx!AsdzjxAf(G$1bznqaMo52l17ylNQC)Sz}r^kDO(EZIAS2il>lC^km?63J??SoIo zX7Mr!8!ub`T^WZ+9?t5tUv^(M>*z8(upg@5WzVix2|yPMM3)rYa~KyHVwVm2T$0tP zVk-Ce<_kmO59p%w5a*rj+=*2x;C#qcrGRM3fAVZy2vB^MVz|?CtdY?zN?W{xq%Sq( zqgveE73|+THet-&pq@-H@T~_}ex-%gK>WRbSmGb#lC!a2g2ZjEzXI`P`p)wd)QQYL z9C?Qx7n&vM4_n)ej5P?XjZZw&$PZAr?3mNz{v6e>Yvvlo>-4L2c3sW6%%bk817o1pI5;3mzqYg!Pn zPriD?`Vg79pf}NO;y)J-FwBLwyWluCi*lX*EKs5quaZ-#>zUxlo0c>W7Oi)7*$$iw z2^_L)4JUXwz>4UdBK;`uVP1@>Q!T!ldTjL37D5Q!QKC$d2sf25e$@m1f_{dUyF9$A zB~CwZDSKW}ejP9HbPi8`s#N@wi-xqY=$ zaUIk%aB52*IXyA4?|Pj>+zr0E+eHPe4Un$Y@{ryYeBLGwDE?65ty8ZvswMiMkRVmD zTF5b1)aIoZd^GE$IDg;tM60ZCapX~ZM_S<7Ki#dx64#JB%9!MlRAeHEzO@smAOKA` ztCzYv3VH;h)oS&M;D)OJ^Zk?%hVDQ!pZds9hG8gxRx~z>O>=6J4u^;@vIJ8)mx8+_ zT@^pi$o|8D3ZD4AK+2QBU&wrlj?(Co`ojtQaSlPNeTIc)CQz^6va%?lYK#}v{JcVL zVbVx!MR2*5=wJ=yjAhGDqMB= zgVC{WGWRr)YO_p&WUSYGAP}kshYC!NPIHE9~emh$Z03kPb z_g-a#cP#u32n3~2`0xtLcBBVkDy5#3@RXL>X=o6v+%yT0$qv5A+J})UXYW0WOJ0b*Y6HJW;t8}cf=X+eC0{3H3IY6N!H}-R4DkcsXUEa(_`Qr8v4-NUscD`KS;0^jYp4HtG&Ku_S1A;9;SnXD*rRjc7H#a<802R7jz!eWT3O+ZRMr+?5d)f+BWk$^`r#n zEw__ET=q+jjDHCt3Yks|q2xgmL2mZ<83YV1|Lk+Zi zV|q8#@)hz)C!tX8>ahRR`r|EFqEnHjCe6r_r}%pU#5z4epbs8zG{lTI38e2_ERiQ6$7vbH;3Cy(32I-Wd+Km zt|s3kU=Ej#n9S#I3e&)1XOZ{xAFZ#JIuhJloA}?c#+b}!9yHBeNYjU=ri}DXNLtQ# zQY`y=c-6Ir1P1;C>V78ui`PscNrVFbQu^lki?in!%CO%g`6*-J3g-Op{@UXlZDbg! zQ(E?Qyr8`8Y_o(r$Dm(d_PJ%(%yIY5#vW;(J;5ZD(EkRh;>R6O^InMAp&KP=tPkpx zyCQA(&euxHCu2#SW9=F}R$?Y0PrRm@?Tilc8<3YK%JN;>$V}eVPV~om_6^7)3XO`F z`S{scNAJDZJqn}(2t-aM=o_P$3xLQY<@;E&MP70`Vvr(*rJ_$l!OE|xoy4d(g};_p z&|#AYu(cXyt`E5H0T5lk6NA~8NoTFJHGC<s;L&|i;D?9ByXgb9pTe1K$odlK zN0}bc08pbfC+$HAD5%PKLl8dkQheYIf7eyT)#iLzg`jfsEkk9*Pz(dL(yR9Ci{;Dh zgy^V8Of^jNfyy;SFJBOVF$@HoY46DO{(9nrcLyFa!NMVmez7#a=H*l{E0!Rxp17RAjt)D$p1zkp24Mz0hL?1Yl*qw*--+j14Da zJM-836sdoCR#NfCg!X$`xr_GtcHxPf$<~|c78f1TwBdSR=qhF7<*Da+Bhh7ay;ZmG z#VY{Z;LyB1MD}Jn7oc<}OMi0UG;kyH^xsv&R_}%H&z!9@>zctB>t?w>3Fp=#@83Rt z@n?Kl=EJAEc1D_6nOOXM2$8?cXw;R@+DzYftH3pEAw1hM0 zv2%5ma@ik7gRq0iw9I7>yZpGVHHa4K&ZtqaI-=jt;x9r421b7%Q=COZ35Jxo(99On z7rG>aDdxz($wctZRGPa2g#2pLKWp_iVHpeES0@*yf{GFZUCJFwyhx%%_iS!}Wyu4k z=qfrGcb(}=Bl*bLaed*8J?>j%5;nWCL9~S1f)Tp+i;BBc4eu|+q_%hPio^5CLD!Y$99FNU0MwIdjAbc5p75~H{m!z(TQ z{uXuANH@(rYi()M;O7H9Si1?y*ZibzVLi;NPDXK$)mbs;pEwe~-zJs=SYOjA`@C5j8S_p5s{tHmA+Vlw~3X6I=4)9=pZoSX~1;r087 zf0GhT-BTPX1a@r3*oF)!+@`;waEf^ZKvM>!84lu9mq? z1qJiJ1LO%@3l~3qOl9|?Xl>-45~|(r6k_$WD7pHV1=VZnQ=E-W3s*h^`b^Uk<<763 zGP0>aDVNHQ(m=|e5zDK6Hyb#u8E2Ja1T)FtOY*eK3s6XQRn2#oMzKD4Z= z{~=2p^q2EqHy_7jYm(uB#BZbm=~k786Ky=femrKiNj6*d`Y(}t1i{yTfQ5>U6}u!T zr{|20628V2HG?b%0>dO@e|JxriE<7-;A1Nw7E__u} zk-h5^3y}JpLwZDd_)BNW&dp&vu}Gbhoc^lzw%}Hi;kouptCz*oXK?Lv*y5XKo>J$Merr6U<`fIQ%^Wz?l(L(9>wBJqc%l!&YFEg5eHueI0lrgwD_H1kvO?;AZsnxJ4Pkgxq3Nt=CW7Z21>sfFO^%(3U0#TTg!Ze`Qh?^nUaaJDkyqw&!$lk; ze_HlMi55k=Bx)jz7$_T5oti}eIXe^wi+E;4hTMX|(71KB-3KJ=tZw^RU_ z;*awDe1l8!Z8Ir=WnMM`ntrC+uEJbD13EFOe3<06bF5N0ujwC7^Ouw3y_!h6g4;IE zY|6^1GGtH7*Jser?qV#NgxY!#^V_daU+**~2rX;_*9; z8u0Mw=ZkQ#mv^AA?;YJP8#-7GS>WjrY58k>w6VAs+J^!B#soCBkd&wg$`5M~CN3@x z!!u9%9^A<&MMSn?we`tIi9z$UTfNe^f66~ieQjXFcfLL=N+uh#tcKKth2oYiBj+&G z6vbPlOJq77!_es((?y>X&n1SQhm@&bOu`=nN$xYnu+fe*dhyE(9C4?0X7aN=n z_F)5<7$wS{NkJf6AOm)uwqbI|Q9wYnsw~=)5k$ZMUaZzd%;rjSyZ?Djx|9PrZL}@5 zpS+Zz0<$>0)rU1scy4f36BGc08@5$uDwtSQTZ^9`)}!uAi)Hw_vM!z#FfcZih7-$C zD~c@Wg_0?O)&c0>i(~3M4_8}u>n7|SN5l08!)w}#wSnVSPa?ZN$lj&tlf@l)hg@&8 ziVjLmc{wNds;Ayg%FJkT*}{D`@cv@4Vzw6&SOn910o8PqxiY@q zl#79PN>GCfOn*HhF_$3u>T=$KX;z;(cIG)N$p7N|nch9ZWZ$47HnH@#?HbA*C!F|b zO}s3h!sw!bkWkPWiK293abGj~&uC%yfxB=&SOGUvAG7Q!`G6)*uP$YPQQ_a!HnEM_ ze#kWWzvZ8z3X%2EDQt_MoSJ&8Tbj=+Gj(bhF+}m8jQ>*VUu2xEWHRBsyhv}@uE>17 z6ZVhw>|~^dU}2xtAB)ygZ%OmOv%_yrLFcEUy{G|^7oJ4%zVx+UKk7 z)&r8obn=T>JVarASr{G;Q$ty6I!;p(6?W;*W#E>w&+RbZCr1fsO)jrkOW86!?vk%y zRT|NuXwcD5rlN&R{#A-GZ92TLnjh}Nwpo|DxOocV1R%+u&o)!?q|6ArSGA(&V@%sqXx!~ zWnp*hqIx>0%8{Jf%v?mv?SNrWJopLfVy}GqTnG^FI+t)`0tWGPnPC7>z zRWNEQj$MYzt)VsKyqli%2=J^kd+q`V)g4}s!LX@<$ajO1-gTxQT+s-xP~>(h7OEC0 zn>~S;mVM`T_YR+%3l1Ct=V%vzJDDmh42~plV-s%;BOq1JEOa}Yu^o&9ZNYQ0lUl5$ zF9>DdI!)x_>#!{HNR8HKE)i`_%^?@#A;(*v(n=?{0D)*aVfdS55}78G|8+&XZ`Hi4 zv)p`f4ms4v-}qUeEjyIJ^c<*%3Dg9_BBA=6=u* z%lnviild-yzU10xCqiN$$|Hpyb6PL(bK`m0z#te1ZJGWiN|@A2_j<Zy%jRv3~ zc(*O{`8q*V*$V0~D_NV_+-GcBK!?013P6C7KVe~##++N2ZVf|k#&Uhkq=b5T^$LHl zrc~oG6*GT{i=2xDa4rk{cAJ|RO&Cp4$J8aYexH$C*eYoA+jA0s+Ka_XW{GF4+6vz! zYdc>gAp%C%yLIo^%{%YP%`zmwXoa2!K^!P?X#o7EfwQx)UI-3oqX`9dim=Fs?QgJg zy@~!zaOjH`e)Vvf#E4YE#4~S19&fJk3dJA>vJNt~M%-JoM|meUK;(b&C3cBAyK}cy zK9)wkO+N6m(o)p5HAn#M5F>PWBb!dAPeQzX{ngwV$nD5`t-s%zSaMpeRR(GErIfJ+ zUtI2vo2;11FR9B7ZhC4APCGKHgnet2$U?0`^&QN)|MjkEfPOuy`;+mi`E8zsOR7QT zz{^&P@-Q0w6MDr5!~-kW+B{El&2_p6Wz)}XT;P0(3gYql{PmXui{o49_4&(1pC=h5 zG4Hg-W1{9m0(B6rzDHT2XCzX#Tn~1$?91sHE92MI)gk(k-2;K{aJ3R>9!7yvtnVla zn6J9U@L#PsMVIWG8}gi8WDv&8n@yqsQc;x`X+0BWbl=9GGz3bKemwld)Edhe&Fxx3 zX3fg8m&+IteRI<@FiLpBc1>583~6*Y^RoLRE|J(h*fB*oHPT z-OiSYa(_YXr)#Y29xt5Jd7S4z`C+ndf;FdNxZ{+?7bX12bO#+l9Zha17s^M{I|+u* zhl3#wq5vf2zvJWj^172eym@9%rb;5ZB((l`@i<8_f>NjY7iG|8?-r?3TBy^&i-uq| z9dQ7NB_lu$4V6+-f8(1zd`DmD_nb5H_&?+M>w7{X8m8F}>I^w0^#beo#A$19pX*AK z=e(G2Ki)1(zx+a?y|3KnSA7`I4c}OrQQD&{=Ohqp8D6?J`1M^?cLiip(@%E zyg=BexI3|`(iC)c&a6D&Eb-Oe*N2XFkKVs6QoD;A-(a(*RYYy)NGLn~2HJUzZ+<&A z_xZJ}IA)qOx^_QepnKLll}9(zWVj8fWqq+L+@#!rh3qnKWSopG(E+1*#KvLpEpPD@}S*lzRGp1D?oc zaA^ealLniqB)ZK0n&UX zw=PeA)Xz@;_U}*+GbaZHTsSYL`bl0lNJ0@!x~70akCJb&^uC{9rvgi(vNsVL zS|KVRcvp)qP$N97=6ir5a&v3u@GgzYkOdu|{AYR-%BckNsbdu>6^RI`G!u)3Hl)Ygzm9PXD<{f)nLs5MmKLyN=el^H_J^%I?#HibHiYoZmHTq z=<0Vq93d>}K}qXays>l2YMAI+<}LXLcW$!lz`FWpJ-!IY^lH3_&`n<@TO=(~xB!_x zW?RcUi=Hi8Gq)WYU5J4qhJ#CJ*^9lC@V`B^b!rO%vRR{3K&t$+ z#%Ci1%1TQZ33;%i-FZ2a?j31&6`i55zdyhDR>zl&Uo{4O#9Q%3d|R^# zhsb#lgZfBMpW_uEuskwdSt_N9)0{%Rjjia-XLDHIP%4ejO#@h@_dL?tphex9p(Xo^6M7 zEDkgsYGyLt-HxxsY1ZI;eUjADtD3Apu$NUVVjs-U@ewsG=dAvWNBJciWvm2{%KSD% zOCGROy=sgQr$KTGdzTWOs#|Ep-NIzs1EkCest)=1_UlCsa2RpD?BN~i_Gf|u=!4a@ zvtFiAot%tv_P4YaR9|@y1hn2)*?GMzLZ^+^lIalp14U~3VxpvGWn`pb!8lq<1BGD- z`>Swm7M)n5?=SoU1N*Qa&-Q*DM{Y~N93!Zh;Ex@;k=A$S0*`8}#d!=!!5IIvzm3dK z9UffiTrWMRpdG@zSNV3(ed*Wys^j@H3*)j{97`EZ9-Vc`Uhis*rydNrBOCNY&pyQz zARkX+3hnO7g^1q+X=_igV>cC`q)v*-jn1v6h%{Y|m7j0ztX4_bzl;5msiCcmkzVEb z$qv(P&xr=C8DKZkLLmylV}>ak36!LqGcY9GP)wiC39Pa9eLwBBhc?%5kcMWu{NYcM zZEfbo&M!|Zg$Bv3{&HL$|IY?D@+ngV-gbE*$RNhBx92uk&HaW8gdR(`(r*}LVtNE0 zjF6Wq34O!}d0}oU2;ephBJY4`NQ35H<6!b2Aa~u3PK9+c5DwOrSi@i?n7>SJS_t8E zHl(nDQ1%9Dn1~h6Nxo?5!%OK{Cvk?4pDJ|&I6I>#IiPWct3L)HKpaGjMOc?qMdWHan=UgxZ3F;RLj5e8bVRpShe^ z6P2=hp>V(XOJhr$pF~!wN``Cj@m-vl5U&D=-z!^Z(4AZ!2F%BFA@81dnm&AAW?%9` zFd3{So8=~m22{+qK!p2$vON3;Xt@c|Aru~r`4l?M*VonDd$S}ql8kccUt2m85h_ek zuL=of%+zD?(&8x8#s4?=aqY=$$k{K?2MS|PUtgc*T#_s3MJ*jP`^W|Tz zZ@ovi(2mUkec|^pAo#nfscR7_EdXb>eJAtS1bPN#Y$d*S0FW6_1=udbfW*eN>m~|MmBEeZe z&n}bsTtGp$hpYpr=O6#4ZKI@ zttIuIpqfwShF<`q<>*!eBWRNPxKFtOvB*VTF>?z}i$%gq)1^l&KW8_rU%CW+ z87}bC(+pGm7jl|&Jyjra{f`(T%|YLOc9cUyH+OZI9sOr@%Q!_uZs!CU-s^uS8Z`ue z^KHjZE<;F|vj%gA?~|l4R6izjPvzcifC^M|KG;H&%g`w!yfUC=oYWC;X_k!BcfH(m z1Cc2t#EF0uG=1mQc_O!WCQV$W2Ncr^Vh^AuRrSnktRu3yI1=mjKhZ$nASELB~rZL zLs|0_DWAdlw|V{=TsUxa^svwRcYh(Nsk6fj1M>`=`o=43N@(q8x~ni(P5#MF!0FMO zg9f2AVXOqHFh|Mv3@hW|C$BV9rUPXizRCppx6hSwC1uaN-dfbIReQHFVpKJ> zR;dxAW{jfv=JUh%56G2sCD%FUIUcY3X3^b>JQ7(Nk=ZV~|0Z>U|8Lo;A4P)(uXq%wrPvygBT5ue6RL0RoDek z%%NT(>>bkEJMf6ida|r_Ygr1R_TTPIjoib8$OtBnh3y6jqretrU=bLSElu=hy zsmo2zsjsO#T2(dD)|s859&`d?JhkJB(HN=SgN~|7FT=b8o6RcYDOxB14OF(J27wjp z9*Ri4{~n&@lr!_+3TJXi#@-+Yh_VD?!?YsB`Zi8KL^ICt-Ww7i`D7t5PMUd0CFnU- zG{oK>mava|N@+-(|8X?wxuyttO7PXta35LE1uke#O2vQapHETbP%Yky5gx_#zMGnI zQRx6I5>laC3RoXgw+TVn~Tuol>WsvpWl&5P%_l~NhbJ8l|AwAByyT$BwC3|r|s_Ei8 zDIEGRBnkXRl@4rLJ_?Kf+qKLdEgmJ{|j z=c;n#n}k*vY4+C(V)l)*gVj~v^S}T0=5jf3QC2L0=ZD?}tI~0wH(JQ?C8<7P!OT)8 z&l-Ar?bOV&pNB2(m?qL{n%JjZm)=t;x-psMDlG2V>K_mo{Q92CN^bO5{RqZB z5C!1lqf{~H$QwPqV6ha_aD)I0^=`sVYCaYCwXv7)9)t@5)od5*5cdj%u_!%G9aWVi|o_Xp=b+L=>Vvju%@riPAZ z_9Pcy71-RDHgTi?bpFAw3KwWbk^(sHM3-BkRe-eb%$UkZ@rL4?ZComSvY<|G{1+uy z4y&pxQbA|4O+?TO6l+*oa~#lD^{M~EvRyQoM(#tA_T-Q2-pf=?>nNOdk ziZk9pgP8!7I3Vr?UJsVVDgbP8b57yM0e2(C1Lf|&lO5pi>puG_dOUs-fOuXXN2;jN zHk#dd@7-fsxl)L&Lxb;^a9#&6s(3?=K8$#_7GZ7BtfcbT50PMl)B(Me_c=#10rM|z z6{R5dHovf~HmbxrsOCE$8ke2IIL{P^^cXfrGbGU{Hp$xp*TEhJO|xZXPI|yv={wJI zYeYn`;z>FM3_3||(>?uRmpoUG@!#UN?u+pCdU*XXuNF-ezFcOwihcIO%mVXH)`(!^ zCH=rLrYxr4EuNPjls8_+pQXtv2~v2#m2@B!$1N|PKTcc@Fdlm&#p>!~1w?2UOYsSP zW+YLZ0qobWeT3*?QV=-U?`ua;DNW8koY2EZAZ8b9{+7)gsl*g@Mg=t^AT?Nst<^7a z5pG$v7JqsgJY`GVhJ2yoqhWka$U|xZ_$eNjznEwE7BK9@GB5_!7P=$2rs-=dtPg-K zf0wz2>IIWw>YdQ9%C*cmC_g~Kh3iYQR6OG2g7a3MpXsnz0noj@?w6TG1Yma|L`qiv z$y}(1_T2yktl{Efz`6Sx{UZWQYL9$crky7Y(#FkbYD`=%w~-Zd?ol9zS2a>kcoxLo zoEL?J22=Lbh={-)Ag5kUJmmRQHNtcKZ1NNXC*YplFW`|kK*hLypbuKs)Ef%{oQx-F zXq0Hq9xMM+)B6MU!!3uAGOo6BYP)#Vq*+$F96}%1&cQ(t#8;cVB7g zrT@D4U2s9RCUM`gH}@H&Lbpt;dCNjv9_7SO*8P0t_L2oga6~XnHJ827l{J6WNZ-Ew zXbHt6_n~)Culx}(DtPd2)I?;%gD)RkHuJ_1hK~N&+c%y7Fk%=4t$Gr* zn3Bid!s9zsWWnFH>_XF*Tn=>-f~DLtG0C9ho5QBHG!dxypM)F2r4+?A(jKVjB6;pl zt|7%=Z~DyVCl3Ccoj>;2!F|g6Eb%f6#~35>298!qgyQco?6(?!dx?TNdUM)=erT*b zq3eCEkxL5KP4TR5SBHnc?g3FqOjU0hK8BUX-&Ck7j{yrukjFKr{dXZ&ETk_EhMKHL zm*tOT&%hR8q}A1&C%9j@(8(qdG>m_hc zorXLo_UwZzt~#vR=J`y=2JOj|HT>YyWH9;YxJKx84Pr4p|F08r{+H8+R=pjjbB4 z5U$tYqj<*oBU#|5#Dh15vU{IdG_Ro-Bdq(CXKNjMu0?(v-E0u!yYt((Y~HcC((?H= zxi9j6_vgpnQt9eiNX^m;QlQDT+~_wtuJ4_LUKWF0c}X$n1Hb%0zcoN*T8qU$-I#zz zv+K(F@uR+zCtML8*=_YA`D2|XHC}p6Wg*So-;oYJn)w_F?mHF(KpMgJi(YA&8W=$;r@tNVT6LOTB#FT6xg<&Q_>5WQnlZ20vZxc+1}4<{+$fv2KgO zs*K#R)Amt%WY{_3tORCGwEuD>5rJ_O;3AJ8HH8$*_dfFjuVGlxKdBPI>XgiHls{^` zRbalc-Abgx43z1w(cGb2D=jpfK%<#abPdPfLh>?TO7iBkz3)e8`hkmR>pt$^;T|7x zx@rlDAX-qNSidYCQcxTV9e72q?h=(=M2`A%hotg*O^ui$MB1GG9j-E`Qu0$PGUW!W zRIcV+ILUJP8aKNPazH5VYZwiU#^*R?(nRB(S3ivAP{%U`w_1vLDyA3>4ME=ZgQ!-z0vt4 zL3SoqHvB?WE2G@Xqy2%%Bs-&pQ9_b}!_OrrznMHZG-sRO5EO}cyu-s5@5y<-eCqEL zLQJ^0^y_ZxLMp#G+xd3nYNRgWA0&r-qB#i!BrL>O8E?7Zz?8$zL2`M&IzmtXZs2)B zujZ$Be>uO~bVylETNFdHFwa>0;&&&nSX)QlUB8fGHJmuk2>3$?wh*R8FTU3f+!W2Y zVPD+Yh`>Gf^Zt~FvqgUQY1MnHhl`cH0cPy8p#%%Q=_$4l;3}TLw6Hw<@`6==<(9y= zkw?qObT*Klt$`+x|3j6A6hmUK9nHS5?bh~9epx*Z)U13+v=f-~HI! z5kXpP!sk5?M4%Ml`9c?A=4>x(bBSvIG<5udbkL>`D2>;UdK4?aKD8_Gttk z;Uq~u*lAW=1W|K|bT4Gb`Pux@c3XM;)|M;MUe!>zk}5Vd%wK)%+T!;)+r_fFf-36R zgocZu@lcJIvRpfiRA#XqLWw#9WkhqNWKQMnEMrYpgP`EEz4qMj<;z9e;MabU2s<#b0&Z@e(8IUxtHsfor9h!lVt+5Y zfuxJ8c{=`xaE34AvDw=iMfE8t{MgN}X`Y6npNAFFxle6XnYmeZj1Bk2BpV9!tFHwp zz06G$K5#I!O|ASX^Uf|>(Nk@dS22@MrD&TvoSl#C9Htv~aVaHlODQBq8;&A$a}^3R z!{G)X^a%8p8TR5sqZjx~TZQ!jhB;hU3d`(B0S@%f9U7qe>&lz47 zz8=sS$V`uoud)!VYVZ^|CD|OmH9I;we|+Y)UK;SCtpC#6f69S__>)6E>29UyFogK~ zqU^k@TSDs^lkaf8&N;w}&glg4JU^ZM0k_m$|w<1JMKtX2?v*ZHV> z^+EeZ4G%SuQtg{b5=>b|mvR8Vv^tMxt6j(yAs#tYkJ?4n%h4=!1fN%IB~HQ>g%6yE zsHUAwYSO1AC0(Z}(Mq&il~nd0sy5d)ea|<)ICVeGj0RTS2+*spwVc}0dc*i0ocn}3 zaUlR=OMBVRBL{g%#8{58?aKD-2R{zJ{A(T5w1kr1P2$5l;XrqCzx7{ceO>wf(xG#1 z;U(MqmEPMpv0Y|j0HswnHAdZV9&8e8qbOYv6M=}Udnp?9@PwuZa`R3y(_;qNaS;~m^sZ-}g%`rDxS`Qrxj z=-CILDqB@x8?Or{lCVG+yLLON>vpMq14`Z3;6u%$%(|b)e74|y09c(@Z7yGQegjps z$4xgZyF0F$f}o>9!2|8@GB^;;fZ>j(g+4~CsBg*PG#~{vfY{`ZrVN&U$2%p$Y`ja8 zOW~>1Jt3FDqM%4f^M!pUa*FVKbw20F`SlL@PU-$rz)gJaj*;vY&bY6^uX=cj4>6d6 zG%S9Dk20dFMxw9~6xjsa+{}l^y6sxbbp?``v!)?S){m{|tW_*S|1QWJkr~!T=~^id z|L3zy9SlEyKOHz63UOn!fsE8FJ*teQx=0QoggT)inL5U-!8dB_LVC zjJjkEoclg2>e=mPliKFloY$Gq=>8wqp9ZAsOwv7}6S4T!3Cl4=R zjT@SefDBNKqWKwdc_$yO%hpO7dkVIpgelQg`(Ye0jvxw*n1}-1wLO$VIPX{I-)7OV ztwLo1YC-{%{ZdTAA5F;rh6|r?)Nn*dOW%YF;!>@_ z3gNATBw^A*6jmckpqhq`ycRG~rvQX?cwfLHSia8Q=)qtQv?E{ri}>$Z5svB%lpnBB_2 zrj9mSpl^RbT^EzS_cp?RH`ka1ViKy)eLdGip8Qsy#1n?kL3|PoWA%TQVs>@k?1mk_ z?YNgXkmr+skV`|sTZq*k=It2{EHO0CKnl`C$9@aoh}aQ`Oco1&1_1Jbi}_@gfS_A5 z)Szc*3MCytPx5~*QG=X&azD|<$~_zzsHcNZZv$1Ko3Ss$A=d}2&AR>L8a6%KUdj+t zX;Ec$emLQZY{X9P2~3LlP-2{vMfTHlb+yw&_tw2Q59r3dEYm$7xqUU5XJN-zaa3ln zWi>MT499?=3JcQdjGF2o1f`8^0s{1hqHih&E4!@8auY+tzx>W%2L00ZKv=Zt`oKlq zuP1ACCR+*I_{U+VJNFruj*cGrd;Q#n;3<|gJ)pp)wCn56K}{A_+A+&Z`(D#|ZWi5U zzZL{zh5AB*7R;)_I2zu{;LmcE9LcHTJ9`~DF(hy49;s1--A)})3`;FI?2f8|z22+uN)D zf`A9<#^;k38;EiI`qxV1U3|qi(*Q^EhiyyN+PAa}*CvCd^LMKW_MiT3&d*kez)G+7 zPOfST(vrzu$D|X6-t+Ba!TTAbp4*MtZTb4ztv|L;maA0KLyj&7_%bx@B>kGVH%Nv5 z+IcSioE zMJUl2{ApyPBkIRGU$ZwftgLxLl)gWV`N(vQUnt5%g`w)T>Lg}L3|HI$C}f$~pWD?L zShdjt;aGaZUn_{T08&=4h3pXko56b1pDCWN@*)*$*;)txmKR`O=XzDExf`S~?moak zQLzDPPUUHBxePg@w~9{TPACNWeLG!%U}uBttWM;nDBJS3)R<6Vdrr>tu-2~5Cns;~ z+nhB36S5zQT%~OT<|QfxmK)tRL4z9}VuEVBN#iFdFZ9dUWChuAHe8FoGsnQTVMCkg z1Ec#{Y^TLF)3a!#Je{$zF=G$VV3ynFkb)mTbGg-h=9l}%DL3CY2{+R=9GO#_9v`Fg zD@YtjZmZ@LH5^Mw_1Rd$n4{QMduVG_DXAz#j_u3i9yC1gbn`xQ@a(5DV&{hFZyoQnY< zhT_k@A6s7iP0AX?*L%jbs2qqfnBG9LbHx{XjL{>H(1I|=li7jy4R_ufD zuUBPv*3s~zOgsngzb%gEePhN%jjBUA77yYBbKpsgnMkBe7EO77l3MPx2U%mQt{o?bKaI;R9%i z1UvIvQPm3AVRAM=NI(&%g#VOh#Ep8baum*%ZmJdD)(O5fM-2!Az?|3?o z25*dS!|CQXT1;P%jg=D;W5pjTzo^xJLk>W$$3}srpaFUm3cd_M|1AFzuMQ?-bdb0^ zn(>5NrH3S9(!esK)xpky<<)vl0o`)2-^uUq76;Dzr9kz!6?Sp%-gD=|qSk#)-~pU34MZp_999Y59a_v$Qqnl!MRiX&!iR^Is#G$f_yc z8>P9x<)<@RJha860Ka(+1yj+1-NG=~x<9ooof;1%%#pubrhva+W4!xxv=(={5-C0- zO^mWaoH=o@JA#-s?ZaUL7>XF0F90hvP*2mJ5=dP|v{;j^HO|S&KpX7x+TLR1@_2zLUDvJBo8+cHm0}O9Q1u zGZ3q}vE@AV^tc&KnnZkpLkAbzl@U{>0!t^tX$h57;cVCW{*S^Kt$9$|JnyN48pbiqiJ^P|n97 z>-1Gk77)|3AqmT_i!bAhl}ZZs$U)7KwC>d*B%lLs`8@)JXA(c~EjI z3vvkNK1+^ElY|>c=&R|g)v!wZt3Tu0rdhVeiUDuK1*=A>Ie(XAL%d=DJgX0j%-GXR5uCVx9NjXy5xCLP^t(`8@<(R17aUu z%rW%8Y%&#Q#jgso@ku?fGkU zst_Jd)pu$#o}v8g=nDS=RikEN( zV1Hc-Mw|WrSpY6T=1`x&xCigV9aAgQfml?&Ck_&E@wJ(4TlOKhKMTfbT41!YgXCAgW34{Pv3!}bAsYrX?quxC)8YSi4;IRFi`GQa^T={G?Rsm#i==P#o*b~hU ze7Qb0HoGE$zC1fitJ}a|FvM5-beb6+9R$lE-$~utuDc@0|2vCG3j6z|;9s$YEBZt6 zje@T8$Vq1;5%HHe-~WNgbG1U8-SYG4JQy2qpazUbhK7>KSghDdNRfCVO*()iveZw<`}GGlAdNbKfiUGt#4;z?~LGrv)?NesNfx{x-CjAgsS7+A)oD$3omC8vWqF%5UN*Uv z;r<=oI6iJVy0vWzTKMD|B#YpCG(GL3cbE}Rfcgso*#g*^4-~Ii!PQvL6gJ>au1&&J zO4x5q3X2#jaGPEA&Ge0=`CHMd}*(R(EFjKb|#L;}tw2AS6 zi7_$mL4IVW3bmdX!SZy41X6@wLko2B;=>gtPMEE|^Gg@+s5TC>jxD33vTsJ`TMfV; z)Kl|;cDBg=EXuJS*13gl=L$@VSfEDQ}F zAKr7j>U3#YRCJqxa4&3s%^W>)`t?K^GZS!<1e*xIH1!bYXkI{4qeqH+!% zTTHs%m`W)w;KXCMDuLIZXU~!hdf5NxKNug_G#8Er|AyIsCyaL&9@Ma+i-_kssY<<2 zC^?xcK&*GyA$ez|QPJSQc@zB}&x8`^!x6{4`7@;P&`VOObDP(!<=FYfyM1af9e4=; zxMc6&Ur4UI4jab5!AxUlcG*jCFUQy~X4&K9_m};~^JB;E!5j|jPeF1uYzf(-ILNk* zg=E?Bw-+}BRwTpz?tH0iuN>tNptM=14?@`)SelDG=(XBx)6_^A8W=c-eDiF21}Ft} zyq>tNsUX+@VHN~ZatiCdTg&3bUf-%Bn9I{^*z1qX3)rH?Ic+~;HQJ^szPbVbOlQ23t6w> zo68u`O4ju_LD*I^*sYRShW70 zy~X==1vrojU6}t+KnnNLtS2*J`HR0!*89x=w$6&)q0bg!s-#yP6sa_HlM-|YY7Hkk z1ckc;*NDH|&VZu0i1Hzj0t&hHs;Tu}eX$#B*(7=KMict)vOloBJUjKZ2J8t>;^bHR zfLlztSUruB4>fKzc6!fJxaf(;9%KmkFK^<&$!=GAfPj6})j!J%M^^epXZ4x ze`Y2?2`xi})4XMOx9ma;e;+*%%e@1tT?l!*dU`r%6OL-K?7Vt&e{-WMlhS52#S z&lc!1=6^IfXGa$e{I4oxLGI6n{k^Wahxgl61`3(18;E$u{(irGyz0C|-o%qOoxeaP z0ws)i7-TdMB^a?PABI$&1t_JBCRQB`g??Rk+6>aB>3a!jTdW?GBIX(het^$V#(qe~ zIAGrZ6@WB7=-28~MUYwF@K|Ma7?EIOpSry^6$3# zQTrw{k;ofH0kOJG!W1Bqlu9j)f-g6$ANrYrr|Z{~dC_dsSURP}POm8uNf(XN$^MJb zt5_P-NB2?EOTXtVvQBtB7 zTcMEAAmlej?#fsRZB9m}2~b?U2*W@myJ4Ck zGCyZSf}S)je`>o;kgX*5QUXfsR7+uzd>d@$FejcW8f1 z|K!p>v?VrtZqALF+NTK(f!@n@xYao-M#;-L@NCqJd?`j_4yBlWbmKQUC_0&iy=3G% zTj#PFxDVB2${_0~7lnjHBM#*RZs>t}BSHG%kVzoLZ%tTKs;yZ~tp%f!Hj%4L!g=-Z zRZ|}j$gI4VEI?ROWgGg8Ca6CrpeDEGm6;jwZXuI>gTW2X*HP+5oy) zZ0u1B^u>eB>M)Zn>%F);DiANma_cd&ljQD0O~AW)5hxl?g=CGj*A&V3WpjU^3J~PE z6AQQo*7saM_Ld~4KL6>vO$K3F;YdJ=5-C9AkGX@6J=5C+b93{Uu#OrSISOaJy)T=n zj61b%W)pkI=Qs95J|y&fhhWn=VOsgDKzqACLnrMsNXha0T$Ys4TuDabD`!=YVAU(vWZ+}3Vf5I1hNdYR_~oH9@%uLJ_4mS$i-@UJk$S{tEAX+aOsf= z2#a@)rf2uFV!? z;1lXNlyr^bw@2~dw^;<6R+|7SfXap&iz^FyxJf;VSOIxl-?sfB?-J2>b2nmC@;w>A#rPT+ac&0b19n4^{A=nld&|^YB1%~l+3vuo9V^f&l1Td zOKz(h$N&KD#IkzRkn^YVuWPQhYeR1t29u6EO+*lB3tI$Fm}*hgHqN@kdtoef@^yZd zA11E7-B{I#Qzr-wkAPTH!mfvVe69$524cn-t7=h|u`B_D0W=0`(vDbKO4wlpkZAQ0 zo>FlSp)EuePSYz3%{5m2#Z`~OcNC&mWs??^V-KsCz9JP-Cv?lt#?jUznK#L|*U1xm zPHT0VxZd%}L8@g+O7X2p_W!O^5u4o~r1T0+=J9D6(6X-zSu24`W1sbsW}wmV*U-dw z4+RZx=nJ>p{3DUY$L95mja?NkCKy8wtU7ZEWlYF`6o9}8p!N4aAPlNvMJa?Eb*5pG zD$sV$))+#Br`m0AEZS6M-(~;{w3I*Bc&)*!;@;So*$Nh&*VF1;tSZ0pPEeejY;Y%s zAP8qm`_|uV^&SRvelRxHm#}ZD=Qcar_jJqSt}oVp26-2K++tE=9{acUGAGP<+K0AF zrT|tn`2kjHKI?$mJsHQn6dw=NmlU;-ao1_*QV&P;LY_kzhg$}>98_B~9qt4OHoVd| zU1_cJ-Bf!wD&<7X6(?N~dCqFubCbp@(R#&m(m*CjH?^-x<~ab7O+i3y!nI_|*i^4T zj>bCUS()J>iA0RYy{PAlXJ?g_vs;j(k|+MmQjC_|a^0avKFDgNy%`9OT#Ol;O3oA}{k zQ)STXWI(0}+&WR!PrA0&-JSqS;o{zXJDoM6Lwp{zptYP_6$xJKzN`#OqTxEPd6JL$ z6bmJ$H5&v4{#NP;JsBk&1%~~&qlVqwwu3xyu*I@lg*)q?&oe4k5hOlkbn)=ybMNl% zCe)Q3`^y$I8pV+GR;W_+u|5`}*ZOj{{zGD6QN*(IfEGJsUFVFQ>hXR|5=j=d4zmF* z1+;h*FB}@$+PdU&MSZ-eIJsh;H<((?&;8qJ4wL6f$Uh>?-v~Dd`pcAHQEddi11L0V z6Tac{%0MJHFPAVCC0qNZ?VClVlSl=V!A|h^8O@A_6*^n(xUW-4;wxRbOcn#Wa2rjU z-0z&hXu!{8J1Ap>?6}aHFNgG9CKVOl2V$D`v~wlN>S7DlvAn?gdk7G_EwBEF_{fKS z3wRb&U#1-@=4EuNR*EJG2>vi!!rhcr22Tk5qvbSJMhF@kK1`Tj-v5(3 z5UW6!Drx=lT^=fLGj%FJ7|0dFUF;!uG+B7}p-F*_0!VE~(O}riZx5#MIW49^AAttb z^<8>O|0$67N<@zY1NcN6ilLecBLMX=pIpz(uM!2gOa7Mi7^F-RulE#f$~9n~7o;J% zXQO4eofO)A9Vmg%=@16<6Nw=Pi#%Z@GHdRvx zi0^>yTV9@8a_p*APfbrt;M4Khp2+Wba{U9?H0!{;ZLS-+F9PJt)TOiHNAGa+AW#5) z;Igc_KQ5k7Y%!%}VQN1$>mp*`V5)~}BhgS-66lyg3vJ0W%lqUEqQT-3*1pntB3Hyw z1Vl+A!2eQPYFDHz^BZ1LK7S4IWy3h^>dNP0k1)L(U;*u`%EDxMDjFyRw3^kh<}MR2 zT6fRpFP;$1(jSh;7dtb3%!Fr2n##E3O$2t&PU8vh>7ZsVw?;B0AM#^#>B&qg8x{W5 zM=Gh$Tv?W}v^9eLsyhnmF#Yg9vW!?D+kESQrUDx5;QWI0v0v!5VCOzi4~ISp|3>!? zYcHj!j`VeA;01zh^;W=?l{ewgma$d}<;>vl-tm~zJ^yH?`fXY^7ohML>+j;Vk_FuP z@2+Pokg9(3Gp>Ui%vca6(RT)PK`g1n`eNa?QH6BEE`1&xGetwUBVM=5D`d7<8Rb02 z3(>(gob>5?+}5ANGPDv9K=c5xaSEo0hKKXwsUlPo#DP5=s#G?7%VO7I0hRH^Lc>&O z8f$Oqn?i~xSw(~`63XVxeSZ9{U~TeJ?*22c5Wf(Th@dBT;4%~CpGiNSC^Vtiem;zl&Y@4E+gnpkTm5#J?I@TOL|h^-}vO}Ql5e2%rwfP<3JD)3U|lyEIv z4PxysJOC6_0J=@-Yf!5{k^w0ub80%*FZ?ohhpjCrVzPwlAy1TgkhX^yh0pM4E^p2T}q%HBZY*sU@wLHOEr5v8JB^8(7?akF*g`92R)l-5!yRl zXS6DZ{i0!xS|`U(Yd=ZW*6c3W^6tn7i;BIdnQ}h(+kLThr7c!N2$thi1Src}Yf_-_ z1SJQX^_bOS?z2aMW&h@UGn_JW#aXW5sEDchv`{p-^(7?5s6A%je26YY{;0O=GF`Xse5pZUF)4IEz5;15f|=@VX8~XeyUlW& zEdB$2y&wkNs|Ob8+M;1T z!O#_xg{4*WJJH$B(CM!mkPBe0de*CoQNldJ*Mox%_rSIm!u3^v!Rzj2y{5G@Ze?j2 zz1G9*Fr|#rvgapzub#S^eW+n`@4gsD$F>5&qYX3@BO&oz!Y%Lyl5+F>i~7O(V)%lS z42f*sq6G8WsMAU(h~E`vzl}-D;%Ct!sl)J)B|0dCCMq@=DMKDk z8mXgRdI#<#-CbVe2|IrZWR;=`tEuYW&f)=OFiKd@HBf%z;<+;TFMxP`NWX@T)wOh-z&OvIIF*&n#Hj+XTpsCtHtY zBDk#??|gJv!;~WTxG1XvH-qa=!isrdv>82=XPX<+R&)d9TLxw=bcR@m1m zcVhF5FnoHq=qXt4fC`7-lseBGXI2@^hui!JJB1%_`?l*{z|GcJoQz)JkV7Wky)N-e zA8qeSM}V1P8>%KcDW~%3#|yZ-_;qL0StSYaC$+0KUr73%a`|IDPf?5-LOtFcBZkNo z%GHNYg>5_30JObLI`rg2rO`k|^5YFsU!@L{ey8Ap%qQ_NP;7z{t7mp&oHBt4u@T{y zjEpan7T>$liM#_cmsac0D1dSer)JQ42O|E>Kg?QRA~0})Cprj!O&A|QsYhtCK@e?# zWXdLfc_a4n(2ht0WMKTS#?mJB=7kx-1y#;r3I#14EDt1s)W*J$SId=eG+r-Q&MY%u z=3HI6!y?oYFd#>32|Iex{MT`<*VPP&lbRL?l&&tj) zCbdOwrWnh9ARA_09kkKX;5(urAQ)JUh8KFj?_*wCkN0|z{VRiN#BW4Lf71L5W#jBE8`hhHpPn*yHuj)1L#BUgS}lZaHP+0(PQL{a??}5e>S3RfYzh z9msNz$#RrAus|h@j%*=oQkpQTjNJP9-`hu<+ex|>E<~8aMD}ru`}smPjZ(Y&fN$pf ziqU9A#cd#zG8{|?{XU}{tM>+=l2o{#VynSKC%3r5-isShuudaV{OHY@7Qbe z$`qXZ{q+wo&xVNrQ{4^md(F)|Jgmyh`*BRh@m>57m6aCR>Z*=ZhrQ3L7OrorFxGne zye-T>mR_Rr_HM^Wy<09u%d(5}3?EBl*q~3U!m^(&c}nZp&N7&Pt~0|fe`g4(ZTe(E zl8wpKT$W}#m6X3k8fDCT&`?;;cRm}-39WLz?Dy*?ux&NU=jAsy@7B#>`oBxu;9K|j zxdayN-~Y~~2!sK_*8oG;s|OHmV5N_}hCZtaR22TUN8h1;%)erpHOX4BXik+(eIT47 zJUkxvl4owNIfm%S?=kf~8NSQaD;2G7#|_nWws6f3Y%Rh>qnXezcq0%HH4eJB9zS+t z>q>K&!*$N@`f#{P!m~TL+XoChBN)Yw@_4N}k)od@e;#dfs(!>W15r)p_Bl*5eI!W_P2}?uP8H>#yZ8FyCCyP4K}H^ znnG);4M1?rVs5jlg{P*$M=;6?6CYGs*YRGa*0{kKz(+f1H+XR3BZPxZt-->{*i zR|1UzJ%3*$Gp%R$B0&~Gc}7nw_t zxJ*`9`fab}>y}cQ4TJk7EXYpVz?t1hOZu43iG$?^zvN7I|xm#E2N+HEl(YoOuOP!>ZyHzHu*r!gquPkzE9RB{D3@ebo^bWne zmC0L3+Ap6Hh*^(uIy=7kud#lyW;&zHJvjiXOa48S`9vC%ZL$XR4Tc`ZKn${jKaz9b zu+`6y=dF$AL0neNgy`|XrhNh>>~YDNC%r$SKYr3UUoT-v zem=G^;9}qM_q$Jf=*f>KbH_=NhVd~xauUscb^7h?;-k?7v*64`gI@jjN*~*IdB{gD zd&M(!Jz%ak1|QnAJ-CMHy;ebT$`y^gT^mnIlY%dOqZII5sXR*0Om;1ZO@0l%S=>igb|Gox)cMod zHPUM!BP8?A>Yo9M!i7I>b+L=ImA3#j%K~Zxg)BTK5mE#8UD0qicgZ6ESxNT21#>TTbG(RjHy$Un77aZjw|OsnRH1lKC1bii1gD*ylzf2N}N zq8jtNv~sX<1;BFOpu$?yOC%u`m4X!piiR6hOc3q&oqUOttBu`Q=@N+)-;Na$ZwKxq`$+rJ~MP-^p#8Zs8 zGJFpWv@8rt&0?Q@Xd-Bcjl8zTFv6`gV7>5msTih+H;Y0(*A!mdnKpfR-$`@Ym3iXQ z|7Pz|I$d_=^I3@6h7UyK`9W{9(TfAjbCHtok5NLO=fp}_n&6b|0?lEUziawS%@rT0 zAig~Fax>K`e_3RvK~*tDi~jJ?%gA-|gG0ZHfhWP}c=k3q{&!inC_>s3%S)PG!YJT; zbDyjDKF-U}mlKVj<)NQm;>>{Eb?3mh4!_ViPFuBR2l7T^`T!rN`}g-;Xy68i4-1Vn?&FeSqf+Uq)jLvq98XG0lth%UZwS*H zj}?yqSN$*X6tE@Xe%ygU6w#oMU&D6@VpRz&PwvbMx`MZQT}3IU;-6 z?pCut+pbFsYq33dTt}1I^MGH~CgrV(m^tsj)BS!1I%w&8t-A?Lu3Me&Qq$aWaFq7l zbS4cexr)|wm~W+Z7tZ#tWD>n5tFacRFJ=tOvZE10twQ|w7!@aQOjaJM9#o$pqS8ru zP8KJQC5=$&1m?H(E;5o@57V&?$*eGD3g~sE@a)*&y->N+(;m3%d0I}0z#rqBnqPp$ z-)weD8|lx#c+%t3AY~eK`@!7$lto&g%l-M;qwUVWzP>Xb|AaGs_8?#AJM05R(|;(F z>>9Ecgiv$CPJ57QB^#nzNX{*-n!&nc8H|3Uzr}8zPF{5dk=AzR@6_cCoZqbcUSkY& zx;j)Hyu4gGe{mpYX%K7P@JUND=KXZ%S0%63ksHe$YT>k0BrzGN;X$3Sa(Rt|63^R$ z{ITh)=T~0-Tt=vqT@H&n7H1mN*>pE+VSCK%MZi7m?cTLXJ4u($t(220r{8~P zkawySDu%8{&<(r)jAhiT{&1*~MQvb)>!lQnE>Etc*JZR(g`3}@t&K~bHu}#RNi|GS z<$SEe12bfgs)8uLeBa5*kj07y<(`{1B-7Ji|L&EAnY2g~z7kE#)k~$rfuF$fm~*Ep zd((%}m4Zaiuq$fWP-$7{+mp_}lQ9f)$5kvw&wUZYCifp!#8J_B4T>{~O$j8Up3^Y4 z7=3CL>8kYPzCNhuDUfy(W)B32*nNQAn}5&bRiU|lD)#x0nOgtIyzkN8N9q+sNI=L> z%P1BNkKWFLi65=^x_hL}eG?AxinI%lIya_^n>btk!{ydw4}GzGHS1OGJhYHTYnF8j zzT=s=@ZXTv1K|uMUHJ3r^wau(t}oQwU-!4N%B_9oWwVPbiIUsZ>2Uo>o6Rc&Fc5?+3qrPoNTOV21P`@@CcOq%Ab7yIMM^~c#93=}XjQ(uTGrtQv8%#E+% zGZ21Ii@9ZF;QN}i*Q4;<4F?k@3aQ)^P!WVbHg)DbJ8+%4-=MGIPX`t7QiX1Cnk-uuX( z4g;!eb)6sUY`>M*WH&eMhNDE_vpWL^0m_&@LFI~b zt|VWxf+^3wIMZ~J8z?aO^f7+fZMXa{fBp;B-!Kul64%8)KYx{sZTemtkxE{o7aU)o zzfxMH1QfjAZS~4(V?!vjFUObHn5z*QIa{1-x`rd>kZXxP_@-Ms?}qa?t<`xvQ%;-h zE;wH%uZ#@K`10$|^S7_V)93xC=QvzVonSbo%Ymn*q~NX#r&kuuQSWQB`2iJ z@tO*{e?jM0_U8Q`;qG^-yOo=_V-f|8)XGR|8@XAnC|96bYS^yY7&6p)KE0eS z$5i+qrkk`wkV~v7BIi=50cgGZq>9~DNRffxJHx+WExcqP2<1? xs|ckQ2EPTya|jNBQiwT4!AMG;LpUE_{~x@p-D$WB(^CKd002ovPDHLkV1ipT_PYQ8 literal 0 HcmV?d00001 diff --git a/src/tethys/niluswraps/PDeployment.java b/src/tethys/niluswraps/PDeployment.java index 364a9a46..4652329c 100644 --- a/src/tethys/niluswraps/PDeployment.java +++ b/src/tethys/niluswraps/PDeployment.java @@ -50,6 +50,10 @@ public class PDeployment { public void setMatchedPAMGaurdPeriod(RecordingPeriod matchedPAMGaurdPeriod) { this.matchedPAMGaurdPeriod = matchedPAMGaurdPeriod; } + + public String getShortDescription() { + return String.format("%s %s", deployment.getId(), PamCalendar.formatDBDate(getAudioStart())); + } } diff --git a/src/tethys/niluswraps/PGranularityType.java b/src/tethys/niluswraps/PGranularityType.java new file mode 100644 index 00000000..ee898d64 --- /dev/null +++ b/src/tethys/niluswraps/PGranularityType.java @@ -0,0 +1,58 @@ +package tethys.niluswraps; + +import nilus.GranularityEnumType; +import nilus.GranularityType; + +/** + * Decorate GranularityType + * @author dg50 + * + */ +public class PGranularityType { + + /** + * Nicer formatted name for a dialog. + * @param granularity + * @return + */ + public static String prettyString(GranularityEnumType granularity) { + switch (granularity) { + case BINNED: + return "Binned"; + case CALL: + return "Call"; + case ENCOUNTER: + return "Encounter"; + case GROUPED: + return "Grouped"; + default: + break; + + } + return granularity.toString(); + } + + /** + * Tool tip for display in a dialog. + * @param granularity + * @return + */ + public static String toolTip(GranularityEnumType granularity) { + switch (granularity) { + case BINNED: + return "Output of counts in regular time periods"; + case CALL: + return "Call level output"; + case ENCOUNTER: + return "Encounter level output"; + case GROUPED: + return "Grouped output (whatever that is?)"; + default: + break; + + } + return prettyString(granularity); + } + + +} diff --git a/src/tethys/output/StreamExportParams.java b/src/tethys/output/StreamExportParams.java index d4842e64..2ba4f2fd 100644 --- a/src/tethys/output/StreamExportParams.java +++ b/src/tethys/output/StreamExportParams.java @@ -2,6 +2,9 @@ package tethys.output; import java.io.Serializable; +import nilus.DescriptionType; +import nilus.GranularityEnumType; + /** * Parameters controlling export of a single stream. * Starts just with a boolean 'selected', but may grow. @@ -23,5 +26,16 @@ public class StreamExportParams implements Serializable { public String longDataName; public boolean selected; + + public GranularityEnumType granularity = GranularityEnumType.CALL; + + public nilus.DescriptionType detectionDescription; + + public DescriptionType getDetectionDescription() { + if (detectionDescription == null) { + detectionDescription = new DescriptionType(); + } + return detectionDescription; + } } diff --git a/src/tethys/output/TethysExporter.java b/src/tethys/output/TethysExporter.java index e2bcb980..35733a2d 100644 --- a/src/tethys/output/TethysExporter.java +++ b/src/tethys/output/TethysExporter.java @@ -218,7 +218,6 @@ public class TethysExporter { * Then do whatever else is needed to complete the document. */ - dbxmlConnect.closeDatabase(); return true; } diff --git a/src/tethys/swing/DatablockDetectionsPanel.java b/src/tethys/swing/DatablockDetectionsPanel.java new file mode 100644 index 00000000..bf2ee42e --- /dev/null +++ b/src/tethys/swing/DatablockDetectionsPanel.java @@ -0,0 +1,89 @@ +package tethys.swing; + +import java.awt.BorderLayout; + +import javax.swing.JComponent; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JTable; +import javax.swing.border.TitledBorder; +import javax.swing.table.AbstractTableModel; + +import PamView.tables.SwingTableColumnWidths; +import PamguardMVC.PamDataBlock; +import tethys.TethysControl; + +/** + * Table of Detections documents for a single PAMGuard datablock. + * Generally, this should only have a smallish number of entries in it + * so may not need too much real estate on the display. + * @author dg50 + * + */ +public class DatablockDetectionsPanel extends TethysGUIPanel implements StreamTableObserver { + + private JPanel mainPanel; + + private JLabel dataBlockName; + + private TableModel tableModel; + + private JTable table; + + private PamDataBlock dataBlock; + + public DatablockDetectionsPanel(TethysControl tethysControl) { + super(tethysControl); + mainPanel = new JPanel(new BorderLayout()); + mainPanel.add(BorderLayout.NORTH, dataBlockName = new JLabel("PAMGUard data stream", JLabel.LEFT)); + mainPanel.setBorder(new TitledBorder("Data stream Tethys Detections documents")); + + tableModel = new TableModel(); + table = new JTable(tableModel); + JScrollPane scrollPane = new JScrollPane(table); + mainPanel.add(BorderLayout.CENTER, scrollPane); + + new SwingTableColumnWidths(tethysControl.getUnitName() + getClass().getName(), table); + + } + + @Override + public JComponent getComponent() { + return mainPanel; + } + + @Override + public void selectDataBlock(PamDataBlock dataBlock) { + this.dataBlock = dataBlock; + dataBlockName.setText(dataBlock.getLongDataName()); + } + + private class TableModel extends AbstractTableModel { + + private String[] colNames = {"Person", "Name", "Abstract"}; + + @Override + public int getRowCount() { + // TODO Auto-generated method stub + return 0; + } + + @Override + public int getColumnCount() { + return colNames.length; + } + + @Override + public String getColumnName(int column) { + return colNames[column]; + } + + @Override + public Object getValueAt(int rowIndex, int columnIndex) { + // TODO Auto-generated method stub + return null; + } + + } +} diff --git a/src/tethys/swing/DatablockSynchPanel.java b/src/tethys/swing/DatablockSynchPanel.java index 0049587b..8da66a90 100644 --- a/src/tethys/swing/DatablockSynchPanel.java +++ b/src/tethys/swing/DatablockSynchPanel.java @@ -1,6 +1,12 @@ package tethys.swing; import java.awt.BorderLayout; +import java.awt.event.ComponentEvent; +import java.awt.event.ComponentListener; +import java.awt.event.KeyAdapter; +import java.awt.event.KeyEvent; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; import java.util.ArrayList; import javax.swing.JComponent; @@ -10,9 +16,11 @@ import javax.swing.JTable; import javax.swing.border.TitledBorder; import javax.swing.table.AbstractTableModel; + import PamUtils.PamCalendar; import PamView.panel.PamPanel; import PamView.tables.SwingTableColumnWidths; +import PamguardMVC.PamDataBlock; import dataMap.OfflineDataMap; import tethys.TethysControl; import tethys.TethysState; @@ -27,6 +35,8 @@ public class DatablockSynchPanel extends TethysGUIPanel { private SynchTableModel synchTableModel; private ArrayList dataBlockSynchInfo; + + private ArrayList tableObservers = new ArrayList<>(); public DatablockSynchPanel(TethysControl tethysControl) { super(tethysControl); @@ -37,6 +47,8 @@ public class DatablockSynchPanel extends TethysGUIPanel { new SwingTableColumnWidths(tethysControl.getUnitName()+"SynchTable", synchTable); JScrollPane scrollPane = new JScrollPane(synchTable); mainPanel.add(BorderLayout.CENTER, scrollPane); + synchTable.addMouseListener(new MouseActions()); + synchTable.addKeyListener(new KeyActions()); } @Override @@ -44,11 +56,47 @@ public class DatablockSynchPanel extends TethysGUIPanel { return mainPanel; } + private class KeyActions extends KeyAdapter { + @Override + public void keyReleased(KeyEvent e) { + if(e.getKeyCode() == KeyEvent.VK_UP || e.getKeyCode() == KeyEvent.VK_DOWN) { + selectRow(); + } + } + + } + private class MouseActions extends MouseAdapter { + @Override + public void mouseClicked(MouseEvent e) { + selectRow(); + } + + } + + private void selectRow() { + int row = synchTable.getSelectedRow(); + if (row < 0) { + return; + } + DatablockSynchInfo synchInfo = dataBlockSynchInfo.get(row); +// datablockDetectionsPanel.setDataBlock(synchInfo.getDataBlock()); + notifyObservers(synchInfo.getDataBlock()); + } @Override public void updateState(TethysState tethysState) { synchTableModel.fireTableDataChanged(); } + + public void addTableObserver(StreamTableObserver observer) { + tableObservers.add(observer); + } + + public void notifyObservers(PamDataBlock dataBlock) { + for (StreamTableObserver obs : tableObservers) { + obs.selectDataBlock(dataBlock); + } + } private ArrayList getSychInfos() { if (dataBlockSynchInfo == null) { diff --git a/src/tethys/swing/DeploymentExportPanel.java b/src/tethys/swing/DeploymentExportPanel.java new file mode 100644 index 00000000..dd9a7ce0 --- /dev/null +++ b/src/tethys/swing/DeploymentExportPanel.java @@ -0,0 +1,268 @@ +package tethys.swing; + +import java.awt.BorderLayout; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.ArrayList; + +import javax.swing.JButton; +import javax.swing.JComboBox; +import javax.swing.JComponent; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JTextField; +import javax.swing.border.TitledBorder; + +import Acquisition.AcquisitionControl; +import Acquisition.DaqSystem; +import Acquisition.FolderInputSystem; +import PamController.PamControlledUnit; +import PamController.PamController; +import PamUtils.PamCalendar; +import PamView.dialog.PamGridBagContraints; +import PamView.dialog.warn.WarnOnce; +import PamView.panel.PamAlignmentPanel; +import PamView.panel.WestAlignedPanel; +import binaryFileStorage.BinaryStore; +import generalDatabase.DBControlUnit; +import metadata.deployment.DeploymentData; +import nilus.Deployment; +import nilus.Deployment.Data; +import tethys.TethysControl; +import tethys.TethysState; +import tethys.dbxml.DBXMLConnect; +import tethys.deployment.RecordingPeriod; +import tethys.niluswraps.PDeployment; + +public class DeploymentExportPanel extends TethysGUIPanel implements DeploymentTableObserver { + + private JPanel mainPanel; + + private JButton showAllDeployments, bigExportButton; + + private JTextField site, cruise; +// , region; don't inlude region here - it's set with the NewProject along with the project name. + // the stuff here may vary within a project. + private JTextField rawURI, binaryURI, databaseURI; + private JTextField contact, date; + + private JComboBox projectDeployments; + + private ArrayList tethysDeploys; + + private PAMGuardDeploymentsTable pamDeploymentsTable; + + private ArrayList selectedDeployments; + + public DeploymentExportPanel(TethysControl tethysControl, PAMGuardDeploymentsTable pamDeploymentsTable) { + super(tethysControl); + this.pamDeploymentsTable = pamDeploymentsTable; + mainPanel = new PamAlignmentPanel(BorderLayout.NORTH); + mainPanel.setLayout(new GridBagLayout()); + mainPanel.setBorder(new TitledBorder("Deployment Detail")); + GridBagConstraints c = new PamGridBagContraints(); + showAllDeployments = new JButton("Show project deployments"); + showAllDeployments.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + tethysControl.showProjectDeploymentsDialog(); + } + }); + site = new JTextField(40); + cruise = new JTextField(20); + rawURI = new JTextField(20); + binaryURI = new JTextField(20); + databaseURI = new JTextField(20); + contact = new JTextField(20); + date = new JTextField(20); + date.setEditable(false); + projectDeployments = new JComboBox(); + projectDeployments.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + selectExistingDeployment(); + } + }); + +// c.gridx = 1; +// mainPanel.add(showAllDeployments, c); +// c.gridwidth = 1; + addPair("Site ", site, c); + addPair("Cruise ", cruise, c); + addPair("Raw data URI ", rawURI, c); + addPair("Binary data URI ", binaryURI, c); + addPair("Datbase URI ", databaseURI, c); + addPair("Contact ", contact, c); + addPair("Date ", date, c); + addPair("Set from ", projectDeployments, c); + + bigExportButton = new JButton("Export selection"); + bigExportButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + exportButtonPressed(); + } + }); + c.gridx = 1; + c.gridy++; + mainPanel.add(bigExportButton, c); + + + } + + protected void selectExistingDeployment() { + int row = projectDeployments.getSelectedIndex(); + if (row < 0 || tethysDeploys == null) { + return; + } + + if (row >= tethysDeploys.size()) { + return; + } + PDeployment deployment = tethysDeploys.get(row); + String msg = "Do you want to copy settings from deploymnet document " + deployment.deployment.getId(); + int ans = WarnOnce.showWarning("Deployment data", msg, WarnOnce.OK_CANCEL_OPTION); + if (ans == WarnOnce.OK_OPTION) { + copyDeploymentData(deployment.deployment); + } + } + + private void copyDeploymentData(Deployment deployment) { + DeploymentData globalMeta = getTethysControl().getGlobalDeplopymentData(); + globalMeta.setSite(deployment.getSite()); + globalMeta.setCruise(deployment.getCruise()); + globalMeta.setRegion(deployment.getRegion()); + setInternal(); + } + + @Override + public void updateState(TethysState tethysState) { + super.updateState(tethysState); + switch (tethysState.stateType) { + case NEWPAMGUARDSELECTION: + setInternal(); + setDefaultStores(); + enableControls(); + break; + case NEWPROJECTSELECTION: + updateDeployments(); + enableControls(); + } + } + + private void updateDeployments() { + tethysDeploys = null; + projectDeployments.removeAllItems(); + ArrayList deploys = getTethysControl().getDeploymentHandler().getProjectDeployments(); + if (deploys == null) { + return; + } + for (PDeployment aDep : deploys) { + projectDeployments.addItem(aDep.getShortDescription()); + } + tethysDeploys = deploys; + } + + private void addPair(String label, JComponent component, GridBagConstraints c) { + c.gridy++; + c.gridx = 0; + mainPanel.add(new JLabel(label, JLabel.RIGHT), c); + c.gridx++; + mainPanel.add(component, c); + } + + @Override + public JComponent getComponent() { + // TODO Auto-generated method stub + return mainPanel; + } + + /** + * Set the parms from internally stored data. + */ + private void setInternal() { + DeploymentData globalMeta = getTethysControl().getGlobalDeplopymentData(); + site.setText(globalMeta.getSite()); + cruise.setText(globalMeta.getCruise()); +// region.setText(globalMeta.getRegion()); + date.setText(PamCalendar.formatDBDateTime(System.currentTimeMillis())); + } + + private void setDefaultStores() { + + + BinaryStore binStore = BinaryStore.findBinaryStoreControl(); + if (binStore != null) { + binaryURI.setText(binStore.getBinaryStoreSettings().getStoreLocation()); + } + + DBControlUnit databaseControl = DBControlUnit.findDatabaseControl(); + if (databaseControl != null) { + databaseURI.setText(databaseControl.getLongDatabaseName()); + } + + try { + PamControlledUnit daq = PamController.getInstance().findControlledUnit(AcquisitionControl.class, null); + if (daq instanceof AcquisitionControl) { + AcquisitionControl daqCtrl = (AcquisitionControl) daq; + DaqSystem system = daqCtrl.findDaqSystem(null);// getAcquisitionProcess().getRunningSystem(); + if (system instanceof FolderInputSystem) { + FolderInputSystem fip = (FolderInputSystem) system; + rawURI.setText(fip.getFolderInputParameters().recentFiles.get(0)); + } + } + } + catch (Exception e) { + rawURI.setText("unknown"); + } + + } + + @Override + public void selectionChanged() { + selectedDeployments = pamDeploymentsTable.getSelectedDeployments(); + enableControls(); + } + + protected void exportButtonPressed() { + if (selectedDeployments == null || selectedDeployments.size() == 0) { + return; + }; + int freeId = getTethysControl().getDeploymentHandler().getFirstFreeDeploymentId(); + for (int i = 0; i < selectedDeployments.size(); i++) { + RecordingPeriod recordPeriod = selectedDeployments.get(i); + PDeployment exDeploymnet = recordPeriod.getMatchedTethysDeployment(); + Deployment deployment = null; + if (exDeploymnet != null) { + deployment = getTethysControl().getDeploymentHandler().createDeploymentDocument(freeId, recordPeriod); + deployment.setId(exDeploymnet.deployment.getId()); + } + if (deployment == null) { + deployment = getTethysControl().getDeploymentHandler().createDeploymentDocument(freeId++, recordPeriod); + } + // fill in a few things from here + deployment.setCruise(cruise.getText()); + deployment.setSite(site.getText()); + // also need to sort out track data here, etc. +// Should really tidy this up a lot and move functionality to DeploymentHandler with all +// the metadata in a object ? +// Data data = new nilus.Deployment.Data(); +// d + DBXMLConnect dbxmlConnect = getTethysControl().getDbxmlConnect(); + if (exDeploymnet != null) { + dbxmlConnect.updateDocument(deployment); + } + else { + dbxmlConnect.postToTethys(deployment); + } + } + } + + private void enableControls() { + boolean enable = selectedDeployments != null && selectedDeployments.size() > 0; + bigExportButton.setEnabled(enable); + } + +} diff --git a/src/tethys/swing/DeploymentTableObserver.java b/src/tethys/swing/DeploymentTableObserver.java new file mode 100644 index 00000000..1eda9db4 --- /dev/null +++ b/src/tethys/swing/DeploymentTableObserver.java @@ -0,0 +1,7 @@ +package tethys.swing; + +public interface DeploymentTableObserver { + + public void selectionChanged(); + +} diff --git a/src/tethys/swing/DeploymentsPanel.java b/src/tethys/swing/DeploymentsPanel.java index 73e238fd..c41d7465 100644 --- a/src/tethys/swing/DeploymentsPanel.java +++ b/src/tethys/swing/DeploymentsPanel.java @@ -17,25 +17,30 @@ public class DeploymentsPanel extends TethysGUIPanel { private PAMGuardDeploymentsTable pamDeploymentsTable; - private TethysDeploymentsTable tethysDeploymentsTable; + DeploymentExportPanel exportPanel; +// private TethysDeploymentsTable tethysDeploymentsTable; public DeploymentsPanel(TethysControl tethysControl) { super(tethysControl); pamDeploymentsTable = new PAMGuardDeploymentsTable(tethysControl); - tethysDeploymentsTable = new TethysDeploymentsTable(tethysControl); + exportPanel = new DeploymentExportPanel(tethysControl, pamDeploymentsTable); + pamDeploymentsTable.addObserver(exportPanel); +// tethysDeploymentsTable = new TethysDeploymentsTable(tethysControl); mainPanel = new PamPanel(new BorderLayout()); mainPanel.setBorder(new TitledBorder("Deployment information")); - JSplitPane splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT); - splitPane.add(pamDeploymentsTable.getComponent()); - splitPane.add(tethysDeploymentsTable.getComponent()); - mainPanel.add(splitPane,BorderLayout.CENTER); - SwingUtilities.invokeLater(new Runnable() { - - @Override - public void run() { - splitPane.setDividerLocation(0.6); - } - }); +// JSplitPane splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT); +// splitPane.add(pamDeploymentsTable.getComponent()); +// splitPane.add(tethysDeploymentsTable.getComponent()); +// mainPanel.add(splitPane,BorderLayout.CENTER); +// SwingUtilities.invokeLater(new Runnable() { +// +// @Override +// public void run() { +// splitPane.setDividerLocation(0.6); +// } +// }); + mainPanel.add(BorderLayout.CENTER, pamDeploymentsTable.getComponent()); + mainPanel.add(BorderLayout.EAST, exportPanel.getComponent()); } @Override diff --git a/src/tethys/swing/DetectionsExportPanel.java b/src/tethys/swing/DetectionsExportPanel.java new file mode 100644 index 00000000..eda59aaa --- /dev/null +++ b/src/tethys/swing/DetectionsExportPanel.java @@ -0,0 +1,64 @@ +package tethys.swing; + +import java.awt.BorderLayout; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +import javax.swing.JButton; +import javax.swing.JComponent; +import javax.swing.JPanel; +import javax.swing.border.TitledBorder; + +import PamView.dialog.PamGridBagContraints; +import PamView.panel.PamAlignmentPanel; +import PamguardMVC.PamDataBlock; +import tethys.TethysControl; +import tethys.swing.export.DetectionsExportWizard; + +public class DetectionsExportPanel extends TethysGUIPanel implements StreamTableObserver { + + private JPanel mainPanel; + + private JButton exportButton; + + private PamDataBlock selectedDataBlock; + + public DetectionsExportPanel(TethysControl tethysControl) { + super(tethysControl); + mainPanel = new PamAlignmentPanel(BorderLayout.NORTH); + mainPanel.setLayout(new GridBagLayout()); + mainPanel.setBorder(new TitledBorder("Export")); + exportButton = new JButton("Export"); + exportButton.setToolTipText("Export PAMGaurd data to Tethys"); + exportButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + doExport(); + } + }); + exportButton.setEnabled(false); + GridBagConstraints c = new PamGridBagContraints(); + mainPanel.add(exportButton, c); + } + + @Override + public JComponent getComponent() { + return mainPanel; + } + + private void doExport() { + if (selectedDataBlock == null) { + return; + } + DetectionsExportWizard.showDilaog(getTethysControl().getGuiFrame(), getTethysControl(), selectedDataBlock); + } + + @Override + public void selectDataBlock(PamDataBlock dataBlock) { + this.selectedDataBlock = dataBlock; + exportButton.setEnabled(selectedDataBlock != null); + } + +} diff --git a/src/tethys/swing/Images.java b/src/tethys/swing/Images.java new file mode 100644 index 00000000..1d73e710 --- /dev/null +++ b/src/tethys/swing/Images.java @@ -0,0 +1,24 @@ +package tethys.swing; + +import java.awt.Image; +import java.io.File; +import java.io.IOException; + +import javax.imageio.ImageIO; +import javax.swing.ImageIcon; + +public class Images { + + private static final String imageRes = "tethys/images/Tethys-200.png"; + public static ImageIcon getTethysImage() { + ImageIcon tethysImage = null; + try { + tethysImage = new ImageIcon(ClassLoader.getSystemResource(imageRes)); + } + catch (Exception e) { + System.out.println(e.getMessage()); +// System.out.println("Unable to load file " + file.getAbsolutePath()); + } + return tethysImage; + } +} diff --git a/src/tethys/swing/NewProjectDialog.java b/src/tethys/swing/NewProjectDialog.java index 353ad732..03f64318 100644 --- a/src/tethys/swing/NewProjectDialog.java +++ b/src/tethys/swing/NewProjectDialog.java @@ -22,7 +22,7 @@ public class NewProjectDialog extends PamView.dialog.PamDialog { private JTextField projectName; private JTextField projectRegion; - + private DeploymentData deploymentData; private NewProjectDialog(Window parentFrame, TethysControl tethysControl) { diff --git a/src/tethys/swing/PAMGuardDeploymentsTable.java b/src/tethys/swing/PAMGuardDeploymentsTable.java index 25e93601..59a8d354 100644 --- a/src/tethys/swing/PAMGuardDeploymentsTable.java +++ b/src/tethys/swing/PAMGuardDeploymentsTable.java @@ -5,7 +5,9 @@ import java.awt.Color; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.util.ArrayList; +import java.util.Arrays; +import javax.swing.JCheckBox; import javax.swing.JComponent; import javax.swing.JPanel; import javax.swing.JScrollPane; @@ -39,6 +41,10 @@ public class PAMGuardDeploymentsTable extends TethysGUIPanel { private JPanel mainPanel; private DeploymentOverview deploymentOverview; + + private boolean[] selection = new boolean[0]; + + private ArrayList observers = new ArrayList<>(); public PAMGuardDeploymentsTable(TethysControl tethysControl) { super(tethysControl); @@ -47,7 +53,7 @@ public class PAMGuardDeploymentsTable extends TethysGUIPanel { mainPanel.setBorder(new TitledBorder("PAMGuard recording periods")); tableModel = new TableModel(); table = new JTable(tableModel); - table.setRowSelectionAllowed(true); +// table.setRowSelectionAllowed(true); table.addMouseListener(new TableMouse()); JScrollPane scrollPane = new JScrollPane(table); mainPanel.add(BorderLayout.CENTER, scrollPane); @@ -76,6 +82,18 @@ public class PAMGuardDeploymentsTable extends TethysGUIPanel { } } + @Override + public void mouseClicked(MouseEvent e) { + int aRow = table.getSelectedRow(); + int col = table.getSelectedColumn(); + if (aRow >= 0 && aRow < selection.length && col == 6) { + selection[aRow] = !selection[aRow]; + for (DeploymentTableObserver obs : observers) { + obs.selectionChanged(); + } + } + } + } public void showPopup() { @@ -107,6 +125,24 @@ public class PAMGuardDeploymentsTable extends TethysGUIPanel { */ } + + /** + * Get a list of selected recording periods. + * @return list of selected periods. + */ + public ArrayList getSelectedDeployments() { + if (deploymentOverview == null) { + return null; + } + ArrayList selDeps = new ArrayList<>(); + int n = Math.min(selection.length, deploymentOverview.getRecordingPeriods().size()); + for (int i = 0; i < n; i++) { + if (selection[i]) { + selDeps.add(deploymentOverview.getRecordingPeriods().get(i)); + } + } + return selDeps; + } @Override public void updateState(TethysState tethysState) { @@ -136,15 +172,28 @@ public class PAMGuardDeploymentsTable extends TethysGUIPanel { private void updateDeployments() { DeploymentHandler deploymentHandler = getTethysControl().getDeploymentHandler(); deploymentOverview = deploymentHandler.getDeploymentOverview(); + int n = deploymentOverview.getRecordingPeriods().size(); + if (selection.length < n) { + selection = Arrays.copyOf(selection, n); +// for (int i = 0; i < setDefaultStores.length; i++) { +// if (selectBoxes[i] == null) { +// selectBoxes[i] = new JCheckBox(); +// } +// } + } tableModel.fireTableDataChanged(); // DeploymentData deplData = getTethysControl().getGlobalDeplopymentData(); // ArrayList projectDeployments = getTethysControl().getDbxmlQueries().getProjectDeployments(deplData.getProject()); // deploymentHandler.matchPamguard2Tethys(deploymentOverview, projectDeployments); } + + public void addObserver(DeploymentTableObserver observer) { + observers.add(observer); + } private class TableModel extends AbstractTableModel { - private String[] columnNames = {"Id", "Start", "Stop", "Duration", "Cycle", "Tethys Deployment"}; + private String[] columnNames = {"Id", "Start", "Stop", "Duration", "Cycle", "Tethys Deployment", "Select"}; @Override public int getRowCount() { @@ -165,6 +214,15 @@ public class PAMGuardDeploymentsTable extends TethysGUIPanel { public int getColumnCount() { return columnNames.length; } + + @Override + public Class getColumnClass(int columnIndex) { + if (columnIndex == 6) { + return Boolean.class; +// return JCheckBox.class; + } + return super.getColumnClass(columnIndex); + } @Override public Object getValueAt(int rowIndex, int columnIndex) { @@ -176,6 +234,11 @@ public class PAMGuardDeploymentsTable extends TethysGUIPanel { return getValueAt(period, rowIndex, columnIndex); } + @Override + public boolean isCellEditable(int rowIndex, int columnIndex) { + return columnIndex == 6; + } + private Object getValueAt(RecordingPeriod period, int rowIndex, int columnIndex) { switch (columnIndex) { case 0: @@ -193,6 +256,9 @@ public class PAMGuardDeploymentsTable extends TethysGUIPanel { case 5: PDeployment deployment = period.getMatchedTethysDeployment(); return makeDeplString(period, deployment); + case 6: +// return selectBoxes[rowIndex]; + return selection[rowIndex]; } return null; diff --git a/src/tethys/swing/ProjectDeploymentsDialog.java b/src/tethys/swing/ProjectDeploymentsDialog.java new file mode 100644 index 00000000..fed3041e --- /dev/null +++ b/src/tethys/swing/ProjectDeploymentsDialog.java @@ -0,0 +1,57 @@ +package tethys.swing; + +import java.awt.Window; + +import PamView.dialog.PamDialog; +import tethys.TethysControl; +import tethys.TethysState; +import tethys.TethysState.StateType; + +/** + * Modeless dialog showing all project deployments. + * @author dg50 + * + */ +public class ProjectDeploymentsDialog extends PamDialog { + + private TethysDeploymentsTable deploymentsPanel; + private TethysControl tethysControl; + private static ProjectDeploymentsDialog singleInstance; + + private ProjectDeploymentsDialog(Window parentFrame, TethysControl tethysControl) { + super(parentFrame, "Project deployments", false); + this.tethysControl = tethysControl; + deploymentsPanel = new TethysDeploymentsTable(tethysControl); + setDialogComponent(deploymentsPanel.getComponent()); + setModal(false); + setResizable(true); + getCancelButton().setVisible(false); + } + + public static void showDialog(Window parentFrame, TethysControl tethysControl) { + if (singleInstance == null) { + singleInstance = new ProjectDeploymentsDialog(parentFrame, tethysControl); + } + singleInstance.setVisible(true); + singleInstance.deploymentsPanel.updateState(new TethysState(StateType.NEWPROJECTSELECTION)); +// if (singleInstance.is) + } + + @Override + public boolean getParams() { + // TODO Auto-generated method stub + return true; + } + + @Override + public void cancelButtonPressed() { + // TODO Auto-generated method stub + + } + + @Override + public void restoreDefaultSettings() { + // TODO Auto-generated method stub + + } +} diff --git a/src/tethys/swing/StreamTableObserver.java b/src/tethys/swing/StreamTableObserver.java new file mode 100644 index 00000000..cd0f3b13 --- /dev/null +++ b/src/tethys/swing/StreamTableObserver.java @@ -0,0 +1,9 @@ +package tethys.swing; + +import PamguardMVC.PamDataBlock; + +public interface StreamTableObserver { + + public void selectDataBlock(PamDataBlock dataBlock); + +} diff --git a/src/tethys/swing/TethysConnectionPanel.java b/src/tethys/swing/TethysConnectionPanel.java index c13efd54..95837d6a 100644 --- a/src/tethys/swing/TethysConnectionPanel.java +++ b/src/tethys/swing/TethysConnectionPanel.java @@ -62,6 +62,8 @@ public class TethysConnectionPanel extends TethysGUIPanel { private JButton newInstrument; + private JButton openClient; + public TethysConnectionPanel(TethysControl tethysControl) { super(tethysControl); mainPanel = new WestAlignedPanel(new GridBagLayout()); @@ -71,6 +73,8 @@ public class TethysConnectionPanel extends TethysGUIPanel { serverSelButton.setToolTipText("Select server"); serverStatus = new ScrollingPamLabel(SERVERSTATUSLENGTH); serverName.setEditable(false); + openClient = new JButton("Open Client"); + openClient.setToolTipText("Open Tethys client in web browser"); // serverStatus.setEditable(false); serverSelButton.addActionListener(new ActionListener() { @Override @@ -78,6 +82,12 @@ public class TethysConnectionPanel extends TethysGUIPanel { selectServer(); } }); + openClient.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + tethysControl.openTethysClient(); + } + }); newProjectButton = new JButton("New project"); newProjectButton.setToolTipText("Create new project information"); newProjectButton.addActionListener(new ActionListener() { @@ -121,6 +131,9 @@ public class TethysConnectionPanel extends TethysGUIPanel { c.gridx++; c.gridwidth = 2; mainPanel.add(serverStatus, c); + c.gridx += c.gridwidth; + c.gridwidth = 1; + mainPanel.add(openClient, c); c.gridx =0; c.gridy++; diff --git a/src/tethys/swing/TethysImagePanel.java b/src/tethys/swing/TethysImagePanel.java new file mode 100644 index 00000000..b0a74610 --- /dev/null +++ b/src/tethys/swing/TethysImagePanel.java @@ -0,0 +1,50 @@ +package tethys.swing; + +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Image; + +import javax.swing.ImageIcon; +import javax.swing.JPanel; +import javax.swing.border.BevelBorder; + + +public class TethysImagePanel extends JPanel { + + private static final long serialVersionUID = 1L; + private ImageIcon image; + private int prefWidth; + private int prefHeight; + private int size; + + public TethysImagePanel(int size) { + this.size = size; + image = Images.getTethysImage(); + if (image != null) { + prefWidth = image.getIconWidth(); + prefHeight = image.getIconHeight(); + } +// setBorder(new BevelBorder(BevelBorder.RAISED)); + } + + @Override + protected void paintComponent(Graphics g) { + super.paintComponent(g); + if (image == null) { + return; + } + int inset = 2; + g.drawImage(image.getImage(), inset, inset, getWidth()-inset*2, getHeight()-inset*2, + 0, 0, prefWidth, prefHeight, null); + } + + @Override + public Dimension getPreferredSize() { + return new Dimension(size, size); + } + + + + + +} diff --git a/src/tethys/swing/TethysMainPanel.java b/src/tethys/swing/TethysMainPanel.java index 72e07590..49b01c0b 100644 --- a/src/tethys/swing/TethysMainPanel.java +++ b/src/tethys/swing/TethysMainPanel.java @@ -21,21 +21,39 @@ public class TethysMainPanel extends TethysGUIPanel { private DeploymentsPanel deploymentsPanel; + private DatablockDetectionsPanel datablockDetectionsPanel; + + private DetectionsExportPanel detectionsExportPanel; + public TethysMainPanel(TethysControl tethysControl) { super(tethysControl); this.tethysControl = tethysControl; mainPanel = new JPanel(new BorderLayout()); connectionPanel = new TethysConnectionPanel(tethysControl); + datablockDetectionsPanel = new DatablockDetectionsPanel(tethysControl); datablockSynchPanel = new DatablockSynchPanel(tethysControl); deploymentsPanel = new DeploymentsPanel(tethysControl); + detectionsExportPanel = new DetectionsExportPanel(tethysControl); + datablockSynchPanel.addTableObserver(detectionsExportPanel); + datablockSynchPanel.addTableObserver(datablockDetectionsPanel); - mainPanel.add(BorderLayout.NORTH, connectionPanel.getComponent()); + JSplitPane southwestSplit = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT); + JPanel southEastPanel = new JPanel(new BorderLayout()); + + JPanel northPanel = new JPanel(new BorderLayout()); + northPanel.add(BorderLayout.CENTER, connectionPanel.getComponent()); + northPanel.add(BorderLayout.WEST, new TethysImagePanel(100)); + mainPanel.add(BorderLayout.NORTH, northPanel); JSplitPane splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT); // splitPane.set mainPanel.add(BorderLayout.CENTER, splitPane); // mainPanel.add(BorderLayout.CENTER, datablockSynchPanel.getComponent()); splitPane.add(deploymentsPanel.getComponent()); - splitPane.add(datablockSynchPanel.getComponent()); + southwestSplit.add(datablockSynchPanel.getComponent()); + southwestSplit.add(southEastPanel); + southEastPanel.add(datablockDetectionsPanel.getComponent(), BorderLayout.CENTER); + southEastPanel.add(detectionsExportPanel.getComponent(), BorderLayout.EAST); + splitPane.add(southwestSplit); SwingUtilities.invokeLater(new Runnable() { @Override public void run() { diff --git a/src/tethys/swing/export/DescriptionCard.java b/src/tethys/swing/export/DescriptionCard.java new file mode 100644 index 00000000..13b13ee3 --- /dev/null +++ b/src/tethys/swing/export/DescriptionCard.java @@ -0,0 +1,30 @@ +package tethys.swing.export; + +import java.awt.BorderLayout; + +import PamguardMVC.PamDataBlock; +import tethys.TethysControl; +import tethys.output.StreamExportParams; + +public class DescriptionCard extends ExportWizardCard { + + private DescriptionTypePanel descriptionPanel; + + public DescriptionCard(TethysControl tethysControl, PamDataBlock dataBlock) { + super(tethysControl, "Description", dataBlock); + this.setLayout(new BorderLayout()); + descriptionPanel = new DescriptionTypePanel("Description data", true, true, true); + this.add(BorderLayout.CENTER, descriptionPanel.getMainPanel()); + } + + @Override + public boolean getParams(StreamExportParams streamExportParams) { + return descriptionPanel.getParams(streamExportParams.getDetectionDescription()); + } + + @Override + public void setParams(StreamExportParams streamExportParams) { + descriptionPanel.setParams(streamExportParams.getDetectionDescription()); + } + +} diff --git a/src/tethys/swing/export/DescriptionTypePanel.java b/src/tethys/swing/export/DescriptionTypePanel.java new file mode 100644 index 00000000..2fc968cb --- /dev/null +++ b/src/tethys/swing/export/DescriptionTypePanel.java @@ -0,0 +1,104 @@ +package tethys.swing.export; + +import java.awt.Dimension; +import java.awt.Label; + +import javax.swing.BoxLayout; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JTextArea; +import javax.swing.border.TitledBorder; + +import PamView.dialog.PamDialog; +import nilus.DescriptionType; + +/** + * Panel containing the three test entry fields for nilus.DescriptionType + * @author dg50 + * + */ +public class DescriptionTypePanel { + + private JTextArea tObjectives, tAbstract, tMethod; + + private JPanel mainPanel; + + private boolean requireObjective; + + private boolean requireAbstract; + + private boolean requireMethod; + + private static final int ctrlWidth = 40; + + public DescriptionTypePanel(String bordertitle, boolean requireObjective, boolean requireAbstract, boolean requireMethod) { + this.requireObjective = requireObjective; + this.requireAbstract = requireAbstract; + this.requireMethod = requireMethod; + + mainPanel = new JPanel(); + if (bordertitle != null) { + mainPanel.setBorder(new TitledBorder(bordertitle)); + } + tObjectives = new JTextArea(12, ctrlWidth); + tAbstract = new JTextArea(8, ctrlWidth); + tMethod = new JTextArea(9, ctrlWidth); + + mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.Y_AXIS)); + addScrollablePanel(tObjectives, "Objectives"); + addScrollablePanel(tAbstract, "Abstract"); + addScrollablePanel(tMethod, "Method"); + } + + private void addScrollablePanel(JTextArea textArea, String title) { + // TODO Auto-generated method stub +// mainPanel.add(new Label(title, JLabel.LEFT)); +// textArea.setMinimumSize(new Dimension(200, 200)); + JScrollPane scrollPane = new JScrollPane(textArea, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); + scrollPane.setBorder(new TitledBorder(title)); + scrollPane.setPreferredSize(new Dimension(scrollPane.getPreferredSize().height/2, 0)); + mainPanel.add(scrollPane); + } + + public JPanel getMainPanel() { + return mainPanel; + } + + public void setParams(DescriptionType description) { + if (description == null) { + tObjectives.setText(null); + tAbstract.setText(null); + tMethod.setText(null); + } + } + + public boolean getParams(DescriptionType description) { + if (checkField(requireObjective, tObjectives) == false) { + return PamDialog.showWarning(null, "Objectives", "The objectives field must be competed"); + } + if (checkField(requireAbstract, tAbstract) == false) { + return PamDialog.showWarning(null, "Abstract", "The abstract field must be competed"); + } + if (checkField(requireMethod, tMethod) == false) { + return PamDialog.showWarning(null, "Method", "The method field must be competed"); + } + + description.setObjectives(tObjectives.getText()); + description.setAbstract(tAbstract.getText()); + description.setMethod(tMethod.getText()); + + return true; + } + + private boolean checkField(boolean required, JTextArea field) { + if (required == false) { + return true; + } + String txt = field.getText(); + if (txt == null || txt.length() == 0) { + return false; + } + return true; + } +} diff --git a/src/tethys/swing/export/DetectionsExportWizard.java b/src/tethys/swing/export/DetectionsExportWizard.java new file mode 100644 index 00000000..1e67d67d --- /dev/null +++ b/src/tethys/swing/export/DetectionsExportWizard.java @@ -0,0 +1,146 @@ +package tethys.swing.export; + +import java.awt.BorderLayout; +import java.awt.CardLayout; +import java.awt.Component; +import java.awt.Window; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.ArrayList; + +import javax.swing.JButton; +import javax.swing.JPanel; +import javax.swing.JTextArea; +import javax.swing.border.TitledBorder; + +import PamView.dialog.PamDialog; +import PamguardMVC.PamDataBlock; +import tethys.TethysControl; +import tethys.output.StreamExportParams; + +public class DetectionsExportWizard extends PamDialog { + + private PamDataBlock dataBlock; + private CardLayout cardLayout; + private JPanel mainPanel; + private GranularityCard granularityCard; + private DescriptionCard descriptionCard; + private JButton prevButton; + private StreamExportParams streamExportParams; + + private ArrayList wizardCards = new ArrayList(); + + private DetectionsExportWizard(Window parentFrame, TethysControl tethysControl, PamDataBlock dataBlock) { + super(parentFrame, "Detections Export", false); + this.dataBlock = dataBlock; + cardLayout = new CardLayout(); + mainPanel = new JPanel(cardLayout); + + addCard(granularityCard = new GranularityCard(tethysControl, dataBlock)); + addCard(descriptionCard = new DescriptionCard(tethysControl, dataBlock)); + + streamExportParams = tethysControl.getTethysExportParams().getStreamParams(dataBlock); + + cardLayout.first(mainPanel); + + setDialogComponent(mainPanel); + + getOkButton().setText("Next"); + prevButton = new JButton("Previous"); + getButtonPanel().add(prevButton, 0); + prevButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + previousButton(); + } + }); + + setResizable(true); + } + + private void addCard(ExportWizardCard wizPanel) { + mainPanel.add(wizPanel, wizPanel.getTitle()); + wizardCards.add(wizPanel); + } + + public static void showDilaog(Window parentFrame, TethysControl tethysControl, PamDataBlock dataBlock) { + DetectionsExportWizard wiz = new DetectionsExportWizard(parentFrame, tethysControl, dataBlock); + wiz.setParams(); + wiz.setVisible(true); + } + + private void setParams() { + for (ExportWizardCard wizCard : wizardCards) { + wizCard.setParams(streamExportParams); + } +// granularityCard.setParams(streamExportParams); + } + + /** + * Called when 'previous' button is clicked. + */ + protected void previousButton() { + cardLayout.previous(mainPanel); + enableControls(); + } + + @Override + public boolean getParams() { + int iCard = getCardIndex(); + if (iCard < wizardCards.size()-1) { + if (checkCurrentCard()) { + cardLayout.next(mainPanel); + enableControls(); + } + return false; + } + +// if (cardLayout.) +// cardLayout.next(mainPanel); +// System.out.println(mainPanel.getComponent(0).isShowing()); + /* + * there seems to be no obvious way of knowing which card is showing except + * to go through and see which one has isShowing() == true, then test for first and + * last, etc. + */ + enableControls(); + return false; + } + + @Override + public void cancelButtonPressed() { + // TODO Auto-generated method stub + + } + + @Override + public void restoreDefaultSettings() { + // TODO Auto-generated method stub + + } + + private void enableControls() { + int iCard = getCardIndex(); + prevButton.setEnabled(iCard > 0); + boolean isLast = iCard == wizardCards.size()-1; + getOkButton().setText(isLast ? "Export" : "Next"); + } + + private boolean checkCurrentCard() { + int iCard = getCardIndex(); + if (iCard < 0) { + return true; + } + return wizardCards.get(iCard).getParams(streamExportParams); + } + + private int getCardIndex() { + for (int i = 0; i < mainPanel.getComponentCount(); i++) { + Component component = mainPanel.getComponent(i); + if (component.isVisible()) { + return i; + } + } + return -1; + } +} diff --git a/src/tethys/swing/export/ExportWizardCard.java b/src/tethys/swing/export/ExportWizardCard.java new file mode 100644 index 00000000..f81c7b12 --- /dev/null +++ b/src/tethys/swing/export/ExportWizardCard.java @@ -0,0 +1,43 @@ +package tethys.swing.export; + +import javax.swing.JPanel; + +import PamguardMVC.PamDataBlock; +import tethys.TethysControl; +import tethys.output.StreamExportParams; + +/** + * Slightly standardised panels to put into the export wizard + * so that it's easy to work out which 'card' we're on, etc. + * @author dg50 + * + */ +abstract class ExportWizardCard extends JPanel { + + private String title; + private PamDataBlock dataBlock; + private TethysControl tethysControl; + + public ExportWizardCard(TethysControl tethysControl, String title, PamDataBlock dataBlock) { + this.tethysControl = tethysControl; + this.title = title; + this.dataBlock = dataBlock; + } + + public PamDataBlock getDataBlock() { + return dataBlock; + } + + public TethysControl getTethysControl() { + return tethysControl; + } + + public abstract boolean getParams(StreamExportParams streamExportParams); + + public abstract void setParams(StreamExportParams streamExportParams); + + public String getTitle() { + return title; + } + +} diff --git a/src/tethys/swing/export/GranularityCard.java b/src/tethys/swing/export/GranularityCard.java new file mode 100644 index 00000000..768119aa --- /dev/null +++ b/src/tethys/swing/export/GranularityCard.java @@ -0,0 +1,144 @@ +package tethys.swing.export; + +import java.awt.BorderLayout; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +import javax.swing.BoxLayout; +import javax.swing.ButtonGroup; +import javax.swing.JButton; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JRadioButton; +import javax.swing.JScrollPane; +import javax.swing.JTextArea; +import javax.swing.JTextField; +import javax.swing.border.TitledBorder; + +import org.w3c.dom.Document; + +import PamController.settings.output.xml.PamguardXMLWriter; +import PamView.dialog.PamGridBagContraints; +import PamguardMVC.PamDataBlock; +import PamguardMVC.dataSelector.DataSelectParams; +import PamguardMVC.dataSelector.DataSelector; +import PamguardMVC.dataSelector.DataSelectorChangeListener; +import nilus.GranularityEnumType; +import tethys.TethysControl; +import tethys.niluswraps.PGranularityType; +import tethys.output.StreamExportParams; + +public class GranularityCard extends ExportWizardCard { + + private JRadioButton[] granularities; + + private JTextArea dataSelectionText; + + private JTextField binLength, encounterGap; + + private DataSelector dataSelector; + + public GranularityCard(TethysControl tethysControl, PamDataBlock dataBlock) { + super(tethysControl, "Granularity", dataBlock); + setLayout(new BoxLayout(this, BoxLayout.Y_AXIS)); + + // granularity + GranularityEnumType[] grans = GranularityEnumType.values(); + granularities = new JRadioButton[grans.length]; + JPanel granPanel = new JPanel(new GridBagLayout()); + GridBagConstraints c = new PamGridBagContraints(); + granPanel.setBorder(new TitledBorder("Granularity")); + ButtonGroup granGroup = new ButtonGroup(); + for (int i = 0; i < grans.length; i++) { + c.gridx = 0; + granularities[i] = new JRadioButton(PGranularityType.prettyString(grans[i])); + granularities[i].setToolTipText(PGranularityType.toolTip(grans[i])); + granPanel.add(granularities[i], c); + granGroup.add(granularities[i]); + if (grans[i] == GranularityEnumType.BINNED) { + c.gridx++; + granPanel.add(new JLabel(" bin duration ", JLabel.RIGHT), c); + c.gridx++; + granPanel.add(binLength = new JTextField(5), c); + c.gridx++; + granPanel.add(new JLabel(" (s) ", JLabel.LEFT), c); + + } + if (grans[i] == GranularityEnumType.ENCOUNTER) { + c.gridx++; + granPanel.add(new JLabel(" min gap ", JLabel.RIGHT), c); + c.gridx++; + granPanel.add(encounterGap = new JTextField(5), c); + c.gridx++; + granPanel.add(new JLabel(" (s) ", JLabel.LEFT), c); + + } + c.gridy++; + } + this.add(granPanel); + + // data selection + dataSelector = dataBlock.getDataSelector(tethysControl.getDataSelectName(), false); + if (dataSelector != null) { + dataSelectionText = new JTextArea(8, 40); + JPanel dataPanel = new JPanel(new BorderLayout()); + JPanel nPanel = new JPanel(new BorderLayout()); + dataPanel.add(BorderLayout.NORTH, nPanel); + JButton selectorButton = dataSelector.getDialogButton(tethysControl.getGuiFrame(), new DataSelectorChangeListener() { + @Override + public void selectorChange(DataSelector changedSelector) { + newDataSelection(); + } + }); + nPanel.add(BorderLayout.EAST, selectorButton); + newDataSelection(); + nPanel.add(BorderLayout.CENTER, new JLabel("Data selection filter ", JLabel.RIGHT)); + dataPanel.setBorder(new TitledBorder("Data selection filter")); + JScrollPane sp = new JScrollPane(dataSelectionText, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED); + dataPanel.add(BorderLayout.CENTER, sp); + this.add(dataPanel); + } + + } + + protected void newDataSelection() { + if (dataSelector == null) { + return; + } + DataSelectParams params = dataSelector.getParams(); + if (params == null) { + return; + } + if (params.getCombinationFlag() == 2) { + dataSelectionText.setText("Not enabled"); + return; + } + String txt = dataSelector.getDescription(); + dataSelectionText.setText(txt); + } + + @Override + public boolean getParams(StreamExportParams streamExportParams) { + GranularityEnumType[] grans = GranularityEnumType.values(); + for (int i = 0; i < grans.length; i++) { + if (granularities[i].isSelected()) { + streamExportParams.granularity = grans[i]; + break; + } + } + + return streamExportParams.granularity != null; + } + + @Override + public void setParams(StreamExportParams streamExportParams) { + GranularityEnumType[] grans = GranularityEnumType.values(); + for (int i = 0; i < grans.length; i++) { + granularities[i].setSelected(streamExportParams.granularity == grans[i]); + } + newDataSelection(); + } + +}