@tensorflow/tfjs-converter
Version:
Tensorflow model converter for javascript
183 lines • 41.4 kB
JavaScript
/**
* @license
* Copyright 2018 Google LLC. All Rights Reserved.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* =============================================================================
*/
// tslint:disable-next-line: no-imports-from-dist
import * as tfOps from '@tensorflow/tfjs-core/dist/ops/ops_for_converter';
import { getPadding, getParamValue } from './utils';
function fusedConvAndDepthWiseParams(node, tensorMap, context) {
const [extraOp, activationFunc] = getParamValue('fusedOps', node, tensorMap, context);
const isBiasAdd = extraOp === 'biasadd';
const noBiasAdd = !isBiasAdd;
const isPrelu = activationFunc === 'prelu';
const isBatchNorm = extraOp === 'fusedbatchnorm';
const numArgs = getParamValue('numArgs', node, tensorMap, context);
if (isBiasAdd) {
if (isPrelu && numArgs !== 2) {
throw new Error('FusedConv2d and DepthwiseConv2d with BiasAdd and Prelu ' +
'must have two extra arguments: bias and alpha.');
}
if (!isPrelu && isBiasAdd && numArgs !== 1) {
throw new Error('FusedConv2d and DepthwiseConv2d with BiasAdd must have ' +
'one extra argument: bias.');
}
}
if (isBatchNorm) {
throw new Error('FusedConv2d and DepthwiseConv2d with FusedBatchNorm is not supported');
}
const stride = getParamValue('strides', node, tensorMap, context);
const pad = getPadding(node, tensorMap, context);
const dataFormat = getParamValue('dataFormat', node, tensorMap, context)
.toUpperCase();
const dilations = getParamValue('dilations', node, tensorMap, context);
let [biasArg, preluArg] = getParamValue('args', node, tensorMap, context);
if (noBiasAdd) {
preluArg = biasArg;
biasArg = undefined;
}
const leakyreluAlpha = getParamValue('leakyreluAlpha', node, tensorMap, context);
return {
stride,
pad,
dataFormat,
dilations,
biasArg,
preluArg,
activationFunc,
leakyreluAlpha
};
}
export const executeOp = (node, tensorMap, context) => {
switch (node.op) {
case 'Conv1D': {
const stride = getParamValue('stride', node, tensorMap, context);
const pad = getParamValue('pad', node, tensorMap, context);
const dataFormat = getParamValue('dataFormat', node, tensorMap, context)
.toUpperCase();
const dilation = getParamValue('dilation', node, tensorMap, context);
return [tfOps.conv1d(getParamValue('x', node, tensorMap, context), getParamValue('filter', node, tensorMap, context), stride, pad, dataFormat, dilation)];
}
case 'Conv2D': {
const stride = getParamValue('strides', node, tensorMap, context);
const pad = getPadding(node, tensorMap, context);
const dataFormat = getParamValue('dataFormat', node, tensorMap, context)
.toUpperCase();
const dilations = getParamValue('dilations', node, tensorMap, context);
return [tfOps.conv2d(getParamValue('x', node, tensorMap, context), getParamValue('filter', node, tensorMap, context), [stride[1], stride[2]], pad, dataFormat, [dilations[1], dilations[2]])];
}
case '_FusedConv2D': {
const { stride, pad, dataFormat, dilations, biasArg, preluArg, activationFunc, leakyreluAlpha } = fusedConvAndDepthWiseParams(node, tensorMap, context);
return [tfOps.fused.conv2d({
x: getParamValue('x', node, tensorMap, context),
filter: getParamValue('filter', node, tensorMap, context),
strides: [stride[1], stride[2]],
pad: pad,
dataFormat: dataFormat,
dilations: [dilations[1], dilations[2]],
bias: biasArg,
activation: activationFunc,
preluActivationWeights: preluArg,
leakyreluAlpha
})];
}
case 'FusedDepthwiseConv2dNative': {
const { stride, pad, dataFormat, dilations, biasArg, preluArg, activationFunc, leakyreluAlpha, } = fusedConvAndDepthWiseParams(node, tensorMap, context);
return [tfOps.fused.depthwiseConv2d({
x: getParamValue('x', node, tensorMap, context),
filter: getParamValue('filter', node, tensorMap, context),
strides: [stride[1], stride[2]],
pad: pad,
dataFormat: dataFormat,
dilations: [dilations[1], dilations[2]],
bias: biasArg,
activation: activationFunc,
preluActivationWeights: preluArg,
leakyreluAlpha
})];
}
case 'Conv2DBackpropInput':
case 'Conv2dTranspose': {
const shape = getParamValue('outputShape', node, tensorMap, context);
const stride = getParamValue('strides', node, tensorMap, context);
const pad = getPadding(node, tensorMap, context);
return [tfOps.conv2dTranspose(getParamValue('x', node, tensorMap, context), getParamValue('filter', node, tensorMap, context), shape, [stride[1], stride[2]], pad)];
}
case 'DepthwiseConv2dNative':
case 'DepthwiseConv2d': {
const stride = getParamValue('strides', node, tensorMap, context);
const pad = getPadding(node, tensorMap, context);
const dilations = getParamValue('dilations', node, tensorMap, context);
const dataFormat = getParamValue('dataFormat', node, tensorMap, context)
.toUpperCase();
return [tfOps.depthwiseConv2d(getParamValue('input', node, tensorMap, context), getParamValue('filter', node, tensorMap, context), [stride[1], stride[2]], pad, dataFormat, [dilations[1], dilations[2]])];
}
case 'Conv3D': {
const stride = getParamValue('strides', node, tensorMap, context);
const pad = getParamValue('pad', node, tensorMap, context);
const dataFormat = getParamValue('dataFormat', node, tensorMap, context)
.toUpperCase();
const dilations = getParamValue('dilations', node, tensorMap, context);
return [tfOps.conv3d(getParamValue('x', node, tensorMap, context), getParamValue('filter', node, tensorMap, context), [stride[1], stride[2], stride[3]], pad, dataFormat, [dilations[1], dilations[2], dilations[3]])];
}
case 'AvgPool': {
const stride = getParamValue('strides', node, tensorMap, context);
const pad = getParamValue('pad', node, tensorMap, context);
const kernelSize = getParamValue('kernelSize', node, tensorMap, context);
return [tfOps.avgPool(getParamValue('x', node, tensorMap, context), [kernelSize[1], kernelSize[2]], [stride[1], stride[2]], pad)];
}
case 'MaxPool': {
const stride = getParamValue('strides', node, tensorMap, context);
const pad = getParamValue('pad', node, tensorMap, context);
const kernelSize = getParamValue('kernelSize', node, tensorMap, context);
return [tfOps.maxPool(getParamValue('x', node, tensorMap, context), [kernelSize[1], kernelSize[2]], [stride[1], stride[2]], pad)];
}
case 'MaxPoolWithArgmax': {
const stride = getParamValue('strides', node, tensorMap, context);
const pad = getParamValue('pad', node, tensorMap, context);
const kernelSize = getParamValue('kernelSize', node, tensorMap, context);
const includeBatchInIndex = getParamValue('includeBatchInIndex', node, tensorMap, context);
const { result, indexes } = tfOps.maxPoolWithArgmax(getParamValue('x', node, tensorMap, context), [kernelSize[1], kernelSize[2]], [stride[1], stride[2]], pad, includeBatchInIndex);
return [result, indexes];
}
case 'AvgPool3D': {
const stride = getParamValue('strides', node, tensorMap, context);
const pad = getParamValue('pad', node, tensorMap, context);
const kernelSize = getParamValue('kernelSize', node, tensorMap, context);
return [tfOps.avgPool3d(getParamValue('x', node, tensorMap, context), [kernelSize[1], kernelSize[2], kernelSize[3]], [stride[1], stride[2], stride[3]], pad)];
}
case 'MaxPool3D': {
const stride = getParamValue('strides', node, tensorMap, context);
const pad = getParamValue('pad', node, tensorMap, context);
const kernelSize = getParamValue('kernelSize', node, tensorMap, context);
return [tfOps.maxPool3d(getParamValue('x', node, tensorMap, context), [kernelSize[1], kernelSize[2], kernelSize[3]], [stride[1], stride[2], stride[3]], pad)];
}
case 'Dilation2D': {
const strides = getParamValue('strides', node, tensorMap, context);
const pad = getParamValue('pad', node, tensorMap, context);
const dilations = getParamValue('dilations', node, tensorMap, context);
// strides: [1, stride_height, stride_width, 1].
const strideHeight = strides[1];
const strideWidth = strides[2];
// dilations: [1, dilation_height, dilation_width, 1].
const dilationHeight = dilations[1];
const dilationWidth = dilations[2];
return [tfOps.dilation2d(getParamValue('x', node, tensorMap, context), getParamValue('filter', node, tensorMap, context), [strideHeight, strideWidth], pad, [dilationHeight, dilationWidth], 'NHWC' /* dataFormat */)];
}
default:
throw TypeError(`Node type ${node.op} is not implemented`);
}
};
export const CATEGORY = 'convolution';
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29udm9sdXRpb25fZXhlY3V0b3IuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi90ZmpzLWNvbnZlcnRlci9zcmMvb3BlcmF0aW9ucy9leGVjdXRvcnMvY29udm9sdXRpb25fZXhlY3V0b3IudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7Ozs7Ozs7Ozs7OztHQWVHO0FBR0gsaURBQWlEO0FBQ2pELE9BQU8sS0FBSyxLQUFLLE1BQU0sa0RBQWtELENBQUM7QUFNMUUsT0FBTyxFQUFDLFVBQVUsRUFBRSxhQUFhLEVBQUMsTUFBTSxTQUFTLENBQUM7QUFFbEQsU0FBUywyQkFBMkIsQ0FDaEMsSUFBVSxFQUFFLFNBQTBCLEVBQUUsT0FBeUI7SUFDbkUsTUFBTSxDQUFDLE9BQU8sRUFBRSxjQUFjLENBQUMsR0FDMUIsYUFBYSxDQUFDLFVBQVUsRUFBRSxJQUFJLEVBQUUsU0FBUyxFQUFFLE9BQU8sQ0FBYyxDQUFDO0lBRXRFLE1BQU0sU0FBUyxHQUFHLE9BQU8sS0FBSyxTQUFTLENBQUM7SUFDeEMsTUFBTSxTQUFTLEdBQUcsQ0FBQyxTQUFTLENBQUM7SUFDN0IsTUFBTSxPQUFPLEdBQUcsY0FBYyxLQUFLLE9BQU8sQ0FBQztJQUMzQyxNQUFNLFdBQVcsR0FBRyxPQUFPLEtBQUssZ0JBQWdCLENBQUM7SUFFakQsTUFBTSxPQUFPLEdBQ1IsYUFBYSxDQUFDLFNBQVMsRUFBRSxJQUFJLEVBQUUsU0FBUyxFQUFFLE9BQU8sQ0FBWSxDQUFDO0lBQ25FLElBQUksU0FBUyxFQUFFO1FBQ2IsSUFBSSxPQUFPLElBQUksT0FBTyxLQUFLLENBQUMsRUFBRTtZQUM1QixNQUFNLElBQUksS0FBSyxDQUNYLHlEQUF5RDtnQkFDekQsZ0RBQWdELENBQUMsQ0FBQztTQUN2RDtRQUNELElBQUksQ0FBQyxPQUFPLElBQUksU0FBUyxJQUFJLE9BQU8sS0FBSyxDQUFDLEVBQUU7WUFDMUMsTUFBTSxJQUFJLEtBQUssQ0FDWCx5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WUFDbkUsTUFBTSxHQUFHLEdBQUcsYUFBYSxDQUFDLEtBQUssRUFBRSxJQUFJLEVBQUUsU0FBUyxFQUFFLE9BQU8sQ0FBQyxDQUFDO1lBQzNELE1BQU0sU0FBUyxHQUNYLGFBQWEsQ0FBQyxXQUFXLEVBQUUsSUFBSSxFQUFFLFNBQVMsRUFBRSxPQUFPLENBQWEsQ0FBQztZQUVyRSxnREFBZ0Q7WUFDaEQsTUFBTSxZQUFZLEdBQUcsT0FBTyxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQ2hDLE1BQU0sV0FBVyxHQUFHLE9BQU8sQ0FBQyxDQUFDLENBQUMsQ0FBQztZQUUvQixzREFBc0Q7WUFDdEQsTUFBTSxjQUFjLEdBQUcsU0FBUyxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQ3BDLE1BQU0sYUFBYSxHQUFHLFNBQVMsQ0FBQyxDQUFDLENBQUMsQ0FBQztZQUVuQyxPQUFPLENBQUMsS0FBSyxDQUFDLFVBQVUsQ0FDcEIsYUFBYSxDQUFDLEdBQUcsRUFBRSxJQUFJLEVBQUUsU0FBUyxFQUFFLE9BQU8sQ0FDL0IsRUFDWixhQUFhLENBQUMsUUFBUSxFQUFFLElBQUksRUFBRSxTQUFTLEVBQUUsT0FBTyxDQUFhLEVBQzdELENBQUMsWUFBWSxFQUFFLFdBQVcsQ0FBQyxFQUFFLEdBQXVCLEVBQ3BELENBQUMsY0FBYyxFQUFFLGFBQWEsQ0FBQyxFQUFFLE1BQU0sQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDLENBQUM7U0FDaEU7UUFFRDtZQUNFLE1BQU0sU0FBUyxDQUFDLGFBQWEsSUFBSSxDQUFDLEVBQUUscUJBQXFCLENBQUMsQ0FBQztLQUM5RDtBQUNILENBQUMsQ0FBQztBQUVOLE1BQU0sQ0FBQyxNQUFNLFFBQVEsR0FBRyxhQUFhLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgMjAxOCBHb29nbGUgTExDLiBBbGwgUmlnaHRzIFJlc2VydmVkLlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKiA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICovXG5cbmltcG9ydCB7UmFuaywgVGVuc29yLCBUZW5zb3IzRCwgVGVuc29yNEQsIFRlbnNvcjVEfSBmcm9tICdAdGVuc29yZmxvdy90ZmpzLWNvcmUnO1xuLy8gdHNsaW50OmRpc2FibGUtbmV4dC1saW5lOiBuby1pbXBvcnRzLWZyb20tZGlzdFxuaW1wb3J0ICogYXMgdGZPcHMgZnJvbSAnQHRlbnNvcmZsb3cvdGZqcy1jb3JlL2Rpc3Qvb3BzL29wc19mb3JfY29udmVydGVyJztcblxuaW1wb3J0IHtOYW1lZFRlbnNvcnNNYXB9IGZyb20gJy4uLy4uL2RhdGEvdHlwZXMnO1xuaW1wb3J0IHtFeGVjdXRpb25Db250ZXh0fSBmcm9tICcuLi8uLi9leGVjdXRvci9leGVjdXRpb25fY29udGV4dCc7XG5pbXBvcnQge0ludGVybmFsT3BFeGVjdXRvciwgTm9kZX0gZnJvbSAnLi4vdHlwZXMnO1xuXG5pbXBvcnQge2dldFBhZGRpbmcsIGdldFBhcmFtVmFsdWV9IGZyb20gJy4vdXRpbHMnO1xuXG5mdW5jdGlvbiBmdXNlZENvbnZBbmREZXB0aFdpc2VQYXJhbXMoXG4gICAgbm9kZTogTm9kZSwgdGVuc29yTWFwOiBOYW1lZFRlbnNvcnNNYXAsIGNvbnRleHQ6IEV4ZWN1dGlvbkNvbnRleHQpIHtcbiAgY29uc3QgW2V4dHJhT3AsIGFjdGl2YXRpb25GdW5jXSA9XG4gICAgICAoZ2V0UGFyYW1WYWx1ZSgnZnVzZWRPcHMnLCBub2RlLCB0ZW5zb3JNYXAsIGNvbnRleHQpIGFzIHN0cmluZ1tdKTtcblxuICBjb25zdCBpc0JpYXNBZGQgPSBleHRyYU9wID09PSAnYmlhc2FkZCc7XG4gIGNvbnN0IG5vQmlhc0FkZCA9ICFpc0JpYXNBZGQ7XG4gIGNvbnN0IGlzUHJlbHUgPSBhY3RpdmF0aW9uRnVuYyA9PT0gJ3ByZWx1JztcbiAgY29uc3QgaXNCYXRjaE5vcm0gPSBleHRyYU9wID09PSAnZnVzZWRiYXRjaG5vcm0nO1xuXG4gIGNvbnN0IG51bUFyZ3MgPVxuICAgICAgKGdldFBhcmFtVmFsdWUoJ251bUFyZ3MnLCBub2RlLCB0ZW5zb3JNYXAsIGNvbnRleHQpIGFzIG51bWJlcik7XG4gIGlmIChpc0JpYXNBZGQpIHtcbiAgICBpZiAoaXNQcmVsdSAmJiBudW1BcmdzICE9PSAyKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgICAgJ0Z1c2VkQ29udjJkIGFuZCBEZXB0aHdpc2VDb252MmQgd2l0aCBCaWFzQWRkIGFuZCBQcmVsdSAnICtcbiAgICAgICAgICAnbXVzdCBoYXZlIHR3byBleHRyYSBhcmd1bWVudHM6IGJpYXMgYW5kIGFscGhhLicpO1xuICAgIH1cbiAgICBpZiAoIWlzUHJlbHUgJiYgaXNCaWFzQWRkICYmIG51bUFyZ3MgIT09IDEpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgICAnRnVzZWRDb252MmQgYW5kIERlcHRod2lzZUNvbnYyZCB3aXRoIEJpYXNBZGQgbXVzdCBoYXZlICcgK1xuICAgICAgICAgICdvbmUgZXh0cmEgYXJndW1lbnQ6IGJpYXMuJyk7XG4gICAgfVxuICB9XG4gIGlmIChpc0JhdGNoTm9ybSkge1xuICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgJ0Z1c2VkQ29udjJkIGFuZCBEZXB0aHdpc2VDb252MmQgd2l0aCBGdXNlZEJhdGNoTm9ybSBpcyBub3Qgc3VwcG9ydGVkJyk7XG4gIH1cbiAgY29uc3Qgc3RyaWRlID0gZ2V0UGFyYW1WYWx1ZSgnc3RyaWRlcycsIG5vZGUsIHRlbnNvck1hcCwgY29udGV4dCkgYXMgbnVtYmVyW107XG4gIGNvbnN0IHBhZCA9IGdldFBhZGRpbmcobm9kZSwgdGVuc29yTWFwLCBjb250ZXh0KTtcbiAgY29uc3QgZGF0YUZvcm1hdCA9XG4gICAgICAoZ2V0UGFyYW1WYWx1ZSgnZGF0YUZvcm1hdCcsIG5vZGUsIHRlbnNvck1hcCwgY29udGV4dCkgYXMgc3RyaW5nKVxuICAgICAgICAgIC50b1VwcGVyQ2FzZSgpO1xuICBjb25zdCBkaWxhdGlvbnMgPVxuICAgICAgZ2V0UGFyYW1WYWx1ZSgnZGlsYXRpb25zJywgbm9kZSwgdGVuc29yTWFwLCBjb250ZXh0KSBhcyBudW1iZXJbXTtcbiAgbGV0IFtiaWFzQXJnLCBwcmVsdUFyZ10gPVxuICAgICAgZ2V0UGFyYW1WYWx1ZSgnYXJncycsIG5vZGUsIHRlbnNvck1hcCwgY29udGV4dCkgYXMgVGVuc29yW107XG4gIGlmIChub0JpYXNBZGQpIHtcbiAgICBwcmVsdUFyZyA9IGJpYXNBcmc7XG4gICAgYmlhc0FyZyA9IHVuZGVmaW5lZDtcbiAgfVxuICBjb25zdCBsZWFreXJlbHVBbHBoYSA9XG4gICAgICBnZXRQYXJhbVZhbHVlKCdsZWFreXJlbHVBbHBoYScsIG5vZGUsIHRlbnNvck1hcCwgY29udGV4dCkgYXMgbnVtYmVyO1xuXG4gIHJldHVybiB7XG4gICAgc3RyaWRlLFxuICAgIHBhZCxcbiAgICBkYXRhRm9ybWF0LFxuICAgIGRpbGF0aW9ucyxcbiAgICBiaWFzQXJnLFxuICAgIHByZWx1QXJnLFxuICAgIGFjdGl2YXRpb25GdW5jLFxuICAgIGxlYWt5cmVsdUFscGhhXG4gIH07XG59XG5cbmV4cG9ydCBjb25zdCBleGVjdXRlT3A6IEludGVybmFsT3BFeGVjdXRvciA9XG4gICAgKG5vZGU6IE5vZGUsIHRlbnNvck1hcDogTmFtZWRUZW5zb3JzTWFwLFxuICAgICBjb250ZXh0OiBFeGVjdXRpb25Db250ZXh0KTogVGVuc29yW10gPT4ge1xuICAgICAgc3dpdGNoIChub2RlLm9wKSB7XG4gICAgICAgIGNhc2UgJ0NvbnYxRCc6IHtcbiAgICAgICAgICBjb25zdCBzdHJpZGUgPVxuICAgICAgICAgICAgICBnZXRQYXJhbVZhbHVlKCdzdHJpZGUnLCBub2RlLCB0ZW5zb3JNYXAsIGNvbnRleHQpIGFzIG51bWJlcjtcbiAgICAgICAgICBjb25zdCBwYWQgPSBnZXRQYXJhbVZhbHVlKCdwYWQnLCBub2RlLCB0ZW5zb3JNYXAsIGNvbnRleHQpO1xuICAgICAgICAgIGNvbnN0IGRhdGFGb3JtYXQgPVxuICAgICAgICAgICAgICAoZ2V0UGFyYW1WYWx1ZSgnZGF0YUZvcm1hdCcsIG5vZGUsIHRlbnNvck1hcCwgY29udGV4dCkgYXMgc3RyaW5nKVxuICAgICAgICAgICAgICAgICAgLnRvVXBwZXJDYXNlKCk7XG4gICAgICAgICAgY29uc3QgZGlsYXRpb24gPVxuICAgICAgICAgICAgICBnZXRQYXJhbVZhbHVlKCdkaWxhdGlvbicsIG5vZGUsIHRlbnNvck1hcCwgY29udGV4dCkgYXMgbnVtYmVyO1xuICAgICAgICAgIHJldHVybiBbdGZPcHMuY29udjFkKFxuICAgICAgICAgICAgICBnZXRQYXJhbVZhbHVlKCd4Jywgbm9kZSwgdGVuc29yTWFwLCBjb250ZXh0KSBhcyBUZW5zb3IzRCxcbiAgICAgICAgICAgICAgZ2V0UGFyYW1WYWx1ZSgnZmlsdGVyJywgbm9kZSwgdGVuc29yTWFwLCBjb250ZXh0KSBhcyBUZW5zb3IzRCxcbiAgICAgICAgICAgICAgc3RyaWRlLCBwYWQgYXMgJ3ZhbGlkJyB8ICdzYW1lJywgZGF0YUZvcm1hdCBhcyAnTldDJyB8ICdOQ1cnLFxuICAgICAgICAgICAgICBkaWxhdGlvbildO1xuICAgICAgICB9XG4gICAgICAgIGNhc2UgJ0NvbnYyRCc6IHtcbiAgICAgICAgICBjb25zdCBzdHJpZGUgPVxuICAgICAgICAgICAgICBnZXRQYXJhbVZhbHVlKCdzdHJpZGVzJywgbm9kZSwgdGVuc29yTWFwLCBjb250ZXh0KSBhcyBudW1iZXJbXTtcbiAgICAgICAgICBjb25zdCBwYWQgPSBnZXRQYWRkaW5nKG5vZGUsIHRlbnNvck1hcCwgY29udGV4dCk7XG4gICAgICAgICAgY29uc3QgZGF0YUZvcm1hdCA9XG4gICAgICAgICAgICAgIChnZXRQYXJhbVZhbHVlKCdkYXRhRm9ybWF0Jywgbm9kZSwgdGVuc29yTWFwLCBjb250ZXh0KSBhcyBzdHJpbmcpXG4gICAgICAgICAgICAgICAgICAudG9VcHBlckNhc2UoKTtcbiAgICAgICAgICBjb25zdCBkaWxhdGlvbnMgPVxuICAgICAgICAgICAgICBnZXRQYXJhbVZhbHVlKCdkaWxhdGlvbnMnLCBub2RlLCB0ZW5zb3JNYXAsIGNvbnRleHQpIGFzIG51bWJlcltdO1xuICAgICAgICAgIHJldHVybiBbdGZPcHMuY29udjJkKFxuICAgICAgICAgICAgICBnZXRQYXJhbVZhbHVlKCd4Jywgbm9kZSwgdGVuc29yTWFwLCBjb250ZXh0KSBhcyBUZW5zb3IzRCB8XG4gICAgICAgICAgICAgICAgICBUZW5zb3I0RCxcbiAgICAgICAgICAgICAgZ2V0UGFyYW1WYWx1ZSgnZmlsdGVyJywgbm9kZSwgdGVuc29yTWFwLCBjb250ZXh0KSBhcyBUZW5zb3I0RCxcbiAgICAgICAgICAgICAgW3N0cmlkZVsxXSwgc3RyaWRlWzJdXSwgcGFkIGFzICd2YWxpZCcgfCAnc2FtZScsXG4gICAgICAgICAgICAgIGRhdGFGb3JtYXQgYXMgJ05IV0MnIHwgJ05DSFcnLCBbZGlsYXRpb25zWzFdLCBkaWxhdGlvbnNbMl1dKV07XG4gICAgICAgIH1cbiAgICAgICAgY2FzZSAnX0Z1c2VkQ29udjJEJzoge1xuICAgICAgICAgIGNvbnN0IHtcbiAgICAgICAgICAgIHN0cmlkZSxcbiAgICAgICAgICAgIHBhZCxcbiAgICAgICAgICAgIGRhdGFGb3JtYXQsXG4gICAgICAgICAgICBkaWxhdGlvbnMsXG4gICAgICAgICAgICBiaWFzQXJnLFxuICAgICAgICAgICAgcHJlbHVBcmcsXG4gICAgICAgICAgICBhY3RpdmF0aW9uRnVuYyxcbiAgICAgICAgICAgIGxlYWt5cmVsdUFscGhhXG4gICAgICAgICAgfSA9IGZ1c2VkQ29udkFuZERlcHRoV2lzZVBhcmFtcyhub2RlLCB0ZW5zb3JNYXAsIGNvbnRleHQpO1xuXG4gICAgICAgICAgcmV0dXJuIFt0Zk9wcy5mdXNlZC5jb252MmQoe1xuICAgICAgICAgICAgeDogZ2V0UGFyYW1WYWx1ZSgneCcsIG5vZGUsIHRlbnNvck1hcCwgY29udGV4dCkgYXMgVGVuc29yM0QgfFxuICAgICAgICAgICAgICAgIFRlbnNvcjRELFxuICAgICAgICAgICAgZmlsdGVyOiBnZXRQYXJhbVZhbHVlKCdmaWx0ZXInLCBub2RlLCB0ZW5zb3JNYXAsIGNvbnRleHQpIGFzXG4gICAgICAgICAgICAgICAgVGVuc29yNEQsXG4gICAgICAgICAgICBzdHJpZGVzOiBbc3RyaWRlWzFdLCBzdHJpZGVbMl1dLFxuICAgICAgICAgICAgcGFkOiBwYWQgYXMgJ3ZhbGlkJyB8ICdzYW1lJyxcbiAgICAgICAgICAgIGRhdGFGb3JtYXQ6IGRhdGFGb3JtYXQgYXMgJ05IV0MnIHwgJ05DSFcnLFxuICAgICAgICAgICAgZGlsYXRpb25zOiBbZGlsYXRpb25zWzFdLCBkaWxhdGlvbnNbMl1dLFxuICAgICAgICAgICAgYmlhczogYmlhc0FyZyxcbiAgICAgICAgICAgIGFjdGl2YXRpb246IGFjdGl2YXRpb25GdW5jIGFzIHRmT3BzLmZ1c2VkLkFjdGl2YXRpb24sXG4gICAgICAgICAgICBwcmVsdUFjdGl2YXRpb25XZWlnaHRzOiBwcmVsdUFyZyxcbiAgICAgICAgICAgIGxlYWt5cmVsdUFscGhhXG4gICAgICAgICAgfSldO1xuICAgICAgICB9XG5cbiAgICAgICAgY2FzZSAnRnVzZWREZXB0aHdpc2VDb252MmROYXRpdmUnOiB7XG4gICAgICAgICAgY29uc3Qge1xuICAgICAgICAgICAgc3RyaWRlLFxuICAgICAgICAgICAgcGFkLFxuICAgICAgICAgICAgZGF0YUZvcm1hdCxcbiAgICAgICAgICAgIGRpbGF0aW9ucyxcbiAgICAgICAgICAgIGJpYXNBcmcsXG4gICAgICAgICAgICBwcmVsdUFyZyxcbiAgICAgICAgICAgIGFjdGl2YXRpb25GdW5jLFxuICAgICAgICAgICAgbGVha3lyZWx1QWxwaGEsXG4gICAgICAgICAgfSA9IGZ1c2VkQ29udkFuZERlcHRoV2lzZVBhcmFtcyhub2RlLCB0ZW5zb3JNYXAsIGNvbnRleHQpO1xuXG4gICAgICAgICAgcmV0dXJuIFt0Zk9wcy5mdXNlZC5kZXB0aHdpc2VDb252MmQoe1xuICAgICAgICAgICAgeDogZ2V0UGFyYW1WYWx1ZSgneCcsIG5vZGUsIHRlbnNvck1hcCwgY29udGV4dCkgYXMgVGVuc29yM0QgfFxuICAgICAgICAgICAgICAgIFRlbnNvcjRELFxuICAgICAgICAgICAgZmlsdGVyOiBnZXRQYXJhbVZhbHVlKCdmaWx0ZXInLCBub2RlLCB0ZW5zb3JNYXAsIGNvbnRleHQpIGFzXG4gICAgICAgICAgICAgICAgVGVuc29yNEQsXG4gICAgICAgICAgICBzdHJpZGVzOiBbc3RyaWRlWzFdLCBzdHJpZGVbMl1dLFxuICAgICAgICAgICAgcGFkOiBwYWQgYXMgJ3ZhbGlkJyB8ICdzYW1lJyxcbiAgICAgICAgICAgIGRhdGFGb3JtYXQ6IGRhdGFGb3JtYXQgYXMgJ05IV0MnIHwgJ05DSFcnLFxuICAgICAgICAgICAgZGlsYXRpb25zOiBbZGlsYXRpb25zWzFdLCBkaWxhdGlvbnNbMl1dLFxuICAgICAgICAgICAgYmlhczogYmlhc0FyZyxcbiAgICAgICAgICAgIGFjdGl2YXRpb246IGFjdGl2YXRpb25GdW5jIGFzIHRmT3BzLmZ1c2VkLkFjdGl2YXRpb24sXG4gICAgICAgICAgICBwcmVsdUFjdGl2YXRpb25XZWlnaHRzOiBwcmVsdUFyZyxcbiAgICAgICAgICAgIGxlYWt5cmVsdUFscGhhXG4gICAgICAgICAgfSldO1xuICAgICAgICB9XG4gICAgICAgIGNhc2UgJ0NvbnYyREJhY2twcm9wSW5wdXQnOlxuICAgICAgICBjYXNlICdDb252MmRUcmFuc3Bvc2UnOiB7XG4gICAgICAgICAgY29uc3Qgc2hhcGUgPSBnZXRQYXJhbVZhbHVlKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICdvdXRwdXRTaGFwZScsIG5vZGUsIHRlbnNvck1hcCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb250ZXh0KSBhcyBbbnVtYmVyLCBudW1iZXIsIG51bWJlcl0gfFxuICAgICAgICAgICAgICBbbnVtYmVyLCBudW1iZXIsIG51bWJlciwgbnVtYmVyXTtcbiAgICAgICAgICBjb25zdCBzdHJpZGUgPVxuICAgICAgICAgICAgICBnZXRQYXJhbVZhbHVlKCdzdHJpZGVzJywgbm9kZSwgdGVuc29yTWFwLCBjb250ZXh0KSBhcyBudW1iZXJbXTtcbiAgICAgICAgICBjb25zdCBwYWQgPSBnZXRQYWRkaW5nKG5vZGUsIHRlbnNvck1hcCwgY29udGV4dCk7XG4gICAgICAgICAgcmV0dXJuIFt0Zk9wcy5jb252MmRUcmFuc3Bvc2UoXG4gICAgICAgICAgICAgIGdldFBhcmFtVmFsdWUoJ3gnLCBub2RlLCB0ZW5zb3JNYXAsIGNvbnRleHQpIGFzIFRlbnNvcjNEIHxcbiAgICAgICAgICAgICAgICAgIFRlbnNvcjRELFxuICAgICAgICAgICAgICBnZXRQYXJhbVZhbHVlKCdmaWx0ZXInLCBub2RlLCB0ZW5zb3JNYXAsIGNvbnRleHQpIGFzIFRlbnNvcjRELFxuICAgICAgICAgICAgICBzaGFwZSwgW3N0cmlkZVsxXSwgc3RyaWRlWzJdXSwgcGFkIGFzICd2YWxpZCcgfCAnc2FtZScpXTtcbiAgICAgICAgfVxuICAgICAgICBjYXNlICdEZXB0aHdpc2VDb252MmROYXRpdmUnOlxuICAgICAgICBjYXNlICdEZXB0aHdpc2VDb252MmQnOiB7XG4gICAgICAgICAgY29uc3Qgc3RyaWRlID1cbiAgICAgICAgICAgICAgZ2V0UGFyYW1WYWx1ZSgnc3RyaWRlcycsIG5vZGUsIHRlbnNvck1hcCwgY29udGV4dCkgYXMgbnVtYmVyW107XG4gICAgICAgICAgY29uc3QgcGFkID0gZ2V0UGFkZGluZyhub2RlLCB0ZW5zb3JNYXAsIGNvbnRleHQpO1xuICAgICAgICAgIGNvbnN0IGRpbGF0aW9ucyA9XG4gICAgICAgICAgICAgIGdldFBhcmFtVmFsdWUoJ2RpbGF0aW9ucycsIG5vZGUsIHRlbnNvck1hcCwgY29udGV4dCkgYXMgbnVtYmVyW107XG4gICAgICAgICAgY29uc3QgZGF0YUZvcm1hdCA9XG4gICAgICAgICAgICAgIChnZXRQYXJhbVZhbHVlKCdkYXRhRm9ybWF0Jywgbm9kZSwgdGVuc29yTWFwLCBjb250ZXh0KSBhcyBzdHJpbmcpXG4gICAgICAgICAgICAgICAgICAudG9VcHBlckNhc2UoKTtcblxuICAgICAgICAgIHJldHVybiBbdGZPcHMuZGVwdGh3aXNlQ29udjJkKFxuICAgICAgICAgICAgICBnZXRQYXJhbVZhbHVlKCdpbnB1dCcsIG5vZGUsIHRlbnNvck1hcCwgY29udGV4dCkgYXMgVGVuc29yM0QgfFxuICAgICAgICAgICAgICAgICAgVGVuc29yNEQsXG4gICAgICAgICAgICAgIGdldFBhcmFtVmFsdWUoJ2ZpbHRlcicsIG5vZGUsIHRlbnNvck1hcCwgY29udGV4dCkgYXMgVGVuc29yNEQsXG4gICAgICAgICAgICAgIFtzdHJpZGVbMV0sIHN0cmlkZVsyXV0sIHBhZCBhcyAndmFsaWQnIHwgJ3NhbWUnLFxuICAgICAgICAgICAgICBkYXRhRm9ybWF0IGFzICdOSFdDJyB8ICdOQ0hXJywgW2RpbGF0aW9uc1sxXSwgZGlsYXRpb25zWzJdXSldO1xuICAgICAgICB9XG4gICAgICAgIGNhc2UgJ0NvbnYzRCc6IHtcbiAgICAgICAgICBjb25zdCBzdHJpZGUgPVxuICAgICAgICAgICAgICBnZXRQYXJhbVZhbHVlKCdzdHJpZGVzJywgbm9kZSwgdGVuc29yTWFwLCBjb250ZXh0KSBhcyBudW1iZXJbXTtcbiAgICAgICAgICBjb25zdCBwYWQgPSBnZXRQYXJhbVZhbHVlKCdwYWQnLCBub2RlLCB0ZW5zb3JNYXAsIGNvbnRleHQpO1xuICAgICAgICAgIGNvbnN0IGRhdGFGb3JtYXQgPVxuICAgICAgICAgICAgICAoZ2V0UGFyYW1WYWx1ZSgnZGF0YUZvcm1hdCcsIG5vZGUsIHRlbnNvck1hcCwgY29udGV4dCkgYXMgc3RyaW5nKVxuICAgICAgICAgICAgICAgICAgLnRvVXBwZXJDYXNlKCk7XG4gICAgICAgICAgY29uc3QgZGlsYXRpb25zID1cbiAgICAgICAgICAgICAgZ2V0UGFyYW1WYWx1ZSgnZGlsYXRpb25zJywgbm9kZSwgdGVuc29yTWFwLCBjb250ZXh0KSBhcyBudW1iZXJbXTtcbiAgICAgICAgICByZXR1cm4gW3RmT3BzLmNvbnYzZChcbiAgICAgICAgICAgICAgZ2V0UGFyYW1WYWx1ZSgneCcsIG5vZGUsIHRlbnNvck1hcCwgY29udGV4dCkgYXMgVGVuc29yNEQgfFxuICAgICAgICAgICAgICAgICAgVGVuc29yPFJhbmsuUjU+LFxuICAgICAgICAgICAgICBnZXRQYXJhbVZhbHVlKCdmaWx0ZXInLCBub2RlLCB0ZW5zb3JNYXAsIGNvbnRleHQpIGFzXG4gICAgICAgICAgICAgICAgICBUZW5zb3I8UmFuay5SNT4sXG4gICAgICAgICAgICAgIFtzdHJpZGVbMV0sIHN0cmlkZVsyXSwgc3RyaWRlWzNdXSwgcGFkIGFzICd2YWxpZCcgfCAnc2FtZScsXG4gICAgICAgICAgICAgIGRhdGFGb3JtYXQgYXMgJ05ESFdDJyB8ICdOQ0RIVycsXG4gICAgICAgICAgICAgIFtkaWxhdGlvbnNbMV0sIGRpbGF0aW9uc1syXSwgZGlsYXRpb25zWzNdXSldO1xuICAgICAgICB9XG4gICAgICAgIGNhc2UgJ0F2Z1Bvb2wnOiB7XG4gICAgICAgICAgY29uc3Qgc3RyaWRlID1cbiAgICAgICAgICAgICAgZ2V0UGFyYW1WYWx1ZSgnc3RyaWRlcycsIG5vZGUsIHRlbnNvck1hcCwgY29udGV4dCkgYXMgbnVtYmVyW107XG4gICAgICAgICAgY29uc3QgcGFkID0gZ2V0UGFyYW1WYWx1ZSgncGFkJywgbm9kZSwgdGVuc29yTWFwLCBjb250ZXh0KTtcbiAgICAgICAgICBjb25zdCBrZXJuZWxTaXplID1cbiAgICAgICAgICAgICAgZ2V0UGFyYW1WYWx1ZSgna2VybmVsU2l6ZScsIG5vZGUsIHRlbnNvck1hcCwgY29udGV4dCkgYXMgbnVtYmVyW107XG5cbiAgICAgICAgICByZXR1cm4gW3RmT3BzLmF2Z1Bvb2woXG4gICAgICAgICAgICAgIGdldFBhcmFtVmFsdWUoJ3gnLCBub2RlLCB0ZW5zb3JNYXAsIGNvbnRleHQpIGFzIFRlbnNvcjNEIHxcbiAgICAgICAgICAgICAgICAgIFRlbnNvcjRELFxuICAgICAgICAgICAgICBba2VybmVsU2l6ZVsxXSwga2VybmVsU2l6ZVsyXV0sIFtzdHJpZGVbMV0sIHN0cmlkZVsyXV0sXG4gICAgICAgICAgICAgIHBhZCBhcyAndmFsaWQnIHwgJ3NhbWUnKV07XG4gICAgICAgIH1cbiAgICAgICAgY2FzZSAnTWF4UG9vbCc6IHtcbiAgICAgICAgICBjb25zdCBzdHJpZGUgPVxuICAgICAgICAgICAgICBnZXRQYXJhbVZhbHVlKCdzdHJpZGVzJywgbm9kZSwgdGVuc29yTWFwLCBjb250ZXh0KSBhcyBudW1iZXJbXTtcbiAgICAgICAgICBjb25zdCBwYWQgPSBnZXRQYXJhbVZhbHVlKCdwYWQnLCBub2RlLCB0ZW5zb3JNYXAsIGNvbnRleHQpO1xuICAgICAgICAgIGNvbnN0IGtlcm5lbFNpemUgPVxuICAgICAgICAgICAgICBnZXRQYXJhbVZhbHVlKCdrZXJuZWxTaXplJywgbm9kZSwgdGVuc29yTWFwLCBjb250ZXh0KSBhcyBudW1iZXJbXTtcblxuICAgICAgICAgIHJldHVybiBbdGZPcHMubWF4UG9vbChcbiAgICAgICAgICAgICAgZ2V0UGFyYW1WYWx1ZSgneCcsIG5vZGUsIHRlbnNvck1hcCwgY29udGV4dCkgYXMgVGVuc29yM0QgfFxuICAgICAgICAgICAgICAgICAgVGVuc29yNEQsXG4gICAgICAgICAgICAgIFtrZXJuZWxTaXplWzFdLCBrZXJuZWxTaXplWzJdXSwgW3N0cmlkZVsxXSwgc3RyaWRlWzJdXSxcbiAgICAgICAgICAgICAgcGFkIGFzICd2YWxpZCcgfCAnc2FtZScpXTtcbiAgICAgICAgfVxuICAgICAgICBjYXNlICdNYXhQb29sV2l0aEFyZ21heCc6IHtcbiAgICAgICAgICBjb25zdCBzdHJpZGUgPVxuICAgICAgICAgICAgICBnZXRQYXJhbVZhbHVlKCdzdHJpZGVzJywgbm9kZSwgdGVuc29yTWFwLCBjb250ZXh0KSBhcyBudW1iZXJbXTtcbiAgICAgICAgICBjb25zdCBwYWQgPSBnZXRQYXJhbVZhbHVlKCdwYWQnLCBub2RlLCB0ZW5zb3JNYXAsIGNvbnRleHQpO1xuICAgICAgICAgIGNvbnN0IGtlcm5lbFNpemUgPVxuICAgICAgICAgICAgICBnZXRQYXJhbVZhbHVlKCdrZXJuZWxTaXplJywgbm9kZSwgdGVuc29yTWFwLCBjb250ZXh0KSBhcyBudW1iZXJbXTtcbiAgICAgICAgICBjb25zdCBpbmNsdWRlQmF0Y2hJbkluZGV4ID1cbiAgICAgICAgICAgICAgZ2V0UGFyYW1WYWx1ZSgnaW5jbHVkZUJhdGNoSW5JbmRleCcsIG5vZGUsIHRlbnNvck1hcCwgY29udGV4dCkgYXNcbiAgICAgICAgICAgICAgYm9vbGVhbjtcbiAgICAgICAgICBjb25zdCB7cmVzdWx0LCBpbmRleGVzfSA9IHRmT3BzLm1heFBvb2xXaXRoQXJnbWF4KFxuICAgICAgICAgICAgICBnZXRQYXJhbVZhbHVlKCd4Jywgbm9kZSwgdGVuc29yTWFwLCBjb250ZXh0KSBhcyBUZW5zb3I0RCxcbiAgICAgICAgICAgICAgW2tlcm5lbFNpemVbMV0sIGtlcm5lbFNpemVbMl1dLCBbc3RyaWRlWzFdLCBzdHJpZGVbMl1dLFxuICAgICAgICAgICAgICBwYWQgYXMgJ3ZhbGlkJyB8ICdzYW1lJywgaW5jbHVkZUJhdGNoSW5JbmRleCk7XG4gICAgICAgICAgcmV0dXJuIFtyZXN1bHQsIGluZGV4ZXNdO1xuICAgICAgICB9XG4gICAgICAgIGNhc2UgJ0F2Z1Bvb2wzRCc6IHtcbiAgICAgICAgICBjb25zdCBzdHJpZGUgPVxuICAgICAgICAgICAgICBnZXRQYXJhbVZhbHVlKCdzdHJpZGVzJywgbm9kZSwgdGVuc29yTWFwLCBjb250ZXh0KSBhcyBudW1iZXJbXTtcbiAgICAgICAgICBjb25zdCBwYWQgPSBnZXRQYXJhbVZhbHVlKCdwYWQnLCBub2RlLCB0ZW5zb3JNYXAsIGNvbnRleHQpO1xuICAgICAgICAgIGNvbnN0IGtlcm5lbFNpemUgPVxuICAgICAgICAgICAgICBnZXRQYXJhbVZhbHVlKCdrZXJuZWxTaXplJywgbm9kZSwgdGVuc29yTWFwLCBjb250ZXh0KSBhcyBudW1iZXJbXTtcblxuICAgICAgICAgIHJldHVybiBbdGZPcHMuYXZnUG9vbDNkKFxuICAgICAgICAgICAgICBnZXRQYXJhbVZhbHVlKCd4Jywgbm9kZSwgdGVuc29yTWFwLCBjb250ZXh0KSBhcyBUZW5zb3I1RCxcbiAgICAgICAgICAgICAgW2tlcm5lbFNpemVbMV0sIGtlcm5lbFNpemVbMl0sIGtlcm5lbFNpemVbM11dLFxuICAgICAgICAgICAgICBbc3RyaWRlWzFdLCBzdHJpZGVbMl0sIHN0cmlkZVszXV0sIHBhZCBhcyAndmFsaWQnIHwgJ3NhbWUnKV07XG4gICAgICAgIH1cblxuICAgICAgICBjYXNlICdNYXhQb29sM0QnOiB7XG4gICAgICAgICAgY29uc3Qgc3RyaWRlID1cbiAgICAgICAgICAgICAgZ2V0UGFyYW1WYWx1ZSgnc3RyaWRlcycsIG5vZGUsIHRlbnNvck1hcCwgY29udGV4dCkgYXMgbnVtYmVyW107XG4gICAgICAgICAgY29uc3QgcGFkID0gZ2V0UGFyYW1WYWx1ZSgncGFkJywgbm9kZSwgdGVuc29yTWFwLCBjb250ZXh0KTtcbiAgICAgICAgICBjb25zdCBrZXJuZWxTaXplID1cbiAgICAgICAgICAgICAgZ2V0UGFyYW1WYWx1ZSgna2VybmVsU2l6ZScsIG5vZGUsIHRlbnNvck1hcCwgY29udGV4dCkgYXMgbnVtYmVyW107XG5cbiAgICAgICAgICByZXR1cm4gW3RmT3BzLm1heFBvb2wzZChcbiAgICAgICAgICAgICAgZ2V0UGFyYW1WYWx1ZSgneCcsIG5vZGUsIHRlbnNvck1hcCwgY29udGV4dCkgYXMgVGVuc29yNUQsXG4gICAgICAgICAgICAgIFtrZXJuZWxTaXplWzFdLCBrZXJuZWxTaXplWzJdLCBrZXJuZWxTaXplWzNdXSxcbiAgICAgICAgICAgICAgW3N0cmlkZVsxXSwgc3RyaWRlWzJdLCBzdHJpZGVbM11dLCBwYWQgYXMgJ3ZhbGlkJyB8ICdzYW1lJyldO1xuICAgICAgICB9XG5cbiAgICAgICAgY2FzZSAnRGlsYXRpb24yRCc6IHtcbiAgICAgICAgICBjb25zdCBzdHJpZGVzID1cbiAgICAgICAgICAgICAgZ2V0UGFyYW1WYWx1ZSgnc3RyaWRlcycsIG5vZGUsIHRlbnNvck1hcCwgY29udGV4dCkgYXMgbnVtYmVyW107XG4gICAgICAgICAgY29uc3QgcGFkID0gZ2V0UGFyYW1WYWx1ZSgncGFkJywgbm9kZSwgdGVuc29yTWFwLCBjb250ZXh0KTtcbiAgICAgICAgICBjb25zdCBkaWxhdGlvbnMgPVxuICAgICAgICAgICAgICBnZXRQYXJhbVZhbHVlKCdkaWxhdGlvbnMnLCBub2RlLCB0ZW5zb3JNYXAsIGNvbnRleHQpIGFzIG51bWJlcltdO1xuXG4gICAgICAgICAgLy8gc3RyaWRlczogWzEsIHN0cmlkZV9oZWlnaHQsIHN0cmlkZV93aWR0aCwgMV0uXG4gICAgICAgICAgY29uc3Qgc3RyaWRlSGVpZ2h0ID0gc3RyaWRlc1sxXTtcbiAgICAgICAgICBjb25zdCBzdHJpZGVXaWR0aCA9IHN0cmlkZXNbMl07XG5cbiAgICAgICAgICAvLyBkaWxhdGlvbnM6IFsxLCBkaWxhdGlvbl9oZWlnaHQsIGRpbGF0aW9uX3dpZHRoLCAxXS5cbiAgICAgICAgICBjb25zdCBkaWxhdGlvbkhlaWdodCA9IGRpbGF0aW9uc1sxXTtcbiAgICAgICAgICBjb25zdCBkaWxhdGlvbldpZHRoID0gZGlsYXRpb25zWzJdO1xuXG4gICAgICAgICAgcmV0dXJuIFt0Zk9wcy5kaWxhdGlvbjJkKFxuICAgICAgICAgICAgICBnZXRQYXJhbVZhbHVlKCd4Jywgbm9kZSwgdGVuc29yTWFwLCBjb250ZXh0KSBhcyBUZW5zb3IzRCB8XG4gICAgICAgICAgICAgICAgICBUZW5zb3I0RCxcbiAgICAgICAgICAgICAgZ2V0UGFyYW1WYWx1ZSgnZmlsdGVyJywgbm9kZSwgdGVuc29yTWFwLCBjb250ZXh0KSBhcyBUZW5zb3IzRCxcbiAgICAgICAgICAgICAgW3N0cmlkZUhlaWdodCwgc3RyaWRlV2lkdGhdLCBwYWQgYXMgJ3ZhbGlkJyB8ICdzYW1lJyxcbiAgICAgICAgICAgICAgW2RpbGF0aW9uSGVpZ2h0LCBkaWxhdGlvbldpZHRoXSwgJ05IV0MnIC8qIGRhdGFGb3JtYXQgKi8pXTtcbiAgICAgICAgfVxuXG4gICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgdGhyb3cgVHlwZUVycm9yKGBOb2RlIHR5cGUgJHtub2RlLm9wfSBpcyBub3QgaW1wbGVtZW50ZWRgKTtcbiAgICAgIH1cbiAgICB9O1xuXG5leHBvcnQgY29uc3QgQ0FURUdPUlkgPSAnY29udm9sdXRpb24nO1xuIl19