@smarterplan/ngx-smarterplan-locations 0.2.44 → 0.2.45
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.
- package/esm2020/lib/components/carousel/carousel.component.mjs +28 -0
- package/esm2020/lib/components/chevron/chevron.component.mjs +18 -0
- package/esm2020/lib/components/detail-location/detail-location.component.mjs +168 -0
- package/esm2020/lib/components/form-location/form-location.component.mjs +237 -0
- package/esm2020/lib/components/images/images.component.mjs +107 -0
- package/esm2020/lib/components/locations/locations.component.mjs +145 -0
- package/esm2020/lib/components/locations/map/map-popup/map-popup.component.mjs +66 -0
- package/esm2020/lib/components/locations/map/map.component.mjs +91 -0
- package/esm2020/lib/components/plan-legend/plan-legend.component.mjs +47 -0
- package/esm2020/lib/components/plans/calibration/calibration.component.mjs +468 -0
- package/esm2020/lib/components/plans/edit-plan/edit-plan.component.mjs +324 -0
- package/esm2020/lib/components/plans/plans.component.mjs +225 -0
- package/esm2020/lib/components/tab-navigation/tab-navigation.component.mjs +41 -0
- package/esm2020/lib/components/visits/visits.component.mjs +283 -0
- package/esm2020/lib/components/zones/add-audio-zone/add-audio-zone.component.mjs +230 -0
- package/esm2020/lib/components/zones/add-zone/add-zone.component.mjs +315 -0
- package/esm2020/lib/components/zones/add-zone/selection/selection.component.mjs +77 -0
- package/esm2020/lib/components/zones/add-zone/sweep-plan-selection/sweep-plan-selection.component.mjs +502 -0
- package/esm2020/lib/components/zones/zones.component.mjs +268 -0
- package/esm2020/lib/helper.service.mjs +134 -0
- package/esm2020/lib/ngx-smarterplan-location-routing.module.mjs +49 -0
- package/esm2020/lib/ngx-smarterplan-locations.module.mjs +125 -0
- package/esm2020/lib/ngx-smarterplan-locations.service.mjs +14 -0
- package/esm2020/lib/pipes/count-audio-sweeps.pipe.mjs +27 -0
- package/esm2020/lib/radio-button/radio-button.component.mjs +26 -0
- package/esm2020/public-api.mjs +9 -0
- package/esm2020/smarterplan-ngx-smarterplan-locations.mjs +5 -0
- package/fesm2015/smarterplan-ngx-smarterplan-locations.mjs +3991 -0
- package/fesm2015/smarterplan-ngx-smarterplan-locations.mjs.map +1 -0
- package/fesm2020/smarterplan-ngx-smarterplan-locations.mjs +3828 -0
- package/fesm2020/smarterplan-ngx-smarterplan-locations.mjs.map +1 -0
- package/lib/components/carousel/carousel.component.d.ts +12 -0
- package/lib/components/chevron/chevron.component.d.ts +9 -0
- package/lib/components/detail-location/detail-location.component.d.ts +55 -0
- package/lib/components/form-location/form-location.component.d.ts +45 -0
- package/lib/components/images/images.component.d.ts +33 -0
- package/lib/components/locations/locations.component.d.ts +51 -0
- package/lib/components/locations/map/map-popup/map-popup.component.d.ts +22 -0
- package/lib/components/locations/map/map.component.d.ts +22 -0
- package/lib/components/plan-legend/plan-legend.component.d.ts +14 -0
- package/lib/components/plans/calibration/calibration.component.d.ts +140 -0
- package/lib/components/plans/edit-plan/edit-plan.component.d.ts +55 -0
- package/lib/components/plans/plans.component.d.ts +63 -0
- package/lib/components/tab-navigation/tab-navigation.component.d.ts +13 -0
- package/lib/components/visits/visits.component.d.ts +62 -0
- package/lib/components/zones/add-audio-zone/add-audio-zone.component.d.ts +63 -0
- package/lib/components/zones/add-zone/add-zone.component.d.ts +69 -0
- package/lib/components/zones/add-zone/selection/selection.component.d.ts +44 -0
- package/lib/components/zones/add-zone/sweep-plan-selection/sweep-plan-selection.component.d.ts +107 -0
- package/lib/components/zones/zones.component.d.ts +73 -0
- package/lib/helper.service.d.ts +53 -0
- package/lib/ngx-smarterplan-location-routing.module.d.ts +7 -0
- package/lib/ngx-smarterplan-locations.module.d.ts +36 -0
- package/lib/ngx-smarterplan-locations.service.d.ts +6 -0
- package/lib/pipes/count-audio-sweeps.pipe.d.ts +10 -0
- package/lib/radio-button/radio-button.component.d.ts +12 -0
- package/package.json +22 -5
- package/{src/public-api.ts → public-api.d.ts} +4 -11
- package/smarterplan-ngx-smarterplan-locations.d.ts +5 -0
- package/.browserslistrc +0 -16
- package/karma.conf.js +0 -44
- package/ng-package.json +0 -7
- package/src/lib/components/carousel/carousel.component.html +0 -13
- package/src/lib/components/carousel/carousel.component.scss +0 -0
- package/src/lib/components/carousel/carousel.component.spec.ts +0 -25
- package/src/lib/components/carousel/carousel.component.ts +0 -31
- package/src/lib/components/chevron/chevron.component.html +0 -5
- package/src/lib/components/chevron/chevron.component.scss +0 -16
- package/src/lib/components/chevron/chevron.component.spec.ts +0 -25
- package/src/lib/components/chevron/chevron.component.ts +0 -17
- package/src/lib/components/detail-location/detail-location.component.html +0 -108
- package/src/lib/components/detail-location/detail-location.component.scss +0 -0
- package/src/lib/components/detail-location/detail-location.component.spec.ts +0 -25
- package/src/lib/components/detail-location/detail-location.component.ts +0 -215
- package/src/lib/components/form-location/form-location.component.html +0 -160
- package/src/lib/components/form-location/form-location.component.scss +0 -62
- package/src/lib/components/form-location/form-location.component.spec.ts +0 -25
- package/src/lib/components/form-location/form-location.component.ts +0 -274
- package/src/lib/components/images/images.component.html +0 -27
- package/src/lib/components/images/images.component.scss +0 -0
- package/src/lib/components/images/images.component.spec.ts +0 -25
- package/src/lib/components/images/images.component.ts +0 -133
- package/src/lib/components/locations/locations.component.html +0 -63
- package/src/lib/components/locations/locations.component.scss +0 -121
- package/src/lib/components/locations/locations.component.spec.ts +0 -25
- package/src/lib/components/locations/locations.component.ts +0 -186
- package/src/lib/components/locations/map/map-popup/map-popup.component.html +0 -11
- package/src/lib/components/locations/map/map-popup/map-popup.component.scss +0 -51
- package/src/lib/components/locations/map/map-popup/map-popup.component.spec.ts +0 -25
- package/src/lib/components/locations/map/map-popup/map-popup.component.ts +0 -79
- package/src/lib/components/locations/map/map.component.html +0 -2
- package/src/lib/components/locations/map/map.component.scss +0 -0
- package/src/lib/components/locations/map/map.component.spec.ts +0 -25
- package/src/lib/components/locations/map/map.component.ts +0 -111
- package/src/lib/components/plan-legend/plan-legend.component.html +0 -9
- package/src/lib/components/plan-legend/plan-legend.component.scss +0 -38
- package/src/lib/components/plan-legend/plan-legend.component.spec.ts +0 -25
- package/src/lib/components/plan-legend/plan-legend.component.ts +0 -50
- package/src/lib/components/plans/calibration/calibration.component.html +0 -98
- package/src/lib/components/plans/calibration/calibration.component.scss +0 -136
- package/src/lib/components/plans/calibration/calibration.component.spec.ts +0 -25
- package/src/lib/components/plans/calibration/calibration.component.ts +0 -603
- package/src/lib/components/plans/edit-plan/edit-plan.component.html +0 -77
- package/src/lib/components/plans/edit-plan/edit-plan.component.scss +0 -9
- package/src/lib/components/plans/edit-plan/edit-plan.component.spec.ts +0 -25
- package/src/lib/components/plans/edit-plan/edit-plan.component.ts +0 -421
- package/src/lib/components/plans/plans.component.html +0 -102
- package/src/lib/components/plans/plans.component.scss +0 -24
- package/src/lib/components/plans/plans.component.spec.ts +0 -25
- package/src/lib/components/plans/plans.component.ts +0 -305
- package/src/lib/components/tab-navigation/tab-navigation.component.html +0 -7
- package/src/lib/components/tab-navigation/tab-navigation.component.scss +0 -27
- package/src/lib/components/tab-navigation/tab-navigation.component.spec.ts +0 -25
- package/src/lib/components/tab-navigation/tab-navigation.component.ts +0 -35
- package/src/lib/components/visits/visits.component.html +0 -134
- package/src/lib/components/visits/visits.component.scss +0 -24
- package/src/lib/components/visits/visits.component.spec.ts +0 -25
- package/src/lib/components/visits/visits.component.ts +0 -357
- package/src/lib/components/zones/add-audio-zone/add-audio-zone.component.html +0 -73
- package/src/lib/components/zones/add-audio-zone/add-audio-zone.component.scss +0 -14
- package/src/lib/components/zones/add-audio-zone/add-audio-zone.component.spec.ts +0 -25
- package/src/lib/components/zones/add-audio-zone/add-audio-zone.component.ts +0 -269
- package/src/lib/components/zones/add-zone/add-zone.component.html +0 -153
- package/src/lib/components/zones/add-zone/add-zone.component.scss +0 -44
- package/src/lib/components/zones/add-zone/add-zone.component.spec.ts +0 -25
- package/src/lib/components/zones/add-zone/add-zone.component.ts +0 -377
- package/src/lib/components/zones/add-zone/selection/selection.component.html +0 -3
- package/src/lib/components/zones/add-zone/selection/selection.component.scss +0 -16
- package/src/lib/components/zones/add-zone/selection/selection.component.spec.ts +0 -25
- package/src/lib/components/zones/add-zone/selection/selection.component.ts +0 -95
- package/src/lib/components/zones/add-zone/sweep-plan-selection/sweep-plan-selection.component.html +0 -73
- package/src/lib/components/zones/add-zone/sweep-plan-selection/sweep-plan-selection.component.scss +0 -23
- package/src/lib/components/zones/add-zone/sweep-plan-selection/sweep-plan-selection.component.spec.ts +0 -25
- package/src/lib/components/zones/add-zone/sweep-plan-selection/sweep-plan-selection.component.ts +0 -595
- package/src/lib/components/zones/zones.component.html +0 -181
- package/src/lib/components/zones/zones.component.scss +0 -36
- package/src/lib/components/zones/zones.component.spec.ts +0 -25
- package/src/lib/components/zones/zones.component.ts +0 -339
- package/src/lib/helper.service.ts +0 -161
- package/src/lib/ngx-smarterplan-location-routing.module.ts +0 -41
- package/src/lib/ngx-smarterplan-locations.module.ts +0 -74
- package/src/lib/ngx-smarterplan-locations.service.spec.ts +0 -16
- package/src/lib/ngx-smarterplan-locations.service.ts +0 -9
- package/src/lib/pipes/count-audio-sweeps.pipe.ts +0 -21
- package/src/lib/radio-button/radio-button.component.html +0 -9
- package/src/lib/radio-button/radio-button.component.scss +0 -152
- package/src/lib/radio-button/radio-button.component.spec.ts +0 -25
- package/src/lib/radio-button/radio-button.component.ts +0 -26
- package/src/test.ts +0 -27
- package/tsconfig.lib.json +0 -15
- package/tsconfig.lib.prod.json +0 -10
- package/tsconfig.spec.json +0 -17
|
@@ -0,0 +1,502 @@
|
|
|
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 "@ngx-translate/core";
|
|
8
|
+
import * as i3 from "../selection/selection.component";
|
|
9
|
+
import * as i4 from "../../../plan-legend/plan-legend.component";
|
|
10
|
+
import * as i5 from "../../../../radio-button/radio-button.component";
|
|
11
|
+
import * as i6 from "@ng-bootstrap/ng-bootstrap";
|
|
12
|
+
import * as i7 from "@angular/common";
|
|
13
|
+
export class SweepPlanSelectionComponent {
|
|
14
|
+
constructor(zoneService, navigationService, planService, translate) {
|
|
15
|
+
this.zoneService = zoneService;
|
|
16
|
+
this.navigationService = navigationService;
|
|
17
|
+
this.planService = planService;
|
|
18
|
+
this.translate = translate;
|
|
19
|
+
this.chosenScansOnPlan = [];
|
|
20
|
+
this.navIDsZoneEdit = [];
|
|
21
|
+
// sweeps belonging to any audio zone
|
|
22
|
+
this.occupiedSweeps = [];
|
|
23
|
+
// sweeps unavailable (cannot be chosen)
|
|
24
|
+
this.unavailableSweeps = [];
|
|
25
|
+
// if choosing sweeps for audio zone
|
|
26
|
+
this.editingAudioZone = false;
|
|
27
|
+
this.multipleFloors = false;
|
|
28
|
+
/** all scan buttons Element */
|
|
29
|
+
this.buttonElements = [];
|
|
30
|
+
/** Scan buttons that are in the current selection */
|
|
31
|
+
this.buttonsInSelection = [];
|
|
32
|
+
this.sweepsSelected = new EventEmitter();
|
|
33
|
+
this.isSettingStartSweep = false;
|
|
34
|
+
this.chosenSweepsPerFloor = new Map(); // map matching floorID to sweeps selected
|
|
35
|
+
this.inputSweepsPerFloor = new Map(); // map matching floorID to sweeps selected for zone in edition
|
|
36
|
+
this.selectionChanged = false;
|
|
37
|
+
}
|
|
38
|
+
async ngOnInit() {
|
|
39
|
+
await this.getPlans();
|
|
40
|
+
this.setSweepsOfInputZone();
|
|
41
|
+
}
|
|
42
|
+
ngOnChanges() {
|
|
43
|
+
if (this.chosenPlan) {
|
|
44
|
+
this.setSweepsOfInputZone();
|
|
45
|
+
this.chosenScansOnPlan = [];
|
|
46
|
+
this.clearDivPlan();
|
|
47
|
+
this.addScanPoints();
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
setSweepsOfInputZone() {
|
|
51
|
+
this.navIDsZoneEdit = this.inputZone ? this.inputZone.sweepIDs : [];
|
|
52
|
+
if (this.multipleFloors) {
|
|
53
|
+
this.plans.forEach((plan) => {
|
|
54
|
+
if (!this.inputSweepsPerFloor.get(plan.zoneID)) {
|
|
55
|
+
this.inputSweepsPerFloor.set(plan.zoneID, this.navIDsZoneEdit.filter((sweep) => plan.zone.sweepIDs.includes(sweep)));
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
else {
|
|
60
|
+
if (this.inputZone) {
|
|
61
|
+
//filter plans only for the parent Zone
|
|
62
|
+
this.plans = this.plans.filter((p) => p.zoneID === this.inputZone.parentID);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
async getPlans() {
|
|
67
|
+
this.plans = await this.planService.getSingedPlansForSpace(this.spaceID);
|
|
68
|
+
}
|
|
69
|
+
async onPlanClick(plan) {
|
|
70
|
+
const switchPlan = () => {
|
|
71
|
+
this.selectionChanged = false;
|
|
72
|
+
this.chosenPlan = plan;
|
|
73
|
+
this.chosenScansOnPlan = [];
|
|
74
|
+
this.clearDivPlan();
|
|
75
|
+
this.addScanPoints();
|
|
76
|
+
};
|
|
77
|
+
if (this.selectionChanged) {
|
|
78
|
+
const message = this.translate.instant("confirm.cancelModifZoneSweeps");
|
|
79
|
+
if (window.confirm(message)) {
|
|
80
|
+
switchPlan();
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
else {
|
|
84
|
+
switchPlan();
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
async addScanPoints() {
|
|
88
|
+
let wasModified = false;
|
|
89
|
+
if (this.multipleFloors) {
|
|
90
|
+
// check if we have already validated buttons for this floor
|
|
91
|
+
if (this.chosenSweepsPerFloor.get(this.chosenPlan.zoneID)) {
|
|
92
|
+
this.chosenScansOnPlan = this.chosenSweepsPerFloor.get(this.chosenPlan.zoneID);
|
|
93
|
+
wasModified = true;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
this.divPlan = document.querySelector("#planDiv");
|
|
97
|
+
const zoneOfPlan = await this.zoneService.getZone(this.chosenPlan.zoneID);
|
|
98
|
+
const navigations = await this.navigationService.getNavigationsForZone(zoneOfPlan);
|
|
99
|
+
if (this.newZoneData)
|
|
100
|
+
await this.setScanByDraw(navigations);
|
|
101
|
+
this.buttonElements = await showScanPointsOnPlanInDiv(this.chosenPlan, this.divPlan, navigations);
|
|
102
|
+
for (const element of this.buttonElements) {
|
|
103
|
+
if (this.unavailableSweeps && this.unavailableSweeps.includes(element.id)) {
|
|
104
|
+
styleButton(element, SweepState.DISABLED);
|
|
105
|
+
}
|
|
106
|
+
else {
|
|
107
|
+
if (wasModified) {
|
|
108
|
+
if (this.chosenScansOnPlan.includes(element.id)) {
|
|
109
|
+
styleButton(element, SweepState.ADDED);
|
|
110
|
+
}
|
|
111
|
+
else {
|
|
112
|
+
styleButton(element, SweepState.REMOVED);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
else {
|
|
116
|
+
if (this.navIDsZoneEdit.length > 0 &&
|
|
117
|
+
this.navIDsZoneEdit.includes(element.id)) {
|
|
118
|
+
styleButton(element, SweepState.ADDED);
|
|
119
|
+
if (!this.chosenScansOnPlan.includes(element.id)) {
|
|
120
|
+
this.chosenScansOnPlan.push(element.id);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
else if (this.occupiedSweeps && this.occupiedSweeps.includes(element.id)) {
|
|
124
|
+
styleButton(element, SweepState.OCCUPIED);
|
|
125
|
+
}
|
|
126
|
+
else {
|
|
127
|
+
styleButton(element, SweepState.REMOVED);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
//start point should be last condition
|
|
131
|
+
if (this.inputZone && this.inputZone.startSweepID === element.id) {
|
|
132
|
+
console.log("setting start point");
|
|
133
|
+
styleButton(element, SweepState.STARTPOINT);
|
|
134
|
+
}
|
|
135
|
+
element.addEventListener("click", (event) => this.onButtonScanClicked(event.target));
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
this.panZoom = panzoom(this.divPlan, {
|
|
139
|
+
bounds: true,
|
|
140
|
+
boundsPadding: 0,
|
|
141
|
+
maxZoom: 3.5,
|
|
142
|
+
beforeMouseDown(e) {
|
|
143
|
+
return (e.button === 2); /** Ignore event for right click (use for selecting) */
|
|
144
|
+
},
|
|
145
|
+
});
|
|
146
|
+
if (this.multipleFloors) {
|
|
147
|
+
this.chosenSweepsPerFloor.set(this.chosenPlan.zoneID, [...this.chosenScansOnPlan]);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
/** Function if we are coming for svg editor workflow */
|
|
151
|
+
setScanByDraw(navigations) {
|
|
152
|
+
return new Promise(async (resolve) => {
|
|
153
|
+
const rect = {
|
|
154
|
+
width: this.newZoneData.width,
|
|
155
|
+
height: this.newZoneData.height,
|
|
156
|
+
};
|
|
157
|
+
const img = await getMetaForImage(this.chosenPlan.filepath);
|
|
158
|
+
const { coeffX, coeffY } = getCoefficientsForImage(img, rect);
|
|
159
|
+
const draw = this.newZoneData.elements;
|
|
160
|
+
draw.map(async (element) => {
|
|
161
|
+
switch (element.nodeName) {
|
|
162
|
+
case "rect":
|
|
163
|
+
await this.setScanInRect(img, coeffX, coeffY, element, navigations);
|
|
164
|
+
break;
|
|
165
|
+
case "ellipse":
|
|
166
|
+
await this.setScanInCircle(img, coeffX, coeffY, element, navigations);
|
|
167
|
+
break;
|
|
168
|
+
case "path":
|
|
169
|
+
await this.setScanInPolygon(img, coeffX, coeffY, element, navigations);
|
|
170
|
+
break;
|
|
171
|
+
default:
|
|
172
|
+
break;
|
|
173
|
+
}
|
|
174
|
+
});
|
|
175
|
+
resolve();
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
async setScanInRect(img, coeffX, coeffY, element, navigations) {
|
|
179
|
+
const calibrage = JSON.parse(this.chosenPlan.calibration);
|
|
180
|
+
navigations.map((navigation) => {
|
|
181
|
+
const positionsOnPlan = navigation.positionOnPlan.map((entry) => JSON.parse(entry));
|
|
182
|
+
const positionOnPlan = positionsOnPlan.find((data) => data.planID === this.chosenPlan.id);
|
|
183
|
+
if (positionOnPlan) {
|
|
184
|
+
const realWidth = img.width / coeffX;
|
|
185
|
+
const realHeight = img.height / coeffY;
|
|
186
|
+
const navY = (positionOnPlan.y * realHeight) / calibrage.imgHeight;
|
|
187
|
+
const navX = (positionOnPlan.x * realWidth) / calibrage.imgWidth;
|
|
188
|
+
if (navX > element.x &&
|
|
189
|
+
navX < element.x + element.width &&
|
|
190
|
+
navY > element.y &&
|
|
191
|
+
navY < element.y + element.height &&
|
|
192
|
+
!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
|
+
/**
|
|
210
|
+
* TODO calculer la rotation du rectangle
|
|
211
|
+
*/
|
|
212
|
+
// if (
|
|
213
|
+
// navX > element.x &&
|
|
214
|
+
// navX < element.x + element.width &&
|
|
215
|
+
// navY > element.y &&
|
|
216
|
+
// navY < element.y + element.height &&
|
|
217
|
+
// !this.navIDsZoneEdit.includes(navigation.id)
|
|
218
|
+
// ) {
|
|
219
|
+
// this.navIDsZoneEdit.push(navigation.id);
|
|
220
|
+
// }
|
|
221
|
+
});
|
|
222
|
+
} // EO
|
|
223
|
+
async setScanInCircle(img, coeffX, coeffY, element, navigations) {
|
|
224
|
+
const calibrage = JSON.parse(this.chosenPlan.calibration);
|
|
225
|
+
navigations.map(navigation => {
|
|
226
|
+
const positionsOnPlan = navigation.positionOnPlan.map((entry) => JSON.parse(entry));
|
|
227
|
+
const positionOnPlan = positionsOnPlan.find((data) => data.planID === this.chosenPlan.id);
|
|
228
|
+
if (positionOnPlan) {
|
|
229
|
+
const realWidth = img.width / coeffX;
|
|
230
|
+
const realHeight = img.height / coeffY;
|
|
231
|
+
let navY = (positionOnPlan.y * realHeight) / calibrage.imgHeight;
|
|
232
|
+
let navX = (positionOnPlan.x * realWidth) / calibrage.imgWidth;
|
|
233
|
+
if (element.angle) {
|
|
234
|
+
const rotatePos = rotate({ x: navX, y: navY }, { x: element.cx, y: element.cy }, element.angle);
|
|
235
|
+
navX = rotatePos.x;
|
|
236
|
+
navY = rotatePos.y;
|
|
237
|
+
}
|
|
238
|
+
const valueX = Math.pow(navX - element.cx, 2) / Math.pow(element.rx, 2);
|
|
239
|
+
const valueY = Math.pow(navY - element.cy, 2) / Math.pow(element.ry, 2);
|
|
240
|
+
const result = valueX + valueY;
|
|
241
|
+
if (result <= 1 && !this.navIDsZoneEdit.includes(navigation.id)) {
|
|
242
|
+
this.navIDsZoneEdit.push(navigation.id);
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
// old calibration
|
|
246
|
+
// const position = JSON.parse(navigation.position);
|
|
247
|
+
// let navX = (calibrage.offsetX + position.x * calibrage.x) / coeffX;
|
|
248
|
+
// let navY = (calibrage.offsetY + position.z * calibrage.y) / coeffY;
|
|
249
|
+
// if (element.angle) {
|
|
250
|
+
// const rotatePos = rotate(
|
|
251
|
+
// { x: navX, y: navY },
|
|
252
|
+
// { x: element.cx, y: element.cy },
|
|
253
|
+
// element.angle,
|
|
254
|
+
// );
|
|
255
|
+
// navX = rotatePos.x;
|
|
256
|
+
// navY = rotatePos.y;
|
|
257
|
+
// }
|
|
258
|
+
// const valueX =
|
|
259
|
+
// Math.pow(navX - element.cx, 2) / Math.pow(element.rx, 2);
|
|
260
|
+
// const valueY =
|
|
261
|
+
// Math.pow(navY - element.cy, 2) / Math.pow(element.ry, 2);
|
|
262
|
+
// const result = valueX + valueY;
|
|
263
|
+
// if (result <= 1 && !this.navIDsZoneEdit.includes(navigation.id)) {
|
|
264
|
+
// this.navIDsZoneEdit.push(navigation.id);
|
|
265
|
+
// }
|
|
266
|
+
});
|
|
267
|
+
} // EO
|
|
268
|
+
async setScanInPolygon(img, coeffX, coeffY, element, navigations) {
|
|
269
|
+
const calibrage = JSON.parse(this.chosenPlan.calibration);
|
|
270
|
+
navigations.map(async (navigation) => {
|
|
271
|
+
const positionsOnPlan = navigation.positionOnPlan.map((entry) => JSON.parse(entry));
|
|
272
|
+
const positionOnPlan = positionsOnPlan.find((data) => data.planID === this.chosenPlan.id);
|
|
273
|
+
if (positionOnPlan) {
|
|
274
|
+
const realWidth = img.width / coeffX;
|
|
275
|
+
const realHeight = img.height / coeffY;
|
|
276
|
+
let navY = (positionOnPlan.y * realHeight) / calibrage.imgHeight;
|
|
277
|
+
let navX = (positionOnPlan.x * realWidth) / calibrage.imgWidth;
|
|
278
|
+
const p = {
|
|
279
|
+
x: navX,
|
|
280
|
+
y: navY,
|
|
281
|
+
};
|
|
282
|
+
if (isInPolygon(p, element.segList) &&
|
|
283
|
+
!this.navIDsZoneEdit.includes(navigation.id)) {
|
|
284
|
+
this.navIDsZoneEdit.push(navigation.id);
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
// old calibration
|
|
288
|
+
// const position = JSON.parse(navigation.position);
|
|
289
|
+
// const p = {
|
|
290
|
+
// x: (calibrage.offsetX + position.x * calibrage.x) / coeffX,
|
|
291
|
+
// y: (calibrage.offsetY + position.z * calibrage.y) / coeffY,
|
|
292
|
+
// };
|
|
293
|
+
// if (element.angle) {
|
|
294
|
+
// p = this.rotate(
|
|
295
|
+
// p,
|
|
296
|
+
// { x: element.cx, y: element.cy },
|
|
297
|
+
// element.angle,
|
|
298
|
+
// );
|
|
299
|
+
// }
|
|
300
|
+
// if (
|
|
301
|
+
// isInPolygon(p, element.segList) &&
|
|
302
|
+
// !this.navIDsZoneEdit.includes(navigation.id)
|
|
303
|
+
// ) {
|
|
304
|
+
// this.navIDsZoneEdit.push(navigation.id);
|
|
305
|
+
// }
|
|
306
|
+
});
|
|
307
|
+
}
|
|
308
|
+
clearDivPlan() {
|
|
309
|
+
if (this.divPlan)
|
|
310
|
+
this.divPlan.innerHTML = "";
|
|
311
|
+
}
|
|
312
|
+
/**
|
|
313
|
+
* Trigger each by the selectionComponent when selection change
|
|
314
|
+
* Update the current selected scan buttons
|
|
315
|
+
* @param selection new selection
|
|
316
|
+
*/
|
|
317
|
+
onSelectionChanged(selection) {
|
|
318
|
+
const unselectedButtons = [];
|
|
319
|
+
const newSelectedButtons = [];
|
|
320
|
+
/** For each button, decide whether will be add to selected list or unselected list */
|
|
321
|
+
for (const button of this.buttonElements) {
|
|
322
|
+
const isSelected = buttonIsInSelection(button, selection);
|
|
323
|
+
if (this.buttonsInSelection.includes(button)) {
|
|
324
|
+
/** If the button is already in the selected list, we check if it should be unselect */
|
|
325
|
+
if (!isSelected) {
|
|
326
|
+
unselectedButtons.push(button);
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
else if (isSelected) {
|
|
330
|
+
newSelectedButtons.push(button);
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
/** Visually Update unselected list */
|
|
334
|
+
for (const button of unselectedButtons) {
|
|
335
|
+
setVisuallySelected(button, false);
|
|
336
|
+
}
|
|
337
|
+
/** Visually Update selected list */
|
|
338
|
+
for (const button of newSelectedButtons) {
|
|
339
|
+
setVisuallySelected(button, true);
|
|
340
|
+
}
|
|
341
|
+
/** Remove unselected list */
|
|
342
|
+
this.buttonsInSelection = this.buttonsInSelection.filter((button) => {
|
|
343
|
+
return !unselectedButtons.includes(button);
|
|
344
|
+
});
|
|
345
|
+
/** Add new selected buttons */
|
|
346
|
+
this.buttonsInSelection = [
|
|
347
|
+
...this.buttonsInSelection,
|
|
348
|
+
...newSelectedButtons,
|
|
349
|
+
];
|
|
350
|
+
}
|
|
351
|
+
/**
|
|
352
|
+
* Trigger when the user click to add the selected scans
|
|
353
|
+
*/
|
|
354
|
+
onSelectionAdd() {
|
|
355
|
+
for (const button of this.buttonsInSelection) {
|
|
356
|
+
if (!this.chosenScansOnPlan.includes(button.id)) {
|
|
357
|
+
this.onButtonScanClicked(button);
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
this.onSelectionChanged({ top: 0, left: 0, width: 0, height: 0 });
|
|
361
|
+
}
|
|
362
|
+
/**
|
|
363
|
+
* Trigger when the user click to remove the selected scans
|
|
364
|
+
*/
|
|
365
|
+
onSelectionRemove() {
|
|
366
|
+
for (const button of this.buttonsInSelection) {
|
|
367
|
+
if (this.chosenScansOnPlan.includes(button.id)) {
|
|
368
|
+
this.onButtonScanClicked(button);
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
this.onSelectionChanged({ top: 0, left: 0, width: 0, height: 0 });
|
|
372
|
+
}
|
|
373
|
+
/**
|
|
374
|
+
* Trigger when the user click to select all scans
|
|
375
|
+
*/
|
|
376
|
+
onSelectAll() {
|
|
377
|
+
this.buttonsInSelection = [...this.buttonElements];
|
|
378
|
+
for (const button of this.buttonsInSelection) {
|
|
379
|
+
setVisuallySelected(button, true);
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
/**
|
|
383
|
+
* Trigger when the user change the size of the scan points
|
|
384
|
+
* @param event
|
|
385
|
+
*/
|
|
386
|
+
onChangeScanSize(event) {
|
|
387
|
+
const factor = event.target.value;
|
|
388
|
+
for (const button of this.buttonElements) {
|
|
389
|
+
button.style.transform = `scale(${factor})`;
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
/**
|
|
393
|
+
* When a button representing a scan is clicked
|
|
394
|
+
* @param button
|
|
395
|
+
*/
|
|
396
|
+
onButtonScanClicked(button) {
|
|
397
|
+
this.selectionChanged = true;
|
|
398
|
+
if (this.isSettingStartSweep) {
|
|
399
|
+
if (this.startSweepID === button.id) {
|
|
400
|
+
// we deselect the starting point
|
|
401
|
+
button.style.backgroundImage = `url("https://api.iconify.design/mdi:adjust.svg?color=green&height=17&width=17")`;
|
|
402
|
+
this.startSweepID = null;
|
|
403
|
+
return;
|
|
404
|
+
}
|
|
405
|
+
button.style.backgroundImage = `url('https://api.iconify.design/ic/baseline-flag-circle.svg?color=white&width=17&height=17')`;
|
|
406
|
+
if (!this.chosenScansOnPlan.includes(button.id)) {
|
|
407
|
+
this.chosenScansOnPlan.push(button.id);
|
|
408
|
+
}
|
|
409
|
+
if (this.startSweepID) {
|
|
410
|
+
// we are changing start sweep
|
|
411
|
+
const btnChanged = this.buttonElements.find((btn) => btn.id === this.startSweepID);
|
|
412
|
+
btnChanged.style.backgroundImage = `url("https://api.iconify.design/mdi:adjust.svg?color=green&height=17&width=17")`;
|
|
413
|
+
}
|
|
414
|
+
this.startSweepID = button.id;
|
|
415
|
+
return;
|
|
416
|
+
}
|
|
417
|
+
if (!this.chosenScansOnPlan.includes(button.id)) {
|
|
418
|
+
// add to selection
|
|
419
|
+
button.style.backgroundImage = `url("https://api.iconify.design/mdi:adjust.svg?color=green&height=17&width=17")`;
|
|
420
|
+
this.chosenScansOnPlan.push(button.id);
|
|
421
|
+
}
|
|
422
|
+
else {
|
|
423
|
+
// remove from selection
|
|
424
|
+
if (this.occupiedSweeps.includes(button.id) && !this.navIDsZoneEdit.includes(button.id)) {
|
|
425
|
+
// the sweep belongs to another zone => set orange
|
|
426
|
+
button.style.backgroundImage = `url("https://api.iconify.design/mdi:adjust.svg?color=orange&height=17&width=17")`;
|
|
427
|
+
}
|
|
428
|
+
else {
|
|
429
|
+
button.style.backgroundImage = `url("https://api.iconify.design/mdi:close-circle-outline.svg?color=red&height=17&width=17")`;
|
|
430
|
+
}
|
|
431
|
+
const index = this.chosenScansOnPlan.indexOf(button.id);
|
|
432
|
+
this.chosenScansOnPlan.splice(index, 1);
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
onSaveSelection() {
|
|
436
|
+
if (this.multipleFloors) {
|
|
437
|
+
// rassemble all sweeps per floors
|
|
438
|
+
let finalSweeps = [];
|
|
439
|
+
Array.from(this.inputSweepsPerFloor.keys()).forEach(floorID => {
|
|
440
|
+
if (this.chosenSweepsPerFloor.get(floorID)) {
|
|
441
|
+
// the sweeps for this floor were modified, we take them
|
|
442
|
+
finalSweeps = [...finalSweeps, ...this.chosenSweepsPerFloor.get(floorID)];
|
|
443
|
+
}
|
|
444
|
+
else {
|
|
445
|
+
// was not modified, we take the previous values
|
|
446
|
+
finalSweeps = [...finalSweeps, ...this.inputSweepsPerFloor.get(floorID)];
|
|
447
|
+
}
|
|
448
|
+
});
|
|
449
|
+
// console.log("final sweeps", finalSweeps);
|
|
450
|
+
this.sweepsSelected.emit({ "sweeps": finalSweeps, "startSweepID": this.startSweepID });
|
|
451
|
+
}
|
|
452
|
+
else {
|
|
453
|
+
this.sweepsSelected.emit({ "sweeps": this.chosenScansOnPlan, "startSweepID": this.startSweepID });
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
onCancel() {
|
|
457
|
+
if (this.selectionChanged) {
|
|
458
|
+
const message = this.translate.instant("confirm.cancelModifZoneSweeps");
|
|
459
|
+
if (window.confirm(message)) {
|
|
460
|
+
this.sweepsSelected.emit(null);
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
else {
|
|
464
|
+
this.sweepsSelected.emit(null);
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
/**
|
|
468
|
+
* Adds current selection of sweeps for current floor (plan) for multifloor zone.
|
|
469
|
+
* It has to be saved anyway with onSaveSelection!
|
|
470
|
+
*/
|
|
471
|
+
onValidateForFloor() {
|
|
472
|
+
if (this.multipleFloors) {
|
|
473
|
+
this.chosenSweepsPerFloor.set(this.chosenPlan.zoneID, [...this.chosenScansOnPlan]);
|
|
474
|
+
this.selectionChanged = false;
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
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 }, { token: i2.TranslateService }], target: i0.ɵɵFactoryTarget.Component });
|
|
479
|
+
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", multipleFloors: "multipleFloors" }, 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 <div *ngIf=\"multipleFloors\"> \n {{ chosenSweepsPerFloor.get(chosenPlan.zoneID) ? chosenSweepsPerFloor.get(chosenPlan.zoneID).length : \"0\"}} {{'scan points selected on this floor' | translate}} \n <button class=\"btn btn-primary rounded-pill\" (click)=\"onValidateForFloor()\" [disabled]=\"!selectionChanged\">{{'Update selection for this floor' | translate}}</button>\n </div>\n <div *ngIf=\"!multipleFloors\">\n {{ chosenScansOnPlan.length }} {{'scan points chosen' | translate}} \n </div>\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 <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{border-radius:6px;overflow:hidden;background-color:var(--smarterplan-secondary)}.scanTool{margin:0px 1rem}.protip{color:gray;padding:0}.tool-label{font-size:1rem}\n"], components: [{ type: i3.SelectionComponent, selector: "lib-selection", outputs: ["onSelectionChanged"] }, { type: i4.PlanLegendComponent, selector: "lib-plan-legend", inputs: ["isAudioZone"] }, { type: i5.RadioButtonComponent, selector: "lib-radio-button", inputs: ["label"], outputs: ["isCheckedEvent"] }], directives: [{ type: i6.NgbDropdown, selector: "[ngbDropdown]", inputs: ["autoClose", "dropdownClass", "open", "placement", "container", "display"], outputs: ["openChange"], exportAs: ["ngbDropdown"] }, { type: i7.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i6.NgbDropdownToggle, selector: "[ngbDropdownToggle]" }, { type: i6.NgbDropdownMenu, selector: "[ngbDropdownMenu]" }, { type: i7.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i6.NgbDropdownItem, selector: "[ngbDropdownItem]", inputs: ["disabled"] }], pipes: { "translate": i2.TranslatePipe } });
|
|
480
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.2.7", ngImport: i0, type: SweepPlanSelectionComponent, decorators: [{
|
|
481
|
+
type: Component,
|
|
482
|
+
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 <div *ngIf=\"multipleFloors\"> \n {{ chosenSweepsPerFloor.get(chosenPlan.zoneID) ? chosenSweepsPerFloor.get(chosenPlan.zoneID).length : \"0\"}} {{'scan points selected on this floor' | translate}} \n <button class=\"btn btn-primary rounded-pill\" (click)=\"onValidateForFloor()\" [disabled]=\"!selectionChanged\">{{'Update selection for this floor' | translate}}</button>\n </div>\n <div *ngIf=\"!multipleFloors\">\n {{ chosenScansOnPlan.length }} {{'scan points chosen' | translate}} \n </div>\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 <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{border-radius:6px;overflow:hidden;background-color:var(--smarterplan-secondary)}.scanTool{margin:0px 1rem}.protip{color:gray;padding:0}.tool-label{font-size:1rem}\n"] }]
|
|
483
|
+
}], ctorParameters: function () { return [{ type: i1.ZoneService }, { type: i1.NavigationService }, { type: i1.PlanService }, { type: i2.TranslateService }]; }, propDecorators: { spaceID: [{
|
|
484
|
+
type: Input
|
|
485
|
+
}], chosenScansOnPlan: [{
|
|
486
|
+
type: Input
|
|
487
|
+
}], newZoneData: [{
|
|
488
|
+
type: Input
|
|
489
|
+
}], occupiedSweeps: [{
|
|
490
|
+
type: Input
|
|
491
|
+
}], unavailableSweeps: [{
|
|
492
|
+
type: Input
|
|
493
|
+
}], editingAudioZone: [{
|
|
494
|
+
type: Input
|
|
495
|
+
}], inputZone: [{
|
|
496
|
+
type: Input
|
|
497
|
+
}], multipleFloors: [{
|
|
498
|
+
type: Input
|
|
499
|
+
}], sweepsSelected: [{
|
|
500
|
+
type: Output
|
|
501
|
+
}] } });
|
|
502
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3dlZXAtcGxhbi1zZWxlY3Rpb24uY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvbmd4LXNtYXJ0ZXJwbGFuLWxvY2F0aW9ucy9zcmMvbGliL2NvbXBvbmVudHMvem9uZXMvYWRkLXpvbmUvc3dlZXAtcGxhbi1zZWxlY3Rpb24vc3dlZXAtcGxhbi1zZWxlY3Rpb24uY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvbmd4LXNtYXJ0ZXJwbGFuLWxvY2F0aW9ucy9zcmMvbGliL2NvbXBvbmVudHMvem9uZXMvYWRkLXpvbmUvc3dlZXAtcGxhbi1zZWxlY3Rpb24vc3dlZXAtcGxhbi1zZWxlY3Rpb24uY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFNBQVMsRUFBRSxZQUFZLEVBQUUsS0FBSyxFQUFVLE1BQU0sRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUUvRSxPQUFPLEVBQUUsdUJBQXVCLEVBQUUsZUFBZSxFQUE2Qyx5QkFBeUIsRUFBNEIsTUFBTSxtQ0FBbUMsQ0FBQztBQUM3TCxPQUFPLE9BQW9CLE1BQU0sU0FBUyxDQUFDO0FBQzNDLE9BQU8sRUFBRSxtQkFBbUIsRUFBRSxXQUFXLEVBQWEsTUFBTSxFQUFFLG1CQUFtQixFQUFFLFdBQVcsRUFBRSxVQUFVLEVBQUUsTUFBTSw0QkFBNEIsQ0FBQzs7Ozs7Ozs7O0FBTy9JLE1BQU0sT0FBTywyQkFBMkI7SUFvRHBDLFlBQ1ksV0FBd0IsRUFDeEIsaUJBQW9DLEVBQ3BDLFdBQXdCLEVBQ3hCLFNBQTJCO1FBSDNCLGdCQUFXLEdBQVgsV0FBVyxDQUFhO1FBQ3hCLHNCQUFpQixHQUFqQixpQkFBaUIsQ0FBbUI7UUFDcEMsZ0JBQVcsR0FBWCxXQUFXLENBQWE7UUFDeEIsY0FBUyxHQUFULFNBQVMsQ0FBa0I7UUFsRDlCLHNCQUFpQixHQUFhLEVBQUUs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QUcsS0FBSyxDQUFDO1NBQ2pDO0lBQ0wsQ0FBQzs7d0hBdGtCUSwyQkFBMkI7NEdBQTNCLDJCQUEyQixrWkNYeEMsNDJIQXlFQTsyRkQ5RGEsMkJBQTJCO2tCQUx2QyxTQUFTOytCQUNJLDBCQUEwQjsyTEFRM0IsT0FBTztzQkFBZixLQUFLO2dCQUVHLGlCQUFpQjtzQkFBekIsS0FBSztnQkFHRyxXQUFXO3NCQUFuQixLQUFLO2dCQUtHLGNBQWM7c0JBQXRCLEtBQUs7Z0JBR0csaUJBQWlCO3NCQUF6QixLQUFLO2dCQUdHLGdCQUFnQjtzQkFBeEIsS0FBSztnQkFFRyxTQUFTO3NCQUFqQixLQUFLO2dCQUVHLGNBQWM7c0JBQXRCLEtBQUs7Z0JBZ0JJLGNBQWM7c0JBQXZCLE1BQU0iLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBDb21wb25lbnQsIEV2ZW50RW1pdHRlciwgSW5wdXQsIE9uSW5pdCwgT3V0cHV0IH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBUcmFuc2xhdGVTZXJ2aWNlIH0gZnJvbSAnQG5neC10cmFuc2xhdGUvY29yZSc7XG5pbXBvcnQgeyBnZXRDb2VmZmljaWVudHNGb3JJbWFnZSwgZ2V0TWV0YUZvckltYWdlLCBOYXZpZ2F0aW9uLCBOYXZpZ2F0aW9uU2VydmljZSwgUGxhbiwgWm9uZSwgc2hvd1NjYW5Qb2ludHNPblBsYW5JbkRpdiwgWm9uZVNlcnZpY2UsIFBsYW5TZXJ2aWNlIH0gZnJvbSAnQHNtYXJ0ZXJwbGFuL25neC1zbWFydGVycGxhbi1jb3JlJztcbmltcG9ydCBwYW56b29tLCB7IFBhblpvb20gfSBmcm9tICdwYW56b29tJztcbmltcG9ydCB7IGJ1dHRvbklzSW5TZWxlY3Rpb24sIGlzSW5Qb2x5Z29uLCBSZWN0YW5nbGUsIHJvdGF0ZSwgc2V0VmlzdWFsbHlTZWxlY3RlZCwgc3R5bGVCdXR0b24sIFN3ZWVwU3RhdGUgfSBmcm9tICcuLi8uLi8uLi8uLi9oZWxwZXIuc2VydmljZSc7XG5cbkBDb21wb25lbnQoe1xuICAgIHNlbGVjdG9yOiAnbGliLXN3ZWVwLXBsYW4tc2VsZWN0aW9uJyxcbiAgICB0ZW1wbGF0ZVVybDogJy4vc3dlZXAtcGxhbi1zZWxlY3Rpb24uY29tcG9uZW50Lmh0bWwnLFxuICAgIHN0eWxlVXJsczogWycuL3N3ZWVwLXBsYW4tc2VsZWN0aW9uLmNvbXBvbmVudC5zY3NzJ11cbn0pXG5leHBvcnQgY2xhc3MgU3dlZXBQbGFuU2VsZWN0aW9uQ29tcG9uZW50IGltcGxlbWVudHMgT25Jbml0IHtcblxuICAgIHBsYW5zOiBQbGFuW107XG5cbiAgICBASW5wdXQoKSBzcGFjZUlEOiBzdHJpbmc7XG5cbiAgICBASW5wdXQoKSBjaG9zZW5TY2Fuc09uUGxhbjogc3RyaW5nW10gPSBbXTtcblxuICAgIC8qKiBpZiBjb21taW5nIGZyb20gRWRpdCBQbGFuIFNWRyBab25lIGNyZWF0aW9uICovXG4gICAgQElucHV0KCkgbmV3Wm9uZURhdGE6IGFueTtcblxuICAgIG5hdklEc1pvbmVFZGl0OiBzdHJpbmdbXSA9IFtdO1xuXG4gICAgLy8gc3dlZXBzIGJlbG9uZ2luZyB0byBhbnkgYXVkaW8gem9uZVxuICAgIEBJbnB1dCgpIG9jY3VwaWVkU3dlZXBzOiBzdHJpbmdbXSA9IFtdO1xuXG4gICAgLy8gc3dlZXBzIHVuYXZhaWxhYmxlIChjYW5ub3QgYmUgY2hvc2VuKVxuICAgIEBJbnB1dCgpIHVuYXZhaWxhYmxlU3dlZXBzOiBzdHJpbmdbXSA9IFtdO1xuXG4gICAgLy8gaWYgY2hvb3Npbmcgc3dlZXBzIGZvciBhdWRpbyB6b25lXG4gICAgQElucHV0KCkgZWRpdGluZ0F1ZGlvWm9uZTogYm9vbGVhbiA9IGZhbHNlO1xuXG4gICAgQElucHV0KCkgaW5wdXRab25lOiBab25lO1xuXG4gICAgQElucHV0KCkgbXVsdGlwbGVGbG9vcnM6IGJvb2xlYW4gPSBmYWxzZTtcblxuICAgIGNob3NlblBsYW46IFBsYW47XG5cbiAgICAvKiogcGFuWm9vbSBlbGVtZW50IGZvciBhZGRpbmcgc2NhbnMgKi9cbiAgICBwYW5ab29tOiBQYW5ab29tO1xuXG4gICAgLyoqIGRpdlBsYW4gKHVzZSBCeSBwYW5ab29tKSAqL1xuICAgIGRpdlBsYW46IEhUTUxFbGVtZW50O1xuXG4gICAgLyoqIGFsbCBzY2FuIGJ1dHRvbnMgRWxlbWVudCAqL1xuICAgIGJ1dHRvbkVsZW1lbnRzOiBIVE1MQnV0dG9uRWxlbWVudFtdID0gW107XG5cbiAgICAvKiogU2NhbiBidXR0b25zIHRoYXQgYXJlIGluIHRoZSBjdXJyZW50IHNlbGVjdGlvbiAqL1xuICAgIGJ1dHRvbnNJblNlbGVjdGlvbjogSFRNTEJ1dHRvbkVsZW1lbnRbXSA9IFtdO1xuXG4gICAgQE91dHB1dCgpIHN3ZWVwc1NlbGVjdGVkID0gbmV3IEV2ZW50RW1pdHRlcjx7IHN3ZWVwczogc3RyaW5nW107IHN0YXJ0U3dlZXBJRDogc3RyaW5nOyB9PigpO1xuXG4gICAgaXNTZXR0aW5nU3RhcnRTd2VlcCA9IGZhbHNlO1xuXG4gICAgc3RhcnRTd2VlcElEOiBzdHJpbmc7XG5cbiAgICBjaG9zZW5Td2VlcHNQZXJGbG9vciA9IG5ldyBNYXA8c3RyaW5nLCBzdHJpbmdbXT4oKTsgLy8gbWFwIG1hdGNoaW5nIGZsb29ySUQgdG8gc3dlZXBzIHNlbGVjdGVkXG5cbiAgICBpbnB1dFN3ZWVwc1BlckZsb29yID0gbmV3IE1hcDxzdHJpbmcsIHN0cmluZ1tdPigpOyAvLyBtYXAgbWF0Y2hpbmcgZmxvb3JJRCB0byBzd2VlcHMgc2VsZWN0ZWQgZm9yIHpvbmUgaW4gZWRpdGlvblxuXG4gICAgc2VsZWN0aW9uQ2hhbmdlZCA9IGZhbHNlO1xuXG4gICAgY29uc3RydWN0b3IoXG4gICAgICAgIHByaXZhdGUgem9uZVNlcnZpY2U6IFpvbmVTZXJ2aWNlLFxuICAgICAgICBwcml2YXRlIG5hdmlnYXRpb25TZXJ2aWNlOiBOYXZpZ2F0aW9uU2VydmljZSxcbiAgICAgICAgcHJpdmF0ZSBwbGFuU2VydmljZTogUGxhblNlcnZpY2UsXG4gICAgICAgIHByaXZhdGUgdHJhbnNsYXRlOiBUcmFuc2xhdGVTZXJ2aWNlLFxuICAgICkgeyB9XG5cbiAgICBhc3luYyBuZ09uSW5pdCgpIHtcbiAgICAgICAgYXdhaXQgdGhpcy5nZXRQbGFucygpO1xuICAgICAgICB0aGlzLnNldFN3ZWVwc09mSW5wdXRab25lKCk7XG4gICAgfVxuXG4gICAgbmdPbkNoYW5nZXMoKSB7XG4gICAgICAgIGlmICh0aGlzLmNob3NlblBsYW4pIHtcbiAgICAgICAgICAgIHRoaXMuc2V0U3dlZXBzT2ZJbnB1dFpvbmUoKTtcbiAgICAgICAgICAgIHRoaXMuY2hvc2VuU2NhbnNPblBsYW4gPSBbXTtcbiAgICAgICAgICAgIHRoaXMuY2xlYXJEaXZQbGFuKCk7XG4gICAgICAgICAgICB0aGlzLmFkZFNjYW5Qb2ludHMoKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHNldFN3ZWVwc09mSW5wdXRab25lKCkge1xuICAgICAgICB0aGlzLm5hdklEc1pvbmVFZGl0ID0gdGhpcy5pbnB1dFpvbmUgPyB0aGlzLmlucHV0Wm9uZS5zd2VlcElEcyA6IFtdO1xuICAgICAgICBpZiAodGhpcy5tdWx0aXBsZUZsb29ycykge1xuICAgICAgICAgICAgdGhpcy5wbGFucy5mb3JFYWNoKChwbGFuKSA9PiB7XG4gICAgICAgICAgICAgICAgaWYgKCF0aGlzLmlucHV0U3dlZXBzUGVyRmxvb3IuZ2V0KHBsYW4uem9uZUlEKSkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmlucHV0U3dlZXBzUGVyRmxvb3Iuc2V0KHBsYW4uem9uZUlELFxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5uYXZJRHNab25lRWRpdC5maWx0ZXIoKHN3ZWVwKSA9PiBwbGFuLnpvbmUuc3dlZXBJRHMuaW5jbHVkZXMoc3dlZXApKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBpZiAodGhpcy5pbnB1dFpvbmUpIHtcbiAgICAgICAgICAgICAgICAvL2ZpbHRlciBwbGFucyBvbmx5IGZvciB0aGUgcGFyZW50IFpvbmVcbiAgICAgICAgICAgICAgICB0aGlzLnBsYW5zID0gdGhpcy5wbGFucy5maWx0ZXIoKHApID0+IHAuem9uZUlEID09PSB0aGlzLmlucHV0Wm9uZS5wYXJlbnRJRCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBhc3luYyBnZXRQbGFucygpIHtcbiAgICAgICAgdGhpcy5wbGFucyA9IGF3YWl0IHRoaXMucGxhblNlcnZpY2UuZ2V0U2luZ2VkUGxhbnNGb3JTcGFjZShcbiAgICAgICAgICAgIHRoaXMuc3BhY2VJRCxcbiAgICAgICAgKTtcbiAgICB9XG5cbiAgICBhc3luYyBvblBsYW5DbGljayhwbGFuOiBQbGFuKSB7XG4gICAgICAgIGNvbnN0IHN3aXRjaFBsYW4gPSAoKSA9PiB7XG4gICAgICAgICAgICB0aGlzLnNlbGVjdGlvbkNoYW5nZWQgPSBmYWxzZTtcbiAgICAgICAgICAgIHRoaXMuY2hvc2VuUGxhbiA9IHBsYW47XG4gICAgICAgICAgICB0aGlzLmNob3NlblNjYW5zT25QbGFuID0gW107XG4gICAgICAgICAgICB0aGlzLmNsZWFyRGl2UGxhbigpO1xuICAgICAgICAgICAgdGhpcy5hZGRTY2FuUG9pbnRzKCk7XG4gICAgICAgIH07XG4gICAgICAgIGlmICh0aGlzLnNlbGVjdGlvbkNoYW5nZWQpIHtcbiAgICAgICAgICAgIGNvbnN0IG1lc3NhZ2UgPSB0aGlzLnRyYW5zbGF0ZS5pbnN0YW50KFwiY29uZmlybS5jYW5jZWxNb2RpZlpvbmVTd2VlcHNcIik7XG4gICAgICAgICAgICBpZiAod2luZG93LmNvbmZpcm0obWVzc2FnZSkpIHtcbiAgICAgICAgICAgICAgICBzd2l0Y2hQbGFuKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBzd2l0Y2hQbGFuKCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBhc3luYyBhZGRTY2FuUG9pbnRzKCkge1xuICAgICAgICBsZXQgd2FzTW9kaWZpZWQgPSBmYWxzZTtcbiAgICAgICAgaWYgKHRoaXMubXVsdGlwbGVGbG9vcnMpIHtcbiAgICAgICAgICAgIC8vIGNoZWNrIGlmIHdlIGhhdmUgYWxyZWFkeSB2YWxpZGF0ZWQgYnV0dG9ucyBmb3IgdGhpcyBmbG9vclxuICAgICAgICAgICAgaWYgKHRoaXMuY2hvc2VuU3dlZXBzUGVyRmxvb3IuZ2V0KHRoaXMuY2hvc2VuUGxhbi56b25lSUQpKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5jaG9zZW5TY2Fuc09uUGxhbiA9IHRoaXMuY2hvc2VuU3dlZXBzUGVyRmxvb3IuZ2V0KHRoaXMuY2hvc2VuUGxhbi56b25lSUQpO1xuICAgICAgICAgICAgICAgIHdhc01vZGlmaWVkID0gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICB0aGlzLmRpdlBsYW4gPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKFwiI3BsYW5EaXZcIikgYXMgSFRNTEVsZW1lbnQ7XG4gICAgICAgIGNvbnN0IHpvbmVPZlBsYW4gPSBhd2FpdCB0aGlzLnpvbmVTZXJ2aWNlLmdldFpvbmUoXG4gICAgICAgICAgICB0aGlzLmNob3NlblBsYW4uem9uZUlELFxuICAgICAgICApO1xuICAgICAgICBjb25zdCBuYXZpZ2F0aW9ucyA9IGF3YWl0IHRoaXMubmF2aWdhdGlvblNlcnZpY2UuZ2V0TmF2aWdhdGlvbnNGb3Jab25lKFxuICAgICAgICAgICAgem9uZU9mUGxhbixcbiAgICAgICAgKTtcbiAgICAgICAgaWYgKHRoaXMubmV3Wm9uZURhdGEpIGF3YWl0IHRoaXMuc2V0U2NhbkJ5RHJhdyhuYXZpZ2F0aW9ucyk7XG4gICAgICAgIHRoaXMuYnV0dG9uRWxlbWVudHMgPSBhd2FpdCBzaG93U2NhblBvaW50c09uUGxhbkluRGl2KFxuICAgICAgICAgICAgdGhpcy5jaG9zZW5QbGFuLFxuICAgICAgICAgICAgdGhpcy5kaXZQbGFuLFxuICAgICAgICAgICAgbmF2aWdhdGlvbnMsXG4gICAgICAgICk7XG4gICAgICAgIGZvciAoY29uc3QgZWxlbWVudCBvZiB0aGlzLmJ1dHRvbkVsZW1lbnRzKSB7XG4gICAgICAgICAgICBpZiAodGhpcy51bmF2YWlsYWJsZVN3ZWVwcyAmJiB0aGlzLnVuYXZhaWxhYmxlU3dlZXBzLmluY2x1ZGVzKGVsZW1lbnQuaWQpKSB7XG4gICAgICAgICAgICAgICAgc3R5bGVCdXR0b24oZWxlbWVudCwgU3dlZXBTdGF0ZS5ESVNBQkxFRCk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuXG4gICAgICAgICAgICAgICAgaWYgKHdhc01vZGlmaWVkKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLmNob3NlblNjYW5zT25QbGFuLmluY2x1ZGVzKGVsZW1lbnQuaWQpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzdHlsZUJ1dHRvbihlbGVtZW50LCBTd2VlcFN0YXRlLkFEREVEKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHN0eWxlQnV0dG9uKGVsZW1lbnQsIFN3ZWVwU3RhdGUuUkVNT1ZFRCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBpZiAoXG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLm5hdklEc1pvbmVFZGl0Lmxlbmd0aCA+IDAgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMubmF2SURzWm9uZUVkaXQuaW5jbHVkZXMoZWxlbWVudC5pZCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHN0eWxlQnV0dG9uKGVsZW1lbnQsIFN3ZWVwU3RhdGUuQURERUQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCF0aGlzLmNob3NlblNjYW5zT25QbGFuLmluY2x1ZGVzKGVsZW1lbnQuaWQpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jaG9zZW5TY2Fuc09uUGxhbi5wdXNoKGVsZW1lbnQuaWQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHRoaXMub2NjdXBpZWRTd2VlcHMgJiYgdGhpcy5vY2N1cGllZFN3ZWVwcy5pbmNsdWRlcyhlbGVtZW50LmlkKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgc3R5bGVCdXR0b24oZWxlbWVudCwgU3dlZXBTdGF0ZS5PQ0NVUElFRCk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzdHlsZUJ1dHRvbihlbGVtZW50LCBTd2VlcFN0YXRlLlJFTU9WRUQpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy9zdGFydCBwb2ludCBzaG91bGQgYmUgbGFzdCBjb25kaXRpb24gXG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuaW5wdXRab25lICYmIHRoaXMuaW5wdXRab25lLnN0YXJ0U3dlZXBJRCA9PT0gZWxlbWVudC5pZCkge1xuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmxvZyhcInNldHRpbmcgc3RhcnQgcG9pbnRcIik7XG4gICAgICAgICAgICAgICAgICAgIHN0eWxlQnV0dG9uKGVsZW1lbnQsIFN3ZWVwU3RhdGUuU1RBUlRQT0lOVCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsZW1lbnQuYWRkRXZlbnRMaXN0ZW5lcihcImNsaWNrXCIsIChldmVudCkgPT5cbiAgICAgICAgICAgICAgICAgICAgdGhpcy5vbkJ1dHRvblNjYW5DbGlja2VkKGV2ZW50LnRhcmdldCBhcyBIVE1MRWxlbWVudCksXG4gICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICB0aGlzLnBhblpvb20gPSBwYW56b29tKHRoaXMuZGl2UGxhbiwge1xuICAgICAgICAgICAgYm91bmRzOiB0cnVlLFxuICAgICAgICAgICAgYm91bmRzUGFkZGluZzogMCxcbiAgICAgICAgICAgIG1heFpvb206IDMuNSxcbiAgICAgICAgICAgIGJlZm9yZU1vdXNlRG93bihlOiBNb3VzZUV2ZW50KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIChcbiAgICAgICAgICAgICAgICAgICAgZS5idXR0b24gPT09IDJcbiAgICAgICAgICAgICAgICApOyAvKiogSWdub3JlIGV2ZW50IGZvciByaWdodCBjbGljayAodXNlIGZvciBzZWxlY3RpbmcpICovXG4gICAgICAgICAgICB9LFxuICAgICAgICB9KTtcbiAgICAgICAgaWYgKHRoaXMubXVsdGlwbGVGbG9vcnMpIHtcbiAgICAgICAgICAgIHRoaXMuY2hvc2VuU3dlZXBzUGVyRmxvb3Iuc2V0KHRoaXMuY2hvc2VuUGxhbi56b25lSUQsIFsuLi50aGlzLmNob3NlblNjYW5zT25QbGFuXSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKiogRnVuY3Rpb24gaWYgd2UgYXJlIGNvbWluZyBmb3Igc3ZnIGVkaXRvciB3b3JrZmxvdyAqL1xuICAgIHNldFNjYW5CeURyYXcobmF2aWdhdGlvbnM6IGFueVtdKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZShhc3luYyAocmVzb2x2ZSkgPT4ge1xuICAgICAgICAgICAgY29uc3QgcmVjdCA9IHtcbiAgICAgICAgICAgICAgICB3aWR0aDogdGhpcy5uZXdab25lRGF0YS53aWR0aCxcbiAgICAgICAgICAgICAgICBoZWlnaHQ6IHRoaXMubmV3Wm9uZURhdGEuaGVpZ2h0LFxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIGNvbnN0IGltZyA9IGF3YWl0IGdldE1ldGFGb3JJbWFnZSh0aGlzLmNob3NlblBsYW4uZmlsZXBhdGgpO1xuICAgICAgICAgICAgY29uc3QgeyBjb2VmZlgsIGNvZWZmWSB9ID0gZ2V0Q29lZmZpY2llbnRzRm9ySW1hZ2UoaW1nLCByZWN0KTtcblxuICAgICAgICAgICAgY29uc3QgZHJhdyA9IHRoaXMubmV3Wm9uZURhdGEuZWxlbWVudHM7XG5cbiAgICAgICAgICAgIGRyYXcubWFwKGFzeW5jIChlbGVtZW50OiBhbnkpID0+IHtcbiAgICAgICAgICAgICAgICBzd2l0Y2ggKGVsZW1lbnQubm9kZU5hbWUpIHtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBcInJlY3RcIjpcbiAgICAgICAgICAgICAgICAgICAgICAgIGF3YWl0IHRoaXMuc2V0U2NhbkluUmVjdChcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbWcsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29lZmZYLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvZWZmWSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbGVtZW50LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5hdmlnYXRpb25zLFxuICAgICAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgICAgICAgICAgICAgIGNhc2UgXCJlbGxpcHNlXCI6XG4gICAgICAgICAgICAgICAgICAgICAgICBhd2FpdCB0aGlzLnNldFNjYW5JbkNpcmNsZShcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbWcsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29lZmZYLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvZWZmWSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbGVtZW50LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5hdmlnYXRpb25zLFxuICAgICAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgICAgICAgICAgICAgIGNhc2UgXCJwYXRoXCI6XG4gICAgICAgICAgICAgICAgICAgICAgICBhd2FpdCB0aGlzLnNldFNjYW5JblBvbHlnb24oXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaW1nLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvZWZmWCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2VmZlksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxlbWVudCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBuYXZpZ2F0aW9ucyxcbiAgICAgICAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICByZXNvbHZlKCk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIGFzeW5jIHNldFNjYW5JblJlY3QoaW1nOiBhbnksIGNvZWZmWDogbnVtYmVyLCBjb2VmZlk6IG51bWJlcixcbiAgICAgICAgZWxlbWVudDogeyBhbmdsZTogYW55OyBjeDogYW55OyBjeTogYW55OyB4OiBudW1iZXI7IHdpZHRoOiBhbnk7IHk6IG51bWJlcjsgaGVpZ2h0OiBhbnk7IH0sIG5hdmlnYXRpb25zOiBhbnlbXSkge1xuICAgICAgICBjb25zdCBjYWxpYnJhZ2UgPSBKU09OLnBhcnNlKHRoaXMuY2hvc2VuUGxhbi5jYWxpYnJhdGlvbik7XG4gICAgICAgIG5hdmlnYXRpb25zLm1hcCgobmF2aWdhdGlvbikgPT4ge1xuICAgICAgICAgICAgY29uc3QgcG9zaXRpb25zT25QbGFuID0gbmF2aWdhdGlvbi5wb3NpdGlvbk9uUGxhbi5tYXAoKGVudHJ5KSA9PlxuICAgICAgICAgICAgICAgIEpTT04ucGFyc2UoZW50cnkpLFxuICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIGNvbnN0IHBvc2l0aW9uT25QbGFuID0gcG9zaXRpb25zT25QbGFuLmZpbmQoXG4gICAgICAgICAgICAgICAgKGRhdGEpID0+IGRhdGEucGxhbklEID09PSB0aGlzLmNob3NlblBsYW4uaWQsXG4gICAgICAgICAgICApO1xuICAgICAgICAgICAgaWYgKHBvc2l0aW9uT25QbGFuKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgcmVhbFdpZHRoID0gaW1nLndpZHRoIC8gY29lZmZYO1xuICAgICAgICAgICAgICAgIGNvbnN0IHJlYWxIZWlnaHQgPSBpbWcuaGVpZ2h0IC8gY29lZmZZO1xuICAgICAgICAgICAgICAgIGNvbnN0IG5hdlkgPSAocG9zaXRpb25PblBsYW4ueSAqIHJlYWxIZWlnaHQpIC8gY2FsaWJyYWdlLmltZ0hlaWdodDtcbiAgICAgICAgICAgICAgICBjb25zdCBuYXZYID0gKHBvc2l0aW9uT25QbGFuLnggKiByZWFsV2lkdGgpIC8gY2FsaWJyYWdlLmltZ1dpZHRoO1xuICAgICAgICAgICAgICAgIGlmIChcbiAgICAgICAgICAgICAgICAgICAgbmF2WCA+IGVsZW1lbnQueCAmJlxuICAgICAgICAgICAgICAgICAgICBuYXZYIDwgZWxlbWVudC54ICsgZWxlbWVudC53aWR0aCAmJlxuICAgICAgICAgICAgICAgICAgICBuYXZZID4gZWxlbWVudC55ICYmXG4gICAgICAgICAgICAgICAgICAgIG5hdlkgPCBlbGVtZW50LnkgKyBlbGVtZW50LmhlaWdodCAmJlxuICAgICAgICAgICAgICAgICAgICAhdGhpcy5uYXZJRHNab25lRWRpdC5pbmNsdWRlcyhuYXZpZ2F0aW9uLmlkKVxuICAgICAgICAgICAgICAgICkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLm5hdklEc1pvbmVFZGl0LnB1c2gobmF2aWdhdGlvbi5pZCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBvbGQgY2FsaWJyYXRpb246XG4gICAgICAgICAgICAvLyBjb25zdCBwb3NpdGlvbiA9IEpTT04ucGFyc2UobmF2aWdhdGlvbi5wb3NpdGlvbik7XG4gICAgICAgICAgICAvLyBsZXQgbmF2WCA9IChjYWxpYnJhZ2Uub2Zmc2V0WCArIHBvc2l0aW9uLnggKiBjYWxpYnJhZ2UueCkgLyBjb2VmZlg7XG4gICAgICAgICAgICAvLyBsZXQgbmF2WSA9IChjYWxpYnJhZ2Uub2Zmc2V0WSArIHBvc2l0aW9uLnogKiBjYWxpYnJhZ2UueSkgLyBjb2VmZlk7XG4gICAgICAgICAgICAvLyBpZiAoZWxlbWVudC5hbmdsZSkge1xuICAgICAgICAgICAgLy8gICAgIGNvbnN0IHJvdGF0ZVBvcyA9IHJvdGF0ZShcbiAgICAgICAgICAgIC8vICAgICAgICAgeyB4OiBuYXZYLCB5OiBuYXZZIH0sXG4gICAgICAgICAgICAvLyAgICAgICAgIHsgeDogZWxlbWVudC5jeCwgeTogZWxlbWVudC5jeSB9LFxuICAgICAgICAgICAgLy8gICAgICAgICBlbGVtZW50LmFuZ2xlLFxuICAgICAgICAgICAgLy8gICAgICk7XG4gICAgICAgICAgICAvLyAgICAgbmF2WCA9IHJvdGF0ZVBvcy54O1xuICAgICAgICAgICAgLy8gICAgIG5hdlkgPSByb3RhdGVQb3MueTtcbiAgICAgICAgICAgIC8vIH1cbiAgICAgICAgICAgIC8qKlxuICAgICAgICAgICAgICogVE9ETyBjYWxjdWxlciBsYSByb3RhdGlvbiBkdSByZWN0YW5nbGVcbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgLy8gaWYgKFxuICAgICAgICAgICAgLy8gICAgIG5hdlggPiBlbGVtZW50LnggJiZcbiAgICAgICAgICAgIC8vICAgICBuYXZYIDwgZWxlbWVudC54ICsgZWxlbWVudC53aWR0aCAmJlxuICAgICAgICAgICAgLy8gICAgIG5hdlkgPiBlbGVtZW50LnkgJiZcbiAgICAgICAgICAgIC8vICAgICBuYXZZIDwgZWxlbWVudC55ICsgZWxlbWVudC5oZWlnaHQgJiZcbiAgICAgICAgICAgIC8vICAgICAhdGhpcy5uYXZJRHNab25lRWRpdC5pbmNsdWRlcyhuYXZpZ2F0aW9uLmlkKVxuICAgICAgICAgICAgLy8gKSB7XG4gICAgICAgICAgICAvLyAgICAgdGhpcy5uYXZJRHNab25lRWRpdC5wdXNoKG5hdmlnYXRpb24uaWQpO1xuICAgICAgICAgICAgLy8gfVxuICAgICAgICB9KTtcbiAgICB9IC8vIEVPXG5cbiAgICBhc3luYyBzZXRTY2FuSW5DaXJjbGUoaW1nOiBhbnksIGNvZWZmWDogbnVtYmVyLCBjb2VmZlk6IG51bWJlcixcbiAgICAgICAgZWxlbWVudDogeyBhbmdsZTogYW55OyBjeDogbnVtYmVyOyBjeTogbnVtYmVyOyByeDogbnVtYmVyOyByeTogbnVtYmVyOyB9LCBuYXZpZ2F0aW9uczogTmF2aWdhdGlvbltdKSB7XG4gICAgICAgIGNvbnN0IGNhbGlicmFnZSA9IEpTT04ucGFyc2UodGhpcy5jaG9zZW5QbGFuLmNhbGlicmF0aW9uKTtcbiAgICAgICAgbmF2aWdhdGlvbnMubWFwKG5hdmlnYXRpb24gPT4ge1xuICAgICAgICAgICAgY29uc3QgcG9zaXRpb25zT25QbGFuID0gbmF2aWdhdGlvbi5wb3NpdGlvbk9uUGxhbi5tYXAoKGVudHJ5KSA9PlxuICAgICAgICAgICAgICAgIEpTT04ucGFyc2UoZW50cnkpLFxuICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIGNvbnN0IHBvc2l0aW9uT25QbGFuID0gcG9zaXRpb25zT25QbGFuLmZpbmQoXG4gICAgICAgICAgICAgICAgKGRhdGEpID0+IGRhdGEucGxhbklEID09PSB0aGlzLmNob3NlblBsYW4uaWQsXG4gICAgICAgICAgICApO1xuICAgICAgICAgICAgaWYgKHBvc2l0aW9uT25QbGFuKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgcmVhbFdpZHRoID0gaW1nLndpZHRoIC8gY29lZmZYO1xuICAgICAgICAgICAgICAgIGNvbnN0IHJlYWxIZWlnaHQgPSBpbWcuaGVpZ2h0IC8gY29lZmZZO1xuICAgICAgICAgICAgICAgIGxldCBuYXZZID0gKHBvc2l0aW9uT25QbGFuLnkgKiByZWFsSGVpZ2h0KSAvIGNhbGlicmFnZS5pbWdIZWlnaHQ7XG4gICAgICAgICAgICAgICAgbGV0IG5hdlggPSAocG9zaXRpb25PblBsYW4ueCAqIHJlYWxXaWR0aCkgLyBjYWxpYnJhZ2UuaW1nV2lkdGg7XG4gICAgICAgICAgICAgICAgaWYgKGVsZW1lbnQuYW5nbGUpIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3Qgcm90YXRlUG9zID0gcm90YXRlKFxuICAgICAgICAgICAgICAgICAgICAgICAgeyB4OiBuYXZYLCB5OiBuYXZZIH0sXG4gICAgICAgICAgICAgICAgICAgICAgICB7IHg6IGVsZW1lbnQuY3gsIHk6IGVsZW1lbnQuY3kgfSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGVsZW1lbnQuYW5nbGUsXG4gICAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgICAgIG5hdlggPSByb3RhdGVQb3MueDtcbiAgICAgICAgICAgICAgICAgICAgbmF2WSA9IHJvdGF0ZVBvcy55O1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGNvbnN0IHZhbHVlWCA9XG4gICAgICAgICAgICAgICAgICAgIE1hdGgucG93KG5hdlggLSBlbGVtZW50LmN4LCAyKSAvIE1hdGgucG93KGVsZW1lbnQucngsIDIpO1xuICAgICAgICAgICAgICAgIGNvbnN0IHZhbHVlWSA9XG4gICAgICAgICAgICAgICAgICAgIE1hdGgucG93KG5hdlkgLSBlbGVtZW50LmN5LCAyKSAvIE1hdGgucG93KGVsZW1lbnQucnksIDIpO1xuICAgICAgICAgICAgICAgIGNvbnN0IHJlc3VsdCA9IHZhbHVlWCArIHZhbHVlWTtcbiAgICAgICAgICAgICAgICBpZiAocmVzdWx0IDw9IDEgJiYgIXRoaXMubmF2SURzWm9uZUVkaXQuaW5jbHVkZXMobmF2aWdhdGlvbi5pZCkpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5uYXZJRHNab25lRWRpdC5wdXNoKG5hdmlnYXRpb24uaWQpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gb2xkIGNhbGlicmF0aW9uXG4gICAgICAgICAgICAvLyBjb25zdCBwb3NpdGlvbiA9IEpTT04ucGFyc2UobmF2aWdhdGlvbi5wb3NpdGlvbik7XG4gICAgICAgICAgICAvLyBsZXQgbmF2WCA9IChjYWxpYnJhZ2Uub2Zmc2V0WCArIHBvc2l0aW9uLnggKiBjYWxpYnJhZ2UueCkgLyBjb2VmZlg7XG4gICAgICAgICAgICAvLyBsZXQgbmF2WSA9IChjYWxpYnJhZ2Uub2Zmc2V0WSArIHBvc2l0aW9uLnogKiBjYWxpYnJhZ2UueSkgLyBjb2VmZlk7XG4gICAgICAgICAgICAvLyBpZiAoZWxlbWVudC5hbmdsZSkge1xuICAgICAgICAgICAgLy8gICAgIGNvbnN0IHJvdGF0ZVBvcyA9IHJvdGF0ZShcbiAgICAgICAgICAgIC8vICAgICAgICAgeyB4OiBuYXZYLCB5OiBuYXZZIH0sXG4gICAgICAgICAgICAvLyAgICAgICAgIHsgeDogZWxlbWVudC5jeCwgeTogZWxlbWVudC5jeSB9LFxuICAgICAgICAgICAgLy8gICAgICAgICBlbGVtZW50LmFuZ2xlLFxuICAgICAgICAgICAgLy8gICAgICk7XG4gICAgICAgICAgICAvLyAgICAgbmF2WCA9IHJvdGF0ZVBvcy54O1xuICAgICAgICAgICAgLy8gICAgIG5hdlkgPSByb3RhdGVQb3MueTtcbiAgICAgICAgICAgIC8vIH1cblxuICAgICAgICAgICAgLy8gY29uc3QgdmFsdWVYID1cbiAgICAgICAgICAgIC8vICAgICBNYXRoLnBvdyhuYXZYIC0gZWxlbWVudC5jeCwgMikgLyBNYXRoLnBvdyhlbGVtZW50LnJ4LCAyKTtcbiAgICAgICAgICAgIC8vIGNvbnN0IHZhbHVlWSA9XG4gICAgICAgICAgICAvLyAgICAgTWF0aC5wb3cobmF2WSAtIGVsZW1lbnQuY3ksIDIpIC8gTWF0aC5wb3coZWxlbWVudC5yeSwgMik7XG4gICAgICAgICAgICAvLyBjb25zdCByZXN1bHQgPSB2YWx1ZVggKyB2YWx1ZVk7XG4gICAgICAgICAgICAvLyBpZiAocmVzdWx0IDw9IDEgJiYgIXRoaXMubmF2SURzWm9uZUVkaXQuaW5jbHVkZXMobmF2aWdhdGlvbi5pZCkpIHtcbiAgICAgICAgICAgIC8vICAgICB0aGlzLm5hdklEc1pvbmVFZGl0LnB1c2gobmF2aWdhdGlvbi5pZCk7XG4gICAgICAgICAgICAvLyB9XG4gICAgICAgIH0pO1xuICAgIH0gLy8gRU9cblxuICAgIGFzeW5jIHNldFNjYW5JblBvbHlnb24oaW1nOiBhbnksIGNvZWZmWDogbnVtYmVyLCBjb2VmZlk6IG51bWJlciwgZWxlbWVudDogeyBzZWdMaXN0OiBhbnk7IH0sIG5hdmlnYXRpb25zOiBhbnlbXSkge1xuICAgICAgICBjb25zdCBjYWxpYnJhZ2UgPSBKU09OLnBhcnNlKHRoaXMuY2hvc2VuUGxhbi5jYWxpYnJhdGlvbik7XG4gICAgICAgIG5hdmlnYXRpb25zLm1hcChhc3luYyAobmF2aWdhdGlvbikgPT4ge1xuXG4gICAgICAgICAgICBjb25zdCBwb3NpdGlvbnNPblBsYW4gPSBuYXZpZ2F0aW9uLnBvc2l0aW9uT25QbGFuLm1hcCgoZW50cnkpID0+XG4gICAgICAgICAgICAgICAgSlNPTi5wYXJzZShlbnRyeSksXG4gICAgICAgICAgICApO1xuICAgICAgICAgICAgY29uc3QgcG9zaXRpb25PblBsYW4gPSBwb3NpdGlvbnNPblBsYW4uZmluZChcbiAgICAgICAgICAgICAgICAoZGF0YSkgPT4gZGF0YS5wbGFuSUQgPT09IHRoaXMuY2hvc2VuUGxhbi5pZCxcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICBpZiAocG9zaXRpb25PblBsYW4pIHtcbiAgICAgICAgICAgICAgICBjb25zdCByZWFsV2lkdGggPSBpbWcud2lkdGggLyBjb2VmZlg7XG4gICAgICAgICAgICAgICAgY29uc3QgcmVhbEhlaWdodCA9IGltZy5oZWlnaHQgLyBjb2VmZlk7XG4gICAgICAgICAgICAgICAgbGV0IG5hdlkgPSAocG9zaXRpb25PblBsYW4ueSAqIHJlYWxIZWlnaHQpIC8gY2FsaWJyYWdlLmltZ0hlaWdodDtcbiAgICAgICAgICAgICAgICBsZXQgbmF2WCA9IChwb3NpdGlvbk9uUGxhbi54ICogcmVhbFdpZHRoKSAvIGNhbGlicmFnZS5pbWdXaWR0aDtcblxuICAgICAgICAgICAgICAgIGNvbnN0IHAgPSB7XG4gICAgICAgICAgICAgICAgICAgIHg6IG5hdlgsXG4gICAgICAgICAgICAgICAgICAgIHk6IG5hdlksXG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICBpZiAoXG4gICAgICAgICAgICAgICAgICAgIGlzSW5Qb2x5Z29uKHAsIGVsZW1lbnQuc2VnTGlzdCkgJiZcbiAgICAgICAgICAgICAgICAgICAgIXRoaXMubmF2SURzWm9uZUVkaXQuaW5jbHVkZXMobmF2aWdhdGlvbi5pZClcbiAgICAgICAgICAgICAgICApIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5uYXZJRHNab25lRWRpdC5wdXNoKG5hdmlnYXRpb24uaWQpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gb2xkIGNhbGlicmF0aW9uXG4gICAgICAgICAgICAvLyBjb25zdCBwb3NpdGlvbiA9IEpTT04ucGFyc2UobmF2aWdhdGlvbi5wb3NpdGlvbik7XG4gICAgICAgICAgICAvLyBjb25zdCBwID0ge1xuICAgICAgICAgICAgLy8gICAgIHg6IChjYWxpYnJhZ2Uub2Zmc2V0WCArIHBvc2l0aW9uLnggKiBjYWxpYnJhZ2UueCkgLyBjb2VmZlgsXG4gICAgICAgICAgICAvLyAgICAgeTogKGNhbGlicmFnZS5vZmZzZXRZICsgcG9zaXRpb24ueiAqIGNhbGlicmFnZS55KSAvIGNvZWZmWSxcbiAgICAgICAgICAgIC8vIH07XG4gICAgICAgICAgICAvLyBpZiAoZWxlbWVudC5hbmdsZSkge1xuICAgICAgICAgICAgLy8gICAgIHAgPSB0aGlzLnJvdGF0ZShcbiAgICAgICAgICAgIC8vICAgICAgICAgcCxcbiAgICAgICAgICAgIC8vICAgICAgICAgeyB4OiBlbGVtZW50LmN4LCB5OiBlbGVtZW50LmN5IH0sXG4gICAgICAgICAgICAvLyAgICAgICAgIGVsZW1lbnQuYW5nbGUsXG4gICAgICAgICAgICAvLyAgICAgKTtcbiAgICAgICAgICAgIC8vIH1cbiAgICAgICAgICAgIC8vIGlmIChcbiAgICAgICAgICAgIC8vICAgICBpc0luUG9seWdvbihwLCBlbGVtZW50LnNlZ0xpc3QpICYmXG4gICAgICAgICAgICAvLyAgICAgIXRoaXMubmF2SURzWm9uZUVkaXQuaW5jbHVkZXMobmF2aWdhdGlvbi5pZClcbiAgICAgICAgICAgIC8vICkge1xuICAgICAgICAgICAgLy8gICAgIHRoaXMubmF2SURzWm9uZUVkaXQucHVzaChuYXZpZ2F0aW9uLmlkKTtcbiAgICAgICAgICAgIC8vIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgY2xlYXJEaXZQbGFuKCkge1xuICAgICAgICBpZiAodGhpcy5kaXZQbGFuKSB0aGlzLmRpdlBsYW4uaW5uZXJIVE1MID0gXCJcIjtcbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIFRyaWdnZXIgZWFjaCBieSB0aGUgc2VsZWN0aW9uQ29tcG9uZW50IHdoZW4gc2VsZWN0aW9uIGNoYW5nZVxuICAgICAqIFVwZGF0ZSB0aGUgY3VycmVudCBzZWxlY3RlZCBzY2FuIGJ1dHRvbnNcbiAgICAgKiBAcGFyYW0gc2VsZWN0aW9uIG5ldyBzZWxlY3Rpb25cbiAgICAgKi9cbiAgICBvblNlbGVjdGlvbkNoYW5nZWQoc2VsZWN0aW9uOiBSZWN0YW5nbGUpIHtcbiAgICAgICAgY29uc3QgdW5zZWxlY3RlZEJ1dHRvbnM6IEhUTUxCdXR0b25FbGVtZW50W10gPSBbXTtcbiAgICAgICAgY29uc3QgbmV3U2VsZWN0ZWRCdXR0b25zID0gW107XG5cbiAgICAgICAgLyoqIEZvciBlYWNoIGJ1dHRvbiwgZGVjaWRlIHdoZXRoZXIgd2lsbCBiZSBhZGQgdG8gc2VsZWN0ZWQgbGlzdCBvciB1bnNlbGVjdGVkIGxpc3QgKi9cbiAgICAgICAgZm9yIChjb25zdCBidXR0b24gb2YgdGhpcy5idXR0b25FbGVtZW50cykge1xuICAgICAgICAgICAgY29uc3QgaXNTZWxlY3RlZCA9IGJ1dHRvbklzSW5TZWxlY3Rpb24oYnV0dG9uLCBzZWxlY3Rpb24pO1xuICAgICAgICAgICAgaWYgKHRoaXMuYnV0dG9uc0luU2VsZWN0aW9uLmluY2x1ZGVzKGJ1dHRvbikpIHtcbiAgICAgICAgICAgICAgICAvKiogSWYgdGhlIGJ1dHRvbiBpcyBhbHJlYWR5IGluIHRoZSBzZWxlY3RlZCBsaXN0LCB3ZSBjaGVjayBpZiBpdCBzaG91bGQgYmUgdW5zZWxlY3QgKi9cbiAgICAgICAgICAgICAgICBpZiAoIWlzU2VsZWN0ZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgdW5zZWxlY3RlZEJ1dHRvbnMucHVzaChidXR0b24pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNTZWxlY3RlZCkge1xuICAgICAgICAgICAgICAgIG5ld1NlbGVjdGVkQnV0dG9ucy5wdXNoKGJ1dHRvbik7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICAvKiogVmlzdWFsbHkgVXBkYXRlIHVuc2VsZWN0ZWQgbGlzdCAqL1xuICAgICAgICBmb3IgKGNvbnN0IGJ1dHRvbiBvZiB1bnNlbGVjdGVkQnV0dG9ucykge1xuICAgICAgICAgICAgc2V0VmlzdWFsbHlTZWxlY3RlZChidXR0b24sIGZhbHNlKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8qKiBWaXN1YWxseSBVcGRhdGUgc2VsZWN0ZWQgbGlzdCAqL1xuICAgICAgICBmb3IgKGNvbnN0IGJ1dHRvbiBvZiBuZXdTZWxlY3RlZEJ1dHRvbnMpIHtcbiAgICAgICAgICAgIHNldFZpc3VhbGx5U2VsZWN0ZWQoYnV0dG9uLCB0cnVlKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8qKiBSZW1vdmUgIHVuc2VsZWN0ZWQgbGlzdCAqL1xuICAgICAgICB0aGlzLmJ1dHRvbnNJblNlbGVjdGlvbiA9IHRoaXMuYnV0dG9uc0luU2VsZWN0aW9uLmZpbHRlcigoYnV0dG9uKSA9PiB7XG4gICAgICAgICAgICByZXR1cm4gIXVuc2VsZWN0ZWRCdXR0b25zLmluY2x1ZGVzKGJ1dHRvbik7XG4gICAgICAgIH0pO1xuICAgICAgICAvKiogQWRkIG5ldyBzZWxlY3RlZCBidXR0b25zICovXG4gICAgICAgIHRoaXMuYnV0dG9uc0luU2VsZWN0aW9uID0gW1xuICAgICAgICAgICAgLi4udGhpcy5idXR0b25zSW5TZWxlY3Rpb24sXG4gICAgICAgICAgICAuLi5uZXdTZWxlY3RlZEJ1dHRvbnMsXG4gICAgICAgIF07XG4gICAgfVxuXG5cblxuICAgIC8qKlxuICAgICAqIFRyaWdnZXIgd2hlbiB0aGUgdXNlciBjbGljayB0byBhZGQgdGhlIHNlbGVjdGVkIHNjYW5zXG4gICAgICovXG4gICAgb25TZWxlY3Rpb25BZGQoKSB7XG4gICAgICAgIGZvciAoY29uc3QgYnV0dG9uIG9mIHRoaXMuYnV0dG9uc0luU2VsZWN0aW9uKSB7XG4gICAgICAgICAgICBpZiAoIXRoaXMuY2hvc2VuU2NhbnNPblBsYW4uaW5jbHVkZXMoYnV0dG9uLmlkKSkge1xuICAgICAgICAgICAgICAgIHRoaXMub25CdXR0b25TY2FuQ2xpY2tlZChidXR0b24pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5vblNlbGVjdGlvbkNoYW5nZWQoeyB0b3A6IDAsIGxlZnQ6IDAsIHdpZHRoOiAwLCBoZWlnaHQ6IDAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVHJpZ2dlciB3aGVuIHRoZSB1c2VyIGNsaWNrIHRvIHJlbW92ZSB0aGUgc2VsZWN0ZWQgc2NhbnNcbiAgICAgKi9cbiAgICBvblNlbGVjdGlvblJlbW92ZSgpIHtcbiAgICAgICAgZm9yIChjb25zdCBidXR0b24gb2YgdGhpcy5idXR0b25zSW5TZWxlY3Rpb24pIHtcbiAgICAgICAgICAgIGlmICh0aGlzLmNob3NlblNjYW5zT25QbGFuLmluY2x1ZGVzKGJ1dHRvbi5pZCkpIHtcbiAgICAgICAgICAgICAgICB0aGlzLm9uQnV0dG9uU2NhbkNsaWNrZWQoYnV0dG9uKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICB0aGlzLm9uU2VsZWN0aW9uQ2hhbmdlZCh7IHRvcDogMCwgbGVmdDogMCwgd2lkdGg6IDAsIGhlaWdodDogMCB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUcmlnZ2VyIHdoZW4gdGhlIHVzZXIgY2xpY2sgdG8gc2VsZWN0IGFsbCBzY2Fuc1xuICAgICAqL1xuICAgIG9uU2VsZWN0QWxsKCkge1xuICAgICAgICB0aGlzLmJ1dHRvbnNJblNlbGVjdGlvbiA9IFsuLi50aGlzLmJ1dHRvbkVsZW1lbnRzXTtcbiAgICAgICAgZm9yIChjb25zdCBidXR0b24gb2YgdGhpcy5idXR0b25zSW5TZWxlY3Rpb24pIHtcbiAgICAgICAgICAgIHNldFZpc3VhbGx5U2VsZWN0ZWQoYnV0dG9uLCB0cnVlKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRyaWdnZXIgd2hlbiB0aGUgdXNlciBjaGFuZ2UgdGhlIHNpemUgb2YgdGhlIHNjYW4gcG9pbnRzXG4gICAgICogQHBhcmFtIGV2ZW50XG4gICAgICovXG4gICAgb25DaGFuZ2VTY2FuU2l6ZShldmVudDogYW55KSB7XG4gICAgICAgIGNvbnN0IGZhY3RvciA9IGV2ZW50LnRhcmdldC52YWx1ZTtcblxuICAgICAgICBmb3IgKGNvbnN0IGJ1dHRvbiBvZiB0aGlzLmJ1dHRvbkVsZW1lbnRzKSB7XG4gICAgICAgICAgICBidXR0b24uc3R5bGUudHJhbnNmb3JtID0gYHNjYWxlKCR7ZmFjdG9yfSlgO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogV2hlbiBhIGJ1dHRvbiByZXByZXNlbnRpbmcgYSBzY2FuIGlzIGNsaWNrZWRcbiAgICAgKiBAcGFyYW0gYnV0dG9uXG4gICAgICovXG4gICAgb25CdXR0b25TY2FuQ2xpY2tlZChidXR0b246IEhUTUxFbGVtZW50KSB7XG4gICAgICAgIHRoaXMuc2VsZWN0aW9uQ2hhbmdlZCA9IHRydWU7XG4gICAgICAgIGlmICh0aGlzLmlzU2V0dGluZ1N0YXJ0U3dlZXApIHtcbiAgICAgICAgICAgIGlmICh0aGlzLnN0YXJ0U3dlZXBJRCA9PT0gYnV0dG9uLmlkKSB7XG4gICAgICAgICAgICAgICAgLy8gd2UgZGVzZWxlY3QgdGhlIHN0YXJ0aW5nIHBvaW50XG4gICAgICAgICAgICAgICAgYnV0dG9uLnN0eWxlLmJhY2tncm91bmRJbWFnZSA9IGB1cmwoXCJodHRwczovL2FwaS5pY29uaWZ5LmRlc2lnbi9tZGk6YWRqdXN0LnN2Zz9jb2xvcj1ncmVlbiZoZWlnaHQ9MTcmd2lkdGg9MTdcIilgO1xuICAgICAgICAgICAgICAgIHRoaXMuc3RhcnRTd2VlcElEID0gbnVsbDtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBidXR0b24uc3R5bGUuYmFja2dyb3VuZEltYWdlID0gYHVybCgnaHR0cHM6Ly9hcGkuaWNvbmlmeS5kZXNpZ24vaWMvYmFzZWxpbmUtZmxhZy1jaXJjbGUuc3ZnP2NvbG9yPXdoaXRlJndpZHRoPTE3JmhlaWdodD0xNycpYDtcbiAgICAgICAgICAgIGlmICghdGhpcy5jaG9zZW5TY2Fuc09uUGxhbi5pbmNsdWRlcyhidXR0b24uaWQpKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5jaG9zZW5TY2Fuc09uUGxhbi5wdXNoKGJ1dHRvbi5pZCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodGhpcy5zdGFydFN3ZWVwSUQpIHtcbiAgICAgICAgICAgICAgICAvLyB3ZSBhcmUgY2hhbmdpbmcgc3RhcnQgc3dlZXBcbiAgICAgICAgICAgICAgICBjb25zdCBidG5DaGFuZ2VkID0gdGhpcy5idXR0b25FbGVtZW50cy5maW5kKChidG4pID0+IGJ0bi5pZCA9PT0gdGhpcy5zdGFydFN3ZWVwSUQpO1xuICAgICAgICAgICAgICAgIGJ0bkNoYW5nZWQuc3R5bGUuYmFja2dyb3VuZEltYWdlID0gYHVybChcImh0dHBzOi8vYXBpLmljb25pZnkuZGVzaWduL21kaTphZGp1c3Quc3ZnP2NvbG9yPWdyZWVuJmhlaWdodD0xNyZ3aWR0aD0xN1wiKWA7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLnN0YXJ0U3dlZXBJRCA9IGJ1dHRvbi5pZDtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBpZiAoIXRoaXMuY2hvc2VuU2NhbnNPblBsYW4uaW5jbHVkZXMoYnV0dG9uLmlkKSkge1xuICAgICAgICAgICAgLy8gYWRkIHRvIHNlbGVjdGlvblxuICAgICAgICAgICAgYnV0dG9uLnN0eWxlLmJhY2tncm91bmRJbWFnZSA9IGB1cmwoXCJodHRwczovL2FwaS5pY29uaWZ5LmRlc2lnbi9tZGk6YWRqdXN0LnN2Zz9jb2xvcj1ncmVlbiZoZWlnaHQ9MTcmd2lkdGg9MTdcIilgO1xuICAgICAgICAgICAgdGhpcy5jaG9zZW5TY2Fuc09uUGxhbi5wdXNoKGJ1dHRvbi5pZCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAvLyByZW1vdmUgZnJvbSBzZWxlY3Rpb25cbiAgICAgICAgICAgIGlmICh0aGlzLm9jY3VwaWVkU3dlZXBzLmluY2x1ZGVzKGJ1dHRvbi5pZCkgJiYgIXRoaXMubmF2SURzWm9uZUVkaXQuaW5jbHVkZXMoYnV0dG9uLmlkKSkge1xuICAgICAgICAgICAgICAgIC8vIHRoZSBzd2VlcCBiZWxvbmdzIHRvIGFub3RoZXIgem9uZSA9PiBzZXQgb3JhbmdlXG4gICAgICAgICAgICAgICAgYnV0dG9uLnN0eWxlLmJhY2tncm91bmRJbWFnZSA9IGB1cmwoXCJodHRwczovL2FwaS5pY29uaWZ5LmRlc2lnbi9tZGk6YWRqdXN0LnN2Zz9jb2xvcj1vcmFuZ2UmaGVpZ2h0PTE3JndpZHRoPTE3XCIpYDtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgYnV0dG9uLnN0eWxlLmJhY2tncm91bmRJbWFnZSA9IGB1cmwoXCJodHRwczovL2FwaS5pY29uaWZ5LmRlc2lnbi9tZGk6Y2xvc2UtY2lyY2xlLW91dGxpbmUuc3ZnP2NvbG9yPXJlZCZoZWlnaHQ9MTcmd2lkdGg9MTdcIilgO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3QgaW5kZXggPSB0aGlzLmNob3NlblNjYW5zT25QbGFuLmluZGV4T2YoYnV0dG9uLmlkKTtcbiAgICAgICAgICAgIHRoaXMuY2hvc2VuU2NhbnNPblBsYW4uc3BsaWNlKGluZGV4LCAxKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIG9uU2F2ZVNlbGVjdGlvbigpIHtcbiAgICAgICAgaWYgKHRoaXMubXVsdGlwbGVGbG9vcnMpIHtcbiAgICAgICAgICAgIC8vIHJhc3NlbWJsZSBhbGwgc3dlZXBzIHBlciBmbG9vcnNcbiAgICAgICAgICAgIGxldCBmaW5hbFN3ZWVwcyA9IFtdO1xuICAgICAgICAgICAgQXJyYXkuZnJvbSh0aGlzLmlucHV0U3dlZXBzUGVyRmxvb3Iua2V5cygpKS5mb3JFYWNoKGZsb29ySUQgPT4ge1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLmNob3NlblN3ZWVwc1BlckZsb29yLmdldChmbG9vcklEKSkge1xuICAgICAgICAgICAgICAgICAgICAvLyB0aGUgc3dlZXBzIGZvciB0aGlzIGZsb29yIHdlcmUgbW9kaWZpZWQsIHdlIHRha2UgdGhlbVxuICAgICAgICAgICAgICAgICAgICBmaW5hbFN3ZWVwcyA9IFsuLi5maW5hbFN3ZWVwcywgLi4udGhpcy5jaG9zZW5Td2VlcHNQZXJGbG9vci5nZXQoZmxvb3JJRCldO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIHdhcyBub3QgbW9kaWZpZWQsIHdlIHRha2UgdGhlIHByZXZpb3VzIHZhbHVlc1xuICAgICAgICAgICAgICAgICAgICBmaW5hbFN3ZWVwcyA9IFsuLi5maW5hbFN3ZWVwcywgLi4udGhpcy5pbnB1dFN3ZWVwc1BlckZsb29yLmdldChmbG9vcklEKV07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAvLyBjb25zb2xlLmxvZyhcImZpbmFsIHN3ZWVwc1wiLCBmaW5hbFN3ZWVwcyk7XG4gICAgICAgICAgICB0aGlzLnN3ZWVwc1NlbGVjdGVkLmVtaXQoeyBcInN3ZWVwc1wiOiBmaW5hbFN3ZWVwcywgXCJzdGFydFN3ZWVwSURcIjogdGhpcy5zdGFydFN3ZWVwSUQgfSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aGlzLnN3ZWVwc1NlbGVjdGVkLmVtaXQoeyBcInN3ZWVwc1wiOiB0aGlzLmNob3NlblNjYW5zT25QbGFuLCBcInN0YXJ0U3dlZXBJRFwiOiB0aGlzLnN0YXJ0U3dlZXBJRCB9KTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIG9uQ2FuY2VsKCkge1xuICAgICAgICBpZiAodGhpcy5zZWxlY3Rpb25DaGFuZ2VkKSB7XG4gICAgICAgICAgICBjb25zdCBtZXNzYWdlID0gdGhpcy50cmFuc2xhdGUuaW5zdGFudChcImNvbmZpcm0uY2FuY2VsTW9kaWZab25lU3dlZXBzXCIpO1xuICAgICAgICAgICAgaWYgKHdpbmRvdy5jb25maXJtKG1lc3NhZ2UpKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5zd2VlcHNTZWxlY3RlZC5lbWl0KG51bGwpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5zd2VlcHNTZWxlY3RlZC5lbWl0KG51bGwpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQWRkcyBjdXJyZW50IHNlbGVjdGlvbiBvZiBzd2VlcHMgZm9yIGN1cnJlbnQgZmxvb3IgKHBsYW4pIGZvciBtdWx0aWZsb29yIHpvbmUuXG4gICAgICogSXQgaGFzIHRvIGJlIHNhdmVkIGFueXdheSB3aXRoIG9uU2F2ZVNlbGVjdGlvbiFcbiAgICAgKi9cbiAgICBvblZhbGlkYXRlRm9yRmxvb3IoKSB7XG4gICAgICAgIGlmICh0aGlzLm11bHRpcGxlRmxvb3JzKSB7XG4gICAgICAgICAgICB0aGlzLmNob3NlblN3ZWVwc1BlckZsb29yLnNldCh0aGlzLmNob3NlblBsYW4uem9uZUlELCBbLi4udGhpcy5jaG9zZW5TY2Fuc09uUGxhbl0pO1xuICAgICAgICAgICAgdGhpcy5zZWxlY3Rpb25DaGFuZ2VkID0gZmFsc2U7XG4gICAgICAgIH1cbiAgICB9XG59XG4iLCI8ZGl2IG5nYkRyb3Bkb3duIGNsYXNzPVwic3Atcm93IGQtaW5saW5lLWJsb2NrXCI+XG4gICAgPGRpdiBjbGFzcz1cImNvbC1zbS0zXCIgKm5nSWY9XCJwbGFuc1wiPlxuICAgICAgICAgICAgPGJ1dHRvbiB0eXBlPVwiYnV0dG9uXCIgY2xhc3M9XCJidG4gYnRuLWxhYmVsLWZpbGUgcm91bmRlZC1waWxsXCIgaWQ9XCJkcm9wZG93bkJhc2ljMVwiXG4gICAgICAgICAgICAgICAgbmdiRHJvcGRvd25Ub2dnbGU+e3tjaG9zZW5QbGFuID9cbiAgICAgICAgICAgICAgICBjaG9zZW5QbGFuLm5hbWUgOiAoJ0Nob29zZSBQbGFuJyB8IHRyYW5zbGF0ZSkgfX08L2J1dHRvbj5cbiAgICAgICAgICAgIDxkaXYgbmdiRHJvcGRvd25NZW51IGFyaWEtbGFiZWxsZWRieT1cImRyb3Bkb3duQmFzaWMxXCI+XG4gICAgICAgICAgICAgICAgPGJ1dHRvbiB0eXBlPVwiYnV0dG9uXCIgbmdiRHJvcGRvd25JdGVtICpuZ0Zvcj1cImxldCBwbGFuIG9mIHBsYW5zXCIgKGNsaWNrKT1cIm9uUGxhbkNsaWNrKHBsYW4pXCJcbiAgICAgICAgICAgICAgICAgICAgW2Rpc2FibGVkXT1cIiFwbGFuLmNhbGlicmF0aW9uXCI+e3sgcGxhbi5uYW1lIH19XG4gICAgICAgICAgICAgICAgPC9idXR0b24+XG4gICAgICAgICAgICA8L2Rpdj5cbiAgICA8L2Rpdj5cbjwvZGl2PlxuPGRpdiBjbGFzcz1cInNwLXJvd1wiPlxuICAgIDxsaWItc2VsZWN0aW9uIGNsYXNzPVwiY29sLW1kLThcIiAob25TZWxlY3Rpb25DaGFuZ2VkKT1cIm9uU2VsZWN0aW9uQ2hhbmdlZCgkZXZlbnQpXCI+XG4gICAgICAgIDxsaWItcGxhbi1sZWdlbmQgW2lzQXVkaW9ab25lXT1cImVkaXRpbmdBdWRpb1pvbmVcIiAqbmdJZj1cImJ1dHRvbkVsZW1lbnRzLmxlbmd0aCA+IDBcIj48L2xpYi1wbGFuLWxlZ2VuZD5cbiAgICAgICAgPGRpdiBjbGFzcz1cInNlbGVjdFpvbmVcIiBvbmNvbnRleHRtZW51PVwicmV0dXJuIGZhbHNlO1wiPlxuICAgICAgICAgICAgPGRpdiBjbGFzcz1cInNwLXJvd1wiPlxuICAgICAgICAgICAgICAgIDxkaXYgc3R5bGU9XCJvdmVyZmxvdzogaGlkZGVuO3dpZHRoOjEwMCU7XCI+XG4gICAgICAgICAgICAgICAgICAgIDxkaXYgc3R5bGU9XCJoZWlnaHQ6IDQwMHB4OyB3aWR0aDogMTAwJTtcIiBpZD1cInBsYW5EaXZcIj5cbiAgICAgICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgPC9kaXY+XG4gICAgPC9saWItc2VsZWN0aW9uPlxuICAgIFxuICAgIDxkaXYgY2xhc3M9XCJjb2wtbWQtNCBzY2FuVG9vbFwiICpuZ0lmPVwiYnV0dG9uRWxlbWVudHMubGVuZ3RoID4gMFwiPlxuICAgICAgICA8ZGl2IGNsYXNzPVwic3Atcm93IGQtaW5saW5lLWJsb2NrXCI+XG4gICAgICAgICAgICA8aDI+e3snc2VsZWN0VG9vbC50aXRsZScgfCB0cmFuc2xhdGV9fTwvaDI+XG4gICAgICAgICAgICA8ZGl2IGNsYXNzPVwicHJvdGlwXCI+e3snc2VsZWN0VG9vbC50aXAnIHwgdHJhbnNsYXRlfX0uPC9kaXY+XG4gICAgICAgIDwvZGl2PlxuICAgIFxuICAgICAgICA8ZGl2IGNsYXNzPVwic3Atcm93XCI+XG4gICAgICAgICAgICA8ZGl2IGNsYXNzPVwiY29sLTNcIiBzdHlsZT1cInBhZGRpbmc6MHB4XCI+XG4gICAgICAgICAgICAgICAgPGxhYmVsIGNsYXNzPVwidG9vbC1sYWJlbFwiIGZvcj1cInNjYW5TaXplXCI+e3snc2VsZWN0VG9vbC5zaXplJyB8IHRyYW5zbGF0ZX19PC9sYWJlbD5cbiAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgPGRpdiBjbGFzcz1cImNvbC05XCI+XG4gICAgICAgICAgICAgICAgPGlucHV0IHR5cGU9XCJyYW5nZVwiIGNsYXNzPVwiZm9ybS1yYW5nZVwiIG1pbj1cIjAuMDAxXCIgbWF4PVwiNVwiIHN0ZXA9XCIwLjAxXCIgdmFsdWU9XCIxXCJcbiAgICAgICAgICAgICAgICAgICAgaWQ9XCJzY2FuU2l6ZVwiIChpbnB1dCk9XCJvbkNoYW5nZVNjYW5TaXplKCRldmVudClcIj5cbiAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICA8L2Rpdj5cbiAgICBcbiAgICAgICAgPGRpdiBjbGFzcz1cInNwLXJvd1wiPlxuICAgICAgICAgICAgPGJ1dHRvbiBjbGFzcz1cImJ0biBidG4tcHJpbWFyeSByb3VuZGVkLXBpbGxcIiAoY2xpY2spPVwib25TZWxlY3RBbGwoKVwiPnt7J3NlbGVjdFRvb2wuc2VsZWN0QWxsJyB8IHRyYW5zbGF0ZX19PC9idXR0b24+XG4gICAgICAgIDwvZGl2PlxuICAgIFxuICAgICAgICA8ZGl2ICpuZ0lmPVwiYnV0dG9uc0luU2VsZWN0aW9uLmxlbmd0aCA+IDBcIiBjbGFzcz1cImVkaXQtc2VsZWN0ZWRcIj5cbiAgICAgICAgICAgIDxzcGFuIGNsYXNzPVwidG9vbC1sYWJlbFwiPnt7J3NlbGVjdFRvb2wuZWRpdCcgfCB0cmFuc2xhdGV9fSA6IDwvc3Bhbj5cbiAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJzcC1yb3dcIj5cbiAgICAgICAgICAgICAgICA8YnV0dG9uIGNsYXNzPVwiYnRuIHJvdW5kZWQtcGlsbCBidG4tcHJpbWFyeSBtcy0zIG1lLTJcIiAoY2xpY2spPVwib25TZWxlY3Rpb25BZGQoKVwiPnt7J3NlbGVjdFRvb2wuYWRkJyB8IHRyYW5zbGF0ZX19PC9idXR0b24+XG4gICAgICAgICAgICAgICAgPGJ1dHRvbiBjbGFzcz1cImJ0biBidG4tcHJpbWFyeSByb3VuZGVkLXBpbGxcIiAoY2xpY2spPVwib25TZWxlY3Rpb25SZW1vdmUoKVwiPnt7J3NlbGVjdFRvb2wudW5kbycgfCB0cmFuc2xhdGV9fTwvYnV0dG9uPlxuICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgIDwvZGl2PlxuXG4gICAgICAgIDxkaXYgY2xhc3M9XCJzcC1yb3dcIj5cbiAgICAgICAgICAgIDxkaXYgKm5nSWY9XCJtdWx0aXBsZUZsb29yc1wiPiBcbiAgICAgICAgICAgICAgICB7eyBjaG9zZW5Td2VlcHNQZXJGbG9vci5nZXQoY2hvc2VuUGxhbi56b25lSUQpID8gY2hvc2VuU3dlZXBzUGVyRmxvb3IuZ2V0KGNob3NlblBsYW4uem9uZUlEKS5sZW5ndGggOiBcIjBcIn19IHt7J3NjYW4gcG9pbnRzIHNlbGVjdGVkIG9uIHRoaXMgZmxvb3InIHwgdHJhbnNsYXRlfX0gXG4gICAgICAgICAgICAgICAgPGJ1dHRvbiBjbGFzcz1cImJ0biBidG4tcHJpbWFyeSByb3VuZGVkLXBpbGxcIiAoY2xpY2spPVwib25WYWxpZGF0ZUZvckZsb29yKClcIiBbZGlzYWJsZWRdPVwiIXNlbGVjdGlvbkNoYW5nZWRcIj57eydVcGRhdGUgc2VsZWN0aW9uIGZvciB0aGlzIGZsb29yJyB8IHRyYW5zbGF0ZX19PC9idXR0b24+XG4gICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgIDxkaXYgKm5nSWY9XCIhbXVsdGlwbGVGbG9vcnNcIj5cbiAgICAgICAgICAgICAgICB7eyBjaG9zZW5TY2Fuc09uUGxhbi5sZW5ndGggfX0ge3snc2NhbiBwb2ludHMgY2hvc2VuJyB8IHRyYW5zbGF0ZX19ICBcbiAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICA8L2Rpdj5cbiAgICAgICAgPGRpdiAqbmdJZj1cIiFlZGl0aW5nQXVkaW9ab25lXCIgY2xhc3M9XCJzcC1yb3dcIj5cbiAgICAgICAgICAgIDxsaWItcmFkaW8tYnV0dG9uICBsYWJlbD1cInt7ICdzZWxlY3RUb29sLmNob29zZVN0YXJ0UG9pbnQnICB8IHRyYW5zbGF0ZSB9fVwiIChpc0NoZWNrZWRFdmVudCk9XCJpc1NldHRpbmdTdGFydFN3ZWVwPSFpc1NldHRpbmdTdGFydFN3ZWVwXCI+PC9saWItcmFkaW8tYnV0dG9uPlxuICAgICAgICA8L2Rpdj5cbiAgICAgICAgPGRpdiBjbGFzcz1cInNwLXJvd1wiPlxuICAgICAgICAgICAgPGJ1dHRvbiBjbGFzcz1cImJ0biBidG4tcHJpbWFyeSByb3VuZGVkLXBpbGxcIiAoY2xpY2spPVwib25TYXZlU2VsZWN0aW9uKClcIj57eydzZWxlY3RUb29sLnNhdmVTZWxlY3Rpb24nIHwgdHJhbnNsYXRlfX08L2J1dHRvbj5cbiAgICAgICAgICAgIDxidXR0b24gY2xhc3M9XCJidG4gYnRuLW91dGxpbmUtcHJpbWFyeSByb3VuZGVkLXBpbGxcIiAoY2xpY2spPVwib25DYW5jZWwoKVwiPnt7J3NlbGVjdFRvb2wuY2FuY2VsU2VsZWN0aW9uJyB8IHRyYW5zbGF0ZX19PC9idXR0b24+XG4gICAgICAgIDwvZGl2PlxuICAgIDwvZGl2PlxuXG48L2Rpdj5cbiAgIFxuIl19
|