@smarterplan/ngx-smarterplan-core 1.2.38 → 1.2.45
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +24 -24
- package/esm2020/lib/components/csv-export/csv-export.component.mjs +59 -59
- package/esm2020/lib/components/loader/loader.component.mjs +23 -23
- package/esm2020/lib/components/menu-bar/avatar/avatar.component.mjs +80 -80
- package/esm2020/lib/components/menu-bar/menu-bar.component.mjs +99 -99
- package/esm2020/lib/components/menu-bar/navigation-bar/navigation-bar.component.mjs +384 -384
- package/esm2020/lib/components/menu-bar/range-date-picker/range-date-picker.component.mjs +147 -147
- package/esm2020/lib/components/modal-switch-visit/modal-switch-visit.component.mjs +40 -40
- package/esm2020/lib/components/search-bar/search-bar.component.mjs +63 -63
- package/esm2020/lib/components/support-modal/support-modal.component.mjs +66 -66
- package/esm2020/lib/config.mjs +4 -4
- package/esm2020/lib/helpers.service.mjs +470 -470
- package/esm2020/lib/matterport-extensions/hsl-loader/HlsLoader.mjs +69 -69
- package/esm2020/lib/matterport-extensions/nest-thermostat/CanvasImage.mjs +51 -51
- package/esm2020/lib/matterport-extensions/nest-thermostat/CanvasRenderer.mjs +61 -61
- package/esm2020/lib/matterport-extensions/nest-thermostat/NestThermostat.mjs +158 -158
- package/esm2020/lib/matterport-extensions/nest-thermostat/PlaneRenderer.mjs +85 -85
- package/esm2020/lib/matterport-extensions/scene-component/SceneComponent.mjs +128 -128
- package/esm2020/lib/matterport-extensions/security-camera/SecurityCamera.mjs +249 -249
- package/esm2020/lib/matterport-extensions/tv-player/TvPlayer.mjs +98 -98
- package/esm2020/lib/matterport-extensions/video-renderer/VideoRenderer.mjs +64 -64
- package/esm2020/lib/matterport-extensions/view-frustum-mesh/ViewFrustumMesh.mjs +221 -221
- package/esm2020/lib/mattertagData.mjs +165 -165
- package/esm2020/lib/ngx-smarterplan-core.module.mjs +122 -122
- package/esm2020/lib/ngx-smarterplan-core.service.mjs +14 -14
- package/esm2020/lib/pipes/duration-to-string.pipe.mjs +66 -66
- package/esm2020/lib/pipes/format-date-number-to-digits.pipe.mjs +30 -30
- package/esm2020/lib/pipes/hashtag-from-id.pipe.mjs +26 -26
- package/esm2020/lib/pipes/safe-url.pipe.mjs +20 -20
- package/esm2020/lib/pipes/time-date-to-local-string.pipe.mjs +104 -104
- package/esm2020/lib/pipes/username-from-id.pipe.mjs +29 -29
- package/esm2020/lib/services/amplify-cache.service.mjs +72 -72
- package/esm2020/lib/services/base-tab.service.mjs +24 -24
- package/esm2020/lib/services/baseVisibility.service.mjs +18 -18
- package/esm2020/lib/services/content.service.mjs +135 -135
- package/esm2020/lib/services/filter.service.mjs +599 -599
- package/esm2020/lib/services/intervention.service.mjs +236 -236
- package/esm2020/lib/services/locale.service.mjs +45 -45
- package/esm2020/lib/services/matterport-import.service.mjs +340 -340
- package/esm2020/lib/services/matterport.service.mjs +1587 -1578
- package/esm2020/lib/services/models/affectation.service.mjs +60 -60
- package/esm2020/lib/services/models/base-object.service.mjs +70 -70
- package/esm2020/lib/services/models/capture.service.mjs +34 -34
- package/esm2020/lib/services/models/comment.service.mjs +98 -98
- package/esm2020/lib/services/models/domain.service.mjs +78 -78
- package/esm2020/lib/services/models/equipment.service.mjs +683 -683
- package/esm2020/lib/services/models/event.service.mjs +128 -128
- package/esm2020/lib/services/models/feature.service.mjs +380 -364
- package/esm2020/lib/services/models/hashtag.service.mjs +38 -38
- package/esm2020/lib/services/models/layer.service.mjs +33 -33
- package/esm2020/lib/services/models/measurement.service.mjs +199 -199
- package/esm2020/lib/services/models/mission.service.mjs +206 -206
- package/esm2020/lib/services/models/navigation.service.mjs +92 -92
- package/esm2020/lib/services/models/node.service.mjs +31 -31
- package/esm2020/lib/services/models/object3D.service.mjs +364 -364
- package/esm2020/lib/services/models/operation.service.mjs +59 -59
- package/esm2020/lib/services/models/organisation.service.mjs +73 -73
- package/esm2020/lib/services/models/plan.service.mjs +799 -799
- package/esm2020/lib/services/models/poi.service.mjs +103 -103
- package/esm2020/lib/services/models/profile.service.mjs +58 -58
- package/esm2020/lib/services/models/property.service.mjs +44 -44
- package/esm2020/lib/services/models/space.service.mjs +204 -204
- package/esm2020/lib/services/models/template.service.mjs +41 -41
- package/esm2020/lib/services/models/ticket.service.mjs +526 -526
- package/esm2020/lib/services/models/visit.service.mjs +130 -130
- package/esm2020/lib/services/models/zone.service.mjs +225 -225
- package/esm2020/lib/services/navigator.service.mjs +212 -212
- package/esm2020/lib/services/s3.service.mjs +137 -137
- package/esm2020/lib/services/search.service.mjs +124 -124
- package/esm2020/lib/services/support.service.mjs +42 -42
- package/esm2020/lib/services/tag.service.mjs +111 -111
- package/esm2020/lib/services/user.service.mjs +501 -501
- package/esm2020/lib/services/validators.service.mjs +50 -50
- package/esm2020/lib/services/viewer.service.mjs +389 -389
- package/esm2020/lib/services/zone-drawer.service.mjs +76 -76
- package/esm2020/lib/services/zoneChange.service.mjs +30 -30
- package/esm2020/lib/types.service.mjs +311 -310
- package/esm2020/lib/validators/email.directive.mjs +7 -7
- package/esm2020/lib/validators/no-empty.directive.mjs +12 -12
- package/esm2020/lib/validators/number.directive.mjs +12 -12
- package/esm2020/lib/validators/text.directive.mjs +12 -12
- package/esm2020/public-api.mjs +72 -72
- package/esm2020/smarterplan-ngx-smarterplan-core.mjs +4 -4
- package/fesm2015/smarterplan-ngx-smarterplan-core.mjs +13009 -12983
- package/fesm2015/smarterplan-ngx-smarterplan-core.mjs.map +1 -1
- package/fesm2020/smarterplan-ngx-smarterplan-core.mjs +12258 -12232
- package/fesm2020/smarterplan-ngx-smarterplan-core.mjs.map +1 -1
- package/lib/components/csv-export/csv-export.component.d.ts +18 -18
- package/lib/components/loader/loader.component.d.ts +10 -10
- package/lib/components/menu-bar/avatar/avatar.component.d.ts +21 -21
- package/lib/components/menu-bar/menu-bar.component.d.ts +38 -38
- package/lib/components/menu-bar/navigation-bar/navigation-bar.component.d.ts +73 -73
- package/lib/components/menu-bar/range-date-picker/range-date-picker.component.d.ts +35 -35
- package/lib/components/modal-switch-visit/modal-switch-visit.component.d.ts +22 -22
- package/lib/components/search-bar/search-bar.component.d.ts +16 -16
- package/lib/components/support-modal/support-modal.component.d.ts +26 -26
- package/lib/config.d.ts +22 -22
- package/lib/helpers.service.d.ts +79 -79
- package/lib/matterport-extensions/hsl-loader/HlsLoader.d.ts +26 -26
- package/lib/matterport-extensions/nest-thermostat/CanvasImage.d.ts +31 -31
- package/lib/matterport-extensions/nest-thermostat/CanvasRenderer.d.ts +37 -37
- package/lib/matterport-extensions/nest-thermostat/NestThermostat.d.ts +42 -42
- package/lib/matterport-extensions/nest-thermostat/PlaneRenderer.d.ts +46 -46
- package/lib/matterport-extensions/scene-component/SceneComponent.d.ts +388 -388
- package/lib/matterport-extensions/security-camera/SecurityCamera.d.ts +47 -47
- package/lib/matterport-extensions/tv-player/TvPlayer.d.ts +26 -26
- package/lib/matterport-extensions/video-renderer/VideoRenderer.d.ts +26 -26
- package/lib/matterport-extensions/view-frustum-mesh/ViewFrustumMesh.d.ts +43 -43
- package/lib/mattertagData.d.ts +70 -70
- package/lib/ngx-smarterplan-core.module.d.ts +29 -29
- package/lib/ngx-smarterplan-core.service.d.ts +6 -6
- package/lib/pipes/duration-to-string.pipe.d.ts +12 -12
- package/lib/pipes/format-date-number-to-digits.pipe.d.ts +10 -10
- package/lib/pipes/hashtag-from-id.pipe.d.ts +10 -10
- package/lib/pipes/safe-url.pipe.d.ts +10 -10
- package/lib/pipes/time-date-to-local-string.pipe.d.ts +16 -16
- package/lib/pipes/username-from-id.pipe.d.ts +11 -11
- package/lib/services/amplify-cache.service.d.ts +37 -37
- package/lib/services/base-tab.service.d.ts +10 -10
- package/lib/services/baseVisibility.service.d.ts +9 -9
- package/lib/services/content.service.d.ts +28 -28
- package/lib/services/filter.service.d.ts +60 -60
- package/lib/services/intervention.service.d.ts +25 -25
- package/lib/services/locale.service.d.ts +23 -23
- package/lib/services/matterport-import.service.d.ts +53 -53
- package/lib/services/matterport.service.d.ts +336 -336
- package/lib/services/models/affectation.service.d.ts +14 -14
- package/lib/services/models/base-object.service.d.ts +20 -20
- package/lib/services/models/capture.service.d.ts +13 -13
- package/lib/services/models/comment.service.d.ts +26 -26
- package/lib/services/models/domain.service.d.ts +19 -19
- package/lib/services/models/equipment.service.d.ts +93 -93
- package/lib/services/models/event.service.d.ts +43 -43
- package/lib/services/models/feature.service.d.ts +75 -74
- package/lib/services/models/hashtag.service.d.ts +13 -13
- package/lib/services/models/layer.service.d.ts +11 -11
- package/lib/services/models/measurement.service.d.ts +51 -51
- package/lib/services/models/mission.service.d.ts +39 -39
- package/lib/services/models/navigation.service.d.ts +29 -29
- package/lib/services/models/node.service.d.ts +12 -12
- package/lib/services/models/object3D.service.d.ts +57 -57
- package/lib/services/models/operation.service.d.ts +15 -15
- package/lib/services/models/organisation.service.d.ts +19 -19
- package/lib/services/models/plan.service.d.ts +133 -133
- package/lib/services/models/poi.service.d.ts +25 -25
- package/lib/services/models/profile.service.d.ts +16 -16
- package/lib/services/models/property.service.d.ts +13 -13
- package/lib/services/models/space.service.d.ts +46 -46
- package/lib/services/models/template.service.d.ts +15 -15
- package/lib/services/models/ticket.service.d.ts +93 -93
- package/lib/services/models/visit.service.d.ts +24 -24
- package/lib/services/models/zone.service.d.ts +50 -50
- package/lib/services/navigator.service.d.ts +61 -61
- package/lib/services/s3.service.d.ts +14 -14
- package/lib/services/search.service.d.ts +20 -20
- package/lib/services/support.service.d.ts +17 -17
- package/lib/services/tag.service.d.ts +29 -29
- package/lib/services/user.service.d.ts +118 -118
- package/lib/services/validators.service.d.ts +18 -18
- package/lib/services/viewer.service.d.ts +110 -110
- package/lib/services/zone-drawer.service.d.ts +7 -7
- package/lib/services/zoneChange.service.d.ts +17 -17
- package/lib/types.service.d.ts +842 -840
- package/lib/validators/email.directive.d.ts +2 -2
- package/lib/validators/no-empty.directive.d.ts +2 -2
- package/lib/validators/number.directive.d.ts +2 -2
- package/lib/validators/text.directive.d.ts +2 -2
- package/package.json +1 -1
- package/public-api.d.ts +64 -64
- package/smarterplan-ngx-smarterplan-core.d.ts +5 -5
|
@@ -1,1578 +1,1587 @@
|
|
|
1
|
-
import { Inject, Injectable } from '@angular/core';
|
|
2
|
-
import { Subject } from 'rxjs';
|
|
3
|
-
//import * as serialijse from "serialijse";
|
|
4
|
-
import { getDistanceBetweenTwoPoints, poiTypeToString, wait, } from '../helpers.service';
|
|
5
|
-
import { MattertagData } from '../mattertagData';
|
|
6
|
-
import { FeatureType, MattertagActionMode, PoiType, SpModule, TagAction, ViewerInteractions, } from '../types.service';
|
|
7
|
-
import { Object3D } from 'three';
|
|
8
|
-
import { CameraMode } from '../types.service';
|
|
9
|
-
import { NestThermostat } from '../matterport-extensions/nest-thermostat/NestThermostat';
|
|
10
|
-
import { PlaneRenderer } from '../matterport-extensions/nest-thermostat/PlaneRenderer';
|
|
11
|
-
import { CanvasRenderer } from "../matterport-extensions/nest-thermostat/CanvasRenderer";
|
|
12
|
-
import { TvPlayer } from "../matterport-extensions/tv-player/TvPlayer";
|
|
13
|
-
import * as i0 from "@angular/core";
|
|
14
|
-
import * as i1 from "@angular/router";
|
|
15
|
-
import * as i2 from "./baseVisibility.service";
|
|
16
|
-
import * as i3 from "../config";
|
|
17
|
-
export class MatterportService {
|
|
18
|
-
constructor(config, router, activeRoute, visibilityService, ngZone) {
|
|
19
|
-
this.router = router;
|
|
20
|
-
this.activeRoute = activeRoute;
|
|
21
|
-
this.visibilityService = visibilityService;
|
|
22
|
-
this.ngZone = ngZone;
|
|
23
|
-
this.slots = []; //SlotNode[] = [];
|
|
24
|
-
this.nodes = [];
|
|
25
|
-
this.lastCameraPosition = { x: 0.0, y: 0.0, z: 0.0 };
|
|
26
|
-
this.cursorPositionButtonDisplayed = false;
|
|
27
|
-
// Measure mode
|
|
28
|
-
this.isMeasureModeOn = false;
|
|
29
|
-
this.interactionMode = ViewerInteractions.DEFAULT;
|
|
30
|
-
// List of created Mattertag IDs in the current viewer session
|
|
31
|
-
this.mattertagIDs = [];
|
|
32
|
-
// Dictionnary of MattertagID and its data (mattertagData)
|
|
33
|
-
this.dictionnaryTags = new Map();
|
|
34
|
-
this.dictionnaryObjects3D = new Map();
|
|
35
|
-
this.dictionnarySceneObjects3D = new Map();
|
|
36
|
-
this.lastMeasure = [];
|
|
37
|
-
this.distancesLastMeasure = [];
|
|
38
|
-
this.resolution = {
|
|
39
|
-
width: 500,
|
|
40
|
-
height: 600,
|
|
41
|
-
};
|
|
42
|
-
this.visibility = {
|
|
43
|
-
mattertags: false,
|
|
44
|
-
sweeps: true,
|
|
45
|
-
};
|
|
46
|
-
this.tagsAttachments = {};
|
|
47
|
-
this.currentSweep = new Subject();
|
|
48
|
-
//camera position with rotation
|
|
49
|
-
this.currentCameraPose = new Subject();
|
|
50
|
-
this.forbiddenSweeps = [];
|
|
51
|
-
this.tagAction = new Subject();
|
|
52
|
-
this.inTransitionMode = false;
|
|
53
|
-
this.inTransitionSweep = false;
|
|
54
|
-
this.noLightForObjects = true;
|
|
55
|
-
this.currentCameraMode = CameraMode.OUTSIDE;
|
|
56
|
-
this.onCameraModeChanged = new Subject();
|
|
57
|
-
this.onGoToTag = new Subject();
|
|
58
|
-
this.tagMessengerOn = false;
|
|
59
|
-
/**
|
|
60
|
-
* Actions on left click when positioning mattertag in visit
|
|
61
|
-
*/
|
|
62
|
-
this.pointerLeftClickHandler = () => {
|
|
63
|
-
if (this.mattertagToFollow) {
|
|
64
|
-
const mattertagData = this.dictionnaryTags.get(this.mattertagToFollow);
|
|
65
|
-
mattertagData.setPosition({ ...this.poseMatterport.position }); // copy!! not the reference
|
|
66
|
-
mattertagData.setNormal({ ...this.poseMatterport.normal }); // copy!! not the reference
|
|
67
|
-
this.dictionnaryTags.set(this.mattertagToFollow, mattertagData);
|
|
68
|
-
this.updateMatterTagContentForTagID(this.mattertagToFollow);
|
|
69
|
-
}
|
|
70
|
-
this.onValidatedMattertag();
|
|
71
|
-
};
|
|
72
|
-
this.pointerRightClickHandler = (e) => {
|
|
73
|
-
e.preventDefault();
|
|
74
|
-
this.cancelFollowingCursor();
|
|
75
|
-
alert('action cancelled');
|
|
76
|
-
};
|
|
77
|
-
this.pointerMiddleClickHandler = (e) => {
|
|
78
|
-
this.textDisplayCursorPositionPanel.innerHTML = `position:
|
|
79
|
-
${this.pointToString(this.poseMatterport.position)}\n
|
|
80
|
-
normal:
|
|
81
|
-
${this.pointToString(this.poseMatterport.normal)}\n
|
|
82
|
-
floorId:
|
|
83
|
-
${this.poseMatterport.floorId}`;
|
|
84
|
-
// this.textDisplayCursorPositionPanel.style.display = 'visible';
|
|
85
|
-
this.getCursorPositionButton.style.display = 'none';
|
|
86
|
-
};
|
|
87
|
-
this.config = config;
|
|
88
|
-
// TODO: only for dev!
|
|
89
|
-
if (!!this.getCursorPositionButton &&
|
|
90
|
-
(document.location.href.indexOf('dev') !== -1 || document.location.href.indexOf('localhost') !== -1)) {
|
|
91
|
-
this.intervalCursorPointerPosition = setInterval(() => {
|
|
92
|
-
if (!this.poseMatterport) {
|
|
93
|
-
return;
|
|
94
|
-
}
|
|
95
|
-
const nextShow = this.poseMatterport.time + 1000;
|
|
96
|
-
if (new Date().getTime() > nextShow) {
|
|
97
|
-
if (this.cursorPositionButtonDisplayed) {
|
|
98
|
-
return;
|
|
99
|
-
}
|
|
100
|
-
const size = {
|
|
101
|
-
w: this.container.clientWidth,
|
|
102
|
-
h: this.container.clientHeight,
|
|
103
|
-
};
|
|
104
|
-
const coord = this.sdk.Conversion.worldToScreen(this.poseMatterport.position, this.poseCamera, size);
|
|
105
|
-
this.getCursorPositionButton.style.left = `${coord.x - 25}px`;
|
|
106
|
-
this.getCursorPositionButton.style.top = `${coord.y - 22}px`;
|
|
107
|
-
this.getCursorPositionButton.style.display = 'block';
|
|
108
|
-
// this.textDisplayCursorPositionPanel.style.display = 'none';
|
|
109
|
-
this.cursorPositionButtonDisplayed = true;
|
|
110
|
-
}
|
|
111
|
-
}, 500);
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
get currentSpaceID() {
|
|
115
|
-
return this._currentSpaceID;
|
|
116
|
-
}
|
|
117
|
-
set currentSpaceID(value) {
|
|
118
|
-
this._currentSpaceID = value;
|
|
119
|
-
}
|
|
120
|
-
/**
|
|
121
|
-
* Initializes Matterport and all listeners/data
|
|
122
|
-
* @param tagService BaseTagService (to inject html)
|
|
123
|
-
* @param module SpModule (Museum, Immo) to subscribe only to needed functionnnalities
|
|
124
|
-
* @returns boolean
|
|
125
|
-
*/
|
|
126
|
-
async initSdk(tagService, module = SpModule.IMMO) {
|
|
127
|
-
if (this.sdk) {
|
|
128
|
-
// clean if sdk is running already
|
|
129
|
-
await this.action_delete_all_mattertags();
|
|
130
|
-
}
|
|
131
|
-
this.tagService = tagService;
|
|
132
|
-
this.SPModule = module;
|
|
133
|
-
return new Promise((resolve, reject) => {
|
|
134
|
-
// Retrieve DOM elements
|
|
135
|
-
this.pointerButton = document.querySelector('#viewer-pointer-trick');
|
|
136
|
-
this.container = document.querySelector('#viewer-module');
|
|
137
|
-
const iframe = document.querySelector('#viewer-module');
|
|
138
|
-
if (!iframe) {
|
|
139
|
-
return;
|
|
140
|
-
}
|
|
141
|
-
// Add listeners
|
|
142
|
-
if (this.pointerButton) {
|
|
143
|
-
this.pointerButton.addEventListener('click', this.pointerLeftClickHandler);
|
|
144
|
-
// cancel on right click
|
|
145
|
-
this.pointerButton.addEventListener('contextmenu', this.pointerRightClickHandler);
|
|
146
|
-
}
|
|
147
|
-
// Retrieve DOM elements
|
|
148
|
-
this.getCursorPositionButton = document.querySelector('#button');
|
|
149
|
-
this.textDisplayCursorPositionPanel = document.querySelector('#text');
|
|
150
|
-
if (this.getCursorPositionButton) {
|
|
151
|
-
// get position on Matterport "model" on middle click
|
|
152
|
-
this.getCursorPositionButton.addEventListener('click', this.pointerMiddleClickHandler);
|
|
153
|
-
}
|
|
154
|
-
// Load SDK
|
|
155
|
-
console.log('Loading Matterport SDK');
|
|
156
|
-
const showcaseWindow = iframe.contentWindow;
|
|
157
|
-
iframe.addEventListener('load', async function () {
|
|
158
|
-
try {
|
|
159
|
-
this.sdk = await showcaseWindow.MP_SDK.connect(showcaseWindow, 'qn9wsasuy5h2fzrbrn1nzr0id', '3.5');
|
|
160
|
-
}
|
|
161
|
-
catch (e) {
|
|
162
|
-
console.error(e);
|
|
163
|
-
return;
|
|
164
|
-
}
|
|
165
|
-
// Load Mattertag icons and custom subscriptions
|
|
166
|
-
switch (module) {
|
|
167
|
-
case SpModule.IMMO:
|
|
168
|
-
this.sdk.Asset.registerTexture('icon-ticket', this.config.my_config.icon_ticket);
|
|
169
|
-
this.sdk.Asset.registerTexture('icon-equipment', this.config.my_config.icon_equipment);
|
|
170
|
-
this.sdk.Asset.registerTexture('icon-measure', this.config.my_config.icon_measure);
|
|
171
|
-
this.sdk.Asset.registerTexture('icon-data', this.config.my_config.icon_data);
|
|
172
|
-
this.sdk.Asset.registerTexture('icon-object3d', this.config.my_config.icon_object3d);
|
|
173
|
-
this.sdk.Measurements.data.subscribe({
|
|
174
|
-
onAdded: function (index, item, collection) {
|
|
175
|
-
// console.log(
|
|
176
|
-
// "item added to the collection",
|
|
177
|
-
// index,
|
|
178
|
-
// item,
|
|
179
|
-
// );
|
|
180
|
-
// this.measurements[index] = item;
|
|
181
|
-
this.lastMeasure = item.points;
|
|
182
|
-
}.bind(this),
|
|
183
|
-
onCollectionUpdated: function (collection) {
|
|
184
|
-
// console.log('the entire up-to-date collection', collection);
|
|
185
|
-
this.getDistanceForLastMeasurement();
|
|
186
|
-
}.bind(this),
|
|
187
|
-
});
|
|
188
|
-
this.sdk.Measurements.mode.subscribe(function (measurementModeState) {
|
|
189
|
-
// measurement mode state has changed
|
|
190
|
-
this.isMeasureModeOn = measurementModeState.active;
|
|
191
|
-
// console.log('Is measurement mode currently active? ', measurementModeState.active);
|
|
192
|
-
}.bind(this));
|
|
193
|
-
break;
|
|
194
|
-
case SpModule.MUSEUM:
|
|
195
|
-
this.sdk.Asset.registerTexture('icon-data', this.config.my_config.icon_data);
|
|
196
|
-
break;
|
|
197
|
-
case SpModule.HOTEL:
|
|
198
|
-
this.sdk.Asset.registerTexture('icon_room_available', this.config.my_config.icon_room_available);
|
|
199
|
-
this.sdk.Asset.registerTexture('icon_room_unavailable', this.config.my_config.icon_room_unavailable);
|
|
200
|
-
this.sdk.Asset.registerTexture('icon_room_chosen', this.config.my_config.icon_room_chosen);
|
|
201
|
-
this.sdk.Asset.registerTexture('icon_room_viewed', this.config.my_config.icon_room_viewed);
|
|
202
|
-
break;
|
|
203
|
-
default:
|
|
204
|
-
break;
|
|
205
|
-
}
|
|
206
|
-
this.sdk.Asset.registerTexture('icon-position', this.config.my_config.icon_position);
|
|
207
|
-
// Current Room (used for getting bounding box and eventually lazy load mattertag or object3D inside current Room)
|
|
208
|
-
this.sdk.Room.current.subscribe((currentRoom) => {
|
|
209
|
-
console.log(`hello current Room ${JSON.stringify(currentRoom)}`);
|
|
210
|
-
});
|
|
211
|
-
// 3D position's pointer
|
|
212
|
-
this.sdk.Pointer.intersection.subscribe(function (intersection) {
|
|
213
|
-
this.poseMatterport = intersection;
|
|
214
|
-
this.poseMatterport.time = new Date().getTime();
|
|
215
|
-
if (!this.oldPoseMatterportPosition) {
|
|
216
|
-
this.oldPoseMatterportPosition = {
|
|
217
|
-
x: 0,
|
|
218
|
-
y: 0,
|
|
219
|
-
z: 0,
|
|
220
|
-
};
|
|
221
|
-
}
|
|
222
|
-
if (this.interactionMode !== ViewerInteractions.DEFAULT &&
|
|
223
|
-
this.mattertagToFollow) {
|
|
224
|
-
// follow the pointer and changes the position of the last tag
|
|
225
|
-
// (we are about to validate, but it exists in sdk already)
|
|
226
|
-
this.enable_following_tag(this.mattertagToFollow);
|
|
227
|
-
}
|
|
228
|
-
if (!!this.getCursorPositionButton && !!this.getCursorPositionButton.style &&
|
|
229
|
-
(document.URL.indexOf('https://dev.smarterplan.io') !== -1 || document.location.href.indexOf('localhost') !== -1)) {
|
|
230
|
-
this.getCursorPositionButton.style.display = 'none';
|
|
231
|
-
this.cursorPositionButtonDisplayed = false;
|
|
232
|
-
}
|
|
233
|
-
}.bind(this));
|
|
234
|
-
//Camera mode
|
|
235
|
-
this.sdk.Mode.current.subscribe((mode) => {
|
|
236
|
-
this.inTransitionSweep = false;
|
|
237
|
-
switch (mode) {
|
|
238
|
-
case 'mode.dollhouse':
|
|
239
|
-
this.currentCameraMode = CameraMode.DOLLHOUSE;
|
|
240
|
-
break;
|
|
241
|
-
case 'mode.floorplan':
|
|
242
|
-
this.currentCameraMode = CameraMode.FLOORPLAN;
|
|
243
|
-
break;
|
|
244
|
-
case 'mode.inside':
|
|
245
|
-
this.currentCameraMode = CameraMode.INSIDE;
|
|
246
|
-
break;
|
|
247
|
-
case 'mode.transitioning':
|
|
248
|
-
this.currentCameraMode = CameraMode.TRANSITIONING;
|
|
249
|
-
break;
|
|
250
|
-
default:
|
|
251
|
-
this.currentCameraMode = CameraMode.OUTSIDE;
|
|
252
|
-
}
|
|
253
|
-
this.onCameraModeChanged.next(this.currentCameraMode);
|
|
254
|
-
});
|
|
255
|
-
// Camera's viewpoint
|
|
256
|
-
this.sdk.Camera.pose.subscribe(function subscr(pose) {
|
|
257
|
-
this.poseCamera = pose;
|
|
258
|
-
this.currentCameraPose.next(pose);
|
|
259
|
-
// console.log('Current position is ', pose.position);
|
|
260
|
-
// console.log('Rotation angle is ', pose.rotation);
|
|
261
|
-
// console.log("Sweep UUID is", pose.sweep);
|
|
262
|
-
}.bind(this));
|
|
263
|
-
// subscribe to sweeps
|
|
264
|
-
this.sdk.Sweep.data.subscribe({
|
|
265
|
-
onCollectionUpdated: function subscr(collection) {
|
|
266
|
-
// console.log("Sweep collection updated");
|
|
267
|
-
this.sweeps = Object.keys(collection);
|
|
268
|
-
}.bind(this),
|
|
269
|
-
});
|
|
270
|
-
// subscribe to current sweep
|
|
271
|
-
this.sdk.Sweep.current.subscribe(function subscr(currentSweep) {
|
|
272
|
-
// Change to the current sweep has occurred.
|
|
273
|
-
if (currentSweep.sid === '') {
|
|
274
|
-
// console.log('Not currently stationed at a sweep position');
|
|
275
|
-
}
|
|
276
|
-
else {
|
|
277
|
-
// console.log("emmiting sweep", currentSweep.sid);
|
|
278
|
-
this.currentSweep.next(currentSweep.sid);
|
|
279
|
-
}
|
|
280
|
-
}.bind(this));
|
|
281
|
-
// Subscribe to Floor data
|
|
282
|
-
this.sdk.Floor.data.subscribe({
|
|
283
|
-
onCollectionUpdated: function upd(collection) {
|
|
284
|
-
this.floors = Object.values(collection);
|
|
285
|
-
}.bind(this),
|
|
286
|
-
});
|
|
287
|
-
// on tag click open details page
|
|
288
|
-
this.sdk.on('tag.click', (sid) => {
|
|
289
|
-
// get object of this tag
|
|
290
|
-
try {
|
|
291
|
-
const mattertagData = this.dictionnaryTags.get(sid);
|
|
292
|
-
if (!mattertagData) {
|
|
293
|
-
console.log('no mattertagData to display');
|
|
294
|
-
return;
|
|
295
|
-
}
|
|
296
|
-
const url = tagService.getUrlForSeeDetails(mattertagData.getObject(), mattertagData.getType());
|
|
297
|
-
if (url !== '') {
|
|
298
|
-
this.visibilityService.detailShowing.next(true);
|
|
299
|
-
this.ngZone.run(() => {
|
|
300
|
-
this.router.navigate([url]);
|
|
301
|
-
});
|
|
302
|
-
}
|
|
303
|
-
}
|
|
304
|
-
catch {
|
|
305
|
-
console.log('Cannot show details for tag');
|
|
306
|
-
}
|
|
307
|
-
});
|
|
308
|
-
// Pointer trick
|
|
309
|
-
// Create a div that will appear when the cursor is still
|
|
310
|
-
// It will intercept the click of the mouse before it trigerring the Matterport's tour navigation
|
|
311
|
-
this.timerPointer = setInterval(this.updatePointerTrick.bind(this), 50);
|
|
312
|
-
/**
|
|
313
|
-
* Transitions
|
|
314
|
-
*/
|
|
315
|
-
this.sdk.on('viewmode.changestart', function (to, from) {
|
|
316
|
-
// console.log('Starting to move to ' + to + ' from ' + from);
|
|
317
|
-
this.inTransitionMode = true;
|
|
318
|
-
}.bind(this));
|
|
319
|
-
this.sdk.on('viewmode.changeend', function (oldMode, newMode) {
|
|
320
|
-
// console.log('Ended to move to ' + newMode + ' from ' + oldMode);
|
|
321
|
-
if (newMode !== 'mode.transitioning') {
|
|
322
|
-
this.inTransitionMode = false;
|
|
323
|
-
}
|
|
324
|
-
}.bind(this));
|
|
325
|
-
this.sdk.on(this.sdk.Sweep.Event.ENTER, function (oldSweep, newSweep) {
|
|
326
|
-
// console.log('Leaving sweep ' + oldSweep);
|
|
327
|
-
// console.log('Entering sweep ' + newSweep);
|
|
328
|
-
this.inTransitionSweep = false;
|
|
329
|
-
this.displayAzimutalCrown();
|
|
330
|
-
}.bind(this));
|
|
331
|
-
this.sdk.on(this.sdk.Sweep.Event.EXIT, function (fromSweep, toSweep) {
|
|
332
|
-
// console.log('Leaving sweep ' + fromSweep);
|
|
333
|
-
// console.log('Transitioning to sweep ' + toSweep);
|
|
334
|
-
this.inTransitionSweep = true;
|
|
335
|
-
}.bind(this));
|
|
336
|
-
// TODO: get scene with getter instead!
|
|
337
|
-
const [sceneObject] = await this.sdk.Scene.createObjects(1);
|
|
338
|
-
const node = sceneObject.addNode();
|
|
339
|
-
node.start();
|
|
340
|
-
this.threeJSScene = node.obj3D.parent;
|
|
341
|
-
// await this.sdk.Scene.configure((renderer: any, three: any) => {
|
|
342
|
-
// renderer.physicallyCorrectLights = true;
|
|
343
|
-
// renderer.outputEncoding = three.sRGBEncoding;
|
|
344
|
-
// renderer.shadowMap.enabled = true;
|
|
345
|
-
// renderer.shadowMap.bias = 0.0001;
|
|
346
|
-
// renderer.shadowMap.type = three.PCFSoftShadowMap;
|
|
347
|
-
// });
|
|
348
|
-
// TODO: wait for MP ticket resolution before decomment these!
|
|
349
|
-
// Wait until Showcase is actually playing....
|
|
350
|
-
// this.sdk.Tag.data.subscribe({
|
|
351
|
-
// onAdded: async function (index, item, collection) {
|
|
352
|
-
//
|
|
353
|
-
// let thisOpacity = 0.2;
|
|
354
|
-
// this.sdk.Tag.editOpacity(index, thisOpacity);
|
|
355
|
-
//
|
|
356
|
-
// let source = null;
|
|
357
|
-
// try {
|
|
358
|
-
// source = await Promise.all([
|
|
359
|
-
// this.sdk.Sensor.createSource(this.sdk.Sensor.SourceType.SPHERE, {
|
|
360
|
-
// origin: item.anchorPosition,
|
|
361
|
-
// radius: Number(3),
|
|
362
|
-
// userData: {
|
|
363
|
-
// id: index + '-sphere-source',
|
|
364
|
-
// },
|
|
365
|
-
// })
|
|
366
|
-
// ]);
|
|
367
|
-
// } catch (e) {
|
|
368
|
-
// console.log('could not create Sphere sensor')
|
|
369
|
-
// console.error(e);
|
|
370
|
-
// }
|
|
371
|
-
// if (!source) {
|
|
372
|
-
// return;
|
|
373
|
-
// }
|
|
374
|
-
//
|
|
375
|
-
// let sensor = null;
|
|
376
|
-
// try {
|
|
377
|
-
// sensor = await this.sdk.Sensor.createSensor(this.sdk.Sensor.SensorType.CAMERA);
|
|
378
|
-
// } catch (e) {
|
|
379
|
-
// console.log('could not create Camera sensor')
|
|
380
|
-
// console.error(e);
|
|
381
|
-
// }
|
|
382
|
-
// if (!sensor) {
|
|
383
|
-
// return;
|
|
384
|
-
// }
|
|
385
|
-
//
|
|
386
|
-
// sensor.addSource(...source);
|
|
387
|
-
// sensor.readings.subscribe({
|
|
388
|
-
// onUpdated(source, reading) {
|
|
389
|
-
// console.log(thisOpacity);
|
|
390
|
-
// let oldOpacity = thisOpacity;
|
|
391
|
-
// if (reading.inRange) {
|
|
392
|
-
// thisOpacity = 1;
|
|
393
|
-
// console.log(index + ' is inRange');
|
|
394
|
-
// } else if (reading.inView) {
|
|
395
|
-
// console.log(index + ' is inView but not inRange');
|
|
396
|
-
// thisOpacity = 0.5;
|
|
397
|
-
// } else {
|
|
398
|
-
// thisOpacity = 0.2;
|
|
399
|
-
// console.log(index + ' is not inView or inRange');
|
|
400
|
-
// }
|
|
401
|
-
//
|
|
402
|
-
// this.sdk.Tag.editOpacity(index, thisOpacity);
|
|
403
|
-
// /*
|
|
404
|
-
// let inc = 0.01;
|
|
405
|
-
// if (oldOpacity > thisOpacity) {
|
|
406
|
-
// inc = -0.01;
|
|
407
|
-
// }
|
|
408
|
-
//
|
|
409
|
-
// for(var i = oldOpacity; i != thisOpacity; i=i+inc) {
|
|
410
|
-
// setTimeout(function() {
|
|
411
|
-
// mpSdk.Tag.editOpacity(index, i);
|
|
412
|
-
// console.log('Delay', i);
|
|
413
|
-
// },10);
|
|
414
|
-
// }
|
|
415
|
-
// */
|
|
416
|
-
// }
|
|
417
|
-
// });
|
|
418
|
-
// //sensor.showDebug(true);
|
|
419
|
-
// }.bind(this),
|
|
420
|
-
// onCollectionUpdated: function (collection) {
|
|
421
|
-
// console.log('Collection received. There are ', Object.keys(collection).length, ' Tags in the collection', collection);
|
|
422
|
-
// }
|
|
423
|
-
// });
|
|
424
|
-
resolve(true);
|
|
425
|
-
}.bind(this));
|
|
426
|
-
});
|
|
427
|
-
}
|
|
428
|
-
setLightingOff() {
|
|
429
|
-
this.noLightForObjects = true;
|
|
430
|
-
}
|
|
431
|
-
pointToString(point) {
|
|
432
|
-
var x = point.x.toFixed(3);
|
|
433
|
-
var y = point.y.toFixed(3);
|
|
434
|
-
var z = point.z.toFixed(3);
|
|
435
|
-
return `{ x: ${x}, y: ${y}, z: ${z} }`;
|
|
436
|
-
}
|
|
437
|
-
//
|
|
438
|
-
// ---------- Measurements related ----------
|
|
439
|
-
//
|
|
440
|
-
/**
|
|
441
|
-
* Callback after measurement is performed
|
|
442
|
-
*/
|
|
443
|
-
getDistanceForLastMeasurement() {
|
|
444
|
-
if (this.lastMeasure.length > 0) {
|
|
445
|
-
const numberPoints = this.lastMeasure.length;
|
|
446
|
-
this.distancesLastMeasure = [];
|
|
447
|
-
for (let index = 1; index < numberPoints; index += 1) {
|
|
448
|
-
const distance = getDistanceBetweenTwoPoints(this.lastMeasure[index - 1], this.lastMeasure[index]);
|
|
449
|
-
this.distancesLastMeasure.push(distance);
|
|
450
|
-
}
|
|
451
|
-
this.takeScreenShot().then((res) => {
|
|
452
|
-
this.router.navigate([`visit/${this.currentSpaceID}/add_measurement`]);
|
|
453
|
-
});
|
|
454
|
-
}
|
|
455
|
-
}
|
|
456
|
-
getLastDistances() {
|
|
457
|
-
return this.distancesLastMeasure;
|
|
458
|
-
}
|
|
459
|
-
/**
|
|
460
|
-
* Takes screenshot and saves base64 in lastScreenshotUri
|
|
461
|
-
* @returns Promise
|
|
462
|
-
*/
|
|
463
|
-
takeScreenShot() {
|
|
464
|
-
return this.sdk.Renderer.takeScreenShot(this.resolution, this.visibility).then(function (screenShotUri) {
|
|
465
|
-
// base64 string
|
|
466
|
-
this.lastScreenshotUri = screenShotUri;
|
|
467
|
-
return Promise.resolve();
|
|
468
|
-
}.bind(this));
|
|
469
|
-
}
|
|
470
|
-
getScreenShotUri() {
|
|
471
|
-
return this.lastScreenshotUri;
|
|
472
|
-
}
|
|
473
|
-
getLastMeasurement() {
|
|
474
|
-
const data = {
|
|
475
|
-
measure: this.lastMeasure,
|
|
476
|
-
sweep: this.poseCamera.sweep,
|
|
477
|
-
};
|
|
478
|
-
return data;
|
|
479
|
-
}
|
|
480
|
-
//
|
|
481
|
-
// ---------- Utils ----------
|
|
482
|
-
//
|
|
483
|
-
/**
|
|
484
|
-
* Styling of pointer
|
|
485
|
-
*/
|
|
486
|
-
updatePointerTrick() {
|
|
487
|
-
if (this.interactionMode !== ViewerInteractions.DEFAULT &&
|
|
488
|
-
this.mattertagToFollow &&
|
|
489
|
-
this.poseMatterport &&
|
|
490
|
-
this.getDistPosition(this.poseMatterport.position, this.oldPoseMatterportPosition) > 25) {
|
|
491
|
-
this.pointerButton.style.display = 'none';
|
|
492
|
-
const size = {
|
|
493
|
-
w: this.container.clientWidth,
|
|
494
|
-
h: this.container.clientHeight,
|
|
495
|
-
};
|
|
496
|
-
const coords = this.sdk.Conversion.worldToScreen(this.poseMatterport.position, this.poseCamera, size);
|
|
497
|
-
this.pointerButton.style.left = `${coords.x * Math.sign(coords.x) - 25}px`;
|
|
498
|
-
this.pointerButton.style.top = `${coords.y * Math.sign(coords.x) - 25}px`;
|
|
499
|
-
this.oldPoseMatterportPosition = {
|
|
500
|
-
...this.poseMatterport.position,
|
|
501
|
-
};
|
|
502
|
-
}
|
|
503
|
-
else {
|
|
504
|
-
this.pointerButton.style.display = 'block';
|
|
505
|
-
}
|
|
506
|
-
}
|
|
507
|
-
/**
|
|
508
|
-
* Realtime mattertag following the cursor
|
|
509
|
-
* @param mattertag string
|
|
510
|
-
*/
|
|
511
|
-
enable_following_tag(mattertag) {
|
|
512
|
-
this.sdk.Tag.editPosition(mattertag, {
|
|
513
|
-
anchorPosition: {
|
|
514
|
-
x: this.poseMatterport.position.x * 1,
|
|
515
|
-
y: this.poseMatterport.position.y * 1,
|
|
516
|
-
z: this.poseMatterport.position.z * 1,
|
|
517
|
-
},
|
|
518
|
-
stemVector: {
|
|
519
|
-
x: this.poseMatterport.normal.x * 0.3,
|
|
520
|
-
y: this.poseMatterport.normal.y * 0.3,
|
|
521
|
-
z: this.poseMatterport.normal.z * 0.3,
|
|
522
|
-
},
|
|
523
|
-
});
|
|
524
|
-
}
|
|
525
|
-
/**
|
|
526
|
-
* Get the distance betwween two 3D positions
|
|
527
|
-
* Used in order to see how much the cursor has moved from the previous position
|
|
528
|
-
* @param pos1
|
|
529
|
-
* @param pos2
|
|
530
|
-
*/
|
|
531
|
-
getDistPosition(pos1, pos2) {
|
|
532
|
-
const size = {
|
|
533
|
-
w: this.container.clientWidth,
|
|
534
|
-
h: this.container.clientHeight,
|
|
535
|
-
};
|
|
536
|
-
const coords1 = this.sdk.Conversion.worldToScreen(pos1, this.poseCamera, size);
|
|
537
|
-
const coords2 = this.sdk.Conversion.worldToScreen(pos2, this.poseCamera, size);
|
|
538
|
-
return Math.sqrt((coords1.x - coords2.x) ** 2 + (coords1.y - coords2.y) ** 2);
|
|
539
|
-
}
|
|
540
|
-
//
|
|
541
|
-
// ---------- Mattertag related ----------
|
|
542
|
-
//
|
|
543
|
-
/**
|
|
544
|
-
* Creates the Mattertag that will follow the cursor
|
|
545
|
-
* @param mattertagData MattertagData
|
|
546
|
-
*/
|
|
547
|
-
async addCursorMattertag(mattertagData) {
|
|
548
|
-
if (!this.poseMatterport)
|
|
549
|
-
return;
|
|
550
|
-
this.mattertagToFollow = await this.addMattertagToViewer(mattertagData);
|
|
551
|
-
console.log('following the tag', this.mattertagToFollow);
|
|
552
|
-
this.sdk.Tag.editIcon(this.mattertagToFollow, 'icon-position');
|
|
553
|
-
this.sdk.Tag.editOpacity(this.mattertagToFollow, 1);
|
|
554
|
-
}
|
|
555
|
-
/**
|
|
556
|
-
* Adds Mattertag to viewer for an existing object with coordinates (in mattertagData.poi)
|
|
557
|
-
* (position, injected html, set icon)
|
|
558
|
-
* @param mattertagData
|
|
559
|
-
* returns mattertagID
|
|
560
|
-
*/
|
|
561
|
-
async addMattertagToViewer(mattertagData) {
|
|
562
|
-
let sidList;
|
|
563
|
-
if (!this.sdk) {
|
|
564
|
-
return null;
|
|
565
|
-
}
|
|
566
|
-
try {
|
|
567
|
-
sidList = await this.sdk.Tag.add(mattertagData.getData());
|
|
568
|
-
}
|
|
569
|
-
catch (error) {
|
|
570
|
-
console.log('Tag does not belong to the visit', error, mattertagData.getData());
|
|
571
|
-
}
|
|
572
|
-
if (sidList) {
|
|
573
|
-
const mattertagID = sidList[0];
|
|
574
|
-
// console.log("added tag", mattertagData.getType(), mattertagID);
|
|
575
|
-
this.mattertagIDs.push(mattertagID);
|
|
576
|
-
this.dictionnaryTags.set(mattertagID, mattertagData);
|
|
577
|
-
return mattertagID;
|
|
578
|
-
}
|
|
579
|
-
return null;
|
|
580
|
-
}
|
|
581
|
-
/**
|
|
582
|
-
* Actions when position of mattertag is validated by left click
|
|
583
|
-
*/
|
|
584
|
-
onValidatedMattertag() {
|
|
585
|
-
this.setInteractionMode(ViewerInteractions.DEFAULT);
|
|
586
|
-
const lastTag = this.getLastTag();
|
|
587
|
-
if (lastTag) {
|
|
588
|
-
const callbackMode = this.dictionnaryTags
|
|
589
|
-
.get(lastTag)
|
|
590
|
-
.getCallbackActionMode();
|
|
591
|
-
this.callbackAfterMattertagValidation(callbackMode);
|
|
592
|
-
}
|
|
593
|
-
}
|
|
594
|
-
/**
|
|
595
|
-
* Registers new icon (path to image) and set its for Mattertag
|
|
596
|
-
* @param mattertagID string
|
|
597
|
-
* @param iconPath string
|
|
598
|
-
*/
|
|
599
|
-
async addNewIconAndSetForTag(mattertagID, iconPath) {
|
|
600
|
-
await this.sdk.Asset.registerTexture(`icon_${mattertagID}`, iconPath);
|
|
601
|
-
this.sdk.Tag.editIcon(mattertagID, `icon_${mattertagID}`);
|
|
602
|
-
}
|
|
603
|
-
/**
|
|
604
|
-
* Changes icon of Mattertag (the iconName should be registered = one of default ones)
|
|
605
|
-
* @param mattertagID string
|
|
606
|
-
* @param iconName string
|
|
607
|
-
*/
|
|
608
|
-
async setRegistredIconForTag(mattertagID, iconName) {
|
|
609
|
-
try {
|
|
610
|
-
this.sdk.Tag.editIcon(mattertagID, iconName);
|
|
611
|
-
}
|
|
612
|
-
catch (e) {
|
|
613
|
-
console.log('could not edit Icon with name ', iconName, '. Is it registered?');
|
|
614
|
-
}
|
|
615
|
-
}
|
|
616
|
-
/**
|
|
617
|
-
* Sets default icon for a tag (registered in initSdk) OR uses tagIcon from POI (available from MattertagData)
|
|
618
|
-
* @param mattertagID string
|
|
619
|
-
* @param mattertagData MattertagData
|
|
620
|
-
* @returns
|
|
621
|
-
*/
|
|
622
|
-
async setTagIconAndOpacity(mattertagID, mattertagData) {
|
|
623
|
-
if (this.SPModule === SpModule.HOTEL) {
|
|
624
|
-
const room = mattertagData.getObject();
|
|
625
|
-
let iconName = `icon_room`;
|
|
626
|
-
if (room.available) {
|
|
627
|
-
iconName = `${iconName}_available`;
|
|
628
|
-
}
|
|
629
|
-
else {
|
|
630
|
-
iconName = `${iconName}_unavailable`;
|
|
631
|
-
}
|
|
632
|
-
this.sdk.Tag.editIcon(mattertagID, iconName);
|
|
633
|
-
return;
|
|
634
|
-
}
|
|
635
|
-
const stringTagType = poiTypeToString(mattertagData.getType());
|
|
636
|
-
let opacity = this.config.my_config.DEFAULT_OPACITY_TAG;
|
|
637
|
-
let iconName = `icon-${stringTagType}`;
|
|
638
|
-
const poi = mattertagData.getPoi();
|
|
639
|
-
if (poi && poi.tagIcon) {
|
|
640
|
-
const tagIcon = JSON.parse(poi.tagIcon);
|
|
641
|
-
if (mattertagData.getType() === PoiType.DATA) {
|
|
642
|
-
const feature = mattertagData.getObject();
|
|
643
|
-
if (feature.type === FeatureType.INDICATOR_TEMP) {
|
|
644
|
-
tagIcon.src = this.tagService.getIconTagImageForFeature(feature, poi);
|
|
645
|
-
}
|
|
646
|
-
}
|
|
647
|
-
if (tagIcon.src) {
|
|
648
|
-
const pathSigned = await this.tagService.getSignedTagIconSource(tagIcon.src);
|
|
649
|
-
if (pathSigned) {
|
|
650
|
-
try {
|
|
651
|
-
iconName = `icon-${stringTagType}-${mattertagID}-${mattertagData.customIconIndex}`;
|
|
652
|
-
await this.sdk.Asset.registerTexture(iconName, pathSigned);
|
|
653
|
-
mattertagData.customIconIndex += 1;
|
|
654
|
-
}
|
|
655
|
-
catch {
|
|
656
|
-
console.log('error registerIcon');
|
|
657
|
-
}
|
|
658
|
-
}
|
|
659
|
-
}
|
|
660
|
-
if (tagIcon.opacity) {
|
|
661
|
-
opacity = tagIcon.opacity;
|
|
662
|
-
}
|
|
663
|
-
}
|
|
664
|
-
try {
|
|
665
|
-
this.sdk.Tag.editIcon(mattertagID, iconName);
|
|
666
|
-
this.sdk.Tag.editOpacity(mattertagID, opacity);
|
|
667
|
-
}
|
|
668
|
-
catch (error) {
|
|
669
|
-
console.log('Error editIcon or opacity', error);
|
|
670
|
-
}
|
|
671
|
-
}
|
|
672
|
-
/**
|
|
673
|
-
* Moves viewer to last tag created
|
|
674
|
-
*/
|
|
675
|
-
goToLastTag() {
|
|
676
|
-
setTimeout(() => {
|
|
677
|
-
const lastTag = this.getLastTag();
|
|
678
|
-
this.goToTag(lastTag);
|
|
679
|
-
}, 2000);
|
|
680
|
-
}
|
|
681
|
-
/**
|
|
682
|
-
* Moves viewer to Mattertag with ID provided
|
|
683
|
-
* @param mattertagID string
|
|
684
|
-
* @returns
|
|
685
|
-
*/
|
|
686
|
-
async goToTag(mattertagID) {
|
|
687
|
-
if (mattertagID === '')
|
|
688
|
-
return;
|
|
689
|
-
try {
|
|
690
|
-
this.onGoToTag.next(mattertagID);
|
|
691
|
-
await this.sdk.Sweep.current.waitUntil((currentSweep) => currentSweep !== '');
|
|
692
|
-
await this.sdk.Mattertag.navigateToTag(mattertagID, this.sdk.Mattertag.Transition.FLY);
|
|
693
|
-
}
|
|
694
|
-
catch (error) {
|
|
695
|
-
console.log('cannot navigate to tag', error);
|
|
696
|
-
}
|
|
697
|
-
}
|
|
698
|
-
/**
|
|
699
|
-
* Updates content of Mattertag with mattertagID (billboard, injected html, tag icon)
|
|
700
|
-
* @param mattertagID string
|
|
701
|
-
* @param object Ticket, Equipment, Feature, etc
|
|
702
|
-
* @param tagType PoiType
|
|
703
|
-
*/
|
|
704
|
-
async updateMatterTagContentForTagID(mattertagID, object = null, tagType = null) {
|
|
705
|
-
this.sdk.Tag.editBillboard(mattertagID, this.dictionnaryTags.get(mattertagID).getData());
|
|
706
|
-
if (object && tagType) {
|
|
707
|
-
await this.injectHtmlInTag(tagType, object, mattertagID);
|
|
708
|
-
}
|
|
709
|
-
await this.setTagIconAndOpacity(mattertagID, this.dictionnaryTags.get(mattertagID));
|
|
710
|
-
}
|
|
711
|
-
/**
|
|
712
|
-
* Updates injected html for Mattertag
|
|
713
|
-
* @param mattertagID string
|
|
714
|
-
* @param object Ticket, Equipment, Feature, etc
|
|
715
|
-
* @param tagType PoiType
|
|
716
|
-
*/
|
|
717
|
-
async updateInjectedHtmlForTagID(mattertagID, object, tagType) {
|
|
718
|
-
await this.injectHtmlInTag(tagType, object, mattertagID);
|
|
719
|
-
}
|
|
720
|
-
/**
|
|
721
|
-
* Deletes Mattertag from Viewer by its ID
|
|
722
|
-
* @param mattertagID string
|
|
723
|
-
*/
|
|
724
|
-
deleteMattertagFromId(mattertagID) {
|
|
725
|
-
this.sdk.Tag.remove(mattertagID);
|
|
726
|
-
this.dictionnaryTags.delete(mattertagID);
|
|
727
|
-
}
|
|
728
|
-
/**
|
|
729
|
-
* Deletes latest created mattertag
|
|
730
|
-
*/
|
|
731
|
-
deleteLastMattertag() {
|
|
732
|
-
const mattertagID = this.mattertagIDs.pop();
|
|
733
|
-
if (mattertagID) {
|
|
734
|
-
this.deleteMattertagFromId(mattertagID);
|
|
735
|
-
}
|
|
736
|
-
}
|
|
737
|
-
/**
|
|
738
|
-
* Legacy: used to be called action_add_mattertag_from_POI
|
|
739
|
-
* Adds and configures Mattertag for an object (Ticket, Equipment, Feature, etc) that corresponds to POI (coordinates, tagIcon)
|
|
740
|
-
* @param tagType PoiType
|
|
741
|
-
* @param object Ticket, Equipment, Feature...
|
|
742
|
-
* @param poi POI
|
|
743
|
-
* @returns
|
|
744
|
-
*/
|
|
745
|
-
async createMattertagFromPOI(tagType, object, poi) {
|
|
746
|
-
// check if tag exists already
|
|
747
|
-
const { tag, sweep } = this.getTagFromElementId(object.id);
|
|
748
|
-
if (tag) {
|
|
749
|
-
// console.log("tag exists", object)
|
|
750
|
-
return;
|
|
751
|
-
}
|
|
752
|
-
const mattertagData = new MattertagData(tagType);
|
|
753
|
-
mattertagData.setObject(object, tagType);
|
|
754
|
-
if (poi.coordinate) {
|
|
755
|
-
mattertagData.setPosition(JSON.parse(poi.coordinate));
|
|
756
|
-
}
|
|
757
|
-
if (poi.metadata) {
|
|
758
|
-
const tagMetadata = JSON.parse(poi.metadata);
|
|
759
|
-
if (tagMetadata.normal) {
|
|
760
|
-
mattertagData.setNormal(tagMetadata.normal);
|
|
761
|
-
}
|
|
762
|
-
else {
|
|
763
|
-
mattertagData.setNormal({ x: 0, y: -0.15, z: 0 });
|
|
764
|
-
}
|
|
765
|
-
}
|
|
766
|
-
if (poi.matterportSweepID) {
|
|
767
|
-
mattertagData.setSweepID(poi.matterportSweepID);
|
|
768
|
-
}
|
|
769
|
-
mattertagData.setPoi(poi);
|
|
770
|
-
const createdTagID = await this.addMattertagToViewer(mattertagData);
|
|
771
|
-
if (createdTagID && this.sdk) {
|
|
772
|
-
await this.setTagIconAndOpacity(createdTagID, mattertagData);
|
|
773
|
-
await this.injectHtmlInTag(tagType, object, createdTagID);
|
|
774
|
-
}
|
|
775
|
-
}
|
|
776
|
-
/**
|
|
777
|
-
* Inject custom HTML as Mattertag content
|
|
778
|
-
* @param tagType PoiType
|
|
779
|
-
* @param object Ticket, Equipment, Feature etc
|
|
780
|
-
* @param tagID string
|
|
781
|
-
*/
|
|
782
|
-
async injectHtmlInTag(tagType, object, tagID) {
|
|
783
|
-
let html = await this.tagService.getHtmlToInject(tagType, object);
|
|
784
|
-
if (html !== '' && this.sdk) {
|
|
785
|
-
const scriptTag = this.tagService.getScriptForTag(object, tagType);
|
|
786
|
-
html += `${scriptTag}`;
|
|
787
|
-
// create and register the sandbox
|
|
788
|
-
const [sandboxId, messenger] = await this.sdk.Tag.registerSandbox(html);
|
|
789
|
-
// detach previous sandbox from a tag
|
|
790
|
-
let attachmentID = this.tagsAttachments[tagID];
|
|
791
|
-
if (attachmentID) {
|
|
792
|
-
this.sdk.Tag.detach(tagID, attachmentID);
|
|
793
|
-
}
|
|
794
|
-
this.tagsAttachments[tagID] = sandboxId;
|
|
795
|
-
// attach the sandbox to a tag
|
|
796
|
-
this.sdk.Tag.attach(tagID, sandboxId);
|
|
797
|
-
// receive data from the sandbox
|
|
798
|
-
// tagMessengerOn allows to go here only once
|
|
799
|
-
if (!this.tagMessengerOn) {
|
|
800
|
-
this.tagMessengerOn = true;
|
|
801
|
-
const imageClick = (featureID) => {
|
|
802
|
-
// console.log("image click handler", featureID);
|
|
803
|
-
this.tagService.onActionImageClick(featureID);
|
|
804
|
-
};
|
|
805
|
-
const audioClick = (audioCommentID) => {
|
|
806
|
-
// console.log("audio click handler", audioCommentID);
|
|
807
|
-
this.tagService.onActionAudioClick(audioCommentID);
|
|
808
|
-
};
|
|
809
|
-
const videoClick = (url) => {
|
|
810
|
-
this.tagService.onActionVideoClick(url);
|
|
811
|
-
};
|
|
812
|
-
messenger.on(TagAction.DETAIL_CLICK, this.tagService.onActionDetailClick.bind(this.tagService));
|
|
813
|
-
messenger.on(TagAction.TICKET_CLICK, this.tagService.onActionDetailClick.bind(this.tagService));
|
|
814
|
-
messenger.on(TagAction.AUDIO_CLICK, audioClick);
|
|
815
|
-
messenger.on(TagAction.IMAGE_CLICK, imageClick);
|
|
816
|
-
messenger.on(TagAction.VIDEO_CLICK, videoClick);
|
|
817
|
-
messenger.on(TagAction.DOC_CLICK, this.tagService.onActionDocClick.bind(this.tagService));
|
|
818
|
-
messenger.on(TagAction.YOUTUBE_CLICK, this.tagService.onActionYoutubeClick.bind(this.tagService));
|
|
819
|
-
}
|
|
820
|
-
}
|
|
821
|
-
else {
|
|
822
|
-
// if html is empty (case of EMBED content), we edit billboard for Feature and attach new content
|
|
823
|
-
const { comment, tagDescription } = this.tagService.getBillboardMediaToEmbed(object);
|
|
824
|
-
if (comment) {
|
|
825
|
-
// register the media
|
|
826
|
-
const [attachmentID] = await this.sdk.Tag.registerAttachment(comment.externalLink);
|
|
827
|
-
// attach
|
|
828
|
-
this.sdk.Tag.attach(tagID, attachmentID);
|
|
829
|
-
this.sdk.Tag.editBillboard(tagID, {
|
|
830
|
-
label: object.title,
|
|
831
|
-
description: tagDescription,
|
|
832
|
-
});
|
|
833
|
-
}
|
|
834
|
-
}
|
|
835
|
-
}
|
|
836
|
-
async action_delete_all_mattertags() {
|
|
837
|
-
await this.sdk.Tag.remove(...this.mattertagIDs);
|
|
838
|
-
this.mattertagIDs = [];
|
|
839
|
-
this.dictionnaryTags.clear();
|
|
840
|
-
}
|
|
841
|
-
/**
|
|
842
|
-
* Deletes Mattertag from visit associated with object ID (ticketID, etc)
|
|
843
|
-
* @param elementID string
|
|
844
|
-
*/
|
|
845
|
-
async deleteMattertagForObject(elementID) {
|
|
846
|
-
const matterTagID = this.getTagFromElementId(elementID).tag;
|
|
847
|
-
if (matterTagID) {
|
|
848
|
-
try {
|
|
849
|
-
await this.sdk.Tag.remove(matterTagID);
|
|
850
|
-
this.dictionnaryTags.delete(matterTagID);
|
|
851
|
-
const index = this.mattertagIDs.indexOf(matterTagID);
|
|
852
|
-
this.mattertagIDs.splice(index, 1);
|
|
853
|
-
}
|
|
854
|
-
catch (error) {
|
|
855
|
-
console.log('Cannot delete tag', matterTagID, error);
|
|
856
|
-
}
|
|
857
|
-
}
|
|
858
|
-
}
|
|
859
|
-
/**
|
|
860
|
-
* uuid from threejs
|
|
861
|
-
* @param uuid
|
|
862
|
-
*/
|
|
863
|
-
async deleteObject3D(uuid) {
|
|
864
|
-
this.dictionnaryObjects3D.get(uuid).obj3D.visible = false;
|
|
865
|
-
}
|
|
866
|
-
getObject3DModelNodeFromDictionnary(uuid) {
|
|
867
|
-
let obj = this.dictionnaryObjects3D.get(uuid);
|
|
868
|
-
if (!obj) {
|
|
869
|
-
console.log("weird thing again");
|
|
870
|
-
return null;
|
|
871
|
-
}
|
|
872
|
-
//might break things or fix everything ..?
|
|
873
|
-
if (obj.obj3D.uuid != uuid) {
|
|
874
|
-
console.log("we have THE problem");
|
|
875
|
-
obj.obj3D.uuid = uuid;
|
|
876
|
-
}
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
*
|
|
881
|
-
* @param
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
mattertagData.
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
mattertagData.
|
|
893
|
-
mattertagData.
|
|
894
|
-
|
|
895
|
-
this.
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
*
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
mattertagData
|
|
905
|
-
mattertagData.
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
this.
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
*
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
this.
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
this.
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
this.
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
this.
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
this.
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
*
|
|
1004
|
-
* @param
|
|
1005
|
-
* @param
|
|
1006
|
-
* @param
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
object.pois.items
|
|
1026
|
-
|
|
1027
|
-
const
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
this.sdk.
|
|
1042
|
-
this.
|
|
1043
|
-
|
|
1044
|
-
.
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
this.
|
|
1053
|
-
this.sdk.
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
*
|
|
1061
|
-
* @
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
let
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
*
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
*
|
|
1094
|
-
* @
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
//
|
|
1107
|
-
//
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
//
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
this.
|
|
1242
|
-
this.
|
|
1243
|
-
this.
|
|
1244
|
-
|
|
1245
|
-
this.
|
|
1246
|
-
this.
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
this.pointerButton.removeEventListener('
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
//
|
|
1276
|
-
//
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
var
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
node.addComponent('mp.lights')
|
|
1286
|
-
node.
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
nodeControl.
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
//
|
|
1299
|
-
//
|
|
1300
|
-
//
|
|
1301
|
-
|
|
1302
|
-
let
|
|
1303
|
-
let
|
|
1304
|
-
let
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
localRotation
|
|
1326
|
-
|
|
1327
|
-
localPosition
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
case 'obj':
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
case 'fbx':
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
case 'gltf':
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
case 'glb':
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
case 'dae':
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
console.log(
|
|
1360
|
-
console.log(
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
console.log(
|
|
1364
|
-
|
|
1365
|
-
//
|
|
1366
|
-
//
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
lightsNode.
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
modelNode.obj3D.
|
|
1377
|
-
modelNode.obj3D.
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
this.
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
//
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
//
|
|
1400
|
-
//console.log(
|
|
1401
|
-
|
|
1402
|
-
this.
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
//console.log(
|
|
1407
|
-
//console.log(
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
"
|
|
1422
|
-
"
|
|
1423
|
-
"
|
|
1424
|
-
"
|
|
1425
|
-
|
|
1426
|
-
"
|
|
1427
|
-
"
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
"
|
|
1432
|
-
"
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
"
|
|
1436
|
-
"
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
//
|
|
1455
|
-
//
|
|
1456
|
-
// ci
|
|
1457
|
-
|
|
1458
|
-
cv
|
|
1459
|
-
|
|
1460
|
-
plane
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
plane.
|
|
1467
|
-
|
|
1468
|
-
sc
|
|
1469
|
-
sc.
|
|
1470
|
-
sc.
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
sc.
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
sc
|
|
1481
|
-
sc.
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
sc.
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
obj
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
//
|
|
1514
|
-
//this.sdk.Tag.
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
this.
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
node =
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
node.
|
|
1537
|
-
|
|
1538
|
-
//
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
//
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
//
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
}
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWF0dGVycG9ydC5zZXJ2aWNlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvbmd4LXNtYXJ0ZXJwbGFuLWNvcmUvc3JjL2xpYi9zZXJ2aWNlcy9tYXR0ZXJwb3J0LnNlcnZpY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFDLE1BQU0sRUFBRSxVQUFVLEVBQVMsTUFBTSxlQUFlLENBQUM7QUFFekQsT0FBTyxFQUFDLE9BQU8sRUFBQyxNQUFNLE1BQU0sQ0FBQztBQUM3QiwyQ0FBMkM7QUFDM0MsT0FBTyxFQUNMLDJCQUEyQixFQUMzQixlQUFlLEVBQ2YsSUFBSSxHQUNMLE1BQU0sb0JBQW9CLENBQUM7QUFDNUIsT0FBTyxFQUFDLGFBQWEsRUFBQyxNQUFNLGtCQUFrQixDQUFDO0FBQy9DLE9BQU8sRUFFTCxXQUFXLEVBRVgsbUJBQW1CLEVBRW5CLE9BQU8sRUFDUCxRQUFRLEVBQ1IsU0FBUyxFQUNULGtCQUFrQixHQUNuQixNQUFNLGtCQUFrQixDQUFDO0FBQzFCLE9BQU8sRUFBQyxRQUFRLEVBQUMsTUFBTSxPQUFPLENBQUM7QUFJL0IsT0FBTyxFQUFDLFVBQVUsRUFBQyxNQUFNLGtCQUFrQixDQUFDO0FBRzVDLE9BQU8sRUFBQyxjQUFjLEVBQUMsTUFBTSx5REFBeUQsQ0FBQztBQUN2RixPQUFPLEVBQUMsYUFBYSxFQUFDLE1BQU0sd0RBQXdELENBQUM7QUFDckYsT0FBTyxFQUFDLGNBQWMsRUFBQyxNQUFNLHlEQUF5RCxDQUFDO0FBR3ZGLE9BQU8sRUFBQyxRQUFRLEVBQUMsTUFBTSw2Q0FBNkMsQ0FBQzs7Ozs7QUF3QnJFLE1BQU0sT0FBTyxpQkFBaUI7SUFvSjVCLFlBQ29CLE1BQWMsRUFDeEIsTUFBYyxFQUNkLFdBQTJCLEVBQzNCLGlCQUF3QyxFQUN4QyxNQUFjO1FBSGQsV0FBTSxHQUFOLE1BQU0sQ0FBUTtRQUNkLGdCQUFXLEdBQVgsV0FBVyxDQUFnQjtRQUMzQixzQkFBaUIsR0FBakIsaUJBQWlCLENBQXVCO1FBQ3hDLFdBQU0sR0FBTixNQUFNLENBQVE7UUF2SmhCLFVBQUssR0FBVSxFQUFFLENBQUMsQ0FBQSxrQkFBa0I7UUFFcEMsVUFBSyxHQUFpQixFQUFFLENBQUM7UUFVMUIsdUJBQWtCLEdBQVEsRUFBQyxDQUFDLEVBQUMsR0FBRyxFQUFDLENBQUMsRUFBQyxHQUFHLEVBQUMsQ0FBQyxFQUFDLEdBQUcsRUFBQyxDQUFDO1FBUTdDLGtDQUE2QixHQUFHLEtBQUssQ0FBQztRQUs5QyxlQUFlO1FBQ1Asb0JBQWUsR0FBRyxLQUFLLENBQUM7UUFFeEIsb0JBQWUsR0FBVyxrQkFBa0IsQ0FBQyxPQUFPLENBQUM7UUFFN0QsOERBQThEO1FBQ3RELGlCQUFZLEdBQWtCLEVBQUUsQ0FBQztRQUV6QywwREFBMEQ7UUFDbEQsb0JBQWUsR0FBK0IsSUFBSSxHQUFHLEVBQUUsQ0FBQztRQUV4RCx5QkFBb0IsR0FBcUIsSUFBSSxHQUFHLEVBQUUsQ0FBQztRQUVuRCw4QkFBeUIsR0FBcUIsSUFBSSxHQUFHLEVBQUUsQ0FBQztRQUl4RCxnQkFBVyxHQUFHLEVBQUUsQ0FBQztRQUVqQix5QkFBb0IsR0FBYSxFQUFFLENBQUM7UUFFcEMsZUFBVSxHQUFHO1lBQ25CLEtBQUssRUFBRSxHQUFHO1lBQ1YsTUFBTSxFQUFFLEdBQUc7U0FDWixDQUFDO1FBRU0sZUFBVSxHQUFHO1lBQ25CLFVBQVUsRUFBRSxLQUFLO1lBQ2pCLE1BQU0sRUFBRSxJQUFJO1NBQ2IsQ0FBQztRQUVLLG9CQUFlLEdBQVcsRUFBRSxDQUFDO1FBTTdCLGlCQUFZLEdBQW9CLElBQUksT0FBTyxFQUFFLENBQUM7UUFFckQsK0JBQStCO1FBQ3hCLHNCQUFpQixHQUFpQixJQUFJLE9BQU8sRUFBRSxDQUFDO1FBb0J2RCxvQkFBZSxHQUFhLEVBQUUsQ0FBQztRQUV4QixjQUFTLEdBQThDLElBQUksT0FBTyxFQUFFLENBQUM7UUFRckUscUJBQWdCLEdBQUcsS0FBSyxDQUFDO1FBRXpCLHNCQUFpQixHQUFHLEtBQUssQ0FBQztRQUV6QixzQkFBaUIsR0FBRyxJQUFJLENBQUM7UUFFMUIsc0JBQWlCLEdBQWUsVUFBVSxDQUFDLE9BQU8sQ0FBQztRQUVuRCx3QkFBbUIsR0FBRyxJQUFJLE9BQU8sRUFBYyxDQUFDO1FBRWhELGNBQVMsR0FBRyxJQUFJLE9BQU8sRUFBVSxDQUFDO1FBRXpDLG1CQUFjLEdBQUcsS0FBSyxDQUFDO1FBUXZCOztXQUVHO1FBQ0gsNEJBQXVCLEdBQUcsR0FBRyxFQUFFO1lBQzdCLElBQUksSUFBSSxDQUFDLGlCQUFpQixFQUFFO2dCQUMxQixNQUFNLGFBQWEsR0FBRyxJQUFJLENBQUMsZUFBZSxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsaUJBQWlCLENBQUMsQ0FBQztnQkFDdkUsYUFBYSxDQUFDLFdBQVcsQ0FBQyxFQUFDLEdBQUcsSUFBSSxDQUFDLGNBQWMsQ0FBQyxRQUFRLEVBQUMsQ0FBQyxDQUFDLENBQUMsMkJBQTJCO2dCQUN6RixhQUFhLENBQUMsU0FBUyxDQUFDLEVBQUMsR0FBRyxJQUFJLENBQUMsY0FBYyxDQUFDLE1BQU0sRUFBQyxDQUFDLENBQUMsQ0FBQywyQkFBMkI7Z0JBQ3JGLElBQUksQ0FBQyxlQUFlLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxpQkFBaUIsRUFBRSxhQUFhLENBQUMsQ0FBQztnQkFDaEUsSUFBSSxDQUFDLDhCQUE4QixDQUFDLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDO2FBQzdEO1lBQ0QsSUFBSSxDQUFDLG9CQUFvQixFQUFFLENBQUM7UUFDOUIsQ0FBQyxDQUFDO1FBRUYsNkJBQXdCLEdBQUcsQ0FBQyxDQUFDLEVBQUUsRUFBRTtZQUMvQixDQUFDLENBQUMsY0FBYyxFQUFFLENBQUM7WUFDbkIsSUFBSSxDQUFDLHFCQUFxQixFQUFFLENBQUM7WUFDN0IsS0FBSyxDQUFDLGtCQUFrQixDQUFDLENBQUM7UUFDNUIsQ0FBQyxDQUFDO1FBRUYsOEJBQXlCLEdBQUcsQ0FBQyxDQUFDLEVBQUUsRUFBRTtZQUNoQyxJQUFJLENBQUMsOEJBQThCLENBQUMsU0FBUyxHQUFHO1NBQzNDLElBQUksQ0FBQyxhQUFhLENBQUMsSUFBSSxDQUFDLGNBQWMsQ0FBQyxRQUFRLENBQUM7O1NBRWhELElBQUksQ0FBQyxhQUFhLENBQUMsSUFBSSxDQUFDLGNBQWMsQ0FBQyxNQUFNLENBQUM7O1NBRTlDLElBQUksQ0FBQyxjQUFjLENBQUMsT0FBTyxFQUFFLENBQUM7WUFDbkMsaUVBQWlFO1lBQ2pFLElBQUksQ0FBQyx1QkFBdUIsQ0FBQyxLQUFLLENBQUMsT0FBTyxHQUFHLE1BQU0sQ0FBQztRQUN0RCxDQUFDLENBQUE7UUFTQyxJQUFJLENBQUMsTUFBTSxHQUFHLE1BQU0sQ0FBQztRQUVyQixzQkFBc0I7UUFDdEIsSUFBSSxDQUFDLENBQUMsSUFBSSxDQUFDLHVCQUF1QjtZQUNoQyxDQUFDLFFBQVEsQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLENBQUMsSUFBSSxRQUFRLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsV0FBVyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsRUFBRTtZQUN0RyxJQUFJLENBQUMsNkJBQTZCLEdBQUcsV0FBVyxDQUFDLEdBQUcsRUFBRTtnQkFDcEQsSUFBSSxDQUFDLElBQUksQ0FBQyxjQUFjLEVBQUU7b0JBQ3hCLE9BQU87aUJBQ1I7Z0JBRUQsTUFBTSxRQUFRLEdBQUcsSUFBSSxDQUFDLGNBQWMsQ0FBQyxJQUFJLEdBQUcsSUFBSSxDQUFDO2dCQUNqRCxJQUFJLElBQUksSUFBSSxFQUFFLENBQUMsT0FBTyxFQUFFLEdBQUcsUUFBUSxFQUFFO29CQUNuQyxJQUFJLElBQUksQ0FBQyw2QkFBNkIsRUFBRTt3QkFDdEMsT0FBTztxQkFDUjtvQkFFRCxNQUFNLElBQUksR0FBRzt3QkFDWCxDQUFDLEVBQUUsSUFBSSxDQUFDLFNBQVMsQ0FBQyxXQUFXO3dCQUM3QixDQUFDLEVBQUUsSUFBSSxDQUFDLFNBQVMsQ0FBQyxZQUFZO3FCQUMvQixDQUFDO29CQUNGLE1BQU0sS0FBSyxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsVUFBVSxDQUFDLGFBQWEsQ0FBQyxJQUFJLENBQUMsY0FBYyxDQUFDLFFBQVEsRUFBRSxJQUFJLENBQUMsVUFBVSxFQUFFLElBQUksQ0FBQyxDQUFDO29CQUNyRyxJQUFJLENBQUMsdUJBQXVCLENBQUMsS0FBSyxDQUFDLElBQUksR0FBRyxHQUFHLEtBQUssQ0FBQyxDQUFDLEdBQUcsRUFBRSxJQUFJLENBQUM7b0JBQzlELElBQUksQ0FBQyx1QkFBdUIsQ0FBQyxLQUFLLENBQUMsR0FBRyxHQUFHLEdBQUcsS0FBSyxDQUFDLENBQUMsR0FBRyxFQUFFLElBQUksQ0FBQztvQkFDN0QsSUFBSSxDQUFDLHVCQUF1QixDQUFDLEtBQUssQ0FBQyxPQUFPLEdBQUcsT0FBTyxDQUFDO29CQUNyRCw4REFBOEQ7b0JBQzlELElBQUksQ0FBQyw2QkFBNkIsR0FBRyxJQUFJLENBQUM7aUJBQzNDO1lBQ0gsQ0FBQyxFQUFFLEdBQUcsQ0FBQyxDQUFDO1NBQ1Q7SUFDSCxDQUFDO0lBM0dELElBQVcsY0FBYztRQUN2QixPQUFPLElBQUksQ0FBQyxlQUFlLENBQUM7SUFDOUIsQ0FBQztJQUVELElBQVcsY0FBYyxDQUFDLEtBQWE7UUFDckMsSUFBSSxDQUFDLGVBQWUsR0FBRyxLQUFLLENBQUM7SUFDL0IsQ0FBQztJQXVHRDs7Ozs7T0FLRztJQUNILEtBQUssQ0FBQyxPQUFPLENBQ1gsVUFBMEIsRUFDMUIsU0FBbUIsUUFBUSxDQUFDLElBQUk7UUFFaEMsSUFBSSxJQUFJLENBQUMsR0FBRyxFQUFFO1lBQ1osa0NBQWtDO1lBQ2xDLE1BQU0sSUFBSSxDQUFDLDRCQUE0QixFQUFFLENBQUM7U0FDM0M7UUFDRCxJQUFJLENBQUMsVUFBVSxHQUFHLFVBQVUsQ0FBQztRQUM3QixJQUFJLENBQUMsUUFBUSxHQUFHLE1BQU0sQ0FBQztRQUN2QixPQUFPLElBQUksT0FBTyxDQUFDLENBQUMsT0FBTyxFQUFFLE1BQU0sRUFBRSxFQUFFO1lBQ3JDLHdCQUF3QjtZQUN4QixJQUFJLENBQUMsYUFBYSxHQUFHLFFBQVEsQ0FBQyxhQUFhLENBQ3pDLHVCQUF1QixDQUNULENBQUM7WUFDakIsSUFBSSxDQUFDLFNBQVMsR0FBRyxRQUFRLENBQUMsYUFBYSxDQUFDLGdCQUFnQixDQUFnQixDQUFDO1lBQ3pFLE1BQU0sTUFBTSxHQUFHLFFBQVEsQ0FBQyxhQUFhLENBQ25DLGdCQUFnQixDQUNJLENBQUM7WUFDdkIsSUFBSSxDQUFDLE1BQU0sRUFBRTtnQkFDWCxPQUFPO2FBQ1I7WUFFRCxnQkFBZ0I7WUFDaEIsSUFBSSxJQUFJLENBQUMsYUFBYSxFQUFFO2dCQUN0QixJQUFJLENBQUMsYUFBYSxDQUFDLGdCQUFnQixDQUNqQyxPQUFPLEVBQ1AsSUFBSSxDQUFDLHVCQUF1QixDQUM3QixDQUFDO2dCQUNGLHdCQUF3QjtnQkFDeEIsSUFBSSxDQUFDLGFBQWEsQ0FBQyxnQkFBZ0IsQ0FDakMsYUFBYSxFQUNiLElBQUksQ0FBQyx3QkFBd0IsQ0FDOUIsQ0FBQzthQUNIO1lBQ0Qsd0JBQXdCO1lBQ3hCLElBQUksQ0FBQyx1QkFBdUIsR0FBRyxRQUFRLENBQUMsYUFBYSxDQUNuRCxTQUFTLENBQ0ssQ0FBQztZQUNqQixJQUFJLENBQUMsOEJBQThCLEdBQUcsUUFBUSxDQUFDLGFBQWEsQ0FDMUQsT0FBTyxDQUNPLENBQUM7WUFDakIsSUFBSSxJQUFJLENBQUMsdUJBQXVCLEVBQUU7Z0JBQ2hDLHFEQUFxRDtnQkFDckQsSUFBSSxDQUFDLHVCQUF1QixDQUFDLGdCQUFnQixDQUMzQyxPQUFPLEVBQ1AsSUFBSSxDQUFDLHlCQUF5QixDQUMvQixDQUFDO2FBQ0g7WUFFRCxXQUFXO1lBQ1gsT0FBTyxDQUFDLEdBQUcsQ0FBQyx3QkFBd0IsQ0FBQyxDQUFDO1lBQ3RDLE1BQU0sY0FBYyxHQUFHLE1BQU0sQ0FBQyxhQUFhLENBQUM7WUFDNUMsTUFBTSxDQUFDLGdCQUFnQixDQUNyQixNQUFNLEVBQ04sS0FBSztnQkFDSCxJQUFJO29CQUNGLElBQUksQ0FBQyxHQUFHLEdBQUcsTUFBTSxjQUFjLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FDNUMsY0FBYyxFQUNkLDJCQUEyQixFQUMzQixLQUFLLENBQ04sQ0FBQztpQkFDSDtnQkFBQyxPQUFPLENBQUMsRUFBRTtvQkFDVixPQUFPLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDO29CQUNqQixPQUFPO2lCQUNSO2dCQUVELGdEQUFnRDtnQkFDaEQsUUFBUSxNQUFNLEVBQUU7b0JBQ2QsS0FBSyxRQUFRLENBQUMsSUFBSTt3QkFDaEIsSUFBSSxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsZUFBZSxDQUM1QixhQUFhLEVBQ2IsSUFBSSxDQUFDLE1BQU0sQ0FBQyxTQUFTLENBQUMsV0FBVyxDQUNsQyxDQUFDO3dCQUNGLElBQUksQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLGVBQWUsQ0FDNUIsZ0JBQWdCLEVBQ2hCLElBQUksQ0FBQyxNQUFNLENBQUMsU0FBUyxDQUFDLGNBQWMsQ0FDckMsQ0FBQzt3QkFDRixJQUFJLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxlQUFlLENBQzVCLGNBQWMsRUFDZCxJQUFJLENBQUMsTUFBTSxDQUFDLFNBQVMsQ0FBQyxZQUFZLENBQ25DLENBQUM7d0JBQ0YsSUFBSSxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsZUFBZSxDQUM1QixXQUFXLEVBQ1gsSUFBSSxDQUFDLE1BQU0sQ0FBQyxTQUFTLENBQUMsU0FBUyxDQUNoQyxDQUFDO3dCQUNGLElBQUksQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLGVBQWUsQ0FDNUIsZUFBZSxFQUNmLElBQUksQ0FBQyxNQUFNLENBQUMsU0FBUyxDQUFDLGFBQWEsQ0FDcEMsQ0FBQzt3QkFFRixJQUFJLENBQUMsR0FBRyxDQUFDLFlBQVksQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDOzRCQUNuQyxPQUFPLEVBQUUsVUFDUCxLQUFVLEVBQ1YsSUFBcUIsRUFDckIsVUFBZTtnQ0FFZixlQUFlO2dDQUNmLHNDQUFzQztnQ0FDdEMsYUFBYTtnQ0FDYixZQUFZO2dDQUNaLEtBQUs7Z0NBQ0wsbUNBQW1DO2dDQUNuQyxJQUFJLENBQUMsV0FBVyxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUM7NEJBQ2pDLENBQUMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDOzRCQUNaLG1CQUFtQixFQUFFLFVBQVUsVUFBZTtnQ0FDNUMsK0RBQStEO2dDQUMvRCxJQUFJLENBQUMsNkJBQTZCLEVBQUUsQ0FBQzs0QkFDdkMsQ0FBQyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUM7eUJBQ2IsQ0FBQyxDQUFDO3dCQUNILElBQUksQ0FBQyxHQUFHLENBQUMsWUFBWSxDQUFDLElBQUksQ0FBQyxTQUFTLENBQ2xDLFVBQVUsb0JBQXFDOzRCQUM3QyxxQ0FBcUM7NEJBQ3JDLElBQUksQ0FBQyxlQUFlLEdBQUcsb0JBQW9CLENBQUMsTUFBTSxDQUFDOzRCQUNuRCxzRkFBc0Y7d0JBQ3hGLENBQUMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQ2IsQ0FBQzt3QkFDRixNQUFNO29CQUNSLEtBQUssUUFBUSxDQUFDLE1BQU07d0JBQ2xCLElBQUksQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLGVBQWUsQ0FDNUIsV0FBVyxFQUNYLElBQUksQ0FBQyxNQUFNLENBQUMsU0FBUyxDQUFDLFNBQVMsQ0FDaEMsQ0FBQzt3QkFDRixNQUFNO29CQUNSLEtBQUssUUFBUSxDQUFDLEtBQUs7d0JBQ2pCLElBQUksQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLGVBQWUsQ0FDNUIscUJBQXFCLEVBQ3JCLElBQUksQ0FBQyxNQUFNLENBQUMsU0FBUyxDQUFDLG1CQUFtQixDQUMxQyxDQUFDO3dCQUNGLElBQUksQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLGVBQWUsQ0FDNUIsdUJBQXVCLEVBQ3ZCLElBQUksQ0FBQyxNQUFNLENBQUMsU0FBUyxDQUFDLHFCQUFxQixDQUM1QyxDQUFDO3dCQUNGLElBQUksQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLGVBQWUsQ0FDNUIsa0JBQWtCLEVBQ2xCLElBQUksQ0FBQyxNQUFNLENBQUMsU0FBUyxDQUFDLGdCQUFnQixDQUN2QyxDQUFDO3dCQUNGLElBQUksQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLGVBQWUsQ0FDNUIsa0JBQWtCLEVBQ2xCLElBQUksQ0FBQyxNQUFNLENBQUMsU0FBUyxDQUFDLGdCQUFnQixDQUN2QyxDQUFDO3dCQUNGLE1BQU07b0JBQ1I7d0JBQ0UsTUFBTTtpQkFDVDtnQkFFRCxJQUFJLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxlQUFlLENBQzVCLGVBQWUsRUFDZixJQUFJLENBQUMsTUFBTSxDQUFDLFNBQVMsQ0FBQyxhQUFhLENBQ3BDLENBQUM7Z0JBRUYsa0hBQWtIO2dCQUNsSCxJQUFJLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsU0FBUyxDQUFDLENBQUMsV0FBVyxFQUFFLEVBQUU7b0JBQzlDLE9BQU8sQ0FBQyxHQUFHLENBQUMsc0JBQXNCLElBQUksQ0FBQyxTQUFTLENBQUMsV0FBVyxDQUFDLEVBQUUsQ0FBQyxDQUFDO2dCQUNuRSxDQUFDLENBQUMsQ0FBQztnQkFFSCx3QkFBd0I7Z0JBQ3hCLElBQUksQ0FBQyxHQUFHLENBQUMsT0FBTyxDQUFDLFlBQVksQ0FBQyxTQUFTLENBQ3JDLFVBQVUsWUFBaUI7b0JBQ3pCLElBQUksQ0FBQyxjQUFjLEdBQUcsWUFBWSxDQUFDO29CQUNuQyxJQUFJLENBQUMsY0FBYyxDQUFDLElBQUksR0FBRyxJQUFJLElBQUksRUFBRSxDQUFDLE9BQU8sRUFBRSxDQUFDO29CQUNoRCxJQUFJLENBQUMsSUFBSSxDQUFDLHlCQUF5QixFQUFFO3dCQUNuQyxJQUFJLENBQUMseUJBQXlCLEdBQUc7NEJBQy9CLENBQUMsRUFBRSxDQUFDOzRCQUNKLENBQUMsRUFBRSxDQUFDOzRCQUNKLENBQUMsRUFBRSxDQUFDO3lCQUNMLENBQUM7cUJBQ0g7b0JBRUQsSUFDRSxJQUFJLENBQUMsZUFBZSxLQUFLLGtCQUFrQixDQUFDLE9BQU87d0JBQ25ELElBQUksQ0FBQyxpQkFBaUIsRUFDdEI7d0JBQ0EsOERBQThEO3dCQUM5RCwyREFBMkQ7d0JBQzNELElBQUksQ0FBQyxvQkFBb0IsQ0FBQyxJQUFJLENBQUMsaUJBQWlCLENBQUMsQ0FBQztxQkFDbkQ7b0JBQ0QsSUFBSSxDQUFDLENBQUMsSUFBSSxDQUFDLHVCQUF1QixJQUFJLENBQUMsQ0FBQyxJQUFJLENBQUMsdUJBQXVCLENBQUMsS0FBSzt3QkFDMUUsQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDLE9BQU8sQ0FBQyw0QkFBNEIsQ0FBQyxLQUFLLENBQUMsQ0FBQyxJQUFJLFFBQVEsQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxXQUFXLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxFQUFFO3dCQUNqSCxJQUFJLENBQUMsdUJBQXVCLENBQUMsS0FBSyxDQUFDLE9BQU8sR0FBRyxNQUFNLENBQUM7d0JBQ3BELElBQUksQ0FBQyw2QkFBNkIsR0FBRyxLQUFLLENBQUM7cUJBQzVDO2dCQUNILENBQUMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQ2IsQ0FBQztnQkFFRixhQUFhO2dCQUNiLElBQUksQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxTQUFTLENBQUMsQ0FBQyxJQUFJLEVBQUUsRUFBRTtvQkFDdkMsSUFBSSxDQUFDLGlCQUFpQixHQUFHLEtBQUssQ0FBQztvQkFDL0IsUUFBUSxJQUFJLEVBQUU7d0JBQ1osS0FBSyxnQkFBZ0I7NEJBQ25CLElBQUksQ0FBQyxpQkFBaUIsR0FBRyxVQUFVLENBQUMsU0FBUyxDQUFDOzRCQUM5QyxNQUFNO3dCQUNSLEtBQUssZ0JBQWdCOzRCQUNuQixJQUFJLENBQUMsaUJBQWlCLEdBQUcsVUFBVSxDQUFDLFNBQVMsQ0FBQzs0QkFDOUMsTUFBTTt3QkFDUixLQUFLLGFBQWE7NEJBQ2hCLElBQUksQ0FBQyxpQkFBaUIsR0FBRyxVQUFVLENBQUMsTUFBTSxDQUFDOzRCQUMzQyxNQUFNO3dCQUNSLEtBQUssb0JBQW9COzRCQUN2QixJQUFJLENBQUMsaUJBQWlCLEdBQUcsVUFBVSxDQUFDLGFBQWEsQ0FBQzs0QkFDbEQsTUFBTTt3QkFDUjs0QkFDRSxJQUFJLENBQUMsaUJBQWlCLEdBQUcsVUFBVSxDQUFDLE9BQU8sQ0FBQztxQkFDL0M7b0JBQ0QsSUFBSSxDQUFDLG1CQUFtQixDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsaUJBQWlCLENBQUMsQ0FBQztnQkFDeEQsQ0FBQyxDQUFDLENBQUM7Z0JBRUgscUJBQXFCO2dCQUNyQixJQUFJLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUM1QixTQUFTLE1BQU0sQ0FBQyxJQUFTO29CQUN2QixJQUFJLENBQUMsVUFBVSxHQUFHLElBQUksQ0FBQztvQkFFdkIsSUFBSSxDQUFDLGlCQUFpQixDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztvQkFDbEMsc0RBQXNEO29CQUN0RCxvREFBb0Q7b0JBQ3BELDRDQUE0QztnQkFDOUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FDYixDQUFDO2dCQUVGLHNCQUFzQjtnQkFDdEIsSUFBSSxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQztvQkFDNUIsbUJBQW1CLEVBQUUsU0FBUyxNQUFNLENBQUMsVUFBYzt3QkFDakQsMkNBQTJDO3dCQUMzQyxJQUFJLENBQUMsTUFBTSxHQUFHLE1BQU0sQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLENBQUM7b0JBQ3hDLENBQUMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDO2lCQUNiLENBQUMsQ0FBQztnQkFFSCw2QkFBNkI7Z0JBQzdCLElBQUksQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxTQUFTLENBQzlCLFNBQVMsTUFBTSxDQUFDLFlBQTZCO29CQUMzQyw0Q0FBNEM7b0JBQzVDLElBQUksWUFBWSxDQUFDLEdBQUcsS0FBSyxFQUFFLEVBQUU7d0JBQzNCLDhEQUE4RDtxQkFDL0Q7eUJBQU07d0JBQ0wsbURBQW1EO3dCQUNuRCxJQUFJLENBQUMsWUFBWSxDQUFDLElBQUksQ0FBQyxZQUFZLENBQUMsR0FBRyxDQUFDLENBQUM7cUJBQzFDO2dCQUNILENBQUMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQ2IsQ0FBQztnQkFFRiwwQkFBMEI7Z0JBQzFCLElBQUksQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUM7b0JBQzVCLG1CQUFtQixFQUFFLFNBQVMsR0FBRyxDQUFZLFVBQWU7d0JBQzFELElBQUksQ0FBQyxNQUFNLEdBQUcsTUFBTSxDQUFDLE1BQU0sQ0FBQyxVQUFVLENBQUMsQ0FBQztvQkFDMUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUM7aUJBQ2IsQ0FBQyxDQUFDO2dCQUVILGlDQUFpQztnQkFDakMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsV0FBVyxFQUFFLENBQUMsR0FBVyxFQUFFLEVBQUU7b0JBQ3ZDLHlCQUF5QjtvQkFDekIsSUFBSTt3QkFDRixNQUFNLGFBQWEsR0FBRyxJQUFJLENBQUMsZUFBZSxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQzt3QkFDcEQsSUFBSSxDQUFDLGFBQWEsRUFBQzs0QkFDakIsT0FBTyxDQUFDLEdBQUcsQ0FBQyw2QkFBNkIsQ0FBQyxDQUFDOzRCQUMzQyxPQUFPO3lCQUNSO3dCQUNELE1BQU0sR0FBRyxHQUFHLFVBQVUsQ0FBQyxtQkFBbUIsQ0FDeEMsYUFBYSxDQUFDLFNBQVMsRUFBRSxFQUN6QixhQUFhLENBQUMsT0FBTyxFQUFFLENBQ3hCLENBQUM7d0JBQ0YsSUFBSSxHQUFHLEtBQUssRUFBRSxFQUFFOzRCQUNkLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxhQUFhLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDOzRCQUNoRCxJQUFJLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxHQUFHLEVBQUU7Z0NBQ25CLElBQUksQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQzs0QkFDOUIsQ0FBQyxDQUFDLENBQUM7eUJBQ0o7cUJBQ0Y7b0JBQUMsTUFBTTt3QkFDTixPQUFPLENBQUMsR0FBRyxDQUFDLDZCQUE2QixDQUFDLENBQUM7cUJBQzVDO2dCQUNILENBQUMsQ0FBQyxDQUFDO2dCQUVILGdCQUFnQjtnQkFDaEIseURBQXlEO2dCQUN6RCxpR0FBaUc7Z0JBQ2pHLElBQUksQ0FBQyxZQUFZLEdBQUcsV0FBVyxDQUM3QixJQUFJLENBQUMsa0JBQWtCLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxFQUNsQyxFQUFFLENBQ0gsQ0FBQztnQkFFRjs7bUJBRUc7Z0JBQ0gsSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQ1Qsc0JBQXNCLEVBQ3RCLFVBQVUsRUFBRSxFQUFFLElBQUk7b0JBQ2hCLDhEQUE4RDtvQkFDOUQsSUFBSSxDQUFDLGdCQUFnQixHQUFHLElBQUksQ0FBQztnQkFDL0IsQ0FBQyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FDYixDQUFDO2dCQUVGLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUNULG9CQUFvQixFQUNwQixVQUFVLE9BQU8sRUFBRSxPQUFPO29CQUN4QixtRUFBbUU7b0JBQ25FLElBQUksT0FBTyxLQUFLLG9CQUFvQixFQUFFO3dCQUNwQyxJQUFJLENBQUMsZ0JBQWdCLEdBQUcsS0FBSyxDQUFDO3FCQUMvQjtnQkFDSCxDQUFDLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUNiLENBQUM7Z0JBRUYsSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQ1QsSUFBSSxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLEtBQUssRUFDMUIsVUFBVSxRQUFRLEVBQUUsUUFBUTtvQkFDMUIsNENBQTRDO29CQUM1Qyw2Q0FBNkM7b0JBQzdDLElBQUksQ0FBQyxpQkFBaUIsR0FBRyxLQUFLLENBQUM7b0JBQy9CLElBQUksQ0FBQyxvQkFBb0IsRUFBRSxDQUFDO2dCQUM5QixDQUFDLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUNiLENBQUM7Z0JBQ0YsSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQ1QsSUFBSSxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLElBQUksRUFDekIsVUFBVSxTQUFTLEVBQUUsT0FBTztvQkFDMUIsK0NBQStDO29CQUMvQyxzREFBc0Q7b0JBQ3RELElBQUksQ0FBQyxpQkFBaUIsR0FBRyxJQUFJLENBQUM7Z0JBQ2hDLENBQUMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQ2IsQ0FBQztnQkFFRix1Q0FBdUM7Z0JBQ3ZDLE1BQU0sQ0FBQyxXQUFXLENBQUMsR0FBRyxNQUFNLElBQUksQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLGFBQWEsQ0FBQyxDQUFDLENBQUMsQ0FBQztnQkFDNUQsTUFBTSxJQUFJLEdBQUcsV0FBVyxDQUFDLE9BQU8sRUFBRSxDQUFDO2dCQUNuQyxJQUFJLENBQUMsS0FBSyxFQUFFLENBQUM7Z0JBQ2IsSUFBSSxDQUFDLFlBQVksR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQztnQkFFdEMsa0VBQWtFO2dCQUNsRSw2Q0FBNkM7Z0JBQzdDLGtEQUFrRDtnQkFDbEQsdUNBQXVDO2dCQUN2QyxzQ0FBc0M7Z0JBQ3RDLHNEQUFzRDtnQkFDdEQsTUFBTTtnQkFHTiw4REFBOEQ7Z0JBQzlELDhDQUE4QztnQkFDOUMsZ0NBQWdDO2dCQUNoQyx3REFBd0Q7Z0JBQ3hELEVBQUU7Z0JBQ0YsNkJBQTZCO2dCQUM3QixvREFBb0Q7Z0JBQ3BELEVBQUU7Z0JBQ0YseUJBQXlCO2dCQUN6QixZQUFZO2dCQUNaLHFDQUFxQztnQkFDckMsNEVBQTRFO2dCQUM1RSx5Q0FBeUM7Z0JBQ3pDLCtCQUErQjtnQkFDL0Isd0JBQXdCO2dCQUN4Qiw0Q0FBNEM7Z0JBQzVDLGVBQWU7Z0JBQ2YsYUFBYTtnQkFDYixZQUFZO2dCQUNaLG9CQUFvQjtnQkFDcEIsc0RBQXNEO2dCQUN0RCwwQkFBMEI7Z0JBQzFCLFFBQVE7Z0JBQ1IscUJBQXFCO2dCQUNyQixnQkFBZ0I7Z0JBQ2hCLFFBQVE7Z0JBQ1IsRUFBRTtnQkFDRix5QkFBeUI7Z0JBQ3pCLFlBQVk7Z0JBQ1osd0ZBQXdGO2dCQUN4RixvQkFBb0I7Z0JBQ3BCLHNEQUFzRDtnQkFDdEQsMEJBQTBCO2dCQUMxQixRQUFRO2dCQUNSLHFCQUFxQjtnQkFDckIsZ0JBQWdCO2dCQUNoQixRQUFRO2dCQUNSLEVBQUU7Z0JBQ0YsbUNBQW1DO2dCQUNuQyxrQ0FBa0M7Z0JBQ2xDLHFDQUFxQztnQkFDckMsb0NBQW9DO2dCQUNwQyx3Q0FBd0M7Z0JBQ3hDLGlDQUFpQztnQkFDakMsNkJBQTZCO2dCQUM3QixnREFBZ0Q7Z0JBQ2hELHVDQUF1QztnQkFDdkMsK0RBQStEO2dCQUMvRCwrQkFBK0I7Z0JBQy9CLG1CQUFtQjtnQkFDbkIsK0JBQStCO2dCQUMvQiw4REFBOEQ7Z0JBQzlELFlBQVk7Z0JBQ1osRUFBRTtnQkFDRix3REFBd0Q7Z0JBQ3hELGFBQWE7Z0JBQ2Isb0NBQW9DO2dCQUNwQyxvREFBb0Q7Z0JBQ3BELG1DQUFtQztnQkFDbkMsc0JBQXNCO2dCQUN0QixFQUFFO2dCQUNGLHlFQUF5RTtnQkFDekUsZ0RBQWdEO2dCQUNoRCw0REFBNEQ7Z0JBQzVELGlEQUFpRDtnQkFDakQsK0JBQStCO2dCQUMvQixzQkFBc0I7Z0JBQ3RCLGFBQWE7Z0JBQ2IsVUFBVTtnQkFDVixVQUFVO2dCQUNWLGdDQUFnQztnQkFDaEMsa0JBQWtCO2dCQUNsQixpREFBaUQ7Z0JBQ2pELDZIQUE2SDtnQkFDN0gsTUFBTTtnQkFDTixNQUFNO2dCQUVOLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQztZQUNoQixDQUFDLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUNiLENBQUM7UUFDSixDQUFDLENBQUMsQ0FBQztJQUNMLENBQUM7SUFHRCxjQUFjO1FBQ1osSUFBSSxDQUFDLGlCQUFpQixHQUFHLElBQUksQ0FBQztJQUNoQyxDQUFDO0lBRUQsYUFBYSxDQUFDLEtBQTBDO1FBQ3RELElBQUksQ0FBQyxHQUFHLEtBQUssQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQzNCLElBQUksQ0FBQyxHQUFHLEtBQUssQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQzNCLElBQUksQ0FBQyxHQUFHLEtBQUssQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBRTNCLE9BQU8sUUFBUSxDQUFDLFFBQVEsQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDO0lBQ3pDLENBQUM7SUFFRCxFQUFFO0lBQ0YsNkNBQTZDO0lBQzdDLEVBQUU7SUFDRjs7T0FFRztJQUNILDZCQUE2QjtRQUMzQixJQUFJLElBQUksQ0FBQyxXQUFXLENBQUMsTUFBTSxHQUFHLENBQUMsRUFBRTtZQUMvQixNQUFNLFlBQVksR0FBRyxJQUFJLENBQUMsV0FBVyxDQUFDLE1BQU0sQ0FBQztZQUM3QyxJQUFJLENBQUMsb0JBQW9CLEdBQUcsRUFBRSxDQUFDO1lBQy9CLEtBQUssSUFBSSxLQUFLLEdBQUcsQ0FBQyxFQUFFLEtBQUssR0FBRyxZQUFZLEVBQUUsS0FBSyxJQUFJLENBQUMsRUFBRTtnQkFDcEQsTUFBTSxRQUFRLEdBQUcsMkJBQTJCLENBQzFDLElBQUksQ0FBQyxXQUFXLENBQUMsS0FBSyxHQUFHLENBQUMsQ0FBQyxFQUMzQixJQUFJLENBQUMsV0FBVyxDQUFDLEtBQUssQ0FBQyxDQUN4QixDQUFDO2dCQUNGLElBQUksQ0FBQyxvQkFBb0IsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUM7YUFDMUM7WUFDRCxJQUFJLENBQUMsY0FBYyxFQUFFLENBQUMsSUFBSSxDQUFDLENBQUMsR0FBRyxFQUFFLEVBQUU7Z0JBQ2pDLElBQUksQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDLENBQUMsU0FBUyxJQUFJLENBQUMsY0FBYyxrQkFBa0IsQ0FBQyxDQUFDLENBQUM7WUFDekUsQ0FBQyxDQUFDLENBQUM7U0FDSjtJQUNILENBQUM7SUFFRCxnQkFBZ0I7UUFDZCxPQUFPLElBQUksQ0FBQyxvQkFBb0IsQ0FBQztJQUNuQyxDQUFDO0lBRUQ7OztPQUdHO0lBQ0gsY0FBYztRQUNaLE9BQU8sSUFBSSxDQUFDLEdBQUcsQ0FBQyxRQUFRLENBQUMsY0FBYyxDQUNyQyxJQUFJLENBQUMsVUFBVSxFQUNmLElBQUksQ0FBQyxVQUFVLENBQ2hCLENBQUMsSUFBSSxDQUNKLFVBQVUsYUFBa0I7WUFDMUIsZ0JBQWdCO1lBQ2hCLElBQUksQ0FBQyxpQkFBaUIsR0FBRyxhQUFhLENBQUM7WUFDdkMsT0FBTyxPQUFPLENBQUMsT0FBTyxFQUFFLENBQUM7UUFDM0IsQ0FBQyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FDYixDQUFDO0lBQ0osQ0FBQztJQUVELGdCQUFnQjtRQUNkLE9BQU8sSUFBSSxDQUFDLGlCQUFpQixDQUFDO0lBQ2hDLENBQUM7SUFFRCxrQkFBa0I7UUFDaEIsTUFBTSxJQUFJLEdBQUc7WUFDWCxPQUFPLEVBQUUsSUFBSSxDQUFDLFdBQVc7WUFDekIsS0FBSyxFQUFFLElBQUksQ0FBQyxVQUFVLENBQUMsS0FBSztTQUM3QixDQUFDO1FBQ0YsT0FBTyxJQUFJLENBQUM7SUFDZCxDQUFDO0lBRUQsRUFBRTtJQUNGLDhCQUE4QjtJQUM5QixFQUFFO0lBQ0Y7O09BRUc7SUFDSCxrQkFBa0I7UUFDaEIsSUFDRSxJQUFJLENBQUMsZUFBZSxLQUFLLGtCQUFrQixDQUFDLE9BQU87WUFDbkQsSUFBSSxDQUFDLGlCQUFpQjtZQUN0QixJQUFJLENBQUMsY0FBYztZQUNuQixJQUFJLENBQUMsZUFBZSxDQUNsQixJQUFJLENBQUMsY0FBYyxDQUFDLFFBQVEsRUFDNUIsSUFBSSxDQUFDLHlCQUF5QixDQUMvQixHQUFHLEVBQUUsRUFDTjtZQUNBLElBQUksQ0FBQyxhQUFhLENBQUMsS0FBSyxDQUFDLE9BQU8sR0FBRyxNQUFNLENBQUM7WUFFMUMsTUFBTSxJQUFJLEdBQUc7Z0JBQ1gsQ0FBQyxFQUFFLElBQUksQ0FBQyxTQUFTLENBQUMsV0FBVztnQkFDN0IsQ0FBQyxFQUFFLElBQUksQ0FBQyxTQUFTLENBQUMsWUFBWTthQUMvQixDQUFDO1lBQ0YsTUFBTSxNQUFNLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxVQUFVLENBQUMsYUFBYSxDQUM5QyxJQUFJLENBQUMsY0FBYyxDQUFDLFFBQVEsRUFDNUIsSUFBSSxDQUFDLFVBQVUsRUFDZixJQUFJLENBQ0wsQ0FBQztZQUNGLElBQUksQ0FBQyxhQUFhLENBQUMsS0FBSyxDQUFDLElBQUksR0FBRyxHQUM5QixNQUFNLENBQUMsQ0FBQyxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxHQUFHLEVBQ25DLElBQUksQ0FBQztZQUNMLElBQUksQ0FBQyxhQUFhLENBQUMsS0FBSyxDQUFDLEdBQUcsR0FBRyxHQUFHLE1BQU0sQ0FBQyxDQUFDLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLEdBQUcsRUFBRSxJQUFJLENBQUM7WUFDMUUsSUFBSSxDQUFDLHlCQUF5QixHQUFHO2dCQUMvQixHQUFHLElBQUksQ0FBQyxjQUFjLENBQUMsUUFBUTthQUNoQyxDQUFDO1NBQ0g7YUFBTTtZQUNMLElBQUksQ0FBQyxhQUFhLENBQUMsS0FBSyxDQUFDLE9BQU8sR0FBRyxPQUFPLENBQUM7U0FDNUM7SUFDSCxDQUFDO0lBRUQ7OztPQUdHO0lBQ0gsb0JBQW9CLENBQUMsU0FBaUI7UUFDcEMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsWUFBWSxDQUFDLFNBQVMsRUFBRTtZQUNuQyxjQUFjLEVBQUU7Z0JBQ2QsQ0FBQyxFQUFFLElBQUksQ0FBQyxjQUFjLENBQUMsUUFBUSxDQUFDLENBQUMsR0FBRyxDQUFDO2dCQUNyQyxDQUFDLEVBQUUsSUFBSSxDQUFDLGNBQWMsQ0FBQyxRQUFRLENBQUMsQ0FBQyxHQUFHLENBQUM7Z0JBQ3JDLENBQUMsRUFBRSxJQUFJLENBQUMsY0FBYyxDQUFDLFFBQVEsQ0FBQyxDQUFDLEdBQUcsQ0FBQzthQUN0QztZQUNELFVBQVUsRUFBRTtnQkFDVixDQUFDLEVBQUUsSUFBSSxDQUFDLGNBQWMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxHQUFHLEdBQUc7Z0JBQ3JDLENBQUMsRUFBRSxJQUFJLENBQUMsY0FBYyxDQUFDLE1BQU0sQ0FBQyxDQUFDLEdBQUcsR0FBRztnQkFDckMsQ0FBQyxFQUFFLElBQUksQ0FBQyxjQUFjLENBQUMsTUFBTSxDQUFDLENBQUMsR0FBRyxHQUFHO2FBQ3RDO1NBQ0YsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztJQUVEOzs7OztPQUtHO0lBQ0gsZUFBZSxDQUFDLElBQVMsRUFBRSxJQUFTO1FBQ2xDLE1BQU0sSUFBSSxHQUFHO1lBQ1gsQ0FBQyxFQUFFLElBQUksQ0FBQyxTQUFTLENBQUMsV0FBVztZQUM3QixDQUFDLEVBQUUsSUFBSSxDQUFDLFNBQVMsQ0FBQyxZQUFZO1NBQy9CLENBQUM7UUFDRixNQUFNLE9BQU8sR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLFVBQVUsQ0FBQyxhQUFhLENBQy9DLElBQUksRUFDSixJQUFJLENBQUMsVUFBVSxFQUNmLElBQUksQ0FDTCxDQUFDO1FBQ0YsTUFBTSxPQUFPLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxVQUFVLENBQUMsYUFBYSxDQUMvQyxJQUFJLEVBQ0osSUFBSSxDQUFDLFVBQVUsRUFDZixJQUFJLENBQ0wsQ0FBQztRQUNGLE9BQU8sSUFBSSxDQUFDLElBQUksQ0FDZCxDQUFDLE9BQU8sQ0FBQyxDQUFDLEdBQUcsT0FBTyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLE9BQU8sQ0FBQyxDQUFDLEdBQUcsT0FBTyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FDNUQsQ0FBQztJQUNKLENBQUM7SUFFRCxFQUFFO0lBQ0YsMENBQTBDO0lBQzFDLEVBQUU7SUFDRjs7O09BR0c7SUFDSCxLQUFLLENBQUMsa0JBQWtCLENBQUMsYUFBNEI7UUFDbkQsSUFBSSxDQUFDLElBQUksQ0FBQyxjQUFjO1lBQUUsT0FBTztRQUNqQyxJQUFJLENBQUMsaUJBQWlCLEdBQUcsTUFBTSxJQUFJLENBQUMsb0JBQW9CLENBQUMsYUFBYSxDQUFDLENBQUM7UUFDeEUsT0FBTyxDQUFDLEdBQUcsQ0FBQyxtQkFBbUIsRUFBRSxJQUFJLENBQUMsaUJBQWlCLENBQUMsQ0FBQztRQUN6RCxJQUFJLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLGlCQUFpQixFQUFFLGVBQWUsQ0FBQyxDQUFDO1FBQy9ELElBQUksQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLFdBQVcsQ0FBQyxJQUFJLENBQUMsaUJBQWlCLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDdEQsQ0FBQztJQUVEOzs7OztPQUtHO0lBQ0gsS0FBSyxDQUFDLG9CQUFvQixDQUN4QixhQUE0QjtRQUU1QixJQUFJLE9BQU8sQ0FBQztRQUNaLElBQUksQ0FBQyxJQUFJLENBQUMsR0FBRyxFQUFFO1lBQ2IsT0FBTyxJQUFJLENBQUM7U0FDYjtRQUNELElBQUk7WUFDRixPQUFPLEdBQUcsTUFBTSxJQUFJLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsYUFBYSxDQUFDLE9BQU8sRUFBRSxDQUFDLENBQUM7U0FDM0Q7UUFBQyxPQUFPLEtBQUssRUFBRTtZQUNkLE9BQU8sQ0FBQyxHQUFHLENBQ1Qsa0NBQWtDLEVBQ2xDLEtBQUssRUFDTCxhQUFhLENBQUMsT0FBTyxFQUFFLENBQ3hCLENBQUM7U0FDSDtRQUNELElBQUksT0FBTyxFQUFFO1lBQ1gsTUFBTSxXQUFXLEdBQUcsT0FBTyxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQy9CLGtFQUFrRTtZQUNsRSxJQUFJLENBQUMsWUFBWSxDQUFDLElBQUksQ0FBQyxXQUFXLENBQUMsQ0FBQztZQUNwQyxJQUFJLENBQUMsZUFBZSxDQUFDLEdBQUcsQ0FBQyxXQUFXLEVBQUUsYUFBYSxDQUFDLENBQUM7WUFDckQsT0FBTyxXQUFXLENBQUM7U0FDcEI7UUFDRCxPQUFPLElBQUksQ0FBQztJQUNkLENBQUM7SUFFRDs7T0FFRztJQUNILG9CQUFvQjtRQUNsQixJQUFJLENBQUMsa0JBQWtCLENBQUMsa0JBQWtCLENBQUMsT0FBTyxDQUFDLENBQUM7UUFDcEQsTUFBTSxPQUFPLEdBQUcsSUFBSSxDQUFDLFVBQVUsRUFBRSxDQUFDO1FBQ2xDLElBQUksT0FBTyxFQUFFO1lBQ1gsTUFBTSxZQUFZLEdBQUcsSUFBSSxDQUFDLGVBQWU7aUJBQ3RDLEdBQUcsQ0FBQyxPQUFPLENBQUM7aUJBQ1oscUJBQXFCLEVBQUUsQ0FBQztZQUMzQixJQUFJLENBQUMsZ0NBQWdDLENBQUMsWUFBWSxDQUFDLENBQUM7U0FDckQ7SUFDSCxDQUFDO0lBRUQ7Ozs7T0FJRztJQUNILEtBQUssQ0FBQyxzQkFBc0IsQ0FBQyxXQUFtQixFQUFFLFFBQWdCO1FBQ2hFLE1BQU0sSUFBSSxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsZUFBZSxDQUFDLFFBQVEsV0FBVyxFQUFFLEVBQUUsUUFBUSxDQUFDLENBQUM7UUFDdEUsSUFBSSxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsUUFBUSxDQUFDLFdBQVcsRUFBRSxRQUFRLFdBQVcsRUFBRSxDQUFDLENBQUM7SUFDNUQsQ0FBQztJQUVEOzs7O09BSUc7SUFDSCxLQUFLLENBQUMsc0JBQXNCLENBQUMsV0FBbUIsRUFBRSxRQUFnQjtRQUNoRSxJQUFJO1lBQ0YsSUFBSSxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsUUFBUSxDQUFDLFdBQVcsRUFBRSxRQUFRLENBQUMsQ0FBQztTQUM5QztRQUFDLE9BQU8sQ0FBQyxFQUFFO1lBQ1YsT0FBTyxDQUFDLEdBQUcsQ0FDVCxnQ0FBZ0MsRUFDaEMsUUFBUSxFQUNSLHFCQUFxQixDQUN0QixDQUFDO1NBQ0g7SUFDSCxDQUFDO0lBRUQ7Ozs7O09BS0c7SUFDSCxLQUFLLENBQUMsb0JBQW9CLENBQ3hCLFdBQW1CLEVBQ25CLGFBQTRCO1FBRTVCLElBQUksSUFBSSxDQUFDLFFBQVEsS0FBSyxRQUFRLENBQUMsS0FBSyxFQUFFO1lBQ3BDLE1BQU0sSUFBSSxHQUFHLGFBQWEsQ0FBQyxTQUFTLEVBQUUsQ0FBQztZQUN2QyxJQUFJLFFBQVEsR0FBRyxXQUFXLENBQUM7WUFDM0IsSUFBSSxJQUFJLENBQUMsU0FBUyxFQUFFO2dCQUNsQixRQUFRLEdBQUcsR0FBRyxRQUFRLFlBQVksQ0FBQzthQUNwQztpQkFBTTtnQkFDTCxRQUFRLEdBQUcsR0FBRyxRQUFRLGNBQWMsQ0FBQzthQUN0QztZQUNELElBQUksQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLFFBQVEsQ0FBQyxXQUFXLEVBQUUsUUFBUSxDQUFDLENBQUM7WUFDN0MsT0FBTztTQUNSO1FBQ0QsTUFBTSxhQUFhLEdBQUcsZUFBZSxDQUFDLGFBQWEsQ0FBQyxPQUFPLEVBQUUsQ0FBQyxDQUFDO1FBQy9ELElBQUksT0FBTyxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUMsU0FBUyxDQUFDLG1CQUFtQixDQUFDO1FBQ3hELElBQUksUUFBUSxHQUFHLFFBQVEsYUFBYSxFQUFFLENBQUM7UUFDdkMsTUFBTSxHQUFHLEdBQUcsYUFBYSxDQUFDLE1BQU0sRUFBRSxDQUFDO1FBQ25DLElBQUksR0FBRyxJQUFJLEdBQUcsQ0FBQyxPQUFPLEVBQUU7WUFDdEIsTUFBTSxPQUFPLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsT0FBTyxDQUFDLENBQUM7WUFDeEMsSUFBSSxhQUFhLENBQUMsT0FBTyxFQUFFLEtBQUssT0FBTyxDQUFDLElBQUksRUFBRTtnQkFDNUMsTUFBTSxPQUFPLEdBQUcsYUFBYSxDQUFDLFNBQVMsRUFBRSxDQUFDO2dCQUMxQyxJQUFJLE9BQU8sQ0FBQyxJQUFJLEtBQUssV0FBVyxDQUFDLGNBQWMsRUFBRTtvQkFDL0MsT0FBTyxDQUFDLEdBQUcsR0FBRyxJQUFJLENBQUMsVUFBVSxDQUFDLHlCQUF5QixDQUFDLE9BQU8sRUFBRSxHQUFHLENBQUMsQ0FBQztpQkFDdkU7YUFDRjtZQUNELElBQUksT0FBTyxDQUFDLEdBQUcsRUFBRTtnQkFDZixNQUFNLFVBQVUsR0FBRyxNQUFNLElBQUksQ0FBQyxVQUFVLENBQUMsc0JBQXNCLENBQzdELE9BQU8sQ0FBQyxHQUFHLENBQ1osQ0FBQztnQkFDRixJQUFJLFVBQVUsRUFBRTtvQkFDZCxJQUFJO3dCQUNGLFFBQVEsR0FBRyxRQUFRLGFBQWEsSUFBSSxXQUFXLElBQUksYUFBYSxDQUFDLGVBQWUsRUFBRSxDQUFDO3dCQUNuRixNQUFNLElBQUksQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLGVBQWUsQ0FBQyxRQUFRLEVBQUUsVUFBVSxDQUFDLENBQUM7d0JBQzNELGFBQWEsQ0FBQyxlQUFlLElBQUksQ0FBQyxDQUFDO3FCQUNwQztvQkFBQyxNQUFNO3dCQUNOLE9BQU8sQ0FBQyxHQUFHLENBQUMsb0JBQW9CLENBQUMsQ0FBQztxQkFDbkM7aUJBQ0Y7YUFDRjtZQUNELElBQUksT0FBTyxDQUFDLE9BQU8sRUFBRTtnQkFDbkIsT0FBTyxHQUFHLE9BQU8sQ0FBQyxPQUFPLENBQUM7YUFDM0I7U0FDRjtRQUNELElBQUk7WUFDRixJQUFJLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxRQUFRLENBQUMsV0FBVyxFQUFFLFFBQVEsQ0FBQyxDQUFDO1lBQzdDLElBQUksQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLFdBQVcsQ0FBQyxXQUFXLEVBQUUsT0FBTyxDQUFDLENBQUM7U0FDaEQ7UUFBQyxPQUFPLEtBQUssRUFBRTtZQUNkLE9BQU8sQ0FBQyxHQUFHLENBQUMsMkJBQTJCLEVBQUUsS0FBSyxDQUFDLENBQUM7U0FDakQ7SUFDSCxDQUFDO0lBRUQ7O09BRUc7SUFDSCxXQUFXO1FBQ1QsVUFBVSxDQUFDLEdBQUcsRUFBRTtZQUNkLE1BQU0sT0FBTyxHQUFHLElBQUksQ0FBQyxVQUFVLEVBQUUsQ0FBQztZQUNsQyxJQUFJLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBQ3hCLENBQUMsRUFBRSxJQUFJLENBQUMsQ0FBQztJQUNYLENBQUM7SUFFRDs7OztPQUlHO0lBQ0gsS0FBSyxDQUFDLE9BQU8sQ0FBQyxXQUFtQjtRQUMvQixJQUFJLFdBQVcsS0FBSyxFQUFFO1lBQUUsT0FBTztRQUMvQixJQUFJO1lBQ0YsSUFBSSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLENBQUM7WUFDakMsTUFBTSxJQUFJLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsU0FBUyxDQUNwQyxDQUFDLFlBQVksRUFBRSxFQUFFLENBQUMsWUFBWSxLQUFLLEVBQUUsQ0FDdEMsQ0FBQztZQUNGLE1BQU0sSUFBSSxDQUFDLEdBQUcsQ0FBQyxTQUFTLENBQUMsYUFBYSxDQUNwQyxXQUFXLEVBQ1gsSUFBSSxDQUFDLEdBQUcsQ0FBQyxTQUFTLENBQUMsVUFBVSxDQUFDLEdBQUcsQ0FDbEMsQ0FBQztTQUNIO1FBQUMsT0FBTyxLQUFLLEVBQUU7WUFDZCxPQUFPLENBQUMsR0FBRyxDQUFDLHdCQUF3QixFQUFFLEtBQUssQ0FBQyxDQUFDO1NBQzlDO0lBQ0gsQ0FBQztJQUVEOzs7OztPQUtHO0lBQ0gsS0FBSyxDQUFDLDhCQUE4QixDQUNsQyxXQUFtQixFQUNuQixTQUF1QixJQUFJLEVBQzNCLFVBQW1CLElBQUk7UUFFdkIsSUFBSSxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsYUFBYSxDQUN4QixXQUFXLEVBQ1gsSUFBSSxDQUFDLGVBQWUsQ0FBQyxHQUFHLENBQUMsV0FBVyxDQUFDLENBQUMsT0FBTyxFQUFFLENBQ2hELENBQUM7UUFDRixJQUFJLE1BQU0sSUFBSSxPQUFPLEVBQUU7WUFDckIsTUFBTSxJQUFJLENBQUMsZUFBZSxDQUFDLE9BQU8sRUFBRSxNQUFNLEVBQUUsV0FBVyxDQUFDLENBQUM7U0FDMUQ7UUFDRCxNQUFNLElBQUksQ0FBQyxvQkFBb0IsQ0FDN0IsV0FBVyxFQUNYLElBQUksQ0FBQyxlQUFlLENBQUMsR0FBRyxDQUFDLFdBQVcsQ0FBQyxDQUN0QyxDQUFDO0lBQ0osQ0FBQztJQUVEOzs7OztPQUtHO0lBQ0gsS0FBSyxDQUFDLDBCQUEwQixDQUM5QixXQUFtQixFQUNuQixNQUFXLEVBQ1gsT0FBZ0I7UUFFaEIsTUFBTSxJQUFJLENBQUMsZUFBZSxDQUFDLE9BQU8sRUFBRSxNQUFNLEVBQUUsV0FBVyxDQUFDLENBQUM7SUFDM0QsQ0FBQztJQUVEOzs7T0FHRztJQUNILHFCQUFxQixDQUFDLFdBQW1CO1FBQ3ZDLElBQUksQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxXQUFXLENBQUMsQ0FBQztRQUNqQyxJQUFJLENBQUMsZUFBZSxDQUFDLE1BQU0sQ0FBQyxXQUFXLENBQUMsQ0FBQztJQUMzQyxDQUFDO0lBRUQ7O09BRUc7SUFDSCxtQkFBbUI7UUFDakIsTUFBTSxXQUFXLEdBQUcsSUFBSSxDQUFDLFlBQVksQ0FBQyxHQUFHLEVBQUUsQ0FBQztRQUM1QyxJQUFJLFdBQVcsRUFBRTtZQUNmLElBQUksQ0FBQyxxQkFBcUIsQ0FBQyxXQUFXLENBQUMsQ0FBQztTQUN6QztJQUNILENBQUM7SUFFRDs7Ozs7OztPQU9HO0lBQ0gsS0FBSyxDQUFDLHNCQUFzQixDQUMxQixPQUFnQixFQUNoQixNQUFvQixFQUNwQixHQUFRO1FBRVIsOEJBQThCO1FBQzlCLE1BQU0sRUFBQyxHQUFHLEVBQUUsS0FBSyxFQUFDLEdBQUcsSUFBSSxDQUFDLG1CQUFtQixDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUMsQ0FBQztRQUN6RCxJQUFJLEdBQUcsRUFBRTtZQUNQLG9DQUFvQztZQUNwQyxPQUFPO1NBQ1I7UUFDRCxNQUFNLGFBQWEsR0FBa0IsSUFBSSxhQUFhLENBQUMsT0FBTyxDQUFDLENBQUM7UUFDaEUsYUFBYSxDQUFDLFNBQVMsQ0FBQyxNQUFNLEVBQUUsT0FBTyxDQUFDLENBQUM7UUFDekMsSUFBSSxHQUFHLENBQUMsVUFBVSxFQUFFO1lBQ2xCLGFBQWEsQ0FBQyxXQUFXLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQztTQUN2RDtRQUNELElBQUksR0FBRyxDQUFDLFFBQVEsRUFBRTtZQUNoQixNQUFNLFdBQVcsR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxRQUFRLENBQUMsQ0FBQztZQUM3QyxJQUFJLFdBQVcsQ0FBQyxNQUFNLEVBQUU7Z0JBQ3RCLGFBQWEsQ0FBQyxTQUFTLENBQUMsV0FBVyxDQUFDLE1BQU0sQ0FBQyxDQUFDO2FBQzdDO2lCQUFNO2dCQUNMLGFBQWEsQ0FBQyxTQUFTLENBQUMsRUFBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLElBQUksRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFDLENBQUMsQ0FBQzthQUNqRDtTQUNGO1FBQ0QsSUFBSSxHQUFHLENBQUMsaUJBQWlCLEVBQUU7WUFDekIsYUFBYSxDQUFDLFVBQVUsQ0FBQyxHQUFHLENBQUMsaUJBQWlCLENBQUMsQ0FBQztTQUNqRDtRQUNELGFBQWEsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUM7UUFFMUIsTUFBTSxZQUFZLEdBQUcsTUFBTSxJQUFJLENBQUMsb0JBQW9CLENBQUMsYUFBYSxDQUFDLENBQUM7UUFDcEUsSUFBSSxZQUFZLElBQUksSUFBSSxDQUFDLEdBQUcsRUFBRTtZQUM1QixNQUFNLElBQUksQ0FBQyxvQkFBb0IsQ0FBQyxZQUFZLEVBQUUsYUFBYSxDQUFDLENBQUM7WUFDN0QsTUFBTSxJQUFJLENBQUMsZUFBZSxDQUFDLE9BQU8sRUFBRSxNQUFNLEVBQUUsWUFBWSxDQUFDLENBQUM7U0FDM0Q7SUFDSCxDQUFDO0lBRUQ7Ozs7O09BS0c7SUFDSCxLQUFLLENBQUMsZUFBZSxDQUFDLE9BQWdCLEVBQUUsTUFBb0IsRUFBRSxLQUFhO1FBQ3pFLElBQUksSUFBSSxHQUFHLE1BQU0sSUFBSSxDQUFDLFVBQVUsQ0FBQyxlQUFlLENBQUMsT0FBTyxFQUFFLE1BQU0sQ0FBQyxDQUFDO1FBQ2xFLElBQUksSUFBSSxLQUFLLEVBQUUsSUFBSSxJQUFJLENBQUMsR0FBRyxFQUFFO1lBQzNCLE1BQU0sU0FBUyxHQUFHLElBQUksQ0FBQyxVQUFVLENBQUMsZUFBZSxDQUFDLE1BQU0sRUFBRSxPQUFPLENBQUMsQ0FBQztZQUNuRSxJQUFJLElBQUksR0FBRyxTQUFTLEVBQUUsQ0FBQztZQUN2QixrQ0FBa0M7WUFDbEMsTUFBTSxDQUFDLFNBQVMsRUFBRSxTQUFTLENBQUMsR0FBRyxNQUFNLElBQUksQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLGVBQWUsQ0FBQyxJQUFJLENBQUMsQ0FBQztZQUV4RSxxQ0FBcUM7WUFDckMsSUFBSSxZQUFZLEdBQUcsSUFBSSxDQUFDLGVBQWUsQ0FBQyxLQUFLLENBQUMsQ0FBQztZQUMvQyxJQUFJLFlBQVksRUFBRTtnQkFDaEIsSUFBSSxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLEtBQUssRUFBRSxZQUFZLENBQUMsQ0FBQzthQUMxQztZQUNELElBQUksQ0FBQyxlQUFlLENBQUMsS0FBSyxDQUFDLEdBQUcsU0FBUyxDQUFDO1lBRXhDLDhCQUE4QjtZQUM5QixJQUFJLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsS0FBSyxFQUFFLFNBQVMsQ0FBQyxDQUFDO1lBQ3RDLGdDQUFnQztZQUNoQyw2Q0FBNkM7WUFDN0MsSUFBSSxDQUFDLElBQUksQ0FBQyxjQUFjLEVBQUU7Z0JBQ3hCLElBQUksQ0FBQyxjQUFjLEdBQUcsSUFBSSxDQUFDO2dCQUMzQixNQUFNLFVBQVUsR0FBRyxDQUFDLFNBQWlCLEVBQUUsRUFBRTtvQkFDdkMsaURBQWlEO29CQUNqRCxJQUFJLENBQUMsVUFBVSxDQUFDLGtCQUFrQixDQUFDLFNBQVMsQ0FBQyxDQUFDO2dCQUNoRCxDQUFDLENBQUM7Z0JBRUYsTUFBTSxVQUFVLEdBQUcsQ0FBQyxjQUFzQixFQUFFLEVBQUU7b0JBQzVDLHNEQUFzRDtvQkFDdEQsSUFBSSxDQUFDLFVBQVUsQ0FBQyxrQkFBa0IsQ0FBQyxjQUFjLENBQUMsQ0FBQztnQkFDckQsQ0FBQyxDQUFDO2dCQUNGLE1BQU0sVUFBVSxHQUFHLENBQUMsR0FBVyxFQUFFLEVBQUU7b0JBQ2pDLElBQUksQ0FBQyxVQUFVLENBQUMsa0JBQWtCLENBQUMsR0FBRyxDQUFDLENBQUM7Z0JBQzFDLENBQUMsQ0FBQztnQkFDRixTQUFTLENBQUMsRUFBRSxDQUNWLFNBQVMsQ0FBQyxZQUFZLEVBQ3RCLElBQUksQ0FBQyxVQUFVLENBQUMsbUJBQW1CLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsQ0FDMUQsQ0FBQztnQkFDRixTQUFTLENBQUMsRUFBRSxDQUNWLFNBQVMsQ0FBQyxZQUFZLEVBQ3RCLElBQUksQ0FBQyxVQUFVLENBQUMsbUJBQW1CLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsQ0FDMUQsQ0FBQztnQkFDRixTQUFTLENBQUMsRUFBRSxDQUFDLFNBQVMsQ0FBQyxXQUFXLEVBQUUsVUFBVSxDQUFDLENBQUM7Z0JBQ2hELFNBQVMsQ0FBQyxFQUFFLENBQUMsU0FBUyxDQUFDLFdBQVcsRUFBRSxVQUFVLENBQUMsQ0FBQztnQkFDaEQsU0FBUyxDQUFDLEVBQUUsQ0FBQyxTQUFTLENBQUMsV0FBVyxFQUFFLFVBQVUsQ0FBQyxDQUFDO2dCQUNoRCxTQUFTLENBQUMsRUFBRSxDQUNWLFNBQVMsQ0FBQyxTQUFTLEVBQ25CLElBQUksQ0FBQyxVQUFVLENBQUMsZ0JBQWdCLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsQ0FDdkQsQ0FBQztnQkFDRixTQUFTLENBQUMsRUFBRSxDQUNWLFNBQVMsQ0FBQyxhQUFhLEVBQ3ZCLElBQUksQ0FBQyxVQUFVLENBQUMsb0JBQW9CLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsQ0FDM0QsQ0FBQzthQUNIO1NBQ0Y7YUFBTTtZQUNMLGlHQUFpRztZQUNqRyxNQUFNLEVBQUMsT0FBTyxFQUFFLGNBQWMsRUFBQyxHQUM3QixJQUFJLENBQUMsVUFBVSxDQUFDLHdCQUF3QixDQUFDLE1BQU0sQ0FBQyxDQUFDO1lBQ25ELElBQUksT0FBTyxFQUFFO2dCQUNYLHFCQUFxQjtnQkFDckIsTUFBTSxDQUFDLFlBQVksQ0FBQyxHQUFHLE1BQU0sSUFBSSxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsa0JBQWtCLENBQzFELE9BQU8sQ0FBQyxZQUFZLENBQ3JCLENBQUM7Z0JBQ0YsU0FBUztnQkFDVCxJQUFJLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsS0FBSyxFQUFFLFlBQVksQ0FBQyxDQUFDO2dCQUN6QyxJQUFJLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxhQUFhLENBQUMsS0FBSyxFQUFFO29CQUNoQyxLQUFLLEVBQUUsTUFBTSxDQUFDLEtBQUs7b0JBQ25CLFdBQVcsRUFBRSxjQUFjO2lCQUM1QixDQUFDLENBQUM7YUFDSjtTQUNGO0lBQ0gsQ0FBQztJQUVELEtBQUssQ0FBQyw0QkFBNEI7UUFDaEMsTUFBTSxJQUFJLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsR0FBRyxJQUFJLENBQUMsWUFBWSxDQUFDLENBQUM7UUFDaEQsSUFBSSxDQUFDLFlBQVksR0FBRyxFQUFFLENBQUM7UUFDdkIsSUFBSSxDQUFDLGVBQWUsQ0FBQyxLQUFLLEVBQUUsQ0FBQztJQUMvQixDQUFDO0lBRUQ7OztPQUdHO0lBQ0gsS0FBSyxDQUFDLHdCQUF3QixDQUFDLFNBQWlCO1FBQzlDLE1BQU0sV0FBVyxHQUFHLElBQUksQ0FBQyxtQkFBbUIsQ0FBQyxTQUFTLENBQUMsQ0FBQyxHQUFHLENBQUM7UUFDNUQsSUFBSSxXQUFXLEVBQUU7WUFDZixJQUFJO2dCQUNGLE1BQU0sSUFBSSxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLFdBQVcsQ0FBQyxDQUFDO2dCQUN2QyxJQUFJLENBQUMsZUFBZSxDQUFDLE1BQU0sQ0FBQyxXQUFXLENBQUMsQ0FBQztnQkFDekMsTUFBTSxLQUFLLEdBQUcsSUFBSSxDQUFDLFlBQVksQ0FBQyxPQUFPLENBQUMsV0FBVyxDQUFDLENBQUM7Z0JBQ3JELElBQUksQ0FBQyxZQUFZLENBQUMsTUFBTSxDQUFDLEtBQUssRUFBRSxDQUFDLENBQUMsQ0FBQzthQUNwQztZQUFDLE9BQU8sS0FBSyxFQUFFO2dCQUNkLE9BQU8sQ0FBQyxHQUFHLENBQUMsbUJBQW1CLEVBQUUsV0FBVyxFQUFFLEtBQUssQ0FBQyxDQUFDO2FBQ3REO1NBQ0Y7SUFDSCxDQUFDO0lBRUQ7OztPQUdHO0lBQ0gsS0FBSyxDQUFDLGNBQWMsQ0FBQyxJQUFZO1FBQy9CLElBQUksQ0FBQyxvQkFBb0IsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLENBQUMsS0FBSyxDQUFDLE9BQU8sR0FBRyxLQUFLLENBQUM7SUFDNUQsQ0FBQztJQUVELG1DQUFtQyxDQUFDLElBQVk7UUFDNUMsSUFBSSxHQUFHLEdBQUcsSUFBSSxDQUFDLG9CQUFvQixDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUM5QyxJQUFHLENBQUMsR0FBRyxFQUFDO1lBQ04sT0FBTyxDQUFDLEdBQUcsQ0FBQyxtQkFBbUIsQ0FBQyxDQUFDO1lBQ2pDLE9BQU8sSUFBSSxDQUFDO1NBQ2I7UUFDRCwwQ0FBMEM7UUFDMUMsSUFBRyxHQUFHLENBQUMsS0FBSyxDQUFDLElBQUksSUFBSSxJQUFJLEVBQUM7WUFDeEIsT0FBTyxDQUFDLEdBQUcsQ0FBQyxxQkFBcUIsQ0FBQyxDQUFDO1lBQ25DLEdBQUcsQ0FBQyxLQUFLLENBQUMsSUFBSSxHQUFHLElBQUksQ0FBQztTQUN2QjtJQUNMLENBQUM7SUFFRDs7OztPQUlHO0lBQ0gsS0FBSyxDQUFDLDZCQUE2QixDQUFDLE9BQWdCLEVBQUUsT0FBcUI7UUFDekUsTUFBTSxhQUFhLEdBQUcsSUFBSSxhQUFhLENBQUMsT0FBTyxDQUFDLENBQUM7UUFDakQsMENBQTBDO1FBQzFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsR0FBRyxPQUFPLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQztRQUNqQyxJQUFJLEdBQUcsSUFBSSxHQUFHLENBQUMsVUFBVSxFQUFFO1lBQ3pCLGFBQWEsQ0FBQyxXQUFXLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQztZQUN0RCxhQUFhLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMscUNBQXFDO1NBQ2pFO1FBQ0QsYUFBYSxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQ2hELGFBQWEsQ0FBQyxXQUFXLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxRQUFRLENBQUMsQ0FBQztRQUNwRCxhQUFhLENBQUMsU0FBUyxDQUFDLE9BQU8sRUFBRSxPQUFPLENBQUMsQ0FBQztRQUMxQyxJQUFJLENBQUMsaUJBQWlCLEdBQUcsTUFBTSxJQUFJLENBQUMsb0JBQW9CLENBQUMsYUFBYSxDQUFDLENBQUM7UUFDeEUsSUFBSSxDQUFDLGtCQUFrQixDQUFDLGtCQUFrQixDQUFDLFdBQVcsQ0FBQyxDQUFDO1FBQ3hELE1BQU0sSUFBSSxDQUFDLGtCQUFrQixDQUFDLGFBQWEsQ0FBQyxDQUFDO0lBQy9DLENBQUM7SUFFRDs7O09BR0c7SUFDSCxLQUFLLENBQUMsc0JBQXNCLENBQUMsT0FBZ0I7UUFDM0MsTUFBTSxhQUFhLEdBQUcsSUFBSSxhQUFhLENBQUMsT0FBTyxDQUFDLENBQUM7UUFDakQsYUFBYSxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQ2hELGFBQWEsQ0FBQyxXQUFXLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxRQUFRLENBQUMsQ0FBQztRQUNwRCxJQUFJLENBQUMsa0JBQWtCLENBQUMsa0JBQWtCLENBQUMsTUFBTSxDQUFDLENBQUM7UUFDbkQsTUFBTSxJQUFJLENBQUMsa0JBQWtCLENBQUMsYUFBYSxDQUFDLENBQUM7SUFDL0MsQ0FBQztJQUVEOztPQUVHO0lBQ0gscUJBQXFCO1FBQ25CLElBQUksQ0FBQyxtQkFBbUIsRUFBRSxDQUFDO1FBQzNCLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxrQkFBa0IsQ0FBQyxPQUFPLENBQUMsQ0FBQztJQUN0RCxDQUFDO0lBRUQsZUFBZSxDQUFDLFlBQTZCO1FBQzNDLElBQUksQ0FBQyxZQUFZLEdBQUcsWUFBWSxDQUFDO0lBQ25DLENBQUM7SUFFRCxlQUFlO1FBQ2IsT0FBTyxJQUFJLENBQUMsWUFBWSxDQUFDO0lBQzNCLENBQUM7SUFFRDs7O09BR0c7SUFDSCxnQ0FBZ0MsQ0FBQyxJQUF5QjtRQUN4RCxJQUFJLENBQUMsaUJBQWlCLENBQUMsYUFBYSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUNoRCxNQUFNLE9BQU8sR0FBRyxJQUFJLENBQUMsVUFBVSxFQUFFLENBQUM7UUFDbEMsUUFBUSxJQUFJLEVBQUU7WUFDWixLQUFLLG1CQUFtQixDQUFDLGFBQWE7Z0JBQ3BDLElBQUksQ0FBQyxXQUFXLEVBQUUsQ0FBQztnQkFDbkIsSUFBSSxDQUFDLE1BQU0sQ0FBQyxRQUFRLENBQUMsQ0FBQyxTQUFTLElBQUksQ0FBQyxjQUFjLFlBQVksQ0FBQyxDQUFDLENBQUM7Z0JBQ2pFLE1BQU07WUFDUixLQUFLLG1CQUFtQixDQUFDLFVBQVU7Z0JBQ2pDLElBQUksQ0FBQyxXQUFXLEVBQUUsQ0FBQztnQkFDbkIsSUFBSSxDQUFDLE1BQU0sQ0FBQyxRQUFRLENBQUMsQ0FBQyxTQUFTLElBQUksQ0FBQyxjQUFjLGFBQWEsQ0FBQyxDQUFDLENBQUM7Z0JBQ2xFLE1BQU07WUFDUixLQUFLLG1CQUFtQixDQUFDLFlBQVk7Z0JBQ25DLElBQUksQ0FBQyxXQUFXLEVBQUUsQ0FBQztnQkFDbkIsSUFBSSxDQUFDLE1BQU0sQ0FBQyxRQUFRLENBQUMsQ0FBQyxTQUFTLElBQUksQ0FBQyxjQUFjLGVBQWUsQ0FBQyxDQUFDLENBQUM7Z0JBQ3BFLE1BQU07WUFDUixLQUFLLG1CQUFtQixDQUFDLFFBQVE7Z0JBQy9CLElBQUksQ0FBQyxXQUFXLEVBQUUsQ0FBQztnQkFDbkIsSUFBSSxHQUFXLENBQUM7Z0JBQ2hCLElBQUksSUFBSSxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxFQUFFO29CQUNqQyxHQUFHLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsU0FBUyxDQUFDLENBQUMsRUFBRSxJQUFJLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQztpQkFDbEU7cUJBQU07b0JBQ0wsR0FBRyxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDO2lCQUN2QjtnQkFDRCxJQUFJLENBQUMsTUFBTSxDQUFDLFFBQVEsQ0FBQyxDQUFDLEdBQUcsR0FBRyxjQUFjLENBQUMsQ0FBQyxDQUFDO2dCQUM3QyxNQUFNO1lBQ1IsS0FBSyxtQkFBbUIsQ0FBQyxRQUFRO2dCQUMvQixJQUFJLENBQUMsV0FBVyxFQUFFLENBQUM7Z0JBQ25CLElBQUksQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDLENBQUMsU0FBUyxJQUFJLENBQUMsY0FBYyxjQUFjLENBQUMsRUFBRTtvQkFDakUsV0FBVyxFQUFFLEVBQUMsTUFBTSxFQUFFLElBQUksRUFBQztpQkFDNUIsQ0FBQyxDQUFDO2dCQUNILE1BQU07WUFDUixLQUFLLG1CQUFtQixDQUFDLFFBQVE7Z0JBQy9CLElBQUksQ0FBQyxXQUFXLEVBQUUsQ0FBQztnQkFDbkIsSUFBSSxDQUFDLE1BQU0sQ0FBQyxRQUFRLENBQUMsQ0FBQyxTQUFTLElBQUksQ0FBQyxjQUFjLFdBQVcsQ0FBQyxDQUFDLENBQUM7Z0JBQ2hFLE1BQU07WUFDUixLQUFLLG1CQUFtQixDQUFDLGlCQUFpQjtnQkFDeEMsSUFBSSxPQUFPLEVBQUU7b0JBQ1gsNkJBQTZCO29CQUM3QixJQUFJLENBQUMsTUFBTSxDQUFDLFFBQVEsQ0FDbEIsQ0FBQyxTQUFTLElBQUksQ0FBQyxjQUFjLGFBQWEsSUFBSSxDQUFDLFlBQVksQ0FBQyxFQUFFLEVBQUUsQ0FBQyxFQUNqRSxFQUFDLFdBQVcsRUFBRSxFQUFDLFdBQVcsRUFBRSxJQUFJLEVBQUMsRUFBQyxDQUNuQyxDQUFDO2lCQUNIO2dCQUNELE1BQU07WUFDUixLQUFLLG1CQUFtQixDQUFDLGVBQWU7Z0JBQ3RDLElBQUksT0FBTyxFQUFFO29CQUNYLElBQUksQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUNsQjt3QkFDRSxTQUFTLElBQUksQ0FBQyxjQUFjLFdBQzFCLElBQUksQ0FBQyxlQUFlLENBQUMsR0FBRyxDQUFDLE9BQU8sQ0FBQyxDQUFDLFNBQ3BDLEVBQUU7cUJBQ0gsRUFDRCxFQUFDLFdBQVcsRUFBRSxFQUFDLFdBQVcsRUFBRSxJQUFJLEVBQUMsRUFBQyxDQUNuQyxDQUFDO2lCQUNIO2dCQUNELE1BQU07WUFDUixLQUFLLG1CQUFtQixDQUFDLGtCQUFrQjtnQkFDekMsSUFBSSxPQUFPLEVBQUU7b0JBQ1gsSUFBSSxDQUFDLE1BQU0sQ0FBQyxRQUFRLENBQ2xCO3dCQUNFLFNBQVMsSUFBSSxDQUFDLGNBQWMsVUFDMUIsSUFBSSxDQUFDLGVBQWUsQ0FBQyxHQUFHLENBQUMsT0FBTyxDQUFDLENBQUMsU0FDcEMsRUFBRTtxQkFDSCxFQUNELEVBQUMsV0FBVyxFQUFFLEVBQUMsV0FBVyxFQUFFLElBQUksRUFBQyxFQUFDLENBQ25DLENBQUM7aUJBQ0g7Z0JBQ0QsTUFBTTtZQUNSLEtBQUssbUJBQW1CLENBQUMsYUFBYTtnQkFDcEMsSUFBSSxPQUFPLEVBQUU7b0JBQ1gsSUFBSSxDQUFDLE1BQU0sQ0FBQyxRQUFRLENBQUMsRUFBRSxFQUFFO3dCQUN2QixVQUFVLEVBQUUsSUFBSSxDQUFDLFdBQVc7d0JBQzVCLFdBQVcsRUFBRSxFQUFDLFdBQVcsRUFBRSxJQUFJLEVBQUMsRUFBRSxtQkFBbUIsRUFBRyxPQUFPO3FCQUNoRSxDQUFDLENBQUM7aUJBQ0o7Z0JBQ0QsTUFBTTtZQUNSLEtBQUssbUJBQW1CLENBQUMsYUFBYTtnQkFDcEMsSUFBSSxPQUFPLEVBQUU7b0JBQ1gsSUFBSSxDQUFDLE1BQU0sQ0FBQyxRQUFRLENBQUMsRUFBRSxFQUFFO3dCQUN2QixVQUFVLEVBQUUsSUFBSSxDQUFDLFdBQVc7d0JBQzVCLFdBQVcsRUFBRSxFQUFDLFdBQVcsRUFBRSxJQUFJLEVBQUMsRUFBRSxtQkFBbUIsRUFBRyxPQUFPO3FCQUNoRSxDQUFDLENBQUM7aUJBQ0o7Z0JBQ0QsTUFBTTtTQUNUO0lBQ0gsQ0FBQztJQUVEOzs7Ozs7T0FNRztJQUNILEtBQUssQ0FBQyxvQkFBb0IsQ0FDeEIsV0FBbUIsRUFDbkIsTUFBb0IsRUFDcEIsT0FBZ0IsRUFDaEIsTUFBa0IsSUFBSTtRQUV0QixJQUFJLENBQUMsZUFBZSxDQUFDLEdBQUcsQ0FBQyxXQUFXLENBQUMsQ0FBQyxTQUFTLENBQUMsTUFBTSxFQUFFLE9BQU8sQ0FBQyxDQUFDO1FBQ2pFLElBQUksR0FBRyxFQUFFO1lBQ1AsSUFBSSxDQUFDLGVBQWUsQ0FBQyxHQUFHLENBQUMsV0FBVyxDQUFDLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDO1NBQ25EO1FBQ0QsSUFBSSxDQUFDLGVBQWUsQ0FBQyxHQUFHLENBQUMsV0FBVyxDQUFDLENBQUMsU0FBUyxHQUFHLE1BQU0sQ0FBQyxFQUFFLENBQUM7UUFDNUQsSUFBSTtZQUNGLE1BQU0sSUFBSSxDQUFDLDhCQUE4QixDQUFDLFdBQVcsRUFBRSxNQUFNLEVBQUUsT0FBTyxDQUFDLENBQUM7WUFDeEUsaUJBQWlCO1lBQ2pCLE1BQU0sSUFBSSxDQUFDLDZCQUE2QixDQUN0QyxXQUFXLEVBQ1gsTUFBTSxFQUNOLE9BQU8sRUFDUCxHQUFHLENBQ0osQ0FBQztTQUNIO1FBQUMsT0FBTyxDQUFDLEVBQUU7WUFDVixPQUFPLENBQUMsR0FBRyxDQUFDLGtDQUFrQyxDQUFDLEVBQUUsQ0FBQyxDQUFDO1NBQ3BEO0lBQ0gsQ0FBQztJQUVELEtBQUssQ0FBQyw2QkFBNkIsQ0FDakMsV0FBbUIsRUFDbkIsTUFBb0IsRUFDcEIsT0FBZ0IsRUFDaEIsTUFBa0IsSUFBSTtRQUV0QixNQUFNLGFBQWEsR0FBRyxNQUFNLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxFQUFFLEtBQUssR0FBRyxDQUFDLEVBQUUsQ0FBQyxDQUFDO1FBQzFFLE1BQU0sQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLGFBQWEsQ0FBQyxHQUFHLEdBQUcsQ0FBQztRQUN2QyxNQUFNLEVBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUMsR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxVQUFVLENBQUMsQ0FBQztRQUM3QyxNQUFNLFdBQVcsR0FBRztZQUNsQixjQUFjLEVBQUU7Z0JBQ2QsQ0FBQyxFQUFFLENBQUM7Z0JBQ0osQ0FBQyxFQUFFLENBQUM7Z0JBQ0osQ0FBQyxFQUFFLENBQUM7YUFDTDtZQUNELFVBQVUsRUFBRTtnQkFDVix3RUFBd0U7Z0JBQ3hFLENBQUMsRUFBRSxDQUFDO2dCQUNKLENBQUMsRUFBRSxHQUFHO2dCQUNOLENBQUMsRUFBRSxDQUFDO2FBQ0w7U0FDRixDQUFDO1FBQ0YsSUFBSSxDQUFDLEdBQUcsQ0FBQyxTQUFTLENBQUMsWUFBWSxDQUFDLFdBQVcsRUFBRSxXQUFXLENBQUMsQ0FBQztRQUMxRCxJQUFJLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxZQUFZLENBQUMsV0FBVyxFQUFFLFdBQVcsQ0FBQyxDQUFDO1FBQ3BELElBQUksQ0FBQyxlQUFlO2FBQ2pCLEdBQUcsQ0FBQyxXQUFXLENBQUM7YUFDaEIsV0FBVyxDQUFDLFdBQVcsQ0FBQyxjQUFjLENBQUMsQ0FBQztRQUUzQyxLQUFLLElBQUksS0FBSyxJQUFJLElBQUksQ0FBQyxZQUFZLEVBQUU7WUFDbkMsTUFBTSxVQUFVLEdBQUcsSUFBSSxDQUFDLGVBQWUsQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLENBQUM7WUFDbkQsSUFBSSxDQUFDLFVBQVUsRUFBRTtnQkFDZixTQUFTO2FBQ1Y7WUFDRCxJQUFJLFVBQVUsQ0FBQyxTQUFTLEtBQUssTUFBTSxDQUFDLEVBQUUsSUFBSSxLQUFLLEtBQUssV0FBVyxFQUFFO2dCQUMvRCxJQUFJLENBQUMsZUFBZSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQztnQkFDbkMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDO2dCQUMzQixJQUFJLENBQUMsR0FBRyxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUM7Z0JBQ2pDLE1BQU07YUFDUDtTQUNGO0lBQ0gsQ0FBQztJQUVEOzs7O09BSUc7SUFDSSxtQkFBbUIsQ0FBQyxTQUFpQjtRQUkxQyxJQUFJLEtBQUssR0FBRyxJQUFJLENBQUM7UUFDakIsSUFBSSxPQUFPLEdBQUcsSUFBSSxDQUFDO1FBQ25CLEtBQUssSUFBSSxDQUFDLFdBQVcsRUFBRSxhQUFhLENBQUMsSUFBSSxJQUFJLENBQUMsZUFBZSxFQUFFO1lBQzdELElBQUksYUFBYSxDQUFDLFNBQVMsS0FBSyxTQUFTLEVBQUU7Z0JBQ3pDLEtBQUssR0FBRyxXQUFXLENBQUM7Z0JBQ3BCLE1BQU0sS0FBSyxHQUFHLGFBQWEsQ0FBQyxVQUFVLEVBQUUsQ0FBQztnQkFDekMsSUFBSSxLQUFLLElBQUksSUFBSSxDQUFDLE1BQU0sSUFBSSxJQUFJLENBQUMsTUFBTSxDQUFDLFFBQVEsQ0FBQyxLQUFLLENBQUMsRUFBRTtvQkFDdkQsT0FBTyxHQUFHLEtBQUssQ0FBQztpQkFDakI7YUFDRjtTQUNGO1FBQ0QsT0FBTyxFQUFDLEdBQUcsRUFBRSxLQUFLLEVBQUUsS0FBSyxFQUFFLE9BQU8sRUFBQyxDQUFDO0lBQ3RDLENBQUM7SUFFRDs7O09BR0c7SUFDSCxVQUFVO1FBQ1IsSUFBSSxJQUFJLENBQUMsaUJBQWlCLEVBQUU7WUFDMUIsT0FBTyxJQUFJLENBQUMsaUJBQWlCLENBQUM7U0FDL0I7YUFBTTtZQUNMLE9BQU8sSUFBSSxDQUFDLFlBQVksQ0FBQyxNQUFNLEtBQUssQ0FBQztnQkFDbkMsQ0FBQyxDQUFDLElBQUk7Z0JBQ04sQ0FBQyxDQUFDLElBQUksQ0FBQyxZQUFZLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFDLENBQUM7U0FDckQ7SUFDSCxDQUFDO0lBRUQ7Ozs7T0FJRztJQUNILDRCQUE0QixDQUFDLFdBQW1CO1FBQzlDLElBQUk7WUFDRixPQUFPLElBQUksQ0FBQyxlQUFlLENBQUMsR0FBRyxDQUFDLFdBQVcsQ0FBQyxDQUFDO1NBQzlDO1FBQUMsTUFBTTtZQUNOLE9BQU8sQ0FBQyxHQUFHLENBQUMsdUNBQXVDLEVBQUUsV0FBVyxDQUFDLENBQUM7U0FDbkU7UUFDRCxPQUFPLElBQUksQ0FBQztJQUNkLENBQUM7SUFFRCxFQUFFO0lBQ0YsNkRBQTZEO0lBQzdELEVBQUU7SUFDRixLQUFLLENBQUMsd0JBQXdCO1FBQzVCLElBQUksSUFBSSxDQUFDLGdCQUFnQixJQUFJLElBQUksQ0FBQyxpQkFBaUIsRUFBRTtZQUNuRCxPQUFPLENBQUMsR0FBRyxDQUFDLDhDQUE4QyxDQUFDLENBQUM7WUFDNUQsT0FBTztTQUNSO1FBQ0QsSUFBSTtZQUNGLE1BQU0sSUFBSSxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLGdCQUFnQixDQUFDLENBQUM7U0FDOUM7UUFBQyxPQUFPLENBQUMsRUFBRTtZQUNWLE9BQU8sQ0FBQyxHQUFHLENBQUMsd0JBQXdCLEVBQUUsQ0FBQyxDQUFDLENBQUM7U0FDMUM7SUFDSCxDQUFDO0lBRUQsMEJBQTBCO1FBQ3hCLElBQUksQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxhQUFhLENBQUMsQ0FBQztJQUN0QyxDQUFDO0lBRUQsbUJBQW1CO1FBQ2pCLElBQUk7WUFDRixJQUFJLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxPQUFPLEVBQUUsQ0FBQztTQUMxQjtRQUFDLE9BQU8sQ0FBQyxFQUFFO1lBQ1YsT0FBTyxDQUFDLEdBQUcsQ0FBQyx3QkFBd0IsRUFBRSxDQUFDLENBQUMsQ0FBQztTQUMxQztJQUNILENBQUM7SUFFRCxLQUFLLENBQUMsd0JBQXdCO1FBQzVCLFVBQVUsQ0FBQyxLQUFLLElBQUksRUFBRTtZQUNwQixvRkFBb0Y7WUFDcEYsSUFBSSxJQUFJLENBQUMsZ0JBQWdCLElBQUksSUFBSSxDQUFDLGlCQUFpQixFQUFFO2dCQUNuRCxPQUFPLENBQUMsR0FBRyxDQUFDLDhDQUE4QyxDQUFDLENBQUM7Z0JBQzVELE9BQU87YUFDUjtZQUNELElBQUk7Z0JBQ0YsTUFBTSxJQUFJLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsZ0JBQWdCLENBQUMsQ0FBQzthQUM5QztZQUFDLE9BQU8sQ0FBQyxFQUFFO2dCQUNWLE9BQU8sQ0FBQyxHQUFHLENBQUMsd0JBQXdCLEVBQUUsQ0FBQyxDQUFDLENBQUM7YUFDMUM7UUFDSCxDQUFDLEVBQUUsSUFBSSxDQUFDLENBQUM7SUFDWCxDQUFDO0lBRUQscUJBQXFCO1FBQ25CLE1BQU0sUUFBUSxHQUFHLENBQUMsSUFBSSxDQUFDLGVBQWUsQ0FBQztRQUN2QyxJQUFJLENBQUMsR0FBRyxDQUFDLFlBQVksQ0FBQyxVQUFVLENBQUMsUUFBUSxDQUFDLENBQUMsSUFBSSxDQUFDLEdBQUcsRUFBRTtZQUNuRCxPQUFPLENBQUMsR0FBRyxDQUNULDJCQUEyQixRQUFRLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsVUFBVSxFQUFFLENBQy9ELENBQUM7UUFDSixDQUFDLENBQUMsQ0FBQztJQUNMLENBQUM7SUFFRCw0QkFBNEI7UUFDMUIsSUFBSSxJQUFJLENBQUMsZUFBZSxFQUFFO1lBQ3hCLElBQUksQ0FBQyxxQkFBcUIsRUFBRSxDQUFDO1NBQzlCO0lBQ0gsQ0FBQztJQUVELEtBQUssQ0FBQyxrQkFBa0IsQ0FDdEIsU0FBaUIsRUFDakIsMEJBQWtDLElBQUk7UUFFdEMsSUFBSSxDQUFDLElBQUksQ0FBQyxNQUFNLEVBQUU7WUFDaEIsT0FBTyxDQUFDLEdBQUcsQ0FBQywwQkFBMEIsQ0FBQyxDQUFDO1lBQ3hDLE9BQU87U0FDUjtRQUNELDRCQUE0QjtRQUM1QixrREFBa0Q7UUFDbEQsSUFBSSxlQUFlLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQ3BDLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FBQyxLQUFLLENBQUMsUUFBUSxLQUFLLHVCQUF1QixDQUN0RCxDQUFDO1FBQ0YsSUFBSSxDQUFDLGVBQWUsRUFBRTtZQUNwQixlQUFlLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQ2hDLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FBQyxTQUFTLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsSUFBSSxLQUFLLENBQUMsSUFBSSxJQUFJLEVBQUUsQ0FDOUQsQ0FBQztTQUNIO1FBQ0QsSUFBSSxDQUFDLGVBQWUsRUFBRTtZQUNwQixlQUFlLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUMzQyxTQUFTLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUMsQ0FDN0IsQ0FBQztTQUNIO1FBQ0QsK0JBQStCO1FBQy9CLElBQUksZUFBZSxFQUFFO1lBQ25CLElBQUksS0FBSyxHQUFHLElBQUksQ0FBQztZQUNqQixPQUFPLEtBQUssRUFBRTtnQkFDWixJQUFJO29CQUNGLE1BQU0sVUFBVSxHQUFHLE1BQU0sSUFBSSxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUM1QyxlQUFlLENBQUMsUUFBUSxDQUN6QixDQUFDO29CQUNGLGtEQUFrRDtvQkFDbEQsS0FBSyxHQUFHLEtBQUssQ0FBQztpQkFDZjtnQkFBQyxPQUFPLEtBQUssRUFBRTtvQkFDZCxPQUFPLENBQUMsR0FBRyxDQUFDLHNCQUFzQixFQUFFLEtBQUssQ0FBQyxDQUFDO29CQUMzQyxNQUFNLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQztpQkFDakI7YUFDRjtTQUNGO2FBQU07WUFDTCxPQUFPLENBQUMsSUFBSSxDQUFDLHNDQUFzQyxDQUFDLENBQUM7U0FDdEQ7SUFDSCxDQUFDO0lBRUQsS0FBSyxDQUFDLGtCQUFrQixDQUN0QixLQUFhLEVBQ2IsV0FBcUMsSUFBSTtRQUV6QyxJQUFJLElBQUksQ0FBQyxlQUFlLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQyxFQUFFO1lBQ3hDLE9BQU8sQ0FBQyxHQUFHLENBQUMseUNBQXlDLENBQUMsQ0FBQztZQUN2RCxPQUFPO1NBQ1I7UUFDRCxvRUFBb0U7UUFDcEUsVUFBVSxDQUFDLEtBQUssSUFBSSxFQUFFO1lBQ3BCLElBQUksSUFBSSxDQUFDLGdCQUFnQixJQUFJLElBQUksQ0FBQyxpQkFBaUIsRUFBRTtnQkFDbkQsT0FBTyxDQUFDLEdBQUcsQ0FBQyxtQ0FBbUMsQ0FBQyxDQUFDO2dCQUNqRCxPQUFPO2FBQ1I7WUFDRCxJQUFJO2dCQUNGLElBQUksQ0FBQyxpQkFBaUIsR0FBRyxJQUFJLENBQUM7Z0JBQzlCLE1BQU0sSUFBSSxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLEtBQUssRUFBRTtvQkFDakMsVUFBVSxFQUFFLG9CQUFvQjtvQkFDaEMsY0FBYyxFQUFFLElBQUk7aUJBQ3JCLENBQUMsQ0FBQzthQUNKO1lBQUMsT0FBTyxLQUFLLEVBQUU7Z0JBQ2QsSUFBSSxDQUFDLGlCQUFpQixHQUFHLEtBQUssQ0FBQztnQkFDL0IsT0FBTyxDQUFDLEdBQUcsQ0FBQyxzQkFBc0IsRUFBRSxLQUFLLENBQUMsQ0FBQzthQUM1QztZQUNELElBQUksUUFBUSxFQUFFO2dCQUNaLE1BQU0sSUFBSSxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsV0FBVyxDQUFDLFFBQVEsRUFBRSxFQUFDLEtBQUssRUFBRSxHQUFHLEVBQUMsQ0FBQyxDQUFDLENBQUMsOEJBQThCO2FBQzFGO1FBQ0gsQ0FBQyxFQUFFLElBQUksQ0FBQyxDQUFDO0lBQ1gsQ0FBQztJQUVELGVBQWU7UUFDYixJQUFJLElBQUksQ0FBQyxVQUFVLEVBQUU7WUFDbkIsT0FBTyxJQUFJLENBQUMsVUFBVSxDQUFDLEtBQUssQ0FBQztTQUM5QjtRQUNELE9BQU8sSUFBSSxDQUFDO0lBQ2QsQ0FBQztJQUVELHdCQUF3QjtRQUt0QixJQUFJLElBQUksQ0FBQyxVQUFVLEVBQUU7WUFDbkIsT0FBTyxJQUFJLENBQUMsVUFBVSxDQUFDO1NBQ3hCO1FBQ0QsT0FBTyxJQUFJLENBQUM7SUFDZCxDQUFDO0lBRUQsa0JBQWtCLENBQUMsZUFBdUI7UUFDeEMsSUFBSSxDQUFDLGVBQWUsR0FBRyxlQUFlLENBQUM7SUFDekMsQ0FBQztJQUVELGtCQUFrQjtRQUNoQixPQUFPLElBQUksQ0FBQyxlQUFlLENBQUM7SUFDOUIsQ0FBQztJQUVEOztPQUVHO0lBQ0gsS0FBSyxDQUFDLFFBQVE7UUFDWixPQUFPLENBQUMsR0FBRyxDQUFDLGlCQUFpQixDQUFDLENBQUM7UUFDL0IsSUFBSSxDQUFDLDRCQUE0QixFQUFFLENBQUM7UUFDcEMsSUFBSSxDQUFDLE1BQU0sR0FBRyxJQUFJLENBQUM7UUFDbkIsSUFBSSxDQUFDLE1BQU0sR0FBRyxJQUFJLENBQUM7UUFDbkIsSUFBSSxDQUFDLEdBQUcsR0FBRyxJQUFJLENBQUM7UUFDaEIsYUFBYSxDQUFDLElBQUksQ0FBQyxZQUFZLENBQUMsQ0FBQztRQUNqQyxJQUFJLENBQUMsZUFBZSxHQUFHLEVBQUUsQ0FBQztRQUMxQixJQUFJLENBQUMsY0FBYyxHQUFHLEtBQUssQ0FBQztRQUM1Qix1QkFBdUI7UUFDdkIsSUFBSSxDQUFDLGFBQWEsQ0FBQyxtQkFBbUIsQ0FDcEMsT0FBTyxFQUNQLElBQUksQ0FBQyx1QkFBdUIsQ0FDN0IsQ0FBQztRQUNGLElBQUksQ0FBQyxhQUFhLENBQUMsbUJBQW1CLENBQ3BDLGFBQWEsRUFDYixJQUFJLENBQUMsd0JBQXdCLENBQzlCLENBQUM7UUFFRix3QkFBd0I7UUFDeEIsSUFBSSxJQUFJLENBQUMsdUJBQXVCLEVBQUU7WUFDaEMsSUFBSSxDQUFDLHVCQUF1QixDQUFDLG1CQUFtQixDQUM5QyxVQUFVLEVBQ1YsSUFBSSxDQUFDLHlCQUF5QixDQUMvQixDQUFDO1NBQ0g7UUFDRCxzQkFBc0I7UUFDdEIsSUFBSSxDQUFDLENBQUMsSUFBSSxDQUFDLHVCQUF1QjtZQUNoQyxDQUFDLFFBQVEsQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLENBQUMsSUFBSSxRQUFRLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsV0FBVyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsRUFBRTtZQUN0RyxhQUFhLENBQUMsSUFBSSxDQUFDLDZCQUE2QixDQUFDLENBQUM7U0FDbkQ7SUFDSCxDQUFDO0lBRUQsS0FBSyxDQUFDLHFCQUFxQixDQUFDLGVBQXlCO1FBQ25ELElBQUksQ0FBQyxlQUFlLEdBQUcsQ0FBQyxHQUFHLGVBQWUsQ0FBQyxDQUFDO1FBQzVDLElBQUksT0FBTyxHQUFHLENBQUMsQ0FBQztRQUNoQixNQUFNLE9BQU8sQ0FBQyxHQUFHLENBQ2YsZUFBZSxDQUFDLEdBQUcsQ0FBQyxLQUFLLEVBQUUsS0FBSyxFQUFFLEVBQUU7WUFDbEMsSUFBSTtnQkFDRixNQUFNLElBQUksQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsQ0FBQztnQkFDcEMsT0FBTyxJQUFJLENBQUMsQ0FBQzthQUNkO1lBQUMsT0FBTyxLQUFLLEVBQUU7Z0JBQ2QsT0FBTyxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsQ0FBQzthQUNwQjtRQUNILENBQUMsQ0FBQyxDQUNILENBQUM7UUFDRixPQUFPLENBQUMsR0FBRyxDQUFDLGlCQUFpQixFQUFFLE9BQU8sQ0FBQyxDQUFDO0lBQzFDLENBQUM7SUFFRCxFQUFFO0lBQ0YscURBQXFEO0lBQ3JELEVBQUU7SUFDRixLQUFLLENBQUMsa0JBQWtCO1FBQ3RCLE9BQU8sSUFBSSxPQUFPLENBQUMsS0FBSyxFQUFFLE9BQU8sRUFBRSxFQUFFO1lBQ25DLElBQUksQ0FBQyxXQUFXLENBQUMsR0FBRyxNQUFNLElBQUksQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLGFBQWEsQ0FBQyxDQUFDLENBQUMsQ0FBQztZQUUxRCxJQUFJLElBQUksR0FBRyxXQUFXLENBQUMsT0FBTyxFQUFFLENBQUM7WUFFakMsc0JBQXNCO1lBQ3RCLElBQUksQ0FBQyxZQUFZLENBQUMsV0FBVyxDQUFDLENBQUM7WUFDL0IsaUNBQWlDO1lBQ2pDOzZDQUNpQztZQUNqQyxJQUFJLENBQUMsS0FBSyxFQUFFLENBQUM7WUFFYixNQUFNLFdBQVcsR0FBRyxXQUFXLENBQUMsT0FBTyxFQUFFLENBQUM7WUFDMUMsSUFBSSxDQUFDLGFBQWEsR0FBRyxXQUFXLENBQUMsWUFBWSxDQUFDLHNCQUFzQixDQUFDLENBQUM7WUFDdEUsV0FBVyxDQUFDLEtBQUssRUFBRSxDQUFDO1lBRXBCLDRCQUE0QjtZQUU1QixPQUFPLEVBQUUsQ0FBQztRQUNaLENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztJQUVELEtBQUssQ0FBQyxXQUFXLENBQ2YsR0FBYyxFQUNkLElBQTZCO1FBRTdCLE9BQU8sSUFBSSxPQUFPLENBQUMsS0FBSyxFQUFFLE9BQU8sRUFBRSxFQUFFO1lBQ25DLE1BQU0sQ0FBQyxXQUFXLENBQUMsR0FBRyxNQUFNLElBQUksQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLGFBQWEsQ0FBQyxDQUFDLENBQUMsQ0FBQztZQUU1RCxrRUFBa0U7WUFDbEUsaUJBQWlCO1lBQ2pCLGlCQUFpQjtZQUNqQixRQUFRO1lBQ1IsSUFBSSx3QkFBd0IsR0FBRyxLQUFLLENBQUM7WUFDckMsSUFBSSxnQkFBZ0IsR0FBRyxLQUFLLENBQUM7WUFDN0IsSUFBSSw2QkFBNkIsR0FBRyxLQUFLLENBQUM7WUFDMUMsSUFBSSxnQkFBZ0IsR0FBRyxLQUFLLENBQUM7WUFFN0I7O2VBRUc7WUFDSCxJQUFJLEdBQUcsQ0FBQyxNQUFNLEtBQUssaUJBQWlCLEVBQUU7Z0JBQ3BDLHdCQUF3QixHQUFHLElBQUksQ0FBQzthQUNqQztZQUNELElBQUksR0FBRyxDQUFDLE1BQU0sS0FBSyxpQkFBaUIsRUFBRTtnQkFDcEMsZ0JBQWdCLEdBQUcsSUFBSSxDQUFDO2FBQ3pCO1lBQ0QsSUFBSSxHQUFHLENBQUMsTUFBTSxLQUFLLE9BQU8sRUFBRTtnQkFDMUIsNkJBQTZCLEdBQUcsSUFBSSxDQUFDO2FBQ3RDO1lBQ0QsSUFBRyxHQUFHLENBQUMsTUFBTSxLQUFLLFNBQVMsRUFBRTtnQkFDM0IsZ0JBQWdCLEdBQUcsSUFBSSxDQUFDO2FBQ3pCO1lBRUQsTUFBTSxTQUFTLEdBQUcsV0FBVyxDQUFDLE9BQU8sRUFBRSxDQUFDO1lBQ3hDLElBQUksU0FBUyxHQUFHLElBQUksQ0FBQztZQUNyQixNQUFNLE9BQU8sR0FBRztnQkFDZCxHQUFHLEVBQUUsNkJBQTZCLEdBQUcsQ0FBQyxNQUFNLEdBQzFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxHQUFHLEdBQUcsR0FBRyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLE1BQzFELEVBQUU7Z0JBQ0Ysc0dBQXNHO2dCQUN0RyxhQUFhLEVBQUUsRUFBQyxHQUFHLEVBQUUsQ0FBQyxFQUFFLEdBQUcsRUFBRSxDQUFDLEVBQUUsR0FBRyxFQUFFLENBQUMsRUFBQztnQkFDdkMsc0dBQXNHO2dCQUN0RyxhQUFhLEVBQUUsRUFBQyxHQUFHLEVBQUUsQ0FBQyxFQUFFLEdBQUcsRUFBRSxDQUFDLEVBQUUsR0FBRyxFQUFFLENBQUMsRUFBQztnQkFDdkMsT0FBTyxFQUFFLElBQUk7Z0JBQ2IsZUFBZSxFQUFFLElBQUk7YUFDdEIsQ0FBQztZQUdGLFFBQVEsR0FBRyxDQUFDLE1BQU0sRUFBRTtnQkFDbEIsS0FBSyxNQUFNLENBQUM7Z0JBQ1osS0FBSyxLQUFLO29CQUNSLFNBQVMsR0FBRyxTQUFTLENBQUMsWUFBWSxDQUFDLGNBQWMsRUFBRSxPQUFPLENBQUMsQ0FBQztvQkFDNUQsTUFBTTtnQkFDUixLQUFLLE1BQU0sQ0FBQztnQkFDWixLQUFLLEtBQUs7b0JBQ1IsU0FBUyxHQUFHLFNBQVMsQ0FBQyxZQUFZLENBQUMsY0FBYyxFQUFFLE9BQU8sQ0FBQyxDQUFDO29CQUM1RCxNQUFNO2dCQUNSLEtBQUssT0FBTyxDQUFDO2dCQUNiLEtBQUssTUFBTTtvQkFDVCxTQUFTLEdBQUcsU0FBUyxDQUFDLFlBQVksQ0FBQyxlQUFlLEVBQUUsT0FBTyxDQUFDLENBQUM7b0JBQzdELE1BQU07Z0JBQ1IsS0FBSyxNQUFNLENBQUM7Z0JBQ1osS0FBSyxLQUFLO29CQUNSLFNBQVMsR0FBRyxTQUFTLENBQUMsWUFBWSxDQUFDLGVBQWUsRUFBRSxPQUFPLENBQUMsQ0FBQztvQkFDN0QsTUFBTTtnQkFDUixLQUFLLE1BQU0sQ0FBQztnQkFDWixLQUFLLEtBQUs7b0JBQ1IsU0FBUyxHQUFHLFNBQVMsQ0FBQyxZQUFZLENBQUMsY0FBYyxFQUFFLE9BQU8sQ0FBQyxDQUFDO29CQUM1RCxNQUFNO2dCQUVSO29CQUNFLE9BQU8sQ0FBQyxHQUFHLENBQUMsc0JBQXNCLENBQUMsQ0FBQztvQkFDcEMsTUFBTTthQUNUO1lBRUQsbURBQW1EO1lBQ25EOzs7Ozs7NENBTWdDO1lBQ2hDLDhDQUE4QztZQUM5QyxxQkFBcUI7WUFFckIsNkJBQTZCO1lBQzdCLElBQUksSUFBSSxDQUFDLGlCQUFpQixFQUFFO2dCQUMxQixNQUFNLFVBQVUsR0FBRyxXQUFXLENBQUMsT0FBTyxFQUFFLENBQUM7Z0JBQ3pDLFVBQVUsQ0FBQyxZQUFZLENBQUMsaUJBQWlCLEVBQUU7b0JBQ3pDLFNBQVMsRUFBRSxDQUFDO29CQUNaLEtBQUssRUFBRSxFQUFDLENBQUMsRUFBRSxHQUFHLEVBQUUsQ0FBQyxFQUFFLEdBQUcsRUFBRSxDQUFDLEVBQUUsR0FBRyxFQUFDO2lCQUNoQyxDQUFDLENBQUM7Z0JBQ0gsSUFBSSxDQUFDLGlCQUFpQixHQUFHLEtBQUssQ0FBQzthQUNoQztZQUVELFNBQVMsQ0FBQyxLQUFLLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FDMUIsR0FBRyxDQUFDLFFBQVEsQ0FBQyxDQUFDLEVBQ2QsR0FBRyxDQUFDLFFBQVEsQ0FBQyxDQUFDLEVBQ2QsR0FBRyxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQ2YsQ0FBQztZQUVGLFNBQVMsQ0FBQyxLQUFLLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FDMUIsR0FBRyxDQUFDLFFBQVEsQ0FBQyxDQUFDLEVBQ2QsR0FBRyxDQUFDLFFBQVEsQ0FBQyxDQUFDLEVBQ2QsR0FBRyxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQ2YsQ0FBQztZQUNGLFNBQVMsQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLENBQUMsRUFBRSxHQUFHLENBQUMsS0FBSyxDQUFDLENBQUMsRUFBRSxHQUFHLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQ2pFLElBQUcsZ0JBQWdCLEVBQ25CO2dCQUNFOzttQkFFRztnQkFDSCxJQUFJLENBQUMsY0FBYyxHQUFDLFNBQVMsQ0FBQztnQkFDOUIsSUFBSSxDQUFDLG9CQUFvQixFQUFFLENBQUM7YUFDN0I7WUFFRCwyREFBMkQ7WUFDM0Qsc0ZBQXNGO1lBQ3RGLElBQUksSUFBSSxJQUFJLENBQUMsZ0JBQWdCLEVBQUU7Z0JBQzdCLElBQUksQ0FBQyw0QkFBNEIsQ0FDL0IsU0FBUyxFQUNULFdBQVcsRUFDWCxJQUFJLEVBQ0osSUFBSSxDQUNMLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7YUFDaEM7WUFFRCxJQUFJLElBQUksQ0FBQyxZQUFZLElBQUksT0FBTyxJQUFJLENBQUMsWUFBWSxDQUFDLEVBQUUsS0FBSyxRQUFRLEVBQUU7Z0JBQ2pFLDhFQUE4RTtnQkFDOUUsU0FBUyxDQUFDLEtBQUssQ0FBQyxJQUFJLEdBQUcsSUFBSSxDQUFDLFlBQVksQ0FBQyxFQUFFLENBQUM7YUFDN0M7aUJBQU0sSUFBSSxHQUFHLENBQUMsRUFBRSxFQUFFO2dCQUNqQixTQUFTLENBQUMsS0FBSyxDQUFDLElBQUksR0FBRyxHQUFHLENBQUMsRUFBRSxDQUFDO2FBQy9CO1lBQ0QsSUFBSSxDQUFDLFlBQVksR0FBRyxTQUFTLENBQUMsS0FBSyxDQUFDO1lBRXBDLHVDQUF1QztZQUN2QyxpQ0FBaUM7WUFDakMseUJBQXlCO1lBQ3pCLElBQUksQ0FBQyxvQkFBb0IsQ0FBQyxHQUFHLENBQUMsU0FBUyxDQUFDLEtBQUssQ0FBQyxJQUFJLEVBQUUsU0FBUyxDQUFDLENBQUM7WUFDL0QsSUFBSSxDQUFDLHlCQUF5QixDQUFDLEdBQUcsQ0FBQyxTQUFTLENBQUMsS0FBSyxDQUFDLElBQUksRUFBRSxXQUFXLENBQUMsQ0FBQztZQUV0RTs7Ozs7Ozs7Ozs7Ozs7OEJBY2tCO1lBRWxCLElBQUksd0JBQXdCLEVBQUU7Z0JBRTVCLE1BQU0sUUFBUSxHQUFHLFNBQVMsQ0FBQyxZQUFZLENBQUMsbUJBQW1CLEVBQ3pEO29CQUNFLFdBQVcsRUFBRSxHQUFHO29CQUNoQixVQUFVLEVBQUUsRUFBRTtvQkFDZCxlQUFlLEVBQUUsRUFBRTtvQkFDbkIsUUFBUSxFQUFFLGtCQUFrQjtvQkFDNUIsZUFBZSxFQUFFO3dCQUNmLEdBQUcsRUFBRSxHQUFHO3dCQUNSLEdBQUcsRUFBRSxJQUFJO3dCQUNULEdBQUcsRUFBRSxDQUFDO3FCQUNQO29CQUNELGVBQWUsRUFBRTt3QkFDZixHQUFHLEVBQUUsQ0FBQyxFQUFFO3dCQUNSLEdBQUcsRUFBRSxDQUFDLEVBQUU7d0JBQ1IsR0FBRyxFQUFFLENBQUM7cUJBQ1A7b0JBQ0QsT0FBTyxFQUFFLEtBQUs7b0JBQ2QsV0FBVyxFQUFFLENBQUM7b0JBQ2QsVUFBVSxFQUFFLENBQUMsRUFBRTtpQkFDaEIsQ0FBQyxDQUFDO2dCQUNMLE1BQU0sV0FBVyxHQUFHLFdBQVcsQ0FBQyxPQUFPLENBQUM7b0JBQ3RDLEVBQUUsRUFBRSxnQkFBZ0I7b0JBQ3BCLElBQUksRUFBRSxJQUFJLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxRQUFRLENBQUMsTUFBTTtvQkFDcEMsSUFBSSxFQUFFLFNBQVM7b0JBQ2YsU0FBUyxFQUFFLFFBQVE7b0JBQ25CLFFBQVEsRUFBRSxZQUFZO2lCQUN2QixDQUFDLENBQUM7Z0JBRUgsSUFBSSxDQUFDLHNCQUFzQixHQUFHLFFBQVEsQ0FBQztnQkFDdkMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxXQUFXLEVBQUU7b0JBQ3BCLFVBQVUsQ0FBQyxHQUFHLEVBQUU7d0JBQ2QsUUFBUSxDQUFDLGlCQUFpQixFQUFFLENBQUM7b0JBQy9CLENBQUMsRUFBRSxJQUFJLENBQUMsQ0FBQztpQkFDVjthQUNGO1lBRUQsSUFBSSxnQkFBZ0IsRUFBRTtnQkFDcEIsZ0ZBQWdGO2dCQUNoRixpQ0FBaUM7Z0JBQ2pDLGdDQUFnQztnQkFDaEMsZUFBZTtnQkFDZixNQUFNLEVBQUUsR0FBRyxJQUFJLGNBQWMsRUFBRSxDQUFDO2dCQUNoQyxFQUFFLENBQUMsTUFBTSxFQUFFLENBQUM7Z0JBQ1osTUFBTSxLQUFLLEdBQUcsSUFBSSxhQUFhLEVBQUUsQ0FBQztnQkFDbEMsS0FBSyxDQUFDLE9BQU8sR0FBRztvQkFDZCxVQUFVLEVBQUUsSUFBSSxRQUFRLEVBQUU7b0JBQzFCLFFBQVEsRUFBRSxJQUFJLFFBQVEsRUFBRTtpQkFDekIsQ0FBQztnQkFDRixNQUFNLFlBQVksR0FBRyxFQUFFLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQztnQkFDeEMsS0FBSyxDQUFDLFlBQVksQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDLENBQUM7Z0JBQ3RDLEtBQUssQ0FBQyxNQUFNLENBQUMsU0FBUyxFQUFFLFlBQVksQ0FBQyxDQUFDO2dCQUN0QyxNQUFNLEVBQUUsR0FBRyxJQUFJLGNBQWMsRUFBRSxDQUFDO2dCQUNoQyxFQUFFLENBQUMsWUFBWSxDQUFDLFNBQVMsRUFBRSxLQUFLLEVBQUUsRUFBRSxDQUFDLENBQUM7Z0JBQ3RDLEVBQUUsQ0FBQyxZQUFZLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxDQUFDO2dCQUNuQyxFQUFFLENBQUMsTUFBTSxDQUFDLFNBQVMsRUFBRSxLQUFLLEVBQUUsWUFBWSxDQUFDLENBQUM7Z0JBQzFDLEVBQUUsQ0FBQyw4QkFBOEIsQ0FBQyxFQUFFLENBQUMsQ0FBQztnQkFDdEMsVUFBVSxDQUFDLEdBQUcsRUFBRTtvQkFDZCxFQUFFLENBQUMsTUFBTSxDQUFDLFlBQVksR0FBRyxRQUFRLENBQUM7b0JBQ2xDLEVBQUUsQ0FBQyxlQUFlLEVBQUUsQ0FBQztnQkFDdkIsQ0FBQyxFQUFFLElBQUksQ0FBQyxDQUFDO2FBQ1Y7WUFFRCxJQUFJLDZCQUE2QixFQUFFO2dCQUNqQyxnRkFBZ0Y7Z0JBQ2hGLE1BQU0sRUFBRSxHQUFHLElBQUksUUFBUSxFQUFFLENBQUM7Z0JBQzFCLEVBQUUsQ0FBQyxZQUFZLENBQUMsU0FBUyxDQUFDLENBQUM7Z0JBQzNCLEVBQUUsQ0FBQyxNQUFNLENBQUMsU0FBUyxDQUFDLENBQUM7Z0JBQ3JCLFVBQVUsQ0FBQyxHQUFHLEVBQUU7b0JBQ2QsRUFBRSxDQUFDLE1BQU0sQ0FBQyxZQUFZLEdBQUcsUUFBUSxDQUFDO29CQUNsQyxFQUFFLENBQUMsZUFBZSxFQUFFLENBQUM7Z0JBQ3ZCLENBQUMsRUFBRSxJQUFJLENBQUMsQ0FBQzthQUNWO1lBRUQsV0FBVyxDQUFDLEtBQUssRUFBRSxDQUFDO1lBQ3BCLE9BQU8sQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDLENBQUM7UUFDN0IsQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDO0lBRUQsc0JBQXNCLENBQUMsUUFBYTtRQUNsQyxJQUFJLEdBQUcsR0FBRyxJQUFJLENBQUMsb0JBQW9CLENBQUMsR0FBRyxDQUFDLFFBQVEsQ0FBQyxDQUFDO1FBQ2xELEdBQUcsQ0FBQyxLQUFLLENBQUMsT0FBTyxHQUFHLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUM7SUFDekMsQ0FBQztJQUVELGVBQWUsQ0FBQyxRQUFhO1FBQzNCLElBQUksR0FBRyxHQUFHLElBQUksQ0FBQyxvQkFBb0IsQ0FBQyxHQUFHLENBQUMsUUFBUSxDQUFDLENBQUM7UUFDbEQsT0FBTyxHQUFHLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQztJQUMzQixDQUFDO0lBRUQsS0FBSyxDQUFDLHFCQUFxQixDQUFDLFFBQWE7UUFDdkMsSUFBSSxHQUFHLEdBQUcsSUFBSSxDQUFDLG9CQUFvQixDQUFDLEdBQUcsQ0FBQyxRQUFRLENBQUMsQ0FBQztRQUVsRCwyQkFBMkI7UUFDM0IsTUFBTSxTQUFTLEdBQUc7WUFDaEIsVUFBVSxFQUFFLElBQUksQ0FBQyxTQUFTLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxRQUFRLENBQUM7WUFDOUMsSUFBSSxFQUFFLE9BQU8sQ0FBQyxRQUFRO1lBQ3RCLFNBQVMsRUFBRSxRQUFRLEVBQUUsNEJBQTRCO1NBQzNDLENBQUM7UUFDVCxNQUFNLFFBQVEsR0FBRyxFQUFDLEVBQUUsRUFBRSxRQUFRLEVBQWlCLENBQUM7UUFFaEQsSUFBRztZQUNELE1BQU0sSUFBSSxDQUFDLHNCQUFzQixDQUFDLE9BQU8sQ0FBQyxRQUFRLEVBQUUsUUFBUSxFQUFFLFNBQVMsQ0FBQyxDQUFDO1NBQzFFO1FBQUEsT0FBTSxHQUFRLEVBQUMsR0FBRTtRQUVsQixpRUFBaUU7UUFDakUsd0RBQXdEO1FBQ3hELG9FQUFvRTtRQUVwRSxJQUFJLE1BQU0sR0FBRyxJQUFJLENBQUMsbUJBQW1CLENBQUMsUUFBUSxDQUFDLENBQUM7UUFFaEQsTUFBTSxJQUFJLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQztRQUMvQixJQUFJLENBQUMsbUJBQW1CLEVBQUUsQ0FBQztJQUM3QixDQUFDO0lBRUQsMEJBQTBCLENBQUMsSUFBWTtRQUNyQyxPQUFPLElBQUksQ0FBQyx5QkFBeUIsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDbEQsQ0FBQztJQUVELEtBQUssQ0FBQyxvQkFBb0I7UUFDeEIsSUFBRyxJQUFJLENBQUMsY0FBYyxFQUFDO1lBQ3JCLElBQUksQ0FBQyxjQUFjLENBQUMsS0FBSyxDQUFDLFFBQVEsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxRQUFRLENBQUMsQ0FBQyxFQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsUUFBUSxDQUFDLENBQUMsRUFBQyxJQUFJLENBQUMsVUFBVSxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsQ0FBQTtTQUN6SDtJQUNILENBQUM7SUFFRCxLQUFLLENBQUMsNEJBQTRCLENBQ2hDLFNBQWMsRUFDZCxXQUFnQixFQUNoQixJQUFzQyxFQUN0QyxPQUFnQjtRQUVoQiwwREFBMEQ7UUFDMUQsSUFBSSxJQUFJLEdBQUcsSUFBSSxDQUFDO1FBQ2hCLElBQUksR0FBRyxXQUFXLENBQUMsT0FBTyxFQUFFLENBQUM7UUFDN0IsSUFBSSxDQUFDLElBQUksRUFBRTtZQUNULE1BQU0sQ0FBQyxXQUFXLENBQUMsR0FBRyxNQUFNLElBQUksQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLGFBQWEsQ0FBQyxDQUFDLENBQUMsQ0FBQztZQUM1RCxJQUFJLEdBQUcsV0FBVyxDQUFDLE9BQU8sRUFBRSxDQUFDO1NBQzlCO1FBRUQsTUFBTSxTQUFTLEdBQUcsSUFBSSxDQUFDLFlBQVksQ0FBQyxzQkFBc0IsQ0FBQyxDQUFDO1FBQzVELElBQUksQ0FBQyxLQUFLLEVBQUUsQ0FBQztRQUNiLEVBQUU7UUFDRiwrRkFBK0Y7UUFDL0YsU0FBUyxDQUFDLGlCQUFpQixDQUFDLE9BQU8sR0FBRyxPQUFPLENBQUM7UUFDOUMsRUFBRTtRQUNGLCtDQUErQztRQUMvQyxTQUFTLENBQUMsTUFBTSxDQUFDLFNBQVMsR0FBRyxTQUFTLENBQUM7UUFDdkMsRUFBRTtRQUNGLHFEQUFxRDtRQUNyRCxTQUFTLENBQUMsTUFBTSxDQUFDLElBQUksR0FBRyxJQUFJLENBQUM7UUFDN0IsU0FBUyxDQUFDLEtBQUssQ0FBQyxRQUFRLEdBQUcsU0FBUyxDQUFDLENBQUMsZ0NBQWdDO1FBRXRFLElBQUksQ0FBQyxJQUFJLENBQUMsWUFBWSxJQUFJLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxRQUFRLEVBQUU7WUFDckQsSUFBSTtnQkFDRixTQUFTLENBQUMsS0FBSyxDQUFDLElBQUksR0FBRyxJQUFJLENBQUMsWUFBWSxDQUFDLElBQUksSUFBSSxJQUFJLENBQUMsWUFBWSxDQUFDLEVBQUUsQ0FBQzthQUN2RTtZQUFDLE9BQU8sQ0FBQyxFQUFFO2dCQUNWLE9BQU8sQ0FBQyxHQUFHLENBQUMsc0RBQXNELENBQUMsQ0FBQzthQUNyRTtZQUNELElBQUksQ0FBQyxZQUFZLEdBQUcsU0FBUyxDQUFDLEtBQUssQ0FBQztTQUNyQztRQUVELE9BQU8sU0FBUyxDQUFDO0lBQ25CLENBQUM7SUFFRCx5QkFBeUI7UUFDdkIsSUFBSSxDQUFDLFlBQVksQ0FBQyxRQUFRLENBQUMsaUJBQWlCLENBQUMsT0FBTyxHQUFHLEtBQUssQ0FBQztRQUM3RCxJQUFJLENBQUMsWUFBWSxDQUFDLFFBQVEsQ0FBQyxpQkFBaUIsQ0FBQyxPQUFPLEVBQUUsQ0FBQztRQUN2RCxJQUFJLENBQUMsWUFBWSxDQUFDLFFBQVEsR0FBRyxJQUFJLENBQUM7SUFDcEMsQ0FBQztJQUVELGlCQUFpQjtRQUNmLElBQUksQ0FBQyxzQkFBc0IsQ0FBQyxpQkFBaUIsRUFBRSxDQUFDO0lBQ2xELENBQUM7OzhHQXg4RFUsaUJBQWlCLGtCQXFKbEIsUUFBUTtrSEFySlAsaUJBQWlCLGNBRmhCLE1BQU07MkZBRVAsaUJBQWlCO2tCQUg3QixVQUFVO21CQUFDO29CQUNWLFVBQVUsRUFBRSxNQUFNO2lCQUNuQjs7MEJBc0pJLE1BQU07MkJBQUMsUUFBUSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7SW5qZWN0LCBJbmplY3RhYmxlLCBOZ1pvbmV9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xyXG5pbXBvcnQge0FjdGl2YXRlZFJvdXRlLCBSb3V0ZXJ9IGZyb20gJ0Bhbmd1bGFyL3JvdXRlcic7XHJcbmltcG9ydCB7U3ViamVjdH0gZnJvbSAncnhqcyc7XHJcbi8vaW1wb3J0ICogYXMgc2VyaWFsaWpzZSBmcm9tIFwic2VyaWFsaWpzZVwiO1xyXG5pbXBvcnQge1xyXG4gIGdldERpc3RhbmNlQmV0d2VlblR3b1BvaW50cyxcclxuICBwb2lUeXBlVG9TdHJpbmcsXHJcbiAgd2FpdCxcclxufSBmcm9tICcuLi9oZWxwZXJzLnNlcnZpY2UnO1xyXG5pbXBvcnQge01hdHRlcnRhZ0RhdGF9IGZyb20gJy4uL21hdHRlcnRhZ0RhdGEnO1xyXG5pbXBvcnQge1xyXG4gIERiT2JqZWN0VHlwZSxcclxuICBGZWF0dXJlVHlwZSxcclxuICBJT2JqZWN0M0QsXHJcbiAgTWF0dGVydGFnQWN0aW9uTW9kZSxcclxuICBQT0ksXHJcbiAgUG9pVHlwZSxcclxuICBTcE1vZHVsZSxcclxuICBUYWdBY3Rpb24sXHJcbiAgVmlld2VySW50ZXJhY3Rpb25zLFxyXG59IGZyb20gJy4uL3R5cGVzLnNlcnZpY2UnO1xyXG5pbXBvcnQge09iamVjdDNEfSBmcm9tICd0aHJlZSc7XHJcbmltcG9ydCB7QmFzZVRhZ1NlcnZpY2V9IGZyb20gJy4vdGFnLnNlcnZpY2UnO1xyXG5pbXBvcnQge0Jhc2VWaXNpYmlsaXR5U2VydmljZX0gZnJvbSAnLi9iYXNlVmlzaWJpbGl0eS5zZXJ2aWNlJztcclxuaW1wb3J0IHtDb25maWd9IGZyb20gJy4uL2NvbmZpZyc7XHJcbmltcG9ydCB7Q2FtZXJhTW9kZX0gZnJvbSAnLi4vdHlwZXMuc2VydmljZSc7XHJcbmltcG9ydCB7SVNjZW5lTm9kZSwgQ29tcG9uZW50T3V0cHV0fSBmcm9tIFwiLi4vbWF0dGVycG9ydC1leHRlbnNpb25zL3NjZW5lLWNvbXBvbmVudC9TY2VuZUNvbXBvbmVudFwiO1xyXG5pbXBvcnQge1NlY3VyaXR5Q2FtZXJhfSBmcm9tICcuLi9tYXR0ZXJwb3J0LWV4dGVuc2lvbnMvc2VjdXJpdHktY2FtZXJhL1NlY3VyaXR5Q2FtZXJhJztcclxuaW1wb3J0IHtOZXN0VGhlcm1vc3RhdH0gZnJvbSAnLi4vbWF0dGVycG9ydC1leHRlbnNpb25zL25lc3QtdGhlcm1vc3RhdC9OZXN0VGhlcm1vc3RhdCc7XHJcbmltcG9ydCB7UGxhbmVSZW5kZXJlcn0gZnJvbSAnLi4vbWF0dGVycG9ydC1leHRlbnNpb25zL25lc3QtdGhlcm1vc3RhdC9QbGFuZVJlbmRlcmVyJztcclxuaW1wb3J0IHtDYW52YXNSZW5kZXJlcn0gZnJvbSBcIi4uL21hdHRlcnBvcnQtZXh0ZW5zaW9ucy9uZXN0LXRoZXJtb3N0YXQvQ2FudmFzUmVuZGVyZXJcIjtcclxuaW1wb3J0IHtWaWRlb1JlbmRlcmVyfSBmcm9tIFwiLi4vbWF0dGVycG9ydC1leHRlbnNpb25zL3ZpZGVvLXJlbmRlcmVyL1ZpZGVvUmVuZGVyZXJcIjtcclxuaW1wb3J0IHtIbHNMb2FkZXJ9IGZyb20gXCIuLi9tYXR0ZXJwb3J0LWV4dGVuc2lvbnMvaHNsLWxvYWRlci9IbHNMb2FkZXJcIjtcclxuaW1wb3J0IHtUdlBsYXllcn0gZnJvbSBcIi4uL21hdHRlcnBvcnQtZXh0ZW5zaW9ucy90di1wbGF5ZXIvVHZQbGF5ZXJcIjtcclxuXHJcbi8vIGltcG9ydCB7Q2FudmFzSW1hZ2V9IGZyb20gXCIuLi9tYXR0ZXJwb3J0LWV4dGVuc2lvbnMvbmVzdC10aGVybW9zdGF0L0NhbnZhc0ltYWdlXCI7XHJcblxyXG4vKipcclxuICogQ3VzdG9tIFRocmVlanMgT2JqZWN0IDNEIGludGVyZmFjZVxyXG4gKi9cclxuaW50ZXJmYWNlIFRocmVlSlNPYmplY3QzRCB7XHJcbiAgaWQ6IHN0cmluZztcclxuICB1dWlkPzogc3RyaW5nO1xyXG4gIHBvc2l0aW9uPzogeyB4OiBudW1iZXIsIHk6IG51bWJlciwgejogbnVtYmVyIH1cclxuICByb3RhdGlvbj86IHsgeDogbnVtYmVyLCB5OiBudW1iZXIsIHo6IG51bWJlciB9XHJcbiAgc2NhbGU/OiB7IHg6IG51bWJlciwgeTogbnVtYmVyLCB6OiBudW1iZXIgfVxyXG59XHJcblxyXG5kZWNsYXJlIGdsb2JhbCB7XHJcbiAgaW50ZXJmYWNlIFdpbmRvdyB7XHJcbiAgICBNUF9TREs6IHsgY29ubmVjdDogRnVuY3Rpb24gfTtcclxuICB9XHJcbn1cclxuXHJcbkBJbmplY3RhYmxlKHtcclxuICBwcm92aWRlZEluOiAncm9vdCcsXHJcbn0pXHJcbmV4cG9ydCBjbGFzcyBNYXR0ZXJwb3J0U2VydmljZSB7XHJcblxyXG4gIHByaXZhdGUgc2xvdHM6IGFueVtdID0gW107Ly9TbG90Tm9kZVtdID0gW107XHJcblxyXG4gIHByaXZhdGUgbm9kZXM6IElTY2VuZU5vZGVbXSA9IFtdO1xyXG5cclxuICBwdWJsaWMgc2RrOiBhbnk7XHJcblxyXG4gIHByaXZhdGUgY29udGFpbmVyOiBhbnk7XHJcblxyXG4gIC8vIFBvc2l0aW9uIGNhbWVyYVxyXG4gIHByaXZhdGUgcG9zZU1hdHRlcnBvcnQ6IGFueTtcclxuXHJcbiAgcHVibGljIHBvc2VDYW1lcmE6IHsgcm90YXRpb246IGFueTsgcG9zaXRpb246IGFueTsgc3dlZXA6IGFueSB9O1xyXG4gIHB1YmxpYyBsYXN0Q2FtZXJhUG9zaXRpb246IGFueSA9IHt4OjAuMCx5OjAuMCx6OjAuMH07XHJcblxyXG4gIHByaXZhdGUgYXppbXV0aGFsQ3Jvd246YW55O1xyXG4gIC8vIFBvaW50ZXIgdHJpY2tcclxuICBwcml2YXRlIHBvaW50ZXJCdXR0b246IGFueTtcclxuXHJcbiAgLy8gRGlzcGxheSBhbmQgZ2V0IGN1cnJlbnQgcG9zaXRpb24gb2YgY3Vyc29yIChmb3IgQWRtaW5zIG9ubHkpXHJcbiAgcHJpdmF0ZSBnZXRDdXJzb3JQb3NpdGlvbkJ1dHRvbjogYW55O1xyXG4gIHByaXZhdGUgY3Vyc29yUG9zaXRpb25CdXR0b25EaXNwbGF5ZWQgPSBmYWxzZTtcclxuICBwcml2YXRlIGludGVydmFsQ3Vyc29yUG9pbnRlclBvc2l0aW9uOiBhbnk7XHJcbiAgcHJpdmF0ZSB0ZXh0RGlzcGxheUN1cnNvclBvc2l0aW9uUGFuZWw6IGFueTtcclxuXHJcbiAgcHJpdmF0ZSBvbGRQb3NlTWF0dGVycG9ydFBvc2l0aW9uOiBhbnk7XHJcbiAgLy8gTWVhc3VyZSBtb2RlXHJcbiAgcHJpdmF0ZSBpc01lYXN1cmVNb2RlT24gPSBmYWxzZTtcclxuXHJcbiAgcHJpdmF0ZSBpbnRlcmFjdGlvbk1vZGU6IG51bWJlciA9IFZpZXdlckludGVyYWN0aW9ucy5ERUZBVUxUO1xyXG5cclxuICAvLyBMaXN0IG9mIGNyZWF0ZWQgTWF0dGVydGFnIElEcyBpbiB0aGUgY3VycmVudCB2aWV3ZXIgc2Vzc2lvblxyXG4gIHByaXZhdGUgbWF0dGVydGFnSURzOiBBcnJheTxzdHJpbmc+ID0gW107XHJcblxyXG4gIC8vIERpY3Rpb25uYXJ5IG9mIE1hdHRlcnRhZ0lEIGFuZCBpdHMgZGF0YSAobWF0dGVydGFnRGF0YSlcclxuICBwcml2YXRlIGRpY3Rpb25uYXJ5VGFnczogTWFwPHN0cmluZywgTWF0dGVydGFnRGF0YT4gPSBuZXcgTWFwKCk7XHJcblxyXG4gIHByaXZhdGUgZGljdGlvbm5hcnlPYmplY3RzM0Q6IE1hcDxzdHJpbmcsIGFueT4gPSBuZXcgTWFwKCk7XHJcblxyXG4gIHByaXZhdGUgZGljdGlvbm5hcnlTY2VuZU9iamVjdHMzRDogTWFwPHN0cmluZywgYW55PiA9IG5ldyBNYXAoKTtcclxuXHJcbiAgcHVibGljIHRocmVlSlNTY2VuZTogYW55OyAvLyBnbG9iYWwgcm9vdCBzY2VuZSAobm90IHVzZWQgbm93ISlcclxuXHJcbiAgcHJpdmF0ZSBsYXN0TWVhc3VyZSA9IFtdO1xyXG5cclxuICBwcml2YXRlIGRpc3RhbmNlc0xhc3RNZWFzdXJlOiBudW1iZXJbXSA9IFtdO1xyXG5cclxuICBwcml2YXRlIHJlc29sdXRpb24gPSB7XHJcbiAgICB3aWR0aDogNTAwLFxyXG4gICAgaGVpZ2h0OiA2MDAsXHJcbiAgfTtcclxuXHJcbiAgcHJpdmF0ZSB2aXNpYmlsaXR5ID0ge1xyXG4gICAgbWF0dGVydGFnczogZmFsc2UsXHJcbiAgICBzd2VlcHM6IHRydWUsXHJcbiAgfTtcclxuXHJcbiAgcHVibGljIHRhZ3NBdHRhY2htZW50czogT2JqZWN0ID0ge307XHJcblxyXG4gIHByaXZhdGUgbGFzdFNjcmVlbnNob3RVcmk6IGFueTtcclxuXHJcbiAgcHVibGljIHN3ZWVwczogQXJyYXk8c3RyaW5nPiB8IG51bGw7XHJcblxyXG4gIHB1YmxpYyBjdXJyZW50U3dlZXA6IFN1YmplY3Q8c3RyaW5nPiA9IG5ldyBTdWJqZWN0KCk7XHJcblxyXG4gIC8vY2FtZXJhIHBvc2l0aW9uIHdpdGggcm90YXRpb25cclxuICBwdWJsaWMgY3VycmVudENhbWVyYVBvc2U6IFN1YmplY3Q8YW55PiA9IG5ldyBTdWJqZWN0KCk7XHJcblxyXG4gIHByaXZhdGUgZmxvb3JzPzogQXJyYXk8eyBpZDogc3RyaW5nOyBuYW1lOiBzdHJpbmc7IHNlcXVlbmNlOiBudW1iZXIgfT4gfCBudWxsO1xyXG5cclxuICBwcml2YXRlIF9jdXJyZW50U3BhY2VJRDogc3RyaW5nO1xyXG5cclxuICBwcml2YXRlIGxhc3RPYmplY3QzRDogYW55OyAvLyBUaHJlZSBKUyBvYmplY3RcclxuXHJcbiAgcHJpdmF0ZSBjdXJyZW50Rmxvb3I7XHJcblxyXG4gIHB1YmxpYyBnZXQgY3VycmVudFNwYWNlSUQoKTogc3RyaW5nIHtcclxuICAgIHJldHVybiB0aGlzLl9jdXJyZW50U3BhY2VJRDtcclxuICB9XHJcblxyXG4gIHB1YmxpYyBzZXQgY3VycmVudFNwYWNlSUQodmFsdWU6IHN0cmluZykge1xyXG4gICAgdGhpcy5fY3VycmVudFNwYWNlSUQgPSB2YWx1ZTtcclxuICB9XHJcblxyXG4gIHRpbWVyUG9pbnRlcjogYW55O1xyXG5cclxuICBmb3JiaWRkZW5Td2VlcHM6IHN0cmluZ1tdID0gW107XHJcblxyXG4gIHB1YmxpYyB0YWdBY3Rpb246IFN1YmplY3Q8eyBhY3Rpb246IHN0cmluZzsgZGF0YTogc3RyaW5nIH0+ID0gbmV3IFN1YmplY3QoKTtcclxuXHJcbiAgcHVibGljIG1hdHRlcnRhZ1RvRm9sbG93OiBzdHJpbmcgfCBudWxsO1xyXG5cclxuICB0YWdTZXJ2aWNlOiBCYXNlVGFnU2VydmljZTtcclxuXHJcbiAgY29uZmlnOiBDb25maWc7XHJcblxyXG4gIHB1YmxpYyBpblRyYW5zaXRpb25Nb2RlID0gZmFsc2U7XHJcblxyXG4gIHB1YmxpYyBpblRyYW5zaXRpb25Td2VlcCA9IGZhbHNlO1xyXG5cclxuICBwcml2YXRlIG5vTGlnaHRGb3JPYmplY3RzID0gdHJ1ZTtcclxuXHJcbiAgcHVibGljIGN1cnJlbnRDYW1lcmFNb2RlOiBDYW1lcmFNb2RlID0gQ2FtZXJhTW9kZS5PVVRTSURFO1xyXG5cclxuICBwdWJsaWMgb25DYW1lcmFNb2RlQ2hhbmdlZCA9IG5ldyBTdWJqZWN0PENhbWVyYU1vZGU+KCk7XHJcblxyXG4gIHB1YmxpYyBvbkdvVG9UYWcgPSBuZXcgU3ViamVjdDxzdHJpbmc+KCk7XHJcblxyXG4gIHRhZ01lc3Nlbmdlck9uID0gZmFsc2U7XHJcblxyXG4gIFNQTW9kdWxlOiBTcE1vZHVsZTtcclxuXHJcbiAgcHVibGljIG9iamVjdENvbnRyb2w6IGFueTtcclxuXHJcbiAgcHJpdmF0ZSBzZWN1cml0eUNhbWVyYUFuaW1hdG9yOiBhbnk7XHJcblxyXG4gIC8qKlxyXG4gICAqIEFjdGlvbnMgb24gbGVmdCBjbGljayB3aGVuIHBvc2l0aW9uaW5nIG1hdHRlcnRhZyBpbiB2aXNpdFxyXG4gICAqL1xyXG4gIHBvaW50ZXJMZWZ0Q2xpY2tIYW5kbGVyID0gKCkgPT4ge1xyXG4gICAgaWYgKHRoaXMubWF0dGVydGFnVG9Gb2xsb3cpIHtcclxuICAgICAgY29uc3QgbWF0dGVydGFnRGF0YSA9IHRoaXMuZGljdGlvbm5hcnlUYWdzLmdldCh0aGlzLm1hdHRlcnRhZ1RvRm9sbG93KTtcclxuICAgICAgbWF0dGVydGFnRGF0YS5zZXRQb3NpdGlvbih7Li4udGhpcy5wb3NlTWF0dGVycG9ydC5wb3NpdGlvbn0pOyAvLyBjb3B5ISEgbm90IHRoZSByZWZlcmVuY2VcclxuICAgICAgbWF0dGVydGFnRGF0YS5zZXROb3JtYWwoey4uLnRoaXMucG9zZU1hdHRlcnBvcnQubm9ybWFsfSk7IC8vIGNvcHkhISBub3QgdGhlIHJlZmVyZW5jZVxyXG4gICAgICB0aGlzLmRpY3Rpb25uYXJ5VGFncy5zZXQodGhpcy5tYXR0ZXJ0YWdUb0ZvbGxvdywgbWF0dGVydGFnRGF0YSk7XHJcbiAgICAgIHRoaXMudXBkYXRlTWF0dGVyVGFnQ29udGVudEZvclRhZ0lEKHRoaXMubWF0dGVydGFnVG9Gb2xsb3cpO1xyXG4gICAgfVxyXG4gICAgdGhpcy5vblZhbGlkYXRlZE1hdHRlcnRhZygpO1xyXG4gIH07XHJcblxyXG4gIHBvaW50ZXJSaWdodENsaWNrSGFuZGxlciA9IChlKSA9PiB7XHJcbiAgICBlLnByZXZlbnREZWZhdWx0KCk7XHJcbiAgICB0aGlzLmNhbmNlbEZvbGxvd2luZ0N1cnNvcigpO1xyXG4gICAgYWxlcnQoJ2FjdGlvbiBjYW5jZWxsZWQnKTtcclxuICB9O1xyXG5cclxuICBwb2ludGVyTWlkZGxlQ2xpY2tIYW5kbGVyID0gKGUpID0+IHtcclxuICAgIHRoaXMudGV4dERpc3BsYXlDdXJzb3JQb3NpdGlvblBhbmVsLmlubmVySFRNTCA9IGBwb3NpdGlvbjpcclxuICAgICAgICR7dGhpcy5wb2ludFRvU3RyaW5nKHRoaXMucG9zZU1hdHRlcnBvcnQucG9zaXRpb24pfVxcblxyXG4gICAgICAgbm9ybWFsOlxyXG4gICAgICAgJHt0aGlzLnBvaW50VG9TdHJpbmcodGhpcy5wb3NlTWF0dGVycG9ydC5ub3JtYWwpfVxcblxyXG4gICAgICAgZmxvb3JJZDpcclxuICAgICAgICR7dGhpcy5wb3NlTWF0dGVycG9ydC5mbG9vcklkfWA7XHJcbiAgICAvLyB0aGlzLnRleHREaXNwbGF5Q3Vyc29yUG9zaXRpb25QYW5lbC5zdHlsZS5kaXNwbGF5ID0gJ3Zpc2libGUnO1xyXG4gICAgdGhpcy5nZXRDdXJzb3JQb3NpdGlvbkJ1dHRvbi5zdHlsZS5kaXNwbGF5ID0gJ25vbmUnO1xyXG4gIH1cclxuXHJcbiAgY29uc3RydWN0b3IoXHJcbiAgICBASW5qZWN0KCdjb25maWcnKSBjb25maWc6IENvbmZpZyxcclxuICAgIHByaXZhdGUgcm91dGVyOiBSb3V0ZXIsXHJcbiAgICBwcml2YXRlIGFjdGl2ZVJvdXRlOiBBY3RpdmF0ZWRSb3V0ZSxcclxuICAgIHByaXZhdGUgdmlzaWJpbGl0eVNlcnZpY2U6IEJhc2VWaXNpYmlsaXR5U2VydmljZSxcclxuICAgIHByaXZhdGUgbmdab25lOiBOZ1pvbmVcclxuICApIHtcclxuICAgIHRoaXMuY29uZmlnID0gY29uZmlnO1xyXG5cclxuICAgIC8vIFRPRE86IG9ubHkgZm9yIGRldiFcclxuICAgIGlmICghIXRoaXMuZ2V0Q3Vyc29yUG9zaXRpb25CdXR0b24gJiZcclxuICAgICAgKGRvY3VtZW50LmxvY2F0aW9uLmhyZWYuaW5kZXhPZignZGV2JykgIT09IC0xIHx8IGRvY3VtZW50LmxvY2F0aW9uLmhyZWYuaW5kZXhPZignbG9jYWxob3N0JykgIT09IC0xKSkge1xyXG4gICAgICB0aGlzLmludGVydmFsQ3Vyc29yUG9pbnRlclBvc2l0aW9uID0gc2V0SW50ZXJ2YWwoKCkgPT4ge1xyXG4gICAgICAgIGlmICghdGhpcy5wb3NlTWF0dGVycG9ydCkge1xyXG4gICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgY29uc3QgbmV4dFNob3cgPSB0aGlzLnBvc2VNYXR0ZXJwb3J0LnRpbWUgKyAxMDAwO1xyXG4gICAgICAgIGlmIChuZXcgRGF0ZSgpLmdldFRpbWUoKSA+IG5leHRTaG93KSB7XHJcbiAgICAgICAgICBpZiAodGhpcy5jdXJzb3JQb3NpdGlvbkJ1dHRvbkRpc3BsYXllZCkge1xyXG4gICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgY29uc3Qgc2l6ZSA9IHtcclxuICAgICAgICAgICAgdzogdGhpcy5jb250YWluZXIuY2xpZW50V2lkdGgsXHJcbiAgICAgICAgICAgIGg6IHRoaXMuY29udGFpbmVyLmNsaWVudEhlaWdodCxcclxuICAgICAgICAgIH07XHJcbiAgICAgICAgICBjb25zdCBjb29yZCA9IHRoaXMuc2RrLkNvbnZlcnNpb24ud29ybGRUb1NjcmVlbih0aGlzLnBvc2VNYXR0ZXJwb3J0LnBvc2l0aW9uLCB0aGlzLnBvc2VDYW1lcmEsIHNpemUpO1xyXG4gICAgICAgICAgdGhpcy5nZXRDdXJzb3JQb3NpdGlvbkJ1dHRvbi5zdHlsZS5sZWZ0ID0gYCR7Y29vcmQueCAtIDI1fXB4YDtcclxuICAgICAgICAgIHRoaXMuZ2V0Q3Vyc29yUG9zaXRpb25CdXR0b24uc3R5bGUudG9wID0gYCR7Y29vcmQueSAtIDIyfXB4YDtcclxuICAgICAgICAgIHRoaXMuZ2V0Q3Vyc29yUG9zaXRpb25CdXR0b24uc3R5bGUuZGlzcGxheSA9ICdibG9jayc7XHJcbiAgICAgICAgICAvLyB0aGlzLnRleHREaXNwbGF5Q3Vyc29yUG9zaXRpb25QYW5lbC5zdHlsZS5kaXNwbGF5ID0gJ25vbmUnO1xyXG4gICAgICAgICAgdGhpcy5jdXJzb3JQb3NpdGlvbkJ1dHRvbkRpc3BsYXllZCA9IHRydWU7XHJcbiAgICAgICAgfVxyXG4gICAgICB9LCA1MDApO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogSW5pdGlhbGl6ZXMgTWF0dGVycG9ydCBhbmQgYWxsIGxpc3RlbmVycy9kYXRhXHJcbiAgICogQHBhcmFtIHRhZ1NlcnZpY2UgQmFzZVRhZ1NlcnZpY2UgKHRvIGluamVjdCBodG1sKVxyXG4gICAqIEBwYXJhbSBtb2R1bGUgU3BNb2R1bGUgKE11c2V1bSwgSW1tbykgdG8gc3Vic2NyaWJlIG9ubHkgdG8gbmVlZGVkIGZ1bmN0aW9ubm5hbGl0aWVzXHJcbiAgICogQHJldHVybnMgYm9vbGVhblxyXG4gICAqL1xyXG4gIGFzeW5jIGluaXRTZGsoXHJcbiAgICB0YWdTZXJ2aWNlOiBCYXNlVGFnU2VydmljZSxcclxuICAgIG1vZHVsZTogU3BNb2R1bGUgPSBTcE1vZHVsZS5JTU1PXHJcbiAgKTogUHJvbWlzZTxib29sZWFuPiB7XHJcbiAgICBpZiAodGhpcy5zZGspIHtcclxuICAgICAgLy8gY2xlYW4gaWYgc2RrIGlzIHJ1bm5pbmcgYWxyZWFkeVxyXG4gICAgICBhd2FpdCB0aGlzLmFjdGlvbl9kZWxldGVfYWxsX21hdHRlcnRhZ3MoKTtcclxuICAgIH1cclxuICAgIHRoaXMudGFnU2VydmljZSA9IHRhZ1NlcnZpY2U7XHJcbiAgICB0aGlzLlNQTW9kdWxlID0gbW9kdWxlO1xyXG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcclxuICAgICAgLy8gUmV0cmlldmUgRE9NIGVsZW1lbnRzXHJcbiAgICAgIHRoaXMucG9pbnRlckJ1dHRvbiA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoXHJcbiAgICAgICAgJyN2aWV3ZXItcG9pbnRlci10cmljaydcclxuICAgICAgKSBhcyBIVE1MRWxlbWVudDtcclxuICAgICAgdGhpcy5jb250YWluZXIgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKCcjdmlld2VyLW1vZHVsZScpIGFzIEhUTUxFbGVtZW50O1xyXG4gICAgICBjb25zdCBpZnJhbWUgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKFxyXG4gICAgICAgICcjdmlld2VyLW1vZHVsZSdcclxuICAgICAgKSBhcyBIVE1MSUZyYW1lRWxlbWVudDtcclxuICAgICAgaWYgKCFpZnJhbWUpIHtcclxuICAgICAgICByZXR1cm47XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIC8vIEFkZCBsaXN0ZW5lcnNcclxuICAgICAgaWYgKHRoaXMucG9pbnRlckJ1dHRvbikge1xyXG4gICAgICAgIHRoaXMucG9pbnRlckJ1dHRvbi5hZGRFdmVudExpc3RlbmVyKFxyXG4gICAgICAgICAgJ2NsaWNrJyxcclxuICAgICAgICAgIHRoaXMucG9pbnRlckxlZnRDbGlja0hhbmRsZXJcclxuICAgICAgICApO1xyXG4gICAgICAgIC8vIGNhbmNlbCBvbiByaWdodCBjbGlja1xyXG4gICAgICAgIHRoaXMucG9pbnRlckJ1dHRvbi5hZGRFdmVudExpc3RlbmVyKFxyXG4gICAgICAgICAgJ2NvbnRleHRtZW51JyxcclxuICAgICAgICAgIHRoaXMucG9pbnRlclJpZ2h0Q2xpY2tIYW5kbGVyXHJcbiAgICAgICAgKTtcclxuICAgICAgfVxyXG4gICAgICAvLyBSZXRyaWV2ZSBET00gZWxlbWVudHNcclxuICAgICAgdGhpcy5nZXRDdXJzb3JQb3NpdGlvbkJ1dHRvbiA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoXHJcbiAgICAgICAgJyNidXR0b24nXHJcbiAgICAgICkgYXMgSFRNTEVsZW1lbnQ7XHJcbiAgICAgIHRoaXMudGV4dERpc3BsYXlDdXJzb3JQb3NpdGlvblBhbmVsID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvcihcclxuICAgICAgICAnI3RleHQnXHJcbiAgICAgICkgYXMgSFRNTEVsZW1lbnQ7XHJcbiAgICAgIGlmICh0aGlzLmdldEN1cnNvclBvc2l0aW9uQnV0dG9uKSB7XHJcbiAgICAgICAgLy8gZ2V0IHBvc2l0aW9uIG9uIE1hdHRlcnBvcnQgXCJtb2RlbFwiIG9uIG1pZGRsZSBjbGlja1xyXG4gICAgICAgIHRoaXMuZ2V0Q3Vyc29yUG9zaXRpb25CdXR0b24uYWRkRXZlbnRMaXN0ZW5lcihcclxuICAgICAgICAgICdjbGljaycsXHJcbiAgICAgICAgICB0aGlzLnBvaW50ZXJNaWRkbGVDbGlja0hhbmRsZXJcclxuICAgICAgICApO1xyXG4gICAgICB9XHJcblxyXG4gICAgICAvLyBMb2FkIFNES1xyXG4gICAgICBjb25zb2xlLmxvZygnTG9hZGluZyBNYXR0ZXJwb3J0IFNESycpO1xyXG4gICAgICBjb25zdCBzaG93Y2FzZVdpbmRvdyA9IGlmcmFtZS5jb250ZW50V2luZG93O1xyXG4gICAgICBpZnJhbWUuYWRkRXZlbnRMaXN0ZW5lcihcclxuICAgICAgICAnbG9hZCcsXHJcbiAgICAgICAgYXN5bmMgZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgdHJ5IHtcclxuICAgICAgICAgICAgdGhpcy5zZGsgPSBhd2FpdCBzaG93Y2FzZVdpbmRvdy5NUF9TREsuY29ubmVjdChcclxuICAgICAgICAgICAgICBzaG93Y2FzZVdpbmRvdyxcclxuICAgICAgICAgICAgICAncW45d3Nhc3V5NWgyZnpyYnJuMW56cjBpZCcsXHJcbiAgICAgICAgICAgICAgJzMuNSdcclxuICAgICAgICAgICAgKTtcclxuICAgICAgICAgIH0gY2F0Y2ggKGUpIHtcclxuICAgICAgICAgICAgY29uc29sZS5lcnJvcihlKTtcclxuICAgICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgICAgfVxyXG5cclxuICAgICAgICAgIC8vIExvYWQgTWF0dGVydGFnIGljb25zIGFuZCBjdXN0b20gc3Vic2NyaXB0aW9uc1xyXG4gICAgICAgICAgc3dpdGNoIChtb2R1bGUpIHtcclxuICAgICAgICAgICAgY2FzZSBTcE1vZHVsZS5JTU1POlxyXG4gICAgICAgICAgICAgIHRoaXMuc2RrLkFzc2V0LnJlZ2lzdGVyVGV4dHVyZShcclxuICAgICAgICAgICAgICAgICdpY29uLXRpY2tldCcsXHJcbiAgICAgICAgICAgICAgICB0aGlzLmNvbmZpZy5teV9jb25maWcuaWNvbl90aWNrZXRcclxuICAgICAgICAgICAgICApO1xyXG4gICAgICAgICAgICAgIHRoaXMuc2RrLkFzc2V0LnJlZ2lzdGVyVGV4dHVyZShcclxuICAgICAgICAgICAgICAgICdpY29uLWVxdWlwbWVudCcsXHJcbiAgICAgICAgICAgICAgICB0aGlzLmNvbmZpZy5teV9jb25maWcuaWNvbl9lcXVpcG1lbnRcclxuICAgICAgICAgICAgICApO1xyXG4gICAgICAgICAgICAgIHRoaXMuc2RrLkFzc2V0LnJlZ2lzdGVyVGV4dHVyZShcclxuICAgICAgICAgICAgICAgICdpY29uLW1lYXN1cmUnLFxyXG4gICAgICAgICAgICAgICAgdGhpcy5jb25maWcubXlfY29uZmlnLmljb25fbWVhc3VyZVxyXG4gICAgICAgICAgICAgICk7XHJcbiAgICAgICAgICAgICAgdGhpcy5zZGsuQXNzZXQucmVnaXN0ZXJUZXh0dXJlKFxyXG4gICAgICAgICAgICAgICAgJ2ljb24tZGF0YScsXHJcbiAgICAgICAgICAgICAgICB0aGlzLmNvbmZpZy5teV9jb25maWcuaWNvbl9kYXRhXHJcbiAgICAgICAgICAgICAgKTtcclxuICAgICAgICAgICAgICB0aGlzLnNkay5Bc3NldC5yZWdpc3RlclRleHR1cmUoXHJcbiAgICAgICAgICAgICAgICAnaWNvbi1vYmplY3QzZCcsXHJcbiAgICAgICAgICAgICAgICB0aGlzLmNvbmZpZy5teV9jb25maWcuaWNvbl9vYmplY3QzZFxyXG4gICAgICAgICAgICAgICk7XHJcblxyXG4gICAgICAgICAgICAgIHRoaXMuc2RrLk1lYXN1cmVtZW50cy5kYXRhLnN1YnNjcmliZSh7XHJcbiAgICAgICAgICAgICAgICBvbkFkZGVkOiBmdW5jdGlvbiAoXHJcbiAgICAgICAgICAgICAgICAgIGluZGV4OiBhbnksXHJcbiAgICAgICAgICAgICAgICAgIGl0ZW06IHsgcG9pbnRzOiBhbnkgfSxcclxuICAgICAgICAgICAgICAgICAgY29sbGVjdGlvbjogYW55XHJcbiAgICAgICAgICAgICAgICApIHtcclxuICAgICAgICAgICAgICAgICAgLy8gY29uc29sZS5sb2coXHJcbiAgICAgICAgICAgICAgICAgIC8vICAgICBcIml0ZW0gYWRkZWQgdG8gdGhlIGNvbGxlY3Rpb25cIixcclxuICAgICAgICAgICAgICAgICAgLy8gICAgIGluZGV4LFxyXG4gICAgICAgICAgICAgICAgICAvLyAgICAgaXRlbSxcclxuICAgICAgICAgICAgICAgICAgLy8gKTtcclxuICAgICAgICAgICAgICAgICAgLy8gdGhpcy5tZWFzdXJlbWVudHNbaW5kZXhdID0gaXRlbTtcclxuICAgICAgICAgICAgICAgICAgdGhpcy5sYXN0TWVhc3VyZSA9IGl0ZW0ucG9pbnRzO1xyXG4gICAgICAgICAgICAgICAgfS5iaW5kKHRoaXMpLFxyXG4gICAgICAgICAgICAgICAgb25Db2xsZWN0aW9uVXBkYXRlZDogZnVuY3Rpb24gKGNvbGxlY3Rpb246IGFueSkge1xyXG4gICAgICAgICAgICAgICAgICAvLyBjb25zb2xlLmxvZygndGhlIGVudGlyZSB1cC10by1kYXRlIGNvbGxlY3Rpb24nLCBjb2xsZWN0aW9uKTtcclxuICAgICAgICAgICAgICAgICAgdGhpcy5nZXREaXN0YW5jZUZvckxhc3RNZWFzdXJlbWVudCgpO1xyXG4gICAgICAgICAgICAgICAgfS5iaW5kKHRoaXMpLFxyXG4gICAgICAgICAgICAgIH0pO1xyXG4gICAgICAgICAgICAgIHRoaXMuc2RrLk1lYXN1cmVtZW50cy5tb2RlLnN1YnNjcmliZShcclxuICAgICAgICAgICAgICAgIGZ1bmN0aW9uIChtZWFzdXJlbWVudE1vZGVTdGF0ZTogeyBhY3RpdmU6IGFueSB9KSB7XHJcbiAgICAgICAgICAgICAgICAgIC8vIG1lYXN1cmVtZW50IG1vZGUgc3RhdGUgaGFzIGNoYW5nZWRcclxuICAgICAgICAgICAgICAgICAgdGhpcy5pc01lYXN1cmVNb2RlT24gPSBtZWFzdXJlbWVudE1vZGVTdGF0ZS5hY3RpdmU7XHJcbiAgICAgICAgICAgICAgICAgIC8vIGNvbnNvbGUubG9nKCdJcyBtZWFzdXJlbWVudCBtb2RlIGN1cnJlbnRseSBhY3RpdmU/ICcsIG1lYXN1cmVtZW50TW9kZVN0YXRlLmFjdGl2ZSk7XHJcbiAgICAgICAgICAgICAgICB9LmJpbmQodGhpcylcclxuICAgICAgICAgICAgICApO1xyXG4gICAgICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgICAgICBjYXNlIFNwTW9kdWxlLk1VU0VVTTpcclxuICAgICAgICAgICAgICB0aGlzLnNkay5Bc3NldC5yZWdpc3RlclRleHR1cmUoXHJcbiAgICAgICAgICAgICAgICAnaWNvbi1kYXRhJyxcclxuICAgICAgICAgICAgICAgIHRoaXMuY29uZmlnLm15X2NvbmZpZy5pY29uX2RhdGFcclxuICAgICAgICAgICAgICApO1xyXG4gICAgICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgICAgICBjYXNlIFNwTW9kdWxlLkhPVEVMOlxyXG4gICAgICAgICAgICAgIHRoaXMuc2RrLkFzc2V0LnJlZ2lzdGVyVGV4dHVyZShcclxuICAgICAgICAgICAgICAgICdpY29uX3Jvb21fYXZhaWxhYmxlJyxcclxuICAgICAgICAgICAgICAgIHRoaXMuY29uZmlnLm15X2NvbmZpZy5pY29uX3Jvb21fYXZhaWxhYmxlXHJcbiAgICAgICAgICAgICAgKTtcclxuICAgICAgICAgICAgICB0aGlzLnNkay5Bc3NldC5yZWdpc3RlclRleHR1cmUoXHJcbiAgICAgICAgICAgICAgICAnaWNvbl9yb29tX3VuYXZhaWxhYmxlJyxcclxuICAgICAgICAgICAgICAgIHRoaXMuY29uZmlnLm15X2NvbmZpZy5pY29uX3Jvb21fdW5hdmFpbGFibGVcclxuICAgICAgICAgICAgICApO1xyXG4gICAgICAgICAgICAgIHRoaXMuc2RrLkFzc2V0LnJlZ2lzdGVyVGV4dHVyZShcclxuICAgICAgICAgICAgICAgICdpY29uX3Jvb21fY2hvc2VuJyxcclxuICAgICAgICAgICAgICAgIHRoaXMuY29uZmlnLm15X2NvbmZpZy5pY29uX3Jvb21fY2hvc2VuXHJcbiAgICAgICAgICAgICAgKTtcclxuICAgICAgICAgICAgICB0aGlzLnNkay5Bc3NldC5yZWdpc3RlclRleHR1cmUoXHJcbiAgICAgICAgICAgICAgICAnaWNvbl9yb29tX3ZpZXdlZCcsXHJcbiAgICAgICAgICAgICAgICB0aGlzLmNvbmZpZy5teV9jb25maWcuaWNvbl9yb29tX3ZpZXdlZFxyXG4gICAgICAgICAgICAgICk7XHJcbiAgICAgICAgICAgICAgYnJlYWs7XHJcbiAgICAgICAgICAgIGRlZmF1bHQ6XHJcbiAgICAgICAgICAgICAgYnJlYWs7XHJcbiAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgdGhpcy5zZGsuQXNzZXQucmVnaXN0ZXJUZXh0dXJlKFxyXG4gICAgICAgICAgICAnaWNvbi1wb3NpdGlvbicsXHJcbiAgICAgICAgICAgIHRoaXMuY29uZmlnLm15X2NvbmZpZy5pY29uX3Bvc2l0aW9uXHJcbiAgICAgICAgICApO1xyXG5cclxuICAgICAgICAgIC8vIEN1cnJlbnQgUm9vbSAodXNlZCBmb3IgZ2V0dGluZyBib3VuZGluZyBib3ggYW5kIGV2ZW50dWFsbHkgbGF6eSBsb2FkIG1hdHRlcnRhZyBvciBvYmplY3QzRCBpbnNpZGUgY3VycmVudCBSb29tKVxyXG4gICAgICAgICAgdGhpcy5zZGsuUm9vbS5jdXJyZW50LnN1YnNjcmliZSgoY3VycmVudFJvb20pID0+IHtcclxuICAgICAgICAgICAgY29uc29sZS5sb2coYGhlbGxvIGN1cnJlbnQgUm9vbSAke0pTT04uc3RyaW5naWZ5KGN1cnJlbnRSb29tKX1gKTtcclxuICAgICAgICAgIH0pO1xyXG5cclxuICAgICAgICAgIC8vIDNEIHBvc2l0aW9uJ3MgcG9pbnRlclxyXG4gICAgICAgICAgdGhpcy5zZGsuUG9pbnRlci5pbnRlcnNlY3Rpb24uc3Vic2NyaWJlKFxyXG4gICAgICAgICAgICBmdW5jdGlvbiAoaW50ZXJzZWN0aW9uOiBhbnkpIHtcclxuICAgICAgICAgICAgICB0aGlzLnBvc2VNYXR0ZXJwb3J0ID0gaW50ZXJzZWN0aW9uO1xyXG4gICAgICAgICAgICAgIHRoaXMucG9zZU1hdHRlcnBvcnQudGltZSA9IG5ldyBEYXRlKCkuZ2V0VGltZSgpO1xyXG4gICAgICAgICAgICAgIGlmICghdGhpcy5vbGRQb3NlTWF0dGVycG9ydFBvc2l0aW9uKSB7XHJcbiAgICAgICAgICAgICAgICB0aGlzLm9sZFBvc2VNYXR0ZXJwb3J0UG9zaXRpb24gPSB7XHJcbiAgICAgICAgICAgICAgICAgIHg6IDAsXHJcbiAgICAgICAgICAgICAgICAgIHk6IDAsXHJcbiAgICAgICAgICAgICAgICAgIHo6IDAsXHJcbiAgICAgICAgICAgICAgICB9O1xyXG4gICAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgICAgaWYgKFxyXG4gICAgICAgICAgICAgICAgdGhpcy5pbnRlcmFjdGlvbk1vZGUgIT09IFZpZXdlckludGVyYWN0aW9ucy5ERUZBVUxUICYmXHJcbiAgICAgICAgICAgICAgICB0aGlzLm1hdHRlcnRhZ1RvRm9sbG93XHJcbiAgICAgICAgICAgICAgKSB7XHJcbiAgICAgICAgICAgICAgICAvLyBmb2xsb3cgdGhlIHBvaW50ZXIgYW5kIGNoYW5nZXMgdGhlIHBvc2l0aW9uIG9mIHRoZSBsYXN0IHRhZ1xyXG4gICAgICAgICAgICAgICAgLy8gKHdlIGFyZSBhYm91dCB0byB2YWxpZGF0ZSwgYnV0IGl0IGV4aXN0cyBpbiBzZGsgYWxyZWFkeSlcclxuICAgICAgICAgICAgICAgIHRoaXMuZW5hYmxlX2ZvbGxvd2luZ190YWcodGhpcy5tYXR0ZXJ0YWdUb0ZvbGxvdyk7XHJcbiAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgIGlmICghIXRoaXMuZ2V0Q3Vyc29yUG9zaXRpb25CdXR0b24gJiYgISF0aGlzLmdldEN1cnNvclBvc2l0aW9uQnV0dG9uLnN0eWxlICYmXHJcbiAgICAgICAgICAgICAgKGRvY3VtZW50LlVSTC5pbmRleE9mKCdodHRwczovL2Rldi5zbWFydGVycGxhbi5pbycpICE9PSAtMSB8fCBkb2N1bWVudC5sb2NhdGlvbi5ocmVmLmluZGV4T2YoJ2xvY2FsaG9zdCcpICE9PSAtMSkpIHtcclxuICAgICAgICAgICAgICAgIHRoaXMuZ2V0Q3Vyc29yUG9zaXRpb25CdXR0b24uc3R5bGUuZGlzcGxheSA9ICdub25lJztcclxuICAgICAgICAgICAgICAgIHRoaXMuY3Vyc29yUG9zaXRpb25CdXR0b25EaXNwbGF5ZWQgPSBmYWxzZTtcclxuICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH0uYmluZCh0aGlzKVxyXG4gICAgICAgICAgKTtcclxuXHJcbiAgICAgICAgICAvL0NhbWVyYSBtb2RlXHJcbiAgICAgICAgICB0aGlzLnNkay5Nb2RlLmN1cnJlbnQuc3Vic2NyaWJlKChtb2RlKSA9PiB7XHJcbiAgICAgICAgICAgIHRoaXMuaW5UcmFuc2l0aW9uU3dlZXAgPSBmYWxzZTtcclxuICAgICAgICAgICAgc3dpdGNoIChtb2RlKSB7XHJcbiAgICAgICAgICAgICAgY2FzZSAnbW9kZS5kb2xsaG91c2UnOlxyXG4gICAgICAgICAgICAgICAgdGhpcy5jdXJyZW50Q2FtZXJhTW9kZSA9IENhbWVyYU1vZGUuRE9MTEhPVVNFO1xyXG4gICAgICAgICAgICAgICAgYnJlYWs7XHJcbiAgICAgICAgICAgICAgY2FzZSAnbW9kZS5mbG9vcnBsYW4nOlxyXG4gICAgICAgICAgICAgICAgdGhpcy5jdXJyZW50Q2FtZXJhTW9kZSA9IENhbWVyYU1vZGUuRkxPT1JQTEFOO1xyXG4gICAgICAgICAgICAgICAgYnJlYWs7XHJcbiAgICAgICAgICAgICAgY2FzZSAnbW9kZS5pbnNpZGUnOlxyXG4gICAgICAgICAgICAgICAgdGhpcy5jdXJyZW50Q2FtZXJhTW9kZSA9IENhbWVyYU1vZGUuSU5TSURFO1xyXG4gICAgICAgICAgICAgICAgYnJlYWs7XHJcbiAgICAgICAgICAgICAgY2FzZSAnbW9kZS50cmFuc2l0aW9uaW5nJzpcclxuICAgICAgICAgICAgICAgIHRoaXMuY3VycmVudENhbWVyYU1vZGUgPSBDYW1lcmFNb2RlLlRSQU5TSVRJT05JTkc7XHJcbiAgICAgICAgICAgICAgICBicmVhaztcclxuICAgICAgICAgICAgICBkZWZhdWx0OlxyXG4gICAgICAgICAgICAgICAgdGhpcy5jdXJyZW50Q2FtZXJhTW9kZSA9IENhbWVyYU1vZGUuT1VUU0lERTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB0aGlzLm9uQ2FtZXJhTW9kZUNoYW5nZWQubmV4dCh0aGlzLmN1cnJlbnRDYW1lcmFNb2RlKTtcclxuICAgICAgICAgIH0pO1xyXG5cclxuICAgICAgICAgIC8vIENhbWVyYSdzIHZpZXdwb2ludFxyXG4gICAgICAgICAgdGhpcy5zZGsuQ2FtZXJhLnBvc2Uuc3Vic2NyaWJlKFxyXG4gICAgICAgICAgICBmdW5jdGlvbiBzdWJzY3IocG9zZTogYW55KSB7XHJcbiAgICAgICAgICAgICAgdGhpcy5wb3NlQ2FtZXJhID0gcG9zZTtcclxuXHJcbiAgICAgICAgICAgICAgdGhpcy5jdXJyZW50Q2FtZXJhUG9zZS5uZXh0KHBvc2UpO1xyXG4gICAgICAgICAgICAgIC8vIGNvbnNvbGUubG9nKCdDdXJyZW50IHBvc2l0aW9uIGlzICcsIHBvc2UucG9zaXRpb24pO1xyXG4gICAgICAgICAgICAgIC8vIGNvbnNvbGUubG9nKCdSb3RhdGlvbiBhbmdsZSBpcyAnLCBwb3NlLnJvdGF0aW9uKTtcclxuICAgICAgICAgICAgICAvLyBjb25zb2xlLmxvZyhcIlN3ZWVwIFVVSUQgaXNcIiwgcG9zZS5zd2VlcCk7XHJcbiAgICAgICAgICAgIH0uYmluZCh0aGlzKVxyXG4gICAgICAgICAgKTtcclxuXHJcbiAgICAgICAgICAvLyBzdWJzY3JpYmUgdG8gc3dlZXBzXHJcbiAgICAgICAgICB0aGlzLnNkay5Td2VlcC5kYXRhLnN1YnNjcmliZSh7XHJcbiAgICAgICAgICAgIG9uQ29sbGVjdGlvblVwZGF0ZWQ6IGZ1bmN0aW9uIHN1YnNjcihjb2xsZWN0aW9uOiB7fSkge1xyXG4gICAgICAgICAgICAgIC8vIGNvbnNvbGUubG9nKFwiU3dlZXAgY29sbGVjdGlvbiB1cGRhdGVkXCIpO1xyXG4gICAgICAgICAgICAgIHRoaXMuc3dlZXBzID0gT2JqZWN0LmtleXMoY29sbGVjdGlvbik7XHJcbiAgICAgICAgICAgIH0uYmluZCh0aGlzKSxcclxuICAgICAgICAgIH0pO1xyXG5cclxuICAgICAgICAgIC8vIHN1YnNjcmliZSB0byBjdXJyZW50IHN3ZWVwXHJcbiAgICAgICAgICB0aGlzLnNkay5Td2VlcC5jdXJyZW50LnN1YnNjcmliZShcclxuICAgICAgICAgICAgZnVuY3Rpb24gc3Vic2NyKGN1cnJlbnRTd2VlcDogeyBzaWQ6IHN0cmluZyB9KSB7XHJcbiAgICAgICAgICAgICAgLy8gQ2hhbmdlIHRvIHRoZSBjdXJyZW50IHN3ZWVwIGhhcyBvY2N1cnJlZC5cclxuICAgICAgICAgICAgICBpZiAoY3VycmVudFN3ZWVwLnNpZCA9PT0gJycpIHtcclxuICAgICAgICAgICAgICAgIC8vIGNvbnNvbGUubG9nKCdOb3QgY3VycmVudGx5IHN0YXRpb25lZCBhdCBhIHN3ZWVwIHBvc2l0aW9uJyk7XHJcbiAgICAgICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgICAgIC8vIGNvbnNvbGUubG9nKFwiZW1taXRpbmcgc3dlZXBcIiwgY3VycmVudFN3ZWVwLnNpZCk7XHJcbiAgICAgICAgICAgICAgICB0aGlzLmN1cnJlbnRTd2VlcC5uZXh0KGN1cnJlbnRTd2VlcC5zaWQpO1xyXG4gICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfS5iaW5kKHRoaXMpXHJcbiAgICAgICAgICApO1xyXG5cclxuICAgICAgICAgIC8vIFN1YnNjcmliZSB0byBGbG9vciBkYXRhXHJcbiAgICAgICAgICB0aGlzLnNkay5GbG9vci5kYXRhLnN1YnNjcmliZSh7XHJcbiAgICAgICAgICAgIG9uQ29sbGVjdGlvblVwZGF0ZWQ6IGZ1bmN0aW9uIHVwZCh0aGlzOiBhbnksIGNvbGxlY3Rpb246IGFueSkge1xyXG4gICAgICAgICAgICAgIHRoaXMuZmxvb3JzID0gT2JqZWN0LnZhbHVlcyhjb2xsZWN0aW9uKTtcclxuICAgICAgICAgICAgfS5iaW5kKHRoaXMpLFxyXG4gICAgICAgICAgfSk7XHJcblxyXG4gICAgICAgICAgLy8gb24gdGFnIGNsaWNrIG9wZW4gZGV0YWlscyBwYWdlXHJcbiAgICAgICAgICB0aGlzLnNkay5vbigndGFnLmNsaWNrJywgKHNpZDogc3RyaW5nKSA9PiB7XHJcbiAgICAgICAgICAgIC8vIGdldCBvYmplY3Qgb2YgdGhpcyB0YWdcclxuICAgICAgICAgICAgdHJ5IHtcclxuICAgICAgICAgICAgICBjb25zdCBtYXR0ZXJ0YWdEYXRhID0gdGhpcy5kaWN0aW9ubmFyeVRhZ3MuZ2V0KHNpZCk7XHJcbiAgICAgICAgICAgICAgaWYgKCFtYXR0ZXJ0YWdEYXRhKXtcclxuICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKCdubyBtYXR0ZXJ0YWdEYXRhIHRvIGRpc3BsYXknKTtcclxuICAgICAgICAgICAgICAgIHJldHVybjtcclxuICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgY29uc3QgdXJsID0gdGFnU2VydmljZS5nZXRVcmxGb3JTZWVEZXRhaWxzKFxyXG4gICAgICAgICAgICAgICAgbWF0dGVydGFnRGF0YS5nZXRPYmplY3QoKSxcclxuICAgICAgICAgICAgICAgIG1hdHRlcnRhZ0RhdGEuZ2V0VHlwZSgpXHJcbiAgICAgICAgICAgICAgKTtcclxuICAgICAgICAgICAgICBpZiAodXJsICE9PSAnJykge1xyXG4gICAgICAgICAgICAgICAgdGhpcy52aXNpYmlsaXR5U2VydmljZS5kZXRhaWxTaG93aW5nLm5leHQodHJ1ZSk7XHJcbiAgICAgICAgICAgICAgICB0aGlzLm5nWm9uZS5ydW4oKCkgPT4ge1xyXG4gICAgICAgICAgICAgICAgICB0aGlzLnJvdXRlci5uYXZpZ2F0ZShbdXJsXSk7XHJcbiAgICAgICAgICAgICAgICB9KTtcclxuICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH0gY2F0Y2gge1xyXG4gICAgICAgICAgICAgIGNvbnNvbGUubG9nKCdDYW5ub3Qgc2hvdyBkZXRhaWxzIGZvciB0YWcnKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgfSk7XHJcblxyXG4gICAgICAgICAgLy8gUG9pbnRlciB0cmlja1xyXG4gICAgICAgICAgLy8gQ3JlYXRlIGEgZGl2IHRoYXQgd2lsbCBhcHBlYXIgd2hlbiB0aGUgY3Vyc29yIGlzIHN0aWxsXHJcbiAgICAgICAgICAvLyBJdCB3aWxsIGludGVyY2VwdCB0aGUgY2xpY2sgb2YgdGhlIG1vdXNlIGJlZm9yZSBpdCB0cmlnZXJyaW5nIHRoZSBNYXR0ZXJwb3J0J3MgdG91ciBuYXZpZ2F0aW9uXHJcbiAgICAgICAgICB0aGlzLnRpbWVyUG9pbnRlciA9IHNldEludGVydmFsKFxyXG4gICAgICAgICAgICB0aGlzLnVwZGF0ZVBvaW50ZXJUcmljay5iaW5kKHRoaXMpLFxyXG4gICAgICAgICAgICA1MFxyXG4gICAgICAgICAgKTtcclxuXHJcbiAgICAgICAgICAvKipcclxuICAgICAgICAgICAqIFRyYW5zaXRpb25zXHJcbiAgICAgICAgICAgKi9cclxuICAgICAgICAgIHRoaXMuc2RrLm9uKFxyXG4gICAgICAgICAgICAndmlld21vZGUuY2hhbmdlc3RhcnQnLFxyXG4gICAgICAgICAgICBmdW5jdGlvbiAodG8sIGZyb20pIHtcclxuICAgICAgICAgICAgICAvLyBjb25zb2xlLmxvZygnU3RhcnRpbmcgdG8gbW92ZSB0byAnICsgdG8gKyAnIGZyb20gJyArIGZyb20pO1xyXG4gICAgICAgICAgICAgIHRoaXMuaW5UcmFuc2l0aW9uTW9kZSA9IHRydWU7XHJcbiAgICAgICAgICAgIH0uYmluZCh0aGlzKVxyXG4gICAgICAgICAgKTtcclxuXHJcbiAgICAgICAgICB0aGlzLnNkay5vbihcclxuICAgICAgICAgICAgJ3ZpZXdtb2RlLmNoYW5nZWVuZCcsXHJcbiAgICAgICAgICAgIGZ1bmN0aW9uIChvbGRNb2RlLCBuZXdNb2RlKSB7XHJcbiAgICAgICAgICAgICAgLy8gY29uc29sZS5sb2coJ0VuZGVkIHRvIG1vdmUgdG8gJyArIG5ld01vZGUgKyAnIGZyb20gJyArIG9sZE1vZGUpO1xyXG4gICAgICAgICAgICAgIGlmIChuZXdNb2RlICE9PSAnbW9kZS50cmFuc2l0aW9uaW5nJykge1xyXG4gICAgICAgICAgICAgICAgdGhpcy5pblRyYW5zaXRpb25Nb2RlID0gZmFsc2U7XHJcbiAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB9LmJpbmQodGhpcylcclxuICAgICAgICAgICk7XHJcblxyXG4gICAgICAgICAgdGhpcy5zZGsub24oXHJcbiAgICAgICAgICAgIHRoaXMuc2RrLlN3ZWVwLkV2ZW50LkVOVEVSLFxyXG4gICAgICAgICAgICBmdW5jdGlvbiAob2xkU3dlZXAsIG5ld1N3ZWVwKSB7XHJcbiAgICAgICAgICAgICAgLy8gY29uc29sZS5sb2coJ0xlYXZpbmcgc3dlZXAgJyArIG9sZFN3ZWVwKTtcclxuICAgICAgICAgICAgICAvLyBjb25zb2xlLmxvZygnRW50ZXJpbmcgc3dlZXAgJyArIG5ld1N3ZWVwKTtcclxuICAgICAgICAgICAgICB0aGlzLmluVHJhbnNpdGlvblN3ZWVwID0gZmFsc2U7XHJcbiAgICAgICAgICAgICAgdGhpcy5kaXNwbGF5QXppbXV0YWxDcm93bigpO1xyXG4gICAgICAgICAgICB9LmJpbmQodGhpcylcclxuICAgICAgICAgICk7XHJcbiAgICAgICAgICB0aGlzLnNkay5vbihcclxuICAgICAgICAgICAgdGhpcy5zZGsuU3dlZXAuRXZlbnQuRVhJVCxcclxuICAgICAgICAgICAgZnVuY3Rpb24gKGZyb21Td2VlcCwgdG9Td2VlcCkge1xyXG4gICAgICAgICAgICAgIC8vICAgY29uc29sZS5sb2coJ0xlYXZpbmcgc3dlZXAgJyArIGZyb21Td2VlcCk7XHJcbiAgICAgICAgICAgICAgLy8gICBjb25zb2xlLmxvZygnVHJhbnNpdGlvbmluZyB0byBzd2VlcCAnICsgdG9Td2VlcCk7XHJcbiAgICAgICAgICAgICAgdGhpcy5pblRyYW5zaXRpb25Td2VlcCA9IHRydWU7XHJcbiAgICAgICAgICAgIH0uYmluZCh0aGlzKVxyXG4gICAgICAgICAgKTtcclxuXHJcbiAgICAgICAgICAvLyBUT0RPOiBnZXQgc2NlbmUgd2l0aCBnZXR0ZXIgaW5zdGVhZCFcclxuICAgICAgICAgIGNvbnN0IFtzY2VuZU9iamVjdF0gPSBhd2FpdCB0aGlzLnNkay5TY2VuZS5jcmVhdGVPYmplY3RzKDEpO1xyXG4gICAgICAgICAgY29uc3Qgbm9kZSA9IHNjZW5lT2JqZWN0LmFkZE5vZGUoKTtcclxuICAgICAgICAgIG5vZGUuc3RhcnQoKTtcclxuICAgICAgICAgIHRoaXMudGhyZWVKU1NjZW5lID0gbm9kZS5vYmozRC5wYXJlbnQ7XHJcblxyXG4gICAgICAgICAgLy8gYXdhaXQgdGhpcy5zZGsuU2NlbmUuY29uZmlndXJlKChyZW5kZXJlcjogYW55LCB0aHJlZTogYW55KSA9PiB7XHJcbiAgICAgICAgICAvLyAgIHJlbmRlcmVyLnBoeXNpY2FsbHlDb3JyZWN0TGlnaHRzID0gdHJ1ZTtcclxuICAgICAgICAgIC8vICAgcmVuZGVyZXIub3V0cHV0RW5jb2RpbmcgPSB0aHJlZS5zUkdCRW5jb2Rpbmc7XHJcbiAgICAgICAgICAvLyAgIHJlbmRlcmVyLnNoYWRvd01hcC5lbmFibGVkID0gdHJ1ZTtcclxuICAgICAgICAgIC8vICAgcmVuZGVyZXIuc2hhZG93TWFwLmJpYXMgPSAwLjAwMDE7XHJcbiAgICAgICAgICAvLyAgIHJlbmRlcmVyLnNoYWRvd01hcC50eXBlID0gdGhyZWUuUENGU29mdFNoYWRvd01hcDtcclxuICAgICAgICAgIC8vIH0pO1xyXG5cclxuXHJcbiAgICAgICAgICAvLyBUT0RPOiB3YWl0IGZvciBNUCB0aWNrZXQgcmVzb2x1dGlvbiBiZWZvcmUgZGVjb21tZW50IHRoZXNlIVxyXG4gICAgICAgICAgLy8gV2FpdCB1bnRpbCBTaG93Y2FzZSBpcyBhY3R1YWxseSBwbGF5aW5nLi4uLlxyXG4gICAgICAgICAgLy8gdGhpcy5zZGsuVGFnLmRhdGEuc3Vic2NyaWJlKHtcclxuICAgICAgICAgIC8vICAgb25BZGRlZDogYXN5bmMgZnVuY3Rpb24gKGluZGV4LCBpdGVtLCBjb2xsZWN0aW9uKSB7XHJcbiAgICAgICAgICAvL1xyXG4gICAgICAgICAgLy8gICAgIGxldCB0aGlzT3BhY2l0eSA9IDAuMjtcclxuICAgICAgICAgIC8vICAgICB0aGlzLnNkay5UYWcuZWRpdE9wYWNpdHkoaW5kZXgsIHRoaXNPcGFjaXR5KTtcclxuICAgICAgICAgIC8vXHJcbiAgICAgICAgICAvLyAgICAgbGV0IHNvdXJjZSA9IG51bGw7XHJcbiAgICAgICAgICAvLyAgICAgdHJ5IHtcclxuICAgICAgICAgIC8vICAgICAgIHNvdXJjZSA9IGF3YWl0IFByb21pc2UuYWxsKFtcclxuICAgICAgICAgIC8vICAgICAgICAgdGhpcy5zZGsuU2Vuc29yLmNyZWF0ZVNvdXJjZSh0aGlzLnNkay5TZW5zb3IuU291cmNlVHlwZS5TUEhFUkUsIHtcclxuICAgICAgICAgIC8vICAgICAgICAgICBvcmlnaW46IGl0ZW0uYW5jaG9yUG9zaXRpb24sXHJcbiAgICAgICAgICAvLyAgICAgICAgICAgcmFkaXVzOiBOdW1iZXIoMyksXHJcbiAgICAgICAgICAvLyAgICAgICAgICAgdXNlckRhdGE6IHtcclxuICAgICAgICAgIC8vICAgICAgICAgICAgIGlkOiBpbmRleCArICctc3BoZXJlLXNvdXJjZScsXHJcbiAgICAgICAgICAvLyAgICAgICAgICAgfSxcclxuICAgICAgICAgIC8vICAgICAgICAgfSlcclxuICAgICAgICAgIC8vICAgICAgIF0pO1xyXG4gICAgICAgICAgLy8gICAgIH0gY2F0Y2ggKGUpIHtcclxuICAgICAgICAgIC8vICAgICAgIGNvbnNvbGUubG9nKCdjb3VsZCBub3QgY3JlYXRlIFNwaGVyZSBzZW5zb3InKVxyXG4gICAgICAgICAgLy8gICAgICAgY29uc29sZS5lcnJvcihlKTtcclxuICAgICAgICAgIC8vICAgICB9XHJcbiAgICAgICAgICAvLyAgICAgaWYgKCFzb3VyY2UpIHtcclxuICAgICAgICAgIC8vICAgICAgIHJldHVybjtcclxuICAgICAgICAgIC8vICAgICB9XHJcbiAgICAgICAgICAvL1xyXG4gICAgICAgICAgLy8gICAgIGxldCBzZW5zb3IgPSBudWxsO1xyXG4gICAgICAgICAgLy8gICAgIHRyeSB7XHJcbiAgICAgICAgICAvLyAgICAgICBzZW5zb3IgPSBhd2FpdCB0aGlzLnNkay5TZW5zb3IuY3JlYXRlU2Vuc29yKHRoaXMuc2RrLlNlbnNvci5TZW5zb3JUeXBlLkNBTUVSQSk7XHJcbiAgICAgICAgICAvLyAgICAgfSBjYXRjaCAoZSkge1xyXG4gICAgICAgICAgLy8gICAgICAgY29uc29sZS5sb2coJ2NvdWxkIG5vdCBjcmVhdGUgQ2FtZXJhIHNlbnNvcicpXHJcbiAgICAgICAgICAvLyAgICAgICBjb25zb2xlLmVycm9yKGUpO1xyXG4gICAgICAgICAgLy8gICAgIH1cclxuICAgICAgICAgIC8vICAgICBpZiAoIXNlbnNvcikge1xyXG4gICAgICAgICAgLy8gICAgICAgcmV0dXJuO1xyXG4gICAgICAgICAgLy8gICAgIH1cclxuICAgICAgICAgIC8vXHJcbiAgICAgICAgICAvLyAgICAgc2Vuc29yLmFkZFNvdXJjZSguLi5zb3VyY2UpO1xyXG4gICAgICAgICAgLy8gICAgIHNlbnNvci5yZWFkaW5ncy5zdWJzY3JpYmUoe1xyXG4gICAgICAgICAgLy8gICAgICAgb25VcGRhdGVkKHNvdXJjZSwgcmVhZGluZykge1xyXG4gICAgICAgICAgLy8gICAgICAgICBjb25zb2xlLmxvZyh0aGlzT3BhY2l0eSk7XHJcbiAgICAgICAgICAvLyAgICAgICAgIGxldCBvbGRPcGFjaXR5ID0gdGhpc09wYWNpdHk7XHJcbiAgICAgICAgICAvLyAgICAgICAgIGlmIChyZWFkaW5nLmluUmFuZ2UpIHtcclxuICAgICAgICAgIC8vICAgICAgICAgICB0aGlzT3BhY2l0eSA9IDE7XHJcbiAgICAgICAgICAvLyAgICAgICAgICAgY29uc29sZS5sb2coaW5kZXggKyAnIGlzIGluUmFuZ2UnKTtcclxuICAgICAgICAgIC8vICAgICAgICAgfSBlbHNlIGlmIChyZWFkaW5nLmluVmlldykge1xyXG4gICAgICAgICAgLy8gICAgICAgICAgIGNvbnNvbGUubG9nKGluZGV4ICsgJyBpcyBpblZpZXcgYnV0IG5vdCBpblJhbmdlJyk7XHJcbiAgICAgICAgICAvLyAgICAgICAgICAgdGhpc09wYWNpdHkgPSAwLjU7XHJcbiAgICAgICAgICAvLyAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAvLyAgICAgICAgICAgdGhpc09wYWNpdHkgPSAwLjI7XHJcbiAgICAgICAgICAvLyAgICAgICAgICAgY29uc29sZS5sb2coaW5kZXggKyAnIGlzIG5vdCBpblZpZXcgb3IgaW5SYW5nZScpO1xyXG4gICAgICAgICAgLy8gICAgICAgICB9XHJcbiAgICAgICAgICAvL1xyXG4gICAgICAgICAgLy8gICAgICAgICB0aGlzLnNkay5UYWcuZWRpdE9wYWNpdHkoaW5kZXgsIHRoaXNPcGFjaXR5KTtcclxuICAgICAgICAgIC8vICAgICAgICAgLypcclxuICAgICAgICAgIC8vICAgICAgICAgICAgICAgICAgIGxldCBpbmMgPSAwLjAxO1xyXG4gICAgICAgICAgLy8gICAgICAgICAgICAgICAgICAgaWYgKG9sZE9wYWNpdHkgPiB0aGlzT3BhY2l0eSkge1xyXG4gICAgICAgICAgLy8gICAgICAgICAgICAgICAgICAgICBpbmMgPSAtMC4wMTtcclxuICAgICAgICAgIC8vICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgIC8vXHJcbiAgICAgICAgICAvLyAgICAgICAgICAgICAgICAgICBmb3IodmFyIGkgPSBvbGRPcGFjaXR5OyBpICE9IHRoaXNPcGFjaXR5OyBpPWkraW5jKSB7XHJcbiAgICAgICAgICAvLyAgICAgICAgICAgICAgICAgICAgICAgc2V0VGltZW91dChmdW5jdGlvbigpIHtcclxuICAgICAgICAgIC8vICAgICAgICAgICAgICAgICAgICAgICAgICBtcFNkay5UYWcuZWRpdE9wYWNpdHkoaW5kZXgsIGkpO1xyXG4gICAgICAgICAgLy8gICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKCdEZWxheScsIGkpO1xyXG4gICAgICAgICAgLy8gICAgICAgICAgICAgICAgICAgICAgIH0sMTApO1xyXG4gICAgICAgICAgLy8gICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgLy8gICAgICAgICAqL1xyXG4gICAgICAgICAgLy8gICAgICAgfVxyXG4gICAgICAgICAgLy8gICAgIH0pO1xyXG4gICAgICAgICAgLy8gICAgIC8vc2Vuc29yLnNob3dEZWJ1Zyh0cnVlKTtcclxuICAgICAgICAgIC8vICAgfS5iaW5kKHRoaXMpLFxyXG4gICAgICAgICAgLy8gICBvbkNvbGxlY3Rpb25VcGRhdGVkOiBmdW5jdGlvbiAoY29sbGVjdGlvbikge1xyXG4gICAgICAgICAgLy8gICAgIGNvbnNvbGUubG9nKCdDb2xsZWN0aW9uIHJlY2VpdmVkLiBUaGVyZSBhcmUgJywgT2JqZWN0LmtleXMoY29sbGVjdGlvbikubGVuZ3RoLCAnIFRhZ3MgaW4gdGhlIGNvbGxlY3Rpb24nLCBjb2xsZWN0aW9uKTtcclxuICAgICAgICAgIC8vICAgfVxyXG4gICAgICAgICAgLy8gfSk7XHJcblxyXG4gICAgICAgICAgcmVzb2x2ZSh0cnVlKTtcclxuICAgICAgICB9LmJpbmQodGhpcylcclxuICAgICAgKTtcclxuICAgIH0pO1xyXG4gIH1cclxuXHJcblxyXG4gIHNldExpZ2h0aW5nT2ZmKCkge1xyXG4gICAgdGhpcy5ub0xpZ2h0Rm9yT2JqZWN0cyA9IHRydWU7XHJcbiAgfVxyXG5cclxuICBwb2ludFRvU3RyaW5nKHBvaW50OiB7IHg6IG51bWJlciwgeTogbnVtYmVyLCB6OiBudW1iZXIgfSk6IHN0cmluZyB7XHJcbiAgICB2YXIgeCA9IHBvaW50LngudG9GaXhlZCgzKTtcclxuICAgIHZhciB5ID0gcG9pbnQueS50b0ZpeGVkKDMpO1xyXG4gICAgdmFyIHogPSBwb2ludC56LnRvRml4ZWQoMyk7XHJcblxyXG4gICAgcmV0dXJuIGB7IHg6ICR7eH0sIHk6ICR7eX0sIHo6ICR7en0gfWA7XHJcbiAgfVxyXG5cclxuICAvL1xyXG4gIC8vIC0tLS0tLS0tLS0gTWVhc3VyZW1lbnRzIHJlbGF0ZWQgLS0tLS0tLS0tLVxyXG4gIC8vXHJcbiAgLyoqXHJcbiAgICogQ2FsbGJhY2sgYWZ0ZXIgbWVhc3VyZW1lbnQgaXMgcGVyZm9ybWVkXHJcbiAgICovXHJcbiAgZ2V0RGlzdGFuY2VGb3JMYXN0TWVhc3VyZW1lbnQoKSB7XHJcbiAgICBpZiAodGhpcy5sYXN0TWVhc3VyZS5sZW5ndGggPiAwKSB7XHJcbiAgICAgIGNvbnN0IG51bWJlclBvaW50cyA9IHRoaXMubGFzdE1lYXN1cmUubGVuZ3RoO1xyXG4gICAgICB0aGlzLmRpc3RhbmNlc0xhc3RNZWFzdXJlID0gW107XHJcbiAgICAgIGZvciAobGV0IGluZGV4ID0gMTsgaW5kZXggPCBudW1iZXJQb2ludHM7IGluZGV4ICs9IDEpIHtcclxuICAgICAgICBjb25zdCBkaXN0YW5jZSA9IGdldERpc3RhbmNlQmV0d2VlblR3b1BvaW50cyhcclxuICAgICAgICAgIHRoaXMubGFzdE1lYXN1cmVbaW5kZXggLSAxXSxcclxuICAgICAgICAgIHRoaXMubGFzdE1lYXN1cmVbaW5kZXhdXHJcbiAgICAgICAgKTtcclxuICAgICAgICB0aGlzLmRpc3RhbmNlc0xhc3RNZWFzdXJlLnB1c2goZGlzdGFuY2UpO1xyXG4gICAgICB9XHJcbiAgICAgIHRoaXMudGFrZVNjcmVlblNob3QoKS50aGVuKChyZXMpID0+IHtcclxuICAgICAgICB0aGlzLnJvdXRlci5uYXZpZ2F0ZShbYHZpc2l0LyR7dGhpcy5jdXJyZW50U3BhY2VJRH0vYWRkX21lYXN1cmVtZW50YF0pO1xyXG4gICAgICB9KTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIGdldExhc3REaXN0YW5jZXMoKSB7XHJcbiAgICByZXR1cm4gdGhpcy5kaXN0YW5jZXNMYXN0TWVhc3VyZTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIFRha2VzIHNjcmVlbnNob3QgYW5kIHNhdmVzIGJhc2U2NCBpbiBsYXN0U2NyZWVuc2hvdFVyaVxyXG4gICAqIEByZXR1cm5zIFByb21pc2VcclxuICAgKi9cclxuICB0YWtlU2NyZWVuU2hvdCgpOiBQcm9taXNlPGFueT4ge1xyXG4gICAgcmV0dXJuIHRoaXMuc2RrLlJlbmRlcmVyLnRha2VTY3JlZW5TaG90KFxyXG4gICAgICB0aGlzLnJlc29sdXRpb24sXHJcbiAgICAgIHRoaXMudmlzaWJpbGl0eVxyXG4gICAgKS50aGVuKFxyXG4gICAgICBmdW5jdGlvbiAoc2NyZWVuU2hvdFVyaTogYW55KSB7XHJcbiAgICAgICAgLy8gYmFzZTY0IHN0cmluZ1xyXG4gICAgICAgIHRoaXMubGFzdFNjcmVlbnNob3RVcmkgPSBzY3JlZW5TaG90VXJpO1xyXG4gICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoKTtcclxuICAgICAgfS5iaW5kKHRoaXMpXHJcbiAgICApO1xyXG4gIH1cclxuXHJcbiAgZ2V0U2NyZWVuU2hvdFVyaSgpIHtcclxuICAgIHJldHVybiB0aGlzLmxhc3RTY3JlZW5zaG90VXJpO1xyXG4gIH1cclxuXHJcbiAgZ2V0TGFzdE1lYXN1cmVtZW50KCk6IE9iamVjdCB7XHJcbiAgICBjb25zdCBkYXRhID0ge1xyXG4gICAgICBtZWFzdXJlOiB0aGlzLmxhc3RNZWFzdXJlLFxyXG4gICAgICBzd2VlcDogdGhpcy5wb3NlQ2FtZXJhLnN3ZWVwLFxyXG4gICAgfTtcclxuICAgIHJldHVybiBkYXRhO1xyXG4gIH1cclxuXHJcbiAgLy9cclxuICAvLyAtLS0tLS0tLS0tIFV0aWxzIC0tLS0tLS0tLS1cclxuICAvL1xyXG4gIC8qKlxyXG4gICAqIFN0eWxpbmcgb2YgcG9pbnRlclxyXG4gICAqL1xyXG4gIHVwZGF0ZVBvaW50ZXJUcmljaygpIHtcclxuICAgIGlmIChcclxuICAgICAgdGhpcy5pbnRlcmFjdGlvbk1vZGUgIT09IFZpZXdlckludGVyYWN0aW9ucy5ERUZBVUxUICYmXHJcbiAgICAgIHRoaXMubWF0dGVydGFnVG9Gb2xsb3cgJiZcclxuICAgICAgdGhpcy5wb3NlTWF0dGVycG9ydCAmJlxyXG4gICAgICB0aGlzLmdldERpc3RQb3NpdGlvbihcclxuICAgICAgICB0aGlzLnBvc2VNYXR0ZXJwb3J0LnBvc2l0aW9uLFxyXG4gICAgICAgIHRoaXMub2xkUG9zZU1hdHRlcnBvcnRQb3NpdGlvblxyXG4gICAgICApID4gMjVcclxuICAgICkge1xyXG4gICAgICB0aGlzLnBvaW50ZXJCdXR0b24uc3R5bGUuZGlzcGxheSA9ICdub25lJztcclxuXHJcbiAgICAgIGNvbnN0IHNpemUgPSB7XHJcbiAgICAgICAgdzogdGhpcy5jb250YWluZXIuY2xpZW50V2lkdGgsXHJcbiAgICAgICAgaDogdGhpcy5jb250YWluZXIuY2xpZW50SGVpZ2h0LFxyXG4gICAgICB9O1xyXG4gICAgICBjb25zdCBjb29yZHMgPSB0aGlzLnNkay5Db252ZXJzaW9uLndvcmxkVG9TY3JlZW4oXHJcbiAgICAgICAgdGhpcy5wb3NlTWF0dGVycG9ydC5wb3NpdGlvbixcclxuICAgICAgICB0aGlzLnBvc2VDYW1lcmEsXHJcbiAgICAgICAgc2l6ZVxyXG4gICAgICApO1xyXG4gICAgICB0aGlzLnBvaW50ZXJCdXR0b24uc3R5bGUubGVmdCA9IGAke1xyXG4gICAgICAgIGNvb3Jkcy54ICogTWF0aC5zaWduKGNvb3Jkcy54KSAtIDI1XHJcbiAgICAgIH1weGA7XHJcbiAgICAgIHRoaXMucG9pbnRlckJ1dHRvbi5zdHlsZS50b3AgPSBgJHtjb29yZHMueSAqIE1hdGguc2lnbihjb29yZHMueCkgLSAyNX1weGA7XHJcbiAgICAgIHRoaXMub2xkUG9zZU1hdHRlcnBvcnRQb3NpdGlvbiA9IHtcclxuICAgICAgICAuLi50aGlzLnBvc2VNYXR0ZXJwb3J0LnBvc2l0aW9uLFxyXG4gICAgICB9O1xyXG4gICAgfSBlbHNlIHtcclxuICAgICAgdGhpcy5wb2ludGVyQnV0dG9uLnN0eWxlLmRpc3BsYXkgPSAnYmxvY2snO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogUmVhbHRpbWUgbWF0dGVydGFnIGZvbGxvd2luZyB0aGUgY3Vyc29yXHJcbiAgICogQHBhcmFtIG1hdHRlcnRhZyBzdHJpbmdcclxuICAgKi9cclxuICBlbmFibGVfZm9sbG93aW5nX3RhZyhtYXR0ZXJ0YWc6IHN0cmluZykge1xyXG4gICAgdGhpcy5zZGsuVGFnLmVkaXRQb3NpdGlvbihtYXR0ZXJ0YWcsIHtcclxuICAgICAgYW5jaG9yUG9zaXRpb246IHtcclxuICAgICAgICB4OiB0aGlzLnBvc2VNYXR0ZXJwb3J0LnBvc2l0aW9uLnggKiAxLFxyXG4gICAgICAgIHk6IHRoaXMucG9zZU1hdHRlcnBvcnQucG9zaXRpb24ueSAqIDEsXHJcbiAgICAgICAgejogdGhpcy5wb3NlTWF0dGVycG9ydC5wb3NpdGlvbi56ICogMSxcclxuICAgICAgfSxcclxuICAgICAgc3RlbVZlY3Rvcjoge1xyXG4gICAgICAgIHg6IHRoaXMucG9zZU1hdHRlcnBvcnQubm9ybWFsLnggKiAwLjMsXHJcbiAgICAgICAgeTogdGhpcy5wb3NlTWF0dGVycG9ydC5ub3JtYWwueSAqIDAuMyxcclxuICAgICAgICB6OiB0aGlzLnBvc2VNYXR0ZXJwb3J0Lm5vcm1hbC56ICogMC4zLFxyXG4gICAgICB9LFxyXG4gICAgfSk7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBHZXQgdGhlIGRpc3RhbmNlIGJldHd3ZWVuIHR3byAzRCBwb3NpdGlvbnNcclxuICAgKiBVc2VkIGluIG9yZGVyIHRvIHNlZSBob3cgbXVjaCB0aGUgY3Vyc29yIGhhcyBtb3ZlZCBmcm9tIHRoZSBwcmV2aW91cyBwb3NpdGlvblxyXG4gICAqIEBwYXJhbSBwb3MxXHJcbiAgICogQHBhcmFtIHBvczJcclxuICAgKi9cclxuICBnZXREaXN0UG9zaXRpb24ocG9zMTogYW55LCBwb3MyOiBhbnkpIHtcclxuICAgIGNvbnN0IHNpemUgPSB7XHJcbiAgICAgIHc6IHRoaXMuY29udGFpbmVyLmNsaWVudFdpZHRoLFxyXG4gICAgICBoOiB0aGlzLmNvbnRhaW5lci5jbGllbnRIZWlnaHQsXHJcbiAgICB9O1xyXG4gICAgY29uc3QgY29vcmRzMSA9IHRoaXMuc2RrLkNvbnZlcnNpb24ud29ybGRUb1NjcmVlbihcclxuICAgICAgcG9zMSxcclxuICAgICAgdGhpcy5wb3NlQ2FtZXJhLFxyXG4gICAgICBzaXplXHJcbiAgICApO1xyXG4gICAgY29uc3QgY29vcmRzMiA9IHRoaXMuc2RrLkNvbnZlcnNpb24ud29ybGRUb1NjcmVlbihcclxuICAgICAgcG9zMixcclxuICAgICAgdGhpcy5wb3NlQ2FtZXJhLFxyXG4gICAgICBzaXplXHJcbiAgICApO1xyXG4gICAgcmV0dXJuIE1hdGguc3FydChcclxuICAgICAgKGNvb3JkczEueCAtIGNvb3JkczIueCkgKiogMiArIChjb29yZHMxLnkgLSBjb29yZHMyLnkpICoqIDJcclxuICAgICk7XHJcbiAgfVxyXG5cclxuICAvL1xyXG4gIC8vIC0tLS0tLS0tLS0gTWF0dGVydGFnIHJlbGF0ZWQgLS0tLS0tLS0tLVxyXG4gIC8vXHJcbiAgLyoqXHJcbiAgICogQ3JlYXRlcyB0aGUgTWF0dGVydGFnIHRoYXQgd2lsbCBmb2xsb3cgdGhlIGN1cnNvclxyXG4gICAqIEBwYXJhbSBtYXR0ZXJ0YWdEYXRhIE1hdHRlcnRhZ0RhdGFcclxuICAgKi9cclxuICBhc3luYyBhZGRDdXJzb3JNYXR0ZXJ0YWcobWF0dGVydGFnRGF0YTogTWF0dGVydGFnRGF0YSkge1xyXG4gICAgaWYgKCF0aGlzLnBvc2VNYXR0ZXJwb3J0KSByZXR1cm47XHJcbiAgICB0aGlzLm1hdHRlcnRhZ1RvRm9sbG93ID0gYXdhaXQgdGhpcy5hZGRNYXR0ZXJ0YWdUb1ZpZXdlcihtYXR0ZXJ0YWdEYXRhKTtcclxuICAgIGNvbnNvbGUubG9nKCdmb2xsb3dpbmcgdGhlIHRhZycsIHRoaXMubWF0dGVydGFnVG9Gb2xsb3cpO1xyXG4gICAgdGhpcy5zZGsuVGFnLmVkaXRJY29uKHRoaXMubWF0dGVydGFnVG9Gb2xsb3csICdpY29uLXBvc2l0aW9uJyk7XHJcbiAgICB0aGlzLnNkay5UYWcuZWRpdE9wYWNpdHkodGhpcy5tYXR0ZXJ0YWdUb0ZvbGxvdywgMSk7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBBZGRzIE1hdHRlcnRhZyB0byB2aWV3ZXIgZm9yIGFuIGV4aXN0aW5nIG9iamVjdCB3aXRoIGNvb3JkaW5hdGVzIChpbiBtYXR0ZXJ0YWdEYXRhLnBvaSlcclxuICAgKiAocG9zaXRpb24sIGluamVjdGVkIGh0bWwsIHNldCBpY29uKVxyXG4gICAqIEBwYXJhbSBtYXR0ZXJ0YWdEYXRhXHJcbiAgICogcmV0dXJucyBtYXR0ZXJ0YWdJRFxyXG4gICAqL1xyXG4gIGFzeW5jIGFkZE1hdHRlcnRhZ1RvVmlld2VyKFxyXG4gICAgbWF0dGVydGFnRGF0YTogTWF0dGVydGFnRGF0YVxyXG4gICk6IFByb21pc2U8c3RyaW5nIHwgbnVsbD4ge1xyXG4gICAgbGV0IHNpZExpc3Q7XHJcbiAgICBpZiAoIXRoaXMuc2RrKSB7XHJcbiAgICAgIHJldHVybiBudWxsO1xyXG4gICAgfVxyXG4gICAgdHJ5IHtcclxuICAgICAgc2lkTGlzdCA9IGF3YWl0IHRoaXMuc2RrLlRhZy5hZGQobWF0dGVydGFnRGF0YS5nZXREYXRhKCkpO1xyXG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcclxuICAgICAgY29uc29sZS5sb2coXHJcbiAgICAgICAgJ1RhZyBkb2VzIG5vdCBiZWxvbmcgdG8gdGhlIHZpc2l0JyxcclxuICAgICAgICBlcnJvcixcclxuICAgICAgICBtYXR0ZXJ0YWdEYXRhLmdldERhdGEoKVxyXG4gICAgICApO1xyXG4gICAgfVxyXG4gICAgaWYgKHNpZExpc3QpIHtcclxuICAgICAgY29uc3QgbWF0dGVydGFnSUQgPSBzaWRMaXN0WzBdO1xyXG4gICAgICAvLyBjb25zb2xlLmxvZyhcImFkZGVkIHRhZ1wiLCBtYXR0ZXJ0YWdEYXRhLmdldFR5cGUoKSwgbWF0dGVydGFnSUQpO1xyXG4gICAgICB0aGlzLm1hdHRlcnRhZ0lEcy5wdXNoKG1hdHRlcnRhZ0lEKTtcclxuICAgICAgdGhpcy5kaWN0aW9ubmFyeVRhZ3Muc2V0KG1hdHRlcnRhZ0lELCBtYXR0ZXJ0YWdEYXRhKTtcclxuICAgICAgcmV0dXJuIG1hdHRlcnRhZ0lEO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIG51bGw7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBBY3Rpb25zIHdoZW4gcG9zaXRpb24gb2YgbWF0dGVydGFnIGlzIHZhbGlkYXRlZCBieSBsZWZ0IGNsaWNrXHJcbiAgICovXHJcbiAgb25WYWxpZGF0ZWRNYXR0ZXJ0YWcoKSB7XHJcbiAgICB0aGlzLnNldEludGVyYWN0aW9uTW9kZShWaWV3ZXJJbnRlcmFjdGlvbnMuREVGQVVMVCk7XHJcbiAgICBjb25zdCBsYXN0VGFnID0gdGhpcy5nZXRMYXN0VGFnKCk7XHJcbiAgICBpZiAobGFzdFRhZykge1xyXG4gICAgICBjb25zdCBjYWxsYmFja01vZGUgPSB0aGlzLmRpY3Rpb25uYXJ5VGFnc1xyXG4gICAgICAgIC5nZXQobGFzdFRhZylcclxuICAgICAgICAuZ2V0Q2FsbGJhY2tBY3Rpb25Nb2RlKCk7XHJcbiAgICAgIHRoaXMuY2FsbGJhY2tBZnRlck1hdHRlcnRhZ1ZhbGlkYXRpb24oY2FsbGJhY2tNb2RlKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIFJlZ2lzdGVycyBuZXcgaWNvbiAocGF0aCB0byBpbWFnZSkgYW5kIHNldCBpdHMgZm9yIE1hdHRlcnRhZ1xyXG4gICAqIEBwYXJhbSBtYXR0ZXJ0YWdJRCBzdHJpbmdcclxuICAgKiBAcGFyYW0gaWNvblBhdGggc3RyaW5nXHJcbiAgICovXHJcbiAgYXN5bmMgYWRkTmV3SWNvbkFuZFNldEZvclRhZyhtYXR0ZXJ0YWdJRDogc3RyaW5nLCBpY29uUGF0aDogc3RyaW5nKSB7XHJcbiAgICBhd2FpdCB0aGlzLnNkay5Bc3NldC5yZWdpc3RlclRleHR1cmUoYGljb25fJHttYXR0ZXJ0YWdJRH1gLCBpY29uUGF0aCk7XHJcbiAgICB0aGlzLnNkay5UYWcuZWRpdEljb24obWF0dGVydGFnSUQsIGBpY29uXyR7bWF0dGVydGFnSUR9YCk7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBDaGFuZ2VzIGljb24gb2YgTWF0dGVydGFnICh0aGUgaWNvbk5hbWUgc2hvdWxkIGJlIHJlZ2lzdGVyZWQgPSBvbmUgb2YgZGVmYXVsdCBvbmVzKVxyXG4gICAqIEBwYXJhbSBtYXR0ZXJ0YWdJRCBzdHJpbmdcclxuICAgKiBAcGFyYW0gaWNvbk5hbWUgc3RyaW5nXHJcbiAgICovXHJcbiAgYXN5bmMgc2V0UmVnaXN0cmVkSWNvbkZvclRhZyhtYXR0ZXJ0YWdJRDogc3RyaW5nLCBpY29uTmFtZTogc3RyaW5nKSB7XHJcbiAgICB0cnkge1xyXG4gICAgICB0aGlzLnNkay5UYWcuZWRpdEljb24obWF0dGVydGFnSUQsIGljb25OYW1lKTtcclxuICAgIH0gY2F0Y2ggKGUpIHtcclxuICAgICAgY29uc29sZS5sb2coXHJcbiAgICAgICAgJ2NvdWxkIG5vdCBlZGl0IEljb24gd2l0aCBuYW1lICcsXHJcbiAgICAgICAgaWNvbk5hbWUsXHJcbiAgICAgICAgJy4gSXMgaXQgcmVnaXN0ZXJlZD8nXHJcbiAgICAgICk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBTZXRzIGRlZmF1bHQgaWNvbiBmb3IgYSB0YWcgKHJlZ2lzdGVyZWQgaW4gaW5pdFNkaykgT1IgdXNlcyB0YWdJY29uIGZyb20gUE9JIChhdmFpbGFibGUgZnJvbSBNYXR0ZXJ0YWdEYXRhKVxyXG4gICAqIEBwYXJhbSBtYXR0ZXJ0YWdJRCBzdHJpbmdcclxuICAgKiBAcGFyYW0gbWF0dGVydGFnRGF0YSBNYXR0ZXJ0YWdEYXRhXHJcbiAgICogQHJldHVybnNcclxuICAgKi9cclxuICBhc3luYyBzZXRUYWdJY29uQW5kT3BhY2l0eShcclxuICAgIG1hdHRlcnRhZ0lEOiBzdHJpbmcsXHJcbiAgICBtYXR0ZXJ0YWdEYXRhOiBNYXR0ZXJ0YWdEYXRhXHJcbiAgKSB7XHJcbiAgICBpZiAodGhpcy5TUE1vZHVsZSA9PT0gU3BNb2R1bGUuSE9URUwpIHtcclxuICAgICAgY29uc3Qgcm9vbSA9IG1hdHRlcnRhZ0RhdGEuZ2V0T2JqZWN0KCk7XHJcbiAgICAgIGxldCBpY29uTmFtZSA9IGBpY29uX3Jvb21gO1xyXG4gICAgICBpZiAocm9vbS5hdmFpbGFibGUpIHtcclxuICAgICAgICBpY29uTmFtZSA9IGAke2ljb25OYW1lfV9hdmFpbGFibGVgO1xyXG4gICAgICB9IGVsc2Uge1xyXG4gICAgICAgIGljb25OYW1lID0gYCR7aWNvbk5hbWV9X3VuYXZhaWxhYmxlYDtcclxuICAgICAgfVxyXG4gICAgICB0aGlzLnNkay5UYWcuZWRpdEljb24obWF0dGVydGFnSUQsIGljb25OYW1lKTtcclxuICAgICAgcmV0dXJuO1xyXG4gICAgfVxyXG4gICAgY29uc3Qgc3RyaW5nVGFnVHlwZSA9IHBvaVR5cGVUb1N0cmluZyhtYXR0ZXJ0YWdEYXRhLmdldFR5cGUoKSk7XHJcbiAgICBsZXQgb3BhY2l0eSA9IHRoaXMuY29uZmlnLm15X2NvbmZpZy5ERUZBVUxUX09QQUNJVFlfVEFHO1xyXG4gICAgbGV0IGljb25OYW1lID0gYGljb24tJHtzdHJpbmdUYWdUeXBlfWA7XHJcbiAgICBjb25zdCBwb2kgPSBtYXR0ZXJ0YWdEYXRhLmdldFBvaSgpO1xyXG4gICAgaWYgKHBvaSAmJiBwb2kudGFnSWNvbikge1xyXG4gICAgICBjb25zdCB0YWdJY29uID0gSlNPTi5wYXJzZShwb2kudGFnSWNvbik7XHJcbiAgICAgIGlmIChtYXR0ZXJ0YWdEYXRhLmdldFR5cGUoKSA9PT0gUG9pVHlwZS5EQVRBKSB7XHJcbiAgICAgICAgY29uc3QgZmVhdHVyZSA9IG1hdHRlcnRhZ0RhdGEuZ2V0T2JqZWN0KCk7XHJcbiAgICAgICAgaWYgKGZlYXR1cmUudHlwZSA9PT0gRmVhdHVyZVR5cGUuSU5ESUNBVE9SX1RFTVApIHtcclxuICAgICAgICAgIHRhZ0ljb24uc3JjID0gdGhpcy50YWdTZXJ2aWNlLmdldEljb25UYWdJbWFnZUZvckZlYXR1cmUoZmVhdHVyZSwgcG9pKTtcclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuICAgICAgaWYgKHRhZ0ljb24uc3JjKSB7XHJcbiAgICAgICAgY29uc3QgcGF0aFNpZ25lZCA9IGF3YWl0IHRoaXMudGFnU2VydmljZS5nZXRTaWduZWRUYWdJY29uU291cmNlKFxyXG4gICAgICAgICAgdGFnSWNvbi5zcmNcclxuICAgICAgICApO1xyXG4gICAgICAgIGlmIChwYXRoU2lnbmVkKSB7XHJcbiAgICAgICAgICB0cnkge1xyXG4gICAgICAgICAgICBpY29uTmFtZSA9IGBpY29uLSR7c3RyaW5nVGFnVHlwZX0tJHttYXR0ZXJ0YWdJRH0tJHttYXR0ZXJ0YWdEYXRhLmN1c3RvbUljb25JbmRleH1gO1xyXG4gICAgICAgICAgICBhd2FpdCB0aGlzLnNkay5Bc3NldC5yZWdpc3RlclRleHR1cmUoaWNvbk5hbWUsIHBhdGhTaWduZWQpO1xyXG4gICAgICAgICAgICBtYXR0ZXJ0YWdEYXRhLmN1c3RvbUljb25JbmRleCArPSAxO1xyXG4gICAgICAgICAgfSBjYXRjaCB7XHJcbiAgICAgICAgICAgIGNvbnNvbGUubG9nKCdlcnJvciByZWdpc3Rlckljb24nKTtcclxuICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuICAgICAgaWYgKHRhZ0ljb24ub3BhY2l0eSkge1xyXG4gICAgICAgIG9wYWNpdHkgPSB0YWdJY29uLm9wYWNpdHk7XHJcbiAgICAgIH1cclxuICAgIH1cclxuICAgIHRyeSB7XHJcbiAgICAgIHRoaXMuc2RrLlRhZy5lZGl0SWNvbihtYXR0ZXJ0YWdJRCwgaWNvbk5hbWUpO1xyXG4gICAgICB0aGlzLnNkay5UYWcuZWRpdE9wYWNpdHkobWF0dGVydGFnSUQsIG9wYWNpdHkpO1xyXG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcclxuICAgICAgY29uc29sZS5sb2coJ0Vycm9yIGVkaXRJY29uIG9yIG9wYWNpdHknLCBlcnJvcik7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBNb3ZlcyB2aWV3ZXIgdG8gbGFzdCB0YWcgY3JlYXRlZFxyXG4gICAqL1xyXG4gIGdvVG9MYXN0VGFnKCkge1xyXG4gICAgc2V0VGltZW91dCgoKSA9PiB7XHJcbiAgICAgIGNvbnN0IGxhc3RUYWcgPSB0aGlzLmdldExhc3RUYWcoKTtcclxuICAgICAgdGhpcy5nb1RvVGFnKGxhc3RUYWcpO1xyXG4gICAgfSwgMjAwMCk7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBNb3ZlcyB2aWV3ZXIgdG8gTWF0dGVydGFnIHdpdGggSUQgcHJvdmlkZWRcclxuICAgKiBAcGFyYW0gbWF0dGVydGFnSUQgc3RyaW5nXHJcbiAgICogQHJldHVybnNcclxuICAgKi9cclxuICBhc3luYyBnb1RvVGFnKG1hdHRlcnRhZ0lEOiBzdHJpbmcpIHtcclxuICAgIGlmIChtYXR0ZXJ0YWdJRCA9PT0gJycpIHJldHVybjtcclxuICAgIHRyeSB7XHJcbiAgICAgIHRoaXMub25Hb1RvVGFnLm5leHQobWF0dGVydGFnSUQpO1xyXG4gICAgICBhd2FpdCB0aGlzLnNkay5Td2VlcC5jdXJyZW50LndhaXRVbnRpbChcclxuICAgICAgICAoY3VycmVudFN3ZWVwKSA9PiBjdXJyZW50U3dlZXAgIT09ICcnXHJcbiAgICAgICk7XHJcbiAgICAgIGF3YWl0IHRoaXMuc2RrLk1hdHRlcnRhZy5uYXZpZ2F0ZVRvVGFnKFxyXG4gICAgICAgIG1hdHRlcnRhZ0lELFxyXG4gICAgICAgIHRoaXMuc2RrLk1hdHRlcnRhZy5UcmFuc2l0aW9uLkZMWVxyXG4gICAgICApO1xyXG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcclxuICAgICAgY29uc29sZS5sb2coJ2Nhbm5vdCBuYXZpZ2F0ZSB0byB0YWcnLCBlcnJvcik7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBVcGRhdGVzIGNvbnRlbnQgb2YgTWF0dGVydGFnIHdpdGggbWF0dGVydGFnSUQgKGJpbGxib2FyZCwgaW5qZWN0ZWQgaHRtbCwgdGFnIGljb24pXHJcbiAgICogQHBhcmFtIG1hdHRlcnRhZ0lEIHN0cmluZ1xyXG4gICAqIEBwYXJhbSBvYmplY3QgVGlja2V0LCBFcXVpcG1lbnQsIEZlYXR1cmUsIGV0Y1xyXG4gICAqIEBwYXJhbSB0YWdUeXBlIFBvaVR5cGVcclxuICAgKi9cclxuICBhc3luYyB1cGRhdGVNYXR0ZXJUYWdDb250ZW50Rm9yVGFnSUQoXHJcbiAgICBtYXR0ZXJ0YWdJRDogc3RyaW5nLFxyXG4gICAgb2JqZWN0OiBEYk9iamVjdFR5cGUgPSBudWxsLFxyXG4gICAgdGFnVHlwZTogUG9pVHlwZSA9IG51bGxcclxuICApIHtcclxuICAgIHRoaXMuc2RrLlRhZy5lZGl0QmlsbGJvYXJkKFxyXG4gICAgICBtYXR0ZXJ0YWdJRCxcclxuICAgICAgdGhpcy5kaWN0aW9ubmFyeVRhZ3MuZ2V0KG1hdHRlcnRhZ0lEKS5nZXREYXRhKClcclxuICAgICk7XHJcbiAgICBpZiAob2JqZWN0ICYmIHRhZ1R5cGUpIHtcclxuICAgICAgYXdhaXQgdGhpcy5pbmplY3RIdG1sSW5UYWcodGFnVHlwZSwgb2JqZWN0LCBtYXR0ZXJ0YWdJRCk7XHJcbiAgICB9XHJcbiAgICBhd2FpdCB0aGlzLnNldFRhZ0ljb25BbmRPcGFjaXR5KFxyXG4gICAgICBtYXR0ZXJ0YWdJRCxcclxuICAgICAgdGhpcy5kaWN0aW9ubmFyeVRhZ3MuZ2V0KG1hdHRlcnRhZ0lEKVxyXG4gICAgKTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIFVwZGF0ZXMgaW5qZWN0ZWQgaHRtbCBmb3IgTWF0dGVydGFnXHJcbiAgICogQHBhcmFtIG1hdHRlcnRhZ0lEIHN0cmluZ1xyXG4gICAqIEBwYXJhbSBvYmplY3QgVGlja2V0LCBFcXVpcG1lbnQsIEZlYXR1cmUsIGV0Y1xyXG4gICAqIEBwYXJhbSB0YWdUeXBlIFBvaVR5cGVcclxuICAgKi9cclxuICBhc3luYyB1cGRhdGVJbmplY3RlZEh0bWxGb3JUYWdJRChcclxuICAgIG1hdHRlcnRhZ0lEOiBzdHJpbmcsXHJcbiAgICBvYmplY3Q6IGFueSxcclxuICAgIHRhZ1R5cGU6IFBvaVR5cGVcclxuICApIHtcclxuICAgIGF3YWl0IHRoaXMuaW5qZWN0SHRtbEluVGFnKHRhZ1R5cGUsIG9iamVjdCwgbWF0dGVydGFnSUQpO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogRGVsZXRlcyBNYXR0ZXJ0YWcgZnJvbSBWaWV3ZXIgYnkgaXRzIElEXHJcbiAgICogQHBhcmFtIG1hdHRlcnRhZ0lEIHN0cmluZ1xyXG4gICAqL1xyXG4gIGRlbGV0ZU1hdHRlcnRhZ0Zyb21JZChtYXR0ZXJ0YWdJRDogc3RyaW5nKSB7XHJcbiAgICB0aGlzLnNkay5UYWcucmVtb3ZlKG1hdHRlcnRhZ0lEKTtcclxuICAgIHRoaXMuZGljdGlvbm5hcnlUYWdzLmRlbGV0ZShtYXR0ZXJ0YWdJRCk7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBEZWxldGVzIGxhdGVzdCBjcmVhdGVkIG1hdHRlcnRhZ1xyXG4gICAqL1xyXG4gIGRlbGV0ZUxhc3RNYXR0ZXJ0YWcoKSB7XHJcbiAgICBjb25zdCBtYXR0ZXJ0YWdJRCA9IHRoaXMubWF0dGVydGFnSURzLnBvcCgpO1xyXG4gICAgaWYgKG1hdHRlcnRhZ0lEKSB7XHJcbiAgICAgIHRoaXMuZGVsZXRlTWF0dGVydGFnRnJvbUlkKG1hdHRlcnRhZ0lEKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIExlZ2FjeTogdXNlZCB0byBiZSBjYWxsZWQgYWN0aW9uX2FkZF9tYXR0ZXJ0YWdfZnJvbV9QT0lcclxuICAgKiBBZGRzIGFuZCBjb25maWd1cmVzIE1hdHRlcnRhZyBmb3IgYW4gb2JqZWN0IChUaWNrZXQsIEVxdWlwbWVudCwgRmVhdHVyZSwgZXRjKSB0aGF0IGNvcnJlc3BvbmRzIHRvIFBPSSAoY29vcmRpbmF0ZXMsIHRhZ0ljb24pXHJcbiAgICogQHBhcmFtIHRhZ1R5cGUgUG9pVHlwZVxyXG4gICAqIEBwYXJhbSBvYmplY3QgVGlja2V0LCBFcXVpcG1lbnQsIEZlYXR1cmUuLi5cclxuICAgKiBAcGFyYW0gcG9pIFBPSVxyXG4gICAqIEByZXR1cm5zXHJcbiAgICovXHJcbiAgYXN5bmMgY3JlYXRlTWF0dGVydGFnRnJvbVBPSShcclxuICAgIHRhZ1R5cGU6IFBvaVR5cGUsXHJcbiAgICBvYmplY3Q6IERiT2JqZWN0VHlwZSxcclxuICAgIHBvaTogUE9JXHJcbiAgKTogUHJvbWlzZTxhbnk+IHtcclxuICAgIC8vIGNoZWNrIGlmIHRhZyBleGlzdHMgYWxyZWFkeVxyXG4gICAgY29uc3Qge3RhZywgc3dlZXB9ID0gdGhpcy5nZXRUYWdGcm9tRWxlbWVudElkKG9iamVjdC5pZCk7XHJcbiAgICBpZiAodGFnKSB7XHJcbiAgICAgIC8vIGNvbnNvbGUubG9nKFwidGFnIGV4aXN0c1wiLCBvYmplY3QpXHJcbiAgICAgIHJldHVybjtcclxuICAgIH1cclxuICAgIGNvbnN0IG1hdHRlcnRhZ0RhdGE6IE1hdHRlcnRhZ0RhdGEgPSBuZXcgTWF0dGVydGFnRGF0YSh0YWdUeXBlKTtcclxuICAgIG1hdHRlcnRhZ0RhdGEuc2V0T2JqZWN0KG9iamVjdCwgdGFnVHlwZSk7XHJcbiAgICBpZiAocG9pLmNvb3JkaW5hdGUpIHtcclxuICAgICAgbWF0dGVydGFnRGF0YS5zZXRQb3NpdGlvbihKU09OLnBhcnNlKHBvaS5jb29yZGluYXRlKSk7XHJcbiAgICB9XHJcbiAgICBpZiAocG9pLm1ldGFkYXRhKSB7XHJcbiAgICAgIGNvbnN0IHRhZ01ldGFkYXRhID0gSlNPTi5wYXJzZShwb2kubWV0YWRhdGEpO1xyXG4gICAgICBpZiAodGFnTWV0YWRhdGEubm9ybWFsKSB7XHJcbiAgICAgICAgbWF0dGVydGFnRGF0YS5zZXROb3JtYWwodGFnTWV0YWRhdGEubm9ybWFsKTtcclxuICAgICAgfSBlbHNlIHtcclxuICAgICAgICBtYXR0ZXJ0YWdEYXRhLnNldE5vcm1hbCh7eDogMCwgeTogLTAuMTUsIHo6IDB9KTtcclxuICAgICAgfVxyXG4gICAgfVxyXG4gICAgaWYgKHBvaS5tYXR0ZXJwb3J0U3dlZXBJRCkge1xyXG4gICAgICBtYXR0ZXJ0YWdEYXRhLnNldFN3ZWVwSUQocG9pLm1hdHRlcnBvcnRTd2VlcElEKTtcclxuICAgIH1cclxuICAgIG1hdHRlcnRhZ0RhdGEuc2V0UG9pKHBvaSk7XHJcblxyXG4gICAgY29uc3QgY3JlYXRlZFRhZ0lEID0gYXdhaXQgdGhpcy5hZGRNYXR0ZXJ0YWdUb1ZpZXdlcihtYXR0ZXJ0YWdEYXRhKTtcclxuICAgIGlmIChjcmVhdGVkVGFnSUQgJiYgdGhpcy5zZGspIHtcclxuICAgICAgYXdhaXQgdGhpcy5zZXRUYWdJY29uQW5kT3BhY2l0eShjcmVhdGVkVGFnSUQsIG1hdHRlcnRhZ0RhdGEpO1xyXG4gICAgICBhd2FpdCB0aGlzLmluamVjdEh0bWxJblRhZyh0YWdUeXBlLCBvYmplY3QsIGNyZWF0ZWRUYWdJRCk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBJbmplY3QgY3VzdG9tIEhUTUwgYXMgTWF0dGVydGFnIGNvbnRlbnRcclxuICAgKiBAcGFyYW0gdGFnVHlwZSBQb2lUeXBlXHJcbiAgICogQHBhcmFtIG9iamVjdCBUaWNrZXQsIEVxdWlwbWVudCwgRmVhdHVyZSBldGNcclxuICAgKiBAcGFyYW0gdGFnSUQgc3RyaW5nXHJcbiAgICovXHJcbiAgYXN5bmMgaW5qZWN0SHRtbEluVGFnKHRhZ1R5cGU6IFBvaVR5cGUsIG9iamVjdDogRGJPYmplY3RUeXBlLCB0YWdJRDogc3RyaW5nKSB7XHJcbiAgICBsZXQgaHRtbCA9IGF3YWl0IHRoaXMudGFnU2VydmljZS5nZXRIdG1sVG9JbmplY3QodGFnVHlwZSwgb2JqZWN0KTtcclxuICAgIGlmIChodG1sICE9PSAnJyAmJiB0aGlzLnNkaykge1xyXG4gICAgICBjb25zdCBzY3JpcHRUYWcgPSB0aGlzLnRhZ1NlcnZpY2UuZ2V0U2NyaXB0Rm9yVGFnKG9iamVjdCwgdGFnVHlwZSk7XHJcbiAgICAgIGh0bWwgKz0gYCR7c2NyaXB0VGFnfWA7XHJcbiAgICAgIC8vIGNyZWF0ZSBhbmQgcmVnaXN0ZXIgdGhlIHNhbmRib3hcclxuICAgICAgY29uc3QgW3NhbmRib3hJZCwgbWVzc2VuZ2VyXSA9IGF3YWl0IHRoaXMuc2RrLlRhZy5yZWdpc3RlclNhbmRib3goaHRtbCk7XHJcblxyXG4gICAgICAvLyBkZXRhY2ggcHJldmlvdXMgc2FuZGJveCBmcm9tIGEgdGFnXHJcbiAgICAgIGxldCBhdHRhY2htZW50SUQgPSB0aGlzLnRhZ3NBdHRhY2htZW50c1t0YWdJRF07XHJcbiAgICAgIGlmIChhdHRhY2htZW50SUQpIHtcclxuICAgICAgICB0aGlzLnNkay5UYWcuZGV0YWNoKHRhZ0lELCBhdHRhY2htZW50SUQpO1xyXG4gICAgICB9XHJcbiAgICAgIHRoaXMudGFnc0F0dGFjaG1lbnRzW3RhZ0lEXSA9IHNhbmRib3hJZDtcclxuXHJcbiAgICAgIC8vIGF0dGFjaCB0aGUgc2FuZGJveCB0byBhIHRhZ1xyXG4gICAgICB0aGlzLnNkay5UYWcuYXR0YWNoKHRhZ0lELCBzYW5kYm94SWQpO1xyXG4gICAgICAvLyByZWNlaXZlIGRhdGEgZnJvbSB0aGUgc2FuZGJveFxyXG4gICAgICAvLyB0YWdNZXNzZW5nZXJPbiBhbGxvd3MgdG8gZ28gaGVyZSBvbmx5IG9uY2VcclxuICAgICAgaWYgKCF0aGlzLnRhZ01lc3Nlbmdlck9uKSB7XHJcbiAgICAgICAgdGhpcy50YWdNZXNzZW5nZXJPbiA9IHRydWU7XHJcbiAgICAgICAgY29uc3QgaW1hZ2VDbGljayA9IChmZWF0dXJlSUQ6IHN0cmluZykgPT4ge1xyXG4gICAgICAgICAgLy8gY29uc29sZS5sb2coXCJpbWFnZSBjbGljayBoYW5kbGVyXCIsIGZlYXR1cmVJRCk7XHJcbiAgICAgICAgICB0aGlzLnRhZ1NlcnZpY2Uub25BY3Rpb25JbWFnZUNsaWNrKGZlYXR1cmVJRCk7XHJcbiAgICAgICAgfTtcclxuXHJcbiAgICAgICAgY29uc3QgYXVkaW9DbGljayA9IChhdWRpb0NvbW1lbnRJRDogc3RyaW5nKSA9PiB7XHJcbiAgICAgICAgICAvLyBjb25zb2xlLmxvZyhcImF1ZGlvIGNsaWNrIGhhbmRsZXJcIiwgYXVkaW9Db21tZW50SUQpO1xyXG4gICAgICAgICAgdGhpcy50YWdTZXJ2aWNlLm9uQWN0aW9uQXVkaW9DbGljayhhdWRpb0NvbW1lbnRJRCk7XHJcbiAgICAgICAgfTtcclxuICAgICAgICBjb25zdCB2aWRlb0NsaWNrID0gKHVybDogc3RyaW5nKSA9PiB7XHJcbiAgICAgICAgICB0aGlzLnRhZ1NlcnZpY2Uub25BY3Rpb25WaWRlb0NsaWNrKHVybCk7XHJcbiAgICAgICAgfTtcclxuICAgICAgICBtZXNzZW5nZXIub24oXHJcbiAgICAgICAgICBUYWdBY3Rpb24uREVUQUlMX0NMSUNLLFxyXG4gICAgICAgICAgdGhpcy50YWdTZXJ2aWNlLm9uQWN0aW9uRGV0YWlsQ2xpY2suYmluZCh0aGlzLnRhZ1NlcnZpY2UpXHJcbiAgICAgICAgKTtcclxuICAgICAgICBtZXNzZW5nZXIub24oXHJcbiAgICAgICAgICBUYWdBY3Rpb24uVElDS0VUX0NMSUNLLFxyXG4gICAgICAgICAgdGhpcy50YWdTZXJ2aWNlLm9uQWN0aW9uRGV0YWlsQ2xpY2suYmluZCh0aGlzLnRhZ1NlcnZpY2UpXHJcbiAgICAgICAgKTtcclxuICAgICAgICBtZXNzZW5nZXIub24oVGFnQWN0aW9uLkFVRElPX0NMSUNLLCBhdWRpb0NsaWNrKTtcclxuICAgICAgICBtZXNzZW5nZXIub24oVGFnQWN0aW9uLklNQUdFX0NMSUNLLCBpbWFnZUNsaWNrKTtcclxuICAgICAgICBtZXNzZW5nZXIub24oVGFnQWN0aW9uLlZJREVPX0NMSUNLLCB2aWRlb0NsaWNrKTtcclxuICAgICAgICBtZXNzZW5nZXIub24oXHJcbiAgICAgICAgICBUYWdBY3Rpb24uRE9DX0NMSUNLLFxyXG4gICAgICAgICAgdGhpcy50YWdTZXJ2aWNlLm9uQWN0aW9uRG9jQ2xpY2suYmluZCh0aGlzLnRhZ1NlcnZpY2UpXHJcbiAgICAgICAgKTtcclxuICAgICAgICBtZXNzZW5nZXIub24oXHJcbiAgICAgICAgICBUYWdBY3Rpb24uWU9VVFVCRV9DTElDSyxcclxuICAgICAgICAgIHRoaXMudGFnU2VydmljZS5vbkFjdGlvbllvdXR1YmVDbGljay5iaW5kKHRoaXMudGFnU2VydmljZSlcclxuICAgICAgICApO1xyXG4gICAgICB9XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICAvLyBpZiBodG1sIGlzIGVtcHR5IChjYXNlIG9mIEVNQkVEIGNvbnRlbnQpLCB3ZSBlZGl0IGJpbGxib2FyZCBmb3IgRmVhdHVyZSBhbmQgYXR0YWNoIG5ldyBjb250ZW50XHJcbiAgICAgIGNvbnN0IHtjb21tZW50LCB0YWdEZXNjcmlwdGlvbn0gPVxyXG4gICAgICAgIHRoaXMudGFnU2VydmljZS5nZXRCaWxsYm9hcmRNZWRpYVRvRW1iZWQob2JqZWN0KTtcclxuICAgICAgaWYgKGNvbW1lbnQpIHtcclxuICAgICAgICAvLyByZWdpc3RlciB0aGUgbWVkaWFcclxuICAgICAgICBjb25zdCBbYXR0YWNobWVudElEXSA9IGF3YWl0IHRoaXMuc2RrLlRhZy5yZWdpc3RlckF0dGFjaG1lbnQoXHJcbiAgICAgICAgICBjb21tZW50LmV4dGVybmFsTGlua1xyXG4gICAgICAgICk7XHJcbiAgICAgICAgLy8gYXR0YWNoXHJcbiAgICAgICAgdGhpcy5zZGsuVGFnLmF0dGFjaCh0YWdJRCwgYXR0YWNobWVudElEKTtcclxuICAgICAgICB0aGlzLnNkay5UYWcuZWRpdEJpbGxib2FyZCh0YWdJRCwge1xyXG4gICAgICAgICAgbGFiZWw6IG9iamVjdC50aXRsZSxcclxuICAgICAgICAgIGRlc2NyaXB0aW9uOiB0YWdEZXNjcmlwdGlvbixcclxuICAgICAgICB9KTtcclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgYXN5bmMgYWN0aW9uX2RlbGV0ZV9hbGxfbWF0dGVydGFncygpIHtcclxuICAgIGF3YWl0IHRoaXMuc2RrLlRhZy5yZW1vdmUoLi4udGhpcy5tYXR0ZXJ0YWdJRHMpO1xyXG4gICAgdGhpcy5tYXR0ZXJ0YWdJRHMgPSBbXTtcclxuICAgIHRoaXMuZGljdGlvbm5hcnlUYWdzLmNsZWFyKCk7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBEZWxldGVzIE1hdHRlcnRhZyBmcm9tIHZpc2l0IGFzc29jaWF0ZWQgd2l0aCBvYmplY3QgSUQgKHRpY2tldElELCBldGMpXHJcbiAgICogQHBhcmFtIGVsZW1lbnRJRCBzdHJpbmdcclxuICAgKi9cclxuICBhc3luYyBkZWxldGVNYXR0ZXJ0YWdGb3JPYmplY3QoZWxlbWVudElEOiBzdHJpbmcpIHtcclxuICAgIGNvbnN0IG1hdHRlclRhZ0lEID0gdGhpcy5nZXRUYWdGcm9tRWxlbWVudElkKGVsZW1lbnRJRCkudGFnO1xyXG4gICAgaWYgKG1hdHRlclRhZ0lEKSB7XHJcbiAgICAgIHRyeSB7XHJcbiAgICAgICAgYXdhaXQgdGhpcy5zZGsuVGFnLnJlbW92ZShtYXR0ZXJUYWdJRCk7XHJcbiAgICAgICAgdGhpcy5kaWN0aW9ubmFyeVRhZ3MuZGVsZXRlKG1hdHRlclRhZ0lEKTtcclxuICAgICAgICBjb25zdCBpbmRleCA9IHRoaXMubWF0dGVydGFnSURzLmluZGV4T2YobWF0dGVyVGFnSUQpO1xyXG4gICAgICAgIHRoaXMubWF0dGVydGFnSURzLnNwbGljZShpbmRleCwgMSk7XHJcbiAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XHJcbiAgICAgICAgY29uc29sZS5sb2coJ0Nhbm5vdCBkZWxldGUgdGFnJywgbWF0dGVyVGFnSUQsIGVycm9yKTtcclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogdXVpZCBmcm9tIHRocmVlanNcclxuICAgKiBAcGFyYW0gdXVpZFxyXG4gICAqL1xyXG4gIGFzeW5jIGRlbGV0ZU9iamVjdDNEKHV1aWQ6IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xyXG4gICAgdGhpcy5kaWN0aW9ubmFyeU9iamVjdHMzRC5nZXQodXVpZCkub2JqM0QudmlzaWJsZSA9IGZhbHNlO1xyXG4gIH1cclxuXHJcbiAgZ2V0T2JqZWN0M0RNb2RlbE5vZGVGcm9tRGljdGlvbm5hcnkodXVpZDogc3RyaW5nKTogYW55IHtcclxuICAgICAgbGV0IG9iaiA9IHRoaXMuZGljdGlvbm5hcnlPYmplY3RzM0QuZ2V0KHV1aWQpO1xyXG4gICAgICBpZighb2JqKXtcclxuICAgICAgICBjb25zb2xlLmxvZyhcIndlaXJkIHRoaW5nIGFnYWluXCIpO1xyXG4gICAgICAgIHJldHVybiBudWxsO1xyXG4gICAgICB9XHJcbiAgICAgIC8vbWlnaHQgYnJlYWsgdGhpbmdzIG9yIGZpeCBldmVyeXRoaW5nIC4uP1xyXG4gICAgICBpZihvYmoub2JqM0QudXVpZCAhPSB1dWlkKXtcclxuICAgICAgICBjb25zb2xlLmxvZyhcIndlIGhhdmUgVEhFIHByb2JsZW1cIik7XHJcbiAgICAgICAgb2JqLm9iajNELnV1aWQgPSB1dWlkO1xyXG4gICAgICB9XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBDcmVhdGVzICBNYXR0ZXJ0YWdEYXRhIGFuZCBzdGFydCByZXBvc2l0aW9uaW5nIChjcmVhdGVzIHRlbXBvcmFyeSBtYXR0ZXJ0YWcgdGhhdCBmb2xsb3dzIHRoZSBjdXJzb3IpXHJcbiAgICogQHBhcmFtIHBvaVR5cGUgUG9pVHlwZVxyXG4gICAqIEBwYXJhbSBlbGVtZW50IFRpY2tldCwgRXF1aXBtZW50LCBGZWF0dXJlLCBldGNcclxuICAgKi9cclxuICBhc3luYyBhZGRNYXR0ZXJ0YWdXaGVuUmVwb3NpdGlvbmluZyhwb2lUeXBlOiBQb2lUeXBlLCBlbGVtZW50OiBEYk9iamVjdFR5cGUpIHtcclxuICAgIGNvbnN0IG1hdHRlcnRhZ0RhdGEgPSBuZXcgTWF0dGVydGFnRGF0YShwb2lUeXBlKTtcclxuICAgIC8vIHNldCB0aGUgY29vcmRpbmF0ZXMgb2YgdGhlIGV4aXN0aW5nIHRhZ1xyXG4gICAgY29uc3QgW3BvaV0gPSBlbGVtZW50LnBvaXMuaXRlbXM7XHJcbiAgICBpZiAocG9pICYmIHBvaS5jb29yZGluYXRlKSB7XHJcbiAgICAgIG1hdHRlcnRhZ0RhdGEuc2V0UG9zaXRpb24oSlNPTi5wYXJzZShwb2kuY29vcmRpbmF0ZSkpO1xyXG4gICAgICBtYXR0ZXJ0YWdEYXRhLnNldFBvaShwb2kpOyAvLyB0byBrZWVwIGN1c3RvbSB0YWdJY29uIGFuZCBvcGFjaXR5XHJcbiAgICB9XHJcbiAgICBtYXR0ZXJ0YWdEYXRhLnNldFN3ZWVwSUQodGhpcy5wb3NlQ2FtZXJhLnN3ZWVwKTtcclxuICAgIG1hdHRlcnRhZ0RhdGEuc2V0Um90YXRpb24odGhpcy5wb3NlQ2FtZXJhLnJvdGF0aW9uKTtcclxuICAgIG1hdHRlcnRhZ0RhdGEuc2V0T2JqZWN0KGVsZW1lbnQsIHBvaVR5cGUpO1xyXG4gICAgdGhpcy5tYXR0ZXJ0YWdUb0ZvbGxvdyA9IGF3YWl0IHRoaXMuYWRkTWF0dGVydGFnVG9WaWV3ZXIobWF0dGVydGFnRGF0YSk7XHJcbiAgICB0aGlzLnNldEludGVyYWN0aW9uTW9kZShWaWV3ZXJJbnRlcmFjdGlvbnMuUE9TSVRJT05JTkcpO1xyXG4gICAgYXdhaXQgdGhpcy5hZGRDdXJzb3JNYXR0ZXJ0YWcobWF0dGVydGFnRGF0YSk7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBDcmVhdGVzIE1hdHRlcnRhZ0RhdGEgYW5kIG1hdHRlcnRhZyB0aGF0IGZvbGxvd3MgdGhlIGN1cnNvciB3aGVuIGNob29zaW5nIHBvc2l0aW9uIGZvciBhIG5ldyBvYmplY3RcclxuICAgKiBAcGFyYW0gcG9pVHlwZVxyXG4gICAqL1xyXG4gIGFzeW5jIGFkZE1hdHRlcnRhZ1doZW5BZGRpbmcocG9pVHlwZTogUG9pVHlwZSkge1xyXG4gICAgY29uc3QgbWF0dGVydGFnRGF0YSA9IG5ldyBNYXR0ZXJ0YWdEYXRhKHBvaVR5cGUpO1xyXG4gICAgbWF0dGVydGFnRGF0YS5zZXRTd2VlcElEKHRoaXMucG9zZUNhbWVyYS5zd2VlcCk7XHJcbiAgICBtYXR0ZXJ0YWdEYXRhLnNldFJvdGF0aW9uKHRoaXMucG9zZUNhbWVyYS5yb3RhdGlvbik7XHJcbiAgICB0aGlzLnNldEludGVyYWN0aW9uTW9kZShWaWV3ZXJJbnRlcmFjdGlvbnMuQURESU5HKTtcclxuICAgIGF3YWl0IHRoaXMuYWRkQ3Vyc29yTWF0dGVydGFnKG1hdHRlcnRhZ0RhdGEpO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogQ2FuY2VscyBmb2xsb3dpbmcgb2YgY3Vyc29yIChtZWFuaW5nIGRlbGV0aW5nIGxhc3QgTWF0dGVydGFnKVxyXG4gICAqL1xyXG4gIGNhbmNlbEZvbGxvd2luZ0N1cnNvcigpIHtcclxuICAgIHRoaXMuZGVsZXRlTGFzdE1hdHRlcnRhZygpO1xyXG4gICAgdGhpcy5zZXRJbnRlcmFjdGlvbk1vZGUoVmlld2VySW50ZXJhY3Rpb25zLkRFRkFVTFQpO1xyXG4gIH1cclxuXHJcbiAgc2V0TGFzdE9iamVjdDNEKGxhc3RPYmplY3QzRDogVGhyZWVKU09iamVjdDNEKSB7XHJcbiAgICB0aGlzLmxhc3RPYmplY3QzRCA9IGxhc3RPYmplY3QzRDtcclxuICB9XHJcblxyXG4gIGdldExhc3RPYmplY3QzRCgpOiBUaHJlZUpTT2JqZWN0M0Qge1xyXG4gICAgcmV0dXJuIHRoaXMubGFzdE9iamVjdDNEO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogUGVyZm9ybXMgY2FsbGJhY2sgYWZ0ZXIgbWF0dGVydGFnIHBvc2l0aW9uIHdhcyB2YWxpZGF0ZWQgKGNyZWF0aW9uIG9mIG9iamVjdCBvciByZXBvc2l0aW9uaW5nKVxyXG4gICAqIEBwYXJhbSBtb2RlIE1hdHRlcnRhZ0FjdGlvbk1vZGVcclxuICAgKi9cclxuICBjYWxsYmFja0FmdGVyTWF0dGVydGFnVmFsaWRhdGlvbihtb2RlOiBNYXR0ZXJ0YWdBY3Rpb25Nb2RlKSB7XHJcbiAgICB0aGlzLnZpc2liaWxpdHlTZXJ2aWNlLmRldGFpbFNob3dpbmcubmV4dCh0cnVlKTtcclxuICAgIGNvbnN0IGxhc3RUYWcgPSB0aGlzLmdldExhc3RUYWcoKTtcclxuICAgIHN3aXRjaCAobW9kZSkge1xyXG4gICAgICBjYXNlIE1hdHRlcnRhZ0FjdGlvbk1vZGUuQUREX0VRVUlQTUVOVDpcclxuICAgICAgICB0aGlzLmdvVG9MYXN0VGFnKCk7XHJcbiAgICAgICAgdGhpcy5yb3V0ZXIubmF2aWdhdGUoW2B2aXNpdC8ke3RoaXMuY3VycmVudFNwYWNlSUR9L2FkZF9lcXVpcGBdKTtcclxuICAgICAgICBicmVhaztcclxuICAgICAgY2FzZSBNYXR0ZXJ0YWdBY3Rpb25Nb2RlLkFERF9USUNLRVQ6XHJcbiAgICAgICAgdGhpcy5nb1RvTGFzdFRhZygpO1xyXG4gICAgICAgIHRoaXMucm91dGVyLm5hdmlnYXRlKFtgdmlzaXQvJHt0aGlzLmN1cnJlbnRTcGFjZUlEfS9hZGRfdGlja2V0YF0pO1xyXG4gICAgICAgIGJyZWFrO1xyXG4gICAgICBjYXNlIE1hdHRlcnRhZ0FjdGlvbk1vZGUuQUREX09CSkVDVDNEOlxyXG4gICAgICAgIHRoaXMuZ29Ub0xhc3RUYWcoKTtcclxuICAgICAgICB0aGlzLnJvdXRlci5uYXZpZ2F0ZShbYHZpc2l0LyR7dGhpcy5jdXJyZW50U3BhY2VJRH0vYWRkX29iamVjdDNkYF0pO1xyXG4gICAgICAgIGJyZWFrO1xyXG4gICAgICBjYXNlIE1hdHRlcnRhZ0FjdGlvbk1vZGUuQUREX0RBVEE6XHJcbiAgICAgICAgdGhpcy5nb1RvTGFzdFRhZygpO1xyXG4gICAgICAgIGxldCB1cmw6IHN0cmluZztcclxuICAgICAgICBpZiAodGhpcy5yb3V0ZXIudXJsLmluY2x1ZGVzKCc/JykpIHtcclxuICAgICAgICAgIHVybCA9IHRoaXMucm91dGVyLnVybC5zdWJzdHJpbmcoMCwgdGhpcy5yb3V0ZXIudXJsLmluZGV4T2YoJz8nKSk7XHJcbiAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgIHVybCA9IHRoaXMucm91dGVyLnVybDtcclxuICAgICAgICB9XHJcbiAgICAgICAgdGhpcy5yb3V0ZXIubmF2aWdhdGUoW2Ake3VybH0vYWRkX2ZlYXR1cmVgXSk7XHJcbiAgICAgICAgYnJlYWs7XHJcbiAgICAgIGNhc2UgTWF0dGVydGFnQWN0aW9uTW9kZS5BRERfREVTSzpcclxuICAgICAgICB0aGlzLmdvVG9MYXN0VGFnKCk7XHJcbiAgICAgICAgdGhpcy5yb3V0ZXIubmF2aWdhdGUoW2B2aXNpdC8ke3RoaXMuY3VycmVudFNwYWNlSUR9L2FkZF9mZWF0dXJlYF0sIHtcclxuICAgICAgICAgIHF1ZXJ5UGFyYW1zOiB7aXNEZXNrOiB0cnVlfSxcclxuICAgICAgICB9KTtcclxuICAgICAgICBicmVhaztcclxuICAgICAgY2FzZSBNYXR0ZXJ0YWdBY3Rpb25Nb2RlLkFERF9ST09NOlxyXG4gICAgICAgIHRoaXMuZ29Ub0xhc3RUYWcoKTtcclxuICAgICAgICB0aGlzLnJvdXRlci5uYXZpZ2F0ZShbYHZpc2l0LyR7dGhpcy5jdXJyZW50U3BhY2VJRH0vYWRkX3Jvb21gXSk7XHJcbiAgICAgICAgYnJlYWs7XHJcbiAgICAgIGNhc2UgTWF0dGVydGFnQWN0aW9uTW9kZS5QT1NJVElPTl9PQkpFQ1QzRDpcclxuICAgICAgICBpZiAobGFzdFRhZykge1xyXG4gICAgICAgICAgLy8gRE8gTm90aGluZyAocm91dGluZyksIGp1c3RcclxuICAgICAgICAgIHRoaXMucm91dGVyLm5hdmlnYXRlKFxyXG4gICAgICAgICAgICBbYHZpc2l0LyR7dGhpcy5jdXJyZW50U3BhY2VJRH0vb2JqZWN0M2QvJHt0aGlzLmxhc3RPYmplY3QzRC5pZH1gXSxcclxuICAgICAgICAgICAge3F1ZXJ5UGFyYW1zOiB7cG9zaXRpb25pbmc6IHRydWV9fVxyXG4gICAgICAgICAgKTtcclxuICAgICAgICB9XHJcbiAgICAgICAgYnJlYWs7XHJcbiAgICAgIGNhc2UgTWF0dGVydGFnQWN0aW9uTW9kZS5QT1NJVElPTl9USUNLRVQ6XHJcbiAgICAgICAgaWYgKGxhc3RUYWcpIHtcclxuICAgICAgICAgIHRoaXMucm91dGVyLm5hdmlnYXRlKFxyXG4gICAgICAgICAgICBbXHJcbiAgICAgICAgICAgICAgYHZpc2l0LyR7dGhpcy5jdXJyZW50U3BhY2VJRH0vZGV0YWlsLyR7XHJcbiAgICAgICAgICAgICAgICB0aGlzLmRpY3Rpb25uYXJ5VGFncy5nZXQobGFzdFRhZykuZWxlbWVudElEXHJcbiAgICAgICAgICAgICAgfWAsXHJcbiAgICAgICAgICAgIF0sXHJcbiAgICAgICAgICAgIHtxdWVyeVBhcmFtczoge3Bvc2l0aW9uaW5nOiB0cnVlfX1cclxuICAgICAgICAgICk7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGJyZWFrO1xyXG4gICAgICBjYXNlIE1hdHRlcnRhZ0FjdGlvbk1vZGUuUE9TSVRJT05fRVFVSVBNRU5UOlxyXG4gICAgICAgIGlmIChsYXN0VGFnKSB7XHJcbiAgICAgICAgICB0aGlzLnJvdXRlci5uYXZpZ2F0ZShcclxuICAgICAgICAgICAgW1xyXG4gICAgICAgICAgICAgIGB2aXNpdC8ke3RoaXMuY3VycmVudFNwYWNlSUR9L2VxdWlwLyR7XHJcbiAgICAgICAgICAgICAgICB0aGlzLmRpY3Rpb25uYXJ5VGFncy5nZXQobGFzdFRhZykuZWxlbWVudElEXHJcbiAgICAgICAgICAgICAgfWAsXHJcbiAgICAgICAgICAgIF0sXHJcbiAgICAgICAgICAgIHtxdWVyeVBhcmFtczoge3Bvc2l0aW9uaW5nOiB0cnVlfX1cclxuICAgICAgICAgICk7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGJyZWFrO1xyXG4gICAgICBjYXNlIE1hdHRlcnRhZ0FjdGlvbk1vZGUuUE9TSVRJT05fREFUQTpcclxuICAgICAgICBpZiAobGFzdFRhZykge1xyXG4gICAgICAgICAgdGhpcy5yb3V0ZXIubmF2aWdhdGUoW10sIHtcclxuICAgICAgICAgICAgcmVsYXRpdmVUbzogdGhpcy5hY3RpdmVSb3V0ZSxcclxuICAgICAgICAgICAgcXVlcnlQYXJhbXM6IHtwb3NpdGlvbmluZzogdHJ1ZX0sIHF1ZXJ5UGFyYW1zSGFuZGxpbmcgOiBcIm1lcmdlXCJcclxuICAgICAgICAgIH0pO1xyXG4gICAgICAgIH1cclxuICAgICAgICBicmVhaztcclxuICAgICAgY2FzZSBNYXR0ZXJ0YWdBY3Rpb25Nb2RlLlBPU0lUSU9OX1JPT006XHJcbiAgICAgICAgaWYgKGxhc3RUYWcpIHtcclxuICAgICAgICAgIHRoaXMucm91dGVyLm5hdmlnYXRlKFtdLCB7XHJcbiAgICAgICAgICAgIHJlbGF0aXZlVG86IHRoaXMuYWN0aXZlUm91dGUsXHJcbiAgICAgICAgICAgIHF1ZXJ5UGFyYW1zOiB7cG9zaXRpb25pbmc6IHRydWV9LCBxdWVyeVBhcmFtc0hhbmRsaW5nIDogXCJtZXJnZVwiXHJcbiAgICAgICAgICB9KTtcclxuICAgICAgICB9XHJcbiAgICAgICAgYnJlYWs7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBGdWxseSB1cGRhdGVzIGV4aXN0aW5nIE1hdHRlcnRhZyBjb250ZW50IHdpdGggZGF0YSBvZiBvYmplY3QgKFRpY2tldCwgRXF1aXBtZW50LCBEZXNrKVxyXG4gICAqIEBwYXJhbSBtYXR0ZXJ0YWdJRCBzdHJpbmdcclxuICAgKiBAcGFyYW0gb2JqZWN0IFRpY2tldCwgRXF1aXBtZW50LCBGZWF0dXJlLCBEZXNrXHJcbiAgICogQHBhcmFtIHBvaVR5cGUgUG9pVHlwZVxyXG4gICAqIEBwYXJhbSBwb2kgUE9JXHJcbiAgICovXHJcbiAgYXN5bmMgc2V0T2JqZWN0QW5kUG9pSW5UYWcoXHJcbiAgICBtYXR0ZXJ0YWdJRDogc3RyaW5nLFxyXG4gICAgb2JqZWN0OiBEYk9iamVjdFR5cGUsXHJcbiAgICBwb2lUeXBlOiBQb2lUeXBlLFxyXG4gICAgcG9pOiBQT0kgfCBudWxsID0gbnVsbFxyXG4gICk6IFByb21pc2U8dm9pZD4ge1xyXG4gICAgdGhpcy5kaWN0aW9ubmFyeVRhZ3MuZ2V0KG1hdHRlcnRhZ0lEKS5zZXRPYmplY3Qob2JqZWN0LCBwb2lUeXBlKTtcclxuICAgIGlmIChwb2kpIHtcclxuICAgICAgdGhpcy5kaWN0aW9ubmFyeVRhZ3MuZ2V0KG1hdHRlcnRhZ0lEKS5zZXRQb2kocG9pKTtcclxuICAgIH1cclxuICAgIHRoaXMuZGljdGlvbm5hcnlUYWdzLmdldChtYXR0ZXJ0YWdJRCkuZWxlbWVudElEID0gb2JqZWN0LmlkO1xyXG4gICAgdHJ5IHtcclxuICAgICAgYXdhaXQgdGhpcy51cGRhdGVNYXR0ZXJUYWdDb250ZW50Rm9yVGFnSUQobWF0dGVydGFnSUQsIG9iamVjdCwgcG9pVHlwZSk7XHJcbiAgICAgIC8vIFRPRE86IGZpeCB0aGlzXHJcbiAgICAgIGF3YWl0IHRoaXMudXBkYXRlTWF0dGVyVGFnUG9zSW5TZGtWaWV3ZXIoXHJcbiAgICAgICAgbWF0dGVydGFnSUQsXHJcbiAgICAgICAgb2JqZWN0LFxyXG4gICAgICAgIHBvaVR5cGUsXHJcbiAgICAgICAgcG9pXHJcbiAgICAgICk7XHJcbiAgICB9IGNhdGNoIChlKSB7XHJcbiAgICAgIGNvbnNvbGUubG9nKGBlcnJvciBpbiBzZXRPYmplY3RBbmRQb2lJblRhZzogJHtlfWApO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgYXN5bmMgdXBkYXRlTWF0dGVyVGFnUG9zSW5TZGtWaWV3ZXIoXHJcbiAgICBtYXR0ZXJ0YWdJRDogc3RyaW5nLFxyXG4gICAgb2JqZWN0OiBEYk9iamVjdFR5cGUsXHJcbiAgICBwb2lUeXBlOiBQb2lUeXBlLFxyXG4gICAgcG9pOiBQT0kgfCBudWxsID0gbnVsbFxyXG4gICk6IFByb21pc2U8dm9pZD4ge1xyXG4gICAgY29uc3QgSW5kZXhUb1VwZGF0ZSA9IG9iamVjdC5wb2lzLml0ZW1zLmZpbmRJbmRleCgodSkgPT4gdS5pZCA9PT0gcG9pLmlkKTtcclxuICAgIG9iamVjdC5wb2lzLml0ZW1zW0luZGV4VG9VcGRhdGVdID0gcG9pO1xyXG4gICAgY29uc3Qge3gsIHksIHp9ID0gSlNPTi5wYXJzZShwb2kuY29vcmRpbmF0ZSk7XHJcbiAgICBjb25zdCBuZXdQb3NpdGlvbiA9IHtcclxuICAgICAgYW5jaG9yUG9zaXRpb246IHtcclxuICAgICAgICB4OiB4LFxyXG4gICAgICAgIHk6IHksXHJcbiAgICAgICAgejogeixcclxuICAgICAgfSxcclxuICAgICAgc3RlbVZlY3Rvcjoge1xyXG4gICAgICAgIC8vIG1ha2UgdGhlIFRhZyBzdGljayBzdHJhaWdodCB1cCBhbmQgbWFrZSBpdCAwLjMwIG1ldGVycyAofjEgZm9vdCkgdGFsbFxyXG4gICAgICAgIHg6IDAsXHJcbiAgICAgICAgeTogMC4zLFxyXG4gICAgICAgIHo6IDAsXHJcbiAgICAgIH0sXHJcbiAgICB9O1xyXG4gICAgdGhpcy5zZGsuTWF0dGVydGFnLmVkaXRQb3NpdGlvbihtYXR0ZXJ0YWdJRCwgbmV3UG9zaXRpb24pO1xyXG4gICAgdGhpcy5zZGsuVGFnLmVkaXRQb3NpdGlvbihtYXR0ZXJ0YWdJRCwgbmV3UG9zaXRpb24pO1xyXG4gICAgdGhpcy5kaWN0aW9ubmFyeVRhZ3NcclxuICAgICAgLmdldChtYXR0ZXJ0YWdJRClcclxuICAgICAgLnNldFBvc2l0aW9uKG5ld1Bvc2l0aW9uLmFuY2hvclBvc2l0aW9uKTtcclxuXHJcbiAgICBmb3IgKGxldCB0YWdJZCBvZiB0aGlzLm1hdHRlcnRhZ0lEcykge1xyXG4gICAgICBjb25zdCBjdXJyZW50VGFnID0gdGhpcy5kaWN0aW9ubmFyeVRhZ3MuZ2V0KHRhZ0lkKTtcclxuICAgICAgaWYgKCFjdXJyZW50VGFnKSB7XHJcbiAgICAgICAgY29udGludWU7XHJcbiAgICAgIH1cclxuICAgICAgaWYgKGN1cnJlbnRUYWcuZWxlbWVudElEID09PSBvYmplY3QuaWQgJiYgdGFnSWQgIT09IG1hdHRlcnRhZ0lEKSB7XHJcbiAgICAgICAgdGhpcy5kaWN0aW9ubmFyeVRhZ3MuZGVsZXRlKHRhZ0lkKTtcclxuICAgICAgICB0aGlzLnNkay5UYWcucmVtb3ZlKHRhZ0lkKTtcclxuICAgICAgICB0aGlzLnNkay5NYXR0ZXJ0YWcucmVtb3ZlKHRhZ0lkKTtcclxuICAgICAgICBicmVhaztcclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogR2V0cyBtYXR0ZXJUYWdJRCBhbmQgaXRzIHN3ZWVwIGZvciBhbiBvYmplY3QgSUQgKHRpY2tldCBJRCwgZXRjKVxyXG4gICAqIEBwYXJhbSBlbGVtZW50SUQgc3RyaW5nXHJcbiAgICogQHJldHVybnMge3RhZzogc3RyaW5nIHwgbnVsbCwgc3dlZXA6IHN0cmluZyB8IG51bGx9XHJcbiAgICovXHJcbiAgcHVibGljIGdldFRhZ0Zyb21FbGVtZW50SWQoZWxlbWVudElEOiBzdHJpbmcpOiB7XHJcbiAgICB0YWc6IHN0cmluZyB8IG51bGw7XHJcbiAgICBzd2VlcDogc3RyaW5nIHwgbnVsbDtcclxuICB9IHtcclxuICAgIGxldCB0YWdJRCA9IG51bGw7XHJcbiAgICBsZXQgc3dlZXBJRCA9IG51bGw7XHJcbiAgICBmb3IgKGxldCBbbWF0dGVydGFnSUQsIG1hdHRlcnRhZ0RhdGFdIG9mIHRoaXMuZGljdGlvbm5hcnlUYWdzKSB7XHJcbiAgICAgIGlmIChtYXR0ZXJ0YWdEYXRhLmVsZW1lbnRJRCA9PT0gZWxlbWVudElEKSB7XHJcbiAgICAgICAgdGFnSUQgPSBtYXR0ZXJ0YWdJRDtcclxuICAgICAgICBjb25zdCBzd2VlcCA9IG1hdHRlcnRhZ0RhdGEuZ2V0U3dlZXBJRCgpO1xyXG4gICAgICAgIGlmIChzd2VlcCAmJiB0aGlzLnN3ZWVwcyAmJiB0aGlzLnN3ZWVwcy5pbmNsdWRlcyhzd2VlcCkpIHtcclxuICAgICAgICAgIHN3ZWVwSUQgPSBzd2VlcDtcclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuICAgIH1cclxuICAgIHJldHVybiB7dGFnOiB0YWdJRCwgc3dlZXA6IHN3ZWVwSUR9O1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogR2V0cyBsYXRlc3QgdGFnIGNyZWF0ZWQgaW4gdGhlIHZpc2l0ICh3aGVuIGZvbGxvd2luZyB0aGUgY3Vyc29yIHRvIHBvc2l0aW9uKVxyXG4gICAqIEByZXR1cm5zIHN0cmluZyBtYXR0ZXJ0YWdJRFxyXG4gICAqL1xyXG4gIGdldExhc3RUYWcoKTogc3RyaW5nIHwgbnVsbCB7XHJcbiAgICBpZiAodGhpcy5tYXR0ZXJ0YWdUb0ZvbGxvdykge1xyXG4gICAgICByZXR1cm4gdGhpcy5tYXR0ZXJ0YWdUb0ZvbGxvdztcclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIHJldHVybiB0aGlzLm1hdHRlcnRhZ0lEcy5sZW5ndGggPT09IDBcclxuICAgICAgICA/IG51bGxcclxuICAgICAgICA6IHRoaXMubWF0dGVydGFnSURzW3RoaXMubWF0dGVydGFnSURzLmxlbmd0aCAtIDFdO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogR2V0cyBNYXR0ZXJ0YWdEYXRhIGZvciBNYXR0ZXJ0YWcgKHJlcGxhY2VzIGdldFRhZ0RhdGFGcm9tSWQpXHJcbiAgICogQHBhcmFtIG1hdHRlcnRhZ0lEXHJcbiAgICogQHJldHVybnMgTWF0dGVydGFnRGF0YVxyXG4gICAqL1xyXG4gIGdldE1hdHRlclRhZ0RhdGFGb3JNYXR0ZXJ0YWcobWF0dGVydGFnSUQ6IHN0cmluZyk6IE1hdHRlcnRhZ0RhdGEgfCBudWxsIHtcclxuICAgIHRyeSB7XHJcbiAgICAgIHJldHVybiB0aGlzLmRpY3Rpb25uYXJ5VGFncy5nZXQobWF0dGVydGFnSUQpO1xyXG4gICAgfSBjYXRjaCB7XHJcbiAgICAgIGNvbnNvbGUubG9nKCdjYW5ub3QgcmV0cmlldmUgbWF0dGVydGFnRGF0YSBmb3IgdGFnJywgbWF0dGVydGFnSUQpO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIG51bGw7XHJcbiAgfVxyXG5cclxuICAvL1xyXG4gIC8vIC0tLS0tLS0tLS0gVmlld2VyIHJlbGF0ZWQgKHN3aXRjaCB2aWV3cywgZ28gdG8pIC0tLS0tLS0tLS1cclxuICAvL1xyXG4gIGFzeW5jIGFjdGlvbl90b29sYm94X2Zsb29ycGxhbigpIHtcclxuICAgIGlmICh0aGlzLmluVHJhbnNpdGlvbk1vZGUgfHwgdGhpcy5pblRyYW5zaXRpb25Td2VlcCkge1xyXG4gICAgICBjb25zb2xlLmxvZygndmlld2VyIGlzIGluIHRyYW5zaXRpb24sIGNhbm5vdCBnbyBmbG9vcnBsYW4nKTtcclxuICAgICAgcmV0dXJuO1xyXG4gICAgfVxyXG4gICAgdHJ5IHtcclxuICAgICAgYXdhaXQgdGhpcy5zZGsuTW9kZS5tb3ZlVG8oJ21vZGUuZmxvb3JwbGFuJyk7XHJcbiAgICB9IGNhdGNoIChlKSB7XHJcbiAgICAgIGNvbnNvbGUubG9nKCdjYW5ub3QgZ28gdG8gZmxvb3JwbGFuJywgZSk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBhY3Rpb25fdG9vbGJveF9pbnNpZGVfdmlldygpIHtcclxuICAgIHRoaXMuc2RrLk1vZGUubW92ZVRvKCdtb2RlLmluc2lkZScpO1xyXG4gIH1cclxuXHJcbiAgYWN0aW9uU2hvd0FsbEZsb29ycygpIHtcclxuICAgIHRyeSB7XHJcbiAgICAgIHRoaXMuc2RrLkZsb29yLnNob3dBbGwoKTtcclxuICAgIH0gY2F0Y2ggKGUpIHtcclxuICAgICAgY29uc29sZS5sb2coJ2Nhbm5vdCBzaG93IGFsbCBmbG9vcnMnLCBlKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIGFzeW5jIGFjdGlvbl90b29sYm94X2RvbGxob3VzZSgpIHtcclxuICAgIHNldFRpbWVvdXQoYXN5bmMgKCkgPT4ge1xyXG4gICAgICAvLyBjb25zb2xlLmxvZyhcIm1vZGU6IFwiLCB0aGlzLmluVHJhbnNpdGlvbk1vZGUsIFwiIHN3ZWVwOiBcIiwgdGhpcy5pblRyYW5zaXRpb25Td2VlcCk7XHJcbiAgICAgIGlmICh0aGlzLmluVHJhbnNpdGlvbk1vZGUgfHwgdGhpcy5pblRyYW5zaXRpb25Td2VlcCkge1xyXG4gICAgICAgIGNvbnNvbGUubG9nKCd2aWV3ZXIgaXMgaW4gdHJhbnNpdGlvbiwgY2Fubm90IGdvIGRvbGxob3VzZScpO1xyXG4gICAgICAgIHJldHVybjtcclxuICAgICAgfVxyXG4gICAgICB0cnkge1xyXG4gICAgICAgIGF3YWl0IHRoaXMuc2RrLk1vZGUubW92ZVRvKCdtb2RlLmRvbGxob3VzZScpO1xyXG4gICAgICB9IGNhdGNoIChlKSB7XHJcbiAgICAgICAgY29uc29sZS5sb2coJ2Nhbm5vdCBnbyB0byBkb2xsaG91c2UnLCBlKTtcclxuICAgICAgfVxyXG4gICAgfSwgMTIwMCk7XHJcbiAgfVxyXG5cclxuICBhY3Rpb25fdG9vbGJveF9tZXN1cmUoKSB7XHJcbiAgICBjb25zdCBuZXdTdGF0ZSA9ICF0aGlzLmlzTWVhc3VyZU1vZGVPbjtcclxuICAgIHRoaXMuc2RrLk1lYXN1cmVtZW50cy50b2dnbGVNb2RlKG5ld1N0YXRlKS50aGVuKCgpID0+IHtcclxuICAgICAgY29uc29sZS5sb2coXHJcbiAgICAgICAgYE1lYXN1cmVtZW50IG1vZGUgaXMgbm93ICR7bmV3U3RhdGUgPyAnZW5hYmxlZCcgOiAnZGlzYWJsZWQnfWBcclxuICAgICAgKTtcclxuICAgIH0pO1xyXG4gIH1cclxuXHJcbiAgYWN0aW9uX3Rvb2xib3hfY2FuY2VsX21lc3VyZSgpIHtcclxuICAgIGlmICh0aGlzLmlzTWVhc3VyZU1vZGVPbikge1xyXG4gICAgICB0aGlzLmFjdGlvbl90b29sYm94X21lc3VyZSgpO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgYXN5bmMgYWN0aW9uX2dvX3RvX2Zsb29yKFxyXG4gICAgZmxvb3JOYW1lOiBzdHJpbmcsXHJcbiAgICBtYXR0ZXJwb3J0Rmxvb3JTZXF1ZW5jZTogbnVtYmVyID0gbnVsbFxyXG4gICkge1xyXG4gICAgaWYgKCF0aGlzLmZsb29ycykge1xyXG4gICAgICBjb25zb2xlLmxvZygnRmxvb3IgYXJlIG5vdCBsb2FkZWQgeWV0Jyk7XHJcbiAgICAgIHJldHVybjtcclxuICAgIH1cclxuICAgIC8vIGNvbnNvbGUubG9nKHRoaXMuZmxvb3JzKTtcclxuICAgIC8vIGxvb2sgdXAgZm9yIHNlcXVlbmNlIG51bWJlciAodGhlIHNhZmVzdCBtZXRob2QpXHJcbiAgICBsZXQgZmxvb3JNYXR0ZXJwb3J0ID0gdGhpcy5mbG9vcnMuZmluZChcclxuICAgICAgKGZsb29yKSA9PiBmbG9vci5zZXF1ZW5jZSA9PT0gbWF0dGVycG9ydEZsb29yU2VxdWVuY2VcclxuICAgICk7XHJcbiAgICBpZiAoIWZsb29yTWF0dGVycG9ydCkge1xyXG4gICAgICBmbG9vck1hdHRlcnBvcnQgPSB0aGlzLmZsb29ycy5maW5kKFxyXG4gICAgICAgIChmbG9vcikgPT4gZmxvb3JOYW1lLmluY2x1ZGVzKGZsb29yLm5hbWUpICYmIGZsb29yLm5hbWUgIT0gJydcclxuICAgICAgKTtcclxuICAgIH1cclxuICAgIGlmICghZmxvb3JNYXR0ZXJwb3J0KSB7XHJcbiAgICAgIGZsb29yTWF0dGVycG9ydCA9IHRoaXMuZmxvb3JzLmZpbmQoKGZsb29yKSA9PlxyXG4gICAgICAgIGZsb29yTmFtZS5pbmNsdWRlcyhmbG9vci5pZClcclxuICAgICAgKTtcclxuICAgIH1cclxuICAgIC8vIGNvbnNvbGUubG9nKGZsb29yTWF0dGVycG9ydClcclxuICAgIGlmIChmbG9vck1hdHRlcnBvcnQpIHtcclxuICAgICAgbGV0IHJldHJ5ID0gdHJ1ZTtcclxuICAgICAgd2hpbGUgKHJldHJ5KSB7XHJcbiAgICAgICAgdHJ5IHtcclxuICAgICAgICAgIGNvbnN0IGZsb29ySW5kZXggPSBhd2FpdCB0aGlzLnNkay5GbG9vci5tb3ZlVG8oXHJcbiAgICAgICAgICAgIGZsb29yTWF0dGVycG9ydC5zZXF1ZW5jZVxyXG4gICAgICAgICAgKTtcclxuICAgICAgICAgIC8vIGNvbnNvbGUubG9nKFwibW92ZWQgdG8gZmxvb3JJbmRleFwiLCBmbG9vckluZGV4KTtcclxuICAgICAgICAgIHJldHJ5ID0gZmFsc2U7XHJcbiAgICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcclxuICAgICAgICAgIGNvbnNvbGUubG9nKCdDYW5ub3QgbW92ZSB0byBGbG9vcicsIGVycm9yKTtcclxuICAgICAgICAgIGF3YWl0IHdhaXQoMTAwKTtcclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIGNvbnNvbGUud2FybignTm8gbWF0dGVycG9ydCBmbG9vciBmb3VuZCB0byBtb3ZlIHRvJyk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBhc3luYyBhY3Rpb25fZ29fdG9fc3dlZXAoXHJcbiAgICBzd2VlcDogc3RyaW5nLFxyXG4gICAgcm90YXRpb246IHsgeDogbnVtYmVyOyB5OiBudW1iZXIgfSA9IG51bGxcclxuICApIHtcclxuICAgIGlmICh0aGlzLmZvcmJpZGRlblN3ZWVwcy5pbmNsdWRlcyhzd2VlcCkpIHtcclxuICAgICAgY29uc29sZS5sb2coJ3VzZXIgaXMgbm90IGFsbG93ZWQgdG8gZ28gdG8gdGhpcyBzd2VlcCcpO1xyXG4gICAgICByZXR1cm47XHJcbiAgICB9XHJcbiAgICAvLyBjb25zb2xlLmxvZyhcImdvaW5nIHRvIHN3ZWVwXCIsIHN3ZWVwLCBcIndpdGggcm90YXRpb246XCIsIHJvdGF0aW9uKTtcclxuICAgIHNldFRpbWVvdXQoYXN5bmMgKCkgPT4ge1xyXG4gICAgICBpZiAodGhpcy5pblRyYW5zaXRpb25Nb2RlIHx8IHRoaXMuaW5UcmFuc2l0aW9uU3dlZXApIHtcclxuICAgICAgICBjb25zb2xlLmxvZygnQ2Fubm90IGdvIHRvIHN3ZWVwLCBpbiB0cmFuc2l0aW9uJyk7XHJcbiAgICAgICAgcmV0dXJuO1xyXG4gICAgICB9XHJcbiAgICAgIHRyeSB7XHJcbiAgICAgICAgdGhpcy5pblRyYW5zaXRpb25Td2VlcCA9IHRydWU7XHJcbiAgICAgICAgYXdhaXQgdGhpcy5zZGsuU3dlZXAubW92ZVRvKHN3ZWVwLCB7XHJcbiAgICAgICAgICB0cmFuc2l0aW9uOiAndHJhbnNpdGlvbi5pbnN0YW50JyxcclxuICAgICAgICAgIHRyYW5zaXRpb25UaW1lOiAxNTAwLFxyXG4gICAgICAgIH0pO1xyXG4gICAgICB9IGNhdGNoIChlcnJvcikge1xyXG4gICAgICAgIHRoaXMuaW5UcmFuc2l0aW9uU3dlZXAgPSBmYWxzZTtcclxuICAgICAgICBjb25zb2xlLmxvZygnQ2Fubm90IG1vdmUgdG8gc3dlZXAnLCBlcnJvcik7XHJcbiAgICAgIH1cclxuICAgICAgaWYgKHJvdGF0aW9uKSB7XHJcbiAgICAgICAgYXdhaXQgdGhpcy5zZGsuQ2FtZXJhLnNldFJvdGF0aW9uKHJvdGF0aW9uLCB7c3BlZWQ6IDEwMH0pOyAvLyBzcGVlZCBpcyBkZWdyZWVzIHBlciBzZWNvbmRcclxuICAgICAgfVxyXG4gICAgfSwgMTAwMCk7XHJcbiAgfVxyXG5cclxuICBnZXRDdXJyZW50U3dlZXAoKTogc3RyaW5nIHwgbnVsbCB7XHJcbiAgICBpZiAodGhpcy5wb3NlQ2FtZXJhKSB7XHJcbiAgICAgIHJldHVybiB0aGlzLnBvc2VDYW1lcmEuc3dlZXA7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gbnVsbDtcclxuICB9XHJcblxyXG4gIGdldEN1cnJlbnRDYW1lcmFQb3NpdGlvbigpOiB7XHJcbiAgICByb3RhdGlvbjogYW55O1xyXG4gICAgcG9zaXRpb246IGFueTtcclxuICAgIHN3ZWVwOiBhbnk7XHJcbiAgfSB8IG51bGwge1xyXG4gICAgaWYgKHRoaXMucG9zZUNhbWVyYSkge1xyXG4gICAgICByZXR1cm4gdGhpcy5wb3NlQ2FtZXJhO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIG51bGw7XHJcbiAgfVxyXG5cclxuICBzZXRJbnRlcmFjdGlvbk1vZGUoaW50ZXJhY3Rpb25Nb2RlOiBudW1iZXIpIHtcclxuICAgIHRoaXMuaW50ZXJhY3Rpb25Nb2RlID0gaW50ZXJhY3Rpb25Nb2RlO1xyXG4gIH1cclxuXHJcbiAgZ2V0SW50ZXJhY3Rpb25Nb2RlKCkge1xyXG4gICAgcmV0dXJuIHRoaXMuaW50ZXJhY3Rpb25Nb2RlO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogQ2xlYXIgYWxsIHZhcmlhYmxlcywgZGVsZXRlcyBhbGwgdGFncyAod2hlbiB2aWV3ZXIgaXMgcmVtb3ZlciBvciBtb2RlbCBjaGFuZ2VkPXJlbG9hZCBuZWVkZWQpXHJcbiAgICovXHJcbiAgYXN5bmMgY2xlYXJBbGwoKSB7XHJcbiAgICBjb25zb2xlLmxvZygncmVtb3Zpbmcgdmlld2VyJyk7XHJcbiAgICB0aGlzLmFjdGlvbl9kZWxldGVfYWxsX21hdHRlcnRhZ3MoKTtcclxuICAgIHRoaXMuZmxvb3JzID0gbnVsbDtcclxuICAgIHRoaXMuc3dlZXBzID0gbnVsbDtcclxuICAgIHRoaXMuc2RrID0gbnVsbDtcclxuICAgIGNsZWFySW50ZXJ2YWwodGhpcy50aW1lclBvaW50ZXIpO1xyXG4gICAgdGhpcy5mb3JiaWRkZW5Td2VlcHMgPSBbXTtcclxuICAgIHRoaXMudGFnTWVzc2VuZ2VyT24gPSBmYWxzZTtcclxuICAgIC8vIGNhbmNlbCBzdWJzY3JpcHRpb25zXHJcbiAgICB0aGlzLnBvaW50ZXJCdXR0b24ucmVtb3ZlRXZlbnRMaXN0ZW5lcihcclxuICAgICAgJ2NsaWNrJyxcclxuICAgICAgdGhpcy5wb2ludGVyTGVmdENsaWNrSGFuZGxlclxyXG4gICAgKTtcclxuICAgIHRoaXMucG9pbnRlckJ1dHRvbi5yZW1vdmVFdmVudExpc3RlbmVyKFxyXG4gICAgICAnY29udGV4dG1lbnUnLFxyXG4gICAgICB0aGlzLnBvaW50ZXJSaWdodENsaWNrSGFuZGxlclxyXG4gICAgKTtcclxuXHJcbiAgICAvLyBUT0RPOiBvbmx5IEZvciBBZG1pbnNcclxuICAgIGlmICh0aGlzLmdldEN1cnNvclBvc2l0aW9uQnV0dG9uKSB7XHJcbiAgICAgIHRoaXMuZ2V0Q3Vyc29yUG9zaXRpb25CdXR0b24ucmVtb3ZlRXZlbnRMaXN0ZW5lcihcclxuICAgICAgICAnYXV4Y2xpY2snLFxyXG4gICAgICAgIHRoaXMucG9pbnRlck1pZGRsZUNsaWNrSGFuZGxlclxyXG4gICAgICApO1xyXG4gICAgfVxyXG4gICAgLy8gVE9ETzogb25seSBmb3IgZGV2IVxyXG4gICAgaWYgKCEhdGhpcy5nZXRDdXJzb3JQb3NpdGlvbkJ1dHRvbiAmJlxyXG4gICAgICAoZG9jdW1lbnQubG9jYXRpb24uaHJlZi5pbmRleE9mKCdkZXYnKSAhPT0gLTEgfHwgZG9jdW1lbnQubG9jYXRpb24uaHJlZi5pbmRleE9mKCdsb2NhbGhvc3QnKSAhPT0gLTEpKSB7XHJcbiAgICAgIGNsZWFySW50ZXJ2YWwodGhpcy5pbnRlcnZhbEN1cnNvclBvaW50ZXJQb3NpdGlvbik7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBhc3luYyByZW1vdmVGb3JiaWRkZW5Td2VlcHMoZm9yYmlkZGVuU3dlZXBzOiBzdHJpbmdbXSkge1xyXG4gICAgdGhpcy5mb3JiaWRkZW5Td2VlcHMgPSBbLi4uZm9yYmlkZGVuU3dlZXBzXTtcclxuICAgIGxldCByZW1vdmVkID0gMDtcclxuICAgIGF3YWl0IFByb21pc2UuYWxsKFxyXG4gICAgICBmb3JiaWRkZW5Td2VlcHMubWFwKGFzeW5jIChzd2VlcCkgPT4ge1xyXG4gICAgICAgIHRyeSB7XHJcbiAgICAgICAgICBhd2FpdCB0aGlzLnNkay5Td2VlcC5kaXNhYmxlKHN3ZWVwKTtcclxuICAgICAgICAgIHJlbW92ZWQgKz0gMTtcclxuICAgICAgICB9IGNhdGNoIChlcnJvcikge1xyXG4gICAgICAgICAgY29uc29sZS5sb2coZXJyb3IpO1xyXG4gICAgICAgIH1cclxuICAgICAgfSlcclxuICAgICk7XHJcbiAgICBjb25zb2xlLmxvZygncmVtb3ZlZCBzd2VlcHM6JywgcmVtb3ZlZCk7XHJcbiAgfVxyXG5cclxuICAvL1xyXG4gIC8vIC0tLS0tLS0tLS0gM0Qgb2JqZWN0cyAoU0RLIEJ1bmRsZSBvbmx5KSAtLS0tLS0tLS0tXHJcbiAgLy9cclxuICBhc3luYyBpbml0M0RPYmplY3RWaWV3ZXIoKTogUHJvbWlzZTx2b2lkPiB7XHJcbiAgICByZXR1cm4gbmV3IFByb21pc2UoYXN5bmMgKHJlc29sdmUpID0+IHtcclxuICAgICAgdmFyIFtzY2VuZU9iamVjdF0gPSBhd2FpdCB0aGlzLnNkay5TY2VuZS5jcmVhdGVPYmplY3RzKDEpO1xyXG5cclxuICAgICAgdmFyIG5vZGUgPSBzY2VuZU9iamVjdC5hZGROb2RlKCk7XHJcblxyXG4gICAgICAvLyBUT0RPIGNoYW5nZSB0aGlzIPCfpK5cclxuICAgICAgbm9kZS5hZGRDb21wb25lbnQoJ21wLmxpZ2h0cycpO1xyXG4gICAgICAvL25vZGUuYWRkQ29tcG9uZW50KCdtcC5saWdodHMnKTtcclxuICAgICAgLypub2RlLmFkZENvbXBvbmVudCgnbXAubGlnaHRzJyk7XHJcbiAgICAgIG5vZGUuYWRkQ29tcG9uZW50KCdtcC5saWdodHMnKTsqL1xyXG4gICAgICBub2RlLnN0YXJ0KCk7XHJcblxyXG4gICAgICBjb25zdCBub2RlQ29udHJvbCA9IHNjZW5lT2JqZWN0LmFkZE5vZGUoKTtcclxuICAgICAgdGhpcy5vYmplY3RDb250cm9sID0gbm9kZUNvbnRyb2wuYWRkQ29tcG9uZW50KCdtcC50cmFuc2Zvcm1Db250cm9scycpO1xyXG4gICAgICBub2RlQ29udHJvbC5zdGFydCgpO1xyXG5cclxuICAgICAgLy90aGlzLmFkZDNET2JqZWN0KHt9LG51bGwpO1xyXG5cclxuICAgICAgcmVzb2x2ZSgpO1xyXG4gICAgfSk7XHJcbiAgfVxyXG5cclxuICBhc3luYyBhZGQzRE9iamVjdChcclxuICAgIG9iajogSU9iamVjdDNELFxyXG4gICAgbW9kZT86ICd0cmFuc2xhdGUnIHwgJ3JvdGF0ZSdcclxuICApOiBQcm9taXNlPGFueT4ge1xyXG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKGFzeW5jIChyZXNvbHZlKSA9PiB7XHJcbiAgICAgIGNvbnN0IFtzY2VuZU9iamVjdF0gPSBhd2FpdCB0aGlzLnNkay5TY2VuZS5jcmVhdGVPYmplY3RzKDEpO1xyXG5cclxuICAgICAgLy8gVE9ETzogaW1wcm92bWVudCwgcmVncm91cCBhbGwgb2YgdGhlc2UgaW4gRHluYW1pY2FsIE9iamVjdHMgTGliXHJcbiAgICAgIC8vIFNlY3VyaXR5Q2FtZXJhXHJcbiAgICAgIC8vIE5lc3RUaGVybW9zdGF0XHJcbiAgICAgIC8vIFZpZGVvXHJcbiAgICAgIGxldCBpc0FuaW1hdGVkU2VjdXJpdHlDYW1lcmEgPSBmYWxzZTtcclxuICAgICAgbGV0IGlzTmVzdFRoZXJtb3N0YXQgPSBmYWxzZTtcclxuICAgICAgbGV0IGlzU21hcnRlcnBsYW5Qcm9tb3Rpb25hbFZpZGVvID0gZmFsc2U7XHJcbiAgICAgIGxldCBpc0F6aW11dGhhbENyb3duID0gZmFsc2U7XHJcblxyXG4gICAgICAvKipcclxuICAgICAgICogVE9ETzogcmVmYWN0byB3aXRoIGFuIGVudW0gb3Igc3dpdGNoL2Nhc2VcclxuICAgICAgICovXHJcbiAgICAgIGlmIChvYmoub2JqZWN0ID09PSBcInNlY3VyaXR5X2NhbWVyYVwiKSB7XHJcbiAgICAgICAgaXNBbmltYXRlZFNlY3VyaXR5Q2FtZXJhID0gdHJ1ZTtcclxuICAgICAgfVxyXG4gICAgICBpZiAob2JqLm9iamVjdCA9PT0gXCJuZXN0X3RoZXJtb3N0YXRcIikge1xyXG4gICAgICAgIGlzTmVzdFRoZXJtb3N0YXQgPSB0cnVlO1xyXG4gICAgICB9XHJcbiAgICAgIGlmIChvYmoub2JqZWN0ID09PSAndmlkZW8nKSB7XHJcbiAgICAgICAgaXNTbWFydGVycGxhblByb21vdGlvbmFsVmlkZW8gPSB0cnVlO1xyXG4gICAgICB9XHJcbiAgICAgIGlmKG9iai5vYmplY3QgPT09ICdhemltdXRoJykge1xyXG4gICAgICAgIGlzQXppbXV0aGFsQ3Jvd24gPSB0cnVlO1xyXG4gICAgICB9XHJcblxyXG4gICAgICBjb25zdCBtb2RlbE5vZGUgPSBzY2VuZU9iamVjdC5hZGROb2RlKCk7XHJcbiAgICAgIGxldCBjb21wb25lbnQgPSBudWxsO1xyXG4gICAgICBjb25zdCBpbml0aWFsID0ge1xyXG4gICAgICAgIHVybDogYC9hc3NldHMvM0RvYmplY3RzL29iamVjdHMvJHtvYmoub2JqZWN0fSR7XHJcbiAgICAgICAgICBvYmouZm9ybWF0LmluZGV4T2YoJy4nKSA9PT0gLTEgPyAnLicgKyBvYmouZm9ybWF0IDogb2JqLmZvcm1hdFxyXG4gICAgICAgIH1gLFxyXG4gICAgICAgIC8vIFRPRE8vIHN0b3JlIGxvY2FsUG9zaXRpb24gJiYgbG9jYWxSb3RhdGlvbiBpbiBCREQgdG9vIChpbiBvcmRlciB0byBoYXZlIHBlcnRmZWN0IGluaXRpYWwgcGxhY2VtZW50KVxyXG4gICAgICAgIGxvY2FsUm90YXRpb246IHtcInhcIjogMCwgXCJ5XCI6IDAsIFwielwiOiAwfSxcclxuICAgICAgICAvLyBUT0RPLyBzdG9yZSBsb2NhbFBvc2l0aW9uICYmIGxvY2FsUm90YXRpb24gaW4gQkREIHRvbyAoaW4gb3JkZXIgdG8gaGF2ZSBwZXJ0ZmVjdCBpbml0aWFsIHBsYWNlbWVudClcclxuICAgICAgICBsb2NhbFBvc2l0aW9uOiB7XCJ4XCI6IDAsIFwieVwiOiAwLCBcInpcIjogMH0sXHJcbiAgICAgICAgdmlzaWJsZTogdHJ1ZSxcclxuICAgICAgICBjb2xsaWRlckVuYWJsZWQ6IHRydWVcclxuICAgICAgfTtcclxuXHJcblxyXG4gICAgICBzd2l0Y2ggKG9iai5mb3JtYXQpIHtcclxuICAgICAgICBjYXNlICcub2JqJzpcclxuICAgICAgICBjYXNlICdvYmonOlxyXG4gICAgICAgICAgY29tcG9uZW50ID0gbW9kZWxOb2RlLmFkZENvbXBvbmVudCgnbXAub2JqTG9hZGVyJywgaW5pdGlhbCk7XHJcbiAgICAgICAgICBicmVhaztcclxuICAgICAgICBjYXNlICcuZmJ4JzpcclxuICAgICAgICBjYXNlICdmYngnOlxyXG4gICAgICAgICAgY29tcG9uZW50ID0gbW9kZWxOb2RlLmFkZENvbXBvbmVudCgnbXAuZmJ4TG9hZGVyJywgaW5pdGlhbCk7XHJcbiAgICAgICAgICBicmVhaztcclxuICAgICAgICBjYXNlICcuZ2x0Zic6XHJcbiAgICAgICAgY2FzZSAnZ2x0Zic6XHJcbiAgICAgICAgICBjb21wb25lbnQgPSBtb2RlbE5vZGUuYWRkQ29tcG9uZW50KCdtcC5nbHRmTG9hZGVyJywgaW5pdGlhbCk7XHJcbiAgICAgICAgICBicmVhaztcclxuICAgICAgICBjYXNlICcuZ2xiJzpcclxuICAgICAgICBjYXNlICdnbGInOlxyXG4gICAgICAgICAgY29tcG9uZW50ID0gbW9kZWxOb2RlLmFkZENvbXBvbmVudCgnbXAuZ2x0ZkxvYWRlcicsIGluaXRpYWwpO1xyXG4gICAgICAgICAgYnJlYWs7XHJcbiAgICAgICAgY2FzZSAnLmRhZSc6XHJcbiAgICAgICAgY2FzZSAnZGFlJzpcclxuICAgICAgICAgIGNvbXBvbmVudCA9IG1vZGVsTm9kZS5hZGRDb21wb25lbnQoJ21wLmRhZUxvYWRlcicsIGluaXRpYWwpO1xyXG4gICAgICAgICAgYnJlYWs7XHJcblxyXG4gICAgICAgIGRlZmF1bHQ6XHJcbiAgICAgICAgICBjb25zb2xlLmxvZygnRm9ybWF0IG5vdCBzdXBwb3J0ZWQnKTtcclxuICAgICAgICAgIGJyZWFrO1xyXG4gICAgICB9XHJcblxyXG4gICAgICAvL2NhY2hlIHN5c3RlbSAoaSdsbCB0cnkgdG8gbWFrZSBpdCB3b3JrIGxhdGVyIC4uLilcclxuICAgICAgLypsZXQgb2JqQ29udGVudHNKU09OID0gSlNPTi5zdHJpbmdpZnkobW9kZWxOb2RlKTtcclxuICAgICAgY29uc29sZS5sb2cobW9kZWxOb2RlKTtcclxuICAgICAgY29uc29sZS5sb2cob2JqQ29udGVudHNKU09OKTtcclxuICAgICAgY29uc29sZS5sb2coSlNPTi5zdHJpbmdpZnkobW9kZWxOb2RlKSk7XHJcbiAgICAgIGxvY2FsU3RvcmFnZS5zZXRJdGVtKGB0ZXN0T2JqXyR7b2JqLm9iamVjdH1gLCBvYmpDb250ZW50c0pTT04pO1xyXG4gICAgICBjb25zb2xlLmxvZyhcInN0b3JlZCA/IVwiKTtcclxuICAgICAgY29uc29sZS5sb2codHlwZW9mIG1vZGVsTm9kZSk7Ki9cclxuICAgICAgLy9sZXQgZGF0YVMgPSBzZXJpYWxpanNlLnNlcmlhbGl6ZShtb2RlbE5vZGUpO1xyXG4gICAgICAvL2NvbnNvbGUubG9nKGRhdGFTKTtcclxuXHJcbiAgICAgIC8vIFVzZSAzID8hIEFtYmllbnQgbGlnaHRpbmdzXHJcbiAgICAgIGlmICh0aGlzLm5vTGlnaHRGb3JPYmplY3RzKSB7XHJcbiAgICAgICAgY29uc3QgbGlnaHRzTm9kZSA9IHNjZW5lT2JqZWN0LmFkZE5vZGUoKTtcclxuICAgICAgICBsaWdodHNOb2RlLmFkZENvbXBvbmVudCgnbXAuYW1iaWVudExpZ2h0Jywge1xyXG4gICAgICAgICAgaW50ZW5zaXR5OiAxLFxyXG4gICAgICAgICAgY29sb3I6IHtyOiAxLjAsIGc6IDEuMCwgYjogMS4wfSxcclxuICAgICAgICB9KTtcclxuICAgICAgICB0aGlzLm5vTGlnaHRGb3JPYmplY3RzID0gZmFsc2U7XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIG1vZGVsTm9kZS5vYmozRC5wb3NpdGlvbi5zZXQoXHJcbiAgICAgICAgb2JqLnBvc2l0aW9uLngsXHJcbiAgICAgICAgb2JqLnBvc2l0aW9uLnksXHJcbiAgICAgICAgb2JqLnBvc2l0aW9uLnpcclxuICAgICAgKTtcclxuXHJcbiAgICAgIG1vZGVsTm9kZS5vYmozRC5yb3RhdGlvbi5zZXQoXHJcbiAgICAgICAgb2JqLnJvdGF0aW9uLngsXHJcbiAgICAgICAgb2JqLnJvdGF0aW9uLnksXHJcbiAgICAgICAgb2JqLnJvdGF0aW9uLnpcclxuICAgICAgKTtcclxuICAgICAgbW9kZWxOb2RlLm9iajNELnNjYWxlLnNldChvYmouc2NhbGUueCwgb2JqLnNjYWxlLnksIG9iai5zY2FsZS56KTtcclxuICAgICAgaWYoaXNBemltdXRoYWxDcm93bilcclxuICAgICAge1xyXG4gICAgICAgIC8qaWYobW9kZWxOb2RlLm9iajNELnNjYWxlLnggPj0gMS4wKXtcclxuICAgICAgICAgIG1vZGVsTm9kZS5vYmozRC5zY2FsZS5zZXQob2JqLnNjYWxlLngvNTAwMCwgb2JqLnNjYWxlLnkvNTAwMCwgb2JqLnNjYWxlLnovNTAwMCk7XHJcbiAgICAgICAgfSovXHJcbiAgICAgICAgdGhpcy5hemltdXRoYWxDcm93bj1tb2RlbE5vZGU7XHJcbiAgICAgICAgdGhpcy5kaXNwbGF5QXppbXV0YWxDcm93bigpO1xyXG4gICAgICB9XHJcblxyXG4gICAgICAvLyBCeSBkZWZhdXQsIGR1cmluZyBjcmVhdGlvbiwgb2JqZWN0IGhhcyB0cmFuc2xhdGlvbiBnaXptb1xyXG4gICAgICAvLyA9PiBVc2VyIGhhcyB0byBjbGljayBvbiBsYXRlcmFsIHBhbmVsLCBhbmQgc2F2ZSBpdHMgcG9zaXRpb24gYWZ0ZXIgcGxheWluZyB3aXRoIGl0IVxyXG4gICAgICBpZiAobW9kZSAmJiAhaXNOZXN0VGhlcm1vc3RhdCkge1xyXG4gICAgICAgIHRoaXMuYXR0YWNoR2l6bW9Db250cm9sVG8zRE9iamVjdChcclxuICAgICAgICAgIG1vZGVsTm9kZSxcclxuICAgICAgICAgIHNjZW5lT2JqZWN0LFxyXG4gICAgICAgICAgbW9kZSxcclxuICAgICAgICAgIHRydWVcclxuICAgICAgICApLmNhdGNoKChlKSA9PiBjb25zb2xlLmxvZyhlKSk7XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIGlmICh0aGlzLmxhc3RPYmplY3QzRCAmJiB0eXBlb2YgdGhpcy5sYXN0T2JqZWN0M0QuaWQgPT09ICdzdHJpbmcnKSB7XHJcbiAgICAgICAgLy8gcHJvbXB0IFRocmVlSlMgVVVJRCB0byBtYXRjaCBvdXIgbGFzdCBnZW5lcmF0ZWQgb2JqZWN0IGlmIG5ldyAobm90IGZyb20gRGIpXHJcbiAgICAgICAgbW9kZWxOb2RlLm9iajNELnV1aWQgPSB0aGlzLmxhc3RPYmplY3QzRC5pZDtcclxuICAgICAgfSBlbHNlIGlmIChvYmouaWQpIHtcclxuICAgICAgICBtb2RlbE5vZGUub2JqM0QudXVpZCA9IG9iai5pZDtcclxuICAgICAgfVxyXG4gICAgICB0aGlzLmxhc3RPYmplY3QzRCA9IG1vZGVsTm9kZS5vYmozRDtcclxuXHJcbiAgICAgIC8vIFN0b3JlIHRoaXMgaW4gbWVtb3J5IE1hcCBkaWN0aW9ubmFyeVxyXG4gICAgICAvL2NvbnNvbGUubG9nKFwiQWRkaW5nIG9iamVjdDogXCIpO1xyXG4gICAgICAvL2NvbnNvbGUubG9nKG1vZGVsTm9kZSk7XHJcbiAgICAgIHRoaXMuZGljdGlvbm5hcnlPYmplY3RzM0Quc2V0KG1vZGVsTm9kZS5vYmozRC51dWlkLCBtb2RlbE5vZGUpO1xyXG4gICAgICB0aGlzLmRpY3Rpb25uYXJ5U2NlbmVPYmplY3RzM0Quc2V0KG1vZGVsTm9kZS5vYmozRC51dWlkLCBzY2VuZU9iamVjdCk7XHJcblxyXG4gICAgICAvKnRoaXMuc2RrLkNhbWVyYS5wb3NlLnN1YnNjcmliZShcclxuICAgICAgICBmdW5jdGlvbiAocG9zZTogYW55KSB7XHJcbiAgICAgICAgICAvL2NvbnNvbGUubG9nKFwiaW4gY2FsbGJhY2tcIilcclxuICAgICAgICAgIC8vY29uc29sZS5sb2codGhpcy5sYXN0Q2FtZXJhUG9zaXRpb24pXHJcbiAgICAgICAgICAvL2NvbnNvbGUubG9nKHBvc2UucG9zaXRpb24pXHJcbiAgICAgICAgICBpZigocG9zZS5wb3NpdGlvbi54ID09IHRoaXMubGFzdENhbWVyYVBvc2l0aW9uLnggJiYgcG9zZS5wb3NpdGlvbi55ID09IHRoaXMubGFzdENhbWVyYVBvc2l0aW9uLnkgJiYgcG9zZS5wb3NpdGlvbi56ID09IHRoaXMubGFzdENhbWVyYVBvc2l0aW9uLnopIHx8IHRoaXMuaW5UcmFuc2l0aW9uTW9kZSB8fCB0aGlzLmluVHJhbnNpdGlvblN3ZWVwKXtcclxuICAgICAgICAgICAgLy9jb25zb2xlLmxvZyhcInJldHVybmluZ1wiKVxyXG4gICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgICBjb25zb2xlLmxvZyhcImNhbWVyYSBwb3M6XCIscG9zZS5wb3NpdGlvbik7XHJcbiAgICAgICAgICB0aGlzLmxhc3RDYW1lcmFQb3NpdGlvbiA9IHsuLi5wb3NlLnBvc2l0aW9ufTtcclxuICAgICAgICAgIGlmKHRoaXMubGFzdE9iamVjdDNEKXtcclxuICAgICAgICAgICAgdGhpcy5sYXN0T2JqZWN0M0QucG9zaXRpb24uc2V0KHBvc2UucG9zaXRpb24ueCsuNSxwb3NlLnBvc2l0aW9uLnkrLjUscG9zZS5wb3NpdGlvbi56Ky41KTtcclxuICAgICAgICAgIH1cclxuICAgICAgICB9LmJpbmQodGhpcykpOyovXHJcblxyXG4gICAgICBpZiAoaXNBbmltYXRlZFNlY3VyaXR5Q2FtZXJhKSB7XHJcblxyXG4gICAgICAgIGNvbnN0IGFuaW1hdG9yID0gbW9kZWxOb2RlLmFkZENvbXBvbmVudCgnbXAuc2VjdXJpdHlDYW1lcmEnLFxyXG4gICAgICAgICAge1xyXG4gICAgICAgICAgICBcIm5lYXJQbGFuZVwiOiAwLjEsXHJcbiAgICAgICAgICAgIFwiZmFyUGxhbmVcIjogMTAsXHJcbiAgICAgICAgICAgIFwiaG9yaXpvbnRhbEZPVlwiOiA1MixcclxuICAgICAgICAgICAgXCJhc3BlY3RcIjogMS43Nzc3Nzc3Nzc3Nzc3Nzc3LFxyXG4gICAgICAgICAgICBcImxvY2FsUG9zaXRpb25cIjoge1xyXG4gICAgICAgICAgICAgIFwieFwiOiAwLjMsXHJcbiAgICAgICAgICAgICAgXCJ5XCI6IDAuMTgsXHJcbiAgICAgICAgICAgICAgXCJ6XCI6IDBcclxuICAgICAgICAgICAgfSxcclxuICAgICAgICAgICAgXCJsb2NhbFJvdGF0aW9uXCI6IHtcclxuICAgICAgICAgICAgICBcInhcIjogLTE1LFxyXG4gICAgICAgICAgICAgIFwieVwiOiAtOTAsXHJcbiAgICAgICAgICAgICAgXCJ6XCI6IDBcclxuICAgICAgICAgICAgfSxcclxuICAgICAgICAgICAgXCJjb2xvclwiOiA2NTI4MCxcclxuICAgICAgICAgICAgXCJwYW5QZXJpb2RcIjogNSxcclxuICAgICAgICAgICAgXCJwYW5BbmdsZVwiOiAtNDVcclxuICAgICAgICAgIH0pO1xyXG4gICAgICAgIGNvbnN0IG1vZGVsT3V0cHV0ID0gc2NlbmVPYmplY3QuYWRkUGF0aCh7XHJcbiAgICAgICAgICBpZDogJ2FuaW1hdGVkLW1vZGVsJyxcclxuICAgICAgICAgIHR5cGU6IHRoaXMuc2RrLlNjZW5lLlBhdGhUeXBlLk9VVFBVVCxcclxuICAgICAgICAgIG5vZGU6IG1vZGVsTm9kZSxcclxuICAgICAgICAgIGNvbXBvbmVudDogYW5pbWF0b3IsXHJcbiAgICAgICAgICBwcm9wZXJ0eTogJ29iamVjdFJvb3QnXHJcbiAgICAgICAgfSk7XHJcblxyXG4gICAgICAgIHRoaXMuc2VjdXJpdHlDYW1lcmFBbmltYXRvciA9IGFuaW1hdG9yO1xyXG4gICAgICAgIGlmICghb2JqLnZpZXdGcnVzdHVtKSB7XHJcbiAgICAgICAgICBzZXRUaW1lb3V0KCgpID0+IHtcclxuICAgICAgICAgICAgYW5pbWF0b3IudG9nZ2xlVmlld0ZydXN0dW0oKTtcclxuICAgICAgICAgIH0sIDEwMDApO1xyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG5cclxuICAgICAgaWYgKGlzTmVzdFRoZXJtb3N0YXQpIHtcclxuICAgICAgICAvLyBUT0RPOiB1c2UgYmluZFBhdGggaW5zdGVhZCB1c2luZyBNUCBzZGsgY2xhc3NlcyAoc2VlIFNlY3VyaXR5IENhbWVyYSBleGFtcGxlKVxyXG4gICAgICAgIC8vIGZvciBUViB1c2VzIENhbnZhc0ltYWdlIGJlbG93IVxyXG4gICAgICAgIC8vIGNvbnN0IGNpID0gbmV3IENhbnZhc0ltYWdlKCk7XHJcbiAgICAgICAgLy8gY2kub25Jbml0KCk7XHJcbiAgICAgICAgY29uc3QgY3YgPSBuZXcgQ2FudmFzUmVuZGVyZXIoKTtcclxuICAgICAgICBjdi5vbkluaXQoKTtcclxuICAgICAgICBjb25zdCBwbGFuZSA9IG5ldyBQbGFuZVJlbmRlcmVyKCk7XHJcbiAgICAgICAgcGxhbmUub3V0cHV0cyA9IHtcclxuICAgICAgICAgIG9iamVjdFJvb3Q6IG5ldyBPYmplY3QzRCgpLFxyXG4gICAgICAgICAgY29sbGlkZXI6IG5ldyBPYmplY3QzRCgpXHJcbiAgICAgICAgfTtcclxuICAgICAgICBjb25zdCBpbnB1dFRleHR1cmUgPSBjdi5vdXRwdXRzLnRleHR1cmU7XHJcbiAgICAgICAgcGxhbmUuc2V0Um9vdFNjZW5lKHRoaXMudGhyZWVKU1NjZW5lKTtcclxuICAgICAgICBwbGFuZS5vbkluaXQobW9kZWxOb2RlLCBpbnB1dFRleHR1cmUpO1xyXG4gICAgICAgIGNvbnN0IHNjID0gbmV3IE5lc3RUaGVybW9zdGF0KCk7XHJcbiAgICAgICAgc2Muc2V0Q29tcG9uZW50KGNvbXBvbmVudCwgcGxhbmUsIGN2KTtcclxuICAgICAgICBzYy5zZXRSb290U2NlbmUodGhpcy50aHJlZUpTU2NlbmUpO1xyXG4gICAgICAgIHNjLm9uSW5pdChtb2RlbE5vZGUsIHBsYW5lLCBpbnB1dFRleHR1cmUpO1xyXG4gICAgICAgIGN2LnNldENhbnZhc05lc3RUaGVybW9zdGF0UGFpbnRlcihzYyk7XHJcbiAgICAgICAgc2V0VGltZW91dCgoKSA9PiB7XHJcbiAgICAgICAgICBzYy5pbnB1dHMubG9hZGluZ1N0YXRlID0gXCJMb2FkZWRcIjtcclxuICAgICAgICAgIHNjLm9uSW5wdXRzVXBkYXRlZCgpO1xyXG4gICAgICAgIH0sIDUwMDApO1xyXG4gICAgICB9XHJcblxyXG4gICAgICBpZiAoaXNTbWFydGVycGxhblByb21vdGlvbmFsVmlkZW8pIHtcclxuICAgICAgICAvLyBUT0RPOiB1c2UgYmluZFBhdGggaW5zdGVhZCB1c2luZyBNUCBzZGsgY2xhc3NlcyAoc2VlIFNlY3VyaXR5IENhbWVyYSBleGFtcGxlKVxyXG4gICAgICAgIGNvbnN0IHNjID0gbmV3IFR2UGxheWVyKCk7XHJcbiAgICAgICAgc2Muc2V0Q29tcG9uZW50KGNvbXBvbmVudCk7XHJcbiAgICAgICAgc2Mub25Jbml0KG1vZGVsTm9kZSk7XHJcbiAgICAgICAgc2V0VGltZW91dCgoKSA9PiB7XHJcbiAgICAgICAgICBzYy5pbnB1dHMubG9hZGluZ1N0YXRlID0gXCJMb2FkZWRcIjtcclxuICAgICAgICAgIHNjLm9uSW5wdXRzVXBkYXRlZCgpO1xyXG4gICAgICAgIH0sIDUwMDApO1xyXG4gICAgICB9XHJcblxyXG4gICAgICBzY2VuZU9iamVjdC5zdGFydCgpO1xyXG4gICAgICByZXNvbHZlKHRoaXMubGFzdE9iamVjdDNEKTtcclxuICAgIH0pO1xyXG4gIH1cclxuXHJcbiAgdG9nZ2xlT2JqZWN0VmlzaWJpbGl0eShvYmplY3RJZDogYW55KXtcclxuICAgIGxldCBvYmogPSB0aGlzLmRpY3Rpb25uYXJ5T2JqZWN0czNELmdldChvYmplY3RJZCk7XHJcbiAgICBvYmoub2JqM0QudmlzaWJsZSA9ICFvYmoub2JqM0QudmlzaWJsZTtcclxuICB9XHJcblxyXG4gIGlzT2JqZWN0VmlzaWJsZShvYmplY3RJZDogYW55KTogYm9vbGVhbiB7XHJcbiAgICBsZXQgb2JqID0gdGhpcy5kaWN0aW9ubmFyeU9iamVjdHMzRC5nZXQob2JqZWN0SWQpO1xyXG4gICAgcmV0dXJuIG9iai5vYmozRC52aXNpYmxlO1xyXG4gIH1cclxuXHJcbiAgYXN5bmMgcG9pbnRDYW1lcmFUbzNET2JqZWN0KG9iamVjdElkOiBhbnkpe1xyXG4gICAgbGV0IG9iaiA9IHRoaXMuZGljdGlvbm5hcnlPYmplY3RzM0QuZ2V0KG9iamVjdElkKTtcclxuXHJcbiAgICAvL1dlIGNyZWF0ZSBhIHRlbXBvcmFyeSBUYWdcclxuICAgIGNvbnN0IHBvaU9iamVjdCA9IHtcclxuICAgICAgY29vcmRpbmF0ZTogSlNPTi5zdHJpbmdpZnkob2JqLm9iajNELnBvc2l0aW9uKSxcclxuICAgICAgdHlwZTogUG9pVHlwZS5PQkpFQ1QzRCxcclxuICAgICAgZWxlbWVudElEOiBvYmplY3RJZCwgLy90b2RvOiBiZSBjYXJlZnVsIHdpdGggdGhpc1xyXG4gICAgfSBhcyBQT0k7XHJcbiAgICBjb25zdCBvYmplY3REYiA9IHtpZDogb2JqZWN0SWR9IGFzIERiT2JqZWN0VHlwZTtcclxuXHJcbiAgICB0cnl7XHJcbiAgICAgIGF3YWl0IHRoaXMuY3JlYXRlTWF0dGVydGFnRnJvbVBPSShQb2lUeXBlLk9CSkVDVDNELCBvYmplY3REYiwgcG9pT2JqZWN0KTtcclxuICAgIH1jYXRjaChlcnI6IGFueSl7fVxyXG5cclxuICAgIC8vTm90IHJlYWxseSBuZWNlc3NhcnkgYW55bW9yZSBzaW5jZSB0aGUgdGFnIHdpbGwgZGlzYXBwZWFyIHF1aWNrXHJcbiAgICAvL3RoaXMuc2RrLlRhZy5lZGl0T3BhY2l0eShtYXR0ZXJ0YWdJRCwgMC4wKTsvL29wYWNpdHkpO1xyXG4gICAgLy90aGlzLnNkay5UYWcuYWxsb3dBY3Rpb24obWF0dGVydGFnSUQsIHt9KTsgLy9kaXNhYmxlcyBldmVyeSBhY3Rpb25cclxuXHJcbiAgICBsZXQgcmVzdWx0ID0gdGhpcy5nZXRUYWdGcm9tRWxlbWVudElkKG9iamVjdElkKTtcclxuXHJcbiAgICBhd2FpdCB0aGlzLmdvVG9UYWcocmVzdWx0LnRhZyk7XHJcbiAgICB0aGlzLmRlbGV0ZUxhc3RNYXR0ZXJ0YWcoKTtcclxuICB9XHJcblxyXG4gIGdldFNjZW5lTm9kZUZyb21PYmplY3QzRElkKHV1aWQ6IHN0cmluZyk6IGFueSB7XHJcbiAgICByZXR1cm4gdGhpcy5kaWN0aW9ubmFyeVNjZW5lT2JqZWN0czNELmdldCh1dWlkKTtcclxuICB9XHJcblxyXG4gIGFzeW5jIGRpc3BsYXlBemltdXRhbENyb3duKCl7XHJcbiAgICBpZih0aGlzLmF6aW11dGhhbENyb3duKXtcclxuICAgICAgdGhpcy5hemltdXRoYWxDcm93bi5vYmozRC5wb3NpdGlvbi5zZXQodGhpcy5wb3NlQ2FtZXJhLnBvc2l0aW9uLngsdGhpcy5wb3NlQ2FtZXJhLnBvc2l0aW9uLnksdGhpcy5wb3NlQ2FtZXJhLnBvc2l0aW9uLnopXHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBhc3luYyBhdHRhY2hHaXptb0NvbnRyb2xUbzNET2JqZWN0KFxyXG4gICAgbW9kZWxOb2RlOiBhbnksXHJcbiAgICBzY2VuZU9iamVjdDogYW55LFxyXG4gICAgbW9kZTogJ3RyYW5zbGF0ZScgfCAncm90YXRlJyB8ICdzY2FsZScsXHJcbiAgICB2aXNpYmxlOiBib29sZWFuXHJcbiAgKTogUHJvbWlzZTxhbnk+IHtcclxuICAgIC8vIENyZWF0ZSBhIHNjZW5lIG5vZGUgd2l0aCBhIHRyYW5zZm9ybSBjb250cm9sIGNvbXBvbmVudC5cclxuICAgIGxldCBub2RlID0gbnVsbDtcclxuICAgIG5vZGUgPSBzY2VuZU9iamVjdC5hZGROb2RlKCk7XHJcbiAgICBpZiAoIW5vZGUpIHtcclxuICAgICAgY29uc3QgW3NjZW5lT2JqZWN0XSA9IGF3YWl0IHRoaXMuc2RrLlNjZW5lLmNyZWF0ZU9iamVjdHMoMSk7XHJcbiAgICAgIG5vZGUgPSBzY2VuZU9iamVjdC5hZGROb2RlKCk7XHJcbiAgICB9XHJcblxyXG4gICAgY29uc3QgbXlDb250cm9sID0gbm9kZS5hZGRDb21wb25lbnQoJ21wLnRyYW5zZm9ybUNvbnRyb2xzJyk7XHJcbiAgICBub2RlLnN0YXJ0KCk7XHJcbiAgICAvL1xyXG4gICAgLy8gLy8gTWFrZSB0aGUgdHJhbnNmb3JtIGNvbnRyb2wgdmlzaWJsZSBzbyB0aGF0IHRoZSB1c2VyIGNhbiBtYW5pcHVsYXRlIHRoZSBjb250cm9sIHNlbGVjdGlvbi5cclxuICAgIG15Q29udHJvbC50cmFuc2Zvcm1Db250cm9scy52aXNpYmxlID0gdmlzaWJsZTtcclxuICAgIC8vXHJcbiAgICAvLyAvLyBBdHRhY2ggdGhlIG1vZGVsIHRvIHRoZSB0cmFuc2Zvcm0gY29udHJvbFxyXG4gICAgbXlDb250cm9sLmlucHV0cy5zZWxlY3Rpb24gPSBtb2RlbE5vZGU7XHJcbiAgICAvL1xyXG4gICAgLy8gLy8gc2V0ICd0cmFuc2xhdGUnIG1vZGUgdG8gcG9zaXRpb24gdGhlIHNlbGVjdGlvbi5cclxuICAgIG15Q29udHJvbC5pbnB1dHMubW9kZSA9IG1vZGU7XHJcbiAgICBtb2RlbE5vZGUub2JqM0QuY29udHJvbHMgPSBteUNvbnRyb2w7IC8vIHN0b3JlIGdpem1vQ3RybCBpbnNpZGUgb2JqZWN0XHJcblxyXG4gICAgaWYgKCF0aGlzLmxhc3RPYmplY3QzRCB8fCAhdGhpcy5sYXN0T2JqZWN0M0QuY29udHJvbHMpIHtcclxuICAgICAgdHJ5IHtcclxuICAgICAgICBtb2RlbE5vZGUub2JqM0QudXVpZCA9IHRoaXMubGFzdE9iamVjdDNELnV1aWQgfHwgdGhpcy5sYXN0T2JqZWN0M0QuaWQ7XHJcbiAgICAgIH0gY2F0Y2ggKGUpIHtcclxuICAgICAgICBjb25zb2xlLmxvZyhgaWQgb2JqIGluIFNjZW5lIHdhcyBub3QgYXNzaWduZWQgdG8gaWQgZnJvbSBEQiBzaW5jZWApO1xyXG4gICAgICB9XHJcbiAgICAgIHRoaXMubGFzdE9iamVjdDNEID0gbW9kZWxOb2RlLm9iajNEO1xyXG4gICAgfVxyXG5cclxuICAgIHJldHVybiBtb2RlbE5vZGU7XHJcbiAgfVxyXG5cclxuICByZW1vdmVHaXptb0Zyb21MYXN0T2JqZWN0KCk6IHZvaWQge1xyXG4gICAgdGhpcy5sYXN0T2JqZWN0M0QuY29udHJvbHMudHJhbnNmb3JtQ29udHJvbHMudmlzaWJsZSA9IGZhbHNlO1xyXG4gICAgdGhpcy5sYXN0T2JqZWN0M0QuY29udHJvbHMudHJhbnNmb3JtQ29udHJvbHMuZGlzcG9zZSgpO1xyXG4gICAgdGhpcy5sYXN0T2JqZWN0M0QuY29udHJvbHMgPSBudWxsO1xyXG4gIH1cclxuXHJcbiAgdG9nZ2xlVmlld0ZydXN0dW0oKTogdm9pZCB7XHJcbiAgICB0aGlzLnNlY3VyaXR5Q2FtZXJhQW5pbWF0b3IudG9nZ2xlVmlld0ZydXN0dW0oKTtcclxuICB9XHJcblxyXG4gLypwdWJsaWMgc2V0M0RPYmplY3RNb2RlKG1vZGVsTm9kZTogYW55LCBtb2RlPzogc3RyaW5nKSB7XHJcbiAgIGlmIChtb2RlKSB7XHJcbiAgICAgdGhpcy5vYmplY3RDb250cm9sLmlucHV0cy5zZWxlY3Rpb24gPSBtb2RlbE5vZGU7XHJcbiAgICAgdGhpcy5vYmplY3RDb250cm9sLmlucHV0cy52aXNpYmxlID0gdHJ1ZTtcclxuICAgICB0aGlzLm9iamVjdENvbnRyb2wuaW5wdXRzLm1vZGUgPSBtb2RlO1xyXG5cclxuICAgICBzZXRJbnRlcnZhbCgoKSA9PiB7XHJcbiAgICAgICBjb25zb2xlLmxvZyhtb2RlbE5vZGUpO1xyXG4gICAgIH0sIDUwMDApO1xyXG5cclxuICAgfSBlbHNlIHtcclxuICAgICB0aGlzLm9iamVjdENvbnRyb2wuaW5wdXRzLnZpc2libGUgPSB0cnVlO1xyXG4gICB9XHJcbiB9Ki9cclxufVxyXG4iXX0=
|
|
1
|
+
import { Inject, Injectable } from '@angular/core';
|
|
2
|
+
import { Subject } from 'rxjs';
|
|
3
|
+
//import * as serialijse from "serialijse";
|
|
4
|
+
import { getDistanceBetweenTwoPoints, poiTypeToString, wait, } from '../helpers.service';
|
|
5
|
+
import { MattertagData } from '../mattertagData';
|
|
6
|
+
import { FeatureType, MattertagActionMode, PoiType, SpModule, TagAction, ViewerInteractions, } from '../types.service';
|
|
7
|
+
import { Object3D } from 'three';
|
|
8
|
+
import { CameraMode } from '../types.service';
|
|
9
|
+
import { NestThermostat } from '../matterport-extensions/nest-thermostat/NestThermostat';
|
|
10
|
+
import { PlaneRenderer } from '../matterport-extensions/nest-thermostat/PlaneRenderer';
|
|
11
|
+
import { CanvasRenderer } from "../matterport-extensions/nest-thermostat/CanvasRenderer";
|
|
12
|
+
import { TvPlayer } from "../matterport-extensions/tv-player/TvPlayer";
|
|
13
|
+
import * as i0 from "@angular/core";
|
|
14
|
+
import * as i1 from "@angular/router";
|
|
15
|
+
import * as i2 from "./baseVisibility.service";
|
|
16
|
+
import * as i3 from "../config";
|
|
17
|
+
export class MatterportService {
|
|
18
|
+
constructor(config, router, activeRoute, visibilityService, ngZone) {
|
|
19
|
+
this.router = router;
|
|
20
|
+
this.activeRoute = activeRoute;
|
|
21
|
+
this.visibilityService = visibilityService;
|
|
22
|
+
this.ngZone = ngZone;
|
|
23
|
+
this.slots = []; //SlotNode[] = [];
|
|
24
|
+
this.nodes = [];
|
|
25
|
+
this.lastCameraPosition = { x: 0.0, y: 0.0, z: 0.0 };
|
|
26
|
+
this.cursorPositionButtonDisplayed = false;
|
|
27
|
+
// Measure mode
|
|
28
|
+
this.isMeasureModeOn = false;
|
|
29
|
+
this.interactionMode = ViewerInteractions.DEFAULT;
|
|
30
|
+
// List of created Mattertag IDs in the current viewer session
|
|
31
|
+
this.mattertagIDs = [];
|
|
32
|
+
// Dictionnary of MattertagID and its data (mattertagData)
|
|
33
|
+
this.dictionnaryTags = new Map();
|
|
34
|
+
this.dictionnaryObjects3D = new Map();
|
|
35
|
+
this.dictionnarySceneObjects3D = new Map();
|
|
36
|
+
this.lastMeasure = [];
|
|
37
|
+
this.distancesLastMeasure = [];
|
|
38
|
+
this.resolution = {
|
|
39
|
+
width: 500,
|
|
40
|
+
height: 600,
|
|
41
|
+
};
|
|
42
|
+
this.visibility = {
|
|
43
|
+
mattertags: false,
|
|
44
|
+
sweeps: true,
|
|
45
|
+
};
|
|
46
|
+
this.tagsAttachments = {};
|
|
47
|
+
this.currentSweep = new Subject();
|
|
48
|
+
//camera position with rotation
|
|
49
|
+
this.currentCameraPose = new Subject();
|
|
50
|
+
this.forbiddenSweeps = [];
|
|
51
|
+
this.tagAction = new Subject();
|
|
52
|
+
this.inTransitionMode = false;
|
|
53
|
+
this.inTransitionSweep = false;
|
|
54
|
+
this.noLightForObjects = true;
|
|
55
|
+
this.currentCameraMode = CameraMode.OUTSIDE;
|
|
56
|
+
this.onCameraModeChanged = new Subject();
|
|
57
|
+
this.onGoToTag = new Subject();
|
|
58
|
+
this.tagMessengerOn = false;
|
|
59
|
+
/**
|
|
60
|
+
* Actions on left click when positioning mattertag in visit
|
|
61
|
+
*/
|
|
62
|
+
this.pointerLeftClickHandler = () => {
|
|
63
|
+
if (this.mattertagToFollow) {
|
|
64
|
+
const mattertagData = this.dictionnaryTags.get(this.mattertagToFollow);
|
|
65
|
+
mattertagData.setPosition({ ...this.poseMatterport.position }); // copy!! not the reference
|
|
66
|
+
mattertagData.setNormal({ ...this.poseMatterport.normal }); // copy!! not the reference
|
|
67
|
+
this.dictionnaryTags.set(this.mattertagToFollow, mattertagData);
|
|
68
|
+
this.updateMatterTagContentForTagID(this.mattertagToFollow);
|
|
69
|
+
}
|
|
70
|
+
this.onValidatedMattertag();
|
|
71
|
+
};
|
|
72
|
+
this.pointerRightClickHandler = (e) => {
|
|
73
|
+
e.preventDefault();
|
|
74
|
+
this.cancelFollowingCursor();
|
|
75
|
+
alert('action cancelled');
|
|
76
|
+
};
|
|
77
|
+
this.pointerMiddleClickHandler = (e) => {
|
|
78
|
+
this.textDisplayCursorPositionPanel.innerHTML = `position:
|
|
79
|
+
${this.pointToString(this.poseMatterport.position)}\n
|
|
80
|
+
normal:
|
|
81
|
+
${this.pointToString(this.poseMatterport.normal)}\n
|
|
82
|
+
floorId:
|
|
83
|
+
${this.poseMatterport.floorId}`;
|
|
84
|
+
// this.textDisplayCursorPositionPanel.style.display = 'visible';
|
|
85
|
+
this.getCursorPositionButton.style.display = 'none';
|
|
86
|
+
};
|
|
87
|
+
this.config = config;
|
|
88
|
+
// TODO: only for dev!
|
|
89
|
+
if (!!this.getCursorPositionButton &&
|
|
90
|
+
(document.location.href.indexOf('dev') !== -1 || document.location.href.indexOf('localhost') !== -1)) {
|
|
91
|
+
this.intervalCursorPointerPosition = setInterval(() => {
|
|
92
|
+
if (!this.poseMatterport) {
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
const nextShow = this.poseMatterport.time + 1000;
|
|
96
|
+
if (new Date().getTime() > nextShow) {
|
|
97
|
+
if (this.cursorPositionButtonDisplayed) {
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
const size = {
|
|
101
|
+
w: this.container.clientWidth,
|
|
102
|
+
h: this.container.clientHeight,
|
|
103
|
+
};
|
|
104
|
+
const coord = this.sdk.Conversion.worldToScreen(this.poseMatterport.position, this.poseCamera, size);
|
|
105
|
+
this.getCursorPositionButton.style.left = `${coord.x - 25}px`;
|
|
106
|
+
this.getCursorPositionButton.style.top = `${coord.y - 22}px`;
|
|
107
|
+
this.getCursorPositionButton.style.display = 'block';
|
|
108
|
+
// this.textDisplayCursorPositionPanel.style.display = 'none';
|
|
109
|
+
this.cursorPositionButtonDisplayed = true;
|
|
110
|
+
}
|
|
111
|
+
}, 500);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
get currentSpaceID() {
|
|
115
|
+
return this._currentSpaceID;
|
|
116
|
+
}
|
|
117
|
+
set currentSpaceID(value) {
|
|
118
|
+
this._currentSpaceID = value;
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Initializes Matterport and all listeners/data
|
|
122
|
+
* @param tagService BaseTagService (to inject html)
|
|
123
|
+
* @param module SpModule (Museum, Immo) to subscribe only to needed functionnnalities
|
|
124
|
+
* @returns boolean
|
|
125
|
+
*/
|
|
126
|
+
async initSdk(tagService, module = SpModule.IMMO) {
|
|
127
|
+
if (this.sdk) {
|
|
128
|
+
// clean if sdk is running already
|
|
129
|
+
await this.action_delete_all_mattertags();
|
|
130
|
+
}
|
|
131
|
+
this.tagService = tagService;
|
|
132
|
+
this.SPModule = module;
|
|
133
|
+
return new Promise((resolve, reject) => {
|
|
134
|
+
// Retrieve DOM elements
|
|
135
|
+
this.pointerButton = document.querySelector('#viewer-pointer-trick');
|
|
136
|
+
this.container = document.querySelector('#viewer-module');
|
|
137
|
+
const iframe = document.querySelector('#viewer-module');
|
|
138
|
+
if (!iframe) {
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
// Add listeners
|
|
142
|
+
if (this.pointerButton) {
|
|
143
|
+
this.pointerButton.addEventListener('click', this.pointerLeftClickHandler);
|
|
144
|
+
// cancel on right click
|
|
145
|
+
this.pointerButton.addEventListener('contextmenu', this.pointerRightClickHandler);
|
|
146
|
+
}
|
|
147
|
+
// Retrieve DOM elements
|
|
148
|
+
this.getCursorPositionButton = document.querySelector('#button');
|
|
149
|
+
this.textDisplayCursorPositionPanel = document.querySelector('#text');
|
|
150
|
+
if (this.getCursorPositionButton) {
|
|
151
|
+
// get position on Matterport "model" on middle click
|
|
152
|
+
this.getCursorPositionButton.addEventListener('click', this.pointerMiddleClickHandler);
|
|
153
|
+
}
|
|
154
|
+
// Load SDK
|
|
155
|
+
console.log('Loading Matterport SDK');
|
|
156
|
+
const showcaseWindow = iframe.contentWindow;
|
|
157
|
+
iframe.addEventListener('load', async function () {
|
|
158
|
+
try {
|
|
159
|
+
this.sdk = await showcaseWindow.MP_SDK.connect(showcaseWindow, 'qn9wsasuy5h2fzrbrn1nzr0id', '3.5');
|
|
160
|
+
}
|
|
161
|
+
catch (e) {
|
|
162
|
+
console.error(e);
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
// Load Mattertag icons and custom subscriptions
|
|
166
|
+
switch (module) {
|
|
167
|
+
case SpModule.IMMO:
|
|
168
|
+
this.sdk.Asset.registerTexture('icon-ticket', this.config.my_config.icon_ticket);
|
|
169
|
+
this.sdk.Asset.registerTexture('icon-equipment', this.config.my_config.icon_equipment);
|
|
170
|
+
this.sdk.Asset.registerTexture('icon-measure', this.config.my_config.icon_measure);
|
|
171
|
+
this.sdk.Asset.registerTexture('icon-data', this.config.my_config.icon_data);
|
|
172
|
+
this.sdk.Asset.registerTexture('icon-object3d', this.config.my_config.icon_object3d);
|
|
173
|
+
this.sdk.Measurements.data.subscribe({
|
|
174
|
+
onAdded: function (index, item, collection) {
|
|
175
|
+
// console.log(
|
|
176
|
+
// "item added to the collection",
|
|
177
|
+
// index,
|
|
178
|
+
// item,
|
|
179
|
+
// );
|
|
180
|
+
// this.measurements[index] = item;
|
|
181
|
+
this.lastMeasure = item.points;
|
|
182
|
+
}.bind(this),
|
|
183
|
+
onCollectionUpdated: function (collection) {
|
|
184
|
+
// console.log('the entire up-to-date collection', collection);
|
|
185
|
+
this.getDistanceForLastMeasurement();
|
|
186
|
+
}.bind(this),
|
|
187
|
+
});
|
|
188
|
+
this.sdk.Measurements.mode.subscribe(function (measurementModeState) {
|
|
189
|
+
// measurement mode state has changed
|
|
190
|
+
this.isMeasureModeOn = measurementModeState.active;
|
|
191
|
+
// console.log('Is measurement mode currently active? ', measurementModeState.active);
|
|
192
|
+
}.bind(this));
|
|
193
|
+
break;
|
|
194
|
+
case SpModule.MUSEUM:
|
|
195
|
+
this.sdk.Asset.registerTexture('icon-data', this.config.my_config.icon_data);
|
|
196
|
+
break;
|
|
197
|
+
case SpModule.HOTEL:
|
|
198
|
+
this.sdk.Asset.registerTexture('icon_room_available', this.config.my_config.icon_room_available);
|
|
199
|
+
this.sdk.Asset.registerTexture('icon_room_unavailable', this.config.my_config.icon_room_unavailable);
|
|
200
|
+
this.sdk.Asset.registerTexture('icon_room_chosen', this.config.my_config.icon_room_chosen);
|
|
201
|
+
this.sdk.Asset.registerTexture('icon_room_viewed', this.config.my_config.icon_room_viewed);
|
|
202
|
+
break;
|
|
203
|
+
default:
|
|
204
|
+
break;
|
|
205
|
+
}
|
|
206
|
+
this.sdk.Asset.registerTexture('icon-position', this.config.my_config.icon_position);
|
|
207
|
+
// Current Room (used for getting bounding box and eventually lazy load mattertag or object3D inside current Room)
|
|
208
|
+
this.sdk.Room.current.subscribe((currentRoom) => {
|
|
209
|
+
console.log(`hello current Room ${JSON.stringify(currentRoom)}`);
|
|
210
|
+
});
|
|
211
|
+
// 3D position's pointer
|
|
212
|
+
this.sdk.Pointer.intersection.subscribe(function (intersection) {
|
|
213
|
+
this.poseMatterport = intersection;
|
|
214
|
+
this.poseMatterport.time = new Date().getTime();
|
|
215
|
+
if (!this.oldPoseMatterportPosition) {
|
|
216
|
+
this.oldPoseMatterportPosition = {
|
|
217
|
+
x: 0,
|
|
218
|
+
y: 0,
|
|
219
|
+
z: 0,
|
|
220
|
+
};
|
|
221
|
+
}
|
|
222
|
+
if (this.interactionMode !== ViewerInteractions.DEFAULT &&
|
|
223
|
+
this.mattertagToFollow) {
|
|
224
|
+
// follow the pointer and changes the position of the last tag
|
|
225
|
+
// (we are about to validate, but it exists in sdk already)
|
|
226
|
+
this.enable_following_tag(this.mattertagToFollow);
|
|
227
|
+
}
|
|
228
|
+
if (!!this.getCursorPositionButton && !!this.getCursorPositionButton.style &&
|
|
229
|
+
(document.URL.indexOf('https://dev.smarterplan.io') !== -1 || document.location.href.indexOf('localhost') !== -1)) {
|
|
230
|
+
this.getCursorPositionButton.style.display = 'none';
|
|
231
|
+
this.cursorPositionButtonDisplayed = false;
|
|
232
|
+
}
|
|
233
|
+
}.bind(this));
|
|
234
|
+
//Camera mode
|
|
235
|
+
this.sdk.Mode.current.subscribe((mode) => {
|
|
236
|
+
this.inTransitionSweep = false;
|
|
237
|
+
switch (mode) {
|
|
238
|
+
case 'mode.dollhouse':
|
|
239
|
+
this.currentCameraMode = CameraMode.DOLLHOUSE;
|
|
240
|
+
break;
|
|
241
|
+
case 'mode.floorplan':
|
|
242
|
+
this.currentCameraMode = CameraMode.FLOORPLAN;
|
|
243
|
+
break;
|
|
244
|
+
case 'mode.inside':
|
|
245
|
+
this.currentCameraMode = CameraMode.INSIDE;
|
|
246
|
+
break;
|
|
247
|
+
case 'mode.transitioning':
|
|
248
|
+
this.currentCameraMode = CameraMode.TRANSITIONING;
|
|
249
|
+
break;
|
|
250
|
+
default:
|
|
251
|
+
this.currentCameraMode = CameraMode.OUTSIDE;
|
|
252
|
+
}
|
|
253
|
+
this.onCameraModeChanged.next(this.currentCameraMode);
|
|
254
|
+
});
|
|
255
|
+
// Camera's viewpoint
|
|
256
|
+
this.sdk.Camera.pose.subscribe(function subscr(pose) {
|
|
257
|
+
this.poseCamera = pose;
|
|
258
|
+
this.currentCameraPose.next(pose);
|
|
259
|
+
// console.log('Current position is ', pose.position);
|
|
260
|
+
// console.log('Rotation angle is ', pose.rotation);
|
|
261
|
+
// console.log("Sweep UUID is", pose.sweep);
|
|
262
|
+
}.bind(this));
|
|
263
|
+
// subscribe to sweeps
|
|
264
|
+
this.sdk.Sweep.data.subscribe({
|
|
265
|
+
onCollectionUpdated: function subscr(collection) {
|
|
266
|
+
// console.log("Sweep collection updated");
|
|
267
|
+
this.sweeps = Object.keys(collection);
|
|
268
|
+
}.bind(this),
|
|
269
|
+
});
|
|
270
|
+
// subscribe to current sweep
|
|
271
|
+
this.sdk.Sweep.current.subscribe(function subscr(currentSweep) {
|
|
272
|
+
// Change to the current sweep has occurred.
|
|
273
|
+
if (currentSweep.sid === '') {
|
|
274
|
+
// console.log('Not currently stationed at a sweep position');
|
|
275
|
+
}
|
|
276
|
+
else {
|
|
277
|
+
// console.log("emmiting sweep", currentSweep.sid);
|
|
278
|
+
this.currentSweep.next(currentSweep.sid);
|
|
279
|
+
}
|
|
280
|
+
}.bind(this));
|
|
281
|
+
// Subscribe to Floor data
|
|
282
|
+
this.sdk.Floor.data.subscribe({
|
|
283
|
+
onCollectionUpdated: function upd(collection) {
|
|
284
|
+
this.floors = Object.values(collection);
|
|
285
|
+
}.bind(this),
|
|
286
|
+
});
|
|
287
|
+
// on tag click open details page
|
|
288
|
+
this.sdk.on('tag.click', (sid) => {
|
|
289
|
+
// get object of this tag
|
|
290
|
+
try {
|
|
291
|
+
const mattertagData = this.dictionnaryTags.get(sid);
|
|
292
|
+
if (!mattertagData) {
|
|
293
|
+
console.log('no mattertagData to display');
|
|
294
|
+
return;
|
|
295
|
+
}
|
|
296
|
+
const url = tagService.getUrlForSeeDetails(mattertagData.getObject(), mattertagData.getType());
|
|
297
|
+
if (url !== '') {
|
|
298
|
+
this.visibilityService.detailShowing.next(true);
|
|
299
|
+
this.ngZone.run(() => {
|
|
300
|
+
this.router.navigate([url]);
|
|
301
|
+
});
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
catch {
|
|
305
|
+
console.log('Cannot show details for tag');
|
|
306
|
+
}
|
|
307
|
+
});
|
|
308
|
+
// Pointer trick
|
|
309
|
+
// Create a div that will appear when the cursor is still
|
|
310
|
+
// It will intercept the click of the mouse before it trigerring the Matterport's tour navigation
|
|
311
|
+
this.timerPointer = setInterval(this.updatePointerTrick.bind(this), 50);
|
|
312
|
+
/**
|
|
313
|
+
* Transitions
|
|
314
|
+
*/
|
|
315
|
+
this.sdk.on('viewmode.changestart', function (to, from) {
|
|
316
|
+
// console.log('Starting to move to ' + to + ' from ' + from);
|
|
317
|
+
this.inTransitionMode = true;
|
|
318
|
+
}.bind(this));
|
|
319
|
+
this.sdk.on('viewmode.changeend', function (oldMode, newMode) {
|
|
320
|
+
// console.log('Ended to move to ' + newMode + ' from ' + oldMode);
|
|
321
|
+
if (newMode !== 'mode.transitioning') {
|
|
322
|
+
this.inTransitionMode = false;
|
|
323
|
+
}
|
|
324
|
+
}.bind(this));
|
|
325
|
+
this.sdk.on(this.sdk.Sweep.Event.ENTER, function (oldSweep, newSweep) {
|
|
326
|
+
// console.log('Leaving sweep ' + oldSweep);
|
|
327
|
+
// console.log('Entering sweep ' + newSweep);
|
|
328
|
+
this.inTransitionSweep = false;
|
|
329
|
+
this.displayAzimutalCrown();
|
|
330
|
+
}.bind(this));
|
|
331
|
+
this.sdk.on(this.sdk.Sweep.Event.EXIT, function (fromSweep, toSweep) {
|
|
332
|
+
// console.log('Leaving sweep ' + fromSweep);
|
|
333
|
+
// console.log('Transitioning to sweep ' + toSweep);
|
|
334
|
+
this.inTransitionSweep = true;
|
|
335
|
+
}.bind(this));
|
|
336
|
+
// TODO: get scene with getter instead!
|
|
337
|
+
const [sceneObject] = await this.sdk.Scene.createObjects(1);
|
|
338
|
+
const node = sceneObject.addNode();
|
|
339
|
+
node.start();
|
|
340
|
+
this.threeJSScene = node.obj3D.parent;
|
|
341
|
+
// await this.sdk.Scene.configure((renderer: any, three: any) => {
|
|
342
|
+
// renderer.physicallyCorrectLights = true;
|
|
343
|
+
// renderer.outputEncoding = three.sRGBEncoding;
|
|
344
|
+
// renderer.shadowMap.enabled = true;
|
|
345
|
+
// renderer.shadowMap.bias = 0.0001;
|
|
346
|
+
// renderer.shadowMap.type = three.PCFSoftShadowMap;
|
|
347
|
+
// });
|
|
348
|
+
// TODO: wait for MP ticket resolution before decomment these!
|
|
349
|
+
// Wait until Showcase is actually playing....
|
|
350
|
+
// this.sdk.Tag.data.subscribe({
|
|
351
|
+
// onAdded: async function (index, item, collection) {
|
|
352
|
+
//
|
|
353
|
+
// let thisOpacity = 0.2;
|
|
354
|
+
// this.sdk.Tag.editOpacity(index, thisOpacity);
|
|
355
|
+
//
|
|
356
|
+
// let source = null;
|
|
357
|
+
// try {
|
|
358
|
+
// source = await Promise.all([
|
|
359
|
+
// this.sdk.Sensor.createSource(this.sdk.Sensor.SourceType.SPHERE, {
|
|
360
|
+
// origin: item.anchorPosition,
|
|
361
|
+
// radius: Number(3),
|
|
362
|
+
// userData: {
|
|
363
|
+
// id: index + '-sphere-source',
|
|
364
|
+
// },
|
|
365
|
+
// })
|
|
366
|
+
// ]);
|
|
367
|
+
// } catch (e) {
|
|
368
|
+
// console.log('could not create Sphere sensor')
|
|
369
|
+
// console.error(e);
|
|
370
|
+
// }
|
|
371
|
+
// if (!source) {
|
|
372
|
+
// return;
|
|
373
|
+
// }
|
|
374
|
+
//
|
|
375
|
+
// let sensor = null;
|
|
376
|
+
// try {
|
|
377
|
+
// sensor = await this.sdk.Sensor.createSensor(this.sdk.Sensor.SensorType.CAMERA);
|
|
378
|
+
// } catch (e) {
|
|
379
|
+
// console.log('could not create Camera sensor')
|
|
380
|
+
// console.error(e);
|
|
381
|
+
// }
|
|
382
|
+
// if (!sensor) {
|
|
383
|
+
// return;
|
|
384
|
+
// }
|
|
385
|
+
//
|
|
386
|
+
// sensor.addSource(...source);
|
|
387
|
+
// sensor.readings.subscribe({
|
|
388
|
+
// onUpdated(source, reading) {
|
|
389
|
+
// console.log(thisOpacity);
|
|
390
|
+
// let oldOpacity = thisOpacity;
|
|
391
|
+
// if (reading.inRange) {
|
|
392
|
+
// thisOpacity = 1;
|
|
393
|
+
// console.log(index + ' is inRange');
|
|
394
|
+
// } else if (reading.inView) {
|
|
395
|
+
// console.log(index + ' is inView but not inRange');
|
|
396
|
+
// thisOpacity = 0.5;
|
|
397
|
+
// } else {
|
|
398
|
+
// thisOpacity = 0.2;
|
|
399
|
+
// console.log(index + ' is not inView or inRange');
|
|
400
|
+
// }
|
|
401
|
+
//
|
|
402
|
+
// this.sdk.Tag.editOpacity(index, thisOpacity);
|
|
403
|
+
// /*
|
|
404
|
+
// let inc = 0.01;
|
|
405
|
+
// if (oldOpacity > thisOpacity) {
|
|
406
|
+
// inc = -0.01;
|
|
407
|
+
// }
|
|
408
|
+
//
|
|
409
|
+
// for(var i = oldOpacity; i != thisOpacity; i=i+inc) {
|
|
410
|
+
// setTimeout(function() {
|
|
411
|
+
// mpSdk.Tag.editOpacity(index, i);
|
|
412
|
+
// console.log('Delay', i);
|
|
413
|
+
// },10);
|
|
414
|
+
// }
|
|
415
|
+
// */
|
|
416
|
+
// }
|
|
417
|
+
// });
|
|
418
|
+
// //sensor.showDebug(true);
|
|
419
|
+
// }.bind(this),
|
|
420
|
+
// onCollectionUpdated: function (collection) {
|
|
421
|
+
// console.log('Collection received. There are ', Object.keys(collection).length, ' Tags in the collection', collection);
|
|
422
|
+
// }
|
|
423
|
+
// });
|
|
424
|
+
resolve(true);
|
|
425
|
+
}.bind(this));
|
|
426
|
+
});
|
|
427
|
+
}
|
|
428
|
+
setLightingOff() {
|
|
429
|
+
this.noLightForObjects = true;
|
|
430
|
+
}
|
|
431
|
+
pointToString(point) {
|
|
432
|
+
var x = point.x.toFixed(3);
|
|
433
|
+
var y = point.y.toFixed(3);
|
|
434
|
+
var z = point.z.toFixed(3);
|
|
435
|
+
return `{ x: ${x}, y: ${y}, z: ${z} }`;
|
|
436
|
+
}
|
|
437
|
+
//
|
|
438
|
+
// ---------- Measurements related ----------
|
|
439
|
+
//
|
|
440
|
+
/**
|
|
441
|
+
* Callback after measurement is performed
|
|
442
|
+
*/
|
|
443
|
+
getDistanceForLastMeasurement() {
|
|
444
|
+
if (this.lastMeasure.length > 0) {
|
|
445
|
+
const numberPoints = this.lastMeasure.length;
|
|
446
|
+
this.distancesLastMeasure = [];
|
|
447
|
+
for (let index = 1; index < numberPoints; index += 1) {
|
|
448
|
+
const distance = getDistanceBetweenTwoPoints(this.lastMeasure[index - 1], this.lastMeasure[index]);
|
|
449
|
+
this.distancesLastMeasure.push(distance);
|
|
450
|
+
}
|
|
451
|
+
this.takeScreenShot().then((res) => {
|
|
452
|
+
this.router.navigate([`visit/${this.currentSpaceID}/add_measurement`]);
|
|
453
|
+
});
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
getLastDistances() {
|
|
457
|
+
return this.distancesLastMeasure;
|
|
458
|
+
}
|
|
459
|
+
/**
|
|
460
|
+
* Takes screenshot and saves base64 in lastScreenshotUri
|
|
461
|
+
* @returns Promise
|
|
462
|
+
*/
|
|
463
|
+
takeScreenShot() {
|
|
464
|
+
return this.sdk.Renderer.takeScreenShot(this.resolution, this.visibility).then(function (screenShotUri) {
|
|
465
|
+
// base64 string
|
|
466
|
+
this.lastScreenshotUri = screenShotUri;
|
|
467
|
+
return Promise.resolve();
|
|
468
|
+
}.bind(this));
|
|
469
|
+
}
|
|
470
|
+
getScreenShotUri() {
|
|
471
|
+
return this.lastScreenshotUri;
|
|
472
|
+
}
|
|
473
|
+
getLastMeasurement() {
|
|
474
|
+
const data = {
|
|
475
|
+
measure: this.lastMeasure,
|
|
476
|
+
sweep: this.poseCamera.sweep,
|
|
477
|
+
};
|
|
478
|
+
return data;
|
|
479
|
+
}
|
|
480
|
+
//
|
|
481
|
+
// ---------- Utils ----------
|
|
482
|
+
//
|
|
483
|
+
/**
|
|
484
|
+
* Styling of pointer
|
|
485
|
+
*/
|
|
486
|
+
updatePointerTrick() {
|
|
487
|
+
if (this.interactionMode !== ViewerInteractions.DEFAULT &&
|
|
488
|
+
this.mattertagToFollow &&
|
|
489
|
+
this.poseMatterport &&
|
|
490
|
+
this.getDistPosition(this.poseMatterport.position, this.oldPoseMatterportPosition) > 25) {
|
|
491
|
+
this.pointerButton.style.display = 'none';
|
|
492
|
+
const size = {
|
|
493
|
+
w: this.container.clientWidth,
|
|
494
|
+
h: this.container.clientHeight,
|
|
495
|
+
};
|
|
496
|
+
const coords = this.sdk.Conversion.worldToScreen(this.poseMatterport.position, this.poseCamera, size);
|
|
497
|
+
this.pointerButton.style.left = `${coords.x * Math.sign(coords.x) - 25}px`;
|
|
498
|
+
this.pointerButton.style.top = `${coords.y * Math.sign(coords.x) - 25}px`;
|
|
499
|
+
this.oldPoseMatterportPosition = {
|
|
500
|
+
...this.poseMatterport.position,
|
|
501
|
+
};
|
|
502
|
+
}
|
|
503
|
+
else {
|
|
504
|
+
this.pointerButton.style.display = 'block';
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
/**
|
|
508
|
+
* Realtime mattertag following the cursor
|
|
509
|
+
* @param mattertag string
|
|
510
|
+
*/
|
|
511
|
+
enable_following_tag(mattertag) {
|
|
512
|
+
this.sdk.Tag.editPosition(mattertag, {
|
|
513
|
+
anchorPosition: {
|
|
514
|
+
x: this.poseMatterport.position.x * 1,
|
|
515
|
+
y: this.poseMatterport.position.y * 1,
|
|
516
|
+
z: this.poseMatterport.position.z * 1,
|
|
517
|
+
},
|
|
518
|
+
stemVector: {
|
|
519
|
+
x: this.poseMatterport.normal.x * 0.3,
|
|
520
|
+
y: this.poseMatterport.normal.y * 0.3,
|
|
521
|
+
z: this.poseMatterport.normal.z * 0.3,
|
|
522
|
+
},
|
|
523
|
+
});
|
|
524
|
+
}
|
|
525
|
+
/**
|
|
526
|
+
* Get the distance betwween two 3D positions
|
|
527
|
+
* Used in order to see how much the cursor has moved from the previous position
|
|
528
|
+
* @param pos1
|
|
529
|
+
* @param pos2
|
|
530
|
+
*/
|
|
531
|
+
getDistPosition(pos1, pos2) {
|
|
532
|
+
const size = {
|
|
533
|
+
w: this.container.clientWidth,
|
|
534
|
+
h: this.container.clientHeight,
|
|
535
|
+
};
|
|
536
|
+
const coords1 = this.sdk.Conversion.worldToScreen(pos1, this.poseCamera, size);
|
|
537
|
+
const coords2 = this.sdk.Conversion.worldToScreen(pos2, this.poseCamera, size);
|
|
538
|
+
return Math.sqrt((coords1.x - coords2.x) ** 2 + (coords1.y - coords2.y) ** 2);
|
|
539
|
+
}
|
|
540
|
+
//
|
|
541
|
+
// ---------- Mattertag related ----------
|
|
542
|
+
//
|
|
543
|
+
/**
|
|
544
|
+
* Creates the Mattertag that will follow the cursor
|
|
545
|
+
* @param mattertagData MattertagData
|
|
546
|
+
*/
|
|
547
|
+
async addCursorMattertag(mattertagData) {
|
|
548
|
+
if (!this.poseMatterport)
|
|
549
|
+
return;
|
|
550
|
+
this.mattertagToFollow = await this.addMattertagToViewer(mattertagData);
|
|
551
|
+
console.log('following the tag', this.mattertagToFollow);
|
|
552
|
+
this.sdk.Tag.editIcon(this.mattertagToFollow, 'icon-position');
|
|
553
|
+
this.sdk.Tag.editOpacity(this.mattertagToFollow, 1);
|
|
554
|
+
}
|
|
555
|
+
/**
|
|
556
|
+
* Adds Mattertag to viewer for an existing object with coordinates (in mattertagData.poi)
|
|
557
|
+
* (position, injected html, set icon)
|
|
558
|
+
* @param mattertagData
|
|
559
|
+
* returns mattertagID
|
|
560
|
+
*/
|
|
561
|
+
async addMattertagToViewer(mattertagData) {
|
|
562
|
+
let sidList;
|
|
563
|
+
if (!this.sdk) {
|
|
564
|
+
return null;
|
|
565
|
+
}
|
|
566
|
+
try {
|
|
567
|
+
sidList = await this.sdk.Tag.add(mattertagData.getData());
|
|
568
|
+
}
|
|
569
|
+
catch (error) {
|
|
570
|
+
console.log('Tag does not belong to the visit', error, mattertagData.getData());
|
|
571
|
+
}
|
|
572
|
+
if (sidList) {
|
|
573
|
+
const mattertagID = sidList[0];
|
|
574
|
+
// console.log("added tag", mattertagData.getType(), mattertagID);
|
|
575
|
+
this.mattertagIDs.push(mattertagID);
|
|
576
|
+
this.dictionnaryTags.set(mattertagID, mattertagData);
|
|
577
|
+
return mattertagID;
|
|
578
|
+
}
|
|
579
|
+
return null;
|
|
580
|
+
}
|
|
581
|
+
/**
|
|
582
|
+
* Actions when position of mattertag is validated by left click
|
|
583
|
+
*/
|
|
584
|
+
onValidatedMattertag() {
|
|
585
|
+
this.setInteractionMode(ViewerInteractions.DEFAULT);
|
|
586
|
+
const lastTag = this.getLastTag();
|
|
587
|
+
if (lastTag) {
|
|
588
|
+
const callbackMode = this.dictionnaryTags
|
|
589
|
+
.get(lastTag)
|
|
590
|
+
.getCallbackActionMode();
|
|
591
|
+
this.callbackAfterMattertagValidation(callbackMode);
|
|
592
|
+
}
|
|
593
|
+
}
|
|
594
|
+
/**
|
|
595
|
+
* Registers new icon (path to image) and set its for Mattertag
|
|
596
|
+
* @param mattertagID string
|
|
597
|
+
* @param iconPath string
|
|
598
|
+
*/
|
|
599
|
+
async addNewIconAndSetForTag(mattertagID, iconPath) {
|
|
600
|
+
await this.sdk.Asset.registerTexture(`icon_${mattertagID}`, iconPath);
|
|
601
|
+
this.sdk.Tag.editIcon(mattertagID, `icon_${mattertagID}`);
|
|
602
|
+
}
|
|
603
|
+
/**
|
|
604
|
+
* Changes icon of Mattertag (the iconName should be registered = one of default ones)
|
|
605
|
+
* @param mattertagID string
|
|
606
|
+
* @param iconName string
|
|
607
|
+
*/
|
|
608
|
+
async setRegistredIconForTag(mattertagID, iconName) {
|
|
609
|
+
try {
|
|
610
|
+
this.sdk.Tag.editIcon(mattertagID, iconName);
|
|
611
|
+
}
|
|
612
|
+
catch (e) {
|
|
613
|
+
console.log('could not edit Icon with name ', iconName, '. Is it registered?');
|
|
614
|
+
}
|
|
615
|
+
}
|
|
616
|
+
/**
|
|
617
|
+
* Sets default icon for a tag (registered in initSdk) OR uses tagIcon from POI (available from MattertagData)
|
|
618
|
+
* @param mattertagID string
|
|
619
|
+
* @param mattertagData MattertagData
|
|
620
|
+
* @returns
|
|
621
|
+
*/
|
|
622
|
+
async setTagIconAndOpacity(mattertagID, mattertagData) {
|
|
623
|
+
if (this.SPModule === SpModule.HOTEL) {
|
|
624
|
+
const room = mattertagData.getObject();
|
|
625
|
+
let iconName = `icon_room`;
|
|
626
|
+
if (room.available) {
|
|
627
|
+
iconName = `${iconName}_available`;
|
|
628
|
+
}
|
|
629
|
+
else {
|
|
630
|
+
iconName = `${iconName}_unavailable`;
|
|
631
|
+
}
|
|
632
|
+
this.sdk.Tag.editIcon(mattertagID, iconName);
|
|
633
|
+
return;
|
|
634
|
+
}
|
|
635
|
+
const stringTagType = poiTypeToString(mattertagData.getType());
|
|
636
|
+
let opacity = this.config.my_config.DEFAULT_OPACITY_TAG;
|
|
637
|
+
let iconName = `icon-${stringTagType}`;
|
|
638
|
+
const poi = mattertagData.getPoi();
|
|
639
|
+
if (poi && poi.tagIcon) {
|
|
640
|
+
const tagIcon = JSON.parse(poi.tagIcon);
|
|
641
|
+
if (mattertagData.getType() === PoiType.DATA) {
|
|
642
|
+
const feature = mattertagData.getObject();
|
|
643
|
+
if (feature.type === FeatureType.INDICATOR_TEMP) {
|
|
644
|
+
tagIcon.src = this.tagService.getIconTagImageForFeature(feature, poi);
|
|
645
|
+
}
|
|
646
|
+
}
|
|
647
|
+
if (tagIcon.src) {
|
|
648
|
+
const pathSigned = await this.tagService.getSignedTagIconSource(tagIcon.src);
|
|
649
|
+
if (pathSigned) {
|
|
650
|
+
try {
|
|
651
|
+
iconName = `icon-${stringTagType}-${mattertagID}-${mattertagData.customIconIndex}`;
|
|
652
|
+
await this.sdk.Asset.registerTexture(iconName, pathSigned);
|
|
653
|
+
mattertagData.customIconIndex += 1;
|
|
654
|
+
}
|
|
655
|
+
catch {
|
|
656
|
+
console.log('error registerIcon');
|
|
657
|
+
}
|
|
658
|
+
}
|
|
659
|
+
}
|
|
660
|
+
if (tagIcon.opacity) {
|
|
661
|
+
opacity = tagIcon.opacity;
|
|
662
|
+
}
|
|
663
|
+
}
|
|
664
|
+
try {
|
|
665
|
+
this.sdk.Tag.editIcon(mattertagID, iconName);
|
|
666
|
+
this.sdk.Tag.editOpacity(mattertagID, opacity);
|
|
667
|
+
}
|
|
668
|
+
catch (error) {
|
|
669
|
+
console.log('Error editIcon or opacity', error);
|
|
670
|
+
}
|
|
671
|
+
}
|
|
672
|
+
/**
|
|
673
|
+
* Moves viewer to last tag created
|
|
674
|
+
*/
|
|
675
|
+
goToLastTag() {
|
|
676
|
+
setTimeout(() => {
|
|
677
|
+
const lastTag = this.getLastTag();
|
|
678
|
+
this.goToTag(lastTag);
|
|
679
|
+
}, 2000);
|
|
680
|
+
}
|
|
681
|
+
/**
|
|
682
|
+
* Moves viewer to Mattertag with ID provided
|
|
683
|
+
* @param mattertagID string
|
|
684
|
+
* @returns
|
|
685
|
+
*/
|
|
686
|
+
async goToTag(mattertagID) {
|
|
687
|
+
if (mattertagID === '')
|
|
688
|
+
return;
|
|
689
|
+
try {
|
|
690
|
+
this.onGoToTag.next(mattertagID);
|
|
691
|
+
await this.sdk.Sweep.current.waitUntil((currentSweep) => currentSweep !== '');
|
|
692
|
+
await this.sdk.Mattertag.navigateToTag(mattertagID, this.sdk.Mattertag.Transition.FLY);
|
|
693
|
+
}
|
|
694
|
+
catch (error) {
|
|
695
|
+
console.log('cannot navigate to tag', error);
|
|
696
|
+
}
|
|
697
|
+
}
|
|
698
|
+
/**
|
|
699
|
+
* Updates content of Mattertag with mattertagID (billboard, injected html, tag icon)
|
|
700
|
+
* @param mattertagID string
|
|
701
|
+
* @param object Ticket, Equipment, Feature, etc
|
|
702
|
+
* @param tagType PoiType
|
|
703
|
+
*/
|
|
704
|
+
async updateMatterTagContentForTagID(mattertagID, object = null, tagType = null) {
|
|
705
|
+
this.sdk.Tag.editBillboard(mattertagID, this.dictionnaryTags.get(mattertagID).getData());
|
|
706
|
+
if (object && tagType) {
|
|
707
|
+
await this.injectHtmlInTag(tagType, object, mattertagID);
|
|
708
|
+
}
|
|
709
|
+
await this.setTagIconAndOpacity(mattertagID, this.dictionnaryTags.get(mattertagID));
|
|
710
|
+
}
|
|
711
|
+
/**
|
|
712
|
+
* Updates injected html for Mattertag
|
|
713
|
+
* @param mattertagID string
|
|
714
|
+
* @param object Ticket, Equipment, Feature, etc
|
|
715
|
+
* @param tagType PoiType
|
|
716
|
+
*/
|
|
717
|
+
async updateInjectedHtmlForTagID(mattertagID, object, tagType) {
|
|
718
|
+
await this.injectHtmlInTag(tagType, object, mattertagID);
|
|
719
|
+
}
|
|
720
|
+
/**
|
|
721
|
+
* Deletes Mattertag from Viewer by its ID
|
|
722
|
+
* @param mattertagID string
|
|
723
|
+
*/
|
|
724
|
+
deleteMattertagFromId(mattertagID) {
|
|
725
|
+
this.sdk.Tag.remove(mattertagID);
|
|
726
|
+
this.dictionnaryTags.delete(mattertagID);
|
|
727
|
+
}
|
|
728
|
+
/**
|
|
729
|
+
* Deletes latest created mattertag
|
|
730
|
+
*/
|
|
731
|
+
deleteLastMattertag() {
|
|
732
|
+
const mattertagID = this.mattertagIDs.pop();
|
|
733
|
+
if (mattertagID) {
|
|
734
|
+
this.deleteMattertagFromId(mattertagID);
|
|
735
|
+
}
|
|
736
|
+
}
|
|
737
|
+
/**
|
|
738
|
+
* Legacy: used to be called action_add_mattertag_from_POI
|
|
739
|
+
* Adds and configures Mattertag for an object (Ticket, Equipment, Feature, etc) that corresponds to POI (coordinates, tagIcon)
|
|
740
|
+
* @param tagType PoiType
|
|
741
|
+
* @param object Ticket, Equipment, Feature...
|
|
742
|
+
* @param poi POI
|
|
743
|
+
* @returns
|
|
744
|
+
*/
|
|
745
|
+
async createMattertagFromPOI(tagType, object, poi) {
|
|
746
|
+
// check if tag exists already
|
|
747
|
+
const { tag, sweep } = this.getTagFromElementId(object.id);
|
|
748
|
+
if (tag) {
|
|
749
|
+
// console.log("tag exists", object)
|
|
750
|
+
return;
|
|
751
|
+
}
|
|
752
|
+
const mattertagData = new MattertagData(tagType);
|
|
753
|
+
mattertagData.setObject(object, tagType);
|
|
754
|
+
if (poi.coordinate) {
|
|
755
|
+
mattertagData.setPosition(JSON.parse(poi.coordinate));
|
|
756
|
+
}
|
|
757
|
+
if (poi.metadata) {
|
|
758
|
+
const tagMetadata = JSON.parse(poi.metadata);
|
|
759
|
+
if (tagMetadata.normal) {
|
|
760
|
+
mattertagData.setNormal(tagMetadata.normal);
|
|
761
|
+
}
|
|
762
|
+
else {
|
|
763
|
+
mattertagData.setNormal({ x: 0, y: -0.15, z: 0 });
|
|
764
|
+
}
|
|
765
|
+
}
|
|
766
|
+
if (poi.matterportSweepID) {
|
|
767
|
+
mattertagData.setSweepID(poi.matterportSweepID);
|
|
768
|
+
}
|
|
769
|
+
mattertagData.setPoi(poi);
|
|
770
|
+
const createdTagID = await this.addMattertagToViewer(mattertagData);
|
|
771
|
+
if (createdTagID && this.sdk) {
|
|
772
|
+
await this.setTagIconAndOpacity(createdTagID, mattertagData);
|
|
773
|
+
await this.injectHtmlInTag(tagType, object, createdTagID);
|
|
774
|
+
}
|
|
775
|
+
}
|
|
776
|
+
/**
|
|
777
|
+
* Inject custom HTML as Mattertag content
|
|
778
|
+
* @param tagType PoiType
|
|
779
|
+
* @param object Ticket, Equipment, Feature etc
|
|
780
|
+
* @param tagID string
|
|
781
|
+
*/
|
|
782
|
+
async injectHtmlInTag(tagType, object, tagID) {
|
|
783
|
+
let html = await this.tagService.getHtmlToInject(tagType, object);
|
|
784
|
+
if (html !== '' && this.sdk) {
|
|
785
|
+
const scriptTag = this.tagService.getScriptForTag(object, tagType);
|
|
786
|
+
html += `${scriptTag}`;
|
|
787
|
+
// create and register the sandbox
|
|
788
|
+
const [sandboxId, messenger] = await this.sdk.Tag.registerSandbox(html);
|
|
789
|
+
// detach previous sandbox from a tag
|
|
790
|
+
let attachmentID = this.tagsAttachments[tagID];
|
|
791
|
+
if (attachmentID) {
|
|
792
|
+
this.sdk.Tag.detach(tagID, attachmentID);
|
|
793
|
+
}
|
|
794
|
+
this.tagsAttachments[tagID] = sandboxId;
|
|
795
|
+
// attach the sandbox to a tag
|
|
796
|
+
this.sdk.Tag.attach(tagID, sandboxId);
|
|
797
|
+
// receive data from the sandbox
|
|
798
|
+
// tagMessengerOn allows to go here only once
|
|
799
|
+
if (!this.tagMessengerOn) {
|
|
800
|
+
this.tagMessengerOn = true;
|
|
801
|
+
const imageClick = (featureID) => {
|
|
802
|
+
// console.log("image click handler", featureID);
|
|
803
|
+
this.tagService.onActionImageClick(featureID);
|
|
804
|
+
};
|
|
805
|
+
const audioClick = (audioCommentID) => {
|
|
806
|
+
// console.log("audio click handler", audioCommentID);
|
|
807
|
+
this.tagService.onActionAudioClick(audioCommentID);
|
|
808
|
+
};
|
|
809
|
+
const videoClick = (url) => {
|
|
810
|
+
this.tagService.onActionVideoClick(url);
|
|
811
|
+
};
|
|
812
|
+
messenger.on(TagAction.DETAIL_CLICK, this.tagService.onActionDetailClick.bind(this.tagService));
|
|
813
|
+
messenger.on(TagAction.TICKET_CLICK, this.tagService.onActionDetailClick.bind(this.tagService));
|
|
814
|
+
messenger.on(TagAction.AUDIO_CLICK, audioClick);
|
|
815
|
+
messenger.on(TagAction.IMAGE_CLICK, imageClick);
|
|
816
|
+
messenger.on(TagAction.VIDEO_CLICK, videoClick);
|
|
817
|
+
messenger.on(TagAction.DOC_CLICK, this.tagService.onActionDocClick.bind(this.tagService));
|
|
818
|
+
messenger.on(TagAction.YOUTUBE_CLICK, this.tagService.onActionYoutubeClick.bind(this.tagService));
|
|
819
|
+
}
|
|
820
|
+
}
|
|
821
|
+
else {
|
|
822
|
+
// if html is empty (case of EMBED content), we edit billboard for Feature and attach new content
|
|
823
|
+
const { comment, tagDescription } = this.tagService.getBillboardMediaToEmbed(object);
|
|
824
|
+
if (comment) {
|
|
825
|
+
// register the media
|
|
826
|
+
const [attachmentID] = await this.sdk.Tag.registerAttachment(comment.externalLink);
|
|
827
|
+
// attach
|
|
828
|
+
this.sdk.Tag.attach(tagID, attachmentID);
|
|
829
|
+
this.sdk.Tag.editBillboard(tagID, {
|
|
830
|
+
label: object.title,
|
|
831
|
+
description: tagDescription,
|
|
832
|
+
});
|
|
833
|
+
}
|
|
834
|
+
}
|
|
835
|
+
}
|
|
836
|
+
async action_delete_all_mattertags() {
|
|
837
|
+
await this.sdk.Tag.remove(...this.mattertagIDs);
|
|
838
|
+
this.mattertagIDs = [];
|
|
839
|
+
this.dictionnaryTags.clear();
|
|
840
|
+
}
|
|
841
|
+
/**
|
|
842
|
+
* Deletes Mattertag from visit associated with object ID (ticketID, etc)
|
|
843
|
+
* @param elementID string
|
|
844
|
+
*/
|
|
845
|
+
async deleteMattertagForObject(elementID) {
|
|
846
|
+
const matterTagID = this.getTagFromElementId(elementID).tag;
|
|
847
|
+
if (matterTagID) {
|
|
848
|
+
try {
|
|
849
|
+
await this.sdk.Tag.remove(matterTagID);
|
|
850
|
+
this.dictionnaryTags.delete(matterTagID);
|
|
851
|
+
const index = this.mattertagIDs.indexOf(matterTagID);
|
|
852
|
+
this.mattertagIDs.splice(index, 1);
|
|
853
|
+
}
|
|
854
|
+
catch (error) {
|
|
855
|
+
console.log('Cannot delete tag', matterTagID, error);
|
|
856
|
+
}
|
|
857
|
+
}
|
|
858
|
+
}
|
|
859
|
+
/**
|
|
860
|
+
* uuid from threejs
|
|
861
|
+
* @param uuid
|
|
862
|
+
*/
|
|
863
|
+
async deleteObject3D(uuid) {
|
|
864
|
+
this.dictionnaryObjects3D.get(uuid).obj3D.visible = false;
|
|
865
|
+
}
|
|
866
|
+
getObject3DModelNodeFromDictionnary(uuid) {
|
|
867
|
+
let obj = this.dictionnaryObjects3D.get(uuid);
|
|
868
|
+
if (!obj) {
|
|
869
|
+
console.log("weird thing again");
|
|
870
|
+
return null;
|
|
871
|
+
}
|
|
872
|
+
//might break things or fix everything ..?
|
|
873
|
+
if (obj.obj3D.uuid != uuid) {
|
|
874
|
+
console.log("we have THE problem");
|
|
875
|
+
obj.obj3D.uuid = uuid; //not enugh to fix the pb
|
|
876
|
+
}
|
|
877
|
+
return obj;
|
|
878
|
+
}
|
|
879
|
+
/**
|
|
880
|
+
* Creates MattertagData and start repositioning (creates temporary mattertag that follows the cursor)
|
|
881
|
+
* @param poiType PoiType
|
|
882
|
+
* @param element Ticket, Equipment, Feature, etc
|
|
883
|
+
*/
|
|
884
|
+
async addMattertagWhenRepositioning(poiType, element) {
|
|
885
|
+
const mattertagData = new MattertagData(poiType);
|
|
886
|
+
// set the coordinates of the existing tag
|
|
887
|
+
const [poi] = element.pois.items;
|
|
888
|
+
if (poi && poi.coordinate) {
|
|
889
|
+
mattertagData.setPosition(JSON.parse(poi.coordinate));
|
|
890
|
+
mattertagData.setPoi(poi); // to keep custom tagIcon and opacity
|
|
891
|
+
}
|
|
892
|
+
mattertagData.setSweepID(this.poseCamera.sweep);
|
|
893
|
+
mattertagData.setRotation(this.poseCamera.rotation);
|
|
894
|
+
mattertagData.setObject(element, poiType);
|
|
895
|
+
this.mattertagToFollow = await this.addMattertagToViewer(mattertagData);
|
|
896
|
+
this.setInteractionMode(ViewerInteractions.POSITIONING);
|
|
897
|
+
await this.addCursorMattertag(mattertagData);
|
|
898
|
+
}
|
|
899
|
+
/**
|
|
900
|
+
* Creates MattertagData and mattertag that follows the cursor when choosing position for a new object
|
|
901
|
+
* @param poiType
|
|
902
|
+
*/
|
|
903
|
+
async addMattertagWhenAdding(poiType) {
|
|
904
|
+
const mattertagData = new MattertagData(poiType);
|
|
905
|
+
mattertagData.setSweepID(this.poseCamera.sweep);
|
|
906
|
+
mattertagData.setRotation(this.poseCamera.rotation);
|
|
907
|
+
this.setInteractionMode(ViewerInteractions.ADDING);
|
|
908
|
+
await this.addCursorMattertag(mattertagData);
|
|
909
|
+
}
|
|
910
|
+
/**
|
|
911
|
+
* Cancels following of cursor (meaning deleting last Mattertag)
|
|
912
|
+
*/
|
|
913
|
+
cancelFollowingCursor() {
|
|
914
|
+
this.deleteLastMattertag();
|
|
915
|
+
this.setInteractionMode(ViewerInteractions.DEFAULT);
|
|
916
|
+
}
|
|
917
|
+
setLastObject3D(lastObject3D) {
|
|
918
|
+
this.lastObject3D = lastObject3D;
|
|
919
|
+
}
|
|
920
|
+
getLastObject3D() {
|
|
921
|
+
return this.lastObject3D;
|
|
922
|
+
}
|
|
923
|
+
/**
|
|
924
|
+
* Performs callback after mattertag position was validated (creation of object or repositioning)
|
|
925
|
+
* @param mode MattertagActionMode
|
|
926
|
+
*/
|
|
927
|
+
callbackAfterMattertagValidation(mode) {
|
|
928
|
+
this.visibilityService.detailShowing.next(true);
|
|
929
|
+
const lastTag = this.getLastTag();
|
|
930
|
+
switch (mode) {
|
|
931
|
+
case MattertagActionMode.ADD_EQUIPMENT:
|
|
932
|
+
this.goToLastTag();
|
|
933
|
+
this.router.navigate([`visit/${this.currentSpaceID}/add_equip`]);
|
|
934
|
+
break;
|
|
935
|
+
case MattertagActionMode.ADD_TICKET:
|
|
936
|
+
this.goToLastTag();
|
|
937
|
+
this.router.navigate([`visit/${this.currentSpaceID}/add_ticket`]);
|
|
938
|
+
break;
|
|
939
|
+
case MattertagActionMode.ADD_OBJECT3D:
|
|
940
|
+
this.goToLastTag();
|
|
941
|
+
this.router.navigate([`visit/${this.currentSpaceID}/add_object3d`]);
|
|
942
|
+
break;
|
|
943
|
+
case MattertagActionMode.ADD_DATA:
|
|
944
|
+
this.goToLastTag();
|
|
945
|
+
let url;
|
|
946
|
+
if (this.router.url.includes('?')) {
|
|
947
|
+
url = this.router.url.substring(0, this.router.url.indexOf('?'));
|
|
948
|
+
}
|
|
949
|
+
else {
|
|
950
|
+
url = this.router.url;
|
|
951
|
+
}
|
|
952
|
+
this.router.navigate([`${url}/add_feature`]);
|
|
953
|
+
break;
|
|
954
|
+
case MattertagActionMode.ADD_DESK:
|
|
955
|
+
this.goToLastTag();
|
|
956
|
+
this.router.navigate([`visit/${this.currentSpaceID}/add_feature`], {
|
|
957
|
+
queryParams: { isDesk: true },
|
|
958
|
+
});
|
|
959
|
+
break;
|
|
960
|
+
case MattertagActionMode.ADD_ROOM:
|
|
961
|
+
this.goToLastTag();
|
|
962
|
+
this.router.navigate([`visit/${this.currentSpaceID}/add_room`]);
|
|
963
|
+
break;
|
|
964
|
+
case MattertagActionMode.POSITION_OBJECT3D:
|
|
965
|
+
if (lastTag) {
|
|
966
|
+
// DO Nothing (routing), just
|
|
967
|
+
this.router.navigate([`visit/${this.currentSpaceID}/object3d/${this.lastObject3D.id}`], { queryParams: { positioning: true } });
|
|
968
|
+
}
|
|
969
|
+
break;
|
|
970
|
+
case MattertagActionMode.POSITION_TICKET:
|
|
971
|
+
if (lastTag) {
|
|
972
|
+
this.router.navigate([
|
|
973
|
+
`visit/${this.currentSpaceID}/detail/${this.dictionnaryTags.get(lastTag).elementID}`,
|
|
974
|
+
], { queryParams: { positioning: true } });
|
|
975
|
+
}
|
|
976
|
+
break;
|
|
977
|
+
case MattertagActionMode.POSITION_EQUIPMENT:
|
|
978
|
+
if (lastTag) {
|
|
979
|
+
this.router.navigate([
|
|
980
|
+
`visit/${this.currentSpaceID}/equip/${this.dictionnaryTags.get(lastTag).elementID}`,
|
|
981
|
+
], { queryParams: { positioning: true } });
|
|
982
|
+
}
|
|
983
|
+
break;
|
|
984
|
+
case MattertagActionMode.POSITION_DATA:
|
|
985
|
+
if (lastTag) {
|
|
986
|
+
this.router.navigate([], {
|
|
987
|
+
relativeTo: this.activeRoute,
|
|
988
|
+
queryParams: { positioning: true }, queryParamsHandling: "merge"
|
|
989
|
+
});
|
|
990
|
+
}
|
|
991
|
+
break;
|
|
992
|
+
case MattertagActionMode.POSITION_ROOM:
|
|
993
|
+
if (lastTag) {
|
|
994
|
+
this.router.navigate([], {
|
|
995
|
+
relativeTo: this.activeRoute,
|
|
996
|
+
queryParams: { positioning: true }, queryParamsHandling: "merge"
|
|
997
|
+
});
|
|
998
|
+
}
|
|
999
|
+
break;
|
|
1000
|
+
}
|
|
1001
|
+
}
|
|
1002
|
+
/**
|
|
1003
|
+
* Fully updates existing Mattertag content with data of object (Ticket, Equipment, Desk)
|
|
1004
|
+
* @param mattertagID string
|
|
1005
|
+
* @param object Ticket, Equipment, Feature, Desk
|
|
1006
|
+
* @param poiType PoiType
|
|
1007
|
+
* @param poi POI
|
|
1008
|
+
*/
|
|
1009
|
+
async setObjectAndPoiInTag(mattertagID, object, poiType, poi = null) {
|
|
1010
|
+
this.dictionnaryTags.get(mattertagID).setObject(object, poiType);
|
|
1011
|
+
if (poi) {
|
|
1012
|
+
this.dictionnaryTags.get(mattertagID).setPoi(poi);
|
|
1013
|
+
}
|
|
1014
|
+
this.dictionnaryTags.get(mattertagID).elementID = object.id;
|
|
1015
|
+
try {
|
|
1016
|
+
await this.updateMatterTagContentForTagID(mattertagID, object, poiType);
|
|
1017
|
+
// TODO: fix this
|
|
1018
|
+
await this.updateMatterTagPosInSdkViewer(mattertagID, object, poiType, poi);
|
|
1019
|
+
}
|
|
1020
|
+
catch (e) {
|
|
1021
|
+
console.log(`error in setObjectAndPoiInTag: ${e}`);
|
|
1022
|
+
}
|
|
1023
|
+
}
|
|
1024
|
+
async updateMatterTagPosInSdkViewer(mattertagID, object, poiType, poi = null) {
|
|
1025
|
+
const IndexToUpdate = object.pois.items.findIndex((u) => u.id === poi.id);
|
|
1026
|
+
object.pois.items[IndexToUpdate] = poi;
|
|
1027
|
+
const { x, y, z } = JSON.parse(poi.coordinate);
|
|
1028
|
+
const newPosition = {
|
|
1029
|
+
anchorPosition: {
|
|
1030
|
+
x: x,
|
|
1031
|
+
y: y,
|
|
1032
|
+
z: z,
|
|
1033
|
+
},
|
|
1034
|
+
stemVector: {
|
|
1035
|
+
// make the Tag stick straight up and make it 0.30 meters (~1 foot) tall
|
|
1036
|
+
x: 0,
|
|
1037
|
+
y: 0.3,
|
|
1038
|
+
z: 0,
|
|
1039
|
+
},
|
|
1040
|
+
};
|
|
1041
|
+
this.sdk.Mattertag.editPosition(mattertagID, newPosition);
|
|
1042
|
+
this.sdk.Tag.editPosition(mattertagID, newPosition);
|
|
1043
|
+
this.dictionnaryTags
|
|
1044
|
+
.get(mattertagID)
|
|
1045
|
+
.setPosition(newPosition.anchorPosition);
|
|
1046
|
+
for (let tagId of this.mattertagIDs) {
|
|
1047
|
+
const currentTag = this.dictionnaryTags.get(tagId);
|
|
1048
|
+
if (!currentTag) {
|
|
1049
|
+
continue;
|
|
1050
|
+
}
|
|
1051
|
+
if (currentTag.elementID === object.id && tagId !== mattertagID) {
|
|
1052
|
+
this.dictionnaryTags.delete(tagId);
|
|
1053
|
+
this.sdk.Tag.remove(tagId);
|
|
1054
|
+
this.sdk.Mattertag.remove(tagId);
|
|
1055
|
+
break;
|
|
1056
|
+
}
|
|
1057
|
+
}
|
|
1058
|
+
}
|
|
1059
|
+
/**
|
|
1060
|
+
* Gets matterTagID and its sweep for an object ID (ticket ID, etc)
|
|
1061
|
+
* @param elementID string
|
|
1062
|
+
* @returns {tag: string | null, sweep: string | null}
|
|
1063
|
+
*/
|
|
1064
|
+
getTagFromElementId(elementID) {
|
|
1065
|
+
let tagID = null;
|
|
1066
|
+
let sweepID = null;
|
|
1067
|
+
for (let [mattertagID, mattertagData] of this.dictionnaryTags) {
|
|
1068
|
+
if (mattertagData.elementID === elementID) {
|
|
1069
|
+
tagID = mattertagID;
|
|
1070
|
+
const sweep = mattertagData.getSweepID();
|
|
1071
|
+
if (sweep && this.sweeps && this.sweeps.includes(sweep)) {
|
|
1072
|
+
sweepID = sweep;
|
|
1073
|
+
}
|
|
1074
|
+
}
|
|
1075
|
+
}
|
|
1076
|
+
return { tag: tagID, sweep: sweepID };
|
|
1077
|
+
}
|
|
1078
|
+
/**
|
|
1079
|
+
* Gets latest tag created in the visit (when following the cursor to position)
|
|
1080
|
+
* @returns string mattertagID
|
|
1081
|
+
*/
|
|
1082
|
+
getLastTag() {
|
|
1083
|
+
if (this.mattertagToFollow) {
|
|
1084
|
+
return this.mattertagToFollow;
|
|
1085
|
+
}
|
|
1086
|
+
else {
|
|
1087
|
+
return this.mattertagIDs.length === 0
|
|
1088
|
+
? null
|
|
1089
|
+
: this.mattertagIDs[this.mattertagIDs.length - 1];
|
|
1090
|
+
}
|
|
1091
|
+
}
|
|
1092
|
+
/**
|
|
1093
|
+
* Gets MattertagData for Mattertag (replaces getTagDataFromId)
|
|
1094
|
+
* @param mattertagID
|
|
1095
|
+
* @returns MattertagData
|
|
1096
|
+
*/
|
|
1097
|
+
getMatterTagDataForMattertag(mattertagID) {
|
|
1098
|
+
try {
|
|
1099
|
+
return this.dictionnaryTags.get(mattertagID);
|
|
1100
|
+
}
|
|
1101
|
+
catch {
|
|
1102
|
+
console.log('cannot retrieve mattertagData for tag', mattertagID);
|
|
1103
|
+
}
|
|
1104
|
+
return null;
|
|
1105
|
+
}
|
|
1106
|
+
//
|
|
1107
|
+
// ---------- Viewer related (switch views, go to) ----------
|
|
1108
|
+
//
|
|
1109
|
+
async action_toolbox_floorplan() {
|
|
1110
|
+
if (this.inTransitionMode || this.inTransitionSweep) {
|
|
1111
|
+
console.log('viewer is in transition, cannot go floorplan');
|
|
1112
|
+
return;
|
|
1113
|
+
}
|
|
1114
|
+
try {
|
|
1115
|
+
await this.sdk.Mode.moveTo('mode.floorplan');
|
|
1116
|
+
}
|
|
1117
|
+
catch (e) {
|
|
1118
|
+
console.log('cannot go to floorplan', e);
|
|
1119
|
+
}
|
|
1120
|
+
}
|
|
1121
|
+
action_toolbox_inside_view() {
|
|
1122
|
+
this.sdk.Mode.moveTo('mode.inside');
|
|
1123
|
+
}
|
|
1124
|
+
actionShowAllFloors() {
|
|
1125
|
+
try {
|
|
1126
|
+
this.sdk.Floor.showAll();
|
|
1127
|
+
}
|
|
1128
|
+
catch (e) {
|
|
1129
|
+
console.log('cannot show all floors', e);
|
|
1130
|
+
}
|
|
1131
|
+
}
|
|
1132
|
+
async action_toolbox_dollhouse() {
|
|
1133
|
+
setTimeout(async () => {
|
|
1134
|
+
// console.log("mode: ", this.inTransitionMode, " sweep: ", this.inTransitionSweep);
|
|
1135
|
+
if (this.inTransitionMode || this.inTransitionSweep) {
|
|
1136
|
+
console.log('viewer is in transition, cannot go dollhouse');
|
|
1137
|
+
return;
|
|
1138
|
+
}
|
|
1139
|
+
try {
|
|
1140
|
+
await this.sdk.Mode.moveTo('mode.dollhouse');
|
|
1141
|
+
}
|
|
1142
|
+
catch (e) {
|
|
1143
|
+
console.log('cannot go to dollhouse', e);
|
|
1144
|
+
}
|
|
1145
|
+
}, 1200);
|
|
1146
|
+
}
|
|
1147
|
+
action_toolbox_mesure() {
|
|
1148
|
+
const newState = !this.isMeasureModeOn;
|
|
1149
|
+
this.sdk.Measurements.toggleMode(newState).then(() => {
|
|
1150
|
+
console.log(`Measurement mode is now ${newState ? 'enabled' : 'disabled'}`);
|
|
1151
|
+
});
|
|
1152
|
+
}
|
|
1153
|
+
action_toolbox_cancel_mesure() {
|
|
1154
|
+
if (this.isMeasureModeOn) {
|
|
1155
|
+
this.action_toolbox_mesure();
|
|
1156
|
+
}
|
|
1157
|
+
}
|
|
1158
|
+
async action_go_to_floor(floorName, matterportFloorSequence = null) {
|
|
1159
|
+
if (!this.floors) {
|
|
1160
|
+
console.log('Floor are not loaded yet');
|
|
1161
|
+
return;
|
|
1162
|
+
}
|
|
1163
|
+
// console.log(this.floors);
|
|
1164
|
+
// look up for sequence number (the safest method)
|
|
1165
|
+
let floorMatterport = this.floors.find((floor) => floor.sequence === matterportFloorSequence);
|
|
1166
|
+
if (!floorMatterport) {
|
|
1167
|
+
floorMatterport = this.floors.find((floor) => floorName.includes(floor.name) && floor.name != '');
|
|
1168
|
+
}
|
|
1169
|
+
if (!floorMatterport) {
|
|
1170
|
+
floorMatterport = this.floors.find((floor) => floorName.includes(floor.id));
|
|
1171
|
+
}
|
|
1172
|
+
// console.log(floorMatterport)
|
|
1173
|
+
if (floorMatterport) {
|
|
1174
|
+
let retry = true;
|
|
1175
|
+
while (retry) {
|
|
1176
|
+
try {
|
|
1177
|
+
const floorIndex = await this.sdk.Floor.moveTo(floorMatterport.sequence);
|
|
1178
|
+
// console.log("moved to floorIndex", floorIndex);
|
|
1179
|
+
retry = false;
|
|
1180
|
+
}
|
|
1181
|
+
catch (error) {
|
|
1182
|
+
console.log('Cannot move to Floor', error);
|
|
1183
|
+
await wait(100);
|
|
1184
|
+
}
|
|
1185
|
+
}
|
|
1186
|
+
}
|
|
1187
|
+
else {
|
|
1188
|
+
console.warn('No matterport floor found to move to');
|
|
1189
|
+
}
|
|
1190
|
+
}
|
|
1191
|
+
async action_go_to_sweep(sweep, rotation = null) {
|
|
1192
|
+
if (this.forbiddenSweeps.includes(sweep)) {
|
|
1193
|
+
console.log('user is not allowed to go to this sweep');
|
|
1194
|
+
return;
|
|
1195
|
+
}
|
|
1196
|
+
// console.log("going to sweep", sweep, "with rotation:", rotation);
|
|
1197
|
+
setTimeout(async () => {
|
|
1198
|
+
if (this.inTransitionMode || this.inTransitionSweep) {
|
|
1199
|
+
console.log('Cannot go to sweep, in transition');
|
|
1200
|
+
return;
|
|
1201
|
+
}
|
|
1202
|
+
try {
|
|
1203
|
+
this.inTransitionSweep = true;
|
|
1204
|
+
await this.sdk.Sweep.moveTo(sweep, {
|
|
1205
|
+
transition: 'transition.instant',
|
|
1206
|
+
transitionTime: 1500,
|
|
1207
|
+
});
|
|
1208
|
+
}
|
|
1209
|
+
catch (error) {
|
|
1210
|
+
this.inTransitionSweep = false;
|
|
1211
|
+
console.log('Cannot move to sweep', error);
|
|
1212
|
+
}
|
|
1213
|
+
if (rotation) {
|
|
1214
|
+
await this.sdk.Camera.setRotation(rotation, { speed: 100 }); // speed is degrees per second
|
|
1215
|
+
}
|
|
1216
|
+
}, 1000);
|
|
1217
|
+
}
|
|
1218
|
+
getCurrentSweep() {
|
|
1219
|
+
if (this.poseCamera) {
|
|
1220
|
+
return this.poseCamera.sweep;
|
|
1221
|
+
}
|
|
1222
|
+
return null;
|
|
1223
|
+
}
|
|
1224
|
+
getCurrentCameraPosition() {
|
|
1225
|
+
if (this.poseCamera) {
|
|
1226
|
+
return this.poseCamera;
|
|
1227
|
+
}
|
|
1228
|
+
return null;
|
|
1229
|
+
}
|
|
1230
|
+
setInteractionMode(interactionMode) {
|
|
1231
|
+
this.interactionMode = interactionMode;
|
|
1232
|
+
}
|
|
1233
|
+
getInteractionMode() {
|
|
1234
|
+
return this.interactionMode;
|
|
1235
|
+
}
|
|
1236
|
+
/**
|
|
1237
|
+
* Clear all variables, deletes all tags (when viewer is remover or model changed=reload needed)
|
|
1238
|
+
*/
|
|
1239
|
+
async clearAll() {
|
|
1240
|
+
console.log('removing viewer');
|
|
1241
|
+
this.action_delete_all_mattertags();
|
|
1242
|
+
this.floors = null;
|
|
1243
|
+
this.sweeps = null;
|
|
1244
|
+
this.sdk = null;
|
|
1245
|
+
clearInterval(this.timerPointer);
|
|
1246
|
+
this.forbiddenSweeps = [];
|
|
1247
|
+
this.tagMessengerOn = false;
|
|
1248
|
+
// cancel subscriptions
|
|
1249
|
+
this.pointerButton.removeEventListener('click', this.pointerLeftClickHandler);
|
|
1250
|
+
this.pointerButton.removeEventListener('contextmenu', this.pointerRightClickHandler);
|
|
1251
|
+
// TODO: only For Admins
|
|
1252
|
+
if (this.getCursorPositionButton) {
|
|
1253
|
+
this.getCursorPositionButton.removeEventListener('auxclick', this.pointerMiddleClickHandler);
|
|
1254
|
+
}
|
|
1255
|
+
// TODO: only for dev!
|
|
1256
|
+
if (!!this.getCursorPositionButton &&
|
|
1257
|
+
(document.location.href.indexOf('dev') !== -1 || document.location.href.indexOf('localhost') !== -1)) {
|
|
1258
|
+
clearInterval(this.intervalCursorPointerPosition);
|
|
1259
|
+
}
|
|
1260
|
+
}
|
|
1261
|
+
async removeForbiddenSweeps(forbiddenSweeps) {
|
|
1262
|
+
this.forbiddenSweeps = [...forbiddenSweeps];
|
|
1263
|
+
let removed = 0;
|
|
1264
|
+
await Promise.all(forbiddenSweeps.map(async (sweep) => {
|
|
1265
|
+
try {
|
|
1266
|
+
await this.sdk.Sweep.disable(sweep);
|
|
1267
|
+
removed += 1;
|
|
1268
|
+
}
|
|
1269
|
+
catch (error) {
|
|
1270
|
+
console.log(error);
|
|
1271
|
+
}
|
|
1272
|
+
}));
|
|
1273
|
+
console.log('removed sweeps:', removed);
|
|
1274
|
+
}
|
|
1275
|
+
//
|
|
1276
|
+
// ---------- 3D objects (SDK Bundle only) ----------
|
|
1277
|
+
//
|
|
1278
|
+
async init3DObjectViewer() {
|
|
1279
|
+
return new Promise(async (resolve) => {
|
|
1280
|
+
var [sceneObject] = await this.sdk.Scene.createObjects(1);
|
|
1281
|
+
var node = sceneObject.addNode();
|
|
1282
|
+
// TODO change this 🤮
|
|
1283
|
+
node.addComponent('mp.lights');
|
|
1284
|
+
//node.addComponent('mp.lights');
|
|
1285
|
+
/*node.addComponent('mp.lights');
|
|
1286
|
+
node.addComponent('mp.lights');*/
|
|
1287
|
+
node.start();
|
|
1288
|
+
const nodeControl = sceneObject.addNode();
|
|
1289
|
+
this.objectControl = nodeControl.addComponent('mp.transformControls');
|
|
1290
|
+
nodeControl.start();
|
|
1291
|
+
//this.add3DObject({},null);
|
|
1292
|
+
resolve();
|
|
1293
|
+
});
|
|
1294
|
+
}
|
|
1295
|
+
async add3DObject(obj, mode) {
|
|
1296
|
+
return new Promise(async (resolve) => {
|
|
1297
|
+
const [sceneObject] = await this.sdk.Scene.createObjects(1);
|
|
1298
|
+
// TODO: improvment, regroup all of these in Dynamical Objects Lib
|
|
1299
|
+
// SecurityCamera
|
|
1300
|
+
// NestThermostat
|
|
1301
|
+
// Video
|
|
1302
|
+
let isAnimatedSecurityCamera = false;
|
|
1303
|
+
let isNestThermostat = false;
|
|
1304
|
+
let isSmarterplanPromotionalVideo = false;
|
|
1305
|
+
let isAzimuthalCrown = false;
|
|
1306
|
+
/**
|
|
1307
|
+
* TODO: refacto with an enum or switch/case
|
|
1308
|
+
*/
|
|
1309
|
+
if (obj.object === "security_camera") {
|
|
1310
|
+
isAnimatedSecurityCamera = true;
|
|
1311
|
+
}
|
|
1312
|
+
if (obj.object === "nest_thermostat") {
|
|
1313
|
+
isNestThermostat = true;
|
|
1314
|
+
}
|
|
1315
|
+
if (obj.object === 'video') {
|
|
1316
|
+
isSmarterplanPromotionalVideo = true;
|
|
1317
|
+
}
|
|
1318
|
+
if (obj.object === 'azimuth') {
|
|
1319
|
+
isAzimuthalCrown = true;
|
|
1320
|
+
}
|
|
1321
|
+
const modelNode = sceneObject.addNode();
|
|
1322
|
+
let component = null;
|
|
1323
|
+
const initial = {
|
|
1324
|
+
url: `/assets/3Dobjects/objects/${obj.object}${obj.format.indexOf('.') === -1 ? '.' + obj.format : obj.format}`,
|
|
1325
|
+
// TODO/ store localPosition && localRotation in BDD too (in order to have pertfect initial placement)
|
|
1326
|
+
localRotation: { "x": 0, "y": 0, "z": 0 },
|
|
1327
|
+
// TODO/ store localPosition && localRotation in BDD too (in order to have pertfect initial placement)
|
|
1328
|
+
localPosition: { "x": 0, "y": 0, "z": 0 },
|
|
1329
|
+
visible: true,
|
|
1330
|
+
colliderEnabled: true
|
|
1331
|
+
};
|
|
1332
|
+
switch (obj.format) {
|
|
1333
|
+
case '.obj':
|
|
1334
|
+
case 'obj':
|
|
1335
|
+
component = modelNode.addComponent('mp.objLoader', initial);
|
|
1336
|
+
break;
|
|
1337
|
+
case '.fbx':
|
|
1338
|
+
case 'fbx':
|
|
1339
|
+
component = modelNode.addComponent('mp.fbxLoader', initial);
|
|
1340
|
+
break;
|
|
1341
|
+
case '.gltf':
|
|
1342
|
+
case 'gltf':
|
|
1343
|
+
component = modelNode.addComponent('mp.gltfLoader', initial);
|
|
1344
|
+
break;
|
|
1345
|
+
case '.glb':
|
|
1346
|
+
case 'glb':
|
|
1347
|
+
component = modelNode.addComponent('mp.gltfLoader', initial);
|
|
1348
|
+
break;
|
|
1349
|
+
case '.dae':
|
|
1350
|
+
case 'dae':
|
|
1351
|
+
component = modelNode.addComponent('mp.daeLoader', initial);
|
|
1352
|
+
break;
|
|
1353
|
+
default:
|
|
1354
|
+
console.log('Format not supported');
|
|
1355
|
+
break;
|
|
1356
|
+
}
|
|
1357
|
+
//cache system (i'll try to make it work later ...)
|
|
1358
|
+
/*let objContentsJSON = JSON.stringify(modelNode);
|
|
1359
|
+
console.log(modelNode);
|
|
1360
|
+
console.log(objContentsJSON);
|
|
1361
|
+
console.log(JSON.stringify(modelNode));
|
|
1362
|
+
localStorage.setItem(`testObj_${obj.object}`, objContentsJSON);
|
|
1363
|
+
console.log("stored ?!");
|
|
1364
|
+
console.log(typeof modelNode);*/
|
|
1365
|
+
//let dataS = serialijse.serialize(modelNode);
|
|
1366
|
+
//console.log(dataS);
|
|
1367
|
+
// Use 3 ?! Ambient lightings
|
|
1368
|
+
if (this.noLightForObjects) {
|
|
1369
|
+
const lightsNode = sceneObject.addNode();
|
|
1370
|
+
lightsNode.addComponent('mp.ambientLight', {
|
|
1371
|
+
intensity: 1,
|
|
1372
|
+
color: { r: 1.0, g: 1.0, b: 1.0 },
|
|
1373
|
+
});
|
|
1374
|
+
this.noLightForObjects = false;
|
|
1375
|
+
}
|
|
1376
|
+
modelNode.obj3D.position.set(obj.position.x, obj.position.y, obj.position.z);
|
|
1377
|
+
modelNode.obj3D.rotation.set(obj.rotation.x, obj.rotation.y, obj.rotation.z);
|
|
1378
|
+
modelNode.obj3D.scale.set(obj.scale.x, obj.scale.y, obj.scale.z);
|
|
1379
|
+
if (isAzimuthalCrown) {
|
|
1380
|
+
/*if(modelNode.obj3D.scale.x >= 1.0){
|
|
1381
|
+
modelNode.obj3D.scale.set(obj.scale.x/5000, obj.scale.y/5000, obj.scale.z/5000);
|
|
1382
|
+
}*/
|
|
1383
|
+
this.azimuthalCrown = modelNode;
|
|
1384
|
+
this.displayAzimutalCrown();
|
|
1385
|
+
}
|
|
1386
|
+
// By defaut, during creation, object has translation gizmo
|
|
1387
|
+
// => User has to click on lateral panel, and save its position after playing with it!
|
|
1388
|
+
if (mode && !isNestThermostat) {
|
|
1389
|
+
this.attachGizmoControlTo3DObject(modelNode, sceneObject, mode, true, true).catch((e) => console.log(e));
|
|
1390
|
+
}
|
|
1391
|
+
if (this.lastObject3D && typeof this.lastObject3D.id === 'string') {
|
|
1392
|
+
// prompt ThreeJS UUID to match our last generated object if new (not from Db)
|
|
1393
|
+
modelNode.obj3D.uuid = this.lastObject3D.id;
|
|
1394
|
+
}
|
|
1395
|
+
else if (obj.id) {
|
|
1396
|
+
modelNode.obj3D.uuid = obj.id;
|
|
1397
|
+
}
|
|
1398
|
+
this.lastObject3D = modelNode.obj3D;
|
|
1399
|
+
// Store this in memory Map dictionnary
|
|
1400
|
+
//console.log("Adding object: ");
|
|
1401
|
+
//console.log(modelNode);
|
|
1402
|
+
this.dictionnaryObjects3D.set(modelNode.obj3D.uuid, modelNode);
|
|
1403
|
+
this.dictionnarySceneObjects3D.set(modelNode.obj3D.uuid, sceneObject);
|
|
1404
|
+
/*this.sdk.Camera.pose.subscribe(
|
|
1405
|
+
function (pose: any) {
|
|
1406
|
+
//console.log("in callback")
|
|
1407
|
+
//console.log(this.lastCameraPosition)
|
|
1408
|
+
//console.log(pose.position)
|
|
1409
|
+
if((pose.position.x == this.lastCameraPosition.x && pose.position.y == this.lastCameraPosition.y && pose.position.z == this.lastCameraPosition.z) || this.inTransitionMode || this.inTransitionSweep){
|
|
1410
|
+
//console.log("returning")
|
|
1411
|
+
return;
|
|
1412
|
+
}
|
|
1413
|
+
console.log("camera pos:",pose.position);
|
|
1414
|
+
this.lastCameraPosition = {...pose.position};
|
|
1415
|
+
if(this.lastObject3D){
|
|
1416
|
+
this.lastObject3D.position.set(pose.position.x+.5,pose.position.y+.5,pose.position.z+.5);
|
|
1417
|
+
}
|
|
1418
|
+
}.bind(this));*/
|
|
1419
|
+
if (isAnimatedSecurityCamera) {
|
|
1420
|
+
const animator = modelNode.addComponent('mp.securityCamera', {
|
|
1421
|
+
"nearPlane": 0.1,
|
|
1422
|
+
"farPlane": 10,
|
|
1423
|
+
"horizontalFOV": 52,
|
|
1424
|
+
"aspect": 1.7777777777777777,
|
|
1425
|
+
"localPosition": {
|
|
1426
|
+
"x": 0.3,
|
|
1427
|
+
"y": 0.18,
|
|
1428
|
+
"z": 0
|
|
1429
|
+
},
|
|
1430
|
+
"localRotation": {
|
|
1431
|
+
"x": -15,
|
|
1432
|
+
"y": -90,
|
|
1433
|
+
"z": 0
|
|
1434
|
+
},
|
|
1435
|
+
"color": 65280,
|
|
1436
|
+
"panPeriod": 5,
|
|
1437
|
+
"panAngle": -45
|
|
1438
|
+
});
|
|
1439
|
+
const modelOutput = sceneObject.addPath({
|
|
1440
|
+
id: 'animated-model',
|
|
1441
|
+
type: this.sdk.Scene.PathType.OUTPUT,
|
|
1442
|
+
node: modelNode,
|
|
1443
|
+
component: animator,
|
|
1444
|
+
property: 'objectRoot'
|
|
1445
|
+
});
|
|
1446
|
+
this.securityCameraAnimator = animator;
|
|
1447
|
+
if (!obj.viewFrustum) {
|
|
1448
|
+
setTimeout(() => {
|
|
1449
|
+
animator.toggleViewFrustum();
|
|
1450
|
+
}, 1000);
|
|
1451
|
+
}
|
|
1452
|
+
}
|
|
1453
|
+
if (isNestThermostat) {
|
|
1454
|
+
// TODO: use bindPath instead using MP sdk classes (see Security Camera example)
|
|
1455
|
+
// for TV uses CanvasImage below!
|
|
1456
|
+
// const ci = new CanvasImage();
|
|
1457
|
+
// ci.onInit();
|
|
1458
|
+
const cv = new CanvasRenderer();
|
|
1459
|
+
cv.onInit();
|
|
1460
|
+
const plane = new PlaneRenderer();
|
|
1461
|
+
plane.outputs = {
|
|
1462
|
+
objectRoot: new Object3D(),
|
|
1463
|
+
collider: new Object3D()
|
|
1464
|
+
};
|
|
1465
|
+
const inputTexture = cv.outputs.texture;
|
|
1466
|
+
plane.setRootScene(this.threeJSScene);
|
|
1467
|
+
plane.onInit(modelNode, inputTexture);
|
|
1468
|
+
const sc = new NestThermostat();
|
|
1469
|
+
sc.setComponent(component, plane, cv);
|
|
1470
|
+
sc.setRootScene(this.threeJSScene);
|
|
1471
|
+
sc.onInit(modelNode, plane, inputTexture);
|
|
1472
|
+
cv.setCanvasNestThermostatPainter(sc);
|
|
1473
|
+
setTimeout(() => {
|
|
1474
|
+
sc.inputs.loadingState = "Loaded";
|
|
1475
|
+
sc.onInputsUpdated();
|
|
1476
|
+
}, 5000);
|
|
1477
|
+
}
|
|
1478
|
+
if (isSmarterplanPromotionalVideo) {
|
|
1479
|
+
// TODO: use bindPath instead using MP sdk classes (see Security Camera example)
|
|
1480
|
+
const sc = new TvPlayer();
|
|
1481
|
+
sc.setComponent(component);
|
|
1482
|
+
sc.onInit(modelNode);
|
|
1483
|
+
setTimeout(() => {
|
|
1484
|
+
sc.inputs.loadingState = "Loaded";
|
|
1485
|
+
sc.onInputsUpdated();
|
|
1486
|
+
}, 5000);
|
|
1487
|
+
}
|
|
1488
|
+
sceneObject.start();
|
|
1489
|
+
resolve(this.lastObject3D);
|
|
1490
|
+
});
|
|
1491
|
+
}
|
|
1492
|
+
toggleObjectVisibility(objectId) {
|
|
1493
|
+
let obj = this.dictionnaryObjects3D.get(objectId);
|
|
1494
|
+
obj.obj3D.visible = !obj.obj3D.visible;
|
|
1495
|
+
}
|
|
1496
|
+
isObjectVisible(objectId) {
|
|
1497
|
+
let obj = this.dictionnaryObjects3D.get(objectId);
|
|
1498
|
+
return obj.obj3D.visible;
|
|
1499
|
+
}
|
|
1500
|
+
async pointCameraTo3DObject(objectId) {
|
|
1501
|
+
let obj = this.dictionnaryObjects3D.get(objectId);
|
|
1502
|
+
//We create a temporary Tag
|
|
1503
|
+
const poiObject = {
|
|
1504
|
+
coordinate: JSON.stringify(obj.obj3D.position),
|
|
1505
|
+
type: PoiType.OBJECT3D,
|
|
1506
|
+
elementID: objectId, //todo: be careful with this
|
|
1507
|
+
};
|
|
1508
|
+
const objectDb = { id: objectId };
|
|
1509
|
+
try {
|
|
1510
|
+
await this.createMattertagFromPOI(PoiType.OBJECT3D, objectDb, poiObject);
|
|
1511
|
+
}
|
|
1512
|
+
catch (err) { }
|
|
1513
|
+
//Not really necessary anymore since the tag will disappear quick
|
|
1514
|
+
//this.sdk.Tag.editOpacity(mattertagID, 0.0);//opacity);
|
|
1515
|
+
//this.sdk.Tag.allowAction(mattertagID, {}); //disables every action
|
|
1516
|
+
let result = this.getTagFromElementId(objectId);
|
|
1517
|
+
await this.goToTag(result.tag);
|
|
1518
|
+
this.deleteLastMattertag();
|
|
1519
|
+
}
|
|
1520
|
+
getSceneNodeFromObject3DId(uuid) {
|
|
1521
|
+
return this.dictionnarySceneObjects3D.get(uuid);
|
|
1522
|
+
}
|
|
1523
|
+
async displayAzimutalCrown() {
|
|
1524
|
+
if (this.azimuthalCrown) {
|
|
1525
|
+
this.azimuthalCrown.obj3D.position.set(this.poseCamera.position.x, this.poseCamera.position.y, this.poseCamera.position.z);
|
|
1526
|
+
}
|
|
1527
|
+
}
|
|
1528
|
+
async attachGizmoControlTo3DObject(modelNode, sceneObject, mode, visible, isNewObject) {
|
|
1529
|
+
// Create a scene node with a transform control component.
|
|
1530
|
+
let node = null;
|
|
1531
|
+
node = sceneObject.addNode();
|
|
1532
|
+
if (!node) {
|
|
1533
|
+
const [sceneObject] = await this.sdk.Scene.createObjects(1);
|
|
1534
|
+
node = sceneObject.addNode();
|
|
1535
|
+
}
|
|
1536
|
+
const myControl = node.addComponent('mp.transformControls');
|
|
1537
|
+
node.start();
|
|
1538
|
+
//
|
|
1539
|
+
// // Make the transform control visible so that the user can manipulate the control selection.
|
|
1540
|
+
myControl.transformControls.visible = visible;
|
|
1541
|
+
//
|
|
1542
|
+
// // Attach the model to the transform control
|
|
1543
|
+
myControl.inputs.selection = modelNode;
|
|
1544
|
+
//
|
|
1545
|
+
// // set 'translate' mode to position the selection.
|
|
1546
|
+
myControl.inputs.mode = mode;
|
|
1547
|
+
modelNode.obj3D.controls = myControl; // store gizmoCtrl inside object
|
|
1548
|
+
if (isNewObject) { //i keep the current solution for new objects
|
|
1549
|
+
if (!this.lastObject3D || !this.lastObject3D.controls) {
|
|
1550
|
+
try {
|
|
1551
|
+
modelNode.obj3D.uuid = this.lastObject3D.uuid || this.lastObject3D.id;
|
|
1552
|
+
}
|
|
1553
|
+
catch (e) {
|
|
1554
|
+
console.log(`id obj in Scene was not assigned to id from DB since`);
|
|
1555
|
+
}
|
|
1556
|
+
this.lastObject3D = modelNode.obj3D;
|
|
1557
|
+
}
|
|
1558
|
+
}
|
|
1559
|
+
else { //objects already in place have to become the "lastObject" (i think?)
|
|
1560
|
+
console.log("in my solution !");
|
|
1561
|
+
console.log(modelNode);
|
|
1562
|
+
console.log(modelNode.obj3D.uuid);
|
|
1563
|
+
this.lastObject3D = modelNode.obj3D;
|
|
1564
|
+
}
|
|
1565
|
+
return modelNode;
|
|
1566
|
+
}
|
|
1567
|
+
removeGizmoFromLastObject() {
|
|
1568
|
+
this.lastObject3D.controls.transformControls.visible = false;
|
|
1569
|
+
this.lastObject3D.controls.transformControls.dispose();
|
|
1570
|
+
this.lastObject3D.controls = null;
|
|
1571
|
+
}
|
|
1572
|
+
toggleViewFrustum() {
|
|
1573
|
+
this.securityCameraAnimator.toggleViewFrustum();
|
|
1574
|
+
}
|
|
1575
|
+
}
|
|
1576
|
+
MatterportService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.2.7", ngImport: i0, type: MatterportService, deps: [{ token: 'config' }, { token: i1.Router }, { token: i1.ActivatedRoute }, { token: i2.BaseVisibilityService }, { token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
1577
|
+
MatterportService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "13.2.7", ngImport: i0, type: MatterportService, providedIn: 'root' });
|
|
1578
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.2.7", ngImport: i0, type: MatterportService, decorators: [{
|
|
1579
|
+
type: Injectable,
|
|
1580
|
+
args: [{
|
|
1581
|
+
providedIn: 'root',
|
|
1582
|
+
}]
|
|
1583
|
+
}], ctorParameters: function () { return [{ type: i3.Config, decorators: [{
|
|
1584
|
+
type: Inject,
|
|
1585
|
+
args: ['config']
|
|
1586
|
+
}] }, { type: i1.Router }, { type: i1.ActivatedRoute }, { type: i2.BaseVisibilityService }, { type: i0.NgZone }]; } });
|
|
1587
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWF0dGVycG9ydC5zZXJ2aWNlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvbmd4LXNtYXJ0ZXJwbGFuLWNvcmUvc3JjL2xpYi9zZXJ2aWNlcy9tYXR0ZXJwb3J0LnNlcnZpY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFDLE1BQU0sRUFBRSxVQUFVLEVBQVMsTUFBTSxlQUFlLENBQUM7QUFFekQsT0FBTyxFQUFDLE9BQU8sRUFBQyxNQUFNLE1BQU0sQ0FBQztBQUM3QiwyQ0FBMkM7QUFDM0MsT0FBTyxFQUNMLDJCQUEyQixFQUMzQixlQUFlLEVBQ2YsSUFBSSxHQUNMLE1BQU0sb0JBQW9CLENBQUM7QUFDNUIsT0FBTyxFQUFDLGFBQWEsRUFBQyxNQUFNLGtCQUFrQixDQUFDO0FBQy9DLE9BQU8sRUFFTCxXQUFXLEVBRVgsbUJBQW1CLEVBRW5CLE9BQU8sRUFDUCxRQUFRLEVBQ1IsU0FBUyxFQUNULGtCQUFrQixHQUNuQixNQUFNLGtCQUFrQixDQUFDO0FBQzFCLE9BQU8sRUFBQyxRQUFRLEVBQUMsTUFBTSxPQUFPLENBQUM7QUFJL0IsT0FBTyxFQUFDLFVBQVUsRUFBQyxNQUFNLGtCQUFrQixDQUFDO0FBRzVDLE9BQU8sRUFBQyxjQUFjLEVBQUMsTUFBTSx5REFBeUQsQ0FBQztBQUN2RixPQUFPLEVBQUMsYUFBYSxFQUFDLE1BQU0sd0RBQXdELENBQUM7QUFDckYsT0FBTyxFQUFDLGNBQWMsRUFBQyxNQUFNLHlEQUF5RCxDQUFDO0FBR3ZGLE9BQU8sRUFBQyxRQUFRLEVBQUMsTUFBTSw2Q0FBNkMsQ0FBQzs7Ozs7QUF3QnJFLE1BQU0sT0FBTyxpQkFBaUI7SUFvSjVCLFlBQ29CLE1BQWMsRUFDeEIsTUFBYyxFQUNkLFdBQTJCLEVBQzNCLGlCQUF3QyxFQUN4QyxNQUFjO1FBSGQsV0FBTSxHQUFOLE1BQU0sQ0FBUTtRQUNkLGdCQUFXLEdBQVgsV0FBVyxDQUFnQjtRQUMzQixzQkFBaUIsR0FBakIsaUJBQWlCLENBQXVCO1FBQ3hDLFdBQU0sR0FBTixNQUFNLENBQVE7UUF2SmhCLFVBQUssR0FBVSxFQUFFLENBQUMsQ0FBQSxrQkFBa0I7UUFFcEMsVUFBSyxHQUFpQixFQUFFLENBQUM7UUFVMUIsdUJBQWtCLEdBQVEsRUFBQyxDQUFDLEVBQUMsR0FBRyxFQUFDLENBQUMsRUFBQyxHQUFHLEVBQUMsQ0FBQyxFQUFDLEdBQUcsRUFBQyxDQUFDO1FBUTdDLGtDQUE2QixHQUFHLEtBQUssQ0FBQztRQUs5QyxlQUFlO1FBQ1Asb0JBQWUsR0FBRyxLQUFLLENBQUM7UUFFeEIsb0JBQWUsR0FBVyxrQkFBa0IsQ0FBQyxPQUFPLENBQUM7UUFFN0QsOERBQThEO1FBQ3RELGlCQUFZLEdBQWtCLEVBQUUsQ0FBQztRQUV6QywwREFBMEQ7UUFDbEQsb0JBQWUsR0FBK0IsSUFBSSxHQUFHLEVBQUUsQ0FBQztRQUV4RCx5QkFBb0IsR0FBcUIsSUFBSSxHQUFHLEVBQUUsQ0FBQztRQUVuRCw4QkFBeUIsR0FBcUIsSUFBSSxHQUFHLEVBQUUsQ0FBQztRQUl4RCxnQkFBVyxHQUFHLEVBQUUsQ0FBQztRQUVqQix5QkFBb0IsR0FBYSxFQUFFLENBQUM7UUFFcEMsZUFBVSxHQUFHO1lBQ25CLEtBQUssRUFBRSxHQUFHO1lBQ1YsTUFBTSxFQUFFLEdBQUc7U0FDWixDQUFDO1FBRU0sZUFBVSxHQUFHO1lBQ25CLFVBQVUsRUFBRSxLQUFLO1lBQ2pCLE1BQU0sRUFBRSxJQUFJO1NBQ2IsQ0FBQztRQUVLLG9CQUFlLEdBQVcsRUFBRSxDQUFDO1FBTTdCLGlCQUFZLEdBQW9CLElBQUksT0FBTyxFQUFFLENBQUM7UUFFckQsK0JBQStCO1FBQ3hCLHNCQUFpQixHQUFpQixJQUFJLE9BQU8sRUFBRSxDQUFDO1FBb0J2RCxvQkFBZSxHQUFhLEVBQUUsQ0FBQztRQUV4QixjQUFTLEdBQThDLElBQUksT0FBTyxFQUFFLENBQUM7UUFRckUscUJBQWdCLEdBQUcsS0FBSyxDQUFDO1FBRXpCLHNCQUFpQixHQUFHLEtBQUssQ0FBQztRQUV6QixzQkFBaUIsR0FBRyxJQUFJLENBQUM7UUFFMUIsc0JBQWlCLEdBQWUsVUFBVSxDQUFDLE9BQU8sQ0FBQztRQUVuRCx3QkFBbUIsR0FBRyxJQUFJLE9BQU8sRUFBYyxDQUFDO1FBRWhELGNBQVMsR0FBRyxJQUFJLE9BQU8sRUFBVSxDQUFDO1FBRXpDLG1CQUFjLEdBQUcsS0FBSyxDQUFDO1FBUXZCOztXQUVHO1FBQ0gsNEJBQXVCLEdBQUcsR0FBRyxFQUFFO1lBQzdCLElBQUksSUFBSSxDQUFDLGlCQUFpQixFQUFFO2dCQUMxQixNQUFNLGFBQWEsR0FBRyxJQUFJLENBQUMsZUFBZSxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsaUJBQWlCLENBQUMsQ0FBQztnQkFDdkUsYUFBYSxDQUFDLFdBQVcsQ0FBQyxFQUFDLEdBQUcsSUFBSSxDQUFDLGNBQWMsQ0FBQyxRQUFRLEVBQUMsQ0FBQyxDQUFDLENBQUMsMkJBQTJCO2dCQUN6RixhQUFhLENBQUMsU0FBUyxDQUFDLEVBQUMsR0FBRyxJQUFJLENBQUMsY0FBYyxDQUFDLE1BQU0sRUFBQyxDQUFDLENBQUMsQ0FBQywyQkFBMkI7Z0JBQ3JGLElBQUksQ0FBQyxlQUFlLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxpQkFBaUIsRUFBRSxhQUFhLENBQUMsQ0FBQztnQkFDaEUsSUFBSSxDQUFDLDhCQUE4QixDQUFDLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDO2FBQzdEO1lBQ0QsSUFBSSxDQUFDLG9CQUFvQixFQUFFLENBQUM7UUFDOUIsQ0FBQyxDQUFDO1FBRUYsNkJBQXdCLEdBQUcsQ0FBQyxDQUFDLEVBQUUsRUFBRTtZQUMvQixDQUFDLENBQUMsY0FBYyxFQUFFLENBQUM7WUFDbkIsSUFBSSxDQUFDLHFCQUFxQixFQUFFLENBQUM7WUFDN0IsS0FBSyxDQUFDLGtCQUFrQixDQUFDLENBQUM7UUFDNUIsQ0FBQyxDQUFDO1FBRUYsOEJBQXlCLEdBQUcsQ0FBQyxDQUFDLEVBQUUsRUFBRTtZQUNoQyxJQUFJLENBQUMsOEJBQThCLENBQUMsU0FBUyxHQUFHO1NBQzNDLElBQUksQ0FBQyxhQUFhLENBQUMsSUFBSSxDQUFDLGNBQWMsQ0FBQyxRQUFRLENBQUM7O1NBRWhELElBQUksQ0FBQyxhQUFhLENBQUMsSUFBSSxDQUFDLGNBQWMsQ0FBQyxNQUFNLENBQUM7O1NBRTlDLElBQUksQ0FBQyxjQUFjLENBQUMsT0FBTyxFQUFFLENBQUM7WUFDbkMsaUVBQWlFO1lBQ2pFLElBQUksQ0FBQyx1QkFBdUIsQ0FBQyxLQUFLLENBQUMsT0FBTyxHQUFHLE1BQU0sQ0FBQztRQUN0RCxDQUFDLENBQUE7UUFTQyxJQUFJLENBQUMsTUFBTSxHQUFHLE1BQU0sQ0FBQztRQUVyQixzQkFBc0I7UUFDdEIsSUFBSSxDQUFDLENBQUMsSUFBSSxDQUFDLHVCQUF1QjtZQUNoQyxDQUFDLFFBQVEsQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLENBQUMsSUFBSSxRQUFRLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsV0FBVyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsRUFBRTtZQUN0RyxJQUFJLENBQUMsNkJBQTZCLEdBQUcsV0FBVyxDQUFDLEdBQUcsRUFBRTtnQkFDcEQsSUFBSSxDQUFDLElBQUksQ0FBQyxjQUFjLEVBQUU7b0JBQ3hCLE9BQU87aUJBQ1I7Z0JBRUQsTUFBTSxRQUFRLEdBQUcsSUFBSSxDQUFDLGNBQWMsQ0FBQyxJQUFJLEdBQUcsSUFBSSxDQUFDO2dCQUNqRCxJQUFJLElBQUksSUFBSSxFQUFFLENBQUMsT0FBTyxFQUFFLEdBQUcsUUFBUSxFQUFFO29CQUNuQyxJQUFJLElBQUksQ0FBQyw2QkFBNkIsRUFBRTt3QkFDdEMsT0FBTztxQkFDUjtvQkFFRCxNQUFNLElBQUksR0FBRzt3QkFDWCxDQUFDLEVBQUUsSUFBSSxDQUFDLFNBQVMsQ0FBQyxXQUFXO3dCQUM3QixDQUFDLEVBQUUsSUFBSSxDQUFDLFNBQVMsQ0FBQyxZQUFZO3FCQUMvQixDQUFDO29CQUNGLE1BQU0sS0FBSyxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsVUFBVSxDQUFDLGFBQWEsQ0FBQyxJQUFJLENBQUMsY0FBYyxDQUFDLFFBQVEsRUFBRSxJQUFJLENBQUMsVUFBVSxFQUFFLElBQUksQ0FBQyxDQUFDO29CQUNyRyxJQUFJLENBQUMsdUJBQXVCLENBQUMsS0FBSyxDQUFDLElBQUksR0FBRyxHQUFHLEtBQUssQ0FBQyxDQUFDLEdBQUcsRUFBRSxJQUFJLENBQUM7b0JBQzlELElBQUksQ0FBQyx1QkFBdUIsQ0FBQyxLQUFLLENBQUMsR0FBRyxHQUFHLEdBQUcsS0FBSyxDQUFDLENBQUMsR0FBRyxFQUFFLElBQUksQ0FBQztvQkFDN0QsSUFBSSxDQUFDLHVCQUF1QixDQUFDLEtBQUssQ0FBQyxPQUFPLEdBQUcsT0FBTyxDQUFDO29CQUNyRCw4REFBOEQ7b0JBQzlELElBQUksQ0FBQyw2QkFBNkIsR0FBRyxJQUFJLENBQUM7aUJBQzNDO1lBQ0gsQ0FBQyxFQUFFLEdBQUcsQ0FBQyxDQUFDO1NBQ1Q7SUFDSCxDQUFDO0lBM0dELElBQVcsY0FBYztRQUN2QixPQUFPLElBQUksQ0FBQyxlQUFlLENBQUM7SUFDOUIsQ0FBQztJQUVELElBQVcsY0FBYyxDQUFDLEtBQWE7UUFDckMsSUFBSSxDQUFDLGVBQWUsR0FBRyxLQUFLLENBQUM7SUFDL0IsQ0FBQztJQXVHRDs7Ozs7T0FLRztJQUNILEtBQUssQ0FBQyxPQUFPLENBQ1gsVUFBMEIsRUFDMUIsU0FBbUIsUUFBUSxDQUFDLElBQUk7UUFFaEMsSUFBSSxJQUFJLENBQUMsR0FBRyxFQUFFO1lBQ1osa0NBQWtDO1lBQ2xDLE1BQU0sSUFBSSxDQUFDLDRCQUE0QixFQUFFLENBQUM7U0FDM0M7UUFDRCxJQUFJLENBQUMsVUFBVSxHQUFHLFVBQVUsQ0FBQztRQUM3QixJQUFJLENBQUMsUUFBUSxHQUFHLE1BQU0sQ0FBQztRQUN2QixPQUFPLElBQUksT0FBTyxDQUFDLENBQUMsT0FBTyxFQUFFLE1BQU0sRUFBRSxFQUFFO1lBQ3JDLHdCQUF3QjtZQUN4QixJQUFJLENBQUMsYUFBYSxHQUFHLFFBQVEsQ0FBQyxhQUFhLENBQ3pDLHVCQUF1QixDQUNULENBQUM7WUFDakIsSUFBSSxDQUFDLFNBQVMsR0FBRyxRQUFRLENBQUMsYUFBYSxDQUFDLGdCQUFnQixDQUFnQixDQUFDO1lBQ3pFLE1BQU0sTUFBTSxHQUFHLFFBQVEsQ0FBQyxhQUFhLENBQ25DLGdCQUFnQixDQUNJLENBQUM7WUFDdkIsSUFBSSxDQUFDLE1BQU0sRUFBRTtnQkFDWCxPQUFPO2FBQ1I7WUFFRCxnQkFBZ0I7WUFDaEIsSUFBSSxJQUFJLENBQUMsYUFBYSxFQUFFO2dCQUN0QixJQUFJLENBQUMsYUFBYSxDQUFDLGdCQUFnQixDQUNqQyxPQUFPLEVBQ1AsSUFBSSxDQUFDLHVCQUF1QixDQUM3QixDQUFDO2dCQUNGLHdCQUF3QjtnQkFDeEIsSUFBSSxDQUFDLGFBQWEsQ0FBQyxnQkFBZ0IsQ0FDakMsYUFBYSxFQUNiLElBQUksQ0FBQyx3QkFBd0IsQ0FDOUIsQ0FBQzthQUNIO1lBQ0Qsd0JBQXdCO1lBQ3hCLElBQUksQ0FBQyx1QkFBdUIsR0FBRyxRQUFRLENBQUMsYUFBYSxDQUNuRCxTQUFTLENBQ0ssQ0FBQztZQUNqQixJQUFJLENBQUMsOEJBQThCLEdBQUcsUUFBUSxDQUFDLGFBQWEsQ0FDMUQsT0FBTyxDQUNPLENBQUM7WUFDakIsSUFBSSxJQUFJLENBQUMsdUJBQXVCLEVBQUU7Z0JBQ2hDLHFEQUFxRDtnQkFDckQsSUFBSSxDQUFDLHVCQUF1QixDQUFDLGdCQUFnQixDQUMzQyxPQUFPLEVBQ1AsSUFBSSxDQUFDLHlCQUF5QixDQUMvQixDQUFDO2FBQ0g7WUFFRCxXQUFXO1lBQ1gsT0FBTyxDQUFDLEdBQUcsQ0FBQyx3QkFBd0IsQ0FBQyxDQUFDO1lBQ3RDLE1BQU0sY0FBYyxHQUFHLE1BQU0sQ0FBQyxhQUFhLENBQUM7WUFDNUMsTUFBTSxDQUFDLGdCQUFnQixDQUNyQixNQUFNLEVBQ04sS0FBSztnQkFDSCxJQUFJO29CQUNGLElBQUksQ0FBQyxHQUFHLEdBQUcsTUFBTSxjQUFjLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FDNUMsY0FBYyxFQUNkLDJCQUEyQixFQUMzQixLQUFLLENBQ04sQ0FBQztpQkFDSDtnQkFBQyxPQUFPLENBQUMsRUFBRTtvQkFDVixPQUFPLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDO29CQUNqQixPQUFPO2lCQUNSO2dCQUVELGdEQUFnRDtnQkFDaEQsUUFBUSxNQUFNLEVBQUU7b0JBQ2QsS0FBSyxRQUFRLENBQUMsSUFBSTt3QkFDaEIsSUFBSSxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsZUFBZSxDQUM1QixhQUFhLEVBQ2IsSUFBSSxDQUFDLE1BQU0sQ0FBQyxTQUFTLENBQUMsV0FBVyxDQUNsQyxDQUFDO3dCQUNGLElBQUksQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLGVBQWUsQ0FDNUIsZ0JBQWdCLEVBQ2hCLElBQUksQ0FBQyxNQUFNLENBQUMsU0FBUyxDQUFDLGNBQWMsQ0FDckMsQ0FBQzt3QkFDRixJQUFJLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxlQUFlLENBQzVCLGNBQWMsRUFDZCxJQUFJLENBQUMsTUFBTSxDQUFDLFNBQVMsQ0FBQyxZQUFZLENBQ25DLENBQUM7d0JBQ0YsSUFBSSxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsZUFBZSxDQUM1QixXQUFXLEVBQ1gsSUFBSSxDQUFDLE1BQU0sQ0FBQyxTQUFTLENBQUMsU0FBUyxDQUNoQyxDQUFDO3dCQUNGLElBQUksQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLGVBQWUsQ0FDNUIsZUFBZSxFQUNmLElBQUksQ0FBQyxNQUFNLENBQUMsU0FBUyxDQUFDLGFBQWEsQ0FDcEMsQ0FBQzt3QkFFRixJQUFJLENBQUMsR0FBRyxDQUFDLFlBQVksQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDOzRCQUNuQyxPQUFPLEVBQUUsVUFDUCxLQUFVLEVBQ1YsSUFBcUIsRUFDckIsVUFBZTtnQ0FFZixlQUFlO2dDQUNmLHNDQUFzQztnQ0FDdEMsYUFBYTtnQ0FDYixZQUFZO2dDQUNaLEtBQUs7Z0NBQ0wsbUNBQW1DO2dDQUNuQyxJQUFJLENBQUMsV0FBVyxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUM7NEJBQ2pDLENBQUMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDOzRCQUNaLG1CQUFtQixFQUFFLFVBQVUsVUFBZTtnQ0FDNUMsK0RBQStEO2dDQUMvRCxJQUFJLENBQUMsNkJBQTZCLEVBQUUsQ0FBQzs0QkFDdkMsQ0FBQyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUM7eUJBQ2IsQ0FBQyxDQUFDO3dCQUNILElBQUksQ0FBQyxHQUFHLENBQUMsWUFBWSxDQUFDLElBQUksQ0FBQyxTQUFTLENBQ2xDLFVBQVUsb0JBQXFDOzRCQUM3QyxxQ0FBcUM7NEJBQ3JDLElBQUksQ0FBQyxlQUFlLEdBQUcsb0JBQW9CLENBQUMsTUFBTSxDQUFDOzRCQUNuRCxzRkFBc0Y7d0JBQ3hGLENBQUMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQ2IsQ0FBQzt3QkFDRixNQUFNO29CQUNSLEtBQUssUUFBUSxDQUFDLE1BQU07d0JBQ2xCLElBQUksQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLGVBQWUsQ0FDNUIsV0FBVyxFQUNYLElBQUksQ0FBQyxNQUFNLENBQUMsU0FBUyxDQUFDLFNBQVMsQ0FDaEMsQ0FBQzt3QkFDRixNQUFNO29CQUNSLEtBQUssUUFBUSxDQUFDLEtBQUs7d0JBQ2pCLElBQUksQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLGVBQWUsQ0FDNUIscUJBQXFCLEVBQ3JCLElBQUksQ0FBQyxNQUFNLENBQUMsU0FBUyxDQUFDLG1CQUFtQixDQUMxQyxDQUFDO3dCQUNGLElBQUksQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLGVBQWUsQ0FDNUIsdUJBQXVCLEVBQ3ZCLElBQUksQ0FBQyxNQUFNLENBQUMsU0FBUyxDQUFDLHFCQUFxQixDQUM1QyxDQUFDO3dCQUNGLElBQUksQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLGVBQWUsQ0FDNUIsa0JBQWtCLEVBQ2xCLElBQUksQ0FBQyxNQUFNLENBQUMsU0FBUyxDQUFDLGdCQUFnQixDQUN2QyxDQUFDO3dCQUNGLElBQUksQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLGVBQWUsQ0FDNUIsa0JBQWtCLEVBQ2xCLElBQUksQ0FBQyxNQUFNLENBQUMsU0FBUyxDQUFDLGdCQUFnQixDQUN2QyxDQUFDO3dCQUNGLE1BQU07b0JBQ1I7d0JBQ0UsTUFBTTtpQkFDVDtnQkFFRCxJQUFJLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxlQUFlLENBQzVCLGVBQWUsRUFDZixJQUFJLENBQUMsTUFBTSxDQUFDLFNBQVMsQ0FBQyxhQUFhLENBQ3BDLENBQUM7Z0JBRUYsa0hBQWtIO2dCQUNsSCxJQUFJLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsU0FBUyxDQUFDLENBQUMsV0FBVyxFQUFFLEVBQUU7b0JBQzlDLE9BQU8sQ0FBQyxHQUFHLENBQUMsc0JBQXNCLElBQUksQ0FBQyxTQUFTLENBQUMsV0FBVyxDQUFDLEVBQUUsQ0FBQyxDQUFDO2dCQUNuRSxDQUFDLENBQUMsQ0FBQztnQkFFSCx3QkFBd0I7Z0JBQ3hCLElBQUksQ0FBQyxHQUFHLENBQUMsT0FBTyxDQUFDLFlBQVksQ0FBQyxTQUFTLENBQ3JDLFVBQVUsWUFBaUI7b0JBQ3pCLElBQUksQ0FBQyxjQUFjLEdBQUcsWUFBWSxDQUFDO29CQUNuQyxJQUFJLENBQUMsY0FBYyxDQUFDLElBQUksR0FBRyxJQUFJLElBQUksRUFBRSxDQUFDLE9BQU8sRUFBRSxDQUFDO29CQUNoRCxJQUFJLENBQUMsSUFBSSxDQUFDLHlCQUF5QixFQUFFO3dCQUNuQyxJQUFJLENBQUMseUJBQXlCLEdBQUc7NEJBQy9CLENBQUMsRUFBRSxDQUFDOzRCQUNKLENBQUMsRUFBRSxDQUFDOzRCQUNKLENBQUMsRUFBRSxDQUFDO3lCQUNMLENBQUM7cUJBQ0g7b0JBRUQsSUFDRSxJQUFJLENBQUMsZUFBZSxLQUFLLGtCQUFrQixDQUFDLE9BQU87d0JBQ25ELElBQUksQ0FBQyxpQkFBaUIsRUFDdEI7d0JBQ0EsOERBQThEO3dCQUM5RCwyREFBMkQ7d0JBQzNELElBQUksQ0FBQyxvQkFBb0IsQ0FBQyxJQUFJLENBQUMsaUJBQWlCLENBQUMsQ0FBQztxQkFDbkQ7b0JBQ0QsSUFBSSxDQUFDLENBQUMsSUFBSSxDQUFDLHVCQUF1QixJQUFJLENBQUMsQ0FBQyxJQUFJLENBQUMsdUJBQXVCLENBQUMsS0FBSzt3QkFDMUUsQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDLE9BQU8sQ0FBQyw0QkFBNEIsQ0FBQyxLQUFLLENBQUMsQ0FBQyxJQUFJLFFBQVEsQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxXQUFXLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxFQUFFO3dCQUNqSCxJQUFJLENBQUMsdUJBQXVCLENBQUMsS0FBSyxDQUFDLE9BQU8sR0FBRyxNQUFNLENBQUM7d0JBQ3BELElBQUksQ0FBQyw2QkFBNkIsR0FBRyxLQUFLLENBQUM7cUJBQzVDO2dCQUNILENBQUMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQ2IsQ0FBQztnQkFFRixhQUFhO2dCQUNiLElBQUksQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxTQUFTLENBQUMsQ0FBQyxJQUFJLEVBQUUsRUFBRTtvQkFDdkMsSUFBSSxDQUFDLGlCQUFpQixHQUFHLEtBQUssQ0FBQztvQkFDL0IsUUFBUSxJQUFJLEVBQUU7d0JBQ1osS0FBSyxnQkFBZ0I7NEJBQ25CLElBQUksQ0FBQyxpQkFBaUIsR0FBRyxVQUFVLENBQUMsU0FBUyxDQUFDOzRCQUM5QyxNQUFNO3dCQUNSLEtBQUssZ0JBQWdCOzRCQUNuQixJQUFJLENBQUMsaUJBQWlCLEdBQUcsVUFBVSxDQUFDLFNBQVMsQ0FBQzs0QkFDOUMsTUFBTTt3QkFDUixLQUFLLGFBQWE7NEJBQ2hCLElBQUksQ0FBQyxpQkFBaUIsR0FBRyxVQUFVLENBQUMsTUFBTSxDQUFDOzRCQUMzQyxNQUFNO3dCQUNSLEtBQUssb0JBQW9COzRCQUN2QixJQUFJLENBQUMsaUJBQWlCLEdBQUcsVUFBVSxDQUFDLGFBQWEsQ0FBQzs0QkFDbEQsTUFBTTt3QkFDUjs0QkFDRSxJQUFJLENBQUMsaUJBQWlCLEdBQUcsVUFBVSxDQUFDLE9BQU8sQ0FBQztxQkFDL0M7b0JBQ0QsSUFBSSxDQUFDLG1CQUFtQixDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsaUJBQWlCLENBQUMsQ0FBQztnQkFDeEQsQ0FBQyxDQUFDLENBQUM7Z0JBRUgscUJBQXFCO2dCQUNyQixJQUFJLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUM1QixTQUFTLE1BQU0sQ0FBQyxJQUFTO29CQUN2QixJQUFJLENBQUMsVUFBVSxHQUFHLElBQUksQ0FBQztvQkFFdkIsSUFBSSxDQUFDLGlCQUFpQixDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztvQkFDbEMsc0RBQXNEO29CQUN0RCxvREFBb0Q7b0JBQ3BELDRDQUE0QztnQkFDOUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FDYixDQUFDO2dCQUVGLHNCQUFzQjtnQkFDdEIsSUFBSSxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQztvQkFDNUIsbUJBQW1CLEVBQUUsU0FBUyxNQUFNLENBQUMsVUFBYzt3QkFDakQsMkNBQTJDO3dCQUMzQyxJQUFJLENBQUMsTUFBTSxHQUFHLE1BQU0sQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLENBQUM7b0JBQ3hDLENBQUMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDO2lCQUNiLENBQUMsQ0FBQztnQkFFSCw2QkFBNkI7Z0JBQzdCLElBQUksQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxTQUFTLENBQzlCLFNBQVMsTUFBTSxDQUFDLFlBQTZCO29CQUMzQyw0Q0FBNEM7b0JBQzVDLElBQUksWUFBWSxDQUFDLEdBQUcsS0FBSyxFQUFFLEVBQUU7d0JBQzNCLDhEQUE4RDtxQkFDL0Q7eUJBQU07d0JBQ0wsbURBQW1EO3dCQUNuRCxJQUFJLENBQUMsWUFBWSxDQUFDLElBQUksQ0FBQyxZQUFZLENBQUMsR0FBRyxDQUFDLENBQUM7cUJBQzFDO2dCQUNILENBQUMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQ2IsQ0FBQztnQkFFRiwwQkFBMEI7Z0JBQzFCLElBQUksQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUM7b0JBQzVCLG1CQUFtQixFQUFFLFNBQVMsR0FBRyxDQUFZLFVBQWU7d0JBQzFELElBQUksQ0FBQyxNQUFNLEdBQUcsTUFBTSxDQUFDLE1BQU0sQ0FBQyxVQUFVLENBQUMsQ0FBQztvQkFDMUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUM7aUJBQ2IsQ0FBQyxDQUFDO2dCQUVILGlDQUFpQztnQkFDakMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsV0FBVyxFQUFFLENBQUMsR0FBVyxFQUFFLEVBQUU7b0JBQ3ZDLHlCQUF5QjtvQkFDekIsSUFBSTt3QkFDRixNQUFNLGFBQWEsR0FBRyxJQUFJLENBQUMsZUFBZSxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQzt3QkFDcEQsSUFBSSxDQUFDLGFBQWEsRUFBQzs0QkFDakIsT0FBTyxDQUFDLEdBQUcsQ0FBQyw2QkFBNkIsQ0FBQyxDQUFDOzRCQUMzQyxPQUFPO3lCQUNSO3dCQUNELE1BQU0sR0FBRyxHQUFHLFVBQVUsQ0FBQyxtQkFBbUIsQ0FDeEMsYUFBYSxDQUFDLFNBQVMsRUFBRSxFQUN6QixhQUFhLENBQUMsT0FBTyxFQUFFLENBQ3hCLENBQUM7d0JBQ0YsSUFBSSxHQUFHLEtBQUssRUFBRSxFQUFFOzRCQUNkLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxhQUFhLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDOzRCQUNoRCxJQUFJLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxHQUFHLEVBQUU7Z0NBQ25CLElBQUksQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQzs0QkFDOUIsQ0FBQyxDQUFDLENBQUM7eUJBQ0o7cUJBQ0Y7b0JBQUMsTUFBTTt3QkFDTixPQUFPLENBQUMsR0FBRyxDQUFDLDZCQUE2QixDQUFDLENBQUM7cUJBQzVDO2dCQUNILENBQUMsQ0FBQyxDQUFDO2dCQUVILGdCQUFnQjtnQkFDaEIseURBQXlEO2dCQUN6RCxpR0FBaUc7Z0JBQ2pHLElBQUksQ0FBQyxZQUFZLEdBQUcsV0FBVyxDQUM3QixJQUFJLENBQUMsa0JBQWtCLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxFQUNsQyxFQUFFLENBQ0gsQ0FBQztnQkFFRjs7bUJBRUc7Z0JBQ0gsSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQ1Qsc0JBQXNCLEVBQ3RCLFVBQVUsRUFBRSxFQUFFLElBQUk7b0JBQ2hCLDhEQUE4RDtvQkFDOUQsSUFBSSxDQUFDLGdCQUFnQixHQUFHLElBQUksQ0FBQztnQkFDL0IsQ0FBQyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FDYixDQUFDO2dCQUVGLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUNULG9CQUFvQixFQUNwQixVQUFVLE9BQU8sRUFBRSxPQUFPO29CQUN4QixtRUFBbUU7b0JBQ25FLElBQUksT0FBTyxLQUFLLG9CQUFvQixFQUFFO3dCQUNwQyxJQUFJLENBQUMsZ0JBQWdCLEdBQUcsS0FBSyxDQUFDO3FCQUMvQjtnQkFDSCxDQUFDLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUNiLENBQUM7Z0JBRUYsSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQ1QsSUFBSSxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLEtBQUssRUFDMUIsVUFBVSxRQUFRLEVBQUUsUUFBUTtvQkFDMUIsNENBQTRDO29CQUM1Qyw2Q0FBNkM7b0JBQzdDLElBQUksQ0FBQyxpQkFBaUIsR0FBRyxLQUFLLENBQUM7b0JBQy9CLElBQUksQ0FBQyxvQkFBb0IsRUFBRSxDQUFDO2dCQUM5QixDQUFDLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUNiLENBQUM7Z0JBQ0YsSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQ1QsSUFBSSxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLElBQUksRUFDekIsVUFBVSxTQUFTLEVBQUUsT0FBTztvQkFDMUIsK0NBQStDO29CQUMvQyxzREFBc0Q7b0JBQ3RELElBQUksQ0FBQyxpQkFBaUIsR0FBRyxJQUFJLENBQUM7Z0JBQ2hDLENBQUMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQ2IsQ0FBQztnQkFFRix1Q0FBdUM7Z0JBQ3ZDLE1BQU0sQ0FBQyxXQUFXLENBQUMsR0FBRyxNQUFNLElBQUksQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLGFBQWEsQ0FBQyxDQUFDLENBQUMsQ0FBQztnQkFDNUQsTUFBTSxJQUFJLEdBQUcsV0FBVyxDQUFDLE9BQU8sRUFBRSxDQUFDO2dCQUNuQyxJQUFJLENBQUMsS0FBSyxFQUFFLENBQUM7Z0JBQ2IsSUFBSSxDQUFDLFlBQVksR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQztnQkFFdEMsa0VBQWtFO2dCQUNsRSw2Q0FBNkM7Z0JBQzdDLGtEQUFrRDtnQkFDbEQsdUNBQXVDO2dCQUN2QyxzQ0FBc0M7Z0JBQ3RDLHNEQUFzRDtnQkFDdEQsTUFBTTtnQkFHTiw4REFBOEQ7Z0JBQzlELDhDQUE4QztnQkFDOUMsZ0NBQWdDO2dCQUNoQyx3REFBd0Q7Z0JBQ3hELEVBQUU7Z0JBQ0YsNkJBQTZCO2dCQUM3QixvREFBb0Q7Z0JBQ3BELEVBQUU7Z0JBQ0YseUJBQXlCO2dCQUN6QixZQUFZO2dCQUNaLHFDQUFxQztnQkFDckMsNEVBQTRFO2dCQUM1RSx5Q0FBeUM7Z0JBQ3pDLCtCQUErQjtnQkFDL0Isd0JBQXdCO2dCQUN4Qiw0Q0FBNEM7Z0JBQzVDLGVBQWU7Z0JBQ2YsYUFBYTtnQkFDYixZQUFZO2dCQUNaLG9CQUFvQjtnQkFDcEIsc0RBQXNEO2dCQUN0RCwwQkFBMEI7Z0JBQzFCLFFBQVE7Z0JBQ1IscUJBQXFCO2dCQUNyQixnQkFBZ0I7Z0JBQ2hCLFFBQVE7Z0JBQ1IsRUFBRTtnQkFDRix5QkFBeUI7Z0JBQ3pCLFlBQVk7Z0JBQ1osd0ZBQXdGO2dCQUN4RixvQkFBb0I7Z0JBQ3BCLHNEQUFzRDtnQkFDdEQsMEJBQTBCO2dCQUMxQixRQUFRO2dCQUNSLHFCQUFxQjtnQkFDckIsZ0JBQWdCO2dCQUNoQixRQUFRO2dCQUNSLEVBQUU7Z0JBQ0YsbUNBQW1DO2dCQUNuQyxrQ0FBa0M7Z0JBQ2xDLHFDQUFxQztnQkFDckMsb0NBQW9DO2dCQUNwQyx3Q0FBd0M7Z0JBQ3hDLGlDQUFpQztnQkFDakMsNkJBQTZCO2dCQUM3QixnREFBZ0Q7Z0JBQ2hELHVDQUF1QztnQkFDdkMsK0RBQStEO2dCQUMvRCwrQkFBK0I7Z0JBQy9CLG1CQUFtQjtnQkFDbkIsK0JBQStCO2dCQUMvQiw4REFBOEQ7Z0JBQzlELFlBQVk7Z0JBQ1osRUFBRTtnQkFDRix3REFBd0Q7Z0JBQ3hELGFBQWE7Z0JBQ2Isb0NBQW9DO2dCQUNwQyxvREFBb0Q7Z0JBQ3BELG1DQUFtQztnQkFDbkMsc0JBQXNCO2dCQUN0QixFQUFFO2dCQUNGLHlFQUF5RTtnQkFDekUsZ0RBQWdEO2dCQUNoRCw0REFBNEQ7Z0JBQzVELGlEQUFpRDtnQkFDakQsK0JBQStCO2dCQUMvQixzQkFBc0I7Z0JBQ3RCLGFBQWE7Z0JBQ2IsVUFBVTtnQkFDVixVQUFVO2dCQUNWLGdDQUFnQztnQkFDaEMsa0JBQWtCO2dCQUNsQixpREFBaUQ7Z0JBQ2pELDZIQUE2SDtnQkFDN0gsTUFBTTtnQkFDTixNQUFNO2dCQUVOLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQztZQUNoQixDQUFDLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUNiLENBQUM7UUFDSixDQUFDLENBQUMsQ0FBQztJQUNMLENBQUM7SUFHRCxjQUFjO1FBQ1osSUFBSSxDQUFDLGlCQUFpQixHQUFHLElBQUksQ0FBQztJQUNoQyxDQUFDO0lBRUQsYUFBYSxDQUFDLEtBQTBDO1FBQ3RELElBQUksQ0FBQyxHQUFHLEtBQUssQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQzNCLElBQUksQ0FBQyxHQUFHLEtBQUssQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQzNCLElBQUksQ0FBQyxHQUFHLEtBQUssQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBRTNCLE9BQU8sUUFBUSxDQUFDLFFBQVEsQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDO0lBQ3pDLENBQUM7SUFFRCxFQUFFO0lBQ0YsNkNBQTZDO0lBQzdDLEVBQUU7SUFDRjs7T0FFRztJQUNILDZCQUE2QjtRQUMzQixJQUFJLElBQUksQ0FBQyxXQUFXLENBQUMsTUFBTSxHQUFHLENBQUMsRUFBRTtZQUMvQixNQUFNLFlBQVksR0FBRyxJQUFJLENBQUMsV0FBVyxDQUFDLE1BQU0sQ0FBQztZQUM3QyxJQUFJLENBQUMsb0JBQW9CLEdBQUcsRUFBRSxDQUFDO1lBQy9CLEtBQUssSUFBSSxLQUFLLEdBQUcsQ0FBQyxFQUFFLEtBQUssR0FBRyxZQUFZLEVBQUUsS0FBSyxJQUFJLENBQUMsRUFBRTtnQkFDcEQsTUFBTSxRQUFRLEdBQUcsMkJBQTJCLENBQzFDLElBQUksQ0FBQyxXQUFXLENBQUMsS0FBSyxHQUFHLENBQUMsQ0FBQyxFQUMzQixJQUFJLENBQUMsV0FBVyxDQUFDLEtBQUssQ0FBQyxDQUN4QixDQUFDO2dCQUNGLElBQUksQ0FBQyxvQkFBb0IsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUM7YUFDMUM7WUFDRCxJQUFJLENBQUMsY0FBYyxFQUFFLENBQUMsSUFBSSxDQUFDLENBQUMsR0FBRyxFQUFFLEVBQUU7Z0JBQ2pDLElBQUksQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDLENBQUMsU0FBUyxJQUFJLENBQUMsY0FBYyxrQkFBa0IsQ0FBQyxDQUFDLENBQUM7WUFDekUsQ0FBQyxDQUFDLENBQUM7U0FDSjtJQUNILENBQUM7SUFFRCxnQkFBZ0I7UUFDZCxPQUFPLElBQUksQ0FBQyxvQkFBb0IsQ0FBQztJQUNuQyxDQUFDO0lBRUQ7OztPQUdHO0lBQ0gsY0FBYztRQUNaLE9BQU8sSUFBSSxDQUFDLEdBQUcsQ0FBQyxRQUFRLENBQUMsY0FBYyxDQUNyQyxJQUFJLENBQUMsVUFBVSxFQUNmLElBQUksQ0FBQyxVQUFVLENBQ2hCLENBQUMsSUFBSSxDQUNKLFVBQVUsYUFBa0I7WUFDMUIsZ0JBQWdCO1lBQ2hCLElBQUksQ0FBQyxpQkFBaUIsR0FBRyxhQUFhLENBQUM7WUFDdkMsT0FBTyxPQUFPLENBQUMsT0FBTyxFQUFFLENBQUM7UUFDM0IsQ0FBQyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FDYixDQUFDO0lBQ0osQ0FBQztJQUVELGdCQUFnQjtRQUNkLE9BQU8sSUFBSSxDQUFDLGlCQUFpQixDQUFDO0lBQ2hDLENBQUM7SUFFRCxrQkFBa0I7UUFDaEIsTUFBTSxJQUFJLEdBQUc7WUFDWCxPQUFPLEVBQUUsSUFBSSxDQUFDLFdBQVc7WUFDekIsS0FBSyxFQUFFLElBQUksQ0FBQyxVQUFVLENBQUMsS0FBSztTQUM3QixDQUFDO1FBQ0YsT0FBTyxJQUFJLENBQUM7SUFDZCxDQUFDO0lBRUQsRUFBRTtJQUNGLDhCQUE4QjtJQUM5QixFQUFFO0lBQ0Y7O09BRUc7SUFDSCxrQkFBa0I7UUFDaEIsSUFDRSxJQUFJLENBQUMsZUFBZSxLQUFLLGtCQUFrQixDQUFDLE9BQU87WUFDbkQsSUFBSSxDQUFDLGlCQUFpQjtZQUN0QixJQUFJLENBQUMsY0FBYztZQUNuQixJQUFJLENBQUMsZUFBZSxDQUNsQixJQUFJLENBQUMsY0FBYyxDQUFDLFFBQVEsRUFDNUIsSUFBSSxDQUFDLHlCQUF5QixDQUMvQixHQUFHLEVBQUUsRUFDTjtZQUNBLElBQUksQ0FBQyxhQUFhLENBQUMsS0FBSyxDQUFDLE9BQU8sR0FBRyxNQUFNLENBQUM7WUFFMUMsTUFBTSxJQUFJLEdBQUc7Z0JBQ1gsQ0FBQyxFQUFFLElBQUksQ0FBQyxTQUFTLENBQUMsV0FBVztnQkFDN0IsQ0FBQyxFQUFFLElBQUksQ0FBQyxTQUFTLENBQUMsWUFBWTthQUMvQixDQUFDO1lBQ0YsTUFBTSxNQUFNLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxVQUFVLENBQUMsYUFBYSxDQUM5QyxJQUFJLENBQUMsY0FBYyxDQUFDLFFBQVEsRUFDNUIsSUFBSSxDQUFDLFVBQVUsRUFDZixJQUFJLENBQ0wsQ0FBQztZQUNGLElBQUksQ0FBQyxhQUFhLENBQUMsS0FBSyxDQUFDLElBQUksR0FBRyxHQUM5QixNQUFNLENBQUMsQ0FBQyxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxHQUFHLEVBQ25DLElBQUksQ0FBQztZQUNMLElBQUksQ0FBQyxhQUFhLENBQUMsS0FBSyxDQUFDLEdBQUcsR0FBRyxHQUFHLE1BQU0sQ0FBQyxDQUFDLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLEdBQUcsRUFBRSxJQUFJLENBQUM7WUFDMUUsSUFBSSxDQUFDLHlCQUF5QixHQUFHO2dCQUMvQixHQUFHLElBQUksQ0FBQyxjQUFjLENBQUMsUUFBUTthQUNoQyxDQUFDO1NBQ0g7YUFBTTtZQUNMLElBQUksQ0FBQyxhQUFhLENBQUMsS0FBSyxDQUFDLE9BQU8sR0FBRyxPQUFPLENBQUM7U0FDNUM7SUFDSCxDQUFDO0lBRUQ7OztPQUdHO0lBQ0gsb0JBQW9CLENBQUMsU0FBaUI7UUFDcEMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsWUFBWSxDQUFDLFNBQVMsRUFBRTtZQUNuQyxjQUFjLEVBQUU7Z0JBQ2QsQ0FBQyxFQUFFLElBQUksQ0FBQyxjQUFjLENBQUMsUUFBUSxDQUFDLENBQUMsR0FBRyxDQUFDO2dCQUNyQyxDQUFDLEVBQUUsSUFBSSxDQUFDLGNBQWMsQ0FBQyxRQUFRLENBQUMsQ0FBQyxHQUFHLENBQUM7Z0JBQ3JDLENBQUMsRUFBRSxJQUFJLENBQUMsY0FBYyxDQUFDLFFBQVEsQ0FBQyxDQUFDLEdBQUcsQ0FBQzthQUN0QztZQUNELFVBQVUsRUFBRTtnQkFDVixDQUFDLEVBQUUsSUFBSSxDQUFDLGNBQWMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxHQUFHLEdBQUc7Z0JBQ3JDLENBQUMsRUFBRSxJQUFJLENBQUMsY0FBYyxDQUFDLE1BQU0sQ0FBQyxDQUFDLEdBQUcsR0FBRztnQkFDckMsQ0FBQyxFQUFFLElBQUksQ0FBQyxjQUFjLENBQUMsTUFBTSxDQUFDLENBQUMsR0FBRyxHQUFHO2FBQ3RDO1NBQ0YsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztJQUVEOzs7OztPQUtHO0lBQ0gsZUFBZSxDQUFDLElBQVMsRUFBRSxJQUFTO1FBQ2xDLE1BQU0sSUFBSSxHQUFHO1lBQ1gsQ0FBQyxFQUFFLElBQUksQ0FBQyxTQUFTLENBQUMsV0FBVztZQUM3QixDQUFDLEVBQUUsSUFBSSxDQUFDLFNBQVMsQ0FBQyxZQUFZO1NBQy9CLENBQUM7UUFDRixNQUFNLE9BQU8sR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLFVBQVUsQ0FBQyxhQUFhLENBQy9DLElBQUksRUFDSixJQUFJLENBQUMsVUFBVSxFQUNmLElBQUksQ0FDTCxDQUFDO1FBQ0YsTUFBTSxPQUFPLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxVQUFVLENBQUMsYUFBYSxDQUMvQyxJQUFJLEVBQ0osSUFBSSxDQUFDLFVBQVUsRUFDZixJQUFJLENBQ0wsQ0FBQztRQUNGLE9BQU8sSUFBSSxDQUFDLElBQUksQ0FDZCxDQUFDLE9BQU8sQ0FBQyxDQUFDLEdBQUcsT0FBTyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLE9BQU8sQ0FBQyxDQUFDLEdBQUcsT0FBTyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FDNUQsQ0FBQztJQUNKLENBQUM7SUFFRCxFQUFFO0lBQ0YsMENBQTBDO0lBQzFDLEVBQUU7SUFDRjs7O09BR0c7SUFDSCxLQUFLLENBQUMsa0JBQWtCLENBQUMsYUFBNEI7UUFDbkQsSUFBSSxDQUFDLElBQUksQ0FBQyxjQUFjO1lBQUUsT0FBTztRQUNqQyxJQUFJLENBQUMsaUJBQWlCLEdBQUcsTUFBTSxJQUFJLENBQUMsb0JBQW9CLENBQUMsYUFBYSxDQUFDLENBQUM7UUFDeEUsT0FBTyxDQUFDLEdBQUcsQ0FBQyxtQkFBbUIsRUFBRSxJQUFJLENBQUMsaUJBQWlCLENBQUMsQ0FBQztRQUN6RCxJQUFJLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLGlCQUFpQixFQUFFLGVBQWUsQ0FBQyxDQUFDO1FBQy9ELElBQUksQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLFdBQVcsQ0FBQyxJQUFJLENBQUMsaUJBQWlCLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDdEQsQ0FBQztJQUVEOzs7OztPQUtHO0lBQ0gsS0FBSyxDQUFDLG9CQUFvQixDQUN4QixhQUE0QjtRQUU1QixJQUFJLE9BQU8sQ0FBQztRQUNaLElBQUksQ0FBQyxJQUFJLENBQUMsR0FBRyxFQUFFO1lBQ2IsT0FBTyxJQUFJLENBQUM7U0FDYjtRQUNELElBQUk7WUFDRixPQUFPLEdBQUcsTUFBTSxJQUFJLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsYUFBYSxDQUFDLE9BQU8sRUFBRSxDQUFDLENBQUM7U0FDM0Q7UUFBQyxPQUFPLEtBQUssRUFBRTtZQUNkLE9BQU8sQ0FBQyxHQUFHLENBQ1Qsa0NBQWtDLEVBQ2xDLEtBQUssRUFDTCxhQUFhLENBQUMsT0FBTyxFQUFFLENBQ3hCLENBQUM7U0FDSDtRQUNELElBQUksT0FBTyxFQUFFO1lBQ1gsTUFBTSxXQUFXLEdBQUcsT0FBTyxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQy9CLGtFQUFrRTtZQUNsRSxJQUFJLENBQUMsWUFBWSxDQUFDLElBQUksQ0FBQyxXQUFXLENBQUMsQ0FBQztZQUNwQyxJQUFJLENBQUMsZUFBZSxDQUFDLEdBQUcsQ0FBQyxXQUFXLEVBQUUsYUFBYSxDQUFDLENBQUM7WUFDckQsT0FBTyxXQUFXLENBQUM7U0FDcEI7UUFDRCxPQUFPLElBQUksQ0FBQztJQUNkLENBQUM7SUFFRDs7T0FFRztJQUNILG9CQUFvQjtRQUNsQixJQUFJLENBQUMsa0JBQWtCLENBQUMsa0JBQWtCLENBQUMsT0FBTyxDQUFDLENBQUM7UUFDcEQsTUFBTSxPQUFPLEdBQUcsSUFBSSxDQUFDLFVBQVUsRUFBRSxDQUFDO1FBQ2xDLElBQUksT0FBTyxFQUFFO1lBQ1gsTUFBTSxZQUFZLEdBQUcsSUFBSSxDQUFDLGVBQWU7aUJBQ3RDLEdBQUcsQ0FBQyxPQUFPLENBQUM7aUJBQ1oscUJBQXFCLEVBQUUsQ0FBQztZQUMzQixJQUFJLENBQUMsZ0NBQWdDLENBQUMsWUFBWSxDQUFDLENBQUM7U0FDckQ7SUFDSCxDQUFDO0lBRUQ7Ozs7T0FJRztJQUNILEtBQUssQ0FBQyxzQkFBc0IsQ0FBQyxXQUFtQixFQUFFLFFBQWdCO1FBQ2hFLE1BQU0sSUFBSSxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsZUFBZSxDQUFDLFFBQVEsV0FBVyxFQUFFLEVBQUUsUUFBUSxDQUFDLENBQUM7UUFDdEUsSUFBSSxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsUUFBUSxDQUFDLFdBQVcsRUFBRSxRQUFRLFdBQVcsRUFBRSxDQUFDLENBQUM7SUFDNUQsQ0FBQztJQUVEOzs7O09BSUc7SUFDSCxLQUFLLENBQUMsc0JBQXNCLENBQUMsV0FBbUIsRUFBRSxRQUFnQjtRQUNoRSxJQUFJO1lBQ0YsSUFBSSxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsUUFBUSxDQUFDLFdBQVcsRUFBRSxRQUFRLENBQUMsQ0FBQztTQUM5QztRQUFDLE9BQU8sQ0FBQyxFQUFFO1lBQ1YsT0FBTyxDQUFDLEdBQUcsQ0FDVCxnQ0FBZ0MsRUFDaEMsUUFBUSxFQUNSLHFCQUFxQixDQUN0QixDQUFDO1NBQ0g7SUFDSCxDQUFDO0lBRUQ7Ozs7O09BS0c7SUFDSCxLQUFLLENBQUMsb0JBQW9CLENBQ3hCLFdBQW1CLEVBQ25CLGFBQTRCO1FBRTVCLElBQUksSUFBSSxDQUFDLFFBQVEsS0FBSyxRQUFRLENBQUMsS0FBSyxFQUFFO1lBQ3BDLE1BQU0sSUFBSSxHQUFHLGFBQWEsQ0FBQyxTQUFTLEVBQUUsQ0FBQztZQUN2QyxJQUFJLFFBQVEsR0FBRyxXQUFXLENBQUM7WUFDM0IsSUFBSSxJQUFJLENBQUMsU0FBUyxFQUFFO2dCQUNsQixRQUFRLEdBQUcsR0FBRyxRQUFRLFlBQVksQ0FBQzthQUNwQztpQkFBTTtnQkFDTCxRQUFRLEdBQUcsR0FBRyxRQUFRLGNBQWMsQ0FBQzthQUN0QztZQUNELElBQUksQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLFFBQVEsQ0FBQyxXQUFXLEVBQUUsUUFBUSxDQUFDLENBQUM7WUFDN0MsT0FBTztTQUNSO1FBQ0QsTUFBTSxhQUFhLEdBQUcsZUFBZSxDQUFDLGFBQWEsQ0FBQyxPQUFPLEVBQUUsQ0FBQyxDQUFDO1FBQy9ELElBQUksT0FBTyxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUMsU0FBUyxDQUFDLG1CQUFtQixDQUFDO1FBQ3hELElBQUksUUFBUSxHQUFHLFFBQVEsYUFBYSxFQUFFLENBQUM7UUFDdkMsTUFBTSxHQUFHLEdBQUcsYUFBYSxDQUFDLE1BQU0sRUFBRSxDQUFDO1FBQ25DLElBQUksR0FBRyxJQUFJLEdBQUcsQ0FBQyxPQUFPLEVBQUU7WUFDdEIsTUFBTSxPQUFPLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsT0FBTyxDQUFDLENBQUM7WUFDeEMsSUFBSSxhQUFhLENBQUMsT0FBTyxFQUFFLEtBQUssT0FBTyxDQUFDLElBQUksRUFBRTtnQkFDNUMsTUFBTSxPQUFPLEdBQUcsYUFBYSxDQUFDLFNBQVMsRUFBRSxDQUFDO2dCQUMxQyxJQUFJLE9BQU8sQ0FBQyxJQUFJLEtBQUssV0FBVyxDQUFDLGNBQWMsRUFBRTtvQkFDL0MsT0FBTyxDQUFDLEdBQUcsR0FBRyxJQUFJLENBQUMsVUFBVSxDQUFDLHlCQUF5QixDQUFDLE9BQU8sRUFBRSxHQUFHLENBQUMsQ0FBQztpQkFDdkU7YUFDRjtZQUNELElBQUksT0FBTyxDQUFDLEdBQUcsRUFBRTtnQkFDZixNQUFNLFVBQVUsR0FBRyxNQUFNLElBQUksQ0FBQyxVQUFVLENBQUMsc0JBQXNCLENBQzdELE9BQU8sQ0FBQyxHQUFHLENBQ1osQ0FBQztnQkFDRixJQUFJLFVBQVUsRUFBRTtvQkFDZCxJQUFJO3dCQUNGLFFBQVEsR0FBRyxRQUFRLGFBQWEsSUFBSSxXQUFXLElBQUksYUFBYSxDQUFDLGVBQWUsRUFBRSxDQUFDO3dCQUNuRixNQUFNLElBQUksQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLGVBQWUsQ0FBQyxRQUFRLEVBQUUsVUFBVSxDQUFDLENBQUM7d0JBQzNELGFBQWEsQ0FBQyxlQUFlLElBQUksQ0FBQyxDQUFDO3FCQUNwQztvQkFBQyxNQUFNO3dCQUNOLE9BQU8sQ0FBQyxHQUFHLENBQUMsb0JBQW9CLENBQUMsQ0FBQztxQkFDbkM7aUJBQ0Y7YUFDRjtZQUNELElBQUksT0FBTyxDQUFDLE9BQU8sRUFBRTtnQkFDbkIsT0FBTyxHQUFHLE9BQU8sQ0FBQyxPQUFPLENBQUM7YUFDM0I7U0FDRjtRQUNELElBQUk7WUFDRixJQUFJLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxRQUFRLENBQUMsV0FBVyxFQUFFLFFBQVEsQ0FBQyxDQUFDO1lBQzdDLElBQUksQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLFdBQVcsQ0FBQyxXQUFXLEVBQUUsT0FBTyxDQUFDLENBQUM7U0FDaEQ7UUFBQyxPQUFPLEtBQUssRUFBRTtZQUNkLE9BQU8sQ0FBQyxHQUFHLENBQUMsMkJBQTJCLEVBQUUsS0FBSyxDQUFDLENBQUM7U0FDakQ7SUFDSCxDQUFDO0lBRUQ7O09BRUc7SUFDSCxXQUFXO1FBQ1QsVUFBVSxDQUFDLEdBQUcsRUFBRTtZQUNkLE1BQU0sT0FBTyxHQUFHLElBQUksQ0FBQyxVQUFVLEVBQUUsQ0FBQztZQUNsQyxJQUFJLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBQ3hCLENBQUMsRUFBRSxJQUFJLENBQUMsQ0FBQztJQUNYLENBQUM7SUFFRDs7OztPQUlHO0lBQ0gsS0FBSyxDQUFDLE9BQU8sQ0FBQyxXQUFtQjtRQUMvQixJQUFJLFdBQVcsS0FBSyxFQUFFO1lBQUUsT0FBTztRQUMvQixJQUFJO1lBQ0YsSUFBSSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLENBQUM7WUFDakMsTUFBTSxJQUFJLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsU0FBUyxDQUNwQyxDQUFDLFlBQVksRUFBRSxFQUFFLENBQUMsWUFBWSxLQUFLLEVBQUUsQ0FDdEMsQ0FBQztZQUNGLE1BQU0sSUFBSSxDQUFDLEdBQUcsQ0FBQyxTQUFTLENBQUMsYUFBYSxDQUNwQyxXQUFXLEVBQ1gsSUFBSSxDQUFDLEdBQUcsQ0FBQyxTQUFTLENBQUMsVUFBVSxDQUFDLEdBQUcsQ0FDbEMsQ0FBQztTQUNIO1FBQUMsT0FBTyxLQUFLLEVBQUU7WUFDZCxPQUFPLENBQUMsR0FBRyxDQUFDLHdCQUF3QixFQUFFLEtBQUssQ0FBQyxDQUFDO1NBQzlDO0lBQ0gsQ0FBQztJQUVEOzs7OztPQUtHO0lBQ0gsS0FBSyxDQUFDLDhCQUE4QixDQUNsQyxXQUFtQixFQUNuQixTQUF1QixJQUFJLEVBQzNCLFVBQW1CLElBQUk7UUFFdkIsSUFBSSxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsYUFBYSxDQUN4QixXQUFXLEVBQ1gsSUFBSSxDQUFDLGVBQWUsQ0FBQyxHQUFHLENBQUMsV0FBVyxDQUFDLENBQUMsT0FBTyxFQUFFLENBQ2hELENBQUM7UUFDRixJQUFJLE1BQU0sSUFBSSxPQUFPLEVBQUU7WUFDckIsTUFBTSxJQUFJLENBQUMsZUFBZSxDQUFDLE9BQU8sRUFBRSxNQUFNLEVBQUUsV0FBVyxDQUFDLENBQUM7U0FDMUQ7UUFDRCxNQUFNLElBQUksQ0FBQyxvQkFBb0IsQ0FDN0IsV0FBVyxFQUNYLElBQUksQ0FBQyxlQUFlLENBQUMsR0FBRyxDQUFDLFdBQVcsQ0FBQyxDQUN0QyxDQUFDO0lBQ0osQ0FBQztJQUVEOzs7OztPQUtHO0lBQ0gsS0FBSyxDQUFDLDBCQUEwQixDQUM5QixXQUFtQixFQUNuQixNQUFXLEVBQ1gsT0FBZ0I7UUFFaEIsTUFBTSxJQUFJLENBQUMsZUFBZSxDQUFDLE9BQU8sRUFBRSxNQUFNLEVBQUUsV0FBVyxDQUFDLENBQUM7SUFDM0QsQ0FBQztJQUVEOzs7T0FHRztJQUNILHFCQUFxQixDQUFDLFdBQW1CO1FBQ3ZDLElBQUksQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxXQUFXLENBQUMsQ0FBQztRQUNqQyxJQUFJLENBQUMsZUFBZSxDQUFDLE1BQU0sQ0FBQyxXQUFXLENBQUMsQ0FBQztJQUMzQyxDQUFDO0lBRUQ7O09BRUc7SUFDSCxtQkFBbUI7UUFDakIsTUFBTSxXQUFXLEdBQUcsSUFBSSxDQUFDLFlBQVksQ0FBQyxHQUFHLEVBQUUsQ0FBQztRQUM1QyxJQUFJLFdBQVcsRUFBRTtZQUNmLElBQUksQ0FBQyxxQkFBcUIsQ0FBQyxXQUFXLENBQUMsQ0FBQztTQUN6QztJQUNILENBQUM7SUFFRDs7Ozs7OztPQU9HO0lBQ0gsS0FBSyxDQUFDLHNCQUFzQixDQUMxQixPQUFnQixFQUNoQixNQUFvQixFQUNwQixHQUFRO1FBRVIsOEJBQThCO1FBQzlCLE1BQU0sRUFBQyxHQUFHLEVBQUUsS0FBSyxFQUFDLEdBQUcsSUFBSSxDQUFDLG1CQUFtQixDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUMsQ0FBQztRQUN6RCxJQUFJLEdBQUcsRUFBRTtZQUNQLG9DQUFvQztZQUNwQyxPQUFPO1NBQ1I7UUFDRCxNQUFNLGFBQWEsR0FBa0IsSUFBSSxhQUFhLENBQUMsT0FBTyxDQUFDLENBQUM7UUFDaEUsYUFBYSxDQUFDLFNBQVMsQ0FBQyxNQUFNLEVBQUUsT0FBTyxDQUFDLENBQUM7UUFDekMsSUFBSSxHQUFHLENBQUMsVUFBVSxFQUFFO1lBQ2xCLGFBQWEsQ0FBQyxXQUFXLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQztTQUN2RDtRQUNELElBQUksR0FBRyxDQUFDLFFBQVEsRUFBRTtZQUNoQixNQUFNLFdBQVcsR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxRQUFRLENBQUMsQ0FBQztZQUM3QyxJQUFJLFdBQVcsQ0FBQyxNQUFNLEVBQUU7Z0JBQ3RCLGFBQWEsQ0FBQyxTQUFTLENBQUMsV0FBVyxDQUFDLE1BQU0sQ0FBQyxDQUFDO2FBQzdDO2lCQUFNO2dCQUNMLGFBQWEsQ0FBQyxTQUFTLENBQUMsRUFBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLElBQUksRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFDLENBQUMsQ0FBQzthQUNqRDtTQUNGO1FBQ0QsSUFBSSxHQUFHLENBQUMsaUJBQWlCLEVBQUU7WUFDekIsYUFBYSxDQUFDLFVBQVUsQ0FBQyxHQUFHLENBQUMsaUJBQWlCLENBQUMsQ0FBQztTQUNqRDtRQUNELGFBQWEsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUM7UUFFMUIsTUFBTSxZQUFZLEdBQUcsTUFBTSxJQUFJLENBQUMsb0JBQW9CLENBQUMsYUFBYSxDQUFDLENBQUM7UUFDcEUsSUFBSSxZQUFZLElBQUksSUFBSSxDQUFDLEdBQUcsRUFBRTtZQUM1QixNQUFNLElBQUksQ0FBQyxvQkFBb0IsQ0FBQyxZQUFZLEVBQUUsYUFBYSxDQUFDLENBQUM7WUFDN0QsTUFBTSxJQUFJLENBQUMsZUFBZSxDQUFDLE9BQU8sRUFBRSxNQUFNLEVBQUUsWUFBWSxDQUFDLENBQUM7U0FDM0Q7SUFDSCxDQUFDO0lBRUQ7Ozs7O09BS0c7SUFDSCxLQUFLLENBQUMsZUFBZSxDQUFDLE9BQWdCLEVBQUUsTUFBb0IsRUFBRSxLQUFhO1FBQ3pFLElBQUksSUFBSSxHQUFHLE1BQU0sSUFBSSxDQUFDLFVBQVUsQ0FBQyxlQUFlLENBQUMsT0FBTyxFQUFFLE1BQU0sQ0FBQyxDQUFDO1FBQ2xFLElBQUksSUFBSSxLQUFLLEVBQUUsSUFBSSxJQUFJLENBQUMsR0FBRyxFQUFFO1lBQzNCLE1BQU0sU0FBUyxHQUFHLElBQUksQ0FBQyxVQUFVLENBQUMsZUFBZSxDQUFDLE1BQU0sRUFBRSxPQUFPLENBQUMsQ0FBQztZQUNuRSxJQUFJLElBQUksR0FBRyxTQUFTLEVBQUUsQ0FBQztZQUN2QixrQ0FBa0M7WUFDbEMsTUFBTSxDQUFDLFNBQVMsRUFBRSxTQUFTLENBQUMsR0FBRyxNQUFNLElBQUksQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLGVBQWUsQ0FBQyxJQUFJLENBQUMsQ0FBQztZQUV4RSxxQ0FBcUM7WUFDckMsSUFBSSxZQUFZLEdBQUcsSUFBSSxDQUFDLGVBQWUsQ0FBQyxLQUFLLENBQUMsQ0FBQztZQUMvQyxJQUFJLFlBQVksRUFBRTtnQkFDaEIsSUFBSSxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLEtBQUssRUFBRSxZQUFZLENBQUMsQ0FBQzthQUMxQztZQUNELElBQUksQ0FBQyxlQUFlLENBQUMsS0FBSyxDQUFDLEdBQUcsU0FBUyxDQUFDO1lBRXhDLDhCQUE4QjtZQUM5QixJQUFJLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsS0FBSyxFQUFFLFNBQVMsQ0FBQyxDQUFDO1lBQ3RDLGdDQUFnQztZQUNoQyw2Q0FBNkM7WUFDN0MsSUFBSSxDQUFDLElBQUksQ0FBQyxjQUFjLEVBQUU7Z0JBQ3hCLElBQUksQ0FBQyxjQUFjLEdBQUcsSUFBSSxDQUFDO2dCQUMzQixNQUFNLFVBQVUsR0FBRyxDQUFDLFNBQWlCLEVBQUUsRUFBRTtvQkFDdkMsaURBQWlEO29CQUNqRCxJQUFJLENBQUMsVUFBVSxDQUFDLGtCQUFrQixDQUFDLFNBQVMsQ0FBQyxDQUFDO2dCQUNoRCxDQUFDLENBQUM7Z0JBRUYsTUFBTSxVQUFVLEdBQUcsQ0FBQyxjQUFzQixFQUFFLEVBQUU7b0JBQzVDLHNEQUFzRDtvQkFDdEQsSUFBSSxDQUFDLFVBQVUsQ0FBQyxrQkFBa0IsQ0FBQyxjQUFjLENBQUMsQ0FBQztnQkFDckQsQ0FBQyxDQUFDO2dCQUNGLE1BQU0sVUFBVSxHQUFHLENBQUMsR0FBVyxFQUFFLEVBQUU7b0JBQ2pDLElBQUksQ0FBQyxVQUFVLENBQUMsa0JBQWtCLENBQUMsR0FBRyxDQUFDLENBQUM7Z0JBQzFDLENBQUMsQ0FBQztnQkFDRixTQUFTLENBQUMsRUFBRSxDQUNWLFNBQVMsQ0FBQyxZQUFZLEVBQ3RCLElBQUksQ0FBQyxVQUFVLENBQUMsbUJBQW1CLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsQ0FDMUQsQ0FBQztnQkFDRixTQUFTLENBQUMsRUFBRSxDQUNWLFNBQVMsQ0FBQyxZQUFZLEVBQ3RCLElBQUksQ0FBQyxVQUFVLENBQUMsbUJBQW1CLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsQ0FDMUQsQ0FBQztnQkFDRixTQUFTLENBQUMsRUFBRSxDQUFDLFNBQVMsQ0FBQyxXQUFXLEVBQUUsVUFBVSxDQUFDLENBQUM7Z0JBQ2hELFNBQVMsQ0FBQyxFQUFFLENBQUMsU0FBUyxDQUFDLFdBQVcsRUFBRSxVQUFVLENBQUMsQ0FBQztnQkFDaEQsU0FBUyxDQUFDLEVBQUUsQ0FBQyxTQUFTLENBQUMsV0FBVyxFQUFFLFVBQVUsQ0FBQyxDQUFDO2dCQUNoRCxTQUFTLENBQUMsRUFBRSxDQUNWLFNBQVMsQ0FBQyxTQUFTLEVBQ25CLElBQUksQ0FBQyxVQUFVLENBQUMsZ0JBQWdCLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsQ0FDdkQsQ0FBQztnQkFDRixTQUFTLENBQUMsRUFBRSxDQUNWLFNBQVMsQ0FBQyxhQUFhLEVBQ3ZCLElBQUksQ0FBQyxVQUFVLENBQUMsb0JBQW9CLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsQ0FDM0QsQ0FBQzthQUNIO1NBQ0Y7YUFBTTtZQUNMLGlHQUFpRztZQUNqRyxNQUFNLEVBQUMsT0FBTyxFQUFFLGNBQWMsRUFBQyxHQUM3QixJQUFJLENBQUMsVUFBVSxDQUFDLHdCQUF3QixDQUFDLE1BQU0sQ0FBQyxDQUFDO1lBQ25ELElBQUksT0FBTyxFQUFFO2dCQUNYLHFCQUFxQjtnQkFDckIsTUFBTSxDQUFDLFlBQVksQ0FBQyxHQUFHLE1BQU0sSUFBSSxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsa0JBQWtCLENBQzFELE9BQU8sQ0FBQyxZQUFZLENBQ3JCLENBQUM7Z0JBQ0YsU0FBUztnQkFDVCxJQUFJLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsS0FBSyxFQUFFLFlBQVksQ0FBQyxDQUFDO2dCQUN6QyxJQUFJLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxhQUFhLENBQUMsS0FBSyxFQUFFO29CQUNoQyxLQUFLLEVBQUUsTUFBTSxDQUFDLEtBQUs7b0JBQ25CLFdBQVcsRUFBRSxjQUFjO2lCQUM1QixDQUFDLENBQUM7YUFDSjtTQUNGO0lBQ0gsQ0FBQztJQUVELEtBQUssQ0FBQyw0QkFBNEI7UUFDaEMsTUFBTSxJQUFJLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsR0FBRyxJQUFJLENBQUMsWUFBWSxDQUFDLENBQUM7UUFDaEQsSUFBSSxDQUFDLFlBQVksR0FBRyxFQUFFLENBQUM7UUFDdkIsSUFBSSxDQUFDLGVBQWUsQ0FBQyxLQUFLLEVBQUUsQ0FBQztJQUMvQixDQUFDO0lBRUQ7OztPQUdHO0lBQ0gsS0FBSyxDQUFDLHdCQUF3QixDQUFDLFNBQWlCO1FBQzlDLE1BQU0sV0FBVyxHQUFHLElBQUksQ0FBQyxtQkFBbUIsQ0FBQyxTQUFTLENBQUMsQ0FBQyxHQUFHLENBQUM7UUFDNUQsSUFBSSxXQUFXLEVBQUU7WUFDZixJQUFJO2dCQUNGLE1BQU0sSUFBSSxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLFdBQVcsQ0FBQyxDQUFDO2dCQUN2QyxJQUFJLENBQUMsZUFBZSxDQUFDLE1BQU0sQ0FBQyxXQUFXLENBQUMsQ0FBQztnQkFDekMsTUFBTSxLQUFLLEdBQUcsSUFBSSxDQUFDLFlBQVksQ0FBQyxPQUFPLENBQUMsV0FBVyxDQUFDLENBQUM7Z0JBQ3JELElBQUksQ0FBQyxZQUFZLENBQUMsTUFBTSxDQUFDLEtBQUssRUFBRSxDQUFDLENBQUMsQ0FBQzthQUNwQztZQUFDLE9BQU8sS0FBSyxFQUFFO2dCQUNkLE9BQU8sQ0FBQyxHQUFHLENBQUMsbUJBQW1CLEVBQUUsV0FBVyxFQUFFLEtBQUssQ0FBQyxDQUFDO2FBQ3REO1NBQ0Y7SUFDSCxDQUFDO0lBRUQ7OztPQUdHO0lBQ0gsS0FBSyxDQUFDLGNBQWMsQ0FBQyxJQUFZO1FBQy9CLElBQUksQ0FBQyxvQkFBb0IsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLENBQUMsS0FBSyxDQUFDLE9BQU8sR0FBRyxLQUFLLENBQUM7SUFDNUQsQ0FBQztJQUVELG1DQUFtQyxDQUFDLElBQVk7UUFDNUMsSUFBSSxHQUFHLEdBQUcsSUFBSSxDQUFDLG9CQUFvQixDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUM5QyxJQUFHLENBQUMsR0FBRyxFQUFDO1lBQ04sT0FBTyxDQUFDLEdBQUcsQ0FBQyxtQkFBbUIsQ0FBQyxDQUFDO1lBQ2pDLE9BQU8sSUFBSSxDQUFDO1NBQ2I7UUFDRCwwQ0FBMEM7UUFDMUMsSUFBRyxHQUFHLENBQUMsS0FBSyxDQUFDLElBQUksSUFBSSxJQUFJLEVBQUM7WUFDeEIsT0FBTyxDQUFDLEdBQUcsQ0FBQyxxQkFBcUIsQ0FBQyxDQUFDO1lBQ25DLEdBQUcsQ0FBQyxLQUFLLENBQUMsSUFBSSxHQUFHLElBQUksQ0FBQyxDQUFDLHlCQUF5QjtTQUNqRDtRQUVELE9BQU8sR0FBRyxDQUFDO0lBQ2YsQ0FBQztJQUVEOzs7O09BSUc7SUFDSCxLQUFLLENBQUMsNkJBQTZCLENBQUMsT0FBZ0IsRUFBRSxPQUFxQjtRQUN6RSxNQUFNLGFBQWEsR0FBRyxJQUFJLGFBQWEsQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUNqRCwwQ0FBMEM7UUFDMUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxHQUFHLE9BQU8sQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDO1FBQ2pDLElBQUksR0FBRyxJQUFJLEdBQUcsQ0FBQyxVQUFVLEVBQUU7WUFDekIsYUFBYSxDQUFDLFdBQVcsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDO1lBQ3RELGFBQWEsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxxQ0FBcUM7U0FDakU7UUFDRCxhQUFhLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDaEQsYUFBYSxDQUFDLFdBQVcsQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLFFBQVEsQ0FBQyxDQUFDO1FBQ3BELGFBQWEsQ0FBQyxTQUFTLENBQUMsT0FBTyxFQUFFLE9BQU8sQ0FBQyxDQUFDO1FBQzFDLElBQUksQ0FBQyxpQkFBaUIsR0FBRyxNQUFNLElBQUksQ0FBQyxvQkFBb0IsQ0FBQyxhQUFhLENBQUMsQ0FBQztRQUN4RSxJQUFJLENBQUMsa0JBQWtCLENBQUMsa0JBQWtCLENBQUMsV0FBVyxDQUFDLENBQUM7UUFDeEQsTUFBTSxJQUFJLENBQUMsa0JBQWtCLENBQUMsYUFBYSxDQUFDLENBQUM7SUFDL0MsQ0FBQztJQUVEOzs7T0FHRztJQUNILEtBQUssQ0FBQyxzQkFBc0IsQ0FBQyxPQUFnQjtRQUMzQyxNQUFNLGFBQWEsR0FBRyxJQUFJLGFBQWEsQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUNqRCxhQUFhLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDaEQsYUFBYSxDQUFDLFdBQVcsQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLFFBQVEsQ0FBQyxDQUFDO1FBQ3BELElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxrQkFBa0IsQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUNuRCxNQUFNLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxhQUFhLENBQUMsQ0FBQztJQUMvQyxDQUFDO0lBRUQ7O09BRUc7SUFDSCxxQkFBcUI7UUFDbkIsSUFBSSxDQUFDLG1CQUFtQixFQUFFLENBQUM7UUFDM0IsSUFBSSxDQUFDLGtCQUFrQixDQUFDLGtCQUFrQixDQUFDLE9BQU8sQ0FBQyxDQUFDO0lBQ3RELENBQUM7SUFFRCxlQUFlLENBQUMsWUFBNkI7UUFDM0MsSUFBSSxDQUFDLFlBQVksR0FBRyxZQUFZLENBQUM7SUFDbkMsQ0FBQztJQUVELGVBQWU7UUFDYixPQUFPLElBQUksQ0FBQyxZQUFZLENBQUM7SUFDM0IsQ0FBQztJQUVEOzs7T0FHRztJQUNILGdDQUFnQyxDQUFDLElBQXlCO1FBQ3hELElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxhQUFhLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO1FBQ2hELE1BQU0sT0FBTyxHQUFHLElBQUksQ0FBQyxVQUFVLEVBQUUsQ0FBQztRQUNsQyxRQUFRLElBQUksRUFBRTtZQUNaLEtBQUssbUJBQW1CLENBQUMsYUFBYTtnQkFDcEMsSUFBSSxDQUFDLFdBQVcsRUFBRSxDQUFDO2dCQUNuQixJQUFJLENBQUMsTUFBTSxDQUFDLFFBQVEsQ0FBQyxDQUFDLFNBQVMsSUFBSSxDQUFDLGNBQWMsWUFBWSxDQUFDLENBQUMsQ0FBQztnQkFDakUsTUFBTTtZQUNSLEtBQUssbUJBQW1CLENBQUMsVUFBVTtnQkFDakMsSUFBSSxDQUFDLFdBQVcsRUFBRSxDQUFDO2dCQUNuQixJQUFJLENBQUMsTUFBTSxDQUFDLFFBQVEsQ0FBQyxDQUFDLFNBQVMsSUFBSSxDQUFDLGNBQWMsYUFBYSxDQUFDLENBQUMsQ0FBQztnQkFDbEUsTUFBTTtZQUNSLEtBQUssbUJBQW1CLENBQUMsWUFBWTtnQkFDbkMsSUFBSSxDQUFDLFdBQVcsRUFBRSxDQUFDO2dCQUNuQixJQUFJLENBQUMsTUFBTSxDQUFDLFFBQVEsQ0FBQyxDQUFDLFNBQVMsSUFBSSxDQUFDLGNBQWMsZUFBZSxDQUFDLENBQUMsQ0FBQztnQkFDcEUsTUFBTTtZQUNSLEtBQUssbUJBQW1CLENBQUMsUUFBUTtnQkFDL0IsSUFBSSxDQUFDLFdBQVcsRUFBRSxDQUFDO2dCQUNuQixJQUFJLEdBQVcsQ0FBQztnQkFDaEIsSUFBSSxJQUFJLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDLEVBQUU7b0JBQ2pDLEdBQUcsR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxTQUFTLENBQUMsQ0FBQyxFQUFFLElBQUksQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDO2lCQUNsRTtxQkFBTTtvQkFDTCxHQUFHLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUM7aUJBQ3ZCO2dCQUNELElBQUksQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDLENBQUMsR0FBRyxHQUFHLGNBQWMsQ0FBQyxDQUFDLENBQUM7Z0JBQzdDLE1BQU07WUFDUixLQUFLLG1CQUFtQixDQUFDLFFBQVE7Z0JBQy9CLElBQUksQ0FBQyxXQUFXLEVBQUUsQ0FBQztnQkFDbkIsSUFBSSxDQUFDLE1BQU0sQ0FBQyxRQUFRLENBQUMsQ0FBQyxTQUFTLElBQUksQ0FBQyxjQUFjLGNBQWMsQ0FBQyxFQUFFO29CQUNqRSxXQUFXLEVBQUUsRUFBQyxNQUFNLEVBQUUsSUFBSSxFQUFDO2lCQUM1QixDQUFDLENBQUM7Z0JBQ0gsTUFBTTtZQUNSLEtBQUssbUJBQW1CLENBQUMsUUFBUTtnQkFDL0IsSUFBSSxDQUFDLFdBQVcsRUFBRSxDQUFDO2dCQUNuQixJQUFJLENBQUMsTUFBTSxDQUFDLFFBQVEsQ0FBQyxDQUFDLFNBQVMsSUFBSSxDQUFDLGNBQWMsV0FBVyxDQUFDLENBQUMsQ0FBQztnQkFDaEUsTUFBTTtZQUNSLEtBQUssbUJBQW1CLENBQUMsaUJBQWlCO2dCQUN4QyxJQUFJLE9BQU8sRUFBRTtvQkFDWCw2QkFBNkI7b0JBQzdCLElBQUksQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUNsQixDQUFDLFNBQVMsSUFBSSxDQUFDLGNBQWMsYUFBYSxJQUFJLENBQUMsWUFBWSxDQUFDLEVBQUUsRUFBRSxDQUFDLEVBQ2pFLEVBQUMsV0FBVyxFQUFFLEVBQUMsV0FBVyxFQUFFLElBQUksRUFBQyxFQUFDLENBQ25DLENBQUM7aUJBQ0g7Z0JBQ0QsTUFBTTtZQUNSLEtBQUssbUJBQW1CLENBQUMsZUFBZTtnQkFDdEMsSUFBSSxPQUFPLEVBQUU7b0JBQ1gsSUFBSSxDQUFDLE1BQU0sQ0FBQyxRQUFRLENBQ2xCO3dCQUNFLFNBQVMsSUFBSSxDQUFDLGNBQWMsV0FDMUIsSUFBSSxDQUFDLGVBQWUsQ0FBQyxHQUFHLENBQUMsT0FBTyxDQUFDLENBQUMsU0FDcEMsRUFBRTtxQkFDSCxFQUNELEVBQUMsV0FBVyxFQUFFLEVBQUMsV0FBVyxFQUFFLElBQUksRUFBQyxFQUFDLENBQ25DLENBQUM7aUJBQ0g7Z0JBQ0QsTUFBTTtZQUNSLEtBQUssbUJBQW1CLENBQUMsa0JBQWtCO2dCQUN6QyxJQUFJLE9BQU8sRUFBRTtvQkFDWCxJQUFJLENBQUMsTUFBTSxDQUFDLFFBQVEsQ0FDbEI7d0JBQ0UsU0FBUyxJQUFJLENBQUMsY0FBYyxVQUMxQixJQUFJLENBQUMsZUFBZSxDQUFDLEdBQUcsQ0FBQyxPQUFPLENBQUMsQ0FBQyxTQUNwQyxFQUFFO3FCQUNILEVBQ0QsRUFBQyxXQUFXLEVBQUUsRUFBQyxXQUFXLEVBQUUsSUFBSSxFQUFDLEVBQUMsQ0FDbkMsQ0FBQztpQkFDSDtnQkFDRCxNQUFNO1lBQ1IsS0FBSyxtQkFBbUIsQ0FBQyxhQUFhO2dCQUNwQyxJQUFJLE9BQU8sRUFBRTtvQkFDWCxJQUFJLENBQUMsTUFBTSxDQUFDLFFBQVEsQ0FBQyxFQUFFLEVBQUU7d0JBQ3ZCLFVBQVUsRUFBRSxJQUFJLENBQUMsV0FBVzt3QkFDNUIsV0FBVyxFQUFFLEVBQUMsV0FBVyxFQUFFLElBQUksRUFBQyxFQUFFLG1CQUFtQixFQUFHLE9BQU87cUJBQ2hFLENBQUMsQ0FBQztpQkFDSjtnQkFDRCxNQUFNO1lBQ1IsS0FBSyxtQkFBbUIsQ0FBQyxhQUFhO2dCQUNwQyxJQUFJLE9BQU8sRUFBRTtvQkFDWCxJQUFJLENBQUMsTUFBTSxDQUFDLFFBQVEsQ0FBQyxFQUFFLEVBQUU7d0JBQ3ZCLFVBQVUsRUFBRSxJQUFJLENBQUMsV0FBVzt3QkFDNUIsV0FBVyxFQUFFLEVBQUMsV0FBVyxFQUFFLElBQUksRUFBQyxFQUFFLG1CQUFtQixFQUFHLE9BQU87cUJBQ2hFLENBQUMsQ0FBQztpQkFDSjtnQkFDRCxNQUFNO1NBQ1Q7SUFDSCxDQUFDO0lBRUQ7Ozs7OztPQU1HO0lBQ0gsS0FBSyxDQUFDLG9CQUFvQixDQUN4QixXQUFtQixFQUNuQixNQUFvQixFQUNwQixPQUFnQixFQUNoQixNQUFrQixJQUFJO1FBRXRCLElBQUksQ0FBQyxlQUFlLENBQUMsR0FBRyxDQUFDLFdBQVcsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxNQUFNLEVBQUUsT0FBTyxDQUFDLENBQUM7UUFDakUsSUFBSSxHQUFHLEVBQUU7WUFDUCxJQUFJLENBQUMsZUFBZSxDQUFDLEdBQUcsQ0FBQyxXQUFXLENBQUMsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUM7U0FDbkQ7UUFDRCxJQUFJLENBQUMsZUFBZSxDQUFDLEdBQUcsQ0FBQyxXQUFXLENBQUMsQ0FBQyxTQUFTLEdBQUcsTUFBTSxDQUFDLEVBQUUsQ0FBQztRQUM1RCxJQUFJO1lBQ0YsTUFBTSxJQUFJLENBQUMsOEJBQThCLENBQUMsV0FBVyxFQUFFLE1BQU0sRUFBRSxPQUFPLENBQUMsQ0FBQztZQUN4RSxpQkFBaUI7WUFDakIsTUFBTSxJQUFJLENBQUMsNkJBQTZCLENBQ3RDLFdBQVcsRUFDWCxNQUFNLEVBQ04sT0FBTyxFQUNQLEdBQUcsQ0FDSixDQUFDO1NBQ0g7UUFBQyxPQUFPLENBQUMsRUFBRTtZQUNWLE9BQU8sQ0FBQyxHQUFHLENBQUMsa0NBQWtDLENBQUMsRUFBRSxDQUFDLENBQUM7U0FDcEQ7SUFDSCxDQUFDO0lBRUQsS0FBSyxDQUFDLDZCQUE2QixDQUNqQyxXQUFtQixFQUNuQixNQUFvQixFQUNwQixPQUFnQixFQUNoQixNQUFrQixJQUFJO1FBRXRCLE1BQU0sYUFBYSxHQUFHLE1BQU0sQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLEVBQUUsS0FBSyxHQUFHLENBQUMsRUFBRSxDQUFDLENBQUM7UUFDMUUsTUFBTSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsYUFBYSxDQUFDLEdBQUcsR0FBRyxDQUFDO1FBQ3ZDLE1BQU0sRUFBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBQyxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLFVBQVUsQ0FBQyxDQUFDO1FBQzdDLE1BQU0sV0FBVyxHQUFHO1lBQ2xCLGNBQWMsRUFBRTtnQkFDZCxDQUFDLEVBQUUsQ0FBQztnQkFDSixDQUFDLEVBQUUsQ0FBQztnQkFDSixDQUFDLEVBQUUsQ0FBQzthQUNMO1lBQ0QsVUFBVSxFQUFFO2dCQUNWLHdFQUF3RTtnQkFDeEUsQ0FBQyxFQUFFLENBQUM7Z0JBQ0osQ0FBQyxFQUFFLEdBQUc7Z0JBQ04sQ0FBQyxFQUFFLENBQUM7YUFDTDtTQUNGLENBQUM7UUFDRixJQUFJLENBQUMsR0FBRyxDQUFDLFNBQVMsQ0FBQyxZQUFZLENBQUMsV0FBVyxFQUFFLFdBQVcsQ0FBQyxDQUFDO1FBQzFELElBQUksQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLFlBQVksQ0FBQyxXQUFXLEVBQUUsV0FBVyxDQUFDLENBQUM7UUFDcEQsSUFBSSxDQUFDLGVBQWU7YUFDakIsR0FBRyxDQUFDLFdBQVcsQ0FBQzthQUNoQixXQUFXLENBQUMsV0FBVyxDQUFDLGNBQWMsQ0FBQyxDQUFDO1FBRTNDLEtBQUssSUFBSSxLQUFLLElBQUksSUFBSSxDQUFDLFlBQVksRUFBRTtZQUNuQyxNQUFNLFVBQVUsR0FBRyxJQUFJLENBQUMsZUFBZSxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsQ0FBQztZQUNuRCxJQUFJLENBQUMsVUFBVSxFQUFFO2dCQUNmLFNBQVM7YUFDVjtZQUNELElBQUksVUFBVSxDQUFDLFNBQVMsS0FBSyxNQUFNLENBQUMsRUFBRSxJQUFJLEtBQUssS0FBSyxXQUFXLEVBQUU7Z0JBQy9ELElBQUksQ0FBQyxlQUFlLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDO2dCQUNuQyxJQUFJLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUM7Z0JBQzNCLElBQUksQ0FBQyxHQUFHLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQztnQkFDakMsTUFBTTthQUNQO1NBQ0Y7SUFDSCxDQUFDO0lBRUQ7Ozs7T0FJRztJQUNJLG1CQUFtQixDQUFDLFNBQWlCO1FBSTFDLElBQUksS0FBSyxHQUFHLElBQUksQ0FBQztRQUNqQixJQUFJLE9BQU8sR0FBRyxJQUFJLENBQUM7UUFDbkIsS0FBSyxJQUFJLENBQUMsV0FBVyxFQUFFLGFBQWEsQ0FBQyxJQUFJLElBQUksQ0FBQyxlQUFlLEVBQUU7WUFDN0QsSUFBSSxhQUFhLENBQUMsU0FBUyxLQUFLLFNBQVMsRUFBRTtnQkFDekMsS0FBSyxHQUFHLFdBQVcsQ0FBQztnQkFDcEIsTUFBTSxLQUFLLEdBQUcsYUFBYSxDQUFDLFVBQVUsRUFBRSxDQUFDO2dCQUN6QyxJQUFJLEtBQUssSUFBSSxJQUFJLENBQUMsTUFBTSxJQUFJLElBQUksQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQyxFQUFFO29CQUN2RCxPQUFPLEdBQUcsS0FBSyxDQUFDO2lCQUNqQjthQUNGO1NBQ0Y7UUFDRCxPQUFPLEVBQUMsR0FBRyxFQUFFLEtBQUssRUFBRSxLQUFLLEVBQUUsT0FBTyxFQUFDLENBQUM7SUFDdEMsQ0FBQztJQUVEOzs7T0FHRztJQUNILFVBQVU7UUFDUixJQUFJLElBQUksQ0FBQyxpQkFBaUIsRUFBRTtZQUMxQixPQUFPLElBQUksQ0FBQyxpQkFBaUIsQ0FBQztTQUMvQjthQUFNO1lBQ0wsT0FBTyxJQUFJLENBQUMsWUFBWSxDQUFDLE1BQU0sS0FBSyxDQUFDO2dCQUNuQyxDQUFDLENBQUMsSUFBSTtnQkFDTixDQUFDLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUMsQ0FBQztTQUNyRDtJQUNILENBQUM7SUFFRDs7OztPQUlHO0lBQ0gsNEJBQTRCLENBQUMsV0FBbUI7UUFDOUMsSUFBSTtZQUNGLE9BQU8sSUFBSSxDQUFDLGVBQWUsQ0FBQyxHQUFHLENBQUMsV0FBVyxDQUFDLENBQUM7U0FDOUM7UUFBQyxNQUFNO1lBQ04sT0FBTyxDQUFDLEdBQUcsQ0FBQyx1Q0FBdUMsRUFBRSxXQUFXLENBQUMsQ0FBQztTQUNuRTtRQUNELE9BQU8sSUFBSSxDQUFDO0lBQ2QsQ0FBQztJQUVELEVBQUU7SUFDRiw2REFBNkQ7SUFDN0QsRUFBRTtJQUNGLEtBQUssQ0FBQyx3QkFBd0I7UUFDNUIsSUFBSSxJQUFJLENBQUMsZ0JBQWdCLElBQUksSUFBSSxDQUFDLGlCQUFpQixFQUFFO1lBQ25ELE9BQU8sQ0FBQyxHQUFHLENBQUMsOENBQThDLENBQUMsQ0FBQztZQUM1RCxPQUFPO1NBQ1I7UUFDRCxJQUFJO1lBQ0YsTUFBTSxJQUFJLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsZ0JBQWdCLENBQUMsQ0FBQztTQUM5QztRQUFDLE9BQU8sQ0FBQyxFQUFFO1lBQ1YsT0FBTyxDQUFDLEdBQUcsQ0FBQyx3QkFBd0IsRUFBRSxDQUFDLENBQUMsQ0FBQztTQUMxQztJQUNILENBQUM7SUFFRCwwQkFBMEI7UUFDeEIsSUFBSSxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLGFBQWEsQ0FBQyxDQUFDO0lBQ3RDLENBQUM7SUFFRCxtQkFBbUI7UUFDakIsSUFBSTtZQUNGLElBQUksQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLE9BQU8sRUFBRSxDQUFDO1NBQzFCO1FBQUMsT0FBTyxDQUFDLEVBQUU7WUFDVixPQUFPLENBQUMsR0FBRyxDQUFDLHdCQUF3QixFQUFFLENBQUMsQ0FBQyxDQUFDO1NBQzFDO0lBQ0gsQ0FBQztJQUVELEtBQUssQ0FBQyx3QkFBd0I7UUFDNUIsVUFBVSxDQUFDLEtBQUssSUFBSSxFQUFFO1lBQ3BCLG9GQUFvRjtZQUNwRixJQUFJLElBQUksQ0FBQyxnQkFBZ0IsSUFBSSxJQUFJLENBQUMsaUJBQWlCLEVBQUU7Z0JBQ25ELE9BQU8sQ0FBQyxHQUFHLENBQUMsOENBQThDLENBQUMsQ0FBQztnQkFDNUQsT0FBTzthQUNSO1lBQ0QsSUFBSTtnQkFDRixNQUFNLElBQUksQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDO2FBQzlDO1lBQUMsT0FBTyxDQUFDLEVBQUU7Z0JBQ1YsT0FBTyxDQUFDLEdBQUcsQ0FBQyx3QkFBd0IsRUFBRSxDQUFDLENBQUMsQ0FBQzthQUMxQztRQUNILENBQUMsRUFBRSxJQUFJLENBQUMsQ0FBQztJQUNYLENBQUM7SUFFRCxxQkFBcUI7UUFDbkIsTUFBTSxRQUFRLEdBQUcsQ0FBQyxJQUFJLENBQUMsZUFBZSxDQUFDO1FBQ3ZDLElBQUksQ0FBQyxHQUFHLENBQUMsWUFBWSxDQUFDLFVBQVUsQ0FBQyxRQUFRLENBQUMsQ0FBQyxJQUFJLENBQUMsR0FBRyxFQUFFO1lBQ25ELE9BQU8sQ0FBQyxHQUFHLENBQ1QsMkJBQTJCLFFBQVEsQ0FBQyxDQUFDLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxVQUFVLEVBQUUsQ0FDL0QsQ0FBQztRQUNKLENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztJQUVELDRCQUE0QjtRQUMxQixJQUFJLElBQUksQ0FBQyxlQUFlLEVBQUU7WUFDeEIsSUFBSSxDQUFDLHFCQUFxQixFQUFFLENBQUM7U0FDOUI7SUFDSCxDQUFDO0lBRUQsS0FBSyxDQUFDLGtCQUFrQixDQUN0QixTQUFpQixFQUNqQiwwQkFBa0MsSUFBSTtRQUV0QyxJQUFJLENBQUMsSUFBSSxDQUFDLE1BQU0sRUFBRTtZQUNoQixPQUFPLENBQUMsR0FBRyxDQUFDLDBCQUEwQixDQUFDLENBQUM7WUFDeEMsT0FBTztTQUNSO1FBQ0QsNEJBQTRCO1FBQzVCLGtEQUFrRDtRQUNsRCxJQUFJLGVBQWUsR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDLElBQUksQ0FDcEMsQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUFDLEtBQUssQ0FBQyxRQUFRLEtBQUssdUJBQXVCLENBQ3RELENBQUM7UUFDRixJQUFJLENBQUMsZUFBZSxFQUFFO1lBQ3BCLGVBQWUsR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDLElBQUksQ0FDaEMsQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUFDLFNBQVMsQ0FBQyxRQUFRLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxJQUFJLEtBQUssQ0FBQyxJQUFJLElBQUksRUFBRSxDQUM5RCxDQUFDO1NBQ0g7UUFDRCxJQUFJLENBQUMsZUFBZSxFQUFFO1lBQ3BCLGVBQWUsR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDLEtBQUssRUFBRSxFQUFFLENBQzNDLFNBQVMsQ0FBQyxRQUFRLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQyxDQUM3QixDQUFDO1NBQ0g7UUFDRCwrQkFBK0I7UUFDL0IsSUFBSSxlQUFlLEVBQUU7WUFDbkIsSUFBSSxLQUFLLEdBQUcsSUFBSSxDQUFDO1lBQ2pCLE9BQU8sS0FBSyxFQUFFO2dCQUNaLElBQUk7b0JBQ0YsTUFBTSxVQUFVLEdBQUcsTUFBTSxJQUFJLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQzVDLGVBQWUsQ0FBQyxRQUFRLENBQ3pCLENBQUM7b0JBQ0Ysa0RBQWtEO29CQUNsRCxLQUFLLEdBQUcsS0FBSyxDQUFDO2lCQUNmO2dCQUFDLE9BQU8sS0FBSyxFQUFFO29CQUNkLE9BQU8sQ0FBQyxHQUFHLENBQUMsc0JBQXNCLEVBQUUsS0FBSyxDQUFDLENBQUM7b0JBQzNDLE1BQU0sSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDO2lCQUNqQjthQUNGO1NBQ0Y7YUFBTTtZQUNMLE9BQU8sQ0FBQyxJQUFJLENBQUMsc0NBQXNDLENBQUMsQ0FBQztTQUN0RDtJQUNILENBQUM7SUFFRCxLQUFLLENBQUMsa0JBQWtCLENBQ3RCLEtBQWEsRUFDYixXQUFxQyxJQUFJO1FBRXpDLElBQUksSUFBSSxDQUFDLGVBQWUsQ0FBQyxRQUFRLENBQUMsS0FBSyxDQUFDLEVBQUU7WUFDeEMsT0FBTyxDQUFDLEdBQUcsQ0FBQyx5Q0FBeUMsQ0FBQyxDQUFDO1lBQ3ZELE9BQU87U0FDUjtRQUNELG9FQUFvRTtRQUNwRSxVQUFVLENBQUMsS0FBSyxJQUFJLEVBQUU7WUFDcEIsSUFBSSxJQUFJLENBQUMsZ0JBQWdCLElBQUksSUFBSSxDQUFDLGlCQUFpQixFQUFFO2dCQUNuRCxPQUFPLENBQUMsR0FBRyxDQUFDLG1DQUFtQyxDQUFDLENBQUM7Z0JBQ2pELE9BQU87YUFDUjtZQUNELElBQUk7Z0JBQ0YsSUFBSSxDQUFDLGlCQUFpQixHQUFHLElBQUksQ0FBQztnQkFDOUIsTUFBTSxJQUFJLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsS0FBSyxFQUFFO29CQUNqQyxVQUFVLEVBQUUsb0JBQW9CO29CQUNoQyxjQUFjLEVBQUUsSUFBSTtpQkFDckIsQ0FBQyxDQUFDO2FBQ0o7WUFBQyxPQUFPLEtBQUssRUFBRTtnQkFDZCxJQUFJLENBQUMsaUJBQWlCLEdBQUcsS0FBSyxDQUFDO2dCQUMvQixPQUFPLENBQUMsR0FBRyxDQUFDLHNCQUFzQixFQUFFLEtBQUssQ0FBQyxDQUFDO2FBQzVDO1lBQ0QsSUFBSSxRQUFRLEVBQUU7Z0JBQ1osTUFBTSxJQUFJLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxXQUFXLENBQUMsUUFBUSxFQUFFLEVBQUMsS0FBSyxFQUFFLEdBQUcsRUFBQyxDQUFDLENBQUMsQ0FBQyw4QkFBOEI7YUFDMUY7UUFDSCxDQUFDLEVBQUUsSUFBSSxDQUFDLENBQUM7SUFDWCxDQUFDO0lBRUQsZUFBZTtRQUNiLElBQUksSUFBSSxDQUFDLFVBQVUsRUFBRTtZQUNuQixPQUFPLElBQUksQ0FBQyxVQUFVLENBQUMsS0FBSyxDQUFDO1NBQzlCO1FBQ0QsT0FBTyxJQUFJLENBQUM7SUFDZCxDQUFDO0lBRUQsd0JBQXdCO1FBS3RCLElBQUksSUFBSSxDQUFDLFVBQVUsRUFBRTtZQUNuQixPQUFPLElBQUksQ0FBQyxVQUFVLENBQUM7U0FDeEI7UUFDRCxPQUFPLElBQUksQ0FBQztJQUNkLENBQUM7SUFFRCxrQkFBa0IsQ0FBQyxlQUF1QjtRQUN4QyxJQUFJLENBQUMsZUFBZSxHQUFHLGVBQWUsQ0FBQztJQUN6QyxDQUFDO0lBRUQsa0JBQWtCO1FBQ2hCLE9BQU8sSUFBSSxDQUFDLGVBQWUsQ0FBQztJQUM5QixDQUFDO0lBRUQ7O09BRUc7SUFDSCxLQUFLLENBQUMsUUFBUTtRQUNaLE9BQU8sQ0FBQyxHQUFHLENBQUMsaUJBQWlCLENBQUMsQ0FBQztRQUMvQixJQUFJLENBQUMsNEJBQTRCLEVBQUUsQ0FBQztRQUNwQyxJQUFJLENBQUMsTUFBTSxHQUFHLElBQUksQ0FBQztRQUNuQixJQUFJLENBQUMsTUFBTSxHQUFHLElBQUksQ0FBQztRQUNuQixJQUFJLENBQUMsR0FBRyxHQUFHLElBQUksQ0FBQztRQUNoQixhQUFhLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxDQUFDO1FBQ2pDLElBQUksQ0FBQyxlQUFlLEdBQUcsRUFBRSxDQUFDO1FBQzFCLElBQUksQ0FBQyxjQUFjLEdBQUcsS0FBSyxDQUFDO1FBQzVCLHVCQUF1QjtRQUN2QixJQUFJLENBQUMsYUFBYSxDQUFDLG1CQUFtQixDQUNwQyxPQUFPLEVBQ1AsSUFBSSxDQUFDLHVCQUF1QixDQUM3QixDQUFDO1FBQ0YsSUFBSSxDQUFDLGFBQWEsQ0FBQyxtQkFBbUIsQ0FDcEMsYUFBYSxFQUNiLElBQUksQ0FBQyx3QkFBd0IsQ0FDOUIsQ0FBQztRQUVGLHdCQUF3QjtRQUN4QixJQUFJLElBQUksQ0FBQyx1QkFBdUIsRUFBRTtZQUNoQyxJQUFJLENBQUMsdUJBQXVCLENBQUMsbUJBQW1CLENBQzlDLFVBQVUsRUFDVixJQUFJLENBQUMseUJBQXlCLENBQy9CLENBQUM7U0FDSDtRQUNELHNCQUFzQjtRQUN0QixJQUFJLENBQUMsQ0FBQyxJQUFJLENBQUMsdUJBQXVCO1lBQ2hDLENBQUMsUUFBUSxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsQ0FBQyxJQUFJLFFBQVEsQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxXQUFXLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxFQUFFO1lBQ3RHLGFBQWEsQ0FBQyxJQUFJLENBQUMsNkJBQTZCLENBQUMsQ0FBQztTQUNuRDtJQUNILENBQUM7SUFFRCxLQUFLLENBQUMscUJBQXFCLENBQUMsZUFBeUI7UUFDbkQsSUFBSSxDQUFDLGVBQWUsR0FBRyxDQUFDLEdBQUcsZUFBZSxDQUFDLENBQUM7UUFDNUMsSUFBSSxPQUFPLEdBQUcsQ0FBQyxDQUFDO1FBQ2hCLE1BQU0sT0FBTyxDQUFDLEdBQUcsQ0FDZixlQUFlLENBQUMsR0FBRyxDQUFDLEtBQUssRUFBRSxLQUFLLEVBQUUsRUFBRTtZQUNsQyxJQUFJO2dCQUNGLE1BQU0sSUFBSSxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQyxDQUFDO2dCQUNwQyxPQUFPLElBQUksQ0FBQyxDQUFDO2FBQ2Q7WUFBQyxPQUFPLEtBQUssRUFBRTtnQkFDZCxPQUFPLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxDQUFDO2FBQ3BCO1FBQ0gsQ0FBQyxDQUFDLENBQ0gsQ0FBQztRQUNGLE9BQU8sQ0FBQyxHQUFHLENBQUMsaUJBQWlCLEVBQUUsT0FBTyxDQUFDLENBQUM7SUFDMUMsQ0FBQztJQUVELEVBQUU7SUFDRixxREFBcUQ7SUFDckQsRUFBRTtJQUNGLEtBQUssQ0FBQyxrQkFBa0I7UUFDdEIsT0FBTyxJQUFJLE9BQU8sQ0FBQyxLQUFLLEVBQUUsT0FBTyxFQUFFLEVBQUU7WUFDbkMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxHQUFHLE1BQU0sSUFBSSxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsYUFBYSxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBRTFELElBQUksSUFBSSxHQUFHLFdBQVcsQ0FBQyxPQUFPLEVBQUUsQ0FBQztZQUVqQyxzQkFBc0I7WUFDdEIsSUFBSSxDQUFDLFlBQVksQ0FBQyxXQUFXLENBQUMsQ0FBQztZQUMvQixpQ0FBaUM7WUFDakM7NkNBQ2lDO1lBQ2pDLElBQUksQ0FBQyxLQUFLLEVBQUUsQ0FBQztZQUViLE1BQU0sV0FBVyxHQUFHLFdBQVcsQ0FBQyxPQUFPLEVBQUUsQ0FBQztZQUMxQyxJQUFJLENBQUMsYUFBYSxHQUFHLFdBQVcsQ0FBQyxZQUFZLENBQUMsc0JBQXNCLENBQUMsQ0FBQztZQUN0RSxXQUFXLENBQUMsS0FBSyxFQUFFLENBQUM7WUFFcEIsNEJBQTRCO1lBRTVCLE9BQU8sRUFBRSxDQUFDO1FBQ1osQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDO0lBRUQsS0FBSyxDQUFDLFdBQVcsQ0FDZixHQUFjLEVBQ2QsSUFBNkI7UUFFN0IsT0FBTyxJQUFJLE9BQU8sQ0FBQyxLQUFLLEVBQUUsT0FBTyxFQUFFLEVBQUU7WUFDbkMsTUFBTSxDQUFDLFdBQVcsQ0FBQyxHQUFHLE1BQU0sSUFBSSxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsYUFBYSxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBRTVELGtFQUFrRTtZQUNsRSxpQkFBaUI7WUFDakIsaUJBQWlCO1lBQ2pCLFFBQVE7WUFDUixJQUFJLHdCQUF3QixHQUFHLEtBQUssQ0FBQztZQUNyQyxJQUFJLGdCQUFnQixHQUFHLEtBQUssQ0FBQztZQUM3QixJQUFJLDZCQUE2QixHQUFHLEtBQUssQ0FBQztZQUMxQyxJQUFJLGdCQUFnQixHQUFHLEtBQUssQ0FBQztZQUU3Qjs7ZUFFRztZQUNILElBQUksR0FBRyxDQUFDLE1BQU0sS0FBSyxpQkFBaUIsRUFBRTtnQkFDcEMsd0JBQXdCLEdBQUcsSUFBSSxDQUFDO2FBQ2pDO1lBQ0QsSUFBSSxHQUFHLENBQUMsTUFBTSxLQUFLLGlCQUFpQixFQUFFO2dCQUNwQyxnQkFBZ0IsR0FBRyxJQUFJLENBQUM7YUFDekI7WUFDRCxJQUFJLEdBQUcsQ0FBQyxNQUFNLEtBQUssT0FBTyxFQUFFO2dCQUMxQiw2QkFBNkIsR0FBRyxJQUFJLENBQUM7YUFDdEM7WUFDRCxJQUFHLEdBQUcsQ0FBQyxNQUFNLEtBQUssU0FBUyxFQUFFO2dCQUMzQixnQkFBZ0IsR0FBRyxJQUFJLENBQUM7YUFDekI7WUFFRCxNQUFNLFNBQVMsR0FBRyxXQUFXLENBQUMsT0FBTyxFQUFFLENBQUM7WUFDeEMsSUFBSSxTQUFTLEdBQUcsSUFBSSxDQUFDO1lBQ3JCLE1BQU0sT0FBTyxHQUFHO2dCQUNkLEdBQUcsRUFBRSw2QkFBNkIsR0FBRyxDQUFDLE1BQU0sR0FDMUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEdBQUcsR0FBRyxHQUFHLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsTUFDMUQsRUFBRTtnQkFDRixzR0FBc0c7Z0JBQ3RHLGFBQWEsRUFBRSxFQUFDLEdBQUcsRUFBRSxDQUFDLEVBQUUsR0FBRyxFQUFFLENBQUMsRUFBRSxHQUFHLEVBQUUsQ0FBQyxFQUFDO2dCQUN2QyxzR0FBc0c7Z0JBQ3RHLGFBQWEsRUFBRSxFQUFDLEdBQUcsRUFBRSxDQUFDLEVBQUUsR0FBRyxFQUFFLENBQUMsRUFBRSxHQUFHLEVBQUUsQ0FBQyxFQUFDO2dCQUN2QyxPQUFPLEVBQUUsSUFBSTtnQkFDYixlQUFlLEVBQUUsSUFBSTthQUN0QixDQUFDO1lBR0YsUUFBUSxHQUFHLENBQUMsTUFBTSxFQUFFO2dCQUNsQixLQUFLLE1BQU0sQ0FBQztnQkFDWixLQUFLLEtBQUs7b0JBQ1IsU0FBUyxHQUFHLFNBQVMsQ0FBQyxZQUFZLENBQUMsY0FBYyxFQUFFLE9BQU8sQ0FBQyxDQUFDO29CQUM1RCxNQUFNO2dCQUNSLEtBQUssTUFBTSxDQUFDO2dCQUNaLEtBQUssS0FBSztvQkFDUixTQUFTLEdBQUcsU0FBUyxDQUFDLFlBQVksQ0FBQyxjQUFjLEVBQUUsT0FBTyxDQUFDLENBQUM7b0JBQzVELE1BQU07Z0JBQ1IsS0FBSyxPQUFPLENBQUM7Z0JBQ2IsS0FBSyxNQUFNO29CQUNULFNBQVMsR0FBRyxTQUFTLENBQUMsWUFBWSxDQUFDLGVBQWUsRUFBRSxPQUFPLENBQUMsQ0FBQztvQkFDN0QsTUFBTTtnQkFDUixLQUFLLE1BQU0sQ0FBQztnQkFDWixLQUFLLEtBQUs7b0JBQ1IsU0FBUyxHQUFHLFNBQVMsQ0FBQyxZQUFZLENBQUMsZUFBZSxFQUFFLE9BQU8sQ0FBQyxDQUFDO29CQUM3RCxNQUFNO2dCQUNSLEtBQUssTUFBTSxDQUFDO2dCQUNaLEtBQUssS0FBSztvQkFDUixTQUFTLEdBQUcsU0FBUyxDQUFDLFlBQVksQ0FBQyxjQUFjLEVBQUUsT0FBTyxDQUFDLENBQUM7b0JBQzVELE1BQU07Z0JBRVI7b0JBQ0UsT0FBTyxDQUFDLEdBQUcsQ0FBQyxzQkFBc0IsQ0FBQyxDQUFDO29CQUNwQyxNQUFNO2FBQ1Q7WUFFRCxtREFBbUQ7WUFDbkQ7Ozs7Ozs0Q0FNZ0M7WUFDaEMsOENBQThDO1lBQzlDLHFCQUFxQjtZQUVyQiw2QkFBNkI7WUFDN0IsSUFBSSxJQUFJLENBQUMsaUJBQWlCLEVBQUU7Z0JBQzFCLE1BQU0sVUFBVSxHQUFHLFdBQVcsQ0FBQyxPQUFPLEVBQUUsQ0FBQztnQkFDekMsVUFBVSxDQUFDLFlBQVksQ0FBQyxpQkFBaUIsRUFBRTtvQkFDekMsU0FBUyxFQUFFLENBQUM7b0JBQ1osS0FBSyxFQUFFLEVBQUMsQ0FBQyxFQUFFLEdBQUcsRUFBRSxDQUFDLEVBQUUsR0FBRyxFQUFFLENBQUMsRUFBRSxHQUFHLEVBQUM7aUJBQ2hDLENBQUMsQ0FBQztnQkFDSCxJQUFJLENBQUMsaUJBQWlCLEdBQUcsS0FBSyxDQUFDO2FBQ2hDO1lBRUQsU0FBUyxDQUFDLEtBQUssQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUMxQixHQUFHLENBQUMsUUFBUSxDQUFDLENBQUMsRUFDZCxHQUFHLENBQUMsUUFBUSxDQUFDLENBQUMsRUFDZCxHQUFHLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FDZixDQUFDO1lBRUYsU0FBUyxDQUFDLEtBQUssQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUMxQixHQUFHLENBQUMsUUFBUSxDQUFDLENBQUMsRUFDZCxHQUFHLENBQUMsUUFBUSxDQUFDLENBQUMsRUFDZCxHQUFHLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FDZixDQUFDO1lBQ0YsU0FBUyxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsQ0FBQyxFQUFFLEdBQUcsQ0FBQyxLQUFLLENBQUMsQ0FBQyxFQUFFLEdBQUcsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUM7WUFDakUsSUFBRyxnQkFBZ0IsRUFDbkI7Z0JBQ0U7O21CQUVHO2dCQUNILElBQUksQ0FBQyxjQUFjLEdBQUMsU0FBUyxDQUFDO2dCQUM5QixJQUFJLENBQUMsb0JBQW9CLEVBQUUsQ0FBQzthQUM3QjtZQUVELDJEQUEyRDtZQUMzRCxzRkFBc0Y7WUFDdEYsSUFBSSxJQUFJLElBQUksQ0FBQyxnQkFBZ0IsRUFBRTtnQkFDN0IsSUFBSSxDQUFDLDRCQUE0QixDQUMvQixTQUFTLEVBQ1QsV0FBVyxFQUNYLElBQUksRUFDSixJQUFJLEVBQ0osSUFBSSxDQUNMLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7YUFDaEM7WUFFRCxJQUFJLElBQUksQ0FBQyxZQUFZLElBQUksT0FBTyxJQUFJLENBQUMsWUFBWSxDQUFDLEVBQUUsS0FBSyxRQUFRLEVBQUU7Z0JBQ2pFLDhFQUE4RTtnQkFDOUUsU0FBUyxDQUFDLEtBQUssQ0FBQyxJQUFJLEdBQUcsSUFBSSxDQUFDLFlBQVksQ0FBQyxFQUFFLENBQUM7YUFDN0M7aUJBQU0sSUFBSSxHQUFHLENBQUMsRUFBRSxFQUFFO2dCQUNqQixTQUFTLENBQUMsS0FBSyxDQUFDLElBQUksR0FBRyxHQUFHLENBQUMsRUFBRSxDQUFDO2FBQy9CO1lBQ0QsSUFBSSxDQUFDLFlBQVksR0FBRyxTQUFTLENBQUMsS0FBSyxDQUFDO1lBRXBDLHVDQUF1QztZQUN2QyxpQ0FBaUM7WUFDakMseUJBQXlCO1lBQ3pCLElBQUksQ0FBQyxvQkFBb0IsQ0FBQyxHQUFHLENBQUMsU0FBUyxDQUFDLEtBQUssQ0FBQyxJQUFJLEVBQUUsU0FBUyxDQUFDLENBQUM7WUFDL0QsSUFBSSxDQUFDLHlCQUF5QixDQUFDLEdBQUcsQ0FBQyxTQUFTLENBQUMsS0FBSyxDQUFDLElBQUksRUFBRSxXQUFXLENBQUMsQ0FBQztZQUV0RTs7Ozs7Ozs7Ozs7Ozs7OEJBY2tCO1lBRWxCLElBQUksd0JBQXdCLEVBQUU7Z0JBRTVCLE1BQU0sUUFBUSxHQUFHLFNBQVMsQ0FBQyxZQUFZLENBQUMsbUJBQW1CLEVBQ3pEO29CQUNFLFdBQVcsRUFBRSxHQUFHO29CQUNoQixVQUFVLEVBQUUsRUFBRTtvQkFDZCxlQUFlLEVBQUUsRUFBRTtvQkFDbkIsUUFBUSxFQUFFLGtCQUFrQjtvQkFDNUIsZUFBZSxFQUFFO3dCQUNmLEdBQUcsRUFBRSxHQUFHO3dCQUNSLEdBQUcsRUFBRSxJQUFJO3dCQUNULEdBQUcsRUFBRSxDQUFDO3FCQUNQO29CQUNELGVBQWUsRUFBRTt3QkFDZixHQUFHLEVBQUUsQ0FBQyxFQUFFO3dCQUNSLEdBQUcsRUFBRSxDQUFDLEVBQUU7d0JBQ1IsR0FBRyxFQUFFLENBQUM7cUJBQ1A7b0JBQ0QsT0FBTyxFQUFFLEtBQUs7b0JBQ2QsV0FBVyxFQUFFLENBQUM7b0JBQ2QsVUFBVSxFQUFFLENBQUMsRUFBRTtpQkFDaEIsQ0FBQyxDQUFDO2dCQUNMLE1BQU0sV0FBVyxHQUFHLFdBQVcsQ0FBQyxPQUFPLENBQUM7b0JBQ3RDLEVBQUUsRUFBRSxnQkFBZ0I7b0JBQ3BCLElBQUksRUFBRSxJQUFJLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxRQUFRLENBQUMsTUFBTTtvQkFDcEMsSUFBSSxFQUFFLFNBQVM7b0JBQ2YsU0FBUyxFQUFFLFFBQVE7b0JBQ25CLFFBQVEsRUFBRSxZQUFZO2lCQUN2QixDQUFDLENBQUM7Z0JBRUgsSUFBSSxDQUFDLHNCQUFzQixHQUFHLFFBQVEsQ0FBQztnQkFDdkMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxXQUFXLEVBQUU7b0JBQ3BCLFVBQVUsQ0FBQyxHQUFHLEVBQUU7d0JBQ2QsUUFBUSxDQUFDLGlCQUFpQixFQUFFLENBQUM7b0JBQy9CLENBQUMsRUFBRSxJQUFJLENBQUMsQ0FBQztpQkFDVjthQUNGO1lBRUQsSUFBSSxnQkFBZ0IsRUFBRTtnQkFDcEIsZ0ZBQWdGO2dCQUNoRixpQ0FBaUM7Z0JBQ2pDLGdDQUFnQztnQkFDaEMsZUFBZTtnQkFDZixNQUFNLEVBQUUsR0FBRyxJQUFJLGNBQWMsRUFBRSxDQUFDO2dCQUNoQyxFQUFFLENBQUMsTUFBTSxFQUFFLENBQUM7Z0JBQ1osTUFBTSxLQUFLLEdBQUcsSUFBSSxhQUFhLEVBQUUsQ0FBQztnQkFDbEMsS0FBSyxDQUFDLE9BQU8sR0FBRztvQkFDZCxVQUFVLEVBQUUsSUFBSSxRQUFRLEVBQUU7b0JBQzFCLFFBQVEsRUFBRSxJQUFJLFFBQVEsRUFBRTtpQkFDekIsQ0FBQztnQkFDRixNQUFNLFlBQVksR0FBRyxFQUFFLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQztnQkFDeEMsS0FBSyxDQUFDLFlBQVksQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDLENBQUM7Z0JBQ3RDLEtBQUssQ0FBQyxNQUFNLENBQUMsU0FBUyxFQUFFLFlBQVksQ0FBQyxDQUFDO2dCQUN0QyxNQUFNLEVBQUUsR0FBRyxJQUFJLGNBQWMsRUFBRSxDQUFDO2dCQUNoQyxFQUFFLENBQUMsWUFBWSxDQUFDLFNBQVMsRUFBRSxLQUFLLEVBQUUsRUFBRSxDQUFDLENBQUM7Z0JBQ3RDLEVBQUUsQ0FBQyxZQUFZLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxDQUFDO2dCQUNuQyxFQUFFLENBQUMsTUFBTSxDQUFDLFNBQVMsRUFBRSxLQUFLLEVBQUUsWUFBWSxDQUFDLENBQUM7Z0JBQzFDLEVBQUUsQ0FBQyw4QkFBOEIsQ0FBQyxFQUFFLENBQUMsQ0FBQztnQkFDdEMsVUFBVSxDQUFDLEdBQUcsRUFBRTtvQkFDZCxFQUFFLENBQUMsTUFBTSxDQUFDLFlBQVksR0FBRyxRQUFRLENBQUM7b0JBQ2xDLEVBQUUsQ0FBQyxlQUFlLEVBQUUsQ0FBQztnQkFDdkIsQ0FBQyxFQUFFLElBQUksQ0FBQyxDQUFDO2FBQ1Y7WUFFRCxJQUFJLDZCQUE2QixFQUFFO2dCQUNqQyxnRkFBZ0Y7Z0JBQ2hGLE1BQU0sRUFBRSxHQUFHLElBQUksUUFBUSxFQUFFLENBQUM7Z0JBQzFCLEVBQUUsQ0FBQyxZQUFZLENBQUMsU0FBUyxDQUFDLENBQUM7Z0JBQzNCLEVBQUUsQ0FBQyxNQUFNLENBQUMsU0FBUyxDQUFDLENBQUM7Z0JBQ3JCLFVBQVUsQ0FBQyxHQUFHLEVBQUU7b0JBQ2QsRUFBRSxDQUFDLE1BQU0sQ0FBQyxZQUFZLEdBQUcsUUFBUSxDQUFDO29CQUNsQyxFQUFFLENBQUMsZUFBZSxFQUFFLENBQUM7Z0JBQ3ZCLENBQUMsRUFBRSxJQUFJLENBQUMsQ0FBQzthQUNWO1lBRUQsV0FBVyxDQUFDLEtBQUssRUFBRSxDQUFDO1lBQ3BCLE9BQU8sQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDLENBQUM7UUFDN0IsQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDO0lBRUQsc0JBQXNCLENBQUMsUUFBYTtRQUNsQyxJQUFJLEdBQUcsR0FBRyxJQUFJLENBQUMsb0JBQW9CLENBQUMsR0FBRyxDQUFDLFFBQVEsQ0FBQyxDQUFDO1FBQ2xELEdBQUcsQ0FBQyxLQUFLLENBQUMsT0FBTyxHQUFHLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUM7SUFDekMsQ0FBQztJQUVELGVBQWUsQ0FBQyxRQUFhO1FBQzNCLElBQUksR0FBRyxHQUFHLElBQUksQ0FBQyxvQkFBb0IsQ0FBQyxHQUFHLENBQUMsUUFBUSxDQUFDLENBQUM7UUFDbEQsT0FBTyxHQUFHLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQztJQUMzQixDQUFDO0lBRUQsS0FBSyxDQUFDLHFCQUFxQixDQUFDLFFBQWE7UUFDdkMsSUFBSSxHQUFHLEdBQUcsSUFBSSxDQUFDLG9CQUFvQixDQUFDLEdBQUcsQ0FBQyxRQUFRLENBQUMsQ0FBQztRQUVsRCwyQkFBMkI7UUFDM0IsTUFBTSxTQUFTLEdBQUc7WUFDaEIsVUFBVSxFQUFFLElBQUksQ0FBQyxTQUFTLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxRQUFRLENBQUM7WUFDOUMsSUFBSSxFQUFFLE9BQU8sQ0FBQyxRQUFRO1lBQ3RCLFNBQVMsRUFBRSxRQUFRLEVBQUUsNEJBQTRCO1NBQzNDLENBQUM7UUFDVCxNQUFNLFFBQVEsR0FBRyxFQUFDLEVBQUUsRUFBRSxRQUFRLEVBQWlCLENBQUM7UUFFaEQsSUFBRztZQUNELE1BQU0sSUFBSSxDQUFDLHNCQUFzQixDQUFDLE9BQU8sQ0FBQyxRQUFRLEVBQUUsUUFBUSxFQUFFLFNBQVMsQ0FBQyxDQUFDO1NBQzFFO1FBQUEsT0FBTSxHQUFRLEVBQUMsR0FBRTtRQUVsQixpRUFBaUU7UUFDakUsd0RBQXdEO1FBQ3hELG9FQUFvRTtRQUVwRSxJQUFJLE1BQU0sR0FBRyxJQUFJLENBQUMsbUJBQW1CLENBQUMsUUFBUSxDQUFDLENBQUM7UUFFaEQsTUFBTSxJQUFJLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQztRQUMvQixJQUFJLENBQUMsbUJBQW1CLEVBQUUsQ0FBQztJQUM3QixDQUFDO0lBRUQsMEJBQTBCLENBQUMsSUFBWTtRQUNyQyxPQUFPLElBQUksQ0FBQyx5QkFBeUIsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDbEQsQ0FBQztJQUVELEtBQUssQ0FBQyxvQkFBb0I7UUFDeEIsSUFBRyxJQUFJLENBQUMsY0FBYyxFQUFDO1lBQ3JCLElBQUksQ0FBQyxjQUFjLENBQUMsS0FBSyxDQUFDLFFBQVEsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxRQUFRLENBQUMsQ0FBQyxFQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsUUFBUSxDQUFDLENBQUMsRUFBQyxJQUFJLENBQUMsVUFBVSxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsQ0FBQTtTQUN6SDtJQUNILENBQUM7SUFFRCxLQUFLLENBQUMsNEJBQTRCLENBQ2hDLFNBQWMsRUFDZCxXQUFnQixFQUNoQixJQUFzQyxFQUN0QyxPQUFnQixFQUNoQixXQUFvQjtRQUVwQiwwREFBMEQ7UUFDMUQsSUFBSSxJQUFJLEdBQUcsSUFBSSxDQUFDO1FBQ2hCLElBQUksR0FBRyxXQUFXLENBQUMsT0FBTyxFQUFFLENBQUM7UUFDN0IsSUFBSSxDQUFDLElBQUksRUFBRTtZQUNULE1BQU0sQ0FBQyxXQUFXLENBQUMsR0FBRyxNQUFNLElBQUksQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLGFBQWEsQ0FBQyxDQUFDLENBQUMsQ0FBQztZQUM1RCxJQUFJLEdBQUcsV0FBVyxDQUFDLE9BQU8sRUFBRSxDQUFDO1NBQzlCO1FBRUQsTUFBTSxTQUFTLEdBQUcsSUFBSSxDQUFDLFlBQVksQ0FBQyxzQkFBc0IsQ0FBQyxDQUFDO1FBQzVELElBQUksQ0FBQyxLQUFLLEVBQUUsQ0FBQztRQUNiLEVBQUU7UUFDRiwrRkFBK0Y7UUFDL0YsU0FBUyxDQUFDLGlCQUFpQixDQUFDLE9BQU8sR0FBRyxPQUFPLENBQUM7UUFDOUMsRUFBRTtRQUNGLCtDQUErQztRQUMvQyxTQUFTLENBQUMsTUFBTSxDQUFDLFNBQVMsR0FBRyxTQUFTLENBQUM7UUFDdkMsRUFBRTtRQUNGLHFEQUFxRDtRQUNyRCxTQUFTLENBQUMsTUFBTSxDQUFDLElBQUksR0FBRyxJQUFJLENBQUM7UUFDN0IsU0FBUyxDQUFDLEtBQUssQ0FBQyxRQUFRLEdBQUcsU0FBUyxDQUFDLENBQUMsZ0NBQWdDO1FBQ3RFLElBQUcsV0FBVyxFQUFDLEVBQUUsNkNBQTZDO1lBQzVELElBQUksQ0FBQyxJQUFJLENBQUMsWUFBWSxJQUFJLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxRQUFRLEVBQUU7Z0JBQ3JELElBQUk7b0JBQ0YsU0FBUyxDQUFDLEtBQUssQ0FBQyxJQUFJLEdBQUcsSUFBSSxDQUFDLFlBQVksQ0FBQyxJQUFJLElBQUksSUFBSSxDQUFDLFlBQVksQ0FBQyxFQUFFLENBQUM7aUJBQ3ZFO2dCQUFDLE9BQU8sQ0FBQyxFQUFFO29CQUNWLE9BQU8sQ0FBQyxHQUFHLENBQUMsc0RBQXNELENBQUMsQ0FBQztpQkFDckU7Z0JBQ0QsSUFBSSxDQUFDLFlBQVksR0FBRyxTQUFTLENBQUMsS0FBSyxDQUFDO2FBQ3JDO1NBQ0Y7YUFBSSxFQUFDLHFFQUFxRTtZQUN6RSxPQUFPLENBQUMsR0FBRyxDQUFDLGtCQUFrQixDQUFDLENBQUM7WUFDaEMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxTQUFTLENBQUMsQ0FBQztZQUN2QixPQUFPLENBQUMsR0FBRyxDQUFDLFNBQVMsQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLENBQUM7WUFDbEMsSUFBSSxDQUFDLFlBQVksR0FBRyxTQUFTLENBQUMsS0FBSyxDQUFDO1NBQ3JDO1FBRUQsT0FBTyxTQUFTLENBQUM7SUFDbkIsQ0FBQztJQUVELHlCQUF5QjtRQUN2QixJQUFJLENBQUMsWUFBWSxDQUFDLFFBQVEsQ0FBQyxpQkFBaUIsQ0FBQyxPQUFPLEdBQUcsS0FBSyxDQUFDO1FBQzdELElBQUksQ0FBQyxZQUFZLENBQUMsUUFBUSxDQUFDLGlCQUFpQixDQUFDLE9BQU8sRUFBRSxDQUFDO1FBQ3ZELElBQUksQ0FBQyxZQUFZLENBQUMsUUFBUSxHQUFHLElBQUksQ0FBQztJQUNwQyxDQUFDO0lBRUQsaUJBQWlCO1FBQ2YsSUFBSSxDQUFDLHNCQUFzQixDQUFDLGlCQUFpQixFQUFFLENBQUM7SUFDbEQsQ0FBQzs7OEdBbDlEVSxpQkFBaUIsa0JBcUpsQixRQUFRO2tIQXJKUCxpQkFBaUIsY0FGaEIsTUFBTTsyRkFFUCxpQkFBaUI7a0JBSDdCLFVBQVU7bUJBQUM7b0JBQ1YsVUFBVSxFQUFFLE1BQU07aUJBQ25COzswQkFzSkksTUFBTTsyQkFBQyxRQUFRIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtJbmplY3QsIEluamVjdGFibGUsIE5nWm9uZX0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQge0FjdGl2YXRlZFJvdXRlLCBSb3V0ZXJ9IGZyb20gJ0Bhbmd1bGFyL3JvdXRlcic7XG5pbXBvcnQge1N1YmplY3R9IGZyb20gJ3J4anMnO1xuLy9pbXBvcnQgKiBhcyBzZXJpYWxpanNlIGZyb20gXCJzZXJpYWxpanNlXCI7XG5pbXBvcnQge1xuICBnZXREaXN0YW5jZUJldHdlZW5Ud29Qb2ludHMsXG4gIHBvaVR5cGVUb1N0cmluZyxcbiAgd2FpdCxcbn0gZnJvbSAnLi4vaGVscGVycy5zZXJ2aWNlJztcbmltcG9ydCB7TWF0dGVydGFnRGF0YX0gZnJvbSAnLi4vbWF0dGVydGFnRGF0YSc7XG5pbXBvcnQge1xuICBEYk9iamVjdFR5cGUsXG4gIEZlYXR1cmVUeXBlLFxuICBJT2JqZWN0M0QsXG4gIE1hdHRlcnRhZ0FjdGlvbk1vZGUsXG4gIFBPSSxcbiAgUG9pVHlwZSxcbiAgU3BNb2R1bGUsXG4gIFRhZ0FjdGlvbixcbiAgVmlld2VySW50ZXJhY3Rpb25zLFxufSBmcm9tICcuLi90eXBlcy5zZXJ2aWNlJztcbmltcG9ydCB7T2JqZWN0M0R9IGZyb20gJ3RocmVlJztcbmltcG9ydCB7QmFzZVRhZ1NlcnZpY2V9IGZyb20gJy4vdGFnLnNlcnZpY2UnO1xuaW1wb3J0IHtCYXNlVmlzaWJpbGl0eVNlcnZpY2V9IGZyb20gJy4vYmFzZVZpc2liaWxpdHkuc2VydmljZSc7XG5pbXBvcnQge0NvbmZpZ30gZnJvbSAnLi4vY29uZmlnJztcbmltcG9ydCB7Q2FtZXJhTW9kZX0gZnJvbSAnLi4vdHlwZXMuc2VydmljZSc7XG5pbXBvcnQge0lTY2VuZU5vZGUsIENvbXBvbmVudE91dHB1dH0gZnJvbSBcIi4uL21hdHRlcnBvcnQtZXh0ZW5zaW9ucy9zY2VuZS1jb21wb25lbnQvU2NlbmVDb21wb25lbnRcIjtcbmltcG9ydCB7U2VjdXJpdHlDYW1lcmF9IGZyb20gJy4uL21hdHRlcnBvcnQtZXh0ZW5zaW9ucy9zZWN1cml0eS1jYW1lcmEvU2VjdXJpdHlDYW1lcmEnO1xuaW1wb3J0IHtOZXN0VGhlcm1vc3RhdH0gZnJvbSAnLi4vbWF0dGVycG9ydC1leHRlbnNpb25zL25lc3QtdGhlcm1vc3RhdC9OZXN0VGhlcm1vc3RhdCc7XG5pbXBvcnQge1BsYW5lUmVuZGVyZXJ9IGZyb20gJy4uL21hdHRlcnBvcnQtZXh0ZW5zaW9ucy9uZXN0LXRoZXJtb3N0YXQvUGxhbmVSZW5kZXJlcic7XG5pbXBvcnQge0NhbnZhc1JlbmRlcmVyfSBmcm9tIFwiLi4vbWF0dGVycG9ydC1leHRlbnNpb25zL25lc3QtdGhlcm1vc3RhdC9DYW52YXNSZW5kZXJlclwiO1xuaW1wb3J0IHtWaWRlb1JlbmRlcmVyfSBmcm9tIFwiLi4vbWF0dGVycG9ydC1leHRlbnNpb25zL3ZpZGVvLXJlbmRlcmVyL1ZpZGVvUmVuZGVyZXJcIjtcbmltcG9ydCB7SGxzTG9hZGVyfSBmcm9tIFwiLi4vbWF0dGVycG9ydC1leHRlbnNpb25zL2hzbC1sb2FkZXIvSGxzTG9hZGVyXCI7XG5pbXBvcnQge1R2UGxheWVyfSBmcm9tIFwiLi4vbWF0dGVycG9ydC1leHRlbnNpb25zL3R2LXBsYXllci9UdlBsYXllclwiO1xuXG4vLyBpbXBvcnQge0NhbnZhc0ltYWdlfSBmcm9tIFwiLi4vbWF0dGVycG9ydC1leHRlbnNpb25zL25lc3QtdGhlcm1vc3RhdC9DYW52YXNJbWFnZVwiO1xuXG4vKipcbiAqIEN1c3RvbSBUaHJlZWpzIE9iamVjdCAzRCBpbnRlcmZhY2VcbiAqL1xuaW50ZXJmYWNlIFRocmVlSlNPYmplY3QzRCB7XG4gIGlkOiBzdHJpbmc7XG4gIHV1aWQ/OiBzdHJpbmc7XG4gIHBvc2l0aW9uPzogeyB4OiBudW1iZXIsIHk6IG51bWJlciwgejogbnVtYmVyIH1cbiAgcm90YXRpb24/OiB7IHg6IG51bWJlciwgeTogbnVtYmVyLCB6OiBudW1iZXIgfVxuICBzY2FsZT86IHsgeDogbnVtYmVyLCB5OiBudW1iZXIsIHo6IG51bWJlciB9XG59XG5cbmRlY2xhcmUgZ2xvYmFsIHtcbiAgaW50ZXJmYWNlIFdpbmRvdyB7XG4gICAgTVBfU0RLOiB7IGNvbm5lY3Q6IEZ1bmN0aW9uIH07XG4gIH1cbn1cblxuQEluamVjdGFibGUoe1xuICBwcm92aWRlZEluOiAncm9vdCcsXG59KVxuZXhwb3J0IGNsYXNzIE1hdHRlcnBvcnRTZXJ2aWNlIHtcblxuICBwcml2YXRlIHNsb3RzOiBhbnlbXSA9IFtdOy8vU2xvdE5vZGVbXSA9IFtdO1xuXG4gIHByaXZhdGUgbm9kZXM6IElTY2VuZU5vZGVbXSA9IFtdO1xuXG4gIHB1YmxpYyBzZGs6IGFueTtcblxuICBwcml2YXRlIGNvbnRhaW5lcjogYW55O1xuXG4gIC8vIFBvc2l0aW9uIGNhbWVyYVxuICBwcml2YXRlIHBvc2VNYXR0ZXJwb3J0OiBhbnk7XG5cbiAgcHVibGljIHBvc2VDYW1lcmE6IHsgcm90YXRpb246IGFueTsgcG9zaXRpb246IGFueTsgc3dlZXA6IGFueSB9O1xuICBwdWJsaWMgbGFzdENhbWVyYVBvc2l0aW9uOiBhbnkgPSB7eDowLjAseTowLjAsejowLjB9O1xuXG4gIHByaXZhdGUgYXppbXV0aGFsQ3Jvd246YW55O1xuICAvLyBQb2ludGVyIHRyaWNrXG4gIHByaXZhdGUgcG9pbnRlckJ1dHRvbjogYW55O1xuXG4gIC8vIERpc3BsYXkgYW5kIGdldCBjdXJyZW50IHBvc2l0aW9uIG9mIGN1cnNvciAoZm9yIEFkbWlucyBvbmx5KVxuICBwcml2YXRlIGdldEN1cnNvclBvc2l0aW9uQnV0dG9uOiBhbnk7XG4gIHByaXZhdGUgY3Vyc29yUG9zaXRpb25CdXR0b25EaXNwbGF5ZWQgPSBmYWxzZTtcbiAgcHJpdmF0ZSBpbnRlcnZhbEN1cnNvclBvaW50ZXJQb3NpdGlvbjogYW55O1xuICBwcml2YXRlIHRleHREaXNwbGF5Q3Vyc29yUG9zaXRpb25QYW5lbDogYW55O1xuXG4gIHByaXZhdGUgb2xkUG9zZU1hdHRlcnBvcnRQb3NpdGlvbjogYW55O1xuICAvLyBNZWFzdXJlIG1vZGVcbiAgcHJpdmF0ZSBpc01lYXN1cmVNb2RlT24gPSBmYWxzZTtcblxuICBwcml2YXRlIGludGVyYWN0aW9uTW9kZTogbnVtYmVyID0gVmlld2VySW50ZXJhY3Rpb25zLkRFRkFVTFQ7XG5cbiAgLy8gTGlzdCBvZiBjcmVhdGVkIE1hdHRlcnRhZyBJRHMgaW4gdGhlIGN1cnJlbnQgdmlld2VyIHNlc3Npb25cbiAgcHJpdmF0ZSBtYXR0ZXJ0YWdJRHM6IEFycmF5PHN0cmluZz4gPSBbXTtcblxuICAvLyBEaWN0aW9ubmFyeSBvZiBNYXR0ZXJ0YWdJRCBhbmQgaXRzIGRhdGEgKG1hdHRlcnRhZ0RhdGEpXG4gIHByaXZhdGUgZGljdGlvbm5hcnlUYWdzOiBNYXA8c3RyaW5nLCBNYXR0ZXJ0YWdEYXRhPiA9IG5ldyBNYXAoKTtcblxuICBwcml2YXRlIGRpY3Rpb25uYXJ5T2JqZWN0czNEOiBNYXA8c3RyaW5nLCBhbnk+ID0gbmV3IE1hcCgpO1xuXG4gIHByaXZhdGUgZGljdGlvbm5hcnlTY2VuZU9iamVjdHMzRDogTWFwPHN0cmluZywgYW55PiA9IG5ldyBNYXAoKTtcblxuICBwdWJsaWMgdGhyZWVKU1NjZW5lOiBhbnk7IC8vIGdsb2JhbCByb290IHNjZW5lIChub3QgdXNlZCBub3chKVxuXG4gIHByaXZhdGUgbGFzdE1lYXN1cmUgPSBbXTtcblxuICBwcml2YXRlIGRpc3RhbmNlc0xhc3RNZWFzdXJlOiBudW1iZXJbXSA9IFtdO1xuXG4gIHByaXZhdGUgcmVzb2x1dGlvbiA9IHtcbiAgICB3aWR0aDogNTAwLFxuICAgIGhlaWdodDogNjAwLFxuICB9O1xuXG4gIHByaXZhdGUgdmlzaWJpbGl0eSA9IHtcbiAgICBtYXR0ZXJ0YWdzOiBmYWxzZSxcbiAgICBzd2VlcHM6IHRydWUsXG4gIH07XG5cbiAgcHVibGljIHRhZ3NBdHRhY2htZW50czogT2JqZWN0ID0ge307XG5cbiAgcHJpdmF0ZSBsYXN0U2NyZWVuc2hvdFVyaTogYW55O1xuXG4gIHB1YmxpYyBzd2VlcHM6IEFycmF5PHN0cmluZz4gfCBudWxsO1xuXG4gIHB1YmxpYyBjdXJyZW50U3dlZXA6IFN1YmplY3Q8c3RyaW5nPiA9IG5ldyBTdWJqZWN0KCk7XG5cbiAgLy9jYW1lcmEgcG9zaXRpb24gd2l0aCByb3RhdGlvblxuICBwdWJsaWMgY3VycmVudENhbWVyYVBvc2U6IFN1YmplY3Q8YW55PiA9IG5ldyBTdWJqZWN0KCk7XG5cbiAgcHJpdmF0ZSBmbG9vcnM/OiBBcnJheTx7IGlkOiBzdHJpbmc7IG5hbWU6IHN0cmluZzsgc2VxdWVuY2U6IG51bWJlciB9PiB8IG51bGw7XG5cbiAgcHJpdmF0ZSBfY3VycmVudFNwYWNlSUQ6IHN0cmluZztcblxuICBwcml2YXRlIGxhc3RPYmplY3QzRDogYW55OyAvLyBUaHJlZSBKUyBvYmplY3RcblxuICBwcml2YXRlIGN1cnJlbnRGbG9vcjtcblxuICBwdWJsaWMgZ2V0IGN1cnJlbnRTcGFjZUlEKCk6IHN0cmluZyB7XG4gICAgcmV0dXJuIHRoaXMuX2N1cnJlbnRTcGFjZUlEO1xuICB9XG5cbiAgcHVibGljIHNldCBjdXJyZW50U3BhY2VJRCh2YWx1ZTogc3RyaW5nKSB7XG4gICAgdGhpcy5fY3VycmVudFNwYWNlSUQgPSB2YWx1ZTtcbiAgfVxuXG4gIHRpbWVyUG9pbnRlcjogYW55O1xuXG4gIGZvcmJpZGRlblN3ZWVwczogc3RyaW5nW10gPSBbXTtcblxuICBwdWJsaWMgdGFnQWN0aW9uOiBTdWJqZWN0PHsgYWN0aW9uOiBzdHJpbmc7IGRhdGE6IHN0cmluZyB9PiA9IG5ldyBTdWJqZWN0KCk7XG5cbiAgcHVibGljIG1hdHRlcnRhZ1RvRm9sbG93OiBzdHJpbmcgfCBudWxsO1xuXG4gIHRhZ1NlcnZpY2U6IEJhc2VUYWdTZXJ2aWNlO1xuXG4gIGNvbmZpZzogQ29uZmlnO1xuXG4gIHB1YmxpYyBpblRyYW5zaXRpb25Nb2RlID0gZmFsc2U7XG5cbiAgcHVibGljIGluVHJhbnNpdGlvblN3ZWVwID0gZmFsc2U7XG5cbiAgcHJpdmF0ZSBub0xpZ2h0Rm9yT2JqZWN0cyA9IHRydWU7XG5cbiAgcHVibGljIGN1cnJlbnRDYW1lcmFNb2RlOiBDYW1lcmFNb2RlID0gQ2FtZXJhTW9kZS5PVVRTSURFO1xuXG4gIHB1YmxpYyBvbkNhbWVyYU1vZGVDaGFuZ2VkID0gbmV3IFN1YmplY3Q8Q2FtZXJhTW9kZT4oKTtcblxuICBwdWJsaWMgb25Hb1RvVGFnID0gbmV3IFN1YmplY3Q8c3RyaW5nPigpO1xuXG4gIHRhZ01lc3Nlbmdlck9uID0gZmFsc2U7XG5cbiAgU1BNb2R1bGU6IFNwTW9kdWxlO1xuXG4gIHB1YmxpYyBvYmplY3RDb250cm9sOiBhbnk7XG5cbiAgcHJpdmF0ZSBzZWN1cml0eUNhbWVyYUFuaW1hdG9yOiBhbnk7XG5cbiAgLyoqXG4gICAqIEFjdGlvbnMgb24gbGVmdCBjbGljayB3aGVuIHBvc2l0aW9uaW5nIG1hdHRlcnRhZyBpbiB2aXNpdFxuICAgKi9cbiAgcG9pbnRlckxlZnRDbGlja0hhbmRsZXIgPSAoKSA9PiB7XG4gICAgaWYgKHRoaXMubWF0dGVydGFnVG9Gb2xsb3cpIHtcbiAgICAgIGNvbnN0IG1hdHRlcnRhZ0RhdGEgPSB0aGlzLmRpY3Rpb25uYXJ5VGFncy5nZXQodGhpcy5tYXR0ZXJ0YWdUb0ZvbGxvdyk7XG4gICAgICBtYXR0ZXJ0YWdEYXRhLnNldFBvc2l0aW9uKHsuLi50aGlzLnBvc2VNYXR0ZXJwb3J0LnBvc2l0aW9ufSk7IC8vIGNvcHkhISBub3QgdGhlIHJlZmVyZW5jZVxuICAgICAgbWF0dGVydGFnRGF0YS5zZXROb3JtYWwoey4uLnRoaXMucG9zZU1hdHRlcnBvcnQubm9ybWFsfSk7IC8vIGNvcHkhISBub3QgdGhlIHJlZmVyZW5jZVxuICAgICAgdGhpcy5kaWN0aW9ubmFyeVRhZ3Muc2V0KHRoaXMubWF0dGVydGFnVG9Gb2xsb3csIG1hdHRlcnRhZ0RhdGEpO1xuICAgICAgdGhpcy51cGRhdGVNYXR0ZXJUYWdDb250ZW50Rm9yVGFnSUQodGhpcy5tYXR0ZXJ0YWdUb0ZvbGxvdyk7XG4gICAgfVxuICAgIHRoaXMub25WYWxpZGF0ZWRNYXR0ZXJ0YWcoKTtcbiAgfTtcblxuICBwb2ludGVyUmlnaHRDbGlja0hhbmRsZXIgPSAoZSkgPT4ge1xuICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICB0aGlzLmNhbmNlbEZvbGxvd2luZ0N1cnNvcigpO1xuICAgIGFsZXJ0KCdhY3Rpb24gY2FuY2VsbGVkJyk7XG4gIH07XG5cbiAgcG9pbnRlck1pZGRsZUNsaWNrSGFuZGxlciA9IChlKSA9PiB7XG4gICAgdGhpcy50ZXh0RGlzcGxheUN1cnNvclBvc2l0aW9uUGFuZWwuaW5uZXJIVE1MID0gYHBvc2l0aW9uOlxuICAgICAgICR7dGhpcy5wb2ludFRvU3RyaW5nKHRoaXMucG9zZU1hdHRlcnBvcnQucG9zaXRpb24pfVxcblxuICAgICAgIG5vcm1hbDpcbiAgICAgICAke3RoaXMucG9pbnRUb1N0cmluZyh0aGlzLnBvc2VNYXR0ZXJwb3J0Lm5vcm1hbCl9XFxuXG4gICAgICAgZmxvb3JJZDpcbiAgICAgICAke3RoaXMucG9zZU1hdHRlcnBvcnQuZmxvb3JJZH1gO1xuICAgIC8vIHRoaXMudGV4dERpc3BsYXlDdXJzb3JQb3NpdGlvblBhbmVsLnN0eWxlLmRpc3BsYXkgPSAndmlzaWJsZSc7XG4gICAgdGhpcy5nZXRDdXJzb3JQb3NpdGlvbkJ1dHRvbi5zdHlsZS5kaXNwbGF5ID0gJ25vbmUnO1xuICB9XG5cbiAgY29uc3RydWN0b3IoXG4gICAgQEluamVjdCgnY29uZmlnJykgY29uZmlnOiBDb25maWcsXG4gICAgcHJpdmF0ZSByb3V0ZXI6IFJvdXRlcixcbiAgICBwcml2YXRlIGFjdGl2ZVJvdXRlOiBBY3RpdmF0ZWRSb3V0ZSxcbiAgICBwcml2YXRlIHZpc2liaWxpdHlTZXJ2aWNlOiBCYXNlVmlzaWJpbGl0eVNlcnZpY2UsXG4gICAgcHJpdmF0ZSBuZ1pvbmU6IE5nWm9uZVxuICApIHtcbiAgICB0aGlzLmNvbmZpZyA9IGNvbmZpZztcblxuICAgIC8vIFRPRE86IG9ubHkgZm9yIGRldiFcbiAgICBpZiAoISF0aGlzLmdldEN1cnNvclBvc2l0aW9uQnV0dG9uICYmXG4gICAgICAoZG9jdW1lbnQubG9jYXRpb24uaHJlZi5pbmRleE9mKCdkZXYnKSAhPT0gLTEgfHwgZG9jdW1lbnQubG9jYXRpb24uaHJlZi5pbmRleE9mKCdsb2NhbGhvc3QnKSAhPT0gLTEpKSB7XG4gICAgICB0aGlzLmludGVydmFsQ3Vyc29yUG9pbnRlclBvc2l0aW9uID0gc2V0SW50ZXJ2YWwoKCkgPT4ge1xuICAgICAgICBpZiAoIXRoaXMucG9zZU1hdHRlcnBvcnQpIHtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBuZXh0U2hvdyA9IHRoaXMucG9zZU1hdHRlcnBvcnQudGltZSArIDEwMDA7XG4gICAgICAgIGlmIChuZXcgRGF0ZSgpLmdldFRpbWUoKSA+IG5leHRTaG93KSB7XG4gICAgICAgICAgaWYgKHRoaXMuY3Vyc29yUG9zaXRpb25CdXR0b25EaXNwbGF5ZWQpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBjb25zdCBzaXplID0ge1xuICAgICAgICAgICAgdzogdGhpcy5jb250YWluZXIuY2xpZW50V2lkdGgsXG4gICAgICAgICAgICBoOiB0aGlzLmNvbnRhaW5lci5jbGllbnRIZWlnaHQsXG4gICAgICAgICAgfTtcbiAgICAgICAgICBjb25zdCBjb29yZCA9IHRoaXMuc2RrLkNvbnZlcnNpb24ud29ybGRUb1NjcmVlbih0aGlzLnBvc2VNYXR0ZXJwb3J0LnBvc2l0aW9uLCB0aGlzLnBvc2VDYW1lcmEsIHNpemUpO1xuICAgICAgICAgIHRoaXMuZ2V0Q3Vyc29yUG9zaXRpb25CdXR0b24uc3R5bGUubGVmdCA9IGAke2Nvb3JkLnggLSAyNX1weGA7XG4gICAgICAgICAgdGhpcy5nZXRDdXJzb3JQb3NpdGlvbkJ1dHRvbi5zdHlsZS50b3AgPSBgJHtjb29yZC55IC0gMjJ9cHhgO1xuICAgICAgICAgIHRoaXMuZ2V0Q3Vyc29yUG9zaXRpb25CdXR0b24uc3R5bGUuZGlzcGxheSA9ICdibG9jayc7XG4gICAgICAgICAgLy8gdGhpcy50ZXh0RGlzcGxheUN1cnNvclBvc2l0aW9uUGFuZWwuc3R5bGUuZGlzcGxheSA9ICdub25lJztcbiAgICAgICAgICB0aGlzLmN1cnNvclBvc2l0aW9uQnV0dG9uRGlzcGxheWVkID0gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgfSwgNTAwKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogSW5pdGlhbGl6ZXMgTWF0dGVycG9ydCBhbmQgYWxsIGxpc3RlbmVycy9kYXRhXG4gICAqIEBwYXJhbSB0YWdTZXJ2aWNlIEJhc2VUYWdTZXJ2aWNlICh0byBpbmplY3QgaHRtbClcbiAgICogQHBhcmFtIG1vZHVsZSBTcE1vZHVsZSAoTXVzZXVtLCBJbW1vKSB0byBzdWJzY3JpYmUgb25seSB0byBuZWVkZWQgZnVuY3Rpb25ubmFsaXRpZXNcbiAgICogQHJldHVybnMgYm9vbGVhblxuICAgKi9cbiAgYXN5bmMgaW5pdFNkayhcbiAgICB0YWdTZXJ2aWNlOiBCYXNlVGFnU2VydmljZSxcbiAgICBtb2R1bGU6IFNwTW9kdWxlID0gU3BNb2R1bGUuSU1NT1xuICApOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICBpZiAodGhpcy5zZGspIHtcbiAgICAgIC8vIGNsZWFuIGlmIHNkayBpcyBydW5uaW5nIGFscmVhZHlcbiAgICAgIGF3YWl0IHRoaXMuYWN0aW9uX2RlbGV0ZV9hbGxfbWF0dGVydGFncygpO1xuICAgIH1cbiAgICB0aGlzLnRhZ1NlcnZpY2UgPSB0YWdTZXJ2aWNlO1xuICAgIHRoaXMuU1BNb2R1bGUgPSBtb2R1bGU7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgIC8vIFJldHJpZXZlIERPTSBlbGVtZW50c1xuICAgICAgdGhpcy5wb2ludGVyQnV0dG9uID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvcihcbiAgICAgICAgJyN2aWV3ZXItcG9pbnRlci10cmljaydcbiAgICAgICkgYXMgSFRNTEVsZW1lbnQ7XG4gICAgICB0aGlzLmNvbnRhaW5lciA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoJyN2aWV3ZXItbW9kdWxlJykgYXMgSFRNTEVsZW1lbnQ7XG4gICAgICBjb25zdCBpZnJhbWUgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKFxuICAgICAgICAnI3ZpZXdlci1tb2R1bGUnXG4gICAgICApIGFzIEhUTUxJRnJhbWVFbGVtZW50O1xuICAgICAgaWYgKCFpZnJhbWUpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICAvLyBBZGQgbGlzdGVuZXJzXG4gICAgICBpZiAodGhpcy5wb2ludGVyQnV0dG9uKSB7XG4gICAgICAgIHRoaXMucG9pbnRlckJ1dHRvbi5hZGRFdmVudExpc3RlbmVyKFxuICAgICAgICAgICdjbGljaycsXG4gICAgICAgICAgdGhpcy5wb2ludGVyTGVmdENsaWNrSGFuZGxlclxuICAgICAgICApO1xuICAgICAgICAvLyBjYW5jZWwgb24gcmlnaHQgY2xpY2tcbiAgICAgICAgdGhpcy5wb2ludGVyQnV0dG9uLmFkZEV2ZW50TGlzdGVuZXIoXG4gICAgICAgICAgJ2NvbnRleHRtZW51JyxcbiAgICAgICAgICB0aGlzLnBvaW50ZXJSaWdodENsaWNrSGFuZGxlclxuICAgICAgICApO1xuICAgICAgfVxuICAgICAgLy8gUmV0cmlldmUgRE9NIGVsZW1lbnRzXG4gICAgICB0aGlzLmdldEN1cnNvclBvc2l0aW9uQnV0dG9uID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvcihcbiAgICAgICAgJyNidXR0b24nXG4gICAgICApIGFzIEhUTUxFbGVtZW50O1xuICAgICAgdGhpcy50ZXh0RGlzcGxheUN1cnNvclBvc2l0aW9uUGFuZWwgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKFxuICAgICAgICAnI3RleHQnXG4gICAgICApIGFzIEhUTUxFbGVtZW50O1xuICAgICAgaWYgKHRoaXMuZ2V0Q3Vyc29yUG9zaXRpb25CdXR0b24pIHtcbiAgICAgICAgLy8gZ2V0IHBvc2l0aW9uIG9uIE1hdHRlcnBvcnQgXCJtb2RlbFwiIG9uIG1pZGRsZSBjbGlja1xuICAgICAgICB0aGlzLmdldEN1cnNvclBvc2l0aW9uQnV0dG9uLmFkZEV2ZW50TGlzdGVuZXIoXG4gICAgICAgICAgJ2NsaWNrJyxcbiAgICAgICAgICB0aGlzLnBvaW50ZXJNaWRkbGVDbGlja0hhbmRsZXJcbiAgICAgICAgKTtcbiAgICAgIH1cblxuICAgICAgLy8gTG9hZCBTREtcbiAgICAgIGNvbnNvbGUubG9nKCdMb2FkaW5nIE1hdHRlcnBvcnQgU0RLJyk7XG4gICAgICBjb25zdCBzaG93Y2FzZVdpbmRvdyA9IGlmcmFtZS5jb250ZW50V2luZG93O1xuICAgICAgaWZyYW1lLmFkZEV2ZW50TGlzdGVuZXIoXG4gICAgICAgICdsb2FkJyxcbiAgICAgICAgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICB0aGlzLnNkayA9IGF3YWl0IHNob3djYXNlV2luZG93Lk1QX1NESy5jb25uZWN0KFxuICAgICAgICAgICAgICBzaG93Y2FzZVdpbmRvdyxcbiAgICAgICAgICAgICAgJ3FuOXdzYXN1eTVoMmZ6cmJybjFuenIwaWQnLFxuICAgICAgICAgICAgICAnMy41J1xuICAgICAgICAgICAgKTtcbiAgICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICBjb25zb2xlLmVycm9yKGUpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIC8vIExvYWQgTWF0dGVydGFnIGljb25zIGFuZCBjdXN0b20gc3Vic2NyaXB0aW9uc1xuICAgICAgICAgIHN3aXRjaCAobW9kdWxlKSB7XG4gICAgICAgICAgICBjYXNlIFNwTW9kdWxlLklNTU86XG4gICAgICAgICAgICAgIHRoaXMuc2RrLkFzc2V0LnJlZ2lzdGVyVGV4dHVyZShcbiAgICAgICAgICAgICAgICAnaWNvbi10aWNrZXQnLFxuICAgICAgICAgICAgICAgIHRoaXMuY29uZmlnLm15X2NvbmZpZy5pY29uX3RpY2tldFxuICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICB0aGlzLnNkay5Bc3NldC5yZWdpc3RlclRleHR1cmUoXG4gICAgICAgICAgICAgICAgJ2ljb24tZXF1aXBtZW50JyxcbiAgICAgICAgICAgICAgICB0aGlzLmNvbmZpZy5teV9jb25maWcuaWNvbl9lcXVpcG1lbnRcbiAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgdGhpcy5zZGsuQXNzZXQucmVnaXN0ZXJUZXh0dXJlKFxuICAgICAgICAgICAgICAgICdpY29uLW1lYXN1cmUnLFxuICAgICAgICAgICAgICAgIHRoaXMuY29uZmlnLm15X2NvbmZpZy5pY29uX21lYXN1cmVcbiAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgdGhpcy5zZGsuQXNzZXQucmVnaXN0ZXJUZXh0dXJlKFxuICAgICAgICAgICAgICAgICdpY29uLWRhdGEnLFxuICAgICAgICAgICAgICAgIHRoaXMuY29uZmlnLm15X2NvbmZpZy5pY29uX2RhdGFcbiAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgdGhpcy5zZGsuQXNzZXQucmVnaXN0ZXJUZXh0dXJlKFxuICAgICAgICAgICAgICAgICdpY29uLW9iamVjdDNkJyxcbiAgICAgICAgICAgICAgICB0aGlzLmNvbmZpZy5teV9jb25maWcuaWNvbl9vYmplY3QzZFxuICAgICAgICAgICAgICApO1xuXG4gICAgICAgICAgICAgIHRoaXMuc2RrLk1lYXN1cmVtZW50cy5kYXRhLnN1YnNjcmliZSh7XG4gICAgICAgICAgICAgICAgb25BZGRlZDogZnVuY3Rpb24gKFxuICAgICAgICAgICAgICAgICAgaW5kZXg6IGFueSxcbiAgICAgICAgICAgICAgICAgIGl0ZW06IHsgcG9pbnRzOiBhbnkgfSxcbiAgICAgICAgICAgICAgICAgIGNvbGxlY3Rpb246IGFueVxuICAgICAgICAgICAgICAgICkge1xuICAgICAgICAgICAgICAgICAgLy8gY29uc29sZS5sb2coXG4gICAgICAgICAgICAgICAgICAvLyAgICAgXCJpdGVtIGFkZGVkIHRvIHRoZSBjb2xsZWN0aW9uXCIsXG4gICAgICAgICAgICAgICAgICAvLyAgICAgaW5kZXgsXG4gICAgICAgICAgICAgICAgICAvLyAgICAgaXRlbSxcbiAgICAgICAgICAgICAgICAgIC8vICk7XG4gICAgICAgICAgICAgICAgICAvLyB0aGlzLm1lYXN1cmVtZW50c1tpbmRleF0gPSBpdGVtO1xuICAgICAgICAgICAgICAgICAgdGhpcy5sYXN0TWVhc3VyZSA9IGl0ZW0ucG9pbnRzO1xuICAgICAgICAgICAgICAgIH0uYmluZCh0aGlzKSxcbiAgICAgICAgICAgICAgICBvbkNvbGxlY3Rpb25VcGRhdGVkOiBmdW5jdGlvbiAoY29sbGVjdGlvbjogYW55KSB7XG4gICAgICAgICAgICAgICAgICAvLyBjb25zb2xlLmxvZygndGhlIGVudGlyZSB1cC10by1kYXRlIGNvbGxlY3Rpb24nLCBjb2xsZWN0aW9uKTtcbiAgICAgICAgICAgICAgICAgIHRoaXMuZ2V0RGlzdGFuY2VGb3JMYXN0TWVhc3VyZW1lbnQoKTtcbiAgICAgICAgICAgICAgICB9LmJpbmQodGhpcyksXG4gICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICB0aGlzLnNkay5NZWFzdXJlbWVudHMubW9kZS5zdWJzY3JpYmUoXG4gICAgICAgICAgICAgICAgZnVuY3Rpb24gKG1lYXN1cmVtZW50TW9kZVN0YXRlOiB7IGFjdGl2ZTogYW55IH0pIHtcbiAgICAgICAgICAgICAgICAgIC8vIG1lYXN1cmVtZW50IG1vZGUgc3RhdGUgaGFzIGNoYW5nZWRcbiAgICAgICAgICAgICAgICAgIHRoaXMuaXNNZWFzdXJlTW9kZU9uID0gbWVhc3VyZW1lbnRNb2RlU3RhdGUuYWN0aXZlO1xuICAgICAgICAgICAgICAgICAgLy8gY29uc29sZS5sb2coJ0lzIG1lYXN1cmVtZW50IG1vZGUgY3VycmVudGx5IGFjdGl2ZT8gJywgbWVhc3VyZW1lbnRNb2RlU3RhdGUuYWN0aXZlKTtcbiAgICAgICAgICAgICAgICB9LmJpbmQodGhpcylcbiAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIFNwTW9kdWxlLk1VU0VVTTpcbiAgICAgICAgICAgICAgdGhpcy5zZGsuQXNzZXQucmVnaXN0ZXJUZXh0dXJlKFxuICAgICAgICAgICAgICAgICdpY29uLWRhdGEnLFxuICAgICAgICAgICAgICAgIHRoaXMuY29uZmlnLm15X2NvbmZpZy5pY29uX2RhdGFcbiAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIFNwTW9kdWxlLkhPVEVMOlxuICAgICAgICAgICAgICB0aGlzLnNkay5Bc3NldC5yZWdpc3RlclRleHR1cmUoXG4gICAgICAgICAgICAgICAgJ2ljb25fcm9vbV9hdmFpbGFibGUnLFxuICAgICAgICAgICAgICAgIHRoaXMuY29uZmlnLm15X2NvbmZpZy5pY29uX3Jvb21fYXZhaWxhYmxlXG4gICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgIHRoaXMuc2RrLkFzc2V0LnJlZ2lzdGVyVGV4dHVyZShcbiAgICAgICAgICAgICAgICAnaWNvbl9yb29tX3VuYXZhaWxhYmxlJyxcbiAgICAgICAgICAgICAgICB0aGlzLmNvbmZpZy5teV9jb25maWcuaWNvbl9yb29tX3VuYXZhaWxhYmxlXG4gICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgIHRoaXMuc2RrLkFzc2V0LnJlZ2lzdGVyVGV4dHVyZShcbiAgICAgICAgICAgICAgICAnaWNvbl9yb29tX2Nob3NlbicsXG4gICAgICAgICAgICAgICAgdGhpcy5jb25maWcubXlfY29uZmlnLmljb25fcm9vbV9jaG9zZW5cbiAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgdGhpcy5zZGsuQXNzZXQucmVnaXN0ZXJUZXh0dXJlKFxuICAgICAgICAgICAgICAgICdpY29uX3Jvb21fdmlld2VkJyxcbiAgICAgICAgICAgICAgICB0aGlzLmNvbmZpZy5teV9jb25maWcuaWNvbl9yb29tX3ZpZXdlZFxuICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIHRoaXMuc2RrLkFzc2V0LnJlZ2lzdGVyVGV4dHVyZShcbiAgICAgICAgICAgICdpY29uLXBvc2l0aW9uJyxcbiAgICAgICAgICAgIHRoaXMuY29uZmlnLm15X2NvbmZpZy5pY29uX3Bvc2l0aW9uXG4gICAgICAgICAgKTtcblxuICAgICAgICAgIC8vIEN1cnJlbnQgUm9vbSAodXNlZCBmb3IgZ2V0dGluZyBib3VuZGluZyBib3ggYW5kIGV2ZW50dWFsbHkgbGF6eSBsb2FkIG1hdHRlcnRhZyBvciBvYmplY3QzRCBpbnNpZGUgY3VycmVudCBSb29tKVxuICAgICAgICAgIHRoaXMuc2RrLlJvb20uY3VycmVudC5zdWJzY3JpYmUoKGN1cnJlbnRSb29tKSA9PiB7XG4gICAgICAgICAgICBjb25zb2xlLmxvZyhgaGVsbG8gY3VycmVudCBSb29tICR7SlNPTi5zdHJpbmdpZnkoY3VycmVudFJvb20pfWApO1xuICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgLy8gM0QgcG9zaXRpb24ncyBwb2ludGVyXG4gICAgICAgICAgdGhpcy5zZGsuUG9pbnRlci5pbnRlcnNlY3Rpb24uc3Vic2NyaWJlKFxuICAgICAgICAgICAgZnVuY3Rpb24gKGludGVyc2VjdGlvbjogYW55KSB7XG4gICAgICAgICAgICAgIHRoaXMucG9zZU1hdHRlcnBvcnQgPSBpbnRlcnNlY3Rpb247XG4gICAgICAgICAgICAgIHRoaXMucG9zZU1hdHRlcnBvcnQudGltZSA9IG5ldyBEYXRlKCkuZ2V0VGltZSgpO1xuICAgICAgICAgICAgICBpZiAoIXRoaXMub2xkUG9zZU1hdHRlcnBvcnRQb3NpdGlvbikge1xuICAgICAgICAgICAgICAgIHRoaXMub2xkUG9zZU1hdHRlcnBvcnRQb3NpdGlvbiA9IHtcbiAgICAgICAgICAgICAgICAgIHg6IDAsXG4gICAgICAgICAgICAgICAgICB5OiAwLFxuICAgICAgICAgICAgICAgICAgejogMCxcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgaWYgKFxuICAgICAgICAgICAgICAgIHRoaXMuaW50ZXJhY3Rpb25Nb2RlICE9PSBWaWV3ZXJJbnRlcmFjdGlvbnMuREVGQVVMVCAmJlxuICAgICAgICAgICAgICAgIHRoaXMubWF0dGVydGFnVG9Gb2xsb3dcbiAgICAgICAgICAgICAgKSB7XG4gICAgICAgICAgICAgICAgLy8gZm9sbG93IHRoZSBwb2ludGVyIGFuZCBjaGFuZ2VzIHRoZSBwb3NpdGlvbiBvZiB0aGUgbGFzdCB0YWdcbiAgICAgICAgICAgICAgICAvLyAod2UgYXJlIGFib3V0IHRvIHZhbGlkYXRlLCBidXQgaXQgZXhpc3RzIGluIHNkayBhbHJlYWR5KVxuICAgICAgICAgICAgICAgIHRoaXMuZW5hYmxlX2ZvbGxvd2luZ190YWcodGhpcy5tYXR0ZXJ0YWdUb0ZvbGxvdyk7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgaWYgKCEhdGhpcy5nZXRDdXJzb3JQb3NpdGlvbkJ1dHRvbiAmJiAhIXRoaXMuZ2V0Q3Vyc29yUG9zaXRpb25CdXR0b24uc3R5bGUgJiZcbiAgICAgICAgICAgICAgKGRvY3VtZW50LlVSTC5pbmRleE9mKCdodHRwczovL2Rldi5zbWFydGVycGxhbi5pbycpICE9PSAtMSB8fCBkb2N1bWVudC5sb2NhdGlvbi5ocmVmLmluZGV4T2YoJ2xvY2FsaG9zdCcpICE9PSAtMSkpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmdldEN1cnNvclBvc2l0aW9uQnV0dG9uLnN0eWxlLmRpc3BsYXkgPSAnbm9uZSc7XG4gICAgICAgICAgICAgICAgdGhpcy5jdXJzb3JQb3NpdGlvbkJ1dHRvbkRpc3BsYXllZCA9IGZhbHNlO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9LmJpbmQodGhpcylcbiAgICAgICAgICApO1xuXG4gICAgICAgICAgLy9DYW1lcmEgbW9kZVxuICAgICAgICAgIHRoaXMuc2RrLk1vZGUuY3VycmVudC5zdWJzY3JpYmUoKG1vZGUpID0+IHtcbiAgICAgICAgICAgIHRoaXMuaW5UcmFuc2l0aW9uU3dlZXAgPSBmYWxzZTtcbiAgICAgICAgICAgIHN3aXRjaCAobW9kZSkge1xuICAgICAgICAgICAgICBjYXNlICdtb2RlLmRvbGxob3VzZSc6XG4gICAgICAgICAgICAgICAgdGhpcy5jdXJyZW50Q2FtZXJhTW9kZSA9IENhbWVyYU1vZGUuRE9MTEhPVVNFO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICBjYXNlICdtb2RlLmZsb29ycGxhbic6XG4gICAgICAgICAgICAgICAgdGhpcy5jdXJyZW50Q2FtZXJhTW9kZSA9IENhbWVyYU1vZGUuRkxPT1JQTEFOO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICBjYXNlICdtb2RlLmluc2lkZSc6XG4gICAgICAgICAgICAgICAgdGhpcy5jdXJyZW50Q2FtZXJhTW9kZSA9IENhbWVyYU1vZGUuSU5TSURFO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICBjYXNlICdtb2RlLnRyYW5zaXRpb25pbmcnOlxuICAgICAgICAgICAgICAgIHRoaXMuY3VycmVudENhbWVyYU1vZGUgPSBDYW1lcmFNb2RlLlRSQU5TSVRJT05JTkc7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgdGhpcy5jdXJyZW50Q2FtZXJhTW9kZSA9IENhbWVyYU1vZGUuT1VUU0lERTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMub25DYW1lcmFNb2RlQ2hhbmdlZC5uZXh0KHRoaXMuY3VycmVudENhbWVyYU1vZGUpO1xuICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgLy8gQ2FtZXJhJ3Mgdmlld3BvaW50XG4gICAgICAgICAgdGhpcy5zZGsuQ2FtZXJhLnBvc2Uuc3Vic2NyaWJlKFxuICAgICAgICAgICAgZnVuY3Rpb24gc3Vic2NyKHBvc2U6IGFueSkge1xuICAgICAgICAgICAgICB0aGlzLnBvc2VDYW1lcmEgPSBwb3NlO1xuXG4gICAgICAgICAgICAgIHRoaXMuY3VycmVudENhbWVyYVBvc2UubmV4dChwb3NlKTtcbiAgICAgICAgICAgICAgLy8gY29uc29sZS5sb2coJ0N1cnJlbnQgcG9zaXRpb24gaXMgJywgcG9zZS5wb3NpdGlvbik7XG4gICAgICAgICAgICAgIC8vIGNvbnNvbGUubG9nKCdSb3RhdGlvbiBhbmdsZSBpcyAnLCBwb3NlLnJvdGF0aW9uKTtcbiAgICAgICAgICAgICAgLy8gY29uc29sZS5sb2coXCJTd2VlcCBVVUlEIGlzXCIsIHBvc2Uuc3dlZXApO1xuICAgICAgICAgICAgfS5iaW5kKHRoaXMpXG4gICAgICAgICAgKTtcblxuICAgICAgICAgIC8vIHN1YnNjcmliZSB0byBzd2VlcHNcbiAgICAgICAgICB0aGlzLnNkay5Td2VlcC5kYXRhLnN1YnNjcmliZSh7XG4gICAgICAgICAgICBvbkNvbGxlY3Rpb25VcGRhdGVkOiBmdW5jdGlvbiBzdWJzY3IoY29sbGVjdGlvbjoge30pIHtcbiAgICAgICAgICAgICAgLy8gY29uc29sZS5sb2coXCJTd2VlcCBjb2xsZWN0aW9uIHVwZGF0ZWRcIik7XG4gICAgICAgICAgICAgIHRoaXMuc3dlZXBzID0gT2JqZWN0LmtleXMoY29sbGVjdGlvbik7XG4gICAgICAgICAgICB9LmJpbmQodGhpcyksXG4gICAgICAgICAgfSk7XG5cbiAgICAgICAgICAvLyBzdWJzY3JpYmUgdG8gY3VycmVudCBzd2VlcFxuICAgICAgICAgIHRoaXMuc2RrLlN3ZWVwLmN1cnJlbnQuc3Vic2NyaWJlKFxuICAgICAgICAgICAgZnVuY3Rpb24gc3Vic2NyKGN1cnJlbnRTd2VlcDogeyBzaWQ6IHN0cmluZyB9KSB7XG4gICAgICAgICAgICAgIC8vIENoYW5nZSB0byB0aGUgY3VycmVudCBzd2VlcCBoYXMgb2NjdXJyZWQuXG4gICAgICAgICAgICAgIGlmIChjdXJyZW50U3dlZXAuc2lkID09PSAnJykge1xuICAgICAgICAgICAgICAgIC8vIGNvbnNvbGUubG9nKCdOb3QgY3VycmVudGx5IHN0YXRpb25lZCBhdCBhIHN3ZWVwIHBvc2l0aW9uJyk7XG4gICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgLy8gY29uc29sZS5sb2coXCJlbW1pdGluZyBzd2VlcFwiLCBjdXJyZW50U3dlZXAuc2lkKTtcbiAgICAgICAgICAgICAgICB0aGlzLmN1cnJlbnRTd2VlcC5uZXh0KGN1cnJlbnRTd2VlcC5zaWQpO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9LmJpbmQodGhpcylcbiAgICAgICAgICApO1xuXG4gICAgICAgICAgLy8gU3Vic2NyaWJlIHRvIEZsb29yIGRhdGFcbiAgICAgICAgICB0aGlzLnNkay5GbG9vci5kYXRhLnN1YnNjcmliZSh7XG4gICAgICAgICAgICBvbkNvbGxlY3Rpb25VcGRhdGVkOiBmdW5jdGlvbiB1cGQodGhpczogYW55LCBjb2xsZWN0aW9uOiBhbnkpIHtcbiAgICAgICAgICAgICAgdGhpcy5mbG9vcnMgPSBPYmplY3QudmFsdWVzKGNvbGxlY3Rpb24pO1xuICAgICAgICAgICAgfS5iaW5kKHRoaXMpLFxuICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgLy8gb24gdGFnIGNsaWNrIG9wZW4gZGV0YWlscyBwYWdlXG4gICAgICAgICAgdGhpcy5zZGsub24oJ3RhZy5jbGljaycsIChzaWQ6IHN0cmluZykgPT4ge1xuICAgICAgICAgICAgLy8gZ2V0IG9iamVjdCBvZiB0aGlzIHRhZ1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgY29uc3QgbWF0dGVydGFnRGF0YSA9IHRoaXMuZGljdGlvbm5hcnlUYWdzLmdldChzaWQpO1xuICAgICAgICAgICAgICBpZiAoIW1hdHRlcnRhZ0RhdGEpe1xuICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKCdubyBtYXR0ZXJ0YWdEYXRhIHRvIGRpc3BsYXknKTtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgY29uc3QgdXJsID0gdGFnU2VydmljZS5nZXRVcmxGb3JTZWVEZXRhaWxzKFxuICAgICAgICAgICAgICAgIG1hdHRlcnRhZ0RhdGEuZ2V0T2JqZWN0KCksXG4gICAgICAgICAgICAgICAgbWF0dGVydGFnRGF0YS5nZXRUeXBlKClcbiAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgaWYgKHVybCAhPT0gJycpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnZpc2liaWxpdHlTZXJ2aWNlLmRldGFpbFNob3dpbmcubmV4dCh0cnVlKTtcbiAgICAgICAgICAgICAgICB0aGlzLm5nWm9uZS5ydW4oKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgdGhpcy5yb3V0ZXIubmF2aWdhdGUoW3VybF0pO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGNhdGNoIHtcbiAgICAgICAgICAgICAgY29uc29sZS5sb2coJ0Nhbm5vdCBzaG93IGRldGFpbHMgZm9yIHRhZycpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgLy8gUG9pbnRlciB0cmlja1xuICAgICAgICAgIC8vIENyZWF0ZSBhIGRpdiB0aGF0IHdpbGwgYXBwZWFyIHdoZW4gdGhlIGN1cnNvciBpcyBzdGlsbFxuICAgICAgICAgIC8vIEl0IHdpbGwgaW50ZXJjZXB0IHRoZSBjbGljayBvZiB0aGUgbW91c2UgYmVmb3JlIGl0IHRyaWdlcnJpbmcgdGhlIE1hdHRlcnBvcnQncyB0b3VyIG5hdmlnYXRpb25cbiAgICAgICAgICB0aGlzLnRpbWVyUG9pbnRlciA9IHNldEludGVydmFsKFxuICAgICAgICAgICAgdGhpcy51cGRhdGVQb2ludGVyVHJpY2suYmluZCh0aGlzKSxcbiAgICAgICAgICAgIDUwXG4gICAgICAgICAgKTtcblxuICAgICAgICAgIC8qKlxuICAgICAgICAgICAqIFRyYW5zaXRpb25zXG4gICAgICAgICAgICovXG4gICAgICAgICAgdGhpcy5zZGsub24oXG4gICAgICAgICAgICAndmlld21vZGUuY2hhbmdlc3RhcnQnLFxuICAgICAgICAgICAgZnVuY3Rpb24gKHRvLCBmcm9tKSB7XG4gICAgICAgICAgICAgIC8vIGNvbnNvbGUubG9nKCdTdGFydGluZyB0byBtb3ZlIHRvICcgKyB0byArICcgZnJvbSAnICsgZnJvbSk7XG4gICAgICAgICAgICAgIHRoaXMuaW5UcmFuc2l0aW9uTW9kZSA9IHRydWU7XG4gICAgICAgICAgICB9LmJpbmQodGhpcylcbiAgICAgICAgICApO1xuXG4gICAgICAgICAgdGhpcy5zZGsub24oXG4gICAgICAgICAgICAndmlld21vZGUuY2hhbmdlZW5kJyxcbiAgICAgICAgICAgIGZ1bmN0aW9uIChvbGRNb2RlLCBuZXdNb2RlKSB7XG4gICAgICAgICAgICAgIC8vIGNvbnNvbGUubG9nKCdFbmRlZCB0byBtb3ZlIHRvICcgKyBuZXdNb2RlICsgJyBmcm9tICcgKyBvbGRNb2RlKTtcbiAgICAgICAgICAgICAgaWYgKG5ld01vZGUgIT09ICdtb2RlLnRyYW5zaXRpb25pbmcnKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5pblRyYW5zaXRpb25Nb2RlID0gZmFsc2U7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0uYmluZCh0aGlzKVxuICAgICAgICAgICk7XG5cbiAgICAgICAgICB0aGlzLnNkay5vbihcbiAgICAgICAgICAgIHRoaXMuc2RrLlN3ZWVwLkV2ZW50LkVOVEVSLFxuICAgICAgICAgICAgZnVuY3Rpb24gKG9sZFN3ZWVwLCBuZXdTd2VlcCkge1xuICAgICAgICAgICAgICAvLyBjb25zb2xlLmxvZygnTGVhdmluZyBzd2VlcCAnICsgb2xkU3dlZXApO1xuICAgICAgICAgICAgICAvLyBjb25zb2xlLmxvZygnRW50ZXJpbmcgc3dlZXAgJyArIG5ld1N3ZWVwKTtcbiAgICAgICAgICAgICAgdGhpcy5pblRyYW5zaXRpb25Td2VlcCA9IGZhbHNlO1xuICAgICAgICAgICAgICB0aGlzLmRpc3BsYXlBemltdXRhbENyb3duKCk7XG4gICAgICAgICAgICB9LmJpbmQodGhpcylcbiAgICAgICAgICApO1xuICAgICAgICAgIHRoaXMuc2RrLm9uKFxuICAgICAgICAgICAgdGhpcy5zZGsuU3dlZXAuRXZlbnQuRVhJVCxcbiAgICAgICAgICAgIGZ1bmN0aW9uIChmcm9tU3dlZXAsIHRvU3dlZXApIHtcbiAgICAgICAgICAgICAgLy8gICBjb25zb2xlLmxvZygnTGVhdmluZyBzd2VlcCAnICsgZnJvbVN3ZWVwKTtcbiAgICAgICAgICAgICAgLy8gICBjb25zb2xlLmxvZygnVHJhbnNpdGlvbmluZyB0byBzd2VlcCAnICsgdG9Td2VlcCk7XG4gICAgICAgICAgICAgIHRoaXMuaW5UcmFuc2l0aW9uU3dlZXAgPSB0cnVlO1xuICAgICAgICAgICAgfS5iaW5kKHRoaXMpXG4gICAgICAgICAgKTtcblxuICAgICAgICAgIC8vIFRPRE86IGdldCBzY2VuZSB3aXRoIGdldHRlciBpbnN0ZWFkIVxuICAgICAgICAgIGNvbnN0IFtzY2VuZU9iamVjdF0gPSBhd2FpdCB0aGlzLnNkay5TY2VuZS5jcmVhdGVPYmplY3RzKDEpO1xuICAgICAgICAgIGNvbnN0IG5vZGUgPSBzY2VuZU9iamVjdC5hZGROb2RlKCk7XG4gICAgICAgICAgbm9kZS5zdGFydCgpO1xuICAgICAgICAgIHRoaXMudGhyZWVKU1NjZW5lID0gbm9kZS5vYmozRC5wYXJlbnQ7XG5cbiAgICAgICAgICAvLyBhd2FpdCB0aGlzLnNkay5TY2VuZS5jb25maWd1cmUoKHJlbmRlcmVyOiBhbnksIHRocmVlOiBhbnkpID0+IHtcbiAgICAgICAgICAvLyAgIHJlbmRlcmVyLnBoeXNpY2FsbHlDb3JyZWN0TGlnaHRzID0gdHJ1ZTtcbiAgICAgICAgICAvLyAgIHJlbmRlcmVyLm91dHB1dEVuY29kaW5nID0gdGhyZWUuc1JHQkVuY29kaW5nO1xuICAgICAgICAgIC8vICAgcmVuZGVyZXIuc2hhZG93TWFwLmVuYWJsZWQgPSB0cnVlO1xuICAgICAgICAgIC8vICAgcmVuZGVyZXIuc2hhZG93TWFwLmJpYXMgPSAwLjAwMDE7XG4gICAgICAgICAgLy8gICByZW5kZXJlci5zaGFkb3dNYXAudHlwZSA9IHRocmVlLlBDRlNvZnRTaGFkb3dNYXA7XG4gICAgICAgICAgLy8gfSk7XG5cblxuICAgICAgICAgIC8vIFRPRE86IHdhaXQgZm9yIE1QIHRpY2tldCByZXNvbHV0aW9uIGJlZm9yZSBkZWNvbW1lbnQgdGhlc2UhXG4gICAgICAgICAgLy8gV2FpdCB1bnRpbCBTaG93Y2FzZSBpcyBhY3R1YWxseSBwbGF5aW5nLi4uLlxuICAgICAgICAgIC8vIHRoaXMuc2RrLlRhZy5kYXRhLnN1YnNjcmliZSh7XG4gICAgICAgICAgLy8gICBvbkFkZGVkOiBhc3luYyBmdW5jdGlvbiAoaW5kZXgsIGl0ZW0sIGNvbGxlY3Rpb24pIHtcbiAgICAgICAgICAvL1xuICAgICAgICAgIC8vICAgICBsZXQgdGhpc09wYWNpdHkgPSAwLjI7XG4gICAgICAgICAgLy8gICAgIHRoaXMuc2RrLlRhZy5lZGl0T3BhY2l0eShpbmRleCwgdGhpc09wYWNpdHkpO1xuICAgICAgICAgIC8vXG4gICAgICAgICAgLy8gICAgIGxldCBzb3VyY2UgPSBudWxsO1xuICAgICAgICAgIC8vICAgICB0cnkge1xuICAgICAgICAgIC8vICAgICAgIHNvdXJjZSA9IGF3YWl0IFByb21pc2UuYWxsKFtcbiAgICAgICAgICAvLyAgICAgICAgIHRoaXMuc2RrLlNlbnNvci5jcmVhdGVTb3VyY2UodGhpcy5zZGsuU2Vuc29yLlNvdXJjZVR5cGUuU1BIRVJFLCB7XG4gICAgICAgICAgLy8gICAgICAgICAgIG9yaWdpbjogaXRlbS5hbmNob3JQb3NpdGlvbixcbiAgICAgICAgICAvLyAgICAgICAgICAgcmFkaXVzOiBOdW1iZXIoMyksXG4gICAgICAgICAgLy8gICAgICAgICAgIHVzZXJEYXRhOiB7XG4gICAgICAgICAgLy8gICAgICAgICAgICAgaWQ6IGluZGV4ICsgJy1zcGhlcmUtc291cmNlJyxcbiAgICAgICAgICAvLyAgICAgICAgICAgfSxcbiAgICAgICAgICAvLyAgICAgICAgIH0pXG4gICAgICAgICAgLy8gICAgICAgXSk7XG4gICAgICAgICAgLy8gICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAvLyAgICAgICBjb25zb2xlLmxvZygnY291bGQgbm90IGNyZWF0ZSBTcGhlcmUgc2Vuc29yJylcbiAgICAgICAgICAvLyAgICAgICBjb25zb2xlLmVycm9yKGUpO1xuICAgICAgICAgIC8vICAgICB9XG4gICAgICAgICAgLy8gICAgIGlmICghc291cmNlKSB7XG4gICAgICAgICAgLy8gICAgICAgcmV0dXJuO1xuICAgICAgICAgIC8vICAgICB9XG4gICAgICAgICAgLy9cbiAgICAgICAgICAvLyAgICAgbGV0IHNlbnNvciA9IG51bGw7XG4gICAgICAgICAgLy8gICAgIHRyeSB7XG4gICAgICAgICAgLy8gICAgICAgc2Vuc29yID0gYXdhaXQgdGhpcy5zZGsuU2Vuc29yLmNyZWF0ZVNlbnNvcih0aGlzLnNkay5TZW5zb3IuU2Vuc29yVHlwZS5DQU1FUkEpO1xuICAgICAgICAgIC8vICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgLy8gICAgICAgY29uc29sZS5sb2coJ2NvdWxkIG5vdCBjcmVhdGUgQ2FtZXJhIHNlbnNvcicpXG4gICAgICAgICAgLy8gICAgICAgY29uc29sZS5lcnJvcihlKTtcbiAgICAgICAgICAvLyAgICAgfVxuICAgICAgICAgIC8vICAgICBpZiAoIXNlbnNvcikge1xuICAgICAgICAgIC8vICAgICAgIHJldHVybjtcbiAgICAgICAgICAvLyAgICAgfVxuICAgICAgICAgIC8vXG4gICAgICAgICAgLy8gICAgIHNlbnNvci5hZGRTb3VyY2UoLi4uc291cmNlKTtcbiAgICAgICAgICAvLyAgICAgc2Vuc29yLnJlYWRpbmdzLnN1YnNjcmliZSh7XG4gICAgICAgICAgLy8gICAgICAgb25VcGRhdGVkKHNvdXJjZSwgcmVhZGluZykge1xuICAgICAgICAgIC8vICAgICAgICAgY29uc29sZS5sb2codGhpc09wYWNpdHkpO1xuICAgICAgICAgIC8vICAgICAgICAgbGV0IG9sZE9wYWNpdHkgPSB0aGlzT3BhY2l0eTtcbiAgICAgICAgICAvLyAgICAgICAgIGlmIChyZWFkaW5nLmluUmFuZ2UpIHtcbiAgICAgICAgICAvLyAgICAgICAgICAgdGhpc09wYWNpdHkgPSAxO1xuICAgICAgICAgIC8vICAgICAgICAgICBjb25zb2xlLmxvZyhpbmRleCArICcgaXMgaW5SYW5nZScpO1xuICAgICAgICAgIC8vICAgICAgICAgfSBlbHNlIGlmIChyZWFkaW5nLmluVmlldykge1xuICAgICAgICAgIC8vICAgICAgICAgICBjb25zb2xlLmxvZyhpbmRleCArICcgaXMgaW5WaWV3IGJ1dCBub3QgaW5SYW5nZScpO1xuICAgICAgICAgIC8vICAgICAgICAgICB0aGlzT3BhY2l0eSA9IDAuNTtcbiAgICAgICAgICAvLyAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgLy8gICAgICAgICAgIHRoaXNPcGFjaXR5ID0gMC4yO1xuICAgICAgICAgIC8vICAgICAgICAgICBjb25zb2xlLmxvZyhpbmRleCArICcgaXMgbm90IGluVmlldyBvciBpblJhbmdlJyk7XG4gICAgICAgICAgLy8gICAgICAgICB9XG4gICAgICAgICAgLy9cbiAgICAgICAgICAvLyAgICAgICAgIHRoaXMuc2RrLlRhZy5lZGl0T3BhY2l0eShpbmRleCwgdGhpc09wYWNpdHkpO1xuICAgICAgICAgIC8vICAgICAgICAgLypcbiAgICAgICAgICAvLyAgICAgICAgICAgICAgICAgICBsZXQgaW5jID0gMC4wMTtcbiAgICAgICAgICAvLyAgICAgICAgICAgICAgICAgICBpZiAob2xkT3BhY2l0eSA+IHRoaXNPcGFjaXR5KSB7XG4gICAgICAgICAgLy8gICAgICAgICAgICAgICAgICAgICBpbmMgPSAtMC4wMTtcbiAgICAgICAgICAvLyAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgLy9cbiAgICAgICAgICAvLyAgICAgICAgICAgICAgICAgICBmb3IodmFyIGkgPSBvbGRPcGFjaXR5OyBpICE9IHRoaXNPcGFjaXR5OyBpPWkraW5jKSB7XG4gICAgICAgICAgLy8gICAgICAgICAgICAgICAgICAgICAgIHNldFRpbWVvdXQoZnVuY3Rpb24oKSB7XG4gICAgICAgICAgLy8gICAgICAgICAgICAgICAgICAgICAgICAgIG1wU2RrLlRhZy5lZGl0T3BhY2l0eShpbmRleCwgaSk7XG4gICAgICAgICAgLy8gICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKCdEZWxheScsIGkpO1xuICAgICAgICAgIC8vICAgICAgICAgICAgICAgICAgICAgICB9LDEwKTtcbiAgICAgICAgICAvLyAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgLy8gICAgICAgICAqL1xuICAgICAgICAgIC8vICAgICAgIH1cbiAgICAgICAgICAvLyAgICAgfSk7XG4gICAgICAgICAgLy8gICAgIC8vc2Vuc29yLnNob3dEZWJ1Zyh0cnVlKTtcbiAgICAgICAgICAvLyAgIH0uYmluZCh0aGlzKSxcbiAgICAgICAgICAvLyAgIG9uQ29sbGVjdGlvblVwZGF0ZWQ6IGZ1bmN0aW9uIChjb2xsZWN0aW9uKSB7XG4gICAgICAgICAgLy8gICAgIGNvbnNvbGUubG9nKCdDb2xsZWN0aW9uIHJlY2VpdmVkLiBUaGVyZSBhcmUgJywgT2JqZWN0LmtleXMoY29sbGVjdGlvbikubGVuZ3RoLCAnIFRhZ3MgaW4gdGhlIGNvbGxlY3Rpb24nLCBjb2xsZWN0aW9uKTtcbiAgICAgICAgICAvLyAgIH1cbiAgICAgICAgICAvLyB9KTtcblxuICAgICAgICAgIHJlc29sdmUodHJ1ZSk7XG4gICAgICAgIH0uYmluZCh0aGlzKVxuICAgICAgKTtcbiAgICB9KTtcbiAgfVxuXG5cbiAgc2V0TGlnaHRpbmdPZmYoKSB7XG4gICAgdGhpcy5ub0xpZ2h0Rm9yT2JqZWN0cyA9IHRydWU7XG4gIH1cblxuICBwb2ludFRvU3RyaW5nKHBvaW50OiB7IHg6IG51bWJlciwgeTogbnVtYmVyLCB6OiBudW1iZXIgfSk6IHN0cmluZyB7XG4gICAgdmFyIHggPSBwb2ludC54LnRvRml4ZWQoMyk7XG4gICAgdmFyIHkgPSBwb2ludC55LnRvRml4ZWQoMyk7XG4gICAgdmFyIHogPSBwb2ludC56LnRvRml4ZWQoMyk7XG5cbiAgICByZXR1cm4gYHsgeDogJHt4fSwgeTogJHt5fSwgejogJHt6fSB9YDtcbiAgfVxuXG4gIC8vXG4gIC8vIC0tLS0tLS0tLS0gTWVhc3VyZW1lbnRzIHJlbGF0ZWQgLS0tLS0tLS0tLVxuICAvL1xuICAvKipcbiAgICogQ2FsbGJhY2sgYWZ0ZXIgbWVhc3VyZW1lbnQgaXMgcGVyZm9ybWVkXG4gICAqL1xuICBnZXREaXN0YW5jZUZvckxhc3RNZWFzdXJlbWVudCgpIHtcbiAgICBpZiAodGhpcy5sYXN0TWVhc3VyZS5sZW5ndGggPiAwKSB7XG4gICAgICBjb25zdCBudW1iZXJQb2ludHMgPSB0aGlzLmxhc3RNZWFzdXJlLmxlbmd0aDtcbiAgICAgIHRoaXMuZGlzdGFuY2VzTGFzdE1lYXN1cmUgPSBbXTtcbiAgICAgIGZvciAobGV0IGluZGV4ID0gMTsgaW5kZXggPCBudW1iZXJQb2ludHM7IGluZGV4ICs9IDEpIHtcbiAgICAgICAgY29uc3QgZGlzdGFuY2UgPSBnZXREaXN0YW5jZUJldHdlZW5Ud29Qb2ludHMoXG4gICAgICAgICAgdGhpcy5sYXN0TWVhc3VyZVtpbmRleCAtIDFdLFxuICAgICAgICAgIHRoaXMubGFzdE1lYXN1cmVbaW5kZXhdXG4gICAgICAgICk7XG4gICAgICAgIHRoaXMuZGlzdGFuY2VzTGFzdE1lYXN1cmUucHVzaChkaXN0YW5jZSk7XG4gICAgICB9XG4gICAgICB0aGlzLnRha2VTY3JlZW5TaG90KCkudGhlbigocmVzKSA9PiB7XG4gICAgICAgIHRoaXMucm91dGVyLm5hdmlnYXRlKFtgdmlzaXQvJHt0aGlzLmN1cnJlbnRTcGFjZUlEfS9hZGRfbWVhc3VyZW1lbnRgXSk7XG4gICAgICB9KTtcbiAgICB9XG4gIH1cblxuICBnZXRMYXN0RGlzdGFuY2VzKCkge1xuICAgIHJldHVybiB0aGlzLmRpc3RhbmNlc0xhc3RNZWFzdXJlO1xuICB9XG5cbiAgLyoqXG4gICAqIFRha2VzIHNjcmVlbnNob3QgYW5kIHNhdmVzIGJhc2U2NCBpbiBsYXN0U2NyZWVuc2hvdFVyaVxuICAgKiBAcmV0dXJucyBQcm9taXNlXG4gICAqL1xuICB0YWtlU2NyZWVuU2hvdCgpOiBQcm9taXNlPGFueT4ge1xuICAgIHJldHVybiB0aGlzLnNkay5SZW5kZXJlci50YWtlU2NyZWVuU2hvdChcbiAgICAgIHRoaXMucmVzb2x1dGlvbixcbiAgICAgIHRoaXMudmlzaWJpbGl0eVxuICAgICkudGhlbihcbiAgICAgIGZ1bmN0aW9uIChzY3JlZW5TaG90VXJpOiBhbnkpIHtcbiAgICAgICAgLy8gYmFzZTY0IHN0cmluZ1xuICAgICAgICB0aGlzLmxhc3RTY3JlZW5zaG90VXJpID0gc2NyZWVuU2hvdFVyaTtcbiAgICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpO1xuICAgICAgfS5iaW5kKHRoaXMpXG4gICAgKTtcbiAgfVxuXG4gIGdldFNjcmVlblNob3RVcmkoKSB7XG4gICAgcmV0dXJuIHRoaXMubGFzdFNjcmVlbnNob3RVcmk7XG4gIH1cblxuICBnZXRMYXN0TWVhc3VyZW1lbnQoKTogT2JqZWN0IHtcbiAgICBjb25zdCBkYXRhID0ge1xuICAgICAgbWVhc3VyZTogdGhpcy5sYXN0TWVhc3VyZSxcbiAgICAgIHN3ZWVwOiB0aGlzLnBvc2VDYW1lcmEuc3dlZXAsXG4gICAgfTtcbiAgICByZXR1cm4gZGF0YTtcbiAgfVxuXG4gIC8vXG4gIC8vIC0tLS0tLS0tLS0gVXRpbHMgLS0tLS0tLS0tLVxuICAvL1xuICAvKipcbiAgICogU3R5bGluZyBvZiBwb2ludGVyXG4gICAqL1xuICB1cGRhdGVQb2ludGVyVHJpY2soKSB7XG4gICAgaWYgKFxuICAgICAgdGhpcy5pbnRlcmFjdGlvbk1vZGUgIT09IFZpZXdlckludGVyYWN0aW9ucy5ERUZBVUxUICYmXG4gICAgICB0aGlzLm1hdHRlcnRhZ1RvRm9sbG93ICYmXG4gICAgICB0aGlzLnBvc2VNYXR0ZXJwb3J0ICYmXG4gICAgICB0aGlzLmdldERpc3RQb3NpdGlvbihcbiAgICAgICAgdGhpcy5wb3NlTWF0dGVycG9ydC5wb3NpdGlvbixcbiAgICAgICAgdGhpcy5vbGRQb3NlTWF0dGVycG9ydFBvc2l0aW9uXG4gICAgICApID4gMjVcbiAgICApIHtcbiAgICAgIHRoaXMucG9pbnRlckJ1dHRvbi5zdHlsZS5kaXNwbGF5ID0gJ25vbmUnO1xuXG4gICAgICBjb25zdCBzaXplID0ge1xuICAgICAgICB3OiB0aGlzLmNvbnRhaW5lci5jbGllbnRXaWR0aCxcbiAgICAgICAgaDogdGhpcy5jb250YWluZXIuY2xpZW50SGVpZ2h0LFxuICAgICAgfTtcbiAgICAgIGNvbnN0IGNvb3JkcyA9IHRoaXMuc2RrLkNvbnZlcnNpb24ud29ybGRUb1NjcmVlbihcbiAgICAgICAgdGhpcy5wb3NlTWF0dGVycG9ydC5wb3NpdGlvbixcbiAgICAgICAgdGhpcy5wb3NlQ2FtZXJhLFxuICAgICAgICBzaXplXG4gICAgICApO1xuICAgICAgdGhpcy5wb2ludGVyQnV0dG9uLnN0eWxlLmxlZnQgPSBgJHtcbiAgICAgICAgY29vcmRzLnggKiBNYXRoLnNpZ24oY29vcmRzLngpIC0gMjVcbiAgICAgIH1weGA7XG4gICAgICB0aGlzLnBvaW50ZXJCdXR0b24uc3R5bGUudG9wID0gYCR7Y29vcmRzLnkgKiBNYXRoLnNpZ24oY29vcmRzLngpIC0gMjV9cHhgO1xuICAgICAgdGhpcy5vbGRQb3NlTWF0dGVycG9ydFBvc2l0aW9uID0ge1xuICAgICAgICAuLi50aGlzLnBvc2VNYXR0ZXJwb3J0LnBvc2l0aW9uLFxuICAgICAgfTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5wb2ludGVyQnV0dG9uLnN0eWxlLmRpc3BsYXkgPSAnYmxvY2snO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBSZWFsdGltZSBtYXR0ZXJ0YWcgZm9sbG93aW5nIHRoZSBjdXJzb3JcbiAgICogQHBhcmFtIG1hdHRlcnRhZyBzdHJpbmdcbiAgICovXG4gIGVuYWJsZV9mb2xsb3dpbmdfdGFnKG1hdHRlcnRhZzogc3RyaW5nKSB7XG4gICAgdGhpcy5zZGsuVGFnLmVkaXRQb3NpdGlvbihtYXR0ZXJ0YWcsIHtcbiAgICAgIGFuY2hvclBvc2l0aW9uOiB7XG4gICAgICAgIHg6IHRoaXMucG9zZU1hdHRlcnBvcnQucG9zaXRpb24ueCAqIDEsXG4gICAgICAgIHk6IHRoaXMucG9zZU1hdHRlcnBvcnQucG9zaXRpb24ueSAqIDEsXG4gICAgICAgIHo6IHRoaXMucG9zZU1hdHRlcnBvcnQucG9zaXRpb24ueiAqIDEsXG4gICAgICB9LFxuICAgICAgc3RlbVZlY3Rvcjoge1xuICAgICAgICB4OiB0aGlzLnBvc2VNYXR0ZXJwb3J0Lm5vcm1hbC54ICogMC4zLFxuICAgICAgICB5OiB0aGlzLnBvc2VNYXR0ZXJwb3J0Lm5vcm1hbC55ICogMC4zLFxuICAgICAgICB6OiB0aGlzLnBvc2VNYXR0ZXJwb3J0Lm5vcm1hbC56ICogMC4zLFxuICAgICAgfSxcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXQgdGhlIGRpc3RhbmNlIGJldHd3ZWVuIHR3byAzRCBwb3NpdGlvbnNcbiAgICogVXNlZCBpbiBvcmRlciB0byBzZWUgaG93IG11Y2ggdGhlIGN1cnNvciBoYXMgbW92ZWQgZnJvbSB0aGUgcHJldmlvdXMgcG9zaXRpb25cbiAgICogQHBhcmFtIHBvczFcbiAgICogQHBhcmFtIHBvczJcbiAgICovXG4gIGdldERpc3RQb3NpdGlvbihwb3MxOiBhbnksIHBvczI6IGFueSkge1xuICAgIGNvbnN0IHNpemUgPSB7XG4gICAgICB3OiB0aGlzLmNvbnRhaW5lci5jbGllbnRXaWR0aCxcbiAgICAgIGg6IHRoaXMuY29udGFpbmVyLmNsaWVudEhlaWdodCxcbiAgICB9O1xuICAgIGNvbnN0IGNvb3JkczEgPSB0aGlzLnNkay5Db252ZXJzaW9uLndvcmxkVG9TY3JlZW4oXG4gICAgICBwb3MxLFxuICAgICAgdGhpcy5wb3NlQ2FtZXJhLFxuICAgICAgc2l6ZVxuICAgICk7XG4gICAgY29uc3QgY29vcmRzMiA9IHRoaXMuc2RrLkNvbnZlcnNpb24ud29ybGRUb1NjcmVlbihcbiAgICAgIHBvczIsXG4gICAgICB0aGlzLnBvc2VDYW1lcmEsXG4gICAgICBzaXplXG4gICAgKTtcbiAgICByZXR1cm4gTWF0aC5zcXJ0KFxuICAgICAgKGNvb3JkczEueCAtIGNvb3JkczIueCkgKiogMiArIChjb29yZHMxLnkgLSBjb29yZHMyLnkpICoqIDJcbiAgICApO1xuICB9XG5cbiAgLy9cbiAgLy8gLS0tLS0tLS0tLSBNYXR0ZXJ0YWcgcmVsYXRlZCAtLS0tLS0tLS0tXG4gIC8vXG4gIC8qKlxuICAgKiBDcmVhdGVzIHRoZSBNYXR0ZXJ0YWcgdGhhdCB3aWxsIGZvbGxvdyB0aGUgY3Vyc29yXG4gICAqIEBwYXJhbSBtYXR0ZXJ0YWdEYXRhIE1hdHRlcnRhZ0RhdGFcbiAgICovXG4gIGFzeW5jIGFkZEN1cnNvck1hdHRlcnRhZyhtYXR0ZXJ0YWdEYXRhOiBNYXR0ZXJ0YWdEYXRhKSB7XG4gICAgaWYgKCF0aGlzLnBvc2VNYXR0ZXJwb3J0KSByZXR1cm47XG4gICAgdGhpcy5tYXR0ZXJ0YWdUb0ZvbGxvdyA9IGF3YWl0IHRoaXMuYWRkTWF0dGVydGFnVG9WaWV3ZXIobWF0dGVydGFnRGF0YSk7XG4gICAgY29uc29sZS5sb2coJ2ZvbGxvd2luZyB0aGUgdGFnJywgdGhpcy5tYXR0ZXJ0YWdUb0ZvbGxvdyk7XG4gICAgdGhpcy5zZGsuVGFnLmVkaXRJY29uKHRoaXMubWF0dGVydGFnVG9Gb2xsb3csICdpY29uLXBvc2l0aW9uJyk7XG4gICAgdGhpcy5zZGsuVGFnLmVkaXRPcGFjaXR5KHRoaXMubWF0dGVydGFnVG9Gb2xsb3csIDEpO1xuICB9XG5cbiAgLyoqXG4gICAqIEFkZHMgTWF0dGVydGFnIHRvIHZpZXdlciBmb3IgYW4gZXhpc3Rpbmcgb2JqZWN0IHdpdGggY29vcmRpbmF0ZXMgKGluIG1hdHRlcnRhZ0RhdGEucG9pKVxuICAgKiAocG9zaXRpb24sIGluamVjdGVkIGh0bWwsIHNldCBpY29uKVxuICAgKiBAcGFyYW0gbWF0dGVydGFnRGF0YVxuICAgKiByZXR1cm5zIG1hdHRlcnRhZ0lEXG4gICAqL1xuICBhc3luYyBhZGRNYXR0ZXJ0YWdUb1ZpZXdlcihcbiAgICBtYXR0ZXJ0YWdEYXRhOiBNYXR0ZXJ0YWdEYXRhXG4gICk6IFByb21pc2U8c3RyaW5nIHwgbnVsbD4ge1xuICAgIGxldCBzaWRMaXN0O1xuICAgIGlmICghdGhpcy5zZGspIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cbiAgICB0cnkge1xuICAgICAgc2lkTGlzdCA9IGF3YWl0IHRoaXMuc2RrLlRhZy5hZGQobWF0dGVydGFnRGF0YS5nZXREYXRhKCkpO1xuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICBjb25zb2xlLmxvZyhcbiAgICAgICAgJ1RhZyBkb2VzIG5vdCBiZWxvbmcgdG8gdGhlIHZpc2l0JyxcbiAgICAgICAgZXJyb3IsXG4gICAgICAgIG1hdHRlcnRhZ0RhdGEuZ2V0RGF0YSgpXG4gICAgICApO1xuICAgIH1cbiAgICBpZiAoc2lkTGlzdCkge1xuICAgICAgY29uc3QgbWF0dGVydGFnSUQgPSBzaWRMaXN0WzBdO1xuICAgICAgLy8gY29uc29sZS5sb2coXCJhZGRlZCB0YWdcIiwgbWF0dGVydGFnRGF0YS5nZXRUeXBlKCksIG1hdHRlcnRhZ0lEKTtcbiAgICAgIHRoaXMubWF0dGVydGFnSURzLnB1c2gobWF0dGVydGFnSUQpO1xuICAgICAgdGhpcy5kaWN0aW9ubmFyeVRhZ3Muc2V0KG1hdHRlcnRhZ0lELCBtYXR0ZXJ0YWdEYXRhKTtcbiAgICAgIHJldHVybiBtYXR0ZXJ0YWdJRDtcbiAgICB9XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICAvKipcbiAgICogQWN0aW9ucyB3aGVuIHBvc2l0aW9uIG9mIG1hdHRlcnRhZyBpcyB2YWxpZGF0ZWQgYnkgbGVmdCBjbGlja1xuICAgKi9cbiAgb25WYWxpZGF0ZWRNYXR0ZXJ0YWcoKSB7XG4gICAgdGhpcy5zZXRJbnRlcmFjdGlvbk1vZGUoVmlld2VySW50ZXJhY3Rpb25zLkRFRkFVTFQpO1xuICAgIGNvbnN0IGxhc3RUYWcgPSB0aGlzLmdldExhc3RUYWcoKTtcbiAgICBpZiAobGFzdFRhZykge1xuICAgICAgY29uc3QgY2FsbGJhY2tNb2RlID0gdGhpcy5kaWN0aW9ubmFyeVRhZ3NcbiAgICAgICAgLmdldChsYXN0VGFnKVxuICAgICAgICAuZ2V0Q2FsbGJhY2tBY3Rpb25Nb2RlKCk7XG4gICAgICB0aGlzLmNhbGxiYWNrQWZ0ZXJNYXR0ZXJ0YWdWYWxpZGF0aW9uKGNhbGxiYWNrTW9kZSk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFJlZ2lzdGVycyBuZXcgaWNvbiAocGF0aCB0byBpbWFnZSkgYW5kIHNldCBpdHMgZm9yIE1hdHRlcnRhZ1xuICAgKiBAcGFyYW0gbWF0dGVydGFnSUQgc3RyaW5nXG4gICAqIEBwYXJhbSBpY29uUGF0aCBzdHJpbmdcbiAgICovXG4gIGFzeW5jIGFkZE5ld0ljb25BbmRTZXRGb3JUYWcobWF0dGVydGFnSUQ6IHN0cmluZywgaWNvblBhdGg6IHN0cmluZykge1xuICAgIGF3YWl0IHRoaXMuc2RrLkFzc2V0LnJlZ2lzdGVyVGV4dHVyZShgaWNvbl8ke21hdHRlcnRhZ0lEfWAsIGljb25QYXRoKTtcbiAgICB0aGlzLnNkay5UYWcuZWRpdEljb24obWF0dGVydGFnSUQsIGBpY29uXyR7bWF0dGVydGFnSUR9YCk7XG4gIH1cblxuICAvKipcbiAgICogQ2hhbmdlcyBpY29uIG9mIE1hdHRlcnRhZyAodGhlIGljb25OYW1lIHNob3VsZCBiZSByZWdpc3RlcmVkID0gb25lIG9mIGRlZmF1bHQgb25lcylcbiAgICogQHBhcmFtIG1hdHRlcnRhZ0lEIHN0cmluZ1xuICAgKiBAcGFyYW0gaWNvbk5hbWUgc3RyaW5nXG4gICAqL1xuICBhc3luYyBzZXRSZWdpc3RyZWRJY29uRm9yVGFnKG1hdHRlcnRhZ0lEOiBzdHJpbmcsIGljb25OYW1lOiBzdHJpbmcpIHtcbiAgICB0cnkge1xuICAgICAgdGhpcy5zZGsuVGFnLmVkaXRJY29uKG1hdHRlcnRhZ0lELCBpY29uTmFtZSk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgY29uc29sZS5sb2coXG4gICAgICAgICdjb3VsZCBub3QgZWRpdCBJY29uIHdpdGggbmFtZSAnLFxuICAgICAgICBpY29uTmFtZSxcbiAgICAgICAgJy4gSXMgaXQgcmVnaXN0ZXJlZD8nXG4gICAgICApO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBTZXRzIGRlZmF1bHQgaWNvbiBmb3IgYSB0YWcgKHJlZ2lzdGVyZWQgaW4gaW5pdFNkaykgT1IgdXNlcyB0YWdJY29uIGZyb20gUE9JIChhdmFpbGFibGUgZnJvbSBNYXR0ZXJ0YWdEYXRhKVxuICAgKiBAcGFyYW0gbWF0dGVydGFnSUQgc3RyaW5nXG4gICAqIEBwYXJhbSBtYXR0ZXJ0YWdEYXRhIE1hdHRlcnRhZ0RhdGFcbiAgICogQHJldHVybnNcbiAgICovXG4gIGFzeW5jIHNldFRhZ0ljb25BbmRPcGFjaXR5KFxuICAgIG1hdHRlcnRhZ0lEOiBzdHJpbmcsXG4gICAgbWF0dGVydGFnRGF0YTogTWF0dGVydGFnRGF0YVxuICApIHtcbiAgICBpZiAodGhpcy5TUE1vZHVsZSA9PT0gU3BNb2R1bGUuSE9URUwpIHtcbiAgICAgIGNvbnN0IHJvb20gPSBtYXR0ZXJ0YWdEYXRhLmdldE9iamVjdCgpO1xuICAgICAgbGV0IGljb25OYW1lID0gYGljb25fcm9vbWA7XG4gICAgICBpZiAocm9vbS5hdmFpbGFibGUpIHtcbiAgICAgICAgaWNvbk5hbWUgPSBgJHtpY29uTmFtZX1fYXZhaWxhYmxlYDtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGljb25OYW1lID0gYCR7aWNvbk5hbWV9X3VuYXZhaWxhYmxlYDtcbiAgICAgIH1cbiAgICAgIHRoaXMuc2RrLlRhZy5lZGl0SWNvbihtYXR0ZXJ0YWdJRCwgaWNvbk5hbWUpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBjb25zdCBzdHJpbmdUYWdUeXBlID0gcG9pVHlwZVRvU3RyaW5nKG1hdHRlcnRhZ0RhdGEuZ2V0VHlwZSgpKTtcbiAgICBsZXQgb3BhY2l0eSA9IHRoaXMuY29uZmlnLm15X2NvbmZpZy5ERUZBVUxUX09QQUNJVFlfVEFHO1xuICAgIGxldCBpY29uTmFtZSA9IGBpY29uLSR7c3RyaW5nVGFnVHlwZX1gO1xuICAgIGNvbnN0IHBvaSA9IG1hdHRlcnRhZ0RhdGEuZ2V0UG9pKCk7XG4gICAgaWYgKHBvaSAmJiBwb2kudGFnSWNvbikge1xuICAgICAgY29uc3QgdGFnSWNvbiA9IEpTT04ucGFyc2UocG9pLnRhZ0ljb24pO1xuICAgICAgaWYgKG1hdHRlcnRhZ0RhdGEuZ2V0VHlwZSgpID09PSBQb2lUeXBlLkRBVEEpIHtcbiAgICAgICAgY29uc3QgZmVhdHVyZSA9IG1hdHRlcnRhZ0RhdGEuZ2V0T2JqZWN0KCk7XG4gICAgICAgIGlmIChmZWF0dXJlLnR5cGUgPT09IEZlYXR1cmVUeXBlLklORElDQVRPUl9URU1QKSB7XG4gICAgICAgICAgdGFnSWNvbi5zcmMgPSB0aGlzLnRhZ1NlcnZpY2UuZ2V0SWNvblRhZ0ltYWdlRm9yRmVhdHVyZShmZWF0dXJlLCBwb2kpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBpZiAodGFnSWNvbi5zcmMpIHtcbiAgICAgICAgY29uc3QgcGF0aFNpZ25lZCA9IGF3YWl0IHRoaXMudGFnU2VydmljZS5nZXRTaWduZWRUYWdJY29uU291cmNlKFxuICAgICAgICAgIHRhZ0ljb24uc3JjXG4gICAgICAgICk7XG4gICAgICAgIGlmIChwYXRoU2lnbmVkKSB7XG4gICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGljb25OYW1lID0gYGljb24tJHtzdHJpbmdUYWdUeXBlfS0ke21hdHRlcnRhZ0lEfS0ke21hdHRlcnRhZ0RhdGEuY3VzdG9tSWNvbkluZGV4fWA7XG4gICAgICAgICAgICBhd2FpdCB0aGlzLnNkay5Bc3NldC5yZWdpc3RlclRleHR1cmUoaWNvbk5hbWUsIHBhdGhTaWduZWQpO1xuICAgICAgICAgICAgbWF0dGVydGFnRGF0YS5jdXN0b21JY29uSW5kZXggKz0gMTtcbiAgICAgICAgICB9IGNhdGNoIHtcbiAgICAgICAgICAgIGNvbnNvbGUubG9nKCdlcnJvciByZWdpc3Rlckljb24nKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGlmICh0YWdJY29uLm9wYWNpdHkpIHtcbiAgICAgICAgb3BhY2l0eSA9IHRhZ0ljb24ub3BhY2l0eTtcbiAgICAgIH1cbiAgICB9XG4gICAgdHJ5IHtcbiAgICAgIHRoaXMuc2RrLlRhZy5lZGl0SWNvbihtYXR0ZXJ0YWdJRCwgaWNvbk5hbWUpO1xuICAgICAgdGhpcy5zZGsuVGFnLmVkaXRPcGFjaXR5KG1hdHRlcnRhZ0lELCBvcGFjaXR5KTtcbiAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgY29uc29sZS5sb2coJ0Vycm9yIGVkaXRJY29uIG9yIG9wYWNpdHknLCBlcnJvcik7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIE1vdmVzIHZpZXdlciB0byBsYXN0IHRhZyBjcmVhdGVkXG4gICAqL1xuICBnb1RvTGFzdFRhZygpIHtcbiAgICBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgIGNvbnN0IGxhc3RUYWcgPSB0aGlzLmdldExhc3RUYWcoKTtcbiAgICAgIHRoaXMuZ29Ub1RhZyhsYXN0VGFnKTtcbiAgICB9LCAyMDAwKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBNb3ZlcyB2aWV3ZXIgdG8gTWF0dGVydGFnIHdpdGggSUQgcHJvdmlkZWRcbiAgICogQHBhcmFtIG1hdHRlcnRhZ0lEIHN0cmluZ1xuICAgKiBAcmV0dXJuc1xuICAgKi9cbiAgYXN5bmMgZ29Ub1RhZyhtYXR0ZXJ0YWdJRDogc3RyaW5nKSB7XG4gICAgaWYgKG1hdHRlcnRhZ0lEID09PSAnJykgcmV0dXJuO1xuICAgIHRyeSB7XG4gICAgICB0aGlzLm9uR29Ub1RhZy5uZXh0KG1hdHRlcnRhZ0lEKTtcbiAgICAgIGF3YWl0IHRoaXMuc2RrLlN3ZWVwLmN1cnJlbnQud2FpdFVudGlsKFxuICAgICAgICAoY3VycmVudFN3ZWVwKSA9PiBjdXJyZW50U3dlZXAgIT09ICcnXG4gICAgICApO1xuICAgICAgYXdhaXQgdGhpcy5zZGsuTWF0dGVydGFnLm5hdmlnYXRlVG9UYWcoXG4gICAgICAgIG1hdHRlcnRhZ0lELFxuICAgICAgICB0aGlzLnNkay5NYXR0ZXJ0YWcuVHJhbnNpdGlvbi5GTFlcbiAgICAgICk7XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIGNvbnNvbGUubG9nKCdjYW5ub3QgbmF2aWdhdGUgdG8gdGFnJywgZXJyb3IpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBVcGRhdGVzIGNvbnRlbnQgb2YgTWF0dGVydGFnIHdpdGggbWF0dGVydGFnSUQgKGJpbGxib2FyZCwgaW5qZWN0ZWQgaHRtbCwgdGFnIGljb24pXG4gICAqIEBwYXJhbSBtYXR0ZXJ0YWdJRCBzdHJpbmdcbiAgICogQHBhcmFtIG9iamVjdCBUaWNrZXQsIEVxdWlwbWVudCwgRmVhdHVyZSwgZXRjXG4gICAqIEBwYXJhbSB0YWdUeXBlIFBvaVR5cGVcbiAgICovXG4gIGFzeW5jIHVwZGF0ZU1hdHRlclRhZ0NvbnRlbnRGb3JUYWdJRChcbiAgICBtYXR0ZXJ0YWdJRDogc3RyaW5nLFxuICAgIG9iamVjdDogRGJPYmplY3RUeXBlID0gbnVsbCxcbiAgICB0YWdUeXBlOiBQb2lUeXBlID0gbnVsbFxuICApIHtcbiAgICB0aGlzLnNkay5UYWcuZWRpdEJpbGxib2FyZChcbiAgICAgIG1hdHRlcnRhZ0lELFxuICAgICAgdGhpcy5kaWN0aW9ubmFyeVRhZ3MuZ2V0KG1hdHRlcnRhZ0lEKS5nZXREYXRhKClcbiAgICApO1xuICAgIGlmIChvYmplY3QgJiYgdGFnVHlwZSkge1xuICAgICAgYXdhaXQgdGhpcy5pbmplY3RIdG1sSW5UYWcodGFnVHlwZSwgb2JqZWN0LCBtYXR0ZXJ0YWdJRCk7XG4gICAgfVxuICAgIGF3YWl0IHRoaXMuc2V0VGFnSWNvbkFuZE9wYWNpdHkoXG4gICAgICBtYXR0ZXJ0YWdJRCxcbiAgICAgIHRoaXMuZGljdGlvbm5hcnlUYWdzLmdldChtYXR0ZXJ0YWdJRClcbiAgICApO1xuICB9XG5cbiAgLyoqXG4gICAqIFVwZGF0ZXMgaW5qZWN0ZWQgaHRtbCBmb3IgTWF0dGVydGFnXG4gICAqIEBwYXJhbSBtYXR0ZXJ0YWdJRCBzdHJpbmdcbiAgICogQHBhcmFtIG9iamVjdCBUaWNrZXQsIEVxdWlwbWVudCwgRmVhdHVyZSwgZXRjXG4gICAqIEBwYXJhbSB0YWdUeXBlIFBvaVR5cGVcbiAgICovXG4gIGFzeW5jIHVwZGF0ZUluamVjdGVkSHRtbEZvclRhZ0lEKFxuICAgIG1hdHRlcnRhZ0lEOiBzdHJpbmcsXG4gICAgb2JqZWN0OiBhbnksXG4gICAgdGFnVHlwZTogUG9pVHlwZVxuICApIHtcbiAgICBhd2FpdCB0aGlzLmluamVjdEh0bWxJblRhZyh0YWdUeXBlLCBvYmplY3QsIG1hdHRlcnRhZ0lEKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBEZWxldGVzIE1hdHRlcnRhZyBmcm9tIFZpZXdlciBieSBpdHMgSURcbiAgICogQHBhcmFtIG1hdHRlcnRhZ0lEIHN0cmluZ1xuICAgKi9cbiAgZGVsZXRlTWF0dGVydGFnRnJvbUlkKG1hdHRlcnRhZ0lEOiBzdHJpbmcpIHtcbiAgICB0aGlzLnNkay5UYWcucmVtb3ZlKG1hdHRlcnRhZ0lEKTtcbiAgICB0aGlzLmRpY3Rpb25uYXJ5VGFncy5kZWxldGUobWF0dGVydGFnSUQpO1xuICB9XG5cbiAgLyoqXG4gICAqIERlbGV0ZXMgbGF0ZXN0IGNyZWF0ZWQgbWF0dGVydGFnXG4gICAqL1xuICBkZWxldGVMYXN0TWF0dGVydGFnKCkge1xuICAgIGNvbnN0IG1hdHRlcnRhZ0lEID0gdGhpcy5tYXR0ZXJ0YWdJRHMucG9wKCk7XG4gICAgaWYgKG1hdHRlcnRhZ0lEKSB7XG4gICAgICB0aGlzLmRlbGV0ZU1hdHRlcnRhZ0Zyb21JZChtYXR0ZXJ0YWdJRCk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIExlZ2FjeTogdXNlZCB0byBiZSBjYWxsZWQgYWN0aW9uX2FkZF9tYXR0ZXJ0YWdfZnJvbV9QT0lcbiAgICogQWRkcyBhbmQgY29uZmlndXJlcyBNYXR0ZXJ0YWcgZm9yIGFuIG9iamVjdCAoVGlja2V0LCBFcXVpcG1lbnQsIEZlYXR1cmUsIGV0YykgdGhhdCBjb3JyZXNwb25kcyB0byBQT0kgKGNvb3JkaW5hdGVzLCB0YWdJY29uKVxuICAgKiBAcGFyYW0gdGFnVHlwZSBQb2lUeXBlXG4gICAqIEBwYXJhbSBvYmplY3QgVGlja2V0LCBFcXVpcG1lbnQsIEZlYXR1cmUuLi5cbiAgICogQHBhcmFtIHBvaSBQT0lcbiAgICogQHJldHVybnNcbiAgICovXG4gIGFzeW5jIGNyZWF0ZU1hdHRlcnRhZ0Zyb21QT0koXG4gICAgdGFnVHlwZTogUG9pVHlwZSxcbiAgICBvYmplY3Q6IERiT2JqZWN0VHlwZSxcbiAgICBwb2k6IFBPSVxuICApOiBQcm9taXNlPGFueT4ge1xuICAgIC8vIGNoZWNrIGlmIHRhZyBleGlzdHMgYWxyZWFkeVxuICAgIGNvbnN0IHt0YWcsIHN3ZWVwfSA9IHRoaXMuZ2V0VGFnRnJvbUVsZW1lbnRJZChvYmplY3QuaWQpO1xuICAgIGlmICh0YWcpIHtcbiAgICAgIC8vIGNvbnNvbGUubG9nKFwidGFnIGV4aXN0c1wiLCBvYmplY3QpXG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGNvbnN0IG1hdHRlcnRhZ0RhdGE6IE1hdHRlcnRhZ0RhdGEgPSBuZXcgTWF0dGVydGFnRGF0YSh0YWdUeXBlKTtcbiAgICBtYXR0ZXJ0YWdEYXRhLnNldE9iamVjdChvYmplY3QsIHRhZ1R5cGUpO1xuICAgIGlmIChwb2kuY29vcmRpbmF0ZSkge1xuICAgICAgbWF0dGVydGFnRGF0YS5zZXRQb3NpdGlvbihKU09OLnBhcnNlKHBvaS5jb29yZGluYXRlKSk7XG4gICAgfVxuICAgIGlmIChwb2kubWV0YWRhdGEpIHtcbiAgICAgIGNvbnN0IHRhZ01ldGFkYXRhID0gSlNPTi5wYXJzZShwb2kubWV0YWRhdGEpO1xuICAgICAgaWYgKHRhZ01ldGFkYXRhLm5vcm1hbCkge1xuICAgICAgICBtYXR0ZXJ0YWdEYXRhLnNldE5vcm1hbCh0YWdNZXRhZGF0YS5ub3JtYWwpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgbWF0dGVydGFnRGF0YS5zZXROb3JtYWwoe3g6IDAsIHk6IC0wLjE1LCB6OiAwfSk7XG4gICAgICB9XG4gICAgfVxuICAgIGlmIChwb2kubWF0dGVycG9ydFN3ZWVwSUQpIHtcbiAgICAgIG1hdHRlcnRhZ0RhdGEuc2V0U3dlZXBJRChwb2kubWF0dGVycG9ydFN3ZWVwSUQpO1xuICAgIH1cbiAgICBtYXR0ZXJ0YWdEYXRhLnNldFBvaShwb2kpO1xuXG4gICAgY29uc3QgY3JlYXRlZFRhZ0lEID0gYXdhaXQgdGhpcy5hZGRNYXR0ZXJ0YWdUb1ZpZXdlcihtYXR0ZXJ0YWdEYXRhKTtcbiAgICBpZiAoY3JlYXRlZFRhZ0lEICYmIHRoaXMuc2RrKSB7XG4gICAgICBhd2FpdCB0aGlzLnNldFRhZ0ljb25BbmRPcGFjaXR5KGNyZWF0ZWRUYWdJRCwgbWF0dGVydGFnRGF0YSk7XG4gICAgICBhd2FpdCB0aGlzLmluamVjdEh0bWxJblRhZyh0YWdUeXBlLCBvYmplY3QsIGNyZWF0ZWRUYWdJRCk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEluamVjdCBjdXN0b20gSFRNTCBhcyBNYXR0ZXJ0YWcgY29udGVudFxuICAgKiBAcGFyYW0gdGFnVHlwZSBQb2lUeXBlXG4gICAqIEBwYXJhbSBvYmplY3QgVGlja2V0LCBFcXVpcG1lbnQsIEZlYXR1cmUgZXRjXG4gICAqIEBwYXJhbSB0YWdJRCBzdHJpbmdcbiAgICovXG4gIGFzeW5jIGluamVjdEh0bWxJblRhZyh0YWdUeXBlOiBQb2lUeXBlLCBvYmplY3Q6IERiT2JqZWN0VHlwZSwgdGFnSUQ6IHN0cmluZykge1xuICAgIGxldCBodG1sID0gYXdhaXQgdGhpcy50YWdTZXJ2aWNlLmdldEh0bWxUb0luamVjdCh0YWdUeXBlLCBvYmplY3QpO1xuICAgIGlmIChodG1sICE9PSAnJyAmJiB0aGlzLnNkaykge1xuICAgICAgY29uc3Qgc2NyaXB0VGFnID0gdGhpcy50YWdTZXJ2aWNlLmdldFNjcmlwdEZvclRhZyhvYmplY3QsIHRhZ1R5cGUpO1xuICAgICAgaHRtbCArPSBgJHtzY3JpcHRUYWd9YDtcbiAgICAgIC8vIGNyZWF0ZSBhbmQgcmVnaXN0ZXIgdGhlIHNhbmRib3hcbiAgICAgIGNvbnN0IFtzYW5kYm94SWQsIG1lc3Nlbmdlcl0gPSBhd2FpdCB0aGlzLnNkay5UYWcucmVnaXN0ZXJTYW5kYm94KGh0bWwpO1xuXG4gICAgICAvLyBkZXRhY2ggcHJldmlvdXMgc2FuZGJveCBmcm9tIGEgdGFnXG4gICAgICBsZXQgYXR0YWNobWVudElEID0gdGhpcy50YWdzQXR0YWNobWVudHNbdGFnSURdO1xuICAgICAgaWYgKGF0dGFjaG1lbnRJRCkge1xuICAgICAgICB0aGlzLnNkay5UYWcuZGV0YWNoKHRhZ0lELCBhdHRhY2htZW50SUQpO1xuICAgICAgfVxuICAgICAgdGhpcy50YWdzQXR0YWNobWVudHNbdGFnSURdID0gc2FuZGJveElkO1xuXG4gICAgICAvLyBhdHRhY2ggdGhlIHNhbmRib3ggdG8gYSB0YWdcbiAgICAgIHRoaXMuc2RrLlRhZy5hdHRhY2godGFnSUQsIHNhbmRib3hJZCk7XG4gICAgICAvLyByZWNlaXZlIGRhdGEgZnJvbSB0aGUgc2FuZGJveFxuICAgICAgLy8gdGFnTWVzc2VuZ2VyT24gYWxsb3dzIHRvIGdvIGhlcmUgb25seSBvbmNlXG4gICAgICBpZiAoIXRoaXMudGFnTWVzc2VuZ2VyT24pIHtcbiAgICAgICAgdGhpcy50YWdNZXNzZW5nZXJPbiA9IHRydWU7XG4gICAgICAgIGNvbnN0IGltYWdlQ2xpY2sgPSAoZmVhdHVyZUlEOiBzdHJpbmcpID0+IHtcbiAgICAgICAgICAvLyBjb25zb2xlLmxvZyhcImltYWdlIGNsaWNrIGhhbmRsZXJcIiwgZmVhdHVyZUlEKTtcbiAgICAgICAgICB0aGlzLnRhZ1NlcnZpY2Uub25BY3Rpb25JbWFnZUNsaWNrKGZlYXR1cmVJRCk7XG4gICAgICAgIH07XG5cbiAgICAgICAgY29uc3QgYXVkaW9DbGljayA9IChhdWRpb0NvbW1lbnRJRDogc3RyaW5nKSA9PiB7XG4gICAgICAgICAgLy8gY29uc29sZS5sb2coXCJhdWRpbyBjbGljayBoYW5kbGVyXCIsIGF1ZGlvQ29tbWVudElEKTtcbiAgICAgICAgICB0aGlzLnRhZ1NlcnZpY2Uub25BY3Rpb25BdWRpb0NsaWNrKGF1ZGlvQ29tbWVudElEKTtcbiAgICAgICAgfTtcbiAgICAgICAgY29uc3QgdmlkZW9DbGljayA9ICh1cmw6IHN0cmluZykgPT4ge1xuICAgICAgICAgIHRoaXMudGFnU2VydmljZS5vbkFjdGlvblZpZGVvQ2xpY2sodXJsKTtcbiAgICAgICAgfTtcbiAgICAgICAgbWVzc2VuZ2VyLm9uKFxuICAgICAgICAgIFRhZ0FjdGlvbi5ERVRBSUxfQ0xJQ0ssXG4gICAgICAgICAgdGhpcy50YWdTZXJ2aWNlLm9uQWN0aW9uRGV0YWlsQ2xpY2suYmluZCh0aGlzLnRhZ1NlcnZpY2UpXG4gICAgICAgICk7XG4gICAgICAgIG1lc3Nlbmdlci5vbihcbiAgICAgICAgICBUYWdBY3Rpb24uVElDS0VUX0NMSUNLLFxuICAgICAgICAgIHRoaXMudGFnU2VydmljZS5vbkFjdGlvbkRldGFpbENsaWNrLmJpbmQodGhpcy50YWdTZXJ2aWNlKVxuICAgICAgICApO1xuICAgICAgICBtZXNzZW5nZXIub24oVGFnQWN0aW9uLkFVRElPX0NMSUNLLCBhdWRpb0NsaWNrKTtcbiAgICAgICAgbWVzc2VuZ2VyLm9uKFRhZ0FjdGlvbi5JTUFHRV9DTElDSywgaW1hZ2VDbGljayk7XG4gICAgICAgIG1lc3Nlbmdlci5vbihUYWdBY3Rpb24uVklERU9fQ0xJQ0ssIHZpZGVvQ2xpY2spO1xuICAgICAgICBtZXNzZW5nZXIub24oXG4gICAgICAgICAgVGFnQWN0aW9uLkRPQ19DTElDSyxcbiAgICAgICAgICB0aGlzLnRhZ1NlcnZpY2Uub25BY3Rpb25Eb2NDbGljay5iaW5kKHRoaXMudGFnU2VydmljZSlcbiAgICAgICAgKTtcbiAgICAgICAgbWVzc2VuZ2VyLm9uKFxuICAgICAgICAgIFRhZ0FjdGlvbi5ZT1VUVUJFX0NMSUNLLFxuICAgICAgICAgIHRoaXMudGFnU2VydmljZS5vbkFjdGlvbllvdXR1YmVDbGljay5iaW5kKHRoaXMudGFnU2VydmljZSlcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgLy8gaWYgaHRtbCBpcyBlbXB0eSAoY2FzZSBvZiBFTUJFRCBjb250ZW50KSwgd2UgZWRpdCBiaWxsYm9hcmQgZm9yIEZlYXR1cmUgYW5kIGF0dGFjaCBuZXcgY29udGVudFxuICAgICAgY29uc3Qge2NvbW1lbnQsIHRhZ0Rlc2NyaXB0aW9ufSA9XG4gICAgICAgIHRoaXMudGFnU2VydmljZS5nZXRCaWxsYm9hcmRNZWRpYVRvRW1iZWQob2JqZWN0KTtcbiAgICAgIGlmIChjb21tZW50KSB7XG4gICAgICAgIC8vIHJlZ2lzdGVyIHRoZSBtZWRpYVxuICAgICAgICBjb25zdCBbYXR0YWNobWVudElEXSA9IGF3YWl0IHRoaXMuc2RrLlRhZy5yZWdpc3RlckF0dGFjaG1lbnQoXG4gICAgICAgICAgY29tbWVudC5leHRlcm5hbExpbmtcbiAgICAgICAgKTtcbiAgICAgICAgLy8gYXR0YWNoXG4gICAgICAgIHRoaXMuc2RrLlRhZy5hdHRhY2godGFnSUQsIGF0dGFjaG1lbnRJRCk7XG4gICAgICAgIHRoaXMuc2RrLlRhZy5lZGl0QmlsbGJvYXJkKHRhZ0lELCB7XG4gICAgICAgICAgbGFiZWw6IG9iamVjdC50aXRsZSxcbiAgICAgICAgICBkZXNjcmlwdGlvbjogdGFnRGVzY3JpcHRpb24sXG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIGFzeW5jIGFjdGlvbl9kZWxldGVfYWxsX21hdHRlcnRhZ3MoKSB7XG4gICAgYXdhaXQgdGhpcy5zZGsuVGFnLnJlbW92ZSguLi50aGlzLm1hdHRlcnRhZ0lEcyk7XG4gICAgdGhpcy5tYXR0ZXJ0YWdJRHMgPSBbXTtcbiAgICB0aGlzLmRpY3Rpb25uYXJ5VGFncy5jbGVhcigpO1xuICB9XG5cbiAgLyoqXG4gICAqIERlbGV0ZXMgTWF0dGVydGFnIGZyb20gdmlzaXQgYXNzb2NpYXRlZCB3aXRoIG9iamVjdCBJRCAodGlja2V0SUQsIGV0YylcbiAgICogQHBhcmFtIGVsZW1lbnRJRCBzdHJpbmdcbiAgICovXG4gIGFzeW5jIGRlbGV0ZU1hdHRlcnRhZ0Zvck9iamVjdChlbGVtZW50SUQ6IHN0cmluZykge1xuICAgIGNvbnN0IG1hdHRlclRhZ0lEID0gdGhpcy5nZXRUYWdGcm9tRWxlbWVudElkKGVsZW1lbnRJRCkudGFnO1xuICAgIGlmIChtYXR0ZXJUYWdJRCkge1xuICAgICAgdHJ5IHtcbiAgICAgICAgYXdhaXQgdGhpcy5zZGsuVGFnLnJlbW92ZShtYXR0ZXJUYWdJRCk7XG4gICAgICAgIHRoaXMuZGljdGlvbm5hcnlUYWdzLmRlbGV0ZShtYXR0ZXJUYWdJRCk7XG4gICAgICAgIGNvbnN0IGluZGV4ID0gdGhpcy5tYXR0ZXJ0YWdJRHMuaW5kZXhPZihtYXR0ZXJUYWdJRCk7XG4gICAgICAgIHRoaXMubWF0dGVydGFnSURzLnNwbGljZShpbmRleCwgMSk7XG4gICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICBjb25zb2xlLmxvZygnQ2Fubm90IGRlbGV0ZSB0YWcnLCBtYXR0ZXJUYWdJRCwgZXJyb3IpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiB1dWlkIGZyb20gdGhyZWVqc1xuICAgKiBAcGFyYW0gdXVpZFxuICAgKi9cbiAgYXN5bmMgZGVsZXRlT2JqZWN0M0QodXVpZDogc3RyaW5nKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgdGhpcy5kaWN0aW9ubmFyeU9iamVjdHMzRC5nZXQodXVpZCkub2JqM0QudmlzaWJsZSA9IGZhbHNlO1xuICB9XG5cbiAgZ2V0T2JqZWN0M0RNb2RlbE5vZGVGcm9tRGljdGlvbm5hcnkodXVpZDogc3RyaW5nKTogYW55IHtcbiAgICAgIGxldCBvYmogPSB0aGlzLmRpY3Rpb25uYXJ5T2JqZWN0czNELmdldCh1dWlkKTtcbiAgICAgIGlmKCFvYmope1xuICAgICAgICBjb25zb2xlLmxvZyhcIndlaXJkIHRoaW5nIGFnYWluXCIpO1xuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgIH1cbiAgICAgIC8vbWlnaHQgYnJlYWsgdGhpbmdzIG9yIGZpeCBldmVyeXRoaW5nIC4uP1xuICAgICAgaWYob2JqLm9iajNELnV1aWQgIT0gdXVpZCl7XG4gICAgICAgIGNvbnNvbGUubG9nKFwid2UgaGF2ZSBUSEUgcHJvYmxlbVwiKTtcbiAgICAgICAgb2JqLm9iajNELnV1aWQgPSB1dWlkOyAvL25vdCBlbnVnaCB0byBmaXggdGhlIHBiXG4gICAgICB9XG5cbiAgICAgIHJldHVybiBvYmo7XG4gIH1cblxuICAvKipcbiAgICogQ3JlYXRlcyAgTWF0dGVydGFnRGF0YSBhbmQgc3RhcnQgcmVwb3NpdGlvbmluZyAoY3JlYXRlcyB0ZW1wb3JhcnkgbWF0dGVydGFnIHRoYXQgZm9sbG93cyB0aGUgY3Vyc29yKVxuICAgKiBAcGFyYW0gcG9pVHlwZSBQb2lUeXBlXG4gICAqIEBwYXJhbSBlbGVtZW50IFRpY2tldCwgRXF1aXBtZW50LCBGZWF0dXJlLCBldGNcbiAgICovXG4gIGFzeW5jIGFkZE1hdHRlcnRhZ1doZW5SZXBvc2l0aW9uaW5nKHBvaVR5cGU6IFBvaVR5cGUsIGVsZW1lbnQ6IERiT2JqZWN0VHlwZSkge1xuICAgIGNvbnN0IG1hdHRlcnRhZ0RhdGEgPSBuZXcgTWF0dGVydGFnRGF0YShwb2lUeXBlKTtcbiAgICAvLyBzZXQgdGhlIGNvb3JkaW5hdGVzIG9mIHRoZSBleGlzdGluZyB0YWdcbiAgICBjb25zdCBbcG9pXSA9IGVsZW1lbnQucG9pcy5pdGVtcztcbiAgICBpZiAocG9pICYmIHBvaS5jb29yZGluYXRlKSB7XG4gICAgICBtYXR0ZXJ0YWdEYXRhLnNldFBvc2l0aW9uKEpTT04ucGFyc2UocG9pLmNvb3JkaW5hdGUpKTtcbiAgICAgIG1hdHRlcnRhZ0RhdGEuc2V0UG9pKHBvaSk7IC8vIHRvIGtlZXAgY3VzdG9tIHRhZ0ljb24gYW5kIG9wYWNpdHlcbiAgICB9XG4gICAgbWF0dGVydGFnRGF0YS5zZXRTd2VlcElEKHRoaXMucG9zZUNhbWVyYS5zd2VlcCk7XG4gICAgbWF0dGVydGFnRGF0YS5zZXRSb3RhdGlvbih0aGlzLnBvc2VDYW1lcmEucm90YXRpb24pO1xuICAgIG1hdHRlcnRhZ0RhdGEuc2V0T2JqZWN0KGVsZW1lbnQsIHBvaVR5cGUpO1xuICAgIHRoaXMubWF0dGVydGFnVG9Gb2xsb3cgPSBhd2FpdCB0aGlzLmFkZE1hdHRlcnRhZ1RvVmlld2VyKG1hdHRlcnRhZ0RhdGEpO1xuICAgIHRoaXMuc2V0SW50ZXJhY3Rpb25Nb2RlKFZpZXdlckludGVyYWN0aW9ucy5QT1NJVElPTklORyk7XG4gICAgYXdhaXQgdGhpcy5hZGRDdXJzb3JNYXR0ZXJ0YWcobWF0dGVydGFnRGF0YSk7XG4gIH1cblxuICAvKipcbiAgICogQ3JlYXRlcyBNYXR0ZXJ0YWdEYXRhIGFuZCBtYXR0ZXJ0YWcgdGhhdCBmb2xsb3dzIHRoZSBjdXJzb3Igd2hlbiBjaG9vc2luZyBwb3NpdGlvbiBmb3IgYSBuZXcgb2JqZWN0XG4gICAqIEBwYXJhbSBwb2lUeXBlXG4gICAqL1xuICBhc3luYyBhZGRNYXR0ZXJ0YWdXaGVuQWRkaW5nKHBvaVR5cGU6IFBvaVR5cGUpIHtcbiAgICBjb25zdCBtYXR0ZXJ0YWdEYXRhID0gbmV3IE1hdHRlcnRhZ0RhdGEocG9pVHlwZSk7XG4gICAgbWF0dGVydGFnRGF0YS5zZXRTd2VlcElEKHRoaXMucG9zZUNhbWVyYS5zd2VlcCk7XG4gICAgbWF0dGVydGFnRGF0YS5zZXRSb3RhdGlvbih0aGlzLnBvc2VDYW1lcmEucm90YXRpb24pO1xuICAgIHRoaXMuc2V0SW50ZXJhY3Rpb25Nb2RlKFZpZXdlckludGVyYWN0aW9ucy5BRERJTkcpO1xuICAgIGF3YWl0IHRoaXMuYWRkQ3Vyc29yTWF0dGVydGFnKG1hdHRlcnRhZ0RhdGEpO1xuICB9XG5cbiAgLyoqXG4gICAqIENhbmNlbHMgZm9sbG93aW5nIG9mIGN1cnNvciAobWVhbmluZyBkZWxldGluZyBsYXN0IE1hdHRlcnRhZylcbiAgICovXG4gIGNhbmNlbEZvbGxvd2luZ0N1cnNvcigpIHtcbiAgICB0aGlzLmRlbGV0ZUxhc3RNYXR0ZXJ0YWcoKTtcbiAgICB0aGlzLnNldEludGVyYWN0aW9uTW9kZShWaWV3ZXJJbnRlcmFjdGlvbnMuREVGQVVMVCk7XG4gIH1cblxuICBzZXRMYXN0T2JqZWN0M0QobGFzdE9iamVjdDNEOiBUaHJlZUpTT2JqZWN0M0QpIHtcbiAgICB0aGlzLmxhc3RPYmplY3QzRCA9IGxhc3RPYmplY3QzRDtcbiAgfVxuXG4gIGdldExhc3RPYmplY3QzRCgpOiBUaHJlZUpTT2JqZWN0M0Qge1xuICAgIHJldHVybiB0aGlzLmxhc3RPYmplY3QzRDtcbiAgfVxuXG4gIC8qKlxuICAgKiBQZXJmb3JtcyBjYWxsYmFjayBhZnRlciBtYXR0ZXJ0YWcgcG9zaXRpb24gd2FzIHZhbGlkYXRlZCAoY3JlYXRpb24gb2Ygb2JqZWN0IG9yIHJlcG9zaXRpb25pbmcpXG4gICAqIEBwYXJhbSBtb2RlIE1hdHRlcnRhZ0FjdGlvbk1vZGVcbiAgICovXG4gIGNhbGxiYWNrQWZ0ZXJNYXR0ZXJ0YWdWYWxpZGF0aW9uKG1vZGU6IE1hdHRlcnRhZ0FjdGlvbk1vZGUpIHtcbiAgICB0aGlzLnZpc2liaWxpdHlTZXJ2aWNlLmRldGFpbFNob3dpbmcubmV4dCh0cnVlKTtcbiAgICBjb25zdCBsYXN0VGFnID0gdGhpcy5nZXRMYXN0VGFnKCk7XG4gICAgc3dpdGNoIChtb2RlKSB7XG4gICAgICBjYXNlIE1hdHRlcnRhZ0FjdGlvbk1vZGUuQUREX0VRVUlQTUVOVDpcbiAgICAgICAgdGhpcy5nb1RvTGFzdFRhZygpO1xuICAgICAgICB0aGlzLnJvdXRlci5uYXZpZ2F0ZShbYHZpc2l0LyR7dGhpcy5jdXJyZW50U3BhY2VJRH0vYWRkX2VxdWlwYF0pO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgTWF0dGVydGFnQWN0aW9uTW9kZS5BRERfVElDS0VUOlxuICAgICAgICB0aGlzLmdvVG9MYXN0VGFnKCk7XG4gICAgICAgIHRoaXMucm91dGVyLm5hdmlnYXRlKFtgdmlzaXQvJHt0aGlzLmN1cnJlbnRTcGFjZUlEfS9hZGRfdGlja2V0YF0pO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgTWF0dGVydGFnQWN0aW9uTW9kZS5BRERfT0JKRUNUM0Q6XG4gICAgICAgIHRoaXMuZ29Ub0xhc3RUYWcoKTtcbiAgICAgICAgdGhpcy5yb3V0ZXIubmF2aWdhdGUoW2B2aXNpdC8ke3RoaXMuY3VycmVudFNwYWNlSUR9L2FkZF9vYmplY3QzZGBdKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIE1hdHRlcnRhZ0FjdGlvbk1vZGUuQUREX0RBVEE6XG4gICAgICAgIHRoaXMuZ29Ub0xhc3RUYWcoKTtcbiAgICAgICAgbGV0IHVybDogc3RyaW5nO1xuICAgICAgICBpZiAodGhpcy5yb3V0ZXIudXJsLmluY2x1ZGVzKCc/JykpIHtcbiAgICAgICAgICB1cmwgPSB0aGlzLnJvdXRlci51cmwuc3Vic3RyaW5nKDAsIHRoaXMucm91dGVyLnVybC5pbmRleE9mKCc/JykpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHVybCA9IHRoaXMucm91dGVyLnVybDtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnJvdXRlci5uYXZpZ2F0ZShbYCR7dXJsfS9hZGRfZmVhdHVyZWBdKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIE1hdHRlcnRhZ0FjdGlvbk1vZGUuQUREX0RFU0s6XG4gICAgICAgIHRoaXMuZ29Ub0xhc3RUYWcoKTtcbiAgICAgICAgdGhpcy5yb3V0ZXIubmF2aWdhdGUoW2B2aXNpdC8ke3RoaXMuY3VycmVudFNwYWNlSUR9L2FkZF9mZWF0dXJlYF0sIHtcbiAgICAgICAgICBxdWVyeVBhcmFtczoge2lzRGVzazogdHJ1ZX0sXG4gICAgICAgIH0pO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgTWF0dGVydGFnQWN0aW9uTW9kZS5BRERfUk9PTTpcbiAgICAgICAgdGhpcy5nb1RvTGFzdFRhZygpO1xuICAgICAgICB0aGlzLnJvdXRlci5uYXZpZ2F0ZShbYHZpc2l0LyR7dGhpcy5jdXJyZW50U3BhY2VJRH0vYWRkX3Jvb21gXSk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSBNYXR0ZXJ0YWdBY3Rpb25Nb2RlLlBPU0lUSU9OX09CSkVDVDNEOlxuICAgICAgICBpZiAobGFzdFRhZykge1xuICAgICAgICAgIC8vIERPIE5vdGhpbmcgKHJvdXRpbmcpLCBqdXN0XG4gICAgICAgICAgdGhpcy5yb3V0ZXIubmF2aWdhdGUoXG4gICAgICAgICAgICBbYHZpc2l0LyR7dGhpcy5jdXJyZW50U3BhY2VJRH0vb2JqZWN0M2QvJHt0aGlzLmxhc3RPYmplY3QzRC5pZH1gXSxcbiAgICAgICAgICAgIHtxdWVyeVBhcmFtczoge3Bvc2l0aW9uaW5nOiB0cnVlfX1cbiAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSBNYXR0ZXJ0YWdBY3Rpb25Nb2RlLlBPU0lUSU9OX1RJQ0tFVDpcbiAgICAgICAgaWYgKGxhc3RUYWcpIHtcbiAgICAgICAgICB0aGlzLnJvdXRlci5uYXZpZ2F0ZShcbiAgICAgICAgICAgIFtcbiAgICAgICAgICAgICAgYHZpc2l0LyR7dGhpcy5jdXJyZW50U3BhY2VJRH0vZGV0YWlsLyR7XG4gICAgICAgICAgICAgICAgdGhpcy5kaWN0aW9ubmFyeVRhZ3MuZ2V0KGxhc3RUYWcpLmVsZW1lbnRJRFxuICAgICAgICAgICAgICB9YCxcbiAgICAgICAgICAgIF0sXG4gICAgICAgICAgICB7cXVlcnlQYXJhbXM6IHtwb3NpdGlvbmluZzogdHJ1ZX19XG4gICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgTWF0dGVydGFnQWN0aW9uTW9kZS5QT1NJVElPTl9FUVVJUE1FTlQ6XG4gICAgICAgIGlmIChsYXN0VGFnKSB7XG4gICAgICAgICAgdGhpcy5yb3V0ZXIubmF2aWdhdGUoXG4gICAgICAgICAgICBbXG4gICAgICAgICAgICAgIGB2aXNpdC8ke3RoaXMuY3VycmVudFNwYWNlSUR9L2VxdWlwLyR7XG4gICAgICAgICAgICAgICAgdGhpcy5kaWN0aW9ubmFyeVRhZ3MuZ2V0KGxhc3RUYWcpLmVsZW1lbnRJRFxuICAgICAgICAgICAgICB9YCxcbiAgICAgICAgICAgIF0sXG4gICAgICAgICAgICB7cXVlcnlQYXJhbXM6IHtwb3NpdGlvbmluZzogdHJ1ZX19XG4gICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgTWF0dGVydGFnQWN0aW9uTW9kZS5QT1NJVElPTl9EQVRBOlxuICAgICAgICBpZiAobGFzdFRhZykge1xuICAgICAgICAgIHRoaXMucm91dGVyLm5hdmlnYXRlKFtdLCB7XG4gICAgICAgICAgICByZWxhdGl2ZVRvOiB0aGlzLmFjdGl2ZVJvdXRlLFxuICAgICAgICAgICAgcXVlcnlQYXJhbXM6IHtwb3NpdGlvbmluZzogdHJ1ZX0sIHF1ZXJ5UGFyYW1zSGFuZGxpbmcgOiBcIm1lcmdlXCJcbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgTWF0dGVydGFnQWN0aW9uTW9kZS5QT1NJVElPTl9ST09NOlxuICAgICAgICBpZiAobGFzdFRhZykge1xuICAgICAgICAgIHRoaXMucm91dGVyLm5hdmlnYXRlKFtdLCB7XG4gICAgICAgICAgICByZWxhdGl2ZVRvOiB0aGlzLmFjdGl2ZVJvdXRlLFxuICAgICAgICAgICAgcXVlcnlQYXJhbXM6IHtwb3NpdGlvbmluZzogdHJ1ZX0sIHF1ZXJ5UGFyYW1zSGFuZGxpbmcgOiBcIm1lcmdlXCJcbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICBicmVhaztcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogRnVsbHkgdXBkYXRlcyBleGlzdGluZyBNYXR0ZXJ0YWcgY29udGVudCB3aXRoIGRhdGEgb2Ygb2JqZWN0IChUaWNrZXQsIEVxdWlwbWVudCwgRGVzaylcbiAgICogQHBhcmFtIG1hdHRlcnRhZ0lEIHN0cmluZ1xuICAgKiBAcGFyYW0gb2JqZWN0IFRpY2tldCwgRXF1aXBtZW50LCBGZWF0dXJlLCBEZXNrXG4gICAqIEBwYXJhbSBwb2lUeXBlIFBvaVR5cGVcbiAgICogQHBhcmFtIHBvaSBQT0lcbiAgICovXG4gIGFzeW5jIHNldE9iamVjdEFuZFBvaUluVGFnKFxuICAgIG1hdHRlcnRhZ0lEOiBzdHJpbmcsXG4gICAgb2JqZWN0OiBEYk9iamVjdFR5cGUsXG4gICAgcG9pVHlwZTogUG9pVHlwZSxcbiAgICBwb2k6IFBPSSB8IG51bGwgPSBudWxsXG4gICk6IFByb21pc2U8dm9pZD4ge1xuICAgIHRoaXMuZGljdGlvbm5hcnlUYWdzLmdldChtYXR0ZXJ0YWdJRCkuc2V0T2JqZWN0KG9iamVjdCwgcG9pVHlwZSk7XG4gICAgaWYgKHBvaSkge1xuICAgICAgdGhpcy5kaWN0aW9ubmFyeVRhZ3MuZ2V0KG1hdHRlcnRhZ0lEKS5zZXRQb2kocG9pKTtcbiAgICB9XG4gICAgdGhpcy5kaWN0aW9ubmFyeVRhZ3MuZ2V0KG1hdHRlcnRhZ0lEKS5lbGVtZW50SUQgPSBvYmplY3QuaWQ7XG4gICAgdHJ5IHtcbiAgICAgIGF3YWl0IHRoaXMudXBkYXRlTWF0dGVyVGFnQ29udGVudEZvclRhZ0lEKG1hdHRlcnRhZ0lELCBvYmplY3QsIHBvaVR5cGUpO1xuICAgICAgLy8gVE9ETzogZml4IHRoaXNcbiAgICAgIGF3YWl0IHRoaXMudXBkYXRlTWF0dGVyVGFnUG9zSW5TZGtWaWV3ZXIoXG4gICAgICAgIG1hdHRlcnRhZ0lELFxuICAgICAgICBvYmplY3QsXG4gICAgICAgIHBvaVR5cGUsXG4gICAgICAgIHBvaVxuICAgICAgKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBjb25zb2xlLmxvZyhgZXJyb3IgaW4gc2V0T2JqZWN0QW5kUG9pSW5UYWc6ICR7ZX1gKTtcbiAgICB9XG4gIH1cblxuICBhc3luYyB1cGRhdGVNYXR0ZXJUYWdQb3NJblNka1ZpZXdlcihcbiAgICBtYXR0ZXJ0YWdJRDogc3RyaW5nLFxuICAgIG9iamVjdDogRGJPYmplY3RUeXBlLFxuICAgIHBvaVR5cGU6IFBvaVR5cGUsXG4gICAgcG9pOiBQT0kgfCBudWxsID0gbnVsbFxuICApOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBjb25zdCBJbmRleFRvVXBkYXRlID0gb2JqZWN0LnBvaXMuaXRlbXMuZmluZEluZGV4KCh1KSA9PiB1LmlkID09PSBwb2kuaWQpO1xuICAgIG9iamVjdC5wb2lzLml0ZW1zW0luZGV4VG9VcGRhdGVdID0gcG9pO1xuICAgIGNvbnN0IHt4LCB5LCB6fSA9IEpTT04ucGFyc2UocG9pLmNvb3JkaW5hdGUpO1xuICAgIGNvbnN0IG5ld1Bvc2l0aW9uID0ge1xuICAgICAgYW5jaG9yUG9zaXRpb246IHtcbiAgICAgICAgeDogeCxcbiAgICAgICAgeTogeSxcbiAgICAgICAgejogeixcbiAgICAgIH0sXG4gICAgICBzdGVtVmVjdG9yOiB7XG4gICAgICAgIC8vIG1ha2UgdGhlIFRhZyBzdGljayBzdHJhaWdodCB1cCBhbmQgbWFrZSBpdCAwLjMwIG1ldGVycyAofjEgZm9vdCkgdGFsbFxuICAgICAgICB4OiAwLFxuICAgICAgICB5OiAwLjMsXG4gICAgICAgIHo6IDAsXG4gICAgICB9LFxuICAgIH07XG4gICAgdGhpcy5zZGsuTWF0dGVydGFnLmVkaXRQb3NpdGlvbihtYXR0ZXJ0YWdJRCwgbmV3UG9zaXRpb24pO1xuICAgIHRoaXMuc2RrLlRhZy5lZGl0UG9zaXRpb24obWF0dGVydGFnSUQsIG5ld1Bvc2l0aW9uKTtcbiAgICB0aGlzLmRpY3Rpb25uYXJ5VGFnc1xuICAgICAgLmdldChtYXR0ZXJ0YWdJRClcbiAgICAgIC5zZXRQb3NpdGlvbihuZXdQb3NpdGlvbi5hbmNob3JQb3NpdGlvbik7XG5cbiAgICBmb3IgKGxldCB0YWdJZCBvZiB0aGlzLm1hdHRlcnRhZ0lEcykge1xuICAgICAgY29uc3QgY3VycmVudFRhZyA9IHRoaXMuZGljdGlvbm5hcnlUYWdzLmdldCh0YWdJZCk7XG4gICAgICBpZiAoIWN1cnJlbnRUYWcpIHtcbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG4gICAgICBpZiAoY3VycmVudFRhZy5lbGVtZW50SUQgPT09IG9iamVjdC5pZCAmJiB0YWdJZCAhPT0gbWF0dGVydGFnSUQpIHtcbiAgICAgICAgdGhpcy5kaWN0aW9ubmFyeVRhZ3MuZGVsZXRlKHRhZ0lkKTtcbiAgICAgICAgdGhpcy5zZGsuVGFnLnJlbW92ZSh0YWdJZCk7XG4gICAgICAgIHRoaXMuc2RrLk1hdHRlcnRhZy5yZW1vdmUodGFnSWQpO1xuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogR2V0cyBtYXR0ZXJUYWdJRCBhbmQgaXRzIHN3ZWVwIGZvciBhbiBvYmplY3QgSUQgKHRpY2tldCBJRCwgZXRjKVxuICAgKiBAcGFyYW0gZWxlbWVudElEIHN0cmluZ1xuICAgKiBAcmV0dXJucyB7dGFnOiBzdHJpbmcgfCBudWxsLCBzd2VlcDogc3RyaW5nIHwgbnVsbH1cbiAgICovXG4gIHB1YmxpYyBnZXRUYWdGcm9tRWxlbWVudElkKGVsZW1lbnRJRDogc3RyaW5nKToge1xuICAgIHRhZzogc3RyaW5nIHwgbnVsbDtcbiAgICBzd2VlcDogc3RyaW5nIHwgbnVsbDtcbiAgfSB7XG4gICAgbGV0IHRhZ0lEID0gbnVsbDtcbiAgICBsZXQgc3dlZXBJRCA9IG51bGw7XG4gICAgZm9yIChsZXQgW21hdHRlcnRhZ0lELCBtYXR0ZXJ0YWdEYXRhXSBvZiB0aGlzLmRpY3Rpb25uYXJ5VGFncykge1xuICAgICAgaWYgKG1hdHRlcnRhZ0RhdGEuZWxlbWVudElEID09PSBlbGVtZW50SUQpIHtcbiAgICAgICAgdGFnSUQgPSBtYXR0ZXJ0YWdJRDtcbiAgICAgICAgY29uc3Qgc3dlZXAgPSBtYXR0ZXJ0YWdEYXRhLmdldFN3ZWVwSUQoKTtcbiAgICAgICAgaWYgKHN3ZWVwICYmIHRoaXMuc3dlZXBzICYmIHRoaXMuc3dlZXBzLmluY2x1ZGVzKHN3ZWVwKSkge1xuICAgICAgICAgIHN3ZWVwSUQgPSBzd2VlcDtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4ge3RhZzogdGFnSUQsIHN3ZWVwOiBzd2VlcElEfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXRzIGxhdGVzdCB0YWcgY3JlYXRlZCBpbiB0aGUgdmlzaXQgKHdoZW4gZm9sbG93aW5nIHRoZSBjdXJzb3IgdG8gcG9zaXRpb24pXG4gICAqIEByZXR1cm5zIHN0cmluZyBtYXR0ZXJ0YWdJRFxuICAgKi9cbiAgZ2V0TGFzdFRhZygpOiBzdHJpbmcgfCBudWxsIHtcbiAgICBpZiAodGhpcy5tYXR0ZXJ0YWdUb0ZvbGxvdykge1xuICAgICAgcmV0dXJuIHRoaXMubWF0dGVydGFnVG9Gb2xsb3c7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiB0aGlzLm1hdHRlcnRhZ0lEcy5sZW5ndGggPT09IDBcbiAgICAgICAgPyBudWxsXG4gICAgICAgIDogdGhpcy5tYXR0ZXJ0YWdJRHNbdGhpcy5tYXR0ZXJ0YWdJRHMubGVuZ3RoIC0gMV07XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEdldHMgTWF0dGVydGFnRGF0YSBmb3IgTWF0dGVydGFnIChyZXBsYWNlcyBnZXRUYWdEYXRhRnJvbUlkKVxuICAgKiBAcGFyYW0gbWF0dGVydGFnSURcbiAgICogQHJldHVybnMgTWF0dGVydGFnRGF0YVxuICAgKi9cbiAgZ2V0TWF0dGVyVGFnRGF0YUZvck1hdHRlcnRhZyhtYXR0ZXJ0YWdJRDogc3RyaW5nKTogTWF0dGVydGFnRGF0YSB8IG51bGwge1xuICAgIHRyeSB7XG4gICAgICByZXR1cm4gdGhpcy5kaWN0aW9ubmFyeVRhZ3MuZ2V0KG1hdHRlcnRhZ0lEKTtcbiAgICB9IGNhdGNoIHtcbiAgICAgIGNvbnNvbGUubG9nKCdjYW5ub3QgcmV0cmlldmUgbWF0dGVydGFnRGF0YSBmb3IgdGFnJywgbWF0dGVydGFnSUQpO1xuICAgIH1cbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIC8vXG4gIC8vIC0tLS0tLS0tLS0gVmlld2VyIHJlbGF0ZWQgKHN3aXRjaCB2aWV3cywgZ28gdG8pIC0tLS0tLS0tLS1cbiAgLy9cbiAgYXN5bmMgYWN0aW9uX3Rvb2xib3hfZmxvb3JwbGFuKCkge1xuICAgIGlmICh0aGlzLmluVHJhbnNpdGlvbk1vZGUgfHwgdGhpcy5pblRyYW5zaXRpb25Td2VlcCkge1xuICAgICAgY29uc29sZS5sb2coJ3ZpZXdlciBpcyBpbiB0cmFuc2l0aW9uLCBjYW5ub3QgZ28gZmxvb3JwbGFuJyk7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIHRyeSB7XG4gICAgICBhd2FpdCB0aGlzLnNkay5Nb2RlLm1vdmVUbygnbW9kZS5mbG9vcnBsYW4nKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBjb25zb2xlLmxvZygnY2Fubm90IGdvIHRvIGZsb29ycGxhbicsIGUpO1xuICAgIH1cbiAgfVxuXG4gIGFjdGlvbl90b29sYm94X2luc2lkZV92aWV3KCkge1xuICAgIHRoaXMuc2RrLk1vZGUubW92ZVRvKCdtb2RlLmluc2lkZScpO1xuICB9XG5cbiAgYWN0aW9uU2hvd0FsbEZsb29ycygpIHtcbiAgICB0cnkge1xuICAgICAgdGhpcy5zZGsuRmxvb3Iuc2hvd0FsbCgpO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGNvbnNvbGUubG9nKCdjYW5ub3Qgc2hvdyBhbGwgZmxvb3JzJywgZSk7XG4gICAgfVxuICB9XG5cbiAgYXN5bmMgYWN0aW9uX3Rvb2xib3hfZG9sbGhvdXNlKCkge1xuICAgIHNldFRpbWVvdXQoYXN5bmMgKCkgPT4ge1xuICAgICAgLy8gY29uc29sZS5sb2coXCJtb2RlOiBcIiwgdGhpcy5pblRyYW5zaXRpb25Nb2RlLCBcIiBzd2VlcDogXCIsIHRoaXMuaW5UcmFuc2l0aW9uU3dlZXApO1xuICAgICAgaWYgKHRoaXMuaW5UcmFuc2l0aW9uTW9kZSB8fCB0aGlzLmluVHJhbnNpdGlvblN3ZWVwKSB7XG4gICAgICAgIGNvbnNvbGUubG9nKCd2aWV3ZXIgaXMgaW4gdHJhbnNpdGlvbiwgY2Fubm90IGdvIGRvbGxob3VzZScpO1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgICB0cnkge1xuICAgICAgICBhd2FpdCB0aGlzLnNkay5Nb2RlLm1vdmVUbygnbW9kZS5kb2xsaG91c2UnKTtcbiAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgY29uc29sZS5sb2coJ2Nhbm5vdCBnbyB0byBkb2xsaG91c2UnLCBlKTtcbiAgICAgIH1cbiAgICB9LCAxMjAwKTtcbiAgfVxuXG4gIGFjdGlvbl90b29sYm94X21lc3VyZSgpIHtcbiAgICBjb25zdCBuZXdTdGF0ZSA9ICF0aGlzLmlzTWVhc3VyZU1vZGVPbjtcbiAgICB0aGlzLnNkay5NZWFzdXJlbWVudHMudG9nZ2xlTW9kZShuZXdTdGF0ZSkudGhlbigoKSA9PiB7XG4gICAgICBjb25zb2xlLmxvZyhcbiAgICAgICAgYE1lYXN1cmVtZW50IG1vZGUgaXMgbm93ICR7bmV3U3RhdGUgPyAnZW5hYmxlZCcgOiAnZGlzYWJsZWQnfWBcbiAgICAgICk7XG4gICAgfSk7XG4gIH1cblxuICBhY3Rpb25fdG9vbGJveF9jYW5jZWxfbWVzdXJlKCkge1xuICAgIGlmICh0aGlzLmlzTWVhc3VyZU1vZGVPbikge1xuICAgICAgdGhpcy5hY3Rpb25fdG9vbGJveF9tZXN1cmUoKTtcbiAgICB9XG4gIH1cblxuICBhc3luYyBhY3Rpb25fZ29fdG9fZmxvb3IoXG4gICAgZmxvb3JOYW1lOiBzdHJpbmcsXG4gICAgbWF0dGVycG9ydEZsb29yU2VxdWVuY2U6IG51bWJlciA9IG51bGxcbiAgKSB7XG4gICAgaWYgKCF0aGlzLmZsb29ycykge1xuICAgICAgY29uc29sZS5sb2coJ0Zsb29yIGFyZSBub3QgbG9hZGVkIHlldCcpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICAvLyBjb25zb2xlLmxvZyh0aGlzLmZsb29ycyk7XG4gICAgLy8gbG9vayB1cCBmb3Igc2VxdWVuY2UgbnVtYmVyICh0aGUgc2FmZXN0IG1ldGhvZClcbiAgICBsZXQgZmxvb3JNYXR0ZXJwb3J0ID0gdGhpcy5mbG9vcnMuZmluZChcbiAgICAgIChmbG9vcikgPT4gZmxvb3Iuc2VxdWVuY2UgPT09IG1hdHRlcnBvcnRGbG9vclNlcXVlbmNlXG4gICAgKTtcbiAgICBpZiAoIWZsb29yTWF0dGVycG9ydCkge1xuICAgICAgZmxvb3JNYXR0ZXJwb3J0ID0gdGhpcy5mbG9vcnMuZmluZChcbiAgICAgICAgKGZsb29yKSA9PiBmbG9vck5hbWUuaW5jbHVkZXMoZmxvb3IubmFtZSkgJiYgZmxvb3IubmFtZSAhPSAnJ1xuICAgICAgKTtcbiAgICB9XG4gICAgaWYgKCFmbG9vck1hdHRlcnBvcnQpIHtcbiAgICAgIGZsb29yTWF0dGVycG9ydCA9IHRoaXMuZmxvb3JzLmZpbmQoKGZsb29yKSA9PlxuICAgICAgICBmbG9vck5hbWUuaW5jbHVkZXMoZmxvb3IuaWQpXG4gICAgICApO1xuICAgIH1cbiAgICAvLyBjb25zb2xlLmxvZyhmbG9vck1hdHRlcnBvcnQpXG4gICAgaWYgKGZsb29yTWF0dGVycG9ydCkge1xuICAgICAgbGV0IHJldHJ5ID0gdHJ1ZTtcbiAgICAgIHdoaWxlIChyZXRyeSkge1xuICAgICAgICB0cnkge1xuICAgICAgICAgIGNvbnN0IGZsb29ySW5kZXggPSBhd2FpdCB0aGlzLnNkay5GbG9vci5tb3ZlVG8oXG4gICAgICAgICAgICBmbG9vck1hdHRlcnBvcnQuc2VxdWVuY2VcbiAgICAgICAgICApO1xuICAgICAgICAgIC8vIGNvbnNvbGUubG9nKFwibW92ZWQgdG8gZmxvb3JJbmRleFwiLCBmbG9vckluZGV4KTtcbiAgICAgICAgICByZXRyeSA9IGZhbHNlO1xuICAgICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICAgIGNvbnNvbGUubG9nKCdDYW5ub3QgbW92ZSB0byBGbG9vcicsIGVycm9yKTtcbiAgICAgICAgICBhd2FpdCB3YWl0KDEwMCk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgY29uc29sZS53YXJuKCdObyBtYXR0ZXJwb3J0IGZsb29yIGZvdW5kIHRvIG1vdmUgdG8nKTtcbiAgICB9XG4gIH1cblxuICBhc3luYyBhY3Rpb25fZ29fdG9fc3dlZXAoXG4gICAgc3dlZXA6IHN0cmluZyxcbiAgICByb3RhdGlvbjogeyB4OiBudW1iZXI7IHk6IG51bWJlciB9ID0gbnVsbFxuICApIHtcbiAgICBpZiAodGhpcy5mb3JiaWRkZW5Td2VlcHMuaW5jbHVkZXMoc3dlZXApKSB7XG4gICAgICBjb25zb2xlLmxvZygndXNlciBpcyBub3QgYWxsb3dlZCB0byBnbyB0byB0aGlzIHN3ZWVwJyk7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIC8vIGNvbnNvbGUubG9nKFwiZ29pbmcgdG8gc3dlZXBcIiwgc3dlZXAsIFwid2l0aCByb3RhdGlvbjpcIiwgcm90YXRpb24pO1xuICAgIHNldFRpbWVvdXQoYXN5bmMgKCkgPT4ge1xuICAgICAgaWYgKHRoaXMuaW5UcmFuc2l0aW9uTW9kZSB8fCB0aGlzLmluVHJhbnNpdGlvblN3ZWVwKSB7XG4gICAgICAgIGNvbnNvbGUubG9nKCdDYW5ub3QgZ28gdG8gc3dlZXAsIGluIHRyYW5zaXRpb24nKTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgICAgdHJ5IHtcbiAgICAgICAgdGhpcy5pblRyYW5zaXRpb25Td2VlcCA9IHRydWU7XG4gICAgICAgIGF3YWl0IHRoaXMuc2RrLlN3ZWVwLm1vdmVUbyhzd2VlcCwge1xuICAgICAgICAgIHRyYW5zaXRpb246ICd0cmFuc2l0aW9uLmluc3RhbnQnLFxuICAgICAgICAgIHRyYW5zaXRpb25UaW1lOiAxNTAwLFxuICAgICAgICB9KTtcbiAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgIHRoaXMuaW5UcmFuc2l0aW9uU3dlZXAgPSBmYWxzZTtcbiAgICAgICAgY29uc29sZS5sb2coJ0Nhbm5vdCBtb3ZlIHRvIHN3ZWVwJywgZXJyb3IpO1xuICAgICAgfVxuICAgICAgaWYgKHJvdGF0aW9uKSB7XG4gICAgICAgIGF3YWl0IHRoaXMuc2RrLkNhbWVyYS5zZXRSb3RhdGlvbihyb3RhdGlvbiwge3NwZWVkOiAxMDB9KTsgLy8gc3BlZWQgaXMgZGVncmVlcyBwZXIgc2Vjb25kXG4gICAgICB9XG4gICAgfSwgMTAwMCk7XG4gIH1cblxuICBnZXRDdXJyZW50U3dlZXAoKTogc3RyaW5nIHwgbnVsbCB7XG4gICAgaWYgKHRoaXMucG9zZUNhbWVyYSkge1xuICAgICAgcmV0dXJuIHRoaXMucG9zZUNhbWVyYS5zd2VlcDtcbiAgICB9XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICBnZXRDdXJyZW50Q2FtZXJhUG9zaXRpb24oKToge1xuICAgIHJvdGF0aW9uOiBhbnk7XG4gICAgcG9zaXRpb246IGFueTtcbiAgICBzd2VlcDogYW55O1xuICB9IHwgbnVsbCB7XG4gICAgaWYgKHRoaXMucG9zZUNhbWVyYSkge1xuICAgICAgcmV0dXJuIHRoaXMucG9zZUNhbWVyYTtcbiAgICB9XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICBzZXRJbnRlcmFjdGlvbk1vZGUoaW50ZXJhY3Rpb25Nb2RlOiBudW1iZXIpIHtcbiAgICB0aGlzLmludGVyYWN0aW9uTW9kZSA9IGludGVyYWN0aW9uTW9kZTtcbiAgfVxuXG4gIGdldEludGVyYWN0aW9uTW9kZSgpIHtcbiAgICByZXR1cm4gdGhpcy5pbnRlcmFjdGlvbk1vZGU7XG4gIH1cblxuICAvKipcbiAgICogQ2xlYXIgYWxsIHZhcmlhYmxlcywgZGVsZXRlcyBhbGwgdGFncyAod2hlbiB2aWV3ZXIgaXMgcmVtb3ZlciBvciBtb2RlbCBjaGFuZ2VkPXJlbG9hZCBuZWVkZWQpXG4gICAqL1xuICBhc3luYyBjbGVhckFsbCgpIHtcbiAgICBjb25zb2xlLmxvZygncmVtb3Zpbmcgdmlld2VyJyk7XG4gICAgdGhpcy5hY3Rpb25fZGVsZXRlX2FsbF9tYXR0ZXJ0YWdzKCk7XG4gICAgdGhpcy5mbG9vcnMgPSBudWxsO1xuICAgIHRoaXMuc3dlZXBzID0gbnVsbDtcbiAgICB0aGlzLnNkayA9IG51bGw7XG4gICAgY2xlYXJJbnRlcnZhbCh0aGlzLnRpbWVyUG9pbnRlcik7XG4gICAgdGhpcy5mb3JiaWRkZW5Td2VlcHMgPSBbXTtcbiAgICB0aGlzLnRhZ01lc3Nlbmdlck9uID0gZmFsc2U7XG4gICAgLy8gY2FuY2VsIHN1YnNjcmlwdGlvbnNcbiAgICB0aGlzLnBvaW50ZXJCdXR0b24ucmVtb3ZlRXZlbnRMaXN0ZW5lcihcbiAgICAgICdjbGljaycsXG4gICAgICB0aGlzLnBvaW50ZXJMZWZ0Q2xpY2tIYW5kbGVyXG4gICAgKTtcbiAgICB0aGlzLnBvaW50ZXJCdXR0b24ucmVtb3ZlRXZlbnRMaXN0ZW5lcihcbiAgICAgICdjb250ZXh0bWVudScsXG4gICAgICB0aGlzLnBvaW50ZXJSaWdodENsaWNrSGFuZGxlclxuICAgICk7XG5cbiAgICAvLyBUT0RPOiBvbmx5IEZvciBBZG1pbnNcbiAgICBpZiAodGhpcy5nZXRDdXJzb3JQb3NpdGlvbkJ1dHRvbikge1xuICAgICAgdGhpcy5nZXRDdXJzb3JQb3NpdGlvbkJ1dHRvbi5yZW1vdmVFdmVudExpc3RlbmVyKFxuICAgICAgICAnYXV4Y2xpY2snLFxuICAgICAgICB0aGlzLnBvaW50ZXJNaWRkbGVDbGlja0hhbmRsZXJcbiAgICAgICk7XG4gICAgfVxuICAgIC8vIFRPRE86IG9ubHkgZm9yIGRldiFcbiAgICBpZiAoISF0aGlzLmdldEN1cnNvclBvc2l0aW9uQnV0dG9uICYmXG4gICAgICAoZG9jdW1lbnQubG9jYXRpb24uaHJlZi5pbmRleE9mKCdkZXYnKSAhPT0gLTEgfHwgZG9jdW1lbnQubG9jYXRpb24uaHJlZi5pbmRleE9mKCdsb2NhbGhvc3QnKSAhPT0gLTEpKSB7XG4gICAgICBjbGVhckludGVydmFsKHRoaXMuaW50ZXJ2YWxDdXJzb3JQb2ludGVyUG9zaXRpb24pO1xuICAgIH1cbiAgfVxuXG4gIGFzeW5jIHJlbW92ZUZvcmJpZGRlblN3ZWVwcyhmb3JiaWRkZW5Td2VlcHM6IHN0cmluZ1tdKSB7XG4gICAgdGhpcy5mb3JiaWRkZW5Td2VlcHMgPSBbLi4uZm9yYmlkZGVuU3dlZXBzXTtcbiAgICBsZXQgcmVtb3ZlZCA9IDA7XG4gICAgYXdhaXQgUHJvbWlzZS5hbGwoXG4gICAgICBmb3JiaWRkZW5Td2VlcHMubWFwKGFzeW5jIChzd2VlcCkgPT4ge1xuICAgICAgICB0cnkge1xuICAgICAgICAgIGF3YWl0IHRoaXMuc2RrLlN3ZWVwLmRpc2FibGUoc3dlZXApO1xuICAgICAgICAgIHJlbW92ZWQgKz0gMTtcbiAgICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgICBjb25zb2xlLmxvZyhlcnJvcik7XG4gICAgICAgIH1cbiAgICAgIH0pXG4gICAgKTtcbiAgICBjb25zb2xlLmxvZygncmVtb3ZlZCBzd2VlcHM6JywgcmVtb3ZlZCk7XG4gIH1cblxuICAvL1xuICAvLyAtLS0tLS0tLS0tIDNEIG9iamVjdHMgKFNESyBCdW5kbGUgb25seSkgLS0tLS0tLS0tLVxuICAvL1xuICBhc3luYyBpbml0M0RPYmplY3RWaWV3ZXIoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKGFzeW5jIChyZXNvbHZlKSA9PiB7XG4gICAgICB2YXIgW3NjZW5lT2JqZWN0XSA9IGF3YWl0IHRoaXMuc2RrLlNjZW5lLmNyZWF0ZU9iamVjdHMoMSk7XG5cbiAgICAgIHZhciBub2RlID0gc2NlbmVPYmplY3QuYWRkTm9kZSgpO1xuXG4gICAgICAvLyBUT0RPIGNoYW5nZSB0aGlzIPCfpK5cbiAgICAgIG5vZGUuYWRkQ29tcG9uZW50KCdtcC5saWdodHMnKTtcbiAgICAgIC8vbm9kZS5hZGRDb21wb25lbnQoJ21wLmxpZ2h0cycpO1xuICAgICAgLypub2RlLmFkZENvbXBvbmVudCgnbXAubGlnaHRzJyk7XG4gICAgICBub2RlLmFkZENvbXBvbmVudCgnbXAubGlnaHRzJyk7Ki9cbiAgICAgIG5vZGUuc3RhcnQoKTtcblxuICAgICAgY29uc3Qgbm9kZUNvbnRyb2wgPSBzY2VuZU9iamVjdC5hZGROb2RlKCk7XG4gICAgICB0aGlzLm9iamVjdENvbnRyb2wgPSBub2RlQ29udHJvbC5hZGRDb21wb25lbnQoJ21wLnRyYW5zZm9ybUNvbnRyb2xzJyk7XG4gICAgICBub2RlQ29udHJvbC5zdGFydCgpO1xuXG4gICAgICAvL3RoaXMuYWRkM0RPYmplY3Qoe30sbnVsbCk7XG5cbiAgICAgIHJlc29sdmUoKTtcbiAgICB9KTtcbiAgfVxuXG4gIGFzeW5jIGFkZDNET2JqZWN0KFxuICAgIG9iajogSU9iamVjdDNELFxuICAgIG1vZGU/OiAndHJhbnNsYXRlJyB8ICdyb3RhdGUnXG4gICk6IFByb21pc2U8YW55PiB7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKGFzeW5jIChyZXNvbHZlKSA9PiB7XG4gICAgICBjb25zdCBbc2NlbmVPYmplY3RdID0gYXdhaXQgdGhpcy5zZGsuU2NlbmUuY3JlYXRlT2JqZWN0cygxKTtcblxuICAgICAgLy8gVE9ETzogaW1wcm92bWVudCwgcmVncm91cCBhbGwgb2YgdGhlc2UgaW4gRHluYW1pY2FsIE9iamVjdHMgTGliXG4gICAgICAvLyBTZWN1cml0eUNhbWVyYVxuICAgICAgLy8gTmVzdFRoZXJtb3N0YXRcbiAgICAgIC8vIFZpZGVvXG4gICAgICBsZXQgaXNBbmltYXRlZFNlY3VyaXR5Q2FtZXJhID0gZmFsc2U7XG4gICAgICBsZXQgaXNOZXN0VGhlcm1vc3RhdCA9IGZhbHNlO1xuICAgICAgbGV0IGlzU21hcnRlcnBsYW5Qcm9tb3Rpb25hbFZpZGVvID0gZmFsc2U7XG4gICAgICBsZXQgaXNBemltdXRoYWxDcm93biA9IGZhbHNlO1xuXG4gICAgICAvKipcbiAgICAgICAqIFRPRE86IHJlZmFjdG8gd2l0aCBhbiBlbnVtIG9yIHN3aXRjaC9jYXNlXG4gICAgICAgKi9cbiAgICAgIGlmIChvYmoub2JqZWN0ID09PSBcInNlY3VyaXR5X2NhbWVyYVwiKSB7XG4gICAgICAgIGlzQW5pbWF0ZWRTZWN1cml0eUNhbWVyYSA9IHRydWU7XG4gICAgICB9XG4gICAgICBpZiAob2JqLm9iamVjdCA9PT0gXCJuZXN0X3RoZXJtb3N0YXRcIikge1xuICAgICAgICBpc05lc3RUaGVybW9zdGF0ID0gdHJ1ZTtcbiAgICAgIH1cbiAgICAgIGlmIChvYmoub2JqZWN0ID09PSAndmlkZW8nKSB7XG4gICAgICAgIGlzU21hcnRlcnBsYW5Qcm9tb3Rpb25hbFZpZGVvID0gdHJ1ZTtcbiAgICAgIH1cbiAgICAgIGlmKG9iai5vYmplY3QgPT09ICdhemltdXRoJykge1xuICAgICAgICBpc0F6aW11dGhhbENyb3duID0gdHJ1ZTtcbiAgICAgIH1cblxuICAgICAgY29uc3QgbW9kZWxOb2RlID0gc2NlbmVPYmplY3QuYWRkTm9kZSgpO1xuICAgICAgbGV0IGNvbXBvbmVudCA9IG51bGw7XG4gICAgICBjb25zdCBpbml0aWFsID0ge1xuICAgICAgICB1cmw6IGAvYXNzZXRzLzNEb2JqZWN0cy9vYmplY3RzLyR7b2JqLm9iamVjdH0ke1xuICAgICAgICAgIG9iai5mb3JtYXQuaW5kZXhPZignLicpID09PSAtMSA/ICcuJyArIG9iai5mb3JtYXQgOiBvYmouZm9ybWF0XG4gICAgICAgIH1gLFxuICAgICAgICAvLyBUT0RPLyBzdG9yZSBsb2NhbFBvc2l0aW9uICYmIGxvY2FsUm90YXRpb24gaW4gQkREIHRvbyAoaW4gb3JkZXIgdG8gaGF2ZSBwZXJ0ZmVjdCBpbml0aWFsIHBsYWNlbWVudClcbiAgICAgICAgbG9jYWxSb3RhdGlvbjoge1wieFwiOiAwLCBcInlcIjogMCwgXCJ6XCI6IDB9LFxuICAgICAgICAvLyBUT0RPLyBzdG9yZSBsb2NhbFBvc2l0aW9uICYmIGxvY2FsUm90YXRpb24gaW4gQkREIHRvbyAoaW4gb3JkZXIgdG8gaGF2ZSBwZXJ0ZmVjdCBpbml0aWFsIHBsYWNlbWVudClcbiAgICAgICAgbG9jYWxQb3NpdGlvbjoge1wieFwiOiAwLCBcInlcIjogMCwgXCJ6XCI6IDB9LFxuICAgICAgICB2aXNpYmxlOiB0cnVlLFxuICAgICAgICBjb2xsaWRlckVuYWJsZWQ6IHRydWVcbiAgICAgIH07XG5cblxuICAgICAgc3dpdGNoIChvYmouZm9ybWF0KSB7XG4gICAgICAgIGNhc2UgJy5vYmonOlxuICAgICAgICBjYXNlICdvYmonOlxuICAgICAgICAgIGNvbXBvbmVudCA9IG1vZGVsTm9kZS5hZGRDb21wb25lbnQoJ21wLm9iakxvYWRlcicsIGluaXRpYWwpO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlICcuZmJ4JzpcbiAgICAgICAgY2FzZSAnZmJ4JzpcbiAgICAgICAgICBjb21wb25lbnQgPSBtb2RlbE5vZGUuYWRkQ29tcG9uZW50KCdtcC5mYnhMb2FkZXInLCBpbml0aWFsKTtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSAnLmdsdGYnOlxuICAgICAgICBjYXNlICdnbHRmJzpcbiAgICAgICAgICBjb21wb25lbnQgPSBtb2RlbE5vZGUuYWRkQ29tcG9uZW50KCdtcC5nbHRmTG9hZGVyJywgaW5pdGlhbCk7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgJy5nbGInOlxuICAgICAgICBjYXNlICdnbGInOlxuICAgICAgICAgIGNvbXBvbmVudCA9IG1vZGVsTm9kZS5hZGRDb21wb25lbnQoJ21wLmdsdGZMb2FkZXInLCBpbml0aWFsKTtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSAnLmRhZSc6XG4gICAgICAgIGNhc2UgJ2RhZSc6XG4gICAgICAgICAgY29tcG9uZW50ID0gbW9kZWxOb2RlLmFkZENvbXBvbmVudCgnbXAuZGFlTG9hZGVyJywgaW5pdGlhbCk7XG4gICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICBjb25zb2xlLmxvZygnRm9ybWF0IG5vdCBzdXBwb3J0ZWQnKTtcbiAgICAgICAgICBicmVhaztcbiAgICAgIH1cblxuICAgICAgLy9jYWNoZSBzeXN0ZW0gKGknbGwgdHJ5IHRvIG1ha2UgaXQgd29yayBsYXRlciAuLi4pXG4gICAgICAvKmxldCBvYmpDb250ZW50c0pTT04gPSBKU09OLnN0cmluZ2lmeShtb2RlbE5vZGUpO1xuICAgICAgY29uc29sZS5sb2cobW9kZWxOb2RlKTtcbiAgICAgIGNvbnNvbGUubG9nKG9iakNvbnRlbnRzSlNPTik7XG4gICAgICBjb25zb2xlLmxvZyhKU09OLnN0cmluZ2lmeShtb2RlbE5vZGUpKTtcbiAgICAgIGxvY2FsU3RvcmFnZS5zZXRJdGVtKGB0ZXN0T2JqXyR7b2JqLm9iamVjdH1gLCBvYmpDb250ZW50c0pTT04pO1xuICAgICAgY29uc29sZS5sb2coXCJzdG9yZWQgPyFcIik7XG4gICAgICBjb25zb2xlLmxvZyh0eXBlb2YgbW9kZWxOb2RlKTsqL1xuICAgICAgLy9sZXQgZGF0YVMgPSBzZXJpYWxpanNlLnNlcmlhbGl6ZShtb2RlbE5vZGUpO1xuICAgICAgLy9jb25zb2xlLmxvZyhkYXRhUyk7XG5cbiAgICAgIC8vIFVzZSAzID8hIEFtYmllbnQgbGlnaHRpbmdzXG4gICAgICBpZiAodGhpcy5ub0xpZ2h0Rm9yT2JqZWN0cykge1xuICAgICAgICBjb25zdCBsaWdodHNOb2RlID0gc2NlbmVPYmplY3QuYWRkTm9kZSgpO1xuICAgICAgICBsaWdodHNOb2RlLmFkZENvbXBvbmVudCgnbXAuYW1iaWVudExpZ2h0Jywge1xuICAgICAgICAgIGludGVuc2l0eTogMSxcbiAgICAgICAgICBjb2xvcjoge3I6IDEuMCwgZzogMS4wLCBiOiAxLjB9LFxuICAgICAgICB9KTtcbiAgICAgICAgdGhpcy5ub0xpZ2h0Rm9yT2JqZWN0cyA9IGZhbHNlO1xuICAgICAgfVxuXG4gICAgICBtb2RlbE5vZGUub2JqM0QucG9zaXRpb24uc2V0KFxuICAgICAgICBvYmoucG9zaXRpb24ueCxcbiAgICAgICAgb2JqLnBvc2l0aW9uLnksXG4gICAgICAgIG9iai5wb3NpdGlvbi56XG4gICAgICApO1xuXG4gICAgICBtb2RlbE5vZGUub2JqM0Qucm90YXRpb24uc2V0KFxuICAgICAgICBvYmoucm90YXRpb24ueCxcbiAgICAgICAgb2JqLnJvdGF0aW9uLnksXG4gICAgICAgIG9iai5yb3RhdGlvbi56XG4gICAgICApO1xuICAgICAgbW9kZWxOb2RlLm9iajNELnNjYWxlLnNldChvYmouc2NhbGUueCwgb2JqLnNjYWxlLnksIG9iai5zY2FsZS56KTtcbiAgICAgIGlmKGlzQXppbXV0aGFsQ3Jvd24pXG4gICAgICB7XG4gICAgICAgIC8qaWYobW9kZWxOb2RlLm9iajNELnNjYWxlLnggPj0gMS4wKXtcbiAgICAgICAgICBtb2RlbE5vZGUub2JqM0Quc2NhbGUuc2V0KG9iai5zY2FsZS54LzUwMDAsIG9iai5zY2FsZS55LzUwMDAsIG9iai5zY2FsZS56LzUwMDApO1xuICAgICAgICB9Ki9cbiAgICAgICAgdGhpcy5hemltdXRoYWxDcm93bj1tb2RlbE5vZGU7XG4gICAgICAgIHRoaXMuZGlzcGxheUF6aW11dGFsQ3Jvd24oKTtcbiAgICAgIH1cblxuICAgICAgLy8gQnkgZGVmYXV0LCBkdXJpbmcgY3JlYXRpb24sIG9iamVjdCBoYXMgdHJhbnNsYXRpb24gZ2l6bW9cbiAgICAgIC8vID0+IFVzZXIgaGFzIHRvIGNsaWNrIG9uIGxhdGVyYWwgcGFuZWwsIGFuZCBzYXZlIGl0cyBwb3NpdGlvbiBhZnRlciBwbGF5aW5nIHdpdGggaXQhXG4gICAgICBpZiAobW9kZSAmJiAhaXNOZXN0VGhlcm1vc3RhdCkge1xuICAgICAgICB0aGlzLmF0dGFjaEdpem1vQ29udHJvbFRvM0RPYmplY3QoXG4gICAgICAgICAgbW9kZWxOb2RlLFxuICAgICAgICAgIHNjZW5lT2JqZWN0LFxuICAgICAgICAgIG1vZGUsXG4gICAgICAgICAgdHJ1ZSxcbiAgICAgICAgICB0cnVlXG4gICAgICAgICkuY2F0Y2goKGUpID0+IGNvbnNvbGUubG9nKGUpKTtcbiAgICAgIH1cblxuICAgICAgaWYgKHRoaXMubGFzdE9iamVjdDNEICYmIHR5cGVvZiB0aGlzLmxhc3RPYmplY3QzRC5pZCA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgLy8gcHJvbXB0IFRocmVlSlMgVVVJRCB0byBtYXRjaCBvdXIgbGFzdCBnZW5lcmF0ZWQgb2JqZWN0IGlmIG5ldyAobm90IGZyb20gRGIpXG4gICAgICAgIG1vZGVsTm9kZS5vYmozRC51dWlkID0gdGhpcy5sYXN0T2JqZWN0M0QuaWQ7XG4gICAgICB9IGVsc2UgaWYgKG9iai5pZCkge1xuICAgICAgICBtb2RlbE5vZGUub2JqM0QudXVpZCA9IG9iai5pZDtcbiAgICAgIH1cbiAgICAgIHRoaXMubGFzdE9iamVjdDNEID0gbW9kZWxOb2RlLm9iajNEO1xuXG4gICAgICAvLyBTdG9yZSB0aGlzIGluIG1lbW9yeSBNYXAgZGljdGlvbm5hcnlcbiAgICAgIC8vY29uc29sZS5sb2coXCJBZGRpbmcgb2JqZWN0OiBcIik7XG4gICAgICAvL2NvbnNvbGUubG9nKG1vZGVsTm9kZSk7XG4gICAgICB0aGlzLmRpY3Rpb25uYXJ5T2JqZWN0czNELnNldChtb2RlbE5vZGUub2JqM0QudXVpZCwgbW9kZWxOb2RlKTtcbiAgICAgIHRoaXMuZGljdGlvbm5hcnlTY2VuZU9iamVjdHMzRC5zZXQobW9kZWxOb2RlLm9iajNELnV1aWQsIHNjZW5lT2JqZWN0KTtcblxuICAgICAgLyp0aGlzLnNkay5DYW1lcmEucG9zZS5zdWJzY3JpYmUoXG4gICAgICAgIGZ1bmN0aW9uIChwb3NlOiBhbnkpIHtcbiAgICAgICAgICAvL2NvbnNvbGUubG9nKFwiaW4gY2FsbGJhY2tcIilcbiAgICAgICAgICAvL2NvbnNvbGUubG9nKHRoaXMubGFzdENhbWVyYVBvc2l0aW9uKVxuICAgICAgICAgIC8vY29uc29sZS5sb2cocG9zZS5wb3NpdGlvbilcbiAgICAgICAgICBpZigocG9zZS5wb3NpdGlvbi54ID09IHRoaXMubGFzdENhbWVyYVBvc2l0aW9uLnggJiYgcG9zZS5wb3NpdGlvbi55ID09IHRoaXMubGFzdENhbWVyYVBvc2l0aW9uLnkgJiYgcG9zZS5wb3NpdGlvbi56ID09IHRoaXMubGFzdENhbWVyYVBvc2l0aW9uLnopIHx8IHRoaXMuaW5UcmFuc2l0aW9uTW9kZSB8fCB0aGlzLmluVHJhbnNpdGlvblN3ZWVwKXtcbiAgICAgICAgICAgIC8vY29uc29sZS5sb2coXCJyZXR1cm5pbmdcIilcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICB9XG4gICAgICAgICAgY29uc29sZS5sb2coXCJjYW1lcmEgcG9zOlwiLHBvc2UucG9zaXRpb24pO1xuICAgICAgICAgIHRoaXMubGFzdENhbWVyYVBvc2l0aW9uID0gey4uLnBvc2UucG9zaXRpb259O1xuICAgICAgICAgIGlmKHRoaXMubGFzdE9iamVjdDNEKXtcbiAgICAgICAgICAgIHRoaXMubGFzdE9iamVjdDNELnBvc2l0aW9uLnNldChwb3NlLnBvc2l0aW9uLngrLjUscG9zZS5wb3NpdGlvbi55Ky41LHBvc2UucG9zaXRpb24ueisuNSk7XG4gICAgICAgICAgfVxuICAgICAgICB9LmJpbmQodGhpcykpOyovXG5cbiAgICAgIGlmIChpc0FuaW1hdGVkU2VjdXJpdHlDYW1lcmEpIHtcblxuICAgICAgICBjb25zdCBhbmltYXRvciA9IG1vZGVsTm9kZS5hZGRDb21wb25lbnQoJ21wLnNlY3VyaXR5Q2FtZXJhJyxcbiAgICAgICAgICB7XG4gICAgICAgICAgICBcIm5lYXJQbGFuZVwiOiAwLjEsXG4gICAgICAgICAgICBcImZhclBsYW5lXCI6IDEwLFxuICAgICAgICAgICAgXCJob3Jpem9udGFsRk9WXCI6IDUyLFxuICAgICAgICAgICAgXCJhc3BlY3RcIjogMS43Nzc3Nzc3Nzc3Nzc3Nzc3LFxuICAgICAgICAgICAgXCJsb2NhbFBvc2l0aW9uXCI6IHtcbiAgICAgICAgICAgICAgXCJ4XCI6IDAuMyxcbiAgICAgICAgICAgICAgXCJ5XCI6IDAuMTgsXG4gICAgICAgICAgICAgIFwielwiOiAwXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgXCJsb2NhbFJvdGF0aW9uXCI6IHtcbiAgICAgICAgICAgICAgXCJ4XCI6IC0xNSxcbiAgICAgICAgICAgICAgXCJ5XCI6IC05MCxcbiAgICAgICAgICAgICAgXCJ6XCI6IDBcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBcImNvbG9yXCI6IDY1MjgwLFxuICAgICAgICAgICAgXCJwYW5QZXJpb2RcIjogNSxcbiAgICAgICAgICAgIFwicGFuQW5nbGVcIjogLTQ1XG4gICAgICAgICAgfSk7XG4gICAgICAgIGNvbnN0IG1vZGVsT3V0cHV0ID0gc2NlbmVPYmplY3QuYWRkUGF0aCh7XG4gICAgICAgICAgaWQ6ICdhbmltYXRlZC1tb2RlbCcsXG4gICAgICAgICAgdHlwZTogdGhpcy5zZGsuU2NlbmUuUGF0aFR5cGUuT1VUUFVULFxuICAgICAgICAgIG5vZGU6IG1vZGVsTm9kZSxcbiAgICAgICAgICBjb21wb25lbnQ6IGFuaW1hdG9yLFxuICAgICAgICAgIHByb3BlcnR5OiAnb2JqZWN0Um9vdCdcbiAgICAgICAgfSk7XG5cbiAgICAgICAgdGhpcy5zZWN1cml0eUNhbWVyYUFuaW1hdG9yID0gYW5pbWF0b3I7XG4gICAgICAgIGlmICghb2JqLnZpZXdGcnVzdHVtKSB7XG4gICAgICAgICAgc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICAgICAgICBhbmltYXRvci50b2dnbGVWaWV3RnJ1c3R1bSgpO1xuICAgICAgICAgIH0sIDEwMDApO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGlmIChpc05lc3RUaGVybW9zdGF0KSB7XG4gICAgICAgIC8vIFRPRE86IHVzZSBiaW5kUGF0aCBpbnN0ZWFkIHVzaW5nIE1QIHNkayBjbGFzc2VzIChzZWUgU2VjdXJpdHkgQ2FtZXJhIGV4YW1wbGUpXG4gICAgICAgIC8vIGZvciBUViB1c2VzIENhbnZhc0ltYWdlIGJlbG93IVxuICAgICAgICAvLyBjb25zdCBjaSA9IG5ldyBDYW52YXNJbWFnZSgpO1xuICAgICAgICAvLyBjaS5vbkluaXQoKTtcbiAgICAgICAgY29uc3QgY3YgPSBuZXcgQ2FudmFzUmVuZGVyZXIoKTtcbiAgICAgICAgY3Yub25Jbml0KCk7XG4gICAgICAgIGNvbnN0IHBsYW5lID0gbmV3IFBsYW5lUmVuZGVyZXIoKTtcbiAgICAgICAgcGxhbmUub3V0cHV0cyA9IHtcbiAgICAgICAgICBvYmplY3RSb290OiBuZXcgT2JqZWN0M0QoKSxcbiAgICAgICAgICBjb2xsaWRlcjogbmV3IE9iamVjdDNEKClcbiAgICAgICAgfTtcbiAgICAgICAgY29uc3QgaW5wdXRUZXh0dXJlID0gY3Yub3V0cHV0cy50ZXh0dXJlO1xuICAgICAgICBwbGFuZS5zZXRSb290U2NlbmUodGhpcy50aHJlZUpTU2NlbmUpO1xuICAgICAgICBwbGFuZS5vbkluaXQobW9kZWxOb2RlLCBpbnB1dFRleHR1cmUpO1xuICAgICAgICBjb25zdCBzYyA9IG5ldyBOZXN0VGhlcm1vc3RhdCgpO1xuICAgICAgICBzYy5zZXRDb21wb25lbnQoY29tcG9uZW50LCBwbGFuZSwgY3YpO1xuICAgICAgICBzYy5zZXRSb290U2NlbmUodGhpcy50aHJlZUpTU2NlbmUpO1xuICAgICAgICBzYy5vbkluaXQobW9kZWxOb2RlLCBwbGFuZSwgaW5wdXRUZXh0dXJlKTtcbiAgICAgICAgY3Yuc2V0Q2FudmFzTmVzdFRoZXJtb3N0YXRQYWludGVyKHNjKTtcbiAgICAgICAgc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICAgICAgc2MuaW5wdXRzLmxvYWRpbmdTdGF0ZSA9IFwiTG9hZGVkXCI7XG4gICAgICAgICAgc2Mub25JbnB1dHNVcGRhdGVkKCk7XG4gICAgICAgIH0sIDUwMDApO1xuICAgICAgfVxuXG4gICAgICBpZiAoaXNTbWFydGVycGxhblByb21vdGlvbmFsVmlkZW8pIHtcbiAgICAgICAgLy8gVE9ETzogdXNlIGJpbmRQYXRoIGluc3RlYWQgdXNpbmcgTVAgc2RrIGNsYXNzZXMgKHNlZSBTZWN1cml0eSBDYW1lcmEgZXhhbXBsZSlcbiAgICAgICAgY29uc3Qgc2MgPSBuZXcgVHZQbGF5ZXIoKTtcbiAgICAgICAgc2Muc2V0Q29tcG9uZW50KGNvbXBvbmVudCk7XG4gICAgICAgIHNjLm9uSW5pdChtb2RlbE5vZGUpO1xuICAgICAgICBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgICAgICBzYy5pbnB1dHMubG9hZGluZ1N0YXRlID0gXCJMb2FkZWRcIjtcbiAgICAgICAgICBzYy5vbklucHV0c1VwZGF0ZWQoKTtcbiAgICAgICAgfSwgNTAwMCk7XG4gICAgICB9XG5cbiAgICAgIHNjZW5lT2JqZWN0LnN0YXJ0KCk7XG4gICAgICByZXNvbHZlKHRoaXMubGFzdE9iamVjdDNEKTtcbiAgICB9KTtcbiAgfVxuXG4gIHRvZ2dsZU9iamVjdFZpc2liaWxpdHkob2JqZWN0SWQ6IGFueSl7XG4gICAgbGV0IG9iaiA9IHRoaXMuZGljdGlvbm5hcnlPYmplY3RzM0QuZ2V0KG9iamVjdElkKTtcbiAgICBvYmoub2JqM0QudmlzaWJsZSA9ICFvYmoub2JqM0QudmlzaWJsZTtcbiAgfVxuXG4gIGlzT2JqZWN0VmlzaWJsZShvYmplY3RJZDogYW55KTogYm9vbGVhbiB7XG4gICAgbGV0IG9iaiA9IHRoaXMuZGljdGlvbm5hcnlPYmplY3RzM0QuZ2V0KG9iamVjdElkKTtcbiAgICByZXR1cm4gb2JqLm9iajNELnZpc2libGU7XG4gIH1cblxuICBhc3luYyBwb2ludENhbWVyYVRvM0RPYmplY3Qob2JqZWN0SWQ6IGFueSl7XG4gICAgbGV0IG9iaiA9IHRoaXMuZGljdGlvbm5hcnlPYmplY3RzM0QuZ2V0KG9iamVjdElkKTtcblxuICAgIC8vV2UgY3JlYXRlIGEgdGVtcG9yYXJ5IFRhZ1xuICAgIGNvbnN0IHBvaU9iamVjdCA9IHtcbiAgICAgIGNvb3JkaW5hdGU6IEpTT04uc3RyaW5naWZ5KG9iai5vYmozRC5wb3NpdGlvbiksXG4gICAgICB0eXBlOiBQb2lUeXBlLk9CSkVDVDNELFxuICAgICAgZWxlbWVudElEOiBvYmplY3RJZCwgLy90b2RvOiBiZSBjYXJlZnVsIHdpdGggdGhpc1xuICAgIH0gYXMgUE9JO1xuICAgIGNvbnN0IG9iamVjdERiID0ge2lkOiBvYmplY3RJZH0gYXMgRGJPYmplY3RUeXBlO1xuXG4gICAgdHJ5e1xuICAgICAgYXdhaXQgdGhpcy5jcmVhdGVNYXR0ZXJ0YWdGcm9tUE9JKFBvaVR5cGUuT0JKRUNUM0QsIG9iamVjdERiLCBwb2lPYmplY3QpO1xuICAgIH1jYXRjaChlcnI6IGFueSl7fVxuXG4gICAgLy9Ob3QgcmVhbGx5IG5lY2Vzc2FyeSBhbnltb3JlIHNpbmNlIHRoZSB0YWcgd2lsbCBkaXNhcHBlYXIgcXVpY2tcbiAgICAvL3RoaXMuc2RrLlRhZy5lZGl0T3BhY2l0eShtYXR0ZXJ0YWdJRCwgMC4wKTsvL29wYWNpdHkpO1xuICAgIC8vdGhpcy5zZGsuVGFnLmFsbG93QWN0aW9uKG1hdHRlcnRhZ0lELCB7fSk7IC8vZGlzYWJsZXMgZXZlcnkgYWN0aW9uXG5cbiAgICBsZXQgcmVzdWx0ID0gdGhpcy5nZXRUYWdGcm9tRWxlbWVudElkKG9iamVjdElkKTtcblxuICAgIGF3YWl0IHRoaXMuZ29Ub1RhZyhyZXN1bHQudGFnKTtcbiAgICB0aGlzLmRlbGV0ZUxhc3RNYXR0ZXJ0YWcoKTtcbiAgfVxuXG4gIGdldFNjZW5lTm9kZUZyb21PYmplY3QzRElkKHV1aWQ6IHN0cmluZyk6IGFueSB7XG4gICAgcmV0dXJuIHRoaXMuZGljdGlvbm5hcnlTY2VuZU9iamVjdHMzRC5nZXQodXVpZCk7XG4gIH1cblxuICBhc3luYyBkaXNwbGF5QXppbXV0YWxDcm93bigpe1xuICAgIGlmKHRoaXMuYXppbXV0aGFsQ3Jvd24pe1xuICAgICAgdGhpcy5hemltdXRoYWxDcm93bi5vYmozRC5wb3NpdGlvbi5zZXQodGhpcy5wb3NlQ2FtZXJhLnBvc2l0aW9uLngsdGhpcy5wb3NlQ2FtZXJhLnBvc2l0aW9uLnksdGhpcy5wb3NlQ2FtZXJhLnBvc2l0aW9uLnopXG4gICAgfVxuICB9XG5cbiAgYXN5bmMgYXR0YWNoR2l6bW9Db250cm9sVG8zRE9iamVjdChcbiAgICBtb2RlbE5vZGU6IGFueSxcbiAgICBzY2VuZU9iamVjdDogYW55LFxuICAgIG1vZGU6ICd0cmFuc2xhdGUnIHwgJ3JvdGF0ZScgfCAnc2NhbGUnLFxuICAgIHZpc2libGU6IGJvb2xlYW4sXG4gICAgaXNOZXdPYmplY3Q6IGJvb2xlYW5cbiAgKTogUHJvbWlzZTxhbnk+IHtcbiAgICAvLyBDcmVhdGUgYSBzY2VuZSBub2RlIHdpdGggYSB0cmFuc2Zvcm0gY29udHJvbCBjb21wb25lbnQuXG4gICAgbGV0IG5vZGUgPSBudWxsO1xuICAgIG5vZGUgPSBzY2VuZU9iamVjdC5hZGROb2RlKCk7XG4gICAgaWYgKCFub2RlKSB7XG4gICAgICBjb25zdCBbc2NlbmVPYmplY3RdID0gYXdhaXQgdGhpcy5zZGsuU2NlbmUuY3JlYXRlT2JqZWN0cygxKTtcbiAgICAgIG5vZGUgPSBzY2VuZU9iamVjdC5hZGROb2RlKCk7XG4gICAgfVxuXG4gICAgY29uc3QgbXlDb250cm9sID0gbm9kZS5hZGRDb21wb25lbnQoJ21wLnRyYW5zZm9ybUNvbnRyb2xzJyk7XG4gICAgbm9kZS5zdGFydCgpO1xuICAgIC8vXG4gICAgLy8gLy8gTWFrZSB0aGUgdHJhbnNmb3JtIGNvbnRyb2wgdmlzaWJsZSBzbyB0aGF0IHRoZSB1c2VyIGNhbiBtYW5pcHVsYXRlIHRoZSBjb250cm9sIHNlbGVjdGlvbi5cbiAgICBteUNvbnRyb2wudHJhbnNmb3JtQ29udHJvbHMudmlzaWJsZSA9IHZpc2libGU7XG4gICAgLy9cbiAgICAvLyAvLyBBdHRhY2ggdGhlIG1vZGVsIHRvIHRoZSB0cmFuc2Zvcm0gY29udHJvbFxuICAgIG15Q29udHJvbC5pbnB1dHMuc2VsZWN0aW9uID0gbW9kZWxOb2RlO1xuICAgIC8vXG4gICAgLy8gLy8gc2V0ICd0cmFuc2xhdGUnIG1vZGUgdG8gcG9zaXRpb24gdGhlIHNlbGVjdGlvbi5cbiAgICBteUNvbnRyb2wuaW5wdXRzLm1vZGUgPSBtb2RlO1xuICAgIG1vZGVsTm9kZS5vYmozRC5jb250cm9scyA9IG15Q29udHJvbDsgLy8gc3RvcmUgZ2l6bW9DdHJsIGluc2lkZSBvYmplY3RcbiAgICBpZihpc05ld09iamVjdCl7IC8vaSBrZWVwIHRoZSBjdXJyZW50IHNvbHV0aW9uIGZvciBuZXcgb2JqZWN0c1xuICAgICAgaWYgKCF0aGlzLmxhc3RPYmplY3QzRCB8fCAhdGhpcy5sYXN0T2JqZWN0M0QuY29udHJvbHMpIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBtb2RlbE5vZGUub2JqM0QudXVpZCA9IHRoaXMubGFzdE9iamVjdDNELnV1aWQgfHwgdGhpcy5sYXN0T2JqZWN0M0QuaWQ7XG4gICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICBjb25zb2xlLmxvZyhgaWQgb2JqIGluIFNjZW5lIHdhcyBub3QgYXNzaWduZWQgdG8gaWQgZnJvbSBEQiBzaW5jZWApO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMubGFzdE9iamVjdDNEID0gbW9kZWxOb2RlLm9iajNEO1xuICAgICAgfVxuICAgIH1lbHNley8vb2JqZWN0cyBhbHJlYWR5IGluIHBsYWNlIGhhdmUgdG8gYmVjb21lIHRoZSBcImxhc3RPYmplY3RcIiAoaSB0aGluaz8pXG4gICAgICBjb25zb2xlLmxvZyhcImluIG15IHNvbHV0aW9uICFcIik7XG4gICAgICBjb25zb2xlLmxvZyhtb2RlbE5vZGUpO1xuICAgICAgY29uc29sZS5sb2cobW9kZWxOb2RlLm9iajNELnV1aWQpO1xuICAgICAgdGhpcy5sYXN0T2JqZWN0M0QgPSBtb2RlbE5vZGUub2JqM0Q7XG4gICAgfVxuXG4gICAgcmV0dXJuIG1vZGVsTm9kZTtcbiAgfVxuXG4gIHJlbW92ZUdpem1vRnJvbUxhc3RPYmplY3QoKTogdm9pZCB7XG4gICAgdGhpcy5sYXN0T2JqZWN0M0QuY29udHJvbHMudHJhbnNmb3JtQ29udHJvbHMudmlzaWJsZSA9IGZhbHNlO1xuICAgIHRoaXMubGFzdE9iamVjdDNELmNvbnRyb2xzLnRyYW5zZm9ybUNvbnRyb2xzLmRpc3Bvc2UoKTtcbiAgICB0aGlzLmxhc3RPYmplY3QzRC5jb250cm9scyA9IG51bGw7XG4gIH1cblxuICB0b2dnbGVWaWV3RnJ1c3R1bSgpOiB2b2lkIHtcbiAgICB0aGlzLnNlY3VyaXR5Q2FtZXJhQW5pbWF0b3IudG9nZ2xlVmlld0ZydXN0dW0oKTtcbiAgfVxuXG4gLypwdWJsaWMgc2V0M0RPYmplY3RNb2RlKG1vZGVsTm9kZTogYW55LCBtb2RlPzogc3RyaW5nKSB7XG4gICBpZiAobW9kZSkge1xuICAgICB0aGlzLm9iamVjdENvbnRyb2wuaW5wdXRzLnNlbGVjdGlvbiA9IG1vZGVsTm9kZTtcbiAgICAgdGhpcy5vYmplY3RDb250cm9sLmlucHV0cy52aXNpYmxlID0gdHJ1ZTtcbiAgICAgdGhpcy5vYmplY3RDb250cm9sLmlucHV0cy5tb2RlID0gbW9kZTtcblxuICAgICBzZXRJbnRlcnZhbCgoKSA9PiB7XG4gICAgICAgY29uc29sZS5sb2cobW9kZWxOb2RlKTtcbiAgICAgfSwgNTAwMCk7XG5cbiAgIH0gZWxzZSB7XG4gICAgIHRoaXMub2JqZWN0Q29udHJvbC5pbnB1dHMudmlzaWJsZSA9IHRydWU7XG4gICB9XG4gfSovXG59XG4iXX0=
|