kwikid-agent-dashboard 0.0.21 → 0.0.22

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,62 +1,160 @@
1
1
  import { __awaiter } from "tslib";
2
2
  import { Injectable, ViewChildren } from '@angular/core';
3
- import { map } from 'rxjs/operators';
3
+ import * as L from 'leaflet';
4
+ import 'leaflet-routing-machine';
5
+ import { checkObjectPathExists, getObjectValueFromPath } from 'kwikid-toolkit';
4
6
  import * as i0 from "@angular/core";
5
- import * as i1 from "@angular/google-maps";
7
+ import * as i1 from "./agent.service";
6
8
  export class MapService {
7
- constructor(mapDirectionsService) {
8
- this.mapDirectionsService = mapDirectionsService;
9
- this.markers = [];
10
- this.directionsRenderOption = {};
11
- }
12
- getMarkers() {
13
- return this.markers;
14
- }
15
- setMarkers(markers) {
16
- this.markers = markers;
9
+ constructor(agentService) {
10
+ this.agentService = agentService;
11
+ this.allMarkers = [];
17
12
  }
13
+ // To Initialize Map
18
14
  initMap() {
19
15
  return __awaiter(this, void 0, void 0, function* () {
20
16
  this.myPosition = yield this.getPosition();
21
- this.map = {
22
- zoom: 10,
23
- center: this.myPosition,
24
- streetViewControl: false,
25
- mapTypeControl: false,
26
- fullscreenControl: false,
27
- zoomControl: false
28
- };
17
+ this.map = L.map('map', {
18
+ center: [this.myPosition.lat, this.myPosition.lng],
19
+ zoom: 13
20
+ });
21
+ L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png').addTo(this.map);
29
22
  });
30
23
  }
31
- plotMarkers(customers) {
32
- this.markers = [];
33
- let path = [];
34
- this.markers.push(this.myPosition);
35
- const request = {
36
- origin: this.myPosition,
37
- destination: this.myPosition,
38
- waypoints: path,
39
- optimizeWaypoints: true,
40
- travelMode: google.maps.TravelMode.DRIVING
41
- };
42
- this.directionsRenderOption = {
43
- suppressMarkers: true
44
- };
45
- this.directionsResults$ = this.mapDirectionsService
46
- .route(request)
47
- .pipe(map((response) => response.result));
48
- this.directionsResults$.subscribe((val) => {
49
- customers = this.sortList(val.routes[0].waypoint_order, customers);
50
- customers.map((customer) => {
51
- path.push({
52
- location: this.getLatLng(customer.task_details.customer_details.location),
53
- stopover: true
54
- });
55
- this.markers.push(this.getLatLng(customer.task_details.customer_details.location));
24
+ // To Add Marker in Map
25
+ addMarker({ lat, lng, title, color }) {
26
+ L.marker([lat, lng], {
27
+ icon: L.icon({
28
+ iconUrl: color == 'red' ? 'assets/map-marker-0.png' : 'assets/map-marker-1.png'
29
+ })
30
+ })
31
+ .addTo(this.map)
32
+ .bindPopup(title);
33
+ }
34
+ // To Plot Directions for All Tasks
35
+ plotDirectionsForAllTasks(tasks) {
36
+ if (this.map) {
37
+ this.allMarkers = [];
38
+ // Create Agent Marker & Plot It.
39
+ const myMarker = {
40
+ lat: this.myPosition.lat,
41
+ lng: this.myPosition.lng,
42
+ title: 0,
43
+ color: 'red'
44
+ };
45
+ this.addMarker(myMarker);
46
+ this.allMarkers.push(myMarker);
47
+ // Create Markers for all Tasks
48
+ tasks.map((task, index) => {
49
+ const marker = this.getLatLng(this.getLocation(task), index);
50
+ this.allMarkers.push(marker);
56
51
  });
52
+ // Run Algorithm to get optimized Routes
53
+ const startingPoint = this.allMarkers[0];
54
+ const unvisitedWaypoints = this.allMarkers.slice(1);
55
+ const optimizedRoute = this.nearestNeighborAlgorithm(startingPoint, unvisitedWaypoints);
56
+ // Sort All Markers as per optimized routes
57
+ this.allMarkers = this.sortTasksAsPerDistance(optimizedRoute, this.allMarkers, true);
58
+ // Sort All Tasks as per optimized routes
59
+ tasks = this.sortTasksAsPerDistance(optimizedRoute.slice(1), tasks, false);
60
+ // Plot Markers for All Tasks
61
+ tasks.map((task, index) => {
62
+ const marker = this.getLatLng(this.getLocation(task), index);
63
+ this.addMarker(marker);
64
+ });
65
+ // Set Styles for all Task Routes
66
+ const styles = [
67
+ { color: 'blue', opacity: 1, weight: 8 },
68
+ { color: 'white', opacity: 0.6, weight: 12 }
69
+ ];
70
+ // Set Routes for all Tasks
71
+ this.allTasksRoutes = this.setRoutes(this.allMarkers, styles);
72
+ this.fitMapBounds();
73
+ }
74
+ return tasks;
75
+ }
76
+ // To plot Direction for selected Task
77
+ plotDirectionsForSelectedTask(index) {
78
+ if (index !== null) {
79
+ // Remove Previously Selected Task Route
80
+ if (this.selectedTaskRoutes) {
81
+ this.map.removeControl(this.selectedTaskRoutes);
82
+ }
83
+ // Remove All Tasks Routes
84
+ if (this.allTasksRoutes) {
85
+ this.map.removeControl(this.allTasksRoutes);
86
+ }
87
+ const taskMarker = this.allMarkers[index + 1];
88
+ // If Location is Available in Task Details
89
+ if (taskMarker.color != 'red') {
90
+ const markers = [this.allMarkers[0], taskMarker];
91
+ const styles = [
92
+ { color: 'green', opacity: 1, weight: 8 },
93
+ { color: 'white', opacity: 0.4, weight: 12 }
94
+ ];
95
+ this.selectedTaskRoutes = this.setRoutes(markers, styles);
96
+ this.setSelectedTaskDistanceAndTime();
97
+ }
98
+ else {
99
+ alert('No Location Available');
100
+ }
101
+ }
102
+ // Set All Tasks Routes Again & Remove Selected Tasks route
103
+ else {
104
+ if (this.selectedTaskRoutes) {
105
+ this.map.removeControl(this.selectedTaskRoutes);
106
+ }
107
+ this.map.addControl(this.allTasksRoutes);
108
+ this.selectedTaskRoutes = undefined;
109
+ }
110
+ this.fitMapBounds();
111
+ }
112
+ // Get Distance & Time of Selected Task
113
+ getSelectedTaskDistanceAndTime() {
114
+ return this.selectedTaskDistanceAndTime;
115
+ }
116
+ // Set Distance & Time of Selected Task
117
+ setSelectedTaskDistanceAndTime() {
118
+ this.selectedTaskRoutes.on('routesfound', function (e) {
119
+ let routes = e.routes;
120
+ let summary = routes[0].summary;
121
+ const distance = summary.totalDistance / 1000;
122
+ const time = Math.round((summary.totalTime % 3600) / 60);
123
+ this.selectedTaskDistanceAndTime = {
124
+ distance: distance,
125
+ time: time
126
+ };
57
127
  });
58
- return this.directionsResults$;
59
128
  }
129
+ // To sort Task as per nearest distance
130
+ sortTasksAsPerDistance(order, tasks, isMarker) {
131
+ let sortedTasks = [];
132
+ for (let i = 0; i < tasks.length; i++) {
133
+ const title = isMarker ? order[i].title : order[i].title - 1;
134
+ let task = tasks[title];
135
+ sortedTasks.push(task);
136
+ }
137
+ return sortedTasks;
138
+ }
139
+ // To set routes in the maps
140
+ setRoutes(markers, styles) {
141
+ return L.Routing.control({
142
+ waypoints: markers,
143
+ lineOptions: {
144
+ styles: styles
145
+ },
146
+ createMarker: function () {
147
+ return null;
148
+ },
149
+ routeWhileDragging: true
150
+ }).addTo(this.map);
151
+ }
152
+ // To set view point on the map
153
+ fitMapBounds() {
154
+ const markerLatLngs = this.allMarkers.map((marker) => L.latLng(marker.lat, marker.lng));
155
+ this.map.fitBounds(markerLatLngs);
156
+ }
157
+ // To get Current Position
60
158
  getPosition() {
61
159
  return new Promise((resolve, reject) => {
62
160
  navigator.geolocation.watchPosition((resp) => {
@@ -69,31 +167,86 @@ export class MapService {
69
167
  });
70
168
  });
71
169
  }
72
- getLatLng(data) {
73
- let url = data.split('@');
74
- let lat_long_match = url[1].split(',');
75
- let lat = Number(lat_long_match[0]);
76
- let long = Number(lat_long_match[1]);
77
- return { lat: lat, lng: long };
170
+ // To extract Location from the Task Details
171
+ getLocation(task) {
172
+ var _a, _b, _c, _d, _e, _f;
173
+ if (checkObjectPathExists(this.agentService.config, 'dashboard.taskLocationPath')) {
174
+ const location = getObjectValueFromPath(task, this.agentService.config.dashboard.taskLocationPath);
175
+ return location;
176
+ }
177
+ else {
178
+ return ((_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.location) !== 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.location);
179
+ }
180
+ }
181
+ // To get Latitude & Longitude from Task Location
182
+ getLatLng(data, index) {
183
+ try {
184
+ const url = data.split('@');
185
+ const lat_long_match = url[1].split(',');
186
+ const lat = Number(lat_long_match[0]);
187
+ const long = Number(lat_long_match[1]);
188
+ return { lat: lat, lng: long, title: index + 1, color: 'blue' };
189
+ }
190
+ catch (_a) {
191
+ // If could not find Google Maps Location URL in Task
192
+ return {
193
+ lat: this.myPosition.lat,
194
+ lng: this.myPosition.lng,
195
+ title: index + 1,
196
+ color: 'red'
197
+ };
198
+ }
199
+ }
200
+ // To Calculate Distance between two markers
201
+ calculateDistance(point1, point2) {
202
+ const lat1 = point1.lat;
203
+ const lng1 = point1.lng;
204
+ const lat2 = point2.lat;
205
+ const lng2 = point2.lng;
206
+ const R = 6371; // Earth radius in kilometers
207
+ const dLat = (lat2 - lat1) * (Math.PI / 180);
208
+ const dLng = (lng2 - lng1) * (Math.PI / 180);
209
+ const a = Math.sin(dLat / 2) * Math.sin(dLat / 2) +
210
+ Math.cos((lat1 * Math.PI) / 180) *
211
+ Math.cos((lat2 * Math.PI) / 180) *
212
+ Math.sin(dLng / 2) *
213
+ Math.sin(dLng / 2);
214
+ const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
215
+ const distance = R * c;
216
+ return distance;
78
217
  }
79
- sortList(order, customersData) {
80
- let c = [];
81
- for (let i = 0; i < customersData.length; i++) {
82
- let customer = customersData[order[i]];
83
- c.push(customer);
218
+ // To calculate nearest distance from marker
219
+ nearestNeighborAlgorithm(startingPoint, unvisitedPoints) {
220
+ let currentPoint = startingPoint;
221
+ const path = [currentPoint];
222
+ const visitedPoints = new Set([currentPoint]);
223
+ while (unvisitedPoints.length > 0) {
224
+ let nearestPoint = null;
225
+ let minDistance = Number.POSITIVE_INFINITY;
226
+ for (const point of unvisitedPoints) {
227
+ const distance = this.calculateDistance(currentPoint, point);
228
+ if (distance < minDistance) {
229
+ minDistance = distance;
230
+ nearestPoint = point;
231
+ }
232
+ }
233
+ path.push(nearestPoint);
234
+ visitedPoints.add(nearestPoint);
235
+ currentPoint = nearestPoint;
236
+ unvisitedPoints = unvisitedPoints.filter((point) => !visitedPoints.has(point));
84
237
  }
85
- return c;
238
+ return path;
86
239
  }
87
240
  }
88
- /** @nocollapse */ MapService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.17", ngImport: i0, type: MapService, deps: [{ token: i1.MapDirectionsService }], target: i0.ɵɵFactoryTarget.Injectable });
241
+ /** @nocollapse */ MapService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.17", ngImport: i0, type: MapService, deps: [{ token: i1.AgentService }], target: i0.ɵɵFactoryTarget.Injectable });
89
242
  /** @nocollapse */ MapService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "12.2.17", ngImport: i0, type: MapService, providedIn: 'root' });
90
243
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.17", ngImport: i0, type: MapService, decorators: [{
91
244
  type: Injectable,
92
245
  args: [{
93
246
  providedIn: 'root'
94
247
  }]
95
- }], ctorParameters: function () { return [{ type: i1.MapDirectionsService }]; }, propDecorators: { directionsRenders: [{
248
+ }], ctorParameters: function () { return [{ type: i1.AgentService }]; }, propDecorators: { directionsRenders: [{
96
249
  type: ViewChildren,
97
250
  args: ['directionsRender']
98
251
  }] } });
99
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWFwLnNlcnZpY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9rd2lraWQtYWdlbnQtZGFzaGJvYXJkL3NyYy9saWIvc2VydmljZXMvbWFwLnNlcnZpY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLE9BQU8sRUFBYyxVQUFVLEVBQWEsWUFBWSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBRWhGLE9BQU8sRUFBRSxHQUFHLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQzs7O0FBU3JDLE1BQU0sT0FBTyxVQUFVO0lBYXJCLFlBQW1CLG9CQUEwQztRQUExQyx5QkFBb0IsR0FBcEIsb0JBQW9CLENBQXNCO1FBVDdELFlBQU8sR0FBUSxFQUFFLENBQUM7UUFHbEIsMkJBQXNCLEdBQUcsRUFBRSxDQUFDO0lBTW9DLENBQUM7SUFFakUsVUFBVTtRQUNSLE9BQU8sSUFBSSxDQUFDLE9BQU8sQ0FBQztJQUN0QixDQUFDO0lBRUQsVUFBVSxDQUFDLE9BQU87UUFDaEIsSUFBSSxDQUFDLE9BQU8sR0FBRyxPQUFPLENBQUM7SUFDekIsQ0FBQztJQUVLLE9BQU87O1lBQ1gsSUFBSSxDQUFDLFVBQVUsR0FBRyxNQUFNLElBQUksQ0FBQyxXQUFXLEVBQUUsQ0FBQztZQUUzQyxJQUFJLENBQUMsR0FBRyxHQUFHO2dCQUNULElBQUksRUFBRSxFQUFFO2dCQUNSLE1BQU0sRUFBRSxJQUFJLENBQUMsVUFBVTtnQkFDdkIsaUJBQWlCLEVBQUUsS0FBSztnQkFDeEIsY0FBYyxFQUFFLEtBQUs7Z0JBQ3JCLGlCQUFpQixFQUFFLEtBQUs7Z0JBQ3hCLFdBQVcsRUFBRSxLQUFLO2FBQ25CLENBQUM7UUFDSixDQUFDO0tBQUE7SUFFRCxXQUFXLENBQUMsU0FBUztRQUNuQixJQUFJLENBQUMsT0FBTyxHQUFHLEVBQUUsQ0FBQztRQUNsQixJQUFJLElBQUksR0FBRyxFQUFFLENBQUM7UUFFZCxJQUFJLENBQUMsT0FBTyxDQUFDLElBQUks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QUM3QyxJQUFJLFFBQVEsR0FBRyxhQUFhLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7WUFDdkMsQ0FBQyxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQztTQUNsQjtRQUVELE9BQU8sQ0FBQyxDQUFDO0lBQ1gsQ0FBQzs7MkhBN0dVLFVBQVU7K0hBQVYsVUFBVSxjQUZULE1BQU07NEZBRVAsVUFBVTtrQkFIdEIsVUFBVTttQkFBQztvQkFDVixVQUFVLEVBQUUsTUFBTTtpQkFDbkI7MkdBVW1DLGlCQUFpQjtzQkFBbEQsWUFBWTt1QkFBQyxrQkFBa0IiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBFbGVtZW50UmVmLCBJbmplY3RhYmxlLCBRdWVyeUxpc3QsIFZpZXdDaGlsZHJlbiB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgbG9nTWV0aG9kIH0gZnJvbSAna3dpa2lkLXRvb2xraXQnO1xuaW1wb3J0IHsgbWFwIH0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xuXG5pbXBvcnQgeyBNYXBEaXJlY3Rpb25zU2VydmljZSB9IGZyb20gJ0Bhbmd1bGFyL2dvb2dsZS1tYXBzJztcblxuZGVjbGFyZSBjb25zdCBnb29nbGU6IGFueTtcblxuQEluamVjdGFibGUoe1xuICBwcm92aWRlZEluOiAncm9vdCdcbn0pXG5leHBvcnQgY2xhc3MgTWFwU2VydmljZSB7XG4gIG15UG9zaXRpb247XG4gIG1hcDogYW55O1xuXG4gIG1hcmtlcnM6IGFueSA9IFtdO1xuXG4gIGRpcmVjdGlvbnNSZXN1bHRzJDtcbiAgZGlyZWN0aW9uc1JlbmRlck9wdGlvbiA9IHt9O1xuXG4gIEBWaWV3Q2hpbGRyZW4oJ2RpcmVjdGlvbnNSZW5kZXInKSBkaXJlY3Rpb25zUmVuZGVyczogUXVlcnlMaXN0PFxuICAgIEVsZW1lbnRSZWY8Z29vZ2xlLm1hcHMuRGlyZWN0aW9uc1JlbmRlcmVyPlxuICA+O1xuXG4gIGNvbnN0cnVjdG9yKHB1YmxpYyBtYXBEaXJlY3Rpb25zU2VydmljZTogTWFwRGlyZWN0aW9uc1NlcnZpY2UpIHt9XG5cbiAgZ2V0TWFya2VycygpIHtcbiAgICByZXR1cm4gdGhpcy5tYXJrZXJzO1xuICB9XG5cbiAgc2V0TWFya2VycyhtYXJrZXJzKSB7XG4gICAgdGhpcy5tYXJrZXJzID0gbWFya2VycztcbiAgfVxuXG4gIGFzeW5jIGluaXRNYXAoKSB7XG4gICAgdGhpcy5teVBvc2l0aW9uID0gYXdhaXQgdGhpcy5nZXRQb3NpdGlvbigpO1xuXG4gICAgdGhpcy5tYXAgPSB7XG4gICAgICB6b29tOiAxMCxcbiAgICAgIGNlbnRlcjogdGhpcy5teVBvc2l0aW9uLFxuICAgICAgc3RyZWV0Vmlld0NvbnRyb2w6IGZhbHNlLFxuICAgICAgbWFwVHlwZUNvbnRyb2w6IGZhbHNlLFxuICAgICAgZnVsbHNjcmVlbkNvbnRyb2w6IGZhbHNlLFxuICAgICAgem9vbUNvbnRyb2w6IGZhbHNlXG4gICAgfTtcbiAgfVxuXG4gIHBsb3RNYXJrZXJzKGN1c3RvbWVycykge1xuICAgIHRoaXMubWFya2VycyA9IFtdO1xuICAgIGxldCBwYXRoID0gW107XG5cbiAgICB0aGlzLm1hcmtlcnMucHVzaCh0aGlzLm15UG9zaXRpb24pO1xuXG4gICAgY29uc3QgcmVxdWVzdDogZ29vZ2xlLm1hcHMuRGlyZWN0aW9uc1JlcXVlc3QgPSB7XG4gICAgICBvcmlnaW46IHRoaXMubXlQb3NpdGlvbixcbiAgICAgIGRlc3RpbmF0aW9uOiB0aGlzLm15UG9zaXRpb24sXG4gICAgICB3YXlwb2ludHM6IHBhdGgsXG4gICAgICBvcHRpbWl6ZVdheXBvaW50czogdHJ1ZSxcbiAgICAgIHRyYXZlbE1vZGU6IGdvb2dsZS5tYXBzLlRyYXZlbE1vZGUuRFJJVklOR1xuICAgIH07XG5cbiAgICB0aGlzLmRpcmVjdGlvbnNSZW5kZXJPcHRpb24gPSB7XG4gICAgICBzdXBwcmVzc01hcmtlcnM6IHRydWVcbiAgICB9O1xuXG4gICAgdGhpcy5kaXJlY3Rpb25zUmVzdWx0cyQgPSB0aGlzLm1hcERpcmVjdGlvbnNTZXJ2aWNlXG4gICAgICAucm91dGUocmVxdWVzdClcbiAgICAgIC5waXBlKG1hcCgocmVzcG9uc2UpID0+IHJlc3BvbnNlLnJlc3VsdCkpO1xuXG4gICAgdGhpcy5kaXJlY3Rpb25zUmVzdWx0cyQuc3Vic2NyaWJlKCh2YWwpID0+IHtcbiAgICAgIGN1c3RvbWVycyA9IHRoaXMuc29ydExpc3QodmFsLnJvdXRlc1swXS53YXlwb2ludF9vcmRlciwgY3VzdG9tZXJzKTtcbiAgICAgIGN1c3RvbWVycy5tYXAoKGN1c3RvbWVyKSA9PiB7XG4gICAgICAgIHBhdGgucHVzaCh7XG4gICAgICAgICAgbG9jYXRpb246IHRoaXMuZ2V0TGF0TG5nKFxuICAgICAgICAgICAgY3VzdG9tZXIudGFza19kZXRhaWxzLmN1c3RvbWVyX2RldGFpbHMubG9jYXRpb25cbiAgICAgICAgICApLFxuICAgICAgICAgIHN0b3BvdmVyOiB0cnVlXG4gICAgICAgIH0pO1xuXG4gICAgICAgIHRoaXMubWFya2Vycy5wdXNoKFxuICAgICAgICAgIHRoaXMuZ2V0TGF0TG5nKGN1c3RvbWVyLnRhc2tfZGV0YWlscy5jdXN0b21lcl9kZXRhaWxzLmxvY2F0aW9uKVxuICAgICAgICApO1xuICAgICAgfSk7XG4gICAgfSk7XG5cbiAgICByZXR1cm4gdGhpcy5kaXJlY3Rpb25zUmVzdWx0cyQ7XG4gIH1cblxuICBnZXRQb3NpdGlvbigpOiBQcm9taXNlPGFueT4ge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICBuYXZpZ2F0b3IuZ2VvbG9jYXRpb24ud2F0Y2hQb3NpdGlvbihcbiAgICAgICAgKHJlc3ApID0+IHtcbiAgICAgICAgICByZXNvbHZlKHtcbiAgICAgICAgICAgIGxuZzogcmVzcC5jb29yZHMubG9uZ2l0dWRlLFxuICAgICAgICAgICAgbGF0OiByZXNwLmNvb3Jkcy5sYXRpdHVkZVxuICAgICAgICAgIH0pO1xuICAgICAgICB9LFxuICAgICAgICAoZXJyKSA9PiB7XG4gICAgICAgICAgcmVqZWN0KGVycik7XG4gICAgICAgIH1cbiAgICAgICk7XG4gICAgfSk7XG4gIH1cblxuICBnZXRMYXRMbmcoZGF0YSkge1xuICAgIGxldCB1cmwgPSBkYXRhLnNwbGl0KCdAJyk7XG4gICAgbGV0IGxhdF9sb25nX21hdGNoID0gdXJsWzFdLnNwbGl0KCcsJyk7XG4gICAgbGV0IGxhdCA9IE51bWJlcihsYXRfbG9uZ19tYXRjaFswXSk7XG4gICAgbGV0IGxvbmcgPSBOdW1iZXIobGF0X2xvbmdfbWF0Y2hbMV0pO1xuICAgIHJldHVybiB7IGxhdDogbGF0LCBsbmc6IGxvbmcgfTtcbiAgfVxuXG4gIHNvcnRMaXN0KG9yZGVyLCBjdXN0b21lcnNEYXRhKSB7XG4gICAgbGV0IGMgPSBbXTtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGN1c3RvbWVyc0RhdGEubGVuZ3RoOyBpKyspIHtcbiAgICAgIGxldCBjdXN0b21lciA9IGN1c3RvbWVyc0RhdGFbb3JkZXJbaV1dO1xuICAgICAgYy5wdXNoKGN1c3RvbWVyKTtcbiAgICB9XG5cbiAgICByZXR1cm4gYztcbiAgfVxufVxuIl19
252
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWFwLnNlcnZpY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9rd2lraWQtYWdlbnQtZGFzaGJvYXJkL3NyYy9saWIvc2VydmljZXMvbWFwLnNlcnZpY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLE9BQU8sRUFBYyxVQUFVLEVBQWEsWUFBWSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQ2hGLE9BQU8sS0FBSyxDQUFDLE1BQU0sU0FBUyxDQUFDO0FBQzdCLE9BQU8seUJBQXlCLENBQUM7QUFFakMsT0FBTyxFQUFFLHFCQUFxQixFQUFFLHNCQUFzQixFQUFFLE1BQU0sZ0JBQWdCLENBQUM7OztBQUsvRSxNQUFNLE9BQU8sVUFBVTtJQWFyQixZQUFvQixZQUEwQjtRQUExQixpQkFBWSxHQUFaLFlBQVksQ0FBYztRQVY5QyxlQUFVLEdBQVEsRUFBRSxDQUFDO0lBVTRCLENBQUM7SUFFbEQsb0JBQW9CO0lBQ2QsT0FBTzs7WUFDWCxJQUFJLENBQUMsVUFBVSxHQUFHLE1BQU0sSUFBSSxDQUFDLFdBQVcsRUFBRSxDQUFDO1lBQzNDLElBQUksQ0FBQyxHQUFHLEdBQUcsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxLQUFLLEVBQUU7Z0JBQ3RCLE1BQU0sRUFBRSxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsR0FBRyxFQUFFLElBQUksQ0FBQyxVQUFVLENBQUMsR0FBRyxDQUFDO2dCQUNsRCxJQUFJLEVBQUUsRUFBRTthQUNULENBQUMsQ0FBQztZQUNILENBQUMsQ0FBQyxTQUFTLENBQUMsb0RBQW9ELENBQUMsQ0FBQyxLQUFLLENBQ3JFLElBQUksQ0FBQyxHQUFHLENBQ1QsQ0FBQztRQUNKLENBQUM7S0FBQTtJQUVELHVCQUF1QjtJQUN2QixTQUFTLENBQUMsRUFBRSxHQUFHLEVBQUUsR0FBRyxFQUFFLEtBQUssRUFBRSxLQUFLLEVBQUU7UUFDbEMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFDLEdBQUcsRUFB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V0FBVyxFQUFFO29CQUMxQixXQUFXLEdBQUcsUUFBUSxDQUFDO29CQUN2QixZQUFZLEdBQUcsS0FBSyxDQUFDO2lCQUN0QjthQUNGO1lBRUQsSUFBSSxDQUFDLElBQUksQ0FBQyxZQUFZLENBQUMsQ0FBQztZQUN4QixhQUFhLENBQUMsR0FBRyxDQUFDLFlBQVksQ0FBQyxDQUFDO1lBQ2hDLFlBQVksR0FBRyxZQUFZLENBQUM7WUFFNUIsZUFBZSxHQUFHLGVBQWUsQ0FBQyxNQUFNLENBQ3RDLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FBQyxDQUFDLGFBQWEsQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLENBQ3JDLENBQUM7U0FDSDtRQUVELE9BQU8sSUFBSSxDQUFDO0lBQ2QsQ0FBQzs7MkhBN1NVLFVBQVU7K0hBQVYsVUFBVSxjQUZULE1BQU07NEZBRVAsVUFBVTtrQkFIdEIsVUFBVTttQkFBQztvQkFDVixVQUFVLEVBQUUsTUFBTTtpQkFDbkI7bUdBVW1DLGlCQUFpQjtzQkFBbEQsWUFBWTt1QkFBQyxrQkFBa0IiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBFbGVtZW50UmVmLCBJbmplY3RhYmxlLCBRdWVyeUxpc3QsIFZpZXdDaGlsZHJlbiB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0ICogYXMgTCBmcm9tICdsZWFmbGV0JztcbmltcG9ydCAnbGVhZmxldC1yb3V0aW5nLW1hY2hpbmUnO1xuaW1wb3J0IHsgQWdlbnRTZXJ2aWNlIH0gZnJvbSAnLi9hZ2VudC5zZXJ2aWNlJztcbmltcG9ydCB7IGNoZWNrT2JqZWN0UGF0aEV4aXN0cywgZ2V0T2JqZWN0VmFsdWVGcm9tUGF0aCB9IGZyb20gJ2t3aWtpZC10b29sa2l0JztcblxuQEluamVjdGFibGUoe1xuICBwcm92aWRlZEluOiAncm9vdCdcbn0pXG5leHBvcnQgY2xhc3MgTWFwU2VydmljZSB7XG4gIG15UG9zaXRpb247XG4gIG1hcDogYW55O1xuICBhbGxNYXJrZXJzOiBhbnkgPSBbXTtcblxuICBhbGxUYXNrc1JvdXRlczogYW55O1xuICBzZWxlY3RlZFRhc2tSb3V0ZXM6IGFueTtcbiAgc2VsZWN0ZWRUYXNrRGlzdGFuY2VBbmRUaW1lOiBhbnk7XG5cbiAgQFZpZXdDaGlsZHJlbignZGlyZWN0aW9uc1JlbmRlcicpIGRpcmVjdGlvbnNSZW5kZXJzOiBRdWVyeUxpc3Q8XG4gICAgRWxlbWVudFJlZjxnb29nbGUubWFwcy5EaXJlY3Rpb25zUmVuZGVyZXI+XG4gID47XG5cbiAgY29uc3RydWN0b3IocHJpdmF0ZSBhZ2VudFNlcnZpY2U6IEFnZW50U2VydmljZSkge31cblxuICAvLyBUbyBJbml0aWFsaXplIE1hcFxuICBhc3luYyBpbml0TWFwKCkge1xuICAgIHRoaXMubXlQb3NpdGlvbiA9IGF3YWl0IHRoaXMuZ2V0UG9zaXRpb24oKTtcbiAgICB0aGlzLm1hcCA9IEwubWFwKCdtYXAnLCB7XG4gICAgICBjZW50ZXI6IFt0aGlzLm15UG9zaXRpb24ubGF0LCB0aGlzLm15UG9zaXRpb24ubG5nXSxcbiAgICAgIHpvb206IDEzXG4gICAgfSk7XG4gICAgTC50aWxlTGF5ZXIoJ2h0dHBzOi8ve3N9LnRpbGUub3BlbnN0cmVldG1hcC5vcmcve3p9L3t4fS97eX0ucG5nJykuYWRkVG8oXG4gICAgICB0aGlzLm1hcFxuICAgICk7XG4gIH1cblxuICAvLyBUbyBBZGQgTWFya2VyIGluIE1hcFxuICBhZGRNYXJrZXIoeyBsYXQsIGxuZywgdGl0bGUsIGNvbG9yIH0pIHtcbiAgICBMLm1hcmtlcihbbGF0LCBsbmddLCB7XG4gICAgICBpY29uOiBMLmljb24oe1xuICAgICAgICBpY29uVXJsOlxuICAgICAgICAgIGNvbG9yID09ICdyZWQnID8gJ2Fzc2V0cy9tYXAtbWFya2VyLTAucG5nJyA6ICdhc3NldHMvbWFwLW1hcmtlci0xLnBuZydcbiAgICAgIH0pXG4gICAgfSlcbiAgICAgIC5hZGRUbyh0aGlzLm1hcClcbiAgICAgIC5iaW5kUG9wdXAodGl0bGUpO1xuICB9XG5cbiAgLy8gVG8gUGxvdCBEaXJlY3Rpb25zIGZvciBBbGwgVGFza3NcbiAgcGxvdERpcmVjdGlvbnNGb3JBbGxUYXNrcyh0YXNrcykge1xuICAgIGlmICh0aGlzLm1hcCkge1xuICAgICAgdGhpcy5hbGxNYXJrZXJzID0gW107XG5cbiAgICAgIC8vIENyZWF0ZSBBZ2VudCBNYXJrZXIgJiBQbG90IEl0LlxuICAgICAgY29uc3QgbXlNYXJrZXIgPSB7XG4gICAgICAgIGxhdDogdGhpcy5teVBvc2l0aW9uLmxhdCxcbiAgICAgICAgbG5nOiB0aGlzLm15UG9zaXRpb24ubG5nLFxuICAgICAgICB0aXRsZTogMCxcbiAgICAgICAgY29sb3I6ICdyZWQnXG4gICAgICB9O1xuICAgICAgdGhpcy5hZGRNYXJrZXIobXlNYXJrZXIpO1xuICAgICAgdGhpcy5hbGxNYXJrZXJzLnB1c2gobXlNYXJrZXIpO1xuXG4gICAgICAvLyBDcmVhdGUgTWFya2VycyBmb3IgYWxsIFRhc2tzXG4gICAgICB0YXNrcy5tYXAoKHRhc2ssIGluZGV4KSA9PiB7XG4gICAgICAgIGNvbnN0IG1hcmtlciA9IHRoaXMuZ2V0TGF0TG5nKHRoaXMuZ2V0TG9jYXRpb24odGFzayksIGluZGV4KTtcbiAgICAgICAgdGhpcy5hbGxNYXJrZXJzLnB1c2gobWFya2VyKTtcbiAgICAgIH0pO1xuXG4gICAgICAvLyBSdW4gQWxnb3JpdGhtIHRvIGdldCBvcHRpbWl6ZWQgUm91dGVzXG4gICAgICBjb25zdCBzdGFydGluZ1BvaW50ID0gdGhpcy5hbGxNYXJrZXJzWzBdO1xuICAgICAgY29uc3QgdW52aXNpdGVkV2F5cG9pbnRzID0gdGhpcy5hbGxNYXJrZXJzLnNsaWNlKDEpO1xuICAgICAgY29uc3Qgb3B0aW1pemVkUm91dGUgPSB0aGlzLm5lYXJlc3ROZWlnaGJvckFsZ29yaXRobShcbiAgICAgICAgc3RhcnRpbmdQb2ludCxcbiAgICAgICAgdW52aXNpdGVkV2F5cG9pbnRzXG4gICAgICApO1xuXG4gICAgICAvLyBTb3J0IEFsbCBNYXJrZXJzIGFzIHBlciBvcHRpbWl6ZWQgcm91dGVzXG4gICAgICB0aGlzLmFsbE1hcmtlcnMgPSB0aGlzLnNvcnRUYXNrc0FzUGVyRGlzdGFuY2UoXG4gICAgICAgIG9wdGltaXplZFJvdXRlLFxuICAgICAgICB0aGlzLmFsbE1hcmtlcnMsXG4gICAgICAgIHRydWVcbiAgICAgICk7XG5cbiAgICAgIC8vIFNvcnQgQWxsIFRhc2tzIGFzIHBlciBvcHRpbWl6ZWQgcm91dGVzXG4gICAgICB0YXNrcyA9IHRoaXMuc29ydFRhc2tzQXNQZXJEaXN0YW5jZShcbiAgICAgICAgb3B0aW1pemVkUm91dGUuc2xpY2UoMSksXG4gICAgICAgIHRhc2tzLFxuICAgICAgICBmYWxzZVxuICAgICAgKTtcblxuICAgICAgLy8gUGxvdCBNYXJrZXJzIGZvciBBbGwgVGFza3NcbiAgICAgIHRhc2tzLm1hcCgodGFzaywgaW5kZXgpID0+IHtcbiAgICAgICAgY29uc3QgbWFya2VyID0gdGhpcy5nZXRMYXRMbmcodGhpcy5nZXRMb2NhdGlvbih0YXNrKSwgaW5kZXgpO1xuICAgICAgICB0aGlzLmFkZE1hcmtlcihtYXJrZXIpO1xuICAgICAgfSk7XG5cbiAgICAgIC8vIFNldCBTdHlsZXMgZm9yIGFsbCBUYXNrIFJvdXRlc1xuICAgICAgY29uc3Qgc3R5bGVzID0gW1xuICAgICAgICB7IGNvbG9yOiAnYmx1ZScsIG9wYWNpdHk6IDEsIHdlaWdodDogOCB9LFxuICAgICAgICB7IGNvbG9yOiAnd2hpdGUnLCBvcGFjaXR5OiAwLjYsIHdlaWdodDogMTIgfVxuICAgICAgXTtcblxuICAgICAgLy8gU2V0IFJvdXRlcyBmb3IgYWxsIFRhc2tzXG4gICAgICB0aGlzLmFsbFRhc2tzUm91dGVzID0gdGhpcy5zZXRSb3V0ZXModGhpcy5hbGxNYXJrZXJzLCBzdHlsZXMpO1xuICAgICAgdGhpcy5maXRNYXBCb3VuZHMoKTtcbiAgICB9XG4gICAgcmV0dXJuIHRhc2tzO1xuICB9XG5cbiAgLy8gVG8gcGxvdCBEaXJlY3Rpb24gZm9yIHNlbGVjdGVkIFRhc2tcbiAgcGxvdERpcmVjdGlvbnNGb3JTZWxlY3RlZFRhc2soaW5kZXgpIHtcbiAgICBpZiAoaW5kZXggIT09IG51bGwpIHtcbiAgICAgIC8vIFJlbW92ZSBQcmV2aW91c2x5IFNlbGVjdGVkIFRhc2sgUm91dGVcbiAgICAgIGlmICh0aGlzLnNlbGVjdGVkVGFza1JvdXRlcykge1xuICAgICAgICB0aGlzLm1hcC5yZW1vdmVDb250cm9sKHRoaXMuc2VsZWN0ZWRUYXNrUm91dGVzKTtcbiAgICAgIH1cblxuICAgICAgLy8gUmVtb3ZlIEFsbCBUYXNrcyBSb3V0ZXNcbiAgICAgIGlmICh0aGlzLmFsbFRhc2tzUm91dGVzKSB7XG4gICAgICAgIHRoaXMubWFwLnJlbW92ZUNvbnRyb2wodGhpcy5hbGxUYXNrc1JvdXRlcyk7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IHRhc2tNYXJrZXIgPSB0aGlzLmFsbE1hcmtlcnNbaW5kZXggKyAxXTtcblxuICAgICAgLy8gSWYgTG9jYXRpb24gaXMgQXZhaWxhYmxlIGluIFRhc2sgRGV0YWlsc1xuICAgICAgaWYgKHRhc2tNYXJrZXIuY29sb3IgIT0gJ3JlZCcpIHtcbiAgICAgICAgY29uc3QgbWFya2VycyA9IFt0aGlzLmFsbE1hcmtlcnNbMF0sIHRhc2tNYXJrZXJdO1xuICAgICAgICBjb25zdCBzdHlsZXMgPSBbXG4gICAgICAgICAgeyBjb2xvcjogJ2dyZWVuJywgb3BhY2l0eTogMSwgd2VpZ2h0OiA4IH0sXG4gICAgICAgICAgeyBjb2xvcjogJ3doaXRlJywgb3BhY2l0eTogMC40LCB3ZWlnaHQ6IDEyIH1cbiAgICAgICAgXTtcbiAgICAgICAgdGhpcy5zZWxlY3RlZFRhc2tSb3V0ZXMgPSB0aGlzLnNldFJvdXRlcyhtYXJrZXJzLCBzdHlsZXMpO1xuICAgICAgICB0aGlzLnNldFNlbGVjdGVkVGFza0Rpc3RhbmNlQW5kVGltZSgpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgYWxlcnQoJ05vIExvY2F0aW9uIEF2YWlsYWJsZScpO1xuICAgICAgfVxuICAgIH1cbiAgICAvLyBTZXQgQWxsIFRhc2tzIFJvdXRlcyBBZ2FpbiAmIFJlbW92ZSBTZWxlY3RlZCBUYXNrcyByb3V0ZVxuICAgIGVsc2Uge1xuICAgICAgaWYgKHRoaXMuc2VsZWN0ZWRUYXNrUm91dGVzKSB7XG4gICAgICAgIHRoaXMubWFwLnJlbW92ZUNvbnRyb2wodGhpcy5zZWxlY3RlZFRhc2tSb3V0ZXMpO1xuICAgICAgfVxuICAgICAgdGhpcy5tYXAuYWRkQ29udHJvbCh0aGlzLmFsbFRhc2tzUm91dGVzKTtcbiAgICAgIHRoaXMuc2VsZWN0ZWRUYXNrUm91dGVzID0gdW5kZWZpbmVkO1xuICAgIH1cbiAgICB0aGlzLmZpdE1hcEJvdW5kcygpO1xuICB9XG5cbiAgLy8gR2V0IERpc3RhbmNlICYgVGltZSBvZiBTZWxlY3RlZCBUYXNrXG4gIGdldFNlbGVjdGVkVGFza0Rpc3RhbmNlQW5kVGltZSgpIHtcbiAgICByZXR1cm4gdGhpcy5zZWxlY3RlZFRhc2tEaXN0YW5jZUFuZFRpbWU7XG4gIH1cblxuICAvLyBTZXQgRGlzdGFuY2UgJiBUaW1lIG9mIFNlbGVjdGVkIFRhc2tcbiAgc2V0U2VsZWN0ZWRUYXNrRGlzdGFuY2VBbmRUaW1lKCkge1xuICAgIHRoaXMuc2VsZWN0ZWRUYXNrUm91dGVzLm9uKCdyb3V0ZXNmb3VuZCcsIGZ1bmN0aW9uIChlKSB7XG4gICAgICBsZXQgcm91dGVzID0gZS5yb3V0ZXM7XG4gICAgICBsZXQgc3VtbWFyeSA9IHJvdXRlc1swXS5zdW1tYXJ5O1xuXG4gICAgICBjb25zdCBkaXN0YW5jZSA9IHN1bW1hcnkudG90YWxEaXN0YW5jZSAvIDEwMDA7XG4gICAgICBjb25zdCB0aW1lID0gTWF0aC5yb3VuZCgoc3VtbWFyeS50b3RhbFRpbWUgJSAzNjAwKSAvIDYwKTtcblxuICAgICAgdGhpcy5zZWxlY3RlZFRhc2tEaXN0YW5jZUFuZFRpbWUgPSB7XG4gICAgICAgIGRpc3RhbmNlOiBkaXN0YW5jZSxcbiAgICAgICAgdGltZTogdGltZVxuICAgICAgfTtcbiAgICB9KTtcbiAgfVxuXG4gIC8vIFRvIHNvcnQgVGFzayBhcyBwZXIgbmVhcmVzdCBkaXN0YW5jZVxuICBzb3J0VGFza3NBc1BlckRpc3RhbmNlKG9yZGVyLCB0YXNrcywgaXNNYXJrZXIpIHtcbiAgICBsZXQgc29ydGVkVGFza3MgPSBbXTtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRhc2tzLmxlbmd0aDsgaSsrKSB7XG4gICAgICBjb25zdCB0aXRsZSA9IGlzTWFya2VyID8gb3JkZXJbaV0udGl0bGUgOiBvcmRlcltpXS50aXRsZSAtIDE7XG4gICAgICBsZXQgdGFzayA9IHRhc2tzW3RpdGxlXTtcbiAgICAgIHNvcnRlZFRhc2tzLnB1c2godGFzayk7XG4gICAgfVxuICAgIHJldHVybiBzb3J0ZWRUYXNrcztcbiAgfVxuXG4gIC8vIFRvIHNldCByb3V0ZXMgaW4gdGhlIG1hcHNcbiAgc2V0Um91dGVzKG1hcmtlcnMsIHN0eWxlcykge1xuICAgIHJldHVybiBMLlJvdXRpbmcuY29udHJvbCh7XG4gICAgICB3YXlwb2ludHM6IG1hcmtlcnMsXG4gICAgICBsaW5lT3B0aW9uczoge1xuICAgICAgICBzdHlsZXM6IHN0eWxlc1xuICAgICAgfSxcbiAgICAgIGNyZWF0ZU1hcmtlcjogZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgIH0sXG4gICAgICByb3V0ZVdoaWxlRHJhZ2dpbmc6IHRydWVcbiAgICB9KS5hZGRUbyh0aGlzLm1hcCk7XG4gIH1cblxuICAvLyBUbyBzZXQgdmlldyBwb2ludCBvbiB0aGUgbWFwXG4gIGZpdE1hcEJvdW5kcygpIHtcbiAgICBjb25zdCBtYXJrZXJMYXRMbmdzID0gdGhpcy5hbGxNYXJrZXJzLm1hcCgobWFya2VyKSA9PlxuICAgICAgTC5sYXRMbmcobWFya2VyLmxhdCwgbWFya2VyLmxuZylcbiAgICApO1xuICAgIHRoaXMubWFwLmZpdEJvdW5kcyhtYXJrZXJMYXRMbmdzKTtcbiAgfVxuXG4gIC8vIFRvIGdldCBDdXJyZW50IFBvc2l0aW9uXG4gIGdldFBvc2l0aW9uKCk6IFByb21pc2U8YW55PiB7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgIG5hdmlnYXRvci5nZW9sb2NhdGlvbi53YXRjaFBvc2l0aW9uKFxuICAgICAgICAocmVzcCkgPT4ge1xuICAgICAgICAgIHJlc29sdmUoe1xuICAgICAgICAgICAgbG5nOiByZXNwLmNvb3Jkcy5sb25naXR1ZGUsXG4gICAgICAgICAgICBsYXQ6IHJlc3AuY29vcmRzLmxhdGl0dWRlXG4gICAgICAgICAgfSk7XG4gICAgICAgIH0sXG4gICAgICAgIChlcnIpID0+IHtcbiAgICAgICAgICByZWplY3QoZXJyKTtcbiAgICAgICAgfVxuICAgICAgKTtcbiAgICB9KTtcbiAgfVxuXG4gIC8vIFRvIGV4dHJhY3QgTG9jYXRpb24gZnJvbSB0aGUgVGFzayBEZXRhaWxzXG4gIGdldExvY2F0aW9uKHRhc2spIHtcbiAgICBpZiAoXG4gICAgICBjaGVja09iamVjdFBhdGhFeGlzdHMoXG4gICAgICAgIHRoaXMuYWdlbnRTZXJ2aWNlLmNvbmZpZyxcbiAgICAgICAgJ2Rhc2hib2FyZC50YXNrTG9jYXRpb25QYXRoJ1xuICAgICAgKVxuICAgICkge1xuICAgICAgY29uc3QgbG9jYXRpb24gPSBnZXRPYmplY3RWYWx1ZUZyb21QYXRoKFxuICAgICAgICB0YXNrLFxuICAgICAgICB0aGlzLmFnZW50U2VydmljZS5jb25maWcuZGFzaGJvYXJkLnRhc2tMb2NhdGlvblBhdGhcbiAgICAgICk7XG4gICAgICByZXR1cm4gbG9jYXRpb247XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiAoXG4gICAgICAgIHRhc2s/LmV4dHJhcz8udGFza19kZXRhaWxzPy5jdXN0b21lcl9kZXRhaWxzPy5sb2NhdGlvbiA/P1xuICAgICAgICB0YXNrPy50YXNrX2RldGFpbHM/LmN1c3RvbWVyX2RldGFpbHM/LmxvY2F0aW9uXG4gICAgICApO1xuICAgIH1cbiAgfVxuXG4gIC8vIFRvIGdldCBMYXRpdHVkZSAmIExvbmdpdHVkZSBmcm9tIFRhc2sgTG9jYXRpb25cbiAgZ2V0TGF0TG5nKGRhdGEsIGluZGV4KSB7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHVybCA9IGRhdGEuc3BsaXQoJ0AnKTtcbiAgICAgIGNvbnN0IGxhdF9sb25nX21hdGNoID0gdXJsWzFdLnNwbGl0KCcsJyk7XG4gICAgICBjb25zdCBsYXQgPSBOdW1iZXIobGF0X2xvbmdfbWF0Y2hbMF0pO1xuICAgICAgY29uc3QgbG9uZyA9IE51bWJlcihsYXRfbG9uZ19tYXRjaFsxXSk7XG4gICAgICByZXR1cm4geyBsYXQ6IGxhdCwgbG5nOiBsb25nLCB0aXRsZTogaW5kZXggKyAxLCBjb2xvcjogJ2JsdWUnIH07XG4gICAgfSBjYXRjaCB7XG4gICAgICAvLyBJZiBjb3VsZCBub3QgZmluZCBHb29nbGUgTWFwcyBMb2NhdGlvbiBVUkwgaW4gVGFza1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgbGF0OiB0aGlzLm15UG9zaXRpb24ubGF0LFxuICAgICAgICBsbmc6IHRoaXMubXlQb3NpdGlvbi5sbmcsXG4gICAgICAgIHRpdGxlOiBpbmRleCArIDEsXG4gICAgICAgIGNvbG9yOiAncmVkJ1xuICAgICAgfTtcbiAgICB9XG4gIH1cblxuICAvLyBUbyBDYWxjdWxhdGUgRGlzdGFuY2UgYmV0d2VlbiB0d28gbWFya2Vyc1xuICBjYWxjdWxhdGVEaXN0YW5jZShwb2ludDE6IGFueSwgcG9pbnQyOiBhbnkpOiBudW1iZXIge1xuICAgIGNvbnN0IGxhdDEgPSBwb2ludDEubGF0O1xuICAgIGNvbnN0IGxuZzEgPSBwb2ludDEubG5nO1xuICAgIGNvbnN0IGxhdDIgPSBwb2ludDIubGF0O1xuICAgIGNvbnN0IGxuZzIgPSBwb2ludDIubG5nO1xuXG4gICAgY29uc3QgUiA9IDYzNzE7IC8vIEVhcnRoIHJhZGl1cyBpbiBraWxvbWV0ZXJzXG4gICAgY29uc3QgZExhdCA9IChsYXQyIC0gbGF0MSkgKiAoTWF0aC5QSSAvIDE4MCk7XG4gICAgY29uc3QgZExuZyA9IChsbmcyIC0gbG5nMSkgKiAoTWF0aC5QSSAvIDE4MCk7XG4gICAgY29uc3QgYSA9XG4gICAgICBNYXRoLnNpbihkTGF0IC8gMikgKiBNYXRoLnNpbihkTGF0IC8gMikgK1xuICAgICAgTWF0aC5jb3MoKGxhdDEgKiBNYXRoLlBJKSAvIDE4MCkgKlxuICAgICAgICBNYXRoLmNvcygobGF0MiAqIE1hdGguUEkpIC8gMTgwKSAqXG4gICAgICAgIE1hdGguc2luKGRMbmcgLyAyKSAqXG4gICAgICAgIE1hdGguc2luKGRMbmcgLyAyKTtcbiAgICBjb25zdCBjID0gMiAqIE1hdGguYXRhbjIoTWF0aC5zcXJ0KGEpLCBNYXRoLnNxcnQoMSAtIGEpKTtcbiAgICBjb25zdCBkaXN0YW5jZSA9IFIgKiBjO1xuXG4gICAgcmV0dXJuIGRpc3RhbmNlO1xuICB9XG5cbiAgLy8gVG8gY2FsY3VsYXRlIG5lYXJlc3QgZGlzdGFuY2UgZnJvbSBtYXJrZXJcbiAgbmVhcmVzdE5laWdoYm9yQWxnb3JpdGhtKHN0YXJ0aW5nUG9pbnQ6IGFueSwgdW52aXNpdGVkUG9pbnRzOiBhbnlbXSk6IGFueVtdIHtcbiAgICBsZXQgY3VycmVudFBvaW50ID0gc3RhcnRpbmdQb2ludDtcbiAgICBjb25zdCBwYXRoOiBhbnlbXSA9IFtjdXJyZW50UG9pbnRdO1xuICAgIGNvbnN0IHZpc2l0ZWRQb2ludHM6IFNldDxhbnk+ID0gbmV3IFNldChbY3VycmVudFBvaW50XSk7XG5cbiAgICB3aGlsZSAodW52aXNpdGVkUG9pbnRzLmxlbmd0aCA+IDApIHtcbiAgICAgIGxldCBuZWFyZXN0UG9pbnQgPSBudWxsO1xuICAgICAgbGV0IG1pbkRpc3RhbmNlID0gTnVtYmVyLlBPU0lUSVZFX0lORklOSVRZO1xuXG4gICAgICBmb3IgKGNvbnN0IHBvaW50IG9mIHVudmlzaXRlZFBvaW50cykge1xuICAgICAgICBjb25zdCBkaXN0YW5jZSA9IHRoaXMuY2FsY3VsYXRlRGlzdGFuY2UoY3VycmVudFBvaW50LCBwb2ludCk7XG4gICAgICAgIGlmIChkaXN0YW5jZSA8IG1pbkRpc3RhbmNlKSB7XG4gICAgICAgICAgbWluRGlzdGFuY2UgPSBkaXN0YW5jZTtcbiAgICAgICAgICBuZWFyZXN0UG9pbnQgPSBwb2ludDtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBwYXRoLnB1c2gobmVhcmVzdFBvaW50KTtcbiAgICAgIHZpc2l0ZWRQb2ludHMuYWRkKG5lYXJlc3RQb2ludCk7XG4gICAgICBjdXJyZW50UG9pbnQgPSBuZWFyZXN0UG9pbnQ7XG5cbiAgICAgIHVudmlzaXRlZFBvaW50cyA9IHVudmlzaXRlZFBvaW50cy5maWx0ZXIoXG4gICAgICAgIChwb2ludCkgPT4gIXZpc2l0ZWRQb2ludHMuaGFzKHBvaW50KVxuICAgICAgKTtcbiAgICB9XG5cbiAgICByZXR1cm4gcGF0aDtcbiAgfVxufVxuIl19