ng-materialgrammi
Version:
An Angular framework which follows
254 lines • 40.1 kB
JavaScript
import { Component, EventEmitter, Input, Output } from '@angular/core';
import { FormControl } from '@angular/forms';
import * as i0 from "@angular/core";
import * as i1 from "../collapse/collapse.component";
import * as i2 from "../button/button.component";
import * as i3 from "../input/input.component";
import * as i4 from "../select/select.component";
import * as i5 from "../pagination/pagination.component";
import * as i6 from "../dropable/dropable.component";
import * as i7 from "../dragable/dragable.component";
import * as i8 from "@angular/common";
export class TableComponent {
constructor(cdref) {
this.cdref = cdref;
this.theme = "primary";
this.mgData = [];
this.ignoredColumns = ["id"];
this.sortBy = "";
this.sortDirection = "ASC";
this.tableTitle = "Table";
this.fixedHeader = false;
this.dragableSort = false;
this.paginate = {
status: false,
perPage: 5
};
this.pagingPosition = {
top: true,
bottom: true
};
this.columnsOrder = [];
this.showOptions = {
title: false,
filter: false,
sort: false,
count: false
};
this.buttons = [];
/*
[{
title: "options",
data: [{
id: "btn1",
text: `<i class="fas fa-hammer"></i>`
}]
}]
*/
this.clicked = new EventEmitter();
this.currentPage = 1;
this.show = false;
this.reformedData = [];
this.reformedHeads = {};
this.headings = [];
this.filterQuery = [];
this.count = 0;
this.paginatedData = [];
this.openFilterBox = false;
this.openSortBox = false;
this.sortOptions = [];
}
setCurrentPage(event) {
this.currentPage = event;
}
setShowTimer() {
var $this = this;
setTimeout(function () {
$this.show = true;
}, 1000);
}
ngOnInit() {
this.init();
this.setShowTimer();
}
ngOnChanges() {
this.init();
}
ngAfterContentChecked() {
this.cdref.detectChanges();
}
buttonIsClicked(btnId, rowNum) {
this.clicked.emit({
id: btnId,
data: this.reformedData[rowNum]
});
}
init() {
this.extractHeadings();
this.refactorData();
this.count = this.reformedData.length;
}
concatHeads(headObj) {
for (let i = 0; i < headObj.length; i++) {
if (!this.headings.includes(headObj[i]) && !this.ignoredColumns.includes(headObj[i])) {
this.headings.push(headObj[i]);
this.sortOptions.push({ name: headObj[i], val: headObj[i] });
this.filterQuery.push({ name: headObj[i], val: new FormControl("") });
}
}
}
sortColumns() {
if (this.columnsOrder && this.columnsOrder.length > 0) {
let newHeads = [];
for (let i = 0; i < this.columnsOrder.length; i++) {
for (let j = 0; j < this.headings.length; j++) {
if (this.columnsOrder[i] === this.headings[j]) {
newHeads.push(this.headings[j]);
}
}
}
let newDiff = this.headings.filter((x) => !newHeads.includes(x));
newHeads = [...newHeads, ...newDiff];
this.headings = newHeads;
}
}
extractHeadings() {
for (let i = 0; i < this.mgData.length; i++) {
let objHeads = Object.keys(this.mgData[i]);
this.concatHeads(objHeads);
}
this.sortColumns();
}
refactorData(dataToUpdate = this.mgData) {
this.reformedData = [];
for (let i = 0; i < dataToUpdate.length; i++) {
let data = [];
for (let j = 0; j < this.headings.length; j++) {
if (dataToUpdate[i]) {
let d = dataToUpdate[i][this.headings[j]] != undefined ? dataToUpdate[i][this.headings[j]] : "-";
data.push(d);
}
}
this.reformedData.push(data);
}
this.reformedHeads = this.reformedData[0];
this.sortByException();
}
sortFlip(newKey) {
this.sortDirection = this.sortDirection === "" ? "ASC" : this.sortDirection;
if (this.sortBy != "") {
if (this.sortBy == newKey) {
if (this.sortDirection == "ASC") {
this.sortDirection = "DESC";
}
else {
this.sortDirection = "ASC";
}
}
else {
this.sortDirection = "ASC";
}
}
}
sort(sortKey) {
console.log("key ==> ", sortKey);
this.sortByException();
if (this.sortBy != "") {
this.sortFlip(sortKey);
this.sortBy = sortKey;
let sorter = this.headings.indexOf(this.sortBy);
var $this = this;
let compare = (a, b) => {
a[sorter] = a[sorter].toString();
b[sorter] = b[sorter].toString();
if (a[sorter] < b[sorter]) {
return $this.sortDirection === "ASC" ? -1 : 1;
}
if (a[sorter] > b[sorter]) {
return $this.sortDirection === "ASC" ? 1 : -1;
}
return 0;
};
this.reformedData = this.reformedData.sort(compare);
}
}
sortByException() {
if (this.sortBy == "") {
this.sortBy = this.headings[0];
}
}
filter(filterKey) {
this.reformedData = this.reformedData.filter(function (el) {
return el.price <= 1000 &&
el.sqft >= 500 &&
el.num_of_beds >= 2 &&
el.num_of_baths >= 2.5;
});
}
openSorter() {
this.openSortBox = !this.openSortBox;
this.openFilterBox = false;
}
openFilter() {
this.openFilterBox = !this.openFilterBox;
this.openSortBox = false;
}
search(enable) {
console.log(enable);
}
recieveData(event, k) {
if (this.dragableSort) {
let fromColumn = this.columnsOrder[event.order];
this.columnsOrder[event.order] = this.columnsOrder[k];
this.columnsOrder[k] = fromColumn;
fromColumn = undefined;
this.extractHeadings();
if (this.paginate.status) {
this.refactorData(this.paginatedData);
}
else {
this.refactorData();
}
}
}
updatePaginatedData(data) {
this.paginatedData = data;
if (this.paginate.status)
this.refactorData(this.paginatedData);
}
}
TableComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.0.3", ngImport: i0, type: TableComponent, deps: [{ token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
TableComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.0.3", type: TableComponent, selector: "mg-table", inputs: { theme: "theme", mgData: "mgData", ignoredColumns: "ignoredColumns", sortBy: "sortBy", sortDirection: "sortDirection", tableTitle: "tableTitle", fixedHeader: "fixedHeader", dragableSort: "dragableSort", paginate: "paginate", pagingPosition: "pagingPosition", columnsOrder: "columnsOrder", showOptions: "showOptions", buttons: "buttons" }, outputs: { clicked: "clicked" }, usesOnChanges: true, ngImport: i0, template: "<div class=\"pad-10\">\n <div class=\"pad-5\">\n <h3><span [innerHtml]=\"tableTitle\" *ngIf=\"showOptions.title\">Table</span> <small class=\"right\" *ngIf=\"showOptions.count\">{{count}} <i\n class=\"fas fa-list-ol padL-5 pointer\" (click)=\"openSorter()\" *ngIf=\"showOptions.sort\"></i> <i\n class=\"fas fa-filter padL-5 font-16 pointer\" (click)=\"openFilter()\" *ngIf=\"showOptions.filter\"></i></small></h3>\n <mg-collapse widgetId=\"1\" [show]=\"openFilterBox\">\n <div class=\"pad-10 collapse-filter-box\">\n <h4>Filter </h4>\n <mg-button (clicked)=\"search($event)\" theme=\"success\" btnSize=\"sm\"><i class=\"fas fa-search padR-5\"></i> Search\n </mg-button>\n <div class=\"row\">\n <div class=\"col m3 l3 s6\" *ngFor=\"let filter of filterQuery\">\n <mg-input [control]=\"filter.val\"><span [innerHtml]=\"filter.name\"></span></mg-input>\n </div>\n </div>\n </div>\n </mg-collapse>\n\n <mg-collapse widgetId=\"2\" [show]=\"openSortBox\">\n <div class=\"pad-10 collapse-sorter-box\">\n <h4 style=\"margin-bottom: 5px;\">Sort</h4>\n <mg-select [options]=\"sortOptions\" (value)=\"sort($event)\"></mg-select>\n </div>\n </mg-collapse>\n </div>\n <div class=\"padV-5\" *ngIf=\"paginate.status && pagingPosition.top\">\n <mg-pagination (page)=\"setCurrentPage($event)\" [currentPage]=\"currentPage\" [theme]=\"theme\" [fullDataMode]=\"true\" [data]=\"mgData\" [perPage]=\"paginate.perPage\" (getdata)=\"updatePaginatedData($event)\"></mg-pagination>\n </div>\n <table class=\"{{theme}}\">\n <thead [ngClass]=\"fixedHeader ? 'fixed-header' : ''\">\n <ng-container>\n \n <th *ngFor=\"let head of headings; let k = index\"><span (click)=\"sort(head)\">\n <mg-dropable (dataRecieved)=\"recieveData($event, k)\">\n <mg-dragable [data]=\"{order: k}\" [dragable]=\"dragableSort\">\n {{head}}\n </mg-dragable>\n </mg-dropable>\n </span></th>\n <ng-container *ngIf=\"buttons && buttons.length > 0\">\n <th *ngFor=\"let btn of buttons\">\n <span *ngIf = \"btn && btn.title\" [innerHtml]=\"btn.title\"></span>\n </th>\n </ng-container>\n </ng-container>\n \n </thead>\n <tbody>\n <ng-container>\n <tr *ngFor=\"let data of reformedData; let ind=index;\">\n <td *ngFor=\"let col of data\" [innerHtml]=\"col\"></td>\n <ng-container *ngIf=\"buttons && buttons.length > 0\">\n <td *ngFor=\"let btn of buttons\">\n <ng-container *ngIf=\"btn.data && btn.data.length > 0\">\n <ng-container *ngFor=\"let d of btn.data\">\n <span (click)=\"buttonIsClicked(d.id, ind)\" [innerHtml]=\"d.text\" style=\"cursor: pointer; padding-left: 5px; padding-right: 5px;\"></span>\n </ng-container>\n </ng-container>\n </td>\n </ng-container>\n \n </tr>\n </ng-container>\n \n </tbody>\n </table>\n <div class=\"padV-5\" *ngIf=\"paginate.status && pagingPosition.bottom\">\n <mg-pagination (page)=\"setCurrentPage($event)\" [currentPage]=\"currentPage\" [theme]=\"theme\" [fullDataMode]=\"true\" [data]=\"mgData\" [perPage]=\"paginate.perPage\" (getdata)=\"updatePaginatedData($event)\"></mg-pagination>\n </div>\n</div>\n", styles: [".fixed-header{position:sticky;top:45px}\n"], components: [{ type: i1.CollapseComponent, selector: "mg-collapse", inputs: ["id", "show", "class"], outputs: ["active"] }, { type: i2.ButtonComponent, selector: "mg-button", inputs: ["taskType", "btnStyle", "task", "target", "theme", "class", "btnSize", "isBlock", "round", "allowMargin", "allowShrink", "options", "isExternalLink", "newTab"], outputs: ["clicked", "active"] }, { type: i3.InputComponent, selector: "mg-input", inputs: ["theme", "form", "placeholder", "control", "type", "dark", "class", "value", "rounded", "filled", "info"], outputs: ["data", "isFocused", "keyup"] }, { type: i4.SelectComponent, selector: "mg-select", inputs: ["searchOpt", "theme", "selectTitle", "selectType", "enableSearch", "options"], outputs: ["value"] }, { type: i5.PaginationComponent, selector: "mg-pagination", inputs: ["theme", "data", "fullDataMode", "perPage", "currentPage", "icons", "max"], outputs: ["page", "getdata"] }, { type: i6.DropableComponent, selector: "mg-dropable", inputs: ["dropFiles", "class"], outputs: ["onEvent", "dataRecieved"] }, { type: i7.DragableComponent, selector: "mg-dragable", inputs: ["dragable", "data", "class"], outputs: ["onEvent"] }], directives: [{ type: i8.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i8.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i8.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }] });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.0.3", ngImport: i0, type: TableComponent, decorators: [{
type: Component,
args: [{ selector: 'mg-table', template: "<div class=\"pad-10\">\n <div class=\"pad-5\">\n <h3><span [innerHtml]=\"tableTitle\" *ngIf=\"showOptions.title\">Table</span> <small class=\"right\" *ngIf=\"showOptions.count\">{{count}} <i\n class=\"fas fa-list-ol padL-5 pointer\" (click)=\"openSorter()\" *ngIf=\"showOptions.sort\"></i> <i\n class=\"fas fa-filter padL-5 font-16 pointer\" (click)=\"openFilter()\" *ngIf=\"showOptions.filter\"></i></small></h3>\n <mg-collapse widgetId=\"1\" [show]=\"openFilterBox\">\n <div class=\"pad-10 collapse-filter-box\">\n <h4>Filter </h4>\n <mg-button (clicked)=\"search($event)\" theme=\"success\" btnSize=\"sm\"><i class=\"fas fa-search padR-5\"></i> Search\n </mg-button>\n <div class=\"row\">\n <div class=\"col m3 l3 s6\" *ngFor=\"let filter of filterQuery\">\n <mg-input [control]=\"filter.val\"><span [innerHtml]=\"filter.name\"></span></mg-input>\n </div>\n </div>\n </div>\n </mg-collapse>\n\n <mg-collapse widgetId=\"2\" [show]=\"openSortBox\">\n <div class=\"pad-10 collapse-sorter-box\">\n <h4 style=\"margin-bottom: 5px;\">Sort</h4>\n <mg-select [options]=\"sortOptions\" (value)=\"sort($event)\"></mg-select>\n </div>\n </mg-collapse>\n </div>\n <div class=\"padV-5\" *ngIf=\"paginate.status && pagingPosition.top\">\n <mg-pagination (page)=\"setCurrentPage($event)\" [currentPage]=\"currentPage\" [theme]=\"theme\" [fullDataMode]=\"true\" [data]=\"mgData\" [perPage]=\"paginate.perPage\" (getdata)=\"updatePaginatedData($event)\"></mg-pagination>\n </div>\n <table class=\"{{theme}}\">\n <thead [ngClass]=\"fixedHeader ? 'fixed-header' : ''\">\n <ng-container>\n \n <th *ngFor=\"let head of headings; let k = index\"><span (click)=\"sort(head)\">\n <mg-dropable (dataRecieved)=\"recieveData($event, k)\">\n <mg-dragable [data]=\"{order: k}\" [dragable]=\"dragableSort\">\n {{head}}\n </mg-dragable>\n </mg-dropable>\n </span></th>\n <ng-container *ngIf=\"buttons && buttons.length > 0\">\n <th *ngFor=\"let btn of buttons\">\n <span *ngIf = \"btn && btn.title\" [innerHtml]=\"btn.title\"></span>\n </th>\n </ng-container>\n </ng-container>\n \n </thead>\n <tbody>\n <ng-container>\n <tr *ngFor=\"let data of reformedData; let ind=index;\">\n <td *ngFor=\"let col of data\" [innerHtml]=\"col\"></td>\n <ng-container *ngIf=\"buttons && buttons.length > 0\">\n <td *ngFor=\"let btn of buttons\">\n <ng-container *ngIf=\"btn.data && btn.data.length > 0\">\n <ng-container *ngFor=\"let d of btn.data\">\n <span (click)=\"buttonIsClicked(d.id, ind)\" [innerHtml]=\"d.text\" style=\"cursor: pointer; padding-left: 5px; padding-right: 5px;\"></span>\n </ng-container>\n </ng-container>\n </td>\n </ng-container>\n \n </tr>\n </ng-container>\n \n </tbody>\n </table>\n <div class=\"padV-5\" *ngIf=\"paginate.status && pagingPosition.bottom\">\n <mg-pagination (page)=\"setCurrentPage($event)\" [currentPage]=\"currentPage\" [theme]=\"theme\" [fullDataMode]=\"true\" [data]=\"mgData\" [perPage]=\"paginate.perPage\" (getdata)=\"updatePaginatedData($event)\"></mg-pagination>\n </div>\n</div>\n", styles: [".fixed-header{position:sticky;top:45px}\n"] }]
}], ctorParameters: function () { return [{ type: i0.ChangeDetectorRef }]; }, propDecorators: { theme: [{
type: Input
}], mgData: [{
type: Input
}], ignoredColumns: [{
type: Input
}], sortBy: [{
type: Input
}], sortDirection: [{
type: Input
}], tableTitle: [{
type: Input
}], fixedHeader: [{
type: Input
}], dragableSort: [{
type: Input
}], paginate: [{
type: Input
}], pagingPosition: [{
type: Input
}], columnsOrder: [{
type: Input
}], showOptions: [{
type: Input
}], buttons: [{
type: Input
}], clicked: [{
type: Output
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGFibGUuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvbWF0ZXJpYWxncmFtbWkvc3JjL2xpYi9jb21wb25lbnRzL3RhYmxlL3RhYmxlLmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL21hdGVyaWFsZ3JhbW1pL3NyYy9saWIvY29tcG9uZW50cy90YWJsZS90YWJsZS5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQTBDLFNBQVMsRUFBRSxZQUFZLEVBQUUsS0FBSyxFQUFxQixNQUFNLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDbEksT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLGdCQUFnQixDQUFDOzs7Ozs7Ozs7O0FBTzdDLE1BQU0sT0FBTyxjQUFjO0lBdUV6QixZQUFvQixLQUF3QjtRQUF4QixVQUFLLEdBQUwsS0FBSyxDQUFtQjtRQXRFbkMsVUFBSyxHQUFHLFNBQVMsQ0FBQztRQUNsQixXQUFNLEdBQVEsRUFBRSxDQUFDO1FBQ2pCLG1CQUFjLEdBQVEsQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUM3QixXQUFNLEdBQVEsRUFBRSxDQUFDO1FBQ2pCLGtCQUFhLEdBQUcsS0FBSyxDQUFDO1FBQ3RCLGVBQVUsR0FBRyxPQUFPLENBQUM7UUFDckIsZ0JBQVcsR0FBRyxLQUFLLENBQUM7UUFDcEIsaUJBQVksR0FBRyxLQUFLLENBQUM7UUFDckIsYUFBUSxHQUFRO1lBQ3ZCLE1BQU0sRUFBRSxLQUFLO1lBQ2IsT0FBTyxFQUFFLENBQUM7U0FDWCxDQUFDO1FBRU8sbUJBQWMsR0FBRztZQUN4QixHQUFHLEVBQUUsSUFBSTtZQUNULE1BQU0sRUFBRSxJQUFJO1NBQ2IsQ0FBQTtRQUVRLGlCQUFZLEdBQU8sRUFBRSxDQUFDO1FBRXRCLGdCQUFXLEdBQUc7WUFDckIsS0FBSyxFQUFFLEtBQUs7WUFDWixNQUFNLEVBQUUsS0FB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Q0csUUFBUTtzQkFBaEIsS0FBSztnQkFLRyxjQUFjO3NCQUF0QixLQUFLO2dCQUtHLFlBQVk7c0JBQXBCLEtBQUs7Z0JBRUcsV0FBVztzQkFBbkIsS0FBSztnQkFPRyxPQUFPO3NCQUFmLEtBQUs7Z0JBWUksT0FBTztzQkFBaEIsTUFBTSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEFmdGVyQ29udGVudENoZWNrZWQsIENoYW5nZURldGVjdG9yUmVmLCBDb21wb25lbnQsIEV2ZW50RW1pdHRlciwgSW5wdXQsIE9uQ2hhbmdlcywgT25Jbml0LCBPdXRwdXQgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IEZvcm1Db250cm9sIH0gZnJvbSAnQGFuZ3VsYXIvZm9ybXMnO1xuXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICdtZy10YWJsZScsXG4gIHRlbXBsYXRlVXJsOiAnLi90YWJsZS5jb21wb25lbnQuaHRtbCcsXG4gIHN0eWxlVXJsczogWycuL3RhYmxlLmNvbXBvbmVudC5jc3MnXVxufSlcbmV4cG9ydCBjbGFzcyBUYWJsZUNvbXBvbmVudCBpbXBsZW1lbnRzIE9uSW5pdCwgT25DaGFuZ2VzLCBBZnRlckNvbnRlbnRDaGVja2VkIHtcbiAgQElucHV0KCkgdGhlbWUgPSBcInByaW1hcnlcIjtcbiAgQElucHV0KCkgbWdEYXRhOiBhbnkgPSBbXTtcbiAgQElucHV0KCkgaWdub3JlZENvbHVtbnM6IGFueSA9IFtcImlkXCJdO1xuICBASW5wdXQoKSBzb3J0Qnk6IGFueSA9IFwiXCI7XG4gIEBJbnB1dCgpIHNvcnREaXJlY3Rpb24gPSBcIkFTQ1wiO1xuICBASW5wdXQoKSB0YWJsZVRpdGxlID0gXCJUYWJsZVwiO1xuICBASW5wdXQoKSBmaXhlZEhlYWRlciA9IGZhbHNlO1xuICBASW5wdXQoKSBkcmFnYWJsZVNvcnQgPSBmYWxzZTtcbiAgQElucHV0KCkgcGFnaW5hdGU/OmFueSA9IHtcbiAgICBzdGF0dXM6IGZhbHNlLCBcbiAgICBwZXJQYWdlOiA1XG4gIH07XG5cbiAgQElucHV0KCkgcGFnaW5nUG9zaXRpb24gPSB7XG4gICAgdG9wOiB0cnVlLFxuICAgIGJvdHRvbTogdHJ1ZVxuICB9XG5cbiAgQElucHV0KCkgY29sdW1uc09yZGVyOmFueSA9IFtdO1xuXG4gIEBJbnB1dCgpIHNob3dPcHRpb25zID0ge1xuICAgIHRpdGxlOiBmYWxzZSxcbiAgICBmaWx0ZXI6IGZhbHNlLFxuICAgIHNvcnQ6IGZhbHNlLFxuICAgIGNvdW50OiBmYWxzZVxuICB9O1xuXG4gIEBJbnB1dCgpIGJ1dHRvbnM6YW55ID0gW107XG5cbiAgLyogXG4gIFt7XG4gICAgdGl0bGU6IFwib3B0aW9uc1wiLFxuICAgIGRhdGE6IFt7XG4gICAgICBpZDogXCJidG4xXCIsXG4gICAgICB0ZXh0OiBgPGkgY2xhc3M9XCJmYXMgZmEtaGFtbWVyXCI+PC9pPmBcbiAgICB9XVxuICB9XVxuICAqL1xuXG4gIEBPdXRwdXQoKSBjbGlja2VkID0gbmV3IEV2ZW50RW1pdHRlcigpO1xuXG4gIGN1cnJlbnRQYWdlID0gMTtcbiAgc2hvdyA9IGZhbHNlO1xuICBcbiAgc2V0Q3VycmVudFBhZ2UoZXZlbnQ6bnVtYmVyKXtcbiAgICB0aGlzLmN1cnJlbnRQYWdlID0gZXZlbnQ7XG4gIH1cblxuICBzZXRTaG93VGltZXIoKTogYW55IHtcbiAgICB2YXIgJHRoaXMgPSB0aGlzO1xuICAgIHNldFRpbWVvdXQoZnVuY3Rpb24gKCkge1xuICAgICAgJHRoaXMuc2hvdyA9IHRydWU7XG4gICAgfSwgMTAwMCk7XG4gIH1cbiAgcmVmb3JtZWREYXRhOiBhbnkgPSBbXTtcbiAgcmVmb3JtZWRIZWFkczogYW55ID0ge307XG5cbiAgaGVhZGluZ3M6IGFueSA9IFtdO1xuXG4gIGZpbHRlclF1ZXJ5OiBhbnkgPSBbXTtcblxuICBjb3VudCA9IDA7XG5cbiAgcGFnaW5hdGVkRGF0YSA9IFtdO1xuXG4gIG9wZW5GaWx0ZXJCb3ggPSBmYWxzZTtcbiAgb3BlblNvcnRCb3ggPSBmYWxzZTtcbiAgc29ydE9wdGlvbnM6IGFueSA9IFtdO1xuXG5cbiAgY29uc3RydWN0b3IocHJpdmF0ZSBjZHJlZjogQ2hhbmdlRGV0ZWN0b3JSZWYpIHsgfVxuXG4gIG5nT25Jbml0KCk6IHZvaWQge1xuICAgIHRoaXMuaW5pdCgpO1xuICAgIHRoaXMuc2V0U2hvd1RpbWVyKCk7XG4gIH1cblxuICBuZ09uQ2hhbmdlcygpOiB2b2lkIHtcbiAgICB0aGlzLmluaXQoKTtcbiAgfVxuXG4gIG5nQWZ0ZXJDb250ZW50Q2hlY2tlZCgpe1xuICAgIHRoaXMuY2RyZWYuZGV0ZWN0Q2hhbmdlcygpO1xuICB9XG5cbiAgYnV0dG9uSXNDbGlja2VkKGJ0bklkOiBzdHJpbmcsIHJvd051bTogbnVtYmVyKXtcbiAgICB0aGlzLmNsaWNrZWQuZW1pdCh7XG4gICAgICBpZDogYnRuSWQsXG4gICAgICBkYXRhOiB0aGlzLnJlZm9ybWVkRGF0YVtyb3dOdW1dXG4gICAgfSk7XG4gIH1cblxuICBpbml0KCkge1xuICAgIHRoaXMuZXh0cmFjdEhlYWRpbmdzKCk7XG4gICAgdGhpcy5yZWZhY3RvckRhdGEoKTtcbiAgICB0aGlzLmNvdW50ID0gdGhpcy5yZWZvcm1lZERhdGEubGVuZ3RoO1xuICB9XG5cbiAgY29uY2F0SGVhZHMoaGVhZE9iajogYW55KSB7XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBoZWFkT2JqLmxlbmd0aDsgaSsrKSB7XG4gICAgICBpZiAoIXRoaXMuaGVhZGluZ3MuaW5jbHVkZXMoaGVhZE9ialtpXSkgJiYgIXRoaXMuaWdub3JlZENvbHVtbnMuaW5jbHVkZXMoaGVhZE9ialtpXSkpIHtcbiAgICAgICAgdGhpcy5oZWFkaW5ncy5wdXNoKGhlYWRPYmpbaV0pO1xuICAgICAgICB0aGlzLnNvcnRPcHRpb25zLnB1c2goeyBuYW1lOiBoZWFkT2JqW2ldLCB2YWw6IGhlYWRPYmpbaV0gfSk7XG4gICAgICAgIHRoaXMuZmlsdGVyUXVlcnkucHVzaCh7IG5hbWU6IGhlYWRPYmpbaV0sIHZhbDogbmV3IEZvcm1Db250cm9sKFwiXCIpIH0pO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHNvcnRDb2x1bW5zKCl7XG4gICAgaWYodGhpcy5jb2x1bW5zT3JkZXIgJiYgdGhpcy5jb2x1bW5zT3JkZXIubGVuZ3RoID4gMCl7XG4gICAgICBsZXQgbmV3SGVhZHM6YW55ID0gW107XG4gICAgICBmb3IobGV0IGkgPSAwOyBpIDwgdGhpcy5jb2x1bW5zT3JkZXIubGVuZ3RoOyBpKyspe1xuICAgICAgICBmb3IobGV0IGogPSAwOyBqIDwgdGhpcy5oZWFkaW5ncy5sZW5ndGg7IGorKyl7XG4gICAgICAgICAgaWYodGhpcy5jb2x1bW5zT3JkZXJbaV0gPT09IHRoaXMuaGVhZGluZ3Nbal0pe1xuICAgICAgICAgICAgbmV3SGVhZHMucHVzaCh0aGlzLmhlYWRpbmdzW2pdKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgbGV0IG5ld0RpZmYgPSB0aGlzLmhlYWRpbmdzLmZpbHRlcigoeDphbnkpID0+ICFuZXdIZWFkcy5pbmNsdWRlcyh4KSk7XG4gICAgICBuZXdIZWFkcyA9IFsuLi5uZXdIZWFkcywgLi4ubmV3RGlmZl07XG4gICAgICB0aGlzLmhlYWRpbmdzID0gbmV3SGVhZHM7XG4gICAgfVxuICB9XG5cbiAgZXh0cmFjdEhlYWRpbmdzKCkge1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy5tZ0RhdGEubGVuZ3RoOyBpKyspIHtcbiAgICAgIGxldCBvYmpIZWFkcyA9IE9iamVjdC5rZXlzKHRoaXMubWdEYXRhW2ldKTtcbiAgICAgIHRoaXMuY29uY2F0SGVhZHMob2JqSGVhZHMpO1xuICAgIH1cbiAgICB0aGlzLnNvcnRDb2x1bW5zKCk7XG4gIH1cblxuICByZWZhY3RvckRhdGEoZGF0YVRvVXBkYXRlOiBhbnlbXSA9IHRoaXMubWdEYXRhKSB7XG5cbiAgICB0aGlzLnJlZm9ybWVkRGF0YSA9IFtdO1xuXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBkYXRhVG9VcGRhdGUubGVuZ3RoOyBpKyspIHtcbiAgICAgIGxldCBkYXRhOiBhbnkgPSBbXTtcblxuICAgICAgZm9yIChsZXQgaiA9IDA7IGogPCB0aGlzLmhlYWRpbmdzLmxlbmd0aDsgaisrKSB7XG4gICAgICAgIGlmKGRhdGFUb1VwZGF0ZVtpXSl7XG4gICAgICAgICAgbGV0IGQgPSBkYXRhVG9VcGRhdGVbaV1bdGhpcy5oZWFkaW5nc1tqXV0gIT0gdW5kZWZpbmVkID8gZGF0YVRvVXBkYXRlW2ldW3RoaXMuaGVhZGluZ3Nbal1dIDogXCItXCI7XG4gICAgICAgICAgZGF0YS5wdXNoKGQpO1xuICAgICAgICB9XG4gICAgICAgIFxuICAgICAgfVxuXG4gICAgICB0aGlzLnJlZm9ybWVkRGF0YS5wdXNoKGRhdGEpO1xuXG4gICAgfVxuXG4gICAgdGhpcy5yZWZvcm1lZEhlYWRzID0gdGhpcy5yZWZvcm1lZERhdGFbMF07XG4gICAgdGhpcy5zb3J0QnlFeGNlcHRpb24oKTtcbiAgfVxuXG4gIHNvcnRGbGlwKG5ld0tleTogYW55KSB7XG4gICAgdGhpcy5zb3J0RGlyZWN0aW9uID0gdGhpcy5zb3J0RGlyZWN0aW9uID09PSBcIlwiID8gXCJBU0NcIiA6IHRoaXMuc29ydERpcmVjdGlvbjtcbiAgICBpZiAodGhpcy5zb3J0QnkgIT0gXCJcIikge1xuICAgICAgaWYgKHRoaXMuc29ydEJ5ID09IG5ld0tleSkge1xuICAgICAgICBpZiAodGhpcy5zb3J0RGlyZWN0aW9uID09IFwiQVNDXCIpIHtcbiAgICAgICAgICB0aGlzLnNvcnREaXJlY3Rpb24gPSBcIkRFU0NcIjtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB0aGlzLnNvcnREaXJlY3Rpb24gPSBcIkFTQ1wiO1xuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aGlzLnNvcnREaXJlY3Rpb24gPSBcIkFTQ1wiO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHNvcnQoc29ydEtleTogYW55KSB7XG4gICAgY29uc29sZS5sb2coXCJrZXkgPT0+IFwiLCBzb3J0S2V5KTtcbiAgICB0aGlzLnNvcnRCeUV4Y2VwdGlvbigpO1xuICAgIGlmICh0aGlzLnNvcnRCeSAhPSBcIlwiKSB7XG4gICAgICB0aGlzLnNvcnRGbGlwKHNvcnRLZXkpO1xuICAgICAgdGhpcy5zb3J0QnkgPSBzb3J0S2V5O1xuICAgICAgbGV0IHNvcnRlciA9IHRoaXMuaGVhZGluZ3MuaW5kZXhPZih0aGlzLnNvcnRCeSk7XG4gICAgICB2YXIgJHRoaXMgPSB0aGlzO1xuICAgICAgbGV0IGNvbXBhcmUgPSAoYTogYW55LCBiOiBhbnkpID0+IHtcbiAgICAgICAgYVtzb3J0ZXJdID0gYVtzb3J0ZXJdLnRvU3RyaW5nKCk7XG4gICAgICAgIGJbc29ydGVyXSA9IGJbc29ydGVyXS50b1N0cmluZygpO1xuXG4gICAgICAgIGlmIChhW3NvcnRlcl0gPCBiW3NvcnRlcl0pIHtcbiAgICAgICAgICByZXR1cm4gJHRoaXMuc29ydERpcmVjdGlvbiA9PT0gXCJBU0NcIiA/IC0xIDogMTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoYVtzb3J0ZXJdID4gYltzb3J0ZXJdKSB7XG4gICAgICAgICAgcmV0dXJuICR0aGlzLnNvcnREaXJlY3Rpb24gPT09IFwiQVNDXCIgPyAxIDogLTE7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIDA7XG4gICAgICB9XG4gICAgICB0aGlzLnJlZm9ybWVkRGF0YSA9IHRoaXMucmVmb3JtZWREYXRhLnNvcnQoY29tcGFyZSk7XG4gICAgfVxuXG4gIH1cblxuICBzb3J0QnlFeGNlcHRpb24oKSB7XG4gICAgaWYgKHRoaXMuc29ydEJ5ID09IFwiXCIpIHtcbiAgICAgIHRoaXMuc29ydEJ5ID0gdGhpcy5oZWFkaW5nc1swXTtcbiAgICB9XG4gIH1cblxuXG4gIGZpbHRlcihmaWx0ZXJLZXk6IGFueSkge1xuICAgIHRoaXMucmVmb3JtZWREYXRhID0gdGhpcy5yZWZvcm1lZERhdGEuZmlsdGVyKGZ1bmN0aW9uIChlbDogYW55KSB7XG4gICAgICByZXR1cm4gZWwucHJpY2UgPD0gMTAwMCAmJlxuICAgICAgICBlbC5zcWZ0ID49IDUwMCAmJlxuICAgICAgICBlbC5udW1fb2ZfYmVkcyA+PSAyICYmXG4gICAgICAgIGVsLm51bV9vZl9iYXRocyA+PSAyLjU7XG4gICAgfSk7XG4gIH1cblxuICBvcGVuU29ydGVyKCkge1xuICAgIHRoaXMub3BlblNvcnRCb3ggPSAhdGhpcy5vcGVuU29ydEJveDtcbiAgICB0aGlzLm9wZW5GaWx0ZXJCb3ggPSBmYWxzZTtcbiAgfVxuXG4gIG9wZW5GaWx0ZXIoKSB7XG4gICAgdGhpcy5vcGVuRmlsdGVyQm94ID0gIXRoaXMub3BlbkZpbHRlckJveDtcbiAgICB0aGlzLm9wZW5Tb3J0Qm94ID0gZmFsc2U7XG4gIH1cblxuICBzZWFyY2goZW5hYmxlOiBib29sZWFuKSB7XG4gICAgY29uc29sZS5sb2coZW5hYmxlKTtcbiAgfVxuXG4gIHJlY2lldmVEYXRhKGV2ZW50OiBhbnksIGs6IG51bWJlcil7XG4gICAgaWYodGhpcy5kcmFnYWJsZVNvcnQpe1xuICAgICAgbGV0IGZyb21Db2x1bW4gPSB0aGlzLmNvbHVtbnNPcmRlcltldmVudC5vcmRlcl07XG4gICAgICB0aGlzLmNvbHVtbnNPcmRlcltldmVudC5vcmRlcl0gPSB0aGlzLmNvbHVtbnNPcmRlcltrXTtcbiAgICAgIHRoaXMuY29sdW1uc09yZGVyW2tdID0gZnJvbUNvbHVtbjtcbiAgICAgIGZyb21Db2x1bW4gPSB1bmRlZmluZWQ7XG4gICAgICB0aGlzLmV4dHJhY3RIZWFkaW5ncygpO1xuICAgICAgaWYodGhpcy5wYWdpbmF0ZS5zdGF0dXMpe1xuICAgICAgICB0aGlzLnJlZmFjdG9yRGF0YSh0aGlzLnBhZ2luYXRlZERhdGEpO1xuICAgICAgfWVsc2Uge1xuICAgICAgICB0aGlzLnJlZmFjdG9yRGF0YSgpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHVwZGF0ZVBhZ2luYXRlZERhdGEoZGF0YTphbnkpe1xuICAgIHRoaXMucGFnaW5hdGVkRGF0YSA9IGRhdGE7XG4gICAgaWYodGhpcy5wYWdpbmF0ZS5zdGF0dXMpIHRoaXMucmVmYWN0b3JEYXRhKHRoaXMucGFnaW5hdGVkRGF0YSk7XG4gIH1cblxufVxuIiwiPGRpdiBjbGFzcz1cInBhZC0xMFwiPlxuICA8ZGl2IGNsYXNzPVwicGFkLTVcIj5cbiAgICA8aDM+PHNwYW4gW2lubmVySHRtbF09XCJ0YWJsZVRpdGxlXCIgKm5nSWY9XCJzaG93T3B0aW9ucy50aXRsZVwiPlRhYmxlPC9zcGFuPiA8c21hbGwgY2xhc3M9XCJyaWdodFwiICpuZ0lmPVwic2hvd09wdGlvbnMuY291bnRcIj57e2NvdW50fX0gPGlcbiAgICAgICAgICBjbGFzcz1cImZhcyBmYS1saXN0LW9sIHBhZEwtNSBwb2ludGVyXCIgKGNsaWNrKT1cIm9wZW5Tb3J0ZXIoKVwiICpuZ0lmPVwic2hvd09wdGlvbnMuc29ydFwiPjwvaT4gPGlcbiAgICAgICAgICBjbGFzcz1cImZhcyBmYS1maWx0ZXIgcGFkTC01IGZvbnQtMTYgcG9pbnRlclwiIChjbGljayk9XCJvcGVuRmlsdGVyKClcIiAqbmdJZj1cInNob3dPcHRpb25zLmZpbHRlclwiPjwvaT48L3NtYWxsPjwvaDM+XG4gICAgPG1nLWNvbGxhcHNlIHdpZGdldElkPVwiMVwiIFtzaG93XT1cIm9wZW5GaWx0ZXJCb3hcIj5cbiAgICAgIDxkaXYgY2xhc3M9XCJwYWQtMTAgY29sbGFwc2UtZmlsdGVyLWJveFwiPlxuICAgICAgICA8aDQ+RmlsdGVyIDwvaDQ+XG4gICAgICAgIDxtZy1idXR0b24gKGNsaWNrZWQpPVwic2VhcmNoKCRldmVudClcIiB0aGVtZT1cInN1Y2Nlc3NcIiBidG5TaXplPVwic21cIj48aSBjbGFzcz1cImZhcyBmYS1zZWFyY2ggcGFkUi01XCI+PC9pPiBTZWFyY2hcbiAgICAgICAgPC9tZy1idXR0b24+XG4gICAgICAgIDxkaXYgY2xhc3M9XCJyb3dcIj5cbiAgICAgICAgICA8ZGl2IGNsYXNzPVwiY29sIG0zIGwzIHM2XCIgKm5nRm9yPVwibGV0IGZpbHRlciBvZiBmaWx0ZXJRdWVyeVwiPlxuICAgICAgICAgICAgPG1nLWlucHV0IFtjb250cm9sXT1cImZpbHRlci52YWxcIj48c3BhbiBbaW5uZXJIdG1sXT1cImZpbHRlci5uYW1lXCI+PC9zcGFuPjwvbWctaW5wdXQ+XG4gICAgICAgICAgPC9kaXY+XG4gICAgICAgIDwvZGl2PlxuICAgICAgPC9kaXY+XG4gICAgPC9tZy1jb2xsYXBzZT5cblxuICAgIDxtZy1jb2xsYXBzZSB3aWRnZXRJZD1cIjJcIiBbc2hvd109XCJvcGVuU29ydEJveFwiPlxuICAgICAgPGRpdiBjbGFzcz1cInBhZC0xMCBjb2xsYXBzZS1zb3J0ZXItYm94XCI+XG4gICAgICAgIDxoNCBzdHlsZT1cIm1hcmdpbi1ib3R0b206IDVweDtcIj5Tb3J0PC9oND5cbiAgICAgICAgPG1nLXNlbGVjdCBbb3B0aW9uc109XCJzb3J0T3B0aW9uc1wiICh2YWx1ZSk9XCJzb3J0KCRldmVudClcIj48L21nLXNlbGVjdD5cbiAgICAgIDwvZGl2PlxuICAgIDwvbWctY29sbGFwc2U+XG4gIDwvZGl2PlxuICA8ZGl2IGNsYXNzPVwicGFkVi01XCIgKm5nSWY9XCJwYWdpbmF0ZS5zdGF0dXMgJiYgcGFnaW5nUG9zaXRpb24udG9wXCI+XG4gICAgPG1nLXBhZ2luYXRpb24gKHBhZ2UpPVwic2V0Q3VycmVudFBhZ2UoJGV2ZW50KVwiIFtjdXJyZW50UGFnZV09XCJjdXJyZW50UGFnZVwiIFt0aGVtZV09XCJ0aGVtZVwiIFtmdWxsRGF0YU1vZGVdPVwidHJ1ZVwiIFtkYXRhXT1cIm1nRGF0YVwiIFtwZXJQYWdlXT1cInBhZ2luYXRlLnBlclBhZ2VcIiAoZ2V0ZGF0YSk9XCJ1cGRhdGVQYWdpbmF0ZWREYXRhKCRldmVudClcIj48L21nLXBhZ2luYXRpb24+XG4gIDwvZGl2PlxuICA8dGFibGUgY2xhc3M9XCJ7e3RoZW1lfX1cIj5cbiAgICA8dGhlYWQgW25nQ2xhc3NdPVwiZml4ZWRIZWFkZXIgPyAnZml4ZWQtaGVhZGVyJyA6ICcnXCI+XG4gICAgICA8bmctY29udGFpbmVyPlxuICAgICAgICBcbiAgICAgICAgPHRoICpuZ0Zvcj1cImxldCBoZWFkIG9mIGhlYWRpbmdzOyBsZXQgayA9IGluZGV4XCI+PHNwYW4gKGNsaWNrKT1cInNvcnQoaGVhZClcIj5cbiAgICAgICAgICA8bWctZHJvcGFibGUgKGRhdGFSZWNpZXZlZCk9XCJyZWNpZXZlRGF0YSgkZXZlbnQsIGspXCI+XG4gICAgICAgICAgICA8bWctZHJhZ2FibGUgW2RhdGFdPVwie29yZGVyOiBrfVwiIFtkcmFnYWJsZV09XCJkcmFnYWJsZVNvcnRcIj5cbiAgICAgICAgICAgICAge3toZWFkfX1cbiAgICAgICAgICAgIDwvbWctZHJhZ2FibGU+XG4gICAgICAgICAgPC9tZy1kcm9wYWJsZT5cbiAgICAgICAgICA8L3NwYW4+PC90aD5cbiAgICAgICAgICA8bmctY29udGFpbmVyICpuZ0lmPVwiYnV0dG9ucyAmJiBidXR0b25zLmxlbmd0aCA+IDBcIj5cbiAgICAgICAgICAgIDx0aCAqbmdGb3I9XCJsZXQgYnRuIG9mIGJ1dHRvbnNcIj5cbiAgICAgICAgICAgICAgPHNwYW4gKm5nSWYgPSBcImJ0biAmJiBidG4udGl0bGVcIiBbaW5uZXJIdG1sXT1cImJ0bi50aXRsZVwiPjwvc3Bhbj5cbiAgICAgICAgICAgIDwvdGg+XG4gICAgICAgICAgPC9uZy1jb250YWluZXI+XG4gICAgICA8L25nLWNvbnRhaW5lcj5cbiAgICAgIFxuICAgIDwvdGhlYWQ+XG4gICAgPHRib2R5PlxuICAgICAgPG5nLWNvbnRhaW5lcj5cbiAgICAgICAgPHRyICpuZ0Zvcj1cImxldCBkYXRhIG9mIHJlZm9ybWVkRGF0YTsgbGV0IGluZD1pbmRleDtcIj5cbiAgICAgICAgICA8dGQgKm5nRm9yPVwibGV0IGNvbCBvZiBkYXRhXCIgW2lubmVySHRtbF09XCJjb2xcIj48L3RkPlxuICAgICAgICAgIDxuZy1jb250YWluZXIgKm5nSWY9XCJidXR0b25zICYmIGJ1dHRvbnMubGVuZ3RoID4gMFwiPlxuICAgICAgICAgICAgPHRkICpuZ0Zvcj1cImxldCBidG4gb2YgYnV0dG9uc1wiPlxuICAgICAgICAgICAgICA8bmctY29udGFpbmVyICpuZ0lmPVwiYnRuLmRhdGEgJiYgYnRuLmRhdGEubGVuZ3RoID4gMFwiPlxuICAgICAgICAgICAgICAgIDxuZy1jb250YWluZXIgKm5nRm9yPVwibGV0IGQgb2YgYnRuLmRhdGFcIj5cbiAgICAgICAgICAgICAgICAgIDxzcGFuIChjbGljayk9XCJidXR0b25Jc0NsaWNrZWQoZC5pZCwgaW5kKVwiIFtpbm5lckh0bWxdPVwiZC50ZXh0XCIgc3R5bGU9XCJjdXJzb3I6IHBvaW50ZXI7IHBhZGRpbmctbGVmdDogNXB4OyBwYWRkaW5nLXJpZ2h0OiA1cHg7XCI+PC9zcGFuPlxuICAgICAgICAgICAgICAgIDwvbmctY29udGFpbmVyPlxuICAgICAgICAgICAgICA8L25nLWNvbnRhaW5lcj5cbiAgICAgICAgICAgIDwvdGQ+XG4gICAgICAgICAgPC9uZy1jb250YWluZXI+XG4gICAgICAgICAgXG4gICAgICAgIDwvdHI+XG4gICAgICA8L25nLWNvbnRhaW5lcj5cbiAgICAgIFxuICAgIDwvdGJvZHk+XG4gIDwvdGFibGU+XG4gIDxkaXYgY2xhc3M9XCJwYWRWLTVcIiAqbmdJZj1cInBhZ2luYXRlLnN0YXR1cyAmJiBwYWdpbmdQb3NpdGlvbi5ib3R0b21cIj5cbiAgICA8bWctcGFnaW5hdGlvbiAocGFnZSk9XCJzZXRDdXJyZW50UGFnZSgkZXZlbnQpXCIgW2N1cnJlbnRQYWdlXT1cImN1cnJlbnRQYWdlXCIgW3RoZW1lXT1cInRoZW1lXCIgW2Z1bGxEYXRhTW9kZV09XCJ0cnVlXCIgW2RhdGFdPVwibWdEYXRhXCIgW3BlclBhZ2VdPVwicGFnaW5hdGUucGVyUGFnZVwiIChnZXRkYXRhKT1cInVwZGF0ZVBhZ2luYXRlZERhdGEoJGV2ZW50KVwiPjwvbWctcGFnaW5hdGlvbj5cbiAgPC9kaXY+XG48L2Rpdj5cbiJdfQ==