@smarterplan/ngx-smarterplan-core 1.4.5 → 1.4.7

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 (41) hide show
  1. package/esm2022/lib/helpers.service.mjs +27 -20
  2. package/esm2022/lib/mattertagData.mjs +84 -84
  3. package/esm2022/lib/pipes/time-date-to-local-string.pipe.mjs +3 -8
  4. package/esm2022/lib/services/locale.service.mjs +3 -5
  5. package/esm2022/lib/services/matterport-import.service.mjs +3 -3
  6. package/esm2022/lib/services/matterport-measurement.service.mjs +78 -0
  7. package/esm2022/lib/services/matterport-navigation.service.mjs +157 -0
  8. package/esm2022/lib/services/matterport-object3d.service.mjs +234 -0
  9. package/esm2022/lib/services/matterport-pointer.service.mjs +130 -0
  10. package/esm2022/lib/services/matterport-tag.service.mjs +458 -0
  11. package/esm2022/lib/services/matterport.service.mjs +427 -988
  12. package/esm2022/lib/services/models/equipment.service.mjs +3 -4
  13. package/esm2022/lib/services/models/feature.service.mjs +3 -3
  14. package/esm2022/lib/services/models/measurement.service.mjs +3 -3
  15. package/esm2022/lib/services/models/ticket.service.mjs +3 -4
  16. package/esm2022/lib/services/navigator.service.mjs +10 -2
  17. package/esm2022/lib/services/tag.service.mjs +45 -19
  18. package/esm2022/lib/services/viewer.service.mjs +51 -16
  19. package/esm2022/lib/types.service.mjs +1 -1
  20. package/fesm2022/smarterplan-ngx-smarterplan-core.mjs +2028 -1490
  21. package/fesm2022/smarterplan-ngx-smarterplan-core.mjs.map +1 -1
  22. package/lib/helpers.service.d.ts +6 -0
  23. package/lib/mattertagData.d.ts +52 -10
  24. package/lib/services/matterport-measurement.service.d.ts +35 -0
  25. package/lib/services/matterport-navigation.service.d.ts +38 -0
  26. package/lib/services/matterport-object3d.service.d.ts +31 -0
  27. package/lib/services/matterport-pointer.service.d.ts +31 -0
  28. package/lib/services/matterport-tag.service.d.ts +104 -0
  29. package/lib/services/matterport.service.d.ts +91 -92
  30. package/lib/services/models/equipment.service.d.ts +2 -2
  31. package/lib/services/models/feature.service.d.ts +2 -2
  32. package/lib/services/models/measurement.service.d.ts +2 -2
  33. package/lib/services/models/ticket.service.d.ts +2 -2
  34. package/lib/services/tag.service.d.ts +4 -0
  35. package/lib/services/viewer.service.d.ts +1 -1
  36. package/lib/types.service.d.ts +2 -0
  37. package/package.json +21 -1
  38. package/esm2022/lib/matterport-extensions/hsl-loader/HlsLoader.mjs +0 -66
  39. package/esm2022/lib/matterport-extensions/video-renderer/VideoRenderer.mjs +0 -63
  40. package/lib/matterport-extensions/hsl-loader/HlsLoader.d.ts +0 -26
  41. package/lib/matterport-extensions/video-renderer/VideoRenderer.d.ts +0 -26
@@ -0,0 +1,458 @@
1
+ import { isDevMode, Injectable } from '@angular/core';
2
+ import { Subject } from 'rxjs';
3
+ import { MattertagData } from '../mattertagData';
4
+ import { TagAction, CameraMode } from '../types.service';
5
+ import { wait } from '../helpers.service';
6
+ import * as i0 from "@angular/core";
7
+ import * as i1 from "./matterport-navigation.service";
8
+ export class MatterportTagService {
9
+ navigationService;
10
+ dictionnaryTags = new Map();
11
+ tagAddQueue = Promise.resolve();
12
+ mattertagToFollow = null;
13
+ onGoToTag = new Subject();
14
+ mattertagIDs = [];
15
+ tagsAttachments = {};
16
+ tagMessengerOn = false;
17
+ tagService = null;
18
+ tagsCurrentOpacity = new Map();
19
+ tagsCurrentEnabled = new Map();
20
+ constructor(navigationService) {
21
+ this.navigationService = navigationService;
22
+ }
23
+ setTagService(service) {
24
+ this.tagService = service;
25
+ }
26
+ /** Opens a specific tag in the Matterport viewer by its ID. */
27
+ async goToTag(sdk, sid) {
28
+ if (!sdk)
29
+ return;
30
+ try {
31
+ this.onGoToTag.next(sid);
32
+ await sdk.Tag.open(sid);
33
+ }
34
+ catch (e) {
35
+ if (isDevMode())
36
+ console.warn('Cannot open tag', sid, e);
37
+ }
38
+ }
39
+ /** Opens the most recently created tag in the viewer. */
40
+ async goToLastTag(sdk) {
41
+ if (!sdk || this.mattertagIDs.length === 0)
42
+ return;
43
+ const lastSid = this.mattertagIDs[this.mattertagIDs.length - 1];
44
+ return this.goToTag(sdk, lastSid);
45
+ }
46
+ /**
47
+ * Adds a Mattertag to the viewer, serializing calls to prevent SDK race conditions.
48
+ * Reuses existing IDs if the tag is already present in the session.
49
+ */
50
+ async addMattertagToViewer(sdk, mattertagData) {
51
+ if (!sdk)
52
+ return null;
53
+ this.tagAddQueue = this.tagAddQueue.then(async () => {
54
+ const data = mattertagData.getData();
55
+ const existingId = data?.id || null;
56
+ try {
57
+ const sidList = await sdk.Tag.add(data);
58
+ if (sidList && sidList.length > 0) {
59
+ const mattertagID = sidList[0];
60
+ this.mattertagIDs.push(mattertagID);
61
+ this.dictionnaryTags.set(mattertagID, mattertagData);
62
+ return mattertagID;
63
+ }
64
+ }
65
+ catch (error) {
66
+ if (error?.message?.includes('already in use') && existingId) {
67
+ if (!this.dictionnaryTags.has(existingId)) {
68
+ this.mattertagIDs.push(existingId);
69
+ this.dictionnaryTags.set(existingId, mattertagData);
70
+ }
71
+ return existingId;
72
+ }
73
+ if (isDevMode())
74
+ console.warn('Failed to add tag to viewer', error);
75
+ }
76
+ return null;
77
+ });
78
+ return this.tagAddQueue;
79
+ }
80
+ /**
81
+ * Internal method to add and configure a Mattertag with icon, opacity, and HTML content.
82
+ * Handles existing tags gracefully and queues operations to avoid SDK conflicts.
83
+ */
84
+ async _doAddMattertag(sdk, mattertagData, setTagIconAndOpacity, injectHtmlInTag) {
85
+ const descriptor = mattertagData.getMattertagDescriptor();
86
+ //console.log('descriptor', descriptor);
87
+ const sid = descriptor[0]['id'];
88
+ if (sid && this.dictionnaryTags.has(sid)) {
89
+ await setTagIconAndOpacity(sid, mattertagData);
90
+ await injectHtmlInTag(mattertagData.getType(), mattertagData.getObject(), sid);
91
+ return sid;
92
+ }
93
+ this.tagAddQueue = this.tagAddQueue.then(async () => {
94
+ try {
95
+ const [createdSid] = await sdk.Tag.add(...descriptor);
96
+ this.mattertagIDs.push(createdSid);
97
+ this.dictionnaryTags.set(createdSid, mattertagData);
98
+ await wait(100);
99
+ await setTagIconAndOpacity(createdSid, mattertagData);
100
+ injectHtmlInTag(mattertagData.getType(), mattertagData.getObject(), createdSid).catch(err => {
101
+ if (isDevMode())
102
+ console.warn('HTML injection failed for', createdSid, err);
103
+ });
104
+ return createdSid;
105
+ }
106
+ catch (e) {
107
+ if (e?.message?.includes('already in use') && sid) {
108
+ if (!this.dictionnaryTags.has(sid)) {
109
+ this.mattertagIDs.push(sid);
110
+ this.dictionnaryTags.set(sid, mattertagData);
111
+ }
112
+ await setTagIconAndOpacity(sid, mattertagData);
113
+ await injectHtmlInTag(mattertagData.getType(), mattertagData.getObject(), sid);
114
+ return sid;
115
+ }
116
+ throw e;
117
+ }
118
+ });
119
+ return this.tagAddQueue;
120
+ }
121
+ getDistance(p1, p2) {
122
+ return Math.sqrt(Math.pow(p2.x - p1.x, 2) + Math.pow(p2.y - p1.y, 2) + Math.pow(p2.z - p1.z, 2));
123
+ }
124
+ /**
125
+ * Checks if a tag is within the bounding box of any active room (adding a slight margin to account for wall-mounted tags).
126
+ * If there are no active rooms (e.g., hallway), falls back to returning true.
127
+ */
128
+ isTagInRooms(mattertagData, rooms) {
129
+ if (!rooms || rooms.length === 0)
130
+ return false;
131
+ const tagPos = mattertagData.getPosition();
132
+ const margin = 1.5;
133
+ return rooms.some((room) => {
134
+ if (!room.bounds)
135
+ return false;
136
+ const { min, max } = room.bounds;
137
+ return (tagPos.x >= min.x - margin && tagPos.x <= max.x + margin &&
138
+ tagPos.y >= min.y - margin && tagPos.y <= max.y + margin &&
139
+ tagPos.z >= min.z - margin && tagPos.z <= max.z + margin);
140
+ });
141
+ }
142
+ /**
143
+ * Computes the final context-aware opacity for a single tag.
144
+ * @param currentFloorSequence Authoritative current floor sequence from sdk.Floor.current
145
+ * (null = single-floor model or unknown).
146
+ * @param currentRooms Array of active rooms the camera is in.
147
+ */
148
+ /*computeSingleTagContextOpacity(
149
+ mattertagData: MattertagData,
150
+ poseCamera: any,
151
+ sweepCollection: any,
152
+ currentFloorSequence: number | null,
153
+ currentRooms: any[]
154
+ ): number {
155
+ const mode = this.navigationService.currentCameraMode;
156
+
157
+ // 1. Check Floor
158
+ const tagFloorId = this.getFloorIdForTag(mattertagData, sweepCollection);
159
+ const currentFloorId = currentFloorSequence?.toString();
160
+ if (tagFloorId && currentFloorId && tagFloorId !== currentFloorId) {
161
+ return 0;
162
+ }
163
+
164
+ // 2. Si Dollhouse -> Pleine opacité
165
+ //if (mode !== CameraMode.INSIDE) return 1;
166
+
167
+ // 3. Si Inside -> Check pièce + Distance progressive
168
+ //if (!this.isTagInRooms(mattertagData, currentRooms)) return 0;
169
+
170
+ return 1;
171
+ }*/
172
+ /** Returns the ID of the most recently added tag. */
173
+ getLastTag() {
174
+ if (this.mattertagIDs.length === 0)
175
+ return null;
176
+ return this.mattertagIDs[this.mattertagIDs.length - 1];
177
+ }
178
+ /**
179
+ * Updates the visibility (opacity) of all tags based on the current camera mode,
180
+ * floor and room context. Must be called after each sweep, floor or mode change.
181
+ *
182
+ * Rules:
183
+ * - DOLLHOUSE / FLOORPLAN → all tags hidden (opacity 0).
184
+ * - INSIDE → only tags whose sweep belongs to the current floor are shown;
185
+ * proximity-based opacity is applied via computeTagOpacity().
186
+ * Tags on other floors are hidden (opacity 0).
187
+ * - TRANSITIONING → no change (skip update to avoid flickering).
188
+ *
189
+ * @param sdk Matterport SDK instance.
190
+ * @param poseCamera Current camera pose.
191
+ * @param sweepCollection Full collection of sweeps.
192
+ * @param currentCameraMode Current camera mode.
193
+ * @param mattertagToFollow ID of the cursor tag (never touched).
194
+ */
195
+ async updateTagsVisibilityForContext(sdk, sweepCollection, currentCameraMode, mattertagToFollow, currentFloorSequence = null, currentRooms = []) {
196
+ if (!sdk || this.dictionnaryTags.size === 0)
197
+ return;
198
+ const isInteriorMode = currentCameraMode === CameraMode.INSIDE;
199
+ const currentFloorId = currentFloorSequence !== null ? currentFloorSequence.toString() : null;
200
+ const promises = [];
201
+ for (const [tagId, mattertagData] of this.dictionnaryTags) {
202
+ if (tagId === mattertagToFollow)
203
+ continue;
204
+ const tagFloorId = this.getFloorIdForTag(mattertagData, sweepCollection);
205
+ const isOnCurrentFloor = !tagFloorId || !currentFloorId || tagFloorId === currentFloorId;
206
+ let targetOpacity = 0;
207
+ let shouldBeEnabled = false;
208
+ // Calculation of opacity and enable status
209
+ if (isOnCurrentFloor) {
210
+ if (!isInteriorMode) {
211
+ targetOpacity = 1;
212
+ shouldBeEnabled = true;
213
+ }
214
+ else {
215
+ targetOpacity = 0.9;
216
+ shouldBeEnabled = true;
217
+ }
218
+ }
219
+ // Apply changes
220
+ // Tooltip and click management
221
+ const lastEnabled = this.tagsCurrentEnabled.get(tagId);
222
+ if (lastEnabled !== shouldBeEnabled) {
223
+ this.tagsCurrentEnabled.set(tagId, shouldBeEnabled);
224
+ promises.push(sdk.Tag.allowAction(tagId, {
225
+ opening: shouldBeEnabled,
226
+ navigating: shouldBeEnabled,
227
+ docking: false
228
+ }).catch(() => { }));
229
+ }
230
+ // Opacity management
231
+ const lastOpacity = this.tagsCurrentOpacity.get(tagId) ?? -1;
232
+ if (Math.abs(lastOpacity - targetOpacity) > 0.05) {
233
+ this.tagsCurrentOpacity.set(tagId, targetOpacity);
234
+ promises.push(sdk.Tag.editOpacity(tagId, targetOpacity).catch(() => { }));
235
+ }
236
+ }
237
+ await Promise.all(promises);
238
+ }
239
+ /** Removes a specific tag from the viewer and local dictionaries. */
240
+ async deleteMattertagFromId(sdk, mattertagID) {
241
+ try {
242
+ if (sdk)
243
+ await sdk.Tag.remove(mattertagID);
244
+ this.dictionnaryTags.delete(mattertagID);
245
+ const index = this.mattertagIDs.indexOf(mattertagID);
246
+ if (index > -1)
247
+ this.mattertagIDs.splice(index, 1);
248
+ }
249
+ catch (e) {
250
+ if (isDevMode())
251
+ console.warn('Cannot delete tag', mattertagID, e);
252
+ }
253
+ }
254
+ /** Removes the last added tag from the viewer. */
255
+ async deleteLastMattertag(sdk) {
256
+ const lastSid = this.getLastTag();
257
+ if (lastSid)
258
+ await this.deleteMattertagFromId(sdk, lastSid);
259
+ }
260
+ /** Clears all tags from the viewer and resets local state. */
261
+ async action_delete_all_mattertags(sdk) {
262
+ if (sdk) {
263
+ const sidsToRemove = [...this.mattertagIDs];
264
+ for (const sid of sidsToRemove) {
265
+ try {
266
+ await sdk.Tag.remove(sid);
267
+ }
268
+ catch (e) { }
269
+ }
270
+ }
271
+ this.clear();
272
+ }
273
+ /**
274
+ * Creates and configures a Mattertag from a POI, handling coordinates, normals, and sweep ID.
275
+ * Skips creation if a tag for the object already exists.
276
+ */
277
+ async createMattertagFromPOI(sdk, tagType, object, poi, poseCamera, getTagFromElementId, setTagIconAndOpacity, injectHtmlInTag) {
278
+ const { tag } = getTagFromElementId(object.id);
279
+ if (tag)
280
+ return;
281
+ const mattertagData = new MattertagData(tagType);
282
+ mattertagData.setObject(object, tagType);
283
+ if (poi.coordinate) {
284
+ try {
285
+ mattertagData.setPosition(JSON.parse(poi.coordinate));
286
+ }
287
+ catch (e) {
288
+ if (isDevMode())
289
+ console.warn('Error parsing POI coordinates', poi.coordinate);
290
+ }
291
+ }
292
+ if (poi.metadata) {
293
+ try {
294
+ const tagMetadata = JSON.parse(poi.metadata);
295
+ mattertagData.setNormal(tagMetadata.normal || { x: 0, y: -0.15, z: 0 });
296
+ }
297
+ catch (e) {
298
+ mattertagData.setNormal({ x: 0, y: -0.15, z: 0 });
299
+ }
300
+ }
301
+ if (poi.matterportSweepID) {
302
+ mattertagData.setSweepID(poi.matterportSweepID);
303
+ }
304
+ mattertagData.setPoi(poi);
305
+ const createdTagID = await this.addMattertagToViewer(sdk, mattertagData);
306
+ if (createdTagID && sdk) {
307
+ await wait(100);
308
+ await setTagIconAndOpacity(createdTagID, mattertagData);
309
+ injectHtmlInTag(tagType, object, createdTagID).catch(err => {
310
+ if (isDevMode())
311
+ console.warn('HTML injection failed for', createdTagID, err);
312
+ });
313
+ }
314
+ return createdTagID;
315
+ }
316
+ /** Updates the icon, opacity, and HTML content of an existing tag. */
317
+ async updateMatterTagContentForTagID(sdk, mattertagID, object, poiType, setTagIconAndOpacity, injectHtmlInTag) {
318
+ const mattertagData = this.dictionnaryTags.get(mattertagID);
319
+ if (!mattertagData)
320
+ return;
321
+ if (object) {
322
+ mattertagData.setObject(object, poiType);
323
+ }
324
+ await setTagIconAndOpacity(mattertagID, mattertagData);
325
+ await injectHtmlInTag(poiType, object, mattertagID);
326
+ }
327
+ /** Registers a custom texture and applies it to a tag, optionally adjusting opacity. */
328
+ async addNewIconAndSetForTag(sdk, mattertagID, iconPath, applyOpacity, opacity) {
329
+ if (!sdk)
330
+ return;
331
+ try {
332
+ const iconName = `custom-icon-${mattertagID}`;
333
+ await sdk.Asset.registerTexture(iconName, iconPath);
334
+ await sdk.Tag.editIcon(mattertagID, iconName);
335
+ if (applyOpacity) {
336
+ await sdk.Tag.editOpacity(mattertagID, opacity);
337
+ }
338
+ }
339
+ catch (error) {
340
+ if (isDevMode())
341
+ console.warn('Error setting custom icon or opacity', error);
342
+ }
343
+ }
344
+ /** Finds the tag ID and sweep ID associated with a specific element ID. */
345
+ getTagFromElementId(elementID, sweeps) {
346
+ let tagID = null;
347
+ let sweepID = null;
348
+ for (let [mattertagID, mattertagData] of this.dictionnaryTags) {
349
+ if (mattertagData.elementID === elementID) {
350
+ tagID = mattertagID;
351
+ const sweep = mattertagData.getSweepID();
352
+ if (sweep && sweeps && sweeps.includes(sweep)) {
353
+ sweepID = sweep;
354
+ }
355
+ }
356
+ }
357
+ return { tag: tagID, sweep: sweepID };
358
+ }
359
+ /** Retrieves the floor identifier associated with a tag based on its sweep data.
360
+ * Handles both the object form ({ floorInfo: { id, sequence }, floor: { id } })
361
+ * and the primitive form (floor: number) used by Matterport SDK v3.
362
+ */
363
+ getFloorIdForTag(mattertagData, sweepCollection) {
364
+ const sweepId = mattertagData.getSweepID();
365
+ if (!sweepId || !sweepCollection)
366
+ return null;
367
+ const sweepData = sweepCollection[sweepId];
368
+ if (!sweepData)
369
+ return null;
370
+ // SDK v3: sweep.floor is a primitive number (the sequence index)
371
+ if (typeof sweepData.floor === 'number') {
372
+ return sweepData.floor.toString();
373
+ }
374
+ // Older / extended formats
375
+ return sweepData?.floorInfo?.id
376
+ ?? sweepData?.floorInfo?.sequence?.toString()
377
+ ?? sweepData?.floorId
378
+ ?? sweepData?.floor?.id
379
+ ?? sweepData?.floor?.sequence?.toString()
380
+ ?? null;
381
+ }
382
+ /**
383
+ * Injects custom HTML or fallback billboard media into a Mattertag sandbox.
384
+ * Attaches event listeners for interactive elements within the tag.
385
+ */
386
+ async injectHtmlInTag(sdk, tagType, object, tagID) {
387
+ if (!this.tagService) {
388
+ console.error('[MatterportTagService] tagService is not initialized.');
389
+ return;
390
+ }
391
+ try {
392
+ let html = await this.tagService.getHtmlToInject(tagType, object);
393
+ if (html && html.trim().length > 0 && sdk) {
394
+ const scriptTag = this.tagService.getScriptForTag(object, tagType);
395
+ html += `${scriptTag}`;
396
+ const [sandboxId, messenger] = await sdk.Tag.registerSandbox(html);
397
+ const attachmentID = this.tagsAttachments[tagID];
398
+ if (attachmentID) {
399
+ try {
400
+ await sdk.Tag.detach(tagID, attachmentID);
401
+ }
402
+ catch (e) { }
403
+ }
404
+ this.tagsAttachments[tagID] = sandboxId;
405
+ await sdk.Tag.attach(tagID, sandboxId);
406
+ // Attach the "View informations" handler in tooltip
407
+ messenger.on(TagAction.DETAIL_CLICK, this.tagService.onActionDetailClick.bind(this.tagService));
408
+ messenger.on(TagAction.TICKET_CLICK, this.tagService.onActionDetailClick.bind(this.tagService));
409
+ messenger.on(TagAction.AUDIO_CLICK, (audioCommentID) => this.tagService.onActionAudioClick(audioCommentID));
410
+ messenger.on(TagAction.VIDEO_CLICK, (videoUrl) => this.tagService.onActionVideoClick(videoUrl));
411
+ messenger.on(TagAction.IMAGE_CLICK, (imageCommentID) => this.tagService.onActionImageClick(imageCommentID));
412
+ messenger.on(TagAction.DOC_CLICK, (docUrl) => this.tagService.onActionDocClick(docUrl));
413
+ messenger.on(TagAction.YOUTUBE_CLICK, (youtubeUrl) => this.tagService.onActionYoutubeClick(youtubeUrl));
414
+ }
415
+ else if (sdk) {
416
+ const { comment, tagDescription } = this.tagService.getBillboardMediaToEmbed(object);
417
+ if (comment) {
418
+ const attachmentID = await sdk.Tag.registerAttachment({
419
+ type: 'media',
420
+ data: {
421
+ url: comment.externalLink,
422
+ label: object.title || 'Media',
423
+ },
424
+ });
425
+ await sdk.Tag.attach(tagID, attachmentID);
426
+ const billboardAttachmentID = await sdk.Tag.registerAttachment({
427
+ type: 'billboard',
428
+ data: {
429
+ title: object.title,
430
+ description: tagDescription,
431
+ },
432
+ });
433
+ await sdk.Tag.attach(tagID, billboardAttachmentID);
434
+ this.tagsAttachments[tagID] = billboardAttachmentID;
435
+ }
436
+ }
437
+ }
438
+ catch (error) {
439
+ console.error('[MatterportTagService] Error in injectHtmlInTag:', error);
440
+ }
441
+ }
442
+ /** Clears all local tag data and resets the addition queue. */
443
+ clear() {
444
+ this.dictionnaryTags.clear();
445
+ this.tagAddQueue = Promise.resolve();
446
+ this.mattertagToFollow = null;
447
+ this.mattertagIDs = [];
448
+ }
449
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: MatterportTagService, deps: [{ token: i1.MatterportNavigationService }], target: i0.ɵɵFactoryTarget.Injectable });
450
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: MatterportTagService, providedIn: 'root' });
451
+ }
452
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: MatterportTagService, decorators: [{
453
+ type: Injectable,
454
+ args: [{
455
+ providedIn: 'root',
456
+ }]
457
+ }], ctorParameters: () => [{ type: i1.MatterportNavigationService }] });
458
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWF0dGVycG9ydC10YWcuc2VydmljZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL25neC1zbWFydGVycGxhbi1jb3JlL3NyYy9saWIvc2VydmljZXMvbWF0dGVycG9ydC10YWcuc2VydmljZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsU0FBUyxFQUFFLFVBQVUsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUN0RCxPQUFPLEVBQUUsT0FBTyxFQUFFLE1BQU0sTUFBTSxDQUFDO0FBQy9CLE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQztBQUNqRCxPQUFPLEVBQWtELFNBQVMsRUFBRSxVQUFVLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQztBQUV6RyxPQUFPLEVBQUUsSUFBSSxFQUFFLE1BQU0sb0JBQW9CLENBQUM7OztBQU0xQyxNQUFNLE9BQU8sb0JBQW9CO0lBYXJCO0lBWkgsZUFBZSxHQUErQixJQUFJLEdBQUcsRUFBRSxDQUFDO0lBQ3hELFdBQVcsR0FBaUIsT0FBTyxDQUFDLE9BQU8sRUFBRSxDQUFDO0lBQzlDLGlCQUFpQixHQUFrQixJQUFJLENBQUM7SUFDeEMsU0FBUyxHQUFHLElBQUksT0FBTyxFQUFVLENBQUM7SUFDbEMsWUFBWSxHQUFrQixFQUFFLENBQUM7SUFDakMsZUFBZSxHQUFXLEVBQUUsQ0FBQztJQUM3QixjQUFjLEdBQVksS0FBSyxDQUFDO0lBQ2hDLFVBQVUsR0FBMEIsSUFBSSxDQUFDO0lBQ3hDLGtCQUFrQixHQUF3QixJQUFJLEdBQUcsRUFBRSxDQUFDO0lBQ3BELGtCQUFrQixHQUF5QixJQUFJLEdBQUcsRUFBRSxDQUFDO0lBRTdELFlBQ1UsaUJBQThDO1FBQTlDLHNCQUFpQixHQUFqQixpQkFBaUIsQ0FBNkI7SUFDcEQsQ0FBQztJQUVMLGFBQWEsQ0FBQyxPQUF1QjtRQUNuQyxJQUFJLENBQUMsVUFBVSxHQUFHLE9BQU8sQ0FBQztJQUM1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RSxLQUFLLENBQUMsQ0FBQztRQUMzRSxDQUFDO0lBQ0gsQ0FBQztJQUVELCtEQUErRDtJQUMvRCxLQUFLO1FBQ0gsSUFBSSxDQUFDLGVBQWUsQ0FBQyxLQUFLLEVBQUUsQ0FBQztRQUM3QixJQUFJLENBQUMsV0FBVyxHQUFHLE9BQU8sQ0FBQyxPQUFPLEVBQUUsQ0FBQztRQUNyQyxJQUFJLENBQUMsaUJBQWlCLEdBQUcsSUFBSSxDQUFDO1FBQzlCLElBQUksQ0FBQyxZQUFZLEdBQUcsRUFBRSxDQUFDO0lBQ3pCLENBQUM7d0dBdGZVLG9CQUFvQjs0R0FBcEIsb0JBQW9CLGNBRm5CLE1BQU07OzRGQUVQLG9CQUFvQjtrQkFIaEMsVUFBVTttQkFBQztvQkFDVixVQUFVLEVBQUUsTUFBTTtpQkFDbkIiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBpc0Rldk1vZGUsIEluamVjdGFibGUgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcclxuaW1wb3J0IHsgU3ViamVjdCB9IGZyb20gJ3J4anMnO1xyXG5pbXBvcnQgeyBNYXR0ZXJ0YWdEYXRhIH0gZnJvbSAnLi4vbWF0dGVydGFnRGF0YSc7XHJcbmltcG9ydCB7IFBvaVR5cGUsIERiT2JqZWN0VHlwZSwgUE9JLCBWaWV3ZXJJbnRlcmFjdGlvbnMsIFRhZ0FjdGlvbiwgQ2FtZXJhTW9kZSB9IGZyb20gJy4uL3R5cGVzLnNlcnZpY2UnO1xyXG5pbXBvcnQgeyBNYXR0ZXJwb3J0TmF2aWdhdGlvblNlcnZpY2UgfSBmcm9tICcuL21hdHRlcnBvcnQtbmF2aWdhdGlvbi5zZXJ2aWNlJztcclxuaW1wb3J0IHsgd2FpdCB9IGZyb20gJy4uL2hlbHBlcnMuc2VydmljZSc7XHJcbmltcG9ydCB7IEJhc2VUYWdTZXJ2aWNlIH0gZnJvbSAnLi90YWcuc2VydmljZSc7XHJcblxyXG5ASW5qZWN0YWJsZSh7XHJcbiAgcHJvdmlkZWRJbjogJ3Jvb3QnLFxyXG59KVxyXG5leHBvcnQgY2xhc3MgTWF0dGVycG9ydFRhZ1NlcnZpY2Uge1xyXG4gIHB1YmxpYyBkaWN0aW9ubmFyeVRhZ3M6IE1hcDxzdHJpbmcsIE1hdHRlcnRhZ0RhdGE+ID0gbmV3IE1hcCgpO1xyXG4gIHB1YmxpYyB0YWdBZGRRdWV1ZTogUHJvbWlzZTxhbnk+ID0gUHJvbWlzZS5yZXNvbHZlKCk7XHJcbiAgcHVibGljIG1hdHRlcnRhZ1RvRm9sbG93OiBzdHJpbmcgfCBudWxsID0gbnVsbDtcclxuICBwdWJsaWMgb25Hb1RvVGFnID0gbmV3IFN1YmplY3Q8c3RyaW5nPigpO1xyXG4gIHB1YmxpYyBtYXR0ZXJ0YWdJRHM6IEFycmF5PHN0cmluZz4gPSBbXTtcclxuICBwdWJsaWMgdGFnc0F0dGFjaG1lbnRzOiBPYmplY3QgPSB7fTtcclxuICBwdWJsaWMgdGFnTWVzc2VuZ2VyT246IGJvb2xlYW4gPSBmYWxzZTtcclxuICBwdWJsaWMgdGFnU2VydmljZTogQmFzZVRhZ1NlcnZpY2UgfCBudWxsID0gbnVsbDtcclxuICBwcml2YXRlIHRhZ3NDdXJyZW50T3BhY2l0eTogTWFwPHN0cmluZywgbnVtYmVyPiA9IG5ldyBNYXAoKTtcclxuICBwcml2YXRlIHRhZ3NDdXJyZW50RW5hYmxlZDogTWFwPHN0cmluZywgYm9vbGVhbj4gPSBuZXcgTWFwKCk7XHJcblxyXG4gIGNvbnN0cnVjdG9yKFxyXG4gICAgcHJpdmF0ZSBuYXZpZ2F0aW9uU2VydmljZTogTWF0dGVycG9ydE5hdmlnYXRpb25TZXJ2aWNlXHJcbiAgKSB7IH1cclxuXHJcbiAgc2V0VGFnU2VydmljZShzZXJ2aWNlOiBCYXNlVGFnU2VydmljZSk6IHZvaWQge1xyXG4gICAgdGhpcy50YWdTZXJ2aWNlID0gc2VydmljZTtcclxuICB9XHJcblxyXG4gIC8qKiBPcGVucyBhIHNwZWNpZmljIHRhZyBpbiB0aGUgTWF0dGVycG9ydCB2aWV3ZXIgYnkgaXRzIElELiAqL1xyXG4gIGFzeW5jIGdvVG9UYWcoc2RrOiBhbnksIHNpZDogc3RyaW5nKTogUHJvbWlzZTxhbnk+IHtcclxuICAgIGlmICghc2RrKSByZXR1cm47XHJcbiAgICB0cnkge1xyXG4gICAgICB0aGlzLm9uR29Ub1RhZy5uZXh0KHNpZCk7XHJcbiAgICAgIGF3YWl0IHNkay5UYWcub3BlbihzaWQpO1xyXG4gICAgfSBjYXRjaCAoZSkge1xyXG4gICAgICBpZiAoaXNEZXZNb2RlKCkpIGNvbnNvbGUud2FybignQ2Fubm90IG9wZW4gdGFnJywgc2lkLCBlKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIC8qKiBPcGVucyB0aGUgbW9zdCByZWNlbnRseSBjcmVhdGVkIHRhZyBpbiB0aGUgdmlld2VyLiAqL1xyXG4gIGFzeW5jIGdvVG9MYXN0VGFnKHNkazogYW55KTogUHJvbWlzZTxhbnk+IHtcclxuICAgIGlmICghc2RrIHx8IHRoaXMubWF0dGVydGFnSURzLmxlbmd0aCA9PT0gMCkgcmV0dXJuO1xyXG4gICAgY29uc3QgbGFzdFNpZCA9IHRoaXMubWF0dGVydGFnSURzW3RoaXMubWF0dGVydGFnSURzLmxlbmd0aCAtIDFdO1xyXG4gICAgcmV0dXJuIHRoaXMuZ29Ub1RhZyhzZGssIGxhc3RTaWQpO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogQWRkcyBhIE1hdHRlcnRhZyB0byB0aGUgdmlld2VyLCBzZXJpYWxpemluZyBjYWxscyB0byBwcmV2ZW50IFNESyByYWNlIGNvbmRpdGlvbnMuXHJcbiAgICogUmV1c2VzIGV4aXN0aW5nIElEcyBpZiB0aGUgdGFnIGlzIGFscmVhZHkgcHJlc2VudCBpbiB0aGUgc2Vzc2lvbi5cclxuICAgKi9cclxuICBhc3luYyBhZGRNYXR0ZXJ0YWdUb1ZpZXdlcihzZGs6IGFueSwgbWF0dGVydGFnRGF0YTogTWF0dGVydGFnRGF0YSk6IFByb21pc2U8c3RyaW5nIHwgbnVsbD4ge1xyXG4gICAgaWYgKCFzZGspIHJldHVybiBudWxsO1xyXG5cclxuICAgIHRoaXMudGFnQWRkUXVldWUgPSB0aGlzLnRhZ0FkZFF1ZXVlLnRoZW4oYXN5bmMgKCkgPT4ge1xyXG4gICAgICBjb25zdCBkYXRhID0gbWF0dGVydGFnRGF0YS5nZXREYXRhKCkgYXMgYW55O1xyXG4gICAgICBjb25zdCBleGlzdGluZ0lkID0gZGF0YT8uaWQgfHwgbnVsbDtcclxuXHJcbiAgICAgIHRyeSB7XHJcbiAgICAgICAgY29uc3Qgc2lkTGlzdCA9IGF3YWl0IHNkay5UYWcuYWRkKGRhdGEpO1xyXG4gICAgICAgIGlmIChzaWRMaXN0ICYmIHNpZExpc3QubGVuZ3RoID4gMCkge1xyXG4gICAgICAgICAgY29uc3QgbWF0dGVydGFnSUQgPSBzaWRMaXN0WzBdO1xyXG4gICAgICAgICAgdGhpcy5tYXR0ZXJ0YWdJRHMucHVzaChtYXR0ZXJ0YWdJRCk7XHJcbiAgICAgICAgICB0aGlzLmRpY3Rpb25uYXJ5VGFncy5zZXQobWF0dGVydGFnSUQsIG1hdHRlcnRhZ0RhdGEpO1xyXG4gICAgICAgICAgcmV0dXJuIG1hdHRlcnRhZ0lEO1xyXG4gICAgICAgIH1cclxuICAgICAgfSBjYXRjaCAoZXJyb3I6IGFueSkge1xyXG4gICAgICAgIGlmIChlcnJvcj8ubWVzc2FnZT8uaW5jbHVkZXMoJ2FscmVhZHkgaW4gdXNlJykgJiYgZXhpc3RpbmdJZCkge1xyXG4gICAgICAgICAgaWYgKCF0aGlzLmRpY3Rpb25uYXJ5VGFncy5oYXMoZXhpc3RpbmdJZCkpIHtcclxuICAgICAgICAgICAgdGhpcy5tYXR0ZXJ0YWdJRHMucHVzaChleGlzdGluZ0lkKTtcclxuICAgICAgICAgICAgdGhpcy5kaWN0aW9ubmFyeVRhZ3Muc2V0KGV4aXN0aW5nSWQsIG1hdHRlcnRhZ0RhdGEpO1xyXG4gICAgICAgICAgfVxyXG4gICAgICAgICAgcmV0dXJuIGV4aXN0aW5nSWQ7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGlmIChpc0Rldk1vZGUoKSkgY29uc29sZS53YXJuKCdGYWlsZWQgdG8gYWRkIHRhZyB0byB2aWV3ZXInLCBlcnJvcik7XHJcbiAgICAgIH1cclxuICAgICAgcmV0dXJuIG51bGw7XHJcbiAgICB9KTtcclxuXHJcbiAgICByZXR1cm4gdGhpcy50YWdBZGRRdWV1ZTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIEludGVybmFsIG1ldGhvZCB0byBhZGQgYW5kIGNvbmZpZ3VyZSBhIE1hdHRlcnRhZyB3aXRoIGljb24sIG9wYWNpdHksIGFuZCBIVE1MIGNvbnRlbnQuXHJcbiAgICogSGFuZGxlcyBleGlzdGluZyB0YWdzIGdyYWNlZnVsbHkgYW5kIHF1ZXVlcyBvcGVyYXRpb25zIHRvIGF2b2lkIFNESyBjb25mbGljdHMuXHJcbiAgICovXHJcbiAgYXN5bmMgX2RvQWRkTWF0dGVydGFnKFxyXG4gICAgc2RrOiBhbnksXHJcbiAgICBtYXR0ZXJ0YWdEYXRhOiBNYXR0ZXJ0YWdEYXRhLFxyXG4gICAgc2V0VGFnSWNvbkFuZE9wYWNpdHk6IChzaWQ6IHN0cmluZywgbXQ6IE1hdHRlcnRhZ0RhdGEpID0+IFByb21pc2U8dm9pZD4sXHJcbiAgICBpbmplY3RIdG1sSW5UYWc6ICh0eXBlOiBQb2lUeXBlLCBvYmo6IERiT2JqZWN0VHlwZSwgc2lkOiBzdHJpbmcpID0+IFByb21pc2U8dm9pZD5cclxuICApOiBQcm9taXNlPHN0cmluZz4ge1xyXG4gICAgY29uc3QgZGVzY3JpcHRvciA9IG1hdHRlcnRhZ0RhdGEuZ2V0TWF0dGVydGFnRGVzY3JpcHRvcigpO1xyXG4gICAgLy9jb25zb2xlLmxvZygnZGVzY3JpcHRvcicsIGRlc2NyaXB0b3IpO1xyXG4gICAgY29uc3Qgc2lkID0gZGVzY3JpcHRvclswXVsnaWQnXTtcclxuXHJcbiAgICBpZiAoc2lkICYmIHRoaXMuZGljdGlvbm5hcnlUYWdzLmhhcyhzaWQpKSB7XHJcbiAgICAgIGF3YWl0IHNldFRhZ0ljb25BbmRPcGFjaXR5KHNpZCwgbWF0dGVydGFnRGF0YSk7XHJcbiAgICAgIGF3YWl0IGluamVjdEh0bWxJblRhZyhtYXR0ZXJ0YWdEYXRhLmdldFR5cGUoKSwgbWF0dGVydGFnRGF0YS5nZXRPYmplY3QoKSwgc2lkKTtcclxuICAgICAgcmV0dXJuIHNpZDtcclxuICAgIH1cclxuXHJcbiAgICB0aGlzLnRhZ0FkZFF1ZXVlID0gdGhpcy50YWdBZGRRdWV1ZS50aGVuKGFzeW5jICgpID0+IHtcclxuICAgICAgdHJ5IHtcclxuICAgICAgICBjb25zdCBbY3JlYXRlZFNpZF0gPSBhd2FpdCBzZGsuVGFnLmFkZCguLi5kZXNjcmlwdG9yKTtcclxuICAgICAgICB0aGlzLm1hdHRlcnRhZ0lEcy5wdXNoKGNyZWF0ZWRTaWQpO1xyXG4gICAgICAgIHRoaXMuZGljdGlvbm5hcnlUYWdzLnNldChjcmVhdGVkU2lkLCBtYXR0ZXJ0YWdEYXRhKTtcclxuXHJcbiAgICAgICAgYXdhaXQgd2FpdCgxMDApO1xyXG4gICAgICAgIGF3YWl0IHNldFRhZ0ljb25BbmRPcGFjaXR5KGNyZWF0ZWRTaWQsIG1hdHRlcnRhZ0RhdGEpO1xyXG5cclxuICAgICAgICBpbmplY3RIdG1sSW5UYWcobWF0dGVydGFnRGF0YS5nZXRUeXBlKCksIG1hdHRlcnRhZ0RhdGEuZ2V0T2JqZWN0KCksIGNyZWF0ZWRTaWQpLmNhdGNoKGVyciA9PiB7XHJcbiAgICAgICAgICBpZiAoaXNEZXZNb2RlKCkpIGNvbnNvbGUud2FybignSFRNTCBpbmplY3Rpb24gZmFpbGVkIGZvcicsIGNyZWF0ZWRTaWQsIGVycik7XHJcbiAgICAgICAgfSk7XHJcblxyXG4gICAgICAgIHJldHVybiBjcmVhdGVkU2lkO1xyXG4gICAgICB9IGNhdGNoIChlOiBhbnkpIHtcclxuICAgICAgICBpZiAoZT8ubWVzc2FnZT8uaW5jbHVkZXMoJ2FscmVhZHkgaW4gdXNlJykgJiYgc2lkKSB7XHJcbiAgICAgICAgICBpZiAoIXRoaXMuZGljdGlvbm5hcnlUYWdzLmhhcyhzaWQpKSB7XHJcbiAgICAgICAgICAgIHRoaXMubWF0dGVydGFnSURzLnB1c2goc2lkKTtcclxuICAgICAgICAgICAgdGhpcy5kaWN0aW9ubmFyeVRhZ3Muc2V0KHNpZCwgbWF0dGVydGFnRGF0YSk7XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgICBhd2FpdCBzZXRUYWdJY29uQW5kT3BhY2l0eShzaWQsIG1hdHRlcnRhZ0RhdGEpO1xyXG4gICAgICAgICAgYXdhaXQgaW5qZWN0SHRtbEluVGFnKG1hdHRlcnRhZ0RhdGEuZ2V0VHlwZSgpLCBtYXR0ZXJ0YWdEYXRhLmdldE9iamVjdCgpLCBzaWQpO1xyXG4gICAgICAgICAgcmV0dXJuIHNpZDtcclxuICAgICAgICB9XHJcbiAgICAgICAgdGhyb3cgZTtcclxuICAgICAgfVxyXG4gICAgfSk7XHJcblxyXG4gICAgcmV0dXJuIHRoaXMudGFnQWRkUXVldWU7XHJcbiAgfVxyXG5cclxuICBnZXREaXN0YW5jZShwMTogYW55LCBwMjogYW55KTogbnVtYmVyIHtcclxuICAgIHJldHVybiBNYXRoLnNxcnQoTWF0aC5wb3cocDIueCAtIHAxLngsIDIpICsgTWF0aC5wb3cocDIueSAtIHAxLnksIDIpICsgTWF0aC5wb3cocDIueiAtIHAxLnosIDIpKTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIENoZWNrcyBpZiBhIHRhZyBpcyB3aXRoaW4gdGhlIGJvdW5kaW5nIGJveCBvZiBhbnkgYWN0aXZlIHJvb20gKGFkZGluZyBhIHNsaWdodCBtYXJnaW4gdG8gYWNjb3VudCBmb3Igd2FsbC1tb3VudGVkIHRhZ3MpLlxyXG4gICAqIElmIHRoZXJlIGFyZSBubyBhY3RpdmUgcm9vbXMgKGUuZy4sIGhhbGx3YXkpLCBmYWxscyBiYWNrIHRvIHJldHVybmluZyB0cnVlLlxyXG4gICAqL1xyXG4gIGlzVGFnSW5Sb29tcyhtYXR0ZXJ0YWdEYXRhOiBNYXR0ZXJ0YWdEYXRhLCByb29tczogYW55W10pOiBib29sZWFuIHtcclxuICAgIGlmICghcm9vbXMgfHwgcm9vbXMubGVuZ3RoID09PSAwKSByZXR1cm4gZmFsc2U7XHJcblxyXG4gICAgY29uc3QgdGFnUG9zID0gbWF0dGVydGFnRGF0YS5nZXRQb3NpdGlvbigpO1xyXG4gICAgY29uc3QgbWFyZ2luID0gMS41O1xyXG5cclxuICAgIHJldHVybiByb29tcy5zb21lKChyb29tKSA9PiB7XHJcbiAgICAgIGlmICghcm9vbS5ib3VuZHMpIHJldHVybiBmYWxzZTtcclxuICAgICAgY29uc3QgeyBtaW4sIG1heCB9ID0gcm9vbS5ib3VuZHM7XHJcblxyXG4gICAgICByZXR1cm4gKFxyXG4gICAgICAgIHRhZ1Bvcy54ID49IG1pbi54IC0gbWFyZ2luICYmIHRhZ1Bvcy54IDw9IG1heC54ICsgbWFyZ2luICYmXHJcbiAgICAgICAgdGFnUG9zLnkgPj0gbWluLnkgLSBtYXJnaW4gJiYgdGFnUG9zLnkgPD0gbWF4LnkgKyBtYXJnaW4gJiZcclxuICAgICAgICB0YWdQb3MueiA+PSBtaW4ueiAtIG1hcmdpbiAmJiB0YWdQb3MueiA8PSBtYXgueiArIG1hcmdpblxyXG4gICAgICApO1xyXG4gICAgfSk7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBDb21wdXRlcyB0aGUgZmluYWwgY29udGV4dC1hd2FyZSBvcGFjaXR5IGZvciBhIHNpbmdsZSB0YWcuXHJcbiAgICogQHBhcmFtIGN1cnJlbnRGbG9vclNlcXVlbmNlICBBdXRob3JpdGF0aXZlIGN1cnJlbnQgZmxvb3Igc2VxdWVuY2UgZnJvbSBzZGsuRmxvb3IuY3VycmVudFxyXG4gICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKG51bGwgPSBzaW5nbGUtZmxvb3IgbW9kZWwgb3IgdW5rbm93bikuXHJcbiAgICogQHBhcmFtIGN1cnJlbnRSb29tcyAgICAgICAgICBBcnJheSBvZiBhY3RpdmUgcm9vbXMgdGhlIGNhbWVyYSBpcyBpbi5cclxuICAgKi9cclxuICAvKmNvbXB1dGVTaW5nbGVUYWdDb250ZXh0T3BhY2l0eShcclxuICAgIG1hdHRlcnRhZ0RhdGE6IE1hdHRlcnRhZ0RhdGEsXHJcbiAgICBwb3NlQ2FtZXJhOiBhbnksXHJcbiAgICBzd2VlcENvbGxlY3Rpb246IGFueSxcclxuICAgIGN1cnJlbnRGbG9vclNlcXVlbmNlOiBudW1iZXIgfCBudWxsLFxyXG4gICAgY3VycmVudFJvb21zOiBhbnlbXVxyXG4gICk6IG51bWJlciB7XHJcbiAgICBjb25zdCBtb2RlID0gdGhpcy5uYXZpZ2F0aW9uU2VydmljZS5jdXJyZW50Q2FtZXJhTW9kZTtcclxuXHJcbiAgICAvLyAxLiBDaGVjayBGbG9vclxyXG4gICAgY29uc3QgdGFnRmxvb3JJZCA9IHRoaXMuZ2V0Rmxvb3JJZEZvclRhZyhtYXR0ZXJ0YWdEYXRhLCBzd2VlcENvbGxlY3Rpb24pO1xyXG4gICAgY29uc3QgY3VycmVudEZsb29ySWQgPSBjdXJyZW50Rmxvb3JTZXF1ZW5jZT8udG9TdHJpbmcoKTtcclxuICAgIGlmICh0YWdGbG9vcklkICYmIGN1cnJlbnRGbG9vcklkICYmIHRhZ0Zsb29ySWQgIT09IGN1cnJlbnRGbG9vcklkKSB7XHJcbiAgICAgIHJldHVybiAwO1xyXG4gICAgfVxyXG5cclxuICAgIC8vIDIuIFNpIERvbGxob3VzZSAtPiBQbGVpbmUgb3BhY2l0w6lcclxuICAgIC8vaWYgKG1vZGUgIT09IENhbWVyYU1vZGUuSU5TSURFKSByZXR1cm4gMTtcclxuXHJcbiAgICAvLyAzLiBTaSBJbnNpZGUgLT4gQ2hlY2sgcGnDqGNlICsgRGlzdGFuY2UgcHJvZ3Jlc3NpdmVcclxuICAgIC8vaWYgKCF0aGlzLmlzVGFnSW5Sb29tcyhtYXR0ZXJ0YWdEYXRhLCBjdXJyZW50Um9vbXMpKSByZXR1cm4gMDtcclxuXHJcbiAgICByZXR1cm4gMTtcclxuICB9Ki9cclxuXHJcbiAgLyoqIFJldHVybnMgdGhlIElEIG9mIHRoZSBtb3N0IHJlY2VudGx5IGFkZGVkIHRhZy4gKi9cclxuICBnZXRMYXN0VGFnKCk6IHN0cmluZyB8IG51bGwge1xyXG4gICAgaWYgKHRoaXMubWF0dGVydGFnSURzLmxlbmd0aCA9PT0gMCkgcmV0dXJuIG51bGw7XHJcbiAgICByZXR1cm4gdGhpcy5tYXR0ZXJ0YWdJRHNbdGhpcy5tYXR0ZXJ0YWdJRHMubGVuZ3RoIC0gMV07XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBVcGRhdGVzIHRoZSB2aXNpYmlsaXR5IChvcGFjaXR5KSBvZiBhbGwgdGFncyBiYXNlZCBvbiB0aGUgY3VycmVudCBjYW1lcmEgbW9kZSxcclxuICAgKiBmbG9vciBhbmQgcm9vbSBjb250ZXh0LiBNdXN0IGJlIGNhbGxlZCBhZnRlciBlYWNoIHN3ZWVwLCBmbG9vciBvciBtb2RlIGNoYW5nZS5cclxuICAgKlxyXG4gICAqIFJ1bGVzOlxyXG4gICAqICAtIERPTExIT1VTRSAvIEZMT09SUExBTiDihpIgYWxsIHRhZ3MgaGlkZGVuIChvcGFjaXR5IDApLlxyXG4gICAqICAtIElOU0lERSDihpIgb25seSB0YWdzIHdob3NlIHN3ZWVwIGJlbG9uZ3MgdG8gdGhlIGN1cnJlbnQgZmxvb3IgYXJlIHNob3duO1xyXG4gICAqICAgIHByb3hpbWl0eS1iYXNlZCBvcGFjaXR5IGlzIGFwcGxpZWQgdmlhIGNvbXB1dGVUYWdPcGFjaXR5KCkuXHJcbiAgICogICAgVGFncyBvbiBvdGhlciBmbG9vcnMgYXJlIGhpZGRlbiAob3BhY2l0eSAwKS5cclxuICAgKiAgLSBUUkFOU0lUSU9OSU5HIOKGkiBubyBjaGFuZ2UgKHNraXAgdXBkYXRlIHRvIGF2b2lkIGZsaWNrZXJpbmcpLlxyXG4gICAqXHJcbiAgICogQHBhcmFtIHNkayAgICAgICAgICBNYXR0ZXJwb3J0IFNESyBpbnN0YW5jZS5cclxuICAgKiBAcGFyYW0gcG9zZUNhbWVyYSAgIEN1cnJlbnQgY2FtZXJhIHBvc2UuXHJcbiAgICogQHBhcmFtIHN3ZWVwQ29sbGVjdGlvbiAgRnVsbCBjb2xsZWN0aW9uIG9mIHN3ZWVwcy5cclxuICAgKiBAcGFyYW0gY3VycmVudENhbWVyYU1vZGUgIEN1cnJlbnQgY2FtZXJhIG1vZGUuXHJcbiAgICogQHBhcmFtIG1hdHRlcnRhZ1RvRm9sbG93ICBJRCBvZiB0aGUgY3Vyc29yIHRhZyAobmV2ZXIgdG91Y2hlZCkuXHJcbiAgICovXHJcbiAgYXN5bmMgdXBkYXRlVGFnc1Zpc2liaWxpdHlGb3JDb250ZXh0KFxyXG4gICAgc2RrOiBhbnksXHJcbiAgICBzd2VlcENvbGxlY3Rpb246IGFueSxcclxuICAgIGN1cnJlbnRDYW1lcmFNb2RlOiBDYW1lcmFNb2RlLFxyXG4gICAgbWF0dGVydGFnVG9Gb2xsb3c6IHN0cmluZyB8IG51bGwsXHJcbiAgICBjdXJyZW50Rmxvb3JTZXF1ZW5jZTogbnVtYmVyIHwgbnVsbCA9IG51bGwsXHJcbiAgICBjdXJyZW50Um9vbXM6IGFueVtdID0gW11cclxuICApOiBQcm9taXNlPHZvaWQ+IHtcclxuICAgIGlmICghc2RrIHx8IHRoaXMuZGljdGlvbm5hcnlUYWdzLnNpemUgPT09IDApIHJldHVybjtcclxuXHJcbiAgICBjb25zdCBpc0ludGVyaW9yTW9kZSA9IGN1cnJlbnRDYW1lcmFNb2RlID09PSBDYW1lcmFNb2RlLklOU0lERTtcclxuICAgIGNvbnN0IGN1cnJlbnRGbG9vcklkID0gY3VycmVudEZsb29yU2VxdWVuY2UgIT09IG51bGwgPyBjdXJyZW50Rmxvb3JTZXF1ZW5jZS50b1N0cmluZygpIDogbnVsbDtcclxuICAgIGNvbnN0IHByb21pc2VzID0gW107XHJcblxyXG4gICAgZm9yIChjb25zdCBbdGFnSWQsIG1hdHRlcnRhZ0RhdGFdIG9mIHRoaXMuZGljdGlvbm5hcnlUYWdzKSB7XHJcbiAgICAgIGlmICh0YWdJZCA9PT0gbWF0dGVydGFnVG9Gb2xsb3cpIGNvbnRpbnVlO1xyXG5cclxuICAgICAgY29uc3QgdGFnRmxvb3JJZCA9IHRoaXMuZ2V0Rmxvb3JJZEZvclRhZyhtYXR0ZXJ0YWdEYXRhLCBzd2VlcENvbGxlY3Rpb24pO1xyXG4gICAgICBjb25zdCBpc09uQ3VycmVudEZsb29yID0gIXRhZ0Zsb29ySWQgfHwgIWN1cnJlbnRGbG9vcklkIHx8IHRhZ0Zsb29ySWQgPT09IGN1cnJlbnRGbG9vcklkO1xyXG5cclxuICAgICAgbGV0IHRhcmdldE9wYWNpdHkgPSAwO1xyXG4gICAgICBsZXQgc2hvdWxkQmVFbmFibGVkID0gZmFsc2U7XHJcblxyXG4gICAgICAvLyBDYWxjdWxhdGlvbiBvZiBvcGFjaXR5IGFuZCBlbmFibGUgc3RhdHVzXHJcbiAgICAgIGlmIChpc09uQ3VycmVudEZsb29yKSB7XHJcbiAgICAgICAgaWYgKCFpc0ludGVyaW9yTW9kZSkge1xyXG4gICAgICAgICAgdGFyZ2V0T3BhY2l0eSA9IDE7XHJcbiAgICAgICAgICBzaG91bGRCZUVuYWJsZWQgPSB0cnVlO1xyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICB0YXJnZXRPcGFjaXR5ID0gMC45O1xyXG4gICAgICAgICAgc2hvdWxkQmVFbmFibGVkID0gdHJ1ZTtcclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuICAgICAgLy8gQXBwbHkgY2hhbmdlc1xyXG5cclxuICAgICAgLy8gVG9vbHRpcCBhbmQgY2xpY2sgbWFuYWdlbWVudFxyXG4gICAgICBjb25zdCBsYXN0RW5hYmxlZCA9IHRoaXMudGFnc0N1cnJlbnRFbmFibGVkLmdldCh0YWdJZCk7XHJcbiAgICAgIGlmIChsYXN0RW5hYmxlZCAhPT0gc2hvdWxkQmVFbmFibGVkKSB7XHJcbiAgICAgICAgdGhpcy50YWdzQ3VycmVudEVuYWJsZWQuc2V0KHRhZ0lkLCBzaG91bGRCZUVuYWJsZWQpO1xyXG4gICAgICAgIHByb21pc2VzLnB1c2goc2RrLlRhZy5hbGxvd0FjdGlvbih0YWdJZCwge1xyXG4gICAgICAgICAgb3BlbmluZzogc2hvdWxkQmVFbmFibGVkLFxyXG4gICAgICAgICAgbmF2aWdhdGluZzogc2hvdWxkQmVFbmFibGVkLFxyXG4gICAgICAgICAgZG9ja2luZzogZmFsc2VcclxuICAgICAgICB9KS5jYXRjaCgoKSA9PiB7IH0pKTtcclxuICAgICAgfVxyXG4gICAgICAvLyBPcGFjaXR5IG1hbmFnZW1lbnRcclxuICAgICAgY29uc3QgbGFzdE9wYWNpdHkgPSB0aGlzLnRhZ3NDdXJyZW50T3BhY2l0eS5nZXQodGFnSWQpID8/IC0xO1xyXG4gICAgICBpZiAoTWF0aC5hYnMobGFzdE9wYWNpdHkgLSB0YXJnZXRPcGFjaXR5KSA+IDAuMDUpIHtcclxuICAgICAgICB0aGlzLnRhZ3NDdXJyZW50T3BhY2l0eS5zZXQodGFnSWQsIHRhcmdldE9wYWNpdHkpO1xyXG4gICAgICAgIHByb21pc2VzLnB1c2goc2RrLlRhZy5lZGl0T3BhY2l0eSh0YWdJZCwgdGFyZ2V0T3BhY2l0eSkuY2F0Y2goKCkgPT4geyB9KSk7XHJcbiAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICBhd2FpdCBQcm9taXNlLmFsbChwcm9taXNlcyk7XHJcbiAgfVxyXG5cclxuICAvKiogUmVtb3ZlcyBhIHNwZWNpZmljIHRhZyBmcm9tIHRoZSB2aWV3ZXIgYW5kIGxvY2FsIGRpY3Rpb25hcmllcy4gKi9cclxuICBhc3luYyBkZWxldGVNYXR0ZXJ0YWdGcm9tSWQoc2RrOiBhbnksIG1hdHRlcnRhZ0lEOiBzdHJpbmcpOiBQcm9taXNlPHZvaWQ+IHtcclxuICAgIHRyeSB7XHJcbiAgICAgIGlmIChzZGspIGF3YWl0IHNkay5UYWcucmVtb3ZlKG1hdHRlcnRhZ0lEKTtcclxuICAgICAgdGhpcy5kaWN0aW9ubmFyeVRhZ3MuZGVsZXRlKG1hdHRlcnRhZ0lEKTtcclxuICAgICAgY29uc3QgaW5kZXggPSB0aGlzLm1hdHRlcnRhZ0lEcy5pbmRleE9mKG1hdHRlcnRhZ0lEKTtcclxuICAgICAgaWYgKGluZGV4ID4gLTEpIHRoaXMubWF0dGVydGFnSURzLnNwbGljZShpbmRleCwgMSk7XHJcbiAgICB9IGNhdGNoIChlOiBhbnkpIHtcclxuICAgICAgaWYgKGlzRGV2TW9kZSgpKSBjb25zb2xlLndhcm4oJ0Nhbm5vdCBkZWxldGUgdGFnJywgbWF0dGVydGFnSUQsIGUpO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLyoqIFJlbW92ZXMgdGhlIGxhc3QgYWRkZWQgdGFnIGZyb20gdGhlIHZpZXdlci4gKi9cclxuICBhc3luYyBkZWxldGVMYXN0TWF0dGVydGFnKHNkazogYW55KTogUHJvbWlzZTx2b2lkPiB7XHJcbiAgICBjb25zdCBsYXN0U2lkID0gdGhpcy5nZXRMYXN0VGFnKCk7XHJcbiAgICBpZiAobGFzdFNpZCkgYXdhaXQgdGhpcy5kZWxldGVNYXR0ZXJ0YWdGcm9tSWQoc2RrLCBsYXN0U2lkKTtcclxuICB9XHJcblxyXG4gIC8qKiBDbGVhcnMgYWxsIHRhZ3MgZnJvbSB0aGUgdmlld2VyIGFuZCByZXNldHMgbG9jYWwgc3RhdGUuICovXHJcbiAgYXN5bmMgYWN0aW9uX2RlbGV0ZV9hbGxfbWF0dGVydGFncyhzZGs6IGFueSk6IFByb21pc2U8dm9pZD4ge1xyXG4gICAgaWYgKHNkaykge1xyXG4gICAgICBjb25zdCBzaWRzVG9SZW1vdmUgPSBbLi4udGhpcy5tYXR0ZXJ0YWdJRHNdO1xyXG4gICAgICBmb3IgKGNvbnN0IHNpZCBvZiBzaWRzVG9SZW1vdmUpIHtcclxuICAgICAgICB0cnkge1xyXG4gICAgICAgICAgYXdhaXQgc2RrLlRhZy5yZW1vdmUoc2lkKTtcclxuICAgICAgICB9IGNhdGNoIChlKSB7IH1cclxuICAgICAgfVxyXG4gICAgfVxyXG4gICAgdGhpcy5jbGVhcigpO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogQ3JlYXRlcyBhbmQgY29uZmlndXJlcyBhIE1hdHRlcnRhZyBmcm9tIGEgUE9JLCBoYW5kbGluZyBjb29yZGluYXRlcywgbm9ybWFscywgYW5kIHN3ZWVwIElELlxyXG4gICAqIFNraXBzIGNyZWF0aW9uIGlmIGEgdGFnIGZvciB0aGUgb2JqZWN0IGFscmVhZHkgZXhpc3RzLlxyXG4gICAqL1xyXG4gIGFzeW5jIGNyZWF0ZU1hdHRlcnRhZ0Zyb21QT0koXHJcbiAgICBzZGs6IGFueSxcclxuICAgIHRhZ1R5cGU6IFBvaVR5cGUsXHJcbiAgICBvYmplY3Q6IERiT2JqZWN0VHlwZSxcclxuICAgIHBvaTogUE9JLFxyXG4gICAgcG9zZUNhbWVyYTogYW55LFxyXG4gICAgZ2V0VGFnRnJvbUVsZW1lbnRJZDogKGlkOiBzdHJpbmcpID0+IHsgdGFnOiBzdHJpbmc7IHN3ZWVwOiBzdHJpbmcgfSxcclxuICAgIHNldFRhZ0ljb25BbmRPcGFjaXR5OiAoc2lkOiBzdHJpbmcsIG10OiBNYXR0ZXJ0YWdEYXRhKSA9PiBQcm9taXNlPHZvaWQ+LFxyXG4gICAgaW5qZWN0SHRtbEluVGFnOiAodHlwZTogUG9pVHlwZSwgb2JqOiBEYk9iamVjdFR5cGUsIHNpZDogc3RyaW5nKSA9PiBQcm9taXNlPHZvaWQ+XHJcbiAgKTogUHJvbWlzZTxhbnk+IHtcclxuICAgIGNvbnN0IHsgdGFnIH0gPSBnZXRUYWdGcm9tRWxlbWVudElkKG9iamVjdC5pZCk7XHJcbiAgICBpZiAodGFnKSByZXR1cm47XHJcblxyXG4gICAgY29uc3QgbWF0dGVydGFnRGF0YTogTWF0dGVydGFnRGF0YSA9IG5ldyBNYXR0ZXJ0YWdEYXRhKHRhZ1R5cGUpO1xyXG4gICAgbWF0dGVydGFnRGF0YS5zZXRPYmplY3Qob2JqZWN0LCB0YWdUeXBlKTtcclxuXHJcbiAgICBpZiAocG9pLmNvb3JkaW5hdGUpIHtcclxuICAgICAgdHJ5IHtcclxuICAgICAgICBtYXR0ZXJ0YWdEYXRhLnNldFBvc2l0aW9uKEpTT04ucGFyc2UocG9pLmNvb3JkaW5hdGUpKTtcclxuICAgICAgfSBjYXRjaCAoZSkge1xyXG4gICAgICAgIGlmIChpc0Rldk1vZGUoKSkgY29uc29sZS53YXJuKCdFcnJvciBwYXJzaW5nIFBPSSBjb29yZGluYXRlcycsIHBvaS5jb29yZGluYXRlKTtcclxuICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIGlmIChwb2kubWV0YWRhdGEpIHtcclxuICAgICAgdHJ5IHtcclxuICAgICAgICBjb25zdCB0YWdNZXRhZGF0YSA9IEpTT04ucGFyc2UocG9pLm1ldGFkYXRhKTtcclxuICAgICAgICBtYXR0ZXJ0YWdEYXRhLnNldE5vcm1hbCh0YWdNZXRhZGF0YS5ub3JtYWwgfHwgeyB4OiAwLCB5OiAtMC4xNSwgejogMCB9KTtcclxuICAgICAgfSBjYXRjaCAoZSkge1xyXG4gICAgICAgIG1hdHRlcnRhZ0RhdGEuc2V0Tm9ybWFsKHsgeDogMCwgeTogLTAuMTUsIHo6IDAgfSk7XHJcbiAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICBpZiAocG9pLm1hdHRlcnBvcnRTd2VlcElEKSB7XHJcbiAgICAgIG1hdHRlcnRhZ0RhdGEuc2V0U3dlZXBJRChwb2kubWF0dGVycG9ydFN3ZWVwSUQpO1xyXG4gICAgfVxyXG4gICAgbWF0dGVydGFnRGF0YS5zZXRQb2kocG9pKTtcclxuXHJcbiAgICBjb25zdCBjcmVhdGVkVGFnSUQgPSBhd2FpdCB0aGlzLmFkZE1hdHRlcnRhZ1RvVmlld2VyKHNkaywgbWF0dGVydGFnRGF0YSk7XHJcblxyXG4gICAgaWYgKGNyZWF0ZWRUYWdJRCAmJiBzZGspIHtcclxuICAgICAgYXdhaXQgd2FpdCgxMDApO1xyXG4gICAgICBhd2FpdCBzZXRUYWdJY29uQW5kT3BhY2l0eShjcmVhdGVkVGFnSUQsIG1hdHRlcnRhZ0RhdGEpO1xyXG4gICAgICBpbmplY3RIdG1sSW5UYWcodGFnVHlwZSwgb2JqZWN0LCBjcmVhdGVkVGFnSUQpLmNhdGNoKGVyciA9PiB7XHJcbiAgICAgICAgaWYgKGlzRGV2TW9kZSgpKSBjb25zb2xlLndhcm4oJ0hUTUwgaW5qZWN0aW9uIGZhaWxlZCBmb3InLCBjcmVhdGVkVGFnSUQsIGVycik7XHJcbiAgICAgIH0pO1xyXG4gICAgfVxyXG5cclxuICAgIHJldHVybiBjcmVhdGVkVGFnSUQ7XHJcbiAgfVxyXG5cclxuICAvKiogVXBkYXRlcyB0aGUgaWNvbiwgb3BhY2l0eSwgYW5kIEhUTUwgY29udGVudCBvZiBhbiBleGlzdGluZyB0YWcuICovXHJcbiAgYXN5bmMgdXBkYXRlTWF0dGVyVGFnQ29udGVudEZvclRhZ0lEKFxyXG4gICAgc2RrOiBhbnksXHJcbiAgICBtYXR0ZXJ0YWdJRDogc3RyaW5nLFxyXG4gICAgb2JqZWN0OiBEYk9iamVjdFR5cGUsXHJcbiAgICBwb2lUeXBlOiBQb2lUeXBlLFxyXG4gICAgc2V0VGFnSWNvbkFuZE9wYWNpdHk6IChzaWQ6IHN0cmluZywgbXQ6IE1hdHRlcnRhZ0RhdGEpID0+IFByb21pc2U8dm9pZD4sXHJcbiAgICBpbmplY3RIdG1sSW5UYWc6ICh0eXBlOiBQb2lUeXBlLCBvYmo6IERiT2JqZWN0VHlwZSwgc2lkOiBzdHJpbmcpID0+IFByb21pc2U8dm9pZD5cclxuICApOiBQcm9taXNlPGFueT4ge1xyXG4gICAgY29uc3QgbWF0dGVydGFnRGF0YSA9IHRoaXMuZGljdGlvbm5hcnlUYWdzLmdldChtYXR0ZXJ0YWdJRCk7XHJcbiAgICBpZiAoIW1hdHRlcnRhZ0RhdGEpIHJldHVybjtcclxuXHJcbiAgICBpZiAob2JqZWN0KSB7XHJcbiAgICAgIG1hdHRlcnRhZ0RhdGEuc2V0T2JqZWN0KG9iamVjdCwgcG9pVHlwZSk7XHJcbiAgICB9XHJcblxyXG4gICAgYXdhaXQgc2V0VGFnSWNvbkFuZE9wYWNpdHkobWF0dGVydGFnSUQsIG1hdHRlcnRhZ0RhdGEpO1xyXG4gICAgYXdhaXQgaW5qZWN0SHRtbEluVGFnKHBvaVR5cGUsIG9iamVjdCwgbWF0dGVydGFnSUQpO1xyXG4gIH1cclxuXHJcbiAgLyoqIFJlZ2lzdGVycyBhIGN1c3RvbSB0ZXh0dXJlIGFuZCBhcHBsaWVzIGl0IHRvIGEgdGFnLCBvcHRpb25hbGx5IGFkanVzdGluZyBvcGFjaXR5LiAqL1xyXG4gIGFzeW5jIGFkZE5ld0ljb25BbmRTZXRGb3JUYWcoXHJcbiAgICBzZGs6IGFueSxcclxuICAgIG1hdHRlcnRhZ0lEOiBzdHJpbmcsXHJcbiAgICBpY29uUGF0aDogc3RyaW5nLFxyXG4gICAgYXBwbHlPcGFjaXR5OiBib29sZWFuLFxyXG4gICAgb3BhY2l0eTogbnVtYmVyXHJcbiAgKSB7XHJcbiAgICBpZiAoIXNkaykgcmV0dXJuO1xyXG4gICAgdHJ5IHtcclxuICAgICAgY29uc3QgaWNvbk5hbWUgPSBgY3VzdG9tLWljb24tJHttYXR0ZXJ0YWdJRH1gO1xyXG4gICAgICBhd2FpdCBzZGsuQXNzZXQucmVnaXN0ZXJUZXh0dXJlKGljb25OYW1lLCBpY29uUGF0aCk7XHJcbiAgICAgIGF3YWl0IHNkay5UYWcuZWRpdEljb24obWF0dGVydGFnSUQsIGljb25OYW1lKTtcclxuXHJcbiAgICAgIGlmIChhcHBseU9wYWNpdHkpIHtcclxuICAgICAgICBhd2FpdCBzZGsuVGFnLmVkaXRPcGFjaXR5KG1hdHRlcnRhZ0lELCBvcGFjaXR5KTtcclxuICAgICAgfVxyXG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcclxuICAgICAgaWYgKGlzRGV2TW9kZSgpKSBjb25zb2xlLndhcm4oJ0Vycm9yIHNldHRpbmcgY3VzdG9tIGljb24gb3Igb3BhY2l0eScsIGVycm9yKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIC8qKiBGaW5kcyB0aGUgdGFnIElEIGFuZCBzd2VlcCBJRCBhc3NvY2lhdGVkIHdpdGggYSBzcGVjaWZpYyBlbGVtZW50IElELiAqL1xyXG4gIGdldFRhZ0Zyb21FbGVtZW50SWQoZWxlbWVudElEOiBzdHJpbmcsIHN3ZWVwczogc3RyaW5nW10gfCBudWxsKTogeyB0YWc6IHN0cmluZyB8IG51bGw7IHN3ZWVwOiBzdHJpbmcgfCBudWxsIH0ge1xyXG4gICAgbGV0IHRhZ0lEID0gbnVsbDtcclxuICAgIGxldCBzd2VlcElEID0gbnVsbDtcclxuICAgIGZvciAobGV0IFttYXR0ZXJ0YWdJRCwgbWF0dGVydGFnRGF0YV0gb2YgdGhpcy5kaWN0aW9ubmFyeVRhZ3MpIHtcclxuICAgICAgaWYgKG1hdHRlcnRhZ0RhdGEuZWxlbWVudElEID09PSBlbGVtZW50SUQpIHtcclxuICAgICAgICB0YWdJRCA9IG1hdHRlcnRhZ0lEO1xyXG4gICAgICAgIGNvbnN0IHN3ZWVwID0gbWF0dGVydGFnRGF0YS5nZXRTd2VlcElEKCk7XHJcbiAgICAgICAgaWYgKHN3ZWVwICYmIHN3ZWVwcyAmJiBzd2VlcHMuaW5jbHVkZXMoc3dlZXApKSB7XHJcbiAgICAgICAgICBzd2VlcElEID0gc3dlZXA7XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgICByZXR1cm4geyB0YWc6IHRhZ0lELCBzd2VlcDogc3dlZXBJRCB9O1xyXG4gIH1cclxuXHJcbiAgLyoqIFJldHJpZXZlcyB0aGUgZmxvb3IgaWRlbnRpZmllciBhc3NvY2lhdGVkIHdpdGggYSB0YWcgYmFzZWQgb24gaXRzIHN3ZWVwIGRhdGEuXHJcbiAgICogIEhhbmRsZXMgYm90aCB0aGUgb2JqZWN0IGZvcm0gKHsgZmxvb3JJbmZvOiB7IGlkLCBzZXF1ZW5jZSB9LCBmbG9vcjogeyBpZCB9IH0pXHJcbiAgICogIGFuZCB0aGUgcHJpbWl0aXZlIGZvcm0gKGZsb29yOiBudW1iZXIpIHVzZWQgYnkgTWF0dGVycG9ydCBTREsgdjMuXHJcbiAgICovXHJcbiAgZ2V0Rmxvb3JJZEZvclRhZyhtYXR0ZXJ0YWdEYXRhOiBNYXR0ZXJ0YWdEYXRhLCBzd2VlcENvbGxlY3Rpb246IGFueSk6IHN0cmluZyB8IG51bGwge1xyXG4gICAgY29uc3Qgc3dlZXBJZCA9IG1hdHRlcnRhZ0RhdGEuZ2V0U3dlZXBJRCgpO1xyXG4gICAgaWYgKCFzd2VlcElkIHx8ICFzd2VlcENvbGxlY3Rpb24pIHJldHVybiBudWxsO1xyXG5cclxuICAgIGNvbnN0IHN3ZWVwRGF0YSA9IHN3ZWVwQ29sbGVjdGlvbltzd2VlcElkXTtcclxuICAgIGlmICghc3dlZXBEYXRhKSByZXR1cm4gbnVsbDtcclxuXHJcbiAgICAvLyBTREsgdjM6IHN3ZWVwLmZsb29yIGlzIGEgcHJpbWl0aXZlIG51bWJlciAodGhlIHNlcXVlbmNlIGluZGV4KVxyXG4gICAgaWYgKHR5cGVvZiBzd2VlcERhdGEuZmxvb3IgPT09ICdudW1iZXInKSB7XHJcbiAgICAgIHJldHVybiBzd2VlcERhdGEuZmxvb3IudG9TdHJpbmcoKTtcclxuICAgIH1cclxuXHJcbiAgICAvLyBPbGRlciAvIGV4dGVuZGVkIGZvcm1hdHNcclxuICAgIHJldHVybiBzd2VlcERhdGE/LmZsb29ySW5mbz8uaWRcclxuICAgICAgPz8gc3dlZXBEYXRhPy5mbG9vckluZm8/LnNlcXVlbmNlPy50b1N0cmluZygpXHJcbiAgICAgID8/IHN3ZWVwRGF0YT8uZmxvb3JJZFxyXG4gICAgICA/PyBzd2VlcERhdGE/LmZsb29yPy5pZFxyXG4gICAgICA/PyBzd2VlcERhdGE/LmZsb29yPy5zZXF1ZW5jZT8udG9TdHJpbmcoKVxyXG4gICAgICA/PyBudWxsO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogSW5qZWN0cyBjdXN0b20gSFRNTCBvciBmYWxsYmFjayBiaWxsYm9hcmQgbWVkaWEgaW50byBhIE1hdHRlcnRhZyBzYW5kYm94LlxyXG4gICAqIEF0dGFjaGVzIGV2ZW50IGxpc3RlbmVycyBmb3IgaW50ZXJhY3RpdmUgZWxlbWVudHMgd2l0aGluIHRoZSB0YWcuXHJcbiAgICovXHJcbiAgYXN5bmMgaW5qZWN0SHRtbEluVGFnKHNkazogYW55LCB0YWdUeXBlOiBQb2lUeXBlLCBvYmplY3Q6IERiT2JqZWN0VHlwZSwgdGFnSUQ6IHN0cmluZykge1xyXG4gICAgaWYgKCF0aGlzLnRhZ1NlcnZpY2UpIHtcclxuICAgICAgY29uc29sZS5lcnJvcignW01hdHRlcnBvcnRUYWdTZXJ2aWNlXSB0YWdTZXJ2aWNlIGlzIG5vdCBpbml0aWFsaXplZC4nKTtcclxuICAgICAgcmV0dXJuO1xyXG4gICAgfVxyXG4gICAgdHJ5IHtcclxuICAgICAgbGV0IGh0bWwgPSBhd2FpdCB0aGlzLnRhZ1NlcnZpY2UuZ2V0SHRtbFRvSW5qZWN0KHRhZ1R5cGUsIG9iamVjdCk7XHJcblxyXG4gICAgICBpZiAoaHRtbCAmJiBodG1sLnRyaW0oKS5sZW5ndGggPiAwICYmIHNkaykge1xyXG4gICAgICAgIGNvbnN0IHNjcmlwdFRhZyA9IHRoaXMudGFnU2VydmljZS5nZXRTY3JpcHRGb3JUYWcob2JqZWN0LCB0YWdUeXBlKTtcclxuICAgICAgICBodG1sICs9IGAke3NjcmlwdFRhZ31gO1xyXG5cclxuICAgICAgICBjb25zdCBbc2FuZGJveElkLCBtZXNzZW5nZXJdID0gYXdhaXQgc2RrLlRhZy5yZWdpc3RlclNhbmRib3goaHRtbCk7XHJcblxyXG4gICAgICAgIGNvbnN0IGF0dGFjaG1lbnRJRCA9IHRoaXMudGFnc0F0dGFjaG1lbnRzW3RhZ0lEXTtcclxuICAgICAgICBpZiAoYXR0YWNobWVudElEKSB7XHJcbiAgICAgICAgICB0cnkge1xyXG4gICAgICAgICAgICBhd2FpdCBzZGsuVGFnLmRldGFjaCh0YWdJRCwgYXR0YWNobWVudElEKTtcclxuICAgICAgICAgIH0gY2F0Y2ggKGUpIHsgfVxyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgdGhpcy50YWdzQXR0YWNobWVudHNbdGFnSURdID0gc2FuZGJveElkO1xyXG4gICAgICAgIGF3YWl0IHNkay5UYWcuYXR0YWNoKHRhZ0lELCBzYW5kYm94SWQpO1xyXG5cclxuICAgICAgICAvLyBBdHRhY2ggdGhlIFwiVmlldyBpbmZvcm1hdGlvbnNcIiBoYW5kbGVyIGluIHRvb2x0aXBcclxuICAgICAgICBtZXNzZW5nZXIub24oVGFnQWN0aW9uLkRFVEFJTF9DTElDSywgdGhpcy50YWdTZXJ2aWNlLm9uQWN0aW9uRGV0YWlsQ2xpY2suYmluZCh0aGlzLnRhZ1NlcnZpY2UpKTtcclxuICAgICAgICBtZXNzZW5nZXIub24oVGFnQWN0aW9uLlRJQ0tFVF9DTElDSywgdGhpcy50YWdTZXJ2aWNlLm9uQWN0aW9uRGV0YWlsQ2xpY2suYmluZCh0aGlzLnRhZ1NlcnZpY2UpKTtcclxuICAgICAgICBtZXNzZW5nZXIub24oVGFnQWN0aW9uLkFVRElPX0NMSUNLLCAoYXVkaW9Db21tZW50SUQ6IHN0cmluZykgPT4gdGhpcy50YWdTZXJ2aWNlLm9uQWN0aW9uQXVkaW9DbGljayhhdWRpb0NvbW1lbnRJRCkpO1xyXG4gICAgICAgIG1lc3Nlbmdlci5vbihUYWdBY3Rpb24uVklERU9fQ0xJQ0ssICh2aWRlb1VybDogc3RyaW5nKSA9PiB0aGlzLnRhZ1NlcnZpY2Uub25BY3Rpb25WaWRlb0NsaWNrKHZpZGVvVXJsKSk7XHJcbiAgICAgICAgbWVzc2VuZ2VyLm9uKFRhZ0FjdGlvbi5JTUFHRV9DTElDSywgKGltYWdlQ29tbWVudElEOiBzdHJpbmcpID0+IHRoaXMudGFnU2VydmljZS5vbkFjdGlvbkltYWdlQ2xpY2soaW1hZ2VDb21tZW50SUQpKTtcclxuICAgICAgICBtZXNzZW5nZXIub24oVGFnQWN0aW9uLkRPQ19DTElDSywgKGRvY1VybDogc3RyaW5nKSA9PiB0aGlzLnRhZ1NlcnZpY2Uub25BY3Rpb25Eb2NDbGljayhkb2NVcmwpKTtcclxuICAgICAgICBtZXNzZW5nZXIub24oVGFnQWN0aW9uLllPVVRVQkVfQ0xJQ0ssICh5b3V0dWJlVXJsOiBzdHJpbmcpID0+IHRoaXMudGFnU2VydmljZS5vbkFjdGlvbllvdXR1YmVDbGljayh5b3V0dWJlVXJsKSk7XHJcbiAgICAgIH0gZWxzZSBpZiAoc2RrKSB7XHJcbiAgICAgICAgY29uc3QgeyBjb21tZW50LCB0YWdEZXNjcmlwdGlvbiB9ID0gdGhpcy50YWdTZXJ2aWNlLmdldEJpbGxib2FyZE1lZGlhVG9FbWJlZChvYmplY3QpO1xyXG5cclxuICAgICAgICBpZiAoY29tbWVudCkge1xyXG4gICAgICAgICAgY29uc3QgYXR0YWNobWVudElEID0gYXdhaXQgc2RrLlRhZy5yZWdpc3RlckF0dGFjaG1lbnQoe1xyXG4gICAgICAgICAgICB0eXBlOiAnbWVkaWEnLFxyXG4gICAgICAgICAgICBkYXRhOiB7XHJcbiAgICAgICAgICAgICAgdXJsOiBjb21tZW50LmV4dGVybmFsTGluayxcclxuICAgICAgICAgICAgICBsYWJlbDogb2JqZWN0LnRpdGxlIHx8ICdNZWRpYScsXHJcbiAgICAgICAgICAgIH0sXHJcbiAgICAgICAgICB9KTtcclxuXHJcbiAgICAgICAgICBhd2FpdCBzZGsuVGFnLmF0dGFjaCh0YWdJRCwgYXR0YWNobWVudElEKTtcclxuXHJcbiAgICAgICAgICBjb25zdCBiaWxsYm9hcmRBdHRhY2htZW50SUQgPSBhd2FpdCBzZGsuVGFnLnJlZ2lzdGVyQXR0YWNobWVudCh7XHJcbiAgICAgICAgICAgIHR5cGU6ICdiaWxsYm9hcmQnLFxyXG4gICAgICAgICAgICBkYXRhOiB7XHJcbiAgICAgICAgICAgICAgdGl0bGU6IG9iamVjdC50aXRsZSxcclxuICAgICAgICAgICAgICBkZXNjcmlwdGlvbjogdGFnRGVzY3JpcHRpb24sXHJcbiAgICAgICAgICAgIH0sXHJcbiAgICAgICAgICB9KTtcclxuXHJcbiAgICAgICAgICBhd2FpdCBzZGsuVGFnLmF0dGFjaCh0YWdJRCwgYmlsbGJvYXJkQXR0YWNobWVudElEKTtcclxuICAgICAgICAgIHRoaXMudGFnc0F0dGFjaG1lbnRzW3RhZ0lEXSA9IGJpbGxib2FyZEF0dGFjaG1lbnRJRDtcclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuICAgIH0gY2F0Y2ggKGVycm9yKSB7XHJcbiAgICAgIGNvbnNvbGUuZXJyb3IoJ1tNYXR0ZXJwb3J0VGFnU2VydmljZV0gRXJyb3IgaW4gaW5qZWN0SHRtbEluVGFnOicsIGVycm9yKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIC8qKiBDbGVhcnMgYWxsIGxvY2FsIHRhZyBkYXRhIGFuZCByZXNldHMgdGhlIGFkZGl0aW9uIHF1ZXVlLiAqL1xyXG4gIGNsZWFyKCkge1xyXG4gICAgdGhpcy5kaWN0aW9ubmFyeVRhZ3MuY2xlYXIoKTtcclxuICAgIHRoaXMudGFnQWRkUXVldWUgPSBQcm9taXNlLnJlc29sdmUoKTtcclxuICAgIHRoaXMubWF0dGVydGFnVG9Gb2xsb3cgPSBudWxsO1xyXG4gICAgdGhpcy5tYXR0ZXJ0YWdJRHMgPSBbXTtcclxuICB9XHJcbn1cclxuIl19