@smarterplan/ngx-smarterplan-locations 0.2.21 → 0.2.22
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/esm2020/lib/components/carousel/carousel.component.mjs +27 -27
- package/esm2020/lib/components/chevron/chevron.component.mjs +17 -17
- package/esm2020/lib/components/detail-location/detail-location.component.mjs +154 -154
- package/esm2020/lib/components/form-location/form-location.component.mjs +237 -237
- package/esm2020/lib/components/images/images.component.mjs +90 -90
- package/esm2020/lib/components/locations/locations.component.mjs +141 -141
- package/esm2020/lib/components/locations/map/map-popup/map-popup.component.mjs +65 -65
- package/esm2020/lib/components/locations/map/map.component.mjs +90 -90
- package/esm2020/lib/components/plan-legend/plan-legend.component.mjs +47 -0
- package/esm2020/lib/components/plans/calibration/calibration.component.mjs +468 -468
- package/esm2020/lib/components/plans/edit-plan/edit-plan.component.mjs +324 -324
- package/esm2020/lib/components/plans/plans.component.mjs +210 -210
- package/esm2020/lib/components/tab-navigation/tab-navigation.component.mjs +41 -41
- package/esm2020/lib/components/visits/visits.component.mjs +235 -235
- package/esm2020/lib/components/zones/add-audio-zone/add-audio-zone.component.mjs +230 -230
- package/esm2020/lib/components/zones/add-zone/add-zone.component.mjs +294 -294
- package/esm2020/lib/components/zones/add-zone/selection/selection.component.mjs +76 -76
- package/esm2020/lib/components/zones/add-zone/sweep-plan-selection/sweep-plan-selection.component.mjs +414 -413
- package/esm2020/lib/components/zones/zones.component.mjs +236 -232
- package/esm2020/lib/helper.service.mjs +134 -134
- package/esm2020/lib/ngx-smarterplan-location-routing.module.mjs +49 -49
- package/esm2020/lib/ngx-smarterplan-locations.module.mjs +125 -122
- package/esm2020/lib/ngx-smarterplan-locations.service.mjs +13 -13
- package/esm2020/lib/pipes/count-audio-sweeps.pipe.mjs +26 -26
- package/esm2020/lib/radio-button/radio-button.component.mjs +26 -26
- package/esm2020/public-api.mjs +8 -8
- package/esm2020/smarterplan-ngx-smarterplan-locations.mjs +4 -4
- package/fesm2015/smarterplan-ngx-smarterplan-locations.mjs +3676 -3624
- package/fesm2015/smarterplan-ngx-smarterplan-locations.mjs.map +1 -1
- package/fesm2020/smarterplan-ngx-smarterplan-locations.mjs +3520 -3472
- package/fesm2020/smarterplan-ngx-smarterplan-locations.mjs.map +1 -1
- 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 +51 -51
- package/lib/components/form-location/form-location.component.d.ts +45 -45
- package/lib/components/images/images.component.d.ts +28 -28
- package/lib/components/locations/locations.component.d.ts +50 -50
- package/lib/components/locations/map/map-popup/map-popup.component.d.ts +22 -22
- package/lib/components/locations/map/map.component.d.ts +22 -22
- package/lib/components/plan-legend/plan-legend.component.d.ts +14 -0
- 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 +59 -59
- package/lib/components/tab-navigation/tab-navigation.component.d.ts +13 -13
- package/lib/components/visits/visits.component.d.ts +51 -51
- 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 +67 -67
- 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 +96 -96
- package/lib/components/zones/zones.component.d.ts +67 -67
- 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 -35
- 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 +1 -1
- package/public-api.d.ts +4 -4
- package/smarterplan-ngx-smarterplan-locations.d.ts +5 -5
|
@@ -1,468 +1,468 @@
|
|
|
1
|
-
import { Component, ViewChild } from '@angular/core';
|
|
2
|
-
import { getDocument } from 'pdfjs-dist';
|
|
3
|
-
import { getMetaForImage, } from '@smarterplan/ngx-smarterplan-core';
|
|
4
|
-
import panzoom from 'panzoom';
|
|
5
|
-
import * as i0 from "@angular/core";
|
|
6
|
-
import * as i1 from "@smarterplan/ngx-smarterplan-core";
|
|
7
|
-
import * as i2 from "@angular/router";
|
|
8
|
-
import * as i3 from "@ngx-translate/core";
|
|
9
|
-
import * as i4 from "../../tab-navigation/tab-navigation.component";
|
|
10
|
-
import * as i5 from "@angular/common";
|
|
11
|
-
import * as i6 from "@angular/forms";
|
|
12
|
-
import * as i7 from "@ng-bootstrap/ng-bootstrap";
|
|
13
|
-
export class CalibrationComponent {
|
|
14
|
-
constructor(matterportImportService, planService, route, router, zoneService, spaceService, navigationService, translate) {
|
|
15
|
-
this.matterportImportService = matterportImportService;
|
|
16
|
-
this.planService = planService;
|
|
17
|
-
this.route = route;
|
|
18
|
-
this.router = router;
|
|
19
|
-
this.zoneService = zoneService;
|
|
20
|
-
this.spaceService = spaceService;
|
|
21
|
-
this.navigationService = navigationService;
|
|
22
|
-
this.translate = translate;
|
|
23
|
-
/** Item to display for the navbar */
|
|
24
|
-
this.menuItems = [];
|
|
25
|
-
/** Zoom ratio of the canvas/plan */
|
|
26
|
-
this.canvasZoom = 0;
|
|
27
|
-
/** Opacity for matterport iframe */
|
|
28
|
-
this.opacity = 50;
|
|
29
|
-
/** Current rotation for matterport, [0-360], matterport rotation is bind to input range */
|
|
30
|
-
this.rotation = 180;
|
|
31
|
-
/** Previous rotation, use to calculate the deltaRotation to rotate, when user change rotation value using range input */
|
|
32
|
-
this.prevRotation = 180;
|
|
33
|
-
/** True when the user is currently rotating with the input range, the matterport rotation events will be ignored */
|
|
34
|
-
this.isRotatingRange = false;
|
|
35
|
-
/** Rotating queue event to send to matterport */
|
|
36
|
-
this.rotatingQueueEvent = [];
|
|
37
|
-
/** True when Vertical symmetry is enabled */
|
|
38
|
-
this.reflectV = false;
|
|
39
|
-
/** True when Horizontal symmetry is enabled */
|
|
40
|
-
this.reflectH = false;
|
|
41
|
-
this.chosenPlanIsPdf = false;
|
|
42
|
-
/** First Point in visit, used to determine the calibration */
|
|
43
|
-
this.firstMarkVisit = { x: 0, y: 0 };
|
|
44
|
-
/** Second Point in visit, used to determine the calibration */
|
|
45
|
-
this.secondMarkVisit = { x: 0.5, y: 0.5 };
|
|
46
|
-
/** Equivalent of 'firstMarkVisit' in canvas */
|
|
47
|
-
this.firstMarkPlan = { x: 0, y: 0 };
|
|
48
|
-
/** Equivalent of 'secondMarkVisit' in canvas */
|
|
49
|
-
this.secondMarkPlan = { x: 0, y: 0 };
|
|
50
|
-
/** Calibration result, (offsetX, offsetY, x, y) */
|
|
51
|
-
this.calibrage = {};
|
|
52
|
-
/** Is in preview mode (see scan result) */
|
|
53
|
-
this.preview = false;
|
|
54
|
-
/** Matterport is loading */
|
|
55
|
-
this.loading = true;
|
|
56
|
-
this.positions = [];
|
|
57
|
-
this.floors = [];
|
|
58
|
-
this.zoomCanBeChanged = false;
|
|
59
|
-
}
|
|
60
|
-
ngOnDestroy() {
|
|
61
|
-
if (!this.loading) {
|
|
62
|
-
this.matterportImportService.removeFrame();
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
async ngOnInit() {
|
|
66
|
-
this.spaceID = this.route.snapshot.queryParams.spaceID;
|
|
67
|
-
this.currentSpace = await this.spaceService.getSpace(this.spaceID);
|
|
68
|
-
/** Menu nav bar */
|
|
69
|
-
this.setupMenuItems();
|
|
70
|
-
this.chosenPlan = this.planService.getChosenPlan();
|
|
71
|
-
if (this.chosenPlan) {
|
|
72
|
-
this.chosenPlanIsPdf = this.chosenPlan.annexe.includes('pdf');
|
|
73
|
-
this.launchViewer();
|
|
74
|
-
setTimeout(() => {
|
|
75
|
-
this.configureCanvas().then(() => {
|
|
76
|
-
this.panzoom = panzoom(this.canvas, {
|
|
77
|
-
bounds: true,
|
|
78
|
-
boundsPadding: 0,
|
|
79
|
-
maxZoom: 2.5,
|
|
80
|
-
minZoom: 0.1,
|
|
81
|
-
initialZoom: 1,
|
|
82
|
-
zoomSpeed: 0.02,
|
|
83
|
-
});
|
|
84
|
-
});
|
|
85
|
-
}, 500);
|
|
86
|
-
}
|
|
87
|
-
else {
|
|
88
|
-
this.router.navigate(['/dashboard/localisation', this.spaceID, 'plans']);
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
/** **********************************************************************************************
|
|
92
|
-
* MENU NAV BAR
|
|
93
|
-
*********************************************************************************************** */
|
|
94
|
-
setupMenuItems() {
|
|
95
|
-
this.menuItems = [
|
|
96
|
-
{ label: 'Locations', url: '/localisation' },
|
|
97
|
-
{
|
|
98
|
-
label: this.currentSpace.name,
|
|
99
|
-
url: `/localisation/${this.spaceID}`,
|
|
100
|
-
},
|
|
101
|
-
{
|
|
102
|
-
label: 'Plans',
|
|
103
|
-
url: `/localisation/${this.currentSpace.id}/plans`,
|
|
104
|
-
},
|
|
105
|
-
{
|
|
106
|
-
label: 'Calibration',
|
|
107
|
-
url: `/localisation/${this.currentSpace.id}/plan-calibration?spaceID=${this.currentSpace.id}`,
|
|
108
|
-
},
|
|
109
|
-
];
|
|
110
|
-
}
|
|
111
|
-
/** **********************************************************************************************
|
|
112
|
-
* CANVAS
|
|
113
|
-
*********************************************************************************************** */
|
|
114
|
-
/** Display the plan */
|
|
115
|
-
async configureCanvas() {
|
|
116
|
-
/** Get canvas */
|
|
117
|
-
if (!this.canvas) {
|
|
118
|
-
const canvas = document.querySelector('#canvas');
|
|
119
|
-
this.canvas = canvas;
|
|
120
|
-
}
|
|
121
|
-
if (!this.chosenPlanIsPdf) {
|
|
122
|
-
const image = await getMetaForImage(this.chosenPlan.filepath);
|
|
123
|
-
/** Compute the new size for the canvas/matterport, base on the dimension of the plan, keeping the ratio */
|
|
124
|
-
const size = this.getSizeForCanvas(image.width, image.height);
|
|
125
|
-
/** Compute the plan zoom ratio (use for the calibration later) */
|
|
126
|
-
this.canvasZoom = size.w / image.width;
|
|
127
|
-
this.resizeView(size);
|
|
128
|
-
/** Draw Plan on the canvas */
|
|
129
|
-
this.drawImage(this.chosenPlan.filepath);
|
|
130
|
-
}
|
|
131
|
-
else {
|
|
132
|
-
// TODO
|
|
133
|
-
this.pdfToCanvas();
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
/** Update size of the canvas/matterport */
|
|
137
|
-
resizeView(size) {
|
|
138
|
-
this.canvasDiv.nativeElement.style.width = `${size.w}px`;
|
|
139
|
-
this.canvasDiv.nativeElement.style.height = `${size.h}px`;
|
|
140
|
-
this.canvas.style.width = `${size.w}px`;
|
|
141
|
-
this.canvas.style.height = `${size.h}px`;
|
|
142
|
-
this.canvas.width = size.w;
|
|
143
|
-
this.canvas.height = size.h;
|
|
144
|
-
this.canvasSize = size;
|
|
145
|
-
}
|
|
146
|
-
/** Draw something on the canvas */
|
|
147
|
-
drawImage(url, x = 0, y = 0, icone = false) {
|
|
148
|
-
const image = new Image();
|
|
149
|
-
const size = this.canvasSize;
|
|
150
|
-
const context = this.canvas.getContext('2d');
|
|
151
|
-
/** Flip the context, for symmetry */
|
|
152
|
-
// if (this.reflectV) {
|
|
153
|
-
// context.translate(size.w, 0);
|
|
154
|
-
// context.scale(-1, 1);
|
|
155
|
-
// }
|
|
156
|
-
// if (this.reflectH) {
|
|
157
|
-
// context.translate(0, size.h);
|
|
158
|
-
// context.scale(1, -1);
|
|
159
|
-
// }
|
|
160
|
-
let imageWidth = size.w;
|
|
161
|
-
let imageHeight = size.h;
|
|
162
|
-
image.addEventListener('load', () => {
|
|
163
|
-
if (icone) {
|
|
164
|
-
imageWidth = image.width;
|
|
165
|
-
imageHeight = image.height;
|
|
166
|
-
}
|
|
167
|
-
context.drawImage(image, 0, 0, image.width, image.height, x, y, imageWidth, imageHeight);
|
|
168
|
-
});
|
|
169
|
-
image.src = url;
|
|
170
|
-
}
|
|
171
|
-
/** Get the size for the canvas, based on the plan size, keeping the ratio */
|
|
172
|
-
getSizeForCanvas(w, h) {
|
|
173
|
-
let canvasW = this.canvasDiv.nativeElement.offsetWidth;
|
|
174
|
-
let canvasH = this.canvasDiv.nativeElement.offsetHeight;
|
|
175
|
-
const imageRatio = w / h;
|
|
176
|
-
const canvasRatio = canvasW / canvasH;
|
|
177
|
-
if (imageRatio > canvasRatio) {
|
|
178
|
-
canvasH = canvasW / imageRatio;
|
|
179
|
-
}
|
|
180
|
-
else {
|
|
181
|
-
canvasW = canvasH * imageRatio;
|
|
182
|
-
}
|
|
183
|
-
return { w: canvasW, h: canvasH };
|
|
184
|
-
}
|
|
185
|
-
/** [TODO] Convert a PDF to a Canvas */
|
|
186
|
-
async pdfToCanvas() {
|
|
187
|
-
const pdfjs = await import('pdfjs-dist/build/pdf');
|
|
188
|
-
const pdfjsWorker = await import('pdfjs-dist/build/pdf.worker.entry');
|
|
189
|
-
pdfjs.GlobalWorkerOptions.workerSrc = pdfjsWorker;
|
|
190
|
-
const pdf = await getDocument(this.chosenPlan.filepath)
|
|
191
|
-
.promise;
|
|
192
|
-
const page = await pdf.getPage(1);
|
|
193
|
-
const viewPortParameters = { scale: 1 };
|
|
194
|
-
const viewport = page.getViewport(viewPortParameters);
|
|
195
|
-
this.canvas.height = viewport.height;
|
|
196
|
-
this.canvas.width = viewport.width;
|
|
197
|
-
const size = this.getSizeForCanvas(viewport.width, viewport.height);
|
|
198
|
-
console.log(size);
|
|
199
|
-
this.canvasSize = size;
|
|
200
|
-
this.canvasZoom = size.w / viewport.width;
|
|
201
|
-
const context = this.canvas.getContext('2d');
|
|
202
|
-
const renderContext = {
|
|
203
|
-
canvasContext: context,
|
|
204
|
-
viewport,
|
|
205
|
-
};
|
|
206
|
-
const renderTask = page.render(renderContext).promise;
|
|
207
|
-
renderTask.then(() => console.log('Page rendered'));
|
|
208
|
-
// const res = canvas.toDataURL();
|
|
209
|
-
// if (pdf != null) pdf.destroy();
|
|
210
|
-
// return res;
|
|
211
|
-
}
|
|
212
|
-
/** User click to user Symmetry Vertical */
|
|
213
|
-
onReflectV() {
|
|
214
|
-
this.reflectV = !this.reflectV;
|
|
215
|
-
this.configureCanvas();
|
|
216
|
-
}
|
|
217
|
-
/** User click to user Symmetry Horizontal */
|
|
218
|
-
onReflectH() {
|
|
219
|
-
this.reflectH = !this.reflectH;
|
|
220
|
-
this.configureCanvas();
|
|
221
|
-
}
|
|
222
|
-
/** **********************************************************************************************
|
|
223
|
-
* MATTERPORT
|
|
224
|
-
*********************************************************************************************** */
|
|
225
|
-
/** Launch matterport */
|
|
226
|
-
async launchViewer() {
|
|
227
|
-
await this.matterportImportService.initSdkForModel(this.chosenPlan.model3d);
|
|
228
|
-
const { sdk } = this.matterportImportService;
|
|
229
|
-
this.floors = Object.values(this.matterportImportService.floors);
|
|
230
|
-
// console.log(this.floors);
|
|
231
|
-
setTimeout(async () => {
|
|
232
|
-
/** Move Floor mode */
|
|
233
|
-
sdk.Mode.moveTo(sdk.Mode.Mode.FLOORPLAN).then(async (nextMode) => {
|
|
234
|
-
/** Display the correct floor for the plan */
|
|
235
|
-
try {
|
|
236
|
-
const matterportFloor = this.chosenPlan.zone.metadata ?
|
|
237
|
-
JSON.parse(this.chosenPlan.zone.metadata).matterportFloorSequence : null;
|
|
238
|
-
await this.matterportImportService.moveToFloor(this.chosenPlan.zone.name, matterportFloor);
|
|
239
|
-
/** When the user try to change the view mode we set it back to floorpan */
|
|
240
|
-
sdk.on(sdk.Mode.Event.CHANGE_END, (oldMode, newMode) => {
|
|
241
|
-
if (newMode !== sdk.Mode.Mode.FLOORPLAN) {
|
|
242
|
-
sdk.Mode.moveTo(sdk.Mode.Mode.FLOORPLAN, {
|
|
243
|
-
transition: 'transition.instant',
|
|
244
|
-
});
|
|
245
|
-
}
|
|
246
|
-
});
|
|
247
|
-
}
|
|
248
|
-
catch {
|
|
249
|
-
console.log('couldnot move to floor');
|
|
250
|
-
}
|
|
251
|
-
});
|
|
252
|
-
/** We can display the matterport view now */
|
|
253
|
-
this.loading = false;
|
|
254
|
-
}, 1000);
|
|
255
|
-
/** Update current camera pose and rotation */
|
|
256
|
-
sdk.Camera.pose.subscribe((event) => {
|
|
257
|
-
/** We update only if the user is not changing the rotation with the <input> range, to not override the <input> value */
|
|
258
|
-
if (!this.isRotatingRange) {
|
|
259
|
-
this.rotation = event.rotation.y + 180;
|
|
260
|
-
this.prevRotation = this.rotation;
|
|
261
|
-
this.cameraPose = event;
|
|
262
|
-
}
|
|
263
|
-
});
|
|
264
|
-
}
|
|
265
|
-
/** When the <input> range, for rotation, change */
|
|
266
|
-
async onRotationChange() {
|
|
267
|
-
const rotationDelta = this.rotation - this.prevRotation;
|
|
268
|
-
this.prevRotation = this.rotation;
|
|
269
|
-
/** Send the rotationDelta to th queue event in order to be send to matterport */
|
|
270
|
-
this.rotatingQueueEvent.push(rotationDelta);
|
|
271
|
-
/** Start to process the queue, if it's the first event */
|
|
272
|
-
if (!this.isRotatingRange) {
|
|
273
|
-
this.isRotatingRange = true;
|
|
274
|
-
this.processRotatingQueueEvent();
|
|
275
|
-
}
|
|
276
|
-
}
|
|
277
|
-
/** Process the rotating event queue, send event one by one to matterport */
|
|
278
|
-
async processRotatingQueueEvent() {
|
|
279
|
-
const { sdk } = this.matterportImportService;
|
|
280
|
-
/** While the queue is not empty */
|
|
281
|
-
while (this.rotatingQueueEvent.length > 0) {
|
|
282
|
-
/** Rotate matterport by deltaRotation and remove event from queue */
|
|
283
|
-
await sdk.Camera.rotate(this.rotatingQueueEvent.shift(), 0, {
|
|
284
|
-
speed: 360,
|
|
285
|
-
});
|
|
286
|
-
}
|
|
287
|
-
/** When the queue is empty, then the user is not rotating with the <input> range anymore */
|
|
288
|
-
this.isRotatingRange = false;
|
|
289
|
-
}
|
|
290
|
-
/** **********************************************************************************************
|
|
291
|
-
* USER ACTIONS
|
|
292
|
-
*********************************************************************************************** */
|
|
293
|
-
/** Preview calibration */
|
|
294
|
-
async onPreview() {
|
|
295
|
-
this.preview = true;
|
|
296
|
-
/** Place sweeps */
|
|
297
|
-
this.onPlaceSweeps();
|
|
298
|
-
}
|
|
299
|
-
async calibrate() {
|
|
300
|
-
const [navigation] = this.currentNavigations;
|
|
301
|
-
const position = JSON.parse(navigation.position);
|
|
302
|
-
this.firstMarkPlan =
|
|
303
|
-
await this.matterportImportService.sdk.Renderer.getScreenPosition({
|
|
304
|
-
x: position.x,
|
|
305
|
-
y: position.y,
|
|
306
|
-
z: position.z,
|
|
307
|
-
});
|
|
308
|
-
this.secondMarkPlan =
|
|
309
|
-
await this.matterportImportService.sdk.Renderer.getScreenPosition({
|
|
310
|
-
x: position.x,
|
|
311
|
-
y: 0,
|
|
312
|
-
z: 0,
|
|
313
|
-
});
|
|
314
|
-
const deltaZVisit = 0 - position.z;
|
|
315
|
-
let deltaXPlan = this.secondMarkPlan.x - this.firstMarkPlan.x;
|
|
316
|
-
if (deltaXPlan === 0) {
|
|
317
|
-
// console.log("we moved along Y axis on Plan");
|
|
318
|
-
const deltaYPlan = this.secondMarkPlan.y - this.firstMarkPlan.y;
|
|
319
|
-
this.calibrage.nameYAxis = 'z';
|
|
320
|
-
this.calibrage.nameXAxis = 'x';
|
|
321
|
-
this.calibrage.offsetY = this.secondMarkPlan.y;
|
|
322
|
-
this.calibrage.scaleY = deltaYPlan / deltaZVisit;
|
|
323
|
-
}
|
|
324
|
-
else {
|
|
325
|
-
// console.log(" we moved along X axis on Plan");
|
|
326
|
-
this.calibrage.nameYAxis = 'x';
|
|
327
|
-
this.calibrage.nameXAxis = 'z';
|
|
328
|
-
this.calibrage.offsetX = this.secondMarkPlan.x;
|
|
329
|
-
this.calibrage.scaleX = deltaXPlan / deltaZVisit;
|
|
330
|
-
}
|
|
331
|
-
const thirdMarkPlan = await this.matterportImportService.sdk.Renderer.getScreenPosition({
|
|
332
|
-
x: 0,
|
|
333
|
-
y: 0,
|
|
334
|
-
z: position.z,
|
|
335
|
-
});
|
|
336
|
-
const deltaXVisit = 0 - position.x;
|
|
337
|
-
if (deltaXPlan === 0) {
|
|
338
|
-
// console.log(" we moved along X axis on Plan");
|
|
339
|
-
deltaXPlan = thirdMarkPlan.x - this.firstMarkPlan.x;
|
|
340
|
-
this.calibrage.offsetX = thirdMarkPlan.x;
|
|
341
|
-
this.calibrage.scaleX = deltaXPlan / deltaXVisit;
|
|
342
|
-
}
|
|
343
|
-
else {
|
|
344
|
-
const deltaYPlan = thirdMarkPlan.y - this.firstMarkPlan.y;
|
|
345
|
-
this.calibrage.offsetY = thirdMarkPlan.y;
|
|
346
|
-
this.calibrage.scaleY = deltaYPlan / deltaXVisit;
|
|
347
|
-
}
|
|
348
|
-
/** Take considiration of pan and zoom of plan on canvas */
|
|
349
|
-
const transformInfo = this.panzoom.getTransform();
|
|
350
|
-
const { scale, x, y } = transformInfo;
|
|
351
|
-
// console.log(transformInfo);
|
|
352
|
-
this.calibrage.offsetXPlan = x;
|
|
353
|
-
this.calibrage.offsetYPlan = y;
|
|
354
|
-
this.calibrage.scalePlan = scale;
|
|
355
|
-
console.log(this.calibrage);
|
|
356
|
-
}
|
|
357
|
-
/** Place sweeps */
|
|
358
|
-
async onPlaceSweeps() {
|
|
359
|
-
/** Display all scan */
|
|
360
|
-
const zone = await this.zoneService.getZone(this.chosenPlan.zoneID);
|
|
361
|
-
if (zone) {
|
|
362
|
-
this.currentZone = zone;
|
|
363
|
-
const navigations = await this.navigationService.getNavigationsForZone(this.currentZone);
|
|
364
|
-
this.currentNavigations = navigations;
|
|
365
|
-
await this.calibrate();
|
|
366
|
-
if (navigations.length > 0) {
|
|
367
|
-
for (const navigation of navigations) {
|
|
368
|
-
const testPosition = JSON.parse(navigation.position);
|
|
369
|
-
const positionX = this.calibrage.nameXAxis === 'x' ? testPosition.x : testPosition.z;
|
|
370
|
-
const positionY = this.calibrage.nameYAxis === 'x' ? testPosition.x : testPosition.z;
|
|
371
|
-
const testX = positionX * this.calibrage.scaleX + this.calibrage.offsetX;
|
|
372
|
-
const testY = positionY * this.calibrage.scaleY + this.calibrage.offsetY;
|
|
373
|
-
// console.log("test position GREEN", testX, testY);
|
|
374
|
-
const transformedX = (testX - this.calibrage.offsetXPlan) / this.calibrage.scalePlan; // we are undoing the pan and zoom
|
|
375
|
-
const transformedY = (testY - this.calibrage.offsetYPlan) / this.calibrage.scalePlan;
|
|
376
|
-
this.positions.push({
|
|
377
|
-
navID: navigation.id,
|
|
378
|
-
planID: this.chosenPlan.id,
|
|
379
|
-
x: transformedX,
|
|
380
|
-
y: transformedY,
|
|
381
|
-
});
|
|
382
|
-
const iconSize = 30 * this.calibrage.scalePlan;
|
|
383
|
-
const shift = iconSize / 2;
|
|
384
|
-
this.drawImage('https://api.iconify.design/mdi:adjust.svg?color=green&height=30&width=30', transformedX - shift, transformedY - shift, true);
|
|
385
|
-
}
|
|
386
|
-
}
|
|
387
|
-
}
|
|
388
|
-
}
|
|
389
|
-
/** Save calibration */
|
|
390
|
-
async onSave() {
|
|
391
|
-
if (this.currentZone) {
|
|
392
|
-
/** Normalize with the zoom */
|
|
393
|
-
// this.calibrage.offsetX /= this.canvasZoom;
|
|
394
|
-
// this.calibrage.offsetY /= this.canvasZoom;
|
|
395
|
-
// this.calibrage.x /= this.canvasZoom;
|
|
396
|
-
// this.calibrage.y /= this.canvasZoom;
|
|
397
|
-
this.calibrage.new = true;
|
|
398
|
-
this.calibrage.imgWidth = this.canvasSize.w;
|
|
399
|
-
this.calibrage.imgHeight = this.canvasSize.h;
|
|
400
|
-
await this.planService.updatePlan({
|
|
401
|
-
id: this.chosenPlan.id,
|
|
402
|
-
calibration: JSON.stringify(this.calibrage),
|
|
403
|
-
});
|
|
404
|
-
await Promise.all(this.positions.map(async (position) => {
|
|
405
|
-
const { navID } = position;
|
|
406
|
-
delete position.navID;
|
|
407
|
-
const nav = this.currentNavigations.find((_nav) => _nav.id === navID);
|
|
408
|
-
let positionsDataToUpdate;
|
|
409
|
-
if (nav.positionOnPlan) {
|
|
410
|
-
const positionOnPlan = nav.positionOnPlan.map((entry) => JSON.parse(entry));
|
|
411
|
-
const positionForCurrentPlan = positionOnPlan.find((entry) => entry.planID === this.chosenPlan.id);
|
|
412
|
-
if (positionForCurrentPlan) {
|
|
413
|
-
positionOnPlan.splice(positionOnPlan.indexOf(positionForCurrentPlan), 1, position);
|
|
414
|
-
}
|
|
415
|
-
else {
|
|
416
|
-
positionOnPlan.push(position);
|
|
417
|
-
}
|
|
418
|
-
positionsDataToUpdate = [...positionOnPlan];
|
|
419
|
-
}
|
|
420
|
-
else {
|
|
421
|
-
positionsDataToUpdate = [position];
|
|
422
|
-
}
|
|
423
|
-
// console.log(positionsDataToUpdate);
|
|
424
|
-
await this.navigationService.updateNavigation({
|
|
425
|
-
id: navID,
|
|
426
|
-
positionOnPlan: positionsDataToUpdate.map((entry) => JSON.stringify(entry)),
|
|
427
|
-
});
|
|
428
|
-
}));
|
|
429
|
-
}
|
|
430
|
-
this.matterportImportService.removeFrame();
|
|
431
|
-
this.router.navigate(['/dashboard/localisation', this.spaceID, 'plans']);
|
|
432
|
-
alert(this.translate.instant('calibration.success'));
|
|
433
|
-
}
|
|
434
|
-
/** Reset the canvas */
|
|
435
|
-
onReset() {
|
|
436
|
-
this.reflectH = false;
|
|
437
|
-
this.reflectV = false;
|
|
438
|
-
this.preview = false;
|
|
439
|
-
this.configureCanvas();
|
|
440
|
-
}
|
|
441
|
-
/** Cancel, leave */
|
|
442
|
-
onCancel() {
|
|
443
|
-
this.matterportImportService.removeFrame();
|
|
444
|
-
this.router.navigate(['/dashboard/localisation', this.spaceID, 'plans']);
|
|
445
|
-
alert(this.translate.instant('calibration.canceled'));
|
|
446
|
-
}
|
|
447
|
-
async onFloorClick(floor) {
|
|
448
|
-
this.currentFloor = floor;
|
|
449
|
-
await this.matterportImportService.moveToFloor(floor.id);
|
|
450
|
-
}
|
|
451
|
-
onActivateZoomChange() {
|
|
452
|
-
this.zoomCanBeChanged = !this.zoomCanBeChanged;
|
|
453
|
-
const iframe = document.querySelector('#viewer-frame');
|
|
454
|
-
if (iframe) {
|
|
455
|
-
iframe.style.zIndex = this.zoomCanBeChanged ? '1' : '0';
|
|
456
|
-
}
|
|
457
|
-
}
|
|
458
|
-
}
|
|
459
|
-
CalibrationComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.2.7", ngImport: i0, type: CalibrationComponent, deps: [{ token: i1.MatterportImportService }, { token: i1.PlanService }, { token: i2.ActivatedRoute }, { token: i2.Router }, { token: i1.ZoneService }, { token: i1.SpaceService }, { token: i1.NavigationService }, { token: i3.TranslateService }], target: i0.ɵɵFactoryTarget.Component });
|
|
460
|
-
CalibrationComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.2.7", type: CalibrationComponent, selector: "lib-calibration", viewQueries: [{ propertyName: "canvasDiv", first: true, predicate: ["canvasDiv"], descendants: true }], ngImport: i0, template: "<div class=\"row mt-3\">\
|
|
461
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.2.7", ngImport: i0, type: CalibrationComponent, decorators: [{
|
|
462
|
-
type: Component,
|
|
463
|
-
args: [{ selector: 'lib-calibration', template: "<div class=\"row mt-3\">\
|
|
464
|
-
}], ctorParameters: function () { return [{ type: i1.MatterportImportService }, { type: i1.PlanService }, { type: i2.ActivatedRoute }, { type: i2.Router }, { type: i1.ZoneService }, { type: i1.SpaceService }, { type: i1.NavigationService }, { type: i3.TranslateService }]; }, propDecorators: { canvasDiv: [{
|
|
465
|
-
type: ViewChild,
|
|
466
|
-
args: ['canvasDiv']
|
|
467
|
-
}] } });
|
|
468
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2FsaWJyYXRpb24uY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvbmd4LXNtYXJ0ZXJwbGFuLWxvY2F0aW9ucy9zcmMvbGliL2NvbXBvbmVudHMvcGxhbnMvY2FsaWJyYXRpb24vY2FsaWJyYXRpb24uY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvbmd4LXNtYXJ0ZXJwbGFuLWxvY2F0aW9ucy9zcmMvbGliL2NvbXBvbmVudHMvcGxhbnMvY2FsaWJyYXRpb24vY2FsaWJyYXRpb24uY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFNBQVMsRUFBc0IsU0FBUyxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBR3pFLE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSxZQUFZLENBQUM7QUFFekMsT0FBTyxFQVVILGVBQWUsR0FFbEIsTUFBTSxtQ0FBbUMsQ0FBQztBQUMzQyxPQUFPLE9BQU8sTUFBTSxTQUFTLENBQUM7Ozs7Ozs7OztBQU85QixNQUFNLE9BQU8sb0JBQW9CO0lBb0Y3QixZQUNZLHVCQUFnRCxFQUNoRCxXQUF3QixFQUN4QixLQUFxQixFQUNyQixNQUFjLEVBQ2QsV0FBd0IsRUFDeEIsWUFBMEIsRUFDMUIsaUJBQW9DLEVBQ3BDLFNBQTJCO1FBUDNCLDRCQUF1QixHQUF2Qix1QkFBdUIsQ0FBeUI7UUFDaEQsZ0JBQVcsR0FBWCxXQUFXLENBQWE7UUFDeEIsVUFBSyxHQUFMLEtBQUssQ0FBZ0I7UUFDckIsV0FBTSxHQUFOLE1BQU0sQ0FBUTtRQUNkLGdCQUFXLEdBQVgsV0FBVyxDQUFhO1FBQ3hCLGlCQUFZLEdBQVosWUFBWSxDQUFjO1FBQzFCLHNCQUFpQixHQUFqQixpQkFBaUIsQ0FBbUI7UUFDcEMsY0FBUyxHQUFULFNBQVMsQ0FBa0I7UUEzRnZDLHFDQUFxQztRQUNyQyxjQUFTLEdBQWUsRUFBRSxD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LENBQUMsRUFBRSxDQUFDLENBQUM7SUFDN0QsQ0FBQztJQUVELG9CQUFvQjtRQUNoQixJQUFJLENBQUMsZ0JBQWdCLEdBQUcsQ0FBQyxJQUFJLENBQUMsZ0JBQWdCLENBQUM7UUFDL0MsTUFBTSxNQUFNLEdBQUcsUUFBUSxDQUFDLGFBQWEsQ0FBQyxlQUFlLENBQWdCLENBQUM7UUFDdEUsSUFBSSxNQUFNLEVBQUU7WUFDUixNQUFNLENBQUMsS0FBSyxDQUFDLE1BQU0sR0FBRyxJQUFJLENBQUMsZ0JBQWdCLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDO1NBQzNEO0lBQ0wsQ0FBQzs7aUhBaGtCUSxvQkFBb0I7cUdBQXBCLG9CQUFvQiwrSkN6QmpDLGl6SkFpR007MkZEeEVPLG9CQUFvQjtrQkFMaEMsU0FBUzsrQkFDSSxpQkFBaUI7OFNBWUgsU0FBUztzQkFBaEMsU0FBUzt1QkFBQyxXQUFXIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQ29tcG9uZW50LCBFbGVtZW50UmVmLCBPbkluaXQsIFZpZXdDaGlsZCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xyXG5pbXBvcnQgeyBBY3RpdmF0ZWRSb3V0ZSwgUm91dGVyIH0gZnJvbSAnQGFuZ3VsYXIvcm91dGVyJztcclxuaW1wb3J0IHsgVHJhbnNsYXRlU2VydmljZSB9IGZyb20gJ0BuZ3gtdHJhbnNsYXRlL2NvcmUnO1xyXG5pbXBvcnQgeyBnZXREb2N1bWVudCB9IGZyb20gJ3BkZmpzLWRpc3QnO1xyXG5pbXBvcnQgeyBQREZEb2N1bWVudFByb3h5IH0gZnJvbSAnbmcyLXBkZi12aWV3ZXInO1xyXG5pbXBvcnQge1xyXG4gICAgWm9uZSxcclxuICAgIE1lbnVJdGVtLFxyXG4gICAgUGxhbixcclxuICAgIFNwYWNlLFxyXG4gICAgTmF2aWdhdGlvbixcclxuICAgIFBsYW5TZXJ2aWNlLFxyXG4gICAgWm9uZVNlcnZpY2UsXHJcbiAgICBTcGFjZVNlcnZpY2UsXHJcbiAgICBOYXZpZ2F0aW9uU2VydmljZSxcclxuICAgIGdldE1ldGFGb3JJbWFnZSxcclxuICAgIE1hdHRlcnBvcnRJbXBvcnRTZXJ2aWNlLFxyXG59IGZyb20gJ0BzbWFydGVycGxhbi9uZ3gtc21hcnRlcnBsYW4tY29yZSc7XHJcbmltcG9ydCBwYW56b29tIGZyb20gJ3Bhbnpvb20nO1xyXG5cclxuQENvbXBvbmVudCh7XHJcbiAgICBzZWxlY3RvcjogJ2xpYi1jYWxpYnJhdGlvbicsXHJcbiAgICB0ZW1wbGF0ZVVybDogJy4vY2FsaWJyYXRpb24uY29tcG9uZW50Lmh0bWwnLFxyXG4gICAgc3R5bGVVcmxzOiBbJy4vY2FsaWJyYXRpb24uY29tcG9uZW50LnNjc3MnXSxcclxufSlcclxuZXhwb3J0IGNsYXNzIENhbGlicmF0aW9uQ29tcG9uZW50IGltcGxlbWVudHMgT25Jbml0IHtcclxuICAgIC8qKiBJdGVtIHRvIGRpc3BsYXkgZm9yIHRoZSBuYXZiYXIgKi9cclxuICAgIG1lbnVJdGVtczogTWVudUl0ZW1bXSA9IFtdO1xyXG5cclxuICAgIC8qKiBDYW52YXMgKFBsYW4pICovXHJcbiAgICBjYW52YXM7XHJcblxyXG4gICAgLyoqIENhbnZhc0RpdiAoRGl2IHRoYXQgY29udGFpbiB0aGUgY2FudmFzICsgbWF0dGVycG9ydCBpZnJhbWUpICovXHJcbiAgICBAVmlld0NoaWxkKCdjYW52YXNEaXYnKSBjYW52YXNEaXY6IEVsZW1lbnRSZWY7XHJcblxyXG4gICAgLyoqIFNpemUgb2YgdGhlIGNhbnZhcyAmIG1hdHRlcnBvcnQgaWZyYW1lICovXHJcbiAgICBjYW52YXNTaXplOiB7IHc6IG51bWJlcjsgaDogbnVtYmVyOyB9O1xyXG5cclxuICAgIC8qKiBab29tIHJhdGlvIG9mIHRoZSBjYW52YXMvcGxhbiAgKi9cclxuICAgIGNhbnZhc1pvb20gPSAwO1xyXG5cclxuICAgIC8qKiBPcGFjaXR5IGZvciBtYXR0ZXJwb3J0IGlmcmFtZSAqL1xyXG4gICAgb3BhY2l0eTogbnVtYmVyID0gNTA7XHJcblxyXG4gICAgLyoqIEN1cnJlbnQgcm90YXRpb24gZm9yIG1hdHRlcnBvcnQsIFswLTM2MF0sICBtYXR0ZXJwb3J0IHJvdGF0aW9uIGlzIGJpbmQgdG8gaW5wdXQgcmFuZ2UgKi9cclxuICAgIHJvdGF0aW9uOiBudW1iZXIgPSAxODA7XHJcblxyXG4gICAgLyoqIFByZXZpb3VzIHJvdGF0aW9uLCB1c2UgdG8gY2FsY3VsYXRlIHRoZSBkZWx0YVJvdGF0aW9uIHRvIHJvdGF0ZSwgd2hlbiB1c2VyIGNoYW5nZSByb3RhdGlvbiB2YWx1ZSB1c2luZyByYW5nZSBpbnB1dCAqL1xyXG4gICAgcHJldlJvdGF0aW9uOiBudW1iZXIgPSAxODA7XHJcblxyXG4gICAgLyoqIEN1cnJlbnQgQ2FtZXJhIFBvc2UgKi9cclxuICAgIGNhbWVyYVBvc2U6IGFueTtcclxuXHJcbiAgICAvKiogVHJ1ZSB3aGVuIHRoZSB1c2VyIGlzIGN1cnJlbnRseSByb3RhdGluZyB3aXRoIHRoZSBpbnB1dCByYW5nZSwgdGhlIG1hdHRlcnBvcnQgcm90YXRpb24gZXZlbnRzIHdpbGwgYmUgaWdub3JlZCAqL1xyXG4gICAgaXNSb3RhdGluZ1JhbmdlOiBib29sZWFuID0gZmFsc2U7XHJcblxyXG4gICAgLyoqIFJvdGF0aW5nIHF1ZXVlIGV2ZW50IHRvIHNlbmQgdG8gbWF0dGVycG9ydCAqL1xyXG4gICAgcm90YXRpbmdRdWV1ZUV2ZW50OiBudW1iZXJbXSA9IFtdO1xyXG5cclxuICAgIC8qKiBUcnVlIHdoZW4gVmVydGljYWwgc3ltbWV0cnkgaXMgZW5hYmxlZCAqL1xyXG4gICAgcmVmbGVjdFYgPSBmYWxzZTtcclxuXHJcbiAgICAvKiogVHJ1ZSB3aGVuIEhvcml6b250YWwgc3ltbWV0cnkgaXMgZW5hYmxlZCAqL1xyXG4gICAgcmVmbGVjdEggPSBmYWxzZTtcclxuXHJcbiAgICBjaG9zZW5QbGFuOiBQbGFuO1xyXG5cclxuICAgIHNwYWNlSUQ6IHN0cmluZztcclxuXHJcbiAgICBjdXJyZW50U3BhY2U6IFNwYWNlO1xyXG5cclxuICAgIGN1cnJlbnRab25lOiBab25lO1xyXG5cclxuICAgIGNob3NlblBsYW5Jc1BkZiA9IGZhbHNlO1xyXG5cclxuICAgIC8qKiBGaXJzdCBQb2ludCBpbiB2aXNpdCwgdXNlZCB0byBkZXRlcm1pbmUgdGhlIGNhbGlicmF0aW9uICAqL1xyXG4gICAgZmlyc3RNYXJrVmlzaXQgPSB7IHg6IDAsIHk6IDAgfTtcclxuXHJcbiAgICAvKiogU2Vjb25kIFBvaW50IGluIHZpc2l0LCB1c2VkIHRvIGRldGVybWluZSB0aGUgY2FsaWJyYXRpb24gICovXHJcbiAgICBzZWNvbmRNYXJrVmlzaXQgPSB7IHg6IDAuNSwgeTogMC41IH07XHJcblxyXG4gICAgLyoqIEVxdWl2YWxlbnQgb2YgJ2ZpcnN0TWFya1Zpc2l0JyBpbiBjYW52YXMgICovXHJcbiAgICBmaXJzdE1hcmtQbGFuOiB7IHg6IG51bWJlcjsgeTogbnVtYmVyOyB9ID0geyB4OiAwLCB5OiAwIH07XHJcblxyXG4gICAgLyoqIEVxdWl2YWxlbnQgb2YgJ3NlY29uZE1hcmtWaXNpdCcgaW4gY2FudmFzICAqL1xyXG4gICAgc2Vjb25kTWFya1BsYW46IHsgeDogbnVtYmVyOyB5OiBudW1iZXI7IH0gPSB7IHg6IDAsIHk6IDAgfTtcclxuXHJcbiAgICAvKiogQ2FsaWJyYXRpb24gcmVzdWx0LCAob2Zmc2V0WCwgb2Zmc2V0WSwgeCwgeSkgKi9cclxuICAgIGNhbGlicmFnZTogYW55ID0ge307XHJcblxyXG4gICAgLyoqIElzIGluIHByZXZpZXcgbW9kZSAoc2VlIHNjYW4gcmVzdWx0KSAqL1xyXG4gICAgcHJldmlldyA9IGZhbHNlO1xyXG5cclxuICAgIC8qKiBNYXR0ZXJwb3J0IGlzIGxvYWRpbmcgKi9cclxuICAgIGxvYWRpbmcgPSB0cnVlO1xyXG5cclxuICAgIC8qIGZvciBwYW4gYW5kIHpvb20gb2YgY2FudmFzICovXHJcbiAgICBwYW56b29tOiBhbnk7XHJcblxyXG4gICAgY3VycmVudE5hdmlnYXRpb25zOiBOYXZpZ2F0aW9uW107XHJcblxyXG4gICAgcG9zaXRpb25zOiB7IG5hdklEOiBzdHJpbmc7IHBsYW5JRDogc3RyaW5nOyB4OiBudW1iZXI7IHk6IG51bWJlcjsgfVtdID0gW107XHJcblxyXG4gICAgZmxvb3JzOiBhbnlbXSA9IFtdO1xyXG5cclxuICAgIGN1cnJlbnRGbG9vcjtcclxuXHJcbiAgICB6b29tQ2FuQmVDaGFuZ2VkOiBib29sZWFuID0gZmFsc2U7XHJcblxyXG4gICAgY29uc3RydWN0b3IoXHJcbiAgICAgICAgcHJpdmF0ZSBtYXR0ZXJwb3J0SW1wb3J0U2VydmljZTogTWF0dGVycG9ydEltcG9ydFNlcnZpY2UsXHJcbiAgICAgICAgcHJpdmF0ZSBwbGFuU2VydmljZTogUGxhblNlcnZpY2UsXHJcbiAgICAgICAgcHJpdmF0ZSByb3V0ZTogQWN0aXZhdGVkUm91dGUsXHJcbiAgICAgICAgcHJpdmF0ZSByb3V0ZXI6IFJvdXRlcixcclxuICAgICAgICBwcml2YXRlIHpvbmVTZXJ2aWNlOiBab25lU2VydmljZSxcclxuICAgICAgICBwcml2YXRlIHNwYWNlU2VydmljZTogU3BhY2VTZXJ2aWNlLFxyXG4gICAgICAgIHByaXZhdGUgbmF2aWdhdGlvblNlcnZpY2U6IE5hdmlnYXRpb25TZXJ2aWNlLFxyXG4gICAgICAgIHByaXZhdGUgdHJhbnNsYXRlOiBUcmFuc2xhdGVTZXJ2aWNlXHJcbiAgICApIHsgfVxyXG5cclxuICAgIG5nT25EZXN0cm95KCk6IHZvaWQge1xyXG4gICAgICAgIGlmICghdGhpcy5sb2FkaW5nKSB7XHJcbiAgICAgICAgICAgIHRoaXMubWF0dGVycG9ydEltcG9ydFNlcnZpY2UucmVtb3ZlRnJhbWUoKTtcclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgYXN5bmMgbmdPbkluaXQoKTogUHJvbWlzZTx2b2lkPiB7XHJcbiAgICAgICAgdGhpcy5zcGFjZUlEID0gdGhpcy5yb3V0ZS5zbmFwc2hvdC5xdWVyeVBhcmFtcy5zcGFjZUlEO1xyXG4gICAgICAgIHRoaXMuY3VycmVudFNwYWNlID0gYXdhaXQgdGhpcy5zcGFjZVNlcnZpY2UuZ2V0U3BhY2UodGhpcy5zcGFjZUlEKTtcclxuXHJcbiAgICAgICAgLyoqIE1lbnUgbmF2IGJhciAqL1xyXG4gICAgICAgIHRoaXMuc2V0dXBNZW51SXRlbXMoKTtcclxuXHJcbiAgICAgICAgdGhpcy5jaG9zZW5QbGFuID0gdGhpcy5wbGFuU2VydmljZS5nZXRDaG9zZW5QbGFuKCk7XHJcblxyXG4gICAgICAgIGlmICh0aGlzLmNob3NlblBsYW4pIHtcclxuICAgICAgICAgICAgdGhpcy5jaG9zZW5QbGFuSXNQZGYgPSB0aGlzLmNob3NlblBsYW4uYW5uZXhlLmluY2x1ZGVzKCdwZGYnKTtcclxuICAgICAgICAgICAgdGhpcy5sYXVuY2hWaWV3ZXIoKTtcclxuICAgICAgICAgICAgc2V0VGltZW91dCgoKSA9PiB7XHJcbiAgICAgICAgICAgICAgICB0aGlzLmNvbmZpZ3VyZUNhbnZhcygpLnRoZW4oKCkgPT4ge1xyXG4gICAgICAgICAgICAgICAgICAgIHRoaXMucGFuem9vbSA9IHBhbnpvb20odGhpcy5jYW52YXMsIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgYm91bmRzOiB0cnVlLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICBib3VuZHNQYWRkaW5nOiAwLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICBtYXhab29tOiAyLjUsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIG1pblpvb206IDAuMSxcclxuICAgICAgICAgICAgICAgICAgICAgICAgaW5pdGlhbFpvb206IDEsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHpvb21TcGVlZDogMC4wMixcclxuICAgICAgICAgICAgICAgICAgICB9KTtcclxuICAgICAgICAgICAgICAgIH0pO1xyXG4gICAgICAgICAgICB9LCA1MDApO1xyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgIHRoaXMucm91dGVyLm5hdmlnYXRlKFsnL2Rhc2hib2FyZC9sb2NhbGlzYXRpb24nLCB0aGlzLnNwYWNlSUQsICdwbGFucyddKTtcclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgLyoqICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKipcclxuICAgICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBNRU5VIE5BViBCQVJcclxuICAgICAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiAqL1xyXG4gICAgc2V0dXBNZW51SXRlbXMoKSB7XHJcbiAgICAgICAgdGhpcy5tZW51SXRlbXMgPSBbXHJcbiAgICAgICAgICAgIHsgbGFiZWw6ICdMb2NhdGlvbnMnLCB1cmw6ICcvbG9jYWxpc2F0aW9uJyB9LFxyXG4gICAgICAgICAgICB7XHJcbiAgICAgICAgICAgICAgICBsYWJlbDogdGhpcy5jdXJyZW50U3BhY2UubmFtZSxcclxuICAgICAgICAgICAgICAgIHVybDogYC9sb2NhbGlzYXRpb24vJHt0aGlzLnNwYWNlSUR9YCxcclxuICAgICAgICAgICAgfSxcclxuICAgICAgICAgICAge1xyXG4gICAgICAgICAgICAgICAgbGFiZWw6ICdQbGFucycsXHJcbiAgICAgICAgICAgICAgICB1cmw6IGAvbG9jYWxpc2F0aW9uLyR7dGhpcy5jdXJyZW50U3BhY2UuaWR9L3BsYW5zYCxcclxuICAgICAgICAgICAgfSxcclxuICAgICAgICAgICAge1xyXG4gICAgICAgICAgICAgICAgbGFiZWw6ICdDYWxpYnJhdGlvbicsXHJcbiAgICAgICAgICAgICAgICB1cmw6IGAvbG9jYWxpc2F0aW9uLyR7dGhpcy5jdXJyZW50U3BhY2UuaWR9L3BsYW4tY2FsaWJyYXRpb24/c3BhY2VJRD0ke3RoaXMuY3VycmVudFNwYWNlLmlkfWAsXHJcbiAgICAgICAgICAgIH0sXHJcbiAgICAgICAgXTtcclxuICAgIH1cclxuXHJcbiAgICAvKiogKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKlxyXG4gICAgICogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQ0FOVkFTXHJcbiAgICAgKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiogKi9cclxuXHJcbiAgICAvKiogRGlzcGxheSB0aGUgcGxhbiAqL1xyXG4gICAgYXN5bmMgY29uZmlndXJlQ2FudmFzKCkge1xyXG4gICAgICAgIC8qKiBHZXQgY2FudmFzICovXHJcbiAgICAgICAgaWYgKCF0aGlzLmNhbnZhcykge1xyXG4gICAgICAgICAgICBjb25zdCBjYW52YXMgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKCcjY2FudmFzJykgYXMgSFRNTENhbnZhc0VsZW1lbnQ7XHJcbiAgICAgICAgICAgIHRoaXMuY2FudmFzID0gY2FudmFzO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgaWYgKCF0aGlzLmNob3NlblBsYW5Jc1BkZikge1xyXG4gICAgICAgICAgICBjb25zdCBpbWFnZSA9IGF3YWl0IGdldE1ldGFGb3JJbWFnZSh0aGlzLmNob3NlblBsYW4uZmlsZXBhdGgpO1xyXG4gICAgICAgICAgICAvKiogQ29tcHV0ZSB0aGUgbmV3IHNpemUgZm9yIHRoZSBjYW52YXMvbWF0dGVycG9ydCwgYmFzZSBvbiB0aGUgZGltZW5zaW9uIG9mIHRoZSBwbGFuLCBrZWVwaW5nIHRoZSByYXRpbyAqL1xyXG4gICAgICAgICAgICBjb25zdCBzaXplID0gdGhpcy5nZXRTaXplRm9yQ2FudmFzKGltYWdlLndpZHRoLCBpbWFnZS5oZWlnaHQpO1xyXG5cclxuICAgICAgICAgICAgLyoqIENvbXB1dGUgdGhlIHBsYW4gem9vbSByYXRpbyAodXNlIGZvciB0aGUgY2FsaWJyYXRpb24gbGF0ZXIpICovXHJcbiAgICAgICAgICAgIHRoaXMuY2FudmFzWm9vbSA9IHNpemUudyAvIGltYWdlLndpZHRoO1xyXG5cclxuICAgICAgICAgICAgdGhpcy5yZXNpemVWaWV3KHNpemUpO1xyXG5cclxuICAgICAgICAgICAgLyoqIERyYXcgUGxhbiBvbiB0aGUgY2FudmFzICovXHJcbiAgICAgICAgICAgIHRoaXMuZHJhd0ltYWdlKHRoaXMuY2hvc2VuUGxhbi5maWxlcGF0aCk7XHJcbiAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgLy8gVE9ET1xyXG4gICAgICAgICAgICB0aGlzLnBkZlRvQ2FudmFzKCk7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIC8qKiBVcGRhdGUgc2l6ZSBvZiB0aGUgY2FudmFzL21hdHRlcnBvcnQgKi9cclxuICAgIHJlc2l6ZVZpZXcoc2l6ZSkge1xyXG4gICAgICAgIHRoaXMuY2FudmFzRGl2Lm5hdGl2ZUVsZW1lbnQuc3R5bGUud2lkdGggPSBgJHtzaXplLnd9cHhgO1xyXG4gICAgICAgIHRoaXMuY2FudmFzRGl2Lm5hdGl2ZUVsZW1lbnQuc3R5bGUuaGVpZ2h0ID0gYCR7c2l6ZS5ofXB4YDtcclxuICAgICAgICB0aGlzLmNhbnZhcy5zdHlsZS53aWR0aCA9IGAke3NpemUud31weGA7XHJcbiAgICAgICAgdGhpcy5jYW52YXMuc3R5bGUuaGVpZ2h0ID0gYCR7c2l6ZS5ofXB4YDtcclxuICAgICAgICB0aGlzLmNhbnZhcy53aWR0aCA9IHNpemUudztcclxuICAgICAgICB0aGlzLmNhbnZhcy5oZWlnaHQgPSBzaXplLmg7XHJcbiAgICAgICAgdGhpcy5jYW52YXNTaXplID0gc2l6ZTtcclxuICAgIH1cclxuXHJcbiAgICAvKiogRHJhdyBzb21ldGhpbmcgb24gdGhlIGNhbnZhcyAqL1xyXG4gICAgZHJhd0ltYWdlKHVybDogc3RyaW5nLCB4ID0gMCwgeSA9IDAsIGljb25lID0gZmFsc2UpIHtcclxuICAgICAgICBjb25zdCBpbWFnZSA9IG5ldyBJbWFnZSgpO1xyXG4gICAgICAgIGNvbnN0IHNpemUgPSB0aGlzLmNhbnZhc1NpemU7XHJcbiAgICAgICAgY29uc3QgY29udGV4dCA9IHRoaXMuY2FudmFzLmdldENvbnRleHQoJzJkJyk7XHJcblxyXG4gICAgICAgIC8qKiBGbGlwIHRoZSBjb250ZXh0LCBmb3Igc3ltbWV0cnkgKi9cclxuICAgICAgICAvLyBpZiAodGhpcy5yZWZsZWN0Vikge1xyXG4gICAgICAgIC8vICAgICBjb250ZXh0LnRyYW5zbGF0ZShzaXplLncsIDApO1xyXG4gICAgICAgIC8vICAgICBjb250ZXh0LnNjYWxlKC0xLCAxKTtcclxuICAgICAgICAvLyB9XHJcbiAgICAgICAgLy8gaWYgKHRoaXMucmVmbGVjdEgpIHtcclxuICAgICAgICAvLyAgICAgY29udGV4dC50cmFuc2xhdGUoMCwgc2l6ZS5oKTtcclxuICAgICAgICAvLyAgICAgY29udGV4dC5zY2FsZSgxLCAtMSk7XHJcbiAgICAgICAgLy8gfVxyXG5cclxuICAgICAgICBsZXQgaW1hZ2VXaWR0aCA9IHNpemUudztcclxuICAgICAgICBsZXQgaW1hZ2VIZWlnaHQgPSBzaXplLmg7XHJcbiAgICAgICAgaW1hZ2UuYWRkRXZlbnRMaXN0ZW5lcignbG9hZCcsICgpID0+IHtcclxuICAgICAgICAgICAgaWYgKGljb25lKSB7XHJcbiAgICAgICAgICAgICAgICBpbWFnZVdpZHRoID0gaW1hZ2Uud2lkdGg7XHJcbiAgICAgICAgICAgICAgICBpbWFnZUhlaWdodCA9IGltYWdlLmhlaWdodDtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICBjb250ZXh0LmRyYXdJbWFnZShcclxuICAgICAgICAgICAgICAgIGltYWdlLFxyXG4gICAgICAgICAgICAgICAgMCxcclxuICAgICAgICAgICAgICAgIDAsXHJcbiAgICAgICAgICAgICAgICBpbWFnZS53aWR0aCxcclxuICAgICAgICAgICAgICAgIGltYWdlLmhlaWdodCxcclxuICAgICAgICAgICAgICAgIHgsXHJcbiAgICAgICAgICAgICAgICB5LFxyXG4gICAgICAgICAgICAgICAgaW1hZ2VXaWR0aCxcclxuICAgICAgICAgICAgICAgIGltYWdlSGVpZ2h0XHJcbiAgICAgICAgICAgICk7XHJcbiAgICAgICAgfSk7XHJcbiAgICAgICAgaW1hZ2Uuc3JjID0gdXJsO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKiBHZXQgdGhlIHNpemUgZm9yIHRoZSBjYW52YXMsIGJhc2VkIG9uIHRoZSBwbGFuIHNpemUsIGtlZXBpbmcgdGhlIHJhdGlvICovXHJcbiAgICBnZXRTaXplRm9yQ2FudmFzKHcsIGgpIHtcclxuICAgICAgICBsZXQgY2FudmFzVyA9IHRoaXMuY2FudmFzRGl2Lm5hdGl2ZUVsZW1lbnQub2Zmc2V0V2lkdGg7XHJcbiAgICAgICAgbGV0IGNhbnZhc0ggPSB0aGlzLmNhbnZhc0Rpdi5uYXRpdmVFbGVtZW50Lm9mZnNldEhlaWdodDtcclxuXHJcbiAgICAgICAgY29uc3QgaW1hZ2VSYXRpbyA9IHcgLyBoO1xyXG4gICAgICAgIGNvbnN0IGNhbnZhc1JhdGlvID0gY2FudmFzVyAvIGNhbnZhc0g7XHJcblxyXG4gICAgICAgIGlmIChpbWFnZVJhdGlvID4gY2FudmFzUmF0aW8pIHtcclxuICAgICAgICAgICAgY2FudmFzSCA9IGNhbnZhc1cgLyBpbWFnZVJhdGlvO1xyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgIGNhbnZhc1cgPSBjYW52YXNIICogaW1hZ2VSYXRpbztcclxuICAgICAgICB9XHJcbiAgICAgICAgcmV0dXJuIHsgdzogY2FudmFzVywgaDogY2FudmFzSCB9O1xyXG4gICAgfVxyXG5cclxuICAgIC8qKiBbVE9ET10gQ29udmVydCBhIFBERiB0byBhIENhbnZhcyAqL1xyXG4gICAgYXN5bmMgcGRmVG9DYW52YXMoKSB7XHJcbiAgICAgICAgY29uc3QgcGRmanMgPSBhd2FpdCBpbXBvcnQoJ3BkZmpzLWRpc3QvYnVpbGQvcGRmJyk7XHJcbiAgICAgICAgY29uc3QgcGRmanNXb3JrZXIgPSBhd2FpdCBpbXBvcnQoJ3BkZmpzLWRpc3QvYnVpbGQvcGRmLndvcmtlci5lbnRyeScpO1xyXG5cclxuICAgICAgICBwZGZqcy5HbG9iYWxXb3JrZXJPcHRpb25zLndvcmtlclNyYyA9IHBkZmpzV29ya2VyO1xyXG5cclxuICAgICAgICBjb25zdCBwZGY6IFBERkRvY3VtZW50UHJveHkgPSBhd2FpdCBnZXREb2N1bWVudCh0aGlzLmNob3NlblBsYW4uZmlsZXBhdGgpXHJcbiAgICAgICAgICAgIC5wcm9taXNlO1xyXG4gICAgICAgIGNvbnN0IHBhZ2UgPSBhd2FpdCBwZGYuZ2V0UGFnZSgxKTtcclxuXHJcbiAgICAgICAgY29uc3Qgdmlld1BvcnRQYXJhbWV0ZXJzID0geyBzY2FsZTogMSB9O1xyXG4gICAgICAgIGNvbnN0IHZpZXdwb3J0ID0gcGFnZS5nZXRWaWV3cG9ydCh2aWV3UG9ydFBhcmFtZXRlcnMpO1xyXG5cclxuICAgICAgICB0aGlzLmNhbnZhcy5oZWlnaHQgPSB2aWV3cG9ydC5oZWlnaHQ7XHJcbiAgICAgICAgdGhpcy5jYW52YXMud2lkdGggPSB2aWV3cG9ydC53aWR0aDtcclxuXHJcbiAgICAgICAgY29uc3Qgc2l6ZSA9IHRoaXMuZ2V0U2l6ZUZvckNhbnZhcyh2aWV3cG9ydC53aWR0aCwgdmlld3BvcnQuaGVpZ2h0KTtcclxuICAgICAgICBjb25zb2xlLmxvZyhzaXplKTtcclxuICAgICAgICB0aGlzLmNhbnZhc1NpemUgPSBzaXplO1xyXG5cclxuICAgICAgICB0aGlzLmNhbnZhc1pvb20gPSBzaXplLncgLyB2aWV3cG9ydC53aWR0aDtcclxuXHJcbiAgICAgICAgY29uc3QgY29udGV4dCA9IHRoaXMuY2FudmFzLmdldENvbnRleHQoJzJkJykgYXMgQ2FudmFzUmVuZGVyaW5nQ29udGV4dDJEO1xyXG4gICAgICAgIGNvbnN0IHJlbmRlckNvbnRleHQgPSB7XHJcbiAgICAgICAgICAgIGNhbnZhc0NvbnRleHQ6IGNvbnRleHQsXHJcbiAgICAgICAgICAgIHZpZXdwb3J0LFxyXG4gICAgICAgIH07XHJcbiAgICAgICAgY29uc3QgcmVuZGVyVGFzayA9IHBhZ2UucmVuZGVyKHJlbmRlckNvbnRleHQpLnByb21pc2U7XHJcblxyXG4gICAgICAgIHJlbmRlclRhc2sudGhlbigoKSA9PiBjb25zb2xlLmxvZygnUGFnZSByZW5kZXJlZCcpKTtcclxuXHJcbiAgICAgICAgLy8gY29uc3QgcmVzID0gY2FudmFzLnRvRGF0YVVSTCgpO1xyXG4gICAgICAgIC8vIGlmIChwZGYgIT0gbnVsbCkgcGRmLmRlc3Ryb3koKTtcclxuICAgICAgICAvLyByZXR1cm4gcmVzO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKiBVc2VyIGNsaWNrIHRvIHVzZXIgU3ltbWV0cnkgVmVydGljYWwgKi9cclxuICAgIG9uUmVmbGVjdFYoKSB7XHJcbiAgICAgICAgdGhpcy5yZWZsZWN0ViA9ICF0aGlzLnJlZmxlY3RWO1xyXG4gICAgICAgIHRoaXMuY29uZmlndXJlQ2FudmFzKCk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqIFVzZXIgY2xpY2sgdG8gdXNlciBTeW1tZXRyeSBIb3Jpem9udGFsICovXHJcbiAgICBvblJlZmxlY3RIKCkge1xyXG4gICAgICAgIHRoaXMucmVmbGVjdEggPSAhdGhpcy5yZWZsZWN0SDtcclxuICAgICAgICB0aGlzLmNvbmZpZ3VyZUNhbnZhcygpO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKiAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqXHJcbiAgICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBNQVRURVJQT1JUXHJcbiAgICAgKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiogKi9cclxuXHJcbiAgICAvKiogTGF1bmNoIG1hdHRlcnBvcnQgKi9cclxuICAgIGFzeW5jIGxhdW5jaFZpZXdlcigpIHtcclxuICAgICAgICBhd2FpdCB0aGlzLm1hdHRlcnBvcnRJbXBvcnRTZXJ2aWNlLmluaXRTZGtGb3JNb2RlbCh0aGlzLmNob3NlblBsYW4ubW9kZWwzZCk7XHJcblxyXG4gICAgICAgIGNvbnN0IHsgc2RrIH0gPSB0aGlzLm1hdHRlcnBvcnRJbXBvcnRTZXJ2aWNlO1xyXG4gICAgICAgIHRoaXMuZmxvb3JzID0gT2JqZWN0LnZhbHVlcyh0aGlzLm1hdHRlcnBvcnRJbXBvcnRTZXJ2aWNlLmZsb29ycyk7XHJcbiAgICAgICAgLy8gY29uc29sZS5sb2codGhpcy5mbG9vcnMpO1xyXG4gICAgICAgIHNldFRpbWVvdXQoYXN5bmMgKCkgPT4ge1xyXG4gICAgICAgICAgICAvKiogTW92ZSBGbG9vciBtb2RlICovXHJcbiAgICAgICAgICAgIHNkay5Nb2RlLm1vdmVUbyhzZGsuTW9kZS5Nb2RlLkZMT09SUExBTikudGhlbihhc3luYyAobmV4dE1vZGUpID0+IHtcclxuICAgICAgICAgICAgICAgIC8qKiBEaXNwbGF5IHRoZSBjb3JyZWN0IGZsb29yIGZvciB0aGUgcGxhbiAqL1xyXG4gICAgICAgICAgICAgICAgdHJ5IHtcclxuICAgICAgICAgICAgICAgICAgICBjb25zdCBtYXR0ZXJwb3J0Rmxvb3IgPSB0aGlzLmNob3NlblBsYW4uem9uZS5tZXRhZGF0YSA/XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIEpTT04ucGFyc2UodGhpcy5jaG9zZW5QbGFuLnpvbmUubWV0YWRhdGEpLm1hdHRlcnBvcnRGbG9vclNlcXVlbmNlIDogbnVsbDtcclxuICAgICAgICAgICAgICAgICAgICBhd2FpdCB0aGlzLm1hdHRlcnBvcnRJbXBvcnRTZXJ2aWNlLm1vdmVUb0Zsb29yKHRoaXMuY2hvc2VuUGxhbi56b25lLm5hbWUsIG1hdHRlcnBvcnRGbG9vcik7XHJcblxyXG4gICAgICAgICAgICAgICAgICAgIC8qKiBXaGVuIHRoZSB1c2VyIHRyeSB0byBjaGFuZ2UgdGhlIHZpZXcgbW9kZSB3ZSBzZXQgaXQgYmFjayB0byBmbG9vcnBhbiAqL1xyXG4gICAgICAgICAgICAgICAgICAgIHNkay5vbihzZGsuTW9kZS5FdmVudC5DSEFOR0VfRU5ELCAob2xkTW9kZSwgbmV3TW9kZSkgPT4ge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAobmV3TW9kZSAhPT0gc2RrLk1vZGUuTW9kZS5GTE9PUlBMQU4pIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNkay5Nb2RlLm1vdmVUbyhzZGsuTW9kZS5Nb2RlLkZMT09SUExBTiwge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRyYW5zaXRpb246ICd0cmFuc2l0aW9uLmluc3RhbnQnLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICB9KTtcclxuICAgICAgICAgICAgICAgIH0gY2F0Y2gge1xyXG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKCdjb3VsZG5vdCBtb3ZlIHRvIGZsb29yJyk7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH0pO1xyXG5cclxuICAgICAgICAgICAgLyoqIFdlIGNhbiBkaXNwbGF5IHRoZSBtYXR0ZXJwb3J0IHZpZXcgbm93ICovXHJcbiAgICAgICAgICAgIHRoaXMubG9hZGluZyA9IGZhbHNlO1xyXG4gICAgICAgIH0sIDEwMDApO1xyXG5cclxuICAgICAgICAvKiogVXBkYXRlIGN1cnJlbnQgY2FtZXJhIHBvc2UgYW5kIHJvdGF0aW9uICovXHJcbiAgICAgICAgc2RrLkNhbWVyYS5wb3NlLnN1YnNjcmliZSgoZXZlbnQpID0+IHtcclxuICAgICAgICAgICAgLyoqIFdlIHVwZGF0ZSBvbmx5IGlmIHRoZSB1c2VyIGlzIG5vdCBjaGFuZ2luZyB0aGUgcm90YXRpb24gd2l0aCB0aGUgPGlucHV0PiByYW5nZSwgdG8gbm90IG92ZXJyaWRlIHRoZSA8aW5wdXQ+IHZhbHVlICovXHJcbiAgICAgICAgICAgIGlmICghdGhpcy5pc1JvdGF0aW5nUmFuZ2UpIHtcclxuICAgICAgICAgICAgICAgIHRoaXMucm90YXRpb24gPSBldmVudC5yb3RhdGlvbi55ICsgMTgwO1xyXG4gICAgICAgICAgICAgICAgdGhpcy5wcmV2Um90YXRpb24gPSB0aGlzLnJvdGF0aW9uO1xyXG4gICAgICAgICAgICAgICAgdGhpcy5jYW1lcmFQb3NlID0gZXZlbnQ7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9KTtcclxuICAgIH1cclxuXHJcbiAgICAvKiogV2hlbiB0aGUgPGlucHV0PiByYW5nZSwgZm9yIHJvdGF0aW9uLCBjaGFuZ2UgKi9cclxuICAgIGFzeW5jIG9uUm90YXRpb25DaGFuZ2UoKSB7XHJcbiAgICAgICAgY29uc3Qgcm90YXRpb25EZWx0YSA9IHRoaXMucm90YXRpb24gLSB0aGlzLnByZXZSb3RhdGlvbjtcclxuICAgICAgICB0aGlzLnByZXZSb3RhdGlvbiA9IHRoaXMucm90YXRpb247XHJcblxyXG4gICAgICAgIC8qKiBTZW5kIHRoZSByb3RhdGlvbkRlbHRhIHRvIHRoIHF1ZXVlIGV2ZW50IGluIG9yZGVyIHRvIGJlIHNlbmQgdG8gbWF0dGVycG9ydCAqL1xyXG4gICAgICAgIHRoaXMucm90YXRpbmdRdWV1ZUV2ZW50LnB1c2gocm90YXRpb25EZWx0YSk7XHJcblxyXG4gICAgICAgIC8qKiBTdGFydCB0byBwcm9jZXNzIHRoZSBxdWV1ZSwgaWYgaXQncyB0aGUgZmlyc3QgZXZlbnQgKi9cclxuICAgICAgICBpZiAoIXRoaXMuaXNSb3RhdGluZ1JhbmdlKSB7XHJcbiAgICAgICAgICAgIHRoaXMuaXNSb3RhdGluZ1JhbmdlID0gdHJ1ZTtcclxuICAgICAgICAgICAgdGhpcy5wcm9jZXNzUm90YXRpbmdRdWV1ZUV2ZW50KCk7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIC8qKiBQcm9jZXNzIHRoZSByb3RhdGluZyBldmVudCBxdWV1ZSwgc2VuZCBldmVudCBvbmUgYnkgb25lIHRvIG1hdHRlcnBvcnQgICovXHJcbiAgICBhc3luYyBwcm9jZXNzUm90YXRpbmdRdWV1ZUV2ZW50KCkge1xyXG4gICAgICAgIGNvbnN0IHsgc2RrIH0gPSB0aGlzLm1hdHRlcnBvcnRJbXBvcnRTZXJ2aWNlO1xyXG5cclxuICAgICAgICAvKiogV2hpbGUgdGhlIHF1ZXVlIGlzIG5vdCBlbXB0eSAqL1xyXG4gICAgICAgIHdoaWxlICh0aGlzLnJvdGF0aW5nUXVldWVFdmVudC5sZW5ndGggPiAwKSB7XHJcbiAgICAgICAgICAgIC8qKiBSb3RhdGUgbWF0dGVycG9ydCBieSBkZWx0YVJvdGF0aW9uIGFuZCByZW1vdmUgZXZlbnQgZnJvbSBxdWV1ZSAqL1xyXG4gICAgICAgICAgICBhd2FpdCBzZGsuQ2FtZXJhLnJvdGF0ZSh0aGlzLnJvdGF0aW5nUXVldWVFdmVudC5zaGlmdCgpLCAwLCB7XHJcbiAgICAgICAgICAgICAgICBzcGVlZDogMzYwLFxyXG4gICAgICAgICAgICB9KTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIC8qKiBXaGVuIHRoZSBxdWV1ZSBpcyBlbXB0eSwgdGhlbiB0aGUgdXNlciBpcyBub3Qgcm90YXRpbmcgd2l0aCB0aGUgPGlucHV0PiByYW5nZSBhbnltb3JlICovXHJcbiAgICAgICAgdGhpcy5pc1JvdGF0aW5nUmFuZ2UgPSBmYWxzZTtcclxuICAgIH1cclxuXHJcbiAgICAvKiogKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKlxyXG4gICAgICogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVVNFUiBBQ1RJT05TXHJcbiAgICAgKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiogKi9cclxuXHJcbiAgICAvKiogUHJldmlldyBjYWxpYnJhdGlvbiAqL1xyXG4gICAgYXN5bmMgb25QcmV2aWV3KCkge1xyXG4gICAgICAgIHRoaXMucHJldmlldyA9IHRydWU7XHJcbiAgICAgICAgLyoqIFBsYWNlIHN3ZWVwcyAqL1xyXG4gICAgICAgIHRoaXMub25QbGFjZVN3ZWVwcygpO1xyXG4gICAgfVxyXG5cclxuICAgIGFzeW5jIGNhbGlicmF0ZSgpIHtcclxuICAgICAgICBjb25zdCBbbmF2aWdhdGlvbl0gPSB0aGlzLmN1cnJlbnROYXZpZ2F0aW9ucztcclxuICAgICAgICBjb25zdCBwb3NpdGlvbiA9IEpTT04ucGFyc2UobmF2aWdhdGlvbi5wb3NpdGlvbik7XHJcbiAgICAgICAgdGhpcy5maXJzdE1hcmtQbGFuID1cclxuICAgICAgICAgICAgYXdhaXQgdGhpcy5tYXR0ZXJwb3J0SW1wb3J0U2VydmljZS5zZGsuUmVuZGVyZXIuZ2V0U2NyZWVuUG9zaXRpb24oe1xyXG4gICAgICAgICAgICAgICAgeDogcG9zaXRpb24ueCxcclxuICAgICAgICAgICAgICAgIHk6IHBvc2l0aW9uLnksXHJcbiAgICAgICAgICAgICAgICB6OiBwb3NpdGlvbi56LFxyXG4gICAgICAgICAgICB9KTtcclxuICAgICAgICB0aGlzLnNlY29uZE1hcmtQbGFuID1cclxuICAgICAgICAgICAgYXdhaXQgdGhpcy5tYXR0ZXJwb3J0SW1wb3J0U2VydmljZS5zZGsuUmVuZGVyZXIuZ2V0U2NyZWVuUG9zaXRpb24oe1xyXG4gICAgICAgICAgICAgICAgeDogcG9zaXRpb24ueCxcclxuICAgICAgICAgICAgICAgIHk6IDAsXHJcbiAgICAgICAgICAgICAgICB6OiAwLFxyXG4gICAgICAgICAgICB9KTtcclxuICAgICAgICBjb25zdCBkZWx0YVpWaXNpdCA9IDAgLSBwb3NpdGlvbi56O1xyXG4gICAgICAgIGxldCBkZWx0YVhQbGFuID0gdGhpcy5zZWNvbmRNYXJrUGxhbi54IC0gdGhpcy5maXJzdE1hcmtQbGFuLng7XHJcbiAgICAgICAgaWYgKGRlbHRhWFBsYW4gPT09IDApIHtcclxuICAgICAgICAgICAgLy8gY29uc29sZS5sb2coXCJ3ZSBtb3ZlZCBhbG9uZyBZIGF4aXMgb24gUGxhblwiKTtcclxuICAgICAgICAgICAgY29uc3QgZGVsdGFZUGxhbiA9IHRoaXMuc2Vjb25kTWFya1BsYW4ueSAtIHRoaXMuZmlyc3RNYXJrUGxhbi55O1xyXG4gICAgICAgICAgICB0aGlzLmNhbGlicmFnZS5uYW1lWUF4aXMgPSAneic7XHJcbiAgICAgICAgICAgIHRoaXMuY2FsaWJyYWdlLm5hbWVYQXhpcyA9ICd4JztcclxuICAgICAgICAgICAgdGhpcy5jYWxpYnJhZ2Uub2Zmc2V0WSA9IHRoaXMuc2Vjb25kTWFya1BsYW4ueTtcclxuICAgICAgICAgICAgdGhpcy5jYWxpYnJhZ2Uuc2NhbGVZID0gZGVsdGFZUGxhbiAvIGRlbHRhWlZpc2l0O1xyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgIC8vIGNvbnNvbGUubG9nKFwiIHdlIG1vdmVkIGFsb25nIFggYXhpcyBvbiBQbGFuXCIpO1xyXG4gICAgICAgICAgICB0aGlzLmNhbGlicmFnZS5uYW1lWUF4aXMgPSAneCc7XHJcbiAgICAgICAgICAgIHRoaXMuY2FsaWJyYWdlLm5hbWVYQXhpcyA9ICd6JztcclxuICAgICAgICAgICAgdGhpcy5jYWxpYnJhZ2Uub2Zmc2V0WCA9IHRoaXMuc2Vjb25kTWFya1BsYW4ueDtcclxuICAgICAgICAgICAgdGhpcy5jYWxpYnJhZ2Uuc2NhbGVYID0gZGVsdGFYUGxhbiAvIGRlbHRhWlZpc2l0O1xyXG4gICAgICAgIH1cclxuICAgICAgICBjb25zdCB0aGlyZE1hcmtQbGFuID1cclxuICAgICAgICAgICAgYXdhaXQgdGhpcy5tYXR0ZXJwb3J0SW1wb3J0U2VydmljZS5zZGsuUmVuZGVyZXIuZ2V0U2NyZWVuUG9zaXRpb24oe1xyXG4gICAgICAgICAgICAgICAgeDogMCxcclxuICAgICAgICAgICAgICAgIHk6IDAsXHJcbiAgICAgICAgICAgICAgICB6OiBwb3NpdGlvbi56LFxyXG4gICAgICAgICAgICB9KTtcclxuICAgICAgICBjb25zdCBkZWx0YVhWaXNpdCA9IDAgLSBwb3NpdGlvbi54O1xyXG4gICAgICAgIGlmIChkZWx0YVhQbGFuID09PSAwKSB7XHJcbiAgICAgICAgICAgIC8vIGNvbnNvbGUubG9nKFwiIHdlIG1vdmVkIGFsb25nIFggYXhpcyBvbiBQbGFuXCIpO1xyXG4gICAgICAgICAgICBkZWx0YVhQbGFuID0gdGhpcmRNYXJrUGxhbi54IC0gdGhpcy5maXJzdE1hcmtQbGFuLng7XHJcbiAgICAgICAgICAgIHRoaXMuY2FsaWJyYWdlLm9mZnNldFggPSB0aGlyZE1hcmtQbGFuLng7XHJcbiAgICAgICAgICAgIHRoaXMuY2FsaWJyYWdlLnNjYWxlWCA9IGRlbHRhWFBsYW4gLyBkZWx0YVhWaXNpdDtcclxuICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICBjb25zdCBkZWx0YVlQbGFuID0gdGhpcmRNYXJrUGxhbi55IC0gdGhpcy5maXJzdE1hcmtQbGFuLnk7XHJcbiAgICAgICAgICAgIHRoaXMuY2FsaWJyYWdlLm9mZnNldFkgPSB0aGlyZE1hcmtQbGFuLnk7XHJcbiAgICAgICAgICAgIHRoaXMuY2FsaWJyYWdlLnNjYWxlWSA9IGRlbHRhWVBsYW4gLyBkZWx0YVhWaXNpdDtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIC8qKiBUYWtlIGNvbnNpZGlyYXRpb24gb2YgcGFuIGFuZCB6b29tIG9mIHBsYW4gb24gY2FudmFzICovXHJcbiAgICAgICAgY29uc3QgdHJhbnNmb3JtSW5mbyA9IHRoaXMucGFuem9vbS5nZXRUcmFuc2Zvcm0oKTtcclxuICAgICAgICBjb25zdCB7IHNjYWxlLCB4LCB5IH0gPSB0cmFuc2Zvcm1JbmZvO1xyXG4gICAgICAgIC8vIGNvbnNvbGUubG9nKHRyYW5zZm9ybUluZm8pO1xyXG4gICAgICAgIHRoaXMuY2FsaWJyYWdlLm9mZnNldFhQbGFuID0geDtcclxuICAgICAgICB0aGlzLmNhbGlicmFnZS5vZmZzZXRZUGxhbiA9IHk7XHJcbiAgICAgICAgdGhpcy5jYWxpYnJhZ2Uuc2NhbGVQbGFuID0gc2NhbGU7XHJcbiAgICAgICAgY29uc29sZS5sb2codGhpcy5jYWxpYnJhZ2UpO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKiBQbGFjZSBzd2VlcHMgKi9cclxuICAgIGFzeW5jIG9uUGxhY2VTd2VlcHMoKSB7XHJcbiAgICAgICAgLyoqIERpc3BsYXkgYWxsIHNjYW4gKi9cclxuICAgICAgICBjb25zdCB6b25lID0gYXdhaXQgdGhpcy56b25lU2VydmljZS5nZXRab25lKHRoaXMuY2hvc2VuUGxhbi56b25lSUQpO1xyXG5cclxuICAgICAgICBpZiAoem9uZSkge1xyXG4gICAgICAgICAgICB0aGlzLmN1cnJlbnRab25lID0gem9uZTtcclxuICAgICAgICAgICAgY29uc3QgbmF2aWdhdGlvbnMgPSBhd2FpdCB0aGlzLm5hdmlnYXRpb25TZXJ2aWNlLmdldE5hdmlnYXRpb25zRm9yWm9uZShcclxuICAgICAgICAgICAgICAgIHRoaXMuY3VycmVudFpvbmVcclxuICAgICAgICAgICAgKTtcclxuICAgICAgICAgICAgdGhpcy5jdXJyZW50TmF2aWdhdGlvbnMgPSBuYXZpZ2F0aW9ucztcclxuICAgICAgICAgICAgYXdhaXQgdGhpcy5jYWxpYnJhdGUoKTtcclxuICAgICAgICAgICAgaWYgKG5hdmlnYXRpb25zLmxlbmd0aCA+IDApIHtcclxuICAgICAgICAgICAgICAgIGZvciAoY29uc3QgbmF2aWdhdGlvbiBvZiBuYXZpZ2F0aW9ucykge1xyXG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHRlc3RQb3NpdGlvbiA9IEpTT04ucGFyc2UobmF2aWdhdGlvbi5wb3NpdGlvbik7XHJcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgcG9zaXRpb25YID1cclxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jYWxpYnJhZ2UubmFtZVhBeGlzID09PSAneCcgPyB0ZXN0UG9zaXRpb24ueCA6IHRlc3RQb3NpdGlvbi56O1xyXG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHBvc2l0aW9uWSA9XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY2FsaWJyYWdlLm5hbWVZQXhpcyA9PT0gJ3gnID8gdGVzdFBvc2l0aW9uLnggOiB0ZXN0UG9zaXRpb24uejtcclxuICAgICAgICAgICAgICAgICAgICBjb25zdCB0ZXN0WCA9XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHBvc2l0aW9uWCAqIHRoaXMuY2FsaWJyYWdlLnNjYWxlWCArIHRoaXMuY2FsaWJyYWdlLm9mZnNldFg7XHJcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgdGVzdFkgPVxyXG4gICAgICAgICAgICAgICAgICAgICAgICBwb3NpdGlvblkgKiB0aGlzLmNhbGlicmFnZS5zY2FsZVkgKyB0aGlzLmNhbGlicmFnZS5vZmZzZXRZO1xyXG4gICAgICAgICAgICAgICAgICAgIC8vIGNvbnNvbGUubG9nKFwidGVzdCBwb3NpdGlvbiBHUkVFTlwiLCB0ZXN0WCwgdGVzdFkpO1xyXG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHRyYW5zZm9ybWVkWCA9XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICh0ZXN0WCAtIHRoaXMuY2FsaWJyYWdlLm9mZnNldFhQbGFuKSAvIHRoaXMuY2FsaWJyYWdlLnNjYWxlUGxhbjsgLy8gd2UgYXJlIHVuZG9pbmcgdGhlIHBhbiBhbmQgem9vbVxyXG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHRyYW5zZm9ybWVkWSA9XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICh0ZXN0WSAtIHRoaXMuY2FsaWJyYWdlLm9mZnNldFlQbGFuKSAvIHRoaXMuY2FsaWJyYWdlLnNjYWxlUGxhbjtcclxuICAgICAgICAgICAgICAgICAgICB0aGlzLnBvc2l0aW9ucy5wdXNoKHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgbmF2SUQ6IG5hdmlnYXRpb24uaWQsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHBsYW5JRDogdGhpcy5jaG9zZW5QbGFuLmlkLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICB4OiB0cmFuc2Zvcm1lZFgsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHk6IHRyYW5zZm9ybWVkWSxcclxuICAgICAgICAgICAgICAgICAgICB9KTtcclxuICAgICAgICAgICAgICAgICAgICBjb25zdCBpY29uU2l6ZSA9IDMwICogdGhpcy5jYWxpYnJhZ2Uuc2NhbGVQbGFuO1xyXG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHNoaWZ0ID0gaWNvblNpemUgLyAyO1xyXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZHJhd0ltYWdlKFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAnaHR0cHM6Ly9hcGkuaWNvbmlmeS5kZXNpZ24vbWRpOmFkanVzdC5zdmc/Y29sb3I9Z3JlZW4maGVpZ2h0PTMwJndpZHRoPTMwJyxcclxuICAgICAgICAgICAgICAgICAgICAgICAgdHJhbnNmb3JtZWRYIC0gc2hpZnQsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHRyYW5zZm9ybWVkWSAtIHNoaWZ0LFxyXG4gICAgICAgICAgICAgICAgICAgICAgICB0cnVlXHJcbiAgICAgICAgICAgICAgICAgICAgKTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICAvKiogU2F2ZSBjYWxpYnJhdGlvbiAqL1xyXG4gICAgYXN5bmMgb25TYXZlKCkge1xyXG4gICAgICAgIGlmICh0aGlzLmN1cnJlbnRab25lKSB7XHJcbiAgICAgICAgICAgIC8qKiBOb3JtYWxpemUgd2l0aCB0aGUgem9vbSAqL1xyXG4gICAgICAgICAgICAvLyB0aGlzLmNhbGlicmFnZS5vZmZzZXRYIC89IHRoaXMuY2FudmFzWm9vbTtcclxuICAgICAgICAgICAgLy8gdGhpcy5jYWxpYnJhZ2Uub2Zmc2V0WSAvPSB0aGlzLmNhbnZhc1pvb207XHJcbiAgICAgICAgICAgIC8vIHRoaXMuY2FsaWJyYWdlLnggLz0gdGhpcy5jYW52YXNab29tO1xyXG4gICAgICAgICAgICAvLyB0aGlzLmNhbGlicmFnZS55IC89IHRoaXMuY2FudmFzWm9vbTtcclxuICAgICAgICAgICAgdGhpcy5jYWxpYnJhZ2UubmV3ID0gdHJ1ZTtcclxuICAgICAgICAgICAgdGhpcy5jYWxpYnJhZ2UuaW1nV2lkdGggPSB0aGlzLmNhbnZhc1NpemUudztcclxuICAgICAgICAgICAgdGhpcy5jYWxpYnJhZ2UuaW1nSGVpZ2h0ID0gdGhpcy5jYW52YXNTaXplLmg7XHJcblxyXG4gICAgICAgICAgICBhd2FpdCB0aGlzLnBsYW5TZXJ2aWNlLnVwZGF0ZVBsYW4oe1xyXG4gICAgICAgICAgICAgICAgaWQ6IHRoaXMuY2hvc2VuUGxhbi5pZCxcclxuICAgICAgICAgICAgICAgIGNhbGlicmF0aW9uOiBKU09OLnN0cmluZ2lmeSh0aGlzLmNhbGlicmFnZSksXHJcbiAgICAgICAgICAgIH0pO1xyXG4gICAgICAgICAgICBhd2FpdCBQcm9taXNlLmFsbChcclxuICAgICAgICAgICAgICAgIHRoaXMucG9zaXRpb25zLm1hcChhc3luYyAocG9zaXRpb24pID0+IHtcclxuICAgICAgICAgICAgICAgICAgICBjb25zdCB7IG5hdklEIH0gPSBwb3NpdGlvbjtcclxuICAgICAgICAgICAgICAgICAgICBkZWxldGUgcG9zaXRpb24ubmF2SUQ7XHJcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgbmF2ID0gdGhpcy5jdXJyZW50TmF2aWdhdGlvbnMuZmluZCgoX25hdikgPT4gX25hdi5pZCA9PT0gbmF2SUQpO1xyXG4gICAgICAgICAgICAgICAgICAgIGxldCBwb3NpdGlvbnNEYXRhVG9VcGRhdGU7XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKG5hdi5wb3NpdGlvbk9uUGxhbikge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBwb3NpdGlvbk9uUGxhbiA9IG5hdi5wb3NpdGlvbk9uUGxhbi5tYXAoKGVudHJ5KSA9PlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgSlNPTi5wYXJzZShlbnRyeSlcclxuICAgICAgICAgICAgICAgICAgICAgICAgKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgcG9zaXRpb25Gb3JDdXJyZW50UGxhbiA9IHBvc2l0aW9uT25QbGFuLmZpbmQoXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAoZW50cnkpID0+IGVudHJ5LnBsYW5JRCA9PT0gdGhpcy5jaG9zZW5QbGFuLmlkXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChwb3NpdGlvbkZvckN1cnJlbnRQbGFuKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwb3NpdGlvbk9uUGxhbi5zcGxpY2UoXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcG9zaXRpb25PblBsYW4uaW5kZXhPZihwb3NpdGlvbkZvckN1cnJlbnRQbGFuKSxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAxLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBvc2l0aW9uXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICApO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcG9zaXRpb25PblBsYW4ucHVzaChwb3NpdGlvbik7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICAgICAgcG9zaXRpb25zRGF0YVRvVXBkYXRlID0gWy4uLnBvc2l0aW9uT25QbGFuXTtcclxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBwb3NpdGlvbnNEYXRhVG9VcGRhdGUgPSBbcG9zaXRpb25dO1xyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICAvLyBjb25zb2xlLmxvZyhwb3NpdGlvbnNEYXRhVG9VcGRhdGUpO1xyXG4gICAgICAgICAgICAgICAgICAgIGF3YWl0IHRoaXMubmF2aWdhdGlvblNlcnZpY2UudXBkYXRlTmF2aWdhdGlvbih7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGlkOiBuYXZJRCxcclxuICAgICAgICAgICAgICAgICAgICAgICAgcG9zaXRpb25PblBsYW46IHBvc2l0aW9uc0RhdGFUb1VwZGF0ZS5tYXAoKGVudHJ5KSA9PlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgSlNPTi5zdHJpbmdpZnkoZW50cnkpXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICksXHJcbiAgICAgICAgICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgICAgICAgICB9KVxyXG4gICAgICAgICAgICApO1xyXG4gICAgICAgIH1cclxuICAgICAgICB0aGlzLm1hdHRlcnBvcnRJbXBvcnRTZXJ2aWNlLnJlbW92ZUZyYW1lKCk7XHJcblxyXG4gICAgICAgIHRoaXMucm91dGVyLm5hdmlnYXRlKFsnL2Rhc2hib2FyZC9sb2NhbGlzYXRpb24nLCB0aGlzLnNwYWNlSUQsICdwbGFucyddKTtcclxuICAgICAgICBhbGVydCh0aGlzLnRyYW5zbGF0ZS5pbnN0YW50KCdjYWxpYnJhdGlvbi5zdWNjZXNzJykpO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKiBSZXNldCB0aGUgY2FudmFzICovXHJcbiAgICBvblJlc2V0KCkge1xyXG4gICAgICAgIHRoaXMucmVmbGVjdEggPSBmYWxzZTtcclxuICAgICAgICB0aGlzLnJlZmxlY3RWID0gZmFsc2U7XHJcbiAgICAgICAgdGhpcy5wcmV2aWV3ID0gZmFsc2U7XHJcblxyXG4gICAgICAgIHRoaXMuY29uZmlndXJlQ2FudmFzKCk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqIENhbmNlbCwgbGVhdmUgKi9cclxuICAgIG9uQ2FuY2VsKCkge1xyXG4gICAgICAgIHRoaXMubWF0dGVycG9ydEltcG9ydFNlcnZpY2UucmVtb3ZlRnJhbWUoKTtcclxuICAgICAgICB0aGlzLnJvdXRlci5uYXZpZ2F0ZShbJy9kYXNoYm9hcmQvbG9jYWxpc2F0aW9uJywgdGhpcy5zcGFjZUlELCAncGxhbnMnXSk7XHJcbiAgICAgICAgYWxlcnQodGhpcy50cmFuc2xhdGUuaW5zdGFudCgnY2FsaWJyYXRpb24uY2FuY2VsZWQnKSk7XHJcbiAgICB9XHJcblxyXG4gICAgYXN5bmMgb25GbG9vckNsaWNrKGZsb29yKSB7XHJcbiAgICAgICAgdGhpcy5jdXJyZW50Rmxvb3IgPSBmbG9vcjtcclxuICAgICAgICBhd2FpdCB0aGlzLm1hdHRlcnBvcnRJbXBvcnRTZXJ2aWNlLm1vdmVUb0Zsb29yKGZsb29yLmlkKTtcclxuICAgIH1cclxuXHJcbiAgICBvbkFjdGl2YXRlWm9vbUNoYW5nZSgpIHtcclxuICAgICAgICB0aGlzLnpvb21DYW5CZUNoYW5nZWQgPSAhdGhpcy56b29tQ2FuQmVDaGFuZ2VkO1xyXG4gICAgICAgIGNvbnN0IGlmcmFtZSA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoJyN2aWV3ZXItZnJhbWUnKSBhcyBIVE1MRWxlbWVudDtcclxuICAgICAgICBpZiAoaWZyYW1lKSB7XHJcbiAgICAgICAgICAgIGlmcmFtZS5zdHlsZS56SW5kZXggPSB0aGlzLnpvb21DYW5CZUNoYW5nZWQgPyAnMScgOiAnMCc7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG59XHJcbiIsIjxkaXYgY2xhc3M9XCJyb3cgbXQtM1wiPlxyXG4gICAgPGRpdiBjbGFzcz1cImNvbFwiPlxyXG4gICAgICAgIDxkaXYgY2xhc3M9XCJtLTNcIj5cclxuICAgICAgICAgICAgPGxpYi10YWItbmF2aWdhdGlvbiBbbWVudUl0ZW1zXT0nbWVudUl0ZW1zJz48L2xpYi10YWItbmF2aWdhdGlvbj5cclxuICAgICAgICA8L2Rpdj5cclxuICAgIDwvZGl2PlxyXG48L2Rpdj5cclxuXHJcbjxkaXYgaWQ9XCJyb3dDYW52YXNcIj5cclxuICAgIDxkaXYgI2NhbnZhc0RpdiBpZD1cImNhbnZhc0RpdlwiPlxyXG5cclxuICAgICAgICA8ZGl2IGlkPVwidmlld2VyLWZyYW1lXCIgW3N0eWxlLnBvaW50ZXItZXZlbnRzXT1cInpvb21DYW5CZUNoYW5nZWQ/J2F1dG8nOidub25lJ1wiPlxyXG4gICAgICAgICAgICA8IS0tIDxkaXYgY2xhc3M9XCJibHVyXCI+PC9kaXY+IC0tPlxyXG4gICAgICAgIDwvZGl2PlxyXG4gICAgICAgIDxjYW52YXMgaWQ9XCJjYW52YXNcIiBbbmdTdHlsZV09XCJ7J29wYWNpdHknOiAocHJldmlld3x8bG9hZGluZykgPyAnMScgOiAnY2FsYygnICsgb3BhY2l0eSArICcvIDEwMCknfVwiPjwvY2FudmFzPlxyXG4gICAgPC9kaXY+XHJcblxyXG4gICAgPGRpdiBjbGFzcz1cImNhbGlicmF0aW9uLXRvb2xzIGNvbnRhaW5lci1mbHVpZFwiICpuZ0lmPVwiIShwcmV2aWV3IHx8IGxvYWRpbmcpXCI+XHJcbiAgICAgICAgPGgxPnt7J0NhbGlicmF0aW9uIHRvb2wnIHwgdHJhbnNsYXRlfX08L2gxPlxyXG4gICAgICAgIDxkaXYgY2xhc3M9XCJ0b29sXCI+XHJcbiAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJyb3cgbXMtMCBtZS0wIGxlZ2VuZFwiPlxyXG4gICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImxlZ2VuZC1iYXItaW5kaWNhdG9yXCIgW25nU3R5bGVdPVwieydvcGFjaXR5JzogJ2NhbGMoJyArICgtKG9wYWNpdHktMTAwKSsxMCkgKyAnLyAxMDApJ31cIj5cclxuICAgICAgICAgICAgICAgICAgICB7eydMZXNzJyB8IHRyYW5zbGF0ZX19PC9kaXY+XHJcbiAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwibGVnZW5kLXRpdGxlXCI+e3snUGxhbiBPcGFjaXR5JyB8IHRyYW5zbGF0ZSB9fTwvZGl2PlxyXG4gICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImxlZ2VuZC1iYXItaW5kaWNhdG9yXCIgW25nU3R5bGVdPVwieydvcGFjaXR5JzogJ2NhbGMoJyArIChvcGFjaXR5KzEwKSArICcvIDEwMCknfVwiPnt7J01vcmUnIHxcclxuICAgICAgICAgICAgICAgICAgICB0cmFuc2xhdGV9fTwvZGl2PlxyXG4gICAgICAgICAgICA8L2Rpdj5cclxuICAgICAgICAgICAgPGRpdiBjbGFzcz1cInJvdyBtcy0wIG1lLTAgXCI+XHJcbiAgICAgICAgICAgICAgICA8aW5wdXQgW2Rpc2FibGVkXT1cImZhbHNlXCIgW25nTW9kZWxPcHRpb25zXT1cIntzdGFuZGFsb25lOiB0cnVlfVwiIFsobmdNb2RlbCldPVwib3BhY2l0eVwiIHR5cGU9XCJyYW5nZVwiXHJcbiAgICAgICAgICAgICAgICAgICAgY2xhc3M9XCJmb3JtLXJhbmdlXCIgbWluPVwiMFwiIG1heD1cIjEwMFwiIHZhbHVlPVwiNTBcIiBpZD1cIm9wYWNpdHlcIj5cclxuICAgICAgICAgICAgPC9kaXY+XHJcbiAgICAgICAgPC9kaXY+XHJcbiAgICAgICAgPGRpdiBjbGFzcz1cInRvb2xcIj5cclxuICAgICAgICAgICAgPGRpdiBjbGFzcz1cInJvdyBtcy0wIG1lLTAgXCI+XHJcbiAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwibGFiZWwtbGVnZW5kXCI+e3snQ2hhbmdlIFZpc2l0IEZsb29yJyB8IHRyYW5zbGF0ZX19PC9kaXY+XHJcbiAgICAgICAgICAgICAgICA8ZGl2IG5nYkRyb3Bkb3duIGNsYXNzPVwiZC1pbmxpbmUtYmxvY2sgbXMtM1wiPlxyXG4gICAgICAgICAgICAgICAgICAgIDxidXR0b24gY2xhc3M9XCJidG4gYnRuLWxhYmVsLWZpbGUgcm91bmRlZC1waWxsXCIgaWQ9XCJkcm9wZG93bkJhc2ljMVwiIG5nYkRyb3Bkb3duVG9nZ2xlPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICB7e2N1cnJlbnRGbG9vciA/IGN1cnJlbnRGbG9vci5pZCA6ICgnRmxvb3InIHwgdHJhbnNsYXRlKSB9fTwvYnV0dG9uPlxyXG4gICAgICAgICAgICAgICAgICAgIDxkaXYgbmdiRHJvcGRvd25NZW51IGFyaWEtbGFiZWxsZWRieT1cImRyb3Bkb3duQmFzaWMxXCI+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIDxidXR0b24gbmdiRHJvcGRvd25JdGVtICpuZ0Zvcj1cImxldCBmbG9vciBvZiBmbG9vcnNcIiAoY2xpY2spPVwib25GbG9vckNsaWNrKGZsb29yKVwiPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAge3sgZmxvb3IubmFtZS5sZW5ndGggPiAwID8gZmxvb3IubmFtZSA6ICgnRmxvb3IgJyArIGZsb29yLmlkKSB9fVxyXG4gICAgICAgICAgICAgICAgICAgICAgICA8L2J1dHRvbj5cclxuICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cclxuICAgICAgICAgICAgICAgIDwvZGl2PlxyXG4gICAgICAgICAgICA8L2Rpdj5cclxuXHJcbiAgICAgICAgPC9kaXY+XHJcbiAgICAgICAgPGRpdiBjbGFzcz1cInRvb2xcIj5cclxuICAgICAgICAgICAgPGRpdiBjbGFzcz1cInJvdyBtcy0wIG1lLTAgXCI+XHJcbiAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwidG9vbC1jaGVja2JveC1jb250YWluZXJcIj5cclxuICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwidG9vbC1jaGVja2JveC1zdWJjb250YWluZXJcIj5cclxuICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImxhYmVsLWxlZ2VuZCBtZS0zXCI+e3snUGFuL1pvb20gVmlzaXQnIHwgdHJhbnNsYXRlfX0ge3t6b29tQ2FuQmVDaGFuZ2VkID8gXCJPTlwiIDpcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwiT0ZGXCJ9fVxyXG4gICAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cclxuICAgICAgICAgICAgICAgICAgICAgICAgPGlucHV0IHR5cGU9XCJjaGVja2JveFwiIChjaGFuZ2UpPVwib25BY3RpdmF0ZVpvb21DaGFuZ2UoKVwiIHN0eWxlPVwibWFyZ2luLXRvcDogNXB4O1wiPlxyXG4gICAgICAgICAgICAgICAgICAgIDwvZGl2PlxyXG4gICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJjYXJkIGJvcmRlci13YXJuaW5nIG1iLTMgbXQtM1wiICpuZ0lmPVwiem9vbUNhbkJlQ2hhbmdlZFwiPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwiY2FyZC1ib2R5IHRleHQtd2FybmluZ1wiPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPGg1IGNsYXNzPVwiY2FyZC10aXRsZVwiPnt7XCJjYWxpYnJhdGlvbi53YWl0LW1lc3NhZ2VcIiB8IHRyYW5zbGF0ZX19PC9oNT5cclxuICAgICAgICAgICAgICAgICAgICAgICAgPC9kaXY+XHJcbiAgICAgICAgICAgICAgICAgICAgPC9kaXY+XHJcbiAgICAgICAgICAgICAgICA8L2Rpdj5cclxuICAgICAgICAgICAgPC9kaXY+XHJcbiAgICAgICAgPC9kaXY+XHJcblxyXG4gICAgICAgIDxkaXYgY2xhc3M9XCJhY3Rpb25cIj5cclxuICAgICAgICAgICAgPGJ1dHRvbiB0eXBlPVwiYnV0dG9uXCIgY2xhc3M9XCJidG4gYnRuLW91dGxpbmUtcHJpbWFyeSByb3VuZGVkLXBpbGxcIiAoY2xpY2spPVwib25QcmV2aWV3KClcIlxyXG4gICAgICAgICAgICAgICAgW2Rpc2FibGVkXT1cInpvb21DYW5CZUNoYW5nZWRcIj57eydQcmV2aWV3JyB8IHRyYW5zbGF0ZX19PC9idXR0b24+XHJcbiAgICAgICAgICAgIDxidXR0b24gdHlwZT1cImJ1dHRvblwiIGNsYXNzPVwiYnRuIGJ0bi1vdXRsaW5lLXByaW1hcnkgcm91bmRlZC1waWxsXCIgKGNsaWNrKT1cIm9uQ2FuY2VsKClcIj57eydDYW5jZWwnIHxcclxuICAgICAgICAgICAgICAgIHRyYW5zbGF0ZX19PC9idXR0b24+XHJcblxyXG4gICAgICAgIDwvZGl2PlxyXG5cclxuICAgIDwvZGl2PlxyXG4gICAgPGRpdiBjbGFzcz1cImNhbGlicmF0aW9uLXRvb2xzIGNvbnRhaW5lci1mbHVpZFwiICpuZ0lmPVwicHJldmlld1wiPlxyXG4gICAgICAgIDxoMT57eydWYWxpZGF0aW9uJyB8IHRyYW5zbGF0ZX19PC9oMT5cclxuICAgICAgICA8ZGl2IGNsYXNzPVwiYWN0aW9uXCI+XHJcbiAgICAgICAgICAgIDxidXR0b24gdHlwZT1cImJ1dHRvblwiIGNsYXNzPVwiYnRuIGJ0bi1vdXRsaW5lLXByaW1hcnkgcm91bmRlZC1waWxsXCIgKGNsaWNrKT1cIm9uU2F2ZSgpXCI+e3snVmFsaWRhdGUnIHxcclxuICAgICAgICAgICAgICAgIHRyYW5zbGF0ZX19PC9idXR0b24+XHJcbiAgICAgICAgICAgIDxidXR0b24gdHlwZT1cImJ1dHRvblwiIGNsYXNzPVwiYnRuIGJ0bi1vdXRsaW5lLXByaW1hcnkgcm91bmRlZC1waWxsXCIgKGNsaWNrKT1cIm9uUmVzZXQoKVwiPnt7J1Jlc2V0JyB8XHJcbiAgICAgICAgICAgICAgICB0cmFuc2xhdGV9fTwvYnV0dG9uPlxyXG4gICAgICAgICAgICA8YnV0dG9uIHR5cGU9XCJidXR0b25cIiBjbGFzcz1cImJ0biBidG4tb3V0bGluZS1wcmltYXJ5IHJvdW5kZWQtcGlsbFwiIChjbGljayk9XCJvbkNhbmNlbCgpXCI+e3snQ2FuY2VsJyB8XHJcbiAgICAgICAgICAgICAgICB0cmFuc2xhdGV9fTwvYnV0dG9uPlxyXG5cclxuICAgICAgICA8L2Rpdj5cclxuICAgIDwvZGl2PlxyXG5cclxuXHJcbiAgICA8ZGl2IGNsYXNzPVwiY2FsaWJyYXRpb24tdG9vbHMgY29udGFpbmVyLWZsdWlkXCIgKm5nSWY9XCJsb2FkaW5nXCI+XHJcbiAgICAgICAgPGgzPnt7XCJXYWl0aW5nIGZvciBNYXR0ZXJwb3J0XCIgfCB0cmFuc2xhdGV9fS4uLjwvaDM+XHJcbiAgICAgICAgPGRpdiBjbGFzcz1cImQtZmxleCBqdXN0aWZ5LWNvbnRlbnQtY2VudGVyXCI+XHJcbiAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJzcGlubmVyLWJvcmRlclwiIHJvbGU9XCJzdGF0dXNcIj5cclxuICAgICAgICAgICAgICAgIDxzcGFuIGNsYXNzPVwidmlzdWFsbHktaGlkZGVuXCI+TG9hZGluZy4uLjwvc3Bhbj5cclxuICAgICAgICAgICAgPC9kaXY+XHJcbiAgICAgICAgPC9kaXY+XHJcblxyXG4gICAgPC9kaXY+XHJcbjwvZGl2PiJdfQ==
|
|
1
|
+
import { Component, ViewChild } from '@angular/core';
|
|
2
|
+
import { getDocument } from 'pdfjs-dist';
|
|
3
|
+
import { getMetaForImage, } from '@smarterplan/ngx-smarterplan-core';
|
|
4
|
+
import panzoom from 'panzoom';
|
|
5
|
+
import * as i0 from "@angular/core";
|
|
6
|
+
import * as i1 from "@smarterplan/ngx-smarterplan-core";
|
|
7
|
+
import * as i2 from "@angular/router";
|
|
8
|
+
import * as i3 from "@ngx-translate/core";
|
|
9
|
+
import * as i4 from "../../tab-navigation/tab-navigation.component";
|
|
10
|
+
import * as i5 from "@angular/common";
|
|
11
|
+
import * as i6 from "@angular/forms";
|
|
12
|
+
import * as i7 from "@ng-bootstrap/ng-bootstrap";
|
|
13
|
+
export class CalibrationComponent {
|
|
14
|
+
constructor(matterportImportService, planService, route, router, zoneService, spaceService, navigationService, translate) {
|
|
15
|
+
this.matterportImportService = matterportImportService;
|
|
16
|
+
this.planService = planService;
|
|
17
|
+
this.route = route;
|
|
18
|
+
this.router = router;
|
|
19
|
+
this.zoneService = zoneService;
|
|
20
|
+
this.spaceService = spaceService;
|
|
21
|
+
this.navigationService = navigationService;
|
|
22
|
+
this.translate = translate;
|
|
23
|
+
/** Item to display for the navbar */
|
|
24
|
+
this.menuItems = [];
|
|
25
|
+
/** Zoom ratio of the canvas/plan */
|
|
26
|
+
this.canvasZoom = 0;
|
|
27
|
+
/** Opacity for matterport iframe */
|
|
28
|
+
this.opacity = 50;
|
|
29
|
+
/** Current rotation for matterport, [0-360], matterport rotation is bind to input range */
|
|
30
|
+
this.rotation = 180;
|
|
31
|
+
/** Previous rotation, use to calculate the deltaRotation to rotate, when user change rotation value using range input */
|
|
32
|
+
this.prevRotation = 180;
|
|
33
|
+
/** True when the user is currently rotating with the input range, the matterport rotation events will be ignored */
|
|
34
|
+
this.isRotatingRange = false;
|
|
35
|
+
/** Rotating queue event to send to matterport */
|
|
36
|
+
this.rotatingQueueEvent = [];
|
|
37
|
+
/** True when Vertical symmetry is enabled */
|
|
38
|
+
this.reflectV = false;
|
|
39
|
+
/** True when Horizontal symmetry is enabled */
|
|
40
|
+
this.reflectH = false;
|
|
41
|
+
this.chosenPlanIsPdf = false;
|
|
42
|
+
/** First Point in visit, used to determine the calibration */
|
|
43
|
+
this.firstMarkVisit = { x: 0, y: 0 };
|
|
44
|
+
/** Second Point in visit, used to determine the calibration */
|
|
45
|
+
this.secondMarkVisit = { x: 0.5, y: 0.5 };
|
|
46
|
+
/** Equivalent of 'firstMarkVisit' in canvas */
|
|
47
|
+
this.firstMarkPlan = { x: 0, y: 0 };
|
|
48
|
+
/** Equivalent of 'secondMarkVisit' in canvas */
|
|
49
|
+
this.secondMarkPlan = { x: 0, y: 0 };
|
|
50
|
+
/** Calibration result, (offsetX, offsetY, x, y) */
|
|
51
|
+
this.calibrage = {};
|
|
52
|
+
/** Is in preview mode (see scan result) */
|
|
53
|
+
this.preview = false;
|
|
54
|
+
/** Matterport is loading */
|
|
55
|
+
this.loading = true;
|
|
56
|
+
this.positions = [];
|
|
57
|
+
this.floors = [];
|
|
58
|
+
this.zoomCanBeChanged = false;
|
|
59
|
+
}
|
|
60
|
+
ngOnDestroy() {
|
|
61
|
+
if (!this.loading) {
|
|
62
|
+
this.matterportImportService.removeFrame();
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
async ngOnInit() {
|
|
66
|
+
this.spaceID = this.route.snapshot.queryParams.spaceID;
|
|
67
|
+
this.currentSpace = await this.spaceService.getSpace(this.spaceID);
|
|
68
|
+
/** Menu nav bar */
|
|
69
|
+
this.setupMenuItems();
|
|
70
|
+
this.chosenPlan = this.planService.getChosenPlan();
|
|
71
|
+
if (this.chosenPlan) {
|
|
72
|
+
this.chosenPlanIsPdf = this.chosenPlan.annexe.includes('pdf');
|
|
73
|
+
this.launchViewer();
|
|
74
|
+
setTimeout(() => {
|
|
75
|
+
this.configureCanvas().then(() => {
|
|
76
|
+
this.panzoom = panzoom(this.canvas, {
|
|
77
|
+
bounds: true,
|
|
78
|
+
boundsPadding: 0,
|
|
79
|
+
maxZoom: 2.5,
|
|
80
|
+
minZoom: 0.1,
|
|
81
|
+
initialZoom: 1,
|
|
82
|
+
zoomSpeed: 0.02,
|
|
83
|
+
});
|
|
84
|
+
});
|
|
85
|
+
}, 500);
|
|
86
|
+
}
|
|
87
|
+
else {
|
|
88
|
+
this.router.navigate(['/dashboard/localisation', this.spaceID, 'plans']);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
/** **********************************************************************************************
|
|
92
|
+
* MENU NAV BAR
|
|
93
|
+
*********************************************************************************************** */
|
|
94
|
+
setupMenuItems() {
|
|
95
|
+
this.menuItems = [
|
|
96
|
+
{ label: 'Locations', url: '/localisation' },
|
|
97
|
+
{
|
|
98
|
+
label: this.currentSpace.name,
|
|
99
|
+
url: `/localisation/${this.spaceID}`,
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
label: 'Plans',
|
|
103
|
+
url: `/localisation/${this.currentSpace.id}/plans`,
|
|
104
|
+
},
|
|
105
|
+
{
|
|
106
|
+
label: 'Calibration',
|
|
107
|
+
url: `/localisation/${this.currentSpace.id}/plan-calibration?spaceID=${this.currentSpace.id}`,
|
|
108
|
+
},
|
|
109
|
+
];
|
|
110
|
+
}
|
|
111
|
+
/** **********************************************************************************************
|
|
112
|
+
* CANVAS
|
|
113
|
+
*********************************************************************************************** */
|
|
114
|
+
/** Display the plan */
|
|
115
|
+
async configureCanvas() {
|
|
116
|
+
/** Get canvas */
|
|
117
|
+
if (!this.canvas) {
|
|
118
|
+
const canvas = document.querySelector('#canvas');
|
|
119
|
+
this.canvas = canvas;
|
|
120
|
+
}
|
|
121
|
+
if (!this.chosenPlanIsPdf) {
|
|
122
|
+
const image = await getMetaForImage(this.chosenPlan.filepath);
|
|
123
|
+
/** Compute the new size for the canvas/matterport, base on the dimension of the plan, keeping the ratio */
|
|
124
|
+
const size = this.getSizeForCanvas(image.width, image.height);
|
|
125
|
+
/** Compute the plan zoom ratio (use for the calibration later) */
|
|
126
|
+
this.canvasZoom = size.w / image.width;
|
|
127
|
+
this.resizeView(size);
|
|
128
|
+
/** Draw Plan on the canvas */
|
|
129
|
+
this.drawImage(this.chosenPlan.filepath);
|
|
130
|
+
}
|
|
131
|
+
else {
|
|
132
|
+
// TODO
|
|
133
|
+
this.pdfToCanvas();
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
/** Update size of the canvas/matterport */
|
|
137
|
+
resizeView(size) {
|
|
138
|
+
this.canvasDiv.nativeElement.style.width = `${size.w}px`;
|
|
139
|
+
this.canvasDiv.nativeElement.style.height = `${size.h}px`;
|
|
140
|
+
this.canvas.style.width = `${size.w}px`;
|
|
141
|
+
this.canvas.style.height = `${size.h}px`;
|
|
142
|
+
this.canvas.width = size.w;
|
|
143
|
+
this.canvas.height = size.h;
|
|
144
|
+
this.canvasSize = size;
|
|
145
|
+
}
|
|
146
|
+
/** Draw something on the canvas */
|
|
147
|
+
drawImage(url, x = 0, y = 0, icone = false) {
|
|
148
|
+
const image = new Image();
|
|
149
|
+
const size = this.canvasSize;
|
|
150
|
+
const context = this.canvas.getContext('2d');
|
|
151
|
+
/** Flip the context, for symmetry */
|
|
152
|
+
// if (this.reflectV) {
|
|
153
|
+
// context.translate(size.w, 0);
|
|
154
|
+
// context.scale(-1, 1);
|
|
155
|
+
// }
|
|
156
|
+
// if (this.reflectH) {
|
|
157
|
+
// context.translate(0, size.h);
|
|
158
|
+
// context.scale(1, -1);
|
|
159
|
+
// }
|
|
160
|
+
let imageWidth = size.w;
|
|
161
|
+
let imageHeight = size.h;
|
|
162
|
+
image.addEventListener('load', () => {
|
|
163
|
+
if (icone) {
|
|
164
|
+
imageWidth = image.width;
|
|
165
|
+
imageHeight = image.height;
|
|
166
|
+
}
|
|
167
|
+
context.drawImage(image, 0, 0, image.width, image.height, x, y, imageWidth, imageHeight);
|
|
168
|
+
});
|
|
169
|
+
image.src = url;
|
|
170
|
+
}
|
|
171
|
+
/** Get the size for the canvas, based on the plan size, keeping the ratio */
|
|
172
|
+
getSizeForCanvas(w, h) {
|
|
173
|
+
let canvasW = this.canvasDiv.nativeElement.offsetWidth;
|
|
174
|
+
let canvasH = this.canvasDiv.nativeElement.offsetHeight;
|
|
175
|
+
const imageRatio = w / h;
|
|
176
|
+
const canvasRatio = canvasW / canvasH;
|
|
177
|
+
if (imageRatio > canvasRatio) {
|
|
178
|
+
canvasH = canvasW / imageRatio;
|
|
179
|
+
}
|
|
180
|
+
else {
|
|
181
|
+
canvasW = canvasH * imageRatio;
|
|
182
|
+
}
|
|
183
|
+
return { w: canvasW, h: canvasH };
|
|
184
|
+
}
|
|
185
|
+
/** [TODO] Convert a PDF to a Canvas */
|
|
186
|
+
async pdfToCanvas() {
|
|
187
|
+
const pdfjs = await import('pdfjs-dist/build/pdf');
|
|
188
|
+
const pdfjsWorker = await import('pdfjs-dist/build/pdf.worker.entry');
|
|
189
|
+
pdfjs.GlobalWorkerOptions.workerSrc = pdfjsWorker;
|
|
190
|
+
const pdf = await getDocument(this.chosenPlan.filepath)
|
|
191
|
+
.promise;
|
|
192
|
+
const page = await pdf.getPage(1);
|
|
193
|
+
const viewPortParameters = { scale: 1 };
|
|
194
|
+
const viewport = page.getViewport(viewPortParameters);
|
|
195
|
+
this.canvas.height = viewport.height;
|
|
196
|
+
this.canvas.width = viewport.width;
|
|
197
|
+
const size = this.getSizeForCanvas(viewport.width, viewport.height);
|
|
198
|
+
console.log(size);
|
|
199
|
+
this.canvasSize = size;
|
|
200
|
+
this.canvasZoom = size.w / viewport.width;
|
|
201
|
+
const context = this.canvas.getContext('2d');
|
|
202
|
+
const renderContext = {
|
|
203
|
+
canvasContext: context,
|
|
204
|
+
viewport,
|
|
205
|
+
};
|
|
206
|
+
const renderTask = page.render(renderContext).promise;
|
|
207
|
+
renderTask.then(() => console.log('Page rendered'));
|
|
208
|
+
// const res = canvas.toDataURL();
|
|
209
|
+
// if (pdf != null) pdf.destroy();
|
|
210
|
+
// return res;
|
|
211
|
+
}
|
|
212
|
+
/** User click to user Symmetry Vertical */
|
|
213
|
+
onReflectV() {
|
|
214
|
+
this.reflectV = !this.reflectV;
|
|
215
|
+
this.configureCanvas();
|
|
216
|
+
}
|
|
217
|
+
/** User click to user Symmetry Horizontal */
|
|
218
|
+
onReflectH() {
|
|
219
|
+
this.reflectH = !this.reflectH;
|
|
220
|
+
this.configureCanvas();
|
|
221
|
+
}
|
|
222
|
+
/** **********************************************************************************************
|
|
223
|
+
* MATTERPORT
|
|
224
|
+
*********************************************************************************************** */
|
|
225
|
+
/** Launch matterport */
|
|
226
|
+
async launchViewer() {
|
|
227
|
+
await this.matterportImportService.initSdkForModel(this.chosenPlan.model3d);
|
|
228
|
+
const { sdk } = this.matterportImportService;
|
|
229
|
+
this.floors = Object.values(this.matterportImportService.floors);
|
|
230
|
+
// console.log(this.floors);
|
|
231
|
+
setTimeout(async () => {
|
|
232
|
+
/** Move Floor mode */
|
|
233
|
+
sdk.Mode.moveTo(sdk.Mode.Mode.FLOORPLAN).then(async (nextMode) => {
|
|
234
|
+
/** Display the correct floor for the plan */
|
|
235
|
+
try {
|
|
236
|
+
const matterportFloor = this.chosenPlan.zone.metadata ?
|
|
237
|
+
JSON.parse(this.chosenPlan.zone.metadata).matterportFloorSequence : null;
|
|
238
|
+
await this.matterportImportService.moveToFloor(this.chosenPlan.zone.name, matterportFloor);
|
|
239
|
+
/** When the user try to change the view mode we set it back to floorpan */
|
|
240
|
+
sdk.on(sdk.Mode.Event.CHANGE_END, (oldMode, newMode) => {
|
|
241
|
+
if (newMode !== sdk.Mode.Mode.FLOORPLAN) {
|
|
242
|
+
sdk.Mode.moveTo(sdk.Mode.Mode.FLOORPLAN, {
|
|
243
|
+
transition: 'transition.instant',
|
|
244
|
+
});
|
|
245
|
+
}
|
|
246
|
+
});
|
|
247
|
+
}
|
|
248
|
+
catch {
|
|
249
|
+
console.log('couldnot move to floor');
|
|
250
|
+
}
|
|
251
|
+
});
|
|
252
|
+
/** We can display the matterport view now */
|
|
253
|
+
this.loading = false;
|
|
254
|
+
}, 1000);
|
|
255
|
+
/** Update current camera pose and rotation */
|
|
256
|
+
sdk.Camera.pose.subscribe((event) => {
|
|
257
|
+
/** We update only if the user is not changing the rotation with the <input> range, to not override the <input> value */
|
|
258
|
+
if (!this.isRotatingRange) {
|
|
259
|
+
this.rotation = event.rotation.y + 180;
|
|
260
|
+
this.prevRotation = this.rotation;
|
|
261
|
+
this.cameraPose = event;
|
|
262
|
+
}
|
|
263
|
+
});
|
|
264
|
+
}
|
|
265
|
+
/** When the <input> range, for rotation, change */
|
|
266
|
+
async onRotationChange() {
|
|
267
|
+
const rotationDelta = this.rotation - this.prevRotation;
|
|
268
|
+
this.prevRotation = this.rotation;
|
|
269
|
+
/** Send the rotationDelta to th queue event in order to be send to matterport */
|
|
270
|
+
this.rotatingQueueEvent.push(rotationDelta);
|
|
271
|
+
/** Start to process the queue, if it's the first event */
|
|
272
|
+
if (!this.isRotatingRange) {
|
|
273
|
+
this.isRotatingRange = true;
|
|
274
|
+
this.processRotatingQueueEvent();
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
/** Process the rotating event queue, send event one by one to matterport */
|
|
278
|
+
async processRotatingQueueEvent() {
|
|
279
|
+
const { sdk } = this.matterportImportService;
|
|
280
|
+
/** While the queue is not empty */
|
|
281
|
+
while (this.rotatingQueueEvent.length > 0) {
|
|
282
|
+
/** Rotate matterport by deltaRotation and remove event from queue */
|
|
283
|
+
await sdk.Camera.rotate(this.rotatingQueueEvent.shift(), 0, {
|
|
284
|
+
speed: 360,
|
|
285
|
+
});
|
|
286
|
+
}
|
|
287
|
+
/** When the queue is empty, then the user is not rotating with the <input> range anymore */
|
|
288
|
+
this.isRotatingRange = false;
|
|
289
|
+
}
|
|
290
|
+
/** **********************************************************************************************
|
|
291
|
+
* USER ACTIONS
|
|
292
|
+
*********************************************************************************************** */
|
|
293
|
+
/** Preview calibration */
|
|
294
|
+
async onPreview() {
|
|
295
|
+
this.preview = true;
|
|
296
|
+
/** Place sweeps */
|
|
297
|
+
this.onPlaceSweeps();
|
|
298
|
+
}
|
|
299
|
+
async calibrate() {
|
|
300
|
+
const [navigation] = this.currentNavigations;
|
|
301
|
+
const position = JSON.parse(navigation.position);
|
|
302
|
+
this.firstMarkPlan =
|
|
303
|
+
await this.matterportImportService.sdk.Renderer.getScreenPosition({
|
|
304
|
+
x: position.x,
|
|
305
|
+
y: position.y,
|
|
306
|
+
z: position.z,
|
|
307
|
+
});
|
|
308
|
+
this.secondMarkPlan =
|
|
309
|
+
await this.matterportImportService.sdk.Renderer.getScreenPosition({
|
|
310
|
+
x: position.x,
|
|
311
|
+
y: 0,
|
|
312
|
+
z: 0,
|
|
313
|
+
});
|
|
314
|
+
const deltaZVisit = 0 - position.z;
|
|
315
|
+
let deltaXPlan = this.secondMarkPlan.x - this.firstMarkPlan.x;
|
|
316
|
+
if (deltaXPlan === 0) {
|
|
317
|
+
// console.log("we moved along Y axis on Plan");
|
|
318
|
+
const deltaYPlan = this.secondMarkPlan.y - this.firstMarkPlan.y;
|
|
319
|
+
this.calibrage.nameYAxis = 'z';
|
|
320
|
+
this.calibrage.nameXAxis = 'x';
|
|
321
|
+
this.calibrage.offsetY = this.secondMarkPlan.y;
|
|
322
|
+
this.calibrage.scaleY = deltaYPlan / deltaZVisit;
|
|
323
|
+
}
|
|
324
|
+
else {
|
|
325
|
+
// console.log(" we moved along X axis on Plan");
|
|
326
|
+
this.calibrage.nameYAxis = 'x';
|
|
327
|
+
this.calibrage.nameXAxis = 'z';
|
|
328
|
+
this.calibrage.offsetX = this.secondMarkPlan.x;
|
|
329
|
+
this.calibrage.scaleX = deltaXPlan / deltaZVisit;
|
|
330
|
+
}
|
|
331
|
+
const thirdMarkPlan = await this.matterportImportService.sdk.Renderer.getScreenPosition({
|
|
332
|
+
x: 0,
|
|
333
|
+
y: 0,
|
|
334
|
+
z: position.z,
|
|
335
|
+
});
|
|
336
|
+
const deltaXVisit = 0 - position.x;
|
|
337
|
+
if (deltaXPlan === 0) {
|
|
338
|
+
// console.log(" we moved along X axis on Plan");
|
|
339
|
+
deltaXPlan = thirdMarkPlan.x - this.firstMarkPlan.x;
|
|
340
|
+
this.calibrage.offsetX = thirdMarkPlan.x;
|
|
341
|
+
this.calibrage.scaleX = deltaXPlan / deltaXVisit;
|
|
342
|
+
}
|
|
343
|
+
else {
|
|
344
|
+
const deltaYPlan = thirdMarkPlan.y - this.firstMarkPlan.y;
|
|
345
|
+
this.calibrage.offsetY = thirdMarkPlan.y;
|
|
346
|
+
this.calibrage.scaleY = deltaYPlan / deltaXVisit;
|
|
347
|
+
}
|
|
348
|
+
/** Take considiration of pan and zoom of plan on canvas */
|
|
349
|
+
const transformInfo = this.panzoom.getTransform();
|
|
350
|
+
const { scale, x, y } = transformInfo;
|
|
351
|
+
// console.log(transformInfo);
|
|
352
|
+
this.calibrage.offsetXPlan = x;
|
|
353
|
+
this.calibrage.offsetYPlan = y;
|
|
354
|
+
this.calibrage.scalePlan = scale;
|
|
355
|
+
console.log(this.calibrage);
|
|
356
|
+
}
|
|
357
|
+
/** Place sweeps */
|
|
358
|
+
async onPlaceSweeps() {
|
|
359
|
+
/** Display all scan */
|
|
360
|
+
const zone = await this.zoneService.getZone(this.chosenPlan.zoneID);
|
|
361
|
+
if (zone) {
|
|
362
|
+
this.currentZone = zone;
|
|
363
|
+
const navigations = await this.navigationService.getNavigationsForZone(this.currentZone);
|
|
364
|
+
this.currentNavigations = navigations;
|
|
365
|
+
await this.calibrate();
|
|
366
|
+
if (navigations.length > 0) {
|
|
367
|
+
for (const navigation of navigations) {
|
|
368
|
+
const testPosition = JSON.parse(navigation.position);
|
|
369
|
+
const positionX = this.calibrage.nameXAxis === 'x' ? testPosition.x : testPosition.z;
|
|
370
|
+
const positionY = this.calibrage.nameYAxis === 'x' ? testPosition.x : testPosition.z;
|
|
371
|
+
const testX = positionX * this.calibrage.scaleX + this.calibrage.offsetX;
|
|
372
|
+
const testY = positionY * this.calibrage.scaleY + this.calibrage.offsetY;
|
|
373
|
+
// console.log("test position GREEN", testX, testY);
|
|
374
|
+
const transformedX = (testX - this.calibrage.offsetXPlan) / this.calibrage.scalePlan; // we are undoing the pan and zoom
|
|
375
|
+
const transformedY = (testY - this.calibrage.offsetYPlan) / this.calibrage.scalePlan;
|
|
376
|
+
this.positions.push({
|
|
377
|
+
navID: navigation.id,
|
|
378
|
+
planID: this.chosenPlan.id,
|
|
379
|
+
x: transformedX,
|
|
380
|
+
y: transformedY,
|
|
381
|
+
});
|
|
382
|
+
const iconSize = 30 * this.calibrage.scalePlan;
|
|
383
|
+
const shift = iconSize / 2;
|
|
384
|
+
this.drawImage('https://api.iconify.design/mdi:adjust.svg?color=green&height=30&width=30', transformedX - shift, transformedY - shift, true);
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
/** Save calibration */
|
|
390
|
+
async onSave() {
|
|
391
|
+
if (this.currentZone) {
|
|
392
|
+
/** Normalize with the zoom */
|
|
393
|
+
// this.calibrage.offsetX /= this.canvasZoom;
|
|
394
|
+
// this.calibrage.offsetY /= this.canvasZoom;
|
|
395
|
+
// this.calibrage.x /= this.canvasZoom;
|
|
396
|
+
// this.calibrage.y /= this.canvasZoom;
|
|
397
|
+
this.calibrage.new = true;
|
|
398
|
+
this.calibrage.imgWidth = this.canvasSize.w;
|
|
399
|
+
this.calibrage.imgHeight = this.canvasSize.h;
|
|
400
|
+
await this.planService.updatePlan({
|
|
401
|
+
id: this.chosenPlan.id,
|
|
402
|
+
calibration: JSON.stringify(this.calibrage),
|
|
403
|
+
});
|
|
404
|
+
await Promise.all(this.positions.map(async (position) => {
|
|
405
|
+
const { navID } = position;
|
|
406
|
+
delete position.navID;
|
|
407
|
+
const nav = this.currentNavigations.find((_nav) => _nav.id === navID);
|
|
408
|
+
let positionsDataToUpdate;
|
|
409
|
+
if (nav.positionOnPlan) {
|
|
410
|
+
const positionOnPlan = nav.positionOnPlan.map((entry) => JSON.parse(entry));
|
|
411
|
+
const positionForCurrentPlan = positionOnPlan.find((entry) => entry.planID === this.chosenPlan.id);
|
|
412
|
+
if (positionForCurrentPlan) {
|
|
413
|
+
positionOnPlan.splice(positionOnPlan.indexOf(positionForCurrentPlan), 1, position);
|
|
414
|
+
}
|
|
415
|
+
else {
|
|
416
|
+
positionOnPlan.push(position);
|
|
417
|
+
}
|
|
418
|
+
positionsDataToUpdate = [...positionOnPlan];
|
|
419
|
+
}
|
|
420
|
+
else {
|
|
421
|
+
positionsDataToUpdate = [position];
|
|
422
|
+
}
|
|
423
|
+
// console.log(positionsDataToUpdate);
|
|
424
|
+
await this.navigationService.updateNavigation({
|
|
425
|
+
id: navID,
|
|
426
|
+
positionOnPlan: positionsDataToUpdate.map((entry) => JSON.stringify(entry)),
|
|
427
|
+
});
|
|
428
|
+
}));
|
|
429
|
+
}
|
|
430
|
+
this.matterportImportService.removeFrame();
|
|
431
|
+
this.router.navigate(['/dashboard/localisation', this.spaceID, 'plans']);
|
|
432
|
+
alert(this.translate.instant('calibration.success'));
|
|
433
|
+
}
|
|
434
|
+
/** Reset the canvas */
|
|
435
|
+
onReset() {
|
|
436
|
+
this.reflectH = false;
|
|
437
|
+
this.reflectV = false;
|
|
438
|
+
this.preview = false;
|
|
439
|
+
this.configureCanvas();
|
|
440
|
+
}
|
|
441
|
+
/** Cancel, leave */
|
|
442
|
+
onCancel() {
|
|
443
|
+
this.matterportImportService.removeFrame();
|
|
444
|
+
this.router.navigate(['/dashboard/localisation', this.spaceID, 'plans']);
|
|
445
|
+
alert(this.translate.instant('calibration.canceled'));
|
|
446
|
+
}
|
|
447
|
+
async onFloorClick(floor) {
|
|
448
|
+
this.currentFloor = floor;
|
|
449
|
+
await this.matterportImportService.moveToFloor(floor.id);
|
|
450
|
+
}
|
|
451
|
+
onActivateZoomChange() {
|
|
452
|
+
this.zoomCanBeChanged = !this.zoomCanBeChanged;
|
|
453
|
+
const iframe = document.querySelector('#viewer-frame');
|
|
454
|
+
if (iframe) {
|
|
455
|
+
iframe.style.zIndex = this.zoomCanBeChanged ? '1' : '0';
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
CalibrationComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.2.7", ngImport: i0, type: CalibrationComponent, deps: [{ token: i1.MatterportImportService }, { token: i1.PlanService }, { token: i2.ActivatedRoute }, { token: i2.Router }, { token: i1.ZoneService }, { token: i1.SpaceService }, { token: i1.NavigationService }, { token: i3.TranslateService }], target: i0.ɵɵFactoryTarget.Component });
|
|
460
|
+
CalibrationComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.2.7", type: CalibrationComponent, selector: "lib-calibration", viewQueries: [{ propertyName: "canvasDiv", first: true, predicate: ["canvasDiv"], descendants: true }], ngImport: i0, template: "<div class=\"row mt-3\">\n <div class=\"col\">\n <div class=\"m-3\">\n <lib-tab-navigation [menuItems]='menuItems'></lib-tab-navigation>\n </div>\n </div>\n</div>\n\n<div id=\"rowCanvas\">\n <div #canvasDiv id=\"canvasDiv\">\n\n <div id=\"viewer-frame\" [style.pointer-events]=\"zoomCanBeChanged?'auto':'none'\">\n <!-- <div class=\"blur\"></div> -->\n </div>\n <canvas id=\"canvas\" [ngStyle]=\"{'opacity': (preview||loading) ? '1' : 'calc(' + opacity + '/ 100)'}\"></canvas>\n </div>\n\n <div class=\"calibration-tools container-fluid\" *ngIf=\"!(preview || loading)\">\n <h1>{{'Calibration tool' | translate}}</h1>\n <div class=\"tool\">\n <div class=\"row ms-0 me-0 legend\">\n <div class=\"legend-bar-indicator\" [ngStyle]=\"{'opacity': 'calc(' + (-(opacity-100)+10) + '/ 100)'}\">\n {{'Less' | translate}}</div>\n <div class=\"legend-title\">{{'Plan Opacity' | translate }}</div>\n <div class=\"legend-bar-indicator\" [ngStyle]=\"{'opacity': 'calc(' + (opacity+10) + '/ 100)'}\">{{'More' |\n translate}}</div>\n </div>\n <div class=\"row ms-0 me-0 \">\n <input [disabled]=\"false\" [ngModelOptions]=\"{standalone: true}\" [(ngModel)]=\"opacity\" type=\"range\"\n class=\"form-range\" min=\"0\" max=\"100\" value=\"50\" id=\"opacity\">\n </div>\n </div>\n <div class=\"tool\">\n <div class=\"row ms-0 me-0 \">\n <div class=\"label-legend\">{{'Change Visit Floor' | translate}}</div>\n <div ngbDropdown class=\"d-inline-block ms-3\">\n <button class=\"btn btn-label-file rounded-pill\" id=\"dropdownBasic1\" ngbDropdownToggle>\n {{currentFloor ? currentFloor.id : ('Floor' | translate) }}</button>\n <div ngbDropdownMenu aria-labelledby=\"dropdownBasic1\">\n <button ngbDropdownItem *ngFor=\"let floor of floors\" (click)=\"onFloorClick(floor)\">\n {{ floor.name.length > 0 ? floor.name : ('Floor ' + floor.id) }}\n </button>\n </div>\n </div>\n </div>\n\n </div>\n <div class=\"tool\">\n <div class=\"row ms-0 me-0 \">\n <div class=\"tool-checkbox-container\">\n <div class=\"tool-checkbox-subcontainer\">\n <div class=\"label-legend me-3\">{{'Pan/Zoom Visit' | translate}} {{zoomCanBeChanged ? \"ON\" :\n \"OFF\"}}\n </div>\n <input type=\"checkbox\" (change)=\"onActivateZoomChange()\" style=\"margin-top: 5px;\">\n </div>\n <div class=\"card border-warning mb-3 mt-3\" *ngIf=\"zoomCanBeChanged\">\n <div class=\"card-body text-warning\">\n <h5 class=\"card-title\">{{\"calibration.wait-message\" | translate}}</h5>\n </div>\n </div>\n </div>\n </div>\n </div>\n\n <div class=\"action\">\n <button type=\"button\" class=\"btn btn-outline-primary rounded-pill\" (click)=\"onPreview()\"\n [disabled]=\"zoomCanBeChanged\">{{'Preview' | translate}}</button>\n <button type=\"button\" class=\"btn btn-outline-primary rounded-pill\" (click)=\"onCancel()\">{{'Cancel' |\n translate}}</button>\n\n </div>\n\n </div>\n <div class=\"calibration-tools container-fluid\" *ngIf=\"preview\">\n <h1>{{'Validation' | translate}}</h1>\n <div class=\"action\">\n <button type=\"button\" class=\"btn btn-outline-primary rounded-pill\" (click)=\"onSave()\">{{'Validate' |\n translate}}</button>\n <button type=\"button\" class=\"btn btn-outline-primary rounded-pill\" (click)=\"onReset()\">{{'Reset' |\n translate}}</button>\n <button type=\"button\" class=\"btn btn-outline-primary rounded-pill\" (click)=\"onCancel()\">{{'Cancel' |\n translate}}</button>\n\n </div>\n </div>\n\n\n <div class=\"calibration-tools container-fluid\" *ngIf=\"loading\">\n <h3>{{\"Waiting for Matterport\" | translate}}...</h3>\n <div class=\"d-flex justify-content-center\">\n <div class=\"spinner-border\" role=\"status\">\n <span class=\"visually-hidden\">Loading...</span>\n </div>\n </div>\n\n </div>\n</div>", styles: [".button-visit{display:none;height:30px;width:30px;position:absolute;background:url(https://api.iconify.design/mdi:map-marker-check.svg?color=red&height=30) no-repeat scroll 0 0 transparent;border:none}#button-visit-left{left:350px;top:550px}#button-visit-right{left:500px;top:600px}#rowCanvas{display:flex}#canvasDiv{height:100%;width:100%;position:relative}#canvas{width:100%;height:100%;opacity:.5}#viewer-frame{top:0;position:absolute;width:100%;height:100%}.calibration-tools{margin-left:20px;width:400px;background-color:#fff;z-index:11;border:1px solid var(--smarterplan-primary);padding:7px}.form-range{width:100%}.tool{margin-top:20px}.tool .legend{justify-content:space-between;position:relative;margin-bottom:5px}.tool .legend-title{font-size:1.2rem;color:var(--smarterplan-primary);margin:auto;width:100%;font-weight:700;display:flex;justify-content:center}.tool .legend-bar-indicator{width:15%!important}.tool .label-legend{color:var(--smarterplan-primary);font-size:1.1rem;max-width:55%}.tool .tool-checkbox-container{display:flex;flex-direction:column}.tool .tool-checkbox-container .tool-checkbox-subcontainer{display:flex}.blur{width:150px;height:52px;position:absolute;background-color:#1e2023;bottom:0}.symmetry{padding:5px;border:solid 2px;border-radius:10px;color:var(--smarterplan-primary);margin:25px 10px;cursor:pointer}.symmetry:hover{color:var(--smarterplan-primary)}.symmetry-row{justify-content:center}.action{margin-top:30px;display:flex;justify-content:space-evenly}h1{color:var(--smarterplan-primary);text-align:center;margin-bottom:20px}h3{color:var(--smarterplan-primary);text-align:center;margin-bottom:10px}.btn-outline-primary.disabled{background-color:var(--smarterplan-orange)!important}\n"], components: [{ type: i4.TabNavigationComponent, selector: "lib-tab-navigation", inputs: ["menuItems"], outputs: ["onGoBack"] }], directives: [{ type: i5.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { type: i5.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i6.RangeValueAccessor, selector: "input[type=range][formControlName],input[type=range][formControl],input[type=range][ngModel]" }, { type: i6.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { type: i6.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { type: i6.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { type: i7.NgbDropdown, selector: "[ngbDropdown]", inputs: ["autoClose", "dropdownClass", "open", "placement", "container", "display"], outputs: ["openChange"], exportAs: ["ngbDropdown"] }, { type: i7.NgbDropdownToggle, selector: "[ngbDropdownToggle]" }, { type: i7.NgbDropdownMenu, selector: "[ngbDropdownMenu]" }, { type: i5.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i7.NgbDropdownItem, selector: "[ngbDropdownItem]", inputs: ["disabled"] }], pipes: { "translate": i3.TranslatePipe } });
|
|
461
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.2.7", ngImport: i0, type: CalibrationComponent, decorators: [{
|
|
462
|
+
type: Component,
|
|
463
|
+
args: [{ selector: 'lib-calibration', template: "<div class=\"row mt-3\">\n <div class=\"col\">\n <div class=\"m-3\">\n <lib-tab-navigation [menuItems]='menuItems'></lib-tab-navigation>\n </div>\n </div>\n</div>\n\n<div id=\"rowCanvas\">\n <div #canvasDiv id=\"canvasDiv\">\n\n <div id=\"viewer-frame\" [style.pointer-events]=\"zoomCanBeChanged?'auto':'none'\">\n <!-- <div class=\"blur\"></div> -->\n </div>\n <canvas id=\"canvas\" [ngStyle]=\"{'opacity': (preview||loading) ? '1' : 'calc(' + opacity + '/ 100)'}\"></canvas>\n </div>\n\n <div class=\"calibration-tools container-fluid\" *ngIf=\"!(preview || loading)\">\n <h1>{{'Calibration tool' | translate}}</h1>\n <div class=\"tool\">\n <div class=\"row ms-0 me-0 legend\">\n <div class=\"legend-bar-indicator\" [ngStyle]=\"{'opacity': 'calc(' + (-(opacity-100)+10) + '/ 100)'}\">\n {{'Less' | translate}}</div>\n <div class=\"legend-title\">{{'Plan Opacity' | translate }}</div>\n <div class=\"legend-bar-indicator\" [ngStyle]=\"{'opacity': 'calc(' + (opacity+10) + '/ 100)'}\">{{'More' |\n translate}}</div>\n </div>\n <div class=\"row ms-0 me-0 \">\n <input [disabled]=\"false\" [ngModelOptions]=\"{standalone: true}\" [(ngModel)]=\"opacity\" type=\"range\"\n class=\"form-range\" min=\"0\" max=\"100\" value=\"50\" id=\"opacity\">\n </div>\n </div>\n <div class=\"tool\">\n <div class=\"row ms-0 me-0 \">\n <div class=\"label-legend\">{{'Change Visit Floor' | translate}}</div>\n <div ngbDropdown class=\"d-inline-block ms-3\">\n <button class=\"btn btn-label-file rounded-pill\" id=\"dropdownBasic1\" ngbDropdownToggle>\n {{currentFloor ? currentFloor.id : ('Floor' | translate) }}</button>\n <div ngbDropdownMenu aria-labelledby=\"dropdownBasic1\">\n <button ngbDropdownItem *ngFor=\"let floor of floors\" (click)=\"onFloorClick(floor)\">\n {{ floor.name.length > 0 ? floor.name : ('Floor ' + floor.id) }}\n </button>\n </div>\n </div>\n </div>\n\n </div>\n <div class=\"tool\">\n <div class=\"row ms-0 me-0 \">\n <div class=\"tool-checkbox-container\">\n <div class=\"tool-checkbox-subcontainer\">\n <div class=\"label-legend me-3\">{{'Pan/Zoom Visit' | translate}} {{zoomCanBeChanged ? \"ON\" :\n \"OFF\"}}\n </div>\n <input type=\"checkbox\" (change)=\"onActivateZoomChange()\" style=\"margin-top: 5px;\">\n </div>\n <div class=\"card border-warning mb-3 mt-3\" *ngIf=\"zoomCanBeChanged\">\n <div class=\"card-body text-warning\">\n <h5 class=\"card-title\">{{\"calibration.wait-message\" | translate}}</h5>\n </div>\n </div>\n </div>\n </div>\n </div>\n\n <div class=\"action\">\n <button type=\"button\" class=\"btn btn-outline-primary rounded-pill\" (click)=\"onPreview()\"\n [disabled]=\"zoomCanBeChanged\">{{'Preview' | translate}}</button>\n <button type=\"button\" class=\"btn btn-outline-primary rounded-pill\" (click)=\"onCancel()\">{{'Cancel' |\n translate}}</button>\n\n </div>\n\n </div>\n <div class=\"calibration-tools container-fluid\" *ngIf=\"preview\">\n <h1>{{'Validation' | translate}}</h1>\n <div class=\"action\">\n <button type=\"button\" class=\"btn btn-outline-primary rounded-pill\" (click)=\"onSave()\">{{'Validate' |\n translate}}</button>\n <button type=\"button\" class=\"btn btn-outline-primary rounded-pill\" (click)=\"onReset()\">{{'Reset' |\n translate}}</button>\n <button type=\"button\" class=\"btn btn-outline-primary rounded-pill\" (click)=\"onCancel()\">{{'Cancel' |\n translate}}</button>\n\n </div>\n </div>\n\n\n <div class=\"calibration-tools container-fluid\" *ngIf=\"loading\">\n <h3>{{\"Waiting for Matterport\" | translate}}...</h3>\n <div class=\"d-flex justify-content-center\">\n <div class=\"spinner-border\" role=\"status\">\n <span class=\"visually-hidden\">Loading...</span>\n </div>\n </div>\n\n </div>\n</div>", styles: [".button-visit{display:none;height:30px;width:30px;position:absolute;background:url(https://api.iconify.design/mdi:map-marker-check.svg?color=red&height=30) no-repeat scroll 0 0 transparent;border:none}#button-visit-left{left:350px;top:550px}#button-visit-right{left:500px;top:600px}#rowCanvas{display:flex}#canvasDiv{height:100%;width:100%;position:relative}#canvas{width:100%;height:100%;opacity:.5}#viewer-frame{top:0;position:absolute;width:100%;height:100%}.calibration-tools{margin-left:20px;width:400px;background-color:#fff;z-index:11;border:1px solid var(--smarterplan-primary);padding:7px}.form-range{width:100%}.tool{margin-top:20px}.tool .legend{justify-content:space-between;position:relative;margin-bottom:5px}.tool .legend-title{font-size:1.2rem;color:var(--smarterplan-primary);margin:auto;width:100%;font-weight:700;display:flex;justify-content:center}.tool .legend-bar-indicator{width:15%!important}.tool .label-legend{color:var(--smarterplan-primary);font-size:1.1rem;max-width:55%}.tool .tool-checkbox-container{display:flex;flex-direction:column}.tool .tool-checkbox-container .tool-checkbox-subcontainer{display:flex}.blur{width:150px;height:52px;position:absolute;background-color:#1e2023;bottom:0}.symmetry{padding:5px;border:solid 2px;border-radius:10px;color:var(--smarterplan-primary);margin:25px 10px;cursor:pointer}.symmetry:hover{color:var(--smarterplan-primary)}.symmetry-row{justify-content:center}.action{margin-top:30px;display:flex;justify-content:space-evenly}h1{color:var(--smarterplan-primary);text-align:center;margin-bottom:20px}h3{color:var(--smarterplan-primary);text-align:center;margin-bottom:10px}.btn-outline-primary.disabled{background-color:var(--smarterplan-orange)!important}\n"] }]
|
|
464
|
+
}], ctorParameters: function () { return [{ type: i1.MatterportImportService }, { type: i1.PlanService }, { type: i2.ActivatedRoute }, { type: i2.Router }, { type: i1.ZoneService }, { type: i1.SpaceService }, { type: i1.NavigationService }, { type: i3.TranslateService }]; }, propDecorators: { canvasDiv: [{
|
|
465
|
+
type: ViewChild,
|
|
466
|
+
args: ['canvasDiv']
|
|
467
|
+
}] } });
|
|
468
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2FsaWJyYXRpb24uY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvbmd4LXNtYXJ0ZXJwbGFuLWxvY2F0aW9ucy9zcmMvbGliL2NvbXBvbmVudHMvcGxhbnMvY2FsaWJyYXRpb24vY2FsaWJyYXRpb24uY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvbmd4LXNtYXJ0ZXJwbGFuLWxvY2F0aW9ucy9zcmMvbGliL2NvbXBvbmVudHMvcGxhbnMvY2FsaWJyYXRpb24vY2FsaWJyYXRpb24uY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFNBQVMsRUFBc0IsU0FBUyxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBR3pFLE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSxZQUFZLENBQUM7QUFFekMsT0FBTyxFQVVILGVBQWUsR0FFbEIsTUFBTSxtQ0FBbUMsQ0FBQztBQUMzQyxPQUFPLE9BQU8sTUFBTSxTQUFTLENBQUM7Ozs7Ozs7OztBQU85QixNQUFNLE9BQU8sb0JBQW9CO0lBb0Y3QixZQUNZLHVCQUFnRCxFQUNoRCxXQUF3QixFQUN4QixLQUFxQixFQUNyQixNQUFjLEVBQ2QsV0FBd0IsRUFDeEIsWUFBMEIsRUFDMUIsaUJBQW9DLEVBQ3BDLFNBQTJCO1FBUDNCLDRCQUF1QixHQUF2Qix1QkFBdUIsQ0FBeUI7UUFDaEQsZ0JBQVcsR0FBWCxXQUFXLENBQWE7UUFDeEIsVUFBSyxHQUFMLEtBQUssQ0FBZ0I7UUFDckIsV0FBTSxHQUFOLE1BQU0sQ0FBUTtRQUNkLGdCQUFXLEdBQVgsV0FBVyxDQUFhO1FBQ3hCLGlCQUFZLEdBQVosWUFBWSxDQUFjO1FBQzFCLHNCQUFpQixHQUFqQixpQkFBaUIsQ0FBbUI7UUFDcEMsY0FBUyxHQUFULFNBQVMsQ0FBa0I7UUEzRnZDLHFDQUFxQztRQUNyQyxjQUFTLEdBQWUsRUFBRSxDQUFDO1FBVzNCLHFDQUFxQztRQUNyQyxlQUFVLEdBQUcsQ0FBQyxDQUFDO1FBRWYsb0NBQW9DO1FBQ3BDLFlBQU8sR0FBVyxFQUFFLENBQUM7UUFFckIsNEZBQTRGO1FBQzVGLGFBQVEsR0FBVyxHQUFHLENBQUM7UUFFdkIseUhBQXlIO1FBQ3pILGlCQUFZLEdBQVcsR0FBRyxDQUFDO1FBSzNCLG9IQUFvSDtRQUNwSCxvQkFBZSxHQUFZLEtBQUssQ0FBQztRQUVqQyxpREFBaUQ7UUFDakQsdUJBQWtCLEdBQWEsRUFBRSxDQUFDO1FBRWxDLDZDQUE2QztRQUM3QyxhQUFRLEdBQUcsS0FBSyxDQUFDO1FBRWpCLCtDQUErQztRQUMvQyxhQUFRLEdBQUcsS0FBSyxDQUFDO1FBVWpCLG9CQUFlLEdBQUcsS0FBSyxDQUFDO1FBRXhCLCtEQUErRDtRQUMvRCxtQkFBYyxHQUFHLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUM7UUFFaEMsZ0VBQWdFO1FBQ2hFLG9CQUFlLEdBQUcsRUFBRSxDQUFDLEVBQUUsR0FBRyxFQUFFLENBQUMsRUFBRSxHQUFHLEVBQUUsQ0FBQztRQUVyQyxnREFBZ0Q7UUFDaEQsa0JBQWEsR0FBOEIsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQztRQUUxRCxpREFBaUQ7UUFDakQsbUJBQWMsR0FBOEIsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQztRQUUzRCxtREFBbUQ7UUFDbkQsY0FBUyxHQUFRLEVBQUUsQ0FBQztRQUVwQiwyQ0FBMkM7UUFDM0MsWUFBTyxHQUFHLEtBQUssQ0FBQztRQUVoQiw0QkFBNEI7UUFDNUIsWUFBTyxHQUFHLElBQUksQ0FBQztRQU9mLGNBQVMsR0FBK0QsRUFBRSxDQUFDO1FBRTNFLFdBQU0sR0FBVSxFQUFFLENBQUM7UUFJbkIscUJBQWdCLEdBQVksS0FBSyxDQUFDO0lBVzlCLENBQUM7SUFFTCxXQUFXO1FBQ1AsSUFBSSxDQUFDLElBQUksQ0FBQyxPQUFPLEVBQUU7WUFDZixJQUFJLENBQUMsdUJBQXVCLENBQUMsV0FBVyxFQUFFLENBQUM7U0FDOUM7SUFDTCxDQUFDO0lBRUQsS0FBSyxDQUFDLFFBQVE7UUFDVixJQUFJLENBQUMsT0FBTyxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsUUFBUSxDQUFDLFdBQVcsQ0FBQyxPQUFPLENBQUM7UUFDdkQsSUFBSSxDQUFDLFlBQVksR0FBRyxNQUFNLElBQUksQ0FBQyxZQUFZLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUVuRSxtQkFBbUI7UUFDbkIsSUFBSSxDQUFDLGNBQWMsRUFBRSxDQUFDO1FBRXRCLElBQUksQ0FBQyxVQUFVLEdBQUcsSUFBSSxDQUFDLFdBQVcsQ0FBQyxhQUFhLEVBQUUsQ0FBQztRQUVuRCxJQUFJLElBQUksQ0FBQyxVQUFVLEVBQUU7WUFDakIsSUFBSSxDQUFDLGVBQWUsR0FBRyxJQUFJLENBQUMsVUFBVSxDQUFDLE1BQU0sQ0FBQyxRQUFRLENBQUMsS0FBSyxDQUFDLENBQUM7WUFDOUQsSUFBSSxDQUFDLFlBQVksRUFBRSxDQUFDO1lBQ3BCLFVBQVUsQ0FBQyxHQUFHLEVBQUU7Z0JBQ1osSUFBSSxDQUFDLGVBQWUsRUFBRSxDQUFDLElBQUksQ0FBQyxHQUFHLEVBQUU7b0JBQzdCLElBQUksQ0FBQyxPQUFPLEdBQUcsT0FBTyxDQUFDLElBQUksQ0FBQyxNQUFNLEVBQUU7d0JBQ2hDLE1BQU0sRUFBRSxJQUFJO3dCQUNaLGFBQWEsRUFBRSxDQUFDO3dCQUNoQixPQUFPLEVBQUUsR0FBRzt3QkFDWixPQUFPLEVBQUUsR0FBRzt3QkFDWixXQUFXLEVBQUUsQ0FBQzt3QkFDZCxTQUFTLEVBQUUsSUFBSTtxQkFDbEIsQ0FBQyxDQUFDO2dCQUNQLENBQUMsQ0FBQyxDQUFDO1lBQ1AsQ0FBQyxFQUFFLEdBQUcsQ0FBQyxDQUFDO1NBQ1g7YUFBTTtZQUNILElBQUksQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDLENBQUMseUJBQXlCLEVBQUUsSUFBSSxDQUFDLE9BQU8sRUFBRSxPQUFPLENBQUMsQ0FBQyxDQUFDO1NBQzVFO0lBQ0wsQ0FBQztJQUVEOzt1R0FFbUc7SUFDbkcsY0FBYztRQUNWLElBQUksQ0FBQyxTQUFTLEdBQUc7WUFDYixFQUFFLEtBQUssRUFBRSxXQUFXLEVBQUUsR0FBRyxFQUFFLGVBQWUsRUFBRTtZQUM1QztnQkFDSSxLQUFLLEVBQUUsSUFBSSxDQUFDLFlBQVksQ0FBQyxJQUFJO2dCQUM3QixHQUFHLEVBQUUsaUJBQWlCLElBQUksQ0FBQyxPQUFPLEVBQUU7YUFDdkM7WUFDRDtnQkFDSSxLQUFLLEVBQUUsT0FBTztnQkFDZCxHQUFHLEVBQUUsaUJBQWlCLElBQUksQ0FBQyxZQUFZLENBQUMsRUFBRSxRQUFRO2FBQ3JEO1lBQ0Q7Z0JBQ0ksS0FBSyxFQUFFLGFBQWE7Z0JBQ3BCLEdBQUcsRUFBRSxpQkFBaUIsSUFBSSxDQUFDLFlBQVksQ0FBQyxFQUFFLDZCQUE2QixJQUFJLENBQUMsWUFBWSxDQUFDLEVBQUUsRUFBRTthQUNoRztTQUNKLENBQUM7SUFDTixDQUFDO0lBRUQ7O3VHQUVtRztJQUVuRyx1QkFBdUI7SUFDdkIsS0FBSyxDQUFDLGVBQWU7UUFDakIsaUJBQWlCO1FBQ2pCLElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxFQUFFO1lBQ2QsTUFBTSxNQUFNLEdBQUcsUUFBUSxDQUFDLGFBQWEsQ0FBQyxTQUFTLENBQXNCLENBQUM7WUFDdEUsSUFBSSxDQUFDLE1BQU0sR0FBRyxNQUFNLENBQUM7U0FDeEI7UUFFRCxJQUFJLENBQUMsSUFBSSxDQUFDLGVBQWUsRUFBRTtZQUN2QixNQUFNLEtBQUssR0FBRyxNQUFNLGVBQWUsQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLFFBQVEsQ0FBQyxDQUFDO1lBQzlELDJHQUEyRztZQUMzRyxNQUFNLElBQUksR0FBRyxJQUFJLENBQUMsZ0JBQWdCLENBQUMsS0FBSyxDQUFDLEtBQUssRUFBRSxLQUFLLENBQUMsTUFBTSxDQUFDLENBQUM7WUFFOUQsa0VBQWtFO1lBQ2xFLElBQUksQ0FBQyxVQUFVLEdBQUcsSUFBSSxDQUFDLENBQUMsR0FBRyxLQUFLLENBQUMsS0FBSyxDQUFDO1lBRXZDLElBQUksQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLENBQUM7WUFFdEIsOEJBQThCO1lBQzlCLElBQUksQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxRQUFRLENBQUMsQ0FBQztTQUM1QzthQUFNO1lBQ0gsT0FBTztZQUNQLElBQUksQ0FBQyxXQUFXLEVBQUUsQ0FBQztTQUN0QjtJQUNMLENBQUM7SUFFRCwyQ0FBMkM7SUFDM0MsVUFBVSxDQUFDLElBQUk7UUFDWCxJQUFJLENBQUMsU0FBUyxDQUFDLGFBQWEsQ0FBQyxLQUFLLENBQUMsS0FBSyxHQUFHLEdBQUcsSUFBSSxDQUFDLENBQUMsSUFBSSxDQUFDO1FBQ3pELElBQUksQ0FBQyxTQUFTLENBQUMsYUFBYSxDQUFDLEtBQUssQ0FBQyxNQUFNLEdBQUcsR0FBRyxJQUFJLENBQUMsQ0FBQyxJQUFJLENBQUM7UUFDMUQsSUFBSSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsS0FBSyxHQUFHLEdBQUcsSUFBSSxDQUFDLENBQUMsSUFBSSxDQUFDO1FBQ3hDLElBQUksQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLE1BQU0sR0FBRyxHQUFHLElBQUksQ0FBQyxDQUFDLElBQUksQ0FBQztRQUN6QyxJQUFJLENBQUMsTUFBTSxDQUFDLEtBQUssR0FBRyxJQUFJLENBQUMsQ0FBQyxDQUFDO1FBQzNCLElBQUksQ0FBQyxNQUFNLENBQUMsTUFBTSxHQUFHLElBQUksQ0FBQyxDQUFDLENBQUM7UUFDNUIsSUFBSSxDQUFDLFVBQVUsR0FBRyxJQUFJLENBQUM7SUFDM0IsQ0FBQztJQUVELG1DQUFtQztJQUNuQyxTQUFTLENBQUMsR0FBVyxFQUFFLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLENBQUMsRUFBRSxLQUFLLEdBQUcsS0FBSztRQUM5QyxNQUFNLEtBQUssR0FBRyxJQUFJLEtBQUssRUFBRSxDQUFDO1FBQzFCLE1BQU0sSUFBSSxHQUFHLElBQUksQ0FBQyxVQUFVLENBQUM7UUFDN0IsTUFBTSxPQUFPLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLENBQUM7UUFFN0MscUNBQXFDO1FBQ3JDLHVCQUF1QjtRQUN2QixvQ0FBb0M7UUFDcEMsNEJBQTRCO1FBQzVCLElBQUk7UUFDSix1QkFBdUI7UUFDdkIsb0NBQW9DO1FBQ3BDLDRCQUE0QjtRQUM1QixJQUFJO1FBRUosSUFBSSxVQUFVLEdBQUcsSUFBSSxDQUFDLENBQUMsQ0FBQztRQUN4QixJQUFJLFdBQVcsR0FBRyxJQUFJLENBQUMsQ0FBQyxDQUFDO1FBQ3pCLEtBQUssQ0FBQyxnQkFBZ0IsQ0FBQyxNQUFNLEVBQUUsR0FBRyxFQUFFO1lBQ2hDLElBQUksS0FBSyxFQUFFO2dCQUNQLFVBQVUsR0FBRyxLQUFLLENBQUMsS0FBSyxDQUFDO2dCQUN6QixXQUFXLEdBQUcsS0FBSyxDQUFDLE1BQU0sQ0FBQzthQUM5QjtZQUNELE9BQU8sQ0FBQyxTQUFTLENBQ2IsS0FBSyxFQUNMLENBQUMsRUFDRCxDQUFDLEVBQ0QsS0FBSyxDQUFDLEtBQUssRUFDWCxLQUFLLENBQUMsTUFBTSxFQUNaLENBQUMsRUFDRCxDQUFDLEVBQ0QsVUFBVSxFQUNWLFdBQVcsQ0FDZCxDQUFDO1FBQ04sQ0FBQyxDQUFDLENBQUM7UUFDSCxLQUFLLENBQUMsR0FBRyxHQUFHLEdBQUcsQ0FBQztJQUNwQixDQUFDO0lBRUQsNkVBQTZFO0lBQzdFLGdCQUFnQixDQUFDLENBQUMsRUFBRSxDQUFDO1FBQ2pCLElBQUksT0FBTyxHQUFHLElBQUksQ0FBQyxTQUFTLENBQUMsYUFBYSxDQUFDLFdBQVcsQ0FBQztRQUN2RCxJQUFJLE9BQU8sR0FBRyxJQUFJLENBQUMsU0FBUyxDQUFDLGFBQWEsQ0FBQyxZQUFZLENBQUM7UUFFeEQsTUFBTSxVQUFVLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQztRQUN6QixNQUFNLFdBQVcsR0FBRyxPQUFPLEdBQUcsT0FBTyxDQUFDO1FBRXRDLElBQUksVUFBVSxHQUFHLFdBQVcsRUFBRTtZQUMxQixPQUFPLEdBQUcsT0FBTyxHQUFHLFVBQVUsQ0FBQztTQUNsQzthQUFNO1lBQ0gsT0FBTyxHQUFHLE9BQU8sR0FBRyxVQUFVLENBQUM7U0FDbEM7UUFDRCxPQUFPLEVBQUUsQ0FBQyxFQUFFLE9BQU8sRUFBRSxDQUFDLEVBQUUsT0FBTyxFQUFFLENBQUM7SUFDdEMsQ0FBQztJQUVELHVDQUF1QztJQUN2QyxLQUFLLENBQUMsV0FBVztRQUNiLE1BQU0sS0FBSyxHQUFHLE1BQU0sTUFBTSxDQUFDLHNCQUFzQixDQUFDLENBQUM7UUFDbkQsTUFBTSxXQUFXLEdBQUcsTUFBTSxNQUFNLENBQUMsbUNBQW1DLENBQUMsQ0FBQztRQUV0RSxLQUFLLENBQUMsbUJBQW1CLENBQUMsU0FBUyxHQUFHLFdBQVcsQ0FBQztRQUVsRCxNQUFNLEdBQUcsR0FBcUIsTUFBTSxXQUFXLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxRQUFRLENBQUM7YUFDcEUsT0FBTyxDQUFDO1FBQ2IsTUFBTSxJQUFJLEdBQUcsTUFBTSxHQUFHLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBRWxDLE1BQU0sa0JBQWtCLEdBQUcsRUFBRSxLQUFLLEVBQUUsQ0FBQyxFQUFFLENBQUM7UUFDeEMsTUFBTSxRQUFRLEdBQUcsSUFBSSxDQUFDLFdBQVcsQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDO1FBRXRELElBQUksQ0FBQyxNQUFNLENBQUMsTUFBTSxHQUFHLFFBQVEsQ0FBQyxNQUFNLENBQUM7UUFDckMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxLQUFLLEdBQUcsUUFBUSxDQUFDLEtBQUssQ0FBQztRQUVuQyxNQUFNLElBQUksR0FBRyxJQUFJLENBQUMsZ0JBQWdCLENBQUMsUUFBUSxDQUFDLEtBQUssRUFBRSxRQUFRLENBQUMsTUFBTSxDQUFDLENBQUM7UUFDcEUsT0FBTyxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUNsQixJQUFJLENBQUMsVUFBVSxHQUFHLElBQUksQ0FBQztRQUV2QixJQUFJLENBQUMsVUFBVSxHQUFHLElBQUksQ0FBQyxDQUFDLEdBQUcsUUFBUSxDQUFDLEtBQUssQ0FBQztRQUUxQyxNQUFNLE9BQU8sR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQTZCLENBQUM7UUFDekUsTUFBTSxhQUFhLEdBQUc7WUFDbEIsYUFBYSxFQUFFLE9BQU87WUFDdEIsUUFBUTtTQUNYLENBQUM7UUFDRixNQUFNLFVBQVUsR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDLGFBQWEsQ0FBQyxDQUFDLE9BQU8sQ0FBQztRQUV0RCxVQUFVLENBQUMsSUFBSSxDQUFDLEdBQUcsRUFBRSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsZUFBZSxDQUFDLENBQUMsQ0FBQztRQUVwRCxrQ0FBa0M7UUFDbEMsa0NBQWtDO1FBQ2xDLGNBQWM7SUFDbEIsQ0FBQztJQUVELDJDQUEyQztJQUMzQyxVQUFVO1FBQ04sSUFBSSxDQUFDLFFBQVEsR0FBRyxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUM7UUFDL0IsSUFBSSxDQUFDLGVBQWUsRUFBRSxDQUFDO0lBQzNCLENBQUM7SUFFRCw2Q0FBNkM7SUFDN0MsVUFBVTtRQUNOLElBQUksQ0FBQyxRQUFRLEdBQUcsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDO1FBQy9CLElBQUksQ0FBQyxlQUFlLEVBQUUsQ0FBQztJQUMzQixDQUFDO0lBRUQ7O3VHQUVtRztJQUVuRyx3QkFBd0I7SUFDeEIsS0FBSyxDQUFDLFlBQVk7UUFDZCxNQUFNLElBQUksQ0FBQyx1QkFBdUIsQ0FBQyxlQUFlLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUU1RSxNQUFNLEVBQUUsR0FBRyxFQUFFLEdBQUcsSUFBSSxDQUFDLHVCQUF1QixDQUFDO1FBQzdDLElBQUksQ0FBQyxNQUFNLEdBQUcsTUFBTSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsdUJBQXVCLENBQUMsTUFBTSxDQUFDLENBQUM7UUFDakUsNEJBQTRCO1FBQzVCLFVBQVUsQ0FBQyxLQUFLLElBQUksRUFBRTtZQUNsQixzQkFBc0I7WUFDdEIsR0FBRyxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLENBQUMsSUFBSSxDQUFDLEtBQUssRUFBRSxRQUFRLEVBQUUsRUFBRTtnQkFDN0QsNkNBQTZDO2dCQUM3QyxJQUFJO29CQUNBLE1BQU0sZUFBZSxHQUFHLElBQUksQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFDO3dCQUNuRCxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFDLHVCQUF1QixDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUM7b0JBQzdFLE1BQU0sSUFBSSxDQUFDLHVCQUF1QixDQUFDLFdBQVcsQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxJQUFJLEVBQUUsZUFBZSxDQUFDLENBQUM7b0JBRTNGLDJFQUEyRTtvQkFDM0UsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxVQUFVLEVBQUUsQ0FBQyxPQUFPLEVBQUUsT0FBTyxFQUFFLEVBQUU7d0JBQ25ELElBQUksT0FBTyxLQUFLLEdBQUcsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLFNBQVMsRUFBRTs0QkFDckMsR0FBRyxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsU0FBUyxFQUFFO2dDQUNyQyxVQUFVLEVBQUUsb0JBQW9COzZCQUNuQyxDQUFDLENBQUM7eUJBQ047b0JBQ0wsQ0FBQyxDQUFDLENBQUM7aUJBQ047Z0JBQUMsTUFBTTtvQkFDSixPQUFPLENBQUMsR0FBRyxDQUFDLHdCQUF3QixDQUFDLENBQUM7aUJBQ3pDO1lBQ0wsQ0FBQyxDQUFDLENBQUM7WUFFSCw2Q0FBNkM7WUFDN0MsSUFBSSxDQUFDLE9BQU8sR0FBRyxLQUFLLENBQUM7UUFDekIsQ0FBQyxFQUFFLElBQUksQ0FBQyxDQUFDO1FBRVQsOENBQThDO1FBQzlDLEdBQUcsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDLEtBQUssRUFBRSxFQUFFO1lBQ2hDLHdIQUF3SDtZQUN4SCxJQUFJLENBQUMsSUFBSSxDQUFDLGVBQWUsRUFBRTtnQkFDdkIsSUFBSSxDQUFDLFFBQVEsR0FBRyxLQUFLLENBQUMsUUFBUSxDQUFDLENBQUMsR0FBRyxHQUFHLENBQUM7Z0JBQ3ZDLElBQUksQ0FBQyxZQUFZLEdBQUcsSUFBSSxDQUFDLFFBQVEsQ0FBQztnQkFDbEMsSUFBSSxDQUFDLFVBQVUsR0FBRyxLQUFLLENBQUM7YUFDM0I7UUFDTCxDQUFDLENBQUMsQ0FBQztJQUNQLENBQUM7SUFFRCxtREFBbUQ7SUFDbkQsS0FBSyxDQUFDLGdCQUFnQjtRQUNsQixNQUFNLGFBQWEsR0FBRyxJQUFJLENBQUMsUUFBUSxHQUFHLElBQUksQ0FBQyxZQUFZLENBQUM7UUFDeEQsSUFBSSxDQUFDLFlBQVksR0FBRyxJQUFJLENBQUMsUUFBUSxDQUFDO1FBRWxDLGlGQUFpRjtRQUNqRixJQUFJLENBQUMsa0JBQWtCLENBQUMsSUFBSSxDQUFDLGFBQWEsQ0FBQyxDQUFDO1FBRTVDLDBEQUEwRDtRQUMxRCxJQUFJLENBQUMsSUFBSSxDQUFDLGVBQWUsRUFBRTtZQUN2QixJQUFJLENBQUMsZUFBZSxHQUFHLElBQUksQ0FBQztZQUM1QixJQUFJLENBQUMseUJBQXlCLEVBQUUsQ0FBQztTQUNwQztJQUNMLENBQUM7SUFFRCw2RUFBNkU7SUFDN0UsS0FBSyxDQUFDLHlCQUF5QjtRQUMzQixNQUFNLEVBQUUsR0FBRyxFQUFFLEdBQUcsSUFBSSxDQUFDLHVCQUF1QixDQUFDO1FBRTdDLG1DQUFtQztRQUNuQyxPQUFPLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxFQUFFO1lBQ3ZDLHFFQUFxRTtZQUNyRSxNQUFNLEdBQUcsQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUFDLEVBQUU7Z0JBQ3hELEtBQUssRUFBRSxHQUFHO2FBQ2IsQ0FBQyxDQUFDO1NBQ047UUFFRCw0RkFBNEY7UUFDNUYsSUFBSSxDQUFDLGVBQWUsR0FBRyxLQUFLLENBQUM7SUFDakMsQ0FBQztJQUVEOzt1R0FFbUc7SUFFbkcsMEJBQTBCO0lBQzFCLEtBQUssQ0FBQyxTQUFTO1FBQ1gsSUFBSSxDQUFDLE9BQU8sR0FBRyxJQUFJLENBQUM7UUFDcEIsbUJBQW1CO1FBQ25CLElBQUksQ0FBQyxhQUFhLEVBQUUsQ0FBQztJQUN6QixDQUFDO0lBRUQsS0FBSyxDQUFDLFNBQVM7UUFDWCxNQUFNLENBQUMsVUFBVSxDQUFDLEdBQUcsSUFBSSxDQUFDLGtCQUFrQixDQUFDO1FBQzdDLE1BQU0sUUFBUSxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsVUFBVSxDQUFDLFFBQVEsQ0FBQyxDQUFDO1FBQ2pELElBQUksQ0FBQyxhQUFhO1lBQ2QsTUFBTSxJQUFJLENBQUMsdUJBQXVCLENBQUMsR0FBRyxDQUFDLFFBQVEsQ0FBQyxpQkFBaUIsQ0FBQztnQkFDOUQsQ0FBQyxFQUFFLFFBQVEsQ0FBQyxDQUFDO2dCQUNiLENBQUMsRUFBRSxRQUFRLENBQUMsQ0FBQztnQkFDYixDQUFDLEVBQUUsUUFBUSxDQUFDLENBQUM7YUFDaEIsQ0FBQyxDQUFDO1FBQ1AsSUFBSSxDQUFDLGNBQWM7WUFDZixNQUFNLElBQUksQ0FBQyx1QkFBdUIsQ0FBQyxHQUFHLENBQUMsUUFBUSxDQUFDLGlCQUFpQixDQUFDO2dCQUM5RCxDQUFDLEVBQUUsUUFBUSxDQUFDLENBQUM7Z0JBQ2IsQ0FBQyxFQUFFLENBQUM7Z0JBQ0osQ0FBQyxFQUFFLENBQUM7YUFDUCxDQUFDLENBQUM7UUFDUCxNQUFNLFdBQVcsR0FBRyxDQUFDLEdBQUcsUUFBUSxDQUFDLENBQUMsQ0FBQztRQUNuQyxJQUFJLFVBQVUsR0FBRyxJQUFJLENBQUMsY0FBYyxDQUFDLENBQUMsR0FBRyxJQUFJLENBQUMsYUFBYSxDQUFDLENBQUMsQ0FBQztRQUM5RCxJQUFJLFVBQVUsS0FBSyxDQUFDLEVBQUU7WUFDbEIsZ0RBQWdEO1lBQ2hELE1BQU0sVUFBVSxHQUFHLElBQUksQ0FBQyxjQUFjLENBQUMsQ0FBQyxHQUFHLElBQUksQ0FBQyxhQUFhLENBQUMsQ0FBQyxDQUFDO1lBQ2hFLElBQUksQ0FBQyxTQUFTLENBQUMsU0FBUyxHQUFHLEdBQUcsQ0FBQztZQUMvQixJQUFJLENBQUMsU0FBUyxDQUFDLFNBQVMsR0FBRyxHQUFHLENBQUM7WUFDL0IsSUFBSSxDQUFDLFNBQVMsQ0FBQyxPQUFPLEdBQUcsSUFBSSxDQUFDLGNBQWMsQ0FBQyxDQUFDLENBQUM7WUFDL0MsSUFBSSxDQUFDLFNBQVMsQ0FBQyxNQUFNLEdBQUcsVUFBVSxHQUFHLFdBQVcsQ0FBQztTQUNwRDthQUFNO1lBQ0gsaURBQWlEO1lBQ2pELElBQUksQ0FBQyxTQUFTLENBQUMsU0FBUyxHQUFHLEdBQUcsQ0FBQztZQUMvQixJQUFJLENBQUMsU0FBUyxDQUFDLFNBQVMsR0FBRyxHQUFHLENBQUM7WUFDL0IsSUFBSSxDQUFDLFNBQVMsQ0FBQyxPQUFPLEdBQUcsSUFBSSxDQUFDLGNBQWMsQ0FBQyxDQUFDLENBQUM7WUFDL0MsSUFBSSxDQUFDLFNBQVMsQ0FBQyxNQUFNLEdBQUcsVUFBVSxHQUFHLFdBQVcsQ0FBQztTQUNwRDtRQUNELE1BQU0sYUFBYSxHQUNmLE1BQU0sSUFBSSxDQUFDLHVCQUF1QixDQUFDLEdBQUcsQ0FBQyxRQUFRLENBQUMsaUJBQWlCLENBQUM7WUFDOUQsQ0FBQyxFQUFFLENBQUM7WUFDSixDQUFDLEVBQUUsQ0FBQztZQUNKLENBQUMsRUFBRSxRQUFRLENBQUMsQ0FBQztTQUNoQixDQUFDLENBQUM7UUFDUCxNQUFNLFdBQVcsR0FBRyxDQUFDLEdBQUcsUUFBUSxDQUFDLENBQUMsQ0FBQztRQUNuQyxJQUFJLFVBQVUsS0FBSyxDQUFDLEVBQUU7WUFDbEIsaURBQWlEO1lBQ2pELFVBQVUsR0FBRyxhQUFhLENBQUMsQ0FBQyxHQUFHLElBQUksQ0FBQyxhQUFhLENBQUMsQ0FBQyxDQUFDO1lBQ3BELElBQUksQ0FBQyxTQUFTLENBQUMsT0FBTyxHQUFHLGFBQWEsQ0FBQyxDQUFDLENBQUM7WUFDekMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxNQUFNLEdBQUcsVUFBVSxHQUFHLFdBQVcsQ0FBQztTQUNwRDthQUFNO1lBQ0gsTUFBTSxVQUFVLEdBQUcsYUFBYSxDQUFDLENBQUMsR0FBRyxJQUFJLENBQUMsYUFBYSxDQUFDLENBQUMsQ0FBQztZQUMxRCxJQUFJLENBQUMsU0FBUyxDQUFDLE9BQU8sR0FBRyxhQUFhLENBQUMsQ0FBQyxDQUFDO1lBQ3pDLElBQUksQ0FBQyxTQUFTLENBQUMsTUFBTSxHQUFHLFVBQVUsR0FBRyxXQUFXLENBQUM7U0FDcEQ7UUFFRCwyREFBMkQ7UUFDM0QsTUFBTSxhQUFhLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxZQUFZLEVBQUUsQ0FBQztRQUNsRCxNQUFNLEVBQUUsS0FBSyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsR0FBRyxhQUFhLENBQUM7UUFDdEMsOEJBQThCO1FBQzlCLElBQUksQ0FBQyxTQUFTLENBQUMsV0FBVyxHQUFHLENBQUMsQ0FBQztRQUMvQixJQUFJLENBQUMsU0FBUyxDQUFDLFdBQVcsR0FBRyxDQUFDLENBQUM7UUFDL0IsSUFBSSxDQUFDLFNBQVMsQ0FBQyxTQUFTLEdBQUcsS0FBSyxDQUFDO1FBQ2pDLE9BQU8sQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDO0lBQ2hDLENBQUM7SUFFRCxtQkFBbUI7SUFDbkIsS0FBSyxDQUFDLGFBQWE7UUFDZix1QkFBdUI7UUFDdkIsTUFBTSxJQUFJLEdBQUcsTUFBTSxJQUFJLENBQUMsV0FBVyxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBRXBFLElBQUksSUFBSSxFQUFFO1lBQ04sSUFBSSxDQUFDLFdBQVcsR0FBRyxJQUFJLENBQUM7WUFDeEIsTUFBTSxXQUFXLEdBQUcsTUFBTSxJQUFJLENBQUMsaUJBQWlCLENBQUMscUJBQXFCLENBQ2xFLElBQUksQ0FBQyxXQUFXLENBQ25CLENBQUM7WUFDRixJQUFJLENBQUMsa0JBQWtCLEdBQUcsV0FBVyxDQUFDO1lBQ3RDLE1BQU0sSUFBSSxDQUFDLFNBQVMsRUFBRSxDQUFDO1lBQ3ZCLElBQUksV0FBVyxDQUFDLE1BQU0sR0FBRyxDQUFDLEVBQUU7Z0JBQ3hCLEtBQUssTUFBTSxVQUFVLElBQUksV0FBVyxFQUFFO29CQUNsQyxNQUFNLFlBQVksR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLFVBQVUsQ0FBQyxRQUFRLENBQUMsQ0FBQztvQkFDckQsTUFBTSxTQUFTLEdBQ1gsSUFBSSxDQUFDLFNBQVMsQ0FBQyxTQUFTLEtBQUssR0FBRyxDQUFDLENBQUMsQ0FBQyxZQUFZLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxZQUFZLENBQUMsQ0FBQyxDQUFDO29CQUN2RSxNQUFNLFNBQVMsR0FDWCxJQUFJLENBQUMsU0FBUyxDQUFDLFNBQVMsS0FBSyxHQUFHLENBQUMsQ0FBQyxDQUFDLFlBQVksQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLFlBQVksQ0FBQyxDQUFDLENBQUM7b0JBQ3ZFLE1BQU0sS0FBSyxHQUNQLFNBQVMsR0FBRyxJQUFJLENBQUMsU0FBUyxDQUFDLE1BQU0sR0FBRyxJQUFJLENBQUMsU0FBUyxDQUFDLE9BQU8sQ0FBQztvQkFDL0QsTUFBTSxLQUFLLEdBQ1AsU0FBUyxHQUFHLElBQUksQ0FBQyxTQUFTLENBQUMsTUFBTSxHQUFHLElBQUksQ0FBQyxTQUFTLENBQUMsT0FBTyxDQUFDO29CQUMvRCxvREFBb0Q7b0JBQ3BELE1BQU0sWUFBWSxHQUNkLENBQUMsS0FBSyxHQUFHLElBQUksQ0FBQyxTQUFTLENBQUMsV0FBVyxDQUFDLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQyxTQUFTLENBQUMsQ0FBQyxrQ0FBa0M7b0JBQ3ZHLE1BQU0sWUFBWSxHQUNkLENBQUMsS0FBSyxHQUFHLElBQUksQ0FBQyxTQUFTLENBQUMsV0FBVyxDQUFDLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQyxTQUFTLENBQUM7b0JBQ3BFLElBQUksQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDO3dCQUNoQixLQUFLLEVBQUUsVUFBVSxDQUFDLEVBQUU7d0JBQ3BCLE1BQU0sRUFBRSxJQUFJLENBQUMsVUFBVSxDQUFDLEVBQUU7d0JBQzFCLENBQUMsRUFBRSxZQUFZO3dCQUNmLENBQUMsRUFBRSxZQUFZO3FCQUNsQixDQUFDLENBQUM7b0JBQ0gsTUFBTSxRQUFRLEdBQUcsRUFBRSxHQUFHLElBQUksQ0FBQyxTQUFTLENBQUMsU0FBUyxDQUFDO29CQUMvQyxNQUFNLEtBQUssR0FBRyxRQUFRLEdBQUcsQ0FBQyxDQUFDO29CQUMzQixJQUFJLENBQUMsU0FBUyxDQUNWLDBFQUEwRSxFQUMxRSxZQUFZLEdBQUcsS0FBSyxFQUNwQixZQUFZLEdBQUcsS0FBSyxFQUNwQixJQUFJLENBQ1AsQ0FBQztpQkFDTDthQUNKO1NBQ0o7SUFDTCxDQUFDO0lBRUQsdUJBQXVCO0lBQ3ZCLEtBQUssQ0FBQyxNQUFNO1FBQ1IsSUFBSSxJQUFJLENBQUMsV0FBVyxFQUFFO1lBQ2xCLDhCQUE4QjtZQUM5Qiw2Q0FBNkM7WUFDN0MsNkNBQTZDO1lBQzdDLHVDQUF1QztZQUN2Qyx1Q0FBdUM7WUFDdkMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxHQUFHLEdBQUcsSUFBSSxDQUFDO1lBQzFCLElBQUksQ0FBQyxTQUFTLENBQUMsUUFBUSxHQUFHLElBQUksQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDO1lBQzVDLElBQUksQ0FBQyxTQUFTLENBQUMsU0FBUyxHQUFHLElBQUksQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDO1lBRTdDLE1BQU0sSUFBSSxDQUFDLFdBQVcsQ0FBQyxVQUFVLENBQUM7Z0JBQzlCLEVBQUUsRUFBRSxJQUFJLENBQUMsVUFBVSxDQUFDLEVBQUU7Z0JBQ3RCLFdBQVcsRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUM7YUFDOUMsQ0FBQyxDQUFDO1lBQ0gsTUFBTSxPQUFPLENBQUMsR0FBRyxDQUNiLElBQUksQ0FBQyxTQUFTLENBQUMsR0FBRyxDQUFDLEtBQUssRUFBRSxRQUFRLEVBQUUsRUFBRTtnQkFDbEMsTUFBTSxFQUFFLEtBQUssRUFBRSxHQUFHLFFBQVEsQ0FBQztnQkFDM0IsT0FBTyxRQUFRLENBQUMsS0FBSyxDQUFDO2dCQUN0QixNQUFNLEdBQUcsR0FBRyxJQUFJLENBQUMsa0JBQWtCLENBQUMsSUFBSSxDQUFDLENBQUMsSUFBSSxFQUFFLEVBQUUsQ0FBQyxJQUFJLENBQUMsRUFBRSxLQUFLLEtBQUssQ0FBQyxDQUFDO2dCQUN0RSxJQUFJLHFCQUFxQixDQUFDO2dCQUMxQixJQUFJLEdBQUcsQ0FBQyxjQUFjLEVBQUU7b0JBQ3BCLE1BQU0sY0FBYyxHQUFHLEdBQUcsQ0FBQyxjQUFjLENBQUMsR0FBRyxDQUFDLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FDcEQsSUFBSSxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsQ0FDcEIsQ0FBQztvQkFDRixNQUFNLHNCQUFzQixHQUFHLGNBQWMsQ0FBQyxJQUFJLENBQzlDLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FBQyxLQUFLLENBQUMsTUFBTSxLQUFLLElBQUksQ0FBQyxVQUFVLENBQUMsRUFBRSxDQUNqRCxDQUFDO29CQUNGLElBQUksc0JBQXNCLEVBQUU7d0JBQ3hCLGNBQWMsQ0FBQyxNQUFNLENBQ2pCLGNBQWMsQ0FBQyxPQUFPLENBQUMsc0JBQXNCLENBQUMsRUFDOUMsQ0FBQyxFQUNELFFBQVEsQ0FDWCxDQUFDO3FCQUNMO3lCQUFNO3dCQUNILGNBQWMsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUM7cUJBQ2pDO29CQUNELHFCQUFxQixHQUFHLENBQUMsR0FBRyxjQUFjLENBQUMsQ0FBQztpQkFDL0M7cUJBQU07b0JBQ0gscUJBQXFCLEdBQUcsQ0FBQyxRQUFRLENBQUMsQ0FBQztpQkFDdEM7Z0JBQ0Qsc0NBQXNDO2dCQUN0QyxNQUFNLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxnQkFBZ0IsQ0FBQztvQkFDMUMsRUFBRSxFQUFFLEtBQUs7b0JBQ1QsY0FBYyxFQUFFLHFCQUFxQixDQUFDLEdBQUcsQ0FBQyxDQUFDLEtBQUssRUFBRSxFQUFFLENBQ2hELElBQUksQ0FBQyxTQUFTLENBQUMsS0FBSyxDQUFDLENBQ3hCO2lCQUNKLENBQUMsQ0FBQztZQUNQLENBQUMsQ0FBQyxDQUNMLENBQUM7U0FDTDtRQUNELElBQUksQ0FBQyx1QkFBdUIsQ0FBQyxXQUFXLEVBQUUsQ0FBQztRQUUzQyxJQUFJLENBQUMsTUFBTSxDQUFDLFFBQVEsQ0FBQyxDQUFDLHlCQUF5QixFQUFFLElBQUksQ0FBQyxPQUFPLEVBQUUsT0FBTyxDQUFDLENBQUMsQ0FBQztRQUN6RSxLQUFLLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxPQUFPLENBQUMscUJBQXFCLENBQUMsQ0FBQyxDQUFDO0lBQ3pELENBQUM7SUFFRCx1QkFBdUI7SUFDdkIsT0FBTztRQUNILElBQUksQ0FBQyxRQUFRLEdBQUcsS0FBSyxDQUFDO1FBQ3RCLElBQUksQ0FBQyxRQUFRLEdBQUcsS0FBSyxDQUFDO1FBQ3RCLElBQUksQ0FBQyxPQUFPLEdBQUcsS0FBSyxDQUFDO1FBRXJCLElBQUksQ0FBQyxlQUFlLEVBQUUsQ0FBQztJQUMzQixDQUFDO0lBRUQsb0JBQW9CO0lBQ3BCLFFBQVE7UUFDSixJQUFJLENBQUMsdUJBQXVCLENBQUMsV0FBVyxFQUFFLENBQUM7UUFDM0MsSUFBSSxDQUFDLE1BQU0sQ0FBQyxRQUFRLENBQUMsQ0FBQyx5QkFBeUIsRUFBRSxJQUFJLENBQUMsT0FBTyxFQUFFLE9BQU8sQ0FBQyxDQUFDLENBQUM7UUFDekUsS0FBSyxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsT0FBTyxDQUFDLHNCQUFzQixDQUFDLENBQUMsQ0FBQztJQUMxRCxDQUFDO0lBRUQsS0FBSyxDQUFDLFlBQVksQ0FBQyxLQUFLO1FBQ3BCLElBQUksQ0FBQyxZQUFZLEdBQUcsS0FBSyxDQUFDO1FBQzFCLE1BQU0sSUFBSSxDQUFDLHVCQUF1QixDQUFDLFdBQVcsQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDLENBQUM7SUFDN0QsQ0FBQztJQUVELG9CQUFvQjtRQUNoQixJQUFJLENBQUMsZ0JBQWdCLEdBQUcsQ0FBQyxJQUFJLENBQUMsZ0JBQWdCLENBQUM7UUFDL0MsTUFBTSxNQUFNLEdBQUcsUUFBUSxDQUFDLGFBQWEsQ0FBQyxlQUFlLENBQWdCLENBQUM7UUFDdEUsSUFBSSxNQUFNLEVBQUU7WUFDUixNQUFNLENBQUMsS0FBSyxDQUFDLE1BQU0sR0FBRyxJQUFJLENBQUMsZ0JBQWdCLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDO1NBQzNEO0lBQ0wsQ0FBQzs7aUhBaGtCUSxvQkFBb0I7cUdBQXBCLG9CQUFvQiwrSkN6QmpDLCttSkFpR007MkZEeEVPLG9CQUFvQjtrQkFMaEMsU0FBUzsrQkFDSSxpQkFBaUI7OFNBWUgsU0FBUztzQkFBaEMsU0FBUzt1QkFBQyxXQUFXIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQ29tcG9uZW50LCBFbGVtZW50UmVmLCBPbkluaXQsIFZpZXdDaGlsZCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgQWN0aXZhdGVkUm91dGUsIFJvdXRlciB9IGZyb20gJ0Bhbmd1bGFyL3JvdXRlcic7XG5pbXBvcnQgeyBUcmFuc2xhdGVTZXJ2aWNlIH0gZnJvbSAnQG5neC10cmFuc2xhdGUvY29yZSc7XG5pbXBvcnQgeyBnZXREb2N1bWVudCB9IGZyb20gJ3BkZmpzLWRpc3QnO1xuaW1wb3J0IHsgUERGRG9jdW1lbnRQcm94eSB9IGZyb20gJ25nMi1wZGYtdmlld2VyJztcbmltcG9ydCB7XG4gICAgWm9uZSxcbiAgICBNZW51SXRlbSxcbiAgICBQbGFuLFxuICAgIFNwYWNlLFxuICAgIE5hdmlnYXRpb24sXG4gICAgUGxhblNlcnZpY2UsXG4gICAgWm9uZVNlcnZpY2UsXG4gICAgU3BhY2VTZXJ2aWNlLFxuICAgIE5hdmlnYXRpb25TZXJ2aWNlLFxuICAgIGdldE1ldGFGb3JJbWFnZSxcbiAgICBNYXR0ZXJwb3J0SW1wb3J0U2VydmljZSxcbn0gZnJvbSAnQHNtYXJ0ZXJwbGFuL25neC1zbWFydGVycGxhbi1jb3JlJztcbmltcG9ydCBwYW56b29tIGZyb20gJ3Bhbnpvb20nO1xuXG5AQ29tcG9uZW50KHtcbiAgICBzZWxlY3RvcjogJ2xpYi1jYWxpYnJhdGlvbicsXG4gICAgdGVtcGxhdGVVcmw6ICcuL2NhbGlicmF0aW9uLmNvbXBvbmVudC5odG1sJyxcbiAgICBzdHlsZVVybHM6IFsnLi9jYWxpYnJhdGlvbi5jb21wb25lbnQuc2NzcyddLFxufSlcbmV4cG9ydCBjbGFzcyBDYWxpYnJhdGlvbkNvbXBvbmVudCBpbXBsZW1lbnRzIE9uSW5pdCB7XG4gICAgLyoqIEl0ZW0gdG8gZGlzcGxheSBmb3IgdGhlIG5hdmJhciAqL1xuICAgIG1lbnVJdGVtczogTWVudUl0ZW1bXSA9IFtdO1xuXG4gICAgLyoqIENhbnZhcyAoUGxhbikgKi9cbiAgICBjYW52YXM7XG5cbiAgICAvKiogQ2FudmFzRGl2IChEaXYgdGhhdCBjb250YWluIHRoZSBjYW52YXMgKyBtYXR0ZXJwb3J0IGlmcmFtZSkgKi9cbiAgICBAVmlld0NoaWxkKCdjYW52YXNEaXYnKSBjYW52YXNEaXY6IEVsZW1lbnRSZWY7XG5cbiAgICAvKiogU2l6ZSBvZiB0aGUgY2FudmFzICYgbWF0dGVycG9ydCBpZnJhbWUgKi9cbiAgICBjYW52YXNTaXplOiB7IHc6IG51bWJlcjsgaDogbnVtYmVyOyB9O1xuXG4gICAgLyoqIFpvb20gcmF0aW8gb2YgdGhlIGNhbnZhcy9wbGFuICAqL1xuICAgIGNhbnZhc1pvb20gPSAwO1xuXG4gICAgLyoqIE9wYWNpdHkgZm9yIG1hdHRlcnBvcnQgaWZyYW1lICovXG4gICAgb3BhY2l0eTogbnVtYmVyID0gNTA7XG5cbiAgICAvKiogQ3VycmVudCByb3RhdGlvbiBmb3IgbWF0dGVycG9ydCwgWzAtMzYwXSwgIG1hdHRlcnBvcnQgcm90YXRpb24gaXMgYmluZCB0byBpbnB1dCByYW5nZSAqL1xuICAgIHJvdGF0aW9uOiBudW1iZXIgPSAxODA7XG5cbiAgICAvKiogUHJldmlvdXMgcm90YXRpb24sIHVzZSB0byBjYWxjdWxhdGUgdGhlIGRlbHRhUm90YXRpb24gdG8gcm90YXRlLCB3aGVuIHVzZXIgY2hhbmdlIHJvdGF0aW9uIHZhbHVlIHVzaW5nIHJhbmdlIGlucHV0ICovXG4gICAgcHJldlJvdGF0aW9uOiBudW1iZXIgPSAxODA7XG5cbiAgICAvKiogQ3VycmVudCBDYW1lcmEgUG9zZSAqL1xuICAgIGNhbWVyYVBvc2U6IGFueTtcblxuICAgIC8qKiBUcnVlIHdoZW4gdGhlIHVzZXIgaXMgY3VycmVudGx5IHJvdGF0aW5nIHdpdGggdGhlIGlucHV0IHJhbmdlLCB0aGUgbWF0dGVycG9ydCByb3RhdGlvbiBldmVudHMgd2lsbCBiZSBpZ25vcmVkICovXG4gICAgaXNSb3RhdGluZ1JhbmdlOiBib29sZWFuID0gZmFsc2U7XG5cbiAgICAvKiogUm90YXRpbmcgcXVldWUgZXZlbnQgdG8gc2VuZCB0byBtYXR0ZXJwb3J0ICovXG4gICAgcm90YXRpbmdRdWV1ZUV2ZW50OiBudW1iZXJbXSA9IFtdO1xuXG4gICAgLyoqIFRydWUgd2hlbiBWZXJ0aWNhbCBzeW1tZXRyeSBpcyBlbmFibGVkICovXG4gICAgcmVmbGVjdFYgPSBmYWxzZTtcblxuICAgIC8qKiBUcnVlIHdoZW4gSG9yaXpvbnRhbCBzeW1tZXRyeSBpcyBlbmFibGVkICovXG4gICAgcmVmbGVjdEggPSBmYWxzZTtcblxuICAgIGNob3NlblBsYW46IFBsYW47XG5cbiAgICBzcGFjZUlEOiBzdHJpbmc7XG5cbiAgICBjdXJyZW50U3BhY2U6IFNwYWNlO1xuXG4gICAgY3VycmVudFpvbmU6IFpvbmU7XG5cbiAgICBjaG9zZW5QbGFuSXNQZGYgPSBmYWxzZTtcblxuICAgIC8qKiBGaXJzdCBQb2ludCBpbiB2aXNpdCwgdXNlZCB0byBkZXRlcm1pbmUgdGhlIGNhbGlicmF0aW9uICAqL1xuICAgIGZpcnN0TWFya1Zpc2l0ID0geyB4OiAwLCB5OiAwIH07XG5cbiAgICAvKiogU2Vjb25kIFBvaW50IGluIHZpc2l0LCB1c2VkIHRvIGRldGVybWluZSB0aGUgY2FsaWJyYXRpb24gICovXG4gICAgc2Vjb25kTWFya1Zpc2l0ID0geyB4OiAwLjUsIHk6IDAuNSB9O1xuXG4gICAgLyoqIEVxdWl2YWxlbnQgb2YgJ2ZpcnN0TWFya1Zpc2l0JyBpbiBjYW52YXMgICovXG4gICAgZmlyc3RNYXJrUGxhbjogeyB4OiBudW1iZXI7IHk6IG51bWJlcjsgfSA9IHsgeDogMCwgeTogMCB9O1xuXG4gICAgLyoqIEVxdWl2YWxlbnQgb2YgJ3NlY29uZE1hcmtWaXNpdCcgaW4gY2FudmFzICAqL1xuICAgIHNlY29uZE1hcmtQbGFuOiB7IHg6IG51bWJlcjsgeTogbnVtYmVyOyB9ID0geyB4OiAwLCB5OiAwIH07XG5cbiAgICAvKiogQ2FsaWJyYXRpb24gcmVzdWx0LCAob2Zmc2V0WCwgb2Zmc2V0WSwgeCwgeSkgKi9cbiAgICBjYWxpYnJhZ2U6IGFueSA9IHt9O1xuXG4gICAgLyoqIElzIGluIHByZXZpZXcgbW9kZSAoc2VlIHNjYW4gcmVzdWx0KSAqL1xuICAgIHByZXZpZXcgPSBmYWxzZTtcblxuICAgIC8qKiBNYXR0ZXJwb3J0IGlzIGxvYWRpbmcgKi9cbiAgICBsb2FkaW5nID0gdHJ1ZTtcblxuICAgIC8qIGZvciBwYW4gYW5kIHpvb20gb2YgY2FudmFzICovXG4gICAgcGFuem9vbTogYW55O1xuXG4gICAgY3VycmVudE5hdmlnYXRpb25zOiBOYXZpZ2F0aW9uW107XG5cbiAgICBwb3NpdGlvbnM6IHsgbmF2SUQ6IHN0cmluZzsgcGxhbklEOiBzdHJpbmc7IHg6IG51bWJlcjsgeTogbnVtYmVyOyB9W10gPSBbXTtcblxuICAgIGZsb29yczogYW55W10gPSBbXTtcblxuICAgIGN1cnJlbnRGbG9vcjtcblxuICAgIHpvb21DYW5CZUNoYW5nZWQ6IGJvb2xlYW4gPSBmYWxzZTtcblxuICAgIGNvbnN0cnVjdG9yKFxuICAgICAgICBwcml2YXRlIG1hdHRlcnBvcnRJbXBvcnRTZXJ2aWNlOiBNYXR0ZXJwb3J0SW1wb3J0U2VydmljZSxcbiAgICAgICAgcHJpdmF0ZSBwbGFuU2VydmljZTogUGxhblNlcnZpY2UsXG4gICAgICAgIHByaXZhdGUgcm91dGU6IEFjdGl2YXRlZFJvdXRlLFxuICAgICAgICBwcml2YXRlIHJvdXRlcjogUm91dGVyLFxuICAgICAgICBwcml2YXRlIHpvbmVTZXJ2aWNlOiBab25lU2VydmljZSxcbiAgICAgICAgcHJpdmF0ZSBzcGFjZVNlcnZpY2U6IFNwYWNlU2VydmljZSxcbiAgICAgICAgcHJpdmF0ZSBuYXZpZ2F0aW9uU2VydmljZTogTmF2aWdhdGlvblNlcnZpY2UsXG4gICAgICAgIHByaXZhdGUgdHJhbnNsYXRlOiBUcmFuc2xhdGVTZXJ2aWNlXG4gICAgKSB7IH1cblxuICAgIG5nT25EZXN0cm95KCk6IHZvaWQge1xuICAgICAgICBpZiAoIXRoaXMubG9hZGluZykge1xuICAgICAgICAgICAgdGhpcy5tYXR0ZXJwb3J0SW1wb3J0U2VydmljZS5yZW1vdmVGcmFtZSgpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgYXN5bmMgbmdPbkluaXQoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIHRoaXMuc3BhY2VJRCA9IHRoaXMucm91dGUuc25hcHNob3QucXVlcnlQYXJhbXMuc3BhY2VJRDtcbiAgICAgICAgdGhpcy5jdXJyZW50U3BhY2UgPSBhd2FpdCB0aGlzLnNwYWNlU2VydmljZS5nZXRTcGFjZSh0aGlzLnNwYWNlSUQpO1xuXG4gICAgICAgIC8qKiBNZW51IG5hdiBiYXIgKi9cbiAgICAgICAgdGhpcy5zZXR1cE1lbnVJdGVtcygpO1xuXG4gICAgICAgIHRoaXMuY2hvc2VuUGxhbiA9IHRoaXMucGxhblNlcnZpY2UuZ2V0Q2hvc2VuUGxhbigpO1xuXG4gICAgICAgIGlmICh0aGlzLmNob3NlblBsYW4pIHtcbiAgICAgICAgICAgIHRoaXMuY2hvc2VuUGxhbklzUGRmID0gdGhpcy5jaG9zZW5QbGFuLmFubmV4ZS5pbmNsdWRlcygncGRmJyk7XG4gICAgICAgICAgICB0aGlzLmxhdW5jaFZpZXdlcigpO1xuICAgICAgICAgICAgc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy5jb25maWd1cmVDYW52YXMoKS50aGVuKCgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5wYW56b29tID0gcGFuem9vbSh0aGlzLmNhbnZhcywge1xuICAgICAgICAgICAgICAgICAgICAgICAgYm91bmRzOiB0cnVlLFxuICAgICAgICAgICAgICAgICAgICAgICAgYm91bmRzUGFkZGluZzogMCxcbiAgICAgICAgICAgICAgICAgICAgICAgIG1heFpvb206IDIuNSxcbiAgICAgICAgICAgICAgICAgICAgICAgIG1pblpvb206IDAuMSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGluaXRpYWxab29tOiAxLFxuICAgICAgICAgICAgICAgICAgICAgICAgem9vbVNwZWVkOiAwLjAyLFxuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0sIDUwMCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aGlzLnJvdXRlci5uYXZpZ2F0ZShbJy9kYXNoYm9hcmQvbG9jYWxpc2F0aW9uJywgdGhpcy5zcGFjZUlELCAncGxhbnMnXSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKiogKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKlxuICAgICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBNRU5VIE5BViBCQVJcbiAgICAgKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiogKi9cbiAgICBzZXR1cE1lbnVJdGVtcygpIHtcbiAgICAgICAgdGhpcy5tZW51SXRlbXMgPSBbXG4gICAgICAgICAgICB7IGxhYmVsOiAnTG9jYXRpb25zJywgdXJsOiAnL2xvY2FsaXNhdGlvbicgfSxcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICBsYWJlbDogdGhpcy5jdXJyZW50U3BhY2UubmFtZSxcbiAgICAgICAgICAgICAgICB1cmw6IGAvbG9jYWxpc2F0aW9uLyR7dGhpcy5zcGFjZUlEfWAsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgIGxhYmVsOiAnUGxhbnMnLFxuICAgICAgICAgICAgICAgIHVybDogYC9sb2NhbGlzYXRpb24vJHt0aGlzLmN1cnJlbnRTcGFjZS5pZH0vcGxhbnNgLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICBsYWJlbDogJ0NhbGlicmF0aW9uJyxcbiAgICAgICAgICAgICAgICB1cmw6IGAvbG9jYWxpc2F0aW9uLyR7dGhpcy5jdXJyZW50U3BhY2UuaWR9L3BsYW4tY2FsaWJyYXRpb24/c3BhY2VJRD0ke3RoaXMuY3VycmVudFNwYWNlLmlkfWAsXG4gICAgICAgICAgICB9LFxuICAgICAgICBdO1xuICAgIH1cblxuICAgIC8qKiAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqXG4gICAgICogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQ0FOVkFTXG4gICAgICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqICovXG5cbiAgICAvKiogRGlzcGxheSB0aGUgcGxhbiAqL1xuICAgIGFzeW5jIGNvbmZpZ3VyZUNhbnZhcygpIHtcbiAgICAgICAgLyoqIEdldCBjYW52YXMgKi9cbiAgICAgICAgaWYgKCF0aGlzLmNhbnZhcykge1xuICAgICAgICAgICAgY29uc3QgY2FudmFzID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvcignI2NhbnZhcycpIGFzIEhUTUxDYW52YXNFbGVtZW50O1xuICAgICAgICAgICAgdGhpcy5jYW52YXMgPSBjYW52YXM7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIXRoaXMuY2hvc2VuUGxhbklzUGRmKSB7XG4gICAgICAgICAgICBjb25zdCBpbWFnZSA9IGF3YWl0IGdldE1ldGFGb3JJbWFnZSh0aGlzLmNob3NlblBsYW4uZmlsZXBhdGgpO1xuICAgICAgICAgICAgLyoqIENvbXB1dGUgdGhlIG5ldyBzaXplIGZvciB0aGUgY2FudmFzL21hdHRlcnBvcnQsIGJhc2Ugb24gdGhlIGRpbWVuc2lvbiBvZiB0aGUgcGxhbiwga2VlcGluZyB0aGUgcmF0aW8gKi9cbiAgICAgICAgICAgIGNvbnN0IHNpemUgPSB0aGlzLmdldFNpemVGb3JDYW52YXMoaW1hZ2Uud2lkdGgsIGltYWdlLmhlaWdodCk7XG5cbiAgICAgICAgICAgIC8qKiBDb21wdXRlIHRoZSBwbGFuIHpvb20gcmF0aW8gKHVzZSBmb3IgdGhlIGNhbGlicmF0aW9uIGxhdGVyKSAqL1xuICAgICAgICAgICAgdGhpcy5jYW52YXNab29tID0gc2l6ZS53IC8gaW1hZ2Uud2lkdGg7XG5cbiAgICAgICAgICAgIHRoaXMucmVzaXplVmlldyhzaXplKTtcblxuICAgICAgICAgICAgLyoqIERyYXcgUGxhbiBvbiB0aGUgY2FudmFzICovXG4gICAgICAgICAgICB0aGlzLmRyYXdJbWFnZSh0aGlzLmNob3NlblBsYW4uZmlsZXBhdGgpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgLy8gVE9ET1xuICAgICAgICAgICAgdGhpcy5wZGZUb0NhbnZhcygpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqIFVwZGF0ZSBzaXplIG9mIHRoZSBjYW52YXMvbWF0dGVycG9ydCAqL1xuICAgIHJlc2l6ZVZpZXcoc2l6ZSkge1xuICAgICAgICB0aGlzLmNhbnZhc0Rpdi5uYXRpdmVFbGVtZW50LnN0eWxlLndpZHRoID0gYCR7c2l6ZS53fXB4YDtcbiAgICAgICAgdGhpcy5jYW52YXNEaXYubmF0aXZlRWxlbWVudC5zdHlsZS5oZWlnaHQgPSBgJHtzaXplLmh9cHhgO1xuICAgICAgICB0aGlzLmNhbnZhcy5zdHlsZS53aWR0aCA9IGAke3NpemUud31weGA7XG4gICAgICAgIHRoaXMuY2FudmFzLnN0eWxlLmhlaWdodCA9IGAke3NpemUuaH1weGA7XG4gICAgICAgIHRoaXMuY2FudmFzLndpZHRoID0gc2l6ZS53O1xuICAgICAgICB0aGlzLmNhbnZhcy5oZWlnaHQgPSBzaXplLmg7XG4gICAgICAgIHRoaXMuY2FudmFzU2l6ZSA9IHNpemU7XG4gICAgfVxuXG4gICAgLyoqIERyYXcgc29tZXRoaW5nIG9uIHRoZSBjYW52YXMgKi9cbiAgICBkcmF3SW1hZ2UodXJsOiBzdHJpbmcsIHggPSAwLCB5ID0gMCwgaWNvbmUgPSBmYWxzZSkge1xuICAgICAgICBjb25zdCBpbWFnZSA9IG5ldyBJbWFnZSgpO1xuICAgICAgICBjb25zdCBzaXplID0gdGhpcy5jYW52YXNTaXplO1xuICAgICAgICBjb25zdCBjb250ZXh0ID0gdGhpcy5jYW52YXMuZ2V0Q29udGV4dCgnMmQnKTtcblxuICAgICAgICAvKiogRmxpcCB0aGUgY29udGV4dCwgZm9yIHN5bW1ldHJ5ICovXG4gICAgICAgIC8vIGlmICh0aGlzLnJlZmxlY3RWKSB7XG4gICAgICAgIC8vICAgICBjb250ZXh0LnRyYW5zbGF0ZShzaXplLncsIDApO1xuICAgICAgICAvLyAgICAgY29udGV4dC5zY2FsZSgtMSwgMSk7XG4gICAgICAgIC8vIH1cbiAgICAgICAgLy8gaWYgKHRoaXMucmVmbGVjdEgpIHtcbiAgICAgICAgLy8gICAgIGNvbnRleHQudHJhbnNsYXRlKDAsIHNpemUuaCk7XG4gICAgICAgIC8vICAgICBjb250ZXh0LnNjYWxlKDEsIC0xKTtcbiAgICAgICAgLy8gfVxuXG4gICAgICAgIGxldCBpbWFnZVdpZHRoID0gc2l6ZS53O1xuICAgICAgICBsZXQgaW1hZ2VIZWlnaHQgPSBzaXplLmg7XG4gICAgICAgIGltYWdlLmFkZEV2ZW50TGlzdGVuZXIoJ2xvYWQnLCAoKSA9PiB7XG4gICAgICAgICAgICBpZiAoaWNvbmUpIHtcbiAgICAgICAgICAgICAgICBpbWFnZVdpZHRoID0gaW1hZ2Uud2lkdGg7XG4gICAgICAgICAgICAgICAgaW1hZ2VIZWlnaHQgPSBpbWFnZS5oZWlnaHQ7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjb250ZXh0LmRyYXdJbWFnZShcbiAgICAgICAgICAgICAgICBpbWFnZSxcbiAgICAgICAgICAgICAgICAwLFxuICAgICAgICAgICAgICAgIDAsXG4gICAgICAgICAgICAgICAgaW1hZ2Uud2lkdGgsXG4gICAgICAgICAgICAgICAgaW1hZ2UuaGVpZ2h0LFxuICAgICAgICAgICAgICAgIHgsXG4gICAgICAgICAgICAgICAgeSxcbiAgICAgICAgICAgICAgICBpbWFnZVdpZHRoLFxuICAgICAgICAgICAgICAgIGltYWdlSGVpZ2h0XG4gICAgICAgICAgICApO1xuICAgICAgICB9KTtcbiAgICAgICAgaW1hZ2Uuc3JjID0gdXJsO1xuICAgIH1cblxuICAgIC8qKiBHZXQgdGhlIHNpemUgZm9yIHRoZSBjYW52YXMsIGJhc2VkIG9uIHRoZSBwbGFuIHNpemUsIGtlZXBpbmcgdGhlIHJhdGlvICovXG4gICAgZ2V0U2l6ZUZvckNhbnZhcyh3LCBoKSB7XG4gICAgICAgIGxldCBjYW52YXNXID0gdGhpcy5jYW52YXNEaXYubmF0aXZlRWxlbWVudC5vZmZzZXRXaWR0aDtcbiAgICAgICAgbGV0IGNhbnZhc0ggPSB0aGlzLmNhbnZhc0Rpdi5uYXRpdmVFbGVtZW50Lm9mZnNldEhlaWdodDtcblxuICAgICAgICBjb25zdCBpbWFnZVJhdGlvID0gdyAvIGg7XG4gICAgICAgIGNvbnN0IGNhbnZhc1JhdGlvID0gY2FudmFzVyAvIGNhbnZhc0g7XG5cbiAgICAgICAgaWYgKGltYWdlUmF0aW8gPiBjYW52YXNSYXRpbykge1xuICAgICAgICAgICAgY2FudmFzSCA9IGNhbnZhc1cgLyBpbWFnZVJhdGlvO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgY2FudmFzVyA9IGNhbnZhc0ggKiBpbWFnZVJhdGlvO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB7IHc6IGNhbnZhc1csIGg6IGNhbnZhc0ggfTtcbiAgICB9XG5cbiAgICAvKiogW1RPRE9dIENvbnZlcnQgYSBQREYgdG8gYSBDYW52YXMgKi9cbiAgICBhc3luYyBwZGZUb0NhbnZhcygpIHtcbiAgICAgICAgY29uc3QgcGRmanMgPSBhd2FpdCBpbXBvcnQoJ3BkZmpzLWRpc3QvYnVpbGQvcGRmJyk7XG4gICAgICAgIGNvbnN0IHBkZmpzV29ya2VyID0gYXdhaXQgaW1wb3J0KCdwZGZqcy1kaXN0L2J1aWxkL3BkZi53b3JrZXIuZW50cnknKTtcblxuICAgICAgICBwZGZqcy5HbG9iYWxXb3JrZXJPcHRpb25zLndvcmtlclNyYyA9IHBkZmpzV29ya2VyO1xuXG4gICAgICAgIGNvbnN0IHBkZjogUERGRG9jdW1lbnRQcm94eSA9IGF3YWl0IGdldERvY3VtZW50KHRoaXMuY2hvc2VuUGxhbi5maWxlcGF0aClcbiAgICAgICAgICAgIC5wcm9taXNlO1xuICAgICAgICBjb25zdCBwYWdlID0gYXdhaXQgcGRmLmdldFBhZ2UoMSk7XG5cbiAgICAgICAgY29uc3Qgdmlld1BvcnRQYXJhbWV0ZXJzID0geyBzY2FsZTogMSB9O1xuICAgICAgICBjb25zdCB2aWV3cG9ydCA9IHBhZ2UuZ2V0Vmlld3BvcnQodmlld1BvcnRQYXJhbWV0ZXJzKTtcblxuICAgICAgICB0aGlzLmNhbnZhcy5oZWlnaHQgPSB2aWV3cG9ydC5oZWlnaHQ7XG4gICAgICAgIHRoaXMuY2FudmFzLndpZHRoID0gdmlld3BvcnQud2lkdGg7XG5cbiAgICAgICAgY29uc3Qgc2l6ZSA9IHRoaXMuZ2V0U2l6ZUZvckNhbnZhcyh2aWV3cG9ydC53aWR0aCwgdmlld3BvcnQuaGVpZ2h0KTtcbiAgICAgICAgY29uc29sZS5sb2coc2l6ZSk7XG4gICAgICAgIHRoaXMuY2FudmFzU2l6ZSA9IHNpemU7XG5cbiAgICAgICAgdGhpcy5jYW52YXNab29tID0gc2l6ZS53IC8gdmlld3BvcnQud2lkdGg7XG5cbiAgICAgICAgY29uc3QgY29udGV4dCA9IHRoaXMuY2FudmFzLmdldENvbnRleHQoJzJkJykgYXMgQ2FudmFzUmVuZGVyaW5nQ29udGV4dDJEO1xuICAgICAgICBjb25zdCByZW5kZXJDb250ZXh0ID0ge1xuICAgICAgICAgICAgY2FudmFzQ29udGV4dDogY29udGV4dCxcbiAgICAgICAgICAgIHZpZXdwb3J0LFxuICAgICAgICB9O1xuICAgICAgICBjb25zdCByZW5kZXJUYXNrID0gcGFnZS5yZW5kZXIocmVuZGVyQ29udGV4dCkucHJvbWlzZTtcblxuICAgICAgICByZW5kZXJUYXNrLnRoZW4oKCkgPT4gY29uc29sZS5sb2coJ1BhZ2UgcmVuZGVyZWQnKSk7XG5cbiAgICAgICAgLy8gY29uc3QgcmVzID0gY2FudmFzLnRvRGF0YVVSTCgpO1xuICAgICAgICAvLyBpZiAocGRmICE9IG51bGwpIHBkZi5kZXN0cm95KCk7XG4gICAgICAgIC8vIHJldHVybiByZXM7XG4gICAgfVxuXG4gICAgLyoqIFVzZXIgY2xpY2sgdG8gdXNlciBTeW1tZXRyeSBWZXJ0aWNhbCAqL1xuICAgIG9uUmVmbGVjdFYoKSB7XG4gICAgICAgIHRoaXMucmVmbGVjdFYgPSAhdGhpcy5yZWZsZWN0VjtcbiAgICAgICAgdGhpcy5jb25maWd1cmVDYW52YXMoKTtcbiAgICB9XG5cbiAgICAvKiogVXNlciBjbGljayB0byB1c2VyIFN5bW1ldHJ5IEhvcml6b250YWwgKi9cbiAgICBvblJlZmxlY3RIKCkge1xuICAgICAgICB0aGlzLnJlZmxlY3RIID0gIXRoaXMucmVmbGVjdEg7XG4gICAgICAgIHRoaXMuY29uZmlndXJlQ2FudmFzKCk7XG4gICAgfVxuXG4gICAgLyoqICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKipcbiAgICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBNQVRURVJQT1JUXG4gICAgICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqICovXG5cbiAgICAvKiogTGF1bmNoIG1hdHRlcnBvcnQgKi9cbiAgICBhc3luYyBsYXVuY2hWaWV3ZXIoKSB7XG4gICAgICAgIGF3YWl0IHRoaXMubWF0dGVycG9ydEltcG9ydFNlcnZpY2UuaW5pdFNka0Zvck1vZGVsKHRoaXMuY2hvc2VuUGxhbi5tb2RlbDNkKTtcblxuICAgICAgICBjb25zdCB7IHNkayB9ID0gdGhpcy5tYXR0ZXJwb3J0SW1wb3J0U2VydmljZTtcbiAgICAgICAgdGhpcy5mbG9vcnMgPSBPYmplY3QudmFsdWVzKHRoaXMubWF0dGVycG9ydEltcG9ydFNlcnZpY2UuZmxvb3JzKTtcbiAgICAgICAgLy8gY29uc29sZS5sb2codGhpcy5mbG9vcnMpO1xuICAgICAgICBzZXRUaW1lb3V0KGFzeW5jICgpID0+IHtcbiAgICAgICAgICAgIC8qKiBNb3ZlIEZsb29yIG1vZGUgKi9cbiAgICAgICAgICAgIHNkay5Nb2RlLm1vdmVUbyhzZGsuTW9kZS5Nb2RlLkZMT09SUExBTikudGhlbihhc3luYyAobmV4dE1vZGUpID0+IHtcbiAgICAgICAgICAgICAgICAvKiogRGlzcGxheSB0aGUgY29ycmVjdCBmbG9vciBmb3IgdGhlIHBsYW4gKi9cbiAgICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBtYXR0ZXJwb3J0Rmxvb3IgPSB0aGlzLmNob3NlblBsYW4uem9uZS5tZXRhZGF0YSA/XG4gICAgICAgICAgICAgICAgICAgICAgICBKU09OLnBhcnNlKHRoaXMuY2hvc2VuUGxhbi56b25lLm1ldGFkYXRhKS5tYXR0ZXJwb3J0Rmxvb3JTZXF1ZW5jZSA6IG51bGw7XG4gICAgICAgICAgICAgICAgICAgIGF3YWl0IHRoaXMubWF0dGVycG9ydEltcG9ydFNlcnZpY2UubW92ZVRvRmxvb3IodGhpcy5jaG9zZW5QbGFuLnpvbmUubmFtZSwgbWF0dGVycG9ydEZsb29yKTtcblxuICAgICAgICAgICAgICAgICAgICAvKiogV2hlbiB0aGUgdXNlciB0cnkgdG8gY2hhbmdlIHRoZSB2aWV3IG1vZGUgd2Ugc2V0IGl0IGJhY2sgdG8gZmxvb3JwYW4gKi9cbiAgICAgICAgICAgICAgICAgICAgc2RrLm9uKHNkay5Nb2RlLkV2ZW50LkNIQU5HRV9FTkQsIChvbGRNb2RlLCBuZXdNb2RlKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAobmV3TW9kZSAhPT0gc2RrLk1vZGUuTW9kZS5GTE9PUlBMQU4pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZGsuTW9kZS5tb3ZlVG8oc2RrLk1vZGUuTW9kZS5GTE9PUlBMQU4sIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdHJhbnNpdGlvbjogJ3RyYW5zaXRpb24uaW5zdGFudCcsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIH0gY2F0Y2gge1xuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmxvZygnY291bGRub3QgbW92ZSB0byBmbG9vcicpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAvKiogV2UgY2FuIGRpc3BsYXkgdGhlIG1hdHRlcnBvcnQgdmlldyBub3cgKi9cbiAgICAgICAgICAgIHRoaXMubG9hZGluZyA9IGZhbHNlO1xuICAgICAgICB9LCAxMDAwKTtcblxuICAgICAgICAvKiogVXBkYXRlIGN1cnJlbnQgY2FtZXJhIHBvc2UgYW5kIHJvdGF0aW9uICovXG4gICAgICAgIHNkay5DYW1lcmEucG9zZS5zdWJzY3JpYmUoKGV2ZW50KSA9PiB7XG4gICAgICAgICAgICAvKiogV2UgdXBkYXRlIG9ubHkgaWYgdGhlIHVzZXIgaXMgbm90IGNoYW5naW5nIHRoZSByb3RhdGlvbiB3aXRoIHRoZSA8aW5wdXQ+IHJhbmdlLCB0byBub3Qgb3ZlcnJpZGUgdGhlIDxpbnB1dD4gdmFsdWUgKi9cbiAgICAgICAgICAgIGlmICghdGhpcy5pc1JvdGF0aW5nUmFuZ2UpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnJvdGF0aW9uID0gZXZlbnQucm90YXRpb24ueSArIDE4MDtcbiAgICAgICAgICAgICAgICB0aGlzLnByZXZSb3RhdGlvbiA9IHRoaXMucm90YXRpb247XG4gICAgICAgICAgICAgICAgdGhpcy5jYW1lcmFQb3NlID0gZXZlbnQ7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKiBXaGVuIHRoZSA8aW5wdXQ+IHJhbmdlLCBmb3Igcm90YXRpb24sIGNoYW5nZSAqL1xuICAgIGFzeW5jIG9uUm90YXRpb25DaGFuZ2UoKSB7XG4gICAgICAgIGNvbnN0IHJvdGF0aW9uRGVsdGEgPSB0aGlzLnJvdGF0aW9uIC0gdGhpcy5wcmV2Um90YXRpb247XG4gICAgICAgIHRoaXMucHJldlJvdGF0aW9uID0gdGhpcy5yb3RhdGlvbjtcblxuICAgICAgICAvKiogU2VuZCB0aGUgcm90YXRpb25EZWx0YSB0byB0aCBxdWV1ZSBldmVudCBpbiBvcmRlciB0byBiZSBzZW5kIHRvIG1hdHRlcnBvcnQgKi9cbiAgICAgICAgdGhpcy5yb3RhdGluZ1F1ZXVlRXZlbnQucHVzaChyb3RhdGlvbkRlbHRhKTtcblxuICAgICAgICAvKiogU3RhcnQgdG8gcHJvY2VzcyB0aGUgcXVldWUsIGlmIGl0J3MgdGhlIGZpcnN0IGV2ZW50ICovXG4gICAgICAgIGlmICghdGhpcy5pc1JvdGF0aW5nUmFuZ2UpIHtcbiAgICAgICAgICAgIHRoaXMuaXNSb3RhdGluZ1JhbmdlID0gdHJ1ZTtcbiAgICAgICAgICAgIHRoaXMucHJvY2Vzc1JvdGF0aW5nUXVldWVFdmVudCgpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqIFByb2Nlc3MgdGhlIHJvdGF0aW5nIGV2ZW50IHF1ZXVlLCBzZW5kIGV2ZW50IG9uZSBieSBvbmUgdG8gbWF0dGVycG9ydCAgKi9cbiAgICBhc3luYyBwcm9jZXNzUm90YXRpbmdRdWV1ZUV2ZW50KCkge1xuICAgICAgICBjb25zdCB7IHNkayB9ID0gdGhpcy5tYXR0ZXJwb3J0SW1wb3J0U2VydmljZTtcblxuICAgICAgICAvKiogV2hpbGUgdGhlIHF1ZXVlIGlzIG5vdCBlbXB0eSAqL1xuICAgICAgICB3aGlsZSAodGhpcy5yb3RhdGluZ1F1ZXVlRXZlbnQubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgLyoqIFJvdGF0ZSBtYXR0ZXJwb3J0IGJ5IGRlbHRhUm90YXRpb24gYW5kIHJlbW92ZSBldmVudCBmcm9tIHF1ZXVlICovXG4gICAgICAgICAgICBhd2FpdCBzZGsuQ2FtZXJhLnJvdGF0ZSh0aGlzLnJvdGF0aW5nUXVldWVFdmVudC5zaGlmdCgpLCAwLCB7XG4gICAgICAgICAgICAgICAgc3BlZWQ6IDM2MCxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG5cbiAgICAgICAgLyoqIFdoZW4gdGhlIHF1ZXVlIGlzIGVtcHR5LCB0aGVuIHRoZSB1c2VyIGlzIG5vdCByb3RhdGluZyB3aXRoIHRoZSA8aW5wdXQ+IHJhbmdlIGFueW1vcmUgKi9cbiAgICAgICAgdGhpcy5pc1JvdGF0aW5nUmFuZ2UgPSBmYWxzZTtcbiAgICB9XG5cbiAgICAvKiogKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKlxuICAgICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFVTRVIgQUNUSU9OU1xuICAgICAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiAqL1xuXG4gICAgLyoqIFByZXZpZXcgY2FsaWJyYXRpb24gKi9cbiAgICBhc3luYyBvblByZXZpZXcoKSB7XG4gICAgICAgIHRoaXMucHJldmlldyA9IHRydWU7XG4gICAgICAgIC8qKiBQbGFjZSBzd2VlcHMgKi9cbiAgICAgICAgdGhpcy5vblBsYWNlU3dlZXBzKCk7XG4gICAgfVxuXG4gICAgYXN5bmMgY2FsaWJyYXRlKCkge1xuICAgICAgICBjb25zdCBbbmF2aWdhdGlvbl0gPSB0aGlzLmN1cnJlbnROYXZpZ2F0aW9ucztcbiAgICAgICAgY29uc3QgcG9zaXRpb24gPSBKU09OLnBhcnNlKG5hdmlnYXRpb24ucG9zaXRpb24pO1xuICAgICAgICB0aGlzLmZpcnN0TWFya1BsYW4gPVxuICAgICAgICAgICAgYXdhaXQgdGhpcy5tYXR0ZXJwb3J0SW1wb3J0U2VydmljZS5zZGsuUmVuZGVyZXIuZ2V0U2NyZWVuUG9zaXRpb24oe1xuICAgICAgICAgICAgICAgIHg6IHBvc2l0aW9uLngsXG4gICAgICAgICAgICAgICAgeTogcG9zaXRpb24ueSxcbiAgICAgICAgICAgICAgICB6OiBwb3NpdGlvbi56LFxuICAgICAgICAgICAgfSk7XG4gICAgICAgIHRoaXMuc2Vjb25kTWFya1BsYW4gPVxuICAgICAgICAgICAgYXdhaXQgdGhpcy5tYXR0ZXJwb3J0SW1wb3J0U2VydmljZS5zZGsuUmVuZGVyZXIuZ2V0U2NyZWVuUG9zaXRpb24oe1xuICAgICAgICAgICAgICAgIHg6IHBvc2l0aW9uLngsXG4gICAgICAgICAgICAgICAgeTogMCxcbiAgICAgICAgICAgICAgICB6OiAwLFxuICAgICAgICAgICAgfSk7XG4gICAgICAgIGNvbnN0IGRlbHRhWlZpc2l0ID0gMCAtIHBvc2l0aW9uLno7XG4gICAgICAgIGxldCBkZWx0YVhQbGFuID0gdGhpcy5zZWNvbmRNYXJrUGxhbi54IC0gdGhpcy5maXJzdE1hcmtQbGFuLng7XG4gICAgICAgIGlmIChkZWx0YVhQbGFuID09PSAwKSB7XG4gICAgICAgICAgICAvLyBjb25zb2xlLmxvZyhcIndlIG1vdmVkIGFsb25nIFkgYXhpcyBvbiBQbGFuXCIpO1xuICAgICAgICAgICAgY29uc3QgZGVsdGFZUGxhbiA9IHRoaXMuc2Vjb25kTWFya1BsYW4ueSAtIHRoaXMuZmlyc3RNYXJrUGxhbi55O1xuICAgICAgICAgICAgdGhpcy5jYWxpYnJhZ2UubmFtZVlBeGlzID0gJ3onO1xuICAgICAgICAgICAgdGhpcy5jYWxpYnJhZ2UubmFtZVhBeGlzID0gJ3gnO1xuICAgICAgICAgICAgdGhpcy5jYWxpYnJhZ2Uub2Zmc2V0WSA9IHRoaXMuc2Vjb25kTWFya1BsYW4ueTtcbiAgICAgICAgICAgIHRoaXMuY2FsaWJyYWdlLnNjYWxlWSA9IGRlbHRhWVBsYW4gLyBkZWx0YVpWaXNpdDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8vIGNvbnNvbGUubG9nKFwiIHdlIG1vdmVkIGFsb25nIFggYXhpcyBvbiBQbGFuXCIpO1xuICAgICAgICAgICAgdGhpcy5jYWxpYnJhZ2UubmFtZVlBeGlzID0gJ3gnO1xuICAgICAgICAgICAgdGhpcy5jYWxpYnJhZ2UubmFtZVhBeGlzID0gJ3onO1xuICAgICAgICAgICAgdGhpcy5jYWxpYnJhZ2Uub2Zmc2V0WCA9IHRoaXMuc2Vjb25kTWFya1BsYW4ueDtcbiAgICAgICAgICAgIHRoaXMuY2FsaWJyYWdlLnNjYWxlWCA9IGRlbHRhWFBsYW4gLyBkZWx0YVpWaXNpdDtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCB0aGlyZE1hcmtQbGFuID1cbiAgICAgICAgICAgIGF3YWl0IHRoaXMubWF0dGVycG9ydEltcG9ydFNlcnZpY2Uuc2RrLlJlbmRlcmVyLmdldFNjcmVlblBvc2l0aW9uKHtcbiAgICAgICAgICAgICAgICB4OiAwLFxuICAgICAgICAgICAgICAgIHk6IDAsXG4gICAgICAgICAgICAgICAgejogcG9zaXRpb24ueixcbiAgICAgICAgICAgIH0pO1xuICAgICAgICBjb25zdCBkZWx0YVhWaXNpdCA9IDAgLSBwb3NpdGlvbi54O1xuICAgICAgICBpZiAoZGVsdGFYUGxhbiA9PT0gMCkge1xuICAgICAgICAgICAgLy8gY29uc29sZS5sb2coXCIgd2UgbW92ZWQgYWxvbmcgWCBheGlzIG9uIFBsYW5cIik7XG4gICAgICAgICAgICBkZWx0YVhQbGFuID0gdGhpcmRNYXJrUGxhbi54IC0gdGhpcy5maXJzdE1hcmtQbGFuLng7XG4gICAgICAgICAgICB0aGlzLmNhbGlicmFnZS5vZmZzZXRYID0gdGhpcmRNYXJrUGxhbi54O1xuICAgICAgICAgICAgdGhpcy5jYWxpYnJhZ2Uuc2NhbGVYID0gZGVsdGFYUGxhbiAvIGRlbHRhWFZpc2l0O1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgY29uc3QgZGVsdGFZUGxhbiA9IHRoaXJkTWFya1BsYW4ueSAtIHRoaXMuZmlyc3RNYXJrUGxhbi55O1xuICAgICAgICAgICAgdGhpcy5jYWxpYnJhZ2Uub2Zmc2V0WSA9IHRoaXJkTWFya1BsYW4ueTtcbiAgICAgICAgICAgIHRoaXMuY2FsaWJyYWdlLnNjYWxlWSA9IGRlbHRhWVBsYW4gLyBkZWx0YVhWaXNpdDtcbiAgICAgICAgfVxuXG4gICAgICAgIC8qKiBUYWtlIGNvbnNpZGlyYXRpb24gb2YgcGFuIGFuZCB6b29tIG9mIHBsYW4gb24gY2FudmFzICovXG4gICAgICAgIGNvbnN0IHRyYW5zZm9ybUluZm8gPSB0aGlzLnBhbnpvb20uZ2V0VHJhbnNmb3JtKCk7XG4gICAgICAgIGNvbnN0IHsgc2NhbGUsIHgsIHkgfSA9IHRyYW5zZm9ybUluZm87XG4gICAgICAgIC8vIGNvbnNvbGUubG9nKHRyYW5zZm9ybUluZm8pO1xuICAgICAgICB0aGlzLmNhbGlicmFnZS5vZmZzZXRYUGxhbiA9IHg7XG4gICAgICAgIHRoaXMuY2FsaWJyYWdlLm9mZnNldFlQbGFuID0geTtcbiAgICAgICAgdGhpcy5jYWxpYnJhZ2Uuc2NhbGVQbGFuID0gc2NhbGU7XG4gICAgICAgIGNvbnNvbGUubG9nKHRoaXMuY2FsaWJyYWdlKTtcbiAgICB9XG5cbiAgICAvKiogUGxhY2Ugc3dlZXBzICovXG4gICAgYXN5bmMgb25QbGFjZVN3ZWVwcygpIHtcbiAgICAgICAgLyoqIERpc3BsYXkgYWxsIHNjYW4gKi9cbiAgICAgICAgY29uc3Qgem9uZSA9IGF3YWl0IHRoaXMuem9uZVNlcnZpY2UuZ2V0Wm9uZSh0aGlzLmNob3NlblBsYW4uem9uZUlEKTtcblxuICAgICAgICBpZiAoem9uZSkge1xuICAgICAgICAgICAgdGhpcy5jdXJyZW50Wm9uZSA9IHpvbmU7XG4gICAgICAgICAgICBjb25zdCBuYXZpZ2F0aW9ucyA9IGF3YWl0IHRoaXMubmF2aWdhdGlvblNlcnZpY2UuZ2V0TmF2aWdhdGlvbnNGb3Jab25lKFxuICAgICAgICAgICAgICAgIHRoaXMuY3VycmVudFpvbmVcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICB0aGlzLmN1cnJlbnROYXZpZ2F0aW9ucyA9IG5hdmlnYXRpb25zO1xuICAgICAgICAgICAgYXdhaXQgdGhpcy5jYWxpYnJhdGUoKTtcbiAgICAgICAgICAgIGlmIChuYXZpZ2F0aW9ucy5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICAgICAgZm9yIChjb25zdCBuYXZpZ2F0aW9uIG9mIG5hdmlnYXRpb25zKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHRlc3RQb3NpdGlvbiA9IEpTT04ucGFyc2UobmF2aWdhdGlvbi5wb3NpdGlvbik7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHBvc2l0aW9uWCA9XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNhbGlicmFnZS5uYW1lWEF4aXMgPT09ICd4JyA/IHRlc3RQb3NpdGlvbi54IDogdGVzdFBvc2l0aW9uLno7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHBvc2l0aW9uWSA9XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNhbGlicmFnZS5uYW1lWUF4aXMgPT09ICd4JyA/IHRlc3RQb3NpdGlvbi54IDogdGVzdFBvc2l0aW9uLno7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHRlc3RYID1cbiAgICAgICAgICAgICAgICAgICAgICAgIHBvc2l0aW9uWCAqIHRoaXMuY2FsaWJyYWdlLnNjYWxlWCArIHRoaXMuY2FsaWJyYWdlLm9mZnNldFg7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHRlc3RZID1cbiAgICAgICAgICAgICAgICAgICAgICAgIHBvc2l0aW9uWSAqIHRoaXMuY2FsaWJyYWdlLnNjYWxlWSArIHRoaXMuY2FsaWJyYWdlLm9mZnNldFk7XG4gICAgICAgICAgICAgICAgICAgIC8vIGNvbnNvbGUubG9nKFwidGVzdCBwb3NpdGlvbiBHUkVFTlwiLCB0ZXN0WCwgdGVzdFkpO1xuICAgICAgICAgICAgICAgICAgICBjb25zdCB0cmFuc2Zvcm1lZFggPVxuICAgICAgICAgICAgICAgICAgICAgICAgKHRlc3RYIC0gdGhpcy5jYWxpYnJhZ2Uub2Zmc2V0WFBsYW4pIC8gdGhpcy5jYWxpYnJhZ2Uuc2NhbGVQbGFuOyAvLyB3ZSBhcmUgdW5kb2luZyB0aGUgcGFuIGFuZCB6b29tXG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHRyYW5zZm9ybWVkWSA9XG4gICAgICAgICAgICAgICAgICAgICAgICAodGVzdFkgLSB0aGlzLmNhbGlicmFnZS5vZmZzZXRZUGxhbikgLyB0aGlzLmNhbGlicmFnZS5zY2FsZVBsYW47XG4gICAgICAgICAgICAgICAgICAgIHRoaXMucG9zaXRpb25zLnB1c2goe1xuICAgICAgICAgICAgICAgICAgICAgICAgbmF2SUQ6IG5hdmlnYXRpb24uaWQsXG4gICAgICAgICAgICAgICAgICAgICAgICBwbGFuSUQ6IHRoaXMuY2hvc2VuUGxhbi5pZCxcbiAgICAgICAgICAgICAgICAgICAgICAgIHg6IHRyYW5zZm9ybWVkWCxcbiAgICAgICAgICAgICAgICAgICAgICAgIHk6IHRyYW5zZm9ybWVkWSxcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGljb25TaXplID0gMzAgKiB0aGlzLmNhbGlicmFnZS5zY2FsZVBsYW47XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHNoaWZ0ID0gaWNvblNpemUgLyAyO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmRyYXdJbWFnZShcbiAgICAgICAgICAgICAgICAgICAgICAgICdodHRwczovL2FwaS5pY29uaWZ5LmRlc2lnbi9tZGk6YWRqdXN0LnN2Zz9jb2xvcj1ncmVlbiZoZWlnaHQ9MzAmd2lkdGg9MzAnLFxuICAgICAgICAgICAgICAgICAgICAgICAgdHJhbnNmb3JtZWRYIC0gc2hpZnQsXG4gICAgICAgICAgICAgICAgICAgICAgICB0cmFuc2Zvcm1lZFkgLSBzaGlmdCxcbiAgICAgICAgICAgICAgICAgICAgICAgIHRydWVcbiAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKiogU2F2ZSBjYWxpYnJhdGlvbiAqL1xuICAgIGFzeW5jIG9uU2F2ZSgpIHtcbiAgICAgICAgaWYgKHRoaXMuY3VycmVudFpvbmUpIHtcbiAgICAgICAgICAgIC8qKiBOb3JtYWxpemUgd2l0aCB0aGUgem9vbSAqL1xuICAgICAgICAgICAgLy8gdGhpcy5jYWxpYnJhZ2Uub2Zmc2V0WCAvPSB0aGlzLmNhbnZhc1pvb207XG4gICAgICAgICAgICAvLyB0aGlzLmNhbGlicmFnZS5vZmZzZXRZIC89IHRoaXMuY2FudmFzWm9vbTtcbiAgICAgICAgICAgIC8vIHRoaXMuY2FsaWJyYWdlLnggLz0gdGhpcy5jYW52YXNab29tO1xuICAgICAgICAgICAgLy8gdGhpcy5jYWxpYnJhZ2UueSAvPSB0aGlzLmNhbnZhc1pvb207XG4gICAgICAgICAgICB0aGlzLmNhbGlicmFnZS5uZXcgPSB0cnVlO1xuICAgICAgICAgICAgdGhpcy5jYWxpYnJhZ2UuaW1nV2lkdGggPSB0aGlzLmNhbnZhc1NpemUudztcbiAgICAgICAgICAgIHRoaXMuY2FsaWJyYWdlLmltZ0hlaWdodCA9IHRoaXMuY2FudmFzU2l6ZS5oO1xuXG4gICAgICAgICAgICBhd2FpdCB0aGlzLnBsYW5TZXJ2aWNlLnVwZGF0ZVBsYW4oe1xuICAgICAgICAgICAgICAgIGlkOiB0aGlzLmNob3NlblBsYW4uaWQsXG4gICAgICAgICAgICAgICAgY2FsaWJyYXRpb246IEpTT04uc3RyaW5naWZ5KHRoaXMuY2FsaWJyYWdlKSxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgYXdhaXQgUHJvbWlzZS5hbGwoXG4gICAgICAgICAgICAgICAgdGhpcy5wb3NpdGlvbnMubWFwKGFzeW5jIChwb3NpdGlvbikgPT4ge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCB7IG5hdklEIH0gPSBwb3NpdGlvbjtcbiAgICAgICAgICAgICAgICAgICAgZGVsZXRlIHBvc2l0aW9uLm5hdklEO1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBuYXYgPSB0aGlzLmN1cnJlbnROYXZpZ2F0aW9ucy5maW5kKChfbmF2KSA9PiBfbmF2LmlkID09PSBuYXZJRCk7XG4gICAgICAgICAgICAgICAgICAgIGxldCBwb3NpdGlvbnNEYXRhVG9VcGRhdGU7XG4gICAgICAgICAgICAgICAgICAgIGlmIChuYXYucG9zaXRpb25PblBsYW4pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHBvc2l0aW9uT25QbGFuID0gbmF2LnBvc2l0aW9uT25QbGFuLm1hcCgoZW50cnkpID0+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgSlNPTi5wYXJzZShlbnRyeSlcbiAgICAgICAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBwb3NpdGlvbkZvckN1cnJlbnRQbGFuID0gcG9zaXRpb25PblBsYW4uZmluZChcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAoZW50cnkpID0+IGVudHJ5LnBsYW5JRCA9PT0gdGhpcy5jaG9zZW5QbGFuLmlkXG4gICAgICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHBvc2l0aW9uRm9yQ3VycmVudFBsYW4pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwb3NpdGlvbk9uUGxhbi5zcGxpY2UoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBvc2l0aW9uT25QbGFuLmluZGV4T2YocG9zaXRpb25Gb3JDdXJyZW50UGxhbiksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDEsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBvc2l0aW9uXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcG9zaXRpb25PblBsYW4ucHVzaChwb3NpdGlvbik7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBwb3NpdGlvbnNEYXRhVG9VcGRhdGUgPSBbLi4ucG9zaXRpb25PblBsYW5dO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgcG9zaXRpb25zRGF0YVRvVXBkYXRlID0gW3Bvc2l0aW9uXTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAvLyBjb25zb2xlLmxvZyhwb3NpdGlvbnNEYXRhVG9VcGRhdGUpO1xuICAgICAgICAgICAgICAgICAgICBhd2FpdCB0aGlzLm5hdmlnYXRpb25TZXJ2aWNlLnVwZGF0ZU5hdmlnYXRpb24oe1xuICAgICAgICAgICAgICAgICAgICAgICAgaWQ6IG5hdklELFxuICAgICAgICAgICAgICAgICAgICAgICAgcG9zaXRpb25PblBsYW46IHBvc2l0aW9uc0RhdGFUb1VwZGF0ZS5tYXAoKGVudHJ5KSA9PlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIEpTT04uc3RyaW5naWZ5KGVudHJ5KVxuICAgICAgICAgICAgICAgICAgICAgICAgKSxcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5tYXR0ZXJwb3J0SW1wb3J0U2VydmljZS5yZW1vdmVGcmFtZSgpO1xuXG4gICAgICAgIHRoaXMucm91dGVyLm5hdmlnYXRlKFsnL2Rhc2hib2FyZC9sb2NhbGlzYXRpb24nLCB0aGlzLnNwYWNlSUQsICdwbGFucyddKTtcbiAgICAgICAgYWxlcnQodGhpcy50cmFuc2xhdGUuaW5zdGFudCgnY2FsaWJyYXRpb24uc3VjY2VzcycpKTtcbiAgICB9XG5cbiAgICAvKiogUmVzZXQgdGhlIGNhbnZhcyAqL1xuICAgIG9uUmVzZXQoKSB7XG4gICAgICAgIHRoaXMucmVmbGVjdEggPSBmYWxzZTtcbiAgICAgICAgdGhpcy5yZWZsZWN0ViA9IGZhbHNlO1xuICAgICAgICB0aGlzLnByZXZpZXcgPSBmYWxzZTtcblxuICAgICAgICB0aGlzLmNvbmZpZ3VyZUNhbnZhcygpO1xuICAgIH1cblxuICAgIC8qKiBDYW5jZWwsIGxlYXZlICovXG4gICAgb25DYW5jZWwoKSB7XG4gICAgICAgIHRoaXMubWF0dGVycG9ydEltcG9ydFNlcnZpY2UucmVtb3ZlRnJhbWUoKTtcbiAgICAgICAgdGhpcy5yb3V0ZXIubmF2aWdhdGUoWycvZGFzaGJvYXJkL2xvY2FsaXNhdGlvbicsIHRoaXMuc3BhY2VJRCwgJ3BsYW5zJ10pO1xuICAgICAgICBhbGVydCh0aGlzLnRyYW5zbGF0ZS5pbnN0YW50KCdjYWxpYnJhdGlvbi5jYW5jZWxlZCcpKTtcbiAgICB9XG5cbiAgICBhc3luYyBvbkZsb29yQ2xpY2soZmxvb3IpIHtcbiAgICAgICAgdGhpcy5jdXJyZW50Rmxvb3IgPSBmbG9vcjtcbiAgICAgICAgYXdhaXQgdGhpcy5tYXR0ZXJwb3J0SW1wb3J0U2VydmljZS5tb3ZlVG9GbG9vcihmbG9vci5pZCk7XG4gICAgfVxuXG4gICAgb25BY3RpdmF0ZVpvb21DaGFuZ2UoKSB7XG4gICAgICAgIHRoaXMuem9vbUNhbkJlQ2hhbmdlZCA9ICF0aGlzLnpvb21DYW5CZUNoYW5nZWQ7XG4gICAgICAgIGNvbnN0IGlmcmFtZSA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoJyN2aWV3ZXItZnJhbWUnKSBhcyBIVE1MRWxlbWVudDtcbiAgICAgICAgaWYgKGlmcmFtZSkge1xuICAgICAgICAgICAgaWZyYW1lLnN0eWxlLnpJbmRleCA9IHRoaXMuem9vbUNhbkJlQ2hhbmdlZCA/ICcxJyA6ICcwJztcbiAgICAgICAgfVxuICAgIH1cbn1cbiIsIjxkaXYgY2xhc3M9XCJyb3cgbXQtM1wiPlxuICAgIDxkaXYgY2xhc3M9XCJjb2xcIj5cbiAgICAgICAgPGRpdiBjbGFzcz1cIm0tM1wiPlxuICAgICAgICAgICAgPGxpYi10YWItbmF2aWdhdGlvbiBbbWVudUl0ZW1zXT0nbWVudUl0ZW1zJz48L2xpYi10YWItbmF2aWdhdGlvbj5cbiAgICAgICAgPC9kaXY+XG4gICAgPC9kaXY+XG48L2Rpdj5cblxuPGRpdiBpZD1cInJvd0NhbnZhc1wiPlxuICAgIDxkaXYgI2NhbnZhc0RpdiBpZD1cImNhbnZhc0RpdlwiPlxuXG4gICAgICAgIDxkaXYgaWQ9XCJ2aWV3ZXItZnJhbWVcIiBbc3R5bGUucG9pbnRlci1ldmVudHNdPVwiem9vbUNhbkJlQ2hhbmdlZD8nYXV0byc6J25vbmUnXCI+XG4gICAgICAgICAgICA8IS0tIDxkaXYgY2xhc3M9XCJibHVyXCI+PC9kaXY+IC0tPlxuICAgICAgICA8L2Rpdj5cbiAgICAgICAgPGNhbnZhcyBpZD1cImNhbnZhc1wiIFtuZ1N0eWxlXT1cInsnb3BhY2l0eSc6IChwcmV2aWV3fHxsb2FkaW5nKSA/ICcxJyA6ICdjYWxjKCcgKyBvcGFjaXR5ICsgJy8gMTAwKSd9XCI+PC9jYW52YXM+XG4gICAgPC9kaXY+XG5cbiAgICA8ZGl2IGNsYXNzPVwiY2FsaWJyYXRpb24tdG9vbHMgY29udGFpbmVyLWZsdWlkXCIgKm5nSWY9XCIhKHByZXZpZXcgfHwgbG9hZGluZylcIj5cbiAgICAgICAgPGgxPnt7J0NhbGlicmF0aW9uIHRvb2wnIHwgdHJhbnNsYXRlfX08L2gxPlxuICAgICAgICA8ZGl2IGNsYXNzPVwidG9vbFwiPlxuICAgICAgICAgICAgPGRpdiBjbGFzcz1cInJvdyBtcy0wIG1lLTAgbGVnZW5kXCI+XG4gICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImxlZ2VuZC1iYXItaW5kaWNhdG9yXCIgW25nU3R5bGVdPVwieydvcGFjaXR5JzogJ2NhbGMoJyArICgtKG9wYWNpdHktMTAwKSsxMCkgKyAnLyAxMDApJ31cIj5cbiAgICAgICAgICAgICAgICAgICAge3snTGVzcycgfCB0cmFuc2xhdGV9fTwvZGl2PlxuICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJsZWdlbmQtdGl0bGVcIj57eydQbGFuIE9wYWNpdHknIHwgdHJhbnNsYXRlIH19PC9kaXY+XG4gICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImxlZ2VuZC1iYXItaW5kaWNhdG9yXCIgW25nU3R5bGVdPVwieydvcGFjaXR5JzogJ2NhbGMoJyArIChvcGFjaXR5KzEwKSArICcvIDEwMCknfVwiPnt7J01vcmUnIHxcbiAgICAgICAgICAgICAgICAgICAgdHJhbnNsYXRlfX08L2Rpdj5cbiAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgPGRpdiBjbGFzcz1cInJvdyBtcy0wIG1lLTAgXCI+XG4gICAgICAgICAgICAgICAgPGlucHV0IFtkaXNhYmxlZF09XCJmYWxzZVwiIFtuZ01vZGVsT3B0aW9uc109XCJ7c3RhbmRhbG9uZTogdHJ1ZX1cIiBbKG5nTW9kZWwpXT1cIm9wYWNpdHlcIiB0eXBlPVwicmFuZ2VcIlxuICAgICAgICAgICAgICAgICAgICBjbGFzcz1cImZvcm0tcmFuZ2VcIiBtaW49XCIwXCIgbWF4PVwiMTAwXCIgdmFsdWU9XCI1MFwiIGlkPVwib3BhY2l0eVwiPlxuICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgIDwvZGl2PlxuICAgICAgICA8ZGl2IGNsYXNzPVwidG9vbFwiPlxuICAgICAgICAgICAgPGRpdiBjbGFzcz1cInJvdyBtcy0wIG1lLTAgXCI+XG4gICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImxhYmVsLWxlZ2VuZFwiPnt7J0NoYW5nZSBWaXNpdCBGbG9vcicgfCB0cmFuc2xhdGV9fTwvZGl2PlxuICAgICAgICAgICAgICAgIDxkaXYgbmdiRHJvcGRvd24gY2xhc3M9XCJkLWlubGluZS1ibG9jayBtcy0zXCI+XG4gICAgICAgICAgICAgICAgICAgIDxidXR0b24gY2xhc3M9XCJidG4gYnRuLWxhYmVsLWZpbGUgcm91bmRlZC1waWxsXCIgaWQ9XCJkcm9wZG93bkJhc2ljMVwiIG5nYkRyb3Bkb3duVG9nZ2xlPlxuICAgICAgICAgICAgICAgICAgICAgICAge3tjdXJyZW50Rmxvb3IgPyBjdXJyZW50Rmxvb3IuaWQgOiAoJ0Zsb29yJyB8IHRyYW5zbGF0ZSkgfX08L2J1dHRvbj5cbiAgICAgICAgICAgICAgICAgICAgPGRpdiBuZ2JEcm9wZG93bk1lbnUgYXJpYS1sYWJlbGxlZGJ5PVwiZHJvcGRvd25CYXNpYzFcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgIDxidXR0b24gbmdiRHJvcGRvd25JdGVtICpuZ0Zvcj1cImxldCBmbG9vciBvZiBmbG9vcnNcIiAoY2xpY2spPVwib25GbG9vckNsaWNrKGZsb29yKVwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHt7IGZsb29yLm5hbWUubGVuZ3RoID4gMCA/IGZsb29yLm5hbWUgOiAoJ0Zsb29yICcgKyBmbG9vci5pZCkgfX1cbiAgICAgICAgICAgICAgICAgICAgICAgIDwvYnV0dG9uPlxuICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgIDwvZGl2PlxuXG4gICAgICAgIDwvZGl2PlxuICAgICAgICA8ZGl2IGNsYXNzPVwidG9vbFwiPlxuICAgICAgICAgICAgPGRpdiBjbGFzcz1cInJvdyBtcy0wIG1lLTAgXCI+XG4gICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cInRvb2wtY2hlY2tib3gtY29udGFpbmVyXCI+XG4gICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJ0b29sLWNoZWNrYm94LXN1YmNvbnRhaW5lclwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImxhYmVsLWxlZ2VuZCBtZS0zXCI+e3snUGFuL1pvb20gVmlzaXQnIHwgdHJhbnNsYXRlfX0ge3t6b29tQ2FuQmVDaGFuZ2VkID8gXCJPTlwiIDpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBcIk9GRlwifX1cbiAgICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICAgICAgICAgICAgPGlucHV0IHR5cGU9XCJjaGVja2JveFwiIChjaGFuZ2UpPVwib25BY3RpdmF0ZVpvb21DaGFuZ2UoKVwiIHN0eWxlPVwibWFyZ2luLXRvcDogNXB4O1wiPlxuICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImNhcmQgYm9yZGVyLXdhcm5pbmcgbWItMyBtdC0zXCIgKm5nSWY9XCJ6b29tQ2FuQmVDaGFuZ2VkXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwiY2FyZC1ib2R5IHRleHQtd2FybmluZ1wiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxoNSBjbGFzcz1cImNhcmQtdGl0bGVcIj57e1wiY2FsaWJyYXRpb24ud2FpdC1tZXNzYWdlXCIgfCB0cmFuc2xhdGV9fTwvaDU+XG4gICAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgPC9kaXY+XG5cbiAgICAgICAgPGRpdiBjbGFzcz1cImFjdGlvblwiPlxuICAgICAgICAgICAgPGJ1dHRvbiB0eXBlPVwiYnV0dG9uXCIgY2xhc3M9XCJidG4gYnRuLW91dGxpbmUtcHJpbWFyeSByb3VuZGVkLXBpbGxcIiAoY2xpY2spPVwib25QcmV2aWV3KClcIlxuICAgICAgICAgICAgICAgIFtkaXNhYmxlZF09XCJ6b29tQ2FuQmVDaGFuZ2VkXCI+e3snUHJldmlldycgfCB0cmFuc2xhdGV9fTwvYnV0dG9uPlxuICAgICAgICAgICAgPGJ1dHRvbiB0eXBlPVwiYnV0dG9uXCIgY2xhc3M9XCJidG4gYnRuLW91dGxpbmUtcHJpbWFyeSByb3VuZGVkLXBpbGxcIiAoY2xpY2spPVwib25DYW5jZWwoKVwiPnt7J0NhbmNlbCcgfFxuICAgICAgICAgICAgICAgIHRyYW5zbGF0ZX19PC9idXR0b24+XG5cbiAgICAgICAgPC9kaXY+XG5cbiAgICA8L2Rpdj5cbiAgICA8ZGl2IGNsYXNzPVwiY2FsaWJyYXRpb24tdG9vbHMgY29udGFpbmVyLWZsdWlkXCIgKm5nSWY9XCJwcmV2aWV3XCI+XG4gICAgICAgIDxoMT57eydWYWxpZGF0aW9uJyB8IHRyYW5zbGF0ZX19PC9oMT5cbiAgICAgICAgPGRpdiBjbGFzcz1cImFjdGlvblwiPlxuICAgICAgICAgICAgPGJ1dHRvbiB0eXBlPVwiYnV0dG9uXCIgY2xhc3M9XCJidG4gYnRuLW91dGxpbmUtcHJpbWFyeSByb3VuZGVkLXBpbGxcIiAoY2xpY2spPVwib25TYXZlKClcIj57eydWYWxpZGF0ZScgfFxuICAgICAgICAgICAgICAgIHRyYW5zbGF0ZX19PC9idXR0b24+XG4gICAgICAgICAgICA8YnV0dG9uIHR5cGU9XCJidXR0b25cIiBjbGFzcz1cImJ0biBidG4tb3V0bGluZS1wcmltYXJ5IHJvdW5kZWQtcGlsbFwiIChjbGljayk9XCJvblJlc2V0KClcIj57eydSZXNldCcgfFxuICAgICAgICAgICAgICAgIHRyYW5zbGF0ZX19PC9idXR0b24+XG4gICAgICAgICAgICA8YnV0dG9uIHR5cGU9XCJidXR0b25cIiBjbGFzcz1cImJ0biBidG4tb3V0bGluZS1wcmltYXJ5IHJvdW5kZWQtcGlsbFwiIChjbGljayk9XCJvbkNhbmNlbCgpXCI+e3snQ2FuY2VsJyB8XG4gICAgICAgICAgICAgICAgdHJhbnNsYXRlfX08L2J1dHRvbj5cblxuICAgICAgICA8L2Rpdj5cbiAgICA8L2Rpdj5cblxuXG4gICAgPGRpdiBjbGFzcz1cImNhbGlicmF0aW9uLXRvb2xzIGNvbnRhaW5lci1mbHVpZFwiICpuZ0lmPVwibG9hZGluZ1wiPlxuICAgICAgICA8aDM+e3tcIldhaXRpbmcgZm9yIE1hdHRlcnBvcnRcIiB8IHRyYW5zbGF0ZX19Li4uPC9oMz5cbiAgICAgICAgPGRpdiBjbGFzcz1cImQtZmxleCBqdXN0aWZ5LWNvbnRlbnQtY2VudGVyXCI+XG4gICAgICAgICAgICA8ZGl2IGNsYXNzPVwic3Bpbm5lci1ib3JkZXJcIiByb2xlPVwic3RhdHVzXCI+XG4gICAgICAgICAgICAgICAgPHNwYW4gY2xhc3M9XCJ2aXN1YWxseS1oaWRkZW5cIj5Mb2FkaW5nLi4uPC9zcGFuPlxuICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgIDwvZGl2PlxuXG4gICAgPC9kaXY+XG48L2Rpdj4iXX0=
|