UNPKG

@c8y/ngx-components

Version:

Angular modules for Cumulocity IoT applications

74 lines 34.9 kB
import { __decorate, __metadata } from "tslib"; import { Component, Output, EventEmitter, Input } from '@angular/core'; import { Observable, BehaviorSubject } from 'rxjs'; import { debounceTime, distinctUntilChanged, tap, switchMap, shareReplay } from 'rxjs/operators'; import { memoize } from '@c8y/ngx-components'; import { RepositoryService, RepositoryType } from '@c8y/ngx-components/repository/shared'; import { gettext } from '@c8y/ngx-components'; import { TranslateService } from '@ngx-translate/core'; import { property, get } from 'lodash-es'; import { BulkOperationsService } from '@c8y/ngx-components/operations/bulk-operations-service'; import * as i0 from "@angular/core"; import * as i1 from "@c8y/ngx-components/repository/shared"; import * as i2 from "@c8y/ngx-components/operations/bulk-operations-service"; import * as i3 from "@ngx-translate/core"; import * as i4 from "@c8y/ngx-components"; import * as i5 from "@angular/common"; import * as i6 from "@angular/forms"; import * as i7 from "@c8y/ngx-components/operations/stepper-frames"; export class SelectFirmwareComponent { constructor(repositoryService, bulkOpsService, translate) { this.repositoryService = repositoryService; this.bulkOpsService = bulkOpsService; this.translate = translate; this.firmware = new EventEmitter(); this.elementCount = 0; this.DD_LOW_COUNT = 10; this.textFilter$ = new BehaviorSubject(''); this.firmwares$ = this.textFilter$ .pipe(debounceTime(400), distinctUntilChanged()) .pipe(switchMap(text => this.getFirmwares(text)), tap(resp => { this.elementCount = resp.data ? resp.data.length : 0; }), shareReplay(1)); this.isLegacy = this.repositoryService.isLegacyEntry.bind(this.repositoryService); this.DEVICE_TYPE_NOT_AVAILABLE = gettext('No device type available.'); this.DESCRIPTION_NOT_AVAILABLE = gettext('No description available.'); } ngOnInit() { this.DD_LOW_COUNT = this.bulkOpsService.DD_LOW_COUNT; } selectFirmware(selected, fw) { if (selected) { this.firmware.emit(fw); } } getBaseVersionsCount$(firmware) { return this.firmwares$.pipe(switchMap(() => this.repositoryService.getBaseVersionsCount$(firmware)), shareReplay(1)); } getDescriptionTitle(firmware) { return get(firmware, 'description', this.translate.instant(this.DESCRIPTION_NOT_AVAILABLE)); } getDeviceTypeTitle(firmware) { return get(firmware, 'c8y_Filter.type', this.translate.instant(this.DEVICE_TYPE_NOT_AVAILABLE)); } getFirmwares(partialName) { return this.repositoryService.listRepositoryEntries(RepositoryType.FIRMWARE, { partialName }); } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: SelectFirmwareComponent, deps: [{ token: i1.RepositoryService }, { token: i2.BulkOperationsService }, { token: i3.TranslateService }], target: i0.ɵɵFactoryTarget.Component }); } static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: SelectFirmwareComponent, selector: "c8y-select-firmware-step", inputs: { selected: "selected" }, outputs: { firmware: "firmware" }, ngImport: i0, template: "<c8y-select-step-frame\n [header]=\"'Select firmware' | translate\"\n [noResults]=\"(textFilter$ | async).length > 0 && elementCount === 0\"\n>\n <label\n class=\"sr-only\"\n for=\"fFilter\"\n >\n {{ 'Filter\u2026' | translate }}\n </label>\n <div\n class=\"input-group input-group-search\"\n filters\n >\n <input\n class=\"form-control\"\n title=\"{{ 'Filter\u2026' | translate }}\"\n id=\"fFilter\"\n placeholder=\"{{ 'Filter\u2026' | translate }}\"\n type=\"search\"\n [ngModel]=\"textFilter$ | async\"\n (ngModelChange)=\"textFilter$.next($event)\"\n />\n <span class=\"input-group-addon\">\n <i\n c8yIcon=\"search\"\n *ngIf=\"(textFilter$ | async).length === 0\"\n ></i>\n <i\n class=\"text-muted\"\n c8yIcon=\"times\"\n *ngIf=\"(textFilter$ | async).length > 0\"\n (click)=\"textFilter$.next('')\"\n ></i>\n </span>\n </div>\n <c8y-li\n class=\"hidden-sm hidden-xs m-r-8 m-l-8\"\n header\n >\n <c8y-li-icon><i class=\"p-l-32 p-r-40\"></i></c8y-li-icon>\n <c8y-li-body class=\"content-flex-40\">\n <div class=\"col-3\">\n <span\n class=\"text-truncate\"\n title=\" {{ 'Name' | translate }} \"\n >\n {{ 'Name' | translate }}\n </span>\n </div>\n <div class=\"col-4\">\n <span\n class=\"text-truncate\"\n title=\"{{ 'Description' | translate }}\"\n >\n {{ 'Description' | translate }}\n </span>\n </div>\n <div class=\"col-3\">\n <span\n class=\"text-truncate\"\n title=\"{{ 'Device type' | translate }}\"\n >\n {{ 'Device type' | translate }}\n </span>\n </div>\n <div class=\"col-2\">\n <span\n class=\"text-truncate\"\n title=\"{{ 'Versions' | translate }}\"\n >\n {{ 'Versions' | translate }}\n </span>\n </div>\n </c8y-li-body>\n </c8y-li>\n <c8y-list-group list>\n <c8y-li *c8yFor=\"let firmware of firmwares$ | async; let i = index; loadMore: 'auto'\">\n <c8y-li-radio\n (onSelect)=\"selectFirmware($event, firmware)\"\n [selected]=\"firmware === selected\"\n ></c8y-li-radio>\n <c8y-li-icon>\n <i c8yIcon=\"c8y-firmware\"></i>\n </c8y-li-icon>\n\n <c8y-li-body class=\"content-flex-40\">\n <div class=\"col-3 m-b-xs-8\">\n <div\n class=\"text-truncate\"\n title=\"{{ firmware.name }}\"\n >\n <c8y-highlight\n [text]=\"firmware.name\"\n [pattern]=\"textFilter$ | async\"\n ></c8y-highlight>\n </div>\n </div>\n <div class=\"col-4 m-b-xs-8\">\n <div\n class=\"text-truncate\"\n title=\"{{ getDescriptionTitle(firmware) }}\"\n >\n <span\n class=\"text-label-small m-r-8 visible-xs visible-sm\"\n translate\n >\n Description\n </span>\n <small *ngIf=\"firmware.description; else noDesc\">\n {{ firmware.description }}\n </small>\n <ng-template #noDesc>\n <small>\n <em\n class=\"text-muted\"\n translate\n >\n No description available.\n </em>\n </small>\n </ng-template>\n </div>\n </div>\n <div class=\"col-3 m-b-xs-8\">\n <div\n class=\"text-truncate\"\n title=\"{{ 'Device type' | translate }}: {{ getDeviceTypeTitle(firmware) }}\"\n >\n <span\n class=\"text-label-small m-r-8 visible-xs visible-sm\"\n translate\n >\n Device type\n </span>\n <span *ngIf=\"firmware.c8y_Filter?.type; else noType\">\n {{ firmware.c8y_Filter?.type }}\n </span>\n <ng-template #noType>\n <em\n class=\"text-muted\"\n translate\n >\n Undefined`device type`\n </em>\n </ng-template>\n </div>\n </div>\n <div class=\"col-2\">\n <span\n class=\"label label-warning m-l-auto-sm\"\n *ngIf=\"isLegacy(firmware)\"\n >\n <span translate>Legacy</span>\n </span>\n\n <span *ngIf=\"!isLegacy(firmware)\">\n <span *ngIf=\"(getBaseVersionsCount$(firmware) | async) === null\">\n <span class=\"label label-info\">\n <i\n class=\"icon-spin\"\n c8yIcon=\"circle-o-notch\"\n ></i>\n </span>\n </span>\n <span *ngIf=\"(getBaseVersionsCount$(firmware) | async) !== null\">\n <span [ngPlural]=\"getBaseVersionsCount$(firmware) | async\">\n <ng-template ngPluralCase=\"=0\">\n <span class=\"label label-default\">\n <span translate>No versions</span>\n </span>\n </ng-template>\n <ng-template ngPluralCase=\"=1\">\n <span\n class=\"text-label-small m-r-8 visible-xs visible-sm\"\n translate\n >\n version\n </span>\n <span class=\"badge badge-info m-l-auto-sm\">1</span>\n </ng-template>\n <ng-template ngPluralCase=\"other\">\n <span\n class=\"text-label-small m-r-8 visible-xs visible-sm\"\n translate\n >\n versions\n </span>\n <span class=\"badge badge-info m-l-auto-sm\">\n {{ getBaseVersionsCount$(firmware) | async }}\n </span>\n </ng-template>\n </span>\n </span>\n </span>\n </div>\n </c8y-li-body>\n </c8y-li>\n </c8y-list-group>\n</c8y-select-step-frame>\n", dependencies: [{ kind: "directive", type: i4.IconDirective, selector: "[c8yIcon]", inputs: ["c8yIcon"] }, { kind: "directive", type: i4.C8yTranslateDirective, selector: "[translate],[ngx-translate]" }, { kind: "directive", type: i5.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i5.NgPlural, selector: "[ngPlural]", inputs: ["ngPlural"] }, { kind: "directive", type: i5.NgPluralCase, selector: "[ngPluralCase]" }, { kind: "directive", type: i4.ForOfDirective, selector: "[c8yFor]", inputs: ["c8yForOf", "c8yForLoadMore", "c8yForPipe", "c8yForNotFound", "c8yForMaxIterations", "c8yForLoadingTemplate", "c8yForLoadNextLabel", "c8yForLoadingLabel", "c8yForRealtime", "c8yForRealtimeOptions", "c8yForComparator", "c8yForEnableVirtualScroll", "c8yForVirtualScrollElementSize", "c8yForVirtualScrollStrategy", "c8yForVirtualScrollContainerHeight"], outputs: ["c8yForCount", "c8yForChange", "c8yForLoadMoreComponent"] }, { kind: "component", type: i4.HighlightComponent, selector: "c8y-highlight", inputs: ["pattern", "text", "elementClass", "shouldTrimPattern"] }, { kind: "directive", type: i6.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: i6.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i6.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: i4.ListGroupComponent, selector: "c8y-list-group" }, { kind: "component", type: i4.ListItemComponent, selector: "c8y-list-item, c8y-li", inputs: ["active", "highlighted", "emptyActions", "dense", "collapsed", "selectable"], outputs: ["collapsedChange"] }, { kind: "component", type: i4.ListItemIconComponent, selector: "c8y-list-item-icon, c8y-li-icon", inputs: ["icon", "status"] }, { kind: "component", type: i4.ListItemBodyComponent, selector: "c8y-list-item-body, c8y-li-body", inputs: ["body"] }, { kind: "component", type: i4.ListItemRadioComponent, selector: "c8y-list-item-radio, c8y-li-radio", inputs: ["selected", "name", "disabled", "value"], outputs: ["onSelect"] }, { kind: "component", type: i7.SelectStepFrameComponent, selector: "c8y-select-step-frame", inputs: ["header", "noResults"] }, { kind: "pipe", type: i4.C8yTranslatePipe, name: "translate" }, { kind: "pipe", type: i5.AsyncPipe, name: "async" }] }); } } __decorate([ memoize(property('id')), __metadata("design:type", Function), __metadata("design:paramtypes", [Object]), __metadata("design:returntype", Observable) ], SelectFirmwareComponent.prototype, "getBaseVersionsCount$", null); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: SelectFirmwareComponent, decorators: [{ type: Component, args: [{ selector: 'c8y-select-firmware-step', template: "<c8y-select-step-frame\n [header]=\"'Select firmware' | translate\"\n [noResults]=\"(textFilter$ | async).length > 0 && elementCount === 0\"\n>\n <label\n class=\"sr-only\"\n for=\"fFilter\"\n >\n {{ 'Filter\u2026' | translate }}\n </label>\n <div\n class=\"input-group input-group-search\"\n filters\n >\n <input\n class=\"form-control\"\n title=\"{{ 'Filter\u2026' | translate }}\"\n id=\"fFilter\"\n placeholder=\"{{ 'Filter\u2026' | translate }}\"\n type=\"search\"\n [ngModel]=\"textFilter$ | async\"\n (ngModelChange)=\"textFilter$.next($event)\"\n />\n <span class=\"input-group-addon\">\n <i\n c8yIcon=\"search\"\n *ngIf=\"(textFilter$ | async).length === 0\"\n ></i>\n <i\n class=\"text-muted\"\n c8yIcon=\"times\"\n *ngIf=\"(textFilter$ | async).length > 0\"\n (click)=\"textFilter$.next('')\"\n ></i>\n </span>\n </div>\n <c8y-li\n class=\"hidden-sm hidden-xs m-r-8 m-l-8\"\n header\n >\n <c8y-li-icon><i class=\"p-l-32 p-r-40\"></i></c8y-li-icon>\n <c8y-li-body class=\"content-flex-40\">\n <div class=\"col-3\">\n <span\n class=\"text-truncate\"\n title=\" {{ 'Name' | translate }} \"\n >\n {{ 'Name' | translate }}\n </span>\n </div>\n <div class=\"col-4\">\n <span\n class=\"text-truncate\"\n title=\"{{ 'Description' | translate }}\"\n >\n {{ 'Description' | translate }}\n </span>\n </div>\n <div class=\"col-3\">\n <span\n class=\"text-truncate\"\n title=\"{{ 'Device type' | translate }}\"\n >\n {{ 'Device type' | translate }}\n </span>\n </div>\n <div class=\"col-2\">\n <span\n class=\"text-truncate\"\n title=\"{{ 'Versions' | translate }}\"\n >\n {{ 'Versions' | translate }}\n </span>\n </div>\n </c8y-li-body>\n </c8y-li>\n <c8y-list-group list>\n <c8y-li *c8yFor=\"let firmware of firmwares$ | async; let i = index; loadMore: 'auto'\">\n <c8y-li-radio\n (onSelect)=\"selectFirmware($event, firmware)\"\n [selected]=\"firmware === selected\"\n ></c8y-li-radio>\n <c8y-li-icon>\n <i c8yIcon=\"c8y-firmware\"></i>\n </c8y-li-icon>\n\n <c8y-li-body class=\"content-flex-40\">\n <div class=\"col-3 m-b-xs-8\">\n <div\n class=\"text-truncate\"\n title=\"{{ firmware.name }}\"\n >\n <c8y-highlight\n [text]=\"firmware.name\"\n [pattern]=\"textFilter$ | async\"\n ></c8y-highlight>\n </div>\n </div>\n <div class=\"col-4 m-b-xs-8\">\n <div\n class=\"text-truncate\"\n title=\"{{ getDescriptionTitle(firmware) }}\"\n >\n <span\n class=\"text-label-small m-r-8 visible-xs visible-sm\"\n translate\n >\n Description\n </span>\n <small *ngIf=\"firmware.description; else noDesc\">\n {{ firmware.description }}\n </small>\n <ng-template #noDesc>\n <small>\n <em\n class=\"text-muted\"\n translate\n >\n No description available.\n </em>\n </small>\n </ng-template>\n </div>\n </div>\n <div class=\"col-3 m-b-xs-8\">\n <div\n class=\"text-truncate\"\n title=\"{{ 'Device type' | translate }}: {{ getDeviceTypeTitle(firmware) }}\"\n >\n <span\n class=\"text-label-small m-r-8 visible-xs visible-sm\"\n translate\n >\n Device type\n </span>\n <span *ngIf=\"firmware.c8y_Filter?.type; else noType\">\n {{ firmware.c8y_Filter?.type }}\n </span>\n <ng-template #noType>\n <em\n class=\"text-muted\"\n translate\n >\n Undefined`device type`\n </em>\n </ng-template>\n </div>\n </div>\n <div class=\"col-2\">\n <span\n class=\"label label-warning m-l-auto-sm\"\n *ngIf=\"isLegacy(firmware)\"\n >\n <span translate>Legacy</span>\n </span>\n\n <span *ngIf=\"!isLegacy(firmware)\">\n <span *ngIf=\"(getBaseVersionsCount$(firmware) | async) === null\">\n <span class=\"label label-info\">\n <i\n class=\"icon-spin\"\n c8yIcon=\"circle-o-notch\"\n ></i>\n </span>\n </span>\n <span *ngIf=\"(getBaseVersionsCount$(firmware) | async) !== null\">\n <span [ngPlural]=\"getBaseVersionsCount$(firmware) | async\">\n <ng-template ngPluralCase=\"=0\">\n <span class=\"label label-default\">\n <span translate>No versions</span>\n </span>\n </ng-template>\n <ng-template ngPluralCase=\"=1\">\n <span\n class=\"text-label-small m-r-8 visible-xs visible-sm\"\n translate\n >\n version\n </span>\n <span class=\"badge badge-info m-l-auto-sm\">1</span>\n </ng-template>\n <ng-template ngPluralCase=\"other\">\n <span\n class=\"text-label-small m-r-8 visible-xs visible-sm\"\n translate\n >\n versions\n </span>\n <span class=\"badge badge-info m-l-auto-sm\">\n {{ getBaseVersionsCount$(firmware) | async }}\n </span>\n </ng-template>\n </span>\n </span>\n </span>\n </div>\n </c8y-li-body>\n </c8y-li>\n </c8y-list-group>\n</c8y-select-step-frame>\n" }] }], ctorParameters: () => [{ type: i1.RepositoryService }, { type: i2.BulkOperationsService }, { type: i3.TranslateService }], propDecorators: { selected: [{ type: Input }], firmware: [{ type: Output }], getBaseVersionsCount$: [] } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VsZWN0LWZpcm13YXJlLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL29wZXJhdGlvbnMvc3RlcHBlci1idWxrLXR5cGUtZmlybXdhcmUvc2VsZWN0LWZpcm13YXJlLmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uL29wZXJhdGlvbnMvc3RlcHBlci1idWxrLXR5cGUtZmlybXdhcmUvc2VsZWN0LWZpcm13YXJlLmNvbXBvbmVudC5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQSxPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0sRUFBRSxZQUFZLEVBQUUsS0FBSyxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQ3ZFLE9BQU8sRUFBRSxVQUFVLEVBQUUsZUFBZSxFQUFFLE1BQU0sTUFBTSxDQUFDO0FBQ25ELE9BQU8sRUFBRSxZQUFZLEVBQUUsb0JBQW9CLEVBQUUsR0FBRyxFQUFFLFNBQVMsRUFBRSxXQUFXLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUNqRyxPQUFPLEVBQUUsT0FBTyxFQUFFLE1BQU0scUJBQXFCLENBQUM7QUFDOUMsT0FBTyxFQUFFLGlCQUFpQixFQUFFLGNBQWMsRUFBRSxNQUFNLHVDQUF1QyxDQUFDO0FBQzFGLE9BQU8sRUFBRSxPQUFPLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQztBQUU5QyxPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQztBQUN2RCxPQUFPLEVBQUUsUUFBUSxFQUFFLEdBQUcsRUFBRSxNQUFNLFdBQVcsQ0FBQztBQUMxQyxPQUFPLEVBQUUscUJBQXFCLEVBQUUsTUFBTSx3REFBd0QsQ0FBQzs7Ozs7Ozs7O0FBTS9GLE1BQU0sT0FBTyx1QkFBdUI7SUFvQmxDLFlBQ1UsaUJBQW9DLEVBQ3BDLGNBQXFDLEVBQ3JDLFNBQTJCO1FBRjNCLHNCQUFpQixHQUFqQixpQkFBaUIsQ0FBbUI7UUFDcEMsbUJBQWMsR0FBZCxjQUFjLENBQXVCO1FBQ3JDLGNBQVMsR0FBVCxTQUFTLENBQWtCO1FBckIzQixhQUFRLEdBQWlDLElBQUksWUFBWSxFQUFrQixDQUFDO1FBQ3RGLGlCQUFZLEdBQUcsQ0FBQyxDQUFDO1FBQ2pCLGlCQUFZLEdBQUcsRUFBRSxDQUFDO1FBQ2xCLGdCQUFXLEdBQTRCLElBQUksZUFBZSxDQUFDLEVBQUUsQ0FBQyxDQUFDO1FBRS9ELGVBQVUsR0FBNEMsSUFBSSxDQUFDLFdBQVc7YUFDbkUsSUFBSSxDQUFDLFlBQVksQ0FBQyxHQUFHLENBQUMsRUFBRSxvQkFBb0IsRUFBRSxDQUFDO2FBQy9DLElBQUksQ0FDSCxTQUFTLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDLElBQUksQ0FBQyxDQUFDLEVBQzFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsRUFBRTtZQUNULElBQUksQ0FBQyxZQUFZLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUN2RCxDQUFDLENBQUMsRUFDRixXQUFXLENBQUMsQ0FBQyxDQUFDLENBQ2YsQ0FBQztRQUNKLGFBQVEsR0FBRyxJQUFJLENBQUMsaUJBQWlCLENBQUMsYUFBYSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsaUJBQWlCLENBQUMsQ0FBQztRQUNwRSw4QkFBeUIsR0FBVyxPQUFPLENBQUMsMkJBQTJCLENBQUMsQ0FBQztRQUN6RSw4QkFBeUIsR0FBVyxPQUFPLENBQUMsMkJBQTJCLENBQUMsQ0FBQztJQU0vRSxDQUFDO0lBRUosUUFBUTtRQUNOLElBQUksQ0FBQyxZQUFZLEdBQUcsSUFBSSxDQUFDLGNBQWMsQ0FBQyxZQUFZLENBQUM7SUFDdkQsQ0FBQztJQUVELGNBQWMsQ0FBQyxRQUFpQixFQUFFLEVBQWtCO1FBQ2xELElBQUksUUFBUSxFQUFFLENBQUM7WUFDYixJQUFJLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQztRQUN6QixDQUFDO0lBQ0gsQ0FBQztJQUdELHFCQUFxQixDQUFDLFFBQXdCO1FBQzVDLE9BQU8sSUFBSSxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQ3pCLFNBQVMsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxJQUFJLENBQUMsaUJBQWlCLENBQUMscUJBQXFCLENBQUMsUUFBUSxDQUFDLENBQUMsRUFDdkUsV0FBVyxDQUFDLENBQUMsQ0FBQyxDQUNmLENBQUM7SUFDSixDQUFDO0lBRUQsbUJBQW1CLENBQUMsUUFBd0I7UUFDMUMsT0FBTyxHQUFHLENBQUMsUUFBUSxFQUFFLGFBQWEsRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMseUJBQXlCLENBQUMsQ0FBQyxDQUFDO0lBQzlGLENBQUM7SUFFRCxrQkFBa0IsQ0FBQyxRQUF3QjtRQUN6QyxPQUFPLEdBQUcsQ0FBQyxRQUFRLEVBQUUsaUJBQWlCLEVBQUUsSUFBSSxDQUFDLFNBQVMsQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLHlCQUF5QixDQUFDLENBQUMsQ0FBQztJQUNsRyxDQUFDO0lBRU8sWUFBWSxDQUFDLFdBQW9CO1FBQ3ZDLE9BQU8sSUFBSSxDQUFDLGlCQUFpQixDQUFDLHFCQUFxQixDQUFDLGNBQWMsQ0FBQyxRQUFRLEVBQUUsRUFBRSxXQUFXLEVBQUUsQ0FBQyxDQUFDO0lBQ2hHLENBQUM7K0dBdERVLHVCQUF1QjttR0FBdkIsdUJBQXVCLHFJQ2ZwQyxzbk1Bd01BOztBRHBKRTtJQURDLE9BQU8sQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLENBQUM7OztvQ0FDeUIsVUFBVTtvRUFLMUQ7NEZBMUNVLHVCQUF1QjtrQkFKbkMsU0FBUzsrQkFDRSwwQkFBMEI7eUpBSTNCLFFBQVE7c0JBQWhCLEtBQUs7Z0JBQ0ksUUFBUTtzQkFBakIsTUFBTTtnQkFtQ1AscUJBQXFCIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQ29tcG9uZW50LCBPdXRwdXQsIEV2ZW50RW1pdHRlciwgSW5wdXQgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IE9ic2VydmFibGUsIEJlaGF2aW9yU3ViamVjdCB9IGZyb20gJ3J4anMnO1xuaW1wb3J0IHsgZGVib3VuY2VUaW1lLCBkaXN0aW5jdFVudGlsQ2hhbmdlZCwgdGFwLCBzd2l0Y2hNYXAsIHNoYXJlUmVwbGF5IH0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xuaW1wb3J0IHsgbWVtb2l6ZSB9IGZyb20gJ0BjOHkvbmd4LWNvbXBvbmVudHMnO1xuaW1wb3J0IHsgUmVwb3NpdG9yeVNlcnZpY2UsIFJlcG9zaXRvcnlUeXBlIH0gZnJvbSAnQGM4eS9uZ3gtY29tcG9uZW50cy9yZXBvc2l0b3J5L3NoYXJlZCc7XG5pbXBvcnQgeyBnZXR0ZXh0IH0gZnJvbSAnQGM4eS9uZ3gtY29tcG9uZW50cyc7XG5pbXBvcnQgeyBJUmVzdWx0TGlzdCwgSU1hbmFnZWRPYmplY3QgfSBmcm9tICdAYzh5L2NsaWVudCc7XG5pbXBvcnQgeyBUcmFuc2xhdGVTZXJ2aWNlIH0gZnJvbSAnQG5neC10cmFuc2xhdGUvY29yZSc7XG5pbXBvcnQgeyBwcm9wZXJ0eSwgZ2V0IH0gZnJvbSAnbG9kYXNoLWVzJztcbmltcG9ydCB7IEJ1bGtPcGVyYXRpb25zU2VydmljZSB9IGZyb20gJ0BjOHkvbmd4LWNvbXBvbmVudHMvb3BlcmF0aW9ucy9idWxrLW9wZXJhdGlvbnMtc2VydmljZSc7XG5cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ2M4eS1zZWxlY3QtZmlybXdhcmUtc3RlcCcsXG4gIHRlbXBsYXRlVXJsOiAnc2VsZWN0LWZpcm13YXJlLmNvbXBvbmVudC5odG1sJ1xufSlcbmV4cG9ydCBjbGFzcyBTZWxlY3RGaXJtd2FyZUNvbXBvbmVudCB7XG4gIEBJbnB1dCgpIHNlbGVjdGVkOiBJTWFuYWdlZE9iamVjdDtcbiAgQE91dHB1dCgpIGZpcm13YXJlOiBFdmVudEVtaXR0ZXI8SU1hbmFnZWRPYmplY3Q+ID0gbmV3IEV2ZW50RW1pdHRlcjxJTWFuYWdlZE9iamVjdD4oKTtcbiAgZWxlbWVudENvdW50ID0gMDtcbiAgRERfTE9XX0NPVU5UID0gMTA7XG4gIHRleHRGaWx0ZXIkOiBCZWhhdmlvclN1YmplY3Q8c3RyaW5nPiA9IG5ldyBCZWhhdmlvclN1YmplY3QoJycpO1xuXG4gIGZpcm13YXJlcyQ6IE9ic2VydmFibGU8SVJlc3VsdExpc3Q8SU1hbmFnZWRPYmplY3Q+PiA9IHRoaXMudGV4dEZpbHRlciRcbiAgICAucGlwZShkZWJvdW5jZVRpbWUoNDAwKSwgZGlzdGluY3RVbnRpbENoYW5nZWQoKSlcbiAgICAucGlwZShcbiAgICAgIHN3aXRjaE1hcCh0ZXh0ID0+IHRoaXMuZ2V0RmlybXdhcmVzKHRleHQpKSxcbiAgICAgIHRhcChyZXNwID0+IHtcbiAgICAgICAgdGhpcy5lbGVtZW50Q291bnQgPSByZXNwLmRhdGEgPyByZXNwLmRhdGEubGVuZ3RoIDogMDtcbiAgICAgIH0pLFxuICAgICAgc2hhcmVSZXBsYXkoMSlcbiAgICApO1xuICBpc0xlZ2FjeSA9IHRoaXMucmVwb3NpdG9yeVNlcnZpY2UuaXNMZWdhY3lFbnRyeS5iaW5kKHRoaXMucmVwb3NpdG9yeVNlcnZpY2UpO1xuICByZWFkb25seSBERVZJQ0VfVFlQRV9OT1RfQVZBSUxBQkxFOiBzdHJpbmcgPSBnZXR0ZXh0KCdObyBkZXZpY2UgdHlwZSBhdmFpbGFibGUuJyk7XG4gIHJlYWRvbmx5IERFU0NSSVBUSU9OX05PVF9BVkFJTEFCTEU6IHN0cmluZyA9IGdldHRleHQoJ05vIGRlc2NyaXB0aW9uIGF2YWlsYWJsZS4nKTtcblxuICBjb25zdHJ1Y3RvcihcbiAgICBwcml2YXRlIHJlcG9zaXRvcnlTZXJ2aWNlOiBSZXBvc2l0b3J5U2VydmljZSxcbiAgICBwcml2YXRlIGJ1bGtPcHNTZXJ2aWNlOiBCdWxrT3BlcmF0aW9uc1NlcnZpY2UsXG4gICAgcHJpdmF0ZSB0cmFuc2xhdGU6IFRyYW5zbGF0ZVNlcnZpY2VcbiAgKSB7fVxuXG4gIG5nT25Jbml0KCkge1xuICAgIHRoaXMuRERfTE9XX0NPVU5UID0gdGhpcy5idWxrT3BzU2VydmljZS5ERF9MT1dfQ09VTlQ7XG4gIH1cblxuICBzZWxlY3RGaXJtd2FyZShzZWxlY3RlZDogYm9vbGVhbiwgZnc6IElNYW5hZ2VkT2JqZWN0KSB7XG4gICAgaWYgKHNlbGVjdGVkKSB7XG4gICAgICB0aGlzLmZpcm13YXJlLmVtaXQoZncpO1xuICAgIH1cbiAgfVxuXG4gIEBtZW1vaXplKHByb3BlcnR5KCdpZCcpKVxuICBnZXRCYXNlVmVyc2lvbnNDb3VudCQoZmlybXdhcmU6IElNYW5hZ2VkT2JqZWN0KTogT2JzZXJ2YWJsZTxudW1iZXIgfCBzdHJpbmc+IHtcbiAgICByZXR1cm4gdGhpcy5maXJtd2FyZXMkLnBpcGUoXG4gICAgICBzd2l0Y2hNYXAoKCkgPT4gdGhpcy5yZXBvc2l0b3J5U2VydmljZS5nZXRCYXNlVmVyc2lvbnNDb3VudCQoZmlybXdhcmUpKSxcbiAgICAgIHNoYXJlUmVwbGF5KDEpXG4gICAgKTtcbiAgfVxuXG4gIGdldERlc2NyaXB0aW9uVGl0bGUoZmlybXdhcmU6IElNYW5hZ2VkT2JqZWN0KTogc3RyaW5nIHtcbiAgICByZXR1cm4gZ2V0KGZpcm13YXJlLCAnZGVzY3JpcHRpb24nLCB0aGlzLnRyYW5zbGF0ZS5pbnN0YW50KHRoaXMuREVTQ1JJUFRJT05fTk9UX0FWQUlMQUJMRSkpO1xuICB9XG5cbiAgZ2V0RGV2aWNlVHlwZVRpdGxlKGZpcm13YXJlOiBJTWFuYWdlZE9iamVjdCk6IHN0cmluZyB7XG4gICAgcmV0dXJuIGdldChmaXJtd2FyZSwgJ2M4eV9GaWx0ZXIudHlwZScsIHRoaXMudHJhbnNsYXRlLmluc3RhbnQodGhpcy5ERVZJQ0VfVFlQRV9OT1RfQVZBSUxBQkxFKSk7XG4gIH1cblxuICBwcml2YXRlIGdldEZpcm13YXJlcyhwYXJ0aWFsTmFtZT86IHN0cmluZykge1xuICAgIHJldHVybiB0aGlzLnJlcG9zaXRvcnlTZXJ2aWNlLmxpc3RSZXBvc2l0b3J5RW50cmllcyhSZXBvc2l0b3J5VHlwZS5GSVJNV0FSRSwgeyBwYXJ0aWFsTmFtZSB9KTtcbiAgfVxufVxuIiwiPGM4eS1zZWxlY3Qtc3RlcC1mcmFtZVxuICBbaGVhZGVyXT1cIidTZWxlY3QgZmlybXdhcmUnIHwgdHJhbnNsYXRlXCJcbiAgW25vUmVzdWx0c109XCIodGV4dEZpbHRlciQgfCBhc3luYykubGVuZ3RoID4gMCAmJiBlbGVtZW50Q291bnQgPT09IDBcIlxuPlxuICA8bGFiZWxcbiAgICBjbGFzcz1cInNyLW9ubHlcIlxuICAgIGZvcj1cImZGaWx0ZXJcIlxuICA+XG4gICAge3sgJ0ZpbHRlcuKApicgfCB0cmFuc2xhdGUgfX1cbiAgPC9sYWJlbD5cbiAgPGRpdlxuICAgIGNsYXNzPVwiaW5wdXQtZ3JvdXAgaW5wdXQtZ3JvdXAtc2VhcmNoXCJcbiAgICBmaWx0ZXJzXG4gID5cbiAgICA8aW5wdXRcbiAgICAgIGNsYXNzPVwiZm9ybS1jb250cm9sXCJcbiAgICAgIHRpdGxlPVwie3sgJ0ZpbHRlcuKApicgfCB0cmFuc2xhdGUgfX1cIlxuICAgICAgaWQ9XCJmRmlsdGVyXCJcbiAgICAgIHBsYWNlaG9sZGVyPVwie3sgJ0ZpbHRlcuKApicgfCB0cmFuc2xhdGUgfX1cIlxuICAgICAgdHlwZT1cInNlYXJjaFwiXG4gICAgICBbbmdNb2RlbF09XCJ0ZXh0RmlsdGVyJCB8IGFzeW5jXCJcbiAgICAgIChuZ01vZGVsQ2hhbmdlKT1cInRleHRGaWx0ZXIkLm5leHQoJGV2ZW50KVwiXG4gICAgLz5cbiAgICA8c3BhbiBjbGFzcz1cImlucHV0LWdyb3VwLWFkZG9uXCI+XG4gICAgICA8aVxuICAgICAgICBjOHlJY29uPVwic2VhcmNoXCJcbiAgICAgICAgKm5nSWY9XCIodGV4dEZpbHRlciQgfCBhc3luYykubGVuZ3RoID09PSAwXCJcbiAgICAgID48L2k+XG4gICAgICA8aVxuICAgICAgICBjbGFzcz1cInRleHQtbXV0ZWRcIlxuICAgICAgICBjOHlJY29uPVwidGltZXNcIlxuICAgICAgICAqbmdJZj1cIih0ZXh0RmlsdGVyJCB8IGFzeW5jKS5sZW5ndGggPiAwXCJcbiAgICAgICAgKGNsaWNrKT1cInRleHRGaWx0ZXIkLm5leHQoJycpXCJcbiAgICAgID48L2k+XG4gICAgPC9zcGFuPlxuICA8L2Rpdj5cbiAgPGM4eS1saVxuICAgIGNsYXNzPVwiaGlkZGVuLXNtIGhpZGRlbi14cyBtLXItOCBtLWwtOFwiXG4gICAgaGVhZGVyXG4gID5cbiAgICA8Yzh5LWxpLWljb24+PGkgY2xhc3M9XCJwLWwtMzIgcC1yLTQwXCI+PC9pPjwvYzh5LWxpLWljb24+XG4gICAgPGM4eS1saS1ib2R5IGNsYXNzPVwiY29udGVudC1mbGV4LTQwXCI+XG4gICAgICA8ZGl2IGNsYXNzPVwiY29sLTNcIj5cbiAgICAgICAgPHNwYW5cbiAgICAgICAgICBjbGFzcz1cInRleHQtdHJ1bmNhdGVcIlxuICAgICAgICAgIHRpdGxlPVwiIHt7ICdOYW1lJyB8IHRyYW5zbGF0ZSB9fSBcIlxuICAgICAgICA+XG4gICAgICAgICAge3sgJ05hbWUnIHwgdHJhbnNsYXRlIH19XG4gICAgICAgIDwvc3Bhbj5cbiAgICAgIDwvZGl2PlxuICAgICAgPGRpdiBjbGFzcz1cImNvbC00XCI+XG4gICAgICAgIDxzcGFuXG4gICAgICAgICAgY2xhc3M9XCJ0ZXh0LXRydW5jYXRlXCJcbiAgICAgICAgICB0aXRsZT1cInt7ICdEZXNjcmlwdGlvbicgfCB0cmFuc2xhdGUgfX1cIlxuICAgICAgICA+XG4gICAgICAgICAge3sgJ0Rlc2NyaXB0aW9uJyB8IHRyYW5zbGF0ZSB9fVxuICAgICAgICA8L3NwYW4+XG4gICAgICA8L2Rpdj5cbiAgICAgIDxkaXYgY2xhc3M9XCJjb2wtM1wiPlxuICAgICAgICA8c3BhblxuICAgICAgICAgIGNsYXNzPVwidGV4dC10cnVuY2F0ZVwiXG4gICAgICAgICAgdGl0bGU9XCJ7eyAnRGV2aWNlIHR5cGUnIHwgdHJhbnNsYXRlIH19XCJcbiAgICAgICAgPlxuICAgICAgICAgIHt7ICdEZXZpY2UgdHlwZScgfCB0cmFuc2xhdGUgfX1cbiAgICAgICAgPC9zcGFuPlxuICAgICAgPC9kaXY+XG4gICAgICA8ZGl2IGNsYXNzPVwiY29sLTJcIj5cbiAgICAgICAgPHNwYW5cbiAgICAgICAgICBjbGFzcz1cInRleHQtdHJ1bmNhdGVcIlxuICAgICAgICAgIHRpdGxlPVwie3sgJ1ZlcnNpb25zJyB8IHRyYW5zbGF0ZSB9fVwiXG4gICAgICAgID5cbiAgICAgICAgICB7eyAnVmVyc2lvbnMnIHwgdHJhbnNsYXRlIH19XG4gICAgICAgIDwvc3Bhbj5cbiAgICAgIDwvZGl2PlxuICAgIDwvYzh5LWxpLWJvZHk+XG4gIDwvYzh5LWxpPlxuICA8Yzh5LWxpc3QtZ3JvdXAgbGlzdD5cbiAgICA8Yzh5LWxpICpjOHlGb3I9XCJsZXQgZmlybXdhcmUgb2YgZmlybXdhcmVzJCB8IGFzeW5jOyBsZXQgaSA9IGluZGV4OyBsb2FkTW9yZTogJ2F1dG8nXCI+XG4gICAgICA8Yzh5LWxpLXJhZGlvXG4gICAgICAgIChvblNlbGVjdCk9XCJzZWxlY3RGaXJtd2FyZSgkZXZlbnQsIGZpcm13YXJlKVwiXG4gICAgICAgIFtzZWxlY3RlZF09XCJmaXJtd2FyZSA9PT0gc2VsZWN0ZWRcIlxuICAgICAgPjwvYzh5LWxpLXJhZGlvPlxuICAgICAgPGM4eS1saS1pY29uPlxuICAgICAgICA8aSBjOHlJY29uPVwiYzh5LWZpcm13YXJlXCI+PC9pPlxuICAgICAgPC9jOHktbGktaWNvbj5cblxuICAgICAgPGM4eS1saS1ib2R5IGNsYXNzPVwiY29udGVudC1mbGV4LTQwXCI+XG4gICAgICAgIDxkaXYgY2xhc3M9XCJjb2wtMyBtLWIteHMtOFwiPlxuICAgICAgICAgIDxkaXZcbiAgICAgICAgICAgIGNsYXNzPVwidGV4dC10cnVuY2F0ZVwiXG4gICAgICAgICAgICB0aXRsZT1cInt7IGZpcm13YXJlLm5hbWUgfX1cIlxuICAgICAgICAgID5cbiAgICAgICAgICAgIDxjOHktaGlnaGxpZ2h0XG4gICAgICAgICAgICAgIFt0ZXh0XT1cImZpcm13YXJlLm5hbWVcIlxuICAgICAgICAgICAgICBbcGF0dGVybl09XCJ0ZXh0RmlsdGVyJCB8IGFzeW5jXCJcbiAgICAgICAgICAgID48L2M4eS1oaWdobGlnaHQ+XG4gICAgICAgICAgPC9kaXY+XG4gICAgICAgIDwvZGl2PlxuICAgICAgICA8ZGl2IGNsYXNzPVwiY29sLTQgbS1iLXhzLThcIj5cbiAgICAgICAgICA8ZGl2XG4gICAgICAgICAgICBjbGFzcz1cInRleHQtdHJ1bmNhdGVcIlxuICAgICAgICAgICAgdGl0bGU9XCJ7eyBnZXREZXNjcmlwdGlvblRpdGxlKGZpcm13YXJlKSB9fVwiXG4gICAgICAgICAgPlxuICAgICAgICAgICAgPHNwYW5cbiAgICAgICAgICAgICAgY2xhc3M9XCJ0ZXh0LWxhYmVsLXNtYWxsIG0tci04IHZpc2libGUteHMgdmlzaWJsZS1zbVwiXG4gICAgICAgICAgICAgIHRyYW5zbGF0ZVxuICAgICAgICAgICAgPlxuICAgICAgICAgICAgICBEZXNjcmlwdGlvblxuICAgICAgICAgICAgPC9zcGFuPlxuICAgICAgICAgICAgPHNtYWxsICpuZ0lmPVwiZmlybXdhcmUuZGVzY3JpcHRpb247IGVsc2Ugbm9EZXNjXCI+XG4gICAgICAgICAgICAgIHt7IGZpcm13YXJlLmRlc2NyaXB0aW9uIH19XG4gICAgICAgICAgICA8L3NtYWxsPlxuICAgICAgICAgICAgPG5nLXRlbXBsYXRlICNub0Rlc2M+XG4gICAgICAgICAgICAgIDxzbWFsbD5cbiAgICAgICAgICAgICAgICA8ZW1cbiAgICAgICAgICAgICAgICAgIGNsYXNzPVwidGV4dC1tdXRlZFwiXG4gICAgICAgICAgICAgICAgICB0cmFuc2xhdGVcbiAgICAgICAgICAgICAgICA+XG4gICAgICAgICAgICAgICAgICBObyBkZXNjcmlwdGlvbiBhdmFpbGFibGUuXG4gICAgICAgICAgICAgICAgPC9lbT5cbiAgICAgICAgICAgICAgPC9zbWFsbD5cbiAgICAgICAgICAgIDwvbmctdGVtcGxhdGU+XG4gICAgICAgICAgPC9kaXY+XG4gICAgICAgIDwvZGl2PlxuICAgICAgICA8ZGl2IGNsYXNzPVwiY29sLTMgbS1iLXhzLThcIj5cbiAgICAgICAgICA8ZGl2XG4gICAgICAgICAgICBjbGFzcz1cInRleHQtdHJ1bmNhdGVcIlxuICAgICAgICAgICAgdGl0bGU9XCJ7eyAnRGV2aWNlIHR5cGUnIHwgdHJhbnNsYXRlIH19OiB7eyBnZXREZXZpY2VUeXBlVGl0bGUoZmlybXdhcmUpIH19XCJcbiAgICAgICAgICA+XG4gICAgICAgICAgICA8c3BhblxuICAgICAgICAgICAgICBjbGFzcz1cInRleHQtbGFiZWwtc21hbGwgbS1yLTggdmlzaWJsZS14cyB2aXNpYmxlLXNtXCJcbiAgICAgICAgICAgICAgdHJhbnNsYXRlXG4gICAgICAgICAgICA+XG4gICAgICAgICAgICAgIERldmljZSB0eXBlXG4gICAgICAgICAgICA8L3NwYW4+XG4gICAgICAgICAgICA8c3BhbiAqbmdJZj1cImZpcm13YXJlLmM4eV9GaWx0ZXI/LnR5cGU7IGVsc2Ugbm9UeXBlXCI+XG4gICAgICAgICAgICAgIHt7IGZpcm13YXJlLmM4eV9GaWx0ZXI/LnR5cGUgfX1cbiAgICAgICAgICAgIDwvc3Bhbj5cbiAgICAgICAgICAgIDxuZy10ZW1wbGF0ZSAjbm9UeXBlPlxuICAgICAgICAgICAgICA8ZW1cbiAgICAgICAgICAgICAgICBjbGFzcz1cInRleHQtbXV0ZWRcIlxuICAgICAgICAgICAgICAgIHRyYW5zbGF0ZVxuICAgICAgICAgICAgICA+XG4gICAgICAgICAgICAgICAgVW5kZWZpbmVkYGRldmljZSB0eXBlYFxuICAgICAgICAgICAgICA8L2VtPlxuICAgICAgICAgICAgPC9uZy10ZW1wbGF0ZT5cbiAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgPC9kaXY+XG4gICAgICAgIDxkaXYgY2xhc3M9XCJjb2wtMlwiPlxuICAgICAgICAgIDxzcGFuXG4gICAgICAgICAgICBjbGFzcz1cImxhYmVsIGxhYmVsLXdhcm5pbmcgbS1sLWF1dG8tc21cIlxuICAgICAgICAgICAgKm5nSWY9XCJpc0xlZ2FjeShmaXJtd2FyZSlcIlxuICAgICAgICAgID5cbiAgICAgICAgICAgIDxzcGFuIHRyYW5zbGF0ZT5MZWdhY3k8L3NwYW4+XG4gICAgICAgICAgPC9zcGFuPlxuXG4gICAgICAgICAgPHNwYW4gKm5nSWY9XCIhaXNMZWdhY3koZmlybXdhcmUpXCI+XG4gICAgICAgICAgICA8c3BhbiAqbmdJZj1cIihnZXRCYXNlVmVyc2lvbnNDb3VudCQoZmlybXdhcmUpIHwgYXN5bmMpID09PSBudWxsXCI+XG4gICAgICAgICAgICAgIDxzcGFuIGNsYXNzPVwibGFiZWwgbGFiZWwtaW5mb1wiPlxuICAgICAgICAgICAgICAgIDxpXG4gICAgICAgICAgICAgICAgICBjbGFzcz1cImljb24tc3BpblwiXG4gICAgICAgICAgICAgICAgICBjOHlJY29uPVwiY2lyY2xlLW8tbm90Y2hcIlxuICAgICAgICAgICAgICAgID48L2k+XG4gICAgICAgICAgICAgIDwvc3Bhbj5cbiAgICAgICAgICAgIDwvc3Bhbj5cbiAgICAgICAgICAgIDxzcGFuICpuZ0lmPVwiKGdldEJhc2VWZXJzaW9uc0NvdW50JChmaXJtd2FyZSkgfCBhc3luYykgIT09IG51bGxcIj5cbiAgICAgICAgICAgICAgPHNwYW4gW25nUGx1cmFsXT1cImdldEJhc2VWZXJzaW9uc0NvdW50JChmaXJtd2FyZSkgfCBhc3luY1wiPlxuICAgICAgICAgICAgICAgIDxuZy10ZW1wbGF0ZSBuZ1BsdXJhbENhc2U9XCI9MFwiPlxuICAgICAgICAgICAgICAgICAgPHNwYW4gY2xhc3M9XCJsYWJlbCBsYWJlbC1kZWZhdWx0XCI+XG4gICAgICAgICAgICAgICAgICAgIDxzcGFuIHRyYW5zbGF0ZT5ObyB2ZXJzaW9uczwvc3Bhbj5cbiAgICAgICAgICAgICAgICAgIDwvc3Bhbj5cbiAgICAgICAgICAgICAgICA8L25nLXRlbXBsYXRlPlxuICAgICAgICAgICAgICAgIDxuZy10ZW1wbGF0ZSBuZ1BsdXJhbENhc2U9XCI9MVwiPlxuICAgICAgICAgICAgICAgICAgPHNwYW5cbiAgICAgICAgICAgICAgICAgICAgY2xhc3M9XCJ0ZXh0LWxhYmVsLXNtYWxsIG0tci04IHZpc2libGUteHMgdmlzaWJsZS1zbVwiXG4gICAgICAgICAgICAgICAgICAgIHRyYW5zbGF0ZVxuICAgICAgICAgICAgICAgICAgPlxuICAgICAgICAgICAgICAgICAgICB2ZXJzaW9uXG4gICAgICAgICAgICAgICAgICA8L3NwYW4+XG4gICAgICAgICAgICAgICAgICA8c3BhbiBjbGFzcz1cImJhZGdlIGJhZGdlLWluZm8gbS1sLWF1dG8tc21cIj4xPC9zcGFuPlxuICAgICAgICAgICAgICAgIDwvbmctdGVtcGxhdGU+XG4gICAgICAgICAgICAgICAgPG5nLXRlbXBsYXRlIG5nUGx1cmFsQ2FzZT1cIm90aGVyXCI+XG4gICAgICAgICAgICAgICAgICA8c3BhblxuICAgICAgICAgICAgICAgICAgICBjbGFzcz1cInRleHQtbGFiZWwtc21hbGwgbS1yLTggdmlzaWJsZS14cyB2aXNpYmxlLXNtXCJcbiAgICAgICAgICAgICAgICAgICAgdHJhbnNsYXRlXG4gICAgICAgICAgICAgICAgICA+XG4gICAgICAgICAgICAgICAgICAgIHZlcnNpb25zXG4gICAgICAgICAgICAgICAgICA8L3NwYW4+XG4gICAgICAgICAgICAgICAgICA8c3BhbiBjbGFzcz1cImJhZGdlIGJhZGdlLWluZm8gbS1sLWF1dG8tc21cIj5cbiAgICAgICAgICAgICAgICAgICAge3sgZ2V0QmFzZVZlcnNpb25zQ291bnQkKGZpcm13YXJlKSB8IGFzeW5jIH19XG4gICAgICAgICAgICAgICAgICA8L3NwYW4+XG4gICAgICAgICAgICAgICAgPC9uZy10ZW1wbGF0ZT5cbiAgICAgICAgICAgICAgPC9zcGFuPlxuICAgICAgICAgICAgPC9zcGFuPlxuICAgICAgICAgIDwvc3Bhbj5cbiAgICAgICAgPC9kaXY+XG4gICAgICA8L2M4eS1saS1ib2R5PlxuICAgIDwvYzh5LWxpPlxuICA8L2M4eS1saXN0LWdyb3VwPlxuPC9jOHktc2VsZWN0LXN0ZXAtZnJhbWU+XG4iXX0=