@smarterplan/ngx-smarterplan-locations 0.3.4 → 0.4.2
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/esm2022/lib/components/carousel/carousel.component.mjs +30 -0
- package/esm2022/lib/components/chevron/chevron.component.mjs +18 -0
- package/esm2022/lib/components/detail-location/detail-location.component.mjs +183 -0
- package/{esm2020 → esm2022}/lib/components/form-location/form-location.component.mjs +254 -237
- package/esm2022/lib/components/images/images.component.mjs +120 -0
- package/esm2022/lib/components/locations/locations.component.mjs +157 -0
- package/esm2022/lib/components/locations/map/map-popup/map-popup.component.mjs +72 -0
- package/esm2022/lib/components/locations/map/map.component.mjs +92 -0
- package/esm2022/lib/components/plan-legend/plan-legend.component.mjs +49 -0
- package/esm2022/lib/components/plans/calibration/calibration.component.mjs +494 -0
- package/esm2022/lib/components/plans/edit-plan/edit-plan.component.mjs +350 -0
- package/{esm2020 → esm2022}/lib/components/plans/plans.component.mjs +243 -225
- package/esm2022/lib/components/tab-navigation/tab-navigation.component.mjs +43 -0
- package/esm2022/lib/components/visits/visits.component.mjs +294 -0
- package/esm2022/lib/components/zones/add-audio-zone/add-audio-zone.component.mjs +250 -0
- package/esm2022/lib/components/zones/add-zone/add-zone.component.mjs +333 -0
- package/esm2022/lib/components/zones/add-zone/selection/selection.component.mjs +81 -0
- package/esm2022/lib/components/zones/add-zone/sweep-plan-selection/sweep-plan-selection.component.mjs +518 -0
- package/esm2022/lib/components/zones/zones.component.mjs +291 -0
- package/{esm2020 → esm2022}/lib/helper.service.mjs +133 -133
- package/esm2022/lib/ngx-smarterplan-location-routing.module.mjs +50 -0
- package/esm2022/lib/ngx-smarterplan-locations.module.mjs +124 -0
- package/esm2022/lib/ngx-smarterplan-locations.service.mjs +15 -0
- package/esm2022/lib/pipes/count-audio-sweeps.pipe.mjs +29 -0
- package/esm2022/lib/radio-button/radio-button.component.mjs +28 -0
- package/{esm2020 → esm2022}/public-api.mjs +8 -8
- package/{esm2020 → esm2022}/smarterplan-ngx-smarterplan-locations.mjs +4 -4
- package/{fesm2020 → fesm2022}/smarterplan-ngx-smarterplan-locations.mjs +3959 -3738
- package/fesm2022/smarterplan-ngx-smarterplan-locations.mjs.map +1 -0
- package/index.d.ts +5 -5
- package/lib/components/carousel/carousel.component.d.ts +12 -12
- package/lib/components/chevron/chevron.component.d.ts +9 -9
- package/lib/components/detail-location/detail-location.component.d.ts +55 -55
- package/lib/components/form-location/form-location.component.d.ts +45 -45
- package/lib/components/images/images.component.d.ts +33 -33
- package/lib/components/locations/locations.component.d.ts +51 -51
- package/lib/components/locations/map/map-popup/map-popup.component.d.ts +22 -22
- package/lib/components/locations/map/map.component.d.ts +21 -22
- package/lib/components/plan-legend/plan-legend.component.d.ts +14 -14
- package/lib/components/plans/calibration/calibration.component.d.ts +140 -140
- package/lib/components/plans/edit-plan/edit-plan.component.d.ts +55 -55
- package/lib/components/plans/plans.component.d.ts +63 -63
- package/lib/components/tab-navigation/tab-navigation.component.d.ts +13 -13
- package/lib/components/visits/visits.component.d.ts +63 -63
- package/lib/components/zones/add-audio-zone/add-audio-zone.component.d.ts +63 -63
- package/lib/components/zones/add-zone/add-zone.component.d.ts +69 -69
- package/lib/components/zones/add-zone/selection/selection.component.d.ts +44 -44
- package/lib/components/zones/add-zone/sweep-plan-selection/sweep-plan-selection.component.d.ts +107 -107
- package/lib/components/zones/zones.component.d.ts +73 -73
- package/lib/helper.service.d.ts +53 -53
- package/lib/ngx-smarterplan-location-routing.module.d.ts +7 -7
- package/lib/ngx-smarterplan-locations.module.d.ts +36 -36
- package/lib/ngx-smarterplan-locations.service.d.ts +6 -6
- package/lib/pipes/count-audio-sweeps.pipe.d.ts +10 -10
- package/lib/radio-button/radio-button.component.d.ts +12 -12
- package/package.json +13 -19
- package/public-api.d.ts +4 -4
- package/esm2020/lib/components/carousel/carousel.component.mjs +0 -28
- package/esm2020/lib/components/chevron/chevron.component.mjs +0 -18
- package/esm2020/lib/components/detail-location/detail-location.component.mjs +0 -168
- package/esm2020/lib/components/images/images.component.mjs +0 -107
- package/esm2020/lib/components/locations/locations.component.mjs +0 -145
- package/esm2020/lib/components/locations/map/map-popup/map-popup.component.mjs +0 -66
- package/esm2020/lib/components/locations/map/map.component.mjs +0 -91
- package/esm2020/lib/components/plan-legend/plan-legend.component.mjs +0 -47
- package/esm2020/lib/components/plans/calibration/calibration.component.mjs +0 -468
- package/esm2020/lib/components/plans/edit-plan/edit-plan.component.mjs +0 -324
- package/esm2020/lib/components/tab-navigation/tab-navigation.component.mjs +0 -41
- package/esm2020/lib/components/visits/visits.component.mjs +0 -275
- package/esm2020/lib/components/zones/add-audio-zone/add-audio-zone.component.mjs +0 -230
- package/esm2020/lib/components/zones/add-zone/add-zone.component.mjs +0 -315
- package/esm2020/lib/components/zones/add-zone/selection/selection.component.mjs +0 -77
- package/esm2020/lib/components/zones/add-zone/sweep-plan-selection/sweep-plan-selection.component.mjs +0 -502
- package/esm2020/lib/components/zones/zones.component.mjs +0 -268
- package/esm2020/lib/ngx-smarterplan-location-routing.module.mjs +0 -49
- package/esm2020/lib/ngx-smarterplan-locations.module.mjs +0 -123
- package/esm2020/lib/ngx-smarterplan-locations.service.mjs +0 -14
- package/esm2020/lib/pipes/count-audio-sweeps.pipe.mjs +0 -27
- package/esm2020/lib/radio-button/radio-button.component.mjs +0 -26
- package/fesm2015/smarterplan-ngx-smarterplan-locations.mjs +0 -3983
- package/fesm2015/smarterplan-ngx-smarterplan-locations.mjs.map +0 -1
- package/fesm2020/smarterplan-ngx-smarterplan-locations.mjs.map +0 -1
|
@@ -1,502 +0,0 @@
|
|
|
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 "@ng-bootstrap/ng-bootstrap";
|
|
9
|
-
import * as i4 from "@angular/common";
|
|
10
|
-
import * as i5 from "../selection/selection.component";
|
|
11
|
-
import * as i6 from "../../../../radio-button/radio-button.component";
|
|
12
|
-
import * as i7 from "../../../plan-legend/plan-legend.component";
|
|
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: "15.2.10", 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: "14.0.0", version: "15.2.10", 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\">\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 <lib-plan-legend [isAudioZone]=\"editingAudioZone\" *ngIf=\"buttonElements.length > 0\"></lib-plan-legend>\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 <div *ngIf=\"multipleFloors\"> \r\n {{ chosenSweepsPerFloor.get(chosenPlan.zoneID) ? chosenSweepsPerFloor.get(chosenPlan.zoneID).length : \"0\"}} {{'scan points selected on this floor' | translate}} \r\n <button class=\"btn btn-primary rounded-pill\" (click)=\"onValidateForFloor()\" [disabled]=\"!selectionChanged\">{{'Update selection for this floor' | translate}}</button>\r\n </div>\r\n <div *ngIf=\"!multipleFloors\">\r\n {{ chosenScansOnPlan.length }} {{'scan points chosen' | translate}} \r\n </div>\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 <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{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"], dependencies: [{ kind: "directive", type: i3.NgbDropdown, selector: "[ngbDropdown]", inputs: ["autoClose", "dropdownClass", "open", "placement", "popperOptions", "container", "display"], outputs: ["openChange"], exportAs: ["ngbDropdown"] }, { kind: "directive", type: i3.NgbDropdownToggle, selector: "[ngbDropdownToggle]" }, { kind: "directive", type: i3.NgbDropdownMenu, selector: "[ngbDropdownMenu]" }, { kind: "directive", type: i3.NgbDropdownItem, selector: "[ngbDropdownItem]", inputs: ["disabled"] }, { kind: "directive", type: i4.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i5.SelectionComponent, selector: "lib-selection", outputs: ["onSelectionChanged"] }, { kind: "component", type: i6.RadioButtonComponent, selector: "lib-radio-button", inputs: ["label"], outputs: ["isCheckedEvent"] }, { kind: "component", type: i7.PlanLegendComponent, selector: "lib-plan-legend", inputs: ["isAudioZone"] }, { kind: "pipe", type: i2.TranslatePipe, name: "translate" }] });
|
|
480
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: SweepPlanSelectionComponent, decorators: [{
|
|
481
|
-
type: Component,
|
|
482
|
-
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 <lib-plan-legend [isAudioZone]=\"editingAudioZone\" *ngIf=\"buttonElements.length > 0\"></lib-plan-legend>\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 <div *ngIf=\"multipleFloors\"> \r\n {{ chosenSweepsPerFloor.get(chosenPlan.zoneID) ? chosenSweepsPerFloor.get(chosenPlan.zoneID).length : \"0\"}} {{'scan points selected on this floor' | translate}} \r\n <button class=\"btn btn-primary rounded-pill\" (click)=\"onValidateForFloor()\" [disabled]=\"!selectionChanged\">{{'Update selection for this floor' | translate}}</button>\r\n </div>\r\n <div *ngIf=\"!multipleFloors\">\r\n {{ chosenScansOnPlan.length }} {{'scan points chosen' | translate}} \r\n </div>\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 <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{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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QUcsS0FBSyxDQUFDO1NBQ2pDO0lBQ0wsQ0FBQzs7eUhBdGtCUSwyQkFBMkI7NkdBQTNCLDJCQUEyQixrWkNYeEMsOC9IQXlFQTs0RkQ5RGEsMkJBQTJCO2tCQUx2QyxTQUFTOytCQUNJLDBCQUEwQjsyTEFRM0IsT0FBTztzQkFBZixLQUFLO2dCQUVHLGlCQUFpQjtzQkFBekIsS0FBSztnQkFHRyxXQUFXO3NCQUFuQixLQUFLO2dCQUtHLGNBQWM7c0JBQXRCLEtBQUs7Z0JBR0csaUJBQWlCO3NCQUF6QixLQUFLO2dCQUdHLGdCQUFnQjtzQkFBeEIsS0FBSztnQkFFRyxTQUFTO3NCQUFqQixLQUFLO2dCQUVHLGNBQWM7c0JBQXRCLEtBQUs7Z0JBZ0JJLGNBQWM7c0JBQXZCLE1BQU0iLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBDb21wb25lbnQsIEV2ZW50RW1pdHRlciwgSW5wdXQsIE9uSW5pdCwgT3V0cHV0IH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XHJcbmltcG9ydCB7IFRyYW5zbGF0ZVNlcnZpY2UgfSBmcm9tICdAbmd4LXRyYW5zbGF0ZS9jb3JlJztcclxuaW1wb3J0IHsgZ2V0Q29lZmZpY2llbnRzRm9ySW1hZ2UsIGdldE1ldGFGb3JJbWFnZSwgTmF2aWdhdGlvbiwgTmF2aWdhdGlvblNlcnZpY2UsIFBsYW4sIFpvbmUsIHNob3dTY2FuUG9pbnRzT25QbGFuSW5EaXYsIFpvbmVTZXJ2aWNlLCBQbGFuU2VydmljZSB9IGZyb20gJ0BzbWFydGVycGxhbi9uZ3gtc21hcnRlcnBsYW4tY29yZSc7XHJcbmltcG9ydCBwYW56b29tLCB7IFBhblpvb20gfSBmcm9tICdwYW56b29tJztcclxuaW1wb3J0IHsgYnV0dG9uSXNJblNlbGVjdGlvbiwgaXNJblBvbHlnb24sIFJlY3RhbmdsZSwgcm90YXRlLCBzZXRWaXN1YWxseVNlbGVjdGVkLCBzdHlsZUJ1dHRvbiwgU3dlZXBTdGF0ZSB9IGZyb20gJy4uLy4uLy4uLy4uL2hlbHBlci5zZXJ2aWNlJztcclxuXHJcbkBDb21wb25lbnQoe1xyXG4gICAgc2VsZWN0b3I6ICdsaWItc3dlZXAtcGxhbi1zZWxlY3Rpb24nLFxyXG4gICAgdGVtcGxhdGVVcmw6ICcuL3N3ZWVwLXBsYW4tc2VsZWN0aW9uLmNvbXBvbmVudC5odG1sJyxcclxuICAgIHN0eWxlVXJsczogWycuL3N3ZWVwLXBsYW4tc2VsZWN0aW9uLmNvbXBvbmVudC5zY3NzJ11cclxufSlcclxuZXhwb3J0IGNsYXNzIFN3ZWVwUGxhblNlbGVjdGlvbkNvbXBvbmVudCBpbXBsZW1lbnRzIE9uSW5pdCB7XHJcblxyXG4gICAgcGxhbnM6IFBsYW5bXTtcclxuXHJcbiAgICBASW5wdXQoKSBzcGFjZUlEOiBzdHJpbmc7XHJcblxyXG4gICAgQElucHV0KCkgY2hvc2VuU2NhbnNPblBsYW46IHN0cmluZ1tdID0gW107XHJcblxyXG4gICAgLyoqIGlmIGNvbW1pbmcgZnJvbSBFZGl0IFBsYW4gU1ZHIFpvbmUgY3JlYXRpb24gKi9cclxuICAgIEBJbnB1dCgpIG5ld1pvbmVEYXRhOiBhbnk7XHJcblxyXG4gICAgbmF2SURzWm9uZUVkaXQ6IHN0cmluZ1tdID0gW107XHJcblxyXG4gICAgLy8gc3dlZXBzIGJlbG9uZ2luZyB0byBhbnkgYXVkaW8gem9uZVxyXG4gICAgQElucHV0KCkgb2NjdXBpZWRTd2VlcHM6IHN0cmluZ1tdID0gW107XHJcblxyXG4gICAgLy8gc3dlZXBzIHVuYXZhaWxhYmxlIChjYW5ub3QgYmUgY2hvc2VuKVxyXG4gICAgQElucHV0KCkgdW5hdmFpbGFibGVTd2VlcHM6IHN0cmluZ1tdID0gW107XHJcblxyXG4gICAgLy8gaWYgY2hvb3Npbmcgc3dlZXBzIGZvciBhdWRpbyB6b25lXHJcbiAgICBASW5wdXQoKSBlZGl0aW5nQXVkaW9ab25lOiBib29sZWFuID0gZmFsc2U7XHJcblxyXG4gICAgQElucHV0KCkgaW5wdXRab25lOiBab25lO1xyXG5cclxuICAgIEBJbnB1dCgpIG11bHRpcGxlRmxvb3JzOiBib29sZWFuID0gZmFsc2U7XHJcblxyXG4gICAgY2hvc2VuUGxhbjogUGxhbjtcclxuXHJcbiAgICAvKiogcGFuWm9vbSBlbGVtZW50IGZvciBhZGRpbmcgc2NhbnMgKi9cclxuICAgIHBhblpvb206IFBhblpvb207XHJcblxyXG4gICAgLyoqIGRpdlBsYW4gKHVzZSBCeSBwYW5ab29tKSAqL1xyXG4gICAgZGl2UGxhbjogSFRNTEVsZW1lbnQ7XHJcblxyXG4gICAgLyoqIGFsbCBzY2FuIGJ1dHRvbnMgRWxlbWVudCAqL1xyXG4gICAgYnV0dG9uRWxlbWVudHM6IEhUTUxCdXR0b25FbGVtZW50W10gPSBbXTtcclxuXHJcbiAgICAvKiogU2NhbiBidXR0b25zIHRoYXQgYXJlIGluIHRoZSBjdXJyZW50IHNlbGVjdGlvbiAqL1xyXG4gICAgYnV0dG9uc0luU2VsZWN0aW9uOiBIVE1MQnV0dG9uRWxlbWVudFtdID0gW107XHJcblxyXG4gICAgQE91dHB1dCgpIHN3ZWVwc1NlbGVjdGVkID0gbmV3IEV2ZW50RW1pdHRlcjx7IHN3ZWVwczogc3RyaW5nW107IHN0YXJ0U3dlZXBJRDogc3RyaW5nOyB9PigpO1xyXG5cclxuICAgIGlzU2V0dGluZ1N0YXJ0U3dlZXAgPSBmYWxzZTtcclxuXHJcbiAgICBzdGFydFN3ZWVwSUQ6IHN0cmluZztcclxuXHJcbiAgICBjaG9zZW5Td2VlcHNQZXJGbG9vciA9IG5ldyBNYXA8c3RyaW5nLCBzdHJpbmdbXT4oKTsgLy8gbWFwIG1hdGNoaW5nIGZsb29ySUQgdG8gc3dlZXBzIHNlbGVjdGVkXHJcblxyXG4gICAgaW5wdXRTd2VlcHNQZXJGbG9vciA9IG5ldyBNYXA8c3RyaW5nLCBzdHJpbmdbXT4oKTsgLy8gbWFwIG1hdGNoaW5nIGZsb29ySUQgdG8gc3dlZXBzIHNlbGVjdGVkIGZvciB6b25lIGluIGVkaXRpb25cclxuXHJcbiAgICBzZWxlY3Rpb25DaGFuZ2VkID0gZmFsc2U7XHJcblxyXG4gICAgY29uc3RydWN0b3IoXHJcbiAgICAgICAgcHJpdmF0ZSB6b25lU2VydmljZTogWm9uZVNlcnZpY2UsXHJcbiAgICAgICAgcHJpdmF0ZSBuYXZpZ2F0aW9uU2VydmljZTogTmF2aWdhdGlvblNlcnZpY2UsXHJcbiAgICAgICAgcHJpdmF0ZSBwbGFuU2VydmljZTogUGxhblNlcnZpY2UsXHJcbiAgICAgICAgcHJpdmF0ZSB0cmFuc2xhdGU6IFRyYW5zbGF0ZVNlcnZpY2UsXHJcbiAgICApIHsgfVxyXG5cclxuICAgIGFzeW5jIG5nT25Jbml0KCkge1xyXG4gICAgICAgIGF3YWl0IHRoaXMuZ2V0UGxhbnMoKTtcclxuICAgICAgICB0aGlzLnNldFN3ZWVwc09mSW5wdXRab25lKCk7XHJcbiAgICB9XHJcblxyXG4gICAgbmdPbkNoYW5nZXMoKSB7XHJcbiAgICAgICAgaWYgKHRoaXMuY2hvc2VuUGxhbikge1xyXG4gICAgICAgICAgICB0aGlzLnNldFN3ZWVwc09mSW5wdXRab25lKCk7XHJcbiAgICAgICAgICAgIHRoaXMuY2hvc2VuU2NhbnNPblBsYW4gPSBbXTtcclxuICAgICAgICAgICAgdGhpcy5jbGVhckRpdlBsYW4oKTtcclxuICAgICAgICAgICAgdGhpcy5hZGRTY2FuUG9pbnRzKCk7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIHNldFN3ZWVwc09mSW5wdXRab25lKCkge1xyXG4gICAgICAgIHRoaXMubmF2SURzWm9uZUVkaXQgPSB0aGlzLmlucHV0Wm9uZSA/IHRoaXMuaW5wdXRab25lLnN3ZWVwSURzIDogW107XHJcbiAgICAgICAgaWYgKHRoaXMubXVsdGlwbGVGbG9vcnMpIHtcclxuICAgICAgICAgICAgdGhpcy5wbGFucy5mb3JFYWNoKChwbGFuKSA9PiB7XHJcbiAgICAgICAgICAgICAgICBpZiAoIXRoaXMuaW5wdXRTd2VlcHNQZXJGbG9vci5nZXQocGxhbi56b25lSUQpKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5pbnB1dFN3ZWVwc1BlckZsb29yLnNldChwbGFuLnpvbmVJRCxcclxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5uYXZJRHNab25lRWRpdC5maWx0ZXIoKHN3ZWVwKSA9PiBwbGFuLnpvbmUuc3dlZXBJRHMuaW5jbHVkZXMoc3dlZXApKSk7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH0pO1xyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgIGlmICh0aGlzLmlucHV0Wm9uZSkge1xyXG4gICAgICAgICAgICAgICAgLy9maWx0ZXIgcGxhbnMgb25seSBmb3IgdGhlIHBhcmVudCBab25lXHJcbiAgICAgICAgICAgICAgICB0aGlzLnBsYW5zID0gdGhpcy5wbGFucy5maWx0ZXIoKHApID0+IHAuem9uZUlEID09PSB0aGlzLmlucHV0Wm9uZS5wYXJlbnRJRCk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgYXN5bmMgZ2V0UGxhbnMoKSB7XHJcbiAgICAgICAgdGhpcy5wbGFucyA9IGF3YWl0IHRoaXMucGxhblNlcnZpY2UuZ2V0U2luZ2VkUGxhbnNGb3JTcGFjZShcclxuICAgICAgICAgICAgdGhpcy5zcGFjZUlELFxyXG4gICAgICAgICk7XHJcbiAgICB9XHJcblxyXG4gICAgYXN5bmMgb25QbGFuQ2xpY2socGxhbjogUGxhbikge1xyXG4gICAgICAgIGNvbnN0IHN3aXRjaFBsYW4gPSAoKSA9PiB7XHJcbiAgICAgICAgICAgIHRoaXMuc2VsZWN0aW9uQ2hhbmdlZCA9IGZhbHNlO1xyXG4gICAgICAgICAgICB0aGlzLmNob3NlblBsYW4gPSBwbGFuO1xyXG4gICAgICAgICAgICB0aGlzLmNob3NlblNjYW5zT25QbGFuID0gW107XHJcbiAgICAgICAgICAgIHRoaXMuY2xlYXJEaXZQbGFuKCk7XHJcbiAgICAgICAgICAgIHRoaXMuYWRkU2NhblBvaW50cygpO1xyXG4gICAgICAgIH07XHJcbiAgICAgICAgaWYgKHRoaXMuc2VsZWN0aW9uQ2hhbmdlZCkge1xyXG4gICAgICAgICAgICBjb25zdCBtZXNzYWdlID0gdGhpcy50cmFuc2xhdGUuaW5zdGFudChcImNvbmZpcm0uY2FuY2VsTW9kaWZab25lU3dlZXBzXCIpO1xyXG4gICAgICAgICAgICBpZiAod2luZG93LmNvbmZpcm0obWVzc2FnZSkpIHtcclxuICAgICAgICAgICAgICAgIHN3aXRjaFBsYW4oKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgIHN3aXRjaFBsYW4oKTtcclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgYXN5bmMgYWRkU2NhblBvaW50cygpIHtcclxuICAgICAgICBsZXQgd2FzTW9kaWZpZWQgPSBmYWxzZTtcclxuICAgICAgICBpZiAodGhpcy5tdWx0aXBsZUZsb29ycykge1xyXG4gICAgICAgICAgICAvLyBjaGVjayBpZiB3ZSBoYXZlIGFscmVhZHkgdmFsaWRhdGVkIGJ1dHRvbnMgZm9yIHRoaXMgZmxvb3JcclxuICAgICAgICAgICAgaWYgKHRoaXMuY2hvc2VuU3dlZXBzUGVyRmxvb3IuZ2V0KHRoaXMuY2hvc2VuUGxhbi56b25lSUQpKSB7XHJcbiAgICAgICAgICAgICAgICB0aGlzLmNob3NlblNjYW5zT25QbGFuID0gdGhpcy5jaG9zZW5Td2VlcHNQZXJGbG9vci5nZXQodGhpcy5jaG9zZW5QbGFuLnpvbmVJRCk7XHJcbiAgICAgICAgICAgICAgICB3YXNNb2RpZmllZCA9IHRydWU7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICAgICAgdGhpcy5kaXZQbGFuID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvcihcIiNwbGFuRGl2XCIpIGFzIEhUTUxFbGVtZW50O1xyXG4gICAgICAgIGNvbnN0IHpvbmVPZlBsYW4gPSBhd2FpdCB0aGlzLnpvbmVTZXJ2aWNlLmdldFpvbmUoXHJcbiAgICAgICAgICAgIHRoaXMuY2hvc2VuUGxhbi56b25lSUQsXHJcbiAgICAgICAgKTtcclxuICAgICAgICBjb25zdCBuYXZpZ2F0aW9ucyA9IGF3YWl0IHRoaXMubmF2aWdhdGlvblNlcnZpY2UuZ2V0TmF2aWdhdGlvbnNGb3Jab25lKFxyXG4gICAgICAgICAgICB6b25lT2ZQbGFuLFxyXG4gICAgICAgICk7XHJcbiAgICAgICAgaWYgKHRoaXMubmV3Wm9uZURhdGEpIGF3YWl0IHRoaXMuc2V0U2NhbkJ5RHJhdyhuYXZpZ2F0aW9ucyk7XHJcbiAgICAgICAgdGhpcy5idXR0b25FbGVtZW50cyA9IGF3YWl0IHNob3dTY2FuUG9pbnRzT25QbGFuSW5EaXYoXHJcbiAgICAgICAgICAgIHRoaXMuY2hvc2VuUGxhbixcclxuICAgICAgICAgICAgdGhpcy5kaXZQbGFuLFxyXG4gICAgICAgICAgICBuYXZpZ2F0aW9ucyxcclxuICAgICAgICApO1xyXG4gICAgICAgIGZvciAoY29uc3QgZWxlbWVudCBvZiB0aGlzLmJ1dHRvbkVsZW1lbnRzKSB7XHJcbiAgICAgICAgICAgIGlmICh0aGlzLnVuYXZhaWxhYmxlU3dlZXBzICYmIHRoaXMudW5hdmFpbGFibGVTd2VlcHMuaW5jbHVkZXMoZWxlbWVudC5pZCkpIHtcclxuICAgICAgICAgICAgICAgIHN0eWxlQnV0dG9uKGVsZW1lbnQsIFN3ZWVwU3RhdGUuRElTQUJMRUQpO1xyXG4gICAgICAgICAgICB9IGVsc2Uge1xyXG5cclxuICAgICAgICAgICAgICAgIGlmICh3YXNNb2RpZmllZCkge1xyXG4gICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLmNob3NlblNjYW5zT25QbGFuLmluY2x1ZGVzKGVsZW1lbnQuaWQpKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHN0eWxlQnV0dG9uKGVsZW1lbnQsIFN3ZWVwU3RhdGUuQURERUQpO1xyXG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHN0eWxlQnV0dG9uKGVsZW1lbnQsIFN3ZWVwU3RhdGUuUkVNT1ZFRCk7XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgICAgICAgICBpZiAoXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMubmF2SURzWm9uZUVkaXQubGVuZ3RoID4gMCAmJlxyXG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLm5hdklEc1pvbmVFZGl0LmluY2x1ZGVzKGVsZW1lbnQuaWQpKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHN0eWxlQnV0dG9uKGVsZW1lbnQsIFN3ZWVwU3RhdGUuQURERUQpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoIXRoaXMuY2hvc2VuU2NhbnNPblBsYW4uaW5jbHVkZXMoZWxlbWVudC5pZCkpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY2hvc2VuU2NhbnNPblBsYW4ucHVzaChlbGVtZW50LmlkKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodGhpcy5vY2N1cGllZFN3ZWVwcyAmJiB0aGlzLm9jY3VwaWVkU3dlZXBzLmluY2x1ZGVzKGVsZW1lbnQuaWQpKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHN0eWxlQnV0dG9uKGVsZW1lbnQsIFN3ZWVwU3RhdGUuT0NDVVBJRUQpO1xyXG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHN0eWxlQnV0dG9uKGVsZW1lbnQsIFN3ZWVwU3RhdGUuUkVNT1ZFRCk7XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgICAgIC8vc3RhcnQgcG9pbnQgc2hvdWxkIGJlIGxhc3QgY29uZGl0aW9uIFxyXG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuaW5wdXRab25lICYmIHRoaXMuaW5wdXRab25lLnN0YXJ0U3dlZXBJRCA9PT0gZWxlbWVudC5pZCkge1xyXG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKFwic2V0dGluZyBzdGFydCBwb2ludFwiKTtcclxuICAgICAgICAgICAgICAgICAgICBzdHlsZUJ1dHRvbihlbGVtZW50LCBTd2VlcFN0YXRlLlNUQVJUUE9JTlQpO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgZWxlbWVudC5hZGRFdmVudExpc3RlbmVyKFwiY2xpY2tcIiwgKGV2ZW50KSA9PlxyXG4gICAgICAgICAgICAgICAgICAgIHRoaXMub25CdXR0b25TY2FuQ2xpY2tlZChldmVudC50YXJnZXQgYXMgSFRNTEVsZW1lbnQpLFxyXG4gICAgICAgICAgICAgICAgKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuICAgICAgICB0aGlzLnBhblpvb20gPSBwYW56b29tKHRoaXMuZGl2UGxhbiwge1xyXG4gICAgICAgICAgICBib3VuZHM6IHRydWUsXHJcbiAgICAgICAgICAgIGJvdW5kc1BhZGRpbmc6IDAsXHJcbiAgICAgICAgICAgIG1heFpvb206IDMuNSxcclxuICAgICAgICAgICAgYmVmb3JlTW91c2VEb3duKGU6IE1vdXNlRXZlbnQpIHtcclxuICAgICAgICAgICAgICAgIHJldHVybiAoXHJcbiAgICAgICAgICAgICAgICAgICAgZS5idXR0b24gPT09IDJcclxuICAgICAgICAgICAgICAgICk7IC8qKiBJZ25vcmUgZXZlbnQgZm9yIHJpZ2h0IGNsaWNrICh1c2UgZm9yIHNlbGVjdGluZykgKi9cclxuICAgICAgICAgICAgfSxcclxuICAgICAgICB9KTtcclxuICAgICAgICBpZiAodGhpcy5tdWx0aXBsZUZsb29ycykge1xyXG4gICAgICAgICAgICB0aGlzLmNob3NlblN3ZWVwc1BlckZsb29yLnNldCh0aGlzLmNob3NlblBsYW4uem9uZUlELCBbLi4udGhpcy5jaG9zZW5TY2Fuc09uUGxhbl0pO1xyXG4gICAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICAvKiogRnVuY3Rpb24gaWYgd2UgYXJlIGNvbWluZyBmb3Igc3ZnIGVkaXRvciB3b3JrZmxvdyAqL1xyXG4gICAgc2V0U2NhbkJ5RHJhdyhuYXZpZ2F0aW9uczogYW55W10pOiBQcm9taXNlPHZvaWQ+IHtcclxuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoYXN5bmMgKHJlc29sdmUpID0+IHtcclxuICAgICAgICAgICAgY29uc3QgcmVjdCA9IHtcclxuICAgICAgICAgICAgICAgIHdpZHRoOiB0aGlzLm5ld1pvbmVEYXRhLndpZHRoLFxyXG4gICAgICAgICAgICAgICAgaGVpZ2h0OiB0aGlzLm5ld1pvbmVEYXRhLmhlaWdodCxcclxuICAgICAgICAgICAgfTtcclxuICAgICAgICAgICAgY29uc3QgaW1nID0gYXdhaXQgZ2V0TWV0YUZvckltYWdlKHRoaXMuY2hvc2VuUGxhbi5maWxlcGF0aCk7XHJcbiAgICAgICAgICAgIGNvbnN0IHsgY29lZmZYLCBjb2VmZlkgfSA9IGdldENvZWZmaWNpZW50c0ZvckltYWdlKGltZywgcmVjdCk7XHJcblxyXG4gICAgICAgICAgICBjb25zdCBkcmF3ID0gdGhpcy5uZXdab25lRGF0YS5lbGVtZW50cztcclxuXHJcbiAgICAgICAgICAgIGRyYXcubWFwKGFzeW5jIChlbGVtZW50OiBhbnkpID0+IHtcclxuICAgICAgICAgICAgICAgIHN3aXRjaCAoZWxlbWVudC5ub2RlTmFtZSkge1xyXG4gICAgICAgICAgICAgICAgICAgIGNhc2UgXCJyZWN0XCI6XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGF3YWl0IHRoaXMuc2V0U2NhbkluUmVjdChcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGltZyxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvZWZmWCxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvZWZmWSxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsZW1lbnQsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBuYXZpZ2F0aW9ucyxcclxuICAgICAgICAgICAgICAgICAgICAgICAgKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XHJcblxyXG4gICAgICAgICAgICAgICAgICAgIGNhc2UgXCJlbGxpcHNlXCI6XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGF3YWl0IHRoaXMuc2V0U2NhbkluQ2lyY2xlKFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaW1nLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29lZmZYLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29lZmZZLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxlbWVudCxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5hdmlnYXRpb25zLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICApO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBcInBhdGhcIjpcclxuICAgICAgICAgICAgICAgICAgICAgICAgYXdhaXQgdGhpcy5zZXRTY2FuSW5Qb2x5Z29uKFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaW1nLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29lZmZYLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29lZmZZLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxlbWVudCxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5hdmlnYXRpb25zLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICApO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcclxuICAgICAgICAgICAgICAgICAgICBkZWZhdWx0OlxyXG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfSk7XHJcblxyXG4gICAgICAgICAgICByZXNvbHZlKCk7XHJcbiAgICAgICAgfSk7XHJcbiAgICB9XHJcblxyXG4gICAgYXN5bmMgc2V0U2NhbkluUmVjdChpbWc6IGFueSwgY29lZmZYOiBudW1iZXIsIGNvZWZmWTogbnVtYmVyLFxyXG4gICAgICAgIGVsZW1lbnQ6IHsgYW5nbGU6IGFueTsgY3g6IGFueTsgY3k6IGFueTsgeDogbnVtYmVyOyB3aWR0aDogYW55OyB5OiBudW1iZXI7IGhlaWdodDogYW55OyB9LCBuYXZpZ2F0aW9uczogYW55W10pIHtcclxuICAgICAgICBjb25zdCBjYWxpYnJhZ2UgPSBKU09OLnBhcnNlKHRoaXMuY2hvc2VuUGxhbi5jYWxpYnJhdGlvbik7XHJcbiAgICAgICAgbmF2aWdhdGlvbnMubWFwKChuYXZpZ2F0aW9uKSA9PiB7XHJcbiAgICAgICAgICAgIGNvbnN0IHBvc2l0aW9uc09uUGxhbiA9IG5hdmlnYXRpb24ucG9zaXRpb25PblBsYW4ubWFwKChlbnRyeSkgPT5cclxuICAgICAgICAgICAgICAgIEpTT04ucGFyc2UoZW50cnkpLFxyXG4gICAgICAgICAgICApO1xyXG4gICAgICAgICAgICBjb25zdCBwb3NpdGlvbk9uUGxhbiA9IHBvc2l0aW9uc09uUGxhbi5maW5kKFxyXG4gICAgICAgICAgICAgICAgKGRhdGEpID0+IGRhdGEucGxhbklEID09PSB0aGlzLmNob3NlblBsYW4uaWQsXHJcbiAgICAgICAgICAgICk7XHJcbiAgICAgICAgICAgIGlmIChwb3NpdGlvbk9uUGxhbikge1xyXG4gICAgICAgICAgICAgICAgY29uc3QgcmVhbFdpZHRoID0gaW1nLndpZHRoIC8gY29lZmZYO1xyXG4gICAgICAgICAgICAgICAgY29uc3QgcmVhbEhlaWdodCA9IGltZy5oZWlnaHQgLyBjb2VmZlk7XHJcbiAgICAgICAgICAgICAgICBjb25zdCBuYXZZID0gKHBvc2l0aW9uT25QbGFuLnkgKiByZWFsSGVpZ2h0KSAvIGNhbGlicmFnZS5pbWdIZWlnaHQ7XHJcbiAgICAgICAgICAgICAgICBjb25zdCBuYXZYID0gKHBvc2l0aW9uT25QbGFuLnggKiByZWFsV2lkdGgpIC8gY2FsaWJyYWdlLmltZ1dpZHRoO1xyXG4gICAgICAgICAgICAgICAgaWYgKFxyXG4gICAgICAgICAgICAgICAgICAgIG5hdlggPiBlbGVtZW50LnggJiZcclxuICAgICAgICAgICAgICAgICAgICBuYXZYIDwgZWxlbWVudC54ICsgZWxlbWVudC53aWR0aCAmJlxyXG4gICAgICAgICAgICAgICAgICAgIG5hdlkgPiBlbGVtZW50LnkgJiZcclxuICAgICAgICAgICAgICAgICAgICBuYXZZIDwgZWxlbWVudC55ICsgZWxlbWVudC5oZWlnaHQgJiZcclxuICAgICAgICAgICAgICAgICAgICAhdGhpcy5uYXZJRHNab25lRWRpdC5pbmNsdWRlcyhuYXZpZ2F0aW9uLmlkKVxyXG4gICAgICAgICAgICAgICAgKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5uYXZJRHNab25lRWRpdC5wdXNoKG5hdmlnYXRpb24uaWQpO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAvLyBvbGQgY2FsaWJyYXRpb246XHJcbiAgICAgICAgICAgIC8vIGNvbnN0IHBvc2l0aW9uID0gSlNPTi5wYXJzZShuYXZpZ2F0aW9uLnBvc2l0aW9uKTtcclxuICAgICAgICAgICAgLy8gbGV0IG5hdlggPSAoY2FsaWJyYWdlLm9mZnNldFggKyBwb3NpdGlvbi54ICogY2FsaWJyYWdlLngpIC8gY29lZmZYO1xyXG4gICAgICAgICAgICAvLyBsZXQgbmF2WSA9IChjYWxpYnJhZ2Uub2Zmc2V0WSArIHBvc2l0aW9uLnogKiBjYWxpYnJhZ2UueSkgLyBjb2VmZlk7XHJcbiAgICAgICAgICAgIC8vIGlmIChlbGVtZW50LmFuZ2xlKSB7XHJcbiAgICAgICAgICAgIC8vICAgICBjb25zdCByb3RhdGVQb3MgPSByb3RhdGUoXHJcbiAgICAgICAgICAgIC8vICAgICAgICAgeyB4OiBuYXZYLCB5OiBuYXZZIH0sXHJcbiAgICAgICAgICAgIC8vICAgICAgICAgeyB4OiBlbGVtZW50LmN4LCB5OiBlbGVtZW50LmN5IH0sXHJcbiAgICAgICAgICAgIC8vICAgICAgICAgZWxlbWVudC5hbmdsZSxcclxuICAgICAgICAgICAgLy8gICAgICk7XHJcbiAgICAgICAgICAgIC8vICAgICBuYXZYID0gcm90YXRlUG9zLng7XHJcbiAgICAgICAgICAgIC8vICAgICBuYXZZID0gcm90YXRlUG9zLnk7XHJcbiAgICAgICAgICAgIC8vIH1cclxuICAgICAgICAgICAgLyoqXHJcbiAgICAgICAgICAgICAqIFRPRE8gY2FsY3VsZXIgbGEgcm90YXRpb24gZHUgcmVjdGFuZ2xlXHJcbiAgICAgICAgICAgICAqL1xyXG4gICAgICAgICAgICAvLyBpZiAoXHJcbiAgICAgICAgICAgIC8vICAgICBuYXZYID4gZWxlbWVudC54ICYmXHJcbiAgICAgICAgICAgIC8vICAgICBuYXZYIDwgZWxlbWVudC54ICsgZWxlbWVudC53aWR0aCAmJlxyXG4gICAgICAgICAgICAvLyAgICAgbmF2WSA+IGVsZW1lbnQueSAmJlxyXG4gICAgICAgICAgICAvLyAgICAgbmF2WSA8IGVsZW1lbnQueSArIGVsZW1lbnQuaGVpZ2h0ICYmXHJcbiAgICAgICAgICAgIC8vICAgICAhdGhpcy5uYXZJRHNab25lRWRpdC5pbmNsdWRlcyhuYXZpZ2F0aW9uLmlkKVxyXG4gICAgICAgICAgICAvLyApIHtcclxuICAgICAgICAgICAgLy8gICAgIHRoaXMubmF2SURzWm9uZUVkaXQucHVzaChuYXZpZ2F0aW9uLmlkKTtcclxuICAgICAgICAgICAgLy8gfVxyXG4gICAgICAgIH0pO1xyXG4gICAgfSAvLyBFT1xyXG5cclxuICAgIGFzeW5jIHNldFNjYW5JbkNpcmNsZShpbWc6IGFueSwgY29lZmZYOiBudW1iZXIsIGNvZWZmWTogbnVtYmVyLFxyXG4gICAgICAgIGVsZW1lbnQ6IHsgYW5nbGU6IGFueTsgY3g6IG51bWJlcjsgY3k6IG51bWJlcjsgcng6IG51bWJlcjsgcnk6IG51bWJlcjsgfSwgbmF2aWdhdGlvbnM6IE5hdmlnYXRpb25bXSkge1xyXG4gICAgICAgIGNvbnN0IGNhbGlicmFnZSA9IEpTT04ucGFyc2UodGhpcy5jaG9zZW5QbGFuLmNhbGlicmF0aW9uKTtcclxuICAgICAgICBuYXZpZ2F0aW9ucy5tYXAobmF2aWdhdGlvbiA9PiB7XHJcbiAgICAgICAgICAgIGNvbnN0IHBvc2l0aW9uc09uUGxhbiA9IG5hdmlnYXRpb24ucG9zaXRpb25PblBsYW4ubWFwKChlbnRyeSkgPT5cclxuICAgICAgICAgICAgICAgIEpTT04ucGFyc2UoZW50cnkpLFxyXG4gICAgICAgICAgICApO1xyXG4gICAgICAgICAgICBjb25zdCBwb3NpdGlvbk9uUGxhbiA9IHBvc2l0aW9uc09uUGxhbi5maW5kKFxyXG4gICAgICAgICAgICAgICAgKGRhdGEpID0+IGRhdGEucGxhbklEID09PSB0aGlzLmNob3NlblBsYW4uaWQsXHJcbiAgICAgICAgICAgICk7XHJcbiAgICAgICAgICAgIGlmIChwb3NpdGlvbk9uUGxhbikge1xyXG4gICAgICAgICAgICAgICAgY29uc3QgcmVhbFdpZHRoID0gaW1nLndpZHRoIC8gY29lZmZYO1xyXG4gICAgICAgICAgICAgICAgY29uc3QgcmVhbEhlaWdodCA9IGltZy5oZWlnaHQgLyBjb2VmZlk7XHJcbiAgICAgICAgICAgICAgICBsZXQgbmF2WSA9IChwb3NpdGlvbk9uUGxhbi55ICogcmVhbEhlaWdodCkgLyBjYWxpYnJhZ2UuaW1nSGVpZ2h0O1xyXG4gICAgICAgICAgICAgICAgbGV0IG5hdlggPSAocG9zaXRpb25PblBsYW4ueCAqIHJlYWxXaWR0aCkgLyBjYWxpYnJhZ2UuaW1nV2lkdGg7XHJcbiAgICAgICAgICAgICAgICBpZiAoZWxlbWVudC5hbmdsZSkge1xyXG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHJvdGF0ZVBvcyA9IHJvdGF0ZShcclxuICAgICAgICAgICAgICAgICAgICAgICAgeyB4OiBuYXZYLCB5OiBuYXZZIH0sXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHsgeDogZWxlbWVudC5jeCwgeTogZWxlbWVudC5jeSB9LFxyXG4gICAgICAgICAgICAgICAgICAgICAgICBlbGVtZW50LmFuZ2xlLFxyXG4gICAgICAgICAgICAgICAgICAgICk7XHJcbiAgICAgICAgICAgICAgICAgICAgbmF2WCA9IHJvdGF0ZVBvcy54O1xyXG4gICAgICAgICAgICAgICAgICAgIG5hdlkgPSByb3RhdGVQb3MueTtcclxuICAgICAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgICAgICBjb25zdCB2YWx1ZVggPVxyXG4gICAgICAgICAgICAgICAgICAgIE1hdGgucG93KG5hdlggLSBlbGVtZW50LmN4LCAyKSAvIE1hdGgucG93KGVsZW1lbnQucngsIDIpO1xyXG4gICAgICAgICAgICAgICAgY29uc3QgdmFsdWVZID1cclxuICAgICAgICAgICAgICAgICAgICBNYXRoLnBvdyhuYXZZIC0gZWxlbWVudC5jeSwgMikgLyBNYXRoLnBvdyhlbGVtZW50LnJ5LCAyKTtcclxuICAgICAgICAgICAgICAgIGNvbnN0IHJlc3VsdCA9IHZhbHVlWCArIHZhbHVlWTtcclxuICAgICAgICAgICAgICAgIGlmIChyZXN1bHQgPD0gMSAmJiAhdGhpcy5uYXZJRHNab25lRWRpdC5pbmNsdWRlcyhuYXZpZ2F0aW9uLmlkKSkge1xyXG4gICAgICAgICAgICAgICAgICAgIHRoaXMubmF2SURzWm9uZUVkaXQucHVzaChuYXZpZ2F0aW9uLmlkKTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgLy8gb2xkIGNhbGlicmF0aW9uXHJcbiAgICAgICAgICAgIC8vIGNvbnN0IHBvc2l0aW9uID0gSlNPTi5wYXJzZShuYXZpZ2F0aW9uLnBvc2l0aW9uKTtcclxuICAgICAgICAgICAgLy8gbGV0IG5hdlggPSAoY2FsaWJyYWdlLm9mZnNldFggKyBwb3NpdGlvbi54ICogY2FsaWJyYWdlLngpIC8gY29lZmZYO1xyXG4gICAgICAgICAgICAvLyBsZXQgbmF2WSA9IChjYWxpYnJhZ2Uub2Zmc2V0WSArIHBvc2l0aW9uLnogKiBjYWxpYnJhZ2UueSkgLyBjb2VmZlk7XHJcbiAgICAgICAgICAgIC8vIGlmIChlbGVtZW50LmFuZ2xlKSB7XHJcbiAgICAgICAgICAgIC8vICAgICBjb25zdCByb3RhdGVQb3MgPSByb3RhdGUoXHJcbiAgICAgICAgICAgIC8vICAgICAgICAgeyB4OiBuYXZYLCB5OiBuYXZZIH0sXHJcbiAgICAgICAgICAgIC8vICAgICAgICAgeyB4OiBlbGVtZW50LmN4LCB5OiBlbGVtZW50LmN5IH0sXHJcbiAgICAgICAgICAgIC8vICAgICAgICAgZWxlbWVudC5hbmdsZSxcclxuICAgICAgICAgICAgLy8gICAgICk7XHJcbiAgICAgICAgICAgIC8vICAgICBuYXZYID0gcm90YXRlUG9zLng7XHJcbiAgICAgICAgICAgIC8vICAgICBuYXZZID0gcm90YXRlUG9zLnk7XHJcbiAgICAgICAgICAgIC8vIH1cclxuXHJcbiAgICAgICAgICAgIC8vIGNvbnN0IHZhbHVlWCA9XHJcbiAgICAgICAgICAgIC8vICAgICBNYXRoLnBvdyhuYXZYIC0gZWxlbWVudC5jeCwgMikgLyBNYXRoLnBvdyhlbGVtZW50LnJ4LCAyKTtcclxuICAgICAgICAgICAgLy8gY29uc3QgdmFsdWVZID1cclxuICAgICAgICAgICAgLy8gICAgIE1hdGgucG93KG5hdlkgLSBlbGVtZW50LmN5LCAyKSAvIE1hdGgucG93KGVsZW1lbnQucnksIDIpO1xyXG4gICAgICAgICAgICAvLyBjb25zdCByZXN1bHQgPSB2YWx1ZVggKyB2YWx1ZVk7XHJcbiAgICAgICAgICAgIC8vIGlmIChyZXN1bHQgPD0gMSAmJiAhdGhpcy5uYXZJRHNab25lRWRpdC5pbmNsdWRlcyhuYXZpZ2F0aW9uLmlkKSkge1xyXG4gICAgICAgICAgICAvLyAgICAgdGhpcy5uYXZJRHNab25lRWRpdC5wdXNoKG5hdmlnYXRpb24uaWQpO1xyXG4gICAgICAgICAgICAvLyB9XHJcbiAgICAgICAgfSk7XHJcbiAgICB9IC8vIEVPXHJcblxyXG4gICAgYXN5bmMgc2V0U2NhbkluUG9seWdvbihpbWc6IGFueSwgY29lZmZYOiBudW1iZXIsIGNvZWZmWTogbnVtYmVyLCBlbGVtZW50OiB7IHNlZ0xpc3Q6IGFueTsgfSwgbmF2aWdhdGlvbnM6IGFueVtdKSB7XHJcbiAgICAgICAgY29uc3QgY2FsaWJyYWdlID0gSlNPTi5wYXJzZSh0aGlzLmNob3NlblBsYW4uY2FsaWJyYXRpb24pO1xyXG4gICAgICAgIG5hdmlnYXRpb25zLm1hcChhc3luYyAobmF2aWdhdGlvbikgPT4ge1xyXG5cclxuICAgICAgICAgICAgY29uc3QgcG9zaXRpb25zT25QbGFuID0gbmF2aWdhdGlvbi5wb3NpdGlvbk9uUGxhbi5tYXAoKGVudHJ5KSA9PlxyXG4gICAgICAgICAgICAgICAgSlNPTi5wYXJzZShlbnRyeSksXHJcbiAgICAgICAgICAgICk7XHJcbiAgICAgICAgICAgIGNvbnN0IHBvc2l0aW9uT25QbGFuID0gcG9zaXRpb25zT25QbGFuLmZpbmQoXHJcbiAgICAgICAgICAgICAgICAoZGF0YSkgPT4gZGF0YS5wbGFuSUQgPT09IHRoaXMuY2hvc2VuUGxhbi5pZCxcclxuICAgICAgICAgICAgKTtcclxuICAgICAgICAgICAgaWYgKHBvc2l0aW9uT25QbGFuKSB7XHJcbiAgICAgICAgICAgICAgICBjb25zdCByZWFsV2lkdGggPSBpbWcud2lkdGggLyBjb2VmZlg7XHJcbiAgICAgICAgICAgICAgICBjb25zdCByZWFsSGVpZ2h0ID0gaW1nLmhlaWdodCAvIGNvZWZmWTtcclxuICAgICAgICAgICAgICAgIGxldCBuYXZZID0gKHBvc2l0aW9uT25QbGFuLnkgKiByZWFsSGVpZ2h0KSAvIGNhbGlicmFnZS5pbWdIZWlnaHQ7XHJcbiAgICAgICAgICAgICAgICBsZXQgbmF2WCA9IChwb3NpdGlvbk9uUGxhbi54ICogcmVhbFdpZHRoKSAvIGNhbGlicmFnZS5pbWdXaWR0aDtcclxuXHJcbiAgICAgICAgICAgICAgICBjb25zdCBwID0ge1xyXG4gICAgICAgICAgICAgICAgICAgIHg6IG5hdlgsXHJcbiAgICAgICAgICAgICAgICAgICAgeTogbmF2WSxcclxuICAgICAgICAgICAgICAgIH07XHJcbiAgICAgICAgICAgICAgICBpZiAoXHJcbiAgICAgICAgICAgICAgICAgICAgaXNJblBvbHlnb24ocCwgZWxlbWVudC5zZWdMaXN0KSAmJlxyXG4gICAgICAgICAgICAgICAgICAgICF0aGlzLm5hdklEc1pvbmVFZGl0LmluY2x1ZGVzKG5hdmlnYXRpb24uaWQpXHJcbiAgICAgICAgICAgICAgICApIHtcclxuICAgICAgICAgICAgICAgICAgICB0aGlzLm5hdklEc1pvbmVFZGl0LnB1c2gobmF2aWdhdGlvbi5pZCk7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIC8vIG9sZCBjYWxpYnJhdGlvblxyXG4gICAgICAgICAgICAvLyBjb25zdCBwb3NpdGlvbiA9IEpTT04ucGFyc2UobmF2aWdhdGlvbi5wb3NpdGlvbik7XHJcbiAgICAgICAgICAgIC8vIGNvbnN0IHAgPSB7XHJcbiAgICAgICAgICAgIC8vICAgICB4OiAoY2FsaWJyYWdlLm9mZnNldFggKyBwb3NpdGlvbi54ICogY2FsaWJyYWdlLngpIC8gY29lZmZYLFxyXG4gICAgICAgICAgICAvLyAgICAgeTogKGNhbGlicmFnZS5vZmZzZXRZICsgcG9zaXRpb24ueiAqIGNhbGlicmFnZS55KSAvIGNvZWZmWSxcclxuICAgICAgICAgICAgLy8gfTtcclxuICAgICAgICAgICAgLy8gaWYgKGVsZW1lbnQuYW5nbGUpIHtcclxuICAgICAgICAgICAgLy8gICAgIHAgPSB0aGlzLnJvdGF0ZShcclxuICAgICAgICAgICAgLy8gICAgICAgICBwLFxyXG4gICAgICAgICAgICAvLyAgICAgICAgIHsgeDogZWxlbWVudC5jeCwgeTogZWxlbWVudC5jeSB9LFxyXG4gICAgICAgICAgICAvLyAgICAgICAgIGVsZW1lbnQuYW5nbGUsXHJcbiAgICAgICAgICAgIC8vICAgICApO1xyXG4gICAgICAgICAgICAvLyB9XHJcbiAgICAgICAgICAgIC8vIGlmIChcclxuICAgICAgICAgICAgLy8gICAgIGlzSW5Qb2x5Z29uKHAsIGVsZW1lbnQuc2VnTGlzdCkgJiZcclxuICAgICAgICAgICAgLy8gICAgICF0aGlzLm5hdklEc1pvbmVFZGl0LmluY2x1ZGVzKG5hdmlnYXRpb24uaWQpXHJcbiAgICAgICAgICAgIC8vICkge1xyXG4gICAgICAgICAgICAvLyAgICAgdGhpcy5uYXZJRHNab25lRWRpdC5wdXNoKG5hdmlnYXRpb24uaWQpO1xyXG4gICAgICAgICAgICAvLyB9XHJcbiAgICAgICAgfSk7XHJcbiAgICB9XHJcblxyXG4gICAgY2xlYXJEaXZQbGFuKCkge1xyXG4gICAgICAgIGlmICh0aGlzLmRpdlBsYW4pIHRoaXMuZGl2UGxhbi5pbm5lckhUTUwgPSBcIlwiO1xyXG4gICAgfVxyXG5cclxuXHJcbiAgICAvKipcclxuICAgICAqIFRyaWdnZXIgZWFjaCBieSB0aGUgc2VsZWN0aW9uQ29tcG9uZW50IHdoZW4gc2VsZWN0aW9uIGNoYW5nZVxyXG4gICAgICogVXBkYXRlIHRoZSBjdXJyZW50IHNlbGVjdGVkIHNjYW4gYnV0dG9uc1xyXG4gICAgICogQHBhcmFtIHNlbGVjdGlvbiBuZXcgc2VsZWN0aW9uXHJcbiAgICAgKi9cclxuICAgIG9uU2VsZWN0aW9uQ2hhbmdlZChzZWxlY3Rpb246IFJlY3RhbmdsZSkge1xyXG4gICAgICAgIGNvbnN0IHVuc2VsZWN0ZWRCdXR0b25zOiBIVE1MQnV0dG9uRWxlbWVudFtdID0gW107XHJcbiAgICAgICAgY29uc3QgbmV3U2VsZWN0ZWRCdXR0b25zID0gW107XHJcblxyXG4gICAgICAgIC8qKiBGb3IgZWFjaCBidXR0b24sIGRlY2lkZSB3aGV0aGVyIHdpbGwgYmUgYWRkIHRvIHNlbGVjdGVkIGxpc3Qgb3IgdW5zZWxlY3RlZCBsaXN0ICovXHJcbiAgICAgICAgZm9yIChjb25zdCBidXR0b24gb2YgdGhpcy5idXR0b25FbGVtZW50cykge1xyXG4gICAgICAgICAgICBjb25zdCBpc1NlbGVjdGVkID0gYnV0dG9uSXNJblNlbGVjdGlvbihidXR0b24sIHNlbGVjdGlvbik7XHJcbiAgICAgICAgICAgIGlmICh0aGlzLmJ1dHRvbnNJblNlbGVjdGlvbi5pbmNsdWRlcyhidXR0b24pKSB7XHJcbiAgICAgICAgICAgICAgICAvKiogSWYgdGhlIGJ1dHRvbiBpcyBhbHJlYWR5IGluIHRoZSBzZWxlY3RlZCBsaXN0LCB3ZSBjaGVjayBpZiBpdCBzaG91bGQgYmUgdW5zZWxlY3QgKi9cclxuICAgICAgICAgICAgICAgIGlmICghaXNTZWxlY3RlZCkge1xyXG4gICAgICAgICAgICAgICAgICAgIHVuc2VsZWN0ZWRCdXR0b25zLnB1c2goYnV0dG9uKTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfSBlbHNlIGlmIChpc1NlbGVjdGVkKSB7XHJcbiAgICAgICAgICAgICAgICBuZXdTZWxlY3RlZEJ1dHRvbnMucHVzaChidXR0b24pO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICAvKiogVmlzdWFsbHkgVXBkYXRlIHVuc2VsZWN0ZWQgbGlzdCAqL1xyXG4gICAgICAgIGZvciAoY29uc3QgYnV0dG9uIG9mIHVuc2VsZWN0ZWRCdXR0b25zKSB7XHJcbiAgICAgICAgICAgIHNldFZpc3VhbGx5U2VsZWN0ZWQoYnV0dG9uLCBmYWxzZSk7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICAvKiogVmlzdWFsbHkgVXBkYXRlIHNlbGVjdGVkIGxpc3QgKi9cclxuICAgICAgICBmb3IgKGNvbnN0IGJ1dHRvbiBvZiBuZXdTZWxlY3RlZEJ1dHRvbnMpIHtcclxuICAgICAgICAgICAgc2V0VmlzdWFsbHlTZWxlY3RlZChidXR0b24sIHRydWUpO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgLyoqIFJlbW92ZSAgdW5zZWxlY3RlZCBsaXN0ICovXHJcbiAgICAgICAgdGhpcy5idXR0b25zSW5TZWxlY3Rpb24gPSB0aGlzLmJ1dHRvbnNJblNlbGVjdGlvbi5maWx0ZXIoKGJ1dHRvbikgPT4ge1xyXG4gICAgICAgICAgICByZXR1cm4gIXVuc2VsZWN0ZWRCdXR0b25zLmluY2x1ZGVzKGJ1dHRvbik7XHJcbiAgICAgICAgfSk7XHJcbiAgICAgICAgLyoqIEFkZCBuZXcgc2VsZWN0ZWQgYnV0dG9ucyAqL1xyXG4gICAgICAgIHRoaXMuYnV0dG9uc0luU2VsZWN0aW9uID0gW1xyXG4gICAgICAgICAgICAuLi50aGlzLmJ1dHRvbnNJblNlbGVjdGlvbixcclxuICAgICAgICAgICAgLi4ubmV3U2VsZWN0ZWRCdXR0b25zLFxyXG4gICAgICAgIF07XHJcbiAgICB9XHJcblxyXG5cclxuXHJcbiAgICAvKipcclxuICAgICAqIFRyaWdnZXIgd2hlbiB0aGUgdXNlciBjbGljayB0byBhZGQgdGhlIHNlbGVjdGVkIHNjYW5zXHJcbiAgICAgKi9cclxuICAgIG9uU2VsZWN0aW9uQWRkKCkge1xyXG4gICAgICAgIGZvciAoY29uc3QgYnV0dG9uIG9mIHRoaXMuYnV0dG9uc0luU2VsZWN0aW9uKSB7XHJcbiAgICAgICAgICAgIGlmICghdGhpcy5jaG9zZW5TY2Fuc09uUGxhbi5pbmNsdWRlcyhidXR0b24uaWQpKSB7XHJcbiAgICAgICAgICAgICAgICB0aGlzLm9uQnV0dG9uU2NhbkNsaWNrZWQoYnV0dG9uKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgdGhpcy5vblNlbGVjdGlvbkNoYW5nZWQoeyB0b3A6IDAsIGxlZnQ6IDAsIHdpZHRoOiAwLCBoZWlnaHQ6IDAgfSk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBUcmlnZ2VyIHdoZW4gdGhlIHVzZXIgY2xpY2sgdG8gcmVtb3ZlIHRoZSBzZWxlY3RlZCBzY2Fuc1xyXG4gICAgICovXHJcbiAgICBvblNlbGVjdGlvblJlbW92ZSgpIHtcclxuICAgICAgICBmb3IgKGNvbnN0IGJ1dHRvbiBvZiB0aGlzLmJ1dHRvbnNJblNlbGVjdGlvbikge1xyXG4gICAgICAgICAgICBpZiAodGhpcy5jaG9zZW5TY2Fuc09uUGxhbi5pbmNsdWRlcyhidXR0b24uaWQpKSB7XHJcbiAgICAgICAgICAgICAgICB0aGlzLm9uQnV0dG9uU2NhbkNsaWNrZWQoYnV0dG9uKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuICAgICAgICB0aGlzLm9uU2VsZWN0aW9uQ2hhbmdlZCh7IHRvcDogMCwgbGVmdDogMCwgd2lkdGg6IDAsIGhlaWdodDogMCB9KTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIFRyaWdnZXIgd2hlbiB0aGUgdXNlciBjbGljayB0byBzZWxlY3QgYWxsIHNjYW5zXHJcbiAgICAgKi9cclxuICAgIG9uU2VsZWN0QWxsKCkge1xyXG4gICAgICAgIHRoaXMuYnV0dG9uc0luU2VsZWN0aW9uID0gWy4uLnRoaXMuYnV0dG9uRWxlbWVudHNdO1xyXG4gICAgICAgIGZvciAoY29uc3QgYnV0dG9uIG9mIHRoaXMuYnV0dG9uc0luU2VsZWN0aW9uKSB7XHJcbiAgICAgICAgICAgIHNldFZpc3VhbGx5U2VsZWN0ZWQoYnV0dG9uLCB0cnVlKTtcclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBUcmlnZ2VyIHdoZW4gdGhlIHVzZXIgY2hhbmdlIHRoZSBzaXplIG9mIHRoZSBzY2FuIHBvaW50c1xyXG4gICAgICogQHBhcmFtIGV2ZW50XHJcbiAgICAgKi9cclxuICAgIG9uQ2hhbmdlU2NhblNpemUoZXZlbnQ6IGFueSkge1xyXG4gICAgICAgIGNvbnN0IGZhY3RvciA9IGV2ZW50LnRhcmdldC52YWx1ZTtcclxuXHJcbiAgICAgICAgZm9yIChjb25zdCBidXR0b24gb2YgdGhpcy5idXR0b25FbGVtZW50cykge1xyXG4gICAgICAgICAgICBidXR0b24uc3R5bGUudHJhbnNmb3JtID0gYHNjYWxlKCR7ZmFjdG9yfSlgO1xyXG4gICAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIFdoZW4gYSBidXR0b24gcmVwcmVzZW50aW5nIGEgc2NhbiBpcyBjbGlja2VkXHJcbiAgICAgKiBAcGFyYW0gYnV0dG9uXHJcbiAgICAgKi9cclxuICAgIG9uQnV0dG9uU2NhbkNsaWNrZWQoYnV0dG9uOiBIVE1MRWxlbWVudCkge1xyXG4gICAgICAgIHRoaXMuc2VsZWN0aW9uQ2hhbmdlZCA9IHRydWU7XHJcbiAgICAgICAgaWYgKHRoaXMuaXNTZXR0aW5nU3RhcnRTd2VlcCkge1xyXG4gICAgICAgICAgICBpZiAodGhpcy5zdGFydFN3ZWVwSUQgPT09IGJ1dHRvbi5pZCkge1xyXG4gICAgICAgICAgICAgICAgLy8gd2UgZGVzZWxlY3QgdGhlIHN0YXJ0aW5nIHBvaW50XHJcbiAgICAgICAgICAgICAgICBidXR0b24uc3R5bGUuYmFja2dyb3VuZEltYWdlID0gYHVybChcImh0dHBzOi8vYXBpLmljb25pZnkuZGVzaWduL21kaTphZGp1c3Quc3ZnP2NvbG9yPWdyZWVuJmhlaWdodD0xNyZ3aWR0aD0xN1wiKWA7XHJcbiAgICAgICAgICAgICAgICB0aGlzLnN0YXJ0U3dlZXBJRCA9IG51bGw7XHJcbiAgICAgICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgYnV0dG9uLnN0eWxlLmJhY2tncm91bmRJbWFnZSA9IGB1cmwoJ2h0dHBzOi8vYXBpLmljb25pZnkuZGVzaWduL2ljL2Jhc2VsaW5lLWZsYWctY2lyY2xlLnN2Zz9jb2xvcj13aGl0ZSZ3aWR0aD0xNyZoZWlnaHQ9MTcnKWA7XHJcbiAgICAgICAgICAgIGlmICghdGhpcy5jaG9zZW5TY2Fuc09uUGxhbi5pbmNsdWRlcyhidXR0b24uaWQpKSB7XHJcbiAgICAgICAgICAgICAgICB0aGlzLmNob3NlblNjYW5zT25QbGFuLnB1c2goYnV0dG9uLmlkKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICBpZiAodGhpcy5zdGFydFN3ZWVwSUQpIHtcclxuICAgICAgICAgICAgICAgIC8vIHdlIGFyZSBjaGFuZ2luZyBzdGFydCBzd2VlcFxyXG4gICAgICAgICAgICAgICAgY29uc3QgYnRuQ2hhbmdlZCA9IHRoaXMuYnV0dG9uRWxlbWVudHMuZmluZCgoYnRuKSA9PiBidG4uaWQgPT09IHRoaXMuc3RhcnRTd2VlcElEKTtcclxuICAgICAgICAgICAgICAgIGJ0bkNoYW5nZWQuc3R5bGUuYmFja2dyb3VuZEltYWdlID0gYHVybChcImh0dHBzOi8vYXBpLmljb25pZnkuZGVzaWduL21kaTphZGp1c3Quc3ZnP2NvbG9yPWdyZWVuJmhlaWdodD0xNyZ3aWR0aD0xN1wiKWA7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgdGhpcy5zdGFydFN3ZWVwSUQgPSBidXR0b24uaWQ7XHJcbiAgICAgICAgICAgIHJldHVybjtcclxuICAgICAgICB9XHJcbiAgICAgICAgaWYgKCF0aGlzLmNob3NlblNjYW5zT25QbGFuLmluY2x1ZGVzKGJ1dHRvbi5pZCkpIHtcclxuICAgICAgICAgICAgLy8gYWRkIHRvIHNlbGVjdGlvblxyXG4gICAgICAgICAgICBidXR0b24uc3R5bGUuYmFja2dyb3VuZEltYWdlID0gYHVybChcImh0dHBzOi8vYXBpLmljb25pZnkuZGVzaWduL21kaTphZGp1c3Quc3ZnP2NvbG9yPWdyZWVuJmhlaWdodD0xNyZ3aWR0aD0xN1wiKWA7XHJcbiAgICAgICAgICAgIHRoaXMuY2hvc2VuU2NhbnNPblBsYW4ucHVzaChidXR0b24uaWQpO1xyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgIC8vIHJlbW92ZSBmcm9tIHNlbGVjdGlvblxyXG4gICAgICAgICAgICBpZiAodGhpcy5vY2N1cGllZFN3ZWVwcy5pbmNsdWRlcyhidXR0b24uaWQpICYmICF0aGlzLm5hdklEc1pvbmVFZGl0LmluY2x1ZGVzKGJ1dHRvbi5pZCkpIHtcclxuICAgICAgICAgICAgICAgIC8vIHRoZSBzd2VlcCBiZWxvbmdzIHRvIGFub3RoZXIgem9uZSA9PiBzZXQgb3JhbmdlXHJcbiAgICAgICAgICAgICAgICBidXR0b24uc3R5bGUuYmFja2dyb3VuZEltYWdlID0gYHVybChcImh0dHBzOi8vYXBpLmljb25pZnkuZGVzaWduL21kaTphZGp1c3Quc3ZnP2NvbG9yPW9yYW5nZSZoZWlnaHQ9MTcmd2lkdGg9MTdcIilgO1xyXG4gICAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgYnV0dG9uLnN0eWxlLmJhY2tncm91bmRJbWFnZSA9IGB1cmwoXCJodHRwczovL2FwaS5pY29uaWZ5LmRlc2lnbi9tZGk6Y2xvc2UtY2lyY2xlLW91dGxpbmUuc3ZnP2NvbG9yPXJlZCZoZWlnaHQ9MTcmd2lkdGg9MTdcIilgO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIGNvbnN0IGluZGV4ID0gdGhpcy5jaG9zZW5TY2Fuc09uUGxhbi5pbmRleE9mKGJ1dHRvbi5pZCk7XHJcbiAgICAgICAgICAgIHRoaXMuY2hvc2VuU2NhbnNPblBsYW4uc3BsaWNlKGluZGV4LCAxKTtcclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgb25TYXZlU2VsZWN0aW9uKCkge1xyXG4gICAgICAgIGlmICh0aGlzLm11bHRpcGxlRmxvb3JzKSB7XHJcbiAgICAgICAgICAgIC8vIHJhc3NlbWJsZSBhbGwgc3dlZXBzIHBlciBmbG9vcnNcclxuICAgICAgICAgICAgbGV0IGZpbmFsU3dlZXBzID0gW107XHJcbiAgICAgICAgICAgIEFycmF5LmZyb20odGhpcy5pbnB1dFN3ZWVwc1BlckZsb29yLmtleXMoKSkuZm9yRWFjaChmbG9vcklEID0+IHtcclxuICAgICAgICAgICAgICAgIGlmICh0aGlzLmNob3NlblN3ZWVwc1BlckZsb29yLmdldChmbG9vcklEKSkge1xyXG4gICAgICAgICAgICAgICAgICAgIC8vIHRoZSBzd2VlcHMgZm9yIHRoaXMgZmxvb3Igd2VyZSBtb2RpZmllZCwgd2UgdGFrZSB0aGVtXHJcbiAgICAgICAgICAgICAgICAgICAgZmluYWxTd2VlcHMgPSBbLi4uZmluYWxTd2VlcHMsIC4uLnRoaXMuY2hvc2VuU3dlZXBzUGVyRmxvb3IuZ2V0KGZsb29ySUQpXTtcclxuICAgICAgICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgICAgICAgICAgLy8gd2FzIG5vdCBtb2RpZmllZCwgd2UgdGFrZSB0aGUgcHJldmlvdXMgdmFsdWVzXHJcbiAgICAgICAgICAgICAgICAgICAgZmluYWxTd2VlcHMgPSBbLi4uZmluYWxTd2VlcHMsIC4uLnRoaXMuaW5wdXRTd2VlcHNQZXJGbG9vci5nZXQoZmxvb3JJRCldO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB9KTtcclxuICAgICAgICAgICAgLy8gY29uc29sZS5sb2coXCJmaW5hbCBzd2VlcHNcIiwgZmluYWxTd2VlcHMpO1xyXG4gICAgICAgICAgICB0aGlzLnN3ZWVwc1NlbGVjdGVkLmVtaXQoeyBcInN3ZWVwc1wiOiBmaW5hbFN3ZWVwcywgXCJzdGFydFN3ZWVwSURcIjogdGhpcy5zdGFydFN3ZWVwSUQgfSk7XHJcbiAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgdGhpcy5zd2VlcHNTZWxlY3RlZC5lbWl0KHsgXCJzd2VlcHNcIjogdGhpcy5jaG9zZW5TY2Fuc09uUGxhbiwgXCJzdGFydFN3ZWVwSURcIjogdGhpcy5zdGFydFN3ZWVwSUQgfSk7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIG9uQ2FuY2VsKCkge1xyXG4gICAgICAgIGlmICh0aGlzLnNlbGVjdGlvbkNoYW5nZWQpIHtcclxuICAgICAgICAgICAgY29uc3QgbWVzc2FnZSA9IHRoaXMudHJhbnNsYXRlLmluc3RhbnQoXCJjb25maXJtLmNhbmNlbE1vZGlmWm9uZVN3ZWVwc1wiKTtcclxuICAgICAgICAgICAgaWYgKHdpbmRvdy5jb25maXJtKG1lc3NhZ2UpKSB7XHJcbiAgICAgICAgICAgICAgICB0aGlzLnN3ZWVwc1NlbGVjdGVkLmVtaXQobnVsbCk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICB0aGlzLnN3ZWVwc1NlbGVjdGVkLmVtaXQobnVsbCk7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogQWRkcyBjdXJyZW50IHNlbGVjdGlvbiBvZiBzd2VlcHMgZm9yIGN1cnJlbnQgZmxvb3IgKHBsYW4pIGZvciBtdWx0aWZsb29yIHpvbmUuXHJcbiAgICAgKiBJdCBoYXMgdG8gYmUgc2F2ZWQgYW55d2F5IHdpdGggb25TYXZlU2VsZWN0aW9uIVxyXG4gICAgICovXHJcbiAgICBvblZhbGlkYXRlRm9yRmxvb3IoKSB7XHJcbiAgICAgICAgaWYgKHRoaXMubXVsdGlwbGVGbG9vcnMpIHtcclxuICAgICAgICAgICAgdGhpcy5jaG9zZW5Td2VlcHNQZXJGbG9vci5zZXQodGhpcy5jaG9zZW5QbGFuLnpvbmVJRCwgWy4uLnRoaXMuY2hvc2VuU2NhbnNPblBsYW5dKTtcclxuICAgICAgICAgICAgdGhpcy5zZWxlY3Rpb25DaGFuZ2VkID0gZmFsc2U7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG59XHJcbiIsIjxkaXYgbmdiRHJvcGRvd24gY2xhc3M9XCJzcC1yb3cgZC1pbmxpbmUtYmxvY2tcIj5cclxuICAgIDxkaXYgY2xhc3M9XCJjb2wtc20tM1wiICpuZ0lmPVwicGxhbnNcIj5cclxuICAgICAgICAgICAgPGJ1dHRvbiB0eXBlPVwiYnV0dG9uXCIgY2xhc3M9XCJidG4gYnRuLWxhYmVsLWZpbGUgcm91bmRlZC1waWxsXCIgaWQ9XCJkcm9wZG93bkJhc2ljMVwiXHJcbiAgICAgICAgICAgICAgICBuZ2JEcm9wZG93blRvZ2dsZT57e2Nob3NlblBsYW4gP1xyXG4gICAgICAgICAgICAgICAgY2hvc2VuUGxhbi5uYW1lIDogKCdDaG9vc2UgUGxhbicgfCB0cmFuc2xhdGUpIH19PC9idXR0b24+XHJcbiAgICAgICAgICAgIDxkaXYgbmdiRHJvcGRvd25NZW51IGFyaWEtbGFiZWxsZWRieT1cImRyb3Bkb3duQmFzaWMxXCI+XHJcbiAgICAgICAgICAgICAgICA8YnV0dG9uIHR5cGU9XCJidXR0b25cIiBuZ2JEcm9wZG93bkl0ZW0gKm5nRm9yPVwibGV0IHBsYW4gb2YgcGxhbnNcIiAoY2xpY2spPVwib25QbGFuQ2xpY2socGxhbilcIlxyXG4gICAgICAgICAgICAgICAgICAgIFtkaXNhYmxlZF09XCIhcGxhbi5jYWxpYnJhdGlvblwiPnt7IHBsYW4ubmFtZSB9fVxyXG4gICAgICAgICAgICAgICAgPC9idXR0b24+XHJcbiAgICAgICAgICAgIDwvZGl2PlxyXG4gICAgPC9kaXY+XHJcbjwvZGl2PlxyXG48ZGl2IGNsYXNzPVwic3Atcm93XCI+XHJcbiAgICA8bGliLXNlbGVjdGlvbiBjbGFzcz1cImNvbC1tZC04XCIgKG9uU2VsZWN0aW9uQ2hhbmdlZCk9XCJvblNlbGVjdGlvbkNoYW5nZWQoJGV2ZW50KVwiPlxyXG4gICAgICAgIDxsaWItcGxhbi1sZWdlbmQgW2lzQXVkaW9ab25lXT1cImVkaXRpbmdBdWRpb1pvbmVcIiAqbmdJZj1cImJ1dHRvbkVsZW1lbnRzLmxlbmd0aCA+IDBcIj48L2xpYi1wbGFuLWxlZ2VuZD5cclxuICAgICAgICA8ZGl2IGNsYXNzPVwic2VsZWN0Wm9uZVwiIG9uY29udGV4dG1lbnU9XCJyZXR1cm4gZmFsc2U7XCI+XHJcbiAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJzcC1yb3dcIj5cclxuICAgICAgICAgICAgICAgIDxkaXYgc3R5bGU9XCJvdmVyZmxvdzogaGlkZGVuO3dpZHRoOjEwMCU7XCI+XHJcbiAgICAgICAgICAgICAgICAgICAgPGRpdiBzdHlsZT1cImhlaWdodDogNDAwcHg7IHdpZHRoOiAxMDAlO1wiIGlkPVwicGxhbkRpdlwiPlxyXG4gICAgICAgICAgICAgICAgICAgIDwvZGl2PlxyXG4gICAgICAgICAgICAgICAgPC9kaXY+XHJcbiAgICAgICAgICAgIDwvZGl2PlxyXG4gICAgICAgIDwvZGl2PlxyXG4gICAgPC9saWItc2VsZWN0aW9uPlxyXG4gICAgXHJcbiAgICA8ZGl2IGNsYXNzPVwiY29sLW1kLTQgc2NhblRvb2xcIiAqbmdJZj1cImJ1dHRvbkVsZW1lbnRzLmxlbmd0aCA+IDBcIj5cclxuICAgICAgICA8ZGl2IGNsYXNzPVwic3Atcm93IGQtaW5saW5lLWJsb2NrXCI+XHJcbiAgICAgICAgICAgIDxoMj57eydzZWxlY3RUb29sLnRpdGxlJyB8IHRyYW5zbGF0ZX19PC9oMj5cclxuICAgICAgICAgICAgPGRpdiBjbGFzcz1cInByb3RpcFwiPnt7J3NlbGVjdFRvb2wudGlwJyB8IHRyYW5zbGF0ZX19LjwvZGl2PlxyXG4gICAgICAgIDwvZGl2PlxyXG4gICAgXHJcbiAgICAgICAgPGRpdiBjbGFzcz1cInNwLXJvd1wiPlxyXG4gICAgICAgICAgICA8ZGl2IGNsYXNzPVwiY29sLTNcIiBzdHlsZT1cInBhZGRpbmc6MHB4XCI+XHJcbiAgICAgICAgICAgICAgICA8bGFiZWwgY2xhc3M9XCJ0b29sLWxhYmVsXCIgZm9yPVwic2NhblNpemVcIj57eydzZWxlY3RUb29sLnNpemUnIHwgdHJhbnNsYXRlfX08L2xhYmVsPlxyXG4gICAgICAgICAgICA8L2Rpdj5cclxuICAgICAgICAgICAgPGRpdiBjbGFzcz1cImNvbC05XCI+XHJcbiAgICAgICAgICAgICAgICA8aW5wdXQgdHlwZT1cInJhbmdlXCIgY2xhc3M9XCJmb3JtLXJhbmdlXCIgbWluPVwiMC4wMDFcIiBtYXg9XCI1XCIgc3RlcD1cIjAuMDFcIiB2YWx1ZT1cIjFcIlxyXG4gICAgICAgICAgICAgICAgICAgIGlkPVwic2NhblNpemVcIiAoaW5wdXQpPVwib25DaGFuZ2VTY2FuU2l6ZSgkZXZlbnQpXCI+XHJcbiAgICAgICAgICAgIDwvZGl2PlxyXG4gICAgICAgIDwvZGl2PlxyXG4gICAgXHJcbiAgICAgICAgPGRpdiBjbGFzcz1cInNwLXJvd1wiPlxyXG4gICAgICAgICAgICA8YnV0dG9uIGNsYXNzPVwiYnRuIGJ0bi1wcmltYXJ5IHJvdW5kZWQtcGlsbFwiIChjbGljayk9XCJvblNlbGVjdEFsbCgpXCI+e3snc2VsZWN0VG9vbC5zZWxlY3RBbGwnIHwgdHJhbnNsYXRlfX08L2J1dHRvbj5cclxuICAgICAgICA8L2Rpdj5cclxuICAgIFxyXG4gICAgICAgIDxkaXYgKm5nSWY9XCJidXR0b25zSW5TZWxlY3Rpb24ubGVuZ3RoID4gMFwiIGNsYXNzPVwiZWRpdC1zZWxlY3RlZFwiPlxyXG4gICAgICAgICAgICA8c3BhbiBjbGFzcz1cInRvb2wtbGFiZWxcIj57eydzZWxlY3RUb29sLmVkaXQnIHwgdHJhbnNsYXRlfX0gOiA8L3NwYW4+XHJcbiAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJzcC1yb3dcIj5cclxuICAgICAgICAgICAgICAgIDxidXR0b24gY2xhc3M9XCJidG4gcm91bmRlZC1waWxsIGJ0bi1wcmltYXJ5IG1zLTMgbWUtMlwiIChjbGljayk9XCJvblNlbGVjdGlvbkFkZCgpXCI+e3snc2VsZWN0VG9vbC5hZGQnIHwgdHJhbnNsYXRlfX08L2J1dHRvbj5cclxuICAgICAgICAgICAgICAgIDxidXR0b24gY2xhc3M9XCJidG4gYnRuLXByaW1hcnkgcm91bmRlZC1waWxsXCIgKGNsaWNrKT1cIm9uU2VsZWN0aW9uUmVtb3ZlKClcIj57eydzZWxlY3RUb29sLnVuZG8nIHwgdHJhbnNsYXRlfX08L2J1dHRvbj5cclxuICAgICAgICAgICAgPC9kaXY+XHJcbiAgICAgICAgPC9kaXY+XHJcblxyXG4gICAgICAgIDxkaXYgY2xhc3M9XCJzcC1yb3dcIj5cclxuICAgICAgICAgICAgPGRpdiAqbmdJZj1cIm11bHRpcGxlRmxvb3JzXCI+IFxyXG4gICAgICAgICAgICAgICAge3sgY2hvc2VuU3dlZXBzUGVyRmxvb3IuZ2V0KGNob3NlblBsYW4uem9uZUlEKSA/IGNob3NlblN3ZWVwc1BlckZsb29yLmdldChjaG9zZW5QbGFuLnpvbmVJRCkubGVuZ3RoIDogXCIwXCJ9fSB7eydzY2FuIHBvaW50cyBzZWxlY3RlZCBvbiB0aGlzIGZsb29yJyB8IHRyYW5zbGF0ZX19IFxyXG4gICAgICAgICAgICAgICAgPGJ1dHRvbiBjbGFzcz1cImJ0biBidG4tcHJpbWFyeSByb3VuZGVkLXBpbGxcIiAoY2xpY2spPVwib25WYWxpZGF0ZUZvckZsb29yKClcIiBbZGlzYWJsZWRdPVwiIXNlbGVjdGlvbkNoYW5nZWRcIj57eydVcGRhdGUgc2VsZWN0aW9uIGZvciB0aGlzIGZsb29yJyB8IHRyYW5zbGF0ZX19PC9idXR0b24+XHJcbiAgICAgICAgICAgIDwvZGl2PlxyXG4gICAgICAgICAgICA8ZGl2ICpuZ0lmPVwiIW11bHRpcGxlRmxvb3JzXCI+XHJcbiAgICAgICAgICAgICAgICB7eyBjaG9zZW5TY2Fuc09uUGxhbi5sZW5ndGggfX0ge3snc2NhbiBwb2ludHMgY2hvc2VuJyB8IHRyYW5zbGF0ZX19ICBcclxuICAgICAgICAgICAgPC9kaXY+XHJcbiAgICAgICAgPC9kaXY+XHJcbiAgICAgICAgPGRpdiAqbmdJZj1cIiFlZGl0aW5nQXVkaW9ab25lXCIgY2xhc3M9XCJzcC1yb3dcIj5cclxuICAgICAgICAgICAgPGxpYi1yYWRpby1idXR0b24gIGxhYmVsPVwie3sgJ3NlbGVjdFRvb2wuY2hvb3NlU3RhcnRQb2ludCcgIHwgdHJhbnNsYXRlIH19XCIgKGlzQ2hlY2tlZEV2ZW50KT1cImlzU2V0dGluZ1N0YXJ0U3dlZXA9IWlzU2V0dGluZ1N0YXJ0U3dlZXBcIj48L2xpYi1yYWRpby1idXR0b24+XHJcbiAgICAgICAgPC9kaXY+XHJcbiAgICAgICAgPGRpdiBjbGFzcz1cInNwLXJvd1wiPlxyXG4gICAgICAgICAgICA8YnV0dG9uIGNsYXNzPVwiYnRuIGJ0bi1wcmltYXJ5IHJvdW5kZWQtcGlsbFwiIChjbGljayk9XCJvblNhdmVTZWxlY3Rpb24oKVwiPnt7J3NlbGVjdFRvb2wuc2F2ZVNlbGVjdGlvbicgfCB0cmFuc2xhdGV9fTwvYnV0dG9uPlxyXG4gICAgICAgICAgICA8YnV0dG9uIGNsYXNzPVwiYnRuIGJ0bi1vdXRsaW5lLXByaW1hcnkgcm91bmRlZC1waWxsXCIgKGNsaWNrKT1cIm9uQ2FuY2VsKClcIj57eydzZWxlY3RUb29sLmNhbmNlbFNlbGVjdGlvbicgfCB0cmFuc2xhdGV9fTwvYnV0dG9uPlxyXG4gICAgICAgIDwvZGl2PlxyXG4gICAgPC9kaXY+XHJcblxyXG48L2Rpdj5cclxuICAgXHJcbiJdfQ==
|