@smarterplan/ngx-smarterplan-locations 0.0.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. package/README.md +24 -0
  2. package/esm2020/lib/components/carousel/carousel.component.mjs +28 -0
  3. package/esm2020/lib/components/chevron/chevron.component.mjs +18 -0
  4. package/esm2020/lib/components/detail-location/detail-location.component.mjs +154 -0
  5. package/esm2020/lib/components/form-location/form-location.component.mjs +215 -0
  6. package/esm2020/lib/components/images/images.component.mjs +91 -0
  7. package/esm2020/lib/components/locations/locations.component.mjs +138 -0
  8. package/esm2020/lib/components/locations/map/map-popup/map-popup.component.mjs +66 -0
  9. package/esm2020/lib/components/locations/map/map.component.mjs +91 -0
  10. package/esm2020/lib/components/plans/calibration/calibration.component.mjs +484 -0
  11. package/esm2020/lib/components/plans/edit-plan/edit-plan.component.mjs +314 -0
  12. package/esm2020/lib/components/plans/plans.component.mjs +211 -0
  13. package/esm2020/lib/components/tab-navigation/tab-navigation.component.mjs +40 -0
  14. package/esm2020/lib/components/visits/visits.component.mjs +227 -0
  15. package/esm2020/lib/components/zones/add-zone/add-zone.component.mjs +592 -0
  16. package/esm2020/lib/components/zones/add-zone/selection/selection.component.mjs +77 -0
  17. package/esm2020/lib/components/zones/zones.component.mjs +214 -0
  18. package/esm2020/lib/helper.service.mjs +2 -0
  19. package/esm2020/lib/ngx-smarterplan-location-routing.module.mjs +49 -0
  20. package/esm2020/lib/ngx-smarterplan-locations.module.mjs +107 -0
  21. package/esm2020/lib/ngx-smarterplan-locations.service.mjs +14 -0
  22. package/esm2020/public-api.mjs +6 -0
  23. package/esm2020/smarterplan-ngx-smarterplan-locations.mjs +5 -0
  24. package/fesm2015/smarterplan-ngx-smarterplan-locations.mjs +3126 -0
  25. package/fesm2015/smarterplan-ngx-smarterplan-locations.mjs.map +1 -0
  26. package/fesm2020/smarterplan-ngx-smarterplan-locations.mjs +2987 -0
  27. package/fesm2020/smarterplan-ngx-smarterplan-locations.mjs.map +1 -0
  28. package/lib/components/carousel/carousel.component.d.ts +12 -0
  29. package/lib/components/chevron/chevron.component.d.ts +9 -0
  30. package/lib/components/detail-location/detail-location.component.d.ts +51 -0
  31. package/lib/components/form-location/form-location.component.d.ts +40 -0
  32. package/lib/components/images/images.component.d.ts +28 -0
  33. package/lib/components/locations/locations.component.d.ts +49 -0
  34. package/lib/components/locations/map/map-popup/map-popup.component.d.ts +22 -0
  35. package/lib/components/locations/map/map.component.d.ts +22 -0
  36. package/lib/components/plans/calibration/calibration.component.d.ts +140 -0
  37. package/lib/components/plans/edit-plan/edit-plan.component.d.ts +54 -0
  38. package/lib/components/plans/plans.component.d.ts +59 -0
  39. package/lib/components/tab-navigation/tab-navigation.component.d.ts +13 -0
  40. package/lib/components/visits/visits.component.d.ts +51 -0
  41. package/lib/components/zones/add-zone/add-zone.component.d.ts +154 -0
  42. package/lib/components/zones/add-zone/selection/selection.component.d.ts +44 -0
  43. package/lib/components/zones/zones.component.d.ts +66 -0
  44. package/lib/helper.service.d.ts +6 -0
  45. package/lib/ngx-smarterplan-location-routing.module.d.ts +7 -0
  46. package/lib/ngx-smarterplan-locations.module.d.ts +31 -0
  47. package/lib/ngx-smarterplan-locations.service.d.ts +6 -0
  48. package/package.json +39 -0
  49. package/public-api.d.ts +2 -0
  50. package/smarterplan-ngx-smarterplan-locations.d.ts +5 -0
@@ -0,0 +1,484 @@
1
+ import { Component, ViewChild } from '@angular/core';
2
+ import { getDocument } from "pdfjs-dist";
3
+ import { getMetaForImage } from 'ngx-smarterplan-core';
4
+ import panzoom from 'panzoom';
5
+ import * as i0 from "@angular/core";
6
+ import * as i1 from "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([
89
+ "/dashboard/localisation",
90
+ this.spaceID,
91
+ "plans",
92
+ ]);
93
+ }
94
+ }
95
+ /** **********************************************************************************************
96
+ * MENU NAV BAR
97
+ *********************************************************************************************** */
98
+ setupMenuItems() {
99
+ this.menuItems = [
100
+ { label: "Locations", url: "/localisation" },
101
+ {
102
+ label: this.currentSpace.name,
103
+ url: `/localisation/${this.spaceID}`,
104
+ },
105
+ {
106
+ label: "Plans",
107
+ url: `/localisation/${this.currentSpace.id}/plans`,
108
+ },
109
+ {
110
+ label: "Calibration",
111
+ url: `/localisation/${this.currentSpace.id}/plan-calibration?spaceID=${this.currentSpace.id}`,
112
+ },
113
+ ];
114
+ }
115
+ /** **********************************************************************************************
116
+ * CANVAS
117
+ *********************************************************************************************** */
118
+ /** Display the plan */
119
+ async configureCanvas() {
120
+ /** Get canvas */
121
+ if (!this.canvas) {
122
+ const canvas = document.querySelector("#canvas");
123
+ this.canvas = canvas;
124
+ }
125
+ if (!this.chosenPlanIsPdf) {
126
+ const image = await getMetaForImage(this.chosenPlan.filepath);
127
+ /** Compute the new size for the canvas/matterport, base on the dimension of the plan, keeping the ratio */
128
+ const size = this.getSizeForCanvas(image.width, image.height);
129
+ /** Compute the plan zoom ratio (use for the calibration later) */
130
+ this.canvasZoom = size.w / image.width;
131
+ this.resizeView(size);
132
+ /** Draw Plan on the canvas */
133
+ this.drawImage(this.chosenPlan.filepath);
134
+ }
135
+ else {
136
+ // TODO
137
+ this.pdfToCanvas();
138
+ }
139
+ }
140
+ /** Update size of the canvas/matterport */
141
+ resizeView(size) {
142
+ this.canvasDiv.nativeElement.style.width = `${size.w}px`;
143
+ this.canvasDiv.nativeElement.style.height = `${size.h}px`;
144
+ this.canvas.style.width = `${size.w}px`;
145
+ this.canvas.style.height = `${size.h}px`;
146
+ this.canvas.width = size.w;
147
+ this.canvas.height = size.h;
148
+ this.canvasSize = size;
149
+ }
150
+ /** Draw something on the canvas */
151
+ drawImage(url, x = 0, y = 0, icone = false) {
152
+ const image = new Image();
153
+ const size = this.canvasSize;
154
+ const context = this.canvas.getContext("2d");
155
+ /** Flip the context, for symmetry */
156
+ // if (this.reflectV) {
157
+ // context.translate(size.w, 0);
158
+ // context.scale(-1, 1);
159
+ // }
160
+ // if (this.reflectH) {
161
+ // context.translate(0, size.h);
162
+ // context.scale(1, -1);
163
+ // }
164
+ let imageWidth = size.w;
165
+ let imageHeight = size.h;
166
+ image.addEventListener("load", () => {
167
+ if (icone) {
168
+ imageWidth = image.width;
169
+ imageHeight = image.height;
170
+ }
171
+ context.drawImage(image, 0, 0, image.width, image.height, x, y, imageWidth, imageHeight);
172
+ });
173
+ image.src = url;
174
+ }
175
+ /** Get the size for the canvas, based on the plan size, keeping the ratio */
176
+ getSizeForCanvas(w, h) {
177
+ let canvasW = this.canvasDiv.nativeElement.offsetWidth;
178
+ let canvasH = this.canvasDiv.nativeElement.offsetHeight;
179
+ const imageRatio = w / h;
180
+ const canvasRatio = canvasW / canvasH;
181
+ if (imageRatio > canvasRatio) {
182
+ canvasH = canvasW / imageRatio;
183
+ }
184
+ else {
185
+ canvasW = canvasH * imageRatio;
186
+ }
187
+ return { w: canvasW, h: canvasH };
188
+ }
189
+ /** [TODO] Convert a PDF to a Canvas */
190
+ async pdfToCanvas() {
191
+ const pdfjs = await import("pdfjs-dist/build/pdf");
192
+ const pdfjsWorker = await import("pdfjs-dist/build/pdf.worker.entry");
193
+ pdfjs.GlobalWorkerOptions.workerSrc = pdfjsWorker;
194
+ const pdf = await getDocument(this.chosenPlan.filepath).promise;
195
+ const page = await pdf.getPage(1);
196
+ const viewPortParameters = { scale: 1 };
197
+ const viewport = page.getViewport(viewPortParameters);
198
+ this.canvas.height = viewport.height;
199
+ this.canvas.width = viewport.width;
200
+ const size = this.getSizeForCanvas(viewport.width, viewport.height);
201
+ console.log(size);
202
+ this.canvasSize = size;
203
+ this.canvasZoom = size.w / viewport.width;
204
+ const context = this.canvas.getContext("2d");
205
+ const renderContext = {
206
+ canvasContext: context,
207
+ viewport,
208
+ };
209
+ const renderTask = page.render(renderContext).promise;
210
+ renderTask.then(() => console.log("Page rendered"));
211
+ // const res = canvas.toDataURL();
212
+ // if (pdf != null) pdf.destroy();
213
+ // return res;
214
+ }
215
+ /** User click to user Symmetry Vertical */
216
+ onReflectV() {
217
+ this.reflectV = !this.reflectV;
218
+ this.configureCanvas();
219
+ }
220
+ /** User click to user Symmetry Horizontal */
221
+ onReflectH() {
222
+ this.reflectH = !this.reflectH;
223
+ this.configureCanvas();
224
+ }
225
+ /** **********************************************************************************************
226
+ * MATTERPORT
227
+ *********************************************************************************************** */
228
+ /** Launch matterport */
229
+ async launchViewer() {
230
+ await this.matterportImportService.initSdkForModel(this.chosenPlan.model3d);
231
+ const { sdk } = this.matterportImportService;
232
+ this.floors = Object.values(this.matterportImportService.floors);
233
+ // console.log(this.floors);
234
+ setTimeout(async () => {
235
+ /** Move Floor mode */
236
+ await sdk.Mode.moveTo(sdk.Mode.Mode.FLOORPLAN);
237
+ /** Display the correct floor for the plan */
238
+ try {
239
+ await this.matterportImportService.moveToFloor(this.chosenPlan.name);
240
+ }
241
+ catch {
242
+ console.log("couldnot move to floor");
243
+ }
244
+ /** We can display the matterport view now */
245
+ this.loading = false;
246
+ }, 300);
247
+ /** When the user try to change the view mode we set it back to floorpan */
248
+ sdk.on(sdk.Mode.Event.CHANGE_END, (oldMode, newMode) => {
249
+ if (newMode !== sdk.Mode.Mode.FLOORPLAN) {
250
+ sdk.Mode.moveTo(sdk.Mode.Mode.FLOORPLAN, {
251
+ transition: "transition.instant",
252
+ });
253
+ }
254
+ });
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"
370
+ ? testPosition.x
371
+ : testPosition.z;
372
+ const positionY = this.calibrage.nameYAxis === "x"
373
+ ? testPosition.x
374
+ : testPosition.z;
375
+ const testX = positionX * this.calibrage.scaleX +
376
+ this.calibrage.offsetX;
377
+ const testY = positionY * this.calibrage.scaleY +
378
+ this.calibrage.offsetY;
379
+ // console.log("test position GREEN", testX, testY);
380
+ const transformedX = (testX - this.calibrage.offsetXPlan) /
381
+ this.calibrage.scalePlan; // we are undoing the pan and zoom
382
+ const transformedY = (testY - this.calibrage.offsetYPlan) /
383
+ this.calibrage.scalePlan;
384
+ this.positions.push({
385
+ navID: navigation.id,
386
+ planID: this.chosenPlan.id,
387
+ x: transformedX,
388
+ y: transformedY,
389
+ });
390
+ const iconSize = 30 * this.calibrage.scalePlan;
391
+ const shift = iconSize / 2;
392
+ this.drawImage("https://api.iconify.design/mdi:adjust.svg?color=green&height=30&width=30", transformedX - shift, transformedY - shift, true);
393
+ }
394
+ }
395
+ }
396
+ }
397
+ /** Save calibration */
398
+ async onSave() {
399
+ if (this.currentZone) {
400
+ /** Normalize with the zoom */
401
+ // this.calibrage.offsetX /= this.canvasZoom;
402
+ // this.calibrage.offsetY /= this.canvasZoom;
403
+ // this.calibrage.x /= this.canvasZoom;
404
+ // this.calibrage.y /= this.canvasZoom;
405
+ this.calibrage.new = true;
406
+ this.calibrage.imgWidth = this.canvasSize.w;
407
+ this.calibrage.imgHeight = this.canvasSize.h;
408
+ await this.planService.updatePlan({
409
+ id: this.chosenPlan.id,
410
+ calibration: JSON.stringify(this.calibrage),
411
+ });
412
+ await Promise.all(this.positions.map(async (position) => {
413
+ const { navID } = position;
414
+ delete position.navID;
415
+ const nav = this.currentNavigations.find((_nav) => _nav.id === navID);
416
+ let positionsDataToUpdate;
417
+ if (nav.positionOnPlan) {
418
+ const positionOnPlan = nav.positionOnPlan.map((entry) => JSON.parse(entry));
419
+ const positionForCurrentPlan = positionOnPlan.find((entry) => entry.planID === this.chosenPlan.id);
420
+ if (positionForCurrentPlan) {
421
+ positionOnPlan.splice(positionOnPlan.indexOf(positionForCurrentPlan), 1, position);
422
+ }
423
+ else {
424
+ positionOnPlan.push(position);
425
+ }
426
+ positionsDataToUpdate = [...positionOnPlan];
427
+ }
428
+ else {
429
+ positionsDataToUpdate = [position];
430
+ }
431
+ // console.log(positionsDataToUpdate);
432
+ await this.navigationService.updateNavigation({
433
+ id: navID,
434
+ positionOnPlan: positionsDataToUpdate.map((entry) => JSON.stringify(entry)),
435
+ });
436
+ }));
437
+ }
438
+ this.matterportImportService.removeFrame();
439
+ this.router.navigate([
440
+ "/dashboard/localisation",
441
+ this.spaceID,
442
+ "plans",
443
+ ]);
444
+ alert(this.translate.instant("calibration.success"));
445
+ }
446
+ /** Reset the canvas */
447
+ onReset() {
448
+ this.reflectH = false;
449
+ this.reflectV = false;
450
+ this.preview = false;
451
+ this.configureCanvas();
452
+ }
453
+ /** Cancel, leave */
454
+ onCancel() {
455
+ this.matterportImportService.removeFrame();
456
+ this.router.navigate([
457
+ "/dashboard/localisation",
458
+ this.spaceID,
459
+ "plans",
460
+ ]);
461
+ alert(this.translate.instant("calibration.canceled"));
462
+ }
463
+ async onFloorClick(floor) {
464
+ this.currentFloor = floor;
465
+ await this.matterportImportService.moveToFloor(floor.id);
466
+ }
467
+ onActivateZoomChange() {
468
+ this.zoomCanBeChanged = !this.zoomCanBeChanged;
469
+ const iframe = document.querySelector("#viewer-frame");
470
+ if (iframe) {
471
+ iframe.style.zIndex = this.zoomCanBeChanged ? "1" : "0";
472
+ }
473
+ }
474
+ }
475
+ 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 });
476
+ 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 [ngStyle]=\"{'opacity': 'calc(' + (-(opacity-100)+10) + '/ 100)'}\">{{'Less' | translate}}</div>\n <div class=\"legend-title\">{{'Plan Opacity' | translate }}</div>\n <div [ngStyle]=\"{'opacity': 'calc(' + (opacity+10) + '/ 100)'}\">{{'More' | 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=\"label-legend me-3\">{{'Pan/Zoom Visit' | translate}} {{zoomCanBeChanged ? \"ON\" : \"OFF\"}}\n </div>\n <input type=\"checkbox\" (change)=\"onActivateZoomChange()\" style=\"margin-top: 5px;\">\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\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);position:absolute;margin:auto;width:100%;text-align:center;font-weight:700}.tool .label-legend{color:var(--smarterplan-primary);font-size:1.1rem}.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 } });
477
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.2.7", ngImport: i0, type: CalibrationComponent, decorators: [{
478
+ type: Component,
479
+ 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 [ngStyle]=\"{'opacity': 'calc(' + (-(opacity-100)+10) + '/ 100)'}\">{{'Less' | translate}}</div>\n <div class=\"legend-title\">{{'Plan Opacity' | translate }}</div>\n <div [ngStyle]=\"{'opacity': 'calc(' + (opacity+10) + '/ 100)'}\">{{'More' | 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=\"label-legend me-3\">{{'Pan/Zoom Visit' | translate}} {{zoomCanBeChanged ? \"ON\" : \"OFF\"}}\n </div>\n <input type=\"checkbox\" (change)=\"onActivateZoomChange()\" style=\"margin-top: 5px;\">\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\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);position:absolute;margin:auto;width:100%;text-align:center;font-weight:700}.tool .label-legend{color:var(--smarterplan-primary);font-size:1.1rem}.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"] }]
480
+ }], 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: [{
481
+ type: ViewChild,
482
+ args: ["canvasDiv"]
483
+ }] } });
484
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2FsaWJyYXRpb24uY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvbmd4LXNtYXJ0ZXJwbGFuLWxvY2F0aW9ucy9zcmMvbGliL2NvbXBvbmVudHMvcGxhbnMvY2FsaWJyYXRpb24vY2FsaWJyYXRpb24uY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvbmd4LXNtYXJ0ZXJwbGFuLWxvY2F0aW9ucy9zcmMvbGliL2NvbXBvbmVudHMvcGxhbnMvY2FsaWJyYXRpb24vY2FsaWJyYXRpb24uY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFNBQVMsRUFBc0IsU0FBUyxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBR3pFLE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSxZQUFZLENBQUM7QUFFekMsT0FBTyxFQUFzRyxlQUFlLEVBQTJCLE1BQU0sc0JBQXNCLENBQUM7QUFDcEwsT0FBTyxPQUFPLE1BQU0sU0FBUyxDQUFDOzs7Ozs7Ozs7QUFPOUIsTUFBTSxPQUFPLG9CQUFvQjtJQXFGN0IsWUFDWSx1QkFBZ0QsRUFDaEQsV0FBd0IsRUFDeEIsS0FBcUIsRUFDckIsTUFBYyxFQUNkLFdBQXdCLEVBQ3hCLFlBQTBCLEVBQzFCLGlCQUFvQyxFQUNwQyxTQUEyQjtRQVAzQiw0QkFBdUIsR0FBdkIsdUJBQXVCLENBQXlCO1FBQ2hELGdCQUFXLEdBQVgsV0FBVyxDQUFhO1FBQ3hCLFVBQUssR0FBTCxLQUFLLENBQWdCO1FBQ3JCLFdBQU0sR0FBTixNQUFNLENBQVE7UUFDZCxnQkFBVyxHQUFYLFdBQVcsQ0FBYTtRQUN4QixpQkFBWSxHQUFaLFlBQVksQ0FBYztRQUMxQixzQkFBaUIsR0FBakIsaUJBQWlCLENBQW1CO1FBQ3BDLGNBQVMsR0FBVCxTQUFTLENBQWtCO1FBM0Z2QyxxQ0FBcUM7UUFDckMsY0FBUyxHQUFlLEVBQUUs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QkFBZ0IsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUM7U0FDM0Q7SUFDTCxDQUFDOztpSEEvbEJRLG9CQUFvQjtxR0FBcEIsb0JBQW9CLCtKQ2JqQyxneElBMEZNOzJGRDdFTyxvQkFBb0I7a0JBTGhDLFNBQVM7K0JBQ0UsaUJBQWlCOzhTQWFELFNBQVM7c0JBQWhDLFNBQVM7dUJBQUMsV0FBVyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IENvbXBvbmVudCwgRWxlbWVudFJlZiwgT25Jbml0LCBWaWV3Q2hpbGQgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IEFjdGl2YXRlZFJvdXRlLCBSb3V0ZXIgfSBmcm9tICdAYW5ndWxhci9yb3V0ZXInO1xuaW1wb3J0IHsgVHJhbnNsYXRlU2VydmljZSB9IGZyb20gJ0BuZ3gtdHJhbnNsYXRlL2NvcmUnO1xuaW1wb3J0IHsgZ2V0RG9jdW1lbnQgfSBmcm9tIFwicGRmanMtZGlzdFwiO1xuaW1wb3J0IHsgUERGRG9jdW1lbnRQcm94eSB9IGZyb20gXCJuZzItcGRmLXZpZXdlclwiO1xuaW1wb3J0IHsgWm9uZSwgTWVudUl0ZW0sIFBsYW4sIFNwYWNlLCBOYXZpZ2F0aW9uLCBQbGFuU2VydmljZSwgWm9uZVNlcnZpY2UsIFNwYWNlU2VydmljZSwgTmF2aWdhdGlvblNlcnZpY2UsIGdldE1ldGFGb3JJbWFnZSwgTWF0dGVycG9ydEltcG9ydFNlcnZpY2UgfSBmcm9tICduZ3gtc21hcnRlcnBsYW4tY29yZSc7XG5pbXBvcnQgcGFuem9vbSBmcm9tICdwYW56b29tJztcblxuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAnbGliLWNhbGlicmF0aW9uJyxcbiAgdGVtcGxhdGVVcmw6ICcuL2NhbGlicmF0aW9uLmNvbXBvbmVudC5odG1sJyxcbiAgc3R5bGVVcmxzOiBbJy4vY2FsaWJyYXRpb24uY29tcG9uZW50LnNjc3MnXVxufSlcbmV4cG9ydCBjbGFzcyBDYWxpYnJhdGlvbkNvbXBvbmVudCBpbXBsZW1lbnRzIE9uSW5pdCB7XG5cbiAgICAvKiogSXRlbSB0byBkaXNwbGF5IGZvciB0aGUgbmF2YmFyICovXG4gICAgbWVudUl0ZW1zOiBNZW51SXRlbVtdID0gW107XG5cbiAgICAvKiogQ2FudmFzIChQbGFuKSAqL1xuICAgIGNhbnZhcztcblxuICAgIC8qKiBDYW52YXNEaXYgKERpdiB0aGF0IGNvbnRhaW4gdGhlIGNhbnZhcyArIG1hdHRlcnBvcnQgaWZyYW1lKSAqL1xuICAgIEBWaWV3Q2hpbGQoXCJjYW52YXNEaXZcIikgY2FudmFzRGl2OiBFbGVtZW50UmVmO1xuXG4gICAgLyoqIFNpemUgb2YgdGhlIGNhbnZhcyAmIG1hdHRlcnBvcnQgaWZyYW1lICovXG4gICAgY2FudmFzU2l6ZTogeyB3OiBudW1iZXI7IGg6IG51bWJlciB9O1xuXG4gICAgLyoqIFpvb20gcmF0aW8gb2YgdGhlIGNhbnZhcy9wbGFuICAqL1xuICAgIGNhbnZhc1pvb20gPSAwO1xuXG4gICAgLyoqIE9wYWNpdHkgZm9yIG1hdHRlcnBvcnQgaWZyYW1lICovXG4gICAgb3BhY2l0eTogbnVtYmVyID0gNTA7XG5cbiAgICAvKiogQ3VycmVudCByb3RhdGlvbiBmb3IgbWF0dGVycG9ydCwgWzAtMzYwXSwgIG1hdHRlcnBvcnQgcm90YXRpb24gaXMgYmluZCB0byBpbnB1dCByYW5nZSAqL1xuICAgIHJvdGF0aW9uOiBudW1iZXIgPSAxODA7XG5cbiAgICAvKiogUHJldmlvdXMgcm90YXRpb24sIHVzZSB0byBjYWxjdWxhdGUgdGhlIGRlbHRhUm90YXRpb24gdG8gcm90YXRlLCB3aGVuIHVzZXIgY2hhbmdlIHJvdGF0aW9uIHZhbHVlIHVzaW5nIHJhbmdlIGlucHV0ICovXG4gICAgcHJldlJvdGF0aW9uOiBudW1iZXIgPSAxODA7XG5cbiAgICAvKiogQ3VycmVudCBDYW1lcmEgUG9zZSAqL1xuICAgIGNhbWVyYVBvc2U6IGFueTtcblxuICAgIC8qKiBUcnVlIHdoZW4gdGhlIHVzZXIgaXMgY3VycmVudGx5IHJvdGF0aW5nIHdpdGggdGhlIGlucHV0IHJhbmdlLCB0aGUgbWF0dGVycG9ydCByb3RhdGlvbiBldmVudHMgd2lsbCBiZSBpZ25vcmVkICovXG4gICAgaXNSb3RhdGluZ1JhbmdlOiBib29sZWFuID0gZmFsc2U7XG5cbiAgICAvKiogUm90YXRpbmcgcXVldWUgZXZlbnQgdG8gc2VuZCB0byBtYXR0ZXJwb3J0ICovXG4gICAgcm90YXRpbmdRdWV1ZUV2ZW50OiBudW1iZXJbXSA9IFtdO1xuXG4gICAgLyoqIFRydWUgd2hlbiBWZXJ0aWNhbCBzeW1tZXRyeSBpcyBlbmFibGVkICovXG4gICAgcmVmbGVjdFYgPSBmYWxzZTtcblxuICAgIC8qKiBUcnVlIHdoZW4gSG9yaXpvbnRhbCBzeW1tZXRyeSBpcyBlbmFibGVkICovXG4gICAgcmVmbGVjdEggPSBmYWxzZTtcblxuICAgIGNob3NlblBsYW46IFBsYW47XG5cbiAgICBzcGFjZUlEOiBzdHJpbmc7XG5cbiAgICBjdXJyZW50U3BhY2U6IFNwYWNlO1xuXG4gICAgY3VycmVudFpvbmU6IFpvbmU7XG5cbiAgICBjaG9zZW5QbGFuSXNQZGYgPSBmYWxzZTtcblxuICAgIC8qKiBGaXJzdCBQb2ludCBpbiB2aXNpdCwgdXNlZCB0byBkZXRlcm1pbmUgdGhlIGNhbGlicmF0aW9uICAqL1xuICAgIGZpcnN0TWFya1Zpc2l0ID0geyB4OiAwLCB5OiAwIH07XG5cbiAgICAvKiogU2Vjb25kIFBvaW50IGluIHZpc2l0LCB1c2VkIHRvIGRldGVybWluZSB0aGUgY2FsaWJyYXRpb24gICovXG4gICAgc2Vjb25kTWFya1Zpc2l0ID0geyB4OiAwLjUsIHk6IDAuNSB9O1xuXG4gICAgLyoqIEVxdWl2YWxlbnQgb2YgJ2ZpcnN0TWFya1Zpc2l0JyBpbiBjYW52YXMgICovXG4gICAgZmlyc3RNYXJrUGxhbjogeyB4OiBudW1iZXI7IHk6IG51bWJlciB9ID0geyB4OiAwLCB5OiAwIH07XG5cbiAgICAvKiogRXF1aXZhbGVudCBvZiAnc2Vjb25kTWFya1Zpc2l0JyBpbiBjYW52YXMgICovXG4gICAgc2Vjb25kTWFya1BsYW46IHsgeDogbnVtYmVyOyB5OiBudW1iZXIgfSA9IHsgeDogMCwgeTogMCB9O1xuXG4gICAgLyoqIENhbGlicmF0aW9uIHJlc3VsdCwgKG9mZnNldFgsIG9mZnNldFksIHgsIHkpICovXG4gICAgY2FsaWJyYWdlOiBhbnkgPSB7fTtcblxuICAgIC8qKiBJcyBpbiBwcmV2aWV3IG1vZGUgKHNlZSBzY2FuIHJlc3VsdCkgKi9cbiAgICBwcmV2aWV3ID0gZmFsc2U7XG5cbiAgICAvKiogTWF0dGVycG9ydCBpcyBsb2FkaW5nICovXG4gICAgbG9hZGluZyA9IHRydWU7XG5cbiAgICAvKiBmb3IgcGFuIGFuZCB6b29tIG9mIGNhbnZhcyAqL1xuICAgIHBhbnpvb206IGFueTtcblxuICAgIGN1cnJlbnROYXZpZ2F0aW9uczogTmF2aWdhdGlvbltdO1xuXG4gICAgcG9zaXRpb25zOiB7IG5hdklEOiBzdHJpbmc7IHBsYW5JRDogc3RyaW5nOyB4OiBudW1iZXI7IHk6IG51bWJlciB9W10gPSBbXTtcblxuICAgIGZsb29yczogYW55W10gPSBbXTtcblxuICAgIGN1cnJlbnRGbG9vcjtcblxuICAgIHpvb21DYW5CZUNoYW5nZWQ6IGJvb2xlYW4gPSBmYWxzZTtcblxuICAgIGNvbnN0cnVjdG9yKFxuICAgICAgICBwcml2YXRlIG1hdHRlcnBvcnRJbXBvcnRTZXJ2aWNlOiBNYXR0ZXJwb3J0SW1wb3J0U2VydmljZSxcbiAgICAgICAgcHJpdmF0ZSBwbGFuU2VydmljZTogUGxhblNlcnZpY2UsXG4gICAgICAgIHByaXZhdGUgcm91dGU6IEFjdGl2YXRlZFJvdXRlLFxuICAgICAgICBwcml2YXRlIHJvdXRlcjogUm91dGVyLFxuICAgICAgICBwcml2YXRlIHpvbmVTZXJ2aWNlOiBab25lU2VydmljZSxcbiAgICAgICAgcHJpdmF0ZSBzcGFjZVNlcnZpY2U6IFNwYWNlU2VydmljZSxcbiAgICAgICAgcHJpdmF0ZSBuYXZpZ2F0aW9uU2VydmljZTogTmF2aWdhdGlvblNlcnZpY2UsXG4gICAgICAgIHByaXZhdGUgdHJhbnNsYXRlOiBUcmFuc2xhdGVTZXJ2aWNlLFxuICAgICkge31cblxuICAgIG5nT25EZXN0cm95KCk6IHZvaWQge1xuICAgICAgICBpZiAoIXRoaXMubG9hZGluZykge1xuICAgICAgICAgICAgdGhpcy5tYXR0ZXJwb3J0SW1wb3J0U2VydmljZS5yZW1vdmVGcmFtZSgpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgYXN5bmMgbmdPbkluaXQoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIHRoaXMuc3BhY2VJRCA9IHRoaXMucm91dGUuc25hcHNob3QucXVlcnlQYXJhbXMuc3BhY2VJRDtcbiAgICAgICAgdGhpcy5jdXJyZW50U3BhY2UgPSBhd2FpdCB0aGlzLnNwYWNlU2VydmljZS5nZXRTcGFjZSh0aGlzLnNwYWNlSUQpO1xuXG4gICAgICAgIC8qKiBNZW51IG5hdiBiYXIgKi9cbiAgICAgICAgdGhpcy5zZXR1cE1lbnVJdGVtcygpO1xuXG4gICAgICAgIHRoaXMuY2hvc2VuUGxhbiA9IHRoaXMucGxhblNlcnZpY2UuZ2V0Q2hvc2VuUGxhbigpO1xuXG4gICAgICAgIGlmICh0aGlzLmNob3NlblBsYW4pIHtcbiAgICAgICAgICAgIHRoaXMuY2hvc2VuUGxhbklzUGRmID0gdGhpcy5jaG9zZW5QbGFuLmFubmV4ZS5pbmNsdWRlcyhcInBkZlwiKTtcbiAgICAgICAgICAgIHRoaXMubGF1bmNoVmlld2VyKCk7XG4gICAgICAgICAgICBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLmNvbmZpZ3VyZUNhbnZhcygpLnRoZW4oKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnBhbnpvb20gPSBwYW56b29tKHRoaXMuY2FudmFzLCB7XG4gICAgICAgICAgICAgICAgICAgICAgICBib3VuZHM6IHRydWUsXG4gICAgICAgICAgICAgICAgICAgICAgICBib3VuZHNQYWRkaW5nOiAwLFxuICAgICAgICAgICAgICAgICAgICAgICAgbWF4Wm9vbTogMi41LFxuICAgICAgICAgICAgICAgICAgICAgICAgbWluWm9vbTogMC4xLFxuICAgICAgICAgICAgICAgICAgICAgICAgaW5pdGlhbFpvb206IDEsXG4gICAgICAgICAgICAgICAgICAgICAgICB6b29tU3BlZWQ6IDAuMDIsXG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSwgNTAwKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMucm91dGVyLm5hdmlnYXRlKFtcbiAgICAgICAgICAgICAgICBcIi9kYXNoYm9hcmQvbG9jYWxpc2F0aW9uXCIsXG4gICAgICAgICAgICAgICAgdGhpcy5zcGFjZUlELFxuICAgICAgICAgICAgICAgIFwicGxhbnNcIixcbiAgICAgICAgICAgIF0pO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKipcbiAgICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgTUVOVSBOQVYgQkFSXG4gICAgICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqICovXG4gICAgc2V0dXBNZW51SXRlbXMoKSB7XG4gICAgICAgIHRoaXMubWVudUl0ZW1zID0gW1xuICAgICAgICAgICAgeyBsYWJlbDogXCJMb2NhdGlvbnNcIiwgdXJsOiBcIi9sb2NhbGlzYXRpb25cIiB9LFxuICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgIGxhYmVsOiB0aGlzLmN1cnJlbnRTcGFjZS5uYW1lLFxuICAgICAgICAgICAgICAgIHVybDogYC9sb2NhbGlzYXRpb24vJHt0aGlzLnNwYWNlSUR9YCxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgbGFiZWw6IFwiUGxhbnNcIixcbiAgICAgICAgICAgICAgICB1cmw6IGAvbG9jYWxpc2F0aW9uLyR7dGhpcy5jdXJyZW50U3BhY2UuaWR9L3BsYW5zYCxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgbGFiZWw6IFwiQ2FsaWJyYXRpb25cIixcbiAgICAgICAgICAgICAgICB1cmw6IGAvbG9jYWxpc2F0aW9uLyR7dGhpcy5jdXJyZW50U3BhY2UuaWR9L3BsYW4tY2FsaWJyYXRpb24/c3BhY2VJRD0ke3RoaXMuY3VycmVudFNwYWNlLmlkfWAsXG4gICAgICAgICAgICB9LFxuICAgICAgICBdO1xuICAgIH1cblxuICAgIC8qKiAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqXG4gICAgICogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQ0FOVkFTXG4gICAgICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqICovXG5cbiAgICAvKiogRGlzcGxheSB0aGUgcGxhbiAqL1xuICAgIGFzeW5jIGNvbmZpZ3VyZUNhbnZhcygpIHtcbiAgICAgICAgLyoqIEdldCBjYW52YXMgKi9cbiAgICAgICAgaWYgKCF0aGlzLmNhbnZhcykge1xuICAgICAgICAgICAgY29uc3QgY2FudmFzID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvcihcbiAgICAgICAgICAgICAgICBcIiNjYW52YXNcIixcbiAgICAgICAgICAgICkgYXMgSFRNTENhbnZhc0VsZW1lbnQ7XG4gICAgICAgICAgICB0aGlzLmNhbnZhcyA9IGNhbnZhcztcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghdGhpcy5jaG9zZW5QbGFuSXNQZGYpIHtcbiAgICAgICAgICAgIGNvbnN0IGltYWdlID0gYXdhaXQgZ2V0TWV0YUZvckltYWdlKHRoaXMuY2hvc2VuUGxhbi5maWxlcGF0aCk7XG4gICAgICAgICAgICAvKiogQ29tcHV0ZSB0aGUgbmV3IHNpemUgZm9yIHRoZSBjYW52YXMvbWF0dGVycG9ydCwgYmFzZSBvbiB0aGUgZGltZW5zaW9uIG9mIHRoZSBwbGFuLCBrZWVwaW5nIHRoZSByYXRpbyAqL1xuICAgICAgICAgICAgY29uc3Qgc2l6ZSA9IHRoaXMuZ2V0U2l6ZUZvckNhbnZhcyhpbWFnZS53aWR0aCwgaW1hZ2UuaGVpZ2h0KTtcblxuICAgICAgICAgICAgLyoqIENvbXB1dGUgdGhlIHBsYW4gem9vbSByYXRpbyAodXNlIGZvciB0aGUgY2FsaWJyYXRpb24gbGF0ZXIpICovXG4gICAgICAgICAgICB0aGlzLmNhbnZhc1pvb20gPSBzaXplLncgLyBpbWFnZS53aWR0aDtcblxuICAgICAgICAgICAgdGhpcy5yZXNpemVWaWV3KHNpemUpO1xuXG4gICAgICAgICAgICAvKiogRHJhdyBQbGFuIG9uIHRoZSBjYW52YXMgKi9cbiAgICAgICAgICAgIHRoaXMuZHJhd0ltYWdlKHRoaXMuY2hvc2VuUGxhbi5maWxlcGF0aCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAvLyBUT0RPXG4gICAgICAgICAgICB0aGlzLnBkZlRvQ2FudmFzKCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKiogVXBkYXRlIHNpemUgb2YgdGhlIGNhbnZhcy9tYXR0ZXJwb3J0ICovXG4gICAgcmVzaXplVmlldyhzaXplKSB7XG4gICAgICAgIHRoaXMuY2FudmFzRGl2Lm5hdGl2ZUVsZW1lbnQuc3R5bGUud2lkdGggPSBgJHtzaXplLnd9cHhgO1xuICAgICAgICB0aGlzLmNhbnZhc0Rpdi5uYXRpdmVFbGVtZW50LnN0eWxlLmhlaWdodCA9IGAke3NpemUuaH1weGA7XG4gICAgICAgIHRoaXMuY2FudmFzLnN0eWxlLndpZHRoID0gYCR7c2l6ZS53fXB4YDtcbiAgICAgICAgdGhpcy5jYW52YXMuc3R5bGUuaGVpZ2h0ID0gYCR7c2l6ZS5ofXB4YDtcbiAgICAgICAgdGhpcy5jYW52YXMud2lkdGggPSBzaXplLnc7XG4gICAgICAgIHRoaXMuY2FudmFzLmhlaWdodCA9IHNpemUuaDtcbiAgICAgICAgdGhpcy5jYW52YXNTaXplID0gc2l6ZTtcbiAgICB9XG5cbiAgICAvKiogRHJhdyBzb21ldGhpbmcgb24gdGhlIGNhbnZhcyAqL1xuICAgIGRyYXdJbWFnZSh1cmw6IHN0cmluZywgeCA9IDAsIHkgPSAwLCBpY29uZSA9IGZhbHNlKSB7XG4gICAgICAgIGNvbnN0IGltYWdlID0gbmV3IEltYWdlKCk7XG4gICAgICAgIGNvbnN0IHNpemUgPSB0aGlzLmNhbnZhc1NpemU7XG4gICAgICAgIGNvbnN0IGNvbnRleHQgPSB0aGlzLmNhbnZhcy5nZXRDb250ZXh0KFwiMmRcIik7XG5cbiAgICAgICAgLyoqIEZsaXAgdGhlIGNvbnRleHQsIGZvciBzeW1tZXRyeSAqL1xuICAgICAgICAvLyBpZiAodGhpcy5yZWZsZWN0Vikge1xuICAgICAgICAvLyAgICAgY29udGV4dC50cmFuc2xhdGUoc2l6ZS53LCAwKTtcbiAgICAgICAgLy8gICAgIGNvbnRleHQuc2NhbGUoLTEsIDEpO1xuICAgICAgICAvLyB9XG4gICAgICAgIC8vIGlmICh0aGlzLnJlZmxlY3RIKSB7XG4gICAgICAgIC8vICAgICBjb250ZXh0LnRyYW5zbGF0ZSgwLCBzaXplLmgpO1xuICAgICAgICAvLyAgICAgY29udGV4dC5zY2FsZSgxLCAtMSk7XG4gICAgICAgIC8vIH1cblxuICAgICAgICBsZXQgaW1hZ2VXaWR0aCA9IHNpemUudztcbiAgICAgICAgbGV0IGltYWdlSGVpZ2h0ID0gc2l6ZS5oO1xuICAgICAgICBpbWFnZS5hZGRFdmVudExpc3RlbmVyKFwibG9hZFwiLCAoKSA9PiB7XG4gICAgICAgICAgICBpZiAoaWNvbmUpIHtcbiAgICAgICAgICAgICAgICBpbWFnZVdpZHRoID0gaW1hZ2Uud2lkdGg7XG4gICAgICAgICAgICAgICAgaW1hZ2VIZWlnaHQgPSBpbWFnZS5oZWlnaHQ7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjb250ZXh0LmRyYXdJbWFnZShcbiAgICAgICAgICAgICAgICBpbWFnZSxcbiAgICAgICAgICAgICAgICAwLFxuICAgICAgICAgICAgICAgIDAsXG4gICAgICAgICAgICAgICAgaW1hZ2Uud2lkdGgsXG4gICAgICAgICAgICAgICAgaW1hZ2UuaGVpZ2h0LFxuICAgICAgICAgICAgICAgIHgsXG4gICAgICAgICAgICAgICAgeSxcbiAgICAgICAgICAgICAgICBpbWFnZVdpZHRoLFxuICAgICAgICAgICAgICAgIGltYWdlSGVpZ2h0LFxuICAgICAgICAgICAgKTtcbiAgICAgICAgfSk7XG4gICAgICAgIGltYWdlLnNyYyA9IHVybDtcbiAgICB9XG5cbiAgICAvKiogR2V0IHRoZSBzaXplIGZvciB0aGUgY2FudmFzLCBiYXNlZCBvbiB0aGUgcGxhbiBzaXplLCBrZWVwaW5nIHRoZSByYXRpbyAqL1xuICAgIGdldFNpemVGb3JDYW52YXModywgaCkge1xuICAgICAgICBsZXQgY2FudmFzVyA9IHRoaXMuY2FudmFzRGl2Lm5hdGl2ZUVsZW1lbnQub2Zmc2V0V2lkdGg7XG4gICAgICAgIGxldCBjYW52YXNIID0gdGhpcy5jYW52YXNEaXYubmF0aXZlRWxlbWVudC5vZmZzZXRIZWlnaHQ7XG5cbiAgICAgICAgY29uc3QgaW1hZ2VSYXRpbyA9IHcgLyBoO1xuICAgICAgICBjb25zdCBjYW52YXNSYXRpbyA9IGNhbnZhc1cgLyBjYW52YXNIO1xuXG4gICAgICAgIGlmIChpbWFnZVJhdGlvID4gY2FudmFzUmF0aW8pIHtcbiAgICAgICAgICAgIGNhbnZhc0ggPSBjYW52YXNXIC8gaW1hZ2VSYXRpbztcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNhbnZhc1cgPSBjYW52YXNIICogaW1hZ2VSYXRpbztcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4geyB3OiBjYW52YXNXLCBoOiBjYW52YXNIIH07XG4gICAgfVxuXG4gICAgLyoqIFtUT0RPXSBDb252ZXJ0IGEgUERGIHRvIGEgQ2FudmFzICovXG4gICAgYXN5bmMgcGRmVG9DYW52YXMoKSB7XG4gICAgICAgIGNvbnN0IHBkZmpzID0gYXdhaXQgaW1wb3J0KFwicGRmanMtZGlzdC9idWlsZC9wZGZcIik7XG4gICAgICAgIGNvbnN0IHBkZmpzV29ya2VyID0gYXdhaXQgaW1wb3J0KFwicGRmanMtZGlzdC9idWlsZC9wZGYud29ya2VyLmVudHJ5XCIpO1xuXG4gICAgICAgIHBkZmpzLkdsb2JhbFdvcmtlck9wdGlvbnMud29ya2VyU3JjID0gcGRmanNXb3JrZXI7XG5cbiAgICAgICAgY29uc3QgcGRmOiBQREZEb2N1bWVudFByb3h5ID0gYXdhaXQgZ2V0RG9jdW1lbnQoXG4gICAgICAgICAgICB0aGlzLmNob3NlblBsYW4uZmlsZXBhdGgsXG4gICAgICAgICkucHJvbWlzZTtcbiAgICAgICAgY29uc3QgcGFnZSA9IGF3YWl0IHBkZi5nZXRQYWdlKDEpO1xuXG4gICAgICAgIGNvbnN0IHZpZXdQb3J0UGFyYW1ldGVycyA9IHsgc2NhbGU6IDEgfTtcbiAgICAgICAgY29uc3Qgdmlld3BvcnQgPSBwYWdlLmdldFZpZXdwb3J0KHZpZXdQb3J0UGFyYW1ldGVycyk7XG5cbiAgICAgICAgdGhpcy5jYW52YXMuaGVpZ2h0ID0gdmlld3BvcnQuaGVpZ2h0O1xuICAgICAgICB0aGlzLmNhbnZhcy53aWR0aCA9IHZpZXdwb3J0LndpZHRoO1xuXG4gICAgICAgIGNvbnN0IHNpemUgPSB0aGlzLmdldFNpemVGb3JDYW52YXModmlld3BvcnQud2lkdGgsIHZpZXdwb3J0LmhlaWdodCk7XG4gICAgICAgIGNvbnNvbGUubG9nKHNpemUpO1xuICAgICAgICB0aGlzLmNhbnZhc1NpemUgPSBzaXplO1xuXG4gICAgICAgIHRoaXMuY2FudmFzWm9vbSA9IHNpemUudyAvIHZpZXdwb3J0LndpZHRoO1xuXG4gICAgICAgIGNvbnN0IGNvbnRleHQgPSB0aGlzLmNhbnZhcy5nZXRDb250ZXh0KFxuICAgICAgICAgICAgXCIyZFwiLFxuICAgICAgICApIGFzIENhbnZhc1JlbmRlcmluZ0NvbnRleHQyRDtcbiAgICAgICAgY29uc3QgcmVuZGVyQ29udGV4dCA9IHtcbiAgICAgICAgICAgIGNhbnZhc0NvbnRleHQ6IGNvbnRleHQsXG4gICAgICAgICAgICB2aWV3cG9ydCxcbiAgICAgICAgfTtcbiAgICAgICAgY29uc3QgcmVuZGVyVGFzayA9IHBhZ2UucmVuZGVyKHJlbmRlckNvbnRleHQpLnByb21pc2U7XG5cbiAgICAgICAgcmVuZGVyVGFzay50aGVuKCgpID0+IGNvbnNvbGUubG9nKFwiUGFnZSByZW5kZXJlZFwiKSk7XG5cbiAgICAgICAgLy8gY29uc3QgcmVzID0gY2FudmFzLnRvRGF0YVVSTCgpO1xuICAgICAgICAvLyBpZiAocGRmICE9IG51bGwpIHBkZi5kZXN0cm95KCk7XG4gICAgICAgIC8vIHJldHVybiByZXM7XG4gICAgfVxuXG4gICAgLyoqIFVzZXIgY2xpY2sgdG8gdXNlciBTeW1tZXRyeSBWZXJ0aWNhbCAqL1xuICAgIG9uUmVmbGVjdFYoKSB7XG4gICAgICAgIHRoaXMucmVmbGVjdFYgPSAhdGhpcy5yZWZsZWN0VjtcbiAgICAgICAgdGhpcy5jb25maWd1cmVDYW52YXMoKTtcbiAgICB9XG5cbiAgICAvKiogVXNlciBjbGljayB0byB1c2VyIFN5bW1ldHJ5IEhvcml6b250YWwgKi9cbiAgICBvblJlZmxlY3RIKCkge1xuICAgICAgICB0aGlzLnJlZmxlY3RIID0gIXRoaXMucmVmbGVjdEg7XG4gICAgICAgIHRoaXMuY29uZmlndXJlQ2FudmFzKCk7XG4gICAgfVxuXG4gICAgLyoqICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKipcbiAgICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBNQVRURVJQT1JUXG4gICAgICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqICovXG5cbiAgICAvKiogTGF1bmNoIG1hdHRlcnBvcnQgKi9cbiAgICBhc3luYyBsYXVuY2hWaWV3ZXIoKSB7XG4gICAgICAgIGF3YWl0IHRoaXMubWF0dGVycG9ydEltcG9ydFNlcnZpY2UuaW5pdFNka0Zvck1vZGVsKFxuICAgICAgICAgICAgdGhpcy5jaG9zZW5QbGFuLm1vZGVsM2QsXG4gICAgICAgICk7XG5cbiAgICAgICAgY29uc3QgeyBzZGsgfSA9IHRoaXMubWF0dGVycG9ydEltcG9ydFNlcnZpY2U7XG4gICAgICAgIHRoaXMuZmxvb3JzID0gT2JqZWN0LnZhbHVlcyh0aGlzLm1hdHRlcnBvcnRJbXBvcnRTZXJ2aWNlLmZsb29ycyk7XG4gICAgICAgIC8vIGNvbnNvbGUubG9nKHRoaXMuZmxvb3JzKTtcbiAgICAgICAgc2V0VGltZW91dChhc3luYyAoKSA9PiB7XG4gICAgICAgICAgICAvKiogTW92ZSBGbG9vciBtb2RlICovXG4gICAgICAgICAgICBhd2FpdCBzZGsuTW9kZS5tb3ZlVG8oc2RrLk1vZGUuTW9kZS5GTE9PUlBMQU4pO1xuICAgICAgICAgICAgLyoqIERpc3BsYXkgdGhlIGNvcnJlY3QgZmxvb3IgZm9yIHRoZSBwbGFuICovXG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgIGF3YWl0IHRoaXMubWF0dGVycG9ydEltcG9ydFNlcnZpY2UubW92ZVRvRmxvb3IoXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuY2hvc2VuUGxhbi5uYW1lLFxuICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICB9IGNhdGNoIHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmxvZyhcImNvdWxkbm90IG1vdmUgdG8gZmxvb3JcIik7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8qKiBXZSBjYW4gZGlzcGxheSB0aGUgbWF0dGVycG9ydCB2aWV3IG5vdyAqL1xuICAgICAgICAgICAgdGhpcy5sb2FkaW5nID0gZmFsc2U7XG4gICAgICAgIH0sIDMwMCk7XG5cbiAgICAgICAgLyoqIFdoZW4gdGhlIHVzZXIgdHJ5IHRvIGNoYW5nZSB0aGUgdmlldyBtb2RlIHdlIHNldCBpdCBiYWNrIHRvIGZsb29ycGFuICovXG5cbiAgICAgICAgc2RrLm9uKHNkay5Nb2RlLkV2ZW50LkNIQU5HRV9FTkQsIChvbGRNb2RlLCBuZXdNb2RlKSA9PiB7XG4gICAgICAgICAgICBpZiAobmV3TW9kZSAhPT0gc2RrLk1vZGUuTW9kZS5GTE9PUlBMQU4pIHtcbiAgICAgICAgICAgICAgICBzZGsuTW9kZS5tb3ZlVG8oc2RrLk1vZGUuTW9kZS5GTE9PUlBMQU4sIHtcbiAgICAgICAgICAgICAgICAgICAgdHJhbnNpdGlvbjogXCJ0cmFuc2l0aW9uLmluc3RhbnRcIixcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG5cbiAgICAgICAgLyoqIFVwZGF0ZSBjdXJyZW50IGNhbWVyYSBwb3NlIGFuZCByb3RhdGlvbiAqL1xuICAgICAgICBzZGsuQ2FtZXJhLnBvc2Uuc3Vic2NyaWJlKChldmVudCkgPT4ge1xuICAgICAgICAgICAgLyoqIFdlIHVwZGF0ZSBvbmx5IGlmIHRoZSB1c2VyIGlzIG5vdCBjaGFuZ2luZyB0aGUgcm90YXRpb24gd2l0aCB0aGUgPGlucHV0PiByYW5nZSwgdG8gbm90IG92ZXJyaWRlIHRoZSA8aW5wdXQ+IHZhbHVlICovXG4gICAgICAgICAgICBpZiAoIXRoaXMuaXNSb3RhdGluZ1JhbmdlKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5yb3RhdGlvbiA9IGV2ZW50LnJvdGF0aW9uLnkgKyAxODA7XG4gICAgICAgICAgICAgICAgdGhpcy5wcmV2Um90YXRpb24gPSB0aGlzLnJvdGF0aW9uO1xuICAgICAgICAgICAgICAgIHRoaXMuY2FtZXJhUG9zZSA9IGV2ZW50O1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICAvKiogV2hlbiB0aGUgPGlucHV0PiByYW5nZSwgZm9yIHJvdGF0aW9uLCBjaGFuZ2UgKi9cbiAgICBhc3luYyBvblJvdGF0aW9uQ2hhbmdlKCkge1xuICAgICAgICBjb25zdCByb3RhdGlvbkRlbHRhID0gdGhpcy5yb3RhdGlvbiAtIHRoaXMucHJldlJvdGF0aW9uO1xuICAgICAgICB0aGlzLnByZXZSb3RhdGlvbiA9IHRoaXMucm90YXRpb247XG5cbiAgICAgICAgLyoqIFNlbmQgdGhlIHJvdGF0aW9uRGVsdGEgdG8gdGggcXVldWUgZXZlbnQgaW4gb3JkZXIgdG8gYmUgc2VuZCB0byBtYXR0ZXJwb3J0ICovXG4gICAgICAgIHRoaXMucm90YXRpbmdRdWV1ZUV2ZW50LnB1c2gocm90YXRpb25EZWx0YSk7XG5cbiAgICAgICAgLyoqIFN0YXJ0IHRvIHByb2Nlc3MgdGhlIHF1ZXVlLCBpZiBpdCdzIHRoZSBmaXJzdCBldmVudCAqL1xuICAgICAgICBpZiAoIXRoaXMuaXNSb3RhdGluZ1JhbmdlKSB7XG4gICAgICAgICAgICB0aGlzLmlzUm90YXRpbmdSYW5nZSA9IHRydWU7XG4gICAgICAgICAgICB0aGlzLnByb2Nlc3NSb3RhdGluZ1F1ZXVlRXZlbnQoKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKiBQcm9jZXNzIHRoZSByb3RhdGluZyBldmVudCBxdWV1ZSwgc2VuZCBldmVudCBvbmUgYnkgb25lIHRvIG1hdHRlcnBvcnQgICovXG4gICAgYXN5bmMgcHJvY2Vzc1JvdGF0aW5nUXVldWVFdmVudCgpIHtcbiAgICAgICAgY29uc3QgeyBzZGsgfSA9IHRoaXMubWF0dGVycG9ydEltcG9ydFNlcnZpY2U7XG5cbiAgICAgICAgLyoqIFdoaWxlIHRoZSBxdWV1ZSBpcyBub3QgZW1wdHkgKi9cbiAgICAgICAgd2hpbGUgKHRoaXMucm90YXRpbmdRdWV1ZUV2ZW50Lmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgIC8qKiBSb3RhdGUgbWF0dGVycG9ydCBieSBkZWx0YVJvdGF0aW9uIGFuZCByZW1vdmUgZXZlbnQgZnJvbSBxdWV1ZSAqL1xuICAgICAgICAgICAgYXdhaXQgc2RrLkNhbWVyYS5yb3RhdGUodGhpcy5yb3RhdGluZ1F1ZXVlRXZlbnQuc2hpZnQoKSwgMCwge1xuICAgICAgICAgICAgICAgIHNwZWVkOiAzNjAsXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8qKiBXaGVuIHRoZSBxdWV1ZSBpcyBlbXB0eSwgdGhlbiB0aGUgdXNlciBpcyBub3Qgcm90YXRpbmcgd2l0aCB0aGUgPGlucHV0PiByYW5nZSBhbnltb3JlICovXG4gICAgICAgIHRoaXMuaXNSb3RhdGluZ1JhbmdlID0gZmFsc2U7XG4gICAgfVxuXG4gICAgLyoqICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKipcbiAgICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBVU0VSIEFDVElPTlNcbiAgICAgKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiogKi9cblxuICAgIC8qKiBQcmV2aWV3IGNhbGlicmF0aW9uICovXG4gICAgYXN5bmMgb25QcmV2aWV3KCkge1xuICAgICAgICB0aGlzLnByZXZpZXcgPSB0cnVlO1xuICAgICAgICAvKiogUGxhY2Ugc3dlZXBzICovXG4gICAgICAgIHRoaXMub25QbGFjZVN3ZWVwcygpO1xuICAgIH1cblxuICAgIGFzeW5jIGNhbGlicmF0ZSgpIHtcbiAgICAgICAgY29uc3QgW25hdmlnYXRpb25dID0gdGhpcy5jdXJyZW50TmF2aWdhdGlvbnM7XG4gICAgICAgIGNvbnN0IHBvc2l0aW9uID0gSlNPTi5wYXJzZShuYXZpZ2F0aW9uLnBvc2l0aW9uKTtcbiAgICAgICAgdGhpcy5maXJzdE1hcmtQbGFuID1cbiAgICAgICAgICAgIGF3YWl0IHRoaXMubWF0dGVycG9ydEltcG9ydFNlcnZpY2Uuc2RrLlJlbmRlcmVyLmdldFNjcmVlblBvc2l0aW9uKHtcbiAgICAgICAgICAgICAgICB4OiBwb3NpdGlvbi54LFxuICAgICAgICAgICAgICAgIHk6IHBvc2l0aW9uLnksXG4gICAgICAgICAgICAgICAgejogcG9zaXRpb24ueixcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB0aGlzLnNlY29uZE1hcmtQbGFuID1cbiAgICAgICAgICAgIGF3YWl0IHRoaXMubWF0dGVycG9ydEltcG9ydFNlcnZpY2Uuc2RrLlJlbmRlcmVyLmdldFNjcmVlblBvc2l0aW9uKHtcbiAgICAgICAgICAgICAgICB4OiBwb3NpdGlvbi54LFxuICAgICAgICAgICAgICAgIHk6IDAsXG4gICAgICAgICAgICAgICAgejogMCxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICBjb25zdCBkZWx0YVpWaXNpdCA9IDAgLSBwb3NpdGlvbi56O1xuICAgICAgICBsZXQgZGVsdGFYUGxhbiA9IHRoaXMuc2Vjb25kTWFya1BsYW4ueCAtIHRoaXMuZmlyc3RNYXJrUGxhbi54O1xuICAgICAgICBpZiAoZGVsdGFYUGxhbiA9PT0gMCkge1xuICAgICAgICAgICAgLy8gY29uc29sZS5sb2coXCJ3ZSBtb3ZlZCBhbG9uZyBZIGF4aXMgb24gUGxhblwiKTtcbiAgICAgICAgICAgIGNvbnN0IGRlbHRhWVBsYW4gPSB0aGlzLnNlY29uZE1hcmtQbGFuLnkgLSB0aGlzLmZpcnN0TWFya1BsYW4ueTtcbiAgICAgICAgICAgIHRoaXMuY2FsaWJyYWdlLm5hbWVZQXhpcyA9IFwielwiO1xuICAgICAgICAgICAgdGhpcy5jYWxpYnJhZ2UubmFtZVhBeGlzID0gXCJ4XCI7XG4gICAgICAgICAgICB0aGlzLmNhbGlicmFnZS5vZmZzZXRZID0gdGhpcy5zZWNvbmRNYXJrUGxhbi55O1xuICAgICAgICAgICAgdGhpcy5jYWxpYnJhZ2Uuc2NhbGVZID0gZGVsdGFZUGxhbiAvIGRlbHRhWlZpc2l0O1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgLy8gY29uc29sZS5sb2coXCIgd2UgbW92ZWQgYWxvbmcgWCBheGlzIG9uIFBsYW5cIik7XG4gICAgICAgICAgICB0aGlzLmNhbGlicmFnZS5uYW1lWUF4aXMgPSBcInhcIjtcbiAgICAgICAgICAgIHRoaXMuY2FsaWJyYWdlLm5hbWVYQXhpcyA9IFwielwiO1xuICAgICAgICAgICAgdGhpcy5jYWxpYnJhZ2Uub2Zmc2V0WCA9IHRoaXMuc2Vjb25kTWFya1BsYW4ueDtcbiAgICAgICAgICAgIHRoaXMuY2FsaWJyYWdlLnNjYWxlWCA9IGRlbHRhWFBsYW4gLyBkZWx0YVpWaXNpdDtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCB0aGlyZE1hcmtQbGFuID1cbiAgICAgICAgICAgIGF3YWl0IHRoaXMubWF0dGVycG9ydEltcG9ydFNlcnZpY2Uuc2RrLlJlbmRlcmVyLmdldFNjcmVlblBvc2l0aW9uKHtcbiAgICAgICAgICAgICAgICB4OiAwLFxuICAgICAgICAgICAgICAgIHk6IDAsXG4gICAgICAgICAgICAgICAgejogcG9zaXRpb24ueixcbiAgICAgICAgICAgIH0pO1xuICAgICAgICBjb25zdCBkZWx0YVhWaXNpdCA9IDAgLSBwb3NpdGlvbi54O1xuICAgICAgICBpZiAoZGVsdGFYUGxhbiA9PT0gMCkge1xuICAgICAgICAgICAgLy8gY29uc29sZS5sb2coXCIgd2UgbW92ZWQgYWxvbmcgWCBheGlzIG9uIFBsYW5cIik7XG4gICAgICAgICAgICBkZWx0YVhQbGFuID0gdGhpcmRNYXJrUGxhbi54IC0gdGhpcy5maXJzdE1hcmtQbGFuLng7XG4gICAgICAgICAgICB0aGlzLmNhbGlicmFnZS5vZmZzZXRYID0gdGhpcmRNYXJrUGxhbi54O1xuICAgICAgICAgICAgdGhpcy5jYWxpYnJhZ2Uuc2NhbGVYID0gZGVsdGFYUGxhbiAvIGRlbHRhWFZpc2l0O1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgY29uc3QgZGVsdGFZUGxhbiA9IHRoaXJkTWFya1BsYW4ueSAtIHRoaXMuZmlyc3RNYXJrUGxhbi55O1xuICAgICAgICAgICAgdGhpcy5jYWxpYnJhZ2Uub2Zmc2V0WSA9IHRoaXJkTWFya1BsYW4ueTtcbiAgICAgICAgICAgIHRoaXMuY2FsaWJyYWdlLnNjYWxlWSA9IGRlbHRhWVBsYW4gLyBkZWx0YVhWaXNpdDtcbiAgICAgICAgfVxuXG4gICAgICAgIC8qKiBUYWtlIGNvbnNpZGlyYXRpb24gb2YgcGFuIGFuZCB6b29tIG9mIHBsYW4gb24gY2FudmFzICovXG4gICAgICAgIGNvbnN0IHRyYW5zZm9ybUluZm8gPSB0aGlzLnBhbnpvb20uZ2V0VHJhbnNmb3JtKCk7XG4gICAgICAgIGNvbnN0IHsgc2NhbGUsIHgsIHkgfSA9IHRyYW5zZm9ybUluZm87XG4gICAgICAgIC8vIGNvbnNvbGUubG9nKHRyYW5zZm9ybUluZm8pO1xuICAgICAgICB0aGlzLmNhbGlicmFnZS5vZmZzZXRYUGxhbiA9IHg7XG4gICAgICAgIHRoaXMuY2FsaWJyYWdlLm9mZnNldFlQbGFuID0geTtcbiAgICAgICAgdGhpcy5jYWxpYnJhZ2Uuc2NhbGVQbGFuID0gc2NhbGU7XG4gICAgICAgIGNvbnNvbGUubG9nKHRoaXMuY2FsaWJyYWdlKTtcbiAgICB9XG5cbiAgICAvKiogUGxhY2Ugc3dlZXBzICovXG4gICAgYXN5bmMgb25QbGFjZVN3ZWVwcygpIHtcbiAgICAgICAgLyoqIERpc3BsYXkgYWxsIHNjYW4gKi9cbiAgICAgICAgY29uc3Qgem9uZSA9IGF3YWl0IHRoaXMuem9uZVNlcnZpY2UuZ2V0Wm9uZSh0aGlzLmNob3NlblBsYW4uem9uZUlEKTtcblxuICAgICAgICBpZiAoem9uZSkge1xuICAgICAgICAgICAgdGhpcy5jdXJyZW50Wm9uZSA9IHpvbmU7XG4gICAgICAgICAgICBjb25zdCBuYXZpZ2F0aW9ucyA9XG4gICAgICAgICAgICAgICAgYXdhaXQgdGhpcy5uYXZpZ2F0aW9uU2VydmljZS5nZXROYXZpZ2F0aW9uc0ZvclpvbmUoXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuY3VycmVudFpvbmUsXG4gICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIHRoaXMuY3VycmVudE5hdmlnYXRpb25zID0gbmF2aWdhdGlvbnM7XG4gICAgICAgICAgICBhd2FpdCB0aGlzLmNhbGlicmF0ZSgpO1xuICAgICAgICAgICAgaWYgKG5hdmlnYXRpb25zLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IG5hdmlnYXRpb24gb2YgbmF2aWdhdGlvbnMpIHsgICAgICAgICAgICAgICAgICAgIFxuICAgICAgICAgICAgICAgICAgICBjb25zdCB0ZXN0UG9zaXRpb24gPSBKU09OLnBhcnNlKG5hdmlnYXRpb24ucG9zaXRpb24pO1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBwb3NpdGlvblggPVxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jYWxpYnJhZ2UubmFtZVhBeGlzID09PSBcInhcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgID8gdGVzdFBvc2l0aW9uLnhcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA6IHRlc3RQb3NpdGlvbi56O1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBwb3NpdGlvblkgPVxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jYWxpYnJhZ2UubmFtZVlBeGlzID09PSBcInhcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgID8gdGVzdFBvc2l0aW9uLnhcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA6IHRlc3RQb3NpdGlvbi56O1xuICAgICAgICAgICAgICAgICAgICBjb25zdCB0ZXN0WCA9XG4gICAgICAgICAgICAgICAgICAgICAgICBwb3NpdGlvblggKiB0aGlzLmNhbGlicmFnZS5zY2FsZVggK1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jYWxpYnJhZ2Uub2Zmc2V0WDtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgdGVzdFkgPVxuICAgICAgICAgICAgICAgICAgICAgICAgcG9zaXRpb25ZICogdGhpcy5jYWxpYnJhZ2Uuc2NhbGVZICtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY2FsaWJyYWdlLm9mZnNldFk7XG4gICAgICAgICAgICAgICAgICAgIC8vIGNvbnNvbGUubG9nKFwidGVzdCBwb3NpdGlvbiBHUkVFTlwiLCB0ZXN0WCwgdGVzdFkpO1xuICAgICAgICAgICAgICAgICAgICBjb25zdCB0cmFuc2Zvcm1lZFggPVxuICAgICAgICAgICAgICAgICAgICAgICAgKHRlc3RYIC0gdGhpcy5jYWxpYnJhZ2Uub2Zmc2V0WFBsYW4pIC9cbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY2FsaWJyYWdlLnNjYWxlUGxhbjsgLy8gd2UgYXJlIHVuZG9pbmcgdGhlIHBhbiBhbmQgem9vbVxuICAgICAgICAgICAgICAgICAgICBjb25zdCB0cmFuc2Zvcm1lZFkgPVxuICAgICAgICAgICAgICAgICAgICAgICAgKHRlc3RZIC0gdGhpcy5jYWxpYnJhZ2Uub2Zmc2V0WVBsYW4pIC9cbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY2FsaWJyYWdlLnNjYWxlUGxhbjtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5wb3NpdGlvbnMucHVzaCh7XG4gICAgICAgICAgICAgICAgICAgICAgICBuYXZJRDogbmF2aWdhdGlvbi5pZCxcbiAgICAgICAgICAgICAgICAgICAgICAgIHBsYW5JRDogdGhpcy5jaG9zZW5QbGFuLmlkLFxuICAgICAgICAgICAgICAgICAgICAgICAgeDogdHJhbnNmb3JtZWRYLFxuICAgICAgICAgICAgICAgICAgICAgICAgeTogdHJhbnNmb3JtZWRZLFxuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgaWNvblNpemUgPSAzMCAqIHRoaXMuY2FsaWJyYWdlLnNjYWxlUGxhbjtcbiAgICAgICAgICAgICAgICAgICAgY29uc3Qgc2hpZnQgPSBpY29uU2l6ZSAvIDI7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZHJhd0ltYWdlKFxuICAgICAgICAgICAgICAgICAgICAgICAgXCJodHRwczovL2FwaS5pY29uaWZ5LmRlc2lnbi9tZGk6YWRqdXN0LnN2Zz9jb2xvcj1ncmVlbiZoZWlnaHQ9MzAmd2lkdGg9MzBcIixcbiAgICAgICAgICAgICAgICAgICAgICAgIHRyYW5zZm9ybWVkWCAtIHNoaWZ0LFxuICAgICAgICAgICAgICAgICAgICAgICAgdHJhbnNmb3JtZWRZIC0gc2hpZnQsXG4gICAgICAgICAgICAgICAgICAgICAgICB0cnVlLFxuICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKiBTYXZlIGNhbGlicmF0aW9uICovXG4gICAgYXN5bmMgb25TYXZlKCkge1xuICAgICAgICBpZiAodGhpcy5jdXJyZW50Wm9uZSkge1xuICAgICAgICAgICAgLyoqIE5vcm1hbGl6ZSB3aXRoIHRoZSB6b29tICovXG4gICAgICAgICAgICAvLyB0aGlzLmNhbGlicmFnZS5vZmZzZXRYIC89IHRoaXMuY2FudmFzWm9vbTtcbiAgICAgICAgICAgIC8vIHRoaXMuY2FsaWJyYWdlLm9mZnNldFkgLz0gdGhpcy5jYW52YXNab29tO1xuICAgICAgICAgICAgLy8gdGhpcy5jYWxpYnJhZ2UueCAvPSB0aGlzLmNhbnZhc1pvb207XG4gICAgICAgICAgICAvLyB0aGlzLmNhbGlicmFnZS55IC89IHRoaXMuY2FudmFzWm9vbTtcbiAgICAgICAgICAgIHRoaXMuY2FsaWJyYWdlLm5ldyA9IHRydWU7XG4gICAgICAgICAgICB0aGlzLmNhbGlicmFnZS5pbWdXaWR0aCA9IHRoaXMuY2FudmFzU2l6ZS53O1xuICAgICAgICAgICAgdGhpcy5jYWxpYnJhZ2UuaW1nSGVpZ2h0ID0gdGhpcy5jYW52YXNTaXplLmg7XG5cbiAgICAgICAgICAgIGF3YWl0IHRoaXMucGxhblNlcnZpY2UudXBkYXRlUGxhbih7XG4gICAgICAgICAgICAgICAgaWQ6IHRoaXMuY2hvc2VuUGxhbi5pZCxcbiAgICAgICAgICAgICAgICBjYWxpYnJhdGlvbjogSlNPTi5zdHJpbmdpZnkodGhpcy5jYWxpYnJhZ2UpLFxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBhd2FpdCBQcm9taXNlLmFsbChcbiAgICAgICAgICAgICAgICB0aGlzLnBvc2l0aW9ucy5tYXAoYXN5bmMgKHBvc2l0aW9uKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHsgbmF2SUQgfSA9IHBvc2l0aW9uO1xuICAgICAgICAgICAgICAgICAgICBkZWxldGUgcG9zaXRpb24ubmF2SUQ7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IG5hdiA9IHRoaXMuY3VycmVudE5hdmlnYXRpb25zLmZpbmQoXG4gICAgICAgICAgICAgICAgICAgICAgICAoX25hdikgPT4gX25hdi5pZCA9PT0gbmF2SUQsXG4gICAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgICAgIGxldCBwb3NpdGlvbnNEYXRhVG9VcGRhdGU7XG4gICAgICAgICAgICAgICAgICAgIGlmIChuYXYucG9zaXRpb25PblBsYW4pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHBvc2l0aW9uT25QbGFuID0gbmF2LnBvc2l0aW9uT25QbGFuLm1hcCgoZW50cnkpID0+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgSlNPTi5wYXJzZShlbnRyeSksXG4gICAgICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgcG9zaXRpb25Gb3JDdXJyZW50UGxhbiA9IHBvc2l0aW9uT25QbGFuLmZpbmQoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgKGVudHJ5KSA9PiBlbnRyeS5wbGFuSUQgPT09IHRoaXMuY2hvc2VuUGxhbi5pZCxcbiAgICAgICAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAocG9zaXRpb25Gb3JDdXJyZW50UGxhbikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBvc2l0aW9uT25QbGFuLnNwbGljZShcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcG9zaXRpb25PblBsYW4uaW5kZXhPZihwb3NpdGlvbkZvckN1cnJlbnRQbGFuKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgMSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcG9zaXRpb24sXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcG9zaXRpb25PblBsYW4ucHVzaChwb3NpdGlvbik7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBwb3NpdGlvbnNEYXRhVG9VcGRhdGUgPSBbLi4ucG9zaXRpb25PblBsYW5dO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgcG9zaXRpb25zRGF0YVRvVXBkYXRlID0gW3Bvc2l0aW9uXTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAvLyBjb25zb2xlLmxvZyhwb3NpdGlvbnNEYXRhVG9VcGRhdGUpO1xuICAgICAgICAgICAgICAgICAgICBhd2FpdCB0aGlzLm5hdmlnYXRpb25TZXJ2aWNlLnVwZGF0ZU5hdmlnYXRpb24oe1xuICAgICAgICAgICAgICAgICAgICAgICAgaWQ6IG5hdklELFxuICAgICAgICAgICAgICAgICAgICAgICAgcG9zaXRpb25PblBsYW46IHBvc2l0aW9uc0RhdGFUb1VwZGF0ZS5tYXAoKGVudHJ5KSA9PlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIEpTT04uc3RyaW5naWZ5KGVudHJ5KSxcbiAgICAgICAgICAgICAgICAgICAgICAgICksXG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIH0pLFxuICAgICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLm1hdHRlcnBvcnRJbXBvcnRTZXJ2aWNlLnJlbW92ZUZyYW1lKCk7XG5cbiAgICAgICAgdGhpcy5yb3V0ZXIubmF2aWdhdGUoW1xuICAgICAgICAgICAgXCIvZGFzaGJvYXJkL2xvY2FsaXNhdGlvblwiLFxuICAgICAgICAgICAgdGhpcy5zcGFjZUlELFxuICAgICAgICAgICAgXCJwbGFuc1wiLFxuICAgICAgICBdKTtcbiAgICAgICAgYWxlcnQodGhpcy50cmFuc2xhdGUuaW5zdGFudChcImNhbGlicmF0aW9uLnN1Y2Nlc3NcIikpO1xuICAgIH1cblxuICAgIC8qKiBSZXNldCB0aGUgY2FudmFzICovXG4gICAgb25SZXNldCgpIHtcbiAgICAgICAgdGhpcy5yZWZsZWN0SCA9IGZhbHNlO1xuICAgICAgICB0aGlzLnJlZmxlY3RWID0gZmFsc2U7XG4gICAgICAgIHRoaXMucHJldmlldyA9IGZhbHNlO1xuXG4gICAgICAgIHRoaXMuY29uZmlndXJlQ2FudmFzKCk7XG4gICAgfVxuXG4gICAgLyoqIENhbmNlbCwgbGVhdmUgKi9cbiAgICBvbkNhbmNlbCgpIHtcbiAgICAgICAgdGhpcy5tYXR0ZXJwb3J0SW1wb3J0U2VydmljZS5yZW1vdmVGcmFtZSgpO1xuICAgICAgICB0aGlzLnJvdXRlci5uYXZpZ2F0ZShbXG4gICAgICAgICAgICBcIi9kYXNoYm9hcmQvbG9jYWxpc2F0aW9uXCIsXG4gICAgICAgICAgICB0aGlzLnNwYWNlSUQsXG4gICAgICAgICAgICBcInBsYW5zXCIsXG4gICAgICAgIF0pO1xuICAgICAgICBhbGVydCh0aGlzLnRyYW5zbGF0ZS5pbnN0YW50KFwiY2FsaWJyYXRpb24uY2FuY2VsZWRcIikpO1xuICAgIH1cblxuICAgIGFzeW5jIG9uRmxvb3JDbGljayhmbG9vcikge1xuICAgICAgICB0aGlzLmN1cnJlbnRGbG9vciA9IGZsb29yO1xuICAgICAgICBhd2FpdCB0aGlzLm1hdHRlcnBvcnRJbXBvcnRTZXJ2aWNlLm1vdmVUb0Zsb29yKGZsb29yLmlkKTtcbiAgICB9XG5cbiAgICBvbkFjdGl2YXRlWm9vbUNoYW5nZSgpIHtcbiAgICAgICAgdGhpcy56b29tQ2FuQmVDaGFuZ2VkID0gIXRoaXMuem9vbUNhbkJlQ2hhbmdlZDtcbiAgICAgICAgY29uc3QgaWZyYW1lID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvcihcIiN2aWV3ZXItZnJhbWVcIikgYXMgSFRNTEVsZW1lbnQ7XG4gICAgICAgIGlmIChpZnJhbWUpIHtcbiAgICAgICAgICAgIGlmcmFtZS5zdHlsZS56SW5kZXggPSB0aGlzLnpvb21DYW5CZUNoYW5nZWQgPyBcIjFcIiA6IFwiMFwiO1xuICAgICAgICB9XG4gICAgfVxuXG59XG4iLCI8ZGl2IGNsYXNzPVwicm93IG10LTNcIj5cbiAgICA8ZGl2IGNsYXNzPVwiY29sXCI+XG4gICAgICAgIDxkaXYgY2xhc3M9XCJtLTNcIj5cbiAgICAgICAgICAgIDxsaWItdGFiLW5hdmlnYXRpb24gW21lbnVJdGVtc109J21lbnVJdGVtcyc+PC9saWItdGFiLW5hdmlnYXRpb24+XG4gICAgICAgIDwvZGl2PlxuICAgIDwvZGl2PlxuPC9kaXY+XG5cbjxkaXYgaWQ9XCJyb3dDYW52YXNcIj5cbiAgICA8ZGl2ICNjYW52YXNEaXYgaWQ9XCJjYW52YXNEaXZcIj5cblxuICAgICAgICA8ZGl2IGlkPVwidmlld2VyLWZyYW1lXCIgW3N0eWxlLnBvaW50ZXItZXZlbnRzXT1cInpvb21DYW5CZUNoYW5nZWQ/J2F1dG8nOidub25lJ1wiPlxuICAgICAgICAgICAgPCEtLSA8ZGl2IGNsYXNzPVwiYmx1clwiPjwvZGl2PiAtLT5cbiAgICAgICAgPC9kaXY+XG4gICAgICAgIDxjYW52YXMgaWQ9XCJjYW52YXNcIiBbbmdTdHlsZV09XCJ7J29wYWNpdHknOiAocHJldmlld3x8bG9hZGluZykgPyAnMScgOiAnY2FsYygnICsgb3BhY2l0eSArICcvIDEwMCknfVwiPjwvY2FudmFzPlxuICAgIDwvZGl2PlxuXG4gICAgPGRpdiBjbGFzcz1cImNhbGlicmF0aW9uLXRvb2xzIGNvbnRhaW5lci1mbHVpZFwiICpuZ0lmPVwiIShwcmV2aWV3IHx8IGxvYWRpbmcpXCI+XG4gICAgICAgIDxoMT57eydDYWxpYnJhdGlvbiB0b29sJyB8IHRyYW5zbGF0ZX19PC9oMT5cbiAgICAgICAgPGRpdiBjbGFzcz1cInRvb2xcIj5cbiAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJyb3cgbXMtMCBtZS0wIGxlZ2VuZFwiPlxuICAgICAgICAgICAgICAgIDxkaXYgW25nU3R5bGVdPVwieydvcGFjaXR5JzogJ2NhbGMoJyArICgtKG9wYWNpdHktMTAwKSsxMCkgKyAnLyAxMDApJ31cIj57eydMZXNzJyB8IHRyYW5zbGF0ZX19PC9kaXY+XG4gICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImxlZ2VuZC10aXRsZVwiPnt7J1BsYW4gT3BhY2l0eScgfCB0cmFuc2xhdGUgfX08L2Rpdj5cbiAgICAgICAgICAgICAgICA8ZGl2IFtuZ1N0eWxlXT1cInsnb3BhY2l0eSc6ICdjYWxjKCcgKyAob3BhY2l0eSsxMCkgKyAnLyAxMDApJ31cIj57eydNb3JlJyB8IHRyYW5zbGF0ZX19PC9kaXY+XG4gICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJyb3cgbXMtMCBtZS0wIFwiPlxuICAgICAgICAgICAgICAgIDxpbnB1dCBbZGlzYWJsZWRdPVwiZmFsc2VcIiBbbmdNb2RlbE9wdGlvbnNdPVwie3N0YW5kYWxvbmU6IHRydWV9XCIgWyhuZ01vZGVsKV09XCJvcGFjaXR5XCIgdHlwZT1cInJhbmdlXCJcbiAgICAgICAgICAgICAgICAgICAgY2xhc3M9XCJmb3JtLXJhbmdlXCIgbWluPVwiMFwiIG1heD1cIjEwMFwiIHZhbHVlPVwiNTBcIiBpZD1cIm9wYWNpdHlcIj5cbiAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICA8L2Rpdj5cbiAgICAgICAgPGRpdiBjbGFzcz1cInRvb2xcIj5cbiAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJyb3cgbXMtMCBtZS0wIFwiPlxuICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJsYWJlbC1sZWdlbmRcIj57eydDaGFuZ2UgVmlzaXQgRmxvb3InIHwgdHJhbnNsYXRlfX08L2Rpdj5cbiAgICAgICAgICAgICAgICA8ZGl2IG5nYkRyb3Bkb3duIGNsYXNzPVwiZC1pbmxpbmUtYmxvY2sgbXMtM1wiPlxuICAgICAgICAgICAgICAgICAgICA8YnV0dG9uIGNsYXNzPVwiYnRuIGJ0bi1sYWJlbC1maWxlIHJvdW5kZWQtcGlsbFwiIGlkPVwiZHJvcGRvd25CYXNpYzFcIiBuZ2JEcm9wZG93blRvZ2dsZT5cbiAgICAgICAgICAgICAgICAgICAgICAgIHt7Y3VycmVudEZsb29yID8gY3VycmVudEZsb29yLmlkIDogKCdGbG9vcicgfCB0cmFuc2xhdGUpIH19PC9idXR0b24+XG4gICAgICAgICAgICAgICAgICAgIDxkaXYgbmdiRHJvcGRvd25NZW51IGFyaWEtbGFiZWxsZWRieT1cImRyb3Bkb3duQmFzaWMxXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICA8YnV0dG9uIG5nYkRyb3Bkb3duSXRlbSAqbmdGb3I9XCJsZXQgZmxvb3Igb2YgZmxvb3JzXCIgKGNsaWNrKT1cIm9uRmxvb3JDbGljayhmbG9vcilcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB7eyBmbG9vci5uYW1lLmxlbmd0aCA+IDAgPyBmbG9vci5uYW1lIDogKCdGbG9vciAnICsgZmxvb3IuaWQpIH19XG4gICAgICAgICAgICAgICAgICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICA8L2Rpdj5cblxuICAgICAgICA8L2Rpdj5cbiAgICAgICAgPGRpdiBjbGFzcz1cInRvb2xcIj5cbiAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJyb3cgbXMtMCBtZS0wIFwiPlxuICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJsYWJlbC1sZWdlbmQgbWUtM1wiPnt7J1Bhbi9ab29tIFZpc2l0JyB8IHRyYW5zbGF0ZX19IHt7em9vbUNhbkJlQ2hhbmdlZCA/IFwiT05cIiA6IFwiT0ZGXCJ9fVxuICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICAgIDxpbnB1dCB0eXBlPVwiY2hlY2tib3hcIiAoY2hhbmdlKT1cIm9uQWN0aXZhdGVab29tQ2hhbmdlKClcIiBzdHlsZT1cIm1hcmdpbi10b3A6IDVweDtcIj5cbiAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwiY2FyZCBib3JkZXItd2FybmluZyBtYi0zIG10LTNcIiAqbmdJZj1cInpvb21DYW5CZUNoYW5nZWRcIj5cbiAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImNhcmQtYm9keSB0ZXh0LXdhcm5pbmdcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgIDxoNSBjbGFzcz1cImNhcmQtdGl0bGVcIj57e1wiY2FsaWJyYXRpb24ud2FpdC1tZXNzYWdlXCIgfCB0cmFuc2xhdGV9fTwvaDU+XG4gICAgICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgIDwvZGl2PlxuXG4gICAgICAgIDxkaXYgY2xhc3M9XCJhY3Rpb25cIj5cbiAgICAgICAgICAgIDxidXR0b24gdHlwZT1cImJ1dHRvblwiIGNsYXNzPVwiYnRuIGJ0bi1vdXRsaW5lLXByaW1hcnkgcm91bmRlZC1waWxsXCIgKGNsaWNrKT1cIm9uUHJldmlldygpXCJcbiAgICAgICAgICAgICAgICBbZGlzYWJsZWRdPVwiem9vbUNhbkJlQ2hhbmdlZFwiPnt7J1ByZXZpZXcnIHwgdHJhbnNsYXRlfX08L2J1dHRvbj5cbiAgICAgICAgICAgIDxidXR0b24gdHlwZT1cImJ1dHRvblwiIGNsYXNzPVwiYnRuIGJ0bi1vdXRsaW5lLXByaW1hcnkgcm91bmRlZC1waWxsXCIgKGNsaWNrKT1cIm9uQ2FuY2VsKClcIj57eydDYW5jZWwnIHxcbiAgICAgICAgICAgICAgICB0cmFuc2xhdGV9fTwvYnV0dG9uPlxuXG4gICAgICAgIDwvZGl2PlxuXG4gICAgPC9kaXY+XG4gICAgPGRpdiBjbGFzcz1cImNhbGlicmF0aW9uLXRvb2xzIGNvbnRhaW5lci1mbHVpZFwiICpuZ0lmPVwicHJldmlld1wiPlxuICAgICAgICA8aDE+e3snVmFsaWRhdGlvbicgfCB0cmFuc2xhdGV9fTwvaDE+XG4gICAgICAgIDxkaXYgY2xhc3M9XCJhY3Rpb25cIj5cbiAgICAgICAgICAgIDxidXR0b24gdHlwZT1cImJ1dHRvblwiIGNsYXNzPVwiYnRuIGJ0bi1vdXRsaW5lLXByaW1hcnkgcm91bmRlZC1waWxsXCIgKGNsaWNrKT1cIm9uU2F2ZSgpXCI+e3snVmFsaWRhdGUnIHxcbiAgICAgICAgICAgICAgICB0cmFuc2xhdGV9fTwvYnV0dG9uPlxuICAgICAgICAgICAgPGJ1dHRvbiB0eXBlPVwiYnV0dG9uXCIgY2xhc3M9XCJidG4gYnRuLW91dGxpbmUtcHJpbWFyeSByb3VuZGVkLXBpbGxcIiAoY2xpY2spPVwib25SZXNldCgpXCI+e3snUmVzZXQnIHxcbiAgICAgICAgICAgICAgICB0cmFuc2xhdGV9fTwvYnV0dG9uPlxuICAgICAgICAgICAgPGJ1dHRvbiB0eXBlPVwiYnV0dG9uXCIgY2xhc3M9XCJidG4gYnRuLW91dGxpbmUtcHJpbWFyeSByb3VuZGVkLXBpbGxcIiAoY2xpY2spPVwib25DYW5jZWwoKVwiPnt7J0NhbmNlbCcgfFxuICAgICAgICAgICAgICAgIHRyYW5zbGF0ZX19PC9idXR0b24+XG5cbiAgICAgICAgPC9kaXY+XG4gICAgPC9kaXY+XG5cblxuICAgIDxkaXYgY2xhc3M9XCJjYWxpYnJhdGlvbi10b29scyBjb250YWluZXItZmx1aWRcIiAqbmdJZj1cImxvYWRpbmdcIj5cbiAgICAgICAgPGgzPnt7XCJXYWl0aW5nIGZvciBNYXR0ZXJwb3J0XCIgfCB0cmFuc2xhdGV9fS4uLjwvaDM+XG4gICAgICAgIDxkaXYgY2xhc3M9XCJkLWZsZXgganVzdGlmeS1jb250ZW50LWNlbnRlclwiPlxuICAgICAgICAgICAgPGRpdiBjbGFzcz1cInNwaW5uZXItYm9yZGVyXCIgcm9sZT1cInN0YXR1c1wiPlxuICAgICAgICAgICAgICAgIDxzcGFuIGNsYXNzPVwidmlzdWFsbHktaGlkZGVuXCI+TG9hZGluZy4uLjwvc3Bhbj5cbiAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICA8L2Rpdj5cblxuICAgIDwvZGl2PlxuPC9kaXY+Il19