cfc-ds
Version:
Design System do Conselho Federal de Contabilidade baseado no govbr-ds
141 lines • 36.7 kB
JavaScript
import { Component, Input, HostListener, ViewChild } from '@angular/core';
import * as i0 from "@angular/core";
import * as i1 from "@angular/common";
import * as i2 from "../tab/tab.component";
import * as i3 from "../tabItem/tab-item.component";
import * as i4 from "../tabContent/tab-content.component";
export class NotificationComponent {
elementRef;
userName = '';
userEmail = '';
notifications = [];
tabs = [];
showUserArea = true;
showCloseButton = true;
isOpen = false;
maxHeight = '60vh';
showTabs = true;
cfcTabRef;
// Para categorizar as notificações por tab
notificationsByTab = [];
constructor(elementRef) {
this.elementRef = elementRef;
}
ngOnInit() {
// Organiza as notificações por categoria (tab)
this.organizeNotificationsByTab();
// Atualiza os contadores de cada tab
this.updateTabCounters();
// Define o primeiro tab como ativo, caso exista
if (this.tabs && this.tabs.length > 0) {
this.tabs[0].active = true;
}
this.notifications.forEach(notification => {
if (notification.isRead === undefined) {
notification.isRead = false;
}
});
}
ngAfterViewInit() {
setTimeout(() => {
this.selectFirstTab();
});
}
selectFirstTab() {
const tabElement = this.elementRef.nativeElement.querySelector('cfc-tab');
if (tabElement) {
const firstTabItem = tabElement.querySelector('cfc-tab-item');
if (firstTabItem) {
// Simula um clique no primeiro tab-item
firstTabItem.click();
}
}
}
organizeNotificationsByTab() {
if (!this.notifications) {
this.notificationsByTab = [];
return;
}
if (this.tabs && this.tabs.length) {
this.notificationsByTab = this.tabs.map(tab => {
// Se não houver categoria definida, coloca todas no primeiro tab
if (!this.notifications.some(n => n.category)) {
return tab.label.toLowerCase() === this.tabs[0].label.toLowerCase()
? [...this.notifications]
: [];
}
return this.notifications.filter(notification => notification.category?.toLowerCase() === tab.label.toLowerCase());
});
}
else {
// Se não houver tabs, coloca todas as notificações no primeiro grupo
this.notificationsByTab = [this.notifications];
}
}
/**
* Atualiza os contadores de cada tab
*/
updateTabCounters() {
if (this.tabs && this.tabs.length && this.notificationsByTab.length) {
this.tabs.forEach((tab, index) => {
if (index < this.notificationsByTab.length) {
// Conta apenas notificações não lidas
tab.counter = this.notificationsByTab[index].filter(n => n.isNew).length;
}
});
}
}
/**
* Fecha o notification quando o usuário clica fora dele
*/
clickOutside(event) {
if (!this.elementRef.nativeElement.contains(event.target) && this.isOpen) {
this.close();
}
}
/**
* Fecha o notification
*/
close() {
this.isOpen = false;
}
/**
* Marca uma notificação como lida
*/
markAsRead(notification) {
notification.isNew = false;
notification.isRead = true;
this.updateTabCounters();
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: NotificationComponent, deps: [{ token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component });
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: NotificationComponent, selector: "cfc-notification", inputs: { userName: "userName", userEmail: "userEmail", notifications: "notifications", tabs: "tabs", showUserArea: "showUserArea", showCloseButton: "showCloseButton", isOpen: "isOpen", maxHeight: "maxHeight", showTabs: "showTabs" }, host: { listeners: { "document:click": "clickOutside($event)" } }, viewQueries: [{ propertyName: "cfcTabRef", first: true, predicate: ["cfcTabRef"], descendants: true }], ngImport: i0, template: "<!-- notification.component.html -->\r\n<div class=\"cfc-notification-container\" [class.is-open]=\"isOpen\">\r\n <div class=\"cfc-notification-surface\">\r\n <!-- \u00C1rea do usu\u00E1rio (1) - Opcional -->\r\n <div class=\"cfc-notification-user-area\" *ngIf=\"showUserArea\">\r\n <div class=\"user-info\">\r\n <h3 class=\"user-name\">{{ userName }}</h3>\r\n <p class=\"user-email\">{{ userEmail }}</p>\r\n </div>\r\n\r\n <!-- Bot\u00E3o Fechar (2) - Opcional -->\r\n <button *ngIf=\"showCloseButton\"\r\n class=\"cfc-notification-close-button\"\r\n (click)=\"close()\"\r\n aria-label=\"Fechar notifica\u00E7\u00F5es\">\r\n <span class=\"close-icon\">\u2715</span>\r\n </button>\r\n </div>\r\n\r\n <!-- Componente Divider (5) -->\r\n <div class=\"cfc-divider\" *ngIf=\"showUserArea\"></div>\r\n\r\n <!-- Usando o componente cfc-tab -->\r\n <cfc-tab #cfcTabRef *ngIf=\"showTabs && tabs && tabs.length\" density=\"default\" tabAlignment=\"center\" >\r\n <!-- Cria os tab-items din\u00E2micos baseados nos tabs fornecidos -->\r\n <cfc-tab-item *ngFor=\"let tab of tabs\"\r\n [label]=\"tab.label\"\r\n [icon]=\"tab.icon\">\r\n </cfc-tab-item>\r\n\r\n <!-- Cria os tab-contents correspondentes -->\r\n <cfc-tab-content *ngFor=\"let tabNotifications of notificationsByTab; let i = index\">\r\n <div class=\"cfc-notification-items\" [style.max-height]=\"maxHeight\">\r\n <!-- Lista de notifica\u00E7\u00F5es -->\r\n <div *ngFor=\"let notification of tabNotifications\"\r\n class=\"cfc-notification-item\"\r\n [class.is-new]=\"notification.isNew\"\r\n [class.is-read]=\"notification.isRead\"\r\n (click)=\"markAsRead(notification)\">\r\n\r\n <!-- Tag de Status (opcional) -->\r\n <div *ngIf=\"notification.isNew\" class=\"notification-tag\">\r\n <span class=\"tag-indicator\" [style.background-color]=\"notification.tagColor || '#FFD100'\"></span>\r\n <span class=\"tag-label\">Novo</span>\r\n </div>\r\n\r\n <!-- T\u00EDtulo da Notifica\u00E7\u00E3o -->\r\n <h4 class=\"notification-title\">{{ notification.title }}</h4>\r\n\r\n <!-- Conte\u00FAdo -->\r\n <p class=\"notification-content\">{{ notification.content }}</p>\r\n\r\n <!-- Componente Divider (5) -->\r\n <div class=\"cfc-divider\"></div>\r\n </div>\r\n\r\n <!-- Mensagem para nenhuma notifica\u00E7\u00E3o -->\r\n <div *ngIf=\"!tabNotifications || tabNotifications.length === 0\" class=\"no-notifications\">\r\n <p>Nenhuma notifica\u00E7\u00E3o dispon\u00EDvel.</p>\r\n </div>\r\n </div>\r\n </cfc-tab-content>\r\n </cfc-tab>\r\n\r\n <!-- Quando n\u00E3o h\u00E1 tabs, exibe todas as notifica\u00E7\u00F5es -->\r\n <div *ngIf=\"!showTabs || !tabs || !tabs.length\" class=\"cfc-notification-items-container\">\r\n <div class=\"cfc-notification-items\" [style.max-height]=\"maxHeight\">\r\n <!-- Lista de notifica\u00E7\u00F5es -->\r\n <div *ngFor=\"let notification of notifications\"\r\n class=\"cfc-notification-item\"\r\n [class.is-new]=\"notification.isNew\"\r\n [class.is-read]=\"notification.isRead\"\r\n (click)=\"markAsRead(notification)\">\r\n\r\n <!-- Tag de Status (opcional) -->\r\n <div *ngIf=\"notification.isNew\" class=\"notification-tag\">\r\n <span class=\"tag-indicator\" [style.background-color]=\"notification.tagColor || '#FFD100'\"></span>\r\n <span class=\"tag-label\">Novo</span>\r\n </div>\r\n\r\n <!-- T\u00EDtulo da Notifica\u00E7\u00E3o -->\r\n <h4 class=\"notification-title\">{{ notification.title }}</h4>\r\n\r\n <!-- Informa\u00E7\u00E3o Cronol\u00F3gica -->\r\n <p class=\"notification-time\">{{ notification.time }}</p>\r\n\r\n <!-- Conte\u00FAdo -->\r\n <p class=\"notification-content\">{{ notification.content }}</p>\r\n\r\n <!-- Componente Divider (5) -->\r\n <div class=\"cfc-divider\"></div>\r\n </div>\r\n\r\n <!-- Mensagem para nenhuma notifica\u00E7\u00E3o -->\r\n <div *ngIf=\"!notifications || notifications.length === 0\" class=\"no-notifications\">\r\n <p>Nenhuma notifica\u00E7\u00E3o dispon\u00EDvel.</p>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n</div>\r\n", styles: [".cfc-notification-container{position:relative;display:none}.cfc-notification-container.is-open{display:block}.cfc-notification-surface{position:absolute;top:0;right:0;background-color:#fff;border-radius:4px;box-shadow:0 2px 8px #00000026;width:400px;z-index:1000;overflow:hidden}@media (max-width: 767px){.cfc-notification-surface{width:100%;position:fixed;top:0;left:0;right:0;height:100vh;border-radius:0}}.cfc-notification-user-area{display:flex;justify-content:space-between;align-items:center;padding:16px}.cfc-notification-user-area .user-info .user-name{margin:0;font-size:18px;font-weight:500;color:#333}.cfc-notification-user-area .user-info .user-email{margin:4px 0 0;font-size:14px;color:#666}.cfc-notification-close-button{background:none;border:none;cursor:pointer;width:32px;height:32px;display:flex;align-items:center;justify-content:center;color:#333}.cfc-notification-close-button:hover{background-color:#0000000d;border-radius:50%}.cfc-notification-close-button .close-icon{font-size:16px}.cfc-divider{height:1px;background-color:#e0e0e0;width:100%}.cfc-notification-items{overflow-y:auto;position:relative;max-height:60vh}.cfc-notification-items::-webkit-scrollbar{width:6px}.cfc-notification-items::-webkit-scrollbar-track{background:#f1f1f1}.cfc-notification-items::-webkit-scrollbar-thumb{background:#888;border-radius:3px}.cfc-notification-items::-webkit-scrollbar-thumb:hover{background:#555}.cfc-notification-item{padding:16px;cursor:pointer;transition:background-color .2s ease}.cfc-notification-item:hover{background-color:#00000008}.cfc-notification-item.is-new{background-color:#0e47cb0d}.cfc-notification-item .notification-tag{display:flex;align-items:center;margin-bottom:8px}.cfc-notification-item .notification-tag .tag-indicator{width:10px;height:10px;border-radius:50%;margin-right:6px}.cfc-notification-item .notification-tag .tag-label{font-size:12px;font-weight:500;color:#666}.cfc-notification-item .notification-title{margin:0 0 4px;font-size:16px;font-weight:500;color:#333}.cfc-notification-item .notification-time{margin:0 0 8px;font-size:12px;color:#888}.cfc-notification-item .notification-content{margin:0;font-size:14px;color:#555;line-height:1.5}.cfc-notification-item .cfc-divider{margin-top:16px}.no-notifications{padding:24px 16px;text-align:center;color:#666}@media (max-width: 991px) and (min-width: 768px){.cfc-notification-surface{width:50%;max-width:400px}}@media (max-width: 767px){.cfc-notification-close-button{display:flex!important}}\n"], dependencies: [{ kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i2.TabComponent, selector: "cfc-tab", inputs: ["density", "tabAlignment"] }, { kind: "component", type: i3.TabItemComponent, selector: "cfc-tab-item", inputs: ["label", "icon", "counter", "id", "active", "disabled"] }, { kind: "component", type: i4.TabContentComponent, selector: "cfc-tab-content", inputs: ["active"] }] });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: NotificationComponent, decorators: [{
type: Component,
args: [{ selector: 'cfc-notification', template: "<!-- notification.component.html -->\r\n<div class=\"cfc-notification-container\" [class.is-open]=\"isOpen\">\r\n <div class=\"cfc-notification-surface\">\r\n <!-- \u00C1rea do usu\u00E1rio (1) - Opcional -->\r\n <div class=\"cfc-notification-user-area\" *ngIf=\"showUserArea\">\r\n <div class=\"user-info\">\r\n <h3 class=\"user-name\">{{ userName }}</h3>\r\n <p class=\"user-email\">{{ userEmail }}</p>\r\n </div>\r\n\r\n <!-- Bot\u00E3o Fechar (2) - Opcional -->\r\n <button *ngIf=\"showCloseButton\"\r\n class=\"cfc-notification-close-button\"\r\n (click)=\"close()\"\r\n aria-label=\"Fechar notifica\u00E7\u00F5es\">\r\n <span class=\"close-icon\">\u2715</span>\r\n </button>\r\n </div>\r\n\r\n <!-- Componente Divider (5) -->\r\n <div class=\"cfc-divider\" *ngIf=\"showUserArea\"></div>\r\n\r\n <!-- Usando o componente cfc-tab -->\r\n <cfc-tab #cfcTabRef *ngIf=\"showTabs && tabs && tabs.length\" density=\"default\" tabAlignment=\"center\" >\r\n <!-- Cria os tab-items din\u00E2micos baseados nos tabs fornecidos -->\r\n <cfc-tab-item *ngFor=\"let tab of tabs\"\r\n [label]=\"tab.label\"\r\n [icon]=\"tab.icon\">\r\n </cfc-tab-item>\r\n\r\n <!-- Cria os tab-contents correspondentes -->\r\n <cfc-tab-content *ngFor=\"let tabNotifications of notificationsByTab; let i = index\">\r\n <div class=\"cfc-notification-items\" [style.max-height]=\"maxHeight\">\r\n <!-- Lista de notifica\u00E7\u00F5es -->\r\n <div *ngFor=\"let notification of tabNotifications\"\r\n class=\"cfc-notification-item\"\r\n [class.is-new]=\"notification.isNew\"\r\n [class.is-read]=\"notification.isRead\"\r\n (click)=\"markAsRead(notification)\">\r\n\r\n <!-- Tag de Status (opcional) -->\r\n <div *ngIf=\"notification.isNew\" class=\"notification-tag\">\r\n <span class=\"tag-indicator\" [style.background-color]=\"notification.tagColor || '#FFD100'\"></span>\r\n <span class=\"tag-label\">Novo</span>\r\n </div>\r\n\r\n <!-- T\u00EDtulo da Notifica\u00E7\u00E3o -->\r\n <h4 class=\"notification-title\">{{ notification.title }}</h4>\r\n\r\n <!-- Conte\u00FAdo -->\r\n <p class=\"notification-content\">{{ notification.content }}</p>\r\n\r\n <!-- Componente Divider (5) -->\r\n <div class=\"cfc-divider\"></div>\r\n </div>\r\n\r\n <!-- Mensagem para nenhuma notifica\u00E7\u00E3o -->\r\n <div *ngIf=\"!tabNotifications || tabNotifications.length === 0\" class=\"no-notifications\">\r\n <p>Nenhuma notifica\u00E7\u00E3o dispon\u00EDvel.</p>\r\n </div>\r\n </div>\r\n </cfc-tab-content>\r\n </cfc-tab>\r\n\r\n <!-- Quando n\u00E3o h\u00E1 tabs, exibe todas as notifica\u00E7\u00F5es -->\r\n <div *ngIf=\"!showTabs || !tabs || !tabs.length\" class=\"cfc-notification-items-container\">\r\n <div class=\"cfc-notification-items\" [style.max-height]=\"maxHeight\">\r\n <!-- Lista de notifica\u00E7\u00F5es -->\r\n <div *ngFor=\"let notification of notifications\"\r\n class=\"cfc-notification-item\"\r\n [class.is-new]=\"notification.isNew\"\r\n [class.is-read]=\"notification.isRead\"\r\n (click)=\"markAsRead(notification)\">\r\n\r\n <!-- Tag de Status (opcional) -->\r\n <div *ngIf=\"notification.isNew\" class=\"notification-tag\">\r\n <span class=\"tag-indicator\" [style.background-color]=\"notification.tagColor || '#FFD100'\"></span>\r\n <span class=\"tag-label\">Novo</span>\r\n </div>\r\n\r\n <!-- T\u00EDtulo da Notifica\u00E7\u00E3o -->\r\n <h4 class=\"notification-title\">{{ notification.title }}</h4>\r\n\r\n <!-- Informa\u00E7\u00E3o Cronol\u00F3gica -->\r\n <p class=\"notification-time\">{{ notification.time }}</p>\r\n\r\n <!-- Conte\u00FAdo -->\r\n <p class=\"notification-content\">{{ notification.content }}</p>\r\n\r\n <!-- Componente Divider (5) -->\r\n <div class=\"cfc-divider\"></div>\r\n </div>\r\n\r\n <!-- Mensagem para nenhuma notifica\u00E7\u00E3o -->\r\n <div *ngIf=\"!notifications || notifications.length === 0\" class=\"no-notifications\">\r\n <p>Nenhuma notifica\u00E7\u00E3o dispon\u00EDvel.</p>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n</div>\r\n", styles: [".cfc-notification-container{position:relative;display:none}.cfc-notification-container.is-open{display:block}.cfc-notification-surface{position:absolute;top:0;right:0;background-color:#fff;border-radius:4px;box-shadow:0 2px 8px #00000026;width:400px;z-index:1000;overflow:hidden}@media (max-width: 767px){.cfc-notification-surface{width:100%;position:fixed;top:0;left:0;right:0;height:100vh;border-radius:0}}.cfc-notification-user-area{display:flex;justify-content:space-between;align-items:center;padding:16px}.cfc-notification-user-area .user-info .user-name{margin:0;font-size:18px;font-weight:500;color:#333}.cfc-notification-user-area .user-info .user-email{margin:4px 0 0;font-size:14px;color:#666}.cfc-notification-close-button{background:none;border:none;cursor:pointer;width:32px;height:32px;display:flex;align-items:center;justify-content:center;color:#333}.cfc-notification-close-button:hover{background-color:#0000000d;border-radius:50%}.cfc-notification-close-button .close-icon{font-size:16px}.cfc-divider{height:1px;background-color:#e0e0e0;width:100%}.cfc-notification-items{overflow-y:auto;position:relative;max-height:60vh}.cfc-notification-items::-webkit-scrollbar{width:6px}.cfc-notification-items::-webkit-scrollbar-track{background:#f1f1f1}.cfc-notification-items::-webkit-scrollbar-thumb{background:#888;border-radius:3px}.cfc-notification-items::-webkit-scrollbar-thumb:hover{background:#555}.cfc-notification-item{padding:16px;cursor:pointer;transition:background-color .2s ease}.cfc-notification-item:hover{background-color:#00000008}.cfc-notification-item.is-new{background-color:#0e47cb0d}.cfc-notification-item .notification-tag{display:flex;align-items:center;margin-bottom:8px}.cfc-notification-item .notification-tag .tag-indicator{width:10px;height:10px;border-radius:50%;margin-right:6px}.cfc-notification-item .notification-tag .tag-label{font-size:12px;font-weight:500;color:#666}.cfc-notification-item .notification-title{margin:0 0 4px;font-size:16px;font-weight:500;color:#333}.cfc-notification-item .notification-time{margin:0 0 8px;font-size:12px;color:#888}.cfc-notification-item .notification-content{margin:0;font-size:14px;color:#555;line-height:1.5}.cfc-notification-item .cfc-divider{margin-top:16px}.no-notifications{padding:24px 16px;text-align:center;color:#666}@media (max-width: 991px) and (min-width: 768px){.cfc-notification-surface{width:50%;max-width:400px}}@media (max-width: 767px){.cfc-notification-close-button{display:flex!important}}\n"] }]
}], ctorParameters: () => [{ type: i0.ElementRef }], propDecorators: { userName: [{
type: Input
}], userEmail: [{
type: Input
}], notifications: [{
type: Input
}], tabs: [{
type: Input
}], showUserArea: [{
type: Input
}], showCloseButton: [{
type: Input
}], isOpen: [{
type: Input
}], maxHeight: [{
type: Input
}], showTabs: [{
type: Input
}], cfcTabRef: [{
type: ViewChild,
args: ['cfcTabRef']
}], clickOutside: [{
type: HostListener,
args: ['document:click', ['$event']]
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibm90aWZpY2F0aW9uLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL2NmYy1kcy9zcmMvbGliL2NvbXBvbmVudHMvbm90aWZpY2F0aW9uL25vdGlmaWNhdGlvbi5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9jZmMtZHMvc3JjL2xpYi9jb21wb25lbnRzL25vdGlmaWNhdGlvbi9ub3RpZmljYXRpb24uY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFNBQVMsRUFBRSxLQUFLLEVBQXNCLFlBQVksRUFBRSxTQUFTLEVBQWlCLE1BQU0sZUFBZSxDQUFDOzs7Ozs7QUFTN0csTUFBTSxPQUFPLHFCQUFxQjtJQWdCWjtJQWZYLFFBQVEsR0FBVyxFQUFFLENBQUM7SUFDdEIsU0FBUyxHQUFXLEVBQUUsQ0FBQztJQUN2QixhQUFhLEdBQXVCLEVBQUUsQ0FBQztJQUN2QyxJQUFJLEdBQWMsRUFBRSxDQUFDO0lBQ3JCLFlBQVksR0FBWSxJQUFJLENBQUM7SUFDN0IsZUFBZSxHQUFZLElBQUksQ0FBQztJQUNoQyxNQUFNLEdBQVksS0FBSyxDQUFDO0lBQ3hCLFNBQVMsR0FBVyxNQUFNLENBQUM7SUFDM0IsUUFBUSxHQUFZLElBQUksQ0FBQztJQUVWLFNBQVMsQ0FBTTtJQUV2QywyQ0FBMkM7SUFDM0Msa0JBQWtCLEdBQXlCLEVBQUUsQ0FBQztJQUU5QyxZQUFvQixVQUFzQjtRQUF0QixlQUFVLEdBQVYsVUFBVSxDQUFZO0lBQUcsQ0FBQztJQUU5QyxRQUFRO1FBQ04sK0NBQStDO1FBQy9DLElBQUksQ0FBQywwQkFBMEIsRUFBRSxDQUFDO1FBRWxDLHFDQUFxQztRQUNyQyxJQUFJLENBQUMsaUJBQWlCLEVBQUUsQ0FBQztRQUV6QixnREFBZ0Q7UUFDaEQsSUFBSSxJQUFJLENBQUMsSUFBSSxJQUFJLElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxHQUFHLENBQUMsRUFBRSxDQUFDO1lBQ3RDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsTUFBTSxHQUFHLElBQUksQ0FBQztRQUM3QixDQUFDO1FBRUQsSUFBSSxDQUFDLGFBQWEsQ0FBQyxPQUFPLENBQUMsWUFBWSxDQUFDLEVBQUU7WUFDeEMsSUFBSSxZQUFZLENBQUMsTUFBTSxLQUFLLFNBQVMsRUFBRSxDQUFDO2dCQUN0QyxZQUFZLENBQUMsTUFBTSxHQUFHLEtBQUssQ0FBQztZQUM5QixDQUFDO1FBQ0gsQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDO0lBRUQsZUFBZTtRQUNiLFVBQVUsQ0FBQyxHQUFHLEVBQUU7WUFDZCxJQUFJLENBQUMsY0FBYyxFQUFFLENBQUM7UUFDeEIsQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDO0lBRU8sY0FBYztRQUNwQixNQUFNLFVBQVUsR0FBRyxJQUFJLENBQUMsVUFBVSxDQUFDLGFBQWEsQ0FBQyxhQUFhLENBQUMsU0FBUyxDQUFDLENBQUM7UUFFMUUsSUFBSSxVQUFVLEVBQUUsQ0FBQztZQUNmLE1BQU0sWUFBWSxHQUFHLFVBQVUsQ0FBQyxhQUFhLENBQUMsY0FBYyxDQUFDLENBQUM7WUFFOUQsSUFBSSxZQUFZLEVBQUUsQ0FBQztnQkFDakIsd0NBQXdDO2dCQUN4QyxZQUFZLENBQUMsS0FBSyxFQUFFLENBQUM7WUFDdkIsQ0FBQztRQUNILENBQUM7SUFDSCxDQUFDO0lBRUQsMEJBQTBCO1FBQ3hCLElBQUksQ0FBQyxJQUFJLENBQUMsYUFBYSxFQUFFLENBQUM7WUFDeEIsSUFBSSxDQUFDLGtCQUFrQixHQUFHLEVBQUUsQ0FBQztZQUM3QixPQUFPO1FBQ1QsQ0FBQztRQUVELElBQUksSUFBSSxDQUFDLElBQUksSUFBSSxJQUFJLENBQUMsSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFDO1lBQ2xDLElBQUksQ0FBQyxrQkFBa0IsR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsRUFBRTtnQkFDNUMsaUVBQWlFO2dCQUNqRSxJQUFJLENBQUMsSUFBSSxDQUFDLGFBQWEsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDLEVBQUUsQ0FBQztvQkFDOUMsT0FBTyxHQUFHLENBQUMsS0FBSyxDQUFDLFdBQVcsRUFBRSxLQUFLLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLFdBQVcsRUFBRTt3QkFDakUsQ0FBQyxDQUFDLENBQUMsR0FBRyxJQUFJLENBQUMsYUFBYSxDQUFDO3dCQUN6QixDQUFDLENBQUMsRUFBRSxDQUFDO2dCQUNULENBQUM7Z0JBRUQsT0FBTyxJQUFJLENBQUMsYUFBYSxDQUFDLE1BQU0sQ0FBQyxZQUFZLENBQUMsRUFBRSxDQUM5QyxZQUFZLENBQUMsUUFBUSxFQUFFLFdBQVcsRUFBRSxLQUFLLEdBQUcsQ0FBQyxLQUFLLENBQUMsV0FBVyxFQUFFLENBQUMsQ0FBQztZQUN0RSxDQUFDLENBQUMsQ0FBQztRQUNMLENBQUM7YUFBTSxDQUFDO1lBQ04scUVBQXFFO1lBQ3JFLElBQUksQ0FBQyxrQkFBa0IsR0FBRyxDQUFDLElBQUksQ0FBQyxhQUFhLENBQUMsQ0FBQztRQUNqRCxDQUFDO0lBQ0gsQ0FBQztJQUVEOztPQUVHO0lBQ0gsaUJBQWlCO1FBQ2YsSUFBSSxJQUFJLENBQUMsSUFBSSxJQUFJLElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxJQUFJLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxNQUFNLEVBQUUsQ0FBQztZQUNwRSxJQUFJLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDLEdBQUcsRUFBRSxLQUFLLEVBQUUsRUFBRTtnQkFDL0IsSUFBSSxLQUFLLEdBQUcsSUFBSSxDQUFDLGtCQUFrQixDQUFDLE1BQU0sRUFBRSxDQUFDO29CQUMzQyxzQ0FBc0M7b0JBQ3RDLEdBQUcsQ0FBQyxPQUFPLEdBQUcsSUFBSSxDQUFDLGtCQUFrQixDQUFDLEtBQUssQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxNQUFNLENBQUM7Z0JBQzNFLENBQUM7WUFDSCxDQUFDLENBQUMsQ0FBQztRQUNMLENBQUM7SUFDSCxDQUFDO0lBRUQ7O09BRUc7SUFFSCxZQUFZLENBQUMsS0FBWTtRQUN2QixJQUFJLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxhQUFhLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsSUFBSSxJQUFJLENBQUMsTUFBTSxFQUFFLENBQUM7WUFDekUsSUFBSSxDQUFDLEtBQUssRUFBRSxDQUFDO1FBQ2YsQ0FBQztJQUNILENBQUM7SUFFRDs7T0FFRztJQUNILEtBQUs7UUFDSCxJQUFJLENBQUMsTUFBTSxHQUFHLEtBQUssQ0FBQztJQUN0QixDQUFDO0lBRUQ7O09BRUc7SUFDSCxVQUFVLENBQUMsWUFBOEI7UUFDdkMsWUFBWSxDQUFDLEtBQUssR0FBRyxLQUFLLENBQUM7UUFDM0IsWUFBWSxDQUFDLE1BQU0sR0FBRyxJQUFJLENBQUM7UUFDM0IsSUFBSSxDQUFDLGlCQUFpQixFQUFFLENBQUM7SUFDM0IsQ0FBQzt3R0F0SFUscUJBQXFCOzRGQUFyQixxQkFBcUIsNmNDVGxDLHVpSkFxR0E7OzRGRDVGYSxxQkFBcUI7a0JBTGpDLFNBQVM7K0JBQ0Usa0JBQWtCOytFQUtuQixRQUFRO3NCQUFoQixLQUFLO2dCQUNHLFNBQVM7c0JBQWpCLEtBQUs7Z0JBQ0csYUFBYTtzQkFBckIsS0FBSztnQkFDRyxJQUFJO3NCQUFaLEtBQUs7Z0JBQ0csWUFBWTtzQkFBcEIsS0FBSztnQkFDRyxlQUFlO3NCQUF2QixLQUFLO2dCQUNHLE1BQU07c0JBQWQsS0FBSztnQkFDRyxTQUFTO3NCQUFqQixLQUFLO2dCQUNHLFFBQVE7c0JBQWhCLEtBQUs7Z0JBRWtCLFNBQVM7c0JBQWhDLFNBQVM7dUJBQUMsV0FBVztnQkF1RnRCLFlBQVk7c0JBRFgsWUFBWTt1QkFBQyxnQkFBZ0IsRUFBRSxDQUFDLFFBQVEsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IENvbXBvbmVudCwgSW5wdXQsIE9uSW5pdCwgRWxlbWVudFJlZiwgSG9zdExpc3RlbmVyLCBWaWV3Q2hpbGQsIEFmdGVyVmlld0luaXQgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcclxuaW1wb3J0IHsgTm90aWZpY2F0aW9uSXRlbSB9IGZyb20gJy4uLy4uL21vZGVscy9ub3RpZmljYXRpb24taXRlbS5tb2RlbCc7XHJcbmltcG9ydCB7IFRhYkl0ZW0gfSBmcm9tICcuLi8uLi9tb2RlbHMvdGFiLWl0ZW0ubW9kZWwnO1xyXG5cclxuQENvbXBvbmVudCh7XHJcbiAgc2VsZWN0b3I6ICdjZmMtbm90aWZpY2F0aW9uJyxcclxuICB0ZW1wbGF0ZVVybDogJy4vbm90aWZpY2F0aW9uLmNvbXBvbmVudC5odG1sJyxcclxuICBzdHlsZVVybHM6IFsnLi9ub3RpZmljYXRpb24uY29tcG9uZW50LnNjc3MnXVxyXG59KVxyXG5leHBvcnQgY2xhc3MgTm90aWZpY2F0aW9uQ29tcG9uZW50IGltcGxlbWVudHMgT25Jbml0LCBBZnRlclZpZXdJbml0IHtcclxuICBASW5wdXQoKSB1c2VyTmFtZTogc3RyaW5nID0gJyc7XHJcbiAgQElucHV0KCkgdXNlckVtYWlsOiBzdHJpbmcgPSAnJztcclxuICBASW5wdXQoKSBub3RpZmljYXRpb25zOiBOb3RpZmljYXRpb25JdGVtW10gPSBbXTtcclxuICBASW5wdXQoKSB0YWJzOiBUYWJJdGVtW10gPSBbXTtcclxuICBASW5wdXQoKSBzaG93VXNlckFyZWE6IGJvb2xlYW4gPSB0cnVlO1xyXG4gIEBJbnB1dCgpIHNob3dDbG9zZUJ1dHRvbjogYm9vbGVhbiA9IHRydWU7XHJcbiAgQElucHV0KCkgaXNPcGVuOiBib29sZWFuID0gZmFsc2U7XHJcbiAgQElucHV0KCkgbWF4SGVpZ2h0OiBzdHJpbmcgPSAnNjB2aCc7XHJcbiAgQElucHV0KCkgc2hvd1RhYnM6IGJvb2xlYW4gPSB0cnVlO1xyXG5cclxuICBAVmlld0NoaWxkKCdjZmNUYWJSZWYnKSBjZmNUYWJSZWY6IGFueTtcclxuXHJcbiAgLy8gUGFyYSBjYXRlZ29yaXphciBhcyBub3RpZmljYcOnw7VlcyBwb3IgdGFiXHJcbiAgbm90aWZpY2F0aW9uc0J5VGFiOiBOb3RpZmljYXRpb25JdGVtW11bXSA9IFtdO1xyXG5cclxuICBjb25zdHJ1Y3Rvcihwcml2YXRlIGVsZW1lbnRSZWY6IEVsZW1lbnRSZWYpIHt9XHJcblxyXG4gIG5nT25Jbml0KCk6IHZvaWQge1xyXG4gICAgLy8gT3JnYW5pemEgYXMgbm90aWZpY2HDp8O1ZXMgcG9yIGNhdGVnb3JpYSAodGFiKVxyXG4gICAgdGhpcy5vcmdhbml6ZU5vdGlmaWNhdGlvbnNCeVRhYigpO1xyXG5cclxuICAgIC8vIEF0dWFsaXphIG9zIGNvbnRhZG9yZXMgZGUgY2FkYSB0YWJcclxuICAgIHRoaXMudXBkYXRlVGFiQ291bnRlcnMoKTtcclxuXHJcbiAgICAvLyBEZWZpbmUgbyBwcmltZWlybyB0YWIgY29tbyBhdGl2bywgY2FzbyBleGlzdGFcclxuICAgIGlmICh0aGlzLnRhYnMgJiYgdGhpcy50YWJzLmxlbmd0aCA+IDApIHtcclxuICAgICAgdGhpcy50YWJzWzBdLmFjdGl2ZSA9IHRydWU7XHJcbiAgICB9XHJcblxyXG4gICAgdGhpcy5ub3RpZmljYXRpb25zLmZvckVhY2gobm90aWZpY2F0aW9uID0+IHtcclxuICAgICAgaWYgKG5vdGlmaWNhdGlvbi5pc1JlYWQgPT09IHVuZGVmaW5lZCkge1xyXG4gICAgICAgIG5vdGlmaWNhdGlvbi5pc1JlYWQgPSBmYWxzZTtcclxuICAgICAgfVxyXG4gICAgfSk7XHJcbiAgfVxyXG5cclxuICBuZ0FmdGVyVmlld0luaXQoKTogdm9pZCB7XHJcbiAgICBzZXRUaW1lb3V0KCgpID0+IHtcclxuICAgICAgdGhpcy5zZWxlY3RGaXJzdFRhYigpO1xyXG4gICAgfSk7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIHNlbGVjdEZpcnN0VGFiKCk6IHZvaWQge1xyXG4gICAgY29uc3QgdGFiRWxlbWVudCA9IHRoaXMuZWxlbWVudFJlZi5uYXRpdmVFbGVtZW50LnF1ZXJ5U2VsZWN0b3IoJ2NmYy10YWInKTtcclxuXHJcbiAgICBpZiAodGFiRWxlbWVudCkge1xyXG4gICAgICBjb25zdCBmaXJzdFRhYkl0ZW0gPSB0YWJFbGVtZW50LnF1ZXJ5U2VsZWN0b3IoJ2NmYy10YWItaXRlbScpO1xyXG5cclxuICAgICAgaWYgKGZpcnN0VGFiSXRlbSkge1xyXG4gICAgICAgIC8vIFNpbXVsYSB1bSBjbGlxdWUgbm8gcHJpbWVpcm8gdGFiLWl0ZW1cclxuICAgICAgICBmaXJzdFRhYkl0ZW0uY2xpY2soKTtcclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgb3JnYW5pemVOb3RpZmljYXRpb25zQnlUYWIoKTogdm9pZCB7XHJcbiAgICBpZiAoIXRoaXMubm90aWZpY2F0aW9ucykge1xyXG4gICAgICB0aGlzLm5vdGlmaWNhdGlvbnNCeVRhYiA9IFtdO1xyXG4gICAgICByZXR1cm47XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKHRoaXMudGFicyAmJiB0aGlzLnRhYnMubGVuZ3RoKSB7XHJcbiAgICAgIHRoaXMubm90aWZpY2F0aW9uc0J5VGFiID0gdGhpcy50YWJzLm1hcCh0YWIgPT4ge1xyXG4gICAgICAgIC8vIFNlIG7Do28gaG91dmVyIGNhdGVnb3JpYSBkZWZpbmlkYSwgY29sb2NhIHRvZGFzIG5vIHByaW1laXJvIHRhYlxyXG4gICAgICAgIGlmICghdGhpcy5ub3RpZmljYXRpb25zLnNvbWUobiA9PiBuLmNhdGVnb3J5KSkge1xyXG4gICAgICAgICAgcmV0dXJuIHRhYi5sYWJlbC50b0xvd2VyQ2FzZSgpID09PSB0aGlzLnRhYnNbMF0ubGFiZWwudG9Mb3dlckNhc2UoKVxyXG4gICAgICAgICAgICA/IFsuLi50aGlzLm5vdGlmaWNhdGlvbnNdXHJcbiAgICAgICAgICAgIDogW107XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICByZXR1cm4gdGhpcy5ub3RpZmljYXRpb25zLmZpbHRlcihub3RpZmljYXRpb24gPT5cclxuICAgICAgICAgIG5vdGlmaWNhdGlvbi5jYXRlZ29yeT8udG9Mb3dlckNhc2UoKSA9PT0gdGFiLmxhYmVsLnRvTG93ZXJDYXNlKCkpO1xyXG4gICAgICB9KTtcclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIC8vIFNlIG7Do28gaG91dmVyIHRhYnMsIGNvbG9jYSB0b2RhcyBhcyBub3RpZmljYcOnw7VlcyBubyBwcmltZWlybyBncnVwb1xyXG4gICAgICB0aGlzLm5vdGlmaWNhdGlvbnNCeVRhYiA9IFt0aGlzLm5vdGlmaWNhdGlvbnNdO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogQXR1YWxpemEgb3MgY29udGFkb3JlcyBkZSBjYWRhIHRhYlxyXG4gICAqL1xyXG4gIHVwZGF0ZVRhYkNvdW50ZXJzKCk6IHZvaWQge1xyXG4gICAgaWYgKHRoaXMudGFicyAmJiB0aGlzLnRhYnMubGVuZ3RoICYmIHRoaXMubm90aWZpY2F0aW9uc0J5VGFiLmxlbmd0aCkge1xyXG4gICAgICB0aGlzLnRhYnMuZm9yRWFjaCgodGFiLCBpbmRleCkgPT4ge1xyXG4gICAgICAgIGlmIChpbmRleCA8IHRoaXMubm90aWZpY2F0aW9uc0J5VGFiLmxlbmd0aCkge1xyXG4gICAgICAgICAgLy8gQ29udGEgYXBlbmFzIG5vdGlmaWNhw6fDtWVzIG7Do28gbGlkYXNcclxuICAgICAgICAgIHRhYi5jb3VudGVyID0gdGhpcy5ub3RpZmljYXRpb25zQnlUYWJbaW5kZXhdLmZpbHRlcihuID0+IG4uaXNOZXcpLmxlbmd0aDtcclxuICAgICAgICB9XHJcbiAgICAgIH0pO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogRmVjaGEgbyBub3RpZmljYXRpb24gcXVhbmRvIG8gdXN1w6FyaW8gY2xpY2EgZm9yYSBkZWxlXHJcbiAgICovXHJcbiAgQEhvc3RMaXN0ZW5lcignZG9jdW1lbnQ6Y2xpY2snLCBbJyRldmVudCddKVxyXG4gIGNsaWNrT3V0c2lkZShldmVudDogRXZlbnQpOiB2b2lkIHtcclxuICAgIGlmICghdGhpcy5lbGVtZW50UmVmLm5hdGl2ZUVsZW1lbnQuY29udGFpbnMoZXZlbnQudGFyZ2V0KSAmJiB0aGlzLmlzT3Blbikge1xyXG4gICAgICB0aGlzLmNsb3NlKCk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBGZWNoYSBvIG5vdGlmaWNhdGlvblxyXG4gICAqL1xyXG4gIGNsb3NlKCk6IHZvaWQge1xyXG4gICAgdGhpcy5pc09wZW4gPSBmYWxzZTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIE1hcmNhIHVtYSBub3RpZmljYcOnw6NvIGNvbW8gbGlkYVxyXG4gICAqL1xyXG4gIG1hcmtBc1JlYWQobm90aWZpY2F0aW9uOiBOb3RpZmljYXRpb25JdGVtKTogdm9pZCB7XHJcbiAgICBub3RpZmljYXRpb24uaXNOZXcgPSBmYWxzZTtcclxuICAgIG5vdGlmaWNhdGlvbi5pc1JlYWQgPSB0cnVlO1xyXG4gICAgdGhpcy51cGRhdGVUYWJDb3VudGVycygpO1xyXG4gIH1cclxufVxyXG4iLCI8IS0tIG5vdGlmaWNhdGlvbi5jb21wb25lbnQuaHRtbCAtLT5cclxuPGRpdiBjbGFzcz1cImNmYy1ub3RpZmljYXRpb24tY29udGFpbmVyXCIgW2NsYXNzLmlzLW9wZW5dPVwiaXNPcGVuXCI+XHJcbiAgPGRpdiBjbGFzcz1cImNmYy1ub3RpZmljYXRpb24tc3VyZmFjZVwiPlxyXG4gICAgPCEtLSDDgXJlYSBkbyB1c3XDoXJpbyAoMSkgLSBPcGNpb25hbCAtLT5cclxuICAgIDxkaXYgY2xhc3M9XCJjZmMtbm90aWZpY2F0aW9uLXVzZXItYXJlYVwiICpuZ0lmPVwic2hvd1VzZXJBcmVhXCI+XHJcbiAgICAgIDxkaXYgY2xhc3M9XCJ1c2VyLWluZm9cIj5cclxuICAgICAgICA8aDMgY2xhc3M9XCJ1c2VyLW5hbWVcIj57eyB1c2VyTmFtZSB9fTwvaDM+XHJcbiAgICAgICAgPHAgY2xhc3M9XCJ1c2VyLWVtYWlsXCI+e3sgdXNlckVtYWlsIH19PC9wPlxyXG4gICAgICA8L2Rpdj5cclxuXHJcbiAgICAgIDwhLS0gQm90w6NvIEZlY2hhciAoMikgLSBPcGNpb25hbCAtLT5cclxuICAgICAgPGJ1dHRvbiAqbmdJZj1cInNob3dDbG9zZUJ1dHRvblwiXHJcbiAgICAgICAgICAgICAgY2xhc3M9XCJjZmMtbm90aWZpY2F0aW9uLWNsb3NlLWJ1dHRvblwiXHJcbiAgICAgICAgICAgICAgKGNsaWNrKT1cImNsb3NlKClcIlxyXG4gICAgICAgICAgICAgIGFyaWEtbGFiZWw9XCJGZWNoYXIgbm90aWZpY2HDp8O1ZXNcIj5cclxuICAgICAgICA8c3BhbiBjbGFzcz1cImNsb3NlLWljb25cIj7inJU8L3NwYW4+XHJcbiAgICAgIDwvYnV0dG9uPlxyXG4gICAgPC9kaXY+XHJcblxyXG4gICAgPCEtLSBDb21wb25lbnRlIERpdmlkZXIgKDUpIC0tPlxyXG4gICAgPGRpdiBjbGFzcz1cImNmYy1kaXZpZGVyXCIgKm5nSWY9XCJzaG93VXNlckFyZWFcIj48L2Rpdj5cclxuXHJcbiAgICA8IS0tIFVzYW5kbyBvIGNvbXBvbmVudGUgY2ZjLXRhYiAtLT5cclxuICAgIDxjZmMtdGFiICNjZmNUYWJSZWYgKm5nSWY9XCJzaG93VGFicyAmJiB0YWJzICYmIHRhYnMubGVuZ3RoXCIgZGVuc2l0eT1cImRlZmF1bHRcIiB0YWJBbGlnbm1lbnQ9XCJjZW50ZXJcIiA+XHJcbiAgICAgIDwhLS0gQ3JpYSBvcyB0YWItaXRlbXMgZGluw6JtaWNvcyBiYXNlYWRvcyBub3MgdGFicyBmb3JuZWNpZG9zIC0tPlxyXG4gICAgICA8Y2ZjLXRhYi1pdGVtICpuZ0Zvcj1cImxldCB0YWIgb2YgdGFic1wiXHJcbiAgICAgICAgICAgICAgICAgICAgW2xhYmVsXT1cInRhYi5sYWJlbFwiXHJcbiAgICAgICAgICAgICAgICAgICAgW2ljb25dPVwidGFiLmljb25cIj5cclxuICAgICAgPC9jZmMtdGFiLWl0ZW0+XHJcblxyXG4gICAgICA8IS0tIENyaWEgb3MgdGFiLWNvbnRlbnRzIGNvcnJlc3BvbmRlbnRlcyAtLT5cclxuICAgICAgPGNmYy10YWItY29udGVudCAqbmdGb3I9XCJsZXQgdGFiTm90aWZpY2F0aW9ucyBvZiBub3RpZmljYXRpb25zQnlUYWI7IGxldCBpID0gaW5kZXhcIj5cclxuICAgICAgICA8ZGl2IGNsYXNzPVwiY2ZjLW5vdGlmaWNhdGlvbi1pdGVtc1wiIFtzdHlsZS5tYXgtaGVpZ2h0XT1cIm1heEhlaWdodFwiPlxyXG4gICAgICAgICAgPCEtLSBMaXN0YSBkZSBub3RpZmljYcOnw7VlcyAtLT5cclxuICAgICAgICAgIDxkaXYgKm5nRm9yPVwibGV0IG5vdGlmaWNhdGlvbiBvZiB0YWJOb3RpZmljYXRpb25zXCJcclxuICAgICAgICAgICAgICAgY2xhc3M9XCJjZmMtbm90aWZpY2F0aW9uLWl0ZW1cIlxyXG4gICAgICAgICAgICAgICBbY2xhc3MuaXMtbmV3XT1cIm5vdGlmaWNhdGlvbi5pc05ld1wiXHJcbiAgICAgICAgICAgICAgIFtjbGFzcy5pcy1yZWFkXT1cIm5vdGlmaWNhdGlvbi5pc1JlYWRcIlxyXG4gICAgICAgICAgICAgICAoY2xpY2spPVwibWFya0FzUmVhZChub3RpZmljYXRpb24pXCI+XHJcblxyXG4gICAgICAgICAgICA8IS0tIFRhZyBkZSBTdGF0dXMgKG9wY2lvbmFsKSAtLT5cclxuICAgICAgICAgICAgPGRpdiAqbmdJZj1cIm5vdGlmaWNhdGlvbi5pc05ld1wiIGNsYXNzPVwibm90aWZpY2F0aW9uLXRhZ1wiPlxyXG4gICAgICAgICAgICAgIDxzcGFuIGNsYXNzPVwidGFnLWluZGljYXRvclwiIFtzdHlsZS5iYWNrZ3JvdW5kLWNvbG9yXT1cIm5vdGlmaWNhdGlvbi50YWdDb2xvciB8fCAnI0ZGRDEwMCdcIj48L3NwYW4+XHJcbiAgICAgICAgICAgICAgPHNwYW4gY2xhc3M9XCJ0YWctbGFiZWxcIj5Ob3ZvPC9zcGFuPlxyXG4gICAgICAgICAgICA8L2Rpdj5cclxuXHJcbiAgICAgICAgICAgIDwhLS0gVMOtdHVsbyBkYSBOb3RpZmljYcOnw6NvIC0tPlxyXG4gICAgICAgICAgICA8aDQgY2xhc3M9XCJub3RpZmljYXRpb24tdGl0bGVcIj57eyBub3RpZmljYXRpb24udGl0bGUgfX08L2g0PlxyXG5cclxuICAgICAgICAgICAgPCEtLSBDb250ZcO6ZG8gLS0+XHJcbiAgICAgICAgICAgIDxwIGNsYXNzPVwibm90aWZpY2F0aW9uLWNvbnRlbnRcIj57eyBub3RpZmljYXRpb24uY29udGVudCB9fTwvcD5cclxuXHJcbiAgICAgICAgICAgIDwhLS0gQ29tcG9uZW50ZSBEaXZpZGVyICg1KSAtLT5cclxuICAgICAgICAgICAgPGRpdiBjbGFzcz1cImNmYy1kaXZpZGVyXCI+PC9kaXY+XHJcbiAgICAgICAgICA8L2Rpdj5cclxuXHJcbiAgICAgICAgICA8IS0tIE1lbnNhZ2VtIHBhcmEgbmVuaHVtYSBub3RpZmljYcOnw6NvIC0tPlxyXG4gICAgICAgICAgPGRpdiAqbmdJZj1cIiF0YWJOb3RpZmljYXRpb25zIHx8IHRhYk5vdGlmaWNhdGlvbnMubGVuZ3RoID09PSAwXCIgY2xhc3M9XCJuby1ub3RpZmljYXRpb25zXCI+XHJcbiAgICAgICAgICAgIDxwPk5lbmh1bWEgbm90aWZpY2HDp8OjbyBkaXNwb27DrXZlbC48L3A+XHJcbiAgICAgICAgICA8L2Rpdj5cclxuICAgICAgICA8L2Rpdj5cclxuICAgICAgPC9jZmMtdGFiLWNvbnRlbnQ+XHJcbiAgICA8L2NmYy10YWI+XHJcblxyXG4gICAgPCEtLSBRdWFuZG8gbsOjbyBow6EgdGFicywgZXhpYmUgdG9kYXMgYXMgbm90aWZpY2HDp8O1ZXMgLS0+XHJcbiAgICA8ZGl2ICpuZ0lmPVwiIXNob3dUYWJzIHx8ICF0YWJzIHx8ICF0YWJzLmxlbmd0aFwiIGNsYXNzPVwiY2ZjLW5vdGlmaWNhdGlvbi1pdGVtcy1jb250YWluZXJcIj5cclxuICAgICAgPGRpdiBjbGFzcz1cImNmYy1ub3RpZmljYXRpb24taXRlbXNcIiBbc3R5bGUubWF4LWhlaWdodF09XCJtYXhIZWlnaHRcIj5cclxuICAgICAgICA8IS0tIExpc3RhIGRlIG5vdGlmaWNhw6fDtWVzIC0tPlxyXG4gICAgICAgIDxkaXYgKm5nRm9yPVwibGV0IG5vdGlmaWNhdGlvbiBvZiBub3RpZmljYXRpb25zXCJcclxuICAgICAgICAgICAgIGNsYXNzPVwiY2ZjLW5vdGlmaWNhdGlvbi1pdGVtXCJcclxuICAgICAgICAgICAgIFtjbGFzcy5pcy1uZXddPVwibm90aWZpY2F0aW9uLmlzTmV3XCJcclxuICAgICAgICAgICAgIFtjbGFzcy5pcy1yZWFkXT1cIm5vdGlmaWNhdGlvbi5pc1JlYWRcIlxyXG4gICAgICAgICAgICAgKGNsaWNrKT1cIm1hcmtBc1JlYWQobm90aWZpY2F0aW9uKVwiPlxyXG5cclxuICAgICAgICAgIDwhLS0gVGFnIGRlIFN0YXR1cyAob3BjaW9uYWwpIC0tPlxyXG4gICAgICAgICAgPGRpdiAqbmdJZj1cIm5vdGlmaWNhdGlvbi5pc05ld1wiIGNsYXNzPVwibm90aWZpY2F0aW9uLXRhZ1wiPlxyXG4gICAgICAgICAgICA8c3BhbiBjbGFzcz1cInRhZy1pbmRpY2F0b3JcIiBbc3R5bGUuYmFja2dyb3VuZC1jb2xvcl09XCJub3RpZmljYXRpb24udGFnQ29sb3IgfHwgJyNGRkQxMDAnXCI+PC9zcGFuPlxyXG4gICAgICAgICAgICA8c3BhbiBjbGFzcz1cInRhZy1sYWJlbFwiPk5vdm88L3NwYW4+XHJcbiAgICAgICAgICA8L2Rpdj5cclxuXHJcbiAgICAgICAgICA8IS0tIFTDrXR1bG8gZGEgTm90aWZpY2HDp8OjbyAtLT5cclxuICAgICAgICAgIDxoNCBjbGFzcz1cIm5vdGlmaWNhdGlvbi10aXRsZVwiPnt7IG5vdGlmaWNhdGlvbi50aXRsZSB9fTwvaDQ+XHJcblxyXG4gICAgICAgICAgPCEtLSBJbmZvcm1hw6fDo28gQ3Jvbm9sw7NnaWNhIC0tPlxyXG4gICAgICAgICAgPHAgY2xhc3M9XCJub3RpZmljYXRpb24tdGltZVwiPnt7IG5vdGlmaWNhdGlvbi50aW1lIH19PC9wPlxyXG5cclxuICAgICAgICAgIDwhLS0gQ29udGXDumRvIC0tPlxyXG4gICAgICAgICAgPHAgY2xhc3M9XCJub3RpZmljYXRpb24tY29udGVudFwiPnt7IG5vdGlmaWNhdGlvbi5jb250ZW50IH19PC9wPlxyXG5cclxuICAgICAgICAgIDwhLS0gQ29tcG9uZW50ZSBEaXZpZGVyICg1KSAtLT5cclxuICAgICAgICAgIDxkaXYgY2xhc3M9XCJjZmMtZGl2aWRlclwiPjwvZGl2PlxyXG4gICAgICAgIDwvZGl2PlxyXG5cclxuICAgICAgICA8IS0tIE1lbnNhZ2VtIHBhcmEgbmVuaHVtYSBub3RpZmljYcOnw6NvIC0tPlxyXG4gICAgICAgIDxkaXYgKm5nSWY9XCIhbm90aWZpY2F0aW9ucyB8fCBub3RpZmljYXRpb25zLmxlbmd0aCA9PT0gMFwiIGNsYXNzPVwibm8tbm90aWZpY2F0aW9uc1wiPlxyXG4gICAgICAgICAgPHA+TmVuaHVtYSBub3RpZmljYcOnw6NvIGRpc3BvbsOtdmVsLjwvcD5cclxuICAgICAgICA8L2Rpdj5cclxuICAgICAgPC9kaXY+XHJcbiAgICA8L2Rpdj5cclxuICA8L2Rpdj5cclxuPC9kaXY+XHJcbiJdfQ==