UNPKG

kwikid-camera

Version:
236 lines 40.7 kB
import { __decorate } from "tslib"; /* eslint-disable no-empty-function */ /* eslint-disable @typescript-eslint/no-empty-function */ /* eslint-disable @typescript-eslint/no-unused-vars */ /* eslint-disable brace-style */ import { Component, EventEmitter, Input, Output, forwardRef } from "@angular/core"; import { FormControl, FormGroup, NG_VALUE_ACCESSOR } from "@angular/forms"; import { checkObjectKeyExists, isNotEmptyValue, logMethod } from "kwikid-toolkit"; import { Subscription } from "rxjs"; import { distinctUntilChanged } from "rxjs/operators"; import { DEFAULT_VALUES, VALIDATE_KEY_VALUES } from "./input-camera.constants"; import { isValidKeyValue } from "./input-camera.validation"; import * as i0 from "@angular/core"; import * as i1 from "@taiga-ui/core"; import * as i2 from "@angular/forms"; import * as i3 from "@angular/common"; export class KwikUIInputCameraComponent { constructor() { this.buttonText = DEFAULT_VALUES.buttonText; this.disabled = DEFAULT_VALUES.disabled; this.focus = DEFAULT_VALUES.focus; this.formControl = new FormControl({}); this.formControlName = DEFAULT_VALUES.formControlName; this.icon = DEFAULT_VALUES.icon; this.id = DEFAULT_VALUES.id; this.invalid = DEFAULT_VALUES.invalid; this.mediaFiles = DEFAULT_VALUES.mediaFiles; this.properties = { readOnly: false }; this.showMediaFiles = DEFAULT_VALUES.showMediaFiles; this.size = DEFAULT_VALUES.size; this.type = DEFAULT_VALUES.type; this.validators = { required: true }; this.onClick = new EventEmitter(); this.getRemovedFile = new EventEmitter(); this.openDropdown = false; this.formGroup = new FormGroup({}); this.subscriptions = new Subscription(); } ngOnInit() { this.formGroup = new FormGroup({ [this.formControlName]: new FormControl(this.formControl) }); this.validators = Object.assign({}, this.validators); this.setDisabled(); this.mediaFiles = this.filterDuplicatesAndEmpty(this.mediaFiles); this.loadMediaFiles(this.mediaFiles); this.subscriptions.add(this.formGroup.controls[this.formControlName].valueChanges .pipe(distinctUntilChanged()) // makes sure the value has actually changed. .subscribe((value) => this.loadMediaFiles(value))); } ngOnChanges(changes) { const verifyChange = (key) => { return checkObjectKeyExists(changes, key) && !changes[key].firstChange; }; for (const change of Object.entries(changes)) { const key = change[0]; const value = change[1].currentValue; this.validateInputProperty(key, value); } if (verifyChange("formControl")) { this.formControl = changes.formControl.currentValue; } if (verifyChange("icon")) { this.icon = changes.icon.currentValue; } if (verifyChange("size")) { this.size = changes.size.currentValue; } if (verifyChange("type")) { this.type = changes.type.currentValue; } if (verifyChange("mediaFiles")) { this.mediaFiles = this.filterDuplicatesAndEmpty(changes.mediaFiles.currentValue); this.loadMediaFiles(this.mediaFiles); } if (verifyChange("disabled")) { this.disabled = changes.disabled.currentValue; this.setDisabled(); } } ngOnDestroy() { this.subscriptions.unsubscribe(); // ensure when component is destroyed the subscription is also and not left open. } validateInputProperty(key, value) { if (VALIDATE_KEY_VALUES[key] && !isValidKeyValue(key, value)) { this[key] = DEFAULT_VALUES[key]; } } /** * @description Handles setting up of error and focus on the input field is it is invalid */ setDisabled() { if (this.formGroup.controls[this.formControlName] !== undefined) { if (this.disabled === true) { this.formGroup.controls[this.formControlName].disable({ emitEvent: false }); } else { this.formGroup.controls[this.formControlName].enable({ emitEvent: false }); } } } /** * @description Handles setting up of error and focus on the input field is it is invalid */ setError() { if (this.formGroup.controls[this.formControlName] !== undefined && this.formGroup.controls[this.formControlName].invalid) { this.invalid = true; this.focus = true; } else { this.invalid = false; this.focus = false; } } loadMediaFiles(files) { if (!Array.isArray(files)) { files = [files]; } this.formGroup.controls[this.formControlName].patchValue(files, { emitEvent: false }); } filterDuplicatesAndEmpty(files) { const uniqueFiles = []; files = files.filter((file) => isNotEmptyValue(file)); files.forEach((file) => { const isDuplicate = uniqueFiles.some((existingFile) => existingFile === file); if (!isDuplicate) { uniqueFiles.push(file); } }); return uniqueFiles; } /** * @description Handles firing of 2 events on (keyup) event * * @param value */ handleOnClick(e) { this.emitEvent(this.onClick, e); } handleOnClickRemoveFile(mediaFile) { const mediaFiles = this.mediaFiles.filter((f) => { return !(f === mediaFile); }); this.emitEvent(this.getRemovedFile, { key: this.formControlName, value: mediaFile, mediaFiles }); } handleFocusedChange(e) { if (!this.invalid) { this.focus = e; } } emitEvent(event, data) { event.emit(data); } /** Method Implementations for Abstract Control */ writeValue(value) { } registerOnChange(fn) { } registerOnTouched(fn) { } setDisabledState(isDisabled) { } } /** @nocollapse */ KwikUIInputCameraComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.17", ngImport: i0, type: KwikUIInputCameraComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); /** @nocollapse */ KwikUIInputCameraComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.17", type: KwikUIInputCameraComponent, selector: "kwikui-input-camera", inputs: { buttonText: "buttonText", disabled: "disabled", focus: "focus", formControl: "formControl", formControlName: "formControlName", icon: "icon", id: "id", invalid: "invalid", mediaFiles: "mediaFiles", properties: "properties", showMediaFiles: "showMediaFiles", size: "size", type: "type", validators: "validators" }, outputs: { onClick: "onClick", getRemovedFile: "getRemovedFile" }, providers: [ { provide: NG_VALUE_ACCESSOR, useExisting: forwardRef((() => KwikUIInputCameraComponent)), multi: true } ], usesOnChanges: true, ngImport: i0, template: "<div\n [formGroup]=\"formGroup\"\n [id]=\"id\"\n class=\"input-camera-container\"\n>\n <div\n class=\"input-camera-button-container\"\n *ngIf=\"size === 's'\"\n >\n <button\n *ngIf=\"size === 's'\"\n tuiButton\n appearance=\"flat\"\n shape=\"square\"\n size=\"m\"\n [disabled]=\"formControl.disabled\"\n class=\"input-camera-button\"\n [class.button-small]=\"size === 's'\"\n (click)=\"handleOnClick($event)\"\n >\n <tui-svg [src]=\"icon\"></tui-svg>\n </button>\n <button\n *ngIf=\"showMediaFiles && size === 's'\"\n tuiButton\n appearance=\"flat\"\n shape=\"square\"\n size=\"m\"\n class=\"input-camera-media-added\"\n [class.button-small]=\"size === 's'\"\n [tuiDropdown]=\"mediaFiles.length > 0 ? MEDIA_ADDED : MEDIA_ADDED_NONE\"\n [tuiDropdownManual]=\"openDropdown\"\n (click)=\"openDropdown = !openDropdown\"\n >\n {{ mediaFiles.length }}\n </button>\n </div>\n\n <button\n *ngIf=\"size === 'm'\"\n [disabled]=\"formControl.disabled\"\n class=\"input-camera-button\"\n [class.button-medium]=\"size === 'm'\"\n (click)=\"handleOnClick($event)\"\n >\n <div>{{ buttonText }}</div>\n <tui-svg [src]=\"icon\"></tui-svg>\n </button>\n\n <button\n *ngIf=\"size === 'l'\"\n [disabled]=\"formControl.disabled\"\n class=\"input-camera-button\"\n [class.button-large]=\"size === 'l'\"\n (click)=\"handleOnClick($event)\"\n >\n <tui-svg [src]=\"icon\"></tui-svg>\n <div>{{ buttonText }}</div>\n </button>\n\n <ng-container *ngIf=\"size !== 's'\">\n <ng-container *ngIf=\"mediaFiles.length > 0 && showMediaFiles\">\n <ng-container *ngTemplateOutlet=\"MEDIA_ADDED\"></ng-container>\n </ng-container>\n <ng-container *ngIf=\"mediaFiles.length === 0 && showMediaFiles\">\n <ng-container *ngTemplateOutlet=\"MEDIA_ADDED_NONE\"></ng-container>\n </ng-container>\n </ng-container>\n</div>\n\n<ng-template #MEDIA_ADDED>\n <div\n class=\"media-added\"\n [class.small]=\"size === 's'\"\n [class.medium]=\"size === 'm'\"\n [class.large]=\"size === 'l'\"\n (click)=\"(null)\"\n >\n <ng-container *ngIf=\"type === 'capture'\">\n <ng-container *ngFor=\"let mediaFile of mediaFiles\">\n <div class=\"media-item-container\">\n <button\n *ngIf=\"!formControl.disabled\"\n tuiButton\n appearance=\"whiteblock\"\n shape=\"square\"\n size=\"s\"\n class=\"media-item-remove-button\"\n [tuiHint]=\"REMOVE_FILE_TOOPTIP\"\n (click)=\"handleOnClickRemoveFile(mediaFile)\"\n >\n <tui-svg src=\"tuiIconClose\"></tui-svg>\n </button>\n <img\n [src]=\"mediaFile\"\n class=\"media-image\"\n />\n </div>\n </ng-container>\n </ng-container>\n <ng-container *ngIf=\"type === 'record'\">\n <ng-container *ngFor=\"let mediaFile of mediaFiles\">\n <div class=\"media-item-container\">\n <button\n *ngIf=\"!formControl.disabled\"\n tuiButton\n appearance=\"whiteblock\"\n shape=\"square\"\n size=\"s\"\n class=\"media-item-remove-button\"\n [tuiHint]=\"REMOVE_FILE_TOOPTIP\"\n (click)=\"handleOnClickRemoveFile(mediaFile)\"\n >\n <tui-svg src=\"tuiIconClose\"></tui-svg>\n </button>\n <video\n controls\n class=\"media-video\"\n >\n <source [src]=\"mediaFile\" />\n Your browser does not support the video tag.\n </video>\n </div>\n </ng-container>\n </ng-container>\n </div>\n</ng-template>\n\n<ng-template #MEDIA_ADDED_NONE>\n <div\n *ngIf=\"showMediaFiles\"\n class=\"media-added-none\"\n (click)=\"(undefined)\"\n >\n No Media Added\n </div>\n</ng-template>\n\n<ng-template #REMOVE_FILE_TOOPTIP>\n <div> Remove File </div>\n</ng-template>\n", styles: [".input-camera-container{width:100%;display:flex;flex-direction:column;align-items:stretch;justify-content:flex-start;grid-gap:1rem;gap:1rem}.input-camera-container .input-camera-button-container{align-content:center;align-items:center;cursor:pointer;display:flex;flex-direction:row;font-size:1rem;font-weight:bold;gap:.25rem;grid-gap:.25rem;justify-content:center;width:-moz-fit-content;width:fit-content}.input-camera-container .input-camera-button-container .input-camera-media-added{border-radius:50%}.input-camera-container .input-camera-button{display:flex;flex-direction:row;align-content:center;justify-content:space-between;align-items:center;grid-gap:1rem;gap:1rem;padding:1rem;border-radius:.5rem;outline:none;border:1px dashed var(--tui-primary);color:var(--tui-primary);background:white;text-transform:lowercase;font-size:1rem;cursor:pointer;transform:scale(1);transition:1s linear ease}.input-camera-container .input-camera-button:hover:not(:disabled)>tui-svg{transition:1s linear ease;transform:scale(1.1)}.input-camera-container .input-camera-button:active>tui-svg{transition:1s linear ease;transform:scale(.95)}.input-camera-container .input-camera-button:disabled{opacity:.5;cursor:not-allowed}.input-camera-container .input-camera-button.button-small{border-radius:50%}.input-camera-container .input-camera-button.button-medium{padding:.75rem 1rem}.input-camera-container .input-camera-button.button-large{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:1.5rem 1rem}.media-added{display:flex;flex-direction:column;justify-content:flex-start;align-items:stretch;grid-gap:1rem;gap:1rem;padding:.15rem;border-radius:.5rem}.media-added .media-item-container{position:relative}.media-added .media-item-container .media-item-remove-button{position:absolute;right:.5rem;top:.5rem;border-radius:50%;z-index:2}.media-added .media-item-container .media-image{width:100%;height:auto;border-radius:5px;box-shadow:#00000005 0 1px 3px,#1b1f2326 0 0 0 1px}.media-added .media-item-container .media-video{width:100%;height:auto;border-radius:5px;box-shadow:#00000005 0 1px 3px,#1b1f2326 0 0 0 1px}.media-added-none{width:100%;border:1px solid lightgray;border-radius:.5rem;padding:.75rem 1rem;background-color:#f5f5f5;display:flex;flex-direction:row;justify-content:center;align-content:center;align-items:center}\n"], components: [{ type: i1.TuiButtonComponent, selector: "button[tuiButton], button[tuiIconButton], a[tuiButton], a[tuiIconButton]", inputs: ["appearance", "disabled", "icon", "iconRight", "shape", "showLoader", "size"] }, { type: i1.TuiSvgComponent, selector: "tui-svg", inputs: ["src"] }], directives: [{ type: i2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { type: i2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i1.TuiDropdownDirective, selector: "[tuiDropdown]:not(ng-container)", inputs: ["tuiDropdown"], exportAs: ["tuiDropdown"] }, { type: i1.TuiDropdownDriverDirective, selector: "[tuiDropdown]" }, { type: i1.TuiDropdownPositionDirective, selector: "[tuiDropdown]" }, { type: i1.TuiDropdownManualDirective, selector: "[tuiDropdown][tuiDropdownManual]", inputs: ["tuiDropdownManual"] }, { type: i3.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet"] }, { type: i3.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i1.TuiHintDirective, selector: "[tuiHint]:not(ng-container):not(ng-template)", inputs: ["tuiHint", "tuiHintContext", "tuiHintAppearance"] }, { type: i1.TuiHintDriverDirective, selector: "[tuiHint]:not(ng-container):not(ng-template)" }, { type: i1.TuiHintHoverDirective, selector: "[tuiHint]:not(ng-container):not(ng-template)", inputs: ["tuiHintShowDelay", "tuiHintHideDelay"], exportAs: ["tuiHintHover"] }, { type: i1.TuiHintPositionDirective, selector: "[tuiHint]:not(ng-container):not(ng-template)", inputs: ["tuiHintDirection"] }] }); __decorate([ logMethod ], KwikUIInputCameraComponent.prototype, "ngOnChanges", null); __decorate([ logMethod ], KwikUIInputCameraComponent.prototype, "loadMediaFiles", null); __decorate([ logMethod ], KwikUIInputCameraComponent.prototype, "filterDuplicatesAndEmpty", null); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.17", ngImport: i0, type: KwikUIInputCameraComponent, decorators: [{ type: Component, args: [{ selector: "kwikui-input-camera", templateUrl: "./input-camera.component.html", styleUrls: ["./input-camera.component.scss"], providers: [ { provide: NG_VALUE_ACCESSOR, useExisting: forwardRef((() => KwikUIInputCameraComponent)), multi: true } ] }] }], propDecorators: { buttonText: [{ type: Input }], disabled: [{ type: Input }], focus: [{ type: Input }], formControl: [{ type: Input }], formControlName: [{ type: Input }], icon: [{ type: Input }], id: [{ type: Input }], invalid: [{ type: Input }], mediaFiles: [{ type: Input }], properties: [{ type: Input }], showMediaFiles: [{ type: Input }], size: [{ type: Input }], type: [{ type: Input }], validators: [{ type: Input }], onClick: [{ type: Output }], getRemovedFile: [{ type: Output }], ngOnChanges: [], loadMediaFiles: [], filterDuplicatesAndEmpty: [] } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5wdXQtY2FtZXJhLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL2t3aWtpZC1jYW1lcmEvc3JjL2xpYi9jb21wb25lbnRzL2t3aWt1aS1pbnB1dC1jYW1lcmEvaW5wdXQtY2FtZXJhLmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL2t3aWtpZC1jYW1lcmEvc3JjL2xpYi9jb21wb25lbnRzL2t3aWt1aS1pbnB1dC1jYW1lcmEvaW5wdXQtY2FtZXJhLmNvbXBvbmVudC5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQSxzQ0FBc0M7QUFDdEMseURBQXlEO0FBQ3pELHNEQUFzRDtBQUN0RCxnQ0FBZ0M7QUFDaEMsT0FBTyxFQUNMLFNBQVMsRUFDVCxZQUFZLEVBQ1osS0FBSyxFQUdMLE1BQU0sRUFFTixVQUFVLEVBQ1gsTUFBTSxlQUFlLENBQUM7QUFDdkIsT0FBTyxFQUVMLFdBQVcsRUFDWCxTQUFTLEVBQ1QsaUJBQWlCLEVBQ2xCLE1BQU0sZ0JBQWdCLENBQUM7QUFDeEIsT0FBTyxFQUNMLG9CQUFvQixFQUNwQixlQUFlLEVBQ2YsU0FBUyxFQUNWLE1BQU0sZ0JBQWdCLENBQUM7QUFDeEIsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUNwQyxPQUFPLEVBQUUsb0JBQW9CLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUN0RCxPQUFPLEVBQUUsY0FBYyxFQUFFLG1CQUFtQixFQUFFLE1BQU0sMEJBQTBCLENBQUM7QUFLL0UsT0FBTyxFQUFFLGVBQWUsRUFBRSxNQUFNLDJCQUEyQixDQUFDOzs7OztBQWM1RCxNQUFNLE9BQU8sMEJBQTBCO0lBWnZDO1FBZVcsZUFBVSxHQUFXLGNBQWMsQ0FBQyxVQUFVLENBQUM7UUFFL0MsYUFBUSxHQUFZLGNBQWMsQ0FBQyxRQUFRLENBQUM7UUFFNUMsVUFBSyxHQUFZLGNBQWMsQ0FBQyxLQUFL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QVosS0FBSztnQkFFRyxJQUFJO3NCQUFaLEtBQUs7Z0JBRUcsVUFBVTtzQkFBbEIsS0FBSztnQkFFSSxPQUFPO3NCQUFoQixNQUFNO2dCQUVHLGNBQWM7c0JBQXZCLE1BQU07Z0JBMEJQLFdBQVcsTUFpRlgsY0FBYyxNQVdkLHdCQUF3QiIsInNvdXJjZXNDb250ZW50IjpbIi8qIGVzbGludC1kaXNhYmxlIG5vLWVtcHR5LWZ1bmN0aW9uICovXG4vKiBlc2xpbnQtZGlzYWJsZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tZW1wdHktZnVuY3Rpb24gKi9cbi8qIGVzbGludC1kaXNhYmxlIEB0eXBlc2NyaXB0LWVzbGludC9uby11bnVzZWQtdmFycyAqL1xuLyogZXNsaW50LWRpc2FibGUgYnJhY2Utc3R5bGUgKi9cbmltcG9ydCB7XG4gIENvbXBvbmVudCxcbiAgRXZlbnRFbWl0dGVyLFxuICBJbnB1dCxcbiAgT25DaGFuZ2VzLFxuICBPbkluaXQsXG4gIE91dHB1dCxcbiAgU2ltcGxlQ2hhbmdlcyxcbiAgZm9yd2FyZFJlZlxufSBmcm9tIFwiQGFuZ3VsYXIvY29yZVwiO1xuaW1wb3J0IHtcbiAgQ29udHJvbFZhbHVlQWNjZXNzb3IsXG4gIEZvcm1Db250cm9sLFxuICBGb3JtR3JvdXAsXG4gIE5HX1ZBTFVFX0FDQ0VTU09SXG59IGZyb20gXCJAYW5ndWxhci9mb3Jtc1wiO1xuaW1wb3J0IHtcbiAgY2hlY2tPYmplY3RLZXlFeGlzdHMsXG4gIGlzTm90RW1wdHlWYWx1ZSxcbiAgbG9nTWV0aG9kXG59IGZyb20gXCJrd2lraWQtdG9vbGtpdFwiO1xuaW1wb3J0IHsgU3Vic2NyaXB0aW9uIH0gZnJvbSBcInJ4anNcIjtcbmltcG9ydCB7IGRpc3RpbmN0VW50aWxDaGFuZ2VkIH0gZnJvbSBcInJ4anMvb3BlcmF0b3JzXCI7XG5pbXBvcnQgeyBERUZBVUxUX1ZBTFVFUywgVkFMSURBVEVfS0VZX1ZBTFVFUyB9IGZyb20gXCIuL2lucHV0LWNhbWVyYS5jb25zdGFudHNcIjtcbmltcG9ydCB7XG4gIFRLd2lrVUlJbnB1dENhbWVyYVNpemUsXG4gIFRLd2lrVUlJbnB1dENhbWVyYVR5cGVcbn0gZnJvbSBcIi4vaW5wdXQtY2FtZXJhLmRlZmluaXRpb25zXCI7XG5pbXBvcnQgeyBpc1ZhbGlkS2V5VmFsdWUgfSBmcm9tIFwiLi9pbnB1dC1jYW1lcmEudmFsaWRhdGlvblwiO1xuXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6IFwia3dpa3VpLWlucHV0LWNhbWVyYVwiLFxuICB0ZW1wbGF0ZVVybDogXCIuL2lucHV0LWNhbWVyYS5jb21wb25lbnQuaHRtbFwiLFxuICBzdHlsZVVybHM6IFtcIi4vaW5wdXQtY2FtZXJhLmNvbXBvbmVudC5zY3NzXCJdLFxuICBwcm92aWRlcnM6IFtcbiAgICB7XG4gICAgICBwcm92aWRlOiBOR19WQUxVRV9BQ0NFU1NPUixcbiAgICAgIHVzZUV4aXN0aW5nOiBmb3J3YXJkUmVmKCgpID0+IEt3aWtVSUlucHV0Q2FtZXJhQ29tcG9uZW50KSxcbiAgICAgIG11bHRpOiB0cnVlXG4gICAgfVxuICBdXG59KVxuZXhwb3J0IGNsYXNzIEt3aWtVSUlucHV0Q2FtZXJhQ29tcG9uZW50XG4gIGltcGxlbWVudHMgT25Jbml0LCBPbkNoYW5nZXMsIENvbnRyb2xWYWx1ZUFjY2Vzc29yXG57XG4gIEBJbnB1dCgpIGJ1dHRvblRleHQ6IHN0cmluZyA9IERFRkFVTFRfVkFMVUVTLmJ1dHRvblRleHQ7XG5cbiAgQElucHV0KCkgZGlzYWJsZWQ6IGJvb2xlYW4gPSBERUZBVUxUX1ZBTFVFUy5kaXNhYmxlZDtcblxuICBASW5wdXQoKSBmb2N1czogYm9vbGVhbiA9IERFRkFVTFRfVkFMVUVTLmZvY3VzO1xuXG4gIEBJbnB1dCgpIGZvcm1Db250cm9sOiBGb3JtQ29udHJvbCA9IG5ldyBGb3JtQ29udHJvbCh7fSk7XG5cbiAgQElucHV0KCkgZm9ybUNvbnRyb2xOYW1lOiBzdHJpbmcgPSBERUZBVUxUX1ZBTFVFUy5mb3JtQ29udHJvbE5hbWU7XG5cbiAgQElucHV0KCkgaWNvbjogc3RyaW5nID0gREVGQVVMVF9WQUxVRVMuaWNvbjtcblxuICBASW5wdXQoKSBpZDogc3RyaW5nID0gREVGQVVMVF9WQUxVRVMuaWQ7XG5cbiAgQElucHV0KCkgaW52YWxpZDogYm9vbGVhbiA9IERFRkFVTFRfVkFMVUVTLmludmFsaWQ7XG5cbiAgQElucHV0KCkgbWVkaWFGaWxlczogYW55W10gPSBERUZBVUxUX1ZBTFVFUy5tZWRpYUZpbGVzO1xuXG4gIEBJbnB1dCgpIHByb3BlcnRpZXMgPSB7IHJlYWRPbmx5OiBmYWxzZSB9O1xuXG4gIEBJbnB1dCgpIHNob3dNZWRpYUZpbGVzOiBib29sZWFuID0gREVGQVVMVF9WQUxVRVMuc2hvd01lZGlhRmlsZXM7XG5cbiAgQElucHV0KCkgc2l6ZTogVEt3aWtVSUlucHV0Q2FtZXJhU2l6ZSA9IERFRkFVTFRfVkFMVUVTLnNpemU7XG5cbiAgQElucHV0KCkgdHlwZTogVEt3aWtVSUlucHV0Q2FtZXJhVHlwZSA9IERFRkFVTFRfVkFMVUVTLnR5cGU7XG5cbiAgQElucHV0KCkgdmFsaWRhdG9ycyA9IHsgcmVxdWlyZWQ6IHRydWUgfTtcblxuICBAT3V0cHV0KCkgb25DbGljazogRXZlbnRFbWl0dGVyPGFueT4gPSBuZXcgRXZlbnRFbWl0dGVyPGFueT4oKTtcblxuICBAT3V0cHV0KCkgZ2V0UmVtb3ZlZEZpbGU6IEV2ZW50RW1pdHRlcjxhbnk+ID0gbmV3IEV2ZW50RW1pdHRlcjxhbnk+KCk7XG5cbiAgb3BlbkRyb3Bkb3duID0gZmFsc2U7XG5cbiAgZm9ybUdyb3VwOiBGb3JtR3JvdXAgPSBuZXcgRm9ybUdyb3VwKHt9KTtcblxuICBzdWJzY3JpcHRpb25zID0gbmV3IFN1YnNjcmlwdGlvbigpO1xuXG4gIG5nT25Jbml0KCk6IHZvaWQge1xuICAgIHRoaXMuZm9ybUdyb3VwID0gbmV3IEZvcm1Hcm91cCh7XG4gICAgICBbdGhpcy5mb3JtQ29udHJvbE5hbWVdOiBuZXcgRm9ybUNvbnRyb2wodGhpcy5mb3JtQ29udHJvbClcbiAgICB9KTtcbiAgICB0aGlzLnZhbGlkYXRvcnMgPSB7IC4uLnRoaXMudmFsaWRhdG9ycyB9O1xuICAgIHRoaXMuc2V0RGlzYWJsZWQoKTtcblxuICAgIHRoaXMubWVkaWFGaWxlcyA9IHRoaXMuZmlsdGVyRHVwbGljYXRlc0FuZEVtcHR5KHRoaXMubWVkaWFGaWxlcyk7XG4gICAgdGhpcy5sb2FkTWVkaWFGaWxlcyh0aGlzLm1lZGlhRmlsZXMpO1xuXG4gICAgdGhpcy5zdWJzY3JpcHRpb25zLmFkZChcbiAgICAgIHRoaXMuZm9ybUdyb3VwLmNvbnRyb2xzW3RoaXMuZm9ybUNvbnRyb2xOYW1lXS52YWx1ZUNoYW5nZXNcbiAgICAgICAgLnBpcGUoZGlzdGluY3RVbnRpbENoYW5nZWQoKSkgLy8gbWFrZXMgc3VyZSB0aGUgdmFsdWUgaGFzIGFjdHVhbGx5IGNoYW5nZWQuXG4gICAgICAgIC5zdWJzY3JpYmUoKHZhbHVlKSA9PiB0aGlzLmxvYWRNZWRpYUZpbGVzKHZhbHVlKSlcbiAgICApO1xuICB9XG5cbiAgQGxvZ01ldGhvZFxuICBuZ09uQ2hhbmdlcyhjaGFuZ2VzOiBTaW1wbGVDaGFuZ2VzKSB7XG4gICAgY29uc3QgdmVyaWZ5Q2hhbmdlID0gKGtleTogc3RyaW5nKSA9PiB7XG4gICAgICByZXR1cm4gY2hlY2tPYmplY3RLZXlFeGlzdHMoY2hhbmdlcywga2V5KSAmJiAhY2hhbmdlc1trZXldLmZpcnN0Q2hhbmdlO1xuICAgIH07XG5cbiAgICBmb3IgKGNvbnN0IGNoYW5nZSBvZiBPYmplY3QuZW50cmllcyhjaGFuZ2VzKSkge1xuICAgICAgY29uc3Qga2V5OiBzdHJpbmcgPSBjaGFuZ2VbMF07XG4gICAgICBjb25zdCB2YWx1ZTogYW55ID0gY2hhbmdlWzFdLmN1cnJlbnRWYWx1ZTtcbiAgICAgIHRoaXMudmFsaWRhdGVJbnB1dFByb3BlcnR5KGtleSwgdmFsdWUpO1xuICAgIH1cblxuICAgIGlmICh2ZXJpZnlDaGFuZ2UoXCJmb3JtQ29udHJvbFwiKSkge1xuICAgICAgdGhpcy5mb3JtQ29udHJvbCA9IGNoYW5nZXMuZm9ybUNvbnRyb2wuY3VycmVudFZhbHVlO1xuICAgIH1cbiAgICBpZiAodmVyaWZ5Q2hhbmdlKFwiaWNvblwiKSkge1xuICAgICAgdGhpcy5pY29uID0gY2hhbmdlcy5pY29uLmN1cnJlbnRWYWx1ZTtcbiAgICB9XG4gICAgaWYgKHZlcmlmeUNoYW5nZShcInNpemVcIikpIHtcbiAgICAgIHRoaXMuc2l6ZSA9IGNoYW5nZXMuc2l6ZS5jdXJyZW50VmFsdWU7XG4gICAgfVxuICAgIGlmICh2ZXJpZnlDaGFuZ2UoXCJ0eXBlXCIpKSB7XG4gICAgICB0aGlzLnR5cGUgPSBjaGFuZ2VzLnR5cGUuY3VycmVudFZhbHVlO1xuICAgIH1cbiAgICBpZiAodmVyaWZ5Q2hhbmdlKFwibWVkaWFGaWxlc1wiKSkge1xuICAgICAgdGhpcy5tZWRpYUZpbGVzID0gdGhpcy5maWx0ZXJEdXBsaWNhdGVzQW5kRW1wdHkoXG4gICAgICAgIGNoYW5nZXMubWVkaWFGaWxlcy5jdXJyZW50VmFsdWVcbiAgICAgICk7XG4gICAgICB0aGlzLmxvYWRNZWRpYUZpbGVzKHRoaXMubWVkaWFGaWxlcyk7XG4gICAgfVxuICAgIGlmICh2ZXJpZnlDaGFuZ2UoXCJkaXNhYmxlZFwiKSkge1xuICAgICAgdGhpcy5kaXNhYmxlZCA9IGNoYW5nZXMuZGlzYWJsZWQuY3VycmVudFZhbHVlO1xuXG4gICAgICB0aGlzLnNldERpc2FibGVkKCk7XG4gICAgfVxuICB9XG5cbiAgbmdPbkRlc3Ryb3koKTogdm9pZCB7XG4gICAgdGhpcy5zdWJzY3JpcHRpb25zLnVuc3Vic2NyaWJlKCk7XG4gICAgLy8gZW5zdXJlIHdoZW4gY29tcG9uZW50IGlzIGRlc3Ryb3llZCB0aGUgc3Vic2NyaXB0aW9uIGlzIGFsc28gYW5kIG5vdCBsZWZ0IG9wZW4uXG4gIH1cblxuICBwcml2YXRlIHZhbGlkYXRlSW5wdXRQcm9wZXJ0eShrZXk6IHN0cmluZywgdmFsdWU6IGFueSk6IHZvaWQge1xuICAgIGlmIChWQUxJREFURV9LRVlfVkFMVUVTW2tleV0gJiYgIWlzVmFsaWRLZXlWYWx1ZShrZXksIHZhbHVlKSkge1xuICAgICAgdGhpc1trZXldID0gREVGQVVMVF9WQUxVRVNba2V5XTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIEhhbmRsZXMgc2V0dGluZyB1cCBvZiBlcnJvciBhbmQgZm9jdXMgb24gdGhlIGlucHV0IGZpZWxkIGlzIGl0IGlzIGludmFsaWRcbiAgICovXG4gIHNldERpc2FibGVkKCkge1xuICAgIGlmICh0aGlzLmZvcm1Hcm91cC5jb250cm9sc1t0aGlzLmZvcm1Db250cm9sTmFtZV0gIT09IHVuZGVmaW5lZCkge1xuICAgICAgaWYgKHRoaXMuZGlzYWJsZWQgPT09IHRydWUpIHtcbiAgICAgICAgdGhpcy5mb3JtR3JvdXAuY29udHJvbHNbdGhpcy5mb3JtQ29udHJvbE5hbWVdLmRpc2FibGUoe1xuICAgICAgICAgIGVtaXRFdmVudDogZmFsc2VcbiAgICAgICAgfSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aGlzLmZvcm1Hcm91cC5jb250cm9sc1t0aGlzLmZvcm1Db250cm9sTmFtZV0uZW5hYmxlKHtcbiAgICAgICAgICBlbWl0RXZlbnQ6IGZhbHNlXG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gSGFuZGxlcyBzZXR0aW5nIHVwIG9mIGVycm9yIGFuZCBmb2N1cyBvbiB0aGUgaW5wdXQgZmllbGQgaXMgaXQgaXMgaW52YWxpZFxuICAgKi9cbiAgc2V0RXJyb3IoKSB7XG4gICAgaWYgKFxuICAgICAgdGhpcy5mb3JtR3JvdXAuY29udHJvbHNbdGhpcy5mb3JtQ29udHJvbE5hbWVdICE9PSB1bmRlZmluZWQgJiZcbiAgICAgIHRoaXMuZm9ybUdyb3VwLmNvbnRyb2xzW3RoaXMuZm9ybUNvbnRyb2xOYW1lXS5pbnZhbGlkXG4gICAgKSB7XG4gICAgICB0aGlzLmludmFsaWQgPSB0cnVlO1xuICAgICAgdGhpcy5mb2N1cyA9IHRydWU7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMuaW52YWxpZCA9IGZhbHNlO1xuICAgICAgdGhpcy5mb2N1cyA9IGZhbHNlO1xuICAgIH1cbiAgfVxuXG4gIEBsb2dNZXRob2RcbiAgbG9hZE1lZGlhRmlsZXMoZmlsZXM6IGFueVtdKSB7XG4gICAgaWYgKCFBcnJheS5pc0FycmF5KGZpbGVzKSkge1xuICAgICAgZmlsZXMgPSBbZmlsZXNdO1xuICAgIH1cblxuICAgIHRoaXMuZm9ybUdyb3VwLmNvbnRyb2xzW3RoaXMuZm9ybUNvbnRyb2xOYW1lXS5wYXRjaFZhbHVlKGZpbGVzLCB7XG4gICAgICBlbWl0RXZlbnQ6IGZhbHNlXG4gICAgfSk7XG4gIH1cblxuICBAbG9nTWV0aG9kXG4gIGZpbHRlckR1cGxpY2F0ZXNBbmRFbXB0eShmaWxlczogYW55W10pOiBhbnlbXSB7XG4gICAgY29uc3QgdW5pcXVlRmlsZXM6IGFueVtdID0gW107XG5cbiAgICBmaWxlcyA9IGZpbGVzLmZpbHRlcigoZmlsZSkgPT4gaXNOb3RFbXB0eVZhbHVlKGZpbGUpKTtcblxuICAgIGZpbGVzLmZvckVhY2goKGZpbGUpID0+IHtcbiAgICAgIGNvbnN0IGlzRHVwbGljYXRlID0gdW5pcXVlRmlsZXMuc29tZShcbiAgICAgICAgKGV4aXN0aW5nRmlsZSkgPT4gZXhpc3RpbmdGaWxlID09PSBmaWxlXG4gICAgICApO1xuXG4gICAgICBpZiAoIWlzRHVwbGljYXRlKSB7XG4gICAgICAgIHVuaXF1ZUZpbGVzLnB1c2goZmlsZSk7XG4gICAgICB9XG4gICAgfSk7XG5cbiAgICByZXR1cm4gdW5pcXVlRmlsZXM7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIEhhbmRsZXMgZmlyaW5nIG9mIDIgZXZlbnRzIG9uIChrZXl1cCkgZXZlbnRcbiAgICpcbiAgICogQHBhcmFtIHZhbHVlXG4gICAqL1xuICBoYW5kbGVPbkNsaWNrKGU6IGFueSkge1xuICAgIHRoaXMuZW1pdEV2ZW50KHRoaXMub25DbGljaywgZSk7XG4gIH1cblxuICBoYW5kbGVPbkNsaWNrUmVtb3ZlRmlsZShtZWRpYUZpbGU6IGFueSkge1xuICAgIGNvbnN0IG1lZGlhRmlsZXMgPSB0aGlzLm1lZGlhRmlsZXMuZmlsdGVyKChmOiBhbnkpID0+IHtcbiAgICAgIHJldHVybiAhKGYgPT09IG1lZGlhRmlsZSk7XG4gICAgfSk7XG5cbiAgICB0aGlzLmVtaXRFdmVudCh0aGlzLmdldFJlbW92ZWRGaWxlLCB7XG4gICAgICBrZXk6IHRoaXMuZm9ybUNvbnRyb2xOYW1lLFxuICAgICAgdmFsdWU6IG1lZGlhRmlsZSxcbiAgICAgIG1lZGlhRmlsZXNcbiAgICB9KTtcbiAgfVxuXG4gIGhhbmRsZUZvY3VzZWRDaGFuZ2UoZTogYW55KSB7XG4gICAgaWYgKCF0aGlzLmludmFsaWQpIHtcbiAgICAgIHRoaXMuZm9jdXMgPSBlO1xuICAgIH1cbiAgfVxuXG4gIGVtaXRFdmVudChldmVudDogYW55LCBkYXRhOiBhbnkpIHtcbiAgICBldmVudC5lbWl0KGRhdGEpO1xuICB9XG5cbiAgLyoqIE1ldGhvZCBJbXBsZW1lbnRhdGlvbnMgZm9yIEFic3RyYWN0IENvbnRyb2wgKi9cbiAgd3JpdGVWYWx1ZSh2YWx1ZTogYW55KTogdm9pZCB7fVxuXG4gIHJlZ2lzdGVyT25DaGFuZ2UoZm46IGFueSk6IHZvaWQge31cblxuICByZWdpc3Rlck9uVG91Y2hlZChmbjogYW55KTogdm9pZCB7fVxuXG4gIHNldERpc2FibGVkU3RhdGU/KGlzRGlzYWJsZWQ6IGJvb2xlYW4pOiB2b2lkIHt9XG59XG4iLCI8ZGl2XG4gIFtmb3JtR3JvdXBdPVwiZm9ybUdyb3VwXCJcbiAgW2lkXT1cImlkXCJcbiAgY2xhc3M9XCJpbnB1dC1jYW1lcmEtY29udGFpbmVyXCJcbj5cbiAgPGRpdlxuICAgIGNsYXNzPVwiaW5wdXQtY2FtZXJhLWJ1dHRvbi1jb250YWluZXJcIlxuICAgICpuZ0lmPVwic2l6ZSA9PT0gJ3MnXCJcbiAgPlxuICAgIDxidXR0b25cbiAgICAgICpuZ0lmPVwic2l6ZSA9PT0gJ3MnXCJcbiAgICAgIHR1aUJ1dHRvblxuICAgICAgYXBwZWFyYW5jZT1cImZsYXRcIlxuICAgICAgc2hhcGU9XCJzcXVhcmVcIlxuICAgICAgc2l6ZT1cIm1cIlxuICAgICAgW2Rpc2FibGVkXT1cImZvcm1Db250cm9sLmRpc2FibGVkXCJcbiAgICAgIGNsYXNzPVwiaW5wdXQtY2FtZXJhLWJ1dHRvblwiXG4gICAgICBbY2xhc3MuYnV0dG9uLXNtYWxsXT1cInNpemUgPT09ICdzJ1wiXG4gICAgICAoY2xpY2spPVwiaGFuZGxlT25DbGljaygkZXZlbnQpXCJcbiAgICA+XG4gICAgICA8dHVpLXN2ZyBbc3JjXT1cImljb25cIj48L3R1aS1zdmc+XG4gICAgPC9idXR0b24+XG4gICAgPGJ1dHRvblxuICAgICAgKm5nSWY9XCJzaG93TWVkaWFGaWxlcyAmJiBzaXplID09PSAncydcIlxuICAgICAgdHVpQnV0dG9uXG4gICAgICBhcHBlYXJhbmNlPVwiZmxhdFwiXG4gICAgICBzaGFwZT1cInNxdWFyZVwiXG4gICAgICBzaXplPVwibVwiXG4gICAgICBjbGFzcz1cImlucHV0LWNhbWVyYS1tZWRpYS1hZGRlZFwiXG4gICAgICBbY2xhc3MuYnV0dG9uLXNtYWxsXT1cInNpemUgPT09ICdzJ1wiXG4gICAgICBbdHVpRHJvcGRvd25dPVwibWVkaWFGaWxlcy5sZW5ndGggPiAwID8gTUVESUFfQURERUQgOiBNRURJQV9BRERFRF9OT05FXCJcbiAgICAgIFt0dWlEcm9wZG93bk1hbnVhbF09XCJvcGVuRHJvcGRvd25cIlxuICAgICAgKGNsaWNrKT1cIm9wZW5Ecm9wZG93biA9ICFvcGVuRHJvcGRvd25cIlxuICAgID5cbiAgICAgIHt7IG1lZGlhRmlsZXMubGVuZ3RoIH19XG4gICAgPC9idXR0b24+XG4gIDwvZGl2PlxuXG4gIDxidXR0b25cbiAgICAqbmdJZj1cInNpemUgPT09ICdtJ1wiXG4gICAgW2Rpc2FibGVkXT1cImZvcm1Db250cm9sLmRpc2FibGVkXCJcbiAgICBjbGFzcz1cImlucHV0LWNhbWVyYS1idXR0b25cIlxuICAgIFtjbGFzcy5idXR0b24tbWVkaXVtXT1cInNpemUgPT09ICdtJ1wiXG4gICAgKGNsaWNrKT1cImhhbmRsZU9uQ2xpY2soJGV2ZW50KVwiXG4gID5cbiAgICA8ZGl2Pnt7IGJ1dHRvblRleHQgfX08L2Rpdj5cbiAgICA8dHVpLXN2ZyBbc3JjXT1cImljb25cIj48L3R1aS1zdmc+XG4gIDwvYnV0dG9uPlxuXG4gIDxidXR0b25cbiAgICAqbmdJZj1cInNpemUgPT09ICdsJ1wiXG4gICAgW2Rpc2FibGVkXT1cImZvcm1Db250cm9sLmRpc2FibGVkXCJcbiAgICBjbGFzcz1cImlucHV0LWNhbWVyYS1idXR0b25cIlxuICAgIFtjbGFzcy5idXR0b24tbGFyZ2VdPVwic2l6ZSA9PT0gJ2wnXCJcbiAgICAoY2xpY2spPVwiaGFuZGxlT25DbGljaygkZXZlbnQpXCJcbiAgPlxuICAgIDx0dWktc3ZnIFtzcmNdPVwiaWNvblwiPjwvdHVpLXN2Zz5cbiAgICA8ZGl2Pnt7IGJ1dHRvblRleHQgfX08L2Rpdj5cbiAgPC9idXR0b24+XG5cbiAgPG5nLWNvbnRhaW5lciAqbmdJZj1cInNpemUgIT09ICdzJ1wiPlxuICAgIDxuZy1jb250YWluZXIgKm5nSWY9XCJtZWRpYUZpbGVzLmxlbmd0aCA+IDAgJiYgc2hvd01lZGlhRmlsZXNcIj5cbiAgICAgIDxuZy1jb250YWluZXIgKm5nVGVtcGxhdGVPdXRsZXQ9XCJNRURJQV9BRERFRFwiPjwvbmctY29udGFpbmVyPlxuICAgIDwvbmctY29udGFpbmVyPlxuICAgIDxuZy1jb250YWluZXIgKm5nSWY9XCJtZWRpYUZpbGVzLmxlbmd0aCA9PT0gMCAmJiBzaG93TWVkaWFGaWxlc1wiPlxuICAgICAgPG5nLWNvbnRhaW5lciAqbmdUZW1wbGF0ZU91dGxldD1cIk1FRElBX0FEREVEX05PTkVcIj48L25nLWNvbnRhaW5lcj5cbiAgICA8L25nLWNvbnRhaW5lcj5cbiAgPC9uZy1jb250YWluZXI+XG48L2Rpdj5cblxuPG5nLXRlbXBsYXRlICNNRURJQV9BRERFRD5cbiAgPGRpdlxuICAgIGNsYXNzPVwibWVkaWEtYWRkZWRcIlxuICAgIFtjbGFzcy5zbWFsbF09XCJzaXplID09PSAncydcIlxuICAgIFtjbGFzcy5tZWRpdW1dPVwic2l6ZSA9PT0gJ20nXCJcbiAgICBbY2xhc3MubGFyZ2VdPVwic2l6ZSA9PT0gJ2wnXCJcbiAgICAoY2xpY2spPVwiKG51bGwpXCJcbiAgPlxuICAgIDxuZy1jb250YWluZXIgKm5nSWY9XCJ0eXBlID09PSAnY2FwdHVyZSdcIj5cbiAgICAgIDxuZy1jb250YWluZXIgKm5nRm9yPVwibGV0IG1lZGlhRmlsZSBvZiBtZWRpYUZpbGVzXCI+XG4gICAgICAgIDxkaXYgY2xhc3M9XCJtZWRpYS1pdGVtLWNvbnRhaW5lclwiPlxuICAgICAgICAgIDxidXR0b25cbiAgICAgICAgICAgICpuZ0lmPVwiIWZvcm1Db250cm9sLmRpc2FibGVkXCJcbiAgICAgICAgICAgIHR1aUJ1dHRvblxuICAgICAgICAgICAgYXBwZWFyYW5jZT1cIndoaXRlYmxvY2tcIlxuICAgICAgICAgICAgc2hhcGU9XCJzcXVhcmVcIlxuICAgICAgICAgICAgc2l6ZT1cInNcIlxuICAgICAgICAgICAgY2xhc3M9XCJtZWRpYS1pdGVtLXJlbW92ZS1idXR0b25cIlxuICAgICAgICAgICAgW3R1aUhpbnRdPVwiUkVNT1ZFX0ZJTEVfVE9PUFRJUFwiXG4gICAgICAgICAgICAoY2xpY2spPVwiaGFuZGxlT25DbGlja1JlbW92ZUZpbGUobWVkaWFGaWxlKVwiXG4gICAgICAgICAgPlxuICAgICAgICAgICAgPHR1aS1zdmcgc3JjPVwidHVpSWNvbkNsb3NlXCI+PC90dWktc3ZnPlxuICAgICAgICAgIDwvYnV0dG9uPlxuICAgICAgICAgIDxpbWdcbiAgICAgICAgICAgIFtzcmNdPVwibWVkaWFGaWxlXCJcbiAgICAgICAgICAgIGNsYXNzPVwibWVkaWEtaW1hZ2VcIlxuICAgICAgICAgIC8+XG4gICAgICAgIDwvZGl2PlxuICAgICAgPC9uZy1jb250YWluZXI+XG4gICAgPC9uZy1jb250YWluZXI+XG4gICAgPG5nLWNvbnRhaW5lciAqbmdJZj1cInR5cGUgPT09ICdyZWNvcmQnXCI+XG4gICAgICA8bmctY29udGFpbmVyICpuZ0Zvcj1cImxldCBtZWRpYUZpbGUgb2YgbWVkaWFGaWxlc1wiPlxuICAgICAgICA8ZGl2IGNsYXNzPVwibWVkaWEtaXRlbS1jb250YWluZXJcIj5cbiAgICAgICAgICA8YnV0dG9uXG4gICAgICAgICAgICAqbmdJZj1cIiFmb3JtQ29udHJvbC5kaXNhYmxlZFwiXG4gICAgICAgICAgICB0dWlCdXR0b25cbiAgICAgICAgICAgIGFwcGVhcmFuY2U9XCJ3aGl0ZWJsb2NrXCJcbiAgICAgICAgICAgIHNoYXBlPVwic3F1YXJlXCJcbiAgICAgICAgICAgIHNpemU9XCJzXCJcbiAgICAgICAgICAgIGNsYXNzPVwibWVkaWEtaXRlbS1yZW1vdmUtYnV0dG9uXCJcbiAgICAgICAgICAgIFt0dWlIaW50XT1cIlJFTU9WRV9GSUxFX1RPT1BUSVBcIlxuICAgICAgICAgICAgKGNsaWNrKT1cImhhbmRsZU9uQ2xpY2tSZW1vdmVGaWxlKG1lZGlhRmlsZSlcIlxuICAgICAgICAgID5cbiAgICAgICAgICAgIDx0dWktc3ZnIHNyYz1cInR1aUljb25DbG9zZVwiPjwvdHVpLXN2Zz5cbiAgICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgICA8dmlkZW9cbiAgICAgICAgICAgIGNvbnRyb2xzXG4gICAgICAgICAgICBjbGFzcz1cIm1lZGlhLXZpZGVvXCJcbiAgICAgICAgICA+XG4gICAgICAgICAgICA8c291cmNlIFtzcmNdPVwibWVkaWFGaWxlXCIgLz5cbiAgICAgICAgICAgIFlvdXIgYnJvd3NlciBkb2VzIG5vdCBzdXBwb3J0IHRoZSB2aWRlbyB0YWcuXG4gICAgICAgICAgPC92aWRlbz5cbiAgICAgICAgPC9kaXY+XG4gICAgICA8L25nLWNvbnRhaW5lcj5cbiAgICA8L25nLWNvbnRhaW5lcj5cbiAgPC9kaXY+XG48L25nLXRlbXBsYXRlPlxuXG48bmctdGVtcGxhdGUgI01FRElBX0FEREVEX05PTkU+XG4gIDxkaXZcbiAgICAqbmdJZj1cInNob3dNZWRpYUZpbGVzXCJcbiAgICBjbGFzcz1cIm1lZGlhLWFkZGVkLW5vbmVcIlxuICAgIChjbGljayk9XCIodW5kZWZpbmVkKVwiXG4gID5cbiAgICBObyBNZWRpYSBBZGRlZFxuICA8L2Rpdj5cbjwvbmctdGVtcGxhdGU+XG5cbjxuZy10ZW1wbGF0ZSAjUkVNT1ZFX0ZJTEVfVE9PUFRJUD5cbiAgPGRpdj4gUmVtb3ZlIEZpbGUgPC9kaXY+XG48L25nLXRlbXBsYXRlPlxuIl19