@sinequa/assistant 3.9.2 → 3.9.3

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 (43) hide show
  1. package/chat/chat.component.d.ts +35 -38
  2. package/chat/chat.service.d.ts +190 -84
  3. package/chat/debug-message/debug-message-details/debug-message-details.component.d.ts +19 -0
  4. package/chat/debug-message/debug-message.component.d.ts +9 -12
  5. package/chat/debug-message/debug-message.service.d.ts +15 -0
  6. package/chat/documents-upload/document-list/document-list.component.d.ts +1 -0
  7. package/chat/public-api.d.ts +0 -2
  8. package/chat/saved-chats/i18n/en.json +1 -1
  9. package/chat/saved-chats/i18n/fr.json +1 -1
  10. package/chat/saved-chats/saved-chats.component.d.ts +1 -0
  11. package/chat/saved-chats/saved-chats.service.d.ts +27 -0
  12. package/chat/services/assistant-configuration.service.d.ts +34 -0
  13. package/chat/services/assistant-metadata.service.d.ts +18 -0
  14. package/chat/services/assistant-tokens-tracking.service.d.ts +23 -0
  15. package/chat/services/assistant-ws-frames.service.d.ts +50 -0
  16. package/chat/services/signalR-connection.service.d.ts +25 -0
  17. package/chat/types.d.ts +12 -3
  18. package/chat/utils/utils.service.d.ts +67 -0
  19. package/esm2022/chat/chat.component.mjs +198 -227
  20. package/esm2022/chat/chat.service.mjs +450 -267
  21. package/esm2022/chat/debug-message/debug-message-details/debug-message-details.component.mjs +43 -0
  22. package/esm2022/chat/debug-message/debug-message.component.mjs +27 -30
  23. package/esm2022/chat/debug-message/debug-message.service.mjs +52 -0
  24. package/esm2022/chat/dialogs/rename-saved-chat.component.mjs +6 -5
  25. package/esm2022/chat/documents-upload/document-list/document-list.component.mjs +4 -2
  26. package/esm2022/chat/public-api.mjs +1 -3
  27. package/esm2022/chat/saved-chats/saved-chats.component.mjs +11 -10
  28. package/esm2022/chat/saved-chats/saved-chats.service.mjs +165 -0
  29. package/esm2022/chat/services/assistant-configuration.service.mjs +171 -0
  30. package/esm2022/chat/services/assistant-metadata.service.mjs +67 -0
  31. package/esm2022/chat/services/assistant-tokens-tracking.service.mjs +57 -0
  32. package/esm2022/chat/services/assistant-ws-frames.service.mjs +392 -0
  33. package/esm2022/chat/services/signalR-connection.service.mjs +109 -0
  34. package/esm2022/chat/types.mjs +1 -1
  35. package/esm2022/chat/unified-plugins/embedded-image-reference.plugin.mjs +2 -3
  36. package/esm2022/chat/utils/utils.service.mjs +170 -0
  37. package/fesm2022/sinequa-assistant-chat.mjs +2020 -1648
  38. package/fesm2022/sinequa-assistant-chat.mjs.map +1 -1
  39. package/package.json +1 -1
  40. package/chat/rest-chat.service.d.ts +0 -31
  41. package/chat/websocket-chat.service.d.ts +0 -102
  42. package/esm2022/chat/rest-chat.service.mjs +0 -300
  43. package/esm2022/chat/websocket-chat.service.mjs +0 -659
@@ -3,36 +3,33 @@ import { ChangeDetectionStrategy, ChangeDetectorRef, Component, ContentChild, Ev
3
3
  import { FormsModule } from "@angular/forms";
4
4
  import { TranslocoPipe, TranslocoService, provideTranslocoScope } from '@jsverse/transloco';
5
5
  import { HubConnectionState } from "@microsoft/signalr";
6
- import { BehaviorSubject, Subscription, combineLatest, filter, fromEvent, map, merge, of, switchMap, take, tap } from "rxjs";
7
- import { isAuthenticated, setGlobalConfig } from "@sinequa/atomic";
6
+ import { BehaviorSubject, Subscription, combineLatest, filter, fromEvent, merge, of, switchMap, take, tap } from "rxjs";
7
+ import { guid, isAuthenticated, setGlobalConfig } from "@sinequa/atomic";
8
8
  import { ChatMessageComponent } from "./chat-message/chat-message.component";
9
9
  import { ChatService } from "./chat.service";
10
+ import { AssistantUtils } from "./utils/utils.service";
10
11
  import { DebugMessageComponent } from "./debug-message/debug-message.component";
11
12
  import { InstanceManagerService } from "./instance-manager.service";
12
- import { RestChatService } from "./rest-chat.service";
13
13
  import { NotificationsService } from "./services/notification.service";
14
14
  import { PrincipalService } from "./services/principal.service";
15
15
  import { SearchService } from "./services/search.service";
16
16
  import { TokenProgressBarComponent } from "./token-progress-bar/token-progress-bar.component";
17
17
  import { TooltipDirective } from "./tooltip/tooltip.directive";
18
- import { WebSocketChatService } from "./websocket-chat.service";
19
18
  import * as i0 from "@angular/core";
20
19
  import * as i1 from "@angular/common";
21
20
  import * as i2 from "@angular/forms";
22
21
  export class ChatComponent {
23
22
  constructor() {
24
- this.websocketService = inject(WebSocketChatService);
25
- this.restService = inject(RestChatService);
23
+ this.chatService = inject(ChatService);
26
24
  this.instanceManagerService = inject(InstanceManagerService);
27
25
  this.searchService = inject(SearchService);
28
26
  this.principalService = inject(PrincipalService);
29
27
  this.cdr = inject(ChangeDetectorRef);
30
28
  this.notificationsService = inject(NotificationsService);
31
29
  this.transloco = inject(TranslocoService);
30
+ this.assistantUtils = inject(AssistantUtils);
32
31
  /** Define the query to use to fetch answers */
33
32
  this.query = this.searchService.query;
34
- /** Define the protocol to be used for this chat instance*/
35
- this.protocol = "WEBSOCKET";
36
33
  /** Map of listeners overriding default registered ones*/
37
34
  this.messageHandlers = new Map();
38
35
  /** When the assistant answer a user question, automatically scroll down to the bottom of the discussion */
@@ -87,10 +84,8 @@ export class ChatComponent {
87
84
  if (this.appConfig) {
88
85
  setGlobalConfig(this.appConfig);
89
86
  }
90
- this._sub.add(of(isAuthenticated()).pipe(tap(_ => this.instantiateChatService()), map(_ => this.chatService.initChatConfig()), switchMap(() => this.chatService.initConfig$), filter(initConfig => !!initConfig), switchMap(_ => this.chatService.init()), switchMap(_ => this.chatService.initProcess$), filter(success => !!success), tap(_ => {
91
- if (this.chatService instanceof WebSocketChatService) {
92
- this.connection.emit(this.chatService.connection);
93
- }
87
+ this._sub.add(of(isAuthenticated()).pipe(tap(_ => this.instantiateChatService()), switchMap(_ => this.chatService.init()), switchMap(_ => this.chatService.initProcess$.pipe(filter(Boolean))), tap(_ => {
88
+ this.connection.emit(this.chatService.connection);
94
89
  this.onLoadChat();
95
90
  }), tap(_ => this.chatService.overrideUser()), switchMap(_ => this.chatService.userOverride$), switchMap(_ => this.chatService.assistantConfig$), tap(config => {
96
91
  this.isAdminOrDeletedAdmin = this.principalService.principal.isAdministrator || this.principalService.principal.isDelegatedAdmin || false;
@@ -123,28 +118,15 @@ export class ChatComponent {
123
118
  this._sub.unsubscribe();
124
119
  this._dataSubscription?.unsubscribe();
125
120
  this._reloadSubscription?.unsubscribe();
126
- if (this.chatService instanceof WebSocketChatService) {
127
- this.chatService.stopConnection();
128
- }
121
+ this.chatService.stopConnection();
129
122
  }
130
123
  get isAdmin() {
131
124
  return this.principalService.principal?.isAdministrator || false;
132
125
  }
133
126
  /**
134
- * Instantiate the chat service based on the provided @input protocol
135
- * This chat service instance will then be stored in the instanceManagerService with provided @input instanceId as a key
127
+ * This chat service instance is stored in the instanceManagerService with provided @input instanceId as a key
136
128
  */
137
129
  instantiateChatService() {
138
- switch (this.protocol) {
139
- case 'REST':
140
- this.chatService = this.restService;
141
- break;
142
- case 'WEBSOCKET':
143
- this.chatService = this.websocketService;
144
- break;
145
- default:
146
- throw new Error(`Could not found a ChatService implementation corresponding to the provided protocol: '${this.protocol}'`);
147
- }
148
130
  this.chatService.setChatInstanceId(this.instanceId);
149
131
  this.instanceManagerService.storeInstance(this.instanceId, this.chatService);
150
132
  }
@@ -162,7 +144,7 @@ export class ChatComponent {
162
144
  _handleChanges() {
163
145
  const changes = this.changes$.value;
164
146
  // If the chat service is a WebSocketChatService, handle the override of the message handlers if exists
165
- if (changes?.messageHandlers && this.messageHandlers && this.chatService instanceof WebSocketChatService) {
147
+ if (changes?.messageHandlers && this.messageHandlers) {
166
148
  this.chatService.overrideMessageHandlers(this.messageHandlers);
167
149
  }
168
150
  /**
@@ -171,18 +153,18 @@ export class ChatComponent {
171
153
  */
172
154
  if (!this.firstChangesHandled || changes?.chat) {
173
155
  const openChat = () => {
174
- if (this.messages$.value) {
156
+ if (this.messages$.value && this.config.savedChatSettings?.enabled) {
175
157
  this.chatService.listSavedChat(); // Refresh the list of saved chats
176
158
  }
177
159
  this.openChat(this.chat.messages);
178
160
  };
179
161
  this.chatService.generateChatId();
180
162
  if (this.chat) {
181
- this.chatService.generateAuditEvent('ast-new-chat', { 'configuration': JSON.stringify(this.chatService.assistantConfig$.value), 'chat-init': JSON.stringify(this.chat) });
163
+ this.chatService.generateAuditEvent('ast-chat.new', { 'configuration': JSON.stringify(this.chatService.assistantConfig$.value), 'chat-init': JSON.stringify(this.chat) });
182
164
  openChat();
183
165
  }
184
166
  else {
185
- this.chatService.generateAuditEvent('ast-new-chat', { 'configuration': JSON.stringify(this.chatService.assistantConfig$.value) });
167
+ this.chatService.generateAuditEvent('ast-chat.new', { 'configuration': JSON.stringify(this.chatService.assistantConfig$.value) });
186
168
  this.loadDefaultChat();
187
169
  }
188
170
  }
@@ -257,13 +239,12 @@ export class ChatComponent {
257
239
  * generates a new chat audit event, and handles the query mode.
258
240
  */
259
241
  _triggerReloadAfterQueryChange() {
260
- const systemMsg = { role: 'system', content: this.config.defaultValues.systemPrompt, additionalProperties: { display: false } };
242
+ const systemMsg = { role: 'system', content: this.config.defaultValues.systemPrompt, additionalProperties: { display: false, messageId: guid() } };
261
243
  // backward compatibility with old configuration files
262
244
  const userPrompt = this.config.defaultValues.userPrompt.replace(/\{\{(.*?)\}\}/g, '[[$1]]');
263
- const userMsg = { role: 'user', content: ChatService.formatPrompt(this.transloco.translate(userPrompt), { principal: this.principalService.principal }), additionalProperties: { display: this.config.modeSettings.displayUserPrompt } };
264
- this.chatService.setSavedChatId(undefined); // Reset the savedChatId
245
+ const userMsg = { role: 'user', content: AssistantUtils.formatPrompt(this.transloco.translate(userPrompt), { principal: this.principalService.principal }), additionalProperties: { display: this.config.modeSettings.displayUserPrompt, messageId: guid() } };
265
246
  this.chatService.generateChatId(); // Generate a new chatId
266
- this.chatService.generateAuditEvent('ast-new-chat', { 'configuration': JSON.stringify(this.chatService.assistantConfig$.value) }); // Generate a new chat audit event
247
+ this.chatService.generateAuditEvent('ast-chat.new', { 'configuration': JSON.stringify(this.chatService.assistantConfig$.value) }); // Generate a new chat audit event
267
248
  this._handleQueryMode(systemMsg, userMsg);
268
249
  }
269
250
  /**
@@ -302,13 +283,13 @@ export class ChatComponent {
302
283
  }
303
284
  if (this.question.trim() && this.messages$.value && this.chatService.chatHistory) {
304
285
  // When the user submits a question, if the user is editing a previous message, remove all subsequent messages from the chat history
305
- if (this.messageToEdit !== undefined) {
286
+ if (this.indexMessageToEdit !== undefined) {
306
287
  // Update the messages in the UI
307
- this.messages$.next(this.messages$.value.slice(0, this.messageToEdit));
288
+ this.messages$.next(this.messages$.value.slice(0, this.indexMessageToEdit));
308
289
  // Update the raw messages in the chat history which is the clean version used to make the next request
309
- this.chatService.chatHistory = this.chatService.chatHistory.slice(0, this.remappedMessageToEdit);
310
- this.messageToEdit = undefined;
311
- this.remappedMessageToEdit = undefined;
290
+ this.chatService.chatHistory = this.chatService.chatHistory.slice(0, this.rankMessageToEdit);
291
+ this.indexMessageToEdit = undefined;
292
+ this.rankMessageToEdit = undefined;
312
293
  }
313
294
  // Remove the search warning message if exists
314
295
  if (this.chatService.chatHistory.at(-1)?.role === 'search-warning') {
@@ -331,11 +312,12 @@ export class ChatComponent {
331
312
  _fetchAnswer(question, conversation) {
332
313
  // merge additionalWorkflowProperties from the chat component and the customization JSON
333
314
  const additionalWorkflowProperties = { ...this.config.additionalWorkflowProperties, ...this.additionalWorkflowProperties };
334
- const userMsg = { role: 'user', content: question, additionalProperties: { display: true, isUserInput: true, additionalWorkflowProperties } };
315
+ const userMsg = { role: 'user', content: question, additionalProperties: { display: true, messageId: guid(), isUserInput: true, additionalWorkflowProperties } };
335
316
  const messages = [...conversation, userMsg];
336
- this.messages$.next(messages);
317
+ this.messages$.next(messages); // Update the messages in the UI with the new user message
318
+ this.chatService.chatHistory = messages; // Update the chat history with the new user message
337
319
  this.fetch(messages);
338
- this.chatService.generateAuditEvent('ast-message', { ...this._defineMessageAuditDetails(userMsg, messages.length - 1), 'query': JSON.stringify(this.query), 'is-user-input': true, 'enabled-functions': this.config.defaultValues.functions?.filter(func => func.enabled).map(func => func.name), 'additional-workflow-properties': JSON.stringify(additionalWorkflowProperties) });
320
+ this.chatService.generateAuditEvent('ast-message.message', { ...this._defineMessageAuditDetails(userMsg), 'query': JSON.stringify(this.query), 'is-user-input': true, 'enabled-functions': this.config.defaultValues.functions?.filter(func => func.enabled).map(func => func.name), 'additional-workflow-properties': JSON.stringify(additionalWorkflowProperties) });
339
321
  }
340
322
  /**
341
323
  * Depending on the connection's state :
@@ -355,17 +337,14 @@ export class ChatComponent {
355
337
  this._dataSubscription?.unsubscribe();
356
338
  this._dataSubscription = this.chatService.fetch(messages, this.query)
357
339
  .subscribe({
358
- next: res => {
359
- this.lastFetchDuration = res.executionTimeMilliseconds;
360
- this.updateData(res.history);
361
- },
340
+ next: res => this.updateData(res.history),
362
341
  error: () => {
363
342
  this._updateConnectionStatus();
364
343
  if (!this.isConnected) {
365
344
  const message = {
366
345
  role: 'connection-error',
367
346
  content: { type: "text", text: this.transloco.translate(this.config.connectionSettings.connectionErrorMessage) },
368
- additionalProperties: { display: true }
347
+ additionalProperties: { display: true, messageId: guid() }
369
348
  };
370
349
  this.messages$.next([...messages, message]);
371
350
  }
@@ -383,7 +362,7 @@ export class ChatComponent {
383
362
  });
384
363
  }
385
364
  else {
386
- const message = { role: 'connection-error', content: this.transloco.translate(this.config.connectionSettings.connectionErrorMessage), additionalProperties: { display: true } };
365
+ const message = { role: 'connection-error', content: this.transloco.translate(this.config.connectionSettings.connectionErrorMessage), additionalProperties: { display: true, messageId: guid() } };
387
366
  this.messages$.next([...messages, message]);
388
367
  }
389
368
  if (this.automaticScrollToLastResponse) {
@@ -398,60 +377,58 @@ export class ChatComponent {
398
377
  * * If failed => increase the number of retrial attempts
399
378
  */
400
379
  retryFetch() {
401
- if (this.chatService instanceof WebSocketChatService) {
402
- // A one-time listener for reconnected event
403
- const onReconnectedHandler = () => {
404
- // Get the messages without the last one (the connection error message)
405
- const messages = this.messages$.value.slice(0, -1);
406
- // Find the last "user" message in the messages list
407
- let index = messages.length - 1;
408
- while (index >= 0 && messages[index].role !== 'user') {
409
- index--;
410
- }
411
- // If a user message is found (and it should always be the case), remove all subsequent messages from the chat history
412
- // Update the messages in the UI
413
- // and fetch the answer from the assistant
414
- if (index >= 0) {
415
- this.messages$.next(this.messages$.value.slice(0, index + 1));
416
- const remappedIndex = this._remapIndexInChatHistory(index);
417
- this.chatService.chatHistory = this.chatService.chatHistory.slice(0, remappedIndex + 1);
418
- this.fetch(this.chatService.chatHistory);
380
+ // A one-time listener for reconnected event
381
+ const onReconnectedHandler = () => {
382
+ // Get the messages without the last one (the connection error message)
383
+ const messages = this.messages$.value.slice(0, -1);
384
+ // Find the last "user" message in the messages list
385
+ let index = messages.length - 1;
386
+ while (index >= 0 && messages[index].role !== 'user') {
387
+ index--;
388
+ }
389
+ // If a user message is found (and it should always be the case), remove all subsequent messages from the chat history
390
+ // Update the messages in the UI
391
+ // and fetch the answer from the assistant
392
+ if (index >= 0) {
393
+ this.messages$.next(this.messages$.value.slice(0, index + 1));
394
+ const remappedIndex = this.assistantUtils.getMessageRankInChatHistory(this.chatService.chatHistory, messages[index].additionalProperties.messageId);
395
+ this.chatService.chatHistory = this.chatService.chatHistory.slice(0, remappedIndex + 1);
396
+ this.fetch(this.chatService.chatHistory);
397
+ }
398
+ this.retrialAttempts = undefined; // Reset the number of retrial attempts
399
+ /**
400
+ * To remove the handler for onreconnected() after it's been registered,cannot directly use off() like you would for normal events registered with connection.on().
401
+ * Instead, you need to explicitly remove or reset the handler by assigning it to null or an empty function
402
+ */
403
+ this.chatService.connection.onreconnected(() => { });
404
+ // Reset the flag to ensure the handler is registered again when needed
405
+ this._isReconnectedListenerRegistered = false;
406
+ };
407
+ // Depending on the connection's state, take the appropriate action
408
+ switch (this.chatService.connection.state) {
409
+ case HubConnectionState.Connected:
410
+ // If the connection is re-established in the meantime, fetch the messages
411
+ onReconnectedHandler();
412
+ break;
413
+ case HubConnectionState.Reconnecting:
414
+ // Attach the reconnected listener if not already registered
415
+ if (!this._isReconnectedListenerRegistered) {
416
+ this.chatService.connection.onreconnected(onReconnectedHandler);
417
+ this._isReconnectedListenerRegistered = true;
419
418
  }
420
- this.retrialAttempts = undefined; // Reset the number of retrial attempts
421
- /**
422
- * To remove the handler for onreconnected() after it's been registered,cannot directly use off() like you would for normal events registered with connection.on().
423
- * Instead, you need to explicitly remove or reset the handler by assigning it to null or an empty function
424
- */
425
- this.chatService.connection.onreconnected(() => { });
426
- // Reset the flag to ensure the handler is registered again when needed
427
- this._isReconnectedListenerRegistered = false;
428
- };
429
- // Depending on the connection's state, take the appropriate action
430
- switch (this.chatService.connection.state) {
431
- case HubConnectionState.Connected:
432
- // If the connection is re-established in the meantime, fetch the messages
433
- onReconnectedHandler();
434
- break;
435
- case HubConnectionState.Reconnecting:
436
- // Attach the reconnected listener if not already registered
437
- if (!this._isReconnectedListenerRegistered) {
438
- this.chatService.connection.onreconnected(onReconnectedHandler);
439
- this._isReconnectedListenerRegistered = true;
440
- }
441
- // Increase the number of retrial attempts
419
+ // Increase the number of retrial attempts
420
+ this.retrialAttempts = this.retrialAttempts ? this.retrialAttempts + 1 : 1;
421
+ break;
422
+ case HubConnectionState.Disconnected:
423
+ // Start the new connection
424
+ this.chatService.startConnection()
425
+ .then(() => onReconnectedHandler())
426
+ .catch(() => {
442
427
  this.retrialAttempts = this.retrialAttempts ? this.retrialAttempts + 1 : 1;
443
- break;
444
- case HubConnectionState.Disconnected:
445
- // Start the new connection
446
- this.chatService.startConnection()
447
- .then(() => onReconnectedHandler())
448
- .catch(() => {
449
- this.retrialAttempts = this.retrialAttempts ? this.retrialAttempts + 1 : 1;
450
- });
451
- break;
452
- default:
453
- break;
454
- }
428
+ });
429
+ break;
430
+ default:
431
+ break;
455
432
  }
456
433
  }
457
434
  /**
@@ -459,7 +436,7 @@ export class ChatComponent {
459
436
  * For the REST protocol, the connection is always considered connected (for the moment).
460
437
  */
461
438
  _updateConnectionStatus() {
462
- this.isConnected = (this.chatService instanceof WebSocketChatService) ? this.chatService.connection.state === HubConnectionState.Connected : true;
439
+ this.isConnected = this.chatService.connection.state === HubConnectionState.Connected;
463
440
  }
464
441
  /**
465
442
  * Update the UI with the new messages
@@ -504,10 +481,11 @@ export class ChatComponent {
504
481
  if (!!this.chatService.streaming$.value || !!this.chatService.stoppingGeneration$.value) {
505
482
  return;
506
483
  }
507
- this.chatService.setSavedChatId(undefined); // Reset the savedChatId
508
484
  this.chatService.generateChatId(); // Generate a new chatId
509
- this.chatService.listSavedChat(); // Refresh the list of saved chats
510
- this.chatService.generateAuditEvent('ast-new-chat', { 'configuration': JSON.stringify(this.chatService.assistantConfig$.value) }); // Generate a new chat audit event
485
+ if (this.config.savedChatSettings?.enabled) {
486
+ this.chatService.listSavedChat(); // Refresh the list of saved chats
487
+ }
488
+ this.chatService.generateAuditEvent('ast-chat.new', { 'configuration': JSON.stringify(this.chatService.assistantConfig$.value) }); // Generate a new chat audit event
511
489
  this.loadDefaultChat(); // Start a new chat
512
490
  }
513
491
  /**
@@ -529,7 +507,7 @@ export class ChatComponent {
529
507
  console.error(`No action is defined for attaching a document to the assistant "${this.instanceId}"`);
530
508
  return;
531
509
  }
532
- const userMsg = { role: 'user', content: '', additionalProperties: { display: false, isUserInput: false, type: "Action", forcedWorkflow: attachDocAction.forcedWorkflow, forcedWorkflowProperties: { ...(attachDocAction.forcedWorkflowProperties || {}), ids }, additionalWorkflowProperties: this.config.additionalWorkflowProperties } };
510
+ const userMsg = { role: 'user', content: '', additionalProperties: { display: false, messageId: guid(), isUserInput: false, type: "Action", forcedWorkflow: attachDocAction.forcedWorkflow, forcedWorkflowProperties: { ...(attachDocAction.forcedWorkflowProperties || {}), ids }, additionalWorkflowProperties: this.config.additionalWorkflowProperties } };
533
511
  // Remove the search warning message if exists
534
512
  if (this.chatService.chatHistory.at(-1)?.role === 'search-warning') {
535
513
  this.chatService.chatHistory.pop();
@@ -549,10 +527,10 @@ export class ChatComponent {
549
527
  */
550
528
  loadDefaultChat() {
551
529
  // Define the default system prompt and user prompt messages
552
- const systemMsg = { role: 'system', content: this.config.defaultValues.systemPrompt, additionalProperties: { display: false } };
530
+ const systemMsg = { role: 'system', content: this.config.defaultValues.systemPrompt, additionalProperties: { display: false, messageId: guid() } };
553
531
  // backward compatibility with old configuration files
554
532
  const userPrompt = this.config.defaultValues.userPrompt.replace(/\{\{(.*?)\}\}/g, '[[$1]]');
555
- const userMsg = { role: 'user', content: ChatService.formatPrompt(this.transloco.translate(userPrompt), { principal: this.principalService.principal }), additionalProperties: { display: this.config.modeSettings.displayUserPrompt } };
533
+ const userMsg = { role: 'user', content: AssistantUtils.formatPrompt(this.transloco.translate(userPrompt), { principal: this.principalService.principal }), additionalProperties: { display: this.config.modeSettings.displayUserPrompt, messageId: guid() } };
556
534
  if (this.config.modeSettings.initialization.event === 'Query') {
557
535
  this._handleQueryMode(systemMsg, userMsg);
558
536
  }
@@ -573,12 +551,12 @@ export class ChatComponent {
573
551
  _handlePromptMode(systemMsg, userMsg) {
574
552
  if (this.config.modeSettings.sendUserPrompt) {
575
553
  this.openChat([systemMsg, userMsg]);
576
- this.chatService.generateAuditEvent('ast-message', this._defineMessageAuditDetails(systemMsg, 0));
577
- this.chatService.generateAuditEvent('ast-message', this._defineMessageAuditDetails(userMsg, 1));
554
+ this.chatService.generateAuditEvent('ast-message.message', this._defineMessageAuditDetails(systemMsg));
555
+ this.chatService.generateAuditEvent('ast-message.message', this._defineMessageAuditDetails(userMsg));
578
556
  }
579
557
  else {
580
558
  this.openChat([systemMsg]);
581
- this.chatService.generateAuditEvent('ast-message', this._defineMessageAuditDetails(systemMsg, 0));
559
+ this.chatService.generateAuditEvent('ast-message.message', this._defineMessageAuditDetails(systemMsg));
582
560
  }
583
561
  }
584
562
  /**
@@ -590,33 +568,40 @@ export class ChatComponent {
590
568
  */
591
569
  _handleQueryMode(systemMsg, userMsg) {
592
570
  if (!!this.query.text) {
593
- const userQueryMsg = { role: 'user', content: this.query.text, additionalProperties: { display: this.config.modeSettings.initialization.displayUserQuery, query: this.query, forcedWorkflow: this.config.modeSettings.initialization.forcedWorkflow, forcedFunction: this.config.modeSettings.initialization.forcedFunction, isUserInput: true, additionalWorkflowProperties: this.config.additionalWorkflowProperties } };
571
+ const userQueryMsg = { role: 'user', content: this.query.text, additionalProperties: { display: this.config.modeSettings.initialization.displayUserQuery, messageId: guid(), query: this.query, forcedWorkflow: this.config.modeSettings.initialization.forcedWorkflow, forcedFunction: this.config.modeSettings.initialization.forcedFunction, isUserInput: true, additionalWorkflowProperties: this.config.additionalWorkflowProperties } };
594
572
  if (this.config.modeSettings.sendUserPrompt) {
595
573
  this.openChat([systemMsg, userMsg, userQueryMsg]);
596
- this.chatService.generateAuditEvent('ast-message', this._defineMessageAuditDetails(systemMsg, 0));
597
- this.chatService.generateAuditEvent('ast-message', this._defineMessageAuditDetails(userMsg, 1));
598
- this.chatService.generateAuditEvent('ast-message', { ...this._defineMessageAuditDetails(userQueryMsg, 2), 'query': JSON.stringify(this.query), 'is-user-input': true, 'forced-workflow': this.config.modeSettings.initialization.forcedWorkflow, 'forced-function': this.config.modeSettings.initialization.forcedFunction, 'enabled-functions': this.config.defaultValues.functions?.filter(func => func.enabled).map(func => func.name), 'additional-workflow-properties': JSON.stringify(this.config.additionalWorkflowProperties) });
574
+ this.chatService.generateAuditEvent('ast-message.message', this._defineMessageAuditDetails(systemMsg));
575
+ this.chatService.generateAuditEvent('ast-message.message', this._defineMessageAuditDetails(userMsg));
576
+ this.chatService.generateAuditEvent('ast-message.message', { ...this._defineMessageAuditDetails(userQueryMsg), 'query': JSON.stringify(this.query), 'is-user-input': true, 'forced-workflow': this.config.modeSettings.initialization.forcedWorkflow, 'forced-function': this.config.modeSettings.initialization.forcedFunction, 'enabled-functions': this.config.defaultValues.functions?.filter(func => func.enabled).map(func => func.name), 'additional-workflow-properties': JSON.stringify(this.config.additionalWorkflowProperties) });
599
577
  }
600
578
  else {
601
579
  this.openChat([systemMsg, userQueryMsg]);
602
- this.chatService.generateAuditEvent('ast-message', this._defineMessageAuditDetails(systemMsg, 0));
603
- this.chatService.generateAuditEvent('ast-message', { ...this._defineMessageAuditDetails(userQueryMsg, 1), 'query': JSON.stringify(this.query), 'is-user-input': true, 'forced-workflow': this.config.modeSettings.initialization.forcedWorkflow, 'forced-function': this.config.modeSettings.initialization.forcedFunction, 'enabled-functions': this.config.defaultValues.functions?.filter(func => func.enabled).map(func => func.name), 'additional-workflow-properties': JSON.stringify(this.config.additionalWorkflowProperties) });
580
+ this.chatService.generateAuditEvent('ast-message.message', this._defineMessageAuditDetails(systemMsg));
581
+ this.chatService.generateAuditEvent('ast-message.message', { ...this._defineMessageAuditDetails(userQueryMsg), 'query': JSON.stringify(this.query), 'is-user-input': true, 'forced-workflow': this.config.modeSettings.initialization.forcedWorkflow, 'forced-function': this.config.modeSettings.initialization.forcedFunction, 'enabled-functions': this.config.defaultValues.functions?.filter(func => func.enabled).map(func => func.name), 'additional-workflow-properties': JSON.stringify(this.config.additionalWorkflowProperties) });
604
582
  }
605
583
  }
606
584
  else {
607
- const warningMsg = { role: 'search-warning', content: this.transloco.translate(this.config.globalSettings.searchWarningMessage), additionalProperties: { display: true } };
585
+ const warningMsg = { role: 'search-warning', content: this.transloco.translate(this.config.globalSettings.searchWarningMessage), additionalProperties: { display: true, messageId: guid() } };
608
586
  this.openChat([systemMsg, warningMsg]);
609
- this.chatService.generateAuditEvent('ast-message', this._defineMessageAuditDetails(warningMsg, 0));
587
+ this.chatService.generateAuditEvent('ast-message.message', this._defineMessageAuditDetails(warningMsg));
610
588
  }
611
589
  }
612
- _defineMessageAuditDetails(message, rank) {
590
+ _defineMessageAuditDetails(message) {
591
+ const rank = this.assistantUtils.getMessageRankInChatHistory(this.chatService.chatHistory, message.additionalProperties.messageId);
613
592
  const details = {
614
- 'duration': this.lastFetchDuration || 0,
593
+ 'duration': 0,
615
594
  'role': message.role,
616
- 'rank': rank
595
+ 'rank': rank,
596
+ 'message-id': message.additionalProperties.messageId
617
597
  };
618
598
  if (!!this.config.auditSettings?.logContent) {
619
- details.text = message.content;
599
+ if (typeof message.content === 'string') {
600
+ details.text = message.content;
601
+ }
602
+ else if (Array.isArray(message.content)) {
603
+ details.text = message.content.find((msg) => msg.type === "text").text;
604
+ }
620
605
  }
621
606
  return details;
622
607
  }
@@ -625,26 +610,31 @@ export class ChatComponent {
625
610
  * If the last message is from the user, a request to the assistant is made to get an answer
626
611
  * If the last message is from the assistant, the conversation is loaded right away
627
612
  * @param messages The list of messages of the chat
628
- * @param savedChatId The id of the saved chat. If provided (ie. an existing discussion in the saved chat index), update the savedChatId in the chat service for the upcoming saved chat operations
613
+ * @param chatId The id of the discussion. If provided (ie. an existing discussion in the saved chat index), update the chatId in the chat service for the upcoming saved chat operations
629
614
  */
630
- openChat(messages, savedChatId) {
615
+ openChat(messages, chatId) {
631
616
  if (!messages || !Array.isArray(messages)) {
632
617
  console.error('Error occurs while trying to load the discussion. Invalid messages received :', messages);
633
618
  return;
634
619
  }
635
- if (savedChatId) {
636
- this.chatService.setSavedChatId(savedChatId);
637
- this.chatService.generateChatId(savedChatId);
620
+ if (chatId) {
621
+ this.chatService.generateChatId(chatId);
638
622
  }
623
+ // Ensure each message has a unique messageId
624
+ // This is necessary specially in case the assistant is started with a predefined history Or an old saved chat
625
+ const messagesWithIds = messages.map((msg) => {
626
+ msg.additionalProperties.messageId ??= guid();
627
+ return msg;
628
+ });
639
629
  this.resetChat();
640
- this.messages$.next(messages);
641
- this.chatService.chatHistory = messages;
630
+ this.messages$.next(messagesWithIds);
631
+ this.chatService.chatHistory = messagesWithIds;
642
632
  const lastMessage = messages.at(-1);
643
633
  if (lastMessage && lastMessage.role === 'user') {
644
- this.fetch(messages); // If the last message if from a user, an answer from the assistant is expected
634
+ this.fetch(messagesWithIds); // If the last message if from a user, an answer from the assistant is expected
645
635
  }
646
636
  else {
647
- this.updateData(messages); // If the last message if from the assistant, we can load the conversation right away
637
+ this.updateData(messagesWithIds); // If the last message if from the assistant, we can load the conversation right away
648
638
  this.terminateFetch();
649
639
  }
650
640
  this._addScrollListener();
@@ -676,7 +666,15 @@ export class ChatComponent {
676
666
  * The fetch subscription will be terminated.
677
667
  */
678
668
  stopGeneration() {
679
- this.chatService.stopGeneration().subscribe(() => this.terminateFetch());
669
+ this.chatService.stopGeneration().subscribe(() => {
670
+ // Remove the last message if it's an empty message
671
+ // This is due to the manner in which the chat service handles consecutive messages
672
+ const lastMessage = this.messages$.value?.at(-1);
673
+ if (this.isEmptyAssistantMessage(lastMessage)) {
674
+ this.messages$.next(this.messages$.value?.slice(0, -1));
675
+ }
676
+ this.terminateFetch();
677
+ });
680
678
  }
681
679
  /**
682
680
  * Terminate the fetch process by unsubscribing from the data subscription and updating the loading status to false.
@@ -699,35 +697,39 @@ export class ChatComponent {
699
697
  * Once the edited message is submitted, all subsequent messages starting from @param index will be removed from the history and the UI will be updated accordingly.
700
698
  * The assistant will regenerate a new answer based on the updated chat history.
701
699
  * ⚠️ If the assistant is streaming or stopping the generation, the operation is not allowed.
700
+ * @param message The user's message to edit
702
701
  * @param index The index of the user's message to edit
702
+ * @returns void
703
703
  */
704
- editMessage(index) {
704
+ editMessage(message, index) {
705
705
  if (!!this.chatService.streaming$.value || !!this.chatService.stoppingGeneration$.value) {
706
706
  return;
707
707
  }
708
- this.messageToEdit = index;
709
- this.remappedMessageToEdit = this._remapIndexInChatHistory(index);
708
+ this.indexMessageToEdit = index;
709
+ this.rankMessageToEdit = this.assistantUtils.getMessageRankInChatHistory(this.chatService.chatHistory, message.additionalProperties.messageId);
710
710
  // Get user message from both legacy and text message type
711
- const message = this.chatService.chatHistory[this._remapIndexInChatHistory(index)];
712
711
  this.question = typeof message.content === 'string' ? message.content : message.content[0].text;
713
- this.chatService.generateAuditEvent('edit.click', { 'rank': this._remapIndexInChatHistory(index) });
712
+ this.chatService.generateAuditEvent('ast-edit.click', { 'rank': this.rankMessageToEdit, 'message-id': message.additionalProperties.messageId });
714
713
  }
715
714
  /**
716
715
  * Copy a previous assistant message of the chat history to the clipboard.
717
- * @param index The index of the assistant's message to edit
716
+ * @param message The message to copy
717
+ * @param index The index of the message to copy
718
+ * @returns void
718
719
  */
719
- copyMessage(index) {
720
+ copyMessage(message, index) {
720
721
  // Remap the index in the chat history
721
- const idx = this._remapIndexInChatHistory(index);
722
- this.chatService.generateAuditEvent('ast-copy.click', { 'rank': idx });
722
+ const rank = this.assistantUtils.getMessageRankInChatHistory(this.chatService.chatHistory, message.additionalProperties.messageId);
723
+ this.chatService.generateAuditEvent('ast-copy.click', { 'rank': rank, 'message-id': message.additionalProperties.messageId });
723
724
  }
724
725
  /**
725
726
  * Starting from the provided index, remove all subsequent messages from the chat history and the UI accordingly.
726
727
  * The assistant will regenerate a new answer based on the updated chat history.
727
728
  * ⚠️ If the assistant is streaming or stopping the generation, the operation is not allowed.
729
+ * @param message The assistant's message to regenerate
728
730
  * @param index The index of the assistant's message to regenerate
729
731
  */
730
- regenerateMessage(index) {
732
+ regenerateMessage(message, index) {
731
733
  if (!!this.chatService.streaming$.value || !!this.chatService.stoppingGeneration$.value) {
732
734
  return;
733
735
  }
@@ -739,55 +741,15 @@ export class ChatComponent {
739
741
  // It should always be the case that i > 0
740
742
  if (i >= 0) {
741
743
  this.messages$.next(this.messages$.value.slice(0, i + 1));
742
- // Remap the index of this found first previous 'user' message in the chat history
743
- const idx = this._remapIndexInChatHistory(i);
744
+ // Rank of this found first previous 'user' message in the chat history
745
+ const rank = this.assistantUtils.getMessageRankInChatHistory(this.chatService.chatHistory, message.additionalProperties.messageId);
744
746
  // Define and Update the chat history based on which the assistant will generate a new answer
745
- this.chatService.chatHistory = this.chatService.chatHistory.slice(0, idx + 1);
747
+ this.chatService.chatHistory = this.chatService.chatHistory.slice(0, rank);
746
748
  // Fetch the answer
747
749
  this.fetch(this.chatService.chatHistory);
748
- this.chatService.generateAuditEvent('ast-regenerate.click', { 'rank': idx });
750
+ this.chatService.generateAuditEvent('ast-regenerate.click', { 'rank': rank, 'message-id': message.additionalProperties.messageId });
749
751
  }
750
752
  }
751
- /**
752
- * Remaps the index in the chat history.
753
- * The chat history is a list of messages where some messages can be hidden (display set to false).
754
- * The index provided as input is the index of the message in the chat history displayed in the UI.
755
- * This function should be removed once the backend is updated to add the ids of the messages in the chat history
756
- * @param index - The index to be remapped.
757
- */
758
- _remapIndexInChatHistory(index) {
759
- // a copy of the chat history is created to avoid modifying the original chat history.
760
- // Additionally, a rank is giving to each message.
761
- // All messages having role 'user' are updated with the display property set to true, this is mandatory to get the correct rank of the message in the chat history when the user message to remap is hidden
762
- const history = this.chatService.chatHistory
763
- .slice()
764
- .map((message, idx) => ({ ...message, additionalProperties: { ...message.additionalProperties, rank: idx } }))
765
- .map((message) => {
766
- if (message.role === "user") {
767
- return { ...message, additionalProperties: { ...message.additionalProperties, display: true } };
768
- }
769
- return message;
770
- });
771
- // Count the number of hidden messages (of role different then "user") in messages$ before the provided index
772
- // All messages having role 'user' are updated with the display property set to true, this is mandatory to get the correct rank of the message in the chat history when the user message to remap is hidden
773
- // This is mandatory to get the correct rank of the message in the chat history
774
- // Since some hidden messages (like 'system' messages) are not displayed in the UI but have been counted in the provided index
775
- const numberOfHiddenMessagesInMessages$BeforeIndex = this.messages$.value
776
- .slice(0, index)
777
- .map((message) => {
778
- if (message.role === "user") {
779
- return { ...message, additionalProperties: { ...message.additionalProperties, display: true } };
780
- }
781
- return message;
782
- })
783
- .filter(message => !message.additionalProperties.display).length;
784
- // remove all messages that have display set to false
785
- // this is mandatory since at the point of time when the assistant answers a question,
786
- // it might have some hidden messages (for example contextMessages) that are available in the chat history but don't figure in messages$ unless a new question is asked
787
- const filteredHistory = history.filter(message => message.additionalProperties.display);
788
- // return the index of the message in the filtered history
789
- return filteredHistory[index - numberOfHiddenMessagesInMessages$BeforeIndex].additionalProperties.rank;
790
- }
791
753
  /**
792
754
  * Handles the key up event for 'Backspace' and 'Enter' keys.
793
755
  * @param event - The keyboard event.
@@ -827,19 +789,19 @@ export class ChatComponent {
827
789
  /**
828
790
  * Send a "like" event on clicking on the thumb-up icon of an assistant's message
829
791
  * @param message The assistant message to like
830
- * @param rank The rank of the message to like
792
+ * @param index The index of the message to like
831
793
  */
832
- onLike(message, rank) {
794
+ onLike(message, index) {
833
795
  // Remap the index in the chat history
834
- const idx = this._remapIndexInChatHistory(rank);
835
- this.chatService.generateAuditEvent('ast-thumb-up.click', { rank: idx });
796
+ const rank = this.assistantUtils.getMessageRankInChatHistory(this.chatService.chatHistory, message.additionalProperties.messageId);
797
+ this.chatService.generateAuditEvent('ast-thumb-up.click', { 'rank': rank, 'message-id': message.additionalProperties.messageId });
836
798
  this.reportType = 'like';
837
799
  this.messageToReport = message;
838
800
  this.reportComment = undefined;
839
801
  this.reportRank = rank;
840
802
  this.showReport = true;
841
- this.chatService.chatHistory[this._remapIndexInChatHistory(rank)].additionalProperties.$liked = true;
842
- this.chatService.chatHistory[this._remapIndexInChatHistory(rank)].additionalProperties.$disliked = false;
803
+ this.chatService.chatHistory[rank - 1].additionalProperties.$liked = true;
804
+ this.chatService.chatHistory[rank - 1].additionalProperties.$disliked = false;
843
805
  this._updateChatHistory();
844
806
  }
845
807
  /**
@@ -848,24 +810,24 @@ export class ChatComponent {
848
810
  * @param message The assistant message to dislike
849
811
  * @param index The rank of the message to dislike
850
812
  */
851
- onDislike(message, rank) {
813
+ onDislike(message, index) {
852
814
  // Remap the index in the chat history
853
- const idx = this._remapIndexInChatHistory(rank);
854
- this.chatService.generateAuditEvent('ast-thumb-down.click', { rank: idx });
815
+ const rank = this.assistantUtils.getMessageRankInChatHistory(this.chatService.chatHistory, message.additionalProperties.messageId);
816
+ this.chatService.generateAuditEvent('ast-thumb-down.click', { 'rank': rank, 'message-id': message.additionalProperties.messageId });
855
817
  this.reportType = 'dislike';
856
818
  this.messageToReport = message;
857
819
  this.issueType = '';
858
820
  this.reportComment = undefined;
859
821
  this.reportRank = rank;
860
822
  this.showReport = true;
861
- this.chatService.chatHistory[this._remapIndexInChatHistory(rank)].additionalProperties.$disliked = true;
862
- this.chatService.chatHistory[this._remapIndexInChatHistory(rank)].additionalProperties.$liked = false;
823
+ this.chatService.chatHistory[rank - 1].additionalProperties.$disliked = true;
824
+ this.chatService.chatHistory[rank - 1].additionalProperties.$liked = false;
863
825
  this._updateChatHistory();
864
826
  }
865
827
  _updateChatHistory() {
866
828
  this.messages$.next(this.chatService.chatHistory);
867
- if (this.chatService.savedChatId) {
868
- this.chatService.updateSavedChat(this.chatService.savedChatId, undefined, this.chatService.chatHistory).subscribe();
829
+ if (this.config.savedChatSettings.enabled) {
830
+ this.chatService.updateSavedChat(this.chatService.chatId, undefined, this.chatService.chatHistory).subscribe();
869
831
  }
870
832
  this.cdr.detectChanges();
871
833
  }
@@ -875,8 +837,12 @@ export class ChatComponent {
875
837
  sendReport() {
876
838
  const details = {
877
839
  'comment': this.reportComment,
878
- 'rank': this.reportRank,
840
+ 'rank': this.reportRank
879
841
  };
842
+ //check if the message to report is defined. It should always be the case
843
+ if (this.messageToReport) {
844
+ details['message-id'] = this.messageToReport.additionalProperties.messageId;
845
+ }
880
846
  // hide text in case logContent is not enabled
881
847
  if (this.config.auditSettings.logContent)
882
848
  details['text'] = this.messageToReport.content;
@@ -899,17 +865,20 @@ export class ChatComponent {
899
865
  /**
900
866
  * Handle the click on a reference's 'open preview'.
901
867
  * @param data
902
- * @param index rank of the message
868
+ * @param message the message containing the reference
869
+ * @param index index of the message containing the reference
870
+ * @returns void
903
871
  */
904
- openAttachmentPreview(data, rank) {
872
+ openAttachmentPreview(data, message, index) {
905
873
  this.openPreview.emit(data.reference);
906
- const idx = this._remapIndexInChatHistory(rank);
874
+ const rank = this.assistantUtils.getMessageRankInChatHistory(this.chatService.chatHistory, message.additionalProperties.messageId);
907
875
  const details = {
908
876
  'doc-id': data.reference.recordId,
909
877
  'source': data.reference.record.treepath,
910
878
  'collection': data.reference.record.collection,
911
879
  'index': data.reference.record.databasealias,
912
- 'rank': idx
880
+ 'rank': rank,
881
+ 'message-id': message.additionalProperties.messageId
913
882
  };
914
883
  if (!!data.partId)
915
884
  details['part-id'] = data.partId;
@@ -918,16 +887,20 @@ export class ChatComponent {
918
887
  /**
919
888
  * Handle the click on a reference's 'open original document'.
920
889
  * @param data
890
+ * @param message the message containing the reference
891
+ * @param index index of the message containing the reference
892
+ * @returns void
921
893
  */
922
- openOriginalAttachment(data, rank) {
894
+ openOriginalAttachment(data, message, index) {
923
895
  this.openDocument.emit(data.reference.record);
924
- const idx = this._remapIndexInChatHistory(rank);
896
+ const rank = this.assistantUtils.getMessageRankInChatHistory(this.chatService.chatHistory, message.additionalProperties.messageId);
925
897
  const details = {
926
898
  'doc-id': data.reference.recordId,
927
899
  'source': data.reference.record.treepath,
928
900
  'collection': data.reference.record.collection,
929
901
  'index': data.reference.record.databasealias,
930
- 'rank': idx
902
+ 'rank': rank,
903
+ 'message-id': message.additionalProperties.messageId
931
904
  };
932
905
  if (!!data.partId)
933
906
  details['part-id'] = data.partId;
@@ -944,20 +917,21 @@ export class ChatComponent {
944
917
  }
945
918
  /**
946
919
  * It looks for the debug messages available in the current group of "assistant" messages.
947
- * By design, the debug messages are only available in the first visible message among the group "assistant" messages.
948
- * @param index The rank of the message
920
+ * By design, the debug messages are only available in the first visible message among the group of "assistant" messages.
921
+ * @param message The message containing the debug information
922
+ * @param index The index of the message
949
923
  * @returns The debug messages available in the current group of "assistant" messages
950
924
  */
951
- getDebugMessages(index) {
952
- // If it is not an assistant message, return
953
- if ((this.messages$.value)[index].role !== 'assistant') {
925
+ getDebugMessages(message, index) {
926
+ // If it is not an assistant message, return an empty array
927
+ if (message.role !== 'assistant') {
954
928
  return [];
955
929
  }
956
930
  // Get the array of messages up to the indicated index
957
931
  const array = this.messages$.value.slice(0, index + 1);
958
932
  // If it is an assistant message, look for the debug messages available in the current group of "assistant" messages
959
933
  // By design, the debug messages are only available in the first visible message among the group "assistant" messages.
960
- const idx = this.chatService.firstVisibleAssistantMessageIndex(array);
934
+ const idx = this.assistantUtils.firstVisibleAssistantMessageIndex(array);
961
935
  if (idx > -1) {
962
936
  return (this.messages$.value)[idx].additionalProperties.$debug || [];
963
937
  }
@@ -965,10 +939,11 @@ export class ChatComponent {
965
939
  }
966
940
  /**
967
941
  * Handle the click on the 'show log info' button of a message.
968
- * @param index The rank of the message
942
+ * @param message The message containing the debug information
943
+ * @param index The index of the message
969
944
  */
970
- showDebug(index) {
971
- this.debugMessages = this.getDebugMessages(index);
945
+ showDebug(message, index) {
946
+ this.debugMessages = this.getDebugMessages(message, index);
972
947
  this.showDebugMessages = true;
973
948
  this.cdr.detectChanges();
974
949
  }
@@ -1014,27 +989,23 @@ export class ChatComponent {
1014
989
  return false;
1015
990
  }
1016
991
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ChatComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
1017
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.13", type: ChatComponent, isStandalone: true, selector: "sq-chat-v3", inputs: { instanceId: "instanceId", query: "query", queryChangeShouldTriggerReload: "queryChangeShouldTriggerReload", protocol: "protocol", messageHandlers: "messageHandlers", automaticScrollToLastResponse: "automaticScrollToLastResponse", focusAfterResponse: "focusAfterResponse", chat: "chat", assistantMessageIcon: "assistantMessageIcon", userMessageIcon: "userMessageIcon", connectionErrorMessageIcon: "connectionErrorMessageIcon", searchWarningMessageIcon: "searchWarningMessageIcon", additionalWorkflowProperties: "additionalWorkflowProperties", appConfig: "appConfig" }, outputs: { connection: "connection", loading$: "loading", _config: "config", data: "data", openDocument: "openDocument", openPreview: "openPreview", suggestAction: "suggestAction" }, providers: [
1018
- RestChatService,
1019
- WebSocketChatService,
992
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.13", type: ChatComponent, isStandalone: true, selector: "sq-chat-v3", inputs: { instanceId: "instanceId", query: "query", queryChangeShouldTriggerReload: "queryChangeShouldTriggerReload", messageHandlers: "messageHandlers", automaticScrollToLastResponse: "automaticScrollToLastResponse", focusAfterResponse: "focusAfterResponse", chat: "chat", assistantMessageIcon: "assistantMessageIcon", userMessageIcon: "userMessageIcon", connectionErrorMessageIcon: "connectionErrorMessageIcon", searchWarningMessageIcon: "searchWarningMessageIcon", additionalWorkflowProperties: "additionalWorkflowProperties", appConfig: "appConfig" }, outputs: { connection: "connection", loading$: "loading", _config: "config", data: "data", openDocument: "openDocument", openPreview: "openPreview", suggestAction: "suggestAction" }, providers: [
993
+ ChatService,
1020
994
  provideTranslocoScope('chat')
1021
- ], queries: [{ propertyName: "loadingTpl", first: true, predicate: ["loadingTpl"], descendants: true }, { propertyName: "reportTpl", first: true, predicate: ["reportTpl"], descendants: true }, { propertyName: "tokenConsumptionTpl", first: true, predicate: ["tokenConsumptionTpl"], descendants: true }, { propertyName: "debugMessagesTpl", first: true, predicate: ["debugMessagesTpl"], descendants: true }], viewQueries: [{ propertyName: "messageList", first: true, predicate: ["messageList"], descendants: true }, { propertyName: "questionInput", first: true, predicate: ["questionInput"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<ng-container *ngIf=\"!initializationError\">\n <div *ngIf=\"messages$ | async as messages; else loadingTpl || loadingTplDefault\" class=\"h-100 d-flex flex-column\">\n <!-- Token consumption -->\n <div class=\"ms-1\" *ngIf=\"config?.globalSettings?.displayUserQuotaConsumption || config?.globalSettings?.displayChatTokensConsumption\">\n <ng-container *ngTemplateOutlet=\"tokenConsumptionTpl || defaultTokenConsumptionTpl; context: { $implicit: instanceId }\"></ng-container>\n </div>\n\n <!-- Chat Messages -->\n <ul class=\"d-flex flex-column list-unstyled gap-3 overflow-auto flex-grow-1 pe-2 pb-2\" #messageList>\n <ng-container *ngFor=\"let message of messages; let index = index; let last = last\">\n <!-- Regular messages -->\n <li class=\"list-group-item\"\n *ngIf=\"message.additionalProperties.display && !isEmptyAssistantMessage(message)\"\n [style.--bs-list-group-item-padding-y.rem]=\"'0.6'\"\n [class.opacity-50]=\"messageToEdit && (messageToEdit < (index + 1))\">\n <sq-chat-message\n [class.sq-user-message]=\"message.role === 'user'\"\n [class.last-message]=\"last\"\n [message]=\"message\"\n [conversation]=\"messages\"\n [suggestedActions]=\"last ? message.additionalProperties.$suggestedAction : undefined\"\n [assistantMessageIcon]=\"assistantMessageIcon\"\n [userMessageIcon]=\"userMessageIcon\"\n [connectionErrorMessageIcon]=\"connectionErrorMessageIcon\"\n [searchWarningMessageIcon]=\"searchWarningMessageIcon\"\n [streaming]=\"(chatService.streaming$ | async) && (last || isAssistantLastMessages(messages, index))\"\n [canEdit]=\"(chatService.streaming$ | async) === false && messageToEdit === undefined && message.role === 'user'\"\n [canCopy]=\"((chatService.streaming$ | async) === false || !last) && messageToEdit === undefined && message.role !== 'connection-error' && message.role !== 'search-warning'\"\n [canLike]=\"((chatService.streaming$ | async) === false || !last) && message.role === 'assistant'\"\n [canDislike]=\"((chatService.streaming$ | async) === false || !last) && message.role === 'assistant'\"\n [canDebug]=\"(((chatService.streaming$ | async) === false && last) || (!last && messages[index+1].role !== 'assistant')) && message.role === 'assistant' && (getDebugMessages(index).length > 0) && ((isAdminOrDeletedAdmin || (chatService.userOverride$ | async)) && config?.defaultValues.debug)\"\n [canRegenerate]=\"(chatService.streaming$ | async) === false && (last || (!last && messages[index+1].role !== 'assistant')) && message.role === 'assistant' && messageToEdit === undefined\"\n (edit)=\"editMessage(index)\"\n (copy)=\"copyMessage(index)\"\n (regenerate)=\"regenerateMessage(index)\"\n (openDocument)=\"openOriginalAttachment($event, index)\"\n (openPreview)=\"openAttachmentPreview($event, index)\"\n (suggestAction)=\"suggestActionClick($event, index)\"\n (like)=\"onLike(message, index)\"\n (dislike)=\"onDislike(message, index)\"\n (debug)=\"showDebug(index)\">\n </sq-chat-message>\n </li>\n </ng-container>\n <!-- Loading spinner -->\n <li *ngIf=\"(loading$ | async) === true\">\n <ng-container *ngTemplateOutlet=\"loadingTpl || loadingTplDefault\"></ng-container>\n </li>\n </ul>\n\n <!-- Reporting a feedback form -->\n <div class=\"issue-report p-3 rounded-lg\" *ngIf=\"showReport\">\n <ng-container *ngTemplateOutlet=\"reportTpl || reportTplDefault; context: { $implicit: messageToReport, rank: reportRank, type: reportType }\"></ng-container>\n </div>\n\n <!-- User text input -->\n @if (!showReport) {\n <div class=\"user-input mt-auto\">\n <div class=\"py-2\">\n <div [hidden]=\"!isConnected\">\n <ng-container *ngIf=\"enabledUserInput\" [ngTemplateOutlet]=\"inputTpl\"></ng-container>\n </div>\n <!-- Retry button -->\n <!-- hidden attribute is in conflict with a css rule display: flex -->\n @if(!isConnected){\n <button class=\"btn mb-4 ast-error ast-btn sq-retry\" (click)=\"retryFetch()\">\n <span>{{ 'chat.tryAgain' | transloco }}</span>\n <span *ngIf=\"retrialAttempts\" class=\"ms-2 attempts\">{{ retrialAttempts }}</span>\n </button>\n }\n <div class=\"text-end small text-muted px-3\" *ngIf=\"!!config?.globalSettings?.disclaimer\">\n {{ config?.globalSettings?.disclaimer | transloco }}\n </div>\n </div>\n </div>\n }\n\n <!-- Floating scroll button -->\n <div *ngIf=\"!isAtBottom && !showReport\" class=\"sq-floating-scroll\" [ngClass]=\"enabledUserInput ? 'sq-floating-scroll--when-user-input' : 'sq-floating-scroll--without-user-input'\">\n <button class=\"btn shadow\" (click)=\"scrollDown()\" aria-label=\"Scroll down\">\n <i class=\"fas fa-angle-double-down\"></i>\n </button>\n </div>\n </div>\n</ng-container>\n\n<!-- NG TEMPLATES-->\n\n<ng-template #loadingTplDefault>\n <div class=\"spinner-grow text-primary d-block mx-auto my-5\" role=\"status\">\n <span class=\"visually-hidden\">{{ 'chat.loading' | transloco }}</span>\n </div>\n</ng-template>\n\n<ng-template #inputTpl>\n <div class=\"px-3 py-1\">\n <div class=\"ast-input-container\">\n <button disabled class=\"btn btn-light\" aria-label=\"search\">\n <i class=\"fas fa-search\"></i>\n </button>\n <textarea #questionInput rows=\"1\"\n type=\"text\" class=\"form-control\"\n [placeholder]=\"'chat.askSomething' | transloco\" autofocus\n [(ngModel)]=\"question\"\n (keyup)=\"onKeyUp($event)\"\n (keydown)=\"calculateHeight($event)\"\n [disabled]=\"(loading$ | async) || (chatService.streaming$ | async) || (chatService.stoppingGeneration$ | async)\">\n </textarea>\n <div id=\"chat-actions\" class=\"d-flex gap-2\">\n <button\n *ngIf=\"(chatService.streaming$ | async) === false && (loading$ | async) === false && (chatService.stoppingGeneration$ | async) === false\"\n type=\"button\"\n class=\"btn btn-light\"\n aria-label=\"Send message\"\n [sqTooltip]=\"'chat.sendMessage' | transloco\"\n (click)=\"submitQuestion()\">\n <i class=\"fas fa-paper-plane\"></i>\n </button>\n <button\n *ngIf=\"messageToEdit\"\n aria-label=\"Cancel edition\"\n type=\"button\"\n class=\"btn btn-light\"\n [sqTooltip]=\"'chat.cancelEdition' | transloco\"\n (click)=\"messageToEdit = undefined; question = ''\">\n <i class=\"fas fa-undo-alt\"></i>\n </button>\n <span *ngIf=\"(chatService.streaming$ | async) && (chatService.stoppingGeneration$ | async) === false\" class=\"processing\">\n {{ 'chat.generating' | transloco }}<i class=\"fas fa-spinner fa-pulse\"></i>\n </span>\n <span *ngIf=\"(chatService.stoppingGeneration$ | async)\" class=\"processing\">\n {{ 'chat.stopping' | transloco }}<i class=\"fas fa-spinner fa-pulse\"></i>\n </span>\n <button\n *ngIf=\"(chatService.streaming$ | async) && (chatService.stoppingGeneration$ | async) === false\"\n type=\"button\"\n class=\"btn btn-light\"\n aria-label=\"Stop generating\"\n [sqTooltip]=\"'chat.stopGeneration' | transloco\"\n (click)=\"stopGeneration()\">\n <i class=\"fas fa-stop\"></i>\n </button>\n </div>\n </div>\n </div>\n</ng-template>\n\n<ng-template #reportTplDefault let-message let-rank=\"rank\" let-type=\"type\">\n <div class=\"px-3\">\n <ng-container *ngIf=\"type === 'dislike'\">\n <h5>{{ 'chat.issueType' | transloco }}</h5>\n <select class=\"form-select mb-4\" [(ngModel)]=\"issueType\">\n <option [value]=\"''\">{{ 'chat.chooseIssueType' | transloco }}</option>\n <option *ngFor=\"let type of (issueTypes ?? defaultIssueTypes)\" [value]=\"type\">{{ type | transloco }}</option>\n </select>\n <h5>{{ 'chat.askUnlikeReasons' | transloco }}</h5>\n </ng-container>\n <ng-container *ngIf=\"type === 'like'\">\n <h5>{{ 'chat.askLikeReasons' | transloco }}</h5>\n </ng-container>\n <textarea class=\"form-control border border-neutral-200\" [(ngModel)]=\"reportComment\" [placeholder]=\"'chat.writeComment' | transloco\"></textarea>\n <div class=\"d-flex flex-row-reverse gap-1 mt-2\">\n <button class=\"btn btn-primary\" [disabled]=\"type === 'dislike' && !issueType\" (click)=\"sendReport()\">{{ 'chat.send' | transloco }}</button>\n <button class=\"btn btn-light\" (click)=\"ignoreReport()\">{{ 'chat.doNotSend' | transloco }}</button>\n </div>\n </div>\n</ng-template>\n\n<ng-template #defaultTokenConsumptionTpl let-instanceId>\n <sq-token-progress-bar\n [instanceId]=\"instanceId\">\n </sq-token-progress-bar>\n</ng-template>\n\n<div class=\"debug-messages\" [class.displayed]=\"showDebugMessages\">\n <button *ngIf=\"showDebugMessages\" class=\"btn btn-light shadow back-btn\" (click)=\"showDebugMessages=false\" aria-label=\"Hide debug messages\">\n <i class=\"fas fa-chevron-right\"></i>\n </button>\n <ng-container *ngTemplateOutlet=\"debugMessagesTpl || defaultDebugMessagesTpl; context: { $implicit: debugMessages }\">\n </ng-container>\n</div>\n\n<ng-template #defaultDebugMessagesTpl let-debugMessages>\n <sq-debug-message [data]=\"debugMessages\"></sq-debug-message>\n</ng-template>\n", styles: [".ast-primary{color:var(--ast-primary-color, #005DA7);background-color:var(--ast-primary-bg, #f2f8fe)}.ast-primary-hover{background-color:var(--ast-primary-bg, #f2f8fe)}.ast-primary-hover:hover{color:var(--ast-primary-color, #005DA7)}.ast-secondary{color:var(--ast-secondary-color, #FF732E);background-color:var(--ast-secondary-bg, #FFF8F1)}.ast-error{background-color:var(--ast-error-bg, rgba(249, 58, 55, .2));color:var(--ast-action-buttons-color, inherit)}.ast-error:hover{color:var(--ast-error-color, rgba(249, 58, 55, .7))}.ast-btn{border:0;text-align:left;padding-top:.5rem;padding-bottom:.5rem;display:flex;align-items:center}.dark{--ast-primary-bg: #0d0701;--ast-primary-color: #008cd1;--ast-secondary-bg: #00070e;--ast-secondary-color: #ffa258;--ast-input-bg: #070707;--ast-input-color: rgba(222, 218, 218, .75);--ast-muted-color: rgba(222, 218, 218, .75);--ast-saved-chat-hover-background: #262421;--ast-uploaded-doc-hover-background: #262421;--ast-message-table-border-color: #333333;--ast-message-table-tr-bg: #070707;--ast-message-table-tr-border-color: #222222;--ast-reference-icon-color: white;--ast-reference-icon-active-color: black;--ast-reference-passages-color: white;--ast-reference-expanded-hover-bg: #262421;--ast-message-reference-color: black;--ast-action-buttons-color: white;--ast-action-buttons-hover-color: #6dbee6;--ast-report-bg: #070707}:host ::ng-deep .reference,:host ::ng-deep .message-content .reference,:host ::ng-deep .attachment .reference{position:relative;bottom:var(--ast-reference-bottom, .3em);font-weight:var(--ast-reference-font-weight, bold);padding:var(--ast-reference-padding, 0 .2em);margin:var(--ast-reference-margin, 0 .1em);border-radius:var(--ast-reference-border-radius, .2em);background-color:var(--ast-reference-background-color, lightblue);color:var(--ast-reference-color, black)}:host ::ng-deep .reference,:host ::ng-deep .message-content .reference{font-size:var(--ast-reference-message-font-size, .7em)}:host ::ng-deep .attachment .reference{font-size:var(--ast-reference-attachment-font-size, 13px)}:host{font-size:.875rem}:host>div>.user-input>div:not(.progress),:host>div>.issue-report>div,:host>div>ul>li{width:var(--ast-chat-container-width, 100%);max-width:100%;margin-left:auto;margin-right:auto}:host>div>ul{padding-top:var(--ast-chat-padding-top, 0);padding-bottom:var(--ast-chat-padding-bottom, 0)}li.attachment>p{display:-webkit-box;-webkit-box-orient:vertical;overflow:hidden;-webkit-line-clamp:3}li.attachment.expanded>p{display:block}.progress{--bs-progress-height: 3px}.progress.disabled{--bs-progress-height: 20px;--bs-progress-bar-bg: var(--bs-danger)}.user-input{z-index:1}.user-input ul.list-group{max-height:30vh}.form-control:disabled{background-color:#ededed}a.disabled{cursor:default;opacity:.5}.no-max-height{max-height:initial!important}.sq-floating-scroll{position:absolute;right:50%;text-align:center}.sq-floating-scroll--when-user-input{bottom:75px}.sq-floating-scroll--without-user-input{bottom:15px}.sq-floating-scroll .btn{background-color:#fff}.sq-floating-scroll .btn:hover{background-color:#fff;opacity:.9}.ast-input-container{display:flex;align-items:center;background-color:var(--ast-input-bg, #F8F8F8);border-radius:var(--ast-size-3, .75rem)}.ast-input-container>i{padding-left:var(--ast-size-3, .75rem);color:var(--ast-muted-color, rgba(33, 37, 41, .75))}.ast-input-container textarea{padding-left:var(--ast-size-3, .75rem);padding-right:var(--ast-size-3, .75rem);resize:none}.ast-input-container textarea,.ast-input-container button,.ast-input-container button:hover{background-color:transparent;border:0}.ast-input-container button:hover{color:var(--ast-primary-color, #005DA7)}.ast-input-container button:not(:hover){color:var(--ast-muted-color, rgba(33, 37, 41, .75))}.ast-input-container .processing{display:flex;align-items:center;color:var(--ast-secondary-color, #FF732E);gap:.5rem}sq-chat-message.sq-user-message{float:var(--ast-user-message-float, none)}sq-token-progress-bar{z-index:10;position:absolute;top:0;right:0}.debug-messages{position:fixed;z-index:999999;right:-60%;top:0;width:60%;height:100%;transition:all .5s ease;background-color:var(--bs-body-bg);overflow:auto}.debug-messages .back-btn{position:fixed;right:0%;transition:all .5s ease}.debug-messages.displayed{right:0}.debug-messages.displayed .back-btn{right:60%}.debug-messages sq-debug-message:first-of-type{display:block;width:100%}.btn.sq-retry{display:flex;margin:auto;background:var(--ast-error-bg, rgba(249, 58, 55, .2));font-weight:var(--font-weight-bold, 500)}.btn.sq-retry .attempts{display:flex;border-radius:100%;background:#fff;height:20px;width:20px;place-content:center;align-items:center}.issue-report{background-color:var(--ast-report-bg, white)}.text-end{text-align:right}.small{font-size:.875em}.text-muted{--bs-text-opacity: 1;color:var(--bs-secondary-color)}.d-flex{display:flex}.flex-row-reverse{flex-direction:row-reverse}.flex-grow-1{flex-grow:1}.spinner-grow,.spinner-border{display:inline-block;width:var(--bs-spinner-width);height:var(--bs-spinner-height);vertical-align:var(--bs-spinner-vertical-align);border-radius:50%;animation:var(--bs-spinner-animation-speed) linear infinite var(--bs-spinner-animation-name)}.text-primary{--bs-text-opacity: 1;color:rgba(var(--bs-primary-rgb),var(--bs-text-opacity))}.d-block{display:block}.btn{--bs-border-radius: .25rem;--bs-btn-padding-x: .75rem;--bs-btn-padding-y: .375rem;--bs-btn-font-family: ;--bs-btn-font-size: 1rem;--bs-btn-font-weight: 400;--bs-btn-line-height: 1.5;--bs-btn-color: var(--bs-body-color);--bs-btn-bg: transparent;--bs-btn-border-width: var(--bs-border-width);--bs-btn-border-color: transparent;--bs-btn-border-radius: var(--bs-border-radius);--bs-btn-hover-border-color: transparent;--bs-btn-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 1px rgba(0, 0, 0, .075);--bs-btn-disabled-opacity: .65;--bs-btn-focus-box-shadow: 0 0 0 .25rem rgba(var(--bs-btn-focus-shadow-rgb), .5);display:inline-block;padding:var(--bs-btn-padding-y) var(--bs-btn-padding-x);font-family:var(--bs-btn-font-family);font-size:var(--bs-btn-font-size);font-weight:var(--bs-btn-font-weight);line-height:var(--bs-btn-line-height);color:var(--bs-btn-color);text-align:center;text-decoration:none;vertical-align:middle;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;user-select:none;border:var(--bs-btn-border-width) solid var(--bs-btn-border-color);border-radius:var(--bs-btn-border-radius);background-color:var(--bs-btn-bg);transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}.btn-primary{--bs-btn-color: #fff;--bs-btn-bg: #0d6efd;--bs-btn-border-color: #0d6efd;--bs-btn-hover-color: #fff;--bs-btn-hover-bg: #0b5ed7;--bs-btn-hover-border-color: #0a58ca;--bs-btn-focus-shadow-rgb: 49, 132, 253;--bs-btn-active-color: #fff;--bs-btn-active-bg: #0a58ca;--bs-btn-active-border-color: #0a53be;--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);--bs-btn-disabled-color: #fff;--bs-btn-disabled-bg: #0d6efd;--bs-btn-disabled-border-color: #0d6efd}.btn-light{--bs-btn-color: #000;--bs-btn-bg: #f8f9fa;--bs-btn-border-color: #f8f9fa;--bs-btn-hover-color: #000;--bs-btn-hover-bg: #d3d4d5;--bs-btn-hover-border-color: #c6c7c8;--bs-btn-focus-shadow-rgb: 211, 212, 213;--bs-btn-active-color: #000;--bs-btn-active-bg: #c6c7c8;--bs-btn-active-border-color: #babbbc;--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);--bs-btn-disabled-color: #000;--bs-btn-disabled-bg: #f8f9fa;--bs-btn-disabled-border-color: #f8f9fa}.form-control{display:block;width:100%;padding:.375rem .75rem;font-size:1rem;font-weight:400;line-height:1.5;color:var(--bs-body-color);-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:var(--bs-body-bg);background-clip:padding-box;transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out}.form-control:disabled{background-color:var(--bs-body-bg)}.form-select{--bs-form-select-bg-img: url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23343a40' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m2 5 6 6 6-6'/%3e%3c/svg%3e\");display:block;width:100%;padding:.375rem 2.25rem .375rem .75rem;font-size:1rem;font-weight:400;line-height:1.5;color:var(--bs-body-color);-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:var(--bs-body-bg);background-image:var(--bs-form-select-bg-img),var(--bs-form-select-bg-icon, none);background-repeat:no-repeat;background-position:right .75rem center;background-size:16px 12px;border:var(--bs-border-width, 1px) solid var(--bs-border-color, oklch(92.2% 0 0));border-radius:var(--bs-border-radius);transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "pipe", type: i1.AsyncPipe, name: "async" }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i2.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2.SelectControlValueAccessor, selector: "select:not([multiple])[formControlName],select:not([multiple])[formControl],select:not([multiple])[ngModel]", inputs: ["compareWith"] }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: ChatMessageComponent, selector: "sq-chat-message", inputs: ["message", "conversation", "suggestedActions", "assistantMessageIcon", "userMessageIcon", "connectionErrorMessageIcon", "searchWarningMessageIcon", "streaming", "canEdit", "canRegenerate", "canCopy", "canDebug", "canLike", "canDislike"], outputs: ["openDocument", "openPreview", "suggestAction", "edit", "copy", "regenerate", "like", "dislike", "debug"] }, { kind: "component", type: TokenProgressBarComponent, selector: "sq-token-progress-bar", inputs: ["instanceId"] }, { kind: "component", type: DebugMessageComponent, selector: "sq-debug-message", inputs: ["data", "level", "parentColor"] }, { kind: "directive", type: TooltipDirective, selector: "[sqTooltip]", inputs: ["sqTooltip", "sqTooltipData", "sqTooltipTemplate", "placement", "fallbackPlacements", "delay", "hoverableTooltip", "tooltipClass"] }, { kind: "pipe", type: TranslocoPipe, name: "transloco" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
995
+ ], queries: [{ propertyName: "loadingTpl", first: true, predicate: ["loadingTpl"], descendants: true }, { propertyName: "reportTpl", first: true, predicate: ["reportTpl"], descendants: true }, { propertyName: "tokenConsumptionTpl", first: true, predicate: ["tokenConsumptionTpl"], descendants: true }, { propertyName: "debugMessagesTpl", first: true, predicate: ["debugMessagesTpl"], descendants: true }], viewQueries: [{ propertyName: "messageList", first: true, predicate: ["messageList"], descendants: true }, { propertyName: "questionInput", first: true, predicate: ["questionInput"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<ng-container *ngIf=\"!initializationError\">\n <div *ngIf=\"messages$ | async as messages; else loadingTpl || loadingTplDefault\" class=\"h-100 d-flex flex-column\">\n <!-- Token consumption -->\n <div class=\"ms-1\" *ngIf=\"config?.globalSettings?.displayUserQuotaConsumption || config?.globalSettings?.displayChatTokensConsumption\">\n <ng-container *ngTemplateOutlet=\"tokenConsumptionTpl || defaultTokenConsumptionTpl; context: { $implicit: instanceId }\"></ng-container>\n </div>\n\n <!-- Chat Messages -->\n <ul class=\"d-flex flex-column list-unstyled gap-3 overflow-auto flex-grow-1 pe-2 pb-2\" #messageList>\n <ng-container *ngFor=\"let message of messages; let index = index; let last = last\">\n <!-- Regular messages -->\n <li class=\"list-group-item\"\n *ngIf=\"message.additionalProperties.display && !isEmptyAssistantMessage(message)\"\n [style.--bs-list-group-item-padding-y.rem]=\"'0.6'\"\n [class.opacity-50]=\"indexMessageToEdit && (indexMessageToEdit < (index + 1))\">\n <sq-chat-message\n [class.sq-user-message]=\"message.role === 'user'\"\n [class.last-message]=\"last\"\n [message]=\"message\"\n [conversation]=\"messages\"\n [suggestedActions]=\"last ? message.additionalProperties.$suggestedAction : undefined\"\n [assistantMessageIcon]=\"assistantMessageIcon\"\n [userMessageIcon]=\"userMessageIcon\"\n [connectionErrorMessageIcon]=\"connectionErrorMessageIcon\"\n [searchWarningMessageIcon]=\"searchWarningMessageIcon\"\n [streaming]=\"(chatService.streaming$ | async) && (last || isAssistantLastMessages(messages, index))\"\n [canEdit]=\"(chatService.streaming$ | async) === false && indexMessageToEdit === undefined && message.role === 'user'\"\n [canCopy]=\"((chatService.streaming$ | async) === false || !last) && indexMessageToEdit === undefined && message.role !== 'connection-error' && message.role !== 'search-warning'\"\n [canLike]=\"((chatService.streaming$ | async) === false || !last) && message.role === 'assistant'\"\n [canDislike]=\"((chatService.streaming$ | async) === false || !last) && message.role === 'assistant'\"\n [canDebug]=\"(((chatService.streaming$ | async) === false && last) || (!last && messages[index+1].role !== 'assistant')) && message.role === 'assistant' && (getDebugMessages(message, index).length > 0) && ((isAdminOrDeletedAdmin || (chatService.userOverride$ | async)) && config?.defaultValues.debug)\"\n [canRegenerate]=\"(chatService.streaming$ | async) === false && (last || (!last && messages[index+1].role !== 'assistant')) && message.role === 'assistant' && indexMessageToEdit === undefined\"\n (edit)=\"editMessage(message, index)\"\n (copy)=\"copyMessage(message, index)\"\n (regenerate)=\"regenerateMessage(message, index)\"\n (openDocument)=\"openOriginalAttachment($event, message, index)\"\n (openPreview)=\"openAttachmentPreview($event, message, index)\"\n (suggestAction)=\"suggestActionClick($event, index)\"\n (like)=\"onLike(message, index)\"\n (dislike)=\"onDislike(message, index)\"\n (debug)=\"showDebug(message, index)\">\n </sq-chat-message>\n </li>\n </ng-container>\n <!-- Loading spinner -->\n <li *ngIf=\"(loading$ | async) === true\">\n <ng-container *ngTemplateOutlet=\"loadingTpl || loadingTplDefault\"></ng-container>\n </li>\n </ul>\n\n <!-- Reporting a feedback form -->\n <div class=\"issue-report p-3 rounded-lg\" *ngIf=\"showReport\">\n <ng-container *ngTemplateOutlet=\"reportTpl || reportTplDefault; context: { $implicit: messageToReport, rank: reportRank, type: reportType }\"></ng-container>\n </div>\n\n <!-- User text input -->\n @if (!showReport) {\n <div class=\"user-input mt-auto\">\n <div class=\"py-2\">\n <div [hidden]=\"!isConnected\">\n <ng-container *ngIf=\"enabledUserInput\" [ngTemplateOutlet]=\"inputTpl\"></ng-container>\n </div>\n <!-- Retry button -->\n <!-- hidden attribute is in conflict with a css rule display: flex -->\n @if(!isConnected){\n <button class=\"btn mb-4 ast-error ast-btn sq-retry\" (click)=\"retryFetch()\">\n <span>{{ 'chat.tryAgain' | transloco }}</span>\n <span *ngIf=\"retrialAttempts\" class=\"ms-2 attempts\">{{ retrialAttempts }}</span>\n </button>\n }\n <div class=\"text-end small text-muted px-3\" *ngIf=\"!!config?.globalSettings?.disclaimer\">\n {{ config?.globalSettings?.disclaimer | transloco }}\n </div>\n </div>\n </div>\n }\n\n <!-- Floating scroll button -->\n <div *ngIf=\"!isAtBottom && !showReport\" class=\"sq-floating-scroll\" [ngClass]=\"enabledUserInput ? 'sq-floating-scroll--when-user-input' : 'sq-floating-scroll--without-user-input'\">\n <button class=\"btn shadow\" (click)=\"scrollDown()\" aria-label=\"Scroll down\">\n <i class=\"fas fa-angle-double-down\"></i>\n </button>\n </div>\n </div>\n</ng-container>\n\n<!-- NG TEMPLATES-->\n\n<ng-template #loadingTplDefault>\n <div class=\"spinner-grow text-primary d-block mx-auto my-5\" role=\"status\">\n <span class=\"visually-hidden\">{{ 'chat.loading' | transloco }}</span>\n </div>\n</ng-template>\n\n<ng-template #inputTpl>\n <div class=\"px-3 py-1\">\n <div class=\"ast-input-container\">\n <button disabled class=\"btn btn-light\" aria-label=\"search\">\n <i class=\"fas fa-search\"></i>\n </button>\n <textarea #questionInput rows=\"1\"\n type=\"text\" class=\"form-control\"\n [placeholder]=\"'chat.askSomething' | transloco\" autofocus\n [(ngModel)]=\"question\"\n (keyup)=\"onKeyUp($event)\"\n (keydown)=\"calculateHeight($event)\"\n [disabled]=\"(loading$ | async) || (chatService.streaming$ | async) || (chatService.stoppingGeneration$ | async)\">\n </textarea>\n <div id=\"chat-actions\" class=\"d-flex gap-2\">\n <button\n *ngIf=\"(chatService.streaming$ | async) === false && (loading$ | async) === false && (chatService.stoppingGeneration$ | async) === false\"\n type=\"button\"\n class=\"btn btn-light\"\n aria-label=\"Send message\"\n [sqTooltip]=\"'chat.sendMessage' | transloco\"\n (click)=\"submitQuestion()\">\n <i class=\"fas fa-paper-plane\"></i>\n </button>\n <button\n *ngIf=\"indexMessageToEdit\"\n aria-label=\"Cancel edition\"\n type=\"button\"\n class=\"btn btn-light\"\n [sqTooltip]=\"'chat.cancelEdition' | transloco\"\n (click)=\"indexMessageToEdit = undefined; question = ''\">\n <i class=\"fas fa-undo-alt\"></i>\n </button>\n <span *ngIf=\"(chatService.streaming$ | async) && (chatService.stoppingGeneration$ | async) === false\" class=\"processing\">\n {{ 'chat.generating' | transloco }}<i class=\"fas fa-spinner fa-pulse\"></i>\n </span>\n <span *ngIf=\"(chatService.stoppingGeneration$ | async)\" class=\"processing\">\n {{ 'chat.stopping' | transloco }}<i class=\"fas fa-spinner fa-pulse\"></i>\n </span>\n <button\n *ngIf=\"(chatService.streaming$ | async) && (chatService.stoppingGeneration$ | async) === false\"\n type=\"button\"\n class=\"btn btn-light\"\n aria-label=\"Stop generating\"\n [sqTooltip]=\"'chat.stopGeneration' | transloco\"\n (click)=\"stopGeneration()\">\n <i class=\"fas fa-stop\"></i>\n </button>\n </div>\n </div>\n </div>\n</ng-template>\n\n<ng-template #reportTplDefault let-message let-rank=\"rank\" let-type=\"type\">\n <div class=\"px-3\">\n <ng-container *ngIf=\"type === 'dislike'\">\n <h5>{{ 'chat.issueType' | transloco }}</h5>\n <select class=\"form-select mb-4\" [(ngModel)]=\"issueType\">\n <option [value]=\"''\">{{ 'chat.chooseIssueType' | transloco }}</option>\n <option *ngFor=\"let type of (issueTypes ?? defaultIssueTypes)\" [value]=\"type\">{{ type | transloco }}</option>\n </select>\n <h5>{{ 'chat.askUnlikeReasons' | transloco }}</h5>\n </ng-container>\n <ng-container *ngIf=\"type === 'like'\">\n <h5>{{ 'chat.askLikeReasons' | transloco }}</h5>\n </ng-container>\n <textarea class=\"form-control border border-neutral-200\" [(ngModel)]=\"reportComment\" [placeholder]=\"'chat.writeComment' | transloco\"></textarea>\n <div class=\"d-flex flex-row-reverse gap-1 mt-2\">\n <button class=\"btn btn-primary\" [disabled]=\"type === 'dislike' && !issueType\" (click)=\"sendReport()\">{{ 'chat.send' | transloco }}</button>\n <button class=\"btn btn-light\" (click)=\"ignoreReport()\">{{ 'chat.doNotSend' | transloco }}</button>\n </div>\n </div>\n</ng-template>\n\n<ng-template #defaultTokenConsumptionTpl let-instanceId>\n <sq-token-progress-bar\n [instanceId]=\"instanceId\">\n </sq-token-progress-bar>\n</ng-template>\n\n<div class=\"debug-messages\" [class.displayed]=\"showDebugMessages\">\n <button *ngIf=\"showDebugMessages\" class=\"btn btn-light shadow back-btn\" (click)=\"showDebugMessages=false\" aria-label=\"Hide debug messages\">\n <i class=\"fas fa-chevron-right\"></i>\n </button>\n <ng-container *ngTemplateOutlet=\"debugMessagesTpl || defaultDebugMessagesTpl; context: { $implicit: debugMessages }\">\n </ng-container>\n</div>\n\n<ng-template #defaultDebugMessagesTpl let-debugMessages>\n <sq-debug-message [data]=\"debugMessages\"></sq-debug-message>\n</ng-template>\n", styles: [".ast-primary{color:var(--ast-primary-color, #005DA7);background-color:var(--ast-primary-bg, #f2f8fe)}.ast-primary-hover{background-color:var(--ast-primary-bg, #f2f8fe)}.ast-primary-hover:hover{color:var(--ast-primary-color, #005DA7)}.ast-secondary{color:var(--ast-secondary-color, #FF732E);background-color:var(--ast-secondary-bg, #FFF8F1)}.ast-error{background-color:var(--ast-error-bg, rgba(249, 58, 55, .2));color:var(--ast-action-buttons-color, inherit)}.ast-error:hover{color:var(--ast-error-color, rgba(249, 58, 55, .7))}.ast-btn{border:0;text-align:left;padding-top:.5rem;padding-bottom:.5rem;display:flex;align-items:center}.dark{--ast-primary-bg: #0d0701;--ast-primary-color: #008cd1;--ast-secondary-bg: #00070e;--ast-secondary-color: #ffa258;--ast-input-bg: #070707;--ast-input-color: rgba(222, 218, 218, .75);--ast-muted-color: rgba(222, 218, 218, .75);--ast-saved-chat-hover-background: #262421;--ast-uploaded-doc-hover-background: #262421;--ast-message-table-border-color: #333333;--ast-message-table-tr-bg: #070707;--ast-message-table-tr-border-color: #222222;--ast-reference-icon-color: white;--ast-reference-icon-active-color: black;--ast-reference-passages-color: white;--ast-reference-expanded-hover-bg: #262421;--ast-message-reference-color: black;--ast-action-buttons-color: white;--ast-action-buttons-hover-color: #6dbee6;--ast-report-bg: #070707}:host ::ng-deep .reference,:host ::ng-deep .message-content .reference,:host ::ng-deep .attachment .reference{position:relative;bottom:var(--ast-reference-bottom, .3em);font-weight:var(--ast-reference-font-weight, bold);padding:var(--ast-reference-padding, 0 .2em);margin:var(--ast-reference-margin, 0 .1em);border-radius:var(--ast-reference-border-radius, .2em);background-color:var(--ast-reference-background-color, lightblue);color:var(--ast-reference-color, black)}:host ::ng-deep .reference,:host ::ng-deep .message-content .reference{font-size:var(--ast-reference-message-font-size, .7em)}:host ::ng-deep .attachment .reference{font-size:var(--ast-reference-attachment-font-size, 13px)}:host{font-size:.875rem}:host>div>.user-input>div:not(.progress),:host>div>.issue-report>div,:host>div>ul>li{width:var(--ast-chat-container-width, 100%);max-width:100%;margin-left:auto;margin-right:auto}:host>div>ul{padding-top:var(--ast-chat-padding-top, 0);padding-bottom:var(--ast-chat-padding-bottom, 0)}li.attachment>p{display:-webkit-box;-webkit-box-orient:vertical;overflow:hidden;-webkit-line-clamp:3}li.attachment.expanded>p{display:block}.progress{--bs-progress-height: 3px}.progress.disabled{--bs-progress-height: 20px;--bs-progress-bar-bg: var(--bs-danger)}.user-input{z-index:1}.user-input ul.list-group{max-height:30vh}.form-control:disabled{background-color:#ededed}a.disabled{cursor:default;opacity:.5}.no-max-height{max-height:initial!important}.sq-floating-scroll{position:absolute;right:50%;text-align:center}.sq-floating-scroll--when-user-input{bottom:75px}.sq-floating-scroll--without-user-input{bottom:15px}.sq-floating-scroll .btn{background-color:#fff}.sq-floating-scroll .btn:hover{background-color:#fff;opacity:.9}.ast-input-container{display:flex;align-items:center;background-color:var(--ast-input-bg, #F8F8F8);border-radius:var(--ast-size-3, .75rem)}.ast-input-container>i{padding-left:var(--ast-size-3, .75rem);color:var(--ast-muted-color, rgba(33, 37, 41, .75))}.ast-input-container textarea{padding-left:var(--ast-size-3, .75rem);padding-right:var(--ast-size-3, .75rem);resize:none}.ast-input-container textarea,.ast-input-container button,.ast-input-container button:hover{background-color:transparent;border:0}.ast-input-container button:hover{color:var(--ast-primary-color, #005DA7)}.ast-input-container button:not(:hover){color:var(--ast-muted-color, rgba(33, 37, 41, .75))}.ast-input-container .processing{display:flex;align-items:center;color:var(--ast-secondary-color, #FF732E);gap:.5rem}sq-chat-message.sq-user-message{float:var(--ast-user-message-float, none)}sq-token-progress-bar{z-index:10;position:absolute;top:0;right:0}.debug-messages{position:fixed;z-index:999999;right:-60%;top:0;width:60%;height:100%;transition:all .5s ease;background-color:var(--bs-body-bg);overflow:auto}.debug-messages .back-btn{position:fixed;right:0%;transition:all .5s ease}.debug-messages.displayed{right:0}.debug-messages.displayed .back-btn{right:60%}.debug-messages sq-debug-message:first-of-type{display:block;width:100%}.btn.sq-retry{display:flex;margin:auto;background:var(--ast-error-bg, rgba(249, 58, 55, .2));font-weight:var(--font-weight-bold, 500)}.btn.sq-retry .attempts{display:flex;border-radius:100%;background:#fff;height:20px;width:20px;place-content:center;align-items:center}.issue-report{background-color:var(--ast-report-bg, white)}.text-end{text-align:right}.small{font-size:.875em}.text-muted{--bs-text-opacity: 1;color:var(--bs-secondary-color)}.d-flex{display:flex}.flex-row-reverse{flex-direction:row-reverse}.flex-grow-1{flex-grow:1}.spinner-grow,.spinner-border{display:inline-block;width:var(--bs-spinner-width);height:var(--bs-spinner-height);vertical-align:var(--bs-spinner-vertical-align);border-radius:50%;animation:var(--bs-spinner-animation-speed) linear infinite var(--bs-spinner-animation-name)}.text-primary{--bs-text-opacity: 1;color:rgba(var(--bs-primary-rgb),var(--bs-text-opacity))}.d-block{display:block}.btn{--bs-border-radius: .25rem;--bs-btn-padding-x: .75rem;--bs-btn-padding-y: .375rem;--bs-btn-font-family: ;--bs-btn-font-size: 1rem;--bs-btn-font-weight: 400;--bs-btn-line-height: 1.5;--bs-btn-color: var(--bs-body-color);--bs-btn-bg: transparent;--bs-btn-border-width: var(--bs-border-width);--bs-btn-border-color: transparent;--bs-btn-border-radius: var(--bs-border-radius);--bs-btn-hover-border-color: transparent;--bs-btn-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 1px rgba(0, 0, 0, .075);--bs-btn-disabled-opacity: .65;--bs-btn-focus-box-shadow: 0 0 0 .25rem rgba(var(--bs-btn-focus-shadow-rgb), .5);display:inline-block;padding:var(--bs-btn-padding-y) var(--bs-btn-padding-x);font-family:var(--bs-btn-font-family);font-size:var(--bs-btn-font-size);font-weight:var(--bs-btn-font-weight);line-height:var(--bs-btn-line-height);color:var(--bs-btn-color);text-align:center;text-decoration:none;vertical-align:middle;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;user-select:none;border:var(--bs-btn-border-width) solid var(--bs-btn-border-color);border-radius:var(--bs-btn-border-radius);background-color:var(--bs-btn-bg);transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}.btn-primary{--bs-btn-color: #fff;--bs-btn-bg: #0d6efd;--bs-btn-border-color: #0d6efd;--bs-btn-hover-color: #fff;--bs-btn-hover-bg: #0b5ed7;--bs-btn-hover-border-color: #0a58ca;--bs-btn-focus-shadow-rgb: 49, 132, 253;--bs-btn-active-color: #fff;--bs-btn-active-bg: #0a58ca;--bs-btn-active-border-color: #0a53be;--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);--bs-btn-disabled-color: #fff;--bs-btn-disabled-bg: #0d6efd;--bs-btn-disabled-border-color: #0d6efd}.btn-light{--bs-btn-color: #000;--bs-btn-bg: #f8f9fa;--bs-btn-border-color: #f8f9fa;--bs-btn-hover-color: #000;--bs-btn-hover-bg: #d3d4d5;--bs-btn-hover-border-color: #c6c7c8;--bs-btn-focus-shadow-rgb: 211, 212, 213;--bs-btn-active-color: #000;--bs-btn-active-bg: #c6c7c8;--bs-btn-active-border-color: #babbbc;--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);--bs-btn-disabled-color: #000;--bs-btn-disabled-bg: #f8f9fa;--bs-btn-disabled-border-color: #f8f9fa}.form-control{display:block;width:100%;padding:.375rem .75rem;font-size:1rem;font-weight:400;line-height:1.5;color:var(--bs-body-color);-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:var(--bs-body-bg);background-clip:padding-box;transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out}.form-control:disabled{background-color:var(--bs-body-bg)}.form-select{--bs-form-select-bg-img: url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23343a40' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m2 5 6 6 6-6'/%3e%3c/svg%3e\");display:block;width:100%;padding:.375rem 2.25rem .375rem .75rem;font-size:1rem;font-weight:400;line-height:1.5;color:var(--bs-body-color);-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:var(--bs-body-bg);background-image:var(--bs-form-select-bg-img),var(--bs-form-select-bg-icon, none);background-repeat:no-repeat;background-position:right .75rem center;background-size:16px 12px;border:var(--bs-border-width, 1px) solid var(--bs-border-color, oklch(92.2% 0 0));border-radius:var(--bs-border-radius);transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "pipe", type: i1.AsyncPipe, name: "async" }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i2.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2.SelectControlValueAccessor, selector: "select:not([multiple])[formControlName],select:not([multiple])[formControl],select:not([multiple])[ngModel]", inputs: ["compareWith"] }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: ChatMessageComponent, selector: "sq-chat-message", inputs: ["message", "conversation", "suggestedActions", "assistantMessageIcon", "userMessageIcon", "connectionErrorMessageIcon", "searchWarningMessageIcon", "streaming", "canEdit", "canRegenerate", "canCopy", "canDebug", "canLike", "canDislike"], outputs: ["openDocument", "openPreview", "suggestAction", "edit", "copy", "regenerate", "like", "dislike", "debug"] }, { kind: "component", type: TokenProgressBarComponent, selector: "sq-token-progress-bar", inputs: ["instanceId"] }, { kind: "component", type: DebugMessageComponent, selector: "sq-debug-message", inputs: ["data"] }, { kind: "directive", type: TooltipDirective, selector: "[sqTooltip]", inputs: ["sqTooltip", "sqTooltipData", "sqTooltipTemplate", "placement", "fallbackPlacements", "delay", "hoverableTooltip", "tooltipClass"] }, { kind: "pipe", type: TranslocoPipe, name: "transloco" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
1022
996
  }
1023
997
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ChatComponent, decorators: [{
1024
998
  type: Component,
1025
999
  args: [{ selector: 'sq-chat-v3', providers: [
1026
- RestChatService,
1027
- WebSocketChatService,
1000
+ ChatService,
1028
1001
  provideTranslocoScope('chat')
1029
- ], changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, imports: [CommonModule, FormsModule, ChatMessageComponent, TokenProgressBarComponent, DebugMessageComponent, TooltipDirective, TranslocoPipe], template: "<ng-container *ngIf=\"!initializationError\">\n <div *ngIf=\"messages$ | async as messages; else loadingTpl || loadingTplDefault\" class=\"h-100 d-flex flex-column\">\n <!-- Token consumption -->\n <div class=\"ms-1\" *ngIf=\"config?.globalSettings?.displayUserQuotaConsumption || config?.globalSettings?.displayChatTokensConsumption\">\n <ng-container *ngTemplateOutlet=\"tokenConsumptionTpl || defaultTokenConsumptionTpl; context: { $implicit: instanceId }\"></ng-container>\n </div>\n\n <!-- Chat Messages -->\n <ul class=\"d-flex flex-column list-unstyled gap-3 overflow-auto flex-grow-1 pe-2 pb-2\" #messageList>\n <ng-container *ngFor=\"let message of messages; let index = index; let last = last\">\n <!-- Regular messages -->\n <li class=\"list-group-item\"\n *ngIf=\"message.additionalProperties.display && !isEmptyAssistantMessage(message)\"\n [style.--bs-list-group-item-padding-y.rem]=\"'0.6'\"\n [class.opacity-50]=\"messageToEdit && (messageToEdit < (index + 1))\">\n <sq-chat-message\n [class.sq-user-message]=\"message.role === 'user'\"\n [class.last-message]=\"last\"\n [message]=\"message\"\n [conversation]=\"messages\"\n [suggestedActions]=\"last ? message.additionalProperties.$suggestedAction : undefined\"\n [assistantMessageIcon]=\"assistantMessageIcon\"\n [userMessageIcon]=\"userMessageIcon\"\n [connectionErrorMessageIcon]=\"connectionErrorMessageIcon\"\n [searchWarningMessageIcon]=\"searchWarningMessageIcon\"\n [streaming]=\"(chatService.streaming$ | async) && (last || isAssistantLastMessages(messages, index))\"\n [canEdit]=\"(chatService.streaming$ | async) === false && messageToEdit === undefined && message.role === 'user'\"\n [canCopy]=\"((chatService.streaming$ | async) === false || !last) && messageToEdit === undefined && message.role !== 'connection-error' && message.role !== 'search-warning'\"\n [canLike]=\"((chatService.streaming$ | async) === false || !last) && message.role === 'assistant'\"\n [canDislike]=\"((chatService.streaming$ | async) === false || !last) && message.role === 'assistant'\"\n [canDebug]=\"(((chatService.streaming$ | async) === false && last) || (!last && messages[index+1].role !== 'assistant')) && message.role === 'assistant' && (getDebugMessages(index).length > 0) && ((isAdminOrDeletedAdmin || (chatService.userOverride$ | async)) && config?.defaultValues.debug)\"\n [canRegenerate]=\"(chatService.streaming$ | async) === false && (last || (!last && messages[index+1].role !== 'assistant')) && message.role === 'assistant' && messageToEdit === undefined\"\n (edit)=\"editMessage(index)\"\n (copy)=\"copyMessage(index)\"\n (regenerate)=\"regenerateMessage(index)\"\n (openDocument)=\"openOriginalAttachment($event, index)\"\n (openPreview)=\"openAttachmentPreview($event, index)\"\n (suggestAction)=\"suggestActionClick($event, index)\"\n (like)=\"onLike(message, index)\"\n (dislike)=\"onDislike(message, index)\"\n (debug)=\"showDebug(index)\">\n </sq-chat-message>\n </li>\n </ng-container>\n <!-- Loading spinner -->\n <li *ngIf=\"(loading$ | async) === true\">\n <ng-container *ngTemplateOutlet=\"loadingTpl || loadingTplDefault\"></ng-container>\n </li>\n </ul>\n\n <!-- Reporting a feedback form -->\n <div class=\"issue-report p-3 rounded-lg\" *ngIf=\"showReport\">\n <ng-container *ngTemplateOutlet=\"reportTpl || reportTplDefault; context: { $implicit: messageToReport, rank: reportRank, type: reportType }\"></ng-container>\n </div>\n\n <!-- User text input -->\n @if (!showReport) {\n <div class=\"user-input mt-auto\">\n <div class=\"py-2\">\n <div [hidden]=\"!isConnected\">\n <ng-container *ngIf=\"enabledUserInput\" [ngTemplateOutlet]=\"inputTpl\"></ng-container>\n </div>\n <!-- Retry button -->\n <!-- hidden attribute is in conflict with a css rule display: flex -->\n @if(!isConnected){\n <button class=\"btn mb-4 ast-error ast-btn sq-retry\" (click)=\"retryFetch()\">\n <span>{{ 'chat.tryAgain' | transloco }}</span>\n <span *ngIf=\"retrialAttempts\" class=\"ms-2 attempts\">{{ retrialAttempts }}</span>\n </button>\n }\n <div class=\"text-end small text-muted px-3\" *ngIf=\"!!config?.globalSettings?.disclaimer\">\n {{ config?.globalSettings?.disclaimer | transloco }}\n </div>\n </div>\n </div>\n }\n\n <!-- Floating scroll button -->\n <div *ngIf=\"!isAtBottom && !showReport\" class=\"sq-floating-scroll\" [ngClass]=\"enabledUserInput ? 'sq-floating-scroll--when-user-input' : 'sq-floating-scroll--without-user-input'\">\n <button class=\"btn shadow\" (click)=\"scrollDown()\" aria-label=\"Scroll down\">\n <i class=\"fas fa-angle-double-down\"></i>\n </button>\n </div>\n </div>\n</ng-container>\n\n<!-- NG TEMPLATES-->\n\n<ng-template #loadingTplDefault>\n <div class=\"spinner-grow text-primary d-block mx-auto my-5\" role=\"status\">\n <span class=\"visually-hidden\">{{ 'chat.loading' | transloco }}</span>\n </div>\n</ng-template>\n\n<ng-template #inputTpl>\n <div class=\"px-3 py-1\">\n <div class=\"ast-input-container\">\n <button disabled class=\"btn btn-light\" aria-label=\"search\">\n <i class=\"fas fa-search\"></i>\n </button>\n <textarea #questionInput rows=\"1\"\n type=\"text\" class=\"form-control\"\n [placeholder]=\"'chat.askSomething' | transloco\" autofocus\n [(ngModel)]=\"question\"\n (keyup)=\"onKeyUp($event)\"\n (keydown)=\"calculateHeight($event)\"\n [disabled]=\"(loading$ | async) || (chatService.streaming$ | async) || (chatService.stoppingGeneration$ | async)\">\n </textarea>\n <div id=\"chat-actions\" class=\"d-flex gap-2\">\n <button\n *ngIf=\"(chatService.streaming$ | async) === false && (loading$ | async) === false && (chatService.stoppingGeneration$ | async) === false\"\n type=\"button\"\n class=\"btn btn-light\"\n aria-label=\"Send message\"\n [sqTooltip]=\"'chat.sendMessage' | transloco\"\n (click)=\"submitQuestion()\">\n <i class=\"fas fa-paper-plane\"></i>\n </button>\n <button\n *ngIf=\"messageToEdit\"\n aria-label=\"Cancel edition\"\n type=\"button\"\n class=\"btn btn-light\"\n [sqTooltip]=\"'chat.cancelEdition' | transloco\"\n (click)=\"messageToEdit = undefined; question = ''\">\n <i class=\"fas fa-undo-alt\"></i>\n </button>\n <span *ngIf=\"(chatService.streaming$ | async) && (chatService.stoppingGeneration$ | async) === false\" class=\"processing\">\n {{ 'chat.generating' | transloco }}<i class=\"fas fa-spinner fa-pulse\"></i>\n </span>\n <span *ngIf=\"(chatService.stoppingGeneration$ | async)\" class=\"processing\">\n {{ 'chat.stopping' | transloco }}<i class=\"fas fa-spinner fa-pulse\"></i>\n </span>\n <button\n *ngIf=\"(chatService.streaming$ | async) && (chatService.stoppingGeneration$ | async) === false\"\n type=\"button\"\n class=\"btn btn-light\"\n aria-label=\"Stop generating\"\n [sqTooltip]=\"'chat.stopGeneration' | transloco\"\n (click)=\"stopGeneration()\">\n <i class=\"fas fa-stop\"></i>\n </button>\n </div>\n </div>\n </div>\n</ng-template>\n\n<ng-template #reportTplDefault let-message let-rank=\"rank\" let-type=\"type\">\n <div class=\"px-3\">\n <ng-container *ngIf=\"type === 'dislike'\">\n <h5>{{ 'chat.issueType' | transloco }}</h5>\n <select class=\"form-select mb-4\" [(ngModel)]=\"issueType\">\n <option [value]=\"''\">{{ 'chat.chooseIssueType' | transloco }}</option>\n <option *ngFor=\"let type of (issueTypes ?? defaultIssueTypes)\" [value]=\"type\">{{ type | transloco }}</option>\n </select>\n <h5>{{ 'chat.askUnlikeReasons' | transloco }}</h5>\n </ng-container>\n <ng-container *ngIf=\"type === 'like'\">\n <h5>{{ 'chat.askLikeReasons' | transloco }}</h5>\n </ng-container>\n <textarea class=\"form-control border border-neutral-200\" [(ngModel)]=\"reportComment\" [placeholder]=\"'chat.writeComment' | transloco\"></textarea>\n <div class=\"d-flex flex-row-reverse gap-1 mt-2\">\n <button class=\"btn btn-primary\" [disabled]=\"type === 'dislike' && !issueType\" (click)=\"sendReport()\">{{ 'chat.send' | transloco }}</button>\n <button class=\"btn btn-light\" (click)=\"ignoreReport()\">{{ 'chat.doNotSend' | transloco }}</button>\n </div>\n </div>\n</ng-template>\n\n<ng-template #defaultTokenConsumptionTpl let-instanceId>\n <sq-token-progress-bar\n [instanceId]=\"instanceId\">\n </sq-token-progress-bar>\n</ng-template>\n\n<div class=\"debug-messages\" [class.displayed]=\"showDebugMessages\">\n <button *ngIf=\"showDebugMessages\" class=\"btn btn-light shadow back-btn\" (click)=\"showDebugMessages=false\" aria-label=\"Hide debug messages\">\n <i class=\"fas fa-chevron-right\"></i>\n </button>\n <ng-container *ngTemplateOutlet=\"debugMessagesTpl || defaultDebugMessagesTpl; context: { $implicit: debugMessages }\">\n </ng-container>\n</div>\n\n<ng-template #defaultDebugMessagesTpl let-debugMessages>\n <sq-debug-message [data]=\"debugMessages\"></sq-debug-message>\n</ng-template>\n", styles: [".ast-primary{color:var(--ast-primary-color, #005DA7);background-color:var(--ast-primary-bg, #f2f8fe)}.ast-primary-hover{background-color:var(--ast-primary-bg, #f2f8fe)}.ast-primary-hover:hover{color:var(--ast-primary-color, #005DA7)}.ast-secondary{color:var(--ast-secondary-color, #FF732E);background-color:var(--ast-secondary-bg, #FFF8F1)}.ast-error{background-color:var(--ast-error-bg, rgba(249, 58, 55, .2));color:var(--ast-action-buttons-color, inherit)}.ast-error:hover{color:var(--ast-error-color, rgba(249, 58, 55, .7))}.ast-btn{border:0;text-align:left;padding-top:.5rem;padding-bottom:.5rem;display:flex;align-items:center}.dark{--ast-primary-bg: #0d0701;--ast-primary-color: #008cd1;--ast-secondary-bg: #00070e;--ast-secondary-color: #ffa258;--ast-input-bg: #070707;--ast-input-color: rgba(222, 218, 218, .75);--ast-muted-color: rgba(222, 218, 218, .75);--ast-saved-chat-hover-background: #262421;--ast-uploaded-doc-hover-background: #262421;--ast-message-table-border-color: #333333;--ast-message-table-tr-bg: #070707;--ast-message-table-tr-border-color: #222222;--ast-reference-icon-color: white;--ast-reference-icon-active-color: black;--ast-reference-passages-color: white;--ast-reference-expanded-hover-bg: #262421;--ast-message-reference-color: black;--ast-action-buttons-color: white;--ast-action-buttons-hover-color: #6dbee6;--ast-report-bg: #070707}:host ::ng-deep .reference,:host ::ng-deep .message-content .reference,:host ::ng-deep .attachment .reference{position:relative;bottom:var(--ast-reference-bottom, .3em);font-weight:var(--ast-reference-font-weight, bold);padding:var(--ast-reference-padding, 0 .2em);margin:var(--ast-reference-margin, 0 .1em);border-radius:var(--ast-reference-border-radius, .2em);background-color:var(--ast-reference-background-color, lightblue);color:var(--ast-reference-color, black)}:host ::ng-deep .reference,:host ::ng-deep .message-content .reference{font-size:var(--ast-reference-message-font-size, .7em)}:host ::ng-deep .attachment .reference{font-size:var(--ast-reference-attachment-font-size, 13px)}:host{font-size:.875rem}:host>div>.user-input>div:not(.progress),:host>div>.issue-report>div,:host>div>ul>li{width:var(--ast-chat-container-width, 100%);max-width:100%;margin-left:auto;margin-right:auto}:host>div>ul{padding-top:var(--ast-chat-padding-top, 0);padding-bottom:var(--ast-chat-padding-bottom, 0)}li.attachment>p{display:-webkit-box;-webkit-box-orient:vertical;overflow:hidden;-webkit-line-clamp:3}li.attachment.expanded>p{display:block}.progress{--bs-progress-height: 3px}.progress.disabled{--bs-progress-height: 20px;--bs-progress-bar-bg: var(--bs-danger)}.user-input{z-index:1}.user-input ul.list-group{max-height:30vh}.form-control:disabled{background-color:#ededed}a.disabled{cursor:default;opacity:.5}.no-max-height{max-height:initial!important}.sq-floating-scroll{position:absolute;right:50%;text-align:center}.sq-floating-scroll--when-user-input{bottom:75px}.sq-floating-scroll--without-user-input{bottom:15px}.sq-floating-scroll .btn{background-color:#fff}.sq-floating-scroll .btn:hover{background-color:#fff;opacity:.9}.ast-input-container{display:flex;align-items:center;background-color:var(--ast-input-bg, #F8F8F8);border-radius:var(--ast-size-3, .75rem)}.ast-input-container>i{padding-left:var(--ast-size-3, .75rem);color:var(--ast-muted-color, rgba(33, 37, 41, .75))}.ast-input-container textarea{padding-left:var(--ast-size-3, .75rem);padding-right:var(--ast-size-3, .75rem);resize:none}.ast-input-container textarea,.ast-input-container button,.ast-input-container button:hover{background-color:transparent;border:0}.ast-input-container button:hover{color:var(--ast-primary-color, #005DA7)}.ast-input-container button:not(:hover){color:var(--ast-muted-color, rgba(33, 37, 41, .75))}.ast-input-container .processing{display:flex;align-items:center;color:var(--ast-secondary-color, #FF732E);gap:.5rem}sq-chat-message.sq-user-message{float:var(--ast-user-message-float, none)}sq-token-progress-bar{z-index:10;position:absolute;top:0;right:0}.debug-messages{position:fixed;z-index:999999;right:-60%;top:0;width:60%;height:100%;transition:all .5s ease;background-color:var(--bs-body-bg);overflow:auto}.debug-messages .back-btn{position:fixed;right:0%;transition:all .5s ease}.debug-messages.displayed{right:0}.debug-messages.displayed .back-btn{right:60%}.debug-messages sq-debug-message:first-of-type{display:block;width:100%}.btn.sq-retry{display:flex;margin:auto;background:var(--ast-error-bg, rgba(249, 58, 55, .2));font-weight:var(--font-weight-bold, 500)}.btn.sq-retry .attempts{display:flex;border-radius:100%;background:#fff;height:20px;width:20px;place-content:center;align-items:center}.issue-report{background-color:var(--ast-report-bg, white)}.text-end{text-align:right}.small{font-size:.875em}.text-muted{--bs-text-opacity: 1;color:var(--bs-secondary-color)}.d-flex{display:flex}.flex-row-reverse{flex-direction:row-reverse}.flex-grow-1{flex-grow:1}.spinner-grow,.spinner-border{display:inline-block;width:var(--bs-spinner-width);height:var(--bs-spinner-height);vertical-align:var(--bs-spinner-vertical-align);border-radius:50%;animation:var(--bs-spinner-animation-speed) linear infinite var(--bs-spinner-animation-name)}.text-primary{--bs-text-opacity: 1;color:rgba(var(--bs-primary-rgb),var(--bs-text-opacity))}.d-block{display:block}.btn{--bs-border-radius: .25rem;--bs-btn-padding-x: .75rem;--bs-btn-padding-y: .375rem;--bs-btn-font-family: ;--bs-btn-font-size: 1rem;--bs-btn-font-weight: 400;--bs-btn-line-height: 1.5;--bs-btn-color: var(--bs-body-color);--bs-btn-bg: transparent;--bs-btn-border-width: var(--bs-border-width);--bs-btn-border-color: transparent;--bs-btn-border-radius: var(--bs-border-radius);--bs-btn-hover-border-color: transparent;--bs-btn-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 1px rgba(0, 0, 0, .075);--bs-btn-disabled-opacity: .65;--bs-btn-focus-box-shadow: 0 0 0 .25rem rgba(var(--bs-btn-focus-shadow-rgb), .5);display:inline-block;padding:var(--bs-btn-padding-y) var(--bs-btn-padding-x);font-family:var(--bs-btn-font-family);font-size:var(--bs-btn-font-size);font-weight:var(--bs-btn-font-weight);line-height:var(--bs-btn-line-height);color:var(--bs-btn-color);text-align:center;text-decoration:none;vertical-align:middle;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;user-select:none;border:var(--bs-btn-border-width) solid var(--bs-btn-border-color);border-radius:var(--bs-btn-border-radius);background-color:var(--bs-btn-bg);transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}.btn-primary{--bs-btn-color: #fff;--bs-btn-bg: #0d6efd;--bs-btn-border-color: #0d6efd;--bs-btn-hover-color: #fff;--bs-btn-hover-bg: #0b5ed7;--bs-btn-hover-border-color: #0a58ca;--bs-btn-focus-shadow-rgb: 49, 132, 253;--bs-btn-active-color: #fff;--bs-btn-active-bg: #0a58ca;--bs-btn-active-border-color: #0a53be;--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);--bs-btn-disabled-color: #fff;--bs-btn-disabled-bg: #0d6efd;--bs-btn-disabled-border-color: #0d6efd}.btn-light{--bs-btn-color: #000;--bs-btn-bg: #f8f9fa;--bs-btn-border-color: #f8f9fa;--bs-btn-hover-color: #000;--bs-btn-hover-bg: #d3d4d5;--bs-btn-hover-border-color: #c6c7c8;--bs-btn-focus-shadow-rgb: 211, 212, 213;--bs-btn-active-color: #000;--bs-btn-active-bg: #c6c7c8;--bs-btn-active-border-color: #babbbc;--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);--bs-btn-disabled-color: #000;--bs-btn-disabled-bg: #f8f9fa;--bs-btn-disabled-border-color: #f8f9fa}.form-control{display:block;width:100%;padding:.375rem .75rem;font-size:1rem;font-weight:400;line-height:1.5;color:var(--bs-body-color);-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:var(--bs-body-bg);background-clip:padding-box;transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out}.form-control:disabled{background-color:var(--bs-body-bg)}.form-select{--bs-form-select-bg-img: url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23343a40' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m2 5 6 6 6-6'/%3e%3c/svg%3e\");display:block;width:100%;padding:.375rem 2.25rem .375rem .75rem;font-size:1rem;font-weight:400;line-height:1.5;color:var(--bs-body-color);-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:var(--bs-body-bg);background-image:var(--bs-form-select-bg-img),var(--bs-form-select-bg-icon, none);background-repeat:no-repeat;background-position:right .75rem center;background-size:16px 12px;border:var(--bs-border-width, 1px) solid var(--bs-border-color, oklch(92.2% 0 0));border-radius:var(--bs-border-radius);transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out}\n"] }]
1002
+ ], changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, imports: [CommonModule, FormsModule, ChatMessageComponent, TokenProgressBarComponent, DebugMessageComponent, TooltipDirective, TranslocoPipe], template: "<ng-container *ngIf=\"!initializationError\">\n <div *ngIf=\"messages$ | async as messages; else loadingTpl || loadingTplDefault\" class=\"h-100 d-flex flex-column\">\n <!-- Token consumption -->\n <div class=\"ms-1\" *ngIf=\"config?.globalSettings?.displayUserQuotaConsumption || config?.globalSettings?.displayChatTokensConsumption\">\n <ng-container *ngTemplateOutlet=\"tokenConsumptionTpl || defaultTokenConsumptionTpl; context: { $implicit: instanceId }\"></ng-container>\n </div>\n\n <!-- Chat Messages -->\n <ul class=\"d-flex flex-column list-unstyled gap-3 overflow-auto flex-grow-1 pe-2 pb-2\" #messageList>\n <ng-container *ngFor=\"let message of messages; let index = index; let last = last\">\n <!-- Regular messages -->\n <li class=\"list-group-item\"\n *ngIf=\"message.additionalProperties.display && !isEmptyAssistantMessage(message)\"\n [style.--bs-list-group-item-padding-y.rem]=\"'0.6'\"\n [class.opacity-50]=\"indexMessageToEdit && (indexMessageToEdit < (index + 1))\">\n <sq-chat-message\n [class.sq-user-message]=\"message.role === 'user'\"\n [class.last-message]=\"last\"\n [message]=\"message\"\n [conversation]=\"messages\"\n [suggestedActions]=\"last ? message.additionalProperties.$suggestedAction : undefined\"\n [assistantMessageIcon]=\"assistantMessageIcon\"\n [userMessageIcon]=\"userMessageIcon\"\n [connectionErrorMessageIcon]=\"connectionErrorMessageIcon\"\n [searchWarningMessageIcon]=\"searchWarningMessageIcon\"\n [streaming]=\"(chatService.streaming$ | async) && (last || isAssistantLastMessages(messages, index))\"\n [canEdit]=\"(chatService.streaming$ | async) === false && indexMessageToEdit === undefined && message.role === 'user'\"\n [canCopy]=\"((chatService.streaming$ | async) === false || !last) && indexMessageToEdit === undefined && message.role !== 'connection-error' && message.role !== 'search-warning'\"\n [canLike]=\"((chatService.streaming$ | async) === false || !last) && message.role === 'assistant'\"\n [canDislike]=\"((chatService.streaming$ | async) === false || !last) && message.role === 'assistant'\"\n [canDebug]=\"(((chatService.streaming$ | async) === false && last) || (!last && messages[index+1].role !== 'assistant')) && message.role === 'assistant' && (getDebugMessages(message, index).length > 0) && ((isAdminOrDeletedAdmin || (chatService.userOverride$ | async)) && config?.defaultValues.debug)\"\n [canRegenerate]=\"(chatService.streaming$ | async) === false && (last || (!last && messages[index+1].role !== 'assistant')) && message.role === 'assistant' && indexMessageToEdit === undefined\"\n (edit)=\"editMessage(message, index)\"\n (copy)=\"copyMessage(message, index)\"\n (regenerate)=\"regenerateMessage(message, index)\"\n (openDocument)=\"openOriginalAttachment($event, message, index)\"\n (openPreview)=\"openAttachmentPreview($event, message, index)\"\n (suggestAction)=\"suggestActionClick($event, index)\"\n (like)=\"onLike(message, index)\"\n (dislike)=\"onDislike(message, index)\"\n (debug)=\"showDebug(message, index)\">\n </sq-chat-message>\n </li>\n </ng-container>\n <!-- Loading spinner -->\n <li *ngIf=\"(loading$ | async) === true\">\n <ng-container *ngTemplateOutlet=\"loadingTpl || loadingTplDefault\"></ng-container>\n </li>\n </ul>\n\n <!-- Reporting a feedback form -->\n <div class=\"issue-report p-3 rounded-lg\" *ngIf=\"showReport\">\n <ng-container *ngTemplateOutlet=\"reportTpl || reportTplDefault; context: { $implicit: messageToReport, rank: reportRank, type: reportType }\"></ng-container>\n </div>\n\n <!-- User text input -->\n @if (!showReport) {\n <div class=\"user-input mt-auto\">\n <div class=\"py-2\">\n <div [hidden]=\"!isConnected\">\n <ng-container *ngIf=\"enabledUserInput\" [ngTemplateOutlet]=\"inputTpl\"></ng-container>\n </div>\n <!-- Retry button -->\n <!-- hidden attribute is in conflict with a css rule display: flex -->\n @if(!isConnected){\n <button class=\"btn mb-4 ast-error ast-btn sq-retry\" (click)=\"retryFetch()\">\n <span>{{ 'chat.tryAgain' | transloco }}</span>\n <span *ngIf=\"retrialAttempts\" class=\"ms-2 attempts\">{{ retrialAttempts }}</span>\n </button>\n }\n <div class=\"text-end small text-muted px-3\" *ngIf=\"!!config?.globalSettings?.disclaimer\">\n {{ config?.globalSettings?.disclaimer | transloco }}\n </div>\n </div>\n </div>\n }\n\n <!-- Floating scroll button -->\n <div *ngIf=\"!isAtBottom && !showReport\" class=\"sq-floating-scroll\" [ngClass]=\"enabledUserInput ? 'sq-floating-scroll--when-user-input' : 'sq-floating-scroll--without-user-input'\">\n <button class=\"btn shadow\" (click)=\"scrollDown()\" aria-label=\"Scroll down\">\n <i class=\"fas fa-angle-double-down\"></i>\n </button>\n </div>\n </div>\n</ng-container>\n\n<!-- NG TEMPLATES-->\n\n<ng-template #loadingTplDefault>\n <div class=\"spinner-grow text-primary d-block mx-auto my-5\" role=\"status\">\n <span class=\"visually-hidden\">{{ 'chat.loading' | transloco }}</span>\n </div>\n</ng-template>\n\n<ng-template #inputTpl>\n <div class=\"px-3 py-1\">\n <div class=\"ast-input-container\">\n <button disabled class=\"btn btn-light\" aria-label=\"search\">\n <i class=\"fas fa-search\"></i>\n </button>\n <textarea #questionInput rows=\"1\"\n type=\"text\" class=\"form-control\"\n [placeholder]=\"'chat.askSomething' | transloco\" autofocus\n [(ngModel)]=\"question\"\n (keyup)=\"onKeyUp($event)\"\n (keydown)=\"calculateHeight($event)\"\n [disabled]=\"(loading$ | async) || (chatService.streaming$ | async) || (chatService.stoppingGeneration$ | async)\">\n </textarea>\n <div id=\"chat-actions\" class=\"d-flex gap-2\">\n <button\n *ngIf=\"(chatService.streaming$ | async) === false && (loading$ | async) === false && (chatService.stoppingGeneration$ | async) === false\"\n type=\"button\"\n class=\"btn btn-light\"\n aria-label=\"Send message\"\n [sqTooltip]=\"'chat.sendMessage' | transloco\"\n (click)=\"submitQuestion()\">\n <i class=\"fas fa-paper-plane\"></i>\n </button>\n <button\n *ngIf=\"indexMessageToEdit\"\n aria-label=\"Cancel edition\"\n type=\"button\"\n class=\"btn btn-light\"\n [sqTooltip]=\"'chat.cancelEdition' | transloco\"\n (click)=\"indexMessageToEdit = undefined; question = ''\">\n <i class=\"fas fa-undo-alt\"></i>\n </button>\n <span *ngIf=\"(chatService.streaming$ | async) && (chatService.stoppingGeneration$ | async) === false\" class=\"processing\">\n {{ 'chat.generating' | transloco }}<i class=\"fas fa-spinner fa-pulse\"></i>\n </span>\n <span *ngIf=\"(chatService.stoppingGeneration$ | async)\" class=\"processing\">\n {{ 'chat.stopping' | transloco }}<i class=\"fas fa-spinner fa-pulse\"></i>\n </span>\n <button\n *ngIf=\"(chatService.streaming$ | async) && (chatService.stoppingGeneration$ | async) === false\"\n type=\"button\"\n class=\"btn btn-light\"\n aria-label=\"Stop generating\"\n [sqTooltip]=\"'chat.stopGeneration' | transloco\"\n (click)=\"stopGeneration()\">\n <i class=\"fas fa-stop\"></i>\n </button>\n </div>\n </div>\n </div>\n</ng-template>\n\n<ng-template #reportTplDefault let-message let-rank=\"rank\" let-type=\"type\">\n <div class=\"px-3\">\n <ng-container *ngIf=\"type === 'dislike'\">\n <h5>{{ 'chat.issueType' | transloco }}</h5>\n <select class=\"form-select mb-4\" [(ngModel)]=\"issueType\">\n <option [value]=\"''\">{{ 'chat.chooseIssueType' | transloco }}</option>\n <option *ngFor=\"let type of (issueTypes ?? defaultIssueTypes)\" [value]=\"type\">{{ type | transloco }}</option>\n </select>\n <h5>{{ 'chat.askUnlikeReasons' | transloco }}</h5>\n </ng-container>\n <ng-container *ngIf=\"type === 'like'\">\n <h5>{{ 'chat.askLikeReasons' | transloco }}</h5>\n </ng-container>\n <textarea class=\"form-control border border-neutral-200\" [(ngModel)]=\"reportComment\" [placeholder]=\"'chat.writeComment' | transloco\"></textarea>\n <div class=\"d-flex flex-row-reverse gap-1 mt-2\">\n <button class=\"btn btn-primary\" [disabled]=\"type === 'dislike' && !issueType\" (click)=\"sendReport()\">{{ 'chat.send' | transloco }}</button>\n <button class=\"btn btn-light\" (click)=\"ignoreReport()\">{{ 'chat.doNotSend' | transloco }}</button>\n </div>\n </div>\n</ng-template>\n\n<ng-template #defaultTokenConsumptionTpl let-instanceId>\n <sq-token-progress-bar\n [instanceId]=\"instanceId\">\n </sq-token-progress-bar>\n</ng-template>\n\n<div class=\"debug-messages\" [class.displayed]=\"showDebugMessages\">\n <button *ngIf=\"showDebugMessages\" class=\"btn btn-light shadow back-btn\" (click)=\"showDebugMessages=false\" aria-label=\"Hide debug messages\">\n <i class=\"fas fa-chevron-right\"></i>\n </button>\n <ng-container *ngTemplateOutlet=\"debugMessagesTpl || defaultDebugMessagesTpl; context: { $implicit: debugMessages }\">\n </ng-container>\n</div>\n\n<ng-template #defaultDebugMessagesTpl let-debugMessages>\n <sq-debug-message [data]=\"debugMessages\"></sq-debug-message>\n</ng-template>\n", styles: [".ast-primary{color:var(--ast-primary-color, #005DA7);background-color:var(--ast-primary-bg, #f2f8fe)}.ast-primary-hover{background-color:var(--ast-primary-bg, #f2f8fe)}.ast-primary-hover:hover{color:var(--ast-primary-color, #005DA7)}.ast-secondary{color:var(--ast-secondary-color, #FF732E);background-color:var(--ast-secondary-bg, #FFF8F1)}.ast-error{background-color:var(--ast-error-bg, rgba(249, 58, 55, .2));color:var(--ast-action-buttons-color, inherit)}.ast-error:hover{color:var(--ast-error-color, rgba(249, 58, 55, .7))}.ast-btn{border:0;text-align:left;padding-top:.5rem;padding-bottom:.5rem;display:flex;align-items:center}.dark{--ast-primary-bg: #0d0701;--ast-primary-color: #008cd1;--ast-secondary-bg: #00070e;--ast-secondary-color: #ffa258;--ast-input-bg: #070707;--ast-input-color: rgba(222, 218, 218, .75);--ast-muted-color: rgba(222, 218, 218, .75);--ast-saved-chat-hover-background: #262421;--ast-uploaded-doc-hover-background: #262421;--ast-message-table-border-color: #333333;--ast-message-table-tr-bg: #070707;--ast-message-table-tr-border-color: #222222;--ast-reference-icon-color: white;--ast-reference-icon-active-color: black;--ast-reference-passages-color: white;--ast-reference-expanded-hover-bg: #262421;--ast-message-reference-color: black;--ast-action-buttons-color: white;--ast-action-buttons-hover-color: #6dbee6;--ast-report-bg: #070707}:host ::ng-deep .reference,:host ::ng-deep .message-content .reference,:host ::ng-deep .attachment .reference{position:relative;bottom:var(--ast-reference-bottom, .3em);font-weight:var(--ast-reference-font-weight, bold);padding:var(--ast-reference-padding, 0 .2em);margin:var(--ast-reference-margin, 0 .1em);border-radius:var(--ast-reference-border-radius, .2em);background-color:var(--ast-reference-background-color, lightblue);color:var(--ast-reference-color, black)}:host ::ng-deep .reference,:host ::ng-deep .message-content .reference{font-size:var(--ast-reference-message-font-size, .7em)}:host ::ng-deep .attachment .reference{font-size:var(--ast-reference-attachment-font-size, 13px)}:host{font-size:.875rem}:host>div>.user-input>div:not(.progress),:host>div>.issue-report>div,:host>div>ul>li{width:var(--ast-chat-container-width, 100%);max-width:100%;margin-left:auto;margin-right:auto}:host>div>ul{padding-top:var(--ast-chat-padding-top, 0);padding-bottom:var(--ast-chat-padding-bottom, 0)}li.attachment>p{display:-webkit-box;-webkit-box-orient:vertical;overflow:hidden;-webkit-line-clamp:3}li.attachment.expanded>p{display:block}.progress{--bs-progress-height: 3px}.progress.disabled{--bs-progress-height: 20px;--bs-progress-bar-bg: var(--bs-danger)}.user-input{z-index:1}.user-input ul.list-group{max-height:30vh}.form-control:disabled{background-color:#ededed}a.disabled{cursor:default;opacity:.5}.no-max-height{max-height:initial!important}.sq-floating-scroll{position:absolute;right:50%;text-align:center}.sq-floating-scroll--when-user-input{bottom:75px}.sq-floating-scroll--without-user-input{bottom:15px}.sq-floating-scroll .btn{background-color:#fff}.sq-floating-scroll .btn:hover{background-color:#fff;opacity:.9}.ast-input-container{display:flex;align-items:center;background-color:var(--ast-input-bg, #F8F8F8);border-radius:var(--ast-size-3, .75rem)}.ast-input-container>i{padding-left:var(--ast-size-3, .75rem);color:var(--ast-muted-color, rgba(33, 37, 41, .75))}.ast-input-container textarea{padding-left:var(--ast-size-3, .75rem);padding-right:var(--ast-size-3, .75rem);resize:none}.ast-input-container textarea,.ast-input-container button,.ast-input-container button:hover{background-color:transparent;border:0}.ast-input-container button:hover{color:var(--ast-primary-color, #005DA7)}.ast-input-container button:not(:hover){color:var(--ast-muted-color, rgba(33, 37, 41, .75))}.ast-input-container .processing{display:flex;align-items:center;color:var(--ast-secondary-color, #FF732E);gap:.5rem}sq-chat-message.sq-user-message{float:var(--ast-user-message-float, none)}sq-token-progress-bar{z-index:10;position:absolute;top:0;right:0}.debug-messages{position:fixed;z-index:999999;right:-60%;top:0;width:60%;height:100%;transition:all .5s ease;background-color:var(--bs-body-bg);overflow:auto}.debug-messages .back-btn{position:fixed;right:0%;transition:all .5s ease}.debug-messages.displayed{right:0}.debug-messages.displayed .back-btn{right:60%}.debug-messages sq-debug-message:first-of-type{display:block;width:100%}.btn.sq-retry{display:flex;margin:auto;background:var(--ast-error-bg, rgba(249, 58, 55, .2));font-weight:var(--font-weight-bold, 500)}.btn.sq-retry .attempts{display:flex;border-radius:100%;background:#fff;height:20px;width:20px;place-content:center;align-items:center}.issue-report{background-color:var(--ast-report-bg, white)}.text-end{text-align:right}.small{font-size:.875em}.text-muted{--bs-text-opacity: 1;color:var(--bs-secondary-color)}.d-flex{display:flex}.flex-row-reverse{flex-direction:row-reverse}.flex-grow-1{flex-grow:1}.spinner-grow,.spinner-border{display:inline-block;width:var(--bs-spinner-width);height:var(--bs-spinner-height);vertical-align:var(--bs-spinner-vertical-align);border-radius:50%;animation:var(--bs-spinner-animation-speed) linear infinite var(--bs-spinner-animation-name)}.text-primary{--bs-text-opacity: 1;color:rgba(var(--bs-primary-rgb),var(--bs-text-opacity))}.d-block{display:block}.btn{--bs-border-radius: .25rem;--bs-btn-padding-x: .75rem;--bs-btn-padding-y: .375rem;--bs-btn-font-family: ;--bs-btn-font-size: 1rem;--bs-btn-font-weight: 400;--bs-btn-line-height: 1.5;--bs-btn-color: var(--bs-body-color);--bs-btn-bg: transparent;--bs-btn-border-width: var(--bs-border-width);--bs-btn-border-color: transparent;--bs-btn-border-radius: var(--bs-border-radius);--bs-btn-hover-border-color: transparent;--bs-btn-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 1px rgba(0, 0, 0, .075);--bs-btn-disabled-opacity: .65;--bs-btn-focus-box-shadow: 0 0 0 .25rem rgba(var(--bs-btn-focus-shadow-rgb), .5);display:inline-block;padding:var(--bs-btn-padding-y) var(--bs-btn-padding-x);font-family:var(--bs-btn-font-family);font-size:var(--bs-btn-font-size);font-weight:var(--bs-btn-font-weight);line-height:var(--bs-btn-line-height);color:var(--bs-btn-color);text-align:center;text-decoration:none;vertical-align:middle;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;user-select:none;border:var(--bs-btn-border-width) solid var(--bs-btn-border-color);border-radius:var(--bs-btn-border-radius);background-color:var(--bs-btn-bg);transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}.btn-primary{--bs-btn-color: #fff;--bs-btn-bg: #0d6efd;--bs-btn-border-color: #0d6efd;--bs-btn-hover-color: #fff;--bs-btn-hover-bg: #0b5ed7;--bs-btn-hover-border-color: #0a58ca;--bs-btn-focus-shadow-rgb: 49, 132, 253;--bs-btn-active-color: #fff;--bs-btn-active-bg: #0a58ca;--bs-btn-active-border-color: #0a53be;--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);--bs-btn-disabled-color: #fff;--bs-btn-disabled-bg: #0d6efd;--bs-btn-disabled-border-color: #0d6efd}.btn-light{--bs-btn-color: #000;--bs-btn-bg: #f8f9fa;--bs-btn-border-color: #f8f9fa;--bs-btn-hover-color: #000;--bs-btn-hover-bg: #d3d4d5;--bs-btn-hover-border-color: #c6c7c8;--bs-btn-focus-shadow-rgb: 211, 212, 213;--bs-btn-active-color: #000;--bs-btn-active-bg: #c6c7c8;--bs-btn-active-border-color: #babbbc;--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);--bs-btn-disabled-color: #000;--bs-btn-disabled-bg: #f8f9fa;--bs-btn-disabled-border-color: #f8f9fa}.form-control{display:block;width:100%;padding:.375rem .75rem;font-size:1rem;font-weight:400;line-height:1.5;color:var(--bs-body-color);-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:var(--bs-body-bg);background-clip:padding-box;transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out}.form-control:disabled{background-color:var(--bs-body-bg)}.form-select{--bs-form-select-bg-img: url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23343a40' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m2 5 6 6 6-6'/%3e%3c/svg%3e\");display:block;width:100%;padding:.375rem 2.25rem .375rem .75rem;font-size:1rem;font-weight:400;line-height:1.5;color:var(--bs-body-color);-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:var(--bs-body-bg);background-image:var(--bs-form-select-bg-img),var(--bs-form-select-bg-icon, none);background-repeat:no-repeat;background-position:right .75rem center;background-size:16px 12px;border:var(--bs-border-width, 1px) solid var(--bs-border-color, oklch(92.2% 0 0));border-radius:var(--bs-border-radius);transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out}\n"] }]
1030
1003
  }], propDecorators: { instanceId: [{
1031
1004
  type: Input
1032
1005
  }], query: [{
1033
1006
  type: Input
1034
1007
  }], queryChangeShouldTriggerReload: [{
1035
1008
  type: Input
1036
- }], protocol: [{
1037
- type: Input
1038
1009
  }], messageHandlers: [{
1039
1010
  type: Input
1040
1011
  }], automaticScrollToLastResponse: [{
@@ -1090,4 +1061,4 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImpo
1090
1061
  }], appConfig: [{
1091
1062
  type: Input
1092
1063
  }] } });
1093
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2hhdC5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9wcm9qZWN0cy9hc3Npc3RhbnQvY2hhdC9jaGF0LmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uL3Byb2plY3RzL2Fzc2lzdGFudC9jaGF0L2NoYXQuY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBQy9DLE9BQU8sRUFBRSx1QkFBdUIsRUFBRSxpQkFBaUIsRUFBRSxTQUFTLEVBQUUsWUFBWSxFQUFjLFlBQVksRUFBRSxLQUFLLEVBQWdDLE1BQU0sRUFBOEIsU0FBUyxFQUFFLE1BQU0sRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUMxTixPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDN0MsT0FBTyxFQUFFLGFBQWEsRUFBRSxnQkFBZ0IsRUFBRSxxQkFBcUIsRUFBRSxNQUFNLG9CQUFvQixDQUFDO0FBQzVGLE9BQU8sRUFBaUIsa0JBQWtCLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUN2RSxPQUFPLEVBQUUsZUFBZSxFQUFFLFlBQVksRUFBRSxhQUFhLEVBQUUsTUFBTSxFQUFFLFNBQVMsRUFBRSxHQUFHLEVBQUUsS0FBSyxFQUFFLEVBQUUsRUFBRSxTQUFTLEVBQUUsSUFBSSxFQUFFLEdBQUcsRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUU3SCxPQUFPLEVBQW1DLGVBQWUsRUFBRSxlQUFlLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUVwRyxPQUFPLEVBQUUsb0JBQW9CLEVBQUUsTUFBTSx1Q0FBdUMsQ0FBQztBQUM3RSxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDN0MsT0FBTyxFQUFFLHFCQUFxQixFQUFFLE1BQU0seUNBQXlDLENBQUM7QUFDaEYsT0FBTyxFQUFFLHNCQUFzQixFQUFFLE1BQU0sNEJBQTRCLENBQUM7QUFDcEUsT0FBTyxFQUFFLGVBQWUsRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBQ3RELE9BQU8sRUFBRSxvQkFBb0IsRUFBRSxNQUFNLGlDQUFpQyxDQUFDO0FBQ3ZFLE9BQU8sRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLDhCQUE4QixDQUFDO0FBQ2hFLE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSwyQkFBMkIsQ0FBQztBQUMxRCxPQUFPLEVBQUUseUJBQXlCLEVBQUUsTUFBTSxtREFBbUQsQ0FBQztBQUM5RixPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSw2QkFBNkIsQ0FBQztBQUcvRCxPQUFPLEVBQUUsb0JBQW9CLEVBQUUsTUFBTSwwQkFBMEIsQ0FBQzs7OztBQWVoRSxNQUFNLE9BQU8sYUFBYTtJQWIxQjtRQWVTLHFCQUFnQixHQUFHLE1BQU0sQ0FBQyxvQkFBb0IsQ0FBQyxDQUFDO1FBQ2hELGdCQUFXLEdBQUcsTUFBTSxDQUFDLGVBQWUsQ0FBQyxDQUFDO1FBQ3RDLDJCQUFzQixHQUFHLE1BQU0sQ0FBQyxzQkFBc0IsQ0FBQyxDQUFDO1FBQ3hELGtCQUFhLEdBQUcsTUFBTSxDQUFDLGFBQWEsQ0FBQyxDQUFDO1FBQ3RDLHFCQUFnQixHQUFHLE1BQU0sQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDO1FBQzVDLFFBQUcsR0FBRyxNQUFNLENBQUMsaUJBQWlCLENBQUMsQ0FBQztRQUNoQyx5QkFBb0IsR0FBRyxNQUFNLENBQUMsb0JBQW9CLENBQUMsQ0FBQztRQUMxQyxjQUFTLEdBQUcsTUFBTSxDQUFDLGdCQUFnQixDQUFDLENBQUM7UUFJdEQsK0NBQStDO1FBQ3RDLFVBQUssR0FBVSxJQUFJLENBQUMsYUFBYSxDQUFDLEtBQUssQ0FBQztRQVFqRCwyREFBMkQ7UUFDbEQsYUFBUSxHQUF5QixXQUFXLENBQUM7UUFDdEQseURBQXlEO1FBQ2hELG9CQUFlLEdBQXFDLElBQUksR0FBRyxFQUFFLENBQUM7UUFDdkUsMkdBQTJHO1FBQ2xHLGtDQUE2QixHQUFHLEtBQUssQ0FBQztRQUMvQyx1RkFBdUY7UUFDOUUsdUJBQWtCLEdBQUcsS0FBSyxDQUFDO1FBR3BDLDZDQUE2QztRQUNwQyx5QkFBb0IsR0FBRyxZQUFZLENBQUM7UUFPN0Msb0VBQW9FO1FBQzNELGlDQUE0QixHQUF3QixFQUFFLENBQUM7UUFDaEUsMEVBQTBFO1FBQ2hFLGVBQVUsR0FBRyxJQUFJLFlBQVksRUFBaUIsQ0FBQztRQUN6RCwrRUFBK0U7UUFDL0UsbUVBQW1FO1FBQ2hELGFBQVEsR0FBRyxJQUFJLFlBQVksQ0FBVSxLQUFLLENBQUMsQ0FBQztRQUMvRCw4RUFBOEU7UUFDNUQsWUFBTyxHQUFHLElBQUksWUFBWSxFQUFjLENBQUM7UUFDakQsU0FBSSxHQUFHLElBQUksWUFBWSxFQUFpQixDQUFDO1FBQ25ELG9IQUFvSDtRQUMxRyxpQkFBWSxHQUFHLElBQUksWUFBWSxFQUFXLENBQUM7UUFDckQseUhBQXlIO1FBQy9HLGdCQUFXLEdBQUcsSUFBSSxZQUFZLEVBQXlCLENBQUM7UUFDbEUseUVBQXlFO1FBQy9ELGtCQUFhLEdBQUcsSUFBSSxZQUFZLEVBQW1CLENBQUM7UUFjOUQsY0FBUyxHQUFHLElBQUksZUFBZSxDQUE0QixTQUFTLENBQUMsQ0FBQztRQUN0RSwwQkFBcUIsR0FBRyxLQUFLLENBQUM7UUFDOUIsYUFBUSxHQUFHLEVBQUUsQ0FBQztRQUVOLFNBQUksR0FBRyxJQUFJLFlBQVksRUFBRSxDQUFDO1FBUWxDLGFBQVEsR0FBRyxJQUFJLGVBQWUsQ0FBNEIsU0FBUyxDQUFDLENBQUM7UUFFckUsd0JBQW1CLEdBQUcsS0FBSyxDQUFDO1FBQzVCLGVBQVUsR0FBRyxJQUFJLENBQUM7UUFDbEIsd0JBQW1CLEdBQUcsS0FBSyxDQUFDO1FBQzVCLHFCQUFnQixHQUFHLEtBQUssQ0FBQztRQUN6QixnQkFBVyxHQUFHLElBQUksQ0FBQyxDQUFDLCtDQUErQztRQUVuRSx5RUFBeUU7UUFDakUscUNBQWdDLEdBQUcsS0FBSyxDQUFDO1FBSWpELHNCQUFpQixHQUFhO1lBQzVCLHVCQUF1QjtZQUN2Qix3QkFBd0I7WUFDeEIseUJBQXlCO1lBQ3pCLHFCQUFxQjtZQUNyQiwrQkFBK0I7WUFDL0IsaUJBQWlCO1NBQ2xCLENBQUM7UUFDRixjQUFTLEdBQVcsRUFBRSxDQUFDO1FBSXZCLGVBQVUsR0FBdUIsU0FBUyxDQUFDO1FBQzNDLGVBQVUsR0FBRyxLQUFLLENBQUM7UUFJbkIsc0JBQWlCLEdBQUcsS0FBSyxDQUFDO1FBTWxCLHdCQUFtQixHQUE2QixTQUFTLENBQUM7S0ErK0JuRTtJQTcrQkMsUUFBUTtRQUNOLElBQUksSUFBSSxDQUFDLFNBQVMsRUFBRSxDQUFDO1lBQ25CLGVBQWUsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLENBQUM7UUFDbEMsQ0FBQztRQUVELElBQUksQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUNYLEVBQUUsQ0FBQyxlQUFlLEVBQUUsQ0FBQyxDQUFDLElBQUksQ0FDeEIsR0FBRyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLHNCQUFzQixFQUFFLENBQUMsRUFDdkMsR0FBRyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxjQUFjLEVBQUUsQ0FBQyxFQUMzQyxTQUFTLENBQUMsR0FBRyxFQUFFLENBQUMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxXQUFXLENBQUMsRUFDN0MsTUFBTSxDQUFDLFVBQVUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxFQUNsQyxTQUFTLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLElBQUksRUFBRSxDQUFDLEVBQ3ZDLFNBQVMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxXQUFXLENBQUMsWUFBWSxDQUFDLEVBQzdDLE1BQU0sQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsRUFDNUIsR0FBRyxDQUFDLENBQUMsQ0FBQyxFQUFFO1lBQ04sSUFBSSxJQUFJLENBQUMsV0FBVyxZQUFZLG9CQUFvQixFQUFFLENBQUM7Z0JBQ3JELElBQUksQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxXQUFXLENBQUMsVUFBVSxDQUFDLENBQUM7WUFDcEQsQ0FBQztZQUNELElBQUksQ0FBQyxVQUFVLEVBQUUsQ0FBQztRQUNwQixDQUFDLENBQUMsRUFDRixHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLFlBQVksRUFBRSxDQUFDLEVBQ3pDLFNBQVMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxXQUFXLENBQUMsYUFBYSxDQUFDLEVBQzlDLFNBQVMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxXQUFXLENBQUMsZ0JBQWdCLENBQUMsRUFDakQsR0FBRyxDQUFDLE1BQU0sQ0FBQyxFQUFFO1lBQ1gsSUFBSSxDQUFDLHFCQUFxQixHQUFHLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxTQUFVLENBQUMsZUFBZSxJQUFJLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxTQUFVLENBQUMsZ0JBQWdCLElBQUksS0FBSyxDQUFDO1lBQzVJLElBQUksQ0FBQyxNQUFNLEdBQUcsTUFBTyxDQUFDO1lBQ3RCLElBQUksQ0FBQyxnQkFBZ0IsR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDLFlBQVksQ0FBQyxnQkFBZ0IsQ0FBQztZQUNsRSxJQUFJLENBQUMsVUFBVSxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUMsYUFBYSxFQUFFLFVBQVUsRUFBRSxNQUFNLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsYUFBYyxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUMsU0FBUyxDQUFDO1lBQ3BILElBQUksQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDO1lBQzFCLElBQUksQ0FBQztnQkFDSCxJQUFJLENBQUMsc0JBQXNCLEVBQUUsQ0FBQztnQkFDOUIsSUFBRyxDQUFDLElBQUksQ0FBQyxtQkFBbUIsRUFBRSxDQUFDO29CQUM3QixJQUFJLENBQUMsY0FBYyxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLGdDQUFnQztvQkFDOUYsSUFBSSxDQUFDLGNBQWMsRUFBRSxDQUFDO29CQUN0QixJQUFJLENBQUMsa0JBQWtCLEVBQUUsQ0FBQztvQkFDMUIsSUFBSSxDQUFDLG1CQUFtQixHQUFHLElBQUksQ0FBQztnQkFDbEMsQ0FBQztZQUNILENBQUM7WUFBQyxPQUFPLEtBQUssRUFBRSxDQUFDO2dCQUNmLElBQUksQ0FBQyxtQkFBbUIsR0FBRyxJQUFJLENBQUE7Z0JBQy9CLE1BQU0sS0FBSyxDQUFDO1lBQ2QsQ0FBQztRQUNILENBQUMsQ0FBQyxDQUNILENBQUMsU0FBUyxFQUFFLENBQ2QsQ0FBQztJQUNKLENBQUM7SUFFRCxXQUFXLENBQUMsT0FBc0I7UUFDaEMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLENBQUM7UUFDNUIsSUFBSSxJQUFJLENBQUMsTUFBTSxFQUFFLENBQUM7WUFDaEIsSUFBSSxDQUFDLGNBQWMsRUFBRSxDQUFDO1FBQ3hCLENBQUM7SUFDSCxDQUFDO0lBRUQsV0FBVztRQUNULElBQUksQ0FBQyxJQUFJLENBQUMsV0FBVyxFQUFFLENBQUM7UUFDeEIsSUFBSSxDQUFDLGlCQUFpQixFQUFFLFdBQVcsRUFBRSxDQUFDO1FBQ3RDLElBQUksQ0FBQyxtQkFBbUIsRUFBRSxXQUFXLEVBQUUsQ0FBQztRQUN4QyxJQUFJLElBQUksQ0FBQyxXQUFXLFlBQVksb0JBQW9CLEVBQUUsQ0FBQztZQUNyRCxJQUFJLENBQUMsV0FBVyxDQUFDLGNBQWMsRUFBRSxDQUFDO1FBQ3BDLENBQUM7SUFDSCxDQUFDO0lBRUQsSUFBSSxPQUFPO1FBQ1QsT0FBTyxJQUFJLENBQUMsZ0JBQWdCLENBQUMsU0FBUyxFQUFFLGVBQWUsSUFBSSxLQUFLLENBQUM7SUFDbkUsQ0FBQztJQUVEOzs7T0FHRztJQUNILHNCQUFzQjtRQUNwQixRQUFRLElBQUksQ0FBQyxRQUFRLEVBQUUsQ0FBQztZQUN0QixLQUFLLE1BQU07Z0JBQ1QsSUFBSSxDQUFDLFdBQVcsR0FBRyxJQUFJLENBQUMsV0FBVyxDQUFDO2dCQUNwQyxNQUFNO1lBQ1IsS0FBSyxXQUFXO2dCQUNkLElBQUksQ0FBQyxXQUFXLEdBQUcsSUFBSSxDQUFDLGdCQUFnQixDQUFDO2dCQUN6QyxNQUFNO1lBQ1I7Z0JBQ0UsTUFBTSxJQUFJLEtBQUssQ0FBQyx5RkFBeUYsSUFBSSxDQUFDLFFBQVEsR0FBRyxDQUFDLENBQUM7UUFDL0gsQ0FBQztRQUNELElBQUksQ0FBQyxXQUFXLENBQUMsaUJBQWlCLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxDQUFDO1FBQ3BELElBQUksQ0FBQyxzQkFBc0IsQ0FBQyxhQUFhLENBQUMsSUFBSSxDQUFDLFVBQVUsRUFBRSxJQUFJLENBQUMsV0FBVyxDQUFDLENBQUM7SUFDL0UsQ0FBQztJQUVEOzs7Ozs7Ozs7O09BVUc7SUFDSyxjQUFjO1FBQ3BCLE1BQU0sT0FBTyxHQUFHLElBQUksQ0FBQyxRQUFRLENBQUMsS0FBSyxDQUFDO1FBQ3BDLHVHQUF1RztRQUN2RyxJQUFJLE9BQU8sRUFBRSxlQUFlLElBQUksSUFBSSxDQUFDLGVBQWUsSUFBSSxJQUFJLENBQUMsV0FBVyxZQUFZLG9CQUFvQixFQUFFLENBQUM7WUFDekcsSUFBSSxDQUFDLFdBQVcsQ0FBQyx1QkFBdUIsQ0FBQyxJQUFJLENBQUMsZUFBZSxDQUFDLENBQUM7UUFDakUsQ0FBQztRQUNEOzs7V0FHRztRQUNILElBQUksQ0FBQyxJQUFJLENBQUMsbUJBQW1CLElBQUksT0FBTyxFQUFFLElBQUksRUFBRSxDQUFDO1lBQy9DLE1BQU0sUUFBUSxHQUFHLEdBQUcsRUFBRTtnQkFDcEIsSUFBSSxJQUFJLENBQUMsU0FBUyxDQUFDLEtBQUssRUFBRSxDQUFDO29CQUN6QixJQUFJLENBQUMsV0FBVyxDQUFDLGFBQWEsRUFBRSxDQUFDLENBQUMsa0NBQWtDO2dCQUN0RSxDQUFDO2dCQUNELElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLElBQUssQ0FBQyxRQUFRLENBQUMsQ0FBQztZQUNyQyxDQUFDLENBQUM7WUFDRixJQUFJLENBQUMsV0FBVyxDQUFDLGNBQWMsRUFBRSxDQUFDO1lBQ2xDLElBQUksSUFBSSxDQUFDLElBQUksRUFBRSxDQUFDO2dCQUNkLElBQUksQ0FBQyxXQUFXLENBQUMsa0JBQWtCLENBQUMsY0FBYyxFQUFFLEVBQUMsZUFBZSxFQUFFLElBQUksQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxnQkFBZ0IsQ0FBQyxLQUFLLENBQUMsRUFBQyxXQUFXLEVBQUUsSUFBSSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLEVBQUMsQ0FBQyxDQUFDO2dCQUN2SyxRQUFRLEVBQUUsQ0FBQztZQUNiLENBQUM7aUJBQU0sQ0FBQztnQkFDTixJQUFJLENBQUMsV0FBVyxDQUFDLGtCQUFrQixDQUFDLGNBQWMsRUFBRSxFQUFDLGVBQWUsRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxXQUFXLENBQUMsZ0JBQWdCLENBQUMsS0FBSyxDQUFDLEVBQUMsQ0FBQyxDQUFDO2dCQUNoSSxJQUFJLENBQUMsZUFBZSxFQUFFLENBQUM7WUFDekIsQ0FBQztRQUNILENBQUM7UUFDRDs7OztXQUlHO1FBQ0gsSUFBSSxJQUFJLENBQUMsbUJBQW1CLElBQUksT0FBTyxFQUFFLEtBQUssSUFBSSxJQUFJLENBQUMsTUFBTSxDQUFDLFlBQVksQ0FBQyxjQUFjLENBQUMsS0FBSyxLQUFLLE9BQU8sRUFBRSxDQUFDO1lBQzVHLElBQUksSUFBSSxDQUFDLDhCQUE4QixDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsOEJBQThCLENBQUMsSUFBSSxDQUFDLGNBQWMsRUFBRSxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksRUFBRSxDQUFDO2dCQUN0SCxJQUFJLENBQUMsQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLG1CQUFtQixDQUFDLEtBQUssRUFBRSxDQUFDO29CQUNqRCxJQUFJLENBQUMsSUFBSSxDQUFDLG1CQUFtQixFQUFFLENBQUM7d0JBQzlCLHdGQUF3Rjt3QkFDeEYsSUFBSSxDQUFDLG1CQUFtQixHQUFHLGFBQWEsQ0FBQzs0QkFDdkMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxVQUFVOzRCQUMzQixJQUFJLENBQUMsV0FBVyxDQUFDLG1CQUFtQjt5QkFDckMsQ0FBQzs2QkFDQyxJQUFJLENBQ0gsTUFBTSxDQUFDLENBQUMsQ0FBQyxTQUFTLEVBQUUsUUFBUSxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsU0FBUyxJQUFJLENBQUMsUUFBUSxDQUFDLEVBQUUsNEJBQTRCO3dCQUN4RixJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsaUNBQWlDO3lCQUMxQyxDQUFDLFNBQVMsQ0FBQyxHQUFHLEVBQUU7NEJBQ2YsNENBQTRDOzRCQUM1QyxJQUFJLENBQUMsOEJBQThCLEVBQUUsQ0FBQzs0QkFDdEMsK0NBQStDOzRCQUMvQyxJQUFJLENBQUMsY0FBYyxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQzs0QkFDN0QsNENBQTRDOzRCQUM1QyxJQUFJLENBQUMsbUJBQW1CLEdBQUcsU0FBUyxDQUFDO3dCQUN2QyxDQUFDLENBQUMsQ0FBQztvQkFDUCxDQUFDO2dCQUNILENBQUM7cUJBQU0sSUFBSSxDQUFDLENBQUMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxVQUFVLENBQUMsS0FBSyxFQUFFLENBQUM7b0JBQy9DLElBQUksQ0FBQyxJQUFJLENBQUMsbUJBQW1CLEVBQUUsQ0FBQzt3QkFDOUIsSUFBSSxDQUFDLG1CQUFtQixHQUFHLElBQUksQ0FBQyxXQUFXLENBQUMsY0FBYyxFQUFFOzZCQUN6RCxTQUFTLENBQUM7NEJBQ1QsSUFBSSxFQUFFLEdBQUcsRUFBRSxHQUFFLENBQUM7NEJBQ2QsS0FBSyxFQUFFLEdBQUcsRUFBRTtnQ0FDViw0Q0FBNEM7Z0NBQzVDLElBQUksQ0FBQyxtQkFBbUIsRUFBRSxXQUFXLEVBQUUsQ0FBQztnQ0FDeEMsSUFBSSxDQUFDLG1CQUFtQixHQUFHLFNBQVMsQ0FBQzs0QkFDdkMsQ0FBQzs0QkFDRCxRQUFRLEVBQUUsR0FBRyxFQUFFO2dDQUNiLGtFQUFrRTtnQ0FDbEUsSUFBSSxDQUFDLFdBQVcsQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUM5QixNQUFNLENBQUMsQ0FBQyxTQUFTLEVBQUUsRUFBRSxDQUFDLENBQUMsU0FBUyxDQUFDLEVBQ2pDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FDUixDQUFDLFNBQVMsQ0FBQyxHQUFHLEVBQUU7b0NBQ2YsNENBQTRDO29DQUM1QyxJQUFJLENBQUMsOEJBQThCLEVBQUUsQ0FBQztvQ0FDdEMsK0NBQStDO29DQUMvQyxJQUFJLENBQUMsY0FBYyxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQztvQ0FDN0QsNENBQTRDO29DQUM1QyxJQUFJLENBQUMsbUJBQW9CLENBQUMsV0FBVyxFQUFFLENBQUM7b0NBQ3hDLElBQUksQ0FBQyxtQkFBbUIsR0FBRyxTQUFTLENBQUM7Z0NBQ3ZDLENBQUMsQ0FBQyxDQUFDOzRCQUNMLENBQUM7eUJBQ0YsQ0FBQyxDQUFDO29CQUNQLENBQUM7Z0JBQ0gsQ0FBQztxQkFBTSxDQUFDO29CQUNOLDRDQUE0QztvQkFDNUMsSUFBSSxDQUFDLDhCQUE4QixFQUFFLENBQUM7b0JBQ3RDLCtDQUErQztvQkFDL0MsSUFBSSxDQUFDLGNBQWMsR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUM7Z0JBQy9ELENBQUM7WUFDSCxDQUFDO2lCQUFNLENBQUM7Z0JBQ04sK0NBQStDO2dCQUMvQyxJQUFJLENBQUMsY0FBYyxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQztZQUMvRCxDQUFDO1FBQ0gsQ0FBQztJQUNILENBQUM7SUFFRDs7Ozs7T0FLRztJQUNLLDhCQUE4QjtRQUNwQyxNQUFNLFNBQVMsR0FBRyxFQUFFLElBQUksRUFBRSxRQUFRLEVBQUUsT0FBTyxFQUFFLElBQUksQ0FBQyxNQUFNLENBQUMsYUFBYSxDQUFDLFlBQVksRUFBRSxvQkFBb0IsRUFBRSxFQUFFLE9BQU8sRUFBRSxLQUFLLEVBQUUsRUFBRSxDQUFDO1FBQ2hJLHNEQUFzRDtRQUN0RCxNQUFNLFVBQVUsR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDLGFBQWEsQ0FBQyxVQUFVLENBQUMsT0FBTyxDQUFDLGdCQUFnQixFQUFFLFFBQVEsQ0FBQyxDQUFDO1FBQzVGLE1BQU0sT0FBTyxHQUFHLEVBQUUsSUFBSSxFQUFFLE1BQU0sRUFBRSxPQUFPLEVBQUUsV0FBVyxDQUFDLFlBQVksQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLFNBQVMsQ0FBQyxVQUFVLENBQUMsRUFBRyxFQUFFLFNBQVMsRUFBRSxJQUFJLENBQUMsZ0JBQWdCLENBQUMsU0FBUyxFQUFFLENBQUMsRUFBRSxvQkFBb0IsRUFBRSxFQUFFLE9BQU8sRUFBRSxJQUFJLENBQUMsTUFBTSxDQUFDLFlBQVksQ0FBQyxpQkFBaUIsRUFBRSxFQUFFLENBQUM7UUFDMU8sSUFBSSxDQUFDLFdBQVcsQ0FBQyxjQUFjLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyx3QkFBd0I7UUFDcEUsSUFBSSxDQUFDLFdBQVcsQ0FBQyxjQUFjLEVBQUUsQ0FBQyxDQUFDLHdCQUF3QjtRQUMzRCxJQUFJLENBQUMsV0FBVyxDQUFDLGtCQUFrQixDQUFDLGNBQWMsRUFBRSxFQUFDLGVBQWUsRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxXQUFXLENBQUMsZ0JBQWdCLENBQUMsS0FBSyxDQUFDLEVBQUMsQ0FBQyxDQUFDLENBQUMsa0NBQWtDO1FBQ25LLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxTQUFTLEVBQUUsT0FBTyxDQUFDLENBQUM7SUFDNUMsQ0FBQztJQUdEOzs7Ozs7Ozs7T0FTRztJQUNLLGtCQUFrQjtRQUN4QixJQUFJLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FDWCxLQUFLLENBQUMsSUFBSSxDQUFDLFFBQVEsRUFBRSxJQUFJLENBQUMsU0FBUyxFQUFFLElBQUksQ0FBQyxXQUFXLENBQUMsVUFBVSxFQUFFLFNBQVMsQ0FBQyxJQUFJLENBQUMsV0FBWSxDQUFDLGFBQWEsRUFBRSxRQUFRLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxHQUFHLEVBQUU7WUFDckksSUFBSSxDQUFDLFVBQVUsR0FBRyxJQUFJLENBQUMsNkJBQTZCLEVBQUUsQ0FBQztZQUN2RCxJQUFJLENBQUMsR0FBRyxDQUFDLGFBQWEsRUFBRSxDQUFDO1FBQzNCLENBQUMsQ0FBQyxDQUNILENBQUM7SUFDSixDQUFDO0lBRUQ7O09BRUc7SUFDSCxzQkFBc0I7UUFDcEIsSUFBSSxDQUFDLGdCQUFnQixHQUFHLElBQUksQ0FBQyxXQUFXLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsYUFBYSxDQUFDLFVBQVUsRUFBRSxJQUFJLENBQUMsTUFBTSxDQUFDLGFBQWEsQ0FBQyxRQUFRLENBQUMsQ0FBQztRQUM1SCxJQUFJLENBQUMsR0FBRyxDQUFDLGFBQWEsRUFBRSxDQUFDO0lBQzNCLENBQUM7SUFFRDs7Ozs7O09BTUc7SUFDSCxjQUFjO1FBQ1osSUFBSSxDQUFDLENBQUMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxVQUFVLENBQUMsS0FBSyxJQUFJLENBQUMsQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLG1CQUFtQixDQUFDLEtBQUssRUFBRSxDQUFDO1lBQ3hGLE9BQU87UUFDVCxDQUFDO1FBQ0QsSUFBSSxJQUFJLENBQUMsUUFBUSxDQUFDLElBQUksRUFBRSxJQUFJLElBQUksQ0FBQyxTQUFTLENBQUMsS0FBSyxJQUFJLElBQUksQ0FBQyxXQUFXLENBQUMsV0FBVyxFQUFFLENBQUM7WUFDakYsb0lBQW9JO1lBQ3BJLElBQUksSUFBSSxDQUFDLGFBQWEsS0FBSyxTQUFTLEVBQUUsQ0FBQztnQkFDckMsZ0NBQWdDO2dCQUNoQyxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsQ0FBQyxFQUFFLElBQUksQ0FBQyxhQUFhLENBQUMsQ0FBQyxDQUFDO2dCQUN2RSx1R0FBdUc7Z0JBQ3ZHLElBQUksQ0FBQyxXQUFXLENBQUMsV0FBVyxHQUFHLElBQUksQ0FBQyxXQUFXLENBQUMsV0FBVyxDQUFDLEtBQUssQ0FBQyxDQUFDLEVBQUUsSUFBSSxDQUFDLHFCQUFxQixDQUFDLENBQUM7Z0JBQ2pHLElBQUksQ0FBQyxhQUFhLEdBQUcsU0FBUyxDQUFDO2dCQUMvQixJQUFJLENBQUMscUJBQXFCLEdBQUcsU0FBUyxDQUFDO1lBQ3pDLENBQUM7WUFDRCw4Q0FBOEM7WUFDOUMsSUFBSSxJQUFJLENBQUMsV0FBVyxDQUFDLFdBQVcsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxJQUFJLEtBQUssZ0JBQWdCLEVBQUUsQ0FBQztnQkFDbkUsSUFBSSxDQUFDLFdBQVcsQ0FBQyxXQUFXLENBQUMsR0FBRyxFQUFFLENBQUM7WUFDckMsQ0FBQztZQUNELG1CQUFtQjtZQUNuQixJQUFJLENBQUMsWUFBWSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxFQUFFLEVBQUUsSUFBSSxDQUFDLFdBQVcsQ0FBQyxXQUFXLENBQUMsQ0FBQztZQUN0RSxrQ0FBa0M7WUFDbEMsSUFBSSxDQUFDLGFBQWMsQ0FBQyxhQUFhLENBQUMsS0FBSyxHQUFHLEVBQUUsQ0FBQztZQUM3QyxJQUFJLENBQUMsYUFBYyxDQUFDLGFBQWEsQ0FBQyxLQUFLLENBQUMsTUFBTSxHQUFHLE1BQU0sQ0FBQztRQUMxRCxDQUFDO0lBQ0gsQ0FBQztJQUVEOzs7Ozs7T0FNRztJQUNLLFlBQVksQ0FBQyxRQUFnQixFQUFFLFlBQTJCO1FBQ2hFLHdGQUF3RjtRQUN4RixNQUFNLDRCQUE0QixHQUFHLEVBQUUsR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDLDRCQUE0QixFQUFFLEdBQUcsSUFBSSxDQUFDLDRCQUE0QixFQUFFLENBQUM7UUFDM0gsTUFBTSxPQUFPLEdBQUcsRUFBRSxJQUFJLEVBQUUsTUFBTSxFQUFFLE9BQU8sRUFBRSxRQUFRLEVBQUUsb0JBQW9CLEVBQUUsRUFBRSxPQUFPLEVBQUUsSUFBSSxFQUFFLFdBQVcsRUFBRSxJQUFJLEVBQUUsNEJBQTRCLEVBQUUsRUFBRSxDQUFDO1FBQzlJLE1BQU0sUUFBUSxHQUFHLENBQUMsR0FBRyxZQUFZLEVBQUUsT0FBTyxDQUFDLENBQUM7UUFDNUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUM7UUFDOUIsSUFBSSxDQUFDLEtBQUssQ0FBQyxRQUFRLENBQUMsQ0FBQztRQUNyQixJQUFJLENBQUMsV0FBVyxDQUFDLGtCQUFrQixDQUFDLGFBQWEsRUFBRSxFQUFFLEdBQUcsSUFBSSxDQUFDLDBCQUEwQixDQUFDLE9BQU8sRUFBRSxRQUFRLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQyxFQUFFLE9BQU8sRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsRUFBRSxlQUFlLEVBQUUsSUFBSSxFQUFFLG1CQUFtQixFQUFFLElBQUksQ0FBQyxNQUFNLENBQUMsYUFBYSxDQUFDLFNBQVMsRUFBRSxNQUFNLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxFQUFFLGdDQUFnQyxFQUFFLElBQUksQ0FBQyxTQUFTLENBQUMsNEJBQTRCLENBQUMsRUFBRSxDQUFDLENBQUM7SUFDdFgsQ0FBQztJQUVEOzs7Ozs7T0FNRztJQUNJLEtBQUssQ0FBQyxRQUF1QjtRQUNsQyxJQUFJLENBQUMsQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLFVBQVUsQ0FBQyxLQUFLLElBQUksQ0FBQyxDQUFDLElBQUksQ0FBQyxXQUFXLENBQUMsbUJBQW1CLENBQUMsS0FBSyxFQUFFLENBQUM7WUFDeEYsT0FBTztRQUNULENBQUM7UUFDRCxJQUFJLENBQUMsdUJBQXVCLEVBQUUsQ0FBQztRQUMvQixJQUFJLENBQUMsR0FBRyxDQUFDLGFBQWEsRUFBRSxDQUFDO1FBRXpCLElBQUksSUFBSSxDQUFDLFdBQVcsRUFBRSxDQUFDO1lBQ3JCLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO1lBQ3pCLElBQUksQ0FBQyxpQkFBaUIsRUFBRSxXQUFXLEVBQUUsQ0FBQztZQUN0QyxJQUFJLENBQUMsaUJBQWlCLEdBQUcsSUFBSSxDQUFDLFdBQVcsQ0FBQyxLQUFLLENBQUMsUUFBUSxFQUFFLElBQUksQ0FBQyxLQUFLLENBQUM7aUJBQ2xFLFNBQVMsQ0FBQztnQkFDVCxJQUFJLEVBQUUsR0FBRyxDQUFDLEVBQUU7b0JBQ1YsSUFBSSxDQUFDLGlCQUFpQixHQUFHLEdBQUcsQ0FBQyx5QkFBeUIsQ0FBQztvQkFDdkQsSUFBSSxDQUFDLFVBQVUsQ0FBQyxHQUFHLENBQUMsT0FBTyxDQUFDLENBQUM7Z0JBQy9CLENBQUM7Z0JBQ0QsS0FBSyxFQUFFLEdBQUcsRUFBRTtvQkFDVixJQUFJLENBQUMsdUJBQXVCLEVBQUUsQ0FBQztvQkFDL0IsSUFBSSxDQUFDLElBQUksQ0FBQyxXQUFXLEVBQUUsQ0FBQzt3QkFDdEIsTUFBTSxPQUFPLEdBQUc7NEJBQ2QsSUFBSSxFQUFFLGtCQUFrQjs0QkFDeEIsT0FBTyxFQUFHLEVBQUUsSUFBSSxFQUFFLE1BQU0sRUFBRSxJQUFJLEVBQUUsSUFBSSxDQUFDLFNBQVMsQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxrQkFBa0IsQ0FBQyxzQkFBc0IsQ0FBQyxFQUF5Qjs0QkFDeEksb0JBQW9CLEVBQUUsRUFBRSxPQUFPLEVBQUUsSUFBSSxFQUFFO3lCQUNsQixDQUFDO3dCQUN4QixJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxDQUFDLEdBQUcsUUFBUSxFQUFFLE9BQU8sQ0FBQyxDQUFDLENBQUM7b0JBQzlDLENBQUM7b0JBQ0QsSUFBSSxDQUFDLGNBQWMsRUFBRSxDQUFDO2dCQUN4QixDQUFDO2dCQUNELFFBQVEsRUFBRSxHQUFHLEVBQUU7b0JBQ2IsbURBQW1EO29CQUNuRCxtRkFBbUY7b0JBQ25GLE1BQU0sV0FBVyxHQUFHLElBQUksQ0FBQyxTQUFTLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO29CQUNqRCxJQUFJLElBQUksQ0FBQyx1QkFBdUIsQ0FBQyxXQUFXLENBQUMsRUFBRSxDQUFDO3dCQUM5QyxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLEtBQUssRUFBRSxLQUFLLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztvQkFDMUQsQ0FBQztvQkFDRCxJQUFJLENBQUMsY0FBYyxFQUFFLENBQUM7Z0JBQ3hCLENBQUM7YUFDRixDQUFDLENBQUM7UUFDUCxDQUFDO2FBQU0sQ0FBQztZQUNOLE1BQU0sT0FBTyxHQUFHLEVBQUUsSUFBSSxFQUFFLGtCQUFrQixFQUFFLE9BQU8sRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLGtCQUFrQixDQUFDLHNCQUFzQixDQUFDLEVBQUUsb0JBQW9CLEVBQUUsRUFBRSxPQUFPLEVBQUUsSUFBSSxFQUFFLEVBQUUsQ0FBQztZQUNoTCxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxDQUFDLEdBQUcsUUFBUSxFQUFFLE9BQU8sQ0FBQyxDQUFDLENBQUM7UUFDOUMsQ0FBQztRQUVELElBQUksSUFBSSxDQUFDLDZCQUE2QixFQUFFLENBQUM7WUFDdkMsSUFBSSxDQUFDLFVBQVUsRUFBRSxDQUFDO1FBQ3BCLENBQUM7SUFDSCxDQUFDO0lBRUQ7Ozs7OztPQU1HO0lBQ0gsVUFBVTtRQUNSLElBQUksSUFBSSxDQUFDLFdBQVcsWUFBWSxvQkFBb0IsRUFBRSxDQUFDO1lBQ3JELDRDQUE0QztZQUM1QyxNQUFNLG9CQUFvQixHQUFHLEdBQUcsRUFBRTtnQkFDaEMsdUVBQXVFO2dCQUN2RSxNQUFNLFFBQVEsR0FBRyxJQUFJLENBQUMsU0FBUyxDQUFDLEtBQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7Z0JBQ3BELG9EQUFvRDtnQkFDcEQsSUFBSSxLQUFLLEdBQUcsUUFBUSxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUM7Z0JBQ2hDLE9BQU8sS0FBSyxJQUFJLENBQUMsSUFBSSxRQUFRLENBQUMsS0FBSyxDQUFDLENBQUMsSUFBSSxLQUFLLE1BQU0sRUFBRSxDQUFDO29CQUNyRCxLQUFLLEVBQUUsQ0FBQztnQkFDVixDQUFDO2dCQUNELHNIQUFzSDtnQkFDdEgsZ0NBQWdDO2dCQUNoQywwQ0FBMEM7Z0JBQzFDLElBQUksS0FBSyxJQUFJLENBQUMsRUFBRSxDQUFDO29CQUNmLElBQUksQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsS0FBTSxDQUFDLEtBQUssQ0FBQyxDQUFDLEVBQUUsS0FBSyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUM7b0JBQy9ELE1BQU0sYUFBYSxHQUFHLElBQUksQ0FBQyx3QkFBd0IsQ0FBQyxLQUFLLENBQUMsQ0FBQztvQkFDM0QsSUFBSSxDQUFDLFdBQVcsQ0FBQyxXQUFXLEdBQUcsSUFBSSxDQUFDLFdBQVcsQ0FBQyxXQUFZLENBQUMsS0FBSyxDQUFDLENBQUMsRUFBRSxhQUFhLEdBQUcsQ0FBQyxDQUFDLENBQUM7b0JBQ3pGLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxXQUFXLENBQUMsQ0FBQztnQkFDM0MsQ0FBQztnQkFDRCxJQUFJLENBQUMsZUFBZSxHQUFHLFNBQVMsQ0FBQyxDQUFDLHVDQUF1QztnQkFDekU7OzttQkFHRztnQkFDRixJQUFJLENBQUMsV0FBb0MsQ0FBQyxVQUFXLENBQUMsYUFBYSxDQUFDLEdBQUcsRUFBRSxHQUFFLENBQUMsQ0FBQyxDQUFDO2dCQUMvRSx1RUFBdUU7Z0JBQ3ZFLElBQUksQ0FBQyxnQ0FBZ0MsR0FBRyxLQUFLLENBQUM7WUFDaEQsQ0FBQyxDQUFBO1lBQ0QsbUVBQW1FO1lBQ25FLFFBQVEsSUFBSSxDQUFDLFdBQVcsQ0FBQyxVQUFXLENBQUMsS0FBSyxFQUFFLENBQUM7Z0JBQzNDLEtBQUssa0JBQWtCLENBQUMsU0FBUztvQkFDL0IsMEVBQTBFO29CQUMxRSxvQkFBb0IsRUFBRSxDQUFDO29CQUN2QixNQUFNO2dCQUNSLEtBQUssa0JBQWtCLENBQUMsWUFBWTtvQkFDbEMsNERBQTREO29CQUM1RCxJQUFJLENBQUMsSUFBSSxDQUFDLGdDQUFnQyxFQUFFLENBQUM7d0JBQzNDLElBQUksQ0FBQyxXQUFXLENBQUMsVUFBVyxDQUFDLGFBQWEsQ0FBQyxvQkFBb0IsQ0FBQyxDQUFDO3dCQUNqRSxJQUFJLENBQUMsZ0NBQWdDLEdBQUcsSUFBSSxDQUFDO29CQUMvQyxDQUFDO29CQUNELDBDQUEwQztvQkFDMUMsSUFBSSxDQUFDLGVBQWUsR0FBRyxJQUFJLENBQUMsZUFBZSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsZUFBZSxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO29CQUMzRSxNQUFNO2dCQUNSLEtBQUssa0JBQWtCLENBQUMsWUFBWTtvQkFDbEMsMkJBQTJCO29CQUMzQixJQUFJLENBQUMsV0FBVyxDQUFDLGVBQWUsRUFBRTt5QkFDL0IsSUFBSSxDQUFDLEdBQUcsRUFBRSxDQUFDLG9CQUFvQixFQUFFLENBQUM7eUJBQ2xDLEtBQUssQ0FBQyxHQUFHLEVBQUU7d0JBQ1YsSUFBSSxDQUFDLGVBQWUsR0FBRyxJQUFJLENBQUMsZUFBZSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsZUFBZSxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO29CQUM3RSxDQUFDLENBQUMsQ0FBQztvQkFDTCxNQUFNO2dCQUNSO29CQUNFLE1BQU07WUFDVixDQUFDO1FBQ0gsQ0FBQztJQUNILENBQUM7SUFFRDs7O09BR0c7SUFDSyx1QkFBdUI7UUFDN0IsSUFBSSxDQUFDLFdBQVcsR0FBRyxDQUFDLElBQUksQ0FBQyxXQUFXLFlBQVksb0JBQW9CLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxVQUFXLENBQUMsS0FBSyxLQUFLLGtCQUFrQixDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDO0lBQ3JKLENBQUM7SUFFRDs7O09BR0c7SUFDSCxVQUFVLENBQUMsUUFBdUI7UUFDaEMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUM7UUFDOUIsSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUM7UUFDekIsSUFBSSxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDMUIsSUFBSSxDQUFDLFFBQVEsR0FBRyxFQUFFLENBQUM7UUFDbkIsSUFBSSxJQUFJLENBQUMsNkJBQTZCLEVBQUUsQ0FBQztZQUN2QyxJQUFJLENBQUMsVUFBVSxFQUFFLENBQUM7UUFDcEIsQ0FBQztJQUNILENBQUM7SUFFRDs7T0FFRztJQUNLLDZCQUE2QjtRQUNuQyxJQUFJLElBQUksQ0FBQyxXQUFXLEVBQUUsYUFBYSxFQUFFLENBQUM7WUFDcEMsT0FBTyxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxXQUFXLEVBQUUsYUFBYSxDQUFDLFlBQVksR0FBRyxJQUFJLENBQUMsV0FBVyxFQUFFLGFBQWEsQ0FBQyxTQUFTLEdBQUcsQ0FBQyxDQUFDLElBQUksSUFBSSxDQUFDLFdBQVcsRUFBRSxhQUFhLENBQUMsWUFBWSxDQUFDO1FBQ2xLLENBQUM7UUFDRCxPQUFPLElBQUksQ0FBQztJQUNkLENBQUM7SUFFRDs7T0FFRztJQUNILFVBQVU7UUFDUixVQUFVLENBQUMsR0FBRyxFQUFFO1lBQ2QsSUFBSSxJQUFJLENBQUMsV0FBVyxFQUFFLGFBQWEsRUFBRSxDQUFDO2dCQUNwQyxJQUFJLENBQUMsV0FBVyxDQUFDLGFBQWEsQ0FBQyxTQUFTLEdBQUcsSUFBSSxDQUFDLFdBQVcsQ0FBQyxhQUFhLENBQUMsWUFBWSxDQUFDO2dCQUN2RixJQUFJLENBQUMsR0FBRyxDQUFDLGFBQWEsRUFBRSxDQUFDO1lBQzNCLENBQUM7UUFDSCxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUM7SUFDVCxDQUFDO0lBRUQ7Ozs7O09BS0c7SUFDSCxPQUFPO1FBQ0wsSUFBSSxDQUFDLENBQUMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxVQUFVLENBQUMsS0FBSyxJQUFJLENBQUMsQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLG1CQUFtQixDQUFDLEtBQUssRUFBRSxDQUFDO1lBQ3hGLE9BQU87UUFDVCxDQUFDO1FBQ0QsSUFBSSxDQUFDLFdBQVcsQ0FBQyxjQUFjLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyx3QkFBd0I7UUFDcEUsSUFBSSxDQUFDLFdBQVcsQ0FBQyxjQUFjLEVBQUUsQ0FBQyxDQUFDLHdCQUF3QjtRQUMzRCxJQUFJLENBQUMsV0FBVyxDQUFDLGFBQWEsRUFBRSxDQUFDLENBQUMsa0NBQWtDO1FBQ3BFLElBQUksQ0FBQyxXQUFXLENBQUMsa0JBQWtCLENBQUMsY0FBYyxFQUFFLEVBQUMsZUFBZSxFQUFFLElBQUksQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxnQkFBZ0IsQ0FBQyxLQUFLLENBQUMsRUFBQyxDQUFDLENBQUMsQ0FBQyxrQ0FBa0M7UUFDbkssSUFBSSxDQUFDLGVBQWUsRUFBRSxDQUFDLENBQUMsbUJBQW1CO0lBQzdDLENBQUM7SUFFRDs7Ozs7O09BTUc7SUFDSCxZQUFZLENBQUMsR0FBYTtRQUN4QixJQUFJLENBQUMsQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLFVBQVUsQ0FBQyxLQUFLLElBQUksQ0FBQyxDQUFDLElBQUksQ0FBQyxXQUFXLENBQUMsbUJBQW1CLENBQUMsS0FBSyxFQUFFLENBQUM7WUFDeEYsT0FBTztRQUNULENBQUM7UUFDRCxJQUFJLENBQUMsR0FBRyxJQUFJLEdBQUcsRUFBRSxNQUFNLEdBQUcsQ0FBQyxFQUFFLENBQUM7WUFDNUIsT0FBTztRQUNULENBQUM7UUFDRCxNQUFNLGVBQWUsR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDLFlBQVksQ0FBQyxPQUFPLEVBQUUsQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDO1FBQzlFLElBQUksQ0FBQyxlQUFlLEVBQUUsQ0FBQztZQUNyQixPQUFPLENBQUMsS0FBSyxDQUFDLG1FQUFtRSxJQUFJLENBQUMsVUFBVSxHQUFHLENBQUMsQ0FBQztZQUNyRyxPQUFPO1FBQ1QsQ0FBQztRQUNELE1BQU0sT0FBTyxHQUFHLEVBQUUsSUFBSSxFQUFFLE1BQU0sRUFBRSxPQUFPLEVBQUUsRUFBRSxFQUFFLG9CQUFvQixFQUFFLEVBQUMsT0FBTyxFQUFFLEtBQUssRUFBRSxXQUFXLEVBQUUsS0FBSyxFQUFFLElBQUksRUFBRSxRQUFRLEVBQUUsY0FBYyxFQUFFLGVBQWUsQ0FBQyxjQUFjLEVBQUUsd0JBQXdCLEVBQUUsRUFBQyxHQUFHLENBQUMsZUFBZSxDQUFDLHdCQUF3QixJQUFJLEVBQUUsQ0FBQyxFQUFFLEdBQUcsRUFBQyxFQUFFLDRCQUE0QixFQUFFLElBQUksQ0FBQyxNQUFNLENBQUMsNEJBQTRCLEVBQUMsRUFBQyxDQUFDO1FBQ3ZVLDhDQUE4QztRQUM5QyxJQUFJLElBQUksQ0FBQyxXQUFXLENBQUMsV0FBWSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLElBQUksS0FBSyxnQkFBZ0IsRUFBRSxDQUFDO1lBQ3BFLElBQUksQ0FBQyxXQUFXLENBQUMsV0FBWSxDQUFDLEdBQUcsRUFBRSxDQUFDO1FBQ3RDLENBQUM7UUFDRCxNQUFNLFFBQVEsR0FBRyxDQUFDLEdBQUcsSUFBSSxDQUFDLFdBQVcsQ0FBQyxXQUFZLEVBQUUsT0FBTyxDQUFDLENBQUM7UUFDN0QsSUFBSSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUM7UUFDOUIsSUFBSSxDQUFDLEtBQUssQ0FBQyxRQUFRLENBQUMsQ0FBQztRQUNyQixJQUFJLENBQUMsV0FBVyxDQUFDLGtCQUFrQixDQUFDLHNCQUFzQixFQUFFO1lBQzFELFFBQVEsRUFBRSxpQkFBaUI7WUFDM0IsaUJBQWlCLEVBQUUscUNBQXFDO1lBQ3hELDRCQUE0QixFQUFFLElBQUksQ0FBQyxTQUFTLENBQUMsR0FBRyxDQUFDO1NBQ2xELENBQUMsQ0FBQztJQUNMLENBQUM7SUFFRDs7O09BR0c7SUFDSCxlQUFlO1FBQ2IsNERBQTREO1FBQzVELE1BQU0sU0FBUyxHQUFHLEVBQUUsSUFBSSxFQUFFLFFBQVEsRUFBRSxPQUFPLEVBQUUsSUFBSSxDQUFDLE1BQU0sQ0FBQyxhQUFhLENBQUMsWUFBWSxFQUFFLG9CQUFvQixFQUFFLEVBQUUsT0FBTyxFQUFFLEtBQUssRUFBRSxFQUFFLENBQUM7UUFDaEksc0RBQXNEO1FBQ3RELE1BQU0sVUFBVSxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUMsYUFBYSxDQUFDLFVBQVUsQ0FBQyxPQUFPLENBQUMsZ0JBQWdCLEVBQUUsUUFBUSxDQUFDLENBQUM7UUFDNUYsTUFBTSxPQUFPLEdBQUcsRUFBRSxJQUFJLEVBQUUsTUFBTSxFQUFFLE9BQU8sRUFBRSxXQUFXLENBQUMsWUFBWSxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsU0FBUyxDQUFDLFVBQVUsQ0FBQyxFQUFHLEVBQUUsU0FBUyxFQUFFLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxTQUFTLEVBQUUsQ0FBQyxFQUFFLG9CQUFvQixFQUFFLEVBQUUsT0FBTyxFQUFFLElBQUksQ0FBQyxNQUFNLENBQUMsWUFBWSxDQUFDLGlCQUFpQixFQUFFLEVBQUUsQ0FBQztRQUUxTyxJQUFJLElBQUksQ0FBQyxNQUFNLENBQUMsWUFBWSxDQUFDLGNBQWMsQ0FBQyxLQUFLLEtBQUssT0FBTyxFQUFFLENBQUM7WUFDOUQsSUFBSSxDQUFDLGdCQUFnQixDQUFDLFNBQVMsRUFBRSxPQUFPLENBQUMsQ0FBQztRQUM1QyxDQUFDO2FBQU0sQ0FBQztZQUNOLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxTQUFTLEVBQUUsT0FBTyxDQUFDLENBQUM7UUFDN0MsQ0FBQztJQUNILENBQUM7SUFFRDs7Ozs7Ozs7O09BU0c7SUFDSyxpQkFBaUIsQ0FBQyxTQUFzQixFQUFFLE9BQW9CO1FBQ3BFLElBQUksSUFBSSxDQUFDLE1BQU0sQ0FBQyxZQUFZLENBQUMsY0FBYyxFQUFFLENBQUM7WUFDNUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFDLFNBQVMsRUFBRSxPQUFPLENBQUMsQ0FBQyxDQUFDO1lBQ3BDLElBQUksQ0FBQyxXQUFXLENBQUMsa0JBQWtCLENBQUMsYUFBYSxFQUFFLElBQUksQ0FBQywwQkFBMEIsQ0FBQyxTQUFTLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQztZQUNsRyxJQUFJLENBQUMsV0FBVyxDQUFDLGtCQUFrQixDQUFDLGFBQWEsRUFBRSxJQUFJLENBQUMsMEJBQTBCLENBQUMsT0FBTyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDbEcsQ0FBQzthQUFNLENBQUM7WUFDTixJQUFJLENBQUMsUUFBUSxDQUFDLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQztZQUMzQixJQUFJLENBQUMsV0FBVyxDQUFDLGtCQUFrQixDQUFDLGFBQWEsRUFBRSxJQUFJLENBQUMsMEJBQTBCLENBQUMsU0FBUyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDcEcsQ0FBQztJQUNILENBQUM7SUFFRDs7Ozs7O09BTUc7SUFDSyxnQkFBZ0IsQ0FBQyxTQUFzQixFQUFFLE9BQW9CO1FBQ25FLElBQUksQ0FBQyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxFQUFFLENBQUM7WUFDdEIsTUFBTSxZQUFZLEdBQUcsRUFBRSxJQUFJLEVBQUUsTUFBTSxFQUFFLE9BQU8sRUFBRSxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksRUFBRSxvQkFBb0IsRUFBRSxFQUFFLE9BQU8sRUFBRSxJQUFJLENBQUMsTUFBTSxDQUFDLFlBQVksQ0FBQyxjQUFjLENBQUMsZ0JBQWdCLEVBQUUsS0FBSyxFQUFFLElBQUksQ0FBQyxLQUFLLEVBQUUsY0FBYyxFQUFFLElBQUksQ0FBQyxNQUFNLENBQUMsWUFBWSxDQUFDLGNBQWMsQ0FBQyxjQUFjLEVBQUUsY0FBYyxFQUFFLElBQUksQ0FBQyxNQUFNLENBQUMsWUFBWSxDQUFDLGNBQWMsQ0FBQyxjQUFjLEVBQUUsV0FBVyxFQUFFLElBQUksRUFBRSw0QkFBNEIsRUFBRSxJQUFJLENBQUMsTUFBTSxDQUFDLDRCQUE0QixFQUFFLEVBQUUsQ0FBQztZQUMzWixJQUFJLElBQUksQ0FBQyxNQUFNLENBQUMsWUFBWSxDQUFDLGNBQWMsRUFBRSxDQUFDO2dCQUM1QyxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUMsU0FBUyxFQUFFLE9BQU8sRUFBRSxZQUFZLENBQUMsQ0FBQyxDQUFDO2dCQUNsRCxJQUFJLENBQUMsV0FBVyxDQUFDLGtCQUFrQixDQUFDLGFBQWEsRUFBRSxJQUFJLENBQUMsMEJBQTBCLENBQUMsU0FBUyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7Z0JBQ2xHLElBQUksQ0FBQyxXQUFXLENBQUMsa0JBQWtCLENBQUMsYUFBYSxFQUFFLElBQUksQ0FBQywwQkFBMEIsQ0FBQyxPQUFPLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQztnQkFDaEcsSUFBSSxDQUFDLFdBQVcsQ0FBQyxrQkFBa0IsQ0FBQyxhQUFhLEVBQUUsRUFBRSxHQUFHLElBQUksQ0FBQywwQkFBMEIsQ0FBQyxZQUFZLEVBQUUsQ0FBQyxDQUFDLEVBQUUsT0FBTyxFQUFFLElBQUksQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxFQUFFLGVBQWUsRUFBRSxJQUFJLEVBQUUsaUJBQWlCLEVBQUUsSUFBSSxDQUFDLE1BQU0sQ0FBQyxZQUFZLENBQUMsY0FBYyxDQUFDLGNBQWMsRUFBRSxpQkFBaUIsRUFBRSxJQUFJLENBQUMsTUFBTSxDQUFDLFlBQVksQ0FBQyxjQUFjLENBQUMsY0FBYyxFQUFFLG1CQUFtQixFQUFFLElBQUksQ0FBQyxNQUFNLENBQUMsYUFBYSxDQUFDLFNBQVMsRUFBRSxNQUFNLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxFQUFFLGdDQUFnQyxFQUFFLElBQUksQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyw0QkFBNEIsQ0FBQyxFQUFFLENBQUMsQ0FBQztZQUMzZ0IsQ0FBQztpQkFBTSxDQUFDO2dCQUNOLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQyxTQUFTLEVBQUUsWUFBWSxDQUFDLENBQUMsQ0FBQztnQkFDekMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxrQkFBa0IsQ0FBQyxhQUFhLEVBQUUsSUFBSSxDQUFDLDBCQUEwQixDQUFDLFNBQVMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDO2dCQUNsRyxJQUFJLENBQUMsV0FBVyxDQUFDLGtCQUFrQixDQUFDLGFBQWEsRUFBRSxFQUFFLEdBQUcsSUFBSSxDQUFDLDBCQUEwQixDQUFDLFlBQVksRUFBRSxDQUFDLENBQUMsRUFBRSxPQUFPLEVBQUUsSUFBSSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLEVBQUUsZUFBZSxFQUFFLElBQUksRUFBRSxpQkFBaUIsRUFBRSxJQUFJLENBQUMsTUFBTSxDQUFDLFlBQVksQ0FBQyxjQUFjLENBQUMsY0FBYyxFQUFFLGlCQUFpQixFQUFFLElBQUksQ0FBQyxNQUFNLENBQUMsWUFBWSxDQUFDLGNBQWMsQ0FBQyxjQUFjLEVBQUUsbUJBQW1CLEVBQUUsSUFBSSxDQUFDLE1BQU0sQ0FBQyxhQUFhLENBQUMsU0FBUyxFQUFFLE1BQU0sQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLEVBQUUsZ0NBQWdDLEVBQUUsSUFBSSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLDRCQUE0QixDQUFDLEVBQUUsQ0FBQyxDQUFDO1lBQzNnQixDQUFDO1FBQ0gsQ0FBQzthQUFNLENBQUM7WUFDTixNQUFNLFVBQVUsR0FBRyxFQUFFLElBQUksRUFBRSxnQkFBZ0IsRUFBRSxPQUFPLEVBQUUsSUFBSSxDQUFDLFNBQVMsQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxjQUFjLENBQUMsb0JBQW9CLENBQUMsRUFBRSxvQkFBb0IsRUFBRSxFQUFFLE9BQU8sRUFBRSxJQUFJLEVBQUUsRUFBRSxDQUFDO1lBQzNLLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQyxTQUFTLEVBQUUsVUFBVSxDQUFDLENBQUMsQ0FBQztZQUN2QyxJQUFJLENBQUMsV0FBVyxDQUFDLGtCQUFrQixDQUFDLGFBQWEsRUFBRSxJQUFJLENBQUMsMEJBQTBCLENBQUMsVUFBVSxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDckcsQ0FBQztJQUNILENBQUM7SUFFTywwQkFBMEIsQ0FBQyxPQUFvQixFQUFFLElBQVk7UUFDbkUsTUFBTSxPQUFPLEdBQXdCO1lBQ25DLFVBQVUsRUFBRSxJQUFJLENBQUMsaUJBQWlCLElBQUksQ0FBQztZQUN2QyxNQUFNLEVBQUUsT0FBTyxDQUFDLElBQUk7WUFDcEIsTUFBTSxFQUFFLElBQUk7U0FDYixDQUFDO1FBQ0YsSUFBSSxDQUFDLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxhQUFhLEVBQUUsVUFBVSxFQUFFLENBQUM7WUFDNUMsT0FBTyxDQUFDLElBQUksR0FBRyxPQUFPLENBQUMsT0FBTyxDQUFDO1FBQ2pDLENBQUM7UUFDRCxPQUFPLE9BQU8sQ0FBQztJQUNqQixDQUFDO0lBRUQ7Ozs7OztPQU1HO0lBQ0gsUUFBUSxDQUFDLFFBQXNCLEVBQUUsV0FBb0I7UUFDbkQsSUFBSSxDQUFDLFFBQVEsSUFBSSxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsUUFBUSxDQUFDLEVBQUUsQ0FBQztZQUMxQyxPQUFPLENBQUMsS0FBSyxDQUFDLCtFQUErRSxFQUFFLFFBQVEsQ0FBQyxDQUFDO1lBQ3pHLE9BQU87UUFDVCxDQUFDO1FBQ0QsSUFBSSxXQUFXLEVBQUUsQ0FBQztZQUNoQixJQUFJLENBQUMsV0FBVyxDQUFDLGNBQWMsQ0FBQyxXQUFXLENBQUMsQ0FBQztZQUM3QyxJQUFJLENBQUMsV0FBVyxDQUFDLGNBQWMsQ0FBQyxXQUFXLENBQUMsQ0FBQztRQUMvQyxDQUFDO1FBQ0QsSUFBSSxDQUFDLFNBQVMsRUFBRSxDQUFDO1FBQ2pCLElBQUksQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFDO1FBQzlCLElBQUksQ0FBQyxXQUFXLENBQUMsV0FBVyxHQUFHLFFBQVEsQ0FBQztRQUN4QyxNQUFNLFdBQVcsR0FBRyxRQUFRLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDcEMsSUFBSSxXQUFXLElBQUksV0FBVyxDQUFDLElBQUksS0FBSyxNQUFNLEVBQUUsQ0FBQztZQUMvQyxJQUFJLENBQUMsS0FBSyxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsK0VBQStFO1FBQ3ZHLENBQUM7YUFDSSxDQUFDO1lBQ0osSUFBSSxDQUFDLFVBQVUsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLHFGQUFxRjtZQUNoSCxJQUFJLENBQUMsY0FBYyxFQUFFLENBQUM7UUFDeEIsQ0FBQztRQUNELElBQUksQ0FBQyxrQkFBa0IsRUFBRSxDQUFDO0lBQzVCLENBQUM7SUFFRDs7OztPQUlHO0lBQ0gsU0FBUztRQUNQLElBQUksSUFBSSxDQUFDLFNBQVMsQ0FBQyxLQUFLLEVBQUUsQ0FBQztZQUN6QixJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLGFBQWE7UUFDL0MsQ0FBQztRQUNELElBQUksQ0FBQyxXQUFXLENBQUMsV0FBVyxHQUFHLFNBQVMsQ0FBQyxDQUFDLHFCQUFxQjtRQUMvRCxJQUFJLENBQUMsUUFBUSxHQUFHLEVBQUUsQ0FBQztRQUNuQixJQUFJLENBQUMsY0FBYyxFQUFFLENBQUM7SUFDeEIsQ0FBQztJQUVEOzs7T0FHRztJQUNILFVBQVU7UUFDUixJQUFJLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUN6QixJQUFJLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FDWCxJQUFJLENBQUMsV0FBVyxDQUFDLGNBQWM7YUFDNUIsSUFBSSxDQUNILE1BQU0sQ0FBQyxTQUFTLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxTQUFTLENBQUMsRUFDaEMsU0FBUyxDQUFDLFNBQVMsQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxZQUFZLENBQUMsU0FBVSxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQ3BFLE1BQU0sQ0FBQyxnQkFBZ0IsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLGdCQUFnQixDQUFDLEVBQzlDLEdBQUcsQ0FBQyxnQkFBZ0IsQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxnQkFBaUIsQ0FBQyxPQUFPLEVBQUUsZ0JBQWlCLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FDeEYsQ0FBQyxTQUFTLEVBQUUsQ0FDaEIsQ0FBQztJQUNKLENBQUM7SUFFRDs7O09BR0c7SUFDSCxjQUFjO1FBQ1osSUFBSSxDQUFDLFdBQVcsQ0FBQyxjQUFjLEVBQUUsQ0FBQyxTQUFTLENBQ3pDLEdBQUcsRUFBRSxDQUFDLElBQUksQ0FBQyxjQUFjLEVBQUUsQ0FDNUIsQ0FBQztJQUNKLENBQUM7SUFFRDs7O09BR0c7SUFDSCxjQUFjO1FBQ1osSUFBSSxDQUFDLGlCQUFpQixFQUFFLFdBQVcsRUFBRSxDQUFDO1FBQ3RDLElBQUksQ0FBQyxpQkFBaUIsR0FBRyxTQUFTLENBQUM7UUFDbkMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDMUIsSUFBSSxDQUFDLEdBQUcsQ0FBQyxhQUFhLEVBQUUsQ0FBQztRQUV6QixJQUFJLElBQUksQ0FBQyxrQkFBa0IsRUFBRSxDQUFDO1lBQzVCLFVBQVUsQ0FBQyxHQUFHLEVBQUU7Z0JBQ2QsSUFBSSxDQUFDLGFBQWEsRUFBRSxhQUFhLENBQUMsS0FBSyxFQUFFLENBQUM7WUFDNUMsQ0FBQyxDQUFDLENBQUM7UUFDTCxDQUFDO0lBQ0gsQ0FBQztJQUVEOzs7Ozs7O09BT0c7SUFDSCxXQUFXLENBQUMsS0FBYTtRQUN2QixJQUFJLENBQUMsQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLFVBQVUsQ0FBQyxLQUFLLElBQUksQ0FBQyxDQUFDLElBQUksQ0FBQyxXQUFXLENBQUMsbUJBQW1CLENBQUMsS0FBSyxFQUFFLENBQUM7WUFDeEYsT0FBTztRQUNULENBQUM7UUFDRCxJQUFJLENBQUMsYUFBYSxHQUFHLEtBQUssQ0FBQztRQUMzQixJQUFJLENBQUMscUJBQXFCLEdBQUcsSUFBSSxDQUFDLHdCQUF3QixDQUFDLEtBQUssQ0FBQyxDQUFDO1FBRWxFLDBEQUEwRDtRQUMxRCxNQUFNLE9BQU8sR0FBRyxJQUFJLENBQUMsV0FBVyxDQUFDLFdBQVksQ0FBQyxJQUFJLENBQUMsd0JBQXdCLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQztRQUNwRixJQUFJLENBQUMsUUFBUSxHQUFHLE9BQU8sT0FBTyxDQUFDLE9BQU8sS0FBSyxRQUFRLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFFLE9BQU8sQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUF3QixDQUFDLElBQUksQ0FBQztRQUV4SCxJQUFJLENBQUMsV0FBVyxDQUFDLGtCQUFrQixDQUFDLFlBQVksRUFBRSxFQUFDLE1BQU0sRUFBRSxJQUFJLENBQUMsd0JBQXdCLENBQUMsS0FBSyxDQUFDLEVBQUMsQ0FBQyxDQUFDO0lBQ3BHLENBQUM7SUFFRDs7O09BR0c7SUFDSCxXQUFXLENBQUMsS0FBYTtRQUN2QixzQ0FBc0M7UUFDdEMsTUFBTSxHQUFHLEdBQUcsSUFBSSxDQUFDLHdCQUF3QixDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQ2pELElBQUksQ0FBQyxXQUFXLENBQUMsa0JBQWtCLENBQUMsZ0JBQWdCLEVBQUUsRUFBRSxNQUFNLEVBQUUsR0FBRyxFQUFFLENBQUMsQ0FBQztJQUN6RSxDQUFDO0lBRUQ7Ozs7O09BS0c7SUFDSCxpQkFBaUIsQ0FBQyxLQUFhO1FBQzdCLElBQUksQ0FBQyxDQUFDLElBQUksQ0FBQyxXQUFXLENBQUMsVUFBVSxDQUFDLEtBQUssSUFBSSxDQUFDLENBQUMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxtQkFBbUIsQ0FBQyxLQUFLLEVBQUUsQ0FBQztZQUN4RixPQUFPO1FBQ1QsQ0FBQztRQUNELHlKQUF5SjtRQUN6SixJQUFJLENBQUMsR0FBRyxLQUFLLENBQUM7UUFDZCxPQUFPLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxLQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLEtBQUssTUFBTSxJQUFJLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxLQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxvQkFBb0IsQ0FBQyxXQUFXLEtBQUssSUFBSSxDQUFDLEVBQUUsQ0FBQztZQUN2SSxDQUFDLEVBQUUsQ0FBQztRQUNOLENBQUM7UUFDRCwwQ0FBMEM7UUFDMUMsSUFBSSxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUM7WUFDWCxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLEtBQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQyxFQUFFLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQzNELGtGQUFrRjtZQUNsRixNQUFNLEdBQUcsR0FBRyxJQUFJLENBQUMsd0JBQXdCLENBQUMsQ0FBQyxDQUFDLENBQUM7WUFDN0MsNkZBQTZGO1lBQzdGLElBQUksQ0FBQyxXQUFXLENBQUMsV0FBVyxHQUFHLElBQUksQ0FBQyxXQUFXLENBQUMsV0FBWSxDQUFDLEtBQUssQ0FBQyxDQUFDLEVBQUUsR0FBRyxHQUFHLENBQUMsQ0FBQyxDQUFDO1lBQy9FLG1CQUFtQjtZQUNuQixJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxXQUFXLENBQUMsV0FBVyxDQUFDLENBQUM7WUFDekMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxrQkFBa0IsQ0FBQyxzQkFBc0IsRUFBRSxFQUFFLE1BQU0sRUFBRSxHQUFHLEVBQUUsQ0FBQyxDQUFDO1FBQy9FLENBQUM7SUFDSCxDQUFDO0lBRUQ7Ozs7OztPQU1HO0lBQ0ssd0JBQXdCLENBQUMsS0FBYTtRQUM1QyxzRkFBc0Y7UUFDdEYsa0RBQWtEO1FBQ2xELDJNQUEyTTtRQUMzTSxNQUFNLE9BQU8sR0FBRyxJQUFJLENBQUMsV0FBVyxDQUFDLFdBQVk7YUFDMUMsS0FBSyxFQUFFO2FBQ1AsR0FBRyxDQUFDLENBQUMsT0FBTyxFQUFFLEdBQUcsRUFBRSxFQUFFLENBQUMsQ0FBQyxFQUFFLEdBQUcsT0FBTyxFQUFFLG9CQUFvQixFQUFFLEVBQUUsR0FBRyxPQUFPLENBQUMsb0JBQW9CLEVBQUUsSUFBSSxFQUFFLEdBQUcsRUFBRSxFQUFFLENBQUMsQ0FBQzthQUM3RyxHQUFHLENBQUMsQ0FBQyxPQUFPLEVBQUUsRUFBRTtZQUNmLElBQUksT0FBTyxDQUFDLElBQUksS0FBSyxNQUFNLEVBQUUsQ0FBQztnQkFDNUIsT0FBTyxFQUFFLEdBQUcsT0FBTyxFQUFFLG9CQUFvQixFQUFFLEVBQUUsR0FBRyxPQUFPLENBQUMsb0JBQW9CLEVBQUUsT0FBTyxFQUFFLElBQUksRUFBRSxFQUFFLENBQUE7WUFDakcsQ0FBQztZQUNELE9BQU8sT0FBTyxDQUFDO1FBQ2pCLENBQUMsQ0FBQyxDQUFBO1FBQ0osNkdBQTZHO1FBQzdHLDJNQUEyTTtRQUMzTSwrRUFBK0U7UUFDL0UsOEhBQThIO1FBQzlILE1BQU0sNENBQTRDLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQyxLQUFNO2FBQ3ZFLEtBQUssQ0FBQyxDQUFDLEVBQUUsS0FBSyxDQUFDO2FBQ2YsR0FBRyxDQUFDLENBQUMsT0FBTyxFQUFFLEVBQUU7WUFDZixJQUFJLE9BQU8sQ0FBQyxJQUFJLEtBQUssTUFBTSxFQUFFLENBQUM7Z0JBQzVCLE9BQU8sRUFBRSxHQUFHLE9BQU8sRUFBRSxvQkFBb0IsRUFBRSxFQUFFLEdBQUcsT0FBTyxDQUFDLG9CQUFvQixFQUFFLE9BQU8sRUFBRSxJQUFJLEVBQUUsRUFBRSxDQUFBO1lBQ2pHLENBQUM7WUFDRCxPQUFPLE9BQU8sQ0FBQztRQUNqQixDQUFDLENBQUM7YUFDRCxNQUFNLENBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxvQkFBb0IsQ0FBQyxPQUFPLENBQUMsQ0FBQyxNQUFNLENBQUM7UUFDbkUscURBQXFEO1FBQ3JELHNGQUFzRjtRQUN0Rix1S0FBdUs7UUFDdkssTUFBTSxlQUFlLEdBQUcsT0FBTyxDQUFDLE1BQU0sQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDLE9BQU8sQ0FBQyxvQkFBb0IsQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUN4RiwwREFBMEQ7UUFDMUQsT0FBTyxlQUFlLENBQUMsS0FBSyxHQUFHLDRDQUE0QyxDQUFDLENBQUMsb0JBQW9CLENBQUMsSUFBSSxDQUFDO0lBQ3pHLENBQUM7SUFFRDs7O09BR0c7SUFDSCxPQUFPLENBQUMsS0FBb0I7UUFDMUIsUUFBUSxLQUFLLENBQUMsR0FBRyxFQUFFLENBQUM7WUFDbEIsS0FBSyxXQUFXO2dCQUNkLElBQUksQ0FBQyxlQUFlLEVBQUUsQ0FBQztnQkFDdkIsTUFBTTtZQUNSLEtBQUssT0FBTztnQkFDVixJQUFJLENBQUMsS0FBSyxDQUFDLFFBQVEsRUFBRSxDQUFDO29CQUNwQixLQUFLLENBQUMsY0FBYyxFQUFFLENBQUM7b0JBQ3ZCLElBQUksQ0FBQyxjQUFjLEVBQUUsQ0FBQztnQkFDeEIsQ0FBQztnQkFDRCxJQUFJLENBQUMsZUFBZSxFQUFFLENBQUM7Z0JBQ3ZCLE1BQU07WUFDUjtnQkFDRSxNQUFNO1FBQ1YsQ0FBQztJQUNILENBQUM7SUFFRDs7OztPQUlHO0lBQ0gsZUFBZSxDQUFDLEtBQXFCO1FBQ25DLElBQUksS0FBSyxFQUFFLEdBQUcsS0FBSyxPQUFPLElBQUksQ0FBQyxLQUFLLENBQUMsUUFBUSxFQUFFLENBQUM7WUFDOUMsS0FBSyxFQUFFLGNBQWMsRUFBRSxDQUFDO1FBQzFCLENBQUM7UUFDRCxNQUFNLFNBQVMsR0FBRyxHQUFHLENBQUM7UUFDdEIsTUFBTSxFQUFFLEdBQUcsSUFBSSxDQUFDLGFBQWMsQ0FBQyxhQUFhLENBQUM7UUFDN0MsRUFBRSxDQUFDLEtBQUssQ0FBQyxTQUFTLEdBQUcsR0FBRyxTQUFTLElBQUksQ0FBQztRQUN0QyxFQUFFLENBQUMsS0FBSyxDQUFDLE1BQU0sR0FBRyxNQUFNLENBQUM7UUFDekIsRUFBRSxDQUFDLEtBQUssQ0FBQyxNQUFNLEdBQUcsR0FBRyxFQUFFLENBQUMsWUFBWSxJQUFJLENBQUM7UUFDekMsRUFBRSxDQUFDLEtBQUssQ0FBQyxTQUFTLEdBQUcsRUFBRSxDQUFDLFlBQVksSUFBSSxTQUFTLENBQUMsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDO0lBQzFFLENBQUM7SUFFRDs7OztPQUlHO0lBQ0gsTUFBTSxDQUFDLE9BQW9CLEVBQUUsSUFBWTtRQUN2QyxzQ0FBc0M7UUFDdEMsTUFBTSxHQUFHLEdBQUcsSUFBSSxDQUFDLHdCQUF3QixDQUFDLElBQUksQ0FBQyxDQUFDO1FBQ2hELElBQUksQ0FBQyxXQUFXLENBQUMsa0JBQWtCLENBQUMsb0JBQW9CLEVBQUUsRUFBRSxJQUFJLEVBQUUsR0FBRyxFQUFFLENBQUMsQ0FBQztRQUN6RSxJQUFJLENBQUMsVUFBVSxHQUFHLE1BQU0sQ0FBQztRQUN6QixJQUFJLENBQUMsZUFBZSxHQUFHLE9BQU8sQ0FBQztRQUMvQixJQUFJLENBQUMsYUFBYSxHQUFHLFNBQVMsQ0FBQztRQUMvQixJQUFJLENBQUMsVUFBVSxHQUFHLElBQUksQ0FBQztRQUN2QixJQUFJLENBQUMsVUFBVSxHQUFHLElBQUksQ0FBQTtRQUV0QixJQUFJLENBQUMsV0FBVyxDQUFDLFdBQVksQ0FBQyxJQUFJLENBQUMsd0JBQXdCLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxvQkFBb0IsQ0FBQyxNQUFNLEdBQUcsSUFBSSxDQUFDO1FBQ3RHLElBQUksQ0FBQyxXQUFXLENBQUMsV0FBWSxDQUFDLElBQUksQ0FBQyx3QkFBd0IsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLG9CQUFvQixDQUFDLFNBQVMsR0FBRyxLQUFLLENBQUM7UUFDMUcsSUFBSSxDQUFDLGtCQUFrQixFQUFFLENBQUM7SUFDNUIsQ0FBQztJQUVEOzs7OztPQUtHO0lBQ0gsU0FBUyxDQUFDLE9BQW9CLEVBQUUsSUFBWTtRQUMxQyxzQ0FBc0M7UUFDdEMsTUFBTSxHQUFHLEdBQUcsSUFBSSxDQUFDLHdCQUF3QixDQUFDLElBQUksQ0FBQyxDQUFDO1FBQ2hELElBQUksQ0FBQyxXQUFXLENBQUMsa0JBQWtCLENBQUMsc0JBQXNCLEVBQUUsRUFBRSxJQUFJLEVBQUUsR0FBRyxFQUFFLENBQUMsQ0FBQztRQUMzRSxJQUFJLENBQUMsVUFBVSxHQUFHLFNBQVMsQ0FBQztRQUM1QixJQUFJLENBQUMsZUFBZSxHQUFHLE9BQU8sQ0FBQztRQUMvQixJQUFJLENBQUMsU0FBUyxHQUFHLEVBQUUsQ0FBQztRQUNwQixJQUFJLENBQUMsYUFBYSxHQUFHLFNBQVMsQ0FBQztRQUMvQixJQUFJLENBQUMsVUFBVSxHQUFHLElBQUksQ0FBQztRQUN2QixJQUFJLENBQUMsVUFBVSxHQUFHLElBQUksQ0FBQTtRQUV0QixJQUFJLENBQUMsV0FBVyxDQUFDLFdBQVksQ0FBQyxJQUFJLENBQUMsd0JBQXdCLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxvQkFBb0IsQ0FBQyxTQUFTLEdBQUcsSUFBSSxDQUFDO1FBQ3pHLElBQUksQ0FBQyxXQUFXLENBQUMsV0FBWSxDQUFDLElBQUksQ0FBQyx3QkFBd0IsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLG9CQUFvQixDQUFDLE1BQU0sR0FBRyxLQUFLLENBQUM7UUFDdkcsSUFBSSxDQUFDLGtCQUFrQixFQUFFLENBQUM7SUFDNUIsQ0FBQztJQUVPLGtCQUFrQjtRQUN4QixJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLFdBQVcsQ0FBQyxDQUFDO1FBQ2xELElBQUksSUFBSSxDQUFDLFdBQVcsQ0FBQyxXQUFXLEVBQUUsQ0FBQztZQUNqQyxJQUFJLENBQUMsV0FBVyxDQUFDLGVBQWUsQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLFdBQVcsRUFBRSxTQUFTLEVBQUUsSUFBSSxDQUFDLFdBQVcsQ0FBQyxXQUFXLENBQUMsQ0FBQyxTQUFTLEVBQUUsQ0FBQztRQUN0SCxDQUFDO1FBQ0QsSUFBSSxDQUFDLEdBQUcsQ0FBQyxhQUFhLEVBQUUsQ0FBQztJQUMzQixDQUFDO0lBRUQ7O09BRUc7SUFDSCxVQUFVO1FBQ1IsTUFBTSxPQUFPLEdBQUc7WUFDZCxTQUFTLEVBQUUsSUFBSSxDQUFDLGFBQWE7WUFDN0IsTUFBTSxFQUFFLElBQUksQ0FBQyxVQUFVO1NBQ3hCLENBQUM7UUFFRiw4Q0FBOEM7UUFDOUMsSUFBSSxJQUFJLENBQUMsTUFBTSxDQUFDLGFBQWEsQ0FBQyxVQUFVO1lBQ3RDLE9BQU8sQ0FBQyxNQUFNLENBQUMsR0FBRyxJQUFJLENBQUMsZUFBZ0IsQ0FBQyxPQUFPLENBQUM7UUFFbEQsSUFBSSxJQUFJLENBQUMsVUFBVSxLQUFLLFNBQVMsRUFBRSxDQUFDO1lBQ2xDLE9BQU8sQ0FBQyxhQUFhLENBQUMsR0FBRyxJQUFJLENBQUMsU0FBUyxDQUFDO1lBQ3hDLElBQUksQ0FBQyxXQUFXLENBQUMsa0JBQWtCLENBQUMsMEJBQTBCLEVBQUUsT0FBTyxDQUFDLENBQUM7UUFDM0UsQ0FBQzthQUFNLENBQUM7WUFDTixJQUFJLENBQUMsV0FBVyxDQUFDLGtCQUFrQixDQUFDLDBCQUEwQixFQUFFLE9BQU8sQ0FBQyxDQUFDO1FBQzNFLENBQUM7UUFDRCxJQUFJLENBQUMsb0JBQW9CLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsU0FBUyxDQUFDLDZCQUE2QixDQUFDLENBQUMsQ0FBQztRQUMzRixJQUFJLENBQUMsVUFBVSxHQUFHLEtBQUssQ0FBQztJQUMxQixDQUFDO0lBRUQ7O09BRUc7SUFDSCxZQUFZO1FBQ1YsSUFBSSxDQUFDLFVBQVUsR0FBRyxLQUFLLENBQUM7SUFDMUIsQ0FBQztJQUVEOzs7O09BSUc7SUFDSCxxQkFBcUIsQ0FBQyxJQUEyRCxFQUFFLElBQVk7UUFDN0YsSUFBSSxDQUFDLFdBQVcsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDO1FBQ3RDLE1BQU0sR0FBRyxHQUFHLElBQUksQ0FBQyx3QkFBd0IsQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUNoRCxNQUFNLE9BQU8sR0FBRztZQUNkLFFBQVEsRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLFFBQVE7WUFDakMsUUFBUSxFQUFFLElBQUksQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLFFBQVE7WUFDeEMsWUFBWSxFQUFFLElBQUksQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLFVBQVU7WUFDOUMsT0FBTyxFQUFFLElBQUksQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLGFBQWE7WUFDNUMsTUFBTSxFQUFFLEdBQUc7U0FDWixDQUFDO1FBQ0YsSUFBSSxDQUFDLENBQUMsSUFBSSxDQUFDLE1BQU07WUFBRSxPQUFPLENBQUMsU0FBUyxDQUFDLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQztRQUNwRCxJQUFJLENBQUMsV0FBVyxDQUFDLGtCQUFrQixDQUFDLDhCQUE4QixFQUFFLE9BQU8sQ0FBQyxDQUFDO0lBQy9FLENBQUM7SUFFRDs7O09BR0c7SUFDSCxzQkFBc0IsQ0FBQyxJQUEyRCxFQUFFLElBQVk7UUFDOUYsSUFBSSxDQUFDLFlBQVksQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUM5QyxNQUFNLEdBQUcsR0FBRyxJQUFJLENBQUMsd0JBQXdCLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDaEQsTUFBTSxPQUFPLEdBQUc7WUFDZCxRQUFRLEVBQUUsSUFBSSxDQUFDLFNBQVMsQ0FBQyxRQUFRO1lBQ2pDLFFBQVEsRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxRQUFRO1lBQ3hDLFlBQVksRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxVQUFVO1lBQzlDLE9BQU8sRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxhQUFhO1lBQzVDLE1BQU0sRUFBRSxHQUFHO1NBQ1osQ0FBQztRQUNGLElBQUksQ0FBQyxDQUFDLElBQUksQ0FBQyxNQUFNO1lBQUUsT0FBTyxDQUFDLFNBQVMsQ0FBQyxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUM7UUFDcEQsSUFBSSxDQUFDLFdBQVcsQ0FBQyxrQkFBa0IsQ0FBQywyQkFBMkIsRUFBRSxPQUFPLENBQUMsQ0FBQztJQUM1RSxDQUFDO0lBRUQ7Ozs7T0FJRztJQUNILGtCQUFrQixDQUFDLE1BQXVCLEVBQUUsS0FBYTtRQUN2RCxJQUFJLENBQUMsYUFBYSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUNoQyxJQUFJLENBQUMsV0FBVyxDQUFDLGtCQUFrQixDQUFDLDRCQUE0QixFQUFFLEVBQUMsTUFBTSxFQUFFLE1BQU0sQ0FBQyxPQUFPLEVBQUUsc0JBQXNCLEVBQUUsTUFBTSxDQUFDLElBQUksRUFBQyxDQUFDLENBQUE7SUFDbEksQ0FBQztJQUVEOzs7OztPQUtHO0lBQ0gsZ0JBQWdCLENBQUMsS0FBYTtRQUM1Qiw0Q0FBNEM7UUFDNUMsSUFBSSxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsS0FBTSxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsSUFBSSxLQUFLLFdBQVcsRUFBRSxDQUFDO1lBQ3hELE9BQU8sRUFBRSxDQUFDO1FBQ1osQ0FBQztRQUNELHNEQUFzRDtRQUN0RCxNQUFNLEtBQUssR0FBRyxJQUFJLENBQUMsU0FBUyxDQUFDLEtBQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQyxFQUFFLEtBQUssR0FBRyxDQUFDLENBQUMsQ0FBQztRQUN4RCxvSEFBb0g7UUFDcEgsc0hBQXNIO1FBQ3RILE1BQU0sR0FBRyxHQUFHLElBQUksQ0FBQyxXQUFXLENBQUMsaUNBQWlDLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDdEUsSUFBSSxHQUFHLEdBQUcsQ0FBQyxDQUFDLEVBQUUsQ0FBQztZQUNiLE9BQU8sQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLEtBQU0sQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLG9CQUFvQixDQUFDLE1BQU0sSUFBSSxFQUFFLENBQUM7UUFDeEUsQ0FBQztRQUNELE9BQU8sRUFBRSxDQUFDO0lBQ1osQ0FBQztJQUVEOzs7T0FHRztJQUNILFNBQVMsQ0FBQyxLQUFhO1FBQ3JCLElBQUksQ0FBQyxhQUFhLEdBQUcsSUFBSSxDQUFDLGdCQUFnQixDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQ2xELElBQUksQ0FBQyxpQkFBaUIsR0FBRyxJQUFJLENBQUM7UUFDOUIsSUFBSSxDQUFDLEdBQUcsQ0FBQyxhQUFhLEVBQUUsQ0FBQztJQUMzQixDQUFDO0lBRUQ7Ozs7OztPQU1HO0lBQ0gsdUJBQXVCLENBQUMsUUFBdUIsRUFBRSxLQUFhO1FBQzVELEtBQUssSUFBSSxDQUFDLEdBQUcsS0FBSyxFQUFFLENBQUMsR0FBRyxRQUFRLENBQUMsTUFBTSxFQUFFLENBQUMsRUFBRSxFQUFFLENBQUM7WUFDN0MsSUFBSSxRQUFRLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxLQUFLLFdBQVc7Z0JBQUUsT0FBTyxLQUFLLENBQUM7UUFDckQsQ0FBQztRQUNELE9BQU8sSUFBSSxDQUFDO0lBQ2QsQ0FBQztJQUVEOzs7Ozs7OztPQVFHO0lBQ0gsdUJBQXVCLENBQUMsT0FBZ0M7UUFDdEQsSUFDRSxPQUFPLEVBQUUsSUFBSSxLQUFLLFdBQVc7ZUFDMUI7WUFDRCxzQkFBc0I7WUFDdEIsQ0FBQyxPQUFPLE9BQU8sRUFBRSxPQUFPLEtBQUssUUFBUSxJQUFJLE9BQU8sRUFBRSxPQUFPLEtBQUssRUFBRSxDQUFDO2dCQUNqRSxtQkFBbUI7Z0JBQ25CLFNBQVM7bUJBQ0osT0FBTyxFQUFFLE9BQTZCLEVBQUUsQ0FBQyxDQUFDLENBQXdCLEVBQUUsSUFBSSxLQUFLLEVBQUU7WUFDcEYsb0ZBQW9GO2FBQ3JGO2VBQ0UsQ0FBQyxPQUFPLEVBQUUsb0JBQW9CLEVBQUUsV0FBVztlQUMzQyxDQUFDLE9BQU8sRUFBRSxvQkFBb0IsRUFBRSxTQUFTO2VBQ3pDLENBQUMsT0FBTyxFQUFFLG9CQUFvQixFQUFFLE1BQU07ZUFDdEMsQ0FBQyxPQUFPLEVBQUUsb0JBQW9CLEVBQUUsZ0JBQWdCLEVBQ25ELENBQUM7WUFDRCxPQUFPLElBQUksQ0FBQztRQUNkLENBQUM7UUFDRCxPQUFPLEtBQUssQ0FBQztJQUNmLENBQUM7K0dBbm1DVSxhQUFhO21HQUFiLGFBQWEsa3pCQVRiO1lBQ1QsZUFBZTtZQUNmLG9CQUFvQjtZQUNwQixxQkFBcUIsQ0FBQyxNQUFNLENBQUM7U0FDOUIsK29CQy9CSCx5aVRBeUxBLGdxUkR2SlksWUFBWSx5akJBQUUsV0FBVywwZ0NBQUUsb0JBQW9CLHdhQUFFLHlCQUF5QiwwRkFBRSxxQkFBcUIsdUdBQUUsZ0JBQWdCLGdNQUFFLGFBQWE7OzRGQUVqSSxhQUFhO2tCQWJ6QixTQUFTOytCQUNFLFlBQVksYUFHWDt3QkFDVCxlQUFlO3dCQUNmLG9CQUFvQjt3QkFDcEIscUJBQXFCLENBQUMsTUFBTSxDQUFDO3FCQUM5QixtQkFDZ0IsdUJBQXVCLENBQUMsTUFBTSxjQUNuQyxJQUFJLFdBQ1AsQ0FBQyxZQUFZLEVBQUUsV0FBVyxFQUFFLG9CQUFvQixFQUFFLHlCQUF5QixFQUFFLHFCQUFxQixFQUFFLGdCQUFnQixFQUFFLGFBQWEsQ0FBQzs4QkFjcEksVUFBVTtzQkFBbEIsS0FBSztnQkFFRyxLQUFLO3NCQUFiLEtBQUs7Z0JBT0csOEJBQThCO3NCQUF0QyxLQUFLO2dCQUVHLFFBQVE7c0JBQWhCLEtBQUs7Z0JBRUcsZUFBZTtzQkFBdkIsS0FBSztnQkFFRyw2QkFBNkI7c0JBQXJDLEtBQUs7Z0JBRUcsa0JBQWtCO3NCQUExQixLQUFLO2dCQUVHLElBQUk7c0JBQVosS0FBSztnQkFFRyxvQkFBb0I7c0JBQTVCLEtBQUs7Z0JBRUcsZUFBZTtzQkFBdkIsS0FBSztnQkFFRywwQkFBMEI7c0JBQWxDLEtBQUs7Z0JBRUcsd0JBQXdCO3NCQUFoQyxLQUFLO2dCQUVHLDRCQUE0QjtzQkFBcEMsS0FBSztnQkFFSSxVQUFVO3NCQUFuQixNQUFNO2dCQUdZLFFBQVE7c0JBQTFCLE1BQU07dUJBQUMsU0FBUztnQkFFQyxPQUFPO3NCQUF4QixNQUFNO3VCQUFDLFFBQVE7Z0JBQ04sSUFBSTtzQkFBYixNQUFNO2dCQUVHLFlBQVk7c0JBQXJCLE1BQU07Z0JBRUcsV0FBVztzQkFBcEIsTUFBTTtnQkFFRyxhQUFhO3NCQUF0QixNQUFNO2dCQUVtQixXQUFXO3NCQUFwQyxTQUFTO3VCQUFDLGFBQWE7Z0JBQ0ksYUFBYTtzQkFBeEMsU0FBUzt1QkFBQyxlQUFlO2dCQUVFLFVBQVU7c0JBQXJDLFlBQVk7dUJBQUMsWUFBWTtnQkFDQyxTQUFTO3NCQUFuQyxZQUFZO3VCQUFDLFdBQVc7Z0JBQ1ksbUJBQW1CO3NCQUF2RCxZQUFZO3VCQUFDLHFCQUFxQjtnQkFDRCxnQkFBZ0I7c0JBQWpELFlBQVk7dUJBQUMsa0JBQWtCO2dCQUV2QixTQUFTO3NCQUFqQixLQUFLIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQ29tbW9uTW9kdWxlIH0gZnJvbSBcIkBhbmd1bGFyL2NvbW1vblwiO1xuaW1wb3J0IHsgQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3ksIENoYW5nZURldGVjdG9yUmVmLCBDb21wb25lbnQsIENvbnRlbnRDaGlsZCwgRWxlbWVudFJlZiwgRXZlbnRFbWl0dGVyLCBJbnB1dCwgT25DaGFuZ2VzLCBPbkRlc3Ryb3ksIE9uSW5pdCwgT3V0cHV0LCBTaW1wbGVDaGFuZ2VzLCBUZW1wbGF0ZVJlZiwgVmlld0NoaWxkLCBpbmplY3QgfSBmcm9tIFwiQGFuZ3VsYXIvY29yZVwiO1xuaW1wb3J0IHsgRm9ybXNNb2R1bGUgfSBmcm9tIFwiQGFuZ3VsYXIvZm9ybXNcIjtcbmltcG9ydCB7IFRyYW5zbG9jb1BpcGUsIFRyYW5zbG9jb1NlcnZpY2UsIHByb3ZpZGVUcmFuc2xvY29TY29wZSB9IGZyb20gJ0Bqc3ZlcnNlL3RyYW5zbG9jbyc7XG5pbXBvcnQgeyBIdWJDb25uZWN0aW9uLCBIdWJDb25uZWN0aW9uU3RhdGUgfSBmcm9tIFwiQG1pY3Jvc29mdC9zaWduYWxyXCI7XG5pbXBvcnQgeyBCZWhhdmlvclN1YmplY3QsIFN1YnNjcmlwdGlvbiwgY29tYmluZUxhdGVzdCwgZmlsdGVyLCBmcm9tRXZlbnQsIG1hcCwgbWVyZ2UsIG9mLCBzd2l0Y2hNYXAsIHRha2UsIHRhcCB9IGZyb20gXCJyeGpzXCI7XG5cbmltcG9ydCB7IEFwcEdsb2JhbENvbmZpZywgQXJ0aWNsZSwgUXVlcnksIGlzQXV0aGVudGljYXRlZCwgc2V0R2xvYmFsQ29uZmlnIH0gZnJvbSBcIkBzaW5lcXVhL2F0b21pY1wiO1xuXG5pbXBvcnQgeyBDaGF0TWVzc2FnZUNvbXBvbmVudCB9IGZyb20gXCIuL2NoYXQtbWVzc2FnZS9jaGF0LW1lc3NhZ2UuY29tcG9uZW50XCI7XG5pbXBvcnQgeyBDaGF0U2VydmljZSB9IGZyb20gXCIuL2NoYXQuc2VydmljZVwiO1xuaW1wb3J0IHsgRGVidWdNZXNzYWdlQ29tcG9uZW50IH0gZnJvbSBcIi4vZGVidWctbWVzc2FnZS9kZWJ1Zy1tZXNzYWdlLmNvbXBvbmVudFwiO1xuaW1wb3J0IHsgSW5zdGFuY2VNYW5hZ2VyU2VydmljZSB9IGZyb20gXCIuL2luc3RhbmNlLW1hbmFnZXIuc2VydmljZVwiO1xuaW1wb3J0IHsgUmVzdENoYXRTZXJ2aWNlIH0gZnJvbSBcIi4vcmVzdC1jaGF0LnNlcnZpY2VcIjtcbmltcG9ydCB7IE5vdGlmaWNhdGlvbnNTZXJ2aWNlIH0gZnJvbSBcIi4vc2VydmljZXMvbm90aWZpY2F0aW9uLnNlcnZpY2VcIjtcbmltcG9ydCB7IFByaW5jaXBhbFNlcnZpY2UgfSBmcm9tIFwiLi9zZXJ2aWNlcy9wcmluY2lwYWwuc2VydmljZVwiO1xuaW1wb3J0IHsgU2VhcmNoU2VydmljZSB9IGZyb20gXCIuL3NlcnZpY2VzL3NlYXJjaC5zZXJ2aWNlXCI7XG5pbXBvcnQgeyBUb2tlblByb2dyZXNzQmFyQ29tcG9uZW50IH0gZnJvbSBcIi4vdG9rZW4tcHJvZ3Jlc3MtYmFyL3Rva2VuLXByb2dyZXNzLWJhci5jb21wb25lbnRcIjtcbmltcG9ydCB7IFRvb2x0aXBEaXJlY3RpdmUgfSBmcm9tIFwiLi90b29sdGlwL3Rvb2x0aXAuZGlyZWN0aXZlXCI7XG5pbXBvcnQgeyBDaGF0Q29uZmlnLCBDaGF0Q29udGV4dEF0dGFjaG1lbnQsIENoYXRNZXNzYWdlLCBEZWJ1Z01lc3NhZ2UsIEdsbG1Nb2RlbERlc2NyaXB0aW9uLCBJbml0Q2hhdCwgTWVzc2FnZUhhbmRsZXIsIFJhd01lc3NhZ2UsIFN1Z2dlc3RlZEFjdGlvbiB9IGZyb20gXCIuL3R5cGVzXCI7XG5pbXBvcnQgeyBSYXdNZXNzYWdlQ29udGVudCwgVGV4dE1lc3NhZ2VDb250ZW50IH0gZnJvbSBcIi4vdHlwZXMvbWVzc2FnZS1jb250ZW50LnR5cGVzXCI7XG5pbXBvcnQgeyBXZWJTb2NrZXRDaGF0U2VydmljZSB9IGZyb20gXCIuL3dlYnNvY2tldC1jaGF0LnNlcnZpY2VcIjtcblxuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAnc3EtY2hhdC12MycsIC8vIG1hbmRhdG9yeSBzaW5jZSBAc2luZXF1YS9jb21wb25lbnRzIGFscmVhZHkgaGFzIHRoZSBzYW1lIHRhZy1uYW1lIFwic3EtY2hhdFwiXG4gIHRlbXBsYXRlVXJsOiAnLi9jaGF0LmNvbXBvbmVudC5odG1sJyxcbiAgc3R5bGVVcmxzOiBbJy4vY2hhdC5jb21wb25lbnQuc2NzcyddLFxuICBwcm92aWRlcnM6IFtcbiAgICBSZXN0Q2hhdFNlcnZpY2UsXG4gICAgV2ViU29ja2V0Q2hhdFNlcnZpY2UsXG4gICAgcHJvdmlkZVRyYW5zbG9jb1Njb3BlKCdjaGF0JylcbiAgXSxcbiAgY2hhbmdlRGV0ZWN0aW9uOiBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneS5PblB1c2gsXG4gIHN0YW5kYWxvbmU6IHRydWUsXG4gIGltcG9ydHM6IFtDb21tb25Nb2R1bGUsIEZvcm1zTW9kdWxlLCBDaGF0TWVzc2FnZUNvbXBvbmVudCwgVG9rZW5Qcm9ncmVzc0JhckNvbXBvbmVudCwgRGVidWdNZXNzYWdlQ29tcG9uZW50LCBUb29sdGlwRGlyZWN0aXZlLCBUcmFuc2xvY29QaXBlXVxufSlcbmV4cG9ydCBjbGFzcyBDaGF0Q29tcG9uZW50IGltcGxlbWVudHMgT25Jbml0LCBPbkNoYW5nZXMsIE9uRGVzdHJveSB7XG5cbiAgcHVibGljIHdlYnNvY2tldFNlcnZpY2UgPSBpbmplY3QoV2ViU29ja2V0Q2hhdFNlcnZpY2UpO1xuICBwdWJsaWMgcmVzdFNlcnZpY2UgPSBpbmplY3QoUmVzdENoYXRTZXJ2aWNlKTtcbiAgcHVibGljIGluc3RhbmNlTWFuYWdlclNlcnZpY2UgPSBpbmplY3QoSW5zdGFuY2VNYW5hZ2VyU2VydmljZSk7XG4gIHB1YmxpYyBzZWFyY2hTZXJ2aWNlID0gaW5qZWN0KFNlYXJjaFNlcnZpY2UpO1xuICBwdWJsaWMgcHJpbmNpcGFsU2VydmljZSA9IGluamVjdChQcmluY2lwYWxTZXJ2aWNlKTtcbiAgcHVibGljIGNkciA9IGluamVjdChDaGFuZ2VEZXRlY3RvclJlZik7XG4gIHB1YmxpYyBub3RpZmljYXRpb25zU2VydmljZSA9IGluamVjdChOb3RpZmljYXRpb25zU2VydmljZSk7XG4gIHByaXZhdGUgcmVhZG9ubHkgdHJhbnNsb2NvID0gaW5qZWN0KFRyYW5zbG9jb1NlcnZpY2UpO1xuXG4gIC8qKiBEZWZpbmUgdGhlIGtleSBiYXNlZCBvbiBpdCwgdGhlIGNoYXQgc2VydmljZSBpbnN0YW5jZSB3aWxsIGJlIHN0b3JlZCAqL1xuICBASW5wdXQoKSBpbnN0YW5jZUlkOiBzdHJpbmc7XG4gIC8qKiBEZWZpbmUgdGhlIHF1ZXJ5IHRvIHVzZSB0byBmZXRjaCBhbnN3ZXJzICovXG4gIEBJbnB1dCgpIHF1ZXJ5OiBRdWVyeSA9IHRoaXMuc2VhcmNoU2VydmljZS5xdWVyeTtcbiAgLyoqIEZ1bmN0aW9uIHRoYXQgZGV0ZXJtaW5lcyB3aGV0aGVyIHRoZSBjaGF0IHNob3VsZCBiZSByZWxvYWRlZCBhZnRlciB0aGUgcXVlcnkgY2hhbmdlc1xuICAgKiBJZiBub3QgcHJvdmlkZWQsIHRoZSBjaGF0IHdpbGwgYmUgcmVsb2FkZWQgYnkgZGVmYXVsdFxuICAgKiBAcGFyYW0gcHJldlF1ZXJ5IFRoZSBwcmV2aW91cyBxdWVyeVxuICAgKiBAcGFyYW0gbmV3UXVlcnkgVGhlIG5ldyBxdWVyeVxuICAgKiBAcmV0dXJucyB0cnVlIGlmIHRoZSBjaGF0IHNob3VsZCBiZSByZWxvYWRlZCwgZmFsc2Ugb3RoZXJ3aXNlXG4gICAqL1xuICBASW5wdXQoKSBxdWVyeUNoYW5nZVNob3VsZFRyaWdnZXJSZWxvYWQ6IChwcmV2UXVlcnk6IFF1ZXJ5LCBuZXdRdWVyeTogUXVlcnkpID0+IGJvb2xlYW47XG4gIC8qKiBEZWZpbmUgdGhlIHByb3RvY29sIHRvIGJlIHVzZWQgZm9yIHRoaXMgY2hhdCBpbnN0YW5jZSovXG4gIEBJbnB1dCgpIHByb3RvY29sOiAnUkVTVCcgfCAnV0VCU09DS0VUJyA9IFwiV0VCU09DS0VUXCI7XG4gIC8qKiBNYXAgb2YgbGlzdGVuZXJzIG92ZXJyaWRpbmcgZGVmYXVsdCByZWdpc3RlcmVkIG9uZXMqL1xuICBASW5wdXQoKSBtZXNzYWdlSGFuZGxlcnM6IE1hcDxzdHJpbmcsIE1lc3NhZ2VIYW5kbGVyPGFueT4+ID0gbmV3IE1hcCgpO1xuICAvKiogV2hlbiB0aGUgYXNzaXN0YW50IGFuc3dlciBhIHVzZXIgcXVlc3Rpb24sIGF1dG9tYXRpY2FsbHkgc2Nyb2xsIGRvd24gdG8gdGhlIGJvdHRvbSBvZiB0aGUgZGlzY3Vzc2lvbiAqL1xuICBASW5wdXQoKSBhdXRvbWF0aWNTY3JvbGxUb0xhc3RSZXNwb25zZSA9IGZhbHNlO1xuICAvKiogV2hlbiB0aGUgYXNzaXN0YW50IGFuc3dlciBhIHVzZXIgcXVlc3Rpb24sIGF1dG9tYXRpY2FsbHkgZm9jdXMgdG8gdGhlIGNoYXQgaW5wdXQgKi9cbiAgQElucHV0KCkgZm9jdXNBZnRlclJlc3BvbnNlID0gZmFsc2U7XG4gIC8qKiBBIGNoYXQgZGlzY3Vzc2lvbiB0aGF0IHRoZSBjb21wb25lbnQgc2hvdWxkIGdldCBpbml0aWFsaXplZCB3aXRoIGl0ICovXG4gIEBJbnB1dCgpIGNoYXQ/OiBJbml0Q2hhdDtcbiAgLyoqIEljb24gdG8gdXNlIGZvciB0aGUgYXNzaXN0YW50IG1lc3NhZ2VzICovXG4gIEBJbnB1dCgpIGFzc2lzdGFudE1lc3NhZ2VJY29uID0gJ3NxLXNpbmVxdWEnO1xuICAvKiogSWNvbiB0byB1c2UgZm9yIHRoZSB1c2VyIG1lc3NhZ2VzICovXG4gIEBJbnB1dCgpIHVzZXJNZXNzYWdlSWNvbjogc3RyaW5nO1xuICAvKiogSWNvbiB0byB1c2UgZm9yIHRoZSBjb25uZWN0aW9uIGVycm9yIG1lc3NhZ2VzICovXG4gIEBJbnB1dCgpIGNvbm5lY3Rpb25FcnJvck1lc3NhZ2VJY29uOiBzdHJpbmc7XG4gIC8qKiBJY29uIHRvIHVzZSBmb3IgdGhlIHNlYXJjaCB3YXJuaW5nIG1lc3NhZ2VzICovXG4gIEBJbnB1dCgpIHNlYXJjaFdhcm5pbmdNZXNzYWdlSWNvbjogc3RyaW5nO1xuICAvLyBBZGQgY3VzdG9tIGFkZGl0aW9uYWxXb3JrZmxvd1Byb3BlcnRpZXMgdG8gdGhlIHVzZXIgcXVlcnkgbWVzc2FnZVxuICBASW5wdXQoKSBhZGRpdGlvbmFsV29ya2Zsb3dQcm9wZXJ0aWVzOiBSZWNvcmQ8c3RyaW5nLCBhbnk+ID0ge307XG4gIC8qKiBFdmVudCBlbWl0dGVyIHRyaWdnZXJlZCBvbmNlIHRoZSBzaWduYWxSIGNvbm5lY3Rpb24gaXMgZXN0YWJsaXNoZWQgICovXG4gIEBPdXRwdXQoKSBjb25uZWN0aW9uID0gbmV3IEV2ZW50RW1pdHRlcjxIdWJDb25uZWN0aW9uPigpO1xuICAvKiogRXZlbnQgZW1pdHRlciB0cmlnZ2VyZWQgZWFjaCB0aW1lIHRoZSBhc3Npc3RhbnQgdXBkYXRlcyB0aGUgY3VycmVudCBjaGF0ICovXG4gIC8qKiBFdmVudCBlbWl0dGVyIHRyaWdnZXJlZCB3aGVuIHRoZSBjaGF0IGlzIGxvYWRpbmcgbmV3IGNvbnRlbnQgKi9cbiAgQE91dHB1dChcImxvYWRpbmdcIikgbG9hZGluZyQgPSBuZXcgRXZlbnRFbWl0dGVyPGJvb2xlYW4+KGZhbHNlKTtcbiAgLyoqIEVtaXRzIHRoZSBhc3Npc3RhbnQgY29uZmlndXJhdGlvbiB1c2VkIHdoZW4gaW5zdGFudGlhdGluZyB0aGUgY29tcG9uZW50ICovXG4gIEBPdXRwdXQoXCJjb25maWdcIikgX2NvbmZpZyA9IG5ldyBFdmVudEVtaXR0ZXI8Q2hhdENvbmZpZz4oKTtcbiAgQE91dHB1dCgpIGRhdGEgPSBuZXcgRXZlbnRFbWl0dGVyPENoYXRNZXNzYWdlW10+KCk7XG4gIC8qKiBFdmVudCBlbWl0dGVyIHRyaWdnZXJlZCB3aGVuIHRoZSB1c2VyIGNsaWNrcyB0byBvcGVuIHRoZSBvcmlnaW5hbCBkb2N1bWVudCByZXByZXNlbnRpbmcgdGhlIGNvbnRleHQgYXR0YWNobWVudCovXG4gIEBPdXRwdXQoKSBvcGVuRG9jdW1lbnQgPSBuZXcgRXZlbnRFbWl0dGVyPEFydGljbGU+KCk7XG4gIC8qKiBFdmVudCBlbWl0dGVyIHRyaWdnZXJlZCB3aGVuIHRoZSB1c2VyIGNsaWNrcyB0byBvcGVuIHRoZSBwcmV2aWV3IG9mIGEgZG9jdW1lbnQgcmVwcmVzZW50aW5nIHRoZSBjb250ZXh0IGF0dGFjaG1lbnQgKi9cbiAgQE91dHB1dCgpIG9wZW5QcmV2aWV3ID0gbmV3IEV2ZW50RW1pdHRlcjxDaGF0Q29udGV4dEF0dGFjaG1lbnQ+KCk7XG4gIC8qKiBFdmVudCBlbWl0dGVyIHRyaWdnZXJlZCB3aGVuIHRoZSB1c2VyIGNsaWNrcyBvbiBhIHN1Z2dlc3RlZCBhY3Rpb24gKi9cbiAgQE91dHB1dCgpIHN1Z2dlc3RBY3Rpb24gPSBuZXcgRXZlbnRFbWl0dGVyPFN1Z2dlc3RlZEFjdGlvbj4oKTtcbiAgLyoqIFZpZXdDaGlsZCBkZWNvcmF0b3JzIHRvIGFjY2VzcyB0aGUgdGVtcGxhdGUgZWxlbWVudHMgKi9cbiAgQFZpZXdDaGlsZCgnbWVzc2FnZUxpc3QnKSBtZXNzYWdlTGlzdD86IEVsZW1lbnRSZWY8SFRNTFVMaXN0RWxlbWVudD47XG4gIEBWaWV3Q2hpbGQoJ3F1ZXN0aW9uSW5wdXQnKSBxdWVzdGlvbklucHV0PzogRWxlbWVudFJlZjxIVE1MVGV4dEFyZWFFbGVtZW50PjtcbiAgLyoqIENvbnRlbnRDaGlsZCBkZWNvcmF0b3JzIGFsbG93aW5nIHRoZSBvdmVycmlkZSBvZiB0aGUgZGVmYXVsdCB0ZW1wbGF0ZXMgZnJvbSB0aGUgcGFyZW50IGNvbXBvbmVudCAqL1xuICBAQ29udGVudENoaWxkKCdsb2FkaW5nVHBsJykgbG9hZGluZ1RwbD86IFRlbXBsYXRlUmVmPGFueT47XG4gIEBDb250ZW50Q2hpbGQoJ3JlcG9ydFRwbCcpIHJlcG9ydFRwbD86IFRlbXBsYXRlUmVmPGFueT47XG4gIEBDb250ZW50Q2hpbGQoJ3Rva2VuQ29uc3VtcHRpb25UcGwnKSB0b2tlbkNvbnN1bXB0aW9uVHBsPzogVGVtcGxhdGVSZWY8YW55PjtcbiAgQENvbnRlbnRDaGlsZCgnZGVidWdNZXNzYWdlc1RwbCcpIGRlYnVnTWVzc2FnZXNUcGw/OiBUZW1wbGF0ZVJlZjxhbnk+O1xuXG4gIEBJbnB1dCgpIGFwcENvbmZpZzogQXBwR2xvYmFsQ29uZmlnO1xuXG4gIGNoYXRTZXJ2aWNlOiBDaGF0U2VydmljZTtcbiAgY29uZmlnOiBDaGF0Q29uZmlnO1xuICBtZXNzYWdlcyQgPSBuZXcgQmVoYXZpb3JTdWJqZWN0PENoYXRNZXNzYWdlW10gfCB1bmRlZmluZWQ+KHVuZGVmaW5lZCk7XG4gIGlzQWRtaW5PckRlbGV0ZWRBZG1pbiA9IGZhbHNlO1xuICBxdWVzdGlvbiA9ICcnO1xuXG4gIHByaXZhdGUgX3N1YiA9IG5ldyBTdWJzY3JpcHRpb24oKTtcbiAgcHJpdmF0ZSBfZGF0YVN1YnNjcmlwdGlvbjogU3Vic2NyaXB0aW9uIHwgdW5kZWZpbmVkO1xuXG4gIC8qKiBWYXJpYWJsZXMgdGhhdCBkZXBlbmQgb24gdGhlIHR5cGUgb2YgbW9kZWwgaW4gdXNlICovXG4gIG1vZGVsRGVzY3JpcHRpb24/OiBHbGxtTW9kZWxEZXNjcmlwdGlvbjtcblxuICBtZXNzYWdlVG9FZGl0PzogbnVtYmVyO1xuICByZW1hcHBlZE1lc3NhZ2VUb0VkaXQ/OiBudW1iZXI7XG4gIGNoYW5nZXMkID0gbmV3IEJlaGF2aW9yU3ViamVjdDxTaW1wbGVDaGFuZ2VzIHwgdW5kZWZpbmVkPih1bmRlZmluZWQpO1xuICBjdXJyZW50TWVzc2FnZUluZGV4OiBudW1iZXIgfCB1bmRlZmluZWQ7XG4gIGZpcnN0Q2hhbmdlc0hhbmRsZWQgPSBmYWxzZTtcbiAgaXNBdEJvdHRvbSA9IHRydWU7XG4gIGluaXRpYWxpemF0aW9uRXJyb3IgPSBmYWxzZTtcbiAgZW5hYmxlZFVzZXJJbnB1dCA9IGZhbHNlO1xuICBpc0Nvbm5lY3RlZCA9IHRydWU7IC8vIEJ5IGRlZmF1bHQsIHRoZSBjaGF0IGlzIGNvbnNpZGVyZWQgY29ubmVjdGVkXG4gIHJldHJpYWxBdHRlbXB0czogbnVtYmVyIHwgdW5kZWZpbmVkO1xuICAvLyBGbGFnIHRvIHRyYWNrIHdoZXRoZXIgdGhlICdyZWNvbm5lY3RlZCcgbGlzdGVuZXIgaXMgYWxyZWFkeSByZWdpc3RlcmVkXG4gIHByaXZhdGUgX2lzUmVjb25uZWN0ZWRMaXN0ZW5lclJlZ2lzdGVyZWQgPSBmYWxzZTtcblxuICAvLyBJc3N1ZSByZXBvcnRpbmdcbiAgaXNzdWVUeXBlcz86IHN0cmluZ1tdO1xuICBkZWZhdWx0SXNzdWVUeXBlczogc3RyaW5nW10gPSBbXG4gICAgJ2NoYXQudXNlckludGVyZmFjZUJ1ZycsXG4gICAgJ2NoYXQuaW5jb3JyZWN0UmVzcG9uc2UnLFxuICAgICdjaGF0LmluY29tcGxldGVSZXNwb25zZScsXG4gICAgJ2NoYXQudGVjaG5pY2FsSXNzdWUnLFxuICAgICdjaGF0LnByaXZhY3lEYXRhU2VjdXJpdHlJc3N1ZScsXG4gICAgJ2NoYXQub3RoZXJJc3N1ZSdcbiAgXTtcbiAgaXNzdWVUeXBlOiBzdHJpbmcgPSAnJztcbiAgcmVwb3J0Q29tbWVudD86IHN0cmluZztcbiAgbWVzc2FnZVRvUmVwb3J0PzogQ2hhdE1lc3NhZ2U7XG4gIHJlcG9ydFJhbms/OiBudW1iZXI7XG4gIHJlcG9ydFR5cGU6ICdsaWtlJyB8ICdkaXNsaWtlJyA9ICdkaXNsaWtlJztcbiAgc2hvd1JlcG9ydCA9IGZhbHNlO1xuXG4gIC8vIERlYnVnIG1lc3NhZ2VzXG4gIGRlYnVnTWVzc2FnZXM6IERlYnVnTWVzc2FnZVtdIHwgdW5kZWZpbmVkO1xuICBzaG93RGVidWdNZXNzYWdlcyA9IGZhbHNlO1xuXG4gIC8vIExhc3QgbWVzc2FnZSBkdXJhdGlvblxuICBsYXN0RmV0Y2hEdXJhdGlvbj86IG51bWJlcjtcblxuICBwcml2YXRlIF9wcmV2aW91c1F1ZXJ5OiBRdWVyeTtcbiAgcHJpdmF0ZSBfcmVsb2FkU3Vic2NyaXB0aW9uOiBTdWJzY3JpcHRpb24gfCB1bmRlZmluZWQgPSB1bmRlZmluZWQ7XG5cbiAgbmdPbkluaXQoKTogdm9pZCB7XG4gICAgaWYgKHRoaXMuYXBwQ29uZmlnKSB7XG4gICAgICBzZXRHbG9iYWxDb25maWcodGhpcy5hcHBDb25maWcpO1xuICAgIH1cblxuICAgIHRoaXMuX3N1Yi5hZGQoXG4gICAgICBvZihpc0F1dGhlbnRpY2F0ZWQoKSkucGlwZShcbiAgICAgICAgdGFwKF8gPT4gdGhpcy5pbnN0YW50aWF0ZUNoYXRTZXJ2aWNlKCkpLFxuICAgICAgICBtYXAoXyA9PiB0aGlzLmNoYXRTZXJ2aWNlLmluaXRDaGF0Q29uZmlnKCkpLFxuICAgICAgICBzd2l0Y2hNYXAoKCkgPT4gdGhpcy5jaGF0U2VydmljZS5pbml0Q29uZmlnJCksXG4gICAgICAgIGZpbHRlcihpbml0Q29uZmlnID0+ICEhaW5pdENvbmZpZyksXG4gICAgICAgIHN3aXRjaE1hcChfID0+IHRoaXMuY2hhdFNlcnZpY2UuaW5pdCgpKSxcbiAgICAgICAgc3dpdGNoTWFwKF8gPT4gdGhpcy5jaGF0U2VydmljZS5pbml0UHJvY2VzcyQpLFxuICAgICAgICBmaWx0ZXIoc3VjY2VzcyA9PiAhIXN1Y2Nlc3MpLFxuICAgICAgICB0YXAoXyA9PiB7XG4gICAgICAgICAgaWYgKHRoaXMuY2hhdFNlcnZpY2UgaW5zdGFuY2VvZiBXZWJTb2NrZXRDaGF0U2VydmljZSkge1xuICAgICAgICAgICAgdGhpcy5jb25uZWN0aW9uLmVtaXQodGhpcy5jaGF0U2VydmljZS5jb25uZWN0aW9uKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgdGhpcy5vbkxvYWRDaGF0KCk7XG4gICAgICAgIH0pLFxuICAgICAgICB0YXAoXyA9PiB0aGlzLmNoYXRTZXJ2aWNlLm92ZXJyaWRlVXNlcigpKSxcbiAgICAgICAgc3dpdGNoTWFwKF8gPT4gdGhpcy5jaGF0U2VydmljZS51c2VyT3ZlcnJpZGUkKSxcbiAgICAgICAgc3dpdGNoTWFwKF8gPT4gdGhpcy5jaGF0U2VydmljZS5hc3Npc3RhbnRDb25maWckKSxcbiAgICAgICAgdGFwKGNvbmZpZyA9PiB7XG4gICAgICAgICAgdGhpcy5pc0FkbWluT3JEZWxldGVkQWRtaW4gPSB0aGlzLnByaW5jaXBhbFNlcnZpY2UucHJpbmNpcGFsIS5pc0FkbWluaXN0cmF0b3IgfHwgdGhpcy5wcmluY2lwYWxTZXJ2aWNlLnByaW5jaXBhbCEuaXNEZWxlZ2F0ZWRBZG1pbiB8fCBmYWxzZTtcbiAgICAgICAgICB0aGlzLmNvbmZpZyA9IGNvbmZpZyE7XG4gICAgICAgICAgdGhpcy5lbmFibGVkVXNlcklucHV0ID0gdGhpcy5jb25maWcubW9kZVNldHRpbmdzLmVuYWJsZWRVc2VySW5wdXQ7XG4gICAgICAgICAgdGhpcy5pc3N1ZVR5cGVzID0gdGhpcy5jb25maWcuYXVkaXRTZXR0aW5ncz8uaXNzdWVUeXBlcz8ubGVuZ3RoID8gdGhpcy5jb25maWcuYXVkaXRTZXR0aW5ncyEuaXNzdWVUeXBlcyA6IHVuZGVmaW5lZDtcbiAgICAgICAgICB0aGlzLl9jb25maWcuZW1pdChjb25maWcpO1xuICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICB0aGlzLnVwZGF0ZU1vZGVsRGVzY3JpcHRpb24oKTtcbiAgICAgICAgICAgIGlmKCF0aGlzLmZpcnN0Q2hhbmdlc0hhbmRsZWQpIHtcbiAgICAgICAgICAgICAgdGhpcy5fcHJldmlvdXNRdWVyeSA9IEpTT04ucGFyc2UoSlNPTi5zdHJpbmdpZnkodGhpcy5xdWVyeSkpOyAvLyBJbml0aWFsaXplIHRoZSBwcmV2aW91cyBxdWVyeVxuICAgICAgICAgICAgICB0aGlzLl9oYW5kbGVDaGFuZ2VzKCk7XG4gICAgICAgICAgICAgIHRoaXMuX2FkZFNjcm9sbExpc3RlbmVyKCk7XG4gICAgICAgICAgICAgIHRoaXMuZmlyc3RDaGFuZ2VzSGFuZGxlZCA9IHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgICAgIHRoaXMuaW5pdGlhbGl6YXRpb25FcnJvciA9IHRydWVcbiAgICAgICAgICAgIHRocm93IGVycm9yO1xuICAgICAgICAgIH1cbiAgICAgICAgfSlcbiAgICAgICkuc3Vic2NyaWJlKClcbiAgICApO1xuICB9XG5cbiAgbmdPbkNoYW5nZXMoY2hhbmdlczogU2ltcGxlQ2hhbmdlcykge1xuICAgIHRoaXMuY2hhbmdlcyQubmV4dChjaGFuZ2VzKTtcbiAgICBpZiAodGhpcy5jb25maWcpIHtcbiAgICAgIHRoaXMuX2hhbmRsZUNoYW5nZXMoKTtcbiAgICB9XG4gIH1cblxuICBuZ09uRGVzdHJveSgpOiB2b2lkIHtcbiAgICB0aGlzLl9zdWIudW5zdWJzY3JpYmUoKTtcbiAgICB0aGlzLl9kYXRhU3Vic2NyaXB0aW9uPy51bnN1YnNjcmliZSgpO1xuICAgIHRoaXMuX3JlbG9hZFN1YnNjcmlwdGlvbj8udW5zdWJzY3JpYmUoKTtcbiAgICBpZiAodGhpcy5jaGF0U2VydmljZSBpbnN0YW5jZW9mIFdlYlNvY2tldENoYXRTZXJ2aWNlKSB7XG4gICAgICB0aGlzLmNoYXRTZXJ2aWNlLnN0b3BDb25uZWN0aW9uKCk7XG4gICAgfVxuICB9XG5cbiAgZ2V0IGlzQWRtaW4oKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMucHJpbmNpcGFsU2VydmljZS5wcmluY2lwYWw/LmlzQWRtaW5pc3RyYXRvciB8fCBmYWxzZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBJbnN0YW50aWF0ZSB0aGUgY2hhdCBzZXJ2aWNlIGJhc2VkIG9uIHRoZSBwcm92aWRlZCBAaW5wdXQgcHJvdG9jb2xcbiAgICogVGhpcyBjaGF0IHNlcnZpY2UgaW5zdGFuY2Ugd2lsbCB0aGVuIGJlIHN0b3JlZCBpbiB0aGUgaW5zdGFuY2VNYW5hZ2VyU2VydmljZSB3aXRoIHByb3ZpZGVkIEBpbnB1dCBpbnN0YW5jZUlkIGFzIGEga2V5XG4gICAqL1xuICBpbnN0YW50aWF0ZUNoYXRTZXJ2aWNlKCk6IHZvaWQge1xuICAgIHN3aXRjaCAodGhpcy5wcm90b2NvbCkge1xuICAgICAgY2FzZSAnUkVTVCc6XG4gICAgICAgIHRoaXMuY2hhdFNlcnZpY2UgPSB0aGlzLnJlc3RTZXJ2aWNlO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgJ1dFQlNPQ0tFVCc6XG4gICAgICAgIHRoaXMuY2hhdFNlcnZpY2UgPSB0aGlzLndlYnNvY2tldFNlcnZpY2U7XG4gICAgICAgIGJyZWFrO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBDb3VsZCBub3QgZm91bmQgYSBDaGF0U2VydmljZSBpbXBsZW1lbnRhdGlvbiBjb3JyZXNwb25kaW5nIHRvIHRoZSBwcm92aWRlZCBwcm90b2NvbDogJyR7dGhpcy5wcm90b2NvbH0nYCk7XG4gICAgfVxuICAgIHRoaXMuY2hhdFNlcnZpY2Uuc2V0Q2hhdEluc3RhbmNlSWQodGhpcy5pbnN0YW5jZUlkKTtcbiAgICB0aGlzLmluc3RhbmNlTWFuYWdlclNlcnZpY2Uuc3RvcmVJbnN0YW5jZSh0aGlzLmluc3RhbmNlSWQsIHRoaXMuY2hhdFNlcnZpY2UpO1xuICB9XG5cbiAgLyoqXG4gICAqIEhhbmRsZXMgdGhlIGNoYW5nZXMgaW4gdGhlIGNoYXQgY29tcG9uZW50LlxuICAgKiBJZiB0aGUgY2hhdCBzZXJ2aWNlIGlzIGEgV2ViU29ja2V0Q2hhdFNlcnZpY2UsIGl0IGhhbmRsZXMgdGhlIG92ZXJyaWRlIG9mIHRoZSBtZXNzYWdlIGhhbmRsZXJzIGlmIHRoZXkgZXhpc3QuXG4gICAqIEluaXRpYWxpemVzIHRoZSBjaGF0IHdpdGggdGhlIHByb3ZpZGVkIGNoYXQgbWVzc2FnZXMgaWYgdGhleSBleGlzdCwgb3RoZXJ3aXNlIGxvYWRzIHRoZSBkZWZhdWx0IGNoYXQuXG4gICAqIElmIHRoZSBjaGF0IGlzIGluaXRpYWxpemVkLCB0aGUgaW5pdGlhbGl6YXRpb24gZXZlbnQgaXMgXCJRdWVyeVwiLCB0aGUgcXVlcnkgY2hhbmdlcywgYW5kIHRoZSBxdWVyeUNoYW5nZVNob3VsZFRyaWdnZXJSZWxvYWQgZnVuY3Rpb24gaXMgcHJvdmlkZWQsXG4gICAqIHRoZW4gdGhlIGNoYXQgc2hvdWxkIGJlIHJlbG9hZGVkIGlmIHRoZSBmdW5jdGlvbiByZXR1cm5zIHRydWUuIE90aGVyd2lzZSwgdGhlIGNoYXQgc2hvdWxkIGJlIHJlbG9hZGVkIGJ5IGRlZmF1bHQuXG4gICAqIEl0IHRha2VzIGludG8gYWNjb3VudCB0aGUgb25nb2luZyBzdHJlYW1pbmcgcHJvY2VzcyBhbmQgdGhlIG9uZ29pbmcgc3RvcHBpbmcgcHJvY2VzcyB0byB0cmlnZ2VyIHRoYXQgY29uZGl0aW9uYWxseSBkZWZpbmUgdGhlIGxvZ2ljXG4gICAqIG9mIHRoZSByZWxvYWQgOlxuICAgKiAtIElmIHRoZSBjaGF0IGlzIHN0cmVhbWluZywgdGhlbiBzdG9wIHRoZSBnZW5lcmF0aW9uIGFuZCB3YWl0IGZvciB0aGUgZmV0Y2ggdG8gY29tcGxldGUgYmVmb3JlIHJlbG9hZGluZyB0aGUgY2hhdC5cbiAgICogLSBJZiB0aGUgY2hhdCBpcyBzdG9wcGluZyB0aGUgZ2VuZXJhdGlvbiwgdGhlbiB3YWl0IGZvciB0aGUgZmV0Y2ggdG8gY29tcGxldGUgYmVmb3JlIHJlbG9hZGluZyB0aGUgY2hhdC5cbiAgICovXG4gIHByaXZhdGUgX2hhbmRsZUNoYW5nZXMoKSB7XG4gICAgY29uc3QgY2hhbmdlcyA9IHRoaXMuY2hhbmdlcyQudmFsdWU7XG4gICAgLy8gSWYgdGhlIGNoYXQgc2VydmljZSBpcyBhIFdlYlNvY2tldENoYXRTZXJ2aWNlLCBoYW5kbGUgdGhlIG92ZXJyaWRlIG9mIHRoZSBtZXNzYWdlIGhhbmRsZXJzIGlmIGV4aXN0c1xuICAgIGlmIChjaGFuZ2VzPy5tZXNzYWdlSGFuZGxlcnMgJiYgdGhpcy5tZXNzYWdlSGFuZGxlcnMgJiYgdGhpcy5jaGF0U2VydmljZSBpbnN0YW5jZW9mIFdlYlNvY2tldENoYXRTZXJ2aWNlKSB7XG4gICAgICB0aGlzLmNoYXRTZXJ2aWNlLm92ZXJyaWRlTWVzc2FnZUhhbmRsZXJzKHRoaXMubWVzc2FnZUhhbmRsZXJzKTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogSW5pdGlhbGl6ZSB0aGUgY2hhdCB3aXRoIHRoZSBwcm92aWRlZCBjaGF0IG1lc3NhZ2VzIGlmIGV4aXN0cywgb3RoZXJ3aXNlIGxvYWQgdGhlIGRlZmF1bHQgY2hhdFxuICAgICAqIE9uY2UgdGhlIGNoYXQgaXMgaW5pdGlhbGl6ZWQgKGZpcnN0Q2hhbmdlc0hhbmRsZWQgaXMgdHJ1ZSksIGFsbG93IG9wZW5pbmcgdGhlIGNoYXQgd2l0aCB0aGUgbmV3IHByb3ZpZGVkIG1lc3NhZ2VzIChpZiBleGlzdHMpXG4gICAgICovXG4gICAgaWYgKCF0aGlzLmZpcnN0Q2hhbmdlc0hhbmRsZWQgfHwgY2hhbmdlcz8uY2hhdCkge1xuICAgICAgY29uc3Qgb3BlbkNoYXQgPSAoKSA9PiB7XG4gICAgICAgIGlmICh0aGlzLm1lc3NhZ2VzJC52YWx1ZSkge1xuICAgICAgICAgIHRoaXMuY2hhdFNlcnZpY2UubGlzdFNhdmVkQ2hhdCgpOyAvLyBSZWZyZXNoIHRoZSBsaXN0IG9mIHNhdmVkIGNoYXRzXG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5vcGVuQ2hhdCh0aGlzLmNoYXQhLm1lc3NhZ2VzKTtcbiAgICAgIH07XG4gICAgICB0aGlzLmNoYXRTZXJ2aWNlLmdlbmVyYXRlQ2hhdElkKCk7XG4gICAgICBpZiAodGhpcy5jaGF0KSB7XG4gICAgICAgIHRoaXMuY2hhdFNlcnZpY2UuZ2VuZXJhdGVBdWRpdEV2ZW50KCdhc3QtbmV3LWNoYXQnLCB7J2NvbmZpZ3VyYXRpb24nOiBKU09OLnN0cmluZ2lmeSh0aGlzLmNoYXRTZXJ2aWNlLmFzc2lzdGFudENvbmZpZyQudmFsdWUpLCdjaGF0LWluaXQnOiBKU09OLnN0cmluZ2lmeSh0aGlzLmNoYXQpfSk7XG4gICAgICAgIG9wZW5DaGF0KCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aGlzLmNoYXRTZXJ2aWNlLmdlbmVyYXRlQXVkaXRFdmVudCgnYXN0LW5ldy1jaGF0Jywgeydjb25maWd1cmF0aW9uJzogSlNPTi5zdHJpbmdpZnkodGhpcy5jaGF0U2VydmljZS5hc3Npc3RhbnRDb25maWckLnZhbHVlKX0pO1xuICAgICAgICB0aGlzLmxvYWREZWZhdWx0Q2hhdCgpO1xuICAgICAgfVxuICAgIH1cbiAgICAvKipcbiAgICAgKiBJZiB0aGUgY2hhdCBpcyBpbml0aWFsaXplZCwgdGhlIGluaXRpYWxpemF0aW9uIGV2ZW50IGlzIFwiUXVlcnlcIiwgdGhlIHF1ZXJ5IGNoYW5nZXMgYW5kIHRoZSBxdWVyeUNoYW5nZVNob3VsZFRyaWdnZXJSZWxvYWQgZnVuY3Rpb24gaXMgcHJvdmlkZWQsXG4gICAgICogdGhlbiB0aGUgY2hhdCBzaG91bGQgYmUgcmVsb2FkZWQgaWYgdGhlIGZ1bmN0aW9uIHJldHVybnMgdHJ1ZVxuICAgICAqIE90aGVyd2lzZSwgdGhlIGNoYXQgc2hvdWxkIGJlIHJlbG9hZGVkIGJ5IGRlZmF1bHRcbiAgICAgKi9cbiAgICBpZiAodGhpcy5maXJzdENoYW5nZXNIYW5kbGVkICYmIGNoYW5nZXM/LnF1ZXJ5ICYmIHRoaXMuY29uZmlnLm1vZGVTZXR0aW5ncy5pbml0aWFsaXphdGlvbi5ldmVudCA9PT0gJ1F1ZXJ5Jykge1xuICAgICAgaWYgKHRoaXMucXVlcnlDaGFuZ2VTaG91bGRUcmlnZ2VyUmVsb2FkID8gdGhpcy5xdWVyeUNoYW5nZVNob3VsZFRyaWdnZXJSZWxvYWQodGhpcy5fcHJldmlvdXNRdWVyeSwgdGhpcy5xdWVyeSkgOiB0cnVlKSB7XG4gICAgICAgIGlmICghIXRoaXMuY2hhdFNlcnZpY2Uuc3RvcHBpbmdHZW5lcmF0aW9uJC52YWx1ZSkge1xuICAgICAgICAgIGlmICghdGhpcy5fcmVsb2FkU3Vic2NyaXB0aW9uKSB7XG4gICAgICAgICAgICAvLyBDcmVhdGUgYSBzdWJzY3JpcHRpb24gdG8gd2FpdCBmb3IgYm90aCBzdHJlYW1pbmckIGFuZCBzdG9wcGluZ0dlbmVyYXRpb24kIHRvIGJlIGZhbHNlXG4gICAgICAgICAgICB0aGlzLl9yZWxvYWRTdWJzY3JpcHRpb24gPSBjb21iaW5lTGF0ZXN0KFtcbiAgICAgICAgICAgICAgdGhpcy5jaGF0U2VydmljZS5zdHJlYW1pbmckLFxuICAgICAgICAgICAgICB0aGlzLmNoYXRTZXJ2aWNlLnN0b3BwaW5nR2VuZXJhdGlvbiRcbiAgICAgICAgICAgIF0pXG4gICAgICAgICAgICAgIC5waXBlKFxuICAgICAgICAgICAgICAgIGZpbHRlcigoW3N0cmVhbWluZywgc3RvcHBpbmddKSA9PiAhc3RyZWFtaW5nICYmICFzdG9wcGluZyksIC8vIFdhaXQgdW50aWwgYm90aCBhcmUgZmFsc2VcbiAgICAgICAgICAgICAgICB0YWtlKDEpIC8vIENvbXBsZXRlIGFmdGVyIHRoZSBmaXJzdCBtYXRjaFxuICAgICAgICAgICAgICApLnN1YnNjcmliZSgoKSA9PiB7XG4gICAgICAgICAgICAgICAgLy8gRXhlY3V0ZSB0aGUgcmVsb2FkIGFmdGVyIHRoZSBxdWVyeSBjaGFuZ2VcbiAgICAgICAgICAgICAgICB0aGlzLl90cmlnZ2VyUmVsb2FkQWZ0ZXJRdWVyeUNoYW5nZSgpO1xuICAgICAgICAgICAgICAgIC8vIFVwZGF0ZSBfcHJldmlvdXNRdWVyeSB3aXRoIHRoZSBjdXJyZW50IHF1ZXJ5XG4gICAgICAgICAgICAgICAgdGhpcy5fcHJldmlvdXNRdWVyeSA9IEpTT04ucGFyc2UoSlNPTi5zdHJpbmdpZnkodGhpcy5xdWVyeSkpO1xuICAgICAgICAgICAgICAgIC8vIENsZWFuIHVwIHN1YnNjcmlwdGlvbiBhbmQgcmVzZXQgaXRzIHZhbHVlXG4gICAgICAgICAgICAgICAgdGhpcy5fcmVsb2FkU3Vic2NyaXB0aW9uID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSBpZiAoISF0aGlzLmNoYXRTZXJ2aWNlLnN0cmVhbWluZyQudmFsdWUpIHtcbiAgICAgICAgICBpZiAoIXRoaXMuX3JlbG9hZFN1YnNjcmlwdGlvbikge1xuICAgICAgICAgICAgdGhpcy5fcmVsb2FkU3Vic2NyaXB0aW9uID0gdGhpcy5jaGF0U2VydmljZS5zdG9wR2VuZXJhdGlvbigpXG4gICAgICAgICAgICAgIC5zdWJzY3JpYmUoe1xuICAgICAgICAgICAgICAgIG5leHQ6ICgpID0+IHt9LFxuICAgICAgICAgICAgICAgIGVycm9yOiAoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAvLyBDbGVhbiB1cCBzdWJzY3JpcHRpb24gYW5kIHJlc2V0IGl0cyB2YWx1ZVxuICAgICAgICAgICAgICAgICAgdGhpcy5fcmVsb2FkU3Vic2NyaXB0aW9uPy51bnN1YnNjcmliZSgpO1xuICAgICAgICAgICAgICAgICAgdGhpcy5fcmVsb2FkU3Vic2NyaXB0aW9uID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgY29tcGxldGU6ICgpID0+IHtcbiAgICAgICAgICAgICAgICAgIC8vIFdhaXQgZm9yIHRoZSBvbmdvaW5nIGZldGNoIHRvIGNvbXBsZXRlLCB0aGVuIHRyaWdnZXIgdGhlIHJlbG9hZFxuICAgICAgICAgICAgICAgICAgdGhpcy5jaGF0U2VydmljZS5zdHJlYW1pbmckLnBpcGUoXG4gICAgICAgICAgICAgICAgICAgIGZpbHRlcigoc3RyZWFtaW5nKSA9PiAhc3RyZWFtaW5nKSxcbiAgICAgICAgICAgICAgICAgICAgdGFrZSgxKVxuICAgICAgICAgICAgICAgICAgKS5zdWJzY3JpYmUoKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAvLyBFeGVjdXRlIHRoZSByZWxvYWQgYWZ0ZXIgdGhlIHF1ZXJ5IGNoYW5nZVxuICAgICAgICAgICAgICAgICAgICB0aGlzLl90cmlnZ2VyUmVsb2FkQWZ0ZXJRdWVyeUNoYW5nZSgpO1xuICAgICAgICAgICAgICAgICAgICAvLyBVcGRhdGUgX3ByZXZpb3VzUXVlcnkgd2l0aCB0aGUgY3VycmVudCBxdWVyeVxuICAgICAgICAgICAgICAgICAgICB0aGlzLl9wcmV2aW91c1F1ZXJ5ID0gSlNPTi5wYXJzZShKU09OLnN0cmluZ2lmeSh0aGlzLnF1ZXJ5KSk7XG4gICAgICAgICAgICAgICAgICAgIC8vIENsZWFuIHVwIHN1YnNjcmlwdGlvbiBhbmQgcmVzZXQgaXRzIHZhbHVlXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuX3JlbG9hZFN1YnNjcmlwdGlvbiEudW5zdWJzY3JpYmUoKTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5fcmVsb2FkU3Vic2NyaXB0aW9uID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgLy8gRXhlY3V0ZSB0aGUgcmVsb2FkIGFmdGVyIHRoZSBxdWVyeSBjaGFuZ2VcbiAgICAgICAgICB0aGlzLl90cmlnZ2VyUmVsb2FkQWZ0ZXJRdWVyeUNoYW5nZSgpO1xuICAgICAgICAgIC8vIFVwZGF0ZSBfcHJldmlvdXNRdWVyeSB3aXRoIHRoZSBjdXJyZW50IHF1ZXJ5XG4gICAgICAgICAgdGhpcy5fcHJldmlvdXNRdWVyeSA9IEpTT04ucGFyc2UoSlNPTi5zdHJpbmdpZnkodGhpcy5xdWVyeSkpO1xuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICAvLyBVcGRhdGUgX3ByZXZpb3VzUXVlcnkgd2l0aCB0aGUgY3VycmVudCBxdWVyeVxuICAgICAgICB0aGlzLl9wcmV2aW91c1F1ZXJ5ID0gSlNPTi5wYXJzZShKU09OLnN0cmluZ2lmeSh0aGlzLnF1ZXJ5KSk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFRyaWdnZXJzIGEgcmVsb2FkIGFmdGVyIHRoZSBxdWVyeSBjaGFuZ2UuXG4gICAqIFRoaXMgbWV0aG9kIHBlcmZvcm1zIHRoZSBuZWNlc3Nhcnkgb3BlcmF0aW9ucyB0byByZWxvYWQgdGhlIGNoYXQgYWZ0ZXIgYSBxdWVyeSBjaGFuZ2UuXG4gICAqIEl0IHNldHMgdGhlIHN5c3RlbSBhbmQgdXNlciBtZXNzYWdlcywgcmVzZXRzIHRoZSBzYXZlZENoYXRJZCwgZ2VuZXJhdGVzIGEgbmV3IGNoYXRJZCxcbiAgICogZ2VuZXJhdGVzIGEgbmV3IGNoYXQgYXVkaXQgZXZlbnQsIGFuZCBoYW5kbGVzIHRoZSBxdWVyeSBtb2RlLlxuICAgKi9cbiAgcHJpdmF0ZSBfdHJpZ2dlclJlbG9hZEFmdGVyUXVlcnlDaGFuZ2UoKSB7XG4gICAgY29uc3Qgc3lzdGVtTXNnID0geyByb2xlOiAnc3lzdGVtJywgY29udGVudDogdGhpcy5jb25maWcuZGVmYXVsdFZhbHVlcy5zeXN0ZW1Qcm9tcHQsIGFkZGl0aW9uYWxQcm9wZXJ0aWVzOiB7IGRpc3BsYXk6IGZhbHNlIH0gfTtcbiAgICAvLyBiYWNrd2FyZCBjb21wYXRpYmlsaXR5IHdpdGggb2xkIGNvbmZpZ3VyYXRpb24gZmlsZXNcbiAgICBjb25zdCB1c2VyUHJvbXB0ID0gdGhpcy5jb25maWcuZGVmYXVsdFZhbHVlcy51c2VyUHJvbXB0LnJlcGxhY2UoL1xce1xceyguKj8pXFx9XFx9L2csICdbWyQxXV0nKTtcbiAgICBjb25zdCB1c2VyTXNnID0geyByb2xlOiAndXNlcicsIGNvbnRlbnQ6IENoYXRTZXJ2aWNlLmZvcm1hdFByb21wdCh0aGlzLnRyYW5zbG9jby50cmFuc2xhdGUodXNlclByb21wdCkgLCB7IHByaW5jaXBhbDogdGhpcy5wcmluY2lwYWxTZXJ2aWNlLnByaW5jaXBhbCB9KSwgYWRkaXRpb25hbFByb3BlcnRpZXM6IHsgZGlzcGxheTogdGhpcy5jb25maWcubW9kZVNldHRpbmdzLmRpc3BsYXlVc2VyUHJvbXB0IH0gfTtcbiAgICB0aGlzLmNoYXRTZXJ2aWNlLnNldFNhdmVkQ2hhdElkKHVuZGVmaW5lZCk7IC8vIFJlc2V0IHRoZSBzYXZlZENoYXRJZFxuICAgIHRoaXMuY2hhdFNlcnZpY2UuZ2VuZXJhdGVDaGF0SWQoKTsgLy8gR2VuZXJhdGUgYSBuZXcgY2hhdElkXG4gICAgdGhpcy5jaGF0U2VydmljZS5nZW5lcmF0ZUF1ZGl0RXZlbnQoJ2FzdC1uZXctY2hhdCcsIHsnY29uZmlndXJhdGlvbic6IEpTT04uc3RyaW5naWZ5KHRoaXMuY2hhdFNlcnZpY2UuYXNzaXN0YW50Q29uZmlnJC52YWx1ZSl9KTsgLy8gR2VuZXJhdGUgYSBuZXcgY2hhdCBhdWRpdCBldmVudFxuICAgIHRoaXMuX2hhbmRsZVF1ZXJ5TW9kZShzeXN0ZW1Nc2csIHVzZXJNc2cpO1xuICB9XG5cblxuICAvKipcbiAgICogQWRkcyBhIHNjcm9sbCBsaXN0ZW5lciB0byB0aGUgbWVzc2FnZSBsaXN0IGVsZW1lbnQuXG4gICAqIFRoZSBsaXN0ZW5lciBpcyB0cmlnZ2VyZWQgd2hlbiBhbnkgb2YgdGhlIGZvbGxvd2luZyBldmVudHMgb2NjdXI6XG4gICAqIC0gTG9hZGluZyBzdGF0ZSBjaGFuZ2VzXG4gICAqIC0gTWVzc2FnZXMgY2hhbmdlXG4gICAqIC0gU3RyZWFtaW5nIHN0YXRlIGNoYW5nZXNcbiAgICogLSBTY3JvbGwgZXZlbnQgb2NjdXJzIG9uIHRoZSBtZXNzYWdlIGxpc3QgZWxlbWVudFxuICAgKlxuICAgKiBXaGVuIHRoZSBsaXN0ZW5lciBpcyB0cmlnZ2VyZWQsIGl0IHVwZGF0ZXMgdGhlIGBpc0F0Qm90dG9tYCBwcm9wZXJ0eS5cbiAgICovXG4gIHByaXZhdGUgX2FkZFNjcm9sbExpc3RlbmVyKCkge1xuICAgIHRoaXMuX3N1Yi5hZGQoXG4gICAgICBtZXJnZSh0aGlzLmxvYWRpbmckLCB0aGlzLm1lc3NhZ2VzJCwgdGhpcy5jaGF0U2VydmljZS5zdHJlYW1pbmckLCBmcm9tRXZlbnQodGhpcy5tZXNzYWdlTGlzdCEubmF0aXZlRWxlbWVudCwgJ3Njcm9sbCcpKS5zdWJzY3JpYmUoKCkgPT4ge1xuICAgICAgICB0aGlzLmlzQXRCb3R0b20gPSB0aGlzLl90b2dnbGVTY3JvbGxCdXR0b25WaXNpYmlsaXR5KCk7XG4gICAgICAgIHRoaXMuY2RyLmRldGVjdENoYW5nZXMoKTtcbiAgICAgIH0pXG4gICAgKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXQgdGhlIG1vZGVsIGRlc2NyaXB0aW9uIGJhc2VkIG9uIHRoZSBkZWZhdWx0VmFsdWVzIHNlcnZpY2VfaWQgYW5kIG1vZGVsX2lkXG4gICAqL1xuICB1cGRhdGVNb2RlbERlc2NyaXB0aW9uKCkge1xuICAgIHRoaXMubW9kZWxEZXNjcmlwdGlvbiA9IHRoaXMuY2hhdFNlcnZpY2UuZ2V0TW9kZWwodGhpcy5jb25maWcuZGVmYXVsdFZhbHVlcy5zZXJ2aWNlX2lkLCB0aGlzLmNvbmZpZy5kZWZhdWx0VmFsdWVzLm1vZGVsX2lkKTtcbiAgICB0aGlzLmNkci5kZXRlY3RDaGFuZ2VzKCk7XG4gIH1cblxuICAvKipcbiAgICogU3VibWl0cyBhIHF1ZXN0aW9uIGZyb20gdGhlIHVzZXIuXG4gICAqIElmIHRoZSB1c2VyIGlzIGVkaXRpbmcgYSBwcmV2aW91cyBtZXNzYWdlLCByZW1vdmVzIGFsbCBzdWJzZXF1ZW50IG1lc3NhZ2VzIGZyb20gdGhlIGNoYXQgaGlzdG9yeS5cbiAgICogVHJpZ2dlcnMgdGhlIGZldGNoIG9mIHRoZSBhbnN3ZXIgZm9yIHRoZSBzdWJtaXR0ZWQgcXVlc3Rpb24gYnkgY2FsbGluZyBfZmV0Y2hBbnN3ZXIoKS5cbiAgICogQ2xlYXJzIHRoZSBpbnB1dCB2YWx1ZSBpbiB0aGUgVUkuXG4gICAqIOKaoO+4jyBJZiB0aGUgY2hhdCBpcyBzdHJlYW1pbmcgb3Igc3RvcHBpbmcgdGhlIGdlbmVyYXRpb24sIHRoZSBvcGVyYXRpb24gaXMgbm90IGFsbG93ZWQuXG4gICAqL1xuICBzdWJtaXRRdWVzdGlvbigpIHtcbiAgICBpZiAoISF0aGlzLmNoYXRTZXJ2aWNlLnN0cmVhbWluZyQudmFsdWUgfHwgISF0aGlzLmNoYXRTZXJ2aWNlLnN0b3BwaW5nR2VuZXJhdGlvbiQudmFsdWUpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgaWYgKHRoaXMucXVlc3Rpb24udHJpbSgpICYmIHRoaXMubWVzc2FnZXMkLnZhbHVlICYmIHRoaXMuY2hhdFNlcnZpY2UuY2hhdEhpc3RvcnkpIHtcbiAgICAgIC8vIFdoZW4gdGhlIHVzZXIgc3VibWl0cyBhIHF1ZXN0aW9uLCBpZiB0aGUgdXNlciBpcyBlZGl0aW5nIGEgcHJldmlvdXMgbWVzc2FnZSwgcmVtb3ZlIGFsbCBzdWJzZXF1ZW50IG1lc3NhZ2VzIGZyb20gdGhlIGNoYXQgaGlzdG9yeVxuICAgICAgaWYgKHRoaXMubWVzc2FnZVRvRWRpdCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIC8vIFVwZGF0ZSB0aGUgbWVzc2FnZXMgaW4gdGhlIFVJXG4gICAgICAgIHRoaXMubWVzc2FnZXMkLm5leHQodGhpcy5tZXNzYWdlcyQudmFsdWUuc2xpY2UoMCwgdGhpcy5tZXNzYWdlVG9FZGl0KSk7XG4gICAgICAgIC8vIFVwZGF0ZSB0aGUgcmF3IG1lc3NhZ2VzIGluIHRoZSBjaGF0IGhpc3Rvcnkgd2hpY2ggaXMgdGhlIGNsZWFuIHZlcnNpb24gdXNlZCB0byBtYWtlIHRoZSBuZXh0IHJlcXVlc3RcbiAgICAgICAgdGhpcy5jaGF0U2VydmljZS5jaGF0SGlzdG9yeSA9IHRoaXMuY2hhdFNlcnZpY2UuY2hhdEhpc3Rvcnkuc2xpY2UoMCwgdGhpcy5yZW1hcHBlZE1lc3NhZ2VUb0VkaXQpO1xuICAgICAgICB0aGlzLm1lc3NhZ2VUb0VkaXQgPSB1bmRlZmluZWQ7XG4gICAgICAgIHRoaXMucmVtYXBwZWRNZXNzYWdlVG9FZGl0ID0gdW5kZWZpbmVkO1xuICAgICAgfVxuICAgICAgLy8gUmVtb3ZlIHRoZSBzZWFyY2ggd2FybmluZyBtZXNzYWdlIGlmIGV4aXN0c1xuICAgICAgaWYgKHRoaXMuY2hhdFNlcnZpY2UuY2hhdEhpc3RvcnkuYXQoLTEpPy5yb2xlID09PSAnc2VhcmNoLXdhcm5pbmcnKSB7XG4gICAgICAgIHRoaXMuY2hhdFNlcnZpY2UuY2hhdEhpc3RvcnkucG9wKCk7XG4gICAgICB9XG4gICAgICAvLyBGZXRjaCB0aGUgYW5zd2VyXG4gICAgICB0aGlzLl9mZXRjaEFuc3dlcih0aGlzLnF1ZXN0aW9uLnRyaW0oKSwgdGhpcy5jaGF0U2VydmljZS5jaGF0SGlzdG9yeSk7XG4gICAgICAvLyBDbGVhciB0aGUgaW5wdXQgdmFsdWUgaW4gdGhlIFVJXG4gICAgICB0aGlzLnF1ZXN0aW9uSW5wdXQhLm5hdGl2ZUVsZW1lbnQudmFsdWUgPSAnJztcbiAgICAgIHRoaXMucXVlc3Rpb25JbnB1dCEubmF0aXZlRWxlbWVudC5zdHlsZS5oZWlnaHQgPSBgYXV0b2A7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFRyaWdnZXJzIHRoZSBmZXRjaCBvZiB0aGUgYW5zd2VyIGZvciB0aGUgZ2l2ZW4gcXVlc3Rpb24gYW5kIHVwZGF0ZXMgdGhlIGNvbnZlcnNhdGlvbi5cbiAgICogR2VuZXJhdGVzIGFuIGF1ZGl0IGV2ZW50IGZvciB0aGUgdXNlciBpbnB1dC5cbiAgICpcbiAgICogQHBhcmFtIHF1ZXN0aW9uIC0gVGhlIHF1ZXN0aW9uIGFza2VkIGJ5IHRoZSB1c2VyLlxuICAgKiBAcGFyYW0gY29udmVyc2F0aW9uIC0gVGhlIGN1cnJlbnQgY29udmVyc2F0aW9uIG1lc3NhZ2VzLlxuICAgKi9cbiAgcHJpdmF0ZSBfZmV0Y2hBbnN3ZXIocXVlc3Rpb246IHN0cmluZywgY29udmVyc2F0aW9uOiBDaGF0TWVzc2FnZVtdKSB7XG4gICAgLy8gbWVyZ2UgYWRkaXRpb25hbFdvcmtmbG93UHJvcGVydGllcyBmcm9tIHRoZSBjaGF0IGNvbXBvbmVudCBhbmQgdGhlIGN1c3RvbWl6YXRpb24gSlNPTlxuICAgIGNvbnN0IGFkZGl0aW9uYWxXb3JrZmxvd1Byb3BlcnRpZXMgPSB7IC4uLnRoaXMuY29uZmlnLmFkZGl0aW9uYWxXb3JrZmxvd1Byb3BlcnRpZXMsIC4uLnRoaXMuYWRkaXRpb25hbFdvcmtmbG93UHJvcGVydGllcyB9O1xuICAgIGNvbnN0IHVzZXJNc2cgPSB7IHJvbGU6ICd1c2VyJywgY29udGVudDogcXVlc3Rpb24sIGFkZGl0aW9uYWxQcm9wZXJ0aWVzOiB7IGRpc3BsYXk6IHRydWUsIGlzVXNlcklucHV0OiB0cnVlLCBhZGRpdGlvbmFsV29ya2Zsb3dQcm9wZXJ0aWVzIH0gfTtcbiAgICBjb25zdCBtZXNzYWdlcyA9IFsuLi5jb252ZXJzYXRpb24sIHVzZXJNc2ddO1xuICAgIHRoaXMubWVzc2FnZXMkLm5leHQobWVzc2FnZXMpO1xuICAgIHRoaXMuZmV0Y2gobWVzc2FnZXMpO1xuICAgIHRoaXMuY2hhdFNlcnZpY2UuZ2VuZXJhdGVBdWRpdEV2ZW50KCdhc3QtbWVzc2FnZScsIHsgLi4udGhpcy5fZGVmaW5lTWVzc2FnZUF1ZGl0RGV0YWlscyh1c2VyTXNnLCBtZXNzYWdlcy5sZW5ndGggLSAxKSwgJ3F1ZXJ5JzogSlNPTi5zdHJpbmdpZnkodGhpcy5xdWVyeSksICdpcy11c2VyLWlucHV0JzogdHJ1ZSwgJ2VuYWJsZWQtZnVuY3Rpb25zJzogdGhpcy5jb25maWcuZGVmYXVsdFZhbHVlcy5mdW5jdGlvbnM/LmZpbHRlcihmdW5jID0+IGZ1bmMuZW5hYmxlZCkubWFwKGZ1bmMgPT4gZnVuYy5uYW1lKSwgJ2FkZGl0aW9uYWwtd29ya2Zsb3ctcHJvcGVydGllcyc6IEpTT04uc3RyaW5naWZ5KGFkZGl0aW9uYWxXb3JrZmxvd1Byb3BlcnRpZXMpIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIERlcGVuZGluZyBvbiB0aGUgY29ubmVjdGlvbidzIHN0YXRlIDpcbiAgICogIC0gSWYgY29ubmVjdGVkID0+IGdpdmVuIGEgbGlzdCBvZiBtZXNzYWdlcywgdGhlIGNoYXQgZW5kcG9pbnQgaXMgaW52b2tlZCBmb3IgYSBjb250aW51YXRpb24gYW5kIHVwZGF0ZXMgdGhlIGxpc3Qgb2YgbWVzc2FnZXMgYWNjb3JkaW5nbHkuXG4gICAqICAtIElmIGFueSBvdGhlciBzdGF0ZSA9PiBhIGNvbm5lY3Rpb24gZXJyb3IgbWVzc2FnZSBpcyBkaXNwbGF5ZWQgaW4gdGhlIGNoYXQuXG4gICAqIOKaoO+4jyBJZiB0aGUgYXNzaXN0YW50IGlzIHN0cmVhbWluZyBvciBzdG9wcGluZyB0aGUgZ2VuZXJhdGlvbiwgdGhlIG9wZXJhdGlvbiBpcyBub3QgYWxsb3dlZC5cbiAgICogQHBhcmFtIG1lc3NhZ2VzIFRoZSBsaXN0IG9mIG1lc3NhZ2VzIHRvIGludm9rZSB0aGUgY2hhdCBlbmRwb2ludCB3aXRoXG4gICAqL1xuICBwdWJsaWMgZmV0Y2gobWVzc2FnZXM6IENoYXRNZXNzYWdlW10pIHtcbiAgICBpZiAoISF0aGlzLmNoYXRTZXJ2aWNlLnN0cmVhbWluZyQudmFsdWUgfHwgISF0aGlzLmNoYXRTZXJ2aWNlLnN0b3BwaW5nR2VuZXJhdGlvbiQudmFsdWUpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgdGhpcy5fdXBkYXRlQ29ubmVjdGlvblN0YXR1cygpO1xuICAgIHRoaXMuY2RyLmRldGVjdENoYW5nZXMoKTtcblxuICAgIGlmICh0aGlzLmlzQ29ubmVjdGVkKSB7XG4gICAgICB0aGlzLmxvYWRpbmckLm5leHQodHJ1ZSk7XG4gICAgICB0aGlzLl9kYXRhU3Vic2NyaXB0aW9uPy51bnN1YnNjcmliZSgpO1xuICAgICAgdGhpcy5fZGF0YVN1YnNjcmlwdGlvbiA9IHRoaXMuY2hhdFNlcnZpY2UuZmV0Y2gobWVzc2FnZXMsIHRoaXMucXVlcnkpXG4gICAgICAgIC5zdWJzY3JpYmUoe1xuICAgICAgICAgIG5leHQ6IHJlcyA9PiB7XG4gICAgICAgICAgICB0aGlzLmxhc3RGZXRjaER1cmF0aW9uID0gcmVzLmV4ZWN1dGlvblRpbWVNaWxsaXNlY29uZHM7XG4gICAgICAgICAgICB0aGlzLnVwZGF0ZURhdGEocmVzLmhpc3RvcnkpO1xuICAgICAgICAgIH0sXG4gICAgICAgICAgZXJyb3I6ICgpID0+IHtcbiAgICAgICAgICAgIHRoaXMuX3VwZGF0ZUNvbm5lY3Rpb25TdGF0dXMoKTtcbiAgICAgICAgICAgIGlmICghdGhpcy5pc0Nvbm5lY3RlZCkge1xuICAgICAgICAgICAgICBjb25zdCBtZXNzYWdlID0ge1xuICAgICAgICAgICAgICAgIHJvbGU6ICdjb25uZWN0aW9uLWVycm9yJyxcbiAgICAgICAgICAgICAgICBjb250ZW50OiAoeyB0eXBlOiBcInRleHRcIiwgdGV4dDogdGhpcy50cmFuc2xvY28udHJhbnNsYXRlKHRoaXMuY29uZmlnLmNvbm5lY3Rpb25TZXR0aW5ncy5jb25uZWN0aW9uRXJyb3JNZXNzYWdlKSB9IGFzIFRleHRNZXNzYWdlQ29udGVudCksXG4gICAgICAgICAgICAgICAgYWRkaXRpb25hbFByb3BlcnRpZXM6IHsgZGlzcGxheTogdHJ1ZSB9XG4gICAgICAgICAgICAgIH0gYXMgYW55IGFzIENoYXRNZXNzYWdlO1xuICAgICAgICAgICAgICB0aGlzLm1lc3NhZ2VzJC5uZXh0KFsuLi5tZXNzYWdlcywgbWVzc2FnZV0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy50ZXJtaW5hdGVGZXRjaCgpO1xuICAgICAgICAgIH0sXG4gICAgICAgICAgY29tcGxldGU6ICgpID0+IHtcbiAgICAgICAgICAgIC8vIFJlbW92ZSB0aGUgbGFzdCBtZXNzYWdlIGlmIGl0J3MgYW4gZW1wdHkgbWVzc2FnZVxuICAgICAgICAgICAgLy8gVGhpcyBpcyBkdWUgdG8gdGhlIG1hbm5lciBpbiB3aGljaCB0aGUgY2hhdCBzZXJ2aWNlIGhhbmRsZXMgY29uc2VjdXRpdmUgbWVzc2FnZXNcbiAgICAgICAgICAgIGNvbnN0IGxhc3RNZXNzYWdlID0gdGhpcy5tZXNzYWdlcyQudmFsdWU/LmF0KC0xKTtcbiAgICAgICAgICAgIGlmICh0aGlzLmlzRW1wdHlBc3Npc3RhbnRNZXNzYWdlKGxhc3RNZXNzYWdlKSkge1xuICAgICAgICAgICAgICB0aGlzLm1lc3NhZ2VzJC5uZXh0KHRoaXMubWVzc2FnZXMkLnZhbHVlPy5zbGljZSgwLCAtMSkpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy50ZXJtaW5hdGVGZXRjaCgpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGNvbnN0IG1lc3NhZ2UgPSB7IHJvbGU6ICdjb25uZWN0aW9uLWVycm9yJywgY29udGVudDogdGhpcy50cmFuc2xvY28udHJhbnNsYXRlKHRoaXMuY29uZmlnLmNvbm5lY3Rpb25TZXR0aW5ncy5jb25uZWN0aW9uRXJyb3JNZXNzYWdlKSwgYWRkaXRpb25hbFByb3BlcnRpZXM6IHsgZGlzcGxheTogdHJ1ZSB9IH07XG4gICAgICB0aGlzLm1lc3NhZ2VzJC5uZXh0KFsuLi5tZXNzYWdlcywgbWVzc2FnZV0pO1xuICAgIH1cblxuICAgIGlmICh0aGlzLmF1dG9tYXRpY1Njcm9sbFRvTGFzdFJlc3BvbnNlKSB7XG4gICAgICB0aGlzLnNjcm9sbERvd24oKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogUmV0cnkgdG8gZmV0Y2ggdGhlIG1lc3NhZ2VzIGlmIHRoZSBjb25uZWN0aW9uIGlzc3Vlcy5cbiAgICogIC0gSWYgcmVjb25uZWN0aW5nID0+IGtlZXAgZGlzcGxheSB0aGUgY29ubmVjdGlvbiBlcnJvciBtZXNzYWdlIGV2ZW4gd2hlbiBjbGlja2luZyBvbiB0aGUgXCJyZXRyeVwiIGJ1dHRvbiBhbmQgaW5jcmVhc2luZyB0aGUgbnVtYmVyIG9mIHJldHJpYWwgYXR0ZW1wdHMsIHVudGlsIHRoZSBjb25uZWN0aW9uIGlzIHJlLWVzdGFibGlzaGVkXG4gICAqICAtIElmIGRpc2Nvbm5lY3RlZCA9PiBPbiBjbGljayBvbiB0aGUgXCJyZXRyeVwiIGJ1dHRvbiwgc3RhcnQgdGhlIGNvbm5lY3Rpb24gcHJvY2VzcyB3aGlsZSBkaXNwbGF5aW5nIHRoZSBjb25uZWN0aW9uIGVycm9yIG1lc3NhZ2UgOlxuICAgKiAgICAgICogSWYgc3VjY2Vzc2Z1bCA9PiBnaXZlbiBhIGxpc3Qgb2YgbWVzc2FnZXMsIHRoZSBjaGF0IGVuZHBvaW50IGlzIGludm9rZWQgZm9yIGEgY29udGludWF0aW9uIGFuZCB1cGRhdGVzIHRoZSBsaXN0IG9mIG1lc3NhZ2VzIGFjY29yZGluZ2x5LlxuICAgKiAgICAgICogSWYgZmFpbGVkID0+IGluY3JlYXNlIHRoZSBudW1iZXIgb2YgcmV0cmlhbCBhdHRlbXB0c1xuICAgKi9cbiAgcmV0cnlGZXRjaCgpIHtcbiAgICBpZiAodGhpcy5jaGF0U2VydmljZSBpbnN0YW5jZW9mIFdlYlNvY2tldENoYXRTZXJ2aWNlKSB7XG4gICAgICAvLyBBIG9uZS10aW1lIGxpc3RlbmVyIGZvciByZWNvbm5lY3RlZCBldmVudFxuICAgICAgY29uc3Qgb25SZWNvbm5lY3RlZEhhbmRsZXIgPSAoKSA9PiB7XG4gICAgICAgIC8vIEdldCB0aGUgbWVzc2FnZXMgd2l0aG91dCB0aGUgbGFzdCBvbmUgKHRoZSBjb25uZWN0aW9uIGVycm9yIG1lc3NhZ2UpXG4gICAgICAgIGNvbnN0IG1lc3NhZ2VzID0gdGhpcy5tZXNzYWdlcyQudmFsdWUhLnNsaWNlKDAsIC0xKTtcbiAgICAgICAgLy8gRmluZCB0aGUgbGFzdCBcInVzZXJcIiBtZXNzYWdlIGluIHRoZSBtZXNzYWdlcyBsaXN0XG4gICAgICAgIGxldCBpbmRleCA9IG1lc3NhZ2VzLmxlbmd0aCAtIDE7XG4gICAgICAgIHdoaWxlIChpbmRleCA+PSAwICYmIG1lc3NhZ2VzW2luZGV4XS5yb2xlICE9PSAndXNlcicpIHtcbiAgICAgICAgICBpbmRleC0tO1xuICAgICAgICB9XG4gICAgICAgIC8vIElmIGEgdXNlciBtZXNzYWdlIGlzIGZvdW5kIChhbmQgaXQgc2hvdWxkIGFsd2F5cyBiZSB0aGUgY2FzZSksIHJlbW92ZSBhbGwgc3Vic2VxdWVudCBtZXNzYWdlcyBmcm9tIHRoZSBjaGF0IGhpc3RvcnlcbiAgICAgICAgLy8gVXBkYXRlIHRoZSBtZXNzYWdlcyBpbiB0aGUgVUlcbiAgICAgICAgLy8gYW5kIGZldGNoIHRoZSBhbnN3ZXIgZnJvbSB0aGUgYXNzaXN0YW50XG4gICAgICAgIGlmIChpbmRleCA+PSAwKSB7XG4gICAgICAgICAgdGhpcy5tZXNzYWdlcyQubmV4dCh0aGlzLm1lc3NhZ2VzJC52YWx1ZSEuc2xpY2UoMCwgaW5kZXggKyAxKSk7XG4gICAgICAgICAgY29uc3QgcmVtYXBwZWRJbmRleCA9IHRoaXMuX3JlbWFwSW5kZXhJbkNoYXRIaXN0b3J5KGluZGV4KTtcbiAgICAgICAgICB0aGlzLmNoYXRTZXJ2aWNlLmNoYXRIaXN0b3J5ID0gdGhpcy5jaGF0U2VydmljZS5jaGF0SGlzdG9yeSEuc2xpY2UoMCwgcmVtYXBwZWRJbmRleCArIDEpO1xuICAgICAgICAgIHRoaXMuZmV0Y2godGhpcy5jaGF0U2VydmljZS5jaGF0SGlzdG9yeSk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5yZXRyaWFsQXR0ZW1wdHMgPSB1bmRlZmluZWQ7IC8vIFJlc2V0IHRoZSBudW1iZXIgb2YgcmV0cmlhbCBhdHRlbXB0c1xuICAgICAgICAvKipcbiAgICAgICAgICogVG8gcmVtb3ZlIHRoZSBoYW5kbGVyIGZvciBvbnJlY29ubmVjdGVkKCkgYWZ0ZXIgaXQncyBiZWVuIHJlZ2lzdGVyZWQsY2Fubm90IGRpcmVjdGx5IHVzZSBvZmYoKSBsaWtlIHlvdSB3b3VsZCBmb3Igbm9ybWFsIGV2ZW50cyByZWdpc3RlcmVkIHdpdGggY29ubmVjdGlvbi5vbigpLlxuICAgICAgICAgKiBJbnN0ZWFkLCB5b3UgbmVlZCB0byBleHBsaWNpdGx5IHJlbW92ZSBvciByZXNldCB0aGUgaGFuZGxlciBieSBhc3NpZ25pbmcgaXQgdG8gbnVsbCBvciBhbiBlbXB0eSBmdW5jdGlvblxuICAgICAgICAgKi9cbiAgICAgICAgKHRoaXMuY2hhdFNlcnZpY2UgYXMgV2ViU29ja2V0Q2hhdFNlcnZpY2UpLmNvbm5lY3Rpb24hLm9ucmVjb25uZWN0ZWQoKCkgPT4ge30pO1xuICAgICAgICAvLyBSZXNldCB0aGUgZmxhZyB0byBlbnN1cmUgdGhlIGhhbmRsZXIgaXMgcmVnaXN0ZXJlZCBhZ2FpbiB3aGVuIG5lZWRlZFxuICAgICAgICB0aGlzLl9pc1JlY29ubmVjdGVkTGlzdGVuZXJSZWdpc3RlcmVkID0gZmFsc2U7XG4gICAgICB9XG4gICAgICAvLyBEZXBlbmRpbmcgb24gdGhlIGNvbm5lY3Rpb24ncyBzdGF0ZSwgdGFrZSB0aGUgYXBwcm9wcmlhdGUgYWN0aW9uXG4gICAgICBzd2l0Y2ggKHRoaXMuY2hhdFNlcnZpY2UuY29ubmVjdGlvbiEuc3RhdGUpIHtcbiAgICAgICAgY2FzZSBIdWJDb25uZWN0aW9uU3RhdGUuQ29ubmVjdGVkOlxuICAgICAgICAgIC8vIElmIHRoZSBjb25uZWN0aW9uIGlzIHJlLWVzdGFibGlzaGVkIGluIHRoZSBtZWFudGltZSwgZmV0Y2ggdGhlIG1lc3NhZ2VzXG4gICAgICAgICAgb25SZWNvbm5lY3RlZEhhbmRsZXIoKTtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSBIdWJDb25uZWN0aW9uU3RhdGUuUmVjb25uZWN0aW5nOlxuICAgICAgICAgIC8vIEF0dGFjaCB0aGUgcmVjb25uZWN0ZWQgbGlzdGVuZXIgaWYgbm90IGFscmVhZHkgcmVnaXN0ZXJlZFxuICAgICAgICAgIGlmICghdGhpcy5faXNSZWNvbm5lY3RlZExpc3RlbmVyUmVnaXN0ZXJlZCkge1xuICAgICAgICAgICAgdGhpcy5jaGF0U2VydmljZS5jb25uZWN0aW9uIS5vbnJlY29ubmVjdGVkKG9uUmVjb25uZWN0ZWRIYW5kbGVyKTtcbiAgICAgICAgICAgIHRoaXMuX2lzUmVjb25uZWN0ZWRMaXN0ZW5lclJlZ2lzdGVyZWQgPSB0cnVlO1xuICAgICAgICAgIH1cbiAgICAgICAgICAvLyBJbmNyZWFzZSB0aGUgbnVtYmVyIG9mIHJldHJpYWwgYXR0ZW1wdHNcbiAgICAgICAgICB0aGlzLnJldHJpYWxBdHRlbXB0cyA9IHRoaXMucmV0cmlhbEF0dGVtcHRzID8gdGhpcy5yZXRyaWFsQXR0ZW1wdHMgKyAxIDogMTtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSBIdWJDb25uZWN0aW9uU3RhdGUuRGlzY29ubmVjdGVkOlxuICAgICAgICAgIC8vIFN0YXJ0IHRoZSBuZXcgY29ubmVjdGlvblxuICAgICAgICAgIHRoaXMuY2hhdFNlcnZpY2Uuc3RhcnRDb25uZWN0aW9uKClcbiAgICAgICAgICAgIC50aGVuKCgpID0+IG9uUmVjb25uZWN0ZWRIYW5kbGVyKCkpXG4gICAgICAgICAgICAuY2F0Y2goKCkgPT4geyAvLyBJZiB0aGUgY29ubmVjdGlvbiBmYWlscywgaW5jcmVhc2UgdGhlIG51bWJlciBvZiByZXRyaWFsIGF0dGVtcHRzXG4gICAgICAgICAgICAgIHRoaXMucmV0cmlhbEF0dGVtcHRzID0gdGhpcy5yZXRyaWFsQXR0ZW1wdHMgPyB0aGlzLnJldHJpYWxBdHRlbXB0cyArIDEgOiAxO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIENoZWNrIGlmIHRoZSBzaWduYWxSIGNvbm5lY3Rpb24gaXMgY29ubmVjdGVkLlxuICAgKiBGb3IgdGhlIFJFU1QgcHJvdG9jb2wsIHRoZSBjb25uZWN0aW9uIGlzIGFsd2F5cyBjb25zaWRlcmVkIGNvbm5lY3RlZCAoZm9yIHRoZSBtb21lbnQpLlxuICAgKi9cbiAgcHJpdmF0ZSBfdXBkYXRlQ29ubmVjdGlvblN0YXR1cygpIHtcbiAgICB0aGlzLmlzQ29ubmVjdGVkID0gKHRoaXMuY2hhdFNlcnZpY2UgaW5zdGFuY2VvZiBXZWJTb2NrZXRDaGF0U2VydmljZSkgPyB0aGlzLmNoYXRTZXJ2aWNlLmNvbm5lY3Rpb24hLnN0YXRlID09PSBIdWJDb25uZWN0aW9uU3RhdGUuQ29ubmVjdGVkIDogdHJ1ZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBVcGRhdGUgdGhlIFVJIHdpdGggdGhlIG5ldyBtZXNzYWdlc1xuICAgKiBAcGFyYW0gbWVzc2FnZXNcbiAgICovXG4gIHVwZGF0ZURhdGEobWVzc2FnZXM6IENoYXRNZXNzYWdlW10pIHtcbiAgICB0aGlzLm1lc3NhZ2VzJC5uZXh0KG1lc3NhZ2VzKTtcbiAgICB0aGlzLmRhdGEuZW1pdChtZXNzYWdlcyk7XG4gICAgdGhpcy5sb2FkaW5nJC5uZXh0KGZhbHNlKTtcbiAgICB0aGlzLnF1ZXN0aW9uID0gJyc7XG4gICAgaWYgKHRoaXMuYXV0b21hdGljU2Nyb2xsVG9MYXN0UmVzcG9uc2UpIHtcbiAgICAgIHRoaXMuc2Nyb2xsRG93bigpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBAcmV0dXJucyB0cnVlIGlmIHRoZSBjaGF0IGRpc2N1c3Npb24gaXMgc2Nyb2xsZWQgZG93biB0byB0aGUgYm90dG9tLCBmYWxzZSBvdGhlcndpc2VcbiAgICovXG4gIHByaXZhdGUgX3RvZ2dsZVNjcm9sbEJ1dHRvblZpc2liaWxpdHkoKTogYm9vbGVhbiB7XG4gICAgaWYgKHRoaXMubWVzc2FnZUxpc3Q/Lm5hdGl2ZUVsZW1lbnQpIHtcbiAgICAgIHJldHVybiBNYXRoLnJvdW5kKHRoaXMubWVzc2FnZUxpc3Q/Lm5hdGl2ZUVsZW1lbnQuc2Nyb2xsSGVpZ2h0IC0gdGhpcy5tZXNzYWdlTGlzdD8ubmF0aXZlRWxlbWVudC5zY3JvbGxUb3AgLSAxKSA8PSB0aGlzLm1lc3NhZ2VMaXN0Py5uYXRpdmVFbGVtZW50LmNsaWVudEhlaWdodDtcbiAgICB9XG4gICAgcmV0dXJuIHRydWU7XG4gIH1cblxuICAvKipcbiAgICogU2Nyb2xsIGRvd24gdG8gdGhlIGJvdHRvbSBvZiB0aGUgY2hhdCBkaXNjdXNzaW9uXG4gICAqL1xuICBzY3JvbGxEb3duKCkge1xuICAgIHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgaWYgKHRoaXMubWVzc2FnZUxpc3Q/Lm5hdGl2ZUVsZW1lbnQpIHtcbiAgICAgICAgdGhpcy5tZXNzYWdlTGlzdC5uYXRpdmVFbGVtZW50LnNjcm9sbFRvcCA9IHRoaXMubWVzc2FnZUxpc3QubmF0aXZlRWxlbWVudC5zY3JvbGxIZWlnaHQ7XG4gICAgICAgIHRoaXMuY2RyLmRldGVjdENoYW5nZXMoKTtcbiAgICAgIH1cbiAgICB9LCAxMCk7XG4gIH1cblxuICAvKipcbiAgICogU3RhcnQgYSBuZXcgY2hhdCB3aXRoIHRoZSBkZWZhdWx0VmFsdWVzIHNldHRpbmdzLlxuICAgKiBUaGUgc2F2ZWRDaGF0SWQgaW4gdGhlIGNoYXQgc2VydmljZSB3aWxsIGJlIHJlc2V0LCBzbyB0aGF0IHRoZSB1cGNvbWluZyBzYXZlZCBjaGF0IG9wZXJhdGlvbnMgd2lsbCBiZSBwZXJmb3JtZWQgb24gdGhlIGZyZXNoIG5ldyBjaGF0LlxuICAgKiBJZiB0aGUgc2F2ZWRDaGF0IGZlYXR1cmUgaXMgZW5hYmxlZCwgdGhlIGxpc3Qgb2Ygc2F2ZWQgY2hhdHMgd2lsbCBiZSByZWZyZXNoZWQuXG4gICAqIOKaoO+4jyBJZiB0aGUgYXNzaXN0YW50IGlzIHN0cmVhbWluZyBvciBzdG9wcGluZyB0aGUgZ2VuZXJhdGlvbiwgdGhlIG9wZXJhdGlvbiBpcyBub3QgYWxsb3dlZC5cbiAgICovXG4gIG5ld0NoYXQoKSB7XG4gICAgaWYgKCEhdGhpcy5jaGF0U2VydmljZS5zdHJlYW1pbmckLnZhbHVlIHx8ICEhdGhpcy5jaGF0U2VydmljZS5zdG9wcGluZ0dlbmVyYXRpb24kLnZhbHVlKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIHRoaXMuY2hhdFNlcnZpY2Uuc2V0U2F2ZWRDaGF0SWQodW5kZWZpbmVkKTsgLy8gUmVzZXQgdGhlIHNhdmVkQ2hhdElkXG4gICAgdGhpcy5jaGF0U2VydmljZS5nZW5lcmF0ZUNoYXRJZCgpOyAvLyBHZW5lcmF0ZSBhIG5ldyBjaGF0SWRcbiAgICB0aGlzLmNoYXRTZXJ2aWNlLmxpc3RTYXZlZENoYXQoKTsgLy8gUmVmcmVzaCB0aGUgbGlzdCBvZiBzYXZlZCBjaGF0c1xuICAgIHRoaXMuY2hhdFNlcnZpY2UuZ2VuZXJhdGVBdWRpdEV2ZW50KCdhc3QtbmV3LWNoYXQnLCB7J2NvbmZpZ3VyYXRpb24nOiBKU09OLnN0cmluZ2lmeSh0aGlzLmNoYXRTZXJ2aWNlLmFzc2lzdGFudENvbmZpZyQudmFsdWUpfSk7IC8vIEdlbmVyYXRlIGEgbmV3IGNoYXQgYXVkaXQgZXZlbnRcbiAgICB0aGlzLmxvYWREZWZhdWx0Q2hhdCgpOyAvLyBTdGFydCBhIG5ldyBjaGF0XG4gIH1cblxuICAvKipcbiAgICogQXR0YWNoZXMgdGhlIHNwZWNpZmllZCBkb2N1bWVudCBJRHMgdG8gdGhlIGFzc2lzdGFudC5cbiAgICogSWYgbm8gZG9jdW1lbnQgSURzIGFyZSBwcm92aWRlZCwgdGhlIG9wZXJhdGlvbiBpcyBub3QgYWxsb3dlZC5cbiAgICogSWYgdGhlIGFjdGlvbiBmb3IgYXR0YWNoaW5nIGEgZG9jdW1lbnQgaXMgbm90IGRlZmluZWQgYXQgdGhlIGFwcGxpY2F0aW9uIGN1c3RvbWl6YXRpb24gbGV2ZWwsIGFuIGVycm9yIGlzIGxvZ2dlZC5cbiAgICog4pqg77iPIElmIHRoZSBhc3Npc3RhbnQgaXMgc3RyZWFtaW5nIG9yIHN0b3BwaW5nIHRoZSBnZW5lcmF0aW9uLCB0aGUgb3BlcmF0aW9uIGlzIG5vdCBhbGxvd2VkLlxuICAgKiBAcGFyYW0gaWRzIC0gQW4gYXJyYXkgb2YgZG9jdW1lbnQgSURzIHRvIGF0dGFjaC5cbiAgICovXG4gIGF0dGFjaFRvQ2hhdChpZHM6IHN0cmluZ1tdKSB7XG4gICAgaWYgKCEhdGhpcy5jaGF0U2VydmljZS5zdHJlYW1pbmckLnZhbHVlIHx8ICEhdGhpcy5jaGF0U2VydmljZS5zdG9wcGluZ0dlbmVyYXRpb24kLnZhbHVlKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGlmICghaWRzIHx8IGlkcz8ubGVuZ3RoIDwgMSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBjb25zdCBhdHRhY2hEb2NBY3Rpb24gPSB0aGlzLmNvbmZpZy5tb2RlU2V0dGluZ3MuYWN0aW9ucz8uW1wiYXR0YWNoRG9jQWN0aW9uXCJdO1xuICAgIGlmICghYXR0YWNoRG9jQWN0aW9uKSB7XG4gICAgICBjb25zb2xlLmVycm9yKGBObyBhY3Rpb24gaXMgZGVmaW5lZCBmb3IgYXR0YWNoaW5nIGEgZG9jdW1lbnQgdG8gdGhlIGFzc2lzdGFudCBcIiR7dGhpcy5pbnN0YW5jZUlkfVwiYCk7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGNvbnN0IHVzZXJNc2cgPSB7IHJvbGU6ICd1c2VyJywgY29udGVudDogJycsIGFkZGl0aW9uYWxQcm9wZXJ0aWVzOiB7ZGlzcGxheTogZmFsc2UsIGlzVXNlcklucHV0OiBmYWxzZSwgdHlwZTogXCJBY3Rpb25cIiwgZm9yY2VkV29ya2Zsb3c6IGF0dGFjaERvY0FjdGlvbi5mb3JjZWRXb3JrZmxvdywgZm9yY2VkV29ya2Zsb3dQcm9wZXJ0aWVzOiB7Li4uKGF0dGFjaERvY0FjdGlvbi5mb3JjZWRXb3JrZmxvd1Byb3BlcnRpZXMgfHwge30pLCBpZHN9LCBhZGRpdGlvbmFsV29ya2Zsb3dQcm9wZXJ0aWVzOiB0aGlzLmNvbmZpZy5hZGRpdGlvbmFsV29ya2Zsb3dQcm9wZXJ0aWVzfX07XG4gICAgLy8gUmVtb3ZlIHRoZSBzZWFyY2ggd2FybmluZyBtZXNzYWdlIGlmIGV4aXN0c1xuICAgIGlmICh0aGlzLmNoYXRTZXJ2aWNlLmNoYXRIaXN0b3J5IS5hdCgtMSk/LnJvbGUgPT09ICdzZWFyY2gtd2FybmluZycpIHtcbiAgICAgIHRoaXMuY2hhdFNlcnZpY2UuY2hhdEhpc3RvcnkhLnBvcCgpO1xuICAgIH1cbiAgICBjb25zdCBtZXNzYWdlcyA9IFsuLi50aGlzLmNoYXRTZXJ2aWNlLmNoYXRIaXN0b3J5ISwgdXNlck1zZ107XG4gICAgdGhpcy5tZXNzYWdlcyQubmV4dChtZXNzYWdlcyk7XG4gICAgdGhpcy5mZXRjaChtZXNzYWdlcyk7XG4gICAgdGhpcy5jaGF0U2VydmljZS5nZW5lcmF0ZUF1ZGl0RXZlbnQoJ2FzdC1hY3Rpb24ucmVxdWVzdGVkJywge1xuICAgICAgJ2RldGFpbCc6ICdhdHRhY2hEb2NBY3Rpb24nLFxuICAgICAgJ2ZvcmNlZC13b3JrZmxvdyc6ICdTaW5lcXVhQWRkU2VsZWN0ZWREb2N1bWVudHNXb3JrZmxvdycsXG4gICAgICAnZm9yY2VkLXdvcmtmbG93LXByb3BlcnRpZXMnOiBKU09OLnN0cmluZ2lmeShpZHMpLFxuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIFN0YXJ0IHRoZSBkZWZhdWx0IGNoYXQgd2l0aCB0aGUgZGVmYXVsdFZhbHVlcyBzZXR0aW5nc1xuICAgKiBJZiB0aGUgY2hhdCBpcyBtZWFudCB0byBiZSBpbml0aWFsaXplZCB3aXRoIGV2ZW50ID09PSBcIlF1ZXJ5XCIsIHRoZSBjb3JyZXNwb25kaW5nIHVzZXIgcXVlcnkgbWVzc2FnZSB3aWxsIGJlIGFkZGVkIHRvIHRoZSBjaGF0IGhpc3RvcnlcbiAgICovXG4gIGxvYWREZWZhdWx0Q2hhdCgpIHtcbiAgICAvLyBEZWZpbmUgdGhlIGRlZmF1bHQgc3lzdGVtIHByb21wdCBhbmQgdXNlciBwcm9tcHQgbWVzc2FnZXNcbiAgICBjb25zdCBzeXN0ZW1Nc2cgPSB7IHJvbGU6ICdzeXN0ZW0nLCBjb250ZW50OiB0aGlzLmNvbmZpZy5kZWZhdWx0VmFsdWVzLnN5c3RlbVByb21wdCwgYWRkaXRpb25hbFByb3BlcnRpZXM6IHsgZGlzcGxheTogZmFsc2UgfSB9O1xuICAgIC8vIGJhY2t3YXJkIGNvbXBhdGliaWxpdHkgd2l0aCBvbGQgY29uZmlndXJhdGlvbiBmaWxlc1xuICAgIGNvbnN0IHVzZXJQcm9tcHQgPSB0aGlzLmNvbmZpZy5kZWZhdWx0VmFsdWVzLnVzZXJQcm9tcHQucmVwbGFjZSgvXFx7XFx7KC4qPylcXH1cXH0vZywgJ1tbJDFdXScpO1xuICAgIGNvbnN0IHVzZXJNc2cgPSB7IHJvbGU6ICd1c2VyJywgY29udGVudDogQ2hhdFNlcnZpY2UuZm9ybWF0UHJvbXB0KHRoaXMudHJhbnNsb2NvLnRyYW5zbGF0ZSh1c2VyUHJvbXB0KSAsIHsgcHJpbmNpcGFsOiB0aGlzLnByaW5jaXBhbFNlcnZpY2UucHJpbmNpcGFsIH0pLCBhZGRpdGlvbmFsUHJvcGVydGllczogeyBkaXNwbGF5OiB0aGlzLmNvbmZpZy5tb2RlU2V0dGluZ3MuZGlzcGxheVVzZXJQcm9tcHQgfSB9O1xuXG4gICAgaWYgKHRoaXMuY29uZmlnLm1vZGVTZXR0aW5ncy5pbml0aWFsaXphdGlvbi5ldmVudCA9PT0gJ1F1ZXJ5Jykge1xuICAgICAgdGhpcy5faGFuZGxlUXVlcnlNb2RlKHN5c3RlbU1zZywgdXNlck1zZyk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMuX2hhbmRsZVByb21wdE1vZGUoc3lzdGVtTXNnLCB1c2VyTXNnKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogSGFuZGxlcyB0aGUgcHJvbXB0IG1vZGUgb2YgdGhlIGNoYXQgY29tcG9uZW50LlxuICAgKiBJZiBgc2VuZFVzZXJQcm9tcHRgIGlzIHRydWUsIGl0IG9wZW5zIHRoZSBjaGF0IHdpdGggYm90aCBzeXN0ZW0gYW5kIHVzZXIgbWVzc2FnZXMsXG4gICAqIGFuZCBnZW5lcmF0ZXMgYXVkaXQgZXZlbnRzIGZvciBib3RoIG1lc3NhZ2VzLlxuICAgKiBJZiBgc2VuZFVzZXJQcm9tcHRgIGlzIGZhbHNlLCBpdCBvcGVucyB0aGUgY2hhdCB3aXRoIG9ubHkgdGhlIHN5c3RlbSBtZXNzYWdlLFxuICAgKiBhbmQgZ2VuZXJhdGVzIGFuIGF1ZGl0IGV2ZW50IGZvciB0aGUgc3lzdGVtIG1lc3NhZ2UuXG4gICAqXG4gICAqIEBwYXJhbSBzeXN0ZW1Nc2cgLSBUaGUgc3lzdGVtIG1lc3NhZ2UgdG8gYmUgZGlzcGxheWVkIGluIHRoZSBjaGF0LlxuICAgKiBAcGFyYW0gdXNlck1zZyAtIFRoZSB1c2VyIG1lc3NhZ2UgdG8gYmUgZGlzcGxheWVkIGluIHRoZSBjaGF0IChvcHRpb25hbCkuXG4gICAqL1xuICBwcml2YXRlIF9oYW5kbGVQcm9tcHRNb2RlKHN5c3RlbU1zZzogQ2hhdE1lc3NhZ2UsIHVzZXJNc2c6IENoYXRNZXNzYWdlKSB7XG4gICAgaWYgKHRoaXMuY29uZmlnLm1vZGVTZXR0aW5ncy5zZW5kVXNlclByb21wdCkge1xuICAgICAgdGhpcy5vcGVuQ2hhdChbc3lzdGVtTXNnLCB1c2VyTXNnXSk7XG4gICAgICB0aGlzLmNoYXRTZXJ2aWNlLmdlbmVyYXRlQXVkaXRFdmVudCgnYXN0LW1lc3NhZ2UnLCB0aGlzLl9kZWZpbmVNZXNzYWdlQXVkaXREZXRhaWxzKHN5c3RlbU1zZywgMCkpO1xuICAgICAgdGhpcy5jaGF0U2VydmljZS5nZW5lcmF0ZUF1ZGl0RXZlbnQoJ2FzdC1tZXNzYWdlJywgdGhpcy5fZGVmaW5lTWVzc2FnZUF1ZGl0RGV0YWlscyh1c2VyTXNnLCAxKSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMub3BlbkNoYXQoW3N5c3RlbU1zZ10pO1xuICAgICAgdGhpcy5jaGF0U2VydmljZS5nZW5lcmF0ZUF1ZGl0RXZlbnQoJ2FzdC1tZXNzYWdlJywgdGhpcy5fZGVmaW5lTWVzc2FnZUF1ZGl0RGV0YWlscyhzeXN0ZW1Nc2csIDApKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogSGFuZGxlcyB0aGUgcXVlcnkgbW9kZSBieSBkaXNwbGF5aW5nIHRoZSBzeXN0ZW0gbWVzc2FnZSwgdXNlciBtZXNzYWdlLCBhbmQgdXNlciBxdWVyeSBtZXNzYWdlLlxuICAgKiBJZiB0aGUgcHJvdmlkZWQgcXVlcnkgdGV4dCBpcyBub3QgZW1wdHksIHRoZW4gYWRkIHRoZSB1c2VyIHF1ZXJ5IG1lc3NhZ2UgdG8gdGhlIGNoYXQgaGlzdG9yeSBhbmQgaW52b2tlIHRoZSBhc3Npc3RhbnRcbiAgICogT3RoZXJ3aXNlLCBqdXN0IHN0YXJ0IGEgbmV3IGNoYXQgd2l0aCBhIHdhcm5pbmcgbWVzc2FnZSBpbnZpdGluZyB0aGUgdXNlciB0byBwZXJmb3JtIGEgZnVsbCB0ZXh0IHNlYXJjaCB0byByZXRyaWV2ZSBzb21lIHJlc3VsdHNcbiAgICogQHBhcmFtIHN5c3RlbU1zZyAtIFRoZSBzeXN0ZW0gbWVzc2FnZSB0byBiZSBkaXNwbGF5ZWQuXG4gICAqIEBwYXJhbSB1c2VyTXNnIC0gVGhlIHVzZXIgbWVzc2FnZSB0byBiZSBkaXNwbGF5ZWQuXG4gICAqL1xuICBwcml2YXRlIF9oYW5kbGVRdWVyeU1vZGUoc3lzdGVtTXNnOiBDaGF0TWVzc2FnZSwgdXNlck1zZzogQ2hhdE1lc3NhZ2UpIHtcbiAgICBpZiAoISF0aGlzLnF1ZXJ5LnRleHQpIHtcbiAgICAgIGNvbnN0IHVzZXJRdWVyeU1zZyA9IHsgcm9sZTogJ3VzZXInLCBjb250ZW50OiB0aGlzLnF1ZXJ5LnRleHQsIGFkZGl0aW9uYWxQcm9wZXJ0aWVzOiB7IGRpc3BsYXk6IHRoaXMuY29uZmlnLm1vZGVTZXR0aW5ncy5pbml0aWFsaXphdGlvbi5kaXNwbGF5VXNlclF1ZXJ5LCBxdWVyeTogdGhpcy5xdWVyeSwgZm9yY2VkV29ya2Zsb3c6IHRoaXMuY29uZmlnLm1vZGVTZXR0aW5ncy5pbml0aWFsaXphdGlvbi5mb3JjZWRXb3JrZmxvdywgZm9yY2VkRnVuY3Rpb246IHRoaXMuY29uZmlnLm1vZGVTZXR0aW5ncy5pbml0aWFsaXphdGlvbi5mb3JjZWRGdW5jdGlvbiwgaXNVc2VySW5wdXQ6IHRydWUsIGFkZGl0aW9uYWxXb3JrZmxvd1Byb3BlcnRpZXM6IHRoaXMuY29uZmlnLmFkZGl0aW9uYWxXb3JrZmxvd1Byb3BlcnRpZXMgfSB9O1xuICAgICAgaWYgKHRoaXMuY29uZmlnLm1vZGVTZXR0aW5ncy5zZW5kVXNlclByb21wdCkge1xuICAgICAgICB0aGlzLm9wZW5DaGF0KFtzeXN0ZW1Nc2csIHVzZXJNc2csIHVzZXJRdWVyeU1zZ10pO1xuICAgICAgICB0aGlzLmNoYXRTZXJ2aWNlLmdlbmVyYXRlQXVkaXRFdmVudCgnYXN0LW1lc3NhZ2UnLCB0aGlzLl9kZWZpbmVNZXNzYWdlQXVkaXREZXRhaWxzKHN5c3RlbU1zZywgMCkpO1xuICAgICAgICB0aGlzLmNoYXRTZXJ2aWNlLmdlbmVyYXRlQXVkaXRFdmVudCgnYXN0LW1lc3NhZ2UnLCB0aGlzLl9kZWZpbmVNZXNzYWdlQXVkaXREZXRhaWxzKHVzZXJNc2csIDEpKTtcbiAgICAgICAgdGhpcy5jaGF0U2VydmljZS5nZW5lcmF0ZUF1ZGl0RXZlbnQoJ2FzdC1tZXNzYWdlJywgeyAuLi50aGlzLl9kZWZpbmVNZXNzYWdlQXVkaXREZXRhaWxzKHVzZXJRdWVyeU1zZywgMiksICdxdWVyeSc6IEpTT04uc3RyaW5naWZ5KHRoaXMucXVlcnkpLCAnaXMtdXNlci1pbnB1dCc6IHRydWUsICdmb3JjZWQtd29ya2Zsb3cnOiB0aGlzLmNvbmZpZy5tb2RlU2V0dGluZ3MuaW5pdGlhbGl6YXRpb24uZm9yY2VkV29ya2Zsb3csICdmb3JjZWQtZnVuY3Rpb24nOiB0aGlzLmNvbmZpZy5tb2RlU2V0dGluZ3MuaW5pdGlhbGl6YXRpb24uZm9yY2VkRnVuY3Rpb24sICdlbmFibGVkLWZ1bmN0aW9ucyc6IHRoaXMuY29uZmlnLmRlZmF1bHRWYWx1ZXMuZnVuY3Rpb25zPy5maWx0ZXIoZnVuYyA9PiBmdW5jLmVuYWJsZWQpLm1hcChmdW5jID0+IGZ1bmMubmFtZSksICdhZGRpdGlvbmFsLXdvcmtmbG93LXByb3BlcnRpZXMnOiBKU09OLnN0cmluZ2lmeSh0aGlzLmNvbmZpZy5hZGRpdGlvbmFsV29ya2Zsb3dQcm9wZXJ0aWVzKSB9KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRoaXMub3BlbkNoYXQoW3N5c3RlbU1zZywgdXNlclF1ZXJ5TXNnXSk7XG4gICAgICAgIHRoaXMuY2hhdFNlcnZpY2UuZ2VuZXJhdGVBdWRpdEV2ZW50KCdhc3QtbWVzc2FnZScsIHRoaXMuX2RlZmluZU1lc3NhZ2VBdWRpdERldGFpbHMoc3lzdGVtTXNnLCAwKSk7XG4gICAgICAgIHRoaXMuY2hhdFNlcnZpY2UuZ2VuZXJhdGVBdWRpdEV2ZW50KCdhc3QtbWVzc2FnZScsIHsgLi4udGhpcy5fZGVmaW5lTWVzc2FnZUF1ZGl0RGV0YWlscyh1c2VyUXVlcnlNc2csIDEpLCAncXVlcnknOiBKU09OLnN0cmluZ2lmeSh0aGlzLnF1ZXJ5KSwgJ2lzLXVzZXItaW5wdXQnOiB0cnVlLCAnZm9yY2VkLXdvcmtmbG93JzogdGhpcy5jb25maWcubW9kZVNldHRpbmdzLmluaXRpYWxpemF0aW9uLmZvcmNlZFdvcmtmbG93LCAnZm9yY2VkLWZ1bmN0aW9uJzogdGhpcy5jb25maWcubW9kZVNldHRpbmdzLmluaXRpYWxpemF0aW9uLmZvcmNlZEZ1bmN0aW9uLCAnZW5hYmxlZC1mdW5jdGlvbnMnOiB0aGlzLmNvbmZpZy5kZWZhdWx0VmFsdWVzLmZ1bmN0aW9ucz8uZmlsdGVyKGZ1bmMgPT4gZnVuYy5lbmFibGVkKS5tYXAoZnVuYyA9PiBmdW5jLm5hbWUpLCAnYWRkaXRpb25hbC13b3JrZmxvdy1wcm9wZXJ0aWVzJzogSlNPTi5zdHJpbmdpZnkodGhpcy5jb25maWcuYWRkaXRpb25hbFdvcmtmbG93UHJvcGVydGllcykgfSk7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIGNvbnN0IHdhcm5pbmdNc2cgPSB7IHJvbGU6ICdzZWFyY2gtd2FybmluZycsIGNvbnRlbnQ6IHRoaXMudHJhbnNsb2NvLnRyYW5zbGF0ZSh0aGlzLmNvbmZpZy5nbG9iYWxTZXR0aW5ncy5zZWFyY2hXYXJuaW5nTWVzc2FnZSksIGFkZGl0aW9uYWxQcm9wZXJ0aWVzOiB7IGRpc3BsYXk6IHRydWUgfSB9O1xuICAgICAgdGhpcy5vcGVuQ2hhdChbc3lzdGVtTXNnLCB3YXJuaW5nTXNnXSk7XG4gICAgICB0aGlzLmNoYXRTZXJ2aWNlLmdlbmVyYXRlQXVkaXRFdmVudCgnYXN0LW1lc3NhZ2UnLCB0aGlzLl9kZWZpbmVNZXNzYWdlQXVkaXREZXRhaWxzKHdhcm5pbmdNc2csIDApKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIF9kZWZpbmVNZXNzYWdlQXVkaXREZXRhaWxzKG1lc3NhZ2U6IENoYXRNZXNzYWdlLCByYW5rOiBudW1iZXIpOiBSZWNvcmQ8c3RyaW5nLCBhbnk+IHtcbiAgICBjb25zdCBkZXRhaWxzOiBSZWNvcmQ8c3RyaW5nLCBhbnk+ID0ge1xuICAgICAgJ2R1cmF0aW9uJzogdGhpcy5sYXN0RmV0Y2hEdXJhdGlvbiB8fCAwLFxuICAgICAgJ3JvbGUnOiBtZXNzYWdlLnJvbGUsXG4gICAgICAncmFuayc6IHJhbmtcbiAgICB9O1xuICAgIGlmICghIXRoaXMuY29uZmlnLmF1ZGl0U2V0dGluZ3M/LmxvZ0NvbnRlbnQpIHtcbiAgICAgIGRldGFpbHMudGV4dCA9IG1lc3NhZ2UuY29udGVudDtcbiAgICB9XG4gICAgcmV0dXJuIGRldGFpbHM7XG4gIH1cblxuICAvKipcbiAgICogU3RhcnQvb3BlbiBhIG5ldyBjaGF0IHdpdGggdGhlIHByb3ZpZGVkIG1lc3NhZ2VzIGFuZCBjaGF0SWRcbiAgICogSWYgdGhlIGxhc3QgbWVzc2FnZSBpcyBmcm9tIHRoZSB1c2VyLCBhIHJlcXVlc3QgdG8gdGhlIGFzc2lzdGFudCBpcyBtYWRlIHRvIGdldCBhbiBhbnN3ZXJcbiAgICogSWYgdGhlIGxhc3QgbWVzc2FnZSBpcyBmcm9tIHRoZSBhc3Npc3RhbnQsIHRoZSBjb252ZXJzYXRpb24gaXMgbG9hZGVkIHJpZ2h0IGF3YXlcbiAgICogQHBhcmFtIG1lc3NhZ2VzIFRoZSBsaXN0IG9mIG1lc3NhZ2VzIG9mIHRoZSBjaGF0XG4gICAqIEBwYXJhbSBzYXZlZENoYXRJZCAgVGhlIGlkIG9mIHRoZSBzYXZlZCBjaGF0LiBJZiBwcm92aWRlZCAoaWUuIGFuIGV4aXN0aW5nIGRpc2N1c3Npb24gaW4gdGhlIHNhdmVkIGNoYXQgaW5kZXgpLCB1cGRhdGUgdGhlIHNhdmVkQ2hhdElkIGluIHRoZSBjaGF0IHNlcnZpY2UgZm9yIHRoZSB1cGNvbWluZyBzYXZlZCBjaGF0IG9wZXJhdGlvbnNcbiAgICovXG4gIG9wZW5DaGF0KG1lc3NhZ2VzOiBSYXdNZXNzYWdlW10sIHNhdmVkQ2hhdElkPzogc3RyaW5nKSB7XG4gICAgaWYgKCFtZXNzYWdlcyB8fCAhQXJyYXkuaXNBcnJheShtZXNzYWdlcykpIHtcbiAgICAgIGNvbnNvbGUuZXJyb3IoJ0Vycm9yIG9jY3VycyB3aGlsZSB0cnlpbmcgdG8gbG9hZCB0aGUgZGlzY3Vzc2lvbi4gSW52YWxpZCBtZXNzYWdlcyByZWNlaXZlZCA6JywgbWVzc2FnZXMpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBpZiAoc2F2ZWRDaGF0SWQpIHtcbiAgICAgIHRoaXMuY2hhdFNlcnZpY2Uuc2V0U2F2ZWRDaGF0SWQoc2F2ZWRDaGF0SWQpO1xuICAgICAgdGhpcy5jaGF0U2VydmljZS5nZW5lcmF0ZUNoYXRJZChzYXZlZENoYXRJZCk7XG4gICAgfVxuICAgIHRoaXMucmVzZXRDaGF0KCk7XG4gICAgdGhpcy5tZXNzYWdlcyQubmV4dChtZXNzYWdlcyk7XG4gICAgdGhpcy5jaGF0U2VydmljZS5jaGF0SGlzdG9yeSA9IG1lc3NhZ2VzO1xuICAgIGNvbnN0IGxhc3RNZXNzYWdlID0gbWVzc2FnZXMuYXQoLTEpO1xuICAgIGlmIChsYXN0TWVzc2FnZSAmJiBsYXN0TWVzc2FnZS5yb2xlID09PSAndXNlcicpIHtcbiAgICAgIHRoaXMuZmV0Y2gobWVzc2FnZXMpOyAvLyBJZiB0aGUgbGFzdCBtZXNzYWdlIGlmIGZyb20gYSB1c2VyLCBhbiBhbnN3ZXIgZnJvbSB0aGUgYXNzaXN0YW50IGlzIGV4cGVjdGVkXG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgdGhpcy51cGRhdGVEYXRhKG1lc3NhZ2VzKTsgLy8gSWYgdGhlIGxhc3QgbWVzc2FnZSBpZiBmcm9tIHRoZSBhc3Npc3RhbnQsIHdlIGNhbiBsb2FkIHRoZSBjb252ZXJzYXRpb24gcmlnaHQgYXdheVxuICAgICAgdGhpcy50ZXJtaW5hdGVGZXRjaCgpO1xuICAgIH1cbiAgICB0aGlzLl9hZGRTY3JvbGxMaXN0ZW5lcigpO1xuICB9XG5cbiAgLyoqXG4gICAqIFJlc2V0IHRoZSBjaGF0IGJ5IGNsZWFyaW5nIHRoZSBjaGF0IGhpc3RvcnkgYW5kIHRoZSBVSSBhY2NvcmRpbmdseVxuICAgKiBUaGUgdXNlciBpbnB1dCB3aWxsIGJlIGNsZWFyZWRcbiAgICogVGhlIGZldGNoIHN1YnNjcmlwdGlvbiB3aWxsIGJlIHRlcm1pbmF0ZWRcbiAgICovXG4gIHJlc2V0Q2hhdCgpIHtcbiAgICBpZiAodGhpcy5tZXNzYWdlcyQudmFsdWUpIHtcbiAgICAgIHRoaXMubWVzc2FnZXMkLm5leHQodW5kZWZpbmVkKTsgLy8gUmVzZXQgY2hhdFxuICAgIH1cbiAgICB0aGlzLmNoYXRTZXJ2aWNlLmNoYXRIaXN0b3J5ID0gdW5kZWZpbmVkOyAvLyBSZXNldCBjaGF0IGhpc3RvcnlcbiAgICB0aGlzLnF1ZXN0aW9uID0gJyc7XG4gICAgdGhpcy50ZXJtaW5hdGVGZXRjaCgpO1xuICB9XG5cbiAgLyoqXG4gICAqIEZldGNoIGFuZCBMb2FkIHRoZSBzYXZlZCBjaGF0IGZyb20gdGhlIHNhdmVkIGNoYXQgaW5kZXguXG4gICAqIElmIHRoZSBzYXZlZCBjaGF0IGlzIGZvdW5kLCB0aGUgY2hhdCBkaXNjdXNzaW9uIHdpbGwgYmUgbG9hZGVkIHdpdGggdGhlIHByb3ZpZGVkIG1lc3NhZ2VzIGFuZCBjaGF0SWRcbiAgICovXG4gIG9uTG9hZENoYXQoKSB7XG4gICAgdGhpcy5sb2FkaW5nJC5uZXh0KHRydWUpO1xuICAgIHRoaXMuX3N1Yi5hZGQoXG4gICAgICB0aGlzLmNoYXRTZXJ2aWNlLmxvYWRTYXZlZENoYXQkXG4gICAgICAgIC5waXBlKFxuICAgICAgICAgIGZpbHRlcihzYXZlZENoYXQgPT4gISFzYXZlZENoYXQpLFxuICAgICAgICAgIHN3aXRjaE1hcChzYXZlZENoYXQgPT4gdGhpcy5jaGF0U2VydmljZS5nZXRTYXZlZENoYXQoc2F2ZWRDaGF0IS5pZCkpLFxuICAgICAgICAgIGZpbHRlcihzYXZlZENoYXRIaXN0b3J5ID0+ICEhc2F2ZWRDaGF0SGlzdG9yeSksXG4gICAgICAgICAgdGFwKHNhdmVkQ2hhdEhpc3RvcnkgPT4gdGhpcy5vcGVuQ2hhdChzYXZlZENoYXRIaXN0b3J5IS5oaXN0b3J5LCBzYXZlZENoYXRIaXN0b3J5IS5pZCkpXG4gICAgICAgICkuc3Vic2NyaWJlKClcbiAgICApO1xuICB9XG5cbiAgLyoqXG4gICAqIFN0b3AgdGhlIGdlbmVyYXRpb24gb2YgdGhlIGN1cnJlbnQgYXNzaXN0YW50J3MgYW5zd2VyLlxuICAgKiBUaGUgZmV0Y2ggc3Vic2NyaXB0aW9uIHdpbGwgYmUgdGVybWluYXRlZC5cbiAgICovXG4gIHN0b3BHZW5lcmF0aW9uKCkge1xuICAgIHRoaXMuY2hhdFNlcnZpY2Uuc3RvcEdlbmVyYXRpb24oKS5zdWJzY3JpYmUoXG4gICAgICAoKSA9PiB0aGlzLnRlcm1pbmF0ZUZldGNoKClcbiAgICApO1xuICB9XG5cbiAgLyoqXG4gICAqIFRlcm1pbmF0ZSB0aGUgZmV0Y2ggcHJvY2VzcyBieSB1bnN1YnNjcmliaW5nIGZyb20gdGhlIGRhdGEgc3Vic2NyaXB0aW9uIGFuZCB1cGRhdGluZyB0aGUgbG9hZGluZyBzdGF0dXMgdG8gZmFsc2UuXG4gICAqIEFkZGl0aW9uYWxseSwgZm9jdXMgb24gdGhlIGNoYXQgaW5wdXQgaWYgdGhlIGZvY3VzQWZ0ZXJSZXNwb25zZSBmbGFnIGlzIHNldCB0byB0cnVlLlxuICAgKi9cbiAgdGVybWluYXRlRmV0Y2goKSB7XG4gICAgdGhpcy5fZGF0YVN1YnNjcmlwdGlvbj8udW5zdWJzY3JpYmUoKTtcbiAgICB0aGlzLl9kYXRhU3Vic2NyaXB0aW9uID0gdW5kZWZpbmVkO1xuICAgIHRoaXMubG9hZGluZyQubmV4dChmYWxzZSk7XG4gICAgdGhpcy5jZHIuZGV0ZWN0Q2hhbmdlcygpO1xuXG4gICAgaWYgKHRoaXMuZm9jdXNBZnRlclJlc3BvbnNlKSB7XG4gICAgICBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgICAgdGhpcy5xdWVzdGlvbklucHV0Py5uYXRpdmVFbGVtZW50LmZvY3VzKCk7XG4gICAgICB9KTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQ29weSBhIHByZXZpb3VzIHVzZXIgbWVzc2FnZSBvZiB0aGUgY2hhdCBoaXN0b3J5IHRvIHRoZSBjaGF0IHVzZXIgaW5wdXQuXG4gICAqIFRodXMsIHRoZSB1c2VyIGNhbiBlZGl0IGFuZCByZXN1Ym1pdCB0aGUgbWVzc2FnZS5cbiAgICogT25jZSB0aGUgZWRpdGVkIG1lc3NhZ2UgaXMgc3VibWl0dGVkLCBhbGwgc3Vic2VxdWVudCBtZXNzYWdlcyBzdGFydGluZyBmcm9tIEBwYXJhbSBpbmRleCB3aWxsIGJlIHJlbW92ZWQgZnJvbSB0aGUgaGlzdG9yeSBhbmQgdGhlIFVJIHdpbGwgYmUgdXBkYXRlZCBhY2NvcmRpbmdseS5cbiAgICogVGhlIGFzc2lzdGFudCB3aWxsIHJlZ2VuZXJhdGUgYSBuZXcgYW5zd2VyIGJhc2VkIG9uIHRoZSB1cGRhdGVkIGNoYXQgaGlzdG9yeS5cbiAgICog4pqg77iPIElmIHRoZSBhc3Npc3RhbnQgaXMgc3RyZWFtaW5nIG9yIHN0b3BwaW5nIHRoZSBnZW5lcmF0aW9uLCB0aGUgb3BlcmF0aW9uIGlzIG5vdCBhbGxvd2VkLlxuICAgKiBAcGFyYW0gaW5kZXggVGhlIGluZGV4IG9mIHRoZSB1c2VyJ3MgbWVzc2FnZSB0byBlZGl0XG4gICAqL1xuICBlZGl0TWVzc2FnZShpbmRleDogbnVtYmVyKSB7XG4gICAgaWYgKCEhdGhpcy5jaGF0U2VydmljZS5zdHJlYW1pbmckLnZhbHVlIHx8ICEhdGhpcy5jaGF0U2VydmljZS5zdG9wcGluZ0dlbmVyYXRpb24kLnZhbHVlKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIHRoaXMubWVzc2FnZVRvRWRpdCA9IGluZGV4O1xuICAgIHRoaXMucmVtYXBwZWRNZXNzYWdlVG9FZGl0ID0gdGhpcy5fcmVtYXBJbmRleEluQ2hhdEhpc3RvcnkoaW5kZXgpO1xuXG4gICAgLy8gR2V0IHVzZXIgbWVzc2FnZSBmcm9tIGJvdGggbGVnYWN5IGFuZCB0ZXh0IG1lc3NhZ2UgdHlwZVxuICAgIGNvbnN0IG1lc3NhZ2UgPSB0aGlzLmNoYXRTZXJ2aWNlLmNoYXRIaXN0b3J5IVt0aGlzLl9yZW1hcEluZGV4SW5DaGF0SGlzdG9yeShpbmRleCldO1xuICAgIHRoaXMucXVlc3Rpb24gPSB0eXBlb2YgbWVzc2FnZS5jb250ZW50ID09PSAnc3RyaW5nJyA/IG1lc3NhZ2UuY29udGVudCA6IChtZXNzYWdlLmNvbnRlbnRbMF0gYXMgVGV4dE1lc3NhZ2VDb250ZW50KS50ZXh0O1xuXG4gICAgdGhpcy5jaGF0U2VydmljZS5nZW5lcmF0ZUF1ZGl0RXZlbnQoJ2VkaXQuY2xpY2snLCB7J3JhbmsnOiB0aGlzLl9yZW1hcEluZGV4SW5DaGF0SGlzdG9yeShpbmRleCl9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDb3B5IGEgcHJldmlvdXMgYXNzaXN0YW50IG1lc3NhZ2Ugb2YgdGhlIGNoYXQgaGlzdG9yeSB0byB0aGUgY2xpcGJvYXJkLlxuICAgKiBAcGFyYW0gaW5kZXggVGhlIGluZGV4IG9mIHRoZSBhc3Npc3RhbnQncyBtZXNzYWdlIHRvIGVkaXRcbiAgICovXG4gIGNvcHlNZXNzYWdlKGluZGV4OiBudW1iZXIpIHtcbiAgICAvLyBSZW1hcCB0aGUgaW5kZXggaW4gdGhlIGNoYXQgaGlzdG9yeVxuICAgIGNvbnN0IGlkeCA9IHRoaXMuX3JlbWFwSW5kZXhJbkNoYXRIaXN0b3J5KGluZGV4KTtcbiAgICB0aGlzLmNoYXRTZXJ2aWNlLmdlbmVyYXRlQXVkaXRFdmVudCgnYXN0LWNvcHkuY2xpY2snLCB7ICdyYW5rJzogaWR4IH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIFN0YXJ0aW5nIGZyb20gdGhlIHByb3ZpZGVkIGluZGV4LCByZW1vdmUgYWxsIHN1YnNlcXVlbnQgbWVzc2FnZXMgZnJvbSB0aGUgY2hhdCBoaXN0b3J5IGFuZCB0aGUgVUkgYWNjb3JkaW5nbHkuXG4gICAqIFRoZSBhc3Npc3RhbnQgd2lsbCByZWdlbmVyYXRlIGEgbmV3IGFuc3dlciBiYXNlZCBvbiB0aGUgdXBkYXRlZCBjaGF0IGhpc3RvcnkuXG4gICAqIOKaoO+4jyBJZiB0aGUgYXNzaXN0YW50IGlzIHN0cmVhbWluZyBvciBzdG9wcGluZyB0aGUgZ2VuZXJhdGlvbiwgdGhlIG9wZXJhdGlvbiBpcyBub3QgYWxsb3dlZC5cbiAgICogQHBhcmFtIGluZGV4IFRoZSBpbmRleCBvZiB0aGUgYXNzaXN0YW50J3MgbWVzc2FnZSB0byByZWdlbmVyYXRlXG4gICAqL1xuICByZWdlbmVyYXRlTWVzc2FnZShpbmRleDogbnVtYmVyKSB7XG4gICAgaWYgKCEhdGhpcy5jaGF0U2VydmljZS5zdHJlYW1pbmckLnZhbHVlIHx8ICEhdGhpcy5jaGF0U2VydmljZS5zdG9wcGluZ0dlbmVyYXRpb24kLnZhbHVlKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIC8vIFVwZGF0ZSB0aGUgbWVzc2FnZXMgaW4gdGhlIFVJIGJ5IHJlbW92aW5nIGFsbCBzdWJzZXF1ZW50ICdhc3Npc3RhbnQnIG1lc3NhZ2VzIHN0YXJ0aW5nIGZyb20gdGhlIHByb3ZpZGVkIGluZGV4IHVudGlsIHRoZSBmaXJzdCBwcmV2aW91cyAndXNlcicgbWVzc2FnZVxuICAgIGxldCBpID0gaW5kZXg7XG4gICAgd2hpbGUgKGkgPj0gMCAmJiAhKCh0aGlzLm1lc3NhZ2VzJC52YWx1ZSEpW2ldLnJvbGUgPT09ICd1c2VyJyAmJiAodGhpcy5tZXNzYWdlcyQudmFsdWUhKVtpXS5hZGRpdGlvbmFsUHJvcGVydGllcy5pc1VzZXJJbnB1dCA9PT0gdHJ1ZSkpIHtcbiAgICAgIGktLTtcbiAgICB9XG4gICAgLy8gSXQgc2hvdWxkIGFsd2F5cyBiZSB0aGUgY2FzZSB0aGF0IGkgPiAwXG4gICAgaWYgKGkgPj0gMCkge1xuICAgICAgdGhpcy5tZXNzYWdlcyQubmV4dCh0aGlzLm1lc3NhZ2VzJC52YWx1ZSEuc2xpY2UoMCwgaSArIDEpKTtcbiAgICAgIC8vIFJlbWFwIHRoZSBpbmRleCBvZiB0aGlzIGZvdW5kIGZpcnN0IHByZXZpb3VzICd1c2VyJyBtZXNzYWdlIGluIHRoZSBjaGF0IGhpc3RvcnlcbiAgICAgIGNvbnN0IGlkeCA9IHRoaXMuX3JlbWFwSW5kZXhJbkNoYXRIaXN0b3J5KGkpO1xuICAgICAgLy8gRGVmaW5lIGFuZCBVcGRhdGUgdGhlIGNoYXQgaGlzdG9yeSBiYXNlZCBvbiB3aGljaCB0aGUgYXNzaXN0YW50IHdpbGwgZ2VuZXJhdGUgYSBuZXcgYW5zd2VyXG4gICAgICB0aGlzLmNoYXRTZXJ2aWNlLmNoYXRIaXN0b3J5ID0gdGhpcy5jaGF0U2VydmljZS5jaGF0SGlzdG9yeSEuc2xpY2UoMCwgaWR4ICsgMSk7XG4gICAgICAvLyBGZXRjaCB0aGUgYW5zd2VyXG4gICAgICB0aGlzLmZldGNoKHRoaXMuY2hhdFNlcnZpY2UuY2hhdEhpc3RvcnkpO1xuICAgICAgdGhpcy5jaGF0U2VydmljZS5nZW5lcmF0ZUF1ZGl0RXZlbnQoJ2FzdC1yZWdlbmVyYXRlLmNsaWNrJywgeyAncmFuayc6IGlkeCB9KTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogUmVtYXBzIHRoZSBpbmRleCBpbiB0aGUgY2hhdCBoaXN0b3J5LlxuICAgKiBUaGUgY2hhdCBoaXN0b3J5IGlzIGEgbGlzdCBvZiBtZXNzYWdlcyB3aGVyZSBzb21lIG1lc3NhZ2VzIGNhbiBiZSBoaWRkZW4gKGRpc3BsYXkgc2V0IHRvIGZhbHNlKS5cbiAgICogVGhlIGluZGV4IHByb3ZpZGVkIGFzIGlucHV0IGlzIHRoZSBpbmRleCBvZiB0aGUgbWVzc2FnZSBpbiB0aGUgY2hhdCBoaXN0b3J5IGRpc3BsYXllZCBpbiB0aGUgVUkuXG4gICAqIFRoaXMgZnVuY3Rpb24gc2hvdWxkIGJlIHJlbW92ZWQgb25jZSB0aGUgYmFja2VuZCBpcyB1cGRhdGVkIHRvIGFkZCB0aGUgaWRzIG9mIHRoZSBtZXNzYWdlcyBpbiB0aGUgY2hhdCBoaXN0b3J5XG4gICAqIEBwYXJhbSBpbmRleCAtIFRoZSBpbmRleCB0byBiZSByZW1hcHBlZC5cbiAgICovXG4gIHByaXZhdGUgX3JlbWFwSW5kZXhJbkNoYXRIaXN0b3J5KGluZGV4OiBudW1iZXIpIHtcbiAgICAvLyBhIGNvcHkgb2YgdGhlIGNoYXQgaGlzdG9yeSBpcyBjcmVhdGVkIHRvIGF2b2lkIG1vZGlmeWluZyB0aGUgb3JpZ2luYWwgY2hhdCBoaXN0b3J5LlxuICAgIC8vIEFkZGl0aW9uYWxseSwgYSByYW5rIGlzIGdpdmluZyB0byBlYWNoIG1lc3NhZ2UuXG4gICAgLy8gQWxsIG1lc3NhZ2VzIGhhdmluZyByb2xlICd1c2VyJyBhcmUgdXBkYXRlZCB3aXRoIHRoZSBkaXNwbGF5IHByb3BlcnR5IHNldCB0byB0cnVlLCB0aGlzIGlzIG1hbmRhdG9yeSB0byBnZXQgdGhlIGNvcnJlY3QgcmFuayBvZiB0aGUgbWVzc2FnZSBpbiB0aGUgY2hhdCBoaXN0b3J5IHdoZW4gdGhlIHVzZXIgbWVzc2FnZSB0byByZW1hcCBpcyBoaWRkZW5cbiAgICBjb25zdCBoaXN0b3J5ID0gdGhpcy5jaGF0U2VydmljZS5jaGF0SGlzdG9yeSFcbiAgICAgIC5zbGljZSgpXG4gICAgICAubWFwKChtZXNzYWdlLCBpZHgpID0+ICh7IC4uLm1lc3NhZ2UsIGFkZGl0aW9uYWxQcm9wZXJ0aWVzOiB7IC4uLm1lc3NhZ2UuYWRkaXRpb25hbFByb3BlcnRpZXMsIHJhbms6IGlkeCB9IH0pKVxuICAgICAgLm1hcCgobWVzc2FnZSkgPT4ge1xuICAgICAgICBpZiAobWVzc2FnZS5yb2xlID09PSBcInVzZXJcIikge1xuICAgICAgICAgIHJldHVybiB7IC4uLm1lc3NhZ2UsIGFkZGl0aW9uYWxQcm9wZXJ0aWVzOiB7IC4uLm1lc3NhZ2UuYWRkaXRpb25hbFByb3BlcnRpZXMsIGRpc3BsYXk6IHRydWUgfSB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG1lc3NhZ2U7XG4gICAgICB9KVxuICAgIC8vIENvdW50IHRoZSBudW1iZXIgb2YgaGlkZGVuIG1lc3NhZ2VzIChvZiByb2xlIGRpZmZlcmVudCB0aGVuIFwidXNlclwiKSBpbiBtZXNzYWdlcyQgYmVmb3JlIHRoZSBwcm92aWRlZCBpbmRleFxuICAgIC8vIEFsbCBtZXNzYWdlcyBoYXZpbmcgcm9sZSAndXNlcicgYXJlIHVwZGF0ZWQgd2l0aCB0aGUgZGlzcGxheSBwcm9wZXJ0eSBzZXQgdG8gdHJ1ZSwgdGhpcyBpcyBtYW5kYXRvcnkgdG8gZ2V0IHRoZSBjb3JyZWN0IHJhbmsgb2YgdGhlIG1lc3NhZ2UgaW4gdGhlIGNoYXQgaGlzdG9yeSB3aGVuIHRoZSB1c2VyIG1lc3NhZ2UgdG8gcmVtYXAgaXMgaGlkZGVuXG4gICAgLy8gVGhpcyBpcyBtYW5kYXRvcnkgdG8gZ2V0IHRoZSBjb3JyZWN0IHJhbmsgb2YgdGhlIG1lc3NhZ2UgaW4gdGhlIGNoYXQgaGlzdG9yeVxuICAgIC8vIFNpbmNlIHNvbWUgaGlkZGVuIG1lc3NhZ2VzIChsaWtlICdzeXN0ZW0nIG1lc3NhZ2VzKSBhcmUgbm90IGRpc3BsYXllZCBpbiB0aGUgVUkgYnV0IGhhdmUgYmVlbiBjb3VudGVkIGluIHRoZSBwcm92aWRlZCBpbmRleFxuICAgIGNvbnN0IG51bWJlck9mSGlkZGVuTWVzc2FnZXNJbk1lc3NhZ2VzJEJlZm9yZUluZGV4ID0gdGhpcy5tZXNzYWdlcyQudmFsdWUhXG4gICAgICAuc2xpY2UoMCwgaW5kZXgpXG4gICAgICAubWFwKChtZXNzYWdlKSA9PiB7XG4gICAgICAgIGlmIChtZXNzYWdlLnJvbGUgPT09IFwidXNlclwiKSB7XG4gICAgICAgICAgcmV0dXJuIHsgLi4ubWVzc2FnZSwgYWRkaXRpb25hbFByb3BlcnRpZXM6IHsgLi4ubWVzc2FnZS5hZGRpdGlvbmFsUHJvcGVydGllcywgZGlzcGxheTogdHJ1ZSB9IH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbWVzc2FnZTtcbiAgICAgIH0pXG4gICAgICAuZmlsdGVyKG1lc3NhZ2UgPT4gIW1lc3NhZ2UuYWRkaXRpb25hbFByb3BlcnRpZXMuZGlzcGxheSkubGVuZ3RoO1xuICAgIC8vIHJlbW92ZSBhbGwgbWVzc2FnZXMgdGhhdCBoYXZlIGRpc3BsYXkgc2V0IHRvIGZhbHNlXG4gICAgLy8gdGhpcyBpcyBtYW5kYXRvcnkgc2luY2UgYXQgdGhlIHBvaW50IG9mIHRpbWUgd2hlbiB0aGUgYXNzaXN0YW50IGFuc3dlcnMgYSBxdWVzdGlvbixcbiAgICAvLyBpdCBtaWdodCBoYXZlIHNvbWUgaGlkZGVuIG1lc3NhZ2VzIChmb3IgZXhhbXBsZSBjb250ZXh0TWVzc2FnZXMpIHRoYXQgYXJlIGF2YWlsYWJsZSBpbiB0aGUgY2hhdCBoaXN0b3J5IGJ1dCBkb24ndCBmaWd1cmUgaW4gbWVzc2FnZXMkIHVubGVzcyBhIG5ldyBxdWVzdGlvbiBpcyBhc2tlZFxuICAgIGNvbnN0IGZpbHRlcmVkSGlzdG9yeSA9IGhpc3RvcnkuZmlsdGVyKG1lc3NhZ2UgPT4gbWVzc2FnZS5hZGRpdGlvbmFsUHJvcGVydGllcy5kaXNwbGF5KTtcbiAgICAvLyByZXR1cm4gdGhlIGluZGV4IG9mIHRoZSBtZXNzYWdlIGluIHRoZSBmaWx0ZXJlZCBoaXN0b3J5XG4gICAgcmV0dXJuIGZpbHRlcmVkSGlzdG9yeVtpbmRleCAtIG51bWJlck9mSGlkZGVuTWVzc2FnZXNJbk1lc3NhZ2VzJEJlZm9yZUluZGV4XS5hZGRpdGlvbmFsUHJvcGVydGllcy5yYW5rO1xuICB9XG5cbiAgLyoqXG4gICAqIEhhbmRsZXMgdGhlIGtleSB1cCBldmVudCBmb3IgJ0JhY2tzcGFjZScgYW5kICdFbnRlcicga2V5cy5cbiAgICogQHBhcmFtIGV2ZW50IC0gVGhlIGtleWJvYXJkIGV2ZW50LlxuICAgKi9cbiAgb25LZXlVcChldmVudDogS2V5Ym9hcmRFdmVudCk6IHZvaWQge1xuICAgIHN3aXRjaCAoZXZlbnQua2V5KSB7XG4gICAgICBjYXNlICdCYWNrc3BhY2UnOlxuICAgICAgICB0aGlzLmNhbGN1bGF0ZUhlaWdodCgpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgJ0VudGVyJzpcbiAgICAgICAgaWYgKCFldmVudC5zaGlmdEtleSkge1xuICAgICAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgICAgdGhpcy5zdWJtaXRRdWVzdGlvbigpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuY2FsY3VsYXRlSGVpZ2h0KCk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgYnJlYWs7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIENhbGN1bGF0ZXMgYW5kIGFkanVzdHMgdGhlIGhlaWdodCBvZiB0aGUgcXVlc3Rpb24gaW5wdXQgZWxlbWVudCBiYXNlZCBvbiBpdHMgY29udGVudC5cbiAgICogSWYgdGhlIEVudGVyIGtleSBpcyBwcmVzc2VkIHdpdGhvdXQgdGhlIFNoaWZ0IGtleSwgaXQgcHJldmVudHMgdGhlIGRlZmF1bHQgYmVoYXZpb3IuXG4gICAqIEBwYXJhbSBldmVudCBUaGUga2V5Ym9hcmQgZXZlbnRcbiAgICovXG4gIGNhbGN1bGF0ZUhlaWdodChldmVudD86IEtleWJvYXJkRXZlbnQpOiB2b2lkIHtcbiAgICBpZiAoZXZlbnQ/LmtleSA9PT0gJ0VudGVyJyAmJiAhZXZlbnQuc2hpZnRLZXkpIHtcbiAgICAgIGV2ZW50Py5wcmV2ZW50RGVmYXVsdCgpO1xuICAgIH1cbiAgICBjb25zdCBtYXhIZWlnaHQgPSAxNzA7XG4gICAgY29uc3QgZWwgPSB0aGlzLnF1ZXN0aW9uSW5wdXQhLm5hdGl2ZUVsZW1lbnQ7XG4gICAgZWwuc3R5bGUubWF4SGVpZ2h0ID0gYCR7bWF4SGVpZ2h0fXB4YDtcbiAgICBlbC5zdHlsZS5oZWlnaHQgPSAnYXV0byc7XG4gICAgZWwuc3R5bGUuaGVpZ2h0ID0gYCR7ZWwuc2Nyb2xsSGVpZ2h0fXB4YDtcbiAgICBlbC5zdHlsZS5vdmVyZmxvd1kgPSBlbC5zY3JvbGxIZWlnaHQgPj0gbWF4SGVpZ2h0ID8gJ3Njcm9sbCcgOiAnaGlkZGVuJztcbiAgfVxuXG4gIC8qKlxuICAgKiBTZW5kIGEgXCJsaWtlXCIgZXZlbnQgb24gY2xpY2tpbmcgb24gdGhlIHRodW1iLXVwIGljb24gb2YgYW4gYXNzaXN0YW50J3MgbWVzc2FnZVxuICAgKiBAcGFyYW0gbWVzc2FnZSBUaGUgYXNzaXN0YW50IG1lc3NhZ2UgdG8gbGlrZVxuICAgKiBAcGFyYW0gcmFuayBUaGUgcmFuayBvZiB0aGUgbWVzc2FnZSB0byBsaWtlXG4gICAqL1xuICBvbkxpa2UobWVzc2FnZTogQ2hhdE1lc3NhZ2UsIHJhbms6IG51bWJlcik6IHZvaWQge1xuICAgIC8vIFJlbWFwIHRoZSBpbmRleCBpbiB0aGUgY2hhdCBoaXN0b3J5XG4gICAgY29uc3QgaWR4ID0gdGhpcy5fcmVtYXBJbmRleEluQ2hhdEhpc3RvcnkocmFuayk7XG4gICAgdGhpcy5jaGF0U2VydmljZS5nZW5lcmF0ZUF1ZGl0RXZlbnQoJ2FzdC10aHVtYi11cC5jbGljaycsIHsgcmFuazogaWR4IH0pO1xuICAgIHRoaXMucmVwb3J0VHlwZSA9ICdsaWtlJztcbiAgICB0aGlzLm1lc3NhZ2VUb1JlcG9ydCA9IG1lc3NhZ2U7XG4gICAgdGhpcy5yZXBvcnRDb21tZW50ID0gdW5kZWZpbmVkO1xuICAgIHRoaXMucmVwb3J0UmFuayA9IHJhbms7XG4gICAgdGhpcy5zaG93UmVwb3J0ID0gdHJ1ZVxuXG4gICAgdGhpcy5jaGF0U2VydmljZS5jaGF0SGlzdG9yeSFbdGhpcy5fcmVtYXBJbmRleEluQ2hhdEhpc3RvcnkocmFuayldLmFkZGl0aW9uYWxQcm9wZXJ0aWVzLiRsaWtlZCA9IHRydWU7XG4gICAgdGhpcy5jaGF0U2VydmljZS5jaGF0SGlzdG9yeSFbdGhpcy5fcmVtYXBJbmRleEluQ2hhdEhpc3RvcnkocmFuayldLmFkZGl0aW9uYWxQcm9wZXJ0aWVzLiRkaXNsaWtlZCA9IGZhbHNlO1xuICAgIHRoaXMuX3VwZGF0ZUNoYXRIaXN0b3J5KCk7XG4gIH1cblxuICAvKipcbiAgICogU2VuZCBhIFwiZGlzbGlrZVwiIGV2ZW50IG9uIGNsaWNraW5nIG9uIHRoZSB0aHVtYi1kb3duIGljb24gb2YgYW4gYXNzaXN0YW50J3MgbWVzc2FnZS5cbiAgICogSXQgYWxzbyBvcGVucyB0aGUgaXNzdWUgcmVwb3J0aW5nIGRpYWxvZy5cbiAgICogQHBhcmFtIG1lc3NhZ2UgVGhlIGFzc2lzdGFudCBtZXNzYWdlIHRvIGRpc2xpa2VcbiAgICogQHBhcmFtIGluZGV4IFRoZSByYW5rIG9mIHRoZSBtZXNzYWdlIHRvIGRpc2xpa2VcbiAgICovXG4gIG9uRGlzbGlrZShtZXNzYWdlOiBDaGF0TWVzc2FnZSwgcmFuazogbnVtYmVyKTogdm9pZCB7XG4gICAgLy8gUmVtYXAgdGhlIGluZGV4IGluIHRoZSBjaGF0IGhpc3RvcnlcbiAgICBjb25zdCBpZHggPSB0aGlzLl9yZW1hcEluZGV4SW5DaGF0SGlzdG9yeShyYW5rKTtcbiAgICB0aGlzLmNoYXRTZXJ2aWNlLmdlbmVyYXRlQXVkaXRFdmVudCgnYXN0LXRodW1iLWRvd24uY2xpY2snLCB7IHJhbms6IGlkeCB9KTtcbiAgICB0aGlzLnJlcG9ydFR5cGUgPSAnZGlzbGlrZSc7XG4gICAgdGhpcy5tZXNzYWdlVG9SZXBvcnQgPSBtZXNzYWdlO1xuICAgIHRoaXMuaXNzdWVUeXBlID0gJyc7XG4gICAgdGhpcy5yZXBvcnRDb21tZW50ID0gdW5kZWZpbmVkO1xuICAgIHRoaXMucmVwb3J0UmFuayA9IHJhbms7XG4gICAgdGhpcy5zaG93UmVwb3J0ID0gdHJ1ZVxuXG4gICAgdGhpcy5jaGF0U2VydmljZS5jaGF0SGlzdG9yeSFbdGhpcy5fcmVtYXBJbmRleEluQ2hhdEhpc3RvcnkocmFuayldLmFkZGl0aW9uYWxQcm9wZXJ0aWVzLiRkaXNsaWtlZCA9IHRydWU7XG4gICAgdGhpcy5jaGF0U2VydmljZS5jaGF0SGlzdG9yeSFbdGhpcy5fcmVtYXBJbmRleEluQ2hhdEhpc3RvcnkocmFuayldLmFkZGl0aW9uYWxQcm9wZXJ0aWVzLiRsaWtlZCA9IGZhbHNlO1xuICAgIHRoaXMuX3VwZGF0ZUNoYXRIaXN0b3J5KCk7XG4gIH1cblxuICBwcml2YXRlIF91cGRhdGVDaGF0SGlzdG9yeSgpOiB2b2lkIHtcbiAgICB0aGlzLm1lc3NhZ2VzJC5uZXh0KHRoaXMuY2hhdFNlcnZpY2UuY2hhdEhpc3RvcnkpO1xuICAgIGlmICh0aGlzLmNoYXRTZXJ2aWNlLnNhdmVkQ2hhdElkKSB7XG4gICAgICB0aGlzLmNoYXRTZXJ2aWNlLnVwZGF0ZVNhdmVkQ2hhdCh0aGlzLmNoYXRTZXJ2aWNlLnNhdmVkQ2hhdElkLCB1bmRlZmluZWQsIHRoaXMuY2hhdFNlcnZpY2UuY2hhdEhpc3RvcnkpLnN1YnNjcmliZSgpO1xuICAgIH1cbiAgICB0aGlzLmNkci5kZXRlY3RDaGFuZ2VzKCk7XG4gIH1cblxuICAvKipcbiAgICogUmVwb3J0IGFuIGlzc3VlIHJlbGF0ZWQgdG8gdGhlIGFzc2lzdGFudCdzIG1lc3NhZ2UuXG4gICAqL1xuICBzZW5kUmVwb3J0KCk6IHZvaWQge1xuICAgIGNvbnN0IGRldGFpbHMgPSB7XG4gICAgICAnY29tbWVudCc6IHRoaXMucmVwb3J0Q29tbWVudCxcbiAgICAgICdyYW5rJzogdGhpcy5yZXBvcnRSYW5rLFxuICAgIH07XG5cbiAgICAvLyBoaWRlIHRleHQgaW4gY2FzZSBsb2dDb250ZW50IGlzIG5vdCBlbmFibGVkXG4gICAgaWYgKHRoaXMuY29uZmlnLmF1ZGl0U2V0dGluZ3MubG9nQ29udGVudClcbiAgICAgIGRldGFpbHNbJ3RleHQnXSA9IHRoaXMubWVzc2FnZVRvUmVwb3J0IS5jb250ZW50O1xuXG4gICAgaWYgKHRoaXMucmVwb3J0VHlwZSA9PT0gJ2Rpc2xpa2UnKSB7XG4gICAgICBkZXRhaWxzWydyZXBvcnQtdHlwZSddID0gdGhpcy5pc3N1ZVR5cGU7XG4gICAgICB0aGlzLmNoYXRTZXJ2aWNlLmdlbmVyYXRlQXVkaXRFdmVudCgnYXN0LW5lZ2F0aXZlLXJlcG9ydC5zZW5kJywgZGV0YWlscyk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMuY2hhdFNlcnZpY2UuZ2VuZXJhdGVBdWRpdEV2ZW50KCdhc3QtcG9zaXRpdmUtcmVwb3J0LnNlbmQnLCBkZXRhaWxzKTtcbiAgICB9XG4gICAgdGhpcy5ub3RpZmljYXRpb25zU2VydmljZS5zdWNjZXNzKHRoaXMudHJhbnNsb2NvLnRyYW5zbGF0ZSgnY2hhdC5zZW5kUmVwb3J0Tm90aWZpY2F0aW9uJykpO1xuICAgIHRoaXMuc2hvd1JlcG9ydCA9IGZhbHNlO1xuICB9XG5cbiAgLyoqXG4gICAqIENsb3NlIHRoZSByZXBvcnRpbmcgZGlhbG9nLlxuICAgKi9cbiAgaWdub3JlUmVwb3J0KCk6IHZvaWQge1xuICAgIHRoaXMuc2hvd1JlcG9ydCA9IGZhbHNlO1xuICB9XG5cbiAgLyoqXG4gICAqIEhhbmRsZSB0aGUgY2xpY2sgb24gYSByZWZlcmVuY2UncyAnb3BlbiBwcmV2aWV3Jy5cbiAgICogQHBhcmFtIGRhdGFcbiAgICogQHBhcmFtIGluZGV4IHJhbmsgb2YgdGhlIG1lc3NhZ2VcbiAgICovXG4gIG9wZW5BdHRhY2htZW50UHJldmlldyhkYXRhOiB7IHJlZmVyZW5jZTogQ2hhdENvbnRleHRBdHRhY2htZW50LCBwYXJ0SWQ/OiBudW1iZXIgfSwgcmFuazogbnVtYmVyKSB7XG4gICAgdGhpcy5vcGVuUHJldmlldy5lbWl0KGRhdGEucmVmZXJlbmNlKTtcbiAgICBjb25zdCBpZHggPSB0aGlzLl9yZW1hcEluZGV4SW5DaGF0SGlzdG9yeShyYW5rKTtcbiAgICBjb25zdCBkZXRhaWxzID0ge1xuICAgICAgJ2RvYy1pZCc6IGRhdGEucmVmZXJlbmNlLnJlY29yZElkLFxuICAgICAgJ3NvdXJjZSc6IGRhdGEucmVmZXJlbmNlLnJlY29yZC50cmVlcGF0aCxcbiAgICAgICdjb2xsZWN0aW9uJzogZGF0YS5yZWZlcmVuY2UucmVjb3JkLmNvbGxlY3Rpb24sXG4gICAgICAnaW5kZXgnOiBkYXRhLnJlZmVyZW5jZS5yZWNvcmQuZGF0YWJhc2VhbGlhcyxcbiAgICAgICdyYW5rJzogaWR4XG4gICAgfTtcbiAgICBpZiAoISFkYXRhLnBhcnRJZCkgZGV0YWlsc1sncGFydC1pZCddID0gZGF0YS5wYXJ0SWQ7XG4gICAgdGhpcy5jaGF0U2VydmljZS5nZW5lcmF0ZUF1ZGl0RXZlbnQoJ2FzdC1hdHRhY2htZW50LnByZXZpZXcuY2xpY2snLCBkZXRhaWxzKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBIYW5kbGUgdGhlIGNsaWNrIG9uIGEgcmVmZXJlbmNlJ3MgJ29wZW4gb3JpZ2luYWwgZG9jdW1lbnQnLlxuICAgKiBAcGFyYW0gZGF0YVxuICAgKi9cbiAgb3Blbk9yaWdpbmFsQXR0YWNobWVudChkYXRhOiB7IHJlZmVyZW5jZTogQ2hhdENvbnRleHRBdHRhY2htZW50LCBwYXJ0SWQ/OiBudW1iZXIgfSwgcmFuazogbnVtYmVyKSB7XG4gICAgdGhpcy5vcGVuRG9jdW1lbnQuZW1pdChkYXRhLnJlZmVyZW5jZS5yZWNvcmQpO1xuICAgIGNvbnN0IGlkeCA9IHRoaXMuX3JlbWFwSW5kZXhJbkNoYXRIaXN0b3J5KHJhbmspO1xuICAgIGNvbnN0IGRldGFpbHMgPSB7XG4gICAgICAnZG9jLWlkJzogZGF0YS5yZWZlcmVuY2UucmVjb3JkSWQsXG4gICAgICAnc291cmNlJzogZGF0YS5yZWZlcmVuY2UucmVjb3JkLnRyZWVwYXRoLFxuICAgICAgJ2NvbGxlY3Rpb24nOiBkYXRhLnJlZmVyZW5jZS5yZWNvcmQuY29sbGVjdGlvbixcbiAgICAgICdpbmRleCc6IGRhdGEucmVmZXJlbmNlLnJlY29yZC5kYXRhYmFzZWFsaWFzLFxuICAgICAgJ3JhbmsnOiBpZHhcbiAgICB9O1xuICAgIGlmICghIWRhdGEucGFydElkKSBkZXRhaWxzWydwYXJ0LWlkJ10gPSBkYXRhLnBhcnRJZDtcbiAgICB0aGlzLmNoYXRTZXJ2aWNlLmdlbmVyYXRlQXVkaXRFdmVudCgnYXN0LWF0dGFjaG1lbnQubGluay5jbGljaycsIGRldGFpbHMpO1xuICB9XG5cbiAgLyoqXG4gICAqIEhhbmRsZSB0aGUgY2xpY2sgb24gYSBzdWdnZXN0ZWQgYWN0aW9uLlxuICAgKiBAcGFyYW0gYWN0aW9uIFN1Z2dlc3RlZCBhY3Rpb24uXG4gICAqIEBwYXJhbSBpbmRleCBSYW5rIG9mIHRoZSBtZXNzYWdlIGluIHRoZSBjaGF0SGlzdG9yeSByZWxhdGVkIHRvIHRoZSBzdWdnZXN0ZWQgYWN0aW9uLlxuICAgKi9cbiAgc3VnZ2VzdEFjdGlvbkNsaWNrKGFjdGlvbjogU3VnZ2VzdGVkQWN0aW9uLCBpbmRleDogbnVtYmVyKSB7XG4gICAgdGhpcy5zdWdnZXN0QWN0aW9uLmVtaXQoYWN0aW9uKTtcbiAgICB0aGlzLmNoYXRTZXJ2aWNlLmdlbmVyYXRlQXVkaXRFdmVudCgnYXN0LXN1Z2dlc3RlZC1hY3Rpb24uY2xpY2snLCB7J3RleHQnOiBhY3Rpb24uY29udGVudCwgJ3N1Z2dlc3RlZEFjdGlvbi10eXBlJzogYWN0aW9uLnR5cGV9KVxuICB9XG5cbiAgLyoqXG4gICAqIEl0IGxvb2tzIGZvciB0aGUgZGVidWcgbWVzc2FnZXMgYXZhaWxhYmxlIGluIHRoZSBjdXJyZW50IGdyb3VwIG9mIFwiYXNzaXN0YW50XCIgbWVzc2FnZXMuXG4gICAqIEJ5IGRlc2lnbiwgdGhlIGRlYnVnIG1lc3NhZ2VzIGFyZSBvbmx5IGF2YWlsYWJsZSBpbiB0aGUgZmlyc3QgdmlzaWJsZSBtZXNzYWdlIGFtb25nIHRoZSBncm91cCBcImFzc2lzdGFudFwiIG1lc3NhZ2VzLlxuICAgKiBAcGFyYW0gaW5kZXggVGhlIHJhbmsgb2YgdGhlIG1lc3NhZ2VcbiAgICogQHJldHVybnMgVGhlIGRlYnVnIG1lc3NhZ2VzIGF2YWlsYWJsZSBpbiB0aGUgY3VycmVudCBncm91cCBvZiBcImFzc2lzdGFudFwiIG1lc3NhZ2VzXG4gICAqL1xuICBnZXREZWJ1Z01lc3NhZ2VzKGluZGV4OiBudW1iZXIpOiBEZWJ1Z01lc3NhZ2VbXSB7XG4gICAgLy8gSWYgaXQgaXMgbm90IGFuIGFzc2lzdGFudCBtZXNzYWdlLCByZXR1cm5cbiAgICBpZiAoKHRoaXMubWVzc2FnZXMkLnZhbHVlISlbaW5kZXhdLnJvbGUgIT09ICdhc3Npc3RhbnQnKSB7XG4gICAgICByZXR1cm4gW107XG4gICAgfVxuICAgIC8vIEdldCB0aGUgYXJyYXkgb2YgbWVzc2FnZXMgdXAgdG8gdGhlIGluZGljYXRlZCBpbmRleFxuICAgIGNvbnN0IGFycmF5ID0gdGhpcy5tZXNzYWdlcyQudmFsdWUhLnNsaWNlKDAsIGluZGV4ICsgMSk7XG4gICAgLy8gSWYgaXQgaXMgYW4gYXNzaXN0YW50IG1lc3NhZ2UsIGxvb2sgZm9yIHRoZSBkZWJ1ZyBtZXNzYWdlcyBhdmFpbGFibGUgaW4gdGhlIGN1cnJlbnQgZ3JvdXAgb2YgXCJhc3Npc3RhbnRcIiBtZXNzYWdlc1xuICAgIC8vIEJ5IGRlc2lnbiwgdGhlIGRlYnVnIG1lc3NhZ2VzIGFyZSBvbmx5IGF2YWlsYWJsZSBpbiB0aGUgZmlyc3QgdmlzaWJsZSBtZXNzYWdlIGFtb25nIHRoZSBncm91cCBcImFzc2lzdGFudFwiIG1lc3NhZ2VzLlxuICAgIGNvbnN0IGlkeCA9IHRoaXMuY2hhdFNlcnZpY2UuZmlyc3RWaXNpYmxlQXNzaXN0YW50TWVzc2FnZUluZGV4KGFycmF5KTtcbiAgICBpZiAoaWR4ID4gLTEpIHtcbiAgICAgIHJldHVybiAodGhpcy5tZXNzYWdlcyQudmFsdWUhKVtpZHhdLmFkZGl0aW9uYWxQcm9wZXJ0aWVzLiRkZWJ1ZyB8fCBbXTtcbiAgICB9XG4gICAgcmV0dXJuIFtdO1xuICB9XG5cbiAgLyoqXG4gICAqIEhhbmRsZSB0aGUgY2xpY2sgb24gdGhlICdzaG93IGxvZyBpbmZvJyBidXR0b24gb2YgYSBtZXNzYWdlLlxuICAgKiBAcGFyYW0gaW5kZXggVGhlIHJhbmsgb2YgdGhlIG1lc3NhZ2VcbiAgICovXG4gIHNob3dEZWJ1ZyhpbmRleDogbnVtYmVyKTogdm9pZCB7XG4gICAgdGhpcy5kZWJ1Z01lc3NhZ2VzID0gdGhpcy5nZXREZWJ1Z01lc3NhZ2VzKGluZGV4KTtcbiAgICB0aGlzLnNob3dEZWJ1Z01lc3NhZ2VzID0gdHJ1ZTtcbiAgICB0aGlzLmNkci5kZXRlY3RDaGFuZ2VzKCk7XG4gIH1cblxuICAvKipcbiAgICogVmVyaWZ5IHdoZXRoZXIgdGhlIGN1cnJlbnQgbWVzc2FnZSBpcyBhbiBhc3Npc3RhbnQgbWVzc2FnZSBhbmQgdGhhdCBhbGwgZm9sbG93aW5nIG1lc3NhZ2VzIGFyZSBhc3Npc3RhbnQgb25lc1xuICAgKiBVc2VkIHRvIGtlZXAgdGhlIFwiVmlldyBwcm9ncmVzc1wiIG9wZW5lZCBldmVuIHRob3VnaCB0aGUgYXNzaXN0YW50IGlzIHNlbmRpbmcgYWRkaXRpb25hbCBtZXNzYWdlcyBhZnRlciB0aGUgY3VycmVudCBvbmVcbiAgICogQHBhcmFtIG1lc3NhZ2VzIHRoZSBsaXN0IG9mIGN1cnJlbnQgbWVzc2FnZXNcbiAgICogQHBhcmFtIGluZGV4IHRoZSBpbmRleCBvZiB0aGUgY3VycmVudCBtZXNzYWdlXG4gICAqIEByZXR1cm5zIGlmIHRoaXMgbWVzc2FnZXMgYW5kIHRoZSBmb2xsb3dpbmcgb25lcyAoaWYgYW55KSBhcmUgdGhlIGxhc3Qgb25lc1xuICAgKi9cbiAgaXNBc3Npc3RhbnRMYXN0TWVzc2FnZXMobWVzc2FnZXM6IENoYXRNZXNzYWdlW10sIGluZGV4OiBudW1iZXIpOiBib29sZWFuIHtcbiAgICBmb3IgKGxldCBpID0gaW5kZXg7IGkgPCBtZXNzYWdlcy5sZW5ndGg7IGkrKykge1xuICAgICAgaWYgKG1lc3NhZ2VzW2ldLnJvbGUgIT09ICdhc3Npc3RhbnQnKSByZXR1cm4gZmFsc2U7XG4gICAgfVxuICAgIHJldHVybiB0cnVlO1xuICB9XG5cbiAgLyoqXG4gICAqIENoZWNrcyBpZiB0aGUgZ2l2ZW4gbWVzc2FnZSBpcyBhbiBlbXB0eSBhc3Npc3RhbnQgbWVzc2FnZS5cbiAgICogQW4gZW1wdHkgYXNzaXN0YW50IG1lc3NhZ2UgaXMgZGVmaW5lZCBhcyBhIG1lc3NhZ2Ugd2l0aCB0aGUgcm9sZSAnYXNzaXN0YW50JyxcbiAgICogYW4gZW1wdHkgY29udGVudCwgYW5kIG5vIGFkZGl0aW9uYWwgcHJvcGVydGllcyBzdWNoIGFzIGF0dGFjaG1lbnRzLCBwcm9ncmVzcyxcbiAgICogZGVidWcgaW5mb3JtYXRpb24sIG9yIHN1Z2dlc3RlZCBhY3Rpb25zLlxuICAgKlxuICAgKiBAcGFyYW0gbWVzc2FnZSAtIFRoZSBtZXNzYWdlIHRvIGNoZWNrLlxuICAgKiBAcmV0dXJucyBgdHJ1ZWAgaWYgdGhlIG1lc3NhZ2UgaXMgYW4gZW1wdHkgYXNzaXN0YW50IG1lc3NhZ2UsIGBmYWxzZWAgb3RoZXJ3aXNlLlxuICAgKi9cbiAgaXNFbXB0eUFzc2lzdGFudE1lc3NhZ2UobWVzc2FnZTogQ2hhdE1lc3NhZ2UgfCB1bmRlZmluZWQpOiBib29sZWFuIHtcbiAgICBpZiAoXG4gICAgICBtZXNzYWdlPy5yb2xlID09PSAnYXNzaXN0YW50J1xuICAgICAgJiYgKFxuICAgICAgICAvLyBMZWdhY3kgbWVzc2FnZSB0eXBlXG4gICAgICAgICh0eXBlb2YgbWVzc2FnZT8uY29udGVudCA9PT0gJ3N0cmluZycgJiYgbWVzc2FnZT8uY29udGVudCA9PT0gXCJcIilcbiAgICAgICAgLy8gTmV3IG1lc3NhZ2UgdHlwZVxuICAgICAgICAvLyAtIFRleHRcbiAgICAgICAgfHwgKChtZXNzYWdlPy5jb250ZW50IGFzIFJhd01lc3NhZ2VDb250ZW50KT8uWzBdIGFzIFRleHRNZXNzYWdlQ29udGVudCk/LnRleHQgPT09IFwiXCJcbiAgICAgICAgLy8gVE9ETzogaW1hZ2UgYW5kIHZpZGVvIG1lc3NhZ2UgdHlwZXMgaHR0cHM6Ly9zaW5lcXVhLmF0bGFzc2lhbi5uZXQvYnJvd3NlL0VTLTI1OTQwXG4gICAgICApXG4gICAgICAmJiAhbWVzc2FnZT8uYWRkaXRpb25hbFByb3BlcnRpZXM/LiRhdHRhY2htZW50XG4gICAgICAmJiAhbWVzc2FnZT8uYWRkaXRpb25hbFByb3BlcnRpZXM/LiRwcm9ncmVzc1xuICAgICAgJiYgIW1lc3NhZ2U/LmFkZGl0aW9uYWxQcm9wZXJ0aWVzPy4kZGVidWdcbiAgICAgICYmICFtZXNzYWdlPy5hZGRpdGlvbmFsUHJvcGVydGllcz8uJHN1Z2dlc3RlZEFjdGlvblxuICAgICkge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICAgIHJldHVybiBmYWxzZTtcbiAgfVxufVxuIiwiPG5nLWNvbnRhaW5lciAqbmdJZj1cIiFpbml0aWFsaXphdGlvbkVycm9yXCI+XG4gIDxkaXYgKm5nSWY9XCJtZXNzYWdlcyQgfCBhc3luYyBhcyBtZXNzYWdlczsgZWxzZSBsb2FkaW5nVHBsIHx8IGxvYWRpbmdUcGxEZWZhdWx0XCIgY2xhc3M9XCJoLTEwMCBkLWZsZXggZmxleC1jb2x1bW5cIj5cbiAgICA8IS0tIFRva2VuIGNvbnN1bXB0aW9uIC0tPlxuICAgIDxkaXYgY2xhc3M9XCJtcy0xXCIgKm5nSWY9XCJjb25maWc/Lmdsb2JhbFNldHRpbmdzPy5kaXNwbGF5VXNlclF1b3RhQ29uc3VtcHRpb24gfHwgY29uZmlnPy5nbG9iYWxTZXR0aW5ncz8uZGlzcGxheUNoYXRUb2tlbnNDb25zdW1wdGlvblwiPlxuICAgICAgPG5nLWNvbnRhaW5lciAqbmdUZW1wbGF0ZU91dGxldD1cInRva2VuQ29uc3VtcHRpb25UcGwgfHwgZGVmYXVsdFRva2VuQ29uc3VtcHRpb25UcGw7IGNvbnRleHQ6IHsgJGltcGxpY2l0OiBpbnN0YW5jZUlkIH1cIj48L25nLWNvbnRhaW5lcj5cbiAgICA8L2Rpdj5cblxuICAgIDwhLS0gQ2hhdCBNZXNzYWdlcyAtLT5cbiAgICA8dWwgY2xhc3M9XCJkLWZsZXggZmxleC1jb2x1bW4gbGlzdC11bnN0eWxlZCBnYXAtMyBvdmVyZmxvdy1hdXRvIGZsZXgtZ3Jvdy0xIHBlLTIgcGItMlwiICNtZXNzYWdlTGlzdD5cbiAgICAgIDxuZy1jb250YWluZXIgKm5nRm9yPVwibGV0IG1lc3NhZ2Ugb2YgbWVzc2FnZXM7IGxldCBpbmRleCA9IGluZGV4OyBsZXQgbGFzdCA9IGxhc3RcIj5cbiAgICAgICAgPCEtLSBSZWd1bGFyIG1lc3NhZ2VzIC0tPlxuICAgICAgICA8bGkgY2xhc3M9XCJsaXN0LWdyb3VwLWl0ZW1cIlxuICAgICAgICAgICpuZ0lmPVwibWVzc2FnZS5hZGRpdGlvbmFsUHJvcGVydGllcy5kaXNwbGF5ICYmICFpc0VtcHR5QXNzaXN0YW50TWVzc2FnZShtZXNzYWdlKVwiXG4gICAgICAgICAgW3N0eWxlLi0tYnMtbGlzdC1ncm91cC1pdGVtLXBhZGRpbmcteS5yZW1dPVwiJzAuNidcIlxuICAgICAgICAgIFtjbGFzcy5vcGFjaXR5LTUwXT1cIm1lc3NhZ2VUb0VkaXQgJiYgKG1lc3NhZ2VUb0VkaXQgPCAoaW5kZXggKyAxKSlcIj5cbiAgICAgICAgICA8c3EtY2hhdC1tZXNzYWdlXG4gICAgICAgICAgICBbY2xhc3Muc3EtdXNlci1tZXNzYWdlXT1cIm1lc3NhZ2Uucm9sZSA9PT0gJ3VzZXInXCJcbiAgICAgICAgICAgIFtjbGFzcy5sYXN0LW1lc3NhZ2VdPVwibGFzdFwiXG4gICAgICAgICAgICBbbWVzc2FnZV09XCJtZXNzYWdlXCJcbiAgICAgICAgICAgIFtjb252ZXJzYXRpb25dPVwibWVzc2FnZXNcIlxuICAgICAgICAgICAgW3N1Z2dlc3RlZEFjdGlvbnNdPVwibGFzdCA/IG1lc3NhZ2UuYWRkaXRpb25hbFByb3BlcnRpZXMuJHN1Z2dlc3RlZEFjdGlvbiA6IHVuZGVmaW5lZFwiXG4gICAgICAgICAgICBbYXNzaXN0YW50TWVzc2FnZUljb25dPVwiYXNzaXN0YW50TWVzc2FnZUljb25cIlxuICAgICAgICAgICAgW3VzZXJNZXNzYWdlSWNvbl09XCJ1c2VyTWVzc2FnZUljb25cIlxuICAgICAgICAgICAgW2Nvbm5lY3Rpb25FcnJvck1lc3NhZ2VJY29uXT1cImNvbm5lY3Rpb25FcnJvck1lc3NhZ2VJY29uXCJcbiAgICAgICAgICAgIFtzZWFyY2hXYXJuaW5nTWVzc2FnZUljb25dPVwic2VhcmNoV2FybmluZ01lc3NhZ2VJY29uXCJcbiAgICAgICAgICAgIFtzdHJlYW1pbmddPVwiKGNoYXRTZXJ2aWNlLnN0cmVhbWluZyQgfCBhc3luYykgJiYgKGxhc3QgfHwgaXNBc3Npc3RhbnRMYXN0TWVzc2FnZXMobWVzc2FnZXMsIGluZGV4KSlcIlxuICAgICAgICAgICAgW2NhbkVkaXRdPVwiKGNoYXRTZXJ2aWNlLnN0cmVhbWluZyQgfCBhc3luYykgPT09IGZhbHNlICYmIG1lc3NhZ2VUb0VkaXQgPT09IHVuZGVmaW5lZCAmJiBtZXNzYWdlLnJvbGUgPT09ICd1c2VyJ1wiXG4gICAgICAgICAgICBbY2FuQ29weV09XCIoKGNoYXRTZXJ2aWNlLnN0cmVhbWluZyQgfCBhc3luYykgPT09IGZhbHNlIHx8ICFsYXN0KSAmJiBtZXNzYWdlVG9FZGl0ID09PSB1bmRlZmluZWQgJiYgbWVzc2FnZS5yb2xlICE9PSAnY29ubmVjdGlvbi1lcnJvcicgJiYgbWVzc2FnZS5yb2xlICE9PSAnc2VhcmNoLXdhcm5pbmcnXCJcbiAgICAgICAgICAgIFtjYW5MaWtlXT1cIigoY2hhdFNlcnZpY2Uuc3RyZWFtaW5nJCB8IGFzeW5jKSA9PT0gZmFsc2UgfHwgIWxhc3QpICYmIG1lc3NhZ2Uucm9sZSA9PT0gJ2Fzc2lzdGFudCdcIlxuICAgICAgICAgICAgW2NhbkRpc2xpa2VdPVwiKChjaGF0U2VydmljZS5zdHJlYW1pbmckIHwgYXN5bmMpID09PSBmYWxzZSB8fCAhbGFzdCkgJiYgbWVzc2FnZS5yb2xlID09PSAnYXNzaXN0YW50J1wiXG4gICAgICAgICAgICBbY2FuRGVidWddPVwiKCgoY2hhdFNlcnZpY2Uuc3RyZWFtaW5nJCB8IGFzeW5jKSA9PT0gZmFsc2UgJiYgbGFzdCkgfHwgKCFsYXN0ICYmIG1lc3NhZ2VzW2luZGV4KzFdLnJvbGUgIT09ICdhc3Npc3RhbnQnKSkgJiYgbWVzc2FnZS5yb2xlID09PSAnYXNzaXN0YW50JyAmJiAoZ2V0RGVidWdNZXNzYWdlcyhpbmRleCkubGVuZ3RoID4gMCkgJiYgKChpc0FkbWluT3JEZWxldGVkQWRtaW4gfHwgKGNoYXRTZXJ2aWNlLnVzZXJPdmVycmlkZSQgfCBhc3luYykpICYmIGNvbmZpZz8uZGVmYXVsdFZhbHVlcy5kZWJ1ZylcIlxuICAgICAgICAgICAgW2NhblJlZ2VuZXJhdGVdPVwiKGNoYXRTZXJ2aWNlLnN0cmVhbWluZyQgfCBhc3luYykgPT09IGZhbHNlICAmJiAobGFzdCB8fCAoIWxhc3QgJiYgbWVzc2FnZXNbaW5kZXgrMV0ucm9sZSAhPT0gJ2Fzc2lzdGFudCcpKSAgJiYgbWVzc2FnZS5yb2xlID09PSAnYXNzaXN0YW50JyAmJiBtZXNzYWdlVG9FZGl0ID09PSB1bmRlZmluZWRcIlxuICAgICAgICAgICAgKGVkaXQpPVwiZWRpdE1lc3NhZ2UoaW5kZXgpXCJcbiAgICAgICAgICAgIChjb3B5KT1cImNvcHlNZXNzYWdlKGluZGV4KVwiXG4gICAgICAgICAgICAocmVnZW5lcmF0ZSk9XCJyZWdlbmVyYXRlTWVzc2FnZShpbmRleClcIlxuICAgICAgICAgICAgKG9wZW5Eb2N1bWVudCk9XCJvcGVuT3JpZ2luYWxBdHRhY2htZW50KCRldmVudCwgaW5kZXgpXCJcbiAgICAgICAgICAgIChvcGVuUHJldmlldyk9XCJvcGVuQXR0YWNobWVudFByZXZpZXcoJGV2ZW50LCBpbmRleClcIlxuICAgICAgICAgICAgKHN1Z2dlc3RBY3Rpb24pPVwic3VnZ2VzdEFjdGlvbkNsaWNrKCRldmVudCwgaW5kZXgpXCJcbiAgICAgICAgICAgIChsaWtlKT1cIm9uTGlrZShtZXNzYWdlLCBpbmRleClcIlxuICAgICAgICAgICAgKGRpc2xpa2UpPVwib25EaXNsaWtlKG1lc3NhZ2UsIGluZGV4KVwiXG4gICAgICAgICAgICAoZGVidWcpPVwic2hvd0RlYnVnKGluZGV4KVwiPlxuICAgICAgICAgIDwvc3EtY2hhdC1tZXNzYWdlPlxuICAgICAgICA8L2xpPlxuICAgICAgPC9uZy1jb250YWluZXI+XG4gICAgICA8IS0tIExvYWRpbmcgc3Bpbm5lciAtLT5cbiAgICAgIDxsaSAqbmdJZj1cIihsb2FkaW5nJCB8IGFzeW5jKSA9PT0gdHJ1ZVwiPlxuICAgICAgICA8bmctY29udGFpbmVyICpuZ1RlbXBsYXRlT3V0bGV0PVwibG9hZGluZ1RwbCB8fCBsb2FkaW5nVHBsRGVmYXVsdFwiPjwvbmctY29udGFpbmVyPlxuICAgICAgPC9saT5cbiAgICA8L3VsPlxuXG4gICAgPCEtLSBSZXBvcnRpbmcgYSBmZWVkYmFjayBmb3JtIC0tPlxuICAgIDxkaXYgY2xhc3M9XCJpc3N1ZS1yZXBvcnQgcC0zIHJvdW5kZWQtbGdcIiAqbmdJZj1cInNob3dSZXBvcnRcIj5cbiAgICAgIDxuZy1jb250YWluZXIgKm5nVGVtcGxhdGVPdXRsZXQ9XCJyZXBvcnRUcGwgfHwgcmVwb3J0VHBsRGVmYXVsdDsgY29udGV4dDogeyAkaW1wbGljaXQ6IG1lc3NhZ2VUb1JlcG9ydCwgcmFuazogcmVwb3J0UmFuaywgdHlwZTogcmVwb3J0VHlwZSB9XCI+PC9uZy1jb250YWluZXI+XG4gICAgPC9kaXY+XG5cbiAgICA8IS0tIFVzZXIgdGV4dCBpbnB1dCAtLT5cbiAgICBAaWYgKCFzaG93UmVwb3J0KSB7XG4gICAgICA8ZGl2IGNsYXNzPVwidXNlci1pbnB1dCBtdC1hdXRvXCI+XG4gICAgICAgIDxkaXYgY2xhc3M9XCJweS0yXCI+XG4gICAgICAgICAgPGRpdiBbaGlkZGVuXT1cIiFpc0Nvbm5lY3RlZFwiPlxuICAgICAgICAgICAgPG5nLWNvbnRhaW5lciAqbmdJZj1cImVuYWJsZWRVc2VySW5wdXRcIiBbbmdUZW1wbGF0ZU91dGxldF09XCJpbnB1dFRwbFwiPjwvbmctY29udGFpbmVyPlxuICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgIDwhLS0gUmV0cnkgYnV0dG9uIC0tPlxuICAgICAgICAgIDwhLS0gaGlkZGVuIGF0dHJpYnV0ZSBpcyBpbiBjb25mbGljdCB3aXRoIGEgY3NzIHJ1bGUgZGlzcGxheTogZmxleCAtLT5cbiAgICAgICAgICBAaWYoIWlzQ29ubmVjdGVkKXtcbiAgICAgICAgICAgIDxidXR0b24gY2xhc3M9XCJidG4gbWItNCBhc3QtZXJyb3IgYXN0LWJ0biBzcS1yZXRyeVwiIChjbGljayk9XCJyZXRyeUZldGNoKClcIj5cbiAgICAgICAgICAgICAgPHNwYW4+e3sgJ2NoYXQudHJ5QWdhaW4nIHwgdHJhbnNsb2NvIH19PC9zcGFuPlxuICAgICAgICAgICAgICA8c3BhbiAqbmdJZj1cInJldHJpYWxBdHRlbXB0c1wiIGNsYXNzPVwibXMtMiBhdHRlbXB0c1wiPnt7IHJldHJpYWxBdHRlbXB0cyB9fTwvc3Bhbj5cbiAgICAgICAgICAgIDwvYnV0dG9uPlxuICAgICAgICAgIH1cbiAgICAgICAgICA8ZGl2IGNsYXNzPVwidGV4dC1lbmQgc21hbGwgdGV4dC1tdXRlZCBweC0zXCIgKm5nSWY9XCIhIWNvbmZpZz8uZ2xvYmFsU2V0dGluZ3M/LmRpc2NsYWltZXJcIj5cbiAgICAgICAgICAgIHt7IGNvbmZpZz8uZ2xvYmFsU2V0dGluZ3M/LmRpc2NsYWltZXIgfCB0cmFuc2xvY28gfX1cbiAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgPC9kaXY+XG4gICAgICA8L2Rpdj5cbiAgICB9XG5cbiAgICA8IS0tIEZsb2F0aW5nIHNjcm9sbCBidXR0b24gLS0+XG4gICAgPGRpdiAqbmdJZj1cIiFpc0F0Qm90dG9tICYmICFzaG93UmVwb3J0XCIgY2xhc3M9XCJzcS1mbG9hdGluZy1zY3JvbGxcIiBbbmdDbGFzc109XCJlbmFibGVkVXNlcklucHV0ID8gJ3NxLWZsb2F0aW5nLXNjcm9sbC0td2hlbi11c2VyLWlucHV0JyA6ICdzcS1mbG9hdGluZy1zY3JvbGwtLXdpdGhvdXQtdXNlci1pbnB1dCdcIj5cbiAgICAgIDxidXR0b24gY2xhc3M9XCJidG4gc2hhZG93XCIgKGNsaWNrKT1cInNjcm9sbERvd24oKVwiIGFyaWEtbGFiZWw9XCJTY3JvbGwgZG93blwiPlxuICAgICAgICA8aSBjbGFzcz1cImZhcyBmYS1hbmdsZS1kb3VibGUtZG93blwiPjwvaT5cbiAgICAgIDwvYnV0dG9uPlxuICAgIDwvZGl2PlxuICA8L2Rpdj5cbjwvbmctY29udGFpbmVyPlxuXG48IS0tIE5HIFRFTVBMQVRFUy0tPlxuXG48bmctdGVtcGxhdGUgI2xvYWRpbmdUcGxEZWZhdWx0PlxuICA8ZGl2IGNsYXNzPVwic3Bpbm5lci1ncm93IHRleHQtcHJpbWFyeSBkLWJsb2NrIG14LWF1dG8gbXktNVwiIHJvbGU9XCJzdGF0dXNcIj5cbiAgICA8c3BhbiBjbGFzcz1cInZpc3VhbGx5LWhpZGRlblwiPnt7ICdjaGF0LmxvYWRpbmcnIHwgdHJhbnNsb2NvIH19PC9zcGFuPlxuICA8L2Rpdj5cbjwvbmctdGVtcGxhdGU+XG5cbjxuZy10ZW1wbGF0ZSAjaW5wdXRUcGw+XG4gIDxkaXYgY2xhc3M9XCJweC0zIHB5LTFcIj5cbiAgICA8ZGl2IGNsYXNzPVwiYXN0LWlucHV0LWNvbnRhaW5lclwiPlxuICAgICAgPGJ1dHRvbiBkaXNhYmxlZCBjbGFzcz1cImJ0biBidG4tbGlnaHRcIiBhcmlhLWxhYmVsPVwic2VhcmNoXCI+XG4gICAgICAgIDxpIGNsYXNzPVwiZmFzIGZhLXNlYXJjaFwiPjwvaT5cbiAgICAgIDwvYnV0dG9uPlxuICAgICAgPHRleHRhcmVhICNxdWVzdGlvbklucHV0IHJvd3M9XCIxXCJcbiAgICAgICAgdHlwZT1cInRleHRcIiBjbGFzcz1cImZvcm0tY29udHJvbFwiXG4gICAgICAgIFtwbGFjZWhvbGRlcl09XCInY2hhdC5hc2tTb21ldGhpbmcnIHwgdHJhbnNsb2NvXCIgYXV0b2ZvY3VzXG4gICAgICAgIFsobmdNb2RlbCldPVwicXVlc3Rpb25cIlxuICAgICAgICAoa2V5dXApPVwib25LZXlVcCgkZXZlbnQpXCJcbiAgICAgICAgKGtleWRvd24pPVwiY2FsY3VsYXRlSGVpZ2h0KCRldmVudClcIlxuICAgICAgICBbZGlzYWJsZWRdPVwiKGxvYWRpbmckIHwgYXN5bmMpIHx8IChjaGF0U2VydmljZS5zdHJlYW1pbmckIHwgYXN5bmMpIHx8IChjaGF0U2VydmljZS5zdG9wcGluZ0dlbmVyYXRpb24kIHwgYXN5bmMpXCI+XG4gICAgICA8L3RleHRhcmVhPlxuICAgICAgPGRpdiBpZD1cImNoYXQtYWN0aW9uc1wiIGNsYXNzPVwiZC1mbGV4IGdhcC0yXCI+XG4gICAgICAgIDxidXR0b25cbiAgICAgICAgICAqbmdJZj1cIihjaGF0U2VydmljZS5zdHJlYW1pbmckIHwgYXN5bmMpID09PSBmYWxzZSAmJiAobG9hZGluZyQgfCBhc3luYykgPT09IGZhbHNlICYmIChjaGF0U2VydmljZS5zdG9wcGluZ0dlbmVyYXRpb24kIHwgYXN5bmMpID09PSBmYWxzZVwiXG4gICAgICAgICAgdHlwZT1cImJ1dHRvblwiXG4gICAgICAgICAgY2xhc3M9XCJidG4gYnRuLWxpZ2h0XCJcbiAgICAgICAgICBhcmlhLWxhYmVsPVwiU2VuZCBtZXNzYWdlXCJcbiAgICAgICAgICBbc3FUb29sdGlwXT1cIidjaGF0LnNlbmRNZXNzYWdlJyB8IHRyYW5zbG9jb1wiXG4gICAgICAgICAgKGNsaWNrKT1cInN1Ym1pdFF1ZXN0aW9uKClcIj5cbiAgICAgICAgICA8aSBjbGFzcz1cImZhcyBmYS1wYXBlci1wbGFuZVwiPjwvaT5cbiAgICAgICAgPC9idXR0b24+XG4gICAgICAgIDxidXR0b25cbiAgICAgICAgICAqbmdJZj1cIm1lc3NhZ2VUb0VkaXRcIlxuICAgICAgICAgIGFyaWEtbGFiZWw9XCJDYW5jZWwgZWRpdGlvblwiXG4gICAgICAgICAgdHlwZT1cImJ1dHRvblwiXG4gICAgICAgICAgY2xhc3M9XCJidG4gYnRuLWxpZ2h0XCJcbiAgICAgICAgICBbc3FUb29sdGlwXT1cIidjaGF0LmNhbmNlbEVkaXRpb24nIHwgdHJhbnNsb2NvXCJcbiAgICAgICAgICAoY2xpY2spPVwibWVzc2FnZVRvRWRpdCA9IHVuZGVmaW5lZDsgcXVlc3Rpb24gPSAnJ1wiPlxuICAgICAgICAgIDxpIGNsYXNzPVwiZmFzIGZhLXVuZG8tYWx0XCI+PC9pPlxuICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgPHNwYW4gKm5nSWY9XCIoY2hhdFNlcnZpY2Uuc3RyZWFtaW5nJCB8IGFzeW5jKSAmJiAoY2hhdFNlcnZpY2Uuc3RvcHBpbmdHZW5lcmF0aW9uJCB8IGFzeW5jKSA9PT0gZmFsc2VcIiBjbGFzcz1cInByb2Nlc3NpbmdcIj5cbiAgICAgICAgICB7eyAnY2hhdC5nZW5lcmF0aW5nJyB8IHRyYW5zbG9jbyB9fTxpIGNsYXNzPVwiZmFzIGZhLXNwaW5uZXIgZmEtcHVsc2VcIj48L2k+XG4gICAgICAgIDwvc3Bhbj5cbiAgICAgICAgPHNwYW4gKm5nSWY9XCIoY2hhdFNlcnZpY2Uuc3RvcHBpbmdHZW5lcmF0aW9uJCB8IGFzeW5jKVwiIGNsYXNzPVwicHJvY2Vzc2luZ1wiPlxuICAgICAgICAgIHt7ICdjaGF0LnN0b3BwaW5nJyB8IHRyYW5zbG9jbyB9fTxpIGNsYXNzPVwiZmFzIGZhLXNwaW5uZXIgZmEtcHVsc2VcIj48L2k+XG4gICAgICAgIDwvc3Bhbj5cbiAgICAgICAgPGJ1dHRvblxuICAgICAgICAgICpuZ0lmPVwiKGNoYXRTZXJ2aWNlLnN0cmVhbWluZyQgfCBhc3luYykgJiYgKGNoYXRTZXJ2aWNlLnN0b3BwaW5nR2VuZXJhdGlvbiQgfCBhc3luYykgPT09IGZhbHNlXCJcbiAgICAgICAgICB0eXBlPVwiYnV0dG9uXCJcbiAgICAgICAgICBjbGFzcz1cImJ0biBidG4tbGlnaHRcIlxuICAgICAgICAgIGFyaWEtbGFiZWw9XCJTdG9wIGdlbmVyYXRpbmdcIlxuICAgICAgICAgIFtzcVRvb2x0aXBdPVwiJ2NoYXQuc3RvcEdlbmVyYXRpb24nIHwgdHJhbnNsb2NvXCJcbiAgICAgICAgICAoY2xpY2spPVwic3RvcEdlbmVyYXRpb24oKVwiPlxuICAgICAgICAgIDxpIGNsYXNzPVwiZmFzIGZhLXN0b3BcIj48L2k+XG4gICAgICAgIDwvYnV0dG9uPlxuICAgICAgPC9kaXY+XG4gICAgPC9kaXY+XG4gIDwvZGl2PlxuPC9uZy10ZW1wbGF0ZT5cblxuPG5nLXRlbXBsYXRlICNyZXBvcnRUcGxEZWZhdWx0IGxldC1tZXNzYWdlIGxldC1yYW5rPVwicmFua1wiIGxldC10eXBlPVwidHlwZVwiPlxuICA8ZGl2IGNsYXNzPVwicHgtM1wiPlxuICAgIDxuZy1jb250YWluZXIgKm5nSWY9XCJ0eXBlID09PSAnZGlzbGlrZSdcIj5cbiAgICAgIDxoNT57eyAnY2hhdC5pc3N1ZVR5cGUnIHwgdHJhbnNsb2NvIH19PC9oNT5cbiAgICAgIDxzZWxlY3QgY2xhc3M9XCJmb3JtLXNlbGVjdCBtYi00XCIgWyhuZ01vZGVsKV09XCJpc3N1ZVR5cGVcIj5cbiAgICAgICAgPG9wdGlvbiBbdmFsdWVdPVwiJydcIj57eyAnY2hhdC5jaG9vc2VJc3N1ZVR5cGUnIHwgdHJhbnNsb2NvIH19PC9vcHRpb24+XG4gICAgICAgIDxvcHRpb24gKm5nRm9yPVwibGV0IHR5cGUgb2YgKGlzc3VlVHlwZXMgPz8gZGVmYXVsdElzc3VlVHlwZXMpXCIgW3ZhbHVlXT1cInR5cGVcIj57eyB0eXBlIHwgdHJhbnNsb2NvIH19PC9vcHRpb24+XG4gICAgICA8L3NlbGVjdD5cbiAgICAgIDxoNT57eyAnY2hhdC5hc2tVbmxpa2VSZWFzb25zJyB8IHRyYW5zbG9jbyB9fTwvaDU+XG4gICAgPC9uZy1jb250YWluZXI+XG4gICAgPG5nLWNvbnRhaW5lciAqbmdJZj1cInR5cGUgPT09ICdsaWtlJ1wiPlxuICAgICAgPGg1Pnt7ICdjaGF0LmFza0xpa2VSZWFzb25zJyB8IHRyYW5zbG9jbyB9fTwvaDU+XG4gICAgPC9uZy1jb250YWluZXI+XG4gICAgPHRleHRhcmVhIGNsYXNzPVwiZm9ybS1jb250cm9sIGJvcmRlciBib3JkZXItbmV1dHJhbC0yMDBcIiBbKG5nTW9kZWwpXT1cInJlcG9ydENvbW1lbnRcIiBbcGxhY2Vob2xkZXJdPVwiJ2NoYXQud3JpdGVDb21tZW50JyB8IHRyYW5zbG9jb1wiPjwvdGV4dGFyZWE+XG4gICAgPGRpdiBjbGFzcz1cImQtZmxleCBmbGV4LXJvdy1yZXZlcnNlIGdhcC0xIG10LTJcIj5cbiAgICAgIDxidXR0b24gY2xhc3M9XCJidG4gYnRuLXByaW1hcnlcIiBbZGlzYWJsZWRdPVwidHlwZSA9PT0gJ2Rpc2xpa2UnICYmICFpc3N1ZVR5cGVcIiAoY2xpY2spPVwic2VuZFJlcG9ydCgpXCI+e3sgJ2NoYXQuc2VuZCcgfCB0cmFuc2xvY28gfX08L2J1dHRvbj5cbiAgICAgIDxidXR0b24gY2xhc3M9XCJidG4gYnRuLWxpZ2h0XCIgKGNsaWNrKT1cImlnbm9yZVJlcG9ydCgpXCI+e3sgJ2NoYXQuZG9Ob3RTZW5kJyB8IHRyYW5zbG9jbyB9fTwvYnV0dG9uPlxuICAgIDwvZGl2PlxuICA8L2Rpdj5cbjwvbmctdGVtcGxhdGU+XG5cbjxuZy10ZW1wbGF0ZSAjZGVmYXVsdFRva2VuQ29uc3VtcHRpb25UcGwgbGV0LWluc3RhbmNlSWQ+XG4gIDxzcS10b2tlbi1wcm9ncmVzcy1iYXJcbiAgICBbaW5zdGFuY2VJZF09XCJpbnN0YW5jZUlkXCI+XG4gIDwvc3EtdG9rZW4tcHJvZ3Jlc3MtYmFyPlxuPC9uZy10ZW1wbGF0ZT5cblxuPGRpdiBjbGFzcz1cImRlYnVnLW1lc3NhZ2VzXCIgW2NsYXNzLmRpc3BsYXllZF09XCJzaG93RGVidWdNZXNzYWdlc1wiPlxuICA8YnV0dG9uICpuZ0lmPVwic2hvd0RlYnVnTWVzc2FnZXNcIiBjbGFzcz1cImJ0biBidG4tbGlnaHQgc2hhZG93IGJhY2stYnRuXCIgKGNsaWNrKT1cInNob3dEZWJ1Z01lc3NhZ2VzPWZhbHNlXCIgYXJpYS1sYWJlbD1cIkhpZGUgZGVidWcgbWVzc2FnZXNcIj5cbiAgICA8aSBjbGFzcz1cImZhcyBmYS1jaGV2cm9uLXJpZ2h0XCI+PC9pPlxuICA8L2J1dHRvbj5cbiAgPG5nLWNvbnRhaW5lciAqbmdUZW1wbGF0ZU91dGxldD1cImRlYnVnTWVzc2FnZXNUcGwgfHwgZGVmYXVsdERlYnVnTWVzc2FnZXNUcGw7IGNvbnRleHQ6IHsgJGltcGxpY2l0OiBkZWJ1Z01lc3NhZ2VzIH1cIj5cbiAgPC9uZy1jb250YWluZXI+XG48L2Rpdj5cblxuPG5nLXRlbXBsYXRlICNkZWZhdWx0RGVidWdNZXNzYWdlc1RwbCBsZXQtZGVidWdNZXNzYWdlcz5cbiAgPHNxLWRlYnVnLW1lc3NhZ2UgW2RhdGFdPVwiZGVidWdNZXNzYWdlc1wiPjwvc3EtZGVidWctbWVzc2FnZT5cbjwvbmctdGVtcGxhdGU+XG4iXX0=
1064
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2hhdC5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9wcm9qZWN0cy9hc3Npc3RhbnQvY2hhdC9jaGF0LmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uL3Byb2plY3RzL2Fzc2lzdGFudC9jaGF0L2NoYXQuY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBQy9DLE9BQU8sRUFBRSx1QkFBdUIsRUFBRSxpQkFBaUIsRUFBRSxTQUFTLEVBQUUsWUFBWSxFQUFjLFlBQVksRUFBRSxLQUFLLEVBQWdDLE1BQU0sRUFBOEIsU0FBUyxFQUFFLE1BQU0sRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUMxTixPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDN0MsT0FBTyxFQUFFLGFBQWEsRUFBRSxnQkFBZ0IsRUFBRSxxQkFBcUIsRUFBRSxNQUFNLG9CQUFvQixDQUFDO0FBQzVGLE9BQU8sRUFBaUIsa0JBQWtCLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUN2RSxPQUFPLEVBQUUsZUFBZSxFQUFFLFlBQVksRUFBRSxhQUFhLEVBQUUsTUFBTSxFQUFFLFNBQVMsRUFBRSxLQUFLLEVBQUUsRUFBRSxFQUFFLFNBQVMsRUFBRSxJQUFJLEVBQUUsR0FBRyxFQUFFLE1BQU0sTUFBTSxDQUFDO0FBRXhILE9BQU8sRUFBbUMsSUFBSSxFQUFFLGVBQWUsRUFBRSxlQUFlLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUUxRyxPQUFPLEVBQUUsb0JBQW9CLEVBQUUsTUFBTSx1Q0FBdUMsQ0FBQztBQUM3RSxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDN0MsT0FBTyxFQUFFLGNBQWMsRUFBRSxNQUFNLHVCQUF1QixDQUFDO0FBQ3ZELE9BQU8sRUFBRSxxQkFBcUIsRUFBRSxNQUFNLHlDQUF5QyxDQUFD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dUJBQUMsa0JBQWtCO2dCQUV2QixTQUFTO3NCQUFqQixLQUFLIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQ29tbW9uTW9kdWxlIH0gZnJvbSBcIkBhbmd1bGFyL2NvbW1vblwiO1xuaW1wb3J0IHsgQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3ksIENoYW5nZURldGVjdG9yUmVmLCBDb21wb25lbnQsIENvbnRlbnRDaGlsZCwgRWxlbWVudFJlZiwgRXZlbnRFbWl0dGVyLCBJbnB1dCwgT25DaGFuZ2VzLCBPbkRlc3Ryb3ksIE9uSW5pdCwgT3V0cHV0LCBTaW1wbGVDaGFuZ2VzLCBUZW1wbGF0ZVJlZiwgVmlld0NoaWxkLCBpbmplY3QgfSBmcm9tIFwiQGFuZ3VsYXIvY29yZVwiO1xuaW1wb3J0IHsgRm9ybXNNb2R1bGUgfSBmcm9tIFwiQGFuZ3VsYXIvZm9ybXNcIjtcbmltcG9ydCB7IFRyYW5zbG9jb1BpcGUsIFRyYW5zbG9jb1NlcnZpY2UsIHByb3ZpZGVUcmFuc2xvY29TY29wZSB9IGZyb20gJ0Bqc3ZlcnNlL3RyYW5zbG9jbyc7XG5pbXBvcnQgeyBIdWJDb25uZWN0aW9uLCBIdWJDb25uZWN0aW9uU3RhdGUgfSBmcm9tIFwiQG1pY3Jvc29mdC9zaWduYWxyXCI7XG5pbXBvcnQgeyBCZWhhdmlvclN1YmplY3QsIFN1YnNjcmlwdGlvbiwgY29tYmluZUxhdGVzdCwgZmlsdGVyLCBmcm9tRXZlbnQsIG1lcmdlLCBvZiwgc3dpdGNoTWFwLCB0YWtlLCB0YXAgfSBmcm9tIFwicnhqc1wiO1xuXG5pbXBvcnQgeyBBcHBHbG9iYWxDb25maWcsIEFydGljbGUsIFF1ZXJ5LCBndWlkLCBpc0F1dGhlbnRpY2F0ZWQsIHNldEdsb2JhbENvbmZpZyB9IGZyb20gXCJAc2luZXF1YS9hdG9taWNcIjtcblxuaW1wb3J0IHsgQ2hhdE1lc3NhZ2VDb21wb25lbnQgfSBmcm9tIFwiLi9jaGF0LW1lc3NhZ2UvY2hhdC1tZXNzYWdlLmNvbXBvbmVudFwiO1xuaW1wb3J0IHsgQ2hhdFNlcnZpY2UgfSBmcm9tIFwiLi9jaGF0LnNlcnZpY2VcIjtcbmltcG9ydCB7IEFzc2lzdGFudFV0aWxzIH0gZnJvbSBcIi4vdXRpbHMvdXRpbHMuc2VydmljZVwiO1xuaW1wb3J0IHsgRGVidWdNZXNzYWdlQ29tcG9uZW50IH0gZnJvbSBcIi4vZGVidWctbWVzc2FnZS9kZWJ1Zy1tZXNzYWdlLmNvbXBvbmVudFwiO1xuaW1wb3J0IHsgSW5zdGFuY2VNYW5hZ2VyU2VydmljZSB9IGZyb20gXCIuL2luc3RhbmNlLW1hbmFnZXIuc2VydmljZVwiO1xuaW1wb3J0IHsgTm90aWZpY2F0aW9uc1NlcnZpY2UgfSBmcm9tIFwiLi9zZXJ2aWNlcy9ub3RpZmljYXRpb24uc2VydmljZVwiO1xuaW1wb3J0IHsgUHJpbmNpcGFsU2VydmljZSB9IGZyb20gXCIuL3NlcnZpY2VzL3ByaW5jaXBhbC5zZXJ2aWNlXCI7XG5pbXBvcnQgeyBTZWFyY2hTZXJ2aWNlIH0gZnJvbSBcIi4vc2VydmljZXMvc2VhcmNoLnNlcnZpY2VcIjtcbmltcG9ydCB7IFRva2VuUHJvZ3Jlc3NCYXJDb21wb25lbnQgfSBmcm9tIFwiLi90b2tlbi1wcm9ncmVzcy1iYXIvdG9rZW4tcHJvZ3Jlc3MtYmFyLmNvbXBvbmVudFwiO1xuaW1wb3J0IHsgVG9vbHRpcERpcmVjdGl2ZSB9IGZyb20gXCIuL3Rvb2x0aXAvdG9vbHRpcC5kaXJlY3RpdmVcIjtcbmltcG9ydCB7IENoYXRDb25maWcsIENoYXRDb250ZXh0QXR0YWNobWVudCwgQ2hhdE1lc3NhZ2UsIERlYnVnTWVzc2FnZSwgR2xsbU1vZGVsRGVzY3JpcHRpb24sIEluaXRDaGF0LCBNZXNzYWdlSGFuZGxlciwgUmF3TWVzc2FnZSwgU3VnZ2VzdGVkQWN0aW9uIH0gZnJvbSBcIi4vdHlwZXNcIjtcbmltcG9ydCB7IFJhd01lc3NhZ2VDb250ZW50LCBUZXh0TWVzc2FnZUNvbnRlbnQgfSBmcm9tIFwiLi90eXBlcy9tZXNzYWdlLWNvbnRlbnQudHlwZXNcIjtcblxuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAnc3EtY2hhdC12MycsIC8vIG1hbmRhdG9yeSBzaW5jZSBAc2luZXF1YS9jb21wb25lbnRzIGFscmVhZHkgaGFzIHRoZSBzYW1lIHRhZy1uYW1lIFwic3EtY2hhdFwiXG4gIHRlbXBsYXRlVXJsOiAnLi9jaGF0LmNvbXBvbmVudC5odG1sJyxcbiAgc3R5bGVVcmxzOiBbJy4vY2hhdC5jb21wb25lbnQuc2NzcyddLFxuICBwcm92aWRlcnM6IFtcbiAgICBDaGF0U2VydmljZSxcbiAgICBwcm92aWRlVHJhbnNsb2NvU2NvcGUoJ2NoYXQnKVxuICBdLFxuICBjaGFuZ2VEZXRlY3Rpb246IENoYW5nZURldGVjdGlvblN0cmF0ZWd5Lk9uUHVzaCxcbiAgc3RhbmRhbG9uZTogdHJ1ZSxcbiAgaW1wb3J0czogW0NvbW1vbk1vZHVsZSwgRm9ybXNNb2R1bGUsIENoYXRNZXNzYWdlQ29tcG9uZW50LCBUb2tlblByb2dyZXNzQmFyQ29tcG9uZW50LCBEZWJ1Z01lc3NhZ2VDb21wb25lbnQsIFRvb2x0aXBEaXJlY3RpdmUsIFRyYW5zbG9jb1BpcGVdXG59KVxuZXhwb3J0IGNsYXNzIENoYXRDb21wb25lbnQgaW1wbGVtZW50cyBPbkluaXQsIE9uQ2hhbmdlcywgT25EZXN0cm95IHtcblxuICBwdWJsaWMgY2hhdFNlcnZpY2UgPSBpbmplY3QoQ2hhdFNlcnZpY2UpO1xuICBwdWJsaWMgaW5zdGFuY2VNYW5hZ2VyU2VydmljZSA9IGluamVjdChJbnN0YW5jZU1hbmFnZXJTZXJ2aWNlKTtcbiAgcHVibGljIHNlYXJjaFNlcnZpY2UgPSBpbmplY3QoU2VhcmNoU2VydmljZSk7XG4gIHB1YmxpYyBwcmluY2lwYWxTZXJ2aWNlID0gaW5qZWN0KFByaW5jaXBhbFNlcnZpY2UpO1xuICBwdWJsaWMgY2RyID0gaW5qZWN0KENoYW5nZURldGVjdG9yUmVmKTtcbiAgcHVibGljIG5vdGlmaWNhdGlvbnNTZXJ2aWNlID0gaW5qZWN0KE5vdGlmaWNhdGlvbnNTZXJ2aWNlKTtcbiAgcHJpdmF0ZSByZWFkb25seSB0cmFuc2xvY28gPSBpbmplY3QoVHJhbnNsb2NvU2VydmljZSk7XG4gIHByaXZhdGUgcmVhZG9ubHkgYXNzaXN0YW50VXRpbHMgPSBpbmplY3QoQXNzaXN0YW50VXRpbHMpO1xuXG4gIC8qKiBEZWZpbmUgdGhlIGtleSBiYXNlZCBvbiBpdCwgdGhlIGNoYXQgc2VydmljZSBpbnN0YW5jZSB3aWxsIGJlIHN0b3JlZCAqL1xuICBASW5wdXQoKSBpbnN0YW5jZUlkOiBzdHJpbmc7XG4gIC8qKiBEZWZpbmUgdGhlIHF1ZXJ5IHRvIHVzZSB0byBmZXRjaCBhbnN3ZXJzICovXG4gIEBJbnB1dCgpIHF1ZXJ5OiBRdWVyeSA9IHRoaXMuc2VhcmNoU2VydmljZS5xdWVyeTtcbiAgLyoqIEZ1bmN0aW9uIHRoYXQgZGV0ZXJtaW5lcyB3aGV0aGVyIHRoZSBjaGF0IHNob3VsZCBiZSByZWxvYWRlZCBhZnRlciB0aGUgcXVlcnkgY2hhbmdlc1xuICAgKiBJZiBub3QgcHJvdmlkZWQsIHRoZSBjaGF0IHdpbGwgYmUgcmVsb2FkZWQgYnkgZGVmYXVsdFxuICAgKiBAcGFyYW0gcHJldlF1ZXJ5IFRoZSBwcmV2aW91cyBxdWVyeVxuICAgKiBAcGFyYW0gbmV3UXVlcnkgVGhlIG5ldyBxdWVyeVxuICAgKiBAcmV0dXJucyB0cnVlIGlmIHRoZSBjaGF0IHNob3VsZCBiZSByZWxvYWRlZCwgZmFsc2Ugb3RoZXJ3aXNlXG4gICAqL1xuICBASW5wdXQoKSBxdWVyeUNoYW5nZVNob3VsZFRyaWdnZXJSZWxvYWQ6IChwcmV2UXVlcnk6IFF1ZXJ5LCBuZXdRdWVyeTogUXVlcnkpID0+IGJvb2xlYW47XG4gIC8qKiBNYXAgb2YgbGlzdGVuZXJzIG92ZXJyaWRpbmcgZGVmYXVsdCByZWdpc3RlcmVkIG9uZXMqL1xuICBASW5wdXQoKSBtZXNzYWdlSGFuZGxlcnM6IE1hcDxzdHJpbmcsIE1lc3NhZ2VIYW5kbGVyPGFueT4+ID0gbmV3IE1hcCgpO1xuICAvKiogV2hlbiB0aGUgYXNzaXN0YW50IGFuc3dlciBhIHVzZXIgcXVlc3Rpb24sIGF1dG9tYXRpY2FsbHkgc2Nyb2xsIGRvd24gdG8gdGhlIGJvdHRvbSBvZiB0aGUgZGlzY3Vzc2lvbiAqL1xuICBASW5wdXQoKSBhdXRvbWF0aWNTY3JvbGxUb0xhc3RSZXNwb25zZSA9IGZhbHNlO1xuICAvKiogV2hlbiB0aGUgYXNzaXN0YW50IGFuc3dlciBhIHVzZXIgcXVlc3Rpb24sIGF1dG9tYXRpY2FsbHkgZm9jdXMgdG8gdGhlIGNoYXQgaW5wdXQgKi9cbiAgQElucHV0KCkgZm9jdXNBZnRlclJlc3BvbnNlID0gZmFsc2U7XG4gIC8qKiBBIGNoYXQgZGlzY3Vzc2lvbiB0aGF0IHRoZSBjb21wb25lbnQgc2hvdWxkIGdldCBpbml0aWFsaXplZCB3aXRoIGl0ICovXG4gIEBJbnB1dCgpIGNoYXQ/OiBJbml0Q2hhdDtcbiAgLyoqIEljb24gdG8gdXNlIGZvciB0aGUgYXNzaXN0YW50IG1lc3NhZ2VzICovXG4gIEBJbnB1dCgpIGFzc2lzdGFudE1lc3NhZ2VJY29uID0gJ3NxLXNpbmVxdWEnO1xuICAvKiogSWNvbiB0byB1c2UgZm9yIHRoZSB1c2VyIG1lc3NhZ2VzICovXG4gIEBJbnB1dCgpIHVzZXJNZXNzYWdlSWNvbjogc3RyaW5nO1xuICAvKiogSWNvbiB0byB1c2UgZm9yIHRoZSBjb25uZWN0aW9uIGVycm9yIG1lc3NhZ2VzICovXG4gIEBJbnB1dCgpIGNvbm5lY3Rpb25FcnJvck1lc3NhZ2VJY29uOiBzdHJpbmc7XG4gIC8qKiBJY29uIHRvIHVzZSBmb3IgdGhlIHNlYXJjaCB3YXJuaW5nIG1lc3NhZ2VzICovXG4gIEBJbnB1dCgpIHNlYXJjaFdhcm5pbmdNZXNzYWdlSWNvbjogc3RyaW5nO1xuICAvLyBBZGQgY3VzdG9tIGFkZGl0aW9uYWxXb3JrZmxvd1Byb3BlcnRpZXMgdG8gdGhlIHVzZXIgcXVlcnkgbWVzc2FnZVxuICBASW5wdXQoKSBhZGRpdGlvbmFsV29ya2Zsb3dQcm9wZXJ0aWVzOiBSZWNvcmQ8c3RyaW5nLCBhbnk+ID0ge307XG4gIC8qKiBFdmVudCBlbWl0dGVyIHRyaWdnZXJlZCBvbmNlIHRoZSBzaWduYWxSIGNvbm5lY3Rpb24gaXMgZXN0YWJsaXNoZWQgICovXG4gIEBPdXRwdXQoKSBjb25uZWN0aW9uID0gbmV3IEV2ZW50RW1pdHRlcjxIdWJDb25uZWN0aW9uPigpO1xuICAvKiogRXZlbnQgZW1pdHRlciB0cmlnZ2VyZWQgZWFjaCB0aW1lIHRoZSBhc3Npc3RhbnQgdXBkYXRlcyB0aGUgY3VycmVudCBjaGF0ICovXG4gIC8qKiBFdmVudCBlbWl0dGVyIHRyaWdnZXJlZCB3aGVuIHRoZSBjaGF0IGlzIGxvYWRpbmcgbmV3IGNvbnRlbnQgKi9cbiAgQE91dHB1dChcImxvYWRpbmdcIikgbG9hZGluZyQgPSBuZXcgRXZlbnRFbWl0dGVyPGJvb2xlYW4+KGZhbHNlKTtcbiAgLyoqIEVtaXRzIHRoZSBhc3Npc3RhbnQgY29uZmlndXJhdGlvbiB1c2VkIHdoZW4gaW5zdGFudGlhdGluZyB0aGUgY29tcG9uZW50ICovXG4gIEBPdXRwdXQoXCJjb25maWdcIikgX2NvbmZpZyA9IG5ldyBFdmVudEVtaXR0ZXI8Q2hhdENvbmZpZz4oKTtcbiAgQE91dHB1dCgpIGRhdGEgPSBuZXcgRXZlbnRFbWl0dGVyPENoYXRNZXNzYWdlW10+KCk7XG4gIC8qKiBFdmVudCBlbWl0dGVyIHRyaWdnZXJlZCB3aGVuIHRoZSB1c2VyIGNsaWNrcyB0byBvcGVuIHRoZSBvcmlnaW5hbCBkb2N1bWVudCByZXByZXNlbnRpbmcgdGhlIGNvbnRleHQgYXR0YWNobWVudCovXG4gIEBPdXRwdXQoKSBvcGVuRG9jdW1lbnQgPSBuZXcgRXZlbnRFbWl0dGVyPEFydGljbGU+KCk7XG4gIC8qKiBFdmVudCBlbWl0dGVyIHRyaWdnZXJlZCB3aGVuIHRoZSB1c2VyIGNsaWNrcyB0byBvcGVuIHRoZSBwcmV2aWV3IG9mIGEgZG9jdW1lbnQgcmVwcmVzZW50aW5nIHRoZSBjb250ZXh0IGF0dGFjaG1lbnQgKi9cbiAgQE91dHB1dCgpIG9wZW5QcmV2aWV3ID0gbmV3IEV2ZW50RW1pdHRlcjxDaGF0Q29udGV4dEF0dGFjaG1lbnQ+KCk7XG4gIC8qKiBFdmVudCBlbWl0dGVyIHRyaWdnZXJlZCB3aGVuIHRoZSB1c2VyIGNsaWNrcyBvbiBhIHN1Z2dlc3RlZCBhY3Rpb24gKi9cbiAgQE91dHB1dCgpIHN1Z2dlc3RBY3Rpb24gPSBuZXcgRXZlbnRFbWl0dGVyPFN1Z2dlc3RlZEFjdGlvbj4oKTtcbiAgLyoqIFZpZXdDaGlsZCBkZWNvcmF0b3JzIHRvIGFjY2VzcyB0aGUgdGVtcGxhdGUgZWxlbWVudHMgKi9cbiAgQFZpZXdDaGlsZCgnbWVzc2FnZUxpc3QnKSBtZXNzYWdlTGlzdD86IEVsZW1lbnRSZWY8SFRNTFVMaXN0RWxlbWVudD47XG4gIEBWaWV3Q2hpbGQoJ3F1ZXN0aW9uSW5wdXQnKSBxdWVzdGlvbklucHV0PzogRWxlbWVudFJlZjxIVE1MVGV4dEFyZWFFbGVtZW50PjtcbiAgLyoqIENvbnRlbnRDaGlsZCBkZWNvcmF0b3JzIGFsbG93aW5nIHRoZSBvdmVycmlkZSBvZiB0aGUgZGVmYXVsdCB0ZW1wbGF0ZXMgZnJvbSB0aGUgcGFyZW50IGNvbXBvbmVudCAqL1xuICBAQ29udGVudENoaWxkKCdsb2FkaW5nVHBsJykgbG9hZGluZ1RwbD86IFRlbXBsYXRlUmVmPGFueT47XG4gIEBDb250ZW50Q2hpbGQoJ3JlcG9ydFRwbCcpIHJlcG9ydFRwbD86IFRlbXBsYXRlUmVmPGFueT47XG4gIEBDb250ZW50Q2hpbGQoJ3Rva2VuQ29uc3VtcHRpb25UcGwnKSB0b2tlbkNvbnN1bXB0aW9uVHBsPzogVGVtcGxhdGVSZWY8YW55PjtcbiAgQENvbnRlbnRDaGlsZCgnZGVidWdNZXNzYWdlc1RwbCcpIGRlYnVnTWVzc2FnZXNUcGw/OiBUZW1wbGF0ZVJlZjxhbnk+O1xuXG4gIEBJbnB1dCgpIGFwcENvbmZpZzogQXBwR2xvYmFsQ29uZmlnO1xuXG4gIGNvbmZpZzogQ2hhdENvbmZpZztcbiAgbWVzc2FnZXMkID0gbmV3IEJlaGF2aW9yU3ViamVjdDxDaGF0TWVzc2FnZVtdIHwgdW5kZWZpbmVkPih1bmRlZmluZWQpO1xuICBpc0FkbWluT3JEZWxldGVkQWRtaW4gPSBmYWxzZTtcbiAgcXVlc3Rpb24gPSAnJztcblxuICBwcml2YXRlIF9zdWIgPSBuZXcgU3Vic2NyaXB0aW9uKCk7XG4gIHByaXZhdGUgX2RhdGFTdWJzY3JpcHRpb246IFN1YnNjcmlwdGlvbiB8IHVuZGVmaW5lZDtcblxuICAvKiogVmFyaWFibGVzIHRoYXQgZGVwZW5kIG9uIHRoZSB0eXBlIG9mIG1vZGVsIGluIHVzZSAqL1xuICBtb2RlbERlc2NyaXB0aW9uPzogR2xsbU1vZGVsRGVzY3JpcHRpb247XG5cbiAgaW5kZXhNZXNzYWdlVG9FZGl0PzogbnVtYmVyO1xuICByYW5rTWVzc2FnZVRvRWRpdD86IG51bWJlcjtcbiAgY2hhbmdlcyQgPSBuZXcgQmVoYXZpb3JTdWJqZWN0PFNpbXBsZUNoYW5nZXMgfCB1bmRlZmluZWQ+KHVuZGVmaW5lZCk7XG4gIGN1cnJlbnRNZXNzYWdlSW5kZXg6IG51bWJlciB8IHVuZGVmaW5lZDtcbiAgZmlyc3RDaGFuZ2VzSGFuZGxlZCA9IGZhbHNlO1xuICBpc0F0Qm90dG9tID0gdHJ1ZTtcbiAgaW5pdGlhbGl6YXRpb25FcnJvciA9IGZhbHNlO1xuICBlbmFibGVkVXNlcklucHV0ID0gZmFsc2U7XG4gIGlzQ29ubmVjdGVkID0gdHJ1ZTsgLy8gQnkgZGVmYXVsdCwgdGhlIGNoYXQgaXMgY29uc2lkZXJlZCBjb25uZWN0ZWRcbiAgcmV0cmlhbEF0dGVtcHRzOiBudW1iZXIgfCB1bmRlZmluZWQ7XG4gIC8vIEZsYWcgdG8gdHJhY2sgd2hldGhlciB0aGUgJ3JlY29ubmVjdGVkJyBsaXN0ZW5lciBpcyBhbHJlYWR5IHJlZ2lzdGVyZWRcbiAgcHJpdmF0ZSBfaXNSZWNvbm5lY3RlZExpc3RlbmVyUmVnaXN0ZXJlZCA9IGZhbHNlO1xuXG4gIC8vIElzc3VlIHJlcG9ydGluZ1xuICBpc3N1ZVR5cGVzPzogc3RyaW5nW107XG4gIGRlZmF1bHRJc3N1ZVR5cGVzOiBzdHJpbmdbXSA9IFtcbiAgICAnY2hhdC51c2VySW50ZXJmYWNlQnVnJyxcbiAgICAnY2hhdC5pbmNvcnJlY3RSZXNwb25zZScsXG4gICAgJ2NoYXQuaW5jb21wbGV0ZVJlc3BvbnNlJyxcbiAgICAnY2hhdC50ZWNobmljYWxJc3N1ZScsXG4gICAgJ2NoYXQucHJpdmFjeURhdGFTZWN1cml0eUlzc3VlJyxcbiAgICAnY2hhdC5vdGhlcklzc3VlJ1xuICBdO1xuICBpc3N1ZVR5cGU6IHN0cmluZyA9ICcnO1xuICByZXBvcnRDb21tZW50Pzogc3RyaW5nO1xuICBtZXNzYWdlVG9SZXBvcnQ/OiBDaGF0TWVzc2FnZTtcbiAgcmVwb3J0UmFuaz86IG51bWJlcjtcbiAgcmVwb3J0VHlwZTogJ2xpa2UnIHwgJ2Rpc2xpa2UnID0gJ2Rpc2xpa2UnO1xuICBzaG93UmVwb3J0ID0gZmFsc2U7XG5cbiAgLy8gRGVidWcgbWVzc2FnZXNcbiAgZGVidWdNZXNzYWdlczogRGVidWdNZXNzYWdlW10gfCB1bmRlZmluZWQ7XG4gIHNob3dEZWJ1Z01lc3NhZ2VzID0gZmFsc2U7XG5cbiAgcHJpdmF0ZSBfcHJldmlvdXNRdWVyeTogUXVlcnk7XG4gIHByaXZhdGUgX3JlbG9hZFN1YnNjcmlwdGlvbjogU3Vic2NyaXB0aW9uIHwgdW5kZWZpbmVkID0gdW5kZWZpbmVkO1xuXG4gIG5nT25Jbml0KCk6IHZvaWQge1xuICAgIGlmICh0aGlzLmFwcENvbmZpZykge1xuICAgICAgc2V0R2xvYmFsQ29uZmlnKHRoaXMuYXBwQ29uZmlnKTtcbiAgICB9XG5cbiAgICB0aGlzLl9zdWIuYWRkKFxuICAgICAgb2YoaXNBdXRoZW50aWNhdGVkKCkpLnBpcGUoXG4gICAgICAgIHRhcChfID0+IHRoaXMuaW5zdGFudGlhdGVDaGF0U2VydmljZSgpKSxcbiAgICAgICAgc3dpdGNoTWFwKF8gPT4gdGhpcy5jaGF0U2VydmljZS5pbml0KCkpLFxuICAgICAgICBzd2l0Y2hNYXAoXyA9PiB0aGlzLmNoYXRTZXJ2aWNlLmluaXRQcm9jZXNzJC5waXBlKGZpbHRlcihCb29sZWFuKSkpLFxuICAgICAgICB0YXAoXyA9PiB7XG4gICAgICAgICAgdGhpcy5jb25uZWN0aW9uLmVtaXQodGhpcy5jaGF0U2VydmljZS5jb25uZWN0aW9uKTtcbiAgICAgICAgICB0aGlzLm9uTG9hZENoYXQoKTtcbiAgICAgICAgfSksXG4gICAgICAgIHRhcChfID0+IHRoaXMuY2hhdFNlcnZpY2Uub3ZlcnJpZGVVc2VyKCkpLFxuICAgICAgICBzd2l0Y2hNYXAoXyA9PiB0aGlzLmNoYXRTZXJ2aWNlLnVzZXJPdmVycmlkZSQpLFxuICAgICAgICBzd2l0Y2hNYXAoXyA9PiB0aGlzLmNoYXRTZXJ2aWNlLmFzc2lzdGFudENvbmZpZyQpLFxuICAgICAgICB0YXAoY29uZmlnID0+IHtcbiAgICAgICAgICB0aGlzLmlzQWRtaW5PckRlbGV0ZWRBZG1pbiA9IHRoaXMucHJpbmNpcGFsU2VydmljZS5wcmluY2lwYWwhLmlzQWRtaW5pc3RyYXRvciB8fCB0aGlzLnByaW5jaXBhbFNlcnZpY2UucHJpbmNpcGFsIS5pc0RlbGVnYXRlZEFkbWluIHx8IGZhbHNlO1xuICAgICAgICAgIHRoaXMuY29uZmlnID0gY29uZmlnITtcbiAgICAgICAgICB0aGlzLmVuYWJsZWRVc2VySW5wdXQgPSB0aGlzLmNvbmZpZy5tb2RlU2V0dGluZ3MuZW5hYmxlZFVzZXJJbnB1dDtcbiAgICAgICAgICB0aGlzLmlzc3VlVHlwZXMgPSB0aGlzLmNvbmZpZy5hdWRpdFNldHRpbmdzPy5pc3N1ZVR5cGVzPy5sZW5ndGggPyB0aGlzLmNvbmZpZy5hdWRpdFNldHRpbmdzIS5pc3N1ZVR5cGVzIDogdW5kZWZpbmVkO1xuICAgICAgICAgIHRoaXMuX2NvbmZpZy5lbWl0KGNvbmZpZyk7XG4gICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIHRoaXMudXBkYXRlTW9kZWxEZXNjcmlwdGlvbigpO1xuICAgICAgICAgICAgaWYoIXRoaXMuZmlyc3RDaGFuZ2VzSGFuZGxlZCkge1xuICAgICAgICAgICAgICB0aGlzLl9wcmV2aW91c1F1ZXJ5ID0gSlNPTi5wYXJzZShKU09OLnN0cmluZ2lmeSh0aGlzLnF1ZXJ5KSk7IC8vIEluaXRpYWxpemUgdGhlIHByZXZpb3VzIHF1ZXJ5XG4gICAgICAgICAgICAgIHRoaXMuX2hhbmRsZUNoYW5nZXMoKTtcbiAgICAgICAgICAgICAgdGhpcy5fYWRkU2Nyb2xsTGlzdGVuZXIoKTtcbiAgICAgICAgICAgICAgdGhpcy5maXJzdENoYW5nZXNIYW5kbGVkID0gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICAgICAgdGhpcy5pbml0aWFsaXphdGlvbkVycm9yID0gdHJ1ZVxuICAgICAgICAgICAgdGhyb3cgZXJyb3I7XG4gICAgICAgICAgfVxuICAgICAgICB9KVxuICAgICAgKS5zdWJzY3JpYmUoKVxuICAgICk7XG4gIH1cblxuICBuZ09uQ2hhbmdlcyhjaGFuZ2VzOiBTaW1wbGVDaGFuZ2VzKSB7XG4gICAgdGhpcy5jaGFuZ2VzJC5uZXh0KGNoYW5nZXMpO1xuICAgIGlmICh0aGlzLmNvbmZpZykge1xuICAgICAgdGhpcy5faGFuZGxlQ2hhbmdlcygpO1xuICAgIH1cbiAgfVxuXG4gIG5nT25EZXN0cm95KCk6IHZvaWQge1xuICAgIHRoaXMuX3N1Yi51bnN1YnNjcmliZSgpO1xuICAgIHRoaXMuX2RhdGFTdWJzY3JpcHRpb24/LnVuc3Vic2NyaWJlKCk7XG4gICAgdGhpcy5fcmVsb2FkU3Vic2NyaXB0aW9uPy51bnN1YnNjcmliZSgpO1xuICAgIHRoaXMuY2hhdFNlcnZpY2Uuc3RvcENvbm5lY3Rpb24oKTtcbiAgfVxuXG4gIGdldCBpc0FkbWluKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLnByaW5jaXBhbFNlcnZpY2UucHJpbmNpcGFsPy5pc0FkbWluaXN0cmF0b3IgfHwgZmFsc2U7XG4gIH1cblxuICAvKipcbiAgICogVGhpcyBjaGF0IHNlcnZpY2UgaW5zdGFuY2UgaXMgc3RvcmVkIGluIHRoZSBpbnN0YW5jZU1hbmFnZXJTZXJ2aWNlIHdpdGggcHJvdmlkZWQgQGlucHV0IGluc3RhbmNlSWQgYXMgYSBrZXlcbiAgICovXG4gIGluc3RhbnRpYXRlQ2hhdFNlcnZpY2UoKTogdm9pZCB7XG4gICAgdGhpcy5jaGF0U2VydmljZS5zZXRDaGF0SW5zdGFuY2VJZCh0aGlzLmluc3RhbmNlSWQpO1xuICAgIHRoaXMuaW5zdGFuY2VNYW5hZ2VyU2VydmljZS5zdG9yZUluc3RhbmNlKHRoaXMuaW5zdGFuY2VJZCwgdGhpcy5jaGF0U2VydmljZSk7XG4gIH1cblxuICAvKipcbiAgICogSGFuZGxlcyB0aGUgY2hhbmdlcyBpbiB0aGUgY2hhdCBjb21wb25lbnQuXG4gICAqIElmIHRoZSBjaGF0IHNlcnZpY2UgaXMgYSBXZWJTb2NrZXRDaGF0U2VydmljZSwgaXQgaGFuZGxlcyB0aGUgb3ZlcnJpZGUgb2YgdGhlIG1lc3NhZ2UgaGFuZGxlcnMgaWYgdGhleSBleGlzdC5cbiAgICogSW5pdGlhbGl6ZXMgdGhlIGNoYXQgd2l0aCB0aGUgcHJvdmlkZWQgY2hhdCBtZXNzYWdlcyBpZiB0aGV5IGV4aXN0LCBvdGhlcndpc2UgbG9hZHMgdGhlIGRlZmF1bHQgY2hhdC5cbiAgICogSWYgdGhlIGNoYXQgaXMgaW5pdGlhbGl6ZWQsIHRoZSBpbml0aWFsaXphdGlvbiBldmVudCBpcyBcIlF1ZXJ5XCIsIHRoZSBxdWVyeSBjaGFuZ2VzLCBhbmQgdGhlIHF1ZXJ5Q2hhbmdlU2hvdWxkVHJpZ2dlclJlbG9hZCBmdW5jdGlvbiBpcyBwcm92aWRlZCxcbiAgICogdGhlbiB0aGUgY2hhdCBzaG91bGQgYmUgcmVsb2FkZWQgaWYgdGhlIGZ1bmN0aW9uIHJldHVybnMgdHJ1ZS4gT3RoZXJ3aXNlLCB0aGUgY2hhdCBzaG91bGQgYmUgcmVsb2FkZWQgYnkgZGVmYXVsdC5cbiAgICogSXQgdGFrZXMgaW50byBhY2NvdW50IHRoZSBvbmdvaW5nIHN0cmVhbWluZyBwcm9jZXNzIGFuZCB0aGUgb25nb2luZyBzdG9wcGluZyBwcm9jZXNzIHRvIHRyaWdnZXIgdGhhdCBjb25kaXRpb25hbGx5IGRlZmluZSB0aGUgbG9naWNcbiAgICogb2YgdGhlIHJlbG9hZCA6XG4gICAqIC0gSWYgdGhlIGNoYXQgaXMgc3RyZWFtaW5nLCB0aGVuIHN0b3AgdGhlIGdlbmVyYXRpb24gYW5kIHdhaXQgZm9yIHRoZSBmZXRjaCB0byBjb21wbGV0ZSBiZWZvcmUgcmVsb2FkaW5nIHRoZSBjaGF0LlxuICAgKiAtIElmIHRoZSBjaGF0IGlzIHN0b3BwaW5nIHRoZSBnZW5lcmF0aW9uLCB0aGVuIHdhaXQgZm9yIHRoZSBmZXRjaCB0byBjb21wbGV0ZSBiZWZvcmUgcmVsb2FkaW5nIHRoZSBjaGF0LlxuICAgKi9cbiAgcHJpdmF0ZSBfaGFuZGxlQ2hhbmdlcygpIHtcbiAgICBjb25zdCBjaGFuZ2VzID0gdGhpcy5jaGFuZ2VzJC52YWx1ZTtcbiAgICAvLyBJZiB0aGUgY2hhdCBzZXJ2aWNlIGlzIGEgV2ViU29ja2V0Q2hhdFNlcnZpY2UsIGhhbmRsZSB0aGUgb3ZlcnJpZGUgb2YgdGhlIG1lc3NhZ2UgaGFuZGxlcnMgaWYgZXhpc3RzXG4gICAgaWYgKGNoYW5nZXM/Lm1lc3NhZ2VIYW5kbGVycyAmJiB0aGlzLm1lc3NhZ2VIYW5kbGVycykge1xuICAgICAgdGhpcy5jaGF0U2VydmljZS5vdmVycmlkZU1lc3NhZ2VIYW5kbGVycyh0aGlzLm1lc3NhZ2VIYW5kbGVycyk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIEluaXRpYWxpemUgdGhlIGNoYXQgd2l0aCB0aGUgcHJvdmlkZWQgY2hhdCBtZXNzYWdlcyBpZiBleGlzdHMsIG90aGVyd2lzZSBsb2FkIHRoZSBkZWZhdWx0IGNoYXRcbiAgICAgKiBPbmNlIHRoZSBjaGF0IGlzIGluaXRpYWxpemVkIChmaXJzdENoYW5nZXNIYW5kbGVkIGlzIHRydWUpLCBhbGxvdyBvcGVuaW5nIHRoZSBjaGF0IHdpdGggdGhlIG5ldyBwcm92aWRlZCBtZXNzYWdlcyAoaWYgZXhpc3RzKVxuICAgICAqL1xuICAgIGlmICghdGhpcy5maXJzdENoYW5nZXNIYW5kbGVkIHx8IGNoYW5nZXM/LmNoYXQpIHtcbiAgICAgIGNvbnN0IG9wZW5DaGF0ID0gKCkgPT4ge1xuICAgICAgICBpZiAodGhpcy5tZXNzYWdlcyQudmFsdWUgJiYgdGhpcy5jb25maWcuc2F2ZWRDaGF0U2V0dGluZ3M/LmVuYWJsZWQpIHtcbiAgICAgICAgICB0aGlzLmNoYXRTZXJ2aWNlLmxpc3RTYXZlZENoYXQoKTsgLy8gUmVmcmVzaCB0aGUgbGlzdCBvZiBzYXZlZCBjaGF0c1xuICAgICAgICB9XG4gICAgICAgIHRoaXMub3BlbkNoYXQodGhpcy5jaGF0IS5tZXNzYWdlcyk7XG4gICAgICB9O1xuICAgICAgdGhpcy5jaGF0U2VydmljZS5nZW5lcmF0ZUNoYXRJZCgpO1xuICAgICAgaWYgKHRoaXMuY2hhdCkge1xuICAgICAgICB0aGlzLmNoYXRTZXJ2aWNlLmdlbmVyYXRlQXVkaXRFdmVudCgnYXN0LWNoYXQubmV3Jywgeydjb25maWd1cmF0aW9uJzogSlNPTi5zdHJpbmdpZnkodGhpcy5jaGF0U2VydmljZS5hc3Npc3RhbnRDb25maWckLnZhbHVlKSwnY2hhdC1pbml0JzogSlNPTi5zdHJpbmdpZnkodGhpcy5jaGF0KX0pO1xuICAgICAgICBvcGVuQ2hhdCgpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhpcy5jaGF0U2VydmljZS5nZW5lcmF0ZUF1ZGl0RXZlbnQoJ2FzdC1jaGF0Lm5ldycsIHsnY29uZmlndXJhdGlvbic6IEpTT04uc3RyaW5naWZ5KHRoaXMuY2hhdFNlcnZpY2UuYXNzaXN0YW50Q29uZmlnJC52YWx1ZSl9KTtcbiAgICAgICAgdGhpcy5sb2FkRGVmYXVsdENoYXQoKTtcbiAgICAgIH1cbiAgICB9XG4gICAgLyoqXG4gICAgICogSWYgdGhlIGNoYXQgaXMgaW5pdGlhbGl6ZWQsIHRoZSBpbml0aWFsaXphdGlvbiBldmVudCBpcyBcIlF1ZXJ5XCIsIHRoZSBxdWVyeSBjaGFuZ2VzIGFuZCB0aGUgcXVlcnlDaGFuZ2VTaG91bGRUcmlnZ2VyUmVsb2FkIGZ1bmN0aW9uIGlzIHByb3ZpZGVkLFxuICAgICAqIHRoZW4gdGhlIGNoYXQgc2hvdWxkIGJlIHJlbG9hZGVkIGlmIHRoZSBmdW5jdGlvbiByZXR1cm5zIHRydWVcbiAgICAgKiBPdGhlcndpc2UsIHRoZSBjaGF0IHNob3VsZCBiZSByZWxvYWRlZCBieSBkZWZhdWx0XG4gICAgICovXG4gICAgaWYgKHRoaXMuZmlyc3RDaGFuZ2VzSGFuZGxlZCAmJiBjaGFuZ2VzPy5xdWVyeSAmJiB0aGlzLmNvbmZpZy5tb2RlU2V0dGluZ3MuaW5pdGlhbGl6YXRpb24uZXZlbnQgPT09ICdRdWVyeScpIHtcbiAgICAgIGlmICh0aGlzLnF1ZXJ5Q2hhbmdlU2hvdWxkVHJpZ2dlclJlbG9hZCA/IHRoaXMucXVlcnlDaGFuZ2VTaG91bGRUcmlnZ2VyUmVsb2FkKHRoaXMuX3ByZXZpb3VzUXVlcnksIHRoaXMucXVlcnkpIDogdHJ1ZSkge1xuICAgICAgICBpZiAoISF0aGlzLmNoYXRTZXJ2aWNlLnN0b3BwaW5nR2VuZXJhdGlvbiQudmFsdWUpIHtcbiAgICAgICAgICBpZiAoIXRoaXMuX3JlbG9hZFN1YnNjcmlwdGlvbikge1xuICAgICAgICAgICAgLy8gQ3JlYXRlIGEgc3Vic2NyaXB0aW9uIHRvIHdhaXQgZm9yIGJvdGggc3RyZWFtaW5nJCBhbmQgc3RvcHBpbmdHZW5lcmF0aW9uJCB0byBiZSBmYWxzZVxuICAgICAgICAgICAgdGhpcy5fcmVsb2FkU3Vic2NyaXB0aW9uID0gY29tYmluZUxhdGVzdChbXG4gICAgICAgICAgICAgIHRoaXMuY2hhdFNlcnZpY2Uuc3RyZWFtaW5nJCxcbiAgICAgICAgICAgICAgdGhpcy5jaGF0U2VydmljZS5zdG9wcGluZ0dlbmVyYXRpb24kXG4gICAgICAgICAgICBdKVxuICAgICAgICAgICAgICAucGlwZShcbiAgICAgICAgICAgICAgICBmaWx0ZXIoKFtzdHJlYW1pbmcsIHN0b3BwaW5nXSkgPT4gIXN0cmVhbWluZyAmJiAhc3RvcHBpbmcpLCAvLyBXYWl0IHVudGlsIGJvdGggYXJlIGZhbHNlXG4gICAgICAgICAgICAgICAgdGFrZSgxKSAvLyBDb21wbGV0ZSBhZnRlciB0aGUgZmlyc3QgbWF0Y2hcbiAgICAgICAgICAgICAgKS5zdWJzY3JpYmUoKCkgPT4ge1xuICAgICAgICAgICAgICAgIC8vIEV4ZWN1dGUgdGhlIHJlbG9hZCBhZnRlciB0aGUgcXVlcnkgY2hhbmdlXG4gICAgICAgICAgICAgICAgdGhpcy5fdHJpZ2dlclJlbG9hZEFmdGVyUXVlcnlDaGFuZ2UoKTtcbiAgICAgICAgICAgICAgICAvLyBVcGRhdGUgX3ByZXZpb3VzUXVlcnkgd2l0aCB0aGUgY3VycmVudCBxdWVyeVxuICAgICAgICAgICAgICAgIHRoaXMuX3ByZXZpb3VzUXVlcnkgPSBKU09OLnBhcnNlKEpTT04uc3RyaW5naWZ5KHRoaXMucXVlcnkpKTtcbiAgICAgICAgICAgICAgICAvLyBDbGVhbiB1cCBzdWJzY3JpcHRpb24gYW5kIHJlc2V0IGl0cyB2YWx1ZVxuICAgICAgICAgICAgICAgIHRoaXMuX3JlbG9hZFN1YnNjcmlwdGlvbiA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2UgaWYgKCEhdGhpcy5jaGF0U2VydmljZS5zdHJlYW1pbmckLnZhbHVlKSB7XG4gICAgICAgICAgaWYgKCF0aGlzLl9yZWxvYWRTdWJzY3JpcHRpb24pIHtcbiAgICAgICAgICAgIHRoaXMuX3JlbG9hZFN1YnNjcmlwdGlvbiA9IHRoaXMuY2hhdFNlcnZpY2Uuc3RvcEdlbmVyYXRpb24oKVxuICAgICAgICAgICAgICAuc3Vic2NyaWJlKHtcbiAgICAgICAgICAgICAgICBuZXh0OiAoKSA9PiB7fSxcbiAgICAgICAgICAgICAgICBlcnJvcjogKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgLy8gQ2xlYW4gdXAgc3Vic2NyaXB0aW9uIGFuZCByZXNldCBpdHMgdmFsdWVcbiAgICAgICAgICAgICAgICAgIHRoaXMuX3JlbG9hZFN1YnNjcmlwdGlvbj8udW5zdWJzY3JpYmUoKTtcbiAgICAgICAgICAgICAgICAgIHRoaXMuX3JlbG9hZFN1YnNjcmlwdGlvbiA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIGNvbXBsZXRlOiAoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAvLyBXYWl0IGZvciB0aGUgb25nb2luZyBmZXRjaCB0byBjb21wbGV0ZSwgdGhlbiB0cmlnZ2VyIHRoZSByZWxvYWRcbiAgICAgICAgICAgICAgICAgIHRoaXMuY2hhdFNlcnZpY2Uuc3RyZWFtaW5nJC5waXBlKFxuICAgICAgICAgICAgICAgICAgICBmaWx0ZXIoKHN0cmVhbWluZykgPT4gIXN0cmVhbWluZyksXG4gICAgICAgICAgICAgICAgICAgIHRha2UoMSlcbiAgICAgICAgICAgICAgICAgICkuc3Vic2NyaWJlKCgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgLy8gRXhlY3V0ZSB0aGUgcmVsb2FkIGFmdGVyIHRoZSBxdWVyeSBjaGFuZ2VcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5fdHJpZ2dlclJlbG9hZEFmdGVyUXVlcnlDaGFuZ2UoKTtcbiAgICAgICAgICAgICAgICAgICAgLy8gVXBkYXRlIF9wcmV2aW91c1F1ZXJ5IHdpdGggdGhlIGN1cnJlbnQgcXVlcnlcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5fcHJldmlvdXNRdWVyeSA9IEpTT04ucGFyc2UoSlNPTi5zdHJpbmdpZnkodGhpcy5xdWVyeSkpO1xuICAgICAgICAgICAgICAgICAgICAvLyBDbGVhbiB1cCBzdWJzY3JpcHRpb24gYW5kIHJlc2V0IGl0cyB2YWx1ZVxuICAgICAgICAgICAgICAgICAgICB0aGlzLl9yZWxvYWRTdWJzY3JpcHRpb24hLnVuc3Vic2NyaWJlKCk7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuX3JlbG9hZFN1YnNjcmlwdGlvbiA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIC8vIEV4ZWN1dGUgdGhlIHJlbG9hZCBhZnRlciB0aGUgcXVlcnkgY2hhbmdlXG4gICAgICAgICAgdGhpcy5fdHJpZ2dlclJlbG9hZEFmdGVyUXVlcnlDaGFuZ2UoKTtcbiAgICAgICAgICAvLyBVcGRhdGUgX3ByZXZpb3VzUXVlcnkgd2l0aCB0aGUgY3VycmVudCBxdWVyeVxuICAgICAgICAgIHRoaXMuX3ByZXZpb3VzUXVlcnkgPSBKU09OLnBhcnNlKEpTT04uc3RyaW5naWZ5KHRoaXMucXVlcnkpKTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgLy8gVXBkYXRlIF9wcmV2aW91c1F1ZXJ5IHdpdGggdGhlIGN1cnJlbnQgcXVlcnlcbiAgICAgICAgdGhpcy5fcHJldmlvdXNRdWVyeSA9IEpTT04ucGFyc2UoSlNPTi5zdHJpbmdpZnkodGhpcy5xdWVyeSkpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBUcmlnZ2VycyBhIHJlbG9hZCBhZnRlciB0aGUgcXVlcnkgY2hhbmdlLlxuICAgKiBUaGlzIG1ldGhvZCBwZXJmb3JtcyB0aGUgbmVjZXNzYXJ5IG9wZXJhdGlvbnMgdG8gcmVsb2FkIHRoZSBjaGF0IGFmdGVyIGEgcXVlcnkgY2hhbmdlLlxuICAgKiBJdCBzZXRzIHRoZSBzeXN0ZW0gYW5kIHVzZXIgbWVzc2FnZXMsIHJlc2V0cyB0aGUgc2F2ZWRDaGF0SWQsIGdlbmVyYXRlcyBhIG5ldyBjaGF0SWQsXG4gICAqIGdlbmVyYXRlcyBhIG5ldyBjaGF0IGF1ZGl0IGV2ZW50LCBhbmQgaGFuZGxlcyB0aGUgcXVlcnkgbW9kZS5cbiAgICovXG4gIHByaXZhdGUgX3RyaWdnZXJSZWxvYWRBZnRlclF1ZXJ5Q2hhbmdlKCkge1xuICAgIGNvbnN0IHN5c3RlbU1zZyA9IHsgcm9sZTogJ3N5c3RlbScsIGNvbnRlbnQ6IHRoaXMuY29uZmlnLmRlZmF1bHRWYWx1ZXMuc3lzdGVtUHJvbXB0LCBhZGRpdGlvbmFsUHJvcGVydGllczogeyBkaXNwbGF5OiBmYWxzZSwgbWVzc2FnZUlkOiBndWlkKCkgfSB9O1xuICAgIC8vIGJhY2t3YXJkIGNvbXBhdGliaWxpdHkgd2l0aCBvbGQgY29uZmlndXJhdGlvbiBmaWxlc1xuICAgIGNvbnN0IHVzZXJQcm9tcHQgPSB0aGlzLmNvbmZpZy5kZWZhdWx0VmFsdWVzLnVzZXJQcm9tcHQucmVwbGFjZSgvXFx7XFx7KC4qPylcXH1cXH0vZywgJ1tbJDFdXScpO1xuICAgIGNvbnN0IHVzZXJNc2cgPSB7IHJvbGU6ICd1c2VyJywgY29udGVudDogQXNzaXN0YW50VXRpbHMuZm9ybWF0UHJvbXB0KHRoaXMudHJhbnNsb2NvLnRyYW5zbGF0ZSh1c2VyUHJvbXB0KSAsIHsgcHJpbmNpcGFsOiB0aGlzLnByaW5jaXBhbFNlcnZpY2UucHJpbmNpcGFsIH0pLCBhZGRpdGlvbmFsUHJvcGVydGllczogeyBkaXNwbGF5OiB0aGlzLmNvbmZpZy5tb2RlU2V0dGluZ3MuZGlzcGxheVVzZXJQcm9tcHQsIG1lc3NhZ2VJZDogZ3VpZCgpIH0gfTtcbiAgICB0aGlzLmNoYXRTZXJ2aWNlLmdlbmVyYXRlQ2hhdElkKCk7IC8vIEdlbmVyYXRlIGEgbmV3IGNoYXRJZFxuICAgIHRoaXMuY2hhdFNlcnZpY2UuZ2VuZXJhdGVBdWRpdEV2ZW50KCdhc3QtY2hhdC5uZXcnLCB7J2NvbmZpZ3VyYXRpb24nOiBKU09OLnN0cmluZ2lmeSh0aGlzLmNoYXRTZXJ2aWNlLmFzc2lzdGFudENvbmZpZyQudmFsdWUpfSk7IC8vIEdlbmVyYXRlIGEgbmV3IGNoYXQgYXVkaXQgZXZlbnRcbiAgICB0aGlzLl9oYW5kbGVRdWVyeU1vZGUoc3lzdGVtTXNnLCB1c2VyTXNnKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBBZGRzIGEgc2Nyb2xsIGxpc3RlbmVyIHRvIHRoZSBtZXNzYWdlIGxpc3QgZWxlbWVudC5cbiAgICogVGhlIGxpc3RlbmVyIGlzIHRyaWdnZXJlZCB3aGVuIGFueSBvZiB0aGUgZm9sbG93aW5nIGV2ZW50cyBvY2N1cjpcbiAgICogLSBMb2FkaW5nIHN0YXRlIGNoYW5nZXNcbiAgICogLSBNZXNzYWdlcyBjaGFuZ2VcbiAgICogLSBTdHJlYW1pbmcgc3RhdGUgY2hhbmdlc1xuICAgKiAtIFNjcm9sbCBldmVudCBvY2N1cnMgb24gdGhlIG1lc3NhZ2UgbGlzdCBlbGVtZW50XG4gICAqXG4gICAqIFdoZW4gdGhlIGxpc3RlbmVyIGlzIHRyaWdnZXJlZCwgaXQgdXBkYXRlcyB0aGUgYGlzQXRCb3R0b21gIHByb3BlcnR5LlxuICAgKi9cbiAgcHJpdmF0ZSBfYWRkU2Nyb2xsTGlzdGVuZXIoKSB7XG4gICAgdGhpcy5fc3ViLmFkZChcbiAgICAgIG1lcmdlKHRoaXMubG9hZGluZyQsIHRoaXMubWVzc2FnZXMkLCB0aGlzLmNoYXRTZXJ2aWNlLnN0cmVhbWluZyQsIGZyb21FdmVudCh0aGlzLm1lc3NhZ2VMaXN0IS5uYXRpdmVFbGVtZW50LCAnc2Nyb2xsJykpLnN1YnNjcmliZSgoKSA9PiB7XG4gICAgICAgIHRoaXMuaXNBdEJvdHRvbSA9IHRoaXMuX3RvZ2dsZVNjcm9sbEJ1dHRvblZpc2liaWxpdHkoKTtcbiAgICAgICAgdGhpcy5jZHIuZGV0ZWN0Q2hhbmdlcygpO1xuICAgICAgfSlcbiAgICApO1xuICB9XG5cbiAgLyoqXG4gICAqIEdldCB0aGUgbW9kZWwgZGVzY3JpcHRpb24gYmFzZWQgb24gdGhlIGRlZmF1bHRWYWx1ZXMgc2VydmljZV9pZCBhbmQgbW9kZWxfaWRcbiAgICovXG4gIHVwZGF0ZU1vZGVsRGVzY3JpcHRpb24oKSB7XG4gICAgdGhpcy5tb2RlbERlc2NyaXB0aW9uID0gdGhpcy5jaGF0U2VydmljZS5nZXRNb2RlbCh0aGlzLmNvbmZpZy5kZWZhdWx0VmFsdWVzLnNlcnZpY2VfaWQsIHRoaXMuY29uZmlnLmRlZmF1bHRWYWx1ZXMubW9kZWxfaWQpO1xuICAgIHRoaXMuY2RyLmRldGVjdENoYW5nZXMoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBTdWJtaXRzIGEgcXVlc3Rpb24gZnJvbSB0aGUgdXNlci5cbiAgICogSWYgdGhlIHVzZXIgaXMgZWRpdGluZyBhIHByZXZpb3VzIG1lc3NhZ2UsIHJlbW92ZXMgYWxsIHN1YnNlcXVlbnQgbWVzc2FnZXMgZnJvbSB0aGUgY2hhdCBoaXN0b3J5LlxuICAgKiBUcmlnZ2VycyB0aGUgZmV0Y2ggb2YgdGhlIGFuc3dlciBmb3IgdGhlIHN1Ym1pdHRlZCBxdWVzdGlvbiBieSBjYWxsaW5nIF9mZXRjaEFuc3dlcigpLlxuICAgKiBDbGVhcnMgdGhlIGlucHV0IHZhbHVlIGluIHRoZSBVSS5cbiAgICog4pqg77iPIElmIHRoZSBjaGF0IGlzIHN0cmVhbWluZyBvciBzdG9wcGluZyB0aGUgZ2VuZXJhdGlvbiwgdGhlIG9wZXJhdGlvbiBpcyBub3QgYWxsb3dlZC5cbiAgICovXG4gIHN1Ym1pdFF1ZXN0aW9uKCkge1xuICAgIGlmICghIXRoaXMuY2hhdFNlcnZpY2Uuc3RyZWFtaW5nJC52YWx1ZSB8fCAhIXRoaXMuY2hhdFNlcnZpY2Uuc3RvcHBpbmdHZW5lcmF0aW9uJC52YWx1ZSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBpZiAodGhpcy5xdWVzdGlvbi50cmltKCkgJiYgdGhpcy5tZXNzYWdlcyQudmFsdWUgJiYgdGhpcy5jaGF0U2VydmljZS5jaGF0SGlzdG9yeSkge1xuICAgICAgLy8gV2hlbiB0aGUgdXNlciBzdWJtaXRzIGEgcXVlc3Rpb24sIGlmIHRoZSB1c2VyIGlzIGVkaXRpbmcgYSBwcmV2aW91cyBtZXNzYWdlLCByZW1vdmUgYWxsIHN1YnNlcXVlbnQgbWVzc2FnZXMgZnJvbSB0aGUgY2hhdCBoaXN0b3J5XG4gICAgICBpZiAodGhpcy5pbmRleE1lc3NhZ2VUb0VkaXQgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAvLyBVcGRhdGUgdGhlIG1lc3NhZ2VzIGluIHRoZSBVSVxuICAgICAgICB0aGlzLm1lc3NhZ2VzJC5uZXh0KHRoaXMubWVzc2FnZXMkLnZhbHVlLnNsaWNlKDAsIHRoaXMuaW5kZXhNZXNzYWdlVG9FZGl0KSk7XG4gICAgICAgIC8vIFVwZGF0ZSB0aGUgcmF3IG1lc3NhZ2VzIGluIHRoZSBjaGF0IGhpc3Rvcnkgd2hpY2ggaXMgdGhlIGNsZWFuIHZlcnNpb24gdXNlZCB0byBtYWtlIHRoZSBuZXh0IHJlcXVlc3RcbiAgICAgICAgdGhpcy5jaGF0U2VydmljZS5jaGF0SGlzdG9yeSA9IHRoaXMuY2hhdFNlcnZpY2UuY2hhdEhpc3Rvcnkuc2xpY2UoMCwgdGhpcy5yYW5rTWVzc2FnZVRvRWRpdCk7XG4gICAgICAgIHRoaXMuaW5kZXhNZXNzYWdlVG9FZGl0ID0gdW5kZWZpbmVkO1xuICAgICAgICB0aGlzLnJhbmtNZXNzYWdlVG9FZGl0ID0gdW5kZWZpbmVkO1xuICAgICAgfVxuICAgICAgLy8gUmVtb3ZlIHRoZSBzZWFyY2ggd2FybmluZyBtZXNzYWdlIGlmIGV4aXN0c1xuICAgICAgaWYgKHRoaXMuY2hhdFNlcnZpY2UuY2hhdEhpc3RvcnkuYXQoLTEpPy5yb2xlID09PSAnc2VhcmNoLXdhcm5pbmcnKSB7XG4gICAgICAgIHRoaXMuY2hhdFNlcnZpY2UuY2hhdEhpc3RvcnkucG9wKCk7XG4gICAgICB9XG4gICAgICAvLyBGZXRjaCB0aGUgYW5zd2VyXG4gICAgICB0aGlzLl9mZXRjaEFuc3dlcih0aGlzLnF1ZXN0aW9uLnRyaW0oKSwgdGhpcy5jaGF0U2VydmljZS5jaGF0SGlzdG9yeSk7XG4gICAgICAvLyBDbGVhciB0aGUgaW5wdXQgdmFsdWUgaW4gdGhlIFVJXG4gICAgICB0aGlzLnF1ZXN0aW9uSW5wdXQhLm5hdGl2ZUVsZW1lbnQudmFsdWUgPSAnJztcbiAgICAgIHRoaXMucXVlc3Rpb25JbnB1dCEubmF0aXZlRWxlbWVudC5zdHlsZS5oZWlnaHQgPSBgYXV0b2A7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFRyaWdnZXJzIHRoZSBmZXRjaCBvZiB0aGUgYW5zd2VyIGZvciB0aGUgZ2l2ZW4gcXVlc3Rpb24gYW5kIHVwZGF0ZXMgdGhlIGNvbnZlcnNhdGlvbi5cbiAgICogR2VuZXJhdGVzIGFuIGF1ZGl0IGV2ZW50IGZvciB0aGUgdXNlciBpbnB1dC5cbiAgICpcbiAgICogQHBhcmFtIHF1ZXN0aW9uIC0gVGhlIHF1ZXN0aW9uIGFza2VkIGJ5IHRoZSB1c2VyLlxuICAgKiBAcGFyYW0gY29udmVyc2F0aW9uIC0gVGhlIGN1cnJlbnQgY29udmVyc2F0aW9uIG1lc3NhZ2VzLlxuICAgKi9cbiAgcHJpdmF0ZSBfZmV0Y2hBbnN3ZXIocXVlc3Rpb246IHN0cmluZywgY29udmVyc2F0aW9uOiBDaGF0TWVzc2FnZVtdKSB7XG4gICAgLy8gbWVyZ2UgYWRkaXRpb25hbFdvcmtmbG93UHJvcGVydGllcyBmcm9tIHRoZSBjaGF0IGNvbXBvbmVudCBhbmQgdGhlIGN1c3RvbWl6YXRpb24gSlNPTlxuICAgIGNvbnN0IGFkZGl0aW9uYWxXb3JrZmxvd1Byb3BlcnRpZXMgPSB7IC4uLnRoaXMuY29uZmlnLmFkZGl0aW9uYWxXb3JrZmxvd1Byb3BlcnRpZXMsIC4uLnRoaXMuYWRkaXRpb25hbFdvcmtmbG93UHJvcGVydGllcyB9O1xuICAgIGNvbnN0IHVzZXJNc2cgPSB7IHJvbGU6ICd1c2VyJywgY29udGVudDogcXVlc3Rpb24sIGFkZGl0aW9uYWxQcm9wZXJ0aWVzOiB7IGRpc3BsYXk6IHRydWUsIG1lc3NhZ2VJZDogZ3VpZCgpLCBpc1VzZXJJbnB1dDogdHJ1ZSwgYWRkaXRpb25hbFdvcmtmbG93UHJvcGVydGllcyB9IH07XG4gICAgY29uc3QgbWVzc2FnZXMgPSBbLi4uY29udmVyc2F0aW9uLCB1c2VyTXNnXTtcbiAgICB0aGlzLm1lc3NhZ2VzJC5uZXh0KG1lc3NhZ2VzKTsgLy8gVXBkYXRlIHRoZSBtZXNzYWdlcyBpbiB0aGUgVUkgd2l0aCB0aGUgbmV3IHVzZXIgbWVzc2FnZVxuICAgIHRoaXMuY2hhdFNlcnZpY2UuY2hhdEhpc3RvcnkgPSBtZXNzYWdlczsgLy8gVXBkYXRlIHRoZSBjaGF0IGhpc3Rvcnkgd2l0aCB0aGUgbmV3IHVzZXIgbWVzc2FnZVxuICAgIHRoaXMuZmV0Y2gobWVzc2FnZXMpO1xuICAgIHRoaXMuY2hhdFNlcnZpY2UuZ2VuZXJhdGVBdWRpdEV2ZW50KCdhc3QtbWVzc2FnZS5tZXNzYWdlJywgeyAuLi50aGlzLl9kZWZpbmVNZXNzYWdlQXVkaXREZXRhaWxzKHVzZXJNc2cpLCAncXVlcnknOiBKU09OLnN0cmluZ2lmeSh0aGlzLnF1ZXJ5KSwgJ2lzLXVzZXItaW5wdXQnOiB0cnVlLCAnZW5hYmxlZC1mdW5jdGlvbnMnOiB0aGlzLmNvbmZpZy5kZWZhdWx0VmFsdWVzLmZ1bmN0aW9ucz8uZmlsdGVyKGZ1bmMgPT4gZnVuYy5lbmFibGVkKS5tYXAoZnVuYyA9PiBmdW5jLm5hbWUpLCAnYWRkaXRpb25hbC13b3JrZmxvdy1wcm9wZXJ0aWVzJzogSlNPTi5zdHJpbmdpZnkoYWRkaXRpb25hbFdvcmtmbG93UHJvcGVydGllcykgfSk7XG4gIH1cblxuICAvKipcbiAgICogRGVwZW5kaW5nIG9uIHRoZSBjb25uZWN0aW9uJ3Mgc3RhdGUgOlxuICAgKiAgLSBJZiBjb25uZWN0ZWQgPT4gZ2l2ZW4gYSBsaXN0IG9mIG1lc3NhZ2VzLCB0aGUgY2hhdCBlbmRwb2ludCBpcyBpbnZva2VkIGZvciBhIGNvbnRpbnVhdGlvbiBhbmQgdXBkYXRlcyB0aGUgbGlzdCBvZiBtZXNzYWdlcyBhY2NvcmRpbmdseS5cbiAgICogIC0gSWYgYW55IG90aGVyIHN0YXRlID0+IGEgY29ubmVjdGlvbiBlcnJvciBtZXNzYWdlIGlzIGRpc3BsYXllZCBpbiB0aGUgY2hhdC5cbiAgICog4pqg77iPIElmIHRoZSBhc3Npc3RhbnQgaXMgc3RyZWFtaW5nIG9yIHN0b3BwaW5nIHRoZSBnZW5lcmF0aW9uLCB0aGUgb3BlcmF0aW9uIGlzIG5vdCBhbGxvd2VkLlxuICAgKiBAcGFyYW0gbWVzc2FnZXMgVGhlIGxpc3Qgb2YgbWVzc2FnZXMgdG8gaW52b2tlIHRoZSBjaGF0IGVuZHBvaW50IHdpdGhcbiAgICovXG4gIHB1YmxpYyBmZXRjaChtZXNzYWdlczogQ2hhdE1lc3NhZ2VbXSkge1xuICAgIGlmICghIXRoaXMuY2hhdFNlcnZpY2Uuc3RyZWFtaW5nJC52YWx1ZSB8fCAhIXRoaXMuY2hhdFNlcnZpY2Uuc3RvcHBpbmdHZW5lcmF0aW9uJC52YWx1ZSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICB0aGlzLl91cGRhdGVDb25uZWN0aW9uU3RhdHVzKCk7XG4gICAgdGhpcy5jZHIuZGV0ZWN0Q2hhbmdlcygpO1xuXG4gICAgaWYgKHRoaXMuaXNDb25uZWN0ZWQpIHtcbiAgICAgIHRoaXMubG9hZGluZyQubmV4dCh0cnVlKTtcbiAgICAgIHRoaXMuX2RhdGFTdWJzY3JpcHRpb24/LnVuc3Vic2NyaWJlKCk7XG4gICAgICB0aGlzLl9kYXRhU3Vic2NyaXB0aW9uID0gdGhpcy5jaGF0U2VydmljZS5mZXRjaChtZXNzYWdlcywgdGhpcy5xdWVyeSlcbiAgICAgICAgLnN1YnNjcmliZSh7XG4gICAgICAgICAgbmV4dDogcmVzID0+IHRoaXMudXBkYXRlRGF0YShyZXMuaGlzdG9yeSksXG4gICAgICAgICAgZXJyb3I6ICgpID0+IHtcbiAgICAgICAgICAgIHRoaXMuX3VwZGF0ZUNvbm5lY3Rpb25TdGF0dXMoKTtcbiAgICAgICAgICAgIGlmICghdGhpcy5pc0Nvbm5lY3RlZCkge1xuICAgICAgICAgICAgICBjb25zdCBtZXNzYWdlID0ge1xuICAgICAgICAgICAgICAgIHJvbGU6ICdjb25uZWN0aW9uLWVycm9yJyxcbiAgICAgICAgICAgICAgICBjb250ZW50OiAoeyB0eXBlOiBcInRleHRcIiwgdGV4dDogdGhpcy50cmFuc2xvY28udHJhbnNsYXRlKHRoaXMuY29uZmlnLmNvbm5lY3Rpb25TZXR0aW5ncy5jb25uZWN0aW9uRXJyb3JNZXNzYWdlKSB9IGFzIFRleHRNZXNzYWdlQ29udGVudCksXG4gICAgICAgICAgICAgICAgYWRkaXRpb25hbFByb3BlcnRpZXM6IHsgZGlzcGxheTogdHJ1ZSwgbWVzc2FnZUlkOiBndWlkKCkgfVxuICAgICAgICAgICAgICB9IGFzIGFueSBhcyBDaGF0TWVzc2FnZTtcbiAgICAgICAgICAgICAgdGhpcy5tZXNzYWdlcyQubmV4dChbLi4ubWVzc2FnZXMsIG1lc3NhZ2VdKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMudGVybWluYXRlRmV0Y2goKTtcbiAgICAgICAgICB9LFxuICAgICAgICAgIGNvbXBsZXRlOiAoKSA9PiB7XG4gICAgICAgICAgICAvLyBSZW1vdmUgdGhlIGxhc3QgbWVzc2FnZSBpZiBpdCdzIGFuIGVtcHR5IG1lc3NhZ2VcbiAgICAgICAgICAgIC8vIFRoaXMgaXMgZHVlIHRvIHRoZSBtYW5uZXIgaW4gd2hpY2ggdGhlIGNoYXQgc2VydmljZSBoYW5kbGVzIGNvbnNlY3V0aXZlIG1lc3NhZ2VzXG4gICAgICAgICAgICBjb25zdCBsYXN0TWVzc2FnZSA9IHRoaXMubWVzc2FnZXMkLnZhbHVlPy5hdCgtMSk7XG4gICAgICAgICAgICBpZiAodGhpcy5pc0VtcHR5QXNzaXN0YW50TWVzc2FnZShsYXN0TWVzc2FnZSkpIHtcbiAgICAgICAgICAgICAgdGhpcy5tZXNzYWdlcyQubmV4dCh0aGlzLm1lc3NhZ2VzJC52YWx1ZT8uc2xpY2UoMCwgLTEpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMudGVybWluYXRlRmV0Y2goKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH0gZWxzZSB7XG4gICAgICBjb25zdCBtZXNzYWdlID0geyByb2xlOiAnY29ubmVjdGlvbi1lcnJvcicsIGNvbnRlbnQ6IHRoaXMudHJhbnNsb2NvLnRyYW5zbGF0ZSh0aGlzLmNvbmZpZy5jb25uZWN0aW9uU2V0dGluZ3MuY29ubmVjdGlvbkVycm9yTWVzc2FnZSksIGFkZGl0aW9uYWxQcm9wZXJ0aWVzOiB7IGRpc3BsYXk6IHRydWUsIG1lc3NhZ2VJZDogZ3VpZCgpIH0gfTtcbiAgICAgIHRoaXMubWVzc2FnZXMkLm5leHQoWy4uLm1lc3NhZ2VzLCBtZXNzYWdlXSk7XG4gICAgfVxuXG4gICAgaWYgKHRoaXMuYXV0b21hdGljU2Nyb2xsVG9MYXN0UmVzcG9uc2UpIHtcbiAgICAgIHRoaXMuc2Nyb2xsRG93bigpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBSZXRyeSB0byBmZXRjaCB0aGUgbWVzc2FnZXMgaWYgdGhlIGNvbm5lY3Rpb24gaXNzdWVzLlxuICAgKiAgLSBJZiByZWNvbm5lY3RpbmcgPT4ga2VlcCBkaXNwbGF5IHRoZSBjb25uZWN0aW9uIGVycm9yIG1lc3NhZ2UgZXZlbiB3aGVuIGNsaWNraW5nIG9uIHRoZSBcInJldHJ5XCIgYnV0dG9uIGFuZCBpbmNyZWFzaW5nIHRoZSBudW1iZXIgb2YgcmV0cmlhbCBhdHRlbXB0cywgdW50aWwgdGhlIGNvbm5lY3Rpb24gaXMgcmUtZXN0YWJsaXNoZWRcbiAgICogIC0gSWYgZGlzY29ubmVjdGVkID0+IE9uIGNsaWNrIG9uIHRoZSBcInJldHJ5XCIgYnV0dG9uLCBzdGFydCB0aGUgY29ubmVjdGlvbiBwcm9jZXNzIHdoaWxlIGRpc3BsYXlpbmcgdGhlIGNvbm5lY3Rpb24gZXJyb3IgbWVzc2FnZSA6XG4gICAqICAgICAgKiBJZiBzdWNjZXNzZnVsID0+IGdpdmVuIGEgbGlzdCBvZiBtZXNzYWdlcywgdGhlIGNoYXQgZW5kcG9pbnQgaXMgaW52b2tlZCBmb3IgYSBjb250aW51YXRpb24gYW5kIHVwZGF0ZXMgdGhlIGxpc3Qgb2YgbWVzc2FnZXMgYWNjb3JkaW5nbHkuXG4gICAqICAgICAgKiBJZiBmYWlsZWQgPT4gaW5jcmVhc2UgdGhlIG51bWJlciBvZiByZXRyaWFsIGF0dGVtcHRzXG4gICAqL1xuICByZXRyeUZldGNoKCkge1xuICAgIC8vIEEgb25lLXRpbWUgbGlzdGVuZXIgZm9yIHJlY29ubmVjdGVkIGV2ZW50XG4gICAgY29uc3Qgb25SZWNvbm5lY3RlZEhhbmRsZXIgPSAoKSA9PiB7XG4gICAgICAvLyBHZXQgdGhlIG1lc3NhZ2VzIHdpdGhvdXQgdGhlIGxhc3Qgb25lICh0aGUgY29ubmVjdGlvbiBlcnJvciBtZXNzYWdlKVxuICAgICAgY29uc3QgbWVzc2FnZXMgPSB0aGlzLm1lc3NhZ2VzJC52YWx1ZSEuc2xpY2UoMCwgLTEpO1xuICAgICAgLy8gRmluZCB0aGUgbGFzdCBcInVzZXJcIiBtZXNzYWdlIGluIHRoZSBtZXNzYWdlcyBsaXN0XG4gICAgICBsZXQgaW5kZXggPSBtZXNzYWdlcy5sZW5ndGggLSAxO1xuICAgICAgd2hpbGUgKGluZGV4ID49IDAgJiYgbWVzc2FnZXNbaW5kZXhdLnJvbGUgIT09ICd1c2VyJykge1xuICAgICAgICBpbmRleC0tO1xuICAgICAgfVxuICAgICAgLy8gSWYgYSB1c2VyIG1lc3NhZ2UgaXMgZm91bmQgKGFuZCBpdCBzaG91bGQgYWx3YXlzIGJlIHRoZSBjYXNlKSwgcmVtb3ZlIGFsbCBzdWJzZXF1ZW50IG1lc3NhZ2VzIGZyb20gdGhlIGNoYXQgaGlzdG9yeVxuICAgICAgLy8gVXBkYXRlIHRoZSBtZXNzYWdlcyBpbiB0aGUgVUlcbiAgICAgIC8vIGFuZCBmZXRjaCB0aGUgYW5zd2VyIGZyb20gdGhlIGFzc2lzdGFudFxuICAgICAgaWYgKGluZGV4ID49IDApIHtcbiAgICAgICAgdGhpcy5tZXNzYWdlcyQubmV4dCh0aGlzLm1lc3NhZ2VzJC52YWx1ZSEuc2xpY2UoMCwgaW5kZXggKyAxKSk7XG4gICAgICAgIGNvbnN0IHJlbWFwcGVkSW5kZXggPSB0aGlzLmFzc2lzdGFudFV0aWxzLmdldE1lc3NhZ2VSYW5rSW5DaGF0SGlzdG9yeSh0aGlzLmNoYXRTZXJ2aWNlLmNoYXRIaXN0b3J5LCBtZXNzYWdlc1tpbmRleF0uYWRkaXRpb25hbFByb3BlcnRpZXMubWVzc2FnZUlkKTtcbiAgICAgICAgdGhpcy5jaGF0U2VydmljZS5jaGF0SGlzdG9yeSA9IHRoaXMuY2hhdFNlcnZpY2UuY2hhdEhpc3RvcnkhLnNsaWNlKDAsIHJlbWFwcGVkSW5kZXggKyAxKTtcbiAgICAgICAgdGhpcy5mZXRjaCh0aGlzLmNoYXRTZXJ2aWNlLmNoYXRIaXN0b3J5KTtcbiAgICAgIH1cbiAgICAgIHRoaXMucmV0cmlhbEF0dGVtcHRzID0gdW5kZWZpbmVkOyAvLyBSZXNldCB0aGUgbnVtYmVyIG9mIHJldHJpYWwgYXR0ZW1wdHNcbiAgICAgIC8qKlxuICAgICAgICogVG8gcmVtb3ZlIHRoZSBoYW5kbGVyIGZvciBvbnJlY29ubmVjdGVkKCkgYWZ0ZXIgaXQncyBiZWVuIHJlZ2lzdGVyZWQsY2Fubm90IGRpcmVjdGx5IHVzZSBvZmYoKSBsaWtlIHlvdSB3b3VsZCBmb3Igbm9ybWFsIGV2ZW50cyByZWdpc3RlcmVkIHdpdGggY29ubmVjdGlvbi5vbigpLlxuICAgICAgICogSW5zdGVhZCwgeW91IG5lZWQgdG8gZXhwbGljaXRseSByZW1vdmUgb3IgcmVzZXQgdGhlIGhhbmRsZXIgYnkgYXNzaWduaW5nIGl0IHRvIG51bGwgb3IgYW4gZW1wdHkgZnVuY3Rpb25cbiAgICAgICAqL1xuICAgICAgdGhpcy5jaGF0U2VydmljZS5jb25uZWN0aW9uIS5vbnJlY29ubmVjdGVkKCgpID0+IHt9KTtcbiAgICAgIC8vIFJlc2V0IHRoZSBmbGFnIHRvIGVuc3VyZSB0aGUgaGFuZGxlciBpcyByZWdpc3RlcmVkIGFnYWluIHdoZW4gbmVlZGVkXG4gICAgICB0aGlzLl9pc1JlY29ubmVjdGVkTGlzdGVuZXJSZWdpc3RlcmVkID0gZmFsc2U7XG4gICAgfVxuICAgIC8vIERlcGVuZGluZyBvbiB0aGUgY29ubmVjdGlvbidzIHN0YXRlLCB0YWtlIHRoZSBhcHByb3ByaWF0ZSBhY3Rpb25cbiAgICBzd2l0Y2ggKHRoaXMuY2hhdFNlcnZpY2UuY29ubmVjdGlvbiEuc3RhdGUpIHtcbiAgICAgIGNhc2UgSHViQ29ubmVjdGlvblN0YXRlLkNvbm5lY3RlZDpcbiAgICAgICAgLy8gSWYgdGhlIGNvbm5lY3Rpb24gaXMgcmUtZXN0YWJsaXNoZWQgaW4gdGhlIG1lYW50aW1lLCBmZXRjaCB0aGUgbWVzc2FnZXNcbiAgICAgICAgb25SZWNvbm5lY3RlZEhhbmRsZXIoKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIEh1YkNvbm5lY3Rpb25TdGF0ZS5SZWNvbm5lY3Rpbmc6XG4gICAgICAgIC8vIEF0dGFjaCB0aGUgcmVjb25uZWN0ZWQgbGlzdGVuZXIgaWYgbm90IGFscmVhZHkgcmVnaXN0ZXJlZFxuICAgICAgICBpZiAoIXRoaXMuX2lzUmVjb25uZWN0ZWRMaXN0ZW5lclJlZ2lzdGVyZWQpIHtcbiAgICAgICAgICB0aGlzLmNoYXRTZXJ2aWNlLmNvbm5lY3Rpb24hLm9ucmVjb25uZWN0ZWQob25SZWNvbm5lY3RlZEhhbmRsZXIpO1xuICAgICAgICAgIHRoaXMuX2lzUmVjb25uZWN0ZWRMaXN0ZW5lclJlZ2lzdGVyZWQgPSB0cnVlO1xuICAgICAgICB9XG4gICAgICAgIC8vIEluY3JlYXNlIHRoZSBudW1iZXIgb2YgcmV0cmlhbCBhdHRlbXB0c1xuICAgICAgICB0aGlzLnJldHJpYWxBdHRlbXB0cyA9IHRoaXMucmV0cmlhbEF0dGVtcHRzID8gdGhpcy5yZXRyaWFsQXR0ZW1wdHMgKyAxIDogMTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIEh1YkNvbm5lY3Rpb25TdGF0ZS5EaXNjb25uZWN0ZWQ6XG4gICAgICAgIC8vIFN0YXJ0IHRoZSBuZXcgY29ubmVjdGlvblxuICAgICAgICB0aGlzLmNoYXRTZXJ2aWNlLnN0YXJ0Q29ubmVjdGlvbigpXG4gICAgICAgICAgLnRoZW4oKCkgPT4gb25SZWNvbm5lY3RlZEhhbmRsZXIoKSlcbiAgICAgICAgICAuY2F0Y2goKCkgPT4geyAvLyBJZiB0aGUgY29ubmVjdGlvbiBmYWlscywgaW5jcmVhc2UgdGhlIG51bWJlciBvZiByZXRyaWFsIGF0dGVtcHRzXG4gICAgICAgICAgICB0aGlzLnJldHJpYWxBdHRlbXB0cyA9IHRoaXMucmV0cmlhbEF0dGVtcHRzID8gdGhpcy5yZXRyaWFsQXR0ZW1wdHMgKyAxIDogMTtcbiAgICAgICAgICB9KTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICBicmVhaztcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQ2hlY2sgaWYgdGhlIHNpZ25hbFIgY29ubmVjdGlvbiBpcyBjb25uZWN0ZWQuXG4gICAqIEZvciB0aGUgUkVTVCBwcm90b2NvbCwgdGhlIGNvbm5lY3Rpb24gaXMgYWx3YXlzIGNvbnNpZGVyZWQgY29ubmVjdGVkIChmb3IgdGhlIG1vbWVudCkuXG4gICAqL1xuICBwcml2YXRlIF91cGRhdGVDb25uZWN0aW9uU3RhdHVzKCkge1xuICAgIHRoaXMuaXNDb25uZWN0ZWQgPSB0aGlzLmNoYXRTZXJ2aWNlLmNvbm5lY3Rpb24hLnN0YXRlID09PSBIdWJDb25uZWN0aW9uU3RhdGUuQ29ubmVjdGVkO1xuICB9XG5cbiAgLyoqXG4gICAqIFVwZGF0ZSB0aGUgVUkgd2l0aCB0aGUgbmV3IG1lc3NhZ2VzXG4gICAqIEBwYXJhbSBtZXNzYWdlc1xuICAgKi9cbiAgdXBkYXRlRGF0YShtZXNzYWdlczogQ2hhdE1lc3NhZ2VbXSkge1xuICAgIHRoaXMubWVzc2FnZXMkLm5leHQobWVzc2FnZXMpO1xuICAgIHRoaXMuZGF0YS5lbWl0KG1lc3NhZ2VzKTtcbiAgICB0aGlzLmxvYWRpbmckLm5leHQoZmFsc2UpO1xuICAgIHRoaXMucXVlc3Rpb24gPSAnJztcbiAgICBpZiAodGhpcy5hdXRvbWF0aWNTY3JvbGxUb0xhc3RSZXNwb25zZSkge1xuICAgICAgdGhpcy5zY3JvbGxEb3duKCk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEByZXR1cm5zIHRydWUgaWYgdGhlIGNoYXQgZGlzY3Vzc2lvbiBpcyBzY3JvbGxlZCBkb3duIHRvIHRoZSBib3R0b20sIGZhbHNlIG90aGVyd2lzZVxuICAgKi9cbiAgcHJpdmF0ZSBfdG9nZ2xlU2Nyb2xsQnV0dG9uVmlzaWJpbGl0eSgpOiBib29sZWFuIHtcbiAgICBpZiAodGhpcy5tZXNzYWdlTGlzdD8ubmF0aXZlRWxlbWVudCkge1xuICAgICAgcmV0dXJuIE1hdGgucm91bmQodGhpcy5tZXNzYWdlTGlzdD8ubmF0aXZlRWxlbWVudC5zY3JvbGxIZWlnaHQgLSB0aGlzLm1lc3NhZ2VMaXN0Py5uYXRpdmVFbGVtZW50LnNjcm9sbFRvcCAtIDEpIDw9IHRoaXMubWVzc2FnZUxpc3Q/Lm5hdGl2ZUVsZW1lbnQuY2xpZW50SGVpZ2h0O1xuICAgIH1cbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBTY3JvbGwgZG93biB0byB0aGUgYm90dG9tIG9mIHRoZSBjaGF0IGRpc2N1c3Npb25cbiAgICovXG4gIHNjcm9sbERvd24oKSB7XG4gICAgc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICBpZiAodGhpcy5tZXNzYWdlTGlzdD8ubmF0aXZlRWxlbWVudCkge1xuICAgICAgICB0aGlzLm1lc3NhZ2VMaXN0Lm5hdGl2ZUVsZW1lbnQuc2Nyb2xsVG9wID0gdGhpcy5tZXNzYWdlTGlzdC5uYXRpdmVFbGVtZW50LnNjcm9sbEhlaWdodDtcbiAgICAgICAgdGhpcy5jZHIuZGV0ZWN0Q2hhbmdlcygpO1xuICAgICAgfVxuICAgIH0sIDEwKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBTdGFydCBhIG5ldyBjaGF0IHdpdGggdGhlIGRlZmF1bHRWYWx1ZXMgc2V0dGluZ3MuXG4gICAqIFRoZSBzYXZlZENoYXRJZCBpbiB0aGUgY2hhdCBzZXJ2aWNlIHdpbGwgYmUgcmVzZXQsIHNvIHRoYXQgdGhlIHVwY29taW5nIHNhdmVkIGNoYXQgb3BlcmF0aW9ucyB3aWxsIGJlIHBlcmZvcm1lZCBvbiB0aGUgZnJlc2ggbmV3IGNoYXQuXG4gICAqIElmIHRoZSBzYXZlZENoYXQgZmVhdHVyZSBpcyBlbmFibGVkLCB0aGUgbGlzdCBvZiBzYXZlZCBjaGF0cyB3aWxsIGJlIHJlZnJlc2hlZC5cbiAgICog4pqg77iPIElmIHRoZSBhc3Npc3RhbnQgaXMgc3RyZWFtaW5nIG9yIHN0b3BwaW5nIHRoZSBnZW5lcmF0aW9uLCB0aGUgb3BlcmF0aW9uIGlzIG5vdCBhbGxvd2VkLlxuICAgKi9cbiAgbmV3Q2hhdCgpIHtcbiAgICBpZiAoISF0aGlzLmNoYXRTZXJ2aWNlLnN0cmVhbWluZyQudmFsdWUgfHwgISF0aGlzLmNoYXRTZXJ2aWNlLnN0b3BwaW5nR2VuZXJhdGlvbiQudmFsdWUpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgdGhpcy5jaGF0U2VydmljZS5nZW5lcmF0ZUNoYXRJZCgpOyAvLyBHZW5lcmF0ZSBhIG5ldyBjaGF0SWRcbiAgICBpZiAodGhpcy5jb25maWcuc2F2ZWRDaGF0U2V0dGluZ3M/LmVuYWJsZWQpIHtcbiAgICAgIHRoaXMuY2hhdFNlcnZpY2UubGlzdFNhdmVkQ2hhdCgpOyAvLyBSZWZyZXNoIHRoZSBsaXN0IG9mIHNhdmVkIGNoYXRzXG4gICAgfVxuICAgIHRoaXMuY2hhdFNlcnZpY2UuZ2VuZXJhdGVBdWRpdEV2ZW50KCdhc3QtY2hhdC5uZXcnLCB7J2NvbmZpZ3VyYXRpb24nOiBKU09OLnN0cmluZ2lmeSh0aGlzLmNoYXRTZXJ2aWNlLmFzc2lzdGFudENvbmZpZyQudmFsdWUpfSk7IC8vIEdlbmVyYXRlIGEgbmV3IGNoYXQgYXVkaXQgZXZlbnRcbiAgICB0aGlzLmxvYWREZWZhdWx0Q2hhdCgpOyAvLyBTdGFydCBhIG5ldyBjaGF0XG4gIH1cblxuICAvKipcbiAgICogQXR0YWNoZXMgdGhlIHNwZWNpZmllZCBkb2N1bWVudCBJRHMgdG8gdGhlIGFzc2lzdGFudC5cbiAgICogSWYgbm8gZG9jdW1lbnQgSURzIGFyZSBwcm92aWRlZCwgdGhlIG9wZXJhdGlvbiBpcyBub3QgYWxsb3dlZC5cbiAgICogSWYgdGhlIGFjdGlvbiBmb3IgYXR0YWNoaW5nIGEgZG9jdW1lbnQgaXMgbm90IGRlZmluZWQgYXQgdGhlIGFwcGxpY2F0aW9uIGN1c3RvbWl6YXRpb24gbGV2ZWwsIGFuIGVycm9yIGlzIGxvZ2dlZC5cbiAgICog4pqg77iPIElmIHRoZSBhc3Npc3RhbnQgaXMgc3RyZWFtaW5nIG9yIHN0b3BwaW5nIHRoZSBnZW5lcmF0aW9uLCB0aGUgb3BlcmF0aW9uIGlzIG5vdCBhbGxvd2VkLlxuICAgKiBAcGFyYW0gaWRzIC0gQW4gYXJyYXkgb2YgZG9jdW1lbnQgSURzIHRvIGF0dGFjaC5cbiAgICovXG4gIGF0dGFjaFRvQ2hhdChpZHM6IHN0cmluZ1tdKSB7XG4gICAgaWYgKCEhdGhpcy5jaGF0U2VydmljZS5zdHJlYW1pbmckLnZhbHVlIHx8ICEhdGhpcy5jaGF0U2VydmljZS5zdG9wcGluZ0dlbmVyYXRpb24kLnZhbHVlKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGlmICghaWRzIHx8IGlkcz8ubGVuZ3RoIDwgMSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBjb25zdCBhdHRhY2hEb2NBY3Rpb24gPSB0aGlzLmNvbmZpZy5tb2RlU2V0dGluZ3MuYWN0aW9ucz8uW1wiYXR0YWNoRG9jQWN0aW9uXCJdO1xuICAgIGlmICghYXR0YWNoRG9jQWN0aW9uKSB7XG4gICAgICBjb25zb2xlLmVycm9yKGBObyBhY3Rpb24gaXMgZGVmaW5lZCBmb3IgYXR0YWNoaW5nIGEgZG9jdW1lbnQgdG8gdGhlIGFzc2lzdGFudCBcIiR7dGhpcy5pbnN0YW5jZUlkfVwiYCk7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGNvbnN0IHVzZXJNc2cgPSB7IHJvbGU6ICd1c2VyJywgY29udGVudDogJycsIGFkZGl0aW9uYWxQcm9wZXJ0aWVzOiB7ZGlzcGxheTogZmFsc2UsIG1lc3NhZ2VJZDogZ3VpZCgpLCBpc1VzZXJJbnB1dDogZmFsc2UsIHR5cGU6IFwiQWN0aW9uXCIsIGZvcmNlZFdvcmtmbG93OiBhdHRhY2hEb2NBY3Rpb24uZm9yY2VkV29ya2Zsb3csIGZvcmNlZFdvcmtmbG93UHJvcGVydGllczogey4uLihhdHRhY2hEb2NBY3Rpb24uZm9yY2VkV29ya2Zsb3dQcm9wZXJ0aWVzIHx8IHt9KSwgaWRzfSwgYWRkaXRpb25hbFdvcmtmbG93UHJvcGVydGllczogdGhpcy5jb25maWcuYWRkaXRpb25hbFdvcmtmbG93UHJvcGVydGllc319O1xuICAgIC8vIFJlbW92ZSB0aGUgc2VhcmNoIHdhcm5pbmcgbWVzc2FnZSBpZiBleGlzdHNcbiAgICBpZiAodGhpcy5jaGF0U2VydmljZS5jaGF0SGlzdG9yeSEuYXQoLTEpPy5yb2xlID09PSAnc2VhcmNoLXdhcm5pbmcnKSB7XG4gICAgICB0aGlzLmNoYXRTZXJ2aWNlLmNoYXRIaXN0b3J5IS5wb3AoKTtcbiAgICB9XG4gICAgY29uc3QgbWVzc2FnZXMgPSBbLi4udGhpcy5jaGF0U2VydmljZS5jaGF0SGlzdG9yeSEsIHVzZXJNc2ddO1xuICAgIHRoaXMubWVzc2FnZXMkLm5leHQobWVzc2FnZXMpO1xuICAgIHRoaXMuZmV0Y2gobWVzc2FnZXMpO1xuICAgIHRoaXMuY2hhdFNlcnZpY2UuZ2VuZXJhdGVBdWRpdEV2ZW50KCdhc3QtYWN0aW9uLnJlcXVlc3RlZCcsIHtcbiAgICAgICdkZXRhaWwnOiAnYXR0YWNoRG9jQWN0aW9uJyxcbiAgICAgICdmb3JjZWQtd29ya2Zsb3cnOiAnU2luZXF1YUFkZFNlbGVjdGVkRG9jdW1lbnRzV29ya2Zsb3cnLFxuICAgICAgJ2ZvcmNlZC13b3JrZmxvdy1wcm9wZXJ0aWVzJzogSlNPTi5zdHJpbmdpZnkoaWRzKSxcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBTdGFydCB0aGUgZGVmYXVsdCBjaGF0IHdpdGggdGhlIGRlZmF1bHRWYWx1ZXMgc2V0dGluZ3NcbiAgICogSWYgdGhlIGNoYXQgaXMgbWVhbnQgdG8gYmUgaW5pdGlhbGl6ZWQgd2l0aCBldmVudCA9PT0gXCJRdWVyeVwiLCB0aGUgY29ycmVzcG9uZGluZyB1c2VyIHF1ZXJ5IG1lc3NhZ2Ugd2lsbCBiZSBhZGRlZCB0byB0aGUgY2hhdCBoaXN0b3J5XG4gICAqL1xuICBsb2FkRGVmYXVsdENoYXQoKSB7XG4gICAgLy8gRGVmaW5lIHRoZSBkZWZhdWx0IHN5c3RlbSBwcm9tcHQgYW5kIHVzZXIgcHJvbXB0IG1lc3NhZ2VzXG4gICAgY29uc3Qgc3lzdGVtTXNnID0geyByb2xlOiAnc3lzdGVtJywgY29udGVudDogdGhpcy5jb25maWcuZGVmYXVsdFZhbHVlcy5zeXN0ZW1Qcm9tcHQsIGFkZGl0aW9uYWxQcm9wZXJ0aWVzOiB7IGRpc3BsYXk6IGZhbHNlLCBtZXNzYWdlSWQ6IGd1aWQoKSB9IH07XG4gICAgLy8gYmFja3dhcmQgY29tcGF0aWJpbGl0eSB3aXRoIG9sZCBjb25maWd1cmF0aW9uIGZpbGVzXG4gICAgY29uc3QgdXNlclByb21wdCA9IHRoaXMuY29uZmlnLmRlZmF1bHRWYWx1ZXMudXNlclByb21wdC5yZXBsYWNlKC9cXHtcXHsoLio/KVxcfVxcfS9nLCAnW1skMV1dJyk7XG4gICAgY29uc3QgdXNlck1zZyA9IHsgcm9sZTogJ3VzZXInLCBjb250ZW50OiBBc3Npc3RhbnRVdGlscy5mb3JtYXRQcm9tcHQodGhpcy50cmFuc2xvY28udHJhbnNsYXRlKHVzZXJQcm9tcHQpICwgeyBwcmluY2lwYWw6IHRoaXMucHJpbmNpcGFsU2VydmljZS5wcmluY2lwYWwgfSksIGFkZGl0aW9uYWxQcm9wZXJ0aWVzOiB7IGRpc3BsYXk6IHRoaXMuY29uZmlnLm1vZGVTZXR0aW5ncy5kaXNwbGF5VXNlclByb21wdCwgbWVzc2FnZUlkOiBndWlkKCkgfSB9O1xuXG4gICAgaWYgKHRoaXMuY29uZmlnLm1vZGVTZXR0aW5ncy5pbml0aWFsaXphdGlvbi5ldmVudCA9PT0gJ1F1ZXJ5Jykge1xuICAgICAgdGhpcy5faGFuZGxlUXVlcnlNb2RlKHN5c3RlbU1zZywgdXNlck1zZyk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMuX2hhbmRsZVByb21wdE1vZGUoc3lzdGVtTXNnLCB1c2VyTXNnKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogSGFuZGxlcyB0aGUgcHJvbXB0IG1vZGUgb2YgdGhlIGNoYXQgY29tcG9uZW50LlxuICAgKiBJZiBgc2VuZFVzZXJQcm9tcHRgIGlzIHRydWUsIGl0IG9wZW5zIHRoZSBjaGF0IHdpdGggYm90aCBzeXN0ZW0gYW5kIHVzZXIgbWVzc2FnZXMsXG4gICAqIGFuZCBnZW5lcmF0ZXMgYXVkaXQgZXZlbnRzIGZvciBib3RoIG1lc3NhZ2VzLlxuICAgKiBJZiBgc2VuZFVzZXJQcm9tcHRgIGlzIGZhbHNlLCBpdCBvcGVucyB0aGUgY2hhdCB3aXRoIG9ubHkgdGhlIHN5c3RlbSBtZXNzYWdlLFxuICAgKiBhbmQgZ2VuZXJhdGVzIGFuIGF1ZGl0IGV2ZW50IGZvciB0aGUgc3lzdGVtIG1lc3NhZ2UuXG4gICAqXG4gICAqIEBwYXJhbSBzeXN0ZW1Nc2cgLSBUaGUgc3lzdGVtIG1lc3NhZ2UgdG8gYmUgZGlzcGxheWVkIGluIHRoZSBjaGF0LlxuICAgKiBAcGFyYW0gdXNlck1zZyAtIFRoZSB1c2VyIG1lc3NhZ2UgdG8gYmUgZGlzcGxheWVkIGluIHRoZSBjaGF0IChvcHRpb25hbCkuXG4gICAqL1xuICBwcml2YXRlIF9oYW5kbGVQcm9tcHRNb2RlKHN5c3RlbU1zZzogQ2hhdE1lc3NhZ2UsIHVzZXJNc2c6IENoYXRNZXNzYWdlKSB7XG4gICAgaWYgKHRoaXMuY29uZmlnLm1vZGVTZXR0aW5ncy5zZW5kVXNlclByb21wdCkge1xuICAgICAgdGhpcy5vcGVuQ2hhdChbc3lzdGVtTXNnLCB1c2VyTXNnXSk7XG4gICAgICB0aGlzLmNoYXRTZXJ2aWNlLmdlbmVyYXRlQXVkaXRFdmVudCgnYXN0LW1lc3NhZ2UubWVzc2FnZScsIHRoaXMuX2RlZmluZU1lc3NhZ2VBdWRpdERldGFpbHMoc3lzdGVtTXNnKSk7XG4gICAgICB0aGlzLmNoYXRTZXJ2aWNlLmdlbmVyYXRlQXVkaXRFdmVudCgnYXN0LW1lc3NhZ2UubWVzc2FnZScsIHRoaXMuX2RlZmluZU1lc3NhZ2VBdWRpdERldGFpbHModXNlck1zZykpO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLm9wZW5DaGF0KFtzeXN0ZW1Nc2ddKTtcbiAgICAgIHRoaXMuY2hhdFNlcnZpY2UuZ2VuZXJhdGVBdWRpdEV2ZW50KCdhc3QtbWVzc2FnZS5tZXNzYWdlJywgdGhpcy5fZGVmaW5lTWVzc2FnZUF1ZGl0RGV0YWlscyhzeXN0ZW1Nc2cpKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogSGFuZGxlcyB0aGUgcXVlcnkgbW9kZSBieSBkaXNwbGF5aW5nIHRoZSBzeXN0ZW0gbWVzc2FnZSwgdXNlciBtZXNzYWdlLCBhbmQgdXNlciBxdWVyeSBtZXNzYWdlLlxuICAgKiBJZiB0aGUgcHJvdmlkZWQgcXVlcnkgdGV4dCBpcyBub3QgZW1wdHksIHRoZW4gYWRkIHRoZSB1c2VyIHF1ZXJ5IG1lc3NhZ2UgdG8gdGhlIGNoYXQgaGlzdG9yeSBhbmQgaW52b2tlIHRoZSBhc3Npc3RhbnRcbiAgICogT3RoZXJ3aXNlLCBqdXN0IHN0YXJ0IGEgbmV3IGNoYXQgd2l0aCBhIHdhcm5pbmcgbWVzc2FnZSBpbnZpdGluZyB0aGUgdXNlciB0byBwZXJmb3JtIGEgZnVsbCB0ZXh0IHNlYXJjaCB0byByZXRyaWV2ZSBzb21lIHJlc3VsdHNcbiAgICogQHBhcmFtIHN5c3RlbU1zZyAtIFRoZSBzeXN0ZW0gbWVzc2FnZSB0byBiZSBkaXNwbGF5ZWQuXG4gICAqIEBwYXJhbSB1c2VyTXNnIC0gVGhlIHVzZXIgbWVzc2FnZSB0byBiZSBkaXNwbGF5ZWQuXG4gICAqL1xuICBwcml2YXRlIF9oYW5kbGVRdWVyeU1vZGUoc3lzdGVtTXNnOiBDaGF0TWVzc2FnZSwgdXNlck1zZzogQ2hhdE1lc3NhZ2UpIHtcbiAgICBpZiAoISF0aGlzLnF1ZXJ5LnRleHQpIHtcbiAgICAgIGNvbnN0IHVzZXJRdWVyeU1zZyA9IHsgcm9sZTogJ3VzZXInLCBjb250ZW50OiB0aGlzLnF1ZXJ5LnRleHQsIGFkZGl0aW9uYWxQcm9wZXJ0aWVzOiB7IGRpc3BsYXk6IHRoaXMuY29uZmlnLm1vZGVTZXR0aW5ncy5pbml0aWFsaXphdGlvbi5kaXNwbGF5VXNlclF1ZXJ5LCBtZXNzYWdlSWQ6IGd1aWQoKSwgcXVlcnk6IHRoaXMucXVlcnksIGZvcmNlZFdvcmtmbG93OiB0aGlzLmNvbmZpZy5tb2RlU2V0dGluZ3MuaW5pdGlhbGl6YXRpb24uZm9yY2VkV29ya2Zsb3csIGZvcmNlZEZ1bmN0aW9uOiB0aGlzLmNvbmZpZy5tb2RlU2V0dGluZ3MuaW5pdGlhbGl6YXRpb24uZm9yY2VkRnVuY3Rpb24sIGlzVXNlcklucHV0OiB0cnVlLCBhZGRpdGlvbmFsV29ya2Zsb3dQcm9wZXJ0aWVzOiB0aGlzLmNvbmZpZy5hZGRpdGlvbmFsV29ya2Zsb3dQcm9wZXJ0aWVzIH0gfTtcbiAgICAgIGlmICh0aGlzLmNvbmZpZy5tb2RlU2V0dGluZ3Muc2VuZFVzZXJQcm9tcHQpIHtcbiAgICAgICAgdGhpcy5vcGVuQ2hhdChbc3lzdGVtTXNnLCB1c2VyTXNnLCB1c2VyUXVlcnlNc2ddKTtcbiAgICAgICAgdGhpcy5jaGF0U2VydmljZS5nZW5lcmF0ZUF1ZGl0RXZlbnQoJ2FzdC1tZXNzYWdlLm1lc3NhZ2UnLCB0aGlzLl9kZWZpbmVNZXNzYWdlQXVkaXREZXRhaWxzKHN5c3RlbU1zZykpO1xuICAgICAgICB0aGlzLmNoYXRTZXJ2aWNlLmdlbmVyYXRlQXVkaXRFdmVudCgnYXN0LW1lc3NhZ2UubWVzc2FnZScsIHRoaXMuX2RlZmluZU1lc3NhZ2VBdWRpdERldGFpbHModXNlck1zZykpO1xuICAgICAgICB0aGlzLmNoYXRTZXJ2aWNlLmdlbmVyYXRlQXVkaXRFdmVudCgnYXN0LW1lc3NhZ2UubWVzc2FnZScsIHsgLi4udGhpcy5fZGVmaW5lTWVzc2FnZUF1ZGl0RGV0YWlscyh1c2VyUXVlcnlNc2cpLCAncXVlcnknOiBKU09OLnN0cmluZ2lmeSh0aGlzLnF1ZXJ5KSwgJ2lzLXVzZXItaW5wdXQnOiB0cnVlLCAnZm9yY2VkLXdvcmtmbG93JzogdGhpcy5jb25maWcubW9kZVNldHRpbmdzLmluaXRpYWxpemF0aW9uLmZvcmNlZFdvcmtmbG93LCAnZm9yY2VkLWZ1bmN0aW9uJzogdGhpcy5jb25maWcubW9kZVNldHRpbmdzLmluaXRpYWxpemF0aW9uLmZvcmNlZEZ1bmN0aW9uLCAnZW5hYmxlZC1mdW5jdGlvbnMnOiB0aGlzLmNvbmZpZy5kZWZhdWx0VmFsdWVzLmZ1bmN0aW9ucz8uZmlsdGVyKGZ1bmMgPT4gZnVuYy5lbmFibGVkKS5tYXAoZnVuYyA9PiBmdW5jLm5hbWUpLCAnYWRkaXRpb25hbC13b3JrZmxvdy1wcm9wZXJ0aWVzJzogSlNPTi5zdHJpbmdpZnkodGhpcy5jb25maWcuYWRkaXRpb25hbFdvcmtmbG93UHJvcGVydGllcykgfSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aGlzLm9wZW5DaGF0KFtzeXN0ZW1Nc2csIHVzZXJRdWVyeU1zZ10pO1xuICAgICAgICB0aGlzLmNoYXRTZXJ2aWNlLmdlbmVyYXRlQXVkaXRFdmVudCgnYXN0LW1lc3NhZ2UubWVzc2FnZScsIHRoaXMuX2RlZmluZU1lc3NhZ2VBdWRpdERldGFpbHMoc3lzdGVtTXNnKSk7XG4gICAgICAgIHRoaXMuY2hhdFNlcnZpY2UuZ2VuZXJhdGVBdWRpdEV2ZW50KCdhc3QtbWVzc2FnZS5tZXNzYWdlJywgeyAuLi50aGlzLl9kZWZpbmVNZXNzYWdlQXVkaXREZXRhaWxzKHVzZXJRdWVyeU1zZyksICdxdWVyeSc6IEpTT04uc3RyaW5naWZ5KHRoaXMucXVlcnkpLCAnaXMtdXNlci1pbnB1dCc6IHRydWUsICdmb3JjZWQtd29ya2Zsb3cnOiB0aGlzLmNvbmZpZy5tb2RlU2V0dGluZ3MuaW5pdGlhbGl6YXRpb24uZm9yY2VkV29ya2Zsb3csICdmb3JjZWQtZnVuY3Rpb24nOiB0aGlzLmNvbmZpZy5tb2RlU2V0dGluZ3MuaW5pdGlhbGl6YXRpb24uZm9yY2VkRnVuY3Rpb24sICdlbmFibGVkLWZ1bmN0aW9ucyc6IHRoaXMuY29uZmlnLmRlZmF1bHRWYWx1ZXMuZnVuY3Rpb25zPy5maWx0ZXIoZnVuYyA9PiBmdW5jLmVuYWJsZWQpLm1hcChmdW5jID0+IGZ1bmMubmFtZSksICdhZGRpdGlvbmFsLXdvcmtmbG93LXByb3BlcnRpZXMnOiBKU09OLnN0cmluZ2lmeSh0aGlzLmNvbmZpZy5hZGRpdGlvbmFsV29ya2Zsb3dQcm9wZXJ0aWVzKSB9KTtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgY29uc3Qgd2FybmluZ01zZyA9IHsgcm9sZTogJ3NlYXJjaC13YXJuaW5nJywgY29udGVudDogdGhpcy50cmFuc2xvY28udHJhbnNsYXRlKHRoaXMuY29uZmlnLmdsb2JhbFNldHRpbmdzLnNlYXJjaFdhcm5pbmdNZXNzYWdlKSwgYWRkaXRpb25hbFByb3BlcnRpZXM6IHsgZGlzcGxheTogdHJ1ZSwgbWVzc2FnZUlkOiBndWlkKCkgfSB9O1xuICAgICAgdGhpcy5vcGVuQ2hhdChbc3lzdGVtTXNnLCB3YXJuaW5nTXNnXSk7XG4gICAgICB0aGlzLmNoYXRTZXJ2aWNlLmdlbmVyYXRlQXVkaXRFdmVudCgnYXN0LW1lc3NhZ2UubWVzc2FnZScsIHRoaXMuX2RlZmluZU1lc3NhZ2VBdWRpdERldGFpbHMod2FybmluZ01zZykpO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgX2RlZmluZU1lc3NhZ2VBdWRpdERldGFpbHMobWVzc2FnZTogQ2hhdE1lc3NhZ2UpOiBSZWNvcmQ8c3RyaW5nLCBhbnk+IHtcbiAgICBjb25zdCByYW5rID0gdGhpcy5hc3Npc3RhbnRVdGlscy5nZXRNZXNzYWdlUmFua0luQ2hhdEhpc3RvcnkodGhpcy5jaGF0U2VydmljZS5jaGF0SGlzdG9yeSEsIG1lc3NhZ2UuYWRkaXRpb25hbFByb3BlcnRpZXMubWVzc2FnZUlkKTtcbiAgICBjb25zdCBkZXRhaWxzOiBSZWNvcmQ8c3RyaW5nLCBhbnk+ID0ge1xuICAgICAgJ2R1cmF0aW9uJzogMCxcbiAgICAgICdyb2xlJzogbWVzc2FnZS5yb2xlLFxuICAgICAgJ3JhbmsnOiByYW5rLFxuICAgICAgJ21lc3NhZ2UtaWQnOiBtZXNzYWdlLmFkZGl0aW9uYWxQcm9wZXJ0aWVzLm1lc3NhZ2VJZFxuICAgIH07XG4gICAgaWYgKCEhdGhpcy5jb25maWcuYXVkaXRTZXR0aW5ncz8ubG9nQ29udGVudCkge1xuICAgICAgaWYgKHR5cGVvZiBtZXNzYWdlLmNvbnRlbnQgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgIGRldGFpbHMudGV4dCA9IG1lc3NhZ2UuY29udGVudDtcbiAgICAgIH0gZWxzZSBpZiAoQXJyYXkuaXNBcnJheShtZXNzYWdlLmNvbnRlbnQpKSB7XG4gICAgICAgIGRldGFpbHMudGV4dCA9IChtZXNzYWdlLmNvbnRlbnQuZmluZCgobXNnKSA9PiBtc2cudHlwZSA9PT0gXCJ0ZXh0XCIpIGFzIFRleHRNZXNzYWdlQ29udGVudCkudGV4dFxuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gZGV0YWlscztcbiAgfVxuXG4gIC8qKlxuICAgKiBTdGFydC9vcGVuIGEgbmV3IGNoYXQgd2l0aCB0aGUgcHJvdmlkZWQgbWVzc2FnZXMgYW5kIGNoYXRJZFxuICAgKiBJZiB0aGUgbGFzdCBtZXNzYWdlIGlzIGZyb20gdGhlIHVzZXIsIGEgcmVxdWVzdCB0byB0aGUgYXNzaXN0YW50IGlzIG1hZGUgdG8gZ2V0IGFuIGFuc3dlclxuICAgKiBJZiB0aGUgbGFzdCBtZXNzYWdlIGlzIGZyb20gdGhlIGFzc2lzdGFudCwgdGhlIGNvbnZlcnNhdGlvbiBpcyBsb2FkZWQgcmlnaHQgYXdheVxuICAgKiBAcGFyYW0gbWVzc2FnZXMgVGhlIGxpc3Qgb2YgbWVzc2FnZXMgb2YgdGhlIGNoYXRcbiAgICogQHBhcmFtIGNoYXRJZCAgVGhlIGlkIG9mIHRoZSBkaXNjdXNzaW9uLiBJZiBwcm92aWRlZCAoaWUuIGFuIGV4aXN0aW5nIGRpc2N1c3Npb24gaW4gdGhlIHNhdmVkIGNoYXQgaW5kZXgpLCB1cGRhdGUgdGhlIGNoYXRJZCBpbiB0aGUgY2hhdCBzZXJ2aWNlIGZvciB0aGUgdXBjb21pbmcgc2F2ZWQgY2hhdCBvcGVyYXRpb25zXG4gICAqL1xuICBvcGVuQ2hhdChtZXNzYWdlczogUmF3TWVzc2FnZVtdLCBjaGF0SWQ/OiBzdHJpbmcpIHtcbiAgICBpZiAoIW1lc3NhZ2VzIHx8ICFBcnJheS5pc0FycmF5KG1lc3NhZ2VzKSkge1xuICAgICAgY29uc29sZS5lcnJvcignRXJyb3Igb2NjdXJzIHdoaWxlIHRyeWluZyB0byBsb2FkIHRoZSBkaXNjdXNzaW9uLiBJbnZhbGlkIG1lc3NhZ2VzIHJlY2VpdmVkIDonLCBtZXNzYWdlcyk7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGlmIChjaGF0SWQpIHtcbiAgICAgIHRoaXMuY2hhdFNlcnZpY2UuZ2VuZXJhdGVDaGF0SWQoY2hhdElkKTtcbiAgICB9XG4gICAgLy8gRW5zdXJlIGVhY2ggbWVzc2FnZSBoYXMgYSB1bmlxdWUgbWVzc2FnZUlkXG4gICAgLy8gVGhpcyBpcyBuZWNlc3Nhcnkgc3BlY2lhbGx5IGluIGNhc2UgdGhlIGFzc2lzdGFudCBpcyBzdGFydGVkIHdpdGggYSBwcmVkZWZpbmVkIGhpc3RvcnkgT3IgYW4gb2xkIHNhdmVkIGNoYXRcbiAgICBjb25zdCBtZXNzYWdlc1dpdGhJZHM6IENoYXRNZXNzYWdlW10gPSBtZXNzYWdlcy5tYXAoKG1zZykgPT4ge1xuICAgICAgbXNnLmFkZGl0aW9uYWxQcm9wZXJ0aWVzLm1lc3NhZ2VJZCA/Pz0gZ3VpZCgpO1xuICAgICAgcmV0dXJuIG1zZyBhcyBDaGF0TWVzc2FnZTtcbiAgICB9KTtcblxuICAgIHRoaXMucmVzZXRDaGF0KCk7XG4gICAgdGhpcy5tZXNzYWdlcyQubmV4dChtZXNzYWdlc1dpdGhJZHMpO1xuICAgIHRoaXMuY2hhdFNlcnZpY2UuY2hhdEhpc3RvcnkgPSBtZXNzYWdlc1dpdGhJZHM7XG4gICAgY29uc3QgbGFzdE1lc3NhZ2UgPSBtZXNzYWdlcy5hdCgtMSk7XG4gICAgaWYgKGxhc3RNZXNzYWdlICYmIGxhc3RNZXNzYWdlLnJvbGUgPT09ICd1c2VyJykge1xuICAgICAgdGhpcy5mZXRjaChtZXNzYWdlc1dpdGhJZHMpOyAvLyBJZiB0aGUgbGFzdCBtZXNzYWdlIGlmIGZyb20gYSB1c2VyLCBhbiBhbnN3ZXIgZnJvbSB0aGUgYXNzaXN0YW50IGlzIGV4cGVjdGVkXG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgdGhpcy51cGRhdGVEYXRhKG1lc3NhZ2VzV2l0aElkcyk7IC8vIElmIHRoZSBsYXN0IG1lc3NhZ2UgaWYgZnJvbSB0aGUgYXNzaXN0YW50LCB3ZSBjYW4gbG9hZCB0aGUgY29udmVyc2F0aW9uIHJpZ2h0IGF3YXlcbiAgICAgIHRoaXMudGVybWluYXRlRmV0Y2goKTtcbiAgICB9XG4gICAgdGhpcy5fYWRkU2Nyb2xsTGlzdGVuZXIoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXNldCB0aGUgY2hhdCBieSBjbGVhcmluZyB0aGUgY2hhdCBoaXN0b3J5IGFuZCB0aGUgVUkgYWNjb3JkaW5nbHlcbiAgICogVGhlIHVzZXIgaW5wdXQgd2lsbCBiZSBjbGVhcmVkXG4gICAqIFRoZSBmZXRjaCBzdWJzY3JpcHRpb24gd2lsbCBiZSB0ZXJtaW5hdGVkXG4gICAqL1xuICByZXNldENoYXQoKSB7XG4gICAgaWYgKHRoaXMubWVzc2FnZXMkLnZhbHVlKSB7XG4gICAgICB0aGlzLm1lc3NhZ2VzJC5uZXh0KHVuZGVmaW5lZCk7IC8vIFJlc2V0IGNoYXRcbiAgICB9XG4gICAgdGhpcy5jaGF0U2VydmljZS5jaGF0SGlzdG9yeSA9IHVuZGVmaW5lZDsgLy8gUmVzZXQgY2hhdCBoaXN0b3J5XG4gICAgdGhpcy5xdWVzdGlvbiA9ICcnO1xuICAgIHRoaXMudGVybWluYXRlRmV0Y2goKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBGZXRjaCBhbmQgTG9hZCB0aGUgc2F2ZWQgY2hhdCBmcm9tIHRoZSBzYXZlZCBjaGF0IGluZGV4LlxuICAgKiBJZiB0aGUgc2F2ZWQgY2hhdCBpcyBmb3VuZCwgdGhlIGNoYXQgZGlzY3Vzc2lvbiB3aWxsIGJlIGxvYWRlZCB3aXRoIHRoZSBwcm92aWRlZCBtZXNzYWdlcyBhbmQgY2hhdElkXG4gICAqL1xuICBvbkxvYWRDaGF0KCkge1xuICAgIHRoaXMubG9hZGluZyQubmV4dCh0cnVlKTtcbiAgICB0aGlzLl9zdWIuYWRkKFxuICAgICAgdGhpcy5jaGF0U2VydmljZS5sb2FkU2F2ZWRDaGF0JFxuICAgICAgICAucGlwZShcbiAgICAgICAgICBmaWx0ZXIoc2F2ZWRDaGF0ID0+ICEhc2F2ZWRDaGF0KSxcbiAgICAgICAgICBzd2l0Y2hNYXAoc2F2ZWRDaGF0ID0+IHRoaXMuY2hhdFNlcnZpY2UuZ2V0U2F2ZWRDaGF0KHNhdmVkQ2hhdCEuaWQpKSxcbiAgICAgICAgICBmaWx0ZXIoc2F2ZWRDaGF0SGlzdG9yeSA9PiAhIXNhdmVkQ2hhdEhpc3RvcnkpLFxuICAgICAgICAgIHRhcChzYXZlZENoYXRIaXN0b3J5ID0+IHRoaXMub3BlbkNoYXQoc2F2ZWRDaGF0SGlzdG9yeSEuaGlzdG9yeSwgc2F2ZWRDaGF0SGlzdG9yeSEuaWQpKVxuICAgICAgICApLnN1YnNjcmliZSgpXG4gICAgKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBTdG9wIHRoZSBnZW5lcmF0aW9uIG9mIHRoZSBjdXJyZW50IGFzc2lzdGFudCdzIGFuc3dlci5cbiAgICogVGhlIGZldGNoIHN1YnNjcmlwdGlvbiB3aWxsIGJlIHRlcm1pbmF0ZWQuXG4gICAqL1xuICBzdG9wR2VuZXJhdGlvbigpIHtcbiAgICB0aGlzLmNoYXRTZXJ2aWNlLnN0b3BHZW5lcmF0aW9uKCkuc3Vic2NyaWJlKFxuICAgICAgKCkgPT4ge1xuICAgICAgICAvLyBSZW1vdmUgdGhlIGxhc3QgbWVzc2FnZSBpZiBpdCdzIGFuIGVtcHR5IG1lc3NhZ2VcbiAgICAgICAgLy8gVGhpcyBpcyBkdWUgdG8gdGhlIG1hbm5lciBpbiB3aGljaCB0aGUgY2hhdCBzZXJ2aWNlIGhhbmRsZXMgY29uc2VjdXRpdmUgbWVzc2FnZXNcbiAgICAgICAgY29uc3QgbGFzdE1lc3NhZ2UgPSB0aGlzLm1lc3NhZ2VzJC52YWx1ZT8uYXQoLTEpO1xuICAgICAgICBpZiAodGhpcy5pc0VtcHR5QXNzaXN0YW50TWVzc2FnZShsYXN0TWVzc2FnZSkpIHtcbiAgICAgICAgICB0aGlzLm1lc3NhZ2VzJC5uZXh0KHRoaXMubWVzc2FnZXMkLnZhbHVlPy5zbGljZSgwLCAtMSkpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMudGVybWluYXRlRmV0Y2goKTtcbiAgICAgIH1cbiAgICApO1xuICB9XG5cbiAgLyoqXG4gICAqIFRlcm1pbmF0ZSB0aGUgZmV0Y2ggcHJvY2VzcyBieSB1bnN1YnNjcmliaW5nIGZyb20gdGhlIGRhdGEgc3Vic2NyaXB0aW9uIGFuZCB1cGRhdGluZyB0aGUgbG9hZGluZyBzdGF0dXMgdG8gZmFsc2UuXG4gICAqIEFkZGl0aW9uYWxseSwgZm9jdXMgb24gdGhlIGNoYXQgaW5wdXQgaWYgdGhlIGZvY3VzQWZ0ZXJSZXNwb25zZSBmbGFnIGlzIHNldCB0byB0cnVlLlxuICAgKi9cbiAgdGVybWluYXRlRmV0Y2goKSB7XG4gICAgdGhpcy5fZGF0YVN1YnNjcmlwdGlvbj8udW5zdWJzY3JpYmUoKTtcbiAgICB0aGlzLl9kYXRhU3Vic2NyaXB0aW9uID0gdW5kZWZpbmVkO1xuICAgIHRoaXMubG9hZGluZyQubmV4dChmYWxzZSk7XG4gICAgdGhpcy5jZHIuZGV0ZWN0Q2hhbmdlcygpO1xuXG4gICAgaWYgKHRoaXMuZm9jdXNBZnRlclJlc3BvbnNlKSB7XG4gICAgICBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgICAgdGhpcy5xdWVzdGlvbklucHV0Py5uYXRpdmVFbGVtZW50LmZvY3VzKCk7XG4gICAgICB9KTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQ29weSBhIHByZXZpb3VzIHVzZXIgbWVzc2FnZSBvZiB0aGUgY2hhdCBoaXN0b3J5IHRvIHRoZSBjaGF0IHVzZXIgaW5wdXQuXG4gICAqIFRodXMsIHRoZSB1c2VyIGNhbiBlZGl0IGFuZCByZXN1Ym1pdCB0aGUgbWVzc2FnZS5cbiAgICogT25jZSB0aGUgZWRpdGVkIG1lc3NhZ2UgaXMgc3VibWl0dGVkLCBhbGwgc3Vic2VxdWVudCBtZXNzYWdlcyBzdGFydGluZyBmcm9tIEBwYXJhbSBpbmRleCB3aWxsIGJlIHJlbW92ZWQgZnJvbSB0aGUgaGlzdG9yeSBhbmQgdGhlIFVJIHdpbGwgYmUgdXBkYXRlZCBhY2NvcmRpbmdseS5cbiAgICogVGhlIGFzc2lzdGFudCB3aWxsIHJlZ2VuZXJhdGUgYSBuZXcgYW5zd2VyIGJhc2VkIG9uIHRoZSB1cGRhdGVkIGNoYXQgaGlzdG9yeS5cbiAgICog4pqg77iPIElmIHRoZSBhc3Npc3RhbnQgaXMgc3RyZWFtaW5nIG9yIHN0b3BwaW5nIHRoZSBnZW5lcmF0aW9uLCB0aGUgb3BlcmF0aW9uIGlzIG5vdCBhbGxvd2VkLlxuICAgKiBAcGFyYW0gbWVzc2FnZSBUaGUgdXNlcidzIG1lc3NhZ2UgdG8gZWRpdFxuICAgKiBAcGFyYW0gaW5kZXggVGhlIGluZGV4IG9mIHRoZSB1c2VyJ3MgbWVzc2FnZSB0byBlZGl0XG4gICAqIEByZXR1cm5zIHZvaWRcbiAgICovXG4gIGVkaXRNZXNzYWdlKG1lc3NhZ2U6IENoYXRNZXNzYWdlLCBpbmRleDogbnVtYmVyKSB7XG4gICAgaWYgKCEhdGhpcy5jaGF0U2VydmljZS5zdHJlYW1pbmckLnZhbHVlIHx8ICEhdGhpcy5jaGF0U2VydmljZS5zdG9wcGluZ0dlbmVyYXRpb24kLnZhbHVlKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIHRoaXMuaW5kZXhNZXNzYWdlVG9FZGl0ID0gaW5kZXg7XG4gICAgdGhpcy5yYW5rTWVzc2FnZVRvRWRpdCA9IHRoaXMuYXNzaXN0YW50VXRpbHMuZ2V0TWVzc2FnZVJhbmtJbkNoYXRIaXN0b3J5KHRoaXMuY2hhdFNlcnZpY2UuY2hhdEhpc3RvcnkhLCBtZXNzYWdlLmFkZGl0aW9uYWxQcm9wZXJ0aWVzLm1lc3NhZ2VJZCk7XG5cbiAgICAvLyBHZXQgdXNlciBtZXNzYWdlIGZyb20gYm90aCBsZWdhY3kgYW5kIHRleHQgbWVzc2FnZSB0eXBlXG4gICAgdGhpcy5xdWVzdGlvbiA9IHR5cGVvZiBtZXNzYWdlLmNvbnRlbnQgPT09ICdzdHJpbmcnID8gbWVzc2FnZS5jb250ZW50IDogKG1lc3NhZ2UuY29udGVudFswXSBhcyBUZXh0TWVzc2FnZUNvbnRlbnQpLnRleHQ7XG5cbiAgICB0aGlzLmNoYXRTZXJ2aWNlLmdlbmVyYXRlQXVkaXRFdmVudCgnYXN0LWVkaXQuY2xpY2snLCB7J3JhbmsnOiB0aGlzLnJhbmtNZXNzYWdlVG9FZGl0LCAnbWVzc2FnZS1pZCc6IG1lc3NhZ2UuYWRkaXRpb25hbFByb3BlcnRpZXMubWVzc2FnZUlkfSk7XG4gIH1cblxuICAvKipcbiAgICogQ29weSBhIHByZXZpb3VzIGFzc2lzdGFudCBtZXNzYWdlIG9mIHRoZSBjaGF0IGhpc3RvcnkgdG8gdGhlIGNsaXBib2FyZC5cbiAgICogQHBhcmFtIG1lc3NhZ2UgVGhlIG1lc3NhZ2UgdG8gY29weVxuICAgKiBAcGFyYW0gaW5kZXggVGhlIGluZGV4IG9mIHRoZSBtZXNzYWdlIHRvIGNvcHlcbiAgICogQHJldHVybnMgdm9pZFxuICAgKi9cbiAgY29weU1lc3NhZ2UobWVzc2FnZTogQ2hhdE1lc3NhZ2UsIGluZGV4OiBudW1iZXIpIHtcbiAgICAvLyBSZW1hcCB0aGUgaW5kZXggaW4gdGhlIGNoYXQgaGlzdG9yeVxuICAgIGNvbnN0IHJhbmsgPSB0aGlzLmFzc2lzdGFudFV0aWxzLmdldE1lc3NhZ2VSYW5rSW5DaGF0SGlzdG9yeSh0aGlzLmNoYXRTZXJ2aWNlLmNoYXRIaXN0b3J5ISwgbWVzc2FnZS5hZGRpdGlvbmFsUHJvcGVydGllcy5tZXNzYWdlSWQpO1xuICAgIHRoaXMuY2hhdFNlcnZpY2UuZ2VuZXJhdGVBdWRpdEV2ZW50KCdhc3QtY29weS5jbGljaycsIHsgJ3JhbmsnOiByYW5rLCAnbWVzc2FnZS1pZCc6IG1lc3NhZ2UuYWRkaXRpb25hbFByb3BlcnRpZXMubWVzc2FnZUlkIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIFN0YXJ0aW5nIGZyb20gdGhlIHByb3ZpZGVkIGluZGV4LCByZW1vdmUgYWxsIHN1YnNlcXVlbnQgbWVzc2FnZXMgZnJvbSB0aGUgY2hhdCBoaXN0b3J5IGFuZCB0aGUgVUkgYWNjb3JkaW5nbHkuXG4gICAqIFRoZSBhc3Npc3RhbnQgd2lsbCByZWdlbmVyYXRlIGEgbmV3IGFuc3dlciBiYXNlZCBvbiB0aGUgdXBkYXRlZCBjaGF0IGhpc3RvcnkuXG4gICAqIOKaoO+4jyBJZiB0aGUgYXNzaXN0YW50IGlzIHN0cmVhbWluZyBvciBzdG9wcGluZyB0aGUgZ2VuZXJhdGlvbiwgdGhlIG9wZXJhdGlvbiBpcyBub3QgYWxsb3dlZC5cbiAgICogQHBhcmFtIG1lc3NhZ2UgVGhlIGFzc2lzdGFudCdzIG1lc3NhZ2UgdG8gcmVnZW5lcmF0ZVxuICAgKiBAcGFyYW0gaW5kZXggVGhlIGluZGV4IG9mIHRoZSBhc3Npc3RhbnQncyBtZXNzYWdlIHRvIHJlZ2VuZXJhdGVcbiAgICovXG4gIHJlZ2VuZXJhdGVNZXNzYWdlKG1lc3NhZ2U6IENoYXRNZXNzYWdlLCBpbmRleDogbnVtYmVyKSB7XG4gICAgaWYgKCEhdGhpcy5jaGF0U2VydmljZS5zdHJlYW1pbmckLnZhbHVlIHx8ICEhdGhpcy5jaGF0U2VydmljZS5zdG9wcGluZ0dlbmVyYXRpb24kLnZhbHVlKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIC8vIFVwZGF0ZSB0aGUgbWVzc2FnZXMgaW4gdGhlIFVJIGJ5IHJlbW92aW5nIGFsbCBzdWJzZXF1ZW50ICdhc3Npc3RhbnQnIG1lc3NhZ2VzIHN0YXJ0aW5nIGZyb20gdGhlIHByb3ZpZGVkIGluZGV4IHVudGlsIHRoZSBmaXJzdCBwcmV2aW91cyAndXNlcicgbWVzc2FnZVxuICAgIGxldCBpID0gaW5kZXg7XG4gICAgd2hpbGUgKGkgPj0gMCAmJiAhKCh0aGlzLm1lc3NhZ2VzJC52YWx1ZSEpW2ldLnJvbGUgPT09ICd1c2VyJyAmJiAodGhpcy5tZXNzYWdlcyQudmFsdWUhKVtpXS5hZGRpdGlvbmFsUHJvcGVydGllcy5pc1VzZXJJbnB1dCA9PT0gdHJ1ZSkpIHtcbiAgICAgIGktLTtcbiAgICB9XG4gICAgLy8gSXQgc2hvdWxkIGFsd2F5cyBiZSB0aGUgY2FzZSB0aGF0IGkgPiAwXG4gICAgaWYgKGkgPj0gMCkge1xuICAgICAgdGhpcy5tZXNzYWdlcyQubmV4dCh0aGlzLm1lc3NhZ2VzJC52YWx1ZSEuc2xpY2UoMCwgaSArIDEpKTtcbiAgICAgIC8vIFJhbmsgb2YgdGhpcyBmb3VuZCBmaXJzdCBwcmV2aW91cyAndXNlcicgbWVzc2FnZSBpbiB0aGUgY2hhdCBoaXN0b3J5XG4gICAgICBjb25zdCByYW5rID0gdGhpcy5hc3Npc3RhbnRVdGlscy5nZXRNZXNzYWdlUmFua0luQ2hhdEhpc3RvcnkodGhpcy5jaGF0U2VydmljZS5jaGF0SGlzdG9yeSEsIG1lc3NhZ2UuYWRkaXRpb25hbFByb3BlcnRpZXMubWVzc2FnZUlkKTtcbiAgICAgIC8vIERlZmluZSBhbmQgVXBkYXRlIHRoZSBjaGF0IGhpc3RvcnkgYmFzZWQgb24gd2hpY2ggdGhlIGFzc2lzdGFudCB3aWxsIGdlbmVyYXRlIGEgbmV3IGFuc3dlclxuICAgICAgdGhpcy5jaGF0U2VydmljZS5jaGF0SGlzdG9yeSA9IHRoaXMuY2hhdFNlcnZpY2UuY2hhdEhpc3RvcnkhLnNsaWNlKDAsIHJhbmspO1xuICAgICAgLy8gRmV0Y2ggdGhlIGFuc3dlclxuICAgICAgdGhpcy5mZXRjaCh0aGlzLmNoYXRTZXJ2aWNlLmNoYXRIaXN0b3J5KTtcbiAgICAgIHRoaXMuY2hhdFNlcnZpY2UuZ2VuZXJhdGVBdWRpdEV2ZW50KCdhc3QtcmVnZW5lcmF0ZS5jbGljaycsIHsgJ3JhbmsnOiByYW5rLCAnbWVzc2FnZS1pZCc6IG1lc3NhZ2UuYWRkaXRpb25hbFByb3BlcnRpZXMubWVzc2FnZUlkIH0pO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBIYW5kbGVzIHRoZSBrZXkgdXAgZXZlbnQgZm9yICdCYWNrc3BhY2UnIGFuZCAnRW50ZXInIGtleXMuXG4gICAqIEBwYXJhbSBldmVudCAtIFRoZSBrZXlib2FyZCBldmVudC5cbiAgICovXG4gIG9uS2V5VXAoZXZlbnQ6IEtleWJvYXJkRXZlbnQpOiB2b2lkIHtcbiAgICBzd2l0Y2ggKGV2ZW50LmtleSkge1xuICAgICAgY2FzZSAnQmFja3NwYWNlJzpcbiAgICAgICAgdGhpcy5jYWxjdWxhdGVIZWlnaHQoKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlICdFbnRlcic6XG4gICAgICAgIGlmICghZXZlbnQuc2hpZnRLZXkpIHtcbiAgICAgICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICAgIHRoaXMuc3VibWl0UXVlc3Rpb24oKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmNhbGN1bGF0ZUhlaWdodCgpO1xuICAgICAgICBicmVhaztcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIGJyZWFrO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBDYWxjdWxhdGVzIGFuZCBhZGp1c3RzIHRoZSBoZWlnaHQgb2YgdGhlIHF1ZXN0aW9uIGlucHV0IGVsZW1lbnQgYmFzZWQgb24gaXRzIGNvbnRlbnQuXG4gICAqIElmIHRoZSBFbnRlciBrZXkgaXMgcHJlc3NlZCB3aXRob3V0IHRoZSBTaGlmdCBrZXksIGl0IHByZXZlbnRzIHRoZSBkZWZhdWx0IGJlaGF2aW9yLlxuICAgKiBAcGFyYW0gZXZlbnQgVGhlIGtleWJvYXJkIGV2ZW50XG4gICAqL1xuICBjYWxjdWxhdGVIZWlnaHQoZXZlbnQ/OiBLZXlib2FyZEV2ZW50KTogdm9pZCB7XG4gICAgaWYgKGV2ZW50Py5rZXkgPT09ICdFbnRlcicgJiYgIWV2ZW50LnNoaWZ0S2V5KSB7XG4gICAgICBldmVudD8ucHJldmVudERlZmF1bHQoKTtcbiAgICB9XG4gICAgY29uc3QgbWF4SGVpZ2h0ID0gMTcwO1xuICAgIGNvbnN0IGVsID0gdGhpcy5xdWVzdGlvbklucHV0IS5uYXRpdmVFbGVtZW50O1xuICAgIGVsLnN0eWxlLm1heEhlaWdodCA9IGAke21heEhlaWdodH1weGA7XG4gICAgZWwuc3R5bGUuaGVpZ2h0ID0gJ2F1dG8nO1xuICAgIGVsLnN0eWxlLmhlaWdodCA9IGAke2VsLnNjcm9sbEhlaWdodH1weGA7XG4gICAgZWwuc3R5bGUub3ZlcmZsb3dZID0gZWwuc2Nyb2xsSGVpZ2h0ID49IG1heEhlaWdodCA/ICdzY3JvbGwnIDogJ2hpZGRlbic7XG4gIH1cblxuICAvKipcbiAgICogU2VuZCBhIFwibGlrZVwiIGV2ZW50IG9uIGNsaWNraW5nIG9uIHRoZSB0aHVtYi11cCBpY29uIG9mIGFuIGFzc2lzdGFudCdzIG1lc3NhZ2VcbiAgICogQHBhcmFtIG1lc3NhZ2UgVGhlIGFzc2lzdGFudCBtZXNzYWdlIHRvIGxpa2VcbiAgICogQHBhcmFtIGluZGV4IFRoZSBpbmRleCBvZiB0aGUgbWVzc2FnZSB0byBsaWtlXG4gICAqL1xuICBvbkxpa2UobWVzc2FnZTogQ2hhdE1lc3NhZ2UsIGluZGV4OiBudW1iZXIpOiB2b2lkIHtcbiAgICAvLyBSZW1hcCB0aGUgaW5kZXggaW4gdGhlIGNoYXQgaGlzdG9yeVxuICAgIGNvbnN0IHJhbmsgPSB0aGlzLmFzc2lzdGFudFV0aWxzLmdldE1lc3NhZ2VSYW5rSW5DaGF0SGlzdG9yeSh0aGlzLmNoYXRTZXJ2aWNlLmNoYXRIaXN0b3J5ISwgbWVzc2FnZS5hZGRpdGlvbmFsUHJvcGVydGllcy5tZXNzYWdlSWQpO1xuICAgIHRoaXMuY2hhdFNlcnZpY2UuZ2VuZXJhdGVBdWRpdEV2ZW50KCdhc3QtdGh1bWItdXAuY2xpY2snLCB7ICdyYW5rJzogcmFuaywgJ21lc3NhZ2UtaWQnOiBtZXNzYWdlLmFkZGl0aW9uYWxQcm9wZXJ0aWVzLm1lc3NhZ2VJZCB9KTtcbiAgICB0aGlzLnJlcG9ydFR5cGUgPSAnbGlrZSc7XG4gICAgdGhpcy5tZXNzYWdlVG9SZXBvcnQgPSBtZXNzYWdlO1xuICAgIHRoaXMucmVwb3J0Q29tbWVudCA9IHVuZGVmaW5lZDtcbiAgICB0aGlzLnJlcG9ydFJhbmsgPSByYW5rO1xuICAgIHRoaXMuc2hvd1JlcG9ydCA9IHRydWVcblxuICAgIHRoaXMuY2hhdFNlcnZpY2UuY2hhdEhpc3RvcnkhW3JhbmstMV0uYWRkaXRpb25hbFByb3BlcnRpZXMuJGxpa2VkID0gdHJ1ZTtcbiAgICB0aGlzLmNoYXRTZXJ2aWNlLmNoYXRIaXN0b3J5IVtyYW5rLTFdLmFkZGl0aW9uYWxQcm9wZXJ0aWVzLiRkaXNsaWtlZCA9IGZhbHNlO1xuICAgIHRoaXMuX3VwZGF0ZUNoYXRIaXN0b3J5KCk7XG4gIH1cblxuICAvKipcbiAgICogU2VuZCBhIFwiZGlzbGlrZVwiIGV2ZW50IG9uIGNsaWNraW5nIG9uIHRoZSB0aHVtYi1kb3duIGljb24gb2YgYW4gYXNzaXN0YW50J3MgbWVzc2FnZS5cbiAgICogSXQgYWxzbyBvcGVucyB0aGUgaXNzdWUgcmVwb3J0aW5nIGRpYWxvZy5cbiAgICogQHBhcmFtIG1lc3NhZ2UgVGhlIGFzc2lzdGFudCBtZXNzYWdlIHRvIGRpc2xpa2VcbiAgICogQHBhcmFtIGluZGV4IFRoZSByYW5rIG9mIHRoZSBtZXNzYWdlIHRvIGRpc2xpa2VcbiAgICovXG4gIG9uRGlzbGlrZShtZXNzYWdlOiBDaGF0TWVzc2FnZSwgaW5kZXg6IG51bWJlcik6IHZvaWQge1xuICAgIC8vIFJlbWFwIHRoZSBpbmRleCBpbiB0aGUgY2hhdCBoaXN0b3J5XG4gICAgY29uc3QgcmFuayA9IHRoaXMuYXNzaXN0YW50VXRpbHMuZ2V0TWVzc2FnZVJhbmtJbkNoYXRIaXN0b3J5KHRoaXMuY2hhdFNlcnZpY2UuY2hhdEhpc3RvcnkhLCBtZXNzYWdlLmFkZGl0aW9uYWxQcm9wZXJ0aWVzLm1lc3NhZ2VJZCk7XG4gICAgdGhpcy5jaGF0U2VydmljZS5nZW5lcmF0ZUF1ZGl0RXZlbnQoJ2FzdC10aHVtYi1kb3duLmNsaWNrJywgeyAncmFuayc6IHJhbmssICdtZXNzYWdlLWlkJzogbWVzc2FnZS5hZGRpdGlvbmFsUHJvcGVydGllcy5tZXNzYWdlSWQgfSk7XG4gICAgdGhpcy5yZXBvcnRUeXBlID0gJ2Rpc2xpa2UnO1xuICAgIHRoaXMubWVzc2FnZVRvUmVwb3J0ID0gbWVzc2FnZTtcbiAgICB0aGlzLmlzc3VlVHlwZSA9ICcnO1xuICAgIHRoaXMucmVwb3J0Q29tbWVudCA9IHVuZGVmaW5lZDtcbiAgICB0aGlzLnJlcG9ydFJhbmsgPSByYW5rO1xuICAgIHRoaXMuc2hvd1JlcG9ydCA9IHRydWVcblxuICAgIHRoaXMuY2hhdFNlcnZpY2UuY2hhdEhpc3RvcnkhW3JhbmstMV0uYWRkaXRpb25hbFByb3BlcnRpZXMuJGRpc2xpa2VkID0gdHJ1ZTtcbiAgICB0aGlzLmNoYXRTZXJ2aWNlLmNoYXRIaXN0b3J5IVtyYW5rLTFdLmFkZGl0aW9uYWxQcm9wZXJ0aWVzLiRsaWtlZCA9IGZhbHNlO1xuICAgIHRoaXMuX3VwZGF0ZUNoYXRIaXN0b3J5KCk7XG4gIH1cblxuICBwcml2YXRlIF91cGRhdGVDaGF0SGlzdG9yeSgpOiB2b2lkIHtcbiAgICB0aGlzLm1lc3NhZ2VzJC5uZXh0KHRoaXMuY2hhdFNlcnZpY2UuY2hhdEhpc3RvcnkpO1xuICAgIGlmICh0aGlzLmNvbmZpZy5zYXZlZENoYXRTZXR0aW5ncy5lbmFibGVkKSB7XG4gICAgICB0aGlzLmNoYXRTZXJ2aWNlLnVwZGF0ZVNhdmVkQ2hhdCh0aGlzLmNoYXRTZXJ2aWNlLmNoYXRJZCwgdW5kZWZpbmVkLCB0aGlzLmNoYXRTZXJ2aWNlLmNoYXRIaXN0b3J5KS5zdWJzY3JpYmUoKTtcbiAgICB9XG4gICAgdGhpcy5jZHIuZGV0ZWN0Q2hhbmdlcygpO1xuICB9XG5cbiAgLyoqXG4gICAqIFJlcG9ydCBhbiBpc3N1ZSByZWxhdGVkIHRvIHRoZSBhc3Npc3RhbnQncyBtZXNzYWdlLlxuICAgKi9cbiAgc2VuZFJlcG9ydCgpOiB2b2lkIHtcbiAgICBjb25zdCBkZXRhaWxzID0ge1xuICAgICAgJ2NvbW1lbnQnOiB0aGlzLnJlcG9ydENvbW1lbnQsXG4gICAgICAncmFuayc6IHRoaXMucmVwb3J0UmFua1xuICAgIH07XG5cbiAgICAvL2NoZWNrIGlmIHRoZSBtZXNzYWdlIHRvIHJlcG9ydCBpcyBkZWZpbmVkLiBJdCBzaG91bGQgYWx3YXlzIGJlIHRoZSBjYXNlXG4gICAgaWYgKHRoaXMubWVzc2FnZVRvUmVwb3J0KSB7XG4gICAgICBkZXRhaWxzWydtZXNzYWdlLWlkJ10gPSB0aGlzLm1lc3NhZ2VUb1JlcG9ydC5hZGRpdGlvbmFsUHJvcGVydGllcy5tZXNzYWdlSWQ7XG4gICAgfVxuXG4gICAgLy8gaGlkZSB0ZXh0IGluIGNhc2UgbG9nQ29udGVudCBpcyBub3QgZW5hYmxlZFxuICAgIGlmICh0aGlzLmNvbmZpZy5hdWRpdFNldHRpbmdzLmxvZ0NvbnRlbnQpXG4gICAgICBkZXRhaWxzWyd0ZXh0J10gPSB0aGlzLm1lc3NhZ2VUb1JlcG9ydCEuY29udGVudDtcblxuICAgIGlmICh0aGlzLnJlcG9ydFR5cGUgPT09ICdkaXNsaWtlJykge1xuICAgICAgZGV0YWlsc1sncmVwb3J0LXR5cGUnXSA9IHRoaXMuaXNzdWVUeXBlO1xuICAgICAgdGhpcy5jaGF0U2VydmljZS5nZW5lcmF0ZUF1ZGl0RXZlbnQoJ2FzdC1uZWdhdGl2ZS1yZXBvcnQuc2VuZCcsIGRldGFpbHMpO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLmNoYXRTZXJ2aWNlLmdlbmVyYXRlQXVkaXRFdmVudCgnYXN0LXBvc2l0aXZlLXJlcG9ydC5zZW5kJywgZGV0YWlscyk7XG4gICAgfVxuICAgIHRoaXMubm90aWZpY2F0aW9uc1NlcnZpY2Uuc3VjY2Vzcyh0aGlzLnRyYW5zbG9jby50cmFuc2xhdGUoJ2NoYXQuc2VuZFJlcG9ydE5vdGlmaWNhdGlvbicpKTtcbiAgICB0aGlzLnNob3dSZXBvcnQgPSBmYWxzZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDbG9zZSB0aGUgcmVwb3J0aW5nIGRpYWxvZy5cbiAgICovXG4gIGlnbm9yZVJlcG9ydCgpOiB2b2lkIHtcbiAgICB0aGlzLnNob3dSZXBvcnQgPSBmYWxzZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBIYW5kbGUgdGhlIGNsaWNrIG9uIGEgcmVmZXJlbmNlJ3MgJ29wZW4gcHJldmlldycuXG4gICAqIEBwYXJhbSBkYXRhXG4gICAqIEBwYXJhbSBtZXNzYWdlIHRoZSBtZXNzYWdlIGNvbnRhaW5pbmcgdGhlIHJlZmVyZW5jZVxuICAgKiBAcGFyYW0gaW5kZXggaW5kZXggb2YgdGhlIG1lc3NhZ2UgY29udGFpbmluZyB0aGUgcmVmZXJlbmNlXG4gICAqIEByZXR1cm5zIHZvaWRcbiAgICovXG4gIG9wZW5BdHRhY2htZW50UHJldmlldyhkYXRhOiB7IHJlZmVyZW5jZTogQ2hhdENvbnRleHRBdHRhY2htZW50LCBwYXJ0SWQ/OiBudW1iZXIgfSwgbWVzc2FnZTogQ2hhdE1lc3NhZ2UsIGluZGV4OiBudW1iZXIpIHtcbiAgICB0aGlzLm9wZW5QcmV2aWV3LmVtaXQoZGF0YS5yZWZlcmVuY2UpO1xuICAgIGNvbnN0IHJhbmsgPSB0aGlzLmFzc2lzdGFudFV0aWxzLmdldE1lc3NhZ2VSYW5rSW5DaGF0SGlzdG9yeSh0aGlzLmNoYXRTZXJ2aWNlLmNoYXRIaXN0b3J5ISwgbWVzc2FnZS5hZGRpdGlvbmFsUHJvcGVydGllcy5tZXNzYWdlSWQpO1xuICAgIGNvbnN0IGRldGFpbHMgPSB7XG4gICAgICAnZG9jLWlkJzogZGF0YS5yZWZlcmVuY2UucmVjb3JkSWQsXG4gICAgICAnc291cmNlJzogZGF0YS5yZWZlcmVuY2UucmVjb3JkLnRyZWVwYXRoLFxuICAgICAgJ2NvbGxlY3Rpb24nOiBkYXRhLnJlZmVyZW5jZS5yZWNvcmQuY29sbGVjdGlvbixcbiAgICAgICdpbmRleCc6IGRhdGEucmVmZXJlbmNlLnJlY29yZC5kYXRhYmFzZWFsaWFzLFxuICAgICAgJ3JhbmsnOiByYW5rLFxuICAgICAgJ21lc3NhZ2UtaWQnOiBtZXNzYWdlLmFkZGl0aW9uYWxQcm9wZXJ0aWVzLm1lc3NhZ2VJZFxuICAgIH07XG4gICAgaWYgKCEhZGF0YS5wYXJ0SWQpIGRldGFpbHNbJ3BhcnQtaWQnXSA9IGRhdGEucGFydElkO1xuICAgIHRoaXMuY2hhdFNlcnZpY2UuZ2VuZXJhdGVBdWRpdEV2ZW50KCdhc3QtYXR0YWNobWVudC5wcmV2aWV3LmNsaWNrJywgZGV0YWlscyk7XG4gIH1cblxuICAvKipcbiAgICogSGFuZGxlIHRoZSBjbGljayBvbiBhIHJlZmVyZW5jZSdzICdvcGVuIG9yaWdpbmFsIGRvY3VtZW50Jy5cbiAgICogQHBhcmFtIGRhdGFcbiAgICogQHBhcmFtIG1lc3NhZ2UgdGhlIG1lc3NhZ2UgY29udGFpbmluZyB0aGUgcmVmZXJlbmNlXG4gICAqIEBwYXJhbSBpbmRleCBpbmRleCBvZiB0aGUgbWVzc2FnZSBjb250YWluaW5nIHRoZSByZWZlcmVuY2VcbiAgICogQHJldHVybnMgdm9pZFxuICAgKi9cbiAgb3Blbk9yaWdpbmFsQXR0YWNobWVudChkYXRhOiB7IHJlZmVyZW5jZTogQ2hhdENvbnRleHRBdHRhY2htZW50LCBwYXJ0SWQ/OiBudW1iZXIgfSwgbWVzc2FnZTogQ2hhdE1lc3NhZ2UsIGluZGV4OiBudW1iZXIpIHtcbiAgICB0aGlzLm9wZW5Eb2N1bWVudC5lbWl0KGRhdGEucmVmZXJlbmNlLnJlY29yZCk7XG4gICAgY29uc3QgcmFuayA9IHRoaXMuYXNzaXN0YW50VXRpbHMuZ2V0TWVzc2FnZVJhbmtJbkNoYXRIaXN0b3J5KHRoaXMuY2hhdFNlcnZpY2UuY2hhdEhpc3RvcnkhLCBtZXNzYWdlLmFkZGl0aW9uYWxQcm9wZXJ0aWVzLm1lc3NhZ2VJZCk7XG4gICAgY29uc3QgZGV0YWlscyA9IHtcbiAgICAgICdkb2MtaWQnOiBkYXRhLnJlZmVyZW5jZS5yZWNvcmRJZCxcbiAgICAgICdzb3VyY2UnOiBkYXRhLnJlZmVyZW5jZS5yZWNvcmQudHJlZXBhdGgsXG4gICAgICAnY29sbGVjdGlvbic6IGRhdGEucmVmZXJlbmNlLnJlY29yZC5jb2xsZWN0aW9uLFxuICAgICAgJ2luZGV4JzogZGF0YS5yZWZlcmVuY2UucmVjb3JkLmRhdGFiYXNlYWxpYXMsXG4gICAgICAncmFuayc6IHJhbmssXG4gICAgICAnbWVzc2FnZS1pZCc6IG1lc3NhZ2UuYWRkaXRpb25hbFByb3BlcnRpZXMubWVzc2FnZUlkXG4gICAgfTtcbiAgICBpZiAoISFkYXRhLnBhcnRJZCkgZGV0YWlsc1sncGFydC1pZCddID0gZGF0YS5wYXJ0SWQ7XG4gICAgdGhpcy5jaGF0U2VydmljZS5nZW5lcmF0ZUF1ZGl0RXZlbnQoJ2FzdC1hdHRhY2htZW50LmxpbmsuY2xpY2snLCBkZXRhaWxzKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBIYW5kbGUgdGhlIGNsaWNrIG9uIGEgc3VnZ2VzdGVkIGFjdGlvbi5cbiAgICogQHBhcmFtIGFjdGlvbiBTdWdnZXN0ZWQgYWN0aW9uLlxuICAgKiBAcGFyYW0gaW5kZXggUmFuayBvZiB0aGUgbWVzc2FnZSBpbiB0aGUgY2hhdEhpc3RvcnkgcmVsYXRlZCB0byB0aGUgc3VnZ2VzdGVkIGFjdGlvbi5cbiAgICovXG4gIHN1Z2dlc3RBY3Rpb25DbGljayhhY3Rpb246IFN1Z2dlc3RlZEFjdGlvbiwgaW5kZXg6IG51bWJlcikge1xuICAgIHRoaXMuc3VnZ2VzdEFjdGlvbi5lbWl0KGFjdGlvbik7XG4gICAgdGhpcy5jaGF0U2VydmljZS5nZW5lcmF0ZUF1ZGl0RXZlbnQoJ2FzdC1zdWdnZXN0ZWQtYWN0aW9uLmNsaWNrJywgeyd0ZXh0JzogYWN0aW9uLmNvbnRlbnQsICdzdWdnZXN0ZWRBY3Rpb24tdHlwZSc6IGFjdGlvbi50eXBlfSlcbiAgfVxuXG4gIC8qKlxuICAgKiBJdCBsb29rcyBmb3IgdGhlIGRlYnVnIG1lc3NhZ2VzIGF2YWlsYWJsZSBpbiB0aGUgY3VycmVudCBncm91cCBvZiBcImFzc2lzdGFudFwiIG1lc3NhZ2VzLlxuICAgKiBCeSBkZXNpZ24sIHRoZSBkZWJ1ZyBtZXNzYWdlcyBhcmUgb25seSBhdmFpbGFibGUgaW4gdGhlIGZpcnN0IHZpc2libGUgbWVzc2FnZSBhbW9uZyB0aGUgZ3JvdXAgb2YgXCJhc3Npc3RhbnRcIiBtZXNzYWdlcy5cbiAgICogQHBhcmFtIG1lc3NhZ2UgVGhlIG1lc3NhZ2UgY29udGFpbmluZyB0aGUgZGVidWcgaW5mb3JtYXRpb25cbiAgICogQHBhcmFtIGluZGV4IFRoZSBpbmRleCBvZiB0aGUgbWVzc2FnZVxuICAgKiBAcmV0dXJucyBUaGUgZGVidWcgbWVzc2FnZXMgYXZhaWxhYmxlIGluIHRoZSBjdXJyZW50IGdyb3VwIG9mIFwiYXNzaXN0YW50XCIgbWVzc2FnZXNcbiAgICovXG4gIGdldERlYnVnTWVzc2FnZXMobWVzc2FnZTogQ2hhdE1lc3NhZ2UsIGluZGV4OiBudW1iZXIpOiBEZWJ1Z01lc3NhZ2VbXSB7XG4gICAgLy8gSWYgaXQgaXMgbm90IGFuIGFzc2lzdGFudCBtZXNzYWdlLCByZXR1cm4gYW4gZW1wdHkgYXJyYXlcbiAgICBpZiAobWVzc2FnZS5yb2xlICE9PSAnYXNzaXN0YW50Jykge1xuICAgICAgcmV0dXJuIFtdO1xuICAgIH1cbiAgICAvLyBHZXQgdGhlIGFycmF5IG9mIG1lc3NhZ2VzIHVwIHRvIHRoZSBpbmRpY2F0ZWQgaW5kZXhcbiAgICBjb25zdCBhcnJheSA9IHRoaXMubWVzc2FnZXMkLnZhbHVlIS5zbGljZSgwLCBpbmRleCArIDEpO1xuICAgIC8vIElmIGl0IGlzIGFuIGFzc2lzdGFudCBtZXNzYWdlLCBsb29rIGZvciB0aGUgZGVidWcgbWVzc2FnZXMgYXZhaWxhYmxlIGluIHRoZSBjdXJyZW50IGdyb3VwIG9mIFwiYXNzaXN0YW50XCIgbWVzc2FnZXNcbiAgICAvLyBCeSBkZXNpZ24sIHRoZSBkZWJ1ZyBtZXNzYWdlcyBhcmUgb25seSBhdmFpbGFibGUgaW4gdGhlIGZpcnN0IHZpc2libGUgbWVzc2FnZSBhbW9uZyB0aGUgZ3JvdXAgXCJhc3Npc3RhbnRcIiBtZXNzYWdlcy5cbiAgICBjb25zdCBpZHggPSB0aGlzLmFzc2lzdGFudFV0aWxzLmZpcnN0VmlzaWJsZUFzc2lzdGFudE1lc3NhZ2VJbmRleChhcnJheSk7XG4gICAgaWYgKGlkeCA+IC0xKSB7XG4gICAgICByZXR1cm4gKHRoaXMubWVzc2FnZXMkLnZhbHVlISlbaWR4XS5hZGRpdGlvbmFsUHJvcGVydGllcy4kZGVidWcgfHwgW107XG4gICAgfVxuICAgIHJldHVybiBbXTtcbiAgfVxuXG4gIC8qKlxuICAgKiBIYW5kbGUgdGhlIGNsaWNrIG9uIHRoZSAnc2hvdyBsb2cgaW5mbycgYnV0dG9uIG9mIGEgbWVzc2FnZS5cbiAgICogQHBhcmFtIG1lc3NhZ2UgVGhlIG1lc3NhZ2UgY29udGFpbmluZyB0aGUgZGVidWcgaW5mb3JtYXRpb25cbiAgICogQHBhcmFtIGluZGV4IFRoZSBpbmRleCBvZiB0aGUgbWVzc2FnZVxuICAgKi9cbiAgc2hvd0RlYnVnKG1lc3NhZ2U6IENoYXRNZXNzYWdlLCBpbmRleDogbnVtYmVyKTogdm9pZCB7XG4gICAgdGhpcy5kZWJ1Z01lc3NhZ2VzID0gdGhpcy5nZXREZWJ1Z01lc3NhZ2VzKG1lc3NhZ2UsIGluZGV4KTtcbiAgICB0aGlzLnNob3dEZWJ1Z01lc3NhZ2VzID0gdHJ1ZTtcbiAgICB0aGlzLmNkci5kZXRlY3RDaGFuZ2VzKCk7XG4gIH1cblxuICAvKipcbiAgICogVmVyaWZ5IHdoZXRoZXIgdGhlIGN1cnJlbnQgbWVzc2FnZSBpcyBhbiBhc3Npc3RhbnQgbWVzc2FnZSBhbmQgdGhhdCBhbGwgZm9sbG93aW5nIG1lc3NhZ2VzIGFyZSBhc3Npc3RhbnQgb25lc1xuICAgKiBVc2VkIHRvIGtlZXAgdGhlIFwiVmlldyBwcm9ncmVzc1wiIG9wZW5lZCBldmVuIHRob3VnaCB0aGUgYXNzaXN0YW50IGlzIHNlbmRpbmcgYWRkaXRpb25hbCBtZXNzYWdlcyBhZnRlciB0aGUgY3VycmVudCBvbmVcbiAgICogQHBhcmFtIG1lc3NhZ2VzIHRoZSBsaXN0IG9mIGN1cnJlbnQgbWVzc2FnZXNcbiAgICogQHBhcmFtIGluZGV4IHRoZSBpbmRleCBvZiB0aGUgY3VycmVudCBtZXNzYWdlXG4gICAqIEByZXR1cm5zIGlmIHRoaXMgbWVzc2FnZXMgYW5kIHRoZSBmb2xsb3dpbmcgb25lcyAoaWYgYW55KSBhcmUgdGhlIGxhc3Qgb25lc1xuICAgKi9cbiAgaXNBc3Npc3RhbnRMYXN0TWVzc2FnZXMobWVzc2FnZXM6IENoYXRNZXNzYWdlW10sIGluZGV4OiBudW1iZXIpOiBib29sZWFuIHtcbiAgICBmb3IgKGxldCBpID0gaW5kZXg7IGkgPCBtZXNzYWdlcy5sZW5ndGg7IGkrKykge1xuICAgICAgaWYgKG1lc3NhZ2VzW2ldLnJvbGUgIT09ICdhc3Npc3RhbnQnKSByZXR1cm4gZmFsc2U7XG4gICAgfVxuICAgIHJldHVybiB0cnVlO1xuICB9XG5cbiAgLyoqXG4gICAqIENoZWNrcyBpZiB0aGUgZ2l2ZW4gbWVzc2FnZSBpcyBhbiBlbXB0eSBhc3Npc3RhbnQgbWVzc2FnZS5cbiAgICogQW4gZW1wdHkgYXNzaXN0YW50IG1lc3NhZ2UgaXMgZGVmaW5lZCBhcyBhIG1lc3NhZ2Ugd2l0aCB0aGUgcm9sZSAnYXNzaXN0YW50JyxcbiAgICogYW4gZW1wdHkgY29udGVudCwgYW5kIG5vIGFkZGl0aW9uYWwgcHJvcGVydGllcyBzdWNoIGFzIGF0dGFjaG1lbnRzLCBwcm9ncmVzcyxcbiAgICogZGVidWcgaW5mb3JtYXRpb24sIG9yIHN1Z2dlc3RlZCBhY3Rpb25zLlxuICAgKlxuICAgKiBAcGFyYW0gbWVzc2FnZSAtIFRoZSBtZXNzYWdlIHRvIGNoZWNrLlxuICAgKiBAcmV0dXJucyBgdHJ1ZWAgaWYgdGhlIG1lc3NhZ2UgaXMgYW4gZW1wdHkgYXNzaXN0YW50IG1lc3NhZ2UsIGBmYWxzZWAgb3RoZXJ3aXNlLlxuICAgKi9cbiAgaXNFbXB0eUFzc2lzdGFudE1lc3NhZ2UobWVzc2FnZTogQ2hhdE1lc3NhZ2UgfCB1bmRlZmluZWQpOiBib29sZWFuIHtcbiAgICBpZiAoXG4gICAgICBtZXNzYWdlPy5yb2xlID09PSAnYXNzaXN0YW50J1xuICAgICAgJiYgKFxuICAgICAgICAvLyBMZWdhY3kgbWVzc2FnZSB0eXBlXG4gICAgICAgICh0eXBlb2YgbWVzc2FnZT8uY29udGVudCA9PT0gJ3N0cmluZycgJiYgbWVzc2FnZT8uY29udGVudCA9PT0gXCJcIilcbiAgICAgICAgLy8gTmV3IG1lc3NhZ2UgdHlwZVxuICAgICAgICAvLyAtIFRleHRcbiAgICAgICAgfHwgKChtZXNzYWdlPy5jb250ZW50IGFzIFJhd01lc3NhZ2VDb250ZW50KT8uWzBdIGFzIFRleHRNZXNzYWdlQ29udGVudCk/LnRleHQgPT09IFwiXCJcbiAgICAgICAgLy8gVE9ETzogaW1hZ2UgYW5kIHZpZGVvIG1lc3NhZ2UgdHlwZXMgaHR0cHM6Ly9zaW5lcXVhLmF0bGFzc2lhbi5uZXQvYnJvd3NlL0VTLTI1OTQwXG4gICAgICApXG4gICAgICAmJiAhbWVzc2FnZT8uYWRkaXRpb25hbFByb3BlcnRpZXM/LiRhdHRhY2htZW50XG4gICAgICAmJiAhbWVzc2FnZT8uYWRkaXRpb25hbFByb3BlcnRpZXM/LiRwcm9ncmVzc1xuICAgICAgJiYgIW1lc3NhZ2U/LmFkZGl0aW9uYWxQcm9wZXJ0aWVzPy4kZGVidWdcbiAgICAgICYmICFtZXNzYWdlPy5hZGRpdGlvbmFsUHJvcGVydGllcz8uJHN1Z2dlc3RlZEFjdGlvblxuICAgICkge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICAgIHJldHVybiBmYWxzZTtcbiAgfVxufVxuIiwiPG5nLWNvbnRhaW5lciAqbmdJZj1cIiFpbml0aWFsaXphdGlvbkVycm9yXCI+XG4gIDxkaXYgKm5nSWY9XCJtZXNzYWdlcyQgfCBhc3luYyBhcyBtZXNzYWdlczsgZWxzZSBsb2FkaW5nVHBsIHx8IGxvYWRpbmdUcGxEZWZhdWx0XCIgY2xhc3M9XCJoLTEwMCBkLWZsZXggZmxleC1jb2x1bW5cIj5cbiAgICA8IS0tIFRva2VuIGNvbnN1bXB0aW9uIC0tPlxuICAgIDxkaXYgY2xhc3M9XCJtcy0xXCIgKm5nSWY9XCJjb25maWc/Lmdsb2JhbFNldHRpbmdzPy5kaXNwbGF5VXNlclF1b3RhQ29uc3VtcHRpb24gfHwgY29uZmlnPy5nbG9iYWxTZXR0aW5ncz8uZGlzcGxheUNoYXRUb2tlbnNDb25zdW1wdGlvblwiPlxuICAgICAgPG5nLWNvbnRhaW5lciAqbmdUZW1wbGF0ZU91dGxldD1cInRva2VuQ29uc3VtcHRpb25UcGwgfHwgZGVmYXVsdFRva2VuQ29uc3VtcHRpb25UcGw7IGNvbnRleHQ6IHsgJGltcGxpY2l0OiBpbnN0YW5jZUlkIH1cIj48L25nLWNvbnRhaW5lcj5cbiAgICA8L2Rpdj5cblxuICAgIDwhLS0gQ2hhdCBNZXNzYWdlcyAtLT5cbiAgICA8dWwgY2xhc3M9XCJkLWZsZXggZmxleC1jb2x1bW4gbGlzdC11bnN0eWxlZCBnYXAtMyBvdmVyZmxvdy1hdXRvIGZsZXgtZ3Jvdy0xIHBlLTIgcGItMlwiICNtZXNzYWdlTGlzdD5cbiAgICAgIDxuZy1jb250YWluZXIgKm5nRm9yPVwibGV0IG1lc3NhZ2Ugb2YgbWVzc2FnZXM7IGxldCBpbmRleCA9IGluZGV4OyBsZXQgbGFzdCA9IGxhc3RcIj5cbiAgICAgICAgPCEtLSBSZWd1bGFyIG1lc3NhZ2VzIC0tPlxuICAgICAgICA8bGkgY2xhc3M9XCJsaXN0LWdyb3VwLWl0ZW1cIlxuICAgICAgICAgICpuZ0lmPVwibWVzc2FnZS5hZGRpdGlvbmFsUHJvcGVydGllcy5kaXNwbGF5ICYmICFpc0VtcHR5QXNzaXN0YW50TWVzc2FnZShtZXNzYWdlKVwiXG4gICAgICAgICAgW3N0eWxlLi0tYnMtbGlzdC1ncm91cC1pdGVtLXBhZGRpbmcteS5yZW1dPVwiJzAuNidcIlxuICAgICAgICAgIFtjbGFzcy5vcGFjaXR5LTUwXT1cImluZGV4TWVzc2FnZVRvRWRpdCAmJiAoaW5kZXhNZXNzYWdlVG9FZGl0IDwgKGluZGV4ICsgMSkpXCI+XG4gICAgICAgICAgPHNxLWNoYXQtbWVzc2FnZVxuICAgICAgICAgICAgW2NsYXNzLnNxLXVzZXItbWVzc2FnZV09XCJtZXNzYWdlLnJvbGUgPT09ICd1c2VyJ1wiXG4gICAgICAgICAgICBbY2xhc3MubGFzdC1tZXNzYWdlXT1cImxhc3RcIlxuICAgICAgICAgICAgW21lc3NhZ2VdPVwibWVzc2FnZVwiXG4gICAgICAgICAgICBbY29udmVyc2F0aW9uXT1cIm1lc3NhZ2VzXCJcbiAgICAgICAgICAgIFtzdWdnZXN0ZWRBY3Rpb25zXT1cImxhc3QgPyBtZXNzYWdlLmFkZGl0aW9uYWxQcm9wZXJ0aWVzLiRzdWdnZXN0ZWRBY3Rpb24gOiB1bmRlZmluZWRcIlxuICAgICAgICAgICAgW2Fzc2lzdGFudE1lc3NhZ2VJY29uXT1cImFzc2lzdGFudE1lc3NhZ2VJY29uXCJcbiAgICAgICAgICAgIFt1c2VyTWVzc2FnZUljb25dPVwidXNlck1lc3NhZ2VJY29uXCJcbiAgICAgICAgICAgIFtjb25uZWN0aW9uRXJyb3JNZXNzYWdlSWNvbl09XCJjb25uZWN0aW9uRXJyb3JNZXNzYWdlSWNvblwiXG4gICAgICAgICAgICBbc2VhcmNoV2FybmluZ01lc3NhZ2VJY29uXT1cInNlYXJjaFdhcm5pbmdNZXNzYWdlSWNvblwiXG4gICAgICAgICAgICBbc3RyZWFtaW5nXT1cIihjaGF0U2VydmljZS5zdHJlYW1pbmckIHwgYXN5bmMpICYmIChsYXN0IHx8IGlzQXNzaXN0YW50TGFzdE1lc3NhZ2VzKG1lc3NhZ2VzLCBpbmRleCkpXCJcbiAgICAgICAgICAgIFtjYW5FZGl0XT1cIihjaGF0U2VydmljZS5zdHJlYW1pbmckIHwgYXN5bmMpID09PSBmYWxzZSAmJiBpbmRleE1lc3NhZ2VUb0VkaXQgPT09IHVuZGVmaW5lZCAmJiBtZXNzYWdlLnJvbGUgPT09ICd1c2VyJ1wiXG4gICAgICAgICAgICBbY2FuQ29weV09XCIoKGNoYXRTZXJ2aWNlLnN0cmVhbWluZyQgfCBhc3luYykgPT09IGZhbHNlIHx8ICFsYXN0KSAmJiBpbmRleE1lc3NhZ2VUb0VkaXQgPT09IHVuZGVmaW5lZCAmJiBtZXNzYWdlLnJvbGUgIT09ICdjb25uZWN0aW9uLWVycm9yJyAmJiBtZXNzYWdlLnJvbGUgIT09ICdzZWFyY2gtd2FybmluZydcIlxuICAgICAgICAgICAgW2Nhbkxpa2VdPVwiKChjaGF0U2VydmljZS5zdHJlYW1pbmckIHwgYXN5bmMpID09PSBmYWxzZSB8fCAhbGFzdCkgJiYgbWVzc2FnZS5yb2xlID09PSAnYXNzaXN0YW50J1wiXG4gICAgICAgICAgICBbY2FuRGlzbGlrZV09XCIoKGNoYXRTZXJ2aWNlLnN0cmVhbWluZyQgfCBhc3luYykgPT09IGZhbHNlIHx8ICFsYXN0KSAmJiBtZXNzYWdlLnJvbGUgPT09ICdhc3Npc3RhbnQnXCJcbiAgICAgICAgICAgIFtjYW5EZWJ1Z109XCIoKChjaGF0U2VydmljZS5zdHJlYW1pbmckIHwgYXN5bmMpID09PSBmYWxzZSAmJiBsYXN0KSB8fCAoIWxhc3QgJiYgbWVzc2FnZXNbaW5kZXgrMV0ucm9sZSAhPT0gJ2Fzc2lzdGFudCcpKSAmJiBtZXNzYWdlLnJvbGUgPT09ICdhc3Npc3RhbnQnICYmIChnZXREZWJ1Z01lc3NhZ2VzKG1lc3NhZ2UsIGluZGV4KS5sZW5ndGggPiAwKSAmJiAoKGlzQWRtaW5PckRlbGV0ZWRBZG1pbiB8fCAoY2hhdFNlcnZpY2UudXNlck92ZXJyaWRlJCB8IGFzeW5jKSkgJiYgY29uZmlnPy5kZWZhdWx0VmFsdWVzLmRlYnVnKVwiXG4gICAgICAgICAgICBbY2FuUmVnZW5lcmF0ZV09XCIoY2hhdFNlcnZpY2Uuc3RyZWFtaW5nJCB8IGFzeW5jKSA9PT0gZmFsc2UgICYmIChsYXN0IHx8ICghbGFzdCAmJiBtZXNzYWdlc1tpbmRleCsxXS5yb2xlICE9PSAnYXNzaXN0YW50JykpICAmJiBtZXNzYWdlLnJvbGUgPT09ICdhc3Npc3RhbnQnICYmIGluZGV4TWVzc2FnZVRvRWRpdCA9PT0gdW5kZWZpbmVkXCJcbiAgICAgICAgICAgIChlZGl0KT1cImVkaXRNZXNzYWdlKG1lc3NhZ2UsIGluZGV4KVwiXG4gICAgICAgICAgICAoY29weSk9XCJjb3B5TWVzc2FnZShtZXNzYWdlLCBpbmRleClcIlxuICAgICAgICAgICAgKHJlZ2VuZXJhdGUpPVwicmVnZW5lcmF0ZU1lc3NhZ2UobWVzc2FnZSwgaW5kZXgpXCJcbiAgICAgICAgICAgIChvcGVuRG9jdW1lbnQpPVwib3Blbk9yaWdpbmFsQXR0YWNobWVudCgkZXZlbnQsIG1lc3NhZ2UsIGluZGV4KVwiXG4gICAgICAgICAgICAob3BlblByZXZpZXcpPVwib3BlbkF0dGFjaG1lbnRQcmV2aWV3KCRldmVudCwgbWVzc2FnZSwgaW5kZXgpXCJcbiAgICAgICAgICAgIChzdWdnZXN0QWN0aW9uKT1cInN1Z2dlc3RBY3Rpb25DbGljaygkZXZlbnQsIGluZGV4KVwiXG4gICAgICAgICAgICAobGlrZSk9XCJvbkxpa2UobWVzc2FnZSwgaW5kZXgpXCJcbiAgICAgICAgICAgIChkaXNsaWtlKT1cIm9uRGlzbGlrZShtZXNzYWdlLCBpbmRleClcIlxuICAgICAgICAgICAgKGRlYnVnKT1cInNob3dEZWJ1ZyhtZXNzYWdlLCBpbmRleClcIj5cbiAgICAgICAgICA8L3NxLWNoYXQtbWVzc2FnZT5cbiAgICAgICAgPC9saT5cbiAgICAgIDwvbmctY29udGFpbmVyPlxuICAgICAgPCEtLSBMb2FkaW5nIHNwaW5uZXIgLS0+XG4gICAgICA8bGkgKm5nSWY9XCIobG9hZGluZyQgfCBhc3luYykgPT09IHRydWVcIj5cbiAgICAgICAgPG5nLWNvbnRhaW5lciAqbmdUZW1wbGF0ZU91dGxldD1cImxvYWRpbmdUcGwgfHwgbG9hZGluZ1RwbERlZmF1bHRcIj48L25nLWNvbnRhaW5lcj5cbiAgICAgIDwvbGk+XG4gICAgPC91bD5cblxuICAgIDwhLS0gUmVwb3J0aW5nIGEgZmVlZGJhY2sgZm9ybSAtLT5cbiAgICA8ZGl2IGNsYXNzPVwiaXNzdWUtcmVwb3J0IHAtMyByb3VuZGVkLWxnXCIgKm5nSWY9XCJzaG93UmVwb3J0XCI+XG4gICAgICA8bmctY29udGFpbmVyICpuZ1RlbXBsYXRlT3V0bGV0PVwicmVwb3J0VHBsIHx8IHJlcG9ydFRwbERlZmF1bHQ7IGNvbnRleHQ6IHsgJGltcGxpY2l0OiBtZXNzYWdlVG9SZXBvcnQsIHJhbms6IHJlcG9ydFJhbmssIHR5cGU6IHJlcG9ydFR5cGUgfVwiPjwvbmctY29udGFpbmVyPlxuICAgIDwvZGl2PlxuXG4gICAgPCEtLSBVc2VyIHRleHQgaW5wdXQgLS0+XG4gICAgQGlmICghc2hvd1JlcG9ydCkge1xuICAgICAgPGRpdiBjbGFzcz1cInVzZXItaW5wdXQgbXQtYXV0b1wiPlxuICAgICAgICA8ZGl2IGNsYXNzPVwicHktMlwiPlxuICAgICAgICAgIDxkaXYgW2hpZGRlbl09XCIhaXNDb25uZWN0ZWRcIj5cbiAgICAgICAgICAgIDxuZy1jb250YWluZXIgKm5nSWY9XCJlbmFibGVkVXNlcklucHV0XCIgW25nVGVtcGxhdGVPdXRsZXRdPVwiaW5wdXRUcGxcIj48L25nLWNvbnRhaW5lcj5cbiAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICA8IS0tIFJldHJ5IGJ1dHRvbiAtLT5cbiAgICAgICAgICA8IS0tIGhpZGRlbiBhdHRyaWJ1dGUgaXMgaW4gY29uZmxpY3Qgd2l0aCBhIGNzcyBydWxlIGRpc3BsYXk6IGZsZXggLS0+XG4gICAgICAgICAgQGlmKCFpc0Nvbm5lY3RlZCl7XG4gICAgICAgICAgICA8YnV0dG9uIGNsYXNzPVwiYnRuIG1iLTQgYXN0LWVycm9yIGFzdC1idG4gc3EtcmV0cnlcIiAoY2xpY2spPVwicmV0cnlGZXRjaCgpXCI+XG4gICAgICAgICAgICAgIDxzcGFuPnt7ICdjaGF0LnRyeUFnYWluJyB8IHRyYW5zbG9jbyB9fTwvc3Bhbj5cbiAgICAgICAgICAgICAgPHNwYW4gKm5nSWY9XCJyZXRyaWFsQXR0ZW1wdHNcIiBjbGFzcz1cIm1zLTIgYXR0ZW1wdHNcIj57eyByZXRyaWFsQXR0ZW1wdHMgfX08L3NwYW4+XG4gICAgICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgICB9XG4gICAgICAgICAgPGRpdiBjbGFzcz1cInRleHQtZW5kIHNtYWxsIHRleHQtbXV0ZWQgcHgtM1wiICpuZ0lmPVwiISFjb25maWc/Lmdsb2JhbFNldHRpbmdzPy5kaXNjbGFpbWVyXCI+XG4gICAgICAgICAgICB7eyBjb25maWc/Lmdsb2JhbFNldHRpbmdzPy5kaXNjbGFpbWVyIHwgdHJhbnNsb2NvIH19XG4gICAgICAgICAgPC9kaXY+XG4gICAgICAgIDwvZGl2PlxuICAgICAgPC9kaXY+XG4gICAgfVxuXG4gICAgPCEtLSBGbG9hdGluZyBzY3JvbGwgYnV0dG9uIC0tPlxuICAgIDxkaXYgKm5nSWY9XCIhaXNBdEJvdHRvbSAmJiAhc2hvd1JlcG9ydFwiIGNsYXNzPVwic3EtZmxvYXRpbmctc2Nyb2xsXCIgW25nQ2xhc3NdPVwiZW5hYmxlZFVzZXJJbnB1dCA/ICdzcS1mbG9hdGluZy1zY3JvbGwtLXdoZW4tdXNlci1pbnB1dCcgOiAnc3EtZmxvYXRpbmctc2Nyb2xsLS13aXRob3V0LXVzZXItaW5wdXQnXCI+XG4gICAgICA8YnV0dG9uIGNsYXNzPVwiYnRuIHNoYWRvd1wiIChjbGljayk9XCJzY3JvbGxEb3duKClcIiBhcmlhLWxhYmVsPVwiU2Nyb2xsIGRvd25cIj5cbiAgICAgICAgPGkgY2xhc3M9XCJmYXMgZmEtYW5nbGUtZG91YmxlLWRvd25cIj48L2k+XG4gICAgICA8L2J1dHRvbj5cbiAgICA8L2Rpdj5cbiAgPC9kaXY+XG48L25nLWNvbnRhaW5lcj5cblxuPCEtLSBORyBURU1QTEFURVMtLT5cblxuPG5nLXRlbXBsYXRlICNsb2FkaW5nVHBsRGVmYXVsdD5cbiAgPGRpdiBjbGFzcz1cInNwaW5uZXItZ3JvdyB0ZXh0LXByaW1hcnkgZC1ibG9jayBteC1hdXRvIG15LTVcIiByb2xlPVwic3RhdHVzXCI+XG4gICAgPHNwYW4gY2xhc3M9XCJ2aXN1YWxseS1oaWRkZW5cIj57eyAnY2hhdC5sb2FkaW5nJyB8IHRyYW5zbG9jbyB9fTwvc3Bhbj5cbiAgPC9kaXY+XG48L25nLXRlbXBsYXRlPlxuXG48bmctdGVtcGxhdGUgI2lucHV0VHBsPlxuICA8ZGl2IGNsYXNzPVwicHgtMyBweS0xXCI+XG4gICAgPGRpdiBjbGFzcz1cImFzdC1pbnB1dC1jb250YWluZXJcIj5cbiAgICAgIDxidXR0b24gZGlzYWJsZWQgY2xhc3M9XCJidG4gYnRuLWxpZ2h0XCIgYXJpYS1sYWJlbD1cInNlYXJjaFwiPlxuICAgICAgICA8aSBjbGFzcz1cImZhcyBmYS1zZWFyY2hcIj48L2k+XG4gICAgICA8L2J1dHRvbj5cbiAgICAgIDx0ZXh0YXJlYSAjcXVlc3Rpb25JbnB1dCByb3dzPVwiMVwiXG4gICAgICAgIHR5cGU9XCJ0ZXh0XCIgY2xhc3M9XCJmb3JtLWNvbnRyb2xcIlxuICAgICAgICBbcGxhY2Vob2xkZXJdPVwiJ2NoYXQuYXNrU29tZXRoaW5nJyB8IHRyYW5zbG9jb1wiIGF1dG9mb2N1c1xuICAgICAgICBbKG5nTW9kZWwpXT1cInF1ZXN0aW9uXCJcbiAgICAgICAgKGtleXVwKT1cIm9uS2V5VXAoJGV2ZW50KVwiXG4gICAgICAgIChrZXlkb3duKT1cImNhbGN1bGF0ZUhlaWdodCgkZXZlbnQpXCJcbiAgICAgICAgW2Rpc2FibGVkXT1cIihsb2FkaW5nJCB8IGFzeW5jKSB8fCAoY2hhdFNlcnZpY2Uuc3RyZWFtaW5nJCB8IGFzeW5jKSB8fCAoY2hhdFNlcnZpY2Uuc3RvcHBpbmdHZW5lcmF0aW9uJCB8IGFzeW5jKVwiPlxuICAgICAgPC90ZXh0YXJlYT5cbiAgICAgIDxkaXYgaWQ9XCJjaGF0LWFjdGlvbnNcIiBjbGFzcz1cImQtZmxleCBnYXAtMlwiPlxuICAgICAgICA8YnV0dG9uXG4gICAgICAgICAgKm5nSWY9XCIoY2hhdFNlcnZpY2Uuc3RyZWFtaW5nJCB8IGFzeW5jKSA9PT0gZmFsc2UgJiYgKGxvYWRpbmckIHwgYXN5bmMpID09PSBmYWxzZSAmJiAoY2hhdFNlcnZpY2Uuc3RvcHBpbmdHZW5lcmF0aW9uJCB8IGFzeW5jKSA9PT0gZmFsc2VcIlxuICAgICAgICAgIHR5cGU9XCJidXR0b25cIlxuICAgICAgICAgIGNsYXNzPVwiYnRuIGJ0bi1saWdodFwiXG4gICAgICAgICAgYXJpYS1sYWJlbD1cIlNlbmQgbWVzc2FnZVwiXG4gICAgICAgICAgW3NxVG9vbHRpcF09XCInY2hhdC5zZW5kTWVzc2FnZScgfCB0cmFuc2xvY29cIlxuICAgICAgICAgIChjbGljayk9XCJzdWJtaXRRdWVzdGlvbigpXCI+XG4gICAgICAgICAgPGkgY2xhc3M9XCJmYXMgZmEtcGFwZXItcGxhbmVcIj48L2k+XG4gICAgICAgIDwvYnV0dG9uPlxuICAgICAgICA8YnV0dG9uXG4gICAgICAgICAgKm5nSWY9XCJpbmRleE1lc3NhZ2VUb0VkaXRcIlxuICAgICAgICAgIGFyaWEtbGFiZWw9XCJDYW5jZWwgZWRpdGlvblwiXG4gICAgICAgICAgdHlwZT1cImJ1dHRvblwiXG4gICAgICAgICAgY2xhc3M9XCJidG4gYnRuLWxpZ2h0XCJcbiAgICAgICAgICBbc3FUb29sdGlwXT1cIidjaGF0LmNhbmNlbEVkaXRpb24nIHwgdHJhbnNsb2NvXCJcbiAgICAgICAgICAoY2xpY2spPVwiaW5kZXhNZXNzYWdlVG9FZGl0ID0gdW5kZWZpbmVkOyBxdWVzdGlvbiA9ICcnXCI+XG4gICAgICAgICAgPGkgY2xhc3M9XCJmYXMgZmEtdW5kby1hbHRcIj48L2k+XG4gICAgICAgIDwvYnV0dG9uPlxuICAgICAgICA8c3BhbiAqbmdJZj1cIihjaGF0U2VydmljZS5zdHJlYW1pbmckIHwgYXN5bmMpICYmIChjaGF0U2VydmljZS5zdG9wcGluZ0dlbmVyYXRpb24kIHwgYXN5bmMpID09PSBmYWxzZVwiIGNsYXNzPVwicHJvY2Vzc2luZ1wiPlxuICAgICAgICAgIHt7ICdjaGF0LmdlbmVyYXRpbmcnIHwgdHJhbnNsb2NvIH19PGkgY2xhc3M9XCJmYXMgZmEtc3Bpbm5lciBmYS1wdWxzZVwiPjwvaT5cbiAgICAgICAgPC9zcGFuPlxuICAgICAgICA8c3BhbiAqbmdJZj1cIihjaGF0U2VydmljZS5zdG9wcGluZ0dlbmVyYXRpb24kIHwgYXN5bmMpXCIgY2xhc3M9XCJwcm9jZXNzaW5nXCI+XG4gICAgICAgICAge3sgJ2NoYXQuc3RvcHBpbmcnIHwgdHJhbnNsb2NvIH19PGkgY2xhc3M9XCJmYXMgZmEtc3Bpbm5lciBmYS1wdWxzZVwiPjwvaT5cbiAgICAgICAgPC9zcGFuPlxuICAgICAgICA8YnV0dG9uXG4gICAgICAgICAgKm5nSWY9XCIoY2hhdFNlcnZpY2Uuc3RyZWFtaW5nJCB8IGFzeW5jKSAmJiAoY2hhdFNlcnZpY2Uuc3RvcHBpbmdHZW5lcmF0aW9uJCB8IGFzeW5jKSA9PT0gZmFsc2VcIlxuICAgICAgICAgIHR5cGU9XCJidXR0b25cIlxuICAgICAgICAgIGNsYXNzPVwiYnRuIGJ0bi1saWdodFwiXG4gICAgICAgICAgYXJpYS1sYWJlbD1cIlN0b3AgZ2VuZXJhdGluZ1wiXG4gICAgICAgICAgW3NxVG9vbHRpcF09XCInY2hhdC5zdG9wR2VuZXJhdGlvbicgfCB0cmFuc2xvY29cIlxuICAgICAgICAgIChjbGljayk9XCJzdG9wR2VuZXJhdGlvbigpXCI+XG4gICAgICAgICAgPGkgY2xhc3M9XCJmYXMgZmEtc3RvcFwiPjwvaT5cbiAgICAgICAgPC9idXR0b24+XG4gICAgICA8L2Rpdj5cbiAgICA8L2Rpdj5cbiAgPC9kaXY+XG48L25nLXRlbXBsYXRlPlxuXG48bmctdGVtcGxhdGUgI3JlcG9ydFRwbERlZmF1bHQgbGV0LW1lc3NhZ2UgbGV0LXJhbms9XCJyYW5rXCIgbGV0LXR5cGU9XCJ0eXBlXCI+XG4gIDxkaXYgY2xhc3M9XCJweC0zXCI+XG4gICAgPG5nLWNvbnRhaW5lciAqbmdJZj1cInR5cGUgPT09ICdkaXNsaWtlJ1wiPlxuICAgICAgPGg1Pnt7ICdjaGF0Lmlzc3VlVHlwZScgfCB0cmFuc2xvY28gfX08L2g1PlxuICAgICAgPHNlbGVjdCBjbGFzcz1cImZvcm0tc2VsZWN0IG1iLTRcIiBbKG5nTW9kZWwpXT1cImlzc3VlVHlwZVwiPlxuICAgICAgICA8b3B0aW9uIFt2YWx1ZV09XCInJ1wiPnt7ICdjaGF0LmNob29zZUlzc3VlVHlwZScgfCB0cmFuc2xvY28gfX08L29wdGlvbj5cbiAgICAgICAgPG9wdGlvbiAqbmdGb3I9XCJsZXQgdHlwZSBvZiAoaXNzdWVUeXBlcyA/PyBkZWZhdWx0SXNzdWVUeXBlcylcIiBbdmFsdWVdPVwidHlwZVwiPnt7IHR5cGUgfCB0cmFuc2xvY28gfX08L29wdGlvbj5cbiAgICAgIDwvc2VsZWN0PlxuICAgICAgPGg1Pnt7ICdjaGF0LmFza1VubGlrZVJlYXNvbnMnIHwgdHJhbnNsb2NvIH19PC9oNT5cbiAgICA8L25nLWNvbnRhaW5lcj5cbiAgICA8bmctY29udGFpbmVyICpuZ0lmPVwidHlwZSA9PT0gJ2xpa2UnXCI+XG4gICAgICA8aDU+e3sgJ2NoYXQuYXNrTGlrZVJlYXNvbnMnIHwgdHJhbnNsb2NvIH19PC9oNT5cbiAgICA8L25nLWNvbnRhaW5lcj5cbiAgICA8dGV4dGFyZWEgY2xhc3M9XCJmb3JtLWNvbnRyb2wgYm9yZGVyIGJvcmRlci1uZXV0cmFsLTIwMFwiIFsobmdNb2RlbCldPVwicmVwb3J0Q29tbWVudFwiIFtwbGFjZWhvbGRlcl09XCInY2hhdC53cml0ZUNvbW1lbnQnIHwgdHJhbnNsb2NvXCI+PC90ZXh0YXJlYT5cbiAgICA8ZGl2IGNsYXNzPVwiZC1mbGV4IGZsZXgtcm93LXJldmVyc2UgZ2FwLTEgbXQtMlwiPlxuICAgICAgPGJ1dHRvbiBjbGFzcz1cImJ0biBidG4tcHJpbWFyeVwiIFtkaXNhYmxlZF09XCJ0eXBlID09PSAnZGlzbGlrZScgJiYgIWlzc3VlVHlwZVwiIChjbGljayk9XCJzZW5kUmVwb3J0KClcIj57eyAnY2hhdC5zZW5kJyB8IHRyYW5zbG9jbyB9fTwvYnV0dG9uPlxuICAgICAgPGJ1dHRvbiBjbGFzcz1cImJ0biBidG4tbGlnaHRcIiAoY2xpY2spPVwiaWdub3JlUmVwb3J0KClcIj57eyAnY2hhdC5kb05vdFNlbmQnIHwgdHJhbnNsb2NvIH19PC9idXR0b24+XG4gICAgPC9kaXY+XG4gIDwvZGl2PlxuPC9uZy10ZW1wbGF0ZT5cblxuPG5nLXRlbXBsYXRlICNkZWZhdWx0VG9rZW5Db25zdW1wdGlvblRwbCBsZXQtaW5zdGFuY2VJZD5cbiAgPHNxLXRva2VuLXByb2dyZXNzLWJhclxuICAgIFtpbnN0YW5jZUlkXT1cImluc3RhbmNlSWRcIj5cbiAgPC9zcS10b2tlbi1wcm9ncmVzcy1iYXI+XG48L25nLXRlbXBsYXRlPlxuXG48ZGl2IGNsYXNzPVwiZGVidWctbWVzc2FnZXNcIiBbY2xhc3MuZGlzcGxheWVkXT1cInNob3dEZWJ1Z01lc3NhZ2VzXCI+XG4gIDxidXR0b24gKm5nSWY9XCJzaG93RGVidWdNZXNzYWdlc1wiIGNsYXNzPVwiYnRuIGJ0bi1saWdodCBzaGFkb3cgYmFjay1idG5cIiAoY2xpY2spPVwic2hvd0RlYnVnTWVzc2FnZXM9ZmFsc2VcIiBhcmlhLWxhYmVsPVwiSGlkZSBkZWJ1ZyBtZXNzYWdlc1wiPlxuICAgIDxpIGNsYXNzPVwiZmFzIGZhLWNoZXZyb24tcmlnaHRcIj48L2k+XG4gIDwvYnV0dG9uPlxuICA8bmctY29udGFpbmVyICpuZ1RlbXBsYXRlT3V0bGV0PVwiZGVidWdNZXNzYWdlc1RwbCB8fCBkZWZhdWx0RGVidWdNZXNzYWdlc1RwbDsgY29udGV4dDogeyAkaW1wbGljaXQ6IGRlYnVnTWVzc2FnZXMgfVwiPlxuICA8L25nLWNvbnRhaW5lcj5cbjwvZGl2PlxuXG48bmctdGVtcGxhdGUgI2RlZmF1bHREZWJ1Z01lc3NhZ2VzVHBsIGxldC1kZWJ1Z01lc3NhZ2VzPlxuICA8c3EtZGVidWctbWVzc2FnZSBbZGF0YV09XCJkZWJ1Z01lc3NhZ2VzXCI+PC9zcS1kZWJ1Zy1tZXNzYWdlPlxuPC9uZy10ZW1wbGF0ZT5cbiJdfQ==