UNPKG

@iotize/ionic

Version:

Iotize specific building blocks on top of @ionic/angular.

243 lines 35.9 kB
import { MonitorEngine } from '@iotize/tap/data'; import '@iotize/tap/ext/data'; import { debug } from '../../logger'; const TAG = 'DataManager'; export class DataHolder { items; constructor(items = []) { this.items = items; } item(id) { const item = this.items.find((v) => v.id == id); if (!item) { throw new Error(`Item with id "${id}" does not exist`); } return item; } add(item, replace) { if (replace || this.items.find((v) => v.id == item.id) == undefined) { debug(TAG, 'Added item: ', item); this.items.push(item); } return this.item(item.id); } } // export function newBundleConfigToOldBundleConfig(bundlesConfig: BundleConfig[] | undefined): BundleConfigPredefined[] { // if (!bundlesConfig) { // return []; // } // return bundlesConfig.map((bundleConfig: BundleSchemaConfig) => { // const predefinedConfig: BundleConfigPredefined = { // id: bundleConfig.id, // converter: undefined, // name: bundleConfig.name || `Bundle ${bundleConfig.id}`, // variables: (bundleConfig.variables || []).map((variableConfig: MemoryVariableConfig) => { // const variableType = VariableType[variableConfig.type]; // if (variableType === undefined) { // throw new Error(`Invalid variable type: ${variableConfig.type}`); // } // let converter: BodyConverter<any> | undefined; // if (variableConfig.converter) { // converter = variableConfig.converter; // } else { // converter = getConverterFromFormat(variableType, variableConfig.length || 1); // } // const predifinedVariableConfig: TapVariable.Config = { // id: variableConfig.id, // converter: converter, // length: variableConfig.length, // name: variableConfig.name || `Variable ${variableConfig.id}`, // type: variableType, // unit: variableConfig.unit // }; // return predifinedVariableConfig; // }) // }; // return predefinedConfig; // }); // } export class DataManagerIonic { tap; constructor(tap) { this.tap = tap; // const allVariables: AbstractVariable<VariableByType[VariableKey]>[] = Object.values(data.variables); // this.tlvConverter = new TlvBundleConverter(allVariables.map((variable: AbstractVariable<any>) => { // if (!(variable instanceof VariableConfig)) { // throw new Error(`Variable ${variable.identifier} has no config`); // } // return { // id: variable.config.id, // name: variable.config.name, // converter: variable.converter // }; // })); // this.dataStream = this.setupDataStream(); // this.dataLogger = DataLogger.fromTap( // this.tap, // { // period: 2000 // TODO change // } // ); // this.tap.variables._variables = data.variables as any; // this.tap.bundles._bundles = data.bundles as any; // Change variable stream; // Object.values(this.data.variables).map((variable: any) => { // const variableName = variable.config.name; // // console.log('Replacing monitor for ', variable); // variable._monitor = ObservableMonitor.fromObservable( // this.dataStream // .pipe( // filter(data => variableName in data), // map(data => data[variableName]), // rxTap(value => debug(TAG, `Extracted key ${variableName} from monitoring data`, value)) // ) // , // MonitorEngine.State.START // ); // }); // // Change bundle stream; // Object.values(this.data.bundles).map((bundle: any) => { // bundle._monitor = ObservableMonitor.fromObservable( // this.dataStream // .pipe( // rxTap(value => debug(TAG, `New bundle value `, value)) // ) // , // MonitorEngine.State.START // ); // // TODO factorize and clean // Object.values(bundle.variables).map((variable: any) => { // const variableName = variable.config.name; // // console.log('Replacing monitor for variable in bundle', variable); // variable._monitor = ObservableMonitor.fromObservable( // this.dataStream // .pipe( // filter(data => variableName in data), // map(data => data[variableName]), // rxTap(value => debug(TAG, `Extracted key ${variableName} from monitoring data`, value)) // ) // , // MonitorEngine.State.START // ); // }); // }); // debug(TAG, 'New data manager instance: ', this); } // get variables(): Record<VariableKey, AbstractVariable<VariableByType[VariableKey]>> { // return this.data.variables; // } // get bundles(): Record<BundleKey, Bundle<BundleByType[BundleKey]>> { // return this.data.bundles; // } get sourceController() { const currentSourceId = this.switchableStreamController.getCurrentSourceId(); return this.sourceControllers[currentSourceId]; } get isMonitoringRunning() { for (const value of Object.values(this.sourceControllers)) { if (value.state == MonitorEngine.State.START) { return true; } } return false; } switchableStreamController; // dataStream: Observable<Record<string, any>>; // tlvConverter: TlvBundleConverter<Record<string, Uint8Array>>; // dataLogger: DataLogger; sourceControllers = {}; // public static fromSchemaConfig(tap: Tap, schema: TapConfiguratorConfig): DataManagerIonic { // const bundles = schema.config.data ? schema.config.data.bundles || [] : []; // return DataManagerIonic.fromBundleConfig(tap, bundles); // } // public static fromBundleConfig(tap: Tap, bundles: BundleConfig[]): DataManagerIonic { // return new DataManagerIonic( // tap, // DataManagerIonic.createDataFromSchemaConfig(tap, bundles) // ); // } // public static createDataFromSchemaConfig<VariableByType extends Record<string, any>, VariableKey extends string, BundleByType extends Record<string, any>, BundleKey extends string>(tap: Tap, bundlesConfig: BundleSchemaConfig[]) { // const predifinedConfig: BundleConfigPredefined[] = newBundleConfigToOldBundleConfig(bundlesConfig); // return DataManagerIonic.createDataFromConfig(tap, predifinedConfig); // } // public static createDataFromConfig<VariableByType extends Record<string, any>, VariableKey extends string, BundleByType extends Record<string, any>, BundleKey extends string>(tap: Tap, bundlesConfig: BundleConfigPredefined[]) { // // let bundleConfigCopy = [...bundlesConfig]; // const bundles: Record<string, any> = {}; // bundlesConfig.forEach((bundleConfig: BundleConfigPredefined) => { // const bundle: Bundle = Bundle.createFromConfig(bundleConfig, tap.service.bundle, tap.service.variable); // bundles[bundleConfig.name] = bundle; // }); // const variables: Record<string, any> = {}; // bundlesConfig.forEach((bundle) => { // bundle.variables.forEach((variableConfig: TapVariable.Config) => { // debug(TAG, 'Create from variable config: ', variableConfig); // variables[variableConfig.name || variableConfig.id.toString()] = TapVariable.createFromConfig(variableConfig, tap.service.variable); // }); // }); // return { // bundles: bundles as Record<BundleKey, Bundle<BundleByType[BundleKey]>>, // variables: variables as Record<VariableKey, AbstractVariable<VariableByType[VariableKey]>> // }; // } listVariables() { return this.tap.data.listVariables(); } listBundles() { return this.tap.data.listBundles(); } // public variable<T extends VariableKey>(key: T): AbstractVariable<VariableByType[T]> { // if (!(key in this.variables)) { // throw new Error(`Variable with identifier "${key}" is not configured`); // } // return this.variables[key] as AbstractVariable<VariableByType[T]>; // } // public bundle<T extends BundleKey>(key: T): Bundle<BundleByType[T]> { // if (!(key in this.bundles)) { // throw new Error(`Bundle with identifier "${key}" is not configured`); // } // return this.bundles[key] as any; // } stopAll() { debug(TAG, 'Stop monitoring'); // for (const ctrlKey in this.sourceControllers) { // this.sourceControllers[ctrlKey].state = MonitorEngine.State.PAUSE; // } this.tap.data.monitoring.stop(); } startAll(period) { // debug(TAG, `[Controller=${this.sourceController.id}] Start monitoring with period ${period || this.sourceController.period.value}`, this.sourceController); // if (period) { // this.setMonitoringPeriod(period); // } // this.sourceController.state = MonitorEngine.State.START; this.tap.data.monitoring.start(); } setMonitoringPeriod(period) { debug(TAG, 'Changing monitoring period to ', period); this.sourceController.period.next(period); } destroy() { this.stopAll(); } refresh() { if (this.sourceController.refresh) { this.sourceController.refresh(); } } changeDataSource(dataSource) { switch (dataSource) { case 'datalog': this.useDatalogSource(); break; default: this.useLiveSource(); } } useLiveSource() { this.switchableStreamController.useSource('live'); } useDatalogSource() { this.switchableStreamController.useSource('datalog'); } } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW1wbC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL2lvdGl6ZS1pb25pYy9zcmMvbGliL2V4dGVuc2lvbnMvZGF0YS1tYW5hZ2VyL2ltcGwudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBTUEsT0FBTyxFQUFFLGFBQWEsRUFBRSxNQUFNLGtCQUFrQixDQUFDO0FBRWpELE9BQU8sc0JBQXNCLENBQUM7QUFFOUIsT0FBTyxFQUFFLEtBQUssRUFBRSxNQUFNLGNBQWMsQ0FBQztBQVFyQyxNQUFNLEdBQUcsR0FBRyxhQUFhLENBQUM7QUFFMUIsTUFBTSxPQUFPLFVBQVU7SUFDRjtJQUFuQixZQUFtQixRQUFzQixFQUFFO1FBQXhCLFVBQUssR0FBTCxLQUFLLENBQW1CO0lBQUcsQ0FBQztJQUUvQyxJQUFJLENBQUMsRUFBVTtRQUNiLE1BQU0sSUFBSSxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRSxJQUFJLEVBQUUsQ0FBQyxDQUFDO1FBQ2hELElBQUksQ0FBQyxJQUFJLEVBQUUsQ0FBQztZQUNWLE1BQU0sSUFBSSxLQUFLLENBQUMsaUJBQWlCLEVBQUUsa0JBQWtCLENBQUMsQ0FBQztRQUN6RCxDQUFDO1FBQ0QsT0FBTyxJQUFJLENBQUM7SUFDZCxDQUFDO0lBRUQsR0FBRyxDQUFDLElBQWdCLEVBQUUsT0FBZ0I7UUFDcEMsSUFBSSxPQUFPLElBQUksSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxFQUFFLElBQUksSUFBSSxDQUFDLEVBQUUsQ0FBQyxJQUFJLFNBQVMsRUFBRSxDQUFDO1lBQ3BFLEtBQUssQ0FBQyxHQUFHLEVBQUUsY0FBYyxFQUFFLElBQUksQ0FBQyxDQUFDO1lBQ2pDLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFD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XG5pbXBvcnQgeyBUbHZCdW5kbGVDb252ZXJ0ZXIgfSBmcm9tICdAaW90aXplL3RhcC9jbGllbnQvaW1wbCc7XG5pbXBvcnQge1xuICBCdW5kbGVDb25maWcsXG4gIFRhcENvbmZpZ3VyYXRvckNvbmZpZyxcbn0gZnJvbSAnQGlvdGl6ZS90YXAvY29uZmlnL3NjaGVtYS92MSc7XG5pbXBvcnQgeyBNb25pdG9yRW5naW5lIH0gZnJvbSAnQGlvdGl6ZS90YXAvZGF0YSc7XG5pbXBvcnQgeyBEYXRhTG9nZ2VyIH0gZnJvbSAnQGlvdGl6ZS90YXAvZGF0YS1sb2cnO1xuaW1wb3J0ICdAaW90aXplL3RhcC9leHQvZGF0YSc7XG5pbXBvcnQgeyBPYnNlcnZhYmxlIH0gZnJvbSAncnhqcyc7XG5pbXBvcnQgeyBkZWJ1ZyB9IGZyb20gJy4uLy4uL2xvZ2dlcic7XG5pbXBvcnQgeyBTd2l0Y2hhYmxlU3RyZWFtTW9uaXRvciBhcyBTd2l0Y2hhYmxlU3RyZWFtQ29udHJvbGxlciB9IGZyb20gJy4uL3N3aXRjaGFibGUtc3RyZWFtLW1vbml0b3InO1xuaW1wb3J0IHtcbiAgRGF0YVNvdXJjZUNvbnRyb2xsZXIsXG4gIERhdGFTb3VyY2VUeXBlLFxuICBJdGVtSG9sZGVyLFxufSBmcm9tICcuL2RlZmluaXRpb25zJztcblxuY29uc3QgVEFHID0gJ0RhdGFNYW5hZ2VyJztcblxuZXhwb3J0IGNsYXNzIERhdGFIb2xkZXIge1xuICBjb25zdHJ1Y3RvcihwdWJsaWMgaXRlbXM6IEl0ZW1Ib2xkZXJbXSA9IFtdKSB7fVxuXG4gIGl0ZW0oaWQ6IHN0cmluZyk6IEl0ZW1Ib2xkZXIge1xuICAgIGNvbnN0IGl0ZW0gPSB0aGlzLml0ZW1zLmZpbmQoKHYpID0+IHYuaWQgPT0gaWQpO1xuICAgIGlmICghaXRlbSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBJdGVtIHdpdGggaWQgXCIke2lkfVwiIGRvZXMgbm90IGV4aXN0YCk7XG4gICAgfVxuICAgIHJldHVybiBpdGVtO1xuICB9XG5cbiAgYWRkKGl0ZW06IEl0ZW1Ib2xkZXIsIHJlcGxhY2U6IGJvb2xlYW4pIHtcbiAgICBpZiAocmVwbGFjZSB8fCB0aGlzLml0ZW1zLmZpbmQoKHYpID0+IHYuaWQgPT0gaXRlbS5pZCkgPT0gdW5kZWZpbmVkKSB7XG4gICAgICBkZWJ1ZyhUQUcsICdBZGRlZCBpdGVtOiAnLCBpdGVtKTtcbiAgICAgIHRoaXMuaXRlbXMucHVzaChpdGVtKTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuaXRlbShpdGVtLmlkKTtcbiAgfVxufVxuXG4vLyBleHBvcnQgZnVuY3Rpb24gbmV3QnVuZGxlQ29uZmlnVG9PbGRCdW5kbGVDb25maWcoYnVuZGxlc0NvbmZpZzogQnVuZGxlQ29uZmlnW10gfCB1bmRlZmluZWQpOiBCdW5kbGVDb25maWdQcmVkZWZpbmVkW10ge1xuLy8gICAgIGlmICghYnVuZGxlc0NvbmZpZykge1xuLy8gICAgICAgICByZXR1cm4gW107XG4vLyAgICAgfVxuLy8gICAgIHJldHVybiBidW5kbGVzQ29uZmlnLm1hcCgoYnVuZGxlQ29uZmlnOiBCdW5kbGVTY2hlbWFDb25maWcpID0+IHtcbi8vICAgICAgICAgY29uc3QgcHJlZGVmaW5lZENvbmZpZzogQnVuZGxlQ29uZmlnUHJlZGVmaW5lZCA9IHtcbi8vICAgICAgICAgICAgIGlkOiBidW5kbGVDb25maWcuaWQsXG4vLyAgICAgICAgICAgICBjb252ZXJ0ZXI6IHVuZGVmaW5lZCxcbi8vICAgICAgICAgICAgIG5hbWU6IGJ1bmRsZUNvbmZpZy5uYW1lIHx8IGBCdW5kbGUgJHtidW5kbGVDb25maWcuaWR9YCxcbi8vICAgICAgICAgICAgIHZhcmlhYmxlczogKGJ1bmRsZUNvbmZpZy52YXJpYWJsZXMgfHwgW10pLm1hcCgodmFyaWFibGVDb25maWc6IE1lbW9yeVZhcmlhYmxlQ29uZmlnKSA9PiB7XG4vLyAgICAgICAgICAgICAgICAgY29uc3QgdmFyaWFibGVUeXBlID0gVmFyaWFibGVUeXBlW3ZhcmlhYmxlQ29uZmlnLnR5cGVdO1xuLy8gICAgICAgICAgICAgICAgIGlmICh2YXJpYWJsZVR5cGUgPT09IHVuZGVmaW5lZCkge1xuLy8gICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYEludmFsaWQgdmFyaWFibGUgdHlwZTogJHt2YXJpYWJsZUNvbmZpZy50eXBlfWApO1xuLy8gICAgICAgICAgICAgICAgIH1cbi8vICAgICAgICAgICAgICAgICBsZXQgY29udmVydGVyOiBCb2R5Q29udmVydGVyPGFueT4gfCB1bmRlZmluZWQ7XG4vLyAgICAgICAgICAgICAgICAgaWYgKHZhcmlhYmxlQ29uZmlnLmNvbnZlcnRlcikge1xuLy8gICAgICAgICAgICAgICAgICAgICBjb252ZXJ0ZXIgPSB2YXJpYWJsZUNvbmZpZy5jb252ZXJ0ZXI7XG4vLyAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbi8vICAgICAgICAgICAgICAgICAgICAgY29udmVydGVyID0gZ2V0Q29udmVydGVyRnJvbUZvcm1hdCh2YXJpYWJsZVR5cGUsIHZhcmlhYmxlQ29uZmlnLmxlbmd0aCB8fCAxKTtcbi8vICAgICAgICAgICAgICAgICB9XG4vLyAgICAgICAgICAgICAgICAgY29uc3QgcHJlZGlmaW5lZFZhcmlhYmxlQ29uZmlnOiBUYXBWYXJpYWJsZS5Db25maWcgPSB7XG4vLyAgICAgICAgICAgICAgICAgICAgIGlkOiB2YXJpYWJsZUNvbmZpZy5pZCxcbi8vICAgICAgICAgICAgICAgICAgICAgY29udmVydGVyOiBjb252ZXJ0ZXIsXG4vLyAgICAgICAgICAgICAgICAgICAgIGxlbmd0aDogdmFyaWFibGVDb25maWcubGVuZ3RoLFxuLy8gICAgICAgICAgICAgICAgICAgICBuYW1lOiB2YXJpYWJsZUNvbmZpZy5uYW1lIHx8IGBWYXJpYWJsZSAke3ZhcmlhYmxlQ29uZmlnLmlkfWAsXG4vLyAgICAgICAgICAgICAgICAgICAgIHR5cGU6IHZhcmlhYmxlVHlwZSxcbi8vICAgICAgICAgICAgICAgICAgICAgdW5pdDogdmFyaWFibGVDb25maWcudW5pdFxuLy8gICAgICAgICAgICAgICAgIH07XG4vLyAgICAgICAgICAgICAgICAgcmV0dXJuIHByZWRpZmluZWRWYXJpYWJsZUNvbmZpZztcbi8vICAgICAgICAgICAgIH0pXG4vLyAgICAgICAgIH07XG4vLyAgICAgICAgIHJldHVybiBwcmVkZWZpbmVkQ29uZmlnO1xuLy8gICAgIH0pO1xuLy8gfVxuXG5leHBvcnQgY2xhc3MgRGF0YU1hbmFnZXJJb25pYzxcbiAgVmFyaWFibGVCeVR5cGUgZXh0ZW5kcyBSZWNvcmQ8c3RyaW5nLCBhbnk+ID0gUmVjb3JkPHN0cmluZywgYW55PixcbiAgVmFyaWFibGVLZXkgZXh0ZW5kcyBzdHJpbmcgPSBzdHJpbmcsXG4gIEJ1bmRsZUJ5VHlwZSBleHRlbmRzIFJlY29yZDxzdHJpbmcsIGFueT4gPSBSZWNvcmQ8c3RyaW5nLCBhbnk+LFxuICBCdW5kbGVLZXkgZXh0ZW5kcyBzdHJpbmcgPSBzdHJpbmdcbj4ge1xuICBjb25zdHJ1Y3RvcihwdWJsaWMgdGFwOiBUYXApIHtcbiAgICAvLyBjb25zdCBhbGxWYXJpYWJsZXM6IEFic3RyYWN0VmFyaWFibGU8VmFyaWFibGVCeVR5cGVbVmFyaWFibGVLZXldPltdID0gT2JqZWN0LnZhbHVlcyhkYXRhLnZhcmlhYmxlcyk7XG4gICAgLy8gdGhpcy50bHZDb252ZXJ0ZXIgPSBuZXcgVGx2QnVuZGxlQ29udmVydGVyKGFsbFZhcmlhYmxlcy5tYXAoKHZhcmlhYmxlOiBBYnN0cmFjdFZhcmlhYmxlPGFueT4pID0+IHtcbiAgICAvLyAgICAgaWYgKCEodmFyaWFibGUgaW5zdGFuY2VvZiBWYXJpYWJsZUNvbmZpZykpIHtcbiAgICAvLyAgICAgICAgIHRocm93IG5ldyBFcnJvcihgVmFyaWFibGUgJHt2YXJpYWJsZS5pZGVudGlmaWVyfSBoYXMgbm8gY29uZmlnYCk7XG4gICAgLy8gICAgIH1cbiAgICAvLyAgICAgcmV0dXJuIHtcbiAgICAvLyAgICAgICAgIGlkOiB2YXJpYWJsZS5jb25maWcuaWQsXG4gICAgLy8gICAgICAgICBuYW1lOiB2YXJpYWJsZS5jb25maWcubmFtZSxcbiAgICAvLyAgICAgICAgIGNvbnZlcnRlcjogdmFyaWFibGUuY29udmVydGVyXG4gICAgLy8gICAgIH07XG4gICAgLy8gfSkpO1xuICAgIC8vIHRoaXMuZGF0YVN0cmVhbSA9IHRoaXMuc2V0dXBEYXRhU3RyZWFtKCk7XG4gICAgLy8gdGhpcy5kYXRhTG9nZ2VyID0gRGF0YUxvZ2dlci5mcm9tVGFwKFxuICAgIC8vICAgICB0aGlzLnRhcCxcbiAgICAvLyAgICAge1xuICAgIC8vICAgICAgICAgcGVyaW9kOiAyMDAwIC8vIFRPRE8gY2hhbmdlXG4gICAgLy8gICAgIH1cbiAgICAvLyApO1xuICAgIC8vIHRoaXMudGFwLnZhcmlhYmxlcy5fdmFyaWFibGVzID0gZGF0YS52YXJpYWJsZXMgYXMgYW55O1xuICAgIC8vIHRoaXMudGFwLmJ1bmRsZXMuX2J1bmRsZXMgPSBkYXRhLmJ1bmRsZXMgYXMgYW55O1xuICAgIC8vIENoYW5nZSB2YXJpYWJsZSBzdHJlYW07XG4gICAgLy8gT2JqZWN0LnZhbHVlcyh0aGlzLmRhdGEudmFyaWFibGVzKS5tYXAoKHZhcmlhYmxlOiBhbnkpID0+IHtcbiAgICAvLyAgICAgY29uc3QgdmFyaWFibGVOYW1lID0gdmFyaWFibGUuY29uZmlnLm5hbWU7XG4gICAgLy8gICAgIC8vIGNvbnNvbGUubG9nKCdSZXBsYWNpbmcgbW9uaXRvciBmb3IgJywgdmFyaWFibGUpO1xuICAgIC8vICAgICB2YXJpYWJsZS5fbW9uaXRvciA9IE9ic2VydmFibGVNb25pdG9yLmZyb21PYnNlcnZhYmxlKFxuICAgIC8vICAgICAgICAgdGhpcy5kYXRhU3RyZWFtXG4gICAgLy8gICAgICAgICAgICAgLnBpcGUoXG4gICAgLy8gICAgICAgICAgICAgICAgIGZpbHRlcihkYXRhID0+IHZhcmlhYmxlTmFtZSBpbiBkYXRhKSxcbiAgICAvLyAgICAgICAgICAgICAgICAgbWFwKGRhdGEgPT4gZGF0YVt2YXJpYWJsZU5hbWVdKSxcbiAgICAvLyAgICAgICAgICAgICAgICAgcnhUYXAodmFsdWUgPT4gZGVidWcoVEFHLCBgRXh0cmFjdGVkIGtleSAke3ZhcmlhYmxlTmFtZX0gZnJvbSBtb25pdG9yaW5nIGRhdGFgLCB2YWx1ZSkpXG4gICAgLy8gICAgICAgICAgICAgKVxuICAgIC8vICAgICAgICAgLFxuICAgIC8vICAgICAgICAgTW9uaXRvckVuZ2luZS5TdGF0ZS5TVEFSVFxuICAgIC8vICAgICApO1xuICAgIC8vIH0pO1xuICAgIC8vIC8vIENoYW5nZSBidW5kbGUgc3RyZWFtO1xuICAgIC8vIE9iamVjdC52YWx1ZXModGhpcy5kYXRhLmJ1bmRsZXMpLm1hcCgoYnVuZGxlOiBhbnkpID0+IHtcbiAgICAvLyAgICAgYnVuZGxlLl9tb25pdG9yID0gT2JzZXJ2YWJsZU1vbml0b3IuZnJvbU9ic2VydmFibGUoXG4gICAgLy8gICAgICAgICB0aGlzLmRhdGFTdHJlYW1cbiAgICAvLyAgICAgICAgICAgICAucGlwZShcbiAgICAvLyAgICAgICAgICAgICAgICAgcnhUYXAodmFsdWUgPT4gZGVidWcoVEFHLCBgTmV3IGJ1bmRsZSB2YWx1ZSBgLCB2YWx1ZSkpXG4gICAgLy8gICAgICAgICAgICAgKVxuICAgIC8vICAgICAgICAgLFxuICAgIC8vICAgICAgICAgTW9uaXRvckVuZ2luZS5TdGF0ZS5TVEFSVFxuICAgIC8vICAgICApO1xuICAgIC8vICAgICAvLyBUT0RPIGZhY3Rvcml6ZSBhbmQgY2xlYW5cbiAgICAvLyAgICAgT2JqZWN0LnZhbHVlcyhidW5kbGUudmFyaWFibGVzKS5tYXAoKHZhcmlhYmxlOiBhbnkpID0+IHtcbiAgICAvLyAgICAgICAgIGNvbnN0IHZhcmlhYmxlTmFtZSA9IHZhcmlhYmxlLmNvbmZpZy5uYW1lO1xuICAgIC8vICAgICAgICAgLy8gY29uc29sZS5sb2coJ1JlcGxhY2luZyBtb25pdG9yIGZvciB2YXJpYWJsZSBpbiBidW5kbGUnLCB2YXJpYWJsZSk7XG4gICAgLy8gICAgICAgICB2YXJpYWJsZS5fbW9uaXRvciA9IE9ic2VydmFibGVNb25pdG9yLmZyb21PYnNlcnZhYmxlKFxuICAgIC8vICAgICAgICAgICAgIHRoaXMuZGF0YVN0cmVhbVxuICAgIC8vICAgICAgICAgICAgICAgICAucGlwZShcbiAgICAvLyAgICAgICAgICAgICAgICAgICAgIGZpbHRlcihkYXRhID0+IHZhcmlhYmxlTmFtZSBpbiBkYXRhKSxcbiAgICAvLyAgICAgICAgICAgICAgICAgICAgIG1hcChkYXRhID0+IGRhdGFbdmFyaWFibGVOYW1lXSksXG4gICAgLy8gICAgICAgICAgICAgICAgICAgICByeFRhcCh2YWx1ZSA9PiBkZWJ1ZyhUQUcsIGBFeHRyYWN0ZWQga2V5ICR7dmFyaWFibGVOYW1lfSBmcm9tIG1vbml0b3JpbmcgZGF0YWAsIHZhbHVlKSlcbiAgICAvLyAgICAgICAgICAgICAgICAgKVxuICAgIC8vICAgICAgICAgICAgICxcbiAgICAvLyAgICAgICAgICAgICBNb25pdG9yRW5naW5lLlN0YXRlLlNUQVJUXG4gICAgLy8gICAgICAgICApO1xuICAgIC8vICAgICB9KTtcbiAgICAvLyB9KTtcbiAgICAvLyBkZWJ1ZyhUQUcsICdOZXcgZGF0YSBtYW5hZ2VyIGluc3RhbmNlOiAnLCB0aGlzKTtcbiAgfVxuXG4gIC8vIGdldCB2YXJpYWJsZXMoKTogUmVjb3JkPFZhcmlhYmxlS2V5LCBBYnN0cmFjdFZhcmlhYmxlPFZhcmlhYmxlQnlUeXBlW1ZhcmlhYmxlS2V5XT4+IHtcbiAgLy8gICAgIHJldHVybiB0aGlzLmRhdGEudmFyaWFibGVzO1xuICAvLyB9XG5cbiAgLy8gZ2V0IGJ1bmRsZXMoKTogUmVjb3JkPEJ1bmRsZUtleSwgQnVuZGxlPEJ1bmRsZUJ5VHlwZVtCdW5kbGVLZXldPj4ge1xuICAvLyAgICAgcmV0dXJuIHRoaXMuZGF0YS5idW5kbGVzO1xuICAvLyB9XG5cbiAgcHVibGljIGdldCBzb3VyY2VDb250cm9sbGVyKCk6IERhdGFTb3VyY2VDb250cm9sbGVyIHtcbiAgICBjb25zdCBjdXJyZW50U291cmNlSWQgPVxuICAgICAgdGhpcy5zd2l0Y2hhYmxlU3RyZWFtQ29udHJvbGxlci5nZXRDdXJyZW50U291cmNlSWQoKTtcbiAgICByZXR1cm4gdGhpcy5zb3VyY2VDb250cm9sbGVyc1tjdXJyZW50U291cmNlSWRdO1xuICB9XG5cbiAgZ2V0IGlzTW9uaXRvcmluZ1J1bm5pbmcoKSB7XG4gICAgZm9yIChjb25zdCB2YWx1ZSBvZiBPYmplY3QudmFsdWVzKHRoaXMuc291cmNlQ29udHJvbGxlcnMpKSB7XG4gICAgICBpZiAodmFsdWUuc3RhdGUgPT0gTW9uaXRvckVuZ2luZS5TdGF0ZS5TVEFSVCkge1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgc3dpdGNoYWJsZVN0cmVhbUNvbnRyb2xsZXIhOiBTd2l0Y2hhYmxlU3RyZWFtQ29udHJvbGxlcjxhbnk+O1xuICAvLyBkYXRhU3RyZWFtOiBPYnNlcnZhYmxlPFJlY29yZDxzdHJpbmcsIGFueT4+O1xuICAvLyB0bHZDb252ZXJ0ZXI6IFRsdkJ1bmRsZUNvbnZlcnRlcjxSZWNvcmQ8c3RyaW5nLCBVaW50OEFycmF5Pj47XG4gIC8vIGRhdGFMb2dnZXI6IERhdGFMb2dnZXI7XG4gIHNvdXJjZUNvbnRyb2xsZXJzOiBSZWNvcmQ8c3RyaW5nLCBEYXRhU291cmNlQ29udHJvbGxlcj4gPSB7fTtcblxuICAvLyBwdWJsaWMgc3RhdGljIGZyb21TY2hlbWFDb25maWcodGFwOiBUYXAsIHNjaGVtYTogVGFwQ29uZmlndXJhdG9yQ29uZmlnKTogRGF0YU1hbmFnZXJJb25pYyB7XG4gIC8vICAgICBjb25zdCBidW5kbGVzID0gc2NoZW1hLmNvbmZpZy5kYXRhID8gc2NoZW1hLmNvbmZpZy5kYXRhLmJ1bmRsZXMgfHwgW10gOiBbXTtcbiAgLy8gICAgIHJldHVybiBEYXRhTWFuYWdlcklvbmljLmZyb21CdW5kbGVDb25maWcodGFwLCBidW5kbGVzKTtcbiAgLy8gfVxuXG4gIC8vIHB1YmxpYyBzdGF0aWMgZnJvbUJ1bmRsZUNvbmZpZyh0YXA6IFRhcCwgYnVuZGxlczogQnVuZGxlQ29uZmlnW10pOiBEYXRhTWFuYWdlcklvbmljIHtcbiAgLy8gICAgIHJldHVybiBuZXcgRGF0YU1hbmFnZXJJb25pYyhcbiAgLy8gICAgICAgICB0YXAsXG4gIC8vICAgICAgICAgRGF0YU1hbmFnZXJJb25pYy5jcmVhdGVEYXRhRnJvbVNjaGVtYUNvbmZpZyh0YXAsIGJ1bmRsZXMpXG4gIC8vICAgICApO1xuICAvLyB9XG5cbiAgLy8gcHVibGljIHN0YXRpYyBjcmVhdGVEYXRhRnJvbVNjaGVtYUNvbmZpZzxWYXJpYWJsZUJ5VHlwZSBleHRlbmRzIFJlY29yZDxzdHJpbmcsIGFueT4sIFZhcmlhYmxlS2V5IGV4dGVuZHMgc3RyaW5nLCBCdW5kbGVCeVR5cGUgZXh0ZW5kcyBSZWNvcmQ8c3RyaW5nLCBhbnk+LCBCdW5kbGVLZXkgZXh0ZW5kcyBzdHJpbmc+KHRhcDogVGFwLCBidW5kbGVzQ29uZmlnOiBCdW5kbGVTY2hlbWFDb25maWdbXSkge1xuICAvLyAgICAgY29uc3QgcHJlZGlmaW5lZENvbmZpZzogQnVuZGxlQ29uZmlnUHJlZGVmaW5lZFtdID0gbmV3QnVuZGxlQ29uZmlnVG9PbGRCdW5kbGVDb25maWcoYnVuZGxlc0NvbmZpZyk7XG5cbiAgLy8gICAgIHJldHVybiBEYXRhTWFuYWdlcklvbmljLmNyZWF0ZURhdGFGcm9tQ29uZmlnKHRhcCwgcHJlZGlmaW5lZENvbmZpZyk7XG4gIC8vIH1cblxuICAvLyBwdWJsaWMgc3RhdGljIGNyZWF0ZURhdGFGcm9tQ29uZmlnPFZhcmlhYmxlQnlUeXBlIGV4dGVuZHMgUmVjb3JkPHN0cmluZywgYW55PiwgVmFyaWFibGVLZXkgZXh0ZW5kcyBzdHJpbmcsIEJ1bmRsZUJ5VHlwZSBleHRlbmRzIFJlY29yZDxzdHJpbmcsIGFueT4sIEJ1bmRsZUtleSBleHRlbmRzIHN0cmluZz4odGFwOiBUYXAsIGJ1bmRsZXNDb25maWc6IEJ1bmRsZUNvbmZpZ1ByZWRlZmluZWRbXSkge1xuICAvLyAgICAgLy8gbGV0IGJ1bmRsZUNvbmZpZ0NvcHkgPSBbLi4uYnVuZGxlc0NvbmZpZ107XG4gIC8vICAgICBjb25zdCBidW5kbGVzOiBSZWNvcmQ8c3RyaW5nLCBhbnk+ID0ge307XG4gIC8vICAgICBidW5kbGVzQ29uZmlnLmZvckVhY2goKGJ1bmRsZUNvbmZpZzogQnVuZGxlQ29uZmlnUHJlZGVmaW5lZCkgPT4ge1xuICAvLyAgICAgICAgIGNvbnN0IGJ1bmRsZTogQnVuZGxlID0gQnVuZGxlLmNyZWF0ZUZyb21Db25maWcoYnVuZGxlQ29uZmlnLCB0YXAuc2VydmljZS5idW5kbGUsIHRhcC5zZXJ2aWNlLnZhcmlhYmxlKTtcbiAgLy8gICAgICAgICBidW5kbGVzW2J1bmRsZUNvbmZpZy5uYW1lXSA9IGJ1bmRsZTtcbiAgLy8gICAgIH0pO1xuXG4gIC8vICAgICBjb25zdCB2YXJpYWJsZXM6IFJlY29yZDxzdHJpbmcsIGFueT4gPSB7fTtcbiAgLy8gICAgIGJ1bmRsZXNDb25maWcuZm9yRWFjaCgoYnVuZGxlKSA9PiB7XG4gIC8vICAgICAgICAgYnVuZGxlLnZhcmlhYmxlcy5mb3JFYWNoKCh2YXJpYWJsZUNvbmZpZzogVGFwVmFyaWFibGUuQ29uZmlnKSA9PiB7XG4gIC8vICAgICAgICAgICAgIGRlYnVnKFRBRywgJ0NyZWF0ZSBmcm9tIHZhcmlhYmxlIGNvbmZpZzogJywgdmFyaWFibGVDb25maWcpO1xuICAvLyAgICAgICAgICAgICB2YXJpYWJsZXNbdmFyaWFibGVDb25maWcubmFtZSB8fCB2YXJpYWJsZUNvbmZpZy5pZC50b1N0cmluZygpXSA9IFRhcFZhcmlhYmxlLmNyZWF0ZUZyb21Db25maWcodmFyaWFibGVDb25maWcsIHRhcC5zZXJ2aWNlLnZhcmlhYmxlKTtcbiAgLy8gICAgICAgICB9KTtcbiAgLy8gICAgIH0pO1xuXG4gIC8vICAgICByZXR1cm4ge1xuICAvLyAgICAgICAgIGJ1bmRsZXM6IGJ1bmRsZXMgYXMgUmVjb3JkPEJ1bmRsZUtleSwgQnVuZGxlPEJ1bmRsZUJ5VHlwZVtCdW5kbGVLZXldPj4sXG4gIC8vICAgICAgICAgdmFyaWFibGVzOiB2YXJpYWJsZXMgYXMgUmVjb3JkPFZhcmlhYmxlS2V5LCBBYnN0cmFjdFZhcmlhYmxlPFZhcmlhYmxlQnlUeXBlW1ZhcmlhYmxlS2V5XT4+XG4gIC8vICAgICB9O1xuICAvLyB9XG5cbiAgbGlzdFZhcmlhYmxlcygpIHtcbiAgICByZXR1cm4gdGhpcy50YXAuZGF0YS5saXN0VmFyaWFibGVzKCk7XG4gIH1cblxuICBsaXN0QnVuZGxlcygpIHtcbiAgICByZXR1cm4gdGhpcy50YXAuZGF0YS5saXN0QnVuZGxlcygpO1xuICB9XG5cbiAgLy8gcHVibGljIHZhcmlhYmxlPFQgZXh0ZW5kcyBWYXJpYWJsZUtleT4oa2V5OiBUKTogQWJzdHJhY3RWYXJpYWJsZTxWYXJpYWJsZUJ5VHlwZVtUXT4ge1xuICAvLyAgICAgaWYgKCEoa2V5IGluIHRoaXMudmFyaWFibGVzKSkge1xuICAvLyAgICAgICAgIHRocm93IG5ldyBFcnJvcihgVmFyaWFibGUgd2l0aCBpZGVudGlmaWVyIFwiJHtrZXl9XCIgaXMgbm90IGNvbmZpZ3VyZWRgKTtcbiAgLy8gICAgIH1cbiAgLy8gICAgIHJldHVybiB0aGlzLnZhcmlhYmxlc1trZXldIGFzIEFic3RyYWN0VmFyaWFibGU8VmFyaWFibGVCeVR5cGVbVF0+O1xuICAvLyB9XG5cbiAgLy8gcHVibGljIGJ1bmRsZTxUIGV4dGVuZHMgQnVuZGxlS2V5PihrZXk6IFQpOiBCdW5kbGU8QnVuZGxlQnlUeXBlW1RdPiB7XG4gIC8vICAgICBpZiAoIShrZXkgaW4gdGhpcy5idW5kbGVzKSkge1xuICAvLyAgICAgICAgIHRocm93IG5ldyBFcnJvcihgQnVuZGxlIHdpdGggaWRlbnRpZmllciBcIiR7a2V5fVwiIGlzIG5vdCBjb25maWd1cmVkYCk7XG4gIC8vICAgICB9XG4gIC8vICAgICByZXR1cm4gdGhpcy5idW5kbGVzW2tleV0gYXMgYW55O1xuICAvLyB9XG5cbiAgcHVibGljIHN0b3BBbGwoKSB7XG4gICAgZGVidWcoVEFHLCAnU3RvcCBtb25pdG9yaW5nJyk7XG4gICAgLy8gZm9yIChjb25zdCBjdHJsS2V5IGluIHRoaXMuc291cmNlQ29udHJvbGxlcnMpIHtcbiAgICAvLyAgICAgdGhpcy5zb3VyY2VDb250cm9sbGVyc1tjdHJsS2V5XS5zdGF0ZSA9IE1vbml0b3JFbmdpbmUuU3RhdGUuUEFVU0U7XG4gICAgLy8gfVxuICAgIHRoaXMudGFwLmRhdGEubW9uaXRvcmluZy5zdG9wKCk7XG4gIH1cblxuICBwdWJsaWMgc3RhcnRBbGwocGVyaW9kPzogbnVtYmVyKSB7XG4gICAgLy8gZGVidWcoVEFHLCBgW0NvbnRyb2xsZXI9JHt0aGlzLnNvdXJjZUNvbnRyb2xsZXIuaWR9XSBTdGFydCBtb25pdG9yaW5nIHdpdGggcGVyaW9kICR7cGVyaW9kIHx8IHRoaXMuc291cmNlQ29udHJvbGxlci5wZXJpb2QudmFsdWV9YCwgdGhpcy5zb3VyY2VDb250cm9sbGVyKTtcbiAgICAvLyBpZiAocGVyaW9kKSB7XG4gICAgLy8gICAgIHRoaXMuc2V0TW9uaXRvcmluZ1BlcmlvZChwZXJpb2QpO1xuICAgIC8vIH1cbiAgICAvLyB0aGlzLnNvdXJjZUNvbnRyb2xsZXIuc3RhdGUgPSBNb25pdG9yRW5naW5lLlN0YXRlLlNUQVJUO1xuICAgIHRoaXMudGFwLmRhdGEubW9uaXRvcmluZy5zdGFydCgpO1xuICB9XG5cbiAgc2V0TW9uaXRvcmluZ1BlcmlvZChwZXJpb2Q6IG51bWJlcikge1xuICAgIGRlYnVnKFRBRywgJ0NoYW5naW5nIG1vbml0b3JpbmcgcGVyaW9kIHRvICcsIHBlcmlvZCk7XG4gICAgdGhpcy5zb3VyY2VDb250cm9sbGVyLnBlcmlvZC5uZXh0KHBlcmlvZCk7XG4gIH1cblxuICBwdWJsaWMgZGVzdHJveSgpIHtcbiAgICB0aGlzLnN0b3BBbGwoKTtcbiAgfVxuXG4gIHB1YmxpYyByZWZyZXNoKCkge1xuICAgIGlmICh0aGlzLnNvdXJjZUNvbnRyb2xsZXIucmVmcmVzaCkge1xuICAgICAgdGhpcy5zb3VyY2VDb250cm9sbGVyLnJlZnJlc2goKTtcbiAgICB9XG4gIH1cblxuICBjaGFuZ2VEYXRhU291cmNlKGRhdGFTb3VyY2U6IERhdGFTb3VyY2VUeXBlKSB7XG4gICAgc3dpdGNoIChkYXRhU291cmNlKSB7XG4gICAgICBjYXNlICdkYXRhbG9nJzpcbiAgICAgICAgdGhpcy51c2VEYXRhbG9nU291cmNlKCk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhpcy51c2VMaXZlU291cmNlKCk7XG4gICAgfVxuICB9XG5cbiAgdXNlTGl2ZVNvdXJjZSgpIHtcbiAgICB0aGlzLnN3aXRjaGFibGVTdHJlYW1Db250cm9sbGVyLnVzZVNvdXJjZSgnbGl2ZScpO1xuICB9XG5cbiAgdXNlRGF0YWxvZ1NvdXJjZSgpIHtcbiAgICB0aGlzLnN3aXRjaGFibGVTdHJlYW1Db250cm9sbGVyLnVzZVNvdXJjZSgnZGF0YWxvZycpO1xuICB9XG5cbiAgLy8gc2V0dXBEYXRhU3RyZWFtKCkge1xuICAvLyAgICAgY29uc3QgbW9uaXRvcmluZ1BlcmlvZCA9IDEwMDA7XG4gIC8vICAgICBkZWJ1ZyhUQUcsICdzZXR1cERhdGFTdHJlYW0nLCBgUGVyaW9kOiAke21vbml0b3JpbmdQZXJpb2R9YCk7XG4gIC8vICAgICB0aGlzLnNvdXJjZUNvbnRyb2xsZXJzWydkYXRhbG9nJ10gPSB7XG4gIC8vICAgICAgICAgc3RhdGU6IE1vbml0b3JFbmdpbmUuU3RhdGUuU1RPUCxcbiAgLy8gICAgICAgICBwZXJpb2Q6IG5ldyBCZWhhdmlvclN1YmplY3QobW9uaXRvcmluZ1BlcmlvZCksXG4gIC8vICAgICAgICAgaWQ6IGBkYXRhbG9nYFxuICAvLyAgICAgfTtcbiAgLy8gICAgIGNvbnN0IGRhdGFsb2dTdHJlYW0gPSBPYnNlcnZhYmxlTW9uaXRvci5jcmVhdGVTdHJlYW1Gcm9tQ2FsbGFibGUoXG4gIC8vICAgICAgICAgKCkgPT4ge1xuICAvLyAgICAgICAgICAgICBkZWJ1ZyhUQUcsICdOZXcgZGF0YSBsb2dnZXIgY2FsbCcpO1xuICAvLyAgICAgICAgICAgICByZXR1cm4gdGhpcy5kYXRhTG9nZ2VyLmRlcXVldWUoKVxuICAvLyAgICAgICAgICAgICAgICAgLnRoZW4oKGluZm8pID0+IHtcbiAgLy8gICAgICAgICAgICAgICAgICAgICBkZWJ1ZyhUQUcsICc9PT0+IE5FVyBQQUNLRVQgREVRVUVVRTogJywgaW5mbyk7XG4gIC8vICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGluZm87XG4gIC8vICAgICAgICAgICAgICAgICB9KVxuICAvLyAgICAgICAgICAgICAgICAgLnRoZW4oaW5mbyA9PiBpbmZvLnBhY2tldC5yYXdWYXJpYWJsZXMpXG4gIC8vICAgICAgICAgICAgICAgICAudGhlbigocmF3VmFyaWFibGVzOiBhbnkpID0+IHtcbiAgLy8gICAgICAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IGlkIG9mIE9iamVjdC5rZXlzKHJhd1ZhcmlhYmxlcykpIHtcbiAgLy8gICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgdmFyaWFibGU6IGFueSA9IE9iamVjdC52YWx1ZXModGhpcy52YXJpYWJsZXMpLmZpbmQoKHY6IGFueSkgPT4gdi5jb25maWcuaWQgPT0gaWQpO1xuICAvLyAgICAgICAgICAgICAgICAgICAgICAgICBpZiAodmFyaWFibGUpIHtcbiAgLy8gICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJhd1ZhcmlhYmxlc1t2YXJpYWJsZS5jb25maWcubmFtZV0gPSB2YXJpYWJsZS5jb252ZXJ0ZXIuZGVjb2RlKHJhd1ZhcmlhYmxlc1tpZF0pO1xuICAvLyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVsZXRlIHJhd1ZhcmlhYmxlc1tpZF07XG4gIC8vICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gIC8vICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZWJ1ZyhUQUcsICdWYXJpYWJsZSB3aXRoIGlkICcsIGlkLCAnIGlzIG5vdCByZWdpc3RlcmVkJyk7XG4gIC8vICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgLy8gICAgICAgICAgICAgICAgICAgICB9XG4gIC8vICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJhd1ZhcmlhYmxlcztcbiAgLy8gICAgICAgICAgICAgICAgIH0pXG4gIC8vICAgICAgICAgICAgICAgICAudGhlbigoaW5mbykgPT4ge1xuICAvLyAgICAgICAgICAgICAgICAgICAgIGRlYnVnKFRBRywgJz09PT4gTkVXIFBBQ0tFVCBJTlRFUlBFUlQ6ICcsIGluZm8pO1xuICAvLyAgICAgICAgICAgICAgICAgICAgIHJldHVybiBpbmZvO1xuICAvLyAgICAgICAgICAgICAgICAgfSk7XG4gIC8vICAgICAgICAgfSxcbiAgLy8gICAgICAgICB7XG4gIC8vICAgICAgICAgICAgIGR1ZVRpbWU6IDAsXG4gIC8vICAgICAgICAgICAgIGlnbm9yZUVycm9yczogdHJ1ZVxuICAvLyAgICAgICAgIH0sXG4gIC8vICAgICAgICAgdGhpcy5zb3VyY2VDb250cm9sbGVyc1snZGF0YWxvZyddXG4gIC8vICAgICApO1xuXG4gIC8vICAgICB0aGlzLnNvdXJjZUNvbnRyb2xsZXJzWydsaXZlJ10gPSB7XG4gIC8vICAgICAgICAgc3RhdGU6IE1vbml0b3JFbmdpbmUuU3RhdGUuU1RPUCxcbiAgLy8gICAgICAgICBwZXJpb2Q6IG5ldyBCZWhhdmlvclN1YmplY3QobW9uaXRvcmluZ1BlcmlvZCksXG4gIC8vICAgICAgICAgaWQ6IGBsaXZlYFxuICAvLyAgICAgfTtcbiAgLy8gICAgIGNvbnN0IGxpdmVQcm9maWxlU3RyZWFtID0gT2JzZXJ2YWJsZU1vbml0b3IuY3JlYXRlU3RyZWFtRnJvbUNhbGxhYmxlPGFueT4oXG4gIC8vICAgICAgICAgYXN5bmMgKHRpbWU6IG51bWJlcikgPT4ge1xuICAvLyAgICAgICAgICAgICBkZWJ1ZyhUQUcsIGBOZXcgY2FsbCAke3RpbWV9IHRvIHJlYWQgcHJvZmlsZWApO1xuICAvLyAgICAgICAgICAgICBjb25zdCBwcm9maWxlRGF0YSA9IChhd2FpdCB0aGlzLnRhcC5zZXJ2aWNlLnZhcmlhYmxlLnJlYWRQcm9maWxlKCkpLmJvZHkoKTtcbiAgLy8gICAgICAgICAgICAgcmV0dXJuIHRoaXMudGx2Q29udmVydGVyLmRlY29kZShwcm9maWxlRGF0YSk7XG4gIC8vICAgICAgICAgfSxcbiAgLy8gICAgICAgICB7XG4gIC8vICAgICAgICAgICAgIGR1ZVRpbWU6IDAsXG4gIC8vICAgICAgICAgICAgIGlnbm9yZUVycm9yczogdHJ1ZVxuICAvLyAgICAgICAgIH0sXG4gIC8vICAgICAgICAgdGhpcy5zb3VyY2VDb250cm9sbGVyc1snbGl2ZSddXG4gIC8vICAgICApO1xuXG4gIC8vICAgICB0aGlzLnN3aXRjaGFibGVTdHJlYW1Db250cm9sbGVyID0gbmV3IFN3aXRjaGFibGVTdHJlYW1Db250cm9sbGVyKFxuICAvLyAgICAgICAgIHtcbiAgLy8gICAgICAgICAgICAgJ2xpdmUnOiB7XG4gIC8vICAgICAgICAgICAgICAgICBpZDogJ2xpdmUnLFxuICAvLyAgICAgICAgICAgICAgICAgc3RyZWFtOiBsaXZlUHJvZmlsZVN0cmVhbVxuICAvLyAgICAgICAgICAgICB9LFxuICAvLyAgICAgICAgICAgICAnZGF0YWxvZyc6IHtcbiAgLy8gICAgICAgICAgICAgICAgIGlkOiAnZGF0YWxvZycsXG4gIC8vICAgICAgICAgICAgICAgICBzdHJlYW06IGRhdGFsb2dTdHJlYW1cbiAgLy8gICAgICAgICAgICAgfVxuICAvLyAgICAgICAgIH0sXG4gIC8vICAgICAgICAgJ2xpdmUnXG4gIC8vICAgICApO1xuXG4gIC8vICAgICByZXR1cm4gdGhpcy5zd2l0Y2hhYmxlU3RyZWFtQ29udHJvbGxlci5hc09ic2VydmFibGUoKTtcbiAgLy8gICAgIC8vIC5waXBlKFxuICAvLyAgICAgLy8gICAgIHJ4VGFwKHZhbHVlcyA9PiB7XG4gIC8vICAgICAvLyAgICAgICAgIGRlYnVnKFRBRywgJyMjIyMjIyMjIyMjIyMjIyMjJywgdmFsdWVzKVxuICAvLyAgICAgLy8gICAgIH0pXG4gIC8vICAgICAvLyApO1xuICAvLyB9XG59XG4iXX0=