@smarterplan/ngx-smarterplan-locations 0.2.20 → 0.2.21

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.
Files changed (59) hide show
  1. package/esm2020/lib/components/carousel/carousel.component.mjs +27 -27
  2. package/esm2020/lib/components/chevron/chevron.component.mjs +17 -17
  3. package/esm2020/lib/components/detail-location/detail-location.component.mjs +154 -154
  4. package/esm2020/lib/components/form-location/form-location.component.mjs +237 -237
  5. package/esm2020/lib/components/images/images.component.mjs +90 -90
  6. package/esm2020/lib/components/locations/locations.component.mjs +141 -141
  7. package/esm2020/lib/components/locations/map/map-popup/map-popup.component.mjs +65 -65
  8. package/esm2020/lib/components/locations/map/map.component.mjs +90 -90
  9. package/esm2020/lib/components/plans/calibration/calibration.component.mjs +468 -468
  10. package/esm2020/lib/components/plans/edit-plan/edit-plan.component.mjs +324 -324
  11. package/esm2020/lib/components/plans/plans.component.mjs +210 -210
  12. package/esm2020/lib/components/tab-navigation/tab-navigation.component.mjs +41 -41
  13. package/esm2020/lib/components/visits/visits.component.mjs +235 -235
  14. package/esm2020/lib/components/zones/add-audio-zone/add-audio-zone.component.mjs +230 -230
  15. package/esm2020/lib/components/zones/add-zone/add-zone.component.mjs +294 -294
  16. package/esm2020/lib/components/zones/add-zone/selection/selection.component.mjs +76 -76
  17. package/esm2020/lib/components/zones/add-zone/sweep-plan-selection/sweep-plan-selection.component.mjs +413 -414
  18. package/esm2020/lib/components/zones/zones.component.mjs +232 -232
  19. package/esm2020/lib/helper.service.mjs +134 -134
  20. package/esm2020/lib/ngx-smarterplan-location-routing.module.mjs +49 -49
  21. package/esm2020/lib/ngx-smarterplan-locations.module.mjs +122 -122
  22. package/esm2020/lib/ngx-smarterplan-locations.service.mjs +13 -13
  23. package/esm2020/lib/pipes/count-audio-sweeps.pipe.mjs +27 -0
  24. package/esm2020/lib/radio-button/radio-button.component.mjs +26 -26
  25. package/esm2020/public-api.mjs +8 -8
  26. package/esm2020/smarterplan-ngx-smarterplan-locations.mjs +4 -4
  27. package/fesm2015/smarterplan-ngx-smarterplan-locations.mjs +3627 -3648
  28. package/fesm2015/smarterplan-ngx-smarterplan-locations.mjs.map +1 -1
  29. package/fesm2020/smarterplan-ngx-smarterplan-locations.mjs +3475 -3494
  30. package/fesm2020/smarterplan-ngx-smarterplan-locations.mjs.map +1 -1
  31. package/lib/components/carousel/carousel.component.d.ts +12 -12
  32. package/lib/components/chevron/chevron.component.d.ts +9 -9
  33. package/lib/components/detail-location/detail-location.component.d.ts +51 -51
  34. package/lib/components/form-location/form-location.component.d.ts +45 -45
  35. package/lib/components/images/images.component.d.ts +28 -28
  36. package/lib/components/locations/locations.component.d.ts +50 -50
  37. package/lib/components/locations/map/map-popup/map-popup.component.d.ts +22 -22
  38. package/lib/components/locations/map/map.component.d.ts +22 -22
  39. package/lib/components/plans/calibration/calibration.component.d.ts +140 -140
  40. package/lib/components/plans/edit-plan/edit-plan.component.d.ts +55 -55
  41. package/lib/components/plans/plans.component.d.ts +59 -59
  42. package/lib/components/tab-navigation/tab-navigation.component.d.ts +13 -13
  43. package/lib/components/visits/visits.component.d.ts +51 -51
  44. package/lib/components/zones/add-audio-zone/add-audio-zone.component.d.ts +63 -63
  45. package/lib/components/zones/add-zone/add-zone.component.d.ts +67 -67
  46. package/lib/components/zones/add-zone/selection/selection.component.d.ts +44 -44
  47. package/lib/components/zones/add-zone/sweep-plan-selection/sweep-plan-selection.component.d.ts +96 -96
  48. package/lib/components/zones/zones.component.d.ts +67 -67
  49. package/lib/helper.service.d.ts +53 -53
  50. package/lib/ngx-smarterplan-location-routing.module.d.ts +7 -7
  51. package/lib/ngx-smarterplan-locations.module.d.ts +35 -35
  52. package/lib/ngx-smarterplan-locations.service.d.ts +6 -6
  53. package/lib/pipes/count-audio-sweeps.pipe.d.ts +10 -0
  54. package/lib/radio-button/radio-button.component.d.ts +12 -12
  55. package/package.json +2 -2
  56. package/public-api.d.ts +4 -4
  57. package/smarterplan-ngx-smarterplan-locations.d.ts +5 -5
  58. package/esm2020/lib/components/plan-legend/plan-legend.component.mjs +0 -47
  59. package/lib/components/plan-legend/plan-legend.component.d.ts +0 -14
@@ -1,414 +1,413 @@
1
- import { Component, EventEmitter, Input, Output } from '@angular/core';
2
- import { getCoefficientsForImage, getMetaForImage, showScanPointsOnPlanInDiv } from '@smarterplan/ngx-smarterplan-core';
3
- import panzoom from 'panzoom';
4
- import { buttonIsInSelection, isInPolygon, rotate, setVisuallySelected, styleButton, SweepState } from '../../../../helper.service';
5
- import * as i0 from "@angular/core";
6
- import * as i1 from "@smarterplan/ngx-smarterplan-core";
7
- import * as i2 from "../selection/selection.component";
8
- import * as i3 from "../../../plan-legend/plan-legend.component";
9
- import * as i4 from "../../../../radio-button/radio-button.component";
10
- import * as i5 from "@ng-bootstrap/ng-bootstrap";
11
- import * as i6 from "@angular/common";
12
- import * as i7 from "@ngx-translate/core";
13
- export class SweepPlanSelectionComponent {
14
- constructor(zoneService, navigationService, planService) {
15
- this.zoneService = zoneService;
16
- this.navigationService = navigationService;
17
- this.planService = planService;
18
- this.chosenScansOnPlan = [];
19
- this.navIDsZoneEdit = [];
20
- // sweeps belonging to any audio zone
21
- this.occupiedSweeps = [];
22
- // sweeps unavailable (cannot be chosen)
23
- this.unavailableSweeps = [];
24
- // if choosing sweeps for audio zone
25
- this.editingAudioZone = false;
26
- /** all scan buttons Element */
27
- this.buttonElements = [];
28
- /** Scan buttons that are in the current selection */
29
- this.buttonsInSelection = [];
30
- this.sweepsSelected = new EventEmitter();
31
- this.isSettingStartSweep = false;
32
- }
33
- ngOnInit() {
34
- this.getPlans();
35
- if (this.inputZone) {
36
- this.setSweepsOfInputZone();
37
- }
38
- }
39
- ngOnChanges() {
40
- if (this.chosenPlan) {
41
- this.setSweepsOfInputZone();
42
- this.chosenScansOnPlan = [];
43
- this.clearDivPlan();
44
- this.addScanPoints();
45
- }
46
- }
47
- setSweepsOfInputZone() {
48
- this.navIDsZoneEdit = this.inputZone.sweepIDs;
49
- }
50
- async getPlans() {
51
- this.plans = await this.planService.getSingedPlansForSpace(this.spaceID);
52
- }
53
- async onPlanClick(plan) {
54
- this.chosenPlan = plan;
55
- this.clearDivPlan();
56
- this.addScanPoints();
57
- }
58
- async addScanPoints() {
59
- this.divPlan = document.querySelector("#planDiv");
60
- const zoneOfPlan = await this.zoneService.getZone(this.chosenPlan.zoneID);
61
- const navigations = await this.navigationService.getNavigationsForZone(zoneOfPlan);
62
- if (this.newZoneData)
63
- await this.setScanByDraw(navigations);
64
- this.buttonElements = await showScanPointsOnPlanInDiv(this.chosenPlan, this.divPlan, navigations);
65
- for (const element of this.buttonElements) {
66
- if (this.unavailableSweeps && this.unavailableSweeps.includes(element.id)) {
67
- styleButton(element, SweepState.DISABLED);
68
- }
69
- else {
70
- if ((this.navIDsZoneEdit.length > 0 &&
71
- this.navIDsZoneEdit.includes(element.id))
72
- || this.chosenScansOnPlan.includes(element.id)) {
73
- styleButton(element, SweepState.ADDED);
74
- if (!this.chosenScansOnPlan.includes(element.id)) {
75
- this.chosenScansOnPlan.push(element.id);
76
- }
77
- }
78
- else if (this.occupiedSweeps && this.occupiedSweeps.includes(element.id)) {
79
- styleButton(element, SweepState.OCCUPIED);
80
- }
81
- else {
82
- styleButton(element, SweepState.REMOVED);
83
- }
84
- //start point should be last condition
85
- if (this.inputZone && this.inputZone.startSweepID === element.id) {
86
- console.log("setting start point");
87
- styleButton(element, SweepState.STARTPOINT);
88
- }
89
- element.addEventListener("click", (event) => this.onButtonScanClicked(event.target));
90
- }
91
- }
92
- this.panZoom = panzoom(this.divPlan, {
93
- bounds: true,
94
- boundsPadding: 0,
95
- maxZoom: 3.5,
96
- beforeMouseDown(e) {
97
- return (e.button === 2); /** Ignore event for right click (use for selecting) */
98
- },
99
- });
100
- }
101
- /** Function if we are coming for svg editor workflow */
102
- setScanByDraw(navigations) {
103
- return new Promise(async (resolve) => {
104
- const rect = {
105
- width: this.newZoneData.width,
106
- height: this.newZoneData.height,
107
- };
108
- const img = await getMetaForImage(this.chosenPlan.filepath);
109
- const { coeffX, coeffY } = getCoefficientsForImage(img, rect);
110
- const draw = this.newZoneData.elements;
111
- draw.map(async (element) => {
112
- switch (element.nodeName) {
113
- case "rect":
114
- await this.setScanInRect(img, coeffX, coeffY, element, navigations);
115
- break;
116
- case "ellipse":
117
- await this.setScanInCircle(img, coeffX, coeffY, element, navigations);
118
- break;
119
- case "path":
120
- await this.setScanInPolygon(img, coeffX, coeffY, element, navigations);
121
- break;
122
- default:
123
- break;
124
- }
125
- });
126
- resolve();
127
- });
128
- }
129
- async setScanInRect(img, coeffX, coeffY, element, navigations) {
130
- const calibrage = JSON.parse(this.chosenPlan.calibration);
131
- navigations.map((navigation) => {
132
- const positionsOnPlan = navigation.positionOnPlan.map((entry) => JSON.parse(entry));
133
- const positionOnPlan = positionsOnPlan.find((data) => data.planID === this.chosenPlan.id);
134
- if (positionOnPlan) {
135
- const realWidth = img.width / coeffX;
136
- const realHeight = img.height / coeffY;
137
- const navY = (positionOnPlan.y * realHeight) / calibrage.imgHeight;
138
- const navX = (positionOnPlan.x * realWidth) / calibrage.imgWidth;
139
- if (navX > element.x &&
140
- navX < element.x + element.width &&
141
- navY > element.y &&
142
- navY < element.y + element.height &&
143
- !this.navIDsZoneEdit.includes(navigation.id)) {
144
- this.navIDsZoneEdit.push(navigation.id);
145
- }
146
- }
147
- // old calibration:
148
- // const position = JSON.parse(navigation.position);
149
- // let navX = (calibrage.offsetX + position.x * calibrage.x) / coeffX;
150
- // let navY = (calibrage.offsetY + position.z * calibrage.y) / coeffY;
151
- // if (element.angle) {
152
- // const rotatePos = rotate(
153
- // { x: navX, y: navY },
154
- // { x: element.cx, y: element.cy },
155
- // element.angle,
156
- // );
157
- // navX = rotatePos.x;
158
- // navY = rotatePos.y;
159
- // }
160
- /**
161
- * TODO calculer la rotation du rectangle
162
- */
163
- // if (
164
- // navX > element.x &&
165
- // navX < element.x + element.width &&
166
- // navY > element.y &&
167
- // navY < element.y + element.height &&
168
- // !this.navIDsZoneEdit.includes(navigation.id)
169
- // ) {
170
- // this.navIDsZoneEdit.push(navigation.id);
171
- // }
172
- });
173
- } // EO
174
- async setScanInCircle(img, coeffX, coeffY, element, navigations) {
175
- const calibrage = JSON.parse(this.chosenPlan.calibration);
176
- navigations.map(navigation => {
177
- const positionsOnPlan = navigation.positionOnPlan.map((entry) => JSON.parse(entry));
178
- const positionOnPlan = positionsOnPlan.find((data) => data.planID === this.chosenPlan.id);
179
- if (positionOnPlan) {
180
- const realWidth = img.width / coeffX;
181
- const realHeight = img.height / coeffY;
182
- let navY = (positionOnPlan.y * realHeight) / calibrage.imgHeight;
183
- let navX = (positionOnPlan.x * realWidth) / calibrage.imgWidth;
184
- if (element.angle) {
185
- const rotatePos = rotate({ x: navX, y: navY }, { x: element.cx, y: element.cy }, element.angle);
186
- navX = rotatePos.x;
187
- navY = rotatePos.y;
188
- }
189
- const valueX = Math.pow(navX - element.cx, 2) / Math.pow(element.rx, 2);
190
- const valueY = Math.pow(navY - element.cy, 2) / Math.pow(element.ry, 2);
191
- const result = valueX + valueY;
192
- if (result <= 1 && !this.navIDsZoneEdit.includes(navigation.id)) {
193
- this.navIDsZoneEdit.push(navigation.id);
194
- }
195
- }
196
- // old calibration
197
- // const position = JSON.parse(navigation.position);
198
- // let navX = (calibrage.offsetX + position.x * calibrage.x) / coeffX;
199
- // let navY = (calibrage.offsetY + position.z * calibrage.y) / coeffY;
200
- // if (element.angle) {
201
- // const rotatePos = rotate(
202
- // { x: navX, y: navY },
203
- // { x: element.cx, y: element.cy },
204
- // element.angle,
205
- // );
206
- // navX = rotatePos.x;
207
- // navY = rotatePos.y;
208
- // }
209
- // const valueX =
210
- // Math.pow(navX - element.cx, 2) / Math.pow(element.rx, 2);
211
- // const valueY =
212
- // Math.pow(navY - element.cy, 2) / Math.pow(element.ry, 2);
213
- // const result = valueX + valueY;
214
- // if (result <= 1 && !this.navIDsZoneEdit.includes(navigation.id)) {
215
- // this.navIDsZoneEdit.push(navigation.id);
216
- // }
217
- });
218
- } // EO
219
- async setScanInPolygon(img, coeffX, coeffY, element, navigations) {
220
- const calibrage = JSON.parse(this.chosenPlan.calibration);
221
- navigations.map(async (navigation) => {
222
- const positionsOnPlan = navigation.positionOnPlan.map((entry) => JSON.parse(entry));
223
- const positionOnPlan = positionsOnPlan.find((data) => data.planID === this.chosenPlan.id);
224
- if (positionOnPlan) {
225
- const realWidth = img.width / coeffX;
226
- const realHeight = img.height / coeffY;
227
- let navY = (positionOnPlan.y * realHeight) / calibrage.imgHeight;
228
- let navX = (positionOnPlan.x * realWidth) / calibrage.imgWidth;
229
- const p = {
230
- x: navX,
231
- y: navY,
232
- };
233
- if (isInPolygon(p, element.segList) &&
234
- !this.navIDsZoneEdit.includes(navigation.id)) {
235
- this.navIDsZoneEdit.push(navigation.id);
236
- }
237
- }
238
- // old calibration
239
- // const position = JSON.parse(navigation.position);
240
- // const p = {
241
- // x: (calibrage.offsetX + position.x * calibrage.x) / coeffX,
242
- // y: (calibrage.offsetY + position.z * calibrage.y) / coeffY,
243
- // };
244
- // if (element.angle) {
245
- // p = this.rotate(
246
- // p,
247
- // { x: element.cx, y: element.cy },
248
- // element.angle,
249
- // );
250
- // }
251
- // if (
252
- // isInPolygon(p, element.segList) &&
253
- // !this.navIDsZoneEdit.includes(navigation.id)
254
- // ) {
255
- // this.navIDsZoneEdit.push(navigation.id);
256
- // }
257
- });
258
- }
259
- clearDivPlan() {
260
- if (this.divPlan)
261
- this.divPlan.innerHTML = "";
262
- }
263
- /**
264
- * Trigger each by the selectionComponent when selection change
265
- * Update the current selected scan buttons
266
- * @param selection new selection
267
- */
268
- onSelectionChanged(selection) {
269
- const unselectedButtons = [];
270
- const newSelectedButtons = [];
271
- /** For each button, decide whether will be add to selected list or unselected list */
272
- for (const button of this.buttonElements) {
273
- const isSelected = buttonIsInSelection(button, selection);
274
- if (this.buttonsInSelection.includes(button)) {
275
- /** If the button is already in the selected list, we check if it should be unselect */
276
- if (!isSelected) {
277
- unselectedButtons.push(button);
278
- }
279
- }
280
- else if (isSelected) {
281
- newSelectedButtons.push(button);
282
- }
283
- }
284
- /** Visually Update unselected list */
285
- for (const button of unselectedButtons) {
286
- setVisuallySelected(button, false);
287
- }
288
- /** Visually Update selected list */
289
- for (const button of newSelectedButtons) {
290
- setVisuallySelected(button, true);
291
- }
292
- /** Remove unselected list */
293
- this.buttonsInSelection = this.buttonsInSelection.filter((button) => {
294
- return !unselectedButtons.includes(button);
295
- });
296
- /** Add new selected buttons */
297
- this.buttonsInSelection = [
298
- ...this.buttonsInSelection,
299
- ...newSelectedButtons,
300
- ];
301
- }
302
- /**
303
- * Trigger when the user click to add the selected scans
304
- */
305
- onSelectionAdd() {
306
- for (const button of this.buttonsInSelection) {
307
- if (!this.chosenScansOnPlan.includes(button.id)) {
308
- this.onButtonScanClicked(button);
309
- }
310
- }
311
- this.onSelectionChanged({ top: 0, left: 0, width: 0, height: 0 });
312
- }
313
- /**
314
- * Trigger when the user click to remove the selected scans
315
- */
316
- onSelectionRemove() {
317
- for (const button of this.buttonsInSelection) {
318
- if (this.chosenScansOnPlan.includes(button.id)) {
319
- this.onButtonScanClicked(button);
320
- }
321
- }
322
- this.onSelectionChanged({ top: 0, left: 0, width: 0, height: 0 });
323
- }
324
- /**
325
- * Trigger when the user click to select all scans
326
- */
327
- onSelectAll() {
328
- this.buttonsInSelection = [...this.buttonElements];
329
- for (const button of this.buttonsInSelection) {
330
- setVisuallySelected(button, true);
331
- }
332
- }
333
- /**
334
- * Trigger when the user change the size of the scan points
335
- * @param event
336
- */
337
- onChangeScanSize(event) {
338
- const factor = event.target.value;
339
- for (const button of this.buttonElements) {
340
- button.style.transform = `scale(${factor})`;
341
- }
342
- }
343
- /**
344
- * When a button representing a scan is clicked
345
- * @param button
346
- */
347
- onButtonScanClicked(button) {
348
- if (this.isSettingStartSweep) {
349
- if (this.startSweepID === button.id) {
350
- // we deselect the starting point
351
- button.style.backgroundImage = `url("https://api.iconify.design/mdi:adjust.svg?color=green&height=17&width=17")`;
352
- this.startSweepID = null;
353
- return;
354
- }
355
- button.style.backgroundImage = `url('https://api.iconify.design/ic/baseline-flag-circle.svg?color=white&width=17&height=17')`;
356
- if (!this.chosenScansOnPlan.includes(button.id)) {
357
- this.chosenScansOnPlan.push(button.id);
358
- }
359
- if (this.startSweepID) {
360
- // we are changing start sweep
361
- const btnChanged = this.buttonElements.find((btn) => btn.id === this.startSweepID);
362
- btnChanged.style.backgroundImage = `url("https://api.iconify.design/mdi:adjust.svg?color=green&height=17&width=17")`;
363
- }
364
- this.startSweepID = button.id;
365
- return;
366
- }
367
- if (!this.chosenScansOnPlan.includes(button.id)) {
368
- // add to selection
369
- button.style.backgroundImage = `url("https://api.iconify.design/mdi:adjust.svg?color=green&height=17&width=17")`;
370
- this.chosenScansOnPlan.push(button.id);
371
- }
372
- else {
373
- // remove from selection
374
- if (this.occupiedSweeps.includes(button.id) && !this.navIDsZoneEdit.includes(button.id)) {
375
- // the sweep belongs to another zone => set orange
376
- button.style.backgroundImage = `url("https://api.iconify.design/mdi:adjust.svg?color=orange&height=17&width=17")`;
377
- }
378
- else {
379
- button.style.backgroundImage = `url("https://api.iconify.design/mdi:close-circle-outline.svg?color=red&height=17&width=17")`;
380
- }
381
- const index = this.chosenScansOnPlan.indexOf(button.id);
382
- this.chosenScansOnPlan.splice(index, 1);
383
- }
384
- }
385
- onSaveSelection() {
386
- this.sweepsSelected.emit({ "sweeps": this.chosenScansOnPlan, "startSweepID": this.startSweepID });
387
- }
388
- onCancel() {
389
- this.sweepsSelected.emit(null);
390
- }
391
- }
392
- SweepPlanSelectionComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.2.7", ngImport: i0, type: SweepPlanSelectionComponent, deps: [{ token: i1.ZoneService }, { token: i1.NavigationService }, { token: i1.PlanService }], target: i0.ɵɵFactoryTarget.Component });
393
- SweepPlanSelectionComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.2.7", type: SweepPlanSelectionComponent, selector: "lib-sweep-plan-selection", inputs: { spaceID: "spaceID", chosenScansOnPlan: "chosenScansOnPlan", newZoneData: "newZoneData", occupiedSweeps: "occupiedSweeps", unavailableSweeps: "unavailableSweeps", editingAudioZone: "editingAudioZone", inputZone: "inputZone" }, outputs: { sweepsSelected: "sweepsSelected" }, usesOnChanges: true, ngImport: i0, template: "<div ngbDropdown class=\"sp-row d-inline-block\">\n <div class=\"col-sm-3\" *ngIf=\"plans\">\n <button type=\"button\" class=\"btn btn-label-file rounded-pill\" id=\"dropdownBasic1\"\n ngbDropdownToggle>{{chosenPlan ?\n chosenPlan.name : ('Choose Plan' | translate) }}</button>\n <div ngbDropdownMenu aria-labelledby=\"dropdownBasic1\">\n <button type=\"button\" ngbDropdownItem *ngFor=\"let plan of plans\" (click)=\"onPlanClick(plan)\"\n [disabled]=\"!plan.calibration\">{{ plan.name }}\n </button>\n </div>\n </div>\n</div>\n<div class=\"sp-row\">\n <lib-selection class=\"col-md-8\" (onSelectionChanged)=\"onSelectionChanged($event)\">\n <lib-plan-legend [isAudioZone]=\"editingAudioZone\" *ngIf=\"buttonElements.length > 0\"></lib-plan-legend>\n <div class=\"selectZone\" oncontextmenu=\"return false;\">\n <div class=\"sp-row\">\n <div style=\"overflow: hidden;width:100%;\">\n <div style=\"height: 400px; width: 100%;\" id=\"planDiv\">\n </div>\n </div>\n </div>\n </div>\n </lib-selection>\n \n <div class=\"col-md-4 scanTool\" *ngIf=\"buttonElements.length > 0\">\n <div class=\"sp-row d-inline-block\">\n <h2>{{'selectTool.title' | translate}}</h2>\n <div class=\"protip\">{{'selectTool.tip' | translate}}.</div>\n </div>\n \n <div class=\"sp-row\">\n <div class=\"col-3\" style=\"padding:0px\">\n <label class=\"tool-label\" for=\"scanSize\">{{'selectTool.size' | translate}}</label>\n </div>\n <div class=\"col-9\">\n <input type=\"range\" class=\"form-range\" min=\"0.001\" max=\"5\" step=\"0.01\" value=\"1\"\n id=\"scanSize\" (input)=\"onChangeScanSize($event)\">\n </div>\n </div>\n \n <div class=\"sp-row\">\n <button class=\"btn btn-primary rounded-pill\" (click)=\"onSelectAll()\">{{'selectTool.selectAll' | translate}}</button>\n </div>\n \n <div *ngIf=\"buttonsInSelection.length > 0\" class=\"edit-selected\">\n <span class=\"tool-label\">{{'selectTool.edit' | translate}} : </span>\n <div class=\"sp-row\">\n <button class=\"btn rounded-pill btn-primary ms-3 me-2\" (click)=\"onSelectionAdd()\">{{'selectTool.add' | translate}}</button>\n <button class=\"btn btn-primary rounded-pill\" (click)=\"onSelectionRemove()\">{{'selectTool.undo' | translate}}</button>\n </div>\n </div>\n\n <div class=\"sp-row\">\n {{ chosenScansOnPlan.length }} {{'scan points chosen' | translate}} \n </div>\n <div *ngIf=\"!editingAudioZone\" class=\"sp-row\">\n <lib-radio-button label=\"{{ 'selectTool.chooseStartPoint' | translate }}\" (isCheckedEvent)=\"isSettingStartSweep=!isSettingStartSweep\"></lib-radio-button>\n </div>\n \n <div class=\"sp-row\">\n <button class=\"btn btn-primary rounded-pill\" (click)=\"onSaveSelection()\">{{'selectTool.saveSelection' | translate}}</button>\n <button class=\"btn btn-outline-primary rounded-pill\" (click)=\"onCancel()\">{{'selectTool.cancelSelection' | translate}}</button>\n </div>\n </div>\n\n</div>\n \n", styles: [".sp-row{display:flex;margin-bottom:1rem}.selectZone{background-color:gray;border-radius:1rem;overflow:hidden}.scanTool{margin:0px 1rem}.protip{color:gray;padding:0}.tool-label{font-size:1rem}\n"], components: [{ type: i2.SelectionComponent, selector: "lib-selection", outputs: ["onSelectionChanged"] }, { type: i3.PlanLegendComponent, selector: "lib-plan-legend", inputs: ["isAudioZone"] }, { type: i4.RadioButtonComponent, selector: "lib-radio-button", inputs: ["label"], outputs: ["isCheckedEvent"] }], directives: [{ type: i5.NgbDropdown, selector: "[ngbDropdown]", inputs: ["autoClose", "dropdownClass", "open", "placement", "container", "display"], outputs: ["openChange"], exportAs: ["ngbDropdown"] }, { type: i6.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i5.NgbDropdownToggle, selector: "[ngbDropdownToggle]" }, { type: i5.NgbDropdownMenu, selector: "[ngbDropdownMenu]" }, { type: i6.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i5.NgbDropdownItem, selector: "[ngbDropdownItem]", inputs: ["disabled"] }], pipes: { "translate": i7.TranslatePipe } });
394
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.2.7", ngImport: i0, type: SweepPlanSelectionComponent, decorators: [{
395
- type: Component,
396
- args: [{ selector: 'lib-sweep-plan-selection', template: "<div ngbDropdown class=\"sp-row d-inline-block\">\n <div class=\"col-sm-3\" *ngIf=\"plans\">\n <button type=\"button\" class=\"btn btn-label-file rounded-pill\" id=\"dropdownBasic1\"\n ngbDropdownToggle>{{chosenPlan ?\n chosenPlan.name : ('Choose Plan' | translate) }}</button>\n <div ngbDropdownMenu aria-labelledby=\"dropdownBasic1\">\n <button type=\"button\" ngbDropdownItem *ngFor=\"let plan of plans\" (click)=\"onPlanClick(plan)\"\n [disabled]=\"!plan.calibration\">{{ plan.name }}\n </button>\n </div>\n </div>\n</div>\n<div class=\"sp-row\">\n <lib-selection class=\"col-md-8\" (onSelectionChanged)=\"onSelectionChanged($event)\">\n <lib-plan-legend [isAudioZone]=\"editingAudioZone\" *ngIf=\"buttonElements.length > 0\"></lib-plan-legend>\n <div class=\"selectZone\" oncontextmenu=\"return false;\">\n <div class=\"sp-row\">\n <div style=\"overflow: hidden;width:100%;\">\n <div style=\"height: 400px; width: 100%;\" id=\"planDiv\">\n </div>\n </div>\n </div>\n </div>\n </lib-selection>\n \n <div class=\"col-md-4 scanTool\" *ngIf=\"buttonElements.length > 0\">\n <div class=\"sp-row d-inline-block\">\n <h2>{{'selectTool.title' | translate}}</h2>\n <div class=\"protip\">{{'selectTool.tip' | translate}}.</div>\n </div>\n \n <div class=\"sp-row\">\n <div class=\"col-3\" style=\"padding:0px\">\n <label class=\"tool-label\" for=\"scanSize\">{{'selectTool.size' | translate}}</label>\n </div>\n <div class=\"col-9\">\n <input type=\"range\" class=\"form-range\" min=\"0.001\" max=\"5\" step=\"0.01\" value=\"1\"\n id=\"scanSize\" (input)=\"onChangeScanSize($event)\">\n </div>\n </div>\n \n <div class=\"sp-row\">\n <button class=\"btn btn-primary rounded-pill\" (click)=\"onSelectAll()\">{{'selectTool.selectAll' | translate}}</button>\n </div>\n \n <div *ngIf=\"buttonsInSelection.length > 0\" class=\"edit-selected\">\n <span class=\"tool-label\">{{'selectTool.edit' | translate}} : </span>\n <div class=\"sp-row\">\n <button class=\"btn rounded-pill btn-primary ms-3 me-2\" (click)=\"onSelectionAdd()\">{{'selectTool.add' | translate}}</button>\n <button class=\"btn btn-primary rounded-pill\" (click)=\"onSelectionRemove()\">{{'selectTool.undo' | translate}}</button>\n </div>\n </div>\n\n <div class=\"sp-row\">\n {{ chosenScansOnPlan.length }} {{'scan points chosen' | translate}} \n </div>\n <div *ngIf=\"!editingAudioZone\" class=\"sp-row\">\n <lib-radio-button label=\"{{ 'selectTool.chooseStartPoint' | translate }}\" (isCheckedEvent)=\"isSettingStartSweep=!isSettingStartSweep\"></lib-radio-button>\n </div>\n \n <div class=\"sp-row\">\n <button class=\"btn btn-primary rounded-pill\" (click)=\"onSaveSelection()\">{{'selectTool.saveSelection' | translate}}</button>\n <button class=\"btn btn-outline-primary rounded-pill\" (click)=\"onCancel()\">{{'selectTool.cancelSelection' | translate}}</button>\n </div>\n </div>\n\n</div>\n \n", styles: [".sp-row{display:flex;margin-bottom:1rem}.selectZone{background-color:gray;border-radius:1rem;overflow:hidden}.scanTool{margin:0px 1rem}.protip{color:gray;padding:0}.tool-label{font-size:1rem}\n"] }]
397
- }], ctorParameters: function () { return [{ type: i1.ZoneService }, { type: i1.NavigationService }, { type: i1.PlanService }]; }, propDecorators: { spaceID: [{
398
- type: Input
399
- }], chosenScansOnPlan: [{
400
- type: Input
401
- }], newZoneData: [{
402
- type: Input
403
- }], occupiedSweeps: [{
404
- type: Input
405
- }], unavailableSweeps: [{
406
- type: Input
407
- }], editingAudioZone: [{
408
- type: Input
409
- }], inputZone: [{
410
- type: Input
411
- }], sweepsSelected: [{
412
- type: Output
413
- }] } });
414
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3dlZXAtcGxhbi1zZWxlY3Rpb24uY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvbmd4LXNtYXJ0ZXJwbGFuLWxvY2F0aW9ucy9zcmMvbGliL2NvbXBvbmVudHMvem9uZXMvYWRkLXpvbmUvc3dlZXAtcGxhbi1zZWxlY3Rpb24vc3dlZXAtcGxhbi1zZWxlY3Rpb24uY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvbmd4LXNtYXJ0ZXJwbGFuLWxvY2F0aW9ucy9zcmMvbGliL2NvbXBvbmVudHMvem9uZXMvYWRkLXpvbmUvc3dlZXAtcGxhbi1zZWxlY3Rpb24vc3dlZXAtcGxhbi1zZWxlY3Rpb24uY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFNBQVMsRUFBRSxZQUFZLEVBQUUsS0FBSyxFQUFVLE1BQU0sRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUMvRSxPQUFPLEVBQUUsdUJBQXVCLEVBQUUsZUFBZSxFQUE2Qyx5QkFBeUIsRUFBNEIsTUFBTSxtQ0FBbUMsQ0FBQztBQUM3TCxPQUFPLE9BQW9CLE1BQU0sU0FBUyxDQUFDO0FBQzNDLE9BQU8sRUFBRSxtQkFBbUIsRUFBRSxXQUFXLEVBQWEsTUFBTSxFQUFFLG1CQUFtQixFQUFFLFdBQVcsRUFBRSxVQUFVLEVBQUUsTUFBTSw0QkFBNEIsQ0FBQzs7Ozs7Ozs7O0FBTy9JLE1BQU0sT0FBTywyQkFBMkI7SUE0Q3BDLFlBQ1ksV0FBd0IsRUFDeEIsaUJBQW9DLEVBQ3BDLFdBQXdCO1FBRnhCLGdCQUFXLEdBQVgsV0FBVyxDQUFhO1FBQ3hCLHNCQUFpQixHQUFqQixpQkFBaUIsQ0FBbUI7UUFDcEMsZ0JBQVcsR0FBWCxXQUFXLENBQWE7UUF6QzNCLHNCQUFpQixHQUFhLEVBQUUsQ0FBQztRQUsxQyxtQkFBYyxHQUFhLEVBQUUsQ0FBQztRQUU5Qixx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LDBCQUEwQjs0SkFRM0IsT0FBTztzQkFBZixLQUFLO2dCQUVHLGlCQUFpQjtzQkFBekIsS0FBSztnQkFHRyxXQUFXO3NCQUFuQixLQUFLO2dCQUtHLGNBQWM7c0JBQXRCLEtBQUs7Z0JBR0csaUJBQWlCO3NCQUF6QixLQUFLO2dCQUdHLGdCQUFnQjtzQkFBeEIsS0FBSztnQkFFRyxTQUFTO3NCQUFqQixLQUFLO2dCQWdCSSxjQUFjO3NCQUF2QixNQUFNIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQ29tcG9uZW50LCBFdmVudEVtaXR0ZXIsIElucHV0LCBPbkluaXQsIE91dHB1dCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgZ2V0Q29lZmZpY2llbnRzRm9ySW1hZ2UsIGdldE1ldGFGb3JJbWFnZSwgTmF2aWdhdGlvbiwgTmF2aWdhdGlvblNlcnZpY2UsIFBsYW4sIFpvbmUsIHNob3dTY2FuUG9pbnRzT25QbGFuSW5EaXYsIFpvbmVTZXJ2aWNlLCBQbGFuU2VydmljZSB9IGZyb20gJ0BzbWFydGVycGxhbi9uZ3gtc21hcnRlcnBsYW4tY29yZSc7XG5pbXBvcnQgcGFuem9vbSwgeyBQYW5ab29tIH0gZnJvbSAncGFuem9vbSc7XG5pbXBvcnQgeyBidXR0b25Jc0luU2VsZWN0aW9uLCBpc0luUG9seWdvbiwgUmVjdGFuZ2xlLCByb3RhdGUsIHNldFZpc3VhbGx5U2VsZWN0ZWQsIHN0eWxlQnV0dG9uLCBTd2VlcFN0YXRlIH0gZnJvbSAnLi4vLi4vLi4vLi4vaGVscGVyLnNlcnZpY2UnO1xuXG5AQ29tcG9uZW50KHtcbiAgICBzZWxlY3RvcjogJ2xpYi1zd2VlcC1wbGFuLXNlbGVjdGlvbicsXG4gICAgdGVtcGxhdGVVcmw6ICcuL3N3ZWVwLXBsYW4tc2VsZWN0aW9uLmNvbXBvbmVudC5odG1sJyxcbiAgICBzdHlsZVVybHM6IFsnLi9zd2VlcC1wbGFuLXNlbGVjdGlvbi5jb21wb25lbnQuc2NzcyddXG59KVxuZXhwb3J0IGNsYXNzIFN3ZWVwUGxhblNlbGVjdGlvbkNvbXBvbmVudCBpbXBsZW1lbnRzIE9uSW5pdCB7XG5cbiAgICBwbGFuczogUGxhbltdO1xuXG4gICAgQElucHV0KCkgc3BhY2VJRDogc3RyaW5nO1xuXG4gICAgQElucHV0KCkgY2hvc2VuU2NhbnNPblBsYW46IHN0cmluZ1tdID0gW107XG5cbiAgICAvKiogaWYgY29tbWluZyBmcm9tIEVkaXQgUGxhbiBTVkcgWm9uZSBjcmVhdGlvbiAqL1xuICAgIEBJbnB1dCgpIG5ld1pvbmVEYXRhOiBhbnk7XG5cbiAgICBuYXZJRHNab25lRWRpdDogc3RyaW5nW10gPSBbXTtcblxuICAgIC8vIHN3ZWVwcyBiZWxvbmdpbmcgdG8gYW55IGF1ZGlvIHpvbmVcbiAgICBASW5wdXQoKSBvY2N1cGllZFN3ZWVwczogc3RyaW5nW10gPSBbXTtcblxuICAgIC8vIHN3ZWVwcyB1bmF2YWlsYWJsZSAoY2Fubm90IGJlIGNob3NlbilcbiAgICBASW5wdXQoKSB1bmF2YWlsYWJsZVN3ZWVwczogc3RyaW5nW10gPSBbXTtcblxuICAgIC8vIGlmIGNob29zaW5nIHN3ZWVwcyBmb3IgYXVkaW8gem9uZVxuICAgIEBJbnB1dCgpIGVkaXRpbmdBdWRpb1pvbmU6IGJvb2xlYW4gPSBmYWxzZTtcblxuICAgIEBJbnB1dCgpIGlucHV0Wm9uZTogWm9uZTtcblxuICAgIGNob3NlblBsYW46IFBsYW47XG5cbiAgICAvKiogcGFuWm9vbSBlbGVtZW50IGZvciBhZGRpbmcgc2NhbnMgKi9cbiAgICBwYW5ab29tOiBQYW5ab29tO1xuXG4gICAgLyoqIGRpdlBsYW4gKHVzZSBCeSBwYW5ab29tKSAqL1xuICAgIGRpdlBsYW46IEhUTUxFbGVtZW50O1xuXG4gICAgLyoqIGFsbCBzY2FuIGJ1dHRvbnMgRWxlbWVudCAqL1xuICAgIGJ1dHRvbkVsZW1lbnRzOiBIVE1MQnV0dG9uRWxlbWVudFtdID0gW107XG5cbiAgICAvKiogU2NhbiBidXR0b25zIHRoYXQgYXJlIGluIHRoZSBjdXJyZW50IHNlbGVjdGlvbiAqL1xuICAgIGJ1dHRvbnNJblNlbGVjdGlvbjogSFRNTEJ1dHRvbkVsZW1lbnRbXSA9IFtdO1xuXG4gICAgQE91dHB1dCgpIHN3ZWVwc1NlbGVjdGVkID0gbmV3IEV2ZW50RW1pdHRlcjx7IHN3ZWVwczogc3RyaW5nW107IHN0YXJ0U3dlZXBJRDogc3RyaW5nOyB9PigpO1xuXG4gICAgaXNTZXR0aW5nU3RhcnRTd2VlcCA9IGZhbHNlO1xuXG4gICAgc3RhcnRTd2VlcElEOiBzdHJpbmc7XG5cbiAgICBjb25zdHJ1Y3RvcihcbiAgICAgICAgcHJpdmF0ZSB6b25lU2VydmljZTogWm9uZVNlcnZpY2UsXG4gICAgICAgIHByaXZhdGUgbmF2aWdhdGlvblNlcnZpY2U6IE5hdmlnYXRpb25TZXJ2aWNlLFxuICAgICAgICBwcml2YXRlIHBsYW5TZXJ2aWNlOiBQbGFuU2VydmljZSxcbiAgICApIHsgfVxuXG4gICAgbmdPbkluaXQoKTogdm9pZCB7XG4gICAgICAgIHRoaXMuZ2V0UGxhbnMoKTtcbiAgICAgICAgaWYgKHRoaXMuaW5wdXRab25lKSB7XG4gICAgICAgICAgICB0aGlzLnNldFN3ZWVwc09mSW5wdXRab25lKCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBuZ09uQ2hhbmdlcygpIHtcbiAgICAgICAgaWYgKHRoaXMuY2hvc2VuUGxhbikge1xuICAgICAgICAgICAgdGhpcy5zZXRTd2VlcHNPZklucHV0Wm9uZSgpO1xuICAgICAgICAgICAgdGhpcy5jaG9zZW5TY2Fuc09uUGxhbiA9IFtdO1xuICAgICAgICAgICAgdGhpcy5jbGVhckRpdlBsYW4oKTtcbiAgICAgICAgICAgIHRoaXMuYWRkU2NhblBvaW50cygpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgc2V0U3dlZXBzT2ZJbnB1dFpvbmUoKSB7XG4gICAgICAgIHRoaXMubmF2SURzWm9uZUVkaXQgPSB0aGlzLmlucHV0Wm9uZS5zd2VlcElEcztcbiAgICB9XG5cbiAgICBhc3luYyBnZXRQbGFucygpIHtcbiAgICAgICAgdGhpcy5wbGFucyA9IGF3YWl0IHRoaXMucGxhblNlcnZpY2UuZ2V0U2luZ2VkUGxhbnNGb3JTcGFjZShcbiAgICAgICAgICAgIHRoaXMuc3BhY2VJRCxcbiAgICAgICAgKTtcbiAgICB9XG5cbiAgICBhc3luYyBvblBsYW5DbGljayhwbGFuOiBQbGFuKSB7XG4gICAgICAgIHRoaXMuY2hvc2VuUGxhbiA9IHBsYW47XG4gICAgICAgIHRoaXMuY2xlYXJEaXZQbGFuKCk7XG4gICAgICAgIHRoaXMuYWRkU2NhblBvaW50cygpO1xuICAgIH1cblxuICAgIGFzeW5jIGFkZFNjYW5Qb2ludHMoKSB7XG4gICAgICAgIHRoaXMuZGl2UGxhbiA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoXCIjcGxhbkRpdlwiKSBhcyBIVE1MRWxlbWVudDtcbiAgICAgICAgY29uc3Qgem9uZU9mUGxhbiA9IGF3YWl0IHRoaXMuem9uZVNlcnZpY2UuZ2V0Wm9uZShcbiAgICAgICAgICAgIHRoaXMuY2hvc2VuUGxhbi56b25lSUQsXG4gICAgICAgICk7XG4gICAgICAgIGNvbnN0IG5hdmlnYXRpb25zID0gYXdhaXQgdGhpcy5uYXZpZ2F0aW9uU2VydmljZS5nZXROYXZpZ2F0aW9uc0ZvclpvbmUoXG4gICAgICAgICAgICB6b25lT2ZQbGFuLFxuICAgICAgICApO1xuICAgICAgICBpZiAodGhpcy5uZXdab25lRGF0YSkgYXdhaXQgdGhpcy5zZXRTY2FuQnlEcmF3KG5hdmlnYXRpb25zKTtcbiAgICAgICAgdGhpcy5idXR0b25FbGVtZW50cyA9IGF3YWl0IHNob3dTY2FuUG9pbnRzT25QbGFuSW5EaXYoXG4gICAgICAgICAgICB0aGlzLmNob3NlblBsYW4sXG4gICAgICAgICAgICB0aGlzLmRpdlBsYW4sXG4gICAgICAgICAgICBuYXZpZ2F0aW9ucyxcbiAgICAgICAgKTtcbiAgICAgICAgZm9yIChjb25zdCBlbGVtZW50IG9mIHRoaXMuYnV0dG9uRWxlbWVudHMpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLnVuYXZhaWxhYmxlU3dlZXBzICYmIHRoaXMudW5hdmFpbGFibGVTd2VlcHMuaW5jbHVkZXMoZWxlbWVudC5pZCkpIHtcbiAgICAgICAgICAgICAgICBzdHlsZUJ1dHRvbihlbGVtZW50LCBTd2VlcFN0YXRlLkRJU0FCTEVEKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgaWYgKFxuICAgICAgICAgICAgICAgICAgICAodGhpcy5uYXZJRHNab25lRWRpdC5sZW5ndGggPiAwICYmXG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLm5hdklEc1pvbmVFZGl0LmluY2x1ZGVzKGVsZW1lbnQuaWQpKVxuICAgICAgICAgICAgICAgICAgICB8fCB0aGlzLmNob3NlblNjYW5zT25QbGFuLmluY2x1ZGVzKGVsZW1lbnQuaWQpKSB7XG4gICAgICAgICAgICAgICAgICAgIHN0eWxlQnV0dG9uKGVsZW1lbnQsIFN3ZWVwU3RhdGUuQURERUQpO1xuICAgICAgICAgICAgICAgICAgICBpZiAoIXRoaXMuY2hvc2VuU2NhbnNPblBsYW4uaW5jbHVkZXMoZWxlbWVudC5pZCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY2hvc2VuU2NhbnNPblBsYW4ucHVzaChlbGVtZW50LmlkKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodGhpcy5vY2N1cGllZFN3ZWVwcyAmJiB0aGlzLm9jY3VwaWVkU3dlZXBzLmluY2x1ZGVzKGVsZW1lbnQuaWQpKSB7XG4gICAgICAgICAgICAgICAgICAgIHN0eWxlQnV0dG9uKGVsZW1lbnQsIFN3ZWVwU3RhdGUuT0NDVVBJRUQpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHN0eWxlQnV0dG9uKGVsZW1lbnQsIFN3ZWVwU3RhdGUuUkVNT1ZFRCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIC8vc3RhcnQgcG9pbnQgc2hvdWxkIGJlIGxhc3QgY29uZGl0aW9uIFxuICAgICAgICAgICAgICAgIGlmICh0aGlzLmlucHV0Wm9uZSAmJiB0aGlzLmlucHV0Wm9uZS5zdGFydFN3ZWVwSUQgPT09IGVsZW1lbnQuaWQpIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc29sZS5sb2coXCJzZXR0aW5nIHN0YXJ0IHBvaW50XCIpO1xuICAgICAgICAgICAgICAgICAgICBzdHlsZUJ1dHRvbihlbGVtZW50LCBTd2VlcFN0YXRlLlNUQVJUUE9JTlQpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbGVtZW50LmFkZEV2ZW50TGlzdGVuZXIoXCJjbGlja1wiLCAoZXZlbnQpID0+XG4gICAgICAgICAgICAgICAgICAgIHRoaXMub25CdXR0b25TY2FuQ2xpY2tlZChldmVudC50YXJnZXQgYXMgSFRNTEVsZW1lbnQpLFxuICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5wYW5ab29tID0gcGFuem9vbSh0aGlzLmRpdlBsYW4sIHtcbiAgICAgICAgICAgIGJvdW5kczogdHJ1ZSxcbiAgICAgICAgICAgIGJvdW5kc1BhZGRpbmc6IDAsXG4gICAgICAgICAgICBtYXhab29tOiAzLjUsXG4gICAgICAgICAgICBiZWZvcmVNb3VzZURvd24oZTogTW91c2VFdmVudCkge1xuICAgICAgICAgICAgICAgIHJldHVybiAoXG4gICAgICAgICAgICAgICAgICAgIGUuYnV0dG9uID09PSAyXG4gICAgICAgICAgICAgICAgKTsgLyoqIElnbm9yZSBldmVudCBmb3IgcmlnaHQgY2xpY2sgKHVzZSBmb3Igc2VsZWN0aW5nKSAqL1xuICAgICAgICAgICAgfSxcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqIEZ1bmN0aW9uIGlmIHdlIGFyZSBjb21pbmcgZm9yIHN2ZyBlZGl0b3Igd29ya2Zsb3cgKi9cbiAgICBzZXRTY2FuQnlEcmF3KG5hdmlnYXRpb25zOiBhbnlbXSk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoYXN5bmMgKHJlc29sdmUpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IHJlY3QgPSB7XG4gICAgICAgICAgICAgICAgd2lkdGg6IHRoaXMubmV3Wm9uZURhdGEud2lkdGgsXG4gICAgICAgICAgICAgICAgaGVpZ2h0OiB0aGlzLm5ld1pvbmVEYXRhLmhlaWdodCxcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICBjb25zdCBpbWcgPSBhd2FpdCBnZXRNZXRhRm9ySW1hZ2UodGhpcy5jaG9zZW5QbGFuLmZpbGVwYXRoKTtcbiAgICAgICAgICAgIGNvbnN0IHsgY29lZmZYLCBjb2VmZlkgfSA9IGdldENvZWZmaWNpZW50c0ZvckltYWdlKGltZywgcmVjdCk7XG5cbiAgICAgICAgICAgIGNvbnN0IGRyYXcgPSB0aGlzLm5ld1pvbmVEYXRhLmVsZW1lbnRzO1xuXG4gICAgICAgICAgICBkcmF3Lm1hcChhc3luYyAoZWxlbWVudDogYW55KSA9PiB7XG4gICAgICAgICAgICAgICAgc3dpdGNoIChlbGVtZW50Lm5vZGVOYW1lKSB7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgXCJyZWN0XCI6XG4gICAgICAgICAgICAgICAgICAgICAgICBhd2FpdCB0aGlzLnNldFNjYW5JblJlY3QoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaW1nLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvZWZmWCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2VmZlksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxlbWVudCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBuYXZpZ2F0aW9ucyxcbiAgICAgICAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcblxuICAgICAgICAgICAgICAgICAgICBjYXNlIFwiZWxsaXBzZVwiOlxuICAgICAgICAgICAgICAgICAgICAgICAgYXdhaXQgdGhpcy5zZXRTY2FuSW5DaXJjbGUoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaW1nLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvZWZmWCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2VmZlksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxlbWVudCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBuYXZpZ2F0aW9ucyxcbiAgICAgICAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcblxuICAgICAgICAgICAgICAgICAgICBjYXNlIFwicGF0aFwiOlxuICAgICAgICAgICAgICAgICAgICAgICAgYXdhaXQgdGhpcy5zZXRTY2FuSW5Qb2x5Z29uKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGltZyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2VmZlgsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29lZmZZLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsZW1lbnQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbmF2aWdhdGlvbnMsXG4gICAgICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBhc3luYyBzZXRTY2FuSW5SZWN0KGltZzogYW55LCBjb2VmZlg6IG51bWJlciwgY29lZmZZOiBudW1iZXIsXG4gICAgICAgIGVsZW1lbnQ6IHsgYW5nbGU6IGFueTsgY3g6IGFueTsgY3k6IGFueTsgeDogbnVtYmVyOyB3aWR0aDogYW55OyB5OiBudW1iZXI7IGhlaWdodDogYW55OyB9LCBuYXZpZ2F0aW9uczogYW55W10pIHtcbiAgICAgICAgY29uc3QgY2FsaWJyYWdlID0gSlNPTi5wYXJzZSh0aGlzLmNob3NlblBsYW4uY2FsaWJyYXRpb24pO1xuICAgICAgICBuYXZpZ2F0aW9ucy5tYXAoKG5hdmlnYXRpb24pID0+IHtcbiAgICAgICAgICAgIGNvbnN0IHBvc2l0aW9uc09uUGxhbiA9IG5hdmlnYXRpb24ucG9zaXRpb25PblBsYW4ubWFwKChlbnRyeSkgPT5cbiAgICAgICAgICAgICAgICBKU09OLnBhcnNlKGVudHJ5KSxcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICBjb25zdCBwb3NpdGlvbk9uUGxhbiA9IHBvc2l0aW9uc09uUGxhbi5maW5kKFxuICAgICAgICAgICAgICAgIChkYXRhKSA9PiBkYXRhLnBsYW5JRCA9PT0gdGhpcy5jaG9zZW5QbGFuLmlkLFxuICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIGlmIChwb3NpdGlvbk9uUGxhbikge1xuICAgICAgICAgICAgICAgIGNvbnN0IHJlYWxXaWR0aCA9IGltZy53aWR0aCAvIGNvZWZmWDtcbiAgICAgICAgICAgICAgICBjb25zdCByZWFsSGVpZ2h0ID0gaW1nLmhlaWdodCAvIGNvZWZmWTtcbiAgICAgICAgICAgICAgICBjb25zdCBuYXZZID0gKHBvc2l0aW9uT25QbGFuLnkgKiByZWFsSGVpZ2h0KSAvIGNhbGlicmFnZS5pbWdIZWlnaHQ7XG4gICAgICAgICAgICAgICAgY29uc3QgbmF2WCA9IChwb3NpdGlvbk9uUGxhbi54ICogcmVhbFdpZHRoKSAvIGNhbGlicmFnZS5pbWdXaWR0aDtcbiAgICAgICAgICAgICAgICBpZiAoXG4gICAgICAgICAgICAgICAgICAgIG5hdlggPiBlbGVtZW50LnggJiZcbiAgICAgICAgICAgICAgICAgICAgbmF2WCA8IGVsZW1lbnQueCArIGVsZW1lbnQud2lkdGggJiZcbiAgICAgICAgICAgICAgICAgICAgbmF2WSA+IGVsZW1lbnQueSAmJlxuICAgICAgICAgICAgICAgICAgICBuYXZZIDwgZWxlbWVudC55ICsgZWxlbWVudC5oZWlnaHQgJiZcbiAgICAgICAgICAgICAgICAgICAgIXRoaXMubmF2SURzWm9uZUVkaXQuaW5jbHVkZXMobmF2aWdhdGlvbi5pZClcbiAgICAgICAgICAgICAgICApIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5uYXZJRHNab25lRWRpdC5wdXNoKG5hdmlnYXRpb24uaWQpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gb2xkIGNhbGlicmF0aW9uOlxuICAgICAgICAgICAgLy8gY29uc3QgcG9zaXRpb24gPSBKU09OLnBhcnNlKG5hdmlnYXRpb24ucG9zaXRpb24pO1xuICAgICAgICAgICAgLy8gbGV0IG5hdlggPSAoY2FsaWJyYWdlLm9mZnNldFggKyBwb3NpdGlvbi54ICogY2FsaWJyYWdlLngpIC8gY29lZmZYO1xuICAgICAgICAgICAgLy8gbGV0IG5hdlkgPSAoY2FsaWJyYWdlLm9mZnNldFkgKyBwb3NpdGlvbi56ICogY2FsaWJyYWdlLnkpIC8gY29lZmZZO1xuICAgICAgICAgICAgLy8gaWYgKGVsZW1lbnQuYW5nbGUpIHtcbiAgICAgICAgICAgIC8vICAgICBjb25zdCByb3RhdGVQb3MgPSByb3RhdGUoXG4gICAgICAgICAgICAvLyAgICAgICAgIHsgeDogbmF2WCwgeTogbmF2WSB9LFxuICAgICAgICAgICAgLy8gICAgICAgICB7IHg6IGVsZW1lbnQuY3gsIHk6IGVsZW1lbnQuY3kgfSxcbiAgICAgICAgICAgIC8vICAgICAgICAgZWxlbWVudC5hbmdsZSxcbiAgICAgICAgICAgIC8vICAgICApO1xuICAgICAgICAgICAgLy8gICAgIG5hdlggPSByb3RhdGVQb3MueDtcbiAgICAgICAgICAgIC8vICAgICBuYXZZID0gcm90YXRlUG9zLnk7XG4gICAgICAgICAgICAvLyB9XG4gICAgICAgICAgICAvKipcbiAgICAgICAgICAgICAqIFRPRE8gY2FsY3VsZXIgbGEgcm90YXRpb24gZHUgcmVjdGFuZ2xlXG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIC8vIGlmIChcbiAgICAgICAgICAgIC8vICAgICBuYXZYID4gZWxlbWVudC54ICYmXG4gICAgICAgICAgICAvLyAgICAgbmF2WCA8IGVsZW1lbnQueCArIGVsZW1lbnQud2lkdGggJiZcbiAgICAgICAgICAgIC8vICAgICBuYXZZID4gZWxlbWVudC55ICYmXG4gICAgICAgICAgICAvLyAgICAgbmF2WSA8IGVsZW1lbnQueSArIGVsZW1lbnQuaGVpZ2h0ICYmXG4gICAgICAgICAgICAvLyAgICAgIXRoaXMubmF2SURzWm9uZUVkaXQuaW5jbHVkZXMobmF2aWdhdGlvbi5pZClcbiAgICAgICAgICAgIC8vICkge1xuICAgICAgICAgICAgLy8gICAgIHRoaXMubmF2SURzWm9uZUVkaXQucHVzaChuYXZpZ2F0aW9uLmlkKTtcbiAgICAgICAgICAgIC8vIH1cbiAgICAgICAgfSk7XG4gICAgfSAvLyBFT1xuXG4gICAgYXN5bmMgc2V0U2NhbkluQ2lyY2xlKGltZzogYW55LCBjb2VmZlg6IG51bWJlciwgY29lZmZZOiBudW1iZXIsXG4gICAgICAgIGVsZW1lbnQ6IHsgYW5nbGU6IGFueTsgY3g6IG51bWJlcjsgY3k6IG51bWJlcjsgcng6IG51bWJlcjsgcnk6IG51bWJlcjsgfSwgbmF2aWdhdGlvbnM6IE5hdmlnYXRpb25bXSkge1xuICAgICAgICBjb25zdCBjYWxpYnJhZ2UgPSBKU09OLnBhcnNlKHRoaXMuY2hvc2VuUGxhbi5jYWxpYnJhdGlvbik7XG4gICAgICAgIG5hdmlnYXRpb25zLm1hcChuYXZpZ2F0aW9uID0+IHtcbiAgICAgICAgICAgIGNvbnN0IHBvc2l0aW9uc09uUGxhbiA9IG5hdmlnYXRpb24ucG9zaXRpb25PblBsYW4ubWFwKChlbnRyeSkgPT5cbiAgICAgICAgICAgICAgICBKU09OLnBhcnNlKGVudHJ5KSxcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICBjb25zdCBwb3NpdGlvbk9uUGxhbiA9IHBvc2l0aW9uc09uUGxhbi5maW5kKFxuICAgICAgICAgICAgICAgIChkYXRhKSA9PiBkYXRhLnBsYW5JRCA9PT0gdGhpcy5jaG9zZW5QbGFuLmlkLFxuICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIGlmIChwb3NpdGlvbk9uUGxhbikge1xuICAgICAgICAgICAgICAgIGNvbnN0IHJlYWxXaWR0aCA9IGltZy53aWR0aCAvIGNvZWZmWDtcbiAgICAgICAgICAgICAgICBjb25zdCByZWFsSGVpZ2h0ID0gaW1nLmhlaWdodCAvIGNvZWZmWTtcbiAgICAgICAgICAgICAgICBsZXQgbmF2WSA9IChwb3NpdGlvbk9uUGxhbi55ICogcmVhbEhlaWdodCkgLyBjYWxpYnJhZ2UuaW1nSGVpZ2h0O1xuICAgICAgICAgICAgICAgIGxldCBuYXZYID0gKHBvc2l0aW9uT25QbGFuLnggKiByZWFsV2lkdGgpIC8gY2FsaWJyYWdlLmltZ1dpZHRoO1xuICAgICAgICAgICAgICAgIGlmIChlbGVtZW50LmFuZ2xlKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHJvdGF0ZVBvcyA9IHJvdGF0ZShcbiAgICAgICAgICAgICAgICAgICAgICAgIHsgeDogbmF2WCwgeTogbmF2WSB9LFxuICAgICAgICAgICAgICAgICAgICAgICAgeyB4OiBlbGVtZW50LmN4LCB5OiBlbGVtZW50LmN5IH0sXG4gICAgICAgICAgICAgICAgICAgICAgICBlbGVtZW50LmFuZ2xlLFxuICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgICBuYXZYID0gcm90YXRlUG9zLng7XG4gICAgICAgICAgICAgICAgICAgIG5hdlkgPSByb3RhdGVQb3MueTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBjb25zdCB2YWx1ZVggPVxuICAgICAgICAgICAgICAgICAgICBNYXRoLnBvdyhuYXZYIC0gZWxlbWVudC5jeCwgMikgLyBNYXRoLnBvdyhlbGVtZW50LnJ4LCAyKTtcbiAgICAgICAgICAgICAgICBjb25zdCB2YWx1ZVkgPVxuICAgICAgICAgICAgICAgICAgICBNYXRoLnBvdyhuYXZZIC0gZWxlbWVudC5jeSwgMikgLyBNYXRoLnBvdyhlbGVtZW50LnJ5LCAyKTtcbiAgICAgICAgICAgICAgICBjb25zdCByZXN1bHQgPSB2YWx1ZVggKyB2YWx1ZVk7XG4gICAgICAgICAgICAgICAgaWYgKHJlc3VsdCA8PSAxICYmICF0aGlzLm5hdklEc1pvbmVFZGl0LmluY2x1ZGVzKG5hdmlnYXRpb24uaWQpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMubmF2SURzWm9uZUVkaXQucHVzaChuYXZpZ2F0aW9uLmlkKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIG9sZCBjYWxpYnJhdGlvblxuICAgICAgICAgICAgLy8gY29uc3QgcG9zaXRpb24gPSBKU09OLnBhcnNlKG5hdmlnYXRpb24ucG9zaXRpb24pO1xuICAgICAgICAgICAgLy8gbGV0IG5hdlggPSAoY2FsaWJyYWdlLm9mZnNldFggKyBwb3NpdGlvbi54ICogY2FsaWJyYWdlLngpIC8gY29lZmZYO1xuICAgICAgICAgICAgLy8gbGV0IG5hdlkgPSAoY2FsaWJyYWdlLm9mZnNldFkgKyBwb3NpdGlvbi56ICogY2FsaWJyYWdlLnkpIC8gY29lZmZZO1xuICAgICAgICAgICAgLy8gaWYgKGVsZW1lbnQuYW5nbGUpIHtcbiAgICAgICAgICAgIC8vICAgICBjb25zdCByb3RhdGVQb3MgPSByb3RhdGUoXG4gICAgICAgICAgICAvLyAgICAgICAgIHsgeDogbmF2WCwgeTogbmF2WSB9LFxuICAgICAgICAgICAgLy8gICAgICAgICB7IHg6IGVsZW1lbnQuY3gsIHk6IGVsZW1lbnQuY3kgfSxcbiAgICAgICAgICAgIC8vICAgICAgICAgZWxlbWVudC5hbmdsZSxcbiAgICAgICAgICAgIC8vICAgICApO1xuICAgICAgICAgICAgLy8gICAgIG5hdlggPSByb3RhdGVQb3MueDtcbiAgICAgICAgICAgIC8vICAgICBuYXZZID0gcm90YXRlUG9zLnk7XG4gICAgICAgICAgICAvLyB9XG5cbiAgICAgICAgICAgIC8vIGNvbnN0IHZhbHVlWCA9XG4gICAgICAgICAgICAvLyAgICAgTWF0aC5wb3cobmF2WCAtIGVsZW1lbnQuY3gsIDIpIC8gTWF0aC5wb3coZWxlbWVudC5yeCwgMik7XG4gICAgICAgICAgICAvLyBjb25zdCB2YWx1ZVkgPVxuICAgICAgICAgICAgLy8gICAgIE1hdGgucG93KG5hdlkgLSBlbGVtZW50LmN5LCAyKSAvIE1hdGgucG93KGVsZW1lbnQucnksIDIpO1xuICAgICAgICAgICAgLy8gY29uc3QgcmVzdWx0ID0gdmFsdWVYICsgdmFsdWVZO1xuICAgICAgICAgICAgLy8gaWYgKHJlc3VsdCA8PSAxICYmICF0aGlzLm5hdklEc1pvbmVFZGl0LmluY2x1ZGVzKG5hdmlnYXRpb24uaWQpKSB7XG4gICAgICAgICAgICAvLyAgICAgdGhpcy5uYXZJRHNab25lRWRpdC5wdXNoKG5hdmlnYXRpb24uaWQpO1xuICAgICAgICAgICAgLy8gfVxuICAgICAgICB9KTtcbiAgICB9IC8vIEVPXG5cbiAgICBhc3luYyBzZXRTY2FuSW5Qb2x5Z29uKGltZzogYW55LCBjb2VmZlg6IG51bWJlciwgY29lZmZZOiBudW1iZXIsIGVsZW1lbnQ6IHsgc2VnTGlzdDogYW55OyB9LCBuYXZpZ2F0aW9uczogYW55W10pIHtcbiAgICAgICAgY29uc3QgY2FsaWJyYWdlID0gSlNPTi5wYXJzZSh0aGlzLmNob3NlblBsYW4uY2FsaWJyYXRpb24pO1xuICAgICAgICBuYXZpZ2F0aW9ucy5tYXAoYXN5bmMgKG5hdmlnYXRpb24pID0+IHtcblxuICAgICAgICAgICAgY29uc3QgcG9zaXRpb25zT25QbGFuID0gbmF2aWdhdGlvbi5wb3NpdGlvbk9uUGxhbi5tYXAoKGVudHJ5KSA9PlxuICAgICAgICAgICAgICAgIEpTT04ucGFyc2UoZW50cnkpLFxuICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIGNvbnN0IHBvc2l0aW9uT25QbGFuID0gcG9zaXRpb25zT25QbGFuLmZpbmQoXG4gICAgICAgICAgICAgICAgKGRhdGEpID0+IGRhdGEucGxhbklEID09PSB0aGlzLmNob3NlblBsYW4uaWQsXG4gICAgICAgICAgICApO1xuICAgICAgICAgICAgaWYgKHBvc2l0aW9uT25QbGFuKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgcmVhbFdpZHRoID0gaW1nLndpZHRoIC8gY29lZmZYO1xuICAgICAgICAgICAgICAgIGNvbnN0IHJlYWxIZWlnaHQgPSBpbWcuaGVpZ2h0IC8gY29lZmZZO1xuICAgICAgICAgICAgICAgIGxldCBuYXZZID0gKHBvc2l0aW9uT25QbGFuLnkgKiByZWFsSGVpZ2h0KSAvIGNhbGlicmFnZS5pbWdIZWlnaHQ7XG4gICAgICAgICAgICAgICAgbGV0IG5hdlggPSAocG9zaXRpb25PblBsYW4ueCAqIHJlYWxXaWR0aCkgLyBjYWxpYnJhZ2UuaW1nV2lkdGg7XG5cbiAgICAgICAgICAgICAgICBjb25zdCBwID0ge1xuICAgICAgICAgICAgICAgICAgICB4OiBuYXZYLFxuICAgICAgICAgICAgICAgICAgICB5OiBuYXZZLFxuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgaWYgKFxuICAgICAgICAgICAgICAgICAgICBpc0luUG9seWdvbihwLCBlbGVtZW50LnNlZ0xpc3QpICYmXG4gICAgICAgICAgICAgICAgICAgICF0aGlzLm5hdklEc1pvbmVFZGl0LmluY2x1ZGVzKG5hdmlnYXRpb24uaWQpXG4gICAgICAgICAgICAgICAgKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMubmF2SURzWm9uZUVkaXQucHVzaChuYXZpZ2F0aW9uLmlkKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIG9sZCBjYWxpYnJhdGlvblxuICAgICAgICAgICAgLy8gY29uc3QgcG9zaXRpb24gPSBKU09OLnBhcnNlKG5hdmlnYXRpb24ucG9zaXRpb24pO1xuICAgICAgICAgICAgLy8gY29uc3QgcCA9IHtcbiAgICAgICAgICAgIC8vICAgICB4OiAoY2FsaWJyYWdlLm9mZnNldFggKyBwb3NpdGlvbi54ICogY2FsaWJyYWdlLngpIC8gY29lZmZYLFxuICAgICAgICAgICAgLy8gICAgIHk6IChjYWxpYnJhZ2Uub2Zmc2V0WSArIHBvc2l0aW9uLnogKiBjYWxpYnJhZ2UueSkgLyBjb2VmZlksXG4gICAgICAgICAgICAvLyB9O1xuICAgICAgICAgICAgLy8gaWYgKGVsZW1lbnQuYW5nbGUpIHtcbiAgICAgICAgICAgIC8vICAgICBwID0gdGhpcy5yb3RhdGUoXG4gICAgICAgICAgICAvLyAgICAgICAgIHAsXG4gICAgICAgICAgICAvLyAgICAgICAgIHsgeDogZWxlbWVudC5jeCwgeTogZWxlbWVudC5jeSB9LFxuICAgICAgICAgICAgLy8gICAgICAgICBlbGVtZW50LmFuZ2xlLFxuICAgICAgICAgICAgLy8gICAgICk7XG4gICAgICAgICAgICAvLyB9XG4gICAgICAgICAgICAvLyBpZiAoXG4gICAgICAgICAgICAvLyAgICAgaXNJblBvbHlnb24ocCwgZWxlbWVudC5zZWdMaXN0KSAmJlxuICAgICAgICAgICAgLy8gICAgICF0aGlzLm5hdklEc1pvbmVFZGl0LmluY2x1ZGVzKG5hdmlnYXRpb24uaWQpXG4gICAgICAgICAgICAvLyApIHtcbiAgICAgICAgICAgIC8vICAgICB0aGlzLm5hdklEc1pvbmVFZGl0LnB1c2gobmF2aWdhdGlvbi5pZCk7XG4gICAgICAgICAgICAvLyB9XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIGNsZWFyRGl2UGxhbigpIHtcbiAgICAgICAgaWYgKHRoaXMuZGl2UGxhbikgdGhpcy5kaXZQbGFuLmlubmVySFRNTCA9IFwiXCI7XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBUcmlnZ2VyIGVhY2ggYnkgdGhlIHNlbGVjdGlvbkNvbXBvbmVudCB3aGVuIHNlbGVjdGlvbiBjaGFuZ2VcbiAgICAgKiBVcGRhdGUgdGhlIGN1cnJlbnQgc2VsZWN0ZWQgc2NhbiBidXR0b25zXG4gICAgICogQHBhcmFtIHNlbGVjdGlvbiBuZXcgc2VsZWN0aW9uXG4gICAgICovXG4gICAgb25TZWxlY3Rpb25DaGFuZ2VkKHNlbGVjdGlvbjogUmVjdGFuZ2xlKSB7XG4gICAgICAgIGNvbnN0IHVuc2VsZWN0ZWRCdXR0b25zOiBIVE1MQnV0dG9uRWxlbWVudFtdID0gW107XG4gICAgICAgIGNvbnN0IG5ld1NlbGVjdGVkQnV0dG9ucyA9IFtdO1xuXG4gICAgICAgIC8qKiBGb3IgZWFjaCBidXR0b24sIGRlY2lkZSB3aGV0aGVyIHdpbGwgYmUgYWRkIHRvIHNlbGVjdGVkIGxpc3Qgb3IgdW5zZWxlY3RlZCBsaXN0ICovXG4gICAgICAgIGZvciAoY29uc3QgYnV0dG9uIG9mIHRoaXMuYnV0dG9uRWxlbWVudHMpIHtcbiAgICAgICAgICAgIGNvbnN0IGlzU2VsZWN0ZWQgPSBidXR0b25Jc0luU2VsZWN0aW9uKGJ1dHRvbiwgc2VsZWN0aW9uKTtcbiAgICAgICAgICAgIGlmICh0aGlzLmJ1dHRvbnNJblNlbGVjdGlvbi5pbmNsdWRlcyhidXR0b24pKSB7XG4gICAgICAgICAgICAgICAgLyoqIElmIHRoZSBidXR0b24gaXMgYWxyZWFkeSBpbiB0aGUgc2VsZWN0ZWQgbGlzdCwgd2UgY2hlY2sgaWYgaXQgc2hvdWxkIGJlIHVuc2VsZWN0ICovXG4gICAgICAgICAgICAgICAgaWYgKCFpc1NlbGVjdGVkKSB7XG4gICAgICAgICAgICAgICAgICAgIHVuc2VsZWN0ZWRCdXR0b25zLnB1c2goYnV0dG9uKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2UgaWYgKGlzU2VsZWN0ZWQpIHtcbiAgICAgICAgICAgICAgICBuZXdTZWxlY3RlZEJ1dHRvbnMucHVzaChidXR0b24pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgLyoqIFZpc3VhbGx5IFVwZGF0ZSB1bnNlbGVjdGVkIGxpc3QgKi9cbiAgICAgICAgZm9yIChjb25zdCBidXR0b24gb2YgdW5zZWxlY3RlZEJ1dHRvbnMpIHtcbiAgICAgICAgICAgIHNldFZpc3VhbGx5U2VsZWN0ZWQoYnV0dG9uLCBmYWxzZSk7XG4gICAgICAgIH1cblxuICAgICAgICAvKiogVmlzdWFsbHkgVXBkYXRlIHNlbGVjdGVkIGxpc3QgKi9cbiAgICAgICAgZm9yIChjb25zdCBidXR0b24gb2YgbmV3U2VsZWN0ZWRCdXR0b25zKSB7XG4gICAgICAgICAgICBzZXRWaXN1YWxseVNlbGVjdGVkKGJ1dHRvbiwgdHJ1ZSk7XG4gICAgICAgIH1cblxuICAgICAgICAvKiogUmVtb3ZlICB1bnNlbGVjdGVkIGxpc3QgKi9cbiAgICAgICAgdGhpcy5idXR0b25zSW5TZWxlY3Rpb24gPSB0aGlzLmJ1dHRvbnNJblNlbGVjdGlvbi5maWx0ZXIoKGJ1dHRvbikgPT4ge1xuICAgICAgICAgICAgcmV0dXJuICF1bnNlbGVjdGVkQnV0dG9ucy5pbmNsdWRlcyhidXR0b24pO1xuICAgICAgICB9KTtcbiAgICAgICAgLyoqIEFkZCBuZXcgc2VsZWN0ZWQgYnV0dG9ucyAqL1xuICAgICAgICB0aGlzLmJ1dHRvbnNJblNlbGVjdGlvbiA9IFtcbiAgICAgICAgICAgIC4uLnRoaXMuYnV0dG9uc0luU2VsZWN0aW9uLFxuICAgICAgICAgICAgLi4ubmV3U2VsZWN0ZWRCdXR0b25zLFxuICAgICAgICBdO1xuICAgIH1cblxuXG5cbiAgICAvKipcbiAgICAgKiBUcmlnZ2VyIHdoZW4gdGhlIHVzZXIgY2xpY2sgdG8gYWRkIHRoZSBzZWxlY3RlZCBzY2Fuc1xuICAgICAqL1xuICAgIG9uU2VsZWN0aW9uQWRkKCkge1xuICAgICAgICBmb3IgKGNvbnN0IGJ1dHRvbiBvZiB0aGlzLmJ1dHRvbnNJblNlbGVjdGlvbikge1xuICAgICAgICAgICAgaWYgKCF0aGlzLmNob3NlblNjYW5zT25QbGFuLmluY2x1ZGVzKGJ1dHRvbi5pZCkpIHtcbiAgICAgICAgICAgICAgICB0aGlzLm9uQnV0dG9uU2NhbkNsaWNrZWQoYnV0dG9uKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMub25TZWxlY3Rpb25DaGFuZ2VkKHsgdG9wOiAwLCBsZWZ0OiAwLCB3aWR0aDogMCwgaGVpZ2h0OiAwIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRyaWdnZXIgd2hlbiB0aGUgdXNlciBjbGljayB0byByZW1vdmUgdGhlIHNlbGVjdGVkIHNjYW5zXG4gICAgICovXG4gICAgb25TZWxlY3Rpb25SZW1vdmUoKSB7XG4gICAgICAgIGZvciAoY29uc3QgYnV0dG9uIG9mIHRoaXMuYnV0dG9uc0luU2VsZWN0aW9uKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5jaG9zZW5TY2Fuc09uUGxhbi5pbmNsdWRlcyhidXR0b24uaWQpKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5vbkJ1dHRvblNjYW5DbGlja2VkKGJ1dHRvbik7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5vblNlbGVjdGlvbkNoYW5nZWQoeyB0b3A6IDAsIGxlZnQ6IDAsIHdpZHRoOiAwLCBoZWlnaHQ6IDAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVHJpZ2dlciB3aGVuIHRoZSB1c2VyIGNsaWNrIHRvIHNlbGVjdCBhbGwgc2NhbnNcbiAgICAgKi9cbiAgICBvblNlbGVjdEFsbCgpIHtcbiAgICAgICAgdGhpcy5idXR0b25zSW5TZWxlY3Rpb24gPSBbLi4udGhpcy5idXR0b25FbGVtZW50c107XG4gICAgICAgIGZvciAoY29uc3QgYnV0dG9uIG9mIHRoaXMuYnV0dG9uc0luU2VsZWN0aW9uKSB7XG4gICAgICAgICAgICBzZXRWaXN1YWxseVNlbGVjdGVkKGJ1dHRvbiwgdHJ1ZSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUcmlnZ2VyIHdoZW4gdGhlIHVzZXIgY2hhbmdlIHRoZSBzaXplIG9mIHRoZSBzY2FuIHBvaW50c1xuICAgICAqIEBwYXJhbSBldmVudFxuICAgICAqL1xuICAgIG9uQ2hhbmdlU2NhblNpemUoZXZlbnQ6IGFueSkge1xuICAgICAgICBjb25zdCBmYWN0b3IgPSBldmVudC50YXJnZXQudmFsdWU7XG5cbiAgICAgICAgZm9yIChjb25zdCBidXR0b24gb2YgdGhpcy5idXR0b25FbGVtZW50cykge1xuICAgICAgICAgICAgYnV0dG9uLnN0eWxlLnRyYW5zZm9ybSA9IGBzY2FsZSgke2ZhY3Rvcn0pYDtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFdoZW4gYSBidXR0b24gcmVwcmVzZW50aW5nIGEgc2NhbiBpcyBjbGlja2VkXG4gICAgICogQHBhcmFtIGJ1dHRvblxuICAgICAqL1xuICAgIG9uQnV0dG9uU2NhbkNsaWNrZWQoYnV0dG9uOiBIVE1MRWxlbWVudCkge1xuICAgICAgICBpZiAodGhpcy5pc1NldHRpbmdTdGFydFN3ZWVwKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5zdGFydFN3ZWVwSUQgPT09IGJ1dHRvbi5pZCkge1xuICAgICAgICAgICAgICAgIC8vIHdlIGRlc2VsZWN0IHRoZSBzdGFydGluZyBwb2ludFxuICAgICAgICAgICAgICAgIGJ1dHRvbi5zdHlsZS5iYWNrZ3JvdW5kSW1hZ2UgPSBgdXJsKFwiaHR0cHM6Ly9hcGkuaWNvbmlmeS5kZXNpZ24vbWRpOmFkanVzdC5zdmc/Y29sb3I9Z3JlZW4maGVpZ2h0PTE3JndpZHRoPTE3XCIpYDtcbiAgICAgICAgICAgICAgICB0aGlzLnN0YXJ0U3dlZXBJRCA9IG51bGw7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgYnV0dG9uLnN0eWxlLmJhY2tncm91bmRJbWFnZSA9IGB1cmwoJ2h0dHBzOi8vYXBpLmljb25pZnkuZGVzaWduL2ljL2Jhc2VsaW5lLWZsYWctY2lyY2xlLnN2Zz9jb2xvcj13aGl0ZSZ3aWR0aD0xNyZoZWlnaHQ9MTcnKWA7XG4gICAgICAgICAgICBpZiAoIXRoaXMuY2hvc2VuU2NhbnNPblBsYW4uaW5jbHVkZXMoYnV0dG9uLmlkKSkge1xuICAgICAgICAgICAgICAgIHRoaXMuY2hvc2VuU2NhbnNPblBsYW4ucHVzaChidXR0b24uaWQpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHRoaXMuc3RhcnRTd2VlcElEKSB7XG4gICAgICAgICAgICAgICAgLy8gd2UgYXJlIGNoYW5naW5nIHN0YXJ0IHN3ZWVwXG4gICAgICAgICAgICAgICAgY29uc3QgYnRuQ2hhbmdlZCA9IHRoaXMuYnV0dG9uRWxlbWVudHMuZmluZCgoYnRuKSA9PiBidG4uaWQgPT09IHRoaXMuc3RhcnRTd2VlcElEKTtcbiAgICAgICAgICAgICAgICBidG5DaGFuZ2VkLnN0eWxlLmJhY2tncm91bmRJbWFnZSA9IGB1cmwoXCJodHRwczovL2FwaS5pY29uaWZ5LmRlc2lnbi9tZGk6YWRqdXN0LnN2Zz9jb2xvcj1ncmVlbiZoZWlnaHQ9MTcmd2lkdGg9MTdcIilgO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5zdGFydFN3ZWVwSUQgPSBidXR0b24uaWQ7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCF0aGlzLmNob3NlblNjYW5zT25QbGFuLmluY2x1ZGVzKGJ1dHRvbi5pZCkpIHtcbiAgICAgICAgICAgIC8vIGFkZCB0byBzZWxlY3Rpb25cbiAgICAgICAgICAgIGJ1dHRvbi5zdHlsZS5iYWNrZ3JvdW5kSW1hZ2UgPSBgdXJsKFwiaHR0cHM6Ly9hcGkuaWNvbmlmeS5kZXNpZ24vbWRpOmFkanVzdC5zdmc/Y29sb3I9Z3JlZW4maGVpZ2h0PTE3JndpZHRoPTE3XCIpYDtcbiAgICAgICAgICAgIHRoaXMuY2hvc2VuU2NhbnNPblBsYW4ucHVzaChidXR0b24uaWQpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgLy8gcmVtb3ZlIGZyb20gc2VsZWN0aW9uXG4gICAgICAgICAgICBpZiAodGhpcy5vY2N1cGllZFN3ZWVwcy5pbmNsdWRlcyhidXR0b24uaWQpICYmICF0aGlzLm5hdklEc1pvbmVFZGl0LmluY2x1ZGVzKGJ1dHRvbi5pZCkpIHtcbiAgICAgICAgICAgICAgICAvLyB0aGUgc3dlZXAgYmVsb25ncyB0byBhbm90aGVyIHpvbmUgPT4gc2V0IG9yYW5nZVxuICAgICAgICAgICAgICAgIGJ1dHRvbi5zdHlsZS5iYWNrZ3JvdW5kSW1hZ2UgPSBgdXJsKFwiaHR0cHM6Ly9hcGkuaWNvbmlmeS5kZXNpZ24vbWRpOmFkanVzdC5zdmc/Y29sb3I9b3JhbmdlJmhlaWdodD0xNyZ3aWR0aD0xN1wiKWA7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGJ1dHRvbi5zdHlsZS5iYWNrZ3JvdW5kSW1hZ2UgPSBgdXJsKFwiaHR0cHM6Ly9hcGkuaWNvbmlmeS5kZXNpZ24vbWRpOmNsb3NlLWNpcmNsZS1vdXRsaW5lLnN2Zz9jb2xvcj1yZWQmaGVpZ2h0PTE3JndpZHRoPTE3XCIpYDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbnN0IGluZGV4ID0gdGhpcy5jaG9zZW5TY2Fuc09uUGxhbi5pbmRleE9mKGJ1dHRvbi5pZCk7XG4gICAgICAgICAgICB0aGlzLmNob3NlblNjYW5zT25QbGFuLnNwbGljZShpbmRleCwgMSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBvblNhdmVTZWxlY3Rpb24oKSB7XG4gICAgICAgIHRoaXMuc3dlZXBzU2VsZWN0ZWQuZW1pdCh7IFwic3dlZXBzXCI6IHRoaXMuY2hvc2VuU2NhbnNPblBsYW4sIFwic3RhcnRTd2VlcElEXCI6IHRoaXMuc3RhcnRTd2VlcElEIH0pO1xuICAgIH1cblxuICAgIG9uQ2FuY2VsKCkge1xuICAgICAgICB0aGlzLnN3ZWVwc1NlbGVjdGVkLmVtaXQobnVsbCk7XG4gICAgfVxufVxuIiwiPGRpdiBuZ2JEcm9wZG93biBjbGFzcz1cInNwLXJvdyBkLWlubGluZS1ibG9ja1wiPlxuICAgIDxkaXYgY2xhc3M9XCJjb2wtc20tM1wiICpuZ0lmPVwicGxhbnNcIj5cbiAgICAgICAgICAgIDxidXR0b24gdHlwZT1cImJ1dHRvblwiIGNsYXNzPVwiYnRuIGJ0bi1sYWJlbC1maWxlIHJvdW5kZWQtcGlsbFwiIGlkPVwiZHJvcGRvd25CYXNpYzFcIlxuICAgICAgICAgICAgICAgIG5nYkRyb3Bkb3duVG9nZ2xlPnt7Y2hvc2VuUGxhbiA/XG4gICAgICAgICAgICAgICAgY2hvc2VuUGxhbi5uYW1lIDogKCdDaG9vc2UgUGxhbicgfCB0cmFuc2xhdGUpIH19PC9idXR0b24+XG4gICAgICAgICAgICA8ZGl2IG5nYkRyb3Bkb3duTWVudSBhcmlhLWxhYmVsbGVkYnk9XCJkcm9wZG93bkJhc2ljMVwiPlxuICAgICAgICAgICAgICAgIDxidXR0b24gdHlwZT1cImJ1dHRvblwiIG5nYkRyb3Bkb3duSXRlbSAqbmdGb3I9XCJsZXQgcGxhbiBvZiBwbGFuc1wiIChjbGljayk9XCJvblBsYW5DbGljayhwbGFuKVwiXG4gICAgICAgICAgICAgICAgICAgIFtkaXNhYmxlZF09XCIhcGxhbi5jYWxpYnJhdGlvblwiPnt7IHBsYW4ubmFtZSB9fVxuICAgICAgICAgICAgICAgIDwvYnV0dG9uPlxuICAgICAgICAgICAgPC9kaXY+XG4gICAgPC9kaXY+XG48L2Rpdj5cbjxkaXYgY2xhc3M9XCJzcC1yb3dcIj5cbiAgICA8bGliLXNlbGVjdGlvbiBjbGFzcz1cImNvbC1tZC04XCIgKG9uU2VsZWN0aW9uQ2hhbmdlZCk9XCJvblNlbGVjdGlvbkNoYW5nZWQoJGV2ZW50KVwiPlxuICAgICAgICA8bGliLXBsYW4tbGVnZW5kIFtpc0F1ZGlvWm9uZV09XCJlZGl0aW5nQXVkaW9ab25lXCIgKm5nSWY9XCJidXR0b25FbGVtZW50cy5sZW5ndGggPiAwXCI+PC9saWItcGxhbi1sZWdlbmQ+XG4gICAgICAgIDxkaXYgY2xhc3M9XCJzZWxlY3Rab25lXCIgb25jb250ZXh0bWVudT1cInJldHVybiBmYWxzZTtcIj5cbiAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJzcC1yb3dcIj5cbiAgICAgICAgICAgICAgICA8ZGl2IHN0eWxlPVwib3ZlcmZsb3c6IGhpZGRlbjt3aWR0aDoxMDAlO1wiPlxuICAgICAgICAgICAgICAgICAgICA8ZGl2IHN0eWxlPVwiaGVpZ2h0OiA0MDBweDsgd2lkdGg6IDEwMCU7XCIgaWQ9XCJwbGFuRGl2XCI+XG4gICAgICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgIDwvZGl2PlxuICAgIDwvbGliLXNlbGVjdGlvbj5cbiAgICBcbiAgICA8ZGl2IGNsYXNzPVwiY29sLW1kLTQgc2NhblRvb2xcIiAqbmdJZj1cImJ1dHRvbkVsZW1lbnRzLmxlbmd0aCA+IDBcIj5cbiAgICAgICAgPGRpdiBjbGFzcz1cInNwLXJvdyBkLWlubGluZS1ibG9ja1wiPlxuICAgICAgICAgICAgPGgyPnt7J3NlbGVjdFRvb2wudGl0bGUnIHwgdHJhbnNsYXRlfX08L2gyPlxuICAgICAgICAgICAgPGRpdiBjbGFzcz1cInByb3RpcFwiPnt7J3NlbGVjdFRvb2wudGlwJyB8IHRyYW5zbGF0ZX19LjwvZGl2PlxuICAgICAgICA8L2Rpdj5cbiAgICBcbiAgICAgICAgPGRpdiBjbGFzcz1cInNwLXJvd1wiPlxuICAgICAgICAgICAgPGRpdiBjbGFzcz1cImNvbC0zXCIgc3R5bGU9XCJwYWRkaW5nOjBweFwiPlxuICAgICAgICAgICAgICAgIDxsYWJlbCBjbGFzcz1cInRvb2wtbGFiZWxcIiBmb3I9XCJzY2FuU2l6ZVwiPnt7J3NlbGVjdFRvb2wuc2l6ZScgfCB0cmFuc2xhdGV9fTwvbGFiZWw+XG4gICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJjb2wtOVwiPlxuICAgICAgICAgICAgICAgIDxpbnB1dCB0eXBlPVwicmFuZ2VcIiBjbGFzcz1cImZvcm0tcmFuZ2VcIiBtaW49XCIwLjAwMVwiIG1heD1cIjVcIiBzdGVwPVwiMC4wMVwiIHZhbHVlPVwiMVwiXG4gICAgICAgICAgICAgICAgICAgIGlkPVwic2NhblNpemVcIiAoaW5wdXQpPVwib25DaGFuZ2VTY2FuU2l6ZSgkZXZlbnQpXCI+XG4gICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgPC9kaXY+XG4gICAgXG4gICAgICAgIDxkaXYgY2xhc3M9XCJzcC1yb3dcIj5cbiAgICAgICAgICAgIDxidXR0b24gY2xhc3M9XCJidG4gYnRuLXByaW1hcnkgcm91bmRlZC1waWxsXCIgKGNsaWNrKT1cIm9uU2VsZWN0QWxsKClcIj57eydzZWxlY3RUb29sLnNlbGVjdEFsbCcgfCB0cmFuc2xhdGV9fTwvYnV0dG9uPlxuICAgICAgICA8L2Rpdj5cbiAgICBcbiAgICAgICAgPGRpdiAqbmdJZj1cImJ1dHRvbnNJblNlbGVjdGlvbi5sZW5ndGggPiAwXCIgY2xhc3M9XCJlZGl0LXNlbGVjdGVkXCI+XG4gICAgICAgICAgICA8c3BhbiBjbGFzcz1cInRvb2wtbGFiZWxcIj57eydzZWxlY3RUb29sLmVkaXQnIHwgdHJhbnNsYXRlfX0gOiA8L3NwYW4+XG4gICAgICAgICAgICA8ZGl2IGNsYXNzPVwic3Atcm93XCI+XG4gICAgICAgICAgICAgICAgPGJ1dHRvbiBjbGFzcz1cImJ0biByb3VuZGVkLXBpbGwgYnRuLXByaW1hcnkgbXMtMyBtZS0yXCIgKGNsaWNrKT1cIm9uU2VsZWN0aW9uQWRkKClcIj57eydzZWxlY3RUb29sLmFkZCcgfCB0cmFuc2xhdGV9fTwvYnV0dG9uPlxuICAgICAgICAgICAgICAgIDxidXR0b24gY2xhc3M9XCJidG4gYnRuLXByaW1hcnkgcm91bmRlZC1waWxsXCIgKGNsaWNrKT1cIm9uU2VsZWN0aW9uUmVtb3ZlKClcIj57eydzZWxlY3RUb29sLnVuZG8nIHwgdHJhbnNsYXRlfX08L2J1dHRvbj5cbiAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICA8L2Rpdj5cblxuICAgICAgICA8ZGl2IGNsYXNzPVwic3Atcm93XCI+XG4gICAgICAgICAgICB7eyBjaG9zZW5TY2Fuc09uUGxhbi5sZW5ndGggfX0ge3snc2NhbiBwb2ludHMgY2hvc2VuJyB8IHRyYW5zbGF0ZX19ICAgICAgICAgXG4gICAgICAgIDwvZGl2PlxuICAgICAgICA8ZGl2ICpuZ0lmPVwiIWVkaXRpbmdBdWRpb1pvbmVcIiBjbGFzcz1cInNwLXJvd1wiPlxuICAgICAgICAgICAgPGxpYi1yYWRpby1idXR0b24gIGxhYmVsPVwie3sgJ3NlbGVjdFRvb2wuY2hvb3NlU3RhcnRQb2ludCcgIHwgdHJhbnNsYXRlIH19XCIgKGlzQ2hlY2tlZEV2ZW50KT1cImlzU2V0dGluZ1N0YXJ0U3dlZXA9IWlzU2V0dGluZ1N0YXJ0U3dlZXBcIj48L2xpYi1yYWRpby1idXR0b24+XG4gICAgICAgIDwvZGl2PlxuICAgICAgICBcbiAgICAgICAgPGRpdiBjbGFzcz1cInNwLXJvd1wiPlxuICAgICAgICAgICAgPGJ1dHRvbiBjbGFzcz1cImJ0biBidG4tcHJpbWFyeSByb3VuZGVkLXBpbGxcIiAoY2xpY2spPVwib25TYXZlU2VsZWN0aW9uKClcIj57eydzZWxlY3RUb29sLnNhdmVTZWxlY3Rpb24nIHwgdHJhbnNsYXRlfX08L2J1dHRvbj5cbiAgICAgICAgICAgIDxidXR0b24gY2xhc3M9XCJidG4gYnRuLW91dGxpbmUtcHJpbWFyeSByb3VuZGVkLXBpbGxcIiAoY2xpY2spPVwib25DYW5jZWwoKVwiPnt7J3NlbGVjdFRvb2wuY2FuY2VsU2VsZWN0aW9uJyB8IHRyYW5zbGF0ZX19PC9idXR0b24+XG4gICAgICAgIDwvZGl2PlxuICAgIDwvZGl2PlxuXG48L2Rpdj5cbiAgIFxuIl19
1
+ import { Component, EventEmitter, Input, Output } from '@angular/core';
2
+ import { getCoefficientsForImage, getMetaForImage, showScanPointsOnPlanInDiv } from '@smarterplan/ngx-smarterplan-core';
3
+ import panzoom from 'panzoom';
4
+ import { buttonIsInSelection, isInPolygon, rotate, setVisuallySelected, styleButton, SweepState } from '../../../../helper.service';
5
+ import * as i0 from "@angular/core";
6
+ import * as i1 from "@smarterplan/ngx-smarterplan-core";
7
+ import * as i2 from "../selection/selection.component";
8
+ import * as i3 from "../../../../radio-button/radio-button.component";
9
+ import * as i4 from "@ng-bootstrap/ng-bootstrap";
10
+ import * as i5 from "@angular/common";
11
+ import * as i6 from "@ngx-translate/core";
12
+ export class SweepPlanSelectionComponent {
13
+ constructor(zoneService, navigationService, planService) {
14
+ this.zoneService = zoneService;
15
+ this.navigationService = navigationService;
16
+ this.planService = planService;
17
+ this.chosenScansOnPlan = [];
18
+ this.navIDsZoneEdit = [];
19
+ // sweeps belonging to any audio zone
20
+ this.occupiedSweeps = [];
21
+ // sweeps unavailable (cannot be chosen)
22
+ this.unavailableSweeps = [];
23
+ // if choosing sweeps for audio zone
24
+ this.editingAudioZone = false;
25
+ /** all scan buttons Element */
26
+ this.buttonElements = [];
27
+ /** Scan buttons that are in the current selection */
28
+ this.buttonsInSelection = [];
29
+ this.sweepsSelected = new EventEmitter();
30
+ this.isSettingStartSweep = false;
31
+ }
32
+ ngOnInit() {
33
+ this.getPlans();
34
+ if (this.inputZone) {
35
+ this.setSweepsOfInputZone();
36
+ }
37
+ }
38
+ ngOnChanges() {
39
+ if (this.chosenPlan) {
40
+ this.setSweepsOfInputZone();
41
+ this.chosenScansOnPlan = [];
42
+ this.clearDivPlan();
43
+ this.addScanPoints();
44
+ }
45
+ }
46
+ setSweepsOfInputZone() {
47
+ this.navIDsZoneEdit = this.inputZone.sweepIDs;
48
+ }
49
+ async getPlans() {
50
+ this.plans = await this.planService.getSingedPlansForSpace(this.spaceID);
51
+ }
52
+ async onPlanClick(plan) {
53
+ this.chosenPlan = plan;
54
+ this.clearDivPlan();
55
+ this.addScanPoints();
56
+ }
57
+ async addScanPoints() {
58
+ this.divPlan = document.querySelector("#planDiv");
59
+ const zoneOfPlan = await this.zoneService.getZone(this.chosenPlan.zoneID);
60
+ const navigations = await this.navigationService.getNavigationsForZone(zoneOfPlan);
61
+ if (this.newZoneData)
62
+ await this.setScanByDraw(navigations);
63
+ this.buttonElements = await showScanPointsOnPlanInDiv(this.chosenPlan, this.divPlan, navigations);
64
+ for (const element of this.buttonElements) {
65
+ if (this.unavailableSweeps && this.unavailableSweeps.includes(element.id)) {
66
+ styleButton(element, SweepState.DISABLED);
67
+ }
68
+ else {
69
+ if ((this.navIDsZoneEdit.length > 0 &&
70
+ this.navIDsZoneEdit.includes(element.id))
71
+ || this.chosenScansOnPlan.includes(element.id)) {
72
+ styleButton(element, SweepState.ADDED);
73
+ if (!this.chosenScansOnPlan.includes(element.id)) {
74
+ this.chosenScansOnPlan.push(element.id);
75
+ }
76
+ }
77
+ else if (this.occupiedSweeps && this.occupiedSweeps.includes(element.id)) {
78
+ styleButton(element, SweepState.OCCUPIED);
79
+ }
80
+ else {
81
+ styleButton(element, SweepState.REMOVED);
82
+ }
83
+ //start point should be last condition
84
+ if (this.inputZone && this.inputZone.startSweepID === element.id) {
85
+ console.log("setting start point");
86
+ styleButton(element, SweepState.STARTPOINT);
87
+ }
88
+ element.addEventListener("click", (event) => this.onButtonScanClicked(event.target));
89
+ }
90
+ }
91
+ this.panZoom = panzoom(this.divPlan, {
92
+ bounds: true,
93
+ boundsPadding: 0,
94
+ maxZoom: 3.5,
95
+ beforeMouseDown(e) {
96
+ return (e.button === 2); /** Ignore event for right click (use for selecting) */
97
+ },
98
+ });
99
+ }
100
+ /** Function if we are coming for svg editor workflow */
101
+ setScanByDraw(navigations) {
102
+ return new Promise(async (resolve) => {
103
+ const rect = {
104
+ width: this.newZoneData.width,
105
+ height: this.newZoneData.height,
106
+ };
107
+ const img = await getMetaForImage(this.chosenPlan.filepath);
108
+ const { coeffX, coeffY } = getCoefficientsForImage(img, rect);
109
+ const draw = this.newZoneData.elements;
110
+ draw.map(async (element) => {
111
+ switch (element.nodeName) {
112
+ case "rect":
113
+ await this.setScanInRect(img, coeffX, coeffY, element, navigations);
114
+ break;
115
+ case "ellipse":
116
+ await this.setScanInCircle(img, coeffX, coeffY, element, navigations);
117
+ break;
118
+ case "path":
119
+ await this.setScanInPolygon(img, coeffX, coeffY, element, navigations);
120
+ break;
121
+ default:
122
+ break;
123
+ }
124
+ });
125
+ resolve();
126
+ });
127
+ }
128
+ async setScanInRect(img, coeffX, coeffY, element, navigations) {
129
+ const calibrage = JSON.parse(this.chosenPlan.calibration);
130
+ navigations.map((navigation) => {
131
+ const positionsOnPlan = navigation.positionOnPlan.map((entry) => JSON.parse(entry));
132
+ const positionOnPlan = positionsOnPlan.find((data) => data.planID === this.chosenPlan.id);
133
+ if (positionOnPlan) {
134
+ const realWidth = img.width / coeffX;
135
+ const realHeight = img.height / coeffY;
136
+ const navY = (positionOnPlan.y * realHeight) / calibrage.imgHeight;
137
+ const navX = (positionOnPlan.x * realWidth) / calibrage.imgWidth;
138
+ if (navX > element.x &&
139
+ navX < element.x + element.width &&
140
+ navY > element.y &&
141
+ navY < element.y + element.height &&
142
+ !this.navIDsZoneEdit.includes(navigation.id)) {
143
+ this.navIDsZoneEdit.push(navigation.id);
144
+ }
145
+ }
146
+ // old calibration:
147
+ // const position = JSON.parse(navigation.position);
148
+ // let navX = (calibrage.offsetX + position.x * calibrage.x) / coeffX;
149
+ // let navY = (calibrage.offsetY + position.z * calibrage.y) / coeffY;
150
+ // if (element.angle) {
151
+ // const rotatePos = rotate(
152
+ // { x: navX, y: navY },
153
+ // { x: element.cx, y: element.cy },
154
+ // element.angle,
155
+ // );
156
+ // navX = rotatePos.x;
157
+ // navY = rotatePos.y;
158
+ // }
159
+ /**
160
+ * TODO calculer la rotation du rectangle
161
+ */
162
+ // if (
163
+ // navX > element.x &&
164
+ // navX < element.x + element.width &&
165
+ // navY > element.y &&
166
+ // navY < element.y + element.height &&
167
+ // !this.navIDsZoneEdit.includes(navigation.id)
168
+ // ) {
169
+ // this.navIDsZoneEdit.push(navigation.id);
170
+ // }
171
+ });
172
+ } // EO
173
+ async setScanInCircle(img, coeffX, coeffY, element, navigations) {
174
+ const calibrage = JSON.parse(this.chosenPlan.calibration);
175
+ navigations.map(navigation => {
176
+ const positionsOnPlan = navigation.positionOnPlan.map((entry) => JSON.parse(entry));
177
+ const positionOnPlan = positionsOnPlan.find((data) => data.planID === this.chosenPlan.id);
178
+ if (positionOnPlan) {
179
+ const realWidth = img.width / coeffX;
180
+ const realHeight = img.height / coeffY;
181
+ let navY = (positionOnPlan.y * realHeight) / calibrage.imgHeight;
182
+ let navX = (positionOnPlan.x * realWidth) / calibrage.imgWidth;
183
+ if (element.angle) {
184
+ const rotatePos = rotate({ x: navX, y: navY }, { x: element.cx, y: element.cy }, element.angle);
185
+ navX = rotatePos.x;
186
+ navY = rotatePos.y;
187
+ }
188
+ const valueX = Math.pow(navX - element.cx, 2) / Math.pow(element.rx, 2);
189
+ const valueY = Math.pow(navY - element.cy, 2) / Math.pow(element.ry, 2);
190
+ const result = valueX + valueY;
191
+ if (result <= 1 && !this.navIDsZoneEdit.includes(navigation.id)) {
192
+ this.navIDsZoneEdit.push(navigation.id);
193
+ }
194
+ }
195
+ // old calibration
196
+ // const position = JSON.parse(navigation.position);
197
+ // let navX = (calibrage.offsetX + position.x * calibrage.x) / coeffX;
198
+ // let navY = (calibrage.offsetY + position.z * calibrage.y) / coeffY;
199
+ // if (element.angle) {
200
+ // const rotatePos = rotate(
201
+ // { x: navX, y: navY },
202
+ // { x: element.cx, y: element.cy },
203
+ // element.angle,
204
+ // );
205
+ // navX = rotatePos.x;
206
+ // navY = rotatePos.y;
207
+ // }
208
+ // const valueX =
209
+ // Math.pow(navX - element.cx, 2) / Math.pow(element.rx, 2);
210
+ // const valueY =
211
+ // Math.pow(navY - element.cy, 2) / Math.pow(element.ry, 2);
212
+ // const result = valueX + valueY;
213
+ // if (result <= 1 && !this.navIDsZoneEdit.includes(navigation.id)) {
214
+ // this.navIDsZoneEdit.push(navigation.id);
215
+ // }
216
+ });
217
+ } // EO
218
+ async setScanInPolygon(img, coeffX, coeffY, element, navigations) {
219
+ const calibrage = JSON.parse(this.chosenPlan.calibration);
220
+ navigations.map(async (navigation) => {
221
+ const positionsOnPlan = navigation.positionOnPlan.map((entry) => JSON.parse(entry));
222
+ const positionOnPlan = positionsOnPlan.find((data) => data.planID === this.chosenPlan.id);
223
+ if (positionOnPlan) {
224
+ const realWidth = img.width / coeffX;
225
+ const realHeight = img.height / coeffY;
226
+ let navY = (positionOnPlan.y * realHeight) / calibrage.imgHeight;
227
+ let navX = (positionOnPlan.x * realWidth) / calibrage.imgWidth;
228
+ const p = {
229
+ x: navX,
230
+ y: navY,
231
+ };
232
+ if (isInPolygon(p, element.segList) &&
233
+ !this.navIDsZoneEdit.includes(navigation.id)) {
234
+ this.navIDsZoneEdit.push(navigation.id);
235
+ }
236
+ }
237
+ // old calibration
238
+ // const position = JSON.parse(navigation.position);
239
+ // const p = {
240
+ // x: (calibrage.offsetX + position.x * calibrage.x) / coeffX,
241
+ // y: (calibrage.offsetY + position.z * calibrage.y) / coeffY,
242
+ // };
243
+ // if (element.angle) {
244
+ // p = this.rotate(
245
+ // p,
246
+ // { x: element.cx, y: element.cy },
247
+ // element.angle,
248
+ // );
249
+ // }
250
+ // if (
251
+ // isInPolygon(p, element.segList) &&
252
+ // !this.navIDsZoneEdit.includes(navigation.id)
253
+ // ) {
254
+ // this.navIDsZoneEdit.push(navigation.id);
255
+ // }
256
+ });
257
+ }
258
+ clearDivPlan() {
259
+ if (this.divPlan)
260
+ this.divPlan.innerHTML = "";
261
+ }
262
+ /**
263
+ * Trigger each by the selectionComponent when selection change
264
+ * Update the current selected scan buttons
265
+ * @param selection new selection
266
+ */
267
+ onSelectionChanged(selection) {
268
+ const unselectedButtons = [];
269
+ const newSelectedButtons = [];
270
+ /** For each button, decide whether will be add to selected list or unselected list */
271
+ for (const button of this.buttonElements) {
272
+ const isSelected = buttonIsInSelection(button, selection);
273
+ if (this.buttonsInSelection.includes(button)) {
274
+ /** If the button is already in the selected list, we check if it should be unselect */
275
+ if (!isSelected) {
276
+ unselectedButtons.push(button);
277
+ }
278
+ }
279
+ else if (isSelected) {
280
+ newSelectedButtons.push(button);
281
+ }
282
+ }
283
+ /** Visually Update unselected list */
284
+ for (const button of unselectedButtons) {
285
+ setVisuallySelected(button, false);
286
+ }
287
+ /** Visually Update selected list */
288
+ for (const button of newSelectedButtons) {
289
+ setVisuallySelected(button, true);
290
+ }
291
+ /** Remove unselected list */
292
+ this.buttonsInSelection = this.buttonsInSelection.filter((button) => {
293
+ return !unselectedButtons.includes(button);
294
+ });
295
+ /** Add new selected buttons */
296
+ this.buttonsInSelection = [
297
+ ...this.buttonsInSelection,
298
+ ...newSelectedButtons,
299
+ ];
300
+ }
301
+ /**
302
+ * Trigger when the user click to add the selected scans
303
+ */
304
+ onSelectionAdd() {
305
+ for (const button of this.buttonsInSelection) {
306
+ if (!this.chosenScansOnPlan.includes(button.id)) {
307
+ this.onButtonScanClicked(button);
308
+ }
309
+ }
310
+ this.onSelectionChanged({ top: 0, left: 0, width: 0, height: 0 });
311
+ }
312
+ /**
313
+ * Trigger when the user click to remove the selected scans
314
+ */
315
+ onSelectionRemove() {
316
+ for (const button of this.buttonsInSelection) {
317
+ if (this.chosenScansOnPlan.includes(button.id)) {
318
+ this.onButtonScanClicked(button);
319
+ }
320
+ }
321
+ this.onSelectionChanged({ top: 0, left: 0, width: 0, height: 0 });
322
+ }
323
+ /**
324
+ * Trigger when the user click to select all scans
325
+ */
326
+ onSelectAll() {
327
+ this.buttonsInSelection = [...this.buttonElements];
328
+ for (const button of this.buttonsInSelection) {
329
+ setVisuallySelected(button, true);
330
+ }
331
+ }
332
+ /**
333
+ * Trigger when the user change the size of the scan points
334
+ * @param event
335
+ */
336
+ onChangeScanSize(event) {
337
+ const factor = event.target.value;
338
+ for (const button of this.buttonElements) {
339
+ button.style.transform = `scale(${factor})`;
340
+ }
341
+ }
342
+ /**
343
+ * When a button representing a scan is clicked
344
+ * @param button
345
+ */
346
+ onButtonScanClicked(button) {
347
+ if (this.isSettingStartSweep) {
348
+ if (this.startSweepID === button.id) {
349
+ // we deselect the starting point
350
+ button.style.backgroundImage = `url("https://api.iconify.design/mdi:adjust.svg?color=green&height=17&width=17")`;
351
+ this.startSweepID = null;
352
+ return;
353
+ }
354
+ button.style.backgroundImage = `url('https://api.iconify.design/ic/baseline-flag-circle.svg?color=white&width=17&height=17')`;
355
+ if (!this.chosenScansOnPlan.includes(button.id)) {
356
+ this.chosenScansOnPlan.push(button.id);
357
+ }
358
+ if (this.startSweepID) {
359
+ // we are changing start sweep
360
+ const btnChanged = this.buttonElements.find((btn) => btn.id === this.startSweepID);
361
+ btnChanged.style.backgroundImage = `url("https://api.iconify.design/mdi:adjust.svg?color=green&height=17&width=17")`;
362
+ }
363
+ this.startSweepID = button.id;
364
+ return;
365
+ }
366
+ if (!this.chosenScansOnPlan.includes(button.id)) {
367
+ // add to selection
368
+ button.style.backgroundImage = `url("https://api.iconify.design/mdi:adjust.svg?color=green&height=17&width=17")`;
369
+ this.chosenScansOnPlan.push(button.id);
370
+ }
371
+ else {
372
+ // remove from selection
373
+ if (this.occupiedSweeps.includes(button.id) && !this.navIDsZoneEdit.includes(button.id)) {
374
+ // the sweep belongs to another zone => set orange
375
+ button.style.backgroundImage = `url("https://api.iconify.design/mdi:adjust.svg?color=orange&height=17&width=17")`;
376
+ }
377
+ else {
378
+ button.style.backgroundImage = `url("https://api.iconify.design/mdi:close-circle-outline.svg?color=red&height=17&width=17")`;
379
+ }
380
+ const index = this.chosenScansOnPlan.indexOf(button.id);
381
+ this.chosenScansOnPlan.splice(index, 1);
382
+ }
383
+ }
384
+ onSaveSelection() {
385
+ this.sweepsSelected.emit({ "sweeps": this.chosenScansOnPlan, "startSweepID": this.startSweepID });
386
+ }
387
+ onCancel() {
388
+ this.sweepsSelected.emit(null);
389
+ }
390
+ }
391
+ SweepPlanSelectionComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.2.7", ngImport: i0, type: SweepPlanSelectionComponent, deps: [{ token: i1.ZoneService }, { token: i1.NavigationService }, { token: i1.PlanService }], target: i0.ɵɵFactoryTarget.Component });
392
+ SweepPlanSelectionComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.2.7", type: SweepPlanSelectionComponent, selector: "lib-sweep-plan-selection", inputs: { spaceID: "spaceID", chosenScansOnPlan: "chosenScansOnPlan", newZoneData: "newZoneData", occupiedSweeps: "occupiedSweeps", unavailableSweeps: "unavailableSweeps", editingAudioZone: "editingAudioZone", inputZone: "inputZone" }, outputs: { sweepsSelected: "sweepsSelected" }, usesOnChanges: true, ngImport: i0, template: "<div ngbDropdown class=\"sp-row d-inline-block\">\r\n <div class=\"col-sm-3\" *ngIf=\"plans\">\r\n <button type=\"button\" class=\"btn btn-label-file rounded-pill\" id=\"dropdownBasic1\"\r\n ngbDropdownToggle>{{chosenPlan ?\r\n chosenPlan.name : ('Choose Plan' | translate) }}</button>\r\n <div ngbDropdownMenu aria-labelledby=\"dropdownBasic1\">\r\n <button type=\"button\" ngbDropdownItem *ngFor=\"let plan of plans\" (click)=\"onPlanClick(plan)\"\r\n [disabled]=\"!plan.calibration\">{{ plan.name }}\r\n </button>\r\n </div>\r\n </div>\r\n</div>\r\n<div class=\"sp-row\">\r\n <lib-selection class=\"col-md-8\" (onSelectionChanged)=\"onSelectionChanged($event)\">\r\n <div class=\"selectZone\" oncontextmenu=\"return false;\">\r\n <div class=\"sp-row\">\r\n <div style=\"overflow: hidden;width:100%;\">\r\n <div style=\"height: 400px; width: 100%;\" id=\"planDiv\">\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </lib-selection>\r\n \r\n <div class=\"col-md-4 scanTool\" *ngIf=\"buttonElements.length > 0\">\r\n <div class=\"sp-row d-inline-block\">\r\n <h2>{{'selectTool.title' | translate}}</h2>\r\n <div class=\"protip\">{{'selectTool.tip' | translate}}.</div>\r\n </div>\r\n \r\n <div class=\"sp-row\">\r\n <div class=\"col-3\" style=\"padding:0px\">\r\n <label class=\"tool-label\" for=\"scanSize\">{{'selectTool.size' | translate}}</label>\r\n </div>\r\n <div class=\"col-9\">\r\n <input type=\"range\" class=\"form-range\" min=\"0.001\" max=\"5\" step=\"0.01\" value=\"1\"\r\n id=\"scanSize\" (input)=\"onChangeScanSize($event)\">\r\n </div>\r\n </div>\r\n \r\n <div class=\"sp-row\">\r\n <button class=\"btn btn-primary rounded-pill\" (click)=\"onSelectAll()\">{{'selectTool.selectAll' | translate}}</button>\r\n </div>\r\n \r\n <div *ngIf=\"buttonsInSelection.length > 0\" class=\"edit-selected\">\r\n <span class=\"tool-label\">{{'selectTool.edit' | translate}} : </span>\r\n <div class=\"sp-row\">\r\n <button class=\"btn rounded-pill btn-primary ms-3 me-2\" (click)=\"onSelectionAdd()\">{{'selectTool.add' | translate}}</button>\r\n <button class=\"btn btn-primary rounded-pill\" (click)=\"onSelectionRemove()\">{{'selectTool.undo' | translate}}</button>\r\n </div>\r\n </div>\r\n\r\n <div class=\"sp-row\">\r\n {{ chosenScansOnPlan.length }} {{'scan points chosen' | translate}} \r\n </div>\r\n <div *ngIf=\"!editingAudioZone\" class=\"sp-row\">\r\n <lib-radio-button label=\"{{ 'selectTool.chooseStartPoint' | translate }}\" (isCheckedEvent)=\"isSettingStartSweep=!isSettingStartSweep\"></lib-radio-button>\r\n </div>\r\n \r\n <div class=\"sp-row\">\r\n <button class=\"btn btn-primary rounded-pill\" (click)=\"onSaveSelection()\">{{'selectTool.saveSelection' | translate}}</button>\r\n <button class=\"btn btn-outline-primary rounded-pill\" (click)=\"onCancel()\">{{'selectTool.cancelSelection' | translate}}</button>\r\n </div>\r\n </div>\r\n\r\n</div>\r\n \r\n", styles: [".sp-row{display:flex;margin-bottom:1rem}.selectZone{background-color:gray;border-radius:1rem;overflow:hidden}.scanTool{margin:0px 1rem}.protip{color:gray;padding:0}.tool-label{font-size:1rem}\n"], components: [{ type: i2.SelectionComponent, selector: "lib-selection", outputs: ["onSelectionChanged"] }, { type: i3.RadioButtonComponent, selector: "lib-radio-button", inputs: ["label"], outputs: ["isCheckedEvent"] }], directives: [{ type: i4.NgbDropdown, selector: "[ngbDropdown]", inputs: ["autoClose", "dropdownClass", "open", "placement", "container", "display"], outputs: ["openChange"], exportAs: ["ngbDropdown"] }, { type: i5.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i4.NgbDropdownToggle, selector: "[ngbDropdownToggle]" }, { type: i4.NgbDropdownMenu, selector: "[ngbDropdownMenu]" }, { type: i5.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i4.NgbDropdownItem, selector: "[ngbDropdownItem]", inputs: ["disabled"] }], pipes: { "translate": i6.TranslatePipe } });
393
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.2.7", ngImport: i0, type: SweepPlanSelectionComponent, decorators: [{
394
+ type: Component,
395
+ args: [{ selector: 'lib-sweep-plan-selection', template: "<div ngbDropdown class=\"sp-row d-inline-block\">\r\n <div class=\"col-sm-3\" *ngIf=\"plans\">\r\n <button type=\"button\" class=\"btn btn-label-file rounded-pill\" id=\"dropdownBasic1\"\r\n ngbDropdownToggle>{{chosenPlan ?\r\n chosenPlan.name : ('Choose Plan' | translate) }}</button>\r\n <div ngbDropdownMenu aria-labelledby=\"dropdownBasic1\">\r\n <button type=\"button\" ngbDropdownItem *ngFor=\"let plan of plans\" (click)=\"onPlanClick(plan)\"\r\n [disabled]=\"!plan.calibration\">{{ plan.name }}\r\n </button>\r\n </div>\r\n </div>\r\n</div>\r\n<div class=\"sp-row\">\r\n <lib-selection class=\"col-md-8\" (onSelectionChanged)=\"onSelectionChanged($event)\">\r\n <div class=\"selectZone\" oncontextmenu=\"return false;\">\r\n <div class=\"sp-row\">\r\n <div style=\"overflow: hidden;width:100%;\">\r\n <div style=\"height: 400px; width: 100%;\" id=\"planDiv\">\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </lib-selection>\r\n \r\n <div class=\"col-md-4 scanTool\" *ngIf=\"buttonElements.length > 0\">\r\n <div class=\"sp-row d-inline-block\">\r\n <h2>{{'selectTool.title' | translate}}</h2>\r\n <div class=\"protip\">{{'selectTool.tip' | translate}}.</div>\r\n </div>\r\n \r\n <div class=\"sp-row\">\r\n <div class=\"col-3\" style=\"padding:0px\">\r\n <label class=\"tool-label\" for=\"scanSize\">{{'selectTool.size' | translate}}</label>\r\n </div>\r\n <div class=\"col-9\">\r\n <input type=\"range\" class=\"form-range\" min=\"0.001\" max=\"5\" step=\"0.01\" value=\"1\"\r\n id=\"scanSize\" (input)=\"onChangeScanSize($event)\">\r\n </div>\r\n </div>\r\n \r\n <div class=\"sp-row\">\r\n <button class=\"btn btn-primary rounded-pill\" (click)=\"onSelectAll()\">{{'selectTool.selectAll' | translate}}</button>\r\n </div>\r\n \r\n <div *ngIf=\"buttonsInSelection.length > 0\" class=\"edit-selected\">\r\n <span class=\"tool-label\">{{'selectTool.edit' | translate}} : </span>\r\n <div class=\"sp-row\">\r\n <button class=\"btn rounded-pill btn-primary ms-3 me-2\" (click)=\"onSelectionAdd()\">{{'selectTool.add' | translate}}</button>\r\n <button class=\"btn btn-primary rounded-pill\" (click)=\"onSelectionRemove()\">{{'selectTool.undo' | translate}}</button>\r\n </div>\r\n </div>\r\n\r\n <div class=\"sp-row\">\r\n {{ chosenScansOnPlan.length }} {{'scan points chosen' | translate}} \r\n </div>\r\n <div *ngIf=\"!editingAudioZone\" class=\"sp-row\">\r\n <lib-radio-button label=\"{{ 'selectTool.chooseStartPoint' | translate }}\" (isCheckedEvent)=\"isSettingStartSweep=!isSettingStartSweep\"></lib-radio-button>\r\n </div>\r\n \r\n <div class=\"sp-row\">\r\n <button class=\"btn btn-primary rounded-pill\" (click)=\"onSaveSelection()\">{{'selectTool.saveSelection' | translate}}</button>\r\n <button class=\"btn btn-outline-primary rounded-pill\" (click)=\"onCancel()\">{{'selectTool.cancelSelection' | translate}}</button>\r\n </div>\r\n </div>\r\n\r\n</div>\r\n \r\n", styles: [".sp-row{display:flex;margin-bottom:1rem}.selectZone{background-color:gray;border-radius:1rem;overflow:hidden}.scanTool{margin:0px 1rem}.protip{color:gray;padding:0}.tool-label{font-size:1rem}\n"] }]
396
+ }], ctorParameters: function () { return [{ type: i1.ZoneService }, { type: i1.NavigationService }, { type: i1.PlanService }]; }, propDecorators: { spaceID: [{
397
+ type: Input
398
+ }], chosenScansOnPlan: [{
399
+ type: Input
400
+ }], newZoneData: [{
401
+ type: Input
402
+ }], occupiedSweeps: [{
403
+ type: Input
404
+ }], unavailableSweeps: [{
405
+ type: Input
406
+ }], editingAudioZone: [{
407
+ type: Input
408
+ }], inputZone: [{
409
+ type: Input
410
+ }], sweepsSelected: [{
411
+ type: Output
412
+ }] } });
413
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3dlZXAtcGxhbi1zZWxlY3Rpb24uY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvbmd4LXNtYXJ0ZXJwbGFuLWxvY2F0aW9ucy9zcmMvbGliL2NvbXBvbmVudHMvem9uZXMvYWRkLXpvbmUvc3dlZXAtcGxhbi1zZWxlY3Rpb24vc3dlZXAtcGxhbi1zZWxlY3Rpb24uY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvbmd4LXNtYXJ0ZXJwbGFuLWxvY2F0aW9ucy9zcmMvbGliL2NvbXBvbmVudHMvem9uZXMvYWRkLXpvbmUvc3dlZXAtcGxhbi1zZWxlY3Rpb24vc3dlZXAtcGxhbi1zZWxlY3Rpb24uY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFNBQVMsRUFBRSxZQUFZLEVBQUUsS0FBSyxFQUFVLE1BQU0sRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUMvRSxPQUFPLEVBQUUsdUJBQXVCLEVBQUUsZUFBZSxFQUE2Qyx5QkFBeUIsRUFBNEIsTUFBTSxtQ0FBbUMsQ0FBQztBQUM3TCxPQUFPLE9BQW9CLE1BQU0sU0FBUyxDQUFDO0FBQzNDLE9BQU8sRUFBRSxtQkFBbUIsRUFBRSxXQUFXLEVBQWEsTUFBTSxFQUFFLG1CQUFtQixFQUFFLFdBQVcsRUFBRSxVQUFVLEVBQUUsTUFBTSw0QkFBNEIsQ0FBQzs7Ozs7Ozs7QUFPL0ksTUFBTSxPQUFPLDJCQUEyQjtJQTRDcEMsWUFDWSxXQUF3QixFQUN4QixpQkFBb0MsRUFDcEMsV0FBd0I7UUFGeEIsZ0JBQVcsR0FBWCxXQUFXLENBQWE7UUFDeEIsc0JBQWlCLEdBQWpCLGlCQUFpQixDQUFtQjtRQUNwQyxnQkFBVyxHQUFYLFdBQVcsQ0FBYTtRQXpDM0Isc0JBQWlCLEdBQWEsRUFBRSxDQUFDO1FBSzFDLG1CQUFjLEdBQWEsRUFBRSxDQUFDO1FBRTlCLHFDQUFxQztRQUM1QixtQkFBYyxHQUFhLEVBQUUsQ0FBQztRQUV2Qyx3Q0FBd0M7UUFDL0Isc0JBQWlCLEdBQWEsRUFBRSxDQUFDO1FBRTFDLG9DQUFvQztRQUMzQixxQkFBZ0IsR0FBWSxLQUFLLENBQUM7UUFZM0MsK0JBQStCO1FBQy9CLG1CQUFjLEdBQXdCLEVBQUUsQ0FBQztRQUV6QyxxREFBcUQ7UUFDckQsdUJBQWtCLEdBQXdCLEVBQUUsQ0FBQztRQUVuQyxtQkFBYyxHQUFHLElBQUksWUFBWSxFQUErQyxDQUFDO1FBRTNGLHdCQUFtQixHQUFHLEtBQUssQ0FBQztJQVF4QixDQUFDO0lBRUwsUUFBUTtRQUNKLElBQUksQ0FBQyxRQUFRLEVBQUUsQ0FBQztRQUNoQixJQUFJLElBQUksQ0FBQyxTQUFTLEVBQUU7WUFDaEIsSUFBSSxDQUFDLG9CQUFvQixFQUFFLENBQUM7U0FDL0I7SUFDTCxDQUFDO0lBRUQsV0FBVztRQUNQLElBQUksSUFBSSxDQUFDLFVBQVUsRUFBRTtZQUNqQixJQUFJLENBQUMsb0JBQW9CLEVBQUUsQ0FBQztZQUM1QixJQUFJLENBQUMsaUJBQWlCLEdBQUcsRUFBRSxDQUFDO1lBQzVCLElBQUksQ0FBQyxZQUFZLEVBQUUsQ0FBQztZQUNwQixJQUFJLENBQUMsYUFBYSxFQUFFLENBQUM7U0FDeEI7SUFDTCxDQUFDO0lBRUQsb0JBQW9CO1FBQ2hCLElBQUksQ0FBQyxjQUFjLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQyxRQUFRLENBQUM7SUFDbEQsQ0FBQztJQUVELEtBQUssQ0FBQyxRQUFRO1FBQ1YsSUFBSSxDQUFDLEtBQUssR0FBRyxNQUFNLElBQUksQ0FBQyxXQUFXLENBQUMsc0JBQXNCLENBQ3RELElBQUksQ0FBQyxPQUFPLENBQ2YsQ0FBQztJQUNOLENBQUM7SUFFRCxLQUFLLENBQUMsV0FBVyxDQUFDLElBQVU7UUFDeEIsSUFBSSxDQUFDLFVBQVUsR0FBRyxJQUFJLENBQUM7UUFDdkIsSUFBSSxDQUFDLFlBQVksRUFBRSxDQUFDO1FBQ3BCLElBQUksQ0FBQyxhQUFhLEVBQUUsQ0FBQztJQUN6QixDQUFDO0lBRUQsS0FBSyxDQUFDLGFBQWE7UUFDZixJQUFJLENBQUMsT0FBTyxHQUFHLFFBQVEsQ0FBQyxhQUFhLENBQUMsVUFBVSxDQUFnQixDQUFDO1FBQ2pFLE1BQU0sVUFBVSxHQUFHLE1BQU0sSUFBSSxDQUFDLFdBQVcsQ0FBQyxPQUFPLENBQzdDLElBQUksQ0FBQyxVQUFVLENBQUMsTUFBTSxDQUN6QixDQUFDO1FBQ0YsTUFBTSxXQUFXLEdBQUcsTUFBTSxJQUFJLENBQUMsaUJBQWlCLENBQUMscUJBQXFCLENBQ2xFLFVBQVUsQ0FDYixDQUFDO1FBQ0YsSUFBSSxJQUFJLENBQUMsV0FBVztZQUFFLE1BQU0sSUFBSSxDQUFDLGFBQWEsQ0FBQyxXQUFXLENBQUMsQ0FBQztRQUM1RCxJQUFJLENBQUMsY0FBYyxHQUFHLE1BQU0seUJBQXlCLENBQ2pELElBQUksQ0FBQyxVQUFVLEVBQ2YsSUFBSSxDQUFDLE9BQU8sRUFDWixXQUFXLENBQ2QsQ0FBQztRQUNGLEtBQUssTUFBTSxPQUFPLElBQUksSUFBSSxDQUFDLGNBQWMsRUFBRTtZQUN2QyxJQUFJLElBQUksQ0FBQyxpQkFBaUIsSUFBSSxJQUFJLENBQUMsaUJBQWlCLENBQUMsUUFBUSxDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUMsRUFBRTtnQkFDdkUsV0FBVyxDQUFDLE9BQU8sRUFBRSxVQUFVLENBQUMsUUFBUSxDQUFDLENBQUM7YUFDN0M7aUJBQU07Z0JBQ0gsSUFDSSxDQUFDLElBQUksQ0FBQyxjQUFjLENBQUMsTUFBTSxHQUFHLENBQUM7b0JBQzNCLElBQUksQ0FBQyxjQUFjLENBQUMsUUFBUSxDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUMsQ0FBQzt1QkFDMUMsSUFBSSxDQUFDLGlCQUFpQixDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDLEVBQUU7b0JBQ2hELFdBQVcsQ0FBQyxPQUFPLEVBQUUsVUFBVSxDQUFDLEtBQUssQ0FBQyxDQUFDO29CQUN2QyxJQUFJLENBQUMsSUFBSSxDQUFDLGlCQUFpQixDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDLEVBQUU7d0JBQzlDLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQyxDQUFDO3FCQUMzQztpQkFDSjtxQkFBTSxJQUFJLElBQUksQ0FBQyxjQUFjLElBQUksSUFBSSxDQUFDLGNBQWMsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQyxFQUFFO29CQUN4RSxXQUFXLENBQUMsT0FBTyxFQUFFLFVBQVUsQ0FBQyxRQUFRLENBQUMsQ0FBQztpQkFDN0M7cUJBQU07b0JBQ0gsV0FBVyxDQUFDLE9BQU8sRUFBRSxVQUFVLENBQUMsT0FBTyxDQUFDLENBQUM7aUJBQzVDO2dCQUNELHVDQUF1QztnQkFDdkMsSUFBSSxJQUFJLENBQUMsU0FBUyxJQUFJLElBQUksQ0FBQyxTQUFTLENBQUMsWUFBWSxLQUFLLE9BQU8sQ0FBQyxFQUFFLEVBQUU7b0JBQzlELE9BQU8sQ0FBQyxHQUFHLENBQUMscUJBQXFCLENBQUMsQ0FBQztvQkFDbkMsV0FBVyxDQUFDLE9BQU8sRUFBRSxVQUFVLENBQUMsVUFBVSxDQUFDLENBQUM7aUJBQy9DO2dCQUNELE9BQU8sQ0FBQyxnQkFBZ0IsQ0FBQyxPQUFPLEVBQUUsQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUN4QyxJQUFJLENBQUMsbUJBQW1CLENBQUMsS0FBSyxDQUFDLE1BQXFCLENBQUMsQ0FDeEQsQ0FBQzthQUNMO1NBQ0o7UUFDRCxJQUFJLENBQUMsT0FBTyxHQUFHLE9BQU8sQ0FBQyxJQUFJLENBQUMsT0FBTyxFQUFFO1lBQ2pDLE1BQU0sRUFBRSxJQUFJO1lBQ1osYUFBYSxFQUFFLENBQUM7WUFDaEIsT0FBTyxFQUFFLEdBQUc7WUFDWixlQUFlLENBQUMsQ0FBYTtnQkFDekIsT0FBTyxDQUNILENBQUMsQ0FBQyxNQUFNLEtBQUssQ0FBQyxDQUNqQixDQUFDLENBQUMsdURBQXVEO1lBQzlELENBQUM7U0FDSixDQUFDLENBQUM7SUFDUCxDQUFDO0lBRUQsd0RBQXdEO0lBQ3hELGFBQWEsQ0FBQyxXQUFrQjtRQUM1QixPQUFPLElBQUksT0FBTyxDQUFDLEtBQUssRUFBRSxPQUFPLEVBQUUsRUFBRTtZQUNqQyxNQUFNLElBQUksR0FBRztnQkFDVCxLQUFLLEVBQUUsSUFBSSxDQUFDLFdBQVcsQ0FBQyxLQUFLO2dCQUM3QixNQUFNLEVBQUUsSUFBSSxDQUFDLFdBQVcsQ0FBQyxNQUFNO2FBQ2xDLENBQUM7WUFDRixNQUFNLEdBQUcsR0FBRyxNQUFNLGVBQWUsQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLFFBQVEsQ0FBQyxDQUFDO1lBQzVELE1BQU0sRUFBRSxNQUFNLEVBQUUsTUFBTSxFQUFFLEdBQUcsdUJBQXVCLENBQUMsR0FBRyxFQUFFLElBQUksQ0FBQyxDQUFDO1lBRTlELE1BQU0sSUFBSSxHQUFHLElBQUksQ0FBQyxXQUFXLENBQUMsUUFBUSxDQUFDO1lBRXZDLElBQUksQ0FBQyxHQUFHLENBQUMsS0FBSyxFQUFFLE9BQVksRUFBRSxFQUFFO2dCQUM1QixRQUFRLE9BQU8sQ0FBQyxRQUFRLEVBQUU7b0JBQ3RCLEtBQUssTUFBTTt3QkFDUCxNQUFNLElBQUksQ0FBQyxhQUFhLENBQ3BCLEdBQUcsRUFDSCxNQUFNLEVBQ04sTUFBTSxFQUNOLE9BQU8sRUFDUCxXQUFXLENBQ2QsQ0FBQzt3QkFDRixNQUFNO29CQUVWLEtBQUssU0FBUzt3QkFDVixNQUFNLElBQUksQ0FBQyxlQUFlLENBQ3RCLEdBQUcsRUFDSCxNQUFNLEVBQ04sTUFBTSxFQUNOLE9BQU8sRUFDUCxXQUFXLENBQ2QsQ0FBQzt3QkFDRixNQUFNO29CQUVWLEtBQUssTUFBTTt3QkFDUCxNQUFNLElBQUksQ0FBQyxnQkFBZ0IsQ0FDdkIsR0FBRyxFQUNILE1BQU0sRUFDTixNQUFNLEVBQ04sT0FBTyxFQUNQLFdBQVcsQ0FDZCxDQUFDO3dCQUNGLE1BQU07b0JBQ1Y7d0JBQ0ksTUFBTTtpQkFDYjtZQUNMLENBQUMsQ0FBQyxDQUFDO1lBRUgsT0FBTyxFQUFFLENBQUM7UUFDZCxDQUFDLENBQUMsQ0FBQztJQUNQLENBQUM7SUFFRCxLQUFLLENBQUMsYUFBYSxDQUFDLEdBQVEsRUFBRSxNQUFjLEVBQUUsTUFBYyxFQUN4RCxPQUF5RixFQUFFLFdBQWtCO1FBQzdHLE1BQU0sU0FBUyxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxXQUFXLENBQUMsQ0FBQztRQUMxRCxXQUFXLENBQUMsR0FBRyxDQUFDLENBQUMsVUFBVSxFQUFFLEVBQUU7WUFDM0IsTUFBTSxlQUFlLEdBQUcsVUFBVSxDQUFDLGNBQWMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUM1RCxJQUFJLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxDQUNwQixDQUFDO1lBQ0YsTUFBTSxjQUFjLEdBQUcsZUFBZSxDQUFDLElBQUksQ0FDdkMsQ0FBQyxJQUFJLEVBQUUsRUFBRSxDQUFDLElBQUksQ0FBQyxNQUFNLEtBQUssSUFBSSxDQUFDLFVBQVUsQ0FBQyxFQUFFLENBQy9DLENBQUM7WUFDRixJQUFJLGNBQWMsRUFBRTtnQkFDaEIsTUFBTSxTQUFTLEdBQUcsR0FBRyxDQUFDLEtBQUssR0FBRyxNQUFNLENBQUM7Z0JBQ3JDLE1BQU0sVUFBVSxHQUFHLEdBQUcsQ0FBQyxNQUFNLEdBQUcsTUFBTSxDQUFDO2dCQUN2QyxNQUFNLElBQUksR0FBRyxDQUFDLGNBQWMsQ0FBQyxDQUFDLEdBQUcsVUFBVSxDQUFDLEdBQUcsU0FBUyxDQUFDLFNBQVMsQ0FBQztnQkFDbkUsTUFBTSxJQUFJLEdBQUcsQ0FBQyxjQUFjLENBQUMsQ0FBQyxHQUFHLFNBQVMsQ0FBQyxHQUFHLFNBQVMsQ0FBQyxRQUFRLENBQUM7Z0JBQ2pFLElBQ0ksSUFBSSxHQUFHLE9BQU8sQ0FBQyxDQUFDO29CQUNoQixJQUFJLEdBQUcsT0FBTyxDQUFDLENBQUMsR0FBRyxPQUFPLENBQUMsS0FBSztvQkFDaEMsSUFBSSxHQUFHLE9BQU8sQ0FBQyxDQUFDO29CQUNoQixJQUFJLEdBQUcsT0FBTyxDQUFDLENBQUMsR0FBRyxPQUFPLENBQUMsTUFBTTtvQkFDakMsQ0FBQyxJQUFJLENBQUMsY0FBYyxDQUFDLFFBQVEsQ0FBQyxVQUFVLENBQUMsRUFBRSxDQUFDLEVBQzlDO29CQUNFLElBQUksQ0FBQyxjQUFjLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxFQUFFLENBQUMsQ0FBQztpQkFDM0M7YUFDSjtZQUVELG1CQUFtQjtZQUNuQixvREFBb0Q7WUFDcEQsc0VBQXNFO1lBQ3RFLHNFQUFzRTtZQUN0RSx1QkFBdUI7WUFDdkIsZ0NBQWdDO1lBQ2hDLGdDQUFnQztZQUNoQyw0Q0FBNEM7WUFDNUMseUJBQXlCO1lBQ3pCLFNBQVM7WUFDVCwwQkFBMEI7WUFDMUIsMEJBQTBCO1lBQzFCLElBQUk7WUFDSjs7ZUFFRztZQUNILE9BQU87WUFDUCwwQkFBMEI7WUFDMUIsMENBQTBDO1lBQzFDLDBCQUEwQjtZQUMxQiwyQ0FBMkM7WUFDM0MsbURBQW1EO1lBQ25ELE1BQU07WUFDTiwrQ0FBK0M7WUFDL0MsSUFBSTtRQUNSLENBQUMsQ0FBQyxDQUFDO0lBQ1AsQ0FBQyxDQUFDLEtBQUs7SUFFUCxLQUFLLENBQUMsZUFBZSxDQUFDLEdBQVEsRUFBRSxNQUFjLEVBQUUsTUFBYyxFQUMxRCxPQUF3RSxFQUFFLFdBQXlCO1FBQ25HLE1BQU0sU0FBUyxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxXQUFXLENBQUMsQ0FBQztRQUMxRCxXQUFXLENBQUMsR0FBRyxDQUFDLFVBQVUsQ0FBQyxFQUFFO1lBQ3pCLE1BQU0sZUFBZSxHQUFHLFVBQVUsQ0FBQyxjQUFjLENBQUMsR0FBRyxDQUFDLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FDNUQsSUFBSSxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsQ0FDcEIsQ0FBQztZQUNGLE1BQU0sY0FBYyxHQUFHLGVBQWUsQ0FBQyxJQUFJLENBQ3ZDLENBQUMsSUFBSSxFQUFFLEVBQUUsQ0FBQyxJQUFJLENBQUMsTUFBTSxLQUFLLElBQUksQ0FBQyxVQUFVLENBQUMsRUFBRSxDQUMvQyxDQUFDO1lBQ0YsSUFBSSxjQUFjLEVBQUU7Z0JBQ2hCLE1BQU0sU0FBUyxHQUFHLEdBQUcsQ0FBQyxLQUFLLEdBQUcsTUFBTSxDQUFDO2dCQUNyQyxNQUFNLFVBQVUsR0FBRyxHQUFHLENBQUMsTUFBTSxHQUFHLE1BQU0sQ0FBQztnQkFDdkMsSUFBSSxJQUFJLEdBQUcsQ0FBQyxjQUFjLENBQUMsQ0FBQyxHQUFHLFVBQVUsQ0FBQyxHQUFHLFNBQVMsQ0FBQyxTQUFTLENBQUM7Z0JBQ2pFLElBQUksSUFBSSxHQUFHLENBQUMsY0FBYyxDQUFDLENBQUMsR0FBRyxTQUFTLENBQUMsR0FBRyxTQUFTLENBQUMsUUFBUSxDQUFDO2dCQUMvRCxJQUFJLE9BQU8sQ0FBQyxLQUFLLEVBQUU7b0JBQ2YsTUFBTSxTQUFTLEdBQUcsTUFBTSxDQUNwQixFQUFFLENBQUMsRUFBRSxJQUFJLEVBQUUsQ0FBQyxFQUFFLElBQUksRUFBRSxFQUNwQixFQUFFLENBQUMsRUFBRSxPQUFPLENBQUMsRUFBRSxFQUFFLENBQUMsRUFBRSxPQUFPLENBQUMsRUFBRSxFQUFFLEVBQ2hDLE9BQU8sQ0FBQyxLQUFLLENBQ2hCLENBQUM7b0JBQ0YsSUFBSSxHQUFHLFNBQVMsQ0FBQyxDQUFDLENBQUM7b0JBQ25CLElBQUksR0FBRyxTQUFTLENBQUMsQ0FBQyxDQUFDO2lCQUN0QjtnQkFFRCxNQUFNLE1BQU0sR0FDUixJQUFJLENBQUMsR0FBRyxDQUFDLElBQUksR0FBRyxPQUFPLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsT0FBTyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQztnQkFDN0QsTUFBTSxNQUFNLEdBQ1IsSUFBSSxDQUFDLEdBQUcsQ0FBQyxJQUFJLEdBQUcsT0FBTyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLE9BQU8sQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUM7Z0JBQzdELE1BQU0sTUFBTSxHQUFHLE1BQU0sR0FBRyxNQUFNLENBQUM7Z0JBQy9CLElBQUksTUFBTSxJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxjQUFjLENBQUMsUUFBUSxDQUFDLFVBQVUsQ0FBQyxFQUFFLENBQUMsRUFBRTtvQkFDN0QsSUFBSSxDQUFDLGNBQWMsQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLEVBQUUsQ0FBQyxDQUFDO2lCQUMzQzthQUNKO1lBRUQsa0JBQWtCO1lBQ2xCLG9EQUFvRDtZQUNwRCxzRUFBc0U7WUFDdEUsc0VBQXNFO1lBQ3RFLHVCQUF1QjtZQUN2QixnQ0FBZ0M7WUFDaEMsZ0NBQWdDO1lBQ2hDLDRDQUE0QztZQUM1Qyx5QkFBeUI7WUFDekIsU0FBUztZQUNULDBCQUEwQjtZQUMxQiwwQkFBMEI7WUFDMUIsSUFBSTtZQUVKLGlCQUFpQjtZQUNqQixnRUFBZ0U7WUFDaEUsaUJBQWlCO1lBQ2pCLGdFQUFnRTtZQUNoRSxrQ0FBa0M7WUFDbEMscUVBQXFFO1lBQ3JFLCtDQUErQztZQUMvQyxJQUFJO1FBQ1IsQ0FBQyxDQUFDLENBQUM7SUFDUCxDQUFDLENBQUMsS0FBSztJQUVQLEtBQUssQ0FBQyxnQkFBZ0IsQ0FBQyxHQUFRLEVBQUUsTUFBYyxFQUFFLE1BQWMsRUFBRSxPQUEwQixFQUFFLFdBQWtCO1FBQzNHLE1BQU0sU0FBUyxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxXQUFXLENBQUMsQ0FBQztRQUMxRCxXQUFXLENBQUMsR0FBRyxDQUFDLEtBQUssRUFBRSxVQUFVLEVBQUUsRUFBRTtZQUVqQyxNQUFNLGVBQWUsR0FBRyxVQUFVLENBQUMsY0FBYyxDQUFDLEdBQUcsQ0FBQyxDQUFDLEtBQUssRUFBRSxFQUFFLENBQzVELElBQUksQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLENBQ3BCLENBQUM7WUFDRixNQUFNLGNBQWMsR0FBRyxlQUFlLENBQUMsSUFBSSxDQUN2QyxDQUFDLElBQUksRUFBRSxFQUFFLENBQUMsSUFBSSxDQUFDLE1BQU0sS0FBSyxJQUFJLENBQUMsVUFBVSxDQUFDLEVBQUUsQ0FDL0MsQ0FBQztZQUNGLElBQUksY0FBYyxFQUFFO2dCQUNoQixNQUFNLFNBQVMsR0FBRyxHQUFHLENBQUMsS0FBSyxHQUFHLE1BQU0sQ0FBQztnQkFDckMsTUFBTSxVQUFVLEdBQUcsR0FBRyxDQUFDLE1BQU0sR0FBRyxNQUFNLENBQUM7Z0JBQ3ZDLElBQUksSUFBSSxHQUFHLENBQUMsY0FBYyxDQUFDLENBQUMsR0FBRyxVQUFVLENBQUMsR0FBRyxTQUFTLENBQUMsU0FBUyxDQUFDO2dCQUNqRSxJQUFJLElBQUksR0FBRyxDQUFDLGNBQWMsQ0FBQyxDQUFDLEdBQUcsU0FBUyxDQUFDLEdBQUcsU0FBUyxDQUFDLFFBQVEsQ0FBQztnQkFFL0QsTUFBTSxDQUFDLEdBQUc7b0JBQ04sQ0FBQyxFQUFFLElBQUk7b0JBQ1AsQ0FBQyxFQUFFLElBQUk7aUJBQ1YsQ0FBQztnQkFDRixJQUNJLFdBQVcsQ0FBQyxDQUFDLEVBQUUsT0FBTyxDQUFDLE9BQU8sQ0FBQztvQkFDL0IsQ0FBQyxJQUFJLENBQUMsY0FBYyxDQUFDLFFBQVEsQ0FBQyxVQUFVLENBQUMsRUFBRSxDQUFDLEVBQzlDO29CQUNFLElBQUksQ0FBQyxjQUFjLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxFQUFFLENBQUMsQ0FBQztpQkFDM0M7YUFDSjtZQUVELGtCQUFrQjtZQUNsQixvREFBb0Q7WUFDcEQsY0FBYztZQUNkLGtFQUFrRTtZQUNsRSxrRUFBa0U7WUFDbEUsS0FBSztZQUNMLHVCQUF1QjtZQUN2Qix1QkFBdUI7WUFDdkIsYUFBYTtZQUNiLDRDQUE0QztZQUM1Qyx5QkFBeUI7WUFDekIsU0FBUztZQUNULElBQUk7WUFDSixPQUFPO1lBQ1AseUNBQXlDO1lBQ3pDLG1EQUFtRDtZQUNuRCxNQUFNO1lBQ04sK0NBQStDO1lBQy9DLElBQUk7UUFDUixDQUFDLENBQUMsQ0FBQztJQUNQLENBQUM7SUFFRCxZQUFZO1FBQ1IsSUFBSSxJQUFJLENBQUMsT0FBTztZQUFFLElBQUksQ0FBQyxPQUFPLENBQUMsU0FBUyxHQUFHLEVBQUUsQ0FBQztJQUNsRCxDQUFDO0lBR0Q7Ozs7T0FJRztJQUNILGtCQUFrQixDQUFDLFNBQW9CO1FBQ25DLE1BQU0saUJBQWlCLEdBQXdCLEVBQUUsQ0FBQztRQUNsRCxNQUFNLGtCQUFrQixHQUFHLEVBQUUsQ0FBQztRQUU5QixzRkFBc0Y7UUFDdEYsS0FBSyxNQUFNLE1BQU0sSUFBSSxJQUFJLENBQUMsY0FBYyxFQUFFO1lBQ3RDLE1BQU0sVUFBVSxHQUFHLG1CQUFtQixDQUFDLE1BQU0sRUFBRSxTQUFTLENBQUMsQ0FBQztZQUMxRCxJQUFJLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxRQUFRLENBQUMsTUFBTSxDQUFDLEVBQUU7Z0JBQzFDLHVGQUF1RjtnQkFDdkYsSUFBSSxDQUFDLFVBQVUsRUFBRTtvQkFDYixpQkFBaUIsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUM7aUJBQ2xDO2FBQ0o7aUJBQU0sSUFBSSxVQUFVLEVBQUU7Z0JBQ25CLGtCQUFrQixDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQzthQUNuQztTQUNKO1FBRUQsc0NBQXNDO1FBQ3RDLEtBQUssTUFBTSxNQUFNLElBQUksaUJBQWlCLEVBQUU7WUFDcEMsbUJBQW1CLENBQUMsTUFBTSxFQUFFLEtBQUssQ0FBQyxDQUFDO1NBQ3RDO1FBRUQsb0NBQW9DO1FBQ3BDLEtBQUssTUFBTSxNQUFNLElBQUksa0JBQWtCLEVBQUU7WUFDckMsbUJBQW1CLENBQUMsTUFBTSxFQUFFLElBQUksQ0FBQyxDQUFDO1NBQ3JDO1FBRUQsOEJBQThCO1FBQzlCLElBQUksQ0FBQyxrQkFBa0IsR0FBRyxJQUFJLENBQUMsa0JBQWtCLENBQUMsTUFBTSxDQUFDLENBQUMsTUFBTSxFQUFFLEVBQUU7WUFDaEUsT0FBTyxDQUFDLGlCQUFpQixDQUFDLFFBQVEsQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUMvQyxDQUFDLENBQUMsQ0FBQztRQUNILCtCQUErQjtRQUMvQixJQUFJLENBQUMsa0JBQWtCLEdBQUc7WUFDdEIsR0FBRyxJQUFJLENBQUMsa0JBQWtCO1lBQzFCLEdBQUcsa0JBQWtCO1NBQ3hCLENBQUM7SUFDTixDQUFDO0lBSUQ7O09BRUc7SUFDSCxjQUFjO1FBQ1YsS0FBSyxNQUFNLE1BQU0sSUFBSSxJQUFJLENBQUMsa0JBQWtCLEVBQUU7WUFDMUMsSUFBSSxDQUFDLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxRQUFRLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxFQUFFO2dCQUM3QyxJQUFJLENBQUMsbUJBQW1CLENBQUMsTUFBTSxDQUFDLENBQUM7YUFDcEM7U0FDSjtRQUVELElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxFQUFFLEdBQUcsRUFBRSxDQUFDLEVBQUUsSUFBSSxFQUFFLENBQUMsRUFBRSxLQUFLLEVBQUUsQ0FBQyxFQUFFLE1BQU0sRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDO0lBQ3RFLENBQUM7SUFFRDs7T0FFRztJQUNILGlCQUFpQjtRQUNiLEtBQUssTUFBTSxNQUFNLElBQUksSUFBSSxDQUFDLGtCQUFrQixFQUFFO1lBQzFDLElBQUksSUFBSSxDQUFDLGlCQUFpQixDQUFDLFFBQVEsQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDLEVBQUU7Z0JBQzVDLElBQUksQ0FBQyxtQkFBbUIsQ0FBQyxNQUFNLENBQUMsQ0FBQzthQUNwQztTQUNKO1FBQ0QsSUFBSSxDQUFDLGtCQUFrQixDQUFDLEVBQUUsR0FBRyxFQUFFLENBQUMsRUFBRSxJQUFJLEVBQUUsQ0FBQyxFQUFFLEtBQUssRUFBRSxDQUFDLEVBQUUsTUFBTSxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUM7SUFDdEUsQ0FBQztJQUVEOztPQUVHO0lBQ0gsV0FBVztRQUNQLElBQUksQ0FBQyxrQkFBa0IsR0FBRyxDQUFDLEdBQUcsSUFBSSxDQUFDLGNBQWMsQ0FBQyxDQUFDO1FBQ25ELEtBQUssTUFBTSxNQUFNLElBQUksSUFBSSxDQUFDLGtCQUFrQixFQUFFO1lBQzFDLG1CQUFtQixDQUFDLE1BQU0sRUFBRSxJQUFJLENBQUMsQ0FBQztTQUNyQztJQUNMLENBQUM7SUFFRDs7O09BR0c7SUFDSCxnQkFBZ0IsQ0FBQyxLQUFVO1FBQ3ZCLE1BQU0sTUFBTSxHQUFHLEtBQUssQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDO1FBRWxDLEtBQUssTUFBTSxNQUFNLElBQUksSUFBSSxDQUFDLGNBQWMsRUFBRTtZQUN0QyxNQUFNLENBQUMsS0FBSyxDQUFDLFNBQVMsR0FBRyxTQUFTLE1BQU0sR0FBRyxDQUFDO1NBQy9DO0lBQ0wsQ0FBQztJQUVEOzs7T0FHRztJQUNILG1CQUFtQixDQUFDLE1BQW1CO1FBQ25DLElBQUksSUFBSSxDQUFDLG1CQUFtQixFQUFFO1lBQzFCLElBQUksSUFBSSxDQUFDLFlBQVksS0FBSyxNQUFNLENBQUMsRUFBRSxFQUFFO2dCQUNqQyxpQ0FBaUM7Z0JBQ2pDLE1BQU0sQ0FBQyxLQUFLLENBQUMsZUFBZSxHQUFHLGlGQUFpRixDQUFDO2dCQUNqSCxJQUFJLENBQUMsWUFBWSxHQUFHLElBQUksQ0FBQztnQkFDekIsT0FBTzthQUNWO1lBQ0QsTUFBTSxDQUFDLEtBQUssQ0FBQyxlQUFlLEdBQUcsOEZBQThGLENBQUM7WUFDOUgsSUFBSSxDQUFDLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxRQUFRLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxFQUFFO2dCQUM3QyxJQUFJLENBQUMsaUJBQWlCLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUMsQ0FBQzthQUMxQztZQUNELElBQUksSUFBSSxDQUFDLFlBQVksRUFBRTtnQkFDbkIsOEJBQThCO2dCQUM5QixNQUFNLFVBQVUsR0FBRyxJQUFJLENBQUMsY0FBYyxDQUFDLElBQUksQ0FBQyxDQUFDLEdBQUcsRUFBRSxFQUFFLENBQUMsR0FBRyxDQUFDLEVBQUUsS0FBSyxJQUFJLENBQUMsWUFBWSxDQUFDLENBQUM7Z0JBQ25GLFVBQVUsQ0FBQyxLQUFLLENBQUMsZUFBZSxHQUFHLGlGQUFpRixDQUFDO2FBQ3hIO1lBQ0QsSUFBSSxDQUFDLFlBQVksR0FBRyxNQUFNLENBQUMsRUFBRSxDQUFDO1lBQzlCLE9BQU87U0FDVjtRQUNELElBQUksQ0FBQyxJQUFJLENBQUMsaUJBQWlCLENBQUMsUUFBUSxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUMsRUFBRTtZQUM3QyxtQkFBbUI7WUFDbkIsTUFBTSxDQUFDLEtBQUssQ0FBQyxlQUFlLEdBQUcsaUZBQWlGLENBQUM7WUFDakgsSUFBSSxDQUFDLGlCQUFpQixDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDLENBQUM7U0FDMUM7YUFBTTtZQUNILHdCQUF3QjtZQUN4QixJQUFJLElBQUksQ0FBQyxjQUFjLENBQUMsUUFBUSxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxjQUFjLENBQUMsUUFBUSxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUMsRUFBRTtnQkFDckYsa0RBQWtEO2dCQUNsRCxNQUFNLENBQUMsS0FBSyxDQUFDLGVBQWUsR0FBRyxrRkFBa0YsQ0FBQzthQUNySDtpQkFBTTtnQkFDSCxNQUFNLENBQUMsS0FBSyxDQUFDLGVBQWUsR0FBRyw2RkFBNkYsQ0FBQzthQUNoSTtZQUNELE1BQU0sS0FBSyxHQUFHLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxDQUFDO1lBQ3hELElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxNQUFNLENBQUMsS0FBSyxFQUFFLENBQUMsQ0FBQyxDQUFDO1NBQzNDO0lBQ0wsQ0FBQztJQUVELGVBQWU7UUFDWCxJQUFJLENBQUMsY0FBYyxDQUFDLElBQUksQ0FBQyxFQUFFLFFBQVEsRUFBRSxJQUFJLENBQUMsaUJBQWlCLEVBQUUsY0FBYyxFQUFFLElBQUksQ0FBQyxZQUFZLEVBQUUsQ0FBQyxDQUFDO0lBQ3RHLENBQUM7SUFFRCxRQUFRO1FBQ0osSUFBSSxDQUFDLGNBQWMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDbkMsQ0FBQzs7d0hBL2VRLDJCQUEyQjs0R0FBM0IsMkJBQTJCLGdYQ1Z4Qyx1NUdBbUVBOzJGRHpEYSwyQkFBMkI7a0JBTHZDLFNBQVM7K0JBQ0ksMEJBQTBCOzRKQVEzQixPQUFPO3NCQUFmLEtBQUs7Z0JBRUcsaUJBQWlCO3NCQUF6QixLQUFLO2dCQUdHLFdBQVc7c0JBQW5CLEtBQUs7Z0JBS0csY0FBYztzQkFBdEIsS0FBSztnQkFHRyxpQkFBaUI7c0JBQXpCLEtBQUs7Z0JBR0csZ0JBQWdCO3NCQUF4QixLQUFLO2dCQUVHLFNBQVM7c0JBQWpCLEtBQUs7Z0JBZ0JJLGNBQWM7c0JBQXZCLE1BQU0iLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBDb21wb25lbnQsIEV2ZW50RW1pdHRlciwgSW5wdXQsIE9uSW5pdCwgT3V0cHV0IH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XHJcbmltcG9ydCB7IGdldENvZWZmaWNpZW50c0ZvckltYWdlLCBnZXRNZXRhRm9ySW1hZ2UsIE5hdmlnYXRpb24sIE5hdmlnYXRpb25TZXJ2aWNlLCBQbGFuLCBab25lLCBzaG93U2NhblBvaW50c09uUGxhbkluRGl2LCBab25lU2VydmljZSwgUGxhblNlcnZpY2UgfSBmcm9tICdAc21hcnRlcnBsYW4vbmd4LXNtYXJ0ZXJwbGFuLWNvcmUnO1xyXG5pbXBvcnQgcGFuem9vbSwgeyBQYW5ab29tIH0gZnJvbSAncGFuem9vbSc7XHJcbmltcG9ydCB7IGJ1dHRvbklzSW5TZWxlY3Rpb24sIGlzSW5Qb2x5Z29uLCBSZWN0YW5nbGUsIHJvdGF0ZSwgc2V0VmlzdWFsbHlTZWxlY3RlZCwgc3R5bGVCdXR0b24sIFN3ZWVwU3RhdGUgfSBmcm9tICcuLi8uLi8uLi8uLi9oZWxwZXIuc2VydmljZSc7XHJcblxyXG5AQ29tcG9uZW50KHtcclxuICAgIHNlbGVjdG9yOiAnbGliLXN3ZWVwLXBsYW4tc2VsZWN0aW9uJyxcclxuICAgIHRlbXBsYXRlVXJsOiAnLi9zd2VlcC1wbGFuLXNlbGVjdGlvbi5jb21wb25lbnQuaHRtbCcsXHJcbiAgICBzdHlsZVVybHM6IFsnLi9zd2VlcC1wbGFuLXNlbGVjdGlvbi5jb21wb25lbnQuc2NzcyddXHJcbn0pXHJcbmV4cG9ydCBjbGFzcyBTd2VlcFBsYW5TZWxlY3Rpb25Db21wb25lbnQgaW1wbGVtZW50cyBPbkluaXQge1xyXG5cclxuICAgIHBsYW5zOiBQbGFuW107XHJcblxyXG4gICAgQElucHV0KCkgc3BhY2VJRDogc3RyaW5nO1xyXG5cclxuICAgIEBJbnB1dCgpIGNob3NlblNjYW5zT25QbGFuOiBzdHJpbmdbXSA9IFtdO1xyXG5cclxuICAgIC8qKiBpZiBjb21taW5nIGZyb20gRWRpdCBQbGFuIFNWRyBab25lIGNyZWF0aW9uICovXHJcbiAgICBASW5wdXQoKSBuZXdab25lRGF0YTogYW55O1xyXG5cclxuICAgIG5hdklEc1pvbmVFZGl0OiBzdHJpbmdbXSA9IFtdO1xyXG5cclxuICAgIC8vIHN3ZWVwcyBiZWxvbmdpbmcgdG8gYW55IGF1ZGlvIHpvbmVcclxuICAgIEBJbnB1dCgpIG9jY3VwaWVkU3dlZXBzOiBzdHJpbmdbXSA9IFtdO1xyXG5cclxuICAgIC8vIHN3ZWVwcyB1bmF2YWlsYWJsZSAoY2Fubm90IGJlIGNob3NlbilcclxuICAgIEBJbnB1dCgpIHVuYXZhaWxhYmxlU3dlZXBzOiBzdHJpbmdbXSA9IFtdO1xyXG5cclxuICAgIC8vIGlmIGNob29zaW5nIHN3ZWVwcyBmb3IgYXVkaW8gem9uZVxyXG4gICAgQElucHV0KCkgZWRpdGluZ0F1ZGlvWm9uZTogYm9vbGVhbiA9IGZhbHNlO1xyXG5cclxuICAgIEBJbnB1dCgpIGlucHV0Wm9uZTogWm9uZTtcclxuXHJcbiAgICBjaG9zZW5QbGFuOiBQbGFuO1xyXG5cclxuICAgIC8qKiBwYW5ab29tIGVsZW1lbnQgZm9yIGFkZGluZyBzY2FucyAqL1xyXG4gICAgcGFuWm9vbTogUGFuWm9vbTtcclxuXHJcbiAgICAvKiogZGl2UGxhbiAodXNlIEJ5IHBhblpvb20pICovXHJcbiAgICBkaXZQbGFuOiBIVE1MRWxlbWVudDtcclxuXHJcbiAgICAvKiogYWxsIHNjYW4gYnV0dG9ucyBFbGVtZW50ICovXHJcbiAgICBidXR0b25FbGVtZW50czogSFRNTEJ1dHRvbkVsZW1lbnRbXSA9IFtdO1xyXG5cclxuICAgIC8qKiBTY2FuIGJ1dHRvbnMgdGhhdCBhcmUgaW4gdGhlIGN1cnJlbnQgc2VsZWN0aW9uICovXHJcbiAgICBidXR0b25zSW5TZWxlY3Rpb246IEhUTUxCdXR0b25FbGVtZW50W10gPSBbXTtcclxuXHJcbiAgICBAT3V0cHV0KCkgc3dlZXBzU2VsZWN0ZWQgPSBuZXcgRXZlbnRFbWl0dGVyPHsgc3dlZXBzOiBzdHJpbmdbXTsgc3RhcnRTd2VlcElEOiBzdHJpbmc7IH0+KCk7XHJcblxyXG4gICAgaXNTZXR0aW5nU3RhcnRTd2VlcCA9IGZhbHNlO1xyXG5cclxuICAgIHN0YXJ0U3dlZXBJRDogc3RyaW5nO1xyXG5cclxuICAgIGNvbnN0cnVjdG9yKFxyXG4gICAgICAgIHByaXZhdGUgem9uZVNlcnZpY2U6IFpvbmVTZXJ2aWNlLFxyXG4gICAgICAgIHByaXZhdGUgbmF2aWdhdGlvblNlcnZpY2U6IE5hdmlnYXRpb25TZXJ2aWNlLFxyXG4gICAgICAgIHByaXZhdGUgcGxhblNlcnZpY2U6IFBsYW5TZXJ2aWNlLFxyXG4gICAgKSB7IH1cclxuXHJcbiAgICBuZ09uSW5pdCgpOiB2b2lkIHtcclxuICAgICAgICB0aGlzLmdldFBsYW5zKCk7XHJcbiAgICAgICAgaWYgKHRoaXMuaW5wdXRab25lKSB7XHJcbiAgICAgICAgICAgIHRoaXMuc2V0U3dlZXBzT2ZJbnB1dFpvbmUoKTtcclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgbmdPbkNoYW5nZXMoKSB7XHJcbiAgICAgICAgaWYgKHRoaXMuY2hvc2VuUGxhbikge1xyXG4gICAgICAgICAgICB0aGlzLnNldFN3ZWVwc09mSW5wdXRab25lKCk7XHJcbiAgICAgICAgICAgIHRoaXMuY2hvc2VuU2NhbnNPblBsYW4gPSBbXTtcclxuICAgICAgICAgICAgdGhpcy5jbGVhckRpdlBsYW4oKTtcclxuICAgICAgICAgICAgdGhpcy5hZGRTY2FuUG9pbnRzKCk7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIHNldFN3ZWVwc09mSW5wdXRab25lKCkge1xyXG4gICAgICAgIHRoaXMubmF2SURzWm9uZUVkaXQgPSB0aGlzLmlucHV0Wm9uZS5zd2VlcElEcztcclxuICAgIH1cclxuXHJcbiAgICBhc3luYyBnZXRQbGFucygpIHtcclxuICAgICAgICB0aGlzLnBsYW5zID0gYXdhaXQgdGhpcy5wbGFuU2VydmljZS5nZXRTaW5nZWRQbGFuc0ZvclNwYWNlKFxyXG4gICAgICAgICAgICB0aGlzLnNwYWNlSUQsXHJcbiAgICAgICAgKTtcclxuICAgIH1cclxuXHJcbiAgICBhc3luYyBvblBsYW5DbGljayhwbGFuOiBQbGFuKSB7XHJcbiAgICAgICAgdGhpcy5jaG9zZW5QbGFuID0gcGxhbjtcclxuICAgICAgICB0aGlzLmNsZWFyRGl2UGxhbigpO1xyXG4gICAgICAgIHRoaXMuYWRkU2NhblBvaW50cygpO1xyXG4gICAgfVxyXG5cclxuICAgIGFzeW5jIGFkZFNjYW5Qb2ludHMoKSB7XHJcbiAgICAgICAgdGhpcy5kaXZQbGFuID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvcihcIiNwbGFuRGl2XCIpIGFzIEhUTUxFbGVtZW50O1xyXG4gICAgICAgIGNvbnN0IHpvbmVPZlBsYW4gPSBhd2FpdCB0aGlzLnpvbmVTZXJ2aWNlLmdldFpvbmUoXHJcbiAgICAgICAgICAgIHRoaXMuY2hvc2VuUGxhbi56b25lSUQsXHJcbiAgICAgICAgKTtcclxuICAgICAgICBjb25zdCBuYXZpZ2F0aW9ucyA9IGF3YWl0IHRoaXMubmF2aWdhdGlvblNlcnZpY2UuZ2V0TmF2aWdhdGlvbnNGb3Jab25lKFxyXG4gICAgICAgICAgICB6b25lT2ZQbGFuLFxyXG4gICAgICAgICk7XHJcbiAgICAgICAgaWYgKHRoaXMubmV3Wm9uZURhdGEpIGF3YWl0IHRoaXMuc2V0U2NhbkJ5RHJhdyhuYXZpZ2F0aW9ucyk7XHJcbiAgICAgICAgdGhpcy5idXR0b25FbGVtZW50cyA9IGF3YWl0IHNob3dTY2FuUG9pbnRzT25QbGFuSW5EaXYoXHJcbiAgICAgICAgICAgIHRoaXMuY2hvc2VuUGxhbixcclxuICAgICAgICAgICAgdGhpcy5kaXZQbGFuLFxyXG4gICAgICAgICAgICBuYXZpZ2F0aW9ucyxcclxuICAgICAgICApO1xyXG4gICAgICAgIGZvciAoY29uc3QgZWxlbWVudCBvZiB0aGlzLmJ1dHRvbkVsZW1lbnRzKSB7XHJcbiAgICAgICAgICAgIGlmICh0aGlzLnVuYXZhaWxhYmxlU3dlZXBzICYmIHRoaXMudW5hdmFpbGFibGVTd2VlcHMuaW5jbHVkZXMoZWxlbWVudC5pZCkpIHtcclxuICAgICAgICAgICAgICAgIHN0eWxlQnV0dG9uKGVsZW1lbnQsIFN3ZWVwU3RhdGUuRElTQUJMRUQpO1xyXG4gICAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgaWYgKFxyXG4gICAgICAgICAgICAgICAgICAgICh0aGlzLm5hdklEc1pvbmVFZGl0Lmxlbmd0aCA+IDAgJiZcclxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5uYXZJRHNab25lRWRpdC5pbmNsdWRlcyhlbGVtZW50LmlkKSlcclxuICAgICAgICAgICAgICAgICAgICB8fCB0aGlzLmNob3NlblNjYW5zT25QbGFuLmluY2x1ZGVzKGVsZW1lbnQuaWQpKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgc3R5bGVCdXR0b24oZWxlbWVudCwgU3dlZXBTdGF0ZS5BRERFRCk7XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKCF0aGlzLmNob3NlblNjYW5zT25QbGFuLmluY2x1ZGVzKGVsZW1lbnQuaWQpKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY2hvc2VuU2NhbnNPblBsYW4ucHVzaChlbGVtZW50LmlkKTtcclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHRoaXMub2NjdXBpZWRTd2VlcHMgJiYgdGhpcy5vY2N1cGllZFN3ZWVwcy5pbmNsdWRlcyhlbGVtZW50LmlkKSkge1xyXG4gICAgICAgICAgICAgICAgICAgIHN0eWxlQnV0dG9uKGVsZW1lbnQsIFN3ZWVwU3RhdGUuT0NDVVBJRUQpO1xyXG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgICAgICAgICBzdHlsZUJ1dHRvbihlbGVtZW50LCBTd2VlcFN0YXRlLlJFTU9WRUQpO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgLy9zdGFydCBwb2ludCBzaG91bGQgYmUgbGFzdCBjb25kaXRpb24gXHJcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5pbnB1dFpvbmUgJiYgdGhpcy5pbnB1dFpvbmUuc3RhcnRTd2VlcElEID09PSBlbGVtZW50LmlkKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgY29uc29sZS5sb2coXCJzZXR0aW5nIHN0YXJ0IHBvaW50XCIpO1xyXG4gICAgICAgICAgICAgICAgICAgIHN0eWxlQnV0dG9uKGVsZW1lbnQsIFN3ZWVwU3RhdGUuU1RBUlRQT0lOVCk7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICBlbGVtZW50LmFkZEV2ZW50TGlzdGVuZXIoXCJjbGlja1wiLCAoZXZlbnQpID0+XHJcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5vbkJ1dHRvblNjYW5DbGlja2VkKGV2ZW50LnRhcmdldCBhcyBIVE1MRWxlbWVudCksXHJcbiAgICAgICAgICAgICAgICApO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHRoaXMucGFuWm9vbSA9IHBhbnpvb20odGhpcy5kaXZQbGFuLCB7XHJcbiAgICAgICAgICAgIGJvdW5kczogdHJ1ZSxcclxuICAgICAgICAgICAgYm91bmRzUGFkZGluZzogMCxcclxuICAgICAgICAgICAgbWF4Wm9vbTogMy41LFxyXG4gICAgICAgICAgICBiZWZvcmVNb3VzZURvd24oZTogTW91c2VFdmVudCkge1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuIChcclxuICAgICAgICAgICAgICAgICAgICBlLmJ1dHRvbiA9PT0gMlxyXG4gICAgICAgICAgICAgICAgKTsgLyoqIElnbm9yZSBldmVudCBmb3IgcmlnaHQgY2xpY2sgKHVzZSBmb3Igc2VsZWN0aW5nKSAqL1xyXG4gICAgICAgICAgICB9LFxyXG4gICAgICAgIH0pO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKiBGdW5jdGlvbiBpZiB3ZSBhcmUgY29taW5nIGZvciBzdmcgZWRpdG9yIHdvcmtmbG93ICovXHJcbiAgICBzZXRTY2FuQnlEcmF3KG5hdmlnYXRpb25zOiBhbnlbXSk6IFByb21pc2U8dm9pZD4ge1xyXG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZShhc3luYyAocmVzb2x2ZSkgPT4ge1xyXG4gICAgICAgICAgICBjb25zdCByZWN0ID0ge1xyXG4gICAgICAgICAgICAgICAgd2lkdGg6IHRoaXMubmV3Wm9uZURhdGEud2lkdGgsXHJcbiAgICAgICAgICAgICAgICBoZWlnaHQ6IHRoaXMubmV3Wm9uZURhdGEuaGVpZ2h0LFxyXG4gICAgICAgICAgICB9O1xyXG4gICAgICAgICAgICBjb25zdCBpbWcgPSBhd2FpdCBnZXRNZXRhRm9ySW1hZ2UodGhpcy5jaG9zZW5QbGFuLmZpbGVwYXRoKTtcclxuICAgICAgICAgICAgY29uc3QgeyBjb2VmZlgsIGNvZWZmWSB9ID0gZ2V0Q29lZmZpY2llbnRzRm9ySW1hZ2UoaW1nLCByZWN0KTtcclxuXHJcbiAgICAgICAgICAgIGNvbnN0IGRyYXcgPSB0aGlzLm5ld1pvbmVEYXRhLmVsZW1lbnRzO1xyXG5cclxuICAgICAgICAgICAgZHJhdy5tYXAoYXN5bmMgKGVsZW1lbnQ6IGFueSkgPT4ge1xyXG4gICAgICAgICAgICAgICAgc3dpdGNoIChlbGVtZW50Lm5vZGVOYW1lKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBcInJlY3RcIjpcclxuICAgICAgICAgICAgICAgICAgICAgICAgYXdhaXQgdGhpcy5zZXRTY2FuSW5SZWN0KFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaW1nLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29lZmZYLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29lZmZZLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxlbWVudCxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5hdmlnYXRpb25zLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICApO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBcImVsbGlwc2VcIjpcclxuICAgICAgICAgICAgICAgICAgICAgICAgYXdhaXQgdGhpcy5zZXRTY2FuSW5DaXJjbGUoXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbWcsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2VmZlgsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2VmZlksXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbGVtZW50LFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbmF2aWdhdGlvbnMsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xyXG5cclxuICAgICAgICAgICAgICAgICAgICBjYXNlIFwicGF0aFwiOlxyXG4gICAgICAgICAgICAgICAgICAgICAgICBhd2FpdCB0aGlzLnNldFNjYW5JblBvbHlnb24oXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbWcsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2VmZlgsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2VmZlksXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbGVtZW50LFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbmF2aWdhdGlvbnMsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgICAgICAgICAgICAgIGRlZmF1bHQ6XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB9KTtcclxuXHJcbiAgICAgICAgICAgIHJlc29sdmUoKTtcclxuICAgICAgICB9KTtcclxuICAgIH1cclxuXHJcbiAgICBhc3luYyBzZXRTY2FuSW5SZWN0KGltZzogYW55LCBjb2VmZlg6IG51bWJlciwgY29lZmZZOiBudW1iZXIsXHJcbiAgICAgICAgZWxlbWVudDogeyBhbmdsZTogYW55OyBjeDogYW55OyBjeTogYW55OyB4OiBudW1iZXI7IHdpZHRoOiBhbnk7IHk6IG51bWJlcjsgaGVpZ2h0OiBhbnk7IH0sIG5hdmlnYXRpb25zOiBhbnlbXSkge1xyXG4gICAgICAgIGNvbnN0IGNhbGlicmFnZSA9IEpTT04ucGFyc2UodGhpcy5jaG9zZW5QbGFuLmNhbGlicmF0aW9uKTtcclxuICAgICAgICBuYXZpZ2F0aW9ucy5tYXAoKG5hdmlnYXRpb24pID0+IHtcclxuICAgICAgICAgICAgY29uc3QgcG9zaXRpb25zT25QbGFuID0gbmF2aWdhdGlvbi5wb3NpdGlvbk9uUGxhbi5tYXAoKGVudHJ5KSA9PlxyXG4gICAgICAgICAgICAgICAgSlNPTi5wYXJzZShlbnRyeSksXHJcbiAgICAgICAgICAgICk7XHJcbiAgICAgICAgICAgIGNvbnN0IHBvc2l0aW9uT25QbGFuID0gcG9zaXRpb25zT25QbGFuLmZpbmQoXHJcbiAgICAgICAgICAgICAgICAoZGF0YSkgPT4gZGF0YS5wbGFuSUQgPT09IHRoaXMuY2hvc2VuUGxhbi5pZCxcclxuICAgICAgICAgICAgKTtcclxuICAgICAgICAgICAgaWYgKHBvc2l0aW9uT25QbGFuKSB7XHJcbiAgICAgICAgICAgICAgICBjb25zdCByZWFsV2lkdGggPSBpbWcud2lkdGggLyBjb2VmZlg7XHJcbiAgICAgICAgICAgICAgICBjb25zdCByZWFsSGVpZ2h0ID0gaW1nLmhlaWdodCAvIGNvZWZmWTtcclxuICAgICAgICAgICAgICAgIGNvbnN0IG5hdlkgPSAocG9zaXRpb25PblBsYW4ueSAqIHJlYWxIZWlnaHQpIC8gY2FsaWJyYWdlLmltZ0hlaWdodDtcclxuICAgICAgICAgICAgICAgIGNvbnN0IG5hdlggPSAocG9zaXRpb25PblBsYW4ueCAqIHJlYWxXaWR0aCkgLyBjYWxpYnJhZ2UuaW1nV2lkdGg7XHJcbiAgICAgICAgICAgICAgICBpZiAoXHJcbiAgICAgICAgICAgICAgICAgICAgbmF2WCA+IGVsZW1lbnQueCAmJlxyXG4gICAgICAgICAgICAgICAgICAgIG5hdlggPCBlbGVtZW50LnggKyBlbGVtZW50LndpZHRoICYmXHJcbiAgICAgICAgICAgICAgICAgICAgbmF2WSA+IGVsZW1lbnQueSAmJlxyXG4gICAgICAgICAgICAgICAgICAgIG5hdlkgPCBlbGVtZW50LnkgKyBlbGVtZW50LmhlaWdodCAmJlxyXG4gICAgICAgICAgICAgICAgICAgICF0aGlzLm5hdklEc1pvbmVFZGl0LmluY2x1ZGVzKG5hdmlnYXRpb24uaWQpXHJcbiAgICAgICAgICAgICAgICApIHtcclxuICAgICAgICAgICAgICAgICAgICB0aGlzLm5hdklEc1pvbmVFZGl0LnB1c2gobmF2aWdhdGlvbi5pZCk7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIC8vIG9sZCBjYWxpYnJhdGlvbjpcclxuICAgICAgICAgICAgLy8gY29uc3QgcG9zaXRpb24gPSBKU09OLnBhcnNlKG5hdmlnYXRpb24ucG9zaXRpb24pO1xyXG4gICAgICAgICAgICAvLyBsZXQgbmF2WCA9IChjYWxpYnJhZ2Uub2Zmc2V0WCArIHBvc2l0aW9uLnggKiBjYWxpYnJhZ2UueCkgLyBjb2VmZlg7XHJcbiAgICAgICAgICAgIC8vIGxldCBuYXZZID0gKGNhbGlicmFnZS5vZmZzZXRZICsgcG9zaXRpb24ueiAqIGNhbGlicmFnZS55KSAvIGNvZWZmWTtcclxuICAgICAgICAgICAgLy8gaWYgKGVsZW1lbnQuYW5nbGUpIHtcclxuICAgICAgICAgICAgLy8gICAgIGNvbnN0IHJvdGF0ZVBvcyA9IHJvdGF0ZShcclxuICAgICAgICAgICAgLy8gICAgICAgICB7IHg6IG5hdlgsIHk6IG5hdlkgfSxcclxuICAgICAgICAgICAgLy8gICAgICAgICB7IHg6IGVsZW1lbnQuY3gsIHk6IGVsZW1lbnQuY3kgfSxcclxuICAgICAgICAgICAgLy8gICAgICAgICBlbGVtZW50LmFuZ2xlLFxyXG4gICAgICAgICAgICAvLyAgICAgKTtcclxuICAgICAgICAgICAgLy8gICAgIG5hdlggPSByb3RhdGVQb3MueDtcclxuICAgICAgICAgICAgLy8gICAgIG5hdlkgPSByb3RhdGVQb3MueTtcclxuICAgICAgICAgICAgLy8gfVxyXG4gICAgICAgICAgICAvKipcclxuICAgICAgICAgICAgICogVE9ETyBjYWxjdWxlciBsYSByb3RhdGlvbiBkdSByZWN0YW5nbGVcclxuICAgICAgICAgICAgICovXHJcbiAgICAgICAgICAgIC8vIGlmIChcclxuICAgICAgICAgICAgLy8gICAgIG5hdlggPiBlbGVtZW50LnggJiZcclxuICAgICAgICAgICAgLy8gICAgIG5hdlggPCBlbGVtZW50LnggKyBlbGVtZW50LndpZHRoICYmXHJcbiAgICAgICAgICAgIC8vICAgICBuYXZZID4gZWxlbWVudC55ICYmXHJcbiAgICAgICAgICAgIC8vICAgICBuYXZZIDwgZWxlbWVudC55ICsgZWxlbWVudC5oZWlnaHQgJiZcclxuICAgICAgICAgICAgLy8gICAgICF0aGlzLm5hdklEc1pvbmVFZGl0LmluY2x1ZGVzKG5hdmlnYXRpb24uaWQpXHJcbiAgICAgICAgICAgIC8vICkge1xyXG4gICAgICAgICAgICAvLyAgICAgdGhpcy5uYXZJRHNab25lRWRpdC5wdXNoKG5hdmlnYXRpb24uaWQpO1xyXG4gICAgICAgICAgICAvLyB9XHJcbiAgICAgICAgfSk7XHJcbiAgICB9IC8vIEVPXHJcblxyXG4gICAgYXN5bmMgc2V0U2NhbkluQ2lyY2xlKGltZzogYW55LCBjb2VmZlg6IG51bWJlciwgY29lZmZZOiBudW1iZXIsXHJcbiAgICAgICAgZWxlbWVudDogeyBhbmdsZTogYW55OyBjeDogbnVtYmVyOyBjeTogbnVtYmVyOyByeDogbnVtYmVyOyByeTogbnVtYmVyOyB9LCBuYXZpZ2F0aW9uczogTmF2aWdhdGlvbltdKSB7XHJcbiAgICAgICAgY29uc3QgY2FsaWJyYWdlID0gSlNPTi5wYXJzZSh0aGlzLmNob3NlblBsYW4uY2FsaWJyYXRpb24pO1xyXG4gICAgICAgIG5hdmlnYXRpb25zLm1hcChuYXZpZ2F0aW9uID0+IHtcclxuICAgICAgICAgICAgY29uc3QgcG9zaXRpb25zT25QbGFuID0gbmF2aWdhdGlvbi5wb3NpdGlvbk9uUGxhbi5tYXAoKGVudHJ5KSA9PlxyXG4gICAgICAgICAgICAgICAgSlNPTi5wYXJzZShlbnRyeSksXHJcbiAgICAgICAgICAgICk7XHJcbiAgICAgICAgICAgIGNvbnN0IHBvc2l0aW9uT25QbGFuID0gcG9zaXRpb25zT25QbGFuLmZpbmQoXHJcbiAgICAgICAgICAgICAgICAoZGF0YSkgPT4gZGF0YS5wbGFuSUQgPT09IHRoaXMuY2hvc2VuUGxhbi5pZCxcclxuICAgICAgICAgICAgKTtcclxuICAgICAgICAgICAgaWYgKHBvc2l0aW9uT25QbGFuKSB7XHJcbiAgICAgICAgICAgICAgICBjb25zdCByZWFsV2lkdGggPSBpbWcud2lkdGggLyBjb2VmZlg7XHJcbiAgICAgICAgICAgICAgICBjb25zdCByZWFsSGVpZ2h0ID0gaW1nLmhlaWdodCAvIGNvZWZmWTtcclxuICAgICAgICAgICAgICAgIGxldCBuYXZZID0gKHBvc2l0aW9uT25QbGFuLnkgKiByZWFsSGVpZ2h0KSAvIGNhbGlicmFnZS5pbWdIZWlnaHQ7XHJcbiAgICAgICAgICAgICAgICBsZXQgbmF2WCA9IChwb3NpdGlvbk9uUGxhbi54ICogcmVhbFdpZHRoKSAvIGNhbGlicmFnZS5pbWdXaWR0aDtcclxuICAgICAgICAgICAgICAgIGlmIChlbGVtZW50LmFuZ2xlKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgY29uc3Qgcm90YXRlUG9zID0gcm90YXRlKFxyXG4gICAgICAgICAgICAgICAgICAgICAgICB7IHg6IG5hdlgsIHk6IG5hdlkgfSxcclxuICAgICAgICAgICAgICAgICAgICAgICAgeyB4OiBlbGVtZW50LmN4LCB5OiBlbGVtZW50LmN5IH0sXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGVsZW1lbnQuYW5nbGUsXHJcbiAgICAgICAgICAgICAgICAgICAgKTtcclxuICAgICAgICAgICAgICAgICAgICBuYXZYID0gcm90YXRlUG9zLng7XHJcbiAgICAgICAgICAgICAgICAgICAgbmF2WSA9IHJvdGF0ZVBvcy55O1xyXG4gICAgICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgICAgIGNvbnN0IHZhbHVlWCA9XHJcbiAgICAgICAgICAgICAgICAgICAgTWF0aC5wb3cobmF2WCAtIGVsZW1lbnQuY3gsIDIpIC8gTWF0aC5wb3coZWxlbWVudC5yeCwgMik7XHJcbiAgICAgICAgICAgICAgICBjb25zdCB2YWx1ZVkgPVxyXG4gICAgICAgICAgICAgICAgICAgIE1hdGgucG93KG5hdlkgLSBlbGVtZW50LmN5LCAyKSAvIE1hdGgucG93KGVsZW1lbnQucnksIDIpO1xyXG4gICAgICAgICAgICAgICAgY29uc3QgcmVzdWx0ID0gdmFsdWVYICsgdmFsdWVZO1xyXG4gICAgICAgICAgICAgICAgaWYgKHJlc3VsdCA8PSAxICYmICF0aGlzLm5hdklEc1pvbmVFZGl0LmluY2x1ZGVzKG5hdmlnYXRpb24uaWQpKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5uYXZJRHNab25lRWRpdC5wdXNoKG5hdmlnYXRpb24uaWQpO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAvLyBvbGQgY2FsaWJyYXRpb25cclxuICAgICAgICAgICAgLy8gY29uc3QgcG9zaXRpb24gPSBKU09OLnBhcnNlKG5hdmlnYXRpb24ucG9zaXRpb24pO1xyXG4gICAgICAgICAgICAvLyBsZXQgbmF2WCA9IChjYWxpYnJhZ2Uub2Zmc2V0WCArIHBvc2l0aW9uLnggKiBjYWxpYnJhZ2UueCkgLyBjb2VmZlg7XHJcbiAgICAgICAgICAgIC8vIGxldCBuYXZZID0gKGNhbGlicmFnZS5vZmZzZXRZICsgcG9zaXRpb24ueiAqIGNhbGlicmFnZS55KSAvIGNvZWZmWTtcclxuICAgICAgICAgICAgLy8gaWYgKGVsZW1lbnQuYW5nbGUpIHtcclxuICAgICAgICAgICAgLy8gICAgIGNvbnN0IHJvdGF0ZVBvcyA9IHJvdGF0ZShcclxuICAgICAgICAgICAgLy8gICAgICAgICB7IHg6IG5hdlgsIHk6IG5hdlkgfSxcclxuICAgICAgICAgICAgLy8gICAgICAgICB7IHg6IGVsZW1lbnQuY3gsIHk6IGVsZW1lbnQuY3kgfSxcclxuICAgICAgICAgICAgLy8gICAgICAgICBlbGVtZW50LmFuZ2xlLFxyXG4gICAgICAgICAgICAvLyAgICAgKTtcclxuICAgICAgICAgICAgLy8gICAgIG5hdlggPSByb3RhdGVQb3MueDtcclxuICAgICAgICAgICAgLy8gICAgIG5hdlkgPSByb3RhdGVQb3MueTtcclxuICAgICAgICAgICAgLy8gfVxyXG5cclxuICAgICAgICAgICAgLy8gY29uc3QgdmFsdWVYID1cclxuICAgICAgICAgICAgLy8gICAgIE1hdGgucG93KG5hdlggLSBlbGVtZW50LmN4LCAyKSAvIE1hdGgucG93KGVsZW1lbnQucngsIDIpO1xyXG4gICAgICAgICAgICAvLyBjb25zdCB2YWx1ZVkgPVxyXG4gICAgICAgICAgICAvLyAgICAgTWF0aC5wb3cobmF2WSAtIGVsZW1lbnQuY3ksIDIpIC8gTWF0aC5wb3coZWxlbWVudC5yeSwgMik7XHJcbiAgICAgICAgICAgIC8vIGNvbnN0IHJlc3VsdCA9IHZhbHVlWCArIHZhbHVlWTtcclxuICAgICAgICAgICAgLy8gaWYgKHJlc3VsdCA8PSAxICYmICF0aGlzLm5hdklEc1pvbmVFZGl0LmluY2x1ZGVzKG5hdmlnYXRpb24uaWQpKSB7XHJcbiAgICAgICAgICAgIC8vICAgICB0aGlzLm5hdklEc1pvbmVFZGl0LnB1c2gobmF2aWdhdGlvbi5pZCk7XHJcbiAgICAgICAgICAgIC8vIH1cclxuICAgICAgICB9KTtcclxuICAgIH0gLy8gRU9cclxuXHJcbiAgICBhc3luYyBzZXRTY2FuSW5Qb2x5Z29uKGltZzogYW55LCBjb2VmZlg6IG51bWJlciwgY29lZmZZOiBudW1iZXIsIGVsZW1lbnQ6IHsgc2VnTGlzdDogYW55OyB9LCBuYXZpZ2F0aW9uczogYW55W10pIHtcclxuICAgICAgICBjb25zdCBjYWxpYnJhZ2UgPSBKU09OLnBhcnNlKHRoaXMuY2hvc2VuUGxhbi5jYWxpYnJhdGlvbik7XHJcbiAgICAgICAgbmF2aWdhdGlvbnMubWFwKGFzeW5jIChuYXZpZ2F0aW9uKSA9PiB7XHJcblxyXG4gICAgICAgICAgICBjb25zdCBwb3NpdGlvbnNPblBsYW4gPSBuYXZpZ2F0aW9uLnBvc2l0aW9uT25QbGFuLm1hcCgoZW50cnkpID0+XHJcbiAgICAgICAgICAgICAgICBKU09OLnBhcnNlKGVudHJ5KSxcclxuICAgICAgICAgICAgKTtcclxuICAgICAgICAgICAgY29uc3QgcG9zaXRpb25PblBsYW4gPSBwb3NpdGlvbnNPblBsYW4uZmluZChcclxuICAgICAgICAgICAgICAgIChkYXRhKSA9PiBkYXRhLnBsYW5JRCA9PT0gdGhpcy5jaG9zZW5QbGFuLmlkLFxyXG4gICAgICAgICAgICApO1xyXG4gICAgICAgICAgICBpZiAocG9zaXRpb25PblBsYW4pIHtcclxuICAgICAgICAgICAgICAgIGNvbnN0IHJlYWxXaWR0aCA9IGltZy53aWR0aCAvIGNvZWZmWDtcclxuICAgICAgICAgICAgICAgIGNvbnN0IHJlYWxIZWlnaHQgPSBpbWcuaGVpZ2h0IC8gY29lZmZZO1xyXG4gICAgICAgICAgICAgICAgbGV0IG5hdlkgPSAocG9zaXRpb25PblBsYW4ueSAqIHJlYWxIZWlnaHQpIC8gY2FsaWJyYWdlLmltZ0hlaWdodDtcclxuICAgICAgICAgICAgICAgIGxldCBuYXZYID0gKHBvc2l0aW9uT25QbGFuLnggKiByZWFsV2lkdGgpIC8gY2FsaWJyYWdlLmltZ1dpZHRoO1xyXG5cclxuICAgICAgICAgICAgICAgIGNvbnN0IHAgPSB7XHJcbiAgICAgICAgICAgICAgICAgICAgeDogbmF2WCxcclxuICAgICAgICAgICAgICAgICAgICB5OiBuYXZZLFxyXG4gICAgICAgICAgICAgICAgfTtcclxuICAgICAgICAgICAgICAgIGlmIChcclxuICAgICAgICAgICAgICAgICAgICBpc0luUG9seWdvbihwLCBlbGVtZW50LnNlZ0xpc3QpICYmXHJcbiAgICAgICAgICAgICAgICAgICAgIXRoaXMubmF2SURzWm9uZUVkaXQuaW5jbHVkZXMobmF2aWdhdGlvbi5pZClcclxuICAgICAgICAgICAgICAgICkge1xyXG4gICAgICAgICAgICAgICAgICAgIHRoaXMubmF2SURzWm9uZUVkaXQucHVzaChuYXZpZ2F0aW9uLmlkKTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgLy8gb2xkIGNhbGlicmF0aW9uXHJcbiAgICAgICAgICAgIC8vIGNvbnN0IHBvc2l0aW9uID0gSlNPTi5wYXJzZShuYXZpZ2F0aW9uLnBvc2l0aW9uKTtcclxuICAgICAgICAgICAgLy8gY29uc3QgcCA9IHtcclxuICAgICAgICAgICAgLy8gICAgIHg6IChjYWxpYnJhZ2Uub2Zmc2V0WCArIHBvc2l0aW9uLnggKiBjYWxpYnJhZ2UueCkgLyBjb2VmZlgsXHJcbiAgICAgICAgICAgIC8vICAgICB5OiAoY2FsaWJyYWdlLm9mZnNldFkgKyBwb3NpdGlvbi56ICogY2FsaWJyYWdlLnkpIC8gY29lZmZZLFxyXG4gICAgICAgICAgICAvLyB9O1xyXG4gICAgICAgICAgICAvLyBpZiAoZWxlbWVudC5hbmdsZSkge1xyXG4gICAgICAgICAgICAvLyAgICAgcCA9IHRoaXMucm90YXRlKFxyXG4gICAgICAgICAgICAvLyAgICAgICAgIHAsXHJcbiAgICAgICAgICAgIC8vICAgICAgICAgeyB4OiBlbGVtZW50LmN4LCB5OiBlbGVtZW50LmN5IH0sXHJcbiAgICAgICAgICAgIC8vICAgICAgICAgZWxlbWVudC5hbmdsZSxcclxuICAgICAgICAgICAgLy8gICAgICk7XHJcbiAgICAgICAgICAgIC8vIH1cclxuICAgICAgICAgICAgLy8gaWYgKFxyXG4gICAgICAgICAgICAvLyAgICAgaXNJblBvbHlnb24ocCwgZWxlbWVudC5zZWdMaXN0KSAmJlxyXG4gICAgICAgICAgICAvLyAgICAgIXRoaXMubmF2SURzWm9uZUVkaXQuaW5jbHVkZXMobmF2aWdhdGlvbi5pZClcclxuICAgICAgICAgICAgLy8gKSB7XHJcbiAgICAgICAgICAgIC8vICAgICB0aGlzLm5hdklEc1pvbmVFZGl0LnB1c2gobmF2aWdhdGlvbi5pZCk7XHJcbiAgICAgICAgICAgIC8vIH1cclxuICAgICAgICB9KTtcclxuICAgIH1cclxuXHJcbiAgICBjbGVhckRpdlBsYW4oKSB7XHJcbiAgICAgICAgaWYgKHRoaXMuZGl2UGxhbikgdGhpcy5kaXZQbGFuLmlubmVySFRNTCA9IFwiXCI7XHJcbiAgICB9XHJcblxyXG5cclxuICAgIC8qKlxyXG4gICAgICogVHJpZ2dlciBlYWNoIGJ5IHRoZSBzZWxlY3Rpb25Db21wb25lbnQgd2hlbiBzZWxlY3Rpb24gY2hhbmdlXHJcbiAgICAgKiBVcGRhdGUgdGhlIGN1cnJlbnQgc2VsZWN0ZWQgc2NhbiBidXR0b25zXHJcbiAgICAgKiBAcGFyYW0gc2VsZWN0aW9uIG5ldyBzZWxlY3Rpb25cclxuICAgICAqL1xyXG4gICAgb25TZWxlY3Rpb25DaGFuZ2VkKHNlbGVjdGlvbjogUmVjdGFuZ2xlKSB7XHJcbiAgICAgICAgY29uc3QgdW5zZWxlY3RlZEJ1dHRvbnM6IEhUTUxCdXR0b25FbGVtZW50W10gPSBbXTtcclxuICAgICAgICBjb25zdCBuZXdTZWxlY3RlZEJ1dHRvbnMgPSBbXTtcclxuXHJcbiAgICAgICAgLyoqIEZvciBlYWNoIGJ1dHRvbiwgZGVjaWRlIHdoZXRoZXIgd2lsbCBiZSBhZGQgdG8gc2VsZWN0ZWQgbGlzdCBvciB1bnNlbGVjdGVkIGxpc3QgKi9cclxuICAgICAgICBmb3IgKGNvbnN0IGJ1dHRvbiBvZiB0aGlzLmJ1dHRvbkVsZW1lbnRzKSB7XHJcbiAgICAgICAgICAgIGNvbnN0IGlzU2VsZWN0ZWQgPSBidXR0b25Jc0luU2VsZWN0aW9uKGJ1dHRvbiwgc2VsZWN0aW9uKTtcclxuICAgICAgICAgICAgaWYgKHRoaXMuYnV0dG9uc0luU2VsZWN0aW9uLmluY2x1ZGVzKGJ1dHRvbikpIHtcclxuICAgICAgICAgICAgICAgIC8qKiBJZiB0aGUgYnV0dG9uIGlzIGFscmVhZHkgaW4gdGhlIHNlbGVjdGVkIGxpc3QsIHdlIGNoZWNrIGlmIGl0IHNob3VsZCBiZSB1bnNlbGVjdCAqL1xyXG4gICAgICAgICAgICAgICAgaWYgKCFpc1NlbGVjdGVkKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgdW5zZWxlY3RlZEJ1dHRvbnMucHVzaChidXR0b24pO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB9IGVsc2UgaWYgKGlzU2VsZWN0ZWQpIHtcclxuICAgICAgICAgICAgICAgIG5ld1NlbGVjdGVkQnV0dG9ucy5wdXNoKGJ1dHRvbik7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIC8qKiBWaXN1YWxseSBVcGRhdGUgdW5zZWxlY3RlZCBsaXN0ICovXHJcbiAgICAgICAgZm9yIChjb25zdCBidXR0b24gb2YgdW5zZWxlY3RlZEJ1dHRvbnMpIHtcclxuICAgICAgICAgICAgc2V0VmlzdWFsbHlTZWxlY3RlZChidXR0b24sIGZhbHNlKTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIC8qKiBWaXN1YWxseSBVcGRhdGUgc2VsZWN0ZWQgbGlzdCAqL1xyXG4gICAgICAgIGZvciAoY29uc3QgYnV0dG9uIG9mIG5ld1NlbGVjdGVkQnV0dG9ucykge1xyXG4gICAgICAgICAgICBzZXRWaXN1YWxseVNlbGVjdGVkKGJ1dHRvbiwgdHJ1ZSk7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICAvKiogUmVtb3ZlICB1bnNlbGVjdGVkIGxpc3QgKi9cclxuICAgICAgICB0aGlzLmJ1dHRvbnNJblNlbGVjdGlvbiA9IHRoaXMuYnV0dG9uc0luU2VsZWN0aW9uLmZpbHRlcigoYnV0dG9uKSA9PiB7XHJcbiAgICAgICAgICAgIHJldHVybiAhdW5zZWxlY3RlZEJ1dHRvbnMuaW5jbHVkZXMoYnV0dG9uKTtcclxuICAgICAgICB9KTtcclxuICAgICAgICAvKiogQWRkIG5ldyBzZWxlY3RlZCBidXR0b25zICovXHJcbiAgICAgICAgdGhpcy5idXR0b25zSW5TZWxlY3Rpb24gPSBbXHJcbiAgICAgICAgICAgIC4uLnRoaXMuYnV0dG9uc0luU2VsZWN0aW9uLFxyXG4gICAgICAgICAgICAuLi5uZXdTZWxlY3RlZEJ1dHRvbnMsXHJcbiAgICAgICAgXTtcclxuICAgIH1cclxuXHJcblxyXG5cclxuICAgIC8qKlxyXG4gICAgICogVHJpZ2dlciB3aGVuIHRoZSB1c2VyIGNsaWNrIHRvIGFkZCB0aGUgc2VsZWN0ZWQgc2NhbnNcclxuICAgICAqL1xyXG4gICAgb25TZWxlY3Rpb25BZGQoKSB7XHJcbiAgICAgICAgZm9yIChjb25zdCBidXR0b24gb2YgdGhpcy5idXR0b25zSW5TZWxlY3Rpb24pIHtcclxuICAgICAgICAgICAgaWYgKCF0aGlzLmNob3NlblNjYW5zT25QbGFuLmluY2x1ZGVzKGJ1dHRvbi5pZCkpIHtcclxuICAgICAgICAgICAgICAgIHRoaXMub25CdXR0b25TY2FuQ2xpY2tlZChidXR0b24pO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICB0aGlzLm9uU2VsZWN0aW9uQ2hhbmdlZCh7IHRvcDogMCwgbGVmdDogMCwgd2lkdGg6IDAsIGhlaWdodDogMCB9KTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIFRyaWdnZXIgd2hlbiB0aGUgdXNlciBjbGljayB0byByZW1vdmUgdGhlIHNlbGVjdGVkIHNjYW5zXHJcbiAgICAgKi9cclxuICAgIG9uU2VsZWN0aW9uUmVtb3ZlKCkge1xyXG4gICAgICAgIGZvciAoY29uc3QgYnV0dG9uIG9mIHRoaXMuYnV0dG9uc0luU2VsZWN0aW9uKSB7XHJcbiAgICAgICAgICAgIGlmICh0aGlzLmNob3NlblNjYW5zT25QbGFuLmluY2x1ZGVzKGJ1dHRvbi5pZCkpIHtcclxuICAgICAgICAgICAgICAgIHRoaXMub25CdXR0b25TY2FuQ2xpY2tlZChidXR0b24pO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHRoaXMub25TZWxlY3Rpb25DaGFuZ2VkKHsgdG9wOiAwLCBsZWZ0OiAwLCB3aWR0aDogMCwgaGVpZ2h0OiAwIH0pO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogVHJpZ2dlciB3aGVuIHRoZSB1c2VyIGNsaWNrIHRvIHNlbGVjdCBhbGwgc2NhbnNcclxuICAgICAqL1xyXG4gICAgb25TZWxlY3RBbGwoKSB7XHJcbiAgICAgICAgdGhpcy5idXR0b25zSW5TZWxlY3Rpb24gPSBbLi4udGhpcy5idXR0b25FbGVtZW50c107XHJcbiAgICAgICAgZm9yIChjb25zdCBidXR0b24gb2YgdGhpcy5idXR0b25zSW5TZWxlY3Rpb24pIHtcclxuICAgICAgICAgICAgc2V0VmlzdWFsbHlTZWxlY3RlZChidXR0b24sIHRydWUpO1xyXG4gICAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIFRyaWdnZXIgd2hlbiB0aGUgdXNlciBjaGFuZ2UgdGhlIHNpemUgb2YgdGhlIHNjYW4gcG9pbnRzXHJcbiAgICAgKiBAcGFyYW0gZXZlbnRcclxuICAgICAqL1xyXG4gICAgb25DaGFuZ2VTY2FuU2l6ZShldmVudDogYW55KSB7XHJcbiAgICAgICAgY29uc3QgZmFjdG9yID0gZXZlbnQudGFyZ2V0LnZhbHVlO1xyXG5cclxuICAgICAgICBmb3IgKGNvbnN0IGJ1dHRvbiBvZiB0aGlzLmJ1dHRvbkVsZW1lbnRzKSB7XHJcbiAgICAgICAgICAgIGJ1dHRvbi5zdHlsZS50cmFuc2Zvcm0gPSBgc2NhbGUoJHtmYWN0b3J9KWA7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogV2hlbiBhIGJ1dHRvbiByZXByZXNlbnRpbmcgYSBzY2FuIGlzIGNsaWNrZWRcclxuICAgICAqIEBwYXJhbSBidXR0b25cclxuICAgICAqL1xyXG4gICAgb25CdXR0b25TY2FuQ2xpY2tlZChidXR0b246IEhUTUxFbGVtZW50KSB7XHJcbiAgICAgICAgaWYgKHRoaXMuaXNTZXR0aW5nU3RhcnRTd2VlcCkge1xyXG4gICAgICAgICAgICBpZiAodGhpcy5zdGFydFN3ZWVwSUQgPT09IGJ1dHRvbi5pZCkge1xyXG4gICAgICAgICAgICAgICAgLy8gd2UgZGVzZWxlY3QgdGhlIHN0YXJ0aW5nIHBvaW50XHJcbiAgICAgICAgICAgICAgICBidXR0b24uc3R5bGUuYmFja2dyb3VuZEltYWdlID0gYHVybChcImh0dHBzOi8vYXBpLmljb25pZnkuZGVzaWduL21kaTphZGp1c3Quc3ZnP2NvbG9yPWdyZWVuJmhlaWdodD0xNyZ3aWR0aD0xN1wiKWA7XHJcbiAgICAgICAgICAgICAgICB0aGlzLnN0YXJ0U3dlZXBJRCA9IG51bGw7XHJcbiAgICAgICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgYnV0dG9uLnN0eWxlLmJhY2tncm91bmRJbWFnZSA9IGB1cmwoJ2h0dHBzOi8vYXBpLmljb25pZnkuZGVzaWduL2ljL2Jhc2VsaW5lLWZsYWctY2lyY2xlLnN2Zz9jb2xvcj13aGl0ZSZ3aWR0aD0xNyZoZWlnaHQ9MTcnKWA7XHJcbiAgICAgICAgICAgIGlmICghdGhpcy5jaG9zZW5TY2Fuc09uUGxhbi5pbmNsdWRlcyhidXR0b24uaWQpKSB7XHJcbiAgICAgICAgICAgICAgICB0aGlzLmNob3NlblNjYW5zT25QbGFuLnB1c2goYnV0dG9uLmlkKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICBpZiAodGhpcy5zdGFydFN3ZWVwSUQpIHtcclxuICAgICAgICAgICAgICAgIC8vIHdlIGFyZSBjaGFuZ2luZyBzdGFydCBzd2VlcFxyXG4gICAgICAgICAgICAgICAgY29uc3QgYnRuQ2hhbmdlZCA9IHRoaXMuYnV0dG9uRWxlbWVudHMuZmluZCgoYnRuKSA9PiBidG4uaWQgPT09IHRoaXMuc3RhcnRTd2VlcElEKTtcclxuICAgICAgICAgICAgICAgIGJ0bkNoYW5nZWQuc3R5bGUuYmFja2dyb3VuZEltYWdlID0gYHVybChcImh0dHBzOi8vYXBpLmljb25pZnkuZGVzaWduL21kaTphZGp1c3Quc3ZnP2NvbG9yPWdyZWVuJmhlaWdodD0xNyZ3aWR0aD0xN1wiKWA7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgdGhpcy5zdGFydFN3ZWVwSUQgPSBidXR0b24uaWQ7XHJcbiAgICAgICAgICAgIHJldHVybjtcclxuICAgICAgICB9XHJcbiAgICAgICAgaWYgKCF0aGlzLmNob3NlblNjYW5zT25QbGFuLmluY2x1ZGVzKGJ1dHRvbi5pZCkpIHtcclxuICAgICAgICAgICAgLy8gYWRkIHRvIHNlbGVjdGlvblxyXG4gICAgICAgICAgICBidXR0b24uc3R5bGUuYmFja2dyb3VuZEltYWdlID0gYHVybChcImh0dHBzOi8vYXBpLmljb25pZnkuZGVzaWduL21kaTphZGp1c3Quc3ZnP2NvbG9yPWdyZWVuJmhlaWdodD0xNyZ3aWR0aD0xN1wiKWA7XHJcbiAgICAgICAgICAgIHRoaXMuY2hvc2VuU2NhbnNPblBsYW4ucHVzaChidXR0b24uaWQpO1xyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgIC8vIHJlbW92ZSBmcm9tIHNlbGVjdGlvblxyXG4gICAgICAgICAgICBpZiAodGhpcy5vY2N1cGllZFN3ZWVwcy5pbmNsdWRlcyhidXR0b24uaWQpICYmICF0aGlzLm5hdklEc1pvbmVFZGl0LmluY2x1ZGVzKGJ1dHRvbi5pZCkpIHtcclxuICAgICAgICAgICAgICAgIC8vIHRoZSBzd2VlcCBiZWxvbmdzIHRvIGFub3RoZXIgem9uZSA9PiBzZXQgb3JhbmdlXHJcbiAgICAgICAgICAgICAgICBidXR0b24uc3R5bGUuYmFja2dyb3VuZEltYWdlID0gYHVybChcImh0dHBzOi8vYXBpLmljb25pZnkuZGVzaWduL21kaTphZGp1c3Quc3ZnP2NvbG9yPW9yYW5nZSZoZWlnaHQ9MTcmd2lkdGg9MTdcIilgO1xyXG4gICAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgYnV0dG9uLnN0eWxlLmJhY2tncm91bmRJbWFnZSA9IGB1cmwoXCJodHRwczovL2FwaS5pY29uaWZ5LmRlc2lnbi9tZGk6Y2xvc2UtY2lyY2xlLW91dGxpbmUuc3ZnP2NvbG9yPXJlZCZoZWlnaHQ9MTcmd2lkdGg9MTdcIilgO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIGNvbnN0IGluZGV4ID0gdGhpcy5jaG9zZW5TY2Fuc09uUGxhbi5pbmRleE9mKGJ1dHRvbi5pZCk7XHJcbiAgICAgICAgICAgIHRoaXMuY2hvc2VuU2NhbnNPblBsYW4uc3BsaWNlKGluZGV4LCAxKTtcclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgb25TYXZlU2VsZWN0aW9uKCkge1xyXG4gICAgICAgIHRoaXMuc3dlZXBzU2VsZWN0ZWQuZW1pdCh7IFwic3dlZXBzXCI6IHRoaXMuY2hvc2VuU2NhbnNPblBsYW4sIFwic3RhcnRTd2VlcElEXCI6IHRoaXMuc3RhcnRTd2VlcElEIH0pO1xyXG4gICAgfVxyXG5cclxuICAgIG9uQ2FuY2VsKCkge1xyXG4gICAgICAgIHRoaXMuc3dlZXBzU2VsZWN0ZWQuZW1pdChudWxsKTtcclxuICAgIH1cclxufVxyXG4iLCI8ZGl2IG5nYkRyb3Bkb3duIGNsYXNzPVwic3Atcm93IGQtaW5saW5lLWJsb2NrXCI+XHJcbiAgICA8ZGl2IGNsYXNzPVwiY29sLXNtLTNcIiAqbmdJZj1cInBsYW5zXCI+XHJcbiAgICAgICAgICAgIDxidXR0b24gdHlwZT1cImJ1dHRvblwiIGNsYXNzPVwiYnRuIGJ0bi1sYWJlbC1maWxlIHJvdW5kZWQtcGlsbFwiIGlkPVwiZHJvcGRvd25CYXNpYzFcIlxyXG4gICAgICAgICAgICAgICAgbmdiRHJvcGRvd25Ub2dnbGU+e3tjaG9zZW5QbGFuID9cclxuICAgICAgICAgICAgICAgIGNob3NlblBsYW4ubmFtZSA6ICgnQ2hvb3NlIFBsYW4nIHwgdHJhbnNsYXRlKSB9fTwvYnV0dG9uPlxyXG4gICAgICAgICAgICA8ZGl2IG5nYkRyb3Bkb3duTWVudSBhcmlhLWxhYmVsbGVkYnk9XCJkcm9wZG93bkJhc2ljMVwiPlxyXG4gICAgICAgICAgICAgICAgPGJ1dHRvbiB0eXBlPVwiYnV0dG9uXCIgbmdiRHJvcGRvd25JdGVtICpuZ0Zvcj1cImxldCBwbGFuIG9mIHBsYW5zXCIgKGNsaWNrKT1cIm9uUGxhbkNsaWNrKHBsYW4pXCJcclxuICAgICAgICAgICAgICAgICAgICBbZGlzYWJsZWRdPVwiIXBsYW4uY2FsaWJyYXRpb25cIj57eyBwbGFuLm5hbWUgfX1cclxuICAgICAgICAgICAgICAgIDwvYnV0dG9uPlxyXG4gICAgICAgICAgICA8L2Rpdj5cclxuICAgIDwvZGl2PlxyXG48L2Rpdj5cclxuPGRpdiBjbGFzcz1cInNwLXJvd1wiPlxyXG4gICAgPGxpYi1zZWxlY3Rpb24gY2xhc3M9XCJjb2wtbWQtOFwiIChvblNlbGVjdGlvbkNoYW5nZWQpPVwib25TZWxlY3Rpb25DaGFuZ2VkKCRldmVudClcIj5cclxuICAgICAgICA8ZGl2IGNsYXNzPVwic2VsZWN0Wm9uZVwiIG9uY29udGV4dG1lbnU9XCJyZXR1cm4gZmFsc2U7XCI+XHJcbiAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJzcC1yb3dcIj5cclxuICAgICAgICAgICAgICAgIDxkaXYgc3R5bGU9XCJvdmVyZmxvdzogaGlkZGVuO3dpZHRoOjEwMCU7XCI+XHJcbiAgICAgICAgICAgICAgICAgICAgPGRpdiBzdHlsZT1cImhlaWdodDogNDAwcHg7IHdpZHRoOiAxMDAlO1wiIGlkPVwicGxhbkRpdlwiPlxyXG4gICAgICAgICAgICAgICAgICAgIDwvZGl2PlxyXG4gICAgICAgICAgICAgICAgPC9kaXY+XHJcbiAgICAgICAgICAgIDwvZGl2PlxyXG4gICAgICAgIDwvZGl2PlxyXG4gICAgPC9saWItc2VsZWN0aW9uPlxyXG4gICAgXHJcbiAgICA8ZGl2IGNsYXNzPVwiY29sLW1kLTQgc2NhblRvb2xcIiAqbmdJZj1cImJ1dHRvbkVsZW1lbnRzLmxlbmd0aCA+IDBcIj5cclxuICAgICAgICA8ZGl2IGNsYXNzPVwic3Atcm93IGQtaW5saW5lLWJsb2NrXCI+XHJcbiAgICAgICAgICAgIDxoMj57eydzZWxlY3RUb29sLnRpdGxlJyB8IHRyYW5zbGF0ZX19PC9oMj5cclxuICAgICAgICAgICAgPGRpdiBjbGFzcz1cInByb3RpcFwiPnt7J3NlbGVjdFRvb2wudGlwJyB8IHRyYW5zbGF0ZX19LjwvZGl2PlxyXG4gICAgICAgIDwvZGl2PlxyXG4gICAgXHJcbiAgICAgICAgPGRpdiBjbGFzcz1cInNwLXJvd1wiPlxyXG4gICAgICAgICAgICA8ZGl2IGNsYXNzPVwiY29sLTNcIiBzdHlsZT1cInBhZGRpbmc6MHB4XCI+XHJcbiAgICAgICAgICAgICAgICA8bGFiZWwgY2xhc3M9XCJ0b29sLWxhYmVsXCIgZm9yPVwic2NhblNpemVcIj57eydzZWxlY3RUb29sLnNpemUnIHwgdHJhbnNsYXRlfX08L2xhYmVsPlxyXG4gICAgICAgICAgICA8L2Rpdj5cclxuICAgICAgICAgICAgPGRpdiBjbGFzcz1cImNvbC05XCI+XHJcbiAgICAgICAgICAgICAgICA8aW5wdXQgdHlwZT1cInJhbmdlXCIgY2xhc3M9XCJmb3JtLXJhbmdlXCIgbWluPVwiMC4wMDFcIiBtYXg9XCI1XCIgc3RlcD1cIjAuMDFcIiB2YWx1ZT1cIjFcIlxyXG4gICAgICAgICAgICAgICAgICAgIGlkPVwic2NhblNpemVcIiAoaW5wdXQpPVwib25DaGFuZ2VTY2FuU2l6ZSgkZXZlbnQpXCI+XHJcbiAgICAgICAgICAgIDwvZGl2PlxyXG4gICAgICAgIDwvZGl2PlxyXG4gICAgXHJcbiAgICAgICAgPGRpdiBjbGFzcz1cInNwLXJvd1wiPlxyXG4gICAgICAgICAgICA8YnV0dG9uIGNsYXNzPVwiYnRuIGJ0bi1wcmltYXJ5IHJvdW5kZWQtcGlsbFwiIChjbGljayk9XCJvblNlbGVjdEFsbCgpXCI+e3snc2VsZWN0VG9vbC5zZWxlY3RBbGwnIHwgdHJhbnNsYXRlfX08L2J1dHRvbj5cclxuICAgICAgICA8L2Rpdj5cclxuICAgIFxyXG4gICAgICAgIDxkaXYgKm5nSWY9XCJidXR0b25zSW5TZWxlY3Rpb24ubGVuZ3RoID4gMFwiIGNsYXNzPVwiZWRpdC1zZWxlY3RlZFwiPlxyXG4gICAgICAgICAgICA8c3BhbiBjbGFzcz1cInRvb2wtbGFiZWxcIj57eydzZWxlY3RUb29sLmVkaXQnIHwgdHJhbnNsYXRlfX0gOiA8L3NwYW4+XHJcbiAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJzcC1yb3dcIj5cclxuICAgICAgICAgICAgICAgIDxidXR0b24gY2xhc3M9XCJidG4gcm91bmRlZC1waWxsIGJ0bi1wcmltYXJ5IG1zLTMgbWUtMlwiIChjbGljayk9XCJvblNlbGVjdGlvbkFkZCgpXCI+e3snc2VsZWN0VG9vbC5hZGQnIHwgdHJhbnNsYXRlfX08L2J1dHRvbj5cclxuICAgICAgICAgICAgICAgIDxidXR0b24gY2xhc3M9XCJidG4gYnRuLXByaW1hcnkgcm91bmRlZC1waWxsXCIgKGNsaWNrKT1cIm9uU2VsZWN0aW9uUmVtb3ZlKClcIj57eydzZWxlY3RUb29sLnVuZG8nIHwgdHJhbnNsYXRlfX08L2J1dHRvbj5cclxuICAgICAgICAgICAgPC9kaXY+XHJcbiAgICAgICAgPC9kaXY+XHJcblxyXG4gICAgICAgIDxkaXYgY2xhc3M9XCJzcC1yb3dcIj5cclxuICAgICAgICAgICAge3sgY2hvc2VuU2NhbnNPblBsYW4ubGVuZ3RoIH19IHt7J3NjYW4gcG9pbnRzIGNob3NlbicgfCB0cmFuc2xhdGV9fSAgICAgICAgIFxyXG4gICAgICAgIDwvZGl2PlxyXG4gICAgICAgIDxkaXYgKm5nSWY9XCIhZWRpdGluZ0F1ZGlvWm9uZVwiIGNsYXNzPVwic3Atcm93XCI+XHJcbiAgICAgICAgICAgIDxsaWItcmFkaW8tYnV0dG9uICBsYWJlbD1cInt7ICdzZWxlY3RUb29sLmNob29zZVN0YXJ0UG9pbnQnICB8IHRyYW5zbGF0ZSB9fVwiIChpc0NoZWNrZWRFdmVudCk9XCJpc1NldHRpbmdTdGFydFN3ZWVwPSFpc1NldHRpbmdTdGFydFN3ZWVwXCI+PC9saWItcmFkaW8tYnV0dG9uPlxyXG4gICAgICAgIDwvZGl2PlxyXG4gICAgICAgIFxyXG4gICAgICAgIDxkaXYgY2xhc3M9XCJzcC1yb3dcIj5cclxuICAgICAgICAgICAgPGJ1dHRvbiBjbGFzcz1cImJ0biBidG4tcHJpbWFyeSByb3VuZGVkLXBpbGxcIiAoY2xpY2spPVwib25TYXZlU2VsZWN0aW9uKClcIj57eydzZWxlY3RUb29sLnNhdmVTZWxlY3Rpb24nIHwgdHJhbnNsYXRlfX08L2J1dHRvbj5cclxuICAgICAgICAgICAgPGJ1dHRvbiBjbGFzcz1cImJ0biBidG4tb3V0bGluZS1wcmltYXJ5IHJvdW5kZWQtcGlsbFwiIChjbGljayk9XCJvbkNhbmNlbCgpXCI+e3snc2VsZWN0VG9vbC5jYW5jZWxTZWxlY3Rpb24nIHwgdHJhbnNsYXRlfX08L2J1dHRvbj5cclxuICAgICAgICA8L2Rpdj5cclxuICAgIDwvZGl2PlxyXG5cclxuPC9kaXY+XHJcbiAgIFxyXG4iXX0=