kwikid-agent-dashboard
Version:
KwikID's EKYC Agent Map View Module.
252 lines • 36.4 kB
JavaScript
import { __awaiter } from "tslib";
import { Injectable, ViewChildren } from "@angular/core";
import * as L from "leaflet";
import "leaflet-routing-machine";
import { checkObjectPathExists, getObjectValueFromPath, isNotEmptyArray } from "kwikid-toolkit";
import { addressConcator, nearestNeighborAlgorithm } from "../helpers/maps.helpers";
import * as i0 from "@angular/core";
import * as i1 from "./agent.service";
import * as i2 from "@angular/google-maps";
import * as i3 from "@angular/common/http";
export class OpenStreetMapsService {
constructor(agentService, mapDirectionsService, httpClient) {
this.agentService = agentService;
this.mapDirectionsService = mapDirectionsService;
this.httpClient = httpClient;
this.allMarkers = [];
}
// To get Current Position
getPosition() {
return new Promise((resolve, reject) => {
navigator.geolocation.watchPosition((resp) => {
resolve({
lng: resp.coords.longitude,
lat: resp.coords.latitude
});
}, (err) => {
reject(err);
});
});
}
// To extract Location from the Task Details
getLocation(task) {
return __awaiter(this, void 0, void 0, function* () {
return new Promise((resolve) => __awaiter(this, void 0, void 0, function* () {
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p;
let encodedAddres;
// If Fetch Address from Multiple Paths
if (checkObjectPathExists(this.agentService.config, "extendedFlags.taskLocationPaths")) {
// Get address string from multiple paths
const config = this.agentService.config.extendedFlags.taskLocationPaths;
const address = addressConcator(task, config);
// Encode the Address in URI
encodedAddres = encodeURI(address);
}
// If Fetch Address from Single Path
else if (checkObjectPathExists(this.agentService.config, "extendedFlags.taskLocationPath")) {
// Get Address from Single Path
const config = this.agentService.config.extendedFlags.taskLocationPath;
const address = getObjectValueFromPath(task, config);
// Encode the Address in URI
encodedAddres = encodeURI(address);
}
// Default Address Paths Avaiable
else {
const address = (_k = (_j = (_g = (_d = (_c = (_b = (_a = task === null || task === void 0 ? void 0 : task.extras) === null || _a === void 0 ? void 0 : _a.task_details) === null || _b === void 0 ? void 0 : _b.customer_details) === null || _c === void 0 ? void 0 : _c.address) !== null && _d !== void 0 ? _d : (_f = (_e = task === null || task === void 0 ? void 0 : task.task_details) === null || _e === void 0 ? void 0 : _e.customer_details) === null || _f === void 0 ? void 0 : _f.address) !== null && _g !== void 0 ? _g : (_h = task === null || task === void 0 ? void 0 : task.extras) === null || _h === void 0 ? void 0 : _h.address) !== null && _j !== void 0 ? _j : task === null || task === void 0 ? void 0 : task.address) !== null && _k !== void 0 ? _k : "";
// Encode the Address in URI
encodedAddres = encodeURI(address);
}
// URL to geocode Address String to Latitude & Longitude
const url = `https://nominatim.openstreetmap.org/search?q=${encodedAddres}&format=json`;
const response = yield fetch(url);
const data = yield response.json();
// Set Location {lat: LAT, lng: LNG} from address geocoded
const isValidLocation = isNotEmptyArray(data) && ((_l = data[0]) === null || _l === void 0 ? void 0 : _l.lat) & ((_m = data[0]) === null || _m === void 0 ? void 0 : _m.lon);
const location = isValidLocation
? { lat: (_o = data[0]) === null || _o === void 0 ? void 0 : _o.lat, lng: (_p = data[0]) === null || _p === void 0 ? void 0 : _p.lon }
: { lat: null, lng: null };
// Set Location validation & Google Maps URL
location.isValidLocation = isValidLocation;
location.color = isValidLocation ? "blue" : "red";
location.googleMapsUrl = `https://www.google.com/maps/place/${location === null || location === void 0 ? void 0 : location.lat},${location === null || location === void 0 ? void 0 : location.lng}`;
resolve(location);
}));
});
}
// Get Tasks | Markers Location Co Ordinates
getMarkersLocation(myMarker, tasks) {
return __awaiter(this, void 0, void 0, function* () {
return new Promise((resolve) => __awaiter(this, void 0, void 0, function* () {
const markers = [];
markers.push(myMarker);
const promises = tasks.map((task) => __awaiter(this, void 0, void 0, function* () {
const marker = yield this.getLocation(task);
task = Object.assign(Object.assign({}, task), marker);
markers.push(task);
}));
yield Promise.all(promises);
resolve(markers);
}));
});
}
// To Initialize Open Street Map
initializeMap() {
return __awaiter(this, void 0, void 0, function* () {
console.log("Running Init Open Street Maps");
this.myPosition = yield this.getPosition();
this.map = L.map("map", {
center: [this.myPosition.lat, this.myPosition.lng],
zoom: 11
});
L.tileLayer("https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png").addTo(this.map);
});
}
// To Add Open Street Marker in Map
addMarker({ lat, lng, title, color }) {
L.marker([lat, lng], {
icon: L.icon({
iconUrl: color == "red"
? "https://kwikid.s3.ap-south-1.amazonaws.com/CONFIG/USER/assets/map-marker-0.png"
: "https://kwikid.s3.ap-south-1.amazonaws.com/CONFIG/USER/assets/map-marker-1.png"
})
})
.addTo(this.map)
.bindPopup(title);
}
// To Plot Open Street Directions for All Tasks
plotDirectionsForAllTasks(tasks) {
return __awaiter(this, void 0, void 0, function* () {
if (this.map) {
this.allMarkers = [];
// Create Agent Marker & Plot It.
const myMarker = {
lat: this.myPosition.lat,
lng: this.myPosition.lng,
title: 0,
color: "red"
};
this.addMarker(myMarker);
this.allMarkers.push(myMarker);
// Create Markers for all Tasks
this.allMarkers = yield this.getMarkersLocation(myMarker, tasks);
// Run Algorithm to get optimized Routes
const startingPoint = this.allMarkers[0];
const unvisitedWaypoints = this.allMarkers.slice(1);
const optimizedRoute = nearestNeighborAlgorithm(startingPoint, unvisitedWaypoints);
// Sort All Markers as per optimized routes
this.allMarkers = this.sortTasksAsPerDistance(optimizedRoute, this.allMarkers, true);
// Sort All Tasks as per optimized routes
tasks = this.sortTasksAsPerDistance(optimizedRoute.slice(1), tasks, false);
// Plot Markers for All Tasks
tasks.map((task) => {
if (task === null || task === void 0 ? void 0 : task.isValidLocation) {
const marker = this.getLocation(task);
this.addMarker(marker);
}
});
// Set Styles for all Task Routes
const styles = [
{ color: "blue", opacity: 1, weight: 8 },
{ color: "white", opacity: 0.6, weight: 12 }
];
// Set Routes for all Tasks
this.allTasksRoutes = this.setRoutes(this.allMarkers, styles);
this.fitMapBounds();
}
return tasks;
});
}
// To plot Open Street Direction for selected Task
plotDirectionsForSelectedTask(task) {
if (task !== null) {
// Remove Previously Selected Task Route
if (this.selectedTaskRoutes) {
this.map.removeControl(this.selectedTaskRoutes);
}
// Remove All Tasks Routes
if (this.allTasksRoutes) {
this.map.removeControl(this.allTasksRoutes);
}
const taskMarker = task;
// If Location is Available in Task Details
if (taskMarker.color != "red") {
const markers = [this.allMarkers[0], taskMarker];
const styles = [
{ color: "green", opacity: 1, weight: 8 },
{ color: "white", opacity: 0.4, weight: 12 }
];
this.selectedTaskRoutes = this.setRoutes(markers, styles);
this.setSelectedTaskDistanceAndTime();
}
else {
alert("No Location Available");
}
}
// Set All Tasks Routes Again & Remove Selected Tasks route
else {
if (this.selectedTaskRoutes) {
this.map.removeControl(this.selectedTaskRoutes);
}
this.map.addControl(this.allTasksRoutes);
this.selectedTaskRoutes = undefined;
}
this.fitMapBounds();
}
// Get Distance & Time of Selected Task
getSelectedTaskDistanceAndTime() {
return this.selectedTaskDistanceAndTime;
}
// Set Distance & Time of Selected Task
setSelectedTaskDistanceAndTime() {
this.selectedTaskRoutes.on("routesfound", function (e) {
const { routes } = e;
const { summary } = routes[0];
const distance = summary.totalDistance / 1000;
const time = Math.round((summary.totalTime % 3600) / 60);
this.selectedTaskDistanceAndTime = {
distance,
time
};
});
}
// To sort Open Street Maps Task as per nearest distance
sortTasksAsPerDistance(order, tasks, isMarker) {
const sortedTasks = [];
for (let i = 0; i < tasks.length; i++) {
const title = isMarker ? order[i].title : order[i].title - 1;
const task = tasks[title];
sortedTasks.push(task);
}
return sortedTasks;
}
// To set Open Street routes in the maps
setRoutes(markers, styles) {
return L.Routing.control({
waypoints: markers,
lineOptions: {
styles
},
createMarker() {
return null;
},
routeWhileDragging: true
}).addTo(this.map);
}
// To set Open Street view point on the map
fitMapBounds() {
const markerLatLngs = this.allMarkers.map((marker) => L.latLng(marker.lat, marker.lng));
this.map.fitBounds(markerLatLngs);
}
}
/** @nocollapse */ OpenStreetMapsService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.17", ngImport: i0, type: OpenStreetMapsService, deps: [{ token: i1.AgentService }, { token: i2.MapDirectionsService }, { token: i3.HttpClient }], target: i0.ɵɵFactoryTarget.Injectable });
/** @nocollapse */ OpenStreetMapsService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "12.2.17", ngImport: i0, type: OpenStreetMapsService, providedIn: "root" });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.17", ngImport: i0, type: OpenStreetMapsService, decorators: [{
type: Injectable,
args: [{
providedIn: "root"
}]
}], ctorParameters: function () { return [{ type: i1.AgentService }, { type: i2.MapDirectionsService }, { type: i3.HttpClient }]; }, propDecorators: { directionsRenders: [{
type: ViewChildren,
args: ["directionsRender"]
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib3Blbi1zdHJlZXQtbWFwcy5zZXJ2aWNlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMva3dpa2lkLWFnZW50LWRhc2hib2FyZC9zcmMvbGliL3YxL3NlcnZpY2VzL29wZW4tc3RyZWV0LW1hcHMuc2VydmljZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUEsT0FBTyxFQUFjLFVBQVUsRUFBYSxZQUFZLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDaEYsT0FBTyxLQUFLLENBQUMsTUFBTSxTQUFTLENBQUM7QUFDN0IsT0FBTyx5QkFBeUIsQ0FBQztBQUNqQyxPQUFPLEVBQ0wscUJBQXFCLEVBQ3JCLHNCQUFzQixFQUN0QixlQUFlLEVBQ2hCLE1BQU0sZ0JBQWdCLENBQUM7QUFLeEIsT0FBTyxFQUNMLGVBQWUsRUFDZix3QkFBd0IsRUFDekIsTUFBTSx5QkFBeUIsQ0FBQzs7Ozs7QUFLakMsTUFBTSxPQUFPLHFCQUFxQjtJQWlCaEMsWUFDVSxZQUEwQixFQUMzQixvQkFBMEMsRUFDMUMsVUFBc0I7UUFGckIsaUJBQVksR0FBWixZQUFZLENBQWM7UUFDM0IseUJBQW9CLEdBQXBCLG9CQUFvQixDQUFzQjtRQUMxQyxlQUFVLEdBQVYsVUFBVSxDQUFZO1FBZi9CLGVBQVUsR0FBUSxFQUFFLENBQUM7SUFnQmxCLENBQUM7SUFFSiwwQkFBMEI7SUFDMUIsV0FBVztRQUNULE9BQU8sSUFBSSxPQUFPLENBQUMsQ0FBQyxPQUFPLEVBQUUsTUFBTSxFQUFFLEVBQUU7WUFDckMsU0FBUyxDQUFDLFdBQVcsQ0FBQyxhQUFhLENBQ2pDLENBQUMsSUFBSSxFQUFFLEVBQUU7Z0JBQ1AsT0FBTyxDQUFDO29CQUNOLEdBQUcsRUFBRSxJQUFJLENBQUMsTUFBTSxDQUFDLFNBQVM7b0JBQzFCLEdBQUcsRUFBRSxJQUFJLENBQUMsTUFBTSxDQUFDLFFBQVE7aUJBQzFCLENBQUMsQ0FBQztZQUNMLENBQUMsRUFDRCxDQUFD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QyxHQUFHLENBQUMsU0FBUyxDQUFDLGFBQWEsQ0FBQyxDQUFDO0lBQ3BDLENBQUM7O3NJQWxUVSxxQkFBcUI7MElBQXJCLHFCQUFxQixjQUZwQixNQUFNOzRGQUVQLHFCQUFxQjtrQkFIakMsVUFBVTttQkFBQztvQkFDVixVQUFVLEVBQUUsTUFBTTtpQkFDbkI7K0pBY21DLGlCQUFpQjtzQkFBbEQsWUFBWTt1QkFBQyxrQkFBa0IiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBFbGVtZW50UmVmLCBJbmplY3RhYmxlLCBRdWVyeUxpc3QsIFZpZXdDaGlsZHJlbiB9IGZyb20gXCJAYW5ndWxhci9jb3JlXCI7XG5pbXBvcnQgKiBhcyBMIGZyb20gXCJsZWFmbGV0XCI7XG5pbXBvcnQgXCJsZWFmbGV0LXJvdXRpbmctbWFjaGluZVwiO1xuaW1wb3J0IHtcbiAgY2hlY2tPYmplY3RQYXRoRXhpc3RzLFxuICBnZXRPYmplY3RWYWx1ZUZyb21QYXRoLFxuICBpc05vdEVtcHR5QXJyYXlcbn0gZnJvbSBcImt3aWtpZC10b29sa2l0XCI7XG5cbmltcG9ydCB7IE1hcERpcmVjdGlvbnNTZXJ2aWNlIH0gZnJvbSBcIkBhbmd1bGFyL2dvb2dsZS1tYXBzXCI7XG5pbXBvcnQgeyBIdHRwQ2xpZW50IH0gZnJvbSBcIkBhbmd1bGFyL2NvbW1vbi9odHRwXCI7XG5pbXBvcnQgeyBBZ2VudFNlcnZpY2UgfSBmcm9tIFwiLi9hZ2VudC5zZXJ2aWNlXCI7XG5pbXBvcnQge1xuICBhZGRyZXNzQ29uY2F0b3IsXG4gIG5lYXJlc3ROZWlnaGJvckFsZ29yaXRobVxufSBmcm9tIFwiLi4vaGVscGVycy9tYXBzLmhlbHBlcnNcIjtcblxuQEluamVjdGFibGUoe1xuICBwcm92aWRlZEluOiBcInJvb3RcIlxufSlcbmV4cG9ydCBjbGFzcyBPcGVuU3RyZWV0TWFwc1NlcnZpY2Uge1xuICBteVBvc2l0aW9uO1xuXG4gIG1hcDogYW55O1xuXG4gIGFsbE1hcmtlcnM6IGFueSA9IFtdO1xuXG4gIGFsbFRhc2tzUm91dGVzOiBhbnk7XG5cbiAgc2VsZWN0ZWRUYXNrUm91dGVzOiBhbnk7XG5cbiAgc2VsZWN0ZWRUYXNrRGlzdGFuY2VBbmRUaW1lOiBhbnk7XG5cbiAgQFZpZXdDaGlsZHJlbihcImRpcmVjdGlvbnNSZW5kZXJcIikgZGlyZWN0aW9uc1JlbmRlcnM6IFF1ZXJ5TGlzdDxcbiAgICBFbGVtZW50UmVmPGdvb2dsZS5tYXBzLkRpcmVjdGlvbnNSZW5kZXJlcj5cbiAgPjtcblxuICBjb25zdHJ1Y3RvcihcbiAgICBwcml2YXRlIGFnZW50U2VydmljZTogQWdlbnRTZXJ2aWNlLFxuICAgIHB1YmxpYyBtYXBEaXJlY3Rpb25zU2VydmljZTogTWFwRGlyZWN0aW9uc1NlcnZpY2UsXG4gICAgcHVibGljIGh0dHBDbGllbnQ6IEh0dHBDbGllbnRcbiAgKSB7fVxuXG4gIC8vIFRvIGdldCBDdXJyZW50IFBvc2l0aW9uXG4gIGdldFBvc2l0aW9uKCk6IFByb21pc2U8YW55PiB7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgIG5hdmlnYXRvci5nZW9sb2NhdGlvbi53YXRjaFBvc2l0aW9uKFxuICAgICAgICAocmVzcCkgPT4ge1xuICAgICAgICAgIHJlc29sdmUoe1xuICAgICAgICAgICAgbG5nOiByZXNwLmNvb3Jkcy5sb25naXR1ZGUsXG4gICAgICAgICAgICBsYXQ6IHJlc3AuY29vcmRzLmxhdGl0dWRlXG4gICAgICAgICAgfSk7XG4gICAgICAgIH0sXG4gICAgICAgIChlcnIpID0+IHtcbiAgICAgICAgICByZWplY3QoZXJyKTtcbiAgICAgICAgfVxuICAgICAgKTtcbiAgICB9KTtcbiAgfVxuXG4gIC8vIFRvIGV4dHJhY3QgTG9jYXRpb24gZnJvbSB0aGUgVGFzayBEZXRhaWxzXG4gIGFzeW5jIGdldExvY2F0aW9uKHRhc2spIHtcbiAgICByZXR1cm4gbmV3IFByb21pc2UoYXN5bmMocmVzb2x2ZSkgPT4ge1xuICAgICAgbGV0IGVuY29kZWRBZGRyZXM7XG5cbiAgICAgIC8vIElmIEZldGNoIEFkZHJlc3MgZnJvbSBNdWx0aXBsZSBQYXRoc1xuICAgICAgaWYgKFxuICAgICAgICBjaGVja09iamVjdFBhdGhFeGlzdHMoXG4gICAgICAgICAgdGhpcy5hZ2VudFNlcnZpY2UuY29uZmlnLFxuICAgICAgICAgIFwiZXh0ZW5kZWRGbGFncy50YXNrTG9jYXRpb25QYXRoc1wiXG4gICAgICAgIClcbiAgICAgICkge1xuICAgICAgICAvLyBHZXQgYWRkcmVzcyBzdHJpbmcgZnJvbSBtdWx0aXBsZSBwYXRoc1xuICAgICAgICBjb25zdCBjb25maWcgPSB0aGlzLmFnZW50U2VydmljZS5jb25maWcuZXh0ZW5kZWRGbGFncy50YXNrTG9jYXRpb25QYXRocztcbiAgICAgICAgY29uc3QgYWRkcmVzcyA9IGFkZHJlc3NDb25jYXRvcih0YXNrLCBjb25maWcpO1xuXG4gICAgICAgIC8vIEVuY29kZSB0aGUgQWRkcmVzcyBpbiBVUklcbiAgICAgICAgZW5jb2RlZEFkZHJlcyA9IGVuY29kZVVSSShhZGRyZXNzKTtcbiAgICAgIH1cblxuICAgICAgLy8gSWYgRmV0Y2ggQWRkcmVzcyBmcm9tIFNpbmdsZSBQYXRoXG4gICAgICBlbHNlIGlmIChcbiAgICAgICAgY2hlY2tPYmplY3RQYXRoRXhpc3RzKFxuICAgICAgICAgIHRoaXMuYWdlbnRTZXJ2aWNlLmNvbmZpZyxcbiAgICAgICAgICBcImV4dGVuZGVkRmxhZ3MudGFza0xvY2F0aW9uUGF0aFwiXG4gICAgICAgIClcbiAgICAgICkge1xuICAgICAgICAvLyBHZXQgQWRkcmVzcyBmcm9tIFNpbmdsZSBQYXRoXG4gICAgICAgIGNvbnN0IGNvbmZpZyA9IHRoaXMuYWdlbnRTZXJ2aWNlLmNvbmZpZy5leHRlbmRlZEZsYWdzLnRhc2tMb2NhdGlvblBhdGg7XG4gICAgICAgIGNvbnN0IGFkZHJlc3MgPSBnZXRPYmplY3RWYWx1ZUZyb21QYXRoKHRhc2ssIGNvbmZpZyk7XG5cbiAgICAgICAgLy8gRW5jb2RlIHRoZSBBZGRyZXNzIGluIFVSSVxuICAgICAgICBlbmNvZGVkQWRkcmVzID0gZW5jb2RlVVJJKGFkZHJlc3MpO1xuICAgICAgfVxuXG4gICAgICAvLyBEZWZhdWx0IEFkZHJlc3MgUGF0aHMgQXZhaWFibGVcbiAgICAgIGVsc2Uge1xuICAgICAgICBjb25zdCBhZGRyZXNzID1cbiAgICAgICAgICB0YXNrPy5leHRyYXM/LnRhc2tfZGV0YWlscz8uY3VzdG9tZXJfZGV0YWlscz8uYWRkcmVzcyA/P1xuICAgICAgICAgIHRhc2s/LnRhc2tfZGV0YWlscz8uY3VzdG9tZXJfZGV0YWlscz8uYWRkcmVzcyA/P1xuICAgICAgICAgIHRhc2s/LmV4dHJhcz8uYWRkcmVzcyA/P1xuICAgICAgICAgIHRhc2s/LmFkZHJlc3MgPz9cbiAgICAgICAgICBcIlwiO1xuXG4gICAgICAgIC8vIEVuY29kZSB0aGUgQWRkcmVzcyBpbiBVUklcbiAgICAgICAgZW5jb2RlZEFkZHJlcyA9IGVuY29kZVVSSShhZGRyZXNzKTtcbiAgICAgIH1cblxuICAgICAgLy8gVVJMIHRvIGdlb2NvZGUgQWRkcmVzcyBTdHJpbmcgdG8gTGF0aXR1ZGUgJiBMb25naXR1ZGVcbiAgICAgIGNvbnN0IHVybCA9IGBodHRwczovL25vbWluYXRpbS5vcGVuc3RyZWV0bWFwLm9yZy9zZWFyY2g/cT0ke2VuY29kZWRBZGRyZXN9JmZvcm1hdD1qc29uYDtcblxuICAgICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCBmZXRjaCh1cmwpO1xuICAgICAgY29uc3QgZGF0YTogYW55ID0gYXdhaXQgcmVzcG9uc2UuanNvbigpO1xuXG4gICAgICAvLyBTZXQgTG9jYXRpb24ge2xhdDogTEFULCBsbmc6IExOR30gZnJvbSBhZGRyZXNzIGdlb2NvZGVkXG4gICAgICBjb25zdCBpc1ZhbGlkTG9jYXRpb24gPVxuICAgICAgICBpc05vdEVtcHR5QXJyYXkoZGF0YSkgJiYgZGF0YVswXT8ubGF0ICYgZGF0YVswXT8ubG9uO1xuICAgICAgY29uc3QgbG9jYXRpb246IGFueSA9IGlzVmFsaWRMb2NhdGlvblxuICAgICAgICA/IHsgbGF0OiBkYXRhWzBdPy5sYXQsIGxuZzogZGF0YVswXT8ubG9uIH1cbiAgICAgICAgOiB7IGxhdDogbnVsbCwgbG5nOiBudWxsIH07XG5cbiAgICAgIC8vIFNldCBMb2NhdGlvbiB2YWxpZGF0aW9uICYgR29vZ2xlIE1hcHMgVVJMXG4gICAgICBsb2NhdGlvbi5pc1ZhbGlkTG9jYXRpb24gPSBpc1ZhbGlkTG9jYXRpb247XG4gICAgICBsb2NhdGlvbi5jb2xvciA9IGlzVmFsaWRMb2NhdGlvbiA/IFwiYmx1ZVwiIDogXCJyZWRcIjtcbiAgICAgIGxvY2F0aW9uLmdvb2dsZU1hcHNVcmwgPSBgaHR0cHM6Ly93d3cuZ29vZ2xlLmNvbS9tYXBzL3BsYWNlLyR7bG9jYXRpb24/LmxhdH0sJHtsb2NhdGlvbj8ubG5nfWA7XG5cbiAgICAgIHJlc29sdmUobG9jYXRpb24pO1xuICAgIH0pO1xuICB9XG5cbiAgLy8gR2V0IFRhc2tzIHwgTWFya2VycyBMb2NhdGlvbiBDbyBPcmRpbmF0ZXNcbiAgYXN5bmMgZ2V0TWFya2Vyc0xvY2F0aW9uKG15TWFya2VyLCB0YXNrcykge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZShhc3luYyhyZXNvbHZlKSA9PiB7XG4gICAgICBjb25zdCBtYXJrZXJzID0gW107XG4gICAgICBtYXJrZXJzLnB1c2gobXlNYXJrZXIpO1xuICAgICAgY29uc3QgcHJvbWlzZXMgPSB0YXNrcy5tYXAoYXN5bmModGFzaykgPT4ge1xuICAgICAgICBjb25zdCBtYXJrZXI6IGFueSA9IGF3YWl0IHRoaXMuZ2V0TG9jYXRpb24odGFzayk7XG4gICAgICAgIHRhc2sgPSB7IC4uLnRhc2ssIC4uLm1hcmtlciB9O1xuICAgICAgICBtYXJrZXJzLnB1c2godGFzayk7XG4gICAgICB9KTtcblxuICAgICAgYXdhaXQgUHJvbWlzZS5hbGwocHJvbWlzZXMpO1xuXG4gICAgICByZXNvbHZlKG1hcmtlcnMpO1xuICAgIH0pO1xuICB9XG5cbiAgLy8gVG8gSW5pdGlhbGl6ZSBPcGVuIFN0cmVldCBNYXBcbiAgYXN5bmMgaW5pdGlhbGl6ZU1hcCgpIHtcbiAgICBjb25zb2xlLmxvZyhcIlJ1bm5pbmcgSW5pdCBPcGVuIFN0cmVldCBNYXBzXCIpO1xuICAgIHRoaXMubXlQb3NpdGlvbiA9IGF3YWl0IHRoaXMuZ2V0UG9zaXRpb24oKTtcbiAgICB0aGlzLm1hcCA9IEwubWFwKFwibWFwXCIsIHtcbiAgICAgIGNlbnRlcjogW3RoaXMubXlQb3NpdGlvbi5sYXQsIHRoaXMubXlQb3NpdGlvbi5sbmddLFxuICAgICAgem9vbTogMTFcbiAgICB9KTtcbiAgICBMLnRpbGVMYXllcihcImh0dHBzOi8ve3N9LnRpbGUub3BlbnN0cmVldG1hcC5vcmcve3p9L3t4fS97eX0ucG5nXCIpLmFkZFRvKFxuICAgICAgdGhpcy5tYXBcbiAgICApO1xuICB9XG5cbiAgLy8gVG8gQWRkIE9wZW4gU3RyZWV0IE1hcmtlciBpbiBNYXBcbiAgYWRkTWFya2VyKHsgbGF0LCBsbmcsIHRpdGxlLCBjb2xvciB9KSB7XG4gICAgTC5tYXJrZXIoW2xhdCwgbG5nXSwge1xuICAgICAgaWNvbjogTC5pY29uKHtcbiAgICAgICAgaWNvblVybDpcbiAgICAgICAgICBjb2xvciA9PSBcInJlZFwiXG4gICAgICAgICAgICA/IFwiaHR0cHM6Ly9rd2lraWQuczMuYXAtc291dGgtMS5hbWF6b25hd3MuY29tL0NPTkZJRy9VU0VSL2Fzc2V0cy9tYXAtbWFya2VyLTAucG5nXCJcbiAgICAgICAgICAgIDogXCJodHRwczovL2t3aWtpZC5zMy5hcC1zb3V0aC0xLmFtYXpvbmF3cy5jb20vQ09ORklHL1VTRVIvYXNzZXRzL21hcC1tYXJrZXItMS5wbmdcIlxuICAgICAgfSlcbiAgICB9KVxuICAgICAgLmFkZFRvKHRoaXMubWFwKVxuICAgICAgLmJpbmRQb3B1cCh0aXRsZSk7XG4gIH1cblxuICAvLyBUbyBQbG90IE9wZW4gU3RyZWV0IERpcmVjdGlvbnMgZm9yIEFsbCBUYXNrc1xuICBhc3luYyBwbG90RGlyZWN0aW9uc0ZvckFsbFRhc2tzKHRhc2tzKSB7XG4gICAgaWYgKHRoaXMubWFwKSB7XG4gICAgICB0aGlzLmFsbE1hcmtlcnMgPSBbXTtcblxuICAgICAgLy8gQ3JlYXRlIEFnZW50IE1hcmtlciAmIFBsb3QgSXQuXG4gICAgICBjb25zdCBteU1hcmtlciA9IHtcbiAgICAgICAgbGF0OiB0aGlzLm15UG9zaXRpb24ubGF0LFxuICAgICAgICBsbmc6IHRoaXMubXlQb3NpdGlvbi5sbmcsXG4gICAgICAgIHRpdGxlOiAwLFxuICAgICAgICBjb2xvcjogXCJyZWRcIlxuICAgICAgfTtcbiAgICAgIHRoaXMuYWRkTWFya2VyKG15TWFya2VyKTtcbiAgICAgIHRoaXMuYWxsTWFya2Vycy5wdXNoKG15TWFya2VyKTtcblxuICAgICAgLy8gQ3JlYXRlIE1hcmtlcnMgZm9yIGFsbCBUYXNrc1xuICAgICAgdGhpcy5hbGxNYXJrZXJzID0gYXdhaXQgdGhpcy5nZXRNYXJrZXJzTG9jYXRpb24obXlNYXJrZXIsIHRhc2tzKTtcblxuICAgICAgLy8gUnVuIEFsZ29yaXRobSB0byBnZXQgb3B0aW1pemVkIFJvdXRlc1xuICAgICAgY29uc3Qgc3RhcnRpbmdQb2ludCA9IHRoaXMuYWxsTWFya2Vyc1swXTtcbiAgICAgIGNvbnN0IHVudmlzaXRlZFdheXBvaW50cyA9IHRoaXMuYWxsTWFya2Vycy5zbGljZSgxKTtcbiAgICAgIGNvbnN0IG9wdGltaXplZFJvdXRlID0gbmVhcmVzdE5laWdoYm9yQWxnb3JpdGhtKFxuICAgICAgICBzdGFydGluZ1BvaW50LFxuICAgICAgICB1bnZpc2l0ZWRXYXlwb2ludHNcbiAgICAgICk7XG5cbiAgICAgIC8vIFNvcnQgQWxsIE1hcmtlcnMgYXMgcGVyIG9wdGltaXplZCByb3V0ZXNcbiAgICAgIHRoaXMuYWxsTWFya2VycyA9IHRoaXMuc29ydFRhc2tzQXNQZXJEaXN0YW5jZShcbiAgICAgICAgb3B0aW1pemVkUm91dGUsXG4gICAgICAgIHRoaXMuYWxsTWFya2VycyxcbiAgICAgICAgdHJ1ZVxuICAgICAgKTtcblxuICAgICAgLy8gU29ydCBBbGwgVGFza3MgYXMgcGVyIG9wdGltaXplZCByb3V0ZXNcbiAgICAgIHRhc2tzID0gdGhpcy5zb3J0VGFza3NBc1BlckRpc3RhbmNlKFxuICAgICAgICBvcHRpbWl6ZWRSb3V0ZS5zbGljZSgxKSxcbiAgICAgICAgdGFza3MsXG4gICAgICAgIGZhbHNlXG4gICAgICApO1xuXG4gICAgICAvLyBQbG90IE1hcmtlcnMgZm9yIEFsbCBUYXNrc1xuICAgICAgdGFza3MubWFwKCh0YXNrKSA9PiB7XG4gICAgICAgIGlmICh0YXNrPy5pc1ZhbGlkTG9jYXRpb24pIHtcbiAgICAgICAgICBjb25zdCBtYXJrZXI6IGFueSA9IHRoaXMuZ2V0TG9jYXRpb24odGFzayk7XG4gICAgICAgICAgdGhpcy5hZGRNYXJrZXIobWFya2VyKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG5cbiAgICAgIC8vIFNldCBTdHlsZXMgZm9yIGFsbCBUYXNrIFJvdXRlc1xuICAgICAgY29uc3Qgc3R5bGVzID0gW1xuICAgICAgICB7IGNvbG9yOiBcImJsdWVcIiwgb3BhY2l0eTogMSwgd2VpZ2h0OiA4IH0sXG4gICAgICAgIHsgY29sb3I6IFwid2hpdGVcIiwgb3BhY2l0eTogMC42LCB3ZWlnaHQ6IDEyIH1cbiAgICAgIF07XG5cbiAgICAgIC8vIFNldCBSb3V0ZXMgZm9yIGFsbCBUYXNrc1xuICAgICAgdGhpcy5hbGxUYXNrc1JvdXRlcyA9IHRoaXMuc2V0Um91dGVzKHRoaXMuYWxsTWFya2Vycywgc3R5bGVzKTtcbiAgICAgIHRoaXMuZml0TWFwQm91bmRzKCk7XG4gICAgfVxuICAgIHJldHVybiB0YXNrcztcbiAgfVxuXG4gIC8vIFRvIHBsb3QgT3BlbiBTdHJlZXQgRGlyZWN0aW9uIGZvciBzZWxlY3RlZCBUYXNrXG4gIHBsb3REaXJlY3Rpb25zRm9yU2VsZWN0ZWRUYXNrKHRhc2spIHtcbiAgICBpZiAodGFzayAhPT0gbnVsbCkge1xuICAgICAgLy8gUmVtb3ZlIFByZXZpb3VzbHkgU2VsZWN0ZWQgVGFzayBSb3V0ZVxuICAgICAgaWYgKHRoaXMuc2VsZWN0ZWRUYXNrUm91dGVzKSB7XG4gICAgICAgIHRoaXMubWFwLnJlbW92ZUNvbnRyb2wodGhpcy5zZWxlY3RlZFRhc2tSb3V0ZXMpO1xuICAgICAgfVxuXG4gICAgICAvLyBSZW1vdmUgQWxsIFRhc2tzIFJvdXRlc1xuICAgICAgaWYgKHRoaXMuYWxsVGFza3NSb3V0ZXMpIHtcbiAgICAgICAgdGhpcy5tYXAucmVtb3ZlQ29udHJvbCh0aGlzLmFsbFRhc2tzUm91dGVzKTtcbiAgICAgIH1cblxuICAgICAgY29uc3QgdGFza01hcmtlciA9IHRhc2s7XG5cbiAgICAgIC8vIElmIExvY2F0aW9uIGlzIEF2YWlsYWJsZSBpbiBUYXNrIERldGFpbHNcbiAgICAgIGlmICh0YXNrTWFya2VyLmNvbG9yICE9IFwicmVkXCIpIHtcbiAgICAgICAgY29uc3QgbWFya2VycyA9IFt0aGlzLmFsbE1hcmtlcnNbMF0sIHRhc2tNYXJrZXJdO1xuICAgICAgICBjb25zdCBzdHlsZXMgPSBbXG4gICAgICAgICAgeyBjb2xvcjogXCJncmVlblwiLCBvcGFjaXR5OiAxLCB3ZWlnaHQ6IDggfSxcbiAgICAgICAgICB7IGNvbG9yOiBcIndoaXRlXCIsIG9wYWNpdHk6IDAuNCwgd2VpZ2h0OiAxMiB9XG4gICAgICAgIF07XG4gICAgICAgIHRoaXMuc2VsZWN0ZWRUYXNrUm91dGVzID0gdGhpcy5zZXRSb3V0ZXMobWFya2Vycywgc3R5bGVzKTtcbiAgICAgICAgdGhpcy5zZXRTZWxlY3RlZFRhc2tEaXN0YW5jZUFuZFRpbWUoKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGFsZXJ0KFwiTm8gTG9jYXRpb24gQXZhaWxhYmxlXCIpO1xuICAgICAgfVxuICAgIH1cbiAgICAvLyBTZXQgQWxsIFRhc2tzIFJvdXRlcyBBZ2FpbiAmIFJlbW92ZSBTZWxlY3RlZCBUYXNrcyByb3V0ZVxuICAgIGVsc2Uge1xuICAgICAgaWYgKHRoaXMuc2VsZWN0ZWRUYXNrUm91dGVzKSB7XG4gICAgICAgIHRoaXMubWFwLnJlbW92ZUNvbnRyb2wodGhpcy5zZWxlY3RlZFRhc2tSb3V0ZXMpO1xuICAgICAgfVxuICAgICAgdGhpcy5tYXAuYWRkQ29udHJvbCh0aGlzLmFsbFRhc2tzUm91dGVzKTtcbiAgICAgIHRoaXMuc2VsZWN0ZWRUYXNrUm91dGVzID0gdW5kZWZpbmVkO1xuICAgIH1cbiAgICB0aGlzLmZpdE1hcEJvdW5kcygpO1xuICB9XG5cbiAgLy8gR2V0IERpc3RhbmNlICYgVGltZSBvZiBTZWxlY3RlZCBUYXNrXG4gIGdldFNlbGVjdGVkVGFza0Rpc3RhbmNlQW5kVGltZSgpIHtcbiAgICByZXR1cm4gdGhpcy5zZWxlY3RlZFRhc2tEaXN0YW5jZUFuZFRpbWU7XG4gIH1cblxuICAvLyBTZXQgRGlzdGFuY2UgJiBUaW1lIG9mIFNlbGVjdGVkIFRhc2tcbiAgc2V0U2VsZWN0ZWRUYXNrRGlzdGFuY2VBbmRUaW1lKCkge1xuICAgIHRoaXMuc2VsZWN0ZWRUYXNrUm91dGVzLm9uKFwicm91dGVzZm91bmRcIiwgZnVuY3Rpb24oZSkge1xuICAgICAgY29uc3QgeyByb3V0ZXMgfSA9IGU7XG4gICAgICBjb25zdCB7IHN1bW1hcnkgfSA9IHJvdXRlc1swXTtcblxuICAgICAgY29uc3QgZGlzdGFuY2UgPSBzdW1tYXJ5LnRvdGFsRGlzdGFuY2UgLyAxMDAwO1xuICAgICAgY29uc3QgdGltZSA9IE1hdGgucm91bmQoKHN1bW1hcnkudG90YWxUaW1lICUgMzYwMCkgLyA2MCk7XG5cbiAgICAgIHRoaXMuc2VsZWN0ZWRUYXNrRGlzdGFuY2VBbmRUaW1lID0ge1xuICAgICAgICBkaXN0YW5jZSxcbiAgICAgICAgdGltZVxuICAgICAgfTtcbiAgICB9KTtcbiAgfVxuXG4gIC8vIFRvIHNvcnQgT3BlbiBTdHJlZXQgTWFwcyBUYXNrIGFzIHBlciBuZWFyZXN0IGRpc3RhbmNlXG4gIHNvcnRUYXNrc0FzUGVyRGlzdGFuY2Uob3JkZXIsIHRhc2tzLCBpc01hcmtlcikge1xuICAgIGNvbnN0IHNvcnRlZFRhc2tzID0gW107XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0YXNrcy5sZW5ndGg7IGkrKykge1xuICAgICAgY29uc3QgdGl0bGUgPSBpc01hcmtlciA/IG9yZGVyW2ldLnRpdGxlIDogb3JkZXJbaV0udGl0bGUgLSAxO1xuICAgICAgY29uc3QgdGFzayA9IHRhc2tzW3RpdGxlXTtcbiAgICAgIHNvcnRlZFRhc2tzLnB1c2godGFzayk7XG4gICAgfVxuICAgIHJldHVybiBzb3J0ZWRUYXNrcztcbiAgfVxuXG4gIC8vIFRvIHNldCBPcGVuIFN0cmVldCByb3V0ZXMgaW4gdGhlIG1hcHNcbiAgc2V0Um91dGVzKG1hcmtlcnMsIHN0eWxlcykge1xuICAgIHJldHVybiBMLlJvdXRpbmcuY29udHJvbCh7XG4gICAgICB3YXlwb2ludHM6IG1hcmtlcnMsXG4gICAgICBsaW5lT3B0aW9uczoge1xuICAgICAgICBzdHlsZXNcbiAgICAgIH0sXG4gICAgICBjcmVhdGVNYXJrZXIoKSB7XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgICAgfSxcbiAgICAgIHJvdXRlV2hpbGVEcmFnZ2luZzogdHJ1ZVxuICAgIH0pLmFkZFRvKHRoaXMubWFwKTtcbiAgfVxuXG4gIC8vIFRvIHNldCBPcGVuIFN0cmVldCB2aWV3IHBvaW50IG9uIHRoZSBtYXBcbiAgZml0TWFwQm91bmRzKCkge1xuICAgIGNvbnN0IG1hcmtlckxhdExuZ3MgPSB0aGlzLmFsbE1hcmtlcnMubWFwKChtYXJrZXIpID0+XG4gICAgICBMLmxhdExuZyhtYXJrZXIubGF0LCBtYXJrZXIubG5nKVxuICAgICk7XG4gICAgdGhpcy5tYXAuZml0Qm91bmRzKG1hcmtlckxhdExuZ3MpO1xuICB9XG59XG4iXX0=