@smarterplan/ngx-smarterplan-core 1.2.39 → 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.
Files changed (170) hide show
  1. package/README.md +24 -24
  2. package/esm2020/lib/components/csv-export/csv-export.component.mjs +59 -59
  3. package/esm2020/lib/components/loader/loader.component.mjs +23 -23
  4. package/esm2020/lib/components/menu-bar/avatar/avatar.component.mjs +80 -80
  5. package/esm2020/lib/components/menu-bar/menu-bar.component.mjs +99 -99
  6. package/esm2020/lib/components/menu-bar/navigation-bar/navigation-bar.component.mjs +384 -384
  7. package/esm2020/lib/components/menu-bar/range-date-picker/range-date-picker.component.mjs +147 -147
  8. package/esm2020/lib/components/modal-switch-visit/modal-switch-visit.component.mjs +40 -40
  9. package/esm2020/lib/components/search-bar/search-bar.component.mjs +63 -63
  10. package/esm2020/lib/components/support-modal/support-modal.component.mjs +66 -66
  11. package/esm2020/lib/config.mjs +4 -4
  12. package/esm2020/lib/helpers.service.mjs +470 -470
  13. package/esm2020/lib/matterport-extensions/hsl-loader/HlsLoader.mjs +69 -69
  14. package/esm2020/lib/matterport-extensions/nest-thermostat/CanvasImage.mjs +51 -51
  15. package/esm2020/lib/matterport-extensions/nest-thermostat/CanvasRenderer.mjs +61 -61
  16. package/esm2020/lib/matterport-extensions/nest-thermostat/NestThermostat.mjs +158 -158
  17. package/esm2020/lib/matterport-extensions/nest-thermostat/PlaneRenderer.mjs +85 -85
  18. package/esm2020/lib/matterport-extensions/scene-component/SceneComponent.mjs +128 -128
  19. package/esm2020/lib/matterport-extensions/security-camera/SecurityCamera.mjs +249 -249
  20. package/esm2020/lib/matterport-extensions/tv-player/TvPlayer.mjs +98 -98
  21. package/esm2020/lib/matterport-extensions/video-renderer/VideoRenderer.mjs +64 -64
  22. package/esm2020/lib/matterport-extensions/view-frustum-mesh/ViewFrustumMesh.mjs +221 -221
  23. package/esm2020/lib/mattertagData.mjs +165 -165
  24. package/esm2020/lib/ngx-smarterplan-core.module.mjs +122 -122
  25. package/esm2020/lib/ngx-smarterplan-core.service.mjs +14 -14
  26. package/esm2020/lib/pipes/duration-to-string.pipe.mjs +66 -66
  27. package/esm2020/lib/pipes/format-date-number-to-digits.pipe.mjs +30 -30
  28. package/esm2020/lib/pipes/hashtag-from-id.pipe.mjs +26 -26
  29. package/esm2020/lib/pipes/safe-url.pipe.mjs +20 -20
  30. package/esm2020/lib/pipes/time-date-to-local-string.pipe.mjs +104 -104
  31. package/esm2020/lib/pipes/username-from-id.pipe.mjs +29 -29
  32. package/esm2020/lib/services/amplify-cache.service.mjs +72 -72
  33. package/esm2020/lib/services/base-tab.service.mjs +24 -24
  34. package/esm2020/lib/services/baseVisibility.service.mjs +18 -18
  35. package/esm2020/lib/services/content.service.mjs +135 -135
  36. package/esm2020/lib/services/filter.service.mjs +599 -599
  37. package/esm2020/lib/services/intervention.service.mjs +236 -236
  38. package/esm2020/lib/services/locale.service.mjs +45 -45
  39. package/esm2020/lib/services/matterport-import.service.mjs +340 -340
  40. package/esm2020/lib/services/matterport.service.mjs +1587 -1587
  41. package/esm2020/lib/services/models/affectation.service.mjs +60 -60
  42. package/esm2020/lib/services/models/base-object.service.mjs +70 -70
  43. package/esm2020/lib/services/models/capture.service.mjs +34 -34
  44. package/esm2020/lib/services/models/comment.service.mjs +98 -98
  45. package/esm2020/lib/services/models/domain.service.mjs +78 -78
  46. package/esm2020/lib/services/models/equipment.service.mjs +683 -683
  47. package/esm2020/lib/services/models/event.service.mjs +128 -128
  48. package/esm2020/lib/services/models/feature.service.mjs +380 -364
  49. package/esm2020/lib/services/models/hashtag.service.mjs +38 -38
  50. package/esm2020/lib/services/models/layer.service.mjs +33 -33
  51. package/esm2020/lib/services/models/measurement.service.mjs +199 -199
  52. package/esm2020/lib/services/models/mission.service.mjs +206 -206
  53. package/esm2020/lib/services/models/navigation.service.mjs +92 -92
  54. package/esm2020/lib/services/models/node.service.mjs +31 -31
  55. package/esm2020/lib/services/models/object3D.service.mjs +364 -364
  56. package/esm2020/lib/services/models/operation.service.mjs +59 -59
  57. package/esm2020/lib/services/models/organisation.service.mjs +73 -73
  58. package/esm2020/lib/services/models/plan.service.mjs +799 -799
  59. package/esm2020/lib/services/models/poi.service.mjs +103 -103
  60. package/esm2020/lib/services/models/profile.service.mjs +58 -58
  61. package/esm2020/lib/services/models/property.service.mjs +44 -44
  62. package/esm2020/lib/services/models/space.service.mjs +204 -204
  63. package/esm2020/lib/services/models/template.service.mjs +41 -41
  64. package/esm2020/lib/services/models/ticket.service.mjs +526 -526
  65. package/esm2020/lib/services/models/visit.service.mjs +130 -130
  66. package/esm2020/lib/services/models/zone.service.mjs +225 -225
  67. package/esm2020/lib/services/navigator.service.mjs +212 -212
  68. package/esm2020/lib/services/s3.service.mjs +137 -137
  69. package/esm2020/lib/services/search.service.mjs +124 -124
  70. package/esm2020/lib/services/support.service.mjs +42 -42
  71. package/esm2020/lib/services/tag.service.mjs +111 -111
  72. package/esm2020/lib/services/user.service.mjs +501 -501
  73. package/esm2020/lib/services/validators.service.mjs +50 -50
  74. package/esm2020/lib/services/viewer.service.mjs +389 -389
  75. package/esm2020/lib/services/zone-drawer.service.mjs +76 -76
  76. package/esm2020/lib/services/zoneChange.service.mjs +30 -30
  77. package/esm2020/lib/types.service.mjs +311 -310
  78. package/esm2020/lib/validators/email.directive.mjs +7 -7
  79. package/esm2020/lib/validators/no-empty.directive.mjs +12 -12
  80. package/esm2020/lib/validators/number.directive.mjs +12 -12
  81. package/esm2020/lib/validators/text.directive.mjs +12 -12
  82. package/esm2020/public-api.mjs +72 -72
  83. package/esm2020/smarterplan-ngx-smarterplan-core.mjs +4 -4
  84. package/fesm2015/smarterplan-ngx-smarterplan-core.mjs +13009 -12992
  85. package/fesm2015/smarterplan-ngx-smarterplan-core.mjs.map +1 -1
  86. package/fesm2020/smarterplan-ngx-smarterplan-core.mjs +12258 -12241
  87. package/fesm2020/smarterplan-ngx-smarterplan-core.mjs.map +1 -1
  88. package/lib/components/csv-export/csv-export.component.d.ts +18 -18
  89. package/lib/components/loader/loader.component.d.ts +10 -10
  90. package/lib/components/menu-bar/avatar/avatar.component.d.ts +21 -21
  91. package/lib/components/menu-bar/menu-bar.component.d.ts +38 -38
  92. package/lib/components/menu-bar/navigation-bar/navigation-bar.component.d.ts +73 -73
  93. package/lib/components/menu-bar/range-date-picker/range-date-picker.component.d.ts +35 -35
  94. package/lib/components/modal-switch-visit/modal-switch-visit.component.d.ts +22 -22
  95. package/lib/components/search-bar/search-bar.component.d.ts +16 -16
  96. package/lib/components/support-modal/support-modal.component.d.ts +26 -26
  97. package/lib/config.d.ts +22 -22
  98. package/lib/helpers.service.d.ts +79 -79
  99. package/lib/matterport-extensions/hsl-loader/HlsLoader.d.ts +26 -26
  100. package/lib/matterport-extensions/nest-thermostat/CanvasImage.d.ts +31 -31
  101. package/lib/matterport-extensions/nest-thermostat/CanvasRenderer.d.ts +37 -37
  102. package/lib/matterport-extensions/nest-thermostat/NestThermostat.d.ts +42 -42
  103. package/lib/matterport-extensions/nest-thermostat/PlaneRenderer.d.ts +46 -46
  104. package/lib/matterport-extensions/scene-component/SceneComponent.d.ts +388 -388
  105. package/lib/matterport-extensions/security-camera/SecurityCamera.d.ts +47 -47
  106. package/lib/matterport-extensions/tv-player/TvPlayer.d.ts +26 -26
  107. package/lib/matterport-extensions/video-renderer/VideoRenderer.d.ts +26 -26
  108. package/lib/matterport-extensions/view-frustum-mesh/ViewFrustumMesh.d.ts +43 -43
  109. package/lib/mattertagData.d.ts +70 -70
  110. package/lib/ngx-smarterplan-core.module.d.ts +29 -29
  111. package/lib/ngx-smarterplan-core.service.d.ts +6 -6
  112. package/lib/pipes/duration-to-string.pipe.d.ts +12 -12
  113. package/lib/pipes/format-date-number-to-digits.pipe.d.ts +10 -10
  114. package/lib/pipes/hashtag-from-id.pipe.d.ts +10 -10
  115. package/lib/pipes/safe-url.pipe.d.ts +10 -10
  116. package/lib/pipes/time-date-to-local-string.pipe.d.ts +16 -16
  117. package/lib/pipes/username-from-id.pipe.d.ts +11 -11
  118. package/lib/services/amplify-cache.service.d.ts +37 -37
  119. package/lib/services/base-tab.service.d.ts +10 -10
  120. package/lib/services/baseVisibility.service.d.ts +9 -9
  121. package/lib/services/content.service.d.ts +28 -28
  122. package/lib/services/filter.service.d.ts +60 -60
  123. package/lib/services/intervention.service.d.ts +25 -25
  124. package/lib/services/locale.service.d.ts +23 -23
  125. package/lib/services/matterport-import.service.d.ts +53 -53
  126. package/lib/services/matterport.service.d.ts +336 -336
  127. package/lib/services/models/affectation.service.d.ts +14 -14
  128. package/lib/services/models/base-object.service.d.ts +20 -20
  129. package/lib/services/models/capture.service.d.ts +13 -13
  130. package/lib/services/models/comment.service.d.ts +26 -26
  131. package/lib/services/models/domain.service.d.ts +19 -19
  132. package/lib/services/models/equipment.service.d.ts +93 -93
  133. package/lib/services/models/event.service.d.ts +43 -43
  134. package/lib/services/models/feature.service.d.ts +75 -74
  135. package/lib/services/models/hashtag.service.d.ts +13 -13
  136. package/lib/services/models/layer.service.d.ts +11 -11
  137. package/lib/services/models/measurement.service.d.ts +51 -51
  138. package/lib/services/models/mission.service.d.ts +39 -39
  139. package/lib/services/models/navigation.service.d.ts +29 -29
  140. package/lib/services/models/node.service.d.ts +12 -12
  141. package/lib/services/models/object3D.service.d.ts +57 -57
  142. package/lib/services/models/operation.service.d.ts +15 -15
  143. package/lib/services/models/organisation.service.d.ts +19 -19
  144. package/lib/services/models/plan.service.d.ts +133 -133
  145. package/lib/services/models/poi.service.d.ts +25 -25
  146. package/lib/services/models/profile.service.d.ts +16 -16
  147. package/lib/services/models/property.service.d.ts +13 -13
  148. package/lib/services/models/space.service.d.ts +46 -46
  149. package/lib/services/models/template.service.d.ts +15 -15
  150. package/lib/services/models/ticket.service.d.ts +93 -93
  151. package/lib/services/models/visit.service.d.ts +24 -24
  152. package/lib/services/models/zone.service.d.ts +50 -50
  153. package/lib/services/navigator.service.d.ts +61 -61
  154. package/lib/services/s3.service.d.ts +14 -14
  155. package/lib/services/search.service.d.ts +20 -20
  156. package/lib/services/support.service.d.ts +17 -17
  157. package/lib/services/tag.service.d.ts +29 -29
  158. package/lib/services/user.service.d.ts +118 -118
  159. package/lib/services/validators.service.d.ts +18 -18
  160. package/lib/services/viewer.service.d.ts +110 -110
  161. package/lib/services/zone-drawer.service.d.ts +7 -7
  162. package/lib/services/zoneChange.service.d.ts +17 -17
  163. package/lib/types.service.d.ts +842 -840
  164. package/lib/validators/email.directive.d.ts +2 -2
  165. package/lib/validators/no-empty.directive.d.ts +2 -2
  166. package/lib/validators/number.directive.d.ts +2 -2
  167. package/lib/validators/text.directive.d.ts +2 -2
  168. package/package.json +1 -1
  169. package/public-api.d.ts +64 -64
  170. package/smarterplan-ngx-smarterplan-core.d.ts +5 -5
@@ -1,1587 +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; //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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWF0dGVycG9ydC5zZXJ2aWNlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvbmd4LXNtYXJ0ZXJwbGFuLWNvcmUvc3JjL2xpYi9zZXJ2aWNlcy9tYXR0ZXJwb3J0LnNlcnZpY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFDLE1BQU0sRUFBRSxVQUFVLEVBQVMsTUFBTSxlQUFlLENBQUM7QUFFekQsT0FBTyxFQUFDLE9BQU8sRUFBQyxNQUFNLE1BQU0sQ0FBQztBQUM3QiwyQ0FBMkM7QUFDM0MsT0FBTyxFQUNMLDJCQUEyQixFQUMzQixlQUFlLEVBQ2YsSUFBSSxHQUNMLE1BQU0sb0JBQW9CLENBQUM7QUFDNUIsT0FBTyxFQUFDLGFBQWEsRUFBQyxNQUFNLGtCQUFrQixDQUFDO0FBQy9DLE9BQU8sRUFFTCxXQUFXLEVBRVgsbUJBQW1CLEVBRW5CLE9BQU8sRUFDUCxRQUFRLEVBQ1IsU0FBUyxFQUNULGtCQUFrQixHQUNuQixNQUFNLGtCQUFrQixDQUFDO0FBQzFCLE9BQU8sRUFBQyxRQUFRLEVBQUMsTUFBTSxPQUFPLENBQUM7QUFJL0IsT0FBTyxFQUFDLFVBQVUsRUFBQyxNQUFNLGtCQUFrQixDQUFDO0FBRzVDLE9BQU8sRUFBQyxjQUFjLEVBQUMsTUFBTSx5REFBeUQsQ0FBQztBQUN2RixPQUFPLEVBQUMsYUFBYSxFQUFDLE1BQU0sd0RBQXdELENBQUM7QUFDckYsT0FBTyxFQUFDLGNBQWMsRUFBQyxNQUFNLHlEQUF5RCxDQUFDO0FBR3ZGLE9BQU8sRUFBQyxRQUFRLEVBQUMsTUFBTSw2Q0FBNkMsQ0FBQzs7Ozs7QUF3QnJFLE1BQU0sT0FBTyxpQkFBaUI7SUFvSjVCLFlBQ29CLE1BQWMsRUFDeEIsTUFBYyxFQUNkLFdBQTJCLEVBQzNCLGlCQUF3QyxFQUN4QyxNQUFjO1FBSGQsV0FBTSxHQUFOLE1BQU0sQ0FBUTtRQUNkLGdCQUFXLEdBQVgsV0FBVyxDQUFnQjtRQUMzQixz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QUN2QixJQUFJLENBQUMsWUFBWSxDQUFDLFFBQVEsQ0FBQyxpQkFBaUIsQ0FBQyxPQUFPLEdBQUcsS0FBSyxDQUFDO1FBQzdELElBQUksQ0FBQyxZQUFZLENBQUMsUUFBUSxDQUFDLGlCQUFpQixDQUFDLE9BQU8sRUFBRSxDQUFDO1FBQ3ZELElBQUksQ0FBQyxZQUFZLENBQUMsUUFBUSxHQUFHLElBQUksQ0FBQztJQUNwQyxDQUFDO0lBRUQsaUJBQWlCO1FBQ2YsSUFBSSxDQUFDLHNCQUFzQixDQUFDLGlCQUFpQixFQUFFLENBQUM7SUFDbEQsQ0FBQzs7OEdBbDlEVSxpQkFBaUIsa0JBcUpsQixRQUFRO2tIQXJKUCxpQkFBaUIsY0FGaEIsTUFBTTsyRkFFUCxpQkFBaUI7a0JBSDdCLFVBQVU7bUJBQUM7b0JBQ1YsVUFBVSxFQUFFLE1BQU07aUJBQ25COzswQkFzSkksTUFBTTsyQkFBQyxRQUFRIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtJbmplY3QsIEluamVjdGFibGUsIE5nWm9uZX0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XHJcbmltcG9ydCB7QWN0aXZhdGVkUm91dGUsIFJvdXRlcn0gZnJvbSAnQGFuZ3VsYXIvcm91dGVyJztcclxuaW1wb3J0IHtTdWJqZWN0fSBmcm9tICdyeGpzJztcclxuLy9pbXBvcnQgKiBhcyBzZXJpYWxpanNlIGZyb20gXCJzZXJpYWxpanNlXCI7XHJcbmltcG9ydCB7XHJcbiAgZ2V0RGlzdGFuY2VCZXR3ZWVuVHdvUG9pbnRzLFxyXG4gIHBvaVR5cGVUb1N0cmluZyxcclxuICB3YWl0LFxyXG59IGZyb20gJy4uL2hlbHBlcnMuc2VydmljZSc7XHJcbmltcG9ydCB7TWF0dGVydGFnRGF0YX0gZnJvbSAnLi4vbWF0dGVydGFnRGF0YSc7XHJcbmltcG9ydCB7XHJcbiAgRGJPYmplY3RUeXBlLFxyXG4gIEZlYXR1cmVUeXBlLFxyXG4gIElPYmplY3QzRCxcclxuICBNYXR0ZXJ0YWdBY3Rpb25Nb2RlLFxyXG4gIFBPSSxcclxuICBQb2lUeXBlLFxyXG4gIFNwTW9kdWxlLFxyXG4gIFRhZ0FjdGlvbixcclxuICBWaWV3ZXJJbnRlcmFjdGlvbnMsXHJcbn0gZnJvbSAnLi4vdHlwZXMuc2VydmljZSc7XHJcbmltcG9ydCB7T2JqZWN0M0R9IGZyb20gJ3RocmVlJztcclxuaW1wb3J0IHtCYXNlVGFnU2VydmljZX0gZnJvbSAnLi90YWcuc2VydmljZSc7XHJcbmltcG9ydCB7QmFzZVZpc2liaWxpdHlTZXJ2aWNlfSBmcm9tICcuL2Jhc2VWaXNpYmlsaXR5LnNlcnZpY2UnO1xyXG5pbXBvcnQge0NvbmZpZ30gZnJvbSAnLi4vY29uZmlnJztcclxuaW1wb3J0IHtDYW1lcmFNb2RlfSBmcm9tICcuLi90eXBlcy5zZXJ2aWNlJztcclxuaW1wb3J0IHtJU2NlbmVOb2RlLCBDb21wb25lbnRPdXRwdXR9IGZyb20gXCIuLi9tYXR0ZXJwb3J0LWV4dGVuc2lvbnMvc2NlbmUtY29tcG9uZW50L1NjZW5lQ29tcG9uZW50XCI7XHJcbmltcG9ydCB7U2VjdXJpdHlDYW1lcmF9IGZyb20gJy4uL21hdHRlcnBvcnQtZXh0ZW5zaW9ucy9zZWN1cml0eS1jYW1lcmEvU2VjdXJpdHlDYW1lcmEnO1xyXG5pbXBvcnQge05lc3RUaGVybW9zdGF0fSBmcm9tICcuLi9tYXR0ZXJwb3J0LWV4dGVuc2lvbnMvbmVzdC10aGVybW9zdGF0L05lc3RUaGVybW9zdGF0JztcclxuaW1wb3J0IHtQbGFuZVJlbmRlcmVyfSBmcm9tICcuLi9tYXR0ZXJwb3J0LWV4dGVuc2lvbnMvbmVzdC10aGVybW9zdGF0L1BsYW5lUmVuZGVyZXInO1xyXG5pbXBvcnQge0NhbnZhc1JlbmRlcmVyfSBmcm9tIFwiLi4vbWF0dGVycG9ydC1leHRlbnNpb25zL25lc3QtdGhlcm1vc3RhdC9DYW52YXNSZW5kZXJlclwiO1xyXG5pbXBvcnQge1ZpZGVvUmVuZGVyZXJ9IGZyb20gXCIuLi9tYXR0ZXJwb3J0LWV4dGVuc2lvbnMvdmlkZW8tcmVuZGVyZXIvVmlkZW9SZW5kZXJlclwiO1xyXG5pbXBvcnQge0hsc0xvYWRlcn0gZnJvbSBcIi4uL21hdHRlcnBvcnQtZXh0ZW5zaW9ucy9oc2wtbG9hZGVyL0hsc0xvYWRlclwiO1xyXG5pbXBvcnQge1R2UGxheWVyfSBmcm9tIFwiLi4vbWF0dGVycG9ydC1leHRlbnNpb25zL3R2LXBsYXllci9UdlBsYXllclwiO1xyXG5cclxuLy8gaW1wb3J0IHtDYW52YXNJbWFnZX0gZnJvbSBcIi4uL21hdHRlcnBvcnQtZXh0ZW5zaW9ucy9uZXN0LXRoZXJtb3N0YXQvQ2FudmFzSW1hZ2VcIjtcclxuXHJcbi8qKlxyXG4gKiBDdXN0b20gVGhyZWVqcyBPYmplY3QgM0QgaW50ZXJmYWNlXHJcbiAqL1xyXG5pbnRlcmZhY2UgVGhyZWVKU09iamVjdDNEIHtcclxuICBpZDogc3RyaW5nO1xyXG4gIHV1aWQ/OiBzdHJpbmc7XHJcbiAgcG9zaXRpb24/OiB7IHg6IG51bWJlciwgeTogbnVtYmVyLCB6OiBudW1iZXIgfVxyXG4gIHJvdGF0aW9uPzogeyB4OiBudW1iZXIsIHk6IG51bWJlciwgejogbnVtYmVyIH1cclxuICBzY2FsZT86IHsgeDogbnVtYmVyLCB5OiBudW1iZXIsIHo6IG51bWJlciB9XHJcbn1cclxuXHJcbmRlY2xhcmUgZ2xvYmFsIHtcclxuICBpbnRlcmZhY2UgV2luZG93IHtcclxuICAgIE1QX1NESzogeyBjb25uZWN0OiBGdW5jdGlvbiB9O1xyXG4gIH1cclxufVxyXG5cclxuQEluamVjdGFibGUoe1xyXG4gIHByb3ZpZGVkSW46ICdyb290JyxcclxufSlcclxuZXhwb3J0IGNsYXNzIE1hdHRlcnBvcnRTZXJ2aWNlIHtcclxuXHJcbiAgcHJpdmF0ZSBzbG90czogYW55W10gPSBbXTsvL1Nsb3ROb2RlW10gPSBbXTtcclxuXHJcbiAgcHJpdmF0ZSBub2RlczogSVNjZW5lTm9kZVtdID0gW107XHJcblxyXG4gIHB1YmxpYyBzZGs6IGFueTtcclxuXHJcbiAgcHJpdmF0ZSBjb250YWluZXI6IGFueTtcclxuXHJcbiAgLy8gUG9zaXRpb24gY2FtZXJhXHJcbiAgcHJpdmF0ZSBwb3NlTWF0dGVycG9ydDogYW55O1xyXG5cclxuICBwdWJsaWMgcG9zZUNhbWVyYTogeyByb3RhdGlvbjogYW55OyBwb3NpdGlvbjogYW55OyBzd2VlcDogYW55IH07XHJcbiAgcHVibGljIGxhc3RDYW1lcmFQb3NpdGlvbjogYW55ID0ge3g6MC4wLHk6MC4wLHo6MC4wfTtcclxuXHJcbiAgcHJpdmF0ZSBhemltdXRoYWxDcm93bjphbnk7XHJcbiAgLy8gUG9pbnRlciB0cmlja1xyXG4gIHByaXZhdGUgcG9pbnRlckJ1dHRvbjogYW55O1xyXG5cclxuICAvLyBEaXNwbGF5IGFuZCBnZXQgY3VycmVudCBwb3NpdGlvbiBvZiBjdXJzb3IgKGZvciBBZG1pbnMgb25seSlcclxuICBwcml2YXRlIGdldEN1cnNvclBvc2l0aW9uQnV0dG9uOiBhbnk7XHJcbiAgcHJpdmF0ZSBjdXJzb3JQb3NpdGlvbkJ1dHRvbkRpc3BsYXllZCA9IGZhbHNlO1xyXG4gIHByaXZhdGUgaW50ZXJ2YWxDdXJzb3JQb2ludGVyUG9zaXRpb246IGFueTtcclxuICBwcml2YXRlIHRleHREaXNwbGF5Q3Vyc29yUG9zaXRpb25QYW5lbDogYW55O1xyXG5cclxuICBwcml2YXRlIG9sZFBvc2VNYXR0ZXJwb3J0UG9zaXRpb246IGFueTtcclxuICAvLyBNZWFzdXJlIG1vZGVcclxuICBwcml2YXRlIGlzTWVhc3VyZU1vZGVPbiA9IGZhbHNlO1xyXG5cclxuICBwcml2YXRlIGludGVyYWN0aW9uTW9kZTogbnVtYmVyID0gVmlld2VySW50ZXJhY3Rpb25zLkRFRkFVTFQ7XHJcblxyXG4gIC8vIExpc3Qgb2YgY3JlYXRlZCBNYXR0ZXJ0YWcgSURzIGluIHRoZSBjdXJyZW50IHZpZXdlciBzZXNzaW9uXHJcbiAgcHJpdmF0ZSBtYXR0ZXJ0YWdJRHM6IEFycmF5PHN0cmluZz4gPSBbXTtcclxuXHJcbiAgLy8gRGljdGlvbm5hcnkgb2YgTWF0dGVydGFnSUQgYW5kIGl0cyBkYXRhIChtYXR0ZXJ0YWdEYXRhKVxyXG4gIHByaXZhdGUgZGljdGlvbm5hcnlUYWdzOiBNYXA8c3RyaW5nLCBNYXR0ZXJ0YWdEYXRhPiA9IG5ldyBNYXAoKTtcclxuXHJcbiAgcHJpdmF0ZSBkaWN0aW9ubmFyeU9iamVjdHMzRDogTWFwPHN0cmluZywgYW55PiA9IG5ldyBNYXAoKTtcclxuXHJcbiAgcHJpdmF0ZSBkaWN0aW9ubmFyeVNjZW5lT2JqZWN0czNEOiBNYXA8c3RyaW5nLCBhbnk+ID0gbmV3IE1hcCgpO1xyXG5cclxuICBwdWJsaWMgdGhyZWVKU1NjZW5lOiBhbnk7IC8vIGdsb2JhbCByb290IHNjZW5lIChub3QgdXNlZCBub3chKVxyXG5cclxuICBwcml2YXRlIGxhc3RNZWFzdXJlID0gW107XHJcblxyXG4gIHByaXZhdGUgZGlzdGFuY2VzTGFzdE1lYXN1cmU6IG51bWJlcltdID0gW107XHJcblxyXG4gIHByaXZhdGUgcmVzb2x1dGlvbiA9IHtcclxuICAgIHdpZHRoOiA1MDAsXHJcbiAgICBoZWlnaHQ6IDYwMCxcclxuICB9O1xyXG5cclxuICBwcml2YXRlIHZpc2liaWxpdHkgPSB7XHJcbiAgICBtYXR0ZXJ0YWdzOiBmYWxzZSxcclxuICAgIHN3ZWVwczogdHJ1ZSxcclxuICB9O1xyXG5cclxuICBwdWJsaWMgdGFnc0F0dGFjaG1lbnRzOiBPYmplY3QgPSB7fTtcclxuXHJcbiAgcHJpdmF0ZSBsYXN0U2NyZWVuc2hvdFVyaTogYW55O1xyXG5cclxuICBwdWJsaWMgc3dlZXBzOiBBcnJheTxzdHJpbmc+IHwgbnVsbDtcclxuXHJcbiAgcHVibGljIGN1cnJlbnRTd2VlcDogU3ViamVjdDxzdHJpbmc+ID0gbmV3IFN1YmplY3QoKTtcclxuXHJcbiAgLy9jYW1lcmEgcG9zaXRpb24gd2l0aCByb3RhdGlvblxyXG4gIHB1YmxpYyBjdXJyZW50Q2FtZXJhUG9zZTogU3ViamVjdDxhbnk+ID0gbmV3IFN1YmplY3QoKTtcclxuXHJcbiAgcHJpdmF0ZSBmbG9vcnM/OiBBcnJheTx7IGlkOiBzdHJpbmc7IG5hbWU6IHN0cmluZzsgc2VxdWVuY2U6IG51bWJlciB9PiB8IG51bGw7XHJcblxyXG4gIHByaXZhdGUgX2N1cnJlbnRTcGFjZUlEOiBzdHJpbmc7XHJcblxyXG4gIHByaXZhdGUgbGFzdE9iamVjdDNEOiBhbnk7IC8vIFRocmVlIEpTIG9iamVjdFxyXG5cclxuICBwcml2YXRlIGN1cnJlbnRGbG9vcjtcclxuXHJcbiAgcHVibGljIGdldCBjdXJyZW50U3BhY2VJRCgpOiBzdHJpbmcge1xyXG4gICAgcmV0dXJuIHRoaXMuX2N1cnJlbnRTcGFjZUlEO1xyXG4gIH1cclxuXHJcbiAgcHVibGljIHNldCBjdXJyZW50U3BhY2VJRCh2YWx1ZTogc3RyaW5nKSB7XHJcbiAgICB0aGlzLl9jdXJyZW50U3BhY2VJRCA9IHZhbHVlO1xyXG4gIH1cclxuXHJcbiAgdGltZXJQb2ludGVyOiBhbnk7XHJcblxyXG4gIGZvcmJpZGRlblN3ZWVwczogc3RyaW5nW10gPSBbXTtcclxuXHJcbiAgcHVibGljIHRhZ0FjdGlvbjogU3ViamVjdDx7IGFjdGlvbjogc3RyaW5nOyBkYXRhOiBzdHJpbmcgfT4gPSBuZXcgU3ViamVjdCgpO1xyXG5cclxuICBwdWJsaWMgbWF0dGVydGFnVG9Gb2xsb3c6IHN0cmluZyB8IG51bGw7XHJcblxyXG4gIHRhZ1NlcnZpY2U6IEJhc2VUYWdTZXJ2aWNlO1xyXG5cclxuICBjb25maWc6IENvbmZpZztcclxuXHJcbiAgcHVibGljIGluVHJhbnNpdGlvbk1vZGUgPSBmYWxzZTtcclxuXHJcbiAgcHVibGljIGluVHJhbnNpdGlvblN3ZWVwID0gZmFsc2U7XHJcblxyXG4gIHByaXZhdGUgbm9MaWdodEZvck9iamVjdHMgPSB0cnVlO1xyXG5cclxuICBwdWJsaWMgY3VycmVudENhbWVyYU1vZGU6IENhbWVyYU1vZGUgPSBDYW1lcmFNb2RlLk9VVFNJREU7XHJcblxyXG4gIHB1YmxpYyBvbkNhbWVyYU1vZGVDaGFuZ2VkID0gbmV3IFN1YmplY3Q8Q2FtZXJhTW9kZT4oKTtcclxuXHJcbiAgcHVibGljIG9uR29Ub1RhZyA9IG5ldyBTdWJqZWN0PHN0cmluZz4oKTtcclxuXHJcbiAgdGFnTWVzc2VuZ2VyT24gPSBmYWxzZTtcclxuXHJcbiAgU1BNb2R1bGU6IFNwTW9kdWxlO1xyXG5cclxuICBwdWJsaWMgb2JqZWN0Q29udHJvbDogYW55O1xyXG5cclxuICBwcml2YXRlIHNlY3VyaXR5Q2FtZXJhQW5pbWF0b3I6IGFueTtcclxuXHJcbiAgLyoqXHJcbiAgICogQWN0aW9ucyBvbiBsZWZ0IGNsaWNrIHdoZW4gcG9zaXRpb25pbmcgbWF0dGVydGFnIGluIHZpc2l0XHJcbiAgICovXHJcbiAgcG9pbnRlckxlZnRDbGlja0hhbmRsZXIgPSAoKSA9PiB7XHJcbiAgICBpZiAodGhpcy5tYXR0ZXJ0YWdUb0ZvbGxvdykge1xyXG4gICAgICBjb25zdCBtYXR0ZXJ0YWdEYXRhID0gdGhpcy5kaWN0aW9ubmFyeVRhZ3MuZ2V0KHRoaXMubWF0dGVydGFnVG9Gb2xsb3cpO1xyXG4gICAgICBtYXR0ZXJ0YWdEYXRhLnNldFBvc2l0aW9uKHsuLi50aGlzLnBvc2VNYXR0ZXJwb3J0LnBvc2l0aW9ufSk7IC8vIGNvcHkhISBub3QgdGhlIHJlZmVyZW5jZVxyXG4gICAgICBtYXR0ZXJ0YWdEYXRhLnNldE5vcm1hbCh7Li4udGhpcy5wb3NlTWF0dGVycG9ydC5ub3JtYWx9KTsgLy8gY29weSEhIG5vdCB0aGUgcmVmZXJlbmNlXHJcbiAgICAgIHRoaXMuZGljdGlvbm5hcnlUYWdzLnNldCh0aGlzLm1hdHRlcnRhZ1RvRm9sbG93LCBtYXR0ZXJ0YWdEYXRhKTtcclxuICAgICAgdGhpcy51cGRhdGVNYXR0ZXJUYWdDb250ZW50Rm9yVGFnSUQodGhpcy5tYXR0ZXJ0YWdUb0ZvbGxvdyk7XHJcbiAgICB9XHJcbiAgICB0aGlzLm9uVmFsaWRhdGVkTWF0dGVydGFnKCk7XHJcbiAgfTtcclxuXHJcbiAgcG9pbnRlclJpZ2h0Q2xpY2tIYW5kbGVyID0gKGUpID0+IHtcclxuICAgIGUucHJldmVudERlZmF1bHQoKTtcclxuICAgIHRoaXMuY2FuY2VsRm9sbG93aW5nQ3Vyc29yKCk7XHJcbiAgICBhbGVydCgnYWN0aW9uIGNhbmNlbGxlZCcpO1xyXG4gIH07XHJcblxyXG4gIHBvaW50ZXJNaWRkbGVDbGlja0hhbmRsZXIgPSAoZSkgPT4ge1xyXG4gICAgdGhpcy50ZXh0RGlzcGxheUN1cnNvclBvc2l0aW9uUGFuZWwuaW5uZXJIVE1MID0gYHBvc2l0aW9uOlxyXG4gICAgICAgJHt0aGlzLnBvaW50VG9TdHJpbmcodGhpcy5wb3NlTWF0dGVycG9ydC5wb3NpdGlvbil9XFxuXHJcbiAgICAgICBub3JtYWw6XHJcbiAgICAgICAke3RoaXMucG9pbnRUb1N0cmluZyh0aGlzLnBvc2VNYXR0ZXJwb3J0Lm5vcm1hbCl9XFxuXHJcbiAgICAgICBmbG9vcklkOlxyXG4gICAgICAgJHt0aGlzLnBvc2VNYXR0ZXJwb3J0LmZsb29ySWR9YDtcclxuICAgIC8vIHRoaXMudGV4dERpc3BsYXlDdXJzb3JQb3NpdGlvblBhbmVsLnN0eWxlLmRpc3BsYXkgPSAndmlzaWJsZSc7XHJcbiAgICB0aGlzLmdldEN1cnNvclBvc2l0aW9uQnV0dG9uLnN0eWxlLmRpc3BsYXkgPSAnbm9uZSc7XHJcbiAgfVxyXG5cclxuICBjb25zdHJ1Y3RvcihcclxuICAgIEBJbmplY3QoJ2NvbmZpZycpIGNvbmZpZzogQ29uZmlnLFxyXG4gICAgcHJpdmF0ZSByb3V0ZXI6IFJvdXRlcixcclxuICAgIHByaXZhdGUgYWN0aXZlUm91dGU6IEFjdGl2YXRlZFJvdXRlLFxyXG4gICAgcHJpdmF0ZSB2aXNpYmlsaXR5U2VydmljZTogQmFzZVZpc2liaWxpdHlTZXJ2aWNlLFxyXG4gICAgcHJpdmF0ZSBuZ1pvbmU6IE5nWm9uZVxyXG4gICkge1xyXG4gICAgdGhpcy5jb25maWcgPSBjb25maWc7XHJcblxyXG4gICAgLy8gVE9ETzogb25seSBmb3IgZGV2IVxyXG4gICAgaWYgKCEhdGhpcy5nZXRDdXJzb3JQb3NpdGlvbkJ1dHRvbiAmJlxyXG4gICAgICAoZG9jdW1lbnQubG9jYXRpb24uaHJlZi5pbmRleE9mKCdkZXYnKSAhPT0gLTEgfHwgZG9jdW1lbnQubG9jYXRpb24uaHJlZi5pbmRleE9mKCdsb2NhbGhvc3QnKSAhPT0gLTEpKSB7XHJcbiAgICAgIHRoaXMuaW50ZXJ2YWxDdXJzb3JQb2ludGVyUG9zaXRpb24gPSBzZXRJbnRlcnZhbCgoKSA9PiB7XHJcbiAgICAgICAgaWYgKCF0aGlzLnBvc2VNYXR0ZXJwb3J0KSB7XHJcbiAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBjb25zdCBuZXh0U2hvdyA9IHRoaXMucG9zZU1hdHRlcnBvcnQudGltZSArIDEwMDA7XHJcbiAgICAgICAgaWYgKG5ldyBEYXRlKCkuZ2V0VGltZSgpID4gbmV4dFNob3cpIHtcclxuICAgICAgICAgIGlmICh0aGlzLmN1cnNvclBvc2l0aW9uQnV0dG9uRGlzcGxheWVkKSB7XHJcbiAgICAgICAgICAgIHJldHVybjtcclxuICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICBjb25zdCBzaXplID0ge1xyXG4gICAgICAgICAgICB3OiB0aGlzLmNvbnRhaW5lci5jbGllbnRXaWR0aCxcclxuICAgICAgICAgICAgaDogdGhpcy5jb250YWluZXIuY2xpZW50SGVpZ2h0LFxyXG4gICAgICAgICAgfTtcclxuICAgICAgICAgIGNvbnN0IGNvb3JkID0gdGhpcy5zZGsuQ29udmVyc2lvbi53b3JsZFRvU2NyZWVuKHRoaXMucG9zZU1hdHRlcnBvcnQucG9zaXRpb24sIHRoaXMucG9zZUNhbWVyYSwgc2l6ZSk7XHJcbiAgICAgICAgICB0aGlzLmdldEN1cnNvclBvc2l0aW9uQnV0dG9uLnN0eWxlLmxlZnQgPSBgJHtjb29yZC54IC0gMjV9cHhgO1xyXG4gICAgICAgICAgdGhpcy5nZXRDdXJzb3JQb3NpdGlvbkJ1dHRvbi5zdHlsZS50b3AgPSBgJHtjb29yZC55IC0gMjJ9cHhgO1xyXG4gICAgICAgICAgdGhpcy5nZXRDdXJzb3JQb3NpdGlvbkJ1dHRvbi5zdHlsZS5kaXNwbGF5ID0gJ2Jsb2NrJztcclxuICAgICAgICAgIC8vIHRoaXMudGV4dERpc3BsYXlDdXJzb3JQb3NpdGlvblBhbmVsLnN0eWxlLmRpc3BsYXkgPSAnbm9uZSc7XHJcbiAgICAgICAgICB0aGlzLmN1cnNvclBvc2l0aW9uQnV0dG9uRGlzcGxheWVkID0gdHJ1ZTtcclxuICAgICAgICB9XHJcbiAgICAgIH0sIDUwMCk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBJbml0aWFsaXplcyBNYXR0ZXJwb3J0IGFuZCBhbGwgbGlzdGVuZXJzL2RhdGFcclxuICAgKiBAcGFyYW0gdGFnU2VydmljZSBCYXNlVGFnU2VydmljZSAodG8gaW5qZWN0IGh0bWwpXHJcbiAgICogQHBhcmFtIG1vZHVsZSBTcE1vZHVsZSAoTXVzZXVtLCBJbW1vKSB0byBzdWJzY3JpYmUgb25seSB0byBuZWVkZWQgZnVuY3Rpb25ubmFsaXRpZXNcclxuICAgKiBAcmV0dXJucyBib29sZWFuXHJcbiAgICovXHJcbiAgYXN5bmMgaW5pdFNkayhcclxuICAgIHRhZ1NlcnZpY2U6IEJhc2VUYWdTZXJ2aWNlLFxyXG4gICAgbW9kdWxlOiBTcE1vZHVsZSA9IFNwTW9kdWxlLklNTU9cclxuICApOiBQcm9taXNlPGJvb2xlYW4+IHtcclxuICAgIGlmICh0aGlzLnNkaykge1xyXG4gICAgICAvLyBjbGVhbiBpZiBzZGsgaXMgcnVubmluZyBhbHJlYWR5XHJcbiAgICAgIGF3YWl0IHRoaXMuYWN0aW9uX2RlbGV0ZV9hbGxfbWF0dGVydGFncygpO1xyXG4gICAgfVxyXG4gICAgdGhpcy50YWdTZXJ2aWNlID0gdGFnU2VydmljZTtcclxuICAgIHRoaXMuU1BNb2R1bGUgPSBtb2R1bGU7XHJcbiAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xyXG4gICAgICAvLyBSZXRyaWV2ZSBET00gZWxlbWVudHNcclxuICAgICAgdGhpcy5wb2ludGVyQnV0dG9uID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvcihcclxuICAgICAgICAnI3ZpZXdlci1wb2ludGVyLXRyaWNrJ1xyXG4gICAgICApIGFzIEhUTUxFbGVtZW50O1xyXG4gICAgICB0aGlzLmNvbnRhaW5lciA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoJyN2aWV3ZXItbW9kdWxlJykgYXMgSFRNTEVsZW1lbnQ7XHJcbiAgICAgIGNvbnN0IGlmcmFtZSA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoXHJcbiAgICAgICAgJyN2aWV3ZXItbW9kdWxlJ1xyXG4gICAgICApIGFzIEhUTUxJRnJhbWVFbGVtZW50O1xyXG4gICAgICBpZiAoIWlmcmFtZSkge1xyXG4gICAgICAgIHJldHVybjtcclxuICAgICAgfVxyXG5cclxuICAgICAgLy8gQWRkIGxpc3RlbmVyc1xyXG4gICAgICBpZiAodGhpcy5wb2ludGVyQnV0dG9uKSB7XHJcbiAgICAgICAgdGhpcy5wb2ludGVyQnV0dG9uLmFkZEV2ZW50TGlzdGVuZXIoXHJcbiAgICAgICAgICAnY2xpY2snLFxyXG4gICAgICAgICAgdGhpcy5wb2ludGVyTGVmdENsaWNrSGFuZGxlclxyXG4gICAgICAgICk7XHJcbiAgICAgICAgLy8gY2FuY2VsIG9uIHJpZ2h0IGNsaWNrXHJcbiAgICAgICAgdGhpcy5wb2ludGVyQnV0dG9uLmFkZEV2ZW50TGlzdGVuZXIoXHJcbiAgICAgICAgICAnY29udGV4dG1lbnUnLFxyXG4gICAgICAgICAgdGhpcy5wb2ludGVyUmlnaHRDbGlja0hhbmRsZXJcclxuICAgICAgICApO1xyXG4gICAgICB9XHJcbiAgICAgIC8vIFJldHJpZXZlIERPTSBlbGVtZW50c1xyXG4gICAgICB0aGlzLmdldEN1cnNvclBvc2l0aW9uQnV0dG9uID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvcihcclxuICAgICAgICAnI2J1dHRvbidcclxuICAgICAgKSBhcyBIVE1MRWxlbWVudDtcclxuICAgICAgdGhpcy50ZXh0RGlzcGxheUN1cnNvclBvc2l0aW9uUGFuZWwgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKFxyXG4gICAgICAgICcjdGV4dCdcclxuICAgICAgKSBhcyBIVE1MRWxlbWVudDtcclxuICAgICAgaWYgKHRoaXMuZ2V0Q3Vyc29yUG9zaXRpb25CdXR0b24pIHtcclxuICAgICAgICAvLyBnZXQgcG9zaXRpb24gb24gTWF0dGVycG9ydCBcIm1vZGVsXCIgb24gbWlkZGxlIGNsaWNrXHJcbiAgICAgICAgdGhpcy5nZXRDdXJzb3JQb3NpdGlvbkJ1dHRvbi5hZGRFdmVudExpc3RlbmVyKFxyXG4gICAgICAgICAgJ2NsaWNrJyxcclxuICAgICAgICAgIHRoaXMucG9pbnRlck1pZGRsZUNsaWNrSGFuZGxlclxyXG4gICAgICAgICk7XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIC8vIExvYWQgU0RLXHJcbiAgICAgIGNvbnNvbGUubG9nKCdMb2FkaW5nIE1hdHRlcnBvcnQgU0RLJyk7XHJcbiAgICAgIGNvbnN0IHNob3djYXNlV2luZG93ID0gaWZyYW1lLmNvbnRlbnRXaW5kb3c7XHJcbiAgICAgIGlmcmFtZS5hZGRFdmVudExpc3RlbmVyKFxyXG4gICAgICAgICdsb2FkJyxcclxuICAgICAgICBhc3luYyBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICB0cnkge1xyXG4gICAgICAgICAgICB0aGlzLnNkayA9IGF3YWl0IHNob3djYXNlV2luZG93Lk1QX1NESy5jb25uZWN0KFxyXG4gICAgICAgICAgICAgIHNob3djYXNlV2luZG93LFxyXG4gICAgICAgICAgICAgICdxbjl3c2FzdXk1aDJmenJicm4xbnpyMGlkJyxcclxuICAgICAgICAgICAgICAnMy41J1xyXG4gICAgICAgICAgICApO1xyXG4gICAgICAgICAgfSBjYXRjaCAoZSkge1xyXG4gICAgICAgICAgICBjb25zb2xlLmVycm9yKGUpO1xyXG4gICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgLy8gTG9hZCBNYXR0ZXJ0YWcgaWNvbnMgYW5kIGN1c3RvbSBzdWJzY3JpcHRpb25zXHJcbiAgICAgICAgICBzd2l0Y2ggKG1vZHVsZSkge1xyXG4gICAgICAgICAgICBjYXNlIFNwTW9kdWxlLklNTU86XHJcbiAgICAgICAgICAgICAgdGhpcy5zZGsuQXNzZXQucmVnaXN0ZXJUZXh0dXJlKFxyXG4gICAgICAgICAgICAgICAgJ2ljb24tdGlja2V0JyxcclxuICAgICAgICAgICAgICAgIHRoaXMuY29uZmlnLm15X2NvbmZpZy5pY29uX3RpY2tldFxyXG4gICAgICAgICAgICAgICk7XHJcbiAgICAgICAgICAgICAgdGhpcy5zZGsuQXNzZXQucmVnaXN0ZXJUZXh0dXJlKFxyXG4gICAgICAgICAgICAgICAgJ2ljb24tZXF1aXBtZW50JyxcclxuICAgICAgICAgICAgICAgIHRoaXMuY29uZmlnLm15X2NvbmZpZy5pY29uX2VxdWlwbWVudFxyXG4gICAgICAgICAgICAgICk7XHJcbiAgICAgICAgICAgICAgdGhpcy5zZGsuQXNzZXQucmVnaXN0ZXJUZXh0dXJlKFxyXG4gICAgICAgICAgICAgICAgJ2ljb24tbWVhc3VyZScsXHJcbiAgICAgICAgICAgICAgICB0aGlzLmNvbmZpZy5teV9jb25maWcuaWNvbl9tZWFzdXJlXHJcbiAgICAgICAgICAgICAgKTtcclxuICAgICAgICAgICAgICB0aGlzLnNkay5Bc3NldC5yZWdpc3RlclRleHR1cmUoXHJcbiAgICAgICAgICAgICAgICAnaWNvbi1kYXRhJyxcclxuICAgICAgICAgICAgICAgIHRoaXMuY29uZmlnLm15X2NvbmZpZy5pY29uX2RhdGFcclxuICAgICAgICAgICAgICApO1xyXG4gICAgICAgICAgICAgIHRoaXMuc2RrLkFzc2V0LnJlZ2lzdGVyVGV4dHVyZShcclxuICAgICAgICAgICAgICAgICdpY29uLW9iamVjdDNkJyxcclxuICAgICAgICAgICAgICAgIHRoaXMuY29uZmlnLm15X2NvbmZpZy5pY29uX29iamVjdDNkXHJcbiAgICAgICAgICAgICAgKTtcclxuXHJcbiAgICAgICAgICAgICAgdGhpcy5zZGsuTWVhc3VyZW1lbnRzLmRhdGEuc3Vic2NyaWJlKHtcclxuICAgICAgICAgICAgICAgIG9uQWRkZWQ6IGZ1bmN0aW9uIChcclxuICAgICAgICAgICAgICAgICAgaW5kZXg6IGFueSxcclxuICAgICAgICAgICAgICAgICAgaXRlbTogeyBwb2ludHM6IGFueSB9LFxyXG4gICAgICAgICAgICAgICAgICBjb2xsZWN0aW9uOiBhbnlcclxuICAgICAgICAgICAgICAgICkge1xyXG4gICAgICAgICAgICAgICAgICAvLyBjb25zb2xlLmxvZyhcclxuICAgICAgICAgICAgICAgICAgLy8gICAgIFwiaXRlbSBhZGRlZCB0byB0aGUgY29sbGVjdGlvblwiLFxyXG4gICAgICAgICAgICAgICAgICAvLyAgICAgaW5kZXgsXHJcbiAgICAgICAgICAgICAgICAgIC8vICAgICBpdGVtLFxyXG4gICAgICAgICAgICAgICAgICAvLyApO1xyXG4gICAgICAgICAgICAgICAgICAvLyB0aGlzLm1lYXN1cmVtZW50c1tpbmRleF0gPSBpdGVtO1xyXG4gICAgICAgICAgICAgICAgICB0aGlzLmxhc3RNZWFzdXJlID0gaXRlbS5wb2ludHM7XHJcbiAgICAgICAgICAgICAgICB9LmJpbmQodGhpcyksXHJcbiAgICAgICAgICAgICAgICBvbkNvbGxlY3Rpb25VcGRhdGVkOiBmdW5jdGlvbiAoY29sbGVjdGlvbjogYW55KSB7XHJcbiAgICAgICAgICAgICAgICAgIC8vIGNvbnNvbGUubG9nKCd0aGUgZW50aXJlIHVwLXRvLWRhdGUgY29sbGVjdGlvbicsIGNvbGxlY3Rpb24pO1xyXG4gICAgICAgICAgICAgICAgICB0aGlzLmdldERpc3RhbmNlRm9yTGFzdE1lYXN1cmVtZW50KCk7XHJcbiAgICAgICAgICAgICAgICB9LmJpbmQodGhpcyksXHJcbiAgICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgICAgICAgdGhpcy5zZGsuTWVhc3VyZW1lbnRzLm1vZGUuc3Vic2NyaWJlKFxyXG4gICAgICAgICAgICAgICAgZnVuY3Rpb24gKG1lYXN1cmVtZW50TW9kZVN0YXRlOiB7IGFjdGl2ZTogYW55IH0pIHtcclxuICAgICAgICAgICAgICAgICAgLy8gbWVhc3VyZW1lbnQgbW9kZSBzdGF0ZSBoYXMgY2hhbmdlZFxyXG4gICAgICAgICAgICAgICAgICB0aGlzLmlzTWVhc3VyZU1vZGVPbiA9IG1lYXN1cmVtZW50TW9kZVN0YXRlLmFjdGl2ZTtcclxuICAgICAgICAgICAgICAgICAgLy8gY29uc29sZS5sb2coJ0lzIG1lYXN1cmVtZW50IG1vZGUgY3VycmVudGx5IGFjdGl2ZT8gJywgbWVhc3VyZW1lbnRNb2RlU3RhdGUuYWN0aXZlKTtcclxuICAgICAgICAgICAgICAgIH0uYmluZCh0aGlzKVxyXG4gICAgICAgICAgICAgICk7XHJcbiAgICAgICAgICAgICAgYnJlYWs7XHJcbiAgICAgICAgICAgIGNhc2UgU3BNb2R1bGUuTVVTRVVNOlxyXG4gICAgICAgICAgICAgIHRoaXMuc2RrLkFzc2V0LnJlZ2lzdGVyVGV4dHVyZShcclxuICAgICAgICAgICAgICAgICdpY29uLWRhdGEnLFxyXG4gICAgICAgICAgICAgICAgdGhpcy5jb25maWcubXlfY29uZmlnLmljb25fZGF0YVxyXG4gICAgICAgICAgICAgICk7XHJcbiAgICAgICAgICAgICAgYnJlYWs7XHJcbiAgICAgICAgICAgIGNhc2UgU3BNb2R1bGUuSE9URUw6XHJcbiAgICAgICAgICAgICAgdGhpcy5zZGsuQXNzZXQucmVnaXN0ZXJUZXh0dXJlKFxyXG4gICAgICAgICAgICAgICAgJ2ljb25fcm9vbV9hdmFpbGFibGUnLFxyXG4gICAgICAgICAgICAgICAgdGhpcy5jb25maWcubXlfY29uZmlnLmljb25fcm9vbV9hdmFpbGFibGVcclxuICAgICAgICAgICAgICApO1xyXG4gICAgICAgICAgICAgIHRoaXMuc2RrLkFzc2V0LnJlZ2lzdGVyVGV4dHVyZShcclxuICAgICAgICAgICAgICAgICdpY29uX3Jvb21fdW5hdmFpbGFibGUnLFxyXG4gICAgICAgICAgICAgICAgdGhpcy5jb25maWcubXlfY29uZmlnLmljb25fcm9vbV91bmF2YWlsYWJsZVxyXG4gICAgICAgICAgICAgICk7XHJcbiAgICAgICAgICAgICAgdGhpcy5zZGsuQXNzZXQucmVnaXN0ZXJUZXh0dXJlKFxyXG4gICAgICAgICAgICAgICAgJ2ljb25fcm9vbV9jaG9zZW4nLFxyXG4gICAgICAgICAgICAgICAgdGhpcy5jb25maWcubXlfY29uZmlnLmljb25fcm9vbV9jaG9zZW5cclxuICAgICAgICAgICAgICApO1xyXG4gICAgICAgICAgICAgIHRoaXMuc2RrLkFzc2V0LnJlZ2lzdGVyVGV4dHVyZShcclxuICAgICAgICAgICAgICAgICdpY29uX3Jvb21fdmlld2VkJyxcclxuICAgICAgICAgICAgICAgIHRoaXMuY29uZmlnLm15X2NvbmZpZy5pY29uX3Jvb21fdmlld2VkXHJcbiAgICAgICAgICAgICAgKTtcclxuICAgICAgICAgICAgICBicmVhaztcclxuICAgICAgICAgICAgZGVmYXVsdDpcclxuICAgICAgICAgICAgICBicmVhaztcclxuICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICB0aGlzLnNkay5Bc3NldC5yZWdpc3RlclRleHR1cmUoXHJcbiAgICAgICAgICAgICdpY29uLXBvc2l0aW9uJyxcclxuICAgICAgICAgICAgdGhpcy5jb25maWcubXlfY29uZmlnLmljb25fcG9zaXRpb25cclxuICAgICAgICAgICk7XHJcblxyXG4gICAgICAgICAgLy8gQ3VycmVudCBSb29tICh1c2VkIGZvciBnZXR0aW5nIGJvdW5kaW5nIGJveCBhbmQgZXZlbnR1YWxseSBsYXp5IGxvYWQgbWF0dGVydGFnIG9yIG9iamVjdDNEIGluc2lkZSBjdXJyZW50IFJvb20pXHJcbiAgICAgICAgICB0aGlzLnNkay5Sb29tLmN1cnJlbnQuc3Vic2NyaWJlKChjdXJyZW50Um9vbSkgPT4ge1xyXG4gICAgICAgICAgICBjb25zb2xlLmxvZyhgaGVsbG8gY3VycmVudCBSb29tICR7SlNPTi5zdHJpbmdpZnkoY3VycmVudFJvb20pfWApO1xyXG4gICAgICAgICAgfSk7XHJcblxyXG4gICAgICAgICAgLy8gM0QgcG9zaXRpb24ncyBwb2ludGVyXHJcbiAgICAgICAgICB0aGlzLnNkay5Qb2ludGVyLmludGVyc2VjdGlvbi5zdWJzY3JpYmUoXHJcbiAgICAgICAgICAgIGZ1bmN0aW9uIChpbnRlcnNlY3Rpb246IGFueSkge1xyXG4gICAgICAgICAgICAgIHRoaXMucG9zZU1hdHRlcnBvcnQgPSBpbnRlcnNlY3Rpb247XHJcbiAgICAgICAgICAgICAgdGhpcy5wb3NlTWF0dGVycG9ydC50aW1lID0gbmV3IERhdGUoKS5nZXRUaW1lKCk7XHJcbiAgICAgICAgICAgICAgaWYgKCF0aGlzLm9sZFBvc2VNYXR0ZXJwb3J0UG9zaXRpb24pIHtcclxuICAgICAgICAgICAgICAgIHRoaXMub2xkUG9zZU1hdHRlcnBvcnRQb3NpdGlvbiA9IHtcclxuICAgICAgICAgICAgICAgICAgeDogMCxcclxuICAgICAgICAgICAgICAgICAgeTogMCxcclxuICAgICAgICAgICAgICAgICAgejogMCxcclxuICAgICAgICAgICAgICAgIH07XHJcbiAgICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgICBpZiAoXHJcbiAgICAgICAgICAgICAgICB0aGlzLmludGVyYWN0aW9uTW9kZSAhPT0gVmlld2VySW50ZXJhY3Rpb25zLkRFRkFVTFQgJiZcclxuICAgICAgICAgICAgICAgIHRoaXMubWF0dGVydGFnVG9Gb2xsb3dcclxuICAgICAgICAgICAgICApIHtcclxuICAgICAgICAgICAgICAgIC8vIGZvbGxvdyB0aGUgcG9pbnRlciBhbmQgY2hhbmdlcyB0aGUgcG9zaXRpb24gb2YgdGhlIGxhc3QgdGFnXHJcbiAgICAgICAgICAgICAgICAvLyAod2UgYXJlIGFib3V0IHRvIHZhbGlkYXRlLCBidXQgaXQgZXhpc3RzIGluIHNkayBhbHJlYWR5KVxyXG4gICAgICAgICAgICAgICAgdGhpcy5lbmFibGVfZm9sbG93aW5nX3RhZyh0aGlzLm1hdHRlcnRhZ1RvRm9sbG93KTtcclxuICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgaWYgKCEhdGhpcy5nZXRDdXJzb3JQb3NpdGlvbkJ1dHRvbiAmJiAhIXRoaXMuZ2V0Q3Vyc29yUG9zaXRpb25CdXR0b24uc3R5bGUgJiZcclxuICAgICAgICAgICAgICAoZG9jdW1lbnQuVVJMLmluZGV4T2YoJ2h0dHBzOi8vZGV2LnNtYXJ0ZXJwbGFuLmlvJykgIT09IC0xIHx8IGRvY3VtZW50LmxvY2F0aW9uLmhyZWYuaW5kZXhPZignbG9jYWxob3N0JykgIT09IC0xKSkge1xyXG4gICAgICAgICAgICAgICAgdGhpcy5nZXRDdXJzb3JQb3NpdGlvbkJ1dHRvbi5zdHlsZS5kaXNwbGF5ID0gJ25vbmUnO1xyXG4gICAgICAgICAgICAgICAgdGhpcy5jdXJzb3JQb3NpdGlvbkJ1dHRvbkRpc3BsYXllZCA9IGZhbHNlO1xyXG4gICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfS5iaW5kKHRoaXMpXHJcbiAgICAgICAgICApO1xyXG5cclxuICAgICAgICAgIC8vQ2FtZXJhIG1vZGVcclxuICAgICAgICAgIHRoaXMuc2RrLk1vZGUuY3VycmVudC5zdWJzY3JpYmUoKG1vZGUpID0+IHtcclxuICAgICAgICAgICAgdGhpcy5pblRyYW5zaXRpb25Td2VlcCA9IGZhbHNlO1xyXG4gICAgICAgICAgICBzd2l0Y2ggKG1vZGUpIHtcclxuICAgICAgICAgICAgICBjYXNlICdtb2RlLmRvbGxob3VzZSc6XHJcbiAgICAgICAgICAgICAgICB0aGlzLmN1cnJlbnRDYW1lcmFNb2RlID0gQ2FtZXJhTW9kZS5ET0xMSE9VU0U7XHJcbiAgICAgICAgICAgICAgICBicmVhaztcclxuICAgICAgICAgICAgICBjYXNlICdtb2RlLmZsb29ycGxhbic6XHJcbiAgICAgICAgICAgICAgICB0aGlzLmN1cnJlbnRDYW1lcmFNb2RlID0gQ2FtZXJhTW9kZS5GTE9PUlBMQU47XHJcbiAgICAgICAgICAgICAgICBicmVhaztcclxuICAgICAgICAgICAgICBjYXNlICdtb2RlLmluc2lkZSc6XHJcbiAgICAgICAgICAgICAgICB0aGlzLmN1cnJlbnRDYW1lcmFNb2RlID0gQ2FtZXJhTW9kZS5JTlNJREU7XHJcbiAgICAgICAgICAgICAgICBicmVhaztcclxuICAgICAgICAgICAgICBjYXNlICdtb2RlLnRyYW5zaXRpb25pbmcnOlxyXG4gICAgICAgICAgICAgICAgdGhpcy5jdXJyZW50Q2FtZXJhTW9kZSA9IENhbWVyYU1vZGUuVFJBTlNJVElPTklORztcclxuICAgICAgICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgICAgICAgIGRlZmF1bHQ6XHJcbiAgICAgICAgICAgICAgICB0aGlzLmN1cnJlbnRDYW1lcmFNb2RlID0gQ2FtZXJhTW9kZS5PVVRTSURFO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIHRoaXMub25DYW1lcmFNb2RlQ2hhbmdlZC5uZXh0KHRoaXMuY3VycmVudENhbWVyYU1vZGUpO1xyXG4gICAgICAgICAgfSk7XHJcblxyXG4gICAgICAgICAgLy8gQ2FtZXJhJ3Mgdmlld3BvaW50XHJcbiAgICAgICAgICB0aGlzLnNkay5DYW1lcmEucG9zZS5zdWJzY3JpYmUoXHJcbiAgICAgICAgICAgIGZ1bmN0aW9uIHN1YnNjcihwb3NlOiBhbnkpIHtcclxuICAgICAgICAgICAgICB0aGlzLnBvc2VDYW1lcmEgPSBwb3NlO1xyXG5cclxuICAgICAgICAgICAgICB0aGlzLmN1cnJlbnRDYW1lcmFQb3NlLm5leHQocG9zZSk7XHJcbiAgICAgICAgICAgICAgLy8gY29uc29sZS5sb2coJ0N1cnJlbnQgcG9zaXRpb24gaXMgJywgcG9zZS5wb3NpdGlvbik7XHJcbiAgICAgICAgICAgICAgLy8gY29uc29sZS5sb2coJ1JvdGF0aW9uIGFuZ2xlIGlzICcsIHBvc2Uucm90YXRpb24pO1xyXG4gICAgICAgICAgICAgIC8vIGNvbnNvbGUubG9nKFwiU3dlZXAgVVVJRCBpc1wiLCBwb3NlLnN3ZWVwKTtcclxuICAgICAgICAgICAgfS5iaW5kKHRoaXMpXHJcbiAgICAgICAgICApO1xyXG5cclxuICAgICAgICAgIC8vIHN1YnNjcmliZSB0byBzd2VlcHNcclxuICAgICAgICAgIHRoaXMuc2RrLlN3ZWVwLmRhdGEuc3Vic2NyaWJlKHtcclxuICAgICAgICAgICAgb25Db2xsZWN0aW9uVXBkYXRlZDogZnVuY3Rpb24gc3Vic2NyKGNvbGxlY3Rpb246IHt9KSB7XHJcbiAgICAgICAgICAgICAgLy8gY29uc29sZS5sb2coXCJTd2VlcCBjb2xsZWN0aW9uIHVwZGF0ZWRcIik7XHJcbiAgICAgICAgICAgICAgdGhpcy5zd2VlcHMgPSBPYmplY3Qua2V5cyhjb2xsZWN0aW9uKTtcclxuICAgICAgICAgICAgfS5iaW5kKHRoaXMpLFxyXG4gICAgICAgICAgfSk7XHJcblxyXG4gICAgICAgICAgLy8gc3Vic2NyaWJlIHRvIGN1cnJlbnQgc3dlZXBcclxuICAgICAgICAgIHRoaXMuc2RrLlN3ZWVwLmN1cnJlbnQuc3Vic2NyaWJlKFxyXG4gICAgICAgICAgICBmdW5jdGlvbiBzdWJzY3IoY3VycmVudFN3ZWVwOiB7IHNpZDogc3RyaW5nIH0pIHtcclxuICAgICAgICAgICAgICAvLyBDaGFuZ2UgdG8gdGhlIGN1cnJlbnQgc3dlZXAgaGFzIG9jY3VycmVkLlxyXG4gICAgICAgICAgICAgIGlmIChjdXJyZW50U3dlZXAuc2lkID09PSAnJykge1xyXG4gICAgICAgICAgICAgICAgLy8gY29uc29sZS5sb2coJ05vdCBjdXJyZW50bHkgc3RhdGlvbmVkIGF0IGEgc3dlZXAgcG9zaXRpb24nKTtcclxuICAgICAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgLy8gY29uc29sZS5sb2coXCJlbW1pdGluZyBzd2VlcFwiLCBjdXJyZW50U3dlZXAuc2lkKTtcclxuICAgICAgICAgICAgICAgIHRoaXMuY3VycmVudFN3ZWVwLm5leHQoY3VycmVudFN3ZWVwLnNpZCk7XHJcbiAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB9LmJpbmQodGhpcylcclxuICAgICAgICAgICk7XHJcblxyXG4gICAgICAgICAgLy8gU3Vic2NyaWJlIHRvIEZsb29yIGRhdGFcclxuICAgICAgICAgIHRoaXMuc2RrLkZsb29yLmRhdGEuc3Vic2NyaWJlKHtcclxuICAgICAgICAgICAgb25Db2xsZWN0aW9uVXBkYXRlZDogZnVuY3Rpb24gdXBkKHRoaXM6IGFueSwgY29sbGVjdGlvbjogYW55KSB7XHJcbiAgICAgICAgICAgICAgdGhpcy5mbG9vcnMgPSBPYmplY3QudmFsdWVzKGNvbGxlY3Rpb24pO1xyXG4gICAgICAgICAgICB9LmJpbmQodGhpcyksXHJcbiAgICAgICAgICB9KTtcclxuXHJcbiAgICAgICAgICAvLyBvbiB0YWcgY2xpY2sgb3BlbiBkZXRhaWxzIHBhZ2VcclxuICAgICAgICAgIHRoaXMuc2RrLm9uKCd0YWcuY2xpY2snLCAoc2lkOiBzdHJpbmcpID0+IHtcclxuICAgICAgICAgICAgLy8gZ2V0IG9iamVjdCBvZiB0aGlzIHRhZ1xyXG4gICAgICAgICAgICB0cnkge1xyXG4gICAgICAgICAgICAgIGNvbnN0IG1hdHRlcnRhZ0RhdGEgPSB0aGlzLmRpY3Rpb25uYXJ5VGFncy5nZXQoc2lkKTtcclxuICAgICAgICAgICAgICBpZiAoIW1hdHRlcnRhZ0RhdGEpe1xyXG4gICAgICAgICAgICAgICAgY29uc29sZS5sb2coJ25vIG1hdHRlcnRhZ0RhdGEgdG8gZGlzcGxheScpO1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICBjb25zdCB1cmwgPSB0YWdTZXJ2aWNlLmdldFVybEZvclNlZURldGFpbHMoXHJcbiAgICAgICAgICAgICAgICBtYXR0ZXJ0YWdEYXRhLmdldE9iamVjdCgpLFxyXG4gICAgICAgICAgICAgICAgbWF0dGVydGFnRGF0YS5nZXRUeXBlKClcclxuICAgICAgICAgICAgICApO1xyXG4gICAgICAgICAgICAgIGlmICh1cmwgIT09ICcnKSB7XHJcbiAgICAgICAgICAgICAgICB0aGlzLnZpc2liaWxpdHlTZXJ2aWNlLmRldGFpbFNob3dpbmcubmV4dCh0cnVlKTtcclxuICAgICAgICAgICAgICAgIHRoaXMubmdab25lLnJ1bigoKSA9PiB7XHJcbiAgICAgICAgICAgICAgICAgIHRoaXMucm91dGVyLm5hdmlnYXRlKFt1cmxdKTtcclxuICAgICAgICAgICAgICAgIH0pO1xyXG4gICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfSBjYXRjaCB7XHJcbiAgICAgICAgICAgICAgY29uc29sZS5sb2coJ0Nhbm5vdCBzaG93IGRldGFpbHMgZm9yIHRhZycpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICB9KTtcclxuXHJcbiAgICAgICAgICAvLyBQb2ludGVyIHRyaWNrXHJcbiAgICAgICAgICAvLyBDcmVhdGUgYSBkaXYgdGhhdCB3aWxsIGFwcGVhciB3aGVuIHRoZSBjdXJzb3IgaXMgc3RpbGxcclxuICAgICAgICAgIC8vIEl0IHdpbGwgaW50ZXJjZXB0IHRoZSBjbGljayBvZiB0aGUgbW91c2UgYmVmb3JlIGl0IHRyaWdlcnJpbmcgdGhlIE1hdHRlcnBvcnQncyB0b3VyIG5hdmlnYXRpb25cclxuICAgICAgICAgIHRoaXMudGltZXJQb2ludGVyID0gc2V0SW50ZXJ2YWwoXHJcbiAgICAgICAgICAgIHRoaXMudXBkYXRlUG9pbnRlclRyaWNrLmJpbmQodGhpcyksXHJcbiAgICAgICAgICAgIDUwXHJcbiAgICAgICAgICApO1xyXG5cclxuICAgICAgICAgIC8qKlxyXG4gICAgICAgICAgICogVHJhbnNpdGlvbnNcclxuICAgICAgICAgICAqL1xyXG4gICAgICAgICAgdGhpcy5zZGsub24oXHJcbiAgICAgICAgICAgICd2aWV3bW9kZS5jaGFuZ2VzdGFydCcsXHJcbiAgICAgICAgICAgIGZ1bmN0aW9uICh0bywgZnJvbSkge1xyXG4gICAgICAgICAgICAgIC8vIGNvbnNvbGUubG9nKCdTdGFydGluZyB0byBtb3ZlIHRvICcgKyB0byArICcgZnJvbSAnICsgZnJvbSk7XHJcbiAgICAgICAgICAgICAgdGhpcy5pblRyYW5zaXRpb25Nb2RlID0gdHJ1ZTtcclxuICAgICAgICAgICAgfS5iaW5kKHRoaXMpXHJcbiAgICAgICAgICApO1xyXG5cclxuICAgICAgICAgIHRoaXMuc2RrLm9uKFxyXG4gICAgICAgICAgICAndmlld21vZGUuY2hhbmdlZW5kJyxcclxuICAgICAgICAgICAgZnVuY3Rpb24gKG9sZE1vZGUsIG5ld01vZGUpIHtcclxuICAgICAgICAgICAgICAvLyBjb25zb2xlLmxvZygnRW5kZWQgdG8gbW92ZSB0byAnICsgbmV3TW9kZSArICcgZnJvbSAnICsgb2xkTW9kZSk7XHJcbiAgICAgICAgICAgICAgaWYgKG5ld01vZGUgIT09ICdtb2RlLnRyYW5zaXRpb25pbmcnKSB7XHJcbiAgICAgICAgICAgICAgICB0aGlzLmluVHJhbnNpdGlvbk1vZGUgPSBmYWxzZTtcclxuICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH0uYmluZCh0aGlzKVxyXG4gICAgICAgICAgKTtcclxuXHJcbiAgICAgICAgICB0aGlzLnNkay5vbihcclxuICAgICAgICAgICAgdGhpcy5zZGsuU3dlZXAuRXZlbnQuRU5URVIsXHJcbiAgICAgICAgICAgIGZ1bmN0aW9uIChvbGRTd2VlcCwgbmV3U3dlZXApIHtcclxuICAgICAgICAgICAgICAvLyBjb25zb2xlLmxvZygnTGVhdmluZyBzd2VlcCAnICsgb2xkU3dlZXApO1xyXG4gICAgICAgICAgICAgIC8vIGNvbnNvbGUubG9nKCdFbnRlcmluZyBzd2VlcCAnICsgbmV3U3dlZXApO1xyXG4gICAgICAgICAgICAgIHRoaXMuaW5UcmFuc2l0aW9uU3dlZXAgPSBmYWxzZTtcclxuICAgICAgICAgICAgICB0aGlzLmRpc3BsYXlBemltdXRhbENyb3duKCk7XHJcbiAgICAgICAgICAgIH0uYmluZCh0aGlzKVxyXG4gICAgICAgICAgKTtcclxuICAgICAgICAgIHRoaXMuc2RrLm9uKFxyXG4gICAgICAgICAgICB0aGlzLnNkay5Td2VlcC5FdmVudC5FWElULFxyXG4gICAgICAgICAgICBmdW5jdGlvbiAoZnJvbVN3ZWVwLCB0b1N3ZWVwKSB7XHJcbiAgICAgICAgICAgICAgLy8gICBjb25zb2xlLmxvZygnTGVhdmluZyBzd2VlcCAnICsgZnJvbVN3ZWVwKTtcclxuICAgICAgICAgICAgICAvLyAgIGNvbnNvbGUubG9nKCdUcmFuc2l0aW9uaW5nIHRvIHN3ZWVwICcgKyB0b1N3ZWVwKTtcclxuICAgICAgICAgICAgICB0aGlzLmluVHJhbnNpdGlvblN3ZWVwID0gdHJ1ZTtcclxuICAgICAgICAgICAgfS5iaW5kKHRoaXMpXHJcbiAgICAgICAgICApO1xyXG5cclxuICAgICAgICAgIC8vIFRPRE86IGdldCBzY2VuZSB3aXRoIGdldHRlciBpbnN0ZWFkIVxyXG4gICAgICAgICAgY29uc3QgW3NjZW5lT2JqZWN0XSA9IGF3YWl0IHRoaXMuc2RrLlNjZW5lLmNyZWF0ZU9iamVjdHMoMSk7XHJcbiAgICAgICAgICBjb25zdCBub2RlID0gc2NlbmVPYmplY3QuYWRkTm9kZSgpO1xyXG4gICAgICAgICAgbm9kZS5zdGFydCgpO1xyXG4gICAgICAgICAgdGhpcy50aHJlZUpTU2NlbmUgPSBub2RlLm9iajNELnBhcmVudDtcclxuXHJcbiAgICAgICAgICAvLyBhd2FpdCB0aGlzLnNkay5TY2VuZS5jb25maWd1cmUoKHJlbmRlcmVyOiBhbnksIHRocmVlOiBhbnkpID0+IHtcclxuICAgICAgICAgIC8vICAgcmVuZGVyZXIucGh5c2ljYWxseUNvcnJlY3RMaWdodHMgPSB0cnVlO1xyXG4gICAgICAgICAgLy8gICByZW5kZXJlci5vdXRwdXRFbmNvZGluZyA9IHRocmVlLnNSR0JFbmNvZGluZztcclxuICAgICAgICAgIC8vICAgcmVuZGVyZXIuc2hhZG93TWFwLmVuYWJsZWQgPSB0cnVlO1xyXG4gICAgICAgICAgLy8gICByZW5kZXJlci5zaGFkb3dNYXAuYmlhcyA9IDAuMDAwMTtcclxuICAgICAgICAgIC8vICAgcmVuZGVyZXIuc2hhZG93TWFwLnR5cGUgPSB0aHJlZS5QQ0ZTb2Z0U2hhZG93TWFwO1xyXG4gICAgICAgICAgLy8gfSk7XHJcblxyXG5cclxuICAgICAgICAgIC8vIFRPRE86IHdhaXQgZm9yIE1QIHRpY2tldCByZXNvbHV0aW9uIGJlZm9yZSBkZWNvbW1lbnQgdGhlc2UhXHJcbiAgICAgICAgICAvLyBXYWl0IHVudGlsIFNob3djYXNlIGlzIGFjdHVhbGx5IHBsYXlpbmcuLi4uXHJcbiAgICAgICAgICAvLyB0aGlzLnNkay5UYWcuZGF0YS5zdWJzY3JpYmUoe1xyXG4gICAgICAgICAgLy8gICBvbkFkZGVkOiBhc3luYyBmdW5jdGlvbiAoaW5kZXgsIGl0ZW0sIGNvbGxlY3Rpb24pIHtcclxuICAgICAgICAgIC8vXHJcbiAgICAgICAgICAvLyAgICAgbGV0IHRoaXNPcGFjaXR5ID0gMC4yO1xyXG4gICAgICAgICAgLy8gICAgIHRoaXMuc2RrLlRhZy5lZGl0T3BhY2l0eShpbmRleCwgdGhpc09wYWNpdHkpO1xyXG4gICAgICAgICAgLy9cclxuICAgICAgICAgIC8vICAgICBsZXQgc291cmNlID0gbnVsbDtcclxuICAgICAgICAgIC8vICAgICB0cnkge1xyXG4gICAgICAgICAgLy8gICAgICAgc291cmNlID0gYXdhaXQgUHJvbWlzZS5hbGwoW1xyXG4gICAgICAgICAgLy8gICAgICAgICB0aGlzLnNkay5TZW5zb3IuY3JlYXRlU291cmNlKHRoaXMuc2RrLlNlbnNvci5Tb3VyY2VUeXBlLlNQSEVSRSwge1xyXG4gICAgICAgICAgLy8gICAgICAgICAgIG9yaWdpbjogaXRlbS5hbmNob3JQb3NpdGlvbixcclxuICAgICAgICAgIC8vICAgICAgICAgICByYWRpdXM6IE51bWJlcigzKSxcclxuICAgICAgICAgIC8vICAgICAgICAgICB1c2VyRGF0YToge1xyXG4gICAgICAgICAgLy8gICAgICAgICAgICAgaWQ6IGluZGV4ICsgJy1zcGhlcmUtc291cmNlJyxcclxuICAgICAgICAgIC8vICAgICAgICAgICB9LFxyXG4gICAgICAgICAgLy8gICAgICAgICB9KVxyXG4gICAgICAgICAgLy8gICAgICAgXSk7XHJcbiAgICAgICAgICAvLyAgICAgfSBjYXRjaCAoZSkge1xyXG4gICAgICAgICAgLy8gICAgICAgY29uc29sZS5sb2coJ2NvdWxkIG5vdCBjcmVhdGUgU3BoZXJlIHNlbnNvcicpXHJcbiAgICAgICAgICAvLyAgICAgICBjb25zb2xlLmVycm9yKGUpO1xyXG4gICAgICAgICAgLy8gICAgIH1cclxuICAgICAgICAgIC8vICAgICBpZiAoIXNvdXJjZSkge1xyXG4gICAgICAgICAgLy8gICAgICAgcmV0dXJuO1xyXG4gICAgICAgICAgLy8gICAgIH1cclxuICAgICAgICAgIC8vXHJcbiAgICAgICAgICAvLyAgICAgbGV0IHNlbnNvciA9IG51bGw7XHJcbiAgICAgICAgICAvLyAgICAgdHJ5IHtcclxuICAgICAgICAgIC8vICAgICAgIHNlbnNvciA9IGF3YWl0IHRoaXMuc2RrLlNlbnNvci5jcmVhdGVTZW5zb3IodGhpcy5zZGsuU2Vuc29yLlNlbnNvclR5cGUuQ0FNRVJBKTtcclxuICAgICAgICAgIC8vICAgICB9IGNhdGNoIChlKSB7XHJcbiAgICAgICAgICAvLyAgICAgICBjb25zb2xlLmxvZygnY291bGQgbm90IGNyZWF0ZSBDYW1lcmEgc2Vuc29yJylcclxuICAgICAgICAgIC8vICAgICAgIGNvbnNvbGUuZXJyb3IoZSk7XHJcbiAgICAgICAgICAvLyAgICAgfVxyXG4gICAgICAgICAgLy8gICAgIGlmICghc2Vuc29yKSB7XHJcbiAgICAgICAgICAvLyAgICAgICByZXR1cm47XHJcbiAgICAgICAgICAvLyAgICAgfVxyXG4gICAgICAgICAgLy9cclxuICAgICAgICAgIC8vICAgICBzZW5zb3IuYWRkU291cmNlKC4uLnNvdXJjZSk7XHJcbiAgICAgICAgICAvLyAgICAgc2Vuc29yLnJlYWRpbmdzLnN1YnNjcmliZSh7XHJcbiAgICAgICAgICAvLyAgICAgICBvblVwZGF0ZWQoc291cmNlLCByZWFkaW5nKSB7XHJcbiAgICAgICAgICAvLyAgICAgICAgIGNvbnNvbGUubG9nKHRoaXNPcGFjaXR5KTtcclxuICAgICAgICAgIC8vICAgICAgICAgbGV0IG9sZE9wYWNpdHkgPSB0aGlzT3BhY2l0eTtcclxuICAgICAgICAgIC8vICAgICAgICAgaWYgKHJlYWRpbmcuaW5SYW5nZSkge1xyXG4gICAgICAgICAgLy8gICAgICAgICAgIHRoaXNPcGFjaXR5ID0gMTtcclxuICAgICAgICAgIC8vICAgICAgICAgICBjb25zb2xlLmxvZyhpbmRleCArICcgaXMgaW5SYW5nZScpO1xyXG4gICAgICAgICAgLy8gICAgICAgICB9IGVsc2UgaWYgKHJlYWRpbmcuaW5WaWV3KSB7XHJcbiAgICAgICAgICAvLyAgICAgICAgICAgY29uc29sZS5sb2coaW5kZXggKyAnIGlzIGluVmlldyBidXQgbm90IGluUmFuZ2UnKTtcclxuICAgICAgICAgIC8vICAgICAgICAgICB0aGlzT3BhY2l0eSA9IDAuNTtcclxuICAgICAgICAgIC8vICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgIC8vICAgICAgICAgICB0aGlzT3BhY2l0eSA9IDAuMjtcclxuICAgICAgICAgIC8vICAgICAgICAgICBjb25zb2xlLmxvZyhpbmRleCArICcgaXMgbm90IGluVmlldyBvciBpblJhbmdlJyk7XHJcbiAgICAgICAgICAvLyAgICAgICAgIH1cclxuICAgICAgICAgIC8vXHJcbiAgICAgICAgICAvLyAgICAgICAgIHRoaXMuc2RrLlRhZy5lZGl0T3BhY2l0eShpbmRleCwgdGhpc09wYWNpdHkpO1xyXG4gICAgICAgICAgLy8gICAgICAgICAvKlxyXG4gICAgICAgICAgLy8gICAgICAgICAgICAgICAgICAgbGV0IGluYyA9IDAuMDE7XHJcbiAgICAgICAgICAvLyAgICAgICAgICAgICAgICAgICBpZiAob2xkT3BhY2l0eSA+IHRoaXNPcGFjaXR5KSB7XHJcbiAgICAgICAgICAvLyAgICAgICAgICAgICAgICAgICAgIGluYyA9IC0wLjAxO1xyXG4gICAgICAgICAgLy8gICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgLy9cclxuICAgICAgICAgIC8vICAgICAgICAgICAgICAgICAgIGZvcih2YXIgaSA9IG9sZE9wYWNpdHk7IGkgIT0gdGhpc09wYWNpdHk7IGk9aStpbmMpIHtcclxuICAgICAgICAgIC8vICAgICAgICAgICAgICAgICAgICAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uKCkge1xyXG4gICAgICAgICAgLy8gICAgICAgICAgICAgICAgICAgICAgICAgIG1wU2RrLlRhZy5lZGl0T3BhY2l0eShpbmRleCwgaSk7XHJcbiAgICAgICAgICAvLyAgICAgICAgICAgICAgICAgICAgICAgY29uc29sZS5sb2coJ0RlbGF5JywgaSk7XHJcbiAgICAgICAgICAvLyAgICAgICAgICAgICAgICAgICAgICAgfSwxMCk7XHJcbiAgICAgICAgICAvLyAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAvLyAgICAgICAgICovXHJcbiAgICAgICAgICAvLyAgICAgICB9XHJcbiAgICAgICAgICAvLyAgICAgfSk7XHJcbiAgICAgICAgICAvLyAgICAgLy9zZW5zb3Iuc2hvd0RlYnVnKHRydWUpO1xyXG4gICAgICAgICAgLy8gICB9LmJpbmQodGhpcyksXHJcbiAgICAgICAgICAvLyAgIG9uQ29sbGVjdGlvblVwZGF0ZWQ6IGZ1bmN0aW9uIChjb2xsZWN0aW9uKSB7XHJcbiAgICAgICAgICAvLyAgICAgY29uc29sZS5sb2coJ0NvbGxlY3Rpb24gcmVjZWl2ZWQuIFRoZXJlIGFyZSAnLCBPYmplY3Qua2V5cyhjb2xsZWN0aW9uKS5sZW5ndGgsICcgVGFncyBpbiB0aGUgY29sbGVjdGlvbicsIGNvbGxlY3Rpb24pO1xyXG4gICAgICAgICAgLy8gICB9XHJcbiAgICAgICAgICAvLyB9KTtcclxuXHJcbiAgICAgICAgICByZXNvbHZlKHRydWUpO1xyXG4gICAgICAgIH0uYmluZCh0aGlzKVxyXG4gICAgICApO1xyXG4gICAgfSk7XHJcbiAgfVxyXG5cclxuXHJcbiAgc2V0TGlnaHRpbmdPZmYoKSB7XHJcbiAgICB0aGlzLm5vTGlnaHRGb3JPYmplY3RzID0gdHJ1ZTtcclxuICB9XHJcblxyXG4gIHBvaW50VG9TdHJpbmcocG9pbnQ6IHsgeDogbnVtYmVyLCB5OiBudW1iZXIsIHo6IG51bWJlciB9KTogc3RyaW5nIHtcclxuICAgIHZhciB4ID0gcG9pbnQueC50b0ZpeGVkKDMpO1xyXG4gICAgdmFyIHkgPSBwb2ludC55LnRvRml4ZWQoMyk7XHJcbiAgICB2YXIgeiA9IHBvaW50LnoudG9GaXhlZCgzKTtcclxuXHJcbiAgICByZXR1cm4gYHsgeDogJHt4fSwgeTogJHt5fSwgejogJHt6fSB9YDtcclxuICB9XHJcblxyXG4gIC8vXHJcbiAgLy8gLS0tLS0tLS0tLSBNZWFzdXJlbWVudHMgcmVsYXRlZCAtLS0tLS0tLS0tXHJcbiAgLy9cclxuICAvKipcclxuICAgKiBDYWxsYmFjayBhZnRlciBtZWFzdXJlbWVudCBpcyBwZXJmb3JtZWRcclxuICAgKi9cclxuICBnZXREaXN0YW5jZUZvckxhc3RNZWFzdXJlbWVudCgpIHtcclxuICAgIGlmICh0aGlzLmxhc3RNZWFzdXJlLmxlbmd0aCA+IDApIHtcclxuICAgICAgY29uc3QgbnVtYmVyUG9pbnRzID0gdGhpcy5sYXN0TWVhc3VyZS5sZW5ndGg7XHJcbiAgICAgIHRoaXMuZGlzdGFuY2VzTGFzdE1lYXN1cmUgPSBbXTtcclxuICAgICAgZm9yIChsZXQgaW5kZXggPSAxOyBpbmRleCA8IG51bWJlclBvaW50czsgaW5kZXggKz0gMSkge1xyXG4gICAgICAgIGNvbnN0IGRpc3RhbmNlID0gZ2V0RGlzdGFuY2VCZXR3ZWVuVHdvUG9pbnRzKFxyXG4gICAgICAgICAgdGhpcy5sYXN0TWVhc3VyZVtpbmRleCAtIDFdLFxyXG4gICAgICAgICAgdGhpcy5sYXN0TWVhc3VyZVtpbmRleF1cclxuICAgICAgICApO1xyXG4gICAgICAgIHRoaXMuZGlzdGFuY2VzTGFzdE1lYXN1cmUucHVzaChkaXN0YW5jZSk7XHJcbiAgICAgIH1cclxuICAgICAgdGhpcy50YWtlU2NyZWVuU2hvdCgpLnRoZW4oKHJlcykgPT4ge1xyXG4gICAgICAgIHRoaXMucm91dGVyLm5hdmlnYXRlKFtgdmlzaXQvJHt0aGlzLmN1cnJlbnRTcGFjZUlEfS9hZGRfbWVhc3VyZW1lbnRgXSk7XHJcbiAgICAgIH0pO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgZ2V0TGFzdERpc3RhbmNlcygpIHtcclxuICAgIHJldHVybiB0aGlzLmRpc3RhbmNlc0xhc3RNZWFzdXJlO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogVGFrZXMgc2NyZWVuc2hvdCBhbmQgc2F2ZXMgYmFzZTY0IGluIGxhc3RTY3JlZW5zaG90VXJpXHJcbiAgICogQHJldHVybnMgUHJvbWlzZVxyXG4gICAqL1xyXG4gIHRha2VTY3JlZW5TaG90KCk6IFByb21pc2U8YW55PiB7XHJcbiAgICByZXR1cm4gdGhpcy5zZGsuUmVuZGVyZXIudGFrZVNjcmVlblNob3QoXHJcbiAgICAgIHRoaXMucmVzb2x1dGlvbixcclxuICAgICAgdGhpcy52aXNpYmlsaXR5XHJcbiAgICApLnRoZW4oXHJcbiAgICAgIGZ1bmN0aW9uIChzY3JlZW5TaG90VXJpOiBhbnkpIHtcclxuICAgICAgICAvLyBiYXNlNjQgc3RyaW5nXHJcbiAgICAgICAgdGhpcy5sYXN0U2NyZWVuc2hvdFVyaSA9IHNjcmVlblNob3RVcmk7XHJcbiAgICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpO1xyXG4gICAgICB9LmJpbmQodGhpcylcclxuICAgICk7XHJcbiAgfVxyXG5cclxuICBnZXRTY3JlZW5TaG90VXJpKCkge1xyXG4gICAgcmV0dXJuIHRoaXMubGFzdFNjcmVlbnNob3RVcmk7XHJcbiAgfVxyXG5cclxuICBnZXRMYXN0TWVhc3VyZW1lbnQoKTogT2JqZWN0IHtcclxuICAgIGNvbnN0IGRhdGEgPSB7XHJcbiAgICAgIG1lYXN1cmU6IHRoaXMubGFzdE1lYXN1cmUsXHJcbiAgICAgIHN3ZWVwOiB0aGlzLnBvc2VDYW1lcmEuc3dlZXAsXHJcbiAgICB9O1xyXG4gICAgcmV0dXJuIGRhdGE7XHJcbiAgfVxyXG5cclxuICAvL1xyXG4gIC8vIC0tLS0tLS0tLS0gVXRpbHMgLS0tLS0tLS0tLVxyXG4gIC8vXHJcbiAgLyoqXHJcbiAgICogU3R5bGluZyBvZiBwb2ludGVyXHJcbiAgICovXHJcbiAgdXBkYXRlUG9pbnRlclRyaWNrKCkge1xyXG4gICAgaWYgKFxyXG4gICAgICB0aGlzLmludGVyYWN0aW9uTW9kZSAhPT0gVmlld2VySW50ZXJhY3Rpb25zLkRFRkFVTFQgJiZcclxuICAgICAgdGhpcy5tYXR0ZXJ0YWdUb0ZvbGxvdyAmJlxyXG4gICAgICB0aGlzLnBvc2VNYXR0ZXJwb3J0ICYmXHJcbiAgICAgIHRoaXMuZ2V0RGlzdFBvc2l0aW9uKFxyXG4gICAgICAgIHRoaXMucG9zZU1hdHRlcnBvcnQucG9zaXRpb24sXHJcbiAgICAgICAgdGhpcy5vbGRQb3NlTWF0dGVycG9ydFBvc2l0aW9uXHJcbiAgICAgICkgPiAyNVxyXG4gICAgKSB7XHJcbiAgICAgIHRoaXMucG9pbnRlckJ1dHRvbi5zdHlsZS5kaXNwbGF5ID0gJ25vbmUnO1xyXG5cclxuICAgICAgY29uc3Qgc2l6ZSA9IHtcclxuICAgICAgICB3OiB0aGlzLmNvbnRhaW5lci5jbGllbnRXaWR0aCxcclxuICAgICAgICBoOiB0aGlzLmNvbnRhaW5lci5jbGllbnRIZWlnaHQsXHJcbiAgICAgIH07XHJcbiAgICAgIGNvbnN0IGNvb3JkcyA9IHRoaXMuc2RrLkNvbnZlcnNpb24ud29ybGRUb1NjcmVlbihcclxuICAgICAgICB0aGlzLnBvc2VNYXR0ZXJwb3J0LnBvc2l0aW9uLFxyXG4gICAgICAgIHRoaXMucG9zZUNhbWVyYSxcclxuICAgICAgICBzaXplXHJcbiAgICAgICk7XHJcbiAgICAgIHRoaXMucG9pbnRlckJ1dHRvbi5zdHlsZS5sZWZ0ID0gYCR7XHJcbiAgICAgICAgY29vcmRzLnggKiBNYXRoLnNpZ24oY29vcmRzLngpIC0gMjVcclxuICAgICAgfXB4YDtcclxuICAgICAgdGhpcy5wb2ludGVyQnV0dG9uLnN0eWxlLnRvcCA9IGAke2Nvb3Jkcy55ICogTWF0aC5zaWduKGNvb3Jkcy54KSAtIDI1fXB4YDtcclxuICAgICAgdGhpcy5vbGRQb3NlTWF0dGVycG9ydFBvc2l0aW9uID0ge1xyXG4gICAgICAgIC4uLnRoaXMucG9zZU1hdHRlcnBvcnQucG9zaXRpb24sXHJcbiAgICAgIH07XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICB0aGlzLnBvaW50ZXJCdXR0b24uc3R5bGUuZGlzcGxheSA9ICdibG9jayc7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBSZWFsdGltZSBtYXR0ZXJ0YWcgZm9sbG93aW5nIHRoZSBjdXJzb3JcclxuICAgKiBAcGFyYW0gbWF0dGVydGFnIHN0cmluZ1xyXG4gICAqL1xyXG4gIGVuYWJsZV9mb2xsb3dpbmdfdGFnKG1hdHRlcnRhZzogc3RyaW5nKSB7XHJcbiAgICB0aGlzLnNkay5UYWcuZWRpdFBvc2l0aW9uKG1hdHRlcnRhZywge1xyXG4gICAgICBhbmNob3JQb3NpdGlvbjoge1xyXG4gICAgICAgIHg6IHRoaXMucG9zZU1hdHRlcnBvcnQucG9zaXRpb24ueCAqIDEsXHJcbiAgICAgICAgeTogdGhpcy5wb3NlTWF0dGVycG9ydC5wb3NpdGlvbi55ICogMSxcclxuICAgICAgICB6OiB0aGlzLnBvc2VNYXR0ZXJwb3J0LnBvc2l0aW9uLnogKiAxLFxyXG4gICAgICB9LFxyXG4gICAgICBzdGVtVmVjdG9yOiB7XHJcbiAgICAgICAgeDogdGhpcy5wb3NlTWF0dGVycG9ydC5ub3JtYWwueCAqIDAuMyxcclxuICAgICAgICB5OiB0aGlzLnBvc2VNYXR0ZXJwb3J0Lm5vcm1hbC55ICogMC4zLFxyXG4gICAgICAgIHo6IHRoaXMucG9zZU1hdHRlcnBvcnQubm9ybWFsLnogKiAwLjMsXHJcbiAgICAgIH0sXHJcbiAgICB9KTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIEdldCB0aGUgZGlzdGFuY2UgYmV0d3dlZW4gdHdvIDNEIHBvc2l0aW9uc1xyXG4gICAqIFVzZWQgaW4gb3JkZXIgdG8gc2VlIGhvdyBtdWNoIHRoZSBjdXJzb3IgaGFzIG1vdmVkIGZyb20gdGhlIHByZXZpb3VzIHBvc2l0aW9uXHJcbiAgICogQHBhcmFtIHBvczFcclxuICAgKiBAcGFyYW0gcG9zMlxyXG4gICAqL1xyXG4gIGdldERpc3RQb3NpdGlvbihwb3MxOiBhbnksIHBvczI6IGFueSkge1xyXG4gICAgY29uc3Qgc2l6ZSA9IHtcclxuICAgICAgdzogdGhpcy5jb250YWluZXIuY2xpZW50V2lkdGgsXHJcbiAgICAgIGg6IHRoaXMuY29udGFpbmVyLmNsaWVudEhlaWdodCxcclxuICAgIH07XHJcbiAgICBjb25zdCBjb29yZHMxID0gdGhpcy5zZGsuQ29udmVyc2lvbi53b3JsZFRvU2NyZWVuKFxyXG4gICAgICBwb3MxLFxyXG4gICAgICB0aGlzLnBvc2VDYW1lcmEsXHJcbiAgICAgIHNpemVcclxuICAgICk7XHJcbiAgICBjb25zdCBjb29yZHMyID0gdGhpcy5zZGsuQ29udmVyc2lvbi53b3JsZFRvU2NyZWVuKFxyXG4gICAgICBwb3MyLFxyXG4gICAgICB0aGlzLnBvc2VDYW1lcmEsXHJcbiAgICAgIHNpemVcclxuICAgICk7XHJcbiAgICByZXR1cm4gTWF0aC5zcXJ0KFxyXG4gICAgICAoY29vcmRzMS54IC0gY29vcmRzMi54KSAqKiAyICsgKGNvb3JkczEueSAtIGNvb3JkczIueSkgKiogMlxyXG4gICAgKTtcclxuICB9XHJcblxyXG4gIC8vXHJcbiAgLy8gLS0tLS0tLS0tLSBNYXR0ZXJ0YWcgcmVsYXRlZCAtLS0tLS0tLS0tXHJcbiAgLy9cclxuICAvKipcclxuICAgKiBDcmVhdGVzIHRoZSBNYXR0ZXJ0YWcgdGhhdCB3aWxsIGZvbGxvdyB0aGUgY3Vyc29yXHJcbiAgICogQHBhcmFtIG1hdHRlcnRhZ0RhdGEgTWF0dGVydGFnRGF0YVxyXG4gICAqL1xyXG4gIGFzeW5jIGFkZEN1cnNvck1hdHRlcnRhZyhtYXR0ZXJ0YWdEYXRhOiBNYXR0ZXJ0YWdEYXRhKSB7XHJcbiAgICBpZiAoIXRoaXMucG9zZU1hdHRlcnBvcnQpIHJldHVybjtcclxuICAgIHRoaXMubWF0dGVydGFnVG9Gb2xsb3cgPSBhd2FpdCB0aGlzLmFkZE1hdHRlcnRhZ1RvVmlld2VyKG1hdHRlcnRhZ0RhdGEpO1xyXG4gICAgY29uc29sZS5sb2coJ2ZvbGxvd2luZyB0aGUgdGFnJywgdGhpcy5tYXR0ZXJ0YWdUb0ZvbGxvdyk7XHJcbiAgICB0aGlzLnNkay5UYWcuZWRpdEljb24odGhpcy5tYXR0ZXJ0YWdUb0ZvbGxvdywgJ2ljb24tcG9zaXRpb24nKTtcclxuICAgIHRoaXMuc2RrLlRhZy5lZGl0T3BhY2l0eSh0aGlzLm1hdHRlcnRhZ1RvRm9sbG93LCAxKTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIEFkZHMgTWF0dGVydGFnIHRvIHZpZXdlciBmb3IgYW4gZXhpc3Rpbmcgb2JqZWN0IHdpdGggY29vcmRpbmF0ZXMgKGluIG1hdHRlcnRhZ0RhdGEucG9pKVxyXG4gICAqIChwb3NpdGlvbiwgaW5qZWN0ZWQgaHRtbCwgc2V0IGljb24pXHJcbiAgICogQHBhcmFtIG1hdHRlcnRhZ0RhdGFcclxuICAgKiByZXR1cm5zIG1hdHRlcnRhZ0lEXHJcbiAgICovXHJcbiAgYXN5bmMgYWRkTWF0dGVydGFnVG9WaWV3ZXIoXHJcbiAgICBtYXR0ZXJ0YWdEYXRhOiBNYXR0ZXJ0YWdEYXRhXHJcbiAgKTogUHJvbWlzZTxzdHJpbmcgfCBudWxsPiB7XHJcbiAgICBsZXQgc2lkTGlzdDtcclxuICAgIGlmICghdGhpcy5zZGspIHtcclxuICAgICAgcmV0dXJuIG51bGw7XHJcbiAgICB9XHJcbiAgICB0cnkge1xyXG4gICAgICBzaWRMaXN0ID0gYXdhaXQgdGhpcy5zZGsuVGFnLmFkZChtYXR0ZXJ0YWdEYXRhLmdldERhdGEoKSk7XHJcbiAgICB9IGNhdGNoIChlcnJvcikge1xyXG4gICAgICBjb25zb2xlLmxvZyhcclxuICAgICAgICAnVGFnIGRvZXMgbm90IGJlbG9uZyB0byB0aGUgdmlzaXQnLFxyXG4gICAgICAgIGVycm9yLFxyXG4gICAgICAgIG1hdHRlcnRhZ0RhdGEuZ2V0RGF0YSgpXHJcbiAgICAgICk7XHJcbiAgICB9XHJcbiAgICBpZiAoc2lkTGlzdCkge1xyXG4gICAgICBjb25zdCBtYXR0ZXJ0YWdJRCA9IHNpZExpc3RbMF07XHJcbiAgICAgIC8vIGNvbnNvbGUubG9nKFwiYWRkZWQgdGFnXCIsIG1hdHRlcnRhZ0RhdGEuZ2V0VHlwZSgpLCBtYXR0ZXJ0YWdJRCk7XHJcbiAgICAgIHRoaXMubWF0dGVydGFnSURzLnB1c2gobWF0dGVydGFnSUQpO1xyXG4gICAgICB0aGlzLmRpY3Rpb25uYXJ5VGFncy5zZXQobWF0dGVydGFnSUQsIG1hdHRlcnRhZ0RhdGEpO1xyXG4gICAgICByZXR1cm4gbWF0dGVydGFnSUQ7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gbnVsbDtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIEFjdGlvbnMgd2hlbiBwb3NpdGlvbiBvZiBtYXR0ZXJ0YWcgaXMgdmFsaWRhdGVkIGJ5IGxlZnQgY2xpY2tcclxuICAgKi9cclxuICBvblZhbGlkYXRlZE1hdHRlcnRhZygpIHtcclxuICAgIHRoaXMuc2V0SW50ZXJhY3Rpb25Nb2RlKFZpZXdlckludGVyYWN0aW9ucy5ERUZBVUxUKTtcclxuICAgIGNvbnN0IGxhc3RUYWcgPSB0aGlzLmdldExhc3RUYWcoKTtcclxuICAgIGlmIChsYXN0VGFnKSB7XHJcbiAgICAgIGNvbnN0IGNhbGxiYWNrTW9kZSA9IHRoaXMuZGljdGlvbm5hcnlUYWdzXHJcbiAgICAgICAgLmdldChsYXN0VGFnKVxyXG4gICAgICAgIC5nZXRDYWxsYmFja0FjdGlvbk1vZGUoKTtcclxuICAgICAgdGhpcy5jYWxsYmFja0FmdGVyTWF0dGVydGFnVmFsaWRhdGlvbihjYWxsYmFja01vZGUpO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogUmVnaXN0ZXJzIG5ldyBpY29uIChwYXRoIHRvIGltYWdlKSBhbmQgc2V0IGl0cyBmb3IgTWF0dGVydGFnXHJcbiAgICogQHBhcmFtIG1hdHRlcnRhZ0lEIHN0cmluZ1xyXG4gICAqIEBwYXJhbSBpY29uUGF0aCBzdHJpbmdcclxuICAgKi9cclxuICBhc3luYyBhZGROZXdJY29uQW5kU2V0Rm9yVGFnKG1hdHRlcnRhZ0lEOiBzdHJpbmcsIGljb25QYXRoOiBzdHJpbmcpIHtcclxuICAgIGF3YWl0IHRoaXMuc2RrLkFzc2V0LnJlZ2lzdGVyVGV4dHVyZShgaWNvbl8ke21hdHRlcnRhZ0lEfWAsIGljb25QYXRoKTtcclxuICAgIHRoaXMuc2RrLlRhZy5lZGl0SWNvbihtYXR0ZXJ0YWdJRCwgYGljb25fJHttYXR0ZXJ0YWdJRH1gKTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIENoYW5nZXMgaWNvbiBvZiBNYXR0ZXJ0YWcgKHRoZSBpY29uTmFtZSBzaG91bGQgYmUgcmVnaXN0ZXJlZCA9IG9uZSBvZiBkZWZhdWx0IG9uZXMpXHJcbiAgICogQHBhcmFtIG1hdHRlcnRhZ0lEIHN0cmluZ1xyXG4gICAqIEBwYXJhbSBpY29uTmFtZSBzdHJpbmdcclxuICAgKi9cclxuICBhc3luYyBzZXRSZWdpc3RyZWRJY29uRm9yVGFnKG1hdHRlcnRhZ0lEOiBzdHJpbmcsIGljb25OYW1lOiBzdHJpbmcpIHtcclxuICAgIHRyeSB7XHJcbiAgICAgIHRoaXMuc2RrLlRhZy5lZGl0SWNvbihtYXR0ZXJ0YWdJRCwgaWNvbk5hbWUpO1xyXG4gICAgfSBjYXRjaCAoZSkge1xyXG4gICAgICBjb25zb2xlLmxvZyhcclxuICAgICAgICAnY291bGQgbm90IGVkaXQgSWNvbiB3aXRoIG5hbWUgJyxcclxuICAgICAgICBpY29uTmFtZSxcclxuICAgICAgICAnLiBJcyBpdCByZWdpc3RlcmVkPydcclxuICAgICAgKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIFNldHMgZGVmYXVsdCBpY29uIGZvciBhIHRhZyAocmVnaXN0ZXJlZCBpbiBpbml0U2RrKSBPUiB1c2VzIHRhZ0ljb24gZnJvbSBQT0kgKGF2YWlsYWJsZSBmcm9tIE1hdHRlcnRhZ0RhdGEpXHJcbiAgICogQHBhcmFtIG1hdHRlcnRhZ0lEIHN0cmluZ1xyXG4gICAqIEBwYXJhbSBtYXR0ZXJ0YWdEYXRhIE1hdHRlcnRhZ0RhdGFcclxuICAgKiBAcmV0dXJuc1xyXG4gICAqL1xyXG4gIGFzeW5jIHNldFRhZ0ljb25BbmRPcGFjaXR5KFxyXG4gICAgbWF0dGVydGFnSUQ6IHN0cmluZyxcclxuICAgIG1hdHRlcnRhZ0RhdGE6IE1hdHRlcnRhZ0RhdGFcclxuICApIHtcclxuICAgIGlmICh0aGlzLlNQTW9kdWxlID09PSBTcE1vZHVsZS5IT1RFTCkge1xyXG4gICAgICBjb25zdCByb29tID0gbWF0dGVydGFnRGF0YS5nZXRPYmplY3QoKTtcclxuICAgICAgbGV0IGljb25OYW1lID0gYGljb25fcm9vbWA7XHJcbiAgICAgIGlmIChyb29tLmF2YWlsYWJsZSkge1xyXG4gICAgICAgIGljb25OYW1lID0gYCR7aWNvbk5hbWV9X2F2YWlsYWJsZWA7XHJcbiAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgaWNvbk5hbWUgPSBgJHtpY29uTmFtZX1fdW5hdmFpbGFibGVgO1xyXG4gICAgICB9XHJcbiAgICAgIHRoaXMuc2RrLlRhZy5lZGl0SWNvbihtYXR0ZXJ0YWdJRCwgaWNvbk5hbWUpO1xyXG4gICAgICByZXR1cm47XHJcbiAgICB9XHJcbiAgICBjb25zdCBzdHJpbmdUYWdUeXBlID0gcG9pVHlwZVRvU3RyaW5nKG1hdHRlcnRhZ0RhdGEuZ2V0VHlwZSgpKTtcclxuICAgIGxldCBvcGFjaXR5ID0gdGhpcy5jb25maWcubXlfY29uZmlnLkRFRkFVTFRfT1BBQ0lUWV9UQUc7XHJcbiAgICBsZXQgaWNvbk5hbWUgPSBgaWNvbi0ke3N0cmluZ1RhZ1R5cGV9YDtcclxuICAgIGNvbnN0IHBvaSA9IG1hdHRlcnRhZ0RhdGEuZ2V0UG9pKCk7XHJcbiAgICBpZiAocG9pICYmIHBvaS50YWdJY29uKSB7XHJcbiAgICAgIGNvbnN0IHRhZ0ljb24gPSBKU09OLnBhcnNlKHBvaS50YWdJY29uKTtcclxuICAgICAgaWYgKG1hdHRlcnRhZ0RhdGEuZ2V0VHlwZSgpID09PSBQb2lUeXBlLkRBVEEpIHtcclxuICAgICAgICBjb25zdCBmZWF0dXJlID0gbWF0dGVydGFnRGF0YS5nZXRPYmplY3QoKTtcclxuICAgICAgICBpZiAoZmVhdHVyZS50eXBlID09PSBGZWF0dXJlVHlwZS5JTkRJQ0FUT1JfVEVNUCkge1xyXG4gICAgICAgICAgdGFnSWNvbi5zcmMgPSB0aGlzLnRhZ1NlcnZpY2UuZ2V0SWNvblRhZ0ltYWdlRm9yRmVhdHVyZShmZWF0dXJlLCBwb2kpO1xyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG4gICAgICBpZiAodGFnSWNvbi5zcmMpIHtcclxuICAgICAgICBjb25zdCBwYXRoU2lnbmVkID0gYXdhaXQgdGhpcy50YWdTZXJ2aWNlLmdldFNpZ25lZFRhZ0ljb25Tb3VyY2UoXHJcbiAgICAgICAgICB0YWdJY29uLnNyY1xyXG4gICAgICAgICk7XHJcbiAgICAgICAgaWYgKHBhdGhTaWduZWQpIHtcclxuICAgICAgICAgIHRyeSB7XHJcbiAgICAgICAgICAgIGljb25OYW1lID0gYGljb24tJHtzdHJpbmdUYWdUeXBlfS0ke21hdHRlcnRhZ0lEfS0ke21hdHRlcnRhZ0RhdGEuY3VzdG9tSWNvbkluZGV4fWA7XHJcbiAgICAgICAgICAgIGF3YWl0IHRoaXMuc2RrLkFzc2V0LnJlZ2lzdGVyVGV4dHVyZShpY29uTmFtZSwgcGF0aFNpZ25lZCk7XHJcbiAgICAgICAgICAgIG1hdHRlcnRhZ0RhdGEuY3VzdG9tSWNvbkluZGV4ICs9IDE7XHJcbiAgICAgICAgICB9IGNhdGNoIHtcclxuICAgICAgICAgICAgY29uc29sZS5sb2coJ2Vycm9yIHJlZ2lzdGVySWNvbicpO1xyXG4gICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG4gICAgICBpZiAodGFnSWNvbi5vcGFjaXR5KSB7XHJcbiAgICAgICAgb3BhY2l0eSA9IHRhZ0ljb24ub3BhY2l0eTtcclxuICAgICAgfVxyXG4gICAgfVxyXG4gICAgdHJ5IHtcclxuICAgICAgdGhpcy5zZGsuVGFnLmVkaXRJY29uKG1hdHRlcnRhZ0lELCBpY29uTmFtZSk7XHJcbiAgICAgIHRoaXMuc2RrLlRhZy5lZGl0T3BhY2l0eShtYXR0ZXJ0YWdJRCwgb3BhY2l0eSk7XHJcbiAgICB9IGNhdGNoIChlcnJvcikge1xyXG4gICAgICBjb25zb2xlLmxvZygnRXJyb3IgZWRpdEljb24gb3Igb3BhY2l0eScsIGVycm9yKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIE1vdmVzIHZpZXdlciB0byBsYXN0IHRhZyBjcmVhdGVkXHJcbiAgICovXHJcbiAgZ29Ub0xhc3RUYWcoKSB7XHJcbiAgICBzZXRUaW1lb3V0KCgpID0+IHtcclxuICAgICAgY29uc3QgbGFzdFRhZyA9IHRoaXMuZ2V0TGFzdFRhZygpO1xyXG4gICAgICB0aGlzLmdvVG9UYWcobGFzdFRhZyk7XHJcbiAgICB9LCAyMDAwKTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIE1vdmVzIHZpZXdlciB0byBNYXR0ZXJ0YWcgd2l0aCBJRCBwcm92aWRlZFxyXG4gICAqIEBwYXJhbSBtYXR0ZXJ0YWdJRCBzdHJpbmdcclxuICAgKiBAcmV0dXJuc1xyXG4gICAqL1xyXG4gIGFzeW5jIGdvVG9UYWcobWF0dGVydGFnSUQ6IHN0cmluZykge1xyXG4gICAgaWYgKG1hdHRlcnRhZ0lEID09PSAnJykgcmV0dXJuO1xyXG4gICAgdHJ5IHtcclxuICAgICAgdGhpcy5vbkdvVG9UYWcubmV4dChtYXR0ZXJ0YWdJRCk7XHJcbiAgICAgIGF3YWl0IHRoaXMuc2RrLlN3ZWVwLmN1cnJlbnQud2FpdFVudGlsKFxyXG4gICAgICAgIChjdXJyZW50U3dlZXApID0+IGN1cnJlbnRTd2VlcCAhPT0gJydcclxuICAgICAgKTtcclxuICAgICAgYXdhaXQgdGhpcy5zZGsuTWF0dGVydGFnLm5hdmlnYXRlVG9UYWcoXHJcbiAgICAgICAgbWF0dGVydGFnSUQsXHJcbiAgICAgICAgdGhpcy5zZGsuTWF0dGVydGFnLlRyYW5zaXRpb24uRkxZXHJcbiAgICAgICk7XHJcbiAgICB9IGNhdGNoIChlcnJvcikge1xyXG4gICAgICBjb25zb2xlLmxvZygnY2Fubm90IG5hdmlnYXRlIHRvIHRhZycsIGVycm9yKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIFVwZGF0ZXMgY29udGVudCBvZiBNYXR0ZXJ0YWcgd2l0aCBtYXR0ZXJ0YWdJRCAoYmlsbGJvYXJkLCBpbmplY3RlZCBodG1sLCB0YWcgaWNvbilcclxuICAgKiBAcGFyYW0gbWF0dGVydGFnSUQgc3RyaW5nXHJcbiAgICogQHBhcmFtIG9iamVjdCBUaWNrZXQsIEVxdWlwbWVudCwgRmVhdHVyZSwgZXRjXHJcbiAgICogQHBhcmFtIHRhZ1R5cGUgUG9pVHlwZVxyXG4gICAqL1xyXG4gIGFzeW5jIHVwZGF0ZU1hdHRlclRhZ0NvbnRlbnRGb3JUYWdJRChcclxuICAgIG1hdHRlcnRhZ0lEOiBzdHJpbmcsXHJcbiAgICBvYmplY3Q6IERiT2JqZWN0VHlwZSA9IG51bGwsXHJcbiAgICB0YWdUeXBlOiBQb2lUeXBlID0gbnVsbFxyXG4gICkge1xyXG4gICAgdGhpcy5zZGsuVGFnLmVkaXRCaWxsYm9hcmQoXHJcbiAgICAgIG1hdHRlcnRhZ0lELFxyXG4gICAgICB0aGlzLmRpY3Rpb25uYXJ5VGFncy5nZXQobWF0dGVydGFnSUQpLmdldERhdGEoKVxyXG4gICAgKTtcclxuICAgIGlmIChvYmplY3QgJiYgdGFnVHlwZSkge1xyXG4gICAgICBhd2FpdCB0aGlzLmluamVjdEh0bWxJblRhZyh0YWdUeXBlLCBvYmplY3QsIG1hdHRlcnRhZ0lEKTtcclxuICAgIH1cclxuICAgIGF3YWl0IHRoaXMuc2V0VGFnSWNvbkFuZE9wYWNpdHkoXHJcbiAgICAgIG1hdHRlcnRhZ0lELFxyXG4gICAgICB0aGlzLmRpY3Rpb25uYXJ5VGFncy5nZXQobWF0dGVydGFnSUQpXHJcbiAgICApO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogVXBkYXRlcyBpbmplY3RlZCBodG1sIGZvciBNYXR0ZXJ0YWdcclxuICAgKiBAcGFyYW0gbWF0dGVydGFnSUQgc3RyaW5nXHJcbiAgICogQHBhcmFtIG9iamVjdCBUaWNrZXQsIEVxdWlwbWVudCwgRmVhdHVyZSwgZXRjXHJcbiAgICogQHBhcmFtIHRhZ1R5cGUgUG9pVHlwZVxyXG4gICAqL1xyXG4gIGFzeW5jIHVwZGF0ZUluamVjdGVkSHRtbEZvclRhZ0lEKFxyXG4gICAgbWF0dGVydGFnSUQ6IHN0cmluZyxcclxuICAgIG9iamVjdDogYW55LFxyXG4gICAgdGFnVHlwZTogUG9pVHlwZVxyXG4gICkge1xyXG4gICAgYXdhaXQgdGhpcy5pbmplY3RIdG1sSW5UYWcodGFnVHlwZSwgb2JqZWN0LCBtYXR0ZXJ0YWdJRCk7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBEZWxldGVzIE1hdHRlcnRhZyBmcm9tIFZpZXdlciBieSBpdHMgSURcclxuICAgKiBAcGFyYW0gbWF0dGVydGFnSUQgc3RyaW5nXHJcbiAgICovXHJcbiAgZGVsZXRlTWF0dGVydGFnRnJvbUlkKG1hdHRlcnRhZ0lEOiBzdHJpbmcpIHtcclxuICAgIHRoaXMuc2RrLlRhZy5yZW1vdmUobWF0dGVydGFnSUQpO1xyXG4gICAgdGhpcy5kaWN0aW9ubmFyeVRhZ3MuZGVsZXRlKG1hdHRlcnRhZ0lEKTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIERlbGV0ZXMgbGF0ZXN0IGNyZWF0ZWQgbWF0dGVydGFnXHJcbiAgICovXHJcbiAgZGVsZXRlTGFzdE1hdHRlcnRhZygpIHtcclxuICAgIGNvbnN0IG1hdHRlcnRhZ0lEID0gdGhpcy5tYXR0ZXJ0YWdJRHMucG9wKCk7XHJcbiAgICBpZiAobWF0dGVydGFnSUQpIHtcclxuICAgICAgdGhpcy5kZWxldGVNYXR0ZXJ0YWdGcm9tSWQobWF0dGVydGFnSUQpO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogTGVnYWN5OiB1c2VkIHRvIGJlIGNhbGxlZCBhY3Rpb25fYWRkX21hdHRlcnRhZ19mcm9tX1BPSVxyXG4gICAqIEFkZHMgYW5kIGNvbmZpZ3VyZXMgTWF0dGVydGFnIGZvciBhbiBvYmplY3QgKFRpY2tldCwgRXF1aXBtZW50LCBGZWF0dXJlLCBldGMpIHRoYXQgY29ycmVzcG9uZHMgdG8gUE9JIChjb29yZGluYXRlcywgdGFnSWNvbilcclxuICAgKiBAcGFyYW0gdGFnVHlwZSBQb2lUeXBlXHJcbiAgICogQHBhcmFtIG9iamVjdCBUaWNrZXQsIEVxdWlwbWVudCwgRmVhdHVyZS4uLlxyXG4gICAqIEBwYXJhbSBwb2kgUE9JXHJcbiAgICogQHJldHVybnNcclxuICAgKi9cclxuICBhc3luYyBjcmVhdGVNYXR0ZXJ0YWdGcm9tUE9JKFxyXG4gICAgdGFnVHlwZTogUG9pVHlwZSxcclxuICAgIG9iamVjdDogRGJPYmplY3RUeXBlLFxyXG4gICAgcG9pOiBQT0lcclxuICApOiBQcm9taXNlPGFueT4ge1xyXG4gICAgLy8gY2hlY2sgaWYgdGFnIGV4aXN0cyBhbHJlYWR5XHJcbiAgICBjb25zdCB7dGFnLCBzd2VlcH0gPSB0aGlzLmdldFRhZ0Zyb21FbGVtZW50SWQob2JqZWN0LmlkKTtcclxuICAgIGlmICh0YWcpIHtcclxuICAgICAgLy8gY29uc29sZS5sb2coXCJ0YWcgZXhpc3RzXCIsIG9iamVjdClcclxuICAgICAgcmV0dXJuO1xyXG4gICAgfVxyXG4gICAgY29uc3QgbWF0dGVydGFnRGF0YTogTWF0dGVydGFnRGF0YSA9IG5ldyBNYXR0ZXJ0YWdEYXRhKHRhZ1R5cGUpO1xyXG4gICAgbWF0dGVydGFnRGF0YS5zZXRPYmplY3Qob2JqZWN0LCB0YWdUeXBlKTtcclxuICAgIGlmIChwb2kuY29vcmRpbmF0ZSkge1xyXG4gICAgICBtYXR0ZXJ0YWdEYXRhLnNldFBvc2l0aW9uKEpTT04ucGFyc2UocG9pLmNvb3JkaW5hdGUpKTtcclxuICAgIH1cclxuICAgIGlmIChwb2kubWV0YWRhdGEpIHtcclxuICAgICAgY29uc3QgdGFnTWV0YWRhdGEgPSBKU09OLnBhcnNlKHBvaS5tZXRhZGF0YSk7XHJcbiAgICAgIGlmICh0YWdNZXRhZGF0YS5ub3JtYWwpIHtcclxuICAgICAgICBtYXR0ZXJ0YWdEYXRhLnNldE5vcm1hbCh0YWdNZXRhZGF0YS5ub3JtYWwpO1xyXG4gICAgICB9IGVsc2Uge1xyXG4gICAgICAgIG1hdHRlcnRhZ0RhdGEuc2V0Tm9ybWFsKHt4OiAwLCB5OiAtMC4xNSwgejogMH0pO1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgICBpZiAocG9pLm1hdHRlcnBvcnRTd2VlcElEKSB7XHJcbiAgICAgIG1hdHRlcnRhZ0RhdGEuc2V0U3dlZXBJRChwb2kubWF0dGVycG9ydFN3ZWVwSUQpO1xyXG4gICAgfVxyXG4gICAgbWF0dGVydGFnRGF0YS5zZXRQb2kocG9pKTtcclxuXHJcbiAgICBjb25zdCBjcmVhdGVkVGFnSUQgPSBhd2FpdCB0aGlzLmFkZE1hdHRlcnRhZ1RvVmlld2VyKG1hdHRlcnRhZ0RhdGEpO1xyXG4gICAgaWYgKGNyZWF0ZWRUYWdJRCAmJiB0aGlzLnNkaykge1xyXG4gICAgICBhd2FpdCB0aGlzLnNldFRhZ0ljb25BbmRPcGFjaXR5KGNyZWF0ZWRUYWdJRCwgbWF0dGVydGFnRGF0YSk7XHJcbiAgICAgIGF3YWl0IHRoaXMuaW5qZWN0SHRtbEluVGFnKHRhZ1R5cGUsIG9iamVjdCwgY3JlYXRlZFRhZ0lEKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIEluamVjdCBjdXN0b20gSFRNTCBhcyBNYXR0ZXJ0YWcgY29udGVudFxyXG4gICAqIEBwYXJhbSB0YWdUeXBlIFBvaVR5cGVcclxuICAgKiBAcGFyYW0gb2JqZWN0IFRpY2tldCwgRXF1aXBtZW50LCBGZWF0dXJlIGV0Y1xyXG4gICAqIEBwYXJhbSB0YWdJRCBzdHJpbmdcclxuICAgKi9cclxuICBhc3luYyBpbmplY3RIdG1sSW5UYWcodGFnVHlwZTogUG9pVHlwZSwgb2JqZWN0OiBEYk9iamVjdFR5cGUsIHRhZ0lEOiBzdHJpbmcpIHtcclxuICAgIGxldCBodG1sID0gYXdhaXQgdGhpcy50YWdTZXJ2aWNlLmdldEh0bWxUb0luamVjdCh0YWdUeXBlLCBvYmplY3QpO1xyXG4gICAgaWYgKGh0bWwgIT09ICcnICYmIHRoaXMuc2RrKSB7XHJcbiAgICAgIGNvbnN0IHNjcmlwdFRhZyA9IHRoaXMudGFnU2VydmljZS5nZXRTY3JpcHRGb3JUYWcob2JqZWN0LCB0YWdUeXBlKTtcclxuICAgICAgaHRtbCArPSBgJHtzY3JpcHRUYWd9YDtcclxuICAgICAgLy8gY3JlYXRlIGFuZCByZWdpc3RlciB0aGUgc2FuZGJveFxyXG4gICAgICBjb25zdCBbc2FuZGJveElkLCBtZXNzZW5nZXJdID0gYXdhaXQgdGhpcy5zZGsuVGFnLnJlZ2lzdGVyU2FuZGJveChodG1sKTtcclxuXHJcbiAgICAgIC8vIGRldGFjaCBwcmV2aW91cyBzYW5kYm94IGZyb20gYSB0YWdcclxuICAgICAgbGV0IGF0dGFjaG1lbnRJRCA9IHRoaXMudGFnc0F0dGFjaG1lbnRzW3RhZ0lEXTtcclxuICAgICAgaWYgKGF0dGFjaG1lbnRJRCkge1xyXG4gICAgICAgIHRoaXMuc2RrLlRhZy5kZXRhY2godGFnSUQsIGF0dGFjaG1lbnRJRCk7XHJcbiAgICAgIH1cclxuICAgICAgdGhpcy50YWdzQXR0YWNobWVudHNbdGFnSURdID0gc2FuZGJveElkO1xyXG5cclxuICAgICAgLy8gYXR0YWNoIHRoZSBzYW5kYm94IHRvIGEgdGFnXHJcbiAgICAgIHRoaXMuc2RrLlRhZy5hdHRhY2godGFnSUQsIHNhbmRib3hJZCk7XHJcbiAgICAgIC8vIHJlY2VpdmUgZGF0YSBmcm9tIHRoZSBzYW5kYm94XHJcbiAgICAgIC8vIHRhZ01lc3Nlbmdlck9uIGFsbG93cyB0byBnbyBoZXJlIG9ubHkgb25jZVxyXG4gICAgICBpZiAoIXRoaXMudGFnTWVzc2VuZ2VyT24pIHtcclxuICAgICAgICB0aGlzLnRhZ01lc3Nlbmdlck9uID0gdHJ1ZTtcclxuICAgICAgICBjb25zdCBpbWFnZUNsaWNrID0gKGZlYXR1cmVJRDogc3RyaW5nKSA9PiB7XHJcbiAgICAgICAgICAvLyBjb25zb2xlLmxvZyhcImltYWdlIGNsaWNrIGhhbmRsZXJcIiwgZmVhdHVyZUlEKTtcclxuICAgICAgICAgIHRoaXMudGFnU2VydmljZS5vbkFjdGlvbkltYWdlQ2xpY2soZmVhdHVyZUlEKTtcclxuICAgICAgICB9O1xyXG5cclxuICAgICAgICBjb25zdCBhdWRpb0NsaWNrID0gKGF1ZGlvQ29tbWVudElEOiBzdHJpbmcpID0+IHtcclxuICAgICAgICAgIC8vIGNvbnNvbGUubG9nKFwiYXVkaW8gY2xpY2sgaGFuZGxlclwiLCBhdWRpb0NvbW1lbnRJRCk7XHJcbiAgICAgICAgICB0aGlzLnRhZ1NlcnZpY2Uub25BY3Rpb25BdWRpb0NsaWNrKGF1ZGlvQ29tbWVudElEKTtcclxuICAgICAgICB9O1xyXG4gICAgICAgIGNvbnN0IHZpZGVvQ2xpY2sgPSAodXJsOiBzdHJpbmcpID0+IHtcclxuICAgICAgICAgIHRoaXMudGFnU2VydmljZS5vbkFjdGlvblZpZGVvQ2xpY2sodXJsKTtcclxuICAgICAgICB9O1xyXG4gICAgICAgIG1lc3Nlbmdlci5vbihcclxuICAgICAgICAgIFRhZ0FjdGlvbi5ERVRBSUxfQ0xJQ0ssXHJcbiAgICAgICAgICB0aGlzLnRhZ1NlcnZpY2Uub25BY3Rpb25EZXRhaWxDbGljay5iaW5kKHRoaXMudGFnU2VydmljZSlcclxuICAgICAgICApO1xyXG4gICAgICAgIG1lc3Nlbmdlci5vbihcclxuICAgICAgICAgIFRhZ0FjdGlvbi5USUNLRVRfQ0xJQ0ssXHJcbiAgICAgICAgICB0aGlzLnRhZ1NlcnZpY2Uub25BY3Rpb25EZXRhaWxDbGljay5iaW5kKHRoaXMudGFnU2VydmljZSlcclxuICAgICAgICApO1xyXG4gICAgICAgIG1lc3Nlbmdlci5vbihUYWdBY3Rpb24uQVVESU9fQ0xJQ0ssIGF1ZGlvQ2xpY2spO1xyXG4gICAgICAgIG1lc3Nlbmdlci5vbihUYWdBY3Rpb24uSU1BR0VfQ0xJQ0ssIGltYWdlQ2xpY2spO1xyXG4gICAgICAgIG1lc3Nlbmdlci5vbihUYWdBY3Rpb24uVklERU9fQ0xJQ0ssIHZpZGVvQ2xpY2spO1xyXG4gICAgICAgIG1lc3Nlbmdlci5vbihcclxuICAgICAgICAgIFRhZ0FjdGlvbi5ET0NfQ0xJQ0ssXHJcbiAgICAgICAgICB0aGlzLnRhZ1NlcnZpY2Uub25BY3Rpb25Eb2NDbGljay5iaW5kKHRoaXMudGFnU2VydmljZSlcclxuICAgICAgICApO1xyXG4gICAgICAgIG1lc3Nlbmdlci5vbihcclxuICAgICAgICAgIFRhZ0FjdGlvbi5ZT1VUVUJFX0NMSUNLLFxyXG4gICAgICAgICAgdGhpcy50YWdTZXJ2aWNlLm9uQWN0aW9uWW91dHViZUNsaWNrLmJpbmQodGhpcy50YWdTZXJ2aWNlKVxyXG4gICAgICAgICk7XHJcbiAgICAgIH1cclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIC8vIGlmIGh0bWwgaXMgZW1wdHkgKGNhc2Ugb2YgRU1CRUQgY29udGVudCksIHdlIGVkaXQgYmlsbGJvYXJkIGZvciBGZWF0dXJlIGFuZCBhdHRhY2ggbmV3IGNvbnRlbnRcclxuICAgICAgY29uc3Qge2NvbW1lbnQsIHRhZ0Rlc2NyaXB0aW9ufSA9XHJcbiAgICAgICAgdGhpcy50YWdTZXJ2aWNlLmdldEJpbGxib2FyZE1lZGlhVG9FbWJlZChvYmplY3QpO1xyXG4gICAgICBpZiAoY29tbWVudCkge1xyXG4gICAgICAgIC8vIHJlZ2lzdGVyIHRoZSBtZWRpYVxyXG4gICAgICAgIGNvbnN0IFthdHRhY2htZW50SURdID0gYXdhaXQgdGhpcy5zZGsuVGFnLnJlZ2lzdGVyQXR0YWNobWVudChcclxuICAgICAgICAgIGNvbW1lbnQuZXh0ZXJuYWxMaW5rXHJcbiAgICAgICAgKTtcclxuICAgICAgICAvLyBhdHRhY2hcclxuICAgICAgICB0aGlzLnNkay5UYWcuYXR0YWNoKHRhZ0lELCBhdHRhY2htZW50SUQpO1xyXG4gICAgICAgIHRoaXMuc2RrLlRhZy5lZGl0QmlsbGJvYXJkKHRhZ0lELCB7XHJcbiAgICAgICAgICBsYWJlbDogb2JqZWN0LnRpdGxlLFxyXG4gICAgICAgICAgZGVzY3JpcHRpb246IHRhZ0Rlc2NyaXB0aW9uLFxyXG4gICAgICAgIH0pO1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBhc3luYyBhY3Rpb25fZGVsZXRlX2FsbF9tYXR0ZXJ0YWdzKCkge1xyXG4gICAgYXdhaXQgdGhpcy5zZGsuVGFnLnJlbW92ZSguLi50aGlzLm1hdHRlcnRhZ0lEcyk7XHJcbiAgICB0aGlzLm1hdHRlcnRhZ0lEcyA9IFtdO1xyXG4gICAgdGhpcy5kaWN0aW9ubmFyeVRhZ3MuY2xlYXIoKTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIERlbGV0ZXMgTWF0dGVydGFnIGZyb20gdmlzaXQgYXNzb2NpYXRlZCB3aXRoIG9iamVjdCBJRCAodGlja2V0SUQsIGV0YylcclxuICAgKiBAcGFyYW0gZWxlbWVudElEIHN0cmluZ1xyXG4gICAqL1xyXG4gIGFzeW5jIGRlbGV0ZU1hdHRlcnRhZ0Zvck9iamVjdChlbGVtZW50SUQ6IHN0cmluZykge1xyXG4gICAgY29uc3QgbWF0dGVyVGFnSUQgPSB0aGlzLmdldFRhZ0Zyb21FbGVtZW50SWQoZWxlbWVudElEKS50YWc7XHJcbiAgICBpZiAobWF0dGVyVGFnSUQpIHtcclxuICAgICAgdHJ5IHtcclxuICAgICAgICBhd2FpdCB0aGlzLnNkay5UYWcucmVtb3ZlKG1hdHRlclRhZ0lEKTtcclxuICAgICAgICB0aGlzLmRpY3Rpb25uYXJ5VGFncy5kZWxldGUobWF0dGVyVGFnSUQpO1xyXG4gICAgICAgIGNvbnN0IGluZGV4ID0gdGhpcy5tYXR0ZXJ0YWdJRHMuaW5kZXhPZihtYXR0ZXJUYWdJRCk7XHJcbiAgICAgICAgdGhpcy5tYXR0ZXJ0YWdJRHMuc3BsaWNlKGluZGV4LCAxKTtcclxuICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcclxuICAgICAgICBjb25zb2xlLmxvZygnQ2Fubm90IGRlbGV0ZSB0YWcnLCBtYXR0ZXJUYWdJRCwgZXJyb3IpO1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiB1dWlkIGZyb20gdGhyZWVqc1xyXG4gICAqIEBwYXJhbSB1dWlkXHJcbiAgICovXHJcbiAgYXN5bmMgZGVsZXRlT2JqZWN0M0QodXVpZDogc3RyaW5nKTogUHJvbWlzZTx2b2lkPiB7XHJcbiAgICB0aGlzLmRpY3Rpb25uYXJ5T2JqZWN0czNELmdldCh1dWlkKS5vYmozRC52aXNpYmxlID0gZmFsc2U7XHJcbiAgfVxyXG5cclxuICBnZXRPYmplY3QzRE1vZGVsTm9kZUZyb21EaWN0aW9ubmFyeSh1dWlkOiBzdHJpbmcpOiBhbnkge1xyXG4gICAgICBsZXQgb2JqID0gdGhpcy5kaWN0aW9ubmFyeU9iamVjdHMzRC5nZXQodXVpZCk7XHJcbiAgICAgIGlmKCFvYmope1xyXG4gICAgICAgIGNvbnNvbGUubG9nKFwid2VpcmQgdGhpbmcgYWdhaW5cIik7XHJcbiAgICAgICAgcmV0dXJuIG51bGw7XHJcbiAgICAgIH1cclxuICAgICAgLy9taWdodCBicmVhayB0aGluZ3Mgb3IgZml4IGV2ZXJ5dGhpbmcgLi4/XHJcbiAgICAgIGlmKG9iai5vYmozRC51dWlkICE9IHV1aWQpe1xyXG4gICAgICAgIGNvbnNvbGUubG9nKFwid2UgaGF2ZSBUSEUgcHJvYmxlbVwiKTtcclxuICAgICAgICBvYmoub2JqM0QudXVpZCA9IHV1aWQ7IC8vbm90IGVudWdoIHRvIGZpeCB0aGUgcGJcclxuICAgICAgfVxyXG5cclxuICAgICAgcmV0dXJuIG9iajtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIENyZWF0ZXMgIE1hdHRlcnRhZ0RhdGEgYW5kIHN0YXJ0IHJlcG9zaXRpb25pbmcgKGNyZWF0ZXMgdGVtcG9yYXJ5IG1hdHRlcnRhZyB0aGF0IGZvbGxvd3MgdGhlIGN1cnNvcilcclxuICAgKiBAcGFyYW0gcG9pVHlwZSBQb2lUeXBlXHJcbiAgICogQHBhcmFtIGVsZW1lbnQgVGlja2V0LCBFcXVpcG1lbnQsIEZlYXR1cmUsIGV0Y1xyXG4gICAqL1xyXG4gIGFzeW5jIGFkZE1hdHRlcnRhZ1doZW5SZXBvc2l0aW9uaW5nKHBvaVR5cGU6IFBvaVR5cGUsIGVsZW1lbnQ6IERiT2JqZWN0VHlwZSkge1xyXG4gICAgY29uc3QgbWF0dGVydGFnRGF0YSA9IG5ldyBNYXR0ZXJ0YWdEYXRhKHBvaVR5cGUpO1xyXG4gICAgLy8gc2V0IHRoZSBjb29yZGluYXRlcyBvZiB0aGUgZXhpc3RpbmcgdGFnXHJcbiAgICBjb25zdCBbcG9pXSA9IGVsZW1lbnQucG9pcy5pdGVtcztcclxuICAgIGlmIChwb2kgJiYgcG9pLmNvb3JkaW5hdGUpIHtcclxuICAgICAgbWF0dGVydGFnRGF0YS5zZXRQb3NpdGlvbihKU09OLnBhcnNlKHBvaS5jb29yZGluYXRlKSk7XHJcbiAgICAgIG1hdHRlcnRhZ0RhdGEuc2V0UG9pKHBvaSk7IC8vIHRvIGtlZXAgY3VzdG9tIHRhZ0ljb24gYW5kIG9wYWNpdHlcclxuICAgIH1cclxuICAgIG1hdHRlcnRhZ0RhdGEuc2V0U3dlZXBJRCh0aGlzLnBvc2VDYW1lcmEuc3dlZXApO1xyXG4gICAgbWF0dGVydGFnRGF0YS5zZXRSb3RhdGlvbih0aGlzLnBvc2VDYW1lcmEucm90YXRpb24pO1xyXG4gICAgbWF0dGVydGFnRGF0YS5zZXRPYmplY3QoZWxlbWVudCwgcG9pVHlwZSk7XHJcbiAgICB0aGlzLm1hdHRlcnRhZ1RvRm9sbG93ID0gYXdhaXQgdGhpcy5hZGRNYXR0ZXJ0YWdUb1ZpZXdlcihtYXR0ZXJ0YWdEYXRhKTtcclxuICAgIHRoaXMuc2V0SW50ZXJhY3Rpb25Nb2RlKFZpZXdlckludGVyYWN0aW9ucy5QT1NJVElPTklORyk7XHJcbiAgICBhd2FpdCB0aGlzLmFkZEN1cnNvck1hdHRlcnRhZyhtYXR0ZXJ0YWdEYXRhKTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIENyZWF0ZXMgTWF0dGVydGFnRGF0YSBhbmQgbWF0dGVydGFnIHRoYXQgZm9sbG93cyB0aGUgY3Vyc29yIHdoZW4gY2hvb3NpbmcgcG9zaXRpb24gZm9yIGEgbmV3IG9iamVjdFxyXG4gICAqIEBwYXJhbSBwb2lUeXBlXHJcbiAgICovXHJcbiAgYXN5bmMgYWRkTWF0dGVydGFnV2hlbkFkZGluZyhwb2lUeXBlOiBQb2lUeXBlKSB7XHJcbiAgICBjb25zdCBtYXR0ZXJ0YWdEYXRhID0gbmV3IE1hdHRlcnRhZ0RhdGEocG9pVHlwZSk7XHJcbiAgICBtYXR0ZXJ0YWdEYXRhLnNldFN3ZWVwSUQodGhpcy5wb3NlQ2FtZXJhLnN3ZWVwKTtcclxuICAgIG1hdHRlcnRhZ0RhdGEuc2V0Um90YXRpb24odGhpcy5wb3NlQ2FtZXJhLnJvdGF0aW9uKTtcclxuICAgIHRoaXMuc2V0SW50ZXJhY3Rpb25Nb2RlKFZpZXdlckludGVyYWN0aW9ucy5BRERJTkcpO1xyXG4gICAgYXdhaXQgdGhpcy5hZGRDdXJzb3JNYXR0ZXJ0YWcobWF0dGVydGFnRGF0YSk7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBDYW5jZWxzIGZvbGxvd2luZyBvZiBjdXJzb3IgKG1lYW5pbmcgZGVsZXRpbmcgbGFzdCBNYXR0ZXJ0YWcpXHJcbiAgICovXHJcbiAgY2FuY2VsRm9sbG93aW5nQ3Vyc29yKCkge1xyXG4gICAgdGhpcy5kZWxldGVMYXN0TWF0dGVydGFnKCk7XHJcbiAgICB0aGlzLnNldEludGVyYWN0aW9uTW9kZShWaWV3ZXJJbnRlcmFjdGlvbnMuREVGQVVMVCk7XHJcbiAgfVxyXG5cclxuICBzZXRMYXN0T2JqZWN0M0QobGFzdE9iamVjdDNEOiBUaHJlZUpTT2JqZWN0M0QpIHtcclxuICAgIHRoaXMubGFzdE9iamVjdDNEID0gbGFzdE9iamVjdDNEO1xyXG4gIH1cclxuXHJcbiAgZ2V0TGFzdE9iamVjdDNEKCk6IFRocmVlSlNPYmplY3QzRCB7XHJcbiAgICByZXR1cm4gdGhpcy5sYXN0T2JqZWN0M0Q7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBQZXJmb3JtcyBjYWxsYmFjayBhZnRlciBtYXR0ZXJ0YWcgcG9zaXRpb24gd2FzIHZhbGlkYXRlZCAoY3JlYXRpb24gb2Ygb2JqZWN0IG9yIHJlcG9zaXRpb25pbmcpXHJcbiAgICogQHBhcmFtIG1vZGUgTWF0dGVydGFnQWN0aW9uTW9kZVxyXG4gICAqL1xyXG4gIGNhbGxiYWNrQWZ0ZXJNYXR0ZXJ0YWdWYWxpZGF0aW9uKG1vZGU6IE1hdHRlcnRhZ0FjdGlvbk1vZGUpIHtcclxuICAgIHRoaXMudmlzaWJpbGl0eVNlcnZpY2UuZGV0YWlsU2hvd2luZy5uZXh0KHRydWUpO1xyXG4gICAgY29uc3QgbGFzdFRhZyA9IHRoaXMuZ2V0TGFzdFRhZygpO1xyXG4gICAgc3dpdGNoIChtb2RlKSB7XHJcbiAgICAgIGNhc2UgTWF0dGVydGFnQWN0aW9uTW9kZS5BRERfRVFVSVBNRU5UOlxyXG4gICAgICAgIHRoaXMuZ29Ub0xhc3RUYWcoKTtcclxuICAgICAgICB0aGlzLnJvdXRlci5uYXZpZ2F0ZShbYHZpc2l0LyR7dGhpcy5jdXJyZW50U3BhY2VJRH0vYWRkX2VxdWlwYF0pO1xyXG4gICAgICAgIGJyZWFrO1xyXG4gICAgICBjYXNlIE1hdHRlcnRhZ0FjdGlvbk1vZGUuQUREX1RJQ0tFVDpcclxuICAgICAgICB0aGlzLmdvVG9MYXN0VGFnKCk7XHJcbiAgICAgICAgdGhpcy5yb3V0ZXIubmF2aWdhdGUoW2B2aXNpdC8ke3RoaXMuY3VycmVudFNwYWNlSUR9L2FkZF90aWNrZXRgXSk7XHJcbiAgICAgICAgYnJlYWs7XHJcbiAgICAgIGNhc2UgTWF0dGVydGFnQWN0aW9uTW9kZS5BRERfT0JKRUNUM0Q6XHJcbiAgICAgICAgdGhpcy5nb1RvTGFzdFRhZygpO1xyXG4gICAgICAgIHRoaXMucm91dGVyLm5hdmlnYXRlKFtgdmlzaXQvJHt0aGlzLmN1cnJlbnRTcGFjZUlEfS9hZGRfb2JqZWN0M2RgXSk7XHJcbiAgICAgICAgYnJlYWs7XHJcbiAgICAgIGNhc2UgTWF0dGVydGFnQWN0aW9uTW9kZS5BRERfREFUQTpcclxuICAgICAgICB0aGlzLmdvVG9MYXN0VGFnKCk7XHJcbiAgICAgICAgbGV0IHVybDogc3RyaW5nO1xyXG4gICAgICAgIGlmICh0aGlzLnJvdXRlci51cmwuaW5jbHVkZXMoJz8nKSkge1xyXG4gICAgICAgICAgdXJsID0gdGhpcy5yb3V0ZXIudXJsLnN1YnN0cmluZygwLCB0aGlzLnJvdXRlci51cmwuaW5kZXhPZignPycpKTtcclxuICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgdXJsID0gdGhpcy5yb3V0ZXIudXJsO1xyXG4gICAgICAgIH1cclxuICAgICAgICB0aGlzLnJvdXRlci5uYXZpZ2F0ZShbYCR7dXJsfS9hZGRfZmVhdHVyZWBdKTtcclxuICAgICAgICBicmVhaztcclxuICAgICAgY2FzZSBNYXR0ZXJ0YWdBY3Rpb25Nb2RlLkFERF9ERVNLOlxyXG4gICAgICAgIHRoaXMuZ29Ub0xhc3RUYWcoKTtcclxuICAgICAgICB0aGlzLnJvdXRlci5uYXZpZ2F0ZShbYHZpc2l0LyR7dGhpcy5jdXJyZW50U3BhY2VJRH0vYWRkX2ZlYXR1cmVgXSwge1xyXG4gICAgICAgICAgcXVlcnlQYXJhbXM6IHtpc0Rlc2s6IHRydWV9LFxyXG4gICAgICAgIH0pO1xyXG4gICAgICAgIGJyZWFrO1xyXG4gICAgICBjYXNlIE1hdHRlcnRhZ0FjdGlvbk1vZGUuQUREX1JPT006XHJcbiAgICAgICAgdGhpcy5nb1RvTGFzdFRhZygpO1xyXG4gICAgICAgIHRoaXMucm91dGVyLm5hdmlnYXRlKFtgdmlzaXQvJHt0aGlzLmN1cnJlbnRTcGFjZUlEfS9hZGRfcm9vbWBdKTtcclxuICAgICAgICBicmVhaztcclxuICAgICAgY2FzZSBNYXR0ZXJ0YWdBY3Rpb25Nb2RlLlBPU0lUSU9OX09CSkVDVDNEOlxyXG4gICAgICAgIGlmIChsYXN0VGFnKSB7XHJcbiAgICAgICAgICAvLyBETyBOb3RoaW5nIChyb3V0aW5nKSwganVzdFxyXG4gICAgICAgICAgdGhpcy5yb3V0ZXIubmF2aWdhdGUoXHJcbiAgICAgICAgICAgIFtgdmlzaXQvJHt0aGlzLmN1cnJlbnRTcGFjZUlEfS9vYmplY3QzZC8ke3RoaXMubGFzdE9iamVjdDNELmlkfWBdLFxyXG4gICAgICAgICAgICB7cXVlcnlQYXJhbXM6IHtwb3NpdGlvbmluZzogdHJ1ZX19XHJcbiAgICAgICAgICApO1xyXG4gICAgICAgIH1cclxuICAgICAgICBicmVhaztcclxuICAgICAgY2FzZSBNYXR0ZXJ0YWdBY3Rpb25Nb2RlLlBPU0lUSU9OX1RJQ0tFVDpcclxuICAgICAgICBpZiAobGFzdFRhZykge1xyXG4gICAgICAgICAgdGhpcy5yb3V0ZXIubmF2aWdhdGUoXHJcbiAgICAgICAgICAgIFtcclxuICAgICAgICAgICAgICBgdmlzaXQvJHt0aGlzLmN1cnJlbnRTcGFjZUlEfS9kZXRhaWwvJHtcclxuICAgICAgICAgICAgICAgIHRoaXMuZGljdGlvbm5hcnlUYWdzLmdldChsYXN0VGFnKS5lbGVtZW50SURcclxuICAgICAgICAgICAgICB9YCxcclxuICAgICAgICAgICAgXSxcclxuICAgICAgICAgICAge3F1ZXJ5UGFyYW1zOiB7cG9zaXRpb25pbmc6IHRydWV9fVxyXG4gICAgICAgICAgKTtcclxuICAgICAgICB9XHJcbiAgICAgICAgYnJlYWs7XHJcbiAgICAgIGNhc2UgTWF0dGVydGFnQWN0aW9uTW9kZS5QT1NJVElPTl9FUVVJUE1FTlQ6XHJcbiAgICAgICAgaWYgKGxhc3RUYWcpIHtcclxuICAgICAgICAgIHRoaXMucm91dGVyLm5hdmlnYXRlKFxyXG4gICAgICAgICAgICBbXHJcbiAgICAgICAgICAgICAgYHZpc2l0LyR7dGhpcy5jdXJyZW50U3BhY2VJRH0vZXF1aXAvJHtcclxuICAgICAgICAgICAgICAgIHRoaXMuZGljdGlvbm5hcnlUYWdzLmdldChsYXN0VGFnKS5lbGVtZW50SURcclxuICAgICAgICAgICAgICB9YCxcclxuICAgICAgICAgICAgXSxcclxuICAgICAgICAgICAge3F1ZXJ5UGFyYW1zOiB7cG9zaXRpb25pbmc6IHRydWV9fVxyXG4gICAgICAgICAgKTtcclxuICAgICAgICB9XHJcbiAgICAgICAgYnJlYWs7XHJcbiAgICAgIGNhc2UgTWF0dGVydGFnQWN0aW9uTW9kZS5QT1NJVElPTl9EQVRBOlxyXG4gICAgICAgIGlmIChsYXN0VGFnKSB7XHJcbiAgICAgICAgICB0aGlzLnJvdXRlci5uYXZpZ2F0ZShbXSwge1xyXG4gICAgICAgICAgICByZWxhdGl2ZVRvOiB0aGlzLmFjdGl2ZVJvdXRlLFxyXG4gICAgICAgICAgICBxdWVyeVBhcmFtczoge3Bvc2l0aW9uaW5nOiB0cnVlfSwgcXVlcnlQYXJhbXNIYW5kbGluZyA6IFwibWVyZ2VcIlxyXG4gICAgICAgICAgfSk7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGJyZWFrO1xyXG4gICAgICBjYXNlIE1hdHRlcnRhZ0FjdGlvbk1vZGUuUE9TSVRJT05fUk9PTTpcclxuICAgICAgICBpZiAobGFzdFRhZykge1xyXG4gICAgICAgICAgdGhpcy5yb3V0ZXIubmF2aWdhdGUoW10sIHtcclxuICAgICAgICAgICAgcmVsYXRpdmVUbzogdGhpcy5hY3RpdmVSb3V0ZSxcclxuICAgICAgICAgICAgcXVlcnlQYXJhbXM6IHtwb3NpdGlvbmluZzogdHJ1ZX0sIHF1ZXJ5UGFyYW1zSGFuZGxpbmcgOiBcIm1lcmdlXCJcclxuICAgICAgICAgIH0pO1xyXG4gICAgICAgIH1cclxuICAgICAgICBicmVhaztcclxuICAgIH1cclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIEZ1bGx5IHVwZGF0ZXMgZXhpc3RpbmcgTWF0dGVydGFnIGNvbnRlbnQgd2l0aCBkYXRhIG9mIG9iamVjdCAoVGlja2V0LCBFcXVpcG1lbnQsIERlc2spXHJcbiAgICogQHBhcmFtIG1hdHRlcnRhZ0lEIHN0cmluZ1xyXG4gICAqIEBwYXJhbSBvYmplY3QgVGlja2V0LCBFcXVpcG1lbnQsIEZlYXR1cmUsIERlc2tcclxuICAgKiBAcGFyYW0gcG9pVHlwZSBQb2lUeXBlXHJcbiAgICogQHBhcmFtIHBvaSBQT0lcclxuICAgKi9cclxuICBhc3luYyBzZXRPYmplY3RBbmRQb2lJblRhZyhcclxuICAgIG1hdHRlcnRhZ0lEOiBzdHJpbmcsXHJcbiAgICBvYmplY3Q6IERiT2JqZWN0VHlwZSxcclxuICAgIHBvaVR5cGU6IFBvaVR5cGUsXHJcbiAgICBwb2k6IFBPSSB8IG51bGwgPSBudWxsXHJcbiAgKTogUHJvbWlzZTx2b2lkPiB7XHJcbiAgICB0aGlzLmRpY3Rpb25uYXJ5VGFncy5nZXQobWF0dGVydGFnSUQpLnNldE9iamVjdChvYmplY3QsIHBvaVR5cGUpO1xyXG4gICAgaWYgKHBvaSkge1xyXG4gICAgICB0aGlzLmRpY3Rpb25uYXJ5VGFncy5nZXQobWF0dGVydGFnSUQpLnNldFBvaShwb2kpO1xyXG4gICAgfVxyXG4gICAgdGhpcy5kaWN0aW9ubmFyeVRhZ3MuZ2V0KG1hdHRlcnRhZ0lEKS5lbGVtZW50SUQgPSBvYmplY3QuaWQ7XHJcbiAgICB0cnkge1xyXG4gICAgICBhd2FpdCB0aGlzLnVwZGF0ZU1hdHRlclRhZ0NvbnRlbnRGb3JUYWdJRChtYXR0ZXJ0YWdJRCwgb2JqZWN0LCBwb2lUeXBlKTtcclxuICAgICAgLy8gVE9ETzogZml4IHRoaXNcclxuICAgICAgYXdhaXQgdGhpcy51cGRhdGVNYXR0ZXJUYWdQb3NJblNka1ZpZXdlcihcclxuICAgICAgICBtYXR0ZXJ0YWdJRCxcclxuICAgICAgICBvYmplY3QsXHJcbiAgICAgICAgcG9pVHlwZSxcclxuICAgICAgICBwb2lcclxuICAgICAgKTtcclxuICAgIH0gY2F0Y2ggKGUpIHtcclxuICAgICAgY29uc29sZS5sb2coYGVycm9yIGluIHNldE9iamVjdEFuZFBvaUluVGFnOiAke2V9YCk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBhc3luYyB1cGRhdGVNYXR0ZXJUYWdQb3NJblNka1ZpZXdlcihcclxuICAgIG1hdHRlcnRhZ0lEOiBzdHJpbmcsXHJcbiAgICBvYmplY3Q6IERiT2JqZWN0VHlwZSxcclxuICAgIHBvaVR5cGU6IFBvaVR5cGUsXHJcbiAgICBwb2k6IFBPSSB8IG51bGwgPSBudWxsXHJcbiAgKTogUHJvbWlzZTx2b2lkPiB7XHJcbiAgICBjb25zdCBJbmRleFRvVXBkYXRlID0gb2JqZWN0LnBvaXMuaXRlbXMuZmluZEluZGV4KCh1KSA9PiB1LmlkID09PSBwb2kuaWQpO1xyXG4gICAgb2JqZWN0LnBvaXMuaXRlbXNbSW5kZXhUb1VwZGF0ZV0gPSBwb2k7XHJcbiAgICBjb25zdCB7eCwgeSwgen0gPSBKU09OLnBhcnNlKHBvaS5jb29yZGluYXRlKTtcclxuICAgIGNvbnN0IG5ld1Bvc2l0aW9uID0ge1xyXG4gICAgICBhbmNob3JQb3NpdGlvbjoge1xyXG4gICAgICAgIHg6IHgsXHJcbiAgICAgICAgeTogeSxcclxuICAgICAgICB6OiB6LFxyXG4gICAgICB9LFxyXG4gICAgICBzdGVtVmVjdG9yOiB7XHJcbiAgICAgICAgLy8gbWFrZSB0aGUgVGFnIHN0aWNrIHN0cmFpZ2h0IHVwIGFuZCBtYWtlIGl0IDAuMzAgbWV0ZXJzICh+MSBmb290KSB0YWxsXHJcbiAgICAgICAgeDogMCxcclxuICAgICAgICB5OiAwLjMsXHJcbiAgICAgICAgejogMCxcclxuICAgICAgfSxcclxuICAgIH07XHJcbiAgICB0aGlzLnNkay5NYXR0ZXJ0YWcuZWRpdFBvc2l0aW9uKG1hdHRlcnRhZ0lELCBuZXdQb3NpdGlvbik7XHJcbiAgICB0aGlzLnNkay5UYWcuZWRpdFBvc2l0aW9uKG1hdHRlcnRhZ0lELCBuZXdQb3NpdGlvbik7XHJcbiAgICB0aGlzLmRpY3Rpb25uYXJ5VGFnc1xyXG4gICAgICAuZ2V0KG1hdHRlcnRhZ0lEKVxyXG4gICAgICAuc2V0UG9zaXRpb24obmV3UG9zaXRpb24uYW5jaG9yUG9zaXRpb24pO1xyXG5cclxuICAgIGZvciAobGV0IHRhZ0lkIG9mIHRoaXMubWF0dGVydGFnSURzKSB7XHJcbiAgICAgIGNvbnN0IGN1cnJlbnRUYWcgPSB0aGlzLmRpY3Rpb25uYXJ5VGFncy5nZXQodGFnSWQpO1xyXG4gICAgICBpZiAoIWN1cnJlbnRUYWcpIHtcclxuICAgICAgICBjb250aW51ZTtcclxuICAgICAgfVxyXG4gICAgICBpZiAoY3VycmVudFRhZy5lbGVtZW50SUQgPT09IG9iamVjdC5pZCAmJiB0YWdJZCAhPT0gbWF0dGVydGFnSUQpIHtcclxuICAgICAgICB0aGlzLmRpY3Rpb25uYXJ5VGFncy5kZWxldGUodGFnSWQpO1xyXG4gICAgICAgIHRoaXMuc2RrLlRhZy5yZW1vdmUodGFnSWQpO1xyXG4gICAgICAgIHRoaXMuc2RrLk1hdHRlcnRhZy5yZW1vdmUodGFnSWQpO1xyXG4gICAgICAgIGJyZWFrO1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBHZXRzIG1hdHRlclRhZ0lEIGFuZCBpdHMgc3dlZXAgZm9yIGFuIG9iamVjdCBJRCAodGlja2V0IElELCBldGMpXHJcbiAgICogQHBhcmFtIGVsZW1lbnRJRCBzdHJpbmdcclxuICAgKiBAcmV0dXJucyB7dGFnOiBzdHJpbmcgfCBudWxsLCBzd2VlcDogc3RyaW5nIHwgbnVsbH1cclxuICAgKi9cclxuICBwdWJsaWMgZ2V0VGFnRnJvbUVsZW1lbnRJZChlbGVtZW50SUQ6IHN0cmluZyk6IHtcclxuICAgIHRhZzogc3RyaW5nIHwgbnVsbDtcclxuICAgIHN3ZWVwOiBzdHJpbmcgfCBudWxsO1xyXG4gIH0ge1xyXG4gICAgbGV0IHRhZ0lEID0gbnVsbDtcclxuICAgIGxldCBzd2VlcElEID0gbnVsbDtcclxuICAgIGZvciAobGV0IFttYXR0ZXJ0YWdJRCwgbWF0dGVydGFnRGF0YV0gb2YgdGhpcy5kaWN0aW9ubmFyeVRhZ3MpIHtcclxuICAgICAgaWYgKG1hdHRlcnRhZ0RhdGEuZWxlbWVudElEID09PSBlbGVtZW50SUQpIHtcclxuICAgICAgICB0YWdJRCA9IG1hdHRlcnRhZ0lEO1xyXG4gICAgICAgIGNvbnN0IHN3ZWVwID0gbWF0dGVydGFnRGF0YS5nZXRTd2VlcElEKCk7XHJcbiAgICAgICAgaWYgKHN3ZWVwICYmIHRoaXMuc3dlZXBzICYmIHRoaXMuc3dlZXBzLmluY2x1ZGVzKHN3ZWVwKSkge1xyXG4gICAgICAgICAgc3dlZXBJRCA9IHN3ZWVwO1xyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG4gICAgfVxyXG4gICAgcmV0dXJuIHt0YWc6IHRhZ0lELCBzd2VlcDogc3dlZXBJRH07XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBHZXRzIGxhdGVzdCB0YWcgY3JlYXRlZCBpbiB0aGUgdmlzaXQgKHdoZW4gZm9sbG93aW5nIHRoZSBjdXJzb3IgdG8gcG9zaXRpb24pXHJcbiAgICogQHJldHVybnMgc3RyaW5nIG1hdHRlcnRhZ0lEXHJcbiAgICovXHJcbiAgZ2V0TGFzdFRhZygpOiBzdHJpbmcgfCBudWxsIHtcclxuICAgIGlmICh0aGlzLm1hdHRlcnRhZ1RvRm9sbG93KSB7XHJcbiAgICAgIHJldHVybiB0aGlzLm1hdHRlcnRhZ1RvRm9sbG93O1xyXG4gICAgfSBlbHNlIHtcclxuICAgICAgcmV0dXJuIHRoaXMubWF0dGVydGFnSURzLmxlbmd0aCA9PT0gMFxyXG4gICAgICAgID8gbnVsbFxyXG4gICAgICAgIDogdGhpcy5tYXR0ZXJ0YWdJRHNbdGhpcy5tYXR0ZXJ0YWdJRHMubGVuZ3RoIC0gMV07XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBHZXRzIE1hdHRlcnRhZ0RhdGEgZm9yIE1hdHRlcnRhZyAocmVwbGFjZXMgZ2V0VGFnRGF0YUZyb21JZClcclxuICAgKiBAcGFyYW0gbWF0dGVydGFnSURcclxuICAgKiBAcmV0dXJucyBNYXR0ZXJ0YWdEYXRhXHJcbiAgICovXHJcbiAgZ2V0TWF0dGVyVGFnRGF0YUZvck1hdHRlcnRhZyhtYXR0ZXJ0YWdJRDogc3RyaW5nKTogTWF0dGVydGFnRGF0YSB8IG51bGwge1xyXG4gICAgdHJ5IHtcclxuICAgICAgcmV0dXJuIHRoaXMuZGljdGlvbm5hcnlUYWdzLmdldChtYXR0ZXJ0YWdJRCk7XHJcbiAgICB9IGNhdGNoIHtcclxuICAgICAgY29uc29sZS5sb2coJ2Nhbm5vdCByZXRyaWV2ZSBtYXR0ZXJ0YWdEYXRhIGZvciB0YWcnLCBtYXR0ZXJ0YWdJRCk7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gbnVsbDtcclxuICB9XHJcblxyXG4gIC8vXHJcbiAgLy8gLS0tLS0tLS0tLSBWaWV3ZXIgcmVsYXRlZCAoc3dpdGNoIHZpZXdzLCBnbyB0bykgLS0tLS0tLS0tLVxyXG4gIC8vXHJcbiAgYXN5bmMgYWN0aW9uX3Rvb2xib3hfZmxvb3JwbGFuKCkge1xyXG4gICAgaWYgKHRoaXMuaW5UcmFuc2l0aW9uTW9kZSB8fCB0aGlzLmluVHJhbnNpdGlvblN3ZWVwKSB7XHJcbiAgICAgIGNvbnNvbGUubG9nKCd2aWV3ZXIgaXMgaW4gdHJhbnNpdGlvbiwgY2Fubm90IGdvIGZsb29ycGxhbicpO1xyXG4gICAgICByZXR1cm47XHJcbiAgICB9XHJcbiAgICB0cnkge1xyXG4gICAgICBhd2FpdCB0aGlzLnNkay5Nb2RlLm1vdmVUbygnbW9kZS5mbG9vcnBsYW4nKTtcclxuICAgIH0gY2F0Y2ggKGUpIHtcclxuICAgICAgY29uc29sZS5sb2coJ2Nhbm5vdCBnbyB0byBmbG9vcnBsYW4nLCBlKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIGFjdGlvbl90b29sYm94X2luc2lkZV92aWV3KCkge1xyXG4gICAgdGhpcy5zZGsuTW9kZS5tb3ZlVG8oJ21vZGUuaW5zaWRlJyk7XHJcbiAgfVxyXG5cclxuICBhY3Rpb25TaG93QWxsRmxvb3JzKCkge1xyXG4gICAgdHJ5IHtcclxuICAgICAgdGhpcy5zZGsuRmxvb3Iuc2hvd0FsbCgpO1xyXG4gICAgfSBjYXRjaCAoZSkge1xyXG4gICAgICBjb25zb2xlLmxvZygnY2Fubm90IHNob3cgYWxsIGZsb29ycycsIGUpO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgYXN5bmMgYWN0aW9uX3Rvb2xib3hfZG9sbGhvdXNlKCkge1xyXG4gICAgc2V0VGltZW91dChhc3luYyAoKSA9PiB7XHJcbiAgICAgIC8vIGNvbnNvbGUubG9nKFwibW9kZTogXCIsIHRoaXMuaW5UcmFuc2l0aW9uTW9kZSwgXCIgc3dlZXA6IFwiLCB0aGlzLmluVHJhbnNpdGlvblN3ZWVwKTtcclxuICAgICAgaWYgKHRoaXMuaW5UcmFuc2l0aW9uTW9kZSB8fCB0aGlzLmluVHJhbnNpdGlvblN3ZWVwKSB7XHJcbiAgICAgICAgY29uc29sZS5sb2coJ3ZpZXdlciBpcyBpbiB0cmFuc2l0aW9uLCBjYW5ub3QgZ28gZG9sbGhvdXNlJyk7XHJcbiAgICAgICAgcmV0dXJuO1xyXG4gICAgICB9XHJcbiAgICAgIHRyeSB7XHJcbiAgICAgICAgYXdhaXQgdGhpcy5zZGsuTW9kZS5tb3ZlVG8oJ21vZGUuZG9sbGhvdXNlJyk7XHJcbiAgICAgIH0gY2F0Y2ggKGUpIHtcclxuICAgICAgICBjb25zb2xlLmxvZygnY2Fubm90IGdvIHRvIGRvbGxob3VzZScsIGUpO1xyXG4gICAgICB9XHJcbiAgICB9LCAxMjAwKTtcclxuICB9XHJcblxyXG4gIGFjdGlvbl90b29sYm94X21lc3VyZSgpIHtcclxuICAgIGNvbnN0IG5ld1N0YXRlID0gIXRoaXMuaXNNZWFzdXJlTW9kZU9uO1xyXG4gICAgdGhpcy5zZGsuTWVhc3VyZW1lbnRzLnRvZ2dsZU1vZGUobmV3U3RhdGUpLnRoZW4oKCkgPT4ge1xyXG4gICAgICBjb25zb2xlLmxvZyhcclxuICAgICAgICBgTWVhc3VyZW1lbnQgbW9kZSBpcyBub3cgJHtuZXdTdGF0ZSA/ICdlbmFibGVkJyA6ICdkaXNhYmxlZCd9YFxyXG4gICAgICApO1xyXG4gICAgfSk7XHJcbiAgfVxyXG5cclxuICBhY3Rpb25fdG9vbGJveF9jYW5jZWxfbWVzdXJlKCkge1xyXG4gICAgaWYgKHRoaXMuaXNNZWFzdXJlTW9kZU9uKSB7XHJcbiAgICAgIHRoaXMuYWN0aW9uX3Rvb2xib3hfbWVzdXJlKCk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBhc3luYyBhY3Rpb25fZ29fdG9fZmxvb3IoXHJcbiAgICBmbG9vck5hbWU6IHN0cmluZyxcclxuICAgIG1hdHRlcnBvcnRGbG9vclNlcXVlbmNlOiBudW1iZXIgPSBudWxsXHJcbiAgKSB7XHJcbiAgICBpZiAoIXRoaXMuZmxvb3JzKSB7XHJcbiAgICAgIGNvbnNvbGUubG9nKCdGbG9vciBhcmUgbm90IGxvYWRlZCB5ZXQnKTtcclxuICAgICAgcmV0dXJuO1xyXG4gICAgfVxyXG4gICAgLy8gY29uc29sZS5sb2codGhpcy5mbG9vcnMpO1xyXG4gICAgLy8gbG9vayB1cCBmb3Igc2VxdWVuY2UgbnVtYmVyICh0aGUgc2FmZXN0IG1ldGhvZClcclxuICAgIGxldCBmbG9vck1hdHRlcnBvcnQgPSB0aGlzLmZsb29ycy5maW5kKFxyXG4gICAgICAoZmxvb3IpID0+IGZsb29yLnNlcXVlbmNlID09PSBtYXR0ZXJwb3J0Rmxvb3JTZXF1ZW5jZVxyXG4gICAgKTtcclxuICAgIGlmICghZmxvb3JNYXR0ZXJwb3J0KSB7XHJcbiAgICAgIGZsb29yTWF0dGVycG9ydCA9IHRoaXMuZmxvb3JzLmZpbmQoXHJcbiAgICAgICAgKGZsb29yKSA9PiBmbG9vck5hbWUuaW5jbHVkZXMoZmxvb3IubmFtZSkgJiYgZmxvb3IubmFtZSAhPSAnJ1xyXG4gICAgICApO1xyXG4gICAgfVxyXG4gICAgaWYgKCFmbG9vck1hdHRlcnBvcnQpIHtcclxuICAgICAgZmxvb3JNYXR0ZXJwb3J0ID0gdGhpcy5mbG9vcnMuZmluZCgoZmxvb3IpID0+XHJcbiAgICAgICAgZmxvb3JOYW1lLmluY2x1ZGVzKGZsb29yLmlkKVxyXG4gICAgICApO1xyXG4gICAgfVxyXG4gICAgLy8gY29uc29sZS5sb2coZmxvb3JNYXR0ZXJwb3J0KVxyXG4gICAgaWYgKGZsb29yTWF0dGVycG9ydCkge1xyXG4gICAgICBsZXQgcmV0cnkgPSB0cnVlO1xyXG4gICAgICB3aGlsZSAocmV0cnkpIHtcclxuICAgICAgICB0cnkge1xyXG4gICAgICAgICAgY29uc3QgZmxvb3JJbmRleCA9IGF3YWl0IHRoaXMuc2RrLkZsb29yLm1vdmVUbyhcclxuICAgICAgICAgICAgZmxvb3JNYXR0ZXJwb3J0LnNlcXVlbmNlXHJcbiAgICAgICAgICApO1xyXG4gICAgICAgICAgLy8gY29uc29sZS5sb2coXCJtb3ZlZCB0byBmbG9vckluZGV4XCIsIGZsb29ySW5kZXgpO1xyXG4gICAgICAgICAgcmV0cnkgPSBmYWxzZTtcclxuICAgICAgICB9IGNhdGNoIChlcnJvcikge1xyXG4gICAgICAgICAgY29uc29sZS5sb2coJ0Nhbm5vdCBtb3ZlIHRvIEZsb29yJywgZXJyb3IpO1xyXG4gICAgICAgICAgYXdhaXQgd2FpdCgxMDApO1xyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG4gICAgfSBlbHNlIHtcclxuICAgICAgY29uc29sZS53YXJuKCdObyBtYXR0ZXJwb3J0IGZsb29yIGZvdW5kIHRvIG1vdmUgdG8nKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIGFzeW5jIGFjdGlvbl9nb190b19zd2VlcChcclxuICAgIHN3ZWVwOiBzdHJpbmcsXHJcbiAgICByb3RhdGlvbjogeyB4OiBudW1iZXI7IHk6IG51bWJlciB9ID0gbnVsbFxyXG4gICkge1xyXG4gICAgaWYgKHRoaXMuZm9yYmlkZGVuU3dlZXBzLmluY2x1ZGVzKHN3ZWVwKSkge1xyXG4gICAgICBjb25zb2xlLmxvZygndXNlciBpcyBub3QgYWxsb3dlZCB0byBnbyB0byB0aGlzIHN3ZWVwJyk7XHJcbiAgICAgIHJldHVybjtcclxuICAgIH1cclxuICAgIC8vIGNvbnNvbGUubG9nKFwiZ29pbmcgdG8gc3dlZXBcIiwgc3dlZXAsIFwid2l0aCByb3RhdGlvbjpcIiwgcm90YXRpb24pO1xyXG4gICAgc2V0VGltZW91dChhc3luYyAoKSA9PiB7XHJcbiAgICAgIGlmICh0aGlzLmluVHJhbnNpdGlvbk1vZGUgfHwgdGhpcy5pblRyYW5zaXRpb25Td2VlcCkge1xyXG4gICAgICAgIGNvbnNvbGUubG9nKCdDYW5ub3QgZ28gdG8gc3dlZXAsIGluIHRyYW5zaXRpb24nKTtcclxuICAgICAgICByZXR1cm47XHJcbiAgICAgIH1cclxuICAgICAgdHJ5IHtcclxuICAgICAgICB0aGlzLmluVHJhbnNpdGlvblN3ZWVwID0gdHJ1ZTtcclxuICAgICAgICBhd2FpdCB0aGlzLnNkay5Td2VlcC5tb3ZlVG8oc3dlZXAsIHtcclxuICAgICAgICAgIHRyYW5zaXRpb246ICd0cmFuc2l0aW9uLmluc3RhbnQnLFxyXG4gICAgICAgICAgdHJhbnNpdGlvblRpbWU6IDE1MDAsXHJcbiAgICAgICAgfSk7XHJcbiAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XHJcbiAgICAgICAgdGhpcy5pblRyYW5zaXRpb25Td2VlcCA9IGZhbHNlO1xyXG4gICAgICAgIGNvbnNvbGUubG9nKCdDYW5ub3QgbW92ZSB0byBzd2VlcCcsIGVycm9yKTtcclxuICAgICAgfVxyXG4gICAgICBpZiAocm90YXRpb24pIHtcclxuICAgICAgICBhd2FpdCB0aGlzLnNkay5DYW1lcmEuc2V0Um90YXRpb24ocm90YXRpb24sIHtzcGVlZDogMTAwfSk7IC8vIHNwZWVkIGlzIGRlZ3JlZXMgcGVyIHNlY29uZFxyXG4gICAgICB9XHJcbiAgICB9LCAxMDAwKTtcclxuICB9XHJcblxyXG4gIGdldEN1cnJlbnRTd2VlcCgpOiBzdHJpbmcgfCBudWxsIHtcclxuICAgIGlmICh0aGlzLnBvc2VDYW1lcmEpIHtcclxuICAgICAgcmV0dXJuIHRoaXMucG9zZUNhbWVyYS5zd2VlcDtcclxuICAgIH1cclxuICAgIHJldHVybiBudWxsO1xyXG4gIH1cclxuXHJcbiAgZ2V0Q3VycmVudENhbWVyYVBvc2l0aW9uKCk6IHtcclxuICAgIHJvdGF0aW9uOiBhbnk7XHJcbiAgICBwb3NpdGlvbjogYW55O1xyXG4gICAgc3dlZXA6IGFueTtcclxuICB9IHwgbnVsbCB7XHJcbiAgICBpZiAodGhpcy5wb3NlQ2FtZXJhKSB7XHJcbiAgICAgIHJldHVybiB0aGlzLnBvc2VDYW1lcmE7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gbnVsbDtcclxuICB9XHJcblxyXG4gIHNldEludGVyYWN0aW9uTW9kZShpbnRlcmFjdGlvbk1vZGU6IG51bWJlcikge1xyXG4gICAgdGhpcy5pbnRlcmFjdGlvbk1vZGUgPSBpbnRlcmFjdGlvbk1vZGU7XHJcbiAgfVxyXG5cclxuICBnZXRJbnRlcmFjdGlvbk1vZGUoKSB7XHJcbiAgICByZXR1cm4gdGhpcy5pbnRlcmFjdGlvbk1vZGU7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBDbGVhciBhbGwgdmFyaWFibGVzLCBkZWxldGVzIGFsbCB0YWdzICh3aGVuIHZpZXdlciBpcyByZW1vdmVyIG9yIG1vZGVsIGNoYW5nZWQ9cmVsb2FkIG5lZWRlZClcclxuICAgKi9cclxuICBhc3luYyBjbGVhckFsbCgpIHtcclxuICAgIGNvbnNvbGUubG9nKCdyZW1vdmluZyB2aWV3ZXInKTtcclxuICAgIHRoaXMuYWN0aW9uX2RlbGV0ZV9hbGxfbWF0dGVydGFncygpO1xyXG4gICAgdGhpcy5mbG9vcnMgPSBudWxsO1xyXG4gICAgdGhpcy5zd2VlcHMgPSBudWxsO1xyXG4gICAgdGhpcy5zZGsgPSBudWxsO1xyXG4gICAgY2xlYXJJbnRlcnZhbCh0aGlzLnRpbWVyUG9pbnRlcik7XHJcbiAgICB0aGlzLmZvcmJpZGRlblN3ZWVwcyA9IFtdO1xyXG4gICAgdGhpcy50YWdNZXNzZW5nZXJPbiA9IGZhbHNlO1xyXG4gICAgLy8gY2FuY2VsIHN1YnNjcmlwdGlvbnNcclxuICAgIHRoaXMucG9pbnRlckJ1dHRvbi5yZW1vdmVFdmVudExpc3RlbmVyKFxyXG4gICAgICAnY2xpY2snLFxyXG4gICAgICB0aGlzLnBvaW50ZXJMZWZ0Q2xpY2tIYW5kbGVyXHJcbiAgICApO1xyXG4gICAgdGhpcy5wb2ludGVyQnV0dG9uLnJlbW92ZUV2ZW50TGlzdGVuZXIoXHJcbiAgICAgICdjb250ZXh0bWVudScsXHJcbiAgICAgIHRoaXMucG9pbnRlclJpZ2h0Q2xpY2tIYW5kbGVyXHJcbiAgICApO1xyXG5cclxuICAgIC8vIFRPRE86IG9ubHkgRm9yIEFkbWluc1xyXG4gICAgaWYgKHRoaXMuZ2V0Q3Vyc29yUG9zaXRpb25CdXR0b24pIHtcclxuICAgICAgdGhpcy5nZXRDdXJzb3JQb3NpdGlvbkJ1dHRvbi5yZW1vdmVFdmVudExpc3RlbmVyKFxyXG4gICAgICAgICdhdXhjbGljaycsXHJcbiAgICAgICAgdGhpcy5wb2ludGVyTWlkZGxlQ2xpY2tIYW5kbGVyXHJcbiAgICAgICk7XHJcbiAgICB9XHJcbiAgICAvLyBUT0RPOiBvbmx5IGZvciBkZXYhXHJcbiAgICBpZiAoISF0aGlzLmdldEN1cnNvclBvc2l0aW9uQnV0dG9uICYmXHJcbiAgICAgIChkb2N1bWVudC5sb2NhdGlvbi5ocmVmLmluZGV4T2YoJ2RldicpICE9PSAtMSB8fCBkb2N1bWVudC5sb2NhdGlvbi5ocmVmLmluZGV4T2YoJ2xvY2FsaG9zdCcpICE9PSAtMSkpIHtcclxuICAgICAgY2xlYXJJbnRlcnZhbCh0aGlzLmludGVydmFsQ3Vyc29yUG9pbnRlclBvc2l0aW9uKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIGFzeW5jIHJlbW92ZUZvcmJpZGRlblN3ZWVwcyhmb3JiaWRkZW5Td2VlcHM6IHN0cmluZ1tdKSB7XHJcbiAgICB0aGlzLmZvcmJpZGRlblN3ZWVwcyA9IFsuLi5mb3JiaWRkZW5Td2VlcHNdO1xyXG4gICAgbGV0IHJlbW92ZWQgPSAwO1xyXG4gICAgYXdhaXQgUHJvbWlzZS5hbGwoXHJcbiAgICAgIGZvcmJpZGRlblN3ZWVwcy5tYXAoYXN5bmMgKHN3ZWVwKSA9PiB7XHJcbiAgICAgICAgdHJ5IHtcclxuICAgICAgICAgIGF3YWl0IHRoaXMuc2RrLlN3ZWVwLmRpc2FibGUoc3dlZXApO1xyXG4gICAgICAgICAgcmVtb3ZlZCArPSAxO1xyXG4gICAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XHJcbiAgICAgICAgICBjb25zb2xlLmxvZyhlcnJvcik7XHJcbiAgICAgICAgfVxyXG4gICAgICB9KVxyXG4gICAgKTtcclxuICAgIGNvbnNvbGUubG9nKCdyZW1vdmVkIHN3ZWVwczonLCByZW1vdmVkKTtcclxuICB9XHJcblxyXG4gIC8vXHJcbiAgLy8gLS0tLS0tLS0tLSAzRCBvYmplY3RzIChTREsgQnVuZGxlIG9ubHkpIC0tLS0tLS0tLS1cclxuICAvL1xyXG4gIGFzeW5jIGluaXQzRE9iamVjdFZpZXdlcigpOiBQcm9taXNlPHZvaWQ+IHtcclxuICAgIHJldHVybiBuZXcgUHJvbWlzZShhc3luYyAocmVzb2x2ZSkgPT4ge1xyXG4gICAgICB2YXIgW3NjZW5lT2JqZWN0XSA9IGF3YWl0IHRoaXMuc2RrLlNjZW5lLmNyZWF0ZU9iamVjdHMoMSk7XHJcblxyXG4gICAgICB2YXIgbm9kZSA9IHNjZW5lT2JqZWN0LmFkZE5vZGUoKTtcclxuXHJcbiAgICAgIC8vIFRPRE8gY2hhbmdlIHRoaXMg8J+krlxyXG4gICAgICBub2RlLmFkZENvbXBvbmVudCgnbXAubGlnaHRzJyk7XHJcbiAgICAgIC8vbm9kZS5hZGRDb21wb25lbnQoJ21wLmxpZ2h0cycpO1xyXG4gICAgICAvKm5vZGUuYWRkQ29tcG9uZW50KCdtcC5saWdodHMnKTtcclxuICAgICAgbm9kZS5hZGRDb21wb25lbnQoJ21wLmxpZ2h0cycpOyovXHJcbiAgICAgIG5vZGUuc3RhcnQoKTtcclxuXHJcbiAgICAgIGNvbnN0IG5vZGVDb250cm9sID0gc2NlbmVPYmplY3QuYWRkTm9kZSgpO1xyXG4gICAgICB0aGlzLm9iamVjdENvbnRyb2wgPSBub2RlQ29udHJvbC5hZGRDb21wb25lbnQoJ21wLnRyYW5zZm9ybUNvbnRyb2xzJyk7XHJcbiAgICAgIG5vZGVDb250cm9sLnN0YXJ0KCk7XHJcblxyXG4gICAgICAvL3RoaXMuYWRkM0RPYmplY3Qoe30sbnVsbCk7XHJcblxyXG4gICAgICByZXNvbHZlKCk7XHJcbiAgICB9KTtcclxuICB9XHJcblxyXG4gIGFzeW5jIGFkZDNET2JqZWN0KFxyXG4gICAgb2JqOiBJT2JqZWN0M0QsXHJcbiAgICBtb2RlPzogJ3RyYW5zbGF0ZScgfCAncm90YXRlJ1xyXG4gICk6IFByb21pc2U8YW55PiB7XHJcbiAgICByZXR1cm4gbmV3IFByb21pc2UoYXN5bmMgKHJlc29sdmUpID0+IHtcclxuICAgICAgY29uc3QgW3NjZW5lT2JqZWN0XSA9IGF3YWl0IHRoaXMuc2RrLlNjZW5lLmNyZWF0ZU9iamVjdHMoMSk7XHJcblxyXG4gICAgICAvLyBUT0RPOiBpbXByb3ZtZW50LCByZWdyb3VwIGFsbCBvZiB0aGVzZSBpbiBEeW5hbWljYWwgT2JqZWN0cyBMaWJcclxuICAgICAgLy8gU2VjdXJpdHlDYW1lcmFcclxuICAgICAgLy8gTmVzdFRoZXJtb3N0YXRcclxuICAgICAgLy8gVmlkZW9cclxuICAgICAgbGV0IGlzQW5pbWF0ZWRTZWN1cml0eUNhbWVyYSA9IGZhbHNlO1xyXG4gICAgICBsZXQgaXNOZXN0VGhlcm1vc3RhdCA9IGZhbHNlO1xyXG4gICAgICBsZXQgaXNTbWFydGVycGxhblByb21vdGlvbmFsVmlkZW8gPSBmYWxzZTtcclxuICAgICAgbGV0IGlzQXppbXV0aGFsQ3Jvd24gPSBmYWxzZTtcclxuXHJcbiAgICAgIC8qKlxyXG4gICAgICAgKiBUT0RPOiByZWZhY3RvIHdpdGggYW4gZW51bSBvciBzd2l0Y2gvY2FzZVxyXG4gICAgICAgKi9cclxuICAgICAgaWYgKG9iai5vYmplY3QgPT09IFwic2VjdXJpdHlfY2FtZXJhXCIpIHtcclxuICAgICAgICBpc0FuaW1hdGVkU2VjdXJpdHlDYW1lcmEgPSB0cnVlO1xyXG4gICAgICB9XHJcbiAgICAgIGlmIChvYmoub2JqZWN0ID09PSBcIm5lc3RfdGhlcm1vc3RhdFwiKSB7XHJcbiAgICAgICAgaXNOZXN0VGhlcm1vc3RhdCA9IHRydWU7XHJcbiAgICAgIH1cclxuICAgICAgaWYgKG9iai5vYmplY3QgPT09ICd2aWRlbycpIHtcclxuICAgICAgICBpc1NtYXJ0ZXJwbGFuUHJvbW90aW9uYWxWaWRlbyA9IHRydWU7XHJcbiAgICAgIH1cclxuICAgICAgaWYob2JqLm9iamVjdCA9PT0gJ2F6aW11dGgnKSB7XHJcbiAgICAgICAgaXNBemltdXRoYWxDcm93biA9IHRydWU7XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIGNvbnN0IG1vZGVsTm9kZSA9IHNjZW5lT2JqZWN0LmFkZE5vZGUoKTtcclxuICAgICAgbGV0IGNvbXBvbmVudCA9IG51bGw7XHJcbiAgICAgIGNvbnN0IGluaXRpYWwgPSB7XHJcbiAgICAgICAgdXJsOiBgL2Fzc2V0cy8zRG9iamVjdHMvb2JqZWN0cy8ke29iai5vYmplY3R9JHtcclxuICAgICAgICAgIG9iai5mb3JtYXQuaW5kZXhPZignLicpID09PSAtMSA/ICcuJyArIG9iai5mb3JtYXQgOiBvYmouZm9ybWF0XHJcbiAgICAgICAgfWAsXHJcbiAgICAgICAgLy8gVE9ETy8gc3RvcmUgbG9jYWxQb3NpdGlvbiAmJiBsb2NhbFJvdGF0aW9uIGluIEJERCB0b28gKGluIG9yZGVyIHRvIGhhdmUgcGVydGZlY3QgaW5pdGlhbCBwbGFjZW1lbnQpXHJcbiAgICAgICAgbG9jYWxSb3RhdGlvbjoge1wieFwiOiAwLCBcInlcIjogMCwgXCJ6XCI6IDB9LFxyXG4gICAgICAgIC8vIFRPRE8vIHN0b3JlIGxvY2FsUG9zaXRpb24gJiYgbG9jYWxSb3RhdGlvbiBpbiBCREQgdG9vIChpbiBvcmRlciB0byBoYXZlIHBlcnRmZWN0IGluaXRpYWwgcGxhY2VtZW50KVxyXG4gICAgICAgIGxvY2FsUG9zaXRpb246IHtcInhcIjogMCwgXCJ5XCI6IDAsIFwielwiOiAwfSxcclxuICAgICAgICB2aXNpYmxlOiB0cnVlLFxyXG4gICAgICAgIGNvbGxpZGVyRW5hYmxlZDogdHJ1ZVxyXG4gICAgICB9O1xyXG5cclxuXHJcbiAgICAgIHN3aXRjaCAob2JqLmZvcm1hdCkge1xyXG4gICAgICAgIGNhc2UgJy5vYmonOlxyXG4gICAgICAgIGNhc2UgJ29iaic6XHJcbiAgICAgICAgICBjb21wb25lbnQgPSBtb2RlbE5vZGUuYWRkQ29tcG9uZW50KCdtcC5vYmpMb2FkZXInLCBpbml0aWFsKTtcclxuICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgIGNhc2UgJy5mYngnOlxyXG4gICAgICAgIGNhc2UgJ2ZieCc6XHJcbiAgICAgICAgICBjb21wb25lbnQgPSBtb2RlbE5vZGUuYWRkQ29tcG9uZW50KCdtcC5mYnhMb2FkZXInLCBpbml0aWFsKTtcclxuICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgIGNhc2UgJy5nbHRmJzpcclxuICAgICAgICBjYXNlICdnbHRmJzpcclxuICAgICAgICAgIGNvbXBvbmVudCA9IG1vZGVsTm9kZS5hZGRDb21wb25lbnQoJ21wLmdsdGZMb2FkZXInLCBpbml0aWFsKTtcclxuICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgIGNhc2UgJy5nbGInOlxyXG4gICAgICAgIGNhc2UgJ2dsYic6XHJcbiAgICAgICAgICBjb21wb25lbnQgPSBtb2RlbE5vZGUuYWRkQ29tcG9uZW50KCdtcC5nbHRmTG9hZGVyJywgaW5pdGlhbCk7XHJcbiAgICAgICAgICBicmVhaztcclxuICAgICAgICBjYXNlICcuZGFlJzpcclxuICAgICAgICBjYXNlICdkYWUnOlxyXG4gICAgICAgICAgY29tcG9uZW50ID0gbW9kZWxOb2RlLmFkZENvbXBvbmVudCgnbXAuZGFlTG9hZGVyJywgaW5pdGlhbCk7XHJcbiAgICAgICAgICBicmVhaztcclxuXHJcbiAgICAgICAgZGVmYXVsdDpcclxuICAgICAgICAgIGNvbnNvbGUubG9nKCdGb3JtYXQgbm90IHN1cHBvcnRlZCcpO1xyXG4gICAgICAgICAgYnJlYWs7XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIC8vY2FjaGUgc3lzdGVtIChpJ2xsIHRyeSB0byBtYWtlIGl0IHdvcmsgbGF0ZXIgLi4uKVxyXG4gICAgICAvKmxldCBvYmpDb250ZW50c0pTT04gPSBKU09OLnN0cmluZ2lmeShtb2RlbE5vZGUpO1xyXG4gICAgICBjb25zb2xlLmxvZyhtb2RlbE5vZGUpO1xyXG4gICAgICBjb25zb2xlLmxvZyhvYmpDb250ZW50c0pTT04pO1xyXG4gICAgICBjb25zb2xlLmxvZyhKU09OLnN0cmluZ2lmeShtb2RlbE5vZGUpKTtcclxuICAgICAgbG9jYWxTdG9yYWdlLnNldEl0ZW0oYHRlc3RPYmpfJHtvYmoub2JqZWN0fWAsIG9iakNvbnRlbnRzSlNPTik7XHJcbiAgICAgIGNvbnNvbGUubG9nKFwic3RvcmVkID8hXCIpO1xyXG4gICAgICBjb25zb2xlLmxvZyh0eXBlb2YgbW9kZWxOb2RlKTsqL1xyXG4gICAgICAvL2xldCBkYXRhUyA9IHNlcmlhbGlqc2Uuc2VyaWFsaXplKG1vZGVsTm9kZSk7XHJcbiAgICAgIC8vY29uc29sZS5sb2coZGF0YVMpO1xyXG5cclxuICAgICAgLy8gVXNlIDMgPyEgQW1iaWVudCBsaWdodGluZ3NcclxuICAgICAgaWYgKHRoaXMubm9MaWdodEZvck9iamVjdHMpIHtcclxuICAgICAgICBjb25zdCBsaWdodHNOb2RlID0gc2NlbmVPYmplY3QuYWRkTm9kZSgpO1xyXG4gICAgICAgIGxpZ2h0c05vZGUuYWRkQ29tcG9uZW50KCdtcC5hbWJpZW50TGlnaHQnLCB7XHJcbiAgICAgICAgICBpbnRlbnNpdHk6IDEsXHJcbiAgICAgICAgICBjb2xvcjoge3I6IDEuMCwgZzogMS4wLCBiOiAxLjB9LFxyXG4gICAgICAgIH0pO1xyXG4gICAgICAgIHRoaXMubm9MaWdodEZvck9iamVjdHMgPSBmYWxzZTtcclxuICAgICAgfVxyXG5cclxuICAgICAgbW9kZWxOb2RlLm9iajNELnBvc2l0aW9uLnNldChcclxuICAgICAgICBvYmoucG9zaXRpb24ueCxcclxuICAgICAgICBvYmoucG9zaXRpb24ueSxcclxuICAgICAgICBvYmoucG9zaXRpb24uelxyXG4gICAgICApO1xyXG5cclxuICAgICAgbW9kZWxOb2RlLm9iajNELnJvdGF0aW9uLnNldChcclxuICAgICAgICBvYmoucm90YXRpb24ueCxcclxuICAgICAgICBvYmoucm90YXRpb24ueSxcclxuICAgICAgICBvYmoucm90YXRpb24uelxyXG4gICAgICApO1xyXG4gICAgICBtb2RlbE5vZGUub2JqM0Quc2NhbGUuc2V0KG9iai5zY2FsZS54LCBvYmouc2NhbGUueSwgb2JqLnNjYWxlLnopO1xyXG4gICAgICBpZihpc0F6aW11dGhhbENyb3duKVxyXG4gICAgICB7XHJcbiAgICAgICAgLyppZihtb2RlbE5vZGUub2JqM0Quc2NhbGUueCA+PSAxLjApe1xyXG4gICAgICAgICAgbW9kZWxOb2RlLm9iajNELnNjYWxlLnNldChvYmouc2NhbGUueC81MDAwLCBvYmouc2NhbGUueS81MDAwLCBvYmouc2NhbGUuei81MDAwKTtcclxuICAgICAgICB9Ki9cclxuICAgICAgICB0aGlzLmF6aW11dGhhbENyb3duPW1vZGVsTm9kZTtcclxuICAgICAgICB0aGlzLmRpc3BsYXlBemltdXRhbENyb3duKCk7XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIC8vIEJ5IGRlZmF1dCwgZHVyaW5nIGNyZWF0aW9uLCBvYmplY3QgaGFzIHRyYW5zbGF0aW9uIGdpem1vXHJcbiAgICAgIC8vID0+IFVzZXIgaGFzIHRvIGNsaWNrIG9uIGxhdGVyYWwgcGFuZWwsIGFuZCBzYXZlIGl0cyBwb3NpdGlvbiBhZnRlciBwbGF5aW5nIHdpdGggaXQhXHJcbiAgICAgIGlmIChtb2RlICYmICFpc05lc3RUaGVybW9zdGF0KSB7XHJcbiAgICAgICAgdGhpcy5hdHRhY2hHaXptb0NvbnRyb2xUbzNET2JqZWN0KFxyXG4gICAgICAgICAgbW9kZWxOb2RlLFxyXG4gICAgICAgICAgc2NlbmVPYmplY3QsXHJcbiAgICAgICAgICBtb2RlLFxyXG4gICAgICAgICAgdHJ1ZSxcclxuICAgICAgICAgIHRydWVcclxuICAgICAgICApLmNhdGNoKChlKSA9PiBjb25zb2xlLmxvZyhlKSk7XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIGlmICh0aGlzLmxhc3RPYmplY3QzRCAmJiB0eXBlb2YgdGhpcy5sYXN0T2JqZWN0M0QuaWQgPT09ICdzdHJpbmcnKSB7XHJcbiAgICAgICAgLy8gcHJvbXB0IFRocmVlSlMgVVVJRCB0byBtYXRjaCBvdXIgbGFzdCBnZW5lcmF0ZWQgb2JqZWN0IGlmIG5ldyAobm90IGZyb20gRGIpXHJcbiAgICAgICAgbW9kZWxOb2RlLm9iajNELnV1aWQgPSB0aGlzLmxhc3RPYmplY3QzRC5pZDtcclxuICAgICAgfSBlbHNlIGlmIChvYmouaWQpIHtcclxuICAgICAgICBtb2RlbE5vZGUub2JqM0QudXVpZCA9IG9iai5pZDtcclxuICAgICAgfVxyXG4gICAgICB0aGlzLmxhc3RPYmplY3QzRCA9IG1vZGVsTm9kZS5vYmozRDtcclxuXHJcbiAgICAgIC8vIFN0b3JlIHRoaXMgaW4gbWVtb3J5IE1hcCBkaWN0aW9ubmFyeVxyXG4gICAgICAvL2NvbnNvbGUubG9nKFwiQWRkaW5nIG9iamVjdDogXCIpO1xyXG4gICAgICAvL2NvbnNvbGUubG9nKG1vZGVsTm9kZSk7XHJcbiAgICAgIHRoaXMuZGljdGlvbm5hcnlPYmplY3RzM0Quc2V0KG1vZGVsTm9kZS5vYmozRC51dWlkLCBtb2RlbE5vZGUpO1xyXG4gICAgICB0aGlzLmRpY3Rpb25uYXJ5U2NlbmVPYmplY3RzM0Quc2V0KG1vZGVsTm9kZS5vYmozRC51dWlkLCBzY2VuZU9iamVjdCk7XHJcblxyXG4gICAgICAvKnRoaXMuc2RrLkNhbWVyYS5wb3NlLnN1YnNjcmliZShcclxuICAgICAgICBmdW5jdGlvbiAocG9zZTogYW55KSB7XHJcbiAgICAgICAgICAvL2NvbnNvbGUubG9nKFwiaW4gY2FsbGJhY2tcIilcclxuICAgICAgICAgIC8vY29uc29sZS5sb2codGhpcy5sYXN0Q2FtZXJhUG9zaXRpb24pXHJcbiAgICAgICAgICAvL2NvbnNvbGUubG9nKHBvc2UucG9zaXRpb24pXHJcbiAgICAgICAgICBpZigocG9zZS5wb3NpdGlvbi54ID09IHRoaXMubGFzdENhbWVyYVBvc2l0aW9uLnggJiYgcG9zZS5wb3NpdGlvbi55ID09IHRoaXMubGFzdENhbWVyYVBvc2l0aW9uLnkgJiYgcG9zZS5wb3NpdGlvbi56ID09IHRoaXMubGFzdENhbWVyYVBvc2l0aW9uLnopIHx8IHRoaXMuaW5UcmFuc2l0aW9uTW9kZSB8fCB0aGlzLmluVHJhbnNpdGlvblN3ZWVwKXtcclxuICAgICAgICAgICAgLy9jb25zb2xlLmxvZyhcInJldHVybmluZ1wiKVxyXG4gICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgICBjb25zb2xlLmxvZyhcImNhbWVyYSBwb3M6XCIscG9zZS5wb3NpdGlvbik7XHJcbiAgICAgICAgICB0aGlzLmxhc3RDYW1lcmFQb3NpdGlvbiA9IHsuLi5wb3NlLnBvc2l0aW9ufTtcclxuICAgICAgICAgIGlmKHRoaXMubGFzdE9iamVjdDNEKXtcclxuICAgICAgICAgICAgdGhpcy5sYXN0T2JqZWN0M0QucG9zaXRpb24uc2V0KHBvc2UucG9zaXRpb24ueCsuNSxwb3NlLnBvc2l0aW9uLnkrLjUscG9zZS5wb3NpdGlvbi56Ky41KTtcclxuICAgICAgICAgIH1cclxuICAgICAgICB9LmJpbmQodGhpcykpOyovXHJcblxyXG4gICAgICBpZiAoaXNBbmltYXRlZFNlY3VyaXR5Q2FtZXJhKSB7XHJcblxyXG4gICAgICAgIGNvbnN0IGFuaW1hdG9yID0gbW9kZWxOb2RlLmFkZENvbXBvbmVudCgnbXAuc2VjdXJpdHlDYW1lcmEnLFxyXG4gICAgICAgICAge1xyXG4gICAgICAgICAgICBcIm5lYXJQbGFuZVwiOiAwLjEsXHJcbiAgICAgICAgICAgIFwiZmFyUGxhbmVcIjogMTAsXHJcbiAgICAgICAgICAgIFwiaG9yaXpvbnRhbEZPVlwiOiA1MixcclxuICAgICAgICAgICAgXCJhc3BlY3RcIjogMS43Nzc3Nzc3Nzc3Nzc3Nzc3LFxyXG4gICAgICAgICAgICBcImxvY2FsUG9zaXRpb25cIjoge1xyXG4gICAgICAgICAgICAgIFwieFwiOiAwLjMsXHJcbiAgICAgICAgICAgICAgXCJ5XCI6IDAuMTgsXHJcbiAgICAgICAgICAgICAgXCJ6XCI6IDBcclxuICAgICAgICAgICAgfSxcclxuICAgICAgICAgICAgXCJsb2NhbFJvdGF0aW9uXCI6IHtcclxuICAgICAgICAgICAgICBcInhcIjogLTE1LFxyXG4gICAgICAgICAgICAgIFwieVwiOiAtOTAsXHJcbiAgICAgICAgICAgICAgXCJ6XCI6IDBcclxuICAgICAgICAgICAgfSxcclxuICAgICAgICAgICAgXCJjb2xvclwiOiA2NTI4MCxcclxuICAgICAgICAgICAgXCJwYW5QZXJpb2RcIjogNSxcclxuICAgICAgICAgICAgXCJwYW5BbmdsZVwiOiAtNDVcclxuICAgICAgICAgIH0pO1xyXG4gICAgICAgIGNvbnN0IG1vZGVsT3V0cHV0ID0gc2NlbmVPYmplY3QuYWRkUGF0aCh7XHJcbiAgICAgICAgICBpZDogJ2FuaW1hdGVkLW1vZGVsJyxcclxuICAgICAgICAgIHR5cGU6IHRoaXMuc2RrLlNjZW5lLlBhdGhUeXBlLk9VVFBVVCxcclxuICAgICAgICAgIG5vZGU6IG1vZGVsTm9kZSxcclxuICAgICAgICAgIGNvbXBvbmVudDogYW5pbWF0b3IsXHJcbiAgICAgICAgICBwcm9wZXJ0eTogJ29iamVjdFJvb3QnXHJcbiAgICAgICAgfSk7XHJcblxyXG4gICAgICAgIHRoaXMuc2VjdXJpdHlDYW1lcmFBbmltYXRvciA9IGFuaW1hdG9yO1xyXG4gICAgICAgIGlmICghb2JqLnZpZXdGcnVzdHVtKSB7XHJcbiAgICAgICAgICBzZXRUaW1lb3V0KCgpID0+IHtcclxuICAgICAgICAgICAgYW5pbWF0b3IudG9nZ2xlVmlld0ZydXN0dW0oKTtcclxuICAgICAgICAgIH0sIDEwMDApO1xyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG5cclxuICAgICAgaWYgKGlzTmVzdFRoZXJtb3N0YXQpIHtcclxuICAgICAgICAvLyBUT0RPOiB1c2UgYmluZFBhdGggaW5zdGVhZCB1c2luZyBNUCBzZGsgY2xhc3NlcyAoc2VlIFNlY3VyaXR5IENhbWVyYSBleGFtcGxlKVxyXG4gICAgICAgIC8vIGZvciBUViB1c2VzIENhbnZhc0ltYWdlIGJlbG93IVxyXG4gICAgICAgIC8vIGNvbnN0IGNpID0gbmV3IENhbnZhc0ltYWdlKCk7XHJcbiAgICAgICAgLy8gY2kub25Jbml0KCk7XHJcbiAgICAgICAgY29uc3QgY3YgPSBuZXcgQ2FudmFzUmVuZGVyZXIoKTtcclxuICAgICAgICBjdi5vbkluaXQoKTtcclxuICAgICAgICBjb25zdCBwbGFuZSA9IG5ldyBQbGFuZVJlbmRlcmVyKCk7XHJcbiAgICAgICAgcGxhbmUub3V0cHV0cyA9IHtcclxuICAgICAgICAgIG9iamVjdFJvb3Q6IG5ldyBPYmplY3QzRCgpLFxyXG4gICAgICAgICAgY29sbGlkZXI6IG5ldyBPYmplY3QzRCgpXHJcbiAgICAgICAgfTtcclxuICAgICAgICBjb25zdCBpbnB1dFRleHR1cmUgPSBjdi5vdXRwdXRzLnRleHR1cmU7XHJcbiAgICAgICAgcGxhbmUuc2V0Um9vdFNjZW5lKHRoaXMudGhyZWVKU1NjZW5lKTtcclxuICAgICAgICBwbGFuZS5vbkluaXQobW9kZWxOb2RlLCBpbnB1dFRleHR1cmUpO1xyXG4gICAgICAgIGNvbnN0IHNjID0gbmV3IE5lc3RUaGVybW9zdGF0KCk7XHJcbiAgICAgICAgc2Muc2V0Q29tcG9uZW50KGNvbXBvbmVudCwgcGxhbmUsIGN2KTtcclxuICAgICAgICBzYy5zZXRSb290U2NlbmUodGhpcy50aHJlZUpTU2NlbmUpO1xyXG4gICAgICAgIHNjLm9uSW5pdChtb2RlbE5vZGUsIHBsYW5lLCBpbnB1dFRleHR1cmUpO1xyXG4gICAgICAgIGN2LnNldENhbnZhc05lc3RUaGVybW9zdGF0UGFpbnRlcihzYyk7XHJcbiAgICAgICAgc2V0VGltZW91dCgoKSA9PiB7XHJcbiAgICAgICAgICBzYy5pbnB1dHMubG9hZGluZ1N0YXRlID0gXCJMb2FkZWRcIjtcclxuICAgICAgICAgIHNjLm9uSW5wdXRzVXBkYXRlZCgpO1xyXG4gICAgICAgIH0sIDUwMDApO1xyXG4gICAgICB9XHJcblxyXG4gICAgICBpZiAoaXNTbWFydGVycGxhblByb21vdGlvbmFsVmlkZW8pIHtcclxuICAgICAgICAvLyBUT0RPOiB1c2UgYmluZFBhdGggaW5zdGVhZCB1c2luZyBNUCBzZGsgY2xhc3NlcyAoc2VlIFNlY3VyaXR5IENhbWVyYSBleGFtcGxlKVxyXG4gICAgICAgIGNvbnN0IHNjID0gbmV3IFR2UGxheWVyKCk7XHJcbiAgICAgICAgc2Muc2V0Q29tcG9uZW50KGNvbXBvbmVudCk7XHJcbiAgICAgICAgc2Mub25Jbml0KG1vZGVsTm9kZSk7XHJcbiAgICAgICAgc2V0VGltZW91dCgoKSA9PiB7XHJcbiAgICAgICAgICBzYy5pbnB1dHMubG9hZGluZ1N0YXRlID0gXCJMb2FkZWRcIjtcclxuICAgICAgICAgIHNjLm9uSW5wdXRzVXBkYXRlZCgpO1xyXG4gICAgICAgIH0sIDUwMDApO1xyXG4gICAgICB9XHJcblxyXG4gICAgICBzY2VuZU9iamVjdC5zdGFydCgpO1xyXG4gICAgICByZXNvbHZlKHRoaXMubGFzdE9iamVjdDNEKTtcclxuICAgIH0pO1xyXG4gIH1cclxuXHJcbiAgdG9nZ2xlT2JqZWN0VmlzaWJpbGl0eShvYmplY3RJZDogYW55KXtcclxuICAgIGxldCBvYmogPSB0aGlzLmRpY3Rpb25uYXJ5T2JqZWN0czNELmdldChvYmplY3RJZCk7XHJcbiAgICBvYmoub2JqM0QudmlzaWJsZSA9ICFvYmoub2JqM0QudmlzaWJsZTtcclxuICB9XHJcblxyXG4gIGlzT2JqZWN0VmlzaWJsZShvYmplY3RJZDogYW55KTogYm9vbGVhbiB7XHJcbiAgICBsZXQgb2JqID0gdGhpcy5kaWN0aW9ubmFyeU9iamVjdHMzRC5nZXQob2JqZWN0SWQpO1xyXG4gICAgcmV0dXJuIG9iai5vYmozRC52aXNpYmxlO1xyXG4gIH1cclxuXHJcbiAgYXN5bmMgcG9pbnRDYW1lcmFUbzNET2JqZWN0KG9iamVjdElkOiBhbnkpe1xyXG4gICAgbGV0IG9iaiA9IHRoaXMuZGljdGlvbm5hcnlPYmplY3RzM0QuZ2V0KG9iamVjdElkKTtcclxuXHJcbiAgICAvL1dlIGNyZWF0ZSBhIHRlbXBvcmFyeSBUYWdcclxuICAgIGNvbnN0IHBvaU9iamVjdCA9IHtcclxuICAgICAgY29vcmRpbmF0ZTogSlNPTi5zdHJpbmdpZnkob2JqLm9iajNELnBvc2l0aW9uKSxcclxuICAgICAgdHlwZTogUG9pVHlwZS5PQkpFQ1QzRCxcclxuICAgICAgZWxlbWVudElEOiBvYmplY3RJZCwgLy90b2RvOiBiZSBjYXJlZnVsIHdpdGggdGhpc1xyXG4gICAgfSBhcyBQT0k7XHJcbiAgICBjb25zdCBvYmplY3REYiA9IHtpZDogb2JqZWN0SWR9IGFzIERiT2JqZWN0VHlwZTtcclxuXHJcbiAgICB0cnl7XHJcbiAgICAgIGF3YWl0IHRoaXMuY3JlYXRlTWF0dGVydGFnRnJvbVBPSShQb2lUeXBlLk9CSkVDVDNELCBvYmplY3REYiwgcG9pT2JqZWN0KTtcclxuICAgIH1jYXRjaChlcnI6IGFueSl7fVxyXG5cclxuICAgIC8vTm90IHJlYWxseSBuZWNlc3NhcnkgYW55bW9yZSBzaW5jZSB0aGUgdGFnIHdpbGwgZGlzYXBwZWFyIHF1aWNrXHJcbiAgICAvL3RoaXMuc2RrLlRhZy5lZGl0T3BhY2l0eShtYXR0ZXJ0YWdJRCwgMC4wKTsvL29wYWNpdHkpO1xyXG4gICAgLy90aGlzLnNkay5UYWcuYWxsb3dBY3Rpb24obWF0dGVydGFnSUQsIHt9KTsgLy9kaXNhYmxlcyBldmVyeSBhY3Rpb25cclxuXHJcbiAgICBsZXQgcmVzdWx0ID0gdGhpcy5nZXRUYWdGcm9tRWxlbWVudElkKG9iamVjdElkKTtcclxuXHJcbiAgICBhd2FpdCB0aGlzLmdvVG9UYWcocmVzdWx0LnRhZyk7XHJcbiAgICB0aGlzLmRlbGV0ZUxhc3RNYXR0ZXJ0YWcoKTtcclxuICB9XHJcblxyXG4gIGdldFNjZW5lTm9kZUZyb21PYmplY3QzRElkKHV1aWQ6IHN0cmluZyk6IGFueSB7XHJcbiAgICByZXR1cm4gdGhpcy5kaWN0aW9ubmFyeVNjZW5lT2JqZWN0czNELmdldCh1dWlkKTtcclxuICB9XHJcblxyXG4gIGFzeW5jIGRpc3BsYXlBemltdXRhbENyb3duKCl7XHJcbiAgICBpZih0aGlzLmF6aW11dGhhbENyb3duKXtcclxuICAgICAgdGhpcy5hemltdXRoYWxDcm93bi5vYmozRC5wb3NpdGlvbi5zZXQodGhpcy5wb3NlQ2FtZXJhLnBvc2l0aW9uLngsdGhpcy5wb3NlQ2FtZXJhLnBvc2l0aW9uLnksdGhpcy5wb3NlQ2FtZXJhLnBvc2l0aW9uLnopXHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBhc3luYyBhdHRhY2hHaXptb0NvbnRyb2xUbzNET2JqZWN0KFxyXG4gICAgbW9kZWxOb2RlOiBhbnksXHJcbiAgICBzY2VuZU9iamVjdDogYW55LFxyXG4gICAgbW9kZTogJ3RyYW5zbGF0ZScgfCAncm90YXRlJyB8ICdzY2FsZScsXHJcbiAgICB2aXNpYmxlOiBib29sZWFuLFxyXG4gICAgaXNOZXdPYmplY3Q6IGJvb2xlYW5cclxuICApOiBQcm9taXNlPGFueT4ge1xyXG4gICAgLy8gQ3JlYXRlIGEgc2NlbmUgbm9kZSB3aXRoIGEgdHJhbnNmb3JtIGNvbnRyb2wgY29tcG9uZW50LlxyXG4gICAgbGV0IG5vZGUgPSBudWxsO1xyXG4gICAgbm9kZSA9IHNjZW5lT2JqZWN0LmFkZE5vZGUoKTtcclxuICAgIGlmICghbm9kZSkge1xyXG4gICAgICBjb25zdCBbc2NlbmVPYmplY3RdID0gYXdhaXQgdGhpcy5zZGsuU2NlbmUuY3JlYXRlT2JqZWN0cygxKTtcclxuICAgICAgbm9kZSA9IHNjZW5lT2JqZWN0LmFkZE5vZGUoKTtcclxuICAgIH1cclxuXHJcbiAgICBjb25zdCBteUNvbnRyb2wgPSBub2RlLmFkZENvbXBvbmVudCgnbXAudHJhbnNmb3JtQ29udHJvbHMnKTtcclxuICAgIG5vZGUuc3RhcnQoKTtcclxuICAgIC8vXHJcbiAgICAvLyAvLyBNYWtlIHRoZSB0cmFuc2Zvcm0gY29udHJvbCB2aXNpYmxlIHNvIHRoYXQgdGhlIHVzZXIgY2FuIG1hbmlwdWxhdGUgdGhlIGNvbnRyb2wgc2VsZWN0aW9uLlxyXG4gICAgbXlDb250cm9sLnRyYW5zZm9ybUNvbnRyb2xzLnZpc2libGUgPSB2aXNpYmxlO1xyXG4gICAgLy9cclxuICAgIC8vIC8vIEF0dGFjaCB0aGUgbW9kZWwgdG8gdGhlIHRyYW5zZm9ybSBjb250cm9sXHJcbiAgICBteUNvbnRyb2wuaW5wdXRzLnNlbGVjdGlvbiA9IG1vZGVsTm9kZTtcclxuICAgIC8vXHJcbiAgICAvLyAvLyBzZXQgJ3RyYW5zbGF0ZScgbW9kZSB0byBwb3NpdGlvbiB0aGUgc2VsZWN0aW9uLlxyXG4gICAgbXlDb250cm9sLmlucHV0cy5tb2RlID0gbW9kZTtcclxuICAgIG1vZGVsTm9kZS5vYmozRC5jb250cm9scyA9IG15Q29udHJvbDsgLy8gc3RvcmUgZ2l6bW9DdHJsIGluc2lkZSBvYmplY3RcclxuICAgIGlmKGlzTmV3T2JqZWN0KXsgLy9pIGtlZXAgdGhlIGN1cnJlbnQgc29sdXRpb24gZm9yIG5ldyBvYmplY3RzXHJcbiAgICAgIGlmICghdGhpcy5sYXN0T2JqZWN0M0QgfHwgIXRoaXMubGFzdE9iamVjdDNELmNvbnRyb2xzKSB7XHJcbiAgICAgICAgdHJ5IHtcclxuICAgICAgICAgIG1vZGVsTm9kZS5vYmozRC51dWlkID0gdGhpcy5sYXN0T2JqZWN0M0QudXVpZCB8fCB0aGlzLmxhc3RPYmplY3QzRC5pZDtcclxuICAgICAgICB9IGNhdGNoIChlKSB7XHJcbiAgICAgICAgICBjb25zb2xlLmxvZyhgaWQgb2JqIGluIFNjZW5lIHdhcyBub3QgYXNzaWduZWQgdG8gaWQgZnJvbSBEQiBzaW5jZWApO1xyXG4gICAgICAgIH1cclxuICAgICAgICB0aGlzLmxhc3RPYmplY3QzRCA9IG1vZGVsTm9kZS5vYmozRDtcclxuICAgICAgfVxyXG4gICAgfWVsc2V7Ly9vYmplY3RzIGFscmVhZHkgaW4gcGxhY2UgaGF2ZSB0byBiZWNvbWUgdGhlIFwibGFzdE9iamVjdFwiIChpIHRoaW5rPylcclxuICAgICAgY29uc29sZS5sb2coXCJpbiBteSBzb2x1dGlvbiAhXCIpO1xyXG4gICAgICBjb25zb2xlLmxvZyhtb2RlbE5vZGUpO1xyXG4gICAgICBjb25zb2xlLmxvZyhtb2RlbE5vZGUub2JqM0QudXVpZCk7XHJcbiAgICAgIHRoaXMubGFzdE9iamVjdDNEID0gbW9kZWxOb2RlLm9iajNEO1xyXG4gICAgfVxyXG5cclxuICAgIHJldHVybiBtb2RlbE5vZGU7XHJcbiAgfVxyXG5cclxuICByZW1vdmVHaXptb0Zyb21MYXN0T2JqZWN0KCk6IHZvaWQge1xyXG4gICAgdGhpcy5sYXN0T2JqZWN0M0QuY29udHJvbHMudHJhbnNmb3JtQ29udHJvbHMudmlzaWJsZSA9IGZhbHNlO1xyXG4gICAgdGhpcy5sYXN0T2JqZWN0M0QuY29udHJvbHMudHJhbnNmb3JtQ29udHJvbHMuZGlzcG9zZSgpO1xyXG4gICAgdGhpcy5sYXN0T2JqZWN0M0QuY29udHJvbHMgPSBudWxsO1xyXG4gIH1cclxuXHJcbiAgdG9nZ2xlVmlld0ZydXN0dW0oKTogdm9pZCB7XHJcbiAgICB0aGlzLnNlY3VyaXR5Q2FtZXJhQW5pbWF0b3IudG9nZ2xlVmlld0ZydXN0dW0oKTtcclxuICB9XHJcblxyXG4gLypwdWJsaWMgc2V0M0RPYmplY3RNb2RlKG1vZGVsTm9kZTogYW55LCBtb2RlPzogc3RyaW5nKSB7XHJcbiAgIGlmIChtb2RlKSB7XHJcbiAgICAgdGhpcy5vYmplY3RDb250cm9sLmlucHV0cy5zZWxlY3Rpb24gPSBtb2RlbE5vZGU7XHJcbiAgICAgdGhpcy5vYmplY3RDb250cm9sLmlucHV0cy52aXNpYmxlID0gdHJ1ZTtcclxuICAgICB0aGlzLm9iamVjdENvbnRyb2wuaW5wdXRzLm1vZGUgPSBtb2RlO1xyXG5cclxuICAgICBzZXRJbnRlcnZhbCgoKSA9PiB7XHJcbiAgICAgICBjb25zb2xlLmxvZyhtb2RlbE5vZGUpO1xyXG4gICAgIH0sIDUwMDApO1xyXG5cclxuICAgfSBlbHNlIHtcclxuICAgICB0aGlzLm9iamVjdENvbnRyb2wuaW5wdXRzLnZpc2libGUgPSB0cnVlO1xyXG4gICB9XHJcbiB9Ki9cclxufVxyXG4iXX0=
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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWF0dGVycG9ydC5zZXJ2aWNlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvbmd4LXNtYXJ0ZXJwbGFuLWNvcmUvc3JjL2xpYi9zZXJ2aWNlcy9tYXR0ZXJwb3J0LnNlcnZpY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFDLE1BQU0sRUFBRSxVQUFVLEVBQVMsTUFBTSxlQUFlLENBQUM7QUFFekQsT0FBTyxFQUFDLE9BQU8sRUFBQyxNQUFNLE1BQU0sQ0FBQztBQUM3QiwyQ0FBMkM7QUFDM0MsT0FBTyxFQUNMLDJCQUEyQixFQUMzQixlQUFlLEVBQ2YsSUFBSSxHQUNMLE1BQU0sb0JBQW9CLENBQUM7QUFDNUIsT0FBTyxFQUFDLGFBQWEsRUFBQyxNQUFNLGtCQUFrQixDQUFDO0FBQy9DLE9BQU8sRUFFTCxXQUFXLEVBRVgsbUJBQW1CLEVBRW5CLE9BQU8sRUFDUCxRQUFRLEVBQ1IsU0FBUyxFQUNULGtCQUFrQixHQUNuQixNQUFNLGtCQUFrQixDQUFDO0FBQzFCLE9BQU8sRUFBQyxRQUFRLEVBQUMsTUFBTSxPQUFPLENBQUM7QUFJL0IsT0FBTyxFQUFDLFVBQVUsRUFBQyxNQUFNLGtCQUFrQixDQUFDO0FBRzVDLE9BQU8sRUFBQyxjQUFjLEVBQUMsTUFBTSx5REFBeUQsQ0FBQztBQUN2RixPQUFPLEVBQUMsYUFBYSxFQUFDLE1BQU0sd0RBQXdELENBQUM7QUFDckYsT0FBTyxFQUFDLGNBQWMsRUFBQyxNQUFNLHlEQUF5RCxDQUFDO0FBR3ZGLE9BQU8sRUFBQyxRQUFRLEVBQUMsTUFBTSw2Q0FBNkMsQ0FBQzs7Ozs7QUF3QnJFLE1BQU0sT0FBTyxpQkFBaUI7SUFvSjVCLFlBQ29CLE1BQWMsRUFDeEIsTUFBYyxFQUNkLFdBQTJCLEVBQzNCLGlCQUF3QyxFQUN4QyxNQUFjO1FBSGQsV0FBTSxHQUFOLE1BQU0sQ0FBUTtRQUNkLGdCQUFXLEdBQVgsV0FBVyxDQUFnQjtRQUMzQixz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QUN2QixJQUFJLENBQUMsWUFBWSxDQUFDLFFBQVEsQ0FBQyxpQkFBaUIsQ0FBQyxPQUFPLEdBQUcsS0FBSyxDQUFDO1FBQzdELElBQUksQ0FBQyxZQUFZLENBQUMsUUFBUSxDQUFDLGlCQUFpQixDQUFDLE9BQU8sRUFBRSxDQUFDO1FBQ3ZELElBQUksQ0FBQyxZQUFZLENBQUMsUUFBUSxHQUFHLElBQUksQ0FBQztJQUNwQyxDQUFDO0lBRUQsaUJBQWlCO1FBQ2YsSUFBSSxDQUFDLHNCQUFzQixDQUFDLGlCQUFpQixFQUFFLENBQUM7SUFDbEQsQ0FBQzs7OEdBbDlEVSxpQkFBaUIsa0JBcUpsQixRQUFRO2tIQXJKUCxpQkFBaUIsY0FGaEIsTUFBTTsyRkFFUCxpQkFBaUI7a0JBSDdCLFVBQVU7bUJBQUM7b0JBQ1YsVUFBVSxFQUFFLE1BQU07aUJBQ25COzswQkFzSkksTUFBTTsyQkFBQyxRQUFRIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtJbmplY3QsIEluamVjdGFibGUsIE5nWm9uZX0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQge0FjdGl2YXRlZFJvdXRlLCBSb3V0ZXJ9IGZyb20gJ0Bhbmd1bGFyL3JvdXRlcic7XG5pbXBvcnQge1N1YmplY3R9IGZyb20gJ3J4anMnO1xuLy9pbXBvcnQgKiBhcyBzZXJpYWxpanNlIGZyb20gXCJzZXJpYWxpanNlXCI7XG5pbXBvcnQge1xuICBnZXREaXN0YW5jZUJldHdlZW5Ud29Qb2ludHMsXG4gIHBvaVR5cGVUb1N0cmluZyxcbiAgd2FpdCxcbn0gZnJvbSAnLi4vaGVscGVycy5zZXJ2aWNlJztcbmltcG9ydCB7TWF0dGVydGFnRGF0YX0gZnJvbSAnLi4vbWF0dGVydGFnRGF0YSc7XG5pbXBvcnQge1xuICBEYk9iamVjdFR5cGUsXG4gIEZlYXR1cmVUeXBlLFxuICBJT2JqZWN0M0QsXG4gIE1hdHRlcnRhZ0FjdGlvbk1vZGUsXG4gIFBPSSxcbiAgUG9pVHlwZSxcbiAgU3BNb2R1bGUsXG4gIFRhZ0FjdGlvbixcbiAgVmlld2VySW50ZXJhY3Rpb25zLFxufSBmcm9tICcuLi90eXBlcy5zZXJ2aWNlJztcbmltcG9ydCB7T2JqZWN0M0R9IGZyb20gJ3RocmVlJztcbmltcG9ydCB7QmFzZVRhZ1NlcnZpY2V9IGZyb20gJy4vdGFnLnNlcnZpY2UnO1xuaW1wb3J0IHtCYXNlVmlzaWJpbGl0eVNlcnZpY2V9IGZyb20gJy4vYmFzZVZpc2liaWxpdHkuc2VydmljZSc7XG5pbXBvcnQge0NvbmZpZ30gZnJvbSAnLi4vY29uZmlnJztcbmltcG9ydCB7Q2FtZXJhTW9kZX0gZnJvbSAnLi4vdHlwZXMuc2VydmljZSc7XG5pbXBvcnQge0lTY2VuZU5vZGUsIENvbXBvbmVudE91dHB1dH0gZnJvbSBcIi4uL21hdHRlcnBvcnQtZXh0ZW5zaW9ucy9zY2VuZS1jb21wb25lbnQvU2NlbmVDb21wb25lbnRcIjtcbmltcG9ydCB7U2VjdXJpdHlDYW1lcmF9IGZyb20gJy4uL21hdHRlcnBvcnQtZXh0ZW5zaW9ucy9zZWN1cml0eS1jYW1lcmEvU2VjdXJpdHlDYW1lcmEnO1xuaW1wb3J0IHtOZXN0VGhlcm1vc3RhdH0gZnJvbSAnLi4vbWF0dGVycG9ydC1leHRlbnNpb25zL25lc3QtdGhlcm1vc3RhdC9OZXN0VGhlcm1vc3RhdCc7XG5pbXBvcnQge1BsYW5lUmVuZGVyZXJ9IGZyb20gJy4uL21hdHRlcnBvcnQtZXh0ZW5zaW9ucy9uZXN0LXRoZXJtb3N0YXQvUGxhbmVSZW5kZXJlcic7XG5pbXBvcnQge0NhbnZhc1JlbmRlcmVyfSBmcm9tIFwiLi4vbWF0dGVycG9ydC1leHRlbnNpb25zL25lc3QtdGhlcm1vc3RhdC9DYW52YXNSZW5kZXJlclwiO1xuaW1wb3J0IHtWaWRlb1JlbmRlcmVyfSBmcm9tIFwiLi4vbWF0dGVycG9ydC1leHRlbnNpb25zL3ZpZGVvLXJlbmRlcmVyL1ZpZGVvUmVuZGVyZXJcIjtcbmltcG9ydCB7SGxzTG9hZGVyfSBmcm9tIFwiLi4vbWF0dGVycG9ydC1leHRlbnNpb25zL2hzbC1sb2FkZXIvSGxzTG9hZGVyXCI7XG5pbXBvcnQge1R2UGxheWVyfSBmcm9tIFwiLi4vbWF0dGVycG9ydC1leHRlbnNpb25zL3R2LXBsYXllci9UdlBsYXllclwiO1xuXG4vLyBpbXBvcnQge0NhbnZhc0ltYWdlfSBmcm9tIFwiLi4vbWF0dGVycG9ydC1leHRlbnNpb25zL25lc3QtdGhlcm1vc3RhdC9DYW52YXNJbWFnZVwiO1xuXG4vKipcbiAqIEN1c3RvbSBUaHJlZWpzIE9iamVjdCAzRCBpbnRlcmZhY2VcbiAqL1xuaW50ZXJmYWNlIFRocmVlSlNPYmplY3QzRCB7XG4gIGlkOiBzdHJpbmc7XG4gIHV1aWQ/OiBzdHJpbmc7XG4gIHBvc2l0aW9uPzogeyB4OiBudW1iZXIsIHk6IG51bWJlciwgejogbnVtYmVyIH1cbiAgcm90YXRpb24/OiB7IHg6IG51bWJlciwgeTogbnVtYmVyLCB6OiBudW1iZXIgfVxuICBzY2FsZT86IHsgeDogbnVtYmVyLCB5OiBudW1iZXIsIHo6IG51bWJlciB9XG59XG5cbmRlY2xhcmUgZ2xvYmFsIHtcbiAgaW50ZXJmYWNlIFdpbmRvdyB7XG4gICAgTVBfU0RLOiB7IGNvbm5lY3Q6IEZ1bmN0aW9uIH07XG4gIH1cbn1cblxuQEluamVjdGFibGUoe1xuICBwcm92aWRlZEluOiAncm9vdCcsXG59KVxuZXhwb3J0IGNsYXNzIE1hdHRlcnBvcnRTZXJ2aWNlIHtcblxuICBwcml2YXRlIHNsb3RzOiBhbnlbXSA9IFtdOy8vU2xvdE5vZGVbXSA9IFtdO1xuXG4gIHByaXZhdGUgbm9kZXM6IElTY2VuZU5vZGVbXSA9IFtdO1xuXG4gIHB1YmxpYyBzZGs6IGFueTtcblxuICBwcml2YXRlIGNvbnRhaW5lcjogYW55O1xuXG4gIC8vIFBvc2l0aW9uIGNhbWVyYVxuICBwcml2YXRlIHBvc2VNYXR0ZXJwb3J0OiBhbnk7XG5cbiAgcHVibGljIHBvc2VDYW1lcmE6IHsgcm90YXRpb246IGFueTsgcG9zaXRpb246IGFueTsgc3dlZXA6IGFueSB9O1xuICBwdWJsaWMgbGFzdENhbWVyYVBvc2l0aW9uOiBhbnkgPSB7eDowLjAseTowLjAsejowLjB9O1xuXG4gIHByaXZhdGUgYXppbXV0aGFsQ3Jvd246YW55O1xuICAvLyBQb2ludGVyIHRyaWNrXG4gIHByaXZhdGUgcG9pbnRlckJ1dHRvbjogYW55O1xuXG4gIC8vIERpc3BsYXkgYW5kIGdldCBjdXJyZW50IHBvc2l0aW9uIG9mIGN1cnNvciAoZm9yIEFkbWlucyBvbmx5KVxuICBwcml2YXRlIGdldEN1cnNvclBvc2l0aW9uQnV0dG9uOiBhbnk7XG4gIHByaXZhdGUgY3Vyc29yUG9zaXRpb25CdXR0b25EaXNwbGF5ZWQgPSBmYWxzZTtcbiAgcHJpdmF0ZSBpbnRlcnZhbEN1cnNvclBvaW50ZXJQb3NpdGlvbjogYW55O1xuICBwcml2YXRlIHRleHREaXNwbGF5Q3Vyc29yUG9zaXRpb25QYW5lbDogYW55O1xuXG4gIHByaXZhdGUgb2xkUG9zZU1hdHRlcnBvcnRQb3NpdGlvbjogYW55O1xuICAvLyBNZWFzdXJlIG1vZGVcbiAgcHJpdmF0ZSBpc01lYXN1cmVNb2RlT24gPSBmYWxzZTtcblxuICBwcml2YXRlIGludGVyYWN0aW9uTW9kZTogbnVtYmVyID0gVmlld2VySW50ZXJhY3Rpb25zLkRFRkFVTFQ7XG5cbiAgLy8gTGlzdCBvZiBjcmVhdGVkIE1hdHRlcnRhZyBJRHMgaW4gdGhlIGN1cnJlbnQgdmlld2VyIHNlc3Npb25cbiAgcHJpdmF0ZSBtYXR0ZXJ0YWdJRHM6IEFycmF5PHN0cmluZz4gPSBbXTtcblxuICAvLyBEaWN0aW9ubmFyeSBvZiBNYXR0ZXJ0YWdJRCBhbmQgaXRzIGRhdGEgKG1hdHRlcnRhZ0RhdGEpXG4gIHByaXZhdGUgZGljdGlvbm5hcnlUYWdzOiBNYXA8c3RyaW5nLCBNYXR0ZXJ0YWdEYXRhPiA9IG5ldyBNYXAoKTtcblxuICBwcml2YXRlIGRpY3Rpb25uYXJ5T2JqZWN0czNEOiBNYXA8c3RyaW5nLCBhbnk+ID0gbmV3IE1hcCgpO1xuXG4gIHByaXZhdGUgZGljdGlvbm5hcnlTY2VuZU9iamVjdHMzRDogTWFwPHN0cmluZywgYW55PiA9IG5ldyBNYXAoKTtcblxuICBwdWJsaWMgdGhyZWVKU1NjZW5lOiBhbnk7IC8vIGdsb2JhbCByb290IHNjZW5lIChub3QgdXNlZCBub3chKVxuXG4gIHByaXZhdGUgbGFzdE1lYXN1cmUgPSBbXTtcblxuICBwcml2YXRlIGRpc3RhbmNlc0xhc3RNZWFzdXJlOiBudW1iZXJbXSA9IFtdO1xuXG4gIHByaXZhdGUgcmVzb2x1dGlvbiA9IHtcbiAgICB3aWR0aDogNTAwLFxuICAgIGhlaWdodDogNjAwLFxuICB9O1xuXG4gIHByaXZhdGUgdmlzaWJpbGl0eSA9IHtcbiAgICBtYXR0ZXJ0YWdzOiBmYWxzZSxcbiAgICBzd2VlcHM6IHRydWUsXG4gIH07XG5cbiAgcHVibGljIHRhZ3NBdHRhY2htZW50czogT2JqZWN0ID0ge307XG5cbiAgcHJpdmF0ZSBsYXN0U2NyZWVuc2hvdFVyaTogYW55O1xuXG4gIHB1YmxpYyBzd2VlcHM6IEFycmF5PHN0cmluZz4gfCBudWxsO1xuXG4gIHB1YmxpYyBjdXJyZW50U3dlZXA6IFN1YmplY3Q8c3RyaW5nPiA9IG5ldyBTdWJqZWN0KCk7XG5cbiAgLy9jYW1lcmEgcG9zaXRpb24gd2l0aCByb3RhdGlvblxuICBwdWJsaWMgY3VycmVudENhbWVyYVBvc2U6IFN1YmplY3Q8YW55PiA9IG5ldyBTdWJqZWN0KCk7XG5cbiAgcHJpdmF0ZSBmbG9vcnM/OiBBcnJheTx7IGlkOiBzdHJpbmc7IG5hbWU6IHN0cmluZzsgc2VxdWVuY2U6IG51bWJlciB9PiB8IG51bGw7XG5cbiAgcHJpdmF0ZSBfY3VycmVudFNwYWNlSUQ6IHN0cmluZztcblxuICBwcml2YXRlIGxhc3RPYmplY3QzRDogYW55OyAvLyBUaHJlZSBKUyBvYmplY3RcblxuICBwcml2YXRlIGN1cnJlbnRGbG9vcjtcblxuICBwdWJsaWMgZ2V0IGN1cnJlbnRTcGFjZUlEKCk6IHN0cmluZyB7XG4gICAgcmV0dXJuIHRoaXMuX2N1cnJlbnRTcGFjZUlEO1xuICB9XG5cbiAgcHVibGljIHNldCBjdXJyZW50U3BhY2VJRCh2YWx1ZTogc3RyaW5nKSB7XG4gICAgdGhpcy5fY3VycmVudFNwYWNlSUQgPSB2YWx1ZTtcbiAgfVxuXG4gIHRpbWVyUG9pbnRlcjogYW55O1xuXG4gIGZvcmJpZGRlblN3ZWVwczogc3RyaW5nW10gPSBbXTtcblxuICBwdWJsaWMgdGFnQWN0aW9uOiBTdWJqZWN0PHsgYWN0aW9uOiBzdHJpbmc7IGRhdGE6IHN0cmluZyB9PiA9IG5ldyBTdWJqZWN0KCk7XG5cbiAgcHVibGljIG1hdHRlcnRhZ1RvRm9sbG93OiBzdHJpbmcgfCBudWxsO1xuXG4gIHRhZ1NlcnZpY2U6IEJhc2VUYWdTZXJ2aWNlO1xuXG4gIGNvbmZpZzogQ29uZmlnO1xuXG4gIHB1YmxpYyBpblRyYW5zaXRpb25Nb2RlID0gZmFsc2U7XG5cbiAgcHVibGljIGluVHJhbnNpdGlvblN3ZWVwID0gZmFsc2U7XG5cbiAgcHJpdmF0ZSBub0xpZ2h0Rm9yT2JqZWN0cyA9IHRydWU7XG5cbiAgcHVibGljIGN1cnJlbnRDYW1lcmFNb2RlOiBDYW1lcmFNb2RlID0gQ2FtZXJhTW9kZS5PVVRTSURFO1xuXG4gIHB1YmxpYyBvbkNhbWVyYU1vZGVDaGFuZ2VkID0gbmV3IFN1YmplY3Q8Q2FtZXJhTW9kZT4oKTtcblxuICBwdWJsaWMgb25Hb1RvVGFnID0gbmV3IFN1YmplY3Q8c3RyaW5nPigpO1xuXG4gIHRhZ01lc3Nlbmdlck9uID0gZmFsc2U7XG5cbiAgU1BNb2R1bGU6IFNwTW9kdWxlO1xuXG4gIHB1YmxpYyBvYmplY3RDb250cm9sOiBhbnk7XG5cbiAgcHJpdmF0ZSBzZWN1cml0eUNhbWVyYUFuaW1hdG9yOiBhbnk7XG5cbiAgLyoqXG4gICAqIEFjdGlvbnMgb24gbGVmdCBjbGljayB3aGVuIHBvc2l0aW9uaW5nIG1hdHRlcnRhZyBpbiB2aXNpdFxuICAgKi9cbiAgcG9pbnRlckxlZnRDbGlja0hhbmRsZXIgPSAoKSA9PiB7XG4gICAgaWYgKHRoaXMubWF0dGVydGFnVG9Gb2xsb3cpIHtcbiAgICAgIGNvbnN0IG1hdHRlcnRhZ0RhdGEgPSB0aGlzLmRpY3Rpb25uYXJ5VGFncy5nZXQodGhpcy5tYXR0ZXJ0YWdUb0ZvbGxvdyk7XG4gICAgICBtYXR0ZXJ0YWdEYXRhLnNldFBvc2l0aW9uKHsuLi50aGlzLnBvc2VNYXR0ZXJwb3J0LnBvc2l0aW9ufSk7IC8vIGNvcHkhISBub3QgdGhlIHJlZmVyZW5jZVxuICAgICAgbWF0dGVydGFnRGF0YS5zZXROb3JtYWwoey4uLnRoaXMucG9zZU1hdHRlcnBvcnQubm9ybWFsfSk7IC8vIGNvcHkhISBub3QgdGhlIHJlZmVyZW5jZVxuICAgICAgdGhpcy5kaWN0aW9ubmFyeVRhZ3Muc2V0KHRoaXMubWF0dGVydGFnVG9Gb2xsb3csIG1hdHRlcnRhZ0RhdGEpO1xuICAgICAgdGhpcy51cGRhdGVNYXR0ZXJUYWdDb250ZW50Rm9yVGFnSUQodGhpcy5tYXR0ZXJ0YWdUb0ZvbGxvdyk7XG4gICAgfVxuICAgIHRoaXMub25WYWxpZGF0ZWRNYXR0ZXJ0YWcoKTtcbiAgfTtcblxuICBwb2ludGVyUmlnaHRDbGlja0hhbmRsZXIgPSAoZSkgPT4ge1xuICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICB0aGlzLmNhbmNlbEZvbGxvd2luZ0N1cnNvcigpO1xuICAgIGFsZXJ0KCdhY3Rpb24gY2FuY2VsbGVkJyk7XG4gIH07XG5cbiAgcG9pbnRlck1pZGRsZUNsaWNrSGFuZGxlciA9IChlKSA9PiB7XG4gICAgdGhpcy50ZXh0RGlzcGxheUN1cnNvclBvc2l0aW9uUGFuZWwuaW5uZXJIVE1MID0gYHBvc2l0aW9uOlxuICAgICAgICR7dGhpcy5wb2ludFRvU3RyaW5nKHRoaXMucG9zZU1hdHRlcnBvcnQucG9zaXRpb24pfVxcblxuICAgICAgIG5vcm1hbDpcbiAgICAgICAke3RoaXMucG9pbnRUb1N0cmluZyh0aGlzLnBvc2VNYXR0ZXJwb3J0Lm5vcm1hbCl9XFxuXG4gICAgICAgZmxvb3JJZDpcbiAgICAgICAke3RoaXMucG9zZU1hdHRlcnBvcnQuZmxvb3JJZH1gO1xuICAgIC8vIHRoaXMudGV4dERpc3BsYXlDdXJzb3JQb3NpdGlvblBhbmVsLnN0eWxlLmRpc3BsYXkgPSAndmlzaWJsZSc7XG4gICAgdGhpcy5nZXRDdXJzb3JQb3NpdGlvbkJ1dHRvbi5zdHlsZS5kaXNwbGF5ID0gJ25vbmUnO1xuICB9XG5cbiAgY29uc3RydWN0b3IoXG4gICAgQEluamVjdCgnY29uZmlnJykgY29uZmlnOiBDb25maWcsXG4gICAgcHJpdmF0ZSByb3V0ZXI6IFJvdXRlcixcbiAgICBwcml2YXRlIGFjdGl2ZVJvdXRlOiBBY3RpdmF0ZWRSb3V0ZSxcbiAgICBwcml2YXRlIHZpc2liaWxpdHlTZXJ2aWNlOiBCYXNlVmlzaWJpbGl0eVNlcnZpY2UsXG4gICAgcHJpdmF0ZSBuZ1pvbmU6IE5nWm9uZVxuICApIHtcbiAgICB0aGlzLmNvbmZpZyA9IGNvbmZpZztcblxuICAgIC8vIFRPRE86IG9ubHkgZm9yIGRldiFcbiAgICBpZiAoISF0aGlzLmdldEN1cnNvclBvc2l0aW9uQnV0dG9uICYmXG4gICAgICAoZG9jdW1lbnQubG9jYXRpb24uaHJlZi5pbmRleE9mKCdkZXYnKSAhPT0gLTEgfHwgZG9jdW1lbnQubG9jYXRpb24uaHJlZi5pbmRleE9mKCdsb2NhbGhvc3QnKSAhPT0gLTEpKSB7XG4gICAgICB0aGlzLmludGVydmFsQ3Vyc29yUG9pbnRlclBvc2l0aW9uID0gc2V0SW50ZXJ2YWwoKCkgPT4ge1xuICAgICAgICBpZiAoIXRoaXMucG9zZU1hdHRlcnBvcnQpIHtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBuZXh0U2hvdyA9IHRoaXMucG9zZU1hdHRlcnBvcnQudGltZSArIDEwMDA7XG4gICAgICAgIGlmIChuZXcgRGF0ZSgpLmdldFRpbWUoKSA+IG5leHRTaG93KSB7XG4gICAgICAgICAgaWYgKHRoaXMuY3Vyc29yUG9zaXRpb25CdXR0b25EaXNwbGF5ZWQpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBjb25zdCBzaXplID0ge1xuICAgICAgICAgICAgdzogdGhpcy5jb250YWluZXIuY2xpZW50V2lkdGgsXG4gICAgICAgICAgICBoOiB0aGlzLmNvbnRhaW5lci5jbGllbnRIZWlnaHQsXG4gICAgICAgICAgfTtcbiAgICAgICAgICBjb25zdCBjb29yZCA9IHRoaXMuc2RrLkNvbnZlcnNpb24ud29ybGRUb1NjcmVlbih0aGlzLnBvc2VNYXR0ZXJwb3J0LnBvc2l0aW9uLCB0aGlzLnBvc2VDYW1lcmEsIHNpemUpO1xuICAgICAgICAgIHRoaXMuZ2V0Q3Vyc29yUG9zaXRpb25CdXR0b24uc3R5bGUubGVmdCA9IGAke2Nvb3JkLnggLSAyNX1weGA7XG4gICAgICAgICAgdGhpcy5nZXRDdXJzb3JQb3NpdGlvbkJ1dHRvbi5zdHlsZS50b3AgPSBgJHtjb29yZC55IC0gMjJ9cHhgO1xuICAgICAgICAgIHRoaXMuZ2V0Q3Vyc29yUG9zaXRpb25CdXR0b24uc3R5bGUuZGlzcGxheSA9ICdibG9jayc7XG4gICAgICAgICAgLy8gdGhpcy50ZXh0RGlzcGxheUN1cnNvclBvc2l0aW9uUGFuZWwuc3R5bGUuZGlzcGxheSA9ICdub25lJztcbiAgICAgICAgICB0aGlzLmN1cnNvclBvc2l0aW9uQnV0dG9uRGlzcGxheWVkID0gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgfSwgNTAwKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogSW5pdGlhbGl6ZXMgTWF0dGVycG9ydCBhbmQgYWxsIGxpc3RlbmVycy9kYXRhXG4gICAqIEBwYXJhbSB0YWdTZXJ2aWNlIEJhc2VUYWdTZXJ2aWNlICh0byBpbmplY3QgaHRtbClcbiAgICogQHBhcmFtIG1vZHVsZSBTcE1vZHVsZSAoTXVzZXVtLCBJbW1vKSB0byBzdWJzY3JpYmUgb25seSB0byBuZWVkZWQgZnVuY3Rpb25ubmFsaXRpZXNcbiAgICogQHJldHVybnMgYm9vbGVhblxuICAgKi9cbiAgYXN5bmMgaW5pdFNkayhcbiAgICB0YWdTZXJ2aWNlOiBCYXNlVGFnU2VydmljZSxcbiAgICBtb2R1bGU6IFNwTW9kdWxlID0gU3BNb2R1bGUuSU1NT1xuICApOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICBpZiAodGhpcy5zZGspIHtcbiAgICAgIC8vIGNsZWFuIGlmIHNkayBpcyBydW5uaW5nIGFscmVhZHlcbiAgICAgIGF3YWl0IHRoaXMuYWN0aW9uX2RlbGV0ZV9hbGxfbWF0dGVydGFncygpO1xuICAgIH1cbiAgICB0aGlzLnRhZ1NlcnZpY2UgPSB0YWdTZXJ2aWNlO1xuICAgIHRoaXMuU1BNb2R1bGUgPSBtb2R1bGU7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgIC8vIFJldHJpZXZlIERPTSBlbGVtZW50c1xuICAgICAgdGhpcy5wb2ludGVyQnV0dG9uID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvcihcbiAgICAgICAgJyN2aWV3ZXItcG9pbnRlci10cmljaydcbiAgICAgICkgYXMgSFRNTEVsZW1lbnQ7XG4gICAgICB0aGlzLmNvbnRhaW5lciA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoJyN2aWV3ZXItbW9kdWxlJykgYXMgSFRNTEVsZW1lbnQ7XG4gICAgICBjb25zdCBpZnJhbWUgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKFxuICAgICAgICAnI3ZpZXdlci1tb2R1bGUnXG4gICAgICApIGFzIEhUTUxJRnJhbWVFbGVtZW50O1xuICAgICAgaWYgKCFpZnJhbWUpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICAvLyBBZGQgbGlzdGVuZXJzXG4gICAgICBpZiAodGhpcy5wb2ludGVyQnV0dG9uKSB7XG4gICAgICAgIHRoaXMucG9pbnRlckJ1dHRvbi5hZGRFdmVudExpc3RlbmVyKFxuICAgICAgICAgICdjbGljaycsXG4gICAgICAgICAgdGhpcy5wb2ludGVyTGVmdENsaWNrSGFuZGxlclxuICAgICAgICApO1xuICAgICAgICAvLyBjYW5jZWwgb24gcmlnaHQgY2xpY2tcbiAgICAgICAgdGhpcy5wb2ludGVyQnV0dG9uLmFkZEV2ZW50TGlzdGVuZXIoXG4gICAgICAgICAgJ2NvbnRleHRtZW51JyxcbiAgICAgICAgICB0aGlzLnBvaW50ZXJSaWdodENsaWNrSGFuZGxlclxuICAgICAgICApO1xuICAgICAgfVxuICAgICAgLy8gUmV0cmlldmUgRE9NIGVsZW1lbnRzXG4gICAgICB0aGlzLmdldEN1cnNvclBvc2l0aW9uQnV0dG9uID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvcihcbiAgICAgICAgJyNidXR0b24nXG4gICAgICApIGFzIEhUTUxFbGVtZW50O1xuICAgICAgdGhpcy50ZXh0RGlzcGxheUN1cnNvclBvc2l0aW9uUGFuZWwgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKFxuICAgICAgICAnI3RleHQnXG4gICAgICApIGFzIEhUTUxFbGVtZW50O1xuICAgICAgaWYgKHRoaXMuZ2V0Q3Vyc29yUG9zaXRpb25CdXR0b24pIHtcbiAgICAgICAgLy8gZ2V0IHBvc2l0aW9uIG9uIE1hdHRlcnBvcnQgXCJtb2RlbFwiIG9uIG1pZGRsZSBjbGlja1xuICAgICAgICB0aGlzLmdldEN1cnNvclBvc2l0aW9uQnV0dG9uLmFkZEV2ZW50TGlzdGVuZXIoXG4gICAgICAgICAgJ2NsaWNrJyxcbiAgICAgICAgICB0aGlzLnBvaW50ZXJNaWRkbGVDbGlja0hhbmRsZXJcbiAgICAgICAgKTtcbiAgICAgIH1cblxuICAgICAgLy8gTG9hZCBTREtcbiAgICAgIGNvbnNvbGUubG9nKCdMb2FkaW5nIE1hdHRlcnBvcnQgU0RLJyk7XG4gICAgICBjb25zdCBzaG93Y2FzZVdpbmRvdyA9IGlmcmFtZS5jb250ZW50V2luZG93O1xuICAgICAgaWZyYW1lLmFkZEV2ZW50TGlzdGVuZXIoXG4gICAgICAgICdsb2FkJyxcbiAgICAgICAgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICB0aGlzLnNkayA9IGF3YWl0IHNob3djYXNlV2luZG93Lk1QX1NESy5jb25uZWN0KFxuICAgICAgICAgICAgICBzaG93Y2FzZVdpbmRvdyxcbiAgICAgICAgICAgICAgJ3FuOXdzYXN1eTVoMmZ6cmJybjFuenIwaWQnLFxuICAgICAgICAgICAgICAnMy41J1xuICAgICAgICAgICAgKTtcbiAgICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICBjb25zb2xlLmVycm9yKGUpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIC8vIExvYWQgTWF0dGVydGFnIGljb25zIGFuZCBjdXN0b20gc3Vic2NyaXB0aW9uc1xuICAgICAgICAgIHN3aXRjaCAobW9kdWxlKSB7XG4gICAgICAgICAgICBjYXNlIFNwTW9kdWxlLklNTU86XG4gICAgICAgICAgICAgIHRoaXMuc2RrLkFzc2V0LnJlZ2lzdGVyVGV4dHVyZShcbiAgICAgICAgICAgICAgICAnaWNvbi10aWNrZXQnLFxuICAgICAgICAgICAgICAgIHRoaXMuY29uZmlnLm15X2NvbmZpZy5pY29uX3RpY2tldFxuICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICB0aGlzLnNkay5Bc3NldC5yZWdpc3RlclRleHR1cmUoXG4gICAgICAgICAgICAgICAgJ2ljb24tZXF1aXBtZW50JyxcbiAgICAgICAgICAgICAgICB0aGlzLmNvbmZpZy5teV9jb25maWcuaWNvbl9lcXVpcG1lbnRcbiAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgdGhpcy5zZGsuQXNzZXQucmVnaXN0ZXJUZXh0dXJlKFxuICAgICAgICAgICAgICAgICdpY29uLW1lYXN1cmUnLFxuICAgICAgICAgICAgICAgIHRoaXMuY29uZmlnLm15X2NvbmZpZy5pY29uX21lYXN1cmVcbiAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgdGhpcy5zZGsuQXNzZXQucmVnaXN0ZXJUZXh0dXJlKFxuICAgICAgICAgICAgICAgICdpY29uLWRhdGEnLFxuICAgICAgICAgICAgICAgIHRoaXMuY29uZmlnLm15X2NvbmZpZy5pY29uX2RhdGFcbiAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgdGhpcy5zZGsuQXNzZXQucmVnaXN0ZXJUZXh0dXJlKFxuICAgICAgICAgICAgICAgICdpY29uLW9iamVjdDNkJyxcbiAgICAgICAgICAgICAgICB0aGlzLmNvbmZpZy5teV9jb25maWcuaWNvbl9vYmplY3QzZFxuICAgICAgICAgICAgICApO1xuXG4gICAgICAgICAgICAgIHRoaXMuc2RrLk1lYXN1cmVtZW50cy5kYXRhLnN1YnNjcmliZSh7XG4gICAgICAgICAgICAgICAgb25BZGRlZDogZnVuY3Rpb24gKFxuICAgICAgICAgICAgICAgICAgaW5kZXg6IGFueSxcbiAgICAgICAgICAgICAgICAgIGl0ZW06IHsgcG9pbnRzOiBhbnkgfSxcbiAgICAgICAgICAgICAgICAgIGNvbGxlY3Rpb246IGFueVxuICAgICAgICAgICAgICAgICkge1xuICAgICAgICAgICAgICAgICAgLy8gY29uc29sZS5sb2coXG4gICAgICAgICAgICAgICAgICAvLyAgICAgXCJpdGVtIGFkZGVkIHRvIHRoZSBjb2xsZWN0aW9uXCIsXG4gICAgICAgICAgICAgICAgICAvLyAgICAgaW5kZXgsXG4gICAgICAgICAgICAgICAgICAvLyAgICAgaXRlbSxcbiAgICAgICAgICAgICAgICAgIC8vICk7XG4gICAgICAgICAgICAgICAgICAvLyB0aGlzLm1lYXN1cmVtZW50c1tpbmRleF0gPSBpdGVtO1xuICAgICAgICAgICAgICAgICAgdGhpcy5sYXN0TWVhc3VyZSA9IGl0ZW0ucG9pbnRzO1xuICAgICAgICAgICAgICAgIH0uYmluZCh0aGlzKSxcbiAgICAgICAgICAgICAgICBvbkNvbGxlY3Rpb25VcGRhdGVkOiBmdW5jdGlvbiAoY29sbGVjdGlvbjogYW55KSB7XG4gICAgICAgICAgICAgICAgICAvLyBjb25zb2xlLmxvZygndGhlIGVudGlyZSB1cC10by1kYXRlIGNvbGxlY3Rpb24nLCBjb2xsZWN0aW9uKTtcbiAgICAgICAgICAgICAgICAgIHRoaXMuZ2V0RGlzdGFuY2VGb3JMYXN0TWVhc3VyZW1lbnQoKTtcbiAgICAgICAgICAgICAgICB9LmJpbmQodGhpcyksXG4gICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICB0aGlzLnNkay5NZWFzdXJlbWVudHMubW9kZS5zdWJzY3JpYmUoXG4gICAgICAgICAgICAgICAgZnVuY3Rpb24gKG1lYXN1cmVtZW50TW9kZVN0YXRlOiB7IGFjdGl2ZTogYW55IH0pIHtcbiAgICAgICAgICAgICAgICAgIC8vIG1lYXN1cmVtZW50IG1vZGUgc3RhdGUgaGFzIGNoYW5nZWRcbiAgICAgICAgICAgICAgICAgIHRoaXMuaXNNZWFzdXJlTW9kZU9uID0gbWVhc3VyZW1lbnRNb2RlU3RhdGUuYWN0aXZlO1xuICAgICAgICAgICAgICAgICAgLy8gY29uc29sZS5sb2coJ0lzIG1lYXN1cmVtZW50IG1vZGUgY3VycmVudGx5IGFjdGl2ZT8gJywgbWVhc3VyZW1lbnRNb2RlU3RhdGUuYWN0aXZlKTtcbiAgICAgICAgICAgICAgICB9LmJpbmQodGhpcylcbiAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIFNwTW9kdWxlLk1VU0VVTTpcbiAgICAgICAgICAgICAgdGhpcy5zZGsuQXNzZXQucmVnaXN0ZXJUZXh0dXJlKFxuICAgICAgICAgICAgICAgICdpY29uLWRhdGEnLFxuICAgICAgICAgICAgICAgIHRoaXMuY29uZmlnLm15X2NvbmZpZy5pY29uX2RhdGFcbiAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIFNwTW9kdWxlLkhPVEVMOlxuICAgICAgICAgICAgICB0aGlzLnNkay5Bc3NldC5yZWdpc3RlclRleHR1cmUoXG4gICAgICAgICAgICAgICAgJ2ljb25fcm9vbV9hdmFpbGFibGUnLFxuICAgICAgICAgICAgICAgIHRoaXMuY29uZmlnLm15X2NvbmZpZy5pY29uX3Jvb21fYXZhaWxhYmxlXG4gICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgIHRoaXMuc2RrLkFzc2V0LnJlZ2lzdGVyVGV4dHVyZShcbiAgICAgICAgICAgICAgICAnaWNvbl9yb29tX3VuYXZhaWxhYmxlJyxcbiAgICAgICAgICAgICAgICB0aGlzLmNvbmZpZy5teV9jb25maWcuaWNvbl9yb29tX3VuYXZhaWxhYmxlXG4gICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgIHRoaXMuc2RrLkFzc2V0LnJlZ2lzdGVyVGV4dHVyZShcbiAgICAgICAgICAgICAgICAnaWNvbl9yb29tX2Nob3NlbicsXG4gICAgICAgICAgICAgICAgdGhpcy5jb25maWcubXlfY29uZmlnLmljb25fcm9vbV9jaG9zZW5cbiAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgdGhpcy5zZGsuQXNzZXQucmVnaXN0ZXJUZXh0dXJlKFxuICAgICAgICAgICAgICAgICdpY29uX3Jvb21fdmlld2VkJyxcbiAgICAgICAgICAgICAgICB0aGlzLmNvbmZpZy5teV9jb25maWcuaWNvbl9yb29tX3ZpZXdlZFxuICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIHRoaXMuc2RrLkFzc2V0LnJlZ2lzdGVyVGV4dHVyZShcbiAgICAgICAgICAgICdpY29uLXBvc2l0aW9uJyxcbiAgICAgICAgICAgIHRoaXMuY29uZmlnLm15X2NvbmZpZy5pY29uX3Bvc2l0aW9uXG4gICAgICAgICAgKTtcblxuICAgICAgICAgIC8vIEN1cnJlbnQgUm9vbSAodXNlZCBmb3IgZ2V0dGluZyBib3VuZGluZyBib3ggYW5kIGV2ZW50dWFsbHkgbGF6eSBsb2FkIG1hdHRlcnRhZyBvciBvYmplY3QzRCBpbnNpZGUgY3VycmVudCBSb29tKVxuICAgICAgICAgIHRoaXMuc2RrLlJvb20uY3VycmVudC5zdWJzY3JpYmUoKGN1cnJlbnRSb29tKSA9PiB7XG4gICAgICAgICAgICBjb25zb2xlLmxvZyhgaGVsbG8gY3VycmVudCBSb29tICR7SlNPTi5zdHJpbmdpZnkoY3VycmVudFJvb20pfWApO1xuICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgLy8gM0QgcG9zaXRpb24ncyBwb2ludGVyXG4gICAgICAgICAgdGhpcy5zZGsuUG9pbnRlci5pbnRlcnNlY3Rpb24uc3Vic2NyaWJlKFxuICAgICAgICAgICAgZnVuY3Rpb24gKGludGVyc2VjdGlvbjogYW55KSB7XG4gICAgICAgICAgICAgIHRoaXMucG9zZU1hdHRlcnBvcnQgPSBpbnRlcnNlY3Rpb247XG4gICAgICAgICAgICAgIHRoaXMucG9zZU1hdHRlcnBvcnQudGltZSA9IG5ldyBEYXRlKCkuZ2V0VGltZSgpO1xuICAgICAgICAgICAgICBpZiAoIXRoaXMub2xkUG9zZU1hdHRlcnBvcnRQb3NpdGlvbikge1xuICAgICAgICAgICAgICAgIHRoaXMub2xkUG9zZU1hdHRlcnBvcnRQb3NpdGlvbiA9IHtcbiAgICAgICAgICAgICAgICAgIHg6IDAsXG4gICAgICAgICAgICAgICAgICB5OiAwLFxuICAgICAgICAgICAgICAgICAgejogMCxcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgaWYgKFxuICAgICAgICAgICAgICAgIHRoaXMuaW50ZXJhY3Rpb25Nb2RlICE9PSBWaWV3ZXJJbnRlcmFjdGlvbnMuREVGQVVMVCAmJlxuICAgICAgICAgICAgICAgIHRoaXMubWF0dGVydGFnVG9Gb2xsb3dcbiAgICAgICAgICAgICAgKSB7XG4gICAgICAgICAgICAgICAgLy8gZm9sbG93IHRoZSBwb2ludGVyIGFuZCBjaGFuZ2VzIHRoZSBwb3NpdGlvbiBvZiB0aGUgbGFzdCB0YWdcbiAgICAgICAgICAgICAgICAvLyAod2UgYXJlIGFib3V0IHRvIHZhbGlkYXRlLCBidXQgaXQgZXhpc3RzIGluIHNkayBhbHJlYWR5KVxuICAgICAgICAgICAgICAgIHRoaXMuZW5hYmxlX2ZvbGxvd2luZ190YWcodGhpcy5tYXR0ZXJ0YWdUb0ZvbGxvdyk7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgaWYgKCEhdGhpcy5nZXRDdXJzb3JQb3NpdGlvbkJ1dHRvbiAmJiAhIXRoaXMuZ2V0Q3Vyc29yUG9zaXRpb25CdXR0b24uc3R5bGUgJiZcbiAgICAgICAgICAgICAgKGRvY3VtZW50LlVSTC5pbmRleE9mKCdodHRwczovL2Rldi5zbWFydGVycGxhbi5pbycpICE9PSAtMSB8fCBkb2N1bWVudC5sb2NhdGlvbi5ocmVmLmluZGV4T2YoJ2xvY2FsaG9zdCcpICE9PSAtMSkpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmdldEN1cnNvclBvc2l0aW9uQnV0dG9uLnN0eWxlLmRpc3BsYXkgPSAnbm9uZSc7XG4gICAgICAgICAgICAgICAgdGhpcy5jdXJzb3JQb3NpdGlvbkJ1dHRvbkRpc3BsYXllZCA9IGZhbHNlO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9LmJpbmQodGhpcylcbiAgICAgICAgICApO1xuXG4gICAgICAgICAgLy9DYW1lcmEgbW9kZVxuICAgICAgICAgIHRoaXMuc2RrLk1vZGUuY3VycmVudC5zdWJzY3JpYmUoKG1vZGUpID0+IHtcbiAgICAgICAgICAgIHRoaXMuaW5UcmFuc2l0aW9uU3dlZXAgPSBmYWxzZTtcbiAgICAgICAgICAgIHN3aXRjaCAobW9kZSkge1xuICAgICAgICAgICAgICBjYXNlICdtb2RlLmRvbGxob3VzZSc6XG4gICAgICAgICAgICAgICAgdGhpcy5jdXJyZW50Q2FtZXJhTW9kZSA9IENhbWVyYU1vZGUuRE9MTEhPVVNFO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICBjYXNlICdtb2RlLmZsb29ycGxhbic6XG4gICAgICAgICAgICAgICAgdGhpcy5jdXJyZW50Q2FtZXJhTW9kZSA9IENhbWVyYU1vZGUuRkxPT1JQTEFOO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICBjYXNlICdtb2RlLmluc2lkZSc6XG4gICAgICAgICAgICAgICAgdGhpcy5jdXJyZW50Q2FtZXJhTW9kZSA9IENhbWVyYU1vZGUuSU5TSURFO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICBjYXNlICdtb2RlLnRyYW5zaXRpb25pbmcnOlxuICAgICAgICAgICAgICAgIHRoaXMuY3VycmVudENhbWVyYU1vZGUgPSBDYW1lcmFNb2RlLlRSQU5TSVRJT05JTkc7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgdGhpcy5jdXJyZW50Q2FtZXJhTW9kZSA9IENhbWVyYU1vZGUuT1VUU0lERTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMub25DYW1lcmFNb2RlQ2hhbmdlZC5uZXh0KHRoaXMuY3VycmVudENhbWVyYU1vZGUpO1xuICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgLy8gQ2FtZXJhJ3Mgdmlld3BvaW50XG4gICAgICAgICAgdGhpcy5zZGsuQ2FtZXJhLnBvc2Uuc3Vic2NyaWJlKFxuICAgICAgICAgICAgZnVuY3Rpb24gc3Vic2NyKHBvc2U6IGFueSkge1xuICAgICAgICAgICAgICB0aGlzLnBvc2VDYW1lcmEgPSBwb3NlO1xuXG4gICAgICAgICAgICAgIHRoaXMuY3VycmVudENhbWVyYVBvc2UubmV4dChwb3NlKTtcbiAgICAgICAgICAgICAgLy8gY29uc29sZS5sb2coJ0N1cnJlbnQgcG9zaXRpb24gaXMgJywgcG9zZS5wb3NpdGlvbik7XG4gICAgICAgICAgICAgIC8vIGNvbnNvbGUubG9nKCdSb3RhdGlvbiBhbmdsZSBpcyAnLCBwb3NlLnJvdGF0aW9uKTtcbiAgICAgICAgICAgICAgLy8gY29uc29sZS5sb2coXCJTd2VlcCBVVUlEIGlzXCIsIHBvc2Uuc3dlZXApO1xuICAgICAgICAgICAgfS5iaW5kKHRoaXMpXG4gICAgICAgICAgKTtcblxuICAgICAgICAgIC8vIHN1YnNjcmliZSB0byBzd2VlcHNcbiAgICAgICAgICB0aGlzLnNkay5Td2VlcC5kYXRhLnN1YnNjcmliZSh7XG4gICAgICAgICAgICBvbkNvbGxlY3Rpb25VcGRhdGVkOiBmdW5jdGlvbiBzdWJzY3IoY29sbGVjdGlvbjoge30pIHtcbiAgICAgICAgICAgICAgLy8gY29uc29sZS5sb2coXCJTd2VlcCBjb2xsZWN0aW9uIHVwZGF0ZWRcIik7XG4gICAgICAgICAgICAgIHRoaXMuc3dlZXBzID0gT2JqZWN0LmtleXMoY29sbGVjdGlvbik7XG4gICAgICAgICAgICB9LmJpbmQodGhpcyksXG4gICAgICAgICAgfSk7XG5cbiAgICAgICAgICAvLyBzdWJzY3JpYmUgdG8gY3VycmVudCBzd2VlcFxuICAgICAgICAgIHRoaXMuc2RrLlN3ZWVwLmN1cnJlbnQuc3Vic2NyaWJlKFxuICAgICAgICAgICAgZnVuY3Rpb24gc3Vic2NyKGN1cnJlbnRTd2VlcDogeyBzaWQ6IHN0cmluZyB9KSB7XG4gICAgICAgICAgICAgIC8vIENoYW5nZSB0byB0aGUgY3VycmVudCBzd2VlcCBoYXMgb2NjdXJyZWQuXG4gICAgICAgICAgICAgIGlmIChjdXJyZW50U3dlZXAuc2lkID09PSAnJykge1xuICAgICAgICAgICAgICAgIC8vIGNvbnNvbGUubG9nKCdOb3QgY3VycmVudGx5IHN0YXRpb25lZCBhdCBhIHN3ZWVwIHBvc2l0aW9uJyk7XG4gICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgLy8gY29uc29sZS5sb2coXCJlbW1pdGluZyBzd2VlcFwiLCBjdXJyZW50U3dlZXAuc2lkKTtcbiAgICAgICAgICAgICAgICB0aGlzLmN1cnJlbnRTd2VlcC5uZXh0KGN1cnJlbnRTd2VlcC5zaWQpO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9LmJpbmQodGhpcylcbiAgICAgICAgICApO1xuXG4gICAgICAgICAgLy8gU3Vic2NyaWJlIHRvIEZsb29yIGRhdGFcbiAgICAgICAgICB0aGlzLnNkay5GbG9vci5kYXRhLnN1YnNjcmliZSh7XG4gICAgICAgICAgICBvbkNvbGxlY3Rpb25VcGRhdGVkOiBmdW5jdGlvbiB1cGQodGhpczogYW55LCBjb2xsZWN0aW9uOiBhbnkpIHtcbiAgICAgICAgICAgICAgdGhpcy5mbG9vcnMgPSBPYmplY3QudmFsdWVzKGNvbGxlY3Rpb24pO1xuICAgICAgICAgICAgfS5iaW5kKHRoaXMpLFxuICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgLy8gb24gdGFnIGNsaWNrIG9wZW4gZGV0YWlscyBwYWdlXG4gICAgICAgICAgdGhpcy5zZGsub24oJ3RhZy5jbGljaycsIChzaWQ6IHN0cmluZykgPT4ge1xuICAgICAgICAgICAgLy8gZ2V0IG9iamVjdCBvZiB0aGlzIHRhZ1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgY29uc3QgbWF0dGVydGFnRGF0YSA9IHRoaXMuZGljdGlvbm5hcnlUYWdzLmdldChzaWQpO1xuICAgICAgICAgICAgICBpZiAoIW1hdHRlcnRhZ0RhdGEpe1xuICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKCdubyBtYXR0ZXJ0YWdEYXRhIHRvIGRpc3BsYXknKTtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgY29uc3QgdXJsID0gdGFnU2VydmljZS5nZXRVcmxGb3JTZWVEZXRhaWxzKFxuICAgICAgICAgICAgICAgIG1hdHRlcnRhZ0RhdGEuZ2V0T2JqZWN0KCksXG4gICAgICAgICAgICAgICAgbWF0dGVydGFnRGF0YS5nZXRUeXBlKClcbiAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgaWYgKHVybCAhPT0gJycpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnZpc2liaWxpdHlTZXJ2aWNlLmRldGFpbFNob3dpbmcubmV4dCh0cnVlKTtcbiAgICAgICAgICAgICAgICB0aGlzLm5nWm9uZS5ydW4oKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgdGhpcy5yb3V0ZXIubmF2aWdhdGUoW3VybF0pO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGNhdGNoIHtcbiAgICAgICAgICAgICAgY29uc29sZS5sb2coJ0Nhbm5vdCBzaG93IGRldGFpbHMgZm9yIHRhZycpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgLy8gUG9pbnRlciB0cmlja1xuICAgICAgICAgIC8vIENyZWF0ZSBhIGRpdiB0aGF0IHdpbGwgYXBwZWFyIHdoZW4gdGhlIGN1cnNvciBpcyBzdGlsbFxuICAgICAgICAgIC8vIEl0IHdpbGwgaW50ZXJjZXB0IHRoZSBjbGljayBvZiB0aGUgbW91c2UgYmVmb3JlIGl0IHRyaWdlcnJpbmcgdGhlIE1hdHRlcnBvcnQncyB0b3VyIG5hdmlnYXRpb25cbiAgICAgICAgICB0aGlzLnRpbWVyUG9pbnRlciA9IHNldEludGVydmFsKFxuICAgICAgICAgICAgdGhpcy51cGRhdGVQb2ludGVyVHJpY2suYmluZCh0aGlzKSxcbiAgICAgICAgICAgIDUwXG4gICAgICAgICAgKTtcblxuICAgICAgICAgIC8qKlxuICAgICAgICAgICAqIFRyYW5zaXRpb25zXG4gICAgICAgICAgICovXG4gICAgICAgICAgdGhpcy5zZGsub24oXG4gICAgICAgICAgICAndmlld21vZGUuY2hhbmdlc3RhcnQnLFxuICAgICAgICAgICAgZnVuY3Rpb24gKHRvLCBmcm9tKSB7XG4gICAgICAgICAgICAgIC8vIGNvbnNvbGUubG9nKCdTdGFydGluZyB0byBtb3ZlIHRvICcgKyB0byArICcgZnJvbSAnICsgZnJvbSk7XG4gICAgICAgICAgICAgIHRoaXMuaW5UcmFuc2l0aW9uTW9kZSA9IHRydWU7XG4gICAgICAgICAgICB9LmJpbmQodGhpcylcbiAgICAgICAgICApO1xuXG4gICAgICAgICAgdGhpcy5zZGsub24oXG4gICAgICAgICAgICAndmlld21vZGUuY2hhbmdlZW5kJyxcbiAgICAgICAgICAgIGZ1bmN0aW9uIChvbGRNb2RlLCBuZXdNb2RlKSB7XG4gICAgICAgICAgICAgIC8vIGNvbnNvbGUubG9nKCdFbmRlZCB0byBtb3ZlIHRvICcgKyBuZXdNb2RlICsgJyBmcm9tICcgKyBvbGRNb2RlKTtcbiAgICAgICAgICAgICAgaWYgKG5ld01vZGUgIT09ICdtb2RlLnRyYW5zaXRpb25pbmcnKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5pblRyYW5zaXRpb25Nb2RlID0gZmFsc2U7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0uYmluZCh0aGlzKVxuICAgICAgICAgICk7XG5cbiAgICAgICAgICB0aGlzLnNkay5vbihcbiAgICAgICAgICAgIHRoaXMuc2RrLlN3ZWVwLkV2ZW50LkVOVEVSLFxuICAgICAgICAgICAgZnVuY3Rpb24gKG9sZFN3ZWVwLCBuZXdTd2VlcCkge1xuICAgICAgICAgICAgICAvLyBjb25zb2xlLmxvZygnTGVhdmluZyBzd2VlcCAnICsgb2xkU3dlZXApO1xuICAgICAgICAgICAgICAvLyBjb25zb2xlLmxvZygnRW50ZXJpbmcgc3dlZXAgJyArIG5ld1N3ZWVwKTtcbiAgICAgICAgICAgICAgdGhpcy5pblRyYW5zaXRpb25Td2VlcCA9IGZhbHNlO1xuICAgICAgICAgICAgICB0aGlzLmRpc3BsYXlBemltdXRhbENyb3duKCk7XG4gICAgICAgICAgICB9LmJpbmQodGhpcylcbiAgICAgICAgICApO1xuICAgICAgICAgIHRoaXMuc2RrLm9uKFxuICAgICAgICAgICAgdGhpcy5zZGsuU3dlZXAuRXZlbnQuRVhJVCxcbiAgICAgICAgICAgIGZ1bmN0aW9uIChmcm9tU3dlZXAsIHRvU3dlZXApIHtcbiAgICAgICAgICAgICAgLy8gICBjb25zb2xlLmxvZygnTGVhdmluZyBzd2VlcCAnICsgZnJvbVN3ZWVwKTtcbiAgICAgICAgICAgICAgLy8gICBjb25zb2xlLmxvZygnVHJhbnNpdGlvbmluZyB0byBzd2VlcCAnICsgdG9Td2VlcCk7XG4gICAgICAgICAgICAgIHRoaXMuaW5UcmFuc2l0aW9uU3dlZXAgPSB0cnVlO1xuICAgICAgICAgICAgfS5iaW5kKHRoaXMpXG4gICAgICAgICAgKTtcblxuICAgICAgICAgIC8vIFRPRE86IGdldCBzY2VuZSB3aXRoIGdldHRlciBpbnN0ZWFkIVxuICAgICAgICAgIGNvbnN0IFtzY2VuZU9iamVjdF0gPSBhd2FpdCB0aGlzLnNkay5TY2VuZS5jcmVhdGVPYmplY3RzKDEpO1xuICAgICAgICAgIGNvbnN0IG5vZGUgPSBzY2VuZU9iamVjdC5hZGROb2RlKCk7XG4gICAgICAgICAgbm9kZS5zdGFydCgpO1xuICAgICAgICAgIHRoaXMudGhyZWVKU1NjZW5lID0gbm9kZS5vYmozRC5wYXJlbnQ7XG5cbiAgICAgICAgICAvLyBhd2FpdCB0aGlzLnNkay5TY2VuZS5jb25maWd1cmUoKHJlbmRlcmVyOiBhbnksIHRocmVlOiBhbnkpID0+IHtcbiAgICAgICAgICAvLyAgIHJlbmRlcmVyLnBoeXNpY2FsbHlDb3JyZWN0TGlnaHRzID0gdHJ1ZTtcbiAgICAgICAgICAvLyAgIHJlbmRlcmVyLm91dHB1dEVuY29kaW5nID0gdGhyZWUuc1JHQkVuY29kaW5nO1xuICAgICAgICAgIC8vICAgcmVuZGVyZXIuc2hhZG93TWFwLmVuYWJsZWQgPSB0cnVlO1xuICAgICAgICAgIC8vICAgcmVuZGVyZXIuc2hhZG93TWFwLmJpYXMgPSAwLjAwMDE7XG4gICAgICAgICAgLy8gICByZW5kZXJlci5zaGFkb3dNYXAudHlwZSA9IHRocmVlLlBDRlNvZnRTaGFkb3dNYXA7XG4gICAgICAgICAgLy8gfSk7XG5cblxuICAgICAgICAgIC8vIFRPRE86IHdhaXQgZm9yIE1QIHRpY2tldCByZXNvbHV0aW9uIGJlZm9yZSBkZWNvbW1lbnQgdGhlc2UhXG4gICAgICAgICAgLy8gV2FpdCB1bnRpbCBTaG93Y2FzZSBpcyBhY3R1YWxseSBwbGF5aW5nLi4uLlxuICAgICAgICAgIC8vIHRoaXMuc2RrLlRhZy5kYXRhLnN1YnNjcmliZSh7XG4gICAgICAgICAgLy8gICBvbkFkZGVkOiBhc3luYyBmdW5jdGlvbiAoaW5kZXgsIGl0ZW0sIGNvbGxlY3Rpb24pIHtcbiAgICAgICAgICAvL1xuICAgICAgICAgIC8vICAgICBsZXQgdGhpc09wYWNpdHkgPSAwLjI7XG4gICAgICAgICAgLy8gICAgIHRoaXMuc2RrLlRhZy5lZGl0T3BhY2l0eShpbmRleCwgdGhpc09wYWNpdHkpO1xuICAgICAgICAgIC8vXG4gICAgICAgICAgLy8gICAgIGxldCBzb3VyY2UgPSBudWxsO1xuICAgICAgICAgIC8vICAgICB0cnkge1xuICAgICAgICAgIC8vICAgICAgIHNvdXJjZSA9IGF3YWl0IFByb21pc2UuYWxsKFtcbiAgICAgICAgICAvLyAgICAgICAgIHRoaXMuc2RrLlNlbnNvci5jcmVhdGVTb3VyY2UodGhpcy5zZGsuU2Vuc29yLlNvdXJjZVR5cGUuU1BIRVJFLCB7XG4gICAgICAgICAgLy8gICAgICAgICAgIG9yaWdpbjogaXRlbS5hbmNob3JQb3NpdGlvbixcbiAgICAgICAgICAvLyAgICAgICAgICAgcmFkaXVzOiBOdW1iZXIoMyksXG4gICAgICAgICAgLy8gICAgICAgICAgIHVzZXJEYXRhOiB7XG4gICAgICAgICAgLy8gICAgICAgICAgICAgaWQ6IGluZGV4ICsgJy1zcGhlcmUtc291cmNlJyxcbiAgICAgICAgICAvLyAgICAgICAgICAgfSxcbiAgICAgICAgICAvLyAgICAgICAgIH0pXG4gICAgICAgICAgLy8gICAgICAgXSk7XG4gICAgICAgICAgLy8gICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAvLyAgICAgICBjb25zb2xlLmxvZygnY291bGQgbm90IGNyZWF0ZSBTcGhlcmUgc2Vuc29yJylcbiAgICAgICAgICAvLyAgICAgICBjb25zb2xlLmVycm9yKGUpO1xuICAgICAgICAgIC8vICAgICB9XG4gICAgICAgICAgLy8gICAgIGlmICghc291cmNlKSB7XG4gICAgICAgICAgLy8gICAgICAgcmV0dXJuO1xuICAgICAgICAgIC8vICAgICB9XG4gICAgICAgICAgLy9cbiAgICAgICAgICAvLyAgICAgbGV0IHNlbnNvciA9IG51bGw7XG4gICAgICAgICAgLy8gICAgIHRyeSB7XG4gICAgICAgICAgLy8gICAgICAgc2Vuc29yID0gYXdhaXQgdGhpcy5zZGsuU2Vuc29yLmNyZWF0ZVNlbnNvcih0aGlzLnNkay5TZW5zb3IuU2Vuc29yVHlwZS5DQU1FUkEpO1xuICAgICAgICAgIC8vICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgLy8gICAgICAgY29uc29sZS5sb2coJ2NvdWxkIG5vdCBjcmVhdGUgQ2FtZXJhIHNlbnNvcicpXG4gICAgICAgICAgLy8gICAgICAgY29uc29sZS5lcnJvcihlKTtcbiAgICAgICAgICAvLyAgICAgfVxuICAgICAgICAgIC8vICAgICBpZiAoIXNlbnNvcikge1xuICAgICAgICAgIC8vICAgICAgIHJldHVybjtcbiAgICAgICAgICAvLyAgICAgfVxuICAgICAgICAgIC8vXG4gICAgICAgICAgLy8gICAgIHNlbnNvci5hZGRTb3VyY2UoLi4uc291cmNlKTtcbiAgICAgICAgICAvLyAgICAgc2Vuc29yLnJlYWRpbmdzLnN1YnNjcmliZSh7XG4gICAgICAgICAgLy8gICAgICAgb25VcGRhdGVkKHNvdXJjZSwgcmVhZGluZykge1xuICAgICAgICAgIC8vICAgICAgICAgY29uc29sZS5sb2codGhpc09wYWNpdHkpO1xuICAgICAgICAgIC8vICAgICAgICAgbGV0IG9sZE9wYWNpdHkgPSB0aGlzT3BhY2l0eTtcbiAgICAgICAgICAvLyAgICAgICAgIGlmIChyZWFkaW5nLmluUmFuZ2UpIHtcbiAgICAgICAgICAvLyAgICAgICAgICAgdGhpc09wYWNpdHkgPSAxO1xuICAgICAgICAgIC8vICAgICAgICAgICBjb25zb2xlLmxvZyhpbmRleCArICcgaXMgaW5SYW5nZScpO1xuICAgICAgICAgIC8vICAgICAgICAgfSBlbHNlIGlmIChyZWFkaW5nLmluVmlldykge1xuICAgICAgICAgIC8vICAgICAgICAgICBjb25zb2xlLmxvZyhpbmRleCArICcgaXMgaW5WaWV3IGJ1dCBub3QgaW5SYW5nZScpO1xuICAgICAgICAgIC8vICAgICAgICAgICB0aGlzT3BhY2l0eSA9IDAuNTtcbiAgICAgICAgICAvLyAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgLy8gICAgICAgICAgIHRoaXNPcGFjaXR5ID0gMC4yO1xuICAgICAgICAgIC8vICAgICAgICAgICBjb25zb2xlLmxvZyhpbmRleCArICcgaXMgbm90IGluVmlldyBvciBpblJhbmdlJyk7XG4gICAgICAgICAgLy8gICAgICAgICB9XG4gICAgICAgICAgLy9cbiAgICAgICAgICAvLyAgICAgICAgIHRoaXMuc2RrLlRhZy5lZGl0T3BhY2l0eShpbmRleCwgdGhpc09wYWNpdHkpO1xuICAgICAgICAgIC8vICAgICAgICAgLypcbiAgICAgICAgICAvLyAgICAgICAgICAgICAgICAgICBsZXQgaW5jID0gMC4wMTtcbiAgICAgICAgICAvLyAgICAgICAgICAgICAgICAgICBpZiAob2xkT3BhY2l0eSA+IHRoaXNPcGFjaXR5KSB7XG4gICAgICAgICAgLy8gICAgICAgICAgICAgICAgICAgICBpbmMgPSAtMC4wMTtcbiAgICAgICAgICAvLyAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgLy9cbiAgICAgICAgICAvLyAgICAgICAgICAgICAgICAgICBmb3IodmFyIGkgPSBvbGRPcGFjaXR5OyBpICE9IHRoaXNPcGFjaXR5OyBpPWkraW5jKSB7XG4gICAgICAgICAgLy8gICAgICAgICAgICAgICAgICAgICAgIHNldFRpbWVvdXQoZnVuY3Rpb24oKSB7XG4gICAgICAgICAgLy8gICAgICAgICAgICAgICAgICAgICAgICAgIG1wU2RrLlRhZy5lZGl0T3BhY2l0eShpbmRleCwgaSk7XG4gICAgICAgICAgLy8gICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKCdEZWxheScsIGkpO1xuICAgICAgICAgIC8vICAgICAgICAgICAgICAgICAgICAgICB9LDEwKTtcbiAgICAgICAgICAvLyAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgLy8gICAgICAgICAqL1xuICAgICAgICAgIC8vICAgICAgIH1cbiAgICAgICAgICAvLyAgICAgfSk7XG4gICAgICAgICAgLy8gICAgIC8vc2Vuc29yLnNob3dEZWJ1Zyh0cnVlKTtcbiAgICAgICAgICAvLyAgIH0uYmluZCh0aGlzKSxcbiAgICAgICAgICAvLyAgIG9uQ29sbGVjdGlvblVwZGF0ZWQ6IGZ1bmN0aW9uIChjb2xsZWN0aW9uKSB7XG4gICAgICAgICAgLy8gICAgIGNvbnNvbGUubG9nKCdDb2xsZWN0aW9uIHJlY2VpdmVkLiBUaGVyZSBhcmUgJywgT2JqZWN0LmtleXMoY29sbGVjdGlvbikubGVuZ3RoLCAnIFRhZ3MgaW4gdGhlIGNvbGxlY3Rpb24nLCBjb2xsZWN0aW9uKTtcbiAgICAgICAgICAvLyAgIH1cbiAgICAgICAgICAvLyB9KTtcblxuICAgICAgICAgIHJlc29sdmUodHJ1ZSk7XG4gICAgICAgIH0uYmluZCh0aGlzKVxuICAgICAgKTtcbiAgICB9KTtcbiAgfVxuXG5cbiAgc2V0TGlnaHRpbmdPZmYoKSB7XG4gICAgdGhpcy5ub0xpZ2h0Rm9yT2JqZWN0cyA9IHRydWU7XG4gIH1cblxuICBwb2ludFRvU3RyaW5nKHBvaW50OiB7IHg6IG51bWJlciwgeTogbnVtYmVyLCB6OiBudW1iZXIgfSk6IHN0cmluZyB7XG4gICAgdmFyIHggPSBwb2ludC54LnRvRml4ZWQoMyk7XG4gICAgdmFyIHkgPSBwb2ludC55LnRvRml4ZWQoMyk7XG4gICAgdmFyIHogPSBwb2ludC56LnRvRml4ZWQoMyk7XG5cbiAgICByZXR1cm4gYHsgeDogJHt4fSwgeTogJHt5fSwgejogJHt6fSB9YDtcbiAgfVxuXG4gIC8vXG4gIC8vIC0tLS0tLS0tLS0gTWVhc3VyZW1lbnRzIHJlbGF0ZWQgLS0tLS0tLS0tLVxuICAvL1xuICAvKipcbiAgICogQ2FsbGJhY2sgYWZ0ZXIgbWVhc3VyZW1lbnQgaXMgcGVyZm9ybWVkXG4gICAqL1xuICBnZXREaXN0YW5jZUZvckxhc3RNZWFzdXJlbWVudCgpIHtcbiAgICBpZiAodGhpcy5sYXN0TWVhc3VyZS5sZW5ndGggPiAwKSB7XG4gICAgICBjb25zdCBudW1iZXJQb2ludHMgPSB0aGlzLmxhc3RNZWFzdXJlLmxlbmd0aDtcbiAgICAgIHRoaXMuZGlzdGFuY2VzTGFzdE1lYXN1cmUgPSBbXTtcbiAgICAgIGZvciAobGV0IGluZGV4ID0gMTsgaW5kZXggPCBudW1iZXJQb2ludHM7IGluZGV4ICs9IDEpIHtcbiAgICAgICAgY29uc3QgZGlzdGFuY2UgPSBnZXREaXN0YW5jZUJldHdlZW5Ud29Qb2ludHMoXG4gICAgICAgICAgdGhpcy5sYXN0TWVhc3VyZVtpbmRleCAtIDFdLFxuICAgICAgICAgIHRoaXMubGFzdE1lYXN1cmVbaW5kZXhdXG4gICAgICAgICk7XG4gICAgICAgIHRoaXMuZGlzdGFuY2VzTGFzdE1lYXN1cmUucHVzaChkaXN0YW5jZSk7XG4gICAgICB9XG4gICAgICB0aGlzLnRha2VTY3JlZW5TaG90KCkudGhlbigocmVzKSA9PiB7XG4gICAgICAgIHRoaXMucm91dGVyLm5hdmlnYXRlKFtgdmlzaXQvJHt0aGlzLmN1cnJlbnRTcGFjZUlEfS9hZGRfbWVhc3VyZW1lbnRgXSk7XG4gICAgICB9KTtcbiAgICB9XG4gIH1cblxuICBnZXRMYXN0RGlzdGFuY2VzKCkge1xuICAgIHJldHVybiB0aGlzLmRpc3RhbmNlc0xhc3RNZWFzdXJlO1xuICB9XG5cbiAgLyoqXG4gICAqIFRha2VzIHNjcmVlbnNob3QgYW5kIHNhdmVzIGJhc2U2NCBpbiBsYXN0U2NyZWVuc2hvdFVyaVxuICAgKiBAcmV0dXJucyBQcm9taXNlXG4gICAqL1xuICB0YWtlU2NyZWVuU2hvdCgpOiBQcm9taXNlPGFueT4ge1xuICAgIHJldHVybiB0aGlzLnNkay5SZW5kZXJlci50YWtlU2NyZWVuU2hvdChcbiAgICAgIHRoaXMucmVzb2x1dGlvbixcbiAgICAgIHRoaXMudmlzaWJpbGl0eVxuICAgICkudGhlbihcbiAgICAgIGZ1bmN0aW9uIChzY3JlZW5TaG90VXJpOiBhbnkpIHtcbiAgICAgICAgLy8gYmFzZTY0IHN0cmluZ1xuICAgICAgICB0aGlzLmxhc3RTY3JlZW5zaG90VXJpID0gc2NyZWVuU2hvdFVyaTtcbiAgICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpO1xuICAgICAgfS5iaW5kKHRoaXMpXG4gICAgKTtcbiAgfVxuXG4gIGdldFNjcmVlblNob3RVcmkoKSB7XG4gICAgcmV0dXJuIHRoaXMubGFzdFNjcmVlbnNob3RVcmk7XG4gIH1cblxuICBnZXRMYXN0TWVhc3VyZW1lbnQoKTogT2JqZWN0IHtcbiAgICBjb25zdCBkYXRhID0ge1xuICAgICAgbWVhc3VyZTogdGhpcy5sYXN0TWVhc3VyZSxcbiAgICAgIHN3ZWVwOiB0aGlzLnBvc2VDYW1lcmEuc3dlZXAsXG4gICAgfTtcbiAgICByZXR1cm4gZGF0YTtcbiAgfVxuXG4gIC8vXG4gIC8vIC0tLS0tLS0tLS0gVXRpbHMgLS0tLS0tLS0tLVxuICAvL1xuICAvKipcbiAgICogU3R5bGluZyBvZiBwb2ludGVyXG4gICAqL1xuICB1cGRhdGVQb2ludGVyVHJpY2soKSB7XG4gICAgaWYgKFxuICAgICAgdGhpcy5pbnRlcmFjdGlvbk1vZGUgIT09IFZpZXdlckludGVyYWN0aW9ucy5ERUZBVUxUICYmXG4gICAgICB0aGlzLm1hdHRlcnRhZ1RvRm9sbG93ICYmXG4gICAgICB0aGlzLnBvc2VNYXR0ZXJwb3J0ICYmXG4gICAgICB0aGlzLmdldERpc3RQb3NpdGlvbihcbiAgICAgICAgdGhpcy5wb3NlTWF0dGVycG9ydC5wb3NpdGlvbixcbiAgICAgICAgdGhpcy5vbGRQb3NlTWF0dGVycG9ydFBvc2l0aW9uXG4gICAgICApID4gMjVcbiAgICApIHtcbiAgICAgIHRoaXMucG9pbnRlckJ1dHRvbi5zdHlsZS5kaXNwbGF5ID0gJ25vbmUnO1xuXG4gICAgICBjb25zdCBzaXplID0ge1xuICAgICAgICB3OiB0aGlzLmNvbnRhaW5lci5jbGllbnRXaWR0aCxcbiAgICAgICAgaDogdGhpcy5jb250YWluZXIuY2xpZW50SGVpZ2h0LFxuICAgICAgfTtcbiAgICAgIGNvbnN0IGNvb3JkcyA9IHRoaXMuc2RrLkNvbnZlcnNpb24ud29ybGRUb1NjcmVlbihcbiAgICAgICAgdGhpcy5wb3NlTWF0dGVycG9ydC5wb3NpdGlvbixcbiAgICAgICAgdGhpcy5wb3NlQ2FtZXJhLFxuICAgICAgICBzaXplXG4gICAgICApO1xuICAgICAgdGhpcy5wb2ludGVyQnV0dG9uLnN0eWxlLmxlZnQgPSBgJHtcbiAgICAgICAgY29vcmRzLnggKiBNYXRoLnNpZ24oY29vcmRzLngpIC0gMjVcbiAgICAgIH1weGA7XG4gICAgICB0aGlzLnBvaW50ZXJCdXR0b24uc3R5bGUudG9wID0gYCR7Y29vcmRzLnkgKiBNYXRoLnNpZ24oY29vcmRzLngpIC0gMjV9cHhgO1xuICAgICAgdGhpcy5vbGRQb3NlTWF0dGVycG9ydFBvc2l0aW9uID0ge1xuICAgICAgICAuLi50aGlzLnBvc2VNYXR0ZXJwb3J0LnBvc2l0aW9uLFxuICAgICAgfTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5wb2ludGVyQnV0dG9uLnN0eWxlLmRpc3BsYXkgPSAnYmxvY2snO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBSZWFsdGltZSBtYXR0ZXJ0YWcgZm9sbG93aW5nIHRoZSBjdXJzb3JcbiAgICogQHBhcmFtIG1hdHRlcnRhZyBzdHJpbmdcbiAgICovXG4gIGVuYWJsZV9mb2xsb3dpbmdfdGFnKG1hdHRlcnRhZzogc3RyaW5nKSB7XG4gICAgdGhpcy5zZGsuVGFnLmVkaXRQb3NpdGlvbihtYXR0ZXJ0YWcsIHtcbiAgICAgIGFuY2hvclBvc2l0aW9uOiB7XG4gICAgICAgIHg6IHRoaXMucG9zZU1hdHRlcnBvcnQucG9zaXRpb24ueCAqIDEsXG4gICAgICAgIHk6IHRoaXMucG9zZU1hdHRlcnBvcnQucG9zaXRpb24ueSAqIDEsXG4gICAgICAgIHo6IHRoaXMucG9zZU1hdHRlcnBvcnQucG9zaXRpb24ueiAqIDEsXG4gICAgICB9LFxuICAgICAgc3RlbVZlY3Rvcjoge1xuICAgICAgICB4OiB0aGlzLnBvc2VNYXR0ZXJwb3J0Lm5vcm1hbC54ICogMC4zLFxuICAgICAgICB5OiB0aGlzLnBvc2VNYXR0ZXJwb3J0Lm5vcm1hbC55ICogMC4zLFxuICAgICAgICB6OiB0aGlzLnBvc2VNYXR0ZXJwb3J0Lm5vcm1hbC56ICogMC4zLFxuICAgICAgfSxcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXQgdGhlIGRpc3RhbmNlIGJldHd3ZWVuIHR3byAzRCBwb3NpdGlvbnNcbiAgICogVXNlZCBpbiBvcmRlciB0byBzZWUgaG93IG11Y2ggdGhlIGN1cnNvciBoYXMgbW92ZWQgZnJvbSB0aGUgcHJldmlvdXMgcG9zaXRpb25cbiAgICogQHBhcmFtIHBvczFcbiAgICogQHBhcmFtIHBvczJcbiAgICovXG4gIGdldERpc3RQb3NpdGlvbihwb3MxOiBhbnksIHBvczI6IGFueSkge1xuICAgIGNvbnN0IHNpemUgPSB7XG4gICAgICB3OiB0aGlzLmNvbnRhaW5lci5jbGllbnRXaWR0aCxcbiAgICAgIGg6IHRoaXMuY29udGFpbmVyLmNsaWVudEhlaWdodCxcbiAgICB9O1xuICAgIGNvbnN0IGNvb3JkczEgPSB0aGlzLnNkay5Db252ZXJzaW9uLndvcmxkVG9TY3JlZW4oXG4gICAgICBwb3MxLFxuICAgICAgdGhpcy5wb3NlQ2FtZXJhLFxuICAgICAgc2l6ZVxuICAgICk7XG4gICAgY29uc3QgY29vcmRzMiA9IHRoaXMuc2RrLkNvbnZlcnNpb24ud29ybGRUb1NjcmVlbihcbiAgICAgIHBvczIsXG4gICAgICB0aGlzLnBvc2VDYW1lcmEsXG4gICAgICBzaXplXG4gICAgKTtcbiAgICByZXR1cm4gTWF0aC5zcXJ0KFxuICAgICAgKGNvb3JkczEueCAtIGNvb3JkczIueCkgKiogMiArIChjb29yZHMxLnkgLSBjb29yZHMyLnkpICoqIDJcbiAgICApO1xuICB9XG5cbiAgLy9cbiAgLy8gLS0tLS0tLS0tLSBNYXR0ZXJ0YWcgcmVsYXRlZCAtLS0tLS0tLS0tXG4gIC8vXG4gIC8qKlxuICAgKiBDcmVhdGVzIHRoZSBNYXR0ZXJ0YWcgdGhhdCB3aWxsIGZvbGxvdyB0aGUgY3Vyc29yXG4gICAqIEBwYXJhbSBtYXR0ZXJ0YWdEYXRhIE1hdHRlcnRhZ0RhdGFcbiAgICovXG4gIGFzeW5jIGFkZEN1cnNvck1hdHRlcnRhZyhtYXR0ZXJ0YWdEYXRhOiBNYXR0ZXJ0YWdEYXRhKSB7XG4gICAgaWYgKCF0aGlzLnBvc2VNYXR0ZXJwb3J0KSByZXR1cm47XG4gICAgdGhpcy5tYXR0ZXJ0YWdUb0ZvbGxvdyA9IGF3YWl0IHRoaXMuYWRkTWF0dGVydGFnVG9WaWV3ZXIobWF0dGVydGFnRGF0YSk7XG4gICAgY29uc29sZS5sb2coJ2ZvbGxvd2luZyB0aGUgdGFnJywgdGhpcy5tYXR0ZXJ0YWdUb0ZvbGxvdyk7XG4gICAgdGhpcy5zZGsuVGFnLmVkaXRJY29uKHRoaXMubWF0dGVydGFnVG9Gb2xsb3csICdpY29uLXBvc2l0aW9uJyk7XG4gICAgdGhpcy5zZGsuVGFnLmVkaXRPcGFjaXR5KHRoaXMubWF0dGVydGFnVG9Gb2xsb3csIDEpO1xuICB9XG5cbiAgLyoqXG4gICAqIEFkZHMgTWF0dGVydGFnIHRvIHZpZXdlciBmb3IgYW4gZXhpc3Rpbmcgb2JqZWN0IHdpdGggY29vcmRpbmF0ZXMgKGluIG1hdHRlcnRhZ0RhdGEucG9pKVxuICAgKiAocG9zaXRpb24sIGluamVjdGVkIGh0bWwsIHNldCBpY29uKVxuICAgKiBAcGFyYW0gbWF0dGVydGFnRGF0YVxuICAgKiByZXR1cm5zIG1hdHRlcnRhZ0lEXG4gICAqL1xuICBhc3luYyBhZGRNYXR0ZXJ0YWdUb1ZpZXdlcihcbiAgICBtYXR0ZXJ0YWdEYXRhOiBNYXR0ZXJ0YWdEYXRhXG4gICk6IFByb21pc2U8c3RyaW5nIHwgbnVsbD4ge1xuICAgIGxldCBzaWRMaXN0O1xuICAgIGlmICghdGhpcy5zZGspIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cbiAgICB0cnkge1xuICAgICAgc2lkTGlzdCA9IGF3YWl0IHRoaXMuc2RrLlRhZy5hZGQobWF0dGVydGFnRGF0YS5nZXREYXRhKCkpO1xuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICBjb25zb2xlLmxvZyhcbiAgICAgICAgJ1RhZyBkb2VzIG5vdCBiZWxvbmcgdG8gdGhlIHZpc2l0JyxcbiAgICAgICAgZXJyb3IsXG4gICAgICAgIG1hdHRlcnRhZ0RhdGEuZ2V0RGF0YSgpXG4gICAgICApO1xuICAgIH1cbiAgICBpZiAoc2lkTGlzdCkge1xuICAgICAgY29uc3QgbWF0dGVydGFnSUQgPSBzaWRMaXN0WzBdO1xuICAgICAgLy8gY29uc29sZS5sb2coXCJhZGRlZCB0YWdcIiwgbWF0dGVydGFnRGF0YS5nZXRUeXBlKCksIG1hdHRlcnRhZ0lEKTtcbiAgICAgIHRoaXMubWF0dGVydGFnSURzLnB1c2gobWF0dGVydGFnSUQpO1xuICAgICAgdGhpcy5kaWN0aW9ubmFyeVRhZ3Muc2V0KG1hdHRlcnRhZ0lELCBtYXR0ZXJ0YWdEYXRhKTtcbiAgICAgIHJldHVybiBtYXR0ZXJ0YWdJRDtcbiAgICB9XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICAvKipcbiAgICogQWN0aW9ucyB3aGVuIHBvc2l0aW9uIG9mIG1hdHRlcnRhZyBpcyB2YWxpZGF0ZWQgYnkgbGVmdCBjbGlja1xuICAgKi9cbiAgb25WYWxpZGF0ZWRNYXR0ZXJ0YWcoKSB7XG4gICAgdGhpcy5zZXRJbnRlcmFjdGlvbk1vZGUoVmlld2VySW50ZXJhY3Rpb25zLkRFRkFVTFQpO1xuICAgIGNvbnN0IGxhc3RUYWcgPSB0aGlzLmdldExhc3RUYWcoKTtcbiAgICBpZiAobGFzdFRhZykge1xuICAgICAgY29uc3QgY2FsbGJhY2tNb2RlID0gdGhpcy5kaWN0aW9ubmFyeVRhZ3NcbiAgICAgICAgLmdldChsYXN0VGFnKVxuICAgICAgICAuZ2V0Q2FsbGJhY2tBY3Rpb25Nb2RlKCk7XG4gICAgICB0aGlzLmNhbGxiYWNrQWZ0ZXJNYXR0ZXJ0YWdWYWxpZGF0aW9uKGNhbGxiYWNrTW9kZSk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFJlZ2lzdGVycyBuZXcgaWNvbiAocGF0aCB0byBpbWFnZSkgYW5kIHNldCBpdHMgZm9yIE1hdHRlcnRhZ1xuICAgKiBAcGFyYW0gbWF0dGVydGFnSUQgc3RyaW5nXG4gICAqIEBwYXJhbSBpY29uUGF0aCBzdHJpbmdcbiAgICovXG4gIGFzeW5jIGFkZE5ld0ljb25BbmRTZXRGb3JUYWcobWF0dGVydGFnSUQ6IHN0cmluZywgaWNvblBhdGg6IHN0cmluZykge1xuICAgIGF3YWl0IHRoaXMuc2RrLkFzc2V0LnJlZ2lzdGVyVGV4dHVyZShgaWNvbl8ke21hdHRlcnRhZ0lEfWAsIGljb25QYXRoKTtcbiAgICB0aGlzLnNkay5UYWcuZWRpdEljb24obWF0dGVydGFnSUQsIGBpY29uXyR7bWF0dGVydGFnSUR9YCk7XG4gIH1cblxuICAvKipcbiAgICogQ2hhbmdlcyBpY29uIG9mIE1hdHRlcnRhZyAodGhlIGljb25OYW1lIHNob3VsZCBiZSByZWdpc3RlcmVkID0gb25lIG9mIGRlZmF1bHQgb25lcylcbiAgICogQHBhcmFtIG1hdHRlcnRhZ0lEIHN0cmluZ1xuICAgKiBAcGFyYW0gaWNvbk5hbWUgc3RyaW5nXG4gICAqL1xuICBhc3luYyBzZXRSZWdpc3RyZWRJY29uRm9yVGFnKG1hdHRlcnRhZ0lEOiBzdHJpbmcsIGljb25OYW1lOiBzdHJpbmcpIHtcbiAgICB0cnkge1xuICAgICAgdGhpcy5zZGsuVGFnLmVkaXRJY29uKG1hdHRlcnRhZ0lELCBpY29uTmFtZSk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgY29uc29sZS5sb2coXG4gICAgICAgICdjb3VsZCBub3QgZWRpdCBJY29uIHdpdGggbmFtZSAnLFxuICAgICAgICBpY29uTmFtZSxcbiAgICAgICAgJy4gSXMgaXQgcmVnaXN0ZXJlZD8nXG4gICAgICApO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBTZXRzIGRlZmF1bHQgaWNvbiBmb3IgYSB0YWcgKHJlZ2lzdGVyZWQgaW4gaW5pdFNkaykgT1IgdXNlcyB0YWdJY29uIGZyb20gUE9JIChhdmFpbGFibGUgZnJvbSBNYXR0ZXJ0YWdEYXRhKVxuICAgKiBAcGFyYW0gbWF0dGVydGFnSUQgc3RyaW5nXG4gICAqIEBwYXJhbSBtYXR0ZXJ0YWdEYXRhIE1hdHRlcnRhZ0RhdGFcbiAgICogQHJldHVybnNcbiAgICovXG4gIGFzeW5jIHNldFRhZ0ljb25BbmRPcGFjaXR5KFxuICAgIG1hdHRlcnRhZ0lEOiBzdHJpbmcsXG4gICAgbWF0dGVydGFnRGF0YTogTWF0dGVydGFnRGF0YVxuICApIHtcbiAgICBpZiAodGhpcy5TUE1vZHVsZSA9PT0gU3BNb2R1bGUuSE9URUwpIHtcbiAgICAgIGNvbnN0IHJvb20gPSBtYXR0ZXJ0YWdEYXRhLmdldE9iamVjdCgpO1xuICAgICAgbGV0IGljb25OYW1lID0gYGljb25fcm9vbWA7XG4gICAgICBpZiAocm9vbS5hdmFpbGFibGUpIHtcbiAgICAgICAgaWNvbk5hbWUgPSBgJHtpY29uTmFtZX1fYXZhaWxhYmxlYDtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGljb25OYW1lID0gYCR7aWNvbk5hbWV9X3VuYXZhaWxhYmxlYDtcbiAgICAgIH1cbiAgICAgIHRoaXMuc2RrLlRhZy5lZGl0SWNvbihtYXR0ZXJ0YWdJRCwgaWNvbk5hbWUpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBjb25zdCBzdHJpbmdUYWdUeXBlID0gcG9pVHlwZVRvU3RyaW5nKG1hdHRlcnRhZ0RhdGEuZ2V0VHlwZSgpKTtcbiAgICBsZXQgb3BhY2l0eSA9IHRoaXMuY29uZmlnLm15X2NvbmZpZy5ERUZBVUxUX09QQUNJVFlfVEFHO1xuICAgIGxldCBpY29uTmFtZSA9IGBpY29uLSR7c3RyaW5nVGFnVHlwZX1gO1xuICAgIGNvbnN0IHBvaSA9IG1hdHRlcnRhZ0RhdGEuZ2V0UG9pKCk7XG4gICAgaWYgKHBvaSAmJiBwb2kudGFnSWNvbikge1xuICAgICAgY29uc3QgdGFnSWNvbiA9IEpTT04ucGFyc2UocG9pLnRhZ0ljb24pO1xuICAgICAgaWYgKG1hdHRlcnRhZ0RhdGEuZ2V0VHlwZSgpID09PSBQb2lUeXBlLkRBVEEpIHtcbiAgICAgICAgY29uc3QgZmVhdHVyZSA9IG1hdHRlcnRhZ0RhdGEuZ2V0T2JqZWN0KCk7XG4gICAgICAgIGlmIChmZWF0dXJlLnR5cGUgPT09IEZlYXR1cmVUeXBlLklORElDQVRPUl9URU1QKSB7XG4gICAgICAgICAgdGFnSWNvbi5zcmMgPSB0aGlzLnRhZ1NlcnZpY2UuZ2V0SWNvblRhZ0ltYWdlRm9yRmVhdHVyZShmZWF0dXJlLCBwb2kpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBpZiAodGFnSWNvbi5zcmMpIHtcbiAgICAgICAgY29uc3QgcGF0aFNpZ25lZCA9IGF3YWl0IHRoaXMudGFnU2VydmljZS5nZXRTaWduZWRUYWdJY29uU291cmNlKFxuICAgICAgICAgIHRhZ0ljb24uc3JjXG4gICAgICAgICk7XG4gICAgICAgIGlmIChwYXRoU2lnbmVkKSB7XG4gICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGljb25OYW1lID0gYGljb24tJHtzdHJpbmdUYWdUeXBlfS0ke21hdHRlcnRhZ0lEfS0ke21hdHRlcnRhZ0RhdGEuY3VzdG9tSWNvbkluZGV4fWA7XG4gICAgICAgICAgICBhd2FpdCB0aGlzLnNkay5Bc3NldC5yZWdpc3RlclRleHR1cmUoaWNvbk5hbWUsIHBhdGhTaWduZWQpO1xuICAgICAgICAgICAgbWF0dGVydGFnRGF0YS5jdXN0b21JY29uSW5kZXggKz0gMTtcbiAgICAgICAgICB9IGNhdGNoIHtcbiAgICAgICAgICAgIGNvbnNvbGUubG9nKCdlcnJvciByZWdpc3Rlckljb24nKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGlmICh0YWdJY29uLm9wYWNpdHkpIHtcbiAgICAgICAgb3BhY2l0eSA9IHRhZ0ljb24ub3BhY2l0eTtcbiAgICAgIH1cbiAgICB9XG4gICAgdHJ5IHtcbiAgICAgIHRoaXMuc2RrLlRhZy5lZGl0SWNvbihtYXR0ZXJ0YWdJRCwgaWNvbk5hbWUpO1xuICAgICAgdGhpcy5zZGsuVGFnLmVkaXRPcGFjaXR5KG1hdHRlcnRhZ0lELCBvcGFjaXR5KTtcbiAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgY29uc29sZS5sb2coJ0Vycm9yIGVkaXRJY29uIG9yIG9wYWNpdHknLCBlcnJvcik7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIE1vdmVzIHZpZXdlciB0byBsYXN0IHRhZyBjcmVhdGVkXG4gICAqL1xuICBnb1RvTGFzdFRhZygpIHtcbiAgICBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgIGNvbnN0IGxhc3RUYWcgPSB0aGlzLmdldExhc3RUYWcoKTtcbiAgICAgIHRoaXMuZ29Ub1RhZyhsYXN0VGFnKTtcbiAgICB9LCAyMDAwKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBNb3ZlcyB2aWV3ZXIgdG8gTWF0dGVydGFnIHdpdGggSUQgcHJvdmlkZWRcbiAgICogQHBhcmFtIG1hdHRlcnRhZ0lEIHN0cmluZ1xuICAgKiBAcmV0dXJuc1xuICAgKi9cbiAgYXN5bmMgZ29Ub1RhZyhtYXR0ZXJ0YWdJRDogc3RyaW5nKSB7XG4gICAgaWYgKG1hdHRlcnRhZ0lEID09PSAnJykgcmV0dXJuO1xuICAgIHRyeSB7XG4gICAgICB0aGlzLm9uR29Ub1RhZy5uZXh0KG1hdHRlcnRhZ0lEKTtcbiAgICAgIGF3YWl0IHRoaXMuc2RrLlN3ZWVwLmN1cnJlbnQud2FpdFVudGlsKFxuICAgICAgICAoY3VycmVudFN3ZWVwKSA9PiBjdXJyZW50U3dlZXAgIT09ICcnXG4gICAgICApO1xuICAgICAgYXdhaXQgdGhpcy5zZGsuTWF0dGVydGFnLm5hdmlnYXRlVG9UYWcoXG4gICAgICAgIG1hdHRlcnRhZ0lELFxuICAgICAgICB0aGlzLnNkay5NYXR0ZXJ0YWcuVHJhbnNpdGlvbi5GTFlcbiAgICAgICk7XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIGNvbnNvbGUubG9nKCdjYW5ub3QgbmF2aWdhdGUgdG8gdGFnJywgZXJyb3IpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBVcGRhdGVzIGNvbnRlbnQgb2YgTWF0dGVydGFnIHdpdGggbWF0dGVydGFnSUQgKGJpbGxib2FyZCwgaW5qZWN0ZWQgaHRtbCwgdGFnIGljb24pXG4gICAqIEBwYXJhbSBtYXR0ZXJ0YWdJRCBzdHJpbmdcbiAgICogQHBhcmFtIG9iamVjdCBUaWNrZXQsIEVxdWlwbWVudCwgRmVhdHVyZSwgZXRjXG4gICAqIEBwYXJhbSB0YWdUeXBlIFBvaVR5cGVcbiAgICovXG4gIGFzeW5jIHVwZGF0ZU1hdHRlclRhZ0NvbnRlbnRGb3JUYWdJRChcbiAgICBtYXR0ZXJ0YWdJRDogc3RyaW5nLFxuICAgIG9iamVjdDogRGJPYmplY3RUeXBlID0gbnVsbCxcbiAgICB0YWdUeXBlOiBQb2lUeXBlID0gbnVsbFxuICApIHtcbiAgICB0aGlzLnNkay5UYWcuZWRpdEJpbGxib2FyZChcbiAgICAgIG1hdHRlcnRhZ0lELFxuICAgICAgdGhpcy5kaWN0aW9ubmFyeVRhZ3MuZ2V0KG1hdHRlcnRhZ0lEKS5nZXREYXRhKClcbiAgICApO1xuICAgIGlmIChvYmplY3QgJiYgdGFnVHlwZSkge1xuICAgICAgYXdhaXQgdGhpcy5pbmplY3RIdG1sSW5UYWcodGFnVHlwZSwgb2JqZWN0LCBtYXR0ZXJ0YWdJRCk7XG4gICAgfVxuICAgIGF3YWl0IHRoaXMuc2V0VGFnSWNvbkFuZE9wYWNpdHkoXG4gICAgICBtYXR0ZXJ0YWdJRCxcbiAgICAgIHRoaXMuZGljdGlvbm5hcnlUYWdzLmdldChtYXR0ZXJ0YWdJRClcbiAgICApO1xuICB9XG5cbiAgLyoqXG4gICAqIFVwZGF0ZXMgaW5qZWN0ZWQgaHRtbCBmb3IgTWF0dGVydGFnXG4gICAqIEBwYXJhbSBtYXR0ZXJ0YWdJRCBzdHJpbmdcbiAgICogQHBhcmFtIG9iamVjdCBUaWNrZXQsIEVxdWlwbWVudCwgRmVhdHVyZSwgZXRjXG4gICAqIEBwYXJhbSB0YWdUeXBlIFBvaVR5cGVcbiAgICovXG4gIGFzeW5jIHVwZGF0ZUluamVjdGVkSHRtbEZvclRhZ0lEKFxuICAgIG1hdHRlcnRhZ0lEOiBzdHJpbmcsXG4gICAgb2JqZWN0OiBhbnksXG4gICAgdGFnVHlwZTogUG9pVHlwZVxuICApIHtcbiAgICBhd2FpdCB0aGlzLmluamVjdEh0bWxJblRhZyh0YWdUeXBlLCBvYmplY3QsIG1hdHRlcnRhZ0lEKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBEZWxldGVzIE1hdHRlcnRhZyBmcm9tIFZpZXdlciBieSBpdHMgSURcbiAgICogQHBhcmFtIG1hdHRlcnRhZ0lEIHN0cmluZ1xuICAgKi9cbiAgZGVsZXRlTWF0dGVydGFnRnJvbUlkKG1hdHRlcnRhZ0lEOiBzdHJpbmcpIHtcbiAgICB0aGlzLnNkay5UYWcucmVtb3ZlKG1hdHRlcnRhZ0lEKTtcbiAgICB0aGlzLmRpY3Rpb25uYXJ5VGFncy5kZWxldGUobWF0dGVydGFnSUQpO1xuICB9XG5cbiAgLyoqXG4gICAqIERlbGV0ZXMgbGF0ZXN0IGNyZWF0ZWQgbWF0dGVydGFnXG4gICAqL1xuICBkZWxldGVMYXN0TWF0dGVydGFnKCkge1xuICAgIGNvbnN0IG1hdHRlcnRhZ0lEID0gdGhpcy5tYXR0ZXJ0YWdJRHMucG9wKCk7XG4gICAgaWYgKG1hdHRlcnRhZ0lEKSB7XG4gICAgICB0aGlzLmRlbGV0ZU1hdHRlcnRhZ0Zyb21JZChtYXR0ZXJ0YWdJRCk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIExlZ2FjeTogdXNlZCB0byBiZSBjYWxsZWQgYWN0aW9uX2FkZF9tYXR0ZXJ0YWdfZnJvbV9QT0lcbiAgICogQWRkcyBhbmQgY29uZmlndXJlcyBNYXR0ZXJ0YWcgZm9yIGFuIG9iamVjdCAoVGlja2V0LCBFcXVpcG1lbnQsIEZlYXR1cmUsIGV0YykgdGhhdCBjb3JyZXNwb25kcyB0byBQT0kgKGNvb3JkaW5hdGVzLCB0YWdJY29uKVxuICAgKiBAcGFyYW0gdGFnVHlwZSBQb2lUeXBlXG4gICAqIEBwYXJhbSBvYmplY3QgVGlja2V0LCBFcXVpcG1lbnQsIEZlYXR1cmUuLi5cbiAgICogQHBhcmFtIHBvaSBQT0lcbiAgICogQHJldHVybnNcbiAgICovXG4gIGFzeW5jIGNyZWF0ZU1hdHRlcnRhZ0Zyb21QT0koXG4gICAgdGFnVHlwZTogUG9pVHlwZSxcbiAgICBvYmplY3Q6IERiT2JqZWN0VHlwZSxcbiAgICBwb2k6IFBPSVxuICApOiBQcm9taXNlPGFueT4ge1xuICAgIC8vIGNoZWNrIGlmIHRhZyBleGlzdHMgYWxyZWFkeVxuICAgIGNvbnN0IHt0YWcsIHN3ZWVwfSA9IHRoaXMuZ2V0VGFnRnJvbUVsZW1lbnRJZChvYmplY3QuaWQpO1xuICAgIGlmICh0YWcpIHtcbiAgICAgIC8vIGNvbnNvbGUubG9nKFwidGFnIGV4aXN0c1wiLCBvYmplY3QpXG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGNvbnN0IG1hdHRlcnRhZ0RhdGE6IE1hdHRlcnRhZ0RhdGEgPSBuZXcgTWF0dGVydGFnRGF0YSh0YWdUeXBlKTtcbiAgICBtYXR0ZXJ0YWdEYXRhLnNldE9iamVjdChvYmplY3QsIHRhZ1R5cGUpO1xuICAgIGlmIChwb2kuY29vcmRpbmF0ZSkge1xuICAgICAgbWF0dGVydGFnRGF0YS5zZXRQb3NpdGlvbihKU09OLnBhcnNlKHBvaS5jb29yZGluYXRlKSk7XG4gICAgfVxuICAgIGlmIChwb2kubWV0YWRhdGEpIHtcbiAgICAgIGNvbnN0IHRhZ01ldGFkYXRhID0gSlNPTi5wYXJzZShwb2kubWV0YWRhdGEpO1xuICAgICAgaWYgKHRhZ01ldGFkYXRhLm5vcm1hbCkge1xuICAgICAgICBtYXR0ZXJ0YWdEYXRhLnNldE5vcm1hbCh0YWdNZXRhZGF0YS5ub3JtYWwpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgbWF0dGVydGFnRGF0YS5zZXROb3JtYWwoe3g6IDAsIHk6IC0wLjE1LCB6OiAwfSk7XG4gICAgICB9XG4gICAgfVxuICAgIGlmIChwb2kubWF0dGVycG9ydFN3ZWVwSUQpIHtcbiAgICAgIG1hdHRlcnRhZ0RhdGEuc2V0U3dlZXBJRChwb2kubWF0dGVycG9ydFN3ZWVwSUQpO1xuICAgIH1cbiAgICBtYXR0ZXJ0YWdEYXRhLnNldFBvaShwb2kpO1xuXG4gICAgY29uc3QgY3JlYXRlZFRhZ0lEID0gYXdhaXQgdGhpcy5hZGRNYXR0ZXJ0YWdUb1ZpZXdlcihtYXR0ZXJ0YWdEYXRhKTtcbiAgICBpZiAoY3JlYXRlZFRhZ0lEICYmIHRoaXMuc2RrKSB7XG4gICAgICBhd2FpdCB0aGlzLnNldFRhZ0ljb25BbmRPcGFjaXR5KGNyZWF0ZWRUYWdJRCwgbWF0dGVydGFnRGF0YSk7XG4gICAgICBhd2FpdCB0aGlzLmluamVjdEh0bWxJblRhZyh0YWdUeXBlLCBvYmplY3QsIGNyZWF0ZWRUYWdJRCk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEluamVjdCBjdXN0b20gSFRNTCBhcyBNYXR0ZXJ0YWcgY29udGVudFxuICAgKiBAcGFyYW0gdGFnVHlwZSBQb2lUeXBlXG4gICAqIEBwYXJhbSBvYmplY3QgVGlja2V0LCBFcXVpcG1lbnQsIEZlYXR1cmUgZXRjXG4gICAqIEBwYXJhbSB0YWdJRCBzdHJpbmdcbiAgICovXG4gIGFzeW5jIGluamVjdEh0bWxJblRhZyh0YWdUeXBlOiBQb2lUeXBlLCBvYmplY3Q6IERiT2JqZWN0VHlwZSwgdGFnSUQ6IHN0cmluZykge1xuICAgIGxldCBodG1sID0gYXdhaXQgdGhpcy50YWdTZXJ2aWNlLmdldEh0bWxUb0luamVjdCh0YWdUeXBlLCBvYmplY3QpO1xuICAgIGlmIChodG1sICE9PSAnJyAmJiB0aGlzLnNkaykge1xuICAgICAgY29uc3Qgc2NyaXB0VGFnID0gdGhpcy50YWdTZXJ2aWNlLmdldFNjcmlwdEZvclRhZyhvYmplY3QsIHRhZ1R5cGUpO1xuICAgICAgaHRtbCArPSBgJHtzY3JpcHRUYWd9YDtcbiAgICAgIC8vIGNyZWF0ZSBhbmQgcmVnaXN0ZXIgdGhlIHNhbmRib3hcbiAgICAgIGNvbnN0IFtzYW5kYm94SWQsIG1lc3Nlbmdlcl0gPSBhd2FpdCB0aGlzLnNkay5UYWcucmVnaXN0ZXJTYW5kYm94KGh0bWwpO1xuXG4gICAgICAvLyBkZXRhY2ggcHJldmlvdXMgc2FuZGJveCBmcm9tIGEgdGFnXG4gICAgICBsZXQgYXR0YWNobWVudElEID0gdGhpcy50YWdzQXR0YWNobWVudHNbdGFnSURdO1xuICAgICAgaWYgKGF0dGFjaG1lbnRJRCkge1xuICAgICAgICB0aGlzLnNkay5UYWcuZGV0YWNoKHRhZ0lELCBhdHRhY2htZW50SUQpO1xuICAgICAgfVxuICAgICAgdGhpcy50YWdzQXR0YWNobWVudHNbdGFnSURdID0gc2FuZGJveElkO1xuXG4gICAgICAvLyBhdHRhY2ggdGhlIHNhbmRib3ggdG8gYSB0YWdcbiAgICAgIHRoaXMuc2RrLlRhZy5hdHRhY2godGFnSUQsIHNhbmRib3hJZCk7XG4gICAgICAvLyByZWNlaXZlIGRhdGEgZnJvbSB0aGUgc2FuZGJveFxuICAgICAgLy8gdGFnTWVzc2VuZ2VyT24gYWxsb3dzIHRvIGdvIGhlcmUgb25seSBvbmNlXG4gICAgICBpZiAoIXRoaXMudGFnTWVzc2VuZ2VyT24pIHtcbiAgICAgICAgdGhpcy50YWdNZXNzZW5nZXJPbiA9IHRydWU7XG4gICAgICAgIGNvbnN0IGltYWdlQ2xpY2sgPSAoZmVhdHVyZUlEOiBzdHJpbmcpID0+IHtcbiAgICAgICAgICAvLyBjb25zb2xlLmxvZyhcImltYWdlIGNsaWNrIGhhbmRsZXJcIiwgZmVhdHVyZUlEKTtcbiAgICAgICAgICB0aGlzLnRhZ1NlcnZpY2Uub25BY3Rpb25JbWFnZUNsaWNrKGZlYXR1cmVJRCk7XG4gICAgICAgIH07XG5cbiAgICAgICAgY29uc3QgYXVkaW9DbGljayA9IChhdWRpb0NvbW1lbnRJRDogc3RyaW5nKSA9PiB7XG4gICAgICAgICAgLy8gY29uc29sZS5sb2coXCJhdWRpbyBjbGljayBoYW5kbGVyXCIsIGF1ZGlvQ29tbWVudElEKTtcbiAgICAgICAgICB0aGlzLnRhZ1NlcnZpY2Uub25BY3Rpb25BdWRpb0NsaWNrKGF1ZGlvQ29tbWVudElEKTtcbiAgICAgICAgfTtcbiAgICAgICAgY29uc3QgdmlkZW9DbGljayA9ICh1cmw6IHN0cmluZykgPT4ge1xuICAgICAgICAgIHRoaXMudGFnU2VydmljZS5vbkFjdGlvblZpZGVvQ2xpY2sodXJsKTtcbiAgICAgICAgfTtcbiAgICAgICAgbWVzc2VuZ2VyLm9uKFxuICAgICAgICAgIFRhZ0FjdGlvbi5ERVRBSUxfQ0xJQ0ssXG4gICAgICAgICAgdGhpcy50YWdTZXJ2aWNlLm9uQWN0aW9uRGV0YWlsQ2xpY2suYmluZCh0aGlzLnRhZ1NlcnZpY2UpXG4gICAgICAgICk7XG4gICAgICAgIG1lc3Nlbmdlci5vbihcbiAgICAgICAgICBUYWdBY3Rpb24uVElDS0VUX0NMSUNLLFxuICAgICAgICAgIHRoaXMudGFnU2VydmljZS5vbkFjdGlvbkRldGFpbENsaWNrLmJpbmQodGhpcy50YWdTZXJ2aWNlKVxuICAgICAgICApO1xuICAgICAgICBtZXNzZW5nZXIub24oVGFnQWN0aW9uLkFVRElPX0NMSUNLLCBhdWRpb0NsaWNrKTtcbiAgICAgICAgbWVzc2VuZ2VyLm9uKFRhZ0FjdGlvbi5JTUFHRV9DTElDSywgaW1hZ2VDbGljayk7XG4gICAgICAgIG1lc3Nlbmdlci5vbihUYWdBY3Rpb24uVklERU9fQ0xJQ0ssIHZpZGVvQ2xpY2spO1xuICAgICAgICBtZXNzZW5nZXIub24oXG4gICAgICAgICAgVGFnQWN0aW9uLkRPQ19DTElDSyxcbiAgICAgICAgICB0aGlzLnRhZ1NlcnZpY2Uub25BY3Rpb25Eb2NDbGljay5iaW5kKHRoaXMudGFnU2VydmljZSlcbiAgICAgICAgKTtcbiAgICAgICAgbWVzc2VuZ2VyLm9uKFxuICAgICAgICAgIFRhZ0FjdGlvbi5ZT1VUVUJFX0NMSUNLLFxuICAgICAgICAgIHRoaXMudGFnU2VydmljZS5vbkFjdGlvbllvdXR1YmVDbGljay5iaW5kKHRoaXMudGFnU2VydmljZSlcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgLy8gaWYgaHRtbCBpcyBlbXB0eSAoY2FzZSBvZiBFTUJFRCBjb250ZW50KSwgd2UgZWRpdCBiaWxsYm9hcmQgZm9yIEZlYXR1cmUgYW5kIGF0dGFjaCBuZXcgY29udGVudFxuICAgICAgY29uc3Qge2NvbW1lbnQsIHRhZ0Rlc2NyaXB0aW9ufSA9XG4gICAgICAgIHRoaXMudGFnU2VydmljZS5nZXRCaWxsYm9hcmRNZWRpYVRvRW1iZWQob2JqZWN0KTtcbiAgICAgIGlmIChjb21tZW50KSB7XG4gICAgICAgIC8vIHJlZ2lzdGVyIHRoZSBtZWRpYVxuICAgICAgICBjb25zdCBbYXR0YWNobWVudElEXSA9IGF3YWl0IHRoaXMuc2RrLlRhZy5yZWdpc3RlckF0dGFjaG1lbnQoXG4gICAgICAgICAgY29tbWVudC5leHRlcm5hbExpbmtcbiAgICAgICAgKTtcbiAgICAgICAgLy8gYXR0YWNoXG4gICAgICAgIHRoaXMuc2RrLlRhZy5hdHRhY2godGFnSUQsIGF0dGFjaG1lbnRJRCk7XG4gICAgICAgIHRoaXMuc2RrLlRhZy5lZGl0QmlsbGJvYXJkKHRhZ0lELCB7XG4gICAgICAgICAgbGFiZWw6IG9iamVjdC50aXRsZSxcbiAgICAgICAgICBkZXNjcmlwdGlvbjogdGFnRGVzY3JpcHRpb24sXG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIGFzeW5jIGFjdGlvbl9kZWxldGVfYWxsX21hdHRlcnRhZ3MoKSB7XG4gICAgYXdhaXQgdGhpcy5zZGsuVGFnLnJlbW92ZSguLi50aGlzLm1hdHRlcnRhZ0lEcyk7XG4gICAgdGhpcy5tYXR0ZXJ0YWdJRHMgPSBbXTtcbiAgICB0aGlzLmRpY3Rpb25uYXJ5VGFncy5jbGVhcigpO1xuICB9XG5cbiAgLyoqXG4gICAqIERlbGV0ZXMgTWF0dGVydGFnIGZyb20gdmlzaXQgYXNzb2NpYXRlZCB3aXRoIG9iamVjdCBJRCAodGlja2V0SUQsIGV0YylcbiAgICogQHBhcmFtIGVsZW1lbnRJRCBzdHJpbmdcbiAgICovXG4gIGFzeW5jIGRlbGV0ZU1hdHRlcnRhZ0Zvck9iamVjdChlbGVtZW50SUQ6IHN0cmluZykge1xuICAgIGNvbnN0IG1hdHRlclRhZ0lEID0gdGhpcy5nZXRUYWdGcm9tRWxlbWVudElkKGVsZW1lbnRJRCkudGFnO1xuICAgIGlmIChtYXR0ZXJUYWdJRCkge1xuICAgICAgdHJ5IHtcbiAgICAgICAgYXdhaXQgdGhpcy5zZGsuVGFnLnJlbW92ZShtYXR0ZXJUYWdJRCk7XG4gICAgICAgIHRoaXMuZGljdGlvbm5hcnlUYWdzLmRlbGV0ZShtYXR0ZXJUYWdJRCk7XG4gICAgICAgIGNvbnN0IGluZGV4ID0gdGhpcy5tYXR0ZXJ0YWdJRHMuaW5kZXhPZihtYXR0ZXJUYWdJRCk7XG4gICAgICAgIHRoaXMubWF0dGVydGFnSURzLnNwbGljZShpbmRleCwgMSk7XG4gICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICBjb25zb2xlLmxvZygnQ2Fubm90IGRlbGV0ZSB0YWcnLCBtYXR0ZXJUYWdJRCwgZXJyb3IpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiB1dWlkIGZyb20gdGhyZWVqc1xuICAgKiBAcGFyYW0gdXVpZFxuICAgKi9cbiAgYXN5bmMgZGVsZXRlT2JqZWN0M0QodXVpZDogc3RyaW5nKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgdGhpcy5kaWN0aW9ubmFyeU9iamVjdHMzRC5nZXQodXVpZCkub2JqM0QudmlzaWJsZSA9IGZhbHNlO1xuICB9XG5cbiAgZ2V0T2JqZWN0M0RNb2RlbE5vZGVGcm9tRGljdGlvbm5hcnkodXVpZDogc3RyaW5nKTogYW55IHtcbiAgICAgIGxldCBvYmogPSB0aGlzLmRpY3Rpb25uYXJ5T2JqZWN0czNELmdldCh1dWlkKTtcbiAgICAgIGlmKCFvYmope1xuICAgICAgICBjb25zb2xlLmxvZyhcIndlaXJkIHRoaW5nIGFnYWluXCIpO1xuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgIH1cbiAgICAgIC8vbWlnaHQgYnJlYWsgdGhpbmdzIG9yIGZpeCBldmVyeXRoaW5nIC4uP1xuICAgICAgaWYob2JqLm9iajNELnV1aWQgIT0gdXVpZCl7XG4gICAgICAgIGNvbnNvbGUubG9nKFwid2UgaGF2ZSBUSEUgcHJvYmxlbVwiKTtcbiAgICAgICAgb2JqLm9iajNELnV1aWQgPSB1dWlkOyAvL25vdCBlbnVnaCB0byBmaXggdGhlIHBiXG4gICAgICB9XG5cbiAgICAgIHJldHVybiBvYmo7XG4gIH1cblxuICAvKipcbiAgICogQ3JlYXRlcyAgTWF0dGVydGFnRGF0YSBhbmQgc3RhcnQgcmVwb3NpdGlvbmluZyAoY3JlYXRlcyB0ZW1wb3JhcnkgbWF0dGVydGFnIHRoYXQgZm9sbG93cyB0aGUgY3Vyc29yKVxuICAgKiBAcGFyYW0gcG9pVHlwZSBQb2lUeXBlXG4gICAqIEBwYXJhbSBlbGVtZW50IFRpY2tldCwgRXF1aXBtZW50LCBGZWF0dXJlLCBldGNcbiAgICovXG4gIGFzeW5jIGFkZE1hdHRlcnRhZ1doZW5SZXBvc2l0aW9uaW5nKHBvaVR5cGU6IFBvaVR5cGUsIGVsZW1lbnQ6IERiT2JqZWN0VHlwZSkge1xuICAgIGNvbnN0IG1hdHRlcnRhZ0RhdGEgPSBuZXcgTWF0dGVydGFnRGF0YShwb2lUeXBlKTtcbiAgICAvLyBzZXQgdGhlIGNvb3JkaW5hdGVzIG9mIHRoZSBleGlzdGluZyB0YWdcbiAgICBjb25zdCBbcG9pXSA9IGVsZW1lbnQucG9pcy5pdGVtcztcbiAgICBpZiAocG9pICYmIHBvaS5jb29yZGluYXRlKSB7XG4gICAgICBtYXR0ZXJ0YWdEYXRhLnNldFBvc2l0aW9uKEpTT04ucGFyc2UocG9pLmNvb3JkaW5hdGUpKTtcbiAgICAgIG1hdHRlcnRhZ0RhdGEuc2V0UG9pKHBvaSk7IC8vIHRvIGtlZXAgY3VzdG9tIHRhZ0ljb24gYW5kIG9wYWNpdHlcbiAgICB9XG4gICAgbWF0dGVydGFnRGF0YS5zZXRTd2VlcElEKHRoaXMucG9zZUNhbWVyYS5zd2VlcCk7XG4gICAgbWF0dGVydGFnRGF0YS5zZXRSb3RhdGlvbih0aGlzLnBvc2VDYW1lcmEucm90YXRpb24pO1xuICAgIG1hdHRlcnRhZ0RhdGEuc2V0T2JqZWN0KGVsZW1lbnQsIHBvaVR5cGUpO1xuICAgIHRoaXMubWF0dGVydGFnVG9Gb2xsb3cgPSBhd2FpdCB0aGlzLmFkZE1hdHRlcnRhZ1RvVmlld2VyKG1hdHRlcnRhZ0RhdGEpO1xuICAgIHRoaXMuc2V0SW50ZXJhY3Rpb25Nb2RlKFZpZXdlckludGVyYWN0aW9ucy5QT1NJVElPTklORyk7XG4gICAgYXdhaXQgdGhpcy5hZGRDdXJzb3JNYXR0ZXJ0YWcobWF0dGVydGFnRGF0YSk7XG4gIH1cblxuICAvKipcbiAgICogQ3JlYXRlcyBNYXR0ZXJ0YWdEYXRhIGFuZCBtYXR0ZXJ0YWcgdGhhdCBmb2xsb3dzIHRoZSBjdXJzb3Igd2hlbiBjaG9vc2luZyBwb3NpdGlvbiBmb3IgYSBuZXcgb2JqZWN0XG4gICAqIEBwYXJhbSBwb2lUeXBlXG4gICAqL1xuICBhc3luYyBhZGRNYXR0ZXJ0YWdXaGVuQWRkaW5nKHBvaVR5cGU6IFBvaVR5cGUpIHtcbiAgICBjb25zdCBtYXR0ZXJ0YWdEYXRhID0gbmV3IE1hdHRlcnRhZ0RhdGEocG9pVHlwZSk7XG4gICAgbWF0dGVydGFnRGF0YS5zZXRTd2VlcElEKHRoaXMucG9zZUNhbWVyYS5zd2VlcCk7XG4gICAgbWF0dGVydGFnRGF0YS5zZXRSb3RhdGlvbih0aGlzLnBvc2VDYW1lcmEucm90YXRpb24pO1xuICAgIHRoaXMuc2V0SW50ZXJhY3Rpb25Nb2RlKFZpZXdlckludGVyYWN0aW9ucy5BRERJTkcpO1xuICAgIGF3YWl0IHRoaXMuYWRkQ3Vyc29yTWF0dGVydGFnKG1hdHRlcnRhZ0RhdGEpO1xuICB9XG5cbiAgLyoqXG4gICAqIENhbmNlbHMgZm9sbG93aW5nIG9mIGN1cnNvciAobWVhbmluZyBkZWxldGluZyBsYXN0IE1hdHRlcnRhZylcbiAgICovXG4gIGNhbmNlbEZvbGxvd2luZ0N1cnNvcigpIHtcbiAgICB0aGlzLmRlbGV0ZUxhc3RNYXR0ZXJ0YWcoKTtcbiAgICB0aGlzLnNldEludGVyYWN0aW9uTW9kZShWaWV3ZXJJbnRlcmFjdGlvbnMuREVGQVVMVCk7XG4gIH1cblxuICBzZXRMYXN0T2JqZWN0M0QobGFzdE9iamVjdDNEOiBUaHJlZUpTT2JqZWN0M0QpIHtcbiAgICB0aGlzLmxhc3RPYmplY3QzRCA9IGxhc3RPYmplY3QzRDtcbiAgfVxuXG4gIGdldExhc3RPYmplY3QzRCgpOiBUaHJlZUpTT2JqZWN0M0Qge1xuICAgIHJldHVybiB0aGlzLmxhc3RPYmplY3QzRDtcbiAgfVxuXG4gIC8qKlxuICAgKiBQZXJmb3JtcyBjYWxsYmFjayBhZnRlciBtYXR0ZXJ0YWcgcG9zaXRpb24gd2FzIHZhbGlkYXRlZCAoY3JlYXRpb24gb2Ygb2JqZWN0IG9yIHJlcG9zaXRpb25pbmcpXG4gICAqIEBwYXJhbSBtb2RlIE1hdHRlcnRhZ0FjdGlvbk1vZGVcbiAgICovXG4gIGNhbGxiYWNrQWZ0ZXJNYXR0ZXJ0YWdWYWxpZGF0aW9uKG1vZGU6IE1hdHRlcnRhZ0FjdGlvbk1vZGUpIHtcbiAgICB0aGlzLnZpc2liaWxpdHlTZXJ2aWNlLmRldGFpbFNob3dpbmcubmV4dCh0cnVlKTtcbiAgICBjb25zdCBsYXN0VGFnID0gdGhpcy5nZXRMYXN0VGFnKCk7XG4gICAgc3dpdGNoIChtb2RlKSB7XG4gICAgICBjYXNlIE1hdHRlcnRhZ0FjdGlvbk1vZGUuQUREX0VRVUlQTUVOVDpcbiAgICAgICAgdGhpcy5nb1RvTGFzdFRhZygpO1xuICAgICAgICB0aGlzLnJvdXRlci5uYXZpZ2F0ZShbYHZpc2l0LyR7dGhpcy5jdXJyZW50U3BhY2VJRH0vYWRkX2VxdWlwYF0pO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgTWF0dGVydGFnQWN0aW9uTW9kZS5BRERfVElDS0VUOlxuICAgICAgICB0aGlzLmdvVG9MYXN0VGFnKCk7XG4gICAgICAgIHRoaXMucm91dGVyLm5hdmlnYXRlKFtgdmlzaXQvJHt0aGlzLmN1cnJlbnRTcGFjZUlEfS9hZGRfdGlja2V0YF0pO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgTWF0dGVydGFnQWN0aW9uTW9kZS5BRERfT0JKRUNUM0Q6XG4gICAgICAgIHRoaXMuZ29Ub0xhc3RUYWcoKTtcbiAgICAgICAgdGhpcy5yb3V0ZXIubmF2aWdhdGUoW2B2aXNpdC8ke3RoaXMuY3VycmVudFNwYWNlSUR9L2FkZF9vYmplY3QzZGBdKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIE1hdHRlcnRhZ0FjdGlvbk1vZGUuQUREX0RBVEE6XG4gICAgICAgIHRoaXMuZ29Ub0xhc3RUYWcoKTtcbiAgICAgICAgbGV0IHVybDogc3RyaW5nO1xuICAgICAgICBpZiAodGhpcy5yb3V0ZXIudXJsLmluY2x1ZGVzKCc/JykpIHtcbiAgICAgICAgICB1cmwgPSB0aGlzLnJvdXRlci51cmwuc3Vic3RyaW5nKDAsIHRoaXMucm91dGVyLnVybC5pbmRleE9mKCc/JykpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHVybCA9IHRoaXMucm91dGVyLnVybDtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnJvdXRlci5uYXZpZ2F0ZShbYCR7dXJsfS9hZGRfZmVhdHVyZWBdKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIE1hdHRlcnRhZ0FjdGlvbk1vZGUuQUREX0RFU0s6XG4gICAgICAgIHRoaXMuZ29Ub0xhc3RUYWcoKTtcbiAgICAgICAgdGhpcy5yb3V0ZXIubmF2aWdhdGUoW2B2aXNpdC8ke3RoaXMuY3VycmVudFNwYWNlSUR9L2FkZF9mZWF0dXJlYF0sIHtcbiAgICAgICAgICBxdWVyeVBhcmFtczoge2lzRGVzazogdHJ1ZX0sXG4gICAgICAgIH0pO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgTWF0dGVydGFnQWN0aW9uTW9kZS5BRERfUk9PTTpcbiAgICAgICAgdGhpcy5nb1RvTGFzdFRhZygpO1xuICAgICAgICB0aGlzLnJvdXRlci5uYXZpZ2F0ZShbYHZpc2l0LyR7dGhpcy5jdXJyZW50U3BhY2VJRH0vYWRkX3Jvb21gXSk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSBNYXR0ZXJ0YWdBY3Rpb25Nb2RlLlBPU0lUSU9OX09CSkVDVDNEOlxuICAgICAgICBpZiAobGFzdFRhZykge1xuICAgICAgICAgIC8vIERPIE5vdGhpbmcgKHJvdXRpbmcpLCBqdXN0XG4gICAgICAgICAgdGhpcy5yb3V0ZXIubmF2aWdhdGUoXG4gICAgICAgICAgICBbYHZpc2l0LyR7dGhpcy5jdXJyZW50U3BhY2VJRH0vb2JqZWN0M2QvJHt0aGlzLmxhc3RPYmplY3QzRC5pZH1gXSxcbiAgICAgICAgICAgIHtxdWVyeVBhcmFtczoge3Bvc2l0aW9uaW5nOiB0cnVlfX1cbiAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSBNYXR0ZXJ0YWdBY3Rpb25Nb2RlLlBPU0lUSU9OX1RJQ0tFVDpcbiAgICAgICAgaWYgKGxhc3RUYWcpIHtcbiAgICAgICAgICB0aGlzLnJvdXRlci5uYXZpZ2F0ZShcbiAgICAgICAgICAgIFtcbiAgICAgICAgICAgICAgYHZpc2l0LyR7dGhpcy5jdXJyZW50U3BhY2VJRH0vZGV0YWlsLyR7XG4gICAgICAgICAgICAgICAgdGhpcy5kaWN0aW9ubmFyeVRhZ3MuZ2V0KGxhc3RUYWcpLmVsZW1lbnRJRFxuICAgICAgICAgICAgICB9YCxcbiAgICAgICAgICAgIF0sXG4gICAgICAgICAgICB7cXVlcnlQYXJhbXM6IHtwb3NpdGlvbmluZzogdHJ1ZX19XG4gICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgTWF0dGVydGFnQWN0aW9uTW9kZS5QT1NJVElPTl9FUVVJUE1FTlQ6XG4gICAgICAgIGlmIChsYXN0VGFnKSB7XG4gICAgICAgICAgdGhpcy5yb3V0ZXIubmF2aWdhdGUoXG4gICAgICAgICAgICBbXG4gICAgICAgICAgICAgIGB2aXNpdC8ke3RoaXMuY3VycmVudFNwYWNlSUR9L2VxdWlwLyR7XG4gICAgICAgICAgICAgICAgdGhpcy5kaWN0aW9ubmFyeVRhZ3MuZ2V0KGxhc3RUYWcpLmVsZW1lbnRJRFxuICAgICAgICAgICAgICB9YCxcbiAgICAgICAgICAgIF0sXG4gICAgICAgICAgICB7cXVlcnlQYXJhbXM6IHtwb3NpdGlvbmluZzogdHJ1ZX19XG4gICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgTWF0dGVydGFnQWN0aW9uTW9kZS5QT1NJVElPTl9EQVRBOlxuICAgICAgICBpZiAobGFzdFRhZykge1xuICAgICAgICAgIHRoaXMucm91dGVyLm5hdmlnYXRlKFtdLCB7XG4gICAgICAgICAgICByZWxhdGl2ZVRvOiB0aGlzLmFjdGl2ZVJvdXRlLFxuICAgICAgICAgICAgcXVlcnlQYXJhbXM6IHtwb3NpdGlvbmluZzogdHJ1ZX0sIHF1ZXJ5UGFyYW1zSGFuZGxpbmcgOiBcIm1lcmdlXCJcbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgTWF0dGVydGFnQWN0aW9uTW9kZS5QT1NJVElPTl9ST09NOlxuICAgICAgICBpZiAobGFzdFRhZykge1xuICAgICAgICAgIHRoaXMucm91dGVyLm5hdmlnYXRlKFtdLCB7XG4gICAgICAgICAgICByZWxhdGl2ZVRvOiB0aGlzLmFjdGl2ZVJvdXRlLFxuICAgICAgICAgICAgcXVlcnlQYXJhbXM6IHtwb3NpdGlvbmluZzogdHJ1ZX0sIHF1ZXJ5UGFyYW1zSGFuZGxpbmcgOiBcIm1lcmdlXCJcbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICBicmVhaztcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogRnVsbHkgdXBkYXRlcyBleGlzdGluZyBNYXR0ZXJ0YWcgY29udGVudCB3aXRoIGRhdGEgb2Ygb2JqZWN0IChUaWNrZXQsIEVxdWlwbWVudCwgRGVzaylcbiAgICogQHBhcmFtIG1hdHRlcnRhZ0lEIHN0cmluZ1xuICAgKiBAcGFyYW0gb2JqZWN0IFRpY2tldCwgRXF1aXBtZW50LCBGZWF0dXJlLCBEZXNrXG4gICAqIEBwYXJhbSBwb2lUeXBlIFBvaVR5cGVcbiAgICogQHBhcmFtIHBvaSBQT0lcbiAgICovXG4gIGFzeW5jIHNldE9iamVjdEFuZFBvaUluVGFnKFxuICAgIG1hdHRlcnRhZ0lEOiBzdHJpbmcsXG4gICAgb2JqZWN0OiBEYk9iamVjdFR5cGUsXG4gICAgcG9pVHlwZTogUG9pVHlwZSxcbiAgICBwb2k6IFBPSSB8IG51bGwgPSBudWxsXG4gICk6IFByb21pc2U8dm9pZD4ge1xuICAgIHRoaXMuZGljdGlvbm5hcnlUYWdzLmdldChtYXR0ZXJ0YWdJRCkuc2V0T2JqZWN0KG9iamVjdCwgcG9pVHlwZSk7XG4gICAgaWYgKHBvaSkge1xuICAgICAgdGhpcy5kaWN0aW9ubmFyeVRhZ3MuZ2V0KG1hdHRlcnRhZ0lEKS5zZXRQb2kocG9pKTtcbiAgICB9XG4gICAgdGhpcy5kaWN0aW9ubmFyeVRhZ3MuZ2V0KG1hdHRlcnRhZ0lEKS5lbGVtZW50SUQgPSBvYmplY3QuaWQ7XG4gICAgdHJ5IHtcbiAgICAgIGF3YWl0IHRoaXMudXBkYXRlTWF0dGVyVGFnQ29udGVudEZvclRhZ0lEKG1hdHRlcnRhZ0lELCBvYmplY3QsIHBvaVR5cGUpO1xuICAgICAgLy8gVE9ETzogZml4IHRoaXNcbiAgICAgIGF3YWl0IHRoaXMudXBkYXRlTWF0dGVyVGFnUG9zSW5TZGtWaWV3ZXIoXG4gICAgICAgIG1hdHRlcnRhZ0lELFxuICAgICAgICBvYmplY3QsXG4gICAgICAgIHBvaVR5cGUsXG4gICAgICAgIHBvaVxuICAgICAgKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBjb25zb2xlLmxvZyhgZXJyb3IgaW4gc2V0T2JqZWN0QW5kUG9pSW5UYWc6ICR7ZX1gKTtcbiAgICB9XG4gIH1cblxuICBhc3luYyB1cGRhdGVNYXR0ZXJUYWdQb3NJblNka1ZpZXdlcihcbiAgICBtYXR0ZXJ0YWdJRDogc3RyaW5nLFxuICAgIG9iamVjdDogRGJPYmplY3RUeXBlLFxuICAgIHBvaVR5cGU6IFBvaVR5cGUsXG4gICAgcG9pOiBQT0kgfCBudWxsID0gbnVsbFxuICApOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBjb25zdCBJbmRleFRvVXBkYXRlID0gb2JqZWN0LnBvaXMuaXRlbXMuZmluZEluZGV4KCh1KSA9PiB1LmlkID09PSBwb2kuaWQpO1xuICAgIG9iamVjdC5wb2lzLml0ZW1zW0luZGV4VG9VcGRhdGVdID0gcG9pO1xuICAgIGNvbnN0IHt4LCB5LCB6fSA9IEpTT04ucGFyc2UocG9pLmNvb3JkaW5hdGUpO1xuICAgIGNvbnN0IG5ld1Bvc2l0aW9uID0ge1xuICAgICAgYW5jaG9yUG9zaXRpb246IHtcbiAgICAgICAgeDogeCxcbiAgICAgICAgeTogeSxcbiAgICAgICAgejogeixcbiAgICAgIH0sXG4gICAgICBzdGVtVmVjdG9yOiB7XG4gICAgICAgIC8vIG1ha2UgdGhlIFRhZyBzdGljayBzdHJhaWdodCB1cCBhbmQgbWFrZSBpdCAwLjMwIG1ldGVycyAofjEgZm9vdCkgdGFsbFxuICAgICAgICB4OiAwLFxuICAgICAgICB5OiAwLjMsXG4gICAgICAgIHo6IDAsXG4gICAgICB9LFxuICAgIH07XG4gICAgdGhpcy5zZGsuTWF0dGVydGFnLmVkaXRQb3NpdGlvbihtYXR0ZXJ0YWdJRCwgbmV3UG9zaXRpb24pO1xuICAgIHRoaXMuc2RrLlRhZy5lZGl0UG9zaXRpb24obWF0dGVydGFnSUQsIG5ld1Bvc2l0aW9uKTtcbiAgICB0aGlzLmRpY3Rpb25uYXJ5VGFnc1xuICAgICAgLmdldChtYXR0ZXJ0YWdJRClcbiAgICAgIC5zZXRQb3NpdGlvbihuZXdQb3NpdGlvbi5hbmNob3JQb3NpdGlvbik7XG5cbiAgICBmb3IgKGxldCB0YWdJZCBvZiB0aGlzLm1hdHRlcnRhZ0lEcykge1xuICAgICAgY29uc3QgY3VycmVudFRhZyA9IHRoaXMuZGljdGlvbm5hcnlUYWdzLmdldCh0YWdJZCk7XG4gICAgICBpZiAoIWN1cnJlbnRUYWcpIHtcbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG4gICAgICBpZiAoY3VycmVudFRhZy5lbGVtZW50SUQgPT09IG9iamVjdC5pZCAmJiB0YWdJZCAhPT0gbWF0dGVydGFnSUQpIHtcbiAgICAgICAgdGhpcy5kaWN0aW9ubmFyeVRhZ3MuZGVsZXRlKHRhZ0lkKTtcbiAgICAgICAgdGhpcy5zZGsuVGFnLnJlbW92ZSh0YWdJZCk7XG4gICAgICAgIHRoaXMuc2RrLk1hdHRlcnRhZy5yZW1vdmUodGFnSWQpO1xuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogR2V0cyBtYXR0ZXJUYWdJRCBhbmQgaXRzIHN3ZWVwIGZvciBhbiBvYmplY3QgSUQgKHRpY2tldCBJRCwgZXRjKVxuICAgKiBAcGFyYW0gZWxlbWVudElEIHN0cmluZ1xuICAgKiBAcmV0dXJucyB7dGFnOiBzdHJpbmcgfCBudWxsLCBzd2VlcDogc3RyaW5nIHwgbnVsbH1cbiAgICovXG4gIHB1YmxpYyBnZXRUYWdGcm9tRWxlbWVudElkKGVsZW1lbnRJRDogc3RyaW5nKToge1xuICAgIHRhZzogc3RyaW5nIHwgbnVsbDtcbiAgICBzd2VlcDogc3RyaW5nIHwgbnVsbDtcbiAgfSB7XG4gICAgbGV0IHRhZ0lEID0gbnVsbDtcbiAgICBsZXQgc3dlZXBJRCA9IG51bGw7XG4gICAgZm9yIChsZXQgW21hdHRlcnRhZ0lELCBtYXR0ZXJ0YWdEYXRhXSBvZiB0aGlzLmRpY3Rpb25uYXJ5VGFncykge1xuICAgICAgaWYgKG1hdHRlcnRhZ0RhdGEuZWxlbWVudElEID09PSBlbGVtZW50SUQpIHtcbiAgICAgICAgdGFnSUQgPSBtYXR0ZXJ0YWdJRDtcbiAgICAgICAgY29uc3Qgc3dlZXAgPSBtYXR0ZXJ0YWdEYXRhLmdldFN3ZWVwSUQoKTtcbiAgICAgICAgaWYgKHN3ZWVwICYmIHRoaXMuc3dlZXBzICYmIHRoaXMuc3dlZXBzLmluY2x1ZGVzKHN3ZWVwKSkge1xuICAgICAgICAgIHN3ZWVwSUQgPSBzd2VlcDtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4ge3RhZzogdGFnSUQsIHN3ZWVwOiBzd2VlcElEfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXRzIGxhdGVzdCB0YWcgY3JlYXRlZCBpbiB0aGUgdmlzaXQgKHdoZW4gZm9sbG93aW5nIHRoZSBjdXJzb3IgdG8gcG9zaXRpb24pXG4gICAqIEByZXR1cm5zIHN0cmluZyBtYXR0ZXJ0YWdJRFxuICAgKi9cbiAgZ2V0TGFzdFRhZygpOiBzdHJpbmcgfCBudWxsIHtcbiAgICBpZiAodGhpcy5tYXR0ZXJ0YWdUb0ZvbGxvdykge1xuICAgICAgcmV0dXJuIHRoaXMubWF0dGVydGFnVG9Gb2xsb3c7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiB0aGlzLm1hdHRlcnRhZ0lEcy5sZW5ndGggPT09IDBcbiAgICAgICAgPyBudWxsXG4gICAgICAgIDogdGhpcy5tYXR0ZXJ0YWdJRHNbdGhpcy5tYXR0ZXJ0YWdJRHMubGVuZ3RoIC0gMV07XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEdldHMgTWF0dGVydGFnRGF0YSBmb3IgTWF0dGVydGFnIChyZXBsYWNlcyBnZXRUYWdEYXRhRnJvbUlkKVxuICAgKiBAcGFyYW0gbWF0dGVydGFnSURcbiAgICogQHJldHVybnMgTWF0dGVydGFnRGF0YVxuICAgKi9cbiAgZ2V0TWF0dGVyVGFnRGF0YUZvck1hdHRlcnRhZyhtYXR0ZXJ0YWdJRDogc3RyaW5nKTogTWF0dGVydGFnRGF0YSB8IG51bGwge1xuICAgIHRyeSB7XG4gICAgICByZXR1cm4gdGhpcy5kaWN0aW9ubmFyeVRhZ3MuZ2V0KG1hdHRlcnRhZ0lEKTtcbiAgICB9IGNhdGNoIHtcbiAgICAgIGNvbnNvbGUubG9nKCdjYW5ub3QgcmV0cmlldmUgbWF0dGVydGFnRGF0YSBmb3IgdGFnJywgbWF0dGVydGFnSUQpO1xuICAgIH1cbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIC8vXG4gIC8vIC0tLS0tLS0tLS0gVmlld2VyIHJlbGF0ZWQgKHN3aXRjaCB2aWV3cywgZ28gdG8pIC0tLS0tLS0tLS1cbiAgLy9cbiAgYXN5bmMgYWN0aW9uX3Rvb2xib3hfZmxvb3JwbGFuKCkge1xuICAgIGlmICh0aGlzLmluVHJhbnNpdGlvbk1vZGUgfHwgdGhpcy5pblRyYW5zaXRpb25Td2VlcCkge1xuICAgICAgY29uc29sZS5sb2coJ3ZpZXdlciBpcyBpbiB0cmFuc2l0aW9uLCBjYW5ub3QgZ28gZmxvb3JwbGFuJyk7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIHRyeSB7XG4gICAgICBhd2FpdCB0aGlzLnNkay5Nb2RlLm1vdmVUbygnbW9kZS5mbG9vcnBsYW4nKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBjb25zb2xlLmxvZygnY2Fubm90IGdvIHRvIGZsb29ycGxhbicsIGUpO1xuICAgIH1cbiAgfVxuXG4gIGFjdGlvbl90b29sYm94X2luc2lkZV92aWV3KCkge1xuICAgIHRoaXMuc2RrLk1vZGUubW92ZVRvKCdtb2RlLmluc2lkZScpO1xuICB9XG5cbiAgYWN0aW9uU2hvd0FsbEZsb29ycygpIHtcbiAgICB0cnkge1xuICAgICAgdGhpcy5zZGsuRmxvb3Iuc2hvd0FsbCgpO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGNvbnNvbGUubG9nKCdjYW5ub3Qgc2hvdyBhbGwgZmxvb3JzJywgZSk7XG4gICAgfVxuICB9XG5cbiAgYXN5bmMgYWN0aW9uX3Rvb2xib3hfZG9sbGhvdXNlKCkge1xuICAgIHNldFRpbWVvdXQoYXN5bmMgKCkgPT4ge1xuICAgICAgLy8gY29uc29sZS5sb2coXCJtb2RlOiBcIiwgdGhpcy5pblRyYW5zaXRpb25Nb2RlLCBcIiBzd2VlcDogXCIsIHRoaXMuaW5UcmFuc2l0aW9uU3dlZXApO1xuICAgICAgaWYgKHRoaXMuaW5UcmFuc2l0aW9uTW9kZSB8fCB0aGlzLmluVHJhbnNpdGlvblN3ZWVwKSB7XG4gICAgICAgIGNvbnNvbGUubG9nKCd2aWV3ZXIgaXMgaW4gdHJhbnNpdGlvbiwgY2Fubm90IGdvIGRvbGxob3VzZScpO1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgICB0cnkge1xuICAgICAgICBhd2FpdCB0aGlzLnNkay5Nb2RlLm1vdmVUbygnbW9kZS5kb2xsaG91c2UnKTtcbiAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgY29uc29sZS5sb2coJ2Nhbm5vdCBnbyB0byBkb2xsaG91c2UnLCBlKTtcbiAgICAgIH1cbiAgICB9LCAxMjAwKTtcbiAgfVxuXG4gIGFjdGlvbl90b29sYm94X21lc3VyZSgpIHtcbiAgICBjb25zdCBuZXdTdGF0ZSA9ICF0aGlzLmlzTWVhc3VyZU1vZGVPbjtcbiAgICB0aGlzLnNkay5NZWFzdXJlbWVudHMudG9nZ2xlTW9kZShuZXdTdGF0ZSkudGhlbigoKSA9PiB7XG4gICAgICBjb25zb2xlLmxvZyhcbiAgICAgICAgYE1lYXN1cmVtZW50IG1vZGUgaXMgbm93ICR7bmV3U3RhdGUgPyAnZW5hYmxlZCcgOiAnZGlzYWJsZWQnfWBcbiAgICAgICk7XG4gICAgfSk7XG4gIH1cblxuICBhY3Rpb25fdG9vbGJveF9jYW5jZWxfbWVzdXJlKCkge1xuICAgIGlmICh0aGlzLmlzTWVhc3VyZU1vZGVPbikge1xuICAgICAgdGhpcy5hY3Rpb25fdG9vbGJveF9tZXN1cmUoKTtcbiAgICB9XG4gIH1cblxuICBhc3luYyBhY3Rpb25fZ29fdG9fZmxvb3IoXG4gICAgZmxvb3JOYW1lOiBzdHJpbmcsXG4gICAgbWF0dGVycG9ydEZsb29yU2VxdWVuY2U6IG51bWJlciA9IG51bGxcbiAgKSB7XG4gICAgaWYgKCF0aGlzLmZsb29ycykge1xuICAgICAgY29uc29sZS5sb2coJ0Zsb29yIGFyZSBub3QgbG9hZGVkIHlldCcpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICAvLyBjb25zb2xlLmxvZyh0aGlzLmZsb29ycyk7XG4gICAgLy8gbG9vayB1cCBmb3Igc2VxdWVuY2UgbnVtYmVyICh0aGUgc2FmZXN0IG1ldGhvZClcbiAgICBsZXQgZmxvb3JNYXR0ZXJwb3J0ID0gdGhpcy5mbG9vcnMuZmluZChcbiAgICAgIChmbG9vcikgPT4gZmxvb3Iuc2VxdWVuY2UgPT09IG1hdHRlcnBvcnRGbG9vclNlcXVlbmNlXG4gICAgKTtcbiAgICBpZiAoIWZsb29yTWF0dGVycG9ydCkge1xuICAgICAgZmxvb3JNYXR0ZXJwb3J0ID0gdGhpcy5mbG9vcnMuZmluZChcbiAgICAgICAgKGZsb29yKSA9PiBmbG9vck5hbWUuaW5jbHVkZXMoZmxvb3IubmFtZSkgJiYgZmxvb3IubmFtZSAhPSAnJ1xuICAgICAgKTtcbiAgICB9XG4gICAgaWYgKCFmbG9vck1hdHRlcnBvcnQpIHtcbiAgICAgIGZsb29yTWF0dGVycG9ydCA9IHRoaXMuZmxvb3JzLmZpbmQoKGZsb29yKSA9PlxuICAgICAgICBmbG9vck5hbWUuaW5jbHVkZXMoZmxvb3IuaWQpXG4gICAgICApO1xuICAgIH1cbiAgICAvLyBjb25zb2xlLmxvZyhmbG9vck1hdHRlcnBvcnQpXG4gICAgaWYgKGZsb29yTWF0dGVycG9ydCkge1xuICAgICAgbGV0IHJldHJ5ID0gdHJ1ZTtcbiAgICAgIHdoaWxlIChyZXRyeSkge1xuICAgICAgICB0cnkge1xuICAgICAgICAgIGNvbnN0IGZsb29ySW5kZXggPSBhd2FpdCB0aGlzLnNkay5GbG9vci5tb3ZlVG8oXG4gICAgICAgICAgICBmbG9vck1hdHRlcnBvcnQuc2VxdWVuY2VcbiAgICAgICAgICApO1xuICAgICAgICAgIC8vIGNvbnNvbGUubG9nKFwibW92ZWQgdG8gZmxvb3JJbmRleFwiLCBmbG9vckluZGV4KTtcbiAgICAgICAgICByZXRyeSA9IGZhbHNlO1xuICAgICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICAgIGNvbnNvbGUubG9nKCdDYW5ub3QgbW92ZSB0byBGbG9vcicsIGVycm9yKTtcbiAgICAgICAgICBhd2FpdCB3YWl0KDEwMCk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgY29uc29sZS53YXJuKCdObyBtYXR0ZXJwb3J0IGZsb29yIGZvdW5kIHRvIG1vdmUgdG8nKTtcbiAgICB9XG4gIH1cblxuICBhc3luYyBhY3Rpb25fZ29fdG9fc3dlZXAoXG4gICAgc3dlZXA6IHN0cmluZyxcbiAgICByb3RhdGlvbjogeyB4OiBudW1iZXI7IHk6IG51bWJlciB9ID0gbnVsbFxuICApIHtcbiAgICBpZiAodGhpcy5mb3JiaWRkZW5Td2VlcHMuaW5jbHVkZXMoc3dlZXApKSB7XG4gICAgICBjb25zb2xlLmxvZygndXNlciBpcyBub3QgYWxsb3dlZCB0byBnbyB0byB0aGlzIHN3ZWVwJyk7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIC8vIGNvbnNvbGUubG9nKFwiZ29pbmcgdG8gc3dlZXBcIiwgc3dlZXAsIFwid2l0aCByb3RhdGlvbjpcIiwgcm90YXRpb24pO1xuICAgIHNldFRpbWVvdXQoYXN5bmMgKCkgPT4ge1xuICAgICAgaWYgKHRoaXMuaW5UcmFuc2l0aW9uTW9kZSB8fCB0aGlzLmluVHJhbnNpdGlvblN3ZWVwKSB7XG4gICAgICAgIGNvbnNvbGUubG9nKCdDYW5ub3QgZ28gdG8gc3dlZXAsIGluIHRyYW5zaXRpb24nKTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgICAgdHJ5IHtcbiAgICAgICAgdGhpcy5pblRyYW5zaXRpb25Td2VlcCA9IHRydWU7XG4gICAgICAgIGF3YWl0IHRoaXMuc2RrLlN3ZWVwLm1vdmVUbyhzd2VlcCwge1xuICAgICAgICAgIHRyYW5zaXRpb246ICd0cmFuc2l0aW9uLmluc3RhbnQnLFxuICAgICAgICAgIHRyYW5zaXRpb25UaW1lOiAxNTAwLFxuICAgICAgICB9KTtcbiAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgIHRoaXMuaW5UcmFuc2l0aW9uU3dlZXAgPSBmYWxzZTtcbiAgICAgICAgY29uc29sZS5sb2coJ0Nhbm5vdCBtb3ZlIHRvIHN3ZWVwJywgZXJyb3IpO1xuICAgICAgfVxuICAgICAgaWYgKHJvdGF0aW9uKSB7XG4gICAgICAgIGF3YWl0IHRoaXMuc2RrLkNhbWVyYS5zZXRSb3RhdGlvbihyb3RhdGlvbiwge3NwZWVkOiAxMDB9KTsgLy8gc3BlZWQgaXMgZGVncmVlcyBwZXIgc2Vjb25kXG4gICAgICB9XG4gICAgfSwgMTAwMCk7XG4gIH1cblxuICBnZXRDdXJyZW50U3dlZXAoKTogc3RyaW5nIHwgbnVsbCB7XG4gICAgaWYgKHRoaXMucG9zZUNhbWVyYSkge1xuICAgICAgcmV0dXJuIHRoaXMucG9zZUNhbWVyYS5zd2VlcDtcbiAgICB9XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICBnZXRDdXJyZW50Q2FtZXJhUG9zaXRpb24oKToge1xuICAgIHJvdGF0aW9uOiBhbnk7XG4gICAgcG9zaXRpb246IGFueTtcbiAgICBzd2VlcDogYW55O1xuICB9IHwgbnVsbCB7XG4gICAgaWYgKHRoaXMucG9zZUNhbWVyYSkge1xuICAgICAgcmV0dXJuIHRoaXMucG9zZUNhbWVyYTtcbiAgICB9XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICBzZXRJbnRlcmFjdGlvbk1vZGUoaW50ZXJhY3Rpb25Nb2RlOiBudW1iZXIpIHtcbiAgICB0aGlzLmludGVyYWN0aW9uTW9kZSA9IGludGVyYWN0aW9uTW9kZTtcbiAgfVxuXG4gIGdldEludGVyYWN0aW9uTW9kZSgpIHtcbiAgICByZXR1cm4gdGhpcy5pbnRlcmFjdGlvbk1vZGU7XG4gIH1cblxuICAvKipcbiAgICogQ2xlYXIgYWxsIHZhcmlhYmxlcywgZGVsZXRlcyBhbGwgdGFncyAod2hlbiB2aWV3ZXIgaXMgcmVtb3ZlciBvciBtb2RlbCBjaGFuZ2VkPXJlbG9hZCBuZWVkZWQpXG4gICAqL1xuICBhc3luYyBjbGVhckFsbCgpIHtcbiAgICBjb25zb2xlLmxvZygncmVtb3Zpbmcgdmlld2VyJyk7XG4gICAgdGhpcy5hY3Rpb25fZGVsZXRlX2FsbF9tYXR0ZXJ0YWdzKCk7XG4gICAgdGhpcy5mbG9vcnMgPSBudWxsO1xuICAgIHRoaXMuc3dlZXBzID0gbnVsbDtcbiAgICB0aGlzLnNkayA9IG51bGw7XG4gICAgY2xlYXJJbnRlcnZhbCh0aGlzLnRpbWVyUG9pbnRlcik7XG4gICAgdGhpcy5mb3JiaWRkZW5Td2VlcHMgPSBbXTtcbiAgICB0aGlzLnRhZ01lc3Nlbmdlck9uID0gZmFsc2U7XG4gICAgLy8gY2FuY2VsIHN1YnNjcmlwdGlvbnNcbiAgICB0aGlzLnBvaW50ZXJCdXR0b24ucmVtb3ZlRXZlbnRMaXN0ZW5lcihcbiAgICAgICdjbGljaycsXG4gICAgICB0aGlzLnBvaW50ZXJMZWZ0Q2xpY2tIYW5kbGVyXG4gICAgKTtcbiAgICB0aGlzLnBvaW50ZXJCdXR0b24ucmVtb3ZlRXZlbnRMaXN0ZW5lcihcbiAgICAgICdjb250ZXh0bWVudScsXG4gICAgICB0aGlzLnBvaW50ZXJSaWdodENsaWNrSGFuZGxlclxuICAgICk7XG5cbiAgICAvLyBUT0RPOiBvbmx5IEZvciBBZG1pbnNcbiAgICBpZiAodGhpcy5nZXRDdXJzb3JQb3NpdGlvbkJ1dHRvbikge1xuICAgICAgdGhpcy5nZXRDdXJzb3JQb3NpdGlvbkJ1dHRvbi5yZW1vdmVFdmVudExpc3RlbmVyKFxuICAgICAgICAnYXV4Y2xpY2snLFxuICAgICAgICB0aGlzLnBvaW50ZXJNaWRkbGVDbGlja0hhbmRsZXJcbiAgICAgICk7XG4gICAgfVxuICAgIC8vIFRPRE86IG9ubHkgZm9yIGRldiFcbiAgICBpZiAoISF0aGlzLmdldEN1cnNvclBvc2l0aW9uQnV0dG9uICYmXG4gICAgICAoZG9jdW1lbnQubG9jYXRpb24uaHJlZi5pbmRleE9mKCdkZXYnKSAhPT0gLTEgfHwgZG9jdW1lbnQubG9jYXRpb24uaHJlZi5pbmRleE9mKCdsb2NhbGhvc3QnKSAhPT0gLTEpKSB7XG4gICAgICBjbGVhckludGVydmFsKHRoaXMuaW50ZXJ2YWxDdXJzb3JQb2ludGVyUG9zaXRpb24pO1xuICAgIH1cbiAgfVxuXG4gIGFzeW5jIHJlbW92ZUZvcmJpZGRlblN3ZWVwcyhmb3JiaWRkZW5Td2VlcHM6IHN0cmluZ1tdKSB7XG4gICAgdGhpcy5mb3JiaWRkZW5Td2VlcHMgPSBbLi4uZm9yYmlkZGVuU3dlZXBzXTtcbiAgICBsZXQgcmVtb3ZlZCA9IDA7XG4gICAgYXdhaXQgUHJvbWlzZS5hbGwoXG4gICAgICBmb3JiaWRkZW5Td2VlcHMubWFwKGFzeW5jIChzd2VlcCkgPT4ge1xuICAgICAgICB0cnkge1xuICAgICAgICAgIGF3YWl0IHRoaXMuc2RrLlN3ZWVwLmRpc2FibGUoc3dlZXApO1xuICAgICAgICAgIHJlbW92ZWQgKz0gMTtcbiAgICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgICBjb25zb2xlLmxvZyhlcnJvcik7XG4gICAgICAgIH1cbiAgICAgIH0pXG4gICAgKTtcbiAgICBjb25zb2xlLmxvZygncmVtb3ZlZCBzd2VlcHM6JywgcmVtb3ZlZCk7XG4gIH1cblxuICAvL1xuICAvLyAtLS0tLS0tLS0tIDNEIG9iamVjdHMgKFNESyBCdW5kbGUgb25seSkgLS0tLS0tLS0tLVxuICAvL1xuICBhc3luYyBpbml0M0RPYmplY3RWaWV3ZXIoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKGFzeW5jIChyZXNvbHZlKSA9PiB7XG4gICAgICB2YXIgW3NjZW5lT2JqZWN0XSA9IGF3YWl0IHRoaXMuc2RrLlNjZW5lLmNyZWF0ZU9iamVjdHMoMSk7XG5cbiAgICAgIHZhciBub2RlID0gc2NlbmVPYmplY3QuYWRkTm9kZSgpO1xuXG4gICAgICAvLyBUT0RPIGNoYW5nZSB0aGlzIPCfpK5cbiAgICAgIG5vZGUuYWRkQ29tcG9uZW50KCdtcC5saWdodHMnKTtcbiAgICAgIC8vbm9kZS5hZGRDb21wb25lbnQoJ21wLmxpZ2h0cycpO1xuICAgICAgLypub2RlLmFkZENvbXBvbmVudCgnbXAubGlnaHRzJyk7XG4gICAgICBub2RlLmFkZENvbXBvbmVudCgnbXAubGlnaHRzJyk7Ki9cbiAgICAgIG5vZGUuc3RhcnQoKTtcblxuICAgICAgY29uc3Qgbm9kZUNvbnRyb2wgPSBzY2VuZU9iamVjdC5hZGROb2RlKCk7XG4gICAgICB0aGlzLm9iamVjdENvbnRyb2wgPSBub2RlQ29udHJvbC5hZGRDb21wb25lbnQoJ21wLnRyYW5zZm9ybUNvbnRyb2xzJyk7XG4gICAgICBub2RlQ29udHJvbC5zdGFydCgpO1xuXG4gICAgICAvL3RoaXMuYWRkM0RPYmplY3Qoe30sbnVsbCk7XG5cbiAgICAgIHJlc29sdmUoKTtcbiAgICB9KTtcbiAgfVxuXG4gIGFzeW5jIGFkZDNET2JqZWN0KFxuICAgIG9iajogSU9iamVjdDNELFxuICAgIG1vZGU/OiAndHJhbnNsYXRlJyB8ICdyb3RhdGUnXG4gICk6IFByb21pc2U8YW55PiB7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKGFzeW5jIChyZXNvbHZlKSA9PiB7XG4gICAgICBjb25zdCBbc2NlbmVPYmplY3RdID0gYXdhaXQgdGhpcy5zZGsuU2NlbmUuY3JlYXRlT2JqZWN0cygxKTtcblxuICAgICAgLy8gVE9ETzogaW1wcm92bWVudCwgcmVncm91cCBhbGwgb2YgdGhlc2UgaW4gRHluYW1pY2FsIE9iamVjdHMgTGliXG4gICAgICAvLyBTZWN1cml0eUNhbWVyYVxuICAgICAgLy8gTmVzdFRoZXJtb3N0YXRcbiAgICAgIC8vIFZpZGVvXG4gICAgICBsZXQgaXNBbmltYXRlZFNlY3VyaXR5Q2FtZXJhID0gZmFsc2U7XG4gICAgICBsZXQgaXNOZXN0VGhlcm1vc3RhdCA9IGZhbHNlO1xuICAgICAgbGV0IGlzU21hcnRlcnBsYW5Qcm9tb3Rpb25hbFZpZGVvID0gZmFsc2U7XG4gICAgICBsZXQgaXNBemltdXRoYWxDcm93biA9IGZhbHNlO1xuXG4gICAgICAvKipcbiAgICAgICAqIFRPRE86IHJlZmFjdG8gd2l0aCBhbiBlbnVtIG9yIHN3aXRjaC9jYXNlXG4gICAgICAgKi9cbiAgICAgIGlmIChvYmoub2JqZWN0ID09PSBcInNlY3VyaXR5X2NhbWVyYVwiKSB7XG4gICAgICAgIGlzQW5pbWF0ZWRTZWN1cml0eUNhbWVyYSA9IHRydWU7XG4gICAgICB9XG4gICAgICBpZiAob2JqLm9iamVjdCA9PT0gXCJuZXN0X3RoZXJtb3N0YXRcIikge1xuICAgICAgICBpc05lc3RUaGVybW9zdGF0ID0gdHJ1ZTtcbiAgICAgIH1cbiAgICAgIGlmIChvYmoub2JqZWN0ID09PSAndmlkZW8nKSB7XG4gICAgICAgIGlzU21hcnRlcnBsYW5Qcm9tb3Rpb25hbFZpZGVvID0gdHJ1ZTtcbiAgICAgIH1cbiAgICAgIGlmKG9iai5vYmplY3QgPT09ICdhemltdXRoJykge1xuICAgICAgICBpc0F6aW11dGhhbENyb3duID0gdHJ1ZTtcbiAgICAgIH1cblxuICAgICAgY29uc3QgbW9kZWxOb2RlID0gc2NlbmVPYmplY3QuYWRkTm9kZSgpO1xuICAgICAgbGV0IGNvbXBvbmVudCA9IG51bGw7XG4gICAgICBjb25zdCBpbml0aWFsID0ge1xuICAgICAgICB1cmw6IGAvYXNzZXRzLzNEb2JqZWN0cy9vYmplY3RzLyR7b2JqLm9iamVjdH0ke1xuICAgICAgICAgIG9iai5mb3JtYXQuaW5kZXhPZignLicpID09PSAtMSA/ICcuJyArIG9iai5mb3JtYXQgOiBvYmouZm9ybWF0XG4gICAgICAgIH1gLFxuICAgICAgICAvLyBUT0RPLyBzdG9yZSBsb2NhbFBvc2l0aW9uICYmIGxvY2FsUm90YXRpb24gaW4gQkREIHRvbyAoaW4gb3JkZXIgdG8gaGF2ZSBwZXJ0ZmVjdCBpbml0aWFsIHBsYWNlbWVudClcbiAgICAgICAgbG9jYWxSb3RhdGlvbjoge1wieFwiOiAwLCBcInlcIjogMCwgXCJ6XCI6IDB9LFxuICAgICAgICAvLyBUT0RPLyBzdG9yZSBsb2NhbFBvc2l0aW9uICYmIGxvY2FsUm90YXRpb24gaW4gQkREIHRvbyAoaW4gb3JkZXIgdG8gaGF2ZSBwZXJ0ZmVjdCBpbml0aWFsIHBsYWNlbWVudClcbiAgICAgICAgbG9jYWxQb3NpdGlvbjoge1wieFwiOiAwLCBcInlcIjogMCwgXCJ6XCI6IDB9LFxuICAgICAgICB2aXNpYmxlOiB0cnVlLFxuICAgICAgICBjb2xsaWRlckVuYWJsZWQ6IHRydWVcbiAgICAgIH07XG5cblxuICAgICAgc3dpdGNoIChvYmouZm9ybWF0KSB7XG4gICAgICAgIGNhc2UgJy5vYmonOlxuICAgICAgICBjYXNlICdvYmonOlxuICAgICAgICAgIGNvbXBvbmVudCA9IG1vZGVsTm9kZS5hZGRDb21wb25lbnQoJ21wLm9iakxvYWRlcicsIGluaXRpYWwpO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlICcuZmJ4JzpcbiAgICAgICAgY2FzZSAnZmJ4JzpcbiAgICAgICAgICBjb21wb25lbnQgPSBtb2RlbE5vZGUuYWRkQ29tcG9uZW50KCdtcC5mYnhMb2FkZXInLCBpbml0aWFsKTtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSAnLmdsdGYnOlxuICAgICAgICBjYXNlICdnbHRmJzpcbiAgICAgICAgICBjb21wb25lbnQgPSBtb2RlbE5vZGUuYWRkQ29tcG9uZW50KCdtcC5nbHRmTG9hZGVyJywgaW5pdGlhbCk7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgJy5nbGInOlxuICAgICAgICBjYXNlICdnbGInOlxuICAgICAgICAgIGNvbXBvbmVudCA9IG1vZGVsTm9kZS5hZGRDb21wb25lbnQoJ21wLmdsdGZMb2FkZXInLCBpbml0aWFsKTtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSAnLmRhZSc6XG4gICAgICAgIGNhc2UgJ2RhZSc6XG4gICAgICAgICAgY29tcG9uZW50ID0gbW9kZWxOb2RlLmFkZENvbXBvbmVudCgnbXAuZGFlTG9hZGVyJywgaW5pdGlhbCk7XG4gICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICBjb25zb2xlLmxvZygnRm9ybWF0IG5vdCBzdXBwb3J0ZWQnKTtcbiAgICAgICAgICBicmVhaztcbiAgICAgIH1cblxuICAgICAgLy9jYWNoZSBzeXN0ZW0gKGknbGwgdHJ5IHRvIG1ha2UgaXQgd29yayBsYXRlciAuLi4pXG4gICAgICAvKmxldCBvYmpDb250ZW50c0pTT04gPSBKU09OLnN0cmluZ2lmeShtb2RlbE5vZGUpO1xuICAgICAgY29uc29sZS5sb2cobW9kZWxOb2RlKTtcbiAgICAgIGNvbnNvbGUubG9nKG9iakNvbnRlbnRzSlNPTik7XG4gICAgICBjb25zb2xlLmxvZyhKU09OLnN0cmluZ2lmeShtb2RlbE5vZGUpKTtcbiAgICAgIGxvY2FsU3RvcmFnZS5zZXRJdGVtKGB0ZXN0T2JqXyR7b2JqLm9iamVjdH1gLCBvYmpDb250ZW50c0pTT04pO1xuICAgICAgY29uc29sZS5sb2coXCJzdG9yZWQgPyFcIik7XG4gICAgICBjb25zb2xlLmxvZyh0eXBlb2YgbW9kZWxOb2RlKTsqL1xuICAgICAgLy9sZXQgZGF0YVMgPSBzZXJpYWxpanNlLnNlcmlhbGl6ZShtb2RlbE5vZGUpO1xuICAgICAgLy9jb25zb2xlLmxvZyhkYXRhUyk7XG5cbiAgICAgIC8vIFVzZSAzID8hIEFtYmllbnQgbGlnaHRpbmdzXG4gICAgICBpZiAodGhpcy5ub0xpZ2h0Rm9yT2JqZWN0cykge1xuICAgICAgICBjb25zdCBsaWdodHNOb2RlID0gc2NlbmVPYmplY3QuYWRkTm9kZSgpO1xuICAgICAgICBsaWdodHNOb2RlLmFkZENvbXBvbmVudCgnbXAuYW1iaWVudExpZ2h0Jywge1xuICAgICAgICAgIGludGVuc2l0eTogMSxcbiAgICAgICAgICBjb2xvcjoge3I6IDEuMCwgZzogMS4wLCBiOiAxLjB9LFxuICAgICAgICB9KTtcbiAgICAgICAgdGhpcy5ub0xpZ2h0Rm9yT2JqZWN0cyA9IGZhbHNlO1xuICAgICAgfVxuXG4gICAgICBtb2RlbE5vZGUub2JqM0QucG9zaXRpb24uc2V0KFxuICAgICAgICBvYmoucG9zaXRpb24ueCxcbiAgICAgICAgb2JqLnBvc2l0aW9uLnksXG4gICAgICAgIG9iai5wb3NpdGlvbi56XG4gICAgICApO1xuXG4gICAgICBtb2RlbE5vZGUub2JqM0Qucm90YXRpb24uc2V0KFxuICAgICAgICBvYmoucm90YXRpb24ueCxcbiAgICAgICAgb2JqLnJvdGF0aW9uLnksXG4gICAgICAgIG9iai5yb3RhdGlvbi56XG4gICAgICApO1xuICAgICAgbW9kZWxOb2RlLm9iajNELnNjYWxlLnNldChvYmouc2NhbGUueCwgb2JqLnNjYWxlLnksIG9iai5zY2FsZS56KTtcbiAgICAgIGlmKGlzQXppbXV0aGFsQ3Jvd24pXG4gICAgICB7XG4gICAgICAgIC8qaWYobW9kZWxOb2RlLm9iajNELnNjYWxlLnggPj0gMS4wKXtcbiAgICAgICAgICBtb2RlbE5vZGUub2JqM0Quc2NhbGUuc2V0KG9iai5zY2FsZS54LzUwMDAsIG9iai5zY2FsZS55LzUwMDAsIG9iai5zY2FsZS56LzUwMDApO1xuICAgICAgICB9Ki9cbiAgICAgICAgdGhpcy5hemltdXRoYWxDcm93bj1tb2RlbE5vZGU7XG4gICAgICAgIHRoaXMuZGlzcGxheUF6aW11dGFsQ3Jvd24oKTtcbiAgICAgIH1cblxuICAgICAgLy8gQnkgZGVmYXV0LCBkdXJpbmcgY3JlYXRpb24sIG9iamVjdCBoYXMgdHJhbnNsYXRpb24gZ2l6bW9cbiAgICAgIC8vID0+IFVzZXIgaGFzIHRvIGNsaWNrIG9uIGxhdGVyYWwgcGFuZWwsIGFuZCBzYXZlIGl0cyBwb3NpdGlvbiBhZnRlciBwbGF5aW5nIHdpdGggaXQhXG4gICAgICBpZiAobW9kZSAmJiAhaXNOZXN0VGhlcm1vc3RhdCkge1xuICAgICAgICB0aGlzLmF0dGFjaEdpem1vQ29udHJvbFRvM0RPYmplY3QoXG4gICAgICAgICAgbW9kZWxOb2RlLFxuICAgICAgICAgIHNjZW5lT2JqZWN0LFxuICAgICAgICAgIG1vZGUsXG4gICAgICAgICAgdHJ1ZSxcbiAgICAgICAgICB0cnVlXG4gICAgICAgICkuY2F0Y2goKGUpID0+IGNvbnNvbGUubG9nKGUpKTtcbiAgICAgIH1cblxuICAgICAgaWYgKHRoaXMubGFzdE9iamVjdDNEICYmIHR5cGVvZiB0aGlzLmxhc3RPYmplY3QzRC5pZCA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgLy8gcHJvbXB0IFRocmVlSlMgVVVJRCB0byBtYXRjaCBvdXIgbGFzdCBnZW5lcmF0ZWQgb2JqZWN0IGlmIG5ldyAobm90IGZyb20gRGIpXG4gICAgICAgIG1vZGVsTm9kZS5vYmozRC51dWlkID0gdGhpcy5sYXN0T2JqZWN0M0QuaWQ7XG4gICAgICB9IGVsc2UgaWYgKG9iai5pZCkge1xuICAgICAgICBtb2RlbE5vZGUub2JqM0QudXVpZCA9IG9iai5pZDtcbiAgICAgIH1cbiAgICAgIHRoaXMubGFzdE9iamVjdDNEID0gbW9kZWxOb2RlLm9iajNEO1xuXG4gICAgICAvLyBTdG9yZSB0aGlzIGluIG1lbW9yeSBNYXAgZGljdGlvbm5hcnlcbiAgICAgIC8vY29uc29sZS5sb2coXCJBZGRpbmcgb2JqZWN0OiBcIik7XG4gICAgICAvL2NvbnNvbGUubG9nKG1vZGVsTm9kZSk7XG4gICAgICB0aGlzLmRpY3Rpb25uYXJ5T2JqZWN0czNELnNldChtb2RlbE5vZGUub2JqM0QudXVpZCwgbW9kZWxOb2RlKTtcbiAgICAgIHRoaXMuZGljdGlvbm5hcnlTY2VuZU9iamVjdHMzRC5zZXQobW9kZWxOb2RlLm9iajNELnV1aWQsIHNjZW5lT2JqZWN0KTtcblxuICAgICAgLyp0aGlzLnNkay5DYW1lcmEucG9zZS5zdWJzY3JpYmUoXG4gICAgICAgIGZ1bmN0aW9uIChwb3NlOiBhbnkpIHtcbiAgICAgICAgICAvL2NvbnNvbGUubG9nKFwiaW4gY2FsbGJhY2tcIilcbiAgICAgICAgICAvL2NvbnNvbGUubG9nKHRoaXMubGFzdENhbWVyYVBvc2l0aW9uKVxuICAgICAgICAgIC8vY29uc29sZS5sb2cocG9zZS5wb3NpdGlvbilcbiAgICAgICAgICBpZigocG9zZS5wb3NpdGlvbi54ID09IHRoaXMubGFzdENhbWVyYVBvc2l0aW9uLnggJiYgcG9zZS5wb3NpdGlvbi55ID09IHRoaXMubGFzdENhbWVyYVBvc2l0aW9uLnkgJiYgcG9zZS5wb3NpdGlvbi56ID09IHRoaXMubGFzdENhbWVyYVBvc2l0aW9uLnopIHx8IHRoaXMuaW5UcmFuc2l0aW9uTW9kZSB8fCB0aGlzLmluVHJhbnNpdGlvblN3ZWVwKXtcbiAgICAgICAgICAgIC8vY29uc29sZS5sb2coXCJyZXR1cm5pbmdcIilcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICB9XG4gICAgICAgICAgY29uc29sZS5sb2coXCJjYW1lcmEgcG9zOlwiLHBvc2UucG9zaXRpb24pO1xuICAgICAgICAgIHRoaXMubGFzdENhbWVyYVBvc2l0aW9uID0gey4uLnBvc2UucG9zaXRpb259O1xuICAgICAgICAgIGlmKHRoaXMubGFzdE9iamVjdDNEKXtcbiAgICAgICAgICAgIHRoaXMubGFzdE9iamVjdDNELnBvc2l0aW9uLnNldChwb3NlLnBvc2l0aW9uLngrLjUscG9zZS5wb3NpdGlvbi55Ky41LHBvc2UucG9zaXRpb24ueisuNSk7XG4gICAgICAgICAgfVxuICAgICAgICB9LmJpbmQodGhpcykpOyovXG5cbiAgICAgIGlmIChpc0FuaW1hdGVkU2VjdXJpdHlDYW1lcmEpIHtcblxuICAgICAgICBjb25zdCBhbmltYXRvciA9IG1vZGVsTm9kZS5hZGRDb21wb25lbnQoJ21wLnNlY3VyaXR5Q2FtZXJhJyxcbiAgICAgICAgICB7XG4gICAgICAgICAgICBcIm5lYXJQbGFuZVwiOiAwLjEsXG4gICAgICAgICAgICBcImZhclBsYW5lXCI6IDEwLFxuICAgICAgICAgICAgXCJob3Jpem9udGFsRk9WXCI6IDUyLFxuICAgICAgICAgICAgXCJhc3BlY3RcIjogMS43Nzc3Nzc3Nzc3Nzc3Nzc3LFxuICAgICAgICAgICAgXCJsb2NhbFBvc2l0aW9uXCI6IHtcbiAgICAgICAgICAgICAgXCJ4XCI6IDAuMyxcbiAgICAgICAgICAgICAgXCJ5XCI6IDAuMTgsXG4gICAgICAgICAgICAgIFwielwiOiAwXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgXCJsb2NhbFJvdGF0aW9uXCI6IHtcbiAgICAgICAgICAgICAgXCJ4XCI6IC0xNSxcbiAgICAgICAgICAgICAgXCJ5XCI6IC05MCxcbiAgICAgICAgICAgICAgXCJ6XCI6IDBcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBcImNvbG9yXCI6IDY1MjgwLFxuICAgICAgICAgICAgXCJwYW5QZXJpb2RcIjogNSxcbiAgICAgICAgICAgIFwicGFuQW5nbGVcIjogLTQ1XG4gICAgICAgICAgfSk7XG4gICAgICAgIGNvbnN0IG1vZGVsT3V0cHV0ID0gc2NlbmVPYmplY3QuYWRkUGF0aCh7XG4gICAgICAgICAgaWQ6ICdhbmltYXRlZC1tb2RlbCcsXG4gICAgICAgICAgdHlwZTogdGhpcy5zZGsuU2NlbmUuUGF0aFR5cGUuT1VUUFVULFxuICAgICAgICAgIG5vZGU6IG1vZGVsTm9kZSxcbiAgICAgICAgICBjb21wb25lbnQ6IGFuaW1hdG9yLFxuICAgICAgICAgIHByb3BlcnR5OiAnb2JqZWN0Um9vdCdcbiAgICAgICAgfSk7XG5cbiAgICAgICAgdGhpcy5zZWN1cml0eUNhbWVyYUFuaW1hdG9yID0gYW5pbWF0b3I7XG4gICAgICAgIGlmICghb2JqLnZpZXdGcnVzdHVtKSB7XG4gICAgICAgICAgc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICAgICAgICBhbmltYXRvci50b2dnbGVWaWV3RnJ1c3R1bSgpO1xuICAgICAgICAgIH0sIDEwMDApO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGlmIChpc05lc3RUaGVybW9zdGF0KSB7XG4gICAgICAgIC8vIFRPRE86IHVzZSBiaW5kUGF0aCBpbnN0ZWFkIHVzaW5nIE1QIHNkayBjbGFzc2VzIChzZWUgU2VjdXJpdHkgQ2FtZXJhIGV4YW1wbGUpXG4gICAgICAgIC8vIGZvciBUViB1c2VzIENhbnZhc0ltYWdlIGJlbG93IVxuICAgICAgICAvLyBjb25zdCBjaSA9IG5ldyBDYW52YXNJbWFnZSgpO1xuICAgICAgICAvLyBjaS5vbkluaXQoKTtcbiAgICAgICAgY29uc3QgY3YgPSBuZXcgQ2FudmFzUmVuZGVyZXIoKTtcbiAgICAgICAgY3Yub25Jbml0KCk7XG4gICAgICAgIGNvbnN0IHBsYW5lID0gbmV3IFBsYW5lUmVuZGVyZXIoKTtcbiAgICAgICAgcGxhbmUub3V0cHV0cyA9IHtcbiAgICAgICAgICBvYmplY3RSb290OiBuZXcgT2JqZWN0M0QoKSxcbiAgICAgICAgICBjb2xsaWRlcjogbmV3IE9iamVjdDNEKClcbiAgICAgICAgfTtcbiAgICAgICAgY29uc3QgaW5wdXRUZXh0dXJlID0gY3Yub3V0cHV0cy50ZXh0dXJlO1xuICAgICAgICBwbGFuZS5zZXRSb290U2NlbmUodGhpcy50aHJlZUpTU2NlbmUpO1xuICAgICAgICBwbGFuZS5vbkluaXQobW9kZWxOb2RlLCBpbnB1dFRleHR1cmUpO1xuICAgICAgICBjb25zdCBzYyA9IG5ldyBOZXN0VGhlcm1vc3RhdCgpO1xuICAgICAgICBzYy5zZXRDb21wb25lbnQoY29tcG9uZW50LCBwbGFuZSwgY3YpO1xuICAgICAgICBzYy5zZXRSb290U2NlbmUodGhpcy50aHJlZUpTU2NlbmUpO1xuICAgICAgICBzYy5vbkluaXQobW9kZWxOb2RlLCBwbGFuZSwgaW5wdXRUZXh0dXJlKTtcbiAgICAgICAgY3Yuc2V0Q2FudmFzTmVzdFRoZXJtb3N0YXRQYWludGVyKHNjKTtcbiAgICAgICAgc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICAgICAgc2MuaW5wdXRzLmxvYWRpbmdTdGF0ZSA9IFwiTG9hZGVkXCI7XG4gICAgICAgICAgc2Mub25JbnB1dHNVcGRhdGVkKCk7XG4gICAgICAgIH0sIDUwMDApO1xuICAgICAgfVxuXG4gICAgICBpZiAoaXNTbWFydGVycGxhblByb21vdGlvbmFsVmlkZW8pIHtcbiAgICAgICAgLy8gVE9ETzogdXNlIGJpbmRQYXRoIGluc3RlYWQgdXNpbmcgTVAgc2RrIGNsYXNzZXMgKHNlZSBTZWN1cml0eSBDYW1lcmEgZXhhbXBsZSlcbiAgICAgICAgY29uc3Qgc2MgPSBuZXcgVHZQbGF5ZXIoKTtcbiAgICAgICAgc2Muc2V0Q29tcG9uZW50KGNvbXBvbmVudCk7XG4gICAgICAgIHNjLm9uSW5pdChtb2RlbE5vZGUpO1xuICAgICAgICBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgICAgICBzYy5pbnB1dHMubG9hZGluZ1N0YXRlID0gXCJMb2FkZWRcIjtcbiAgICAgICAgICBzYy5vbklucHV0c1VwZGF0ZWQoKTtcbiAgICAgICAgfSwgNTAwMCk7XG4gICAgICB9XG5cbiAgICAgIHNjZW5lT2JqZWN0LnN0YXJ0KCk7XG4gICAgICByZXNvbHZlKHRoaXMubGFzdE9iamVjdDNEKTtcbiAgICB9KTtcbiAgfVxuXG4gIHRvZ2dsZU9iamVjdFZpc2liaWxpdHkob2JqZWN0SWQ6IGFueSl7XG4gICAgbGV0IG9iaiA9IHRoaXMuZGljdGlvbm5hcnlPYmplY3RzM0QuZ2V0KG9iamVjdElkKTtcbiAgICBvYmoub2JqM0QudmlzaWJsZSA9ICFvYmoub2JqM0QudmlzaWJsZTtcbiAgfVxuXG4gIGlzT2JqZWN0VmlzaWJsZShvYmplY3RJZDogYW55KTogYm9vbGVhbiB7XG4gICAgbGV0IG9iaiA9IHRoaXMuZGljdGlvbm5hcnlPYmplY3RzM0QuZ2V0KG9iamVjdElkKTtcbiAgICByZXR1cm4gb2JqLm9iajNELnZpc2libGU7XG4gIH1cblxuICBhc3luYyBwb2ludENhbWVyYVRvM0RPYmplY3Qob2JqZWN0SWQ6IGFueSl7XG4gICAgbGV0IG9iaiA9IHRoaXMuZGljdGlvbm5hcnlPYmplY3RzM0QuZ2V0KG9iamVjdElkKTtcblxuICAgIC8vV2UgY3JlYXRlIGEgdGVtcG9yYXJ5IFRhZ1xuICAgIGNvbnN0IHBvaU9iamVjdCA9IHtcbiAgICAgIGNvb3JkaW5hdGU6IEpTT04uc3RyaW5naWZ5KG9iai5vYmozRC5wb3NpdGlvbiksXG4gICAgICB0eXBlOiBQb2lUeXBlLk9CSkVDVDNELFxuICAgICAgZWxlbWVudElEOiBvYmplY3RJZCwgLy90b2RvOiBiZSBjYXJlZnVsIHdpdGggdGhpc1xuICAgIH0gYXMgUE9JO1xuICAgIGNvbnN0IG9iamVjdERiID0ge2lkOiBvYmplY3RJZH0gYXMgRGJPYmplY3RUeXBlO1xuXG4gICAgdHJ5e1xuICAgICAgYXdhaXQgdGhpcy5jcmVhdGVNYXR0ZXJ0YWdGcm9tUE9JKFBvaVR5cGUuT0JKRUNUM0QsIG9iamVjdERiLCBwb2lPYmplY3QpO1xuICAgIH1jYXRjaChlcnI6IGFueSl7fVxuXG4gICAgLy9Ob3QgcmVhbGx5IG5lY2Vzc2FyeSBhbnltb3JlIHNpbmNlIHRoZSB0YWcgd2lsbCBkaXNhcHBlYXIgcXVpY2tcbiAgICAvL3RoaXMuc2RrLlRhZy5lZGl0T3BhY2l0eShtYXR0ZXJ0YWdJRCwgMC4wKTsvL29wYWNpdHkpO1xuICAgIC8vdGhpcy5zZGsuVGFnLmFsbG93QWN0aW9uKG1hdHRlcnRhZ0lELCB7fSk7IC8vZGlzYWJsZXMgZXZlcnkgYWN0aW9uXG5cbiAgICBsZXQgcmVzdWx0ID0gdGhpcy5nZXRUYWdGcm9tRWxlbWVudElkKG9iamVjdElkKTtcblxuICAgIGF3YWl0IHRoaXMuZ29Ub1RhZyhyZXN1bHQudGFnKTtcbiAgICB0aGlzLmRlbGV0ZUxhc3RNYXR0ZXJ0YWcoKTtcbiAgfVxuXG4gIGdldFNjZW5lTm9kZUZyb21PYmplY3QzRElkKHV1aWQ6IHN0cmluZyk6IGFueSB7XG4gICAgcmV0dXJuIHRoaXMuZGljdGlvbm5hcnlTY2VuZU9iamVjdHMzRC5nZXQodXVpZCk7XG4gIH1cblxuICBhc3luYyBkaXNwbGF5QXppbXV0YWxDcm93bigpe1xuICAgIGlmKHRoaXMuYXppbXV0aGFsQ3Jvd24pe1xuICAgICAgdGhpcy5hemltdXRoYWxDcm93bi5vYmozRC5wb3NpdGlvbi5zZXQodGhpcy5wb3NlQ2FtZXJhLnBvc2l0aW9uLngsdGhpcy5wb3NlQ2FtZXJhLnBvc2l0aW9uLnksdGhpcy5wb3NlQ2FtZXJhLnBvc2l0aW9uLnopXG4gICAgfVxuICB9XG5cbiAgYXN5bmMgYXR0YWNoR2l6bW9Db250cm9sVG8zRE9iamVjdChcbiAgICBtb2RlbE5vZGU6IGFueSxcbiAgICBzY2VuZU9iamVjdDogYW55LFxuICAgIG1vZGU6ICd0cmFuc2xhdGUnIHwgJ3JvdGF0ZScgfCAnc2NhbGUnLFxuICAgIHZpc2libGU6IGJvb2xlYW4sXG4gICAgaXNOZXdPYmplY3Q6IGJvb2xlYW5cbiAgKTogUHJvbWlzZTxhbnk+IHtcbiAgICAvLyBDcmVhdGUgYSBzY2VuZSBub2RlIHdpdGggYSB0cmFuc2Zvcm0gY29udHJvbCBjb21wb25lbnQuXG4gICAgbGV0IG5vZGUgPSBudWxsO1xuICAgIG5vZGUgPSBzY2VuZU9iamVjdC5hZGROb2RlKCk7XG4gICAgaWYgKCFub2RlKSB7XG4gICAgICBjb25zdCBbc2NlbmVPYmplY3RdID0gYXdhaXQgdGhpcy5zZGsuU2NlbmUuY3JlYXRlT2JqZWN0cygxKTtcbiAgICAgIG5vZGUgPSBzY2VuZU9iamVjdC5hZGROb2RlKCk7XG4gICAgfVxuXG4gICAgY29uc3QgbXlDb250cm9sID0gbm9kZS5hZGRDb21wb25lbnQoJ21wLnRyYW5zZm9ybUNvbnRyb2xzJyk7XG4gICAgbm9kZS5zdGFydCgpO1xuICAgIC8vXG4gICAgLy8gLy8gTWFrZSB0aGUgdHJhbnNmb3JtIGNvbnRyb2wgdmlzaWJsZSBzbyB0aGF0IHRoZSB1c2VyIGNhbiBtYW5pcHVsYXRlIHRoZSBjb250cm9sIHNlbGVjdGlvbi5cbiAgICBteUNvbnRyb2wudHJhbnNmb3JtQ29udHJvbHMudmlzaWJsZSA9IHZpc2libGU7XG4gICAgLy9cbiAgICAvLyAvLyBBdHRhY2ggdGhlIG1vZGVsIHRvIHRoZSB0cmFuc2Zvcm0gY29udHJvbFxuICAgIG15Q29udHJvbC5pbnB1dHMuc2VsZWN0aW9uID0gbW9kZWxOb2RlO1xuICAgIC8vXG4gICAgLy8gLy8gc2V0ICd0cmFuc2xhdGUnIG1vZGUgdG8gcG9zaXRpb24gdGhlIHNlbGVjdGlvbi5cbiAgICBteUNvbnRyb2wuaW5wdXRzLm1vZGUgPSBtb2RlO1xuICAgIG1vZGVsTm9kZS5vYmozRC5jb250cm9scyA9IG15Q29udHJvbDsgLy8gc3RvcmUgZ2l6bW9DdHJsIGluc2lkZSBvYmplY3RcbiAgICBpZihpc05ld09iamVjdCl7IC8vaSBrZWVwIHRoZSBjdXJyZW50IHNvbHV0aW9uIGZvciBuZXcgb2JqZWN0c1xuICAgICAgaWYgKCF0aGlzLmxhc3RPYmplY3QzRCB8fCAhdGhpcy5sYXN0T2JqZWN0M0QuY29udHJvbHMpIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBtb2RlbE5vZGUub2JqM0QudXVpZCA9IHRoaXMubGFzdE9iamVjdDNELnV1aWQgfHwgdGhpcy5sYXN0T2JqZWN0M0QuaWQ7XG4gICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICBjb25zb2xlLmxvZyhgaWQgb2JqIGluIFNjZW5lIHdhcyBub3QgYXNzaWduZWQgdG8gaWQgZnJvbSBEQiBzaW5jZWApO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMubGFzdE9iamVjdDNEID0gbW9kZWxOb2RlLm9iajNEO1xuICAgICAgfVxuICAgIH1lbHNley8vb2JqZWN0cyBhbHJlYWR5IGluIHBsYWNlIGhhdmUgdG8gYmVjb21lIHRoZSBcImxhc3RPYmplY3RcIiAoaSB0aGluaz8pXG4gICAgICBjb25zb2xlLmxvZyhcImluIG15IHNvbHV0aW9uICFcIik7XG4gICAgICBjb25zb2xlLmxvZyhtb2RlbE5vZGUpO1xuICAgICAgY29uc29sZS5sb2cobW9kZWxOb2RlLm9iajNELnV1aWQpO1xuICAgICAgdGhpcy5sYXN0T2JqZWN0M0QgPSBtb2RlbE5vZGUub2JqM0Q7XG4gICAgfVxuXG4gICAgcmV0dXJuIG1vZGVsTm9kZTtcbiAgfVxuXG4gIHJlbW92ZUdpem1vRnJvbUxhc3RPYmplY3QoKTogdm9pZCB7XG4gICAgdGhpcy5sYXN0T2JqZWN0M0QuY29udHJvbHMudHJhbnNmb3JtQ29udHJvbHMudmlzaWJsZSA9IGZhbHNlO1xuICAgIHRoaXMubGFzdE9iamVjdDNELmNvbnRyb2xzLnRyYW5zZm9ybUNvbnRyb2xzLmRpc3Bvc2UoKTtcbiAgICB0aGlzLmxhc3RPYmplY3QzRC5jb250cm9scyA9IG51bGw7XG4gIH1cblxuICB0b2dnbGVWaWV3RnJ1c3R1bSgpOiB2b2lkIHtcbiAgICB0aGlzLnNlY3VyaXR5Q2FtZXJhQW5pbWF0b3IudG9nZ2xlVmlld0ZydXN0dW0oKTtcbiAgfVxuXG4gLypwdWJsaWMgc2V0M0RPYmplY3RNb2RlKG1vZGVsTm9kZTogYW55LCBtb2RlPzogc3RyaW5nKSB7XG4gICBpZiAobW9kZSkge1xuICAgICB0aGlzLm9iamVjdENvbnRyb2wuaW5wdXRzLnNlbGVjdGlvbiA9IG1vZGVsTm9kZTtcbiAgICAgdGhpcy5vYmplY3RDb250cm9sLmlucHV0cy52aXNpYmxlID0gdHJ1ZTtcbiAgICAgdGhpcy5vYmplY3RDb250cm9sLmlucHV0cy5tb2RlID0gbW9kZTtcblxuICAgICBzZXRJbnRlcnZhbCgoKSA9PiB7XG4gICAgICAgY29uc29sZS5sb2cobW9kZWxOb2RlKTtcbiAgICAgfSwgNTAwMCk7XG5cbiAgIH0gZWxzZSB7XG4gICAgIHRoaXMub2JqZWN0Q29udHJvbC5pbnB1dHMudmlzaWJsZSA9IHRydWU7XG4gICB9XG4gfSovXG59XG4iXX0=