@iotize/ionic
Version:
Iotize specific building blocks on top of @ionic/angular.
248 lines • 31.1 kB
JavaScript
import { Component, ContentChild, Directive, ElementRef, EventEmitter, HostListener, Input, Output, } from '@angular/core';
import { TapError } from '@iotize/tap';
import { ResultCode } from '@iotize/tap/client/api';
import { TapClientError } from '@iotize/tap/client/impl';
import { debug } from '../logger';
import { TaskManagerService } from '../task-manager/task-manager.service';
import * as i0 from "@angular/core";
import * as i1 from "../task-manager/task-manager.service";
import * as i2 from "@angular/common";
const TAG = 'TaskManagerComponent';
export class TaskManagerActionCancelDirective {
constructor(elementRef) {
this.elementRef = elementRef;
this.onClick = new EventEmitter();
}
// disable(value: boolean) {
// // this.elementRef.
// }
onClickListener() {
debug('app-task-manager-action-cancel clicked');
this.onClick.emit();
}
}
/** @nocollapse */ TaskManagerActionCancelDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: TaskManagerActionCancelDirective, deps: [{ token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Directive });
/** @nocollapse */ TaskManagerActionCancelDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "15.2.10", type: TaskManagerActionCancelDirective, selector: "[app-task-manager-action-cancel]", outputs: { onClick: "onClick" }, host: { listeners: { "click": "onClickListener()" } }, ngImport: i0 });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: TaskManagerActionCancelDirective, decorators: [{
type: Directive,
args: [{
selector: '[app-task-manager-action-cancel]',
}]
}], ctorParameters: function () { return [{ type: i0.ElementRef }]; }, propDecorators: { onClick: [{
type: Output
}], onClickListener: [{
type: HostListener,
args: ['click']
}] } });
export class TaskManagerActionExecDirective {
constructor() {
this.onClick = new EventEmitter();
} // public tpl: TemplateRef<any>
onClickListener() {
this.onClick.emit();
}
}
/** @nocollapse */ TaskManagerActionExecDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: TaskManagerActionExecDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
/** @nocollapse */ TaskManagerActionExecDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "15.2.10", type: TaskManagerActionExecDirective, selector: "[app-task-manager-action-exec]", outputs: { onClick: "onClick" }, host: { listeners: { "click": "onClickListener()" } }, ngImport: i0 });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: TaskManagerActionExecDirective, decorators: [{
type: Directive,
args: [{
selector: '[app-task-manager-action-exec]',
}]
}], ctorParameters: function () { return []; }, propDecorators: { onClick: [{
type: Output
}], onClickListener: [{
type: HostListener,
args: ['click']
}] } });
export class TaskManagerRunningComponent {
constructor(taskManager) {
this.taskManager = taskManager;
}
}
/** @nocollapse */ TaskManagerRunningComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: TaskManagerRunningComponent, deps: [{ token: i1.TaskManagerService }], target: i0.ɵɵFactoryTarget.Component });
/** @nocollapse */ TaskManagerRunningComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.10", type: TaskManagerRunningComponent, selector: "app-task-manager-running", inputs: { context: "context" }, ngImport: i0, template: ' <ng-content></ng-content> ', isInline: true });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: TaskManagerRunningComponent, decorators: [{
type: Component,
args: [{
selector: 'app-task-manager-running',
template: ' <ng-content></ng-content> ',
}]
}], ctorParameters: function () { return [{ type: i1.TaskManagerService }]; }, propDecorators: { context: [{
type: Input
}] } });
export class TaskManagerDelayedComponent {
constructor(taskManager) {
this.taskManager = taskManager;
}
cancelTask() {
debug(TAG, 'Cancel task click');
}
}
/** @nocollapse */ TaskManagerDelayedComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: TaskManagerDelayedComponent, deps: [{ token: i1.TaskManagerService }], target: i0.ɵɵFactoryTarget.Component });
/** @nocollapse */ TaskManagerDelayedComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.10", type: TaskManagerDelayedComponent, selector: "app-task-manager-delayed", inputs: { context: "context" }, ngImport: i0, template: ' <ng-content></ng-content> ', isInline: true });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: TaskManagerDelayedComponent, decorators: [{
type: Component,
args: [{
selector: 'app-task-manager-delayed',
template: ' <ng-content></ng-content> ',
}]
}], ctorParameters: function () { return [{ type: i1.TaskManagerService }]; }, propDecorators: { context: [{
type: Input
}] } });
export class TaskManagerActionComponent {
/** Template inside the MatTab view that contains an `<ng-content>`. */
// @ViewChild(TemplateRef, { static: true }) _implicitContent: TemplateRef<any>;
// @ContentChildren(TaskManagerActionExecDirective) execButton!: TaskManagerActionExecDirective;
constructor(taskManager) {
this.taskManager = taskManager;
}
performTask() {
debug(TAG, 'Perform task click');
}
}
/** @nocollapse */ TaskManagerActionComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: TaskManagerActionComponent, deps: [{ token: i1.TaskManagerService }], target: i0.ɵɵFactoryTarget.Component });
/** @nocollapse */ TaskManagerActionComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.10", type: TaskManagerActionComponent, selector: "app-task-manager-action", inputs: { context: "context" }, ngImport: i0, template: ' <ng-content></ng-content> ', isInline: true });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: TaskManagerActionComponent, decorators: [{
type: Component,
args: [{
selector: 'app-task-manager-action',
template: ' <ng-content></ng-content> ',
}]
}], ctorParameters: function () { return [{ type: i1.TaskManagerService }]; }, propDecorators: { context: [{
type: Input
}] } });
export class TaskManagerComponent {
set task(taskContainerOrString) {
let taskContainer;
taskContainer = taskContainerOrString;
debug(TAG, 'set task ', taskContainer?.task?.id);
this.taskContainer = taskContainer;
}
get taskId() {
return this.taskContainer?.task?.id;
}
// @ContentChild(TaskManagerActionComponent, {}) actionComponent: TaskManagerActionComponent;
constructor(taskManager) {
this.taskManager = taskManager;
}
get loading() {
return false;
}
get taskState() {
return this.taskContainer?.meta?.state;
}
get actionTemplateContext() {
const cont = this._createContext();
if ('execTask' in cont) {
cont['execTask'] = (...context) => {
this.execTask(context);
};
}
return { $implicit: cont };
}
get delayedTemplateContext() {
const context = this._createContext();
if ('execTask' in this) {
context['execTask'] = () => {
if (this.taskId && this.taskManager.hasTask(this.taskId)) {
this.taskManager.cancel(this.taskId);
}
};
}
return { $implicit: context };
}
_createContext() {
return this;
}
ngAfterViewInit() {
if (this.cancelDirective) {
this.cancelDirective.onClick.subscribe(() => {
this.cancelTask();
});
}
else {
debug(TAG, 'cancel button is not set yet');
}
if (this.execDirective) {
this.execDirective.onClick.subscribe(() => {
this.execTask();
});
}
}
ngOnDestroy() {
debug(TAG, 'Task', this.taskId, 'component ngOnDestroy');
this.cancelTask();
}
cancelTask() {
debug(TAG, 'cancelTask clicked!');
if (!this.taskId) {
return;
}
if (this.taskManager.hasTask(this.taskId)) {
this.taskManager.cancel(this.taskId);
}
else {
debug(TAG, 'cannot cancel task ', this.taskId, 'it does not exist');
}
}
explainDelayReason() {
const err = this.taskContainer?.meta.error;
if (err) {
const codeError = err;
switch (codeError.code) {
case TapError.Code.ResponseStatusError:
switch (err.response.status) {
case ResultCode.UNAUTHORIZED:
return 'Waiting for user login';
}
break;
case TapError.Code.ExecuteRequestError:
const cause = err.cause;
if (cause) {
switch (cause.code) {
case TapClientError.Code.NotConnectedError:
case 'NfcTagLostError':
case 'NfcNotConnectedError':
return 'Waiting for Tap reconnection';
}
}
}
return 'Unknown reason';
}
}
execTask(context) {
const container = this.taskContainer;
if (!container) {
return;
}
debug(TAG, 'execTask ', container.task.id);
this.taskManager.addTaskContainer(container);
// this.execDirective.disable(true);
this.taskManager.exec(container.task.id, context).subscribe({
error: (err) => {
debug(`Task ${container.task.id} error: ${err.message}`);
console.warn(err);
// this.execDirective.disable(false);
},
complete: () => {
debug(`Task ${container.task.id} COMPLETED`);
},
});
}
}
/** @nocollapse */ TaskManagerComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: TaskManagerComponent, deps: [{ token: i1.TaskManagerService }], target: i0.ɵɵFactoryTarget.Component });
/** @nocollapse */ TaskManagerComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.10", type: TaskManagerComponent, selector: "app-task-manager", inputs: { task: "task" }, queries: [{ propertyName: "cancelDirective", first: true, predicate: TaskManagerActionCancelDirective, descendants: true, static: true }, { propertyName: "execDirective", first: true, predicate: TaskManagerActionExecDirective, descendants: true, static: true }], ngImport: i0, template: "<ng-container [ngSwitch]=\"taskState\">\n <ng-content\n select=\"app-task-manager-delayed\"\n *ngSwitchCase=\"'delayed'\"\n ></ng-content>\n <ng-content\n select=\"app-task-manager-running\"\n *ngSwitchCase=\"'running'\"\n ></ng-content>\n <ng-content select=\"app-task-manager-action\" *ngSwitchDefault></ng-content>\n</ng-container>\n", styles: [""], dependencies: [{ kind: "directive", type: i2.NgSwitch, selector: "[ngSwitch]", inputs: ["ngSwitch"] }, { kind: "directive", type: i2.NgSwitchCase, selector: "[ngSwitchCase]", inputs: ["ngSwitchCase"] }, { kind: "directive", type: i2.NgSwitchDefault, selector: "[ngSwitchDefault]" }] });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: TaskManagerComponent, decorators: [{
type: Component,
args: [{ selector: 'app-task-manager', template: "<ng-container [ngSwitch]=\"taskState\">\n <ng-content\n select=\"app-task-manager-delayed\"\n *ngSwitchCase=\"'delayed'\"\n ></ng-content>\n <ng-content\n select=\"app-task-manager-running\"\n *ngSwitchCase=\"'running'\"\n ></ng-content>\n <ng-content select=\"app-task-manager-action\" *ngSwitchDefault></ng-content>\n</ng-container>\n" }]
}], ctorParameters: function () { return [{ type: i1.TaskManagerService }]; }, propDecorators: { task: [{
type: Input
}], cancelDirective: [{
type: ContentChild,
args: [TaskManagerActionCancelDirective, { static: true }]
}], execDirective: [{
type: ContentChild,
args: [TaskManagerActionExecDirective, { static: true }]
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGFzay1tYW5hZ2VyLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL2lvdGl6ZS1pb25pYy9zcmMvbGliL3Rhc2stbWFuYWdlci11aS90YXNrLW1hbmFnZXIuY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvaW90aXplLWlvbmljL3NyYy9saWIvdGFzay1tYW5hZ2VyLXVpL3Rhc2stbWFuYWdlci5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBRUwsU0FBUyxFQUNULFlBQVksRUFDWixTQUFTLEVBQ1QsVUFBVSxFQUNWLFlBQVksRUFDWixZQUFZLEVBQ1osS0FBSyxFQUVMLE1BQU0sR0FDUCxNQUFNLGVBQWUsQ0FBQztBQUV2QixPQUFPLEVBQUUsUUFBUSxFQUEwQixNQUFNLGFBQWEsQ0FBQztBQUMvRCxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sd0JBQXdCLENBQUM7QUFDcEQsT0FBTyxFQUFFLGNBQWMsRUFBRSxNQUFNLHlCQUF5QixDQUFDO0FBQ3pELE9BQU8sRUFBRSxLQUFLLEVBQUUsTUFBTSxXQUFXLENBQUM7QUFFbEMsT0FBTyxFQUFFLGtCQUFrQixFQUFFLE1BQU0sc0NBQXNDLENBQUM7Ozs7QUFFMUUsTUFBTSxHQUFHLEdBQUcsc0JBQXNCLENBQUM7QUFLbkMsTUFBTSxPQUFPLGdDQUFnQztJQUczQyxZQUFxQixVQUFzQjtRQUF0QixlQUFVLEdBQVYsVUFBVSxDQUFZO1FBRmpDLFlBQU8sR0FBRyxJQUFJLFlBQVksRUFBUSxDQUFDO0lBRUMsQ0FBQztJQUUvQyw0QkFBNEI7SUFDNUIsd0JBQXdCO0lBQ3hCLElBQUk7SUFFbUIsZUFBZTtRQUNwQyxLQUFLLENBQUMsd0NBQXdDLENBQUMsQ0FBQztRQUNoRCxJQUFJLENBQUMsT0FBTyxDQUFDLElBQUksRUFBRSxDQUFDO0lBQ3RCLENBQUM7O2lKQVpVLGdDQUFnQztxSUFBaEMsZ0NBQWdDOzRGQUFoQyxnQ0FBZ0M7a0JBSDVDLFNBQVM7bUJBQUM7b0JBQ1QsUUFBUSxFQUFFLGtDQUFrQztpQkFDN0M7aUdBRVcsT0FBTztzQkFBaEIsTUFBTTtnQkFRZ0IsZUFBZTtzQkFBckMsWUFBWTt1QkFBQyxPQUFPOztBQVN2QixNQUFNLE9BQU8sOEJBQThCO0lBR3pDO1FBRlUsWUFBTyxHQUFHLElBQUksWUFBWSxFQUFRLENBQUM7SUFFOUIsQ0FBQyxDQUFDLCtCQUErQjtJQUV6QixlQUFlO1FBQ3BDLElBQUksQ0FBQyxPQUFPLENBQUMsSUFBSSxFQUFFLENBQUM7SUFDdEIsQ0FBQzs7K0lBUFUsOEJBQThCO21JQUE5Qiw4QkFBOEI7NEZBQTlCLDhCQUE4QjtrQkFIMUMsU0FBUzttQkFBQztvQkFDVCxRQUFRLEVBQUUsZ0NBQWdDO2lCQUMzQzswRUFFVyxPQUFPO3NCQUFoQixNQUFNO2dCQUlnQixlQUFlO3NCQUFyQyxZQUFZO3VCQUFDLE9BQU87O0FBU3ZCLE1BQU0sT0FBTywyQkFBMkI7SUFNdEMsWUFBbUIsV0FBK0I7UUFBL0IsZ0JBQVcsR0FBWCxXQUFXLENBQW9CO0lBQUcsQ0FBQzs7NElBTjNDLDJCQUEyQjtnSUFBM0IsMkJBQTJCLGdHQUY1Qiw2QkFBNkI7NEZBRTVCLDJCQUEyQjtrQkFKdkMsU0FBUzttQkFBQztvQkFDVCxRQUFRLEVBQUUsMEJBQTBCO29CQUNwQyxRQUFRLEVBQUUsNkJBQTZCO2lCQUN4Qzt5R0FLVSxPQUFPO3NCQUFmLEtBQUs7O0FBU1IsTUFBTSxPQUFPLDJCQUEyQjtJQU10QyxZQUFtQixXQUErQjtRQUEvQixnQkFBVyxHQUFYLFdBQVcsQ0FBb0I7SUFBRyxDQUFDO0lBRXRELFVBQVU7UUFDUixLQUFLLENBQUMsR0FBRyxFQUFFLG1CQUFtQixDQUFDLENBQUM7SUFDbEMsQ0FBQzs7NElBVlUsMkJBQTJCO2dJQUEzQiwyQkFBMkIsZ0dBRjVCLDZCQUE2Qjs0RkFFNUIsMkJBQTJCO2tCQUp2QyxTQUFTO21CQUFDO29CQUNULFFBQVEsRUFBRSwwQkFBMEI7b0JBQ3BDLFFBQVEsRUFBRSw2QkFBNkI7aUJBQ3hDO3lHQUtVLE9BQU87c0JBQWYsS0FBSzs7QUFhUixNQUFNLE9BQU8sMEJBQTBCO0lBR3JDLHVFQUF1RTtJQUN2RSxnRkFBZ0Y7SUFFaEYsZ0dBQWdHO0lBRWhHLFlBQW1CLFdBQStCO1FBQS9CLGdCQUFXLEdBQVgsV0FBVyxDQUFvQjtJQUFHLENBQUM7SUFFdEQsV0FBVztRQUNULEtBQUssQ0FBQyxHQUFHLEVBQUUsb0JBQW9CLENBQUMsQ0FBQztJQUNuQyxDQUFDOzsySUFaVSwwQkFBMEI7K0hBQTFCLDBCQUEwQiwrRkFGM0IsNkJBQTZCOzRGQUU1QiwwQkFBMEI7a0JBSnRDLFNBQVM7bUJBQUM7b0JBQ1QsUUFBUSxFQUFFLHlCQUF5QjtvQkFDbkMsUUFBUSxFQUFFLDZCQUE2QjtpQkFDeEM7eUdBRVUsT0FBTztzQkFBZixLQUFLOztBQW1CUixNQUFNLE9BQU8sb0JBQW9CO0lBRy9CLElBQWEsSUFBSSxDQUNmLHFCQUFrRTtRQUVsRSxJQUFJLGFBQTZELENBQUM7UUFDbEUsYUFBYSxHQUFHLHFCQUEyRCxDQUFDO1FBQzVFLEtBQUssQ0FBQyxHQUFHLEVBQUUsV0FBVyxFQUFFLGFBQWEsRUFBRSxJQUFJLEVBQUUsRUFBRSxDQUFDLENBQUM7UUFDakQsSUFBSSxDQUFDLGFBQWEsR0FBRyxhQUFhLENBQUM7SUFDckMsQ0FBQztJQUVELElBQUksTUFBTTtRQUNSLE9BQU8sSUFBSSxDQUFDLGFBQWEsRUFBRSxJQUFJLEVBQUUsRUFBRSxDQUFDO0lBQ3RDLENBQUM7SUFPRCw2RkFBNkY7SUFFN0YsWUFBbUIsV0FBK0I7UUFBL0IsZ0JBQVcsR0FBWCxXQUFXLENBQW9CO0lBQUcsQ0FBQztJQUV0RCxJQUFJLE9BQU87UUFDVCxPQUFPLEtBQUssQ0FBQztJQUNmLENBQUM7SUFFRCxJQUFJLFNBQVM7UUFDWCxPQUFPLElBQUksQ0FBQyxhQUFhLEVBQUUsSUFBSSxFQUFFLEtBQUssQ0FBQztJQUN6QyxDQUFDO0lBRUQsSUFBSSxxQkFBcUI7UUFDdkIsTUFBTSxJQUFJLEdBQUcsSUFBSSxDQUFDLGNBQWMsRUFBRSxDQUFDO1FBQ25DLElBQUksVUFBVSxJQUFJLElBQUksRUFBRTtZQUN0QixJQUFJLENBQUMsVUFBVSxDQUFDLEdBQUcsQ0FBQyxHQUFHLE9BQWMsRUFBRSxFQUFFO2dCQUN2QyxJQUFJLENBQUMsUUFBUSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1lBQ3pCLENBQUMsQ0FBQztTQUNIO1FBQ0QsT0FBTyxFQUFFLFNBQVMsRUFBRSxJQUFJLEVBQUUsQ0FBQztJQUM3QixDQUFDO0lBRUQsSUFBSSxzQkFBc0I7UUFDeEIsTUFBTSxPQUFPLEdBQUcsSUFBSSxDQUFDLGNBQWMsRUFBRSxDQUFDO1FBQ3RDLElBQUksVUFBVSxJQUFJLElBQUksRUFBRTtZQUN0QixPQUFPLENBQUMsVUFBVSxDQUFDLEdBQUcsR0FBRyxFQUFFO2dCQUN6QixJQUFJLElBQUksQ0FBQyxNQUFNLElBQUksSUFBSSxDQUFDLFdBQVcsQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxFQUFFO29CQUN4RCxJQUFJLENBQUMsV0FBVyxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUM7aUJBQ3RDO1lBQ0gsQ0FBQyxDQUFDO1NBQ0g7UUFDRCxPQUFPLEVBQUUsU0FBUyxFQUFFLE9BQU8sRUFBRSxDQUFDO0lBQ2hDLENBQUM7SUFFTyxjQUFjO1FBQ3BCLE9BQU8sSUFBSSxDQUFDO0lBQ2QsQ0FBQztJQUVELGVBQWU7UUFDYixJQUFJLElBQUksQ0FBQyxlQUFlLEVBQUU7WUFDeEIsSUFBSSxDQUFDLGVBQWUsQ0FBQyxPQUFPLENBQUMsU0FBUyxDQUFDLEdBQUcsRUFBRTtnQkFDMUMsSUFBSSxDQUFDLFVBQVUsRUFBRSxDQUFDO1lBQ3BCLENBQUMsQ0FBQyxDQUFDO1NBQ0o7YUFBTTtZQUNMLEtBQUssQ0FBQyxHQUFHLEVBQUUsOEJBQThCLENBQUMsQ0FBQztTQUM1QztRQUNELElBQUksSUFBSSxDQUFDLGFBQWEsRUFBRTtZQUN0QixJQUFJLENBQUMsYUFBYSxDQUFDLE9BQU8sQ0FBQyxTQUFTLENBQUMsR0FBRyxFQUFFO2dCQUN4QyxJQUFJLENBQUMsUUFBUSxFQUFFLENBQUM7WUFDbEIsQ0FBQyxDQUFDLENBQUM7U0FDSjtJQUNILENBQUM7SUFFRCxXQUFXO1FBQ1QsS0FBSyxDQUFDLEdBQUcsRUFBRSxNQUFNLEVBQUUsSUFBSSxDQUFDLE1BQU0sRUFBRSx1QkFBdUIsQ0FBQyxDQUFDO1FBQ3pELElBQUksQ0FBQyxVQUFVLEVBQUUsQ0FBQztJQUNwQixDQUFDO0lBRUQsVUFBVTtRQUNSLEtBQUssQ0FBQyxHQUFHLEVBQUUscUJBQXFCLENBQUMsQ0FBQztRQUNsQyxJQUFJLENBQUMsSUFBSSxDQUFDLE1BQU0sRUFBRTtZQUNoQixPQUFPO1NBQ1I7UUFDRCxJQUFJLElBQUksQ0FBQyxXQUFXLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsRUFBRTtZQUN6QyxJQUFJLENBQUMsV0FBVyxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUM7U0FDdEM7YUFBTTtZQUNMLEtBQUssQ0FBQyxHQUFHLEVBQUUscUJBQXFCLEVBQUUsSUFBSSxDQUFDLE1BQU0sRUFBRSxtQkFBbUIsQ0FBQyxDQUFDO1NBQ3JFO0lBQ0gsQ0FBQztJQUVELGtCQUFrQjtRQUNoQixNQUFNLEdBQUcsR0FBRyxJQUFJLENBQUMsYUFBYSxFQUFFLElBQUksQ0FBQyxLQUFLLENBQUM7UUFDM0MsSUFBSSxHQUFHLEVBQUU7WUFDUCxNQUFNLFNBQVMsR0FBRyxHQUFnQixDQUFDO1lBQ25DLFFBQVEsU0FBUyxDQUFDLElBQUksRUFBRTtnQkFDdEIsS0FBSyxRQUFRLENBQUMsSUFBSSxDQUFDLG1CQUFtQjtvQkFDcEMsUUFBUyxHQUE4QixDQUFDLFFBQVEsQ0FBQyxNQUFNLEVBQUU7d0JBQ3ZELEtBQUssVUFBVSxDQUFDLFlBQVk7NEJBQzFCLE9BQU8sd0JBQXdCLENBQUM7cUJBQ25DO29CQUNELE1BQU07Z0JBQ1IsS0FBSyxRQUFRLENBQUMsSUFBSSxDQUFDLG1CQUFtQjtvQkFDcEMsTUFBTSxLQUFLLEdBQUksR0FBZ0IsQ0FBQyxLQUFrQixDQUFDO29CQUNuRCxJQUFJLEtBQUssRUFBRTt3QkFDVCxRQUFRLEtBQUssQ0FBQyxJQUFJLEVBQUU7NEJBQ2xCLEtBQUssY0FBYyxDQUFDLElBQUksQ0FBQyxpQkFBaUIsQ0FBQzs0QkFDM0MsS0FBSyxpQkFBaUIsQ0FBQzs0QkFDdkIsS0FBSyxzQkFBc0I7Z0NBQ3pCLE9BQU8sOEJBQThCLENBQUM7eUJBQ3pDO3FCQUNGO2FBQ0o7WUFDRCxPQUFPLGdCQUFnQixDQUFDO1NBQ3pCO0lBQ0gsQ0FBQztJQUVELFFBQVEsQ0FBQyxPQUFhO1FBQ3BCLE1BQU0sU0FBUyxHQUFHLElBQUksQ0FBQyxhQUFhLENBQUM7UUFDckMsSUFBSSxDQUFDLFNBQVMsRUFBRTtZQUNkLE9BQU87U0FDUjtRQUNELEtBQUssQ0FBQyxHQUFHLEVBQUUsV0FBVyxFQUFFLFNBQVMsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUM7UUFDM0MsSUFBSSxDQUFDLFdBQVcsQ0FBQyxnQkFBZ0IsQ0FBQyxTQUFTLENBQUMsQ0FBQztRQUM3QyxvQ0FBb0M7UUFDcEMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxFQUFFLEVBQUUsT0FBTyxDQUFDLENBQUMsU0FBUyxDQUFDO1lBQzFELEtBQUssRUFBRSxDQUFDLEdBQUcsRUFBRSxFQUFFO2dCQUNiLEtBQUssQ0FBQyxRQUFRLFNBQVMsQ0FBQyxJQUFJLENBQUMsRUFBRSxXQUFXLEdBQUcsQ0FBQyxPQUFPLEVBQUUsQ0FBQyxDQUFDO2dCQUN6RCxPQUFPLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDO2dCQUNsQixxQ0FBcUM7WUFDdkMsQ0FBQztZQUNELFFBQVEsRUFBRSxHQUFHLEVBQUU7Z0JBQ2IsS0FBSyxDQUFDLFFBQVEsU0FBUyxDQUFDLElBQUksQ0FBQyxFQUFFLFlBQVksQ0FBQyxDQUFDO1lBQy9DLENBQUM7U0FDRixDQUFDLENBQUM7SUFDTCxDQUFDOztxSUF2SVUsb0JBQW9CO3lIQUFwQixvQkFBb0IsK0hBZ0JqQixnQ0FBZ0MsOEZBRWhDLDhCQUE4Qiw4REM3SDlDLG1XQVdBOzRGRGdHYSxvQkFBb0I7a0JBTGhDLFNBQVM7K0JBQ0Usa0JBQWtCO3lHQU9mLElBQUk7c0JBQWhCLEtBQUs7Z0JBY04sZUFBZTtzQkFEZCxZQUFZO3VCQUFDLGdDQUFnQyxFQUFFLEVBQUUsTUFBTSxFQUFFLElBQUksRUFBRTtnQkFHaEUsYUFBYTtzQkFEWixZQUFZO3VCQUFDLDhCQUE4QixFQUFFLEVBQUUsTUFBTSxFQUFFLElBQUksRUFBRSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XG4gIEFmdGVyVmlld0luaXQsXG4gIENvbXBvbmVudCxcbiAgQ29udGVudENoaWxkLFxuICBEaXJlY3RpdmUsXG4gIEVsZW1lbnRSZWYsXG4gIEV2ZW50RW1pdHRlcixcbiAgSG9zdExpc3RlbmVyLFxuICBJbnB1dCxcbiAgT25EZXN0cm95LFxuICBPdXRwdXQsXG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgQ29kZUVycm9yIH0gZnJvbSAnQGlvdGl6ZS9jb21tb24vZXJyb3InO1xuaW1wb3J0IHsgVGFwRXJyb3IsIFRhcFJlc3BvbnNlU3RhdHVzRXJyb3IgfSBmcm9tICdAaW90aXplL3RhcCc7XG5pbXBvcnQgeyBSZXN1bHRDb2RlIH0gZnJvbSAnQGlvdGl6ZS90YXAvY2xpZW50L2FwaSc7XG5pbXBvcnQgeyBUYXBDbGllbnRFcnJvciB9IGZyb20gJ0Bpb3RpemUvdGFwL2NsaWVudC9pbXBsJztcbmltcG9ydCB7IGRlYnVnIH0gZnJvbSAnLi4vbG9nZ2VyJztcbmltcG9ydCB7IFRhc2tNYW5hZ2VyIH0gZnJvbSAnLi4vdGFzay1tYW5hZ2VyL2RlZmluaXRpb25zJztcbmltcG9ydCB7IFRhc2tNYW5hZ2VyU2VydmljZSB9IGZyb20gJy4uL3Rhc2stbWFuYWdlci90YXNrLW1hbmFnZXIuc2VydmljZSc7XG5cbmNvbnN0IFRBRyA9ICdUYXNrTWFuYWdlckNvbXBvbmVudCc7XG5cbkBEaXJlY3RpdmUoe1xuICBzZWxlY3RvcjogJ1thcHAtdGFzay1tYW5hZ2VyLWFjdGlvbi1jYW5jZWxdJyxcbn0pXG5leHBvcnQgY2xhc3MgVGFza01hbmFnZXJBY3Rpb25DYW5jZWxEaXJlY3RpdmUge1xuICBAT3V0cHV0KCkgb25DbGljayA9IG5ldyBFdmVudEVtaXR0ZXI8dm9pZD4oKTtcblxuICBjb25zdHJ1Y3RvcihyZWFkb25seSBlbGVtZW50UmVmOiBFbGVtZW50UmVmKSB7fVxuXG4gIC8vIGRpc2FibGUodmFsdWU6IGJvb2xlYW4pIHtcbiAgLy8gICAvLyB0aGlzLmVsZW1lbnRSZWYuXG4gIC8vIH1cblxuICBASG9zdExpc3RlbmVyKCdjbGljaycpIG9uQ2xpY2tMaXN0ZW5lcigpIHtcbiAgICBkZWJ1ZygnYXBwLXRhc2stbWFuYWdlci1hY3Rpb24tY2FuY2VsIGNsaWNrZWQnKTtcbiAgICB0aGlzLm9uQ2xpY2suZW1pdCgpO1xuICB9XG59XG5cbkBEaXJlY3RpdmUoe1xuICBzZWxlY3RvcjogJ1thcHAtdGFzay1tYW5hZ2VyLWFjdGlvbi1leGVjXScsXG59KVxuZXhwb3J0IGNsYXNzIFRhc2tNYW5hZ2VyQWN0aW9uRXhlY0RpcmVjdGl2ZSB7XG4gIEBPdXRwdXQoKSBvbkNsaWNrID0gbmV3IEV2ZW50RW1pdHRlcjx2b2lkPigpO1xuXG4gIGNvbnN0cnVjdG9yKCkge30gLy8gcHVibGljIHRwbDogVGVtcGxhdGVSZWY8YW55PlxuXG4gIEBIb3N0TGlzdGVuZXIoJ2NsaWNrJykgb25DbGlja0xpc3RlbmVyKCkge1xuICAgIHRoaXMub25DbGljay5lbWl0KCk7XG4gIH1cbn1cblxuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAnYXBwLXRhc2stbWFuYWdlci1ydW5uaW5nJyxcbiAgdGVtcGxhdGU6ICcgPG5nLWNvbnRlbnQ+PC9uZy1jb250ZW50PiAnLFxufSlcbmV4cG9ydCBjbGFzcyBUYXNrTWFuYWdlclJ1bm5pbmdDb21wb25lbnQge1xuICAvKiogVGVtcGxhdGUgaW5zaWRlIHRoZSBNYXRUYWIgdmlldyB0aGF0IGNvbnRhaW5zIGFuIGA8bmctY29udGVudD5gLiAqL1xuICAvLyBAVmlld0NoaWxkKFRlbXBsYXRlUmVmLCB7IHN0YXRpYzogdHJ1ZSB9KSBfaW1wbGljaXRDb250ZW50OiBUZW1wbGF0ZVJlZjxhbnk+O1xuXG4gIEBJbnB1dCgpIGNvbnRleHQ6IGFueTtcblxuICBjb25zdHJ1Y3RvcihwdWJsaWMgdGFza01hbmFnZXI6IFRhc2tNYW5hZ2VyU2VydmljZSkge31cbn1cblxuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAnYXBwLXRhc2stbWFuYWdlci1kZWxheWVkJyxcbiAgdGVtcGxhdGU6ICcgPG5nLWNvbnRlbnQ+PC9uZy1jb250ZW50PiAnLFxufSlcbmV4cG9ydCBjbGFzcyBUYXNrTWFuYWdlckRlbGF5ZWRDb21wb25lbnQge1xuICAvKiogVGVtcGxhdGUgaW5zaWRlIHRoZSBNYXRUYWIgdmlldyB0aGF0IGNvbnRhaW5zIGFuIGA8bmctY29udGVudD5gLiAqL1xuICAvLyBAVmlld0NoaWxkKFRlbXBsYXRlUmVmLCB7IHN0YXRpYzogdHJ1ZSB9KSBfaW1wbGljaXRDb250ZW50OiBUZW1wbGF0ZVJlZjxhbnk+O1xuXG4gIEBJbnB1dCgpIGNvbnRleHQ6IGFueTtcblxuICBjb25zdHJ1Y3RvcihwdWJsaWMgdGFza01hbmFnZXI6IFRhc2tNYW5hZ2VyU2VydmljZSkge31cblxuICBjYW5jZWxUYXNrKCkge1xuICAgIGRlYnVnKFRBRywgJ0NhbmNlbCB0YXNrIGNsaWNrJyk7XG4gIH1cbn1cblxuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAnYXBwLXRhc2stbWFuYWdlci1hY3Rpb24nLFxuICB0ZW1wbGF0ZTogJyA8bmctY29udGVudD48L25nLWNvbnRlbnQ+ICcsXG59KVxuZXhwb3J0IGNsYXNzIFRhc2tNYW5hZ2VyQWN0aW9uQ29tcG9uZW50IHtcbiAgQElucHV0KCkgY29udGV4dDogYW55O1xuXG4gIC8qKiBUZW1wbGF0ZSBpbnNpZGUgdGhlIE1hdFRhYiB2aWV3IHRoYXQgY29udGFpbnMgYW4gYDxuZy1jb250ZW50PmAuICovXG4gIC8vIEBWaWV3Q2hpbGQoVGVtcGxhdGVSZWYsIHsgc3RhdGljOiB0cnVlIH0pIF9pbXBsaWNpdENvbnRlbnQ6IFRlbXBsYXRlUmVmPGFueT47XG5cbiAgLy8gQENvbnRlbnRDaGlsZHJlbihUYXNrTWFuYWdlckFjdGlvbkV4ZWNEaXJlY3RpdmUpIGV4ZWNCdXR0b24hOiBUYXNrTWFuYWdlckFjdGlvbkV4ZWNEaXJlY3RpdmU7XG5cbiAgY29uc3RydWN0b3IocHVibGljIHRhc2tNYW5hZ2VyOiBUYXNrTWFuYWdlclNlcnZpY2UpIHt9XG5cbiAgcGVyZm9ybVRhc2soKSB7XG4gICAgZGVidWcoVEFHLCAnUGVyZm9ybSB0YXNrIGNsaWNrJyk7XG4gIH1cbn1cblxuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAnYXBwLXRhc2stbWFuYWdlcicsXG4gIHRlbXBsYXRlVXJsOiAnLi90YXNrLW1hbmFnZXIuY29tcG9uZW50Lmh0bWwnLFxuICBzdHlsZVVybHM6IFsnLi90YXNrLW1hbmFnZXIuY29tcG9uZW50LnNjc3MnXSxcbn0pXG5leHBvcnQgY2xhc3MgVGFza01hbmFnZXJDb21wb25lbnQgaW1wbGVtZW50cyBBZnRlclZpZXdJbml0LCBPbkRlc3Ryb3kge1xuICB0YXNrQ29udGFpbmVyPzogVGFza01hbmFnZXIuVGFza0NvbnRhaW5lcjx1bmtub3duPjtcblxuICBASW5wdXQoKSBzZXQgdGFzayhcbiAgICB0YXNrQ29udGFpbmVyT3JTdHJpbmc6IFRhc2tNYW5hZ2VyLlRhc2tDb250YWluZXI8dW5rbm93bj4gfCBzdHJpbmdcbiAgKSB7XG4gICAgbGV0IHRhc2tDb250YWluZXI6IFRhc2tNYW5hZ2VyLlRhc2tDb250YWluZXI8dW5rbm93bj4gfCB1bmRlZmluZWQ7XG4gICAgdGFza0NvbnRhaW5lciA9IHRhc2tDb250YWluZXJPclN0cmluZyBhcyBUYXNrTWFuYWdlci5UYXNrQ29udGFpbmVyPHVua25vd24+O1xuICAgIGRlYnVnKFRBRywgJ3NldCB0YXNrICcsIHRhc2tDb250YWluZXI/LnRhc2s/LmlkKTtcbiAgICB0aGlzLnRhc2tDb250YWluZXIgPSB0YXNrQ29udGFpbmVyO1xuICB9XG5cbiAgZ2V0IHRhc2tJZCgpIHtcbiAgICByZXR1cm4gdGhpcy50YXNrQ29udGFpbmVyPy50YXNrPy5pZDtcbiAgfVxuXG4gIEBDb250ZW50Q2hpbGQoVGFza01hbmFnZXJBY3Rpb25DYW5jZWxEaXJlY3RpdmUsIHsgc3RhdGljOiB0cnVlIH0pXG4gIGNhbmNlbERpcmVjdGl2ZT86IFRhc2tNYW5hZ2VyQWN0aW9uQ2FuY2VsRGlyZWN0aXZlO1xuICBAQ29udGVudENoaWxkKFRhc2tNYW5hZ2VyQWN0aW9uRXhlY0RpcmVjdGl2ZSwgeyBzdGF0aWM6IHRydWUgfSlcbiAgZXhlY0RpcmVjdGl2ZT86IFRhc2tNYW5hZ2VyQWN0aW9uQ2FuY2VsRGlyZWN0aXZlO1xuXG4gIC8vIEBDb250ZW50Q2hpbGQoVGFza01hbmFnZXJBY3Rpb25Db21wb25lbnQsIHt9KSBhY3Rpb25Db21wb25lbnQ6IFRhc2tNYW5hZ2VyQWN0aW9uQ29tcG9uZW50O1xuXG4gIGNvbnN0cnVjdG9yKHB1YmxpYyB0YXNrTWFuYWdlcjogVGFza01hbmFnZXJTZXJ2aWNlKSB7fVxuXG4gIGdldCBsb2FkaW5nKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIGdldCB0YXNrU3RhdGUoKSB7XG4gICAgcmV0dXJuIHRoaXMudGFza0NvbnRhaW5lcj8ubWV0YT8uc3RhdGU7XG4gIH1cblxuICBnZXQgYWN0aW9uVGVtcGxhdGVDb250ZXh0KCkge1xuICAgIGNvbnN0IGNvbnQgPSB0aGlzLl9jcmVhdGVDb250ZXh0KCk7XG4gICAgaWYgKCdleGVjVGFzaycgaW4gY29udCkge1xuICAgICAgY29udFsnZXhlY1Rhc2snXSA9ICguLi5jb250ZXh0OiBhbnlbXSkgPT4ge1xuICAgICAgICB0aGlzLmV4ZWNUYXNrKGNvbnRleHQpO1xuICAgICAgfTtcbiAgICB9XG4gICAgcmV0dXJuIHsgJGltcGxpY2l0OiBjb250IH07XG4gIH1cblxuICBnZXQgZGVsYXllZFRlbXBsYXRlQ29udGV4dCgpIHtcbiAgICBjb25zdCBjb250ZXh0ID0gdGhpcy5fY3JlYXRlQ29udGV4dCgpO1xuICAgIGlmICgnZXhlY1Rhc2snIGluIHRoaXMpIHtcbiAgICAgIGNvbnRleHRbJ2V4ZWNUYXNrJ10gPSAoKSA9PiB7XG4gICAgICAgIGlmICh0aGlzLnRhc2tJZCAmJiB0aGlzLnRhc2tNYW5hZ2VyLmhhc1Rhc2sodGhpcy50YXNrSWQpKSB7XG4gICAgICAgICAgdGhpcy50YXNrTWFuYWdlci5jYW5jZWwodGhpcy50YXNrSWQpO1xuICAgICAgICB9XG4gICAgICB9O1xuICAgIH1cbiAgICByZXR1cm4geyAkaW1wbGljaXQ6IGNvbnRleHQgfTtcbiAgfVxuXG4gIHByaXZhdGUgX2NyZWF0ZUNvbnRleHQoKTogYW55IHtcbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIG5nQWZ0ZXJWaWV3SW5pdCgpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5jYW5jZWxEaXJlY3RpdmUpIHtcbiAgICAgIHRoaXMuY2FuY2VsRGlyZWN0aXZlLm9uQ2xpY2suc3Vic2NyaWJlKCgpID0+IHtcbiAgICAgICAgdGhpcy5jYW5jZWxUYXNrKCk7XG4gICAgICB9KTtcbiAgICB9IGVsc2Uge1xuICAgICAgZGVidWcoVEFHLCAnY2FuY2VsIGJ1dHRvbiBpcyBub3Qgc2V0IHlldCcpO1xuICAgIH1cbiAgICBpZiAodGhpcy5leGVjRGlyZWN0aXZlKSB7XG4gICAgICB0aGlzLmV4ZWNEaXJlY3RpdmUub25DbGljay5zdWJzY3JpYmUoKCkgPT4ge1xuICAgICAgICB0aGlzLmV4ZWNUYXNrKCk7XG4gICAgICB9KTtcbiAgICB9XG4gIH1cblxuICBuZ09uRGVzdHJveSgpIHtcbiAgICBkZWJ1ZyhUQUcsICdUYXNrJywgdGhpcy50YXNrSWQsICdjb21wb25lbnQgbmdPbkRlc3Ryb3knKTtcbiAgICB0aGlzLmNhbmNlbFRhc2soKTtcbiAgfVxuXG4gIGNhbmNlbFRhc2soKSB7XG4gICAgZGVidWcoVEFHLCAnY2FuY2VsVGFzayBjbGlja2VkIScpO1xuICAgIGlmICghdGhpcy50YXNrSWQpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgaWYgKHRoaXMudGFza01hbmFnZXIuaGFzVGFzayh0aGlzLnRhc2tJZCkpIHtcbiAgICAgIHRoaXMudGFza01hbmFnZXIuY2FuY2VsKHRoaXMudGFza0lkKTtcbiAgICB9IGVsc2Uge1xuICAgICAgZGVidWcoVEFHLCAnY2Fubm90IGNhbmNlbCB0YXNrICcsIHRoaXMudGFza0lkLCAnaXQgZG9lcyBub3QgZXhpc3QnKTtcbiAgICB9XG4gIH1cblxuICBleHBsYWluRGVsYXlSZWFzb24oKSB7XG4gICAgY29uc3QgZXJyID0gdGhpcy50YXNrQ29udGFpbmVyPy5tZXRhLmVycm9yO1xuICAgIGlmIChlcnIpIHtcbiAgICAgIGNvbnN0IGNvZGVFcnJvciA9IGVyciBhcyBDb2RlRXJyb3I7XG4gICAgICBzd2l0Y2ggKGNvZGVFcnJvci5jb2RlKSB7XG4gICAgICAgIGNhc2UgVGFwRXJyb3IuQ29kZS5SZXNwb25zZVN0YXR1c0Vycm9yOlxuICAgICAgICAgIHN3aXRjaCAoKGVyciBhcyBUYXBSZXNwb25zZVN0YXR1c0Vycm9yKS5yZXNwb25zZS5zdGF0dXMpIHtcbiAgICAgICAgICAgIGNhc2UgUmVzdWx0Q29kZS5VTkFVVEhPUklaRUQ6XG4gICAgICAgICAgICAgIHJldHVybiAnV2FpdGluZyBmb3IgdXNlciBsb2dpbic7XG4gICAgICAgICAgfVxuICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlIFRhcEVycm9yLkNvZGUuRXhlY3V0ZVJlcXVlc3RFcnJvcjpcbiAgICAgICAgICBjb25zdCBjYXVzZSA9IChlcnIgYXMgVGFwRXJyb3IpLmNhdXNlIGFzIENvZGVFcnJvcjtcbiAgICAgICAgICBpZiAoY2F1c2UpIHtcbiAgICAgICAgICAgIHN3aXRjaCAoY2F1c2UuY29kZSkge1xuICAgICAgICAgICAgICBjYXNlIFRhcENsaWVudEVycm9yLkNvZGUuTm90Q29ubmVjdGVkRXJyb3I6XG4gICAgICAgICAgICAgIGNhc2UgJ05mY1RhZ0xvc3RFcnJvcic6XG4gICAgICAgICAgICAgIGNhc2UgJ05mY05vdENvbm5lY3RlZEVycm9yJzpcbiAgICAgICAgICAgICAgICByZXR1cm4gJ1dhaXRpbmcgZm9yIFRhcCByZWNvbm5lY3Rpb24nO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJldHVybiAnVW5rbm93biByZWFzb24nO1xuICAgIH1cbiAgfVxuXG4gIGV4ZWNUYXNrKGNvbnRleHQ/OiBhbnkpIHtcbiAgICBjb25zdCBjb250YWluZXIgPSB0aGlzLnRhc2tDb250YWluZXI7XG4gICAgaWYgKCFjb250YWluZXIpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgZGVidWcoVEFHLCAnZXhlY1Rhc2sgJywgY29udGFpbmVyLnRhc2suaWQpO1xuICAgIHRoaXMudGFza01hbmFnZXIuYWRkVGFza0NvbnRhaW5lcihjb250YWluZXIpO1xuICAgIC8vIHRoaXMuZXhlY0RpcmVjdGl2ZS5kaXNhYmxlKHRydWUpO1xuICAgIHRoaXMudGFza01hbmFnZXIuZXhlYyhjb250YWluZXIudGFzay5pZCwgY29udGV4dCkuc3Vic2NyaWJlKHtcbiAgICAgIGVycm9yOiAoZXJyKSA9PiB7XG4gICAgICAgIGRlYnVnKGBUYXNrICR7Y29udGFpbmVyLnRhc2suaWR9IGVycm9yOiAke2Vyci5tZXNzYWdlfWApO1xuICAgICAgICBjb25zb2xlLndhcm4oZXJyKTtcbiAgICAgICAgLy8gdGhpcy5leGVjRGlyZWN0aXZlLmRpc2FibGUoZmFsc2UpO1xuICAgICAgfSxcbiAgICAgIGNvbXBsZXRlOiAoKSA9PiB7XG4gICAgICAgIGRlYnVnKGBUYXNrICR7Y29udGFpbmVyLnRhc2suaWR9IENPTVBMRVRFRGApO1xuICAgICAgfSxcbiAgICB9KTtcbiAgfVxufVxuIiwiPG5nLWNvbnRhaW5lciBbbmdTd2l0Y2hdPVwidGFza1N0YXRlXCI+XG4gIDxuZy1jb250ZW50XG4gICAgc2VsZWN0PVwiYXBwLXRhc2stbWFuYWdlci1kZWxheWVkXCJcbiAgICAqbmdTd2l0Y2hDYXNlPVwiJ2RlbGF5ZWQnXCJcbiAgPjwvbmctY29udGVudD5cbiAgPG5nLWNvbnRlbnRcbiAgICBzZWxlY3Q9XCJhcHAtdGFzay1tYW5hZ2VyLXJ1bm5pbmdcIlxuICAgICpuZ1N3aXRjaENhc2U9XCIncnVubmluZydcIlxuICA+PC9uZy1jb250ZW50PlxuICA8bmctY29udGVudCBzZWxlY3Q9XCJhcHAtdGFzay1tYW5hZ2VyLWFjdGlvblwiICpuZ1N3aXRjaERlZmF1bHQ+PC9uZy1jb250ZW50PlxuPC9uZy1jb250YWluZXI+XG4iXX0=