@muraai/mnl-chat 0.0.1-alpha-82b7eb9 → 0.0.1-alpha-51e7ded

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 (56) hide show
  1. package/{esm2020 → esm2022}/lib/chat.module.mjs +19 -19
  2. package/esm2022/lib/components/ng-chat/ng-chat.component.mjs +588 -0
  3. package/esm2022/lib/components/ng-chat-friends-list/ng-chat-friends-list.component.mjs +128 -0
  4. package/esm2022/lib/components/ng-chat-options/ng-chat-options.component.mjs +29 -0
  5. package/esm2022/lib/components/ng-chat-window/ng-chat-window.component.mjs +247 -0
  6. package/esm2022/lib/core/message-counter.mjs +25 -0
  7. package/{esm2020 → esm2022}/lib/firstLetter.pipe.mjs +5 -5
  8. package/esm2022/lib/material.module.mjs +60 -0
  9. package/{esm2020 → esm2022}/lib/pipes/emojify.pipe.mjs +4 -4
  10. package/esm2022/lib/pipes/group-message-display-name.pipe.mjs +24 -0
  11. package/esm2022/lib/pipes/linkfy.pipe.mjs +34 -0
  12. package/{esm2020 → esm2022}/lib/pipes/sanitize.pipe.mjs +5 -5
  13. package/{esm2020 → esm2022}/lib/services/chat.service.mjs +5 -5
  14. package/{fesm2020 → fesm2022}/muraai-mnl-chat.mjs +85 -85
  15. package/fesm2022/muraai-mnl-chat.mjs.map +1 -0
  16. package/lib/components/ng-chat/ng-chat.component.d.ts +1 -1
  17. package/lib/components/ng-chat-friends-list/ng-chat-friends-list.component.d.ts +1 -1
  18. package/lib/components/ng-chat-options/ng-chat-options.component.d.ts +1 -1
  19. package/lib/components/ng-chat-window/ng-chat-window.component.d.ts +1 -1
  20. package/lib/material.module.d.ts +2 -2
  21. package/package.json +7 -13
  22. package/esm2020/lib/components/ng-chat/ng-chat.component.mjs +0 -588
  23. package/esm2020/lib/components/ng-chat-friends-list/ng-chat-friends-list.component.mjs +0 -128
  24. package/esm2020/lib/components/ng-chat-options/ng-chat-options.component.mjs +0 -29
  25. package/esm2020/lib/components/ng-chat-window/ng-chat-window.component.mjs +0 -247
  26. package/esm2020/lib/core/message-counter.mjs +0 -25
  27. package/esm2020/lib/material.module.mjs +0 -60
  28. package/esm2020/lib/pipes/group-message-display-name.pipe.mjs +0 -24
  29. package/esm2020/lib/pipes/linkfy.pipe.mjs +0 -34
  30. package/fesm2015/muraai-mnl-chat.mjs +0 -1436
  31. package/fesm2015/muraai-mnl-chat.mjs.map +0 -1
  32. package/fesm2020/muraai-mnl-chat.mjs.map +0 -1
  33. /package/{esm2020 → esm2022}/lib/core/chat-adapter.mjs +0 -0
  34. /package/{esm2020 → esm2022}/lib/core/chat-controller.mjs +0 -0
  35. /package/{esm2020 → esm2022}/lib/core/chat-group-adapter.mjs +0 -0
  36. /package/{esm2020 → esm2022}/lib/core/chat-option.mjs +0 -0
  37. /package/{esm2020 → esm2022}/lib/core/chat-participant-status-descriptor.mjs +0 -0
  38. /package/{esm2020 → esm2022}/lib/core/chat-participant-status.enum.mjs +0 -0
  39. /package/{esm2020 → esm2022}/lib/core/chat-participant-type.enum.mjs +0 -0
  40. /package/{esm2020 → esm2022}/lib/core/chat-participant.mjs +0 -0
  41. /package/{esm2020 → esm2022}/lib/core/default-file-upload-adapter.mjs +0 -0
  42. /package/{esm2020 → esm2022}/lib/core/file-upload-adapter.mjs +0 -0
  43. /package/{esm2020 → esm2022}/lib/core/group.mjs +0 -0
  44. /package/{esm2020 → esm2022}/lib/core/guid.mjs +0 -0
  45. /package/{esm2020 → esm2022}/lib/core/localization.mjs +0 -0
  46. /package/{esm2020 → esm2022}/lib/core/message-type.enum.mjs +0 -0
  47. /package/{esm2020 → esm2022}/lib/core/message.mjs +0 -0
  48. /package/{esm2020 → esm2022}/lib/core/paged-history-chat-adapter.mjs +0 -0
  49. /package/{esm2020 → esm2022}/lib/core/participant-metadata.mjs +0 -0
  50. /package/{esm2020 → esm2022}/lib/core/participant-response.mjs +0 -0
  51. /package/{esm2020 → esm2022}/lib/core/scroll-direction.enum.mjs +0 -0
  52. /package/{esm2020 → esm2022}/lib/core/theme.enum.mjs +0 -0
  53. /package/{esm2020 → esm2022}/lib/core/user.mjs +0 -0
  54. /package/{esm2020 → esm2022}/lib/core/window.mjs +0 -0
  55. /package/{esm2020 → esm2022}/muraai-mnl-chat.mjs +0 -0
  56. /package/{esm2020 → esm2022}/public-api.mjs +0 -0
@@ -0,0 +1,588 @@
1
+ /* eslint-disable */
2
+ import { Component, Input, ViewChildren, HostListener, Output, EventEmitter, ViewEncapsulation } from '@angular/core';
3
+ import { MessageType } from "../../core/message-type.enum";
4
+ import { Window } from "../../core/window";
5
+ import { ChatParticipantStatus } from "../../core/chat-participant-status.enum";
6
+ import { ScrollDirection } from "../../core/scroll-direction.enum";
7
+ import { PagedHistoryChatAdapter } from '../../core/paged-history-chat-adapter';
8
+ import { DefaultFileUploadAdapter } from '../../core/default-file-upload-adapter';
9
+ import { Theme } from '../../core/theme.enum';
10
+ import { Group } from "../../core/group";
11
+ import { ChatParticipantType } from "../../core/chat-participant-type.enum";
12
+ import { map } from 'rxjs/operators';
13
+ import * as i0 from "@angular/core";
14
+ import * as i1 from "@angular/common/http";
15
+ import * as i2 from "@angular/common";
16
+ import * as i3 from "../ng-chat-friends-list/ng-chat-friends-list.component";
17
+ import * as i4 from "../ng-chat-window/ng-chat-window.component";
18
+ import * as i5 from "../../pipes/sanitize.pipe";
19
+ export class NgChat {
20
+ constructor(_httpClient) {
21
+ this._httpClient = _httpClient;
22
+ // Exposes enums for the ng-template
23
+ this.ChatParticipantType = ChatParticipantType;
24
+ this.ChatParticipantStatus = ChatParticipantStatus;
25
+ this.MessageType = MessageType;
26
+ this._isDisabled = false;
27
+ this.isCollapsed = false;
28
+ this.maximizeWindowOnNewMessage = true;
29
+ this.pollFriendsList = false;
30
+ this.pollingInterval = 5000;
31
+ this.historyEnabled = true;
32
+ this.emojisEnabled = true;
33
+ this.linkfyEnabled = true;
34
+ this.audioEnabled = true;
35
+ this.searchEnabled = true;
36
+ this.audioSource = '../../../assets/notification.wav';
37
+ this.persistWindowsState = true;
38
+ this.title = "Quick chat";
39
+ this.messagePlaceholder = "Type a message";
40
+ this.searchPlaceholder = "Search";
41
+ this.browserNotificationsEnabled = true;
42
+ this.browserNotificationIconSource = '../../../assets/notification.png';
43
+ this.browserNotificationTitle = "New message from";
44
+ this.historyPageSize = 10;
45
+ this.hideFriendsList = false;
46
+ this.hideFriendsListOnUnsupportedViewport = true;
47
+ this.theme = Theme.Light;
48
+ this.messageDatePipeFormat = "short";
49
+ this.showMessageDate = true;
50
+ this.isViewportOnMobileEnabled = false;
51
+ this.onParticipantClicked = new EventEmitter();
52
+ this.onParticipantChatOpened = new EventEmitter();
53
+ this.onParticipantChatClosed = new EventEmitter();
54
+ this.onMessagesSeen = new EventEmitter();
55
+ this.onCloseWindowClicked = new EventEmitter();
56
+ this.browserNotificationsBootstrapped = false;
57
+ this.hasPagedHistory = false;
58
+ // Don't want to add this as a setting to simplify usage. Previous placeholder and title settings available to be used, or use full Localization object.
59
+ this.statusDescription = {
60
+ online: 'Online',
61
+ busy: 'Busy',
62
+ away: 'Away',
63
+ offline: 'Offline'
64
+ };
65
+ this.participantsInteractedWith = [];
66
+ // Defines the size of each opened window to calculate how many windows can be opened on the viewport at the same time.
67
+ this.windowSizeFactor = 320;
68
+ // Total width size of the friends list section
69
+ this.friendsListWidth = 262;
70
+ // Set to true if there is no space to display at least one chat window and 'hideFriendsListOnUnsupportedViewport' is true
71
+ this.unsupportedViewport = false;
72
+ this.windows = [];
73
+ this.isBootstrapped = false;
74
+ }
75
+ get isDisabled() {
76
+ return this._isDisabled;
77
+ }
78
+ set isDisabled(value) {
79
+ this._isDisabled = value;
80
+ if (value) {
81
+ window.clearInterval(this.pollingIntervalWindowInstance);
82
+ }
83
+ else {
84
+ this.activateFriendListFetch();
85
+ }
86
+ }
87
+ get localStorageKey() {
88
+ return `ng-chat-users-${this.userId}`; // Appending the user id so the state is unique per user in a computer.
89
+ }
90
+ ;
91
+ ngOnInit() {
92
+ this.bootstrapChat();
93
+ }
94
+ onResize(event) {
95
+ this.viewPortTotalArea = event.target.innerWidth;
96
+ this.NormalizeWindows();
97
+ }
98
+ // Checks if there are more opened windows than the view port can display
99
+ NormalizeWindows() {
100
+ const maxSupportedOpenedWindows = Math.floor((this.viewPortTotalArea - (!this.hideFriendsList ? this.friendsListWidth : 0)) / this.windowSizeFactor);
101
+ const difference = this.windows.length - maxSupportedOpenedWindows;
102
+ if (difference >= 0) {
103
+ this.windows.splice(this.windows.length - difference);
104
+ }
105
+ this.updateWindowsState(this.windows);
106
+ // Viewport should have space for at least one chat window but should show in mobile if option is enabled.
107
+ this.unsupportedViewport = this.isViewportOnMobileEnabled ? false : this.hideFriendsListOnUnsupportedViewport && maxSupportedOpenedWindows < 1;
108
+ }
109
+ // Initializes the chat plugin and the messaging adapter
110
+ bootstrapChat() {
111
+ let initializationException = null;
112
+ if (this.adapter != null && this.userId != null) {
113
+ try {
114
+ this.viewPortTotalArea = window.innerWidth;
115
+ this.initializeTheme();
116
+ this.initializeDefaultText();
117
+ this.initializeBrowserNotifications();
118
+ // Binding event listeners
119
+ this.adapter.messageReceivedHandler = (participant, msg) => this.onMessageReceived(participant, msg);
120
+ this.adapter.friendsListChangedHandler = (participantsResponse) => this.onFriendsListChanged(participantsResponse);
121
+ this.activateFriendListFetch();
122
+ this.bufferAudioFile();
123
+ this.hasPagedHistory = this.adapter instanceof PagedHistoryChatAdapter;
124
+ if (this.fileUploadUrl && this.fileUploadUrl !== "") {
125
+ this.fileUploadAdapter = new DefaultFileUploadAdapter(this.fileUploadUrl, this._httpClient);
126
+ }
127
+ this.NormalizeWindows();
128
+ this.isBootstrapped = true;
129
+ }
130
+ catch (ex) {
131
+ initializationException = ex;
132
+ }
133
+ }
134
+ if (!this.isBootstrapped) {
135
+ console.error("ng-chat component couldn't be bootstrapped.");
136
+ if (this.userId == null) {
137
+ console.error("ng-chat can't be initialized without an user id. Please make sure you've provided an userId as a parameter of the ng-chat component.");
138
+ }
139
+ if (this.adapter == null) {
140
+ console.error("ng-chat can't be bootstrapped without a ChatAdapter. Please make sure you've provided a ChatAdapter implementation as a parameter of the ng-chat component.");
141
+ }
142
+ if (initializationException) {
143
+ console.error(`An exception has occurred while initializing ng-chat. Details: ${initializationException.message}`);
144
+ console.error(initializationException);
145
+ }
146
+ }
147
+ }
148
+ activateFriendListFetch() {
149
+ if (this.adapter) {
150
+ // Loading current users list
151
+ if (this.pollFriendsList) {
152
+ // Setting a long poll interval to update the friends list
153
+ this.fetchFriendsList(true);
154
+ this.pollingIntervalWindowInstance = window.setInterval(() => this.fetchFriendsList(false), this.pollingInterval);
155
+ }
156
+ else {
157
+ // Since polling was disabled, a friends list update mechanism will have to be implemented in the ChatAdapter.
158
+ this.fetchFriendsList(true);
159
+ }
160
+ }
161
+ }
162
+ // Initializes browser notifications
163
+ async initializeBrowserNotifications() {
164
+ if (this.browserNotificationsEnabled && ("Notification" in window)) {
165
+ if (await Notification.requestPermission() === "granted") {
166
+ this.browserNotificationsBootstrapped = true;
167
+ }
168
+ }
169
+ }
170
+ // Initializes default text
171
+ initializeDefaultText() {
172
+ if (!this.localization) {
173
+ this.localization = {
174
+ messagePlaceholder: this.messagePlaceholder,
175
+ searchPlaceholder: this.searchPlaceholder,
176
+ title: this.title,
177
+ statusDescription: this.statusDescription,
178
+ browserNotificationTitle: this.browserNotificationTitle,
179
+ loadMessageHistoryPlaceholder: "Load older messages"
180
+ };
181
+ }
182
+ }
183
+ initializeTheme() {
184
+ if (this.customTheme) {
185
+ this.theme = Theme.Custom;
186
+ }
187
+ else if (this.theme != Theme.Light && this.theme != Theme.Dark) {
188
+ // TODO: Use es2017 in future with Object.values(Theme).includes(this.theme) to do this check
189
+ throw new Error(`Invalid theme configuration for ng-chat. "${this.theme}" is not a valid theme value.`);
190
+ }
191
+ }
192
+ // Sends a request to load the friends list
193
+ fetchFriendsList(isBootstrapping) {
194
+ this.adapter.listFriends()
195
+ .pipe(map((participantsResponse) => {
196
+ this.participantsResponse = participantsResponse;
197
+ this.participants = participantsResponse.map((response) => {
198
+ return response.participant;
199
+ });
200
+ })).subscribe(() => {
201
+ if (isBootstrapping) {
202
+ this.restoreWindowsState();
203
+ }
204
+ });
205
+ }
206
+ fetchMessageHistory(window) {
207
+ // Not ideal but will keep this until we decide if we are shipping pagination with the default adapter
208
+ if (this.adapter instanceof PagedHistoryChatAdapter) {
209
+ window.isLoadingHistory = true;
210
+ this.adapter.getMessageHistoryByPage(window.participant.id, this.historyPageSize, ++window.historyPage)
211
+ .pipe(map((result) => {
212
+ result.forEach((message) => this.assertMessageType(message));
213
+ window.messages = result.concat(window.messages);
214
+ window.isLoadingHistory = false;
215
+ const direction = (window.historyPage == 1) ? ScrollDirection.Bottom : ScrollDirection.Top;
216
+ window.hasMoreMessages = result.length == this.historyPageSize;
217
+ setTimeout(() => this.onFetchMessageHistoryLoaded(result, window, direction, true));
218
+ })).subscribe();
219
+ }
220
+ else {
221
+ this.adapter.getMessageHistory(window.participant.id)
222
+ .pipe(map((result) => {
223
+ result.forEach((message) => this.assertMessageType(message));
224
+ window.messages = result.concat(window.messages);
225
+ window.isLoadingHistory = false;
226
+ setTimeout(() => this.onFetchMessageHistoryLoaded(result, window, ScrollDirection.Bottom));
227
+ })).subscribe();
228
+ }
229
+ }
230
+ onFetchMessageHistoryLoaded(messages, window, direction, forceMarkMessagesAsSeen = false) {
231
+ this.scrollChatWindow(window, direction);
232
+ if (window.hasFocus || forceMarkMessagesAsSeen) {
233
+ const unseenMessages = messages.filter(m => !m.dateSeen);
234
+ this.markMessagesAsRead(unseenMessages);
235
+ }
236
+ }
237
+ // Updates the friends list via the event handler
238
+ onFriendsListChanged(participantsResponse) {
239
+ if (participantsResponse) {
240
+ this.participantsResponse = participantsResponse;
241
+ this.participants = participantsResponse.map((response) => {
242
+ return response.participant;
243
+ });
244
+ this.participantsInteractedWith = [];
245
+ }
246
+ }
247
+ // Handles received messages by the adapter
248
+ onMessageReceived(participant, message) {
249
+ if (participant && message) {
250
+ const chatWindow = this.openChatWindow(participant);
251
+ this.assertMessageType(message);
252
+ if (!chatWindow[1] || !this.historyEnabled) {
253
+ chatWindow[0].messages.push(message);
254
+ this.scrollChatWindow(chatWindow[0], ScrollDirection.Bottom);
255
+ if (chatWindow[0].hasFocus) {
256
+ this.markMessagesAsRead([message]);
257
+ }
258
+ }
259
+ this.emitMessageSound(chatWindow[0]);
260
+ // Do not push browser notifications with message content for privacy purposes if the 'maximizeWindowOnNewMessage' setting is off and this is a new chat window.
261
+ if (this.maximizeWindowOnNewMessage || (!chatWindow[1] && !chatWindow[0].isCollapsed)) {
262
+ // Some messages are not pushed because they are loaded by fetching the history hence why we supply the message here
263
+ this.emitBrowserNotification(chatWindow[0], message);
264
+ }
265
+ }
266
+ }
267
+ onParticipantClickedFromFriendsList(participant) {
268
+ this.openChatWindow(participant, true, true);
269
+ }
270
+ cancelOptionPrompt() {
271
+ if (this.currentActiveOption) {
272
+ this.currentActiveOption.isActive = false;
273
+ this.currentActiveOption = null;
274
+ }
275
+ }
276
+ onOptionPromptCanceled() {
277
+ this.cancelOptionPrompt();
278
+ }
279
+ onOptionPromptConfirmed(event) {
280
+ // For now this is fine as there is only one option available. Introduce option types and type checking if a new option is added.
281
+ this.confirmNewGroup(event);
282
+ // Canceling current state
283
+ this.cancelOptionPrompt();
284
+ }
285
+ confirmNewGroup(users) {
286
+ const newGroup = new Group(users);
287
+ this.openChatWindow(newGroup);
288
+ if (this.groupAdapter) {
289
+ this.groupAdapter.groupCreated(newGroup);
290
+ }
291
+ }
292
+ // Opens a new chat whindow. Takes care of available viewport
293
+ // Works for opening a chat window for an user or for a group
294
+ // Returns => [Window: Window object reference, boolean: Indicates if this window is a new chat window]
295
+ openChatWindow(participant, focusOnNewWindow = false, invokedByUserClick = false) {
296
+ // Is this window opened?
297
+ const openedWindow = this.windows.find(x => x.participant.id == participant.id);
298
+ if (!openedWindow) {
299
+ if (invokedByUserClick) {
300
+ this.onParticipantClicked.emit(participant);
301
+ }
302
+ // Refer to issue #58 on Github
303
+ const collapseWindow = invokedByUserClick ? false : !this.maximizeWindowOnNewMessage;
304
+ const newChatWindow = new Window(participant, this.historyEnabled, collapseWindow);
305
+ // Loads the chat history via an RxJs Observable
306
+ if (this.historyEnabled) {
307
+ this.fetchMessageHistory(newChatWindow);
308
+ }
309
+ this.windows.unshift(newChatWindow);
310
+ // Is there enough space left in the view port ? but should be displayed in mobile if option is enabled
311
+ if (!this.isViewportOnMobileEnabled) {
312
+ if (this.windows.length * this.windowSizeFactor >= this.viewPortTotalArea - (!this.hideFriendsList ? this.friendsListWidth : 0)) {
313
+ this.windows.pop();
314
+ }
315
+ }
316
+ this.updateWindowsState(this.windows);
317
+ if (focusOnNewWindow && !collapseWindow) {
318
+ this.focusOnWindow(newChatWindow);
319
+ }
320
+ this.participantsInteractedWith.push(participant);
321
+ this.onParticipantChatOpened.emit(participant);
322
+ return [newChatWindow, true];
323
+ }
324
+ else {
325
+ // Returns the existing chat window
326
+ return [openedWindow, false];
327
+ }
328
+ }
329
+ // Focus on the input element of the supplied window
330
+ focusOnWindow(window, callback = () => { }) {
331
+ const windowIndex = this.windows.indexOf(window);
332
+ if (windowIndex >= 0) {
333
+ setTimeout(() => {
334
+ if (this.chatWindows) {
335
+ const chatWindowToFocus = this.chatWindows.toArray()[windowIndex];
336
+ chatWindowToFocus.chatWindowInput.nativeElement.focus();
337
+ }
338
+ callback();
339
+ });
340
+ }
341
+ }
342
+ assertMessageType(message) {
343
+ // Always fallback to "Text" messages to avoid rendenring issues
344
+ if (!message.type) {
345
+ message.type = MessageType.Text;
346
+ }
347
+ }
348
+ // Marks all messages provided as read with the current time.
349
+ markMessagesAsRead(messages) {
350
+ const currentDate = new Date();
351
+ messages.forEach((msg) => {
352
+ msg.dateSeen = currentDate;
353
+ });
354
+ this.onMessagesSeen.emit(messages);
355
+ }
356
+ // Buffers audio file (For component's bootstrapping)
357
+ bufferAudioFile() {
358
+ if (this.audioSource && this.audioSource.length > 0) {
359
+ this.audioFile = new Audio();
360
+ this.audioFile.src = this.audioSource;
361
+ this.audioFile.load();
362
+ }
363
+ }
364
+ // Emits a message notification audio if enabled after every message received
365
+ emitMessageSound(window) {
366
+ if (this.audioEnabled && !window.hasFocus && this.audioFile) {
367
+ this.audioFile.play();
368
+ }
369
+ }
370
+ // Emits a browser notification
371
+ emitBrowserNotification(window, message) {
372
+ // if (this.browserNotificationsBootstrapped && !window.hasFocus && message) {
373
+ if (this.browserNotificationsBootstrapped && message) {
374
+ const notification = new Notification(`${this.localization.browserNotificationTitle} ${window.participant.displayName}`, {
375
+ 'body': message.message,
376
+ 'icon': this.browserNotificationIconSource
377
+ });
378
+ setTimeout(() => {
379
+ notification.close();
380
+ }, message.message.length <= 50 ? 5000 : 7000); // More time to read longer messages
381
+ }
382
+ }
383
+ // Saves current windows state into local storage if persistence is enabled
384
+ updateWindowsState(windows) {
385
+ if (this.persistWindowsState) {
386
+ const participantIds = windows.map((w) => {
387
+ return w.participant.id;
388
+ });
389
+ localStorage.setItem(this.localStorageKey, JSON.stringify(participantIds));
390
+ }
391
+ }
392
+ restoreWindowsState() {
393
+ try {
394
+ if (this.persistWindowsState) {
395
+ const stringfiedParticipantIds = localStorage.getItem(this.localStorageKey);
396
+ if (stringfiedParticipantIds && stringfiedParticipantIds.length > 0) {
397
+ const participantIds = JSON.parse(stringfiedParticipantIds);
398
+ const participantsToRestore = this.participants.filter(u => participantIds.indexOf(u.id) >= 0);
399
+ participantsToRestore.forEach((participant) => {
400
+ this.openChatWindow(participant);
401
+ });
402
+ }
403
+ }
404
+ }
405
+ catch (ex) {
406
+ console.error(`An error occurred while restoring ng-chat windows state. Details: ${ex}`);
407
+ }
408
+ }
409
+ // Gets closest open window if any. Most recent opened has priority (Right)
410
+ getClosestWindow(window) {
411
+ const index = this.windows.indexOf(window);
412
+ if (index > 0) {
413
+ return this.windows[index - 1];
414
+ }
415
+ else if (index == 0 && this.windows.length > 1) {
416
+ return this.windows[index + 1];
417
+ }
418
+ }
419
+ closeWindow(window) {
420
+ const index = this.windows.indexOf(window);
421
+ this.windows.splice(index, 1);
422
+ this.updateWindowsState(this.windows);
423
+ this.onParticipantChatClosed.emit(window.participant);
424
+ }
425
+ getChatWindowComponentInstance(targetWindow) {
426
+ const windowIndex = this.windows.indexOf(targetWindow);
427
+ if (this.chatWindows) {
428
+ let targetWindow = this.chatWindows.toArray()[windowIndex];
429
+ return targetWindow;
430
+ }
431
+ return null;
432
+ }
433
+ // Scrolls a chat window message flow to the bottom
434
+ scrollChatWindow(window, direction) {
435
+ const chatWindow = this.getChatWindowComponentInstance(window);
436
+ if (chatWindow) {
437
+ chatWindow.scrollChatWindow(window, direction);
438
+ }
439
+ }
440
+ onWindowMessagesSeen(messagesSeen) {
441
+ this.markMessagesAsRead(messagesSeen);
442
+ }
443
+ onWindowChatClosed(payload) {
444
+ const { closedWindow, closedViaEscapeKey } = payload;
445
+ if (closedViaEscapeKey) {
446
+ let closestWindow = this.getClosestWindow(closedWindow);
447
+ if (closestWindow) {
448
+ this.focusOnWindow(closestWindow, () => { this.closeWindow(closedWindow); });
449
+ }
450
+ else {
451
+ this.closeWindow(closedWindow);
452
+ }
453
+ }
454
+ else {
455
+ this.closeWindow(closedWindow);
456
+ }
457
+ }
458
+ onWindowTabTriggered(payload) {
459
+ const { triggeringWindow, shiftKeyPressed } = payload;
460
+ const currentWindowIndex = this.windows.indexOf(triggeringWindow);
461
+ let windowToFocus = this.windows[currentWindowIndex + (shiftKeyPressed ? 1 : -1)]; // Goes back on shift + tab
462
+ if (!windowToFocus) {
463
+ // Edge windows, go to start or end
464
+ windowToFocus = this.windows[currentWindowIndex > 0 ? 0 : this.chatWindows.length - 1];
465
+ }
466
+ this.focusOnWindow(windowToFocus);
467
+ }
468
+ onWindowMessageSent(messageSent) {
469
+ this.adapter.sendMessage(messageSent);
470
+ }
471
+ onWindowOptionTriggered(option) {
472
+ this.currentActiveOption = option;
473
+ }
474
+ triggerOpenChatWindow(user) {
475
+ if (user) {
476
+ this.openChatWindow(user);
477
+ }
478
+ }
479
+ triggerCloseChatWindow(userId) {
480
+ const openedWindow = this.windows.find(x => x.participant.id == userId);
481
+ if (openedWindow) {
482
+ this.closeWindow(openedWindow);
483
+ }
484
+ }
485
+ triggerToggleChatWindowVisibility(userId) {
486
+ const openedWindow = this.windows.find(x => x.participant.id == userId);
487
+ if (openedWindow) {
488
+ const chatWindow = this.getChatWindowComponentInstance(openedWindow);
489
+ if (chatWindow) {
490
+ chatWindow.onChatWindowClicked(openedWindow);
491
+ }
492
+ }
493
+ }
494
+ // closeFriendList(){
495
+ // this.hideFriendsList = !this.hideFriendsList
496
+ // this.hideFriendsListChange.emit(this.hideFriendsList)
497
+ // }
498
+ onCloseWindowClick(click) {
499
+ this.onCloseWindowClicked.emit(click);
500
+ }
501
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.1.0", ngImport: i0, type: NgChat, deps: [{ token: i1.HttpClient }], target: i0.ɵɵFactoryTarget.Component }); }
502
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.1.0", type: NgChat, selector: "mnl-chat", inputs: { isDisabled: "isDisabled", adapter: "adapter", groupAdapter: "groupAdapter", userId: "userId", isCollapsed: "isCollapsed", maximizeWindowOnNewMessage: "maximizeWindowOnNewMessage", pollFriendsList: "pollFriendsList", pollingInterval: "pollingInterval", historyEnabled: "historyEnabled", emojisEnabled: "emojisEnabled", linkfyEnabled: "linkfyEnabled", audioEnabled: "audioEnabled", searchEnabled: "searchEnabled", audioSource: "audioSource", persistWindowsState: "persistWindowsState", title: "title", messagePlaceholder: "messagePlaceholder", searchPlaceholder: "searchPlaceholder", browserNotificationsEnabled: "browserNotificationsEnabled", browserNotificationIconSource: "browserNotificationIconSource", browserNotificationTitle: "browserNotificationTitle", historyPageSize: "historyPageSize", localization: "localization", hideFriendsList: "hideFriendsList", hideFriendsListOnUnsupportedViewport: "hideFriendsListOnUnsupportedViewport", fileUploadUrl: "fileUploadUrl", theme: "theme", customTheme: "customTheme", messageDatePipeFormat: "messageDatePipeFormat", showMessageDate: "showMessageDate", isViewportOnMobileEnabled: "isViewportOnMobileEnabled", fileUploadAdapter: "fileUploadAdapter" }, outputs: { onParticipantClicked: "onParticipantClicked", onParticipantChatOpened: "onParticipantChatOpened", onParticipantChatClosed: "onParticipantChatClosed", onMessagesSeen: "onMessagesSeen", onCloseWindowClicked: "onCloseWindowClicked" }, host: { listeners: { "window:resize": "onResize($event)" } }, viewQueries: [{ propertyName: "chatWindows", predicate: ["chatWindow"], descendants: true }], ngImport: i0, template: "<link *ngIf=\"customTheme\" rel=\"stylesheet\" [href]='customTheme | sanitize'>\n\n<div id=\"ng-chat\" *ngIf=\"!isDisabled && isBootstrapped && !unsupportedViewport\" [ngClass]=\"theme\">\n <ng-chat-friends-list\n [localization]=\"localization\"\n [shouldDisplay]=\"!hideFriendsList\"\n [userId]=\"userId\"\n [isCollapsed]=\"isCollapsed\"\n [searchEnabled]=\"searchEnabled\"\n [participants]=\"participants\"\n [participantsResponse]=\"participantsResponse\"\n [participantsInteractedWith]=\"participantsInteractedWith\"\n [windows]=\"windows\"\n [currentActiveOption]=\"currentActiveOption\"\n (onParticipantClicked)=\"onParticipantClickedFromFriendsList($event)\"\n (onOptionPromptCanceled)=\"onOptionPromptCanceled()\"\n (onOptionPromptConfirmed)=\"onOptionPromptConfirmed($event)\"\n (onCloseWindowClick)=\"onCloseWindowClick($event)\"\n >\n </ng-chat-friends-list>\n\n <div *ngFor=\"let window of windows; let i = index\" [ngClass]=\"{'ng-chat-window': true, 'primary-outline-color': true, 'ng-chat-window-collapsed': window.isCollapsed}\" [ngStyle]=\"{'right': (!hideFriendsList ? friendsListWidth : 0) + 20 + windowSizeFactor * i + 'px'}\">\n <ng-chat-window\n #chatWindow\n [fileUploadAdapter]=\"fileUploadAdapter\"\n [localization]=\"localization\"\n [userId]=\"userId\"\n [window]=\"window\"\n [showOptions]=\"groupAdapter\"\n [emojisEnabled]=\"emojisEnabled\"\n [linkfyEnabled]=\"linkfyEnabled\"\n [showMessageDate]=\"showMessageDate\"\n [messageDatePipeFormat]=\"messageDatePipeFormat\"\n [hasPagedHistory]=\"hasPagedHistory\"\n (onMessagesSeen)=\"onWindowMessagesSeen($event)\"\n (onMessageSent)=\"onWindowMessageSent($event)\"\n (onTabTriggered)=\"onWindowTabTriggered($event)\"\n (onChatWindowClosed)=\"onWindowChatClosed($event)\"\n (onOptionTriggered)=\"onWindowOptionTriggered($event)\"\n (onLoadHistoryTriggered)=\"fetchMessageHistory($event)\"\n >\n </ng-chat-window>\n </div>\n</div>\n", styles: [".user-icon{box-sizing:border-box;background-color:#fff;border:2px solid;width:32px;height:20px;border-radius:64px 64px 0 0/64px;margin-top:14px;margin-left:-1px;display:inline-block;vertical-align:middle;position:relative;font-style:normal;color:#ddd;text-align:left;text-indent:-9999px}.user-icon:before{border:2px solid;background-color:#fff;width:12px;height:12px;top:-19px;border-radius:50%;position:absolute;left:50%;-webkit-transform:translateX(-50%);-ms-transform:translateX(-50%);transform:translate(-50%)}.user-icon:before,.user-icon:after{content:\"\";pointer-events:none}.upload-icon{position:absolute;margin-left:3px;margin-top:12px;width:13px;height:4px;border:solid 1px currentColor;border-top:none;border-radius:1px}.upload-icon:before{content:\"\";position:absolute;top:-8px;left:6px;width:1px;height:9px;background-color:currentColor}.upload-icon:after{content:\"\";position:absolute;top:-8px;left:4px;width:4px;height:4px;border-top:solid 1px currentColor;border-right:solid 1px currentColor;-webkit-transform:rotate(-45deg);transform:rotate(-45deg)}.paperclip-icon{position:absolute;margin-left:9px;margin-top:2px;width:6px;height:12px;border-radius:4px 4px 0 0;border-left:solid 1px currentColor;border-right:solid 1px currentColor;border-top:solid 1px currentColor;-webkit-transform:rotate(45deg);transform:rotate(45deg)}.paperclip-icon:before{content:\"\";position:absolute;top:11px;left:-1px;width:4px;height:6px;border-radius:0 0 3px 3px;border-left:solid 1px currentColor;border-right:solid 1px currentColor;border-bottom:solid 1px currentColor}.paperclip-icon:after{content:\"\";position:absolute;left:1px;top:1px;width:2px;height:10px;border-radius:4px 4px 0 0;border-left:solid 1px currentColor;border-right:solid 1px currentColor;border-top:solid 1px currentColor}.check-icon{color:#000;position:absolute;margin-left:3px;margin-top:4px;width:14px;height:8px;border-bottom:solid 1px currentColor;border-left:solid 1px currentColor;-webkit-transform:rotate(-45deg);transform:rotate(-45deg)}.remove-icon{color:#000;position:absolute;margin-left:3px;margin-top:10px}.remove-icon:before{content:\"\";position:absolute;width:15px;height:1px;background-color:currentColor;-webkit-transform:rotate(45deg);transform:rotate(45deg)}.remove-icon:after{content:\"\";position:absolute;width:15px;height:1px;background-color:currentColor;-webkit-transform:rotate(-45deg);transform:rotate(-45deg)}\n", ".loader,.loader:before,.loader:after{background:#e3e3e3;-webkit-animation:load1 1s infinite ease-in-out;animation:load1 1s infinite ease-in-out;width:1em;height:4em}.loader{color:#e3e3e3;text-indent:-9999em;margin:4px auto 0;position:relative;font-size:4px;-webkit-transform:translateZ(0);-ms-transform:translateZ(0);transform:translateZ(0);-webkit-animation-delay:-.16s;animation-delay:-.16s}.loader:before,.loader:after{position:absolute;top:0;content:\"\"}.loader:before{left:-1.5em;-webkit-animation-delay:-.32s;animation-delay:-.32s}.loader:after{left:1.5em}@-webkit-keyframes load1{0%,80%,to{box-shadow:0 0;height:4em}40%{box-shadow:0 -2em;height:5em}}@keyframes load1{0%,80%,to{box-shadow:0 0;height:4em}40%{box-shadow:0 -2em;height:5em}}\n", "#ng-chat{position:fixed;z-index:999;right:0;bottom:0;box-sizing:initial;font-size:11pt;text-align:left}#ng-chat input{outline:none}#ng-chat .shadowed{box-shadow:0 4px 8px #00000040}.ng-chat-loading-wrapper{height:30px;text-align:center;font-size:.9em}.ng-chat-close{text-decoration:none!important;color:red!important;float:right!important;font-weight:900!important;font-size:15px!important}.ng-chat-title,.ng-chat-title:hover{position:relative;z-index:2;height:30px;line-height:30px;font-size:.9em;padding:0 10px;display:block;text-decoration:none;color:#fff!important;font-weight:600!important;cursor:pointer;background-color:#1b1b70!important}.ng-chat-title .ng-chat-title-visibility-toggle-area{display:inline-block;width:85%}.ng-chat-title .ng-chat-title-visibility-toggle-area>strong{font-weight:600;display:block;overflow:hidden;height:30px;text-overflow:ellipsis;white-space:nowrap;max-width:85%;float:left}.ng-chat-title .ng-chat-title-visibility-toggle-area .ng-chat-participant-status{float:left;margin-left:5px}.ng-chat-participant-status{display:inline-block;border-radius:25px;width:8px;height:8px;margin-top:10px}.ng-chat-participant-status.online{background-color:#92a400}.ng-chat-participant-status.busy{background-color:#f91c1e}.ng-chat-participant-status.away{background-color:#f7d21b}.ng-chat-participant-status.offline{background-color:#bababa}.ng-chat-unread-messages-count{margin-left:5px;padding:0 5px;border-radius:25px;font-size:.9em;line-height:30px}.ng-chat-options-container{float:right;margin-right:5px}\n", "#ng-chat.light-theme .primary-text,#ng-chat.light-theme{color:#5c5c5c;font-family:Arial,Helvetica,sans-serif}#ng-chat.light-theme .primary-background{background-color:#fff}#ng-chat.light-theme .secondary-background{background-color:#fafafa}#ng-chat.light-theme .primary-outline-color{border-color:#a3a3a3}#ng-chat.light-theme .friends-search-bar{background-color:#fff}#ng-chat.light-theme .unread-messages-counter-container,#ng-chat.light-theme .ng-chat-people-action,#ng-chat.light-theme .ng-chat-people-action>i{color:#5c5c5c;background-color:#e3e3e3}#ng-chat.light-theme .load-history-action{background-color:#e3e3e3}#ng-chat.light-theme .chat-window-input{background-color:#fff}#ng-chat.light-theme .sent-chat-message-container,#ng-chat.light-theme .file-message-container{background-color:#e3e3e3;border-color:#e3e3e3}#ng-chat.light-theme .received-chat-message-container,#ng-chat.light-theme .file-message-container.received{background-color:#fff;border-color:#e3e3e3}body{font-family:Roboto,Helvetica Neue,sans-serif!important}*{box-shadow:none!important}\n", "#ng-chat.dark-theme .primary-text,#ng-chat.dark-theme{color:#fff;font-family:Arial,Helvetica,sans-serif}#ng-chat.dark-theme .primary-background{background-color:#565656}#ng-chat.dark-theme .secondary-background{background-color:#444}#ng-chat.dark-theme .primary-outline-color{border-color:#353535}#ng-chat.dark-theme .friends-search-bar{background-color:#444;border:1px solid #444;color:#fff}#ng-chat.dark-theme .unread-messages-counter-container,#ng-chat.dark-theme .ng-chat-people-action,#ng-chat.dark-theme .ng-chat-people-action>i{background-color:#fff;color:#444}#ng-chat.dark-theme .load-history-action{background-color:#444}#ng-chat.dark-theme .chat-window-input{background-color:#444;color:#fff}#ng-chat.dark-theme .sent-chat-message-container,#ng-chat.dark-theme .file-message-container{border-color:#444;background-color:#444}#ng-chat.dark-theme .received-chat-message-container,#ng-chat.dark-theme .file-message-container.received{background-color:#565656;border-color:#444}#ng-chat.dark-theme .ng-chat-footer{background-color:#444}#ng-chat.dark-theme .ng-chat-message a{color:#fff}body{font-family:Roboto,Helvetica Neue,sans-serif!important}\n"], dependencies: [{ kind: "directive", type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "component", type: i3.NgChatFriendsListComponent, selector: "ng-chat-friends-list", inputs: ["participants", "participantsResponse", "participantsInteractedWith", "windows", "userId", "localization", "shouldDisplay", "isCollapsed", "searchEnabled", "currentActiveOption", "hideFriendsList"], outputs: ["onParticipantClicked", "onOptionPromptCanceled", "onOptionPromptConfirmed", "onCloseWindowClick"] }, { kind: "component", type: i4.NgChatWindowComponent, selector: "ng-chat-window", inputs: ["fileUploadAdapter", "window", "userId", "localization", "showOptions", "emojisEnabled", "linkfyEnabled", "showMessageDate", "messageDatePipeFormat", "hasPagedHistory"], outputs: ["onChatWindowClosed", "onMessagesSeen", "onMessageSent", "onTabTriggered", "onOptionTriggered", "onLoadHistoryTriggered"] }, { kind: "pipe", type: i5.SanitizePipe, name: "sanitize" }], encapsulation: i0.ViewEncapsulation.None }); }
503
+ }
504
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.1.0", ngImport: i0, type: NgChat, decorators: [{
505
+ type: Component,
506
+ args: [{ selector: 'mnl-chat', encapsulation: ViewEncapsulation.None, template: "<link *ngIf=\"customTheme\" rel=\"stylesheet\" [href]='customTheme | sanitize'>\n\n<div id=\"ng-chat\" *ngIf=\"!isDisabled && isBootstrapped && !unsupportedViewport\" [ngClass]=\"theme\">\n <ng-chat-friends-list\n [localization]=\"localization\"\n [shouldDisplay]=\"!hideFriendsList\"\n [userId]=\"userId\"\n [isCollapsed]=\"isCollapsed\"\n [searchEnabled]=\"searchEnabled\"\n [participants]=\"participants\"\n [participantsResponse]=\"participantsResponse\"\n [participantsInteractedWith]=\"participantsInteractedWith\"\n [windows]=\"windows\"\n [currentActiveOption]=\"currentActiveOption\"\n (onParticipantClicked)=\"onParticipantClickedFromFriendsList($event)\"\n (onOptionPromptCanceled)=\"onOptionPromptCanceled()\"\n (onOptionPromptConfirmed)=\"onOptionPromptConfirmed($event)\"\n (onCloseWindowClick)=\"onCloseWindowClick($event)\"\n >\n </ng-chat-friends-list>\n\n <div *ngFor=\"let window of windows; let i = index\" [ngClass]=\"{'ng-chat-window': true, 'primary-outline-color': true, 'ng-chat-window-collapsed': window.isCollapsed}\" [ngStyle]=\"{'right': (!hideFriendsList ? friendsListWidth : 0) + 20 + windowSizeFactor * i + 'px'}\">\n <ng-chat-window\n #chatWindow\n [fileUploadAdapter]=\"fileUploadAdapter\"\n [localization]=\"localization\"\n [userId]=\"userId\"\n [window]=\"window\"\n [showOptions]=\"groupAdapter\"\n [emojisEnabled]=\"emojisEnabled\"\n [linkfyEnabled]=\"linkfyEnabled\"\n [showMessageDate]=\"showMessageDate\"\n [messageDatePipeFormat]=\"messageDatePipeFormat\"\n [hasPagedHistory]=\"hasPagedHistory\"\n (onMessagesSeen)=\"onWindowMessagesSeen($event)\"\n (onMessageSent)=\"onWindowMessageSent($event)\"\n (onTabTriggered)=\"onWindowTabTriggered($event)\"\n (onChatWindowClosed)=\"onWindowChatClosed($event)\"\n (onOptionTriggered)=\"onWindowOptionTriggered($event)\"\n (onLoadHistoryTriggered)=\"fetchMessageHistory($event)\"\n >\n </ng-chat-window>\n </div>\n</div>\n", styles: [".user-icon{box-sizing:border-box;background-color:#fff;border:2px solid;width:32px;height:20px;border-radius:64px 64px 0 0/64px;margin-top:14px;margin-left:-1px;display:inline-block;vertical-align:middle;position:relative;font-style:normal;color:#ddd;text-align:left;text-indent:-9999px}.user-icon:before{border:2px solid;background-color:#fff;width:12px;height:12px;top:-19px;border-radius:50%;position:absolute;left:50%;-webkit-transform:translateX(-50%);-ms-transform:translateX(-50%);transform:translate(-50%)}.user-icon:before,.user-icon:after{content:\"\";pointer-events:none}.upload-icon{position:absolute;margin-left:3px;margin-top:12px;width:13px;height:4px;border:solid 1px currentColor;border-top:none;border-radius:1px}.upload-icon:before{content:\"\";position:absolute;top:-8px;left:6px;width:1px;height:9px;background-color:currentColor}.upload-icon:after{content:\"\";position:absolute;top:-8px;left:4px;width:4px;height:4px;border-top:solid 1px currentColor;border-right:solid 1px currentColor;-webkit-transform:rotate(-45deg);transform:rotate(-45deg)}.paperclip-icon{position:absolute;margin-left:9px;margin-top:2px;width:6px;height:12px;border-radius:4px 4px 0 0;border-left:solid 1px currentColor;border-right:solid 1px currentColor;border-top:solid 1px currentColor;-webkit-transform:rotate(45deg);transform:rotate(45deg)}.paperclip-icon:before{content:\"\";position:absolute;top:11px;left:-1px;width:4px;height:6px;border-radius:0 0 3px 3px;border-left:solid 1px currentColor;border-right:solid 1px currentColor;border-bottom:solid 1px currentColor}.paperclip-icon:after{content:\"\";position:absolute;left:1px;top:1px;width:2px;height:10px;border-radius:4px 4px 0 0;border-left:solid 1px currentColor;border-right:solid 1px currentColor;border-top:solid 1px currentColor}.check-icon{color:#000;position:absolute;margin-left:3px;margin-top:4px;width:14px;height:8px;border-bottom:solid 1px currentColor;border-left:solid 1px currentColor;-webkit-transform:rotate(-45deg);transform:rotate(-45deg)}.remove-icon{color:#000;position:absolute;margin-left:3px;margin-top:10px}.remove-icon:before{content:\"\";position:absolute;width:15px;height:1px;background-color:currentColor;-webkit-transform:rotate(45deg);transform:rotate(45deg)}.remove-icon:after{content:\"\";position:absolute;width:15px;height:1px;background-color:currentColor;-webkit-transform:rotate(-45deg);transform:rotate(-45deg)}\n", ".loader,.loader:before,.loader:after{background:#e3e3e3;-webkit-animation:load1 1s infinite ease-in-out;animation:load1 1s infinite ease-in-out;width:1em;height:4em}.loader{color:#e3e3e3;text-indent:-9999em;margin:4px auto 0;position:relative;font-size:4px;-webkit-transform:translateZ(0);-ms-transform:translateZ(0);transform:translateZ(0);-webkit-animation-delay:-.16s;animation-delay:-.16s}.loader:before,.loader:after{position:absolute;top:0;content:\"\"}.loader:before{left:-1.5em;-webkit-animation-delay:-.32s;animation-delay:-.32s}.loader:after{left:1.5em}@-webkit-keyframes load1{0%,80%,to{box-shadow:0 0;height:4em}40%{box-shadow:0 -2em;height:5em}}@keyframes load1{0%,80%,to{box-shadow:0 0;height:4em}40%{box-shadow:0 -2em;height:5em}}\n", "#ng-chat{position:fixed;z-index:999;right:0;bottom:0;box-sizing:initial;font-size:11pt;text-align:left}#ng-chat input{outline:none}#ng-chat .shadowed{box-shadow:0 4px 8px #00000040}.ng-chat-loading-wrapper{height:30px;text-align:center;font-size:.9em}.ng-chat-close{text-decoration:none!important;color:red!important;float:right!important;font-weight:900!important;font-size:15px!important}.ng-chat-title,.ng-chat-title:hover{position:relative;z-index:2;height:30px;line-height:30px;font-size:.9em;padding:0 10px;display:block;text-decoration:none;color:#fff!important;font-weight:600!important;cursor:pointer;background-color:#1b1b70!important}.ng-chat-title .ng-chat-title-visibility-toggle-area{display:inline-block;width:85%}.ng-chat-title .ng-chat-title-visibility-toggle-area>strong{font-weight:600;display:block;overflow:hidden;height:30px;text-overflow:ellipsis;white-space:nowrap;max-width:85%;float:left}.ng-chat-title .ng-chat-title-visibility-toggle-area .ng-chat-participant-status{float:left;margin-left:5px}.ng-chat-participant-status{display:inline-block;border-radius:25px;width:8px;height:8px;margin-top:10px}.ng-chat-participant-status.online{background-color:#92a400}.ng-chat-participant-status.busy{background-color:#f91c1e}.ng-chat-participant-status.away{background-color:#f7d21b}.ng-chat-participant-status.offline{background-color:#bababa}.ng-chat-unread-messages-count{margin-left:5px;padding:0 5px;border-radius:25px;font-size:.9em;line-height:30px}.ng-chat-options-container{float:right;margin-right:5px}\n", "#ng-chat.light-theme .primary-text,#ng-chat.light-theme{color:#5c5c5c;font-family:Arial,Helvetica,sans-serif}#ng-chat.light-theme .primary-background{background-color:#fff}#ng-chat.light-theme .secondary-background{background-color:#fafafa}#ng-chat.light-theme .primary-outline-color{border-color:#a3a3a3}#ng-chat.light-theme .friends-search-bar{background-color:#fff}#ng-chat.light-theme .unread-messages-counter-container,#ng-chat.light-theme .ng-chat-people-action,#ng-chat.light-theme .ng-chat-people-action>i{color:#5c5c5c;background-color:#e3e3e3}#ng-chat.light-theme .load-history-action{background-color:#e3e3e3}#ng-chat.light-theme .chat-window-input{background-color:#fff}#ng-chat.light-theme .sent-chat-message-container,#ng-chat.light-theme .file-message-container{background-color:#e3e3e3;border-color:#e3e3e3}#ng-chat.light-theme .received-chat-message-container,#ng-chat.light-theme .file-message-container.received{background-color:#fff;border-color:#e3e3e3}body{font-family:Roboto,Helvetica Neue,sans-serif!important}*{box-shadow:none!important}\n", "#ng-chat.dark-theme .primary-text,#ng-chat.dark-theme{color:#fff;font-family:Arial,Helvetica,sans-serif}#ng-chat.dark-theme .primary-background{background-color:#565656}#ng-chat.dark-theme .secondary-background{background-color:#444}#ng-chat.dark-theme .primary-outline-color{border-color:#353535}#ng-chat.dark-theme .friends-search-bar{background-color:#444;border:1px solid #444;color:#fff}#ng-chat.dark-theme .unread-messages-counter-container,#ng-chat.dark-theme .ng-chat-people-action,#ng-chat.dark-theme .ng-chat-people-action>i{background-color:#fff;color:#444}#ng-chat.dark-theme .load-history-action{background-color:#444}#ng-chat.dark-theme .chat-window-input{background-color:#444;color:#fff}#ng-chat.dark-theme .sent-chat-message-container,#ng-chat.dark-theme .file-message-container{border-color:#444;background-color:#444}#ng-chat.dark-theme .received-chat-message-container,#ng-chat.dark-theme .file-message-container.received{background-color:#565656;border-color:#444}#ng-chat.dark-theme .ng-chat-footer{background-color:#444}#ng-chat.dark-theme .ng-chat-message a{color:#fff}body{font-family:Roboto,Helvetica Neue,sans-serif!important}\n"] }]
507
+ }], ctorParameters: () => [{ type: i1.HttpClient }], propDecorators: { isDisabled: [{
508
+ type: Input
509
+ }], adapter: [{
510
+ type: Input
511
+ }], groupAdapter: [{
512
+ type: Input
513
+ }], userId: [{
514
+ type: Input
515
+ }], isCollapsed: [{
516
+ type: Input
517
+ }], maximizeWindowOnNewMessage: [{
518
+ type: Input
519
+ }], pollFriendsList: [{
520
+ type: Input
521
+ }], pollingInterval: [{
522
+ type: Input
523
+ }], historyEnabled: [{
524
+ type: Input
525
+ }], emojisEnabled: [{
526
+ type: Input
527
+ }], linkfyEnabled: [{
528
+ type: Input
529
+ }], audioEnabled: [{
530
+ type: Input
531
+ }], searchEnabled: [{
532
+ type: Input
533
+ }], audioSource: [{
534
+ type: Input
535
+ }], persistWindowsState: [{
536
+ type: Input
537
+ }], title: [{
538
+ type: Input
539
+ }], messagePlaceholder: [{
540
+ type: Input
541
+ }], searchPlaceholder: [{
542
+ type: Input
543
+ }], browserNotificationsEnabled: [{
544
+ type: Input
545
+ }], browserNotificationIconSource: [{
546
+ type: Input
547
+ }], browserNotificationTitle: [{
548
+ type: Input
549
+ }], historyPageSize: [{
550
+ type: Input
551
+ }], localization: [{
552
+ type: Input
553
+ }], hideFriendsList: [{
554
+ type: Input
555
+ }], hideFriendsListOnUnsupportedViewport: [{
556
+ type: Input
557
+ }], fileUploadUrl: [{
558
+ type: Input
559
+ }], theme: [{
560
+ type: Input
561
+ }], customTheme: [{
562
+ type: Input
563
+ }], messageDatePipeFormat: [{
564
+ type: Input
565
+ }], showMessageDate: [{
566
+ type: Input
567
+ }], isViewportOnMobileEnabled: [{
568
+ type: Input
569
+ }], fileUploadAdapter: [{
570
+ type: Input
571
+ }], onParticipantClicked: [{
572
+ type: Output
573
+ }], onParticipantChatOpened: [{
574
+ type: Output
575
+ }], onParticipantChatClosed: [{
576
+ type: Output
577
+ }], onMessagesSeen: [{
578
+ type: Output
579
+ }], onCloseWindowClicked: [{
580
+ type: Output
581
+ }], chatWindows: [{
582
+ type: ViewChildren,
583
+ args: ['chatWindow']
584
+ }], onResize: [{
585
+ type: HostListener,
586
+ args: ['window:resize', ['$event']]
587
+ }] } });
588
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmctY2hhdC5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9jaGF0L3NyYy9saWIvY29tcG9uZW50cy9uZy1jaGF0L25nLWNoYXQuY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvY2hhdC9zcmMvbGliL2NvbXBvbmVudHMvbmctY2hhdC9uZy1jaGF0LmNvbXBvbmVudC5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLG9CQUFvQjtBQUNwQixPQUFPLEVBQUUsU0FBUyxFQUFFLEtBQUssRUFBVSxZQUFZLEVBQWEsWUFBWSxFQUFFLE1BQU0sRUFBRSxZQUFZLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFPekksT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLDhCQUE4QixDQUFDO0FBQzNELE9BQU8sRUFBRSxNQUFNLEVBQUUsTUFBTSxtQkFBbUIsQ0FBQztBQUMzQyxPQUFPLEVBQUUscUJBQXFCLEVBQUUsTUFBTSx5Q0FBeUMsQ0FBQztBQUNoRixPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0sa0NBQWtDLENBQUM7QUFHbkUsT0FBTyxFQUFFLHVCQUF1QixFQUFFLE1BQU0sdUNBQXVDLENBQUM7QUFFaEYsT0FBTyxFQUFFLHdCQUF3QixFQUFFLE1BQU0sd0NBQXdDLENBQUM7QUFDbEYsT0FBTyxFQUFFLEtBQUssRUFBRSxNQUFNLHVCQUF1QixDQUFDO0FBRTlDLE9BQU8sRUFBRSxLQUFLLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQztBQUN6QyxPQUFPLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSx1Q0FBdUMsQ0FBQztBQUU1RSxPQUFPLEVBQUUsR0FBRyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7Ozs7Ozs7QUFpQnJDLE1BQU0sT0FBTyxNQUFNO0lBQ2YsWUFBb0IsV0FBdUI7UUFBdkIsZ0JBQVcsR0FBWCxXQUFXLENBQVk7UUFFM0Msb0NBQW9DO1FBQzdCLHdCQUFtQixHQUFHLG1CQUFtQixDQUFDO1FBQzFDLDBCQUFxQixHQUFHLHFCQUFxQixDQUFDO1FBQzlDLGdCQUFXLEdBQUcsV0FBVyxDQUFDO1FBRXpCLGdCQUFXLEdBQVksS0FBSyxDQUFDO1FBOEI5QixnQkFBVyxHQUFZLEtBQUssQ0FBQztRQUc3QiwrQkFBMEIsR0FBWSxJQUFJLENBQUM7UUFHM0Msb0JBQWUsR0FBWSxLQUFLLENBQUM7UUFHakMsb0JBQWUsR0FBVyxJQUFJLENBQUM7UUFHL0IsbUJBQWMsR0FBWSxJQUFJLENBQUM7UUFHL0Isa0JBQWEsR0FBWSxJQUFJLENBQUM7UUFHOUIsa0JBQWEsR0FBWSxJQUFJLENBQUM7UUFHOUIsaUJBQVksR0FBWSxJQUFJLENBQUM7UUFHN0Isa0JBQWEsR0FBWSxJQUFJLENBQUM7UUFHOUIsZ0JBQVcsR0FBVyxrQ0FBa0MsQ0FBQztRQUd6RCx3QkFBbUIsR0FBWSxJQUFJLENBQUM7UUFHcEMsVUFBSyxHQUFXLFlBQVksQ0FBQztRQUc3Qix1QkFBa0IsR0FBVyxnQkFBZ0IsQ0FBQztRQUc5QyxzQkFBaUIsR0FBVyxRQUFRLENBQUM7UUFHckMsZ0NBQTJCLEdBQVksSUFBSSxDQUFDO1FBRzVDLGtDQUE2QixHQUFXLGtDQUFrQyxDQUFDO1FBRzNFLDZCQUF3QixHQUFXLGtCQUFrQixDQUFDO1FBR3RELG9CQUFlLEdBQVcsRUFBRSxDQUFDO1FBTTdCLG9CQUFlLEdBQVksS0FBSyxDQUFDO1FBR2pDLHlDQUFvQyxHQUFZLElBQUksQ0FBQztRQU1yRCxVQUFLLEdBQVUsS0FBSyxDQUFDLEtBQUssQ0FBQztRQU0zQiwwQkFBcUIsR0FBVyxPQUFPLENBQUM7UUFHeEMsb0JBQWUsR0FBWSxJQUFJLENBQUM7UUFHaEMsOEJBQXlCLEdBQVksS0FBSyxDQUFDO1FBTTNDLHlCQUFvQixHQUFtQyxJQUFJLFlBQVksRUFBb0IsQ0FBQztRQUc1Riw0QkFBdUIsR0FBbUMsSUFBSSxZQUFZLEVBQW9CLENBQUM7UUFHL0YsNEJBQXVCLEdBQW1DLElBQUksWUFBWSxFQUFvQixDQUFDO1FBRy9GLG1CQUFjLEdBQTRCLElBQUksWUFBWSxFQUFhLENBQUM7UUFHeEUseUJBQW9CLEdBQXlCLElBQUksWUFBWSxFQUFXLENBQUE7UUFFdkUscUNBQWdDLEdBQVksS0FBSyxDQUFDO1FBRW5ELG9CQUFlLEdBQVksS0FBSyxDQUFDO1FBRXhDLHdKQUF3SjtRQUNoSixzQkFBaUIsR0FBc0I7WUFDM0MsTUFBTSxFQUFFLFFBQVE7WUFDaEIsSUFBSSxFQUFFLE1BQU07WUFDWixJQUFJLEVBQUUsTUFBTTtZQUNaLE9BQU8sRUFBRSxTQUFTO1NBQ3JCLENBQUM7UUFRSywrQkFBMEIsR0FBdUIsRUFBRSxDQUFDO1FBVzNELHVIQUF1SDtRQUNoSCxxQkFBZ0IsR0FBVyxHQUFHLENBQUM7UUFFdEMsK0NBQStDO1FBQ3hDLHFCQUFnQixHQUFXLEdBQUcsQ0FBQztRQUt0QywwSEFBMEg7UUFDbkgsd0JBQW1CLEdBQVksS0FBSyxDQUFDO1FBRTVDLFlBQU8sR0FBYSxFQUFFLENBQUM7UUFDdkIsbUJBQWMsR0FBWSxLQUFLLENBQUM7SUFqTGUsQ0FBQztJQVNoRCxJQUFJLFVBQVU7UUFDVixPQUFPLElBQUksQ0FBQyxXQUFXLENBQUM7SUFDNUIsQ0FBQztJQUVELElBQ0ksVUFBVSxDQUFDLEtBQWM7UUFDekIsSUFBSSxDQUFDLFdBQVcsR0FBRyxLQUFLLENBQUM7UUFFekIsSUFBSSxLQUFLLEVBQ1QsQ0FBQztZQUNHLE1BQU0sQ0FBQyxhQUFhLENBQUMsSUFBSSxDQUFDLDZCQUE2QixDQUFDLENBQUE7UUFDNUQsQ0FBQzthQUVELENBQUM7WUFDRyxJQUFJLENBQUMsdUJBQXVCLEVBQUUsQ0FBQztRQUNuQyxDQUFDO0lBQ0wsQ0FBQztJQXNJRCxJQUFZLGVBQWU7UUFFdkIsT0FBTyxpQkFBaUIsSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFDLENBQUMsdUVBQXVFO0lBQ2xILENBQUM7SUFBQSxDQUFDO0lBbUJGLFFBQVE7UUFDSixJQUFJLENBQUMsYUFBYSxFQUFFLENBQUM7SUFDekIsQ0FBQztJQUdELFFBQVEsQ0FBQyxLQUFVO1FBQ2hCLElBQUksQ0FBQyxpQkFBaUIsR0FBRyxLQUFLLENBQUMsTUFBTSxDQUFDLFVBQVUsQ0FBQztRQUVqRCxJQUFJLENBQUMsZ0JBQWdCLEVBQUUsQ0FBQztJQUMzQixDQUFDO0lBRUQseUVBQXlFO0lBQ2pFLGdCQUFnQjtRQUVwQixNQUFNLHlCQUF5QixHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQyxJQUFJLENBQUMsaUJBQWlCLEdBQUcsQ0FBQyxDQUFDLElBQUksQ0FBQyxlQUFlLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsR0FBRyxJQUFJLENBQUMsZ0JBQWdCLENBQUMsQ0FBQztRQUNySixNQUFNLFVBQVUsR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDLE1BQU0sR0FBRyx5QkFBeUIsQ0FBQztRQUVuRSxJQUFJLFVBQVUsSUFBSSxDQUFDLEVBQ25CLENBQUM7WUFDRyxJQUFJLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLE1BQU0sR0FBRyxVQUFVLENBQUMsQ0FBQztRQUMxRCxDQUFDO1FBRUQsSUFBSSxDQUFDLGtCQUFrQixDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUV0QywwR0FBMEc7UUFDMUcsSUFBSSxDQUFDLG1CQUFtQixHQUFHLElBQUksQ0FBQyx5QkFBeUIsQ0FBQSxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsb0NBQW9DLElBQUkseUJBQXlCLEdBQUcsQ0FBQyxDQUFDO0lBQ2xKLENBQUM7SUFFRCx3REFBd0Q7SUFDaEQsYUFBYTtRQUVqQixJQUFJLHVCQUF1QixHQUFHLElBQUksQ0FBQztRQUVuQyxJQUFJLElBQUksQ0FBQyxPQUFPLElBQUksSUFBSSxJQUFJLElBQUksQ0FBQyxNQUFNLElBQUksSUFBSSxFQUMvQyxDQUFDO1lBQ0csSUFDQSxDQUFDO2dCQUNHLElBQUksQ0FBQyxpQkFBaUIsR0FBRyxNQUFNLENBQUMsVUFBVSxDQUFDO2dCQUUzQyxJQUFJLENBQUMsZUFBZSxFQUFFLENBQUM7Z0JBQ3ZCLElBQUksQ0FBQyxxQkFBcUIsRUFBRSxDQUFDO2dCQUM3QixJQUFJLENBQUMsOEJBQThCLEVBQUUsQ0FBQztnQkFFdEMsMEJBQTBCO2dCQUMxQixJQUFJLENBQUMsT0FBTyxDQUFDLHNCQUFzQixHQUFHLENBQUMsV0FBVyxFQUFFLEdBQUcsRUFBRSxFQUFFLENBQUMsSUFBSSxDQUFDLGlCQUFpQixDQUFDLFdBQVcsRUFBRSxHQUFHLENBQUMsQ0FBQztnQkFDckcsSUFBSSxDQUFDLE9BQU8sQ0FBQyx5QkFBeUIsR0FBRyxDQUFDLG9CQUFvQixFQUFFLEVBQUUsQ0FBQyxJQUFJLENBQUMsb0JBQW9CLENBQUMsb0JBQW9CLENBQUMsQ0FBQztnQkFFbkgsSUFBSSxDQUFDLHVCQUF1QixFQUFFLENBQUM7Z0JBRS9CLElBQUksQ0FBQyxlQUFlLEVBQUUsQ0FBQztnQkFFdkIsSUFBSSxDQUFDLGVBQWUsR0FBRyxJQUFJLENBQUMsT0FBTyxZQUFZLHVCQUF1QixDQUFDO2dCQUV2RSxJQUFJLElBQUksQ0FBQyxhQUFhLElBQUksSUFBSSxDQUFDLGFBQWEsS0FBSyxFQUFFLEVBQ25ELENBQUM7b0JBQ0csSUFBSSxDQUFDLGlCQUFpQixHQUFHLElBQUksd0JBQXdCLENBQUMsSUFBSSxDQUFDLGFBQWEsRUFBRSxJQUFJLENBQUMsV0FBVyxDQUFDLENBQUM7Z0JBQ2hHLENBQUM7Z0JBRUQsSUFBSSxDQUFDLGdCQUFnQixFQUFFLENBQUM7Z0JBRXhCLElBQUksQ0FBQyxjQUFjLEdBQUcsSUFBSSxDQUFDO1lBQy9CLENBQUM7WUFDRCxPQUFNLEVBQUUsRUFDUixDQUFDO2dCQUNHLHVCQUF1QixHQUFHLEVBQUUsQ0FBQztZQUNqQyxDQUFDO1FBQ0wsQ0FBQztRQUVELElBQUksQ0FBQyxJQUFJLENBQUMsY0FBYyxFQUFDLENBQUM7WUFDdEIsT0FBTyxDQUFDLEtBQUssQ0FBQyw2Q0FBNkMsQ0FBQyxDQUFDO1lBRTdELElBQUksSUFBSSxDQUFDLE1BQU0sSUFBSSxJQUFJLEVBQUMsQ0FBQztnQkFDckIsT0FBTyxDQUFDLEtBQUssQ0FBQyxzSUFBc0ksQ0FBQyxDQUFDO1lBQzFKLENBQUM7WUFDRCxJQUFJLElBQUksQ0FBQyxPQUFPLElBQUksSUFBSSxFQUFDLENBQUM7Z0JBQ3RCLE9BQU8sQ0FBQyxLQUFLLENBQUMsNkpBQTZKLENBQUMsQ0FBQztZQUNqTCxDQUFDO1lBQ0QsSUFBSSx1QkFBdUIsRUFDM0IsQ0FBQztnQkFDRyxPQUFPLENBQUMsS0FBSyxDQUFDLGtFQUFrRSx1QkFBdUIsQ0FBQyxPQUFPLEVBQUUsQ0FBQyxDQUFDO2dCQUNuSCxPQUFPLENBQUMsS0FBSyxDQUFDLHVCQUF1QixDQUFDLENBQUM7WUFDM0MsQ0FBQztRQUNMLENBQUM7SUFDTCxDQUFDO0lBRU8sdUJBQXVCO1FBQzNCLElBQUksSUFBSSxDQUFDLE9BQU8sRUFDaEIsQ0FBQztZQUNHLDZCQUE2QjtZQUM3QixJQUFJLElBQUksQ0FBQyxlQUFlLEVBQUMsQ0FBQztnQkFDdEIsMERBQTBEO2dCQUMxRCxJQUFJLENBQUMsZ0JBQWdCLENBQUMsSUFBSSxDQUFDLENBQUM7Z0JBQzVCLElBQUksQ0FBQyw2QkFBNkIsR0FBRyxNQUFNLENBQUMsV0FBVyxDQUFDLEdBQUcsRUFBRSxDQUFDLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxLQUFLLENBQUMsRUFBRSxJQUFJLENBQUMsZUFBZSxDQUFDLENBQUM7WUFDdEgsQ0FBQztpQkFFRCxDQUFDO2dCQUNHLDhHQUE4RztnQkFDOUcsSUFBSSxDQUFDLGdCQUFnQixDQUFDLElBQUksQ0FBQyxDQUFDO1lBQ2hDLENBQUM7UUFDTCxDQUFDO0lBQ0wsQ0FBQztJQUVELG9DQUFvQztJQUM1QixLQUFLLENBQUMsOEJBQThCO1FBRXhDLElBQUksSUFBSSxDQUFDLDJCQUEyQixJQUFJLENBQUMsY0FBYyxJQUFJLE1BQU0sQ0FBQyxFQUNsRSxDQUFDO1lBQ0csSUFBSSxNQUFNLFlBQVksQ0FBQyxpQkFBaUIsRUFBRSxLQUFLLFNBQVMsRUFDeEQsQ0FBQztnQkFDRyxJQUFJLENBQUMsZ0NBQWdDLEdBQUcsSUFBSSxDQUFDO1lBQ2pELENBQUM7UUFDTCxDQUFDO0lBQ0wsQ0FBQztJQUVELDJCQUEyQjtJQUNuQixxQkFBcUI7UUFFekIsSUFBSSxDQUFDLElBQUksQ0FBQyxZQUFZLEVBQ3RCLENBQUM7WUFDRyxJQUFJLENBQUMsWUFBWSxHQUFHO2dCQUNoQixrQkFBa0IsRUFBRSxJQUFJLENBQUMsa0JBQWtCO2dCQUMzQyxpQkFBaUIsRUFBRSxJQUFJLENBQUMsaUJBQWlCO2dCQUN6QyxLQUFLLEVBQUUsSUFBSSxDQUFDLEtBQUs7Z0JBQ2pCLGlCQUFpQixFQUFFLElBQUksQ0FBQyxpQkFBaUI7Z0JBQ3pDLHdCQUF3QixFQUFFLElBQUksQ0FBQyx3QkFBd0I7Z0JBQ3ZELDZCQUE2QixFQUFFLHFCQUFxQjthQUN2RCxDQUFDO1FBQ04sQ0FBQztJQUNMLENBQUM7SUFFTyxlQUFlO1FBRW5CLElBQUksSUFBSSxDQUFDLFdBQVcsRUFDcEIsQ0FBQztZQUNHLElBQUksQ0FBQyxLQUFLLEdBQUcsS0FBSyxDQUFDLE1BQU0sQ0FBQztRQUM5QixDQUFDO2FBQ0ksSUFBSSxJQUFJLENBQUMsS0FBSyxJQUFJLEtBQUssQ0FBQyxLQUFLLElBQUksSUFBSSxDQUFDLEtBQUssSUFBSSxLQUFLLENBQUMsSUFBSSxFQUM5RCxDQUFDO1lBQ0csNkZBQTZGO1lBQzdGLE1BQU0sSUFBSSxLQUFLLENBQUMsNkNBQTZDLElBQUksQ0FBQyxLQUFLLCtCQUErQixDQUFDLENBQUM7UUFDNUcsQ0FBQztJQUNMLENBQUM7SUFFRCwyQ0FBMkM7SUFDbkMsZ0JBQWdCLENBQUMsZUFBd0I7UUFFN0MsSUFBSSxDQUFDLE9BQU8sQ0FBQyxXQUFXLEVBQUU7YUFDekIsSUFBSSxDQUNELEdBQUcsQ0FBQyxDQUFDLG9CQUEyQyxFQUFFLEVBQUU7WUFDaEQsSUFBSSxDQUFDLG9CQUFvQixHQUFHLG9CQUFvQixDQUFDO1lBRWpELElBQUksQ0FBQyxZQUFZLEdBQUcsb0JBQW9CLENBQUMsR0FBRyxDQUFDLENBQUMsUUFBNkIsRUFBRSxFQUFFO2dCQUMzRSxPQUFPLFFBQVEsQ0FBQyxXQUFXLENBQUM7WUFDaEMsQ0FBQyxDQUFDLENBQUM7UUFDUCxDQUFDLENBQUMsQ0FDTCxDQUFDLFNBQVMsQ0FBQyxHQUFHLEVBQUU7WUFDYixJQUFJLGVBQWUsRUFDbkIsQ0FBQztnQkFDRyxJQUFJLENBQUMsbUJBQW1CLEVBQUUsQ0FBQztZQUMvQixDQUFDO1FBQ0wsQ0FBQyxDQUFDLENBQUM7SUFDUCxDQUFDO0lBRUQsbUJBQW1CLENBQUMsTUFBYztRQUM5QixzR0FBc0c7UUFDdEcsSUFBSSxJQUFJLENBQUMsT0FBTyxZQUFZLHVCQUF1QixFQUNuRCxDQUFDO1lBQ0csTUFBTSxDQUFDLGdCQUFnQixHQUFHLElBQUksQ0FBQztZQUUvQixJQUFJLENBQUMsT0FBTyxDQUFDLHVCQUF1QixDQUFDLE1BQU0sQ0FBQyxXQUFXLENBQUMsRUFBRSxFQUFFLElBQUksQ0FBQyxlQUFlLEVBQUUsRUFBRSxNQUFNLENBQUMsV0FBVyxDQUFDO2lCQUN0RyxJQUFJLENBQ0QsR0FBRyxDQUFDLENBQUMsTUFBaUIsRUFBRSxFQUFFO2dCQUN0QixNQUFNLENBQUMsT0FBTyxDQUFDLENBQUMsT0FBTyxFQUFFLEVBQUUsQ0FBQyxJQUFJLENBQUMsaUJBQWlCLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQztnQkFFN0QsTUFBTSxDQUFDLFFBQVEsR0FBRyxNQUFNLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxRQUFRLENBQUMsQ0FBQztnQkFDakQsTUFBTSxDQUFDLGdCQUFnQixHQUFHLEtBQUssQ0FBQztnQkFFaEMsTUFBTSxTQUFTLEdBQW9CLENBQUMsTUFBTSxDQUFDLFdBQVcsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsZUFBZSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsZUFBZSxDQUFDLEdBQUcsQ0FBQztnQkFDNUcsTUFBTSxDQUFDLGVBQWUsR0FBRyxNQUFNLENBQUMsTUFBTSxJQUFJLElBQUksQ0FBQyxlQUFlLENBQUM7Z0JBRS9ELFVBQVUsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxJQUFJLENBQUMsMkJBQTJCLENBQUMsTUFBTSxFQUFFLE1BQU0sRUFBRSxTQUFTLEVBQUUsSUFBSSxDQUFDLENBQUMsQ0FBQztZQUN4RixDQUFDLENBQUMsQ0FDTCxDQUFDLFNBQVMsRUFBRSxDQUFDO1FBQ2xCLENBQUM7YUFFRCxDQUFDO1lBQ0csSUFBSSxDQUFDLE9BQU8sQ0FBQyxpQkFBaUIsQ0FBQyxNQUFNLENBQUMsV0FBVyxDQUFDLEVBQUUsQ0FBQztpQkFDcEQsSUFBSSxDQUNELEdBQUcsQ0FBQyxDQUFDLE1BQWlCLEVBQUUsRUFBRTtnQkFDdEIsTUFBTSxDQUFDLE9BQU8sQ0FBQyxDQUFDLE9BQU8sRUFBRSxFQUFFLENBQUMsSUFBSSxDQUFDLGlCQUFpQixDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUM7Z0JBRTdELE1BQU0sQ0FBQyxRQUFRLEdBQUcsTUFBTSxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDLENBQUM7Z0JBQ2pELE1BQU0sQ0FBQyxnQkFBZ0IsR0FBRyxLQUFLLENBQUM7Z0JBRWhDLFVBQVUsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxJQUFJLENBQUMsMkJBQTJCLENBQUMsTUFBTSxFQUFFLE1BQU0sRUFBRSxlQUFlLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQztZQUMvRixDQUFDLENBQUMsQ0FDTCxDQUFDLFNBQVMsRUFBRSxDQUFDO1FBQ2xCLENBQUM7SUFDTCxDQUFDO0lBRU8sMkJBQTJCLENBQUMsUUFBbUIsRUFBRSxNQUFjLEVBQUUsU0FBMEIsRUFBRSwwQkFBbUMsS0FBSztRQUV6SSxJQUFJLENBQUMsZ0JBQWdCLENBQUMsTUFBTSxFQUFFLFNBQVMsQ0FBQyxDQUFBO1FBRXhDLElBQUksTUFBTSxDQUFDLFFBQVEsSUFBSSx1QkFBdUIsRUFDOUMsQ0FBQztZQUNHLE1BQU0sY0FBYyxHQUFHLFFBQVEsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxRQUFRLENBQUMsQ0FBQztZQUV6RCxJQUFJLENBQUMsa0JBQWtCLENBQUMsY0FBYyxDQUFDLENBQUM7UUFDNUMsQ0FBQztJQUNMLENBQUM7SUFFRCxpREFBaUQ7SUFDekMsb0JBQW9CLENBQUMsb0JBQTJDO1FBRXBFLElBQUksb0JBQW9CLEVBQ3hCLENBQUM7WUFDRyxJQUFJLENBQUMsb0JBQW9CLEdBQUcsb0JBQW9CLENBQUM7WUFFakQsSUFBSSxDQUFDLFlBQVksR0FBRyxvQkFBb0IsQ0FBQyxHQUFHLENBQUMsQ0FBQyxRQUE2QixFQUFFLEVBQUU7Z0JBQzNFLE9BQU8sUUFBUSxDQUFDLFdBQVcsQ0FBQztZQUNoQyxDQUFDLENBQUMsQ0FBQztZQUVILElBQUksQ0FBQywwQkFBMEIsR0FBRyxFQUFFLENBQUM7UUFDekMsQ0FBQztJQUNMLENBQUM7SUFFRCwyQ0FBMkM7SUFDbkMsaUJBQWlCLENBQUMsV0FBNkIsRUFBRSxPQUFnQjtRQUVyRSxJQUFJLFdBQVcsSUFBSSxPQUFPLEVBQzFCLENBQUM7WUFDRyxNQUFNLFVBQVUsR0FBRyxJQUFJLENBQUMsY0FBYyxDQUFDLFdBQVcsQ0FBQyxDQUFDO1lBRXBELElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxPQUFPLENBQUMsQ0FBQztZQUVoQyxJQUFJLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLGNBQWMsRUFBQyxDQUFDO2dCQUN4QyxVQUFVLENBQUMsQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQztnQkFFckMsSUFBSSxDQUFDLGdCQUFnQixDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUMsRUFBRSxlQUFlLENBQUMsTUFBTSxDQUFDLENBQUM7Z0JBRTdELElBQUksVUFBVSxDQUFDLENBQUMsQ0FBQyxDQUFDLFFBQVEsRUFDMUIsQ0FBQztvQkFDRyxJQUFJLENBQUMsa0JBQWtCLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDO2dCQUN2QyxDQUFDO1lBQ0wsQ0FBQztZQUVELElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztZQUVyQyxnS0FBZ0s7WUFDaEssSUFBSSxJQUFJLENBQUMsMEJBQTBCLElBQUksQ0FBQyxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxXQUFXLENBQUMsRUFDckYsQ0FBQztnQkFDRyxvSEFBb0g7Z0JBQ3BILElBQUksQ0FBQyx1QkFBdUIsQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDLEVBQUUsT0FBTyxDQUFDLENBQUM7WUFDekQsQ0FBQztRQUNMLENBQUM7SUFDTCxDQUFDO0lBRUQsbUNBQW1DLENBQUMsV0FBNkI7UUFDN0QsSUFBSSxDQUFDLGNBQWMsQ0FBQyxXQUFXLEVBQUUsSUFBSSxFQUFFLElBQUksQ0FBQyxDQUFDO0lBQ2pELENBQUM7SUFFTyxrQkFBa0I7UUFDdEIsSUFBSSxJQUFJLENBQUMsbUJBQW1CLEVBQzVCLENBQUM7WUFDRyxJQUFJLENBQUMsbUJBQW1CLENBQUMsUUFBUSxHQUFHLEtBQUssQ0FBQztZQUMxQyxJQUFJLENBQUMsbUJBQW1CLEdBQUcsSUFBSSxDQUFDO1FBQ3BDLENBQUM7SUFDTCxDQUFDO0lBRUQsc0JBQXNCO1FBQ2xCLElBQUksQ0FBQyxrQkFBa0IsRUFBRSxDQUFDO0lBQzlCLENBQUM7SUFFRCx1QkFBdUIsQ0FBQyxLQUFVO1FBQzlCLGlJQUFpSTtRQUNqSSxJQUFJLENBQUMsZUFBZSxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBRTVCLDBCQUEwQjtRQUMxQixJQUFJLENBQUMsa0JBQWtCLEVBQUUsQ0FBQztJQUM5QixDQUFDO0lBRU8sZUFBZSxDQUFDLEtBQWE7UUFDakMsTUFBTSxRQUFRLEdBQUcsSUFBSSxLQUFLLENBQUMsS0FBSyxDQUFDLENBQUM7UUFFbEMsSUFBSSxDQUFDLGNBQWMsQ0FBQyxRQUFRLENBQUMsQ0FBQztRQUU5QixJQUFJLElBQUksQ0FBQyxZQUFZLEVBQ3JCLENBQUM7WUFDRyxJQUFJLENBQUMsWUFBWSxDQUFDLFlBQVksQ0FBQyxRQUFRLENBQUMsQ0FBQztRQUM3QyxDQUFDO0lBQ0wsQ0FBQztJQUVELDZEQUE2RDtJQUM3RCw2REFBNkQ7SUFDN0QsdUdBQXVHO0lBQy9GLGNBQWMsQ0FBQyxXQUE2QixFQUFFLG1CQUE0QixLQUFLLEVBQUUscUJBQThCLEtBQUs7UUFFeEgseUJBQXlCO1FBQ3pCLE1BQU0sWUFBWSxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLFdBQVcsQ0FBQyxFQUFFLElBQUksV0FBVyxDQUFDLEVBQUUsQ0FBQyxDQUFDO1FBRWhGLElBQUksQ0FBQyxZQUFZLEVBQ2pCLENBQUM7WUFDRyxJQUFJLGtCQUFrQixFQUN0QixDQUFDO2dCQUNHLElBQUksQ0FBQyxvQkFBb0IsQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLENBQUM7WUFDaEQsQ0FBQztZQUVELCtCQUErQjtZQUMvQixNQUFNLGNBQWMsR0FBRyxrQkFBa0IsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQywwQkFBMEIsQ0FBQztZQUVyRixNQUFNLGFBQWEsR0FBVyxJQUFJLE1BQU0sQ0FBQyxXQUFXLEVBQUUsSUFBSSxDQUFDLGNBQWMsRUFBRSxjQUFjLENBQUMsQ0FBQztZQUUzRixnREFBZ0Q7WUFDaEQsSUFBSSxJQUFJLENBQUMsY0FBYyxFQUN2QixDQUFDO2dCQUNHLElBQUksQ0FBQyxtQkFBbUIsQ0FBQyxhQUFhLENBQUMsQ0FBQztZQUM1QyxDQUFDO1lBRUQsSUFBSSxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsYUFBYSxDQUFDLENBQUM7WUFFcEMsdUdBQXVHO1lBQ3ZHLElBQUksQ0FBQyxJQUFJLENBQUMseUJBQXlCLEVBQUUsQ0FBQztnQkFDbEMsSUFBSSxJQUFJLENBQUMsT0FBTyxDQUFDLE1BQU0sR0FBRyxJQUFJLENBQUMsZ0JBQWdCLElBQUksSUFBSSxDQUFDLGlCQUFpQixHQUFHLENBQUMsQ0FBQyxJQUFJLENBQUMsZUFBZSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsZ0JBQWdCLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUM7b0JBQzlILElBQUksQ0FBQyxPQUFPLENBQUMsR0FBRyxFQUFFLENBQUM7Z0JBQ3ZCLENBQUM7WUFDTCxDQUFDO1lBRUQsSUFBSSxDQUFDLGtCQUFrQixDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQztZQUV0QyxJQUFJLGdCQUFnQixJQUFJLENBQUMsY0FBYyxFQUN2QyxDQUFDO2dCQUNHLElBQUksQ0FBQyxhQUFhLENBQUMsYUFBYSxDQUFDLENBQUM7WUFDdEMsQ0FBQztZQUVELElBQUksQ0FBQywwQkFBMEIsQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLENBQUM7WUFDbEQsSUFBSSxDQUFDLHVCQUF1QixDQUFDLElBQUksQ0FBQyxXQUFXLENBQUMsQ0FBQztZQUUvQyxPQUFPLENBQUMsYUFBYSxFQUFFLElBQUksQ0FBQyxDQUFDO1FBQ2pDLENBQUM7YUFFRCxDQUFDO1lBQ0csbUNBQW1DO1lBQ25DLE9BQU8sQ0FBQyxZQUFZLEVBQUUsS0FBSyxDQUFDLENBQUM7UUFDakMsQ0FBQztJQUNMLENBQUM7SUFFRCxvREFBb0Q7SUFDNUMsYUFBYSxDQUFDLE1BQWMsRUFBRSxXQUFxQixHQUFHLEVBQUUsR0FBRSxDQUFDO1FBRS9ELE1BQU0sV0FBVyxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBQ2pELElBQUksV0FBVyxJQUFJLENBQUMsRUFDcEIsQ0FBQztZQUNHLFVBQVUsQ0FBQyxHQUFHLEVBQUU7Z0JBQ1osSUFBSSxJQUFJLENBQUMsV0FBVyxFQUNwQixDQUFDO29CQUNHLE1BQU0saUJBQWlCLEdBQUcsSUFBSSxDQUFDLFdBQVcsQ0FBQyxPQUFPLEVBQUUsQ0FBQyxXQUFXLENBQUMsQ0FBQztvQkFFbEUsaUJBQWlCLENBQUMsZUFBZSxDQUFDLGFBQWEsQ0FBQyxLQUFLLEVBQUUsQ0FBQztnQkFDNUQsQ0FBQztnQkFFRCxRQUFRLEVBQUUsQ0FBQztZQUNmLENBQUMsQ0FBQyxDQUFDO1FBQ1AsQ0FBQztJQUNMLENBQUM7SUFFTyxpQkFBaUIsQ0FBQyxPQUFnQjtRQUN0QyxnRUFBZ0U7UUFDaEUsSUFBSSxDQUFDLE9BQU8sQ0FBQyxJQUFJLEVBQ2pCLENBQUM7WUFDRyxPQUFPLENBQUMsSUFBSSxHQUFHLFdBQVcsQ0FBQyxJQUFJLENBQUM7UUFDcEMsQ0FBQztJQUNMLENBQUM7SUFFRCw2REFBNkQ7SUFDN0Qsa0JBQWtCLENBQUMsUUFBbUI7UUFFbEMsTUFBTSxXQUFXLEdBQUcsSUFBSSxJQUFJLEVBQUUsQ0FBQztRQUUvQixRQUFRLENBQUMsT0FBTyxDQUFDLENBQUMsR0FBRyxFQUFDLEVBQUU7WUFDcEIsR0FBRyxDQUFDLFFBQVEsR0FBRyxXQUFXLENBQUM7UUFDL0IsQ0FBQyxDQUFDLENBQUM7UUFFSCxJQUFJLENBQUMsY0FBYyxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQztJQUN2QyxDQUFDO0lBRUQscURBQXFEO0lBQzdDLGVBQWU7UUFDbkIsSUFBSSxJQUFJLENBQUMsV0FBVyxJQUFJLElBQUksQ0FBQyxXQUFXLENBQUMsTUFBTSxHQUFHLENBQUMsRUFDbkQsQ0FBQztZQUNHLElBQUksQ0FBQyxTQUFTLEdBQUcsSUFBSSxLQUFLLEVBQUUsQ0FBQztZQUM3QixJQUFJLENBQUMsU0FBUyxDQUFDLEdBQUcsR0FBRyxJQUFJLENBQUMsV0FBVyxDQUFDO1lBQ3RDLElBQUksQ0FBQyxTQUFTLENBQUMsSUFBSSxFQUFFLENBQUM7UUFDMUIsQ0FBQztJQUNMLENBQUM7SUFFRCw2RUFBNkU7SUFDckUsZ0JBQWdCLENBQUMsTUFBYztRQUVuQyxJQUFJLElBQUksQ0FBQyxZQUFZLElBQUksQ0FBQyxNQUFNLENBQUMsUUFBUSxJQUFJLElBQUksQ0FBQyxTQUFTLEVBQUUsQ0FBQztZQUMxRCxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksRUFBRSxDQUFDO1FBQzFCLENBQUM7SUFDTCxDQUFDO0lBRUQsK0JBQStCO0lBQ3ZCLHVCQUF1QixDQUFDLE1BQWMsRUFBRSxPQUFnQjtRQUU1RCw4RUFBOEU7UUFDOUUsSUFBSSxJQUFJLENBQUMsZ0NBQWdDLElBQUksT0FBTyxFQUFFLENBQUM7WUFDbkQsTUFBTSxZQUFZLEdBQUcsSUFBSSxZQUFZLENBQUMsR0FBRyxJQUFJLENBQUMsWUFBWSxDQUFDLHdCQUF3QixJQUFJLE1BQU0sQ0FBQyxXQUFXLENBQUMsV0FBVyxFQUFFLEVBQUU7Z0JBQ3JILE1BQU0sRUFBRSxPQUFPLENBQUMsT0FBTztnQkFDdkIsTUFBTSxFQUFFLElBQUksQ0FBQyw2QkFBNkI7YUFDN0MsQ0FBQyxDQUFDO1lBRUgsVUFBVSxDQUFDLEdBQUcsRUFBRTtnQkFDWixZQUFZLENBQUMsS0FBSyxFQUFFLENBQUM7WUFDekIsQ0FBQyxFQUFFLE9BQU8sQ0FBQyxPQUFPLENBQUMsTUFBTSxJQUFJLEVBQUUsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLG9DQUFvQztRQUN4RixDQUFDO0lBQ0wsQ0FBQztJQUVELDJFQUEyRTtJQUNuRSxrQkFBa0IsQ0FBQyxPQUFpQjtRQUV4QyxJQUFJLElBQUksQ0FBQyxtQkFBbUIsRUFDNUIsQ0FBQztZQUNHLE1BQU0sY0FBYyxHQUFHLE9BQU8sQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRTtnQkFDckMsT0FBTyxDQUFDLENBQUMsV0FBVyxDQUFDLEVBQUUsQ0FBQztZQUM1QixDQUFDLENBQUMsQ0FBQztZQUVILFlBQVksQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLGVBQWUsRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLGNBQWMsQ0FBQyxDQUFDLENBQUM7UUFDL0UsQ0FBQztJQUNMLENBQUM7SUFFTyxtQkFBbUI7UUFFdkIsSUFDQSxDQUFDO1lBQ0csSUFBSSxJQUFJLENBQUMsbUJBQW1CLEVBQzVCLENBQUM7Z0JBQ0csTUFBTSx3QkFBd0IsR0FBRyxZQUFZLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxlQUFlLENBQUMsQ0FBQztnQkFFNUUsSUFBSSx3QkFBd0IsSUFBSSx3QkFBd0IsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxFQUNuRSxDQUFDO29CQUNHLE1BQU0sY0FBYyxHQUFhLElBQUksQ0FBQyxLQUFLLENBQUMsd0JBQXdCLENBQUMsQ0FBQztvQkFFdEUsTUFBTSxxQkFBcUIsR0FBRyxJQUFJLENBQUMsWUFBWSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLGNBQWMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDO29CQUUvRixxQkFBcUIsQ0FBQyxPQUFPLENBQUMsQ0FBQyxXQUFXLEVBQUUsRUFBRTt3QkFDMUMsSUFBSSxDQUFDLGNBQWMsQ0FBQyxXQUFXLENBQUMsQ0FBQztvQkFDckMsQ0FBQyxDQUFDLENBQUM7Z0JBQ1AsQ0FBQztZQUNMLENBQUM7UUFDTCxDQUFDO1FBQ0QsT0FBTyxFQUFFLEVBQ1QsQ0FBQztZQUNHLE9BQU8sQ0FBQyxLQUFLLENBQUMscUVBQXFFLEVBQUUsRUFBRSxDQUFDLENBQUM7UUFDN0YsQ0FBQztJQUNMLENBQUM7SUFFRCwyRUFBMkU7SUFDbkUsZ0JBQWdCLENBQUMsTUFBYztRQUVuQyxNQUFNLEtBQUssR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUUzQyxJQUFJLEtBQUssR0FBRyxDQUFDLEVBQ2IsQ0FBQztZQUNHLE9BQU8sSUFBSSxDQUFDLE9BQU8sQ0FBQyxLQUFLLEdBQUcsQ0FBQyxDQUFDLENBQUM7UUFDbkMsQ0FBQzthQUNJLElBQUksS0FBSyxJQUFJLENBQUMsSUFBSSxJQUFJLENBQUMsT0FBTyxDQUFDLE1BQU0sR0FBRyxDQUFDLEVBQzlDLENBQUM7WUFDRyxPQUFPLElBQUksQ0FBQyxPQUFPLENBQUMsS0FBSyxHQUFHLENBQUMsQ0FBQyxDQUFDO1FBQ25DLENBQUM7SUFDTCxDQUFDO0lBRU8sV0FBVyxDQUFDLE1BQWM7UUFFOUIsTUFBTSxLQUFLLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLENBQUM7UUFFM0MsSUFBSSxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsS0FBSyxFQUFFLENBQUMsQ0FBQyxDQUFDO1FBRTlCLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLENBQUM7UUFFdEMsSUFBSSxDQUFDLHVCQUF1QixDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsV0FBVyxDQUFDLENBQUM7SUFDMUQsQ0FBQztJQUVPLDhCQUE4QixDQUFDLFlBQW9CO1FBQ3ZELE1BQU0sV0FBVyxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLFlBQVksQ0FBQyxDQUFDO1FBRXZELElBQUksSUFBSSxDQUFDLFdBQVcsRUFBQyxDQUFDO1lBQ2xCLElBQUksWUFBWSxHQUFHLElBQUksQ0FBQyxXQUFXLENBQUMsT0FBTyxFQUFFLENBQUMsV0FBVyxDQUFDLENBQUM7WUFFM0QsT0FBTyxZQUFZLENBQUM7UUFDeEIsQ0FBQztRQUVELE9BQU8sSUFBSSxDQUFDO0lBQ2hCLENBQUM7SUFFRCxtREFBbUQ7SUFDM0MsZ0JBQWdCLENBQUMsTUFBYyxFQUFFLFNBQTBCO1FBRS9ELE1BQU0sVUFBVSxHQUFHLElBQUksQ0FBQyw4QkFBOEIsQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUUvRCxJQUFJLFVBQVUsRUFBQyxDQUFDO1lBQ1osVUFBVSxDQUFDLGdCQUFnQixDQUFDLE1BQU0sRUFBRSxTQUFTLENBQUMsQ0FBQztRQUNuRCxDQUFDO0lBQ0wsQ0FBQztJQUVELG9CQUFvQixDQUFDLFlBQXVCO1FBQ3hDLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxZQUFZLENBQUMsQ0FBQztJQUMxQyxDQUFDO0lBRUQsa0JBQWtCLENBQUMsT0FBOEQ7UUFDN0UsTUFBTSxFQUFFLFlBQVksRUFBRSxrQkFBa0IsRUFBRSxHQUFHLE9BQU8sQ0FBQztRQUVyRCxJQUFJLGtCQUFrQixFQUFFLENBQUM7WUFDckIsSUFBSSxhQUFhLEdBQUcsSUFBSSxDQUFDLGdCQUFnQixDQUFDLFlBQVksQ0FBQyxDQUFDO1lBRXhELElBQUksYUFBYSxFQUNqQixDQUFDO2dCQUNHLElBQUksQ0FBQyxhQUFhLENBQUMsYUFBYSxFQUFFLEdBQUcsRUFBRSxHQUFHLElBQUksQ0FBQyxXQUFXLENBQUMsWUFBWSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztZQUNqRixDQUFDO2lCQUVELENBQUM7Z0JBQ0csSUFBSSxDQUFDLFdBQVcsQ0FBQyxZQUFZLENBQUMsQ0FBQztZQUNuQyxDQUFDO1FBQ0wsQ0FBQzthQUNJLENBQUM7WUFDRixJQUFJLENBQUMsV0FBVyxDQUFDLFlBQVksQ0FBQyxDQUFDO1FBQ25DLENBQUM7SUFDTCxDQUFDO0lBRUQsb0JBQW9CLENBQUMsT0FBK0Q7UUFDaEYsTUFBTSxFQUFFLGdCQUFnQixFQUFFLGVBQWUsRUFBRSxHQUFHLE9BQU8sQ0FBQztRQUV0RCxNQUFNLGtCQUFrQixHQUFHLElBQUksQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLGdCQUFnQixDQUFDLENBQUM7UUFDbEUsSUFBSSxhQUFhLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxrQkFBa0IsR0FBRyxDQUFDLGVBQWUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQywyQkFBMkI7UUFFOUcsSUFBSSxDQUFDLGFBQWEsRUFDbEIsQ0FBQztZQUNHLG1DQUFtQztZQUNuQyxhQUFhLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxrQkFBa0IsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFDLENBQUM7UUFDM0YsQ0FBQztRQUVELElBQUksQ0FBQyxhQUFhLENBQUMsYUFBYSxDQUFDLENBQUM7SUFDdEMsQ0FBQztJQUVELG1CQUFtQixDQUFDLFdBQW9CO1FBQ3BDLElBQUksQ0FBQyxPQUFPLENBQUMsV0FBVyxDQUFDLFdBQVcsQ0FBQyxDQUFDO0lBQzFDLENBQUM7SUFFRCx1QkFBdUIsQ0FBQyxNQUFtQjtRQUN2QyxJQUFJLENBQUMsbUJBQW1CLEdBQUcsTUFBTSxDQUFDO0lBQ3RDLENBQUM7SUFFRCxxQkFBcUIsQ0FBQyxJQUFVO1FBQzVCLElBQUksSUFBSSxFQUNSLENBQUM7WUFDRyxJQUFJLENBQUMsY0FBYyxDQUFDLElBQUksQ0FBQyxDQUFDO1FBQzlCLENBQUM7SUFDTCxDQUFDO0lBRUssc0JBQXNCLENBQUMsTUFBVztRQUNwQyxNQUFNLFlBQVksR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxXQUFXLENBQUMsRUFBRSxJQUFJLE1BQU0sQ0FBQyxDQUFDO1FBRXhFLElBQUksWUFBWSxFQUNoQixDQUFDO1lBQ0csSUFBSSxDQUFDLFdBQVcsQ0FBQyxZQUFZLENBQUMsQ0FBQztRQUNuQyxDQUFDO0lBQ0wsQ0FBQztJQUVELGlDQUFpQyxDQUFDLE1BQVc7UUFDekMsTUFBTSxZQUFZLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsV0FBVyxDQUFDLEVBQUUsSUFBSSxNQUFNLENBQUMsQ0FBQztRQUV4RSxJQUFJLFlBQVksRUFDaEIsQ0FBQztZQUNHLE1BQU0sVUFBVSxHQUFHLElBQUksQ0FBQyw4QkFBOEIsQ0FBQyxZQUFZLENBQUMsQ0FBQztZQUVyRSxJQUFJLFVBQVUsRUFBQyxDQUFDO2dCQUNaLFVBQVUsQ0FBQyxtQkFBbUIsQ0FBQyxZQUFZLENBQUMsQ0FBQztZQUNqRCxDQUFDO1FBQ0wsQ0FBQztJQUNMLENBQUM7SUFFRCxxQkFBcUI7SUFDckIsbURBQW1EO0lBQ25ELDREQUE0RDtJQUM1RCxJQUFJO0lBQ0osa0JBQWtCLENBQUMsS0FBYTtRQUU1QixJQUFJLENBQUMsb0JBQW9CLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFBO0lBSXpDLENBQUM7OEdBdndCUSxNQUFNO2tHQUFOLE1BQU0sdW5EQ3ZDbkIscXJFQTRDQTs7MkZETGEsTUFBTTtrQkFibEIsU0FBUzsrQkFDSSxVQUFVLGlCQVNMLGlCQUFpQixDQUFDLElBQUk7K0VBa0JqQyxVQUFVO3NCQURiLEtBQUs7Z0JBZUMsT0FBTztzQkFEYixLQUFLO2dCQUlDLFlBQVk7c0JBRGxCLEtBQUs7Z0JBSUMsTUFBTTtzQkFEWixLQUFLO2dCQUlDLFdBQVc7c0JBRGpCLEtBQUs7Z0JBSUMsMEJBQTBCO3NCQURoQyxLQUFLO2dCQUlDLGVBQWU7c0JBRHJCLEtBQUs7Z0JBSUMsZUFBZTtzQkFEckIsS0FBSztnQkFJQyxjQUFjO3NCQURwQixLQUFLO2dCQUlDLGFBQWE7c0JBRG5CLEtBQUs7Z0JBSUMsYUFBYTtzQkFEbkIsS0FBSztnQkFJQyxZQUFZO3NCQURsQixLQUFLO2dCQUlDLGFBQWE7c0JBRG5CLEtBQUs7Z0JBSUMsV0FBVztzQkFEakIsS0FBSztnQkFJQyxtQkFBbUI7c0JBRHpCLEtBQUs7Z0JBSUMsS0FBSztzQkFEWCxLQUFLO2dCQUlDLGtCQUFrQjtzQkFEeEIsS0FBSztnQkFJQyxpQkFBaUI7c0JBRHZCLEtBQUs7Z0JBSUMsMkJBQTJCO3NCQURqQyxLQUFLO2dCQUlDLDZCQUE2QjtzQkFEbkMsS0FBSztnQkFJQyx3QkFBd0I7c0JBRDlCLEtBQUs7Z0JBSUMsZUFBZTtzQkFEckIsS0FBSztnQkFJQyxZQUFZO3NCQURsQixLQUFLO2dCQUlDLGVBQWU7c0JBRHJCLEtBQUs7Z0JBSUMsb0NBQW9DO3NCQUQxQyxLQUFLO2dCQUlDLGFBQWE7c0JBRG5CLEtBQUs7Z0JBSUMsS0FBSztzQkFEWCxLQUFLO2dCQUlDLFdBQVc7c0JBRGpCLEtBQUs7Z0JBSUMscUJBQXFCO3NCQUQzQixLQUFLO2dCQUlDLGVBQWU7c0JBRHJCLEtBQUs7Z0JBSUMseUJBQXlCO3NCQUQvQixLQUFLO2dCQUlDLGlCQUFpQjtzQkFEdkIsS0FBSztnQkFJQyxvQkFBb0I7c0JBRDFCLE1BQU07Z0JBSUEsdUJBQXVCO3NCQUQ3QixNQUFNO2dCQUlBLHVCQUF1QjtzQkFEN0IsTUFBTTtnQkFJQSxjQUFjO3NCQURwQixNQUFNO2dCQUlBLG9CQUFvQjtzQkFEMUIsTUFBTTtnQkErQ3FCLFdBQVc7c0JBQXRDLFlBQVk7dUJBQUMsWUFBWTtnQkFPMUIsUUFBUTtzQkFEUCxZQUFZO3VCQUFDLGVBQWUsRUFBRSxDQUFDLFFBQVEsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qIGVzbGludC1kaXNhYmxlICovXG5pbXBvcnQgeyBDb21wb25lbnQsIElucHV0LCBPbkluaXQsIFZpZXdDaGlsZHJlbiwgUXVlcnlMaXN0LCBIb3N0TGlzdGVuZXIsIE91dHB1dCwgRXZlbnRFbWl0dGVyLCBWaWV3RW5jYXBzdWxhdGlvbiB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgSHR0cENsaWVudCB9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbi9odHRwJztcbmltcG9ydCB7IENoYXRBZGFwdGVyIH0gZnJvbSAnLi4vLi4vY29yZS9jaGF0LWFkYXB0ZXInO1xuaW1wb3J0IHsgSUNoYXRHcm91cEFkYXB0ZXIgfSBmcm9tICcuLi8uLi9jb3JlL2NoYXQtZ3JvdXAtYWRhcHRlcic7XG5pbXBvcnQgeyBVc2VyIH0gZnJvbSBcIi4uLy4uL2NvcmUvdXNlclwiO1xuaW1wb3J0IHsgUGFydGljaXBhbnRSZXNwb25zZSB9IGZyb20gXCIuLi8uLi9jb3JlL3BhcnRpY2lwYW50LXJlc3BvbnNlXCI7XG5pbXBvcnQgeyBNZXNzYWdlIH0gZnJvbSBcIi4uLy4uL2NvcmUvbWVzc2FnZVwiO1xuaW1wb3J0IHsgTWVzc2FnZVR5cGUgfSBmcm9tIFwiLi4vLi4vY29yZS9tZXNzYWdlLXR5cGUuZW51bVwiO1xuaW1wb3J0IHsgV2luZG93IH0gZnJvbSBcIi4uLy4uL2NvcmUvd2luZG93XCI7XG5pbXBvcnQgeyBDaGF0UGFydGljaXBhbnRTdGF0dXMgfSBmcm9tIFwiLi4vLi4vY29yZS9jaGF0LXBhcnRpY2lwYW50LXN0YXR1cy5lbnVtXCI7XG5pbXBvcnQgeyBTY3JvbGxEaXJlY3Rpb24gfSBmcm9tIFwiLi4vLi4vY29yZS9zY3JvbGwtZGlyZWN0aW9uLmVudW1cIjtcbmltcG9ydCB7IExvY2FsaXphdGlvbiwgU3RhdHVzRGVzY3JpcHRpb24gfSBmcm9tICcuLi8uLi9jb3JlL2xvY2FsaXphdGlvbic7XG5pbXBvcnQgeyBJQ2hhdENvbnRyb2xsZXIgfSBmcm9tICcuLi8uLi9jb3JlL2NoYXQtY29udHJvbGxlcic7XG5pbXBvcnQgeyBQYWdlZEhpc3RvcnlDaGF0QWRhcHRlciB9IGZyb20gJy4uLy4uL2NvcmUvcGFnZWQtaGlzdG9yeS1jaGF0LWFkYXB0ZXInO1xuaW1wb3J0IHsgSUZpbGVVcGxvYWRBZGFwdGVyIH0gZnJvbSAnLi4vLi4vY29yZS9maWxlLXVwbG9hZC1hZGFwdGVyJztcbmltcG9ydCB7IERlZmF1bHRGaWxlVXBsb2FkQWRhcHRlciB9IGZyb20gJy4uLy4uL2NvcmUvZGVmYXVsdC1maWxlLXVwbG9hZC1hZGFwdGVyJztcbmltcG9ydCB7IFRoZW1lIH0gZnJvbSAnLi4vLi4vY29yZS90aGVtZS5lbnVtJztcbmltcG9ydCB7IElDaGF0T3B0aW9uIH0gZnJvbSAnLi4vLi4vY29yZS9jaGF0LW9wdGlvbic7XG5pbXBvcnQgeyBHcm91cCB9IGZyb20gXCIuLi8uLi9jb3JlL2dyb3VwXCI7XG5pbXBvcnQgeyBDaGF0UGFydGljaXBhbnRUeXBlIH0gZnJvbSBcIi4uLy4uL2NvcmUvY2hhdC1wYXJ0aWNpcGFudC10eXBlLmVudW1cIjtcbmltcG9ydCB7IElDaGF0UGFydGljaXBhbnQgfSBmcm9tIFwiLi4vLi4vY29yZS9jaGF0LXBhcnRpY2lwYW50XCI7XG5pbXBvcnQgeyBtYXAgfSBmcm9tICdyeGpzL29wZXJhdG9ycyc7XG5pbXBvcnQgeyBOZ0NoYXRXaW5kb3dDb21wb25lbnQgfSBmcm9tICcuLi9uZy1jaGF0LXdpbmRvdy9uZy1jaGF0LXdpbmRvdy5jb21wb25lbnQnO1xuXG5cbkBDb21wb25lbnQoe1xuICAgIHNlbGVjdG9yOiAnbW5sLWNoYXQnLFxuICAgIHRlbXBsYXRlVXJsOiAnbmctY2hhdC5jb21wb25lbnQuaHRtbCcsXG4gICAgc3R5bGVVcmxzOiBbXG4gICAgICAgICcuLi8uLi8uLi9hc3NldHMvaWNvbnMuY3NzJyxcbiAgICAgICAgJy4uLy4uLy4uL2Fzc2V0cy9sb2FkaW5nLXNwaW5uZXIuY3NzJyxcbiAgICAgICAgJy4uLy4uLy4uL2Fzc2V0cy9uZy1jaGF0LmNvbXBvbmVudC5kZWZhdWx0LmNzcycsXG4gICAgICAgICcuLi8uLi8uLi9hc3NldHMvdGhlbWVzL25nLWNoYXQudGhlbWUuZGVmYXVsdC5zY3NzJyxcbiAgICAgICAgJy4uLy4uLy4uL2Fzc2V0cy90aGVtZXMvbmctY2hhdC50aGVtZS5kYXJrLnNjc3MnXG4gICAgXSxcbiAgICBlbmNhcHN1bGF0aW9uOiBWaWV3RW5jYXBzdWxhdGlvbi5Ob25lXG59KVxuXG5leHBvcnQgY2xhc3MgTmdDaGF0IGltcGxlbWVudHMgT25Jbml0LCBJQ2hhdENvbnRyb2xsZXIge1xuICAgIGNvbnN0cnVjdG9yKHByaXZhdGUgX2h0dHBDbGllbnQ6IEh0dHBDbGllbnQpIHsgfVxuXG4gICAgLy8gRXhwb3NlcyBlbnVtcyBmb3IgdGhlIG5nLXRlbXBsYXRlXG4gICAgcHVibGljIENoYXRQYXJ0aWNpcGFudFR5cGUgPSBDaGF0UGFydGljaXBhbnRUeXBlO1xuICAgIHB1YmxpYyBDaGF0UGFydGljaXBhbnRTdGF0dXMgPSBDaGF0UGFydGljaXBhbnRTdGF0dXM7XG4gICAgcHVibGljIE1lc3NhZ2VUeXBlID0gTWVzc2FnZVR5cGU7XG5cbiAgICBwcml2YXRlIF9pc0Rpc2FibGVkOiBib29sZWFuID0gZmFsc2U7XG5cbiAgICBnZXQgaXNEaXNhYmxlZCgpOiBib29sZWFuIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2lzRGlzYWJsZWQ7XG4gICAgfVxuXG4gICAgQElucHV0KClcbiAgICBzZXQgaXNEaXNhYmxlZCh2YWx1ZTogYm9vbGVhbikge1xuICAgICAgICB0aGlzLl9pc0Rpc2FibGVkID0gdmFsdWU7XG5cbiAgICAgICAgaWYgKHZhbHVlKVxuICAgICAgICB7XG4gICAgICAgICAgICB3aW5kb3cuY2xlYXJJbnRlcnZhbCh0aGlzLnBvbGxpbmdJbnRlcnZhbFdpbmRvd0luc3RhbmNlKVxuICAgICAgICB9XG4gICAgICAgIGVsc2VcbiAgICAgICAge1xuICAgICAgICAgICAgdGhpcy5hY3RpdmF0ZUZyaWVuZExpc3RGZXRjaCgpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgQElucHV0KClcbiAgICBwdWJsaWMgYWRhcHRlcjogQ2hhdEFkYXB0ZXI7XG5cbiAgICBASW5wdXQoKVxuICAgIHB1YmxpYyBncm91cEFkYXB0ZXI6IElDaGF0R3JvdXBBZGFwdGVyO1xuXG4gICAgQElucHV0KClcbiAgICBwdWJsaWMgdXNlcklkOiBhbnk7XG5cbiAgICBASW5wdXQoKVxuICAgIHB1YmxpYyBpc0NvbGxhcHNlZDogYm9vbGVhbiA9IGZhbHNlO1xuXG4gICAgQElucHV0KClcbiAgICBwdWJsaWMgbWF4aW1pemVXaW5kb3dPbk5ld01lc3NhZ2U6IGJvb2xlYW4gPSB0cnVlO1xuXG4gICAgQElucHV0KClcbiAgICBwdWJsaWMgcG9sbEZyaWVuZHNMaXN0OiBib29sZWFuID0gZmFsc2U7XG5cbiAgICBASW5wdXQoKVxuICAgIHB1YmxpYyBwb2xsaW5nSW50ZXJ2YWw6IG51bWJlciA9IDUwMDA7XG5cbiAgICBASW5wdXQoKVxuICAgIHB1YmxpYyBoaXN0b3J5RW5hYmxlZDogYm9vbGVhbiA9IHRydWU7XG5cbiAgICBASW5wdXQoKVxuICAgIHB1YmxpYyBlbW9qaXNFbmFibGVkOiBib29sZWFuID0gdHJ1ZTtcblxuICAgIEBJbnB1dCgpXG4gICAgcHVibGljIGxpbmtmeUVuYWJsZWQ6IGJvb2xlYW4gPSB0cnVlO1xuXG4gICAgQElucHV0KClcbiAgICBwdWJsaWMgYXVkaW9FbmFibGVkOiBib29sZWFuID0gdHJ1ZTtcblxuICAgIEBJbnB1dCgpXG4gICAgcHVibGljIHNlYXJjaEVuYWJsZWQ6IGJvb2xlYW4gPSB0cnVlO1xuXG4gICAgQElucHV0KCkgLy8gVE9ETzogVGhpcyBtaWdodCBuZWVkIGEgYmV0dGVyIGNvbnRlbnQgc3RyYXRlZ3lcbiAgICBwdWJsaWMgYXVkaW9Tb3VyY2U6IHN0cmluZyA9ICcuLi8uLi8uLi9hc3NldHMvbm90aWZpY2F0aW9uLndhdic7XG5cbiAgICBASW5wdXQoKVxuICAgIHB1YmxpYyBwZXJzaXN0V2luZG93c1N0YXRlOiBib29sZWFuID0gdHJ1ZTtcblxuICAgIEBJbnB1dCgpXG4gICAgcHVibGljIHRpdGxlOiBzdHJpbmcgPSBcIlF1aWNrIGNoYXRcIjtcblxuICAgIEBJbnB1dCgpXG4gICAgcHVibGljIG1lc3NhZ2VQbGFjZWhvbGRlcjogc3RyaW5nID0gXCJUeXBlIGEgbWVzc2FnZVwiO1xuXG4gICAgQElucHV0KClcbiAgICBwdWJsaWMgc2VhcmNoUGxhY2Vob2xkZXI6IHN0cmluZyA9IFwiU2VhcmNoXCI7XG5cbiAgICBASW5wdXQoKVxuICAgIHB1YmxpYyBicm93c2VyTm90aWZpY2F0aW9uc0VuYWJsZWQ6IGJvb2xlYW4gPSB0cnVlO1xuXG4gICAgQElucHV0KCkgLy8gVE9ETzogVGhpcyBtaWdodCBuZWVkIGEgYmV0dGVyIGNvbnRlbnQgc3RyYXRlZ3lcbiAgICBwdWJsaWMgYnJvd3Nlck5vdGlmaWNhdGlvbkljb25Tb3VyY2U6IHN0cmluZyA9ICcuLi8uLi8uLi9hc3NldHMvbm90aWZpY2F0aW9uLnBuZyc7XG5cbiAgICBASW5wdXQoKVxuICAgIHB1YmxpYyBicm93c2VyTm90aWZpY2F0aW9uVGl0bGU6IHN0cmluZyA9IFwiTmV3IG1lc3NhZ2UgZnJvbVwiO1xuXG4gICAgQElucHV0KClcbiAgICBwdWJsaWMgaGlzdG9yeVBhZ2VTaXplOiBudW1iZXIgPSAxMDtcblxuICAgIEBJbnB1dCgpXG4gICAgcHVibGljIGxvY2FsaXphdGlvbjogTG9jYWxpemF0aW9uO1xuXG4gICAgQElucHV0KClcbiAgICBwdWJsaWMgaGlkZUZyaWVuZHNMaXN0OiBib29sZWFuID0gZmFsc2U7XG5cbiAgICBASW5wdXQoKVxuICAgIHB1YmxpYyBoaWRlRnJpZW5kc0xpc3RPblVuc3VwcG9ydGVkVmlld3BvcnQ6IGJvb2xlYW4gPSB0cnVlO1xuXG4gICAgQElucHV0KClcbiAgICBwdWJsaWMgZmlsZVVwbG9hZFVybDogc3RyaW5nO1xuXG4gICAgQElucHV0KClcbiAgICBwdWJsaWMgdGhlbWU6IFRoZW1lID0gVGhlbWUuTGlnaHQ7XG5cbiAgICBASW5wdXQoKVxuICAgIHB1YmxpYyBjdXN0b21UaGVtZTogc3RyaW5nO1xuXG4gICAgQElucHV0KClcbiAgICBwdWJsaWMgbWVzc2FnZURhdGVQaXBlRm9ybWF0OiBzdHJpbmcgPSBcInNob3J0XCI7XG5cbiAgICBASW5wdXQoKVxuICAgIHB1YmxpYyBzaG93TWVzc2FnZURhdGU6IGJvb2xlYW4gPSB0cnVlO1xuXG4gICAgQElucHV0KClcbiAgICBwdWJsaWMgaXNWaWV3cG9ydE9uTW9iaWxlRW5hYmxlZDogYm9vbGVhbiA9IGZhbHNlO1xuXG4gICAgQElucHV0KClcbiAgICBwdWJsaWMgZmlsZVVwbG9hZEFkYXB0ZXI6IElGaWxlVXBsb2FkQWRhcHRlcjtcblxuICAgIEBPdXRwdXQoKVxuICAgIHB1YmxpYyBvblBhcnRpY2lwYW50Q2xpY2tlZDogRXZlbnRFbWl0dGVyPElDaGF0UGFydGljaXBhbnQ+ID0gbmV3IEV2ZW50RW1pdHRlcjxJQ2hhdFBhcnRpY2lwYW50PigpO1xuXG4gICAgQE91dHB1dCgpXG4gICAgcHVibGljIG9uUGFydGljaXBhbnRDaGF0T3BlbmVkOiBFdmVudEVtaXR0ZXI8SUNoYXRQYXJ0aWNpcGFudD4gPSBuZXcgRXZlbnRFbWl0dGVyPElDaGF0UGFydGljaXBhbnQ+KCk7XG5cbiAgICBAT3V0cHV0KClcbiAgICBwdWJsaWMgb25QYXJ0aWNpcGFudENoYXRDbG9zZWQ6IEV2ZW50RW1pdHRlcjxJQ2hhdFBhcnRpY2lwYW50PiA9IG5ldyBFdmVudEVtaXR0ZXI8SUNoYXRQYXJ0aWNpcGFudD4oKTtcblxuICAgIEBPdXRwdXQoKVxuICAgIHB1YmxpYyBvbk1lc3NhZ2VzU2VlbjogRXZlbnRFbWl0dGVyPE1lc3NhZ2VbXT4gPSBuZXcgRXZlbnRFbWl0dGVyPE1lc3NhZ2VbXT4oKTtcblxuICAgIEBPdXRwdXQoKVxuICAgIHB1YmxpYyBvbkNsb3NlV2luZG93Q2xpY2tlZDpFdmVudEVtaXR0ZXI8Ym9vbGVhbj4gPSBuZXcgRXZlbnRFbWl0dGVyPGJvb2xlYW4+KClcblxuICAgIHByaXZhdGUgYnJvd3Nlck5vdGlmaWNhdGlvbnNCb290c3RyYXBwZWQ6IGJvb2xlYW4gPSBmYWxzZTtcblxuICAgIHB1YmxpYyBoYXNQYWdlZEhpc3Rvcnk6IGJvb2xlYW4gPSBmYWxzZTtcblxuICAgIC8vIERvbid0IHdhbnQgdG8gYWRkIHRoaXMgYXMgYSBzZXR0aW5nIHRvIHNpbXBsaWZ5IHVzYWdlLiBQcmV2aW91cyBwbGFjZWhvbGRlciBhbmQgdGl0bGUgc2V0dGluZ3MgYXZhaWxhYmxlIHRvIGJlIHVzZWQsIG9yIHVzZSBmdWxsIExvY2FsaXphdGlvbiBvYmplY3QuXG4gICAgcHJpdmF0ZSBzdGF0dXNEZXNjcmlwdGlvbjogU3RhdHVzRGVzY3JpcHRpb24gPSB7XG4gICAgICAgIG9ubGluZTogJ09ubGluZScsXG4gICAgICAgIGJ1c3k6ICdCdXN5JyxcbiAgICAgICAgYXdheTogJ0F3YXknLFxuICAgICAgICBvZmZsaW5lOiAnT2ZmbGluZSdcbiAgICB9O1xuXG4gICAgcHJpdmF0ZSBhdWRpb0ZpbGU6IEhUTUxBdWRpb0VsZW1lbnQ7XG5cbiAgICBwdWJsaWMgcGFydGljaXBhbnRzOiBJQ2hhdFBhcnRpY2lwYW50W107XG5cbiAgICBwdWJsaWMgcGFydGljaXBhbnRzUmVzcG9uc2U6IFBhcnRpY2lwYW50UmVzcG9uc2VbXTtcblxuICAgIHB1YmxpYyBwYXJ0aWNpcGFudHNJbnRlcmFjdGVkV2l0aDogSUNoYXRQYXJ0aWNpcGFudFtdID0gW107XG5cbiAgICBwdWJsaWMgY3VycmVudEFjdGl2ZU9wdGlvbjogSUNoYXRPcHRpb24gfCBudWxsO1xuXG4gICAgcHJpdmF0ZSBwb2xsaW5nSW50ZXJ2YWxXaW5kb3dJbnN0YW5jZTogbnVtYmVyO1xuXG4gICAgcHJpdmF0ZSBnZXQgbG9jYWxTdG9yYWdlS2V5KCk6IHN0cmluZ1xuICAgIHtcbiAgICAgICAgcmV0dXJuIGBuZy1jaGF0LXVzZXJzLSR7dGhpcy51c2VySWR9YDsgLy8gQXBwZW5kaW5nIHRoZSB1c2VyIGlkIHNvIHRoZSBzdGF0ZSBpcyB1bmlxdWUgcGVyIHVzZXIgaW4gYSBjb21wdXRlci5cbiAgICB9O1xuXG4gICAgLy8gRGVmaW5lcyB0aGUgc2l6ZSBvZiBlYWNoIG9wZW5lZCB3aW5kb3cgdG8gY2FsY3VsYXRlIGhvdyBtYW55IHdpbmRvd3MgY2FuIGJlIG9wZW5lZCBvbiB0aGUgdmlld3BvcnQgYXQgdGhlIHNhbWUgdGltZS5cbiAgICBwdWJsaWMgd2luZG93U2l6ZUZhY3RvcjogbnVtYmVyID0gMzIwO1xuXG4gICAgLy8gVG90YWwgd2lkdGggc2l6ZSBvZiB0aGUgZnJpZW5kcyBsaXN0IHNlY3Rpb25cbiAgICBwdWJsaWMgZnJpZW5kc0xpc3RXaWR0aDogbnVtYmVyID0gMjYyO1xuXG4gICAgLy8gQXZhaWxhYmxlIGFyZWEgdG8gcmVuZGVyIHRoZSBwbHVnaW5cbiAgICBwcml2YXRlIHZpZXdQb3J0VG90YWxBcmVhOiBudW1iZXI7XG5cbiAgICAvLyBTZXQgdG8gdHJ1ZSBpZiB0aGVyZSBpcyBubyBzcGFjZSB0byBkaXNwbGF5IGF0IGxlYXN0IG9uZSBjaGF0IHdpbmRvdyBhbmQgJ2hpZGVGcmllbmRzTGlzdE9uVW5zdXBwb3J0ZWRWaWV3cG9ydCcgaXMgdHJ1ZVxuICAgIHB1YmxpYyB1bnN1cHBvcnRlZFZpZXdwb3J0OiBib29sZWFuID0gZmFsc2U7XG5cbiAgICB3aW5kb3dzOiBXaW5kb3dbXSA9IFtdO1xuICAgIGlzQm9vdHN0cmFwcGVkOiBib29sZWFuID0gZmFsc2U7XG5cbiAgICBAVmlld0NoaWxkcmVuKCdjaGF0V2luZG93JykgY2hhdFdpbmRvd3M6IFF1ZXJ5TGlzdDxOZ0NoYXRXaW5kb3dDb21wb25lbnQ+O1xuXG4gICAgbmdPbkluaXQoKSB7XG4gICAgICAgIHRoaXMuYm9vdHN0cmFwQ2hhdCgpO1xuICAgIH1cblxuICAgIEBIb3N0TGlzdGVuZXIoJ3dpbmRvdzpyZXNpemUnLCBbJyRldmVudCddKVxuICAgIG9uUmVzaXplKGV2ZW50OiBhbnkpe1xuICAgICAgIHRoaXMudmlld1BvcnRUb3RhbEFyZWEgPSBldmVudC50YXJnZXQuaW5uZXJXaWR0aDtcblxuICAgICAgIHRoaXMuTm9ybWFsaXplV2luZG93cygpO1xuICAgIH1cblxuICAgIC8vIENoZWNrcyBpZiB0aGVyZSBhcmUgbW9yZSBvcGVuZWQgd2luZG93cyB0aGFuIHRoZSB2aWV3IHBvcnQgY2FuIGRpc3BsYXlcbiAgICBwcml2YXRlIE5vcm1hbGl6ZVdpbmRvd3MoKTogdm9pZFxuICAgIHtcbiAgICAgICAgY29uc3QgbWF4U3VwcG9ydGVkT3BlbmVkV2luZG93cyA9IE1hdGguZmxvb3IoKHRoaXMudmlld1BvcnRUb3RhbEFyZWEgLSAoIXRoaXMuaGlkZUZyaWVuZHNMaXN0ID8gdGhpcy5mcmllbmRzTGlzdFdpZHRoIDogMCkpIC8gdGhpcy53aW5kb3dTaXplRmFjdG9yKTtcbiAgICAgICAgY29uc3QgZGlmZmVyZW5jZSA9IHRoaXMud2luZG93cy5sZW5ndGggLSBtYXhTdXBwb3J0ZWRPcGVuZWRXaW5kb3dzO1xuXG4gICAgICAgIGlmIChkaWZmZXJlbmNlID49IDApXG4gICAgICAgIHtcbiAgICAgICAgICAgIHRoaXMud2luZG93cy5zcGxpY2UodGhpcy53aW5kb3dzLmxlbmd0aCAtIGRpZmZlcmVuY2UpO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy51cGRhdGVXaW5kb3dzU3RhdGUodGhpcy53aW5kb3dzKTtcblxuICAgICAgICAvLyBWaWV3cG9ydCBzaG91bGQgaGF2ZSBzcGFjZSBmb3IgYXQgbGVhc3Qgb25lIGNoYXQgd2luZG93IGJ1dCBzaG91bGQgc2hvdyBpbiBtb2JpbGUgaWYgb3B0aW9uIGlzIGVuYWJsZWQuXG4gICAgICAgIHRoaXMudW5zdXBwb3J0ZWRWaWV3cG9ydCA9IHRoaXMuaXNWaWV3cG9ydE9uTW9iaWxlRW5hYmxlZD8gZmFsc2UgOiB0aGlzLmhpZGVGcmllbmRzTGlzdE9uVW5zdXBwb3J0ZWRWaWV3cG9ydCAmJiBtYXhTdXBwb3J0ZWRPcGVuZWRXaW5kb3dzIDwgMTtcbiAgICB9XG5cbiAgICAvLyBJbml0aWFsaXplcyB0aGUgY2hhdCBwbHVnaW4gYW5kIHRoZSBtZXNzYWdpbmcgYWRhcHRlclxuICAgIHByaXZhdGUgYm9vdHN0cmFwQ2hhdCgpOiB2b2lkXG4gICAge1xuICAgICAgICBsZXQgaW5pdGlhbGl6YXRpb25FeGNlcHRpb24gPSBudWxsO1xuXG4gICAgICAgIGlmICh0aGlzLmFkYXB0ZXIgIT0gbnVsbCAmJiB0aGlzLnVzZXJJZCAhPSBudWxsKVxuICAgICAgICB7XG4gICAgICAgICAgICB0cnlcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICB0aGlzLnZpZXdQb3J0VG90YWxBcmVhID0gd2luZG93LmlubmVyV2lkdGg7XG5cbiAgICAgICAgICAgICAgICB0aGlzLmluaXRpYWxpemVUaGVtZSgpO1xuICAgICAgICAgICAgICAgIHRoaXMuaW5pdGlhbGl6ZURlZmF1bHRUZXh0KCk7XG4gICAgICAgICAgICAgICAgdGhpcy5pbml0aWFsaXplQnJvd3Nlck5vdGlmaWNhdGlvbnMoKTtcblxuICAgICAgICAgICAgICAgIC8vIEJpbmRpbmcgZXZlbnQgbGlzdGVuZXJzXG4gICAgICAgICAgICAgICAgdGhpcy5hZGFwdGVyLm1lc3NhZ2VSZWNlaXZlZEhhbmRsZXIgPSAocGFydGljaXBhbnQsIG1zZykgPT4gdGhpcy5vbk1lc3NhZ2VSZWNlaXZlZChwYXJ0aWNpcGFudCwgbXNnKTtcbiAgICAgICAgICAgICAgICB0aGlzLmFkYXB0ZXIuZnJpZW5kc0xpc3RDaGFuZ2VkSGFuZGxlciA9IChwYXJ0aWNpcGFudHNSZXNwb25zZSkgPT4gdGhpcy5vbkZyaWVuZHNMaXN0Q2hhbmdlZChwYXJ0aWNpcGFudHNSZXNwb25zZSk7XG5cbiAgICAgICAgICAgICAgICB0aGlzLmFjdGl2YXRlRnJpZW5kTGlzdEZldGNoKCk7XG5cbiAgICAgICAgICAgICAgICB0aGlzLmJ1ZmZlckF1ZGlvRmlsZSgpO1xuXG4gICAgICAgICAgICAgICAgdGhpcy5oYXNQYWdlZEhpc3RvcnkgPSB0aGlzLmFkYXB0ZXIgaW5zdGFuY2VvZiBQYWdlZEhpc3RvcnlDaGF0QWRhcHRlcjtcblxuICAgICAgICAgICAgICAgIGlmICh0aGlzLmZpbGVVcGxvYWRVcmwgJiYgdGhpcy5maWxlVXBsb2FkVXJsICE9PSBcIlwiKVxuICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5maWxlVXBsb2FkQWRhcHRlciA9IG5ldyBEZWZhdWx0RmlsZVVwbG9hZEFkYXB0ZXIodGhpcy5maWxlVXBsb2FkVXJsLCB0aGlzLl9odHRwQ2xpZW50KTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB0aGlzLk5vcm1hbGl6ZVdpbmRvd3MoKTtcblxuICAgICAgICAgICAgICAgIHRoaXMuaXNCb290c3RyYXBwZWQgPSB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY2F0Y2goZXgpXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgaW5pdGlhbGl6YXRpb25FeGNlcHRpb24gPSBleDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghdGhpcy5pc0Jvb3RzdHJhcHBlZCl7XG4gICAgICAgICAgICBjb25zb2xlLmVycm9yKFwibmctY2hhdCBjb21wb25lbnQgY291bGRuJ3QgYmUgYm9vdHN0cmFwcGVkLlwiKTtcblxuICAgICAgICAgICAgaWYgKHRoaXMudXNlcklkID09IG51bGwpe1xuICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoXCJuZy1jaGF0IGNhbid0IGJlIGluaXRpYWxpemVkIHdpdGhvdXQgYW4gdXNlciBpZC4gUGxlYXNlIG1ha2Ugc3VyZSB5b3UndmUgcHJvdmlkZWQgYW4gdXNlcklkIGFzIGEgcGFyYW1ldGVyIG9mIHRoZSBuZy1jaGF0IGNvbXBvbmVudC5cIik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodGhpcy5hZGFwdGVyID09IG51bGwpe1xuICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoXCJuZy1jaGF0IGNhbid0IGJlIGJvb3RzdHJhcHBlZCB3aXRob3V0IGEgQ2hhdEFkYXB0ZXIuIFBsZWFzZSBtYWtlIHN1cmUgeW91J3ZlIHByb3ZpZGVkIGEgQ2hhdEFkYXB0ZXIgaW1wbGVtZW50YXRpb24gYXMgYSBwYXJhbWV0ZXIgb2YgdGhlIG5nLWNoYXQgY29tcG9uZW50LlwiKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChpbml0aWFsaXphdGlvbkV4Y2VwdGlvbilcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKGBBbiBleGNlcHRpb24gaGFzIG9jY3VycmVkIHdoaWxlIGluaXRpYWxpemluZyBuZy1jaGF0LiBEZXRhaWxzOiAke2luaXRpYWxpemF0aW9uRXhjZXB0aW9uLm1lc3NhZ2V9YCk7XG4gICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihpbml0aWFsaXphdGlvbkV4Y2VwdGlvbik7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcml2YXRlIGFjdGl2YXRlRnJpZW5kTGlzdEZldGNoKCk6IHZvaWQge1xuICAgICAgICBpZiAodGhpcy5hZGFwdGVyKVxuICAgICAgICB7XG4gICAgICAgICAgICAvLyBMb2FkaW5nIGN1cnJlbnQgdXNlcnMgbGlzdFxuICAgICAgICAgICAgaWYgKHRoaXMucG9sbEZyaWVuZHNMaXN0KXtcbiAgICAgICAgICAgICAgICAvLyBTZXR0aW5nIGEgbG9uZyBwb2xsIGludGVydmFsIHRvIHVwZGF0ZSB0aGUgZnJpZW5kcyBsaXN0XG4gICAgICAgICAgICAgICAgdGhpcy5mZXRjaEZyaWVuZHNMaXN0KHRydWUpO1xuICAgICAgICAgICAgICAgIHRoaXMucG9sbGluZ0ludGVydmFsV2luZG93SW5zdGFuY2UgPSB3aW5kb3cuc2V0SW50ZXJ2YWwoKCkgPT4gdGhpcy5mZXRjaEZyaWVuZHNMaXN0KGZhbHNlKSwgdGhpcy5wb2xsaW5nSW50ZXJ2YWwpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZVxuICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgIC8vIFNpbmNlIHBvbGxpbmcgd2FzIGRpc2FibGVkLCBhIGZyaWVuZHMgbGlzdCB1cGRhdGUgbWVjaGFuaXNtIHdpbGwgaGF2ZSB0byBiZSBpbXBsZW1lbnRlZCBpbiB0aGUgQ2hhdEFkYXB0ZXIuXG4gICAgICAgICAgICAgICAgdGhpcy5mZXRjaEZyaWVuZHNMaXN0KHRydWUpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgLy8gSW5pdGlhbGl6ZXMgYnJvd3NlciBub3RpZmljYXRpb25zXG4gICAgcHJpdmF0ZSBhc3luYyBpbml0aWFsaXplQnJvd3Nlck5vdGlmaWNhdGlvbnMoKVxuICAgIHtcbiAgICAgICAgaWYgKHRoaXMuYnJvd3Nlck5vdGlmaWNhdGlvbnNFbmFibGVkICYmIChcIk5vdGlmaWNhdGlvblwiIGluIHdpbmRvdykpXG4gICAgICAgIHtcbiAgICAgICAgICAgIGlmIChhd2FpdCBOb3RpZmljYXRpb24ucmVxdWVzdFBlcm1pc3Npb24oKSA9PT0gXCJncmFudGVkXCIpXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgdGhpcy5icm93c2VyTm90aWZpY2F0aW9uc0Jvb3RzdHJhcHBlZCA9IHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBJbml0aWFsaXplcyBkZWZhdWx0IHRleHRcbiAgICBwcml2YXRlIGluaXRpYWxpemVEZWZhdWx0VGV4dCgpIDogdm9pZFxuICAgIHtcbiAgICAgICAgaWYgKCF0aGlzLmxvY2FsaXphdGlvbilcbiAgICAgICAge1xuICAgICAgICAgICAgdGhpcy5sb2NhbGl6YXRpb24gPSB7XG4gICAgICAgICAgICAgICAgbWVzc2FnZVBsYWNlaG9sZGVyOiB0aGlzLm1lc3NhZ2VQbGFjZWhvbGRlcixcbiAgICAgICAgICAgICAgICBzZWFyY2hQbGFjZWhvbGRlcjogdGhpcy5zZWFyY2hQbGFjZWhvbGRlcixcbiAgICAgICAgICAgICAgICB0aXRsZTogdGhpcy50aXRsZSxcbiAgICAgICAgICAgICAgICBzdGF0dXNEZXNjcmlwdGlvbjogdGhpcy5zdGF0dXNEZXNjcmlwdGlvbixcbiAgICAgICAgICAgICAgICBicm93c2VyTm90aWZpY2F0aW9uVGl0bGU6IHRoaXMuYnJvd3Nlck5vdGlmaWNhdGlvblRpdGxlLFxuICAgICAgICAgICAgICAgIGxvYWRNZXNzYWdlSGlzdG9yeVBsYWNlaG9sZGVyOiBcIkxvYWQgb2xkZXIgbWVzc2FnZXNcIlxuICAgICAgICAgICAgfTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByaXZhdGUgaW5pdGlhbGl6ZVRoZW1lKCk6IHZvaWRcbiAgICB7XG4gICAgICAgIGlmICh0aGlzLmN1c3RvbVRoZW1lKVxuICAgICAgICB7XG4gICAgICAgICAgICB0aGlzLnRoZW1lID0gVGhlbWUuQ3VzdG9tO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKHRoaXMudGhlbWUgIT0gVGhlbWUuTGlnaHQgJiYgdGhpcy50aGVtZSAhPSBUaGVtZS5EYXJrKVxuICAgICAgICB7XG4gICAgICAgICAgICAvLyBUT0RPOiBVc2UgZXMyMDE3IGluIGZ1dHVyZSB3aXRoIE9iamVjdC52YWx1ZXMoVGhlbWUpLmluY2x1ZGVzKHRoaXMudGhlbWUpIHRvIGRvIHRoaXMgY2hlY2tcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgSW52YWxpZCB0aGVtZSBjb25maWd1cmF0aW9uIGZvciBuZy1jaGF0LiBcIiR7dGhpcy50aGVtZX1cIiBpcyBub3QgYSB2YWxpZCB0aGVtZSB2YWx1ZS5gKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8vIFNlbmRzIGEgcmVxdWVzdCB0byBsb2FkIHRoZSBmcmllbmRzIGxpc3RcbiAgICBwcml2YXRlIGZldGNoRnJpZW5kc0xpc3QoaXNCb290c3RyYXBwaW5nOiBib29sZWFuKTogdm9pZFxuICAgIHtcbiAgICAgICAgdGhpcy5hZGFwdGVyLmxpc3RGcmllbmRzKClcbiAgICAgICAgLnBpcGUoXG4gICAgICAgICAgICBtYXAoKHBhcnRpY2lwYW50c1Jlc3BvbnNlOiBQYXJ0aWNpcGFudFJlc3BvbnNlW10pID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLnBhcnRpY2lwYW50c1Jlc3BvbnNlID0gcGFydGljaXBhbnRzUmVzcG9uc2U7XG5cbiAgICAgICAgICAgICAgICB0aGlzLnBhcnRpY2lwYW50cyA9IHBhcnRpY2lwYW50c1Jlc3BvbnNlLm1hcCgocmVzcG9uc2U6IFBhcnRpY2lwYW50UmVzcG9uc2UpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlc3BvbnNlLnBhcnRpY2lwYW50O1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSlcbiAgICAgICAgKS5zdWJzY3JpYmUoKCkgPT4ge1xuICAgICAgICAgICAgaWYgKGlzQm9vdHN0cmFwcGluZylcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICB0aGlzLnJlc3RvcmVXaW5kb3dzU3RhdGUoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgZmV0Y2hNZXNzYWdlSGlzdG9yeSh3aW5kb3c6IFdpbmRvdykge1xuICAgICAgICAvLyBOb3QgaWRlYWwgYnV0IHdpbGwga2VlcCB0aGlzIHVudGlsIHdlIGRlY2lkZSBpZiB3ZSBhcmUgc2hpcHBpbmcgcGFnaW5hdGlvbiB3aXRoIHRoZSBkZWZhdWx0IGFkYXB0ZXJcbiAgICAgICAgaWYgKHRoaXMuYWRhcHRlciBpbnN0YW5jZW9mIFBhZ2VkSGlzdG9yeUNoYXRBZGFwdGVyKVxuICAgICAgICB7XG4gICAgICAgICAgICB3aW5kb3cuaXNMb2FkaW5nSGlzdG9yeSA9IHRydWU7XG5cbiAgICAgICAgICAgIHRoaXMuYWRhcHRlci5nZXRNZXNzYWdlSGlzdG9yeUJ5UGFnZSh3aW5kb3cucGFydGljaXBhbnQuaWQsIHRoaXMuaGlzdG9yeVBhZ2VTaXplLCArK3dpbmRvdy5oaXN0b3J5UGFnZSlcbiAgICAgICAgICAgIC5waXBlKFxuICAgICAgICAgICAgICAgIG1hcCgocmVzdWx0OiBNZXNzYWdlW10pID0+IHtcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0LmZvckVhY2goKG1lc3NhZ2UpID0+IHRoaXMuYXNzZXJ0TWVzc2FnZVR5cGUobWVzc2FnZSkpO1xuXG4gICAgICAgICAgICAgICAgICAgIHdpbmRvdy5tZXNzYWdlcyA9IHJlc3VsdC5jb25jYXQod2luZG93Lm1lc3NhZ2VzKTtcbiAgICAgICAgICAgICAgICAgICAgd2luZG93LmlzTG9hZGluZ0hpc3RvcnkgPSBmYWxzZTtcblxuICAgICAgICAgICAgICAgICAgICBjb25zdCBkaXJlY3Rpb246IFNjcm9sbERpcmVjdGlvbiA9ICh3aW5kb3cuaGlzdG9yeVBhZ2UgPT0gMSkgPyBTY3JvbGxEaXJlY3Rpb24uQm90dG9tIDogU2Nyb2xsRGlyZWN0aW9uLlRvcDtcbiAgICAgICAgICAgICAgICAgICAgd2luZG93Lmhhc01vcmVNZXNzYWdlcyA9IHJlc3VsdC5sZW5ndGggPT0gdGhpcy5oaXN0b3J5UGFnZVNpemU7XG5cbiAgICAgICAgICAgICAgICAgICAgc2V0VGltZW91dCgoKSA9PiB0aGlzLm9uRmV0Y2hNZXNzYWdlSGlzdG9yeUxvYWRlZChyZXN1bHQsIHdpbmRvdywgZGlyZWN0aW9uLCB0cnVlKSk7XG4gICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICkuc3Vic2NyaWJlKCk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZVxuICAgICAgICB7XG4gICAgICAgICAgICB0aGlzLmFkYXB0ZXIuZ2V0TWVzc2FnZUhpc3Rvcnkod2luZG93LnBhcnRpY2lwYW50LmlkKVxuICAgICAgICAgICAgLnBpcGUoXG4gICAgICAgICAgICAgICAgbWFwKChyZXN1bHQ6IE1lc3NhZ2VbXSkgPT4ge1xuICAgICAgICAgICAgICAgICAgICByZXN1bHQuZm9yRWFjaCgobWVzc2FnZSkgPT4gdGhpcy5hc3NlcnRNZXNzYWdlVHlwZShtZXNzYWdlKSk7XG5cbiAgICAgICAgICAgICAgICAgICAgd2luZG93Lm1lc3NhZ2VzID0gcmVzdWx0LmNvbmNhdCh3aW5kb3cubWVzc2FnZXMpO1xuICAgICAgICAgICAgICAgICAgICB3aW5kb3cuaXNMb2FkaW5nSGlzdG9yeSA9IGZhbHNlO1xuXG4gICAgICAgICAgICAgICAgICAgIHNldFRpbWVvdXQoKCkgPT4gdGhpcy5vbkZldGNoTWVzc2FnZUhpc3RvcnlMb2FkZWQocmVzdWx0LCB3aW5kb3csIFNjcm9sbERpcmVjdGlvbi5Cb3R0b20pKTtcbiAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgKS5zdWJzY3JpYmUoKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByaXZhdGUgb25GZXRjaE1lc3NhZ2VIaXN0b3J5TG9hZGVkKG1lc3NhZ2VzOiBNZXNzYWdlW10sIHdpbmRvdzogV2luZG93LCBkaXJlY3Rpb246IFNjcm9sbERpcmVjdGlvbiwgZm9yY2VNYXJrTWVzc2FnZXNBc1NlZW46IGJvb2xlYW4gPSBmYWxzZSk6IHZvaWRcbiAgICB7XG4gICAgICAgIHRoaXMuc2Nyb2xsQ2hhdFdpbmRvdyh3aW5kb3csIGRpcmVjdGlvbilcblxuICAgICAgICBpZiAod2luZG93Lmhhc0ZvY3VzIHx8IGZvcmNlTWFya01lc3NhZ2VzQXNTZWVuKVxuICAgICAgICB7XG4gICAgICAgICAgICBjb25zdCB1bnNlZW5NZXNzYWdlcyA9IG1lc3NhZ2VzLmZpbHRlcihtID0+ICFtLmRhdGVTZWVuKTtcblxuICAgICAgICAgICAgdGhpcy5tYXJrTWVzc2FnZXNBc1JlYWQodW5zZWVuTWVzc2FnZXMpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLy8gVXBkYXRlcyB0aGUgZnJpZW5kcyBsaXN0IHZpYSB0aGUgZXZlbnQgaGFuZGxlclxuICAgIHByaXZhdGUgb25GcmllbmRzTGlzdENoYW5nZWQocGFydGljaXBhbnRzUmVzcG9uc2U6IFBhcnRpY2lwYW50UmVzcG9uc2VbXSk6IHZvaWRcbiAgICB7XG4gICAgICAgIGlmIChwYXJ0aWNpcGFudHNSZXNwb25zZSlcbiAgICAgICAge1xuICAgICAgICAgICAgdGhpcy5wYXJ0aWNpcGFudHNSZXNwb25zZSA9IHBhcnRpY2lwYW50c1Jlc3BvbnNlO1xuXG4gICAgICAgICAgICB0aGlzLnBhcnRpY2lwYW50cyA9IHBhcnRpY2lwYW50c1Jlc3BvbnNlLm1hcCgocmVzcG9uc2U6IFBhcnRpY2lwYW50UmVzcG9uc2UpID0+IHtcbiAgICAgICAgICAgICAgICByZXR1cm4gcmVzcG9uc2UucGFydGljaXBhbnQ7XG4gICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgdGhpcy5wYXJ0aWNpcGFudHNJbnRlcmFjdGVkV2l0aCA9IFtdO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLy8gSGFuZGxlcyByZWNlaXZlZCBtZXNzYWdlcyBieSB0aGUgYWRhcHRlclxuICAgIHByaXZhdGUgb25NZXNzYWdlUmVjZWl2ZWQocGFydGljaXBhbnQ6IElDaGF0UGFydGljaXBhbnQsIG1lc3NhZ2U6IE1lc3NhZ2UpXG4gICAge1xuICAgICAgICBpZiAocGFydGljaXBhbnQgJiYgbWVzc2FnZSlcbiAgICAgICAge1xuICAgICAgICAgICAgY29uc3QgY2hhdFdpbmRvdyA9IHRoaXMub3BlbkNoYXRXaW5kb3cocGFydGljaXBhbnQpO1xuXG4gICAgICAgICAgICB0aGlzLmFzc2VydE1lc3NhZ2VUeXBlKG1lc3NhZ2UpO1xuXG4gICAgICAgICAgICBpZiAoIWNoYXRXaW5kb3dbMV0gfHwgIXRoaXMuaGlzdG9yeUVuYWJsZWQpe1xuICAgICAgICAgICAgICAgIGNoYXRXaW5kb3dbMF0ubWVzc2FnZXMucHVzaChtZXNzYWdlKTtcblxuICAgICAgICAgICAgICAgIHRoaXMuc2Nyb2xsQ2hhdFdpbmRvdyhjaGF0V2luZG93WzBdLCBTY3JvbGxEaXJlY3Rpb24uQm90dG9tKTtcblxuICAgICAgICAgICAgICAgIGlmIChjaGF0V2luZG93WzBdLmhhc0ZvY3VzKVxuICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5tYXJrTWVzc2FnZXNBc1JlYWQoW21lc3NhZ2VdKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRoaXMuZW1pdE1lc3NhZ2VTb3VuZChjaGF0V2luZG93WzBdKTtcblxuICAgICAgICAgICAgLy8gRG8gbm90IHB1c2ggYnJvd3NlciBub3RpZmljYXRpb25zIHdpdGggbWVzc2FnZSBjb250ZW50IGZvciBwcml2YWN5IHB1cnBvc2VzIGlmIHRoZSAnbWF4aW1pemVXaW5kb3dPbk5ld01lc3NhZ2UnIHNldHRpbmcgaXMgb2ZmIGFuZCB0aGlzIGlzIGEgbmV3IGNoYXQgd2luZG93LlxuICAgICAgICAgICAgaWYgKHRoaXMubWF4aW1pemVXaW5kb3dPbk5ld01lc3NhZ2UgfHwgKCFjaGF0V2luZG93WzFdICYmICFjaGF0V2luZG93WzBdLmlzQ29sbGFwc2VkKSlcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAvLyBTb21lIG1lc3NhZ2VzIGFyZSBub3QgcHVzaGVkIGJlY2F1c2UgdGhleSBhcmUgbG9hZGVkIGJ5IGZldGNoaW5nIHRoZSBoaXN0b3J5IGhlbmNlIHdoeSB3ZSBzdXBwbHkgdGhlIG1lc3NhZ2UgaGVyZVxuICAgICAgICAgICAgICAgIHRoaXMuZW1pdEJyb3dzZXJOb3RpZmljYXRpb24oY2hhdFdpbmRvd1swXSwgbWVzc2FnZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBvblBhcnRpY2lwYW50Q2xpY2tlZEZyb21GcmllbmRzTGlzdChwYXJ0aWNpcGFudDogSUNoYXRQYXJ0aWNpcGFudCk6IHZvaWQge1xuICAgICAgICB0aGlzLm9wZW5DaGF0V2luZG93KHBhcnRpY2lwYW50LCB0cnVlLCB0cnVlKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGNhbmNlbE9wdGlvblByb21wdCgpOiB2b2lkIHtcbiAgICAgICAgaWYgKHRoaXMuY3VycmVudEFjdGl2ZU9wdGlvbilcbiAgICAgICAge1xuICAgICAgICAgICAgdGhpcy5jdXJyZW50QWN0aXZlT3B0aW9uLmlzQWN0aXZlID0gZmFsc2U7XG4gICAgICAgICAgICB0aGlzLmN1cnJlbnRBY3RpdmVPcHRpb24gPSBudWxsO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgb25PcHRpb25Qcm9tcHRDYW5jZWxlZCgpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5jYW5jZWxPcHRpb25Qcm9tcHQoKTtcbiAgICB9XG5cbiAgICBvbk9wdGlvblByb21wdENvbmZpcm1lZChldmVudDogYW55KTogdm9pZCB7XG4gICAgICAgIC8vIEZvciBub3cgdGhpcyBpcyBmaW5lIGFzIHRoZXJlIGlzIG9ubHkgb25lIG9wdGlvbiBhdmFpbGFibGUuIEludHJvZHVjZSBvcHRpb24gdHlwZXMgYW5kIHR5cGUgY2hlY2tpbmcgaWYgYSBuZXcgb3B0aW9uIGlzIGFkZGVkLlxuICAgICAgICB0aGlzLmNvbmZpcm1OZXdHcm91cChldmVudCk7XG5cbiAgICAgICAgLy8gQ2FuY2VsaW5nIGN1cnJlbnQgc3RhdGVcbiAgICAgICAgdGhpcy5jYW5jZWxPcHRpb25Qcm9tcHQoKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGNvbmZpcm1OZXdHcm91cCh1c2VyczogVXNlcltdKTogdm9pZCB7XG4gICAgICAgIGNvbnN0IG5ld0dyb3VwID0gbmV3IEdyb3VwKHVzZXJzKTtcblxuICAgICAgICB0aGlzLm9wZW5DaGF0V2luZG93KG5ld0dyb3VwKTtcblxuICAgICAgICBpZiAodGhpcy5ncm91cEFkYXB0ZXIpXG4gICAgICAgIHtcbiAgICAgICAgICAgIHRoaXMuZ3JvdXBBZGFwdGVyLmdyb3VwQ3JlYXRlZChuZXdHcm91cCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBPcGVucyBhIG5ldyBjaGF0IHdoaW5kb3cuIFRha2VzIGNhcmUgb2YgYXZhaWxhYmxlIHZpZXdwb3J0XG4gICAgLy8gV29ya3MgZm9yIG9wZW5pbmcgYSBjaGF0IHdpbmRvdyBmb3IgYW4gdXNlciBvciBmb3IgYSBncm91cFxuICAgIC8vIFJldHVybnMgPT4gW1dpbmRvdzogV2luZG93IG9iamVjdCByZWZlcmVuY2UsIGJvb2xlYW46IEluZGljYXRlcyBpZiB0aGlzIHdpbmRvdyBpcyBhIG5ldyBjaGF0IHdpbmRvd11cbiAgICBwcml2YXRlIG9wZW5DaGF0V2luZG93KHBhcnRpY2lwYW50OiBJQ2hhdFBhcnRpY2lwYW50LCBmb2N1c09uTmV3V2luZG93OiBib29sZWFuID0gZmFsc2UsIGludm9rZWRCeVVzZXJDbGljazogYm9vbGVhbiA9IGZhbHNlKTogW1dpbmRvdywgYm9vbGVhbl1cbiAgICB7XG4gICAgICAgIC8vIElzIHRoaXMgd2luZG93IG9wZW5lZD9cbiAgICAgICAgY29uc3Qgb3BlbmVkV2luZG93ID0gdGhpcy53aW5kb3dzLmZpbmQoeCA9PiB4LnBhcnRpY2lwYW50LmlkID09IHBhcnRpY2lwYW50LmlkKTtcblxuICAgICAgICBpZiAoIW9wZW5lZFdpbmRvdylcbiAgICAgICAge1xuICAgICAgICAgICAgaWYgKGludm9rZWRCeVVzZXJDbGljaylcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICB0aGlzLm9uUGFydGljaXBhbnRDbGlja2VkLmVtaXQocGFydGljaXBhbnQpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBSZWZlciB0byBpc3N1ZSAjNTggb24gR2l0aHViXG4gICAgICAgICAgICBjb25zdCBjb2xsYXBzZVdpbmRvdyA9IGludm9rZWRCeVVzZXJDbGljayA/IGZhbHNlIDogIXRoaXMubWF4aW1pemVXaW5kb3dPbk5ld01lc3NhZ2U7XG5cbiAgICAgICAgICAgIGNvbnN0IG5ld0NoYXRXaW5kb3c6IFdpbmRvdyA9IG5ldyBXaW5kb3cocGFydGljaXBhbnQsIHRoaXMuaGlzdG9yeUVuYWJsZWQsIGNvbGxhcHNlV2luZG93KTtcblxuICAgICAgICAgICAgLy8gTG9hZHMgdGhlIGNoYXQgaGlzdG9yeSB2aWEgYW4gUnhKcyBPYnNlcnZhYmxlXG4gICAgICAgICAgICBpZiAodGhpcy5oaXN0b3J5RW5hYmxlZClcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICB0aGlzLmZldGNoTWVzc2FnZUhpc3RvcnkobmV3Q2hhdFdpbmRvdyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRoaXMud2luZG93cy51bnNoaWZ0KG5ld0NoYXRXaW5kb3cpO1xuXG4gICAgICAgICAgICAvLyBJcyB0aGVyZSBlbm91Z2ggc3BhY2UgbGVmdCBpbiB0aGUgdmlldyBwb3J0ID8gYnV0IHNob3VsZCBiZSBkaXNwbGF5ZWQgaW4gbW9iaWxlIGlmIG9wdGlvbiBpcyBlbmFibGVkXG4gICAgICAgICAgICBpZiAoIXRoaXMuaXNWaWV3cG9ydE9uTW9iaWxlRW5hYmxlZCkge1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLndpbmRvd3MubGVuZ3RoICogdGhpcy53aW5kb3dTaXplRmFjdG9yID49IHRoaXMudmlld1BvcnRUb3RhbEFyZWEgLSAoIXRoaXMuaGlkZUZyaWVuZHNMaXN0ID8gdGhpcy5mcmllbmRzTGlzdFdpZHRoIDogMCkpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy53aW5kb3dzLnBvcCgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy51cGRhdGVXaW5kb3dzU3RhdGUodGhpcy53aW5kb3dzKTtcblxuICAgICAgICAgICAgaWYgKGZvY3VzT25OZXdXaW5kb3cgJiYgIWNvbGxhcHNlV2luZG93KVxuICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgIHRoaXMuZm9jdXNPbldpbmRvdyhuZXdDaGF0V2luZG93KTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy5wYXJ0aWNpcGFudHNJbnRlcmFjdGVkV2l0aC5wdXNoKHBhcnRpY2lwYW50KTtcbiAgICAgICAgICAgIHRoaXMub25QYXJ0aWNpcGFudENoYXRPcGVuZWQuZW1pdChwYXJ0aWNpcGFudCk7XG5cbiAgICAgICAgICAgIHJldHVybiBbbmV3Q2hhdFdpbmRvdywgdHJ1ZV07XG4gICAgICAgIH1cbiAgICAgICAgZWxzZVxuICAgICAgICB7XG4gICAgICAgICAgICAvLyBSZXR1cm5zIHRoZSBleGlzdGluZyBjaGF0IHdpbmRvd1xuICAgICAgICAgICAgcmV0dXJuIFtvcGVuZWRXaW5kb3csIGZhbHNlXTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8vIEZvY3VzIG9uIHRoZSBpbnB1dCBlbGVtZW50IG9mIHRoZSBzdXBwbGllZCB3aW5kb3dcbiAgICBwcml2YXRlIGZvY3VzT25XaW5kb3cod2luZG93OiBXaW5kb3csIGNhbGxiYWNrOiBGdW5jdGlvbiA9ICgpID0+IHt9KSA6IHZvaWRcbiAgICB7XG4gICAgICAgIGNvbnN0IHdpbmRvd0luZGV4ID0gdGhpcy53aW5kb3dzLmluZGV4T2Yod2luZG93KTtcbiAgICAgICAgaWYgKHdpbmRvd0luZGV4ID49IDApXG4gICAgICAgIHtcbiAgICAgICAgICAgIHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLmNoYXRXaW5kb3dzKVxuICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgY2hhdFdpbmRvd1RvRm9jdXMgPSB0aGlzLmNoYXRXaW5kb3dzLnRvQXJyYXkoKVt3aW5kb3dJbmRleF07XG5cbiAgICAgICAgICAgICAgICAgICAgY2hhdFdpbmRvd1RvRm9jdXMuY2hhdFdpbmRvd0lucHV0Lm5hdGl2ZUVsZW1lbnQuZm9jdXMoKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBjYWxsYmFjaygpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcml2YXRlIGFzc2VydE1lc3NhZ2VUeXBlKG1lc3NhZ2U6IE1lc3NhZ2UpOiB2b2lkIHtcbiAgICAgICAgLy8gQWx3YXlzIGZhbGxiYWNrIHRvIFwiVGV4dFwiIG1lc3NhZ2VzIHRvIGF2b2lkIHJlbmRlbnJpbmcgaXNzdWVzXG4gICAgICAgIGlmICghbWVzc2FnZS50eXBlKVxuICAgICAgICB7XG4gICAgICAgICAgICBtZXNzYWdlLnR5cGUgPSBNZXNzYWdlVHlwZS5UZXh0O1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLy8gTWFya3MgYWxsIG1lc3NhZ2VzIHByb3ZpZGVkIGFzIHJlYWQgd2l0aCB0aGUgY3VycmVudCB0aW1lLlxuICAgIG1hcmtNZXNzYWdlc0FzUmVhZChtZXNzYWdlczogTWVzc2FnZVtdKTogdm9pZFxuICAgIHtcbiAgICAgICAgY29uc3QgY3VycmVudERhdGUgPSBuZXcgRGF0ZSgpO1xuXG4gICAgICAgIG1lc3NhZ2VzLmZvckVhY2goKG1zZyk9PntcbiAgICAgICAgICAgIG1zZy5kYXRlU2VlbiA9IGN1cnJlbnREYXRlO1xuICAgICAgICB9KTtcblxuICAgICAgICB0aGlzLm9uTWVzc2FnZXNTZWVuLmVtaXQobWVzc2FnZXMpO1xuICAgIH1cblxuICAgIC8vIEJ1ZmZlcnMgYXVkaW8gZmlsZSAoRm9yIGNvbXBvbmVudCdzIGJvb3RzdHJhcHBpbmcpXG4gICAgcHJpdmF0ZSBidWZmZXJBdWRpb0ZpbGUoKTogdm9pZCB7XG4gICAgICAgIGlmICh0aGlzLmF1ZGlvU291cmNlICYmIHRoaXMuYXVkaW9Tb3VyY2UubGVuZ3RoID4gMClcbiAgICAgICAge1xuICAgICAgICAgICAgdGhpcy5hdWRpb0ZpbGUgPSBuZXcgQXVkaW8oKTtcbiAgICAgICAgICAgIHRoaXMuYXVkaW9GaWxlLnNyYyA9IHRoaXMuYXVkaW9Tb3VyY2U7XG4gICAgICAgICAgICB0aGlzLmF1ZGlvRmlsZS5sb2FkKCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBFbWl0cyBhIG1lc3NhZ2Ugbm90aWZpY2F0aW9uIGF1ZGlvIGlmIGVuYWJsZWQgYWZ0ZXIgZXZlcnkgbWVzc2FnZSByZWNlaXZlZFxuICAgIHByaXZhdGUgZW1pdE1lc3NhZ2VTb3VuZCh3aW5kb3c6IFdpbmRvdyk6IHZvaWRcbiAgICB7XG4gICAgICAgIGlmICh0aGlzLmF1ZGlvRW5hYmxlZCAmJiAhd2luZG93Lmhhc0ZvY3VzICYmIHRoaXMuYXVkaW9GaWxlKSB7XG4gICAgICAgICAgICB0aGlzLmF1ZGlvRmlsZS5wbGF5KCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBFbWl0cyBhIGJyb3dzZXIgbm90aWZpY2F0aW9uXG4gICAgcHJpdmF0ZSBlbWl0QnJvd3Nlck5vdGlmaWNhdGlvbih3aW5kb3c6IFdpbmRvdywgbWVzc2FnZTogTWVzc2FnZSk6IHZvaWRcbiAgICB7XG4gICAgICAgIC8vIGlmICh0aGlzLmJyb3dzZXJOb3RpZmljYXRpb25zQm9vdHN0cmFwcGVkICYmICF3aW5kb3cuaGFzRm9jdXMgJiYgbWVzc2FnZSkge1xuICAgICAgICBpZiAodGhpcy5icm93c2VyTm90aWZpY2F0aW9uc0Jvb3RzdHJhcHBlZCAmJiBtZXNzYWdlKSB7XG4gICAgICAgICAgICBjb25zdCBub3RpZmljYXRpb24gPSBuZXcgTm90aWZpY2F0aW9uKGAke3RoaXMubG9jYWxpemF0aW9uLmJyb3dzZXJOb3RpZmljYXRpb25UaXRsZX0gJHt3aW5kb3cucGFydGljaXBhbnQuZGlzcGxheU5hbWV9YCwge1xuICAgICAgICAgICAgICAgICdib2R5JzogbWVzc2FnZS5tZXNzYWdlLFxuICAgICAgICAgICAgICAgICdpY29uJzogdGhpcy5icm93c2VyTm90aWZpY2F0aW9uSWNvblNvdXJjZVxuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgIHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgICAgICAgICAgIG5vdGlmaWNhdGlvbi5jbG9zZSgpO1xuICAgICAgICAgICAgfSwgbWVzc2FnZS5tZXNzYWdlLmxlbmd0aCA8PSA1MCA/IDUwMDAgOiA3MDAwKTsgLy8gTW9yZSB0aW1lIHRvIHJlYWQgbG9uZ2VyIG1lc3NhZ2VzXG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBTYXZlcyBjdXJyZW50IHdpbmRvd3Mgc3RhdGUgaW50byBsb2NhbCBzdG9yYWdlIGlmIHBlcnNpc3RlbmNlIGlzIGVuYWJsZWRcbiAgICBwcml2YXRlIHVwZGF0ZVdpbmRvd3NTdGF0ZSh3aW5kb3dzOiBXaW5kb3dbXSk6IHZvaWRcbiAgICB7XG4gICAgICAgIGlmICh0aGlzLnBlcnNpc3RXaW5kb3dzU3RhdGUpXG4gICAgICAgIHtcbiAgICAgICAgICAgIGNvbnN0IHBhcnRpY2lwYW50SWRzID0gd2luZG93cy5tYXAoKHcpID0+IHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdy5wYXJ0aWNpcGFudC5pZDtcbiAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICBsb2NhbFN0b3JhZ2Uuc2V0SXRlbSh0aGlzLmxvY2FsU3RvcmFnZUtleSwgSlNPTi5zdHJpbmdpZnkocGFydGljaXBhbnRJZHMpKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByaXZhdGUgcmVzdG9yZVdpbmRvd3NTdGF0ZSgpOiB2b2lkXG4gICAge1xuICAgICAgICB0cnlcbiAgICAgICAge1xuICAgICAgICAgICAgaWYgKHRoaXMucGVyc2lzdFdpbmRvd3NTdGF0ZSlcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICBjb25zdCBzdHJpbmdmaWVkUGFydGljaXBhbnRJZHMgPSBsb2NhbFN0b3JhZ2UuZ2V0SXRlbSh0aGlzLmxvY2FsU3RvcmFnZUtleSk7XG5cbiAgICAgICAgICAgICAgICBpZiAoc3RyaW5nZmllZFBhcnRpY2lwYW50SWRzICYmIHN0cmluZ2ZpZWRQYXJ0aWNpcGFudElkcy5sZW5ndGggPiAwKVxuICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgcGFydGljaXBhbnRJZHMgPSA8bnVtYmVyW10+SlNPTi5wYXJzZShzdHJpbmdmaWVkUGFydGljaXBhbnRJZHMpO1xuXG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHBhcnRpY2lwYW50c1RvUmVzdG9yZSA9IHRoaXMucGFydGljaXBhbnRzLmZpbHRlcih1ID0+IHBhcnRpY2lwYW50SWRzLmluZGV4T2YodS5pZCkgPj0gMCk7XG5cbiAgICAgICAgICAgICAgICAgICAgcGFydGljaXBhbnRzVG9SZXN0b3JlLmZvckVhY2goKHBhcnRpY2lwYW50KSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLm9wZW5DaGF0V2luZG93KHBhcnRpY2lwYW50KTtcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGNhdGNoIChleClcbiAgICAgICAge1xuICAgICAgICAgICAgY29uc29sZS5lcnJvcihgQW4gZXJyb3Igb2NjdXJyZWQgd2hpbGUgcmVzdG9yaW5nIG5nLWNoYXQgd2luZG93cyBzdGF0ZS4gRGV0YWlsczogJHtleH1gKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8vIEdldHMgY2xvc2VzdCBvcGVuIHdpbmRvdyBpZiBhbnkuIE1vc3QgcmVjZW50IG9wZW5lZCBoYXMgcHJpb3JpdHkgKFJpZ2h0KVxuICAgIHByaXZhdGUgZ2V0Q2xvc2VzdFdpbmRvdyh3aW5kb3c6IFdpbmRvdyk6IFdpbmRvdyB8IHVuZGVmaW5lZFxuICAgIHtcbiAgICAgICAgY29uc3QgaW5kZXggPSB0aGlzLndpbmRvd3MuaW5kZXhPZih3aW5kb3cpO1xuXG4gICAgICAgIGlmIChpbmRleCA+IDApXG4gICAgICAgIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLndpbmRvd3NbaW5kZXggLSAxXTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmIChpbmRleCA9PSAwICYmIHRoaXMud2luZG93cy5sZW5ndGggPiAxKVxuICAgICAgICB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy53aW5kb3dzW2luZGV4ICsgMV07XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcml2YXRlIGNsb3NlV2luZG93KHdpbmRvdzogV2luZG93KTogdm9pZFxuICAgIHtcbiAgICAgICAgY29uc3QgaW5kZXggPSB0aGlzLndpbmRvd3MuaW5kZXhPZih3aW5kb3cpO1xuXG4gICAgICAgIHRoaXMud2luZG93cy5zcGxpY2UoaW5kZXgsIDEpO1xuXG4gICAgICAgIHRoaXMudXBkYXRlV2luZG93c1N0YXRlKHRoaXMud2luZG93cyk7XG5cbiAgICAgICAgdGhpcy5vblBhcnRpY2lwYW50Q2hhdENsb3NlZC5lbWl0KHdpbmRvdy5wYXJ0aWNpcGFudCk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBnZXRDaGF0V2luZG93Q29tcG9uZW50SW5zdGFuY2UodGFyZ2V0V2luZG93OiBXaW5kb3cpOiBOZ0NoYXRXaW5kb3dDb21wb25lbnQgfCBudWxsIHtcbiAgICAgICAgY29uc3Qgd2luZG93SW5kZXggPSB0aGlzLndpbmRvd3MuaW5kZXhPZih0YXJnZXRXaW5kb3cpO1xuXG4gICAgICAgIGlmICh0aGlzLmNoYXRXaW5kb3dzKXtcbiAgICAgICAgICAgIGxldCB0YXJnZXRXaW5kb3cgPSB0aGlzLmNoYXRXaW5kb3dzLnRvQXJyYXkoKVt3aW5kb3dJbmRleF07XG5cbiAgICAgICAgICAgIHJldHVybiB0YXJnZXRXaW5kb3c7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG5cbiAgICAvLyBTY3JvbGxzIGEgY2hhdCB3aW5kb3cgbWVzc2FnZSBmbG93IHRvIHRoZSBib3R0b21cbiAgICBwcml2YXRlIHNjcm9sbENoYXRXaW5kb3cod2luZG93OiBXaW5kb3csIGRpcmVjdGlvbjogU2Nyb2xsRGlyZWN0aW9uKTogdm9pZFxuICAgIHtcbiAgICAgICAgY29uc3QgY2hhdFdpbmRvdyA9IHRoaXMuZ2V0Q2hhdFdpbmRvd0NvbXBvbmVudEluc3RhbmNlKHdpbmRvdyk7XG5cbiAgICAgICAgaWYgKGNoYXRXaW5kb3cpe1xuICAgICAgICAgICAgY2hhdFdpbmRvdy5zY3JvbGxDaGF0V2luZG93KHdpbmRvdywgZGlyZWN0aW9uKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIG9uV2luZG93TWVzc2FnZXNTZWVuKG1lc3NhZ2VzU2VlbjogTWVzc2FnZVtdKTogdm9pZCB7XG4gICAgICAgIHRoaXMubWFya01lc3NhZ2VzQXNSZWFkKG1lc3NhZ2VzU2Vlbik7XG4gICAgfVxuXG4gICAgb25XaW5kb3dDaGF0Q2xvc2VkKHBheWxvYWQ6IHsgY2xvc2VkV2luZG93OiBXaW5kb3csIGNsb3NlZFZpYUVzY2FwZUtleTogYm9vbGVhbiB9KTogdm9pZCB7XG4gICAgICAgIGNvbnN0IHsgY2xvc2VkV2luZG93LCBjbG9zZWRWaWFFc2NhcGVLZXkgfSA9IHBheWxvYWQ7XG5cbiAgICAgICAgaWYgKGNsb3NlZFZpYUVzY2FwZUtleSkge1xuICAgICAgICAgICAgbGV0IGNsb3Nlc3RXaW5kb3cgPSB0aGlzLmdldENsb3Nlc3RXaW5kb3coY2xvc2VkV2luZG93KTtcblxuICAgICAgICAgICAgaWYgKGNsb3Nlc3RXaW5kb3cpXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgdGhpcy5mb2N1c09uV2luZG93KGNsb3Nlc3RXaW5kb3csICgpID0+IHsgdGhpcy5jbG9zZVdpbmRvdyhjbG9zZWRXaW5kb3cpOyB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2VcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICB0aGlzLmNsb3NlV2luZG93KGNsb3NlZFdpbmRvdyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICB0aGlzLmNsb3NlV2luZG93KGNsb3NlZFdpbmRvdyk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBvbldpbmRvd1RhYlRyaWdnZXJlZChwYXlsb2FkOiB7IHRyaWdnZXJpbmdXaW5kb3c6IFdpbmRvdywgc2hpZnRLZXlQcmVzc2VkOiBib29sZWFuIH0pOiB2b2lkIHtcbiAgICAgICAgY29uc3QgeyB0cmlnZ2VyaW5nV2luZG93LCBzaGlmdEtleVByZXNzZWQgfSA9IHBheWxvYWQ7XG5cbiAgICAgICAgY29uc3QgY3VycmVudFdpbmRvd0luZGV4ID0gdGhpcy53aW5kb3dzLmluZGV4T2YodHJpZ2dlcmluZ1dpbmRvdyk7XG4gICAgICAgIGxldCB3aW5kb3dUb0ZvY3VzID0gdGhpcy53aW5kb3dzW2N1cnJlbnRXaW5kb3dJbmRleCArIChzaGlmdEtleVByZXNzZWQgPyAxIDogLTEpXTsgLy8gR29lcyBiYWNrIG9uIHNoaWZ0ICsgdGFiXG5cbiAgICAgICAgaWYgKCF3aW5kb3dUb0ZvY3VzKVxuICAgICAgICB7XG4gICAgICAgICAgICAvLyBFZGdlIHdpbmRvd3MsIGdvIHRvIHN0YXJ0IG9yIGVuZFxuICAgICAgICAgICAgd2luZG93VG9Gb2N1cyA9IHRoaXMud2luZG93c1tjdXJyZW50V2luZG93SW5kZXggPiAwID8gMCA6IHRoaXMuY2hhdFdpbmRvd3MubGVuZ3RoIC0gMV07XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLmZvY3VzT25XaW5kb3cod2luZG93VG9Gb2N1cyk7XG4gICAgfVxuXG4gICAgb25XaW5kb3dNZXNzYWdlU2VudChtZXNzYWdlU2VudDogTWVzc2FnZSk6IHZvaWQge1xuICAgICAgICB0aGlzLmFkYXB0ZXIuc2VuZE1lc3NhZ2UobWVzc2FnZVNlbnQpO1xuICAgIH1cblxuICAgIG9uV2luZG93T3B0aW9uVHJpZ2dlcmVkKG9wdGlvbjogSUNoYXRPcHRpb24pOiB2b2lkIHtcbiAgICAgICAgdGhpcy5jdXJyZW50QWN0aXZlT3B0aW9uID0gb3B0aW9uO1xuICAgIH1cblxuICAgIHRyaWdnZXJPcGVuQ2hhdFdpbmRvdyh1c2VyOiBVc2VyKTogdm9pZCB7XG4gICAgICAgIGlmICh1c2VyKVxuICAgICAgICB7XG4gICAgICAgICAgICB0aGlzLm9wZW5DaGF0V2luZG93KHVzZXIpO1xuICAgICAgICB9XG4gICAgfVxuXG4gIHB1YmxpYyAgdHJpZ2dlckNsb3NlQ2hhdFdpbmRvdyh1c2VySWQ6IGFueSk6IHZvaWQge1xuICAgICAgICBjb25zdCBvcGVuZWRXaW5kb3cgPSB0aGlzLndpbmRvd3MuZmluZCh4ID0+IHgucGFydGljaXBhbnQuaWQgPT0gdXNlcklkKTtcblxuICAgICAgICBpZiAob3BlbmVkV2luZG93KVxuICAgICAgICB7XG4gICAgICAgICAgICB0aGlzLmNsb3NlV2luZG93KG9wZW5lZFdpbmRvdyk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICB0cmlnZ2VyVG9nZ2xlQ2hhdFdpbmRvd1Zpc2liaWxpdHkodXNlcklkOiBhbnkpOiB2b2lkIHtcbiAgICAgICAgY29uc3Qgb3BlbmVkV2luZG93ID0gdGhpcy53aW5kb3dzLmZpbmQoeCA9PiB4LnBhcnRpY2lwYW50LmlkID09IHVzZXJJZCk7XG5cbiAgICAgICAgaWYgKG9wZW5lZFdpbmRvdylcbiAgICAgICAge1xuICAgICAgICAgICAgY29uc3QgY2hhdFdpbmRvdyA9IHRoaXMuZ2V0Q2hhdFdpbmRvd0NvbXBvbmVudEluc3RhbmNlKG9wZW5lZFdpbmRvdyk7XG5cbiAgICAgICAgICAgIGlmIChjaGF0V2luZG93KXtcbiAgICAgICAgICAgICAgICBjaGF0V2luZG93Lm9uQ2hhdFdpbmRvd0NsaWNrZWQob3BlbmVkV2luZG93KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8vIGNsb3NlRnJpZW5kTGlzdCgpe1xuICAgIC8vICAgICB0aGlzLmhpZGVGcmllbmRzTGlzdCA9ICF0aGlzLmhpZGVGcmllbmRzTGlzdFxuICAgIC8vICAgICB0aGlzLmhpZGVGcmllbmRzTGlzdENoYW5nZS5lbWl0KHRoaXMuaGlkZUZyaWVuZHNMaXN0KVxuICAgIC8vIH1cbiAgICBvbkNsb3NlV2luZG93Q2xpY2soY2xpY2s6Ym9vbGVhbil7XG5cbiAgICAgICAgdGhpcy5vbkNsb3NlV2luZG93Q2xpY2tlZC5lbWl0KGNsaWNrKVxuXG5cblxuICAgIH1cbn1cbi8qIGVzbGludC1lbmFibGUgKi8iLCI8bGluayAqbmdJZj1cImN1c3RvbVRoZW1lXCIgcmVsPVwic3R5bGVzaGVldFwiIFtocmVmXT0nY3VzdG9tVGhlbWUgfCBzYW5pdGl6ZSc+XG5cbjxkaXYgaWQ9XCJuZy1jaGF0XCIgKm5nSWY9XCIhaXNEaXNhYmxlZCAmJiBpc0Jvb3RzdHJhcHBlZCAmJiAhdW5zdXBwb3J0ZWRWaWV3cG9ydFwiIFtuZ0NsYXNzXT1cInRoZW1lXCI+XG4gICAgPG5nLWNoYXQtZnJpZW5kcy1saXN0XG4gICAgICAgIFtsb2NhbGl6YXRpb25dPVwibG9jYWxpemF0aW9uXCJcbiAgICAgICAgW3Nob3VsZERpc3BsYXldPVwiIWhpZGVGcmllbmRzTGlzdFwiXG4gICAgICAgIFt1c2VySWRdPVwidXNlcklkXCJcbiAgICAgICAgW2lzQ29sbGFwc2VkXT1cImlzQ29sbGFwc2VkXCJcbiAgICAgICAgW3NlYXJjaEVuYWJsZWRdPVwic2VhcmNoRW5hYmxlZFwiXG4gICAgICAgIFtwYXJ0aWNpcGFudHNdPVwicGFydGljaXBhbnRzXCJcbiAgICAgICAgW3BhcnRpY2lwYW50c1Jlc3BvbnNlXT1cInBhcnRpY2lwYW50c1Jlc3BvbnNlXCJcbiAgICAgICAgW3BhcnRpY2lwYW50c0ludGVyYWN0ZWRXaXRoXT1cInBhcnRpY2lwYW50c0ludGVyYWN0ZWRXaXRoXCJcbiAgICAgICAgW3dpbmRvd3NdPVwid2luZG93c1wiXG4gICAgICAgIFtjdXJyZW50QWN0aXZlT3B0aW9uXT1cImN1cnJlbnRBY3RpdmVPcHRpb25cIlxuICAgICAgICAob25QYXJ0aWNpcGFudENsaWNrZWQpPVwib25QYXJ0aWNpcGFudENsaWNrZWRGcm9tRnJpZW5kc0xpc3QoJGV2ZW50KVwiXG4gICAgICAgIChvbk9wdGlvblByb21wdENhbmNlbGVkKT1cIm9uT3B0aW9uUHJvbXB0Q2FuY2VsZWQoKVwiXG4gICAgICAgIChvbk9wdGlvblByb21wdENvbmZpcm1lZCk9XCJvbk9wdGlvblByb21wdENvbmZpcm1lZCgkZXZlbnQpXCJcbiAgICAgICAgKG9uQ2xvc2VXaW5kb3dDbGljayk9XCJvbkNsb3NlV2luZG93Q2xpY2soJGV2ZW50KVwiXG4gICAgPlxuICAgIDwvbmctY2hhdC1mcmllbmRzLWxpc3Q+XG5cbiAgICA8ZGl2ICpuZ0Zvcj1cImxldCB3aW5kb3cgb2Ygd2luZG93czsgbGV0IGkgPSBpbmRleFwiIFtuZ0NsYXNzXT1cInsnbmctY2hhdC13aW5kb3cnOiB0cnVlLCAncHJpbWFyeS1vdXRsaW5lLWNvbG9yJzogdHJ1ZSwgJ25nLWNoYXQtd2luZG93LWNvbGxhcHNlZCc6IHdpbmRvdy5pc0NvbGxhcHNlZH1cIiBbbmdTdHlsZV09XCJ7J3JpZ2h0JzogKCFoaWRlRnJpZW5kc0xpc3QgPyBmcmllbmRzTGlzdFdpZHRoIDogMCkgKyAyMCArIHdpbmRvd1NpemVGYWN0b3IgKiBpICsgJ3B4J31cIj5cbiAgICAgICAgPG5nLWNoYXQtd2luZG93XG4gICAgICAgICAgICAjY2hhdFdpbmRvd1xuICAgICAgICAgICAgW2ZpbGVVcGxvYWRBZGFwdGVyXT1cImZpbGVVcGxvYWRBZGFwdGVyXCJcbiAgICAgICAgICAgIFtsb2NhbGl6YXRpb25dPVwibG9jYWxpemF0aW9uXCJcbiAgICAgICAgICAgIFt1c2VySWRdPVwidXNlcklkXCJcbiAgICAgICAgICAgIFt3aW5kb3ddPVwid2luZG93XCJcbiAgICAgICAgICAgIFtzaG93T3B0aW9uc109XCJncm91cEFkYXB0ZXJcIlxuICAgICAgICAgICAgW2Vtb2ppc0VuYWJsZWRdPVwiZW1vamlzRW5hYmxlZFwiXG4gICAgICAgICAgICBbbGlua2Z5RW5hYmxlZF09XCJsaW5rZnlFbmFibGVkXCJcbiAgICAgICAgICAgIFtzaG93TWVzc2FnZURhdGVdPVwic2hvd01lc3NhZ2VEYXRlXCJcbiAgICAgICAgICAgIFttZXNzYWdlRGF0ZVBpcGVGb3JtYXRdPVwibWVzc2FnZURhdGVQaXBlRm9ybWF0XCJcbiAgICAgICAgICAgIFtoYXNQYWdlZEhpc3RvcnldPVwiaGFzUGFnZWRIaXN0b3J5XCJcbiAgICAgICAgICAgIChvbk1lc3NhZ2VzU2Vlbik9XCJvbldpbmRvd01lc3NhZ2VzU2VlbigkZXZlbnQpXCJcbiAgICAgICAgICAgIChvbk1lc3NhZ2VTZW50KT1cIm9uV2luZG93TWVzc2FnZVNlbnQoJGV2ZW50KVwiXG4gICAgICAgICAgICAob25UYWJUcmlnZ2VyZWQpPVwib25XaW5kb3dUYWJUcmlnZ2VyZWQoJGV2ZW50KVwiXG4gICAgICAgICAgICAob25DaGF0V2luZG93Q2xvc2VkKT1cIm9uV2luZG93Q2hhdENsb3NlZCgkZXZlbnQpXCJcbiAgICAgICAgICAgIChvbk9wdGlvblRyaWdnZXJlZCk9XCJvbldpbmRvd09wdGlvblRyaWdnZXJlZCgkZXZlbnQpXCJcbiAgICAgICAgICAgIChvbkxvYWRIaXN0b3J5VHJpZ2dlcmVkKT1cImZldGNoTWVzc2FnZUhpc3RvcnkoJGV2ZW50KVwiXG4gICAgICAgID5cbiAgICAgICAgPC9uZy1jaGF0LXdpbmRvdz5cbiAgICA8L2Rpdj5cbjwvZGl2PlxuIl19