UNPKG

@jsonforms/angular-material

Version:

Material Renderer Set for Angular module of JSON Forms

254 lines (250 loc) 31.7 kB
/* The MIT License Copyright (c) 2017-2019 EclipseSource Munich https://github.com/eclipsesource/jsonforms Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ import some from 'lodash/some'; import get from 'lodash/get'; import { ChangeDetectionStrategy, ChangeDetectorRef, Component, } from '@angular/core'; import { JsonFormsAngularService, JsonFormsArrayControl, } from '@jsonforms/angular'; import { arrayDefaultTranslations, createDefaultValue, decode, defaultJsonFormsI18nState, findUISchema, getArrayTranslations, getFirstPrimitiveProp, mapDispatchToArrayControlProps, mapStateToArrayControlProps, rankWith, setReadonly, uiTypeIs, } from '@jsonforms/core'; import * as i0 from "@angular/core"; import * as i1 from "@jsonforms/angular"; import * as i2 from "@angular/common"; import * as i3 from "@angular/material/sidenav"; import * as i4 from "@angular/material/list"; import * as i5 from "@angular/material/button"; import * as i6 from "@angular/material/icon"; import * as i7 from "./detail"; const keywords = ['#', 'properties', 'items']; export const removeSchemaKeywords = (path) => { return decode(path .split('/') .filter((s) => !some(keywords, (key) => key === s)) .join('.')); }; export class MasterListComponent extends JsonFormsArrayControl { changeDetectorRef; masterItems; selectedItem; selectedItemIdx; addItem; removeItems; highlightedIdx; translations; constructor(jsonformsService, changeDetectorRef) { super(jsonformsService); this.changeDetectorRef = changeDetectorRef; } onListItemHover(idx) { this.highlightedIdx = idx; } trackElement(_index, element) { return element ? element.label : null; } ngOnInit() { super.ngOnInit(); const dispatch = this.jsonFormsService.updateCore.bind(this.jsonFormsService); const { addItem, removeItems } = mapDispatchToArrayControlProps(dispatch); this.addItem = addItem; this.removeItems = removeItems; } mapAdditionalProps(props) { const { data, path, schema, uischema } = props; const controlElement = uischema; this.propsPath = props.path; const detailUISchema = findUISchema(props.uischemas, schema, `${controlElement.scope}/items`, props.path, 'VerticalLayout', controlElement, props.rootSchema); if (!this.isEnabled()) { setReadonly(detailUISchema); } this.translations = props.translations; const masterItems = (data || []).map((d, index) => { const labelRefInstancePath = controlElement.options?.labelRef && removeSchemaKeywords(controlElement.options.labelRef); const isPrimitive = d !== undefined && typeof d !== 'object'; const masterItem = { label: isPrimitive ? d.toString() : get(d, labelRefInstancePath ?? getFirstPrimitiveProp(schema)), data: d, path: `${path}.${index}`, schema, uischema: detailUISchema, }; return masterItem; }); this.masterItems = masterItems; let newSelectedIdx = -1; let newSelectedItem; if (this.masterItems.length === 0) { // unset select if no elements anymore this.selectedItem = undefined; this.selectedItemIdx = -1; } else if (this.selectedItemIdx >= this.masterItems.length) { // the previous index is to high, reduce it to the maximal possible newSelectedIdx = this.masterItems.length - 1; newSelectedItem = this.masterItems[newSelectedIdx]; } else if (this.selectedItemIdx !== -1 && this.selectedItemIdx < this.masterItems.length) { newSelectedIdx = this.selectedItemIdx; newSelectedItem = this.masterItems[this.selectedItemIdx]; } if (newSelectedItem !== undefined && this.selectedItem !== undefined && (newSelectedItem.label === this.selectedItem.label || newSelectedItem.path === this.selectedItem.path)) { // after checking that we are on the same path, set selection this.selectedItem = newSelectedItem; this.selectedItemIdx = newSelectedIdx; } else if (this.masterItems.length > 0) { // pre-select 1st entry if the previous selected element as fallback this.selectedItem = this.masterItems[0]; this.selectedItemIdx = 0; } this.changeDetectorRef.markForCheck(); } onSelect(item, idx) { this.selectedItem = item; this.selectedItemIdx = idx; } onAddClick() { this.addItem(this.propsPath, createDefaultValue(this.scopedSchema, this.rootSchema))(); } onDeleteClick(item) { this.removeItems(this.propsPath, [item])(); } mapToProps(state) { const props = mapStateToArrayControlProps(state, this.getOwnProps()); const t = state.jsonforms.i18n?.translate ?? defaultJsonFormsI18nState.translate; const translations = getArrayTranslations(t, arrayDefaultTranslations, props.i18nKeyPrefix, props.label); return { ...props, translations }; } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: MasterListComponent, deps: [{ token: i1.JsonFormsAngularService }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component }); static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: MasterListComponent, selector: "jsonforms-list-with-detail-master", usesInheritance: true, ngImport: i0, template: ` <mat-sidenav-container [ngStyle]="{ display: hidden ? 'none' : '' }" autosize="true" class="container" > <mat-sidenav mode="side" opened> <mat-nav-list> <mat-list-item *ngIf="masterItems.length === 0">{{ translations.noDataMessage }}</mat-list-item> <mat-list-item *ngFor=" let item of masterItems; let i = index; trackBy: trackElement " [class.selected]="item === selectedItem" (click)="onSelect(item, i)" (mouseover)="onListItemHover(i)" (mouseout)="onListItemHover(undefined)" > <a matLine>{{ item.label || 'No label set' }}</a> <button mat-icon-button class="button item-button hide" (click)="onDeleteClick(i)" [ngClass]="{ show: highlightedIdx == i }" *ngIf="isEnabled()" > <mat-icon mat-list-icon>delete</mat-icon> </button> </mat-list-item> </mat-nav-list> <button mat-fab color="primary" class="add-button" (click)="onAddClick()" *ngIf="isEnabled()" > <mat-icon [attr.aria-label]="translations.addAriaLabel">add</mat-icon> </button> </mat-sidenav> <mat-sidenav-content class="content"> <jsonforms-detail *ngIf="selectedItem" [item]="selectedItem" ></jsonforms-detail> </mat-sidenav-content> </mat-sidenav-container> `, isInline: true, styles: ["mat-list-item.selected{background:#0000000a}.container{height:100vh}.content{padding:15px;background-color:#fff}.add-button{float:right;margin-top:.5em;margin-right:.25em}.button{float:right;margin-right:.25em}.item-button{position:absolute;top:0;right:0}.hide{display:none}.show{display:inline-block}mat-sidenav{width:20%}\n"], dependencies: [{ kind: "directive", type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "component", type: i3.MatSidenav, selector: "mat-sidenav", inputs: ["fixedInViewport", "fixedTopGap", "fixedBottomGap"], exportAs: ["matSidenav"] }, { kind: "component", type: i3.MatSidenavContainer, selector: "mat-sidenav-container", exportAs: ["matSidenavContainer"] }, { kind: "component", type: i3.MatSidenavContent, selector: "mat-sidenav-content" }, { kind: "component", type: i4.MatNavList, selector: "mat-nav-list", exportAs: ["matNavList"] }, { kind: "component", type: i4.MatListItem, selector: "mat-list-item, a[mat-list-item], button[mat-list-item]", inputs: ["activated"], exportAs: ["matListItem"] }, { kind: "component", type: i5.MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }, { kind: "component", type: i5.MatFabButton, selector: "button[mat-fab]", inputs: ["extended"], exportAs: ["matButton"] }, { kind: "component", type: i6.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: i7.JsonFormsDetailComponent, selector: "jsonforms-detail", inputs: ["item"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: MasterListComponent, decorators: [{ type: Component, args: [{ selector: 'jsonforms-list-with-detail-master', template: ` <mat-sidenav-container [ngStyle]="{ display: hidden ? 'none' : '' }" autosize="true" class="container" > <mat-sidenav mode="side" opened> <mat-nav-list> <mat-list-item *ngIf="masterItems.length === 0">{{ translations.noDataMessage }}</mat-list-item> <mat-list-item *ngFor=" let item of masterItems; let i = index; trackBy: trackElement " [class.selected]="item === selectedItem" (click)="onSelect(item, i)" (mouseover)="onListItemHover(i)" (mouseout)="onListItemHover(undefined)" > <a matLine>{{ item.label || 'No label set' }}</a> <button mat-icon-button class="button item-button hide" (click)="onDeleteClick(i)" [ngClass]="{ show: highlightedIdx == i }" *ngIf="isEnabled()" > <mat-icon mat-list-icon>delete</mat-icon> </button> </mat-list-item> </mat-nav-list> <button mat-fab color="primary" class="add-button" (click)="onAddClick()" *ngIf="isEnabled()" > <mat-icon [attr.aria-label]="translations.addAriaLabel">add</mat-icon> </button> </mat-sidenav> <mat-sidenav-content class="content"> <jsonforms-detail *ngIf="selectedItem" [item]="selectedItem" ></jsonforms-detail> </mat-sidenav-content> </mat-sidenav-container> `, changeDetection: ChangeDetectionStrategy.OnPush, standalone: false, styles: ["mat-list-item.selected{background:#0000000a}.container{height:100vh}.content{padding:15px;background-color:#fff}.add-button{float:right;margin-top:.5em;margin-right:.25em}.button{float:right;margin-right:.25em}.item-button{position:absolute;top:0;right:0}.hide{display:none}.show{display:inline-block}mat-sidenav{width:20%}\n"] }] }], ctorParameters: () => [{ type: i1.JsonFormsAngularService }, { type: i0.ChangeDetectorRef }] }); export const masterDetailTester = rankWith(4, uiTypeIs('ListWithDetail')); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWFzdGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vc3JjL2xpYnJhcnkvb3RoZXIvbWFzdGVyLWRldGFpbC9tYXN0ZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0VBdUJFO0FBQ0YsT0FBTyxJQUFJLE1BQU0sYUFBYSxDQUFDO0FBQy9CLE9BQU8sR0FBRyxNQUFNLFlBQVksQ0FBQztBQUM3QixPQUFPLEVBQ0wsdUJBQXVCLEVBQ3ZCLGlCQUFpQixFQUNqQixTQUFTLEdBRVYsTUFBTSxlQUFlLENBQUM7QUFDdkIsT0FBTyxFQUNMLHVCQUF1QixFQUN2QixxQkFBcUIsR0FDdEIsTUFBTSxvQkFBb0IsQ0FBQztBQUM1QixPQUFPLEVBRUwsd0JBQXdCLEVBR3hCLGtCQUFrQixFQUNsQixNQUFNLEVBQ04seUJBQXlCLEVBQ3pCLFlBQVksRUFDWixvQkFBb0IsRUFDcEIscUJBQXFCLEVBRXJCLDhCQUE4QixFQUM5QiwyQkFBMkIsRUFFM0IsUUFBUSxFQUNSLFdBQVcsRUFFWCxRQUFRLEdBQ1QsTUFBTSxpQkFBaUIsQ0FBQzs7Ozs7Ozs7O0FBRXpCLE1BQU0sUUFBUSxHQUFHLENBQUMsR0FBRyxFQUFFLFlBQVksRUFBRSxPQUFPLENBQUMsQ0FBQztBQUU5QyxNQUFNLENBQUMsTUFBTSxvQkFBb0IsR0FBRyxDQUFDLElBQVksRUFBRSxFQUFFO0lBQ25ELE9BQU8sTUFBTSxDQUNYLElBQUk7U0FDRCxLQUFLLENBQUMsR0FBRyxDQUFDO1NBQ1YsTUFBTSxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLElBQUksQ0FBQyxRQUFRLEVBQUUsQ0FBQyxHQUFHLEVBQUUsRUFBRSxDQUFDLEdBQUcsS0FBSyxDQUFDLENBQUMsQ0FBQztTQUNsRCxJQUFJLENBQUMsR0FBRyxDQUFDLENBQ2IsQ0FBQztBQUNKLENBQUMsQ0FBQztBQWlHRixNQUFNLE9BQU8sbUJBQ1gsU0FBUSxxQkFBcUI7SUFhbkI7SUFWVixXQUFXLENBQVE7SUFDbkIsWUFBWSxDQUFNO0lBQ2xCLGVBQWUsQ0FBUztJQUN4QixPQUFPLENBQTJDO0lBQ2xELFdBQVcsQ0FBbUQ7SUFDOUQsY0FBYyxDQUFTO0lBQ3ZCLFlBQVksQ0FBb0I7SUFFaEMsWUFDRSxnQkFBeUMsRUFDakMsaUJBQW9DO1FBRTVDLEtBQUssQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDO1FBRmhCLHNCQUFpQixHQUFqQixpQkFBaUIsQ0FBbUI7SUFHOUMsQ0FBQztJQUVELGVBQWUsQ0FBQyxHQUFXO1FBQ3pCLElBQUksQ0FBQyxjQUFjLEdBQUcsR0FBRyxDQUFDO0lBQzVCLENBQUM7SUFFRCxZQUFZLENBQUMsTUFBYyxFQUFFLE9BQVk7UUFDdkMsT0FBTyxPQUFPLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQztJQUN4QyxDQUFDO0lBRUQsUUFBUTtRQUNOLEtBQUssQ0FBQyxRQUFRLEVBQUUsQ0FBQztRQUNqQixNQUFNLFFBQVEsR0FBRyxJQUFJLENBQUMsZ0JBQWdCLENBQUMsVUFBVSxDQUFDLElBQUksQ0FDcEQsSUFBSSxDQUFDLGdCQUFnQixDQUN0QixDQUFDO1FBQ0YsTUFBTSxFQUFFLE9BQU8sRUFBRSxXQUFXLEVBQUUsR0FBRyw4QkFBOEIsQ0FBQyxRQUFRLENBQUMsQ0FBQztRQUMxRSxJQUFJLENBQUMsT0FBTyxHQUFHLE9BQU8sQ0FBQztRQUN2QixJQUFJLENBQUMsV0FBVyxHQUFHLFdBQVcsQ0FBQztJQUNqQyxDQUFDO0lBRUQsa0JBQWtCLENBQ2hCLEtBQThEO1FBRTlELE1BQU0sRUFBRSxJQUFJLEVBQUUsSUFBSSxFQUFFLE1BQU0sRUFBRSxRQUFRLEVBQUUsR0FBRyxLQUFLLENBQUM7UUFDL0MsTUFBTSxjQUFjLEdBQUcsUUFBMEIsQ0FBQztRQUNsRCxJQUFJLENBQUMsU0FBUyxHQUFHLEtBQUssQ0FBQyxJQUFJLENBQUM7UUFDNUIsTUFBTSxjQUFjLEdBQUcsWUFBWSxDQUNqQyxLQUFLLENBQUMsU0FBUyxFQUNmLE1BQU0sRUFDTixHQUFHLGNBQWMsQ0FBQyxLQUFLLFFBQVEsRUFDL0IsS0FBSyxDQUFDLElBQUksRUFDVixnQkFBZ0IsRUFDaEIsY0FBYyxFQUNkLEtBQUssQ0FBQyxVQUFVLENBQ2pCLENBQUM7UUFFRixJQUFJLENBQUMsSUFBSSxDQUFDLFNBQVMsRUFBRSxFQUFFLENBQUM7WUFDdEIsV0FBVyxDQUFDLGNBQWMsQ0FBQyxDQUFDO1FBQzlCLENBQUM7UUFFRCxJQUFJLENBQUMsWUFBWSxHQUFHLEtBQUssQ0FBQyxZQUFZLENBQUM7UUFFdkMsTUFBTSxXQUFXLEdBQUcsQ0FBQyxJQUFJLElBQUksRUFBRSxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBTSxFQUFFLEtBQWEsRUFBRSxFQUFFO1lBQzdELE1BQU0sb0JBQW9CLEdBQ3hCLGNBQWMsQ0FBQyxPQUFPLEVBQUUsUUFBUTtnQkFDaEMsb0JBQW9CLENBQUMsY0FBYyxDQUFDLE9BQU8sQ0FBQyxRQUFRLENBQUMsQ0FBQztZQUN4RCxNQUFNLFdBQVcsR0FBRyxDQUFDLEtBQUssU0FBUyxJQUFJLE9BQU8sQ0FBQyxLQUFLLFFBQVEsQ0FBQztZQUM3RCxNQUFNLFVBQVUsR0FBRztnQkFDakIsS0FBSyxFQUFFLFdBQVc7b0JBQ2hCLENBQUMsQ0FBQyxDQUFDLENBQUMsUUFBUSxFQUFFO29CQUNkLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxFQUFFLG9CQUFvQixJQUFJLHFCQUFxQixDQUFDLE1BQU0sQ0FBQyxDQUFDO2dCQUNqRSxJQUFJLEVBQUUsQ0FBQztnQkFDUCxJQUFJLEVBQUUsR0FBRyxJQUFJLElBQUksS0FBSyxFQUFFO2dCQUN4QixNQUFNO2dCQUNOLFFBQVEsRUFBRSxjQUFjO2FBQ3pCLENBQUM7WUFDRixPQUFPLFVBQVUsQ0FBQztRQUNwQixDQUFDLENBQUMsQ0FBQztRQUNILElBQUksQ0FBQyxXQUFXLEdBQUcsV0FBVyxDQUFDO1FBQy9CLElBQUksY0FBYyxHQUFHLENBQUMsQ0FBQyxDQUFDO1FBQ3hCLElBQUksZUFBZSxDQUFDO1FBQ3BCLElBQUksSUFBSSxDQUFDLFdBQVcsQ0FBQyxNQUFNLEtBQUssQ0FBQyxFQUFFLENBQUM7WUFDbEMsc0NBQXNDO1lBQ3RDLElBQUksQ0FBQyxZQUFZLEdBQUcsU0FBUyxDQUFDO1lBQzlCLElBQUksQ0FBQyxlQUFlLEdBQUcsQ0FBQyxDQUFDLENBQUM7UUFDNUIsQ0FBQzthQUFNLElBQUksSUFBSSxDQUFDLGVBQWUsSUFBSSxJQUFJLENBQUMsV0FBVyxDQUFDLE1BQU0sRUFBRSxDQUFDO1lBQzNELG1FQUFtRTtZQUNuRSxjQUFjLEdBQUcsSUFBSSxDQUFDLFdBQVcsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFDO1lBQzdDLGVBQWUsR0FBRyxJQUFJLENBQUMsV0FBVyxDQUFDLGNBQWMsQ0FBQyxDQUFDO1FBQ3JELENBQUM7YUFBTSxJQUNMLElBQUksQ0FBQyxlQUFlLEtBQUssQ0FBQyxDQUFDO1lBQzNCLElBQUksQ0FBQyxlQUFlLEdBQUcsSUFBSSxDQUFDLFdBQVcsQ0FBQyxNQUFNLEVBQzlDLENBQUM7WUFDRCxjQUFjLEdBQUcsSUFBSSxDQUFDLGVBQWUsQ0FBQztZQUN0QyxlQUFlLEdBQUcsSUFBSSxDQUFDLFdBQVcsQ0FBQyxJQUFJLENBQUMsZUFBZSxDQUFDLENBQUM7UUFDM0QsQ0FBQztRQUVELElBQ0UsZUFBZSxLQUFLLFNBQVM7WUFDN0IsSUFBSSxDQUFDLFlBQVksS0FBSyxTQUFTO1lBQy9CLENBQUMsZUFBZSxDQUFDLEtBQUssS0FBSyxJQUFJLENBQUMsWUFBWSxDQUFDLEtBQUs7Z0JBQ2hELGVBQWUsQ0FBQyxJQUFJLEtBQUssSUFBSSxDQUFDLFlBQVksQ0FBQyxJQUFJLENBQUMsRUFDbEQsQ0FBQztZQUNELDZEQUE2RDtZQUM3RCxJQUFJLENBQUMsWUFBWSxHQUFHLGVBQWUsQ0FBQztZQUNwQyxJQUFJLENBQUMsZUFBZSxHQUFHLGNBQWMsQ0FBQztRQUN4QyxDQUFDO2FBQU0sSUFBSSxJQUFJLENBQUMsV0FBVyxDQUFDLE1BQU0sR0FBRyxDQUFDLEVBQUUsQ0FBQztZQUN2QyxvRUFBb0U7WUFDcEUsSUFBSSxDQUFDLFlBQVksR0FBRyxJQUFJLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQ3hDLElBQUksQ0FBQyxlQUFlLEdBQUcsQ0FBQyxDQUFDO1FBQzNCLENBQUM7UUFDRCxJQUFJLENBQUMsaUJBQWlCLENBQUMsWUFBWSxFQUFFLENBQUM7SUFDeEMsQ0FBQztJQUVELFFBQVEsQ0FBQyxJQUFTLEVBQUUsR0FBVztRQUM3QixJQUFJLENBQUMsWUFBWSxHQUFHLElBQUksQ0FBQztRQUN6QixJQUFJLENBQUMsZUFBZSxHQUFHLEdBQUcsQ0FBQztJQUM3QixDQUFDO0lBRUQsVUFBVTtRQUNSLElBQUksQ0FBQyxPQUFPLENBQ1YsSUFBSSxDQUFDLFNBQVMsRUFDZCxrQkFBa0IsQ0FBQyxJQUFJLENBQUMsWUFBWSxFQUFFLElBQUksQ0FBQyxVQUFVLENBQUMsQ0FDdkQsRUFBRSxDQUFDO0lBQ04sQ0FBQztJQUVELGFBQWEsQ0FBQyxJQUFZO1FBQ3hCLElBQUksQ0FBQyxXQUFXLENBQUMsSUFBSSxDQUFDLFNBQVMsRUFBRSxDQUFDLElBQUksQ0FBQyxDQUFDLEVBQUUsQ0FBQztJQUM3QyxDQUFDO0lBRVMsVUFBVSxDQUNsQixLQUFxQjtRQUVyQixNQUFNLEtBQUssR0FBRywyQkFBMkIsQ0FBQyxLQUFLLEVBQUUsSUFBSSxDQUFDLFdBQVcsRUFBRSxDQUFDLENBQUM7UUFDckUsTUFBTSxDQUFDLEdBQ0wsS0FBSyxDQUFDLFNBQVMsQ0FBQyxJQUFJLEVBQUUsU0FBUyxJQUFJLHlCQUF5QixDQUFDLFNBQVMsQ0FBQztRQUN6RSxNQUFNLFlBQVksR0FBRyxvQkFBb0IsQ0FDdkMsQ0FBQyxFQUNELHdCQUF3QixFQUN4QixLQUFLLENBQUMsYUFBYSxFQUNuQixLQUFLLENBQUMsS0FBSyxDQUNaLENBQUM7UUFDRixPQUFPLEVBQUUsR0FBRyxLQUFLLEVBQUUsWUFBWSxFQUFFLENBQUM7SUFDcEMsQ0FBQzt3R0E1SVUsbUJBQW1COzRGQUFuQixtQkFBbUIsZ0dBN0ZwQjs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBbURUOzs0RkEwQ1UsbUJBQW1CO2tCQS9GL0IsU0FBUzsrQkFDRSxtQ0FBbUMsWUFDbkM7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQW1EVCxtQkF1Q2dCLHVCQUF1QixDQUFDLE1BQU0sY0FDbkMsS0FBSzs7QUFpSm5CLE1BQU0sQ0FBQyxNQUFNLGtCQUFrQixHQUFpQixRQUFRLENBQ3RELENBQUMsRUFDRCxRQUFRLENBQUMsZ0JBQWdCLENBQUMsQ0FDM0IsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qXG4gIFRoZSBNSVQgTGljZW5zZVxuICBcbiAgQ29weXJpZ2h0IChjKSAyMDE3LTIwMTkgRWNsaXBzZVNvdXJjZSBNdW5pY2hcbiAgaHR0cHM6Ly9naXRodWIuY29tL2VjbGlwc2Vzb3VyY2UvanNvbmZvcm1zXG4gIFxuICBQZXJtaXNzaW9uIGlzIGhlcmVieSBncmFudGVkLCBmcmVlIG9mIGNoYXJnZSwgdG8gYW55IHBlcnNvbiBvYnRhaW5pbmcgYSBjb3B5XG4gIG9mIHRoaXMgc29mdHdhcmUgYW5kIGFzc29jaWF0ZWQgZG9jdW1lbnRhdGlvbiBmaWxlcyAodGhlIFwiU29mdHdhcmVcIiksIHRvIGRlYWxcbiAgaW4gdGhlIFNvZnR3YXJlIHdpdGhvdXQgcmVzdHJpY3Rpb24sIGluY2x1ZGluZyB3aXRob3V0IGxpbWl0YXRpb24gdGhlIHJpZ2h0c1xuICB0byB1c2UsIGNvcHksIG1vZGlmeSwgbWVyZ2UsIHB1Ymxpc2gsIGRpc3RyaWJ1dGUsIHN1YmxpY2Vuc2UsIGFuZC9vciBzZWxsXG4gIGNvcGllcyBvZiB0aGUgU29mdHdhcmUsIGFuZCB0byBwZXJtaXQgcGVyc29ucyB0byB3aG9tIHRoZSBTb2Z0d2FyZSBpc1xuICBmdXJuaXNoZWQgdG8gZG8gc28sIHN1YmplY3QgdG8gdGhlIGZvbGxvd2luZyBjb25kaXRpb25zOlxuICBcbiAgVGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UgYW5kIHRoaXMgcGVybWlzc2lvbiBub3RpY2Ugc2hhbGwgYmUgaW5jbHVkZWQgaW5cbiAgYWxsIGNvcGllcyBvciBzdWJzdGFudGlhbCBwb3J0aW9ucyBvZiB0aGUgU29mdHdhcmUuXG4gIFxuICBUSEUgU09GVFdBUkUgSVMgUFJPVklERUQgXCJBUyBJU1wiLCBXSVRIT1VUIFdBUlJBTlRZIE9GIEFOWSBLSU5ELCBFWFBSRVNTIE9SXG4gIElNUExJRUQsIElOQ0xVRElORyBCVVQgTk9UIExJTUlURUQgVE8gVEhFIFdBUlJBTlRJRVMgT0YgTUVSQ0hBTlRBQklMSVRZLFxuICBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRSBBTkQgTk9OSU5GUklOR0VNRU5ULiBJTiBOTyBFVkVOVCBTSEFMTCBUSEVcbiAgQVVUSE9SUyBPUiBDT1BZUklHSFQgSE9MREVSUyBCRSBMSUFCTEUgRk9SIEFOWSBDTEFJTSwgREFNQUdFUyBPUiBPVEhFUlxuICBMSUFCSUxJVFksIFdIRVRIRVIgSU4gQU4gQUNUSU9OIE9GIENPTlRSQUNULCBUT1JUIE9SIE9USEVSV0lTRSwgQVJJU0lORyBGUk9NLFxuICBPVVQgT0YgT1IgSU4gQ09OTkVDVElPTiBXSVRIIFRIRSBTT0ZUV0FSRSBPUiBUSEUgVVNFIE9SIE9USEVSIERFQUxJTkdTIElOXG4gIFRIRSBTT0ZUV0FSRS5cbiovXG5pbXBvcnQgc29tZSBmcm9tICdsb2Rhc2gvc29tZSc7XG5pbXBvcnQgZ2V0IGZyb20gJ2xvZGFzaC9nZXQnO1xuaW1wb3J0IHtcbiAgQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3ksXG4gIENoYW5nZURldGVjdG9yUmVmLFxuICBDb21wb25lbnQsXG4gIE9uSW5pdCxcbn0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQge1xuICBKc29uRm9ybXNBbmd1bGFyU2VydmljZSxcbiAgSnNvbkZvcm1zQXJyYXlDb250cm9sLFxufSBmcm9tICdAanNvbmZvcm1zL2FuZ3VsYXInO1xuaW1wb3J0IHtcbiAgQXJyYXlDb250cm9sUHJvcHMsXG4gIGFycmF5RGVmYXVsdFRyYW5zbGF0aW9ucyxcbiAgQXJyYXlUcmFuc2xhdGlvbnMsXG4gIENvbnRyb2xFbGVtZW50LFxuICBjcmVhdGVEZWZhdWx0VmFsdWUsXG4gIGRlY29kZSxcbiAgZGVmYXVsdEpzb25Gb3Jtc0kxOG5TdGF0ZSxcbiAgZmluZFVJU2NoZW1hLFxuICBnZXRBcnJheVRyYW5zbGF0aW9ucyxcbiAgZ2V0Rmlyc3RQcmltaXRpdmVQcm9wLFxuICBKc29uRm9ybXNTdGF0ZSxcbiAgbWFwRGlzcGF0Y2hUb0FycmF5Q29udHJvbFByb3BzLFxuICBtYXBTdGF0ZVRvQXJyYXlDb250cm9sUHJvcHMsXG4gIFJhbmtlZFRlc3RlcixcbiAgcmFua1dpdGgsXG4gIHNldFJlYWRvbmx5LFxuICBTdGF0ZVByb3BzT2ZBcnJheUNvbnRyb2wsXG4gIHVpVHlwZUlzLFxufSBmcm9tICdAanNvbmZvcm1zL2NvcmUnO1xuXG5jb25zdCBrZXl3b3JkcyA9IFsnIycsICdwcm9wZXJ0aWVzJywgJ2l0ZW1zJ107XG5cbmV4cG9ydCBjb25zdCByZW1vdmVTY2hlbWFLZXl3b3JkcyA9IChwYXRoOiBzdHJpbmcpID0+IHtcbiAgcmV0dXJuIGRlY29kZShcbiAgICBwYXRoXG4gICAgICAuc3BsaXQoJy8nKVxuICAgICAgLmZpbHRlcigocykgPT4gIXNvbWUoa2V5d29yZHMsIChrZXkpID0+IGtleSA9PT0gcykpXG4gICAgICAuam9pbignLicpXG4gICk7XG59O1xuXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICdqc29uZm9ybXMtbGlzdC13aXRoLWRldGFpbC1tYXN0ZXInLFxuICB0ZW1wbGF0ZTogYFxuICAgIDxtYXQtc2lkZW5hdi1jb250YWluZXJcbiAgICAgIFtuZ1N0eWxlXT1cInsgZGlzcGxheTogaGlkZGVuID8gJ25vbmUnIDogJycgfVwiXG4gICAgICBhdXRvc2l6ZT1cInRydWVcIlxuICAgICAgY2xhc3M9XCJjb250YWluZXJcIlxuICAgID5cbiAgICAgIDxtYXQtc2lkZW5hdiBtb2RlPVwic2lkZVwiIG9wZW5lZD5cbiAgICAgICAgPG1hdC1uYXYtbGlzdD5cbiAgICAgICAgICA8bWF0LWxpc3QtaXRlbSAqbmdJZj1cIm1hc3Rlckl0ZW1zLmxlbmd0aCA9PT0gMFwiPnt7XG4gICAgICAgICAgICB0cmFuc2xhdGlvbnMubm9EYXRhTWVzc2FnZVxuICAgICAgICAgIH19PC9tYXQtbGlzdC1pdGVtPlxuICAgICAgICAgIDxtYXQtbGlzdC1pdGVtXG4gICAgICAgICAgICAqbmdGb3I9XCJcbiAgICAgICAgICAgICAgbGV0IGl0ZW0gb2YgbWFzdGVySXRlbXM7XG4gICAgICAgICAgICAgIGxldCBpID0gaW5kZXg7XG4gICAgICAgICAgICAgIHRyYWNrQnk6IHRyYWNrRWxlbWVudFxuICAgICAgICAgICAgXCJcbiAgICAgICAgICAgIFtjbGFzcy5zZWxlY3RlZF09XCJpdGVtID09PSBzZWxlY3RlZEl0ZW1cIlxuICAgICAgICAgICAgKGNsaWNrKT1cIm9uU2VsZWN0KGl0ZW0sIGkpXCJcbiAgICAgICAgICAgIChtb3VzZW92ZXIpPVwib25MaXN0SXRlbUhvdmVyKGkpXCJcbiAgICAgICAgICAgIChtb3VzZW91dCk9XCJvbkxpc3RJdGVtSG92ZXIodW5kZWZpbmVkKVwiXG4gICAgICAgICAgPlxuICAgICAgICAgICAgPGEgbWF0TGluZT57eyBpdGVtLmxhYmVsIHx8ICdObyBsYWJlbCBzZXQnIH19PC9hPlxuICAgICAgICAgICAgPGJ1dHRvblxuICAgICAgICAgICAgICBtYXQtaWNvbi1idXR0b25cbiAgICAgICAgICAgICAgY2xhc3M9XCJidXR0b24gaXRlbS1idXR0b24gaGlkZVwiXG4gICAgICAgICAgICAgIChjbGljayk9XCJvbkRlbGV0ZUNsaWNrKGkpXCJcbiAgICAgICAgICAgICAgW25nQ2xhc3NdPVwieyBzaG93OiBoaWdobGlnaHRlZElkeCA9PSBpIH1cIlxuICAgICAgICAgICAgICAqbmdJZj1cImlzRW5hYmxlZCgpXCJcbiAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgPG1hdC1pY29uIG1hdC1saXN0LWljb24+ZGVsZXRlPC9tYXQtaWNvbj5cbiAgICAgICAgICAgIDwvYnV0dG9uPlxuICAgICAgICAgIDwvbWF0LWxpc3QtaXRlbT5cbiAgICAgICAgPC9tYXQtbmF2LWxpc3Q+XG4gICAgICAgIDxidXR0b25cbiAgICAgICAgICBtYXQtZmFiXG4gICAgICAgICAgY29sb3I9XCJwcmltYXJ5XCJcbiAgICAgICAgICBjbGFzcz1cImFkZC1idXR0b25cIlxuICAgICAgICAgIChjbGljayk9XCJvbkFkZENsaWNrKClcIlxuICAgICAgICAgICpuZ0lmPVwiaXNFbmFibGVkKClcIlxuICAgICAgICA+XG4gICAgICAgICAgPG1hdC1pY29uIFthdHRyLmFyaWEtbGFiZWxdPVwidHJhbnNsYXRpb25zLmFkZEFyaWFMYWJlbFwiPmFkZDwvbWF0LWljb24+XG4gICAgICAgIDwvYnV0dG9uPlxuICAgICAgPC9tYXQtc2lkZW5hdj5cbiAgICAgIDxtYXQtc2lkZW5hdi1jb250ZW50IGNsYXNzPVwiY29udGVudFwiPlxuICAgICAgICA8anNvbmZvcm1zLWRldGFpbFxuICAgICAgICAgICpuZ0lmPVwic2VsZWN0ZWRJdGVtXCJcbiAgICAgICAgICBbaXRlbV09XCJzZWxlY3RlZEl0ZW1cIlxuICAgICAgICA+PC9qc29uZm9ybXMtZGV0YWlsPlxuICAgICAgPC9tYXQtc2lkZW5hdi1jb250ZW50PlxuICAgIDwvbWF0LXNpZGVuYXYtY29udGFpbmVyPlxuICBgLFxuICBzdHlsZXM6IFtcbiAgICBgXG4gICAgICAvKiBUT0RPKG1kYy1taWdyYXRpb24pOiBUaGUgZm9sbG93aW5nIHJ1bGUgdGFyZ2V0cyBpbnRlcm5hbCBjbGFzc2VzIG9mIGxpc3QgdGhhdCBtYXkgbm8gbG9uZ2VyIGFwcGx5IGZvciB0aGUgTURDIHZlcnNpb24uICovXG4gICAgICBtYXQtbGlzdC1pdGVtLnNlbGVjdGVkIHtcbiAgICAgICAgYmFja2dyb3VuZDogcmdiYSgwLCAwLCAwLCAwLjA0KTtcbiAgICAgIH1cbiAgICAgIC5jb250YWluZXIge1xuICAgICAgICBoZWlnaHQ6IDEwMHZoO1xuICAgICAgfVxuICAgICAgLmNvbnRlbnQge1xuICAgICAgICBwYWRkaW5nOiAxNXB4O1xuICAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiAjZmZmO1xuICAgICAgfVxuICAgICAgLmFkZC1idXR0b24ge1xuICAgICAgICBmbG9hdDogcmlnaHQ7XG4gICAgICAgIG1hcmdpbi10b3A6IDAuNWVtO1xuICAgICAgICBtYXJnaW4tcmlnaHQ6IDAuMjVlbTtcbiAgICAgIH1cbiAgICAgIC5idXR0b24ge1xuICAgICAgICBmbG9hdDogcmlnaHQ7XG4gICAgICAgIG1hcmdpbi1yaWdodDogMC4yNWVtO1xuICAgICAgfVxuICAgICAgLml0ZW0tYnV0dG9uIHtcbiAgICAgICAgcG9zaXRpb246IGFic29sdXRlO1xuICAgICAgICB0b3A6IDA7XG4gICAgICAgIHJpZ2h0OiAwO1xuICAgICAgfVxuICAgICAgLmhpZGUge1xuICAgICAgICBkaXNwbGF5OiBub25lO1xuICAgICAgfVxuICAgICAgLnNob3cge1xuICAgICAgICBkaXNwbGF5OiBpbmxpbmUtYmxvY2s7XG4gICAgICB9XG4gICAgICBtYXQtc2lkZW5hdiB7XG4gICAgICAgIHdpZHRoOiAyMCU7XG4gICAgICB9XG4gICAgYCxcbiAgXSxcbiAgY2hhbmdlRGV0ZWN0aW9uOiBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneS5PblB1c2gsXG4gIHN0YW5kYWxvbmU6IGZhbHNlLFxufSlcbmV4cG9ydCBjbGFzcyBNYXN0ZXJMaXN0Q29tcG9uZW50XG4gIGV4dGVuZHMgSnNvbkZvcm1zQXJyYXlDb250cm9sXG4gIGltcGxlbWVudHMgT25Jbml0XG57XG4gIG1hc3Rlckl0ZW1zOiBhbnlbXTtcbiAgc2VsZWN0ZWRJdGVtOiBhbnk7XG4gIHNlbGVjdGVkSXRlbUlkeDogbnVtYmVyO1xuICBhZGRJdGVtOiAocGF0aDogc3RyaW5nLCB2YWx1ZTogYW55KSA9PiAoKSA9PiB2b2lkO1xuICByZW1vdmVJdGVtczogKHBhdGg6IHN0cmluZywgdG9EZWxldGU6IG51bWJlcltdKSA9PiAoKSA9PiB2b2lkO1xuICBoaWdobGlnaHRlZElkeDogbnVtYmVyO1xuICB0cmFuc2xhdGlvbnM6IEFycmF5VHJhbnNsYXRpb25zO1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIGpzb25mb3Jtc1NlcnZpY2U6IEpzb25Gb3Jtc0FuZ3VsYXJTZXJ2aWNlLFxuICAgIHByaXZhdGUgY2hhbmdlRGV0ZWN0b3JSZWY6IENoYW5nZURldGVjdG9yUmVmXG4gICkge1xuICAgIHN1cGVyKGpzb25mb3Jtc1NlcnZpY2UpO1xuICB9XG5cbiAgb25MaXN0SXRlbUhvdmVyKGlkeDogbnVtYmVyKSB7XG4gICAgdGhpcy5oaWdobGlnaHRlZElkeCA9IGlkeDtcbiAgfVxuXG4gIHRyYWNrRWxlbWVudChfaW5kZXg6IG51bWJlciwgZWxlbWVudDogYW55KSB7XG4gICAgcmV0dXJuIGVsZW1lbnQgPyBlbGVtZW50LmxhYmVsIDogbnVsbDtcbiAgfVxuXG4gIG5nT25Jbml0KCkge1xuICAgIHN1cGVyLm5nT25Jbml0KCk7XG4gICAgY29uc3QgZGlzcGF0Y2ggPSB0aGlzLmpzb25Gb3Jtc1NlcnZpY2UudXBkYXRlQ29yZS5iaW5kKFxuICAgICAgdGhpcy5qc29uRm9ybXNTZXJ2aWNlXG4gICAgKTtcbiAgICBjb25zdCB7IGFkZEl0ZW0sIHJlbW92ZUl0ZW1zIH0gPSBtYXBEaXNwYXRjaFRvQXJyYXlDb250cm9sUHJvcHMoZGlzcGF0Y2gpO1xuICAgIHRoaXMuYWRkSXRlbSA9IGFkZEl0ZW07XG4gICAgdGhpcy5yZW1vdmVJdGVtcyA9IHJlbW92ZUl0ZW1zO1xuICB9XG5cbiAgbWFwQWRkaXRpb25hbFByb3BzKFxuICAgIHByb3BzOiBBcnJheUNvbnRyb2xQcm9wcyAmIHsgdHJhbnNsYXRpb25zOiBBcnJheVRyYW5zbGF0aW9ucyB9XG4gICkge1xuICAgIGNvbnN0IHsgZGF0YSwgcGF0aCwgc2NoZW1hLCB1aXNjaGVtYSB9ID0gcHJvcHM7XG4gICAgY29uc3QgY29udHJvbEVsZW1lbnQgPSB1aXNjaGVtYSBhcyBDb250cm9sRWxlbWVudDtcbiAgICB0aGlzLnByb3BzUGF0aCA9IHByb3BzLnBhdGg7XG4gICAgY29uc3QgZGV0YWlsVUlTY2hlbWEgPSBmaW5kVUlTY2hlbWEoXG4gICAgICBwcm9wcy51aXNjaGVtYXMsXG4gICAgICBzY2hlbWEsXG4gICAgICBgJHtjb250cm9sRWxlbWVudC5zY29wZX0vaXRlbXNgLFxuICAgICAgcHJvcHMucGF0aCxcbiAgICAgICdWZXJ0aWNhbExheW91dCcsXG4gICAgICBjb250cm9sRWxlbWVudCxcbiAgICAgIHByb3BzLnJvb3RTY2hlbWFcbiAgICApO1xuXG4gICAgaWYgKCF0aGlzLmlzRW5hYmxlZCgpKSB7XG4gICAgICBzZXRSZWFkb25seShkZXRhaWxVSVNjaGVtYSk7XG4gICAgfVxuXG4gICAgdGhpcy50cmFuc2xhdGlvbnMgPSBwcm9wcy50cmFuc2xhdGlvbnM7XG5cbiAgICBjb25zdCBtYXN0ZXJJdGVtcyA9IChkYXRhIHx8IFtdKS5tYXAoKGQ6IGFueSwgaW5kZXg6IG51bWJlcikgPT4ge1xuICAgICAgY29uc3QgbGFiZWxSZWZJbnN0YW5jZVBhdGggPVxuICAgICAgICBjb250cm9sRWxlbWVudC5vcHRpb25zPy5sYWJlbFJlZiAmJlxuICAgICAgICByZW1vdmVTY2hlbWFLZXl3b3Jkcyhjb250cm9sRWxlbWVudC5vcHRpb25zLmxhYmVsUmVmKTtcbiAgICAgIGNvbnN0IGlzUHJpbWl0aXZlID0gZCAhPT0gdW5kZWZpbmVkICYmIHR5cGVvZiBkICE9PSAnb2JqZWN0JztcbiAgICAgIGNvbnN0IG1hc3Rlckl0ZW0gPSB7XG4gICAgICAgIGxhYmVsOiBpc1ByaW1pdGl2ZVxuICAgICAgICAgID8gZC50b1N0cmluZygpXG4gICAgICAgICAgOiBnZXQoZCwgbGFiZWxSZWZJbnN0YW5jZVBhdGggPz8gZ2V0Rmlyc3RQcmltaXRpdmVQcm9wKHNjaGVtYSkpLFxuICAgICAgICBkYXRhOiBkLFxuICAgICAgICBwYXRoOiBgJHtwYXRofS4ke2luZGV4fWAsXG4gICAgICAgIHNjaGVtYSxcbiAgICAgICAgdWlzY2hlbWE6IGRldGFpbFVJU2NoZW1hLFxuICAgICAgfTtcbiAgICAgIHJldHVybiBtYXN0ZXJJdGVtO1xuICAgIH0pO1xuICAgIHRoaXMubWFzdGVySXRlbXMgPSBtYXN0ZXJJdGVtcztcbiAgICBsZXQgbmV3U2VsZWN0ZWRJZHggPSAtMTtcbiAgICBsZXQgbmV3U2VsZWN0ZWRJdGVtO1xuICAgIGlmICh0aGlzLm1hc3Rlckl0ZW1zLmxlbmd0aCA9PT0gMCkge1xuICAgICAgLy8gdW5zZXQgc2VsZWN0IGlmIG5vIGVsZW1lbnRzIGFueW1vcmVcbiAgICAgIHRoaXMuc2VsZWN0ZWRJdGVtID0gdW5kZWZpbmVkO1xuICAgICAgdGhpcy5zZWxlY3RlZEl0ZW1JZHggPSAtMTtcbiAgICB9IGVsc2UgaWYgKHRoaXMuc2VsZWN0ZWRJdGVtSWR4ID49IHRoaXMubWFzdGVySXRlbXMubGVuZ3RoKSB7XG4gICAgICAvLyB0aGUgcHJldmlvdXMgaW5kZXggaXMgdG8gaGlnaCwgcmVkdWNlIGl0IHRvIHRoZSBtYXhpbWFsIHBvc3NpYmxlXG4gICAgICBuZXdTZWxlY3RlZElkeCA9IHRoaXMubWFzdGVySXRlbXMubGVuZ3RoIC0gMTtcbiAgICAgIG5ld1NlbGVjdGVkSXRlbSA9IHRoaXMubWFzdGVySXRlbXNbbmV3U2VsZWN0ZWRJZHhdO1xuICAgIH0gZWxzZSBpZiAoXG4gICAgICB0aGlzLnNlbGVjdGVkSXRlbUlkeCAhPT0gLTEgJiZcbiAgICAgIHRoaXMuc2VsZWN0ZWRJdGVtSWR4IDwgdGhpcy5tYXN0ZXJJdGVtcy5sZW5ndGhcbiAgICApIHtcbiAgICAgIG5ld1NlbGVjdGVkSWR4ID0gdGhpcy5zZWxlY3RlZEl0ZW1JZHg7XG4gICAgICBuZXdTZWxlY3RlZEl0ZW0gPSB0aGlzLm1hc3Rlckl0ZW1zW3RoaXMuc2VsZWN0ZWRJdGVtSWR4XTtcbiAgICB9XG5cbiAgICBpZiAoXG4gICAgICBuZXdTZWxlY3RlZEl0ZW0gIT09IHVuZGVmaW5lZCAmJlxuICAgICAgdGhpcy5zZWxlY3RlZEl0ZW0gIT09IHVuZGVmaW5lZCAmJlxuICAgICAgKG5ld1NlbGVjdGVkSXRlbS5sYWJlbCA9PT0gdGhpcy5zZWxlY3RlZEl0ZW0ubGFiZWwgfHxcbiAgICAgICAgbmV3U2VsZWN0ZWRJdGVtLnBhdGggPT09IHRoaXMuc2VsZWN0ZWRJdGVtLnBhdGgpXG4gICAgKSB7XG4gICAgICAvLyBhZnRlciBjaGVja2luZyB0aGF0IHdlIGFyZSBvbiB0aGUgc2FtZSBwYXRoLCBzZXQgc2VsZWN0aW9uXG4gICAgICB0aGlzLnNlbGVjdGVkSXRlbSA9IG5ld1NlbGVjdGVkSXRlbTtcbiAgICAgIHRoaXMuc2VsZWN0ZWRJdGVtSWR4ID0gbmV3U2VsZWN0ZWRJZHg7XG4gICAgfSBlbHNlIGlmICh0aGlzLm1hc3Rlckl0ZW1zLmxlbmd0aCA+IDApIHtcbiAgICAgIC8vIHByZS1zZWxlY3QgMXN0IGVudHJ5IGlmIHRoZSBwcmV2aW91cyBzZWxlY3RlZCBlbGVtZW50IGFzIGZhbGxiYWNrXG4gICAgICB0aGlzLnNlbGVjdGVkSXRlbSA9IHRoaXMubWFzdGVySXRlbXNbMF07XG4gICAgICB0aGlzLnNlbGVjdGVkSXRlbUlkeCA9IDA7XG4gICAgfVxuICAgIHRoaXMuY2hhbmdlRGV0ZWN0b3JSZWYubWFya0ZvckNoZWNrKCk7XG4gIH1cblxuICBvblNlbGVjdChpdGVtOiBhbnksIGlkeDogbnVtYmVyKTogdm9pZCB7XG4gICAgdGhpcy5zZWxlY3RlZEl0ZW0gPSBpdGVtO1xuICAgIHRoaXMuc2VsZWN0ZWRJdGVtSWR4ID0gaWR4O1xuICB9XG5cbiAgb25BZGRDbGljaygpIHtcbiAgICB0aGlzLmFkZEl0ZW0oXG4gICAgICB0aGlzLnByb3BzUGF0aCxcbiAgICAgIGNyZWF0ZURlZmF1bHRWYWx1ZSh0aGlzLnNjb3BlZFNjaGVtYSwgdGhpcy5yb290U2NoZW1hKVxuICAgICkoKTtcbiAgfVxuXG4gIG9uRGVsZXRlQ2xpY2soaXRlbTogbnVtYmVyKSB7XG4gICAgdGhpcy5yZW1vdmVJdGVtcyh0aGlzLnByb3BzUGF0aCwgW2l0ZW1dKSgpO1xuICB9XG5cbiAgcHJvdGVjdGVkIG1hcFRvUHJvcHMoXG4gICAgc3RhdGU6IEpzb25Gb3Jtc1N0YXRlXG4gICk6IFN0YXRlUHJvcHNPZkFycmF5Q29udHJvbCAmIHsgdHJhbnNsYXRpb25zOiBBcnJheVRyYW5zbGF0aW9ucyB9IHtcbiAgICBjb25zdCBwcm9wcyA9IG1hcFN0YXRlVG9BcnJheUNvbnRyb2xQcm9wcyhzdGF0ZSwgdGhpcy5nZXRPd25Qcm9wcygpKTtcbiAgICBjb25zdCB0ID1cbiAgICAgIHN0YXRlLmpzb25mb3Jtcy5pMThuPy50cmFuc2xhdGUgPz8gZGVmYXVsdEpzb25Gb3Jtc0kxOG5TdGF0ZS50cmFuc2xhdGU7XG4gICAgY29uc3QgdHJhbnNsYXRpb25zID0gZ2V0QXJyYXlUcmFuc2xhdGlvbnMoXG4gICAgICB0LFxuICAgICAgYXJyYXlEZWZhdWx0VHJhbnNsYXRpb25zLFxuICAgICAgcHJvcHMuaTE4bktleVByZWZpeCxcbiAgICAgIHByb3BzLmxhYmVsXG4gICAgKTtcbiAgICByZXR1cm4geyAuLi5wcm9wcywgdHJhbnNsYXRpb25zIH07XG4gIH1cbn1cblxuZXhwb3J0IGNvbnN0IG1hc3RlckRldGFpbFRlc3RlcjogUmFua2VkVGVzdGVyID0gcmFua1dpdGgoXG4gIDQsXG4gIHVpVHlwZUlzKCdMaXN0V2l0aERldGFpbCcpXG4pO1xuIl19