From aff032c66d4086ec3fa46708116061d22953d778 Mon Sep 17 00:00:00 2001 From: NuwanSameera Date: Tue, 2 Feb 2016 16:13:10 +0530 Subject: [PATCH] Add current sensor device type sample --- .../currentsensor/component/agent/pom.xml | 59 + .../agent/src/main/webapp/WEB-INF/web.xml | 23 + .../component/agent/src/main/webapp/index.jsp | 22 + .../component/controller/pom.xml | 59 + .../CurrentSensorControllerService.java | 124 ++ .../org/homeautomation/dto/DeviceJSON.java | 36 + .../util/CurrentSensorServiceUtils.java | 53 + .../src/main/webapp/WEB-INF/cxf-servlet.xml | 38 + .../src/main/webapp/WEB-INF/web.xml | 60 + .../currentsensor/component/manager/pom.xml | 60 + .../CurrentSensorManagerService.java | 255 ++++ .../webapp/META-INF/webapp-classloading.xml | 33 + .../src/main/webapp/WEB-INF/cxf-servlet.xml | 38 + .../manager/src/main/webapp/WEB-INF/web.xml | 58 + .../currentsensor/component/plugin/pom.xml | 73 + .../constants/CurrentSensorConstants.java | 26 + .../plugin/impl/CurrentSensorManager.java | 277 ++++ .../impl/CurrentSensorManagerService.java | 92 ++ .../plugin/impl/dao/CurrentSensorDAO.java | 124 ++ .../dao/impl/CurrentSensorDeviceDAOImpl.java | 237 ++++ .../plugin/impl/util/CurrentSensorUtils.java | 45 + .../plugin/internal/ServiceComponent.java | 21 + .../samples/currentsensor/component/pom.xml | 243 ++++ .../EventReceiver_current.xml | 8 + .../Eventreceiver_current_1.0.0/artifact.xml | 4 + .../Eventstore_current_1.0.0/artifact.xml | 4 + .../org_wso2_iot_devices_current.xml | 44 + .../Eventstream_current_1.0.0/artifact.xml | 5 + .../org.wso2.iot.devices.current_1.0.0.json | 20 + .../Current_Sensor_Script.xml | 13 + .../Current/Sparkscripts_1.0.0/artifact.xml | 4 + .../feature/analytics/Current/artifacts.xml | 11 + .../currentsensor/feature/analytics/build.xml | 19 + .../currentsensor/feature/analytics/pom.xml | 66 + .../currentsensor/feature/feature/pom.xml | 220 +++ .../src/main/resources/agent/Connect.ino | 157 +++ .../src/main/resources/agent/CurrentSensor.h | 69 + .../main/resources/agent/CurrentSensor.ino | 67 + .../src/main/resources/agent/PushData.ino | 105 ++ .../main/resources/agent/sketch.properties | 16 + .../src/main/resources/build.properties | 18 + .../main/resources/configs/currentsensor.json | 36 + .../main/resources/configs/currentsensor.xml | 24 + .../datasources/currentsensor-datasources.xml | 46 + .../src/main/resources/dbscripts/h2.sql | 11 + .../src/main/resources/dbscripts/mysql.sql | 12 + .../device-view.hbs | 104 ++ .../device-view.js | 38 + .../device-view.json | 3 + .../public/images/current-sensor.png | Bin 0 -> 135833 bytes .../public/images/current-sensor.png | Bin 0 -> 135833 bytes .../public/images/display-icon.png | Bin 0 -> 4963 bytes .../public/images/myDevices_analytics.png | Bin 0 -> 195921 bytes .../public/images/schematicsGuide.png | Bin 0 -> 393114 bytes .../public/images/thumb.png | Bin 0 -> 135833 bytes .../public/js/download.js | 181 +++ .../public/js/jquery.validate.js | 1220 +++++++++++++++++ .../type-view.hbs | 296 ++++ .../type-view.json | 3 + .../feature/feature/src/main/resources/p2.inf | 16 + modules/samples/currentsensor/feature/pom.xml | 33 + modules/samples/currentsensor/pom.xml | 250 ++++ 62 files changed, 5179 insertions(+) create mode 100644 modules/samples/currentsensor/component/agent/pom.xml create mode 100644 modules/samples/currentsensor/component/agent/src/main/webapp/WEB-INF/web.xml create mode 100644 modules/samples/currentsensor/component/agent/src/main/webapp/index.jsp create mode 100644 modules/samples/currentsensor/component/controller/pom.xml create mode 100644 modules/samples/currentsensor/component/controller/src/main/java/org/homeautomation/CurrentSensorControllerService.java create mode 100644 modules/samples/currentsensor/component/controller/src/main/java/org/homeautomation/dto/DeviceJSON.java create mode 100644 modules/samples/currentsensor/component/controller/src/main/java/org/homeautomation/util/CurrentSensorServiceUtils.java create mode 100644 modules/samples/currentsensor/component/controller/src/main/webapp/WEB-INF/cxf-servlet.xml create mode 100644 modules/samples/currentsensor/component/controller/src/main/webapp/WEB-INF/web.xml create mode 100644 modules/samples/currentsensor/component/manager/pom.xml create mode 100644 modules/samples/currentsensor/component/manager/src/main/java/org/homeautomation/CurrentSensorManagerService.java create mode 100644 modules/samples/currentsensor/component/manager/src/main/webapp/META-INF/webapp-classloading.xml create mode 100644 modules/samples/currentsensor/component/manager/src/main/webapp/WEB-INF/cxf-servlet.xml create mode 100644 modules/samples/currentsensor/component/manager/src/main/webapp/WEB-INF/web.xml create mode 100644 modules/samples/currentsensor/component/plugin/pom.xml create mode 100644 modules/samples/currentsensor/component/plugin/src/main/java/org/homeautomation/currentsensor/plugin/constants/CurrentSensorConstants.java create mode 100644 modules/samples/currentsensor/component/plugin/src/main/java/org/homeautomation/currentsensor/plugin/impl/CurrentSensorManager.java create mode 100644 modules/samples/currentsensor/component/plugin/src/main/java/org/homeautomation/currentsensor/plugin/impl/CurrentSensorManagerService.java create mode 100644 modules/samples/currentsensor/component/plugin/src/main/java/org/homeautomation/currentsensor/plugin/impl/dao/CurrentSensorDAO.java create mode 100644 modules/samples/currentsensor/component/plugin/src/main/java/org/homeautomation/currentsensor/plugin/impl/dao/impl/CurrentSensorDeviceDAOImpl.java create mode 100644 modules/samples/currentsensor/component/plugin/src/main/java/org/homeautomation/currentsensor/plugin/impl/util/CurrentSensorUtils.java create mode 100644 modules/samples/currentsensor/component/plugin/src/main/java/org/homeautomation/currentsensor/plugin/internal/ServiceComponent.java create mode 100644 modules/samples/currentsensor/component/pom.xml create mode 100644 modules/samples/currentsensor/feature/analytics/Current/Eventreceiver_current_1.0.0/EventReceiver_current.xml create mode 100644 modules/samples/currentsensor/feature/analytics/Current/Eventreceiver_current_1.0.0/artifact.xml create mode 100644 modules/samples/currentsensor/feature/analytics/Current/Eventstore_current_1.0.0/artifact.xml create mode 100644 modules/samples/currentsensor/feature/analytics/Current/Eventstore_current_1.0.0/org_wso2_iot_devices_current.xml create mode 100644 modules/samples/currentsensor/feature/analytics/Current/Eventstream_current_1.0.0/artifact.xml create mode 100644 modules/samples/currentsensor/feature/analytics/Current/Eventstream_current_1.0.0/org.wso2.iot.devices.current_1.0.0.json create mode 100644 modules/samples/currentsensor/feature/analytics/Current/Sparkscripts_1.0.0/Current_Sensor_Script.xml create mode 100644 modules/samples/currentsensor/feature/analytics/Current/Sparkscripts_1.0.0/artifact.xml create mode 100644 modules/samples/currentsensor/feature/analytics/Current/artifacts.xml create mode 100644 modules/samples/currentsensor/feature/analytics/build.xml create mode 100644 modules/samples/currentsensor/feature/analytics/pom.xml create mode 100644 modules/samples/currentsensor/feature/feature/pom.xml create mode 100644 modules/samples/currentsensor/feature/feature/src/main/resources/agent/Connect.ino create mode 100644 modules/samples/currentsensor/feature/feature/src/main/resources/agent/CurrentSensor.h create mode 100644 modules/samples/currentsensor/feature/feature/src/main/resources/agent/CurrentSensor.ino create mode 100644 modules/samples/currentsensor/feature/feature/src/main/resources/agent/PushData.ino create mode 100644 modules/samples/currentsensor/feature/feature/src/main/resources/agent/sketch.properties create mode 100644 modules/samples/currentsensor/feature/feature/src/main/resources/build.properties create mode 100644 modules/samples/currentsensor/feature/feature/src/main/resources/configs/currentsensor.json create mode 100644 modules/samples/currentsensor/feature/feature/src/main/resources/configs/currentsensor.xml create mode 100644 modules/samples/currentsensor/feature/feature/src/main/resources/datasources/currentsensor-datasources.xml create mode 100644 modules/samples/currentsensor/feature/feature/src/main/resources/dbscripts/h2.sql create mode 100644 modules/samples/currentsensor/feature/feature/src/main/resources/dbscripts/mysql.sql create mode 100644 modules/samples/currentsensor/feature/feature/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.device.type.currentsensor.device-view/device-view.hbs create mode 100644 modules/samples/currentsensor/feature/feature/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.device.type.currentsensor.device-view/device-view.js create mode 100644 modules/samples/currentsensor/feature/feature/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.device.type.currentsensor.device-view/device-view.json create mode 100644 modules/samples/currentsensor/feature/feature/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.device.type.currentsensor.device-view/public/images/current-sensor.png create mode 100644 modules/samples/currentsensor/feature/feature/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.device.type.currentsensor.type-view/public/images/current-sensor.png create mode 100644 modules/samples/currentsensor/feature/feature/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.device.type.currentsensor.type-view/public/images/display-icon.png create mode 100644 modules/samples/currentsensor/feature/feature/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.device.type.currentsensor.type-view/public/images/myDevices_analytics.png create mode 100644 modules/samples/currentsensor/feature/feature/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.device.type.currentsensor.type-view/public/images/schematicsGuide.png create mode 100644 modules/samples/currentsensor/feature/feature/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.device.type.currentsensor.type-view/public/images/thumb.png create mode 100644 modules/samples/currentsensor/feature/feature/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.device.type.currentsensor.type-view/public/js/download.js create mode 100644 modules/samples/currentsensor/feature/feature/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.device.type.currentsensor.type-view/public/js/jquery.validate.js create mode 100644 modules/samples/currentsensor/feature/feature/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.device.type.currentsensor.type-view/type-view.hbs create mode 100644 modules/samples/currentsensor/feature/feature/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.device.type.currentsensor.type-view/type-view.json create mode 100644 modules/samples/currentsensor/feature/feature/src/main/resources/p2.inf create mode 100644 modules/samples/currentsensor/feature/pom.xml create mode 100644 modules/samples/currentsensor/pom.xml diff --git a/modules/samples/currentsensor/component/agent/pom.xml b/modules/samples/currentsensor/component/agent/pom.xml new file mode 100644 index 00000000..004da2eb --- /dev/null +++ b/modules/samples/currentsensor/component/agent/pom.xml @@ -0,0 +1,59 @@ + + + + org.homeautomation + component + 1.9.2-SNAPSHOT + ../pom.xml + + 4.0.0 + ${groupId}.currentsensor.agent + 1.9.2-SNAPSHOT + ${groupId}.currentsensor.agent + war + + + junit + junit + ${junit.version} + test + + + + + + org.apache.maven.plugins + maven-compiler-plugin + ${maven-compiler-plugin.version} + + ${wso2.maven.compiler.source} + ${wso2.maven.compiler.target} + + + + maven-war-plugin + ${maven-war-plugin.version} + + ${groupId}.currentsensor.agent_agent + + + + + \ No newline at end of file diff --git a/modules/samples/currentsensor/component/agent/src/main/webapp/WEB-INF/web.xml b/modules/samples/currentsensor/component/agent/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 00000000..f39e4103 --- /dev/null +++ b/modules/samples/currentsensor/component/agent/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,23 @@ + + + Sample-Agent-Webapp + diff --git a/modules/samples/currentsensor/component/agent/src/main/webapp/index.jsp b/modules/samples/currentsensor/component/agent/src/main/webapp/index.jsp new file mode 100644 index 00000000..fa3b38f0 --- /dev/null +++ b/modules/samples/currentsensor/component/agent/src/main/webapp/index.jsp @@ -0,0 +1,22 @@ +<%--/* +* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. +* +* WSO2 Inc. licenses this file to you under the Apache License, +* Version 2.0 (the "License"); you may not use this file except +* in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/--%> + + +

Hello World!

+ + \ No newline at end of file diff --git a/modules/samples/currentsensor/component/controller/pom.xml b/modules/samples/currentsensor/component/controller/pom.xml new file mode 100644 index 00000000..67fb79f3 --- /dev/null +++ b/modules/samples/currentsensor/component/controller/pom.xml @@ -0,0 +1,59 @@ + + + + org.homeautomation + component + 1.9.2-SNAPSHOT + ../pom.xml + + 4.0.0 + ${groupId}.currentsensor.controller + 1.9.2-SNAPSHOT + war + ${groupId}.currentsensor.controller API + http://wso2.com + + + + org.apache.maven.plugins + maven-compiler-plugin + ${maven-compiler-plugin.version} + + UTF-8 + ${wso2.maven.compiler.source} + ${wso2.maven.compiler.target} + + + + maven-war-plugin + ${maven-war-plugin.version} + + ${groupId}.currentsensor.controller + + + + + + + org.homeautomation + ${project-base-package}.plugin + + + \ No newline at end of file diff --git a/modules/samples/currentsensor/component/controller/src/main/java/org/homeautomation/CurrentSensorControllerService.java b/modules/samples/currentsensor/component/controller/src/main/java/org/homeautomation/CurrentSensorControllerService.java new file mode 100644 index 00000000..567cb301 --- /dev/null +++ b/modules/samples/currentsensor/component/controller/src/main/java/org/homeautomation/CurrentSensorControllerService.java @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.homeautomation; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.wso2.carbon.apimgt.annotations.api.API; +import org.wso2.carbon.apimgt.annotations.device.DeviceType; +import org.wso2.carbon.apimgt.annotations.device.feature.Feature; +import org.wso2.carbon.device.mgt.iot.DeviceManagement; +import org.wso2.carbon.device.mgt.iot.currentsensor.controller.api.dto.DeviceJSON; +import org.wso2.carbon.device.mgt.iot.currentsensor.controller.api.util.CurrentSensorServiceUtils; +import org.wso2.carbon.device.mgt.iot.currentsensor.plugin.constants.CurrentSensorConstants; +import org.wso2.carbon.device.mgt.iot.exception.DeviceControllerException; +import org.wso2.carbon.device.mgt.iot.sensormgt.SensorDataManager; +import org.wso2.carbon.device.mgt.iot.sensormgt.SensorRecord; + +import javax.servlet.http.HttpServletResponse; +import javax.ws.rs.*; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import java.util.Calendar; + +@API(name = "currentsensor", version = "1.0.0", context = "/currentsensor") +@DeviceType(value = "currentsensor") +public class CurrentSensorControllerService { + + + private static Log log = LogFactory.getLog(CurrentSensorControllerService.class); + + private boolean waitForServerStartup() { + while (!DeviceManagement.isServerReady()) { + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + return true; + } + } + return false; + } + + /** + * @param owner + * @param deviceId + * @param protocol + * @param response + * @return + */ + @Path("controller/read-current") + @GET + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + @Feature( code="read-current", name="Current", type="monitor", + description="Request current reading from Arduino agent") + public SensorRecord requestCurrent(@HeaderParam("owner") String owner, + @HeaderParam("deviceId") String deviceId, + @HeaderParam("protocol") String protocol, + @Context HttpServletResponse response) { + SensorRecord sensorRecord = null; + + try { + sensorRecord = SensorDataManager.getInstance().getSensorRecord(deviceId, + CurrentSensorConstants.SENSOR_CURRENT); + } catch ( DeviceControllerException e) { + response.setStatus(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode()); + } + + response.setStatus(Response.Status.OK.getStatusCode()); + return sensorRecord; + } + + /** + * @param dataMsg + * @param response + */ + @Path("controller/pushcurrent") + @POST + @Consumes(MediaType.APPLICATION_JSON) + public void pushCurrent(final DeviceJSON dataMsg, @Context HttpServletResponse response) { + + String owner = dataMsg.owner; + String deviceId = dataMsg.deviceId; + float pinData = dataMsg.value; + + SensorDataManager.getInstance().setSensorRecord(deviceId, CurrentSensorConstants.SENSOR_CURRENT, + String.valueOf(pinData), + Calendar.getInstance().getTimeInMillis()); + + SensorDataManager.getInstance().setSensorRecord(deviceId, CurrentSensorConstants.SENSOR_POWER, + String.valueOf(pinData * 230), + Calendar.getInstance().getTimeInMillis()); + + + if (!CurrentSensorServiceUtils.publishToDAS(dataMsg.owner, dataMsg.deviceId, dataMsg.value)) { + response.setStatus(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode()); + log.warn("An error occured whilst trying to publish pin data of Current Sensor Data with ID [" + deviceId + + "] of owner [" + owner + "]"); + } + + if (!CurrentSensorServiceUtils.publishToDAS(dataMsg.owner, dataMsg.deviceId, dataMsg.value * 230)) { + response.setStatus(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode()); + log.warn("An error occured whilst trying to publish pin data of Current Sensor Data with ID [" + deviceId + + "] of owner [" + owner + "]"); + } + } + +} diff --git a/modules/samples/currentsensor/component/controller/src/main/java/org/homeautomation/dto/DeviceJSON.java b/modules/samples/currentsensor/component/controller/src/main/java/org/homeautomation/dto/DeviceJSON.java new file mode 100644 index 00000000..41a04e90 --- /dev/null +++ b/modules/samples/currentsensor/component/controller/src/main/java/org/homeautomation/dto/DeviceJSON.java @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.homeautomation.dto; + +import org.codehaus.jackson.annotate.JsonIgnoreProperties; + +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; + +@XmlRootElement + +@JsonIgnoreProperties(ignoreUnknown = true) +public class DeviceJSON { + @XmlElement(required = true) public String owner; + @XmlElement(required = true) public String deviceId; + @XmlElement(required = true) public String reply; + @XmlElement public Long time; + @XmlElement public String key; + @XmlElement public float value; +} diff --git a/modules/samples/currentsensor/component/controller/src/main/java/org/homeautomation/util/CurrentSensorServiceUtils.java b/modules/samples/currentsensor/component/controller/src/main/java/org/homeautomation/util/CurrentSensorServiceUtils.java new file mode 100644 index 00000000..e2546420 --- /dev/null +++ b/modules/samples/currentsensor/component/controller/src/main/java/org/homeautomation/util/CurrentSensorServiceUtils.java @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.homeautomation.util; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.wso2.carbon.context.PrivilegedCarbonContext; +import org.wso2.carbon.device.mgt.analytics.exception.DataPublisherConfigurationException; +import org.wso2.carbon.device.mgt.analytics.service.DeviceAnalyticsService; +import org.wso2.carbon.device.mgt.iot.currentsensor.plugin.constants.CurrentSensorConstants; + +public class CurrentSensorServiceUtils { + private static final Log log = LogFactory.getLog(CurrentSensorServiceUtils.class); + + //TODO; replace this tenant domain + private static final String SUPER_TENANT = "carbon.super"; + private static final String CURRENT_STREAM_DEFINITION = "org.wso2.iot.devices.current"; + + public static boolean publishToDAS(String owner, String deviceId, float current) { + PrivilegedCarbonContext.startTenantFlow(); + PrivilegedCarbonContext ctx = PrivilegedCarbonContext.getThreadLocalCarbonContext(); + ctx.setTenantDomain(SUPER_TENANT, true); + DeviceAnalyticsService deviceAnalyticsService = (DeviceAnalyticsService) ctx.getOSGiService( + DeviceAnalyticsService.class, null); + Object metdaData[] = {owner, CurrentSensorConstants.DEVICE_TYPE, deviceId, System.currentTimeMillis()}; + Object payloadData[] = {current}; + + try { + deviceAnalyticsService.publishEvent(CURRENT_STREAM_DEFINITION, "1.0.0", metdaData, new Object[0], payloadData); + } catch (DataPublisherConfigurationException e) { + return false; + } finally { + PrivilegedCarbonContext.endTenantFlow(); + } + return true; + } +} diff --git a/modules/samples/currentsensor/component/controller/src/main/webapp/WEB-INF/cxf-servlet.xml b/modules/samples/currentsensor/component/controller/src/main/webapp/WEB-INF/cxf-servlet.xml new file mode 100644 index 00000000..a8dbfe8a --- /dev/null +++ b/modules/samples/currentsensor/component/controller/src/main/webapp/WEB-INF/cxf-servlet.xml @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + diff --git a/modules/samples/currentsensor/component/controller/src/main/webapp/WEB-INF/web.xml b/modules/samples/currentsensor/component/controller/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 00000000..d5258879 --- /dev/null +++ b/modules/samples/currentsensor/component/controller/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,60 @@ + + + + Current-Sensor-Agent-Webapp + + JAX-WS/JAX-RS IOT Current Sensor Endpoint + JAX-WS/JAX-RS Servlet + CXFServlet + + org.apache.cxf.transport.servlet.CXFServlet + + 1 + + + CXFServlet + /* + + + + + managed-api-enabled + true + + + managed-api-owner + admin + + + managed-api-context-template + /currentsensor/{version} + + + managed-api-application + currentsensor + + + managed-api-isSecured + true + + + diff --git a/modules/samples/currentsensor/component/manager/pom.xml b/modules/samples/currentsensor/component/manager/pom.xml new file mode 100644 index 00000000..a0e3a1bb --- /dev/null +++ b/modules/samples/currentsensor/component/manager/pom.xml @@ -0,0 +1,60 @@ + + + + org.homeautomation + component + 1.9.2-SNAPSHOT + ../pom.xml + + 4.0.0 + ${groupId}.currentsensor.manager + war + 1.9.2-SNAPSHOT + ${groupId}.currentsensor.manager + http://wso2.org + + ${basedir}/src/main/java + + + org.apache.maven.plugins + maven-compiler-plugin + ${maven-compiler-plugin.version} + + UTF-8 + ${wso2.maven.compiler.source} + ${wso2.maven.compiler.target} + + + + maven-war-plugin + ${maven-war-plugin.version} + + ${groupId}.currentsensor.manager_mgt + + + + + + + org.homeautomation + ${project-base-package}.plugin + + + \ No newline at end of file diff --git a/modules/samples/currentsensor/component/manager/src/main/java/org/homeautomation/CurrentSensorManagerService.java b/modules/samples/currentsensor/component/manager/src/main/java/org/homeautomation/CurrentSensorManagerService.java new file mode 100644 index 00000000..5519aafe --- /dev/null +++ b/modules/samples/currentsensor/component/manager/src/main/java/org/homeautomation/CurrentSensorManagerService.java @@ -0,0 +1,255 @@ +/* + * Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.homeautomation; + +import org.apache.commons.io.FileUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.wso2.carbon.apimgt.annotations.device.DeviceType; +import org.wso2.carbon.apimgt.webapp.publisher.KeyGenerationUtil; +import org.wso2.carbon.device.mgt.common.Device; +import org.wso2.carbon.device.mgt.common.DeviceIdentifier; +import org.wso2.carbon.device.mgt.common.DeviceManagementException; +import org.wso2.carbon.device.mgt.common.EnrolmentInfo; +import org.wso2.carbon.device.mgt.iot.DeviceManagement; +import org.wso2.carbon.device.mgt.iot.apimgt.AccessTokenInfo; +import org.wso2.carbon.device.mgt.iot.apimgt.TokenClient; +import org.wso2.carbon.device.mgt.iot.currentsensor.plugin.constants.CurrentSensorConstants; +import org.wso2.carbon.device.mgt.iot.exception.AccessTokenException; +import org.wso2.carbon.device.mgt.iot.exception.DeviceControllerException; +import org.wso2.carbon.device.mgt.iot.util.ZipArchive; +import org.wso2.carbon.device.mgt.iot.util.ZipUtil; + +import javax.servlet.http.HttpServletResponse; +import javax.ws.rs.*; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import java.io.IOException; +import java.nio.ByteBuffer; +import java.nio.charset.StandardCharsets; +import java.util.Date; +import java.util.UUID; + +@DeviceType(value = "currentsensor") +public class CurrentSensorManagerService { + + private static Log log = LogFactory.getLog(CurrentSensorManagerService.class); + //TODO; replace this tenant domain + private final String SUPER_TENANT = "carbon.super"; + @Context //injected response proxy supporting multiple thread + private HttpServletResponse response; + + @Path("manager/device/register") + @PUT + public boolean register(@QueryParam("deviceId") String deviceId, + @QueryParam("name") String name, @QueryParam("owner") String owner) { + + DeviceManagement deviceManagement = new DeviceManagement(SUPER_TENANT); + + DeviceIdentifier deviceIdentifier = new DeviceIdentifier(); + deviceIdentifier.setId(deviceId); + deviceIdentifier.setType(CurrentSensorConstants.DEVICE_TYPE); + try { + if (deviceManagement.getDeviceManagementService().isEnrolled(deviceIdentifier)) { + response.setStatus(Response.Status.CONFLICT.getStatusCode()); + return false; + } + + Device device = new Device(); + device.setDeviceIdentifier(deviceId); + EnrolmentInfo enrolmentInfo = new EnrolmentInfo(); + enrolmentInfo.setDateOfEnrolment(new Date().getTime()); + enrolmentInfo.setDateOfLastUpdate(new Date().getTime()); + enrolmentInfo.setStatus(EnrolmentInfo.Status.ACTIVE); + enrolmentInfo.setOwnership(EnrolmentInfo.OwnerShip.BYOD); + device.setName(name); + device.setType(CurrentSensorConstants.DEVICE_TYPE); + enrolmentInfo.setOwner(owner); + device.setEnrolmentInfo(enrolmentInfo); + boolean added = deviceManagement.getDeviceManagementService().enrollDevice(device); + if (added) { + response.setStatus(Response.Status.OK.getStatusCode()); + } else { + response.setStatus(Response.Status.NOT_ACCEPTABLE.getStatusCode()); + } + + return added; + } catch (DeviceManagementException e) { + response.setStatus(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode()); + return false; + } finally { + deviceManagement.endTenantFlow(); + } + } + + @Path("manager/device/remove/{device_id}") + @DELETE + public void removeDevice(@PathParam("device_id") String deviceId, + @Context HttpServletResponse response) { + + DeviceManagement deviceManagement = new DeviceManagement(SUPER_TENANT); + DeviceIdentifier deviceIdentifier = new DeviceIdentifier(); + deviceIdentifier.setId(deviceId); + deviceIdentifier.setType(CurrentSensorConstants.DEVICE_TYPE); + try { + boolean removed = deviceManagement.getDeviceManagementService().disenrollDevice( + deviceIdentifier); + if (removed) { + response.setStatus(Response.Status.OK.getStatusCode()); + } else { + response.setStatus(Response.Status.NOT_ACCEPTABLE.getStatusCode()); + } + } catch (DeviceManagementException e) { + response.setStatus(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode()); + } finally { + deviceManagement.endTenantFlow(); + } + } + + @Path("manager/device/update/{device_id}") + @POST + public boolean updateDevice(@PathParam("device_id") String deviceId, + @QueryParam("name") String name, + @Context HttpServletResponse response) { + + DeviceManagement deviceManagement = new DeviceManagement(SUPER_TENANT); + + DeviceIdentifier deviceIdentifier = new DeviceIdentifier(); + deviceIdentifier.setId(deviceId); + deviceIdentifier.setType(CurrentSensorConstants.DEVICE_TYPE); + try { + Device device = deviceManagement.getDeviceManagementService().getDevice(deviceIdentifier); + device.setDeviceIdentifier(deviceId); + + // device.setDeviceTypeId(deviceTypeId); + device.getEnrolmentInfo().setDateOfLastUpdate(new Date().getTime()); + + device.setName(name); + device.setType(CurrentSensorConstants.DEVICE_TYPE); + + boolean updated = deviceManagement.getDeviceManagementService().modifyEnrollment(device); + + if (updated) { + response.setStatus(Response.Status.OK.getStatusCode()); + + } else { + response.setStatus(Response.Status.NOT_ACCEPTABLE.getStatusCode()); + } + return updated; + } catch (DeviceManagementException e) { + log.error(e.getErrorMessage()); + return false; + } finally { + deviceManagement.endTenantFlow(); + } + } + + @Path("manager/device/{device_id}") + @GET + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + public Device getDevice(@PathParam("device_id") String deviceId) { + + DeviceManagement deviceManagement = new DeviceManagement(SUPER_TENANT); + DeviceIdentifier deviceIdentifier = new DeviceIdentifier(); + deviceIdentifier.setId(deviceId); + deviceIdentifier.setType(CurrentSensorConstants.DEVICE_TYPE); + + try { + return deviceManagement.getDeviceManagementService().getDevice(deviceIdentifier); + } catch (DeviceManagementException ex) { + log.error("Error occurred while retrieving device with Id " + deviceId + "\n" + ex); + return null; + } finally { + deviceManagement.endTenantFlow(); + } + } + + @Path("manager/device/{sketch_type}/download") + @GET + @Produces(MediaType.APPLICATION_JSON) + public Response downloadSketch(@QueryParam("owner") String owner, + @QueryParam("deviceName") String deviceName, + @PathParam("sketch_type") String + sketchType) { + + try { + ZipArchive zipFile = createDownloadFile(owner, deviceName, sketchType); + Response.ResponseBuilder response = Response.ok(FileUtils.readFileToByteArray(zipFile.getZipFile())); + response.type("application/zip"); + response.header("Content-Disposition", "attachment; filename=\"" + zipFile.getFileName() + "\""); + return response.build(); + + } catch (IllegalArgumentException ex) { + return Response.status(400).entity(ex.getMessage()).build();//bad request + } catch (DeviceManagementException ex) { + return Response.status(500).entity(ex.getMessage()).build(); + } catch (AccessTokenException ex) { + return Response.status(500).entity(ex.getMessage()).build(); + } catch (DeviceControllerException ex) { + return Response.status(500).entity(ex.getMessage()).build(); + } catch (IOException ex) { + return Response.status(500).entity(ex.getMessage()).build(); + } + } + + private ZipArchive createDownloadFile(String owner, String deviceName, String sketchType) + throws DeviceManagementException, AccessTokenException, DeviceControllerException { + if (owner == null) { + throw new IllegalArgumentException("Error on createDownloadFile() Owner is null!"); + } + + //create new device id + String deviceId = shortUUID(); + + KeyGenerationUtil.createApplicationKeys("currentsensor"); + + TokenClient accessTokenClient = new TokenClient(CurrentSensorConstants.DEVICE_TYPE); + AccessTokenInfo accessTokenInfo = accessTokenClient.getAccessToken(owner, deviceId); + + //create token + String accessToken = accessTokenInfo.getAccess_token(); + String refreshToken = accessTokenInfo.getRefresh_token(); + //adding registering data + + boolean status; + + //Register the device with CDMF + status = register(deviceId, deviceName, owner); + + if (!status) { + String msg = "Error occurred while registering the device with " + "id: " + deviceId + " owner:" + owner; + throw new DeviceManagementException(msg); + } + + ZipUtil ziputil = new ZipUtil(); + ZipArchive zipFile = ziputil.createZipFile(owner, SUPER_TENANT, sketchType, deviceId, deviceName, accessToken, + refreshToken); + zipFile.setDeviceId(deviceId); + return zipFile; + } + + private static String shortUUID() { + UUID uuid = UUID.randomUUID(); + long l = ByteBuffer.wrap(uuid.toString().getBytes(StandardCharsets.UTF_8)).getLong(); + return Long.toString(l, Character.MAX_RADIX); + } + +} diff --git a/modules/samples/currentsensor/component/manager/src/main/webapp/META-INF/webapp-classloading.xml b/modules/samples/currentsensor/component/manager/src/main/webapp/META-INF/webapp-classloading.xml new file mode 100644 index 00000000..fa446191 --- /dev/null +++ b/modules/samples/currentsensor/component/manager/src/main/webapp/META-INF/webapp-classloading.xml @@ -0,0 +1,33 @@ + + + + + + + + + false + + + CXF,Carbon + diff --git a/modules/samples/currentsensor/component/manager/src/main/webapp/WEB-INF/cxf-servlet.xml b/modules/samples/currentsensor/component/manager/src/main/webapp/WEB-INF/cxf-servlet.xml new file mode 100644 index 00000000..08041520 --- /dev/null +++ b/modules/samples/currentsensor/component/manager/src/main/webapp/WEB-INF/cxf-servlet.xml @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + diff --git a/modules/samples/currentsensor/component/manager/src/main/webapp/WEB-INF/web.xml b/modules/samples/currentsensor/component/manager/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 00000000..b9a45486 --- /dev/null +++ b/modules/samples/currentsensor/component/manager/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,58 @@ + + + + Current-Sensor-Agent-Webapp + + JAX-WS/JAX-RS IOT Current Sensor Endpoint + JAX-WS/JAX-RS Servlet + CXFServlet + org.apache.cxf.transport.servlet.CXFServlet + 1 + + + CXFServlet + /* + + + + + managed-api-enabled + false + + + managed-api-owner + admin + + + managed-api-context-template + /currentsensor/{version} + + + managed-api-application + currentsensor + + + managed-api-isSecured + true + + + diff --git a/modules/samples/currentsensor/component/plugin/pom.xml b/modules/samples/currentsensor/component/plugin/pom.xml new file mode 100644 index 00000000..2b094a3b --- /dev/null +++ b/modules/samples/currentsensor/component/plugin/pom.xml @@ -0,0 +1,73 @@ + + + + org.homeautomation + component + 1.9.2-SNAPSHOT + ../pom.xml + + 4.0.0 + 1.9.2-SNAPSHOT + ${groupId}.currentsensor.plugin + bundle + ${groupId}.currentsensor.plugin for CDMF + http://wso2.org + + + + org.apache.felix + maven-scr-plugin + + + org.apache.maven.plugins + maven-compiler-plugin + ${maven-compiler-plugin.version} + + UTF-8 + ${wso2.maven.compiler.source} + ${wso2.maven.compiler.target} + + + + org.apache.felix + maven-bundle-plugin + ${org.apache.felix.version} + true + + + ${groupId}.currentsensor.plugin + ${groupId}.currentsensor.plugin + 1.9.2-SNAPSHOT + IoT Server Impl Bundle + org.homeautomation.currentsensor.plugin.internal + + + + !org.homeautomation.currentsensor.plugin.internal, + org.homeautomation.currentsensor.plugin.* + + + + + + + + + \ No newline at end of file diff --git a/modules/samples/currentsensor/component/plugin/src/main/java/org/homeautomation/currentsensor/plugin/constants/CurrentSensorConstants.java b/modules/samples/currentsensor/component/plugin/src/main/java/org/homeautomation/currentsensor/plugin/constants/CurrentSensorConstants.java new file mode 100644 index 00000000..e0225bd7 --- /dev/null +++ b/modules/samples/currentsensor/component/plugin/src/main/java/org/homeautomation/currentsensor/plugin/constants/CurrentSensorConstants.java @@ -0,0 +1,26 @@ +/* +* Copyright (c) 2014, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +package org.homeautomation.currentsensor.plugin.constants; + +public class CurrentSensorConstants { + + public final static String DEVICE_TYPE = "currentsensor"; + public final static String DEVICE_PLUGIN_DEVICE_NAME = "DEVICE_NAME"; + public final static String DEVICE_PLUGIN_DEVICE_ID = "CURRENT_SENSOR_DEVICE_ID"; + public final static String SENSOR_CURRENT = "current"; + public final static String SENSOR_POWER = "power"; +} diff --git a/modules/samples/currentsensor/component/plugin/src/main/java/org/homeautomation/currentsensor/plugin/impl/CurrentSensorManager.java b/modules/samples/currentsensor/component/plugin/src/main/java/org/homeautomation/currentsensor/plugin/impl/CurrentSensorManager.java new file mode 100644 index 00000000..d1676369 --- /dev/null +++ b/modules/samples/currentsensor/component/plugin/src/main/java/org/homeautomation/currentsensor/plugin/impl/CurrentSensorManager.java @@ -0,0 +1,277 @@ +/* + * Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * you may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.homeautomation.currentsensor.plugin.impl; + + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.wso2.carbon.device.mgt.common.*; +import org.wso2.carbon.device.mgt.common.configuration.mgt.TenantConfiguration; +import org.wso2.carbon.device.mgt.common.license.mgt.License; +import org.wso2.carbon.device.mgt.common.license.mgt.LicenseManagementException; +import org.wso2.carbon.device.mgt.iot.currentsensor.plugin.impl.dao.CurrentSensorDAO; +import org.wso2.carbon.device.mgt.iot.util.iotdevice.dao.IotDeviceManagementDAOException; +import org.wso2.carbon.device.mgt.iot.util.iotdevice.dao.IotDeviceManagementDAOFactoryInterface; +import org.wso2.carbon.device.mgt.iot.util.iotdevice.dto.IotDevice; +import org.wso2.carbon.device.mgt.iot.util.iotdevice.util.IotDeviceManagementUtil; + +import java.util.ArrayList; +import java.util.List; + + +/** + * This represents the Current Sensor implementation of DeviceManagerService. + */ +public class CurrentSensorManager implements DeviceManager { + + private static final IotDeviceManagementDAOFactoryInterface iotDeviceManagementDAOFactory = new CurrentSensorDAO(); + private static final Log log = LogFactory.getLog(CurrentSensorManager.class); + + + + @Override + public FeatureManager getFeatureManager() { + return null; + } + + @Override + public boolean saveConfiguration(TenantConfiguration tenantConfiguration) + throws DeviceManagementException { + //TODO implement this + return false; + } + + @Override + public TenantConfiguration getConfiguration() throws DeviceManagementException { + //TODO implement this + return null; + } + + @Override + public boolean enrollDevice(Device device) throws DeviceManagementException { + boolean status; + IotDevice iotDevice = IotDeviceManagementUtil.convertToIotDevice(device); + try { + if (log.isDebugEnabled()) { + log.debug("Enrolling a new Current Sensor device : " + device.getDeviceIdentifier()); + } + CurrentSensorDAO.beginTransaction(); + status = iotDeviceManagementDAOFactory.getIotDeviceDAO().addIotDevice( + iotDevice); + CurrentSensorDAO.commitTransaction(); + } catch (IotDeviceManagementDAOException e) { + try { + CurrentSensorDAO.rollbackTransaction(); + } catch (IotDeviceManagementDAOException iotDAOEx) { + String msg = "Error occurred while roll back the device enrol transaction :" + device.toString(); + log.warn(msg, iotDAOEx); + } + String msg = "Error while enrolling the Current Sensor device : " + device.getDeviceIdentifier(); + log.error(msg, e); + throw new DeviceManagementException(msg, e); + } + return status; + } + + @Override + public boolean modifyEnrollment(Device device) throws DeviceManagementException { + boolean status; + IotDevice iotDevice = IotDeviceManagementUtil.convertToIotDevice(device); + try { + if (log.isDebugEnabled()) { + log.debug("Modifying the Current Sensor device enrollment data"); + } + CurrentSensorDAO.beginTransaction(); + status = iotDeviceManagementDAOFactory.getIotDeviceDAO() + .updateIotDevice(iotDevice); + CurrentSensorDAO.commitTransaction(); + } catch (IotDeviceManagementDAOException e) { + try { + CurrentSensorDAO.rollbackTransaction(); + } catch (IotDeviceManagementDAOException iotDAOEx) { + String msg = "Error occurred while roll back the update device transaction :" + device.toString(); + log.warn(msg, iotDAOEx); + } + String msg = "Error while updating the enrollment of the Current Sensor device : " + + device.getDeviceIdentifier(); + log.error(msg, e); + throw new DeviceManagementException(msg, e); + } + return status; + } + + @Override + public boolean disenrollDevice(DeviceIdentifier deviceId) throws DeviceManagementException { + boolean status; + try { + if (log.isDebugEnabled()) { + log.debug("Dis-enrolling Current Sensor device : " + deviceId); + } + CurrentSensorDAO.beginTransaction(); + status = iotDeviceManagementDAOFactory.getIotDeviceDAO() + .deleteIotDevice(deviceId.getId()); + CurrentSensorDAO.commitTransaction(); + } catch (IotDeviceManagementDAOException e) { + try { + CurrentSensorDAO.rollbackTransaction(); + } catch (IotDeviceManagementDAOException iotDAOEx) { + String msg = "Error occurred while roll back the device dis enrol transaction :" + deviceId.toString(); + log.warn(msg, iotDAOEx); + } + String msg = "Error while removing the Current Sensor device : " + deviceId.getId(); + log.error(msg, e); + throw new DeviceManagementException(msg, e); + } + return status; + } + + @Override + public boolean isEnrolled(DeviceIdentifier deviceId) throws DeviceManagementException { + boolean isEnrolled = false; + try { + if (log.isDebugEnabled()) { + log.debug("Checking the enrollment of Current Sensor device : " + deviceId.getId()); + } + IotDevice iotDevice = + iotDeviceManagementDAOFactory.getIotDeviceDAO().getIotDevice( + deviceId.getId()); + if (iotDevice != null) { + isEnrolled = true; + } + } catch (IotDeviceManagementDAOException e) { + String msg = "Error while checking the enrollment status of Current Sensor device : " + + deviceId.getId(); + log.error(msg, e); + throw new DeviceManagementException(msg, e); + } + return isEnrolled; + } + + @Override + public boolean isActive(DeviceIdentifier deviceId) throws DeviceManagementException { + return true; + } + + @Override + public boolean setActive(DeviceIdentifier deviceId, boolean status) + throws DeviceManagementException { + return true; + } + + @Override + public Device getDevice(DeviceIdentifier deviceId) throws DeviceManagementException { + Device device; + try { + if (log.isDebugEnabled()) { + log.debug("Getting the details of Current Sensor device : " + deviceId.getId()); + } + IotDevice iotDevice = iotDeviceManagementDAOFactory.getIotDeviceDAO(). + getIotDevice(deviceId.getId()); + device = IotDeviceManagementUtil.convertToDevice(iotDevice); + } catch (IotDeviceManagementDAOException e) { + String msg = "Error while fetching the Current Sensor device : " + deviceId.getId(); + log.error(msg, e); + throw new DeviceManagementException(msg, e); + } + return device; + } + + @Override + public boolean setOwnership(DeviceIdentifier deviceId, String ownershipType) + throws DeviceManagementException { + return true; + } + + public boolean isClaimable(DeviceIdentifier deviceIdentifier) throws DeviceManagementException { + return false; + } + + @Override + public boolean setStatus(DeviceIdentifier deviceId, String currentOwner, + EnrolmentInfo.Status status) throws DeviceManagementException { + return false; + } + + @Override + public License getLicense(String s) throws LicenseManagementException { + return null; + } + + @Override + public void addLicense(License license) throws LicenseManagementException { + + } + + @Override + public boolean requireDeviceAuthorization() { + return true; + } + + @Override + public boolean updateDeviceInfo(DeviceIdentifier deviceIdentifier, Device device) throws DeviceManagementException { + boolean status; + IotDevice iotDevice = IotDeviceManagementUtil.convertToIotDevice(device); + try { + if (log.isDebugEnabled()) { + log.debug( + "updating the details of Current Sensor device : " + deviceIdentifier); + } + CurrentSensorDAO.beginTransaction(); + status = iotDeviceManagementDAOFactory.getIotDeviceDAO() + .updateIotDevice(iotDevice); + CurrentSensorDAO.commitTransaction(); + } catch (IotDeviceManagementDAOException e) { + try { + CurrentSensorDAO.rollbackTransaction(); + } catch (IotDeviceManagementDAOException iotDAOEx) { + String msg = "Error occurred while roll back the update device info transaction :" + device.toString(); + log.warn(msg, iotDAOEx); + } + String msg = + "Error while updating the Current Sensor device : " + deviceIdentifier; + log.error(msg, e); + throw new DeviceManagementException(msg, e); + } + return status; + } + + @Override + public List getAllDevices() throws DeviceManagementException { + List devices = null; + try { + if (log.isDebugEnabled()) { + log.debug("Fetching the details of all Current Sensor devices"); + } + List iotDevices = + iotDeviceManagementDAOFactory.getIotDeviceDAO().getAllIotDevices(); + if (iotDevices != null) { + devices = new ArrayList(); + for (IotDevice iotDevice : iotDevices) { + devices.add(IotDeviceManagementUtil.convertToDevice(iotDevice)); + } + } + } catch (IotDeviceManagementDAOException e) { + String msg = "Error while fetching all Current Sensor devices."; + log.error(msg, e); + throw new DeviceManagementException(msg, e); + } + return devices; + } + +} \ No newline at end of file diff --git a/modules/samples/currentsensor/component/plugin/src/main/java/org/homeautomation/currentsensor/plugin/impl/CurrentSensorManagerService.java b/modules/samples/currentsensor/component/plugin/src/main/java/org/homeautomation/currentsensor/plugin/impl/CurrentSensorManagerService.java new file mode 100644 index 00000000..09fc22f0 --- /dev/null +++ b/modules/samples/currentsensor/component/plugin/src/main/java/org/homeautomation/currentsensor/plugin/impl/CurrentSensorManagerService.java @@ -0,0 +1,92 @@ +package org.homeautomation.currentsensor.plugin.impl; + +import org.wso2.carbon.device.mgt.common.DeviceIdentifier; +import org.wso2.carbon.device.mgt.common.DeviceManagementException; +import org.wso2.carbon.device.mgt.common.DeviceManager; +import org.wso2.carbon.device.mgt.common.app.mgt.Application; +import org.wso2.carbon.device.mgt.common.app.mgt.ApplicationManagementException; +import org.wso2.carbon.device.mgt.common.app.mgt.ApplicationManager; +import org.wso2.carbon.device.mgt.common.operation.mgt.Operation; +import org.wso2.carbon.device.mgt.common.spi.DeviceManagementService; +import org.wso2.carbon.device.mgt.iot.currentsensor.plugin.constants.CurrentSensorConstants; + +import java.util.List; + +; + +public class CurrentSensorManagerService implements DeviceManagementService{ + private DeviceManager deviceManager; + @Override + public String getType() { + return CurrentSensorConstants.DEVICE_TYPE; + } + + @Override + public String getProviderTenantDomain() { + return "carbon.super"; + } + + @Override + public boolean isSharedWithAllTenants() { + return true; + } + + @Override + public String[] getSharedTenantsDomain() { + return new String[0]; + } + + @Override + public void init() throws DeviceManagementException { + deviceManager= new CurrentSensorManager(); + } + + @Override + public DeviceManager getDeviceManager() { + return deviceManager; + } + + @Override + public ApplicationManager getApplicationManager() { + return null; + } + + @Override + public void notifyOperationToDevices(Operation operation, List list) throws DeviceManagementException { + + } + + @Override + public Application[] getApplications(String domain, int pageNumber, int size) + throws ApplicationManagementException { + return new Application[0]; + } + + @Override + public void updateApplicationStatus(DeviceIdentifier deviceId, Application application, + String status) throws ApplicationManagementException { + + } + + @Override + public String getApplicationStatus(DeviceIdentifier deviceId, Application application) + throws ApplicationManagementException { + return null; + } + + @Override + public void installApplicationForDevices(Operation operation, List list) throws ApplicationManagementException { + + } + + @Override + public void installApplicationForUsers(Operation operation, List list) throws ApplicationManagementException { + + } + + @Override + public void installApplicationForUserRoles(Operation operation, List list) throws ApplicationManagementException { + + } + +} diff --git a/modules/samples/currentsensor/component/plugin/src/main/java/org/homeautomation/currentsensor/plugin/impl/dao/CurrentSensorDAO.java b/modules/samples/currentsensor/component/plugin/src/main/java/org/homeautomation/currentsensor/plugin/impl/dao/CurrentSensorDAO.java new file mode 100644 index 00000000..35b6797d --- /dev/null +++ b/modules/samples/currentsensor/component/plugin/src/main/java/org/homeautomation/currentsensor/plugin/impl/dao/CurrentSensorDAO.java @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * you may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. +*/ + +package org.homeautomation.currentsensor.plugin.impl.dao; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.wso2.carbon.device.mgt.iot.currentsensor.plugin.constants.CurrentSensorConstants; +import org.wso2.carbon.device.mgt.iot.currentsensor.plugin.impl.dao.impl.CurrentSensorDeviceDAOImpl; +import org.wso2.carbon.device.mgt.iot.util.iotdevice.dao.IotDeviceDAO; +import org.wso2.carbon.device.mgt.iot.util.iotdevice.dao.IotDeviceManagementDAOException; +import org.wso2.carbon.device.mgt.iot.util.iotdevice.dao.IotDeviceManagementDAOFactory; +import org.wso2.carbon.device.mgt.iot.util.iotdevice.dao.IotDeviceManagementDAOFactoryInterface; + +import javax.sql.DataSource; +import java.sql.Connection; +import java.sql.SQLException; + +public class CurrentSensorDAO extends IotDeviceManagementDAOFactory + implements IotDeviceManagementDAOFactoryInterface { + + private static final Log log = LogFactory.getLog(CurrentSensorDAO.class); + static DataSource dataSource; // package local variable + private static ThreadLocal currentConnection = new ThreadLocal(); + + public CurrentSensorDAO() { + initCurrentSensorDAO(); + } + + @Override + public IotDeviceDAO getIotDeviceDAO() { + return new CurrentSensorDeviceDAOImpl(); + } + + public static void initCurrentSensorDAO(){ + dataSource = getDataSourceMap().get(CurrentSensorConstants.DEVICE_TYPE); + } + + public static void beginTransaction() throws IotDeviceManagementDAOException { + try { + Connection conn = dataSource.getConnection(); + conn.setAutoCommit(false); + currentConnection.set(conn); + } catch (SQLException e) { + throw new IotDeviceManagementDAOException("Error occurred while retrieving datasource connection", e); + } + } + + public static Connection getConnection() throws IotDeviceManagementDAOException { + if (currentConnection.get() == null) { + try { + currentConnection.set(dataSource.getConnection()); + } catch (SQLException e) { + throw new IotDeviceManagementDAOException("Error occurred while retrieving data source connection", + e); + } + } + return currentConnection.get(); + } + + public static void commitTransaction() throws IotDeviceManagementDAOException { + try { + Connection conn = currentConnection.get(); + if (conn != null) { + conn.commit(); + } else { + if (log.isDebugEnabled()) { + log.debug("Datasource connection associated with the current thread is null, hence commit " + + "has not been attempted"); + } + } + } catch (SQLException e) { + throw new IotDeviceManagementDAOException("Error occurred while committing the transaction", e); + } finally { + closeConnection(); + } + } + + public static void closeConnection() throws IotDeviceManagementDAOException { + + Connection con = currentConnection.get(); + if(con != null){ + try { + con.close(); + } catch (SQLException e) { + log.error("Error occurred while close the connection"); + } + } + currentConnection.remove(); + } + + public static void rollbackTransaction() throws IotDeviceManagementDAOException { + try { + Connection conn = currentConnection.get(); + if (conn != null) { + conn.rollback(); + } else { + if (log.isDebugEnabled()) { + log.debug("Datasource connection associated with the current thread is null, hence rollback " + + "has not been attempted"); + } + } + } catch (SQLException e) { + throw new IotDeviceManagementDAOException("Error occurred while rollback the transaction", e); + } finally { + closeConnection(); + } + } +} \ No newline at end of file diff --git a/modules/samples/currentsensor/component/plugin/src/main/java/org/homeautomation/currentsensor/plugin/impl/dao/impl/CurrentSensorDeviceDAOImpl.java b/modules/samples/currentsensor/component/plugin/src/main/java/org/homeautomation/currentsensor/plugin/impl/dao/impl/CurrentSensorDeviceDAOImpl.java new file mode 100644 index 00000000..d732d8a9 --- /dev/null +++ b/modules/samples/currentsensor/component/plugin/src/main/java/org/homeautomation/currentsensor/plugin/impl/dao/impl/CurrentSensorDeviceDAOImpl.java @@ -0,0 +1,237 @@ +/* + * Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * you may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.homeautomation.currentsensor.impl.dao.impl; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.wso2.carbon.device.mgt.iot.currentsensor.plugin.constants.CurrentSensorConstants; +import org.wso2.carbon.device.mgt.iot.currentsensor.plugin.impl.dao.CurrentSensorDAO; +import org.wso2.carbon.device.mgt.iot.util.iotdevice.dao.IotDeviceDAO; +import org.wso2.carbon.device.mgt.iot.util.iotdevice.dao.IotDeviceManagementDAOException; +import org.wso2.carbon.device.mgt.iot.util.iotdevice.dao.util.IotDeviceManagementDAOUtil; +import org.wso2.carbon.device.mgt.iot.util.iotdevice.dto.IotDevice; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * Implements IotDeviceDAO for current sensor Devices. + */ +public class CurrentSensorDeviceDAOImpl implements IotDeviceDAO { + + + private static final Log log = LogFactory.getLog(CurrentSensorDeviceDAOImpl.class); + + @Override + public IotDevice getIotDevice(String iotDeviceId) + throws IotDeviceManagementDAOException { + Connection conn = null; + PreparedStatement stmt = null; + IotDevice iotDevice = null; + ResultSet resultSet = null; + try { + conn = CurrentSensorDAO.getConnection(); + String selectDBQuery = + "SELECT CURRENT_SENSOR_DEVICE_ID, DEVICE_NAME" + + " FROM CURRENT_SENSOR_DEVICE WHERE CURRENT_SENSOR_DEVICE_ID = ?"; + stmt = conn.prepareStatement(selectDBQuery); + stmt.setString(1, iotDeviceId); + resultSet = stmt.executeQuery(); + + if (resultSet.next()) { + iotDevice = new IotDevice(); + iotDevice.setIotDeviceName(resultSet.getString( + CurrentSensorConstants.DEVICE_PLUGIN_DEVICE_NAME)); + Map propertyMap = new HashMap(); + + + iotDevice.setDeviceProperties(propertyMap); + + if (log.isDebugEnabled()) { + log.debug("Current Sensor device " + iotDeviceId + " data has been fetched from " + + "Current Sensor database."); + } + } + } catch (SQLException e) { + String msg = "Error occurred while fetching Current Sensor device : '" + iotDeviceId + "'"; + log.error(msg, e); + throw new IotDeviceManagementDAOException(msg, e); + } finally { + IotDeviceManagementDAOUtil.cleanupResources(stmt, resultSet); + CurrentSensorDAO.closeConnection(); + } + + return iotDevice; + } + + @Override + public boolean addIotDevice(IotDevice iotDevice) + throws IotDeviceManagementDAOException { + boolean status = false; + Connection conn = null; + PreparedStatement stmt = null; + try { + conn = CurrentSensorDAO.getConnection(); + String createDBQuery = + "INSERT INTO CURRENT_SENSOR_DEVICE(CURRENT_SENSOR_DEVICE_ID, DEVICE_NAME) VALUES (?, ?)"; + + stmt = conn.prepareStatement(createDBQuery); + stmt.setString(1, iotDevice.getIotDeviceId()); + stmt.setString(2, iotDevice.getIotDeviceName()); + if (iotDevice.getDeviceProperties() == null) { + iotDevice.setDeviceProperties(new HashMap()); + } + + + int rows = stmt.executeUpdate(); + if (rows > 0) { + status = true; + if (log.isDebugEnabled()) { + log.debug("Current Sensor device " + iotDevice.getIotDeviceId() + " data has been" + + " added to the Current Sensor database."); + } + } + } catch (SQLException e) { + String msg = "Error occurred while adding the Current Sensor device '" + + iotDevice.getIotDeviceId() + "' to the Current Sensor db."; + log.error(msg, e); + throw new IotDeviceManagementDAOException(msg, e); + } finally { + IotDeviceManagementDAOUtil.cleanupResources(stmt, null); + } + return status; + } + + @Override + public boolean updateIotDevice(IotDevice iotDevice) + throws IotDeviceManagementDAOException { + boolean status = false; + Connection conn = null; + PreparedStatement stmt = null; + try { + conn = CurrentSensorDAO.getConnection(); + String updateDBQuery = + "UPDATE CURRENT_SENSOR_DEVICE SET DEVICE_NAME = ? WHERE CURRENT_SENSOR_DEVICE_ID = ?"; + + stmt = conn.prepareStatement(updateDBQuery); + + if (iotDevice.getDeviceProperties() == null) { + iotDevice.setDeviceProperties(new HashMap()); + } + stmt.setString(1, iotDevice.getIotDeviceName()); + + stmt.setString(2, iotDevice.getIotDeviceId()); + int rows = stmt.executeUpdate(); + if (rows > 0) { + status = true; + if (log.isDebugEnabled()) { + log.debug("Current Sensor device " + iotDevice.getIotDeviceId() + " data has been" + + " modified."); + } + } + } catch (SQLException e) { + String msg = "Error occurred while modifying the Current Sensor device '" + + iotDevice.getIotDeviceId() + "' data."; + log.error(msg, e); + throw new IotDeviceManagementDAOException(msg, e); + } finally { + IotDeviceManagementDAOUtil.cleanupResources(stmt, null); + } + return status; + } + + @Override + public boolean deleteIotDevice(String iotDeviceId) + throws IotDeviceManagementDAOException { + boolean status = false; + Connection conn = null; + PreparedStatement stmt = null; + try { + conn = CurrentSensorDAO.getConnection(); + String deleteDBQuery = + "DELETE FROM CURRENT_SENSOR_DEVICE WHERE CURRENT_SENSOR_DEVICE_ID = ?"; + stmt = conn.prepareStatement(deleteDBQuery); + stmt.setString(1, iotDeviceId); + int rows = stmt.executeUpdate(); + if (rows > 0) { + status = true; + if (log.isDebugEnabled()) { + log.debug("Current Sensor device " + iotDeviceId + " data has deleted" + + " from the Current Sensor database."); + } + } + } catch (SQLException e) { + String msg = "Error occurred while deleting Current Sensor device " + iotDeviceId; + log.error(msg, e); + throw new IotDeviceManagementDAOException(msg, e); + } finally { + IotDeviceManagementDAOUtil.cleanupResources(stmt, null); + } + return status; + } + + @Override + public List getAllIotDevices() + throws IotDeviceManagementDAOException { + + Connection conn = null; + PreparedStatement stmt = null; + ResultSet resultSet = null; + IotDevice iotDevice; + List iotDevices = new ArrayList(); + + try { + conn = CurrentSensorDAO.getConnection(); + String selectDBQuery = + "SELECT CURRENT_SENSOR_DEVICE_ID, DEVICE_NAME " + + "FROM CURRENT_SENSOR_DEVICE"; + stmt = conn.prepareStatement(selectDBQuery); + resultSet = stmt.executeQuery(); + while (resultSet.next()) { + iotDevice = new IotDevice(); + iotDevice.setIotDeviceId(resultSet.getString(CurrentSensorConstants.DEVICE_PLUGIN_DEVICE_ID)); + iotDevice.setIotDeviceName(resultSet.getString(CurrentSensorConstants.DEVICE_PLUGIN_DEVICE_NAME)); + + Map propertyMap = new HashMap(); + + iotDevice.setDeviceProperties(propertyMap); + iotDevices.add(iotDevice); + } + if (log.isDebugEnabled()) { + log.debug("All Current Sensor device details have fetched from Current Sensor database."); + } + return iotDevices; + } catch (SQLException e) { + String msg = "Error occurred while fetching all Current Sensor device data'"; + log.error(msg, e); + throw new IotDeviceManagementDAOException(msg, e); + } finally { + IotDeviceManagementDAOUtil.cleanupResources(stmt, resultSet); + CurrentSensorDAO.closeConnection(); + } + + } + +} diff --git a/modules/samples/currentsensor/component/plugin/src/main/java/org/homeautomation/currentsensor/plugin/impl/util/CurrentSensorUtils.java b/modules/samples/currentsensor/component/plugin/src/main/java/org/homeautomation/currentsensor/plugin/impl/util/CurrentSensorUtils.java new file mode 100644 index 00000000..299f2b58 --- /dev/null +++ b/modules/samples/currentsensor/component/plugin/src/main/java/org/homeautomation/currentsensor/plugin/impl/util/CurrentSensorUtils.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * you may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.homeautomation.currentsensor.plugin.impl.util; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import java.util.Map; + +/** + * Contains utility methods used by Current Sensor plugin. + */ +public class CurrentSensorUtils { + + private static Log log = LogFactory.getLog(CurrentSensorUtils.class); + + public static String getDeviceProperty(Map deviceProperties, String property) { + + String deviceProperty = deviceProperties.get(property); + + if (deviceProperty == null) { + return ""; + } + + return deviceProperty; + } + + +} diff --git a/modules/samples/currentsensor/component/plugin/src/main/java/org/homeautomation/currentsensor/plugin/internal/ServiceComponent.java b/modules/samples/currentsensor/component/plugin/src/main/java/org/homeautomation/currentsensor/plugin/internal/ServiceComponent.java new file mode 100644 index 00000000..d0cfe5d9 --- /dev/null +++ b/modules/samples/currentsensor/component/plugin/src/main/java/org/homeautomation/currentsensor/plugin/internal/ServiceComponent.java @@ -0,0 +1,21 @@ +package org.homeautomation.currentsensor.plugin.internal; +/* + * Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +public class ServiceComponent{ + +} \ No newline at end of file diff --git a/modules/samples/currentsensor/component/pom.xml b/modules/samples/currentsensor/component/pom.xml new file mode 100644 index 00000000..4e3ddebe --- /dev/null +++ b/modules/samples/currentsensor/component/pom.xml @@ -0,0 +1,243 @@ + + + + org.homeautomation + currentsensor + 1.9.2-SNAPSHOT + ../pom.xml + + 4.0.0 + 1.9.2-SNAPSHOT + component + pom + + + + + org.apache.felix + maven-scr-plugin + ${maven-scr-plugin.version} + + + generate-scr-scrdescriptor + + scr + + + + + + + + + + plugin + controller + manager + agent + + + + + + org.homeautomation + ${project-base-package}.plugin + 1.9.2-SNAPSHOT + provided + + + org.wso2.carbon.devicemgt-plugins + org.coffeeking.connectedcup.plugin + 1.9.2-SNAPSHOT + provided + + + + org.wso2.carbon.devicemgt + org.wso2.carbon.apimgt.webapp.publisher + ${carbon.device.mgt.version} + system + + ${basedir}/../../../../repository/components/plugins/org.wso2.carbon.apimgt.webapp.publisher_0.9.2.SNAPSHOT.jar + + + + + org.wso2.carbon + org.wso2.carbon.ndatasource.core + ${carbon.kernel.version} + system + + ${basedir}/../../../../repository/components/plugins/org.wso2.carbon.ndatasource.core_${carbon.kernel.version}.jar + + + + org.wso2.carbon.devicemgt-plugins + org.wso2.carbon.device.mgt.iot + ${carbon.iot.device.mgt.version} + system + + ${basedir}/../../../../repository/components/plugins/org.wso2.carbon.device.mgt.iot_1.9.2.SNAPSHOT.jar + + + + org.wso2.carbon.devicemgt + org.wso2.carbon.device.mgt.core + ${carbon.device.mgt.version} + system + + ${basedir}/../../../../repository/components/plugins/org.wso2.carbon.device.mgt.core_0.9.2.SNAPSHOT.jar + + + + org.wso2.carbon.devicemgt + org.wso2.carbon.device.mgt.common + ${carbon.device.mgt.version} + system + + ${basedir}/../../../../repository/components/plugins/org.wso2.carbon.device.mgt.common_0.9.2.SNAPSHOT.jar + + + + org.wso2.carbon.devicemgt + org.wso2.carbon.certificate.mgt.core + ${carbon.device.mgt.version} + system + + ${basedir}/../../../../repository/components/plugins/org.wso2.carbon.certificate.mgt.core_0.9.2.SNAPSHOT.jar + + + + org.wso2.carbon.devicemgt + org.wso2.carbon.apimgt.annotations + ${carbon.device.mgt.version} + system + + ${basedir}/../../../../repository/components/plugins/org.wso2.carbon.apimgt.annotations_0.9.2.SNAPSHOT.jar + + + + org.wso2.carbon.devicemgt + org.wso2.carbon.device.mgt.analytics + ${carbon.device.mgt.version} + system + + ${basedir}/../../../../repository/components/plugins/org.wso2.carbon.device.mgt.analytics_0.9.2.SNAPSHOT.jar + + + + commons-httpclient.wso2 + commons-httpclient + ${commons-httpclient.orbit.version} + system + + ${basedir}/../../../../repository/components/plugins/commons-httpclient_3.1.0.wso2v2.jar + + + + org.wso2.carbon + org.wso2.carbon.utils + ${carbon.kernel.version} + + + org.bouncycastle.wso2 + bcprov-jdk15on + + + org.wso2.carbon + org.wso2.carbon.user.api + + + org.wso2.carbon + org.wso2.carbon.queuing + + + org.wso2.carbon + org.wso2.carbon.base + + + org.apache.axis2.wso2 + axis2 + + + org.igniterealtime.smack.wso2 + smack + + + org.igniterealtime.smack.wso2 + smackx + + + jaxen + jaxen + + + commons-fileupload.wso2 + commons-fileupload + + + org.apache.ant.wso2 + ant + + + org.apache.ant.wso2 + ant + + + commons-httpclient.wso2 + commons-httpclient + + + org.eclipse.equinox + javax.servlet + + + org.wso2.carbon + org.wso2.carbon.registry.api + + + system + + ${basedir}/../../../../repository/components/plugins/org.wso2.carbon.utils_${carbon.kernel.version}.jar + + + + org.igniterealtime.smack.wso2 + smack + ${smack.wso2.version} + system + + ${basedir}/../../../../repository/components/plugins/smack_3.0.4.wso2v1.jar + + + + org.igniterealtime.smack.wso2 + smackx + ${smackx.wso2.version} + system + + ${basedir}/../../../../repository/components/plugins/smackx_3.0.4.wso2v1.jar + + + + org.json.wso2 + json + ${commons-json.version} + system + + ${basedir}/../../../../repository/components/plugins/json_2.0.0.wso2v1.jar + + + + commons-codec + commons-codec + 1.4.0.wso2v1 + system + + ${basedir}/../../../../repository/components/plugins/commons-codec_1.4.0.wso2v1.jar + + + + + \ No newline at end of file diff --git a/modules/samples/currentsensor/feature/analytics/Current/Eventreceiver_current_1.0.0/EventReceiver_current.xml b/modules/samples/currentsensor/feature/analytics/Current/Eventreceiver_current_1.0.0/EventReceiver_current.xml new file mode 100644 index 00000000..8003949f --- /dev/null +++ b/modules/samples/currentsensor/feature/analytics/Current/Eventreceiver_current_1.0.0/EventReceiver_current.xml @@ -0,0 +1,8 @@ + + + + false + + + + diff --git a/modules/samples/currentsensor/feature/analytics/Current/Eventreceiver_current_1.0.0/artifact.xml b/modules/samples/currentsensor/feature/analytics/Current/Eventreceiver_current_1.0.0/artifact.xml new file mode 100644 index 00000000..e18a54a9 --- /dev/null +++ b/modules/samples/currentsensor/feature/analytics/Current/Eventreceiver_current_1.0.0/artifact.xml @@ -0,0 +1,4 @@ + + + EventReceiver_current.xml + diff --git a/modules/samples/currentsensor/feature/analytics/Current/Eventstore_current_1.0.0/artifact.xml b/modules/samples/currentsensor/feature/analytics/Current/Eventstore_current_1.0.0/artifact.xml new file mode 100644 index 00000000..8fa86f5f --- /dev/null +++ b/modules/samples/currentsensor/feature/analytics/Current/Eventstore_current_1.0.0/artifact.xml @@ -0,0 +1,4 @@ + + + org_wso2_iot_devices_current.xml + diff --git a/modules/samples/currentsensor/feature/analytics/Current/Eventstore_current_1.0.0/org_wso2_iot_devices_current.xml b/modules/samples/currentsensor/feature/analytics/Current/Eventstore_current_1.0.0/org_wso2_iot_devices_current.xml new file mode 100644 index 00000000..866ca925 --- /dev/null +++ b/modules/samples/currentsensor/feature/analytics/Current/Eventstore_current_1.0.0/org_wso2_iot_devices_current.xml @@ -0,0 +1,44 @@ + + + + org.wso2.iot.devices.current:1.0.0 + + EVENT_STORE + + + meta_owner + true + true + false + STRING + + + meta_deviceType + true + true + false + STRING + + + meta_deviceId + true + true + false + STRING + + + meta_time + true + true + false + LONG + + + current + false + false + false + FLOAT + + + \ No newline at end of file diff --git a/modules/samples/currentsensor/feature/analytics/Current/Eventstream_current_1.0.0/artifact.xml b/modules/samples/currentsensor/feature/analytics/Current/Eventstream_current_1.0.0/artifact.xml new file mode 100644 index 00000000..7be7a0ad --- /dev/null +++ b/modules/samples/currentsensor/feature/analytics/Current/Eventstream_current_1.0.0/artifact.xml @@ -0,0 +1,5 @@ + + + org.wso2.iot.devices.current_1.0.0.json + + diff --git a/modules/samples/currentsensor/feature/analytics/Current/Eventstream_current_1.0.0/org.wso2.iot.devices.current_1.0.0.json b/modules/samples/currentsensor/feature/analytics/Current/Eventstream_current_1.0.0/org.wso2.iot.devices.current_1.0.0.json new file mode 100644 index 00000000..744bed66 --- /dev/null +++ b/modules/samples/currentsensor/feature/analytics/Current/Eventstream_current_1.0.0/org.wso2.iot.devices.current_1.0.0.json @@ -0,0 +1,20 @@ +{ + "name": "org.wso2.iot.devices.current", + "version": "1.0.0", + "nickName": "AC Current Data", + "description": "AC Current data received from the Device", + "metaData": [ + {"name":"owner","type":"STRING"}, + {"name":"deviceType","type":"STRING"}, + {"name":"deviceId","type":"STRING"}, + {"name":"time","type":"LONG"} + ], + "payloadData": [ + { + "name": "current","type": "FLOAT" + } + ] +} + + + diff --git a/modules/samples/currentsensor/feature/analytics/Current/Sparkscripts_1.0.0/Current_Sensor_Script.xml b/modules/samples/currentsensor/feature/analytics/Current/Sparkscripts_1.0.0/Current_Sensor_Script.xml new file mode 100644 index 00000000..d17d9c99 --- /dev/null +++ b/modules/samples/currentsensor/feature/analytics/Current/Sparkscripts_1.0.0/Current_Sensor_Script.xml @@ -0,0 +1,13 @@ + + + IoTServer_Sensor_Script + + 0 * * * * ? + diff --git a/modules/samples/currentsensor/feature/analytics/Current/Sparkscripts_1.0.0/artifact.xml b/modules/samples/currentsensor/feature/analytics/Current/Sparkscripts_1.0.0/artifact.xml new file mode 100644 index 00000000..02d3d73f --- /dev/null +++ b/modules/samples/currentsensor/feature/analytics/Current/Sparkscripts_1.0.0/artifact.xml @@ -0,0 +1,4 @@ + + + Current_Sensor_Script.xml + diff --git a/modules/samples/currentsensor/feature/analytics/Current/artifacts.xml b/modules/samples/currentsensor/feature/analytics/Current/artifacts.xml new file mode 100644 index 00000000..082b84ed --- /dev/null +++ b/modules/samples/currentsensor/feature/analytics/Current/artifacts.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/modules/samples/currentsensor/feature/analytics/build.xml b/modules/samples/currentsensor/feature/analytics/build.xml new file mode 100644 index 00000000..e34285ec --- /dev/null +++ b/modules/samples/currentsensor/feature/analytics/build.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/modules/samples/currentsensor/feature/analytics/pom.xml b/modules/samples/currentsensor/feature/analytics/pom.xml new file mode 100644 index 00000000..739d65b3 --- /dev/null +++ b/modules/samples/currentsensor/feature/analytics/pom.xml @@ -0,0 +1,66 @@ + + + + org.homeautomation + feature + 1.9.2-SNAPSHOT + ../pom.xml + + 4.0.0 + ${groupId}.currentsensor.analytics + 1.9.2-SNAPSHOT + pom + ${groupId}.currentsensor.analytics + http://wso2.org + + + + maven-clean-plugin + ${maven-clean-plugin.version} + + + auto-clean + initialize + + clean + + + + + + maven-antrun-plugin + ${wso2.maven.compiler.source} + + + process-resources + + + + + + + run + + + + + + + \ No newline at end of file diff --git a/modules/samples/currentsensor/feature/feature/pom.xml b/modules/samples/currentsensor/feature/feature/pom.xml new file mode 100644 index 00000000..e36046f6 --- /dev/null +++ b/modules/samples/currentsensor/feature/feature/pom.xml @@ -0,0 +1,220 @@ + + + + org.homeautomation + feature + 1.9.2-SNAPSHOT + ../pom.xml + + 4.0.0 + 1.9.2-SNAPSHOT + ${groupId}.currentsensor.feature + pom + ${project.artifactId} + http://wso2.org + + + org.homeautomation + ${project-base-package}.plugin + 1.9.2-SNAPSHOT + + + org.homeautomation + ${project-base-package}.manager + 1.9.2-SNAPSHOT + war + + + org.homeautomation + ${project-base-package}.controller + 1.9.2-SNAPSHOT + war + + + org.homeautomation + ${project-base-package}.agent + 1.9.2-SNAPSHOT + war + + + com.h2database.wso2 + h2-database-engine + 1.2.140.wso2v3 + + + + + + maven-resources-plugin + + + copy-resources + generate-resources + + copy-resources + + + src/main/resources + + + resources + + build.properties + p2.inf + + + + + + + + + org.apache.maven.plugins + maven-dependency-plugin + + + copy-jaxrs-manager-war + package + + copy + + + + + org.homeautomation + ${project-base-package}.manager + war + true + ${basedir}/src/main/resources/webapps/ + currentsensor_mgt.war + + + + + + copy-jaxrs-controller-war + package + + copy + + + + + org.homeautomation + ${project-base-package}.controller + war + true + ${basedir}/src/main/resources/webapps/ + currentsensor.war + + + + + + copy-jaxrs-agent-war + package + + copy + + + + + org.homeautomation + ${project-base-package}.agent + war + true + ${basedir}/src/main/resources/webapps/ + currentsensor_agent.war + + + + + + + + org.apache.maven.plugins + maven-antrun-plugin + ${maven-antrun-plugin.version} + + + create-currentsensor-plugin-mgt-schema + package + + run + + + + + + + + + + + + + + + + + + + + + org.wso2.maven + carbon-p2-plugin + + + p2-feature-generation + package + + p2-feature-gen + + + ${project-base-package} + ../../../features/etc/feature.properties + + + org.wso2.carbon.p2.category.type:server + org.eclipse.equinox.p2.type.group:false + + + + + org.homeautomation:${project-base-package}.plugin:1.9.2-SNAPSHOT + + + + org.wso2.carbon.core.server:${carbon.kernel.version} + + org.wso2.carbon.device.mgt.server:${carbon.device.mgt.version} + + + + + + + + + \ No newline at end of file diff --git a/modules/samples/currentsensor/feature/feature/src/main/resources/agent/Connect.ino b/modules/samples/currentsensor/feature/feature/src/main/resources/agent/Connect.ino new file mode 100644 index 00000000..6694e07c --- /dev/null +++ b/modules/samples/currentsensor/feature/feature/src/main/resources/agent/Connect.ino @@ -0,0 +1,157 @@ +/** + * Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. +**/ + +#include "CurrentSensor.h" +/********************************************************************************************** + Use the below variables when required to set a static IP for the WifiSheild + ***********************************************************************************************/ + +uint32_t ip, ddns, ssubnet, ggateway; +String connecting = "connecting.... "; + +void connectHttp() { + /* Initialise the module */ + if(DEBUG) Serial.println(F("\nInitializing...")); + if (!cc3000.begin()) + { + if(DEBUG) Serial.println(F("Couldn't begin()! Check your wiring?")); + while(1); + } + + /********************************************************************************************** + Only required if using static IP for the WifiSheild + ***********************************************************************************************/ + + ip = cc3000.IP2U32(deviceIP[0], deviceIP[1], deviceIP[2], deviceIP[3]); + ddns = cc3000.IP2U32(dns2[0], dns2[1], dns2[2], dns2[3]); + ssubnet = cc3000.IP2U32(subnet[0], subnet[1], subnet[2], subnet[3]); + ggateway = cc3000.IP2U32(gateway[0], gateway[1], gateway[2], gateway[3]); + cc3000.setStaticIPAddress(ip, ssubnet, ggateway, ddns); // required for setting static IP + + /***********************************************************************************************/ + + + sserver = cc3000.IP2U32(server[0], server[1], server[2], server[3]); + + if(CON_DEBUG) { + Serial.print(F("\nAttempting to connect to ")); + Serial.println(WLAN_SSID); + } + + cc3000.deleteProfiles(); + + if (!cc3000.connectToAP(WLAN_SSID, WLAN_PASS, WLAN_SECURITY)) { + if(CON_DEBUG) Serial.println(F("Failed!")); + while(1); + } + + if(CON_DEBUG) Serial.println(F("Connected to Wifi network!")); + + if(CON_DEBUG) Serial.println(F("Request DHCP")); + while (!cc3000.checkDHCP()) + { + delay(100); + } + + /* Display the IP address DNS, Gateway, etc. */ + while (! displayConnectionDetails()) { + delay(1000); + } + + if (cc3000.checkConnected()) { + Serial.println("client Connected to AP"); + client = cc3000.connectTCP(sserver, SERVICE_PORT); + if (client.connected()) { + if(CON_DEBUG) Serial.println("client Connected to server"); + } else { + if(CON_DEBUG) Serial.println(F("client Connection failed")); + } + } else { + Serial.println(F("client Connection to AP failed")); + } + + if(CON_DEBUG) Serial.println(F("-------------------------------------")); +} + + +void setupResource(){ + String hostIP = getHostIP(server); + String port = String(SERVICE_PORT); + + host = "Host: " + hostIP + ":" + port; + if(DEBUG) Serial.println(host); + + jsonPayLoad = "{\"owner\":\""; + jsonPayLoad += String(DEVICE_OWNER); + jsonPayLoad += "\",\"deviceId\":\""; + jsonPayLoad += String(DEVICE_ID); + jsonPayLoad += "\",\"reply\":\""; + + if(DEBUG) { + Serial.print("JSON Payload: "); + Serial.println(jsonPayLoad); + Serial.println("-------------------------------"); + } +} + +String getHostIP(byte server[4]){ + String hostIP = String(server[0]); + + for ( int index = 1; index < 4; index++) { + hostIP += "." + String(server[index]); + } + + return hostIP; +} + + +bool displayConnectionDetails(void) +{ + uint32_t ipAddress, netmask, gateway, dhcpserv, dnsserv; + + if(!cc3000.getIPAddress(&ipAddress, &netmask, &gateway, &dhcpserv, &dnsserv)) + { + if(DEBUG) Serial.println(F("Unable to retrieve the IP Address!\r\n")); + return false; + } + else + { + if(CON_DEBUG) { + Serial.print(F("\nIP Addr: ")); cc3000.printIPdotsRev(ipAddress); + Serial.print(F("\nNetmask: ")); cc3000.printIPdotsRev(netmask); + Serial.print(F("\nGateway: ")); cc3000.printIPdotsRev(gateway); + Serial.print(F("\nDHCPsrv: ")); cc3000.printIPdotsRev(dhcpserv); + Serial.print(F("\nDNSserv: ")); cc3000.printIPdotsRev(dnsserv); + Serial.println(); + } + return true; + } +} + +void setupClient(){ + client = cc3000.connectTCP(sserver, SERVICE_PORT); //SERVICE_PORT + if (client.connected()) { + if(CON_DEBUG) Serial.println("client Connected to server"); + } else { + while( !cc3000.checkConnected() ){ + connectHttp(); + + } + if(CON_DEBUG) Serial.println(F("client Connection failed")); + } +} diff --git a/modules/samples/currentsensor/feature/feature/src/main/resources/agent/CurrentSensor.h b/modules/samples/currentsensor/feature/feature/src/main/resources/agent/CurrentSensor.h new file mode 100644 index 00000000..e4e0d4ad --- /dev/null +++ b/modules/samples/currentsensor/feature/feature/src/main/resources/agent/CurrentSensor.h @@ -0,0 +1,69 @@ +/** + * Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. +**/ + +#ifndef ArduinoWifiAgent_H +#define ArduinoWifiAgent_H + +#include "Arduino.h" + +// These are the interrupt and control pins +#define ADAFRUIT_CC3000_IRQ 3 // MUST be an interrupt pin! +// These can be any two pins +#define ADAFRUIT_CC3000_VBAT 5 +#define ADAFRUIT_CC3000_CS 10 + +#define WLAN_SSID "ssid" // Your wifi network SSID (cannot be longer than 32 characters!) +#define WLAN_PASS "password" // Your wifi network password + +#define WLAN_SECURITY WLAN_SEC_WPA2 +// Security can be WLAN_SEC_UNSEC, WLAN_SEC_WEP, WLAN_SEC_WPA or WLAN_SEC_WPA2 +#define IDLE_TIMEOUT_MS 3000 + + +#define DEVICE_OWNER "${DEVICE_OWNER}" +#define DEVICE_ID "${DEVICE_ID}" +#define DEVICE_TOKEN "${DEVICE_TOKEN}" +#define REFRESH_DEVICE_TOKEN "${DEVICE_REFRESH_TOKEN}" + +#define SERVICE_EPOINT "/currentsensor/controller/" + +#define POLL_INTERVAL 1000 +#define PUSH_INTERVAL 10000 +#define DEBUG true +#define CON_DEBUG true + +#define SERVICE_PORT 9763 //http port of iot server + +byte server[4] = {192,168,137,173}; //Ip address of iot server +byte deviceIP[4] = { 192, 168, 137,11 }; //Ststic ip address of arduino + +byte dns2[] = { 8, 8, 8, 8 }; //Ststic dns of arduino +byte subnet[] = { 255, 255, 255, 0 }; //Ststic subnet of arduino +byte gateway[] = { 192, 168, 137, 1 }; //Ststic gateway of arduino + + +String host, jsonPayLoad, replyMsg; +String responseMsg, subStrn; +double cpuTemperature =0; +static unsigned long pushTimestamp = 0; +static unsigned long pollTimestamp = 0; + + +#endif + + diff --git a/modules/samples/currentsensor/feature/feature/src/main/resources/agent/CurrentSensor.ino b/modules/samples/currentsensor/feature/feature/src/main/resources/agent/CurrentSensor.ino new file mode 100644 index 00000000..5b1dc46a --- /dev/null +++ b/modules/samples/currentsensor/feature/feature/src/main/resources/agent/CurrentSensor.ino @@ -0,0 +1,67 @@ +/** + * Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. +**/ + + +#include "CurrentSensor.h" +#include +#include +#include +#include +Adafruit_CC3000 cc3000 = Adafruit_CC3000(ADAFRUIT_CC3000_CS, ADAFRUIT_CC3000_IRQ, ADAFRUIT_CC3000_VBAT, + SPI_CLOCK_DIVIDER); // you can change this clock speed + +Adafruit_CC3000_Client client; +EnergyMonitor emon1; + +uint32_t sserver; + + +void setup() +{ + Serial.begin(115200); + Serial.println(F("Current Sensor")); + emon1.current(1, 111.1); + connectHttp(); + setupResource(); + wdt_enable(WDTO_8S); + +} + +void loop() +{ + wdt_reset(); + while( !cc3000.checkConnected() ){ + connectHttp(); + + } + + if(millis() - pushTimestamp > PUSH_INTERVAL){ + while (!client.connected()) { + setupClient(); + } + pushData(); + + pushTimestamp = millis(); + } + + //Serial.println("PUSHED"); + + + wdt_reset(); + +} diff --git a/modules/samples/currentsensor/feature/feature/src/main/resources/agent/PushData.ino b/modules/samples/currentsensor/feature/feature/src/main/resources/agent/PushData.ino new file mode 100644 index 00000000..10ec4ae6 --- /dev/null +++ b/modules/samples/currentsensor/feature/feature/src/main/resources/agent/PushData.ino @@ -0,0 +1,105 @@ +/** + * Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. +**/ + +#include "CurrentSensor.h" + +/********************************************************************************************** + This method will traverse the array of digital pins and batch the data from the those pins together. + It makes a single call to the server and sends all pin values as a batch. + Server dis-assembles it accordingly and makes multiple publish calls for each sensor type. + ***********************************************************************************************/ + +void pushData(){ + String payLoad = "Current"; + payLoad = payLoad + "\",\"value\":\""; + + double irms = emon1.calcIrms(1460); + payLoad+=irms; + + + payLoad += "\"}"; + + client.fastrprint(F("POST ")); + client.fastrprint(SERVICE_EPOINT); client.fastrprint(F("pushcurrent")); + client.fastrprint(F(" HTTP/1.1")); client.fastrprint(F("\n")); + client.fastrprint(host.c_str()); client.fastrprint(F("\n")); + client.fastrprint(F("Content-Type: application/json")); client.fastrprint(F("\n")); + client.fastrprint(F("Content-Length: ")); + + int payLength = jsonPayLoad.length() + payLoad.length(); + + client.fastrprint(String(payLength).c_str()); client.fastrprint(F("\n")); + client.fastrprint(F("\n")); + + if(DEBUG) { + Serial.print("POST "); + Serial.print(SERVICE_EPOINT); + Serial.print("pushcurrent"); + Serial.print(" HTTP/1.1"); Serial.println(); + Serial.print(host); Serial.println(); + Serial.print("Content-Type: application/json"); Serial.println(); + Serial.print("Content-Length: "); + Serial.print(payLength); Serial.println(); + Serial.println(); + } + + + int chunkSize = 50; + + for (int i = 0; i < jsonPayLoad.length(); i++) { + if ( (i+1)*chunkSize > jsonPayLoad.length()) { + client.print(jsonPayLoad.substring(i*chunkSize, jsonPayLoad.length())); + if(DEBUG) Serial.print(jsonPayLoad.substring(i*chunkSize, jsonPayLoad.length())); + i = jsonPayLoad.length(); + } else { + client.print(jsonPayLoad.substring(i*chunkSize, (i+1)*chunkSize)); + if(DEBUG) Serial.print(jsonPayLoad.substring(i*chunkSize, (i+1)*chunkSize)); + } + } + + for (int i = 0; i < payLoad.length(); i++) { + if ( (i+1)*chunkSize > payLoad.length()) { + client.print(payLoad.substring(i*chunkSize, payLoad.length())); + if(DEBUG) Serial.print(payLoad.substring(i*chunkSize, payLoad.length())); + i = payLoad.length(); + } else { + client.print(payLoad.substring(i*chunkSize, (i+1)*chunkSize)); + if(DEBUG) Serial.print(payLoad.substring(i*chunkSize, (i+1)*chunkSize)); + } + } + + client.fastrprint(F("\n")); + if(DEBUG) Serial.println(); + + delay(1000); + + + while (client.available()) { + char response = client.read(); + if(DEBUG) Serial.print(response); + } + + + if(DEBUG) { + Serial.println(); + Serial.println("-------------------------------"); + } + + payLoad = ""; +} + diff --git a/modules/samples/currentsensor/feature/feature/src/main/resources/agent/sketch.properties b/modules/samples/currentsensor/feature/feature/src/main/resources/agent/sketch.properties new file mode 100644 index 00000000..74829afb --- /dev/null +++ b/modules/samples/currentsensor/feature/feature/src/main/resources/agent/sketch.properties @@ -0,0 +1,16 @@ +#/* +# * Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. +# * WSO2 Inc. licenses this file to you under the Apache License, +# * Version 2.0 (the "License"); you may not use this file except +# * in compliance with the License. +# * You may obtain a copy of the License at +# * http://www.apache.org/licenses/LICENSE-2.0 +# * Unless required by applicable law or agreed to in writing, +# * software distributed under the License is distributed on an +# * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# * KIND, either express or implied. See the License for the +# * specific language governing permissions and limitations +# * under the License. +# */ +templates=deviceConfig.properties +zipfilename=currentsensor.zip diff --git a/modules/samples/currentsensor/feature/feature/src/main/resources/build.properties b/modules/samples/currentsensor/feature/feature/src/main/resources/build.properties new file mode 100644 index 00000000..a7e289bc --- /dev/null +++ b/modules/samples/currentsensor/feature/feature/src/main/resources/build.properties @@ -0,0 +1,18 @@ +# +custom = true diff --git a/modules/samples/currentsensor/feature/feature/src/main/resources/configs/currentsensor.json b/modules/samples/currentsensor/feature/feature/src/main/resources/configs/currentsensor.json new file mode 100644 index 00000000..dbdc7258 --- /dev/null +++ b/modules/samples/currentsensor/feature/feature/src/main/resources/configs/currentsensor.json @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +{ + "deviceType": { + "label": "", + "category": "virtual", + }, + "analyticStreams": [ + { + "name": "Current", + "table": "DEVICE_CURRENT_SUMMARY", + "ui_unit": { + "name": "cdmf.unit.analytics.line-chart", + "data":[ + {"column": {"name":"TIME", "label":"time", "ui-mapping":"x-axis"}}, + {"column": {"name":"CURRENT", "label":"current", "ui-mapping":"y-axis"}} + ] + } + } + ] +} \ No newline at end of file diff --git a/modules/samples/currentsensor/feature/feature/src/main/resources/configs/currentsensor.xml b/modules/samples/currentsensor/feature/feature/src/main/resources/configs/currentsensor.xml new file mode 100644 index 00000000..e8e1a67d --- /dev/null +++ b/modules/samples/currentsensor/feature/feature/src/main/resources/configs/currentsensor.xml @@ -0,0 +1,24 @@ + + + + + + jdbc/currentsensorDM_DB + + diff --git a/modules/samples/currentsensor/feature/feature/src/main/resources/datasources/currentsensor-datasources.xml b/modules/samples/currentsensor/feature/feature/src/main/resources/datasources/currentsensor-datasources.xml new file mode 100644 index 00000000..05fbd3ac --- /dev/null +++ b/modules/samples/currentsensor/feature/feature/src/main/resources/datasources/currentsensor-datasources.xml @@ -0,0 +1,46 @@ + + + + + org.wso2.carbon.ndatasource.rdbms.RDBMSDataSourceReader + + + + currentsensorDM_DB + The datasource used for the this device type + + jdbc/currentsensorDM_DB + + + + jdbc:h2:repository/database/currentsensorDM_DB;DB_CLOSE_ON_EXIT=FALSE + + wso2carbon + wso2carbon + org.h2.Driver + 50 + 60000 + true + SELECT 1 + 30000 + + + + + diff --git a/modules/samples/currentsensor/feature/feature/src/main/resources/dbscripts/h2.sql b/modules/samples/currentsensor/feature/feature/src/main/resources/dbscripts/h2.sql new file mode 100644 index 00000000..6b3be839 --- /dev/null +++ b/modules/samples/currentsensor/feature/feature/src/main/resources/dbscripts/h2.sql @@ -0,0 +1,11 @@ + +-- ----------------------------------------------------- +-- Agent Database +-- ----------------------------------------------------- +CREATE TABLE IF NOT EXISTS `currentsensor_DEVICE` ( + `currentsensor_DEVICE_ID` VARCHAR(45) NOT NULL , + `DEVICE_NAME` VARCHAR(100) NULL DEFAULT NULL, + PRIMARY KEY (`currentsensor_DEVICE_ID`) ); + + + diff --git a/modules/samples/currentsensor/feature/feature/src/main/resources/dbscripts/mysql.sql b/modules/samples/currentsensor/feature/feature/src/main/resources/dbscripts/mysql.sql new file mode 100644 index 00000000..76d1b0e3 --- /dev/null +++ b/modules/samples/currentsensor/feature/feature/src/main/resources/dbscripts/mysql.sql @@ -0,0 +1,12 @@ +-- ----------------------------------------------------- +-- Agent Database +-- ----------------------------------------------------- +CREATE TABLE IF NOT EXISTS `currentsensor_DEVICE` ( + `currentsensor_DEVICE_ID` VARCHAR(45) NOT NULL , + `DEVICE_NAME` VARCHAR(100) NULL DEFAULT NULL, + PRIMARY KEY (`currentsensor_DEVICE_ID`) ) +ENGINE = InnoDB; + + + + diff --git a/modules/samples/currentsensor/feature/feature/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.device.type.currentsensor.device-view/device-view.hbs b/modules/samples/currentsensor/feature/feature/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.device.type.currentsensor.device-view/device-view.hbs new file mode 100644 index 00000000..18f74e53 --- /dev/null +++ b/modules/samples/currentsensor/feature/feature/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.device.type.currentsensor.device-view/device-view.hbs @@ -0,0 +1,104 @@ +{{#zone "topCss"}} + +{{/zone}} + +{{#zone "device-thumbnail"}} + +{{/zone}} + +{{#zone "operation-status"}} +{{/zone}} + +{{#zone "device-opetations"}} +{{/zone}} + +{{#zone "device-detail-properties"}} +
+ +
+ +
+ +
+
Device Statistics
+ {{unit "iot.unit.device.stats" device=device}} +
+ +
+ +
Policy Compliance
+
+
Policies
+
+ +
+
+ No policies found +
+
+
+
+
+ + + + + Add device specific policy +
+
+
Operations Log
+
+ +
+
+ Not available yet +
+
+
+
+
+
+
+
+{{/zone}} diff --git a/modules/samples/currentsensor/feature/feature/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.device.type.currentsensor.device-view/device-view.js b/modules/samples/currentsensor/feature/feature/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.device.type.currentsensor.device-view/device-view.js new file mode 100644 index 00000000..75648e23 --- /dev/null +++ b/modules/samples/currentsensor/feature/feature/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.device.type.currentsensor.device-view/device-view.js @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +function onRequest(context) { + + var log = new Log("device-view.js"); + var deviceType = context.uriParams.deviceType; + var deviceId = request.getParameter("id"); + + var getProperty = require("process").getProperty; + var port = getProperty("carbon.https.port"); + var host = getProperty("carbon.local.ip"); + var sessionId = session.getId(); + if (deviceType != null && deviceType != undefined && deviceId != null && deviceId != undefined) { + var deviceModule = require("/app/modules/device.js").deviceModule; + var device = deviceModule.viewDevice(deviceType, deviceId); + + if (device && device.status != "error") { + log.info(device); + return {"device": device, "port" : port, "host" : host , "sessionId" : sessionId}; + } + } +} \ No newline at end of file diff --git a/modules/samples/currentsensor/feature/feature/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.device.type.currentsensor.device-view/device-view.json b/modules/samples/currentsensor/feature/feature/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.device.type.currentsensor.device-view/device-view.json new file mode 100644 index 00000000..9eecd8f5 --- /dev/null +++ b/modules/samples/currentsensor/feature/feature/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.device.type.currentsensor.device-view/device-view.json @@ -0,0 +1,3 @@ +{ + "version": "1.0.0" +} \ No newline at end of file diff --git a/modules/samples/currentsensor/feature/feature/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.device.type.currentsensor.device-view/public/images/current-sensor.png b/modules/samples/currentsensor/feature/feature/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.device.type.currentsensor.device-view/public/images/current-sensor.png new file mode 100644 index 0000000000000000000000000000000000000000..6a505849fa1693d3826aa6e46cc03f33213b24e0 GIT binary patch literal 135833 zcma&N1yCHpxA42Ty9EeNaCct_8VJFHyF+kYbg|$b9D+N+g1bxb1ovIs-E|-Le)a0T zuj+RQau; zHdj!8Yke31fWYqnz~h@La328h-~s>+O#lFqbO3CXtZ!#r$5X905VjcuR8APrXXr(S0^i5 zdrN9}Z)ZztAv0SC0KjWGyZuw$`_^jq<#@GKnmlCg_sLc@7kiMGSaxO*OUfSc2C?a> zjFdATy(IF>)gkO9AQ$#n1AF8Y%*O%JppoL@-rtz^BF`cMhG>ak{k(7hzZbKBz(qJH zH#Zj#?0FD*6FJb#!qmjlwAk$4<%K7Z5CFZhgbOx~EIInCDKFvVb!kI++eP}QlyJp4 zCLJ&eQ$@Td!5i%z>6@3GoEz+&3lMlF0iaKEjLLa>QXO?CD=fC9XD+ubKO4OsWmIK@ z|4sECTxr(Vg?8sEerGf2`d0UvR9y05&z7G7iho5~~rp$;s0cHOpbZ1x056N(@}<6O0DWZGLHj4c!acJ?5eV1I*lc)YKY1@aVMa zJc9xrP<6BXP+v>o6({FkJK@i*+4B$sYMItP#~L30l)*H_4Csvwz|wU?+RNR#yb|3w zo9d=UvDM&(Eg-}CX^BL`VX`4hi*GmQ z7w`e@ywfQJ{SIiq=%j|YrGgp2e{xSQ4sJe0xYu^r4j^ZJ zc!ECY&pce~cb*|gT3g+Iuz1;e6_vOLDT1DFfL8DFRQlN%Z~J+Tq^83k9UK!li>h$OQxX z0EkoobAUFWw5H|&2kCO~__->ko5k(1;NKJJU!bub8o(Yr`wU=uO*nln#R0$SJQEO9 zz=EOzGH76-XM!vChE)NfLYV&}-7U0737JwHr-{E>SH z#+q$#Y+nh4yz8PVuy8yRMC$H98(&)PTb$LM(0jaM1#AS^{CNFvuYbA?WTw(Udk~yi zTOFC4+WW&iOff`FfmNiJ{y>)uP16|{Dff@`d{|bO206MZj z%?JQ?8#8N*3Pv^rfO|6r;E4pQ2W&YXnA^@A$O!m*4($yIM8SfCi$z633ynZW!NLlU z!XYIkA|<7w<-10CJbLtb1{$Iw+yn&&g-Qj6%1Q=>hRQy8qeNeJk_~igKW53ovW}|Z z0C?*p&uBeVlC%J78A%hFp7snXiYyR&pdZjj6|UQ`+w%2!E|EIV1bR+QoezMC{;QG2 zJx|--<5YX5MW^P%Ma5+jdMBo8VzbMsCS!v8kzP(!N>+LsCvi)ffh)OZ;3JJ0{?}qT zIxFH*`H((nk<=(kbokI@rOhYVc%TJsFAGC~@(73hzI26BiTt2SX1HNm{NNvH^_nagfymR7_>X0&X5+`Iq+EO6nU^)%3BNv^NM(L;DV zDkU}=0nco4PVIEI!>e#Mu3cya4K8qwh-Df2d-a>5CPZz@F&NwIN#1vGIKGbNAiOq* zub6kM$?+GB5D~I4w~nT;Y6Q-Mg_TuL^8Kx-T!cLoKRdyqzikINTkIbC%A|sb6PwVv zWb8_TkR@tUxSznpqL<_?BT6-%%+W6@Y^$u2m17VqXSiR^-po_pbWss9zkxcL~Pee@B&Q zMC>L`^g?jKeIGt+`yF3#j2Vyp8s#&y$8J9^=`U*>60?gpCv@nV_^edlzTlEUeUen~r*D5J{3pLCS$INu+IO#3eA2aE znnvVl`47(=3gqcz5R(LUztZ#&RlgQtkT4M$=s(TB9PVh35#x~<%%v8J4Vq5yEn z?%g(arOEEK<~oavZ=a6amgcHrRAqC&}#2D*|CvQwN<$`*>@#@Vf}0$TX>20zRXQbj6YnF zvv(7dLK@%iK#Ll*Qs_aERxO-$!K|s(^i5FAR_XI1%5&dC%B{=6u~D<;xoLvV588Nz z!)oIit;Idr{D@dQLFho&y9wJ0>kfa#e>La7Jqk6im(v^9;L@E4+Z=DeT-l?Lg=xTy zAAa9Xtn+s0$^Q7KJF{^O!{6bo0-+;=8Y3somlqg+_Si8)-T_+qiUfT_=H>C&FfH^S zITjNwnCPGE4;|0#hVK28Nm;VE4-XjsZCaJ;sGWT;c3Atgau;i7dP3Cr#8DXLW})xb z@u+M2QK;JsP>cU{qPbX*!S7LMPcu3F1Y z5tIS00bR-c^vhCNK$GOY+ zW(+D74{yzU#1xeoJc?;UVEVHOGN1MzT&$%DkxuD~pN}~*OhwYNJ!5bJU6=m)vYu0( z>%B6-K3l8m=5|stD;B-W!1WWFC#(4*Jmr43RqJQK^B>ymYdZvk0*%K@b=?F_yYISz zK~+pyJiUdxa-L@ZFJ9^25?vHOqtHdurl)RB29<3(*&=7i8*f)k^xbZv2=TIpJZb04 z*oG}WPUD|?+v5}fpKNZ3^#-;in-kY|TPzxF zqaf-iQAgoMg(KZjP^k8S@4!UWhj$`8sJXv?_YR>Ty!RDk_D`_{EJxGhNQ$(q^X{%d zm#HiLP67*)e9<32?N7rwB(2SD|Eq782hqY&xRJ>w)=XZ!7fM9C!p=jPSU9x0O_Ff7 zTlujN&!i$BWnVH$%UE1FG1+p5)qIvE8n}4-OC*kMYeFUaqpo|)Zw@ZGgblj1rCue^ zy%UXCr7l*CByQ2^CANv)hK%c}o%3-6pk=}^AN@0z$#1IPdg65{0t`W^EneWcQCyVE z?bg5ETcsMcSJ?)Fa-H{42AvT@o4ZbB7uY>hbrxmRM5H5sLQVc^;%*}h4C#UdueHC7 z`AZmOO~ISUiumEzrzZAPU{+U8vS}ujx{`)FxokU zMy}^?3AuHfO`nDxlV5tPwDqZ;cnwlWju*R5 z9A&iQ0DSV>e<|+K??M+OcEjEu)EXaM{rd)|E*A{en$Hw)<>BL;oHT^(dz9J=VSAV7t9v2e)tWh(>i2 z6b0k~KB_WD9ZY%A4P&X@jaJL6Kibn=u+v>^b@iNe?IZ6{91^d6#w{gO=~&Y^oJm=* zYqma-SV<*N9<;(7-|;+ZISGAqT#UN;Dq26K{JdF3vRq1xA=FQ5WFnE-|L)__ZpYPZ zjSyWwh4uibfVb6O5vloD;`LzhrO+A-#6!H_KlR|9q z&ni|!@s{?R{=5Fj&v`q>thy&el&!R1D?0jkE>21E(cF4tX6s3>I}%&KNabh^E4QM7 zueIUFAQu}vQ;BB>x@V9h-O1DwaA*ChFv|2sf!$|tFhkBZ4q>Pr(;B@s*c=!o{|F5 zFamDsxuqh*%v(>`HZ;b2msnb9V!yC=*aMJt82vo2FI zKag@ZSnl9dspQRFBsLYO73sFl1@RlIjtfgtH!6j47r(46xdswo$ zI1;N!Jg-875O|B@fn?HvtUzyRc=_esZ<>TOn$ncWlkp#VYLT{L9&WE1SMJ>xJvjD| zbd&MmjkuQ>@@?)$ z$3w=ZMOBmfjTrG0tAsD$AbyYc*964vUr&{+L1q1xHm*G6cZX`Cyb@sFf$FpL$w3rr zfZOqxi&${ocB1MTS&~pj7+br}1DwEwo$L?_XUT)(_SfQ<5#&!koW@ye@@2L5&)3}O zVdCVmOeDx%+pQI%0BEZypkbA~ct1B3tRk64xLlmf3QNBJ;-vD4 zFSE=@5&L6QPLtDm1%_i+t39Pp%0ImZo1fW4RTPwIMk1ox*W6Xw@Hq3TGZEaFVm2H3R%{8Z(vO0WIQ~|l!jlp^k z$@F<}C^DikCTDgmEo7fq>sJ;{7j1e-?jp0Y=HY1x5BahBmsxk6pZ9oS*Rd*_q%;Op zj?naUo$5VxJL4!8s?_{R1f==3u$YH1*-gevX-oh2qZRy=kVmTjqu42#z!9$xJBaD@ z`P~;=H-MiI1@9?O1!~PRb`PJJ$7DE!dGD5$jr0I#ny4`(r6>RDeaz0ZLq6naodhSP zSwP016$7d}n6zM}xhG6hGUvmSAQ;d88KEw!&ylg#R@+m?InnL(M=Q!(yAD3j%dD05uG4) zm}{(ve%e8dH@W&6SwK5g8Y1X%h5>CNOi|J!V`KIGiN!g4F_CogInQg}BFRPY(d}+i zS~1(X366FrHiF)G%xp`UN2jXwZ~k#sO9I6jT-}~AtE)2b^_*z-sLP*Q{lSj4QNN;R z=y;+8Tjh+Z}pp`NXBy`v&QXEqn^Br_| zrgmxd(k_WyzrHLh{(ZYz21J63?65=n7k8pUN!7RJD~c}Pfp5mJ5RPmo=A_B4%ojc@ zp=2an<5M5oE`QtI1qKNYN2m7})aB<#PIE57L{tl7H+eZKOPO&zKl@AG{&fyT)fzhtt=!w{gFl|rTA8S_UK#ReFR17Cp<8a=KFp$Ha2ee7sW5LknK3+H zLh_mk@sYMV*|am#2SFG3TZ2l!l2*_53Jepqs|klzwQrNW{?7C82Z`8<~WTYpCjQ5_5}*EJrT07eQ*#oUlp>A#y#!^T>h^cK4>m~8n^tScPfOxC zt?9qm8cxj~y$&-|(3_c-49lI7G4(W_QXl3jhLoft++ zPL_!o5VrNv=4Z5n=_>L~hKJ+N$4E!prI_`<6bjm2fvlc)?z8qz75-N6{`Tbw>)G~Dz$*@+?HZ_bh7F5_UHcy@b zgxt#>zhP(^pUw|H8Q6)>sBJNu>uqUI7!v5M7|qXsMj16h?@_Bq^Rrq2Ts=4mcf3YK z3*V;pWd!L4-r<<{u+|PZeK;n5Hkz~Yc1z?49YkOCSXe^|WD*e<6726i{?v(VFe;HT zwykExJn=jIXFW;p${BvmmY9kUu(uRy8;z>1qwhz=0Rj}3NsnQSjeW4UG&uvHDx5rQ zjYa9}JzD6?A`W3ASBkSue1Ov#A7iShZ!g#8uVU8~!l|zcy@wMTkUZE6AKT(g+iSmo z@zLuAK7|(Wo*JF?r#$N<6eXAwgA!ITM!%0`_Wm(9msi|sW-gADUAHz7W|C@2==*lf zO-aLo5Q5+v$W%FkWA=K&wFJR9b%ckmxad53uB+WVWh~cdOc`^2Pk;6j4}JA{k%5Dn zpAG+_2fq6W2TpmJ9fIjbiU&>wsDC`aDTuy=Ktdlq%NAZm4j(>TbqVfV!4M{oCkpj_ zxZaQy$-@80ge<*mt^SJ%owVuK?FhxN-`1#I78+6SoJh)+uYYIvu+3137CU&jg{#3t~;uk7is zp$ob9qn!Qg-9#@uDHp@E&z2*v>I2spuwuX^BP-9}fbu_^!hay}j~*U4;IAFs0exXj zo=pM90ZoVnuA_+dn6!Y)*X=FfT47{%B6Co%xMs?HM7|u#JR= zBX4y0mvC8`Zp2G#txw^sq5gA|0|cMg`h{PjKX zzWk-8x_=xVfO`*tUWWw0hymN(BXY>dJ>LWLd_Z^YrvVLQFC5VUh}{>DYk#u>zA9g8 ztEC0}sJf<;RCwgv!YO$Uf=TS7z*Ml&o@+3>r*4f|%@p9^@4+Nx-JdO=@g!fNujHkK zf4f_KFEP@Lqqeon#v$-8#bvNVjmvPfZuU%|Q+GGTF;yqIa0V&rJ6$1C9bsJ^*wbED z01!1H;9=Bw@P(D~POz^&KSodKvo`Ft z+ZvBRl$Q>Jj)0uts5|=#7E}MK#;?Y$g-lKk&nqIQ2S&ulhdCupz+@kfxB$=q<(6Z? z8{k!GcVEQfRN(blWXdtl>sjO+gy!9TJhY~p5bg!_m2BbN4GtwNi+Sqq?wse$5e4vg z_7I;_iwXF<#sN5n@Bp5aSfL<6q;o_78KsyP?s*;!bskIDs5AuZjO z^!KpWynyMc6Ik(gE>$W*Og2n-Ha2*4Ha51=Ggh7C0OF8)>wH+v+EuASg&O zP_nld8U!!R3$u_#M5d83LnQjjC-WNdo{A?ZACZ9=9WN=5g`bSOUPzpb5SbB6T|!5U z&(lg)iN)tRF%t1tdW67-_S$@$a*hm2BA_j$r=bKf9nL3jJ^W>!I@ce1kBxEFITabL z;uuP-cI5h^<|NvJpa9AoqjiZcaNPYb(U)^ph*MopZ?B{-%qlnm4{bXfMV{6|wIn=< zsoU1(E7>!4`llG;Y)T|F)pWYu()TvBl)AxaCM6CpP&Os&=o>gBe}ZG+I9FvYFkxF z40*7X%lS7&6s@dY`-ED+WUj(Ac&8;zJ~^hOZiWEkPH|79!*8AW=>xf-Zl-(jSXN&% z$JH0g&3VCkLHfn%4B2p93f-scM8MtF?w?N0p(VT-1*wGL$aI@0RHF^QZZY`jvt0<~ zWt#D|h}}n7j74&^FM)Z^Xfs4qPwSQscHWv9axoL8X=@Fjm{xZdV3l_lDQ0XI00j7^ z`AFBVBCOyYShV>-(PP*B*=DHzR!HvO?#g%rU%M|w8rrmk@L2PpCqxSSL-Dw+nwWMhw@rLJ|W4qyS-)BsW7vj>IpMwkPgQe+_8aSrs|jl~$rWErz@QBXZzw z%eQ&bm=b-_=ayI-<*qH*bF|mm*KAd~V5mMQn>7?HbDHvk)v~807x#NU_DSa(iR@Uh zLK{g(2nZ$cprPm{hx?+eXQg1X9Valwu$pDqrt@d^BTs_^3kLO{D3wu$wAiT(!HznQ zpN%WJUhB=yLsRoYEL6QgBE$U}Ze`c_Y?FVv>3h>0kzAX_^%h(XGV4i=%j@bi+c!Sx zoApURNhWI=;+3rL+Ny$aLI!>iddsMTUVIw+x=2E41>{x(37*XOO3QODZkc7f`-bOZ zwf@fWFS%b&Ku9=7>j5&wAXEUZw z0q!hifmiG;K1-VvDAt(Wzrih2U!U4UPlU(kW(ALNiE4NcvGb^-A+ewCh|K%LFtIfs zCG>c!LAt~`#hqClYyXV3vpd8!fLBeC`emm1ySvNE<=(^-$|gd+QqdLkIII^FZdF3C z|K-DGGmN*y?e)q8TNt!nj=jfzk<7sWf8O$|s&=~WY) z&SCO0|0&`rI2sxDt$(Bd1h^GhTUm3r%y^h|-&X|cZcGe#X8gstQSSCX%IuB1_FVWy zJikdScQxv!f_E|am$+xc-wKNv+;7Eqb_yVq7vStyAx|5S#5n^{UtCZ)4eF~gQ>`_{ z-kmVq@K#gUYzd=H_hwqSP;pe$yF&iCT>A`JT7MwA3!7Mu6M%qFs58_SghvW>n^!6n zW0lheOAQm!+Qps;D=Mb;%X{gPMaJAsB!-zZ(;0dbf}))m`W0_y$UyAz_QSh)A|JXi?L>?DZTKApE3r7)g5kE?3y!HsLd| z8|$Bm8*!|gqW>~hC5nUfJ*oO$dgAFcc;om_Ll5>x`jp%0ayyi50XZAd*+&E&>RA1I zkM3HeXTFu+AJ8)~5z)RFxO{fturxglO~|S^$GAhjATPG~dwBOTZUtXrJFFkXi!T$n z(yUA7ksvt0h;>p0bop)k!XUEfC0+#*^sAVj z-kw$*#W)b+*Yl>k(nRq9)(Fdg2FFj{RHaO6=AP+nwv8p1X4zqq%r$5dZk@J&t>XMo zm;vOX<D;&UxFL%qc%aw{cKmSFo zrfIc`GYfeOJMnz^b&QTJ6T1Ff$K|5*l znXBmk1Q|fuGdY-c-&0KxC$!=X4^NfH>R+7#MzQV2>jMkhcv6J~qZz5df?m*`&j(xa zL%2N*ChG}3iA}9~M6wEV3E@Fk=4f2@y+Y<)FJMpdT^-S4E|LKR>Qz)t`H zHnX-$XS1*$mLcT=yQ!xVHW=%y_vloUX!9P-?4Zt%TMH#Iap@>&#h^Tf@XjyvwEAwF z2we}?7Y8K&5i!ucR44<*e){=YI@Pf98IZNxNV^q6GUF%cS~2}<5klXYRx@!*z`{lj z^p6QPosy#)4GrS-u0F&Dc%5Pc*ze>H>Ru-HQ%UVk!+l1V@ON8U-O9U;Ef!OcygtU+dbU8gU!lVN>6iFQX&bPVLTPV2T4fZ&KJ+0%Y~-%&V1yM z$+nt*GB@h3xa!vp{#ROt&Q}wbSAT!S%ooUR9aq|%oVQ$0FSQm-HJF`RV`Y0uT=e+~ z&Fvryzxk9MJ7?cnGL0{NWtQ-_b&z!Igcytz+^(N1%beZ(ytIjiNMwluRI|`2+Nvs+ zb9g)LiT1xS_j3LxzyQQUs_ftqQE&TA=PaAI@xkSxM`w+wa7 zJbX>x4AQ(O@bnYZM_DW=1btoczj7A9Re%?=cm<)LD6MaJc9Ew`9+cD?sPn1{yFdT%E8^S=v%8M+4;NT_S6kQC!fk`#-`3=kAtF6Wqh2F07h6`U5Ku z8UF(=Sm@1ayOVa-j~e~Jj+L4sJ{d-Gc)vU1$)GA`S2xl^{?h4tk*Lo2(;-m7n~rv5 zs&3IM2~*3C!=34gfx|)`6nOkF6=g6J59|u|S!?E$V}UIzo}{wWa{Jbo_s@uiE*wbf zl?XKVfdHb#5UrXZUnmXzzNo!Yk-AYPKzG4vG|uO;TuM#)46${3c{IPDg`{@-Y>X&M)pqLRt9XmJ5^HBrr>*-^y*QM%mGRqQFr? z*t3wQ+uww5);nCwoHp^Z{+#2UsNY@09C-czqXlHV??>SyI6<9!kS@L}I|3?_X2CeG zgs=BkdLBPb28VB4#mn|s^=H(=+!h;J5ET3wD?CwZ&!f`CH1}?Pe=)k(_g_nN+xz!z z2C`agnG%9*d)6M_zyUt`K#DIf%a@Hr=F)3j(;+l`gu2JDTGVwS8u+~wITGop(jPn8 zTqwTA#^8RB0!hiK{kN@oO-j#Z|IeLQzjt;rSD%qsSog4E#c^s-kZ>$~!%i+6e;KEh zA5rx9M2^ZR9WDGPu)xg}?)KZSlim4xhpjfle@pK=@lNzzZzk}PTFl(U=eSpH4>;~U z;nuJ7))RE!JpK#w6!#v=j!c{sh&rub@;WracSoGKAh8 zl#70if(O$edBzYONv)fwP)EYlRp-n`~OF<;6S0)NTiBKDhSocN?F4>-${<~%=f2(ZrQgDI3oB{XVH zoPvKP>l@^AUOc-;(5bMX9ZuTmB5TPyA{2x}JmSzKYN)k2M;@gR%eOXWaiDsDX zl)9B987+-JByo5sE_ujFL-CDWPW8B|20PP)&h7L5->jfLe&iML)N%6(2>8W^?N$9( zP2(*SB;H;2e@OeVb#^xgp#PUdr~dDQp9h`WoQs>^l#7dtm)neopHJ|A81uYYxw!sY zzFB#A1>Z(Oyga;bm+SxmV6R2I@{;SpNgBTu@Cp0t!jcrl;lA2gBdD zJYOw9c8-pYlw#S$oOgfBOx*awu&0*kn@#keRYYJXT-%E z;06#mlZ=(6`zA#sPJsOtSwIUjDaA^*c&YYxB4N_V09=ZRrTL)62d<@v;NGEaMSKHY zT^AVi9VJ_qo#c=*>wT44 zcY-(A(bj!wgnwA|iQA2?&5$1+bn0`9@v6V?0oN|*d0F^hFX-d1$kN(dU0nB!53;i| zkPFNwX^|A^%W>2s?DVZB#u==hV7P~i_0{`aeD-GOB%FeX1YEyZweK;BV{ROQaJ$37weFr9Nb+OgC83`?VC6 zS(=IXF=69`H-Ej{m-3|r5{%q!mu7|2ZG)_e zMOd}5RL0gOIa-U~zwh~tf*X?JU-L?AX1+B_-O96gKH+nUvY^B8Ui6eq-?0TN!~*NL znt?8<0rOCHc%ti7oULfJnA=simu{Tnq|Be0necF}M;$^<%;_>6zSYlnn86rDX(jz^aK%vfU8B248 zVKO6Yy6;Cik6cW7bZtvy(7(ZtF#P=-WLRMPk+?Mivm`Gs>b}s!=MkDAG!FxFbP$Gz zA#0D!uz5S$A5I%l^3ePys3ZG?i~g~wRpDDQJwD+e0~ba+S=N_5SBG+6rIOW-jJTwH ze=GqID4La=Tz8SQAlNJgO)C?FoLrQgRg{FEfkwS9I5xJt9T!7;;`j<(?-3eG~G8w`rE#)P__WRM|~)^2PZ zhE!Q3UoWA8R-_@@x9iTG&zy1QR9^g+WD_a9Js?xd_DqZgA)n=PjV)ETQ?v_vv1H&> z_|t{6+qdh@-3i?l5H7kJkNY3#Z*KYLOh zF<2`arK(o%=E%5YwS>R<)C=vR>imjyrR&?@ks%oE+j21fB%OD2KqbW^x=E+3l(L?6AAigw|e})9}8?6f^W%tfKM_~U%i%( zU#x2_wNoi0{OwNsCtG(PuCW#9JDBqTgrgoFnxOjjC3{be2^wL7Od5Vd*(kC|^uzFX znZQD*0$!Bb02AL2g+xMg205UD%O6w0_NBPv!%Je#bAh1iQ}2K^Vc)aHYx6U=Q~x(_ z8+--2WG4Yv#@U)L#Q*NN^Oh%t-+8Hnhx~t3*l<0oS{REs|dDa0xKP||=;A{RJ=J%Xg2hRBV zjr!tX0jFOf@t98w;qG^SpAq_>o+pMr4WrPkn*B?e)hNwL)yfy}O?%=-)y$Cp+^c)+%DQ@Tt2b}6Bz?HuD4kCm=S6XQT zq-n6hVmJ7<8Z>ja(Cn{xrTvITM3|J0TGf1ka#?o|HF9{at9WYMf4!Mm-@cyl+PMHd zguG;&UA6<4IVlR$Ph(MmaavcRL!mFp7BC-`quWlZp0fb8qjq1*&b9exYH5Vdc0r}) z#f!7Uq-fEmNTj6hnOCE=ZixmGJpY!Yzxp`Hz&?T~oLa7>?%SI9*|x57rWVW2SFqBL z_@VEcssE1p-m(QWKsax zVxC8OxBah^kn+K@Gl}bG`j7n*mTs^|g#m;>!qMhK45mEvK9r9g_qdJ``W?j}R4gFI z&GYtI3)LWas86cxK+I)9(}F9ZS7B5!rNJ=WF?yMTAT4Y^2PFVE`jipo-r>+(fQ?n~ zxUqzZ&Xg>rFdO6V-ursfTf@!twO5Q3yYKc(%kR^g%Ev)0Jxb@PrMwFCvGkGta$zyA zX))(gherEx&WP)mlM@_gbC}Ik_A&dpzVTK6v|alCFP7rJ32zJO#P|&4VJl`^5GB`H z!gqYTz1-H_Mp<1sy@~A*Hy(lc8%<{DZS}(^1a}Z`o@JJUH%!6D>jD5ZnoS(YV=_ow zzXfgbTmuWsC%QS|^)_)5&rGkaX6@)5PT zdJv_#Qv32AaVV?67Z>GJM5?gUyP1_Dz~!kGR+2^}=)sLnHW4U;Bs*hypCAwClcm`T zA%7Twpi@j;GhX?knffyt7os0M-rfD2H7klU7X^<{b0b8D5-;| z#qX&l3q(yVCr1w0OMAHAn2#r zO@0Kr3)L_fYSBquH;18QcX}CRq?1P8-e9;SDXdG}LuL~wDebn297uzRI_DyX3P@Lw zeoGf-E@zSAH>b6+`h)VY`n%WorP%RMrekG4j|x|K6M>#_{kHg)M&&6BR!Bss9t6yw z!VIfx+2G_19sAYNrMxnUJrKb?G|L2}j=(20u_US@Uz0)9EMpSXm(6Dopg{c`7<}kp zhN{Z{c}V?q40cT7yz50%@k|L&13uiOpntz3BmpeGP2O$~y`{S!CL+77 zc{zGP39`DHRkhqi^H(EUTEtG%8XIHvu?$H=F3~2+iTz!KYyr@$L07{S{-*AaulbKq zTY;cGR|jq2BRbaKeH>f>KYa!LfQyV&1SeXUy6d}g8LX@5=v|EHopN(_wavR*yJ=s) zMdkbr&&17C<9rdmKPSa;*H!)#I9+-7OeHu^vIF58lmp-bmfIicmd$%km18NEt+gd- zAlos08aqi7+A#D@EA3A&EOYOO^56k7^cB>#CAS~@B!_DAl~*HKh84d{29_`*A<#H{ zfTt;W55P=9et1aghixl4yxsqA%roA{{&-v?r?z#Ge+iL`E*iMhnlI4$u=sh(nYR8H zjh~{gF(K^?e^I{kxzD;XMQ6>WXa=~DE;OCUjeKx*s^p0YMf&La*w-ye7 zSSyK^NK8YEu0Bxn_Z^Oc!oEHck1Env;SZPu$#PLD^Hx<6WfS*<j{{NMYis2HVJ> zvNHcswRc93AmnyZAVPv;`J^5LQ2W3nmEx1>{}lT#zOG-qC7D;95o%kPp`ktwiMETSG%=`U?pf1F65Ub-S9MmMW zpxIF9PG4zy0QruMfvF~{oWe+W%4Yf&)`DzR;a7GW)9Az?@0ASvFg9L1UTPM_#5Kab zV7SaEY&CVnxX$k-aCwRqK{`iCos<@3v;U-fF%vJUO%>9w6^g5K9+Wi9($r=H>mStEc)z`J7pv0YM`|3Rey;sJ{E3Tj zn{~U*5uEN*vMu-xqaw?JuGQUHoEnkWDp!=AS zmuwZujmXq%LxE#vQI;06N3m#8Ob_*)4QG*W%4wOPSHKRYUW=a--imQC?GIAsky{Mceh2wgcwsHVz0rOQx#r#@PFea!4`sL&R)Z5`I9xwGJruB9e#rk3I3N8-D^?@=v!H5ONA zl+=8uS_=6XwORY9XGnror`ZQrzBOT#9o)3n)?eQZn!%^392MBPg=k0DSpho)fQ zqOxR`AqIg?y~+iJHd2sifqCI;8DBBM>?${14+-OI`m;3dJ{up;|a1E;xKR zR7Ij#l4|E~h&CckU*RGuf6NV+R#n8~7K%_Nzkq`+J z#vld@jvz>h9ZM){AW{YeWdfLjrg3KCVpC1xRH!O($}R$$vZVo40)TimmY=&upIfVr z9(PbYU87S7Efe=q!0iYqF4hbsE34=qbV3N51 z6{ZH~u*T*e5hR1+-Cp_i7pv#4nk`q9WYiEWOk^2|`VeRSO_i!bkhp(9 zq;<-l(sc#uaU(!XF^}LVlAsWf2IQ0)1d;tjq9*1JL>k#qlyHlhWLcmRc~GgKASjIi zgek5ojP#WML|CO_&f>Niid~Cy=ybQoy1bH5Gq`Xaak3Zk}7T*OnZors})> zjBn#BrMHO}<8!82eHvA(#_Vk6x>Kxs{!!g)bw$m%Y43^kaSjdo!M(yehI)E`Ev66e zXQ*JN-k|!OANnPlVyhvjR|HmxHF?A!Fez!8?I|FX&S6eDyn-btF$rl53JMBJP%@g% z-?)K=NQg+u01)CD+(;k|Ku{xKP*4>pB{D1%LX}Zyxf}-g$q!kKnRrB zN_C&UK`N@o4Xr7S^_oN$W6!Tn+M{AZ>If!phy)r?)`WFnKm{BT$}v4AFhfO~jcO1d zPZ8skI*5r0UVjyK~feHyAnhSRNgq_{;rR!W-qh1sgVwEm6nO(s& zA+3ni42*2Z)CEw0gekW4*+@f}1Rx4BV8m}mIYy3yfTYtH6da3tql7r1CnjYi0G2XH zVI*}mB@QYasR}c(r2vRvXW+NDhFi-!yQ>?+tsO&QX5rxdpE}(=(D4q5kH|!|igZjI zjDhzx%qbP{sq4wH4FifWC=)9h=s@k)ULD+hjN=HFZeAU?OGYPL7slzp1a?FPP$CnD zEw?$A#`JbgNym7@@Aa9eyR>LvW7OzU{8;oF_T$UP=87xk#@cAr6=dS3Bvv(`cz~ya zQ(&Yn^a(1YlujjyCl@14B$-3QuZS5wQ;=9K#8N&U{;5ZZ6kAA)rZxrHTWx_ zIa7rYyfQ&Rs^yQ$czD~2fJcoFpA^Ilm+AjVs;X7 z*qSIDb;_@i?4bb2H*1g-!p7j-mVM@&|Lg-s6o%fbkp$mnIVr}Yl7tAk=^;AFq^t?4 zz(mE@G>BsHL^_6-r{08o+zJZ%slMh)VgT8o#Q{m#0=WRsXCf9DOruvqP=ZwqMJ-%k~WQ|$!*Q(+82QP&T~Bd{TcTB~Snv1DnAERj=CGE_=Pv)=qD* zz2mlbLRpe8nSv&Wsj5OP=iQlwqer`kW?PoFR&H#Z|LW$s7Y2)OxX}i|n=H$U7SIA& zW3rtaFYERy=8vr{Zyh-~UsWnhNXkx1vEEVTWN;Njm^Oh=MI)#nD%&TtwJI?M1!v}a zSLBJi!imFnT&>*dKI&vf)=(vMukD*A^d)M+TO@`W>gQ4-uGa0!1Qe}VV@gyDV(e8! zjezO;wW2)SM>sTmgm?(_A$Wx!`7*|K@~Rauh{Hvl0Ngco?YL8?s$`g;6aXb<1(}Fh zP!RbbmZ%X{q5zmQ7>pt-c|n!{qS9mN!p?5FyS2M{eSNsG$%-tIjFX_`sJ`6suBCrvZ|11&=5pG#%8T{yW4HGy0*qOcf*C}R#`7*xITe94B8N1<13^(hyA(cgr23D))Gjg#0i0M~lvMAv-no;xWj!g` zbF@#K^jf>^V6W+>G{A&$WiW0_Hc3R2mE4rkQu8p~XI_4=d+A4&>G!gO$k-Y zlx(OP2|yM;sIMHv*sLg8)AOyVR&Gf{75b}Nm%qPx{k7r76+hU9ACdvvR$jD;ZKI^j zY+$UCVX{O8b3v4W4ciQ4Tdl0>?QUGSWV+KQP9D%m>!_b>rT&yu83=^LfDxD)f>EnZ z!V852IZ^|(3<{=Jmc6`0FP^VH{Xol_ao9!OJBat=NZ*GuLS^>E?)}0Yhtt~$TOo#K#SXX zyL&Kiw@uEfmFunbE?(Nb{@P&eS~XZFKVXK*idJFKo&k))2pN!#g#*D78zu{CGZ$nG zaSqOrStVvge-cH|df)ev~A?Aa6SMLxzhzWtj%~QTEU2yF zsIPXf@7%byvwVKEbEir=`#DHP8#D-vq+n^R(Lu`o)GC7#R z8QTKZ5NCje;oQ*Lm1{wYscz9Z*$Q46B+(i>L5YQw0$>aXD7}i-B+lAtH>k2Aj}sh_ z5SS>aLZDu^P5WOyKU%xdclp%faQMIZwN6o(TN*v+-W1^GyAiSBI?3Y)UU3BOSxrq2~Q0 zO?Q&iQLJSF;( z{mz;n?Whb58!|<1TPQjJOT;}8gBYAESt6q*Bebl^K?c?mkIiLy<|-wEl1idzkVLGf5HZ-m*!Ve+ctrrE1PT&rHQQR$ zP8lMaF=bOzGY8=~Z@jQ{G9#dyiT!kw;ndhX=9Zi-8qbTGK?Ws)M@>LWeU7@<(`Y{> z`P^ps5|y&|ub*g`n7rSU<>4fT^%gf?Cpy}<+T?qq&)XpF-}A+WtpT$!9A=6z>u+IGh$0NW1E94WhSyhB1!-% zyX%{)H&#!cIqoV25i=nmx#FrCN@~}JNP>!hR9J{S2`e$F2arVW0SHJV)lo=9*;usf zH0zWp*>rVpFwluJq2_Y!9bQt6cC3Sh5^lLt;&?K_8OAxmm>*G3NmKi?9y3XN>3B!? zL&J}Lz5C4kmMBTxE8KpYOnh}QCP ziRrlVZ9u$4#Ptjl6tPf|6EQyC6i`u1QK2R@ z0wyQ6Yznf4uwl-LGnj%ohat@^OisjPGGj8!IhmYHhUlqlm<)$xqA4n3C~DZ#jZ4eZ za|`WmOT8cSjwY)C z-FwbAAN>R_slKgsM7SxTXd+9qXqrh7C3tEBM4Oy$>g3{78Z$5VL&N*M-scwNadwwZ z-dpbKTWSVRX!zYCxV)cE#9MGVba0m5TrM-)%E`|fUKfg<^biLn78WoMiQVHVwgRS-T+1V3b zXnqc)y1mQl)y3XQ^Gil;D1`_$5M?!_kxQZks3DS?^56rYpe&;x(=B5y1+BXQH1SCZ z5Noj}bWDVSdX}?Cp(%dwjnX3;oOHS^$$n#;ZHUr%JTY<46%DqUK2G$ik5*impvsKD zqHl2^!C3orPmFl`SJrpY$b6d@kUil>0XlJ{+quvi1tx^)3>#j9iOQ}Z0*6?gj@8Jh z&IrIr=V_!`igKL2Ydzhpk2O&ufq3c6wGKV_>8oFPrPaxT1Td?~h%!Q#vliQ&xdYRN z&5g~;=CCcc8B9SYW1HK&#d&5rZIk603>y;^vD)_@!b*Nbm5>5LCd=Z{$_AoANrLF0 zU+t`Kj1C_pqTwj-_Y+cs)4xhWOpvkIiYh1kvIGJXML8M)i5eyb0z(KHsb(zPsltwE zji($duhhbsW1Y&zBQTlwP5R!a4kOhVsb-oHQyWZ#n;K41$CJrX)Q5R;iiMTWI7jisIBKp1S<)-w_^x+H5Uzo2W}Rht0{f zV7sO$C@a8umKTz>C@=D?-EMbn(K0#PBBP8&7$7DhHh>s4%A`Q3v>NoQs#FgqZnaQ3 zL7oK-p{mrm5JG>g|ATM5c<=p3TisJqAH9iL%3zMFaj1pzqdy;0vo!(Lq-0|N5rCs7 zJyjm2D5`)E#8_@LajDU9p#=G8P}#NUJ(3Mz5{gKz-)7>8RMl>N4|X>;%CgcZ(xwU+Sk7{5Ou?eBawbwl{YdDv***EK;Qq@j+Cn+BlvBNMRCA zywwPe$VPip|oD!*V?x+*G+BMoac6aNr5UoP@!k>Ut zq>Zc8`e#tBXPF50HHo|)IHfxhul>;QBkpQ?A5W}3ObNHH5md)tyLDa=2}?AAf_>W` z`lAmlnrGd0qWj9Zt&PwUlH7#M8n4j`LRByc=1Y!q2``z9VHCtnDyTVE(Q2kys?@Nx z#L0BWp8VwJF8uL@%(MXmn^87nY=>Gc?#|kFCu>g^#dLeRV_SB(JLqq$jkY$+-j4SJ z6GCCL)^wK*+sqbi6PQGl$g2#7TRXkApp@C7Xis;i7Uqg>7rBNiR3pcbjB{_)dv8!I z-dH<+_inp89ovseU?M@x1}KhbM2R`YgnH8{lt^FzAac)%Ok=?drzlO~ytG=i#9i&J zi*$Y`SVF^(sDbEXIy{{CTao zm2PIr3c)}^(r(iRTwG%uW9?(KmV`>&!o*@m1NwsoP4cS|ELjGe`Q&4lzWFE0Lo#h{ zb!}^&y0iJrT&vxs%;rVc7&{sbb}wA-uPhOq<oV!EwrRDx{L znVCOu)SFf|f0XROjqTy)dT(cUyTwzc+ilHGFC3g6?iM{^K)npB%2(yi^5si+Kl+I> zr0!f4pr;yRr~n(Sn|fN)$%#l!)Tc}`xM_O_fC(NLXs)S)ag$5kTjFw@QH)*wK#0_> zJ$JYX598oLwJTrE%bp}@ND9?xc=gdttfrdlzFx!oiVk=SsrDVi#4RU_Z!?w9i8!JY z57wLQ5BCI)$;<+8XR=1Od=IpzRB5VSy5m^>^5xM`+6aEym|bHeB&X}>^2P>|5Ri#F z6eU?$8uC@GaIBa^%p%Pi>rgsXeohb*HlSESU~$i^#Owt*We6 zFI^t2UTs5WX93;v{pHd6g~9GhsCLym@hc|_u|GI>a4v7#?Ts+XvOmye}zl~Qz{l0;-~))_=KOM^QSk|ev@c-A(w#rl+rqfV+d=)t(-sV8^0Hf+%n&MGym z)Unp&`TFw8?zO9#_Kz-PAuR4LJ>OruD;s-QtY2hHz$^q-h4M} zb+@s;PD&^!u~+COJZ1ftpIT`6=(#@bJI2w|xEDL+!Rx$(xh{ zCtvMtVwv9lF_Te7RgJNC9?P!2=3z7SKF@8P1Ej-ERhcR76Jt^@Och{`9d)gTs*$P~ zt>{?Cs616LLk(392Tq={vj^O;7dg?zR1R{h7cTjom8sT9%Zuw5-t28$48Am+DG`ie zB8o1T(NL<^jH=lJYKTPCnvpG9p%O5&s0PtI8}6>m&QA5#beOg0j?9I%(BJHZ;b_<| zMKnt0OS*d#J;L-MCMlQHY9)|S34l^1ni;Bz*bt7KZhqw|e(@ncH)DNhy!IsifV9`g z2DVAezJW?6jmpN_IDU{PtE2(5lXtHf+<*1Qm>Ey80>f|Q0+Eou;D8bfR5;Am$N)sDLD;5Io7hS#6n zdGq%VEX+ziw>xlC)1A&t=Z-TcPCsxDkwIv-AJsCp4V}6cMV@Ln-d3J}7-{mSC2tJ5PwF!>;B^&H^g!vthg z#(nlgObiLGS08|ykN^sTdM1(yC#%%JQzqWt+5YYyer2vZMR2PZ&Sko8%GbAV{4kU~ zHCbb?5b+dson3!|lo+4&=q`SPl?lowYlq+sXURERgvq$FQq0`(ng7{=C;rUo`|g;V znGS-oieWD{|C-$$!Jue3BvQi-(#IfBC@YL52?(le#99*q7-}+j!6P%(|LWH=Q_Cvs zxw+Ipq$g3)G|^0uI!dH^qzT{gB~ll146bfeA#RZ+PE0*eOGNCqA>a4*#%)Ql@Am0< zR}ZGiU5z~z!CPmaZ$IOx_walEZ53qhI$6B9I21Fb;tQ4$nZO{aPa`65Y(A!lCaTP& zLUD6(4FHVm-^BR_*GX<8ib5JhXXj>4Kl;G6mtLw?mUF-6w!XK${whJq*vN29GPX&u zmS}92O;YcXxQCdDY7#XWBT|xhFC*`SP;?HQx&Mh@Idu1EFqBC(GM zl3I^l72`Xg&>FtQwSYzKu_r`qG7Q$&^6t#Aw=-B=S~zjkOigjoLJ&)QZqr=29v-|S zbAFFh0*!@Z_2&77)2sMhzV*`h0?c@?wcwjgt~{B;5W()HV8^W@J=6j@mQe^b9(y8$*8GBKd>4~wW-xJVYr4uIIHBCO7N$tSx~FN#n0lHd(I7WjFsD`ap zYwp;QS6=$QWjXQi1DC%2wbAJ_X5o;ESj(?0eKQ!IzAmq$ufpj=w#V_Kldxooc-ge+(}&cQu7SP%ufX|Q5LD- z5w;pY#+Syj!%4P{>(!Mj-SliMPO7FoYSxs5_XWFY~lyRn#An_G`3cw zpH8yGRAo?Ri42Lrdqn^<)-Il_R#xUu-kBdfboo19JACToi6=gF`A`37YHjh@C!bn* z=G%82IbmlHZCqbDa`2F^zy|9fd-kIH&4Yy>t1(RGizF(P{5Km_d7Z>N)%xB^M<&|k zME#s}!_)IMQsgJPi_{D+$H{9w;@Hm`esb4aW`y+CO*+9`MB|3M7yAT^9Y-+Xro1Oc z?7`C~AKA%hqHmdhzpDsHAO-{ISb})bma4d_LSX}e4QYsW_o{%&mbdv=h0YG8dZ{hwg{MzeZ{uh4b8^i^XR|=}iL`tM&;vo-6s0J#e znrEGb?yo>O}h{vICzJ0Hw1-YwhXcy)!L#EV?1voLp-62Xfl;2 z0~Nq)2;1A`+IoL|>+l1Q@JxGqX<4fN>0kJzN?|jcc<2*LFFiYZ-@~1|?p-;1?#?g% z;_&pNPCF+*|0VI_Jd83dN2HBbcgnhIA^dvyB2??ms*sx49<6WI z7;aDXTx;CcOy81JPfWgQ9V+%i!;d2h+ybc79M`ubP)#5gB8Ts-A%tW?DO}%@3+UKH zpvK@gQ>=PcnuJ~(lfx#*c=u_90)(Ql5{5x309EN*E%Am!I)p%$$zppq^mZ!{GGjWe zEHW-bT!5kw_?S*mqa6_0gbCFv1QVG{1Q$XvS3LNu|MAoRVK{*F0|Z8iO++(5nF6bcTK7<9h?1%GTC_2F zA(&)o2~rJEV|cW=v-avM-A;S+($`|hY zMAh$CY7RaASlonM7zs)SMvxmU_RMS7W=ytBmZ1120vG+hARLIAIaz{}ZPkdrE8$KmxqSu%Grg8#Ww2ofu(Z zI8I0r#$<9Bh6scrsu4n(Z0A)?a@zzES0lH5;oNu-GH zYZP4P$g%F7XPhCMxALi$caWe^HBn5K)2n4cJ(*`NR8QPhmq?AuLTuM0H@(U5&CL|` zW)5E3;PE%&TCX#ii|*0kq6WD|4PL7OhQ-2hKQz3rxNy51VdBrK;~CL7bZCPuPUOS} zi$*l&9laypYW#C*IS}H;uQ?_f<0Vng|Cxw*PdIr8k=Y3*m;yj%Rea@x0B{;~R3qGxsjEGdG*W^`_y&oBB1?#QZ2c~YzefokQ-o6Z1H1}4C$ zTK5zn3Clo1_sELs1kyTogA;SUw#wOikM}tg@8_E2Ury}%u}OJyBd-eqilg=BVYk_k zBEbb;ITxI-s&X_M4Tr{Oolm%n?hBC1PLMG zYB?$Y*euU%VJsVCt+82_Wx2_UtkrI}^P(tP?RL9pw@qf-t#-TBDT*R5^2}z&8e5IMg7d)|8Vuwqj6KIyK)t{m99FiQFM5*ieY>QCh1r5RrgmbYw82ac(uL z(LJv@y##8AtR?Tnw5ERT@BP=?*B6a&cXp<;&{beKgs-G5)db270u$E*j7D?4ndn6; z@0ei&P*622hihwdM~;e#GH{_>-PpOYICsaLc5W`(@j)qTkpj*GLBMqQkx%YkIlubq zYyIU#Tja&5GsFl^$xyK{S9-t;o8;dYf2vJf?V7m|T|Ny0=`QRu7pn(OMSU$zA4aU2 z(p!#8X?(CWz3IjzQ&cA=whG~KPFinx+H;^aRO}jVNzKD~-wyYEr3~YwzaF)trXe=Q zr)JNAua&Q=vKkEfz1`h@uRrMb`n|z$SoVhfsvP?Ma4;P8hok;*FdX))sv7poYUs+! zRlclzAMElZRpj)zYjJ^S+Y zPyNCJ5hO`m8{0(?PSQSrp~P7hL4(h2&^YOcV}z(pZ&<6KYUU50h*?&@7erx{ts!D& zR*!m44*+Uno3l2bkG#nQ_z_YDXW)vLUwu9wo|(G$!BF|77oXQ^n9VQ1WGYIk#9UT> z`{J8BH!jTI_eAH|F$r4C&UPMuqTCrw-*tDV+x7|<$=HGrx2U0*bJX^c2(@rEM5&n` z`Y2S*uP*W8h8&$UE?`2Rtyy2=MpF6@H98LCbH3T%1Q~0-(If<0kq{Jh9+5uvT4r#J z_}tGL-b*YPBlR?jk^oV&g!ZK63a!erH|X!|Z0>AsZEfvrY;JC@t!-^>Zf|XG?eup0 zqv2rST`amF7BLbDm%-w(T zmp>D%WJV2C6r;XxcR>u!s48*z=z(+3UftaadE1CjiVtXP;8lr|9d2xtMePDo1c?Pz zy~rC;wInHLpczn;R>OD{HH(OG~Ru ztIO-FYrC7y@5^c=>9i72P(TPuWFzKKB&b3J3G&7OlVNHX?X+eX#u5RU&4UE* zD+m!85hYgdya*&naL$W5HwwA+ZYV{YL*Og}iK|LiwM;8hRdv#xZFLs1H($H_*yqob z{m7Q6)z=kFAd#k>lKKg8S(_*zmzFw>H$sw0spTh0YFL8^#aRYoZ_m`0kpg0Jl?%I@ z#mqsn+{(!dG(dwA`>i+L2wPin;81U4I}CPqFTG)kV)3=-TPIG~+4w5xobs?BwU%?wRF!Qya~&VNG;Xiv6wyVhlaOJ z6I7eHV3?aeaqw<^V}0?)()FvCuUxu({o3`l)s5|~-C;Qzj!Ngf1c{}-f{0iVrT^Ga zW;n|Ym~G?%8q3iDA@YL>%ABcyjS^{ylA{4tam+w5}&CW1MjMS)oo>-2^P-du7~b?=1*UK@bNQjDEN3(DGNx|5QSQlAtcOn-A7}H zj2WB&h?8D>vxZ?vrJm72nd${zw_I6C7{Us1>_=Cg`QDw6KVcS*F1`4g9}W+mK26ip zt8c!U4|Y#}`U`!fnS1W*U%jyM($i;t?w9=Ohc@1Ltv{-)&ANvUds52~D0Mob2tKAV zQGP~25ibp8Y6P{ZrYs~~+4^ju8l9k^I0`|H-crCCT#Vv7`4pX+$C?*LZp&Po%{OMYSIqZkr~Es^QoNCIFQymzI{U zT)A@b!lg@ZoWH)jw6VH5+U*Uistj?8>_vz{N&?}aAhOol%yO1zHhHVCs2a;E2ws%D zNC27OT{#+fC-IE;E~uym=QM;s3WOl4>AP_o#q1-(0qV&W00R<5sL}9jDC(w2>U@T# zu|>ntC@w4Fq#I9T27-w}1YqJoMj6Cx4O?TZn(3pbsx}eCv-cq@lxbADwinJw1AG}y z+;Q*)>o2~1{r)FUI1#G^At5EMWvER}SXPQovJ$n6CQ!U_szB0UKx#a1(sU*PDT5W! zO*1nT6ym|8&~W+b@18ty;^@g^%P)L0>&%mB9lrbi#S3Ry{oy#K?*|V>|e)i34SC=+6HV6HYE1i&+pb9nC z+RWNK&#cL8p$ZqO5G42z2ZgcmQ@P4}@0|ou?_3ZcLQoAMhzL|wB!~o&*k*|NWKdB= zIq(Qdk>u5Eh(*Fg^Rv0uNtCw%+VC&#L4>(7L(W!RVU;6%$&-~)* z#n*G}9Q*tiWu`M%`IYZ~l~0^J`s7o??cMcnf5R|$<`10trQbqlx~jx>yP1LWP^VyG zu2tUSv{P#}nke~}HoT67;yK+3ozP!OBjxmKjpyAdD;0RaS~|aJE-Zxyj+?Sl=ID$W zbBB6jBMrnPwiKfz%Xlh2nHSUuvN2eyDRvUxNqCZ|p-rhl0PjPdn!HLB0CSRJU0z;1 z`^xJty!_JnbFVL7TkG`(BjR*nqFc`(H3Pu%~~ zH(y-5xO(!wL!*%z6J054jq|9rs$&?2a$2({?JY2Ch^!1v$&N`>Gi5?()D2aYC@4Bb zcH_C1<`(AjW5;^emc^J*jr?eL_KtgXV_B_rL!CNyYUlI=8>?GKpLnV)!`vOCY`PO0 zJ)(dhNKE?(CUy44@@Yu{5~4{3uCCE&QraTc=_zg;>z}@UpgmVoq81*SZi$7HhE^PH9{&uhQm<^!TaD{r7EHj z5kNx>4gv{?89@jt_25B*kM~A3#2kT?L<1Wm5|C0>u3>_KpfSl;6+mJqv-TBe0QOXu zuCXT$K#5I^GtE3zQF}?Is*)Ph7-A+M1Q4@|j1%X0NRtU5rOf$}R09SAK_M(IpkRVH zS9&Qj$_Y-SGnF5^>-ZZ_zjXY8UrOyRNka2Un_ea|Z5ktU5Pcg^W26`mWrZ3Q0TZD` zp%hjYN`srIdS4tlH1*))y`A0Ni?17--TC=1t-SR7+J*Bc9{J??%U8Rb8^zJ1!RygS zKSj{eiCX5Ft`8bS42YG2g-Xq5swH5Ql!Um}ehAzQ3u4Hs9U&S6xp*^l4OpEJ!bk=y0hVYaslF3fu_Ekh+qsPgt7|W zJ0HAwC?G*ZRRk(jmOe-oGlyuA932)VNb(yIVZ#8c24c#LWj0XFY_~t?P0x0`bA!P! zh7OTHDk`E$dN8@K)R9H^`fb-lg!=15A>Q;b)&Sr!6=OUSt0_*}=!Hb+OHJ}h0{2!h zRCBo1J>WzOBCP^jf@vFqLduaht(-`S5lY~7Ni!Q z)il+V$zP_yK+_&B57l%EodBxW3FFUVXb=@BVo>P!`_Di3^!L8~y;om3yS%nO9C;Bb z%aH`NwkV36ZG;u8u}p;EgLC4&mmuD22+;sZoO3?7;6(z01l16Ow@6@O1sP_WSpsEw z*6wtsy3v$>k^2Kok&olSae*FMxn%h=<+ZAhyTUFhn`$r-*lNJrGnT) zgp7i8=tDQN77TJuj@@}^c46j~@4xhOf9bQT0^(2$q9k!cMF6ZeCbNj1uR^hjKsJN- z*jij^PtVv^iwMfJ{nGQ(%-J1xk`pE=cY9^f?%ceJx=Ku89NC@gEAxj><_ky6^qdg# z1JeN1M_(CXim7z6psKz2KmkN53>7k*rUc@lti)97#-?myVuMnoWT9q{#(Tk}62T0O zbVZ#Y#e`oZ$?(Ns6%=go(jtAXr=0>Sq}+%&)*nrS4yh%q8&9w_<>c}9ZU$^rJFRP@ zSE-25D;bA7X=rypL-eXKUQCslL0DT~`QCTG^Zjps=lq**ZuLi_k(5;#LSVA()|AO9 zcyFy`VpRGf4EYEB5+a z|KV3!hmTKx>CX#i86kLd7Y@uH|2Y_F32^|c1k_mwOhkJLC>cW6I|3RN-y-um&Ke|w zHF;ddrzxZ+<=C|0;x-;*jnyy(K|sw_5Li&cVxji2ixEZuNgYE&xV~*(z9OH0kjqlI zKKyIydQHi%;dV6*f1>3ed!*7Do9Rl#}heejhJ!8;#BgrICp zmgPk7z5=D2uBs{|A!K3qrd()H~Su(2`MqFiVG;L0%|fykkQC@s>~1tLuILVJ#^oTfAGz7&%OHC zuRaE!@HF+FNLuv5Y6Fa=Qfc?{_14U+nVQN7+G_U}FYL5&$0r`S`n|7(%`?60m$$dJ zjz09raDCQQrEM3*kz;cYf4Vz=(1V#0V_8U@Q>|bk#sS0{UFe9Ac0{a4qyb_f4IL%9 zct`J;)LvvwHN`}rZL+W=MJY-~#}X^9DUuYCLV_CJsI_EsI;I&aYGah~sF7;K^l9NGVm14Zn)BZQL0E1A{@*WR0$43E;UGWskF<1)MB2W79SCnpg3ILXt zm%jG3uYBhl-@JNtaZtM9psHL&fX!@{S!0cXVZ+{g=R#Rk-g)n0P!Q*R2+mkzi1WN? z2wbsKC-m5c>UT1<}~I|l@K(9z}9Hc;c)1^4{l`G*t|8>otd5P9$1)}J$UHg z@e@Z69z3)#J-sm3nVN3rxk{+Ya(j1sYiD}KZDEQjO{B!Ozg9;M-Zf~UO4QaQ~ZlOcdAvP*PCYzpZ+csAo!AW<< zJo^XVIs5c$zy5dsMyrM3;=*J`1YJNXwM@hQaOL%vj^BUp(u*&3THS@Gp4_~6Y4*T@ z{_?ezS6;aH&-}UTFTPx4hK!o5HFP|8>Ue(OP;kPAvkdCtCDJ8OyW}7t4RGyn30;G#L2}WjyXkYcD9#>*#^QN9Gm|b~-IzjW#wnHa6F9T)T1Q@|D+Le{FGb zX=QzLb8W4^-P;}YW0Dek&z1=UCL4u4iP>bCMHVxCW6VU0fn#E7*c!veT2c^MW^Sfe zqERz|6lyqPC|E^92nt=_*jia$7lBAH5MzyPWt~=cZn`@+H-FbJ{qJd^jjGSaSZk|F z0>mkef{=P-OvI#NR7ue?L`ux%2zNg9=!;)}`pV01-v8PAD1-o3QOnf3w(5r43wPf` zKzF9CyIZ}h=kI*%v2$PjlLKp~{O0QFmGcKqpP4#-=SZ@{PkhGp`h)GQ**or-CH2vz z-mn0pQVo=tBX^4_YC5Wus9{@!gd0MFicsQe?6C=~sp`>zUMAF-z)3RDT6VK>5>`xf zI${Z-u|7%Igpkx96RCp7Xv!Ksg$52o6UilwjY>bZy@uK#Oqsc?M&J6zH^2PvzkKn+ zwb7{D>Fx9fBULrVSYwSbhK&X|hqA1yva0;ZyVwLw;2dj2M2{XhGCOy0Yh!UZ+}hmS z?r*QJu3Yc!?zqZ{N~b+_Xm0-KiBor-K7IE+cinOKeRtn=@{ZG|4c{TEMB{M z_O;i({-<9)f8pZgD_7R8FKujY0183%zU>YMl@A&utsN#1G25artrj=PBxT~ronm9G z&9a<`qlmGIY+{OxPs7Z_U?O5m%4yn{f(ysxOk_Ad-LN4R5jI9d*c!$Jyi!t=wXEFE zs9Jn;nIAQChoK+|8iC_%S=9@a)LB?jqXI1*dz)o&0aY314o#hU@ZR&^d+y99@3WT0 z1BjZ3)$Z#r9zAwqbGNV6;M9W;-}u4z=Z@W#A3L>r?oG+E**ovrSno}rd64Eh&Z{{% zJ9lW-IVELcB}%kPFa>~8v9GZ&Knyk%rCE{$S`7{|M5ea97*A+vVy{p`JF1b!HP=yr z+ODoS#^X^QJ!TsTR?>*kir`vQSEN7E?pn4ES3G;R=aIcp}lb8$u9`0k{aSS zR?LkJ9GyoM#1J>$by6?!#^*N9HphyO%3}^yO|3}NlgK_n?MXqApviSVo3xRN{8&yX zRG})&4A6@&z3_*>`}?oFbauBl91KUh!(Q;7nXSo;HAGAX-nr4xm(IJYs>+gB32coe zCLaVzod~PTiQm#*Hpc4KR2w?7=Ih#(0J36w08X|z?E%+InhOva=HfZ4D$ zHdaRQAt3}+30{e^#&kXS1k)3(2t=GQneW(=brq^KmPwMpS^MF zlgHJIA%fHCqsMo;bDL*hFmnqlufCGsclXrs35R{%HQrX+v5; zEr2d{6;yf33ea1 z(2&f9h?iHFe*gD=|LJdie`{xZXLr!s9hT04lnomb>u>f!%3GgDL3 zl^Vs-f`+=r_*YFy7T4vixC-IhKPP9V~jPNFqLfLG0xU7+o*Z25Rni9 z01ZLBk65WV%uMh|LKXW;F(5XwAI30Hr4fT+5u2nD(-kumGHi+27_v6DtQfUm5HYJL zAjF2e^Zn%(gJDHrOv|!V;#f^7+O;;Q7^4PIAt^<>$a44qHLJf~qhvBCaB`BvJw(02@`JXvP`0kFfek=!)ijR0BU0CRQpj z5=g?BMvR)oY`!=2#u%FiKu9^GbGW^3 z7Y>G?%4#xx@ftpVug*Op`mmmZ_&k{%1Hr79vXBX$KM;EIef#%6ie zZe_7r$%>4bEgNGjk!3?F61|b3J_F_4sTq%cKyr0bM&Fd4nFxsip@`t>7$2dkNt`k?NN!PmtN~#KD%)6 zNPF(kYhV8(GqrH{pZzPETc|R0WoTZx?!WYq8M?rf6k~x2In9(tjJ2Jba-cE36-kKA zrlm0P>!Q)Uso7X#%+|*wG(^e)Gq0|${La7rH{bux_qKKhgTZiTcc&UvlqT~T8BtJh zVK^9!My_&|$*A3#nw_2QcBglCx34c=+TPmS-rkfD4$jVh>NB7G%+G!9=f3#!4?p_w z?99~UPpo`({o2*nUV8PV=U;mH)mJZHxw5&s>B_1Kt`w0FBm_}4HgC7Poo=USPMH(~{4A>A6F!se*o z>l9P$l3Ob?saVTWKo#Q33V9ADsFWkmZ9@zYRU_Q-$b-+%{K>VapF45p&)B524psG_ z{LnlUQYiyuBF!4C5s#!a;lt6OArL$9Tq_{O9H&;SO7lsMd#SeRNG{`1H6!7{sL@MG z{V9SZewS&~w}{HKk!a9w z+UR0y4P?Szr-G)?P>h-T@j)Ml&=8Xa0-k%}+5ho>_?^oauJrqZ-R<6Pf9Rx4R)-eM z2!YC~8jeO~IU=Hk0}I{m)YR<3-L18ajg^(ftE2wzf%*Ag`ob5#_)EX|g)e>Kfd}ui z6I}oRRaIWPa`E|RpMT*8&%J*3?DfUP{vc{JxZoq;A+Ry+c6)Yac6zGYYPVI@xiB0J z`u$z;7!F6?djb&|W0;xqJkPQ$v$?gL6`5gHz?du&HzTnsCjY5UW)6|*Me2h@T}V|j z9FdQz8Wc(}K|+uqL4ase1R*lUnp6|#%}ElRN~~9$>kmd@x399E8OpLOD_Wh-)YQ~e zw^J1JYqY!LyHmz6jVc#H5ap;XqTW~6GhpR}ItjvBMjy%hk$CSYMw$dDqN+4}}CcA|+VDrCs~x z4SDQNDyzT-llWJ{Sdd}Nu4oXC3N&+B)Dy`G+NaiX5Ly>y4P`s#4j=i@5aWVK_~SqP z{eSoSf3&{d+wS$&x3@;4VT8d&c2L_=RhGS8Rr!&Kwu;Wo^vvwcd{qsWubo?7z9H4{ zp@$y%^}q1zzxro?^}&Z9it#gORPu!L?(&t3&pz|qv)_OA_19isys^~p4@y^+!G)l~ z2UWE;o1L9sI50mwGcBsFtXg??`Rdi-s1gxl*cg*#w$&~SO=mW|rft45>Bm4oe_t<4={jJ23KGIi?AZZ3f>E3v8}10SSx<9sR7;OmZj3U>4{*;@kH7M#-@N$Dt8+)6B32DGLqiFyLSWT;77)o{lo-*C z`T&8rHf)(t?5(x;HNl@LAq$fEW38ClG(` zwF+E+>6Oh(Z*-=n+IfEUYkx3v_|%zS`HLfklCnkj#6e>))oO2?du?#z{M3Dq5)()m z6jX|KJ0~o^`f96a9lqo4_LHAOw_AC&28gUu0gRR~&s>s+Pf}91+2e#cp(8uq)r}np zCQWK|Y$P6q-)KzapG3t?SPgu%LqiZT%)LSHfB0wr{9E7p?#@nsx7XX<9Slchtg)aV zGODz_)vrqLya!}q;ozZzM@HpnV{>`=#^q2ApZxS^|Jq;wYrp#E{_ONr7l0G5iriR3 zw7jzP+%rG;;dh^Y@#R-!4s1N84b%(S&oLKD}(cu_my}AQPH6AV-F&* z1WEJil>EgwK*ksVAc<`RL(IggAg07C)doFVx22OdJwerlh~S7a#zbtawZ-gAYMnYi zD$8=%TVG#1UhY=IQLEk6EF;5Ek1z@naZ}PYRA~Tb41%byg7In%Inm%`_R!Sv#~!%! z%y;hk%;QH6TNjdwY5bR&q5?lRo4pY~BPCLfHa6OvfRJba$%)6UL%f?pq@qUaO$Z3W#czB)tX#SGOMlKT93j=J?CHj}(fSe} zI*K659OX9i+1bvW5A0kyJGFSdb^HVZ7@D>7L-*h7JkH#6FB=HpJc6htQb8i2DJZ~L zJ-2}?YkK-HIp>)TNfHihW|P!(4;#yxNCO*dWsO1dTI;+t3@aL^7d57eR6o+5mqCJI zv$nDJ-~ZG9?wMy^=nY5PJKKZ)KzvA+i6DT3hYKz;q78$Y+U=sZyLJ8Q8)Y^6)Dxfn z8-MF>{@LI7wcJ_&rK@a~XKaJ`mtTG1n_vIN55E7ys~4~B?(}M7wJTHnO&$Cv$o99`PTUDtlHyD;xS(Q~) zmcz;oeefb0yarK-hA8u(5D{Wk2*e;Z7;B-1#G+OZnb>LZKDyT@yWGrXd6v82S=my? zLNx^-trH2N-LP94SQ%l6qHYE#1kSj9XM8s)nd8Q}&3hQ__MVp+o}b_zD6TW(z~`K8drEl7%Y4 zt5_j2#097{((m`yuk3EE&CVSWqN!8&uUBt2P43V-#l+055OYV)cjM;a9zq&_*61hG;j zQVFA|5UE1Jx;Pk(AQ@v!)bJ2AGKNShaI8KAA~wuKQCdQM@IC|vXPGr7Q0257`H{0W zBQQXbX&i{Wie(~J7o;#86b6J!sRK3y;j#=T&m22)`plJQzJJGOA71Eks6;@F#Had8XRB-H`Se2`GMI6M7#6v=wiE`~LmHuWp zQ%F=*uW6FRhD8yDN107x?SZt;15`yd)O~#QUP2HeurXO?obyEBC>Tw~T5FAsGt|u3 zEX`1$q!I$f&IKqc-Hn`=Y5=A%?6qeWN+aG|;-H!Dl{oA;&qLc}Tiy%VbohrrrKh$f z0R@0@_ZL3<-T(fdFTQf=z~{~+vnC-csjAmzcaJ$mB&q_0#0^WDNfsbb5Ht*=I$K6W zeM*#CkQhX%CdZELpt78dMODG=?rtq#*}ZYK>X(YVd*XEW=rK~{IT2AP{qFM0VENjx zx82+B*dGn3){c5iH7c}^ySul(BP z_T6Vr|E<6Izx*rz(O;gL>IkIrF1MM<`0|yDU;o-SzWeR(UpjwfdwXlA-|G$fQiWE# zee}f9`Gq+N8c65o=T&s^>h-m?wJP|$$h+OCcB|FxPEAcu6-6!@2K~WcFdB}A&XwMY z1PXPI9z>Gf3pE(a=u$+CsOmrr3utT?#Hqfqmg322Qc!0yu?I~Yb3#sYs))chA`$>j zmerd2>>>b>cnS{0@KOC#f=UqUBRrIeiPX9?kEtF1OZ30g< zQb%f4<|q{zQ)d&0vvo=>tRxggRBG3i=te;tExQR(TZsS!iQw0$`57vZ!S>3=>YFe7 z-R&G0UOC&Hp1S8({zIBsAOjbaK})Y)=r3J%l~^*}+3x(2yN*3_B%7NSff&p@@>JN~ z+Fn~<`QGy>h#^Tb3gUK7PtjRuLb>`@lrq>FMrN=lZ4dMXUJV{+<8z-~P}3_Mw9Z z0Igh=XL)Y<{Dn9F^iRJ0o$q|_^5yIO!LYyE@AZ44GTrXZA71FpPHE85$j#2pwx^1v z>&w@#+)&aix6`&$wDMM`J=K}Y^W3>|W209NeN|OKy!TZQF99LMp+GDFq^|6l+0!b3K8`dmY6tXl;zBv+bpvg4A>Y65+tai9E`+m=1ilqbZ*GSl&PRzEm6)Gc-pQK z+f#h7)}}q6K8y?*1BOpgF$LAC4?O;QbSSSIklOeG#(v~SDKsQR3h*!g#lL*<2hWYlQExC94l5tLq+vdL zfqL=YljS1Ij~qL3@xq0N9)9@$^ndv;KlQ060F;PanVkf6~byu}iASjLj#gXH5UeQu8~Ls5Ty%H3hMT2iFtNsQw#N zqeOL9P`TZ|@#^!t>lWN>t79P6;rj83^AlRgv6^+H6Fwu2x{-+bx=b&U%K9;&f;^g9^ zHKB-JY=83QFMs_j-x!XD{Xu_J_MIzZGY>$}5ap2o%+JiW3VY$~tAFKx`j`HT|KdMy zx7%giXuNjg`k(yqAAkF+-@JC^`gU)y)9dv|11Q?9?#%Rbt6iAf^oK+5-Jt`A*wWcI z&u(vSXL;6XcZ;IkD!QFchX5aZRaGH`sw~UW`5?@2-aA)C-8TXoL&PwKh}f`=u5)Y> zG9`$3=SC8$(z(h8zaPN%Od&;c_66cv1UL+_Csj3g^REx|aCdJMf zpG9Jlufl=D)5jiuWaW*QmoEMMnFkj*g2K@l#w#@kYh(GMN&*Ij1|>ZS_EohxBZmq? z@P0VTTT@C~Lt9yosVsh{VW=~mbHAr4ngGdn5;4q&LG&cdP2$p?EYOY=M1 zc4pSAD#JMhz!)WvG7Hos53T4e3}#3~X%pEf(JzSqF^v;7ld&oc=OC#s6h$#rguEsh z$#_^xnmnb))U#4zOBc5I(uzKC49M4Jc~doM_q}wL$1d zNUtG67+!hpmEZfF-yQS@gVC_p>ko#bhyoH7QVs$Q!iHw%W>mDlz4Q0~{(t_T{HK34 zW)ekKtgWy8>7RW0PyYR%Uc7K|celT@vpXt>Ad?rZcDvPTweq|LmF?v;xdFNlVWZLBh@svHb=M`hJ6OqLlY z3c*DBR#HW0O4bz$g;tgGK2+6kH0-wr?RKZzZgpFQ=iyb&kB3kNUvgn-1PcPJQRjlm zgaCo%AYc`a&a(>gJ}a#EPz4F@{q(1=J^RBOFTZsB?k}~hs!tu{D1J?%jXZ0N53EVl zC^qn93^D)_!P01Zr+58owY4$Y*%X`4OwSD}-1+Ix^sg?CmM$E=|Do*QT;;Sk6a&)C z+MI|fln~M&fHmDa?_U1KYg<<@AAa;vsiJBDl4PUS0xfB(kk}K<2{Z|c?zv!&h>03r z300-Cq7Wq;;${tLPH9O)Qx8z`1xQOpBYiXJ&9LZD&5PHO+cszsmDgKA6zP2i*^GK)I2eAq)nZStpvd246qxBtiA*;rd2mV-gB?<(hl7g14? zK(TE`poO^wSCx5-{;PlZUw`RKUvd&MHlwoo_h0$LfAVtJCSUp?NCFLZDjjkQBi{A*57Q zQda$5zs$3KQJBm>+j;DhUbAx4&s$w)4o0Dd$yBAZ@;oy{EKqU6Ew0V0D{nd$88}ci z!qErro<4bE_4TKho_yl;-P498Xk!JbQ7th#IH=Yt^qdswpC}{4U2S-<5**N!7cJdyWEJ|t@8CK3;?yqkiedrT5H*p)! zp14bY?$7534pjm$aV@zZLOx;*I1;&1#9}~&l7CPdJtVRg)yfVr!51PTutYDvD94j# z)Rqwfbgblvpde1Lw%8+#uu)>Xx{A+l>#p{7`CLTwN=O5#leQk#xMntBj5h7`4` z3ymd&6YeRh%6;ey3Zk({#qa;&ADlgVeo*?I{-|G8rLSVkUj@;OK_Clrv(63YXJ`JO z|MQ9D4;*~-vBw^MLEG;fCE-o)#zrMD-ys@*ryR$nS44w17mVqJS#LHxBIo|JRkZ72Q3?WM< z7L_Z@%27{>2-nU#dAn5B#Jme03|Vo2Rr=>|Mp)VJa*{bU;K0Z$_+NwFTL;sh|C;6wzJru zK6sMnj%~mB+}!f@nKP$lB(B$6Uta88yflCJgK9bThe^>Xjy(2Y@CYt;OX~3fk@|E} zMXifuQALT+8MB?_sS(sDJdud9Nu5Xr1ga)>%GFpvHBeHg^qMeiA~1}`pGt&?qYj5U zM#k87{PJ}ipR-UGk=~PLrmD4q)C8EJo{J|fNf*2|b|PU&Og2q94U)PQeH7Y|LDeun z|Kf|^``UNP!Kl|83`c{qDt$;UQPF~0LYSJK7KGW^sekm}{)7APyAQyP8`pmCU;mqL ze&ahgmR2@5wzhV*ow&@}B5P%NW^HcRg0w%_-P+omUzol7p1T*XFRd=EwL5JxZ1Zfo zJ4M7I0Wg*GyzIq!VTD-Ds&^DHygs%2}CSAMj!z1tu3io7^|`phSveBy~uJ%0a# z_a8iX&=6czRim=EyAw9O1`!b^!-kDD?IIJA(P+57zOuBubp86`;^N|sD>s&w7uPm6 z`n$WMk@FG|^L}frwMuM?+){Mhjb>OA?Iwyd$do5W9c>Y?ZM^J71S3}s%8Gh0%vsSY zilW_aw_Dv-R*>NkBm^%KM`_8qH&rWEb*+Dh3RBhvWA?^t$=ojdRZ}-gVE+L(}b+R!&O?^+@n6uF*NHWWYA6lMoqL zRrRPmxuE$}=ja!Htx$daTi@wzE){uuYVKhB@S){rp59uz`tWc4wYmErr7Uy(-ubV7 zC-k;WmSyeMp@$ypoI2{gHVP=LS`C#9v90~P>ixs9wn&0*DoPqXwP=haP=zsMb0P!v z$b=y95spquN+Qup6w%I?DYk&gFoJ*?&4~_;u<%B)jibga8Ghxue&$Y|YA0ZK^5#W? zijS>zFn<4a+kv2J*w8I<^Kl0v1&9xSXo#M)z2V@G{@~wjZfp27DbUGP8p|NOu1zwf@maPal7fAx=l`w!l@bZLEaXKQ19P!0){+00mDtT7-} zDa*1y*d6wJr|-J!$k8L`-?%s`N9}G4D#ms?t*!(pgqa3|;m&Tas!9L^vc}kqt+mz~ zW2^+}@Aii~OUCkD_ulvE&wciDU--;D_ubp>cD%33!EkeZ-B+ICYRbrFhBK?8qtS3< zZF6mP?aI|FS1w+>c=6KW_3K+(JHt^a5|j;FYnW}8PtA2KXU62l7@Lue#x@XugV(Ye zdGAET`ydjGp&FR5hdEk9B9)0nK^BT4gg~l6L*+{6%H7^}X0j}6wOidzx7%v9jI}D_ zoC_fUCd;M2{M`KT*KNCN{Q%S@OX{G8Da(R$rI3lE1E!$bA`^*D)&XQcZd4&u(4mSKCD@ER7M&JlT?J5$=)gU9 zv7kLWb?59;*=zkjdUUw)=t*N5x)xig+9cm^YybMH!91ab1wKe-l7mxgal%;JkK+6{r~2l{F8?seDLhq z*MIw8{p;_1_u0+OmG#Yy-p){=u?Ij*Y}gof-dBUsXfO!k9(eG*rK8&kF!q z*0MJ9-beV@U@#c;harSGX2>#=Wm#r3FoGLyu5XoPb?o?&Kl|&y^7Fs&#fKkxq|@z` zqjJ#i_jdatftARbqLnkl`)X%*d+EmY%NMSkKY#xE*lPW7}OdgsZP!39HLQ)7$=N%l|UJrgk+vEz~Co1&2q!)72NUjhX6 zO3bDlExr5#1wVJ>m~;JC|L9-c`N*dZeeM?n_OhV~g1DcfhDJOC>r$ez(2_KpP0)EH zOKu^4@rHi#&di#iy0@Z016qpCTT1l^v>~c;0yNRMV1G+%?<3HL6cxj~w6gN8Z+xp9 z4o2muEGrih^+2N8qbd<*XJ!Yz?f>^b`hPtB#3z5}w}1P0e*52CzIbhOb8EZT3*wo{ z7|W54NUEyC;i#;taxk=PKJnP&&igmscr(v)n^~yIvfNnK5Pa~?x#7?`=Rj(#$upA| zg|(SAJR0@4HrFk;9((MQzxwOH`qby1I&$z}>8f6@x3je!O-7kHH#UfDZ>=pYF1~s0 z+#9dIcJadb<;9g=f8;`leh^unccx}?YqPwtdC_WRt#-Rrw6ZLVpo6Nag4ce(S5-sj zd^z&o2a(47l9KOwy0tVMy3~e@;WfgE!BI7{NtT)GZly`j74gPoB82FbsS<*0Z*A}H z?B+$@ZWq(jQ?1sNCDFAv_?}N^U@IkT%fkfC1Bs)|I*-f(YFO3NR_PB+=cFW^%rS9L zCfJJLm7>#$_+7cDxQt9h0l#)8+;bTiqE%3 z`A(j94%lP&pO9mRw=P}nPS4LAKiN5Oz;s(>rKCy*Mo5D?r^2KlTa%oPP6#a~QMB=t z0X4%hp(<5c83#h>4K}YX^_JHToH|XNj%{^^tD6_T_HU0JKX&R%zv2jCsJ$x}LVsIE zj*3hhF^QxtLyg@{K*EJFh!_FtwN|@}g88fKICY~CKdYDH@|)L%8hbVjfPd}D(_sx=LD}%1E^u{ zZEgI$|HJ?8iO)RofBrxIm*4-^_mfEtBWQ9sD7_Ollv$e>d6C;Jv(=znUSDrdwSVo`f8#fP<2N7v z!~<+>Z+BzVXKEZ=8MY^;h1weq*WE?<>HDvb<<@x?N)}XYF>k z-R(|y+eMZUTTx}w%2lrPz3suUEPV*hRaIF5s6iYxdtVy3OlmYRvxpE8vxyp~AgvKq zG~wz@bpu>${h!#@&aKV74{=&C4!=Zz4u_+vERET1w_BrY&n)cxa(3j-7AiG?G80@T zV2fc0?&N~@M?uM|F#$#@%{nIQ7(av&B}2OdUB0?b&S@B+zcK3V4CZ=SAq6rDkWyR_ z??rqCSCV%@M9E|ou}Y+phbZ3|f*Z>4Mr-VNo<5y^v}l7lB!a}|jer%xlJh@ovocMg)&=a z=EQI%(cqn{s-gGZd*7YvKK#%lTU*~-EPN`a1JW3F=017c6M1L73166CuS`$Irkzd=M(k$Rj{)MkArCS9Z$HZA&sz z7u>Gz@5rzpI<3lk%K!!BFk8ut1D`b zbB*NNB9Z_=L2Ds6Mo^VHb}*?1z@R8t4Orkk0+X*mqK0^PX?3``c=GOt+Q*LB*&@qv z4O;@`JB-Zd{yx;1iy3=z)jIYZr%$OVf9pt|E#-6Q3dC;C&3` z1Y_VugVuU<)JXqQQjtlj6v~818+l_@7dLToo+~ejtV!d4BL${$W|~Y5ZmJq?DkXH> zZ{QDIXt?PufA2d#Sh~9C2mbuoE6#~`UV;Qsji$vaWjR=wpT75jyZ>+h)&Kq6g^OD| z+r3^tO0`pJxsj-b;C!g6aukAu5Zdj|{r5k#vAMaivDRvL0Ad(6tdOX{QI_604-Lkc z|37p89&GED-GyP}H^!Xbw_f{wUia0vAL?$YC4ppuP!PxxCXp~8s3ZkW`9TF)xQYZP zDOXGx7ZHY3Oi~6Lmm%Pyin#2=A-2odA%MXo5DH|yx}|=q-+kY&^Vny<)>_{;#~Arz z%=xXgZ?`Dh+$(getNNUM&faJ5wZ1v#7{Bp*EEbE!VwRFTeE3e;Zhr8${NO+PFZ}Z# z|JcW_udm*E{S9?xh88`4{OHSH{p#m_@w1=*>}Otm{ne|R4H0$SY(6{e`q^yJEf&fC)0$`-NMYw-g#M6Ox28T>Oq5!KH}Z z{gj8+B%8owDNe2ege)*(yFpHpS~{a7qAJe`iNx90a9eDV7eDdm>WTUdU4PI_+b6qyuaWgP?+;JQY zhbftw+gRL`$UJ2SNQK6TXf!8w7gqysuP*uYj3pQawI8VHinU8Os$^Z)S&NBfvVw!9 zb;OS@?eS}`Y#u$nxxTsk%rofwbb8Nb*+zQu%A51kJKaY=xEcKXi(kF|`j_0w*@r)T z`Ocd@Tg>i1-=9A7__bG;-}VXk`1qBt_V+(<@7uq71hE6!&NtPVpkP#~wOHH9`Pn@g zjB1Q#`3kR`HNqA^7P3tj7_v8UDs&@jG zZ$13(@A|br{`-Ib_k7>?+^pBHyz+{xNy5eD#n-<4l~4Zc&wb`IpL^}~H`eP7=bXEI zcy!wL-D0siS{p%|80E zk6m0`o%Z`epZS@e{<*Jw`AgU98>DX5&5ll2^F_B>u2u&}vsstB?B?t3_07|p zi_5Fc)uxQ2QGkbm7FV5dWHVRKhQ!QZaS;KDNaElwFeOg0t_tsY=1O0TVIlT5@d}33 ztXbq=LV!?RgIGjTV$MRuDP;mgnA|g`lsc=VURN~`d{lsu*x5~0UEMf=wdioOE^mG= zf9$)8k1H7#{rq|xF>7hV0~5KkF|nu)3}z7rz2EY^N!AG}E(XEbKl+nim zFbN_Dgv_Y=b1O5Mk|lO34v9&TEAPPBm2G=&@o!ibn2nMkD+Hi6b7oq}E zH#e6ouYK{$4}a$W`-va?(fn;6E=t|m(e)c&yMF5%i|3znpcF&moGEiY{dFHDrp*;) z_d6f_(ERSb!RYLxA7ZBT_W7NUeB11FH5%#Yp)i|7)0JWAP_95i{Pp!5818ANYuDl^Ve<*3wi7jysk@Rc^QTG75u#Gr?is73x=GX>ccD z-VWoZe&H9duCK~ihOMeugv7fMxtJAzQcnGB_SLU^<;jyrV5F3og*g#H)to{EIjU*^ z6J6hbfr?(r&i6UT?PJNM#u#^_x}%m;t&3T zXP&wH@U1t8Qns7**S`9VPk!p>KlSrJ_v-6!yHh{!4vtQ`+%Ff4<-yTnF`Li(VOuuq z@zJ9v*Ej27Gin**43~HeYq*eCumH}&OqoH#0tQPnoCcUv@NyX`=T226MIorR1TjUE zlYpHvG3UfdQrGpf`7C$cVzKCFv&DSb&${`n@B7(eHt%K$jMQ~0NtgQ|o-$`i>|S&n z6DJDGWeWLU01Z}(xtWe5yN}eL>*Gr~nDH?0W;Y#=qeH<%hP$hFPHcR$1&eneWP1F@ zgsd$c?<1xobjk8=wvXC1p-vn zT+M{d4Pn{N;o<>TLYTm~JIvY185(@B9vzby9iQF3nk^o^{?h3)A5@~eILh~4xOnT; z)x~8xILLx0uf6l=D_^|x?ESLYZZDo(KYhZSpZ&Gpw|MSs9Ml|IFu!-~PV22TEAS~5 zv*LVJ5eat=oFL5XQGw7MLlM>{iqM`iYCxTv3FOnSl<)ZfCoUn_@Vz`wCjXYlK3u~> zoe}2y@-FltMB=|X4dC1j;BS26rI)_;wX)roaa1kdJoRI4X2#*ksh07bciz0XxMUHL z%wR@xhk0@GVc14COmqe!>4P8oVA1i(lgE8OBO)y&1dvWVt~cw=){O+RT+WYNqyJ#vsph|%ohiT2g`%ya>tl^t%2;#^44_yccR#ebD|hpVFlRpQ0`-gkeeUS4hAdAvG0yZ0U6nU7ADsEj58 zIIFuA7ba)+MkwNH*^7WVEDooGJWhKxm=}f-Rd-yf$=e#~JD{3f2owT?I;K~i;%jf) zcRi1BFtqa@&UUvM4|O3q1y)QZ^S3zF)g6zb@%U9aP=JW&bD#U%!*?E+Vy+ghcM(u5 zf>B2nSS=d33uzXO zx>5DSI9Sb&PY=(}ANL9W+8_PHzxI2+_s!Q{fBB`Ce(~pj{^vgVsaIclP1U+?c6e~q z&t{AHYPnpdoYb_8qS$}wVvY5}0PEL=Hj~0vh;nC@0G4JQHS}k+xgOQc8L^CB)p^L=K zBEjr2HIYh`n&4jzX4E9&Z<7T<+??E)k&NBFjNW?>(r0XZ@_4)T?ns97ECf(@kP8y>cJmuV&ij;XSb*KQTr5#5MG*Z+Yp?;Om>4FMZ~hHaDB01TamptB)<6 zs^2*~d-U+}<>f_9k&pGH!OV-Uqsyo`Eh9;~d-v{aHhc8w?c8Mojbl+Ix3C_zNOlnB zqoaevqs5cQ4?pzc2ma8%@(0=RU;Zcm$)|qylb`#-m!4dni=@8qm;G$s&zA>Bi{(rb zm(kYi?KqCx&1M`&^SWVhH#d)S$HHBg84}8;kYF(+5G7`T5Q{J+2D8A_)S|CeX72m> zVzoFuIXyf$IygQ&Sgn=^2Zx6TtJQqISS}VlAYJbIE=x|5A>gGI)|$6xx=YB^h;+&TTw$MfMyUd$zo!q4j7xjYo>ij4kes)wLWO9xTvpF+=`4PW%?$3pzY_)}prPN;M;66EysyDeJ zPdw_0r9DY5{8y37)8u;|9^o&&^wR5ZzN%KVj6r0GX^rYF3bS%`^^_SYM-$HOq&8|9 zO-qzNk+j`zj*pLzj*b?~)sv^^gd{1IGMYulOd9U3Zp?CWa&T~Xu)ezbC;o}=`H>&_ z;lKXZ{_5ZP+kfxP*WVb5<-T7W9L&1eVli7Rmi??}Bvre)-mEv9?XVq3C7*C!s`2)j zYv?@-$NkI|36g}^Ud1?SR;-C*++;Reu9mCAql1&vlf$Evqr=0K)1!lfgVl1eSk1ex z@48vnB^H`@eV02IVl>AnCb+3LDpNHI_2`}=rpCybc}mnZb0n@4v2g_z!tb2O%mpxL ze6hrAET)k%%c|N7-#r@M*toE*y3+M>Ge(0$?xczo7oisikGeHjpy*T#$Ut%{Uers` zqUvU*wwEsDD9WnrKDvkz)K$>C!MT|{IiP~CUqT0xe%P#M2L~y$7pDL!2}I(;1og9L z@0~nR-q^pC&&_S?DdyRKgy%=$jBR)+@%2O^@ywwvvCdovED z6dkpgY8~?cVX%-SFjA6UgazQ}c7&-ar-eKsCCtqj=)1)L)<7x0axq^nkIv5SoSdDU zoE#q?9UUAU9v-h|^F`lv^F@~%Ob|&KVXmA~%FNc}a&fUVE6S-4bDKh6sI5q+HLzEg zqB>`qX$iMTcXx3xyO|3~Y*-Ni-0>Vmpghy*fvp}5YfGou-s$XG63oZ#miiSKhJT zG_q8Ll8Bh!b?>5?O3{hhJUFONWy&upNePeEp^EW;BasrD=%QKw3yg zJ-V}e=beW+C+6&K=Ecmk6gLN)B{`Xn`UigE$Nv}q((n5t|LRYU zTIzR4!puUFBxh-)3Q5QeW+s-(O^nTU_|FLQtXr;DhlfY=v$NB?_wSt^ogE*a9G)!a z%h__dSS}XbY?iysU`Z@VlBDpHOv0f@3>-S5P23D%tLaWK(?*#kcVpkZ_mwI~QzQd1 zOYk^AuI?PUU#9LYs$1R6>So2=tR#V{o0SAIqk{vSt%k2ZUG%A(_W3GdTeuX`vUQq8 zE()nrz^m>sH+3T=WTMX9$O_p=!Spa!b2y-;26ZtX2{7{Fl;WTm*BAzOHxp7a2(!b7 zQD=GBUiZtMnaCouA$WuYi(I$L9S$Ss@TI3Pr}WB;bR`c~d(8=Qf)k{U`^>dFVDi{6 z1npXzqtXQM!Cl(NBAkjFvz2!P1{gbiBx(!NZhJTZ#cHn+zymuJ?o3a&Sa0cY#%5Z( zs7imj6>l5A(0FieImOZRO6-d-eifAlfXp4lZ@u;QtFOH_=vXhcnlMDZD?jn$KmLdQ<^Sz3eg5CubIEdY zc6@Sta&vwC>MO5qZf=NtHt)NBwp<)8Ypw(n*;vNScDTH}QZ*}PK~qWSIOQ%7erAzy zc1kHR5_3rM*-VE)!Pe#3*~#h2@#&qr_wL=fb9(>I!NKbAaCvxqFrP2yvwk+0-1S|` zECPYB)I{?n5gS7sw*czR#l#@pDIjXq7m+|`_S%O%C>jy5T}{oLT!f>z)K6z}t7K9& zo3vYMO6ux`h*VWaxZ0=&qx(nt>O}$NgPEqeYz8)#p=fDz4Flko1k7aSN^Tk{vz_^s zm9?sd#?c~~liY;NiIawPxV+)-KDuTvGM4So&AM2HAz>LUXL-Q%; zN{HJbmhW$A*n>R(TVjwzpx0l2>O>9U~=4DG7^YCUQm!CPKJD zk|VNVn0-E9ogAM%c=qhU{b%pryMKIkxIA1Pu2zfrY&Pp>^FGC-kc3$T+-0#KC&kf^ zbOo>0f;E<6&&H=(2*$JRw}K8GH6oVVH4=l5n^Wk0xw^6wBVfqLwsLOK>&$4IcrkHt zF(D_9b`dHk`@xqU1!}-`PvmST81{aor3YnWBiyAl)36odw*Q(xFh;)P(H#JjN z^~U>fGcqS7NzLVy+~EpWDv9A>BXX|F=Jhz99i~O`hZi@8z}TP6dX5B5tq$&>R8NaJ zQd`(gUMJi_W2SN4eeWU;U8YQnsq{XS z1G>FW_5U`d!KcoF=;fDR8MZ?iM;ap_zL=G^tM%pT;K}1hf&7~nRgH|mlrxRxxBs>u z`N@CtPrUGf=fC#y*Z=&V{R`4{WwfsA%3x+n2+LoXDu`CggL`++%=D#iytH0lrj(Ye zqoc!kbfAmRJ&Ff+9>ns9e~bbNOA&a=-x zcmKh&_wJpZ-8nrzK3Obg^F^O>&N&G)5`>!`vz;~ z!;Q@oFJuJf1!Nt$SLRg-QIAFFAh_xIZSok6Iksi2w8d<=Y@Ok-*T-|#A=$8XcL66hCKFE*SEfOnv?u|L&b^QoCUsRZgSmT&>l#F=Hf|di zDBuu~!Ynufwa;KP%oA=dH#f#=G;BAt9>&927B7XY27=bx$}5uZk*Pbem=Of=pj8tf zb@y4TgEZUw=Gj^y7ZAb4<0h*N1hrcRZP8IkT*U+QwFO+6MI(k(g+RBroXK-cZQqI)aHFE4Y$EX>@rBdsiE*& z7$lJsgKxH*x88bvv)!n<5~-WD1)3A3oWOK_eNA994g8P6DKoqM{y+E!{_r39-xalC z82{2={10D!<(00VaT3*1Y$TAWt3p+cY}U{2-apM9f91HyzdJY;rZ5 ztdB#zx7S8avB<#WQ7~msn*$O;;YNX>8g4hy^6Mg5IJ>K4S7Y&X|G>WSq!jRB)@7fD z?8CryOmw80e8OP`VOHDx*B2%jk5q6lF0VJ_6aV`X9SM89Ph$YOKNeSjO zBc736k06uHsA;&_-gN1J+1wS0yupJ6jmuv(~yZHR@tb#6w*YhR;IF zjtKmQYqNoAolx8L`jlJaM3RBIt{&q3vxdaWUZOcU$xdE1ZJhxj7bAcZp^T+4AR4xs zu{I3}II8`uP1{M|#a&IA6{zr}?{%B+LutT2^tbzUVVAMjKFEY8kDokx=X_Xib=1ge z3$({wOBwsVXJ8x$f?H8{%1K~!kmvvEzy62+`9JXcuFkJ=-~Ym=e)0eHSN_UuF|*Mn zVJIa`e`Ag?bK!J)dc0gMUw-AK^Yiohe13RvdU$Z`ZaTVY8HTZpqnZJnB#Th)IAu<$ z14$(j5xZ+Cssm=ickVv8cmKhMKK#LFpL^!+ozt_sXNQM}U7x!?rxaa=Ffs2$(}0^Z z+?|~pQ*8?3aVH~?H8hc&V3ZnwRG$HO9a&>lXwf-VBHc7PhSEwc^5PI(fV6^Bv!_wJ z*_MGoU_^j*yH%_2!(=N43TmfFwsC7GOFo&EheLND<+#sJdhsG<@G`IY%}yk24mMXa zH!qGt+=HOlTC5|~gTGksKLB4X|MVw* z`|tYQPoF$0Rx;;5|L6Yvdb3R_v&baV)Z%7t>SVq;Se~7oJ$>@z@xzD9#o=PPn9mk! zT2#YePSuzxXHF@nERr}0OG-&HgPqjOw0M_ihsQ_HJb3WjbI(5e+_QHd+&{Z}dUA5O zT+U`Wb4uWpQ;HQsP#c4T*5ZODTY+lLHkE~m%{FDX8VBJH-URur1+6=$7KK-*%J@n~ zu8r;%D~xy$xVeOyTHCbW>h-*yA0%)KQ>sF}8j)McP!Qu7rTfkw9O>I{k|i9?bUv41 zEu$7D+PV|5t0t!9OwKRN*xiklgtD5G75C9xor;sXBsF)K3*f{9xwBS%g%e>U$;NPK zL)#MhcBEIYXlpEBW8ZAI`D*Q}1D<(h7S?TDyIswl>#>=DMs60?P9%hoMTQki3(jG2 zkHGHg($=nhhLbiSl>^dT->c<9jj^t*8iyc4If#g)CRx^C%4r%IJ!s27Fu)jO&LCo@ z!Md_$CNG1s@>ezce`7K;TlkK;Iwo7hK+ASF(ja~4LHgf1nK1OXYe z6cCp4gL^MNc>ehppZ~z~51zeudgtW$;9#+wca5VgDd!|fB)Cn)Fd{OSIzZM(5eV;B zvq^bh`}Yb2!ifVT+4BcBid^Z6Ud5&7;rQd2m|@z|4>9Ge!QCx@hAF_P`a^&OkYMgn zi&UFr|1~YKu0@-!o7iAFvapD#mXpOe<8ie4QtV*nmzm2z#-T5Cb?-8sxg!^E46d#f z%}Wj?D^PL^j;fJ53p-fJshE=&A<{5vBzJH`>nNPfC4O8s;A&)vlV@)3!}fZ+UgVin zVUj}$GF9EGTMhafcoL8#zzi*NhNy9ttZs*`lU2qVxte;+xn{=J4J-C1GPye|; z^BaHQ2Od6pD?!w4yB+?czw{qP<;=NLH8(OvNCwb`;=0a#3IBDM#^2E0Cy`R^?7!7cKXaS&%F5J2Od0k@9zD(XLrt42g|S}>@WW34pBSNwpqEvV8@u;bL zg``jkc5rehk0m|x4sD`3W5lz8*uzB^69cw29ZtLxBH=FMO~pfzDuXOKjt6r-otK9j z7tzyMdOS~d4Y&)$sR*!EfAyUL&r~*~<^XsG0{aLpq)sYiEFh*b#uFa-pnx)2>}%=) zin-p1NZkOAwN7y-L7$<;x24E>+aE0YL_UHk{>}QS8Z)+2a<2VIlvEJclHgq1feHva z>iLWS&S>2eXtHJYNK^vU92}E=WmN@nn_37ERaAHqN5|e0?p|VDVon~pzfSC)I9Ks5 zm75_AH^POO%zYROQAZ6JC5kbScGf++Sz#JisR})*(q4C&b|Cx;6Q%d2s{O@8gB{@8 zaeVUV@%m=%rOKj$Xk%vX8ne@SyG}Wg>fMv$KlNw+)DQf?Z+`sn?VR&=vpG6C`Wye% z-~Qy!eR6rQ2;8Om#3^YLSuxXc(GQ#L#rXxXZ#U!G3YfB_lq4m|sbdI)m|YSxCvsAw z#e8x9!Tsl+fAPf+eel`m?%z2*T^=rH%f9adN=Qjk?otX~Qf!hzFw{k$ReJ`)6uVl}Ny; zj(1wyvs%KY(W6ceR>PKE07tV?iy%6M5LiUm?=8#Y8+GOb*5f{%-?*x0CIXtHk!wVb zxj8v=M=oUQRxI>zac{VYM;N%IWNv1~#R-Ysjo64?$pr{ggW@O!Ng_p$oJcvjx!v68 zW=4mMQ0g&R5C)CR!z2=>)y%3UOL)Y?O&Oe|Edkq|7^FstT|nAUGYWq;V>;kyO5FBb zV2ORgN$U8+U=4V(UCcJAw#_55>#|94`jdQMrVY%7n6&ILF=Ia(ad zUi$j0V=;1LLD!`ul5f+lC)YK-n)1I#pgfp;s;;2|J=Rfv$Mm)!&#q` zP)a#>y>uy9kl|Q8N$k1e&4wE962NgimURr+sdZf{gFXxmIV>6?S}wMR0hQI5#Yj@B z`hVX8wd$bhMx|=ff?Csj=CPYiq#21)3q6=J*V_}1nm+3e(%omaN)+3AI3*SnDP=r8 z)b6nkke0uBOT%F9x!aTiqg3;(ucMHR}XrMs`Hzs4@5tRek67Jl{ z#M^Yi6p2v`0@w<+q{b}7<1qMo7?*v|t-KMr?!m3CtCHAPw5030gygz0a`Jc^1<|*+ zuN$x81d8_Cf@x@C$!e3VTyZaz+qvyz|&^8 zGMOq$4Fs;OHK(Md7{GXX(3;67Q_Whd)?k%C6Sk-o;N+G>fVylC2~{;nbP7@x$9d%m zvGRr}z$&+QieLq#;a3JD5>*vRs=8X((PH!FCJAuTmA7Uxm@G)$jX+GwDb>|{oIvh~ zlDUx<(Z;-FQ;ASA15??CypeYXiiMro#mPx42Yi&u@(f{u}^M0G?UUk%KgG%3V&atuiXnYm3lvraIoQ9@kXhh`;T?cu>h z@YE654NxN;yc8RU;)B|DBpsPdTtOBaZ4y#q2_m5Hr~po0xegJ#$KRv@%>>|BFBV z&;9?(V%iCub+C`Al-kDV!gBTaa2rbIAUA>j2?oC2h$;wQ;o3d(siIsruT!2v>d}5|hOvb~NjY~~&7jL~V zLba8dYtK~O0vc1Vit|Y7!qTPU+ps3pWoOhovr_!0E0-FI8U1Hy% z#E8bQy7EF0i$lb8J&f}k?dCGs!URi#+*1p+wKjF{>=7*xp_*yWUS-myVwDu&Z5zD^ zUN?>*iH3ziZDTsdcrRpOX&X49I7_XyW~6J|j9P{f+tJ5?XpHr3c=*IXBNaa8F#RMq zr*KhrK#8Ri;K{T-l=0m0-nMX}HW0PQ?Y$e@o%C1M<;mONGvQzLjWTy(`Ro@y_l<9S z&CRXWg^Bm;5Ca(tU!R}<+F$dXfA}Z==*`Vq$8ot@jb-@v|1W>x-}|@!y*qc$6s)Ex zCorpO49KPtUr0v>tGjpaoS#1#%Xn}wYkfQ?Nz9OxX8mHZI5<8&x&Q3lXPw;e%eiq}@6IJpCqq63IGqy7^#Ez5R) z0Co>0ITbf2gH_X)kVSxzbFZb`UE1PN*&rn@NAuxgn<5HuaO%jikdnj9bs#cuB8b!A zG)6n+s+DIINOVn;tF^C^=SkrOmfS+}5xzWb;0z)dnH}Vg7~`m>y1l;4tK+m1C>eRg zc15j(0S%tFNjg%UbIHlYtI{AyqC&29j;iGANvwphsce^F)N2p_PmqF0NkB=+817_7 z+tJ63`nK4hHjZQ?y9!KgL_?UOI9p}T6G(`hV_*WChox@qa4G`PLa`dDwXrlBOJ(;Y z`t*kln*jOy9Z@ss!|ONMj$=rBr$Qy1F0U^C?%)2q^Tli&w`CknE#zsj$Tu@Exf{&? zwV(VW$H%9S-g$I*=j=;g_`?7BPyETh{@4E2!QpCkbojNezMN9d(h;$H370feI1!7S z+&!8tX0N{XYR=N!`h^)?*Ujgv!^6X~latf4yZ0a5eeleKyZ7%NA20j97fzj|+)2uP z*Y!Ci2s1+%4ymT@aiX}!nZ!F_;jUJt@H;Q@I`ezgneIr2Ui*5h`!DQ`es%NY&77-2 zOl~~YiPpg~skz0=&VV`Xk$v~MyS5jZYCuG`h;uzBF;D~*o2wsTeM=f%U#+Yuun`we zDG`|;F7@7WeC4Vq=7Wx|2QL=RAqF_QJTk<|S*R3H=bYgK*+?3ThhlK^$n?~(op&aQ z(_Fa)Y=Ds}DtS4QGT5jpYDmf$nbu73P1)v~ZCWjeJsC!-L)7jNTWnZS(ML?d({OhU z-UtUYP)k+SN*KlYYwoZ0RgLk)B^JxX5)y0BNaNrUN~lAzQb-GQWHW~oG`Q06TArxp z*H&NbVA{cnghz*%LuedBpCMjnBVyyAX4JmZVbxrQXbRdRza6MOW$zK*f7{r768BCH zP_Lu9ys<>|4}R*WUVizNkAC#SH|zCKMsq`$SP+qcK}quZ=H~bOGr#ADe(P_2a(;1q z_vHWmU;fqq!~gz|f9>nv=w^%4yLX>Hxzthnu1|TUYSoCi%_XbF?Czbr7f&yTaVsn! z0IBciN2`OQ%TOkN`*TyA{ zX_6VCT&zy>RCNNV!8E|MECN@CjKjRT88AgRVBs4XZ4eWT*v zm-77sef_Ew?Psv1phRe!F@S_{eN!T0hIJX7$<%2K7}S`mwmDcB;-v0y2a1Ju(S16e z0R_5;Ou&I**j_z(=lI_9gSnaY32aVA!}ZXu7t*;KrG!zvZ4m3&A4F09vQN z(D|`7vx&Ott8TD$muXHGIoBX&;;Q#_A5k{G8H=w6AB&Zde1w^h!Hmc(WDa}ZlD8qV z>cL=Q99(B@!Wo7{E^j!LTO+*HYS~t<5p-T#^$Bj+{jk*qa5reY|D|DPdfi$C-`$_& z?w&Zk^4cq({OM0_*6X5vb2F6Dg78OXrbJFGGHQALx%>ap|LP}78N0swbARg3{M&!} z&s=SW<-w5^ozJ?*51)uI3p*Dp8fHdj9)^o|@7UKK^kbA`h z>pf5@?T7--?Tdu3>C{u~h>2)Lv=-7misTN;nKYF|RMX#uVGYEM;XMpu$GG9A2Y}l8 zp+;W>Ez5|)b^^XbkR3tRLgjNKSeRxKnQf8LoYct9dEc6(jBV*mbV+#-bo?jhd6OJ2?~Azc#p)I=-N$;8YaBZ_JQX=^!md${^U>oiNE|G|7GM^-}kE4b)A`Sw%e4t&^Wjc zA=WW6B3>+JckiBEJY8?rH_PSf=~ys{SglsaC&$k`^ZdOBcNYhJ*GWz}i*zaF zl=?1rec$yxXBLilD1;|y6WDTf5Q-&Z^Y02Zy~lzKUT3MQg524A_)gli6Zg=5VrkXH z)rsG$LTV~W6(^?&W2}Q>{WAtM!rYj`bQVl(uxNp~>hmM)s*pJhlawP0o=*YG_5O-} zdr~5TYFEM0#W2iSQfH=%x!+xkPagGSVkDc@ou4sL&M;vzz>UKxpF1;$#(bb|9#I_u z*g(B92%~ReH?F%F5LgXhPt`<9oWPwLoxl0=(Q_Zk&WZVOCD%8FS+`f$-72GF8{ETT zk*GwdMcb4KRquzYfUFuS4``+>YilBw8QfjOIXMFc1nIVH%+{lh#k5!%;RR4~t)ro9 zT`aakVhx*aoK+$s2@i%Ug=%b6>`5VNj3$qx8@beuFJvA;x2iO@cJ9JUiUeVP73<_( z_QXVlrT32wx$iL3GFvC=W7V^%yFkA5YRm&j>E8aH!Vb7YOl_0?wjpK znBI8%)&J#B{K3EXcm99fVntv8s@l!EaU4xO&AXIx7&wIO83+)Zo*mu2f9K1;^tIEo zyZ7!tI9#2~=d+WOllu?u-F@cn>R{1#vn0rpa!y^&Nm9x=&-;`+$yvmu8rE`~#Or3j zs0OZDT+753hJoS2w3ka7OGEaFgMfyswN!Htjdc}Q8t?1RcA}W+xVEGrLhW9g^*|e( zeX{PUUZx(4Ro>B2>+ZC6$T1R6L>=G#t5$nH1|lGrs>?%_DOE}oRX2D7I0>FTp_d9a=pLh}|tw*kso8>%}VXIEIPp z@l1(P$W>XlR&K_!E>yNOj%0&{#+!E+%(kH zP14OlPG$)9D?B)rE!6DR#XOzI{mVOqvHNb36{>t+O2gg|QQ@Tbi4m})@oys^Sk@fWr zh;m|pOx-N}SHa-E%XiLB-RS7}R{RR8BAG_QxZm_9dS2|M+0hK!v@)O(HhkM;efjmqQP-lc-A$z3B>;W#-eg#G?0fMTlA6Ma0 z_38-wwCOQH+h$N*@L=)_3$NxbG^_F~#v=0@gW zA~uS)I&c&-gHxbF6(xid$Rv&9czhtoOMTR)n zxp(Kmg9k^a$0@g$vG{$zMs#!oKi}hno)C{5L8S)d@!Fy~zybz{k6_np*uEl*V6-F8 z`YsSLAV#8~;&6>no2>e&P2wX!I8ajshV;J>LdbS z!Gw&ou^Q(NFw3HlyQ#Ux#9|OtW}!-RtZ^>vr37`{sM5yV1LGwoA7Kt~(Sth=e0_QI z^zrKCE_Zz?sesHqnbBsz#?7c-_+03ETbIP8xUjeXC1otjcp7t<7b zu-8}uWtzcRtYY-BPdU%w7t@CW8-$z zVe6xkj_?63?g3_)UPrGau_k=1`Bh=p!tNl-!XAM@Xe6r|Nlay;Eqd!cD{NSw3Z@|1 zMyCcM+7>E>sIPi2jxN?K(Xx^u+upKrN*(PUVs-^~b?1G_q3~Pt%-&eB)0bI2=a6rF z{p(-<%F8!bn{gPguC6y%7g|OL5rSF{_7rm@5!_rjFBZ#T7@}V=Gk42fQdM_LiNVYc zAS4)UIxbg>yLV0wmq&}m!QK1EC&#Bbb>_~Jb7aFNk<2NjoN}M@Y%$ASW)bEzMY&K# z+on)+1AsU$;Q-K({9s|Y6BA4GO{)+=wd&aq7u)5$$K0x|UQB+#m=5v;K-RWn=gzjr z)33x^ntVE@Z!CDcwNHpApF_13Dgb1^b8h;{3(WeORLN+xol{5$k!;IXGnLWk~ z_Oh`>m!3T<7Z254gh)VRJez%L4kHkNrE>_`2v<~?BpOB~NTroI!uP&yB??4BgutG{ zHuY&`2FZ;Zw>4aF1@8EL&Z4B*gNOa@NwZaae*n)J|9WAD>k z)4*!0ml8BYEAH+d5Na_SM{Aq1dcjnfdXKSP!`B;wvtB%I*aJJ;)cRg8FY&D^1?|P+ z#GK@wJUoyjNCXyPc7RjLj80PS@~rRXvw6y$a1vn> z;)sN-up?wzRklq)`@braM-@$00;1KcA2NZF6=(KlFCJRV&j9r~jXl3-&uQ z+H<<21oaxhrgnAsybl!!FBfPyhv zHPZDZ0l`)CeAykIm9KniynHyGK8U?1Ovgdg2y7@ms%!N8KeawzI% z%AAxug(6>_lAF1!BjSa^=q|jasA~DqCPV`}xmKjfr(`?d6Z=O=dS3<#yREQ{L9{jA zaPma*+M92D`HNq9dUc^X>M(5Ao9oTyX0w^~b8-d=O{1S9^!m&^j@xnAR>3w=PCX=z zLrId{yo^H&UNJ4!<$QK_dayiMEEWfchkdtTsb438A(A9XiL-RMo6Tlj--#pK?9jmrBFoKtyYEvc4SE96A)Wy zJ&YiLg~}ZcA+y7S<<;u!=^NkZ@4e8^7Lg;!Yz%`NF;q#z|Em-&K3=%0xfc!*wp(JW z-Y86}fhW0xm4ND?SM_eeIx`ARTFe3rsdn)pp10--iI!3w9g>+bvj;Z6E7C5+wv$Z} zIkYmn0tzNDU`7rlDikzH1#t~%;P82<(?iW=57K_f|AG;V<{L+QdDD~g^?UmtH@B=k z+sDSGXrU5c`r;Q~fAfu-?Pe@xI}V%e#>V01;v(|es%W1X9Am73L9FhkMPrfEb+hGa z74DHKF+i%LnR0p5Ccp(NzN%{NjcBveeN?dI1zLBu7t+A z&T_nO{}&xu^#$D(!AOjW>D$OaB%wQ?*2^`*xb3?G*2N`Fpao5SVtcX*D$C!i_bj){wao%}Yge?fewm9-fMA$~zjwMsU@1q#(0Bde;bGVJ zT1rinlln6@l_{-OhX)6DRtHC`H-=A)D2=RZ2!tjEiznH@yMS;M%+s>gw~0km1!TNsGCnKe5}b`vOh zn9($6i?$>dBB+Hl71L&^vKgbFFXfX#wZ-a`jL4X*&N;PRWN%36PB;9Xq78d~b`>3~#zD1IIEY?- z`PJ86es#MY)T|6;v))=!RekdKv1G}8A1c+V#t9xGF(U~lX3Q7!!;_<~%cX*m6xK{3 zJdO8EL=Fy?2S*1-M@N01yF6p=M3O){>9VApbJulU-*;V3k`hvCuJ6QXU|j6o>v@@U zV&Q-i5fDc4E!KNI3bQwYGb*a!Tw6`wxmURFmSyc2`(7cKnusa>4108@+BMvUcy@mQ z`#BaqnKiZbp;RJMbf$G-?i1gkxfG$boE2W3um|5|CDw(@WO%FO)tru5B!jTb{M?bN zDHtr|N%~nr3Q9z@h8dW%5fvpb2GiJ2w#zhF-wbZZd&N&evJrVywVw#TID#7+xvVc| z%j2Bpk6wQX5{5pS8SE}_m~wzw@L;Qn=Zccr7vGTexzF5d>A+D z^|hH1@bJ+?HO+meru8LvgLuwNM3N+T-E2NPI9O##V;P5Gs2RxBTCvo9Fd?%nXWjA1 zYO!49)NvIpL6`x~+~t%drGC~+mpL(WjhQB{8n@UQJDb&I6kOOraNRNF!snzlVAW#} zl*ol5A$sB&VE={UhGY6ZSX)KfI}5WGjdp7ZJZUlalMZe}zg275s!d}@(BuRg6s(X> zMZ1d$)Tj!9Fs`N6El;USwcbZ8mVrqiaH{5tv7Ly8nUO$P*wvmp_LYpnm3zr40SQQ4 z^^!u|DXF_s?4QHqi`-F1{FWNA6NODOw!mO4rfW8L1H%XzeE8byXKBva=e8jOvkgPp zDp#s72+*AwM%=kdP8i9Q+(S~eChoCu!FRh!wi+ib5P=p`0IccaxE1;{y(TDh+ z%GTU`S{a9#C{1hQnrBKJxv8KKcEZV=im~nsb75v)tTu#Gt5WM}aP4ZRWA%+Ahex5~ zcAe5BF@Ns|ig#@&aJyvGodM+W`NcP0dU;*8qZT*YY`5FZCXmIetIPHJW-(v5xvFYp zZuqVn?s9*yI%MXtlv0WnjX#5My<5qG7Dvp>!^6Xavy_<=5da}!hcFUSCta4=tm{)w zoLQ15Fd*RYOQ2}6F|8>k6EqMc0H3``kLd#4{iI4YPn8<|w6$uXwEv3UbFxx zYQ6=J5SJez2F}9f;+|%JMDuTwIL>tC((CH+RCyFG|U(-KG8~Q^B0W1FnOq( zPiuTOW(b6>MeT*?P*NiBYObfVAvz~Ga?asD8_Howg7oA{UIMG(+5s9`ln%nvnSizR|pvFDG|ek5kY<#et7lP0d%!k4Q1S@3Fl6H(4u4t6+xE>K7guIgnNJkRz5HBd(hL2uf68 zXOKF!j>cOJMii0LIGS0QomgeC*Y`h6HOK%1Gl?4`xUG$aIBn@Unup4sc(4ES+t=4r zjvH!*S6+GPowwh--fl}#Ro!m48rB%VdcD4QdOn-=&0yI*22VFYQ(^`Sy6^$XxvO>$ z;4G0=AAAIMqMY;5$?0;@B?du)JH|v{PFW;#KksIK}%Wk(4NfQ6jlOo7f3fo-x{ z0|^Y_35_;NHpanpva8e9j^zQ|8s6IbK~;=}y_(`Q%?K4OY;u~4_wANG)y?=_E!(ac ziR-BDP$y^uA^0bT#N9Cs#R0K3Bykt7UaOb2B7<6dD4b#pEiqs+ujYVQY_Fc>EKxmI_l&Y(UK_ zhLe`X=FPNznD2j}%ui8t9Bk`w6nA4|GaHJtV0V23Eb#D?b-)A`mgE)gv^o(4ebj2A zOtWBf3U?)MQG@0bf}Y?~nQ)kTIY$C65owego}B+GhG>mWX|+Z2W?jd`LhMd%Ve|%b z*AnMsLZDnhMs8FQlWF&a7R?=_jNgU_&UzUP!Ur3yEKVj)o(X0XO}^$Pj6)7RE~QwuPK)WT}>z1QhG z%qOqAN|kT-Y7-#anfHmS{8jv}m)+AK6YB8f>)L}cCH3A9J zlP6D$j{U4NGgWo>h@uclx$92uuFE;6-1U8*bB-3HZb)0HcUX-$fYj!BCnhkOSg&-;{x$#t!L1EV07~9CaJ~mR z`0Wnge5a_yUUI-5ovAInr*Xp(@$G1yS>hGf;Yr+Gz2YG5(sq^r6SGdD4z36#H&)Xw z!DMQTXv$Ycdt=%6zdN6lWl@8!NlTol486kFy%TPT>hPpn(6_l2|?6^HIe9D)ODAFIHY12t)!#wI63YK?2_+d<@dg1UN)+X zHJYiS{RcQsxV4=xN(usiMgQKIvBh(l|0Sf?**(0Z}@1&YAI1u?SRB3#%m9OLEjtbap z!Y5WMVe&D(Wt_doex;fdvtKu(O3Ge)#f@uNy+GO<)*`Cw=h`mY1hxk<@U#({gt*fR z$}6*Rhk90f`%2A@%g>r5eBbk%TLNcQ0eN*V4*RGGU-8;In8RIR?qNG-%}O=;a$*n* zF|B4!ZeW2B_X*V-g+x+LhmIav$V>2{i*x4?VKp;wA#3K@bhMHZxkJsFre4X;1SD~| zZ{19U1grIcfQEI|0BqD@be zxN_2M)R(tDVzKIzD0iX4klo0I#!o!pxqSoY*Qcp*~%JF%5}JtRKaE=vM2yA6jmn%!hRWt23ORJ;dnX!>8in`ZCZMTL^S<&$0 zDemf3K3(~UZXh$W$%VG6+S-;gx(qmn6JU)SbHGC3!ljT_OTch#s58U#@P(s>O}%N| zBGvfBwj!s=4CH-bL$(#>v{0?IjqNx*eCwfZM;(g0n`>zX&_+h^l#`mDKYbbNxV8d$g>&6P6*5qXUnO}eM%8V$;>Q_1m?ge z$U-|ciNb5~obF|xU;^43C4jvtU`pR<2D!BFk+Ih}w0?gNfUN98-|eFJ@kQTJk1DSz zT85?}h~;@rOPW0PCc@HAdg+Kqq-o46$jET6z#hq_UMV9L;IFF>J_JOnRuqRbY%}S;XjHE>B>>4hy?oOm?#kHuJ4JF)c z)k-n75}}KxW(rp(OLghf)N^jN`#`0@Fg0$hQLGcZdIW8%xJ z>nG<=hGFBbuH^1&Wjn0R6oizLB+;Tbm)GNVJ73J)sfQj-@$Nu9(^$8o#eti$X~ z1Uq*Uu)F6htAk~d1UIgneCj06x;}R~XUWW9NZ|F;1U;Ew;Fh9&I@=RXh<$g?rvuz_ z->b)by?b}%W4fxRK8|R|{-~cUfeVFCVcm(}nklBy%vwj_sN4SLHGK=8jNezPbL=TV z+=L*FB>)h`9o#at_vW*9)1Z3cwx+OY#G0E-v#53_n291NA&>-N;>3BzEMz1Ou`Y{L zZ4{i1^E`J;P$4R@;7nXsMPbl`U^@}qg(ZU-B++}d z&1}gy=_n!y!ehtSTWpoXjZMYf)zow}8;sO|;-bZh7RPANk*(C!9XHZqZc0?Q5k`et z07yOb?p9&)I;}X75yt2iojR8G%Os1%@!eI%)uP+34!KJ;?8+kusip`8fa;@}Q!tq# z7o%1N+8Yn2TpB00ieM6~=_c}7^PZJTI~oQb)%i?yFI;b;heuenmD+w zDx1KH$ZQ8@hQUeI3s&H*l}oP)e&j|HVZLzVdC$Gz+Jr!o1q^6~*}?O)xI>$Bw=n)g zQSLH>-8^y?T$q$Y?Px^F00XIU@gyX0WKt&{qxoWUcAxh&>lRl}5^4OLUE(x{jAr2i zNye^-UcT~-y*db5l{s6n=EGgw88v8LSk;tC;0Z8SEnI183<*$$X}8O%*;o@!RMUMT zgjCH9#x$Fu%j476UtYicqzs#3+`jnnkE{;wUR)J0dDuWq&8ZVC;s)LJ7**AZbTR;w zKy1H-q2|v~6V04!sA`SpZ06mlG2LMs_@1H+?ybY6Dy+Np^glg6->lc0aflpLH8b-@ zo1w1jR3kWm&d<-aXinM8wP+bf_b`a|+;wBociwu_n_C8eoeUXHMDuR3oGn8f6_r#H zOOnuB1DueE+2E-f0k+$EhmVAJViS|^>H^X2#Om8~{kt7&d~a1b4H3IZ!EY6Y_{-Kf z$GrC%PTNiF(XlCD&L)>I+67ebq*~$1;S=9YJ=MVoG$}dj&(-MrJY{%OwSh2mH&44| zbmL*SwKO-Cm9ZPUnM{STZkIvx70&B(s<_6fsD#Pp!ST?G@E%llQV~!0vd^zTMk&ZZ6KBtgo+zaiD7J8qzRx zcS*>dY_}y2{B}EBuh+Sotv6dOrmUJqW;Syt?)&*WZ@sOiElRHCVAYb2l(1aRnHg39 z77>vwlDn>B=ENclA`)USyy?yWF-HxKo4W1L3*y!|K($}kl?mSq+Sn&3dSgvCr)Zx> z45Nvl>wD_zCeEHR3i0k82i*cYfLq^JgDHHMq!RyL%z0>@P`1a+YZe}G=7w)MMRG>X z>}?$33B9zP7Nq%C$uv?Bj6`?tAoWY|EX%6f`n4sQ)p_m5I(-R4^5W7T~aARS>i;)OJG)juQkDkYVWk+{8vsmevQ*n|Sw;L8U zRD%h<%A6+iWix=()ZK&>26YHK6?WE^SV1g#K3n?s{Lw2vefiGU)|YRAY_U4K^W3+e zzW9kD9Sp@JCb?#gpw;ha8rUCNtjb}wS+JjNLqBNHx6m!9ZVcu+I?jL(fgA_vDf{gQLJdt@%-u2 z^=4a!5e6&fyEP}Jl!cSq7#4v9zrMIUIysRfrIchcs*0*3n|hLNb#Ss;KE1p;CyHng zvdZ{mkffQUc?Lr$;%!)xq&|TG7G`m{1S>QwV5#kRr~Jab>4@Il_U`~ln+*J_A_d|T&v_1t%3@g3;!?)AmHIHpYn)uskCTGX@>!=!etejm;1zY%>YmXYkf&(1d5 zw@!^cXvk6;;i+{U&0ee-g@oL!x))42ij$=!h{2usva4&^E@w_j5w|zIluvxeN7m;L zAHQ;)*b{qf^T;MvPne-uEr4zzD6WeaBL)+*i3>EDo2sOJmuNkO%z~7e`<#++@R)XavK7dSJw)K?pm*EelGfK3 z4Lhi^p1pGn|EAR6+t>S!8R~nlkKan`*sU=3e15U-bzI4~x7;_$ePU4iyI56BzCUc$ zg}FnjSEv5$&nr0myWgXO|5inW^UY*o2!CItu88wpl0S)hC<|KCC-mqXwb$`b2DhPlDgUW z=&N7)>A!UI#;1~ib57md!&`=Dkn!^Em%sKifB!?j;fLh#d8^}?=A4GO7ORhMC|0rw zhRu3bHcpVv%Vz7v@@&59k7wO{yt>#00-KX~OE$0MNsVycFq@mwQtSSl>x>zOQWjuY zNcWg_one#Jv~;rft8b`FF?V+p;`R0Q`Stl&hRK<;u^$+W+@+XjRkcs~XmL!Y*O%7< z7D+}{N>MFAu6EL#d9_;3=c{&D5Y7sb&(4CJb2u9T%pxi0z%m6a#6nd}C0s)*9cq)6 z7_w}0Tc)b>yCzL;tNZ>rHHz!hKsJcF}_(}U%v5;*TCe?R)~x-mSh@m=M?y? zR6w|Vx-l9KX9eT->ZZ(=vpk!>@WQ7NmSUQ_kwOTN-J%W5DrluLW zv)z8kb_@e*IezL>;MM!~Uvnr4N**pQF4tE#rIf~Ss_1B}PrB5*!%W>hb$y<3Kc8K% zuT(Xs&W*~bV<}@9Rkf7CTn`SGC&y>gW!dyGPE4F4;f|e|B$06HGs2+<&7leA96fdA zE^@sXn^bLYu%CoaZKoLLa7T8s9o5M9aUZKQ{*GNlw+qCy?0xsP!kwu(+c(hBTMJO7 zV!L6YEiK(|my%s+oAzC`?$kq8Q!v2PQamwb;Orq0fok*QZ?;>4*MK`X9MjpQ$@{@4 zi{;=y9nLwCIlRj$&AKpZfl(4Xd9r@t!O3@j{F&2(*=&|O<|INAMr!DsG8@Rjf#6tO z0u~Kpvxq$pH>loy4m-#+_sjJB-JzfRSOSzDBP1I&(`GF6k+PGl*f_cbZIr9hezCGv}l^X+bjAov5&a=c_ ze|CERe4nkfV;=c80T#Z41%0ol-$j{D`%%C3 zo$OK?TjK|70?J53=IJZ$$6xu*lag<>HqCCRIqtMz=BBs=qha=;f~*W|gpEkGx{1?7 zV1^^|S|g=Ce9ht}gCEQ}krJ^0sqX-gI+!Hk@spb*@*955y^*)C-6ZJ%M%CrR3cG

)=|{t@sdb*=ptpXE@{G;;m2qKXm$8f8t4mSs+-G7&~I@$4K<&J*!MRMw+1jcjQsrKVq3NbpA>ygh5%*~ zb7I{TBAU%+nbW*mJooI2H`kj-Pu}RdMNXaBT2-}_A`IrCY(+4ib*CqHFD{|+2E5ssO?Ofcc5b<5AD_yzQk_oHNa2VA_%qkJ-}_DM=W=J2=})w^ySr7Ry)Pdh6tw=VuwC zD!G8+uvPMFD_e45N<`bL#5X4r)ly0<)>YM1p;iYCCo_elr{DOg?UT>tZU$$`q54XK zgd|QbL{1%?)yi0IQW-7W6ii*DrAIly((*-}P}JSoNr-8UE@5(KcOXhw~4aI1Q%n#Hj1 z@8;y+bpOAL&amq#n!NhfpYC^(@A^7>tm^5d+%Fu}jQE?8j%mi3qAMCKP&p3jJHquO z`mVSI--11-y3k5S&_BWKYGe^ARU4D~mqHgD?%Or?CgzmD2d$DD+H$^tZ=baZSl(uskI=^AM@$IE;2Ui+YM~Kds zcJyMt^Fcm1EE-uSlZ}8BsnKZQq*$pJdCedh#)d6#m3<#cZJ3=`edH+Rcdfoke*;}1Z23XZqCc< z%zW5x&bK3oL<*&(;bTVX#uP5UO?MA=Coy-2S{;rVQg>Dnqcj<{LP(`^dSZRs`M<#6{dwIzM47!KS%yx(eJ@vT4d&A{XynR1$U_GQs+aQLQD9nBE~ z=I{Rcz6(Z%PjM!`H?ve-MKhER$SV+sXkM-TWuq3vWrhe_VxgPCo_+CjzUs%vTj``L+Yg=&_m?+Muk?D0>uu5PR>z@~ty?MMpkpaK ztYtLv@SugFzoZ9bg8Fl0R&(&bZN1nYuC$^WVz^c z9LY!{mM+jib4ctC!je)G5sE!|?Fkr?5;GeCPKAgkYH_Q)Rli*&!Wh-Y;zVo}$fz6@ z!+!Ei49{qOpwq(+YIa@R`pfrPL$Mojt2)dG#A&a@w0& zc0lIDq-wvO6ulK+3gT7x#BdW)V!~W*9U$6Sj ztlRdTr%aJ}#a-(AE_XcZCFdl4pSs-9)9si3?#(NojW<~-Ef1b4PaoUWL#x)!WFc;? zxpnpXE-(VtoMua4kxfEt7S6qRgC_g+Z1?5)xS;tJ7L2oN&FRH8jr%kBI^5KB!U6*l1dp z&|v}u;Yyv1FT8u8EIc7FnGgj^``*Ej`(X)04K}IJHrAUm3|5&W?y9<*e)kSbPI)n# zKmXhdv&9SmdHMC<_q{*!(?9j(>08Xw^<7<^yKB+HI)EfemeltG?#4lhKsKnB?PeQe zudrkhi8ri9p15%Ij;Tc!>lB}}KWrOKlBpfm_^zLN-zL|;X)gE{)#AU)OS&I>xx2de zz>B?nuv!;O@%j|HBC9}4GWKkv~DDVEK`L5d-WqK!(?#a zleUB$M5XA5o?Sh2@8D~%Tz&R9bytV4yh6YBI}iWozvCnKj_B#ri8n)ZFzi9XFjI*V><>QlXeX_ZHygYqC0%1x7 zi7uW%Kx#RUM&uMJ5AI}W@#t_8_l~vr^p;^7RA?hsf&(Lw6=#cg#Nm<2 z%0!h;Ppvtm%4!JaSUBrdIDDe;(R)pKn$m`=5VDQL*lgCi-gudMv>=&8;2I}MW-5Y| z^Wo{q>76^y)aC5v$0rBB={Nu2fA*jK$GIB-bU72bYH@ND0y^O_%_XN!IJ<6)j9E6r zcz$t7kuk%>%od|?ZFd7!WDZn^YwI%2L^a58??g|4A8xb1_bUKyW0Sk1yO$dF-?!l2 zsu6UHk>zv?+SsE>6YW!{tfo&@)52Q-hErIx#A8truLwr+$#mYU@U*fFu&3s!8nh`y z&vz7aa;mm9AsCm0VKfo?*o*TIKFI&WkAKI-jov-(iEgg1H^MNclv671W*xJN2$zmw zU{8sy=vK0Td!-F2IVEN=n~{!PmsK_KjG<-w#QPP2ic^2~oL@bmtMhbxhe4bGI8>XR z4T*pmBdT>z>S&Zm);^eosW0NGv zC`>o2!jPjxpnBamyzIRjC8mU!W^2B~#2REDTSjt#R&2(2QWf;qL)L}Dji6JS?=6y<>606(A%93TdcKH?0F@6NC(VYU$tNJ_6Ma~3PsxQ-rqGH>|+G}%a08I@W}#uTZ?_G2)i{$ zP?O=;>1L8$PT?1mxg}37)zyh?U$T9RCKCQOm7T!wT_|s3YSr+3I zeumjR=Xp0<%vQ@j=d`_glt~kd5Y3hcxl4Y1-jO=H2&Iscg}E#d91x z;7VTD3%jx^%zL33jCb~+?oJv8KVFIJyDfG|<{f402Li-U9-BPbG<8rfb0M7T_QL^1kcqybJimegJpVPytgG zO7*e}n}Eq|ni@-z{1(w793m&C;~wv$(lf1=2T~ zg|Hrig~H5|auSgsr9hB!$~onnx>+ZEnk~}2OP!#bNte=co|p4k-=*C1Y}T!2dB!|X zX+H0ltA%ebY;&GP=GnVW(tJh?vJ&6IJOniqq&H_!B1%SVd#i9U?)$&z=YHTcC{8Kn(g zplRjM7L}E%P+!W1aZG-;ZJ#B_?vDP+b#2B&9@7Wf)61(+a1=U1C!j_2V}J&S6Htj=|21jI1P`_b2y1@;xbM zQgcbJ&J5RJ87RAf*dcBaiX|Wcxhs#=$Cak^qj=>w!Z{(twbNm*Y!-*RVOy$*T?iBd z6W6#SkTi!&R@YFOcteevt+=M}OP@_^V&}irS5u4%;EmbIRG=!jNGc%k|B*n=_&BXJ@B(t}idI zFE5UdPGlljM7#>YCL6WN9_8uD4mwmbc?f0^l$`fH_I44T|Cs+{+Bci>eU!m>X_dE3 zD`|g;8YB)hKY0c_+ogVIVnvFE=J4JJ^ywGIAp&@*8W6|l z0IJS{etwv9?`8mpKO}Pt{j*RP7wWng{whro?CJ`TNKMH__30qD3>a7UwtyQvNg#R( zDo&fx2tuUw^PD~C9O2pDtV$7)nYSFyEqsG(a3MhN5gQWkx|wQ}#!gQ}FhyTgH_SgUFe9@2NxWQ&2l2S%k zxyDAC%1@KXU85yCL#Ygal|M5hUy zT4pq+6-eE2G(9yj!_ByPLM4k8Co7Y~6IHV<7njVe=(8BykvT5MV$Lv8%i_YF3Yn{! zs+o~eN2X@vAk#ud5CXaQRmb;+#15<$^G?bJOg)V5l#%xj6+p!onLb&I3r%uEJ_eRlQZY z(c<4rzlLU*N+i{ow9;%rWW^%h!*p_+a$B=rBzBf5yK6pW=1#bfegF?b?LL8`^<+w{*n3e#MCPM z7Vz_qzA`oQ`>Tpy;SR$0j{Pt5HyT%A@9%R3$w|VeBF188SD0DdvLg- zA-u?lnUawM8-goCk(D&U=$MVkIeJP7L@Yc$7$DQjH@;-Ujie+f+)P0^QSP#E>iXRG z3!j}RxM(q?Sb4<8(cC?eCx(bRi4&`LnN6Fg7Qz6tjsIb174N3SjIfJnkJna|h~R}> ztz{*-vy(^4o=DBN4M&rfzvZ!~YY}H2O3k{|PVem_TgyYm6W~o%=r9#3TFi@iM2Q*T zA|lMgU?P$_VMrOg6m{}h-_K?XA`1o#F?UIR*YEzF|JT3x&h^a&GY^}sB$k}|oS9N7 zHk3h4H^ZQpx>zoL>9fDIx%dzMC%^Z9_U+&KJ=^V8O`Qa8?81|q!6ZWV$z8cQB~Myr z+IJ>_f77zySNOl%_7Lvh+>79r@59b?>zmoo*u`P-F1KQ;@;lX9gAQC;3ab)oiI0Q9 z74oioUxu5}o{FS~cr{H1fxzrU;w}=MV(^q1kR(Rp$%H^iG!`ae&qf4Ig(d0eu#rW{ z6C>0PxwwL;b0Lta3PgadKkaApS>|^hmxa-4&Nl;TbAn_rqY#{hz$Q!yS$%9yctlFf zDGcb%jZ=T~_{%=NoQ0W97^xFCbJLVKWdFJEX8p?MM^|nRxKE3scNE)gj6z z@85|58KJH3xubO5S$TC;=BnZeF`(5GSic|QSSd%x+xK&ptg11Gr9QI+Zq3X{B3kIV zXCM62KlWp)V1`1k*VorqH?Gv@H1E@5-ibin#-f*(*PG4o(o1jr#XtM+|E<6AU!)n& zX7e%faL}Ut+?+@&XbP{mcOE~!@Ht1qZOR|Blpamd{0x0V7T_v-RcG%Rl3K1$F_? z`aTQKI>{2(TuP~%_nGqHCLPx}pO~_}gh!+iOdZ8hlvUxRj?D;*bS!fptu7wp&1%k{ zu{7E@1GdoIwmV|1iD}w)LPErD7Q4K7U(DPi9?V;kg^TZ)y&z*a_#Y8#m}vX$7ZK_c zu4*=2%TCOkrCrfgi__L(oRYf{G_h2(PB%DM1R|tO@F1L1+N?L<_Zzm@hKVyOhgVhNA9zv$-i=jO{=FfBuy(e*TNU`}h1$KmLjD+Ky!` z1LeeS;6zjA!VXcdPHB^22!E4SerMHO0CvBi$b&;q@hzdsP*+!S?FX=QMe@Hk+h0?M99V-$ypF+2=W zSi53cv~*n(LF6a91Bn>foSlp#xXfBCp}U%emdH?(wl{X8m@%Oc6%COc6JTytBI*uv zF^uj;1qN|(*IiJpgM^^|^rfHH^{XOE@Z1RtIT;HJB@t%fZr112-*k6I?jzO1I2QWk zPF57mU@8t#c2{EoiL=4MRfxvbfm%Imtqko-kG+c2yqVjXosI+?q;yFkhYe)x) z)TEhsOB0xdAi~bfltegjVw7R{oj>-YZ@%&NXFvOM%jJ9=%gyywa4A;HgMO9|4wqLK zH|zD*L7UB3imeulU-MTYn11SJ( zYK3n!XHc_n_7r9laF}mhw=CkK#UYe4tvb3Kl#rMqOkoTt3;{}*G{ZuM9u{I9^V3&; zcKhVBl8H=n;+zO5ESoHJ_CNy%4CmYG;2g0Trq1=%Ru>d=C5TgMO19Q} z3y4uy5^yH2&fpFs6cYgA)e;zl(|MQ3OEsJ@)LcSl=Rl0jg=0%mvqIg$R{dqC5bcUz z{G($HZSggYuI@ynEtE}NiLCEa;z&IYOAv`SkA+i~cr}tp)sV(Z0v4p$D>^wtSU5cY zlKAiY{lE9${kI;y`r6kIPFGg+=JLjiQnA%?S%hb+8B$u`Y}L)wF0XF-K0mR|U-{4f z#wUOFQ@{1ce&jd(@DCrX4%gd3M-|z%1>nkUG)FZyCdVzp^0y#L@;{C}<}XLS_MI&? z(YMx*hsDCJh#m9T%kPz*wyg-)*r3dn#HcS zZ)1=^JW)|MBjVV}OU(yyfK06iG!kLeQ{+&%n<;zvu-XK&F(Ma{j4%_EGF+nzHz$y% zOr1DSu`as z-AF|7x=X}-2gS^2r@AC>a`2W95CNW;l2?cT`D1_VkNqRxVVK&|co;1r+lc}zWtJ!B zmtX$EmmfZUe6zkWvq~#sz-b)I)y>UfK0i1-nDwi^n=j_`byQ`^+Q1cak#Xq(7tX8dv9M#Gb!gD6rX&QKDmv5PaamS$ z0D=S!NP$3uaEwI`ier_wJ3@ zvCrP$_xoDy9xmniwfTXFF?Qn%%#DQtY39mnRxT3}86smj9SRu95*w4uGRP(c?4e;K zMlfWV7*SB_P*7@86^V6L>+XyIIf|t5c!&}jA0vp0hNuD>L&9m#uDm?E@)eHzOkxV^ z_nhIhhRH4lHq6FURaKP337?wT<0=A504nJWrvv~IF(P#@prl@_-BLoEAC}TZ+YY}C zXipMGR6sSHmFt99uz?VsyxTr>0woGj7BNwldP0}U&{9ieaRuQLBQA@hatHW7zck!- z32N&V?H;ZXl!<54>1(gNeslZQcruA0q$M$Oh7ga&qtd$djg`{%3tRLC)o^uKRh4tj zSd(fS0>l_KMrN?i1s@I_K6v!l9k0Fo#$>wBhJmp0O_T@<#KdH*wMF6Ba2H@H(FY9( zbnDjsx1M|9-Pd0(`^AxCM@v`uv;$6ld!VcmSzf(iE(f&K!{hrCHxR$u1p?pq_jaYa z6L&9Bd|_Fv)!u|1qNZh0E)n9o5FJ!l0*bZ6Nd*Q3%4Ma+a_1p0P=|?cecA}w3*YkZ zDF@8As;ZdJ^-Cs@B%mY$NHb}}Y>Y{F6EZRZr~M)k5n5)(G{0sdW&$=qz}9f^=*1O= z0U!W)54WbO#%L6g5Mvb37^Idc5=3Iuh{%jEz4+Yp(w9x#H^!HR8T3kHC|X3A?p2y;0I3^1Wh_Y)OxjFH$R@fZ`$rqlcHzw@b& zKKacTpWWHM;ffLf>v_E|dlG{m_NDz6HPRueJjn02H+<2~lIkEQ2vNtHwQz}_?QW^&vG=_UspNRLu zp~kIJOgR{kVzN|_+N(q*0vWWbpe#UOR8$F-f-pJ~QLu@k-O9$O0|sOkC%?-8Nih+6`Uf=1hbwYr#Jyb)^z4eohFE%#U zR##Wb!d|{~xhM-jXkyqMjpo7E^?YqOta?4?9Fw(<=5^!i#H5a+y|F87M0oD`mtTA3 z%?BR*?eG8LAAIzqPYrrQ0H{SI@w5Ob1syL53U4oow~Gtmci{tXcVsTnViphj)*;%3 zTxfT8=ysf0AC6hdfs(U!bDY6ax(;+)sjjukH6($ZKuOZr%pgfyUeZQDa-1e0LXfD4 zpvXY!3SfW$ssh#+l|Z@WPH9ZsLhS&FK~PfK3lmAuh)66XpumjG7)2xk0Hm<8K?&8Y z@nRUkf?7hOm|S6$rsXOm$`Tu3wq}q3RU{8;h=@#@+;XA~Kmwo4TnRzv{!F->Z5>;RIx{xmxkr=U;pImACG>=T|=V@uxoW@lPB*aaR)L#25vDXrUl{pOqaEmz@j0 zD?1DL9SC%{pE7WnVTntp4{GOx)SA1y0PlQSQC$=RT#S~MlCPxA9?j%?K@tGqw86-B z6-m4YQc0Wul_dEKC?O<5VjAbABMVuZZ(NnMPs)5E4uf&Xl@~?TD;9Ii|1)Vg!K{ zy_uDqX&%vGN>o3v($J1i6d=cbKm<%mCslCHtqzB!b<~bqM1_$-fshMVjb%4_&y1Lc zj(K$$MIxXhA{904n7u+|Mr1^#(D=LWx$Evb?|b2;XO5gWaqQUf8#iv$O=GPAg%HAI zGV#6MjDG6La3J@}o9Etm``oYoo6kM`(EX1;_2fgR zAKBPAn0~w}%#0_I zEX8bh7g=y6ng?KcZ`ny6BtMW5Fg?AcjVK`kjUcKLLpr*PWVi{D0-`|_6^)T0hd#$B zM2VsVB7#f`7$uPzvk@$T+(ncS(U2&q4$epWV6?y~{W8&pR5%JVGKm^QB49-f8o@9SGdo~|u~{**Q+K$Bjt}lSTCVg} z#McclA(9}P1m_}bhifUYxE=E3*Z@?82w;*liWakp4jq}mE+3fla&h5l8<-86XWpv9 zY=>*Bwkn+~h$w~_RY--95VR;90L-RSK1fJ_L?U_q6=T#W%tjHIjjOjDFi0XBO{4)=Kro~TIw@s5&V^~ z1&L^sT*axoB}GYVL{fgwa(e2d6O$sS z2m(0f+-Z=k_I0O`sMfNU)@vP9RGqO(vujswo&WmHx4x?3=D-Q4mW4ZX_)uBc$zjEHJ41d^~9sc|Iqh;45E0c=kt`Zf~`(K zBMIfBL!K8T@nPZ`0&!coK~+#WKjiXmqT6cabLR);yj&jSFU)0{*dLEVXp9z=pyjH75I`FZ28oyy2o0-dtDNB^AkoL3JpG%$b!hv> z)xDkV(ca$H!GoJy8>7)EHa_jTqLvC}UDv^fCN!$( zeFzY00Uq5-`=wnZwe*CE?@4WjI69c4+SpsHla+{pBNUZp7o+JK$ zH*`7P@H?RBu*K(ROD+Ne3NCPvStZel+@T{t<*P6~qZk*C|MujO;-CRr7;hFsYP;F) zE=r}`IFpLR1-T9(MOUFpD-_NjDiPB$0aR53b|ipyVK2!@Kq-AEQ`Qw$20EB{AJ|}Y z5KUQ8gz<%om)>~x+B;v9>6yx*VK5A{R zTSw(%wW-uM$>flrC=voPC5dQ^DO3S8rdygqdTp72kZ8_m1+6Iz#s<8^y(^RPH9xv6 zyXP(LpEx`m9Nav9H`l$hFFF3=c7 z)G#t3BS%G~oIgc|nix;sdF+7)?*G!YOJt32!o^D$2mN7LmBCZfG!m6as(w!eZ{FA* zkH;(hmDRPivfpPWV~jPX->c@n_DvI;=zRUT5c8KI(UwCMfiP?iV0Wsn7+4c-zVptFH($K|_S0c@g~%HU47@Vz z_4<`_u9?rqqy0pCjsnp~i2{U%4Ko=ot)cDR$v%H9R7Ya)s7Z?{SyT%k5}2;ai5WjC2hP|@Cv1x6wzP@$j$RUZ5s7)`+PbAf( z{^{awFpr!Wcp+TKWW$aqo;n!nsx-D8Tl%#Rk|?bp0uT{Mw9Cj!is=Axu-ac)Ss9i+ zTUeOQR8*oM=haoO-y4lb)9Gw=B_=OOa_F%Fh{hNV*#z-s;#Sm^Qxi&OpZv&2p8fha z=JkZxsKD;d4()Nj-?PresKNWuXu@oWXgc%td}lnZhpWTEpx3WTHl{SiO4Y;OFvi&U zrtzU^n%XxKV~o-?0T4aW{O0KTtrwsB<|~H|te?8??nfRyeec5$9XWE$aIO)ef-Qx5 zIV0{n-iP1y8N~mXfU>i4W&_D`<}S9;*||l?g2;69W~$3_XSyuRhNLS@u!cnJ&AA^0 zX>5_Ui$uy01VE7}wpiLuw@ZW~N|Xmxh$t})6_WiQ2w4eJ91@D8M|W$kS5XiZLtG6i z=ZvlV-%p1^=R?@v+h@bBa6}xNh!mO0 zvIVBmbTn&bUs) z8()3;xs8pDyYD>t@acz6J@~+}6DM6!bvK`gN(;8`)E6Ty*(x?3G%X{KMQpi z(yyea$)8W{1|zK)yEfr{xSP&%43N?rnL&djCli7(9wLaUO1`pl(7NO!NK3HQwo%bG zgPw9eh6(^NF;W2WQANb0bR%bpa5kG=ICt)qS6+SLg;(Bs~& z#}ByDY+t>#edEStHb+EjUEz$z7(&!2ppZwtGy)zooN5b%72=fS}su)r>wYC|R zd4?hoI*dPqVr-aefP=CNg9yB+J&N3!4xMrm8f9zAO9o*zqHVO_0cx z5#XwT3~eZBl9ywihGA|9I;Npw8yPKWl$)X@l@r6RGXS(sxDUibu|zt@^w?}I6^L!n zjv8wZ9^R@3y+OaXx3gQLgea_eF-}N>{$Mm3NAXdjq(JRfP#_|rfgm#+Q<+eV0FH=4 z^oNdYee`1=fA7qDAfA~8#DIwaQDi=!b7F}D1f*yJvoVGt#&HOhv2=BsWyc<@!Zzx%F*LT?ml(b zy$_r^apygo2M!u`1f0tRKr7bIfyCJ54t}`z{O_2E^=;k6vYxViR%aP=u5N@~K&E!O zT2f3=E}cReTR{umetqa7?Hf}%i4Y(Vivp$b6h+Y(w2SD?QmKVatMhp(wqw$yIBr$d z5MnY2K(F6-%pv-nTib8H{od;@z4rR+Z(Y1_aXcLh3L{jNVXjOGy`J0J+;A4RZ{50n zb$d3R8z$E;s;aV%V+gY*L;)g3MkHe6Vwi33%zghUU3ox)R}x5Jw3)}Ek`z?!#spA7 z0%)!Et@-4d&TquorFy<2aYo9(*4T=Jz{H`7d6-c2QN08YLwn3o0Vs2Z(tqR@XC^woQme*r>)B=5;+DPsaPBVXwcwIxNe| z6t)~z))j=TqC_MbeeM0MshcJ^r-~xd_(oLcQ7>#yF73Sa{7bJF#cytIZX7#u@Qyo9 zoV@d{L&uM99Xhl!TqQEM8xt{QrsYjXt2y~#j~oA!m~?vE`Jy!kKud5CpsZL)cO!Iq zDp`83TZt|J+*TSE8!Q9>;2eaPBUB_R3Z&x#a7s{75si{k@e&VBa=VZXRIPjy5ky6W z5ZStFU{z#1nw)*-%*!vo`o`<8pFMMScW2Lgj|SL4(Pvca3OgM34O5UfucsH!o!cLc ze4~Xe%YN1GS4C+UY2M7|)7tweg2>3s2rwOQk0um{pNxZhe5_SabI^Ah^Udt05YQ^DiI7K5oe`38?Xke!VUVpvMdfB*c=RdO&yG7 zXhRe<-}iaaOeoNGY}(S@+XEj^GS4GpK5Qf7rnWEfSo3q4E; zh!~@6ZEkIDZdLsYwkmW6Aqoc1jA>`>92Z5geQW#Pdq{)E5JaSn>p=ySbi`m14NF-F z$Y`3z-*xZFr=EJ^3%_}*5wGgWkcq|zFA0XDA^?M4b?DF?S1w<_bz^5ZsGwJ-Dq{?* z=-&SRXf(RHz1{Ek%CcNp8}$2wvZ$Q1t}L7}))=jNF~+%XLem5voiida1Qm@j1c*BI zVRHG#`HNSddHxk=%%CVYH&+iHIe6g6;iJco9XNFG;GqL+>l;-yzzic?d@MH??IZYq zLZ#5})Fb@P^M&tN5feS%9%Ibef8zn-hT7V%a^X~ zO~=XFYfHnf`|8Y~=Fy|OGTYweMvha`$bQA5eJLMf9^HN_KWMsqu&%w`zGg<~qI z{*hWUefANiPe#hJ25ry4A84?hww#7VW7%cQf=XB!R0j_o==TTx{$Ou!w+?lTAx35< zR3?S8ayvI~hPpv>JnTb&rK^2|NruRR1?_c=wzw*V;f9=;l`zzP3Tr?JoUZHA`kdYM8$2f0lXWjnZ zPFWNy!(r7M^m~J%vbHD+Yn(A<*#{hi#@BUdLTDNf5_||DijyK{)nTl?pN^;3_xIm; z?;-&b!GS{?#_-Cpf8@Zy&4XK8hqpGj4sL90tZ#1g2dmZ=K#1R#Slx*ZJ4y1=67qcm z0=T``N)<$=j}J%eBdN!ZUu1tatF{+|6aZy&rptX!h)7f02_aUev zD5mU^82og4b3Oy89>%T5y{#bD3IstBfFeRf)dqDR<4C5r>b>{oi$4?q7~U;d5H{_3l* zyg1z-7o{!A0tiG%kx(^woXo@CXj&Az&K3P(RrPvRS@rw9vT{{b+0wbHj3GjlAku^o ze278Pg&0C;8jemf(mH~G+!{?n6E0l2_3Eo<3B(#Smdnbm4hQRN8|zz}2aX&(a`^D( z=GNNg#@gC?e=tPi_w^2G>fN6E1s6g#cwbR~+r?M6Cv?Jh{1i1O-JS7!&HtvOy+en2Dmq*>tkIedEgI zD;Lh6KYQlfg|p|cUAsCO?KR$$F>KiO458DQ#zuh%2}wW#)Z13(g_%0t#W>xaUY$*@ zh@T)~5-FyaR@yVNX7(8q7049=ArZE=cZ+Bd%c2+#hrObzit^}@qlRqL%zP+}F@!9l zD1uBGZGw~(WSE2Ll2(kc8*8;sYR+M9i@cTF`cqt_tA5}fikyy>pER1)3keSyVmy5G zz~a5*JWa4RU|Da^~E7Pkj8NwkSgo7eG1FGjmWSk=n$(Y>9J_ zL~^kzdY}HjPrmf6m#*Kq6k}+{4I3_tg203r0OtTYoBLn**?)51sRti<@?-z&|Lq_9 zV}JbLed)!Qe(hI2_th_b`O4L^g5FuH%n~CZAxmUvVng%kXtHM<_j{{_wZq|HxHhPY zey=KwA!o~y7#Kvw2d`0lh~7t31d%3$C?ZiKNC-g-NlrnPs46~6J%!!L{<{}%LKH-> z1}j(fd;Rr|mG!N)&5gB#2M=x@*jnA#+}PY)TVJhu1N^qY?QEpEJyIu06~BFc@jqe@ z#oK9j>84LK?aVyU4Dsu-f&ueY*|ro}WW5~ieH(5w&5=NJid=SIDG}QeiGdBo2ohml z`{{VHef8F*%a<;nzj*$=bC)h(zH$BL{{E=0YaldC)*4$_E(^%$Lx@2|Qi=8;A~CJM z<9t4g2~7{coG-feoYLgL2SsKif)Hw7$JxBDXEWe6UV97&4+iXmgk;RXdaTV(m|bZ0 zFR)He+uVp45N88pzW9?___iEz1|=c~rUYOlNcoe5Xb70aTG#7Uy%qzTdq)pXp;_TU0YPw(??D}_{c*Ke&s7Sgd~bjd3CO^T7wa*0>JX_ zxl8}*pZ(M0cinAl$v_|b_!FP{^v5n;{NI1&D^Gvvx4-b}^WVC)cLO;%VE2wIaC{aQke3TG< zR8bKWRKlQ91ym&XP=`1hjjrx&<2#WQ5Xf0$OV=Ov*474_8(Rkt9N0Q|VDrG%`o`Mo z`ucEXwW|7^Y~{A$g+d4RUbJ@b9mo<(;QZSNcS|Lsec-j|-&~nNlTTX!LZ(Qz@$YHI zlL*C0*Nl*WYwtV4c!9}ewzs!`>(oOm%#OHFU?c#}$A3mJq{bLmxL&VUmgVMw%_Ap{*}^JBQT9GGac&hDi}r2A zB!i^HMQalQ(qf4d&V@3|r5!}%L2`%CXk8XOrKb(9dB;IRe(Ahpg827`CreB<#a9%oyKYE0UF$pwuFh!Kf=L&<^> zHLx<1i4un^tDpGZPrUH07x(vf3d@QpB1l*ih8c;-2QMPO{rRt+e(bY9_Q(E%$+X$s z*=5698-qXo$N$|w^1t}8ci(vL>90Qhjjuob_M2~w_I6k!5QwPv0vgFggA|%(J{#|w zJ+`j2=|JcP{a&x8j9gKZdkqr#9RU05Sr#9TT)%MsCsCxL8lLfocGD>1t`}dT%`0 z-QC^W-QT%&>&Eq4*RS5VdE@4d8#i{g_on;%li93^5~D;_BsA6_k}XPN@*$R0QIsx- z__~?Q<|08Q#oR|9GOI~MVvHermGpD~P)^TGPONH95ECXaNXiJJ8pJnEJ)2DHaornk zZ5;gw5AL69Z#o|N*&9uLZ92aulk3`yRXm_1ZDy~xaq!Sd0cksR1r56BoB&hS>SEdh z$cXHKEkfJdBQTO-H5QHKe!t)A_XdOE*2c!#u-{c@5%IMbTLOSWWVBh+0l>rwNK2Hp zsf3GIHbiQ*Cu!!e;LxU$4GWS_)}Vd>rC}LOoQ4dP8iw4nkmlhesDk)-@X+R=V~1|s zy1vp|-?x+KV~~KJ&@x+;7>6sXH!okgaQ@x`&`|_VfSj-Ul9f;PjKtY;KV1SzXWO zY|N<#?>PPVssG?l{;_x7KJ$&QKljaVJooOqZ|?2wSO~ zDGFPb1sk@msEW!tS5~DpTol$AOU%s1Fe667fQg`ASVf!tLO!I{H)srvNE4%~kHIQq zk*vKCqb6sXk6uD(1aD4#9Bs>m8>m5n3g)V?gTY`p?60n_3|CjzH#gT-`>X3~E9+~6 z;YzR9uXV7AR!yw|Z!OSrrhoN%Lu=V^n+z??mdSYUNBff~G8s?ivw0K=F-5OO z(V&7cMv<6L5E4`cF+tXm5RGNS#01RDc}XY;jYg@BP94aOD?& z^-J?xpPx^6q@F}SQLRyhh>#4DRR{=Cf*w9}$Dr4*=Tkz88es{IyL30Ux#8(JK|RDG zjc?N=&N7#dMS?S~s>-S=dR2Aw=uu)q((M0G0nr#j@V+QZK#CHX35gP|uoXV13e`HV z5)iNBH??mv;nIAen|*ga%@1@82`&BzGhkc^5p(1>0;m#^1nCWWcier)nfK22R!X!;~-<4t9ma#|H>neJ`r+elq!m(U~dHlP3@BsBy)aBB}XFP_?5Nc_kRDU z-gx7+-Q8^>@-g}l*f0?>GnSQV?Lpr?fAt@K=4bx&UpzJ#Zbgkrm8lA|(Rel*8Rt$v zcK;I}IX(W5|CjH+eeU^heDlR;pL_R>xA(@|V#r~sq(MSxq8ABqjx|kZko54@7{kV} zafLJ1u;s!Qy`r+#uw`d$;R-U=5*OAfDHtTf#AFB&jRS>JRn&(NB&ui(BC3sVSV5wR zB36xWnuHA?1!jthA&L)v9OCH4txGp-VdwSN2?4IP07% zinM#N&atzUpo<7dNWe(>`4d7&RZS{mS8^hq&#=1fwE{7-Ix7+S1_i#;QF$wD)(? z0d+>!rCCEx3Fv5mmWJh5q!i)g9mlrT*KXb%^!tN) zKKD(dA`)X_b4TCw*M=7^o;&x>8>b$5V%9VO2tr9To&iCmNZ{DSh^jFuMUwbDG~ubI zp7_#lKk(8E&o@nDjjg?Jf-jsyBwsY&Imr#^R?BDnp0YOB36G9Ns zd7?}r60>1L1sgWR#u#I)vt?11);VWfVU4wDjkS*1FcYQ3KSlzu%&uSgPzyj$N{pb9 zqDYX~_@-$Z-vk0>13+w@1BDnR#3&JBh{5|PQAEAOy7n?_5D{cY(&~Fkh)UF)j+;ioNqJ9(QIS*9Y)VNo1jZE3Rhr$?sHCD1VhVFbB9YkC zbEyL$cpvJfu4i*Ut-Y_ks3JM*tg&Pnkxfyh?3O4oh7h7e@e+MHa7Kx$5z;dVn26XQ z8#3v+s;UCf2NY11C?WXR)ZVb$I&l2SANlB~zyH(sJb0=wj0C^*i@*5nGvDa-2j2TM zAa6BklA&xdil|0BarD07aCL9@CM3H^6p4vglUT>;xt*dMgQ_}Lx?(K|ASNwzrY;dG z5xS!2_o}L>R#w*5R#q>aJJah8Lx_cQm|kwh7_|u@#Ku995ncpDoR3G?@u(3gdziCz zI}6#f@3Ld6<)udETw>Qce88n4IeKAf!A`9|G{>3%tN7K`)e|RAT)K2=ePv}j9yjy3 z0z@AgYKV}Ojp1@-|_e3qnqG7yL}DT)0Q50Z%8-Ms+L0I#Fp5U+0g(+&#xn^~qezgtX`0aZG~kUvBS^|& zNvCEqwntVAB_?83Kv4w=5@YbbX(XzMgb)w~kwZ`gpBJfwgv8_skxjZMMI{Cw(&eWD z;)8D*B|Nls^x=md`^5Kt@8eHBe(>;?#4y_1uN%L&bL-cBfIygdQ(3U6sBEk;eUKa@M{Ps|6B%pDqOhi@%0c0( zqjwy?b>s4-^B3;B@4+x{XxLBR3n)c}w2ep(#C$88^q#a&{Y<}an+Ql+sHKQPgarYmyWbcQ= z)oa(Uf8(oP`aOT}$C`PBoTvx_%E+Qbip&Y@VN?Xtu~H%uHckCKpZ@qazwyE|-}nl~ zh5plbB}?~&A-%!`5vG&bcq+_v z?AU?3?mGJW|D7M&-x*&#cj?X7-+uL#SKog7ts7S^k7r}V2u@QHVVW8QKXO_W?)ljf-#d8&X#H`>m)~hM2X^~ zXx0l-t_tm8FUdC(j8{ZC?cr3_q5z0W5J80~kqU!Kh-?fQCLf}2JP}Ktx2vc`A3!mx z1TRrSjtc=oV3C-ne*yxaA|V8cUP6=*L=spTh>R6h1R{-TD1d}Yq@p6eX=)XSA;u^^ z`WSqO9v}tC#5B;#cL5U-5hEd^5{amfsvsbu8YM~$!3W3XfrCdMeCW~d`Shor_}E8| zpFAQV%%;=nXg|h?2>pKlXFu}~&R@FjTv<1>EEHr$00bi%H09qQ0O7s&oT~b6v@<~< zBB~n!0%Q^KNz0v3b}gQf*;EQvRFE?$Ixi9uEvj&3&lzVA962=I+kO5U&m1_o<(pcg zBr|h6tl(CAnSOHRJZfmAkP1u-yc4$A{v1J*AkvF=Z)xnDz1sSrl!jJA!8tb>vhY$f zBTS>jq<=bm?C{~^$8OxZH5d;1yMys~qAK1;W}oUG5%pGAzwyj7_nf-xfrp=(PiKf2 zK}iKvD8K3{S{W2kR3veOh++tX;qXU)>_^`{`(AVTd|giwF~;bFXEvgdP>ZraLc{#l zYw!Kc-}A|iNMGZ0#8AF`%8WlidOk=?i z454q-i$=hx3MwKXKIVoprV=LUHBpHnL?2>Qkr<(aE|^cwjD(ai1qz_ii>Lrb zR23Bo8e%}gezkV=bbf8y~cA3u5GgfTdtPU_ioHk}4lW|AO-;o$kFzww37 zeVNKCh9*C3Q|4A1>6KOS61Fyv+*GE+ZYL@5eAHEhHH+Qg6w zDd;3Y{^&;^_6ob(8JWt&o_;BSssXp9DR&2B4g`MOHGjlbdcCg3Q5+1K!(s-Qh9hs_y!ST2)-d^MnJ(Z91hQ4 zy79Ts{_4N?C;uc;VKR>bKmfU0)j}G#7~(AS2SHFm`QhL5gYUfg?n^I!b2QmwVvTWL z&jHmKOM$F4MO7-mTWRlsDZpgzw{PxTy>#{Bg{$Y!U$}bd!uHJ@ySv+?(Wv%~NC+Vc zpn!;k=tYBisRIBA#1KR9Fi)wAIznP*M@&o+fq>YsVP+(QzQ>SF{AF`p5V!A(L8AQDA=2qFrU4p5*P zgCI&s!@{UBXow+%CQ*+7Qj9&Op^O4BvxRSP%q?qYOQMMCfjDk0u`?*n(17t|23HNGGa02y+~ zF2%T+47Z2~%7liwaL!m;lttC+ojiHxTd%+J@=Gt;qC`MU+iHjzhGoDwCZwu#sWfEj zD`f-=wHi$96wtIx4)5GI-L^8#9XiKFM`Z(r4}1)Xq!1yyFD1<+DLcHs*4I|IcX#SAjUkF^-OPy*9R`R*)awtPeeT7hcOUZbn(iS3zx25x^(sWwaI8SY32$c)J>F1Kzvkz1d?7FrwLgn0YStumFQkTuKzTKowiqe` zAW=dLiHVR-BI(JWBihq>AR}8fOQ1zk?xd)KVieJo^+2G4QF69Zx|CxGIp#5?UgtI; z87&nwr(kKKO$&$!_!tCATdc1fIC1Bl_doF9V^5rZxCOGzMWdlW9GlP9p&m zDw`C*kj=^*F=Ho4%R%prS6}+2U;Y&|Pv{o z2azZ_|CQ7^>s(Qmt|*+fl-8bUn90P@&K;9V02P1;+63ax$C39Yd4;*`zoq4Wnl zH-6=}?l^h!zDJ&{XLHL&HBpFi$CNC7CduF_kH|nk>gLIhKl0YQpWgeWz3tr_q~eSX zArM7ZIz*Hht>NCFPskUp-ulen{o8-`FaE`i!zX;xFtR4pUP>z#MFf*V1hox`q%;}L zel^N$y%gVuiRJ+@h7i)@&JY>q0|!j%H+QaIzIN&I)ytPIpF4Nq z*3E0X+dI?gr1A46ge3eCkQl{_#1Nxsj9xKO$v~n=R2B6;r0H+kjVS;dPHm1NfMEbc zO!2Cm+H_PQAP_><6jhr+%*X;NBIyTD0Z-|vEonzDF`ZY_@1##g1Zi_DQn0<|4R*@9 zQdLQ~CS z;kC7j2GjMm7k97(zn9B%J{%sB$Dgu$CsX@z4B&pS!j1)sRSRF~C^| z0IEKQ5Pf=_e&q2_96YeKzqbv9KGdKpAZ(DB=8aC~vo`+|i7l}eRX{~T!&DR|Gz~H_ zQ&E=I7S@`wa8<7mm_PIEGZQ~^&LNTlDH1ZWLE{(&T;ck?vM5UD3PQ_7oJJ0$WW zwKklN2D>4K*hE1Q(RnimhlDtr)m2rF_b0#jkN)|e`p*s@ICP?^8*5BnuBRd_`N);W zMyMV|V?;oa_@lr7`!BwG@!98}9!++MNL8BPafYQUflNeUGG(s<#BaUy#?SrKPyZ)> z_RkvI6ZOozNQs5KKTU#kNfb^1P!a%=995be1F4h47OkF)XPVBg0!{P)AZZLk*el)e z#G#WX4m|~r0>HG1qy6!XD>tuPyL$D~^{bbz-MD(?*7mK@Xs4OZ<{>oNNJvlX2+<3w z07@cisz};yC4Z5K4}lO#lh;wvaBO=mLyQ1k0%j0nvgKsyf5#&cZOK%5O4z|1G)M+{ zX-iwdMJO_*KMIH$u}unTsH;(17#yYuc*uxj%K7mcQ^8drAwuJf84g#s4j#Sx&b#h= zl^|ZcBz;%b6He_{vfIp zWmy!3D~-v`Ag1F^y9Y_4Yg{_c>k|E~+g0H5Q@kbGYA1&5e)q#D4J|V)?Qe45k}9xB z8jJ~v5$SsG@+6TWjlo@DKmKE7vcbIa}BD%orPEk{(1NTQ^N< z&{$KF16=*hFFw6>>}USt|I?ppY6Buf3Z0D=I_ViGAPFL+JP$=BK#&Z`#x}=6Z!liIuKq~0G*Z{675zIpT7jqO`Eceig{zj^c4 z?*86*ce|cWXHBi5qA|pbzek`Lg4ZVcCQ*CI&tETJMKJo{N#zl#}2P=4x9rKXliJhFy3nfA_FM_5t{T8D}o?s z%!quH#2}=c-ji?mX}*wmff_>No0&=g!d`Fq13&OX zMZvo}Q}5@&$8=aSj+6d%w7(mICuHUV$b|@?Y79HeC>~Ln3=vvujWI3(K%7P9_s+b1 z@!}<7CL&{OO7%eyCNo@F=?w;;>TF>wGb1w-0a?n9h%8&692eBtAX+}!!gj6Lim;Xm z4V`0#+StGkt2E@O5<%)Le@XO_Q$6#!9T7=_tga4Dox1zxwJYPvWHg$_5K#%l#~8c@ z=B6q+ipQwEwZW@zzx((8=HK|g{O5nVD25V(v7FjxjY z_lJMa5AXlW@y#2T>w3<_A~LUQE6Bu6(*Pd|v;Xmb-VKVzl!;I<>69F4BheuXpx*VY5qY7bFjY+{!pg@jo4ieA4sa(Er! zp7f`qK;1Nx$!u?D|Hjo@ySuwLuivOAB`r{@o3)6eO=Gz^T~ADG_x2rgrE{N zg+LOiM3o=_N|b_)KqV@m5^Ki&ipJFLOYWRBi`G)b1L;fxh$f9C5mLStq%J9S(u4pp zs$_eOfGC1xXN;|EZ_r;^SsSh$IB?*=)}g}(4;(nKbzo!j(AL`K+Mr(+r85Kw;01gm zP2J3aIarYMx*_meL_oY02xG>laDB! zu$7sZ!LT)kt!3j38+HX>zIx%ki|^$=5)jem94ZAu>J2LASfZK&*nmm%MryZ}X+=j} z0D8yvhP)-kB@R%^p}-8V%^EY%j=HqKd3-2BX~;Ob%zo4EDcg#+6%izv6y~ho)^Cw2NqIqj=K5LlezAJrF5nrDVogw%W8AOF8Hz6T#b3 zv6OTU1R#`gsuCq>G^1)_ULv9^T~)dRo2&QUdm`5h08nU}P|xf6teH*cZFSm38IQhtRjk0R2c|WH3}dDL4vYLX2qv` zS_UR0U`oT4lvtJ4pGlVCtSL+93RCuaMb#_Ha?l?P`n{Fa{>tjg`uh6X#@cYD*RM+J zZjN@Bizc zeB-tEY+2UxsY(zDNxMOmHn2W~kou*QC+_^@C%$Jsn%A`pWzsuD3OY8H%I%gn}FQ@A1tR<2&XdhYDm7-N0}C8@)hcNAzXmMOf(uNM;jksi=>kq5@2-SlPWQ) z&o_a@I2iOEdia5>moCp{v)*_#pU;4a$i@&A@YbyzV=P-6LMV$8H`bqi?p6G+{_6kr zFZ{VEEa}AuQuGQ@fkiY2#*mei;e{%yRaO4JKky^hu3nwJJQ+{N)|e2Z0#sFrKuz5c zB7il_gQ^-U{M1kV%wX92!9VbaXEUDw0||Yhz}N-4rCB6$yUR$R=zO0qUi3C^Hvd7% zQSi`FrE^N9YAan%e*dNC04U1BN~;qruI$kr?dHd zUZ>FT#?K+DQ!U5sW5}>&GRBy~6^6{wqesuY`}V~P=X_|=Z9_za zOi7xJh7A|i7&eLo88A=TRow+pEt#SgS4ua0On+zr>(jPa(6@K`s)}i&2!J2jfg&MY z+W2lrTHI8oQlF`YIYd#6M5q$)zUSnbd+wZ!_h&0B)5&x?n`C~SCV7)Whyf^2Fih*4 zn_v6dbHktf$^YY@{=bD9Kopq_S&2atE;|KrFdG9+Q>y|4`w)&EJ@otj(2s6!@4R>B zjVLi4hLI`xjDnZMr9zTkzZg&b-}%X(>h*^o{r(?l>X0Wxh=6Jm)Ef{9D9y78W76aR za64^~7Lh1R^rh}!+ZBBW!O=y=WNNY`Sh{aWMU@wsqgvz2OoG~cV`Du@Gp}=qktHwUvPg=zWnZ6)0szhQGpmOks)N8XQG(u zBPYzQF~+WMtliqVIhyPfV-%r0G$24ux@-b4Y)#?HUX`c{IioVYk?Dgu*;p`vOqTAy zc0-xzoNzk;@^njaLRBPPu=G*by}q)95}a z+Zbb%gNF|&@P#uMC({uz8)Jg^F$Q9zNrbIRh7h$Z%JFpm?rX2#b;pUL$4~kukYNHe zZTu)vw@pR>HEG|_f>Y9JGtVPazo)d2qawj#4Uk=301F!9;>~O)mt6=@K1OO+U%HU9 z<-V;|0c7DUc8_9FkYq?w$T)%tCfW#g6lHC-zKi&~6ql9CYa&{w94KfD1So-GijPa)!FGqA7AgXi zEIW(%HwD1xoBqo1jaOd!OMmt+Z;xvQ^-Tj3M7)A>UP?$kpT+2j(6GJlzK4J8$No^` zo7r^g>m~$I1!BwA0l;9`8;|zC_2TQb2L)jSOU6(V@C!2l^DwjvRgD^l8f$2#MG*F%xqVxKexmKt!T$=t!J< z2JA8nX!&4)EkFit-%4~r73o_0uu21VLd<;R)|OzYln0P8fv;mia7kEM8IJaw8`p0H zADYI87*v6n+J;fP#h7!>I%914{4>u{m_GHr-_tZ9!!y#u1C_EkjDSfsCTR^JD9DKu z$3{DoE9WoQel9AB@y1Nq3V@=j#uy^9MY*>>KJ&_(r|!M$z_DY^yvg;tGqz!t@^>9v zW;$i1YGR7#ve;^@(<32m*QuMyw5372=qJ4GM1q|-1@ZkvCTNEmnAd>cMw^D)P#yU| z(Ajg-<<)WndD**<$Q=Z|y$X{xA58z3+cU7{7itlfm$8QJ5nwT|g{6SK z^jfF6Q}XLUzVmYj2LOt!j0`ysGXqkRP>Z^eWCVyRF=|;=H?Cj)OMm7sy?yqEl4*Rc z8bH0K`4v<3)DQwVD0&h2Z9!OBbq=$>3#q-eE8VWE0=CuzkbF0hL9CdMTkj3lJ1R&*cc{e>#knA z`POSMKXUq>jm?9;_ARG35l^61w{-Wy?dQK-F_5r}lFofp9vOERY(OI=k|L-N^SYiTwnDF5`@tXjy$?KiYG-FJ)FKiU zkc~CYS?h+wVT{dh|K^v^oWH~d6{0hi7?7114YPH|uw$~u+Qj21ielc>@0~eA#KXaG zGTGnV+otxzn8Mo1S|-F^)mvLzyXT&J@44@8K{brTrn@RJ8BOz(iqf*7Z4r~U16r&T zF1awZ9i;1R{le0}U|TmnywcDfnitViEhsPFihTHYZ(4l;NPib?D&5 zbC>pac0>X)rP4rz5@Rw4F)|<+!$q&UbnV)EZ@h8(iPQbHHQ#t5($3?9NW|P#XhNl~ zbc0fo|5FEqr_LMON>uW_waA6jg-0&Sr8J$G7bCZ}!0Vy~%=M<*D5kH|ap_^&6=uo_^_t0*P)sFwtC`@%Zj2qjv3*L4(TB=72jUGU3(-=Djd)hE`(mYsT zjytfaaw;x)jH{53sBI9Q=E9I>wMh!50*0t?^xyvF|N2*d{b?*pspkMeVj~*br!R$A zH_cR4*qE~HJ@)uxpZfHt_V@PcCPaxKXt*$@C`-3>U~Omj*022XXWzSU(HUk0W;VoW zxZo^XM}`d>fossf-(0I_v)!Aw5{WqkuL{oDd+)txe}6y5&>puH0i9z6Df=s5|MEBX zx37Nc`#uF|8{ec@0nRT{s-cN+uBysJ(d)*+&EeYmd+(gv+us!h<^okbl#zO6Oy%fM>YF{#FN z(G^L#*u~uO{eoL z3^#0z?e(gS&6T&`e)E_9)vsK;e$!Y+5N2eeBuTQ?6@^1G%+?w<&KfplS=M!Z`O4+l zY-WvNV_f03w{LpiAQ2%OE{U8=_&~zJ%3y2j!0AUH-8y_gqGXN_BO8-W64^b6nNN`B zr>#rqkzdyoiH(cVWR5=166z1XG$1Z=P8P^>&MaF{73H*GiK41Zu(rN& z-EoHxNzaEw@*EI z?_hNp>X3$Gm@<9SbDDrs1OW-6(&8;4rM#H$KD536(}_I`Fxqzuq0141j@OstieM3E ztgYrU7X@7SR**mxwG~XDW}`wHRnYq~veGgL+i;KD&IhpkpYJ$VB3*6?;eFxYNl7hj zq{Z?$3cK(-=u#|l5IQYoH$aw;V2iiUWA;=_fAUZM z_TT*3z}EX(qiFP!6^cwmBC(!NVho5>mHmzNtsnZ4-?O#3H5!doHAW>wCLRn2gO%#5 zU;fHxf9Z4M>5PmLY8ogwXAOh3Oq95D#yMjw8Dd+M^}M-y@#79enh$(<>`|Q8AW?$r_ucV9BIU?Gzk4Jnmx5NU1f~+?2I4 zhsD*m;Jv{TDKbBz=)>t6x?^*z+3Z%%8Ahc5kWx+%RFwdUStN&!7tXG(tz5l&-Op+! z@WD5AIDhtnbp;Zv3F<9Md z>VTAK`02?-n%tS~o6ts&Ejqk(z$R>k0xfAg-PY}Um!I(pX`l+-r+3PoEO5v#t%}g% zM$4xTp>|N6VgL+#f9tpY>i_G%n|PGy zH3o^bs!!u;W>O8a`80+I2t`p02df|b*eCA4|J45eI0VTSF`$*z74PT2{L8=gwXZ%0 z5RrmmG{z94F{ZE%QHfG%;8YhF$hkrlE?v4bnNEx`2uNhgvh;qwKiWxk!5CvqVT~gO zA}(FAwYh%u*wKd{eyA)8Xft)%|7M|6I@Tg(Cq+_AEe2hfIQQ*27M98~HWVMFNl7cDzdlP!l(B%(r$vbwQa_NwdWuf`aJF!*E*P-|>T5e3a@ z+M)^~#ux-xUEg@?owLt<=}V^{d*JZNJ0_C}17lYlGV4JX0pbY8@ZG2G*&R*JojK=y zo%$?^k%`#a#5;=;k^_jC%BsA6?bh2bzj5UF!HvTQ>$w*dg(z*3L#u`oT>PBaRtsEg z9Z(a0CT9pCw6p$%$VE+xi_|Qp(xAAUK9;~GsjZ+CGTpZOX+BA*>qbRQsWRylFYS15 zkx!XnB#UuSSJLx04&91nIsI(uNuWzds--2%^5nD2J8wH4X)lkAr-bg|4=wm3+3^So zB@e45e+|G^bdKGCp|#;^s)Ynf5Mx|fUw!uJr~k^I`-xk7K0=Hks5BxCs3yoXV4T;} z5PTY7^{e574?X(iQ%_DO)6j%u05{fDz4F4vbD#a?UwiMpbJmhlFwD#b5e=iU1R&|A zO&mXCn8^Upv~Dh6xm4G4CPPesz-W5C-gvw}nT`x4N@!t?W5Yy%g#BJ`YklLcJ5S#C z@cpf6kc?qt3?n0@u~<6@r*=c#iq6{o?_vesZ7Y^xPgxX`w^nJ!ltZ@w^g}&R%y^jaBwxa0GYqwNXMCbKfVnjk_)9V$A7-P!1$RWIJEvT-p ztY5#e^QGVTwWEhOA9(Pg+Q-C_#jNG0_Tm9ZAXb3Fy8G_Ge}8X!?(7APfe;l@gRrsI zT4qkwDn?CbAX^l-_C~LK^M$oxb>faYBxndiDMBg92=f|WI=Ox__T)|cA|9YkCR{{~ zf#z5dY$?E+CCO>BwvfuVGx^)6dfj3n-_337(VmamDJ13t$kIViVX~Nov-m zQ6emou^}rlGWnnlLTPVS$c~aOr|9-jPRtjFE`=kczci{)`==Jukwu!83Thh3cj@eq zlrl>`!sz|l#@b8IKmV8h%ztt5<_-`9@gjAM^VG%@5kPF}S@0eJjJ2!%;fWLXed>EZ zr6A2LXjDO{szNlr@cg&F{KaqVj>g6SKqTZ|uS%ed)HpCBF*6x!jIl0-_S*aJaI*zINZe_no}+&M08mnzRCS$*$RM zExB79=Onwf|4LROLSlf${ojfxb>YHnE5YJ?(S>Dv*rlO$zIP*Xy-n4PE!PiFF>@v) zk>`WoI&xq#neA=wBtKGb-&hfhCz_3G}W^A~-r)6_f0U@TW<>5N50(I5(+8tvQ9kEm7NE3JYHDxlB<{j?nAA4@nC-!^ID0@h zr^u#oT&x?H1_Vp(JV=(85OnJyeLqFG9qp@je(Y{g&^c-8+uq(qS<=j>Z*@l9j$>)L zx!g#$Q%=kVl+FQ&3!YjoYKlvddUKmC`_UD*c0 zm{*lGfKn?xXqwvlMpX^lVSjyN>%b>I`H6n7swZ`bLWa2HYuB!Q^@~rx@#eb`8l(Uq z)>x9M_!`2zL z#xgP>iea<9zPY)z`M~Li4;?(98jVR>O3G;(?NVat_<-2W8L)#kv>dojumG^sJy6#; z-rmyZJM=>@4bXZHyNUGs?4bGL$Y!vF%E2^}M54`uTYG!s>E4J40!WBHh)7g6#yabq z1(Af6iW*gf4FiBH3sY2Id-~ZkufP1j>H7~HK2p!-q(E$1z5ryo4iOQFYSk;B_{gId z&tExz=B#1>Vjz$xhPZUjIR}U_#u!4n?VYn^iq~I#^PN{;JA7pG(9z=(#ru@`2r*%f zvXW54vIaUw(l4o;TD2p!N9cuU4KmXqJyHoUtFYUH<5G-a`bAi(`x#xQNXd3YipwTk zTv}XeI$#H zhJ)eC%KB3u{rKjA&FOfWuCb=6Uw!$_XPNKnw9jBx{W^ z;6uH=vptzi*pPDu6cM>B%l@DrV~8UCVShZ{8;$na5HlImGuAq1Km}3Cvf9|#ICSXn zqmP{)3x_fjMi6<5BptpNDT`qvs1}9Y*xcON-W^ZIDeESMix8qU#ukRzM2!N1ObNjX1Z<2m zwm)2b=e=`JfBy4_HrMZa_`v`WgC{0L)R@2#oLTZrDmv(uk3aSJ)hoBoo;e$%CuCys zzClJ?TIX!x9FeMsMo9XJqO5Li?>zVPGvmEmC+uQAN zL;!?Vl+}K3l;h49L#*~b)+IgL;;ApUbrTCudRJH$t2Ipui`+#)=4vg1w)5Xei<$xn zQ{T2wxc+4Bs>|;^d&4UMSZSOXd877lVjN+q4u+Ca%oOM750t8l~NQj`wWDvE# zG91nP=YQ?DZ(hCl@Z%4ztR0xw4G|D<6j_|X6w*Sp*Y7|1v5#K6a_h`H?+6A(Vdln% zC{mS0ioY@*5%lneBF#pCv0^BLx()%s2z+QKMIv>4r<;are)>5Ep&CuC1mR)d5TFOQ3SQ0DI zZ4ZCUbENL5lHNpGUTG{k$8Jg4`Tw#iYSF{A08YGpw9)-bYa!_lO(@;8LNUg`&X!gA z9G!JkRPWcthejk71POtW2I-KH?yixRF6r*Bp}QPPnxR`-z91da(jd*yLrA~(_YQxv z7OXq>Jm)!Q@6T=&d(7^+Hhzrn%4U(U+2xvNK@rETcd25DpG=Vh8y?i&z|-$lKY0U! zqe+AySj{RGC@lAL3zJ82o-Y}@M#}pe+~+kFd%2F{n6t9pW)Z!}itn%M>1pf{Gc6sD zkN;AeLMD?w1kfeE)JDn26FffEIqtT$)au(oaa{?bs}=YOIp=F?9qg-X0ZHdm$4MK7 zc=X~&mK+6TlP~a>^3@ucZxpY8_1oBDNf@2hiIB+ls@C`|+mQDtVa3QSuFKLZj7=hRr1AWnKk$HFtCK3gXRI3DyA7L3t%;$<3>nadZfG*U*SVrF)^uQ1#D{ zMQVRUgihY`^g;rqZrjawEc77(4`H<7#lHt^uLIav@3$F6TRM0GPLFvc$jtx}YdG1Q zkb!nOtCGRD*<{oLS#*$2+Sb7XY_jWYmzCqj_j;dd&}i-^Uaglv?@d~(2`vuXg2s-a z$_ljgA4l0KDYyBuKnvPHL^GHJgDakOrdOC*V&-!p-@aMwx>9FMB5BeA;ivg#E>`73f1h2*u8_gm6+(3Xts%*`I9iKysVdDy?1pzt`|T@nJbh& z`zMp#$mcvlpvJI^-G$O}gbAXdYp%7YIy69zPL6wLuWQDsj9Q>^bM3|0r~pZ4Wd;0R z`S_{WE46@KH*pavk4}lNQ)|@53sZ@!SB~I|;1k@ek*ZS(oDq?Qd?4KKb0qR5o|Ex`Tntidxn1Tv0~{s zRtki0N9yDw%(%zp>c238^&S`J$_lACu6%c`qM9L0skHwtfHtB2R(m~gr`m_dT(<8h z06N8!OuL1n^LbuRNqNjB2cm8U-f~=9`k!t??0#1`>Ok zvq{W%>k9B*KX#qlunCbm#F_TR$=j1@$&zqMDo*tiqS46CxevjVfl%+sZ)QIlLgh6u zP~e3}=>dI_i}JG#hqNOR$Wt&;Bab1u)P(ET%`ESal#Y%y)S~{E08v{95+Xi8ZnvmE zTAJ&riL<9**VWWAwr*HvTTp^xkuj^)+NJ9Z7WSqKfaM$m4^*F~^QXfHyFFb;xv>Ka z%&d3+n6Z>Fq=~ghryZ$8Iagt-gGEh8B*CRMQd@76*xLRhi5OkL{~GtIQ|&``4Dn;= zeb~a6z~jZqAXASLuhX!bw|3TzZ|RK016$Da6lcTAM9+!#BG-M-({KG#wyj@T@@I$I z9N61BELM(;2=3u>6}@ku5tp}EZK~*b`c>O~KTi>sC+vSIzeqih#g_Lr9Gj5DZ6Xw> z_>7b&IjOt`wXKcRVGINZJv5=n77 zyBPT4TOIPPD%Px{-GRFjC2L^dBcuZ+2lp{>F{Kk$f0!2#X!*>4(snc9chVCzMcC+( z6E`rg*M}KRCP;0spGj{O?c~eE_TsP5yFSUCEc#DBEOyII>D(S2(=d(pH5+zn{9e(S ziR?73Q92iW3p()+He)CzG{dc5U=;vTE9}JHCTh6)&GM=kEhr9+&1V%hNEa7MV-kjj z6Pn+RMEd;b4zzQ+h**F6d)xY@1G!!Qeo(ESsk@@_OrC@!nyV!9)A?)>3>MXMd(d%v{a}mMP*g)~6B0uN#z>11WfJM=_IWiv-mMG%y zE0o=Nec0jD>0!!C6{{MfDKI~;U0jvJHD;eA&sPe44FYc;36ogb!5GMj_hC~uB8Gaa zODou-s7afJ>j)AV%f&a4NpfMbsy7&27Z(C3C{yGu1G)(17##GUYXx3szeBE?fyKJd z#?S9z1^r_af;u0~<1JIc1k5u9Q0%14$hg&sj`&uo{h!Iz)F;dNi#>e~_eOeO*ss1X zg<{loJfs+5F0ICTilKXk8}{L1gIP4Hw$P&Rqc^;*Iq31|o{Y;Wl5C=@>t*zWbc*R| zQ=>Hs6Pd!Hw6Z#HY7ToI2eLUH?wk^D99MmAr~s6Q|9cJ8=4vnS-EF(*<9?XeiqEOi zWKT6sqWuN$SyC`VmJfJ*IeG-(zG z9~r=ns$>n@1aL=2UaKAlf3I|meGp6IFpaOl%&GcP@SpZc!CBE-!zT$UIU53zIX5a( zjfLa({CRN$eVZG9>fe(SgW`E0wJh)vz*zkDa`ZolTmrQZVmxy)Uu-Yt9mqh7+%8K( zn)tU6a4&6W4m=y0dSCWVgm0e!I@KN?q+rh!7N^{=u<}!B{`or0*;c8I%?;Fl%4GJO zE7omiK6LUeS%#;gRYUpgnh}oy40(m~n%3eImpB6qb+;fW$Ig7#Q?kdYbEm>F2nW)wj3T7Gu-MLyvhb`@#J!J zVZT(;{GfxjTK@n*gLs8j2`tYWYH;GA=;}0oa|FuM3Kg_xBotAk!Q123#PQ%)kU~$J z)`>s92AAi5$9|viX}J?>k`Da2usygI>-ha)dt`>2W@$fN=4xnA0xVzfC3U|eljzSY)0tVW zc@1(^Jg*UVRGSC?FKXs-G+%KEA}hm8gB&~@0=9m4ShME{`q}R8#qpWe%~w_7RyUV_ z=uF4fm}z)HNQND3s6nm;P|*~-Z5jMJ?i=+ewZnu@KE{L-_P(iEpdgkRw#S7vuwcy{ z_DV&iA9DCVxyfTDWgE3G^2uVDlmZZO8^q6nrH%gKRIfFUG8asuY95HjM>~~vD6<25 z8!MVp!H{Zi!4KZar|0`GkL;O|O~FMiK4};cpODY(peT2rCd2QYd9-HJBC#dS@$p}O z!+>Z8ffutMKxv>1Q8<*?h)pw=G7h;Om|CiMEq4CWkbBr*Nj&S-FNY%J?HMW zX9*puxbvS8ON0AdC~Hvb#@(~cYPG=io3(cSKxFfRl)a=4l#md%q*j)C>(2s?bl9X6 z*7|4-ZF*6qU5&5vStpqnT2K#k%sV=3{|0pOy1lPgp9)0Ww||>hLQuL0z_fOFuC5WD z@5YX}=0)P7ncY;Sl(SD#incCZMvb!UE}wYnz9ME*BhDnoZWI6g*DEuC;zxnDxQ>Rt ztyipXbOq=`cFY={dXSY9PEyt7{BwMpfr6X*|+vQ{&B-XR4@e~s5LTLHLEczMgn-jqZ3YVt5Y1U z&z802Rn4FwX?sG2B6)D4dBb8%jO>&;am3AxuV|akR;g_D$W#66L0`z*!f%C4m0wI_ z`^P+L^!1FE|EvhPTOgE-A0FC}dsS}GoX_v1X=uU^4eMLlTbk>en_E2A(aP{Cm*_0a z+n8b+*y5W9$Q3gPcIhxjWST-9;HNVBW(|4M_cmdZ7XxHsD;Ep zgxov~oH=}+Ke!D))rsb+?4?GgPc!M!VN!p~mJ4+)zP+$i9)ugiNK_?joNG9-gS5nkq4YvO8kmKn)2k_rS$Q zGQb z>i+=}s|XUQgadB^ya;>)=o%teM;q8;(RZy-C#cZa$k-3kuP)1~Vrjg1dj1=CRpf;k#fz$7nisDHtqB|*ZVAg8vrC(_!^w(j1Ij7rO-iTR zzG#p$fH)&_c?#;!RpS1$$JRrMDQuAOI6u7Nc)TVx_Ic9l^Zh%q)wQYKDSd7s9{?p3 zeHu;_b-ue?cFO4rymFnT(a`99TO_gP(IrMcht!vb4(V!L`A!IG+mqMAEhp0OC$6x(;5VY$-jR~^$b|cRW|3~-n_kX$_`>OpAEcH$@?u^j znNgaHp+vNVjBpQ5*vyne3+*-T@vP39G|~{%c_-*=Z*E5=UB!y^2y}cODELcFW=?Mi zs0Cd&&OYmXGrrq<{(I4km?r@+=A+7eraMwaIF^v=s%w0E`x+mrNuc1v|Uty=wJn<^khHZ2@ zp13mO{G8=cqF`3Odjel@4ZLxw-vz+I{iHhm}XG~PNPf=sU!dv2~Z4miba ztZ{Its;ONrOv>uqOR=qB)_E<#r@1>=x)Ui&3_%HT|4)8Y-NDUOhQ9PIU^j1V{av;b zLBtmS!o(*u5GW1yrIw5Z>~^Q+c43Z1s!bt#8saEf_Pr67>1Wpz zPEVtNhA;4t@p)J5xvb}Mq|$l-iCG1??42y~HvdBo)BHZuVvJ&ThP-v>hw*kRyj`8o zu(OlHWR3C<9(I2vsX|;WVXdMEfk58!e>ixZTogKx_D&HSTQsuk(PeYwYCN7v1GZ=r zbiaE&PFBLiI@%=_1rRK~)giu?Tx2!GmdO`P@%3HWr1(?-vCw<>pf+$5nePQr3(*wE zqD>gwV)_m@>=Dp4UNkf?`sDr(ScWFn)>d;hHn*_(*03z<%jIwq{!!Q>6>MG4v%E!F zEnoMszT70Bns!s>^6IT?iWrylonq23Q?{`Ihx-2;Z987Ozpbi)(M+ig%sfu*A4Ry; z1|s4q7HTICv-20OI`i)JwR1eM<`<$W(G1cH_F+~cusJOPIM_6Z_ga)DxLH=C%ZW}B zJ21#eZLbmQvC8itU|yD$#_6V{-;p68C*&IdCM35_=s ze;S-)*a)+|e^c03J2~3d;4MV9FhPmX_mHJ|3*-KIaSPz-@KW1vw^g=>>I*z^9tTI! z=75%W=pfPmXxLA6Rm@NfduY7#`bwn#=g>$D;VWqzp%?F4v|IVRImg-bzn3Yvz1#J4 zlu3(NNRwVlyBzl^{ymTFAa%MF(>3&0(RJ_SLV+l<_y>B|e1=f#Zw(fYUcJ?!P#;36C}}PzXivkFT~ApQ`D?AXl6ZlV9MsR0GKi(9kzg6 zJw877j_bG7)8FG?z<(#`+E2!2uW^kvPlOsm`1%U-5x5aKQ2jA{i|^&-_|WqVd%l=| z`m^*7+-Pd2XD*F8T607KgH>X+COB3(tpu%i5r{r)jNHLJ2HFbOPj4^-tgHEKIYN|@ zwHFPGg8yx<6!sXD(56TA2Y*%{{%jIt%c?{9Gc4*bP#Ts!%8Rz@8t# z%N-A=xKzQr&tLKJx^%WKj}6|e`wde6>+3m<3VNnq`RHyTlzp673aYEGuWuB%m&?D6 zF#abe*4pJ&BE}X|SU0a{r>-D_cW(0W&&ranf!-0``qAwJ{qu|PTl))@RonFM=1Qd)a+L%l zi~LE^UdOYAs~FC)-V76V1vMrGr6J`7sC4E2nk1dnppGBQ!r4gFy9|1kZ&JP>I(pX^ zsN4EVjEo zwuH@vH1p=hwRqixl7iVr^6LEo2hjPJ7opkaNMNm+vO^&$o?los8h}Fib50Zl}4leN~@+RBGSz~ne7{+Ewl@S7}PodqVFF*hnR;Twos z5#_S0>v33Z&+RU7gugwFhgoSZAQ%0=+(%+7>QvPL4xP%buQu6I(3#;X$3yJUm>C6N zPLC5P8#h4)iKG3uACR_aFVyC-Rbw6%_>bUmjr!@a=ed9N2D7%PD_|=Ih)2onzS>oL ztPc7Y0gPD5%7F2qkX8oC+xc?%&#}s|CjdQY;!#3=8T%hCO6m*1?dZQcigE zKM&;2vyqP0c%U?^$`N$;-pac_4g6b?xaM{^yJ;?W-^ZtJ|Me88a$>;O9H1v!@;m+V!^f_prt4LzC3+H>GzMYzg@vdV$1*36I__V@tvmPINrc{6 zZ(X%7YuB0(kny-0F8H-6642dKYuzv@b!^)kT+UqZ1J?D$h zlVbmTv~Y=nRZNvtZTQ~2)VaFrif?Ydnu{O5n)@F+WDQFd_$8*8|MV6RH<7Gp)>^zK zjGuo-tWt@tES+^M@?kUC3Vql^FMjhhg(1NpWN6bxqG12CqN$%O?5?~(B9s6Ct$b@g zZ`A1O>IpbGx?M01d>pu<=zh_7YcHD5w@Hb8PbQ8F2kaXJennGHYbPP`y^La4=j-=Tf$Mv#0u zi%P~^fPZ0p!qd0$Ykxw=NMmbdjX+PfA>BLhn;5yy_@3k{D*;;4b2*t`PGm9-aynf~ zuiTr+`SiR7WDN%1j%7Cr)SOO`QxnD2%Lf-T$Gw4SPIrRI9bFDsXfaVWlYakeca%+i zT(l>~`14I7sLQpoKm<8c(1?D@XWxFQ!Z4tm75N!nQt$#vBtth~!*+VC`mLRvMSv3D z-n6u6%7*vb0+OtsZ03{zZ#lj?zGyIkxP=V&^Bsgbd73yF5BDxCejE+RRElVqFyvr>8?+rb4AQzG1mv(v})&mV$;NKo;Lo+YfPl#yWOsr@05&ZYsspi7P4tn(8;?u=tb-|s@3`Xf@F&{uL^N=ZN=}VZ*m=XGwiRbA zhDM_(@fCe!mJ88s#mfp>2RG0(R09&i$($*4(qsi8X3-!O30WMHQXaC<)IM{dru}zd z(a_swk{KBv_zaLD-y0~@@jSU}YHW{1->N-Nr2*4zkkefQXVsOaS3;o;!%*nNM}wKp4p zg>SEKJ__F_z?X>YwDQPqmxuP z&4`H=hiXXTXK17o7UxY`r!KmG0cg&TYuPtIn8GoDxm_6VtO?k%GZttjP!f@>>3{uNjs%xqry7ognPXDq>pzUzc-#E3Xj%$Ky5m$pPFny!mS3V4< z7!+1ySSZY^gXuMh^{T*jd9E=zJi9+!P9IC%Cf58uh*cq1_>A&Ru96@(*Gm^Y7d8pIVg5iH-C5Mt) z;GSYIE-LSB|KL+Sx|pgbIXOqnZu(Y~RzN6bLE z(~WChaYyVn@p;S1|K1NGjOH>S4BOzYL{duf<*LH?k0!5SrCpv|OG^27+cRont1Vim zf&(96<7Qeur=g8a;%HRQc|#TX(CNCDo*!^_KT4yFe&VYsPXIF+tXIYfO>s%$NI)76 zqP{~>B^BFF?`O-7ef@kreNRuibOO&t03v7Cnti(|>^>*b@It+~?j{!KTJlwQXIQ)? zL51BEEr@O#T86!VL*zlxOloSXseCx)r}tV5UZAFf>D$EvPapjXK-3p6_QV);zV}pZ z{IHVQ-IR6GbvrT4@tkgaoBq7O(Q|vv%C%u3^kPbmG%G*@g*j#;ct&)!gWIr6?2kzY2^E1Q# z+_|%j3d=1HkoyfuDs$(!xU~o}oyzp$lqf^jcXw$@EP`(v^hjLU!9uvUjjQgfo*l!> zD-&bSA`NsrcOA76BFU8T5*~3 z9bRVsjfHqQ*kK-Vc*er_s@+_o2~p1TMHC zRM9xl_?>!O`Z8_TkpjUT?P6jHb*694pcr_Xp|qkHZa`)vZG|KW0{%^i8bzEgJp~lw z)_+t9zgUZfL$eA;!@s*HV|@~8R;Ra{2w-n3m%lz5#*)4~%AE=9(09x*TEJu8$$`wd zK9AA2qcZAv>Nl$wbD*FOt4Pc;TIEG9x&!@V>VTk`>x}Jv<`eRH`T5@I`IDGl z`O?CF(QnjU@``RCMrupL_CmIdsUx@6`2o9&nP2=bhAC1#UzwG|Kjx}PL44#K>H1GZ z*#BiYU%l2QzeIiYwf)m54Y^Dw?{4mc-#r^q*BR*bJ2X@`x;!l-TPE1b?4r z5H_zxqxmQK+j!4}2{!wdwk4Nlyce7WROg(0*1h zEw|vHp{y-KTxT;EW8Qep8&)3DMsu}(_^+jV+N;N;R#?rcKp$tZp*v@?pR0h@Mf?DkLRxh30C!){>;0;AeDL8X z!O|+3*z153&7Q?7{=Lea_DVUwprgdcOO6Mx=UJuvr$w)|j%R}Bwc5wjpoc_&0_Q;o zBxASadN=N}SQAazXR@N6tqrowtLzLly7gO(OD3a=voNJ74nLZt2@)|2S5sDEC&hrl ziO!6E(-q}7Og_{yuF1+n=mj_x;>(|7yAD>D39=}K>zYWA9J_`w&%y@#(6~jQXQmrUqDa9{R6t&Au#nREaQg-?PjfHyIs`e=CI}zP&{; zsqguB|9n;Zu=l)ZtS-j$Smq|Js>nVz;iseHpv8AwoIO#hVx;47wbBTP;f{FJL~bqS zW+9iN;lu8lI?Zllj>Sv{(@Tk#%;%fzc$^bd(!c-7U4*Q|$?}v{8n6GGp zGqD~AsJEU*t$JR}^ynsXF@GE)<;tx0%E~O6h7Lo$#`O5`qz+5eY&*WN>y(wOuY44J zx)pnpdm7?+`s?rVa9HW|IAeStU;8|93KW>iuM177WM7v}UcV*Q(xxT#dn`1^PfzT= zc(d1nTucMQJtJ5;IPl|yjY)`PXowM!{gfki?+TBw_l6OApqZPI7G#erY7w&R@)p z3uE!+nW_?ija#L<)%%eWb(qLtL06ytj?6J8Bqr8;*u@g%BAiqApM;I`R>ThYDTpL6sVTpsMS!OXR!f&_ zbVlb6nBVx^-M!9#elK>_#^IlAgnZ0g|F`56bhTS4cGSX39k9yFg=yt^^se<3%sIdg zewCQZfJ``$pa%JTe3^))J%x%5F8^gwR!~YU#kV2xMtv$_| zmX_;9+s}e-wfhtFO*1722rTCvLCfkgXCR)VEi)yX=7grDC{17xwixLwAiI9KtXBun z?b(p|e%`mRHg+^FesTM1({|MLQdMdV)5L#L*dWzkg*+J?P9; zUJ`0z2Mp^!{Y4*}Ii7Q$M*$em>(=mh#JScO5axbD$tua!eqA--&0a3OsuybK4!X`R ztNnDl-Hcd}x`f23%rrSrRN5%L0Iy+0iL?wEXGF%n_pD%|p&@Nk{CH9zUNVGDiHRZ3 zfQe3_8k+oHu{_aRuN!q~8JfN6o5!z>i!~i`iKAg@mF0+S`nEm}M-cb0Opr_QKnpy^82k3e;46$GOS`5lF z$!M`i9ZssMs;Q~+mH{YB|C8AKpo_)5jxYZUebX@xIG(>h#W&jflvoj+Kr}39W~L4b zF%!TVHopU9cMUCSD?kkCn!XOZ%C>U*hOisu`$HgemJ2tvcS50ZmqWZcA!3PPx3I z!Uzb*q5<90VYy!@RPvps*kuVZ)3=KP^t{CZzkY0N&5@SVyBdl}TD-R4;v7Y07Hq|Z zn$@f^20?n}fMKbH8zTXC*zDeiaV&hhR}&YH?unSnl5_n^|m} z6m>g}wp++=2lV&;mk``kTZ4soi6T?%rC#jvYRuW zY=n_+7JPL5gH`P&V9Zvy5 zG_2t~p=bHt)ua5H;JWr5H8mCWBmq7Q?wXMO2aDP~XJXd@v8l;*?P8$M!Sa|+x zd^Z|&P;35)i%+1DSu9vy%AIR|Y5`)Tvee>;Xvg;;$^UUa8_$^E?(%royZI$fG*XwZ z-hlxU=N*zF!2a$jy);NJWI{S`PNC8W$Zqx)Cxs*`GMQC0D8htP|&94hv2lDLjRQv<>gwWBzzO-d?!- z1TqNndE^{VN>xov>fD^H9o*x4>eVV2m+D%{N+U^h`?EtDosTd#z+b;ESm=p4HBYgj zflR_tsd`gEM}OG&>pB)jPOdRY6)+QRxy~e98>fI$t68HUEup=>BmafdG>tizD0^{` ztdeD*y~c{mSF1ZFO~itk1)i|zM_Os)C(O*eWBTVhV1a=7fDFDNdCBE`R#RT=xZfHe zfGhRxu4b|%t?=l9^RgxOoLyV=b9$nR^gzxX@3!Oel~KMXrUs`0rXK?XDzV3e3WJ|c zLM_l2xqDj%)$7*1R3?@@TjQIt>dtB&r}N%3l9o;9&YhTFZhZbb`I!H-DfVFfhuxn2 zr!otwK4s%e(E&1}s>=3kUXQr}q4_D}4$tGe_%cTkkH@q90)AY*xZ|b@GxvmJm{Q_a zauDyyZ3C~NHWrAgO9xH299nE9DP-_9kmfJJpte}^`S!p5AxF(JmXdu=+~s4d zu2s*`<6PmJFSnbOPTl7NeW_94#n4OFVVQ=QP#PLRPYA_fyW^4qBmzjA2=So|{gzWt zeV3L>9C3~@#_l{JSkk2TA+z%McVq|87l;EJ zB}sZ!$cT(&4whwRc|_@x{19(BT~QGBMEv3qHZzdE{Lkytwf!AR%%049>rb$RmlMfa z%F;(b>(Z}#uiNZlcU#SXGTyeGgO?pIo)AD{4$-NPIf4>)99uOW&m-7(ROtli2Jsh( zirn(B6^EtP_e^!2?$caHq>>A9;43Wvpv$R4?<&9;0y%3j4F(I|Jhm*?2;@36k1Z-s zps)}Lx}xjq%=M-h74=mDH<*c=H(dJ4XG z-wjGs0{@ccv?p1+qkO=ZJdV?qw)+v*+V1l^*l1LlLW^XQ)Bd6Zm!p5~L4Zxu6glmK}~eiUyo)9YPB?Rrp^&S(uV+Cbdr1y8+tP03s!Q1q_ha-do8vd`Hdi1-rocZ>Cbjn~s^*T~PooKa0 zn(5(-6<1+1+tFg`OWN>_+#5(-a&EPV2BgI1U8JV{oSB>G;KZCmmDyzi0zQ$Vvu6#v zDpd+2V>5 z0Ve{>)ws;D#GExun@ri#>N2Hd@UUM`n^WggbCvg4Sh0&D4d$o`M`2D3$L{9{bwm{OOeXYQ+C6xeA2Vsr3B8aag$x zpdoz8_Bu(Cv+N+EpR;>`Gs{JyxB+kMEEI{F8M}Zv95G33 z)5sfBNoaU66V9(tX2s;Rs5CcnO;y26ZPy9GXy~Sstk8DWY!Q^Hs90IWGfRBrIamrb$LF6w2c%LHucMcG%WO$*if7zA?mEIYQaEEWDHFhA=mQx1#6A6o? zSudk?f(i>}vujtSV4es%G_c0yoIBU2k0PDE{=mm$TGbzSOxuULkN`5Ly7bGQ+{}56 zr;+93X<6g-qnG2;ujfm#N9*UyO2V=u@9i1|A|~bSFfYoSm$W~~%vQBkR_8r-KAleP zE#!B)c>7-hGvV<)B%vggWL2f7*@PWf)-BX9j_Sn|XKbHbEpJ>c9~rYm;n&#|F3Zn@ zYZShqZ8 zNt&-~hjw?45_1U@x_C@nOp~zkNOWL-qD9Z#03#D;e+w!mrkGihYnA7+-~cn9)rgc| z{gEG%265&p%M_pbfj{?&oUn6S#kMeEk$eDy^rWR_adCNQL)?1r)gj$6d08(&+0!&q z>mJJvJ*$o#DvNp&)qV_v!6v;f{97ybt;}V!1oKoG+zjJQ$AvW%dq&I3io-ZEeCav7 zQi@^K87aFW7JO` zHECnfRwb5BLcag*0MKw?)B3LS0?&^Y{gm?jBh~#+Rz!o{zvmll>|kOttz3IGD+ih3 z-F_DAmYKTm{p>Sg*rsDIHR%auK0}yT$_p?Wh$}gy*nz=Uz>?>(9KqyT!0GD$STk!K zUYUs#0=5Q<+?$Yht41L$DlocH_5oIBWx91Q!uqEap2H~=SuuAU4} zU{+WskoH`qSuxFV-c#Z7;s=rW2WNG8B`ijf`I}g$@G{%#=GEQ-Q`X6iqiG zZkXq==NP=urw-acOPbop`brSr!O!I1lc$glGrGREcyU^{4SD;jhqN|va>(0gZ`=hs zG~@U0qXC`%BVIiG>wQ+rI9bUMx@ctmG!R`{`i>1H$~k#&G{w81&bWrZn-ydzoCfDpssj)-zL*tqM!2{ zk9>nnJ;hfwNN>M3%lx9Eq7Rv-f^G9+US9rcPr&oZeXG-Yx5v%NDlq#e_#D-sI2?&F zh1vl+;zC~~<_T9O`xC12$$Ri!cGe=T>te~@YyNC`K|FqKdH8?Ig}O1-L>QpXm-I># zi`aI*W})JVwc5JcA;065r27riexqwAM%NUf;-Je}#8RAp)gNf`9Br4RH6uAo9)6Ny zpc^gO2BX5ciyamSQlde!^63oUO7P>Gf#iNptA(3itAG;v?T!P1W0i?B%` zTTdeG`|{m>OmT|hMAtU&_6k8*abZShU-(dPsD*^cfR-i$4y|e_vZ!cltEe*e*Tcrf zi2D*tG-H)vF`0iHgao)I!5C!KU6<_qOexd2I#YN@;=zypl~1 zRY^I&N`b#H+vqqr`H$a~S&IXclq!9+6&Ib%#4qoumVUO9ZMLmWjD9x8$nH9m_cG!# zA7Y@WF@>eZm?ks^jm&>l=|LcqO(GWA+|qL)4M=)gie^1WhLmzCE#U|Hn>LC*4s_`l z_^VW$VBOLP!ecWz+}6^?{@fN1RY9&~{iZcC*RQT_V!31HBypG@F9XEfnak3&6fhLu z2FX~^p)ToVKop`0F+#GXNOqBno15oT>2^A`l*h)4vFU2e-~Y4VKNoEf7q2XQyE*`54_Lbk<6NIW8_d%7^OdI(PD}fgC)V!*aArgp{ zfGPN0ExjJR$I{9FC>nSX4Ubv7Co`G>5)~si4=gy}Fi2b#WMtIi46LgYpapQ#F6?B=6h<}CLdMhN zkgN|?k;Izy>+-{TbflmpE#QtUDx>bx%BB|i#-UKaRN_QL3r{oj5iXKriB z<@)1wYvA$eW7zs#{Cc2sd-TlhNxCC=5*@>KtOV}}n)JsM_qz)O+FWU76gASZXb+&K zrg}Gf&!^6t8S}H6s;#Y^TZfB1N=wa3V{xO!jyC@rY~}?W*=Xu;oXQK3C#*BB9_;?7rk0OzB_u@zO-0%SU_AAVKEY@ zslF5OcJ}n0_b_7rC5x3Jx13qN>fTfi9iJa0iA4p!1c8LW;+WP?(hSpFdVXGdns$D; zzi2@Evb91nWD}UgG30lJ8y`zZG$2fxG^_=0M$@?8ro_Gd%@PV`DWEB&PU1ge==%Cb z?N4;2ds%Qhp`vbi?IKXjRGS6kY|BZOd^0pX@o#Qw=R6t>Ke6~wNFGzVn5eHfwi>k_ zw>uoB>K!L#W!aA9$kBiw#Stn{Y~`ASD|>F?PBWwbOtCwK#7;Xlr*6ZXf*zM)Drz;d zu4D4pkh7rOplh)^ucy^#1r(hH(}3$U3ggG)pv#-5-q!A`i?2fv9tlr4hMfC5&i4f$ zJuzJ|%&aVS35`e&_Ys6!_FQh^sR{x9J0oUXV(p&C(G&|Xh1Y)u$;^QfmVrp@CIBW(vgPe2Cj{I)(CP^~}8uQp1 zH>t_Bk&T1%(}pm_2v$2}C|(TBeicKkZSuF?T8;+x-7=9UG44F zXkE=n0YrfMF^>EQRynznG?i9K6`UofR$xNxzM7Om%Ls+KkS_Q0qFzHJdQC8^u){sd z%Tj;+9eHZDle@>dPw?pyT(@ukpX2!C{`3vg#2{fAJ(^Gz48F~#mqk|cZ2XM%JW48t zj1Ia;47_4}{>ysW86aE{3+YQJwn;A3PtuMcjHcp76LunUlkPw2BB*zTKt*R~6#VLX zoWt+^{{Kf#r$)@jVY-F(A7KD?y(5gU(0Y%O_Qk6J&aY<;ybn)vp#&mxVu#c*K4~8w z4aMK}{2ZUxLnnkfD|<>%*~0&ivbT(i@(sI3X9!7UhDJePXrzXc?(Q0p5+nublyGQ%dtdt^M=AJfyFipe zxZ}aF6nVY4;Y0;Qxs-}^$E*`-?9bNE4Vw;A&Zx8|Q*U3d!0YYx@zRO2tBPlWy?{Mi z5q=3%9ER1GW<)W6;|l**hLQb-Ev+_ky}bj;dzKzdw2l2KH!sBFb>tDF3;T2FUwDuDB?QbR4mHG;LZGod#Pg(^U^`!smr;V6n=4QFEsaQ zo-0vB9w5_B=JuT1AMPD#-)Ze$A0%b;v{dAekl*ZWG}(RcN$(%-wch0uwV7@-lzjhw z7pYubf-vj;SMmrs@??BSKq($8Lv>GW2;xr$!=X+5P>XOp4v&iK0D`mCfByiW+h$@~ zm_p_lz}gT9GMp_1){NIy3v2SkE7o?GVcd_;8;2^37wp0v8*FL`FlAN`G+HpB%vzYrQ`s@n$DMe51 zIyB4??m6;W=>8}t<&&l0%Z+_oe|x#8q&M00g&o#1Q>69SsT76_>$k~=J^Dc+)xIKX zq>LG=U0Y8FsS4}EFYMP>PGJm^jB zlbgA5i%x(LD5n)6I2E`GOXDY8Y?^;Ee~_fx^z?CioFEO$IZ`S#yo}CLj)geca*HK( zxTj|oKu#)Z7|(|MZ#w3kJMNACILkUz#NCZiPOB~!##a@ ziXM~ncgab4zZFUUF-^7JCqe#mM*bykzNH+@O)gmFNxplcSmZ08Bg#dG`m8ZqxQppv z|LT&3*XOS0i@r0KiU~V1zy?ckxzUrX6utD99S=_;N#vYf?6B0BVx zn(%22t4tpMS=`j-mT3H$DREssHdS~!+O+ye=X|V85d$w zi65!HO@#rEqvSTdIi zKwIOsXz0s8Z+o0$H?65Z9kG|NYZXP4=fc^y-@+)=We-~q_fPlt_s4f{{b#%sQq`CM zd$qQEkCvrsKr;ov%7K(RhweX8VzWd|m?#9mFnC6aHYuq)6s(N zotdyGB;_z3^8u4p8ynYW|RHf>X`V{#svrwql#X!T}zVAbjv z^%Y_Ka$?89*TseBlqPwT(7FBJoUhLle1!3!eTF=M_w=O#QiQR?upj;sK_}M@-iHfI zPGgc+pE3paPUouXoNhMG0G0|+&j5`aiuMExZzoyyUU6r>@Zuu+G=Gl!1lKVs*y