From 65cfca7024eb6984966b623404b2aa369a2aad8d Mon Sep 17 00:00:00 2001 From: lashanfaliq95 Date: Fri, 23 Feb 2018 09:00:18 +0530 Subject: [PATCH 01/21] Updated the last-known api to be able to return a number of records. --- .../service/api/DeviceEventManagementService.java | 6 +++++- .../impl/DeviceEventManagementServiceImpl.java | 12 +++++++++--- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/api/DeviceEventManagementService.java b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/api/DeviceEventManagementService.java index 8b6d7ed030..f4fcadba01 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/api/DeviceEventManagementService.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/api/DeviceEventManagementService.java @@ -290,7 +290,11 @@ public interface DeviceEventManagementService { Response getLastKnownData(@ApiParam(name = "deviceId", value = "id of the device ", required = false) @PathParam("deviceId") String deviceId, @ApiParam(name = "type", value = "name of the device type", required = false) - @PathParam("type") String deviceType); + @PathParam("type") String deviceType, + @ApiParam(name = "limit", value = "limit of the records that needs to be picked up", required = false) + @QueryParam("limit") int limit); + + @GET @Path("/{type}") diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/DeviceEventManagementServiceImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/DeviceEventManagementServiceImpl.java index 5a16fbccdb..0b9827372d 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/DeviceEventManagementServiceImpl.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/DeviceEventManagementServiceImpl.java @@ -340,12 +340,12 @@ public class DeviceEventManagementServiceImpl implements DeviceEventManagementSe } /** - * Returns the last know data point of the device type. + * Returns the last know data point of the device type or last known data points upto the limit. */ @GET @Path("/last-known/{type}/{deviceId}") @Override - public Response getLastKnownData(@PathParam("deviceId") String deviceId, @PathParam("type") String deviceType) { + public Response getLastKnownData(@PathParam("deviceId") String deviceId, @PathParam("type") String deviceType,@QueryParam("limit") int limit) { String query = DEFAULT_META_DEVICE_ID_ATTRIBUTE + ":" + deviceId; String tenantDomain = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantDomain(); String sensorTableName = getTableName(DeviceMgtAPIUtils.getStreamDefinition(deviceType, tenantDomain)); @@ -363,8 +363,13 @@ public class DeviceEventManagementServiceImpl implements DeviceEventManagementSe List sortByFields = new ArrayList<>(); SortByField sortByField = new SortByField(TIMESTAMP_FIELD_NAME, SortType.DESC); sortByFields.add(sortByField); + if(limit == 0){ EventRecords eventRecords = getAllEventsForDevice(sensorTableName, query, sortByFields, 0, 1); - return Response.status(Response.Status.OK.getStatusCode()).entity(eventRecords).build(); + return Response.status(Response.Status.OK.getStatusCode()).entity(eventRecords).build();} + else{ + EventRecords eventRecords = getAllEventsForDevice(sensorTableName, query, sortByFields, 0, limit); + return Response.status(Response.Status.OK.getStatusCode()).entity(eventRecords).build(); + } } catch (AnalyticsException e) { String errorMsg = "Error on retrieving stats on table " + sensorTableName + " with query " + query; log.error(errorMsg); @@ -379,6 +384,7 @@ public class DeviceEventManagementServiceImpl implements DeviceEventManagementSe } } + private void publishEventReceivers(String streamNameWithVersion, TransportType transportType , String requestedTenantDomain, String deviceType) throws RemoteException, UserStoreException, JWTClientException { From 7a1c17081b63623089627fc2719810f75d5acc5f Mon Sep 17 00:00:00 2001 From: lashanfaliq95 Date: Fri, 23 Feb 2018 18:15:15 +0530 Subject: [PATCH 02/21] fixed the issues --- .../api/DeviceEventManagementService.java | 14 +-- .../DeviceEventManagementServiceImpl.java | 105 +++++++++--------- 2 files changed, 60 insertions(+), 59 deletions(-) diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/api/DeviceEventManagementService.java b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/api/DeviceEventManagementService.java index f4fcadba01..f2413ec828 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/api/DeviceEventManagementService.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/api/DeviceEventManagementService.java @@ -288,13 +288,11 @@ public interface DeviceEventManagementService { } ) Response getLastKnownData(@ApiParam(name = "deviceId", value = "id of the device ", required = false) - @PathParam("deviceId") String deviceId, - @ApiParam(name = "type", value = "name of the device type", required = false) - @PathParam("type") String deviceType, - @ApiParam(name = "limit", value = "limit of the records that needs to be picked up", required = false) - @QueryParam("limit") int limit); - - + @PathParam("deviceId") String deviceId, + @ApiParam(name = "type", value = "name of the device type", required = false) + @PathParam("type") String deviceType, + @ApiParam(name = "limit", value = "limit of the records that needs to be picked up", required = false) + @QueryParam("limit") int limit); @GET @Path("/{type}") @@ -348,4 +346,4 @@ public interface DeviceEventManagementService { Response getDeviceTypeEventDefinition(@ApiParam(name = "type", value = "name of the device type", required = false) @PathParam("type")String deviceType) ; -} +} \ No newline at end of file diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/DeviceEventManagementServiceImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/DeviceEventManagementServiceImpl.java index 0b9827372d..e2c3c5642e 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/DeviceEventManagementServiceImpl.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/DeviceEventManagementServiceImpl.java @@ -76,8 +76,47 @@ public class DeviceEventManagementServiceImpl implements DeviceEventManagementSe private static final String MQTT_CONTENT_VALIDATOR = "default"; private static final String TIMESTAMP_FIELD_NAME = "_timestamp"; + private static AnalyticsDataAPI getAnalyticsDataAPI() { + PrivilegedCarbonContext ctx = PrivilegedCarbonContext.getThreadLocalCarbonContext(); + AnalyticsDataAPI analyticsDataAPI = + (AnalyticsDataAPI) ctx.getOSGiService(AnalyticsDataAPI.class, null); + if (analyticsDataAPI == null) { + String msg = "Analytics api service has not initialized."; + log.error(msg); + throw new IllegalStateException(msg); + } + return analyticsDataAPI; + } + + private static EventRecords getAllEventsForDevice(String tableName, String query, List sortByFields + , int offset, int limit) throws AnalyticsException { + int tenantId = CarbonContext.getThreadLocalCarbonContext().getTenantId(); + AnalyticsDataAPI analyticsDataAPI = getAnalyticsDataAPI(); + EventRecords eventRecords = new EventRecords(); + int eventCount = analyticsDataAPI.searchCount(tenantId, tableName, query); + if (eventCount == 0) { + eventRecords.setCount(0); + } + List resultEntries = analyticsDataAPI.search(tenantId, tableName, query, offset, limit, + sortByFields); + List recordIds = getRecordIds(resultEntries); + AnalyticsDataResponse response = analyticsDataAPI.get(tenantId, tableName, 1, null, recordIds); + eventRecords.setCount(eventCount); + eventRecords.setList(AnalyticsDataAPIUtil.listRecords(analyticsDataAPI, response)); + return eventRecords; + } + + private static List getRecordIds(List searchResults) { + List ids = new ArrayList<>(); + for (SearchResultEntry searchResult : searchResults) { + ids.add(searchResult.getId()); + } + return ids; + } + /** * Retrieves the stream definition from das for the given device type. + * * @return dynamic event attribute list */ @GET @@ -196,7 +235,7 @@ public class DeviceEventManagementServiceImpl implements DeviceEventManagementSe return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build(); } catch (EventStreamPersistenceAdminServiceEventStreamPersistenceAdminServiceExceptionException e) { log.error("Failed to create event store for, tenantDomain: " + tenantDomain + " deviceType" + deviceType, - e); + e); return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build(); } } @@ -229,9 +268,11 @@ public class DeviceEventManagementServiceImpl implements DeviceEventManagementSe } eventStreamAdminServiceStub.removeEventStreamDefinition(streamName, Constants.DEFAULT_STREAM_VERSION); EventReceiverAdminServiceCallbackHandler eventReceiverAdminServiceCallbackHandler = - new EventReceiverAdminServiceCallbackHandler() {}; + new EventReceiverAdminServiceCallbackHandler() { + }; EventPublisherAdminServiceCallbackHandler eventPublisherAdminServiceCallbackHandler = - new EventPublisherAdminServiceCallbackHandler() {}; + new EventPublisherAdminServiceCallbackHandler() { + }; String eventReceiverName = getReceiverName(deviceType, tenantDomain, TransportType.MQTT); @@ -254,7 +295,7 @@ public class DeviceEventManagementServiceImpl implements DeviceEventManagementSe tenantBasedEventReceiverAdminServiceStub = DeviceMgtAPIUtils.getEventReceiverAdminServiceStub(); tenantBasedEventStreamAdminServiceStub = DeviceMgtAPIUtils.getEventStreamAdminServiceStub(); tenantBasedEventStreamAdminServiceStub.removeEventStreamDefinition(streamName, - Constants.DEFAULT_STREAM_VERSION); + Constants.DEFAULT_STREAM_VERSION); tenantBasedEventReceiverAdminServiceStub.startundeployInactiveEventReceiverConfiguration( eventReceiverName, eventReceiverAdminServiceCallbackHandler); @@ -298,7 +339,7 @@ public class DeviceEventManagementServiceImpl implements DeviceEventManagementSe @Override public Response getData(@PathParam("deviceId") String deviceId, @QueryParam("from") long from, @QueryParam("to") long to, @PathParam("type") String deviceType, @QueryParam("offset") - int offset, @QueryParam("limit") int limit) { + int offset, @QueryParam("limit") int limit) { if (from == 0 || to == 0) { String errorMessage = "Invalid values for from/to"; return Response.status(Response.Status.BAD_REQUEST).entity(errorMessage).build(); @@ -345,7 +386,7 @@ public class DeviceEventManagementServiceImpl implements DeviceEventManagementSe @GET @Path("/last-known/{type}/{deviceId}") @Override - public Response getLastKnownData(@PathParam("deviceId") String deviceId, @PathParam("type") String deviceType,@QueryParam("limit") int limit) { + public Response getLastKnownData(@PathParam("deviceId") String deviceId, @PathParam("type") String deviceType, @QueryParam("limit") int limit) { String query = DEFAULT_META_DEVICE_ID_ATTRIBUTE + ":" + deviceId; String tenantDomain = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantDomain(); String sensorTableName = getTableName(DeviceMgtAPIUtils.getStreamDefinition(deviceType, tenantDomain)); @@ -363,10 +404,10 @@ public class DeviceEventManagementServiceImpl implements DeviceEventManagementSe List sortByFields = new ArrayList<>(); SortByField sortByField = new SortByField(TIMESTAMP_FIELD_NAME, SortType.DESC); sortByFields.add(sortByField); - if(limit == 0){ - EventRecords eventRecords = getAllEventsForDevice(sensorTableName, query, sortByFields, 0, 1); - return Response.status(Response.Status.OK.getStatusCode()).entity(eventRecords).build();} - else{ + if (limit == 0) { + EventRecords eventRecords = getAllEventsForDevice(sensorTableName, query, sortByFields, 0, 1); + return Response.status(Response.Status.OK.getStatusCode()).entity(eventRecords).build(); + } else { EventRecords eventRecords = getAllEventsForDevice(sensorTableName, query, sortByFields, 0, limit); return Response.status(Response.Status.OK.getStatusCode()).entity(eventRecords).build(); } @@ -384,7 +425,6 @@ public class DeviceEventManagementServiceImpl implements DeviceEventManagementSe } } - private void publishEventReceivers(String streamNameWithVersion, TransportType transportType , String requestedTenantDomain, String deviceType) throws RemoteException, UserStoreException, JWTClientException { @@ -399,7 +439,8 @@ public class DeviceEventManagementServiceImpl implements DeviceEventManagementSe .getActiveEventReceiverConfiguration(eventRecieverNameTobeRemoved); if (eventReceiverConfigurationDto != null) { EventReceiverAdminServiceCallbackHandler eventReceiverAdminServiceCallbackHandler = - new EventReceiverAdminServiceCallbackHandler() {}; + new EventReceiverAdminServiceCallbackHandler() { + }; receiverAdminServiceStub.startundeployActiveEventReceiverConfiguration(eventRecieverNameTobeRemoved , eventReceiverAdminServiceCallbackHandler); } @@ -474,7 +515,7 @@ public class DeviceEventManagementServiceImpl implements DeviceEventManagementSe private void publishEventStore(String streamName, String version, EventAttributeList eventAttributes) throws RemoteException, UserStoreException, JWTClientException, - EventStreamPersistenceAdminServiceEventStreamPersistenceAdminServiceExceptionException { + EventStreamPersistenceAdminServiceEventStreamPersistenceAdminServiceExceptionException { EventStreamPersistenceAdminServiceStub eventStreamPersistenceAdminServiceStub = DeviceMgtAPIUtils.getEventStreamPersistenceAdminServiceStub(); try { @@ -545,44 +586,6 @@ public class DeviceEventManagementServiceImpl implements DeviceEventManagementSe return deviceType.replace(" ", "_").trim() + "-" + tenantDomain + "-" + transportType.toString() + "-receiver"; } - private static AnalyticsDataAPI getAnalyticsDataAPI() { - PrivilegedCarbonContext ctx = PrivilegedCarbonContext.getThreadLocalCarbonContext(); - AnalyticsDataAPI analyticsDataAPI = - (AnalyticsDataAPI) ctx.getOSGiService(AnalyticsDataAPI.class, null); - if (analyticsDataAPI == null) { - String msg = "Analytics api service has not initialized."; - log.error(msg); - throw new IllegalStateException(msg); - } - return analyticsDataAPI; - } - - private static EventRecords getAllEventsForDevice(String tableName, String query, List sortByFields - , int offset, int limit) throws AnalyticsException { - int tenantId = CarbonContext.getThreadLocalCarbonContext().getTenantId(); - AnalyticsDataAPI analyticsDataAPI = getAnalyticsDataAPI(); - EventRecords eventRecords = new EventRecords(); - int eventCount = analyticsDataAPI.searchCount(tenantId, tableName, query); - if (eventCount == 0) { - eventRecords.setCount(0); - } - List resultEntries = analyticsDataAPI.search(tenantId, tableName, query, offset, limit, - sortByFields); - List recordIds = getRecordIds(resultEntries); - AnalyticsDataResponse response = analyticsDataAPI.get(tenantId, tableName, 1, null, recordIds); - eventRecords.setCount(eventCount); - eventRecords.setList(AnalyticsDataAPIUtil.listRecords(analyticsDataAPI, response)); - return eventRecords; - } - - private static List getRecordIds(List searchResults) { - List ids = new ArrayList<>(); - for (SearchResultEntry searchResult : searchResults) { - ids.add(searchResult.getId()); - } - return ids; - } - private void cleanup(Stub stub) { if (stub != null) { try { From 1cfcc3a599d65e941095530671ea1af06e15f018 Mon Sep 17 00:00:00 2001 From: n-jay Date: Mon, 12 Mar 2018 14:27:12 +0530 Subject: [PATCH 03/21] Added iOS DEP API scopes in UI config file --- .../main/resources/jaggeryapps/devicemgt/app/conf/config.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/conf/config.json b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/conf/config.json index 6a59e99d0f..3dcaa53dcf 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/conf/config.json +++ b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/conf/config.json @@ -153,7 +153,9 @@ "perm:admin:device-type", "perm:device:enroll", "perm:geo-service:analytics-view", - "perm:geo-service:alerts-manage" + "perm:geo-service:alerts-manage", + "perm:ios:dep-add", + "perm:ios:dep-view" ], "isOAuthEnabled": true, "backendRestEndpoints": { From fedd2a32579797f3335bfe496841eed2fa35981c Mon Sep 17 00:00:00 2001 From: n-jay Date: Mon, 12 Mar 2018 14:28:24 +0530 Subject: [PATCH 04/21] Added iOS DEP management page to navbar --- .../app/units/cdmf.unit.ui.navbar.nav-menu/nav-menu.hbs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.ui.navbar.nav-menu/nav-menu.hbs b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.ui.navbar.nav-menu/nav-menu.hbs index 886bb4ccbe..3479a9772b 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.ui.navbar.nav-menu/nav-menu.hbs +++ b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.ui.navbar.nav-menu/nav-menu.hbs @@ -120,6 +120,11 @@ Certificate Configurations +
  • + + DEP Configurations + +
  • From 280a63bdbda010534d8f28362dc34d4cd9de1111 Mon Sep 17 00:00:00 2001 From: n-jay Date: Tue, 13 Mar 2018 15:13:22 +0530 Subject: [PATCH 05/21] Remove UI API scopes from config file --- .../main/resources/jaggeryapps/devicemgt/app/conf/config.json | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/conf/config.json b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/conf/config.json index 3dcaa53dcf..6a59e99d0f 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/conf/config.json +++ b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/conf/config.json @@ -153,9 +153,7 @@ "perm:admin:device-type", "perm:device:enroll", "perm:geo-service:analytics-view", - "perm:geo-service:alerts-manage", - "perm:ios:dep-add", - "perm:ios:dep-view" + "perm:geo-service:alerts-manage" ], "isOAuthEnabled": true, "backendRestEndpoints": { From 43feaf7bc7d73a9f2754b6ed18d59e1543ba0c21 Mon Sep 17 00:00:00 2001 From: n-jay Date: Wed, 14 Mar 2018 10:56:47 +0530 Subject: [PATCH 06/21] Add DEP management icon to navmenu The DEP management page is formed once the iOS plugin has been deployed within the IoT Home. Till then, any functionality with regards to DEP management is not present within the server. An icon in the navmenu allows users to access the DEP management page. This commit includes the feature where the navmenu detects if the iOS plugin has been deployed and accordingly displays the icon to access the DEP management page. --- .../units/cdmf.unit.ui.navbar.nav-menu/nav-menu.hbs | 12 +++++++----- .../units/cdmf.unit.ui.navbar.nav-menu/nav-menu.js | 12 ++++++++++++ 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.ui.navbar.nav-menu/nav-menu.hbs b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.ui.navbar.nav-menu/nav-menu.hbs index 3479a9772b..134da44a3e 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.ui.navbar.nav-menu/nav-menu.hbs +++ b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.ui.navbar.nav-menu/nav-menu.hbs @@ -120,11 +120,13 @@ Certificate Configurations -
  • - - DEP Configurations - -
  • + {{#unless iosPluginFlag}} +
  • + + DEP Configurations + +
  • + {{/unless}} diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.ui.navbar.nav-menu/nav-menu.js b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.ui.navbar.nav-menu/nav-menu.js index 69e306f590..eda5f28ff7 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.ui.navbar.nav-menu/nav-menu.js +++ b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.ui.navbar.nav-menu/nav-menu.js @@ -28,6 +28,7 @@ function onRequest(context) { } }); var userModule = require("/app/modules/business-controllers/user.js")["userModule"]; + var deviceModule = require("/app/modules/business-controllers/device.js")["deviceModule"]; var mdmProps = require("/app/modules/conf-reader/main.js")["conf"]; var constants = require("/app/modules/constants.js"); var uiPermissions = userModule.getUIPermissions(); @@ -41,6 +42,17 @@ function onRequest(context) { "device-mgt": [] }; + var typesListResponse = deviceModule.getDeviceTypesConfig(); + var temp = []; + temp = typesListResponse["content"]; + var iosPluginFlag = false; + temp.forEach(function(element) { + if (element["name"] == "ios") { + iosPluginFlag = true; + } + }); + context["iosPluginFlag"] = iosPluginFlag; + // following context.link value comes here based on the value passed at the point // where units are attached to a page zone. // eg: {{unit "appbar" pageLink="users" title="User Management"}} From 84c683a02b36ed2f6712f3e8680e73e2223bc2fc Mon Sep 17 00:00:00 2001 From: n-jay Date: Wed, 14 Mar 2018 11:03:37 +0530 Subject: [PATCH 07/21] Edit nav-menu to include change DEP management page visibility logic --- .../app/units/cdmf.unit.ui.navbar.nav-menu/nav-menu.hbs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.ui.navbar.nav-menu/nav-menu.hbs b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.ui.navbar.nav-menu/nav-menu.hbs index 134da44a3e..9a1d868dec 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.ui.navbar.nav-menu/nav-menu.hbs +++ b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.ui.navbar.nav-menu/nav-menu.hbs @@ -120,13 +120,13 @@ Certificate Configurations - {{#unless iosPluginFlag}} + {{#if iosPluginFlag}}
  • DEP Configurations
  • - {{/unless}} + {{/if}} From 790f91b3b71b04f10d5ec254e60a599f0dd28d23 Mon Sep 17 00:00:00 2001 From: Arcane94 Date: Tue, 9 Jan 2018 10:12:15 +0530 Subject: [PATCH 08/21] Add method overloads --- .../impl/GeoLocationBasedServiceImpl.java | 23 +++ .../service/GeoLocationProviderService.java | 3 + .../GeoLocationProviderServiceImpl.java | 152 ++++++++++++++++++ .../app/pages/cdmf.page.devices/devices.js | 3 +- 4 files changed, 180 insertions(+), 1 deletion(-) diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/GeoLocationBasedServiceImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/GeoLocationBasedServiceImpl.java index 487b367b63..7890b463fc 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/GeoLocationBasedServiceImpl.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/GeoLocationBasedServiceImpl.java @@ -185,6 +185,29 @@ public class GeoLocationBasedServiceImpl implements GeoLocationBasedService { } } + + @Path("alerts/{alertType}") + @POST + @Consumes("application/json") + @Produces("application/json") + public Response createGeoAlertsForGeoDashboard(Alert alert, @PathParam("alertType") String alertType) { + try { + // this is the user who initiates the request + String authorizedUser = MultitenantUtils.getTenantAwareUsername( + CarbonContext.getThreadLocalCarbonContext().getUsername() + ); + + GeoLocationProviderService geoService = DeviceMgtAPIUtils.getGeoService(); + geoService.createGeoAlert(alert, alertType); + return Response.ok().build(); + } catch (GeoLocationBasedServiceException e) { + String error = "Error occurred while creating " + alertType + "alert"; + log.error(error, e); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(error).build(); + } + } + + @Path("alerts/{alertType}/{deviceType}/{deviceId}") @PUT @Consumes("application/json") diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/geo/service/GeoLocationProviderService.java b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/geo/service/GeoLocationProviderService.java index 4c9e02f158..924f385dd3 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/geo/service/GeoLocationProviderService.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/geo/service/GeoLocationProviderService.java @@ -35,6 +35,9 @@ public interface GeoLocationProviderService { boolean createGeoAlert(Alert alert, DeviceIdentifier identifier, String alertType) throws GeoLocationBasedServiceException, AlertAlreadyExistException; + boolean createGeoAlert(Alert alert, String alertType) + throws GeoLocationBasedServiceException; + boolean updateGeoAlert(Alert alert, DeviceIdentifier identifier, String alertType) throws GeoLocationBasedServiceException, AlertAlreadyExistException; diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/geo/service/GeoLocationProviderServiceImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/geo/service/GeoLocationProviderServiceImpl.java index f888d7c32c..1243363cd2 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/geo/service/GeoLocationProviderServiceImpl.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/geo/service/GeoLocationProviderServiceImpl.java @@ -213,12 +213,110 @@ public class GeoLocationProviderServiceImpl implements GeoLocationProviderServic return saveGeoAlert(alert, identifier, alertType, false); } + @Override + public boolean createGeoAlert(Alert alert, String alertType) + throws GeoLocationBasedServiceException { + return saveGeoAlert(alert, alertType, false); + } + @Override public boolean updateGeoAlert(Alert alert, DeviceIdentifier identifier, String alertType) throws GeoLocationBasedServiceException, AlertAlreadyExistException { return saveGeoAlert(alert, identifier, alertType, true); } + public boolean saveGeoAlert(Alert alert, String alertType, boolean isUpdate) + throws GeoLocationBasedServiceException { + + Type type = new TypeToken>() { + }.getType(); + Gson gson = new Gson(); + Map parseMap = gson.fromJson(alert.getParseData(), type); + + Map options = new HashMap<>(); + Object content = null; + + if (GeoServices.ALERT_TYPE_WITHIN.equals(alertType)) { + options.put(GeoServices.QUERY_NAME, alert.getQueryName()); + options.put(GeoServices.AREA_NAME, alert.getCustomName()); + content = parseMap.get(GeoServices.GEO_FENCE_GEO_JSON); + + } else if (GeoServices.ALERT_TYPE_EXIT.equals(alertType)) { + options.put(GeoServices.QUERY_NAME, alert.getQueryName()); + options.put(GeoServices.AREA_NAME, alert.getCustomName()); + content = parseMap.get(GeoServices.GEO_FENCE_GEO_JSON); + + } else if (GeoServices.ALERT_TYPE_SPEED.equals(alertType)) { + content = parseMap.get(GeoServices.SPEED_ALERT_VALUE); + + } else if (GeoServices.ALERT_TYPE_PROXIMITY.equals(alertType)) { + options.put(GeoServices.PROXIMITY_DISTANCE, alert.getProximityDistance()); + options.put(GeoServices.PROXIMITY_TIME, alert.getProximityTime()); + content = alert.getParseData(); + + } else if (GeoServices.ALERT_TYPE_STATIONARY.equals(alertType)) { + options.put(GeoServices.QUERY_NAME, alert.getQueryName()); + options.put(GeoServices.AREA_NAME, alert.getCustomName()); + options.put(GeoServices.STATIONARY_TIME, alert.getStationeryTime()); + options.put(GeoServices.FLUCTUATION_RADIUS, alert.getFluctuationRadius()); + content = alert.getParseData(); + + } else if (GeoServices.ALERT_TYPE_TRAFFIC.equals(alertType)) { + content = parseMap.get(GeoServices.GEO_FENCE_GEO_JSON); + } else { + throw new GeoLocationBasedServiceException( + "Unrecognized execution plan type: " + alertType + " while creating geo alert"); + } + + //persist alert in registry + updateRegistry(getRegistryPath(alertType, alert.getQueryName()), content, + options); + + //deploy alert into event processor + EventProcessorAdminServiceStub eventprocessorStub = null; + String action = (isUpdate ? "updating" : "creating"); + try { + eventprocessorStub = getEventProcessorAdminServiceStub(); + String parsedTemplate = parseTemplate(alertType, parseMap); + String validationResponse = eventprocessorStub.validateExecutionPlan(parsedTemplate); + if (validationResponse.equals("success")) { + if (isUpdate) { + String executionPlanName = getExecutionPlanName(alertType, alert.getQueryName()); + eventprocessorStub.editActiveExecutionPlan(parsedTemplate, executionPlanName); + } else { + eventprocessorStub.deployExecutionPlan(parsedTemplate); + } + } else { + if (validationResponse.startsWith( + "'within' is neither a function extension nor an aggregated attribute extension" + )) { + log.error("GPL Siddhi Geo Extension is not configured. Please execute maven script " + + "`siddhi-geo-extention-deployer.xml` in $IOT_HOME/analytics/scripts"); + } else { + log.error("Execution plan validation failed: " + validationResponse); + } + throw new GeoLocationBasedServiceException( + "Error occurred while " + action + " geo " + alertType); + } + return true; + } catch (AxisFault axisFault) { + throw new GeoLocationBasedServiceException( + "Event processor admin service initialization failed while " + action + " geo alert '" + + alertType, axisFault + ); + } catch (IOException e) { + throw new GeoLocationBasedServiceException( + "Event processor admin service failed while " + action + " geo alert '" + + alertType, e); + } catch (JWTClientException e) { + throw new GeoLocationBasedServiceException( + "JWT token creation failed while " + action + " geo alert '" + alertType, e); + } finally { + cleanup(eventprocessorStub); + } + + } + public boolean saveGeoAlert(Alert alert, DeviceIdentifier identifier, String alertType, boolean isUpdate) throws GeoLocationBasedServiceException, AlertAlreadyExistException { @@ -358,6 +456,34 @@ public class GeoLocationProviderServiceImpl implements GeoLocationProviderServic return path; } + private String getRegistryPath(String alertType, String queryName) + throws GeoLocationBasedServiceException { + String path = ""; + if (GeoServices.ALERT_TYPE_WITHIN.equals(alertType)) { + path = GeoServices.REGISTRY_PATH_FOR_ALERTS + GeoServices.ALERT_TYPE_WITHIN + + "/" + "/" + queryName; + } else if (GeoServices.ALERT_TYPE_EXIT.equals(alertType)) { + path = GeoServices.REGISTRY_PATH_FOR_ALERTS + GeoServices.ALERT_TYPE_EXIT + + "/" + queryName; + } else if (GeoServices.ALERT_TYPE_SPEED.equals(alertType)) { + path = GeoServices.REGISTRY_PATH_FOR_ALERTS + GeoServices.ALERT_TYPE_SPEED + + "/" ; + } else if (GeoServices.ALERT_TYPE_PROXIMITY.equals(alertType)) { + path = GeoServices.REGISTRY_PATH_FOR_ALERTS + GeoServices.ALERT_TYPE_PROXIMITY + + "/" + queryName; + } else if (GeoServices.ALERT_TYPE_STATIONARY.equals(alertType)) { + path = GeoServices.REGISTRY_PATH_FOR_ALERTS + GeoServices.ALERT_TYPE_STATIONARY + + "/" + queryName; + } else if (GeoServices.ALERT_TYPE_TRAFFIC.equals(alertType)) { + path = GeoServices.REGISTRY_PATH_FOR_ALERTS + GeoServices.ALERT_TYPE_TRAFFIC + + "/" + queryName; + } else { + throw new GeoLocationBasedServiceException( + "Unrecognized execution plan type: " + alertType); + } + return path; + } + private String getExecutionPlanName(String alertType, String queryName, String deviceId) { if ("Traffic".equals(alertType)) { return "Geo-ExecutionPlan-Traffic_" + queryName + "_alert"; @@ -368,6 +494,14 @@ public class GeoLocationProviderServiceImpl implements GeoLocationProviderServic } } + private String getExecutionPlanName(String alertType, String queryName) { + if ("Traffic".equals(alertType)) { + return "Geo-ExecutionPlan-Traffic_" + queryName + "_alert"; + } else { + return "Geo-ExecutionPlan-" + alertType + "_" + queryName + "---_" + "_alert"; + } + } + @Override public boolean removeGeoAlert(String alertType, DeviceIdentifier identifier, String queryName) throws GeoLocationBasedServiceException { @@ -650,6 +784,24 @@ public class GeoLocationProviderServiceImpl implements GeoLocationProviderServic } } + private void updateRegistry(String path, Object content, Map options) + throws GeoLocationBasedServiceException { + try { + + Registry registry = getGovernanceRegistry(); + Resource newResource = registry.newResource(); + newResource.setContent(content); + newResource.setMediaType("application/json"); + for (Map.Entry option : options.entrySet()) { + newResource.addProperty(option.getKey(), option.getValue()); + } + registry.put(path, newResource); + } catch (RegistryException e) { + throw new GeoLocationBasedServiceException( + "Error occurred while setting the Within Alert", e); + } + } + /** * Loads the keystore. * diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/pages/cdmf.page.devices/devices.js b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/pages/cdmf.page.devices/devices.js index c973d07985..407819fef9 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/pages/cdmf.page.devices/devices.js +++ b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/pages/cdmf.page.devices/devices.js @@ -10,7 +10,8 @@ * * 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 + * "AS IS" BASIS, WITHOUTna innawa kiala + WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. From 7583957e16710e441e3394f75d5bebe9fbf08f5b Mon Sep 17 00:00:00 2001 From: Arcane94 Date: Fri, 26 Jan 2018 12:51:44 +0530 Subject: [PATCH 09/21] Execution Plans and other updates --- .../service/api/GeoLocationBasedService.java | 56 ++++++++++++++++++- .../GeoLocationProviderServiceImpl.java | 24 +++++++- ...lan-Exit_alert_for_deviceClusters.siddhiql | 21 +++++++ ...an-Speed_alert_for_deviceClusters.siddhiql | 21 +++++++ ...-Traffic_alert_for_deviceClusters.siddhiql | 17 ++++++ ...n-Within_alert_for_deviceClusters.siddhiql | 20 +++++++ .../app/pages/cdmf.page.devices/devices.js | 3 +- 7 files changed, 158 insertions(+), 4 deletions(-) create mode 100644 components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/resources/alerts/Geo-ExecutionPlan-Exit_alert_for_deviceClusters.siddhiql create mode 100644 components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/resources/alerts/Geo-ExecutionPlan-Speed_alert_for_deviceClusters.siddhiql create mode 100644 components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/resources/alerts/Geo-ExecutionPlan-Traffic_alert_for_deviceClusters.siddhiql create mode 100644 components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/resources/alerts/Geo-ExecutionPlan-Within_alert_for_deviceClusters.siddhiql diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/api/GeoLocationBasedService.java b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/api/GeoLocationBasedService.java index a05285f790..b2088f5ba5 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/api/GeoLocationBasedService.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/api/GeoLocationBasedService.java @@ -232,7 +232,7 @@ public interface GeoLocationBasedService { /** * Create Geo alerts - */ + */ @POST @Path("alerts/{alertType}/{deviceType}/{deviceId}") @ApiOperation( @@ -295,6 +295,60 @@ public interface GeoLocationBasedService { required = true) @PathParam("alertType") String alertType); + + /** + * Create Geo alerts for geo-dashboard + */ + @POST + @Path("/alerts/{alertType}") + @ApiOperation( + consumes = "application/json", + produces = "application/json", + httpMethod = "POST", + value = "Create Geo alerts for the device", + notes = "", + response = Response.class, + tags = "Geo Service Management", + extensions = { + @Extension(properties = { + @ExtensionProperty(name = Constants.SCOPE, value = "perm:geo-service:alerts-manage") + }) + } + ) + @ApiResponses(value = { + @ApiResponse( + code = 200, + message = "OK.", + response = Response.class, + responseHeaders = { + @ResponseHeader( + name = "Content-Type", + description = "The content type of the body") + }), + @ApiResponse( + code = 400, + message = "Bad Request. \n Invalid Device Identifiers found.", + response = Response.class), + @ApiResponse( + code = 401, + message = "Unauthorized. \n Unauthorized request."), + @ApiResponse( + code = 500, + message = "Internal Server Error. \n Error on retrieving stats", + response = Response.class) + }) + Response createGeoAlertsForGeoDashboard( + @ApiParam( + name = "alert", + value = "The alert object", + required = true) + @Valid Alert alert, + @ApiParam( + name = "alertType", + value = "The alert type, such as Within, Speed, Stationary", + required = true) + @PathParam("alertType") String alertType); + /** * Update Geo alerts */ diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/geo/service/GeoLocationProviderServiceImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/geo/service/GeoLocationProviderServiceImpl.java index 1243363cd2..39cd9e71dd 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/geo/service/GeoLocationProviderServiceImpl.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/geo/service/GeoLocationProviderServiceImpl.java @@ -277,7 +277,7 @@ public class GeoLocationProviderServiceImpl implements GeoLocationProviderServic String action = (isUpdate ? "updating" : "creating"); try { eventprocessorStub = getEventProcessorAdminServiceStub(); - String parsedTemplate = parseTemplate(alertType, parseMap); + String parsedTemplate = parseTemplateForDeviceClusters(alertType, parseMap); String validationResponse = eventprocessorStub.validateExecutionPlan(parsedTemplate); if (validationResponse.equals("success")) { if (isUpdate) { @@ -765,6 +765,28 @@ public class GeoLocationProviderServiceImpl implements GeoLocationProviderServic } } + private String parseTemplateForDeviceClusters(String alertType, Map parseMap) throws + GeoLocationBasedServiceException { + String templatePath = "alerts/Geo-ExecutionPlan-" + alertType + "_alert_for_deviceClusters.siddhiql"; + InputStream resource = getClass().getClassLoader().getResourceAsStream(templatePath); + if (resource == null) { + throw new GeoLocationBasedServiceException("Could not find template in path : " + templatePath); + } + try { + //Read template + String template = IOUtils.toString(resource, StandardCharsets.UTF_8.toString()); + //Replace variables + for (Map.Entry parseEntry : parseMap.entrySet()) { + String find = "\\$" + parseEntry.getKey(); + template = template.replaceAll(find, parseEntry.getValue()); + } + return template; + } catch (IOException e) { + throw new GeoLocationBasedServiceException( + "Error occurred while populating the template for the Within Alert", e); + } + } + private void updateRegistry(String path, DeviceIdentifier identifier, Object content, Map options) throws GeoLocationBasedServiceException { try { diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/resources/alerts/Geo-ExecutionPlan-Exit_alert_for_deviceClusters.siddhiql b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/resources/alerts/Geo-ExecutionPlan-Exit_alert_for_deviceClusters.siddhiql new file mode 100644 index 0000000000..2259abacdc --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/resources/alerts/Geo-ExecutionPlan-Exit_alert_for_deviceClusters.siddhiql @@ -0,0 +1,21 @@ +/* Enter a unique ExecutionPlan */ +@Plan:name('$executionPlanName') + +/* Enter a unique description for ExecutionPlan */ +-- @Plan:description('ExecutionPlan') + +/* define streams/tables and write queries here ... */ + +@Import('org.wso2.geo.StandardSpatialEvents:1.0.0') +define stream dataIn (id string, latitude double, longitude double, timeStamp long, type string ,speed float, heading float, eventId string); + +@Export('org.wso2.geo.ProcessedSpatialEvents:1.0.0') +define stream dataOut (id string, latitude double, longitude double, timeStamp long, type string ,speed float, heading float, eventId string, state string, information string); + +from dataIn[geo:within(longitude,latitude,"$geoFenceGeoJSON")==false]#geodashboard:subscribe() +select id , latitude, longitude,timeStamp, type, speed, heading ,eventId , "ALERTED" as state, "This device is outside $areaName area!!!" as information +insert into dataOut; +from dataIn[geo:within(longitude,latitude,"$geoFenceGeoJSON")!=false] +select id, latitude, longitude,timeStamp, type, speed, heading ,eventId , "NORMAL" as state, "" as information +insert into dataOut; + diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/resources/alerts/Geo-ExecutionPlan-Speed_alert_for_deviceClusters.siddhiql b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/resources/alerts/Geo-ExecutionPlan-Speed_alert_for_deviceClusters.siddhiql new file mode 100644 index 0000000000..62d76659ce --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/resources/alerts/Geo-ExecutionPlan-Speed_alert_for_deviceClusters.siddhiql @@ -0,0 +1,21 @@ +/* Enter a unique ExecutionPlan */ +@Plan:name('Geo-ExecutionPlan-Speed---_alert') + +/* Enter a unique description for ExecutionPlan */ +-- @Plan:description('ExecutionPlan') + +/* define streams/tables and write queries here ... */ + +@Import('org.wso2.geo.StandardSpatialEvents:1.0.0') +define stream dataIn (id string, latitude double, longitude double, timeStamp long, type string, speed float, heading float, eventId string); + +@Export('org.wso2.geo.ProcessedSpatialEvents:1.0.0') +define stream dataOut (id string, latitude double, longitude double, timeStamp long, type string, speed float, heading float, eventId string, state string, information string); + +from dataIn[speed >= $speedAlertValue]#geodashboard:subscribe() +select id , latitude, longitude,timeStamp, type ,speed, heading ,eventId , "ALERTED" as state, "This device movement is not normal!!" as information +insert into dataOut; +from dataIn[speed < $speedAlertValue] +select id , latitude, longitude,timeStamp, type ,speed, heading ,eventId , "NORMAL" as state, "This device movement is normal" as information +insert into dataOut; + diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/resources/alerts/Geo-ExecutionPlan-Traffic_alert_for_deviceClusters.siddhiql b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/resources/alerts/Geo-ExecutionPlan-Traffic_alert_for_deviceClusters.siddhiql new file mode 100644 index 0000000000..f536581038 --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/resources/alerts/Geo-ExecutionPlan-Traffic_alert_for_deviceClusters.siddhiql @@ -0,0 +1,17 @@ +/* Enter a unique ExecutionPlan */ +@Plan:name('$executionPlanName') + +/* Enter a unique description for ExecutionPlan */ +-- @Plan:description('ExecutionPlan') + +/* define streams/tables and write queries here ... */ + +@Import('rawGeoStream:1.0.0') +define stream dataIn (id string, timeStamp long, geometry string, state string, information string); + +@Export('AlertsNotifications:1.0.0') +define stream dataOut (id string, state string, information string, timeStamp long, latitude double, longitude double); + +from dataIn[geo:intersects(geometry, "$geoFenceGeoJSON")==true and geodashboard:needToNotify(id, str:concat(information, state), "sendFirst") == true] +select id, state, str:concat("Traffic alert in $areaName. State: ", state, " ", information) as information, timeStamp, 0.0 as latitude, 0.0 as longitude +insert into dataOut \ No newline at end of file diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/resources/alerts/Geo-ExecutionPlan-Within_alert_for_deviceClusters.siddhiql b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/resources/alerts/Geo-ExecutionPlan-Within_alert_for_deviceClusters.siddhiql new file mode 100644 index 0000000000..30aea4d7fa --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/resources/alerts/Geo-ExecutionPlan-Within_alert_for_deviceClusters.siddhiql @@ -0,0 +1,20 @@ +/* Enter a unique ExecutionPlan */ +@Plan:name('$executionPlanName') + +/* Enter a unique description for ExecutionPlan */ +-- @Plan:description('ExecutionPlan') + +/* define streams/tables and write queries here ... */ + +@Import('org.wso2.geo.StandardSpatialEvents:1.0.0') +define stream dataIn (id string, latitude double, longitude double, timeStamp long, type string ,speed float, heading float, eventId string); + +@Export('org.wso2.geo.ProcessedSpatialEvents:1.0.0') +define stream dataOut (id string, latitude double, longitude double, timeStamp long, type string ,speed float, heading float, eventId string, state string, information string); + +from dataIn[geo:within(longitude,latitude,"$geoFenceGeoJSON")==true]#geodashboard:subscribe() +select id , latitude, longitude,timeStamp, type, speed, heading ,eventId , "ALERTED" as state, "This device is in $areaName restricted area!!!" as information +insert into dataOut; +from dataIn[geo:within(longitude,latitude,"$geoFenceGeoJSON")!=true] +select id , latitude, longitude,timeStamp, type, speed, heading ,eventId , "NORMAL" as state, "" as information +insert into dataOut; \ No newline at end of file diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/pages/cdmf.page.devices/devices.js b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/pages/cdmf.page.devices/devices.js index 407819fef9..c973d07985 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/pages/cdmf.page.devices/devices.js +++ b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/pages/cdmf.page.devices/devices.js @@ -10,8 +10,7 @@ * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUTna innawa kiala - WARRANTIES OR CONDITIONS OF ANY + * "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. From 7c88dfa0b3fb55497120ec0bd0a876bc80b9bb7a Mon Sep 17 00:00:00 2001 From: Arcane94 Date: Sat, 17 Feb 2018 11:23:52 +0530 Subject: [PATCH 10/21] Minor changes in backend APIs --- .../service/api/GeoLocationBasedService.java | 230 +++++++++++++- .../impl/GeoLocationBasedServiceImpl.java | 128 +++++++- .../service/GeoLocationProviderService.java | 18 ++ .../GeoLocationProviderServiceImpl.java | 293 +++++++++++++++++- ...nPlan-Exit_alert_for_GeoClusters.siddhiql} | 0 ...n-Proximity_alert_for_GeoClusters.siddhiql | 140 +++++++++ ...Plan-Speed_alert_for_GeoClusters.siddhiql} | 0 ...-Stationery_alert_for_GeoClusters.siddhiql | 89 ++++++ ...an-Traffic_alert_for_GeoClusters.siddhiql} | 0 ...lan-Within_alert_for_GeoClusters.siddhiql} | 0 10 files changed, 889 insertions(+), 9 deletions(-) rename components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/resources/alerts/{Geo-ExecutionPlan-Exit_alert_for_deviceClusters.siddhiql => Geo-ExecutionPlan-Exit_alert_for_GeoClusters.siddhiql} (100%) create mode 100644 components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/resources/alerts/Geo-ExecutionPlan-Proximity_alert_for_GeoClusters.siddhiql rename components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/resources/alerts/{Geo-ExecutionPlan-Speed_alert_for_deviceClusters.siddhiql => Geo-ExecutionPlan-Speed_alert_for_GeoClusters.siddhiql} (100%) create mode 100644 components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/resources/alerts/Geo-ExecutionPlan-Stationery_alert_for_GeoClusters.siddhiql rename components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/resources/alerts/{Geo-ExecutionPlan-Traffic_alert_for_deviceClusters.siddhiql => Geo-ExecutionPlan-Traffic_alert_for_GeoClusters.siddhiql} (100%) rename components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/resources/alerts/{Geo-ExecutionPlan-Within_alert_for_deviceClusters.siddhiql => Geo-ExecutionPlan-Within_alert_for_GeoClusters.siddhiql} (100%) diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/api/GeoLocationBasedService.java b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/api/GeoLocationBasedService.java index b2088f5ba5..23602baf0c 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/api/GeoLocationBasedService.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/api/GeoLocationBasedService.java @@ -232,7 +232,7 @@ public interface GeoLocationBasedService { /** * Create Geo alerts - */ + */ @POST @Path("alerts/{alertType}/{deviceType}/{deviceId}") @ApiOperation( @@ -297,7 +297,7 @@ public interface GeoLocationBasedService { /** - * Create Geo alerts for geo-dashboard + * Create Geo alerts for geo clusters */ @POST @Path("/alerts/{alertType}") @@ -305,7 +305,7 @@ public interface GeoLocationBasedService { consumes = "application/json", produces = "application/json", httpMethod = "POST", - value = "Create Geo alerts for the device", + value = "Create Geo alerts for geo clusters", notes = "", response = Response.class, tags = "Geo Service Management", @@ -337,7 +337,7 @@ public interface GeoLocationBasedService { message = "Internal Server Error. \n Error on retrieving stats", response = Response.class) }) - Response createGeoAlertsForGeoDashboard( + Response createGeoAlertsForGeoClusters( @ApiParam( name = "alert", value = "The alert object", @@ -414,6 +414,59 @@ public interface GeoLocationBasedService { required = true) @PathParam("alertType") String alertType); + /** + * Update Geo alerts for geo clusters + */ + @PUT + @Path("alerts/{alertType}") + @ApiOperation( + consumes = "application/json", + produces = "application/json", + httpMethod = "GET", + value = "Update Geo alerts for geo clusters", + notes = "", + response = Response.class, + tags = "Geo Service Management", + extensions = { + @Extension(properties = { + @ExtensionProperty(name = Constants.SCOPE, value = "perm:geo-service:alerts-manage") + }) + } + ) + @ApiResponses(value = { + @ApiResponse( + code = 200, + message = "OK.", + response = Response.class, + responseHeaders = { + @ResponseHeader( + name = "Content-Type", + description = "The content type of the body") + }), + @ApiResponse( + code = 400, + message = "Bad Request. \n Invalid Device Identifiers found.", + response = Response.class), + @ApiResponse( + code = 401, + message = "Unauthorized. \n Unauthorized request."), + @ApiResponse( + code = 500, + message = "Internal Server Error. \n Error on retrieving stats", + response = Response.class) + }) + Response updateGeoAlertsForGeoClusters( + @ApiParam( + name = "alert", + value = "The alert object", + required = true) + @Valid Alert alert, + @ApiParam( + name = "alertType", + value = "The alert type, such as Within, Speed, Stationary", + required = true) + @PathParam("alertType") String alertType); + /** * Retrieve Geo alerts */ @@ -478,6 +531,59 @@ public interface GeoLocationBasedService { required = true) @PathParam("alertType") String alertType); + /** + * Retrieve Geo alerts for geo clusters + */ + @GET + @Path("alerts/{alertType}") + @ApiOperation( + consumes = "application/json", + produces = "application/json", + httpMethod = "GET", + value = "Retrieve Geo alerts for geo clusters", + notes = "", + response = Response.class, + tags = "Geo Service Management", + extensions = { + @Extension(properties = { + @ExtensionProperty(name = Constants.SCOPE, value = "perm:geo-service:alerts-manage") + }) + } + ) + @ApiResponses(value = { + @ApiResponse( + code = 200, + message = "OK.", + response = Response.class, + responseHeaders = { + @ResponseHeader( + name = "Content-Type", + description = "The content type of the body"), + @ResponseHeader( + name = "Last-Modified", + description = "Date and time the resource was last modified.\n" + + "Used by caches, or in conditional requests.") + }), + @ApiResponse( + code = 400, + message = "Bad Request. \n Invalid Device Identifiers found.", + response = Response.class), + @ApiResponse( + code = 401, + message = "Unauthorized. \n Unauthorized request."), + @ApiResponse( + code = 500, + message = "Internal Server Error. \n Error on retrieving stats", + response = Response.class) + }) + Response getGeoAlertsForGeoClusters( + @ApiParam( + name = "alertType", + value = "The alert type, such as Within, Speed, Stationary", + required = true) + @PathParam("alertType") String alertType); + + /** * Retrieve Geo alerts history */ @@ -547,6 +653,68 @@ public interface GeoLocationBasedService { required = true) @QueryParam("to") long to); + /** + * Retrieve Geo alerts history for geo clusters + */ + @GET + @Path("alerts/history") + @ApiOperation( + consumes = "application/json", + produces = "application/json", + httpMethod = "GET", + value = "Retrieve Geo alerts history for geo clusters", + notes = "", + response = Response.class, + tags = "Geo Service Management", + extensions = { + @Extension(properties = { + @ExtensionProperty(name = Constants.SCOPE, value = "perm:geo-service:alerts-manage") + }) + } + ) + @ApiResponses(value = { + @ApiResponse( + code = 200, + message = "OK.", + response = Response.class, + responseHeaders = { + @ResponseHeader( + name = "Content-Type", + description = "The content type of the body"), + @ResponseHeader( + name = "Last-Modified", + description = "Date and time the resource was last modified.\n" + + "Used by caches, or in conditional requests.") + }), + @ApiResponse( + code = 400, + message = "Bad Request. \n Invalid Device Identifiers found.", + response = Response.class), + @ApiResponse( + code = 401, + message = "Unauthorized. \n Unauthorized request."), + @ApiResponse( + code = 500, + message = "Internal Server Error. \n Error on retrieving stats", + response = Response.class) + }) + Response getGeoAlertsHistoryForGeoClusters( + @ApiParam( + name = "from", + value = "Get stats from what time", + required = true) + @QueryParam("from") long from, + @ApiParam( + name = "to", + value = "Get stats up to what time", + required = true) + @QueryParam("to") long to); + + + /** + * Remove geo alerts + */ + @DELETE @Path("alerts/{alertType}/{deviceType}/{deviceId}") @ApiOperation( @@ -607,5 +775,59 @@ public interface GeoLocationBasedService { " here.", required = true) @QueryParam("queryName") String queryName); + + /** + * Remove geo alerts for geo clusters + */ + + @DELETE + @Path("alerts/{alertType}") + @ApiOperation( + consumes = "application/json", + produces = "application/json", + httpMethod = "DELETE", + value = "Deletes Geo alerts for the device", + notes = "", + response = Response.class, + tags = "Geo Service Management", + extensions = { + @Extension(properties = { + @ExtensionProperty(name = Constants.SCOPE, value = "perm:geo-service:alerts-manage") + }) + } + ) + @ApiResponses(value = { + @ApiResponse( + code = 200, + message = "OK.", + response = Response.class, + responseHeaders = { + @ResponseHeader( + name = "Content-Type", + description = "The content type of the body") + }), + @ApiResponse( + code = 400, + message = "Bad Request. \n Invalid Device Identifiers found.", + response = Response.class), + @ApiResponse( + code = 401, + message = "Unauthorized. \n Unauthorized request."), + @ApiResponse( + code = 500, + message = "Internal Server Error. \n Error on retrieving stats", + response = Response.class) + }) + Response removeGeoAlertsForGeoClusters( + @ApiParam( + name = "alertType", + value = "The alert type, such as Within, Speed, Stationary", + required = true) + @PathParam("alertType") String alertType, + @ApiParam( + name = "queryName", + value = "The query name.", + required = true) + @QueryParam("queryName") String queryName); } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/GeoLocationBasedServiceImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/GeoLocationBasedServiceImpl.java index 7890b463fc..c5c96263b9 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/GeoLocationBasedServiceImpl.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/GeoLocationBasedServiceImpl.java @@ -190,7 +190,7 @@ public class GeoLocationBasedServiceImpl implements GeoLocationBasedService { @POST @Consumes("application/json") @Produces("application/json") - public Response createGeoAlertsForGeoDashboard(Alert alert, @PathParam("alertType") String alertType) { + public Response createGeoAlertsForGeoClusters(Alert alert, @PathParam("alertType") String alertType) { try { // this is the user who initiates the request String authorizedUser = MultitenantUtils.getTenantAwareUsername( @@ -245,6 +245,27 @@ public class GeoLocationBasedServiceImpl implements GeoLocationBasedService { } } + @Path("alerts/{alertType}") + @PUT + @Consumes("application/json") + @Produces("application/json") + public Response updateGeoAlertsForGeoClusters(Alert alert, @PathParam("alertType") String alertType) { + try { + // this is the user who initiates the request + String authorizedUser = MultitenantUtils.getTenantAwareUsername( + CarbonContext.getThreadLocalCarbonContext().getUsername() + ); + + GeoLocationProviderService geoService = DeviceMgtAPIUtils.getGeoService(); + geoService.updateGeoAlert(alert, alertType); + return Response.ok().build(); + } catch (GeoLocationBasedServiceException e) { + String error = "Error occurred while updating the geo alert for geo clusters"; + log.error(error, e); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(error).build(); + } + } + @Path("alerts/{alertType}/{deviceType}/{deviceId}") @DELETE @Consumes("application/json") @@ -279,6 +300,27 @@ public class GeoLocationBasedServiceImpl implements GeoLocationBasedService { } } + @Path("alerts/{alertType}") + @DELETE + @Consumes("application/json") + @Produces("application/json") + public Response removeGeoAlertsForGeoClusters(@PathParam("alertType") String alertType, @QueryParam("queryName") String queryName) { + try { + // this is the user who initiates the request + String authorizedUser = MultitenantUtils.getTenantAwareUsername( + CarbonContext.getThreadLocalCarbonContext().getUsername() + ); + + GeoLocationProviderService geoService = DeviceMgtAPIUtils.getGeoService(); + geoService.removeGeoAlert(alertType, queryName); + return Response.ok().build(); + } catch (GeoLocationBasedServiceException e) { + String error = "Error occurred while removing the geo alert for geo clusters"; + log.error(error, e); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(error).build(); + } + } + @Path("alerts/{alertType}/{deviceType}/{deviceId}") @GET @Consumes("application/json") @@ -331,6 +373,47 @@ public class GeoLocationBasedServiceImpl implements GeoLocationBasedService { } } + @Path("alerts/{alertType}") + @GET + @Consumes("application/json") + @Produces("application/json") + public Response getGeoAlertsForGeoClusters(@PathParam("alertType") String alertType) { + try { + + // this is the user who initiates the request + String authorizedUser = MultitenantUtils.getTenantAwareUsername( + CarbonContext.getThreadLocalCarbonContext().getUsername() + ); + + GeoLocationProviderService geoService = DeviceMgtAPIUtils.getGeoService(); + + if (GeoServices.ALERT_TYPE_WITHIN.equals(alertType)) { + List alerts = geoService.getWithinAlerts(); + return Response.ok().entity(alerts).build(); + } else if (GeoServices.ALERT_TYPE_EXIT.equals(alertType)) { + List alerts = geoService.getExitAlerts(); + return Response.ok().entity(alerts).build(); + } else if (GeoServices.ALERT_TYPE_SPEED.equals(alertType)) { + String result = geoService.getSpeedAlerts(); + return Response.ok().entity(result).build(); + } else if (GeoServices.ALERT_TYPE_PROXIMITY.equals(alertType)) { + String result = geoService.getProximityAlerts(); + return Response.ok().entity(result).build(); + } else if (GeoServices.ALERT_TYPE_STATIONARY.equals(alertType)) { + List alerts = geoService.getStationaryAlerts(); + return Response.ok().entity(alerts).build(); + } else if (GeoServices.ALERT_TYPE_TRAFFIC.equals(alertType)) { + List alerts = geoService.getTrafficAlerts(); + return Response.ok().entity(alerts).build(); + } + return null; + } catch (GeoLocationBasedServiceException e) { + String error = "Error occurred while getting the geo alerts for " + alertType + "alert"; + log.error(error, e); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(error).build(); + } + } + @Path("alerts/history/{deviceType}/{deviceId}") @GET @Consumes("application/json") @@ -381,6 +464,49 @@ public class GeoLocationBasedServiceImpl implements GeoLocationBasedService { } } + @Path("alerts/history") + @GET + @Consumes("application/json") + @Produces("application/json") + public Response getGeoAlertsHistoryForGeoClusters(@QueryParam("from") long from, @QueryParam("to") long to) { + String tableName = "IOT_PER_DEVICE_STREAM_GEO_ALERTNOTIFICATIONS"; + String fromDate = String.valueOf(from); + String toDate = String.valueOf(to); + String query = ""; + if (from != 0 || to != 0) { + query = "timeStamp : [" + fromDate + " TO " + toDate + "]"; + } + try { + List sortByFields = new ArrayList<>(); + SortByField sortByField = new SortByField("timeStamp", SortType.ASC); + sortByFields.add(sortByField); + + // this is the user who initiates the request + String authorizedUser = MultitenantUtils.getTenantAwareUsername( + CarbonContext.getThreadLocalCarbonContext().getUsername()); + + try { + String tenantDomain = MultitenantUtils.getTenantDomain(authorizedUser); + int tenantId = DeviceMgtAPIUtils.getRealmService().getTenantManager().getTenantId(tenantDomain); + AnalyticsDataAPI analyticsDataAPI = DeviceMgtAPIUtils.getAnalyticsDataAPI(); + List searchResults = analyticsDataAPI.search(tenantId, tableName, query, + 0, + 100, + sortByFields); + List events = getEventBeans(analyticsDataAPI, tenantId, tableName, new ArrayList(), + searchResults); + return Response.ok().entity(events).build(); + } catch (AnalyticsException | UserStoreException e) { + log.error("Failed to perform search on table: " + tableName + " : " + e.getMessage(), e); + throw DeviceMgtUtil.buildBadRequestException( + Constants.ErrorMessages.STATUS_BAD_REQUEST_MESSAGE_DEFAULT); + } + } catch (Exception e) { + log.error(e.getMessage()); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode()).build(); + } + } + private List getEventBeans(AnalyticsDataAPI analyticsDataAPI, int tenantId, String tableName, List columns, List searchResults) throws AnalyticsException { diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/geo/service/GeoLocationProviderService.java b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/geo/service/GeoLocationProviderService.java index 924f385dd3..47daac0492 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/geo/service/GeoLocationProviderService.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/geo/service/GeoLocationProviderService.java @@ -30,8 +30,12 @@ public interface GeoLocationProviderService { List getWithinAlerts(DeviceIdentifier identifier) throws GeoLocationBasedServiceException; + List getWithinAlerts() throws GeoLocationBasedServiceException; + List getExitAlerts(DeviceIdentifier identifier) throws GeoLocationBasedServiceException; + List getExitAlerts() throws GeoLocationBasedServiceException; + boolean createGeoAlert(Alert alert, DeviceIdentifier identifier, String alertType) throws GeoLocationBasedServiceException, AlertAlreadyExistException; @@ -41,14 +45,28 @@ public interface GeoLocationProviderService { boolean updateGeoAlert(Alert alert, DeviceIdentifier identifier, String alertType) throws GeoLocationBasedServiceException, AlertAlreadyExistException; + boolean updateGeoAlert(Alert alert, String alertType) + throws GeoLocationBasedServiceException; + boolean removeGeoAlert(String alertType, DeviceIdentifier identifier, String queryName) throws GeoLocationBasedServiceException; + boolean removeGeoAlert(String alertType, String queryName) + throws GeoLocationBasedServiceException; + String getSpeedAlerts(DeviceIdentifier identifier) throws GeoLocationBasedServiceException; + String getSpeedAlerts() throws GeoLocationBasedServiceException; + String getProximityAlerts(DeviceIdentifier identifier) throws GeoLocationBasedServiceException; + String getProximityAlerts() throws GeoLocationBasedServiceException; + List getStationaryAlerts(DeviceIdentifier identifier) throws GeoLocationBasedServiceException; + List getStationaryAlerts() throws GeoLocationBasedServiceException; + List getTrafficAlerts(DeviceIdentifier identifier) throws GeoLocationBasedServiceException; + + List getTrafficAlerts() throws GeoLocationBasedServiceException; } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/geo/service/GeoLocationProviderServiceImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/geo/service/GeoLocationProviderServiceImpl.java index 39cd9e71dd..7174bea0ae 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/geo/service/GeoLocationProviderServiceImpl.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/geo/service/GeoLocationProviderServiceImpl.java @@ -159,6 +159,53 @@ public class GeoLocationProviderServiceImpl implements GeoLocationProviderServic } } + @Override + public List getWithinAlerts() throws GeoLocationBasedServiceException { + + Registry registry = getGovernanceRegistry(); + String registryPath = GeoServices.REGISTRY_PATH_FOR_ALERTS + + GeoServices.ALERT_TYPE_WITHIN; + Resource resource; + try { + resource = registry.get(registryPath); + } catch (RegistryException e) { + log.error("Error while reading the registry path: " + registryPath); + return null; + } + + try { + List fences = new ArrayList<>(); + if (resource != null) { + Object contentObj = resource.getContent(); + if (contentObj instanceof String[]) { + String[] content = (String[]) contentObj; + for (String res : content) { + Resource childRes = registry.get(res); + Properties props = childRes.getProperties(); + + GeoFence geoFence = new GeoFence(); + + InputStream inputStream = childRes.getContentStream(); + StringWriter writer = new StringWriter(); + IOUtils.copy(inputStream, writer, "UTF-8"); + geoFence.setGeoJson(writer.toString()); + + List queryNameObj = (List) props.get(GeoServices.QUERY_NAME); + geoFence.setQueryName(queryNameObj != null ? queryNameObj.get(0).toString() : null); + List areaNameObj = (List) props.get(GeoServices.AREA_NAME); + geoFence.setAreaName(areaNameObj != null ? areaNameObj.get(0).toString() : null); + geoFence.setCreatedTime(childRes.getCreatedTime().getTime()); + fences.add(geoFence); + } + } + } + return fences; + } catch (RegistryException | IOException e) { + throw new GeoLocationBasedServiceException( + "Error occurred while getting the geo alerts" , e); + } + } + @Override public List getExitAlerts(DeviceIdentifier identifier) throws GeoLocationBasedServiceException { @@ -207,6 +254,53 @@ public class GeoLocationProviderServiceImpl implements GeoLocationProviderServic } } + @Override + public List getExitAlerts() throws GeoLocationBasedServiceException { + + Registry registry = getGovernanceRegistry(); + String registryPath = GeoServices.REGISTRY_PATH_FOR_ALERTS + + GeoServices.ALERT_TYPE_EXIT; + Resource resource; + try { + resource = registry.get(registryPath); + } catch (RegistryException e) { + log.error("Error while reading the registry path: " + registryPath); + return null; + } + + try { + List fences = new ArrayList<>(); + if (resource != null) { + Object contentObj = resource.getContent(); + if (contentObj instanceof String[]) { + String[] content = (String[]) contentObj; + for (String res : content) { + Resource childRes = registry.get(res); + Properties props = childRes.getProperties(); + + GeoFence geoFence = new GeoFence(); + + InputStream inputStream = childRes.getContentStream(); + StringWriter writer = new StringWriter(); + IOUtils.copy(inputStream, writer, "UTF-8"); + geoFence.setGeoJson(writer.toString()); + + List queryNameObj = (List) props.get(GeoServices.QUERY_NAME); + geoFence.setQueryName(queryNameObj != null ? queryNameObj.get(0).toString() : null); + List areaNameObj = (List) props.get(GeoServices.AREA_NAME); + geoFence.setAreaName(areaNameObj != null ? areaNameObj.get(0).toString() : null); + geoFence.setCreatedTime(childRes.getCreatedTime().getTime()); + fences.add(geoFence); + } + } + } + return fences; + } catch (RegistryException | IOException e) { + throw new GeoLocationBasedServiceException( + "Error occurred while getting the geo alerts", e); + } + } + @Override public boolean createGeoAlert(Alert alert, DeviceIdentifier identifier, String alertType) throws GeoLocationBasedServiceException, AlertAlreadyExistException { @@ -225,6 +319,12 @@ public class GeoLocationProviderServiceImpl implements GeoLocationProviderServic return saveGeoAlert(alert, identifier, alertType, true); } + @Override + public boolean updateGeoAlert(Alert alert, String alertType) + throws GeoLocationBasedServiceException { + return saveGeoAlert(alert, alertType, true); + } + public boolean saveGeoAlert(Alert alert, String alertType, boolean isUpdate) throws GeoLocationBasedServiceException { @@ -277,11 +377,16 @@ public class GeoLocationProviderServiceImpl implements GeoLocationProviderServic String action = (isUpdate ? "updating" : "creating"); try { eventprocessorStub = getEventProcessorAdminServiceStub(); - String parsedTemplate = parseTemplateForDeviceClusters(alertType, parseMap); + String parsedTemplate = parseTemplateForGeoClusters(alertType, parseMap); String validationResponse = eventprocessorStub.validateExecutionPlan(parsedTemplate); if (validationResponse.equals("success")) { if (isUpdate) { String executionPlanName = getExecutionPlanName(alertType, alert.getQueryName()); + try { + String existingPlanName = eventprocessorStub.getActiveExecutionPlan(executionPlanName); + } catch (Exception e) { + eventprocessorStub.deployExecutionPlan(parsedTemplate); + } eventprocessorStub.editActiveExecutionPlan(parsedTemplate, executionPlanName); } else { eventprocessorStub.deployExecutionPlan(parsedTemplate); @@ -498,7 +603,10 @@ public class GeoLocationProviderServiceImpl implements GeoLocationProviderServic if ("Traffic".equals(alertType)) { return "Geo-ExecutionPlan-Traffic_" + queryName + "_alert"; } else { - return "Geo-ExecutionPlan-" + alertType + "_" + queryName + "---_" + "_alert"; + if (alertType.equals("Speed")) { + return "Geo-ExecutionPlan-" + alertType + "---" + "_alert"; + } + return "Geo-ExecutionPlan-" + alertType + "_" + queryName + "---" + "_alert"; } } @@ -530,6 +638,32 @@ public class GeoLocationProviderServiceImpl implements GeoLocationProviderServic } } + @Override + public boolean removeGeoAlert(String alertType, String queryName) + throws GeoLocationBasedServiceException { + removeFromRegistry(alertType, queryName); + String executionPlanName = getExecutionPlanName(alertType, queryName); + EventProcessorAdminServiceStub eventprocessorStub = null; + try { + eventprocessorStub = getEventProcessorAdminServiceStub(); + eventprocessorStub.undeployActiveExecutionPlan(executionPlanName); + return true; + } catch (IOException e) { + throw new GeoLocationBasedServiceException( + "Event processor admin service stub invocation failed while removing geo alert '" + + alertType + + "': " + executionPlanName, e + ); + } catch (JWTClientException e) { + throw new GeoLocationBasedServiceException( + "JWT token creation failed while removing geo alert '" + alertType + "': " + + executionPlanName, e + ); + } finally { + cleanup(eventprocessorStub); + } + } + private void removeFromRegistry(String alertType, DeviceIdentifier identifier, String queryName) throws GeoLocationBasedServiceException { String path = "unknown"; @@ -543,6 +677,18 @@ public class GeoLocationProviderServiceImpl implements GeoLocationProviderServic } } + private void removeFromRegistry(String alertType, String queryName) + throws GeoLocationBasedServiceException { + String path = "unknown"; + try { + path = getRegistryPath(alertType, queryName); + getGovernanceRegistry().delete(path); + } catch (RegistryException e) { + throw new GeoLocationBasedServiceException( + "Error occurred while removing " + alertType + " alert " + " from the path: " + path); + } + } + protected EventProcessorAdminServiceStub getEventProcessorAdminServiceStub() throws JWTClientException { //send alert to event-processing String eventProcessorAdminServiceWSUrl = Utils.replaceSystemProperty(GeoServices.DAS_URL) + @@ -607,6 +753,24 @@ public class GeoLocationProviderServiceImpl implements GeoLocationProviderServic } } + @Override + public String getSpeedAlerts() throws GeoLocationBasedServiceException { + try { + Registry registry = getGovernanceRegistry(); + Resource resource = registry.get(GeoServices.REGISTRY_PATH_FOR_ALERTS + + GeoServices.ALERT_TYPE_SPEED); + if (resource == null) { + return "{'content': false}"; + } + InputStream inputStream = resource.getContentStream(); + StringWriter writer = new StringWriter(); + IOUtils.copy(inputStream, writer, "UTF-8"); + return "{'speedLimit':" + writer.toString() + "}"; + } catch (RegistryException | IOException e) { + return "{'content': false}"; + } + } + @Override public String getProximityAlerts(DeviceIdentifier identifier) throws GeoLocationBasedServiceException { try { @@ -631,6 +795,30 @@ public class GeoLocationProviderServiceImpl implements GeoLocationProviderServic } } + @Override + public String getProximityAlerts() throws GeoLocationBasedServiceException { + try { + Registry registry = getGovernanceRegistry(); + Resource resource = registry.get(GeoServices.REGISTRY_PATH_FOR_ALERTS + + GeoServices.ALERT_TYPE_PROXIMITY); + if (resource != null) { + Properties props = resource.getProperties(); + + List proxDisObj = (List) props.get(GeoServices.PROXIMITY_DISTANCE); + List proxTimeObj = (List) props.get(GeoServices.PROXIMITY_TIME); + + return String.format("{proximityDistance:\"%s\", proximityTime:\"%s\"}", + proxDisObj != null ? proxDisObj.get(0).toString() : "", + proxTimeObj != null ? proxTimeObj.get(0).toString() : ""); + } else { + return "{'content': false}"; + } + } catch (RegistryException e) { + return "{'content': false}"; + } + } + + @Override public List getStationaryAlerts(DeviceIdentifier identifier) throws GeoLocationBasedServiceException { @@ -683,6 +871,57 @@ public class GeoLocationProviderServiceImpl implements GeoLocationProviderServic } } + @Override + public List getStationaryAlerts() throws GeoLocationBasedServiceException { + + Registry registry = getGovernanceRegistry(); + String registryPath = GeoServices.REGISTRY_PATH_FOR_ALERTS + + GeoServices.ALERT_TYPE_STATIONARY; + Resource resource; + try { + resource = registry.get(registryPath); + } catch (RegistryException e) { + log.error("Error while reading the registry path: " + registryPath); + return null; + } + + try { + List fences = new ArrayList<>(); + if (resource != null) { + Object contentObj = resource.getContent(); + + if (contentObj instanceof String[]) { + String[] content = (String[]) contentObj; + for (String res : content) { + Resource childRes = registry.get(res); + Properties props = childRes.getProperties(); + GeoFence geoFence = new GeoFence(); + + InputStream inputStream = childRes.getContentStream(); + StringWriter writer = new StringWriter(); + IOUtils.copy(inputStream, writer, "UTF-8"); + geoFence.setGeoJson(writer.toString()); + + List queryNameObj = (List) props.get(GeoServices.QUERY_NAME); + geoFence.setQueryName(queryNameObj != null ? queryNameObj.get(0).toString() : null); + List areaNameObj = (List) props.get(GeoServices.AREA_NAME); + geoFence.setAreaName(areaNameObj != null ? areaNameObj.get(0).toString() : null); + List sTimeObj = (List) props.get(GeoServices.STATIONARY_TIME); + geoFence.setStationaryTime(sTimeObj != null ? sTimeObj.get(0).toString() : null); + List fluctRadiusObj = (List) props.get(GeoServices.FLUCTUATION_RADIUS); + geoFence.setFluctuationRadius(fluctRadiusObj != null ? fluctRadiusObj.get(0).toString() : null); + geoFence.setCreatedTime(childRes.getCreatedTime().getTime()); + fences.add(geoFence); + } + } + } + return fences; + } catch (RegistryException | IOException e) { + throw new GeoLocationBasedServiceException( + "Error occurred while getting the geo alerts", e); + } + } + @Override public List getTrafficAlerts(DeviceIdentifier identifier) throws GeoLocationBasedServiceException { Registry registry = getGovernanceRegistry(); @@ -730,6 +969,52 @@ public class GeoLocationProviderServiceImpl implements GeoLocationProviderServic } } + @Override + public List getTrafficAlerts() throws GeoLocationBasedServiceException { + Registry registry = getGovernanceRegistry(); + String registryPath = GeoServices.REGISTRY_PATH_FOR_ALERTS + + GeoServices.ALERT_TYPE_STATIONARY; + Resource resource; + try { + resource = registry.get(registryPath); + } catch (RegistryException e) { + log.error("Error while reading the registry path: " + registryPath); + return null; + } + + try { + List fences = new ArrayList<>(); + if (resource != null) { + Object contentObj = resource.getContent(); + if (contentObj instanceof String[]) { + String[] content = (String[]) contentObj; + for (String res : content) { + Resource childRes = registry.get(res); + Properties props = childRes.getProperties(); + + GeoFence geoFence = new GeoFence(); + + InputStream inputStream = childRes.getContentStream(); + StringWriter writer = new StringWriter(); + IOUtils.copy(inputStream, writer, "UTF-8"); + geoFence.setGeoJson(writer.toString()); + + List queryNameObj = (List) props.get(GeoServices.QUERY_NAME); + geoFence.setQueryName(queryNameObj != null ? queryNameObj.get(0).toString() : null); + List sNameObj = (List) props.get(GeoServices.STATIONARY_NAME); + geoFence.setAreaName(sNameObj != null ? sNameObj.get(0).toString() : null); + geoFence.setCreatedTime(childRes.getCreatedTime().getTime()); + fences.add(geoFence); + } + } + } + return fences; + } catch (RegistryException | IOException e) { + throw new GeoLocationBasedServiceException( + "Error occurred while getting the geo alerts", e); + } + } + private Registry getGovernanceRegistry() throws GeoLocationBasedServiceException { try { int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(); @@ -765,9 +1050,9 @@ public class GeoLocationProviderServiceImpl implements GeoLocationProviderServic } } - private String parseTemplateForDeviceClusters(String alertType, Map parseMap) throws + private String parseTemplateForGeoClusters(String alertType, Map parseMap) throws GeoLocationBasedServiceException { - String templatePath = "alerts/Geo-ExecutionPlan-" + alertType + "_alert_for_deviceClusters.siddhiql"; + String templatePath = "alerts/Geo-ExecutionPlan-" + alertType + "_alert_for_GeoClusters.siddhiql"; InputStream resource = getClass().getClassLoader().getResourceAsStream(templatePath); if (resource == null) { throw new GeoLocationBasedServiceException("Could not find template in path : " + templatePath); diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/resources/alerts/Geo-ExecutionPlan-Exit_alert_for_deviceClusters.siddhiql b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/resources/alerts/Geo-ExecutionPlan-Exit_alert_for_GeoClusters.siddhiql similarity index 100% rename from components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/resources/alerts/Geo-ExecutionPlan-Exit_alert_for_deviceClusters.siddhiql rename to components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/resources/alerts/Geo-ExecutionPlan-Exit_alert_for_GeoClusters.siddhiql diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/resources/alerts/Geo-ExecutionPlan-Proximity_alert_for_GeoClusters.siddhiql b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/resources/alerts/Geo-ExecutionPlan-Proximity_alert_for_GeoClusters.siddhiql new file mode 100644 index 0000000000..fb64720391 --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/resources/alerts/Geo-ExecutionPlan-Proximity_alert_for_GeoClusters.siddhiql @@ -0,0 +1,140 @@ +/* Enter a unique ExecutionPlan */ +@Plan:name('Geo-ExecutionPlan-Proximity_alert') + +/* Enter a unique description for ExecutionPlan */ +-- @Plan:description('ExecutionPlan') + +/* define streams/tables and write queries here ... */ + +@Import('org.wso2.geo.StandardSpatialEvents:1.0.0') +define stream dataIn (id string, latitude double, longitude double, timeStamp long, type string, speed float, heading float, eventId string ); + +@Export('org.wso2.geo.ProcessedSpatialEvents:1.0.0') +define stream dataOut ( id string, latitude double, longitude double, timeStamp long, type string, speed float, heading float, eventId string, state string, information string ); + +@IndexBy('id') +define table ProximityTable(id string, timeStamp long); + +@IndexBy('id') +define table AlertsTable(id string , proximityWith string, eventId string); + +from dataIn#geodashboard:subscribe() +select id, latitude, longitude, timeStamp, type, speed, heading, eventId +insert into initialStream; + +from initialStream[type == 'STOP'] +select id , latitude, longitude,timeStamp, type, speed, heading ,eventId , "" as proximityInfo ,"false" as isProximity +insert into dataOutStream; + +from initialStream[type != 'STOP'] +select * +insert into objectInitialStream; + +from objectInitialStream#geo:proximity(id,longitude,latitude, $proximityDistance) +select id, latitude, longitude, timeStamp, type, speed, heading, eventId,inCloseProximity,proximityWith +insert into proxymityStream; + +from proxymityStream[AlertsTable.id == proxymityStream.id in AlertsTable] +select id, latitude, longitude, timeStamp, type, speed, heading, eventId,inCloseProximity,proximityWith,true as inAlertTable +insert into innerStreamOne; + +from proxymityStream[not(AlertsTable.id == proxymityStream.id in AlertsTable)] +select id, latitude, longitude, timeStamp, type, speed, heading, eventId,inCloseProximity,proximityWith,false as inAlertTable +insert into innerStreamOne; + +from proxymityStream[AlertsTable.id == proxymityStream.proximityWith in AlertsTable] +select id, latitude, longitude, timeStamp, type, speed, heading, eventId,inCloseProximity,proximityWith,true as inAlertTable +insert into innerStreamSeven; + +from proxymityStream[not(AlertsTable.id == proxymityStream.proximityWith in AlertsTable)] +select id, latitude, longitude, timeStamp, type, speed, heading, eventId,inCloseProximity,proximityWith,false as inAlertTable +insert into innerStreamSeven; + +from innerStreamOne[inCloseProximity == true AND not(inAlertTable)] +select id,str:concat(",",proximityWith) as proximityWith , eventId +insert into AlertsTable; + +from innerStreamSeven[inCloseProximity == true AND not(inAlertTable)] +select proximityWith as id,str:concat(",",id) as proximityWith , eventId +insert into AlertsTable; + +from innerStreamOne[innerStreamOne.inCloseProximity == true AND inAlertTable]#window.length(0) join AlertsTable +on innerStreamOne.id == AlertsTable.id +select innerStreamOne.id as id, str:concat(",", innerStreamOne.proximityWith, AlertsTable.proximityWith) as proximityWith, innerStreamOne.eventId as eventId +insert into updateStream; + +from innerStreamSeven[innerStreamSeven.inCloseProximity == true AND inAlertTable]#window.length(0) join AlertsTable +on innerStreamSeven.proximityWith == AlertsTable.id +select innerStreamSeven.proximityWith as id, str:concat(",", innerStreamSeven.id, AlertsTable.proximityWith) as proximityWith, innerStreamSeven.eventId as eventId +insert into updateStream; + +from innerStreamOne[innerStreamOne.inCloseProximity == false AND inAlertTable]#window.length(0) join AlertsTable +on innerStreamOne.id == AlertsTable.id +select innerStreamOne.id as id, str:replaceAll(AlertsTable.proximityWith, str:concat(",", innerStreamOne.proximityWith), "") as proximityWith, innerStreamOne.eventId as eventId +insert into updateStream; + +from innerStreamSeven[innerStreamSeven.inCloseProximity == false AND inAlertTable]#window.length(0) join AlertsTable +on innerStreamSeven.proximityWith == AlertsTable.id +select innerStreamSeven.proximityWith as id, str:replaceAll(AlertsTable.proximityWith, str:concat(",", innerStreamSeven.id), "") as proximityWith, innerStreamSeven.eventId as eventId +insert into updateStream; + +from updateStream +select * +update AlertsTable + on id== AlertsTable.id; + +from updateStream[proximityWith == ""] +delete AlertsTable + on id== AlertsTable.id; + +from objectInitialStream[AlertsTable.id == objectInitialStream.id in AlertsTable] +select id, latitude, longitude, timeStamp, type, speed, heading, eventId, true as inAlertTable +insert into publishStream; + +from objectInitialStream[not(AlertsTable.id == objectInitialStream.id in AlertsTable)] +select id, latitude, longitude, timeStamp, type, speed, heading, eventId, false as inAlertTable +insert into publishStream; + +from publishStream[inAlertTable == true]#window.length(0) join AlertsTable +on publishStream.id== AlertsTable.id +select publishStream.id as id, publishStream.latitude as latitude, publishStream.longitude as longitude, publishStream.timeStamp as timeStamp, publishStream.type as type, publishStream.speed as speed, publishStream.heading as heading, publishStream.eventId as eventId, AlertsTable.proximityWith as proximityInfo +insert into innerStreamTwo; + +from publishStream[inAlertTable == false] +delete ProximityTable on ProximityTable.id==id; + +from publishStream[inAlertTable == false] +select id , latitude, longitude,timeStamp, type, speed, heading ,eventId , "" as proximityInfo ,"false" as isProximity +insert into dataOutStream; + +from innerStreamTwo[ProximityTable.id == innerStreamTwo.id in ProximityTable] +insert into innerStreamThree; + +from innerStreamThree#window.length(0) join ProximityTable +on innerStreamThree.id == ProximityTable.id +select innerStreamThree.id , innerStreamThree.latitude, innerStreamThree.longitude,innerStreamThree.timeStamp, innerStreamThree.type, innerStreamThree.speed, innerStreamThree.heading ,innerStreamThree.eventId, ProximityTable.timeStamp as storedTime, innerStreamThree.proximityInfo as proximityInfo +insert into innerStreamFour; + +from innerStreamFour[(timeStamp - storedTime) >= $proximityTime] +select id , latitude, longitude,timeStamp, type, speed, heading ,eventId ,proximityInfo,"true" as isProximity +insert into dataOutStream; + +from innerStreamFour[(timeStamp - storedTime) < $proximityTime] +select id , latitude, longitude,timeStamp, type, speed, heading ,eventId , proximityInfo ,"false" as isProximity +insert into dataOutStream; + +from innerStreamTwo[not(ProximityTable.id == innerStreamTwo.id in ProximityTable)] +select innerStreamTwo.id, innerStreamTwo.timeStamp +insert into ProximityTable; + +from innerStreamTwo[not(ProximityTable.id == innerStreamTwo.id in ProximityTable)] +select id , latitude, longitude,timeStamp, type, speed, heading ,eventId , "" as proximityInfo ,"false" as isProximity +insert into dataOutStream; + +from dataOutStream[isProximity == 'true'] +select id, latitude, longitude, timeStamp, type, speed, heading, eventId,"WARNING" as state,str:concat("Proximity with "," ",proximityInfo) as information +insert into dataOut; + +from dataOutStream[isProximity == 'false'] +select id , latitude, longitude,timeStamp, type, speed, heading ,eventId ,"NORMAL" as state,"" as information +insert into dataOut; \ No newline at end of file diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/resources/alerts/Geo-ExecutionPlan-Speed_alert_for_deviceClusters.siddhiql b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/resources/alerts/Geo-ExecutionPlan-Speed_alert_for_GeoClusters.siddhiql similarity index 100% rename from components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/resources/alerts/Geo-ExecutionPlan-Speed_alert_for_deviceClusters.siddhiql rename to components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/resources/alerts/Geo-ExecutionPlan-Speed_alert_for_GeoClusters.siddhiql diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/resources/alerts/Geo-ExecutionPlan-Stationery_alert_for_GeoClusters.siddhiql b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/resources/alerts/Geo-ExecutionPlan-Stationery_alert_for_GeoClusters.siddhiql new file mode 100644 index 0000000000..46bfbfe2e3 --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/resources/alerts/Geo-ExecutionPlan-Stationery_alert_for_GeoClusters.siddhiql @@ -0,0 +1,89 @@ +/* Enter a unique ExecutionPlan */ +@Plan:name('$executionPlanName') + +/* Enter a unique description for ExecutionPlan */ +-- @Plan:description('ExecutionPlan') + +/* define streams/tables and write queries here ... */ + +@Import('org.wso2.geo.StandardSpatialEvents:1.0.0') +define stream dataIn (id string, latitude double, longitude double, timeStamp long, type string ,speed float, heading float, eventId string); + + +@Export('org.wso2.geo.ProcessedSpatialEvents:1.0.0') +define stream dataOut (id string, latitude double, longitude double, timeStamp long, type string ,speed float, heading float, eventId string, state string, information string); + +@IndexBy('id') +define table StationeryTable(id string, timeStamp long); + +@IndexBy('id') +define table AlertsTable(id string, stationary bool); + +from dataIn#geodashboard:subscribe() +select id, latitude, longitude, timeStamp, type, speed, heading, eventId,geo:within(longitude,latitude,"$geoFenceGeoJSON") as isWithin +insert into innerStreamOne; + +from innerStreamOne[isWithin == false] +delete StationeryTable on StationeryTable.id==id; + +from innerStreamOne[isWithin == false] +select id , latitude, longitude,timeStamp, type, speed, heading ,eventId , "false" as isStationary +insert into dataOutStream; + +from innerStreamOne[isWithin == true]#geo:stationary(id,longitude,latitude, $fluctuationRadius) +select id, latitude, longitude, timeStamp, type, speed, heading, eventId,stationary +insert into innerStreamTwo; + +from innerStreamTwo[innerStreamTwo.stationary == true] +select innerStreamTwo.id, innerStreamTwo.stationary +insert into AlertsTable; + +from innerStreamTwo[innerStreamTwo.stationary == false] +delete AlertsTable on AlertsTable.id==id; + +from innerStreamTwo[innerStreamTwo.stationary == false] +delete StationeryTable on StationeryTable.id==id; + +from innerStreamOne[isWithin == true AND not(AlertsTable.id == innerStreamOne.id in AlertsTable)] +select id , latitude, longitude,timeStamp, type, speed, heading ,eventId , "false" as isStationary +insert into dataOutStream; + +from innerStreamOne[isWithin == true AND AlertsTable.id == innerStreamOne.id in AlertsTable] +insert into innerStreamThree; + +from innerStreamThree#window.length(0) join AlertsTable +on innerStreamThree.id == AlertsTable.id +select innerStreamThree.id , innerStreamThree.latitude, innerStreamThree.longitude,innerStreamThree.timeStamp, innerStreamThree.type, innerStreamThree.speed, innerStreamThree.heading ,innerStreamThree.eventId +insert into innerStreamFour; + +from innerStreamFour[not(StationeryTable.id == innerStreamFour.id in StationeryTable)] +select innerStreamFour.id, innerStreamFour.timeStamp +insert into StationeryTable; + +from innerStreamOne[isWithin == true AND not(StationeryTable.id == innerStreamOne.id in StationeryTable)] +select id , latitude, longitude,timeStamp, type, speed, heading ,eventId , "false" as isStationary +insert into dataOutStream; + +from innerStreamOne[isWithin == true AND StationeryTable.id == innerStreamOne.id in StationeryTable] +insert into innerStreamFive; + +from innerStreamFive#window.length(0) join StationeryTable +on innerStreamFive.id == StationeryTable.id +select innerStreamFive.id , innerStreamFive.latitude, innerStreamFive.longitude,innerStreamFive.timeStamp, innerStreamFive.type, innerStreamFive.speed, innerStreamFive.heading ,innerStreamFive.eventId, StationeryTable.timeStamp as storedTime +insert into innerStreamSix; + +from innerStreamSix[(timeStamp - storedTime) >= $stationeryTime] +select id , latitude, longitude,timeStamp, type, speed, heading ,eventId ,"true" as isStationary +insert into dataOutStream; + +from innerStreamSix[(timeStamp - storedTime) < $stationeryTime] +select id , latitude, longitude,timeStamp, type, speed, heading ,eventId ,"false" as isStationary +insert into dataOutStream; + +from dataOutStream[isStationary == 'true'] +select id ,latitude, longitude,timeStamp, type, speed, heading ,eventId ,"ALERTED" as state, "This device is in $stationeryName area!!!" as information +insert into dataOut; + +from dataOutStream[isStationary == 'false'] +select id , latitude, longitude,timeStamp, type, speed, heading ,eventId ,"NORMAL" as state,"" as information +insert into dataOut; \ No newline at end of file diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/resources/alerts/Geo-ExecutionPlan-Traffic_alert_for_deviceClusters.siddhiql b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/resources/alerts/Geo-ExecutionPlan-Traffic_alert_for_GeoClusters.siddhiql similarity index 100% rename from components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/resources/alerts/Geo-ExecutionPlan-Traffic_alert_for_deviceClusters.siddhiql rename to components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/resources/alerts/Geo-ExecutionPlan-Traffic_alert_for_GeoClusters.siddhiql diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/resources/alerts/Geo-ExecutionPlan-Within_alert_for_deviceClusters.siddhiql b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/resources/alerts/Geo-ExecutionPlan-Within_alert_for_GeoClusters.siddhiql similarity index 100% rename from components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/resources/alerts/Geo-ExecutionPlan-Within_alert_for_deviceClusters.siddhiql rename to components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/resources/alerts/Geo-ExecutionPlan-Within_alert_for_GeoClusters.siddhiql From 9e64c8971d2b135c01fbc1296cc3fb936240b748 Mon Sep 17 00:00:00 2001 From: Arcane94 Date: Fri, 23 Feb 2018 11:17:30 +0530 Subject: [PATCH 11/21] Minor changes in execution plans --- .../mgt/jaxrs/service/impl/GeoLocationBasedServiceImpl.java | 2 +- .../resources/alerts/Geo-ExecutionPlan-Exit_alert.siddhiql | 2 +- .../Geo-ExecutionPlan-Exit_alert_for_GeoClusters.siddhiql | 2 +- .../resources/alerts/Geo-ExecutionPlan-Speed_alert.siddhiql | 4 ++-- .../Geo-ExecutionPlan-Speed_alert_for_GeoClusters.siddhiql | 4 ++-- .../alerts/Geo-ExecutionPlan-Stationery_alert.siddhiql | 2 +- ...eo-ExecutionPlan-Stationery_alert_for_GeoClusters.siddhiql | 2 +- .../resources/alerts/Geo-ExecutionPlan-Within_alert.siddhiql | 2 +- .../Geo-ExecutionPlan-Within_alert_for_GeoClusters.siddhiql | 2 +- 9 files changed, 11 insertions(+), 11 deletions(-) diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/GeoLocationBasedServiceImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/GeoLocationBasedServiceImpl.java index c5c96263b9..4f34589157 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/GeoLocationBasedServiceImpl.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/GeoLocationBasedServiceImpl.java @@ -408,7 +408,7 @@ public class GeoLocationBasedServiceImpl implements GeoLocationBasedService { } return null; } catch (GeoLocationBasedServiceException e) { - String error = "Error occurred while getting the geo alerts for " + alertType + "alert"; + String error = "Error occurred while getting the geo alerts for " + alertType + " alert"; log.error(error, e); return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(error).build(); } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/resources/alerts/Geo-ExecutionPlan-Exit_alert.siddhiql b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/resources/alerts/Geo-ExecutionPlan-Exit_alert.siddhiql index 0b93582f3a..ac6d350cf6 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/resources/alerts/Geo-ExecutionPlan-Exit_alert.siddhiql +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/resources/alerts/Geo-ExecutionPlan-Exit_alert.siddhiql @@ -13,7 +13,7 @@ define stream dataIn (id string, latitude double, longitude double, timeStamp lo define stream dataOut (id string, latitude double, longitude double, timeStamp long, type string ,speed float, heading float, eventId string, state string, information string); from dataIn[geo:within(longitude,latitude,"$geoFenceGeoJSON")==false and id == "$deviceId"]#geodashboard:subscribe() -select id , latitude, longitude,timeStamp, type, speed, heading ,eventId , "ALERTED" as state, "This device is outside $areaName area!!!" as information +select id , latitude, longitude,timeStamp, type, speed, heading ,eventId , "ALERTED" as state, str:concat(str:concat(str:concat(type," device "),id), " is outside $areaName area!!!") as information insert into dataOut; from dataIn[geo:within(longitude,latitude,"$geoFenceGeoJSON")!=false and id == "$deviceId"] select id , latitude, longitude,timeStamp, type, speed, heading ,eventId , "NORMAL" as state, "" as information diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/resources/alerts/Geo-ExecutionPlan-Exit_alert_for_GeoClusters.siddhiql b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/resources/alerts/Geo-ExecutionPlan-Exit_alert_for_GeoClusters.siddhiql index 2259abacdc..68fe23e0b8 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/resources/alerts/Geo-ExecutionPlan-Exit_alert_for_GeoClusters.siddhiql +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/resources/alerts/Geo-ExecutionPlan-Exit_alert_for_GeoClusters.siddhiql @@ -13,7 +13,7 @@ define stream dataIn (id string, latitude double, longitude double, timeStamp lo define stream dataOut (id string, latitude double, longitude double, timeStamp long, type string ,speed float, heading float, eventId string, state string, information string); from dataIn[geo:within(longitude,latitude,"$geoFenceGeoJSON")==false]#geodashboard:subscribe() -select id , latitude, longitude,timeStamp, type, speed, heading ,eventId , "ALERTED" as state, "This device is outside $areaName area!!!" as information +select id , latitude, longitude,timeStamp, type, speed, heading ,eventId , "ALERTED" as state, str:concat(str:concat(str:concat(type," device "),id), " is outside $areaName area!!!") as information insert into dataOut; from dataIn[geo:within(longitude,latitude,"$geoFenceGeoJSON")!=false] select id, latitude, longitude,timeStamp, type, speed, heading ,eventId , "NORMAL" as state, "" as information diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/resources/alerts/Geo-ExecutionPlan-Speed_alert.siddhiql b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/resources/alerts/Geo-ExecutionPlan-Speed_alert.siddhiql index 93c7ca622f..39c4a0b280 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/resources/alerts/Geo-ExecutionPlan-Speed_alert.siddhiql +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/resources/alerts/Geo-ExecutionPlan-Speed_alert.siddhiql @@ -13,10 +13,10 @@ define stream dataIn (id string, latitude double, longitude double, timeStamp lo define stream dataOut (id string, latitude double, longitude double, timeStamp long, type string, speed float, heading float, eventId string, state string, information string); from dataIn[speed >= $speedAlertValue and id == "$deviceId"]#geodashboard:subscribe() -select id , latitude, longitude,timeStamp, type ,speed, heading ,eventId , "ALERTED" as state, "This device movement is not normal!!" as information +select id , latitude, longitude,timeStamp, type ,speed, heading ,eventId , "ALERTED" as state, str:concat(str:concat(str:concat(str:concat("Movement of ",type), " device "), id), " is not normal!!") as information insert into dataOut; from dataIn[speed < $speedAlertValue and id == "$deviceId"] -select id , latitude, longitude,timeStamp, type ,speed, heading ,eventId , "NORMAL" as state, "This device movement is normal" as information +select id , latitude, longitude,timeStamp, type ,speed, heading ,eventId , "NORMAL" as state, str:concat(str:concat(str:concat(str:concat("Movement of ",type), " device "), id), " is normal") as information insert into dataOut; from dataIn[id != "$deviceId"] select id , latitude, longitude,timeStamp, type, speed, heading ,eventId , "NORMAL" as state, "" as information diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/resources/alerts/Geo-ExecutionPlan-Speed_alert_for_GeoClusters.siddhiql b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/resources/alerts/Geo-ExecutionPlan-Speed_alert_for_GeoClusters.siddhiql index 62d76659ce..ba7a6d24d9 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/resources/alerts/Geo-ExecutionPlan-Speed_alert_for_GeoClusters.siddhiql +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/resources/alerts/Geo-ExecutionPlan-Speed_alert_for_GeoClusters.siddhiql @@ -13,9 +13,9 @@ define stream dataIn (id string, latitude double, longitude double, timeStamp lo define stream dataOut (id string, latitude double, longitude double, timeStamp long, type string, speed float, heading float, eventId string, state string, information string); from dataIn[speed >= $speedAlertValue]#geodashboard:subscribe() -select id , latitude, longitude,timeStamp, type ,speed, heading ,eventId , "ALERTED" as state, "This device movement is not normal!!" as information +select id , latitude, longitude,timeStamp, type ,speed, heading ,eventId , "ALERTED" as state, str:concat(str:concat(str:concat(str:concat("Movement of ",type), " device "), id), " is not normal!!") as information insert into dataOut; from dataIn[speed < $speedAlertValue] -select id , latitude, longitude,timeStamp, type ,speed, heading ,eventId , "NORMAL" as state, "This device movement is normal" as information +select id , latitude, longitude,timeStamp, type ,speed, heading ,eventId , "NORMAL" as state, str:concat(str:concat(str:concat(str:concat("Movement of ",type), " device "), id), " is normal") as information insert into dataOut; diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/resources/alerts/Geo-ExecutionPlan-Stationery_alert.siddhiql b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/resources/alerts/Geo-ExecutionPlan-Stationery_alert.siddhiql index 46bfbfe2e3..6f0e8aac75 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/resources/alerts/Geo-ExecutionPlan-Stationery_alert.siddhiql +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/resources/alerts/Geo-ExecutionPlan-Stationery_alert.siddhiql @@ -81,7 +81,7 @@ select id , latitude, longitude,timeStamp, type, speed, heading ,eventId ,"false insert into dataOutStream; from dataOutStream[isStationary == 'true'] -select id ,latitude, longitude,timeStamp, type, speed, heading ,eventId ,"ALERTED" as state, "This device is in $stationeryName area!!!" as information +select id ,latitude, longitude,timeStamp, type, speed, heading ,eventId ,"ALERTED" as state, str:concat(str:concat(str:concat(type," device "),id),"is in $stationeryName area!!!") as information insert into dataOut; from dataOutStream[isStationary == 'false'] diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/resources/alerts/Geo-ExecutionPlan-Stationery_alert_for_GeoClusters.siddhiql b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/resources/alerts/Geo-ExecutionPlan-Stationery_alert_for_GeoClusters.siddhiql index 46bfbfe2e3..6f0e8aac75 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/resources/alerts/Geo-ExecutionPlan-Stationery_alert_for_GeoClusters.siddhiql +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/resources/alerts/Geo-ExecutionPlan-Stationery_alert_for_GeoClusters.siddhiql @@ -81,7 +81,7 @@ select id , latitude, longitude,timeStamp, type, speed, heading ,eventId ,"false insert into dataOutStream; from dataOutStream[isStationary == 'true'] -select id ,latitude, longitude,timeStamp, type, speed, heading ,eventId ,"ALERTED" as state, "This device is in $stationeryName area!!!" as information +select id ,latitude, longitude,timeStamp, type, speed, heading ,eventId ,"ALERTED" as state, str:concat(str:concat(str:concat(type," device "),id),"is in $stationeryName area!!!") as information insert into dataOut; from dataOutStream[isStationary == 'false'] diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/resources/alerts/Geo-ExecutionPlan-Within_alert.siddhiql b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/resources/alerts/Geo-ExecutionPlan-Within_alert.siddhiql index 78db10a679..38240e4937 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/resources/alerts/Geo-ExecutionPlan-Within_alert.siddhiql +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/resources/alerts/Geo-ExecutionPlan-Within_alert.siddhiql @@ -13,7 +13,7 @@ define stream dataIn (id string, latitude double, longitude double, timeStamp lo define stream dataOut (id string, latitude double, longitude double, timeStamp long, type string ,speed float, heading float, eventId string, state string, information string); from dataIn[geo:within(longitude,latitude,"$geoFenceGeoJSON")==true and id == "$deviceId"]#geodashboard:subscribe() -select id , latitude, longitude,timeStamp, type, speed, heading ,eventId , "ALERTED" as state, "This device is in $areaName restricted area!!!" as information +select id , latitude, longitude,timeStamp, type, speed, heading ,eventId , "ALERTED" as state, str:concat(str:concat(str:concat(type," device "), id), " is in $areaName restricted area!!!") as information insert into dataOut; from dataIn[geo:within(longitude,latitude,"$geoFenceGeoJSON")!=true and id == "$deviceId"] select id , latitude, longitude,timeStamp, type, speed, heading ,eventId , "NORMAL" as state, "" as information diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/resources/alerts/Geo-ExecutionPlan-Within_alert_for_GeoClusters.siddhiql b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/resources/alerts/Geo-ExecutionPlan-Within_alert_for_GeoClusters.siddhiql index 30aea4d7fa..67fa2df594 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/resources/alerts/Geo-ExecutionPlan-Within_alert_for_GeoClusters.siddhiql +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/resources/alerts/Geo-ExecutionPlan-Within_alert_for_GeoClusters.siddhiql @@ -13,7 +13,7 @@ define stream dataIn (id string, latitude double, longitude double, timeStamp lo define stream dataOut (id string, latitude double, longitude double, timeStamp long, type string ,speed float, heading float, eventId string, state string, information string); from dataIn[geo:within(longitude,latitude,"$geoFenceGeoJSON")==true]#geodashboard:subscribe() -select id , latitude, longitude,timeStamp, type, speed, heading ,eventId , "ALERTED" as state, "This device is in $areaName restricted area!!!" as information +select id , latitude, longitude,timeStamp, type, speed, heading ,eventId , "ALERTED" as state, str:concat(str:concat(str:concat(type," device "), id), " is in $areaName restricted area!!!") as information insert into dataOut; from dataIn[geo:within(longitude,latitude,"$geoFenceGeoJSON")!=true] select id , latitude, longitude,timeStamp, type, speed, heading ,eventId , "NORMAL" as state, "" as information From 27ae7cfed8321739d15dc8efafd9b0559cb791c5 Mon Sep 17 00:00:00 2001 From: Arcane94 Date: Fri, 23 Feb 2018 21:54:55 +0530 Subject: [PATCH 12/21] Fix for adding alerts twice with same name bug --- .../service/api/GeoLocationBasedService.java | 2 +- .../impl/GeoLocationBasedServiceImpl.java | 11 +++++- .../common/geo/service/AlertAlreadyExist.java | 25 ++++++++++++ .../service/GeoLocationProviderService.java | 4 +- .../GeoLocationProviderServiceImpl.java | 38 ++++++------------- 5 files changed, 49 insertions(+), 31 deletions(-) create mode 100644 components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/geo/service/AlertAlreadyExist.java diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/api/GeoLocationBasedService.java b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/api/GeoLocationBasedService.java index 23602baf0c..8396457e3f 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/api/GeoLocationBasedService.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/api/GeoLocationBasedService.java @@ -327,7 +327,7 @@ public interface GeoLocationBasedService { }), @ApiResponse( code = 400, - message = "Bad Request. \n Invalid Device Identifiers found.", + message = "Bad Request. \n A geo alert with this name already exists.", response = Response.class), @ApiResponse( code = 401, diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/GeoLocationBasedServiceImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/GeoLocationBasedServiceImpl.java index 4f34589157..4bee9d62a8 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/GeoLocationBasedServiceImpl.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/GeoLocationBasedServiceImpl.java @@ -48,6 +48,7 @@ import org.wso2.carbon.device.mgt.jaxrs.util.DeviceMgtUtil; import org.wso2.carbon.user.api.UserStoreException; import org.wso2.carbon.utils.multitenancy.MultitenantUtils; +import javax.persistence.EntityExistsException; import javax.ws.rs.*; import javax.ws.rs.core.Response; import java.util.ArrayList; @@ -201,9 +202,13 @@ public class GeoLocationBasedServiceImpl implements GeoLocationBasedService { geoService.createGeoAlert(alert, alertType); return Response.ok().build(); } catch (GeoLocationBasedServiceException e) { - String error = "Error occurred while creating " + alertType + "alert"; + String error = "Error occurred while creating " + alertType + " alert"; log.error(error, e); return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(error).build(); + } catch (AlertAlreadyExist e) { + String error = "A geo alert with this name already exists."; + log.error(error,e); + return Response.status(Response.Status.BAD_REQUEST).entity(error).build(); } } @@ -263,6 +268,10 @@ public class GeoLocationBasedServiceImpl implements GeoLocationBasedService { String error = "Error occurred while updating the geo alert for geo clusters"; log.error(error, e); return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(error).build(); + } catch (AlertAlreadyExist e) { + String error = "A geo alert with this name already exists."; + log.error(error,e); + return Response.status(Response.Status.BAD_REQUEST).entity(error).build(); } } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/geo/service/AlertAlreadyExist.java b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/geo/service/AlertAlreadyExist.java new file mode 100644 index 0000000000..451b8d98d6 --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/geo/service/AlertAlreadyExist.java @@ -0,0 +1,25 @@ +package org.wso2.carbon.device.mgt.common.geo.service; + +/** + * Custom exception class of Geo Service related operations. + */ + +public class AlertAlreadyExist extends Exception { + + private static final long serialVersionUID = 4709355511911265093L; + + private String errorMessage; + + public String getErrorMessage() { + return errorMessage; + } + + public void setErrorMessage(String errorMessage) { + this.errorMessage = errorMessage; + } + + public AlertAlreadyExist(String msg) { + super(msg); + setErrorMessage(msg); + } +} diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/geo/service/GeoLocationProviderService.java b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/geo/service/GeoLocationProviderService.java index 47daac0492..66e5504f95 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/geo/service/GeoLocationProviderService.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/geo/service/GeoLocationProviderService.java @@ -40,13 +40,13 @@ public interface GeoLocationProviderService { throws GeoLocationBasedServiceException, AlertAlreadyExistException; boolean createGeoAlert(Alert alert, String alertType) - throws GeoLocationBasedServiceException; + throws GeoLocationBasedServiceException,AlertAlreadyExist; boolean updateGeoAlert(Alert alert, DeviceIdentifier identifier, String alertType) throws GeoLocationBasedServiceException, AlertAlreadyExistException; boolean updateGeoAlert(Alert alert, String alertType) - throws GeoLocationBasedServiceException; + throws GeoLocationBasedServiceException,AlertAlreadyExist; boolean removeGeoAlert(String alertType, DeviceIdentifier identifier, String queryName) throws GeoLocationBasedServiceException; diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/geo/service/GeoLocationProviderServiceImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/geo/service/GeoLocationProviderServiceImpl.java index 7174bea0ae..cf95db9b27 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/geo/service/GeoLocationProviderServiceImpl.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/geo/service/GeoLocationProviderServiceImpl.java @@ -55,6 +55,7 @@ import org.wso2.carbon.registry.api.Resource; import javax.net.ssl.KeyManagerFactory; import javax.net.ssl.SSLContext; import javax.net.ssl.TrustManagerFactory; +import javax.persistence.EntityExistsException; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; @@ -303,7 +304,7 @@ public class GeoLocationProviderServiceImpl implements GeoLocationProviderServic @Override public boolean createGeoAlert(Alert alert, DeviceIdentifier identifier, String alertType) - throws GeoLocationBasedServiceException, AlertAlreadyExistException { + throws GeoLocationBasedServiceException { return saveGeoAlert(alert, identifier, alertType, false); } @@ -315,7 +316,7 @@ public class GeoLocationProviderServiceImpl implements GeoLocationProviderServic @Override public boolean updateGeoAlert(Alert alert, DeviceIdentifier identifier, String alertType) - throws GeoLocationBasedServiceException, AlertAlreadyExistException { + throws GeoLocationBasedServiceException { return saveGeoAlert(alert, identifier, alertType, true); } @@ -423,7 +424,7 @@ public class GeoLocationProviderServiceImpl implements GeoLocationProviderServic } public boolean saveGeoAlert(Alert alert, DeviceIdentifier identifier, String alertType, boolean isUpdate) - throws GeoLocationBasedServiceException, AlertAlreadyExistException { + throws GeoLocationBasedServiceException { Type type = new TypeToken>() { }.getType(); @@ -465,38 +466,23 @@ public class GeoLocationProviderServiceImpl implements GeoLocationProviderServic "Unrecognized execution plan type: " + alertType + " while creating geo alert"); } + //persist alert in registry + updateRegistry(getRegistryPath(alertType, identifier, alert.getQueryName()), identifier, content, + options); + //deploy alert into event processor EventProcessorAdminServiceStub eventprocessorStub = null; String action = (isUpdate ? "updating" : "creating"); try { - ExecutionPlanConfigurationDto[] allActiveExecutionPlanConfigs = null; - String activeExecutionPlan = null; - String executionPlanName = getExecutionPlanName(alertType, alert.getQueryName(), - identifier.getId()); eventprocessorStub = getEventProcessorAdminServiceStub(); String parsedTemplate = parseTemplate(alertType, parseMap); String validationResponse = eventprocessorStub.validateExecutionPlan(parsedTemplate); if (validationResponse.equals("success")) { - allActiveExecutionPlanConfigs = eventprocessorStub.getAllActiveExecutionPlanConfigurations(); if (isUpdate) { - for (ExecutionPlanConfigurationDto activeExectionPlanConfig:allActiveExecutionPlanConfigs) { - activeExecutionPlan = activeExectionPlanConfig.getExecutionPlan(); - if (activeExecutionPlan.contains(executionPlanName)) { - eventprocessorStub.editActiveExecutionPlan(parsedTemplate, executionPlanName); - return true; - } - } - eventprocessorStub.deployExecutionPlan(parsedTemplate); + String executionPlanName = getExecutionPlanName(alertType, alert.getQueryName(), + identifier.getId()); + eventprocessorStub.editActiveExecutionPlan(parsedTemplate, executionPlanName); } else { - for (ExecutionPlanConfigurationDto activeExectionPlanConfig:allActiveExecutionPlanConfigs) { - activeExecutionPlan = activeExectionPlanConfig.getExecutionPlan(); - if (activeExecutionPlan.contains(executionPlanName)) { - throw new AlertAlreadyExistException("Execution plan already exists with name " - + executionPlanName); - } - } - updateRegistry(getRegistryPath(alertType, identifier, alert.getQueryName()), identifier, content, - options); eventprocessorStub.deployExecutionPlan(parsedTemplate); } } else { @@ -592,8 +578,6 @@ public class GeoLocationProviderServiceImpl implements GeoLocationProviderServic private String getExecutionPlanName(String alertType, String queryName, String deviceId) { if ("Traffic".equals(alertType)) { return "Geo-ExecutionPlan-Traffic_" + queryName + "_alert"; - } else if ("Speed".equals(alertType)) { - return "Geo-ExecutionPlan-" + alertType + "---" + deviceId + "_alert"; } else { return "Geo-ExecutionPlan-" + alertType + "_" + queryName + "---_" + deviceId + "_alert"; } From 1ffaad6fb79112d817ced756c207e19a82672af8 Mon Sep 17 00:00:00 2001 From: Arcane94 Date: Fri, 23 Feb 2018 22:02:36 +0530 Subject: [PATCH 13/21] rolling back some imports --- .../impl/GeoLocationBasedServiceImpl.java | 1 - .../GeoLocationProviderServiceImpl.java | 27 +++++++++++-------- 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/GeoLocationBasedServiceImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/GeoLocationBasedServiceImpl.java index 4bee9d62a8..5c55096bbe 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/GeoLocationBasedServiceImpl.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/GeoLocationBasedServiceImpl.java @@ -48,7 +48,6 @@ import org.wso2.carbon.device.mgt.jaxrs.util.DeviceMgtUtil; import org.wso2.carbon.user.api.UserStoreException; import org.wso2.carbon.utils.multitenancy.MultitenantUtils; -import javax.persistence.EntityExistsException; import javax.ws.rs.*; import javax.ws.rs.core.Response; import java.util.ArrayList; diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/geo/service/GeoLocationProviderServiceImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/geo/service/GeoLocationProviderServiceImpl.java index cf95db9b27..a5b293ec04 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/geo/service/GeoLocationProviderServiceImpl.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/geo/service/GeoLocationProviderServiceImpl.java @@ -310,7 +310,7 @@ public class GeoLocationProviderServiceImpl implements GeoLocationProviderServic @Override public boolean createGeoAlert(Alert alert, String alertType) - throws GeoLocationBasedServiceException { + throws GeoLocationBasedServiceException,AlertAlreadyExist { return saveGeoAlert(alert, alertType, false); } @@ -322,12 +322,12 @@ public class GeoLocationProviderServiceImpl implements GeoLocationProviderServic @Override public boolean updateGeoAlert(Alert alert, String alertType) - throws GeoLocationBasedServiceException { + throws GeoLocationBasedServiceException,AlertAlreadyExist { return saveGeoAlert(alert, alertType, true); } public boolean saveGeoAlert(Alert alert, String alertType, boolean isUpdate) - throws GeoLocationBasedServiceException { + throws GeoLocationBasedServiceException,AlertAlreadyExist { Type type = new TypeToken>() { }.getType(); @@ -369,28 +369,33 @@ public class GeoLocationProviderServiceImpl implements GeoLocationProviderServic "Unrecognized execution plan type: " + alertType + " while creating geo alert"); } - //persist alert in registry - updateRegistry(getRegistryPath(alertType, alert.getQueryName()), content, - options); - //deploy alert into event processor EventProcessorAdminServiceStub eventprocessorStub = null; String action = (isUpdate ? "updating" : "creating"); try { + String existingPlanName = null; + String executionPlanName = getExecutionPlanName(alertType, alert.getQueryName()); eventprocessorStub = getEventProcessorAdminServiceStub(); String parsedTemplate = parseTemplateForGeoClusters(alertType, parseMap); String validationResponse = eventprocessorStub.validateExecutionPlan(parsedTemplate); if (validationResponse.equals("success")) { if (isUpdate) { - String executionPlanName = getExecutionPlanName(alertType, alert.getQueryName()); try { - String existingPlanName = eventprocessorStub.getActiveExecutionPlan(executionPlanName); - } catch (Exception e) { + existingPlanName = eventprocessorStub.getActiveExecutionPlan(executionPlanName); + } catch (AxisFault axisFault) { eventprocessorStub.deployExecutionPlan(parsedTemplate); } eventprocessorStub.editActiveExecutionPlan(parsedTemplate, executionPlanName); } else { - eventprocessorStub.deployExecutionPlan(parsedTemplate); + try { + existingPlanName = eventprocessorStub.getActiveExecutionPlan(executionPlanName); + if (existingPlanName.contains(executionPlanName)) { + throw new AlertAlreadyExist("Execution plan with this name already exists"); + } + } catch (AxisFault axisFault) { + updateRegistry(getRegistryPath(alertType, alert.getQueryName()), content,options); + eventprocessorStub.deployExecutionPlan(parsedTemplate); + } } } else { if (validationResponse.startsWith( From 8c303911b02f847c10ace5c665c2ba58d4c074dc Mon Sep 17 00:00:00 2001 From: Arcane94 Date: Fri, 9 Mar 2018 14:23:45 +0530 Subject: [PATCH 14/21] Final frontend and backend changes --- .../impl/GeoLocationBasedServiceImpl.java | 4 +- .../impl/GeoLocationBasedServiceImplTest.java | 4 +- .../common/geo/service/AlertAlreadyExist.java | 25 - .../service/GeoLocationProviderService.java | 4 +- .../core/dao/impl/AbstractDeviceDAOImpl.java | 6 +- .../device/mgt/core/geo/GeoCluster.java | 9 +- .../GeoLocationProviderServiceImpl.java | 82 +- .../GeoLocationProviderServiceTest.java | 1 + .../public/js/geo_fencing.js | 117 +- .../public/js/geo_remote.js | 8 +- .../cdmf.unit.geo-devices/geo-devices.hbs | 909 ++++- .../cdmf.unit.geo-devices/geo-devices.js | 58 + .../html_templates/modal/exit_alert.html | 52 + .../html_templates/modal/proximity_alert.html | 95 + .../html_templates/modal/speed_alert.html | 49 + .../modal/stationery_alert.html | 83 + .../html_templates/modal/traffic_point.html | 104 + .../html_templates/modal/within_alert.html | 52 + .../html_templates/view_fence_popup.html | 52 + .../Geo-ExecutionPlan-Exit_alert.siddhiql | 20 + ...Geo-ExecutionPlan-Proximity_alert.siddhiql | 140 + .../Geo-ExecutionPlan-Speed_alert.siddhiql | 20 + ...eo-ExecutionPlan-Stationery_alert.siddhiql | 89 + .../Geo-ExecutionPlan-Traffic_alert.siddhiql | 17 + .../Geo-ExecutionPlan-Within_alert.siddhiql | 20 + .../cdmf.unit.geo-devices/public/css/app.css | 19 + .../cdmf.unit.geo-devices/public/js/app.js | 279 +- .../public/js/application_options.js | 77 + .../public/js/d3/C3_LICENSE | 20 + .../public/js/d3/D3_LICENSE | 26 + .../public/js/d3/c3.min.js | 4 + .../public/js/d3/d3.min.js | 5 + .../public/js/firstTemp.js | 8 + .../public/js/geo_exit_fence.js | 50 + .../public/js/geo_fencing.js | 580 +++ .../public/js/geo_proximity.js | 90 + .../public/js/geo_remote.js | 552 +++ .../public/js/geo_speed.js | 29 + .../public/js/geo_stationary.js | 54 + .../public/js/geo_within.js | 50 + .../js/jquery/bootstrap-datepicker.min.js | 8 + .../public/js/jquery/jquery-2.1.1.min.js | 2066 +++++++++++ .../js/jquery/jquery-ui-timepicker-addon.js | 2245 ++++++++++++ .../jquery/jquery-ui-timepicker-addon.min.js | 5 + .../public/js/jquery/jquery-ui.min.js | 3205 +++++++++++++++++ .../public/js/moment.min.js | 25 + .../public/js/secondTemp.js | 10 + .../public/js/show_alert_in_map.js | 55 + .../public/js/socket.io.min.js | 2 + .../public/js/websocket.js | 355 ++ .../public/css/custom-desktop.css | 1 + .../impl/GeoLocationBasedServiceImpl.java | 157 + .../impl/GeoLocationBasedServiceImplTest.java | 4 +- 53 files changed, 11854 insertions(+), 147 deletions(-) delete mode 100644 components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/geo/service/AlertAlreadyExist.java create mode 100644 components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.geo-devices/geo-devices.js create mode 100644 components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.geo-devices/public/assets/html_templates/modal/exit_alert.html create mode 100644 components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.geo-devices/public/assets/html_templates/modal/proximity_alert.html create mode 100644 components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.geo-devices/public/assets/html_templates/modal/speed_alert.html create mode 100644 components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.geo-devices/public/assets/html_templates/modal/stationery_alert.html create mode 100644 components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.geo-devices/public/assets/html_templates/modal/traffic_point.html create mode 100644 components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.geo-devices/public/assets/html_templates/modal/within_alert.html create mode 100644 components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.geo-devices/public/assets/html_templates/view_fence_popup.html create mode 100644 components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.geo-devices/public/conf/alerts/Geo-ExecutionPlan-Exit_alert.siddhiql create mode 100644 components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.geo-devices/public/conf/alerts/Geo-ExecutionPlan-Proximity_alert.siddhiql create mode 100644 components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.geo-devices/public/conf/alerts/Geo-ExecutionPlan-Speed_alert.siddhiql create mode 100644 components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.geo-devices/public/conf/alerts/Geo-ExecutionPlan-Stationery_alert.siddhiql create mode 100644 components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.geo-devices/public/conf/alerts/Geo-ExecutionPlan-Traffic_alert.siddhiql create mode 100644 components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.geo-devices/public/conf/alerts/Geo-ExecutionPlan-Within_alert.siddhiql create mode 100644 components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.geo-devices/public/js/application_options.js create mode 100644 components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.geo-devices/public/js/d3/C3_LICENSE create mode 100644 components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.geo-devices/public/js/d3/D3_LICENSE create mode 100644 components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.geo-devices/public/js/d3/c3.min.js create mode 100644 components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.geo-devices/public/js/d3/d3.min.js create mode 100644 components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.geo-devices/public/js/firstTemp.js create mode 100644 components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.geo-devices/public/js/geo_exit_fence.js create mode 100644 components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.geo-devices/public/js/geo_fencing.js create mode 100644 components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.geo-devices/public/js/geo_proximity.js create mode 100644 components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.geo-devices/public/js/geo_speed.js create mode 100644 components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.geo-devices/public/js/geo_stationary.js create mode 100644 components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.geo-devices/public/js/geo_within.js create mode 100644 components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.geo-devices/public/js/jquery/bootstrap-datepicker.min.js create mode 100644 components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.geo-devices/public/js/jquery/jquery-2.1.1.min.js create mode 100644 components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.geo-devices/public/js/jquery/jquery-ui-timepicker-addon.js create mode 100644 components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.geo-devices/public/js/jquery/jquery-ui-timepicker-addon.min.js create mode 100644 components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.geo-devices/public/js/jquery/jquery-ui.min.js create mode 100644 components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.geo-devices/public/js/moment.min.js create mode 100644 components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.geo-devices/public/js/secondTemp.js create mode 100644 components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.geo-devices/public/js/show_alert_in_map.js create mode 100644 components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.geo-devices/public/js/socket.io.min.js create mode 100644 components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.geo-devices/public/js/websocket.js diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/GeoLocationBasedServiceImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/GeoLocationBasedServiceImpl.java index 5c55096bbe..34fbaae517 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/GeoLocationBasedServiceImpl.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/GeoLocationBasedServiceImpl.java @@ -204,7 +204,7 @@ public class GeoLocationBasedServiceImpl implements GeoLocationBasedService { String error = "Error occurred while creating " + alertType + " alert"; log.error(error, e); return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(error).build(); - } catch (AlertAlreadyExist e) { + } catch (AlertAlreadyExistException e) { String error = "A geo alert with this name already exists."; log.error(error,e); return Response.status(Response.Status.BAD_REQUEST).entity(error).build(); @@ -267,7 +267,7 @@ public class GeoLocationBasedServiceImpl implements GeoLocationBasedService { String error = "Error occurred while updating the geo alert for geo clusters"; log.error(error, e); return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(error).build(); - } catch (AlertAlreadyExist e) { + } catch (AlertAlreadyExistException e) { String error = "A geo alert with this name already exists."; log.error(error,e); return Response.status(Response.Status.BAD_REQUEST).entity(error).build(); diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/test/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/GeoLocationBasedServiceImplTest.java b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/test/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/GeoLocationBasedServiceImplTest.java index be7209a8e9..ebd20ecbfe 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/test/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/GeoLocationBasedServiceImplTest.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/test/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/GeoLocationBasedServiceImplTest.java @@ -46,10 +46,10 @@ public class GeoLocationBasedServiceImplTest { List geoClusters = new ArrayList<>(); geoClusters.add(new GeoCluster(new GeoCoordinate(1.5, 80.7), new GeoCoordinate(1.1, 79.5), new GeoCoordinate(1.9, 82.1), 3, - "tb32", "aegtew234", "android")); + "tb32", "aegtew234", "android", "1234")); geoClusters.add(new GeoCluster(new GeoCoordinate(10.2, 86.1), new GeoCoordinate(9.8, 84.7), new GeoCoordinate(11.1, 88.1), 4, - "t1gd", "swerty12s", "android")); + "t1gd", "swerty12s", "android", "1234")); Mockito.doReturn(geoClusters).when(deviceManagementProviderService) .findGeoClusters(Mockito.any(GeoCoordinate.class), Mockito.any(GeoCoordinate.class), Mockito.anyInt()); Response response = geoLocationBasedService.getGeoDeviceLocations(0.4, 15, 75.6, diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/geo/service/AlertAlreadyExist.java b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/geo/service/AlertAlreadyExist.java deleted file mode 100644 index 451b8d98d6..0000000000 --- a/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/geo/service/AlertAlreadyExist.java +++ /dev/null @@ -1,25 +0,0 @@ -package org.wso2.carbon.device.mgt.common.geo.service; - -/** - * Custom exception class of Geo Service related operations. - */ - -public class AlertAlreadyExist extends Exception { - - private static final long serialVersionUID = 4709355511911265093L; - - private String errorMessage; - - public String getErrorMessage() { - return errorMessage; - } - - public void setErrorMessage(String errorMessage) { - this.errorMessage = errorMessage; - } - - public AlertAlreadyExist(String msg) { - super(msg); - setErrorMessage(msg); - } -} diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/geo/service/GeoLocationProviderService.java b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/geo/service/GeoLocationProviderService.java index 66e5504f95..92bd4e0d2f 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/geo/service/GeoLocationProviderService.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/geo/service/GeoLocationProviderService.java @@ -40,13 +40,13 @@ public interface GeoLocationProviderService { throws GeoLocationBasedServiceException, AlertAlreadyExistException; boolean createGeoAlert(Alert alert, String alertType) - throws GeoLocationBasedServiceException,AlertAlreadyExist; + throws GeoLocationBasedServiceException,AlertAlreadyExistException; boolean updateGeoAlert(Alert alert, DeviceIdentifier identifier, String alertType) throws GeoLocationBasedServiceException, AlertAlreadyExistException; boolean updateGeoAlert(Alert alert, String alertType) - throws GeoLocationBasedServiceException,AlertAlreadyExist; + throws GeoLocationBasedServiceException,AlertAlreadyExistException; boolean removeGeoAlert(String alertType, DeviceIdentifier identifier, String queryName) throws GeoLocationBasedServiceException; diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/AbstractDeviceDAOImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/AbstractDeviceDAOImpl.java index ac558791b9..0e97c24d8b 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/AbstractDeviceDAOImpl.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/AbstractDeviceDAOImpl.java @@ -1076,7 +1076,8 @@ public abstract class AbstractDeviceDAOImpl implements DeviceDAO { " MAX(DEVICE_LOCATION.LONGITUDE) AS MAX_LONGITUDE," + " SUBSTRING(DEVICE_LOCATION.GEO_HASH,1,?) AS GEOHASH_PREFIX, COUNT(*) AS COUNT," + " MIN(DEVICE.DEVICE_IDENTIFICATION) AS DEVICE_IDENTIFICATION," + - " MIN(DEVICE_TYPE.NAME) AS TYPE " + + " MIN(DEVICE_TYPE.NAME) AS TYPE, " + + " MIN(DEVICE.LAST_UPDATED_TIMESTAMP) AS LAST_UPDATED_TIMESTAMP " + "FROM DM_DEVICE_LOCATION AS DEVICE_LOCATION,DM_DEVICE AS DEVICE, DM_DEVICE_TYPE AS DEVICE_TYPE " + "WHERE DEVICE_LOCATION.LATITUDE BETWEEN ? AND ? AND " + "DEVICE_LOCATION.LONGITUDE BETWEEN ? AND ? AND " + @@ -1100,11 +1101,12 @@ public abstract class AbstractDeviceDAOImpl implements DeviceDAO { double max_longitude = rs.getDouble("MAX_LONGITUDE"); String device_identification = rs.getString("DEVICE_IDENTIFICATION"); String device_type=rs.getString("TYPE"); + String last_seen = rs.getString("LAST_UPDATED_TIMESTAMP"); long count = rs.getLong("COUNT"); String geohashPrefix = rs.getString("GEOHASH_PREFIX"); geoClusters.add(new GeoCluster(new GeoCoordinate(latitude, longitude), new GeoCoordinate(min_latitude,min_longitude), new GeoCoordinate(max_latitude,max_longitude), - count, geohashPrefix,device_identification,device_type)); + count, geohashPrefix,device_identification,device_type,last_seen)); } } catch (SQLException e) { throw new DeviceManagementDAOException("Error occurred while retrieving information of " + diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/geo/GeoCluster.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/geo/GeoCluster.java index a434800d32..6fa306f20b 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/geo/GeoCluster.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/geo/GeoCluster.java @@ -10,11 +10,11 @@ public class GeoCluster { private String geohashPrefix; private String deviceIdentification; private String deviceType; - + private String lastSeen; public GeoCluster(GeoCoordinate coordinates, GeoCoordinate southWestBound, GeoCoordinate northEastBound, long count, - String geohashPrefix, String deviceIdentification, String deviceType){ + String geohashPrefix, String deviceIdentification, String deviceType, String lastSeen){ this.coordinates=coordinates; this.southWestBound=southWestBound; this.northEastBound=northEastBound; @@ -22,6 +22,7 @@ public class GeoCluster { this.geohashPrefix=geohashPrefix; this.deviceIdentification=deviceIdentification; this.deviceType=deviceType; + this.lastSeen = lastSeen; } @@ -51,4 +52,8 @@ public class GeoCluster { public String getDeviceType() { return deviceType; } + + public String getLastSeen() { + return lastSeen; + } } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/geo/service/GeoLocationProviderServiceImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/geo/service/GeoLocationProviderServiceImpl.java index a5b293ec04..0122f6adfe 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/geo/service/GeoLocationProviderServiceImpl.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/geo/service/GeoLocationProviderServiceImpl.java @@ -165,7 +165,7 @@ public class GeoLocationProviderServiceImpl implements GeoLocationProviderServic Registry registry = getGovernanceRegistry(); String registryPath = GeoServices.REGISTRY_PATH_FOR_ALERTS + - GeoServices.ALERT_TYPE_WITHIN; + GeoServices.ALERT_TYPE_WITHIN + "/"; Resource resource; try { resource = registry.get(registryPath); @@ -260,7 +260,7 @@ public class GeoLocationProviderServiceImpl implements GeoLocationProviderServic Registry registry = getGovernanceRegistry(); String registryPath = GeoServices.REGISTRY_PATH_FOR_ALERTS + - GeoServices.ALERT_TYPE_EXIT; + GeoServices.ALERT_TYPE_EXIT + "/"; Resource resource; try { resource = registry.get(registryPath); @@ -304,30 +304,30 @@ public class GeoLocationProviderServiceImpl implements GeoLocationProviderServic @Override public boolean createGeoAlert(Alert alert, DeviceIdentifier identifier, String alertType) - throws GeoLocationBasedServiceException { + throws GeoLocationBasedServiceException, AlertAlreadyExistException { return saveGeoAlert(alert, identifier, alertType, false); } @Override public boolean createGeoAlert(Alert alert, String alertType) - throws GeoLocationBasedServiceException,AlertAlreadyExist { + throws GeoLocationBasedServiceException,AlertAlreadyExistException { return saveGeoAlert(alert, alertType, false); } @Override public boolean updateGeoAlert(Alert alert, DeviceIdentifier identifier, String alertType) - throws GeoLocationBasedServiceException { + throws GeoLocationBasedServiceException, AlertAlreadyExistException { return saveGeoAlert(alert, identifier, alertType, true); } @Override public boolean updateGeoAlert(Alert alert, String alertType) - throws GeoLocationBasedServiceException,AlertAlreadyExist { + throws GeoLocationBasedServiceException,AlertAlreadyExistException { return saveGeoAlert(alert, alertType, true); } public boolean saveGeoAlert(Alert alert, String alertType, boolean isUpdate) - throws GeoLocationBasedServiceException,AlertAlreadyExist { + throws GeoLocationBasedServiceException,AlertAlreadyExistException { Type type = new TypeToken>() { }.getType(); @@ -373,29 +373,34 @@ public class GeoLocationProviderServiceImpl implements GeoLocationProviderServic EventProcessorAdminServiceStub eventprocessorStub = null; String action = (isUpdate ? "updating" : "creating"); try { - String existingPlanName = null; + ExecutionPlanConfigurationDto[] allActiveExecutionPlanConfigs = null; + String activeExecutionPlan = null; String executionPlanName = getExecutionPlanName(alertType, alert.getQueryName()); eventprocessorStub = getEventProcessorAdminServiceStub(); String parsedTemplate = parseTemplateForGeoClusters(alertType, parseMap); String validationResponse = eventprocessorStub.validateExecutionPlan(parsedTemplate); + if (validationResponse.equals("success")) { + allActiveExecutionPlanConfigs = eventprocessorStub.getAllActiveExecutionPlanConfigurations(); if (isUpdate) { - try { - existingPlanName = eventprocessorStub.getActiveExecutionPlan(executionPlanName); - } catch (AxisFault axisFault) { - eventprocessorStub.deployExecutionPlan(parsedTemplate); + for (ExecutionPlanConfigurationDto activeExectionPlanConfig:allActiveExecutionPlanConfigs) { + activeExecutionPlan = activeExectionPlanConfig.getExecutionPlan(); + if (activeExecutionPlan.contains(executionPlanName)) { + eventprocessorStub.editActiveExecutionPlan(parsedTemplate, executionPlanName); + return true; + } } - eventprocessorStub.editActiveExecutionPlan(parsedTemplate, executionPlanName); + eventprocessorStub.deployExecutionPlan(parsedTemplate); } else { - try { - existingPlanName = eventprocessorStub.getActiveExecutionPlan(executionPlanName); - if (existingPlanName.contains(executionPlanName)) { - throw new AlertAlreadyExist("Execution plan with this name already exists"); + for (ExecutionPlanConfigurationDto activeExectionPlanConfig:allActiveExecutionPlanConfigs) { + activeExecutionPlan = activeExectionPlanConfig.getExecutionPlan(); + if (activeExecutionPlan.contains(executionPlanName)) { + throw new AlertAlreadyExistException("Execution plan already exists with name " + + executionPlanName); } - } catch (AxisFault axisFault) { - updateRegistry(getRegistryPath(alertType, alert.getQueryName()), content,options); - eventprocessorStub.deployExecutionPlan(parsedTemplate); } + updateRegistry(getRegistryPath(alertType, alert.getQueryName()),content,options); + eventprocessorStub.deployExecutionPlan(parsedTemplate); } } else { if (validationResponse.startsWith( @@ -429,7 +434,7 @@ public class GeoLocationProviderServiceImpl implements GeoLocationProviderServic } public boolean saveGeoAlert(Alert alert, DeviceIdentifier identifier, String alertType, boolean isUpdate) - throws GeoLocationBasedServiceException { + throws GeoLocationBasedServiceException, AlertAlreadyExistException { Type type = new TypeToken>() { }.getType(); @@ -471,23 +476,38 @@ public class GeoLocationProviderServiceImpl implements GeoLocationProviderServic "Unrecognized execution plan type: " + alertType + " while creating geo alert"); } - //persist alert in registry - updateRegistry(getRegistryPath(alertType, identifier, alert.getQueryName()), identifier, content, - options); - //deploy alert into event processor EventProcessorAdminServiceStub eventprocessorStub = null; String action = (isUpdate ? "updating" : "creating"); try { + ExecutionPlanConfigurationDto[] allActiveExecutionPlanConfigs = null; + String activeExecutionPlan = null; + String executionPlanName = getExecutionPlanName(alertType, alert.getQueryName(), + identifier.getId()); eventprocessorStub = getEventProcessorAdminServiceStub(); String parsedTemplate = parseTemplate(alertType, parseMap); String validationResponse = eventprocessorStub.validateExecutionPlan(parsedTemplate); if (validationResponse.equals("success")) { + allActiveExecutionPlanConfigs = eventprocessorStub.getAllActiveExecutionPlanConfigurations(); if (isUpdate) { - String executionPlanName = getExecutionPlanName(alertType, alert.getQueryName(), - identifier.getId()); - eventprocessorStub.editActiveExecutionPlan(parsedTemplate, executionPlanName); + for (ExecutionPlanConfigurationDto activeExectionPlanConfig:allActiveExecutionPlanConfigs) { + activeExecutionPlan = activeExectionPlanConfig.getExecutionPlan(); + if (activeExecutionPlan.contains(executionPlanName)) { + eventprocessorStub.editActiveExecutionPlan(parsedTemplate, executionPlanName); + return true; + } + } + eventprocessorStub.deployExecutionPlan(parsedTemplate); } else { + for (ExecutionPlanConfigurationDto activeExectionPlanConfig:allActiveExecutionPlanConfigs) { + activeExecutionPlan = activeExectionPlanConfig.getExecutionPlan(); + if (activeExecutionPlan.contains(executionPlanName)) { + throw new AlertAlreadyExistException("Execution plan already exists with name " + + executionPlanName); + } + } + updateRegistry(getRegistryPath(alertType, identifier, alert.getQueryName()), identifier, content, + options); eventprocessorStub.deployExecutionPlan(parsedTemplate); } } else { @@ -495,7 +515,7 @@ public class GeoLocationProviderServiceImpl implements GeoLocationProviderServic "'within' is neither a function extension nor an aggregated attribute extension" )) { log.error("GPL Siddhi Geo Extension is not configured. Please execute maven script " + - "`siddhi-geo-extention-deployer.xml` in $IOT_HOME/analytics/scripts"); + "`siddhi-geo-extention-deployer.xml` in $IOT_HOME/analytics/scripts"); } else { log.error("Execution plan validation failed: " + validationResponse); } @@ -865,7 +885,7 @@ public class GeoLocationProviderServiceImpl implements GeoLocationProviderServic Registry registry = getGovernanceRegistry(); String registryPath = GeoServices.REGISTRY_PATH_FOR_ALERTS + - GeoServices.ALERT_TYPE_STATIONARY; + GeoServices.ALERT_TYPE_STATIONARY + "/"; Resource resource; try { resource = registry.get(registryPath); @@ -962,7 +982,7 @@ public class GeoLocationProviderServiceImpl implements GeoLocationProviderServic public List getTrafficAlerts() throws GeoLocationBasedServiceException { Registry registry = getGovernanceRegistry(); String registryPath = GeoServices.REGISTRY_PATH_FOR_ALERTS + - GeoServices.ALERT_TYPE_STATIONARY; + GeoServices.ALERT_TYPE_STATIONARY + "/"; Resource resource; try { resource = registry.get(registryPath); diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/test/java/org/wso2/carbon/device/mgt/core/geo/service/GeoLocationProviderServiceTest.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/test/java/org/wso2/carbon/device/mgt/core/geo/service/GeoLocationProviderServiceTest.java index 7be18ebff9..73222074c5 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/test/java/org/wso2/carbon/device/mgt/core/geo/service/GeoLocationProviderServiceTest.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/test/java/org/wso2/carbon/device/mgt/core/geo/service/GeoLocationProviderServiceTest.java @@ -30,6 +30,7 @@ import org.wso2.carbon.device.mgt.common.DeviceIdentifier; import org.wso2.carbon.device.mgt.common.DeviceManagementConstants; import org.wso2.carbon.device.mgt.common.DeviceManagementException; import org.wso2.carbon.device.mgt.common.geo.service.Alert; +import org.wso2.carbon.device.mgt.common.geo.service.AlertAlreadyExistException; import org.wso2.carbon.device.mgt.common.geo.service.GeoFence; import org.wso2.carbon.device.mgt.common.geo.service.GeoLocationBasedServiceException; import org.wso2.carbon.device.mgt.common.geo.service.AlertAlreadyExistException; diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.geo-dashboard/public/js/geo_fencing.js b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.geo-dashboard/public/js/geo_fencing.js index 07a42cefd8..182a9a1baa 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.geo-dashboard/public/js/geo_fencing.js +++ b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.geo-dashboard/public/js/geo_fencing.js @@ -39,30 +39,30 @@ function loadGeoFencing() { function openTools(id) { lastId = id; - if (drawControl) { - try{ - map.removeControl(drawControl); - } catch(e) { - console.log("error: " + e.message); - } - console.log("removed drawControl"); + if (drawControl) { + try{ + map.removeControl(drawControl); + } catch(e) { + console.log("error: " + e.message); + } + console.log("removed drawControl"); } if (removeAllControl) { - try { - map.removeControl(removeAllControl); - } catch(e) { - console.log("error: " + e.message); - } - console.log("removed removeAllControl"); + try { + map.removeControl(removeAllControl); + } catch(e) { + console.log("error: " + e.message); + } + console.log("removed removeAllControl"); } if (drawnItems) { - try{ - map.removeLayer(drawnItems); - console.log("removing layer"); - } catch(e) { - console.log("error: " + e.message); - } - console.log("removed drawnItems"); + try{ + map.removeLayer(drawnItems); + console.log("removing layer"); + } catch(e) { + console.log("error: " + e.message); + } + console.log("removed drawnItems"); } closeAll(); @@ -84,7 +84,7 @@ function openTools(id) { drawnItems.clearLayers(); if(id == "Prediction"){ $('#predictionResults').animate({width: ['toggle','swing']},200); - toggeled = false; + toggeled = false; } }); @@ -108,7 +108,7 @@ function openTools(id) { // Initialise the FeatureGroup to store editable layers drawnItems = new L.FeatureGroup(); map.addLayer(drawnItems); - + if (id=="WithIn") { // Initialise the draw control and pass it the FeatureGroup of editable layers drawControl = new L.Control.Draw({ @@ -139,30 +139,30 @@ function openTools(id) { } else if (id=="Exit") { // Initialise the draw control and pass it the FeatureGroup of editable layers drawControl = new L.Control.Draw({ - draw: { - polygon: { - allowIntersection: false, // Restricts shapes to simple polygons - drawError: { - color: '#e1e100', // Color the shape will turn when intersects - message: 'Oh snap! you can\'t draw that!' // Message that will show when intersect - }, - shapeOptions: { - color: '#ff0043' - } - }, - rectangle: { - shapeOptions: { - color: '#002bff' - } - }, - polyline: false, - circle: false, // Turns off this drawing tool - marker: false // Markers are not applicable for within geo fencing - }, - edit: { - featureGroup: drawnItems - } - }); + draw: { + polygon: { + allowIntersection: false, // Restricts shapes to simple polygons + drawError: { + color: '#e1e100', // Color the shape will turn when intersects + message: 'Oh snap! you can\'t draw that!' // Message that will show when intersect + }, + shapeOptions: { + color: '#ff0043' + } + }, + rectangle: { + shapeOptions: { + color: '#002bff' + } + }, + polyline: false, + circle: false, // Turns off this drawing tool + marker: false // Markers are not applicable for within geo fencing + }, + edit: { + featureGroup: drawnItems + } + }); } else if(id=="Stationery"){ // Initialise the draw control and pass it the FeatureGroup of editable layers drawControl = new L.Control.Draw({ @@ -220,9 +220,9 @@ function openTools(id) { } }, marker: { - shapeOptions: { - color: '#ff0043' - } + shapeOptions: { + color: '#ff0043' + } } }, edit: { @@ -230,16 +230,16 @@ function openTools(id) { } }); } else if (id =="Prediction") { - drawControl = new L.Control.Draw({ + drawControl = new L.Control.Draw({ draw: { polygon: false, rectangle: false, polyline: false, circle: false, marker: { - shapeOptions: { - color: '#ff0043' - } + shapeOptions: { + color: '#ff0043' + } } }, edit: { @@ -266,10 +266,10 @@ function createPopup(layer,id) { popupTemplate.find('#addTrafficAlert').attr('leaflet_id', layer._leaflet_id); //console.log(">>got here " + id + " " + popupTemplate.find('#addTrafficAlert') + " " + layer._leaflet_id); } else if (id=="Prediction") { - getPrediction(layer._leaflet_id); - return; + getPrediction(layer._leaflet_id); + return; } - + popupTemplate.find('.exportGeoJson').attr('leaflet_id', layer._leaflet_id); popupTemplate.find('.editGeoJson').attr('leaflet_id', layer._leaflet_id); @@ -362,9 +362,9 @@ function viewFence(geoFenceElement,id) { color: '#ff0043' }; geometryShape= new L.circle([geoJson.coordinates[1],geoJson.coordinates[0]], geoJson.radius,circleOptions); - // var marker=new L.marker([geoJson.coordinates[1],geoJson.coordinates[0]]); + // var marker=new L.marker([geoJson.coordinates[1],geoJson.coordinates[0]]); map.addLayer(geometryShape); - // map.addLayer(marker); + // map.addLayer(marker); } else if (geoJson.type=="Polygon") { geoJson.coordinates[0].pop(); // popout the last coordinate set(lat,lng pair) due to circular chain var leafletLatLngs = []; @@ -493,4 +493,3 @@ function viewFenceByData(geoJson, queryName, areaName, stationeryTime, id) { } closeAll(); } - diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.geo-dashboard/public/js/geo_remote.js b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.geo-dashboard/public/js/geo_remote.js index e5894ceee1..b6e5cba7e3 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.geo-dashboard/public/js/geo_remote.js +++ b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.geo-dashboard/public/js/geo_remote.js @@ -281,7 +281,7 @@ function setWithinAlert(leafletId) { responseHandler, function (xhr) { responseHandler(xhr.responseText, xhr.statusText, xhr); }); - viewFenceByData(selectedAreaGeoJson, queryName, areaName, null, 'Within'); + viewFenceByData(selectedAreaGeoJson, queryName, areaName, null, 'WithIn'); } } @@ -414,7 +414,7 @@ function setStationeryAlert(leafletId) { responseHandler, function (xhr) { responseHandler(xhr.responseText, xhr.statusText, xhr); }); - viewFenceByData(selectedProcessedAreaGeoJson, queryName, areaName, time, 'Stationery'); + viewFenceByData(selectedProcessedAreaGeoJson, queryName, stationeryName, time, 'Stationery'); } @@ -563,8 +563,8 @@ function getAlertsHistory(deviceType, deviceId, timeFrom, timeTo) { if (val.values) { val = val.values; } - var msg = deviceType.charAt(0).toUpperCase() + deviceType.slice(1) + - " " + deviceId + " " + val.information.replace("Alerts: ,", "") + " - " + timeSince(val.timeStamp); + var msg = val.information.replace("Alerts: ,", "").charAt(0).toUpperCase() + + val.information.replace("Alerts: ,", "").slice(1) + " - " + timeSince(val.timeStamp); switch (val.state) { case "NORMAL": return; diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.geo-devices/geo-devices.hbs b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.geo-devices/geo-devices.hbs index 2d6476ee0d..bbcae34eea 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.geo-devices/geo-devices.hbs +++ b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.geo-devices/geo-devices.hbs @@ -27,10 +27,853 @@ {{css "css/leaflet.awesome-markers.css" combine=false}} {{/zone}} +
    +
    +
    +
    +{{#if geoServicesEnabled}} +
    +
    +
    +{{/if}} +
    -
    -
    + {{#if geoServicesEnabled}} +
    +
    +
    + Alerts Stream  + Spatial Stream +
    +
    + {{else}} +
    +
    +
    + {{/if}} + + + +
    +
    +
    +
    +
    +
    +
    + + + + + + + + + + + + + + + + + + + + +
    +
    +
    +

    ID

    +
    +
    Information
    +

    + {{#if geoServicesEnabled}} +
    Speed km/h
    +
    Heading
    + + + + {{/if}} +
    +
    + +
    +
    +
    + +
    + +
    +
    +
    + +
    + +
    +
    +
    + +
    + +
    +
    +

    ID

    + +
    +
    Information
    + +

    +
    +
    + +
    +
    +

    ID

    +
    +
    Severity
    + +

    +
    +
    +
    Information
    + +

    +
    +
    + +
    +
    +
    + + + Name of the selected area(e.g. colombo) +
    +
    +
    +
    + +
    +
    + +
    +
    + Export +
    +
    +
    +
    +
    +
    +
    +
    + + + Name of the selected area(e.g. colombo) +
    +
    +
    +
    + +
    +
    + +
    +
    + Export +
    +
    +
    +
    +
    +
    +
    +
    +
    + + + Name of the selected area(e.g. colombo) + + + + + + +
    +
    +
    +
    + +
    +
    + +
    +
    + Export +
    +
    +
    +
    +
    +
    +
    +
    + + + Name of the selected area(e.g. colombo) +
    +
    +
    +
    + +
    +
    + +
    +
    + Export +
    +
    +
    +
    +
    @@ -39,6 +882,7 @@ {{js "js/leaflet/leaflet.markercluster.js" }} {{js "js/leaflet/L.Control.Locate.js" }} {{js "js/leaflet/L.Control.Focus.js" }} + {{js "js/leaflet/L.Control.GeoAlerts.js" }} {{js "js/leaflet/leaflet.groupedlayercontrol.js" }} {{js "js/leaflet/Leaflet.fullscreen.min.js" }} {{js "js/leaflet/Marker.Rotate.js" }} @@ -47,9 +891,68 @@ {{js "js/typeahead.bundle.min.js" }} {{js "js/geo_remote.js" }} {{js "js/app.js" }} + {{js "js/geo_exit_fence.js" }} + {{js "js/geo_within.js" }} + {{js "js/geo_stationary.js" }} + {{js "js/geo_speed.js" }} + + {{!js "js/jquery/jquery-ui.min.js" }} + + + {{js "js/firstTemp.js" }} + + + {{js "js/d3/d3.min.js" }} + {{js "js/d3/c3.min.js" }} + {{js "js/application_options.js" }} + {{js "js/secondTemp.js" }} + + {{js "js/show_alert_in_map.js" }} + + {{js "js/websocket.js" }} + {{js "js/geo_fencing.js" }} {{/zone}} diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.geo-devices/geo-devices.js b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.geo-devices/geo-devices.js new file mode 100644 index 0000000000..fdf3565720 --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.geo-devices/geo-devices.js @@ -0,0 +1,58 @@ +/* + * 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. + */ + +function onRequest(context) { + + var log = new Log("geo-devices.js"); + var devicemgtProps = require("/app/modules/conf-reader/main.js")["conf"]; + var viewModel = {}; + var carbonServer = require("carbon").server; + var device = context.unit.params.device; + var constants = require("/app/modules/constants.js"); + var wsEndpoint = null; + var jwtService = carbonServer.osgiService( + 'org.wso2.carbon.identity.jwt.client.extension.service.JWTClientManagerService'); + var jwtClient = jwtService.getJWTClient(); + var encodedClientKeys = session.get(constants["ENCODED_TENANT_BASED_WEB_SOCKET_CLIENT_CREDENTIALS"]); + var tokenPair = null; + var token = ""; + if (encodedClientKeys) { + var tokenUtil = require("/app/modules/oauth/token-handler-utils.js")["utils"]; + var resp = tokenUtil.decode(encodedClientKeys).split(":"); + if (context.user.domain == "carbon.super") { + tokenPair = jwtClient.getAccessToken(resp[0], resp[1], context.user.username,"default", {}); + if (tokenPair) { + token = tokenPair.accessToken; + wsEndpoint = devicemgtProps["wssURL"].replace("https", "wss") + "/secured-websocket/"; + } + } else { + tokenPair = jwtClient.getAccessToken(resp[0], resp[1], context.user.username + "@" + context.user.domain,"default", {}); + if (tokenPair) { + token = tokenPair.accessToken; + wsEndpoint = devicemgtProps["wssURL"].replace("https", "wss") + "/secured-websocket/t/"+context.user.domain+"/"; + } + + } + + } + viewModel.device = device; + viewModel.wsToken = token; + viewModel.wsEndpoint = wsEndpoint; + viewModel.geoServicesEnabled = devicemgtProps.serverConfig.geoLocationConfiguration.enabled; + return viewModel; +} \ No newline at end of file diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.geo-devices/public/assets/html_templates/modal/exit_alert.html b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.geo-devices/public/assets/html_templates/modal/exit_alert.html new file mode 100644 index 0000000000..de211e778d --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.geo-devices/public/assets/html_templates/modal/exit_alert.html @@ -0,0 +1,52 @@ + + +
    + \ No newline at end of file diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.geo-devices/public/assets/html_templates/modal/proximity_alert.html b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.geo-devices/public/assets/html_templates/modal/proximity_alert.html new file mode 100644 index 0000000000..fdfb662bac --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.geo-devices/public/assets/html_templates/modal/proximity_alert.html @@ -0,0 +1,95 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.geo-devices/public/assets/html_templates/modal/speed_alert.html b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.geo-devices/public/assets/html_templates/modal/speed_alert.html new file mode 100644 index 0000000000..e3a2ecc364 --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.geo-devices/public/assets/html_templates/modal/speed_alert.html @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.geo-devices/public/assets/html_templates/modal/stationery_alert.html b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.geo-devices/public/assets/html_templates/modal/stationery_alert.html new file mode 100644 index 0000000000..7a0431d827 --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.geo-devices/public/assets/html_templates/modal/stationery_alert.html @@ -0,0 +1,83 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.geo-devices/public/assets/html_templates/view_fence_popup.html b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.geo-devices/public/assets/html_templates/view_fence_popup.html new file mode 100644 index 0000000000..671ae1bb3f --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.geo-devices/public/assets/html_templates/view_fence_popup.html @@ -0,0 +1,52 @@ + + + + + + + + +
    +

    +
    +
    + + +
    +
    +
    +
    +

    +
    +
    + + +
    +
    +
    +
    +

    +
    +
    +
    Stationery time(Seconds)N/A
    + + +
    +
    +
    + + \ No newline at end of file diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.geo-devices/public/conf/alerts/Geo-ExecutionPlan-Exit_alert.siddhiql b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.geo-devices/public/conf/alerts/Geo-ExecutionPlan-Exit_alert.siddhiql new file mode 100644 index 0000000000..53902ccfe5 --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.geo-devices/public/conf/alerts/Geo-ExecutionPlan-Exit_alert.siddhiql @@ -0,0 +1,20 @@ +/* Enter a unique ExecutionPlan */ +@Plan:name('$executionPlanName') + +/* Enter a unique description for ExecutionPlan */ +-- @Plan:description('ExecutionPlan') + +/* define streams/tables and write queries here ... */ + +@Import('org.wso2.geo.StandardSpatialEvents:1.0.0') +define stream dataIn (id string, latitude double, longitude double, timeStamp long, type string ,speed float, heading float, eventId string); + +@Export('org.wso2.geo.ProcessedSpatialEvents:1.0.0') +define stream dataOut (id string, latitude double, longitude double, timeStamp long, type string ,speed float, heading float, eventId string, state string, information string); + +from dataIn[geo:within(longitude,latitude,"$geoFenceGeoJSON")==false and id == "$deviceId"]#geodashboard:subscribe() +select id , latitude, longitude,timeStamp, type, speed, heading ,eventId , "ALERTED" as state, "This device is in $areaName restricted area!!!" as information +insert into dataOut; +from dataIn[geo:within(longitude,latitude,"$geoFenceGeoJSON")!=false and id == "$deviceId"] +select id , latitude, longitude,timeStamp, type, speed, heading ,eventId , "NORMAL" as state, "" as information +insert into dataOut; diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.geo-devices/public/conf/alerts/Geo-ExecutionPlan-Proximity_alert.siddhiql b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.geo-devices/public/conf/alerts/Geo-ExecutionPlan-Proximity_alert.siddhiql new file mode 100644 index 0000000000..fb64720391 --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.geo-devices/public/conf/alerts/Geo-ExecutionPlan-Proximity_alert.siddhiql @@ -0,0 +1,140 @@ +/* Enter a unique ExecutionPlan */ +@Plan:name('Geo-ExecutionPlan-Proximity_alert') + +/* Enter a unique description for ExecutionPlan */ +-- @Plan:description('ExecutionPlan') + +/* define streams/tables and write queries here ... */ + +@Import('org.wso2.geo.StandardSpatialEvents:1.0.0') +define stream dataIn (id string, latitude double, longitude double, timeStamp long, type string, speed float, heading float, eventId string ); + +@Export('org.wso2.geo.ProcessedSpatialEvents:1.0.0') +define stream dataOut ( id string, latitude double, longitude double, timeStamp long, type string, speed float, heading float, eventId string, state string, information string ); + +@IndexBy('id') +define table ProximityTable(id string, timeStamp long); + +@IndexBy('id') +define table AlertsTable(id string , proximityWith string, eventId string); + +from dataIn#geodashboard:subscribe() +select id, latitude, longitude, timeStamp, type, speed, heading, eventId +insert into initialStream; + +from initialStream[type == 'STOP'] +select id , latitude, longitude,timeStamp, type, speed, heading ,eventId , "" as proximityInfo ,"false" as isProximity +insert into dataOutStream; + +from initialStream[type != 'STOP'] +select * +insert into objectInitialStream; + +from objectInitialStream#geo:proximity(id,longitude,latitude, $proximityDistance) +select id, latitude, longitude, timeStamp, type, speed, heading, eventId,inCloseProximity,proximityWith +insert into proxymityStream; + +from proxymityStream[AlertsTable.id == proxymityStream.id in AlertsTable] +select id, latitude, longitude, timeStamp, type, speed, heading, eventId,inCloseProximity,proximityWith,true as inAlertTable +insert into innerStreamOne; + +from proxymityStream[not(AlertsTable.id == proxymityStream.id in AlertsTable)] +select id, latitude, longitude, timeStamp, type, speed, heading, eventId,inCloseProximity,proximityWith,false as inAlertTable +insert into innerStreamOne; + +from proxymityStream[AlertsTable.id == proxymityStream.proximityWith in AlertsTable] +select id, latitude, longitude, timeStamp, type, speed, heading, eventId,inCloseProximity,proximityWith,true as inAlertTable +insert into innerStreamSeven; + +from proxymityStream[not(AlertsTable.id == proxymityStream.proximityWith in AlertsTable)] +select id, latitude, longitude, timeStamp, type, speed, heading, eventId,inCloseProximity,proximityWith,false as inAlertTable +insert into innerStreamSeven; + +from innerStreamOne[inCloseProximity == true AND not(inAlertTable)] +select id,str:concat(",",proximityWith) as proximityWith , eventId +insert into AlertsTable; + +from innerStreamSeven[inCloseProximity == true AND not(inAlertTable)] +select proximityWith as id,str:concat(",",id) as proximityWith , eventId +insert into AlertsTable; + +from innerStreamOne[innerStreamOne.inCloseProximity == true AND inAlertTable]#window.length(0) join AlertsTable +on innerStreamOne.id == AlertsTable.id +select innerStreamOne.id as id, str:concat(",", innerStreamOne.proximityWith, AlertsTable.proximityWith) as proximityWith, innerStreamOne.eventId as eventId +insert into updateStream; + +from innerStreamSeven[innerStreamSeven.inCloseProximity == true AND inAlertTable]#window.length(0) join AlertsTable +on innerStreamSeven.proximityWith == AlertsTable.id +select innerStreamSeven.proximityWith as id, str:concat(",", innerStreamSeven.id, AlertsTable.proximityWith) as proximityWith, innerStreamSeven.eventId as eventId +insert into updateStream; + +from innerStreamOne[innerStreamOne.inCloseProximity == false AND inAlertTable]#window.length(0) join AlertsTable +on innerStreamOne.id == AlertsTable.id +select innerStreamOne.id as id, str:replaceAll(AlertsTable.proximityWith, str:concat(",", innerStreamOne.proximityWith), "") as proximityWith, innerStreamOne.eventId as eventId +insert into updateStream; + +from innerStreamSeven[innerStreamSeven.inCloseProximity == false AND inAlertTable]#window.length(0) join AlertsTable +on innerStreamSeven.proximityWith == AlertsTable.id +select innerStreamSeven.proximityWith as id, str:replaceAll(AlertsTable.proximityWith, str:concat(",", innerStreamSeven.id), "") as proximityWith, innerStreamSeven.eventId as eventId +insert into updateStream; + +from updateStream +select * +update AlertsTable + on id== AlertsTable.id; + +from updateStream[proximityWith == ""] +delete AlertsTable + on id== AlertsTable.id; + +from objectInitialStream[AlertsTable.id == objectInitialStream.id in AlertsTable] +select id, latitude, longitude, timeStamp, type, speed, heading, eventId, true as inAlertTable +insert into publishStream; + +from objectInitialStream[not(AlertsTable.id == objectInitialStream.id in AlertsTable)] +select id, latitude, longitude, timeStamp, type, speed, heading, eventId, false as inAlertTable +insert into publishStream; + +from publishStream[inAlertTable == true]#window.length(0) join AlertsTable +on publishStream.id== AlertsTable.id +select publishStream.id as id, publishStream.latitude as latitude, publishStream.longitude as longitude, publishStream.timeStamp as timeStamp, publishStream.type as type, publishStream.speed as speed, publishStream.heading as heading, publishStream.eventId as eventId, AlertsTable.proximityWith as proximityInfo +insert into innerStreamTwo; + +from publishStream[inAlertTable == false] +delete ProximityTable on ProximityTable.id==id; + +from publishStream[inAlertTable == false] +select id , latitude, longitude,timeStamp, type, speed, heading ,eventId , "" as proximityInfo ,"false" as isProximity +insert into dataOutStream; + +from innerStreamTwo[ProximityTable.id == innerStreamTwo.id in ProximityTable] +insert into innerStreamThree; + +from innerStreamThree#window.length(0) join ProximityTable +on innerStreamThree.id == ProximityTable.id +select innerStreamThree.id , innerStreamThree.latitude, innerStreamThree.longitude,innerStreamThree.timeStamp, innerStreamThree.type, innerStreamThree.speed, innerStreamThree.heading ,innerStreamThree.eventId, ProximityTable.timeStamp as storedTime, innerStreamThree.proximityInfo as proximityInfo +insert into innerStreamFour; + +from innerStreamFour[(timeStamp - storedTime) >= $proximityTime] +select id , latitude, longitude,timeStamp, type, speed, heading ,eventId ,proximityInfo,"true" as isProximity +insert into dataOutStream; + +from innerStreamFour[(timeStamp - storedTime) < $proximityTime] +select id , latitude, longitude,timeStamp, type, speed, heading ,eventId , proximityInfo ,"false" as isProximity +insert into dataOutStream; + +from innerStreamTwo[not(ProximityTable.id == innerStreamTwo.id in ProximityTable)] +select innerStreamTwo.id, innerStreamTwo.timeStamp +insert into ProximityTable; + +from innerStreamTwo[not(ProximityTable.id == innerStreamTwo.id in ProximityTable)] +select id , latitude, longitude,timeStamp, type, speed, heading ,eventId , "" as proximityInfo ,"false" as isProximity +insert into dataOutStream; + +from dataOutStream[isProximity == 'true'] +select id, latitude, longitude, timeStamp, type, speed, heading, eventId,"WARNING" as state,str:concat("Proximity with "," ",proximityInfo) as information +insert into dataOut; + +from dataOutStream[isProximity == 'false'] +select id , latitude, longitude,timeStamp, type, speed, heading ,eventId ,"NORMAL" as state,"" as information +insert into dataOut; \ No newline at end of file diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.geo-devices/public/conf/alerts/Geo-ExecutionPlan-Speed_alert.siddhiql b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.geo-devices/public/conf/alerts/Geo-ExecutionPlan-Speed_alert.siddhiql new file mode 100644 index 0000000000..65dad468d5 --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.geo-devices/public/conf/alerts/Geo-ExecutionPlan-Speed_alert.siddhiql @@ -0,0 +1,20 @@ +/* Enter a unique ExecutionPlan */ +@Plan:name('Geo-ExecutionPlan-Speed---$deviceId_alert') + +/* Enter a unique description for ExecutionPlan */ +-- @Plan:description('ExecutionPlan') + +/* define streams/tables and write queries here ... */ + +@Import('org.wso2.geo.StandardSpatialEvents:1.0.0') +define stream dataIn (id string, latitude double, longitude double, timeStamp long, type string, speed float, heading float, eventId string); + +@Export('org.wso2.geo.ProcessedSpatialEvents:1.0.0') +define stream dataOut (id string, latitude double, longitude double, timeStamp long, type string, speed float, heading float, eventId string, state string, information string); + +from dataIn[speed >= $speedAlertValue and id == "$deviceId"]#geodashboard:subscribe() +select id , latitude, longitude,timeStamp, type ,speed, heading ,eventId , "ALERTED" as state, "This device movement is not normal!!" as information +insert into dataOut; +from dataIn[speed < $speedAlertValue and id == "$deviceId"] +select id , latitude, longitude,timeStamp, type ,speed, heading ,eventId , "NORMAL" as state, "This device movement is normal" as information +insert into dataOut; diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.geo-devices/public/conf/alerts/Geo-ExecutionPlan-Stationery_alert.siddhiql b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.geo-devices/public/conf/alerts/Geo-ExecutionPlan-Stationery_alert.siddhiql new file mode 100644 index 0000000000..46bfbfe2e3 --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.geo-devices/public/conf/alerts/Geo-ExecutionPlan-Stationery_alert.siddhiql @@ -0,0 +1,89 @@ +/* Enter a unique ExecutionPlan */ +@Plan:name('$executionPlanName') + +/* Enter a unique description for ExecutionPlan */ +-- @Plan:description('ExecutionPlan') + +/* define streams/tables and write queries here ... */ + +@Import('org.wso2.geo.StandardSpatialEvents:1.0.0') +define stream dataIn (id string, latitude double, longitude double, timeStamp long, type string ,speed float, heading float, eventId string); + + +@Export('org.wso2.geo.ProcessedSpatialEvents:1.0.0') +define stream dataOut (id string, latitude double, longitude double, timeStamp long, type string ,speed float, heading float, eventId string, state string, information string); + +@IndexBy('id') +define table StationeryTable(id string, timeStamp long); + +@IndexBy('id') +define table AlertsTable(id string, stationary bool); + +from dataIn#geodashboard:subscribe() +select id, latitude, longitude, timeStamp, type, speed, heading, eventId,geo:within(longitude,latitude,"$geoFenceGeoJSON") as isWithin +insert into innerStreamOne; + +from innerStreamOne[isWithin == false] +delete StationeryTable on StationeryTable.id==id; + +from innerStreamOne[isWithin == false] +select id , latitude, longitude,timeStamp, type, speed, heading ,eventId , "false" as isStationary +insert into dataOutStream; + +from innerStreamOne[isWithin == true]#geo:stationary(id,longitude,latitude, $fluctuationRadius) +select id, latitude, longitude, timeStamp, type, speed, heading, eventId,stationary +insert into innerStreamTwo; + +from innerStreamTwo[innerStreamTwo.stationary == true] +select innerStreamTwo.id, innerStreamTwo.stationary +insert into AlertsTable; + +from innerStreamTwo[innerStreamTwo.stationary == false] +delete AlertsTable on AlertsTable.id==id; + +from innerStreamTwo[innerStreamTwo.stationary == false] +delete StationeryTable on StationeryTable.id==id; + +from innerStreamOne[isWithin == true AND not(AlertsTable.id == innerStreamOne.id in AlertsTable)] +select id , latitude, longitude,timeStamp, type, speed, heading ,eventId , "false" as isStationary +insert into dataOutStream; + +from innerStreamOne[isWithin == true AND AlertsTable.id == innerStreamOne.id in AlertsTable] +insert into innerStreamThree; + +from innerStreamThree#window.length(0) join AlertsTable +on innerStreamThree.id == AlertsTable.id +select innerStreamThree.id , innerStreamThree.latitude, innerStreamThree.longitude,innerStreamThree.timeStamp, innerStreamThree.type, innerStreamThree.speed, innerStreamThree.heading ,innerStreamThree.eventId +insert into innerStreamFour; + +from innerStreamFour[not(StationeryTable.id == innerStreamFour.id in StationeryTable)] +select innerStreamFour.id, innerStreamFour.timeStamp +insert into StationeryTable; + +from innerStreamOne[isWithin == true AND not(StationeryTable.id == innerStreamOne.id in StationeryTable)] +select id , latitude, longitude,timeStamp, type, speed, heading ,eventId , "false" as isStationary +insert into dataOutStream; + +from innerStreamOne[isWithin == true AND StationeryTable.id == innerStreamOne.id in StationeryTable] +insert into innerStreamFive; + +from innerStreamFive#window.length(0) join StationeryTable +on innerStreamFive.id == StationeryTable.id +select innerStreamFive.id , innerStreamFive.latitude, innerStreamFive.longitude,innerStreamFive.timeStamp, innerStreamFive.type, innerStreamFive.speed, innerStreamFive.heading ,innerStreamFive.eventId, StationeryTable.timeStamp as storedTime +insert into innerStreamSix; + +from innerStreamSix[(timeStamp - storedTime) >= $stationeryTime] +select id , latitude, longitude,timeStamp, type, speed, heading ,eventId ,"true" as isStationary +insert into dataOutStream; + +from innerStreamSix[(timeStamp - storedTime) < $stationeryTime] +select id , latitude, longitude,timeStamp, type, speed, heading ,eventId ,"false" as isStationary +insert into dataOutStream; + +from dataOutStream[isStationary == 'true'] +select id ,latitude, longitude,timeStamp, type, speed, heading ,eventId ,"ALERTED" as state, "This device is in $stationeryName area!!!" as information +insert into dataOut; + +from dataOutStream[isStationary == 'false'] +select id , latitude, longitude,timeStamp, type, speed, heading ,eventId ,"NORMAL" as state,"" as information +insert into dataOut; \ No newline at end of file diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.geo-devices/public/conf/alerts/Geo-ExecutionPlan-Traffic_alert.siddhiql b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.geo-devices/public/conf/alerts/Geo-ExecutionPlan-Traffic_alert.siddhiql new file mode 100644 index 0000000000..5e6bb5b1a8 --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.geo-devices/public/conf/alerts/Geo-ExecutionPlan-Traffic_alert.siddhiql @@ -0,0 +1,17 @@ +/* Enter a unique ExecutionPlan */ +@Plan:name('$executionPlanName') + +/* Enter a unique description for ExecutionPlan */ +-- @Plan:description('ExecutionPlan') + +/* define streams/tables and write queries here ... */ + +@Import('rawGeoStream:1.0.0') +define stream dataIn (id string, timeStamp long, geometry string, state string, information string); + +@Export('AlertsNotifications:1.0.0') +define stream dataOut (id string, state string, information string, timeStamp long, latitude double, longitude double); + +from dataIn[geo:intersects(geometry, "$geoFenceGeoJSON")==true and geodashboard:needToNotify(id, str:concat(information, state), "sendFirst") == true and id == $deviceId] +select id, state, str:concat("Traffic alert in $areaName. State: ", state, " ", information) as information, timeStamp, 0.0 as latitude, 0.0 as longitude +insert into dataOut \ No newline at end of file diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.geo-devices/public/conf/alerts/Geo-ExecutionPlan-Within_alert.siddhiql b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.geo-devices/public/conf/alerts/Geo-ExecutionPlan-Within_alert.siddhiql new file mode 100644 index 0000000000..b58fd59e33 --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.geo-devices/public/conf/alerts/Geo-ExecutionPlan-Within_alert.siddhiql @@ -0,0 +1,20 @@ +/* Enter a unique ExecutionPlan */ +@Plan:name('$executionPlanName') + +/* Enter a unique description for ExecutionPlan */ +-- @Plan:description('ExecutionPlan') + +/* define streams/tables and write queries here ... */ + +@Import('org.wso2.geo.StandardSpatialEvents:1.0.0') +define stream dataIn (id string, latitude double, longitude double, timeStamp long, type string ,speed float, heading float, eventId string); + +@Export('org.wso2.geo.ProcessedSpatialEvents:1.0.0') +define stream dataOut (id string, latitude double, longitude double, timeStamp long, type string ,speed float, heading float, eventId string, state string, information string); + +from dataIn[geo:within(longitude,latitude,"$geoFenceGeoJSON")==true and id == "$deviceId"]#geodashboard:subscribe() +select id , latitude, longitude,timeStamp, type, speed, heading ,eventId , "ALERTED" as state, "This device is in $areaName restricted area!!!" as information +insert into dataOut; +from dataIn[geo:within(longitude,latitude,"$geoFenceGeoJSON")!=true and id == "$deviceId"] +select id , latitude, longitude,timeStamp, type, speed, heading ,eventId , "NORMAL" as state, "" as information +insert into dataOut; diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.geo-devices/public/css/app.css b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.geo-devices/public/css/app.css index 086e80f550..2cfec651d3 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.geo-devices/public/css/app.css +++ b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.geo-devices/public/css/app.css @@ -128,6 +128,25 @@ input[type="radio"], input[type="checkbox"] { padding: 5px 10px; } +.tab-actions .action-btn.filter.geo-alert { + padding: 10px 15px; + background-color: #ebebeb; + float: left; + cursor: pointer; + position: relative; + margin-left: 10px; + margin-bottom: 10px; +} + +.tab-actions .action-btn.filter.geo-tools { + padding: 10px 15px; + background-color: #ebebeb; + float: right; + cursor: pointer; + position: relative; + margin-left: 10px; + margin-bottom: 10px; +} /* diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.geo-devices/public/js/app.js b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.geo-devices/public/js/app.js index 3a4c73e122..0a702b40b6 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.geo-devices/public/js/app.js +++ b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.geo-devices/public/js/app.js @@ -33,16 +33,22 @@ var map; var geoClusters; var markersLayer = new L.LayerGroup(); var popupContent; +var clusterLat; +var clusterLong; +var lastSeen; +var geoFencingEnabled; var zoomLevel = 15; var tileSet = "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"; var attribution = "© OpenStreetMap contributors"; -function initialLoad() { +function initialLoad(geoFencingEnabled) { + window.geoFencingEnabled = geoFencingEnabled; if (document.getElementById('map') == null) { setTimeout(initialLoad, 500); // give everything some time to render } else { initializeMap(); + processAfterInitializationMap(); $("#loading").hide(); } } @@ -65,6 +71,7 @@ function initializeMap() { maxNativeZoom: 18 }); L.tileLayer(tileSet, {attribution: attribution}).addTo(map); + markersLayer.clearLayers(); markersLayer.addTo(map); showMarkersOnChange(); @@ -86,6 +93,39 @@ function initializeMap() { $("a[href='#left_side_pannel']").trigger('click'); } +function processAfterInitializationMap() { + attributionControl = L.control({ + position: "bottomright" + }); + attributionControl.onAdd = function (map) { + var div = L.DomUtil.create("div", "leaflet-control-attribution"); + div.innerHTML = "Attribution"; + return div; + }; + map.addControl(L.control.fullscreen({position: 'bottomright'})); + + geoAlertsBar = L.control.geoAlerts({position: 'topright'}); + if (geoFencingEnabled) { + map.addControl(geoAlertsBar); + } + + groupedOverlays = { + "Web Map Service layers": {} + }; + + layerControl = L.control.groupedLayers(baseLayers, groupedOverlays, { + collapsed: true, + position: 'bottomleft' + }).addTo(map); + + if (geoFencingEnabled) { + var alertsFromDate = new Date(); + var toDate = new Date(); + alertsFromDate.setHours(alertsFromDate.getHours() - 24); //last 24 hours + getAlertsHistory(alertsFromDate.valueOf(), toDate.valueOf()); + }; +} + var showMarkesOnZoomEnd = function (zoomLevel) { if(map.getZoom()===zoomLevel){ @@ -127,14 +167,17 @@ function geoGridControl(){ geoClusterMarker(count,cluster.coordinates.latitude,cluster.coordinates.longitude, cluster.southWestBound.latitude, cluster.northEastBound.latitude,cluster.southWestBound.longitude,cluster.northEastBound.longitude, - cluster.deviceIdentification,cluster.deviceType); + cluster.deviceIdentification,cluster.deviceType, cluster.lastSeen); } } } function geoClusterMarker(count, clusterLat, clusterLong, minLat, maxLat, minLong, maxLong,deviceIdentification, - deviceType) { + deviceType, lastSeen) { + window.clusterLat = clusterLat; + window.clusterLong = clusterLong; + window.lastSeen = lastSeen; var deviceMarker = L.AwesomeMarkers.icon({ icon: ' ', markerColor: 'blue' @@ -180,17 +223,32 @@ function handleMarkerEvents(event,extra_data,marker) { } -var devicePopupManagement= function(deviceName, deviceType, deviceIdentifier,deviceStatus,deviceOwner){ +var devicePopupManagement= function(deviceName, deviceType, deviceIdentifier,deviceStatus,deviceOwner) { + if (!geoFencingEnabled) { + var deviceMgtUrl = "/devicemgt/device/"; + var html1 = '
    '; + var html2 = '

    ' + '' + deviceName + '' + '

    '; + var html3 = '

    ' + 'Type : ' + deviceType + '

    '; + var html4 = '

    ' + 'Status : ' + deviceStatus + '

    '; + var html5 = '

    ' + 'Owner : ' + deviceOwner + '

    '; + var html6 = '
    '; + var html = html1 + html2 + html3 + html4 + html5 + html6; + return html; + } + + var popupTemplate = $('#markerPopup'); + var fromDate = new Date(); + fromDate.setHours(fromDate.getHours() - 2); + var toDate = new Date(); + var tableData = getAnalyticsData(deviceIdentifier,deviceType,fromDate.valueOf(),toDate.valueOf()); + var data = tableData[tableData.length-1]; + + popupTemplate.find('#objectId').html(deviceIdentifier); + popupTemplate.find('#information').html(data.values.information); + popupTemplate.find('#speed').html(Math.round(data.values.speed * 10) / 10); + popupTemplate.find('#heading').html(angleToHeading(data.values.heading)); - var deviceMgtUrl= "/devicemgt/device/"; - var html1='
    '; - var html2 = '

    '+'' + deviceName + ''+'

    ' ; - var html3 = '

    '+'Type : '+ deviceType+'

    '; - var html4 = '

    '+'Status : '+deviceStatus+'

    '; - var html5 = '

    '+ 'Owner : ' + deviceOwner + '

    '; - var html6='
    '; - var html=html1+html2+html3+html4+html5+html6; - return html; + return popupTemplate.html(); }; var devicePopupContentBackEndCall = function(type,deviceIdentification,marker,callback){ @@ -212,3 +270,198 @@ var successCallBackDeviceDetails=function(device){ popupContent = devicePopupManagement(deviceName,deviceType,deviceIdentifier,deviceStatus,deviceOwner); } + +function getAnalyticsData(deviceId, deviceType, timeFrom, timeTo) { + var tableData = []; + var serviceUrl = '/api/device-mgt/v1.0/geo-services/stats/' + deviceType + '/' + deviceId + '?from=' + timeFrom + '&to=' + timeTo; + invokerUtil.get(serviceUrl, + function (data) { + if(data === "") { + showCurrentLocation(deviceId, deviceType, tableData); + } + tableData = JSON.parse(data); + if (tableData.length === 0) { + showCurrentLocation(deviceId, deviceType, tableData); + } + }, function (message) { + showCurrentLocation(deviceId, deviceType, tableData); + }); + return tableData; +} + +function showRecentAlertsHistory() { + if (geoFencingEnabled) { + var alertsFromDate = new Date(); + var toDate = new Date(); + alertsFromDate.setHours(alertsFromDate.getHours() - 2); //last 24 hours + getAlertsHistory(alertsFromDate.valueOf(), toDate.valueOf()); + } + + if (speedGraphControl) { + setTimeout(function () { + createChart(); + chart.load({columns: [0]}); //TODO: Somehow get device speed history here + }, 100); + } + + noty({text: "Showing last two hours geo history", type: "information"}); +} + +function showAlertsHistory(timeFrom, timeTo) { + if (!timeFrom) { + notifyError('No start time provided to show history. Please provide a suitable value' + timeFrom); + } else if (!timeTo) { + notifyError('No end time provided to show history. Please provide a suitable value' + timeTo); + } else { + $('#dateRangePopup').dialog('close'); + disableRealTime(); + isBatchModeOn = true; + getAlertsHistory(new Date($('#timeFromCal').val()).getTime(), new Date($('#timeToCal').val()).getTime()); + + if (speedGraphControl) { + setTimeout(function () { + createChart(); + chart.load({columns: [0]}); //TODO: Somehow get device speed history here + }, 100); + } + } +} + +function createGeoToolListItem(link, text, icon, menuRoot, alert) { + var listItem = $("
    ", { class: 'action-btn filter'}).appendTo(menuRoot); + var anchor = $("", {href: link, text: ' ' + text}).appendTo(listItem); + if (alert == 'Exit') { + anchor.attr('data-toggle', 'modal'); + anchor.attr('data-target', '#modalExit'); + } else if (alert == 'Within') { + anchor.attr('data-toggle', 'modal'); + anchor.attr('data-target', '#modalWithin'); + } else if (alert == 'Stationery') { + anchor.attr('data-toggle', 'modal'); + anchor.attr('data-target', '#modalStationery'); + } else if (alert == 'Speed') { + anchor.attr('data-toggle', 'modal'); + anchor.attr('data-target', '#modalSpeed'); + } + $("", {class: icon}).prependTo(anchor); + return listItem; +} + +var chart; +function createChart() { + chart = c3.generate({ + bindto: '#chart_div', + data: { + columns: [ + ['speed'] + ] + }, + subchart: { + show: true + }, + axis: { + y: { + label: { + text: 'Speed', + position: 'outer-middle' + } + } + }, + legend: { + show: false + } + }); +} + +function notifyError(message) { + noty({text: message, type: "error"}); +} + +function enableRealTime(geoFencingEnabled) { + $("#realTimeShow").hide(); + $(".geo-alert").show(); + isBatchModeOn = false; + initializeGeoLocation(geoFencingEnabled); +} + +function disableRealTime(){ + $(".geo-alert").hide(); + $("#realTimeShow").show(); +} + +function showCurrentLocation(tableData){ + var location = {}; + location.latitude = clusterLat; + location.longitude = clusterLong; + location.updatedTime = lastSeen; + location.id = deviceId; + location.values = {}; + location.values.id = deviceId; + location.values.information = "Last seen " + timeSince(new Date(location.updatedTime)); + location.values.notify = false; + location.values.speed = 0; + location.values.heading = 0; + location.values.state = "NORMAL"; + location.values.longitude = location.longitude; + location.values.latitude = location.latitude; + location.timestamp = location.updatedTime; + location.values.timeStamp = location.updatedTime; + location.values.type = deviceType; + location._version = "1.0.0"; + tableData.push(location); +} + +function formatDate(date) { + var hours = date.getHours(); + var minutes = date.getMinutes(); + var ampm = hours >= 12 ? 'pm' : 'am'; + hours = hours % 12; + hours = hours ? hours : 12; // the hour '0' should be '12' + minutes = minutes < 10 ? '0'+minutes : minutes; + var strTime = hours + ':' + minutes + ' ' + ampm; + return date.getDate() + "/" + date.getMonth()+1 + "/" + date.getFullYear() + " " + strTime; +} + +function timeSince(date) { + + if (!date) { + return "time is unknown"; + } + + var seconds = Math.floor((new Date() - date) / 1000); + var intervalType; + + var interval = Math.floor(seconds / 31536000); + if (interval >= 1) { + intervalType = 'year'; + } else { + interval = Math.floor(seconds / 2592000); + if (interval >= 1) { + intervalType = 'month'; + } else { + interval = Math.floor(seconds / 86400); + if (interval >= 1) { + intervalType = 'day'; + } else { + interval = Math.floor(seconds / 3600); + if (interval >= 1) { + intervalType = "hour"; + } else { + interval = Math.floor(seconds / 60); + if (interval >= 1) { + intervalType = "minute"; + } else { + interval = seconds; + intervalType = "second"; + } + } + } + } + } + + if (interval > 1 || interval === 0) { + intervalType += 's'; + } + + return interval + ' ' + intervalType + ' ago'; +} \ No newline at end of file diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.geo-devices/public/js/application_options.js b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.geo-devices/public/js/application_options.js new file mode 100644 index 0000000000..cd1915e67a --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.geo-devices/public/js/application_options.js @@ -0,0 +1,77 @@ +/* + * 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. + */ +var ApplicationOptions = { + colors: { + states: { + NORMAL: 'blue', + WARNING: 'blue', + OFFLINE: 'grey', + ALERTED: 'red', + UNKNOWN: 'black' + }, + application: { + header: 'grey' + } + }, + constance:{ + CEP_WEB_SOCKET_OUTPUT_ADAPTOR_NAME: 'iot.per.device.stream.geo.FusedSpatialEvent', + CEP_ON_ALERT_WEB_SOCKET_OUTPUT_ADAPTOR_NAME: 'org.wso2.geo.AlertsNotifications', + CEP_Traffic_STREAM_WEB_SOCKET_OUTPUT_ADAPTOR_NAME: 'DefaultWebsocketOutputAdaptorOnTrafficStream', + CEP_WEB_SOCKET_OUTPUT_ADAPTOR_WEBAPP_NAME: 'secured-websocket', + TENANT_INDEX: 't', + COLON : ':', + PATH_SEPARATOR : '/', + VERSION: '1.0.0', + SPEED_HISTORY_COUNT: 20, + NOTIFY_INFO_TIMEOUT: 1000, + NOTIFY_SUCCESS_TIMEOUT: 1000, + NOTIFY_WARNING_TIMEOUT: 3000, + NOTIFY_DANGER_TIMEOUT: 5000 + }, + messages:{ + app:{ + + } + }, + leaflet: { + iconUrls: { + //TODO path needs to be changed + normalMovingIcon: '/img/markers/object-types/default/moving/alerted.png', + alertedMovingIcon: '/img/markers/moving/arrow_alerted.png', + offlineMovingIcon: '/img/markers/moving/arrow_offline.png', + warningMovingIcon: '/img/markers/moving/arrow_warning.png', + defaultMovingIcon: '/img/markers/moving/arrow_normal.png', + + normalNonMovingIcon: '/img/markers/non_moving/dot_normal.png', + alertedNonMovingIcon: '/img/markers/non_moving/dot_alerted.png', + offlineNonMovingIcon: '/img/markers/non_moving/dot_offline.png', + warningNonMovingIcon: '/img/markers/non_moving/dot_warning.png', + defaultNonMovingIcon: '/img/markers/non_moving/dot_normal.png', + + normalPlaceIcon: '/img/markers/places/marker-icon.png', + alertedPlaceIcon: '/img/markers/places/redMarker.png', + offlinePlaceIcon: '/img/markers/places/ashMarker.png', + warningPlaceIcon: '/img/markers/places/pinkMarker.png', + defaultPlaceIcon: '/img/markers/places/marker-icon.png', + + defaultIcon: '/img/markers/moving/default_icons/marker-icon.png', + resizeIcon: '/img/markers/resize.png', + stopIcon: '/img/markers/stopIcon.png' + } + } +}; diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.geo-devices/public/js/d3/C3_LICENSE b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.geo-devices/public/js/d3/C3_LICENSE new file mode 100644 index 0000000000..29ce9cb0ad --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.geo-devices/public/js/d3/C3_LICENSE @@ -0,0 +1,20 @@ +The MIT License (MIT) + +Copyright (c) 2013 Masayuki Tanaka + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.geo-devices/public/js/d3/D3_LICENSE b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.geo-devices/public/js/d3/D3_LICENSE new file mode 100644 index 0000000000..83013469b9 --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.geo-devices/public/js/d3/D3_LICENSE @@ -0,0 +1,26 @@ +Copyright (c) 2010-2014, Michael Bostock +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* The name Michael Bostock may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL MICHAEL BOSTOCK BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.geo-devices/public/js/d3/c3.min.js b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.geo-devices/public/js/d3/c3.min.js new file mode 100644 index 0000000000..cdbf2d5a55 --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.geo-devices/public/js/d3/c3.min.js @@ -0,0 +1,4 @@ +!function(a){"use strict";function b(a){var b=this.internal=new c(this);b.loadConfig(a),b.init(),function d(a,b,c){for(var e in a)b[e]=a[e].bind(c),Object.keys(a[e]).length>0&&d(a[e],b[e],c)}(e,this,this)}function c(b){var c=this;c.d3=a.d3?a.d3:"undefined"!=typeof require?require("d3"):void 0,c.api=b,c.config=c.getDefaultConfig(),c.data={},c.cache={},c.axes={}}function d(a,b){function c(a,b){a.attr("transform",function(a){return"translate("+Math.ceil(b(a)+s)+", 0)"})}function d(a,b){a.attr("transform",function(a){return"translate(0,"+Math.ceil(b(a))+")"})}function e(a){var b=a[0],c=a[a.length-1];return c>b?[b,c]:[c,b]}function f(a){var b,c,d=[];if(a.ticks)return a.ticks.apply(a,k);for(c=a.domain(),b=Math.ceil(c[0]);b0&&d[0]>0&&d.unshift(d[0]-(d[1]-d[0])),d}function g(){var a,c=m.copy();return b&&(a=m.domain(),c.domain([a[0],a[1]-1])),c}function h(a){return j?j(a):a}function i(i){i.each(function(){function i(a){var b=m(a)+s;return B[0]=0&&C.select(this).style("display",b%z?"none":"block")})}else A.svg.selectAll("."+h.axisX+" .tick text").style("display","block");!D.axis_rotated&&D.axis_x_tick_rotate&&A.rotateTickText(A.axes.x,b.axisX,D.axis_x_tick_rotate),m=A.generateDrawArea?A.generateDrawArea(E,!1):void 0,n=A.generateDrawBar?A.generateDrawBar(F):void 0,o=A.generateDrawLine?A.generateDrawLine(G,!1):void 0,p=A.generateXYForText(F,!0),q=A.generateXYForText(F,!1),A.subY.domain(A.y.domain()),A.subY2.domain(A.y2.domain()),A.tooltip.style("display","none"),A.updateXgridFocus(),B.select("text."+h.text+"."+h.empty).attr("x",A.width/2).attr("y",A.height/2).text(D.data_empty_label_text).transition().style("opacity",I.length?0:1),A.redrawGrid(r,c),A.redrawRegion(r),A.redrawBar(t),A.redrawLine(t),A.redrawArea(t),D.point_show&&A.redrawCircle(),A.hasDataLabel()&&A.redrawText(t),A.redrawArc&&A.redrawArc(r,t,i),A.redrawSubchart&&A.redrawSubchart(d,b,r,t,E,F,G),B.selectAll("."+h.selectedCircles).filter(A.isBarType.bind(A)).selectAll("circle").remove(),D.interaction_enabled&&A.redrawEventRect(),C.transition().duration(r).each(function(){var b=[];A.addTransitionForBar(b,n),A.addTransitionForLine(b,o),A.addTransitionForArea(b,m),D.point_show&&A.addTransitionForCircle(b,K,L),A.addTransitionForText(b,p,q,a.flow),A.addTransitionForRegion(b),A.addTransitionForGrid(b),a.flow&&(v=A.generateWait(),b.forEach(function(a){v.add(a)}),w=A.generateFlow({targets:I,flow:a.flow,duration:r,drawBar:n,drawLine:o,drawArea:m,cx:K,cy:L,xv:J,xForText:p,yForText:q}))}).call(v||function(){},w||function(){}),A.mapToIds(A.data.targets).forEach(function(a){A.withoutFadeIn[a]=!0}),A.updateZoom&&A.updateZoom()},f.updateAndRedraw=function(a){var b,c=this,d=c.config;a=a||{},a.withTransition=s(a,"withTransition",!0),a.withTransform=s(a,"withTransform",!1),a.withLegend=s(a,"withLegend",!1),a.withUpdateXDomain=!0,a.withUpdateOrgXDomain=!0,a.withTransitionForExit=!1,a.withTransitionForTransform=s(a,"withTransitionForTransform",a.withTransition),c.updateSizes(),a.withLegend&&d.legend_show||(b=c.generateAxisTransitions(a.withTransitionForAxis?d.transition_duration:0),c.updateScales(),c.updateSvgSize(),c.transformAll(a.withTransitionForTransform,b)),c.redraw(a,b)},f.isTimeSeries=function(){return"timeseries"===this.config.axis_x_type},f.isCategorized=function(){return this.config.axis_x_type.indexOf("categor")>=0},f.isCustomX=function(){var a=this,b=a.config;return!a.isTimeSeries()&&(b.data_x||r(b.data_xs))},f.getTranslate=function(a){var b,c,d=this,e=d.config;return"main"===a?(b=o(d.margin.left),c=o(d.margin.top)):"context"===a?(b=o(d.margin2.left),c=o(d.margin2.top)):"legend"===a?(b=d.margin3.left,c=d.margin3.top):"x"===a?(b=0,c=e.axis_rotated?0:d.height):"y"===a?(b=0,c=e.axis_rotated?d.height:0):"y2"===a?(b=e.axis_rotated?0:d.width,c=e.axis_rotated?1:0):"subx"===a?(b=0,c=e.axis_rotated?0:d.height2):"arc"===a&&(b=d.arcWidth/2,c=d.arcHeight/2),"translate("+b+","+c+")"},f.initialOpacity=function(a){return null!==a.value&&this.withoutFadeIn[a.id]?1:0},f.opacityForCircle=function(a){var b=this;return i(a.value)?b.isScatterType(a)?.5:1:0},f.opacityForText=function(){return this.hasDataLabel()?1:0},f.xx=function(a){return a?this.x(a.x):null},f.xv=function(a){var b=this;return Math.ceil(b.x(b.isTimeSeries()?b.parseDate(a.value):a.value))},f.yv=function(a){var b=this,c=a.axis&&"y2"===a.axis?b.y2:b.y;return Math.ceil(c(a.value))},f.subxx=function(a){return a?this.subX(a.x):null},f.transformMain=function(a,b){var c,d,e,f=this;b&&b.axisX?c=b.axisX:(c=f.main.select("."+h.axisX),a&&(c=c.transition())),b&&b.axisY?d=b.axisY:(d=f.main.select("."+h.axisY),a&&(d=d.transition())),b&&b.axisY2?e=b.axisY2:(e=f.main.select("."+h.axisY2),a&&(e=e.transition())),(a?f.main.transition():f.main).attr("transform",f.getTranslate("main")),c.attr("transform",f.getTranslate("x")),d.attr("transform",f.getTranslate("y")),e.attr("transform",f.getTranslate("y2")),f.main.select("."+h.chartArcs).attr("transform",f.getTranslate("arc"))},f.transformAll=function(a,b){var c=this;c.transformMain(a,b),c.config.subchart_show&&c.transformContext(a,b),c.legend&&c.transformLegend(a)},f.updateSvgSize=function(){var a=this;a.svg.attr("width",a.currentWidth).attr("height",a.currentHeight),a.svg.select("#"+a.clipId).select("rect").attr("width",a.width).attr("height",a.height),a.svg.select("#"+a.clipIdForXAxis).select("rect").attr("x",a.getXAxisClipX.bind(a)).attr("y",a.getXAxisClipY.bind(a)).attr("width",a.getXAxisClipWidth.bind(a)).attr("height",a.getXAxisClipHeight.bind(a)),a.svg.select("#"+a.clipIdForYAxis).select("rect").attr("x",a.getYAxisClipX.bind(a)).attr("y",a.getYAxisClipY.bind(a)).attr("width",a.getYAxisClipWidth.bind(a)).attr("height",a.getYAxisClipHeight.bind(a)),a.svg.select("."+h.zoomRect).attr("width",a.width).attr("height",a.height),a.selectChart.style("max-height",a.currentHeight+"px")},f.updateDimension=function(){var a=this;a.config.axis_rotated?(a.axes.x.call(a.xAxis),a.axes.subx.call(a.subXAxis)):(a.axes.y.call(a.yAxis),a.axes.y2.call(a.y2Axis)),a.updateSizes(),a.updateScales(),a.updateSvgSize(),a.transformAll(!1)},f.observeInserted=function(b){var c=this,d=new MutationObserver(function(e){e.forEach(function(e){if("childList"===e.type&&e.previousSibling){d.disconnect();var f=a.setInterval(function(){b.node().parentNode&&(a.clearInterval(f),c.updateDimension(),c.redraw({withTransform:!0,withUpdateXDomain:!0,withUpdateOrgXDomain:!0,withTransition:!1,withTransitionForTransform:!1,withLegend:!0}),b.transition().style("opacity",1))},10)}})});d.observe(b.node(),{attributes:!0,childList:!0,characterData:!0})},f.generateResize=function(){function a(){b.forEach(function(a){a()})}var b=[];return a.add=function(a){b.push(a)},a},f.endall=function(a,b){var c=0;a.each(function(){++c}).each("end",function(){--c||b.apply(this,arguments)})},f.generateWait=function(){var a=[],b=function(b,c){var d=setInterval(function(){var b=0;a.forEach(function(a){if(a.empty())return void(b+=1);try{a.transition()}catch(c){b+=1}}),b===a.length&&(clearInterval(d),c&&c())},10)};return b.add=function(b){a.push(b)},b},f.parseDate=function(b){var c,d=this;return c=b instanceof Date?b:"number"==typeof b?new Date(b):d.dataTimeFormat(d.config.data_xFormat).parse(b),(!c||isNaN(+c))&&a.console.error("Failed to parse x '"+b+"' to Date object"),c},f.getDefaultConfig=function(){var a={bindto:"#chart",size_width:void 0,size_height:void 0,padding_left:void 0,padding_right:void 0,padding_top:void 0,padding_bottom:void 0,zoom_enabled:!1,zoom_extent:void 0,zoom_privileged:!1,zoom_onzoom:function(){},interaction_enabled:!0,onmouseover:function(){},onmouseout:function(){},onresize:function(){},onresized:function(){},transition_duration:350,data_x:void 0,data_xs:{},data_xFormat:"%Y-%m-%d",data_xLocaltime:!0,data_idConverter:function(a){return a},data_names:{},data_classes:{},data_groups:[],data_axes:{},data_type:void 0,data_types:{},data_labels:{},data_order:"desc",data_regions:{},data_color:void 0,data_colors:{},data_hide:!1,data_filter:void 0,data_selection_enabled:!1,data_selection_grouped:!1,data_selection_isselectable:function(){return!0},data_selection_multiple:!0,data_onclick:function(){},data_onmouseover:function(){},data_onmouseout:function(){},data_onselected:function(){},data_onunselected:function(){},data_ondragstart:function(){},data_ondragend:function(){},data_url:void 0,data_json:void 0,data_rows:void 0,data_columns:void 0,data_mimeType:void 0,data_keys:void 0,data_empty_label_text:"",subchart_show:!1,subchart_size_height:60,subchart_onbrush:function(){},color_pattern:[],color_threshold:{},legend_show:!0,legend_position:"bottom",legend_inset_anchor:"top-left",legend_inset_x:10,legend_inset_y:0,legend_inset_step:void 0,legend_item_onclick:void 0,legend_item_onmouseover:void 0,legend_item_onmouseout:void 0,legend_equally:!1,axis_rotated:!1,axis_x_show:!0,axis_x_type:"indexed",axis_x_localtime:!0,axis_x_categories:[],axis_x_tick_centered:!1,axis_x_tick_format:void 0,axis_x_tick_culling:{},axis_x_tick_culling_max:10,axis_x_tick_count:void 0,axis_x_tick_fit:!0,axis_x_tick_values:null,axis_x_tick_rotate:void 0,axis_x_tick_outer:!0,axis_x_max:null,axis_x_min:null,axis_x_padding:{},axis_x_height:void 0,axis_x_default:void 0,axis_x_label:{},axis_y_show:!0,axis_y_max:void 0,axis_y_min:void 0,axis_y_center:void 0,axis_y_label:{},axis_y_tick_format:void 0,axis_y_tick_outer:!0,axis_y_padding:void 0,axis_y_ticks:10,axis_y2_show:!1,axis_y2_max:void 0,axis_y2_min:void 0,axis_y2_center:void 0,axis_y2_label:{},axis_y2_tick_format:void 0,axis_y2_tick_outer:!0,axis_y2_padding:void 0,axis_y2_ticks:10,grid_x_show:!1,grid_x_type:"tick",grid_x_lines:[],grid_y_show:!1,grid_y_lines:[],grid_y_ticks:10,grid_focus_show:!0,point_show:!0,point_r:2.5,point_focus_expand_enabled:!0,point_focus_expand_r:void 0,point_select_r:void 0,line_connect_null:!1,bar_width:void 0,bar_width_ratio:.6,bar_width_max:void 0,bar_zerobased:!0,area_zerobased:!0,pie_label_show:!0,pie_label_format:void 0,pie_label_threshold:.05,pie_sort:!0,pie_expand:!0,gauge_label_show:!0,gauge_label_format:void 0,gauge_expand:!0,gauge_min:0,gauge_max:100,gauge_units:void 0,gauge_width:void 0,donut_label_show:!0,donut_label_format:void 0,donut_label_threshold:.05,donut_width:void 0,donut_sort:!0,donut_expand:!0,donut_title:"",regions:[],tooltip_show:!0,tooltip_grouped:!0,tooltip_format_title:void 0,tooltip_format_name:void 0,tooltip_format_value:void 0,tooltip_contents:function(a,b,c,d){return this.getTooltipContent?this.getTooltipContent(a,b,c,d):""},tooltip_init_show:!1,tooltip_init_x:0,tooltip_init_position:{top:"0px",left:"50px"}};return Object.keys(this.additionalConfig).forEach(function(b){a[b]=this.additionalConfig[b]},this),a},f.additionalConfig={},f.loadConfig=function(a){function b(){var a=d.shift();return a&&c&&"object"==typeof c&&a in c?(c=c[a],b()):a?void 0:c}var c,d,e,f=this.config;Object.keys(f).forEach(function(g){c=a,d=g.split("_"),e=b(),m(e)&&(f[g]=e)})},f.getScale=function(a,b,c){return(c?this.d3.time.scale():this.d3.scale.linear()).range([a,b])},f.getX=function(a,b,c,d){var e,f=this,g=f.getScale(a,b,f.isTimeSeries()),h=c?g.domain(c):g;f.isCategorized()?(d=d||function(){return 0},g=function(a,b){var c=h(a)+d(a);return b?c:Math.ceil(c)}):g=function(a,b){var c=h(a);return b?c:Math.ceil(c)};for(e in h)g[e]=h[e];return g.orgDomain=function(){return h.domain()},f.isCategorized()&&(g.domain=function(a){return arguments.length?(h.domain(a),g):(a=this.orgDomain(),[a[0],a[1]+1])}),g},f.getY=function(a,b,c){var d=this.getScale(a,b);return c&&d.domain(c),d},f.getYScale=function(a){return"y2"===this.getAxisId(a)?this.y2:this.y},f.getSubYScale=function(a){return"y2"===this.getAxisId(a)?this.subY2:this.subY},f.updateScales=function(){var a=this,b=a.config,c=!a.x;a.xMin=b.axis_rotated?1:0,a.xMax=b.axis_rotated?a.height:a.width,a.yMin=b.axis_rotated?0:a.height,a.yMax=b.axis_rotated?a.width:1,a.subXMin=a.xMin,a.subXMax=a.xMax,a.subYMin=b.axis_rotated?0:a.height2,a.subYMax=b.axis_rotated?a.width2:1,a.x=a.getX(a.xMin,a.xMax,c?void 0:a.x.orgDomain(),function(){return a.xAxis.tickOffset()}),a.y=a.getY(a.yMin,a.yMax,c?void 0:a.y.domain()),a.y2=a.getY(a.yMin,a.yMax,c?void 0:a.y2.domain()),a.subX=a.getX(a.xMin,a.xMax,a.orgXDomain,function(b){return b%1?0:a.subXAxis.tickOffset()}),a.subY=a.getY(a.subYMin,a.subYMax,c?void 0:a.subY.domain()),a.subY2=a.getY(a.subYMin,a.subYMax,c?void 0:a.subY2.domain()),a.xAxisTickFormat=a.getXAxisTickFormat(),a.xAxisTickValues=b.axis_x_tick_values?b.axis_x_tick_values:c?void 0:a.xAxis.tickValues(),a.xAxis=a.getXAxis(a.x,a.xOrient,a.xAxisTickFormat,a.xAxisTickValues),a.subXAxis=a.getXAxis(a.subX,a.subXOrient,a.xAxisTickFormat,a.xAxisTickValues),a.yAxis=a.getYAxis(a.y,a.yOrient,b.axis_y_tick_format,b.axis_y_ticks),a.y2Axis=a.getYAxis(a.y2,a.y2Orient,b.axis_y2_tick_format,b.axis_y2_ticks),c||(a.brush&&a.brush.scale(a.subX),b.zoom_enabled&&a.zoom.scale(a.x)),a.updateArc&&a.updateArc()},f.getYDomainMin=function(a){var b,c,d,e,f,g,h=this,i=h.config,j=h.mapToIds(a),k=h.getValuesAsIdKeyed(a);if(i.data_groups.length>0)for(g=h.hasNegativeValueInTargets(a),b=0;b=0}),0!==e.length)for(d=e[0],g&&k[d]&&k[d].forEach(function(a,b){k[d][b]=0>a?a:0}),c=1;c0||(k[d][b]+=+a)});return h.d3.min(Object.keys(k).map(function(a){return h.d3.min(k[a])}))},f.getYDomainMax=function(a){var b,c,d,e,f,g,h=this,i=h.config,j=h.mapToIds(a),k=h.getValuesAsIdKeyed(a);if(i.data_groups.length>0)for(g=h.hasPositiveValueInTargets(a),b=0;b=0}),0!==e.length)for(d=e[0],g&&k[d]&&k[d].forEach(function(a,b){k[d][b]=a>0?a:0}),c=1;c+a||(k[d][b]+=+a)});return h.d3.max(Object.keys(k).map(function(a){return h.d3.max(k[a])}))},f.getYDomain=function(a,b){var c,d,e,f,g,h,j,k,l,m,n=this,o=n.config,q=a.filter(function(a){return n.getAxisId(a.id)===b}),r="y2"===b?o.axis_y2_min:o.axis_y_min,s="y2"===b?o.axis_y2_max:o.axis_y_max,t=i(r)?r:n.getYDomainMin(q),u=i(s)?s:n.getYDomainMax(q),v="y2"===b?o.axis_y2_center:o.axis_y_center,w=n.hasType("bar",q)&&o.bar_zerobased||n.hasType("area",q)&&o.area_zerobased,x=n.hasDataLabel()&&o.axis_rotated,y=n.hasDataLabel()&&!o.axis_rotated;return 0===q.length?"y2"===b?n.y2.domain():n.y.domain():(t===u&&(0>t?u=0:t=0),l=t>=0&&u>=0,m=0>=t&&0>=u,w&&(l&&(t=0),m&&(u=0)),c=Math.abs(u-t),d=e=f=.1*c,v&&(g=Math.max(Math.abs(t),Math.abs(u)),u=g-v,t=v-g),x?(h=n.getDataLabelLength(t,u,b,"width"),j=p(n.y.range()),k=[h[0]/j,h[1]/j],e+=c*(k[1]/(1-k[0]-k[1])),f+=c*(k[0]/(1-k[0]-k[1]))):y&&(h=n.getDataLabelLength(t,u,b,"height"),e+=h[1],f+=h[0]),"y"===b&&o.axis_y_padding&&(e=n.getAxisPadding(o.axis_y_padding,"top",d,c),f=n.getAxisPadding(o.axis_y_padding,"bottom",d,c)),"y2"===b&&o.axis_y2_padding&&(e=n.getAxisPadding(o.axis_y2_padding,"top",d,c),f=n.getAxisPadding(o.axis_y2_padding,"bottom",d,c)),w&&(l&&(f=t),m&&(e=-u)),[t-f,u+e])},f.getXDomainMin=function(a){var b=this,c=b.config;return c.axis_x_min?b.isTimeSeries()?this.parseDate(c.axis_x_min):c.axis_x_min:b.d3.min(a,function(a){return b.d3.min(a.values,function(a){return a.x})})},f.getXDomainMax=function(a){var b=this,c=b.config;return c.axis_x_max?b.isTimeSeries()?this.parseDate(c.axis_x_max):c.axis_x_max:b.d3.max(a,function(a){return b.d3.max(a.values,function(a){return a.x})})},f.getXDomainPadding=function(a){var b,c,d,e,f=this,g=f.config,h=this.getEdgeX(a),j=h[1]-h[0];return f.isCategorized()?c=0:f.hasType("bar",a)?(b=f.getMaxDataCount(),c=b>1?j/(b-1)/2:.5):c=.01*j,"object"==typeof g.axis_x_padding&&r(g.axis_x_padding)?(d=i(g.axis_x_padding.left)?g.axis_x_padding.left:c,e=i(g.axis_x_padding.right)?g.axis_x_padding.right:c):d=e="number"==typeof g.axis_x_padding?g.axis_x_padding:c,{left:d,right:e}},f.getXDomain=function(a){var b=this,c=[b.getXDomainMin(a),b.getXDomainMax(a)],d=c[0],e=c[1],f=b.getXDomainPadding(a),g=0,h=0;return d-e!==0||b.isCategorized()||(d=b.isTimeSeries()?new Date(.5*d.getTime()):-.5,e=b.isTimeSeries()?new Date(1.5*e.getTime()):.5),(d||0===d)&&(g=b.isTimeSeries()?new Date(d.getTime()-f.left):d-f.left),(e||0===e)&&(h=b.isTimeSeries()?new Date(e.getTime()+f.right):e+f.right),[g,h]},f.updateXDomain=function(a,b,c,d){var e=this,f=e.config;return c&&(e.x.domain(d?d:e.d3.extent(e.getXDomain(a))),e.orgXDomain=e.x.domain(),f.zoom_enabled&&e.zoom.scale(e.x).updateScaleExtent(),e.subX.domain(e.x.domain()),e.brush&&e.brush.scale(e.subX)),b&&(e.x.domain(d?d:!e.brush||e.brush.empty()?e.orgXDomain:e.brush.extent()),f.zoom_enabled&&e.zoom.scale(e.x).updateScaleExtent()),e.x.domain()},f.isX=function(a){var b=this,c=b.config;return c.data_x&&a===c.data_x||r(c.data_xs)&&t(c.data_xs,a)},f.isNotX=function(a){return!this.isX(a)},f.getXKey=function(a){var b=this,c=b.config;return c.data_x?c.data_x:r(c.data_xs)?c.data_xs[a]:null},f.getXValuesOfXKey=function(a,b){var c,d=this,e=b&&r(b)?d.mapToIds(b):[];return e.forEach(function(b){d.getXKey(b)===a&&(c=d.data.xs[b])}),c},f.getXValue=function(a,b){var c=this;return a in c.data.xs&&c.data.xs[a]&&i(c.data.xs[a][b])?c.data.xs[a][b]:b},f.getOtherTargetXs=function(){var a=this,b=Object.keys(a.data.xs);return b.length?a.data.xs[b[0]]:null},f.getOtherTargetX=function(a){var b=this.getOtherTargetXs();return b&&a1},f.isMultipleX=function(){var a=this,b=a.config;return r(b.data_xs)&&a.hasMultipleX(b.data_xs)},f.addName=function(a){var b,c=this;return a&&(b=c.config.data_names[a.id],a.name=b?b:a.id),a},f.getValueOnIndex=function(a,b){var c=a.filter(function(a){return a.index===b});return c.length?c[0]:null},f.updateTargetX=function(a,b){var c=this;a.forEach(function(a){a.values.forEach(function(d,e){d.x=c.generateTargetX(b[e],a.id,e)}),c.data.xs[a.id]=b})},f.updateTargetXs=function(a,b){var c=this;a.forEach(function(a){b[a.id]&&c.updateTargetX([a],b[a.id])})},f.generateTargetX=function(a,b,c){var d,e=this;return d=e.isTimeSeries()?e.parseDate(a?a:e.getXValue(b,c)):e.isCustomX()&&!e.isCategorized()?i(a)?+a:e.getXValue(b,c):c},f.cloneTarget=function(a){return{id:a.id,id_org:a.id_org,values:a.values.map(function(a){return{x:a.x,value:a.value,id:a.id}})}},f.getPrevX=function(a){var b=this,c=b.getValueOnIndex(b.data.targets[0].values,a-1);return c?c.x:null},f.getNextX=function(a){var b=this,c=b.getValueOnIndex(b.data.targets[0].values,a+1);return c?c.x:null},f.getMaxDataCount=function(){var a=this;return a.d3.max(a.data.targets,function(a){return a.values.length})},f.getMaxDataCountTarget=function(a){var b,c=a.length,d=0;return c>1?a.forEach(function(a){a.values.length>d&&(b=a,d=a.values.length)}):b=c?a[0]:null,b},f.getEdgeX=function(a){var b,c,d=this.getMaxDataCountTarget(a);return d?(b=d.values[0],c=d.values[d.values.length-1],[b.x,c.x]):[0,0]},f.mapToIds=function(a){return a.map(function(a){return a.id})},f.mapToTargetIds=function(a){var b=this;return a?k(a)?[a]:a:b.mapToIds(b.data.targets)},f.hasTarget=function(a,b){var c,d=this.mapToIds(a);for(c=0;ca})},f.hasPositiveValueInTargets=function(a){return this.checkValueInTargets(a,function(a){return a>0})},f.isOrderDesc=function(){var a=this.config;return a.data_order&&"desc"===a.data_order.toLowerCase()},f.isOrderAsc=function(){var a=this.config;return a.data_order&&"asc"===a.data_order.toLowerCase()},f.orderTargets=function(a){var b=this,c=b.config,d=b.isOrderAsc(),e=b.isOrderDesc();return d||e?a.sort(function(a,b){var c=function(a,b){return a+Math.abs(b.value)},e=a.values.reduce(c,0),f=b.values.reduce(c,0);return d?f-e:e-f}):j(c.data_order)&&a.sort(c.data_order),a +},f.filterSameX=function(a,b){return this.d3.merge(a.map(function(a){return a.values})).filter(function(a){return a.x-b===0})},f.filterRemoveNull=function(a){return a.filter(function(a){return i(a.value)})},f.hasDataLabel=function(){var a=this.config;return"boolean"==typeof a.data_labels&&a.data_labels?!0:"object"==typeof a.data_labels&&r(a.data_labels)?!0:!1},f.getDataLabelLength=function(a,b,c,d){var e=this,f=[0,0],g=1.3;return e.selectChart.select("svg").selectAll(".dummy").data([a,b]).enter().append("text").text(function(a){return e.formatByAxisId(c)(a)}).each(function(a,b){f[b]=this.getBoundingClientRect()[d]*g}).remove(),f},f.isNoneArc=function(a){return this.hasTarget(this.data.targets,a.id)},f.isArc=function(a){return"data"in a&&this.hasTarget(this.data.targets,a.data.id)},f.findSameXOfValues=function(a,b){var c,d=a[b].x,e=[];for(c=b-1;c>=0&&d===a[c].x;c--)e.push(a[c]);for(c=b;c0?h=i:g=i,h-g===1||0===g&&0===h?(e=[],(a[g].x||0===a[g].x)&&(e=e.concat(f.findSameXOfValues(a,g))),(a[h].x||0===a[h].x)&&(e=e.concat(f.findSameXOfValues(a,h))),f.findClosest(e,b)):f.findClosestOfValues(a,b,g,h)},f.findClosestFromTargets=function(a,b){var c,d=this;return c=a.map(function(a){return d.findClosestOfValues(a.values,b)}),d.findClosest(c,b)},f.findClosest=function(a,b){var c,d,e=this;return a.forEach(function(a){var f=e.dist(a,b);(c>f||!c)&&(c=f,d=a)}),d},f.dist=function(a,b){var c=this,d=c.config,e="y"===c.getAxisId(a.id)?c.y:c.y2,f=d.axis_rotated?1:0,g=d.axis_rotated?0:1;return Math.pow(c.x(a.x)-b[f],2)+Math.pow(e(a.value)-b[g],2)},f.convertUrlToData=function(a,b,c,d){var e=this,f=b?b:"csv";e.d3.xhr(a,function(a,b){var g;g="json"===f?e.convertJsonToData(JSON.parse(b.response),c):e.convertCsvToData(b.response),d.call(e,g)})},f.convertCsvToData=function(a){var b,c=this.d3,d=c.csv.parseRows(a);return 1===d.length?(b=[{}],d[0].forEach(function(a){b[0][a]=null})):b=c.csv.parse(a),b},f.convertJsonToData=function(a,b){var c,d,e=this,f=[];return b?(c=b.value,b.x&&(c.push(b.x),e.config.data_x=b.x),f.push(c),a.forEach(function(a){var b=[];c.forEach(function(c){var d=l(a[c])?null:a[c];b.push(d)}),f.push(b)}),d=e.convertRowsToData(f)):(Object.keys(a).forEach(function(b){f.push([b].concat(a[b]))}),d=e.convertColumnsToData(f)),d},f.convertRowsToData=function(a){var b,c,d=a[0],e={},f=[];for(b=1;b=0?d.data.xs[c]=(b&&d.data.xs[c]?d.data.xs[c]:[]).concat(a.map(function(a){return a[f]}).filter(i).map(function(a,b){return d.generateTargetX(a,c,b)})):e.data_x?d.data.xs[c]=d.getOtherTargetXs():r(e.data_xs)&&(d.data.xs[c]=d.getXValuesOfXKey(f,d.data.targets)):d.data.xs[c]=a.map(function(a,b){return b})}),f.forEach(function(a){if(!d.data.xs[a])throw new Error('x is not defined for id = "'+a+'".')}),c=f.map(function(b,c){var f=e.data_idConverter(b);return{id:f,id_org:b,values:a.map(function(a,g){var h=d.getXKey(b),i=a[h],j=d.generateTargetX(i,b,g);return d.isCustomX()&&d.isCategorized()&&0===c&&i&&(0===g&&(e.axis_x_categories=[]),e.axis_x_categories.push(i)),(l(a[b])||d.data.xs[b].length<=g)&&(j=void 0),{x:j,value:null===a[b]||isNaN(a[b])?null:+a[b],id:f}}).filter(function(a){return m(a.x)})}}),c.forEach(function(a){var b;a.values=a.values.sort(function(a,b){var c=a.x||0===a.x?a.x:1/0,d=b.x||0===b.x?b.x:1/0;return c-d}),b=0,a.values.forEach(function(a){a.index=b++}),d.data.xs[a.id].sort(function(a,b){return a-b})}),e.data_type&&d.setTargetType(d.mapToIds(c).filter(function(a){return!(a in e.data_types)}),e.data_type),c.forEach(function(a){d.addCache(a.id_org,a)}),c},f.load=function(a,b){var c=this;a&&(b.filter&&(a=a.filter(b.filter)),(b.type||b.types)&&a.forEach(function(a){c.setTargetType(a.id,b.types?b.types[a.id]:b.type)}),c.data.targets.forEach(function(b){for(var c=0;ce?0:e},g=function(a){var b=h.getPrevX(a.index),c=h.data.xs[a.id][a.index];return(h.x(c)+h.x(b?b:c))/2}),b=i.axis_rotated?0:g,c=i.axis_rotated?g:0,d=i.axis_rotated?h.width:f,e=i.axis_rotated?f:h.height),a.attr("class",h.classEvent.bind(h)).attr("x",b).attr("y",c).attr("width",d).attr("height",e)},f.generateEventRectsForSingleX=function(a){var b=this,c=b.d3,d=b.config;a.append("rect").attr("class",b.classEvent.bind(b)).style("cursor",d.data_selection_enabled&&d.data_selection_grouped?"pointer":null).on("mouseover",function(a){var c,e,f=a.index;b.dragging||b.hasArcType()||(c=b.data.targets.map(function(a){return b.addName(b.getValueOnIndex(a.values,f))}),e=[],Object.keys(d.data_names).forEach(function(a){for(var b=0;b0?c:320},f.getCurrentPaddingTop=function(){var a=this.config;return i(a.padding_top)?a.padding_top:0},f.getCurrentPaddingBottom=function(){var a=this.config;return i(a.padding_bottom)?a.padding_bottom:0},f.getCurrentPaddingLeft=function(){var a=this,b=a.config;return i(b.padding_left)?b.padding_left:b.axis_rotated?b.axis_x_show?Math.max(n(a.getAxisWidthByAxisId("x")),40):1:b.axis_y_show?n(a.getAxisWidthByAxisId("y")):1},f.getCurrentPaddingRight=function(){var a=this,b=a.config,c=10,d=a.isLegendRight?a.getLegendWidth()+20:0;return i(b.padding_right)?b.padding_right+1:b.axis_rotated?c+d:(b.axis_y2_show?n(a.getAxisWidthByAxisId("y2")):c)+d},f.getParentRectValue=function(a){for(var b,c=this.selectChart.node();c&&"BODY"!==c.tagName&&!(b=c.getBoundingClientRect()[a]);)c=c.parentNode;return b},f.getParentWidth=function(){return this.getParentRectValue("width")},f.getParentHeight=function(){var a=this.selectChart.style("height");return a.indexOf("px")>0?+a.replace("px",""):0},f.getSvgLeft=function(){var a=this,b=a.config,c=b.axis_rotated?h.axisX:h.axisY,d=a.main.select("."+c).node(),e=d?d.getBoundingClientRect():{right:0},f=a.selectChart.node().getBoundingClientRect(),g=a.hasArcType(),i=e.right-f.left-(g?0:a.getCurrentPaddingLeft());return i>0?i:0},f.getAxisWidthByAxisId=function(a){var b=this,c=b.getAxisLabelPositionById(a);return c.isInner?20+b.getMaxTickWidth(a):40+b.getMaxTickWidth(a)},f.getHorizontalAxisHeight=function(a){var b=this,c=b.config;return"x"!==a||c.axis_x_show?"x"===a&&c.axis_x_height?c.axis_x_height:"y"!==a||c.axis_y_show?"y2"!==a||c.axis_y2_show?(b.getAxisLabelPositionById(a).isInner?30:40)+("y2"===a?-10:0):b.rotated_padding_top:!c.legend_show||b.isLegendRight||b.isLegendInset?1:10:0},f.getEventRectWidth=function(){var a,b,c,d,e,f,g=this,h=g.getMaxDataCountTarget(g.data.targets);return h?(a=h.values[0],b=h.values[h.values.length-1],c=g.x(b.x)-g.x(a.x),0===c?g.config.axis_rotated?g.height:g.width:(d=g.getMaxDataCount(),e=g.hasType("bar")?(d-(g.isCategorized()?.25:1))/d:1,f=d>1?c*e/(d-1):c,1>f?1:f)):0},f.getShapeIndices=function(a){var b,c,d=this,e=d.config,f={},g=0;return d.filterTargetsToShow(d.data.targets.filter(a,d)).forEach(function(a){for(b=0;b=0&&(j+=h(c.values[g].value)-i)}),j}},f.getInterpolate=function(a){var b=this;return b.isSplineType(a)?"cardinal":b.isStepType(a)?"step-after":"linear"},f.initLine=function(){var a=this;a.main.select("."+h.chart).append("g").attr("class",h.chartLines)},f.updateTargetsForLine=function(a){var b,c,d=this,e=d.config,f=d.classChartLine.bind(d),g=d.classLines.bind(d),i=d.classAreas.bind(d),j=d.classCircles.bind(d);b=d.main.select("."+h.chartLines).selectAll("."+h.chartLine).data(a).attr("class",f),c=b.enter().append("g").attr("class",f).style("opacity",0).style("pointer-events","none"),c.append("g").attr("class",g),c.append("g").attr("class",i),c.append("g").attr("class",function(a){return d.generateClass(h.selectedCircles,a.id)}),c.append("g").attr("class",j).style("cursor",function(a){return e.data_selection_isselectable(a)?"pointer":null}),a.forEach(function(a){d.main.selectAll("."+h.selectedCircles+d.getTargetSelectorSuffix(a.id)).selectAll("."+h.selectedCircle).each(function(b){b.value=a.values[b.index].value})})},f.redrawLine=function(a){var b=this;b.mainLine=b.main.selectAll("."+h.lines).selectAll("."+h.line).data(b.lineData.bind(b)),b.mainLine.enter().append("path").attr("class",b.classLine.bind(b)).style("stroke",b.color),b.mainLine.style("opacity",b.initialOpacity.bind(b)).attr("transform",null),b.mainLine.exit().transition().duration(a).style("opacity",0).remove()},f.addTransitionForLine=function(a,b){var c=this;a.push(c.mainLine.transition().attr("d",b).style("stroke",c.color).style("opacity",1))},f.generateDrawLine=function(a,b){var c=this,d=c.config,e=c.d3.svg.line(),f=c.generateGetLinePoint(a,b),g=b?c.getSubYScale:c.getYScale,h=function(a){return(b?c.subxx:c.xx).call(c,a)},i=function(a,b){return d.data_groups.length>0?f(a,b)[0][1]:g.call(c,a.id)(a.value)};return e=d.axis_rotated?e.x(i).y(h):e.x(h).y(i),d.line_connect_null||(e=e.defined(function(a){return null!=a.value})),function(a){var f,h=d.line_connect_null?c.filterRemoveNull(a.values):a.values,i=b?c.x:c.subX,j=g.call(c,a.id),k=0,l=0;return c.isLineType(a)?f=d.data_regions[a.id]?c.lineWithRegions(h,i,j,d.data_regions[a.id]):e.interpolate(c.getInterpolate(a))(h):(h[0]&&(k=i(h[0].x),l=j(h[0].value)),f=d.axis_rotated?"M "+l+" "+k:"M "+k+" "+l),f?f:"M 0 0"}},f.generateGetLinePoint=function(a,b){var c=this,d=c.config,e=a.__max__+1,f=c.getShapeX(0,e,a,!!b),g=c.getShapeY(!!b),h=c.getShapeOffset(c.isLineType,a,!!b),i=b?c.getSubYScale:c.getYScale;return function(a,b){var e=i.call(c,a.id)(0),j=h(a,b)||e,k=f(a),l=g(a);return d.axis_rotated&&(0l||a.value<0&&l>e)&&(l=e),[[k,l-(e-j)]]}},f.lineWithRegions=function(a,b,c,d){function e(a,b){var c;for(c=0;c=g;g+=q)w+=h(a[f-1],a[f],g,p);v=a[f].x}return w},f.redrawArea=function(a){var b=this,c=b.d3;b.mainArea=b.main.selectAll("."+h.areas).selectAll("."+h.area).data(b.lineData.bind(b)),b.mainArea.enter().append("path").attr("class",b.classArea.bind(b)).style("fill",b.color).style("opacity",function(){return b.orgAreaOpacity=+c.select(this).style("opacity"),0}),b.mainArea.style("opacity",b.orgAreaOpacity),b.mainArea.exit().transition().duration(a).style("opacity",0).remove()},f.addTransitionForArea=function(a,b){var c=this;a.push(c.mainArea.transition().attr("d",b).style("fill",c.color).style("opacity",c.orgAreaOpacity))},f.generateDrawArea=function(a,b){var c=this,d=c.config,e=c.d3.svg.area(),f=c.generateGetAreaPoint(a,b),g=b?c.getSubYScale:c.getYScale,h=function(a){return(b?c.subxx:c.xx).call(c,a)},i=function(a,b){return d.data_groups.length>0?f(a,b)[0][1]:g.call(c,a.id)(0)},j=function(a,b){return d.data_groups.length>0?f(a,b)[1][1]:g.call(c,a.id)(a.value)};return e=d.axis_rotated?e.x0(i).x1(j).y(h):e.x(h).y0(i).y1(j),d.line_connect_null||(e=e.defined(function(a){return null!==a.value})),function(a){var b,f=d.line_connect_null?c.filterRemoveNull(a.values):a.values,g=0,h=0;return c.isAreaType(a)?b=e.interpolate(c.getInterpolate(a))(f):(f[0]&&(g=c.x(f[0].x),h=c.getYScale(a.id)(f[0].value)),b=d.axis_rotated?"M "+h+" "+g:"M "+g+" "+h),b?b:"M 0 0"}},f.generateGetAreaPoint=function(a,b){var c=this,d=c.config,e=a.__max__+1,f=c.getShapeX(0,e,a,!!b),g=c.getShapeY(!!b),h=c.getShapeOffset(c.isAreaType,a,!!b),i=b?c.getSubYScale:c.getYScale;return function(a,b){var e=i.call(c,a.id)(0),j=h(a,b)||e,k=f(a),l=g(a);return d.axis_rotated&&(0l||a.value<0&&l>e)&&(l=e),[[k,j],[k,l-(e-j)]]}},f.redrawCircle=function(){var a=this;a.mainCircle=a.main.selectAll("."+h.circles).selectAll("."+h.circle).data(a.lineOrScatterData.bind(a)),a.mainCircle.enter().append("circle").attr("class",a.classCircle.bind(a)).attr("r",a.pointR.bind(a)).style("fill",a.color),a.mainCircle.style("opacity",a.initialOpacity.bind(a)),a.mainCircle.exit().remove()},f.addTransitionForCircle=function(a,b,c){var d=this;a.push(d.mainCircle.transition().style("opacity",d.opacityForCircle.bind(d)).style("fill",d.color).attr("cx",b).attr("cy",c)),a.push(d.main.selectAll("."+h.selectedCircle).transition().attr("cx",b).attr("cy",c))},f.circleX=function(a){return a.x||0===a.x?this.x(a.x):null},f.circleY=function(a,b){var c=this,d=c.getShapeIndices(c.isLineType),e=c.generateGetLinePoint(d);return c.config.data_groups.length>0?e(a,b)[0][1]:c.getYScale(a.id)(a.value)},f.getCircles=function(a,b){var c=this;return(b?c.main.selectAll("."+h.circles+c.getTargetSelectorSuffix(b)):c.main).selectAll("."+h.circle+(i(a)?"-"+a:""))},f.expandCircles=function(a,b){var c=this,d=c.pointExpandedR.bind(c);c.getCircles(a,b).classed(h.EXPANDED,!0).attr("r",d)},f.unexpandCircles=function(a){var b=this,c=b.pointR.bind(b);b.getCircles(a).filter(function(){return b.d3.select(this).classed(h.EXPANDED)}).classed(h.EXPANDED,!1).attr("r",c)},f.pointR=function(a){var b=this,c=b.config;return c.point_show&&!b.isStepType(a)?j(c.point_r)?c.point_r(a):c.point_r:0},f.pointExpandedR=function(a){var b=this,c=b.config;return c.point_focus_expand_enabled?c.point_focus_expand_r?c.point_focus_expand_r:1.75*b.pointR(a):b.pointR(a)},f.pointSelectR=function(a){var b=this,c=b.config;return c.point_select_r?c.point_select_r:4*b.pointR(a)},f.isWithinCircle=function(a,b){var c=this.d3,d=c.mouse(a),e=c.select(a),f=1*e.attr("cx"),g=1*e.attr("cy");return Math.sqrt(Math.pow(f-d[0],2)+Math.pow(g-d[1],2))d.bar_width_max?d.bar_width_max:e},f.getBars=function(a){var b=this;return b.main.selectAll("."+h.bar+(i(a)?"-"+a:""))},f.expandBars=function(a){var b=this;b.getBars(a).classed(h.EXPANDED,!0)},f.unexpandBars=function(a){var b=this;b.getBars(a).classed(h.EXPANDED,!1)},f.generateDrawBar=function(a,b){var c=this,d=c.config,e=c.generateGetBarPoints(a,b);return function(a,b){var c=e(a,b),f=d.axis_rotated?1:0,g=d.axis_rotated?0:1,h="M "+c[0][f]+","+c[0][g]+" L"+c[1][f]+","+c[1][g]+" L"+c[2][f]+","+c[2][g]+" L"+c[3][f]+","+c[3][g]+" z";return h}},f.generateGetBarPoints=function(a,b){var c=this,d=a.__max__+1,e=c.getBarW(c.xAxis,d),f=c.getShapeX(e,d,a,!!b),g=c.getShapeY(!!b),h=c.getShapeOffset(c.isBarType,a,!!b),i=b?c.getSubYScale:c.getYScale;return function(a,b){var d=i.call(c,a.id)(0),j=h(a,b)||d,k=f(a),l=g(a);return c.config.axis_rotated&&(0l||a.value<0&&l>d)&&(l=d),[[k,j],[k,l-(d-j)],[k+e,l-(d-j)],[k+e,j]]}},f.isWithinBar=function(a){var b=this.d3,c=b.mouse(a),d=a.getBoundingClientRect(),e=a.pathSegList.getItem(0),f=a.pathSegList.getItem(1),g=e.x,h=Math.min(e.y,f.y),i=d.width,j=d.height,k=2,l=g-k,m=g+i+k,n=h+j+k,o=h-k;return lf.width?f.width-g.width:d},f.getYForText=function(a,b,c){var d,e=this,f=c.getBoundingClientRect();return d=e.config.axis_rotated?(a[0][0]+a[2][0]+.6*f.height)/2:a[2][1]+(b.value<0?f.height:e.isBarType(b)?-3:-6),d=0||!(b.id in d)&&"line"===a)&&(e=!0)}),e},f.hasArcType=function(a){return this.hasType("pie",a)||this.hasType("donut",a)||this.hasType("gauge",a)},f.isLineType=function(a){var b=this.config,c=k(a)?a:a.id;return!b.data_types[c]||["line","spline","area","area-spline","step","area-step"].indexOf(b.data_types[c])>=0},f.isStepType=function(a){var b=k(a)?a:a.id;return["step","area-step"].indexOf(this.config.data_types[b])>=0},f.isSplineType=function(a){var b=k(a)?a:a.id;return["spline","area-spline"].indexOf(this.config.data_types[b])>=0},f.isAreaType=function(a){var b=k(a)?a:a.id;return["area","area-spline","area-step"].indexOf(this.config.data_types[b])>=0},f.isBarType=function(a){var b=k(a)?a:a.id;return"bar"===this.config.data_types[b]},f.isScatterType=function(a){var b=k(a)?a:a.id;return"scatter"===this.config.data_types[b]},f.isPieType=function(a){var b=k(a)?a:a.id;return"pie"===this.config.data_types[b]},f.isGaugeType=function(a){var b=k(a)?a:a.id;return"gauge"===this.config.data_types[b]},f.isDonutType=function(a){var b=k(a)?a:a.id;return"donut"===this.config.data_types[b]},f.isArcType=function(a){return this.isPieType(a)||this.isDonutType(a)||this.isGaugeType(a)},f.lineData=function(a){return this.isLineType(a)?[a]:[]},f.arcData=function(a){return this.isArcType(a.data)?[a]:[]},f.barData=function(a){return this.isBarType(a)?a.values:[]},f.lineOrScatterData=function(a){return this.isLineType(a)||this.isScatterType(a)?a.values:[]},f.barOrLineData=function(a){return this.isBarType(a)||this.isLineType(a)?a.values:[]},f.initGrid=function(){var a=this,b=a.config,c=a.d3;a.grid=a.main.append("g").attr("clip-path",a.clipPath).attr("class",h.grid),b.grid_x_show&&a.grid.append("g").attr("class",h.xgrids),b.grid_y_show&&a.grid.append("g").attr("class",h.ygrids),a.grid.append("g").attr("class",h.xgridLines),a.grid.append("g").attr("class",h.ygridLines),b.grid_focus_show&&a.grid.append("g").attr("class",h.xgridFocus).append("line").attr("class",h.xgridFocus),a.xgrid=c.selectAll([]),a.xgridLines=c.selectAll([])},f.updateXGrid=function(a){var b=this,c=b.config,d=b.d3,e=b.generateGridData(c.grid_x_type,b.x),f=b.isCategorized()?b.xAxis.tickOffset():0;b.xgridAttr=c.axis_rotated?{x1:0,x2:b.width,y1:function(a){return b.x(a)-f},y2:function(a){return b.x(a)-f}}:{x1:function(a){return b.x(a)+f},x2:function(a){return b.x(a)+f},y1:0,y2:b.height},b.xgrid=b.main.select("."+h.xgrids).selectAll("."+h.xgrid).data(e),b.xgrid.enter().append("line").attr("class",h.xgrid),a||b.xgrid.attr(b.xgridAttr).style("opacity",function(){return+d.select(this).attr(c.axis_rotated?"y1":"x1")===(c.axis_rotated?b.height:0)?0:1}),b.xgrid.exit().remove()},f.updateYGrid=function(){var a=this,b=a.config;a.ygrid=a.main.select("."+h.ygrids).selectAll("."+h.ygrid).data(a.y.ticks(b.grid_y_ticks)),a.ygrid.enter().append("line").attr("class",h.ygrid),a.ygrid.attr("x1",b.axis_rotated?a.y:0).attr("x2",b.axis_rotated?a.y:a.width).attr("y1",b.axis_rotated?0:a.y).attr("y2",b.axis_rotated?a.height:a.y),a.ygrid.exit().remove(),a.smoothLines(a.ygrid,"grid")},f.redrawGrid=function(a,b){var c,d,e,f=this,g=f.main,i=f.config;g.select("line."+h.xgridFocus).style("visibility","hidden"),i.grid_x_show&&f.updateXGrid(),f.xgridLines=g.select("."+h.xgridLines).selectAll("."+h.xgridLine).data(i.grid_x_lines),c=f.xgridLines.enter().append("g").attr("class",function(a){return h.xgridLine+(a.class?" "+a.class:"")}),c.append("line").style("opacity",0),c.append("text").attr("text-anchor","end").attr("transform",i.axis_rotated?"":"rotate(-90)").attr("dx",i.axis_rotated?0:-f.margin.top).attr("dy",-5).style("opacity",0),f.xgridLines.exit().transition().duration(a).style("opacity",0).remove(),b&&i.grid_y_show&&f.updateYGrid(),b&&(f.ygridLines=g.select("."+h.ygridLines).selectAll("."+h.ygridLine).data(i.grid_y_lines),d=f.ygridLines.enter().append("g").attr("class",function(a){return h.ygridLine+(a.class?" "+a.class:"")}),d.append("line").style("opacity",0),d.append("text").attr("text-anchor","end").attr("transform",i.axis_rotated?"rotate(-90)":"").attr("dx",i.axis_rotated?0:-f.margin.top).attr("dy",-5).style("opacity",0),e=f.yv.bind(f),f.ygridLines.select("line").transition().duration(a).attr("x1",i.axis_rotated?e:0).attr("x2",i.axis_rotated?e:f.width).attr("y1",i.axis_rotated?0:e).attr("y2",i.axis_rotated?f.height:e).style("opacity",1),f.ygridLines.select("text").transition().duration(a).attr("x",i.axis_rotated?0:f.width).attr("y",e).text(function(a){return a.text}).style("opacity",1),f.ygridLines.exit().transition().duration(a).style("opacity",0).remove())},f.addTransitionForGrid=function(a){var b=this,c=b.config,d=b.xv.bind(b);a.push(b.xgridLines.select("line").transition().attr("x1",c.axis_rotated?0:d).attr("x2",c.axis_rotated?b.width:d).attr("y1",c.axis_rotated?d:b.margin.top).attr("y2",c.axis_rotated?d:b.height).style("opacity",1)),a.push(b.xgridLines.select("text").transition().attr("x",c.axis_rotated?b.width:0).attr("y",d).text(function(a){return a.text}).style("opacity",1))},f.showXGridFocus=function(a){var b=this,c=b.config,d=a.filter(function(a){return a&&i(a.value)}),e=b.main.selectAll("line."+h.xgridFocus),f=b.xx.bind(b);c.tooltip_show&&(b.hasType("scatter")||b.hasArcType()||(e.style("visibility","visible").data([d[0]]).attr(c.axis_rotated?"y1":"x1",f).attr(c.axis_rotated?"y2":"x2",f),b.smoothLines(e,"grid")))},f.hideXGridFocus=function(){this.main.select("line."+h.xgridFocus).style("visibility","hidden")},f.updateXgridFocus=function(){var a=this,b=a.config;a.main.select("line."+h.xgridFocus).attr("x1",b.axis_rotated?0:-10).attr("x2",b.axis_rotated?a.width:-10).attr("y1",b.axis_rotated?-10:0).attr("y2",b.axis_rotated?-10:a.height)},f.generateGridData=function(a,b){var c,d,e,f,g=this,i=[],j=g.main.select("."+h.axisX).selectAll(".tick").size();if("year"===a)for(c=g.getXDomain(),d=c[0].getFullYear(),e=c[1].getFullYear(),f=d;e>=f;f++)i.push(new Date(f+"-01-01 00:00:00")); +else i=b.ticks(10),i.length>j&&(i=i.filter(function(a){return(""+a).indexOf(".")<0}));return i},f.getGridFilterToRemove=function(a){return a?function(b){var c=!1;return[].concat(a).forEach(function(d){("value"in d&&b.value===a.value||"class"in d&&b.class===a.class)&&(c=!0)}),c}:function(){return!0}},f.removeGridLines=function(a,b){var c=this,d=c.config,e=c.getGridFilterToRemove(a),f=function(a){return!e(a)},g=b?h.xgridLines:h.ygridLines,i=b?h.xgridLine:h.ygridLine;c.main.select("."+g).selectAll("."+i).filter(e).transition().duration(d.transition_duration).style("opacity",0).remove(),b?d.grid_x_lines=d.grid_x_lines.filter(f):d.grid_y_lines=d.grid_y_lines.filter(f)},f.initTooltip=function(){var a,b=this,c=b.config;if(b.tooltip=b.selectChart.style("position","relative").append("div").style("position","absolute").style("pointer-events","none").style("z-index","10").style("display","none"),c.tooltip_init_show){if(b.isTimeSeries()&&k(c.tooltip_init_x)){for(c.tooltip_init_x=b.parseDate(c.tooltip_init_x),a=0;a"+(g||0===g?""+g+"":"")),j=o(a[f].name),i=p(a[f].value,a[f].ratio,a[f].id,a[f].index),k=l.levelColor?l.levelColor(a[f].value):d(a[f].id),e+="",e+=""+j+"",e+=""+i+"",e+="");return e+""},f.showTooltip=function(a,b){var c,d,e,f,g,h,j,k=this,l=k.config,m=k.hasArcType(),n=a.filter(function(a){return a&&i(a.value)});0!==n.length&&l.tooltip_show&&(k.tooltip.html(l.tooltip_contents.call(k,a,k.getXAxisTickFormat(),k.getYFormat(m),k.color)).style("display","block"),c=k.tooltip.property("offsetWidth"),d=k.tooltip.property("offsetHeight"),m?(f=k.width/2+b[0],h=k.height/2+b[1]+20):(l.axis_rotated?(e=k.getSvgLeft(),f=e+b[0]+100,g=f+c,j=k.getCurrentWidth()-k.getCurrentPaddingRight(),h=k.x(n[0].x)+20):(e=k.getSvgLeft(),f=e+k.getCurrentPaddingLeft()+k.x(n[0].x)+20,g=f+c,j=e+k.getCurrentWidth()-k.getCurrentPaddingRight(),h=b[1]+15),g>j&&(f-=g-j),h+d>k.getCurrentHeight()&&h>d+30&&(h-=d+30)),k.tooltip.style("top",h+"px").style("left",f+"px"))},f.hideTooltip=function(){this.tooltip.style("display","none")},f.initLegend=function(){var a=this;a.legend=a.svg.append("g").attr("transform",a.getTranslate("legend")),a.config.legend_show||(a.legend.style("visibility","hidden"),a.hiddenLegendIds=a.mapToIds(a.data.targets)),a.updateLegend(a.mapToIds(a.data.targets),{withTransform:!1,withTransitionForTransform:!1,withTransition:!1})},f.updateSizeForLegend=function(a,b){var c=this,d=c.config,e={top:c.isLegendTop?c.getCurrentPaddingTop()+d.legend_inset_y+5.5:c.currentHeight-a-c.getCurrentPaddingBottom()-d.legend_inset_y,left:c.isLegendLeft?c.getCurrentPaddingLeft()+d.legend_inset_x+.5:c.currentWidth-b-c.getCurrentPaddingRight()-d.legend_inset_x+.5};c.margin3={top:c.isLegendRight?0:c.isLegendInset?e.top:c.currentHeight-a,right:0/0,bottom:0,left:c.isLegendRight?c.currentWidth-b:c.isLegendInset?e.left:0}},f.transformLegend=function(a){var b=this;(a?b.legend.transition():b.legend).attr("transform",b.getTranslate("legend"))},f.updateLegendStep=function(a){this.legendStep=a},f.updateLegendItemWidth=function(a){this.legendItemWidth=a},f.updateLegendItemHeight=function(a){this.legendItemHeight=a},f.getLegendWidth=function(){var a=this;return a.config.legend_show?a.isLegendRight||a.isLegendInset?a.legendItemWidth*(a.legendStep+1):a.currentWidth:0},f.getLegendHeight=function(){var a=this,b=a.config,c=0;return b.legend_show&&(c=a.isLegendRight?a.currentHeight:a.isLegendInset?b.legend_inset_step?Math.max(20,a.legendItemHeight)*(b.legend_inset_step+1):a.height:Math.max(20,a.legendItemHeight)*(a.legendStep+1)),c},f.opacityForLegend=function(a){var b=this;return a.classed(h.legendItemHidden)?b.legendOpacityForHidden:1},f.opacityForUnfocusedLegend=function(a){var b=this;return a.classed(h.legendItemHidden)?b.legendOpacityForHidden:.3},f.toggleFocusLegend=function(a,b){var c=this;c.legend.selectAll("."+h.legendItem).transition().duration(100).style("opacity",function(d){var e=c.d3.select(this);return a&&d!==a?b?c.opacityForUnfocusedLegend(e):c.opacityForLegend(e):b?c.opacityForLegend(e):c.opacityForUnfocusedLegend(e)})},f.revertLegend=function(){var a=this,b=a.d3;a.legend.selectAll("."+h.legendItem).transition().duration(100).style("opacity",function(){return a.opacityForLegend(b.select(this))})},f.showLegend=function(a){var b=this,c=b.config;c.legend_show||(c.legend_show=!0,b.legend.style("visibility","visible")),b.removeHiddenLegendIds(a),b.legend.selectAll(b.selectorLegends(a)).style("visibility","visible").transition().style("opacity",function(){return b.opacityForLegend(b.d3.select(this))})},f.hideLegend=function(a){var b=this,c=b.config;c.legend_show&&q(a)&&(c.legend_show=!1,b.legend.style("visibility","hidden")),b.addHiddenLegendIds(a),b.legend.selectAll(b.selectorLegends(a)).style("opacity",0).style("visibility","hidden")},f.updateLegend=function(a,b,c){function d(b,c,d){function e(a,b){b||(f=(m-A-l)/2,z>f&&(f=(m-l)/2,A=0,G++)),F[a]=G,E[G]=t.isLegendInset?10:f,B[a]=A,A+=l}var f,g,i=t.getTextRect(b.textContent,h.legendItem),j=10*Math.ceil((i.width+w)/10),k=10*Math.ceil((i.height+v)/10),l=t.isLegendRight||t.isLegendInset?k:j,m=t.isLegendRight||t.isLegendInset?t.getLegendHeight():t.getLegendWidth();return d&&(A=0,G=0,x=0,y=0),u.legend_show&&!t.isLegendToShow(c)?void(C[c]=D[c]=F[c]=B[c]=0):(C[c]=j,D[c]=k,(!x||j>=x)&&(x=j),(!y||k>=y)&&(y=k),g=t.isLegendRight||t.isLegendInset?y:x,void(u.legend_equally?(Object.keys(C).forEach(function(a){C[a]=x}),Object.keys(D).forEach(function(a){D[a]=y}),f=(m-g*a.length)/2,z>f?(A=0,G=0,a.forEach(function(a){e(a)})):e(c,!0)):e(c)))}var e,f,g,i,j,k,l,n,o,p,q,r,t=this,u=t.config,v=4,w=36,x=0,y=0,z=10,A=0,B={},C={},D={},E=[0],F={},G=0,H=t.legend.selectAll("."+h.legendItemFocused).size();b=b||{},n=s(b,"withTransition",!0),o=s(b,"withTransitionForTransform",!0),t.isLegendRight?(e=function(a){return x*F[a]},i=function(a){return E[F[a]]+B[a]}):t.isLegendInset?(e=function(a){return x*F[a]+10},i=function(a){return E[F[a]]+B[a]}):(e=function(a){return E[F[a]]+B[a]},i=function(a){return y*F[a]}),f=function(a,b){return e(a,b)+14},j=function(a,b){return i(a,b)+9},g=function(a,b){return e(a,b)-4},k=function(a,b){return i(a,b)-7},l=t.legend.selectAll("."+h.legendItem).data(a).enter().append("g").attr("class",function(a){return t.generateClass(h.legendItem,a)}).style("visibility",function(a){return t.isLegendToShow(a)?"visible":"hidden"}).style("cursor","pointer").on("click",function(a){u.legend_item_onclick?u.legend_item_onclick.call(t,a):t.api.toggle(a)}).on("mouseover",function(a){t.d3.select(this).classed(h.legendItemFocused,!0),t.transiting||t.api.focus(a),u.legend_item_onmouseover&&u.legend_item_onmouseover.call(t,a)}).on("mouseout",function(a){t.d3.select(this).classed(h.legendItemFocused,!1),t.transiting||t.api.revert(),u.legend_item_onmouseout&&u.legend_item_onmouseout.call(t,a)}),l.append("text").text(function(a){return m(u.data_names[a])?u.data_names[a]:a}).each(function(a,b){d(this,a,0===b)}).style("pointer-events","none").attr("x",t.isLegendRight||t.isLegendInset?f:-200).attr("y",t.isLegendRight||t.isLegendInset?-200:j),l.append("rect").attr("class",h.legendItemEvent).style("fill-opacity",0).attr("x",t.isLegendRight||t.isLegendInset?g:-200).attr("y",t.isLegendRight||t.isLegendInset?-200:k),l.append("rect").attr("class",h.legendItemTile).style("pointer-events","none").style("fill",t.color).attr("x",t.isLegendRight||t.isLegendInset?f:-200).attr("y",t.isLegendRight||t.isLegendInset?-200:i).attr("width",10).attr("height",10),t.isLegendInset&&0!==x&&t.legend.insert("g","."+h.legendItem).attr("class",h.legendBackground).append("rect").attr("height",t.getLegendHeight()-10).attr("width",x*(G+1)+10),p=t.legend.selectAll("text").data(a).text(function(a){return m(u.data_names[a])?u.data_names[a]:a}).each(function(a,b){d(this,a,0===b)}),(n?p.transition():p).attr("x",f).attr("y",j),q=t.legend.selectAll("rect."+h.legendItemEvent).data(a),(n?q.transition():q).attr("width",function(a){return C[a]}).attr("height",function(a){return D[a]}).attr("x",g).attr("y",k),r=t.legend.selectAll("rect."+h.legendItemTile).data(a),(n?r.transition():r).style("fill",t.color).attr("x",e).attr("y",i),t.legend.selectAll("."+h.legendItem).classed(h.legendItemHidden,function(a){return!t.isTargetToShow(a)}).transition().style("opacity",function(a){var b=t.d3.select(this);return t.isTargetToShow(a)?!H||b.classed(h.legendItemFocused)?t.opacityForLegend(b):t.opacityForUnfocusedLegend(b):t.legendOpacityForHidden}),t.updateLegendItemWidth(x),t.updateLegendItemHeight(y),t.updateLegendStep(G),t.updateSizes(),t.updateScales(),t.updateSvgSize(),t.transformAll(o,c)},f.initAxis=function(){var a=this,b=a.config,c=a.main;a.axes.x=c.append("g").attr("class",h.axis+" "+h.axisX).attr("clip-path",a.clipPathForXAxis).attr("transform",a.getTranslate("x")).style("visibility",b.axis_x_show?"visible":"hidden"),a.axes.x.append("text").attr("class",h.axisXLabel).attr("transform",b.axis_rotated?"rotate(-90)":"").style("text-anchor",a.textAnchorForXAxisLabel.bind(a)),a.axes.y=c.append("g").attr("class",h.axis+" "+h.axisY).attr("clip-path",a.clipPathForYAxis).attr("transform",a.getTranslate("y")).style("visibility",b.axis_y_show?"visible":"hidden"),a.axes.y.append("text").attr("class",h.axisYLabel).attr("transform",b.axis_rotated?"":"rotate(-90)").style("text-anchor",a.textAnchorForYAxisLabel.bind(a)),a.axes.y2=c.append("g").attr("class",h.axis+" "+h.axisY2).attr("transform",a.getTranslate("y2")).style("visibility",b.axis_y2_show?"visible":"hidden"),a.axes.y2.append("text").attr("class",h.axisY2Label).attr("transform",b.axis_rotated?"":"rotate(-90)").style("text-anchor",a.textAnchorForY2AxisLabel.bind(a))},f.getXAxis=function(a,b,c,e){var f=this,g=f.config,h=d(f.d3,f.isCategorized()).scale(a).orient(b);return h.tickFormat(c).tickValues(e),f.isCategorized()?(h.tickCentered(g.axis_x_tick_centered),q(g.axis_x_tick_culling)&&(g.axis_x_tick_culling=!1)):h.tickOffset=function(){var a=f.getEdgeX(f.data.targets),b=f.x(a[1])-f.x(a[0]),c=b?b:g.axis_rotated?f.height:f.width;return c/f.getMaxDataCount()/2},h},f.getYAxis=function(a,b,c,e){return d(this.d3).scale(a).orient(b).tickFormat(c).ticks(e)},f.getAxisId=function(a){var b=this.config;return a in b.data_axes?b.data_axes[a]:"y"},f.getXAxisTickFormat=function(){var a=this,b=a.config,c=a.isTimeSeries()?a.defaultAxisTimeFormat:a.isCategorized()?a.categoryName:function(a){return 0>a?a.toFixed(0):a};return b.axis_x_tick_format&&(j(b.axis_x_tick_format)?c=b.axis_x_tick_format:a.isTimeSeries()&&(c=function(c){return c?a.axisTimeFormat(b.axis_x_tick_format)(c):""})),j(c)?function(b){return c.call(a,b)}:c},f.getAxisLabelOptionByAxisId=function(a){var b,c=this,d=c.config;return"y"===a?b=d.axis_y_label:"y2"===a?b=d.axis_y2_label:"x"===a&&(b=d.axis_x_label),b},f.getAxisLabelText=function(a){var b=this.getAxisLabelOptionByAxisId(a);return k(b)?b:b?b.text:null},f.setAxisLabelText=function(a,b){var c=this,d=c.config,e=c.getAxisLabelOptionByAxisId(a);k(e)?"y"===a?d.axis_y_label=b:"y2"===a?d.axis_y2_label=b:"x"===a&&(d.axis_x_label=b):e&&(e.text=b)},f.getAxisLabelPosition=function(a,b){var c=this.getAxisLabelOptionByAxisId(a),d=c&&"object"==typeof c&&c.position?c.position:b;return{isInner:d.indexOf("inner")>=0,isOuter:d.indexOf("outer")>=0,isLeft:d.indexOf("left")>=0,isCenter:d.indexOf("center")>=0,isRight:d.indexOf("right")>=0,isTop:d.indexOf("top")>=0,isMiddle:d.indexOf("middle")>=0,isBottom:d.indexOf("bottom")>=0}},f.getXAxisLabelPosition=function(){return this.getAxisLabelPosition("x",this.config.axis_rotated?"inner-top":"inner-right")},f.getYAxisLabelPosition=function(){return this.getAxisLabelPosition("y",this.config.axis_rotated?"inner-right":"inner-top")},f.getY2AxisLabelPosition=function(){return this.getAxisLabelPosition("y2",this.config.axis_rotated?"inner-right":"inner-top")},f.getAxisLabelPositionById=function(a){return"y2"===a?this.getY2AxisLabelPosition():"y"===a?this.getYAxisLabelPosition():this.getXAxisLabelPosition()},f.textForXAxisLabel=function(){return this.getAxisLabelText("x")},f.textForYAxisLabel=function(){return this.getAxisLabelText("y")},f.textForY2AxisLabel=function(){return this.getAxisLabelText("y2")},f.xForAxisLabel=function(a,b){var c=this;return a?b.isLeft?0:b.isCenter?c.width/2:c.width:b.isBottom?-c.height:b.isMiddle?-c.height/2:0},f.dxForAxisLabel=function(a,b){return a?b.isLeft?"0.5em":b.isRight?"-0.5em":"0":b.isTop?"-0.5em":b.isBottom?"0.5em":"0"},f.textAnchorForAxisLabel=function(a,b){return a?b.isLeft?"start":b.isCenter?"middle":"end":b.isBottom?"start":b.isMiddle?"middle":"end"},f.xForXAxisLabel=function(){return this.xForAxisLabel(!this.config.axis_rotated,this.getXAxisLabelPosition())},f.xForYAxisLabel=function(){return this.xForAxisLabel(this.config.axis_rotated,this.getYAxisLabelPosition())},f.xForY2AxisLabel=function(){return this.xForAxisLabel(this.config.axis_rotated,this.getY2AxisLabelPosition())},f.dxForXAxisLabel=function(){return this.dxForAxisLabel(!this.config.axis_rotated,this.getXAxisLabelPosition())},f.dxForYAxisLabel=function(){return this.dxForAxisLabel(this.config.axis_rotated,this.getYAxisLabelPosition())},f.dxForY2AxisLabel=function(){return this.dxForAxisLabel(this.config.axis_rotated,this.getY2AxisLabelPosition())},f.dyForXAxisLabel=function(){var a=this,b=a.config,c=a.getXAxisLabelPosition();return b.axis_rotated?c.isInner?"1.2em":-25-a.getMaxTickWidth("x"):c.isInner?"-0.5em":b.axis_x_height?b.axis_x_height-10:"3em"},f.dyForYAxisLabel=function(){var a=this,b=a.getYAxisLabelPosition();return a.config.axis_rotated?b.isInner?"-0.5em":"3em":b.isInner?"1.2em":-20-a.getMaxTickWidth("y")},f.dyForY2AxisLabel=function(){var a=this,b=a.getY2AxisLabelPosition();return a.config.axis_rotated?b.isInner?"1.2em":"-2.2em":b.isInner?"-0.5em":30+this.getMaxTickWidth("y2")},f.textAnchorForXAxisLabel=function(){var a=this;return a.textAnchorForAxisLabel(!a.config.axis_rotated,a.getXAxisLabelPosition())},f.textAnchorForYAxisLabel=function(){var a=this;return a.textAnchorForAxisLabel(a.config.axis_rotated,a.getYAxisLabelPosition())},f.textAnchorForY2AxisLabel=function(){var a=this;return a.textAnchorForAxisLabel(a.config.axis_rotated,a.getY2AxisLabelPosition())},f.xForRotatedTickText=function(a){return 10*Math.sin(Math.PI*(a/180))},f.yForRotatedTickText=function(a){return 11.5-2.5*(a/15)},f.rotateTickText=function(a,b,c){a.selectAll(".tick text").style("text-anchor","start"),b.selectAll(".tick text").attr("y",this.yForRotatedTickText(c)).attr("x",this.xForRotatedTickText(c)).attr("transform","rotate("+c+")")},f.getMaxTickWidth=function(a){var b,c,d,e=this,f=e.config,g=0;return e.svg&&(b=e.filterTargetsToShow(e.data.targets),"y"===a?(c=e.y.copy().domain(e.getYDomain(b,"y")),d=e.getYAxis(c,e.yOrient,f.axis_y_tick_format,f.axis_y_ticks)):"y2"===a?(c=e.y2.copy().domain(e.getYDomain(b,"y2")),d=e.getYAxis(c,e.y2Orient,f.axis_y2_tick_format,f.axis_y2_ticks)):(c=e.x.copy().domain(e.getXDomain(b)),d=e.getXAxis(c,e.xOrient,e.getXAxisTickFormat(),f.axis_x_tick_values?f.axis_x_tick_values:e.xAxis.tickValues())),e.main.append("g").call(d).each(function(){e.d3.select(this).selectAll("text").each(function(){var a=this.getBoundingClientRect();g=g?e.currentMaxTickWidth:g,e.currentMaxTickWidth},f.updateAxisLabels=function(a){var b=this,c=b.main.select("."+h.axisX+" ."+h.axisXLabel),d=b.main.select("."+h.axisY+" ."+h.axisYLabel),e=b.main.select("."+h.axisY2+" ."+h.axisY2Label);(a?c.transition():c).attr("x",b.xForXAxisLabel.bind(b)).attr("dx",b.dxForXAxisLabel.bind(b)).attr("dy",b.dyForXAxisLabel.bind(b)).text(b.textForXAxisLabel.bind(b)),(a?d.transition():d).attr("x",b.xForYAxisLabel.bind(b)).attr("dx",b.dxForYAxisLabel.bind(b)).attr("dy",b.dyForYAxisLabel.bind(b)).text(b.textForYAxisLabel.bind(b)),(a?e.transition():e).attr("x",b.xForY2AxisLabel.bind(b)).attr("dx",b.dxForY2AxisLabel.bind(b)).attr("dy",b.dyForY2AxisLabel.bind(b)).text(b.textForY2AxisLabel.bind(b))},f.getAxisPadding=function(a,b,c,d){var e="ratio"===a.unit?d:1;return i(a[b])?a[b]*e:c},f.generateTickValues=function(a,b){var c,d,e,f,g,h,i,k=this,l=a;if(b)if(c=j(b)?b():b,1===c)l=[a[0]];else if(2===c)l=[a[0],a[a.length-1]];else if(c>2){for(f=c-2,d=a[0],e=a[a.length-1],g=(e-d)/(f+1),l=[d],h=0;f>h;h++)i=+d+g*(h+1),l.push(k.isTimeSeries()?new Date(i):i);l.push(e)}return k.isTimeSeries()||(l=l.sort(function(a,b){return a-b})),l},f.generateAxisTransitions=function(a){var b=this,c=b.axes;return{axisX:a?c.x.transition().duration(a):c.x,axisY:a?c.y.transition().duration(a):c.y,axisY2:a?c.y2.transition().duration(a):c.y2,axisSubX:a?c.subx.transition().duration(a):c.subx}},f.redrawAxis=function(a,b){var c=this;c.axes.x.style("opacity",b?0:1),c.axes.y.style("opacity",b?0:1),c.axes.y2.style("opacity",b?0:1),c.axes.subx.style("opacity",b?0:1),a.axisX.call(c.xAxis),a.axisY.call(c.yAxis),a.axisY2.call(c.y2Axis),a.axisSubX.call(c.subXAxis)},f.getClipPath=function(b){var c=a.navigator.appVersion.toLowerCase().indexOf("msie 9.")>=0;return"url("+(c?"":document.URL.split("#")[0])+"#"+b+")"},f.getAxisClipX=function(a){return a?-31:-(this.margin.left-1)},f.getAxisClipY=function(a){return a?-20:-4},f.getXAxisClipX=function(){var a=this;return a.getAxisClipX(!a.config.axis_rotated)},f.getXAxisClipY=function(){var a=this;return a.getAxisClipY(!a.config.axis_rotated)},f.getYAxisClipX=function(){var a=this;return a.getAxisClipX(a.config.axis_rotated)},f.getYAxisClipY=function(){var a=this;return a.getAxisClipY(a.config.axis_rotated)},f.getAxisClipWidth=function(a){var b=this;return a?b.width+2+30+30:b.margin.left+20},f.getAxisClipHeight=function(a){var b=this,c=b.config;return a?(c.axis_x_height?c.axis_x_height:0)+80:b.height+8},f.getXAxisClipWidth=function(){var a=this;return a.getAxisClipWidth(!a.config.axis_rotated)},f.getXAxisClipHeight=function(){var a=this;return a.getAxisClipHeight(!a.config.axis_rotated)},f.getYAxisClipWidth=function(){var a=this;return a.getAxisClipWidth(a.config.axis_rotated)},f.getYAxisClipHeight=function(){var a=this;return a.getAxisClipHeight(a.config.axis_rotated)},f.initPie=function(){var a=this,b=a.d3,c=a.config;a.pie=b.layout.pie().value(function(a){return a.values.reduce(function(a,b){return a+b.value},0)}),c.data_order&&c.pie_sort&&c.donut_sort||a.pie.sort(null)},f.updateRadius=function(){var a=this,b=a.config,c=b.gauge_width||b.donut_width;a.radiusExpanded=Math.min(a.arcWidth,a.arcHeight)/2,a.radius=.95*a.radiusExpanded,a.innerRadiusRatio=c?(a.radius-c)/a.radius:.6,a.innerRadius=a.hasType("donut")||a.hasType("gauge")?a.radius*a.innerRadiusRatio:0},f.updateArc=function(){var a=this;a.svgArc=a.getSvgArc(),a.svgArcExpanded=a.getSvgArcExpanded(),a.svgArcExpandedSub=a.getSvgArcExpanded(.98)},f.updateAngle=function(a){var b=this,c=b.config,d=!1,e=0;if(b.pie(b.filterTargetsToShow(b.data.targets)).sort(b.descByStartAngle).forEach(function(b){d||b.data.id!==a.data.id||(d=!0,a=b,a.index=e),e++}),isNaN(a.endAngle)&&(a.endAngle=a.startAngle),b.isGaugeType(a.data)){var f=c.gauge_min,g=c.gauge_max,h=Math.abs(f)+g,i=Math.PI/h;a.startAngle=-1*(Math.PI/2)+i*Math.abs(f),a.endAngle=a.startAngle+i*(a.value>g?g:a.value)}return d?a:null},f.getSvgArc=function(){var a=this,b=a.d3.svg.arc().outerRadius(a.radius).innerRadius(a.innerRadius),c=function(c,d){var e;return d?b(c):(e=a.updateAngle(c),e?b(e):"M 0 0")};return c.centroid=b.centroid,c},f.getSvgArcExpanded=function(a){var b=this,c=b.d3.svg.arc().outerRadius(b.radiusExpanded*(a?a:1)).innerRadius(b.innerRadius);return function(a){var d=b.updateAngle(a);return d?c(d):"M 0 0"}},f.getArc=function(a,b,c){return c||this.isArcType(a.data)?this.svgArc(a,b):"M 0 0"},f.transformForArcLabel=function(a){var b,c,d,e,f,g=this,h=g.updateAngle(a),i="";return h&&!g.hasType("gauge")&&(b=this.svgArc.centroid(h),c=isNaN(b[0])?0:b[0],d=isNaN(b[1])?0:b[1],e=Math.sqrt(c*c+d*d),f=g.radius&&e?(36/g.radius>.375?1.175-36/g.radius:.8)*g.radius/e:0,i="translate("+c*f+","+d*f+")"),i},f.getArcRatio=function(a){var b=this,c=b.hasType("gauge")?Math.PI:2*Math.PI;return a?(a.endAngle-a.startAngle)/c:null},f.convertToArcData=function(a){return this.addName({id:a.data.id,value:a.value,ratio:this.getArcRatio(a),index:a.index})},f.textForArcLabel=function(a){var b,c,d,e,f=this;return f.shouldShowArcLabel()?(b=f.updateAngle(a),c=b?b.value:null,d=f.getArcRatio(b),f.hasType("gauge")||f.meetsArcLabelThreshold(d)?(e=f.getArcLabelFormat(),e?e(c,d):f.defaultArcValueFormat(c,d)):""):""},f.expandArc=function(a,b){var c=this,d=c.svg.selectAll("."+h.chartArc+c.selectorTarget(a)),e=c.svg.selectAll("."+h.arc).filter(function(b){return b.data.id!==a});c.shouldExpand(a)&&d.selectAll("path").transition().duration(50).attr("d",c.svgArcExpanded).transition().duration(100).attr("d",c.svgArcExpandedSub).each(function(a){c.isDonutType(a.data)}),b||e.style("opacity",.3)},f.unexpandArc=function(a){var b=this,c=b.svg.selectAll("."+h.chartArc+b.selectorTarget(a));c.selectAll("path."+h.arc).transition().duration(50).attr("d",b.svgArc),b.svg.selectAll("."+h.arc).style("opacity",1)},f.shouldExpand=function(a){var b=this,c=b.config;return b.isDonutType(a)&&c.donut_expand||b.isGaugeType(a)&&c.gauge_expand||b.isPieType(a)&&c.pie_expand},f.shouldShowArcLabel=function(){var a=this,b=a.config,c=!0;return a.hasType("donut")?c=b.donut_label_show:a.hasType("pie")&&(c=b.pie_label_show),c},f.meetsArcLabelThreshold=function(a){var b=this,c=b.config,d=b.hasType("donut")?c.donut_label_threshold:c.pie_label_threshold;return a>=d},f.getArcLabelFormat=function(){var a=this,b=a.config,c=b.pie_label_format;return a.hasType("gauge")?c=b.gauge_label_format:a.hasType("donut")&&(c=b.donut_label_format),c},f.getArcTitle=function(){var a=this;return a.hasType("donut")?a.config.donut_title:""},f.descByStartAngle=function(a,b){return a.startAngle-b.startAngle},f.updateTargetsForArc=function(a){var b,c,d=this,e=d.main,f=d.classChartArc.bind(d),g=d.classArcs.bind(d);b=e.select("."+h.chartArcs).selectAll("."+h.chartArc).data(d.pie(a)).attr("class",f),c=b.enter().append("g").attr("class",f),c.append("g").attr("class",g),c.append("text").attr("dy",d.hasType("gauge")?"-0.35em":".35em").style("opacity",0).style("text-anchor","middle").style("pointer-events","none")},f.initArc=function(){var a=this;a.arcs=a.main.select("."+h.chart).append("g").attr("class",h.chartArcs).attr("transform",a.getTranslate("arc")),a.arcs.append("text").attr("class",h.chartArcsTitle).style("text-anchor","middle").text(a.getArcTitle())},f.redrawArc=function(a,b,c){var d,e=this,f=e.d3,g=e.config,i=e.main;d=i.selectAll("."+h.arcs).selectAll("."+h.arc).data(e.arcData.bind(e)),d.enter().append("path").attr("class",e.classArc.bind(e)).style("fill",function(a){return e.color(a.data)}).style("cursor",function(a){return g.data_selection_isselectable(a)?"pointer":null}).style("opacity",0).each(function(a){e.isGaugeType(a.data)&&(a.startAngle=a.endAngle=-1*(Math.PI/2)),this._current=a}).on("mouseover",function(a){var b,c;e.transiting||(b=e.updateAngle(a),c=e.convertToArcData(b),e.expandArc(b.data.id),e.toggleFocusLegend(b.data.id,!0),e.config.data_onmouseover(c,this))}).on("mousemove",function(a){var b=e.updateAngle(a),c=e.convertToArcData(b),d=[c];e.showTooltip(d,f.mouse(this))}).on("mouseout",function(a){var b,c;e.transiting||(b=e.updateAngle(a),c=e.convertToArcData(b),e.unexpandArc(b.data.id),e.revertLegend(),e.hideTooltip(),e.config.data_onmouseout(c,this))}).on("click",function(a,b){var c,d;e.toggleShape&&(c=e.updateAngle(a),d=e.convertToArcData(c),e.toggleShape(this,d,b))}),d.attr("transform",function(a){return!e.isGaugeType(a.data)&&c?"scale(0)":""}).style("opacity",function(a){return a===this._current?0:1}).each(function(){e.transiting=!0}).transition().duration(a).attrTween("d",function(a){var b,c=e.updateAngle(a);return c?(isNaN(this._current.endAngle)&&(this._current.endAngle=this._current.startAngle),b=f.interpolate(this._current,c),this._current=b(0),function(a){return e.getArc(b(a),!0)}):function(){return"M 0 0"}}).attr("transform",c?"scale(1)":"").style("fill",function(a){return e.levelColor?e.levelColor(a.data.values[0].value):e.color(a.data.id)}).style("opacity",1).call(e.endall,function(){e.transiting=!1}),d.exit().transition().duration(b).style("opacity",0).remove(),i.selectAll("."+h.chartArc).select("text").style("opacity",0).attr("class",function(a){return e.isGaugeType(a.data)?h.gaugeValue:""}).text(e.textForArcLabel.bind(e)).attr("transform",e.transformForArcLabel.bind(e)).transition().duration(a).style("opacity",function(a){return e.isTargetToShow(a.data.id)&&e.isArcType(a.data)?1:0}),i.select("."+h.chartArcsTitle).style("opacity",e.hasType("donut")||e.hasType("gauge")?1:0)},f.initGauge=function(){var a=this,b=a.config,c=a.arcs;a.hasType("gauge")&&(c.append("path").attr("class",h.chartArcsBackground).attr("d",function(){var c={data:[{value:b.gauge_max}],startAngle:-1*(Math.PI/2),endAngle:Math.PI/2};return a.getArc(c,!0,!0)}),c.append("text").attr("dy",".75em").attr("class",h.chartArcsGaugeUnit).style("text-anchor","middle").style("pointer-events","none").text(b.gauge_label_show?b.gauge_units:""),c.append("text").attr("dx",-1*(a.innerRadius+(a.radius-a.innerRadius)/2)+"px").attr("dy","1.2em").attr("class",h.chartArcsGaugeMin).style("text-anchor","middle").style("pointer-events","none").text(b.gauge_label_show?b.gauge_min:""),c.append("text").attr("dx",a.innerRadius+(a.radius-a.innerRadius)/2+"px").attr("dy","1.2em").attr("class",h.chartArcsGaugeMax).style("text-anchor","middle").style("pointer-events","none").text(b.gauge_label_show?b.gauge_max:""))},f.initRegion=function(){var a=this;a.main.append("g").attr("clip-path",a.clipPath).attr("class",h.regions)},f.redrawRegion=function(a){var b=this,c=b.config;b.mainRegion=b.main.select("."+h.regions).selectAll("."+h.region).data(c.regions),b.mainRegion.enter().append("g").attr("class",b.classRegion.bind(b)).append("rect").style("fill-opacity",0),b.mainRegion.exit().transition().duration(a).style("opacity",0).remove()},f.addTransitionForRegion=function(a){var b=this,c=b.regionX.bind(b),d=b.regionY.bind(b),e=b.regionWidth.bind(b),f=b.regionHeight.bind(b);a.push(b.mainRegion.selectAll("rect").transition().attr("x",c).attr("y",d).attr("width",e).attr("height",f).style("fill-opacity",function(a){return i(a.opacity)?a.opacity:.1}))},f.regionX=function(a){var b,c=this,d=c.config,e="y"===a.axis?c.y:c.y2;return b="y"===a.axis||"y2"===a.axis?d.axis_rotated?"start"in a?e(a.start):0:0:d.axis_rotated?0:"start"in a?c.x(c.isTimeSeries()?c.parseDate(a.start):a.start):0},f.regionY=function(a){var b,c=this,d=c.config,e="y"===a.axis?c.y:c.y2;return b="y"===a.axis||"y2"===a.axis?d.axis_rotated?0:"end"in a?e(a.end):0:d.axis_rotated?"start"in a?c.x(c.isTimeSeries()?c.parseDate(a.start):a.start):0:0},f.regionWidth=function(a){var b,c=this,d=c.config,e=c.regionX(a),f="y"===a.axis?c.y:c.y2;return b="y"===a.axis||"y2"===a.axis?d.axis_rotated?"end"in a?f(a.end):c.width:c.width:d.axis_rotated?c.width:"end"in a?c.x(c.isTimeSeries()?c.parseDate(a.end):a.end):c.width,e>b?0:b-e},f.regionHeight=function(a){var b,c=this,d=c.config,e=this.regionY(a),f="y"===a.axis?c.y:c.y2;return b="y"===a.axis||"y2"===a.axis?d.axis_rotated?c.height:"start"in a?f(a.start):c.height:d.axis_rotated?"end"in a?c.x(c.isTimeSeries()?c.parseDate(a.end):a.end):c.height:c.height,e>b?0:b-e},f.isRegionOnX=function(a){return!a.axis||"x"===a.axis},f.drag=function(a){var b,c,d,e,f,g,i,j,k=this,l=k.config,m=k.main,n=k.d3;k.hasArcType()||l.data_selection_enabled&&(!l.zoom_enabled||k.zoom.altDomain)&&l.data_selection_multiple&&(b=k.dragStart[0],c=k.dragStart[1],d=a[0],e=a[1],f=Math.min(b,d),g=Math.max(b,d),i=l.data_selection_grouped?k.margin.top:Math.min(c,e),j=l.data_selection_grouped?k.height:Math.max(c,e),m.select("."+h.dragarea).attr("x",f).attr("y",i).attr("width",g-f).attr("height",j-i),m.selectAll("."+h.shapes).selectAll("."+h.shape).filter(function(a){return l.data_selection_isselectable(a)}).each(function(a,b){var c,d,e,l,m,o,p=n.select(this),q=p.classed(h.SELECTED),r=p.classed(h.INCLUDED),s=!1;if(p.classed(h.circle))c=1*p.attr("cx"),d=1*p.attr("cy"),m=k.togglePoint,s=c>f&&g>c&&d>i&&j>d;else{if(!p.classed(h.bar))return;o=u(this),c=o.x,d=o.y,e=o.width,l=o.height,m=k.toggleBar,s=!(c>g||f>c+e||d>j||i>d+l)}s^r&&(p.classed(h.INCLUDED,!r),p.classed(h.SELECTED,!q),m.call(k,!q,p,a,b))}))},f.dragstart=function(a){var b=this,c=b.config;b.hasArcType()||c.data_selection_enabled&&(b.dragStart=a,b.main.select("."+h.chart).append("rect").attr("class",h.dragarea).style("opacity",.1),b.dragging=!0,b.config.data_ondragstart())},f.dragend=function(){var a=this,b=a.config;a.hasArcType()||b.data_selection_enabled&&(a.main.select("."+h.dragarea).transition().duration(100).style("opacity",0).remove(),a.main.selectAll("."+h.shape).classed(h.INCLUDED,!1),a.dragging=!1,a.config.data_ondragend())},f.selectPoint=function(a,b,c){var d=this,e=d.config,f=(e.axis_rotated?d.circleY:d.circleX).bind(d),g=(e.axis_rotated?d.circleX:d.circleY).bind(d),i=d.pointSelectR.bind(d);e.data_onselected.call(d.api,b,a.node()),d.main.select("."+h.selectedCircles+d.getTargetSelectorSuffix(b.id)).selectAll("."+h.selectedCircle+"-"+c).data([b]).enter().append("circle").attr("class",function(){return d.generateClass(h.selectedCircle,c)}).attr("cx",f).attr("cy",g).attr("stroke",function(){return d.color(b)}).attr("r",function(a){return 1.4*d.pointSelectR(a)}).transition().duration(100).attr("r",i)},f.unselectPoint=function(a,b,c){var d=this;d.config.data_onunselected(b,a.node()),d.main.select("."+h.selectedCircles+d.getTargetSelectorSuffix(b.id)).selectAll("."+h.selectedCircle+"-"+c).transition().duration(100).attr("r",0).remove()},f.togglePoint=function(a,b,c,d){a?this.selectPoint(b,c,d):this.unselectPoint(b,c,d)},f.selectBar=function(a,b){var c=this;c.config.data_onselected.call(c,b,a.node()),a.transition().duration(100).style("fill",function(){return c.d3.rgb(c.color(b)).brighter(.75)})},f.unselectBar=function(a,b){var c=this;c.config.data_onunselected.call(c,b,a.node()),a.transition().duration(100).style("fill",function(){return c.color(b)})},f.toggleBar=function(a,b,c,d){a?this.selectBar(b,c,d):this.unselectBar(b,c,d)},f.toggleArc=function(a,b,c,d){this.toggleBar(a,b,c.data,d)},f.getToggle=function(a){var b=this;return"circle"===a.nodeName?b.togglePoint:b.d3.select(a).classed(h.bar)?b.toggleBar:b.toggleArc},f.toggleShape=function(a,b,c){var d,e,f=this,g=f.d3,i=f.config,j=g.select(a),k=j.classed(h.SELECTED);"circle"===a.nodeName?(d=f.isWithinCircle(a,1.5*f.pointSelectR(b)),e=f.togglePoint):"path"===a.nodeName&&(j.classed(h.bar)?(d=f.isWithinBar(a),e=f.toggleBar):(d=!0,e=f.toggleArc)),(i.data_selection_grouped||d)&&(i.data_selection_enabled&&i.data_selection_isselectable(b)&&(i.data_selection_multiple||f.main.selectAll("."+h.shapes+(i.data_selection_grouped?f.getTargetSelectorSuffix(b.id):"")).selectAll("."+h.shape).each(function(a,b){var c=g.select(this);c.classed(h.SELECTED)&&e.call(f,!1,c.classed(h.SELECTED,!1),a,b)}),j.classed(h.SELECTED,!k),e.call(f,!k,j,b,c)),f.config.data_onclick.call(f.api,b,a))},f.initBrush=function(){var a=this,b=a.d3;a.brush=b.svg.brush().on("brush",function(){a.redrawForBrush()}),a.brush.update=function(){return a.context&&a.context.select("."+h.brush).call(this),this +},a.brush.scale=function(b){return a.config.axis_rotated?this.y(b):this.x(b)}},f.initSubchart=function(){var a=this,b=a.config,c=a.context=a.svg.append("g").attr("transform",a.getTranslate("context"));b.subchart_show||c.style("visibility","hidden"),c.append("g").attr("clip-path",a.clipPath).attr("class",h.chart),c.select("."+h.chart).append("g").attr("class",h.chartBars),c.select("."+h.chart).append("g").attr("class",h.chartLines),c.append("g").attr("clip-path",a.clipPath).attr("class",h.brush).call(a.brush).selectAll("rect").attr(b.axis_rotated?"width":"height",b.axis_rotated?a.width2:a.height2),a.axes.subx=c.append("g").attr("class",h.axisX).attr("transform",a.getTranslate("subx")).attr("clip-path",b.axis_rotated?"":a.clipPathForXAxis)},f.updateTargetsForSubchart=function(a){var b,c,d,e,f=this,g=f.context,i=f.config,j=f.classChartBar.bind(f),k=f.classBars.bind(f),l=f.classChartLine.bind(f),m=f.classLines.bind(f),n=f.classAreas.bind(f);i.subchart_show&&(e=g.select("."+h.chartBars).selectAll("."+h.chartBar).data(a).attr("class",j),d=e.enter().append("g").style("opacity",0).attr("class",j),d.append("g").attr("class",k),c=g.select("."+h.chartLines).selectAll("."+h.chartLine).data(a).attr("class",l),b=c.enter().append("g").style("opacity",0).attr("class",l),b.append("g").attr("class",m),b.append("g").attr("class",n))},f.redrawSubchart=function(a,b,c,d,e,f,g){var i,j,k,l,m,n,o=this,p=o.d3,q=o.context,r=o.config,s=o.barData.bind(o),t=o.lineData.bind(o),u=o.classBar.bind(o),v=o.classLine.bind(o),w=o.classArea.bind(o),x=o.initialOpacity.bind(o);r.subchart_show&&(p.event&&"zoom"===p.event.type&&o.brush.extent(o.x.orgDomain()).update(),a&&(!r.axis_rotated&&r.axis_x_tick_rotate&&o.rotateTickText(o.axes.subx,b.axisSubX,r.axis_x_tick_rotate),o.brush.empty()||o.brush.extent(o.x.orgDomain()).update(),l=o.generateDrawArea(e,!0),m=o.generateDrawBar(f,!0),n=o.generateDrawLine(g,!0),k=q.selectAll("."+h.bars).selectAll("."+h.bar).data(s),k.enter().append("path").attr("class",u).style("stroke","none").style("fill",o.color),k.style("opacity",x).transition().duration(c).attr("d",m).style("opacity",1),k.exit().transition().duration(c).style("opacity",0).remove(),i=q.selectAll("."+h.lines).selectAll("."+h.line).data(t),i.enter().append("path").attr("class",v).style("stroke",o.color),i.style("opacity",x).transition().duration(c).attr("d",n).style("opacity",1),i.exit().transition().duration(c).style("opacity",0).remove(),j=q.selectAll("."+h.areas).selectAll("."+h.area).data(t),j.enter().append("path").attr("class",w).style("fill",o.color).style("opacity",function(){return o.orgAreaOpacity=+p.select(this).style("opacity"),0}),j.style("opacity",0).transition().duration(c).attr("d",l).style("fill",o.color).style("opacity",o.orgAreaOpacity),j.exit().transition().duration(d).style("opacity",0).remove()))},f.redrawForBrush=function(){var a=this,b=a.x;a.redraw({withTransition:!1,withY:!1,withSubchart:!1,withUpdateXDomain:!0}),a.config.subchart_onbrush.call(a.api,b.orgDomain())},f.transformContext=function(a,b){var c,d=this;b&&b.axisSubX?c=b.axisSubX:(c=d.context.select("."+h.axisX),a&&(c=c.transition())),d.context.attr("transform",d.getTranslate("context")),c.attr("transform",d.getTranslate("subx"))},f.initZoom=function(){var a=this,b=a.d3,c=a.config;a.zoom=b.behavior.zoom().on("zoomstart",function(){a.zoom.altDomain=b.event.sourceEvent.altKey?a.x.orgDomain():null}).on("zoom",function(){a.redrawForZoom.call(a)}),a.zoom.scale=function(a){return c.axis_rotated?this.y(a):this.x(a)},a.zoom.orgScaleExtent=function(){var b=c.zoom_extent?c.zoom_extent:[1,10];return[b[0],Math.max(a.getMaxDataCount()/b[1],b[1])]},a.zoom.updateScaleExtent=function(){var b=p(a.x.orgDomain())/p(a.orgXDomain),c=this.orgScaleExtent();return this.scaleExtent([c[0]*b,c[1]*b]),this}},f.updateZoom=function(){var a=this,b=a.config.zoom_enabled?a.zoom:function(){};a.main.select("."+h.zoomRect).call(b),a.main.selectAll("."+h.eventRect).call(b)},f.redrawForZoom=function(){var a=this,b=a.d3,c=a.config,d=a.zoom,e=a.x,f=a.orgXDomain;if(c.zoom_enabled&&0!==a.filterTargetsToShow(a.data.targets).length){if("mousemove"===b.event.sourceEvent.type&&d.altDomain)return e.domain(d.altDomain),void d.scale(e).updateScaleExtent();a.isCategorized()&&e.orgDomain()[0]===f[0]&&e.domain([f[0]-1e-10,e.orgDomain()[1]]),a.redraw({withTransition:!1,withY:!1,withSubchart:!1}),"mousemove"===b.event.sourceEvent.type&&(a.cancelClick=!0),c.zoom_onzoom.call(a.api,e.orgDomain())}},f.generateColor=function(){var a=this,b=a.config,c=a.d3,d=b.data_colors,e=r(b.color_pattern)?b.color_pattern:c.scale.category10().range(),f=b.data_color,g=[];return function(a){var b,c=a.id||a;return d[c]instanceof Function?b=d[c](a):d[c]?b=d[c]:(g.indexOf(c)<0&&g.push(c),b=e[g.indexOf(c)%e.length],d[c]=b),f instanceof Function?f(b,a):b}},f.generateLevelColor=function(){var a=this,b=a.config,c=b.color_pattern,d=b.color_threshold,e="value"===d.unit,f=d.values&&d.values.length?d.values:[],g=d.max||100;return r(b.color_threshold)?function(a){var b,d,h=c[c.length-1];for(b=0;b0},s=f.getOption=function(a,b,c){return m(a[b])?a[b]:c},t=f.hasValue=function(a,b){var c=!1;return Object.keys(a).forEach(function(d){a[d]===b&&(c=!0)}),c},u=f.getPathBox=function(a){var b=a.getBoundingClientRect(),c=[a.pathSegList.getItem(0),a.pathSegList.getItem(1)],d=c[0].x,e=Math.min(c[0].y,c[1].y);return{x:d,y:e,width:b.width,height:b.height}};e.focus=function(a){function b(a){c.filterTargetsToShow(a).transition().duration(100).style("opacity",1)}var c=this.internal,d=c.svg.selectAll(c.selectorTarget(a)),e=d.filter(c.isNoneArc.bind(c)),f=d.filter(c.isArc.bind(c));this.revert(),this.defocus(),b(e.classed(h.focused,!0)),b(f),c.hasArcType()&&c.expandArc(a,!0),c.toggleFocusLegend(a,!0)},e.defocus=function(a){function b(a){c.filterTargetsToShow(a).transition().duration(100).style("opacity",.3)}var c=this.internal,d=c.svg.selectAll(c.selectorTarget(a)),e=d.filter(c.isNoneArc.bind(c)),f=d.filter(c.isArc.bind(c));this.revert(),b(e.classed(h.focused,!1)),b(f),c.hasArcType()&&c.unexpandArc(a),c.toggleFocusLegend(a,!1)},e.revert=function(a){function b(a){c.filterTargetsToShow(a).transition().duration(100).style("opacity",1)}var c=this.internal,d=c.svg.selectAll(c.selectorTarget(a)),e=d.filter(c.isNoneArc.bind(c)),f=d.filter(c.isArc.bind(c));b(e.classed(h.focused,!1)),b(f),c.hasArcType()&&c.unexpandArc(a),c.revertLegend()},e.show=function(a,b){var c=this.internal;a=c.mapToTargetIds(a),b=b||{},c.removeHiddenTargetIds(a),c.svg.selectAll(c.selectorTargets(a)).transition().style("opacity",1),b.withLegend&&c.showLegend(a),c.redraw({withUpdateOrgXDomain:!0,withUpdateXDomain:!0,withLegend:!0})},e.hide=function(a,b){var c=this.internal;a=c.mapToTargetIds(a),b=b||{},c.addHiddenTargetIds(a),c.svg.selectAll(c.selectorTargets(a)).transition().style("opacity",0),b.withLegend&&c.hideLegend(a),c.redraw({withUpdateOrgXDomain:!0,withUpdateXDomain:!0,withLegend:!0})},e.toggle=function(a){var b=this.internal;b.isTargetToShow(a)?this.hide(a):this.show(a)},e.zoom=function(){},e.zoom.enable=function(a){var b=this.internal;b.config.zoom_enabled=a,b.updateAndRedraw()},e.unzoom=function(){var a=this.internal;a.brush.clear().update(),a.redraw({withUpdateXDomain:!0})},e.load=function(a){var b=this.internal,c=b.config;return a.xs&&b.addXs(a.xs),"classes"in a&&Object.keys(a.classes).forEach(function(b){c.data_classes[b]=a.classes[b]}),"categories"in a&&b.isCategorized()&&(c.axis_x_categories=a.categories),"cacheIds"in a&&b.hasCaches(a.cacheIds)?void b.load(b.getCaches(a.cacheIds),a.done):void("unload"in a?b.unload(b.mapToTargetIds("boolean"==typeof a.unload&&a.unload?null:a.unload),function(){b.loadFromArgs(a)}):b.loadFromArgs(a))},e.unload=function(a){var b=this.internal;a=a||{},b.unload(b.mapToTargetIds(a.ids),function(){b.redraw({withUpdateOrgXDomain:!0,withUpdateXDomain:!0,withLegend:!0}),a.done&&a.done()})},e.flow=function(a){var b,c,d,e,f,g,h,j,k=this.internal,l=[],n=k.getMaxDataCount(),o=0,p=0;if(a.json)c=k.convertJsonToData(a.json,a.keys);else if(a.rows)c=k.convertRowsToData(a.rows);else{if(!a.columns)return;c=k.convertColumnsToData(a.columns)}b=k.convertDataToTargets(c,!0),k.data.targets.forEach(function(a){var c,d,e=!1;for(c=0;cd;d++)b[c].values[d].index=p+d,k.isTimeSeries()||(b[c].values[d].x=p+d);a.values=a.values.concat(b[c].values),b.splice(c,1);break}e||l.push(a.id)}),k.data.targets.forEach(function(a){var b,c;for(b=0;bc;c++)a.values.push({id:a.id,index:p+c,x:k.isTimeSeries()?k.getOtherTargetX(p+c):p+c,value:null})}),k.data.targets.length&&b.forEach(function(a){var b,c=[];for(b=k.data.targets[0].values[0].index;p>b;b++)c.push({id:a.id,index:b,x:k.isTimeSeries()?k.getOtherTargetX(b):b,value:null});a.values.forEach(function(a){a.index+=p,k.isTimeSeries()||(a.x+=p)}),a.values=c.concat(a.values)}),k.data.targets=k.data.targets.concat(b),d=k.getMaxDataCount(),f=k.data.targets[0],g=f.values[0],m(a.to)?(o=0,j=k.isTimeSeries()?k.parseDate(a.to):a.to,f.values.forEach(function(a){a.x1?f.values[f.values.length-1].x-g.x:g.x-k.getXDomain(k.data.targets)[0]:1,e=[g.x-h,g.x],k.updateXDomain(null,!0,!0,e)),k.updateTargets(k.data.targets),k.redraw({flow:{index:g.index,length:o,duration:i(a.duration)?a.duration:k.config.transition_duration,done:a.done,orgDataCount:n},withLegend:!0,withTransition:n>1})},f.generateFlow=function(a){var b=this,c=b.config,d=b.d3;return function(){var e,f,g,i=a.targets,j=a.flow,k=a.drawBar,l=a.drawLine,m=a.drawArea,n=a.cx,o=a.cy,q=a.xv,r=a.xForText,s=a.yForText,t=a.duration,u=1,v=j.index,w=j.length,x=b.getValueOnIndex(b.data.targets[0].values,v),y=b.getValueOnIndex(b.data.targets[0].values,v+w),z=b.x.domain(),A=j.duration||t,B=j.done||function(){},C=b.generateWait(),D=b.xgrid||d.selectAll([]),E=b.xgridLines||d.selectAll([]),F=b.mainRegion||d.selectAll([]),G=b.mainText||d.selectAll([]),H=b.mainBar||d.selectAll([]),I=b.mainLine||d.selectAll([]),J=b.mainArea||d.selectAll([]),K=b.mainCircle||d.selectAll([]);b.data.targets.forEach(function(a){a.values.splice(0,w)}),g=b.updateXDomain(i,!0,!0),b.updateXGrid&&b.updateXGrid(!0),j.orgDataCount?e=1===j.orgDataCount||x.x===y.x?b.x(z[0])-b.x(g[0]):b.isTimeSeries()?b.x(z[0])-b.x(g[0]):b.x(x.x)-b.x(y.x):1!==b.data.targets[0].values.length?e=b.x(z[0])-b.x(g[0]):b.isTimeSeries()?(x=b.getValueOnIndex(b.data.targets[0].values,0),y=b.getValueOnIndex(b.data.targets[0].values,b.data.targets[0].values.length-1),e=b.x(x.x)-b.x(y.x)):e=p(g)/2,u=p(z)/p(g),f="translate("+e+",0) scale("+u+",1)",d.transition().ease("linear").duration(A).each(function(){C.add(b.axes.x.transition().call(b.xAxis)),C.add(H.transition().attr("transform",f)),C.add(I.transition().attr("transform",f)),C.add(J.transition().attr("transform",f)),C.add(K.transition().attr("transform",f)),C.add(G.transition().attr("transform",f)),C.add(F.filter(b.isRegionOnX).transition().attr("transform",f)),C.add(D.transition().attr("transform",f)),C.add(E.transition().attr("transform",f))}).call(C,function(){var a,d=[],e=[],f=[];if(w){for(a=0;w>a;a++)d.push("."+h.shape+"-"+(v+a)),e.push("."+h.text+"-"+(v+a)),f.push("."+h.eventRect+"-"+(v+a));b.svg.selectAll("."+h.shapes).selectAll(d).remove(),b.svg.selectAll("."+h.texts).selectAll(e).remove(),b.svg.selectAll("."+h.eventRects).selectAll(f).remove(),b.svg.select("."+h.xgrid).remove()}D.attr("transform",null).attr(b.xgridAttr),E.attr("transform",null),E.select("line").attr("x1",c.axis_rotated?0:q).attr("x2",c.axis_rotated?b.width:q),E.select("text").attr("x",c.axis_rotated?b.width:0).attr("y",q),H.attr("transform",null).attr("d",k),I.attr("transform",null).attr("d",l),J.attr("transform",null).attr("d",m),K.attr("transform",null).attr("cx",n).attr("cy",o),G.attr("transform",null).attr("x",r).attr("y",s).style("fill-opacity",b.opacityForText.bind(b)),F.attr("transform",null),F.select("rect").filter(b.isRegionOnX).attr("x",b.regionX.bind(b)).attr("width",b.regionWidth.bind(b)),b.updateEventRect(),B()})}},e.selected=function(a){var b=this.internal,c=b.d3;return c.merge(b.main.selectAll("."+h.shapes+b.getTargetSelectorSuffix(a)).selectAll("."+h.shape).filter(function(){return c.select(this).classed(h.SELECTED)}).map(function(a){return a.map(function(a){var b=a.__data__;return b.data?b.data:b})}))},e.select=function(a,b,c){var d=this.internal,e=d.d3,f=d.config;f.data_selection_enabled&&d.main.selectAll("."+h.shapes).selectAll("."+h.shape).each(function(g,i){var j=e.select(this),k=g.data?g.data.id:g.id,l=d.getToggle(this).bind(d),n=f.data_selection_grouped||!a||a.indexOf(k)>=0,o=!b||b.indexOf(i)>=0,p=j.classed(h.SELECTED);j.classed(h.line)||j.classed(h.area)||(n&&o?f.data_selection_isselectable(g)&&!p&&l(!0,j.classed(h.SELECTED,!0),g,i):m(c)&&c&&p&&l(!1,j.classed(h.SELECTED,!1),g,i))})},e.unselect=function(a,b){var c=this.internal,d=c.d3,e=c.config;e.data_selection_enabled&&c.main.selectAll("."+h.shapes).selectAll("."+h.shape).each(function(f,g){var i=d.select(this),j=f.data?f.data.id:f.id,k=c.getToggle(this).bind(c),l=e.data_selection_grouped||!a||a.indexOf(j)>=0,m=!b||b.indexOf(g)>=0,n=i.classed(h.SELECTED);i.classed(h.line)||i.classed(h.area)||l&&m&&e.data_selection_isselectable(f)&&n&&k(!1,i.classed(h.SELECTED,!1),f,g)})},e.transform=function(a,b){var c=this.internal,d=["pie","donut"].indexOf(a)>=0?{withTransform:!0}:null;c.transformTo(b,a,d)},f.transformTo=function(a,b,c){var d=this,e=!d.hasArcType(),f=c||{withTransitionForAxis:e};f.withTransitionForTransform=!1,d.transiting=!1,d.setTargetType(a,b),d.updateAndRedraw(f)},e.groups=function(a){var b=this.internal,c=b.config;return l(a)?c.data_groups:(c.data_groups=a,b.redraw(),c.data_groups)},e.xgrids=function(a){var b=this.internal,c=b.config;return a?(c.grid_x_lines=a,b.redraw(),c.grid_x_lines):c.grid_x_lines},e.xgrids.add=function(a){var b=this.internal;return this.xgrids(b.config.grid_x_lines.concat(a?a:[]))},e.xgrids.remove=function(a){var b=this.internal;b.removeGridLines(a,!0)},e.ygrids=function(a){var b=this.internal,c=b.config;return a?(c.grid_y_lines=a,b.redraw(),c.grid_y_lines):c.grid_y_lines},e.ygrids.add=function(a){var b=this.internal;return this.ygrids(b.config.grid_y_lines.concat(a?a:[]))},e.ygrids.remove=function(a){var b=this.internal;b.removeGridLines(a,!1)},e.regions=function(a){var b=this.internal,c=b.config;return a?(c.regions=a,b.redraw(),c.regions):c.regions},e.regions.add=function(a){var b=this.internal,c=b.config;return a?(c.regions=c.regions.concat(a),b.redraw(),c.regions):c.regions},e.regions.remove=function(a){var b,c,d,e=this.internal,f=e.config;return a=a||{},b=e.getOption(a,"duration",f.transition_duration),c=e.getOption(a,"classes",[h.region]),d=e.main.select("."+h.regions).selectAll(c.map(function(a){return"."+a})),(b?d.transition().duration(b):d).style("opacity",0).remove(),f.regions=f.regions.filter(function(a){var b=!1;return a.class?(a.class.split(" ").forEach(function(a){c.indexOf(a)>=0&&(b=!0)}),!b):!0}),f.regions},e.data=function(){},e.data.get=function(a){var b=this.data.getAsTarget(a);return m(b)?b.values.map(function(a){return a.value}):void 0},e.data.getAsTarget=function(a){var b=this.data.targets.filter(function(b){return b.id===a});return b.length>0?b[0]:void 0},e.data.names=function(a){var b=this.internal,c=b.config;return arguments.length?(Object.keys(a).forEach(function(b){c.data_names[b]=a[b]}),b.redraw({withLegend:!0}),c.data_names):c.data_names},e.data.colors=function(a){var b=this.internal,c=b.config;return arguments.length?(Object.keys(a).forEach(function(b){c.data_colors[b]=a[b]}),b.redraw({withLegend:!0}),c.data_colors):c.data_colors},e.category=function(a,b){var c=this.internal,d=c.config;return arguments.length>1&&(d.axis_x_categories[a]=b,c.redraw()),d.axis_x_categories[a]},e.categories=function(a){var b=this.internal,c=b.config;return arguments.length?(c.axis_x_categories=a,b.redraw(),c.axis_x_categories):c.axis_x_categories},e.color=function(a){var b=this.internal;return b.color(a)},e.x=function(a){var b=this.internal;return arguments.length&&(b.updateTargetX(b.data.targets,a),b.redraw({withUpdateOrgXDomain:!0,withUpdateXDomain:!0})),b.data.xs},e.xs=function(a){var b=this.internal;return arguments.length&&(b.updateTargetXs(b.data.targets,a),b.redraw({withUpdateOrgXDomain:!0,withUpdateXDomain:!0})),b.data.xs},e.axis=function(){},e.axis.labels=function(a){var b=this.internal;arguments.length&&(Object.keys(a).forEach(function(c){b.setAxisLabelText(c,a[c])}),b.updateAxisLabels())},e.axis.max=function(a){var b=this.internal,c=b.config;arguments.length&&("object"==typeof a?(i(a.x)&&(c.axis_x_max=a.x),i(a.y)&&(c.axis_y_max=a.y),i(a.y2)&&(c.axis_y2_max=a.y2)):c.axis_y_max=c.axis_y2_max=a,b.redraw({withUpdateOrgXDomain:!0,withUpdateXDomain:!0}))},e.axis.min=function(a){var b=this.internal,c=b.config;arguments.length&&("object"==typeof a?(i(a.x)&&(c.axis_x_min=a.x),i(a.y)&&(c.axis_y_min=a.y),i(a.y2)&&(c.axis_y2_min=a.y2)):c.axis_y_min=c.axis_y2_min=a,b.redraw({withUpdateOrgXDomain:!0,withUpdateXDomain:!0}))},e.axis.range=function(a){arguments.length&&(m(a.max)&&this.axis.max(a.max),m(a.min)&&this.axis.min(a.min))},e.legend=function(){},e.legend.show=function(a){var b=this.internal;b.showLegend(b.mapToTargetIds(a)),b.updateAndRedraw({withLegend:!0})},e.legend.hide=function(a){var b=this.internal;b.hideLegend(b.mapToTargetIds(a)),b.updateAndRedraw({withLegend:!0})},e.resize=function(a){var b=this.internal,c=b.config;c.size_width=a?a.width:null,c.size_height=a?a.height:null,this.flush()},e.flush=function(){var a=this.internal;a.updateAndRedraw({withLegend:!0,withTransition:!1,withTransitionForTransform:!1})},e.destroy=function(){var b=this.internal;b.data.targets=void 0,b.data.xs={},b.selectChart.classed("c3",!1).html(""),a.onresize=null},"function"==typeof define&&define.amd?define("c3",["d3"],g):"undefined"!=typeof exports&&"undefined"!=typeof module?module.exports=g:a.c3=g}(window); \ No newline at end of file diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.geo-devices/public/js/d3/d3.min.js b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.geo-devices/public/js/d3/d3.min.js new file mode 100644 index 0000000000..88550ae512 --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.geo-devices/public/js/d3/d3.min.js @@ -0,0 +1,5 @@ +!function(){function n(n,t){return t>n?-1:n>t?1:n>=t?0:0/0}function t(n){return null!=n&&!isNaN(n)}function e(n){return{left:function(t,e,r,u){for(arguments.length<3&&(r=0),arguments.length<4&&(u=t.length);u>r;){var i=r+u>>>1;n(t[i],e)<0?r=i+1:u=i}return r},right:function(t,e,r,u){for(arguments.length<3&&(r=0),arguments.length<4&&(u=t.length);u>r;){var i=r+u>>>1;n(t[i],e)>0?u=i:r=i+1}return r}}}function r(n){return n.length}function u(n){for(var t=1;n*t%1;)t*=10;return t}function i(n,t){try{for(var e in t)Object.defineProperty(n.prototype,e,{value:t[e],enumerable:!1})}catch(r){n.prototype=t}}function o(){}function a(n){return ia+n in this}function c(n){return n=ia+n,n in this&&delete this[n]}function s(){var n=[];return this.forEach(function(t){n.push(t)}),n}function l(){var n=0;for(var t in this)t.charCodeAt(0)===oa&&++n;return n}function f(){for(var n in this)if(n.charCodeAt(0)===oa)return!1;return!0}function h(){}function g(n,t,e){return function(){var r=e.apply(t,arguments);return r===t?n:r}}function p(n,t){if(t in n)return t;t=t.charAt(0).toUpperCase()+t.substring(1);for(var e=0,r=aa.length;r>e;++e){var u=aa[e]+t;if(u in n)return u}}function v(){}function d(){}function m(n){function t(){for(var t,r=e,u=-1,i=r.length;++ue;e++)for(var u,i=n[e],o=0,a=i.length;a>o;o++)(u=i[o])&&t(u,o,e);return n}function U(n){return sa(n,da),n}function j(n){var t,e;return function(r,u,i){var o,a=n[i].update,c=a.length;for(i!=e&&(e=i,t=0),u>=t&&(t=u+1);!(o=a[t])&&++t0&&(n=n.substring(0,a));var s=ya.get(n);return s&&(n=s,c=Y),a?t?u:r:t?v:i}function O(n,t){return function(e){var r=Zo.event;Zo.event=e,t[0]=this.__data__;try{n.apply(this,t)}finally{Zo.event=r}}}function Y(n,t){var e=O(n,t);return function(n){var t=this,r=n.relatedTarget;r&&(r===t||8&r.compareDocumentPosition(t))||e.call(t,n)}}function I(){var n=".dragsuppress-"+ ++Ma,t="click"+n,e=Zo.select(Wo).on("touchmove"+n,y).on("dragstart"+n,y).on("selectstart"+n,y);if(xa){var r=Bo.style,u=r[xa];r[xa]="none"}return function(i){function o(){e.on(t,null)}e.on(n,null),xa&&(r[xa]=u),i&&(e.on(t,function(){y(),o()},!0),setTimeout(o,0))}}function Z(n,t){t.changedTouches&&(t=t.changedTouches[0]);var e=n.ownerSVGElement||n;if(e.createSVGPoint){var r=e.createSVGPoint();if(0>_a&&(Wo.scrollX||Wo.scrollY)){e=Zo.select("body").append("svg").style({position:"absolute",top:0,left:0,margin:0,padding:0,border:"none"},"important");var u=e[0][0].getScreenCTM();_a=!(u.f||u.e),e.remove()}return _a?(r.x=t.pageX,r.y=t.pageY):(r.x=t.clientX,r.y=t.clientY),r=r.matrixTransform(n.getScreenCTM().inverse()),[r.x,r.y]}var i=n.getBoundingClientRect();return[t.clientX-i.left-n.clientLeft,t.clientY-i.top-n.clientTop]}function V(){return Zo.event.changedTouches[0].identifier}function X(){return Zo.event.target}function $(){return Wo}function B(n){return n>0?1:0>n?-1:0}function W(n,t,e){return(t[0]-n[0])*(e[1]-n[1])-(t[1]-n[1])*(e[0]-n[0])}function J(n){return n>1?0:-1>n?ba:Math.acos(n)}function G(n){return n>1?Sa:-1>n?-Sa:Math.asin(n)}function K(n){return((n=Math.exp(n))-1/n)/2}function Q(n){return((n=Math.exp(n))+1/n)/2}function nt(n){return((n=Math.exp(2*n))-1)/(n+1)}function tt(n){return(n=Math.sin(n/2))*n}function et(){}function rt(n,t,e){return this instanceof rt?(this.h=+n,this.s=+t,void(this.l=+e)):arguments.length<2?n instanceof rt?new rt(n.h,n.s,n.l):mt(""+n,yt,rt):new rt(n,t,e)}function ut(n,t,e){function r(n){return n>360?n-=360:0>n&&(n+=360),60>n?i+(o-i)*n/60:180>n?o:240>n?i+(o-i)*(240-n)/60:i}function u(n){return Math.round(255*r(n))}var i,o;return n=isNaN(n)?0:(n%=360)<0?n+360:n,t=isNaN(t)?0:0>t?0:t>1?1:t,e=0>e?0:e>1?1:e,o=.5>=e?e*(1+t):e+t-e*t,i=2*e-o,new gt(u(n+120),u(n),u(n-120))}function it(n,t,e){return this instanceof it?(this.h=+n,this.c=+t,void(this.l=+e)):arguments.length<2?n instanceof it?new it(n.h,n.c,n.l):n instanceof at?st(n.l,n.a,n.b):st((n=xt((n=Zo.rgb(n)).r,n.g,n.b)).l,n.a,n.b):new it(n,t,e)}function ot(n,t,e){return isNaN(n)&&(n=0),isNaN(t)&&(t=0),new at(e,Math.cos(n*=Aa)*t,Math.sin(n)*t)}function at(n,t,e){return this instanceof at?(this.l=+n,this.a=+t,void(this.b=+e)):arguments.length<2?n instanceof at?new at(n.l,n.a,n.b):n instanceof it?ot(n.l,n.c,n.h):xt((n=gt(n)).r,n.g,n.b):new at(n,t,e)}function ct(n,t,e){var r=(n+16)/116,u=r+t/500,i=r-e/200;return u=lt(u)*ja,r=lt(r)*Ha,i=lt(i)*Fa,new gt(ht(3.2404542*u-1.5371385*r-.4985314*i),ht(-.969266*u+1.8760108*r+.041556*i),ht(.0556434*u-.2040259*r+1.0572252*i))}function st(n,t,e){return n>0?new it(Math.atan2(e,t)*Ca,Math.sqrt(t*t+e*e),n):new it(0/0,0/0,n)}function lt(n){return n>.206893034?n*n*n:(n-4/29)/7.787037}function ft(n){return n>.008856?Math.pow(n,1/3):7.787037*n+4/29}function ht(n){return Math.round(255*(.00304>=n?12.92*n:1.055*Math.pow(n,1/2.4)-.055))}function gt(n,t,e){return this instanceof gt?(this.r=~~n,this.g=~~t,void(this.b=~~e)):arguments.length<2?n instanceof gt?new gt(n.r,n.g,n.b):mt(""+n,gt,ut):new gt(n,t,e)}function pt(n){return new gt(n>>16,255&n>>8,255&n)}function vt(n){return pt(n)+""}function dt(n){return 16>n?"0"+Math.max(0,n).toString(16):Math.min(255,n).toString(16)}function mt(n,t,e){var r,u,i,o=0,a=0,c=0;if(r=/([a-z]+)\((.*)\)/i.exec(n))switch(u=r[2].split(","),r[1]){case"hsl":return e(parseFloat(u[0]),parseFloat(u[1])/100,parseFloat(u[2])/100);case"rgb":return t(_t(u[0]),_t(u[1]),_t(u[2]))}return(i=Ia.get(n))?t(i.r,i.g,i.b):(null==n||"#"!==n.charAt(0)||isNaN(i=parseInt(n.substring(1),16))||(4===n.length?(o=(3840&i)>>4,o=o>>4|o,a=240&i,a=a>>4|a,c=15&i,c=c<<4|c):7===n.length&&(o=(16711680&i)>>16,a=(65280&i)>>8,c=255&i)),t(o,a,c))}function yt(n,t,e){var r,u,i=Math.min(n/=255,t/=255,e/=255),o=Math.max(n,t,e),a=o-i,c=(o+i)/2;return a?(u=.5>c?a/(o+i):a/(2-o-i),r=n==o?(t-e)/a+(e>t?6:0):t==o?(e-n)/a+2:(n-t)/a+4,r*=60):(r=0/0,u=c>0&&1>c?0:r),new rt(r,u,c)}function xt(n,t,e){n=Mt(n),t=Mt(t),e=Mt(e);var r=ft((.4124564*n+.3575761*t+.1804375*e)/ja),u=ft((.2126729*n+.7151522*t+.072175*e)/Ha),i=ft((.0193339*n+.119192*t+.9503041*e)/Fa);return at(116*u-16,500*(r-u),200*(u-i))}function Mt(n){return(n/=255)<=.04045?n/12.92:Math.pow((n+.055)/1.055,2.4)}function _t(n){var t=parseFloat(n);return"%"===n.charAt(n.length-1)?Math.round(2.55*t):t}function bt(n){return"function"==typeof n?n:function(){return n}}function wt(n){return n}function St(n){return function(t,e,r){return 2===arguments.length&&"function"==typeof e&&(r=e,e=null),kt(t,e,n,r)}}function kt(n,t,e,r){function u(){var n,t=c.status;if(!t&&c.responseText||t>=200&&300>t||304===t){try{n=e.call(i,c)}catch(r){return o.error.call(i,r),void 0}o.load.call(i,n)}else o.error.call(i,c)}var i={},o=Zo.dispatch("beforesend","progress","load","error"),a={},c=new XMLHttpRequest,s=null;return!Wo.XDomainRequest||"withCredentials"in c||!/^(http(s)?:)?\/\//.test(n)||(c=new XDomainRequest),"onload"in c?c.onload=c.onerror=u:c.onreadystatechange=function(){c.readyState>3&&u()},c.onprogress=function(n){var t=Zo.event;Zo.event=n;try{o.progress.call(i,c)}finally{Zo.event=t}},i.header=function(n,t){return n=(n+"").toLowerCase(),arguments.length<2?a[n]:(null==t?delete a[n]:a[n]=t+"",i)},i.mimeType=function(n){return arguments.length?(t=null==n?null:n+"",i):t},i.responseType=function(n){return arguments.length?(s=n,i):s},i.response=function(n){return e=n,i},["get","post"].forEach(function(n){i[n]=function(){return i.send.apply(i,[n].concat(Xo(arguments)))}}),i.send=function(e,r,u){if(2===arguments.length&&"function"==typeof r&&(u=r,r=null),c.open(e,n,!0),null==t||"accept"in a||(a.accept=t+",*/*"),c.setRequestHeader)for(var l in a)c.setRequestHeader(l,a[l]);return null!=t&&c.overrideMimeType&&c.overrideMimeType(t),null!=s&&(c.responseType=s),null!=u&&i.on("error",u).on("load",function(n){u(null,n)}),o.beforesend.call(i,c),c.send(null==r?null:r),i},i.abort=function(){return c.abort(),i},Zo.rebind(i,o,"on"),null==r?i:i.get(Et(r))}function Et(n){return 1===n.length?function(t,e){n(null==t?e:null)}:n}function At(){var n=Ct(),t=Nt()-n;t>24?(isFinite(t)&&(clearTimeout($a),$a=setTimeout(At,t)),Xa=0):(Xa=1,Wa(At))}function Ct(){var n=Date.now();for(Ba=Za;Ba;)n>=Ba.t&&(Ba.f=Ba.c(n-Ba.t)),Ba=Ba.n;return n}function Nt(){for(var n,t=Za,e=1/0;t;)t.f?t=n?n.n=t.n:Za=t.n:(t.t8?function(n){return n/e}:function(n){return n*e},symbol:n}}function Tt(n){var t=n.decimal,e=n.thousands,r=n.grouping,u=n.currency,i=r?function(n){for(var t=n.length,u=[],i=0,o=r[0];t>0&&o>0;)u.push(n.substring(t-=o,t+o)),o=r[i=(i+1)%r.length];return u.reverse().join(e)}:wt;return function(n){var e=Ga.exec(n),r=e[1]||" ",o=e[2]||">",a=e[3]||"",c=e[4]||"",s=e[5],l=+e[6],f=e[7],h=e[8],g=e[9],p=1,v="",d="",m=!1;switch(h&&(h=+h.substring(1)),(s||"0"===r&&"="===o)&&(s=r="0",o="=",f&&(l-=Math.floor((l-1)/4))),g){case"n":f=!0,g="g";break;case"%":p=100,d="%",g="f";break;case"p":p=100,d="%",g="r";break;case"b":case"o":case"x":case"X":"#"===c&&(v="0"+g.toLowerCase());case"c":case"d":m=!0,h=0;break;case"s":p=-1,g="r"}"$"===c&&(v=u[0],d=u[1]),"r"!=g||h||(g="g"),null!=h&&("g"==g?h=Math.max(1,Math.min(21,h)):("e"==g||"f"==g)&&(h=Math.max(0,Math.min(20,h)))),g=Ka.get(g)||qt;var y=s&&f;return function(n){var e=d;if(m&&n%1)return"";var u=0>n||0===n&&0>1/n?(n=-n,"-"):a;if(0>p){var c=Zo.formatPrefix(n,h);n=c.scale(n),e=c.symbol+d}else n*=p;n=g(n,h);var x=n.lastIndexOf("."),M=0>x?n:n.substring(0,x),_=0>x?"":t+n.substring(x+1);!s&&f&&(M=i(M));var b=v.length+M.length+_.length+(y?0:u.length),w=l>b?new Array(b=l-b+1).join(r):"";return y&&(M=i(w+M)),u+=v,n=M+_,("<"===o?u+n+w:">"===o?w+u+n:"^"===o?w.substring(0,b>>=1)+u+n+w.substring(b):u+(y?n:w+n))+e}}}function qt(n){return n+""}function Rt(){this._=new Date(arguments.length>1?Date.UTC.apply(this,arguments):arguments[0])}function Dt(n,t,e){function r(t){var e=n(t),r=i(e,1);return r-t>t-e?e:r}function u(e){return t(e=n(new nc(e-1)),1),e}function i(n,e){return t(n=new nc(+n),e),n}function o(n,r,i){var o=u(n),a=[];if(i>1)for(;r>o;)e(o)%i||a.push(new Date(+o)),t(o,1);else for(;r>o;)a.push(new Date(+o)),t(o,1);return a}function a(n,t,e){try{nc=Rt;var r=new Rt;return r._=n,o(r,t,e)}finally{nc=Date}}n.floor=n,n.round=r,n.ceil=u,n.offset=i,n.range=o;var c=n.utc=Pt(n);return c.floor=c,c.round=Pt(r),c.ceil=Pt(u),c.offset=Pt(i),c.range=a,n}function Pt(n){return function(t,e){try{nc=Rt;var r=new Rt;return r._=t,n(r,e)._}finally{nc=Date}}}function Ut(n){function t(n){function t(t){for(var e,u,i,o=[],a=-1,c=0;++aa;){if(r>=s)return-1;if(u=t.charCodeAt(a++),37===u){if(o=t.charAt(a++),i=N[o in ec?t.charAt(a++):o],!i||(r=i(n,e,r))<0)return-1}else if(u!=e.charCodeAt(r++))return-1}return r}function r(n,t,e){b.lastIndex=0;var r=b.exec(t.substring(e));return r?(n.w=w.get(r[0].toLowerCase()),e+r[0].length):-1}function u(n,t,e){M.lastIndex=0;var r=M.exec(t.substring(e));return r?(n.w=_.get(r[0].toLowerCase()),e+r[0].length):-1}function i(n,t,e){E.lastIndex=0;var r=E.exec(t.substring(e));return r?(n.m=A.get(r[0].toLowerCase()),e+r[0].length):-1}function o(n,t,e){S.lastIndex=0;var r=S.exec(t.substring(e));return r?(n.m=k.get(r[0].toLowerCase()),e+r[0].length):-1}function a(n,t,r){return e(n,C.c.toString(),t,r)}function c(n,t,r){return e(n,C.x.toString(),t,r)}function s(n,t,r){return e(n,C.X.toString(),t,r)}function l(n,t,e){var r=x.get(t.substring(e,e+=2).toLowerCase());return null==r?-1:(n.p=r,e)}var f=n.dateTime,h=n.date,g=n.time,p=n.periods,v=n.days,d=n.shortDays,m=n.months,y=n.shortMonths;t.utc=function(n){function e(n){try{nc=Rt;var t=new nc;return t._=n,r(t)}finally{nc=Date}}var r=t(n);return e.parse=function(n){try{nc=Rt;var t=r.parse(n);return t&&t._}finally{nc=Date}},e.toString=r.toString,e},t.multi=t.utc.multi=re;var x=Zo.map(),M=Ht(v),_=Ft(v),b=Ht(d),w=Ft(d),S=Ht(m),k=Ft(m),E=Ht(y),A=Ft(y);p.forEach(function(n,t){x.set(n.toLowerCase(),t)});var C={a:function(n){return d[n.getDay()]},A:function(n){return v[n.getDay()]},b:function(n){return y[n.getMonth()]},B:function(n){return m[n.getMonth()]},c:t(f),d:function(n,t){return jt(n.getDate(),t,2)},e:function(n,t){return jt(n.getDate(),t,2)},H:function(n,t){return jt(n.getHours(),t,2)},I:function(n,t){return jt(n.getHours()%12||12,t,2)},j:function(n,t){return jt(1+Qa.dayOfYear(n),t,3)},L:function(n,t){return jt(n.getMilliseconds(),t,3)},m:function(n,t){return jt(n.getMonth()+1,t,2)},M:function(n,t){return jt(n.getMinutes(),t,2)},p:function(n){return p[+(n.getHours()>=12)]},S:function(n,t){return jt(n.getSeconds(),t,2)},U:function(n,t){return jt(Qa.sundayOfYear(n),t,2)},w:function(n){return n.getDay()},W:function(n,t){return jt(Qa.mondayOfYear(n),t,2)},x:t(h),X:t(g),y:function(n,t){return jt(n.getFullYear()%100,t,2)},Y:function(n,t){return jt(n.getFullYear()%1e4,t,4)},Z:te,"%":function(){return"%"}},N={a:r,A:u,b:i,B:o,c:a,d:Wt,e:Wt,H:Gt,I:Gt,j:Jt,L:ne,m:Bt,M:Kt,p:l,S:Qt,U:Yt,w:Ot,W:It,x:c,X:s,y:Vt,Y:Zt,Z:Xt,"%":ee};return t}function jt(n,t,e){var r=0>n?"-":"",u=(r?-n:n)+"",i=u.length;return r+(e>i?new Array(e-i+1).join(t)+u:u)}function Ht(n){return new RegExp("^(?:"+n.map(Zo.requote).join("|")+")","i")}function Ft(n){for(var t=new o,e=-1,r=n.length;++e68?1900:2e3)}function Bt(n,t,e){rc.lastIndex=0;var r=rc.exec(t.substring(e,e+2));return r?(n.m=r[0]-1,e+r[0].length):-1}function Wt(n,t,e){rc.lastIndex=0;var r=rc.exec(t.substring(e,e+2));return r?(n.d=+r[0],e+r[0].length):-1}function Jt(n,t,e){rc.lastIndex=0;var r=rc.exec(t.substring(e,e+3));return r?(n.j=+r[0],e+r[0].length):-1}function Gt(n,t,e){rc.lastIndex=0;var r=rc.exec(t.substring(e,e+2));return r?(n.H=+r[0],e+r[0].length):-1}function Kt(n,t,e){rc.lastIndex=0;var r=rc.exec(t.substring(e,e+2));return r?(n.M=+r[0],e+r[0].length):-1}function Qt(n,t,e){rc.lastIndex=0;var r=rc.exec(t.substring(e,e+2));return r?(n.S=+r[0],e+r[0].length):-1}function ne(n,t,e){rc.lastIndex=0;var r=rc.exec(t.substring(e,e+3));return r?(n.L=+r[0],e+r[0].length):-1}function te(n){var t=n.getTimezoneOffset(),e=t>0?"-":"+",r=~~(ua(t)/60),u=ua(t)%60;return e+jt(r,"0",2)+jt(u,"0",2)}function ee(n,t,e){uc.lastIndex=0;var r=uc.exec(t.substring(e,e+1));return r?e+r[0].length:-1}function re(n){for(var t=n.length,e=-1;++e=0?1:-1,a=o*e,c=Math.cos(t),s=Math.sin(t),l=i*s,f=u*c+l*Math.cos(a),h=l*o*Math.sin(a);lc.add(Math.atan2(h,f)),r=n,u=c,i=s}var t,e,r,u,i;fc.point=function(o,a){fc.point=n,r=(t=o)*Aa,u=Math.cos(a=(e=a)*Aa/2+ba/4),i=Math.sin(a)},fc.lineEnd=function(){n(t,e)}}function le(n){var t=n[0],e=n[1],r=Math.cos(e);return[r*Math.cos(t),r*Math.sin(t),Math.sin(e)]}function fe(n,t){return n[0]*t[0]+n[1]*t[1]+n[2]*t[2]}function he(n,t){return[n[1]*t[2]-n[2]*t[1],n[2]*t[0]-n[0]*t[2],n[0]*t[1]-n[1]*t[0]]}function ge(n,t){n[0]+=t[0],n[1]+=t[1],n[2]+=t[2]}function pe(n,t){return[n[0]*t,n[1]*t,n[2]*t]}function ve(n){var t=Math.sqrt(n[0]*n[0]+n[1]*n[1]+n[2]*n[2]);n[0]/=t,n[1]/=t,n[2]/=t}function de(n){return[Math.atan2(n[1],n[0]),G(n[2])]}function me(n,t){return ua(n[0]-t[0])a;++a)u.point((e=n[a])[0],e[1]);return u.lineEnd(),void 0}var c=new Ee(e,n,null,!0),s=new Ee(e,null,c,!1);c.o=s,i.push(c),o.push(s),c=new Ee(r,n,null,!1),s=new Ee(r,null,c,!0),c.o=s,i.push(c),o.push(s)}}),o.sort(t),ke(i),ke(o),i.length){for(var a=0,c=e,s=o.length;s>a;++a)o[a].e=c=!c;for(var l,f,h=i[0];;){for(var g=h,p=!0;g.v;)if((g=g.n)===h)return;l=g.z,u.lineStart();do{if(g.v=g.o.v=!0,g.e){if(p)for(var a=0,s=l.length;s>a;++a)u.point((f=l[a])[0],f[1]);else r(g.x,g.n.x,1,u);g=g.n}else{if(p){l=g.p.z;for(var a=l.length-1;a>=0;--a)u.point((f=l[a])[0],f[1])}else r(g.x,g.p.x,-1,u);g=g.p}g=g.o,l=g.z,p=!p}while(!g.v);u.lineEnd()}}}function ke(n){if(t=n.length){for(var t,e,r=0,u=n[0];++r0){for(_||(i.polygonStart(),_=!0),i.lineStart();++o1&&2&t&&e.push(e.pop().concat(e.shift())),g.push(e.filter(Ce))}var g,p,v,d=t(i),m=u.invert(r[0],r[1]),y={point:o,lineStart:c,lineEnd:s,polygonStart:function(){y.point=l,y.lineStart=f,y.lineEnd=h,g=[],p=[]},polygonEnd:function(){y.point=o,y.lineStart=c,y.lineEnd=s,g=Zo.merge(g);var n=Le(m,p);g.length?(_||(i.polygonStart(),_=!0),Se(g,ze,n,e,i)):n&&(_||(i.polygonStart(),_=!0),i.lineStart(),e(null,null,1,i),i.lineEnd()),_&&(i.polygonEnd(),_=!1),g=p=null},sphere:function(){i.polygonStart(),i.lineStart(),e(null,null,1,i),i.lineEnd(),i.polygonEnd()}},x=Ne(),M=t(x),_=!1;return y}}function Ce(n){return n.length>1}function Ne(){var n,t=[];return{lineStart:function(){t.push(n=[])},point:function(t,e){n.push([t,e])},lineEnd:v,buffer:function(){var e=t;return t=[],n=null,e},rejoin:function(){t.length>1&&t.push(t.pop().concat(t.shift()))}}}function ze(n,t){return((n=n.x)[0]<0?n[1]-Sa-ka:Sa-n[1])-((t=t.x)[0]<0?t[1]-Sa-ka:Sa-t[1])}function Le(n,t){var e=n[0],r=n[1],u=[Math.sin(e),-Math.cos(e),0],i=0,o=0;lc.reset();for(var a=0,c=t.length;c>a;++a){var s=t[a],l=s.length;if(l)for(var f=s[0],h=f[0],g=f[1]/2+ba/4,p=Math.sin(g),v=Math.cos(g),d=1;;){d===l&&(d=0),n=s[d];var m=n[0],y=n[1]/2+ba/4,x=Math.sin(y),M=Math.cos(y),_=m-h,b=_>=0?1:-1,w=b*_,S=w>ba,k=p*x;if(lc.add(Math.atan2(k*b*Math.sin(w),v*M+k*Math.cos(w))),i+=S?_+b*wa:_,S^h>=e^m>=e){var E=he(le(f),le(n));ve(E);var A=he(u,E);ve(A);var C=(S^_>=0?-1:1)*G(A[2]);(r>C||r===C&&(E[0]||E[1]))&&(o+=S^_>=0?1:-1)}if(!d++)break;h=m,p=x,v=M,f=n}}return(-ka>i||ka>i&&0>lc)^1&o}function Te(n){var t,e=0/0,r=0/0,u=0/0;return{lineStart:function(){n.lineStart(),t=1},point:function(i,o){var a=i>0?ba:-ba,c=ua(i-e);ua(c-ba)0?Sa:-Sa),n.point(u,r),n.lineEnd(),n.lineStart(),n.point(a,r),n.point(i,r),t=0):u!==a&&c>=ba&&(ua(e-u)ka?Math.atan((Math.sin(t)*(i=Math.cos(r))*Math.sin(e)-Math.sin(r)*(u=Math.cos(t))*Math.sin(n))/(u*i*o)):(t+r)/2}function Re(n,t,e,r){var u;if(null==n)u=e*Sa,r.point(-ba,u),r.point(0,u),r.point(ba,u),r.point(ba,0),r.point(ba,-u),r.point(0,-u),r.point(-ba,-u),r.point(-ba,0),r.point(-ba,u);else if(ua(n[0]-t[0])>ka){var i=n[0]i}function e(n){var e,i,c,s,l;return{lineStart:function(){s=c=!1,l=1},point:function(f,h){var g,p=[f,h],v=t(f,h),d=o?v?0:u(f,h):v?u(f+(0>f?ba:-ba),h):0;if(!e&&(s=c=v)&&n.lineStart(),v!==c&&(g=r(e,p),(me(e,g)||me(p,g))&&(p[0]+=ka,p[1]+=ka,v=t(p[0],p[1]))),v!==c)l=0,v?(n.lineStart(),g=r(p,e),n.point(g[0],g[1])):(g=r(e,p),n.point(g[0],g[1]),n.lineEnd()),e=g;else if(a&&e&&o^v){var m;d&i||!(m=r(p,e,!0))||(l=0,o?(n.lineStart(),n.point(m[0][0],m[0][1]),n.point(m[1][0],m[1][1]),n.lineEnd()):(n.point(m[1][0],m[1][1]),n.lineEnd(),n.lineStart(),n.point(m[0][0],m[0][1])))}!v||e&&me(e,p)||n.point(p[0],p[1]),e=p,c=v,i=d},lineEnd:function(){c&&n.lineEnd(),e=null},clean:function(){return l|(s&&c)<<1}}}function r(n,t,e){var r=le(n),u=le(t),o=[1,0,0],a=he(r,u),c=fe(a,a),s=a[0],l=c-s*s;if(!l)return!e&&n;var f=i*c/l,h=-i*s/l,g=he(o,a),p=pe(o,f),v=pe(a,h);ge(p,v);var d=g,m=fe(p,d),y=fe(d,d),x=m*m-y*(fe(p,p)-1);if(!(0>x)){var M=Math.sqrt(x),_=pe(d,(-m-M)/y);if(ge(_,p),_=de(_),!e)return _;var b,w=n[0],S=t[0],k=n[1],E=t[1];w>S&&(b=w,w=S,S=b);var A=S-w,C=ua(A-ba)A;if(!C&&k>E&&(b=k,k=E,E=b),N?C?k+E>0^_[1]<(ua(_[0]-w)ba^(w<=_[0]&&_[0]<=S)){var z=pe(d,(-m+M)/y);return ge(z,p),[_,de(z)]}}}function u(t,e){var r=o?n:ba-n,u=0;return-r>t?u|=1:t>r&&(u|=2),-r>e?u|=4:e>r&&(u|=8),u}var i=Math.cos(n),o=i>0,a=ua(i)>ka,c=sr(n,6*Aa);return Ae(t,e,c,o?[0,-n]:[-ba,n-ba])}function Pe(n,t,e,r){return function(u){var i,o=u.a,a=u.b,c=o.x,s=o.y,l=a.x,f=a.y,h=0,g=1,p=l-c,v=f-s;if(i=n-c,p||!(i>0)){if(i/=p,0>p){if(h>i)return;g>i&&(g=i)}else if(p>0){if(i>g)return;i>h&&(h=i)}if(i=e-c,p||!(0>i)){if(i/=p,0>p){if(i>g)return;i>h&&(h=i)}else if(p>0){if(h>i)return;g>i&&(g=i)}if(i=t-s,v||!(i>0)){if(i/=v,0>v){if(h>i)return;g>i&&(g=i)}else if(v>0){if(i>g)return;i>h&&(h=i)}if(i=r-s,v||!(0>i)){if(i/=v,0>v){if(i>g)return;i>h&&(h=i)}else if(v>0){if(h>i)return;g>i&&(g=i)}return h>0&&(u.a={x:c+h*p,y:s+h*v}),1>g&&(u.b={x:c+g*p,y:s+g*v}),u}}}}}}function Ue(n,t,e,r){function u(r,u){return ua(r[0]-n)0?0:3:ua(r[0]-e)0?2:1:ua(r[1]-t)0?1:0:u>0?3:2}function i(n,t){return o(n.x,t.x)}function o(n,t){var e=u(n,1),r=u(t,1);return e!==r?e-r:0===e?t[1]-n[1]:1===e?n[0]-t[0]:2===e?n[1]-t[1]:t[0]-n[0]}return function(a){function c(n){for(var t=0,e=d.length,r=n[1],u=0;e>u;++u)for(var i,o=1,a=d[u],c=a.length,s=a[0];c>o;++o)i=a[o],s[1]<=r?i[1]>r&&W(s,i,n)>0&&++t:i[1]<=r&&W(s,i,n)<0&&--t,s=i;return 0!==t}function s(i,a,c,s){var l=0,f=0;if(null==i||(l=u(i,c))!==(f=u(a,c))||o(i,a)<0^c>0){do s.point(0===l||3===l?n:e,l>1?r:t);while((l=(l+c+4)%4)!==f)}else s.point(a[0],a[1])}function l(u,i){return u>=n&&e>=u&&i>=t&&r>=i}function f(n,t){l(n,t)&&a.point(n,t)}function h(){N.point=p,d&&d.push(m=[]),S=!0,w=!1,_=b=0/0}function g(){v&&(p(y,x),M&&w&&A.rejoin(),v.push(A.buffer())),N.point=f,w&&a.lineEnd()}function p(n,t){n=Math.max(-kc,Math.min(kc,n)),t=Math.max(-kc,Math.min(kc,t));var e=l(n,t);if(d&&m.push([n,t]),S)y=n,x=t,M=e,S=!1,e&&(a.lineStart(),a.point(n,t));else if(e&&w)a.point(n,t);else{var r={a:{x:_,y:b},b:{x:n,y:t}};C(r)?(w||(a.lineStart(),a.point(r.a.x,r.a.y)),a.point(r.b.x,r.b.y),e||a.lineEnd(),k=!1):e&&(a.lineStart(),a.point(n,t),k=!1)}_=n,b=t,w=e}var v,d,m,y,x,M,_,b,w,S,k,E=a,A=Ne(),C=Pe(n,t,e,r),N={point:f,lineStart:h,lineEnd:g,polygonStart:function(){a=A,v=[],d=[],k=!0},polygonEnd:function(){a=E,v=Zo.merge(v);var t=c([n,r]),e=k&&t,u=v.length;(e||u)&&(a.polygonStart(),e&&(a.lineStart(),s(null,null,1,a),a.lineEnd()),u&&Se(v,i,t,s,a),a.polygonEnd()),v=d=m=null}};return N}}function je(n,t){function e(e,r){return e=n(e,r),t(e[0],e[1])}return n.invert&&t.invert&&(e.invert=function(e,r){return e=t.invert(e,r),e&&n.invert(e[0],e[1])}),e}function He(n){var t=0,e=ba/3,r=tr(n),u=r(t,e);return u.parallels=function(n){return arguments.length?r(t=n[0]*ba/180,e=n[1]*ba/180):[180*(t/ba),180*(e/ba)]},u}function Fe(n,t){function e(n,t){var e=Math.sqrt(i-2*u*Math.sin(t))/u;return[e*Math.sin(n*=u),o-e*Math.cos(n)]}var r=Math.sin(n),u=(r+Math.sin(t))/2,i=1+r*(2*u-r),o=Math.sqrt(i)/u;return e.invert=function(n,t){var e=o-t;return[Math.atan2(n,e)/u,G((i-(n*n+e*e)*u*u)/(2*u))]},e}function Oe(){function n(n,t){Ac+=u*n-r*t,r=n,u=t}var t,e,r,u;Tc.point=function(i,o){Tc.point=n,t=r=i,e=u=o},Tc.lineEnd=function(){n(t,e)}}function Ye(n,t){Cc>n&&(Cc=n),n>zc&&(zc=n),Nc>t&&(Nc=t),t>Lc&&(Lc=t)}function Ie(){function n(n,t){o.push("M",n,",",t,i)}function t(n,t){o.push("M",n,",",t),a.point=e}function e(n,t){o.push("L",n,",",t)}function r(){a.point=n}function u(){o.push("Z")}var i=Ze(4.5),o=[],a={point:n,lineStart:function(){a.point=t},lineEnd:r,polygonStart:function(){a.lineEnd=u},polygonEnd:function(){a.lineEnd=r,a.point=n},pointRadius:function(n){return i=Ze(n),a},result:function(){if(o.length){var n=o.join("");return o=[],n}}};return a}function Ze(n){return"m0,"+n+"a"+n+","+n+" 0 1,1 0,"+-2*n+"a"+n+","+n+" 0 1,1 0,"+2*n+"z"}function Ve(n,t){pc+=n,vc+=t,++dc}function Xe(){function n(n,r){var u=n-t,i=r-e,o=Math.sqrt(u*u+i*i);mc+=o*(t+n)/2,yc+=o*(e+r)/2,xc+=o,Ve(t=n,e=r)}var t,e;Rc.point=function(r,u){Rc.point=n,Ve(t=r,e=u)}}function $e(){Rc.point=Ve}function Be(){function n(n,t){var e=n-r,i=t-u,o=Math.sqrt(e*e+i*i);mc+=o*(r+n)/2,yc+=o*(u+t)/2,xc+=o,o=u*n-r*t,Mc+=o*(r+n),_c+=o*(u+t),bc+=3*o,Ve(r=n,u=t)}var t,e,r,u;Rc.point=function(i,o){Rc.point=n,Ve(t=r=i,e=u=o)},Rc.lineEnd=function(){n(t,e)}}function We(n){function t(t,e){n.moveTo(t,e),n.arc(t,e,o,0,wa)}function e(t,e){n.moveTo(t,e),a.point=r}function r(t,e){n.lineTo(t,e)}function u(){a.point=t}function i(){n.closePath()}var o=4.5,a={point:t,lineStart:function(){a.point=e},lineEnd:u,polygonStart:function(){a.lineEnd=i},polygonEnd:function(){a.lineEnd=u,a.point=t},pointRadius:function(n){return o=n,a},result:v};return a}function Je(n){function t(n){return(a?r:e)(n)}function e(t){return Qe(t,function(e,r){e=n(e,r),t.point(e[0],e[1])})}function r(t){function e(e,r){e=n(e,r),t.point(e[0],e[1])}function r(){x=0/0,S.point=i,t.lineStart()}function i(e,r){var i=le([e,r]),o=n(e,r);u(x,M,y,_,b,w,x=o[0],M=o[1],y=e,_=i[0],b=i[1],w=i[2],a,t),t.point(x,M)}function o(){S.point=e,t.lineEnd()}function c(){r(),S.point=s,S.lineEnd=l}function s(n,t){i(f=n,h=t),g=x,p=M,v=_,d=b,m=w,S.point=i}function l(){u(x,M,y,_,b,w,g,p,f,v,d,m,a,t),S.lineEnd=o,o()}var f,h,g,p,v,d,m,y,x,M,_,b,w,S={point:e,lineStart:r,lineEnd:o,polygonStart:function(){t.polygonStart(),S.lineStart=c},polygonEnd:function(){t.polygonEnd(),S.lineStart=r}};return S}function u(t,e,r,a,c,s,l,f,h,g,p,v,d,m){var y=l-t,x=f-e,M=y*y+x*x;if(M>4*i&&d--){var _=a+g,b=c+p,w=s+v,S=Math.sqrt(_*_+b*b+w*w),k=Math.asin(w/=S),E=ua(ua(w)-1)i||ua((y*z+x*L)/M-.5)>.3||o>a*g+c*p+s*v)&&(u(t,e,r,a,c,s,C,N,E,_/=S,b/=S,w,d,m),m.point(C,N),u(C,N,E,_,b,w,l,f,h,g,p,v,d,m))}}var i=.5,o=Math.cos(30*Aa),a=16; +return t.precision=function(n){return arguments.length?(a=(i=n*n)>0&&16,t):Math.sqrt(i)},t}function Ge(n){var t=Je(function(t,e){return n([t*Ca,e*Ca])});return function(n){return er(t(n))}}function Ke(n){this.stream=n}function Qe(n,t){return{point:t,sphere:function(){n.sphere()},lineStart:function(){n.lineStart()},lineEnd:function(){n.lineEnd()},polygonStart:function(){n.polygonStart()},polygonEnd:function(){n.polygonEnd()}}}function nr(n){return tr(function(){return n})()}function tr(n){function t(n){return n=a(n[0]*Aa,n[1]*Aa),[n[0]*h+c,s-n[1]*h]}function e(n){return n=a.invert((n[0]-c)/h,(s-n[1])/h),n&&[n[0]*Ca,n[1]*Ca]}function r(){a=je(o=ir(m,y,x),i);var n=i(v,d);return c=g-n[0]*h,s=p+n[1]*h,u()}function u(){return l&&(l.valid=!1,l=null),t}var i,o,a,c,s,l,f=Je(function(n,t){return n=i(n,t),[n[0]*h+c,s-n[1]*h]}),h=150,g=480,p=250,v=0,d=0,m=0,y=0,x=0,M=Sc,_=wt,b=null,w=null;return t.stream=function(n){return l&&(l.valid=!1),l=er(M(o,f(_(n)))),l.valid=!0,l},t.clipAngle=function(n){return arguments.length?(M=null==n?(b=n,Sc):De((b=+n)*Aa),u()):b},t.clipExtent=function(n){return arguments.length?(w=n,_=n?Ue(n[0][0],n[0][1],n[1][0],n[1][1]):wt,u()):w},t.scale=function(n){return arguments.length?(h=+n,r()):h},t.translate=function(n){return arguments.length?(g=+n[0],p=+n[1],r()):[g,p]},t.center=function(n){return arguments.length?(v=n[0]%360*Aa,d=n[1]%360*Aa,r()):[v*Ca,d*Ca]},t.rotate=function(n){return arguments.length?(m=n[0]%360*Aa,y=n[1]%360*Aa,x=n.length>2?n[2]%360*Aa:0,r()):[m*Ca,y*Ca,x*Ca]},Zo.rebind(t,f,"precision"),function(){return i=n.apply(this,arguments),t.invert=i.invert&&e,r()}}function er(n){return Qe(n,function(t,e){n.point(t*Aa,e*Aa)})}function rr(n,t){return[n,t]}function ur(n,t){return[n>ba?n-wa:-ba>n?n+wa:n,t]}function ir(n,t,e){return n?t||e?je(ar(n),cr(t,e)):ar(n):t||e?cr(t,e):ur}function or(n){return function(t,e){return t+=n,[t>ba?t-wa:-ba>t?t+wa:t,e]}}function ar(n){var t=or(n);return t.invert=or(-n),t}function cr(n,t){function e(n,t){var e=Math.cos(t),a=Math.cos(n)*e,c=Math.sin(n)*e,s=Math.sin(t),l=s*r+a*u;return[Math.atan2(c*i-l*o,a*r-s*u),G(l*i+c*o)]}var r=Math.cos(n),u=Math.sin(n),i=Math.cos(t),o=Math.sin(t);return e.invert=function(n,t){var e=Math.cos(t),a=Math.cos(n)*e,c=Math.sin(n)*e,s=Math.sin(t),l=s*i-c*o;return[Math.atan2(c*i+s*o,a*r+l*u),G(l*r-a*u)]},e}function sr(n,t){var e=Math.cos(n),r=Math.sin(n);return function(u,i,o,a){var c=o*t;null!=u?(u=lr(e,u),i=lr(e,i),(o>0?i>u:u>i)&&(u+=o*wa)):(u=n+o*wa,i=n-.5*c);for(var s,l=u;o>0?l>i:i>l;l-=c)a.point((s=de([e,-r*Math.cos(l),-r*Math.sin(l)]))[0],s[1])}}function lr(n,t){var e=le(t);e[0]-=n,ve(e);var r=J(-e[1]);return((-e[2]<0?-r:r)+2*Math.PI-ka)%(2*Math.PI)}function fr(n,t,e){var r=Zo.range(n,t-ka,e).concat(t);return function(n){return r.map(function(t){return[n,t]})}}function hr(n,t,e){var r=Zo.range(n,t-ka,e).concat(t);return function(n){return r.map(function(t){return[t,n]})}}function gr(n){return n.source}function pr(n){return n.target}function vr(n,t,e,r){var u=Math.cos(t),i=Math.sin(t),o=Math.cos(r),a=Math.sin(r),c=u*Math.cos(n),s=u*Math.sin(n),l=o*Math.cos(e),f=o*Math.sin(e),h=2*Math.asin(Math.sqrt(tt(r-t)+u*o*tt(e-n))),g=1/Math.sin(h),p=h?function(n){var t=Math.sin(n*=h)*g,e=Math.sin(h-n)*g,r=e*c+t*l,u=e*s+t*f,o=e*i+t*a;return[Math.atan2(u,r)*Ca,Math.atan2(o,Math.sqrt(r*r+u*u))*Ca]}:function(){return[n*Ca,t*Ca]};return p.distance=h,p}function dr(){function n(n,u){var i=Math.sin(u*=Aa),o=Math.cos(u),a=ua((n*=Aa)-t),c=Math.cos(a);Dc+=Math.atan2(Math.sqrt((a=o*Math.sin(a))*a+(a=r*i-e*o*c)*a),e*i+r*o*c),t=n,e=i,r=o}var t,e,r;Pc.point=function(u,i){t=u*Aa,e=Math.sin(i*=Aa),r=Math.cos(i),Pc.point=n},Pc.lineEnd=function(){Pc.point=Pc.lineEnd=v}}function mr(n,t){function e(t,e){var r=Math.cos(t),u=Math.cos(e),i=n(r*u);return[i*u*Math.sin(t),i*Math.sin(e)]}return e.invert=function(n,e){var r=Math.sqrt(n*n+e*e),u=t(r),i=Math.sin(u),o=Math.cos(u);return[Math.atan2(n*i,r*o),Math.asin(r&&e*i/r)]},e}function yr(n,t){function e(n,t){o>0?-Sa+ka>t&&(t=-Sa+ka):t>Sa-ka&&(t=Sa-ka);var e=o/Math.pow(u(t),i);return[e*Math.sin(i*n),o-e*Math.cos(i*n)]}var r=Math.cos(n),u=function(n){return Math.tan(ba/4+n/2)},i=n===t?Math.sin(n):Math.log(r/Math.cos(t))/Math.log(u(t)/u(n)),o=r*Math.pow(u(n),i)/i;return i?(e.invert=function(n,t){var e=o-t,r=B(i)*Math.sqrt(n*n+e*e);return[Math.atan2(n,e)/i,2*Math.atan(Math.pow(o/r,1/i))-Sa]},e):Mr}function xr(n,t){function e(n,t){var e=i-t;return[e*Math.sin(u*n),i-e*Math.cos(u*n)]}var r=Math.cos(n),u=n===t?Math.sin(n):(r-Math.cos(t))/(t-n),i=r/u+n;return ua(u)u;u++){for(;r>1&&W(n[e[r-2]],n[e[r-1]],n[u])<=0;)--r;e[r++]=u}return e.slice(0,r)}function Er(n,t){return n[0]-t[0]||n[1]-t[1]}function Ar(n,t,e){return(e[0]-t[0])*(n[1]-t[1])<(e[1]-t[1])*(n[0]-t[0])}function Cr(n,t,e,r){var u=n[0],i=e[0],o=t[0]-u,a=r[0]-i,c=n[1],s=e[1],l=t[1]-c,f=r[1]-s,h=(a*(c-s)-f*(u-i))/(f*o-a*l);return[u+h*o,c+h*l]}function Nr(n){var t=n[0],e=n[n.length-1];return!(t[0]-e[0]||t[1]-e[1])}function zr(){Gr(this),this.edge=this.site=this.circle=null}function Lr(n){var t=Bc.pop()||new zr;return t.site=n,t}function Tr(n){Yr(n),Vc.remove(n),Bc.push(n),Gr(n)}function qr(n){var t=n.circle,e=t.x,r=t.cy,u={x:e,y:r},i=n.P,o=n.N,a=[n];Tr(n);for(var c=i;c.circle&&ua(e-c.circle.x)l;++l)s=a[l],c=a[l-1],Br(s.edge,c.site,s.site,u);c=a[0],s=a[f-1],s.edge=Xr(c.site,s.site,null,u),Or(c),Or(s)}function Rr(n){for(var t,e,r,u,i=n.x,o=n.y,a=Vc._;a;)if(r=Dr(a,o)-i,r>ka)a=a.L;else{if(u=i-Pr(a,o),!(u>ka)){r>-ka?(t=a.P,e=a):u>-ka?(t=a,e=a.N):t=e=a;break}if(!a.R){t=a;break}a=a.R}var c=Lr(n);if(Vc.insert(t,c),t||e){if(t===e)return Yr(t),e=Lr(t.site),Vc.insert(c,e),c.edge=e.edge=Xr(t.site,c.site),Or(t),Or(e),void 0;if(!e)return c.edge=Xr(t.site,c.site),void 0;Yr(t),Yr(e);var s=t.site,l=s.x,f=s.y,h=n.x-l,g=n.y-f,p=e.site,v=p.x-l,d=p.y-f,m=2*(h*d-g*v),y=h*h+g*g,x=v*v+d*d,M={x:(d*y-g*x)/m+l,y:(h*x-v*y)/m+f};Br(e.edge,s,p,M),c.edge=Xr(s,n,null,M),e.edge=Xr(n,p,null,M),Or(t),Or(e)}}function Dr(n,t){var e=n.site,r=e.x,u=e.y,i=u-t;if(!i)return r;var o=n.P;if(!o)return-1/0;e=o.site;var a=e.x,c=e.y,s=c-t;if(!s)return a;var l=a-r,f=1/i-1/s,h=l/s;return f?(-h+Math.sqrt(h*h-2*f*(l*l/(-2*s)-c+s/2+u-i/2)))/f+r:(r+a)/2}function Pr(n,t){var e=n.N;if(e)return Dr(e,t);var r=n.site;return r.y===t?r.x:1/0}function Ur(n){this.site=n,this.edges=[]}function jr(n){for(var t,e,r,u,i,o,a,c,s,l,f=n[0][0],h=n[1][0],g=n[0][1],p=n[1][1],v=Zc,d=v.length;d--;)if(i=v[d],i&&i.prepare())for(a=i.edges,c=a.length,o=0;c>o;)l=a[o].end(),r=l.x,u=l.y,s=a[++o%c].start(),t=s.x,e=s.y,(ua(r-t)>ka||ua(u-e)>ka)&&(a.splice(o,0,new Wr($r(i.site,l,ua(r-f)ka?{x:f,y:ua(t-f)ka?{x:ua(e-p)ka?{x:h,y:ua(t-h)ka?{x:ua(e-g)=-Ea)){var g=c*c+s*s,p=l*l+f*f,v=(f*g-s*p)/h,d=(c*p-l*g)/h,f=d+a,m=Wc.pop()||new Fr;m.arc=n,m.site=u,m.x=v+o,m.y=f+Math.sqrt(v*v+d*d),m.cy=f,n.circle=m;for(var y=null,x=$c._;x;)if(m.yd||d>=a)return;if(h>p){if(i){if(i.y>=s)return}else i={x:d,y:c};e={x:d,y:s}}else{if(i){if(i.yr||r>1)if(h>p){if(i){if(i.y>=s)return}else i={x:(c-u)/r,y:c};e={x:(s-u)/r,y:s}}else{if(i){if(i.yg){if(i){if(i.x>=a)return}else i={x:o,y:r*o+u};e={x:a,y:r*a+u}}else{if(i){if(i.xi&&(u=t.substring(i,u),a[o]?a[o]+=u:a[++o]=u),(e=e[0])===(r=r[0])?a[o]?a[o]+=r:a[++o]=r:(a[++o]=null,c.push({i:o,x:lu(e,r)})),i=Kc.lastIndex;return ir;++r)a[(e=c[r]).i]=e.x(n);return a.join("")})}function hu(n,t){for(var e,r=Zo.interpolators.length;--r>=0&&!(e=Zo.interpolators[r](n,t)););return e}function gu(n,t){var e,r=[],u=[],i=n.length,o=t.length,a=Math.min(n.length,t.length);for(e=0;a>e;++e)r.push(hu(n[e],t[e]));for(;i>e;++e)u[e]=n[e];for(;o>e;++e)u[e]=t[e];return function(n){for(e=0;a>e;++e)u[e]=r[e](n);return u}}function pu(n){return function(t){return 0>=t?0:t>=1?1:n(t)}}function vu(n){return function(t){return 1-n(1-t)}}function du(n){return function(t){return.5*(.5>t?n(2*t):2-n(2-2*t))}}function mu(n){return n*n}function yu(n){return n*n*n}function xu(n){if(0>=n)return 0;if(n>=1)return 1;var t=n*n,e=t*n;return 4*(.5>n?e:3*(n-t)+e-.75)}function Mu(n){return function(t){return Math.pow(t,n)}}function _u(n){return 1-Math.cos(n*Sa)}function bu(n){return Math.pow(2,10*(n-1))}function wu(n){return 1-Math.sqrt(1-n*n)}function Su(n,t){var e;return arguments.length<2&&(t=.45),arguments.length?e=t/wa*Math.asin(1/n):(n=1,e=t/4),function(r){return 1+n*Math.pow(2,-10*r)*Math.sin((r-e)*wa/t)}}function ku(n){return n||(n=1.70158),function(t){return t*t*((n+1)*t-n)}}function Eu(n){return 1/2.75>n?7.5625*n*n:2/2.75>n?7.5625*(n-=1.5/2.75)*n+.75:2.5/2.75>n?7.5625*(n-=2.25/2.75)*n+.9375:7.5625*(n-=2.625/2.75)*n+.984375}function Au(n,t){n=Zo.hcl(n),t=Zo.hcl(t);var e=n.h,r=n.c,u=n.l,i=t.h-e,o=t.c-r,a=t.l-u;return isNaN(o)&&(o=0,r=isNaN(r)?t.c:r),isNaN(i)?(i=0,e=isNaN(e)?t.h:e):i>180?i-=360:-180>i&&(i+=360),function(n){return ot(e+i*n,r+o*n,u+a*n)+""}}function Cu(n,t){n=Zo.hsl(n),t=Zo.hsl(t);var e=n.h,r=n.s,u=n.l,i=t.h-e,o=t.s-r,a=t.l-u;return isNaN(o)&&(o=0,r=isNaN(r)?t.s:r),isNaN(i)?(i=0,e=isNaN(e)?t.h:e):i>180?i-=360:-180>i&&(i+=360),function(n){return ut(e+i*n,r+o*n,u+a*n)+""}}function Nu(n,t){n=Zo.lab(n),t=Zo.lab(t);var e=n.l,r=n.a,u=n.b,i=t.l-e,o=t.a-r,a=t.b-u;return function(n){return ct(e+i*n,r+o*n,u+a*n)+""}}function zu(n,t){return t-=n,function(e){return Math.round(n+t*e)}}function Lu(n){var t=[n.a,n.b],e=[n.c,n.d],r=qu(t),u=Tu(t,e),i=qu(Ru(e,t,-u))||0;t[0]*e[1]180?l+=360:l-s>180&&(s+=360),u.push({i:r.push(r.pop()+"rotate(",null,")")-2,x:lu(s,l)})):l&&r.push(r.pop()+"rotate("+l+")"),f!=h?u.push({i:r.push(r.pop()+"skewX(",null,")")-2,x:lu(f,h)}):h&&r.push(r.pop()+"skewX("+h+")"),g[0]!=p[0]||g[1]!=p[1]?(e=r.push(r.pop()+"scale(",null,",",null,")"),u.push({i:e-4,x:lu(g[0],p[0])},{i:e-2,x:lu(g[1],p[1])})):(1!=p[0]||1!=p[1])&&r.push(r.pop()+"scale("+p+")"),e=u.length,function(n){for(var t,i=-1;++i=0;)e.push(u[r])}function Bu(n,t){for(var e=[n],r=[];null!=(n=e.pop());)if(r.push(n),(i=n.children)&&(u=i.length))for(var u,i,o=-1;++oe;++e)(t=n[e][1])>u&&(r=e,u=t);return r}function ii(n){return n.reduce(oi,0)}function oi(n,t){return n+t[1]}function ai(n,t){return ci(n,Math.ceil(Math.log(t.length)/Math.LN2+1))}function ci(n,t){for(var e=-1,r=+n[0],u=(n[1]-r)/t,i=[];++e<=t;)i[e]=u*e+r;return i}function si(n){return[Zo.min(n),Zo.max(n)]}function li(n,t){return n.value-t.value}function fi(n,t){var e=n._pack_next;n._pack_next=t,t._pack_prev=n,t._pack_next=e,e._pack_prev=t}function hi(n,t){n._pack_next=t,t._pack_prev=n}function gi(n,t){var e=t.x-n.x,r=t.y-n.y,u=n.r+t.r;return.999*u*u>e*e+r*r}function pi(n){function t(n){l=Math.min(n.x-n.r,l),f=Math.max(n.x+n.r,f),h=Math.min(n.y-n.r,h),g=Math.max(n.y+n.r,g)}if((e=n.children)&&(s=e.length)){var e,r,u,i,o,a,c,s,l=1/0,f=-1/0,h=1/0,g=-1/0;if(e.forEach(vi),r=e[0],r.x=-r.r,r.y=0,t(r),s>1&&(u=e[1],u.x=u.r,u.y=0,t(u),s>2))for(i=e[2],yi(r,u,i),t(i),fi(r,i),r._pack_prev=i,fi(i,u),u=r._pack_next,o=3;s>o;o++){yi(r,u,i=e[o]);var p=0,v=1,d=1;for(a=u._pack_next;a!==u;a=a._pack_next,v++)if(gi(a,i)){p=1;break}if(1==p)for(c=r._pack_prev;c!==a._pack_prev&&!gi(c,i);c=c._pack_prev,d++);p?(d>v||v==d&&u.ro;o++)i=e[o],i.x-=m,i.y-=y,x=Math.max(x,i.r+Math.sqrt(i.x*i.x+i.y*i.y));n.r=x,e.forEach(di)}}function vi(n){n._pack_next=n._pack_prev=n}function di(n){delete n._pack_next,delete n._pack_prev}function mi(n,t,e,r){var u=n.children;if(n.x=t+=r*n.x,n.y=e+=r*n.y,n.r*=r,u)for(var i=-1,o=u.length;++i=0;)t=u[i],t.z+=e,t.m+=e,e+=t.s+(r+=t.c)}function Si(n,t,e){return n.a.parent===t.parent?n.a:e}function ki(n){return 1+Zo.max(n,function(n){return n.y})}function Ei(n){return n.reduce(function(n,t){return n+t.x},0)/n.length}function Ai(n){var t=n.children;return t&&t.length?Ai(t[0]):n}function Ci(n){var t,e=n.children;return e&&(t=e.length)?Ci(e[t-1]):n}function Ni(n){return{x:n.x,y:n.y,dx:n.dx,dy:n.dy}}function zi(n,t){var e=n.x+t[3],r=n.y+t[0],u=n.dx-t[1]-t[3],i=n.dy-t[0]-t[2];return 0>u&&(e+=u/2,u=0),0>i&&(r+=i/2,i=0),{x:e,y:r,dx:u,dy:i}}function Li(n){var t=n[0],e=n[n.length-1];return e>t?[t,e]:[e,t]}function Ti(n){return n.rangeExtent?n.rangeExtent():Li(n.range())}function qi(n,t,e,r){var u=e(n[0],n[1]),i=r(t[0],t[1]);return function(n){return i(u(n))}}function Ri(n,t){var e,r=0,u=n.length-1,i=n[r],o=n[u];return i>o&&(e=r,r=u,u=e,e=i,i=o,o=e),n[r]=t.floor(i),n[u]=t.ceil(o),n}function Di(n){return n?{floor:function(t){return Math.floor(t/n)*n},ceil:function(t){return Math.ceil(t/n)*n}}:ss}function Pi(n,t,e,r){var u=[],i=[],o=0,a=Math.min(n.length,t.length)-1;for(n[a]2?Pi:qi,c=r?Uu:Pu;return o=u(n,t,c,e),a=u(t,n,c,hu),i}function i(n){return o(n)}var o,a;return i.invert=function(n){return a(n)},i.domain=function(t){return arguments.length?(n=t.map(Number),u()):n},i.range=function(n){return arguments.length?(t=n,u()):t},i.rangeRound=function(n){return i.range(n).interpolate(zu)},i.clamp=function(n){return arguments.length?(r=n,u()):r},i.interpolate=function(n){return arguments.length?(e=n,u()):e},i.ticks=function(t){return Oi(n,t)},i.tickFormat=function(t,e){return Yi(n,t,e)},i.nice=function(t){return Hi(n,t),u()},i.copy=function(){return Ui(n,t,e,r)},u()}function ji(n,t){return Zo.rebind(n,t,"range","rangeRound","interpolate","clamp")}function Hi(n,t){return Ri(n,Di(Fi(n,t)[2]))}function Fi(n,t){null==t&&(t=10);var e=Li(n),r=e[1]-e[0],u=Math.pow(10,Math.floor(Math.log(r/t)/Math.LN10)),i=t/r*u;return.15>=i?u*=10:.35>=i?u*=5:.75>=i&&(u*=2),e[0]=Math.ceil(e[0]/u)*u,e[1]=Math.floor(e[1]/u)*u+.5*u,e[2]=u,e}function Oi(n,t){return Zo.range.apply(Zo,Fi(n,t))}function Yi(n,t,e){var r=Fi(n,t);if(e){var u=Ga.exec(e);if(u.shift(),"s"===u[8]){var i=Zo.formatPrefix(Math.max(ua(r[0]),ua(r[1])));return u[7]||(u[7]="."+Ii(i.scale(r[2]))),u[8]="f",e=Zo.format(u.join("")),function(n){return e(i.scale(n))+i.symbol}}u[7]||(u[7]="."+Zi(u[8],r)),e=u.join("")}else e=",."+Ii(r[2])+"f";return Zo.format(e)}function Ii(n){return-Math.floor(Math.log(n)/Math.LN10+.01)}function Zi(n,t){var e=Ii(t[2]);return n in ls?Math.abs(e-Ii(Math.max(ua(t[0]),ua(t[1]))))+ +("e"!==n):e-2*("%"===n)}function Vi(n,t,e,r){function u(n){return(e?Math.log(0>n?0:n):-Math.log(n>0?0:-n))/Math.log(t)}function i(n){return e?Math.pow(t,n):-Math.pow(t,-n)}function o(t){return n(u(t))}return o.invert=function(t){return i(n.invert(t))},o.domain=function(t){return arguments.length?(e=t[0]>=0,n.domain((r=t.map(Number)).map(u)),o):r},o.base=function(e){return arguments.length?(t=+e,n.domain(r.map(u)),o):t},o.nice=function(){var t=Ri(r.map(u),e?Math:hs);return n.domain(t),r=t.map(i),o},o.ticks=function(){var n=Li(r),o=[],a=n[0],c=n[1],s=Math.floor(u(a)),l=Math.ceil(u(c)),f=t%1?2:t;if(isFinite(l-s)){if(e){for(;l>s;s++)for(var h=1;f>h;h++)o.push(i(s)*h);o.push(i(s))}else for(o.push(i(s));s++0;h--)o.push(i(s)*h);for(s=0;o[s]c;l--);o=o.slice(s,l)}return o},o.tickFormat=function(n,t){if(!arguments.length)return fs;arguments.length<2?t=fs:"function"!=typeof t&&(t=Zo.format(t));var r,a=Math.max(.1,n/o.ticks().length),c=e?(r=1e-12,Math.ceil):(r=-1e-12,Math.floor);return function(n){return n/i(c(u(n)+r))<=a?t(n):""}},o.copy=function(){return Vi(n.copy(),t,e,r)},ji(o,n)}function Xi(n,t,e){function r(t){return n(u(t))}var u=$i(t),i=$i(1/t);return r.invert=function(t){return i(n.invert(t))},r.domain=function(t){return arguments.length?(n.domain((e=t.map(Number)).map(u)),r):e},r.ticks=function(n){return Oi(e,n)},r.tickFormat=function(n,t){return Yi(e,n,t)},r.nice=function(n){return r.domain(Hi(e,n))},r.exponent=function(o){return arguments.length?(u=$i(t=o),i=$i(1/t),n.domain(e.map(u)),r):t},r.copy=function(){return Xi(n.copy(),t,e)},ji(r,n)}function $i(n){return function(t){return 0>t?-Math.pow(-t,n):Math.pow(t,n)}}function Bi(n,t){function e(e){return i[((u.get(e)||("range"===t.t?u.set(e,n.push(e)):0/0))-1)%i.length]}function r(t,e){return Zo.range(n.length).map(function(n){return t+e*n})}var u,i,a;return e.domain=function(r){if(!arguments.length)return n;n=[],u=new o;for(var i,a=-1,c=r.length;++an?[0/0,0/0]:[n>0?o[n-1]:e[0],nt?0/0:t/i+n,[t,t+1/i]},r.copy=function(){return Ji(n,t,e)},u()}function Gi(n,t){function e(e){return e>=e?t[Zo.bisect(n,e)]:void 0}return e.domain=function(t){return arguments.length?(n=t,e):n},e.range=function(n){return arguments.length?(t=n,e):t},e.invertExtent=function(e){return e=t.indexOf(e),[n[e-1],n[e]]},e.copy=function(){return Gi(n,t)},e}function Ki(n){function t(n){return+n}return t.invert=t,t.domain=t.range=function(e){return arguments.length?(n=e.map(t),t):n},t.ticks=function(t){return Oi(n,t)},t.tickFormat=function(t,e){return Yi(n,t,e)},t.copy=function(){return Ki(n)},t}function Qi(n){return n.innerRadius}function no(n){return n.outerRadius}function to(n){return n.startAngle}function eo(n){return n.endAngle}function ro(n){function t(t){function o(){s.push("M",i(n(l),a))}for(var c,s=[],l=[],f=-1,h=t.length,g=bt(e),p=bt(r);++f1&&u.push("H",r[0]),u.join("")}function ao(n){for(var t=0,e=n.length,r=n[0],u=[r[0],",",r[1]];++t1){a=t[1],i=n[c],c++,r+="C"+(u[0]+o[0])+","+(u[1]+o[1])+","+(i[0]-a[0])+","+(i[1]-a[1])+","+i[0]+","+i[1];for(var s=2;s9&&(u=3*t/Math.sqrt(u),o[a]=u*e,o[a+1]=u*r));for(a=-1;++a<=c;)u=(n[Math.min(c,a+1)][0]-n[Math.max(0,a-1)][0])/(6*(1+o[a]*o[a])),i.push([u||0,o[a]*u||0]);return i}function So(n){return n.length<3?uo(n):n[0]+ho(n,wo(n))}function ko(n){for(var t,e,r,u=-1,i=n.length;++ue?s():(u.active=e,i.event&&i.event.start.call(n,l,t),i.tween.forEach(function(e,r){(r=r.call(n,l,t))&&v.push(r)}),Zo.timer(function(){return p.c=c(r||1)?we:c,1},0,a),void 0)}function c(r){if(u.active!==e)return s();for(var o=r/g,a=f(o),c=v.length;c>0;)v[--c].call(n,a); +return o>=1?(i.event&&i.event.end.call(n,l,t),s()):void 0}function s(){return--u.count?delete u[e]:delete n.__transition__,1}var l=n.__data__,f=i.ease,h=i.delay,g=i.duration,p=Ba,v=[];return p.t=h+a,r>=h?o(r-h):(p.c=o,void 0)},0,a)}}function Uo(n,t){n.attr("transform",function(n){return"translate("+t(n)+",0)"})}function jo(n,t){n.attr("transform",function(n){return"translate(0,"+t(n)+")"})}function Ho(n){return n.toISOString()}function Fo(n,t,e){function r(t){return n(t)}function u(n,e){var r=n[1]-n[0],u=r/e,i=Zo.bisect(Us,u);return i==Us.length?[t.year,Fi(n.map(function(n){return n/31536e6}),e)[2]]:i?t[u/Us[i-1]1?{floor:function(t){for(;e(t=n.floor(t));)t=Oo(t-1);return t},ceil:function(t){for(;e(t=n.ceil(t));)t=Oo(+t+1);return t}}:n))},r.ticks=function(n,t){var e=Li(r.domain()),i=null==n?u(e,10):"number"==typeof n?u(e,n):!n.range&&[{range:n},t];return i&&(n=i[0],t=i[1]),n.range(e[0],Oo(+e[1]+1),1>t?1:t)},r.tickFormat=function(){return e},r.copy=function(){return Fo(n.copy(),t,e)},ji(r,n)}function Oo(n){return new Date(n)}function Yo(n){return JSON.parse(n.responseText)}function Io(n){var t=$o.createRange();return t.selectNode($o.body),t.createContextualFragment(n.responseText)}var Zo={version:"3.4.11"};Date.now||(Date.now=function(){return+new Date});var Vo=[].slice,Xo=function(n){return Vo.call(n)},$o=document,Bo=$o.documentElement,Wo=window;try{Xo(Bo.childNodes)[0].nodeType}catch(Jo){Xo=function(n){for(var t=n.length,e=new Array(t);t--;)e[t]=n[t];return e}}try{$o.createElement("div").style.setProperty("opacity",0,"")}catch(Go){var Ko=Wo.Element.prototype,Qo=Ko.setAttribute,na=Ko.setAttributeNS,ta=Wo.CSSStyleDeclaration.prototype,ea=ta.setProperty;Ko.setAttribute=function(n,t){Qo.call(this,n,t+"")},Ko.setAttributeNS=function(n,t,e){na.call(this,n,t,e+"")},ta.setProperty=function(n,t,e){ea.call(this,n,t+"",e)}}Zo.ascending=n,Zo.descending=function(n,t){return n>t?-1:t>n?1:t>=n?0:0/0},Zo.min=function(n,t){var e,r,u=-1,i=n.length;if(1===arguments.length){for(;++u=e);)e=void 0;for(;++ur&&(e=r)}else{for(;++u=e);)e=void 0;for(;++ur&&(e=r)}return e},Zo.max=function(n,t){var e,r,u=-1,i=n.length;if(1===arguments.length){for(;++u=e);)e=void 0;for(;++ue&&(e=r)}else{for(;++u=e);)e=void 0;for(;++ue&&(e=r)}return e},Zo.extent=function(n,t){var e,r,u,i=-1,o=n.length;if(1===arguments.length){for(;++i=e);)e=u=void 0;for(;++ir&&(e=r),r>u&&(u=r))}else{for(;++i=e);)e=void 0;for(;++ir&&(e=r),r>u&&(u=r))}return[e,u]},Zo.sum=function(n,t){var e,r=0,u=n.length,i=-1;if(1===arguments.length)for(;++i1&&(e=e.map(r)),e=e.filter(t),e.length?Zo.quantile(e.sort(n),.5):void 0};var ra=e(n);Zo.bisectLeft=ra.left,Zo.bisect=Zo.bisectRight=ra.right,Zo.bisector=function(t){return e(1===t.length?function(e,r){return n(t(e),r)}:t)},Zo.shuffle=function(n){for(var t,e,r=n.length;r;)e=0|Math.random()*r--,t=n[r],n[r]=n[e],n[e]=t;return n},Zo.permute=function(n,t){for(var e=t.length,r=new Array(e);e--;)r[e]=n[t[e]];return r},Zo.pairs=function(n){for(var t,e=0,r=n.length-1,u=n[0],i=new Array(0>r?0:r);r>e;)i[e]=[t=u,u=n[++e]];return i},Zo.zip=function(){if(!(u=arguments.length))return[];for(var n=-1,t=Zo.min(arguments,r),e=new Array(t);++n=0;)for(r=n[u],t=r.length;--t>=0;)e[--o]=r[t];return e};var ua=Math.abs;Zo.range=function(n,t,e){if(arguments.length<3&&(e=1,arguments.length<2&&(t=n,n=0)),1/0===(t-n)/e)throw new Error("infinite range");var r,i=[],o=u(ua(e)),a=-1;if(n*=o,t*=o,e*=o,0>e)for(;(r=n+e*++a)>t;)i.push(r/o);else for(;(r=n+e*++a)=i.length)return r?r.call(u,a):e?a.sort(e):a;for(var s,l,f,h,g=-1,p=a.length,v=i[c++],d=new o;++g=i.length)return n;var r=[],u=a[e++];return n.forEach(function(n,u){r.push({key:n,values:t(u,e)})}),u?r.sort(function(n,t){return u(n.key,t.key)}):r}var e,r,u={},i=[],a=[];return u.map=function(t,e){return n(e,t,0)},u.entries=function(e){return t(n(Zo.map,e,0),0)},u.key=function(n){return i.push(n),u},u.sortKeys=function(n){return a[i.length-1]=n,u},u.sortValues=function(n){return e=n,u},u.rollup=function(n){return r=n,u},u},Zo.set=function(n){var t=new h;if(n)for(var e=0,r=n.length;r>e;++e)t.add(n[e]);return t},i(h,{has:a,add:function(n){return this[ia+n]=!0,n},remove:function(n){return n=ia+n,n in this&&delete this[n]},values:s,size:l,empty:f,forEach:function(n){for(var t in this)t.charCodeAt(0)===oa&&n.call(this,t.substring(1))}}),Zo.behavior={},Zo.rebind=function(n,t){for(var e,r=1,u=arguments.length;++r=0&&(r=n.substring(e+1),n=n.substring(0,e)),n)return arguments.length<2?this[n].on(r):this[n].on(r,t);if(2===arguments.length){if(null==t)for(n in this)this.hasOwnProperty(n)&&this[n].on(r,null);return this}},Zo.event=null,Zo.requote=function(n){return n.replace(ca,"\\$&")};var ca=/[\\\^\$\*\+\?\|\[\]\(\)\.\{\}]/g,sa={}.__proto__?function(n,t){n.__proto__=t}:function(n,t){for(var e in t)n[e]=t[e]},la=function(n,t){return t.querySelector(n)},fa=function(n,t){return t.querySelectorAll(n)},ha=Bo.matches||Bo[p(Bo,"matchesSelector")],ga=function(n,t){return ha.call(n,t)};"function"==typeof Sizzle&&(la=function(n,t){return Sizzle(n,t)[0]||null},fa=Sizzle,ga=Sizzle.matchesSelector),Zo.selection=function(){return ma};var pa=Zo.selection.prototype=[];pa.select=function(n){var t,e,r,u,i=[];n=b(n);for(var o=-1,a=this.length;++o=0&&(e=n.substring(0,t),n=n.substring(t+1)),va.hasOwnProperty(e)?{space:va[e],local:n}:n}},pa.attr=function(n,t){if(arguments.length<2){if("string"==typeof n){var e=this.node();return n=Zo.ns.qualify(n),n.local?e.getAttributeNS(n.space,n.local):e.getAttribute(n)}for(t in n)this.each(S(t,n[t]));return this}return this.each(S(n,t))},pa.classed=function(n,t){if(arguments.length<2){if("string"==typeof n){var e=this.node(),r=(n=A(n)).length,u=-1;if(t=e.classList){for(;++ur){if("string"!=typeof n){2>r&&(t="");for(e in n)this.each(z(e,n[e],t));return this}if(2>r)return Wo.getComputedStyle(this.node(),null).getPropertyValue(n);e=""}return this.each(z(n,t,e))},pa.property=function(n,t){if(arguments.length<2){if("string"==typeof n)return this.node()[n];for(t in n)this.each(L(t,n[t]));return this}return this.each(L(n,t))},pa.text=function(n){return arguments.length?this.each("function"==typeof n?function(){var t=n.apply(this,arguments);this.textContent=null==t?"":t}:null==n?function(){this.textContent=""}:function(){this.textContent=n}):this.node().textContent},pa.html=function(n){return arguments.length?this.each("function"==typeof n?function(){var t=n.apply(this,arguments);this.innerHTML=null==t?"":t}:null==n?function(){this.innerHTML=""}:function(){this.innerHTML=n}):this.node().innerHTML},pa.append=function(n){return n=T(n),this.select(function(){return this.appendChild(n.apply(this,arguments))})},pa.insert=function(n,t){return n=T(n),t=b(t),this.select(function(){return this.insertBefore(n.apply(this,arguments),t.apply(this,arguments)||null)})},pa.remove=function(){return this.each(function(){var n=this.parentNode;n&&n.removeChild(this)})},pa.data=function(n,t){function e(n,e){var r,u,i,a=n.length,f=e.length,h=Math.min(a,f),g=new Array(f),p=new Array(f),v=new Array(a);if(t){var d,m=new o,y=new o,x=[];for(r=-1;++rr;++r)p[r]=q(e[r]);for(;a>r;++r)v[r]=n[r]}p.update=g,p.parentNode=g.parentNode=v.parentNode=n.parentNode,c.push(p),s.push(g),l.push(v)}var r,u,i=-1,a=this.length;if(!arguments.length){for(n=new Array(a=(r=this[0]).length);++ii;i++){u.push(t=[]),t.parentNode=(e=this[i]).parentNode;for(var a=0,c=e.length;c>a;a++)(r=e[a])&&n.call(r,r.__data__,a,i)&&t.push(r)}return _(u)},pa.order=function(){for(var n=-1,t=this.length;++n=0;)(e=r[u])&&(i&&i!==e.nextSibling&&i.parentNode.insertBefore(e,i),i=e);return this},pa.sort=function(n){n=D.apply(this,arguments);for(var t=-1,e=this.length;++tn;n++)for(var e=this[n],r=0,u=e.length;u>r;r++){var i=e[r];if(i)return i}return null},pa.size=function(){var n=0;return this.each(function(){++n}),n};var da=[];Zo.selection.enter=U,Zo.selection.enter.prototype=da,da.append=pa.append,da.empty=pa.empty,da.node=pa.node,da.call=pa.call,da.size=pa.size,da.select=function(n){for(var t,e,r,u,i,o=[],a=-1,c=this.length;++ar){if("string"!=typeof n){2>r&&(t=!1);for(e in n)this.each(F(e,n[e],t));return this}if(2>r)return(r=this.node()["__on"+n])&&r._;e=!1}return this.each(F(n,t,e))};var ya=Zo.map({mouseenter:"mouseover",mouseleave:"mouseout"});ya.forEach(function(n){"on"+n in $o&&ya.remove(n)});var xa="onselectstart"in $o?null:p(Bo.style,"userSelect"),Ma=0;Zo.mouse=function(n){return Z(n,x())};var _a=/WebKit/.test(Wo.navigator.userAgent)?-1:0;Zo.touches=function(n,t){return arguments.length<2&&(t=x().touches),t?Xo(t).map(function(t){var e=Z(n,t);return e.identifier=t.identifier,e}):[]},Zo.behavior.drag=function(){function n(){this.on("mousedown.drag",u).on("touchstart.drag",i)}function t(n,t,u,i,o){return function(){function a(){var n,e,r=t(h,v);r&&(n=r[0]-x[0],e=r[1]-x[1],p|=n|e,x=r,g({type:"drag",x:r[0]+s[0],y:r[1]+s[1],dx:n,dy:e}))}function c(){t(h,v)&&(m.on(i+d,null).on(o+d,null),y(p&&Zo.event.target===f),g({type:"dragend"}))}var s,l=this,f=Zo.event.target,h=l.parentNode,g=e.of(l,arguments),p=0,v=n(),d=".drag"+(null==v?"":"-"+v),m=Zo.select(u()).on(i+d,a).on(o+d,c),y=I(),x=t(h,v);r?(s=r.apply(l,arguments),s=[s.x-x[0],s.y-x[1]]):s=[0,0],g({type:"dragstart"})}}var e=M(n,"drag","dragstart","dragend"),r=null,u=t(v,Zo.mouse,$,"mousemove","mouseup"),i=t(V,Zo.touch,X,"touchmove","touchend");return n.origin=function(t){return arguments.length?(r=t,n):r},Zo.rebind(n,e,"on")};var ba=Math.PI,wa=2*ba,Sa=ba/2,ka=1e-6,Ea=ka*ka,Aa=ba/180,Ca=180/ba,Na=Math.SQRT2,za=2,La=4;Zo.interpolateZoom=function(n,t){function e(n){var t=n*y;if(m){var e=Q(v),o=i/(za*h)*(e*nt(Na*t+v)-K(v));return[r+o*s,u+o*l,i*e/Q(Na*t+v)]}return[r+n*s,u+n*l,i*Math.exp(Na*t)]}var r=n[0],u=n[1],i=n[2],o=t[0],a=t[1],c=t[2],s=o-r,l=a-u,f=s*s+l*l,h=Math.sqrt(f),g=(c*c-i*i+La*f)/(2*i*za*h),p=(c*c-i*i-La*f)/(2*c*za*h),v=Math.log(Math.sqrt(g*g+1)-g),d=Math.log(Math.sqrt(p*p+1)-p),m=d-v,y=(m||Math.log(c/i))/Na;return e.duration=1e3*y,e},Zo.behavior.zoom=function(){function n(n){n.on(A,s).on(Ra+".zoom",f).on("dblclick.zoom",h).on(z,l)}function t(n){return[(n[0]-S.x)/S.k,(n[1]-S.y)/S.k]}function e(n){return[n[0]*S.k+S.x,n[1]*S.k+S.y]}function r(n){S.k=Math.max(E[0],Math.min(E[1],n))}function u(n,t){t=e(t),S.x+=n[0]-t[0],S.y+=n[1]-t[1]}function i(){_&&_.domain(x.range().map(function(n){return(n-S.x)/S.k}).map(x.invert)),w&&w.domain(b.range().map(function(n){return(n-S.y)/S.k}).map(b.invert))}function o(n){n({type:"zoomstart"})}function a(n){i(),n({type:"zoom",scale:S.k,translate:[S.x,S.y]})}function c(n){n({type:"zoomend"})}function s(){function n(){l=1,u(Zo.mouse(r),h),a(s)}function e(){f.on(C,null).on(N,null),g(l&&Zo.event.target===i),c(s)}var r=this,i=Zo.event.target,s=L.of(r,arguments),l=0,f=Zo.select(Wo).on(C,n).on(N,e),h=t(Zo.mouse(r)),g=I();H.call(r),o(s)}function l(){function n(){var n=Zo.touches(g);return h=S.k,n.forEach(function(n){n.identifier in v&&(v[n.identifier]=t(n))}),n}function e(){var t=Zo.event.target;Zo.select(t).on(M,i).on(_,f),b.push(t);for(var e=Zo.event.changedTouches,o=0,c=e.length;c>o;++o)v[e[o].identifier]=null;var s=n(),l=Date.now();if(1===s.length){if(500>l-m){var h=s[0],g=v[h.identifier];r(2*S.k),u(h,g),y(),a(p)}m=l}else if(s.length>1){var h=s[0],x=s[1],w=h[0]-x[0],k=h[1]-x[1];d=w*w+k*k}}function i(){for(var n,t,e,i,o=Zo.touches(g),c=0,s=o.length;s>c;++c,i=null)if(e=o[c],i=v[e.identifier]){if(t)break;n=e,t=i}if(i){var l=(l=e[0]-n[0])*l+(l=e[1]-n[1])*l,f=d&&Math.sqrt(l/d);n=[(n[0]+e[0])/2,(n[1]+e[1])/2],t=[(t[0]+i[0])/2,(t[1]+i[1])/2],r(f*h)}m=null,u(n,t),a(p)}function f(){if(Zo.event.touches.length){for(var t=Zo.event.changedTouches,e=0,r=t.length;r>e;++e)delete v[t[e].identifier];for(var u in v)return void n()}Zo.selectAll(b).on(x,null),w.on(A,s).on(z,l),k(),c(p)}var h,g=this,p=L.of(g,arguments),v={},d=0,x=".zoom-"+Zo.event.changedTouches[0].identifier,M="touchmove"+x,_="touchend"+x,b=[],w=Zo.select(g).on(A,null).on(z,e),k=I();H.call(g),e(),o(p)}function f(){var n=L.of(this,arguments);d?clearTimeout(d):(g=t(p=v||Zo.mouse(this)),H.call(this),o(n)),d=setTimeout(function(){d=null,c(n)},50),y(),r(Math.pow(2,.002*Ta())*S.k),u(p,g),a(n)}function h(){var n=L.of(this,arguments),e=Zo.mouse(this),i=t(e),s=Math.log(S.k)/Math.LN2;o(n),r(Math.pow(2,Zo.event.shiftKey?Math.ceil(s)-1:Math.floor(s)+1)),u(e,i),a(n),c(n)}var g,p,v,d,m,x,_,b,w,S={x:0,y:0,k:1},k=[960,500],E=qa,A="mousedown.zoom",C="mousemove.zoom",N="mouseup.zoom",z="touchstart.zoom",L=M(n,"zoomstart","zoom","zoomend");return n.event=function(n){n.each(function(){var n=L.of(this,arguments),t=S;Ss?Zo.select(this).transition().each("start.zoom",function(){S=this.__chart__||{x:0,y:0,k:1},o(n)}).tween("zoom:zoom",function(){var e=k[0],r=k[1],u=e/2,i=r/2,o=Zo.interpolateZoom([(u-S.x)/S.k,(i-S.y)/S.k,e/S.k],[(u-t.x)/t.k,(i-t.y)/t.k,e/t.k]);return function(t){var r=o(t),c=e/r[2];this.__chart__=S={x:u-r[0]*c,y:i-r[1]*c,k:c},a(n)}}).each("end.zoom",function(){c(n)}):(this.__chart__=S,o(n),a(n),c(n))})},n.translate=function(t){return arguments.length?(S={x:+t[0],y:+t[1],k:S.k},i(),n):[S.x,S.y]},n.scale=function(t){return arguments.length?(S={x:S.x,y:S.y,k:+t},i(),n):S.k},n.scaleExtent=function(t){return arguments.length?(E=null==t?qa:[+t[0],+t[1]],n):E},n.center=function(t){return arguments.length?(v=t&&[+t[0],+t[1]],n):v},n.size=function(t){return arguments.length?(k=t&&[+t[0],+t[1]],n):k},n.x=function(t){return arguments.length?(_=t,x=t.copy(),S={x:0,y:0,k:1},n):_},n.y=function(t){return arguments.length?(w=t,b=t.copy(),S={x:0,y:0,k:1},n):w},Zo.rebind(n,L,"on")};var Ta,qa=[0,1/0],Ra="onwheel"in $o?(Ta=function(){return-Zo.event.deltaY*(Zo.event.deltaMode?120:1)},"wheel"):"onmousewheel"in $o?(Ta=function(){return Zo.event.wheelDelta},"mousewheel"):(Ta=function(){return-Zo.event.detail},"MozMousePixelScroll");Zo.color=et,et.prototype.toString=function(){return this.rgb()+""},Zo.hsl=rt;var Da=rt.prototype=new et;Da.brighter=function(n){return n=Math.pow(.7,arguments.length?n:1),new rt(this.h,this.s,this.l/n)},Da.darker=function(n){return n=Math.pow(.7,arguments.length?n:1),new rt(this.h,this.s,n*this.l)},Da.rgb=function(){return ut(this.h,this.s,this.l)},Zo.hcl=it;var Pa=it.prototype=new et;Pa.brighter=function(n){return new it(this.h,this.c,Math.min(100,this.l+Ua*(arguments.length?n:1)))},Pa.darker=function(n){return new it(this.h,this.c,Math.max(0,this.l-Ua*(arguments.length?n:1)))},Pa.rgb=function(){return ot(this.h,this.c,this.l).rgb()},Zo.lab=at;var Ua=18,ja=.95047,Ha=1,Fa=1.08883,Oa=at.prototype=new et;Oa.brighter=function(n){return new at(Math.min(100,this.l+Ua*(arguments.length?n:1)),this.a,this.b)},Oa.darker=function(n){return new at(Math.max(0,this.l-Ua*(arguments.length?n:1)),this.a,this.b)},Oa.rgb=function(){return ct(this.l,this.a,this.b)},Zo.rgb=gt;var Ya=gt.prototype=new et;Ya.brighter=function(n){n=Math.pow(.7,arguments.length?n:1);var t=this.r,e=this.g,r=this.b,u=30;return t||e||r?(t&&u>t&&(t=u),e&&u>e&&(e=u),r&&u>r&&(r=u),new gt(Math.min(255,t/n),Math.min(255,e/n),Math.min(255,r/n))):new gt(u,u,u)},Ya.darker=function(n){return n=Math.pow(.7,arguments.length?n:1),new gt(n*this.r,n*this.g,n*this.b)},Ya.hsl=function(){return yt(this.r,this.g,this.b)},Ya.toString=function(){return"#"+dt(this.r)+dt(this.g)+dt(this.b)};var Ia=Zo.map({aliceblue:15792383,antiquewhite:16444375,aqua:65535,aquamarine:8388564,azure:15794175,beige:16119260,bisque:16770244,black:0,blanchedalmond:16772045,blue:255,blueviolet:9055202,brown:10824234,burlywood:14596231,cadetblue:6266528,chartreuse:8388352,chocolate:13789470,coral:16744272,cornflowerblue:6591981,cornsilk:16775388,crimson:14423100,cyan:65535,darkblue:139,darkcyan:35723,darkgoldenrod:12092939,darkgray:11119017,darkgreen:25600,darkgrey:11119017,darkkhaki:12433259,darkmagenta:9109643,darkolivegreen:5597999,darkorange:16747520,darkorchid:10040012,darkred:9109504,darksalmon:15308410,darkseagreen:9419919,darkslateblue:4734347,darkslategray:3100495,darkslategrey:3100495,darkturquoise:52945,darkviolet:9699539,deeppink:16716947,deepskyblue:49151,dimgray:6908265,dimgrey:6908265,dodgerblue:2003199,firebrick:11674146,floralwhite:16775920,forestgreen:2263842,fuchsia:16711935,gainsboro:14474460,ghostwhite:16316671,gold:16766720,goldenrod:14329120,gray:8421504,green:32768,greenyellow:11403055,grey:8421504,honeydew:15794160,hotpink:16738740,indianred:13458524,indigo:4915330,ivory:16777200,khaki:15787660,lavender:15132410,lavenderblush:16773365,lawngreen:8190976,lemonchiffon:16775885,lightblue:11393254,lightcoral:15761536,lightcyan:14745599,lightgoldenrodyellow:16448210,lightgray:13882323,lightgreen:9498256,lightgrey:13882323,lightpink:16758465,lightsalmon:16752762,lightseagreen:2142890,lightskyblue:8900346,lightslategray:7833753,lightslategrey:7833753,lightsteelblue:11584734,lightyellow:16777184,lime:65280,limegreen:3329330,linen:16445670,magenta:16711935,maroon:8388608,mediumaquamarine:6737322,mediumblue:205,mediumorchid:12211667,mediumpurple:9662683,mediumseagreen:3978097,mediumslateblue:8087790,mediumspringgreen:64154,mediumturquoise:4772300,mediumvioletred:13047173,midnightblue:1644912,mintcream:16121850,mistyrose:16770273,moccasin:16770229,navajowhite:16768685,navy:128,oldlace:16643558,olive:8421376,olivedrab:7048739,orange:16753920,orangered:16729344,orchid:14315734,palegoldenrod:15657130,palegreen:10025880,paleturquoise:11529966,palevioletred:14381203,papayawhip:16773077,peachpuff:16767673,peru:13468991,pink:16761035,plum:14524637,powderblue:11591910,purple:8388736,red:16711680,rosybrown:12357519,royalblue:4286945,saddlebrown:9127187,salmon:16416882,sandybrown:16032864,seagreen:3050327,seashell:16774638,sienna:10506797,silver:12632256,skyblue:8900331,slateblue:6970061,slategray:7372944,slategrey:7372944,snow:16775930,springgreen:65407,steelblue:4620980,tan:13808780,teal:32896,thistle:14204888,tomato:16737095,turquoise:4251856,violet:15631086,wheat:16113331,white:16777215,whitesmoke:16119285,yellow:16776960,yellowgreen:10145074});Ia.forEach(function(n,t){Ia.set(n,pt(t))}),Zo.functor=bt,Zo.xhr=St(wt),Zo.dsv=function(n,t){function e(n,e,i){arguments.length<3&&(i=e,e=null);var o=kt(n,t,null==e?r:u(e),i);return o.row=function(n){return arguments.length?o.response(null==(e=n)?r:u(n)):e},o}function r(n){return e.parse(n.responseText)}function u(n){return function(t){return e.parse(t.responseText,n)}}function i(t){return t.map(o).join(n)}function o(n){return a.test(n)?'"'+n.replace(/\"/g,'""')+'"':n}var a=new RegExp('["'+n+"\n]"),c=n.charCodeAt(0);return e.parse=function(n,t){var r;return e.parseRows(n,function(n,e){if(r)return r(n,e-1);var u=new Function("d","return {"+n.map(function(n,t){return JSON.stringify(n)+": d["+t+"]"}).join(",")+"}");r=t?function(n,e){return t(u(n),e)}:u})},e.parseRows=function(n,t){function e(){if(l>=s)return o;if(u)return u=!1,i;var t=l;if(34===n.charCodeAt(t)){for(var e=t;e++l;){var r=n.charCodeAt(l++),a=1;if(10===r)u=!0;else if(13===r)u=!0,10===n.charCodeAt(l)&&(++l,++a);else if(r!==c)continue;return n.substring(t,l-a)}return n.substring(t)}for(var r,u,i={},o={},a=[],s=n.length,l=0,f=0;(r=e())!==o;){for(var h=[];r!==i&&r!==o;)h.push(r),r=e();(!t||(h=t(h,f++)))&&a.push(h)}return a},e.format=function(t){if(Array.isArray(t[0]))return e.formatRows(t);var r=new h,u=[];return t.forEach(function(n){for(var t in n)r.has(t)||u.push(r.add(t))}),[u.map(o).join(n)].concat(t.map(function(t){return u.map(function(n){return o(t[n])}).join(n)})).join("\n")},e.formatRows=function(n){return n.map(i).join("\n")},e},Zo.csv=Zo.dsv(",","text/csv"),Zo.tsv=Zo.dsv(" ","text/tab-separated-values"),Zo.touch=function(n,t,e){if(arguments.length<3&&(e=t,t=x().changedTouches),t)for(var r,u=0,i=t.length;i>u;++u)if((r=t[u]).identifier===e)return Z(n,r)};var Za,Va,Xa,$a,Ba,Wa=Wo[p(Wo,"requestAnimationFrame")]||function(n){setTimeout(n,17)};Zo.timer=function(n,t,e){var r=arguments.length;2>r&&(t=0),3>r&&(e=Date.now());var u=e+t,i={c:n,t:u,f:!1,n:null};Va?Va.n=i:Za=i,Va=i,Xa||($a=clearTimeout($a),Xa=1,Wa(At))},Zo.timer.flush=function(){Ct(),Nt()},Zo.round=function(n,t){return t?Math.round(n*(t=Math.pow(10,t)))/t:Math.round(n)};var Ja=["y","z","a","f","p","n","\xb5","m","","k","M","G","T","P","E","Z","Y"].map(Lt);Zo.formatPrefix=function(n,t){var e=0;return n&&(0>n&&(n*=-1),t&&(n=Zo.round(n,zt(n,t))),e=1+Math.floor(1e-12+Math.log(n)/Math.LN10),e=Math.max(-24,Math.min(24,3*Math.floor((e-1)/3)))),Ja[8+e/3]};var Ga=/(?:([^{])?([<>=^]))?([+\- ])?([$#])?(0)?(\d+)?(,)?(\.-?\d+)?([a-z%])?/i,Ka=Zo.map({b:function(n){return n.toString(2)},c:function(n){return String.fromCharCode(n)},o:function(n){return n.toString(8)},x:function(n){return n.toString(16)},X:function(n){return n.toString(16).toUpperCase()},g:function(n,t){return n.toPrecision(t)},e:function(n,t){return n.toExponential(t)},f:function(n,t){return n.toFixed(t)},r:function(n,t){return(n=Zo.round(n,zt(n,t))).toFixed(Math.max(0,Math.min(20,zt(n*(1+1e-15),t))))}}),Qa=Zo.time={},nc=Date;Rt.prototype={getDate:function(){return this._.getUTCDate()},getDay:function(){return this._.getUTCDay()},getFullYear:function(){return this._.getUTCFullYear()},getHours:function(){return this._.getUTCHours()},getMilliseconds:function(){return this._.getUTCMilliseconds()},getMinutes:function(){return this._.getUTCMinutes()},getMonth:function(){return this._.getUTCMonth()},getSeconds:function(){return this._.getUTCSeconds()},getTime:function(){return this._.getTime()},getTimezoneOffset:function(){return 0},valueOf:function(){return this._.valueOf()},setDate:function(){tc.setUTCDate.apply(this._,arguments)},setDay:function(){tc.setUTCDay.apply(this._,arguments)},setFullYear:function(){tc.setUTCFullYear.apply(this._,arguments)},setHours:function(){tc.setUTCHours.apply(this._,arguments)},setMilliseconds:function(){tc.setUTCMilliseconds.apply(this._,arguments)},setMinutes:function(){tc.setUTCMinutes.apply(this._,arguments)},setMonth:function(){tc.setUTCMonth.apply(this._,arguments)},setSeconds:function(){tc.setUTCSeconds.apply(this._,arguments)},setTime:function(){tc.setTime.apply(this._,arguments)}};var tc=Date.prototype;Qa.year=Dt(function(n){return n=Qa.day(n),n.setMonth(0,1),n},function(n,t){n.setFullYear(n.getFullYear()+t)},function(n){return n.getFullYear()}),Qa.years=Qa.year.range,Qa.years.utc=Qa.year.utc.range,Qa.day=Dt(function(n){var t=new nc(2e3,0);return t.setFullYear(n.getFullYear(),n.getMonth(),n.getDate()),t},function(n,t){n.setDate(n.getDate()+t)},function(n){return n.getDate()-1}),Qa.days=Qa.day.range,Qa.days.utc=Qa.day.utc.range,Qa.dayOfYear=function(n){var t=Qa.year(n);return Math.floor((n-t-6e4*(n.getTimezoneOffset()-t.getTimezoneOffset()))/864e5)},["sunday","monday","tuesday","wednesday","thursday","friday","saturday"].forEach(function(n,t){t=7-t;var e=Qa[n]=Dt(function(n){return(n=Qa.day(n)).setDate(n.getDate()-(n.getDay()+t)%7),n},function(n,t){n.setDate(n.getDate()+7*Math.floor(t))},function(n){var e=Qa.year(n).getDay();return Math.floor((Qa.dayOfYear(n)+(e+t)%7)/7)-(e!==t)});Qa[n+"s"]=e.range,Qa[n+"s"].utc=e.utc.range,Qa[n+"OfYear"]=function(n){var e=Qa.year(n).getDay();return Math.floor((Qa.dayOfYear(n)+(e+t)%7)/7)}}),Qa.week=Qa.sunday,Qa.weeks=Qa.sunday.range,Qa.weeks.utc=Qa.sunday.utc.range,Qa.weekOfYear=Qa.sundayOfYear;var ec={"-":"",_:" ",0:"0"},rc=/^\s*\d+/,uc=/^%/;Zo.locale=function(n){return{numberFormat:Tt(n),timeFormat:Ut(n)}};var ic=Zo.locale({decimal:".",thousands:",",grouping:[3],currency:["$",""],dateTime:"%a %b %e %X %Y",date:"%m/%d/%Y",time:"%H:%M:%S",periods:["AM","PM"],days:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],shortDays:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],months:["January","February","March","April","May","June","July","August","September","October","November","December"],shortMonths:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"]});Zo.format=ic.numberFormat,Zo.geo={},ue.prototype={s:0,t:0,add:function(n){ie(n,this.t,oc),ie(oc.s,this.s,this),this.s?this.t+=oc.t:this.s=oc.t},reset:function(){this.s=this.t=0},valueOf:function(){return this.s}};var oc=new ue;Zo.geo.stream=function(n,t){n&&ac.hasOwnProperty(n.type)?ac[n.type](n,t):oe(n,t)};var ac={Feature:function(n,t){oe(n.geometry,t)},FeatureCollection:function(n,t){for(var e=n.features,r=-1,u=e.length;++rn?4*ba+n:n,fc.lineStart=fc.lineEnd=fc.point=v}};Zo.geo.bounds=function(){function n(n,t){x.push(M=[l=n,h=n]),f>t&&(f=t),t>g&&(g=t)}function t(t,e){var r=le([t*Aa,e*Aa]);if(m){var u=he(m,r),i=[u[1],-u[0],0],o=he(i,u);ve(o),o=de(o);var c=t-p,s=c>0?1:-1,v=o[0]*Ca*s,d=ua(c)>180;if(d^(v>s*p&&s*t>v)){var y=o[1]*Ca;y>g&&(g=y)}else if(v=(v+360)%360-180,d^(v>s*p&&s*t>v)){var y=-o[1]*Ca;f>y&&(f=y)}else f>e&&(f=e),e>g&&(g=e);d?p>t?a(l,t)>a(l,h)&&(h=t):a(t,h)>a(l,h)&&(l=t):h>=l?(l>t&&(l=t),t>h&&(h=t)):t>p?a(l,t)>a(l,h)&&(h=t):a(t,h)>a(l,h)&&(l=t)}else n(t,e);m=r,p=t}function e(){_.point=t}function r(){M[0]=l,M[1]=h,_.point=n,m=null}function u(n,e){if(m){var r=n-p;y+=ua(r)>180?r+(r>0?360:-360):r}else v=n,d=e;fc.point(n,e),t(n,e)}function i(){fc.lineStart()}function o(){u(v,d),fc.lineEnd(),ua(y)>ka&&(l=-(h=180)),M[0]=l,M[1]=h,m=null}function a(n,t){return(t-=n)<0?t+360:t}function c(n,t){return n[0]-t[0]}function s(n,t){return t[0]<=t[1]?t[0]<=n&&n<=t[1]:nlc?(l=-(h=180),f=-(g=90)):y>ka?g=90:-ka>y&&(f=-90),M[0]=l,M[1]=h}};return function(n){g=h=-(l=f=1/0),x=[],Zo.geo.stream(n,_);var t=x.length;if(t){x.sort(c);for(var e,r=1,u=x[0],i=[u];t>r;++r)e=x[r],s(e[0],u)||s(e[1],u)?(a(u[0],e[1])>a(u[0],u[1])&&(u[1]=e[1]),a(e[0],u[1])>a(u[0],u[1])&&(u[0]=e[0])):i.push(u=e); +for(var o,e,p=-1/0,t=i.length-1,r=0,u=i[t];t>=r;u=e,++r)e=i[r],(o=a(u[1],e[0]))>p&&(p=o,l=e[0],h=u[1])}return x=M=null,1/0===l||1/0===f?[[0/0,0/0],[0/0,0/0]]:[[l,f],[h,g]]}}(),Zo.geo.centroid=function(n){hc=gc=pc=vc=dc=mc=yc=xc=Mc=_c=bc=0,Zo.geo.stream(n,wc);var t=Mc,e=_c,r=bc,u=t*t+e*e+r*r;return Ea>u&&(t=mc,e=yc,r=xc,ka>gc&&(t=pc,e=vc,r=dc),u=t*t+e*e+r*r,Ea>u)?[0/0,0/0]:[Math.atan2(e,t)*Ca,G(r/Math.sqrt(u))*Ca]};var hc,gc,pc,vc,dc,mc,yc,xc,Mc,_c,bc,wc={sphere:v,point:ye,lineStart:Me,lineEnd:_e,polygonStart:function(){wc.lineStart=be},polygonEnd:function(){wc.lineStart=Me}},Sc=Ae(we,Te,Re,[-ba,-ba/2]),kc=1e9;Zo.geo.clipExtent=function(){var n,t,e,r,u,i,o={stream:function(n){return u&&(u.valid=!1),u=i(n),u.valid=!0,u},extent:function(a){return arguments.length?(i=Ue(n=+a[0][0],t=+a[0][1],e=+a[1][0],r=+a[1][1]),u&&(u.valid=!1,u=null),o):[[n,t],[e,r]]}};return o.extent([[0,0],[960,500]])},(Zo.geo.conicEqualArea=function(){return He(Fe)}).raw=Fe,Zo.geo.albers=function(){return Zo.geo.conicEqualArea().rotate([96,0]).center([-.6,38.7]).parallels([29.5,45.5]).scale(1070)},Zo.geo.albersUsa=function(){function n(n){var i=n[0],o=n[1];return t=null,e(i,o),t||(r(i,o),t)||u(i,o),t}var t,e,r,u,i=Zo.geo.albers(),o=Zo.geo.conicEqualArea().rotate([154,0]).center([-2,58.5]).parallels([55,65]),a=Zo.geo.conicEqualArea().rotate([157,0]).center([-3,19.9]).parallels([8,18]),c={point:function(n,e){t=[n,e]}};return n.invert=function(n){var t=i.scale(),e=i.translate(),r=(n[0]-e[0])/t,u=(n[1]-e[1])/t;return(u>=.12&&.234>u&&r>=-.425&&-.214>r?o:u>=.166&&.234>u&&r>=-.214&&-.115>r?a:i).invert(n)},n.stream=function(n){var t=i.stream(n),e=o.stream(n),r=a.stream(n);return{point:function(n,u){t.point(n,u),e.point(n,u),r.point(n,u)},sphere:function(){t.sphere(),e.sphere(),r.sphere()},lineStart:function(){t.lineStart(),e.lineStart(),r.lineStart()},lineEnd:function(){t.lineEnd(),e.lineEnd(),r.lineEnd()},polygonStart:function(){t.polygonStart(),e.polygonStart(),r.polygonStart()},polygonEnd:function(){t.polygonEnd(),e.polygonEnd(),r.polygonEnd()}}},n.precision=function(t){return arguments.length?(i.precision(t),o.precision(t),a.precision(t),n):i.precision()},n.scale=function(t){return arguments.length?(i.scale(t),o.scale(.35*t),a.scale(t),n.translate(i.translate())):i.scale()},n.translate=function(t){if(!arguments.length)return i.translate();var s=i.scale(),l=+t[0],f=+t[1];return e=i.translate(t).clipExtent([[l-.455*s,f-.238*s],[l+.455*s,f+.238*s]]).stream(c).point,r=o.translate([l-.307*s,f+.201*s]).clipExtent([[l-.425*s+ka,f+.12*s+ka],[l-.214*s-ka,f+.234*s-ka]]).stream(c).point,u=a.translate([l-.205*s,f+.212*s]).clipExtent([[l-.214*s+ka,f+.166*s+ka],[l-.115*s-ka,f+.234*s-ka]]).stream(c).point,n},n.scale(1070)};var Ec,Ac,Cc,Nc,zc,Lc,Tc={point:v,lineStart:v,lineEnd:v,polygonStart:function(){Ac=0,Tc.lineStart=Oe},polygonEnd:function(){Tc.lineStart=Tc.lineEnd=Tc.point=v,Ec+=ua(Ac/2)}},qc={point:Ye,lineStart:v,lineEnd:v,polygonStart:v,polygonEnd:v},Rc={point:Ve,lineStart:Xe,lineEnd:$e,polygonStart:function(){Rc.lineStart=Be},polygonEnd:function(){Rc.point=Ve,Rc.lineStart=Xe,Rc.lineEnd=$e}};Zo.geo.path=function(){function n(n){return n&&("function"==typeof a&&i.pointRadius(+a.apply(this,arguments)),o&&o.valid||(o=u(i)),Zo.geo.stream(n,o)),i.result()}function t(){return o=null,n}var e,r,u,i,o,a=4.5;return n.area=function(n){return Ec=0,Zo.geo.stream(n,u(Tc)),Ec},n.centroid=function(n){return pc=vc=dc=mc=yc=xc=Mc=_c=bc=0,Zo.geo.stream(n,u(Rc)),bc?[Mc/bc,_c/bc]:xc?[mc/xc,yc/xc]:dc?[pc/dc,vc/dc]:[0/0,0/0]},n.bounds=function(n){return zc=Lc=-(Cc=Nc=1/0),Zo.geo.stream(n,u(qc)),[[Cc,Nc],[zc,Lc]]},n.projection=function(n){return arguments.length?(u=(e=n)?n.stream||Ge(n):wt,t()):e},n.context=function(n){return arguments.length?(i=null==(r=n)?new Ie:new We(n),"function"!=typeof a&&i.pointRadius(a),t()):r},n.pointRadius=function(t){return arguments.length?(a="function"==typeof t?t:(i.pointRadius(+t),+t),n):a},n.projection(Zo.geo.albersUsa()).context(null)},Zo.geo.transform=function(n){return{stream:function(t){var e=new Ke(t);for(var r in n)e[r]=n[r];return e}}},Ke.prototype={point:function(n,t){this.stream.point(n,t)},sphere:function(){this.stream.sphere()},lineStart:function(){this.stream.lineStart()},lineEnd:function(){this.stream.lineEnd()},polygonStart:function(){this.stream.polygonStart()},polygonEnd:function(){this.stream.polygonEnd()}},Zo.geo.projection=nr,Zo.geo.projectionMutator=tr,(Zo.geo.equirectangular=function(){return nr(rr)}).raw=rr.invert=rr,Zo.geo.rotation=function(n){function t(t){return t=n(t[0]*Aa,t[1]*Aa),t[0]*=Ca,t[1]*=Ca,t}return n=ir(n[0]%360*Aa,n[1]*Aa,n.length>2?n[2]*Aa:0),t.invert=function(t){return t=n.invert(t[0]*Aa,t[1]*Aa),t[0]*=Ca,t[1]*=Ca,t},t},ur.invert=rr,Zo.geo.circle=function(){function n(){var n="function"==typeof r?r.apply(this,arguments):r,t=ir(-n[0]*Aa,-n[1]*Aa,0).invert,u=[];return e(null,null,1,{point:function(n,e){u.push(n=t(n,e)),n[0]*=Ca,n[1]*=Ca}}),{type:"Polygon",coordinates:[u]}}var t,e,r=[0,0],u=6;return n.origin=function(t){return arguments.length?(r=t,n):r},n.angle=function(r){return arguments.length?(e=sr((t=+r)*Aa,u*Aa),n):t},n.precision=function(r){return arguments.length?(e=sr(t*Aa,(u=+r)*Aa),n):u},n.angle(90)},Zo.geo.distance=function(n,t){var e,r=(t[0]-n[0])*Aa,u=n[1]*Aa,i=t[1]*Aa,o=Math.sin(r),a=Math.cos(r),c=Math.sin(u),s=Math.cos(u),l=Math.sin(i),f=Math.cos(i);return Math.atan2(Math.sqrt((e=f*o)*e+(e=s*l-c*f*a)*e),c*l+s*f*a)},Zo.geo.graticule=function(){function n(){return{type:"MultiLineString",coordinates:t()}}function t(){return Zo.range(Math.ceil(i/d)*d,u,d).map(h).concat(Zo.range(Math.ceil(s/m)*m,c,m).map(g)).concat(Zo.range(Math.ceil(r/p)*p,e,p).filter(function(n){return ua(n%d)>ka}).map(l)).concat(Zo.range(Math.ceil(a/v)*v,o,v).filter(function(n){return ua(n%m)>ka}).map(f))}var e,r,u,i,o,a,c,s,l,f,h,g,p=10,v=p,d=90,m=360,y=2.5;return n.lines=function(){return t().map(function(n){return{type:"LineString",coordinates:n}})},n.outline=function(){return{type:"Polygon",coordinates:[h(i).concat(g(c).slice(1),h(u).reverse().slice(1),g(s).reverse().slice(1))]}},n.extent=function(t){return arguments.length?n.majorExtent(t).minorExtent(t):n.minorExtent()},n.majorExtent=function(t){return arguments.length?(i=+t[0][0],u=+t[1][0],s=+t[0][1],c=+t[1][1],i>u&&(t=i,i=u,u=t),s>c&&(t=s,s=c,c=t),n.precision(y)):[[i,s],[u,c]]},n.minorExtent=function(t){return arguments.length?(r=+t[0][0],e=+t[1][0],a=+t[0][1],o=+t[1][1],r>e&&(t=r,r=e,e=t),a>o&&(t=a,a=o,o=t),n.precision(y)):[[r,a],[e,o]]},n.step=function(t){return arguments.length?n.majorStep(t).minorStep(t):n.minorStep()},n.majorStep=function(t){return arguments.length?(d=+t[0],m=+t[1],n):[d,m]},n.minorStep=function(t){return arguments.length?(p=+t[0],v=+t[1],n):[p,v]},n.precision=function(t){return arguments.length?(y=+t,l=fr(a,o,90),f=hr(r,e,y),h=fr(s,c,90),g=hr(i,u,y),n):y},n.majorExtent([[-180,-90+ka],[180,90-ka]]).minorExtent([[-180,-80-ka],[180,80+ka]])},Zo.geo.greatArc=function(){function n(){return{type:"LineString",coordinates:[t||r.apply(this,arguments),e||u.apply(this,arguments)]}}var t,e,r=gr,u=pr;return n.distance=function(){return Zo.geo.distance(t||r.apply(this,arguments),e||u.apply(this,arguments))},n.source=function(e){return arguments.length?(r=e,t="function"==typeof e?null:e,n):r},n.target=function(t){return arguments.length?(u=t,e="function"==typeof t?null:t,n):u},n.precision=function(){return arguments.length?n:0},n},Zo.geo.interpolate=function(n,t){return vr(n[0]*Aa,n[1]*Aa,t[0]*Aa,t[1]*Aa)},Zo.geo.length=function(n){return Dc=0,Zo.geo.stream(n,Pc),Dc};var Dc,Pc={sphere:v,point:v,lineStart:dr,lineEnd:v,polygonStart:v,polygonEnd:v},Uc=mr(function(n){return Math.sqrt(2/(1+n))},function(n){return 2*Math.asin(n/2)});(Zo.geo.azimuthalEqualArea=function(){return nr(Uc)}).raw=Uc;var jc=mr(function(n){var t=Math.acos(n);return t&&t/Math.sin(t)},wt);(Zo.geo.azimuthalEquidistant=function(){return nr(jc)}).raw=jc,(Zo.geo.conicConformal=function(){return He(yr)}).raw=yr,(Zo.geo.conicEquidistant=function(){return He(xr)}).raw=xr;var Hc=mr(function(n){return 1/n},Math.atan);(Zo.geo.gnomonic=function(){return nr(Hc)}).raw=Hc,Mr.invert=function(n,t){return[n,2*Math.atan(Math.exp(t))-Sa]},(Zo.geo.mercator=function(){return _r(Mr)}).raw=Mr;var Fc=mr(function(){return 1},Math.asin);(Zo.geo.orthographic=function(){return nr(Fc)}).raw=Fc;var Oc=mr(function(n){return 1/(1+n)},function(n){return 2*Math.atan(n)});(Zo.geo.stereographic=function(){return nr(Oc)}).raw=Oc,br.invert=function(n,t){return[-t,2*Math.atan(Math.exp(n))-Sa]},(Zo.geo.transverseMercator=function(){var n=_r(br),t=n.center,e=n.rotate;return n.center=function(n){return n?t([-n[1],n[0]]):(n=t(),[n[1],-n[0]])},n.rotate=function(n){return n?e([n[0],n[1],n.length>2?n[2]+90:90]):(n=e(),[n[0],n[1],n[2]-90])},e([0,0,90])}).raw=br,Zo.geom={},Zo.geom.hull=function(n){function t(n){if(n.length<3)return[];var t,u=bt(e),i=bt(r),o=n.length,a=[],c=[];for(t=0;o>t;t++)a.push([+u.call(this,n[t],t),+i.call(this,n[t],t),t]);for(a.sort(Er),t=0;o>t;t++)c.push([a[t][0],-a[t][1]]);var s=kr(a),l=kr(c),f=l[0]===s[0],h=l[l.length-1]===s[s.length-1],g=[];for(t=s.length-1;t>=0;--t)g.push(n[a[s[t]][2]]);for(t=+f;t=r&&s.x<=i&&s.y>=u&&s.y<=o?[[r,o],[i,o],[i,u],[r,u]]:[];l.point=n[a]}),t}function e(n){return n.map(function(n,t){return{x:Math.round(i(n,t)/ka)*ka,y:Math.round(o(n,t)/ka)*ka,i:t}})}var r=wr,u=Sr,i=r,o=u,a=Jc;return n?t(n):(t.links=function(n){return tu(e(n)).edges.filter(function(n){return n.l&&n.r}).map(function(t){return{source:n[t.l.i],target:n[t.r.i]}})},t.triangles=function(n){var t=[];return tu(e(n)).cells.forEach(function(e,r){for(var u,i,o=e.site,a=e.edges.sort(Hr),c=-1,s=a.length,l=a[s-1].edge,f=l.l===o?l.r:l.l;++c=s,h=r>=l,g=(h<<1)+f;n.leaf=!1,n=n.nodes[g]||(n.nodes[g]=ou()),f?u=s:a=s,h?o=l:c=l,i(n,t,e,r,u,o,a,c)}var l,f,h,g,p,v,d,m,y,x=bt(a),M=bt(c);if(null!=t)v=t,d=e,m=r,y=u;else if(m=y=-(v=d=1/0),f=[],h=[],p=n.length,o)for(g=0;p>g;++g)l=n[g],l.xm&&(m=l.x),l.y>y&&(y=l.y),f.push(l.x),h.push(l.y);else for(g=0;p>g;++g){var _=+x(l=n[g],g),b=+M(l,g);v>_&&(v=_),d>b&&(d=b),_>m&&(m=_),b>y&&(y=b),f.push(_),h.push(b)}var w=m-v,S=y-d;w>S?y=d+w:m=v+S;var k=ou();if(k.add=function(n){i(k,n,+x(n,++g),+M(n,g),v,d,m,y)},k.visit=function(n){au(n,k,v,d,m,y)},g=-1,null==t){for(;++g=0?n.substring(0,t):n,r=t>=0?n.substring(t+1):"in";return e=ns.get(e)||Qc,r=ts.get(r)||wt,pu(r(e.apply(null,Vo.call(arguments,1))))},Zo.interpolateHcl=Au,Zo.interpolateHsl=Cu,Zo.interpolateLab=Nu,Zo.interpolateRound=zu,Zo.transform=function(n){var t=$o.createElementNS(Zo.ns.prefix.svg,"g");return(Zo.transform=function(n){if(null!=n){t.setAttribute("transform",n);var e=t.transform.baseVal.consolidate()}return new Lu(e?e.matrix:es)})(n)},Lu.prototype.toString=function(){return"translate("+this.translate+")rotate("+this.rotate+")skewX("+this.skew+")scale("+this.scale+")"};var es={a:1,b:0,c:0,d:1,e:0,f:0};Zo.interpolateTransform=Du,Zo.layout={},Zo.layout.bundle=function(){return function(n){for(var t=[],e=-1,r=n.length;++ea*a/d){if(p>c){var s=t.charge/c;n.px-=i*s,n.py-=o*s}return!0}if(t.point&&c&&p>c){var s=t.pointCharge/c;n.px-=i*s,n.py-=o*s}}return!t.charge}}function t(n){n.px=Zo.event.x,n.py=Zo.event.y,a.resume()}var e,r,u,i,o,a={},c=Zo.dispatch("start","tick","end"),s=[1,1],l=.9,f=rs,h=us,g=-30,p=is,v=.1,d=.64,m=[],y=[];return a.tick=function(){if((r*=.99)<.005)return c.end({type:"end",alpha:r=0}),!0;var t,e,a,f,h,p,d,x,M,_=m.length,b=y.length;for(e=0;b>e;++e)a=y[e],f=a.source,h=a.target,x=h.x-f.x,M=h.y-f.y,(p=x*x+M*M)&&(p=r*i[e]*((p=Math.sqrt(p))-u[e])/p,x*=p,M*=p,h.x-=x*(d=f.weight/(h.weight+f.weight)),h.y-=M*d,f.x+=x*(d=1-d),f.y+=M*d);if((d=r*v)&&(x=s[0]/2,M=s[1]/2,e=-1,d))for(;++e<_;)a=m[e],a.x+=(x-a.x)*d,a.y+=(M-a.y)*d;if(g)for(Vu(t=Zo.geom.quadtree(m),r,o),e=-1;++e<_;)(a=m[e]).fixed||t.visit(n(a));for(e=-1;++e<_;)a=m[e],a.fixed?(a.x=a.px,a.y=a.py):(a.x-=(a.px-(a.px=a.x))*l,a.y-=(a.py-(a.py=a.y))*l);c.tick({type:"tick",alpha:r})},a.nodes=function(n){return arguments.length?(m=n,a):m},a.links=function(n){return arguments.length?(y=n,a):y},a.size=function(n){return arguments.length?(s=n,a):s},a.linkDistance=function(n){return arguments.length?(f="function"==typeof n?n:+n,a):f},a.distance=a.linkDistance,a.linkStrength=function(n){return arguments.length?(h="function"==typeof n?n:+n,a):h},a.friction=function(n){return arguments.length?(l=+n,a):l},a.charge=function(n){return arguments.length?(g="function"==typeof n?n:+n,a):g},a.chargeDistance=function(n){return arguments.length?(p=n*n,a):Math.sqrt(p)},a.gravity=function(n){return arguments.length?(v=+n,a):v},a.theta=function(n){return arguments.length?(d=n*n,a):Math.sqrt(d)},a.alpha=function(n){return arguments.length?(n=+n,r?r=n>0?n:0:n>0&&(c.start({type:"start",alpha:r=n}),Zo.timer(a.tick)),a):r},a.start=function(){function n(n,r){if(!e){for(e=new Array(c),a=0;c>a;++a)e[a]=[];for(a=0;s>a;++a){var u=y[a];e[u.source.index].push(u.target),e[u.target.index].push(u.source)}}for(var i,o=e[t],a=-1,s=o.length;++at;++t)(r=m[t]).index=t,r.weight=0;for(t=0;l>t;++t)r=y[t],"number"==typeof r.source&&(r.source=m[r.source]),"number"==typeof r.target&&(r.target=m[r.target]),++r.source.weight,++r.target.weight;for(t=0;c>t;++t)r=m[t],isNaN(r.x)&&(r.x=n("x",p)),isNaN(r.y)&&(r.y=n("y",v)),isNaN(r.px)&&(r.px=r.x),isNaN(r.py)&&(r.py=r.y);if(u=[],"function"==typeof f)for(t=0;l>t;++t)u[t]=+f.call(this,y[t],t);else for(t=0;l>t;++t)u[t]=f;if(i=[],"function"==typeof h)for(t=0;l>t;++t)i[t]=+h.call(this,y[t],t);else for(t=0;l>t;++t)i[t]=h;if(o=[],"function"==typeof g)for(t=0;c>t;++t)o[t]=+g.call(this,m[t],t);else for(t=0;c>t;++t)o[t]=g;return a.resume()},a.resume=function(){return a.alpha(.1)},a.stop=function(){return a.alpha(0)},a.drag=function(){return e||(e=Zo.behavior.drag().origin(wt).on("dragstart.force",Ou).on("drag.force",t).on("dragend.force",Yu)),arguments.length?(this.on("mouseover.force",Iu).on("mouseout.force",Zu).call(e),void 0):e},Zo.rebind(a,c,"on")};var rs=20,us=1,is=1/0;Zo.layout.hierarchy=function(){function n(u){var i,o=[u],a=[];for(u.depth=0;null!=(i=o.pop());)if(a.push(i),(s=e.call(n,i,i.depth))&&(c=s.length)){for(var c,s,l;--c>=0;)o.push(l=s[c]),l.parent=i,l.depth=i.depth+1;r&&(i.value=0),i.children=s}else r&&(i.value=+r.call(n,i,i.depth)||0),delete i.children;return Bu(u,function(n){var e,u;t&&(e=n.children)&&e.sort(t),r&&(u=n.parent)&&(u.value+=n.value)}),a}var t=Gu,e=Wu,r=Ju;return n.sort=function(e){return arguments.length?(t=e,n):t},n.children=function(t){return arguments.length?(e=t,n):e},n.value=function(t){return arguments.length?(r=t,n):r},n.revalue=function(t){return r&&($u(t,function(n){n.children&&(n.value=0)}),Bu(t,function(t){var e;t.children||(t.value=+r.call(n,t,t.depth)||0),(e=t.parent)&&(e.value+=t.value)})),t},n},Zo.layout.partition=function(){function n(t,e,r,u){var i=t.children;if(t.x=e,t.y=t.depth*u,t.dx=r,t.dy=u,i&&(o=i.length)){var o,a,c,s=-1;for(r=t.value?r/t.value:0;++sg;++g)for(u.call(n,s[0][g],p=v[g],l[0][g][1]),h=1;d>h;++h)u.call(n,s[h][g],p+=l[h-1][g][1],l[h][g][1]);return a}var t=wt,e=ei,r=ri,u=ti,i=Qu,o=ni;return n.values=function(e){return arguments.length?(t=e,n):t},n.order=function(t){return arguments.length?(e="function"==typeof t?t:as.get(t)||ei,n):e},n.offset=function(t){return arguments.length?(r="function"==typeof t?t:cs.get(t)||ri,n):r},n.x=function(t){return arguments.length?(i=t,n):i},n.y=function(t){return arguments.length?(o=t,n):o},n.out=function(t){return arguments.length?(u=t,n):u},n};var as=Zo.map({"inside-out":function(n){var t,e,r=n.length,u=n.map(ui),i=n.map(ii),o=Zo.range(r).sort(function(n,t){return u[n]-u[t]}),a=0,c=0,s=[],l=[];for(t=0;r>t;++t)e=o[t],c>a?(a+=i[e],s.push(e)):(c+=i[e],l.push(e));return l.reverse().concat(s)},reverse:function(n){return Zo.range(n.length).reverse()},"default":ei}),cs=Zo.map({silhouette:function(n){var t,e,r,u=n.length,i=n[0].length,o=[],a=0,c=[];for(e=0;i>e;++e){for(t=0,r=0;u>t;t++)r+=n[t][e][1];r>a&&(a=r),o.push(r)}for(e=0;i>e;++e)c[e]=(a-o[e])/2;return c},wiggle:function(n){var t,e,r,u,i,o,a,c,s,l=n.length,f=n[0],h=f.length,g=[];for(g[0]=c=s=0,e=1;h>e;++e){for(t=0,u=0;l>t;++t)u+=n[t][e][1];for(t=0,i=0,a=f[e][0]-f[e-1][0];l>t;++t){for(r=0,o=(n[t][e][1]-n[t][e-1][1])/(2*a);t>r;++r)o+=(n[r][e][1]-n[r][e-1][1])/a;i+=o*n[t][e][1]}g[e]=c-=u?i/u*a:0,s>c&&(s=c)}for(e=0;h>e;++e)g[e]-=s;return g},expand:function(n){var t,e,r,u=n.length,i=n[0].length,o=1/u,a=[];for(e=0;i>e;++e){for(t=0,r=0;u>t;t++)r+=n[t][e][1];if(r)for(t=0;u>t;t++)n[t][e][1]/=r;else for(t=0;u>t;t++)n[t][e][1]=o}for(e=0;i>e;++e)a[e]=0;return a},zero:ri});Zo.layout.histogram=function(){function n(n,i){for(var o,a,c=[],s=n.map(e,this),l=r.call(this,s,i),f=u.call(this,l,s,i),i=-1,h=s.length,g=f.length-1,p=t?1:1/h;++i0)for(i=-1;++i=l[0]&&a<=l[1]&&(o=c[Zo.bisect(f,a,1,g)-1],o.y+=p,o.push(n[i]));return c}var t=!0,e=Number,r=si,u=ai;return n.value=function(t){return arguments.length?(e=t,n):e},n.range=function(t){return arguments.length?(r=bt(t),n):r},n.bins=function(t){return arguments.length?(u="number"==typeof t?function(n){return ci(n,t)}:bt(t),n):u},n.frequency=function(e){return arguments.length?(t=!!e,n):t},n},Zo.layout.pack=function(){function n(n,i){var o=e.call(this,n,i),a=o[0],c=u[0],s=u[1],l=null==t?Math.sqrt:"function"==typeof t?t:function(){return t};if(a.x=a.y=0,Bu(a,function(n){n.r=+l(n.value)}),Bu(a,pi),r){var f=r*(t?1:Math.max(2*a.r/c,2*a.r/s))/2;Bu(a,function(n){n.r+=f}),Bu(a,pi),Bu(a,function(n){n.r-=f})}return mi(a,c/2,s/2,t?1:1/Math.max(2*a.r/c,2*a.r/s)),o}var t,e=Zo.layout.hierarchy().sort(li),r=0,u=[1,1];return n.size=function(t){return arguments.length?(u=t,n):u},n.radius=function(e){return arguments.length?(t=null==e||"function"==typeof e?e:+e,n):t},n.padding=function(t){return arguments.length?(r=+t,n):r},Xu(n,e)},Zo.layout.tree=function(){function n(n,u){var l=o.call(this,n,u),f=l[0],h=t(f);if(Bu(h,e),h.parent.m=-h.z,$u(h,r),s)$u(f,i);else{var g=f,p=f,v=f;$u(f,function(n){n.xp.x&&(p=n),n.depth>v.depth&&(v=n)});var d=a(g,p)/2-g.x,m=c[0]/(p.x+a(p,g)/2+d),y=c[1]/(v.depth||1);$u(f,function(n){n.x=(n.x+d)*m,n.y=n.depth*y})}return l}function t(n){for(var t,e={A:null,children:[n]},r=[e];null!=(t=r.pop());)for(var u,i=t.children,o=0,a=i.length;a>o;++o)r.push((i[o]=u={_:i[o],parent:t,children:(u=i[o].children)&&u.slice()||[],A:null,a:null,z:0,m:0,c:0,s:0,t:null,i:o}).a=u);return e.children[0]}function e(n){var t=n.children,e=n.parent.children,r=n.i?e[n.i-1]:null;if(t.length){wi(n);var i=(t[0].z+t[t.length-1].z)/2;r?(n.z=r.z+a(n._,r._),n.m=n.z-i):n.z=i}else r&&(n.z=r.z+a(n._,r._));n.parent.A=u(n,r,n.parent.A||e[0])}function r(n){n._.x=n.z+n.parent.m,n.m+=n.parent.m}function u(n,t,e){if(t){for(var r,u=n,i=n,o=t,c=u.parent.children[0],s=u.m,l=i.m,f=o.m,h=c.m;o=_i(o),u=Mi(u),o&&u;)c=Mi(c),i=_i(i),i.a=n,r=o.z+f-u.z-s+a(o._,u._),r>0&&(bi(Si(o,n,e),n,r),s+=r,l+=r),f+=o.m,s+=u.m,h+=c.m,l+=i.m;o&&!_i(i)&&(i.t=o,i.m+=f-l),u&&!Mi(c)&&(c.t=u,c.m+=s-h,e=n)}return e}function i(n){n.x*=c[0],n.y=n.depth*c[1]}var o=Zo.layout.hierarchy().sort(null).value(null),a=xi,c=[1,1],s=null;return n.separation=function(t){return arguments.length?(a=t,n):a},n.size=function(t){return arguments.length?(s=null==(c=t)?i:null,n):s?null:c},n.nodeSize=function(t){return arguments.length?(s=null==(c=t)?null:i,n):s?c:null},Xu(n,o)},Zo.layout.cluster=function(){function n(n,i){var o,a=t.call(this,n,i),c=a[0],s=0;Bu(c,function(n){var t=n.children;t&&t.length?(n.x=Ei(t),n.y=ki(t)):(n.x=o?s+=e(n,o):0,n.y=0,o=n)});var l=Ai(c),f=Ci(c),h=l.x-e(l,f)/2,g=f.x+e(f,l)/2;return Bu(c,u?function(n){n.x=(n.x-c.x)*r[0],n.y=(c.y-n.y)*r[1]}:function(n){n.x=(n.x-h)/(g-h)*r[0],n.y=(1-(c.y?n.y/c.y:1))*r[1]}),a}var t=Zo.layout.hierarchy().sort(null).value(null),e=xi,r=[1,1],u=!1;return n.separation=function(t){return arguments.length?(e=t,n):e},n.size=function(t){return arguments.length?(u=null==(r=t),n):u?null:r},n.nodeSize=function(t){return arguments.length?(u=null!=(r=t),n):u?r:null},Xu(n,t)},Zo.layout.treemap=function(){function n(n,t){for(var e,r,u=-1,i=n.length;++ut?0:t),e.area=isNaN(r)||0>=r?0:r}function t(e){var i=e.children;if(i&&i.length){var o,a,c,s=f(e),l=[],h=i.slice(),p=1/0,v="slice"===g?s.dx:"dice"===g?s.dy:"slice-dice"===g?1&e.depth?s.dy:s.dx:Math.min(s.dx,s.dy);for(n(h,s.dx*s.dy/e.value),l.area=0;(c=h.length)>0;)l.push(o=h[c-1]),l.area+=o.area,"squarify"!==g||(a=r(l,v))<=p?(h.pop(),p=a):(l.area-=l.pop().area,u(l,v,s,!1),v=Math.min(s.dx,s.dy),l.length=l.area=0,p=1/0);l.length&&(u(l,v,s,!0),l.length=l.area=0),i.forEach(t)}}function e(t){var r=t.children;if(r&&r.length){var i,o=f(t),a=r.slice(),c=[];for(n(a,o.dx*o.dy/t.value),c.area=0;i=a.pop();)c.push(i),c.area+=i.area,null!=i.z&&(u(c,i.z?o.dx:o.dy,o,!a.length),c.length=c.area=0);r.forEach(e)}}function r(n,t){for(var e,r=n.area,u=0,i=1/0,o=-1,a=n.length;++oe&&(i=e),e>u&&(u=e));return r*=r,t*=t,r?Math.max(t*u*p/r,r/(t*i*p)):1/0}function u(n,t,e,r){var u,i=-1,o=n.length,a=e.x,s=e.y,l=t?c(n.area/t):0;if(t==e.dx){for((r||l>e.dy)&&(l=e.dy);++ie.dx)&&(l=e.dx);++ie&&(t=1),1>e&&(n=0),function(){var e,r,u;do e=2*Math.random()-1,r=2*Math.random()-1,u=e*e+r*r;while(!u||u>1);return n+t*e*Math.sqrt(-2*Math.log(u)/u)}},logNormal:function(){var n=Zo.random.normal.apply(Zo,arguments);return function(){return Math.exp(n())}},bates:function(n){var t=Zo.random.irwinHall(n);return function(){return t()/n}},irwinHall:function(n){return function(){for(var t=0,e=0;n>e;e++)t+=Math.random();return t}}},Zo.scale={};var ss={floor:wt,ceil:wt};Zo.scale.linear=function(){return Ui([0,1],[0,1],hu,!1)};var ls={s:1,g:1,p:1,r:1,e:1};Zo.scale.log=function(){return Vi(Zo.scale.linear().domain([0,1]),10,!0,[1,10])};var fs=Zo.format(".0e"),hs={floor:function(n){return-Math.ceil(-n)},ceil:function(n){return-Math.floor(-n)}};Zo.scale.pow=function(){return Xi(Zo.scale.linear(),1,[0,1])},Zo.scale.sqrt=function(){return Zo.scale.pow().exponent(.5)},Zo.scale.ordinal=function(){return Bi([],{t:"range",a:[[]]})},Zo.scale.category10=function(){return Zo.scale.ordinal().range(gs)},Zo.scale.category20=function(){return Zo.scale.ordinal().range(ps)},Zo.scale.category20b=function(){return Zo.scale.ordinal().range(vs)},Zo.scale.category20c=function(){return Zo.scale.ordinal().range(ds)};var gs=[2062260,16744206,2924588,14034728,9725885,9197131,14907330,8355711,12369186,1556175].map(vt),ps=[2062260,11454440,16744206,16759672,2924588,10018698,14034728,16750742,9725885,12955861,9197131,12885140,14907330,16234194,8355711,13092807,12369186,14408589,1556175,10410725].map(vt),vs=[3750777,5395619,7040719,10264286,6519097,9216594,11915115,13556636,9202993,12426809,15186514,15190932,8666169,11356490,14049643,15177372,8077683,10834324,13528509,14589654].map(vt),ds=[3244733,7057110,10406625,13032431,15095053,16616764,16625259,16634018,3253076,7652470,10607003,13101504,7695281,10394312,12369372,14342891,6513507,9868950,12434877,14277081].map(vt);Zo.scale.quantile=function(){return Wi([],[])},Zo.scale.quantize=function(){return Ji(0,1,[0,1])},Zo.scale.threshold=function(){return Gi([.5],[0,1])},Zo.scale.identity=function(){return Ki([0,1])},Zo.svg={},Zo.svg.arc=function(){function n(){var n=t.apply(this,arguments),i=e.apply(this,arguments),o=r.apply(this,arguments)+ms,a=u.apply(this,arguments)+ms,c=(o>a&&(c=o,o=a,a=c),a-o),s=ba>c?"0":"1",l=Math.cos(o),f=Math.sin(o),h=Math.cos(a),g=Math.sin(a); +return c>=ys?n?"M0,"+i+"A"+i+","+i+" 0 1,1 0,"+-i+"A"+i+","+i+" 0 1,1 0,"+i+"M0,"+n+"A"+n+","+n+" 0 1,0 0,"+-n+"A"+n+","+n+" 0 1,0 0,"+n+"Z":"M0,"+i+"A"+i+","+i+" 0 1,1 0,"+-i+"A"+i+","+i+" 0 1,1 0,"+i+"Z":n?"M"+i*l+","+i*f+"A"+i+","+i+" 0 "+s+",1 "+i*h+","+i*g+"L"+n*h+","+n*g+"A"+n+","+n+" 0 "+s+",0 "+n*l+","+n*f+"Z":"M"+i*l+","+i*f+"A"+i+","+i+" 0 "+s+",1 "+i*h+","+i*g+"L0,0"+"Z"}var t=Qi,e=no,r=to,u=eo;return n.innerRadius=function(e){return arguments.length?(t=bt(e),n):t},n.outerRadius=function(t){return arguments.length?(e=bt(t),n):e},n.startAngle=function(t){return arguments.length?(r=bt(t),n):r},n.endAngle=function(t){return arguments.length?(u=bt(t),n):u},n.centroid=function(){var n=(t.apply(this,arguments)+e.apply(this,arguments))/2,i=(r.apply(this,arguments)+u.apply(this,arguments))/2+ms;return[Math.cos(i)*n,Math.sin(i)*n]},n};var ms=-Sa,ys=wa-ka;Zo.svg.line=function(){return ro(wt)};var xs=Zo.map({linear:uo,"linear-closed":io,step:oo,"step-before":ao,"step-after":co,basis:po,"basis-open":vo,"basis-closed":mo,bundle:yo,cardinal:fo,"cardinal-open":so,"cardinal-closed":lo,monotone:So});xs.forEach(function(n,t){t.key=n,t.closed=/-closed$/.test(n)});var Ms=[0,2/3,1/3,0],_s=[0,1/3,2/3,0],bs=[0,1/6,2/3,1/6];Zo.svg.line.radial=function(){var n=ro(ko);return n.radius=n.x,delete n.x,n.angle=n.y,delete n.y,n},ao.reverse=co,co.reverse=ao,Zo.svg.area=function(){return Eo(wt)},Zo.svg.area.radial=function(){var n=Eo(ko);return n.radius=n.x,delete n.x,n.innerRadius=n.x0,delete n.x0,n.outerRadius=n.x1,delete n.x1,n.angle=n.y,delete n.y,n.startAngle=n.y0,delete n.y0,n.endAngle=n.y1,delete n.y1,n},Zo.svg.chord=function(){function n(n,a){var c=t(this,i,n,a),s=t(this,o,n,a);return"M"+c.p0+r(c.r,c.p1,c.a1-c.a0)+(e(c,s)?u(c.r,c.p1,c.r,c.p0):u(c.r,c.p1,s.r,s.p0)+r(s.r,s.p1,s.a1-s.a0)+u(s.r,s.p1,c.r,c.p0))+"Z"}function t(n,t,e,r){var u=t.call(n,e,r),i=a.call(n,u,r),o=c.call(n,u,r)+ms,l=s.call(n,u,r)+ms;return{r:i,a0:o,a1:l,p0:[i*Math.cos(o),i*Math.sin(o)],p1:[i*Math.cos(l),i*Math.sin(l)]}}function e(n,t){return n.a0==t.a0&&n.a1==t.a1}function r(n,t,e){return"A"+n+","+n+" 0 "+ +(e>ba)+",1 "+t}function u(n,t,e,r){return"Q 0,0 "+r}var i=gr,o=pr,a=Ao,c=to,s=eo;return n.radius=function(t){return arguments.length?(a=bt(t),n):a},n.source=function(t){return arguments.length?(i=bt(t),n):i},n.target=function(t){return arguments.length?(o=bt(t),n):o},n.startAngle=function(t){return arguments.length?(c=bt(t),n):c},n.endAngle=function(t){return arguments.length?(s=bt(t),n):s},n},Zo.svg.diagonal=function(){function n(n,u){var i=t.call(this,n,u),o=e.call(this,n,u),a=(i.y+o.y)/2,c=[i,{x:i.x,y:a},{x:o.x,y:a},o];return c=c.map(r),"M"+c[0]+"C"+c[1]+" "+c[2]+" "+c[3]}var t=gr,e=pr,r=Co;return n.source=function(e){return arguments.length?(t=bt(e),n):t},n.target=function(t){return arguments.length?(e=bt(t),n):e},n.projection=function(t){return arguments.length?(r=t,n):r},n},Zo.svg.diagonal.radial=function(){var n=Zo.svg.diagonal(),t=Co,e=n.projection;return n.projection=function(n){return arguments.length?e(No(t=n)):t},n},Zo.svg.symbol=function(){function n(n,r){return(ws.get(t.call(this,n,r))||To)(e.call(this,n,r))}var t=Lo,e=zo;return n.type=function(e){return arguments.length?(t=bt(e),n):t},n.size=function(t){return arguments.length?(e=bt(t),n):e},n};var ws=Zo.map({circle:To,cross:function(n){var t=Math.sqrt(n/5)/2;return"M"+-3*t+","+-t+"H"+-t+"V"+-3*t+"H"+t+"V"+-t+"H"+3*t+"V"+t+"H"+t+"V"+3*t+"H"+-t+"V"+t+"H"+-3*t+"Z"},diamond:function(n){var t=Math.sqrt(n/(2*As)),e=t*As;return"M0,"+-t+"L"+e+",0"+" 0,"+t+" "+-e+",0"+"Z"},square:function(n){var t=Math.sqrt(n)/2;return"M"+-t+","+-t+"L"+t+","+-t+" "+t+","+t+" "+-t+","+t+"Z"},"triangle-down":function(n){var t=Math.sqrt(n/Es),e=t*Es/2;return"M0,"+e+"L"+t+","+-e+" "+-t+","+-e+"Z"},"triangle-up":function(n){var t=Math.sqrt(n/Es),e=t*Es/2;return"M0,"+-e+"L"+t+","+e+" "+-t+","+e+"Z"}});Zo.svg.symbolTypes=ws.keys();var Ss,ks,Es=Math.sqrt(3),As=Math.tan(30*Aa),Cs=[],Ns=0;Cs.call=pa.call,Cs.empty=pa.empty,Cs.node=pa.node,Cs.size=pa.size,Zo.transition=function(n){return arguments.length?Ss?n.transition():n:ma.transition()},Zo.transition.prototype=Cs,Cs.select=function(n){var t,e,r,u=this.id,i=[];n=b(n);for(var o=-1,a=this.length;++oi;i++){u.push(t=[]);for(var e=this[i],a=0,c=e.length;c>a;a++)(r=e[a])&&n.call(r,r.__data__,a,i)&&t.push(r)}return qo(u,this.id)},Cs.tween=function(n,t){var e=this.id;return arguments.length<2?this.node().__transition__[e].tween.get(n):P(this,null==t?function(t){t.__transition__[e].tween.remove(n)}:function(r){r.__transition__[e].tween.set(n,t)})},Cs.attr=function(n,t){function e(){this.removeAttribute(a)}function r(){this.removeAttributeNS(a.space,a.local)}function u(n){return null==n?e:(n+="",function(){var t,e=this.getAttribute(a);return e!==n&&(t=o(e,n),function(n){this.setAttribute(a,t(n))})})}function i(n){return null==n?r:(n+="",function(){var t,e=this.getAttributeNS(a.space,a.local);return e!==n&&(t=o(e,n),function(n){this.setAttributeNS(a.space,a.local,t(n))})})}if(arguments.length<2){for(t in n)this.attr(t,n[t]);return this}var o="transform"==n?Du:hu,a=Zo.ns.qualify(n);return Ro(this,"attr."+n,t,a.local?i:u)},Cs.attrTween=function(n,t){function e(n,e){var r=t.call(this,n,e,this.getAttribute(u));return r&&function(n){this.setAttribute(u,r(n))}}function r(n,e){var r=t.call(this,n,e,this.getAttributeNS(u.space,u.local));return r&&function(n){this.setAttributeNS(u.space,u.local,r(n))}}var u=Zo.ns.qualify(n);return this.tween("attr."+n,u.local?r:e)},Cs.style=function(n,t,e){function r(){this.style.removeProperty(n)}function u(t){return null==t?r:(t+="",function(){var r,u=Wo.getComputedStyle(this,null).getPropertyValue(n);return u!==t&&(r=hu(u,t),function(t){this.style.setProperty(n,r(t),e)})})}var i=arguments.length;if(3>i){if("string"!=typeof n){2>i&&(t="");for(e in n)this.style(e,n[e],t);return this}e=""}return Ro(this,"style."+n,t,u)},Cs.styleTween=function(n,t,e){function r(r,u){var i=t.call(this,r,u,Wo.getComputedStyle(this,null).getPropertyValue(n));return i&&function(t){this.style.setProperty(n,i(t),e)}}return arguments.length<3&&(e=""),this.tween("style."+n,r)},Cs.text=function(n){return Ro(this,"text",n,Do)},Cs.remove=function(){return this.each("end.transition",function(){var n;this.__transition__.count<2&&(n=this.parentNode)&&n.removeChild(this)})},Cs.ease=function(n){var t=this.id;return arguments.length<1?this.node().__transition__[t].ease:("function"!=typeof n&&(n=Zo.ease.apply(Zo,arguments)),P(this,function(e){e.__transition__[t].ease=n}))},Cs.delay=function(n){var t=this.id;return arguments.length<1?this.node().__transition__[t].delay:P(this,"function"==typeof n?function(e,r,u){e.__transition__[t].delay=+n.call(e,e.__data__,r,u)}:(n=+n,function(e){e.__transition__[t].delay=n}))},Cs.duration=function(n){var t=this.id;return arguments.length<1?this.node().__transition__[t].duration:P(this,"function"==typeof n?function(e,r,u){e.__transition__[t].duration=Math.max(1,n.call(e,e.__data__,r,u))}:(n=Math.max(1,n),function(e){e.__transition__[t].duration=n}))},Cs.each=function(n,t){var e=this.id;if(arguments.length<2){var r=ks,u=Ss;Ss=e,P(this,function(t,r,u){ks=t.__transition__[e],n.call(t,t.__data__,r,u)}),ks=r,Ss=u}else P(this,function(r){var u=r.__transition__[e];(u.event||(u.event=Zo.dispatch("start","end"))).on(n,t)});return this},Cs.transition=function(){for(var n,t,e,r,u=this.id,i=++Ns,o=[],a=0,c=this.length;c>a;a++){o.push(n=[]);for(var t=this[a],s=0,l=t.length;l>s;s++)(e=t[s])&&(r=Object.create(e.__transition__[u]),r.delay+=r.duration,Po(e,s,i,r)),n.push(e)}return qo(o,i)},Zo.svg.axis=function(){function n(n){n.each(function(){var n,s=Zo.select(this),l=this.__chart__||e,f=this.__chart__=e.copy(),h=null==c?f.ticks?f.ticks.apply(f,a):f.domain():c,g=null==t?f.tickFormat?f.tickFormat.apply(f,a):wt:t,p=s.selectAll(".tick").data(h,f),v=p.enter().insert("g",".domain").attr("class","tick").style("opacity",ka),d=Zo.transition(p.exit()).style("opacity",ka).remove(),m=Zo.transition(p.order()).style("opacity",1),y=Ti(f),x=s.selectAll(".domain").data([0]),M=(x.enter().append("path").attr("class","domain"),Zo.transition(x));v.append("line"),v.append("text");var _=v.select("line"),b=m.select("line"),w=p.select("text").text(g),S=v.select("text"),k=m.select("text");switch(r){case"bottom":n=Uo,_.attr("y2",u),S.attr("y",Math.max(u,0)+o),b.attr("x2",0).attr("y2",u),k.attr("x",0).attr("y",Math.max(u,0)+o),w.attr("dy",".71em").style("text-anchor","middle"),M.attr("d","M"+y[0]+","+i+"V0H"+y[1]+"V"+i);break;case"top":n=Uo,_.attr("y2",-u),S.attr("y",-(Math.max(u,0)+o)),b.attr("x2",0).attr("y2",-u),k.attr("x",0).attr("y",-(Math.max(u,0)+o)),w.attr("dy","0em").style("text-anchor","middle"),M.attr("d","M"+y[0]+","+-i+"V0H"+y[1]+"V"+-i);break;case"left":n=jo,_.attr("x2",-u),S.attr("x",-(Math.max(u,0)+o)),b.attr("x2",-u).attr("y2",0),k.attr("x",-(Math.max(u,0)+o)).attr("y",0),w.attr("dy",".32em").style("text-anchor","end"),M.attr("d","M"+-i+","+y[0]+"H0V"+y[1]+"H"+-i);break;case"right":n=jo,_.attr("x2",u),S.attr("x",Math.max(u,0)+o),b.attr("x2",u).attr("y2",0),k.attr("x",Math.max(u,0)+o).attr("y",0),w.attr("dy",".32em").style("text-anchor","start"),M.attr("d","M"+i+","+y[0]+"H0V"+y[1]+"H"+i)}if(f.rangeBand){var E=f,A=E.rangeBand()/2;l=f=function(n){return E(n)+A}}else l.rangeBand?l=f:d.call(n,f);v.call(n,l),m.call(n,f)})}var t,e=Zo.scale.linear(),r=zs,u=6,i=6,o=3,a=[10],c=null;return n.scale=function(t){return arguments.length?(e=t,n):e},n.orient=function(t){return arguments.length?(r=t in Ls?t+"":zs,n):r},n.ticks=function(){return arguments.length?(a=arguments,n):a},n.tickValues=function(t){return arguments.length?(c=t,n):c},n.tickFormat=function(e){return arguments.length?(t=e,n):t},n.tickSize=function(t){var e=arguments.length;return e?(u=+t,i=+arguments[e-1],n):u},n.innerTickSize=function(t){return arguments.length?(u=+t,n):u},n.outerTickSize=function(t){return arguments.length?(i=+t,n):i},n.tickPadding=function(t){return arguments.length?(o=+t,n):o},n.tickSubdivide=function(){return arguments.length&&n},n};var zs="bottom",Ls={top:1,right:1,bottom:1,left:1};Zo.svg.brush=function(){function n(i){i.each(function(){var i=Zo.select(this).style("pointer-events","all").style("-webkit-tap-highlight-color","rgba(0,0,0,0)").on("mousedown.brush",u).on("touchstart.brush",u),o=i.selectAll(".background").data([0]);o.enter().append("rect").attr("class","background").style("visibility","hidden").style("cursor","crosshair"),i.selectAll(".extent").data([0]).enter().append("rect").attr("class","extent").style("cursor","move");var a=i.selectAll(".resize").data(p,wt);a.exit().remove(),a.enter().append("g").attr("class",function(n){return"resize "+n}).style("cursor",function(n){return Ts[n]}).append("rect").attr("x",function(n){return/[ew]$/.test(n)?-3:null}).attr("y",function(n){return/^[ns]/.test(n)?-3:null}).attr("width",6).attr("height",6).style("visibility","hidden"),a.style("display",n.empty()?"none":null);var l,f=Zo.transition(i),h=Zo.transition(o);c&&(l=Ti(c),h.attr("x",l[0]).attr("width",l[1]-l[0]),e(f)),s&&(l=Ti(s),h.attr("y",l[0]).attr("height",l[1]-l[0]),r(f)),t(f)})}function t(n){n.selectAll(".resize").attr("transform",function(n){return"translate("+l[+/e$/.test(n)]+","+f[+/^s/.test(n)]+")"})}function e(n){n.select(".extent").attr("x",l[0]),n.selectAll(".extent,.n>rect,.s>rect").attr("width",l[1]-l[0])}function r(n){n.select(".extent").attr("y",f[0]),n.selectAll(".extent,.e>rect,.w>rect").attr("height",f[1]-f[0])}function u(){function u(){32==Zo.event.keyCode&&(C||(x=null,z[0]-=l[1],z[1]-=f[1],C=2),y())}function p(){32==Zo.event.keyCode&&2==C&&(z[0]+=l[1],z[1]+=f[1],C=0,y())}function v(){var n=Zo.mouse(_),u=!1;M&&(n[0]+=M[0],n[1]+=M[1]),C||(Zo.event.altKey?(x||(x=[(l[0]+l[1])/2,(f[0]+f[1])/2]),z[0]=l[+(n[0]p?(u=r,r=p):u=p),v[0]!=r||v[1]!=u?(e?o=null:i=null,v[0]=r,v[1]=u,!0):void 0}function m(){v(),S.style("pointer-events","all").selectAll(".resize").style("display",n.empty()?"none":null),Zo.select("body").style("cursor",null),L.on("mousemove.brush",null).on("mouseup.brush",null).on("touchmove.brush",null).on("touchend.brush",null).on("keydown.brush",null).on("keyup.brush",null),N(),w({type:"brushend"})}var x,M,_=this,b=Zo.select(Zo.event.target),w=a.of(_,arguments),S=Zo.select(_),k=b.datum(),E=!/^(n|s)$/.test(k)&&c,A=!/^(e|w)$/.test(k)&&s,C=b.classed("extent"),N=I(),z=Zo.mouse(_),L=Zo.select(Wo).on("keydown.brush",u).on("keyup.brush",p);if(Zo.event.changedTouches?L.on("touchmove.brush",v).on("touchend.brush",m):L.on("mousemove.brush",v).on("mouseup.brush",m),S.interrupt().selectAll("*").interrupt(),C)z[0]=l[0]-z[0],z[1]=f[0]-z[1];else if(k){var T=+/w$/.test(k),q=+/^n/.test(k);M=[l[1-T]-z[0],f[1-q]-z[1]],z[0]=l[T],z[1]=f[q]}else Zo.event.altKey&&(x=z.slice());S.style("pointer-events","none").selectAll(".resize").style("display",null),Zo.select("body").style("cursor",b.style("cursor")),w({type:"brushstart"}),v()}var i,o,a=M(n,"brushstart","brush","brushend"),c=null,s=null,l=[0,0],f=[0,0],h=!0,g=!0,p=qs[0];return n.event=function(n){n.each(function(){var n=a.of(this,arguments),t={x:l,y:f,i:i,j:o},e=this.__chart__||t;this.__chart__=t,Ss?Zo.select(this).transition().each("start.brush",function(){i=e.i,o=e.j,l=e.x,f=e.y,n({type:"brushstart"})}).tween("brush:brush",function(){var e=gu(l,t.x),r=gu(f,t.y);return i=o=null,function(u){l=t.x=e(u),f=t.y=r(u),n({type:"brush",mode:"resize"})}}).each("end.brush",function(){i=t.i,o=t.j,n({type:"brush",mode:"resize"}),n({type:"brushend"})}):(n({type:"brushstart"}),n({type:"brush",mode:"resize"}),n({type:"brushend"}))})},n.x=function(t){return arguments.length?(c=t,p=qs[!c<<1|!s],n):c},n.y=function(t){return arguments.length?(s=t,p=qs[!c<<1|!s],n):s},n.clamp=function(t){return arguments.length?(c&&s?(h=!!t[0],g=!!t[1]):c?h=!!t:s&&(g=!!t),n):c&&s?[h,g]:c?h:s?g:null},n.extent=function(t){var e,r,u,a,h;return arguments.length?(c&&(e=t[0],r=t[1],s&&(e=e[0],r=r[0]),i=[e,r],c.invert&&(e=c(e),r=c(r)),e>r&&(h=e,e=r,r=h),(e!=l[0]||r!=l[1])&&(l=[e,r])),s&&(u=t[0],a=t[1],c&&(u=u[1],a=a[1]),o=[u,a],s.invert&&(u=s(u),a=s(a)),u>a&&(h=u,u=a,a=h),(u!=f[0]||a!=f[1])&&(f=[u,a])),n):(c&&(i?(e=i[0],r=i[1]):(e=l[0],r=l[1],c.invert&&(e=c.invert(e),r=c.invert(r)),e>r&&(h=e,e=r,r=h))),s&&(o?(u=o[0],a=o[1]):(u=f[0],a=f[1],s.invert&&(u=s.invert(u),a=s.invert(a)),u>a&&(h=u,u=a,a=h))),c&&s?[[e,u],[r,a]]:c?[e,r]:s&&[u,a])},n.clear=function(){return n.empty()||(l=[0,0],f=[0,0],i=o=null),n},n.empty=function(){return!!c&&l[0]==l[1]||!!s&&f[0]==f[1]},Zo.rebind(n,a,"on")};var Ts={n:"ns-resize",e:"ew-resize",s:"ns-resize",w:"ew-resize",nw:"nwse-resize",ne:"nesw-resize",se:"nwse-resize",sw:"nesw-resize"},qs=[["n","e","s","w","nw","ne","se","sw"],["e","w"],["n","s"],[]],Rs=Qa.format=ic.timeFormat,Ds=Rs.utc,Ps=Ds("%Y-%m-%dT%H:%M:%S.%LZ");Rs.iso=Date.prototype.toISOString&&+new Date("2000-01-01T00:00:00.000Z")?Ho:Ps,Ho.parse=function(n){var t=new Date(n);return isNaN(t)?null:t},Ho.toString=Ps.toString,Qa.second=Dt(function(n){return new nc(1e3*Math.floor(n/1e3))},function(n,t){n.setTime(n.getTime()+1e3*Math.floor(t))},function(n){return n.getSeconds()}),Qa.seconds=Qa.second.range,Qa.seconds.utc=Qa.second.utc.range,Qa.minute=Dt(function(n){return new nc(6e4*Math.floor(n/6e4))},function(n,t){n.setTime(n.getTime()+6e4*Math.floor(t))},function(n){return n.getMinutes()}),Qa.minutes=Qa.minute.range,Qa.minutes.utc=Qa.minute.utc.range,Qa.hour=Dt(function(n){var t=n.getTimezoneOffset()/60;return new nc(36e5*(Math.floor(n/36e5-t)+t))},function(n,t){n.setTime(n.getTime()+36e5*Math.floor(t))},function(n){return n.getHours()}),Qa.hours=Qa.hour.range,Qa.hours.utc=Qa.hour.utc.range,Qa.month=Dt(function(n){return n=Qa.day(n),n.setDate(1),n},function(n,t){n.setMonth(n.getMonth()+t)},function(n){return n.getMonth()}),Qa.months=Qa.month.range,Qa.months.utc=Qa.month.utc.range;var Us=[1e3,5e3,15e3,3e4,6e4,3e5,9e5,18e5,36e5,108e5,216e5,432e5,864e5,1728e5,6048e5,2592e6,7776e6,31536e6],js=[[Qa.second,1],[Qa.second,5],[Qa.second,15],[Qa.second,30],[Qa.minute,1],[Qa.minute,5],[Qa.minute,15],[Qa.minute,30],[Qa.hour,1],[Qa.hour,3],[Qa.hour,6],[Qa.hour,12],[Qa.day,1],[Qa.day,2],[Qa.week,1],[Qa.month,1],[Qa.month,3],[Qa.year,1]],Hs=Rs.multi([[".%L",function(n){return n.getMilliseconds()}],[":%S",function(n){return n.getSeconds()}],["%I:%M",function(n){return n.getMinutes()}],["%I %p",function(n){return n.getHours()}],["%a %d",function(n){return n.getDay()&&1!=n.getDate()}],["%b %d",function(n){return 1!=n.getDate()}],["%B",function(n){return n.getMonth()}],["%Y",we]]),Fs={range:function(n,t,e){return Zo.range(Math.ceil(n/e)*e,+t,e).map(Oo)},floor:wt,ceil:wt};js.year=Qa.year,Qa.scale=function(){return Fo(Zo.scale.linear(),js,Hs)};var Os=js.map(function(n){return[n[0].utc,n[1]]}),Ys=Ds.multi([[".%L",function(n){return n.getUTCMilliseconds()}],[":%S",function(n){return n.getUTCSeconds()}],["%I:%M",function(n){return n.getUTCMinutes()}],["%I %p",function(n){return n.getUTCHours()}],["%a %d",function(n){return n.getUTCDay()&&1!=n.getUTCDate()}],["%b %d",function(n){return 1!=n.getUTCDate()}],["%B",function(n){return n.getUTCMonth()}],["%Y",we]]);Os.year=Qa.year.utc,Qa.scale.utc=function(){return Fo(Zo.scale.linear(),Os,Ys)},Zo.text=St(function(n){return n.responseText}),Zo.json=function(n,t){return kt(n,"application/json",Yo,t)},Zo.html=function(n,t){return kt(n,"text/html",Io,t)},Zo.xml=St(function(n){return n.responseXML}),"function"==typeof define&&define.amd?define(Zo):"object"==typeof module&&module.exports&&(module.exports=Zo),this.d3=Zo}(); \ No newline at end of file diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.geo-devices/public/js/firstTemp.js b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.geo-devices/public/js/firstTemp.js new file mode 100644 index 0000000000..73f567fe0a --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.geo-devices/public/js/firstTemp.js @@ -0,0 +1,8 @@ +$(function() { + $("#timeFromCal").datepicker({ + orientation: 'top' + }); + $("#timeToCal").datepicker({ + orientation: 'top' + }); +}); diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.geo-devices/public/js/geo_exit_fence.js b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.geo-devices/public/js/geo_exit_fence.js new file mode 100644 index 0000000000..6337711d90 --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.geo-devices/public/js/geo_exit_fence.js @@ -0,0 +1,50 @@ +/* + * 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. + */ + +function initializeExit() { + $(".removeGeoFence").tooltip(); + $("#exit-alert > tbody").empty(); + var serverUrl = "/api/device-mgt/v1.0/geo-services/alerts/Exit"; + invokerUtil.get(serverUrl, function (response) { + if (response == "[]") { + $(".fence-not-exist").show(); + $("#exit-alert").hide(); + } + else if (response) { + $(".fence-not-exist").hide(); + $("#exit-alert").show(); + response = JSON.parse(response); + for (var index in response) { + var alertBean = response[index]; + $("#exit-alert > tbody").append( + "" + alertBean.areaName + "" + + "" + alertBean.queryName + "" + formatDate(new Date(alertBean.createdTime)) + "" + + ""); + } + } else { + $(".fence-not-exist").show(); + $("#exit-alert").hide(); + } + $('.viewGeoFenceRow td:not(:last-child)').click(function () { + viewFence(this.parentElement,'Exit'); + }); + }); +} +initializeExit(); \ No newline at end of file diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.geo-devices/public/js/geo_fencing.js b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.geo-devices/public/js/geo_fencing.js new file mode 100644 index 0000000000..233b0e80d2 --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.geo-devices/public/js/geo_fencing.js @@ -0,0 +1,580 @@ +/* + * 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. + */ + +var drawControl; +var speedGraphControl; +var removeAllControl; +var drawnItems; +var lastId; +var controlDiv; +var deleteLayers; +var deleteLayersCount; + +loadGeoFencing(); + +function loadGeoFencing() { + if (map == null) { + setTimeout(loadGeoFencing, 1000); // give everything some time to render + } else { + map.on('draw:created', function (e) { + var type = e.layerType, layer = e.layer; + drawnItems.addLayer(layer); + console.log("created layer for "+ lastId); + createPopup(layer,lastId); + }); + } +} + +function openTools(id) { + lastId = id; + if (drawControl) { + try{ + map.removeControl(drawControl); + } catch(e) { + console.log("error: " + e.message); + } + console.log("removed drawControl"); + } + if (removeAllControl) { + try { + map.removeControl(removeAllControl); + } catch(e) { + console.log("error: " + e.message); + } + console.log("removed removeAllControl"); + } + if (drawnItems) { + try{ + map.removeLayer(drawnItems); + console.log("removing layer"); + } catch(e) { + console.log("error: " + e.message); + } + console.log("removed drawnItems"); + } + + closeAll(); + noty({text: "Please draw the required area on the map", type: "information"}); + + L.Control.RemoveAll = L.Control.extend( + { + options: { + position: 'topleft' + }, + onAdd: function (map) { + controlDiv = L.DomUtil.create('div', 'leaflet-draw-toolbar leaflet-bar'); + L.DomEvent + .addListener(controlDiv, 'click', L.DomEvent.stopPropagation) + .addListener(controlDiv, 'click', L.DomEvent.preventDefault) + .addListener(controlDiv, 'click', function () { + controlDiv.remove(); + drawControl.removeFrom(map); + drawnItems.clearLayers(); + if(id == "Prediction"){ + $('#predictionResults').animate({width: ['toggle','swing']},200); + toggeled = false; + } + }); + + var controlUI = L.DomUtil.create('a', 'fa fa-times fa-lg drawControlCloseButton', controlDiv); + $(controlUI).css("background-image", "none"); // Remove default control icon + // TODO: bad usage of .hover() use CSS instead + $(controlUI).mouseenter(function () { + $(this).css("color", "red"); + }).mouseleave(function () { + $(this).css("color", "black") + }); + + controlUI.title = 'Close drawer tools'; + controlUI.href = '#'; + return controlDiv; + } + }); + removeAllControl = new L.Control.RemoveAll(); + map.addControl(removeAllControl); + + // Initialise the FeatureGroup to store editable layers + drawnItems = new L.FeatureGroup(); + map.addLayer(drawnItems); + + if (id=="WithIn") { + // Initialise the draw control and pass it the FeatureGroup of editable layers + drawControl = new L.Control.Draw({ + draw: { + polygon: { + allowIntersection: false, // Restricts shapes to simple polygons + drawError: { + color: '#002bff', // Color the shape will turn when intersects + message: 'Oh snap! you can\'t draw that!' // Message that will show when intersect + }, + shapeOptions: { + color: '#002bff' + } + }, + rectangle: { + shapeOptions: { + color: '#002bff' + } + }, + polyline: false, + circle: false, // Turns off this drawing tool + marker: false // Markers are not applicable for within geo fencing + }, + edit: { + featureGroup: drawnItems + } + }); + } else if (id=="Exit") { + // Initialise the draw control and pass it the FeatureGroup of editable layers + drawControl = new L.Control.Draw({ + draw: { + polygon: { + allowIntersection: false, // Restricts shapes to simple polygons + drawError: { + color: '#ff0043', // Color the shape will turn when intersects + message: 'Oh snap! you can\'t draw that!' // Message that will show when intersect + }, + shapeOptions: { + color: '#ff0043' + } + }, + rectangle: { + shapeOptions: { + color: '#ff0043' + } + }, + polyline: false, + circle: false, // Turns off this drawing tool + marker: false // Markers are not applicable for within geo fencing + }, + edit: { + featureGroup: drawnItems + } + }); + } else if(id=="Stationery"){ + // Initialise the draw control and pass it the FeatureGroup of editable layers + drawControl = new L.Control.Draw({ + draw: { + polygon: { + allowIntersection: false, // Restricts shapes to simple polygons + drawError: { + color: '#e1e100', // Color the shape will turn when intersects + message: 'Oh snap! you can\'t draw that!' // Message that will show when intersect + }, + shapeOptions: { + color: '#e1e100' + } + }, + rectangle: { + shapeOptions: { + color: '#e1e100' + } + }, + polyline: false, + circle: { + shapeOptions: { + color: '#e1e100' + } + }, + marker: false // Markers are not applicable for within geo fencing + }, + edit: { + featureGroup: drawnItems + } + }); + } else if (id=="Traffic") { + // Initialise the draw control and pass it the FeatureGroup of editable layers + drawControl = new L.Control.Draw({ + draw: { + polygon: { + allowIntersection: false, // Restricts shapes to simple polygons + drawError: { + color: '#e1e100', // Color the shape will turn when intersects + message: 'Oh snap! you can\'t draw that!' // Message that will show when intersect + }, + shapeOptions: { + color: '#ff0043' + } + }, + rectangle: { + shapeOptions: { + color: '#002bff' + } + }, + polyline: false, + circle: { + shapeOptions: { + color: '#ff0043' + } + }, + marker: { + shapeOptions: { + color: '#ff0043' + } + } + }, + edit: { + featureGroup: drawnItems + } + }); + } else if (id =="Prediction") { + drawControl = new L.Control.Draw({ + draw: { + polygon: false, + rectangle: false, + polyline: false, + circle: false, + marker: { + shapeOptions: { + color: '#ff0043' + } + } + }, + edit: { + featureGroup: drawnItems + } + }); + console.log("prediction tool opened"); + } + map.addControl(drawControl); + map.on('draw:created', function (e) { + var type = e.layerType, layer = e.layer; + drawnItems.addLayer(layer); + console.log("created layer for "+ lastId); + createPopup(layer,lastId); + }); +} + +function createPopup(layer,id) { + if (id=="WithIn") { + var popupTemplate = $('#setWithinAlert'); + popupTemplate.find('#addWithinAlert').attr('leaflet_id', layer._leaflet_id); + } else if (id=="Exit") { + var popupTemplate = $('#setExitAlert'); + popupTemplate.find('#addExitAlert').attr('leaflet_id', layer._leaflet_id); + } else if (id=="Stationery") { + var popupTemplate = $('#setStationeryAlert'); + popupTemplate.find('#addStationeryAlert').attr('leaflet_id', layer._leaflet_id); + } else if (id=="Traffic") { + var popupTemplate = $('#setTrafficAlert'); + popupTemplate.find('#addTrafficAlert').attr('leaflet_id', layer._leaflet_id); + //console.log(">>got here " + id + " " + popupTemplate.find('#addTrafficAlert') + " " + layer._leaflet_id); + } else if (id=="Prediction") { + getPrediction(layer._leaflet_id); + return; + } + + popupTemplate.find('.exportGeoJson').attr('leaflet_id', layer._leaflet_id); + popupTemplate.find('.editGeoJson').attr('leaflet_id', layer._leaflet_id); + + layer.bindPopup(popupTemplate.html(), {closeOnClick: false, closeButton: false}).openPopup(); + // transparent the layer .leaflet-popup-content-wrapper + $(layer._popup._container.childNodes[0]).css("background", "rgba(255,255,255,0.8)"); +} + +function toggleSpeedGraph() { + if (speedGraphControl) { + try { + map.removeControl(speedGraphControl); + speedGraphControl = null; + } catch (e) { + console.log("error: " + e.message); + } + } else { + speedGraphControl = new L.control.speedChart({'position' : 'topright'}); + map.addControl(speedGraphControl); + } +} + +function closeTools(leafletId) { + map.removeLayer(map._layers[leafletId]); + map.removeControl(drawControl); + controlDiv.remove(); + console.log("DEBUG: closeTools(leafletId) = "+leafletId); +} + +/* Export selected area on the map as a json encoded geoJson standard file, no back-end calls simple HTML5 trick ;) */ +function exportToGeoJSON(element, content) { + // HTML5 features has been used here + var geoJsonData = 'data:application/json;charset=utf-8,' + encodeURIComponent(content); + // TODO: replace closest() by using persistence id for templates, template id prefixed by unique id(i.e leaflet_id) + var fileName = $(element).closest('form').attr('area-name') || 'geoJson'; + var link = document.createElement("a"); + link.download = fileName + '.json'; // Use the fence name given by the user as the file name of the JSON file; + link.href = geoJsonData; + document.body.appendChild(link); + link.click(); + document.body.removeChild(link); + delete link; +} + +$(function () { + $("#importGeoJsonFile").change(function () { + var importedFile = this.files[0]; + var reader = new FileReader(); + reader.readAsText(importedFile); + reader.onload = function (e) { + $("#enterGeoJson").text(e.target.result.toString()); + }; + }); +}); +function importGeoJson() { + var updatedGeoJson; + updatedGeoJson = $('#enterGeoJson').val(); + updateDrawing(updatedGeoJson); +} + +function updateDrawing(updatedGeoJson) { + updatedGeoJson = JSON.parse(updatedGeoJson); + // Pop the last LatLng pair because according to the geoJSON standard it use complete round LatLng set to store polygon coordinates + updatedGeoJson.geometry.coordinates[0].pop(); + var leafletLatLngs = []; + $.each(updatedGeoJson.geometry.coordinates[0], function (idx, pItem) { + leafletLatLngs.push({lat: pItem[1], lng: pItem[0]}); + }); + var polygon = new L.Polygon(leafletLatLngs); + polygon.editing.enable(); + map.addLayer(polygon); + createPopup(polygon); + closeAll(); +} + +var prevLayers = []; +function clearPrevLayers() { + for(var i =0; i < prevLayers.length; i++) { + var prevLayer = prevLayers[i]; + map.removeLayer(prevLayer); + } + prevLayers.length = 0; +} + +function viewFence(geoFenceElement,id) { + if (deleteLayers && !deleteLayersCount) { + clearPrevLayers(); + deleteLayersCount = true; + deleteLayers = false; + } + var geoJson = $(geoFenceElement).attr('data-geoJson'); + var matchResults = /(?:"geoFenceGeoJSON"):"{(.*)}"/g.exec(geoJson); + if (matchResults && matchResults.length > 1) { + geoJson = "{" + matchResults[1] + "}"; + } + geoJson = JSON.parse(geoJson.replace(/'/g, '"')); + var queryName = $(geoFenceElement).attr('data-queryName'); + var areaName = $(geoFenceElement).attr('data-areaName'); + var geometryShape; + var circleOptions = {color: null}; + var polygonOptions = {color: null}; + + if (id == "Exit") { + circleOptions.color = '#ff0043'; + polygonOptions.color = '#ff0043'; + } else if (id == "WithIn") { + circleOptions.color = '#002bff'; + polygonOptions.color = '#002bff'; + } else { + circleOptions.color = '#e1e100'; + polygonOptions.color = '#e1e100'; + } + + if (geoJson.type=="Point") { + geometryShape= new L.circle([geoJson.coordinates[1],geoJson.coordinates[0]], geoJson.radius,circleOptions); + map.addLayer(geometryShape); + prevLayers.push(geometryShape); + } else if (geoJson.type=="Polygon") { + geoJson.coordinates[0].pop(); // popout the last coordinate set(lat,lng pair) due to circular chain + var leafletLatLngs = []; + $.each(geoJson.coordinates[0], function (idx, pItem) { + leafletLatLngs.push({lat: pItem[1], lng: pItem[0]}); + }); + geometryShape = new L.Polygon(leafletLatLngs,polygonOptions); + map.addLayer(geometryShape); + prevLayers.push(geometryShape); + } + + var geoPublicUri = $("#geo-charts").data("geo-public-uri"); + + if (id=="Stationery") { + + var stationeryTime=$(geoFenceElement).attr('data-stationeryTime'); + $('#templateLoader').load(geoPublicUri + "/assets/html_templates/view_fence_popup.html #viewStationeryAlert", function () { + var popupTemplate = $('#templateLoader').find('#viewStationeryAlert'); + popupTemplate.find('#exportGeoJson').attr('leaflet_id', geometryShape._leaflet_id); + popupTemplate.find('#hideViewFence').attr('leaflet_id', geometryShape._leaflet_id); + popupTemplate.find('#viewAreaName').html(areaName); + popupTemplate.find('#stationaryAlertForm').attr('area-name', areaName); + popupTemplate.find('#stationaryAlertForm').attr('query-name', queryName); + popupTemplate.find('#viewAreaTime').html(stationeryTime); + geometryShape.bindPopup(popupTemplate.html(), {closeButton: true}).openPopup(); + // transparent the layer .leaflet-popup-content-wrapper + $(geometryShape._popup._container.childNodes[0]).css("background", "rgba(255,255,255,0.8)"); + + }); + } else if (id=="WithIn") { + + $('#templateLoader').load(geoPublicUri + "/assets/html_templates/view_fence_popup.html #viewWithinAlert", function () { + var popupTemplate = $('#templateLoader').find('#viewWithinAlert'); + popupTemplate.find('#exportGeoJson').attr('leaflet_id', geometryShape._leaflet_id); + popupTemplate.find('#hideViewFence').attr('leaflet_id', geometryShape._leaflet_id); + popupTemplate.find('#viewAreaName').html(areaName); + popupTemplate.find('#withinAlertForm').attr('area-name', areaName); + popupTemplate.find('#withinAlertForm').attr('query-name', queryName); + geometryShape.bindPopup(popupTemplate.html(), {closeButton: true}).openPopup(); + // transparent the layer .leaflet-popup-content-wrapper + $(geometryShape._popup._container.childNodes[0]).css("background", "rgba(255,255,255,0.8)"); + }); + } else if (id=="Exit") { + + $('#templateLoader').load(geoPublicUri + "/assets/html_templates/view_fence_popup.html #viewExitAlert", function () { + var popupTemplate = $('#templateLoader').find('#viewExitAlert'); + popupTemplate.find('#exportGeoJson').attr('leaflet_id', geometryShape._leaflet_id); + popupTemplate.find('#hideViewFence').attr('leaflet_id', geometryShape._leaflet_id); + popupTemplate.find('#viewAreaName').html(areaName); + popupTemplate.find('#exitAlertForm').attr('area-name', areaName); + popupTemplate.find('#exitAlertForm').attr('query-name', queryName); + geometryShape.bindPopup(popupTemplate.html(), {closeButton: true}).openPopup(); + // transparent the layer .leaflet-popup-content-wrapper + $(geometryShape._popup._container.childNodes[0]).css("background", "rgba(255,255,255,0.8)"); + }); + } + closeAll(); +} + +// view all defined fence areas of a particular alert type +function viewAll(id) { + deleteLayers = true; + deleteLayersCount = false; + + var table = null; + if (id == "Exit") { + table = $("#exit-alert > tbody"); + } else if (id == "WithIn") { + table = $("#within-alert > tbody"); + } else { + table = $("#stationary-alert-table > tbody"); + } + + table.find('tr').each(function (i, el) { + viewFence(this,id); + }); +} + +// View all defined fence areas of all alert types +function viewAllFences() { + deleteLayers = true; + deleteLayersCount = false; + initializeExit(); + initializeWithin(); + initStationaryAlert(); + initializeSpeed(); + + var table = $("#exit-alert > tbody"); + table.find('tr').each(function (i, el) { + viewFence(this,'Exit'); + }); + table = $("#within-alert > tbody"); + table.find('tr').each(function (i, el) { + viewFence(this,'WithIn'); + }); + table = $("#stationary-alert-table > tbody"); + table.find('tr').each(function (i, el) { + viewFence(this,'Stationery'); + }); +} + +function viewFenceByData(geoJson, queryName, areaName, stationeryTime, id) { + var matchResults = /(?:"geoFenceGeoJSON"):"{(.*)}"/g.exec(geoJson); + if (matchResults && matchResults.length > 1) { + geoJson = "{" + matchResults[1] + "}"; + } + geoJson = JSON.parse(geoJson.replace(/'/g, '"')); + var geometryShape; + + var circleOptions = {color: null}; + var polygonOptions = {color: null}; + + if (id == "Exit") { + circleOptions.color = '#ff0043'; + polygonOptions.color = '#ff0043'; + } else if (id == "WithIn") { + circleOptions.color = '#002bff'; + polygonOptions.color = '#002bff'; + } else { + circleOptions.color = '#e1e100'; + polygonOptions.color = '#e1e100'; + } + + if (geoJson.type=="Point") { + + geometryShape= new L.circle([geoJson.coordinates[1],geoJson.coordinates[0]], geoJson.radius,circleOptions); + // var marker=new L.marker([geoJson.coordinates[1],geoJson.coordinates[0]]); + map.addLayer(geometryShape); + // map.addLayer(marker); + } else if (geoJson.type=="Polygon") { + geoJson.coordinates[0].pop(); // popout the last coordinate set(lat,lng pair) due to circular chain + var leafletLatLngs = []; + $.each(geoJson.coordinates[0], function (idx, pItem) { + leafletLatLngs.push({lat: pItem[1], lng: pItem[0]}); + }); + geometryShape = new L.Polygon(leafletLatLngs,polygonOptions); + map.addLayer(geometryShape); + } + + var geoPublicUri = $("#geo-charts").data("geo-public-uri"); + + if (id=="Stationery") { + + $('#templateLoader').load(geoPublicUri + "/assets/html_templates/view_fence_popup.html #viewStationeryAlert", function () { + var popupTemplate = $('#templateLoader').find('#viewStationeryAlert'); + popupTemplate.find('#exportGeoJson').attr('leaflet_id', geometryShape._leaflet_id); + popupTemplate.find('#hideViewFence').attr('leaflet_id', geometryShape._leaflet_id); + popupTemplate.find('#viewAreaTime').html(stationeryTime); + geometryShape.bindPopup(popupTemplate.html(), {closeButton: true}).openPopup(); + // transparent the layer .leaflet-popup-content-wrapper + $(geometryShape._popup._container.childNodes[0]).css("background", "rgba(255,255,255,0.8)"); + + }); + } else if (id=="WithIn") { + + $('#templateLoader').load(geoPublicUri + "/assets/html_templates/view_fence_popup.html #viewWithinAlert", function () { + var popupTemplate = $('#templateLoader').find('#viewWithinAlert'); + popupTemplate.find('#exportGeoJson').attr('leaflet_id', geometryShape._leaflet_id); + popupTemplate.find('#hideViewFence').attr('leaflet_id', geometryShape._leaflet_id); + popupTemplate.find('#viewAreaName').html(areaName); + popupTemplate.find('#withinAlertForm').attr('area-name', areaName); + popupTemplate.find('#withinAlertForm').attr('query-name', queryName); + geometryShape.bindPopup(popupTemplate.html(), {closeButton: true}).openPopup(); + // transparent the layer .leaflet-popup-content-wrapper + $(geometryShape._popup._container.childNodes[0]).css("background", "rgba(255,255,255,0.8)"); + }); + } else if (id=="Exit") { + + $('#templateLoader').load(geoPublicUri + "/assets/html_templates/view_fence_popup.html #viewExitAlert", function () { + var popupTemplate = $('#templateLoader').find('#viewExitAlert'); + popupTemplate.find('#exportGeoJson').attr('leaflet_id', geometryShape._leaflet_id); + popupTemplate.find('#hideViewFence').attr('leaflet_id', geometryShape._leaflet_id); + popupTemplate.find('#viewAreaName').html(areaName); + popupTemplate.find('#exitAlertForm').attr('area-name', areaName); + popupTemplate.find('#exitAlertForm').attr('query-name', queryName); + geometryShape.bindPopup(popupTemplate.html(), {closeButton: true}).openPopup(); + // transparent the layer .leaflet-popup-content-wrapper + $(geometryShape._popup._container.childNodes[0]).css("background", "rgba(255,255,255,0.8)"); + }); + } + closeAll(); +} \ No newline at end of file diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.geo-devices/public/js/geo_proximity.js b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.geo-devices/public/js/geo_proximity.js new file mode 100644 index 0000000000..b47a97fc0c --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.geo-devices/public/js/geo_proximity.js @@ -0,0 +1,90 @@ +/* + * 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. + */ + +var centerLocation = new L.LatLng(6.999833130825296, 79.99855044297874); +var resizeIconLocation = new L.LatLng(6.99847, 80.14412); +var proximityMap = L.map("proximityMap", { + zoom: 10, + center: centerLocation, + zoomControl: false, + attributionControl: false, + maxZoom: 20 + }); +var proximityDistance = $("#proximityDistance"); +//TODO invoker-util +var serverUrl = "/api/device-mgt/v1.0/geo-services/alerts/Proximity"; +// var serverUrl = "/portal/store/carbon.super/fs/gadget/geo-dashboard/controllers/get_alerts.jag?executionPlanType=Proximity&deviceId=" + deviceId; +invokerUtil.get(serverUrl, function (response) { + response = JSON.parse(response); + proximityDistance.val(response.proximityDistance); + $("#proximityTime").val(response.proximityTime); +}); + +L.grid({ + redraw: 'move' + }).addTo(proximityMap); + +proximityMap.scrollWheelZoom.disable(); + +var marker = L.marker(centerLocation).setIcon(normalMovingIcon); + +marker.addTo(proximityMap); + +var resizeIcon = L.icon({ + iconUrl: ApplicationOptions.leaflet.iconUrls.resizeIcon, + iconAnchor: [24, 24] +}); + +var resizeMarker = L.marker(resizeIconLocation, {icon: resizeIcon, draggable: 'true'}).addTo(proximityMap); +resizeMarker.on('drag', updateRuler); + +var measureLine = new L.Polyline( + [centerLocation, resizeIconLocation ], + { color: "black", opacity: 0.5, stroke: true }); + + +proximityMap.addLayer(measureLine); +measureLine._path.setAttribute("class", 'measuring-line-for-look'); + +var options = { + minWidth: 50, + autoPan: false, + closeButton: true, // should the popups have a close option? + displayTotalDistance: true, + displayPartialDistance: false, + className: 'measuring-label-tooltip' /*css label class name*/ +}; +// var totalDistancePopup = new L.Popup(options,measureLine); +var initialDistance = centerLocation.distanceTo(resizeIconLocation); + +var measureCircle = L.circle(centerLocation, initialDistance).addTo(proximityMap); + +function updateRuler(e) { + var target = e.target; + resizeIconLocation = target.getLatLng(); + measureLine.setLatLngs([centerLocation, resizeIconLocation]); + setDistancePopup(centerLocation, resizeIconLocation) +} + +function setDistancePopup(startLatLng, endLatLng) { + var centerPos = new L.LatLng((startLatLng.lat + endLatLng.lat) / 2, + (startLatLng.lng + endLatLng.lng) / 2), + distance = startLatLng.distanceTo(endLatLng); + proximityDistance.val(distance.toFixed(2)); + measureCircle.setRadius(distance); +} diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.geo-devices/public/js/geo_remote.js b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.geo-devices/public/js/geo_remote.js index 4b65d266d6..bddac4133a 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.geo-devices/public/js/geo_remote.js +++ b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.geo-devices/public/js/geo_remote.js @@ -91,8 +91,560 @@ function getTileServers() { }); } +function addWmsEndPoint() { + serviceName = $('#serviceName').val(); + layers = $('#layers').val(); + wmsVersion = $('#wmsVersion').val(); + serviceEndPoint = $('#serviceEndPoint').val(); + outputFormat = $('#outputFormat').val(); + var validated = false; + + if (serviceName === undefined || serviceName == "" || serviceName == null) { + var message = "Service Provider name cannot be empty."; + noty({text: '' + message + '', type: 'error'}); + } + + /* if(layers === undefined || layers == "" || layers == null){ + layers = ""; + } + + + + if(wmsVersion === undefined || wmsVersion == "" || wmsVersion == null){ + wmsVersion = ""; + } + + + if(outputFormat === undefined || outputFormat == "" || outputFormat == null){ + outputFormat = "image/png"; + }*/ + + if (validated) { + wmsLayer = L.tileLayer.wms(serviceEndPoint, { + layers: layers.split(','), + format: outputFormat ? outputFormat : 'image/png', + version: wmsVersion, + transparent: true, + opacity: 0.4 + }); + + layerControl.addOverlay(wmsLayer, serviceName, "Web Map Service layers"); + map.addLayer(wmsLayer); + + /*var temperature = L.tileLayer.wms('http://gis.srh.noaa.gov/arcgis/services/NDFDTemps/MapServer/WMSServer', { + format: 'img/png', + transparent: true, + layers: 16 + }); + + layerControl.addOverlay(temperature, "testWms", "Web Map Service layers"); + map.addLayer(temperature);*/ + + var data = { + 'serviceName': serviceName, + 'layers': layers, + 'wmsVersion': wmsVersion, + 'serviceEndPoint': serviceEndPoint, + 'outputFormat': outputFormat + }; + var serverUrl = "/api/controllers/wms_endpoints"; + // TODO: If failure happens notify user about the error message + $.post(serverUrl, data, function (response) { + noty({ + text: '' + response + '', + type: 'success' + }); + closeAll(); + }); + } + + +} + +function loadWms() { + // For refference {"wmsServerId" : 1, "serviceUrl" : "http://{s}.somedomain.com/blabla/{z}/{x}/{y}.png", "name" : "Sample server URL", "layers" : "asdsad,sd,adasd,asd", "version" : "1.0.2", "format" : "sadasda/asdas"} + $.getJSON("/api/controllers/wms_endpoints?serverId=all", function (data) { + $.each(data, function (key, val) { + + wmsLayer = L.tileLayer.wms(val.SERVICEURL, { + layers: val.LAYERS.split(','), + format: val.FORMAT ? val.FORMAT : 'image/png', + version: val.VERSION, + transparent: true, + opacity: 0.4 + }); + layerControl.addOverlay(wmsLayer, val.NAME, "Web Map Service layers"); + }); + }); +} + +function setSpeedAlert() { + //TODO: get the device Id from the URL + var speedAlertValue = $("#speedAlertValue").val(); + + if (!speedAlertValue) { + var message = "Speed cannot be empty."; + noty({text: message, type: 'error'}); + } else { + data = { + 'parseData': JSON.stringify({'speedAlertValue': speedAlertValue, 'deviceId': deviceId}), // parseKey : parseValue pair , this key pair is replace with the key in the template file + 'executionPlan': 'Speed', + 'customName': null, + 'cepAction': 'edit', + 'deviceId': deviceId + }; + var serviceUrl = '/api/device-mgt/v1.0/geo-services/alerts/Speed'; + var responseHandler = function (data, textStatus, xhr) { + closeAll(); + if (xhr.status == 200) { + noty({text: 'Successfully added alert', type: 'success'}); + } else { + var ptrn = /(?:)(.*)(?:<\/am\:description>)/g; + var result = (ptrn.exec(data)); + var errorTxt; + if (result) { + errorTxt = result.length > 1 ? result[1] : data; + } else { + errorTxt = data; + } + noty({text: textStatus + ' : ' + errorTxt, type: 'error'}); + } + }; + invokerUtil.put(serviceUrl, + data, + responseHandler, function (xhr) { + responseHandler(xhr.responseText, xhr.statusText, xhr); + }); + } + + +} +var lastToolLeafletId = null; + +function setWithinAlert(leafletId) { + /* + * TODO: replace double quote to single quote because of a conflict when deploying execution plan in CEP + * this is against JSON standards so has been re-replaced when getting the data from governance registry + * (look in get_alerts for .replace() method) + * */ + var selectedAreaGeoJson = JSON.stringify(map._layers[leafletId].toGeoJSON().geometry).replace(/"/g, "'"); + var areaName = $("#withinAlertAreaName").val(); + var queryName = areaName; + + + if (areaName == null || areaName === undefined || areaName == "") { + var message = "Area Name cannot be empty."; + noty({text: message, type: 'error'}); + } else if ($.trim(areaName).indexOf(" ") > -1) { + var message = "Area Name cannot contain spaces."; + noty({text: message, type: 'error'}); + } else { + areaName = $.trim(areaName); + var data = { + 'parseData': JSON.stringify({ + 'geoFenceGeoJSON': selectedAreaGeoJson, + 'executionPlanName': createExecutionPlanName(queryName, "WithIn", deviceId), + 'areaName': areaName, + 'deviceId': deviceId + }), + 'executionPlan': 'Within', + 'customName': areaName, // TODO: fix , When template copies there can be two queryName and areaName id elements in the DOM + 'queryName': queryName, + 'cepAction': 'deploy', + 'deviceId': deviceId + }; + + var serviceUrl = '/api/device-mgt/v1.0/geo-services/alerts/Within'; + var responseHandler = function (data, textStatus, xhr) { + closeTools(leafletId); + if (xhr.status == 200) { + noty({text: 'Successfully added alert', type: 'success'}); + } else { + var ptrn = /(?:)(.*)(?:<\/am\:description>)/g; + var errorTxt; + var result = (ptrn.exec(data)); + if (result) { + errorTxt = result.length > 1 ? result[1] : data; + } else { + errorTxt = data; + } + noty({text: textStatus + ' : ' + errorTxt, type: 'error'}); + } + }; + invokerUtil.post(serviceUrl, + data, + responseHandler, function (xhr) { + responseHandler(xhr.responseText, xhr.statusText, xhr); + }); + viewFenceByData(selectedAreaGeoJson, queryName, areaName, null, 'WithIn'); + } +} + +function setExitAlert(leafletId) { + /* + * TODO: replace double quote to single quote because of a conflict when deploying execution plan in CEP + * this is against JSON standards so has been re-replaced when getting the data from governance registry + * (look in get_alerts for .replace() method) + * */ + var selectedAreaGeoJson = JSON.stringify(map._layers[leafletId].toGeoJSON().geometry).replace(/"/g, "'"); + var areaName = $("#exitAlertAreaName").val(); + var queryName = areaName; + + + if (areaName == null || areaName === undefined || areaName == "") { + var message = "Area Name cannot be empty."; + noty({text: message, type: 'error'}); + } else if ($.trim(areaName).indexOf(" ") > -1) { + var message = "Area Name cannot contain spaces."; + noty({text: message, type: 'error'}); + } else { + areaName = $.trim(areaName); + var data = { + 'parseData': JSON.stringify({ + 'geoFenceGeoJSON': selectedAreaGeoJson, + 'executionPlanName': createExecutionPlanName(queryName, "Exit", deviceId), + 'areaName': areaName, + 'deviceId': deviceId + }), + 'executionPlan': 'Exit', + 'customName': areaName, // TODO: fix , When template copies there can be two queryName and areaName id elements in the DOM + 'queryName': queryName, + 'cepAction': 'deploy', + 'deviceId': deviceId + }; + + var serviceUrl = '/api/device-mgt/v1.0/geo-services/alerts/Exit'; + var responseHandler = function (data, textStatus, xhr) { + closeTools(leafletId); + if (xhr.status == 200) { + noty({text: 'Successfully added alert', type: 'success'}); + } else { + var ptrn = /(?:)(.*)(?:<\/am\:description>)/g; + var errorTxt; + var result = (ptrn.exec(data)); + if (result) { + errorTxt = result.length > 1 ? result[1] : data; + } else { + errorTxt = data; + } + noty({text: textStatus + ' : ' + errorTxt, type: 'error'}); + } + }; + invokerUtil.post(serviceUrl, + data, + responseHandler, function (xhr) { + responseHandler(xhr.responseText, xhr.statusText, xhr); + }); + viewFenceByData(selectedAreaGeoJson, queryName, areaName, null, 'Exit'); + } +} + +function setStationeryAlert(leafletId) { + + var selectedAreaGeoJson = map._layers[leafletId].toGeoJSON().geometry; + + //if a circle is drawn adding radius for the object + if (selectedAreaGeoJson.type == "Point") { + + var radius = map._layers[leafletId]._mRadius; + selectedAreaGeoJson["radius"] = radius; + } + + var selectedProcessedAreaGeoJson = JSON.stringify(selectedAreaGeoJson).replace(/"/g, "'"); + + var stationeryName = $("#stationaryAlertAreaName").val(); + var queryName = stationeryName; + var fluctuationRadius = $("#fRadius").val(); + var time = $("#time").val(); + + if (stationeryName == null || stationeryName === undefined || stationeryName == "") { + var message = "Stationery Name cannot be empty."; + noty({text: message, type: 'error'}); + } else if ($.trim(stationeryName).indexOf(" ") > -1) { + var message = "Stationery Name cannot contain spaces."; + noty({text: message, type: 'error'}); + } else if (fluctuationRadius == null || fluctuationRadius === undefined || fluctuationRadius == "") { + var message = "Fluctuation Radius cannot be empty."; + noty({text: message, type: 'error'}); + } else if (time == null || time === undefined || time == "") { + var message = "Time cannot be empty."; + noty({text: message, type: 'error'}); + } else { + stationeryName = $.trim(stationeryName); + var data = { + 'parseData': JSON.stringify({ + 'geoFenceGeoJSON': selectedProcessedAreaGeoJson, + 'executionPlanName': createExecutionPlanName(queryName, "Stationery", deviceId), + 'stationeryName': stationeryName, + 'stationeryTime': time, + 'fluctuationRadius': fluctuationRadius + }), + 'stationeryTime': time, + 'fluctuationRadius': fluctuationRadius, + 'executionPlan': 'Stationery', + 'customName': stationeryName, // TODO: fix , When template copies there can be two queryName and areaName id elements in the DOM + 'queryName': queryName, + 'cepAction': 'deploy', + 'deviceId': deviceId + }; + var serviceUrl = '/api/device-mgt/v1.0/geo-services/alerts/Stationery'; + var responseHandler = function (data, textStatus, xhr) { + closeTools(leafletId); + if (xhr.status == 200) { + noty({text: 'Successfully added alert', type: 'success'}); + } else { + var ptrn = /(?:)(.*)(?:<\/am\:description>)/g; + var errorTxt; + var result = (ptrn.exec(data)); + if (result) { + errorTxt = result.length > 1 ? result[1] : data; + } else { + errorTxt = data; + } + noty({text: textStatus + ' : ' + errorTxt, type: 'error'}); + } + }; + invokerUtil.post(serviceUrl, + data, + responseHandler, function (xhr) { + responseHandler(xhr.responseText, xhr.statusText, xhr); + }); + viewFenceByData(selectedProcessedAreaGeoJson, queryName, stationeryName, time, 'Stationery'); + } + + +} + +var toggeled = false; +/*function getPrediction(leafletId) { + *//* + * TODO: replace double quote to single quote because of a conflict when deploying execution plan in CEP + * this is against JSON standards so has been re-replaced when getting the data from governance registry + * (look in get_alerts for .replace() method) + * *//* + console.log("leafletId: " + leafletId); + var selectedAreaGeoJson = map._layers[leafletId].toGeoJSON().geometry; + var d = new Date(); + console.log(d); + + var selectedProcessedAreaGeoJson = JSON.stringify(selectedAreaGeoJson).replace(/"/g, "'"); + + requestPredictions(selectedAreaGeoJson.coordinates[0], selectedAreaGeoJson.coordinates[1], d); + if(!toggeled){ + $('#predictionResults').animate({width: 'toggle'}, 100); + toggeled = true; + } + + $.UIkit.notify({ + message: "Generating Predictions", + status: 'warning', + timeout: 5000, + pos: 'top-center' + }); + + setTimeout(function() { + var arr = getPredictions(selectedAreaGeoJson.coordinates[0], selectedAreaGeoJson.coordinates[1], d); + createPredictionChart(); + console.log(arr[1]); + predictionChart.load({columns: arr}); + } + , 5000); + + + + }*/ + + +function setTrafficAlert(leafletId) { + /* + * TODO: replace double quote to single quote because of a conflict when deploying execution plan in CEP + * this is against JSON standards so has been re-replaced when getting the data from governance registry + * (look in get_alerts for .replace() method) + * */ + var selectedAreaGeoJson = map._layers[leafletId].toGeoJSON().geometry; + + //if a circle is drawn adding radius for the object + if (selectedAreaGeoJson.type == "Point") { + + var radius = map._layers[leafletId]._mRadius; + selectedAreaGeoJson["radius"] = radius; + } + + var selectedProcessedAreaGeoJson = JSON.stringify(selectedAreaGeoJson).replace(/"/g, "'"); + + var areaName = $("#trafficAlertAreaName").val(); + var queryName = areaName; + //var time = $("#time").val(); + + if (areaName == null || areaName === undefined || areaName == "") { + var message = "Area Name cannot be empty."; + noty({text: message, type: 'error'}); + } else if ($.trim(areaName).indexOf(" ") > -1) { + var message = "Area Name cannot contain spaces."; + noty({text: message, type: 'error'}); + } else { + areaName = $.trim(areaName); + var data = { + 'parseData': JSON.stringify({ + 'geoFenceGeoJSON': selectedProcessedAreaGeoJson, + 'executionPlanName': createExecutionPlanName(queryName, "Traffic", deviceId), + 'areaName': areaName + }), + 'executionPlan': 'Traffic', + 'customName': areaName, // TODO: fix , When template copies there can be two queryName and areaName id elements in the DOM + 'queryName': queryName, + 'cepAction': 'deploy', + 'deviceId': deviceId + }; + + var serviceUrl = '/api/device-mgt/v1.0/geo-services/alerts/Traffic'; + var responseHandler = function (data, textStatus, xhr) { + closeTools(leafletId); + if (xhr.status == 200) { + noty({text: 'Successfully added alert', type: 'success'}); + } else { + var ptrn = /(?:)(.*)(?:<\/am\:description>)/g; + var errorTxt; + var result = (ptrn.exec(data)); + if (result) { + errorTxt = result.length > 1 ? result[1] : data; + } else { + errorTxt = data; + } + noty({text: textStatus + ' : ' + errorTxt, type: 'error'}); + } + }; + invokerUtil.post(serviceUrl, + data, + responseHandler, function (xhr) { + responseHandler(xhr.responseText, xhr.statusText, xhr); + }); + } +} + +function removeGeoFence(geoFenceElement, id) { + var queryName = $(geoFenceElement).attr('data-queryName'); + var areaName = $(geoFenceElement).attr('data-areaName'); + + var serviceUrl = '/api/device-mgt/v1.0/geo-services/alerts/' + id + '?queryName=' + + queryName; + invokerUtil.delete(serviceUrl, function (response) { + noty({ + text: 'Successfully removed ' + id + ' alert', + type: 'success' + }); + closeAll(); + }, + function (xhr) { + noty({ + text: 'Could not remove ' + id + ' alert', + type: 'error' + }) + }); +} + + +function getAlertsHistory(timeFrom, timeTo) { + var timeRange = ''; + if (timeFrom && timeTo) { + timeRange = '?from=' + timeFrom + '&to=' + timeTo; + } + var serviceUrl = '/api/device-mgt/v1.0/geo-services/alerts/history' + timeRange; + invokerUtil.get(serviceUrl, + function (data) { + geoAlertsBar.clearAllAlerts(); + var alerts = JSON.parse(data); + $.each(alerts, function (key, val) { + if (val.values) { + val = val.values; + } + var msg = val.information.replace("Alerts: ,", "").charAt(0).toUpperCase() + + val.information.replace("Alerts: ,", "").slice(1) + " - " + timeSince(val.timeStamp); + switch (val.state) { + case "NORMAL": + return; + case "WARNING": + geoAlertsBar.addAlert('warn', msg, val); + break; + case "ALERTED": + geoAlertsBar.addAlert('danger', msg, val); + break; + case "OFFLINE": + geoAlertsBar.addAlert('info', msg, val); + break; + } + }); + }, function (message) { + }); +} + + +function setProximityAlert() { + + var proximityDistance = $("#proximityDistance").val(); + var proximityTime = $("#proximityTime").val(); + + if (proximityDistance == null || proximityDistance === undefined || proximityDistance == "") { + var message = "Proximity distance cannot be empty."; + noty({text: message, type: 'error'}); + } else if (proximityTime == null || proximityTime === undefined || proximityTime == "") { + var message = "Proximity Time cannot be empty."; + noty({text: message, type: 'error'}); + } else { + var data = { + 'parseData': JSON.stringify({ + 'proximityTime': proximityTime, + 'proximityDistance': proximityDistance + }), + 'proximityTime': proximityTime, + 'proximityDistance': proximityDistance, + 'executionPlan': 'Proximity', + 'customName': null, + 'cepAction': 'edit', + 'deviceId': deviceId + }; + var serviceUrl = '/api/device-mgt/v1.0/geo-services/alerts/Proximity'; + var responseHandler = function (data, textStatus, xhr) { + closeAll(); + if (xhr.status == 200) { + noty({text: 'Successfully added alert', type: 'success'}); + } else { + var ptrn = /(?:)(.*)(?:<\/am\:description>)/g; + var errorTxt; + var result = (ptrn.exec(data)); + if (result) { + errorTxt = result.length > 1 ? result[1] : data; + } else { + errorTxt = data; + } + noty({text: textStatus + ' : ' + errorTxt, type: 'error'}); + } + }; + invokerUtil.put(serviceUrl, + data, + responseHandler, function (xhr) { + responseHandler(xhr.responseText, xhr.statusText, xhr); + }); + + } +} + +// TODO:this is not a remote call , move this to application.js +function createExecutionPlanName(queryName, id) { + + if (id == "WithIn") { + return 'Geo-ExecutionPlan-Within' + (queryName ? '_' + queryName : '') + "---" + '_alert'; // TODO: value of the `queryName` can't be empty, because it will cause name conflicts in CEP, have to do validation(check not empty String) + } else if (id == "Exit") { + return 'Geo-ExecutionPlan-Exit' + (queryName ? '_' + queryName : '') + "---" + '_alert'; // TODO: value of the `queryName` can't be empty, because it will cause name conflicts in CEP, have to do validation(check not empty String) + } else if (id == "Stationery") { + return 'Geo-ExecutionPlan-Stationery' + (queryName ? '_' + queryName : '') + "---" + '_alert'; // TODO: value of the `queryName` can't be empty, because it will cause name conflicts in CEP, have to do validation(check not empty String) + } else if (id == "Traffic") { + return 'Geo-ExecutionPlan-Traffic' + (queryName ? '_' + queryName : '') + '_alert'; // TODO: value of the `queryName` can't be empty, because it will cause name conflicts in CEP, have to do validation(check not empty String) + } + +} // TODO:this is not a remote call , move this to application.js function closeAll() { diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.geo-devices/public/js/geo_speed.js b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.geo-devices/public/js/geo_speed.js new file mode 100644 index 0000000000..648463dfcd --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.geo-devices/public/js/geo_speed.js @@ -0,0 +1,29 @@ +/* + * 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. + */ + +function initializeSpeed() { + var serverUrl = "/api/device-mgt/v1.0/geo-services/alerts/Speed"; + // var serverUrl = "/portal/store/carbon.super/fs/gadget/geo-dashboard/controllers/get_alerts.jag?executionPlanType=Speed&deviceId=" + deviceId; + invokerUtil.get(serverUrl, function (response) { + response = JSON.parse(response); + if (response) { + $("#speedAlertValue").val(response.speedLimit); + } + }); +} +initializeSpeed(); diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.geo-devices/public/js/geo_stationary.js b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.geo-devices/public/js/geo_stationary.js new file mode 100644 index 0000000000..2011ca56d4 --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.geo-devices/public/js/geo_stationary.js @@ -0,0 +1,54 @@ +/* + * 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. + */ + +function initStationaryAlert() { + // var serverUrl = "/portal/store/carbon.super/fs/gadget/geo-dashboard/controllers/get_alerts.jag?executionPlanType=Stationery&deviceId=" + deviceId; + var serverUrl = "/api/device-mgt/v1.0/geo-services/alerts/Stationery"; + + $(".removeGeoFence").tooltip(); + $("#stationary-alert-table > tbody").empty(); + invokerUtil.get(serverUrl, function (response) { + if (response == "[]") { + $(".fence-not-exist").show(); + $("#stationary-alert-table").hide(); + } + else if (response) { + response = JSON.parse(response); + $(".fence-not-exist").hide(); + $("#stationary-alert-table").show(); + for (var index in response) { + var alert = response[index]; + $("#stationary-alert-table > tbody").append( + "" + + "" + alert.areaName + "" + alert.stationaryTime + "" + alert.fluctuationRadius + + "" + alert.queryName + "" + formatDate(new Date(alert.createdTime)) + "") + } + } else{ + $(".fence-not-exist").show(); + $("#stationary-alert-table").hide(); + } + $('.viewGeoFenceRow td:not(:last-child)').click(function () { + viewFence(this.parentElement,'Stationery'); + }); + }); +} +initStationaryAlert(); \ No newline at end of file diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.geo-devices/public/js/geo_within.js b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.geo-devices/public/js/geo_within.js new file mode 100644 index 0000000000..689eb31d86 --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.geo-devices/public/js/geo_within.js @@ -0,0 +1,50 @@ +/* + * 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. + */ + +function initializeWithin() { + $(".removeGeoFence").tooltip(); + $("#within-alert > tbody").empty(); + var serverUrl = "/api/device-mgt/v1.0/geo-services/alerts/Within"; + invokerUtil.get(serverUrl, function (response) { + if (response == "[]") { + $(".fence-not-exist").show(); + $("#within-alert").hide(); + } + else if (response) { + $(".fence-not-exist").hide(); + $("#within-alert").show(); + response = JSON.parse(response); + for (var index in response) { + var alertBean = response[index]; + $("#within-alert > tbody").append( + "" + alertBean.areaName + "" + + "" + alertBean.queryName + "" + formatDate(new Date(alertBean.createdTime)) + "" + + ""); + } + } else{ + $(".fence-not-exist").show(); + $("#within-alert").hide(); + } + $('.viewGeoFenceRow td:not(:last-child)').click(function () { + viewFence(this.parentElement,'WithIn'); + }); + }); +} +initializeWithin(); \ No newline at end of file diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.geo-devices/public/js/jquery/bootstrap-datepicker.min.js b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.geo-devices/public/js/jquery/bootstrap-datepicker.min.js new file mode 100644 index 0000000000..f26d0d8674 --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.geo-devices/public/js/jquery/bootstrap-datepicker.min.js @@ -0,0 +1,8 @@ +/*! + * Datepicker for Bootstrap v1.4.0 (https://github.com/eternicode/bootstrap-datepicker) + * + * Copyright 2012 Stefan Petre + * Improvements by Andrew Rowls + * Licensed under the Apache License v2.0 (http://www.apache.org/licenses/LICENSE-2.0) + */ +!function(a,b){function c(){return new Date(Date.UTC.apply(Date,arguments))}function d(){var a=new Date;return c(a.getFullYear(),a.getMonth(),a.getDate())}function e(a,b){return a.getUTCFullYear()===b.getUTCFullYear()&&a.getUTCMonth()===b.getUTCMonth()&&a.getUTCDate()===b.getUTCDate()}function f(a){return function(){return this[a].apply(this,arguments)}}function g(b,c){function d(a,b){return b.toLowerCase()}var e,f=a(b).data(),g={},h=new RegExp("^"+c.toLowerCase()+"([A-Z])");c=new RegExp("^"+c.toLowerCase());for(var i in f)c.test(i)&&(e=i.replace(h,d),g[e]=f[i]);return g}function h(b){var c={};if(p[b]||(b=b.split("-")[0],p[b])){var d=p[b];return a.each(o,function(a,b){b in d&&(c[b]=d[b])}),c}}var i=function(){var b={get:function(a){return this.slice(a)[0]},contains:function(a){for(var b=a&&a.valueOf(),c=0,d=this.length;d>c;c++)if(this[c].valueOf()===b)return c;return-1},remove:function(a){this.splice(a,1)},replace:function(b){b&&(a.isArray(b)||(b=[b]),this.clear(),this.push.apply(this,b))},clear:function(){this.length=0},copy:function(){var a=new i;return a.replace(this),a}};return function(){var c=[];return c.push.apply(c,arguments),a.extend(c,b),c}}(),j=function(b,c){this._process_options(c),this.dates=new i,this.viewDate=this.o.defaultViewDate,this.focusDate=null,this.element=a(b),this.isInline=!1,this.isInput=this.element.is("input"),this.component=this.element.hasClass("date")?this.element.find(".add-on, .input-group-addon, .btn"):!1,this.hasInput=this.component&&this.element.find("input").length,this.component&&0===this.component.length&&(this.component=!1),this.picker=a(q.template),this._buildEvents(),this._attachEvents(),this.isInline?this.picker.addClass("datepicker-inline").appendTo(this.element):this.picker.addClass("datepicker-dropdown dropdown-menu"),this.o.rtl&&this.picker.addClass("datepicker-rtl"),this.viewMode=this.o.startView,this.o.calendarWeeks&&this.picker.find("tfoot .today, tfoot .clear").attr("colspan",function(a,b){return parseInt(b)+1}),this._allow_update=!1,this.setStartDate(this._o.startDate),this.setEndDate(this._o.endDate),this.setDaysOfWeekDisabled(this.o.daysOfWeekDisabled),this.setDatesDisabled(this.o.datesDisabled),this.fillDow(),this.fillMonths(),this._allow_update=!0,this.update(),this.showMode(),this.isInline&&this.show()};j.prototype={constructor:j,_process_options:function(e){this._o=a.extend({},this._o,e);var f=this.o=a.extend({},this._o),g=f.language;switch(p[g]||(g=g.split("-")[0],p[g]||(g=n.language)),f.language=g,f.startView){case 2:case"decade":f.startView=2;break;case 1:case"year":f.startView=1;break;default:f.startView=0}switch(f.minViewMode){case 1:case"months":f.minViewMode=1;break;case 2:case"years":f.minViewMode=2;break;default:f.minViewMode=0}f.startView=Math.max(f.startView,f.minViewMode),f.multidate!==!0&&(f.multidate=Number(f.multidate)||!1,f.multidate!==!1&&(f.multidate=Math.max(0,f.multidate))),f.multidateSeparator=String(f.multidateSeparator),f.weekStart%=7,f.weekEnd=(f.weekStart+6)%7;var h=q.parseFormat(f.format);if(f.startDate!==-1/0&&(f.startDate=f.startDate?f.startDate instanceof Date?this._local_to_utc(this._zero_time(f.startDate)):q.parseDate(f.startDate,h,f.language):-1/0),1/0!==f.endDate&&(f.endDate=f.endDate?f.endDate instanceof Date?this._local_to_utc(this._zero_time(f.endDate)):q.parseDate(f.endDate,h,f.language):1/0),f.daysOfWeekDisabled=f.daysOfWeekDisabled||[],a.isArray(f.daysOfWeekDisabled)||(f.daysOfWeekDisabled=f.daysOfWeekDisabled.split(/[,\s]*/)),f.daysOfWeekDisabled=a.map(f.daysOfWeekDisabled,function(a){return parseInt(a,10)}),f.datesDisabled=f.datesDisabled||[],!a.isArray(f.datesDisabled)){var i=[];i.push(q.parseDate(f.datesDisabled,h,f.language)),f.datesDisabled=i}f.datesDisabled=a.map(f.datesDisabled,function(a){return q.parseDate(a,h,f.language)});var j=String(f.orientation).toLowerCase().split(/\s+/g),k=f.orientation.toLowerCase();if(j=a.grep(j,function(a){return/^auto|left|right|top|bottom$/.test(a)}),f.orientation={x:"auto",y:"auto"},k&&"auto"!==k)if(1===j.length)switch(j[0]){case"top":case"bottom":f.orientation.y=j[0];break;case"left":case"right":f.orientation.x=j[0]}else k=a.grep(j,function(a){return/^left|right$/.test(a)}),f.orientation.x=k[0]||"auto",k=a.grep(j,function(a){return/^top|bottom$/.test(a)}),f.orientation.y=k[0]||"auto";else;if(f.defaultViewDate){var l=f.defaultViewDate.year||(new Date).getFullYear(),m=f.defaultViewDate.month||0,o=f.defaultViewDate.day||1;f.defaultViewDate=c(l,m,o)}else f.defaultViewDate=d();f.showOnFocus=f.showOnFocus!==b?f.showOnFocus:!0},_events:[],_secondaryEvents:[],_applyEvents:function(a){for(var c,d,e,f=0;fe?(this.picker.addClass("datepicker-orient-right"),n=k.left+m-b):this.picker.addClass("datepicker-orient-left");var p,q,r=this.o.orientation.y;if("auto"===r&&(p=-g+o-c,q=g+f-(o+l+c),r=Math.max(p,q)===q?"top":"bottom"),this.picker.addClass("datepicker-orient-"+r),"top"===r?o+=l:o-=c+parseInt(this.picker.css("padding-top")),this.o.rtl){var s=e-(n+m);this.picker.css({top:o,right:s,zIndex:j})}else this.picker.css({top:o,left:n,zIndex:j});return this},_allow_update:!0,update:function(){if(!this._allow_update)return this;var b=this.dates.copy(),c=[],d=!1;return arguments.length?(a.each(arguments,a.proxy(function(a,b){b instanceof Date&&(b=this._local_to_utc(b)),c.push(b)},this)),d=!0):(c=this.isInput?this.element.val():this.element.data("date")||this.element.find("input").val(),c=c&&this.o.multidate?c.split(this.o.multidateSeparator):[c],delete this.element.data().date),c=a.map(c,a.proxy(function(a){return q.parseDate(a,this.o.format,this.o.language)},this)),c=a.grep(c,a.proxy(function(a){return athis.o.endDate||!a},this),!0),this.dates.replace(c),this.dates.length?this.viewDate=new Date(this.dates.get(-1)):this.viewDatethis.o.endDate&&(this.viewDate=new Date(this.o.endDate)),d?this.setValue():c.length&&String(b)!==String(this.dates)&&this._trigger("changeDate"),!this.dates.length&&b.length&&this._trigger("clearDate"),this.fill(),this},fillDow:function(){var a=this.o.weekStart,b="";if(this.o.calendarWeeks){this.picker.find(".datepicker-days thead tr:first-child .datepicker-switch").attr("colspan",function(a,b){return parseInt(b)+1});var c=' ';b+=c}for(;a'+p[this.o.language].daysMin[a++%7]+"";b+="",this.picker.find(".datepicker-days thead").append(b)},fillMonths:function(){for(var a="",b=0;12>b;)a+=''+p[this.o.language].monthsShort[b++]+"";this.picker.find(".datepicker-months td").html(a)},setRange:function(b){b&&b.length?this.range=a.map(b,function(a){return a.valueOf()}):delete this.range,this.fill()},getClassNames:function(b){var c=[],d=this.viewDate.getUTCFullYear(),f=this.viewDate.getUTCMonth(),g=new Date;return b.getUTCFullYear()d||b.getUTCFullYear()===d&&b.getUTCMonth()>f)&&c.push("new"),this.focusDate&&b.valueOf()===this.focusDate.valueOf()&&c.push("focused"),this.o.todayHighlight&&b.getUTCFullYear()===g.getFullYear()&&b.getUTCMonth()===g.getMonth()&&b.getUTCDate()===g.getDate()&&c.push("today"),-1!==this.dates.contains(b)&&c.push("active"),(b.valueOf()this.o.endDate||-1!==a.inArray(b.getUTCDay(),this.o.daysOfWeekDisabled))&&c.push("disabled"),this.o.datesDisabled.length>0&&a.grep(this.o.datesDisabled,function(a){return e(b,a)}).length>0&&c.push("disabled","disabled-date"),this.range&&(b>this.range[0]&&b"),this.o.calendarWeeks)){var u=new Date(+n+(this.o.weekStart-n.getUTCDay()-7)%7*864e5),v=new Date(Number(u)+(11-u.getUTCDay())%7*864e5),w=new Date(Number(w=c(v.getUTCFullYear(),0,1))+(11-w.getUTCDay())%7*864e5),x=(v-w)/864e5/7+1;t.push(''+x+"")}if(s=this.getClassNames(n),s.push("day"),this.o.beforeShowDay!==a.noop){var y=this.o.beforeShowDay(this._utc_to_local(n));y===b?y={}:"boolean"==typeof y?y={enabled:y}:"string"==typeof y&&(y={classes:y}),y.enabled===!1&&s.push("disabled"),y.classes&&(s=s.concat(y.classes.split(/\s+/))),y.tooltip&&(d=y.tooltip)}s=a.unique(s),t.push('"+n.getUTCDate()+""),d=null,n.getUTCDay()===this.o.weekEnd&&t.push(""),n.setUTCDate(n.getUTCDate()+1)}this.picker.find(".datepicker-days tbody").empty().append(t.join(""));var z=this.picker.find(".datepicker-months").find("th:eq(1)").text(f).end().find("span").removeClass("active");if(a.each(this.dates,function(a,b){b.getUTCFullYear()===f&&z.eq(b.getUTCMonth()).addClass("active")}),(h>f||f>j)&&z.addClass("disabled"),f===h&&z.slice(0,i).addClass("disabled"),f===j&&z.slice(k+1).addClass("disabled"),this.o.beforeShowMonth!==a.noop){var A=this;a.each(z,function(b,c){if(!a(c).hasClass("disabled")){var d=new Date(f,b,1),e=A.o.beforeShowMonth(d);e===!1&&a(c).addClass("disabled")}})}t="",f=10*parseInt(f/10,10);var B=this.picker.find(".datepicker-years").find("th:eq(1)").text(f+"-"+(f+9)).end().find("td");f-=1;for(var C,D=a.map(this.dates,function(a){return a.getUTCFullYear()}),E=-1;11>E;E++)C=["year"],-1===E?C.push("old"):10===E&&C.push("new"),-1!==a.inArray(f,D)&&C.push("active"),(h>f||f>j)&&C.push("disabled"),t+=''+f+"",f+=1;B.html(t)}},updateNavArrows:function(){if(this._allow_update){var a=new Date(this.viewDate),b=a.getUTCFullYear(),c=a.getUTCMonth();switch(this.viewMode){case 0:this.picker.find(".prev").css(this.o.startDate!==-1/0&&b<=this.o.startDate.getUTCFullYear()&&c<=this.o.startDate.getUTCMonth()?{visibility:"hidden"}:{visibility:"visible"}),this.picker.find(".next").css(1/0!==this.o.endDate&&b>=this.o.endDate.getUTCFullYear()&&c>=this.o.endDate.getUTCMonth()?{visibility:"hidden"}:{visibility:"visible"});break;case 1:case 2:this.picker.find(".prev").css(this.o.startDate!==-1/0&&b<=this.o.startDate.getUTCFullYear()?{visibility:"hidden"}:{visibility:"visible"}),this.picker.find(".next").css(1/0!==this.o.endDate&&b>=this.o.endDate.getUTCFullYear()?{visibility:"hidden"}:{visibility:"visible"})}}},click:function(b){b.preventDefault();var d,e,f,g=a(b.target).closest("span, td, th");if(1===g.length)switch(g[0].nodeName.toLowerCase()){case"th":switch(g[0].className){case"datepicker-switch":this.showMode(1);break;case"prev":case"next":var h=q.modes[this.viewMode].navStep*("prev"===g[0].className?-1:1);switch(this.viewMode){case 0:this.viewDate=this.moveMonth(this.viewDate,h),this._trigger("changeMonth",this.viewDate);break;case 1:case 2:this.viewDate=this.moveYear(this.viewDate,h),1===this.viewMode&&this._trigger("changeYear",this.viewDate)}this.fill();break;case"today":var i=new Date;i=c(i.getFullYear(),i.getMonth(),i.getDate(),0,0,0),this.showMode(-2);var j="linked"===this.o.todayBtn?null:"view";this._setDate(i,j);break;case"clear":this.clearDates()}break;case"span":g.hasClass("disabled")||(this.viewDate.setUTCDate(1),g.hasClass("month")?(f=1,e=g.parent().find("span").index(g),d=this.viewDate.getUTCFullYear(),this.viewDate.setUTCMonth(e),this._trigger("changeMonth",this.viewDate),1===this.o.minViewMode&&this._setDate(c(d,e,f))):(f=1,e=0,d=parseInt(g.text(),10)||0,this.viewDate.setUTCFullYear(d),this._trigger("changeYear",this.viewDate),2===this.o.minViewMode&&this._setDate(c(d,e,f))),this.showMode(-1),this.fill());break;case"td":g.hasClass("day")&&!g.hasClass("disabled")&&(f=parseInt(g.text(),10)||1,d=this.viewDate.getUTCFullYear(),e=this.viewDate.getUTCMonth(),g.hasClass("old")?0===e?(e=11,d-=1):e-=1:g.hasClass("new")&&(11===e?(e=0,d+=1):e+=1),this._setDate(c(d,e,f)))}this.picker.is(":visible")&&this._focused_from&&a(this._focused_from).focus(),delete this._focused_from},_toggle_multidate:function(a){var b=this.dates.contains(a);if(a||this.dates.clear(),-1!==b?(this.o.multidate===!0||this.o.multidate>1||this.o.toggleActive)&&this.dates.remove(b):this.o.multidate===!1?(this.dates.clear(),this.dates.push(a)):this.dates.push(a),"number"==typeof this.o.multidate)for(;this.dates.length>this.o.multidate;)this.dates.remove(0)},_setDate:function(a,b){b&&"date"!==b||this._toggle_multidate(a&&new Date(a)),b&&"view"!==b||(this.viewDate=a&&new Date(a)),this.fill(),this.setValue(),b&&"view"===b||this._trigger("changeDate");var c;this.isInput?c=this.element:this.component&&(c=this.element.find("input")),c&&c.change(),!this.o.autoclose||b&&"date"!==b||this.hide()},moveMonth:function(a,c){if(!a)return b;if(!c)return a;var d,e,f=new Date(a.valueOf()),g=f.getUTCDate(),h=f.getUTCMonth(),i=Math.abs(c);if(c=c>0?1:-1,1===i)e=-1===c?function(){return f.getUTCMonth()===h}:function(){return f.getUTCMonth()!==d},d=h+c,f.setUTCMonth(d),(0>d||d>11)&&(d=(d+12)%12);else{for(var j=0;i>j;j++)f=this.moveMonth(f,c);d=f.getUTCMonth(),f.setUTCDate(g),e=function(){return d!==f.getUTCMonth()}}for(;e();)f.setUTCDate(--g),f.setUTCMonth(d);return f},moveYear:function(a,b){return this.moveMonth(a,12*b)},dateWithinRange:function(a){return a>=this.o.startDate&&a<=this.o.endDate},keydown:function(a){if(!this.picker.is(":visible"))return void(27===a.keyCode&&this.show());var b,c,e,f=!1,g=this.focusDate||this.viewDate;switch(a.keyCode){case 27:this.focusDate?(this.focusDate=null,this.viewDate=this.dates.get(-1)||this.viewDate,this.fill()):this.hide(),a.preventDefault();break;case 37:case 39:if(!this.o.keyboardNavigation)break;b=37===a.keyCode?-1:1,a.ctrlKey?(c=this.moveYear(this.dates.get(-1)||d(),b),e=this.moveYear(g,b),this._trigger("changeYear",this.viewDate)):a.shiftKey?(c=this.moveMonth(this.dates.get(-1)||d(),b),e=this.moveMonth(g,b),this._trigger("changeMonth",this.viewDate)):(c=new Date(this.dates.get(-1)||d()),c.setUTCDate(c.getUTCDate()+b),e=new Date(g),e.setUTCDate(g.getUTCDate()+b)),this.dateWithinRange(e)&&(this.focusDate=this.viewDate=e,this.setValue(),this.fill(),a.preventDefault());break;case 38:case 40:if(!this.o.keyboardNavigation)break;b=38===a.keyCode?-1:1,a.ctrlKey?(c=this.moveYear(this.dates.get(-1)||d(),b),e=this.moveYear(g,b),this._trigger("changeYear",this.viewDate)):a.shiftKey?(c=this.moveMonth(this.dates.get(-1)||d(),b),e=this.moveMonth(g,b),this._trigger("changeMonth",this.viewDate)):(c=new Date(this.dates.get(-1)||d()),c.setUTCDate(c.getUTCDate()+7*b),e=new Date(g),e.setUTCDate(g.getUTCDate()+7*b)),this.dateWithinRange(e)&&(this.focusDate=this.viewDate=e,this.setValue(),this.fill(),a.preventDefault());break;case 32:break;case 13:g=this.focusDate||this.dates.get(-1)||this.viewDate,this.o.keyboardNavigation&&(this._toggle_multidate(g),f=!0),this.focusDate=null,this.viewDate=this.dates.get(-1)||this.viewDate,this.setValue(),this.fill(),this.picker.is(":visible")&&(a.preventDefault(),"function"==typeof a.stopPropagation?a.stopPropagation():a.cancelBubble=!0,this.o.autoclose&&this.hide());break;case 9:this.focusDate=null,this.viewDate=this.dates.get(-1)||this.viewDate,this.fill(),this.hide()}if(f){this._trigger(this.dates.length?"changeDate":"clearDate");var h;this.isInput?h=this.element:this.component&&(h=this.element.find("input")),h&&h.change()}},showMode:function(a){a&&(this.viewMode=Math.max(this.o.minViewMode,Math.min(2,this.viewMode+a))),this.picker.children("div").hide().filter(".datepicker-"+q.modes[this.viewMode].clsName).css("display","block"),this.updateNavArrows()}};var k=function(b,c){this.element=a(b),this.inputs=a.map(c.inputs,function(a){return a.jquery?a[0]:a}),delete c.inputs,m.call(a(this.inputs),c).bind("changeDate",a.proxy(this.dateUpdated,this)),this.pickers=a.map(this.inputs,function(b){return a(b).data("datepicker")}),this.updateDates()};k.prototype={updateDates:function(){this.dates=a.map(this.pickers,function(a){return a.getUTCDate()}),this.updateRanges()},updateRanges:function(){var b=a.map(this.dates,function(a){return a.valueOf()});a.each(this.pickers,function(a,c){c.setRange(b)})},dateUpdated:function(b){if(!this.updating){this.updating=!0;var c=a(b.target).data("datepicker"),d=c.getUTCDate(),e=a.inArray(b.target,this.inputs),f=e-1,g=e+1,h=this.inputs.length;if(-1!==e){if(a.each(this.pickers,function(a,b){b.getUTCDate()||b.setUTCDate(d)}),d=0&&dthis.dates[g])for(;h>g&&d>this.dates[g];)this.pickers[g++].setUTCDate(d);this.updateDates(),delete this.updating}}},remove:function(){a.map(this.pickers,function(a){a.remove()}),delete this.element.data().datepicker}};var l=a.fn.datepicker,m=function(c){var d=Array.apply(null,arguments);d.shift();var e;return this.each(function(){var f=a(this),i=f.data("datepicker"),l="object"==typeof c&&c;if(!i){var m=g(this,"date"),o=a.extend({},n,m,l),p=h(o.language),q=a.extend({},n,p,m,l);if(f.hasClass("input-daterange")||q.inputs){var r={inputs:q.inputs||f.find("input").toArray()};f.data("datepicker",i=new k(this,a.extend(q,r)))}else f.data("datepicker",i=new j(this,q))}return"string"==typeof c&&"function"==typeof i[c]&&(e=i[c].apply(i,d),e!==b)?!1:void 0}),e!==b?e:this};a.fn.datepicker=m;var n=a.fn.datepicker.defaults={autoclose:!1,beforeShowDay:a.noop,beforeShowMonth:a.noop,calendarWeeks:!1,clearBtn:!1,toggleActive:!1,daysOfWeekDisabled:[],datesDisabled:[],endDate:1/0,forceParse:!0,format:"mm/dd/yyyy",keyboardNavigation:!0,language:"en",minViewMode:0,multidate:!1,multidateSeparator:",",orientation:"auto",rtl:!1,startDate:-1/0,startView:0,todayBtn:!1,todayHighlight:!1,weekStart:0,disableTouchKeyboard:!1,enableOnReadonly:!0,container:"body"},o=a.fn.datepicker.locale_opts=["format","rtl","weekStart"];a.fn.datepicker.Constructor=j;var p=a.fn.datepicker.dates={en:{days:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","Sunday"],daysShort:["Sun","Mon","Tue","Wed","Thu","Fri","Sat","Sun"],daysMin:["Su","Mo","Tu","We","Th","Fr","Sa","Su"],months:["January","February","March","April","May","June","July","August","September","October","November","December"],monthsShort:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],today:"Today",clear:"Clear"}},q={modes:[{clsName:"days",navFnc:"Month",navStep:1},{clsName:"months",navFnc:"FullYear",navStep:1},{clsName:"years",navFnc:"FullYear",navStep:10}],isLeapYear:function(a){return a%4===0&&a%100!==0||a%400===0},getDaysInMonth:function(a,b){return[31,q.isLeapYear(a)?29:28,31,30,31,30,31,31,30,31,30,31][b]},validParts:/dd?|DD?|mm?|MM?|yy(?:yy)?/g,nonpunctuation:/[^ -\/:-@\[\u3400-\u9fff-`{-~\t\n\r]+/g,parseFormat:function(a){var b=a.replace(this.validParts,"\x00").split("\x00"),c=a.match(this.validParts);if(!b||!b.length||!c||0===c.length)throw new Error("Invalid date format.");return{separators:b,parts:c}},parseDate:function(d,e,f){function g(){var a=this.slice(0,m[k].length),b=m[k].slice(0,a.length);return a.toLowerCase()===b.toLowerCase()}if(!d)return b;if(d instanceof Date)return d;"string"==typeof e&&(e=q.parseFormat(e));var h,i,k,l=/([\-+]\d+)([dmwy])/,m=d.match(/([\-+]\d+)([dmwy])/g);if(/^[\-+]\d+[dmwy]([\s,]+[\-+]\d+[dmwy])*$/.test(d)){for(d=new Date,k=0;kb;)b+=12;for(b%=12,a.setUTCMonth(b);a.getUTCMonth()!==b;)a.setUTCDate(a.getUTCDate()-1);return a},d:function(a,b){return a.setUTCDate(b)}};t.M=t.MM=t.mm=t.m,t.dd=t.d,d=c(d.getFullYear(),d.getMonth(),d.getDate(),0,0,0);var u=e.parts.slice();if(m.length!==u.length&&(u=a(u).filter(function(b,c){return-1!==a.inArray(c,s)}).toArray()),m.length===u.length){var v;for(k=0,v=u.length;v>k;k++){if(n=parseInt(m[k],10),h=u[k],isNaN(n))switch(h){case"MM":o=a(p[f].months).filter(g),n=a.inArray(o[0],p[f].months)+1;break;case"M":o=a(p[f].monthsShort).filter(g),n=a.inArray(o[0],p[f].monthsShort)+1}r[h]=n}var w,x;for(k=0;k=g;g++)f.length&&b.push(f.shift()),b.push(e[c.parts[g]]);return b.join("")},headTemplate:'«»',contTemplate:'',footTemplate:''};q.template='
    '+q.headTemplate+""+q.footTemplate+'
    '+q.headTemplate+q.contTemplate+q.footTemplate+'
    '+q.headTemplate+q.contTemplate+q.footTemplate+"
    ",a.fn.datepicker.DPGlobal=q,a.fn.datepicker.noConflict=function(){return a.fn.datepicker=l,this},a.fn.datepicker.version="1.4.0",a(document).on("focus.datepicker.data-api click.datepicker.data-api",'[data-provide="datepicker"]',function(b){var c=a(this);c.data("datepicker")||(b.preventDefault(),m.call(c,"show"))}),a(function(){m.call(a('[data-provide="datepicker-inline"]'))})}(window.jQuery); \ No newline at end of file diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.geo-devices/public/js/jquery/jquery-2.1.1.min.js b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.geo-devices/public/js/jquery/jquery-2.1.1.min.js new file mode 100644 index 0000000000..18a8b895d9 --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.geo-devices/public/js/jquery/jquery-2.1.1.min.js @@ -0,0 +1,2066 @@ +/*! jQuery v2.1.1 | (c) 2005, 2014 jQuery Foundation, Inc. | jquery.org/license */ +!function (a, b) { + "object" == typeof module && "object" == typeof module.exports ? module.exports = a.document ? b(a, !0) : function (a) { + if (!a.document)throw new Error("jQuery requires a window with a document"); + return b(a) + } : b(a) +}("undefined" != typeof window ? window : this, function (a, b) { + var c = [], d = c.slice, e = c.concat, f = c.push, g = c.indexOf, h = {}, i = h.toString, j = h.hasOwnProperty, k = {}, l = a.document, m = "2.1.1", n = function (a, b) { + return new n.fn.init(a, b) + }, o = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, p = /^-ms-/, q = /-([\da-z])/gi, r = function (a, b) { + return b.toUpperCase() + }; + n.fn = n.prototype = {jquery: m, constructor: n, selector: "", length: 0, toArray: function () { + return d.call(this) + }, get: function (a) { + return null != a ? 0 > a ? this[a + this.length] : this[a] : d.call(this) + }, pushStack: function (a) { + var b = n.merge(this.constructor(), a); + return b.prevObject = this, b.context = this.context, b + }, each: function (a, b) { + return n.each(this, a, b) + }, map: function (a) { + return this.pushStack(n.map(this, function (b, c) { + return a.call(b, c, b) + })) + }, slice: function () { + return this.pushStack(d.apply(this, arguments)) + }, first: function () { + return this.eq(0) + }, last: function () { + return this.eq(-1) + }, eq: function (a) { + var b = this.length, c = +a + (0 > a ? b : 0); + return this.pushStack(c >= 0 && b > c ? [this[c]] : []) + }, end: function () { + return this.prevObject || this.constructor(null) + }, push: f, sort: c.sort, splice: c.splice}, n.extend = n.fn.extend = function () { + var a, b, c, d, e, f, g = arguments[0] || {}, h = 1, i = arguments.length, j = !1; + for ("boolean" == typeof g && (j = g, g = arguments[h] || {}, h++), "object" == typeof g || n.isFunction(g) || (g = {}), h === i && (g = this, h--); i > h; h++)if (null != (a = arguments[h]))for (b in a)c = g[b], d = a[b], g !== d && (j && d && (n.isPlainObject(d) || (e = n.isArray(d))) ? (e ? (e = !1, f = c && n.isArray(c) ? c : []) : f = c && n.isPlainObject(c) ? c : {}, g[b] = n.extend(j, f, d)) : void 0 !== d && (g[b] = d)); + return g + }, n.extend({expando: "jQuery" + (m + Math.random()).replace(/\D/g, ""), isReady: !0, error: function (a) { + throw new Error(a) + }, noop: function () { + }, isFunction: function (a) { + return"function" === n.type(a) + }, isArray: Array.isArray, isWindow: function (a) { + return null != a && a === a.window + }, isNumeric: function (a) { + return!n.isArray(a) && a - parseFloat(a) >= 0 + }, isPlainObject: function (a) { + return"object" !== n.type(a) || a.nodeType || n.isWindow(a) ? !1 : a.constructor && !j.call(a.constructor.prototype, "isPrototypeOf") ? !1 : !0 + }, isEmptyObject: function (a) { + var b; + for (b in a)return!1; + return!0 + }, type: function (a) { + return null == a ? a + "" : "object" == typeof a || "function" == typeof a ? h[i.call(a)] || "object" : typeof a + }, globalEval: function (a) { + var b, c = eval; + a = n.trim(a), a && (1 === a.indexOf("use strict") ? (b = l.createElement("script"), b.text = a, l.head.appendChild(b).parentNode.removeChild(b)) : c(a)) + }, camelCase: function (a) { + return a.replace(p, "ms-").replace(q, r) + }, nodeName: function (a, b) { + return a.nodeName && a.nodeName.toLowerCase() === b.toLowerCase() + }, each: function (a, b, c) { + var d, e = 0, f = a.length, g = s(a); + if (c) { + if (g) { + for (; f > e; e++)if (d = b.apply(a[e], c), d === !1)break + } else for (e in a)if (d = b.apply(a[e], c), d === !1)break + } else if (g) { + for (; f > e; e++)if (d = b.call(a[e], e, a[e]), d === !1)break + } else for (e in a)if (d = b.call(a[e], e, a[e]), d === !1)break; + return a + }, trim: function (a) { + return null == a ? "" : (a + "").replace(o, "") + }, makeArray: function (a, b) { + var c = b || []; + return null != a && (s(Object(a)) ? n.merge(c, "string" == typeof a ? [a] : a) : f.call(c, a)), c + }, inArray: function (a, b, c) { + return null == b ? -1 : g.call(b, a, c) + }, merge: function (a, b) { + for (var c = +b.length, d = 0, e = a.length; c > d; d++)a[e++] = b[d]; + return a.length = e, a + }, grep: function (a, b, c) { + for (var d, e = [], f = 0, g = a.length, h = !c; g > f; f++)d = !b(a[f], f), d !== h && e.push(a[f]); + return e + }, map: function (a, b, c) { + var d, f = 0, g = a.length, h = s(a), i = []; + if (h)for (; g > f; f++)d = b(a[f], f, c), null != d && i.push(d); else for (f in a)d = b(a[f], f, c), null != d && i.push(d); + return e.apply([], i) + }, guid: 1, proxy: function (a, b) { + var c, e, f; + return"string" == typeof b && (c = a[b], b = a, a = c), n.isFunction(a) ? (e = d.call(arguments, 2), f = function () { + return a.apply(b || this, e.concat(d.call(arguments))) + }, f.guid = a.guid = a.guid || n.guid++, f) : void 0 + }, now: Date.now, support: k}), n.each("Boolean Number String Function Array Date RegExp Object Error".split(" "), function (a, b) { + h["[object " + b + "]"] = b.toLowerCase() + }); + function s(a) { + var b = a.length, c = n.type(a); + return"function" === c || n.isWindow(a) ? !1 : 1 === a.nodeType && b ? !0 : "array" === c || 0 === b || "number" == typeof b && b > 0 && b - 1 in a + } + + var t = function (a) { + var b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u = "sizzle" + -new Date, v = a.document, w = 0, x = 0, y = gb(), z = gb(), A = gb(), B = function (a, b) { + return a === b && (l = !0), 0 + }, C = "undefined", D = 1 << 31, E = {}.hasOwnProperty, F = [], G = F.pop, H = F.push, I = F.push, J = F.slice, K = F.indexOf || function (a) { + for (var b = 0, c = this.length; c > b; b++)if (this[b] === a)return b; + return-1 + }, L = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped", M = "[\\x20\\t\\r\\n\\f]", N = "(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+", O = N.replace("w", "w#"), P = "\\[" + M + "*(" + N + ")(?:" + M + "*([*^$|!~]?=)" + M + "*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + O + "))|)" + M + "*\\]", Q = ":(" + N + ")(?:\\((('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|((?:\\\\.|[^\\\\()[\\]]|" + P + ")*)|.*)\\)|)", R = new RegExp("^" + M + "+|((?:^|[^\\\\])(?:\\\\.)*)" + M + "+$", "g"), S = new RegExp("^" + M + "*," + M + "*"), T = new RegExp("^" + M + "*([>+~]|" + M + ")" + M + "*"), U = new RegExp("=" + M + "*([^\\]'\"]*?)" + M + "*\\]", "g"), V = new RegExp(Q), W = new RegExp("^" + O + "$"), X = {ID: new RegExp("^#(" + N + ")"), CLASS: new RegExp("^\\.(" + N + ")"), TAG: new RegExp("^(" + N.replace("w", "w*") + ")"), ATTR: new RegExp("^" + P), PSEUDO: new RegExp("^" + Q), CHILD: new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + M + "*(even|odd|(([+-]|)(\\d*)n|)" + M + "*(?:([+-]|)" + M + "*(\\d+)|))" + M + "*\\)|)", "i"), bool: new RegExp("^(?:" + L + ")$", "i"), needsContext: new RegExp("^" + M + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" + M + "*((?:-\\d)?\\d*)" + M + "*\\)|)(?=[^-]|$)", "i")}, Y = /^(?:input|select|textarea|button)$/i, Z = /^h\d$/i, $ = /^[^{]+\{\s*\[native \w/, _ = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/, ab = /[+~]/, bb = /'|\\/g, cb = new RegExp("\\\\([\\da-f]{1,6}" + M + "?|(" + M + ")|.)", "ig"), db = function (a, b, c) { + var d = "0x" + b - 65536; + return d !== d || c ? b : 0 > d ? String.fromCharCode(d + 65536) : String.fromCharCode(d >> 10 | 55296, 1023 & d | 56320) + }; + try { + I.apply(F = J.call(v.childNodes), v.childNodes), F[v.childNodes.length].nodeType + } catch (eb) { + I = {apply: F.length ? function (a, b) { + H.apply(a, J.call(b)) + } : function (a, b) { + var c = a.length, d = 0; + while (a[c++] = b[d++]); + a.length = c - 1 + }} + } + function fb(a, b, d, e) { + var f, h, j, k, l, o, r, s, w, x; + if ((b ? b.ownerDocument || b : v) !== n && m(b), b = b || n, d = d || [], !a || "string" != typeof a)return d; + if (1 !== (k = b.nodeType) && 9 !== k)return[]; + if (p && !e) { + if (f = _.exec(a))if (j = f[1]) { + if (9 === k) { + if (h = b.getElementById(j), !h || !h.parentNode)return d; + if (h.id === j)return d.push(h), d + } else if (b.ownerDocument && (h = b.ownerDocument.getElementById(j)) && t(b, h) && h.id === j)return d.push(h), d + } else { + if (f[2])return I.apply(d, b.getElementsByTagName(a)), d; + if ((j = f[3]) && c.getElementsByClassName && b.getElementsByClassName)return I.apply(d, b.getElementsByClassName(j)), d + } + if (c.qsa && (!q || !q.test(a))) { + if (s = r = u, w = b, x = 9 === k && a, 1 === k && "object" !== b.nodeName.toLowerCase()) { + o = g(a), (r = b.getAttribute("id")) ? s = r.replace(bb, "\\$&") : b.setAttribute("id", s), s = "[id='" + s + "'] ", l = o.length; + while (l--)o[l] = s + qb(o[l]); + w = ab.test(a) && ob(b.parentNode) || b, x = o.join(",") + } + if (x)try { + return I.apply(d, w.querySelectorAll(x)), d + } catch (y) { + } finally { + r || b.removeAttribute("id") + } + } + } + return i(a.replace(R, "$1"), b, d, e) + } + + function gb() { + var a = []; + + function b(c, e) { + return a.push(c + " ") > d.cacheLength && delete b[a.shift()], b[c + " "] = e + } + + return b + } + + function hb(a) { + return a[u] = !0, a + } + + function ib(a) { + var b = n.createElement("div"); + try { + return!!a(b) + } catch (c) { + return!1 + } finally { + b.parentNode && b.parentNode.removeChild(b), b = null + } + } + + function jb(a, b) { + var c = a.split("|"), e = a.length; + while (e--)d.attrHandle[c[e]] = b + } + + function kb(a, b) { + var c = b && a, d = c && 1 === a.nodeType && 1 === b.nodeType && (~b.sourceIndex || D) - (~a.sourceIndex || D); + if (d)return d; + if (c)while (c = c.nextSibling)if (c === b)return-1; + return a ? 1 : -1 + } + + function lb(a) { + return function (b) { + var c = b.nodeName.toLowerCase(); + return"input" === c && b.type === a + } + } + + function mb(a) { + return function (b) { + var c = b.nodeName.toLowerCase(); + return("input" === c || "button" === c) && b.type === a + } + } + + function nb(a) { + return hb(function (b) { + return b = +b, hb(function (c, d) { + var e, f = a([], c.length, b), g = f.length; + while (g--)c[e = f[g]] && (c[e] = !(d[e] = c[e])) + }) + }) + } + + function ob(a) { + return a && typeof a.getElementsByTagName !== C && a + } + + c = fb.support = {}, f = fb.isXML = function (a) { + var b = a && (a.ownerDocument || a).documentElement; + return b ? "HTML" !== b.nodeName : !1 + }, m = fb.setDocument = function (a) { + var b, e = a ? a.ownerDocument || a : v, g = e.defaultView; + return e !== n && 9 === e.nodeType && e.documentElement ? (n = e, o = e.documentElement, p = !f(e), g && g !== g.top && (g.addEventListener ? g.addEventListener("unload", function () { + m() + }, !1) : g.attachEvent && g.attachEvent("onunload", function () { + m() + })), c.attributes = ib(function (a) { + return a.className = "i", !a.getAttribute("className") + }), c.getElementsByTagName = ib(function (a) { + return a.appendChild(e.createComment("")), !a.getElementsByTagName("*").length + }), c.getElementsByClassName = $.test(e.getElementsByClassName) && ib(function (a) { + return a.innerHTML = "
    ", a.firstChild.className = "i", 2 === a.getElementsByClassName("i").length + }), c.getById = ib(function (a) { + return o.appendChild(a).id = u, !e.getElementsByName || !e.getElementsByName(u).length + }), c.getById ? (d.find.ID = function (a, b) { + if (typeof b.getElementById !== C && p) { + var c = b.getElementById(a); + return c && c.parentNode ? [c] : [] + } + }, d.filter.ID = function (a) { + var b = a.replace(cb, db); + return function (a) { + return a.getAttribute("id") === b + } + }) : (delete d.find.ID, d.filter.ID = function (a) { + var b = a.replace(cb, db); + return function (a) { + var c = typeof a.getAttributeNode !== C && a.getAttributeNode("id"); + return c && c.value === b + } + }), d.find.TAG = c.getElementsByTagName ? function (a, b) { + return typeof b.getElementsByTagName !== C ? b.getElementsByTagName(a) : void 0 + } : function (a, b) { + var c, d = [], e = 0, f = b.getElementsByTagName(a); + if ("*" === a) { + while (c = f[e++])1 === c.nodeType && d.push(c); + return d + } + return f + }, d.find.CLASS = c.getElementsByClassName && function (a, b) { + return typeof b.getElementsByClassName !== C && p ? b.getElementsByClassName(a) : void 0 + }, r = [], q = [], (c.qsa = $.test(e.querySelectorAll)) && (ib(function (a) { + a.innerHTML = "", a.querySelectorAll("[msallowclip^='']").length && q.push("[*^$]=" + M + "*(?:''|\"\")"), a.querySelectorAll("[selected]").length || q.push("\\[" + M + "*(?:value|" + L + ")"), a.querySelectorAll(":checked").length || q.push(":checked") + }), ib(function (a) { + var b = e.createElement("input"); + b.setAttribute("type", "hidden"), a.appendChild(b).setAttribute("name", "D"), a.querySelectorAll("[name=d]").length && q.push("name" + M + "*[*^$|!~]?="), a.querySelectorAll(":enabled").length || q.push(":enabled", ":disabled"), a.querySelectorAll("*,:x"), q.push(",.*:") + })), (c.matchesSelector = $.test(s = o.matches || o.webkitMatchesSelector || o.mozMatchesSelector || o.oMatchesSelector || o.msMatchesSelector)) && ib(function (a) { + c.disconnectedMatch = s.call(a, "div"), s.call(a, "[s!='']:x"), r.push("!=", Q) + }), q = q.length && new RegExp(q.join("|")), r = r.length && new RegExp(r.join("|")), b = $.test(o.compareDocumentPosition), t = b || $.test(o.contains) ? function (a, b) { + var c = 9 === a.nodeType ? a.documentElement : a, d = b && b.parentNode; + return a === d || !(!d || 1 !== d.nodeType || !(c.contains ? c.contains(d) : a.compareDocumentPosition && 16 & a.compareDocumentPosition(d))) + } : function (a, b) { + if (b)while (b = b.parentNode)if (b === a)return!0; + return!1 + }, B = b ? function (a, b) { + if (a === b)return l = !0, 0; + var d = !a.compareDocumentPosition - !b.compareDocumentPosition; + return d ? d : (d = (a.ownerDocument || a) === (b.ownerDocument || b) ? a.compareDocumentPosition(b) : 1, 1 & d || !c.sortDetached && b.compareDocumentPosition(a) === d ? a === e || a.ownerDocument === v && t(v, a) ? -1 : b === e || b.ownerDocument === v && t(v, b) ? 1 : k ? K.call(k, a) - K.call(k, b) : 0 : 4 & d ? -1 : 1) + } : function (a, b) { + if (a === b)return l = !0, 0; + var c, d = 0, f = a.parentNode, g = b.parentNode, h = [a], i = [b]; + if (!f || !g)return a === e ? -1 : b === e ? 1 : f ? -1 : g ? 1 : k ? K.call(k, a) - K.call(k, b) : 0; + if (f === g)return kb(a, b); + c = a; + while (c = c.parentNode)h.unshift(c); + c = b; + while (c = c.parentNode)i.unshift(c); + while (h[d] === i[d])d++; + return d ? kb(h[d], i[d]) : h[d] === v ? -1 : i[d] === v ? 1 : 0 + }, e) : n + }, fb.matches = function (a, b) { + return fb(a, null, null, b) + }, fb.matchesSelector = function (a, b) { + if ((a.ownerDocument || a) !== n && m(a), b = b.replace(U, "='$1']"), !(!c.matchesSelector || !p || r && r.test(b) || q && q.test(b)))try { + var d = s.call(a, b); + if (d || c.disconnectedMatch || a.document && 11 !== a.document.nodeType)return d + } catch (e) { + } + return fb(b, n, null, [a]).length > 0 + }, fb.contains = function (a, b) { + return(a.ownerDocument || a) !== n && m(a), t(a, b) + }, fb.attr = function (a, b) { + (a.ownerDocument || a) !== n && m(a); + var e = d.attrHandle[b.toLowerCase()], f = e && E.call(d.attrHandle, b.toLowerCase()) ? e(a, b, !p) : void 0; + return void 0 !== f ? f : c.attributes || !p ? a.getAttribute(b) : (f = a.getAttributeNode(b)) && f.specified ? f.value : null + }, fb.error = function (a) { + throw new Error("Syntax error, unrecognized expression: " + a) + }, fb.uniqueSort = function (a) { + var b, d = [], e = 0, f = 0; + if (l = !c.detectDuplicates, k = !c.sortStable && a.slice(0), a.sort(B), l) { + while (b = a[f++])b === a[f] && (e = d.push(f)); + while (e--)a.splice(d[e], 1) + } + return k = null, a + }, e = fb.getText = function (a) { + var b, c = "", d = 0, f = a.nodeType; + if (f) { + if (1 === f || 9 === f || 11 === f) { + if ("string" == typeof a.textContent)return a.textContent; + for (a = a.firstChild; a; a = a.nextSibling)c += e(a) + } else if (3 === f || 4 === f)return a.nodeValue + } else while (b = a[d++])c += e(b); + return c + }, d = fb.selectors = {cacheLength: 50, createPseudo: hb, match: X, attrHandle: {}, find: {}, relative: {">": {dir: "parentNode", first: !0}, " ": {dir: "parentNode"}, "+": {dir: "previousSibling", first: !0}, "~": {dir: "previousSibling"}}, preFilter: {ATTR: function (a) { + return a[1] = a[1].replace(cb, db), a[3] = (a[3] || a[4] || a[5] || "").replace(cb, db), "~=" === a[2] && (a[3] = " " + a[3] + " "), a.slice(0, 4) + }, CHILD: function (a) { + return a[1] = a[1].toLowerCase(), "nth" === a[1].slice(0, 3) ? (a[3] || fb.error(a[0]), a[4] = +(a[4] ? a[5] + (a[6] || 1) : 2 * ("even" === a[3] || "odd" === a[3])), a[5] = +(a[7] + a[8] || "odd" === a[3])) : a[3] && fb.error(a[0]), a + }, PSEUDO: function (a) { + var b, c = !a[6] && a[2]; + return X.CHILD.test(a[0]) ? null : (a[3] ? a[2] = a[4] || a[5] || "" : c && V.test(c) && (b = g(c, !0)) && (b = c.indexOf(")", c.length - b) - c.length) && (a[0] = a[0].slice(0, b), a[2] = c.slice(0, b)), a.slice(0, 3)) + }}, filter: {TAG: function (a) { + var b = a.replace(cb, db).toLowerCase(); + return"*" === a ? function () { + return!0 + } : function (a) { + return a.nodeName && a.nodeName.toLowerCase() === b + } + }, CLASS: function (a) { + var b = y[a + " "]; + return b || (b = new RegExp("(^|" + M + ")" + a + "(" + M + "|$)")) && y(a, function (a) { + return b.test("string" == typeof a.className && a.className || typeof a.getAttribute !== C && a.getAttribute("class") || "") + }) + }, ATTR: function (a, b, c) { + return function (d) { + var e = fb.attr(d, a); + return null == e ? "!=" === b : b ? (e += "", "=" === b ? e === c : "!=" === b ? e !== c : "^=" === b ? c && 0 === e.indexOf(c) : "*=" === b ? c && e.indexOf(c) > -1 : "$=" === b ? c && e.slice(-c.length) === c : "~=" === b ? (" " + e + " ").indexOf(c) > -1 : "|=" === b ? e === c || e.slice(0, c.length + 1) === c + "-" : !1) : !0 + } + }, CHILD: function (a, b, c, d, e) { + var f = "nth" !== a.slice(0, 3), g = "last" !== a.slice(-4), h = "of-type" === b; + return 1 === d && 0 === e ? function (a) { + return!!a.parentNode + } : function (b, c, i) { + var j, k, l, m, n, o, p = f !== g ? "nextSibling" : "previousSibling", q = b.parentNode, r = h && b.nodeName.toLowerCase(), s = !i && !h; + if (q) { + if (f) { + while (p) { + l = b; + while (l = l[p])if (h ? l.nodeName.toLowerCase() === r : 1 === l.nodeType)return!1; + o = p = "only" === a && !o && "nextSibling" + } + return!0 + } + if (o = [g ? q.firstChild : q.lastChild], g && s) { + k = q[u] || (q[u] = {}), j = k[a] || [], n = j[0] === w && j[1], m = j[0] === w && j[2], l = n && q.childNodes[n]; + while (l = ++n && l && l[p] || (m = n = 0) || o.pop())if (1 === l.nodeType && ++m && l === b) { + k[a] = [w, n, m]; + break + } + } else if (s && (j = (b[u] || (b[u] = {}))[a]) && j[0] === w)m = j[1]; else while (l = ++n && l && l[p] || (m = n = 0) || o.pop())if ((h ? l.nodeName.toLowerCase() === r : 1 === l.nodeType) && ++m && (s && ((l[u] || (l[u] = {}))[a] = [w, m]), l === b))break; + return m -= e, m === d || m % d === 0 && m / d >= 0 + } + } + }, PSEUDO: function (a, b) { + var c, e = d.pseudos[a] || d.setFilters[a.toLowerCase()] || fb.error("unsupported pseudo: " + a); + return e[u] ? e(b) : e.length > 1 ? (c = [a, a, "", b], d.setFilters.hasOwnProperty(a.toLowerCase()) ? hb(function (a, c) { + var d, f = e(a, b), g = f.length; + while (g--)d = K.call(a, f[g]), a[d] = !(c[d] = f[g]) + }) : function (a) { + return e(a, 0, c) + }) : e + }}, pseudos: {not: hb(function (a) { + var b = [], c = [], d = h(a.replace(R, "$1")); + return d[u] ? hb(function (a, b, c, e) { + var f, g = d(a, null, e, []), h = a.length; + while (h--)(f = g[h]) && (a[h] = !(b[h] = f)) + }) : function (a, e, f) { + return b[0] = a, d(b, null, f, c), !c.pop() + } + }), has: hb(function (a) { + return function (b) { + return fb(a, b).length > 0 + } + }), contains: hb(function (a) { + return function (b) { + return(b.textContent || b.innerText || e(b)).indexOf(a) > -1 + } + }), lang: hb(function (a) { + return W.test(a || "") || fb.error("unsupported lang: " + a), a = a.replace(cb, db).toLowerCase(), function (b) { + var c; + do if (c = p ? b.lang : b.getAttribute("xml:lang") || b.getAttribute("lang"))return c = c.toLowerCase(), c === a || 0 === c.indexOf(a + "-"); while ((b = b.parentNode) && 1 === b.nodeType); + return!1 + } + }), target: function (b) { + var c = a.location && a.location.hash; + return c && c.slice(1) === b.id + }, root: function (a) { + return a === o + }, focus: function (a) { + return a === n.activeElement && (!n.hasFocus || n.hasFocus()) && !!(a.type || a.href || ~a.tabIndex) + }, enabled: function (a) { + return a.disabled === !1 + }, disabled: function (a) { + return a.disabled === !0 + }, checked: function (a) { + var b = a.nodeName.toLowerCase(); + return"input" === b && !!a.checked || "option" === b && !!a.selected + }, selected: function (a) { + return a.parentNode && a.parentNode.selectedIndex, a.selected === !0 + }, empty: function (a) { + for (a = a.firstChild; a; a = a.nextSibling)if (a.nodeType < 6)return!1; + return!0 + }, parent: function (a) { + return!d.pseudos.empty(a) + }, header: function (a) { + return Z.test(a.nodeName) + }, input: function (a) { + return Y.test(a.nodeName) + }, button: function (a) { + var b = a.nodeName.toLowerCase(); + return"input" === b && "button" === a.type || "button" === b + }, text: function (a) { + var b; + return"input" === a.nodeName.toLowerCase() && "text" === a.type && (null == (b = a.getAttribute("type")) || "text" === b.toLowerCase()) + }, first: nb(function () { + return[0] + }), last: nb(function (a, b) { + return[b - 1] + }), eq: nb(function (a, b, c) { + return[0 > c ? c + b : c] + }), even: nb(function (a, b) { + for (var c = 0; b > c; c += 2)a.push(c); + return a + }), odd: nb(function (a, b) { + for (var c = 1; b > c; c += 2)a.push(c); + return a + }), lt: nb(function (a, b, c) { + for (var d = 0 > c ? c + b : c; --d >= 0;)a.push(d); + return a + }), gt: nb(function (a, b, c) { + for (var d = 0 > c ? c + b : c; ++d < b;)a.push(d); + return a + })}}, d.pseudos.nth = d.pseudos.eq; + for (b in{radio: !0, checkbox: !0, file: !0, password: !0, image: !0})d.pseudos[b] = lb(b); + for (b in{submit: !0, reset: !0})d.pseudos[b] = mb(b); + function pb() { + } + + pb.prototype = d.filters = d.pseudos, d.setFilters = new pb, g = fb.tokenize = function (a, b) { + var c, e, f, g, h, i, j, k = z[a + " "]; + if (k)return b ? 0 : k.slice(0); + h = a, i = [], j = d.preFilter; + while (h) { + (!c || (e = S.exec(h))) && (e && (h = h.slice(e[0].length) || h), i.push(f = [])), c = !1, (e = T.exec(h)) && (c = e.shift(), f.push({value: c, type: e[0].replace(R, " ")}), h = h.slice(c.length)); + for (g in d.filter)!(e = X[g].exec(h)) || j[g] && !(e = j[g](e)) || (c = e.shift(), f.push({value: c, type: g, matches: e}), h = h.slice(c.length)); + if (!c)break + } + return b ? h.length : h ? fb.error(a) : z(a, i).slice(0) + }; + function qb(a) { + for (var b = 0, c = a.length, d = ""; c > b; b++)d += a[b].value; + return d + } + + function rb(a, b, c) { + var d = b.dir, e = c && "parentNode" === d, f = x++; + return b.first ? function (b, c, f) { + while (b = b[d])if (1 === b.nodeType || e)return a(b, c, f) + } : function (b, c, g) { + var h, i, j = [w, f]; + if (g) { + while (b = b[d])if ((1 === b.nodeType || e) && a(b, c, g))return!0 + } else while (b = b[d])if (1 === b.nodeType || e) { + if (i = b[u] || (b[u] = {}), (h = i[d]) && h[0] === w && h[1] === f)return j[2] = h[2]; + if (i[d] = j, j[2] = a(b, c, g))return!0 + } + } + } + + function sb(a) { + return a.length > 1 ? function (b, c, d) { + var e = a.length; + while (e--)if (!a[e](b, c, d))return!1; + return!0 + } : a[0] + } + + function tb(a, b, c) { + for (var d = 0, e = b.length; e > d; d++)fb(a, b[d], c); + return c + } + + function ub(a, b, c, d, e) { + for (var f, g = [], h = 0, i = a.length, j = null != b; i > h; h++)(f = a[h]) && (!c || c(f, d, e)) && (g.push(f), j && b.push(h)); + return g + } + + function vb(a, b, c, d, e, f) { + return d && !d[u] && (d = vb(d)), e && !e[u] && (e = vb(e, f)), hb(function (f, g, h, i) { + var j, k, l, m = [], n = [], o = g.length, p = f || tb(b || "*", h.nodeType ? [h] : h, []), q = !a || !f && b ? p : ub(p, m, a, h, i), r = c ? e || (f ? a : o || d) ? [] : g : q; + if (c && c(q, r, h, i), d) { + j = ub(r, n), d(j, [], h, i), k = j.length; + while (k--)(l = j[k]) && (r[n[k]] = !(q[n[k]] = l)) + } + if (f) { + if (e || a) { + if (e) { + j = [], k = r.length; + while (k--)(l = r[k]) && j.push(q[k] = l); + e(null, r = [], j, i) + } + k = r.length; + while (k--)(l = r[k]) && (j = e ? K.call(f, l) : m[k]) > -1 && (f[j] = !(g[j] = l)) + } + } else r = ub(r === g ? r.splice(o, r.length) : r), e ? e(null, g, r, i) : I.apply(g, r) + }) + } + + function wb(a) { + for (var b, c, e, f = a.length, g = d.relative[a[0].type], h = g || d.relative[" "], i = g ? 1 : 0, k = rb(function (a) { + return a === b + }, h, !0), l = rb(function (a) { + return K.call(b, a) > -1 + }, h, !0), m = [function (a, c, d) { + return!g && (d || c !== j) || ((b = c).nodeType ? k(a, c, d) : l(a, c, d)) + }]; f > i; i++)if (c = d.relative[a[i].type])m = [rb(sb(m), c)]; else { + if (c = d.filter[a[i].type].apply(null, a[i].matches), c[u]) { + for (e = ++i; f > e; e++)if (d.relative[a[e].type])break; + return vb(i > 1 && sb(m), i > 1 && qb(a.slice(0, i - 1).concat({value: " " === a[i - 2].type ? "*" : ""})).replace(R, "$1"), c, e > i && wb(a.slice(i, e)), f > e && wb(a = a.slice(e)), f > e && qb(a)) + } + m.push(c) + } + return sb(m) + } + + function xb(a, b) { + var c = b.length > 0, e = a.length > 0, f = function (f, g, h, i, k) { + var l, m, o, p = 0, q = "0", r = f && [], s = [], t = j, u = f || e && d.find.TAG("*", k), v = w += null == t ? 1 : Math.random() || .1, x = u.length; + for (k && (j = g !== n && g); q !== x && null != (l = u[q]); q++) { + if (e && l) { + m = 0; + while (o = a[m++])if (o(l, g, h)) { + i.push(l); + break + } + k && (w = v) + } + c && ((l = !o && l) && p--, f && r.push(l)) + } + if (p += q, c && q !== p) { + m = 0; + while (o = b[m++])o(r, s, g, h); + if (f) { + if (p > 0)while (q--)r[q] || s[q] || (s[q] = G.call(i)); + s = ub(s) + } + I.apply(i, s), k && !f && s.length > 0 && p + b.length > 1 && fb.uniqueSort(i) + } + return k && (w = v, j = t), r + }; + return c ? hb(f) : f + } + + return h = fb.compile = function (a, b) { + var c, d = [], e = [], f = A[a + " "]; + if (!f) { + b || (b = g(a)), c = b.length; + while (c--)f = wb(b[c]), f[u] ? d.push(f) : e.push(f); + f = A(a, xb(e, d)), f.selector = a + } + return f + }, i = fb.select = function (a, b, e, f) { + var i, j, k, l, m, n = "function" == typeof a && a, o = !f && g(a = n.selector || a); + if (e = e || [], 1 === o.length) { + if (j = o[0] = o[0].slice(0), j.length > 2 && "ID" === (k = j[0]).type && c.getById && 9 === b.nodeType && p && d.relative[j[1].type]) { + if (b = (d.find.ID(k.matches[0].replace(cb, db), b) || [])[0], !b)return e; + n && (b = b.parentNode), a = a.slice(j.shift().value.length) + } + i = X.needsContext.test(a) ? 0 : j.length; + while (i--) { + if (k = j[i], d.relative[l = k.type])break; + if ((m = d.find[l]) && (f = m(k.matches[0].replace(cb, db), ab.test(j[0].type) && ob(b.parentNode) || b))) { + if (j.splice(i, 1), a = f.length && qb(j), !a)return I.apply(e, f), e; + break + } + } + } + return(n || h(a, o))(f, b, !p, e, ab.test(a) && ob(b.parentNode) || b), e + }, c.sortStable = u.split("").sort(B).join("") === u, c.detectDuplicates = !!l, m(), c.sortDetached = ib(function (a) { + return 1 & a.compareDocumentPosition(n.createElement("div")) + }), ib(function (a) { + return a.innerHTML = "
    ", "#" === a.firstChild.getAttribute("href") + }) || jb("type|href|height|width", function (a, b, c) { + return c ? void 0 : a.getAttribute(b, "type" === b.toLowerCase() ? 1 : 2) + }), c.attributes && ib(function (a) { + return a.innerHTML = "", a.firstChild.setAttribute("value", ""), "" === a.firstChild.getAttribute("value") + }) || jb("value", function (a, b, c) { + return c || "input" !== a.nodeName.toLowerCase() ? void 0 : a.defaultValue + }), ib(function (a) { + return null == a.getAttribute("disabled") + }) || jb(L, function (a, b, c) { + var d; + return c ? void 0 : a[b] === !0 ? b.toLowerCase() : (d = a.getAttributeNode(b)) && d.specified ? d.value : null + }), fb + }(a); + n.find = t, n.expr = t.selectors, n.expr[":"] = n.expr.pseudos, n.unique = t.uniqueSort, n.text = t.getText, n.isXMLDoc = t.isXML, n.contains = t.contains; + var u = n.expr.match.needsContext, v = /^<(\w+)\s*\/?>(?:<\/\1>|)$/, w = /^.[^:#\[\.,]*$/; + + function x(a, b, c) { + if (n.isFunction(b))return n.grep(a, function (a, d) { + return!!b.call(a, d, a) !== c + }); + if (b.nodeType)return n.grep(a, function (a) { + return a === b !== c + }); + if ("string" == typeof b) { + if (w.test(b))return n.filter(b, a, c); + b = n.filter(b, a) + } + return n.grep(a, function (a) { + return g.call(b, a) >= 0 !== c + }) + } + + n.filter = function (a, b, c) { + var d = b[0]; + return c && (a = ":not(" + a + ")"), 1 === b.length && 1 === d.nodeType ? n.find.matchesSelector(d, a) ? [d] : [] : n.find.matches(a, n.grep(b, function (a) { + return 1 === a.nodeType + })) + }, n.fn.extend({find: function (a) { + var b, c = this.length, d = [], e = this; + if ("string" != typeof a)return this.pushStack(n(a).filter(function () { + for (b = 0; c > b; b++)if (n.contains(e[b], this))return!0 + })); + for (b = 0; c > b; b++)n.find(a, e[b], d); + return d = this.pushStack(c > 1 ? n.unique(d) : d), d.selector = this.selector ? this.selector + " " + a : a, d + }, filter: function (a) { + return this.pushStack(x(this, a || [], !1)) + }, not: function (a) { + return this.pushStack(x(this, a || [], !0)) + }, is: function (a) { + return!!x(this, "string" == typeof a && u.test(a) ? n(a) : a || [], !1).length + }}); + var y, z = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/, A = n.fn.init = function (a, b) { + var c, d; + if (!a)return this; + if ("string" == typeof a) { + if (c = "<" === a[0] && ">" === a[a.length - 1] && a.length >= 3 ? [null, a, null] : z.exec(a), !c || !c[1] && b)return!b || b.jquery ? (b || y).find(a) : this.constructor(b).find(a); + if (c[1]) { + if (b = b instanceof n ? b[0] : b, n.merge(this, n.parseHTML(c[1], b && b.nodeType ? b.ownerDocument || b : l, !0)), v.test(c[1]) && n.isPlainObject(b))for (c in b)n.isFunction(this[c]) ? this[c](b[c]) : this.attr(c, b[c]); + return this + } + return d = l.getElementById(c[2]), d && d.parentNode && (this.length = 1, this[0] = d), this.context = l, this.selector = a, this + } + return a.nodeType ? (this.context = this[0] = a, this.length = 1, this) : n.isFunction(a) ? "undefined" != typeof y.ready ? y.ready(a) : a(n) : (void 0 !== a.selector && (this.selector = a.selector, this.context = a.context), n.makeArray(a, this)) + }; + A.prototype = n.fn, y = n(l); + var B = /^(?:parents|prev(?:Until|All))/, C = {children: !0, contents: !0, next: !0, prev: !0}; + n.extend({dir: function (a, b, c) { + var d = [], e = void 0 !== c; + while ((a = a[b]) && 9 !== a.nodeType)if (1 === a.nodeType) { + if (e && n(a).is(c))break; + d.push(a) + } + return d + }, sibling: function (a, b) { + for (var c = []; a; a = a.nextSibling)1 === a.nodeType && a !== b && c.push(a); + return c + }}), n.fn.extend({has: function (a) { + var b = n(a, this), c = b.length; + return this.filter(function () { + for (var a = 0; c > a; a++)if (n.contains(this, b[a]))return!0 + }) + }, closest: function (a, b) { + for (var c, d = 0, e = this.length, f = [], g = u.test(a) || "string" != typeof a ? n(a, b || this.context) : 0; e > d; d++)for (c = this[d]; c && c !== b; c = c.parentNode)if (c.nodeType < 11 && (g ? g.index(c) > -1 : 1 === c.nodeType && n.find.matchesSelector(c, a))) { + f.push(c); + break + } + return this.pushStack(f.length > 1 ? n.unique(f) : f) + }, index: function (a) { + return a ? "string" == typeof a ? g.call(n(a), this[0]) : g.call(this, a.jquery ? a[0] : a) : this[0] && this[0].parentNode ? this.first().prevAll().length : -1 + }, add: function (a, b) { + return this.pushStack(n.unique(n.merge(this.get(), n(a, b)))) + }, addBack: function (a) { + return this.add(null == a ? this.prevObject : this.prevObject.filter(a)) + }}); + function D(a, b) { + while ((a = a[b]) && 1 !== a.nodeType); + return a + } + + n.each({parent: function (a) { + var b = a.parentNode; + return b && 11 !== b.nodeType ? b : null + }, parents: function (a) { + return n.dir(a, "parentNode") + }, parentsUntil: function (a, b, c) { + return n.dir(a, "parentNode", c) + }, next: function (a) { + return D(a, "nextSibling") + }, prev: function (a) { + return D(a, "previousSibling") + }, nextAll: function (a) { + return n.dir(a, "nextSibling") + }, prevAll: function (a) { + return n.dir(a, "previousSibling") + }, nextUntil: function (a, b, c) { + return n.dir(a, "nextSibling", c) + }, prevUntil: function (a, b, c) { + return n.dir(a, "previousSibling", c) + }, siblings: function (a) { + return n.sibling((a.parentNode || {}).firstChild, a) + }, children: function (a) { + return n.sibling(a.firstChild) + }, contents: function (a) { + return a.contentDocument || n.merge([], a.childNodes) + }}, function (a, b) { + n.fn[a] = function (c, d) { + var e = n.map(this, b, c); + return"Until" !== a.slice(-5) && (d = c), d && "string" == typeof d && (e = n.filter(d, e)), this.length > 1 && (C[a] || n.unique(e), B.test(a) && e.reverse()), this.pushStack(e) + } + }); + var E = /\S+/g, F = {}; + + function G(a) { + var b = F[a] = {}; + return n.each(a.match(E) || [], function (a, c) { + b[c] = !0 + }), b + } + + n.Callbacks = function (a) { + a = "string" == typeof a ? F[a] || G(a) : n.extend({}, a); + var b, c, d, e, f, g, h = [], i = !a.once && [], j = function (l) { + for (b = a.memory && l, c = !0, g = e || 0, e = 0, f = h.length, d = !0; h && f > g; g++)if (h[g].apply(l[0], l[1]) === !1 && a.stopOnFalse) { + b = !1; + break + } + d = !1, h && (i ? i.length && j(i.shift()) : b ? h = [] : k.disable()) + }, k = {add: function () { + if (h) { + var c = h.length; + !function g(b) { + n.each(b, function (b, c) { + var d = n.type(c); + "function" === d ? a.unique && k.has(c) || h.push(c) : c && c.length && "string" !== d && g(c) + }) + }(arguments), d ? f = h.length : b && (e = c, j(b)) + } + return this + }, remove: function () { + return h && n.each(arguments, function (a, b) { + var c; + while ((c = n.inArray(b, h, c)) > -1)h.splice(c, 1), d && (f >= c && f--, g >= c && g--) + }), this + }, has: function (a) { + return a ? n.inArray(a, h) > -1 : !(!h || !h.length) + }, empty: function () { + return h = [], f = 0, this + }, disable: function () { + return h = i = b = void 0, this + }, disabled: function () { + return!h + }, lock: function () { + return i = void 0, b || k.disable(), this + }, locked: function () { + return!i + }, fireWith: function (a, b) { + return!h || c && !i || (b = b || [], b = [a, b.slice ? b.slice() : b], d ? i.push(b) : j(b)), this + }, fire: function () { + return k.fireWith(this, arguments), this + }, fired: function () { + return!!c + }}; + return k + }, n.extend({Deferred: function (a) { + var b = [ + ["resolve", "done", n.Callbacks("once memory"), "resolved"], + ["reject", "fail", n.Callbacks("once memory"), "rejected"], + ["notify", "progress", n.Callbacks("memory")] + ], c = "pending", d = {state: function () { + return c + }, always: function () { + return e.done(arguments).fail(arguments), this + }, then: function () { + var a = arguments; + return n.Deferred(function (c) { + n.each(b, function (b, f) { + var g = n.isFunction(a[b]) && a[b]; + e[f[1]](function () { + var a = g && g.apply(this, arguments); + a && n.isFunction(a.promise) ? a.promise().done(c.resolve).fail(c.reject).progress(c.notify) : c[f[0] + "With"](this === d ? c.promise() : this, g ? [a] : arguments) + }) + }), a = null + }).promise() + }, promise: function (a) { + return null != a ? n.extend(a, d) : d + }}, e = {}; + return d.pipe = d.then, n.each(b, function (a, f) { + var g = f[2], h = f[3]; + d[f[1]] = g.add, h && g.add(function () { + c = h + }, b[1 ^ a][2].disable, b[2][2].lock), e[f[0]] = function () { + return e[f[0] + "With"](this === e ? d : this, arguments), this + }, e[f[0] + "With"] = g.fireWith + }), d.promise(e), a && a.call(e, e), e + }, when: function (a) { + var b = 0, c = d.call(arguments), e = c.length, f = 1 !== e || a && n.isFunction(a.promise) ? e : 0, g = 1 === f ? a : n.Deferred(), h = function (a, b, c) { + return function (e) { + b[a] = this, c[a] = arguments.length > 1 ? d.call(arguments) : e, c === i ? g.notifyWith(b, c) : --f || g.resolveWith(b, c) + } + }, i, j, k; + if (e > 1)for (i = new Array(e), j = new Array(e), k = new Array(e); e > b; b++)c[b] && n.isFunction(c[b].promise) ? c[b].promise().done(h(b, k, c)).fail(g.reject).progress(h(b, j, i)) : --f; + return f || g.resolveWith(k, c), g.promise() + }}); + var H; + n.fn.ready = function (a) { + return n.ready.promise().done(a), this + }, n.extend({isReady: !1, readyWait: 1, holdReady: function (a) { + a ? n.readyWait++ : n.ready(!0) + }, ready: function (a) { + (a === !0 ? --n.readyWait : n.isReady) || (n.isReady = !0, a !== !0 && --n.readyWait > 0 || (H.resolveWith(l, [n]), n.fn.triggerHandler && (n(l).triggerHandler("ready"), n(l).off("ready")))) + }}); + function I() { + l.removeEventListener("DOMContentLoaded", I, !1), a.removeEventListener("load", I, !1), n.ready() + } + + n.ready.promise = function (b) { + return H || (H = n.Deferred(), "complete" === l.readyState ? setTimeout(n.ready) : (l.addEventListener("DOMContentLoaded", I, !1), a.addEventListener("load", I, !1))), H.promise(b) + }, n.ready.promise(); + var J = n.access = function (a, b, c, d, e, f, g) { + var h = 0, i = a.length, j = null == c; + if ("object" === n.type(c)) { + e = !0; + for (h in c)n.access(a, b, h, c[h], !0, f, g) + } else if (void 0 !== d && (e = !0, n.isFunction(d) || (g = !0), j && (g ? (b.call(a, d), b = null) : (j = b, b = function (a, b, c) { + return j.call(n(a), c) + })), b))for (; i > h; h++)b(a[h], c, g ? d : d.call(a[h], h, b(a[h], c))); + return e ? a : j ? b.call(a) : i ? b(a[0], c) : f + }; + n.acceptData = function (a) { + return 1 === a.nodeType || 9 === a.nodeType || !+a.nodeType + }; + function K() { + Object.defineProperty(this.cache = {}, 0, {get: function () { + return{} + }}), this.expando = n.expando + Math.random() + } + + K.uid = 1, K.accepts = n.acceptData, K.prototype = {key: function (a) { + if (!K.accepts(a))return 0; + var b = {}, c = a[this.expando]; + if (!c) { + c = K.uid++; + try { + b[this.expando] = {value: c}, Object.defineProperties(a, b) + } catch (d) { + b[this.expando] = c, n.extend(a, b) + } + } + return this.cache[c] || (this.cache[c] = {}), c + }, set: function (a, b, c) { + var d, e = this.key(a), f = this.cache[e]; + if ("string" == typeof b)f[b] = c; else if (n.isEmptyObject(f))n.extend(this.cache[e], b); else for (d in b)f[d] = b[d]; + return f + }, get: function (a, b) { + var c = this.cache[this.key(a)]; + return void 0 === b ? c : c[b] + }, access: function (a, b, c) { + var d; + return void 0 === b || b && "string" == typeof b && void 0 === c ? (d = this.get(a, b), void 0 !== d ? d : this.get(a, n.camelCase(b))) : (this.set(a, b, c), void 0 !== c ? c : b) + }, remove: function (a, b) { + var c, d, e, f = this.key(a), g = this.cache[f]; + if (void 0 === b)this.cache[f] = {}; else { + n.isArray(b) ? d = b.concat(b.map(n.camelCase)) : (e = n.camelCase(b), b in g ? d = [b, e] : (d = e, d = d in g ? [d] : d.match(E) || [])), c = d.length; + while (c--)delete g[d[c]] + } + }, hasData: function (a) { + return!n.isEmptyObject(this.cache[a[this.expando]] || {}) + }, discard: function (a) { + a[this.expando] && delete this.cache[a[this.expando]] + }}; + var L = new K, M = new K, N = /^(?:\{[\w\W]*\}|\[[\w\W]*\])$/, O = /([A-Z])/g; + + function P(a, b, c) { + var d; + if (void 0 === c && 1 === a.nodeType)if (d = "data-" + b.replace(O, "-$1").toLowerCase(), c = a.getAttribute(d), "string" == typeof c) { + try { + c = "true" === c ? !0 : "false" === c ? !1 : "null" === c ? null : +c + "" === c ? +c : N.test(c) ? n.parseJSON(c) : c + } catch (e) { + } + M.set(a, b, c) + } else c = void 0; + return c + } + + n.extend({hasData: function (a) { + return M.hasData(a) || L.hasData(a) + }, data: function (a, b, c) { + return M.access(a, b, c) + }, removeData: function (a, b) { + M.remove(a, b) + }, _data: function (a, b, c) { + return L.access(a, b, c) + }, _removeData: function (a, b) { + L.remove(a, b) + }}), n.fn.extend({data: function (a, b) { + var c, d, e, f = this[0], g = f && f.attributes; + if (void 0 === a) { + if (this.length && (e = M.get(f), 1 === f.nodeType && !L.get(f, "hasDataAttrs"))) { + c = g.length; + while (c--)g[c] && (d = g[c].name, 0 === d.indexOf("data-") && (d = n.camelCase(d.slice(5)), P(f, d, e[d]))); + L.set(f, "hasDataAttrs", !0) + } + return e + } + return"object" == typeof a ? this.each(function () { + M.set(this, a) + }) : J(this, function (b) { + var c, d = n.camelCase(a); + if (f && void 0 === b) { + if (c = M.get(f, a), void 0 !== c)return c; + if (c = M.get(f, d), void 0 !== c)return c; + if (c = P(f, d, void 0), void 0 !== c)return c + } else this.each(function () { + var c = M.get(this, d); + M.set(this, d, b), -1 !== a.indexOf("-") && void 0 !== c && M.set(this, a, b) + }) + }, null, b, arguments.length > 1, null, !0) + }, removeData: function (a) { + return this.each(function () { + M.remove(this, a) + }) + }}), n.extend({queue: function (a, b, c) { + var d; + return a ? (b = (b || "fx") + "queue", d = L.get(a, b), c && (!d || n.isArray(c) ? d = L.access(a, b, n.makeArray(c)) : d.push(c)), d || []) : void 0 + }, dequeue: function (a, b) { + b = b || "fx"; + var c = n.queue(a, b), d = c.length, e = c.shift(), f = n._queueHooks(a, b), g = function () { + n.dequeue(a, b) + }; + "inprogress" === e && (e = c.shift(), d--), e && ("fx" === b && c.unshift("inprogress"), delete f.stop, e.call(a, g, f)), !d && f && f.empty.fire() + }, _queueHooks: function (a, b) { + var c = b + "queueHooks"; + return L.get(a, c) || L.access(a, c, {empty: n.Callbacks("once memory").add(function () { + L.remove(a, [b + "queue", c]) + })}) + }}), n.fn.extend({queue: function (a, b) { + var c = 2; + return"string" != typeof a && (b = a, a = "fx", c--), arguments.length < c ? n.queue(this[0], a) : void 0 === b ? this : this.each(function () { + var c = n.queue(this, a, b); + n._queueHooks(this, a), "fx" === a && "inprogress" !== c[0] && n.dequeue(this, a) + }) + }, dequeue: function (a) { + return this.each(function () { + n.dequeue(this, a) + }) + }, clearQueue: function (a) { + return this.queue(a || "fx", []) + }, promise: function (a, b) { + var c, d = 1, e = n.Deferred(), f = this, g = this.length, h = function () { + --d || e.resolveWith(f, [f]) + }; + "string" != typeof a && (b = a, a = void 0), a = a || "fx"; + while (g--)c = L.get(f[g], a + "queueHooks"), c && c.empty && (d++, c.empty.add(h)); + return h(), e.promise(b) + }}); + var Q = /[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source, R = ["Top", "Right", "Bottom", "Left"], S = function (a, b) { + return a = b || a, "none" === n.css(a, "display") || !n.contains(a.ownerDocument, a) + }, T = /^(?:checkbox|radio)$/i; + !function () { + var a = l.createDocumentFragment(), b = a.appendChild(l.createElement("div")), c = l.createElement("input"); + c.setAttribute("type", "radio"), c.setAttribute("checked", "checked"), c.setAttribute("name", "t"), b.appendChild(c), k.checkClone = b.cloneNode(!0).cloneNode(!0).lastChild.checked, b.innerHTML = "", k.noCloneChecked = !!b.cloneNode(!0).lastChild.defaultValue + }(); + var U = "undefined"; + k.focusinBubbles = "onfocusin"in a; + var V = /^key/, W = /^(?:mouse|pointer|contextmenu)|click/, X = /^(?:focusinfocus|focusoutblur)$/, Y = /^([^.]*)(?:\.(.+)|)$/; + + function Z() { + return!0 + } + + function $() { + return!1 + } + + function _() { + try { + return l.activeElement + } catch (a) { + } + } + + n.event = {global: {}, add: function (a, b, c, d, e) { + var f, g, h, i, j, k, l, m, o, p, q, r = L.get(a); + if (r) { + c.handler && (f = c, c = f.handler, e = f.selector), c.guid || (c.guid = n.guid++), (i = r.events) || (i = r.events = {}), (g = r.handle) || (g = r.handle = function (b) { + return typeof n !== U && n.event.triggered !== b.type ? n.event.dispatch.apply(a, arguments) : void 0 + }), b = (b || "").match(E) || [""], j = b.length; + while (j--)h = Y.exec(b[j]) || [], o = q = h[1], p = (h[2] || "").split(".").sort(), o && (l = n.event.special[o] || {}, o = (e ? l.delegateType : l.bindType) || o, l = n.event.special[o] || {}, k = n.extend({type: o, origType: q, data: d, handler: c, guid: c.guid, selector: e, needsContext: e && n.expr.match.needsContext.test(e), namespace: p.join(".")}, f), (m = i[o]) || (m = i[o] = [], m.delegateCount = 0, l.setup && l.setup.call(a, d, p, g) !== !1 || a.addEventListener && a.addEventListener(o, g, !1)), l.add && (l.add.call(a, k), k.handler.guid || (k.handler.guid = c.guid)), e ? m.splice(m.delegateCount++, 0, k) : m.push(k), n.event.global[o] = !0) + } + }, remove: function (a, b, c, d, e) { + var f, g, h, i, j, k, l, m, o, p, q, r = L.hasData(a) && L.get(a); + if (r && (i = r.events)) { + b = (b || "").match(E) || [""], j = b.length; + while (j--)if (h = Y.exec(b[j]) || [], o = q = h[1], p = (h[2] || "").split(".").sort(), o) { + l = n.event.special[o] || {}, o = (d ? l.delegateType : l.bindType) || o, m = i[o] || [], h = h[2] && new RegExp("(^|\\.)" + p.join("\\.(?:.*\\.|)") + "(\\.|$)"), g = f = m.length; + while (f--)k = m[f], !e && q !== k.origType || c && c.guid !== k.guid || h && !h.test(k.namespace) || d && d !== k.selector && ("**" !== d || !k.selector) || (m.splice(f, 1), k.selector && m.delegateCount--, l.remove && l.remove.call(a, k)); + g && !m.length && (l.teardown && l.teardown.call(a, p, r.handle) !== !1 || n.removeEvent(a, o, r.handle), delete i[o]) + } else for (o in i)n.event.remove(a, o + b[j], c, d, !0); + n.isEmptyObject(i) && (delete r.handle, L.remove(a, "events")) + } + }, trigger: function (b, c, d, e) { + var f, g, h, i, k, m, o, p = [d || l], q = j.call(b, "type") ? b.type : b, r = j.call(b, "namespace") ? b.namespace.split(".") : []; + if (g = h = d = d || l, 3 !== d.nodeType && 8 !== d.nodeType && !X.test(q + n.event.triggered) && (q.indexOf(".") >= 0 && (r = q.split("."), q = r.shift(), r.sort()), k = q.indexOf(":") < 0 && "on" + q, b = b[n.expando] ? b : new n.Event(q, "object" == typeof b && b), b.isTrigger = e ? 2 : 3, b.namespace = r.join("."), b.namespace_re = b.namespace ? new RegExp("(^|\\.)" + r.join("\\.(?:.*\\.|)") + "(\\.|$)") : null, b.result = void 0, b.target || (b.target = d), c = null == c ? [b] : n.makeArray(c, [b]), o = n.event.special[q] || {}, e || !o.trigger || o.trigger.apply(d, c) !== !1)) { + if (!e && !o.noBubble && !n.isWindow(d)) { + for (i = o.delegateType || q, X.test(i + q) || (g = g.parentNode); g; g = g.parentNode)p.push(g), h = g; + h === (d.ownerDocument || l) && p.push(h.defaultView || h.parentWindow || a) + } + f = 0; + while ((g = p[f++]) && !b.isPropagationStopped())b.type = f > 1 ? i : o.bindType || q, m = (L.get(g, "events") || {})[b.type] && L.get(g, "handle"), m && m.apply(g, c), m = k && g[k], m && m.apply && n.acceptData(g) && (b.result = m.apply(g, c), b.result === !1 && b.preventDefault()); + return b.type = q, e || b.isDefaultPrevented() || o._default && o._default.apply(p.pop(), c) !== !1 || !n.acceptData(d) || k && n.isFunction(d[q]) && !n.isWindow(d) && (h = d[k], h && (d[k] = null), n.event.triggered = q, d[q](), n.event.triggered = void 0, h && (d[k] = h)), b.result + } + }, dispatch: function (a) { + a = n.event.fix(a); + var b, c, e, f, g, h = [], i = d.call(arguments), j = (L.get(this, "events") || {})[a.type] || [], k = n.event.special[a.type] || {}; + if (i[0] = a, a.delegateTarget = this, !k.preDispatch || k.preDispatch.call(this, a) !== !1) { + h = n.event.handlers.call(this, a, j), b = 0; + while ((f = h[b++]) && !a.isPropagationStopped()) { + a.currentTarget = f.elem, c = 0; + while ((g = f.handlers[c++]) && !a.isImmediatePropagationStopped())(!a.namespace_re || a.namespace_re.test(g.namespace)) && (a.handleObj = g, a.data = g.data, e = ((n.event.special[g.origType] || {}).handle || g.handler).apply(f.elem, i), void 0 !== e && (a.result = e) === !1 && (a.preventDefault(), a.stopPropagation())) + } + return k.postDispatch && k.postDispatch.call(this, a), a.result + } + }, handlers: function (a, b) { + var c, d, e, f, g = [], h = b.delegateCount, i = a.target; + if (h && i.nodeType && (!a.button || "click" !== a.type))for (; i !== this; i = i.parentNode || this)if (i.disabled !== !0 || "click" !== a.type) { + for (d = [], c = 0; h > c; c++)f = b[c], e = f.selector + " ", void 0 === d[e] && (d[e] = f.needsContext ? n(e, this).index(i) >= 0 : n.find(e, this, null, [i]).length), d[e] && d.push(f); + d.length && g.push({elem: i, handlers: d}) + } + return h < b.length && g.push({elem: this, handlers: b.slice(h)}), g + }, props: "altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "), fixHooks: {}, keyHooks: {props: "char charCode key keyCode".split(" "), filter: function (a, b) { + return null == a.which && (a.which = null != b.charCode ? b.charCode : b.keyCode), a + }}, mouseHooks: {props: "button buttons clientX clientY offsetX offsetY pageX pageY screenX screenY toElement".split(" "), filter: function (a, b) { + var c, d, e, f = b.button; + return null == a.pageX && null != b.clientX && (c = a.target.ownerDocument || l, d = c.documentElement, e = c.body, a.pageX = b.clientX + (d && d.scrollLeft || e && e.scrollLeft || 0) - (d && d.clientLeft || e && e.clientLeft || 0), a.pageY = b.clientY + (d && d.scrollTop || e && e.scrollTop || 0) - (d && d.clientTop || e && e.clientTop || 0)), a.which || void 0 === f || (a.which = 1 & f ? 1 : 2 & f ? 3 : 4 & f ? 2 : 0), a + }}, fix: function (a) { + if (a[n.expando])return a; + var b, c, d, e = a.type, f = a, g = this.fixHooks[e]; + g || (this.fixHooks[e] = g = W.test(e) ? this.mouseHooks : V.test(e) ? this.keyHooks : {}), d = g.props ? this.props.concat(g.props) : this.props, a = new n.Event(f), b = d.length; + while (b--)c = d[b], a[c] = f[c]; + return a.target || (a.target = l), 3 === a.target.nodeType && (a.target = a.target.parentNode), g.filter ? g.filter(a, f) : a + }, special: {load: {noBubble: !0}, focus: {trigger: function () { + return this !== _() && this.focus ? (this.focus(), !1) : void 0 + }, delegateType: "focusin"}, blur: {trigger: function () { + return this === _() && this.blur ? (this.blur(), !1) : void 0 + }, delegateType: "focusout"}, click: {trigger: function () { + return"checkbox" === this.type && this.click && n.nodeName(this, "input") ? (this.click(), !1) : void 0 + }, _default: function (a) { + return n.nodeName(a.target, "a") + }}, beforeunload: {postDispatch: function (a) { + void 0 !== a.result && a.originalEvent && (a.originalEvent.returnValue = a.result) + }}}, simulate: function (a, b, c, d) { + var e = n.extend(new n.Event, c, {type: a, isSimulated: !0, originalEvent: {}}); + d ? n.event.trigger(e, null, b) : n.event.dispatch.call(b, e), e.isDefaultPrevented() && c.preventDefault() + }}, n.removeEvent = function (a, b, c) { + a.removeEventListener && a.removeEventListener(b, c, !1) + }, n.Event = function (a, b) { + return this instanceof n.Event ? (a && a.type ? (this.originalEvent = a, this.type = a.type, this.isDefaultPrevented = a.defaultPrevented || void 0 === a.defaultPrevented && a.returnValue === !1 ? Z : $) : this.type = a, b && n.extend(this, b), this.timeStamp = a && a.timeStamp || n.now(), void(this[n.expando] = !0)) : new n.Event(a, b) + }, n.Event.prototype = {isDefaultPrevented: $, isPropagationStopped: $, isImmediatePropagationStopped: $, preventDefault: function () { + var a = this.originalEvent; + this.isDefaultPrevented = Z, a && a.preventDefault && a.preventDefault() + }, stopPropagation: function () { + var a = this.originalEvent; + this.isPropagationStopped = Z, a && a.stopPropagation && a.stopPropagation() + }, stopImmediatePropagation: function () { + var a = this.originalEvent; + this.isImmediatePropagationStopped = Z, a && a.stopImmediatePropagation && a.stopImmediatePropagation(), this.stopPropagation() + }}, n.each({mouseenter: "mouseover", mouseleave: "mouseout", pointerenter: "pointerover", pointerleave: "pointerout"}, function (a, b) { + n.event.special[a] = {delegateType: b, bindType: b, handle: function (a) { + var c, d = this, e = a.relatedTarget, f = a.handleObj; + return(!e || e !== d && !n.contains(d, e)) && (a.type = f.origType, c = f.handler.apply(this, arguments), a.type = b), c + }} + }), k.focusinBubbles || n.each({focus: "focusin", blur: "focusout"}, function (a, b) { + var c = function (a) { + n.event.simulate(b, a.target, n.event.fix(a), !0) + }; + n.event.special[b] = {setup: function () { + var d = this.ownerDocument || this, e = L.access(d, b); + e || d.addEventListener(a, c, !0), L.access(d, b, (e || 0) + 1) + }, teardown: function () { + var d = this.ownerDocument || this, e = L.access(d, b) - 1; + e ? L.access(d, b, e) : (d.removeEventListener(a, c, !0), L.remove(d, b)) + }} + }), n.fn.extend({on: function (a, b, c, d, e) { + var f, g; + if ("object" == typeof a) { + "string" != typeof b && (c = c || b, b = void 0); + for (g in a)this.on(g, b, c, a[g], e); + return this + } + if (null == c && null == d ? (d = b, c = b = void 0) : null == d && ("string" == typeof b ? (d = c, c = void 0) : (d = c, c = b, b = void 0)), d === !1)d = $; else if (!d)return this; + return 1 === e && (f = d, d = function (a) { + return n().off(a), f.apply(this, arguments) + }, d.guid = f.guid || (f.guid = n.guid++)), this.each(function () { + n.event.add(this, a, d, c, b) + }) + }, one: function (a, b, c, d) { + return this.on(a, b, c, d, 1) + }, off: function (a, b, c) { + var d, e; + if (a && a.preventDefault && a.handleObj)return d = a.handleObj, n(a.delegateTarget).off(d.namespace ? d.origType + "." + d.namespace : d.origType, d.selector, d.handler), this; + if ("object" == typeof a) { + for (e in a)this.off(e, b, a[e]); + return this + } + return(b === !1 || "function" == typeof b) && (c = b, b = void 0), c === !1 && (c = $), this.each(function () { + n.event.remove(this, a, c, b) + }) + }, trigger: function (a, b) { + return this.each(function () { + n.event.trigger(a, b, this) + }) + }, triggerHandler: function (a, b) { + var c = this[0]; + return c ? n.event.trigger(a, b, c, !0) : void 0 + }}); + var ab = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi, bb = /<([\w:]+)/, cb = /<|&#?\w+;/, db = /<(?:script|style|link)/i, eb = /checked\s*(?:[^=]|=\s*.checked.)/i, fb = /^$|\/(?:java|ecma)script/i, gb = /^true\/(.*)/, hb = /^\s*\s*$/g, ib = {option: [1, ""], thead: [1, "", "
    "], col: [2, "", "
    "], tr: [2, "", "
    "], td: [3, "", "
    "], _default: [0, "", ""]}; + ib.optgroup = ib.option, ib.tbody = ib.tfoot = ib.colgroup = ib.caption = ib.thead, ib.th = ib.td; + function jb(a, b) { + return n.nodeName(a, "table") && n.nodeName(11 !== b.nodeType ? b : b.firstChild, "tr") ? a.getElementsByTagName("tbody")[0] || a.appendChild(a.ownerDocument.createElement("tbody")) : a + } + + function kb(a) { + return a.type = (null !== a.getAttribute("type")) + "/" + a.type, a + } + + function lb(a) { + var b = gb.exec(a.type); + return b ? a.type = b[1] : a.removeAttribute("type"), a + } + + function mb(a, b) { + for (var c = 0, d = a.length; d > c; c++)L.set(a[c], "globalEval", !b || L.get(b[c], "globalEval")) + } + + function nb(a, b) { + var c, d, e, f, g, h, i, j; + if (1 === b.nodeType) { + if (L.hasData(a) && (f = L.access(a), g = L.set(b, f), j = f.events)) { + delete g.handle, g.events = {}; + for (e in j)for (c = 0, d = j[e].length; d > c; c++)n.event.add(b, e, j[e][c]) + } + M.hasData(a) && (h = M.access(a), i = n.extend({}, h), M.set(b, i)) + } + } + + function ob(a, b) { + var c = a.getElementsByTagName ? a.getElementsByTagName(b || "*") : a.querySelectorAll ? a.querySelectorAll(b || "*") : []; + return void 0 === b || b && n.nodeName(a, b) ? n.merge([a], c) : c + } + + function pb(a, b) { + var c = b.nodeName.toLowerCase(); + "input" === c && T.test(a.type) ? b.checked = a.checked : ("input" === c || "textarea" === c) && (b.defaultValue = a.defaultValue) + } + + n.extend({clone: function (a, b, c) { + var d, e, f, g, h = a.cloneNode(!0), i = n.contains(a.ownerDocument, a); + if (!(k.noCloneChecked || 1 !== a.nodeType && 11 !== a.nodeType || n.isXMLDoc(a)))for (g = ob(h), f = ob(a), d = 0, e = f.length; e > d; d++)pb(f[d], g[d]); + if (b)if (c)for (f = f || ob(a), g = g || ob(h), d = 0, e = f.length; e > d; d++)nb(f[d], g[d]); else nb(a, h); + return g = ob(h, "script"), g.length > 0 && mb(g, !i && ob(a, "script")), h + }, buildFragment: function (a, b, c, d) { + for (var e, f, g, h, i, j, k = b.createDocumentFragment(), l = [], m = 0, o = a.length; o > m; m++)if (e = a[m], e || 0 === e)if ("object" === n.type(e))n.merge(l, e.nodeType ? [e] : e); else if (cb.test(e)) { + f = f || k.appendChild(b.createElement("div")), g = (bb.exec(e) || ["", ""])[1].toLowerCase(), h = ib[g] || ib._default, f.innerHTML = h[1] + e.replace(ab, "<$1>") + h[2], j = h[0]; + while (j--)f = f.lastChild; + n.merge(l, f.childNodes), f = k.firstChild, f.textContent = "" + } else l.push(b.createTextNode(e)); + k.textContent = "", m = 0; + while (e = l[m++])if ((!d || -1 === n.inArray(e, d)) && (i = n.contains(e.ownerDocument, e), f = ob(k.appendChild(e), "script"), i && mb(f), c)) { + j = 0; + while (e = f[j++])fb.test(e.type || "") && c.push(e) + } + return k + }, cleanData: function (a) { + for (var b, c, d, e, f = n.event.special, g = 0; void 0 !== (c = a[g]); g++) { + if (n.acceptData(c) && (e = c[L.expando], e && (b = L.cache[e]))) { + if (b.events)for (d in b.events)f[d] ? n.event.remove(c, d) : n.removeEvent(c, d, b.handle); + L.cache[e] && delete L.cache[e] + } + delete M.cache[c[M.expando]] + } + }}), n.fn.extend({text: function (a) { + return J(this, function (a) { + return void 0 === a ? n.text(this) : this.empty().each(function () { + (1 === this.nodeType || 11 === this.nodeType || 9 === this.nodeType) && (this.textContent = a) + }) + }, null, a, arguments.length) + }, append: function () { + return this.domManip(arguments, function (a) { + if (1 === this.nodeType || 11 === this.nodeType || 9 === this.nodeType) { + var b = jb(this, a); + b.appendChild(a) + } + }) + }, prepend: function () { + return this.domManip(arguments, function (a) { + if (1 === this.nodeType || 11 === this.nodeType || 9 === this.nodeType) { + var b = jb(this, a); + b.insertBefore(a, b.firstChild) + } + }) + }, before: function () { + return this.domManip(arguments, function (a) { + this.parentNode && this.parentNode.insertBefore(a, this) + }) + }, after: function () { + return this.domManip(arguments, function (a) { + this.parentNode && this.parentNode.insertBefore(a, this.nextSibling) + }) + }, remove: function (a, b) { + for (var c, d = a ? n.filter(a, this) : this, e = 0; null != (c = d[e]); e++)b || 1 !== c.nodeType || n.cleanData(ob(c)), c.parentNode && (b && n.contains(c.ownerDocument, c) && mb(ob(c, "script")), c.parentNode.removeChild(c)); + return this + }, empty: function () { + for (var a, b = 0; null != (a = this[b]); b++)1 === a.nodeType && (n.cleanData(ob(a, !1)), a.textContent = ""); + return this + }, clone: function (a, b) { + return a = null == a ? !1 : a, b = null == b ? a : b, this.map(function () { + return n.clone(this, a, b) + }) + }, html: function (a) { + return J(this, function (a) { + var b = this[0] || {}, c = 0, d = this.length; + if (void 0 === a && 1 === b.nodeType)return b.innerHTML; + if ("string" == typeof a && !db.test(a) && !ib[(bb.exec(a) || ["", ""])[1].toLowerCase()]) { + a = a.replace(ab, "<$1>"); + try { + for (; d > c; c++)b = this[c] || {}, 1 === b.nodeType && (n.cleanData(ob(b, !1)), b.innerHTML = a); + b = 0 + } catch (e) { + } + } + b && this.empty().append(a) + }, null, a, arguments.length) + }, replaceWith: function () { + var a = arguments[0]; + return this.domManip(arguments, function (b) { + a = this.parentNode, n.cleanData(ob(this)), a && a.replaceChild(b, this) + }), a && (a.length || a.nodeType) ? this : this.remove() + }, detach: function (a) { + return this.remove(a, !0) + }, domManip: function (a, b) { + a = e.apply([], a); + var c, d, f, g, h, i, j = 0, l = this.length, m = this, o = l - 1, p = a[0], q = n.isFunction(p); + if (q || l > 1 && "string" == typeof p && !k.checkClone && eb.test(p))return this.each(function (c) { + var d = m.eq(c); + q && (a[0] = p.call(this, c, d.html())), d.domManip(a, b) + }); + if (l && (c = n.buildFragment(a, this[0].ownerDocument, !1, this), d = c.firstChild, 1 === c.childNodes.length && (c = d), d)) { + for (f = n.map(ob(c, "script"), kb), g = f.length; l > j; j++)h = c, j !== o && (h = n.clone(h, !0, !0), g && n.merge(f, ob(h, "script"))), b.call(this[j], h, j); + if (g)for (i = f[f.length - 1].ownerDocument, n.map(f, lb), j = 0; g > j; j++)h = f[j], fb.test(h.type || "") && !L.access(h, "globalEval") && n.contains(i, h) && (h.src ? n._evalUrl && n._evalUrl(h.src) : n.globalEval(h.textContent.replace(hb, ""))) + } + return this + }}), n.each({appendTo: "append", prependTo: "prepend", insertBefore: "before", insertAfter: "after", replaceAll: "replaceWith"}, function (a, b) { + n.fn[a] = function (a) { + for (var c, d = [], e = n(a), g = e.length - 1, h = 0; g >= h; h++)c = h === g ? this : this.clone(!0), n(e[h])[b](c), f.apply(d, c.get()); + return this.pushStack(d) + } + }); + var qb, rb = {}; + + function sb(b, c) { + var d, e = n(c.createElement(b)).appendTo(c.body), f = a.getDefaultComputedStyle && (d = a.getDefaultComputedStyle(e[0])) ? d.display : n.css(e[0], "display"); + return e.detach(), f + } + + function tb(a) { + var b = l, c = rb[a]; + return c || (c = sb(a, b), "none" !== c && c || (qb = (qb || n("