forked from mirrors/gecko-dev
29507 lines
No EOL
3.8 MiB
29507 lines
No EOL
3.8 MiB
/*!
|
|
* ONNX Runtime Web v1.14.0
|
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
* Licensed under the MIT License.
|
|
*/
|
|
(function webpackUniversalModuleDefinition(root, factory) {
|
|
if(typeof exports === 'object' && typeof module === 'object')
|
|
module.exports = factory();
|
|
else if(typeof define === 'function' && define.amd)
|
|
define([], factory);
|
|
else if(typeof exports === 'object')
|
|
exports["ort"] = factory();
|
|
else
|
|
root["ort"] = factory();
|
|
})(self, () => {
|
|
return /******/ (() => { // webpackBootstrap
|
|
/******/ var __webpack_modules__ = ({
|
|
|
|
/***/ "../common/dist/lib/backend-impl.js":
|
|
/*!******************************************!*\
|
|
!*** ../common/dist/lib/backend-impl.js ***!
|
|
\******************************************/
|
|
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
__webpack_require__.r(__webpack_exports__);
|
|
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
|
/* harmony export */ "registerBackend": () => (/* binding */ registerBackend),
|
|
/* harmony export */ "resolveBackend": () => (/* binding */ resolveBackend)
|
|
/* harmony export */ });
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
// Licensed under the MIT License.
|
|
const backends = {};
|
|
const backendsSortedByPriority = [];
|
|
/**
|
|
* Register a backend.
|
|
*
|
|
* @param name - the name as a key to lookup as an execution provider.
|
|
* @param backend - the backend object.
|
|
* @param priority - an integer indicating the priority of the backend. Higher number means higher priority. if priority
|
|
* < 0, it will be considered as a 'beta' version and will not be used as a fallback backend by default.
|
|
*
|
|
* @internal
|
|
*/
|
|
const registerBackend = (name, backend, priority) => {
|
|
if (backend && typeof backend.init === 'function' && typeof backend.createSessionHandler === 'function') {
|
|
const currentBackend = backends[name];
|
|
if (currentBackend === undefined) {
|
|
backends[name] = { backend, priority };
|
|
}
|
|
else if (currentBackend.priority > priority) {
|
|
// same name is already registered with a higher priority. skip registeration.
|
|
return;
|
|
}
|
|
else if (currentBackend.priority === priority) {
|
|
if (currentBackend.backend !== backend) {
|
|
throw new Error(`cannot register backend "${name}" using priority ${priority}`);
|
|
}
|
|
}
|
|
if (priority >= 0) {
|
|
const i = backendsSortedByPriority.indexOf(name);
|
|
if (i !== -1) {
|
|
backendsSortedByPriority.splice(i, 1);
|
|
}
|
|
for (let i = 0; i < backendsSortedByPriority.length; i++) {
|
|
if (backends[backendsSortedByPriority[i]].priority <= priority) {
|
|
backendsSortedByPriority.splice(i, 0, name);
|
|
return;
|
|
}
|
|
}
|
|
backendsSortedByPriority.push(name);
|
|
}
|
|
return;
|
|
}
|
|
throw new TypeError('not a valid backend');
|
|
};
|
|
/**
|
|
* Resolve backend by specified hints.
|
|
*
|
|
* @param backendHints - a list of execution provider names to lookup. If omitted use registered backends as list.
|
|
* @returns a promise that resolves to the backend.
|
|
*
|
|
* @internal
|
|
*/
|
|
const resolveBackend = async (backendHints) => {
|
|
const backendNames = backendHints.length === 0 ? backendsSortedByPriority : backendHints;
|
|
const errors = [];
|
|
for (const backendName of backendNames) {
|
|
const backendInfo = backends[backendName];
|
|
if (backendInfo) {
|
|
if (backendInfo.initialized) {
|
|
return backendInfo.backend;
|
|
}
|
|
else if (backendInfo.aborted) {
|
|
continue; // current backend is unavailable; try next
|
|
}
|
|
const isInitializing = !!backendInfo.initPromise;
|
|
try {
|
|
if (!isInitializing) {
|
|
backendInfo.initPromise = backendInfo.backend.init();
|
|
}
|
|
await backendInfo.initPromise;
|
|
backendInfo.initialized = true;
|
|
return backendInfo.backend;
|
|
}
|
|
catch (e) {
|
|
if (!isInitializing) {
|
|
errors.push({ name: backendName, err: e });
|
|
}
|
|
backendInfo.aborted = true;
|
|
}
|
|
finally {
|
|
delete backendInfo.initPromise;
|
|
}
|
|
}
|
|
}
|
|
throw new Error(`no available backend found. ERR: ${errors.map(e => `[${e.name}] ${e.err}`).join(', ')}`);
|
|
};
|
|
//# sourceMappingURL=backend-impl.js.map
|
|
|
|
/***/ }),
|
|
|
|
/***/ "../common/dist/lib/backend.js":
|
|
/*!*************************************!*\
|
|
!*** ../common/dist/lib/backend.js ***!
|
|
\*************************************/
|
|
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
__webpack_require__.r(__webpack_exports__);
|
|
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
|
/* harmony export */ "registerBackend": () => (/* reexport safe */ _backend_impl__WEBPACK_IMPORTED_MODULE_0__.registerBackend)
|
|
/* harmony export */ });
|
|
/* harmony import */ var _backend_impl__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./backend-impl */ "../common/dist/lib/backend-impl.js");
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
// Licensed under the MIT License.
|
|
|
|
//# sourceMappingURL=backend.js.map
|
|
|
|
/***/ }),
|
|
|
|
/***/ "../common/dist/lib/env-impl.js":
|
|
/*!**************************************!*\
|
|
!*** ../common/dist/lib/env-impl.js ***!
|
|
\**************************************/
|
|
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
__webpack_require__.r(__webpack_exports__);
|
|
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
|
/* harmony export */ "EnvImpl": () => (/* binding */ EnvImpl)
|
|
/* harmony export */ });
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
// Licensed under the MIT License.
|
|
class EnvImpl {
|
|
constructor() {
|
|
this.wasm = {};
|
|
this.webgl = {};
|
|
this.logLevelInternal = 'warning';
|
|
}
|
|
// TODO standadize the getter and setter convention in env for other fields.
|
|
set logLevel(value) {
|
|
if (value === undefined) {
|
|
return;
|
|
}
|
|
if (typeof value !== 'string' || ['verbose', 'info', 'warning', 'error', 'fatal'].indexOf(value) === -1) {
|
|
throw new Error(`Unsupported logging level: ${value}`);
|
|
}
|
|
this.logLevelInternal = value;
|
|
}
|
|
get logLevel() {
|
|
return this.logLevelInternal;
|
|
}
|
|
}
|
|
//# sourceMappingURL=env-impl.js.map
|
|
|
|
/***/ }),
|
|
|
|
/***/ "../common/dist/lib/env.js":
|
|
/*!*********************************!*\
|
|
!*** ../common/dist/lib/env.js ***!
|
|
\*********************************/
|
|
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
__webpack_require__.r(__webpack_exports__);
|
|
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
|
/* harmony export */ "env": () => (/* binding */ env)
|
|
/* harmony export */ });
|
|
/* harmony import */ var _env_impl__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./env-impl */ "../common/dist/lib/env-impl.js");
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
// Licensed under the MIT License.
|
|
|
|
/**
|
|
* Represent a set of flags as a global singleton.
|
|
*/
|
|
const env = new _env_impl__WEBPACK_IMPORTED_MODULE_0__.EnvImpl();
|
|
//# sourceMappingURL=env.js.map
|
|
|
|
/***/ }),
|
|
|
|
/***/ "../common/dist/lib/index.js":
|
|
/*!***********************************!*\
|
|
!*** ../common/dist/lib/index.js ***!
|
|
\***********************************/
|
|
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
__webpack_require__.r(__webpack_exports__);
|
|
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
|
/* harmony export */ "InferenceSession": () => (/* reexport safe */ _inference_session__WEBPACK_IMPORTED_MODULE_2__.InferenceSession),
|
|
/* harmony export */ "Tensor": () => (/* reexport safe */ _tensor__WEBPACK_IMPORTED_MODULE_3__.Tensor),
|
|
/* harmony export */ "env": () => (/* reexport safe */ _env__WEBPACK_IMPORTED_MODULE_1__.env),
|
|
/* harmony export */ "registerBackend": () => (/* reexport safe */ _backend__WEBPACK_IMPORTED_MODULE_0__.registerBackend)
|
|
/* harmony export */ });
|
|
/* harmony import */ var _backend__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./backend */ "../common/dist/lib/backend.js");
|
|
/* harmony import */ var _env__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./env */ "../common/dist/lib/env.js");
|
|
/* harmony import */ var _inference_session__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./inference-session */ "../common/dist/lib/inference-session.js");
|
|
/* harmony import */ var _tensor__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./tensor */ "../common/dist/lib/tensor.js");
|
|
/* harmony import */ var _onnx_value__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./onnx-value */ "../common/dist/lib/onnx-value.js");
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
// Licensed under the MIT License.
|
|
/**
|
|
* # ONNX Runtime JavaScript API
|
|
*
|
|
* ONNX Runtime JavaScript API is a unified API for all JavaScript usages, including the following NPM packages:
|
|
*
|
|
* - [onnxruntime-node](https://www.npmjs.com/package/onnxruntime-node)
|
|
* - [onnxruntime-web](https://www.npmjs.com/package/onnxruntime-web)
|
|
* - [onnxruntime-react-native](https://www.npmjs.com/package/onnxruntime-react-native)
|
|
*
|
|
* See also:
|
|
* - [Get Started](https://onnxruntime.ai/docs/get-started/with-javascript.html)
|
|
* - [Inference examples](https://github.com/microsoft/onnxruntime-inference-examples/tree/main/js)
|
|
*
|
|
* @packageDocumentation
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
//# sourceMappingURL=index.js.map
|
|
|
|
/***/ }),
|
|
|
|
/***/ "../common/dist/lib/inference-session-impl.js":
|
|
/*!****************************************************!*\
|
|
!*** ../common/dist/lib/inference-session-impl.js ***!
|
|
\****************************************************/
|
|
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
__webpack_require__.r(__webpack_exports__);
|
|
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
|
/* harmony export */ "InferenceSession": () => (/* binding */ InferenceSession)
|
|
/* harmony export */ });
|
|
/* harmony import */ var _backend_impl__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./backend-impl */ "../common/dist/lib/backend-impl.js");
|
|
/* harmony import */ var _tensor__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./tensor */ "../common/dist/lib/tensor.js");
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
// Licensed under the MIT License.
|
|
|
|
|
|
class InferenceSession {
|
|
constructor(handler) {
|
|
this.handler = handler;
|
|
}
|
|
async run(feeds, arg1, arg2) {
|
|
const fetches = {};
|
|
let options = {};
|
|
// check inputs
|
|
if (typeof feeds !== 'object' || feeds === null || feeds instanceof _tensor__WEBPACK_IMPORTED_MODULE_1__.Tensor || Array.isArray(feeds)) {
|
|
throw new TypeError('\'feeds\' must be an object that use input names as keys and OnnxValue as corresponding values.');
|
|
}
|
|
let isFetchesEmpty = true;
|
|
// determine which override is being used
|
|
if (typeof arg1 === 'object') {
|
|
if (arg1 === null) {
|
|
throw new TypeError('Unexpected argument[1]: cannot be null.');
|
|
}
|
|
if (arg1 instanceof _tensor__WEBPACK_IMPORTED_MODULE_1__.Tensor) {
|
|
throw new TypeError('\'fetches\' cannot be a Tensor');
|
|
}
|
|
if (Array.isArray(arg1)) {
|
|
if (arg1.length === 0) {
|
|
throw new TypeError('\'fetches\' cannot be an empty array.');
|
|
}
|
|
isFetchesEmpty = false;
|
|
// output names
|
|
for (const name of arg1) {
|
|
if (typeof name !== 'string') {
|
|
throw new TypeError('\'fetches\' must be a string array or an object.');
|
|
}
|
|
if (this.outputNames.indexOf(name) === -1) {
|
|
throw new RangeError(`'fetches' contains invalid output name: ${name}.`);
|
|
}
|
|
fetches[name] = null;
|
|
}
|
|
if (typeof arg2 === 'object' && arg2 !== null) {
|
|
options = arg2;
|
|
}
|
|
else if (typeof arg2 !== 'undefined') {
|
|
throw new TypeError('\'options\' must be an object.');
|
|
}
|
|
}
|
|
else {
|
|
// decide whether arg1 is fetches or options
|
|
// if any output name is present and its value is valid OnnxValue, we consider it fetches
|
|
let isFetches = false;
|
|
const arg1Keys = Object.getOwnPropertyNames(arg1);
|
|
for (const name of this.outputNames) {
|
|
if (arg1Keys.indexOf(name) !== -1) {
|
|
const v = arg1[name];
|
|
if (v === null || v instanceof _tensor__WEBPACK_IMPORTED_MODULE_1__.Tensor) {
|
|
isFetches = true;
|
|
isFetchesEmpty = false;
|
|
fetches[name] = v;
|
|
}
|
|
}
|
|
}
|
|
if (isFetches) {
|
|
if (typeof arg2 === 'object' && arg2 !== null) {
|
|
options = arg2;
|
|
}
|
|
else if (typeof arg2 !== 'undefined') {
|
|
throw new TypeError('\'options\' must be an object.');
|
|
}
|
|
}
|
|
else {
|
|
options = arg1;
|
|
}
|
|
}
|
|
}
|
|
else if (typeof arg1 !== 'undefined') {
|
|
throw new TypeError('Unexpected argument[1]: must be \'fetches\' or \'options\'.');
|
|
}
|
|
// check if all inputs are in feed
|
|
for (const name of this.inputNames) {
|
|
if (typeof feeds[name] === 'undefined') {
|
|
throw new Error(`input '${name}' is missing in 'feeds'.`);
|
|
}
|
|
}
|
|
// if no fetches is specified, we use the full output names list
|
|
if (isFetchesEmpty) {
|
|
for (const name of this.outputNames) {
|
|
fetches[name] = null;
|
|
}
|
|
}
|
|
// feeds, fetches and options are prepared
|
|
const results = await this.handler.run(feeds, fetches, options);
|
|
const returnValue = {};
|
|
for (const key in results) {
|
|
if (Object.hasOwnProperty.call(results, key)) {
|
|
returnValue[key] = new _tensor__WEBPACK_IMPORTED_MODULE_1__.Tensor(results[key].type, results[key].data, results[key].dims);
|
|
}
|
|
}
|
|
return returnValue;
|
|
}
|
|
static async create(arg0, arg1, arg2, arg3) {
|
|
// either load from a file or buffer
|
|
let filePathOrUint8Array;
|
|
let options = {};
|
|
if (typeof arg0 === 'string') {
|
|
filePathOrUint8Array = arg0;
|
|
if (typeof arg1 === 'object' && arg1 !== null) {
|
|
options = arg1;
|
|
}
|
|
else if (typeof arg1 !== 'undefined') {
|
|
throw new TypeError('\'options\' must be an object.');
|
|
}
|
|
}
|
|
else if (arg0 instanceof Uint8Array) {
|
|
filePathOrUint8Array = arg0;
|
|
if (typeof arg1 === 'object' && arg1 !== null) {
|
|
options = arg1;
|
|
}
|
|
else if (typeof arg1 !== 'undefined') {
|
|
throw new TypeError('\'options\' must be an object.');
|
|
}
|
|
}
|
|
else if (arg0 instanceof ArrayBuffer ||
|
|
(typeof SharedArrayBuffer !== 'undefined' && arg0 instanceof SharedArrayBuffer)) {
|
|
const buffer = arg0;
|
|
let byteOffset = 0;
|
|
let byteLength = arg0.byteLength;
|
|
if (typeof arg1 === 'object' && arg1 !== null) {
|
|
options = arg1;
|
|
}
|
|
else if (typeof arg1 === 'number') {
|
|
byteOffset = arg1;
|
|
if (!Number.isSafeInteger(byteOffset)) {
|
|
throw new RangeError('\'byteOffset\' must be an integer.');
|
|
}
|
|
if (byteOffset < 0 || byteOffset >= buffer.byteLength) {
|
|
throw new RangeError(`'byteOffset' is out of range [0, ${buffer.byteLength}).`);
|
|
}
|
|
byteLength = arg0.byteLength - byteOffset;
|
|
if (typeof arg2 === 'number') {
|
|
byteLength = arg2;
|
|
if (!Number.isSafeInteger(byteLength)) {
|
|
throw new RangeError('\'byteLength\' must be an integer.');
|
|
}
|
|
if (byteLength <= 0 || byteOffset + byteLength > buffer.byteLength) {
|
|
throw new RangeError(`'byteLength' is out of range (0, ${buffer.byteLength - byteOffset}].`);
|
|
}
|
|
if (typeof arg3 === 'object' && arg3 !== null) {
|
|
options = arg3;
|
|
}
|
|
else if (typeof arg3 !== 'undefined') {
|
|
throw new TypeError('\'options\' must be an object.');
|
|
}
|
|
}
|
|
else if (typeof arg2 !== 'undefined') {
|
|
throw new TypeError('\'byteLength\' must be a number.');
|
|
}
|
|
}
|
|
else if (typeof arg1 !== 'undefined') {
|
|
throw new TypeError('\'options\' must be an object.');
|
|
}
|
|
filePathOrUint8Array = new Uint8Array(buffer, byteOffset, byteLength);
|
|
}
|
|
else {
|
|
throw new TypeError('Unexpected argument[0]: must be \'path\' or \'buffer\'.');
|
|
}
|
|
// get backend hints
|
|
const eps = options.executionProviders || [];
|
|
const backendHints = eps.map(i => typeof i === 'string' ? i : i.name);
|
|
const backend = await (0,_backend_impl__WEBPACK_IMPORTED_MODULE_0__.resolveBackend)(backendHints);
|
|
const handler = await backend.createSessionHandler(filePathOrUint8Array, options);
|
|
return new InferenceSession(handler);
|
|
}
|
|
startProfiling() {
|
|
this.handler.startProfiling();
|
|
}
|
|
endProfiling() {
|
|
this.handler.endProfiling();
|
|
}
|
|
get inputNames() {
|
|
return this.handler.inputNames;
|
|
}
|
|
get outputNames() {
|
|
return this.handler.outputNames;
|
|
}
|
|
}
|
|
//# sourceMappingURL=inference-session-impl.js.map
|
|
|
|
/***/ }),
|
|
|
|
/***/ "../common/dist/lib/inference-session.js":
|
|
/*!***********************************************!*\
|
|
!*** ../common/dist/lib/inference-session.js ***!
|
|
\***********************************************/
|
|
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
__webpack_require__.r(__webpack_exports__);
|
|
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
|
/* harmony export */ "InferenceSession": () => (/* binding */ InferenceSession)
|
|
/* harmony export */ });
|
|
/* harmony import */ var _inference_session_impl__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./inference-session-impl */ "../common/dist/lib/inference-session-impl.js");
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
// Licensed under the MIT License.
|
|
|
|
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
const InferenceSession = _inference_session_impl__WEBPACK_IMPORTED_MODULE_0__.InferenceSession;
|
|
//# sourceMappingURL=inference-session.js.map
|
|
|
|
/***/ }),
|
|
|
|
/***/ "../common/dist/lib/onnx-value.js":
|
|
/*!****************************************!*\
|
|
!*** ../common/dist/lib/onnx-value.js ***!
|
|
\****************************************/
|
|
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
__webpack_require__.r(__webpack_exports__);
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
// Licensed under the MIT License.
|
|
|
|
//# sourceMappingURL=onnx-value.js.map
|
|
|
|
/***/ }),
|
|
|
|
/***/ "../common/dist/lib/tensor-impl.js":
|
|
/*!*****************************************!*\
|
|
!*** ../common/dist/lib/tensor-impl.js ***!
|
|
\*****************************************/
|
|
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
__webpack_require__.r(__webpack_exports__);
|
|
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
|
/* harmony export */ "Tensor": () => (/* binding */ Tensor)
|
|
/* harmony export */ });
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
// Licensed under the MIT License.
|
|
const isBigInt64ArrayAvailable = typeof BigInt64Array !== 'undefined' && typeof BigInt64Array.from === 'function';
|
|
const isBigUint64ArrayAvailable = typeof BigUint64Array !== 'undefined' && typeof BigUint64Array.from === 'function';
|
|
// a runtime map that maps type string to TypedArray constructor. Should match Tensor.DataTypeMap.
|
|
const NUMERIC_TENSOR_TYPE_TO_TYPEDARRAY_MAP = new Map([
|
|
['float32', Float32Array],
|
|
['uint8', Uint8Array],
|
|
['int8', Int8Array],
|
|
['uint16', Uint16Array],
|
|
['int16', Int16Array],
|
|
['int32', Int32Array],
|
|
['bool', Uint8Array],
|
|
['float64', Float64Array],
|
|
['uint32', Uint32Array],
|
|
]);
|
|
// a runtime map that maps type string to TypedArray constructor. Should match Tensor.DataTypeMap.
|
|
const NUMERIC_TENSOR_TYPEDARRAY_TO_TYPE_MAP = new Map([
|
|
[Float32Array, 'float32'],
|
|
[Uint8Array, 'uint8'],
|
|
[Int8Array, 'int8'],
|
|
[Uint16Array, 'uint16'],
|
|
[Int16Array, 'int16'],
|
|
[Int32Array, 'int32'],
|
|
[Float64Array, 'float64'],
|
|
[Uint32Array, 'uint32'],
|
|
]);
|
|
if (isBigInt64ArrayAvailable) {
|
|
NUMERIC_TENSOR_TYPE_TO_TYPEDARRAY_MAP.set('int64', BigInt64Array);
|
|
NUMERIC_TENSOR_TYPEDARRAY_TO_TYPE_MAP.set(BigInt64Array, 'int64');
|
|
}
|
|
if (isBigUint64ArrayAvailable) {
|
|
NUMERIC_TENSOR_TYPE_TO_TYPEDARRAY_MAP.set('uint64', BigUint64Array);
|
|
NUMERIC_TENSOR_TYPEDARRAY_TO_TYPE_MAP.set(BigUint64Array, 'uint64');
|
|
}
|
|
/**
|
|
* calculate size from dims.
|
|
*
|
|
* @param dims the dims array. May be an illegal input.
|
|
*/
|
|
const calculateSize = (dims) => {
|
|
let size = 1;
|
|
for (let i = 0; i < dims.length; i++) {
|
|
const dim = dims[i];
|
|
if (typeof dim !== 'number' || !Number.isSafeInteger(dim)) {
|
|
throw new TypeError(`dims[${i}] must be an integer, got: ${dim}`);
|
|
}
|
|
if (dim < 0) {
|
|
throw new RangeError(`dims[${i}] must be a non-negative integer, got: ${dim}`);
|
|
}
|
|
size *= dim;
|
|
}
|
|
return size;
|
|
};
|
|
class Tensor {
|
|
constructor(arg0, arg1, arg2) {
|
|
let type;
|
|
let data;
|
|
let dims;
|
|
// check whether arg0 is type or data
|
|
if (typeof arg0 === 'string') {
|
|
//
|
|
// Override: constructor(type, data, ...)
|
|
//
|
|
type = arg0;
|
|
dims = arg2;
|
|
if (arg0 === 'string') {
|
|
// string tensor
|
|
if (!Array.isArray(arg1)) {
|
|
throw new TypeError('A string tensor\'s data must be a string array.');
|
|
}
|
|
// we don't check whether every element in the array is string; this is too slow. we assume it's correct and
|
|
// error will be populated at inference
|
|
data = arg1;
|
|
}
|
|
else {
|
|
// numeric tensor
|
|
const typedArrayConstructor = NUMERIC_TENSOR_TYPE_TO_TYPEDARRAY_MAP.get(arg0);
|
|
if (typedArrayConstructor === undefined) {
|
|
throw new TypeError(`Unsupported tensor type: ${arg0}.`);
|
|
}
|
|
if (Array.isArray(arg1)) {
|
|
// use 'as any' here because TypeScript's check on type of 'SupportedTypedArrayConstructors.from()' produces
|
|
// incorrect results.
|
|
// 'typedArrayConstructor' should be one of the typed array prototype objects.
|
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
data = typedArrayConstructor.from(arg1);
|
|
}
|
|
else if (arg1 instanceof typedArrayConstructor) {
|
|
data = arg1;
|
|
}
|
|
else {
|
|
throw new TypeError(`A ${type} tensor's data must be type of ${typedArrayConstructor}`);
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
//
|
|
// Override: constructor(data, ...)
|
|
//
|
|
dims = arg1;
|
|
if (Array.isArray(arg0)) {
|
|
// only boolean[] and string[] is supported
|
|
if (arg0.length === 0) {
|
|
throw new TypeError('Tensor type cannot be inferred from an empty array.');
|
|
}
|
|
const firstElementType = typeof arg0[0];
|
|
if (firstElementType === 'string') {
|
|
type = 'string';
|
|
data = arg0;
|
|
}
|
|
else if (firstElementType === 'boolean') {
|
|
type = 'bool';
|
|
// 'arg0' is of type 'boolean[]'. Uint8Array.from(boolean[]) actually works, but typescript thinks this is
|
|
// wrong type. We use 'as any' to make it happy.
|
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
data = Uint8Array.from(arg0);
|
|
}
|
|
else {
|
|
throw new TypeError(`Invalid element type of data array: ${firstElementType}.`);
|
|
}
|
|
}
|
|
else {
|
|
// get tensor type from TypedArray
|
|
const mappedType = NUMERIC_TENSOR_TYPEDARRAY_TO_TYPE_MAP.get(arg0.constructor);
|
|
if (mappedType === undefined) {
|
|
throw new TypeError(`Unsupported type for tensor data: ${arg0.constructor}.`);
|
|
}
|
|
type = mappedType;
|
|
data = arg0;
|
|
}
|
|
}
|
|
// type and data is processed, now processing dims
|
|
if (dims === undefined) {
|
|
// assume 1-D tensor if dims omitted
|
|
dims = [data.length];
|
|
}
|
|
else if (!Array.isArray(dims)) {
|
|
throw new TypeError('A tensor\'s dims must be a number array');
|
|
}
|
|
// perform check
|
|
const size = calculateSize(dims);
|
|
if (size !== data.length) {
|
|
throw new Error(`Tensor's size(${size}) does not match data length(${data.length}).`);
|
|
}
|
|
this.dims = dims;
|
|
this.type = type;
|
|
this.data = data;
|
|
this.size = size;
|
|
}
|
|
// #endregion
|
|
/**
|
|
* Create a new tensor object from image object
|
|
*
|
|
* @param buffer - Extracted image buffer data - assuming RGBA format
|
|
* @param imageFormat - input image configuration - required configurations height, width, format
|
|
* @param tensorFormat - output tensor configuration - Default is RGB format
|
|
*/
|
|
static bufferToTensor(buffer, options) {
|
|
if (buffer === undefined) {
|
|
throw new Error('Image buffer must be defined');
|
|
}
|
|
if (options.height === undefined || options.width === undefined) {
|
|
throw new Error('Image height and width must be defined');
|
|
}
|
|
const { height, width } = options;
|
|
const norm = options.norm;
|
|
let normMean;
|
|
let normBias;
|
|
if (norm === undefined || norm.mean === undefined) {
|
|
normMean = 255;
|
|
}
|
|
else {
|
|
normMean = norm.mean;
|
|
}
|
|
if (norm === undefined || norm.bias === undefined) {
|
|
normBias = 0;
|
|
}
|
|
else {
|
|
normBias = norm.bias;
|
|
}
|
|
const inputformat = options.bitmapFormat !== undefined ? options.bitmapFormat : 'RGBA';
|
|
// default value is RGBA since imagedata and HTMLImageElement uses it
|
|
const outputformat = options.tensorFormat !== undefined ?
|
|
(options.tensorFormat !== undefined ? options.tensorFormat : 'RGB') :
|
|
'RGB';
|
|
const offset = height * width;
|
|
const float32Data = outputformat === 'RGBA' ? new Float32Array(offset * 4) : new Float32Array(offset * 3);
|
|
// Default pointer assignments
|
|
let step = 4, rImagePointer = 0, gImagePointer = 1, bImagePointer = 2, aImagePointer = 3;
|
|
let rTensorPointer = 0, gTensorPointer = offset, bTensorPointer = offset * 2, aTensorPointer = -1;
|
|
// Updating the pointer assignments based on the input image format
|
|
if (inputformat === 'RGB') {
|
|
step = 3;
|
|
rImagePointer = 0;
|
|
gImagePointer = 1;
|
|
bImagePointer = 2;
|
|
aImagePointer = -1;
|
|
}
|
|
// Updating the pointer assignments based on the output tensor format
|
|
if (outputformat === 'RGBA') {
|
|
aTensorPointer = offset * 3;
|
|
}
|
|
else if (outputformat === 'RBG') {
|
|
rTensorPointer = 0;
|
|
bTensorPointer = offset;
|
|
gTensorPointer = offset * 2;
|
|
}
|
|
else if (outputformat === 'BGR') {
|
|
bTensorPointer = 0;
|
|
gTensorPointer = offset;
|
|
rTensorPointer = offset * 2;
|
|
}
|
|
for (let i = 0; i < offset; i++, rImagePointer += step, bImagePointer += step, gImagePointer += step, aImagePointer += step) {
|
|
float32Data[rTensorPointer++] = (buffer[rImagePointer] + normBias) / normMean;
|
|
float32Data[gTensorPointer++] = (buffer[gImagePointer] + normBias) / normMean;
|
|
float32Data[bTensorPointer++] = (buffer[bImagePointer] + normBias) / normMean;
|
|
if (aTensorPointer !== -1 && aImagePointer !== -1) {
|
|
float32Data[aTensorPointer++] = (buffer[aImagePointer] + normBias) / normMean;
|
|
}
|
|
}
|
|
// Float32Array -> ort.Tensor
|
|
const outputTensor = outputformat === 'RGBA' ? new Tensor('float32', float32Data, [1, 4, height, width]) :
|
|
new Tensor('float32', float32Data, [1, 3, height, width]);
|
|
return outputTensor;
|
|
}
|
|
static async fromImage(image, options) {
|
|
// checking the type of image object
|
|
const isHTMLImageEle = typeof (HTMLImageElement) !== 'undefined' && image instanceof HTMLImageElement;
|
|
const isImageDataEle = typeof (ImageData) !== 'undefined' && image instanceof ImageData;
|
|
const isImageBitmap = typeof (ImageBitmap) !== 'undefined' && image instanceof ImageBitmap;
|
|
const isURL = typeof (String) !== 'undefined' && (image instanceof String || typeof image === 'string');
|
|
let data;
|
|
let tensorConfig = {};
|
|
// filling and checking image configuration options
|
|
if (isHTMLImageEle) {
|
|
// HTMLImageElement - image object - format is RGBA by default
|
|
const canvas = document.createElement('canvas');
|
|
const pixels2DContext = canvas.getContext('2d');
|
|
if (pixels2DContext != null) {
|
|
let height = image.naturalHeight;
|
|
let width = image.naturalWidth;
|
|
if (options !== undefined && options.resizedHeight !== undefined && options.resizedWidth !== undefined) {
|
|
height = options.resizedHeight;
|
|
width = options.resizedWidth;
|
|
}
|
|
if (options !== undefined) {
|
|
tensorConfig = options;
|
|
if (options.tensorFormat !== undefined) {
|
|
throw new Error('Image input config format must be RGBA for HTMLImageElement');
|
|
}
|
|
else {
|
|
tensorConfig.tensorFormat = 'RGBA';
|
|
}
|
|
if (options.height !== undefined && options.height !== height) {
|
|
throw new Error('Image input config height doesn\'t match HTMLImageElement height');
|
|
}
|
|
else {
|
|
tensorConfig.height = height;
|
|
}
|
|
if (options.width !== undefined && options.width !== width) {
|
|
throw new Error('Image input config width doesn\'t match HTMLImageElement width');
|
|
}
|
|
else {
|
|
tensorConfig.width = width;
|
|
}
|
|
}
|
|
else {
|
|
tensorConfig.tensorFormat = 'RGBA';
|
|
tensorConfig.height = height;
|
|
tensorConfig.width = width;
|
|
}
|
|
canvas.width = width;
|
|
canvas.height = height;
|
|
pixels2DContext.drawImage(image, 0, 0, width, height);
|
|
data = pixels2DContext.getImageData(0, 0, width, height).data;
|
|
}
|
|
else {
|
|
throw new Error('Can not access image data');
|
|
}
|
|
}
|
|
else if (isImageDataEle) {
|
|
// ImageData - image object - format is RGBA by default
|
|
const format = 'RGBA';
|
|
let height;
|
|
let width;
|
|
if (options !== undefined && options.resizedWidth !== undefined && options.resizedHeight !== undefined) {
|
|
height = options.resizedHeight;
|
|
width = options.resizedWidth;
|
|
}
|
|
else {
|
|
height = image.height;
|
|
width = image.width;
|
|
}
|
|
if (options !== undefined) {
|
|
tensorConfig = options;
|
|
if (options.bitmapFormat !== undefined && options.bitmapFormat !== format) {
|
|
throw new Error('Image input config format must be RGBA for ImageData');
|
|
}
|
|
else {
|
|
tensorConfig.bitmapFormat = 'RGBA';
|
|
}
|
|
}
|
|
else {
|
|
tensorConfig.bitmapFormat = 'RGBA';
|
|
}
|
|
tensorConfig.height = height;
|
|
tensorConfig.width = width;
|
|
if (options !== undefined) {
|
|
const tempCanvas = document.createElement('canvas');
|
|
tempCanvas.width = width;
|
|
tempCanvas.height = height;
|
|
const pixels2DContext = tempCanvas.getContext('2d');
|
|
if (pixels2DContext != null) {
|
|
pixels2DContext.putImageData(image, 0, 0);
|
|
data = pixels2DContext.getImageData(0, 0, width, height).data;
|
|
}
|
|
else {
|
|
throw new Error('Can not access image data');
|
|
}
|
|
}
|
|
else {
|
|
data = image.data;
|
|
}
|
|
}
|
|
else if (isImageBitmap) {
|
|
// ImageBitmap - image object - format must be provided by user
|
|
if (options === undefined) {
|
|
throw new Error('Please provide image config with format for Imagebitmap');
|
|
}
|
|
if (options.bitmapFormat !== undefined) {
|
|
throw new Error('Image input config format must be defined for ImageBitmap');
|
|
}
|
|
const pixels2DContext = document.createElement('canvas').getContext('2d');
|
|
if (pixels2DContext != null) {
|
|
const height = image.height;
|
|
const width = image.width;
|
|
pixels2DContext.drawImage(image, 0, 0, width, height);
|
|
data = pixels2DContext.getImageData(0, 0, width, height).data;
|
|
if (options !== undefined) {
|
|
// using square brackets to avoid TS error - type 'never'
|
|
if (options.height !== undefined && options.height !== height) {
|
|
throw new Error('Image input config height doesn\'t match ImageBitmap height');
|
|
}
|
|
else {
|
|
tensorConfig.height = height;
|
|
}
|
|
// using square brackets to avoid TS error - type 'never'
|
|
if (options.width !== undefined && options.width !== width) {
|
|
throw new Error('Image input config width doesn\'t match ImageBitmap width');
|
|
}
|
|
else {
|
|
tensorConfig.width = width;
|
|
}
|
|
}
|
|
else {
|
|
tensorConfig.height = height;
|
|
tensorConfig.width = width;
|
|
}
|
|
return Tensor.bufferToTensor(data, tensorConfig);
|
|
}
|
|
else {
|
|
throw new Error('Can not access image data');
|
|
}
|
|
}
|
|
else if (isURL) {
|
|
return new Promise((resolve, reject) => {
|
|
const canvas = document.createElement('canvas');
|
|
const context = canvas.getContext('2d');
|
|
if (!image || !context) {
|
|
return reject();
|
|
}
|
|
const newImage = new Image();
|
|
newImage.crossOrigin = 'Anonymous';
|
|
newImage.src = image;
|
|
newImage.onload = () => {
|
|
canvas.width = newImage.width;
|
|
canvas.height = newImage.height;
|
|
context.drawImage(newImage, 0, 0, canvas.width, canvas.height);
|
|
const img = context.getImageData(0, 0, canvas.width, canvas.height);
|
|
if (options !== undefined) {
|
|
// using square brackets to avoid TS error - type 'never'
|
|
if (options.height !== undefined && options.height !== canvas.height) {
|
|
throw new Error('Image input config height doesn\'t match ImageBitmap height');
|
|
}
|
|
else {
|
|
tensorConfig.height = canvas.height;
|
|
}
|
|
// using square brackets to avoid TS error - type 'never'
|
|
if (options.width !== undefined && options.width !== canvas.width) {
|
|
throw new Error('Image input config width doesn\'t match ImageBitmap width');
|
|
}
|
|
else {
|
|
tensorConfig.width = canvas.width;
|
|
}
|
|
}
|
|
else {
|
|
tensorConfig.height = canvas.height;
|
|
tensorConfig.width = canvas.width;
|
|
}
|
|
resolve(Tensor.bufferToTensor(img.data, tensorConfig));
|
|
};
|
|
});
|
|
}
|
|
else {
|
|
throw new Error('Input data provided is not supported - aborted tensor creation');
|
|
}
|
|
if (data !== undefined) {
|
|
return Tensor.bufferToTensor(data, tensorConfig);
|
|
}
|
|
else {
|
|
throw new Error('Input data provided is not supported - aborted tensor creation');
|
|
}
|
|
}
|
|
toImageData(options) {
|
|
var _a, _b;
|
|
const pixels2DContext = document.createElement('canvas').getContext('2d');
|
|
let image;
|
|
if (pixels2DContext != null) {
|
|
// Default values for height and width & format
|
|
const width = this.dims[3];
|
|
const height = this.dims[2];
|
|
const channels = this.dims[1];
|
|
const inputformat = options !== undefined ? (options.format !== undefined ? options.format : 'RGB') : 'RGB';
|
|
const normMean = options !== undefined ? (((_a = options.norm) === null || _a === void 0 ? void 0 : _a.mean) !== undefined ? options.norm.mean : 255) : 255;
|
|
const normBias = options !== undefined ? (((_b = options.norm) === null || _b === void 0 ? void 0 : _b.bias) !== undefined ? options.norm.bias : 0) : 0;
|
|
const offset = height * width;
|
|
if (options !== undefined) {
|
|
if (options.height !== undefined && options.height !== height) {
|
|
throw new Error('Image output config height doesn\'t match tensor height');
|
|
}
|
|
if (options.width !== undefined && options.width !== width) {
|
|
throw new Error('Image output config width doesn\'t match tensor width');
|
|
}
|
|
if (options.format !== undefined && (channels === 4 && options.format !== 'RGBA') ||
|
|
(channels === 3 && (options.format !== 'RGB' && options.format !== 'BGR'))) {
|
|
throw new Error('Tensor format doesn\'t match input tensor dims');
|
|
}
|
|
}
|
|
// Default pointer assignments
|
|
const step = 4;
|
|
let rImagePointer = 0, gImagePointer = 1, bImagePointer = 2, aImagePointer = 3;
|
|
let rTensorPointer = 0, gTensorPointer = offset, bTensorPointer = offset * 2, aTensorPointer = -1;
|
|
// Updating the pointer assignments based on the input image format
|
|
if (inputformat === 'RGBA') {
|
|
rTensorPointer = 0;
|
|
gTensorPointer = offset;
|
|
bTensorPointer = offset * 2;
|
|
aTensorPointer = offset * 3;
|
|
}
|
|
else if (inputformat === 'RGB') {
|
|
rTensorPointer = 0;
|
|
gTensorPointer = offset;
|
|
bTensorPointer = offset * 2;
|
|
}
|
|
else if (inputformat === 'RBG') {
|
|
rTensorPointer = 0;
|
|
bTensorPointer = offset;
|
|
gTensorPointer = offset * 2;
|
|
}
|
|
image = pixels2DContext.createImageData(width, height);
|
|
for (let i = 0; i < height * width; rImagePointer += step, gImagePointer += step, bImagePointer += step, aImagePointer += step, i++) {
|
|
image.data[rImagePointer] = (this.data[rTensorPointer++] - normBias) * normMean; // R value
|
|
image.data[gImagePointer] = (this.data[gTensorPointer++] - normBias) * normMean; // G value
|
|
image.data[bImagePointer] = (this.data[bTensorPointer++] - normBias) * normMean; // B value
|
|
image.data[aImagePointer] =
|
|
aTensorPointer === -1 ? 255 : (this.data[aTensorPointer++] - normBias) * normMean; // A value
|
|
}
|
|
}
|
|
else {
|
|
throw new Error('Can not access image data');
|
|
}
|
|
return image;
|
|
}
|
|
// #endregion
|
|
// #region tensor utilities
|
|
reshape(dims) {
|
|
return new Tensor(this.type, this.data, dims);
|
|
}
|
|
}
|
|
//# sourceMappingURL=tensor-impl.js.map
|
|
|
|
/***/ }),
|
|
|
|
/***/ "../common/dist/lib/tensor.js":
|
|
/*!************************************!*\
|
|
!*** ../common/dist/lib/tensor.js ***!
|
|
\************************************/
|
|
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
__webpack_require__.r(__webpack_exports__);
|
|
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
|
/* harmony export */ "Tensor": () => (/* binding */ Tensor)
|
|
/* harmony export */ });
|
|
/* harmony import */ var _tensor_impl__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./tensor-impl */ "../common/dist/lib/tensor-impl.js");
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
// Licensed under the MIT License.
|
|
|
|
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
const Tensor = _tensor_impl__WEBPACK_IMPORTED_MODULE_0__.Tensor;
|
|
//# sourceMappingURL=tensor.js.map
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./lib/wasm/binding/ort-wasm-threaded.js":
|
|
/*!***********************************************!*\
|
|
!*** ./lib/wasm/binding/ort-wasm-threaded.js ***!
|
|
\***********************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
var __filename = "/index.js";
|
|
var __dirname = "/";
|
|
|
|
var ortWasmThreaded = (() => {
|
|
var _scriptDir = typeof document !== 'undefined' && document.currentScript ? document.currentScript.src : undefined;
|
|
if (true) _scriptDir = _scriptDir || __filename;
|
|
return (
|
|
function(ortWasmThreaded) {
|
|
ortWasmThreaded = ortWasmThreaded || {};
|
|
|
|
|
|
function d(){m.buffer!=n&&p(m.buffer);return aa}function q(){m.buffer!=n&&p(m.buffer);return ba}function r(){m.buffer!=n&&p(m.buffer);return ca}function v(){m.buffer!=n&&p(m.buffer);return da}function ea(){m.buffer!=n&&p(m.buffer);return fa}var x;x||(x=typeof ortWasmThreaded !== 'undefined' ? ortWasmThreaded : {});var ha,ia;x.ready=new Promise(function(a,b){ha=a;ia=b});
|
|
var ja=Object.assign({},x),ka="./this.program",la=(a,b)=>{throw b;},ma="object"==typeof window,y="function"==typeof importScripts,B="object"==typeof process&&"object"==typeof process.versions&&"string"==typeof process.versions.node,C=x.ENVIRONMENT_IS_PTHREAD||!1,D="";function na(a){return x.locateFile?x.locateFile(a,D):D+a}var oa,pa,qa,fs,ra,sa;
|
|
if(B){D=y?(__webpack_require__(/*! path */ "?75c6").dirname)(D)+"/":__dirname+"/";sa=()=>{ra||(fs=__webpack_require__(/*! fs */ "?63c8"),ra=__webpack_require__(/*! path */ "?75c6"))};oa=function(b,c){sa();b=ra.normalize(b);return fs.readFileSync(b,c?void 0:"utf8")};qa=b=>{b=oa(b,!0);b.buffer||(b=new Uint8Array(b));return b};pa=(b,c,e)=>{sa();b=ra.normalize(b);fs.readFile(b,function(f,h){f?e(f):c(h.buffer)})};1<process.argv.length&&(ka=process.argv[1].replace(/\\/g,"/"));process.argv.slice(2);process.on("uncaughtException",function(b){if(!(b instanceof E))throw b;});process.on("unhandledRejection",
|
|
function(b){throw b;});la=(b,c)=>{if(F())throw process.exitCode=b,c;c instanceof E||G("exiting due to exception: "+c);process.exit(b)};x.inspect=function(){return"[Emscripten Module object]"};let a;try{a=__webpack_require__(/*! worker_threads */ "?c6f7")}catch(b){throw console.error('The "worker_threads" module is not supported in this node.js build - perhaps a newer version is needed?'),b;}__webpack_require__.g.Worker=a.Worker}else if(ma||y)y?D=self.location.href:"undefined"!=typeof document&&document.currentScript&&(D=document.currentScript.src),
|
|
_scriptDir&&(D=_scriptDir),0!==D.indexOf("blob:")?D=D.substr(0,D.replace(/[?#].*/,"").lastIndexOf("/")+1):D="",B||(oa=a=>{var b=new XMLHttpRequest;b.open("GET",a,!1);b.send(null);return b.responseText},y&&(qa=a=>{var b=new XMLHttpRequest;b.open("GET",a,!1);b.responseType="arraybuffer";b.send(null);return new Uint8Array(b.response)}),pa=(a,b,c)=>{var e=new XMLHttpRequest;e.open("GET",a,!0);e.responseType="arraybuffer";e.onload=()=>{200==e.status||0==e.status&&e.response?b(e.response):c()};e.onerror=
|
|
c;e.send(null)});B&&"undefined"==typeof performance&&(__webpack_require__.g.performance=(__webpack_require__(/*! perf_hooks */ "?674f").performance));var ta=console.log.bind(console),ua=console.warn.bind(console);B&&(sa(),ta=a=>fs.writeSync(1,a+"\n"),ua=a=>fs.writeSync(2,a+"\n"));var va=x.print||ta,G=x.printErr||ua;Object.assign(x,ja);ja=null;x.thisProgram&&(ka=x.thisProgram);x.quit&&(la=x.quit);var H;x.wasmBinary&&(H=x.wasmBinary);var noExitRuntime=x.noExitRuntime||!1;"object"!=typeof WebAssembly&&I("no native wasm support detected");
|
|
var m,wa,xa=!1,ya="undefined"!=typeof TextDecoder?new TextDecoder("utf8"):void 0;
|
|
function za(a,b,c){b>>>=0;var e=b+c;for(c=b;a[c]&&!(c>=e);)++c;if(16<c-b&&a.buffer&&ya)return ya.decode(a.buffer instanceof SharedArrayBuffer?a.slice(b,c):a.subarray(b,c));for(e="";b<c;){var f=a[b++];if(f&128){var h=a[b++]&63;if(192==(f&224))e+=String.fromCharCode((f&31)<<6|h);else{var k=a[b++]&63;f=224==(f&240)?(f&15)<<12|h<<6|k:(f&7)<<18|h<<12|k<<6|a[b++]&63;65536>f?e+=String.fromCharCode(f):(f-=65536,e+=String.fromCharCode(55296|f>>10,56320|f&1023))}}else e+=String.fromCharCode(f)}return e}
|
|
function Aa(a,b){return(a>>>=0)?za(q(),a,b):""}
|
|
function Ba(a,b,c,e){c>>>=0;if(!(0<e))return 0;var f=c;e=c+e-1;for(var h=0;h<a.length;++h){var k=a.charCodeAt(h);if(55296<=k&&57343>=k){var l=a.charCodeAt(++h);k=65536+((k&1023)<<10)|l&1023}if(127>=k){if(c>=e)break;b[c++>>>0]=k}else{if(2047>=k){if(c+1>=e)break;b[c++>>>0]=192|k>>6}else{if(65535>=k){if(c+2>=e)break;b[c++>>>0]=224|k>>12}else{if(c+3>=e)break;b[c++>>>0]=240|k>>18;b[c++>>>0]=128|k>>12&63}b[c++>>>0]=128|k>>6&63}b[c++>>>0]=128|k&63}}b[c>>>0]=0;return c-f}
|
|
function Ca(a){for(var b=0,c=0;c<a.length;++c){var e=a.charCodeAt(c);127>=e?b++:2047>=e?b+=2:55296<=e&&57343>=e?(b+=4,++c):b+=3}return b}var n,aa,ba,ca,da,fa;C&&(n=x.buffer);function p(a){n=a;x.HEAP8=aa=new Int8Array(a);x.HEAP16=new Int16Array(a);x.HEAP32=ca=new Int32Array(a);x.HEAPU8=ba=new Uint8Array(a);x.HEAPU16=new Uint16Array(a);x.HEAPU32=da=new Uint32Array(a);x.HEAPF32=new Float32Array(a);x.HEAPF64=fa=new Float64Array(a)}var Da=x.INITIAL_MEMORY||16777216;
|
|
if(C)m=x.wasmMemory,n=x.buffer;else if(x.wasmMemory)m=x.wasmMemory;else if(m=new WebAssembly.Memory({initial:Da/65536,maximum:65536,shared:!0}),!(m.buffer instanceof SharedArrayBuffer))throw G("requested a shared WebAssembly.Memory but the returned buffer is not a SharedArrayBuffer, indicating that while the browser has SharedArrayBuffer it does not have WebAssembly threads support - you may need to set a flag"),B&&console.log("(on node you may need: --experimental-wasm-threads --experimental-wasm-bulk-memory and also use a recent version)"),
|
|
Error("bad memory");m&&(n=m.buffer);Da=n.byteLength;p(n);var Ea,Fa=[],Ga=[],Ha=[],Ia=[],Ja=0;function F(){return noExitRuntime||0<Ja}function Ka(){var a=x.preRun.shift();Fa.unshift(a)}var L=0,La=null,M=null;function I(a){if(C)postMessage({cmd:"onAbort",arg:a});else if(x.onAbort)x.onAbort(a);a="Aborted("+a+")";G(a);xa=!0;a=new WebAssembly.RuntimeError(a+". Build with -sASSERTIONS for more info.");ia(a);throw a;}function Ma(){return O.startsWith("data:application/octet-stream;base64,")}var O;O="ort-wasm-threaded.wasm";
|
|
Ma()||(O=na(O));function Na(){var a=O;try{if(a==O&&H)return new Uint8Array(H);if(qa)return qa(a);throw"both async and sync fetching of the wasm failed";}catch(b){I(b)}}
|
|
function Oa(){if(!H&&(ma||y)){if("function"==typeof fetch&&!O.startsWith("file://"))return fetch(O,{credentials:"same-origin"}).then(function(a){if(!a.ok)throw"failed to load wasm binary file at '"+O+"'";return a.arrayBuffer()}).catch(function(){return Na()});if(pa)return new Promise(function(a,b){pa(O,function(c){a(new Uint8Array(c))},b)})}return Promise.resolve().then(function(){return Na()})}var Pa={};
|
|
function E(a){this.name="ExitStatus";this.message="Program terminated with exit("+a+")";this.status=a}function Qa(a){(a=P.Vb[a])||I();P.mc(a)}function Ra(a){var b=P.Cc();if(!b)return 6;P.ac.push(b);P.Vb[a.Ub]=b;b.Ub=a.Ub;var c={cmd:"run",start_routine:a.Ic,arg:a.zc,pthread_ptr:a.Ub};b.$b=()=>{c.time=performance.now();b.postMessage(c,a.Nc)};b.loaded&&(b.$b(),delete b.$b);return 0}function Sa(a){if(C)return Q(1,1,a);if(!F()){P.oc();if(x.onExit)x.onExit(a);xa=!0}la(a,new E(a))}
|
|
function Ta(a,b){if(!b&&C)throw Ua(a),"unwind";F()||C||(Va(),R(Ha),Wa(0),Xa[1].length&&Ya(1,10),Xa[2].length&&Ya(2,10),P.oc());Sa(a)}
|
|
var P={Yb:[],ac:[],qc:[],Vb:{},fc:function(){C&&P.Ec()},Pc:function(){},Ec:function(){P.receiveObjectTransfer=P.Gc;P.threadInitTLS=P.pc;P.setExitStatus=P.nc;noExitRuntime=!1},nc:function(){},oc:function(){for(var a of Object.values(P.Vb))P.mc(a);for(a of P.Yb)a.terminate();P.Yb=[]},mc:function(a){var b=a.Ub;delete P.Vb[b];P.Yb.push(a);P.ac.splice(P.ac.indexOf(a),1);a.Ub=0;Za(b)},Gc:function(){},pc:function(){P.qc.forEach(a=>a())},Fc:function(a,b){a.onmessage=c=>{c=c.data;var e=c.cmd;a.Ub&&(P.Bc=a.Ub);
|
|
if(c.targetThread&&c.targetThread!=$a()){var f=P.Vb[c.Qc];f?f.postMessage(c,c.transferList):G('Internal error! Worker sent a message "'+e+'" to target pthread '+c.targetThread+", but that thread no longer exists!")}else if("processProxyingQueue"===e)ab(c.queue);else if("spawnThread"===e)Ra(c);else if("cleanupThread"===e)Qa(c.thread);else if("killThread"===e)c=c.thread,e=P.Vb[c],delete P.Vb[c],e.terminate(),Za(c),P.ac.splice(P.ac.indexOf(e),1),e.Ub=0;else if("cancelThread"===e)P.Vb[c.thread].postMessage({cmd:"cancel"});
|
|
else if("loaded"===e)a.loaded=!0,b&&b(a),a.$b&&(a.$b(),delete a.$b);else if("print"===e)va("Thread "+c.threadId+": "+c.text);else if("printErr"===e)G("Thread "+c.threadId+": "+c.text);else if("alert"===e)alert("Thread "+c.threadId+": "+c.text);else if("setimmediate"===c.target)a.postMessage(c);else if("onAbort"===e){if(x.onAbort)x.onAbort(c.arg)}else e&&G("worker sent an unknown command "+e);P.Bc=void 0};a.onerror=c=>{G("worker sent an error! "+c.filename+":"+c.lineno+": "+c.message);throw c;};B&&
|
|
(a.on("message",function(c){a.onmessage({data:c})}),a.on("error",function(c){a.onerror(c)}),a.on("detachedExit",function(){}));a.postMessage({cmd:"load",urlOrBlob:x.mainScriptUrlOrBlob||_scriptDir,wasmMemory:m,wasmModule:wa})},yc:function(){var a=na("ort-wasm-threaded.worker.js");P.Yb.push(new Worker(a))},Cc:function(){0==P.Yb.length&&(P.yc(),P.Fc(P.Yb[0]));return P.Yb.pop()}};x.PThread=P;function R(a){for(;0<a.length;)a.shift()(x)}function bb(a){var b=S();a=a();U(b);return a}
|
|
x.establishStackSpace=function(){var a=$a(),b=r()[a+44>>2>>>0];a=r()[a+48>>2>>>0];cb(b,b-a);U(b)};function Ua(a){if(C)return Q(2,0,a);try{Ta(a)}catch(b){b instanceof E||"unwind"==b||la(1,b)}}var db=[];function V(a){var b=db[a];b||(a>=db.length&&(db.length=a+1),db[a]=b=Ea.get(a));return b}x.invokeEntryPoint=function(a,b){a=V(a)(b);F()?P.nc(a):eb(a)};function fb(a,b){d().set(a,b>>>0)}var gb=[],hb=0,W=0;
|
|
function X(a){this.Zb=a;this.Sb=a-24;this.xc=function(b){v()[this.Sb+4>>2>>>0]=b};this.bc=function(){return v()[this.Sb+4>>2>>>0]};this.wc=function(b){v()[this.Sb+8>>2>>>0]=b};this.Dc=function(){return v()[this.Sb+8>>2>>>0]};this.rc=function(){r()[this.Sb>>2>>>0]=0};this.hc=function(b){b=b?1:0;d()[this.Sb+12>>0>>>0]=b};this.uc=function(){return 0!=d()[this.Sb+12>>0>>>0]};this.ic=function(b){b=b?1:0;d()[this.Sb+13>>0>>>0]=b};this.kc=function(){return 0!=d()[this.Sb+13>>0>>>0]};this.fc=function(b,c){this.cc(0);
|
|
this.xc(b);this.wc(c);this.rc();this.hc(!1);this.ic(!1)};this.sc=function(){Atomics.add(r(),this.Sb>>2,1)};this.Hc=function(){return 1===Atomics.sub(r(),this.Sb>>2,1)};this.cc=function(b){v()[this.Sb+16>>2>>>0]=b};this.tc=function(){return v()[this.Sb+16>>2>>>0]};this.vc=function(){if(ib(this.bc()))return v()[this.Zb>>2>>>0];var b=this.tc();return 0!==b?b:this.Zb}}function jb(a){return kb((new X(a)).Sb)}function lb(a,b,c,e){return C?Q(3,1,a,b,c,e):mb(a,b,c,e)}
|
|
function mb(a,b,c,e){if("undefined"==typeof SharedArrayBuffer)return G("Current environment does not support SharedArrayBuffer, pthreads are not available!"),6;var f=[];if(C&&0===f.length)return lb(a,b,c,e);a={Ic:c,Ub:a,zc:e,Nc:f};return C?(a.Oc="spawnThread",postMessage(a,f),0):Ra(a)}function nb(a,b,c){return C?Q(4,1,a,b,c):0}function ob(a,b){if(C)return Q(5,1,a,b)}function pb(a,b){if(C)return Q(6,1,a,b)}function qb(a,b,c){if(C)return Q(7,1,a,b,c)}function rb(a,b,c){return C?Q(8,1,a,b,c):0}
|
|
function sb(a,b){if(C)return Q(9,1,a,b)}function tb(a,b,c){if(C)return Q(10,1,a,b,c)}function ub(a,b,c,e){if(C)return Q(11,1,a,b,c,e)}function vb(a,b,c,e){if(C)return Q(12,1,a,b,c,e)}function wb(a,b,c,e){if(C)return Q(13,1,a,b,c,e)}function xb(a){if(C)return Q(14,1,a)}function yb(a,b){if(C)return Q(15,1,a,b)}function zb(a,b,c){if(C)return Q(16,1,a,b,c)}function ab(a){Atomics.store(r(),a>>2,1);$a()&&Ab(a);Atomics.compareExchange(r(),a>>2,1,0)}x.executeNotifiedProxyingQueue=ab;
|
|
function Bb(a){return v()[a>>>2]+4294967296*r()[a+4>>>2]}function Cb(a,b,c,e,f,h){return C?Q(17,1,a,b,c,e,f,h):-52}function Db(a,b,c,e,f,h){if(C)return Q(18,1,a,b,c,e,f,h)}function Eb(a){var b=Ca(a)+1,c=Fb(b);c&&Ba(a,d(),c,b);return c}
|
|
function Gb(a,b,c){function e(t){return(t=t.toTimeString().match(/\(([A-Za-z ]+)\)$/))?t[1]:"GMT"}if(C)return Q(19,1,a,b,c);var f=(new Date).getFullYear(),h=new Date(f,0,1),k=new Date(f,6,1);f=h.getTimezoneOffset();var l=k.getTimezoneOffset(),u=Math.max(f,l);r()[a>>2>>>0]=60*u;r()[b>>2>>>0]=Number(f!=l);a=e(h);b=e(k);a=Eb(a);b=Eb(b);l<f?(v()[c>>2>>>0]=a,v()[c+4>>2>>>0]=b):(v()[c>>2>>>0]=b,v()[c+4>>2>>>0]=a)}function Hb(a,b,c){Hb.Ac||(Hb.Ac=!0,Gb(a,b,c))}var Ib,Jb;
|
|
Jb=B?()=>{var a=process.hrtime();return 1E3*a[0]+a[1]/1E6}:C?()=>performance.now()-x.__performance_now_clock_drift:()=>performance.now();function Q(a,b){var c=arguments.length-2,e=arguments;return bb(()=>{for(var f=Kb(8*c),h=f>>3,k=0;k<c;k++){var l=e[2+k];ea()[h+k>>>0]=l}return Lb(a,c,f,b)})}var Mb=[],Nb={};
|
|
function Ob(){if(!Pb){var a={USER:"web_user",LOGNAME:"web_user",PATH:"/",PWD:"/",HOME:"/home/web_user",LANG:("object"==typeof navigator&&navigator.languages&&navigator.languages[0]||"C").replace("-","_")+".UTF-8",_:ka||"./this.program"},b;for(b in Nb)void 0===Nb[b]?delete a[b]:a[b]=Nb[b];var c=[];for(b in a)c.push(b+"="+a[b]);Pb=c}return Pb}var Pb;
|
|
function Qb(a,b){if(C)return Q(20,1,a,b);var c=0;Ob().forEach(function(e,f){var h=b+c;f=v()[a+4*f>>2>>>0]=h;for(h=0;h<e.length;++h)d()[f++>>0>>>0]=e.charCodeAt(h);d()[f>>0>>>0]=0;c+=e.length+1});return 0}function Rb(a,b){if(C)return Q(21,1,a,b);var c=Ob();v()[a>>2>>>0]=c.length;var e=0;c.forEach(function(f){e+=f.length+1});v()[b>>2>>>0]=e;return 0}function Sb(a){return C?Q(22,1,a):52}function Tb(a,b,c,e){return C?Q(23,1,a,b,c,e):52}function Ub(a,b,c,e,f){return C?Q(24,1,a,b,c,e,f):70}
|
|
var Xa=[null,[],[]];function Ya(a,b){var c=Xa[a];0===b||10===b?((1===a?va:G)(za(c,0)),c.length=0):c.push(b)}function Vb(a,b,c,e){if(C)return Q(25,1,a,b,c,e);for(var f=0,h=0;h<c;h++){var k=v()[b>>2>>>0],l=v()[b+4>>2>>>0];b+=8;for(var u=0;u<l;u++)Ya(a,q()[k+u>>>0]);f+=l}v()[e>>2>>>0]=f;return 0}var Y=0;
|
|
function Wb(){if("object"==typeof crypto&&"function"==typeof crypto.getRandomValues){var a=new Uint8Array(1);return()=>{crypto.getRandomValues(a);return a[0]}}if(B)try{var b=__webpack_require__(Object(function webpackMissingModule() { var e = new Error("Cannot find module 'crypto'"); e.code = 'MODULE_NOT_FOUND'; throw e; }()));return()=>b.randomBytes(1)[0]}catch(c){}return()=>I("randomDevice")}function Xb(a,b){Xb.lc||(Xb.lc=Wb());for(var c=0;c<b;c++)d()[a+c>>0>>>0]=Xb.lc();return 0}function Yb(a){return 0===a%4&&(0!==a%100||0===a%400)}var Zb=[31,29,31,30,31,30,31,31,30,31,30,31],$b=[31,28,31,30,31,30,31,31,30,31,30,31];
|
|
function ac(a){var b=Array(Ca(a)+1);Ba(a,b,0,b.length);return b}
|
|
function bc(a,b,c,e){function f(g,w,z){for(g="number"==typeof g?g.toString():g||"";g.length<w;)g=z[0]+g;return g}function h(g,w){return f(g,w,"0")}function k(g,w){function z(T){return 0>T?-1:0<T?1:0}var N;0===(N=z(g.getFullYear()-w.getFullYear()))&&0===(N=z(g.getMonth()-w.getMonth()))&&(N=z(g.getDate()-w.getDate()));return N}function l(g){switch(g.getDay()){case 0:return new Date(g.getFullYear()-1,11,29);case 1:return g;case 2:return new Date(g.getFullYear(),0,3);case 3:return new Date(g.getFullYear(),
|
|
0,2);case 4:return new Date(g.getFullYear(),0,1);case 5:return new Date(g.getFullYear()-1,11,31);case 6:return new Date(g.getFullYear()-1,11,30)}}function u(g){var w=g.Wb;for(g=new Date((new Date(g.Xb+1900,0,1)).getTime());0<w;){var z=g.getMonth(),N=(Yb(g.getFullYear())?Zb:$b)[z];if(w>N-g.getDate())w-=N-g.getDate()+1,g.setDate(1),11>z?g.setMonth(z+1):(g.setMonth(0),g.setFullYear(g.getFullYear()+1));else{g.setDate(g.getDate()+w);break}}z=new Date(g.getFullYear()+1,0,4);w=l(new Date(g.getFullYear(),
|
|
0,4));z=l(z);return 0>=k(w,g)?0>=k(z,g)?g.getFullYear()+1:g.getFullYear():g.getFullYear()-1}var t=r()[e+40>>2>>>0];e={Lc:r()[e>>2>>>0],Kc:r()[e+4>>2>>>0],dc:r()[e+8>>2>>>0],jc:r()[e+12>>2>>>0],ec:r()[e+16>>2>>>0],Xb:r()[e+20>>2>>>0],Tb:r()[e+24>>2>>>0],Wb:r()[e+28>>2>>>0],Rc:r()[e+32>>2>>>0],Jc:r()[e+36>>2>>>0],Mc:t?Aa(t):""};c=Aa(c);t={"%c":"%a %b %d %H:%M:%S %Y","%D":"%m/%d/%y","%F":"%Y-%m-%d","%h":"%b","%r":"%I:%M:%S %p","%R":"%H:%M","%T":"%H:%M:%S","%x":"%m/%d/%y","%X":"%H:%M:%S","%Ec":"%c","%EC":"%C",
|
|
"%Ex":"%m/%d/%y","%EX":"%H:%M:%S","%Ey":"%y","%EY":"%Y","%Od":"%d","%Oe":"%e","%OH":"%H","%OI":"%I","%Om":"%m","%OM":"%M","%OS":"%S","%Ou":"%u","%OU":"%U","%OV":"%V","%Ow":"%w","%OW":"%W","%Oy":"%y"};for(var A in t)c=c.replace(new RegExp(A,"g"),t[A]);var K="Sunday Monday Tuesday Wednesday Thursday Friday Saturday".split(" "),J="January February March April May June July August September October November December".split(" ");t={"%a":function(g){return K[g.Tb].substring(0,3)},"%A":function(g){return K[g.Tb]},
|
|
"%b":function(g){return J[g.ec].substring(0,3)},"%B":function(g){return J[g.ec]},"%C":function(g){return h((g.Xb+1900)/100|0,2)},"%d":function(g){return h(g.jc,2)},"%e":function(g){return f(g.jc,2," ")},"%g":function(g){return u(g).toString().substring(2)},"%G":function(g){return u(g)},"%H":function(g){return h(g.dc,2)},"%I":function(g){g=g.dc;0==g?g=12:12<g&&(g-=12);return h(g,2)},"%j":function(g){for(var w=0,z=0;z<=g.ec-1;w+=(Yb(g.Xb+1900)?Zb:$b)[z++]);return h(g.jc+w,3)},"%m":function(g){return h(g.ec+
|
|
1,2)},"%M":function(g){return h(g.Kc,2)},"%n":function(){return"\n"},"%p":function(g){return 0<=g.dc&&12>g.dc?"AM":"PM"},"%S":function(g){return h(g.Lc,2)},"%t":function(){return"\t"},"%u":function(g){return g.Tb||7},"%U":function(g){return h(Math.floor((g.Wb+7-g.Tb)/7),2)},"%V":function(g){var w=Math.floor((g.Wb+7-(g.Tb+6)%7)/7);2>=(g.Tb+371-g.Wb-2)%7&&w++;if(w)53==w&&(z=(g.Tb+371-g.Wb)%7,4==z||3==z&&Yb(g.Xb)||(w=1));else{w=52;var z=(g.Tb+7-g.Wb-1)%7;(4==z||5==z&&Yb(g.Xb%400-1))&&w++}return h(w,
|
|
2)},"%w":function(g){return g.Tb},"%W":function(g){return h(Math.floor((g.Wb+7-(g.Tb+6)%7)/7),2)},"%y":function(g){return(g.Xb+1900).toString().substring(2)},"%Y":function(g){return g.Xb+1900},"%z":function(g){g=g.Jc;var w=0<=g;g=Math.abs(g)/60;return(w?"+":"-")+String("0000"+(g/60*100+g%60)).slice(-4)},"%Z":function(g){return g.Mc},"%%":function(){return"%"}};c=c.replace(/%%/g,"\x00\x00");for(A in t)c.includes(A)&&(c=c.replace(new RegExp(A,"g"),t[A](e)));c=c.replace(/\0\0/g,"%");A=ac(c);if(A.length>
|
|
b)return 0;fb(A,a);return A.length-1}P.fc();
|
|
var cc=[null,Sa,Ua,lb,nb,ob,pb,qb,rb,sb,tb,ub,vb,wb,xb,yb,zb,Cb,Db,Gb,Qb,Rb,Sb,Tb,Ub,Vb],Pc={b:function(a){return Fb(a+24)+24},n:function(a){a=new X(a);a.uc()||(a.hc(!0),hb--);a.ic(!1);gb.push(a);a.sc();return a.vc()},ma:function(a){G("Unexpected exception thrown, this is not properly supported - aborting");xa=!0;throw a;},x:function(){Z(0);var a=gb.pop();if(a.Hc()&&!a.kc()){var b=a.Dc();b&&V(b)(a.Zb);jb(a.Zb)}W=0},e:function(){var a=W;if(!a)return Y=0;var b=new X(a);b.cc(a);var c=b.bc();if(!c)return Y=
|
|
0,a;for(var e=Array.prototype.slice.call(arguments),f=0;f<e.length;f++){var h=e[f];if(0===h||h===c)break;if(dc(h,c,b.Sb+16))return Y=h,a}Y=c;return a},l:function(){var a=W;if(!a)return Y=0;var b=new X(a);b.cc(a);var c=b.bc();if(!c)return Y=0,a;for(var e=Array.prototype.slice.call(arguments),f=0;f<e.length;f++){var h=e[f];if(0===h||h===c)break;if(dc(h,c,b.Sb+16))return Y=h,a}Y=c;return a},h:function(){var a=W;if(!a)return Y=0;var b=new X(a);b.cc(a);var c=b.bc();if(!c)return Y=0,a;for(var e=Array.prototype.slice.call(arguments),
|
|
f=0;f<e.length;f++){var h=e[f];if(0===h||h===c)break;if(dc(h,c,b.Sb+16))return Y=h,a}Y=c;return a},t:jb,M:function(){var a=gb.pop();a||I("no exception to throw");var b=a.Zb;a.kc()||(gb.push(a),a.ic(!0),a.hc(!1),hb++);W=b;throw b;},c:function(a,b,c){(new X(a)).fc(b,c);W=a;hb++;throw a;},pa:function(){return hb},Fa:function(a){ec(a,!y,1,!ma);P.pc()},T:function(a){C?postMessage({cmd:"cleanupThread",thread:a}):Qa(a)},xa:mb,j:function(a){W||(W=a);throw a;},H:nb,Ma:ob,ua:pb,wa:qb,oa:rb,Ka:sb,Ca:tb,Ja:ub,
|
|
V:vb,va:wb,sa:xb,La:yb,ta:zb,Ta:function(){},X:function(){I("To use dlopen, you need enable dynamic linking, see https://github.com/emscripten-core/emscripten/wiki/Linking")},Ua:function(){I("To use dlopen, you need enable dynamic linking, see https://github.com/emscripten-core/emscripten/wiki/Linking")},W:function(){return Date.now()},ya:function(){return 2097152},Oa:function(){return!0},za:function(a,b,c,e){if(a==b)setTimeout(()=>ab(e));else if(C)postMessage({targetThread:a,cmd:"processProxyingQueue",
|
|
queue:e});else{a=P.Vb[a];if(!a)return;a.postMessage({cmd:"processProxyingQueue",queue:e})}return 1},Ea:function(){return-1},Pa:function(a,b){a=new Date(1E3*Bb(a));r()[b>>2>>>0]=a.getUTCSeconds();r()[b+4>>2>>>0]=a.getUTCMinutes();r()[b+8>>2>>>0]=a.getUTCHours();r()[b+12>>2>>>0]=a.getUTCDate();r()[b+16>>2>>>0]=a.getUTCMonth();r()[b+20>>2>>>0]=a.getUTCFullYear()-1900;r()[b+24>>2>>>0]=a.getUTCDay();a=(a.getTime()-Date.UTC(a.getUTCFullYear(),0,1,0,0,0,0))/864E5|0;r()[b+28>>2>>>0]=a},Qa:function(a,b){a=
|
|
new Date(1E3*Bb(a));r()[b>>2>>>0]=a.getSeconds();r()[b+4>>2>>>0]=a.getMinutes();r()[b+8>>2>>>0]=a.getHours();r()[b+12>>2>>>0]=a.getDate();r()[b+16>>2>>>0]=a.getMonth();r()[b+20>>2>>>0]=a.getFullYear()-1900;r()[b+24>>2>>>0]=a.getDay();var c=new Date(a.getFullYear(),0,1),e=(a.getTime()-c.getTime())/864E5|0;r()[b+28>>2>>>0]=e;r()[b+36>>2>>>0]=-(60*a.getTimezoneOffset());e=(new Date(a.getFullYear(),6,1)).getTimezoneOffset();c=c.getTimezoneOffset();a=(e!=c&&a.getTimezoneOffset()==Math.min(c,e))|0;r()[b+
|
|
32>>2>>>0]=a},Ra:function(a){var b=new Date(r()[a+20>>2>>>0]+1900,r()[a+16>>2>>>0],r()[a+12>>2>>>0],r()[a+8>>2>>>0],r()[a+4>>2>>>0],r()[a>>2>>>0],0),c=r()[a+32>>2>>>0],e=b.getTimezoneOffset(),f=new Date(b.getFullYear(),0,1),h=(new Date(b.getFullYear(),6,1)).getTimezoneOffset(),k=f.getTimezoneOffset(),l=Math.min(k,h);0>c?r()[a+32>>2>>>0]=Number(h!=k&&l==e):0<c!=(l==e)&&(h=Math.max(k,h),b.setTime(b.getTime()+6E4*((0<c?l:h)-e)));r()[a+24>>2>>>0]=b.getDay();c=(b.getTime()-f.getTime())/864E5|0;r()[a+28>>
|
|
2>>>0]=c;r()[a>>2>>>0]=b.getSeconds();r()[a+4>>2>>>0]=b.getMinutes();r()[a+8>>2>>>0]=b.getHours();r()[a+12>>2>>>0]=b.getDate();r()[a+16>>2>>>0]=b.getMonth();return b.getTime()/1E3|0},Aa:Cb,Ba:Db,Sa:Hb,y:function(){I("")},U:function(){if(!B&&!y){var a="Blocking on the main thread is very dangerous, see https://emscripten.org/docs/porting/pthreads.html#blocking-on-the-main-browser-thread";Ib||(Ib={});Ib[a]||(Ib[a]=1,B&&(a="warning: "+a),G(a))}},ra:function(){return 4294901760},B:Jb,Ia:function(a,b,
|
|
c){q().copyWithin(a>>>0,b>>>0,b+c>>>0)},F:function(){return B?(__webpack_require__(/*! os */ "?aedb").cpus)().length:navigator.hardwareConcurrency},Da:function(a,b,c){Mb.length=b;c>>=3;for(var e=0;e<b;e++)Mb[e]=ea()[c+e>>>0];return(0>a?Pa[-a-1]:cc[a]).apply(null,Mb)},qa:function(a){var b=q().length;a>>>=0;if(a<=b||4294901760<a)return!1;for(var c=1;4>=c;c*=2){var e=b*(1+.2/c);e=Math.min(e,a+100663296);var f=Math;e=Math.max(a,e);f=f.min.call(f,4294901760,e+(65536-e%65536)%65536);a:{try{m.grow(f-n.byteLength+65535>>>16);p(m.buffer);
|
|
var h=1;break a}catch(k){}h=void 0}if(h)return!0}return!1},Na:function(){throw"unwind";},Ga:Qb,Ha:Rb,J:Ta,I:Sb,S:Tb,ga:Ub,R:Vb,d:function(){return Y},na:Xb,ia:fc,ja:gc,K:hc,f:ic,P:jc,Q:kc,k:lc,p:mc,q:nc,N:oc,s:pc,w:qc,L:rc,E:sc,aa:tc,_:uc,Z:vc,ca:wc,$:xc,ba:yc,Y:zc,g:Ac,r:Bc,i:Cc,ha:Dc,m:Ec,v:Fc,u:Gc,O:Hc,A:Ic,ka:Jc,C:Kc,D:Lc,fa:Mc,da:Nc,ea:Oc,o:function(a){return a},a:m||x.wasmMemory,G:function(a){Y=a},la:bc,z:function(a,b,c,e){return bc(a,b,c,e)}};
|
|
(function(){function a(f,h){x.asm=f.exports;P.qc.push(x.asm.sb);Ea=x.asm.ub;Ga.unshift(x.asm.Va);wa=h;C||(L--,x.monitorRunDependencies&&x.monitorRunDependencies(L),0==L&&(null!==La&&(clearInterval(La),La=null),M&&(f=M,M=null,f())))}function b(f){a(f.instance,f.module)}function c(f){return Oa().then(function(h){return WebAssembly.instantiate(h,e)}).then(function(h){return h}).then(f,function(h){G("failed to asynchronously prepare wasm: "+h);I(h)})}var e={a:Pc};C||(L++,x.monitorRunDependencies&&x.monitorRunDependencies(L));
|
|
if(x.instantiateWasm)try{return x.instantiateWasm(e,a)}catch(f){return G("Module.instantiateWasm callback failed with error: "+f),!1}(function(){return H||"function"!=typeof WebAssembly.instantiateStreaming||Ma()||O.startsWith("file://")||B||"function"!=typeof fetch?c(b):fetch(O,{credentials:"same-origin"}).then(function(f){return WebAssembly.instantiateStreaming(f,e).then(b,function(h){G("wasm streaming compile failed: "+h);G("falling back to ArrayBuffer instantiation");return c(b)})})})().catch(ia);
|
|
return{}})();x.___wasm_call_ctors=function(){return(x.___wasm_call_ctors=x.asm.Va).apply(null,arguments)};x._OrtInit=function(){return(x._OrtInit=x.asm.Wa).apply(null,arguments)};x._OrtCreateSessionOptions=function(){return(x._OrtCreateSessionOptions=x.asm.Xa).apply(null,arguments)};x._OrtAppendExecutionProvider=function(){return(x._OrtAppendExecutionProvider=x.asm.Ya).apply(null,arguments)};x._OrtAddSessionConfigEntry=function(){return(x._OrtAddSessionConfigEntry=x.asm.Za).apply(null,arguments)};
|
|
x._OrtReleaseSessionOptions=function(){return(x._OrtReleaseSessionOptions=x.asm._a).apply(null,arguments)};x._OrtCreateSession=function(){return(x._OrtCreateSession=x.asm.$a).apply(null,arguments)};x._OrtReleaseSession=function(){return(x._OrtReleaseSession=x.asm.ab).apply(null,arguments)};x._OrtGetInputCount=function(){return(x._OrtGetInputCount=x.asm.bb).apply(null,arguments)};x._OrtGetOutputCount=function(){return(x._OrtGetOutputCount=x.asm.cb).apply(null,arguments)};
|
|
x._OrtGetInputName=function(){return(x._OrtGetInputName=x.asm.db).apply(null,arguments)};x._OrtGetOutputName=function(){return(x._OrtGetOutputName=x.asm.eb).apply(null,arguments)};x._OrtFree=function(){return(x._OrtFree=x.asm.fb).apply(null,arguments)};x._OrtCreateTensor=function(){return(x._OrtCreateTensor=x.asm.gb).apply(null,arguments)};x._OrtGetTensorData=function(){return(x._OrtGetTensorData=x.asm.hb).apply(null,arguments)};
|
|
x._OrtReleaseTensor=function(){return(x._OrtReleaseTensor=x.asm.ib).apply(null,arguments)};x._OrtCreateRunOptions=function(){return(x._OrtCreateRunOptions=x.asm.jb).apply(null,arguments)};x._OrtAddRunConfigEntry=function(){return(x._OrtAddRunConfigEntry=x.asm.kb).apply(null,arguments)};x._OrtReleaseRunOptions=function(){return(x._OrtReleaseRunOptions=x.asm.lb).apply(null,arguments)};x._OrtRun=function(){return(x._OrtRun=x.asm.mb).apply(null,arguments)};
|
|
x._OrtEndProfiling=function(){return(x._OrtEndProfiling=x.asm.nb).apply(null,arguments)};var $a=x._pthread_self=function(){return($a=x._pthread_self=x.asm.ob).apply(null,arguments)},Fb=x._malloc=function(){return(Fb=x._malloc=x.asm.pb).apply(null,arguments)},kb=x._free=function(){return(kb=x._free=x.asm.qb).apply(null,arguments)},Wa=x._fflush=function(){return(Wa=x._fflush=x.asm.rb).apply(null,arguments)};x.__emscripten_tls_init=function(){return(x.__emscripten_tls_init=x.asm.sb).apply(null,arguments)};
|
|
var Va=x.___funcs_on_exit=function(){return(Va=x.___funcs_on_exit=x.asm.tb).apply(null,arguments)},ec=x.__emscripten_thread_init=function(){return(ec=x.__emscripten_thread_init=x.asm.vb).apply(null,arguments)};x.__emscripten_thread_crashed=function(){return(x.__emscripten_thread_crashed=x.asm.wb).apply(null,arguments)};
|
|
var Lb=x._emscripten_run_in_main_runtime_thread_js=function(){return(Lb=x._emscripten_run_in_main_runtime_thread_js=x.asm.xb).apply(null,arguments)},Ab=x.__emscripten_proxy_execute_task_queue=function(){return(Ab=x.__emscripten_proxy_execute_task_queue=x.asm.yb).apply(null,arguments)},Za=x.__emscripten_thread_free_data=function(){return(Za=x.__emscripten_thread_free_data=x.asm.zb).apply(null,arguments)},eb=x.__emscripten_thread_exit=function(){return(eb=x.__emscripten_thread_exit=x.asm.Ab).apply(null,
|
|
arguments)},Z=x._setThrew=function(){return(Z=x._setThrew=x.asm.Bb).apply(null,arguments)},cb=x._emscripten_stack_set_limits=function(){return(cb=x._emscripten_stack_set_limits=x.asm.Cb).apply(null,arguments)},S=x.stackSave=function(){return(S=x.stackSave=x.asm.Db).apply(null,arguments)},U=x.stackRestore=function(){return(U=x.stackRestore=x.asm.Eb).apply(null,arguments)},Kb=x.stackAlloc=function(){return(Kb=x.stackAlloc=x.asm.Fb).apply(null,arguments)},dc=x.___cxa_can_catch=function(){return(dc=x.___cxa_can_catch=
|
|
x.asm.Gb).apply(null,arguments)},ib=x.___cxa_is_pointer_type=function(){return(ib=x.___cxa_is_pointer_type=x.asm.Hb).apply(null,arguments)},Qc=x.dynCall_j=function(){return(Qc=x.dynCall_j=x.asm.Ib).apply(null,arguments)},Rc=x.dynCall_iiiiij=function(){return(Rc=x.dynCall_iiiiij=x.asm.Jb).apply(null,arguments)},Sc=x.dynCall_jii=function(){return(Sc=x.dynCall_jii=x.asm.Kb).apply(null,arguments)},Tc=x.dynCall_viiiiij=function(){return(Tc=x.dynCall_viiiiij=x.asm.Lb).apply(null,arguments)},Uc=x.dynCall_vjji=
|
|
function(){return(Uc=x.dynCall_vjji=x.asm.Mb).apply(null,arguments)},Vc=x.dynCall_viiijjjii=function(){return(Vc=x.dynCall_viiijjjii=x.asm.Nb).apply(null,arguments)},Wc=x.dynCall_iij=function(){return(Wc=x.dynCall_iij=x.asm.Ob).apply(null,arguments)},Xc=x.dynCall_ji=function(){return(Xc=x.dynCall_ji=x.asm.Pb).apply(null,arguments)},Yc=x.dynCall_iiiiiij=function(){return(Yc=x.dynCall_iiiiiij=x.asm.Qb).apply(null,arguments)},Zc=x.dynCall_iiij=function(){return(Zc=x.dynCall_iiij=x.asm.Rb).apply(null,
|
|
arguments)};function ic(a,b){var c=S();try{return V(a)(b)}catch(e){U(c);if(e!==e+0)throw e;Z(1,0)}}function Bc(a,b){var c=S();try{V(a)(b)}catch(e){U(c);if(e!==e+0)throw e;Z(1,0)}}function Cc(a,b,c){var e=S();try{V(a)(b,c)}catch(f){U(e);if(f!==f+0)throw f;Z(1,0)}}function lc(a,b,c){var e=S();try{return V(a)(b,c)}catch(f){U(e);if(f!==f+0)throw f;Z(1,0)}}function mc(a,b,c,e){var f=S();try{return V(a)(b,c,e)}catch(h){U(f);if(h!==h+0)throw h;Z(1,0)}}
|
|
function qc(a,b,c,e,f,h,k){var l=S();try{return V(a)(b,c,e,f,h,k)}catch(u){U(l);if(u!==u+0)throw u;Z(1,0)}}function Ac(a){var b=S();try{V(a)()}catch(c){U(b);if(c!==c+0)throw c;Z(1,0)}}function pc(a,b,c,e,f,h){var k=S();try{return V(a)(b,c,e,f,h)}catch(l){U(k);if(l!==l+0)throw l;Z(1,0)}}function nc(a,b,c,e,f){var h=S();try{return V(a)(b,c,e,f)}catch(k){U(h);if(k!==k+0)throw k;Z(1,0)}}function Ec(a,b,c,e){var f=S();try{V(a)(b,c,e)}catch(h){U(f);if(h!==h+0)throw h;Z(1,0)}}
|
|
function Gc(a,b,c,e,f,h){var k=S();try{V(a)(b,c,e,f,h)}catch(l){U(k);if(l!==l+0)throw l;Z(1,0)}}function Fc(a,b,c,e,f){var h=S();try{V(a)(b,c,e,f)}catch(k){U(h);if(k!==k+0)throw k;Z(1,0)}}function Ic(a,b,c,e,f,h,k,l){var u=S();try{V(a)(b,c,e,f,h,k,l)}catch(t){U(u);if(t!==t+0)throw t;Z(1,0)}}function kc(a,b,c){var e=S();try{return V(a)(b,c)}catch(f){U(e);if(f!==f+0)throw f;Z(1,0)}}function jc(a,b,c){var e=S();try{return V(a)(b,c)}catch(f){U(e);if(f!==f+0)throw f;Z(1,0)}}
|
|
function Jc(a,b,c,e,f,h,k,l,u){var t=S();try{V(a)(b,c,e,f,h,k,l,u)}catch(A){U(t);if(A!==A+0)throw A;Z(1,0)}}function Hc(a,b,c,e,f,h,k){var l=S();try{V(a)(b,c,e,f,h,k)}catch(u){U(l);if(u!==u+0)throw u;Z(1,0)}}function oc(a,b,c,e,f,h){var k=S();try{return V(a)(b,c,e,f,h)}catch(l){U(k);if(l!==l+0)throw l;Z(1,0)}}function rc(a,b,c,e,f,h,k,l){var u=S();try{return V(a)(b,c,e,f,h,k,l)}catch(t){U(u);if(t!==t+0)throw t;Z(1,0)}}
|
|
function sc(a,b,c,e,f,h,k,l,u,t,A,K){var J=S();try{return V(a)(b,c,e,f,h,k,l,u,t,A,K)}catch(g){U(J);if(g!==g+0)throw g;Z(1,0)}}function Kc(a,b,c,e,f,h,k,l,u,t,A){var K=S();try{V(a)(b,c,e,f,h,k,l,u,t,A)}catch(J){U(K);if(J!==J+0)throw J;Z(1,0)}}function Lc(a,b,c,e,f,h,k,l,u,t,A,K,J,g,w,z){var N=S();try{V(a)(b,c,e,f,h,k,l,u,t,A,K,J,g,w,z)}catch(T){U(N);if(T!==T+0)throw T;Z(1,0)}}function hc(a){var b=S();try{return V(a)()}catch(c){U(b);if(c!==c+0)throw c;Z(1,0)}}
|
|
function gc(a,b,c){var e=S();try{return V(a)(b,c)}catch(f){U(e);if(f!==f+0)throw f;Z(1,0)}}function fc(a,b,c){var e=S();try{return V(a)(b,c)}catch(f){U(e);if(f!==f+0)throw f;Z(1,0)}}function Dc(a,b,c,e){var f=S();try{V(a)(b,c,e)}catch(h){U(f);if(h!==h+0)throw h;Z(1,0)}}function Mc(a,b,c,e,f,h,k,l){var u=S();try{Tc(a,b,c,e,f,h,k,l)}catch(t){U(u);if(t!==t+0)throw t;Z(1,0)}}function Oc(a,b,c,e,f,h){var k=S();try{Uc(a,b,c,e,f,h)}catch(l){U(k);if(l!==l+0)throw l;Z(1,0)}}
|
|
function Nc(a,b,c,e,f,h,k,l,u,t,A,K){var J=S();try{Vc(a,b,c,e,f,h,k,l,u,t,A,K)}catch(g){U(J);if(g!==g+0)throw g;Z(1,0)}}function wc(a,b,c,e){var f=S();try{return Wc(a,b,c,e)}catch(h){U(f);if(h!==h+0)throw h;Z(1,0)}}function yc(a,b){var c=S();try{return Xc(a,b)}catch(e){U(c);if(e!==e+0)throw e;Z(1,0)}}function tc(a,b,c,e,f,h,k,l){var u=S();try{return Yc(a,b,c,e,f,h,k,l)}catch(t){U(u);if(t!==t+0)throw t;Z(1,0)}}function xc(a){var b=S();try{return Qc(a)}catch(c){U(b);if(c!==c+0)throw c;Z(1,0)}}
|
|
function uc(a,b,c,e,f,h,k){var l=S();try{return Rc(a,b,c,e,f,h,k)}catch(u){U(l);if(u!==u+0)throw u;Z(1,0)}}function vc(a,b,c,e,f){var h=S();try{return Zc(a,b,c,e,f)}catch(k){U(h);if(k!==k+0)throw k;Z(1,0)}}function zc(a,b,c){var e=S();try{return Sc(a,b,c)}catch(f){U(e);if(f!==f+0)throw f;Z(1,0)}}x.UTF8ToString=Aa;x.stringToUTF8=function(a,b,c){return Ba(a,q(),b,c)};x.lengthBytesUTF8=Ca;x.keepRuntimeAlive=F;x.wasmMemory=m;x.stackSave=S;x.stackRestore=U;x.stackAlloc=Kb;x.ExitStatus=E;x.PThread=P;var $c;
|
|
M=function ad(){$c||bd();$c||(M=ad)};
|
|
function bd(){function a(){if(!$c&&($c=!0,x.calledRun=!0,!xa)){C||R(Ga);ha(x);if(x.onRuntimeInitialized)x.onRuntimeInitialized();if(!C){if(x.postRun)for("function"==typeof x.postRun&&(x.postRun=[x.postRun]);x.postRun.length;){var b=x.postRun.shift();Ia.unshift(b)}R(Ia)}}}if(!(0<L))if(C)ha(x),C||R(Ga),postMessage({cmd:"loaded"});else{if(x.preRun)for("function"==typeof x.preRun&&(x.preRun=[x.preRun]);x.preRun.length;)Ka();R(Fa);0<L||(x.setStatus?(x.setStatus("Running..."),setTimeout(function(){setTimeout(function(){x.setStatus("")},
|
|
1);a()},1)):a())}}if(x.preInit)for("function"==typeof x.preInit&&(x.preInit=[x.preInit]);0<x.preInit.length;)x.preInit.pop()();bd();
|
|
|
|
|
|
return ortWasmThreaded.ready
|
|
}
|
|
);
|
|
})();
|
|
if (true)
|
|
module.exports = ortWasmThreaded;
|
|
else {}
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./lib/wasm/binding/ort-wasm.js":
|
|
/*!**************************************!*\
|
|
!*** ./lib/wasm/binding/ort-wasm.js ***!
|
|
\**************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
var __filename = "/index.js";
|
|
var __dirname = "/";
|
|
|
|
var ortWasm = (() => {
|
|
var _scriptDir = typeof document !== 'undefined' && document.currentScript ? document.currentScript.src : undefined;
|
|
if (true) _scriptDir = _scriptDir || __filename;
|
|
return (
|
|
function(ortWasm) {
|
|
ortWasm = ortWasm || {};
|
|
|
|
|
|
var d;d||(d=typeof ortWasm !== 'undefined' ? ortWasm : {});var aa,ba;d.ready=new Promise(function(a,b){aa=a;ba=b});var ca=Object.assign({},d),da="./this.program",ea=(a,b)=>{throw b;},fa="object"==typeof window,m="function"==typeof importScripts,p="object"==typeof process&&"object"==typeof process.versions&&"string"==typeof process.versions.node,q="",ha,r,v,fs,y,ia;
|
|
if(p)q=m?(__webpack_require__(/*! path */ "?75c6").dirname)(q)+"/":__dirname+"/",ia=()=>{y||(fs=__webpack_require__(/*! fs */ "?63c8"),y=__webpack_require__(/*! path */ "?75c6"))},ha=function(a,b){ia();a=y.normalize(a);return fs.readFileSync(a,b?void 0:"utf8")},v=a=>{a=ha(a,!0);a.buffer||(a=new Uint8Array(a));return a},r=(a,b,c)=>{ia();a=y.normalize(a);fs.readFile(a,function(e,f){e?c(e):b(f.buffer)})},1<process.argv.length&&(da=process.argv[1].replace(/\\/g,"/")),process.argv.slice(2),process.on("uncaughtException",function(a){if(!(a instanceof ja))throw a;}),process.on("unhandledRejection",
|
|
function(a){throw a;}),ea=(a,b)=>{if(noExitRuntime||0<ka)throw process.exitCode=a,b;b instanceof ja||z("exiting due to exception: "+b);process.exit(a)},d.inspect=function(){return"[Emscripten Module object]"};else if(fa||m)m?q=self.location.href:"undefined"!=typeof document&&document.currentScript&&(q=document.currentScript.src),_scriptDir&&(q=_scriptDir),0!==q.indexOf("blob:")?q=q.substr(0,q.replace(/[?#].*/,"").lastIndexOf("/")+1):q="",ha=a=>{var b=new XMLHttpRequest;b.open("GET",a,!1);b.send(null);
|
|
return b.responseText},m&&(v=a=>{var b=new XMLHttpRequest;b.open("GET",a,!1);b.responseType="arraybuffer";b.send(null);return new Uint8Array(b.response)}),r=(a,b,c)=>{var e=new XMLHttpRequest;e.open("GET",a,!0);e.responseType="arraybuffer";e.onload=()=>{200==e.status||0==e.status&&e.response?b(e.response):c()};e.onerror=c;e.send(null)};var la=d.print||console.log.bind(console),z=d.printErr||console.warn.bind(console);Object.assign(d,ca);ca=null;d.thisProgram&&(da=d.thisProgram);d.quit&&(ea=d.quit);
|
|
var A;d.wasmBinary&&(A=d.wasmBinary);var noExitRuntime=d.noExitRuntime||!1;"object"!=typeof WebAssembly&&B("no native wasm support detected");var ma,D=!1,na="undefined"!=typeof TextDecoder?new TextDecoder("utf8"):void 0;
|
|
function oa(a,b,c){b>>>=0;var e=b+c;for(c=b;a[c]&&!(c>=e);)++c;if(16<c-b&&a.buffer&&na)return na.decode(a.subarray(b,c));for(e="";b<c;){var f=a[b++];if(f&128){var h=a[b++]&63;if(192==(f&224))e+=String.fromCharCode((f&31)<<6|h);else{var k=a[b++]&63;f=224==(f&240)?(f&15)<<12|h<<6|k:(f&7)<<18|h<<12|k<<6|a[b++]&63;65536>f?e+=String.fromCharCode(f):(f-=65536,e+=String.fromCharCode(55296|f>>10,56320|f&1023))}}else e+=String.fromCharCode(f)}return e}function pa(a,b){return(a>>>=0)?oa(G,a,b):""}
|
|
function qa(a,b,c,e){c>>>=0;if(!(0<e))return 0;var f=c;e=c+e-1;for(var h=0;h<a.length;++h){var k=a.charCodeAt(h);if(55296<=k&&57343>=k){var l=a.charCodeAt(++h);k=65536+((k&1023)<<10)|l&1023}if(127>=k){if(c>=e)break;b[c++>>>0]=k}else{if(2047>=k){if(c+1>=e)break;b[c++>>>0]=192|k>>6}else{if(65535>=k){if(c+2>=e)break;b[c++>>>0]=224|k>>12}else{if(c+3>=e)break;b[c++>>>0]=240|k>>18;b[c++>>>0]=128|k>>12&63}b[c++>>>0]=128|k>>6&63}b[c++>>>0]=128|k&63}}b[c>>>0]=0;return c-f}
|
|
function ra(a){for(var b=0,c=0;c<a.length;++c){var e=a.charCodeAt(c);127>=e?b++:2047>=e?b+=2:55296<=e&&57343>=e?(b+=4,++c):b+=3}return b}var sa,H,G,I,J;function ta(){var a=ma.buffer;sa=a;d.HEAP8=H=new Int8Array(a);d.HEAP16=new Int16Array(a);d.HEAP32=I=new Int32Array(a);d.HEAPU8=G=new Uint8Array(a);d.HEAPU16=new Uint16Array(a);d.HEAPU32=J=new Uint32Array(a);d.HEAPF32=new Float32Array(a);d.HEAPF64=new Float64Array(a)}var ua,va=[],wa=[],xa=[],ya=[],ka=0;
|
|
function za(){var a=d.preRun.shift();va.unshift(a)}var K=0,Aa=null,L=null;function B(a){if(d.onAbort)d.onAbort(a);a="Aborted("+a+")";z(a);D=!0;a=new WebAssembly.RuntimeError(a+". Build with -sASSERTIONS for more info.");ba(a);throw a;}function Ba(){return N.startsWith("data:application/octet-stream;base64,")}var N;N="ort-wasm.wasm";if(!Ba()){var Ca=N;N=d.locateFile?d.locateFile(Ca,q):q+Ca}
|
|
function Da(){var a=N;try{if(a==N&&A)return new Uint8Array(A);if(v)return v(a);throw"both async and sync fetching of the wasm failed";}catch(b){B(b)}}
|
|
function Ea(){if(!A&&(fa||m)){if("function"==typeof fetch&&!N.startsWith("file://"))return fetch(N,{credentials:"same-origin"}).then(function(a){if(!a.ok)throw"failed to load wasm binary file at '"+N+"'";return a.arrayBuffer()}).catch(function(){return Da()});if(r)return new Promise(function(a,b){r(N,function(c){a(new Uint8Array(c))},b)})}return Promise.resolve().then(function(){return Da()})}function ja(a){this.name="ExitStatus";this.message="Program terminated with exit("+a+")";this.status=a}
|
|
function O(a){for(;0<a.length;)a.shift()(d)}var P=[],Q=0,R=0;
|
|
function S(a){this.Db=a;this.zb=a-24;this.Ub=function(b){J[this.zb+4>>2>>>0]=b};this.Eb=function(){return J[this.zb+4>>2>>>0]};this.Sb=function(b){J[this.zb+8>>2>>>0]=b};this.Wb=function(){return J[this.zb+8>>2>>>0]};this.Tb=function(){I[this.zb>>2>>>0]=0};this.Ib=function(b){H[this.zb+12>>0>>>0]=b?1:0};this.Pb=function(){return 0!=H[this.zb+12>>0>>>0]};this.Jb=function(b){H[this.zb+13>>0>>>0]=b?1:0};this.Lb=function(){return 0!=H[this.zb+13>>0>>>0]};this.Rb=function(b,c){this.Fb(0);this.Ub(b);this.Sb(c);
|
|
this.Tb();this.Ib(!1);this.Jb(!1)};this.Nb=function(){I[this.zb>>2>>>0]+=1};this.Xb=function(){var b=I[this.zb>>2>>>0];I[this.zb>>2>>>0]=b-1;return 1===b};this.Fb=function(b){J[this.zb+16>>2>>>0]=b};this.Ob=function(){return J[this.zb+16>>2>>>0]};this.Qb=function(){if(Fa(this.Eb()))return J[this.Db>>2>>>0];var b=this.Ob();return 0!==b?b:this.Db}}function Ga(a){return Ha((new S(a)).zb)}var T=[];function U(a){var b=T[a];b||(a>=T.length&&(T.length=a+1),T[a]=b=ua.get(a));return b}
|
|
function Ia(a){var b=ra(a)+1,c=Ja(b);c&&qa(a,H,c,b);return c}function Ka(a,b,c){function e(n){return(n=n.toTimeString().match(/\(([A-Za-z ]+)\)$/))?n[1]:"GMT"}var f=(new Date).getFullYear(),h=new Date(f,0,1),k=new Date(f,6,1);f=h.getTimezoneOffset();var l=k.getTimezoneOffset();I[a>>2>>>0]=60*Math.max(f,l);I[b>>2>>>0]=Number(f!=l);a=e(h);b=e(k);a=Ia(a);b=Ia(b);l<f?(J[c>>2>>>0]=a,J[c+4>>2>>>0]=b):(J[c>>2>>>0]=b,J[c+4>>2>>>0]=a)}function La(a,b,c){La.Vb||(La.Vb=!0,Ka(a,b,c))}var Ma={};
|
|
function Na(){if(!Oa){var a={USER:"web_user",LOGNAME:"web_user",PATH:"/",PWD:"/",HOME:"/home/web_user",LANG:("object"==typeof navigator&&navigator.languages&&navigator.languages[0]||"C").replace("-","_")+".UTF-8",_:da||"./this.program"},b;for(b in Ma)void 0===Ma[b]?delete a[b]:a[b]=Ma[b];var c=[];for(b in a)c.push(b+"="+a[b]);Oa=c}return Oa}var Oa,Pa=[null,[],[]];function Qa(a,b){var c=Pa[a];0===b||10===b?((1===a?la:z)(oa(c,0)),c.length=0):c.push(b)}var V=0;
|
|
function Ra(){if("object"==typeof crypto&&"function"==typeof crypto.getRandomValues){var a=new Uint8Array(1);return()=>{crypto.getRandomValues(a);return a[0]}}if(p)try{var b=__webpack_require__(Object(function webpackMissingModule() { var e = new Error("Cannot find module 'crypto'"); e.code = 'MODULE_NOT_FOUND'; throw e; }()));return()=>b.randomBytes(1)[0]}catch(c){}return()=>B("randomDevice")}function W(a,b){W.Mb||(W.Mb=Ra());for(var c=0;c<b;c++)H[a+c>>0>>>0]=W.Mb();return 0}function Sa(a){return 0===a%4&&(0!==a%100||0===a%400)}var Ta=[31,29,31,30,31,30,31,31,30,31,30,31],Ua=[31,28,31,30,31,30,31,31,30,31,30,31];
|
|
function Va(a){var b=Array(ra(a)+1);qa(a,b,0,b.length);return b}
|
|
function Wa(a,b,c,e){function f(g,u,w){for(g="number"==typeof g?g.toString():g||"";g.length<u;)g=w[0]+g;return g}function h(g,u){return f(g,u,"0")}function k(g,u){function w(M){return 0>M?-1:0<M?1:0}var F;0===(F=w(g.getFullYear()-u.getFullYear()))&&0===(F=w(g.getMonth()-u.getMonth()))&&(F=w(g.getDate()-u.getDate()));return F}function l(g){switch(g.getDay()){case 0:return new Date(g.getFullYear()-1,11,29);case 1:return g;case 2:return new Date(g.getFullYear(),0,3);case 3:return new Date(g.getFullYear(),
|
|
0,2);case 4:return new Date(g.getFullYear(),0,1);case 5:return new Date(g.getFullYear()-1,11,31);case 6:return new Date(g.getFullYear()-1,11,30)}}function n(g){var u=g.Bb;for(g=new Date((new Date(g.Cb+1900,0,1)).getTime());0<u;){var w=g.getMonth(),F=(Sa(g.getFullYear())?Ta:Ua)[w];if(u>F-g.getDate())u-=F-g.getDate()+1,g.setDate(1),11>w?g.setMonth(w+1):(g.setMonth(0),g.setFullYear(g.getFullYear()+1));else{g.setDate(g.getDate()+u);break}}w=new Date(g.getFullYear()+1,0,4);u=l(new Date(g.getFullYear(),
|
|
0,4));w=l(w);return 0>=k(u,g)?0>=k(w,g)?g.getFullYear()+1:g.getFullYear():g.getFullYear()-1}var t=I[e+40>>2>>>0];e={$b:I[e>>2>>>0],Zb:I[e+4>>2>>>0],Gb:I[e+8>>2>>>0],Kb:I[e+12>>2>>>0],Hb:I[e+16>>2>>>0],Cb:I[e+20>>2>>>0],Ab:I[e+24>>2>>>0],Bb:I[e+28>>2>>>0],bc:I[e+32>>2>>>0],Yb:I[e+36>>2>>>0],ac:t?pa(t):""};c=pa(c);t={"%c":"%a %b %d %H:%M:%S %Y","%D":"%m/%d/%y","%F":"%Y-%m-%d","%h":"%b","%r":"%I:%M:%S %p","%R":"%H:%M","%T":"%H:%M:%S","%x":"%m/%d/%y","%X":"%H:%M:%S","%Ec":"%c","%EC":"%C","%Ex":"%m/%d/%y",
|
|
"%EX":"%H:%M:%S","%Ey":"%y","%EY":"%Y","%Od":"%d","%Oe":"%e","%OH":"%H","%OI":"%I","%Om":"%m","%OM":"%M","%OS":"%S","%Ou":"%u","%OU":"%U","%OV":"%V","%Ow":"%w","%OW":"%W","%Oy":"%y"};for(var x in t)c=c.replace(new RegExp(x,"g"),t[x]);var E="Sunday Monday Tuesday Wednesday Thursday Friday Saturday".split(" "),C="January February March April May June July August September October November December".split(" ");t={"%a":function(g){return E[g.Ab].substring(0,3)},"%A":function(g){return E[g.Ab]},"%b":function(g){return C[g.Hb].substring(0,
|
|
3)},"%B":function(g){return C[g.Hb]},"%C":function(g){return h((g.Cb+1900)/100|0,2)},"%d":function(g){return h(g.Kb,2)},"%e":function(g){return f(g.Kb,2," ")},"%g":function(g){return n(g).toString().substring(2)},"%G":function(g){return n(g)},"%H":function(g){return h(g.Gb,2)},"%I":function(g){g=g.Gb;0==g?g=12:12<g&&(g-=12);return h(g,2)},"%j":function(g){for(var u=0,w=0;w<=g.Hb-1;u+=(Sa(g.Cb+1900)?Ta:Ua)[w++]);return h(g.Kb+u,3)},"%m":function(g){return h(g.Hb+1,2)},"%M":function(g){return h(g.Zb,
|
|
2)},"%n":function(){return"\n"},"%p":function(g){return 0<=g.Gb&&12>g.Gb?"AM":"PM"},"%S":function(g){return h(g.$b,2)},"%t":function(){return"\t"},"%u":function(g){return g.Ab||7},"%U":function(g){return h(Math.floor((g.Bb+7-g.Ab)/7),2)},"%V":function(g){var u=Math.floor((g.Bb+7-(g.Ab+6)%7)/7);2>=(g.Ab+371-g.Bb-2)%7&&u++;if(u)53==u&&(w=(g.Ab+371-g.Bb)%7,4==w||3==w&&Sa(g.Cb)||(u=1));else{u=52;var w=(g.Ab+7-g.Bb-1)%7;(4==w||5==w&&Sa(g.Cb%400-1))&&u++}return h(u,2)},"%w":function(g){return g.Ab},"%W":function(g){return h(Math.floor((g.Bb+
|
|
7-(g.Ab+6)%7)/7),2)},"%y":function(g){return(g.Cb+1900).toString().substring(2)},"%Y":function(g){return g.Cb+1900},"%z":function(g){g=g.Yb;var u=0<=g;g=Math.abs(g)/60;return(u?"+":"-")+String("0000"+(g/60*100+g%60)).slice(-4)},"%Z":function(g){return g.ac},"%%":function(){return"%"}};c=c.replace(/%%/g,"\x00\x00");for(x in t)c.includes(x)&&(c=c.replace(new RegExp(x,"g"),t[x](e)));c=c.replace(/\0\0/g,"%");x=Va(c);if(x.length>b)return 0;H.set(x,a>>>0);return x.length-1}
|
|
var Jb={a:function(a){return Ja(a+24)+24},m:function(a){a=new S(a);a.Pb()||(a.Ib(!0),Q--);a.Jb(!1);P.push(a);a.Nb();return a.Qb()},ia:function(a){z("Unexpected exception thrown, this is not properly supported - aborting");D=!0;throw a;},w:function(){X(0);var a=P.pop();if(a.Xb()&&!a.Lb()){var b=a.Wb();b&&U(b)(a.Db);Ga(a.Db)}R=0},d:function(){var a=R;if(!a)return V=0;var b=new S(a);b.Fb(a);var c=b.Eb();if(!c)return V=0,a;for(var e=Array.prototype.slice.call(arguments),f=0;f<e.length;f++){var h=e[f];
|
|
if(0===h||h===c)break;if(Xa(h,c,b.zb+16))return V=h,a}V=c;return a},k:function(){var a=R;if(!a)return V=0;var b=new S(a);b.Fb(a);var c=b.Eb();if(!c)return V=0,a;for(var e=Array.prototype.slice.call(arguments),f=0;f<e.length;f++){var h=e[f];if(0===h||h===c)break;if(Xa(h,c,b.zb+16))return V=h,a}V=c;return a},g:function(){var a=R;if(!a)return V=0;var b=new S(a);b.Fb(a);var c=b.Eb();if(!c)return V=0,a;for(var e=Array.prototype.slice.call(arguments),f=0;f<e.length;f++){var h=e[f];if(0===h||h===c)break;
|
|
if(Xa(h,c,b.zb+16))return V=h,a}V=c;return a},s:Ga,L:function(){var a=P.pop();a||B("no exception to throw");var b=a.Db;a.Lb()||(P.push(a),a.Jb(!0),a.Ib(!1),Q++);R=b;throw b;},b:function(a,b,c){(new S(a)).Rb(b,c);R=a;Q++;throw a;},la:function(){return Q},i:function(a){R||(R=a);throw a;},H:function(){return 0},Ba:function(){},pa:function(){},ra:function(){},ka:function(){return 0},za:function(){},ua:function(){},ya:function(){},R:function(){},qa:function(){},na:function(){},Aa:function(){},oa:function(){},
|
|
Ha:function(){},Ja:function(){B("To use dlopen, you need enable dynamic linking, see https://github.com/emscripten-core/emscripten/wiki/Linking")},Ia:function(){B("To use dlopen, you need enable dynamic linking, see https://github.com/emscripten-core/emscripten/wiki/Linking")},S:function(){return Date.now()},Ca:function(){return!0},Da:function(a,b){a=new Date(1E3*(J[a>>>2]+4294967296*I[a+4>>>2]));I[b>>2>>>0]=a.getUTCSeconds();I[b+4>>2>>>0]=a.getUTCMinutes();I[b+8>>2>>>0]=a.getUTCHours();I[b+12>>2>>>
|
|
0]=a.getUTCDate();I[b+16>>2>>>0]=a.getUTCMonth();I[b+20>>2>>>0]=a.getUTCFullYear()-1900;I[b+24>>2>>>0]=a.getUTCDay();I[b+28>>2>>>0]=(a.getTime()-Date.UTC(a.getUTCFullYear(),0,1,0,0,0,0))/864E5|0},Ea:function(a,b){a=new Date(1E3*(J[a>>>2]+4294967296*I[a+4>>>2]));I[b>>2>>>0]=a.getSeconds();I[b+4>>2>>>0]=a.getMinutes();I[b+8>>2>>>0]=a.getHours();I[b+12>>2>>>0]=a.getDate();I[b+16>>2>>>0]=a.getMonth();I[b+20>>2>>>0]=a.getFullYear()-1900;I[b+24>>2>>>0]=a.getDay();var c=new Date(a.getFullYear(),0,1);I[b+
|
|
28>>2>>>0]=(a.getTime()-c.getTime())/864E5|0;I[b+36>>2>>>0]=-(60*a.getTimezoneOffset());var e=(new Date(a.getFullYear(),6,1)).getTimezoneOffset();c=c.getTimezoneOffset();I[b+32>>2>>>0]=(e!=c&&a.getTimezoneOffset()==Math.min(c,e))|0},Fa:function(a){var b=new Date(I[a+20>>2>>>0]+1900,I[a+16>>2>>>0],I[a+12>>2>>>0],I[a+8>>2>>>0],I[a+4>>2>>>0],I[a>>2>>>0],0),c=I[a+32>>2>>>0],e=b.getTimezoneOffset(),f=new Date(b.getFullYear(),0,1),h=(new Date(b.getFullYear(),6,1)).getTimezoneOffset(),k=f.getTimezoneOffset(),
|
|
l=Math.min(k,h);0>c?I[a+32>>2>>>0]=Number(h!=k&&l==e):0<c!=(l==e)&&(h=Math.max(k,h),b.setTime(b.getTime()+6E4*((0<c?l:h)-e)));I[a+24>>2>>>0]=b.getDay();I[a+28>>2>>>0]=(b.getTime()-f.getTime())/864E5|0;I[a>>2>>>0]=b.getSeconds();I[a+4>>2>>>0]=b.getMinutes();I[a+8>>2>>>0]=b.getHours();I[a+12>>2>>>0]=b.getDate();I[a+16>>2>>>0]=b.getMonth();return b.getTime()/1E3|0},sa:function(){return-52},ta:function(){},Ga:La,B:function(){B("")},ma:function(){return 4294901760},I:p?()=>{var a=process.hrtime();return 1E3*
|
|
a[0]+a[1]/1E6}:()=>performance.now(),xa:function(a,b,c){G.copyWithin(a>>>0,b>>>0,b+c>>>0)},G:function(a){var b=G.length;a>>>=0;if(4294901760<a)return!1;for(var c=1;4>=c;c*=2){var e=b*(1+.2/c);e=Math.min(e,a+100663296);var f=Math;e=Math.max(a,e);f=f.min.call(f,4294901760,e+(65536-e%65536)%65536);a:{try{ma.grow(f-sa.byteLength+65535>>>16);ta();var h=1;break a}catch(k){}h=void 0}if(h)return!0}return!1},va:function(a,b){var c=0;Na().forEach(function(e,f){var h=b+c;f=J[a+4*f>>2>>>0]=h;for(h=0;h<e.length;++h)H[f++>>
|
|
0>>>0]=e.charCodeAt(h);H[f>>0>>>0]=0;c+=e.length+1});return 0},wa:function(a,b){var c=Na();J[a>>2>>>0]=c.length;var e=0;c.forEach(function(f){e+=f.length+1});J[b>>2>>>0]=e;return 0},ba:function(a){noExitRuntime||0<ka||(Ya(),O(xa),Za(0),Pa[1].length&&Qa(1,10),Pa[2].length&&Qa(2,10));if(!(noExitRuntime||0<ka)){if(d.onExit)d.onExit(a);D=!0}ea(a,new ja(a))},E:function(){return 52},Q:function(){return 52},ca:function(){return 70},P:function(a,b,c,e){for(var f=0,h=0;h<c;h++){var k=J[b>>2>>>0],l=J[b+4>>
|
|
2>>>0];b+=8;for(var n=0;n<l;n++)Qa(a,G[k+n>>>0]);f+=l}J[e>>2>>>0]=f;return 0},c:function(){return V},ja:W,ea:$a,fa:ab,J:bb,e:cb,N:db,O:eb,j:fb,o:gb,p:hb,M:ib,r:jb,v:kb,K:lb,D:mb,X:nb,V:ob,U:pb,Z:qb,W:rb,Y:sb,T:tb,f:ub,q:vb,h:wb,da:xb,l:yb,t:zb,u:Ab,x:Bb,z:Cb,ga:Db,A:Eb,C:Fb,aa:Gb,_:Hb,$:Ib,n:function(a){return a},F:function(a){V=a},ha:Wa,y:function(a,b,c,e){return Wa(a,b,c,e)}};
|
|
(function(){function a(f){d.asm=f.exports;ma=d.asm.Ka;ta();ua=d.asm.ib;wa.unshift(d.asm.La);K--;d.monitorRunDependencies&&d.monitorRunDependencies(K);0==K&&(null!==Aa&&(clearInterval(Aa),Aa=null),L&&(f=L,L=null,f()))}function b(f){a(f.instance)}function c(f){return Ea().then(function(h){return WebAssembly.instantiate(h,e)}).then(function(h){return h}).then(f,function(h){z("failed to asynchronously prepare wasm: "+h);B(h)})}var e={a:Jb};K++;d.monitorRunDependencies&&d.monitorRunDependencies(K);if(d.instantiateWasm)try{return d.instantiateWasm(e,
|
|
a)}catch(f){return z("Module.instantiateWasm callback failed with error: "+f),!1}(function(){return A||"function"!=typeof WebAssembly.instantiateStreaming||Ba()||N.startsWith("file://")||p||"function"!=typeof fetch?c(b):fetch(N,{credentials:"same-origin"}).then(function(f){return WebAssembly.instantiateStreaming(f,e).then(b,function(h){z("wasm streaming compile failed: "+h);z("falling back to ArrayBuffer instantiation");return c(b)})})})().catch(ba);return{}})();
|
|
d.___wasm_call_ctors=function(){return(d.___wasm_call_ctors=d.asm.La).apply(null,arguments)};d._OrtInit=function(){return(d._OrtInit=d.asm.Ma).apply(null,arguments)};d._OrtCreateSessionOptions=function(){return(d._OrtCreateSessionOptions=d.asm.Na).apply(null,arguments)};d._OrtAppendExecutionProvider=function(){return(d._OrtAppendExecutionProvider=d.asm.Oa).apply(null,arguments)};d._OrtAddSessionConfigEntry=function(){return(d._OrtAddSessionConfigEntry=d.asm.Pa).apply(null,arguments)};
|
|
d._OrtReleaseSessionOptions=function(){return(d._OrtReleaseSessionOptions=d.asm.Qa).apply(null,arguments)};d._OrtCreateSession=function(){return(d._OrtCreateSession=d.asm.Ra).apply(null,arguments)};d._OrtReleaseSession=function(){return(d._OrtReleaseSession=d.asm.Sa).apply(null,arguments)};d._OrtGetInputCount=function(){return(d._OrtGetInputCount=d.asm.Ta).apply(null,arguments)};d._OrtGetOutputCount=function(){return(d._OrtGetOutputCount=d.asm.Ua).apply(null,arguments)};
|
|
d._OrtGetInputName=function(){return(d._OrtGetInputName=d.asm.Va).apply(null,arguments)};d._OrtGetOutputName=function(){return(d._OrtGetOutputName=d.asm.Wa).apply(null,arguments)};d._OrtFree=function(){return(d._OrtFree=d.asm.Xa).apply(null,arguments)};d._OrtCreateTensor=function(){return(d._OrtCreateTensor=d.asm.Ya).apply(null,arguments)};d._OrtGetTensorData=function(){return(d._OrtGetTensorData=d.asm.Za).apply(null,arguments)};
|
|
d._OrtReleaseTensor=function(){return(d._OrtReleaseTensor=d.asm._a).apply(null,arguments)};d._OrtCreateRunOptions=function(){return(d._OrtCreateRunOptions=d.asm.$a).apply(null,arguments)};d._OrtAddRunConfigEntry=function(){return(d._OrtAddRunConfigEntry=d.asm.ab).apply(null,arguments)};d._OrtReleaseRunOptions=function(){return(d._OrtReleaseRunOptions=d.asm.bb).apply(null,arguments)};d._OrtRun=function(){return(d._OrtRun=d.asm.cb).apply(null,arguments)};
|
|
d._OrtEndProfiling=function(){return(d._OrtEndProfiling=d.asm.db).apply(null,arguments)};
|
|
var Ja=d._malloc=function(){return(Ja=d._malloc=d.asm.eb).apply(null,arguments)},Ha=d._free=function(){return(Ha=d._free=d.asm.fb).apply(null,arguments)},Za=d._fflush=function(){return(Za=d._fflush=d.asm.gb).apply(null,arguments)},Ya=d.___funcs_on_exit=function(){return(Ya=d.___funcs_on_exit=d.asm.hb).apply(null,arguments)},X=d._setThrew=function(){return(X=d._setThrew=d.asm.jb).apply(null,arguments)},Y=d.stackSave=function(){return(Y=d.stackSave=d.asm.kb).apply(null,arguments)},Z=d.stackRestore=
|
|
function(){return(Z=d.stackRestore=d.asm.lb).apply(null,arguments)},Kb=d.stackAlloc=function(){return(Kb=d.stackAlloc=d.asm.mb).apply(null,arguments)},Xa=d.___cxa_can_catch=function(){return(Xa=d.___cxa_can_catch=d.asm.nb).apply(null,arguments)},Fa=d.___cxa_is_pointer_type=function(){return(Fa=d.___cxa_is_pointer_type=d.asm.ob).apply(null,arguments)},Lb=d.dynCall_j=function(){return(Lb=d.dynCall_j=d.asm.pb).apply(null,arguments)},Mb=d.dynCall_iiiiij=function(){return(Mb=d.dynCall_iiiiij=d.asm.qb).apply(null,
|
|
arguments)},Nb=d.dynCall_jii=function(){return(Nb=d.dynCall_jii=d.asm.rb).apply(null,arguments)},Ob=d.dynCall_viiiiij=function(){return(Ob=d.dynCall_viiiiij=d.asm.sb).apply(null,arguments)},Pb=d.dynCall_vjji=function(){return(Pb=d.dynCall_vjji=d.asm.tb).apply(null,arguments)},Qb=d.dynCall_viiijjjii=function(){return(Qb=d.dynCall_viiijjjii=d.asm.ub).apply(null,arguments)},Rb=d.dynCall_iij=function(){return(Rb=d.dynCall_iij=d.asm.vb).apply(null,arguments)},Sb=d.dynCall_ji=function(){return(Sb=d.dynCall_ji=
|
|
d.asm.wb).apply(null,arguments)},Tb=d.dynCall_iiiiiij=function(){return(Tb=d.dynCall_iiiiiij=d.asm.xb).apply(null,arguments)},Ub=d.dynCall_iiij=function(){return(Ub=d.dynCall_iiij=d.asm.yb).apply(null,arguments)};function cb(a,b){var c=Y();try{return U(a)(b)}catch(e){Z(c);if(e!==e+0)throw e;X(1,0)}}function vb(a,b){var c=Y();try{U(a)(b)}catch(e){Z(c);if(e!==e+0)throw e;X(1,0)}}function wb(a,b,c){var e=Y();try{U(a)(b,c)}catch(f){Z(e);if(f!==f+0)throw f;X(1,0)}}
|
|
function fb(a,b,c){var e=Y();try{return U(a)(b,c)}catch(f){Z(e);if(f!==f+0)throw f;X(1,0)}}function gb(a,b,c,e){var f=Y();try{return U(a)(b,c,e)}catch(h){Z(f);if(h!==h+0)throw h;X(1,0)}}function kb(a,b,c,e,f,h,k){var l=Y();try{return U(a)(b,c,e,f,h,k)}catch(n){Z(l);if(n!==n+0)throw n;X(1,0)}}function ub(a){var b=Y();try{U(a)()}catch(c){Z(b);if(c!==c+0)throw c;X(1,0)}}function jb(a,b,c,e,f,h){var k=Y();try{return U(a)(b,c,e,f,h)}catch(l){Z(k);if(l!==l+0)throw l;X(1,0)}}
|
|
function hb(a,b,c,e,f){var h=Y();try{return U(a)(b,c,e,f)}catch(k){Z(h);if(k!==k+0)throw k;X(1,0)}}function yb(a,b,c,e){var f=Y();try{U(a)(b,c,e)}catch(h){Z(f);if(h!==h+0)throw h;X(1,0)}}function Ab(a,b,c,e,f,h){var k=Y();try{U(a)(b,c,e,f,h)}catch(l){Z(k);if(l!==l+0)throw l;X(1,0)}}function zb(a,b,c,e,f){var h=Y();try{U(a)(b,c,e,f)}catch(k){Z(h);if(k!==k+0)throw k;X(1,0)}}function Bb(a,b,c,e,f,h,k){var l=Y();try{U(a)(b,c,e,f,h,k)}catch(n){Z(l);if(n!==n+0)throw n;X(1,0)}}
|
|
function Cb(a,b,c,e,f,h,k,l){var n=Y();try{U(a)(b,c,e,f,h,k,l)}catch(t){Z(n);if(t!==t+0)throw t;X(1,0)}}function eb(a,b,c){var e=Y();try{return U(a)(b,c)}catch(f){Z(e);if(f!==f+0)throw f;X(1,0)}}function db(a,b,c){var e=Y();try{return U(a)(b,c)}catch(f){Z(e);if(f!==f+0)throw f;X(1,0)}}function Db(a,b,c,e,f,h,k,l,n){var t=Y();try{U(a)(b,c,e,f,h,k,l,n)}catch(x){Z(t);if(x!==x+0)throw x;X(1,0)}}function ib(a,b,c,e,f,h){var k=Y();try{return U(a)(b,c,e,f,h)}catch(l){Z(k);if(l!==l+0)throw l;X(1,0)}}
|
|
function lb(a,b,c,e,f,h,k,l){var n=Y();try{return U(a)(b,c,e,f,h,k,l)}catch(t){Z(n);if(t!==t+0)throw t;X(1,0)}}function mb(a,b,c,e,f,h,k,l,n,t,x,E){var C=Y();try{return U(a)(b,c,e,f,h,k,l,n,t,x,E)}catch(g){Z(C);if(g!==g+0)throw g;X(1,0)}}function Eb(a,b,c,e,f,h,k,l,n,t,x){var E=Y();try{U(a)(b,c,e,f,h,k,l,n,t,x)}catch(C){Z(E);if(C!==C+0)throw C;X(1,0)}}function Fb(a,b,c,e,f,h,k,l,n,t,x,E,C,g,u,w){var F=Y();try{U(a)(b,c,e,f,h,k,l,n,t,x,E,C,g,u,w)}catch(M){Z(F);if(M!==M+0)throw M;X(1,0)}}
|
|
function bb(a){var b=Y();try{return U(a)()}catch(c){Z(b);if(c!==c+0)throw c;X(1,0)}}function ab(a,b,c){var e=Y();try{return U(a)(b,c)}catch(f){Z(e);if(f!==f+0)throw f;X(1,0)}}function $a(a,b,c){var e=Y();try{return U(a)(b,c)}catch(f){Z(e);if(f!==f+0)throw f;X(1,0)}}function xb(a,b,c,e){var f=Y();try{U(a)(b,c,e)}catch(h){Z(f);if(h!==h+0)throw h;X(1,0)}}function Gb(a,b,c,e,f,h,k,l){var n=Y();try{Ob(a,b,c,e,f,h,k,l)}catch(t){Z(n);if(t!==t+0)throw t;X(1,0)}}
|
|
function Ib(a,b,c,e,f,h){var k=Y();try{Pb(a,b,c,e,f,h)}catch(l){Z(k);if(l!==l+0)throw l;X(1,0)}}function Hb(a,b,c,e,f,h,k,l,n,t,x,E){var C=Y();try{Qb(a,b,c,e,f,h,k,l,n,t,x,E)}catch(g){Z(C);if(g!==g+0)throw g;X(1,0)}}function qb(a,b,c,e){var f=Y();try{return Rb(a,b,c,e)}catch(h){Z(f);if(h!==h+0)throw h;X(1,0)}}function sb(a,b){var c=Y();try{return Sb(a,b)}catch(e){Z(c);if(e!==e+0)throw e;X(1,0)}}
|
|
function nb(a,b,c,e,f,h,k,l){var n=Y();try{return Tb(a,b,c,e,f,h,k,l)}catch(t){Z(n);if(t!==t+0)throw t;X(1,0)}}function rb(a){var b=Y();try{return Lb(a)}catch(c){Z(b);if(c!==c+0)throw c;X(1,0)}}function ob(a,b,c,e,f,h,k){var l=Y();try{return Mb(a,b,c,e,f,h,k)}catch(n){Z(l);if(n!==n+0)throw n;X(1,0)}}function pb(a,b,c,e,f){var h=Y();try{return Ub(a,b,c,e,f)}catch(k){Z(h);if(k!==k+0)throw k;X(1,0)}}function tb(a,b,c){var e=Y();try{return Nb(a,b,c)}catch(f){Z(e);if(f!==f+0)throw f;X(1,0)}}
|
|
d.UTF8ToString=pa;d.stringToUTF8=function(a,b,c){return qa(a,G,b,c)};d.lengthBytesUTF8=ra;d.stackSave=Y;d.stackRestore=Z;d.stackAlloc=Kb;var Vb;L=function Wb(){Vb||Xb();Vb||(L=Wb)};
|
|
function Xb(){function a(){if(!Vb&&(Vb=!0,d.calledRun=!0,!D)){O(wa);aa(d);if(d.onRuntimeInitialized)d.onRuntimeInitialized();if(d.postRun)for("function"==typeof d.postRun&&(d.postRun=[d.postRun]);d.postRun.length;){var b=d.postRun.shift();ya.unshift(b)}O(ya)}}if(!(0<K)){if(d.preRun)for("function"==typeof d.preRun&&(d.preRun=[d.preRun]);d.preRun.length;)za();O(va);0<K||(d.setStatus?(d.setStatus("Running..."),setTimeout(function(){setTimeout(function(){d.setStatus("")},1);a()},1)):a())}}
|
|
if(d.preInit)for("function"==typeof d.preInit&&(d.preInit=[d.preInit]);0<d.preInit.length;)d.preInit.pop()();Xb();
|
|
|
|
|
|
return ortWasm.ready
|
|
}
|
|
);
|
|
})();
|
|
if (true)
|
|
module.exports = ortWasm;
|
|
else {}
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/@protobufjs/aspromise/index.js":
|
|
/*!*****************************************************!*\
|
|
!*** ./node_modules/@protobufjs/aspromise/index.js ***!
|
|
\*****************************************************/
|
|
/***/ ((module) => {
|
|
|
|
"use strict";
|
|
|
|
module.exports = asPromise;
|
|
|
|
/**
|
|
* Callback as used by {@link util.asPromise}.
|
|
* @typedef asPromiseCallback
|
|
* @type {function}
|
|
* @param {Error|null} error Error, if any
|
|
* @param {...*} params Additional arguments
|
|
* @returns {undefined}
|
|
*/
|
|
|
|
/**
|
|
* Returns a promise from a node-style callback function.
|
|
* @memberof util
|
|
* @param {asPromiseCallback} fn Function to call
|
|
* @param {*} ctx Function context
|
|
* @param {...*} params Function arguments
|
|
* @returns {Promise<*>} Promisified function
|
|
*/
|
|
function asPromise(fn, ctx/*, varargs */) {
|
|
var params = new Array(arguments.length - 1),
|
|
offset = 0,
|
|
index = 2,
|
|
pending = true;
|
|
while (index < arguments.length)
|
|
params[offset++] = arguments[index++];
|
|
return new Promise(function executor(resolve, reject) {
|
|
params[offset] = function callback(err/*, varargs */) {
|
|
if (pending) {
|
|
pending = false;
|
|
if (err)
|
|
reject(err);
|
|
else {
|
|
var params = new Array(arguments.length - 1),
|
|
offset = 0;
|
|
while (offset < params.length)
|
|
params[offset++] = arguments[offset];
|
|
resolve.apply(null, params);
|
|
}
|
|
}
|
|
};
|
|
try {
|
|
fn.apply(ctx || null, params);
|
|
} catch (err) {
|
|
if (pending) {
|
|
pending = false;
|
|
reject(err);
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/@protobufjs/base64/index.js":
|
|
/*!**************************************************!*\
|
|
!*** ./node_modules/@protobufjs/base64/index.js ***!
|
|
\**************************************************/
|
|
/***/ ((__unused_webpack_module, exports) => {
|
|
|
|
"use strict";
|
|
|
|
|
|
/**
|
|
* A minimal base64 implementation for number arrays.
|
|
* @memberof util
|
|
* @namespace
|
|
*/
|
|
var base64 = exports;
|
|
|
|
/**
|
|
* Calculates the byte length of a base64 encoded string.
|
|
* @param {string} string Base64 encoded string
|
|
* @returns {number} Byte length
|
|
*/
|
|
base64.length = function length(string) {
|
|
var p = string.length;
|
|
if (!p)
|
|
return 0;
|
|
var n = 0;
|
|
while (--p % 4 > 1 && string.charAt(p) === "=")
|
|
++n;
|
|
return Math.ceil(string.length * 3) / 4 - n;
|
|
};
|
|
|
|
// Base64 encoding table
|
|
var b64 = new Array(64);
|
|
|
|
// Base64 decoding table
|
|
var s64 = new Array(123);
|
|
|
|
// 65..90, 97..122, 48..57, 43, 47
|
|
for (var i = 0; i < 64;)
|
|
s64[b64[i] = i < 26 ? i + 65 : i < 52 ? i + 71 : i < 62 ? i - 4 : i - 59 | 43] = i++;
|
|
|
|
/**
|
|
* Encodes a buffer to a base64 encoded string.
|
|
* @param {Uint8Array} buffer Source buffer
|
|
* @param {number} start Source start
|
|
* @param {number} end Source end
|
|
* @returns {string} Base64 encoded string
|
|
*/
|
|
base64.encode = function encode(buffer, start, end) {
|
|
var parts = null,
|
|
chunk = [];
|
|
var i = 0, // output index
|
|
j = 0, // goto index
|
|
t; // temporary
|
|
while (start < end) {
|
|
var b = buffer[start++];
|
|
switch (j) {
|
|
case 0:
|
|
chunk[i++] = b64[b >> 2];
|
|
t = (b & 3) << 4;
|
|
j = 1;
|
|
break;
|
|
case 1:
|
|
chunk[i++] = b64[t | b >> 4];
|
|
t = (b & 15) << 2;
|
|
j = 2;
|
|
break;
|
|
case 2:
|
|
chunk[i++] = b64[t | b >> 6];
|
|
chunk[i++] = b64[b & 63];
|
|
j = 0;
|
|
break;
|
|
}
|
|
if (i > 8191) {
|
|
(parts || (parts = [])).push(String.fromCharCode.apply(String, chunk));
|
|
i = 0;
|
|
}
|
|
}
|
|
if (j) {
|
|
chunk[i++] = b64[t];
|
|
chunk[i++] = 61;
|
|
if (j === 1)
|
|
chunk[i++] = 61;
|
|
}
|
|
if (parts) {
|
|
if (i)
|
|
parts.push(String.fromCharCode.apply(String, chunk.slice(0, i)));
|
|
return parts.join("");
|
|
}
|
|
return String.fromCharCode.apply(String, chunk.slice(0, i));
|
|
};
|
|
|
|
var invalidEncoding = "invalid encoding";
|
|
|
|
/**
|
|
* Decodes a base64 encoded string to a buffer.
|
|
* @param {string} string Source string
|
|
* @param {Uint8Array} buffer Destination buffer
|
|
* @param {number} offset Destination offset
|
|
* @returns {number} Number of bytes written
|
|
* @throws {Error} If encoding is invalid
|
|
*/
|
|
base64.decode = function decode(string, buffer, offset) {
|
|
var start = offset;
|
|
var j = 0, // goto index
|
|
t; // temporary
|
|
for (var i = 0; i < string.length;) {
|
|
var c = string.charCodeAt(i++);
|
|
if (c === 61 && j > 1)
|
|
break;
|
|
if ((c = s64[c]) === undefined)
|
|
throw Error(invalidEncoding);
|
|
switch (j) {
|
|
case 0:
|
|
t = c;
|
|
j = 1;
|
|
break;
|
|
case 1:
|
|
buffer[offset++] = t << 2 | (c & 48) >> 4;
|
|
t = c;
|
|
j = 2;
|
|
break;
|
|
case 2:
|
|
buffer[offset++] = (t & 15) << 4 | (c & 60) >> 2;
|
|
t = c;
|
|
j = 3;
|
|
break;
|
|
case 3:
|
|
buffer[offset++] = (t & 3) << 6 | c;
|
|
j = 0;
|
|
break;
|
|
}
|
|
}
|
|
if (j === 1)
|
|
throw Error(invalidEncoding);
|
|
return offset - start;
|
|
};
|
|
|
|
/**
|
|
* Tests if the specified string appears to be base64 encoded.
|
|
* @param {string} string String to test
|
|
* @returns {boolean} `true` if probably base64 encoded, otherwise false
|
|
*/
|
|
base64.test = function test(string) {
|
|
return /^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/.test(string);
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/@protobufjs/eventemitter/index.js":
|
|
/*!********************************************************!*\
|
|
!*** ./node_modules/@protobufjs/eventemitter/index.js ***!
|
|
\********************************************************/
|
|
/***/ ((module) => {
|
|
|
|
"use strict";
|
|
|
|
module.exports = EventEmitter;
|
|
|
|
/**
|
|
* Constructs a new event emitter instance.
|
|
* @classdesc A minimal event emitter.
|
|
* @memberof util
|
|
* @constructor
|
|
*/
|
|
function EventEmitter() {
|
|
|
|
/**
|
|
* Registered listeners.
|
|
* @type {Object.<string,*>}
|
|
* @private
|
|
*/
|
|
this._listeners = {};
|
|
}
|
|
|
|
/**
|
|
* Registers an event listener.
|
|
* @param {string} evt Event name
|
|
* @param {function} fn Listener
|
|
* @param {*} [ctx] Listener context
|
|
* @returns {util.EventEmitter} `this`
|
|
*/
|
|
EventEmitter.prototype.on = function on(evt, fn, ctx) {
|
|
(this._listeners[evt] || (this._listeners[evt] = [])).push({
|
|
fn : fn,
|
|
ctx : ctx || this
|
|
});
|
|
return this;
|
|
};
|
|
|
|
/**
|
|
* Removes an event listener or any matching listeners if arguments are omitted.
|
|
* @param {string} [evt] Event name. Removes all listeners if omitted.
|
|
* @param {function} [fn] Listener to remove. Removes all listeners of `evt` if omitted.
|
|
* @returns {util.EventEmitter} `this`
|
|
*/
|
|
EventEmitter.prototype.off = function off(evt, fn) {
|
|
if (evt === undefined)
|
|
this._listeners = {};
|
|
else {
|
|
if (fn === undefined)
|
|
this._listeners[evt] = [];
|
|
else {
|
|
var listeners = this._listeners[evt];
|
|
for (var i = 0; i < listeners.length;)
|
|
if (listeners[i].fn === fn)
|
|
listeners.splice(i, 1);
|
|
else
|
|
++i;
|
|
}
|
|
}
|
|
return this;
|
|
};
|
|
|
|
/**
|
|
* Emits an event by calling its listeners with the specified arguments.
|
|
* @param {string} evt Event name
|
|
* @param {...*} args Arguments
|
|
* @returns {util.EventEmitter} `this`
|
|
*/
|
|
EventEmitter.prototype.emit = function emit(evt) {
|
|
var listeners = this._listeners[evt];
|
|
if (listeners) {
|
|
var args = [],
|
|
i = 1;
|
|
for (; i < arguments.length;)
|
|
args.push(arguments[i++]);
|
|
for (i = 0; i < listeners.length;)
|
|
listeners[i].fn.apply(listeners[i++].ctx, args);
|
|
}
|
|
return this;
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/@protobufjs/float/index.js":
|
|
/*!*************************************************!*\
|
|
!*** ./node_modules/@protobufjs/float/index.js ***!
|
|
\*************************************************/
|
|
/***/ ((module) => {
|
|
|
|
"use strict";
|
|
|
|
|
|
module.exports = factory(factory);
|
|
|
|
/**
|
|
* Reads / writes floats / doubles from / to buffers.
|
|
* @name util.float
|
|
* @namespace
|
|
*/
|
|
|
|
/**
|
|
* Writes a 32 bit float to a buffer using little endian byte order.
|
|
* @name util.float.writeFloatLE
|
|
* @function
|
|
* @param {number} val Value to write
|
|
* @param {Uint8Array} buf Target buffer
|
|
* @param {number} pos Target buffer offset
|
|
* @returns {undefined}
|
|
*/
|
|
|
|
/**
|
|
* Writes a 32 bit float to a buffer using big endian byte order.
|
|
* @name util.float.writeFloatBE
|
|
* @function
|
|
* @param {number} val Value to write
|
|
* @param {Uint8Array} buf Target buffer
|
|
* @param {number} pos Target buffer offset
|
|
* @returns {undefined}
|
|
*/
|
|
|
|
/**
|
|
* Reads a 32 bit float from a buffer using little endian byte order.
|
|
* @name util.float.readFloatLE
|
|
* @function
|
|
* @param {Uint8Array} buf Source buffer
|
|
* @param {number} pos Source buffer offset
|
|
* @returns {number} Value read
|
|
*/
|
|
|
|
/**
|
|
* Reads a 32 bit float from a buffer using big endian byte order.
|
|
* @name util.float.readFloatBE
|
|
* @function
|
|
* @param {Uint8Array} buf Source buffer
|
|
* @param {number} pos Source buffer offset
|
|
* @returns {number} Value read
|
|
*/
|
|
|
|
/**
|
|
* Writes a 64 bit double to a buffer using little endian byte order.
|
|
* @name util.float.writeDoubleLE
|
|
* @function
|
|
* @param {number} val Value to write
|
|
* @param {Uint8Array} buf Target buffer
|
|
* @param {number} pos Target buffer offset
|
|
* @returns {undefined}
|
|
*/
|
|
|
|
/**
|
|
* Writes a 64 bit double to a buffer using big endian byte order.
|
|
* @name util.float.writeDoubleBE
|
|
* @function
|
|
* @param {number} val Value to write
|
|
* @param {Uint8Array} buf Target buffer
|
|
* @param {number} pos Target buffer offset
|
|
* @returns {undefined}
|
|
*/
|
|
|
|
/**
|
|
* Reads a 64 bit double from a buffer using little endian byte order.
|
|
* @name util.float.readDoubleLE
|
|
* @function
|
|
* @param {Uint8Array} buf Source buffer
|
|
* @param {number} pos Source buffer offset
|
|
* @returns {number} Value read
|
|
*/
|
|
|
|
/**
|
|
* Reads a 64 bit double from a buffer using big endian byte order.
|
|
* @name util.float.readDoubleBE
|
|
* @function
|
|
* @param {Uint8Array} buf Source buffer
|
|
* @param {number} pos Source buffer offset
|
|
* @returns {number} Value read
|
|
*/
|
|
|
|
// Factory function for the purpose of node-based testing in modified global environments
|
|
function factory(exports) {
|
|
|
|
// float: typed array
|
|
if (typeof Float32Array !== "undefined") (function() {
|
|
|
|
var f32 = new Float32Array([ -0 ]),
|
|
f8b = new Uint8Array(f32.buffer),
|
|
le = f8b[3] === 128;
|
|
|
|
function writeFloat_f32_cpy(val, buf, pos) {
|
|
f32[0] = val;
|
|
buf[pos ] = f8b[0];
|
|
buf[pos + 1] = f8b[1];
|
|
buf[pos + 2] = f8b[2];
|
|
buf[pos + 3] = f8b[3];
|
|
}
|
|
|
|
function writeFloat_f32_rev(val, buf, pos) {
|
|
f32[0] = val;
|
|
buf[pos ] = f8b[3];
|
|
buf[pos + 1] = f8b[2];
|
|
buf[pos + 2] = f8b[1];
|
|
buf[pos + 3] = f8b[0];
|
|
}
|
|
|
|
/* istanbul ignore next */
|
|
exports.writeFloatLE = le ? writeFloat_f32_cpy : writeFloat_f32_rev;
|
|
/* istanbul ignore next */
|
|
exports.writeFloatBE = le ? writeFloat_f32_rev : writeFloat_f32_cpy;
|
|
|
|
function readFloat_f32_cpy(buf, pos) {
|
|
f8b[0] = buf[pos ];
|
|
f8b[1] = buf[pos + 1];
|
|
f8b[2] = buf[pos + 2];
|
|
f8b[3] = buf[pos + 3];
|
|
return f32[0];
|
|
}
|
|
|
|
function readFloat_f32_rev(buf, pos) {
|
|
f8b[3] = buf[pos ];
|
|
f8b[2] = buf[pos + 1];
|
|
f8b[1] = buf[pos + 2];
|
|
f8b[0] = buf[pos + 3];
|
|
return f32[0];
|
|
}
|
|
|
|
/* istanbul ignore next */
|
|
exports.readFloatLE = le ? readFloat_f32_cpy : readFloat_f32_rev;
|
|
/* istanbul ignore next */
|
|
exports.readFloatBE = le ? readFloat_f32_rev : readFloat_f32_cpy;
|
|
|
|
// float: ieee754
|
|
})(); else (function() {
|
|
|
|
function writeFloat_ieee754(writeUint, val, buf, pos) {
|
|
var sign = val < 0 ? 1 : 0;
|
|
if (sign)
|
|
val = -val;
|
|
if (val === 0)
|
|
writeUint(1 / val > 0 ? /* positive */ 0 : /* negative 0 */ 2147483648, buf, pos);
|
|
else if (isNaN(val))
|
|
writeUint(2143289344, buf, pos);
|
|
else if (val > 3.4028234663852886e+38) // +-Infinity
|
|
writeUint((sign << 31 | 2139095040) >>> 0, buf, pos);
|
|
else if (val < 1.1754943508222875e-38) // denormal
|
|
writeUint((sign << 31 | Math.round(val / 1.401298464324817e-45)) >>> 0, buf, pos);
|
|
else {
|
|
var exponent = Math.floor(Math.log(val) / Math.LN2),
|
|
mantissa = Math.round(val * Math.pow(2, -exponent) * 8388608) & 8388607;
|
|
writeUint((sign << 31 | exponent + 127 << 23 | mantissa) >>> 0, buf, pos);
|
|
}
|
|
}
|
|
|
|
exports.writeFloatLE = writeFloat_ieee754.bind(null, writeUintLE);
|
|
exports.writeFloatBE = writeFloat_ieee754.bind(null, writeUintBE);
|
|
|
|
function readFloat_ieee754(readUint, buf, pos) {
|
|
var uint = readUint(buf, pos),
|
|
sign = (uint >> 31) * 2 + 1,
|
|
exponent = uint >>> 23 & 255,
|
|
mantissa = uint & 8388607;
|
|
return exponent === 255
|
|
? mantissa
|
|
? NaN
|
|
: sign * Infinity
|
|
: exponent === 0 // denormal
|
|
? sign * 1.401298464324817e-45 * mantissa
|
|
: sign * Math.pow(2, exponent - 150) * (mantissa + 8388608);
|
|
}
|
|
|
|
exports.readFloatLE = readFloat_ieee754.bind(null, readUintLE);
|
|
exports.readFloatBE = readFloat_ieee754.bind(null, readUintBE);
|
|
|
|
})();
|
|
|
|
// double: typed array
|
|
if (typeof Float64Array !== "undefined") (function() {
|
|
|
|
var f64 = new Float64Array([-0]),
|
|
f8b = new Uint8Array(f64.buffer),
|
|
le = f8b[7] === 128;
|
|
|
|
function writeDouble_f64_cpy(val, buf, pos) {
|
|
f64[0] = val;
|
|
buf[pos ] = f8b[0];
|
|
buf[pos + 1] = f8b[1];
|
|
buf[pos + 2] = f8b[2];
|
|
buf[pos + 3] = f8b[3];
|
|
buf[pos + 4] = f8b[4];
|
|
buf[pos + 5] = f8b[5];
|
|
buf[pos + 6] = f8b[6];
|
|
buf[pos + 7] = f8b[7];
|
|
}
|
|
|
|
function writeDouble_f64_rev(val, buf, pos) {
|
|
f64[0] = val;
|
|
buf[pos ] = f8b[7];
|
|
buf[pos + 1] = f8b[6];
|
|
buf[pos + 2] = f8b[5];
|
|
buf[pos + 3] = f8b[4];
|
|
buf[pos + 4] = f8b[3];
|
|
buf[pos + 5] = f8b[2];
|
|
buf[pos + 6] = f8b[1];
|
|
buf[pos + 7] = f8b[0];
|
|
}
|
|
|
|
/* istanbul ignore next */
|
|
exports.writeDoubleLE = le ? writeDouble_f64_cpy : writeDouble_f64_rev;
|
|
/* istanbul ignore next */
|
|
exports.writeDoubleBE = le ? writeDouble_f64_rev : writeDouble_f64_cpy;
|
|
|
|
function readDouble_f64_cpy(buf, pos) {
|
|
f8b[0] = buf[pos ];
|
|
f8b[1] = buf[pos + 1];
|
|
f8b[2] = buf[pos + 2];
|
|
f8b[3] = buf[pos + 3];
|
|
f8b[4] = buf[pos + 4];
|
|
f8b[5] = buf[pos + 5];
|
|
f8b[6] = buf[pos + 6];
|
|
f8b[7] = buf[pos + 7];
|
|
return f64[0];
|
|
}
|
|
|
|
function readDouble_f64_rev(buf, pos) {
|
|
f8b[7] = buf[pos ];
|
|
f8b[6] = buf[pos + 1];
|
|
f8b[5] = buf[pos + 2];
|
|
f8b[4] = buf[pos + 3];
|
|
f8b[3] = buf[pos + 4];
|
|
f8b[2] = buf[pos + 5];
|
|
f8b[1] = buf[pos + 6];
|
|
f8b[0] = buf[pos + 7];
|
|
return f64[0];
|
|
}
|
|
|
|
/* istanbul ignore next */
|
|
exports.readDoubleLE = le ? readDouble_f64_cpy : readDouble_f64_rev;
|
|
/* istanbul ignore next */
|
|
exports.readDoubleBE = le ? readDouble_f64_rev : readDouble_f64_cpy;
|
|
|
|
// double: ieee754
|
|
})(); else (function() {
|
|
|
|
function writeDouble_ieee754(writeUint, off0, off1, val, buf, pos) {
|
|
var sign = val < 0 ? 1 : 0;
|
|
if (sign)
|
|
val = -val;
|
|
if (val === 0) {
|
|
writeUint(0, buf, pos + off0);
|
|
writeUint(1 / val > 0 ? /* positive */ 0 : /* negative 0 */ 2147483648, buf, pos + off1);
|
|
} else if (isNaN(val)) {
|
|
writeUint(0, buf, pos + off0);
|
|
writeUint(2146959360, buf, pos + off1);
|
|
} else if (val > 1.7976931348623157e+308) { // +-Infinity
|
|
writeUint(0, buf, pos + off0);
|
|
writeUint((sign << 31 | 2146435072) >>> 0, buf, pos + off1);
|
|
} else {
|
|
var mantissa;
|
|
if (val < 2.2250738585072014e-308) { // denormal
|
|
mantissa = val / 5e-324;
|
|
writeUint(mantissa >>> 0, buf, pos + off0);
|
|
writeUint((sign << 31 | mantissa / 4294967296) >>> 0, buf, pos + off1);
|
|
} else {
|
|
var exponent = Math.floor(Math.log(val) / Math.LN2);
|
|
if (exponent === 1024)
|
|
exponent = 1023;
|
|
mantissa = val * Math.pow(2, -exponent);
|
|
writeUint(mantissa * 4503599627370496 >>> 0, buf, pos + off0);
|
|
writeUint((sign << 31 | exponent + 1023 << 20 | mantissa * 1048576 & 1048575) >>> 0, buf, pos + off1);
|
|
}
|
|
}
|
|
}
|
|
|
|
exports.writeDoubleLE = writeDouble_ieee754.bind(null, writeUintLE, 0, 4);
|
|
exports.writeDoubleBE = writeDouble_ieee754.bind(null, writeUintBE, 4, 0);
|
|
|
|
function readDouble_ieee754(readUint, off0, off1, buf, pos) {
|
|
var lo = readUint(buf, pos + off0),
|
|
hi = readUint(buf, pos + off1);
|
|
var sign = (hi >> 31) * 2 + 1,
|
|
exponent = hi >>> 20 & 2047,
|
|
mantissa = 4294967296 * (hi & 1048575) + lo;
|
|
return exponent === 2047
|
|
? mantissa
|
|
? NaN
|
|
: sign * Infinity
|
|
: exponent === 0 // denormal
|
|
? sign * 5e-324 * mantissa
|
|
: sign * Math.pow(2, exponent - 1075) * (mantissa + 4503599627370496);
|
|
}
|
|
|
|
exports.readDoubleLE = readDouble_ieee754.bind(null, readUintLE, 0, 4);
|
|
exports.readDoubleBE = readDouble_ieee754.bind(null, readUintBE, 4, 0);
|
|
|
|
})();
|
|
|
|
return exports;
|
|
}
|
|
|
|
// uint helpers
|
|
|
|
function writeUintLE(val, buf, pos) {
|
|
buf[pos ] = val & 255;
|
|
buf[pos + 1] = val >>> 8 & 255;
|
|
buf[pos + 2] = val >>> 16 & 255;
|
|
buf[pos + 3] = val >>> 24;
|
|
}
|
|
|
|
function writeUintBE(val, buf, pos) {
|
|
buf[pos ] = val >>> 24;
|
|
buf[pos + 1] = val >>> 16 & 255;
|
|
buf[pos + 2] = val >>> 8 & 255;
|
|
buf[pos + 3] = val & 255;
|
|
}
|
|
|
|
function readUintLE(buf, pos) {
|
|
return (buf[pos ]
|
|
| buf[pos + 1] << 8
|
|
| buf[pos + 2] << 16
|
|
| buf[pos + 3] << 24) >>> 0;
|
|
}
|
|
|
|
function readUintBE(buf, pos) {
|
|
return (buf[pos ] << 24
|
|
| buf[pos + 1] << 16
|
|
| buf[pos + 2] << 8
|
|
| buf[pos + 3]) >>> 0;
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/@protobufjs/inquire/index.js":
|
|
/*!***************************************************!*\
|
|
!*** ./node_modules/@protobufjs/inquire/index.js ***!
|
|
\***************************************************/
|
|
/***/ ((module) => {
|
|
|
|
"use strict";
|
|
|
|
module.exports = inquire;
|
|
|
|
/**
|
|
* Requires a module only if available.
|
|
* @memberof util
|
|
* @param {string} moduleName Module to require
|
|
* @returns {?Object} Required module if available and not empty, otherwise `null`
|
|
*/
|
|
function inquire(moduleName) {
|
|
return null;
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/@protobufjs/pool/index.js":
|
|
/*!************************************************!*\
|
|
!*** ./node_modules/@protobufjs/pool/index.js ***!
|
|
\************************************************/
|
|
/***/ ((module) => {
|
|
|
|
"use strict";
|
|
|
|
module.exports = pool;
|
|
|
|
/**
|
|
* An allocator as used by {@link util.pool}.
|
|
* @typedef PoolAllocator
|
|
* @type {function}
|
|
* @param {number} size Buffer size
|
|
* @returns {Uint8Array} Buffer
|
|
*/
|
|
|
|
/**
|
|
* A slicer as used by {@link util.pool}.
|
|
* @typedef PoolSlicer
|
|
* @type {function}
|
|
* @param {number} start Start offset
|
|
* @param {number} end End offset
|
|
* @returns {Uint8Array} Buffer slice
|
|
* @this {Uint8Array}
|
|
*/
|
|
|
|
/**
|
|
* A general purpose buffer pool.
|
|
* @memberof util
|
|
* @function
|
|
* @param {PoolAllocator} alloc Allocator
|
|
* @param {PoolSlicer} slice Slicer
|
|
* @param {number} [size=8192] Slab size
|
|
* @returns {PoolAllocator} Pooled allocator
|
|
*/
|
|
function pool(alloc, slice, size) {
|
|
var SIZE = size || 8192;
|
|
var MAX = SIZE >>> 1;
|
|
var slab = null;
|
|
var offset = SIZE;
|
|
return function pool_alloc(size) {
|
|
if (size < 1 || size > MAX)
|
|
return alloc(size);
|
|
if (offset + size > SIZE) {
|
|
slab = alloc(SIZE);
|
|
offset = 0;
|
|
}
|
|
var buf = slice.call(slab, offset, offset += size);
|
|
if (offset & 7) // align to 32 bit
|
|
offset = (offset | 7) + 1;
|
|
return buf;
|
|
};
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/@protobufjs/utf8/index.js":
|
|
/*!************************************************!*\
|
|
!*** ./node_modules/@protobufjs/utf8/index.js ***!
|
|
\************************************************/
|
|
/***/ ((__unused_webpack_module, exports) => {
|
|
|
|
"use strict";
|
|
|
|
|
|
/**
|
|
* A minimal UTF8 implementation for number arrays.
|
|
* @memberof util
|
|
* @namespace
|
|
*/
|
|
var utf8 = exports;
|
|
|
|
/**
|
|
* Calculates the UTF8 byte length of a string.
|
|
* @param {string} string String
|
|
* @returns {number} Byte length
|
|
*/
|
|
utf8.length = function utf8_length(string) {
|
|
var len = 0,
|
|
c = 0;
|
|
for (var i = 0; i < string.length; ++i) {
|
|
c = string.charCodeAt(i);
|
|
if (c < 128)
|
|
len += 1;
|
|
else if (c < 2048)
|
|
len += 2;
|
|
else if ((c & 0xFC00) === 0xD800 && (string.charCodeAt(i + 1) & 0xFC00) === 0xDC00) {
|
|
++i;
|
|
len += 4;
|
|
} else
|
|
len += 3;
|
|
}
|
|
return len;
|
|
};
|
|
|
|
/**
|
|
* Reads UTF8 bytes as a string.
|
|
* @param {Uint8Array} buffer Source buffer
|
|
* @param {number} start Source start
|
|
* @param {number} end Source end
|
|
* @returns {string} String read
|
|
*/
|
|
utf8.read = function utf8_read(buffer, start, end) {
|
|
var len = end - start;
|
|
if (len < 1)
|
|
return "";
|
|
var parts = null,
|
|
chunk = [],
|
|
i = 0, // char offset
|
|
t; // temporary
|
|
while (start < end) {
|
|
t = buffer[start++];
|
|
if (t < 128)
|
|
chunk[i++] = t;
|
|
else if (t > 191 && t < 224)
|
|
chunk[i++] = (t & 31) << 6 | buffer[start++] & 63;
|
|
else if (t > 239 && t < 365) {
|
|
t = ((t & 7) << 18 | (buffer[start++] & 63) << 12 | (buffer[start++] & 63) << 6 | buffer[start++] & 63) - 0x10000;
|
|
chunk[i++] = 0xD800 + (t >> 10);
|
|
chunk[i++] = 0xDC00 + (t & 1023);
|
|
} else
|
|
chunk[i++] = (t & 15) << 12 | (buffer[start++] & 63) << 6 | buffer[start++] & 63;
|
|
if (i > 8191) {
|
|
(parts || (parts = [])).push(String.fromCharCode.apply(String, chunk));
|
|
i = 0;
|
|
}
|
|
}
|
|
if (parts) {
|
|
if (i)
|
|
parts.push(String.fromCharCode.apply(String, chunk.slice(0, i)));
|
|
return parts.join("");
|
|
}
|
|
return String.fromCharCode.apply(String, chunk.slice(0, i));
|
|
};
|
|
|
|
/**
|
|
* Writes a string as UTF8 bytes.
|
|
* @param {string} string Source string
|
|
* @param {Uint8Array} buffer Destination buffer
|
|
* @param {number} offset Destination offset
|
|
* @returns {number} Bytes written
|
|
*/
|
|
utf8.write = function utf8_write(string, buffer, offset) {
|
|
var start = offset,
|
|
c1, // character 1
|
|
c2; // character 2
|
|
for (var i = 0; i < string.length; ++i) {
|
|
c1 = string.charCodeAt(i);
|
|
if (c1 < 128) {
|
|
buffer[offset++] = c1;
|
|
} else if (c1 < 2048) {
|
|
buffer[offset++] = c1 >> 6 | 192;
|
|
buffer[offset++] = c1 & 63 | 128;
|
|
} else if ((c1 & 0xFC00) === 0xD800 && ((c2 = string.charCodeAt(i + 1)) & 0xFC00) === 0xDC00) {
|
|
c1 = 0x10000 + ((c1 & 0x03FF) << 10) + (c2 & 0x03FF);
|
|
++i;
|
|
buffer[offset++] = c1 >> 18 | 240;
|
|
buffer[offset++] = c1 >> 12 & 63 | 128;
|
|
buffer[offset++] = c1 >> 6 & 63 | 128;
|
|
buffer[offset++] = c1 & 63 | 128;
|
|
} else {
|
|
buffer[offset++] = c1 >> 12 | 224;
|
|
buffer[offset++] = c1 >> 6 & 63 | 128;
|
|
buffer[offset++] = c1 & 63 | 128;
|
|
}
|
|
}
|
|
return offset - start;
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/guid-typescript/dist/guid.js":
|
|
/*!***************************************************!*\
|
|
!*** ./node_modules/guid-typescript/dist/guid.js ***!
|
|
\***************************************************/
|
|
/***/ ((__unused_webpack_module, exports) => {
|
|
|
|
"use strict";
|
|
|
|
exports.__esModule = true;
|
|
var Guid = /** @class */ (function () {
|
|
function Guid(guid) {
|
|
if (!guid) {
|
|
throw new TypeError("Invalid argument; `value` has no value.");
|
|
}
|
|
this.value = Guid.EMPTY;
|
|
if (guid && Guid.isGuid(guid)) {
|
|
this.value = guid;
|
|
}
|
|
}
|
|
Guid.isGuid = function (guid) {
|
|
var value = guid.toString();
|
|
return guid && (guid instanceof Guid || Guid.validator.test(value));
|
|
};
|
|
Guid.create = function () {
|
|
return new Guid([Guid.gen(2), Guid.gen(1), Guid.gen(1), Guid.gen(1), Guid.gen(3)].join("-"));
|
|
};
|
|
Guid.createEmpty = function () {
|
|
return new Guid("emptyguid");
|
|
};
|
|
Guid.parse = function (guid) {
|
|
return new Guid(guid);
|
|
};
|
|
Guid.raw = function () {
|
|
return [Guid.gen(2), Guid.gen(1), Guid.gen(1), Guid.gen(1), Guid.gen(3)].join("-");
|
|
};
|
|
Guid.gen = function (count) {
|
|
var out = "";
|
|
for (var i = 0; i < count; i++) {
|
|
// tslint:disable-next-line:no-bitwise
|
|
out += (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1);
|
|
}
|
|
return out;
|
|
};
|
|
Guid.prototype.equals = function (other) {
|
|
// Comparing string `value` against provided `guid` will auto-call
|
|
// toString on `guid` for comparison
|
|
return Guid.isGuid(other) && this.value === other.toString();
|
|
};
|
|
Guid.prototype.isEmpty = function () {
|
|
return this.value === Guid.EMPTY;
|
|
};
|
|
Guid.prototype.toString = function () {
|
|
return this.value;
|
|
};
|
|
Guid.prototype.toJSON = function () {
|
|
return {
|
|
value: this.value
|
|
};
|
|
};
|
|
Guid.validator = new RegExp("^[a-z0-9]{8}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{12}$", "i");
|
|
Guid.EMPTY = "00000000-0000-0000-0000-000000000000";
|
|
return Guid;
|
|
}());
|
|
exports.Guid = Guid;
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/long/src/long.js":
|
|
/*!***************************************!*\
|
|
!*** ./node_modules/long/src/long.js ***!
|
|
\***************************************/
|
|
/***/ ((module) => {
|
|
|
|
module.exports = Long;
|
|
|
|
/**
|
|
* wasm optimizations, to do native i64 multiplication and divide
|
|
*/
|
|
var wasm = null;
|
|
|
|
try {
|
|
wasm = new WebAssembly.Instance(new WebAssembly.Module(new Uint8Array([
|
|
0, 97, 115, 109, 1, 0, 0, 0, 1, 13, 2, 96, 0, 1, 127, 96, 4, 127, 127, 127, 127, 1, 127, 3, 7, 6, 0, 1, 1, 1, 1, 1, 6, 6, 1, 127, 1, 65, 0, 11, 7, 50, 6, 3, 109, 117, 108, 0, 1, 5, 100, 105, 118, 95, 115, 0, 2, 5, 100, 105, 118, 95, 117, 0, 3, 5, 114, 101, 109, 95, 115, 0, 4, 5, 114, 101, 109, 95, 117, 0, 5, 8, 103, 101, 116, 95, 104, 105, 103, 104, 0, 0, 10, 191, 1, 6, 4, 0, 35, 0, 11, 36, 1, 1, 126, 32, 0, 173, 32, 1, 173, 66, 32, 134, 132, 32, 2, 173, 32, 3, 173, 66, 32, 134, 132, 126, 34, 4, 66, 32, 135, 167, 36, 0, 32, 4, 167, 11, 36, 1, 1, 126, 32, 0, 173, 32, 1, 173, 66, 32, 134, 132, 32, 2, 173, 32, 3, 173, 66, 32, 134, 132, 127, 34, 4, 66, 32, 135, 167, 36, 0, 32, 4, 167, 11, 36, 1, 1, 126, 32, 0, 173, 32, 1, 173, 66, 32, 134, 132, 32, 2, 173, 32, 3, 173, 66, 32, 134, 132, 128, 34, 4, 66, 32, 135, 167, 36, 0, 32, 4, 167, 11, 36, 1, 1, 126, 32, 0, 173, 32, 1, 173, 66, 32, 134, 132, 32, 2, 173, 32, 3, 173, 66, 32, 134, 132, 129, 34, 4, 66, 32, 135, 167, 36, 0, 32, 4, 167, 11, 36, 1, 1, 126, 32, 0, 173, 32, 1, 173, 66, 32, 134, 132, 32, 2, 173, 32, 3, 173, 66, 32, 134, 132, 130, 34, 4, 66, 32, 135, 167, 36, 0, 32, 4, 167, 11
|
|
])), {}).exports;
|
|
} catch (e) {
|
|
// no wasm support :(
|
|
}
|
|
|
|
/**
|
|
* Constructs a 64 bit two's-complement integer, given its low and high 32 bit values as *signed* integers.
|
|
* See the from* functions below for more convenient ways of constructing Longs.
|
|
* @exports Long
|
|
* @class A Long class for representing a 64 bit two's-complement integer value.
|
|
* @param {number} low The low (signed) 32 bits of the long
|
|
* @param {number} high The high (signed) 32 bits of the long
|
|
* @param {boolean=} unsigned Whether unsigned or not, defaults to signed
|
|
* @constructor
|
|
*/
|
|
function Long(low, high, unsigned) {
|
|
|
|
/**
|
|
* The low 32 bits as a signed value.
|
|
* @type {number}
|
|
*/
|
|
this.low = low | 0;
|
|
|
|
/**
|
|
* The high 32 bits as a signed value.
|
|
* @type {number}
|
|
*/
|
|
this.high = high | 0;
|
|
|
|
/**
|
|
* Whether unsigned or not.
|
|
* @type {boolean}
|
|
*/
|
|
this.unsigned = !!unsigned;
|
|
}
|
|
|
|
// The internal representation of a long is the two given signed, 32-bit values.
|
|
// We use 32-bit pieces because these are the size of integers on which
|
|
// Javascript performs bit-operations. For operations like addition and
|
|
// multiplication, we split each number into 16 bit pieces, which can easily be
|
|
// multiplied within Javascript's floating-point representation without overflow
|
|
// or change in sign.
|
|
//
|
|
// In the algorithms below, we frequently reduce the negative case to the
|
|
// positive case by negating the input(s) and then post-processing the result.
|
|
// Note that we must ALWAYS check specially whether those values are MIN_VALUE
|
|
// (-2^63) because -MIN_VALUE == MIN_VALUE (since 2^63 cannot be represented as
|
|
// a positive number, it overflows back into a negative). Not handling this
|
|
// case would often result in infinite recursion.
|
|
//
|
|
// Common constant values ZERO, ONE, NEG_ONE, etc. are defined below the from*
|
|
// methods on which they depend.
|
|
|
|
/**
|
|
* An indicator used to reliably determine if an object is a Long or not.
|
|
* @type {boolean}
|
|
* @const
|
|
* @private
|
|
*/
|
|
Long.prototype.__isLong__;
|
|
|
|
Object.defineProperty(Long.prototype, "__isLong__", { value: true });
|
|
|
|
/**
|
|
* @function
|
|
* @param {*} obj Object
|
|
* @returns {boolean}
|
|
* @inner
|
|
*/
|
|
function isLong(obj) {
|
|
return (obj && obj["__isLong__"]) === true;
|
|
}
|
|
|
|
/**
|
|
* Tests if the specified object is a Long.
|
|
* @function
|
|
* @param {*} obj Object
|
|
* @returns {boolean}
|
|
*/
|
|
Long.isLong = isLong;
|
|
|
|
/**
|
|
* A cache of the Long representations of small integer values.
|
|
* @type {!Object}
|
|
* @inner
|
|
*/
|
|
var INT_CACHE = {};
|
|
|
|
/**
|
|
* A cache of the Long representations of small unsigned integer values.
|
|
* @type {!Object}
|
|
* @inner
|
|
*/
|
|
var UINT_CACHE = {};
|
|
|
|
/**
|
|
* @param {number} value
|
|
* @param {boolean=} unsigned
|
|
* @returns {!Long}
|
|
* @inner
|
|
*/
|
|
function fromInt(value, unsigned) {
|
|
var obj, cachedObj, cache;
|
|
if (unsigned) {
|
|
value >>>= 0;
|
|
if (cache = (0 <= value && value < 256)) {
|
|
cachedObj = UINT_CACHE[value];
|
|
if (cachedObj)
|
|
return cachedObj;
|
|
}
|
|
obj = fromBits(value, (value | 0) < 0 ? -1 : 0, true);
|
|
if (cache)
|
|
UINT_CACHE[value] = obj;
|
|
return obj;
|
|
} else {
|
|
value |= 0;
|
|
if (cache = (-128 <= value && value < 128)) {
|
|
cachedObj = INT_CACHE[value];
|
|
if (cachedObj)
|
|
return cachedObj;
|
|
}
|
|
obj = fromBits(value, value < 0 ? -1 : 0, false);
|
|
if (cache)
|
|
INT_CACHE[value] = obj;
|
|
return obj;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Returns a Long representing the given 32 bit integer value.
|
|
* @function
|
|
* @param {number} value The 32 bit integer in question
|
|
* @param {boolean=} unsigned Whether unsigned or not, defaults to signed
|
|
* @returns {!Long} The corresponding Long value
|
|
*/
|
|
Long.fromInt = fromInt;
|
|
|
|
/**
|
|
* @param {number} value
|
|
* @param {boolean=} unsigned
|
|
* @returns {!Long}
|
|
* @inner
|
|
*/
|
|
function fromNumber(value, unsigned) {
|
|
if (isNaN(value))
|
|
return unsigned ? UZERO : ZERO;
|
|
if (unsigned) {
|
|
if (value < 0)
|
|
return UZERO;
|
|
if (value >= TWO_PWR_64_DBL)
|
|
return MAX_UNSIGNED_VALUE;
|
|
} else {
|
|
if (value <= -TWO_PWR_63_DBL)
|
|
return MIN_VALUE;
|
|
if (value + 1 >= TWO_PWR_63_DBL)
|
|
return MAX_VALUE;
|
|
}
|
|
if (value < 0)
|
|
return fromNumber(-value, unsigned).neg();
|
|
return fromBits((value % TWO_PWR_32_DBL) | 0, (value / TWO_PWR_32_DBL) | 0, unsigned);
|
|
}
|
|
|
|
/**
|
|
* Returns a Long representing the given value, provided that it is a finite number. Otherwise, zero is returned.
|
|
* @function
|
|
* @param {number} value The number in question
|
|
* @param {boolean=} unsigned Whether unsigned or not, defaults to signed
|
|
* @returns {!Long} The corresponding Long value
|
|
*/
|
|
Long.fromNumber = fromNumber;
|
|
|
|
/**
|
|
* @param {number} lowBits
|
|
* @param {number} highBits
|
|
* @param {boolean=} unsigned
|
|
* @returns {!Long}
|
|
* @inner
|
|
*/
|
|
function fromBits(lowBits, highBits, unsigned) {
|
|
return new Long(lowBits, highBits, unsigned);
|
|
}
|
|
|
|
/**
|
|
* Returns a Long representing the 64 bit integer that comes by concatenating the given low and high bits. Each is
|
|
* assumed to use 32 bits.
|
|
* @function
|
|
* @param {number} lowBits The low 32 bits
|
|
* @param {number} highBits The high 32 bits
|
|
* @param {boolean=} unsigned Whether unsigned or not, defaults to signed
|
|
* @returns {!Long} The corresponding Long value
|
|
*/
|
|
Long.fromBits = fromBits;
|
|
|
|
/**
|
|
* @function
|
|
* @param {number} base
|
|
* @param {number} exponent
|
|
* @returns {number}
|
|
* @inner
|
|
*/
|
|
var pow_dbl = Math.pow; // Used 4 times (4*8 to 15+4)
|
|
|
|
/**
|
|
* @param {string} str
|
|
* @param {(boolean|number)=} unsigned
|
|
* @param {number=} radix
|
|
* @returns {!Long}
|
|
* @inner
|
|
*/
|
|
function fromString(str, unsigned, radix) {
|
|
if (str.length === 0)
|
|
throw Error('empty string');
|
|
if (str === "NaN" || str === "Infinity" || str === "+Infinity" || str === "-Infinity")
|
|
return ZERO;
|
|
if (typeof unsigned === 'number') {
|
|
// For goog.math.long compatibility
|
|
radix = unsigned,
|
|
unsigned = false;
|
|
} else {
|
|
unsigned = !! unsigned;
|
|
}
|
|
radix = radix || 10;
|
|
if (radix < 2 || 36 < radix)
|
|
throw RangeError('radix');
|
|
|
|
var p;
|
|
if ((p = str.indexOf('-')) > 0)
|
|
throw Error('interior hyphen');
|
|
else if (p === 0) {
|
|
return fromString(str.substring(1), unsigned, radix).neg();
|
|
}
|
|
|
|
// Do several (8) digits each time through the loop, so as to
|
|
// minimize the calls to the very expensive emulated div.
|
|
var radixToPower = fromNumber(pow_dbl(radix, 8));
|
|
|
|
var result = ZERO;
|
|
for (var i = 0; i < str.length; i += 8) {
|
|
var size = Math.min(8, str.length - i),
|
|
value = parseInt(str.substring(i, i + size), radix);
|
|
if (size < 8) {
|
|
var power = fromNumber(pow_dbl(radix, size));
|
|
result = result.mul(power).add(fromNumber(value));
|
|
} else {
|
|
result = result.mul(radixToPower);
|
|
result = result.add(fromNumber(value));
|
|
}
|
|
}
|
|
result.unsigned = unsigned;
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Returns a Long representation of the given string, written using the specified radix.
|
|
* @function
|
|
* @param {string} str The textual representation of the Long
|
|
* @param {(boolean|number)=} unsigned Whether unsigned or not, defaults to signed
|
|
* @param {number=} radix The radix in which the text is written (2-36), defaults to 10
|
|
* @returns {!Long} The corresponding Long value
|
|
*/
|
|
Long.fromString = fromString;
|
|
|
|
/**
|
|
* @function
|
|
* @param {!Long|number|string|!{low: number, high: number, unsigned: boolean}} val
|
|
* @param {boolean=} unsigned
|
|
* @returns {!Long}
|
|
* @inner
|
|
*/
|
|
function fromValue(val, unsigned) {
|
|
if (typeof val === 'number')
|
|
return fromNumber(val, unsigned);
|
|
if (typeof val === 'string')
|
|
return fromString(val, unsigned);
|
|
// Throws for non-objects, converts non-instanceof Long:
|
|
return fromBits(val.low, val.high, typeof unsigned === 'boolean' ? unsigned : val.unsigned);
|
|
}
|
|
|
|
/**
|
|
* Converts the specified value to a Long using the appropriate from* function for its type.
|
|
* @function
|
|
* @param {!Long|number|string|!{low: number, high: number, unsigned: boolean}} val Value
|
|
* @param {boolean=} unsigned Whether unsigned or not, defaults to signed
|
|
* @returns {!Long}
|
|
*/
|
|
Long.fromValue = fromValue;
|
|
|
|
// NOTE: the compiler should inline these constant values below and then remove these variables, so there should be
|
|
// no runtime penalty for these.
|
|
|
|
/**
|
|
* @type {number}
|
|
* @const
|
|
* @inner
|
|
*/
|
|
var TWO_PWR_16_DBL = 1 << 16;
|
|
|
|
/**
|
|
* @type {number}
|
|
* @const
|
|
* @inner
|
|
*/
|
|
var TWO_PWR_24_DBL = 1 << 24;
|
|
|
|
/**
|
|
* @type {number}
|
|
* @const
|
|
* @inner
|
|
*/
|
|
var TWO_PWR_32_DBL = TWO_PWR_16_DBL * TWO_PWR_16_DBL;
|
|
|
|
/**
|
|
* @type {number}
|
|
* @const
|
|
* @inner
|
|
*/
|
|
var TWO_PWR_64_DBL = TWO_PWR_32_DBL * TWO_PWR_32_DBL;
|
|
|
|
/**
|
|
* @type {number}
|
|
* @const
|
|
* @inner
|
|
*/
|
|
var TWO_PWR_63_DBL = TWO_PWR_64_DBL / 2;
|
|
|
|
/**
|
|
* @type {!Long}
|
|
* @const
|
|
* @inner
|
|
*/
|
|
var TWO_PWR_24 = fromInt(TWO_PWR_24_DBL);
|
|
|
|
/**
|
|
* @type {!Long}
|
|
* @inner
|
|
*/
|
|
var ZERO = fromInt(0);
|
|
|
|
/**
|
|
* Signed zero.
|
|
* @type {!Long}
|
|
*/
|
|
Long.ZERO = ZERO;
|
|
|
|
/**
|
|
* @type {!Long}
|
|
* @inner
|
|
*/
|
|
var UZERO = fromInt(0, true);
|
|
|
|
/**
|
|
* Unsigned zero.
|
|
* @type {!Long}
|
|
*/
|
|
Long.UZERO = UZERO;
|
|
|
|
/**
|
|
* @type {!Long}
|
|
* @inner
|
|
*/
|
|
var ONE = fromInt(1);
|
|
|
|
/**
|
|
* Signed one.
|
|
* @type {!Long}
|
|
*/
|
|
Long.ONE = ONE;
|
|
|
|
/**
|
|
* @type {!Long}
|
|
* @inner
|
|
*/
|
|
var UONE = fromInt(1, true);
|
|
|
|
/**
|
|
* Unsigned one.
|
|
* @type {!Long}
|
|
*/
|
|
Long.UONE = UONE;
|
|
|
|
/**
|
|
* @type {!Long}
|
|
* @inner
|
|
*/
|
|
var NEG_ONE = fromInt(-1);
|
|
|
|
/**
|
|
* Signed negative one.
|
|
* @type {!Long}
|
|
*/
|
|
Long.NEG_ONE = NEG_ONE;
|
|
|
|
/**
|
|
* @type {!Long}
|
|
* @inner
|
|
*/
|
|
var MAX_VALUE = fromBits(0xFFFFFFFF|0, 0x7FFFFFFF|0, false);
|
|
|
|
/**
|
|
* Maximum signed value.
|
|
* @type {!Long}
|
|
*/
|
|
Long.MAX_VALUE = MAX_VALUE;
|
|
|
|
/**
|
|
* @type {!Long}
|
|
* @inner
|
|
*/
|
|
var MAX_UNSIGNED_VALUE = fromBits(0xFFFFFFFF|0, 0xFFFFFFFF|0, true);
|
|
|
|
/**
|
|
* Maximum unsigned value.
|
|
* @type {!Long}
|
|
*/
|
|
Long.MAX_UNSIGNED_VALUE = MAX_UNSIGNED_VALUE;
|
|
|
|
/**
|
|
* @type {!Long}
|
|
* @inner
|
|
*/
|
|
var MIN_VALUE = fromBits(0, 0x80000000|0, false);
|
|
|
|
/**
|
|
* Minimum signed value.
|
|
* @type {!Long}
|
|
*/
|
|
Long.MIN_VALUE = MIN_VALUE;
|
|
|
|
/**
|
|
* @alias Long.prototype
|
|
* @inner
|
|
*/
|
|
var LongPrototype = Long.prototype;
|
|
|
|
/**
|
|
* Converts the Long to a 32 bit integer, assuming it is a 32 bit integer.
|
|
* @returns {number}
|
|
*/
|
|
LongPrototype.toInt = function toInt() {
|
|
return this.unsigned ? this.low >>> 0 : this.low;
|
|
};
|
|
|
|
/**
|
|
* Converts the Long to a the nearest floating-point representation of this value (double, 53 bit mantissa).
|
|
* @returns {number}
|
|
*/
|
|
LongPrototype.toNumber = function toNumber() {
|
|
if (this.unsigned)
|
|
return ((this.high >>> 0) * TWO_PWR_32_DBL) + (this.low >>> 0);
|
|
return this.high * TWO_PWR_32_DBL + (this.low >>> 0);
|
|
};
|
|
|
|
/**
|
|
* Converts the Long to a string written in the specified radix.
|
|
* @param {number=} radix Radix (2-36), defaults to 10
|
|
* @returns {string}
|
|
* @override
|
|
* @throws {RangeError} If `radix` is out of range
|
|
*/
|
|
LongPrototype.toString = function toString(radix) {
|
|
radix = radix || 10;
|
|
if (radix < 2 || 36 < radix)
|
|
throw RangeError('radix');
|
|
if (this.isZero())
|
|
return '0';
|
|
if (this.isNegative()) { // Unsigned Longs are never negative
|
|
if (this.eq(MIN_VALUE)) {
|
|
// We need to change the Long value before it can be negated, so we remove
|
|
// the bottom-most digit in this base and then recurse to do the rest.
|
|
var radixLong = fromNumber(radix),
|
|
div = this.div(radixLong),
|
|
rem1 = div.mul(radixLong).sub(this);
|
|
return div.toString(radix) + rem1.toInt().toString(radix);
|
|
} else
|
|
return '-' + this.neg().toString(radix);
|
|
}
|
|
|
|
// Do several (6) digits each time through the loop, so as to
|
|
// minimize the calls to the very expensive emulated div.
|
|
var radixToPower = fromNumber(pow_dbl(radix, 6), this.unsigned),
|
|
rem = this;
|
|
var result = '';
|
|
while (true) {
|
|
var remDiv = rem.div(radixToPower),
|
|
intval = rem.sub(remDiv.mul(radixToPower)).toInt() >>> 0,
|
|
digits = intval.toString(radix);
|
|
rem = remDiv;
|
|
if (rem.isZero())
|
|
return digits + result;
|
|
else {
|
|
while (digits.length < 6)
|
|
digits = '0' + digits;
|
|
result = '' + digits + result;
|
|
}
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Gets the high 32 bits as a signed integer.
|
|
* @returns {number} Signed high bits
|
|
*/
|
|
LongPrototype.getHighBits = function getHighBits() {
|
|
return this.high;
|
|
};
|
|
|
|
/**
|
|
* Gets the high 32 bits as an unsigned integer.
|
|
* @returns {number} Unsigned high bits
|
|
*/
|
|
LongPrototype.getHighBitsUnsigned = function getHighBitsUnsigned() {
|
|
return this.high >>> 0;
|
|
};
|
|
|
|
/**
|
|
* Gets the low 32 bits as a signed integer.
|
|
* @returns {number} Signed low bits
|
|
*/
|
|
LongPrototype.getLowBits = function getLowBits() {
|
|
return this.low;
|
|
};
|
|
|
|
/**
|
|
* Gets the low 32 bits as an unsigned integer.
|
|
* @returns {number} Unsigned low bits
|
|
*/
|
|
LongPrototype.getLowBitsUnsigned = function getLowBitsUnsigned() {
|
|
return this.low >>> 0;
|
|
};
|
|
|
|
/**
|
|
* Gets the number of bits needed to represent the absolute value of this Long.
|
|
* @returns {number}
|
|
*/
|
|
LongPrototype.getNumBitsAbs = function getNumBitsAbs() {
|
|
if (this.isNegative()) // Unsigned Longs are never negative
|
|
return this.eq(MIN_VALUE) ? 64 : this.neg().getNumBitsAbs();
|
|
var val = this.high != 0 ? this.high : this.low;
|
|
for (var bit = 31; bit > 0; bit--)
|
|
if ((val & (1 << bit)) != 0)
|
|
break;
|
|
return this.high != 0 ? bit + 33 : bit + 1;
|
|
};
|
|
|
|
/**
|
|
* Tests if this Long's value equals zero.
|
|
* @returns {boolean}
|
|
*/
|
|
LongPrototype.isZero = function isZero() {
|
|
return this.high === 0 && this.low === 0;
|
|
};
|
|
|
|
/**
|
|
* Tests if this Long's value equals zero. This is an alias of {@link Long#isZero}.
|
|
* @returns {boolean}
|
|
*/
|
|
LongPrototype.eqz = LongPrototype.isZero;
|
|
|
|
/**
|
|
* Tests if this Long's value is negative.
|
|
* @returns {boolean}
|
|
*/
|
|
LongPrototype.isNegative = function isNegative() {
|
|
return !this.unsigned && this.high < 0;
|
|
};
|
|
|
|
/**
|
|
* Tests if this Long's value is positive.
|
|
* @returns {boolean}
|
|
*/
|
|
LongPrototype.isPositive = function isPositive() {
|
|
return this.unsigned || this.high >= 0;
|
|
};
|
|
|
|
/**
|
|
* Tests if this Long's value is odd.
|
|
* @returns {boolean}
|
|
*/
|
|
LongPrototype.isOdd = function isOdd() {
|
|
return (this.low & 1) === 1;
|
|
};
|
|
|
|
/**
|
|
* Tests if this Long's value is even.
|
|
* @returns {boolean}
|
|
*/
|
|
LongPrototype.isEven = function isEven() {
|
|
return (this.low & 1) === 0;
|
|
};
|
|
|
|
/**
|
|
* Tests if this Long's value equals the specified's.
|
|
* @param {!Long|number|string} other Other value
|
|
* @returns {boolean}
|
|
*/
|
|
LongPrototype.equals = function equals(other) {
|
|
if (!isLong(other))
|
|
other = fromValue(other);
|
|
if (this.unsigned !== other.unsigned && (this.high >>> 31) === 1 && (other.high >>> 31) === 1)
|
|
return false;
|
|
return this.high === other.high && this.low === other.low;
|
|
};
|
|
|
|
/**
|
|
* Tests if this Long's value equals the specified's. This is an alias of {@link Long#equals}.
|
|
* @function
|
|
* @param {!Long|number|string} other Other value
|
|
* @returns {boolean}
|
|
*/
|
|
LongPrototype.eq = LongPrototype.equals;
|
|
|
|
/**
|
|
* Tests if this Long's value differs from the specified's.
|
|
* @param {!Long|number|string} other Other value
|
|
* @returns {boolean}
|
|
*/
|
|
LongPrototype.notEquals = function notEquals(other) {
|
|
return !this.eq(/* validates */ other);
|
|
};
|
|
|
|
/**
|
|
* Tests if this Long's value differs from the specified's. This is an alias of {@link Long#notEquals}.
|
|
* @function
|
|
* @param {!Long|number|string} other Other value
|
|
* @returns {boolean}
|
|
*/
|
|
LongPrototype.neq = LongPrototype.notEquals;
|
|
|
|
/**
|
|
* Tests if this Long's value differs from the specified's. This is an alias of {@link Long#notEquals}.
|
|
* @function
|
|
* @param {!Long|number|string} other Other value
|
|
* @returns {boolean}
|
|
*/
|
|
LongPrototype.ne = LongPrototype.notEquals;
|
|
|
|
/**
|
|
* Tests if this Long's value is less than the specified's.
|
|
* @param {!Long|number|string} other Other value
|
|
* @returns {boolean}
|
|
*/
|
|
LongPrototype.lessThan = function lessThan(other) {
|
|
return this.comp(/* validates */ other) < 0;
|
|
};
|
|
|
|
/**
|
|
* Tests if this Long's value is less than the specified's. This is an alias of {@link Long#lessThan}.
|
|
* @function
|
|
* @param {!Long|number|string} other Other value
|
|
* @returns {boolean}
|
|
*/
|
|
LongPrototype.lt = LongPrototype.lessThan;
|
|
|
|
/**
|
|
* Tests if this Long's value is less than or equal the specified's.
|
|
* @param {!Long|number|string} other Other value
|
|
* @returns {boolean}
|
|
*/
|
|
LongPrototype.lessThanOrEqual = function lessThanOrEqual(other) {
|
|
return this.comp(/* validates */ other) <= 0;
|
|
};
|
|
|
|
/**
|
|
* Tests if this Long's value is less than or equal the specified's. This is an alias of {@link Long#lessThanOrEqual}.
|
|
* @function
|
|
* @param {!Long|number|string} other Other value
|
|
* @returns {boolean}
|
|
*/
|
|
LongPrototype.lte = LongPrototype.lessThanOrEqual;
|
|
|
|
/**
|
|
* Tests if this Long's value is less than or equal the specified's. This is an alias of {@link Long#lessThanOrEqual}.
|
|
* @function
|
|
* @param {!Long|number|string} other Other value
|
|
* @returns {boolean}
|
|
*/
|
|
LongPrototype.le = LongPrototype.lessThanOrEqual;
|
|
|
|
/**
|
|
* Tests if this Long's value is greater than the specified's.
|
|
* @param {!Long|number|string} other Other value
|
|
* @returns {boolean}
|
|
*/
|
|
LongPrototype.greaterThan = function greaterThan(other) {
|
|
return this.comp(/* validates */ other) > 0;
|
|
};
|
|
|
|
/**
|
|
* Tests if this Long's value is greater than the specified's. This is an alias of {@link Long#greaterThan}.
|
|
* @function
|
|
* @param {!Long|number|string} other Other value
|
|
* @returns {boolean}
|
|
*/
|
|
LongPrototype.gt = LongPrototype.greaterThan;
|
|
|
|
/**
|
|
* Tests if this Long's value is greater than or equal the specified's.
|
|
* @param {!Long|number|string} other Other value
|
|
* @returns {boolean}
|
|
*/
|
|
LongPrototype.greaterThanOrEqual = function greaterThanOrEqual(other) {
|
|
return this.comp(/* validates */ other) >= 0;
|
|
};
|
|
|
|
/**
|
|
* Tests if this Long's value is greater than or equal the specified's. This is an alias of {@link Long#greaterThanOrEqual}.
|
|
* @function
|
|
* @param {!Long|number|string} other Other value
|
|
* @returns {boolean}
|
|
*/
|
|
LongPrototype.gte = LongPrototype.greaterThanOrEqual;
|
|
|
|
/**
|
|
* Tests if this Long's value is greater than or equal the specified's. This is an alias of {@link Long#greaterThanOrEqual}.
|
|
* @function
|
|
* @param {!Long|number|string} other Other value
|
|
* @returns {boolean}
|
|
*/
|
|
LongPrototype.ge = LongPrototype.greaterThanOrEqual;
|
|
|
|
/**
|
|
* Compares this Long's value with the specified's.
|
|
* @param {!Long|number|string} other Other value
|
|
* @returns {number} 0 if they are the same, 1 if the this is greater and -1
|
|
* if the given one is greater
|
|
*/
|
|
LongPrototype.compare = function compare(other) {
|
|
if (!isLong(other))
|
|
other = fromValue(other);
|
|
if (this.eq(other))
|
|
return 0;
|
|
var thisNeg = this.isNegative(),
|
|
otherNeg = other.isNegative();
|
|
if (thisNeg && !otherNeg)
|
|
return -1;
|
|
if (!thisNeg && otherNeg)
|
|
return 1;
|
|
// At this point the sign bits are the same
|
|
if (!this.unsigned)
|
|
return this.sub(other).isNegative() ? -1 : 1;
|
|
// Both are positive if at least one is unsigned
|
|
return (other.high >>> 0) > (this.high >>> 0) || (other.high === this.high && (other.low >>> 0) > (this.low >>> 0)) ? -1 : 1;
|
|
};
|
|
|
|
/**
|
|
* Compares this Long's value with the specified's. This is an alias of {@link Long#compare}.
|
|
* @function
|
|
* @param {!Long|number|string} other Other value
|
|
* @returns {number} 0 if they are the same, 1 if the this is greater and -1
|
|
* if the given one is greater
|
|
*/
|
|
LongPrototype.comp = LongPrototype.compare;
|
|
|
|
/**
|
|
* Negates this Long's value.
|
|
* @returns {!Long} Negated Long
|
|
*/
|
|
LongPrototype.negate = function negate() {
|
|
if (!this.unsigned && this.eq(MIN_VALUE))
|
|
return MIN_VALUE;
|
|
return this.not().add(ONE);
|
|
};
|
|
|
|
/**
|
|
* Negates this Long's value. This is an alias of {@link Long#negate}.
|
|
* @function
|
|
* @returns {!Long} Negated Long
|
|
*/
|
|
LongPrototype.neg = LongPrototype.negate;
|
|
|
|
/**
|
|
* Returns the sum of this and the specified Long.
|
|
* @param {!Long|number|string} addend Addend
|
|
* @returns {!Long} Sum
|
|
*/
|
|
LongPrototype.add = function add(addend) {
|
|
if (!isLong(addend))
|
|
addend = fromValue(addend);
|
|
|
|
// Divide each number into 4 chunks of 16 bits, and then sum the chunks.
|
|
|
|
var a48 = this.high >>> 16;
|
|
var a32 = this.high & 0xFFFF;
|
|
var a16 = this.low >>> 16;
|
|
var a00 = this.low & 0xFFFF;
|
|
|
|
var b48 = addend.high >>> 16;
|
|
var b32 = addend.high & 0xFFFF;
|
|
var b16 = addend.low >>> 16;
|
|
var b00 = addend.low & 0xFFFF;
|
|
|
|
var c48 = 0, c32 = 0, c16 = 0, c00 = 0;
|
|
c00 += a00 + b00;
|
|
c16 += c00 >>> 16;
|
|
c00 &= 0xFFFF;
|
|
c16 += a16 + b16;
|
|
c32 += c16 >>> 16;
|
|
c16 &= 0xFFFF;
|
|
c32 += a32 + b32;
|
|
c48 += c32 >>> 16;
|
|
c32 &= 0xFFFF;
|
|
c48 += a48 + b48;
|
|
c48 &= 0xFFFF;
|
|
return fromBits((c16 << 16) | c00, (c48 << 16) | c32, this.unsigned);
|
|
};
|
|
|
|
/**
|
|
* Returns the difference of this and the specified Long.
|
|
* @param {!Long|number|string} subtrahend Subtrahend
|
|
* @returns {!Long} Difference
|
|
*/
|
|
LongPrototype.subtract = function subtract(subtrahend) {
|
|
if (!isLong(subtrahend))
|
|
subtrahend = fromValue(subtrahend);
|
|
return this.add(subtrahend.neg());
|
|
};
|
|
|
|
/**
|
|
* Returns the difference of this and the specified Long. This is an alias of {@link Long#subtract}.
|
|
* @function
|
|
* @param {!Long|number|string} subtrahend Subtrahend
|
|
* @returns {!Long} Difference
|
|
*/
|
|
LongPrototype.sub = LongPrototype.subtract;
|
|
|
|
/**
|
|
* Returns the product of this and the specified Long.
|
|
* @param {!Long|number|string} multiplier Multiplier
|
|
* @returns {!Long} Product
|
|
*/
|
|
LongPrototype.multiply = function multiply(multiplier) {
|
|
if (this.isZero())
|
|
return ZERO;
|
|
if (!isLong(multiplier))
|
|
multiplier = fromValue(multiplier);
|
|
|
|
// use wasm support if present
|
|
if (wasm) {
|
|
var low = wasm.mul(this.low,
|
|
this.high,
|
|
multiplier.low,
|
|
multiplier.high);
|
|
return fromBits(low, wasm.get_high(), this.unsigned);
|
|
}
|
|
|
|
if (multiplier.isZero())
|
|
return ZERO;
|
|
if (this.eq(MIN_VALUE))
|
|
return multiplier.isOdd() ? MIN_VALUE : ZERO;
|
|
if (multiplier.eq(MIN_VALUE))
|
|
return this.isOdd() ? MIN_VALUE : ZERO;
|
|
|
|
if (this.isNegative()) {
|
|
if (multiplier.isNegative())
|
|
return this.neg().mul(multiplier.neg());
|
|
else
|
|
return this.neg().mul(multiplier).neg();
|
|
} else if (multiplier.isNegative())
|
|
return this.mul(multiplier.neg()).neg();
|
|
|
|
// If both longs are small, use float multiplication
|
|
if (this.lt(TWO_PWR_24) && multiplier.lt(TWO_PWR_24))
|
|
return fromNumber(this.toNumber() * multiplier.toNumber(), this.unsigned);
|
|
|
|
// Divide each long into 4 chunks of 16 bits, and then add up 4x4 products.
|
|
// We can skip products that would overflow.
|
|
|
|
var a48 = this.high >>> 16;
|
|
var a32 = this.high & 0xFFFF;
|
|
var a16 = this.low >>> 16;
|
|
var a00 = this.low & 0xFFFF;
|
|
|
|
var b48 = multiplier.high >>> 16;
|
|
var b32 = multiplier.high & 0xFFFF;
|
|
var b16 = multiplier.low >>> 16;
|
|
var b00 = multiplier.low & 0xFFFF;
|
|
|
|
var c48 = 0, c32 = 0, c16 = 0, c00 = 0;
|
|
c00 += a00 * b00;
|
|
c16 += c00 >>> 16;
|
|
c00 &= 0xFFFF;
|
|
c16 += a16 * b00;
|
|
c32 += c16 >>> 16;
|
|
c16 &= 0xFFFF;
|
|
c16 += a00 * b16;
|
|
c32 += c16 >>> 16;
|
|
c16 &= 0xFFFF;
|
|
c32 += a32 * b00;
|
|
c48 += c32 >>> 16;
|
|
c32 &= 0xFFFF;
|
|
c32 += a16 * b16;
|
|
c48 += c32 >>> 16;
|
|
c32 &= 0xFFFF;
|
|
c32 += a00 * b32;
|
|
c48 += c32 >>> 16;
|
|
c32 &= 0xFFFF;
|
|
c48 += a48 * b00 + a32 * b16 + a16 * b32 + a00 * b48;
|
|
c48 &= 0xFFFF;
|
|
return fromBits((c16 << 16) | c00, (c48 << 16) | c32, this.unsigned);
|
|
};
|
|
|
|
/**
|
|
* Returns the product of this and the specified Long. This is an alias of {@link Long#multiply}.
|
|
* @function
|
|
* @param {!Long|number|string} multiplier Multiplier
|
|
* @returns {!Long} Product
|
|
*/
|
|
LongPrototype.mul = LongPrototype.multiply;
|
|
|
|
/**
|
|
* Returns this Long divided by the specified. The result is signed if this Long is signed or
|
|
* unsigned if this Long is unsigned.
|
|
* @param {!Long|number|string} divisor Divisor
|
|
* @returns {!Long} Quotient
|
|
*/
|
|
LongPrototype.divide = function divide(divisor) {
|
|
if (!isLong(divisor))
|
|
divisor = fromValue(divisor);
|
|
if (divisor.isZero())
|
|
throw Error('division by zero');
|
|
|
|
// use wasm support if present
|
|
if (wasm) {
|
|
// guard against signed division overflow: the largest
|
|
// negative number / -1 would be 1 larger than the largest
|
|
// positive number, due to two's complement.
|
|
if (!this.unsigned &&
|
|
this.high === -0x80000000 &&
|
|
divisor.low === -1 && divisor.high === -1) {
|
|
// be consistent with non-wasm code path
|
|
return this;
|
|
}
|
|
var low = (this.unsigned ? wasm.div_u : wasm.div_s)(
|
|
this.low,
|
|
this.high,
|
|
divisor.low,
|
|
divisor.high
|
|
);
|
|
return fromBits(low, wasm.get_high(), this.unsigned);
|
|
}
|
|
|
|
if (this.isZero())
|
|
return this.unsigned ? UZERO : ZERO;
|
|
var approx, rem, res;
|
|
if (!this.unsigned) {
|
|
// This section is only relevant for signed longs and is derived from the
|
|
// closure library as a whole.
|
|
if (this.eq(MIN_VALUE)) {
|
|
if (divisor.eq(ONE) || divisor.eq(NEG_ONE))
|
|
return MIN_VALUE; // recall that -MIN_VALUE == MIN_VALUE
|
|
else if (divisor.eq(MIN_VALUE))
|
|
return ONE;
|
|
else {
|
|
// At this point, we have |other| >= 2, so |this/other| < |MIN_VALUE|.
|
|
var halfThis = this.shr(1);
|
|
approx = halfThis.div(divisor).shl(1);
|
|
if (approx.eq(ZERO)) {
|
|
return divisor.isNegative() ? ONE : NEG_ONE;
|
|
} else {
|
|
rem = this.sub(divisor.mul(approx));
|
|
res = approx.add(rem.div(divisor));
|
|
return res;
|
|
}
|
|
}
|
|
} else if (divisor.eq(MIN_VALUE))
|
|
return this.unsigned ? UZERO : ZERO;
|
|
if (this.isNegative()) {
|
|
if (divisor.isNegative())
|
|
return this.neg().div(divisor.neg());
|
|
return this.neg().div(divisor).neg();
|
|
} else if (divisor.isNegative())
|
|
return this.div(divisor.neg()).neg();
|
|
res = ZERO;
|
|
} else {
|
|
// The algorithm below has not been made for unsigned longs. It's therefore
|
|
// required to take special care of the MSB prior to running it.
|
|
if (!divisor.unsigned)
|
|
divisor = divisor.toUnsigned();
|
|
if (divisor.gt(this))
|
|
return UZERO;
|
|
if (divisor.gt(this.shru(1))) // 15 >>> 1 = 7 ; with divisor = 8 ; true
|
|
return UONE;
|
|
res = UZERO;
|
|
}
|
|
|
|
// Repeat the following until the remainder is less than other: find a
|
|
// floating-point that approximates remainder / other *from below*, add this
|
|
// into the result, and subtract it from the remainder. It is critical that
|
|
// the approximate value is less than or equal to the real value so that the
|
|
// remainder never becomes negative.
|
|
rem = this;
|
|
while (rem.gte(divisor)) {
|
|
// Approximate the result of division. This may be a little greater or
|
|
// smaller than the actual value.
|
|
approx = Math.max(1, Math.floor(rem.toNumber() / divisor.toNumber()));
|
|
|
|
// We will tweak the approximate result by changing it in the 48-th digit or
|
|
// the smallest non-fractional digit, whichever is larger.
|
|
var log2 = Math.ceil(Math.log(approx) / Math.LN2),
|
|
delta = (log2 <= 48) ? 1 : pow_dbl(2, log2 - 48),
|
|
|
|
// Decrease the approximation until it is smaller than the remainder. Note
|
|
// that if it is too large, the product overflows and is negative.
|
|
approxRes = fromNumber(approx),
|
|
approxRem = approxRes.mul(divisor);
|
|
while (approxRem.isNegative() || approxRem.gt(rem)) {
|
|
approx -= delta;
|
|
approxRes = fromNumber(approx, this.unsigned);
|
|
approxRem = approxRes.mul(divisor);
|
|
}
|
|
|
|
// We know the answer can't be zero... and actually, zero would cause
|
|
// infinite recursion since we would make no progress.
|
|
if (approxRes.isZero())
|
|
approxRes = ONE;
|
|
|
|
res = res.add(approxRes);
|
|
rem = rem.sub(approxRem);
|
|
}
|
|
return res;
|
|
};
|
|
|
|
/**
|
|
* Returns this Long divided by the specified. This is an alias of {@link Long#divide}.
|
|
* @function
|
|
* @param {!Long|number|string} divisor Divisor
|
|
* @returns {!Long} Quotient
|
|
*/
|
|
LongPrototype.div = LongPrototype.divide;
|
|
|
|
/**
|
|
* Returns this Long modulo the specified.
|
|
* @param {!Long|number|string} divisor Divisor
|
|
* @returns {!Long} Remainder
|
|
*/
|
|
LongPrototype.modulo = function modulo(divisor) {
|
|
if (!isLong(divisor))
|
|
divisor = fromValue(divisor);
|
|
|
|
// use wasm support if present
|
|
if (wasm) {
|
|
var low = (this.unsigned ? wasm.rem_u : wasm.rem_s)(
|
|
this.low,
|
|
this.high,
|
|
divisor.low,
|
|
divisor.high
|
|
);
|
|
return fromBits(low, wasm.get_high(), this.unsigned);
|
|
}
|
|
|
|
return this.sub(this.div(divisor).mul(divisor));
|
|
};
|
|
|
|
/**
|
|
* Returns this Long modulo the specified. This is an alias of {@link Long#modulo}.
|
|
* @function
|
|
* @param {!Long|number|string} divisor Divisor
|
|
* @returns {!Long} Remainder
|
|
*/
|
|
LongPrototype.mod = LongPrototype.modulo;
|
|
|
|
/**
|
|
* Returns this Long modulo the specified. This is an alias of {@link Long#modulo}.
|
|
* @function
|
|
* @param {!Long|number|string} divisor Divisor
|
|
* @returns {!Long} Remainder
|
|
*/
|
|
LongPrototype.rem = LongPrototype.modulo;
|
|
|
|
/**
|
|
* Returns the bitwise NOT of this Long.
|
|
* @returns {!Long}
|
|
*/
|
|
LongPrototype.not = function not() {
|
|
return fromBits(~this.low, ~this.high, this.unsigned);
|
|
};
|
|
|
|
/**
|
|
* Returns the bitwise AND of this Long and the specified.
|
|
* @param {!Long|number|string} other Other Long
|
|
* @returns {!Long}
|
|
*/
|
|
LongPrototype.and = function and(other) {
|
|
if (!isLong(other))
|
|
other = fromValue(other);
|
|
return fromBits(this.low & other.low, this.high & other.high, this.unsigned);
|
|
};
|
|
|
|
/**
|
|
* Returns the bitwise OR of this Long and the specified.
|
|
* @param {!Long|number|string} other Other Long
|
|
* @returns {!Long}
|
|
*/
|
|
LongPrototype.or = function or(other) {
|
|
if (!isLong(other))
|
|
other = fromValue(other);
|
|
return fromBits(this.low | other.low, this.high | other.high, this.unsigned);
|
|
};
|
|
|
|
/**
|
|
* Returns the bitwise XOR of this Long and the given one.
|
|
* @param {!Long|number|string} other Other Long
|
|
* @returns {!Long}
|
|
*/
|
|
LongPrototype.xor = function xor(other) {
|
|
if (!isLong(other))
|
|
other = fromValue(other);
|
|
return fromBits(this.low ^ other.low, this.high ^ other.high, this.unsigned);
|
|
};
|
|
|
|
/**
|
|
* Returns this Long with bits shifted to the left by the given amount.
|
|
* @param {number|!Long} numBits Number of bits
|
|
* @returns {!Long} Shifted Long
|
|
*/
|
|
LongPrototype.shiftLeft = function shiftLeft(numBits) {
|
|
if (isLong(numBits))
|
|
numBits = numBits.toInt();
|
|
if ((numBits &= 63) === 0)
|
|
return this;
|
|
else if (numBits < 32)
|
|
return fromBits(this.low << numBits, (this.high << numBits) | (this.low >>> (32 - numBits)), this.unsigned);
|
|
else
|
|
return fromBits(0, this.low << (numBits - 32), this.unsigned);
|
|
};
|
|
|
|
/**
|
|
* Returns this Long with bits shifted to the left by the given amount. This is an alias of {@link Long#shiftLeft}.
|
|
* @function
|
|
* @param {number|!Long} numBits Number of bits
|
|
* @returns {!Long} Shifted Long
|
|
*/
|
|
LongPrototype.shl = LongPrototype.shiftLeft;
|
|
|
|
/**
|
|
* Returns this Long with bits arithmetically shifted to the right by the given amount.
|
|
* @param {number|!Long} numBits Number of bits
|
|
* @returns {!Long} Shifted Long
|
|
*/
|
|
LongPrototype.shiftRight = function shiftRight(numBits) {
|
|
if (isLong(numBits))
|
|
numBits = numBits.toInt();
|
|
if ((numBits &= 63) === 0)
|
|
return this;
|
|
else if (numBits < 32)
|
|
return fromBits((this.low >>> numBits) | (this.high << (32 - numBits)), this.high >> numBits, this.unsigned);
|
|
else
|
|
return fromBits(this.high >> (numBits - 32), this.high >= 0 ? 0 : -1, this.unsigned);
|
|
};
|
|
|
|
/**
|
|
* Returns this Long with bits arithmetically shifted to the right by the given amount. This is an alias of {@link Long#shiftRight}.
|
|
* @function
|
|
* @param {number|!Long} numBits Number of bits
|
|
* @returns {!Long} Shifted Long
|
|
*/
|
|
LongPrototype.shr = LongPrototype.shiftRight;
|
|
|
|
/**
|
|
* Returns this Long with bits logically shifted to the right by the given amount.
|
|
* @param {number|!Long} numBits Number of bits
|
|
* @returns {!Long} Shifted Long
|
|
*/
|
|
LongPrototype.shiftRightUnsigned = function shiftRightUnsigned(numBits) {
|
|
if (isLong(numBits))
|
|
numBits = numBits.toInt();
|
|
numBits &= 63;
|
|
if (numBits === 0)
|
|
return this;
|
|
else {
|
|
var high = this.high;
|
|
if (numBits < 32) {
|
|
var low = this.low;
|
|
return fromBits((low >>> numBits) | (high << (32 - numBits)), high >>> numBits, this.unsigned);
|
|
} else if (numBits === 32)
|
|
return fromBits(high, 0, this.unsigned);
|
|
else
|
|
return fromBits(high >>> (numBits - 32), 0, this.unsigned);
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Returns this Long with bits logically shifted to the right by the given amount. This is an alias of {@link Long#shiftRightUnsigned}.
|
|
* @function
|
|
* @param {number|!Long} numBits Number of bits
|
|
* @returns {!Long} Shifted Long
|
|
*/
|
|
LongPrototype.shru = LongPrototype.shiftRightUnsigned;
|
|
|
|
/**
|
|
* Returns this Long with bits logically shifted to the right by the given amount. This is an alias of {@link Long#shiftRightUnsigned}.
|
|
* @function
|
|
* @param {number|!Long} numBits Number of bits
|
|
* @returns {!Long} Shifted Long
|
|
*/
|
|
LongPrototype.shr_u = LongPrototype.shiftRightUnsigned;
|
|
|
|
/**
|
|
* Converts this Long to signed.
|
|
* @returns {!Long} Signed long
|
|
*/
|
|
LongPrototype.toSigned = function toSigned() {
|
|
if (!this.unsigned)
|
|
return this;
|
|
return fromBits(this.low, this.high, false);
|
|
};
|
|
|
|
/**
|
|
* Converts this Long to unsigned.
|
|
* @returns {!Long} Unsigned long
|
|
*/
|
|
LongPrototype.toUnsigned = function toUnsigned() {
|
|
if (this.unsigned)
|
|
return this;
|
|
return fromBits(this.low, this.high, true);
|
|
};
|
|
|
|
/**
|
|
* Converts this Long to its byte representation.
|
|
* @param {boolean=} le Whether little or big endian, defaults to big endian
|
|
* @returns {!Array.<number>} Byte representation
|
|
*/
|
|
LongPrototype.toBytes = function toBytes(le) {
|
|
return le ? this.toBytesLE() : this.toBytesBE();
|
|
};
|
|
|
|
/**
|
|
* Converts this Long to its little endian byte representation.
|
|
* @returns {!Array.<number>} Little endian byte representation
|
|
*/
|
|
LongPrototype.toBytesLE = function toBytesLE() {
|
|
var hi = this.high,
|
|
lo = this.low;
|
|
return [
|
|
lo & 0xff,
|
|
lo >>> 8 & 0xff,
|
|
lo >>> 16 & 0xff,
|
|
lo >>> 24 ,
|
|
hi & 0xff,
|
|
hi >>> 8 & 0xff,
|
|
hi >>> 16 & 0xff,
|
|
hi >>> 24
|
|
];
|
|
};
|
|
|
|
/**
|
|
* Converts this Long to its big endian byte representation.
|
|
* @returns {!Array.<number>} Big endian byte representation
|
|
*/
|
|
LongPrototype.toBytesBE = function toBytesBE() {
|
|
var hi = this.high,
|
|
lo = this.low;
|
|
return [
|
|
hi >>> 24 ,
|
|
hi >>> 16 & 0xff,
|
|
hi >>> 8 & 0xff,
|
|
hi & 0xff,
|
|
lo >>> 24 ,
|
|
lo >>> 16 & 0xff,
|
|
lo >>> 8 & 0xff,
|
|
lo & 0xff
|
|
];
|
|
};
|
|
|
|
/**
|
|
* Creates a Long from its byte representation.
|
|
* @param {!Array.<number>} bytes Byte representation
|
|
* @param {boolean=} unsigned Whether unsigned or not, defaults to signed
|
|
* @param {boolean=} le Whether little or big endian, defaults to big endian
|
|
* @returns {Long} The corresponding Long value
|
|
*/
|
|
Long.fromBytes = function fromBytes(bytes, unsigned, le) {
|
|
return le ? Long.fromBytesLE(bytes, unsigned) : Long.fromBytesBE(bytes, unsigned);
|
|
};
|
|
|
|
/**
|
|
* Creates a Long from its little endian byte representation.
|
|
* @param {!Array.<number>} bytes Little endian byte representation
|
|
* @param {boolean=} unsigned Whether unsigned or not, defaults to signed
|
|
* @returns {Long} The corresponding Long value
|
|
*/
|
|
Long.fromBytesLE = function fromBytesLE(bytes, unsigned) {
|
|
return new Long(
|
|
bytes[0] |
|
|
bytes[1] << 8 |
|
|
bytes[2] << 16 |
|
|
bytes[3] << 24,
|
|
bytes[4] |
|
|
bytes[5] << 8 |
|
|
bytes[6] << 16 |
|
|
bytes[7] << 24,
|
|
unsigned
|
|
);
|
|
};
|
|
|
|
/**
|
|
* Creates a Long from its big endian byte representation.
|
|
* @param {!Array.<number>} bytes Big endian byte representation
|
|
* @param {boolean=} unsigned Whether unsigned or not, defaults to signed
|
|
* @returns {Long} The corresponding Long value
|
|
*/
|
|
Long.fromBytesBE = function fromBytesBE(bytes, unsigned) {
|
|
return new Long(
|
|
bytes[4] << 24 |
|
|
bytes[5] << 16 |
|
|
bytes[6] << 8 |
|
|
bytes[7],
|
|
bytes[0] << 24 |
|
|
bytes[1] << 16 |
|
|
bytes[2] << 8 |
|
|
bytes[3],
|
|
unsigned
|
|
);
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/onnx-proto/dist/onnx.js":
|
|
/*!**********************************************!*\
|
|
!*** ./node_modules/onnx-proto/dist/onnx.js ***!
|
|
\**********************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
/*eslint-disable block-scoped-var, id-length, no-control-regex, no-magic-numbers, no-prototype-builtins, no-redeclare, no-shadow, no-var, sort-vars*/
|
|
|
|
|
|
var $protobuf = __webpack_require__(/*! protobufjs/minimal */ "./node_modules/protobufjs/minimal.js");
|
|
|
|
// Common aliases
|
|
var $Reader = $protobuf.Reader, $Writer = $protobuf.Writer, $util = $protobuf.util;
|
|
|
|
// Exported root namespace
|
|
var $root = $protobuf.roots["default"] || ($protobuf.roots["default"] = {});
|
|
|
|
$root.onnx = (function() {
|
|
|
|
/**
|
|
* Namespace onnx.
|
|
* @exports onnx
|
|
* @namespace
|
|
*/
|
|
var onnx = {};
|
|
|
|
/**
|
|
* Version enum.
|
|
* @name onnx.Version
|
|
* @enum {string}
|
|
* @property {number} _START_VERSION=0 _START_VERSION value
|
|
* @property {number} IR_VERSION_2017_10_10=1 IR_VERSION_2017_10_10 value
|
|
* @property {number} IR_VERSION_2017_10_30=2 IR_VERSION_2017_10_30 value
|
|
* @property {number} IR_VERSION_2017_11_3=3 IR_VERSION_2017_11_3 value
|
|
* @property {number} IR_VERSION_2019_1_22=4 IR_VERSION_2019_1_22 value
|
|
* @property {number} IR_VERSION=5 IR_VERSION value
|
|
*/
|
|
onnx.Version = (function() {
|
|
var valuesById = {}, values = Object.create(valuesById);
|
|
values[valuesById[0] = "_START_VERSION"] = 0;
|
|
values[valuesById[1] = "IR_VERSION_2017_10_10"] = 1;
|
|
values[valuesById[2] = "IR_VERSION_2017_10_30"] = 2;
|
|
values[valuesById[3] = "IR_VERSION_2017_11_3"] = 3;
|
|
values[valuesById[4] = "IR_VERSION_2019_1_22"] = 4;
|
|
values[valuesById[5] = "IR_VERSION"] = 5;
|
|
return values;
|
|
})();
|
|
|
|
onnx.AttributeProto = (function() {
|
|
|
|
/**
|
|
* Properties of an AttributeProto.
|
|
* @memberof onnx
|
|
* @interface IAttributeProto
|
|
* @property {string|null} [name] AttributeProto name
|
|
* @property {string|null} [refAttrName] AttributeProto refAttrName
|
|
* @property {string|null} [docString] AttributeProto docString
|
|
* @property {onnx.AttributeProto.AttributeType|null} [type] AttributeProto type
|
|
* @property {number|null} [f] AttributeProto f
|
|
* @property {number|Long|null} [i] AttributeProto i
|
|
* @property {Uint8Array|null} [s] AttributeProto s
|
|
* @property {onnx.ITensorProto|null} [t] AttributeProto t
|
|
* @property {onnx.IGraphProto|null} [g] AttributeProto g
|
|
* @property {Array.<number>|null} [floats] AttributeProto floats
|
|
* @property {Array.<number|Long>|null} [ints] AttributeProto ints
|
|
* @property {Array.<Uint8Array>|null} [strings] AttributeProto strings
|
|
* @property {Array.<onnx.ITensorProto>|null} [tensors] AttributeProto tensors
|
|
* @property {Array.<onnx.IGraphProto>|null} [graphs] AttributeProto graphs
|
|
*/
|
|
|
|
/**
|
|
* Constructs a new AttributeProto.
|
|
* @memberof onnx
|
|
* @classdesc Represents an AttributeProto.
|
|
* @implements IAttributeProto
|
|
* @constructor
|
|
* @param {onnx.IAttributeProto=} [properties] Properties to set
|
|
*/
|
|
function AttributeProto(properties) {
|
|
this.floats = [];
|
|
this.ints = [];
|
|
this.strings = [];
|
|
this.tensors = [];
|
|
this.graphs = [];
|
|
if (properties)
|
|
for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
|
|
if (properties[keys[i]] != null)
|
|
this[keys[i]] = properties[keys[i]];
|
|
}
|
|
|
|
/**
|
|
* AttributeProto name.
|
|
* @member {string} name
|
|
* @memberof onnx.AttributeProto
|
|
* @instance
|
|
*/
|
|
AttributeProto.prototype.name = "";
|
|
|
|
/**
|
|
* AttributeProto refAttrName.
|
|
* @member {string} refAttrName
|
|
* @memberof onnx.AttributeProto
|
|
* @instance
|
|
*/
|
|
AttributeProto.prototype.refAttrName = "";
|
|
|
|
/**
|
|
* AttributeProto docString.
|
|
* @member {string} docString
|
|
* @memberof onnx.AttributeProto
|
|
* @instance
|
|
*/
|
|
AttributeProto.prototype.docString = "";
|
|
|
|
/**
|
|
* AttributeProto type.
|
|
* @member {onnx.AttributeProto.AttributeType} type
|
|
* @memberof onnx.AttributeProto
|
|
* @instance
|
|
*/
|
|
AttributeProto.prototype.type = 0;
|
|
|
|
/**
|
|
* AttributeProto f.
|
|
* @member {number} f
|
|
* @memberof onnx.AttributeProto
|
|
* @instance
|
|
*/
|
|
AttributeProto.prototype.f = 0;
|
|
|
|
/**
|
|
* AttributeProto i.
|
|
* @member {number|Long} i
|
|
* @memberof onnx.AttributeProto
|
|
* @instance
|
|
*/
|
|
AttributeProto.prototype.i = $util.Long ? $util.Long.fromBits(0,0,false) : 0;
|
|
|
|
/**
|
|
* AttributeProto s.
|
|
* @member {Uint8Array} s
|
|
* @memberof onnx.AttributeProto
|
|
* @instance
|
|
*/
|
|
AttributeProto.prototype.s = $util.newBuffer([]);
|
|
|
|
/**
|
|
* AttributeProto t.
|
|
* @member {onnx.ITensorProto|null|undefined} t
|
|
* @memberof onnx.AttributeProto
|
|
* @instance
|
|
*/
|
|
AttributeProto.prototype.t = null;
|
|
|
|
/**
|
|
* AttributeProto g.
|
|
* @member {onnx.IGraphProto|null|undefined} g
|
|
* @memberof onnx.AttributeProto
|
|
* @instance
|
|
*/
|
|
AttributeProto.prototype.g = null;
|
|
|
|
/**
|
|
* AttributeProto floats.
|
|
* @member {Array.<number>} floats
|
|
* @memberof onnx.AttributeProto
|
|
* @instance
|
|
*/
|
|
AttributeProto.prototype.floats = $util.emptyArray;
|
|
|
|
/**
|
|
* AttributeProto ints.
|
|
* @member {Array.<number|Long>} ints
|
|
* @memberof onnx.AttributeProto
|
|
* @instance
|
|
*/
|
|
AttributeProto.prototype.ints = $util.emptyArray;
|
|
|
|
/**
|
|
* AttributeProto strings.
|
|
* @member {Array.<Uint8Array>} strings
|
|
* @memberof onnx.AttributeProto
|
|
* @instance
|
|
*/
|
|
AttributeProto.prototype.strings = $util.emptyArray;
|
|
|
|
/**
|
|
* AttributeProto tensors.
|
|
* @member {Array.<onnx.ITensorProto>} tensors
|
|
* @memberof onnx.AttributeProto
|
|
* @instance
|
|
*/
|
|
AttributeProto.prototype.tensors = $util.emptyArray;
|
|
|
|
/**
|
|
* AttributeProto graphs.
|
|
* @member {Array.<onnx.IGraphProto>} graphs
|
|
* @memberof onnx.AttributeProto
|
|
* @instance
|
|
*/
|
|
AttributeProto.prototype.graphs = $util.emptyArray;
|
|
|
|
/**
|
|
* Creates a new AttributeProto instance using the specified properties.
|
|
* @function create
|
|
* @memberof onnx.AttributeProto
|
|
* @static
|
|
* @param {onnx.IAttributeProto=} [properties] Properties to set
|
|
* @returns {onnx.AttributeProto} AttributeProto instance
|
|
*/
|
|
AttributeProto.create = function create(properties) {
|
|
return new AttributeProto(properties);
|
|
};
|
|
|
|
/**
|
|
* Encodes the specified AttributeProto message. Does not implicitly {@link onnx.AttributeProto.verify|verify} messages.
|
|
* @function encode
|
|
* @memberof onnx.AttributeProto
|
|
* @static
|
|
* @param {onnx.IAttributeProto} message AttributeProto message or plain object to encode
|
|
* @param {$protobuf.Writer} [writer] Writer to encode to
|
|
* @returns {$protobuf.Writer} Writer
|
|
*/
|
|
AttributeProto.encode = function encode(message, writer) {
|
|
if (!writer)
|
|
writer = $Writer.create();
|
|
if (message.name != null && message.hasOwnProperty("name"))
|
|
writer.uint32(/* id 1, wireType 2 =*/10).string(message.name);
|
|
if (message.f != null && message.hasOwnProperty("f"))
|
|
writer.uint32(/* id 2, wireType 5 =*/21).float(message.f);
|
|
if (message.i != null && message.hasOwnProperty("i"))
|
|
writer.uint32(/* id 3, wireType 0 =*/24).int64(message.i);
|
|
if (message.s != null && message.hasOwnProperty("s"))
|
|
writer.uint32(/* id 4, wireType 2 =*/34).bytes(message.s);
|
|
if (message.t != null && message.hasOwnProperty("t"))
|
|
$root.onnx.TensorProto.encode(message.t, writer.uint32(/* id 5, wireType 2 =*/42).fork()).ldelim();
|
|
if (message.g != null && message.hasOwnProperty("g"))
|
|
$root.onnx.GraphProto.encode(message.g, writer.uint32(/* id 6, wireType 2 =*/50).fork()).ldelim();
|
|
if (message.floats != null && message.floats.length) {
|
|
writer.uint32(/* id 7, wireType 2 =*/58).fork();
|
|
for (var i = 0; i < message.floats.length; ++i)
|
|
writer.float(message.floats[i]);
|
|
writer.ldelim();
|
|
}
|
|
if (message.ints != null && message.ints.length) {
|
|
writer.uint32(/* id 8, wireType 2 =*/66).fork();
|
|
for (var i = 0; i < message.ints.length; ++i)
|
|
writer.int64(message.ints[i]);
|
|
writer.ldelim();
|
|
}
|
|
if (message.strings != null && message.strings.length)
|
|
for (var i = 0; i < message.strings.length; ++i)
|
|
writer.uint32(/* id 9, wireType 2 =*/74).bytes(message.strings[i]);
|
|
if (message.tensors != null && message.tensors.length)
|
|
for (var i = 0; i < message.tensors.length; ++i)
|
|
$root.onnx.TensorProto.encode(message.tensors[i], writer.uint32(/* id 10, wireType 2 =*/82).fork()).ldelim();
|
|
if (message.graphs != null && message.graphs.length)
|
|
for (var i = 0; i < message.graphs.length; ++i)
|
|
$root.onnx.GraphProto.encode(message.graphs[i], writer.uint32(/* id 11, wireType 2 =*/90).fork()).ldelim();
|
|
if (message.docString != null && message.hasOwnProperty("docString"))
|
|
writer.uint32(/* id 13, wireType 2 =*/106).string(message.docString);
|
|
if (message.type != null && message.hasOwnProperty("type"))
|
|
writer.uint32(/* id 20, wireType 0 =*/160).int32(message.type);
|
|
if (message.refAttrName != null && message.hasOwnProperty("refAttrName"))
|
|
writer.uint32(/* id 21, wireType 2 =*/170).string(message.refAttrName);
|
|
return writer;
|
|
};
|
|
|
|
/**
|
|
* Encodes the specified AttributeProto message, length delimited. Does not implicitly {@link onnx.AttributeProto.verify|verify} messages.
|
|
* @function encodeDelimited
|
|
* @memberof onnx.AttributeProto
|
|
* @static
|
|
* @param {onnx.IAttributeProto} message AttributeProto message or plain object to encode
|
|
* @param {$protobuf.Writer} [writer] Writer to encode to
|
|
* @returns {$protobuf.Writer} Writer
|
|
*/
|
|
AttributeProto.encodeDelimited = function encodeDelimited(message, writer) {
|
|
return this.encode(message, writer).ldelim();
|
|
};
|
|
|
|
/**
|
|
* Decodes an AttributeProto message from the specified reader or buffer.
|
|
* @function decode
|
|
* @memberof onnx.AttributeProto
|
|
* @static
|
|
* @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
|
|
* @param {number} [length] Message length if known beforehand
|
|
* @returns {onnx.AttributeProto} AttributeProto
|
|
* @throws {Error} If the payload is not a reader or valid buffer
|
|
* @throws {$protobuf.util.ProtocolError} If required fields are missing
|
|
*/
|
|
AttributeProto.decode = function decode(reader, length) {
|
|
if (!(reader instanceof $Reader))
|
|
reader = $Reader.create(reader);
|
|
var end = length === undefined ? reader.len : reader.pos + length, message = new $root.onnx.AttributeProto();
|
|
while (reader.pos < end) {
|
|
var tag = reader.uint32();
|
|
switch (tag >>> 3) {
|
|
case 1:
|
|
message.name = reader.string();
|
|
break;
|
|
case 21:
|
|
message.refAttrName = reader.string();
|
|
break;
|
|
case 13:
|
|
message.docString = reader.string();
|
|
break;
|
|
case 20:
|
|
message.type = reader.int32();
|
|
break;
|
|
case 2:
|
|
message.f = reader.float();
|
|
break;
|
|
case 3:
|
|
message.i = reader.int64();
|
|
break;
|
|
case 4:
|
|
message.s = reader.bytes();
|
|
break;
|
|
case 5:
|
|
message.t = $root.onnx.TensorProto.decode(reader, reader.uint32());
|
|
break;
|
|
case 6:
|
|
message.g = $root.onnx.GraphProto.decode(reader, reader.uint32());
|
|
break;
|
|
case 7:
|
|
if (!(message.floats && message.floats.length))
|
|
message.floats = [];
|
|
if ((tag & 7) === 2) {
|
|
var end2 = reader.uint32() + reader.pos;
|
|
while (reader.pos < end2)
|
|
message.floats.push(reader.float());
|
|
} else
|
|
message.floats.push(reader.float());
|
|
break;
|
|
case 8:
|
|
if (!(message.ints && message.ints.length))
|
|
message.ints = [];
|
|
if ((tag & 7) === 2) {
|
|
var end2 = reader.uint32() + reader.pos;
|
|
while (reader.pos < end2)
|
|
message.ints.push(reader.int64());
|
|
} else
|
|
message.ints.push(reader.int64());
|
|
break;
|
|
case 9:
|
|
if (!(message.strings && message.strings.length))
|
|
message.strings = [];
|
|
message.strings.push(reader.bytes());
|
|
break;
|
|
case 10:
|
|
if (!(message.tensors && message.tensors.length))
|
|
message.tensors = [];
|
|
message.tensors.push($root.onnx.TensorProto.decode(reader, reader.uint32()));
|
|
break;
|
|
case 11:
|
|
if (!(message.graphs && message.graphs.length))
|
|
message.graphs = [];
|
|
message.graphs.push($root.onnx.GraphProto.decode(reader, reader.uint32()));
|
|
break;
|
|
default:
|
|
reader.skipType(tag & 7);
|
|
break;
|
|
}
|
|
}
|
|
return message;
|
|
};
|
|
|
|
/**
|
|
* Decodes an AttributeProto message from the specified reader or buffer, length delimited.
|
|
* @function decodeDelimited
|
|
* @memberof onnx.AttributeProto
|
|
* @static
|
|
* @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
|
|
* @returns {onnx.AttributeProto} AttributeProto
|
|
* @throws {Error} If the payload is not a reader or valid buffer
|
|
* @throws {$protobuf.util.ProtocolError} If required fields are missing
|
|
*/
|
|
AttributeProto.decodeDelimited = function decodeDelimited(reader) {
|
|
if (!(reader instanceof $Reader))
|
|
reader = new $Reader(reader);
|
|
return this.decode(reader, reader.uint32());
|
|
};
|
|
|
|
/**
|
|
* Verifies an AttributeProto message.
|
|
* @function verify
|
|
* @memberof onnx.AttributeProto
|
|
* @static
|
|
* @param {Object.<string,*>} message Plain object to verify
|
|
* @returns {string|null} `null` if valid, otherwise the reason why it is not
|
|
*/
|
|
AttributeProto.verify = function verify(message) {
|
|
if (typeof message !== "object" || message === null)
|
|
return "object expected";
|
|
if (message.name != null && message.hasOwnProperty("name"))
|
|
if (!$util.isString(message.name))
|
|
return "name: string expected";
|
|
if (message.refAttrName != null && message.hasOwnProperty("refAttrName"))
|
|
if (!$util.isString(message.refAttrName))
|
|
return "refAttrName: string expected";
|
|
if (message.docString != null && message.hasOwnProperty("docString"))
|
|
if (!$util.isString(message.docString))
|
|
return "docString: string expected";
|
|
if (message.type != null && message.hasOwnProperty("type"))
|
|
switch (message.type) {
|
|
default:
|
|
return "type: enum value expected";
|
|
case 0:
|
|
case 1:
|
|
case 2:
|
|
case 3:
|
|
case 4:
|
|
case 5:
|
|
case 6:
|
|
case 7:
|
|
case 8:
|
|
case 9:
|
|
case 10:
|
|
break;
|
|
}
|
|
if (message.f != null && message.hasOwnProperty("f"))
|
|
if (typeof message.f !== "number")
|
|
return "f: number expected";
|
|
if (message.i != null && message.hasOwnProperty("i"))
|
|
if (!$util.isInteger(message.i) && !(message.i && $util.isInteger(message.i.low) && $util.isInteger(message.i.high)))
|
|
return "i: integer|Long expected";
|
|
if (message.s != null && message.hasOwnProperty("s"))
|
|
if (!(message.s && typeof message.s.length === "number" || $util.isString(message.s)))
|
|
return "s: buffer expected";
|
|
if (message.t != null && message.hasOwnProperty("t")) {
|
|
var error = $root.onnx.TensorProto.verify(message.t);
|
|
if (error)
|
|
return "t." + error;
|
|
}
|
|
if (message.g != null && message.hasOwnProperty("g")) {
|
|
var error = $root.onnx.GraphProto.verify(message.g);
|
|
if (error)
|
|
return "g." + error;
|
|
}
|
|
if (message.floats != null && message.hasOwnProperty("floats")) {
|
|
if (!Array.isArray(message.floats))
|
|
return "floats: array expected";
|
|
for (var i = 0; i < message.floats.length; ++i)
|
|
if (typeof message.floats[i] !== "number")
|
|
return "floats: number[] expected";
|
|
}
|
|
if (message.ints != null && message.hasOwnProperty("ints")) {
|
|
if (!Array.isArray(message.ints))
|
|
return "ints: array expected";
|
|
for (var i = 0; i < message.ints.length; ++i)
|
|
if (!$util.isInteger(message.ints[i]) && !(message.ints[i] && $util.isInteger(message.ints[i].low) && $util.isInteger(message.ints[i].high)))
|
|
return "ints: integer|Long[] expected";
|
|
}
|
|
if (message.strings != null && message.hasOwnProperty("strings")) {
|
|
if (!Array.isArray(message.strings))
|
|
return "strings: array expected";
|
|
for (var i = 0; i < message.strings.length; ++i)
|
|
if (!(message.strings[i] && typeof message.strings[i].length === "number" || $util.isString(message.strings[i])))
|
|
return "strings: buffer[] expected";
|
|
}
|
|
if (message.tensors != null && message.hasOwnProperty("tensors")) {
|
|
if (!Array.isArray(message.tensors))
|
|
return "tensors: array expected";
|
|
for (var i = 0; i < message.tensors.length; ++i) {
|
|
var error = $root.onnx.TensorProto.verify(message.tensors[i]);
|
|
if (error)
|
|
return "tensors." + error;
|
|
}
|
|
}
|
|
if (message.graphs != null && message.hasOwnProperty("graphs")) {
|
|
if (!Array.isArray(message.graphs))
|
|
return "graphs: array expected";
|
|
for (var i = 0; i < message.graphs.length; ++i) {
|
|
var error = $root.onnx.GraphProto.verify(message.graphs[i]);
|
|
if (error)
|
|
return "graphs." + error;
|
|
}
|
|
}
|
|
return null;
|
|
};
|
|
|
|
/**
|
|
* Creates an AttributeProto message from a plain object. Also converts values to their respective internal types.
|
|
* @function fromObject
|
|
* @memberof onnx.AttributeProto
|
|
* @static
|
|
* @param {Object.<string,*>} object Plain object
|
|
* @returns {onnx.AttributeProto} AttributeProto
|
|
*/
|
|
AttributeProto.fromObject = function fromObject(object) {
|
|
if (object instanceof $root.onnx.AttributeProto)
|
|
return object;
|
|
var message = new $root.onnx.AttributeProto();
|
|
if (object.name != null)
|
|
message.name = String(object.name);
|
|
if (object.refAttrName != null)
|
|
message.refAttrName = String(object.refAttrName);
|
|
if (object.docString != null)
|
|
message.docString = String(object.docString);
|
|
switch (object.type) {
|
|
case "UNDEFINED":
|
|
case 0:
|
|
message.type = 0;
|
|
break;
|
|
case "FLOAT":
|
|
case 1:
|
|
message.type = 1;
|
|
break;
|
|
case "INT":
|
|
case 2:
|
|
message.type = 2;
|
|
break;
|
|
case "STRING":
|
|
case 3:
|
|
message.type = 3;
|
|
break;
|
|
case "TENSOR":
|
|
case 4:
|
|
message.type = 4;
|
|
break;
|
|
case "GRAPH":
|
|
case 5:
|
|
message.type = 5;
|
|
break;
|
|
case "FLOATS":
|
|
case 6:
|
|
message.type = 6;
|
|
break;
|
|
case "INTS":
|
|
case 7:
|
|
message.type = 7;
|
|
break;
|
|
case "STRINGS":
|
|
case 8:
|
|
message.type = 8;
|
|
break;
|
|
case "TENSORS":
|
|
case 9:
|
|
message.type = 9;
|
|
break;
|
|
case "GRAPHS":
|
|
case 10:
|
|
message.type = 10;
|
|
break;
|
|
}
|
|
if (object.f != null)
|
|
message.f = Number(object.f);
|
|
if (object.i != null)
|
|
if ($util.Long)
|
|
(message.i = $util.Long.fromValue(object.i)).unsigned = false;
|
|
else if (typeof object.i === "string")
|
|
message.i = parseInt(object.i, 10);
|
|
else if (typeof object.i === "number")
|
|
message.i = object.i;
|
|
else if (typeof object.i === "object")
|
|
message.i = new $util.LongBits(object.i.low >>> 0, object.i.high >>> 0).toNumber();
|
|
if (object.s != null)
|
|
if (typeof object.s === "string")
|
|
$util.base64.decode(object.s, message.s = $util.newBuffer($util.base64.length(object.s)), 0);
|
|
else if (object.s.length)
|
|
message.s = object.s;
|
|
if (object.t != null) {
|
|
if (typeof object.t !== "object")
|
|
throw TypeError(".onnx.AttributeProto.t: object expected");
|
|
message.t = $root.onnx.TensorProto.fromObject(object.t);
|
|
}
|
|
if (object.g != null) {
|
|
if (typeof object.g !== "object")
|
|
throw TypeError(".onnx.AttributeProto.g: object expected");
|
|
message.g = $root.onnx.GraphProto.fromObject(object.g);
|
|
}
|
|
if (object.floats) {
|
|
if (!Array.isArray(object.floats))
|
|
throw TypeError(".onnx.AttributeProto.floats: array expected");
|
|
message.floats = [];
|
|
for (var i = 0; i < object.floats.length; ++i)
|
|
message.floats[i] = Number(object.floats[i]);
|
|
}
|
|
if (object.ints) {
|
|
if (!Array.isArray(object.ints))
|
|
throw TypeError(".onnx.AttributeProto.ints: array expected");
|
|
message.ints = [];
|
|
for (var i = 0; i < object.ints.length; ++i)
|
|
if ($util.Long)
|
|
(message.ints[i] = $util.Long.fromValue(object.ints[i])).unsigned = false;
|
|
else if (typeof object.ints[i] === "string")
|
|
message.ints[i] = parseInt(object.ints[i], 10);
|
|
else if (typeof object.ints[i] === "number")
|
|
message.ints[i] = object.ints[i];
|
|
else if (typeof object.ints[i] === "object")
|
|
message.ints[i] = new $util.LongBits(object.ints[i].low >>> 0, object.ints[i].high >>> 0).toNumber();
|
|
}
|
|
if (object.strings) {
|
|
if (!Array.isArray(object.strings))
|
|
throw TypeError(".onnx.AttributeProto.strings: array expected");
|
|
message.strings = [];
|
|
for (var i = 0; i < object.strings.length; ++i)
|
|
if (typeof object.strings[i] === "string")
|
|
$util.base64.decode(object.strings[i], message.strings[i] = $util.newBuffer($util.base64.length(object.strings[i])), 0);
|
|
else if (object.strings[i].length)
|
|
message.strings[i] = object.strings[i];
|
|
}
|
|
if (object.tensors) {
|
|
if (!Array.isArray(object.tensors))
|
|
throw TypeError(".onnx.AttributeProto.tensors: array expected");
|
|
message.tensors = [];
|
|
for (var i = 0; i < object.tensors.length; ++i) {
|
|
if (typeof object.tensors[i] !== "object")
|
|
throw TypeError(".onnx.AttributeProto.tensors: object expected");
|
|
message.tensors[i] = $root.onnx.TensorProto.fromObject(object.tensors[i]);
|
|
}
|
|
}
|
|
if (object.graphs) {
|
|
if (!Array.isArray(object.graphs))
|
|
throw TypeError(".onnx.AttributeProto.graphs: array expected");
|
|
message.graphs = [];
|
|
for (var i = 0; i < object.graphs.length; ++i) {
|
|
if (typeof object.graphs[i] !== "object")
|
|
throw TypeError(".onnx.AttributeProto.graphs: object expected");
|
|
message.graphs[i] = $root.onnx.GraphProto.fromObject(object.graphs[i]);
|
|
}
|
|
}
|
|
return message;
|
|
};
|
|
|
|
/**
|
|
* Creates a plain object from an AttributeProto message. Also converts values to other types if specified.
|
|
* @function toObject
|
|
* @memberof onnx.AttributeProto
|
|
* @static
|
|
* @param {onnx.AttributeProto} message AttributeProto
|
|
* @param {$protobuf.IConversionOptions} [options] Conversion options
|
|
* @returns {Object.<string,*>} Plain object
|
|
*/
|
|
AttributeProto.toObject = function toObject(message, options) {
|
|
if (!options)
|
|
options = {};
|
|
var object = {};
|
|
if (options.arrays || options.defaults) {
|
|
object.floats = [];
|
|
object.ints = [];
|
|
object.strings = [];
|
|
object.tensors = [];
|
|
object.graphs = [];
|
|
}
|
|
if (options.defaults) {
|
|
object.name = "";
|
|
object.f = 0;
|
|
if ($util.Long) {
|
|
var long = new $util.Long(0, 0, false);
|
|
object.i = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
|
|
} else
|
|
object.i = options.longs === String ? "0" : 0;
|
|
if (options.bytes === String)
|
|
object.s = "";
|
|
else {
|
|
object.s = [];
|
|
if (options.bytes !== Array)
|
|
object.s = $util.newBuffer(object.s);
|
|
}
|
|
object.t = null;
|
|
object.g = null;
|
|
object.docString = "";
|
|
object.type = options.enums === String ? "UNDEFINED" : 0;
|
|
object.refAttrName = "";
|
|
}
|
|
if (message.name != null && message.hasOwnProperty("name"))
|
|
object.name = message.name;
|
|
if (message.f != null && message.hasOwnProperty("f"))
|
|
object.f = options.json && !isFinite(message.f) ? String(message.f) : message.f;
|
|
if (message.i != null && message.hasOwnProperty("i"))
|
|
if (typeof message.i === "number")
|
|
object.i = options.longs === String ? String(message.i) : message.i;
|
|
else
|
|
object.i = options.longs === String ? $util.Long.prototype.toString.call(message.i) : options.longs === Number ? new $util.LongBits(message.i.low >>> 0, message.i.high >>> 0).toNumber() : message.i;
|
|
if (message.s != null && message.hasOwnProperty("s"))
|
|
object.s = options.bytes === String ? $util.base64.encode(message.s, 0, message.s.length) : options.bytes === Array ? Array.prototype.slice.call(message.s) : message.s;
|
|
if (message.t != null && message.hasOwnProperty("t"))
|
|
object.t = $root.onnx.TensorProto.toObject(message.t, options);
|
|
if (message.g != null && message.hasOwnProperty("g"))
|
|
object.g = $root.onnx.GraphProto.toObject(message.g, options);
|
|
if (message.floats && message.floats.length) {
|
|
object.floats = [];
|
|
for (var j = 0; j < message.floats.length; ++j)
|
|
object.floats[j] = options.json && !isFinite(message.floats[j]) ? String(message.floats[j]) : message.floats[j];
|
|
}
|
|
if (message.ints && message.ints.length) {
|
|
object.ints = [];
|
|
for (var j = 0; j < message.ints.length; ++j)
|
|
if (typeof message.ints[j] === "number")
|
|
object.ints[j] = options.longs === String ? String(message.ints[j]) : message.ints[j];
|
|
else
|
|
object.ints[j] = options.longs === String ? $util.Long.prototype.toString.call(message.ints[j]) : options.longs === Number ? new $util.LongBits(message.ints[j].low >>> 0, message.ints[j].high >>> 0).toNumber() : message.ints[j];
|
|
}
|
|
if (message.strings && message.strings.length) {
|
|
object.strings = [];
|
|
for (var j = 0; j < message.strings.length; ++j)
|
|
object.strings[j] = options.bytes === String ? $util.base64.encode(message.strings[j], 0, message.strings[j].length) : options.bytes === Array ? Array.prototype.slice.call(message.strings[j]) : message.strings[j];
|
|
}
|
|
if (message.tensors && message.tensors.length) {
|
|
object.tensors = [];
|
|
for (var j = 0; j < message.tensors.length; ++j)
|
|
object.tensors[j] = $root.onnx.TensorProto.toObject(message.tensors[j], options);
|
|
}
|
|
if (message.graphs && message.graphs.length) {
|
|
object.graphs = [];
|
|
for (var j = 0; j < message.graphs.length; ++j)
|
|
object.graphs[j] = $root.onnx.GraphProto.toObject(message.graphs[j], options);
|
|
}
|
|
if (message.docString != null && message.hasOwnProperty("docString"))
|
|
object.docString = message.docString;
|
|
if (message.type != null && message.hasOwnProperty("type"))
|
|
object.type = options.enums === String ? $root.onnx.AttributeProto.AttributeType[message.type] : message.type;
|
|
if (message.refAttrName != null && message.hasOwnProperty("refAttrName"))
|
|
object.refAttrName = message.refAttrName;
|
|
return object;
|
|
};
|
|
|
|
/**
|
|
* Converts this AttributeProto to JSON.
|
|
* @function toJSON
|
|
* @memberof onnx.AttributeProto
|
|
* @instance
|
|
* @returns {Object.<string,*>} JSON object
|
|
*/
|
|
AttributeProto.prototype.toJSON = function toJSON() {
|
|
return this.constructor.toObject(this, $protobuf.util.toJSONOptions);
|
|
};
|
|
|
|
/**
|
|
* AttributeType enum.
|
|
* @name onnx.AttributeProto.AttributeType
|
|
* @enum {string}
|
|
* @property {number} UNDEFINED=0 UNDEFINED value
|
|
* @property {number} FLOAT=1 FLOAT value
|
|
* @property {number} INT=2 INT value
|
|
* @property {number} STRING=3 STRING value
|
|
* @property {number} TENSOR=4 TENSOR value
|
|
* @property {number} GRAPH=5 GRAPH value
|
|
* @property {number} FLOATS=6 FLOATS value
|
|
* @property {number} INTS=7 INTS value
|
|
* @property {number} STRINGS=8 STRINGS value
|
|
* @property {number} TENSORS=9 TENSORS value
|
|
* @property {number} GRAPHS=10 GRAPHS value
|
|
*/
|
|
AttributeProto.AttributeType = (function() {
|
|
var valuesById = {}, values = Object.create(valuesById);
|
|
values[valuesById[0] = "UNDEFINED"] = 0;
|
|
values[valuesById[1] = "FLOAT"] = 1;
|
|
values[valuesById[2] = "INT"] = 2;
|
|
values[valuesById[3] = "STRING"] = 3;
|
|
values[valuesById[4] = "TENSOR"] = 4;
|
|
values[valuesById[5] = "GRAPH"] = 5;
|
|
values[valuesById[6] = "FLOATS"] = 6;
|
|
values[valuesById[7] = "INTS"] = 7;
|
|
values[valuesById[8] = "STRINGS"] = 8;
|
|
values[valuesById[9] = "TENSORS"] = 9;
|
|
values[valuesById[10] = "GRAPHS"] = 10;
|
|
return values;
|
|
})();
|
|
|
|
return AttributeProto;
|
|
})();
|
|
|
|
onnx.ValueInfoProto = (function() {
|
|
|
|
/**
|
|
* Properties of a ValueInfoProto.
|
|
* @memberof onnx
|
|
* @interface IValueInfoProto
|
|
* @property {string|null} [name] ValueInfoProto name
|
|
* @property {onnx.ITypeProto|null} [type] ValueInfoProto type
|
|
* @property {string|null} [docString] ValueInfoProto docString
|
|
*/
|
|
|
|
/**
|
|
* Constructs a new ValueInfoProto.
|
|
* @memberof onnx
|
|
* @classdesc Represents a ValueInfoProto.
|
|
* @implements IValueInfoProto
|
|
* @constructor
|
|
* @param {onnx.IValueInfoProto=} [properties] Properties to set
|
|
*/
|
|
function ValueInfoProto(properties) {
|
|
if (properties)
|
|
for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
|
|
if (properties[keys[i]] != null)
|
|
this[keys[i]] = properties[keys[i]];
|
|
}
|
|
|
|
/**
|
|
* ValueInfoProto name.
|
|
* @member {string} name
|
|
* @memberof onnx.ValueInfoProto
|
|
* @instance
|
|
*/
|
|
ValueInfoProto.prototype.name = "";
|
|
|
|
/**
|
|
* ValueInfoProto type.
|
|
* @member {onnx.ITypeProto|null|undefined} type
|
|
* @memberof onnx.ValueInfoProto
|
|
* @instance
|
|
*/
|
|
ValueInfoProto.prototype.type = null;
|
|
|
|
/**
|
|
* ValueInfoProto docString.
|
|
* @member {string} docString
|
|
* @memberof onnx.ValueInfoProto
|
|
* @instance
|
|
*/
|
|
ValueInfoProto.prototype.docString = "";
|
|
|
|
/**
|
|
* Creates a new ValueInfoProto instance using the specified properties.
|
|
* @function create
|
|
* @memberof onnx.ValueInfoProto
|
|
* @static
|
|
* @param {onnx.IValueInfoProto=} [properties] Properties to set
|
|
* @returns {onnx.ValueInfoProto} ValueInfoProto instance
|
|
*/
|
|
ValueInfoProto.create = function create(properties) {
|
|
return new ValueInfoProto(properties);
|
|
};
|
|
|
|
/**
|
|
* Encodes the specified ValueInfoProto message. Does not implicitly {@link onnx.ValueInfoProto.verify|verify} messages.
|
|
* @function encode
|
|
* @memberof onnx.ValueInfoProto
|
|
* @static
|
|
* @param {onnx.IValueInfoProto} message ValueInfoProto message or plain object to encode
|
|
* @param {$protobuf.Writer} [writer] Writer to encode to
|
|
* @returns {$protobuf.Writer} Writer
|
|
*/
|
|
ValueInfoProto.encode = function encode(message, writer) {
|
|
if (!writer)
|
|
writer = $Writer.create();
|
|
if (message.name != null && message.hasOwnProperty("name"))
|
|
writer.uint32(/* id 1, wireType 2 =*/10).string(message.name);
|
|
if (message.type != null && message.hasOwnProperty("type"))
|
|
$root.onnx.TypeProto.encode(message.type, writer.uint32(/* id 2, wireType 2 =*/18).fork()).ldelim();
|
|
if (message.docString != null && message.hasOwnProperty("docString"))
|
|
writer.uint32(/* id 3, wireType 2 =*/26).string(message.docString);
|
|
return writer;
|
|
};
|
|
|
|
/**
|
|
* Encodes the specified ValueInfoProto message, length delimited. Does not implicitly {@link onnx.ValueInfoProto.verify|verify} messages.
|
|
* @function encodeDelimited
|
|
* @memberof onnx.ValueInfoProto
|
|
* @static
|
|
* @param {onnx.IValueInfoProto} message ValueInfoProto message or plain object to encode
|
|
* @param {$protobuf.Writer} [writer] Writer to encode to
|
|
* @returns {$protobuf.Writer} Writer
|
|
*/
|
|
ValueInfoProto.encodeDelimited = function encodeDelimited(message, writer) {
|
|
return this.encode(message, writer).ldelim();
|
|
};
|
|
|
|
/**
|
|
* Decodes a ValueInfoProto message from the specified reader or buffer.
|
|
* @function decode
|
|
* @memberof onnx.ValueInfoProto
|
|
* @static
|
|
* @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
|
|
* @param {number} [length] Message length if known beforehand
|
|
* @returns {onnx.ValueInfoProto} ValueInfoProto
|
|
* @throws {Error} If the payload is not a reader or valid buffer
|
|
* @throws {$protobuf.util.ProtocolError} If required fields are missing
|
|
*/
|
|
ValueInfoProto.decode = function decode(reader, length) {
|
|
if (!(reader instanceof $Reader))
|
|
reader = $Reader.create(reader);
|
|
var end = length === undefined ? reader.len : reader.pos + length, message = new $root.onnx.ValueInfoProto();
|
|
while (reader.pos < end) {
|
|
var tag = reader.uint32();
|
|
switch (tag >>> 3) {
|
|
case 1:
|
|
message.name = reader.string();
|
|
break;
|
|
case 2:
|
|
message.type = $root.onnx.TypeProto.decode(reader, reader.uint32());
|
|
break;
|
|
case 3:
|
|
message.docString = reader.string();
|
|
break;
|
|
default:
|
|
reader.skipType(tag & 7);
|
|
break;
|
|
}
|
|
}
|
|
return message;
|
|
};
|
|
|
|
/**
|
|
* Decodes a ValueInfoProto message from the specified reader or buffer, length delimited.
|
|
* @function decodeDelimited
|
|
* @memberof onnx.ValueInfoProto
|
|
* @static
|
|
* @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
|
|
* @returns {onnx.ValueInfoProto} ValueInfoProto
|
|
* @throws {Error} If the payload is not a reader or valid buffer
|
|
* @throws {$protobuf.util.ProtocolError} If required fields are missing
|
|
*/
|
|
ValueInfoProto.decodeDelimited = function decodeDelimited(reader) {
|
|
if (!(reader instanceof $Reader))
|
|
reader = new $Reader(reader);
|
|
return this.decode(reader, reader.uint32());
|
|
};
|
|
|
|
/**
|
|
* Verifies a ValueInfoProto message.
|
|
* @function verify
|
|
* @memberof onnx.ValueInfoProto
|
|
* @static
|
|
* @param {Object.<string,*>} message Plain object to verify
|
|
* @returns {string|null} `null` if valid, otherwise the reason why it is not
|
|
*/
|
|
ValueInfoProto.verify = function verify(message) {
|
|
if (typeof message !== "object" || message === null)
|
|
return "object expected";
|
|
if (message.name != null && message.hasOwnProperty("name"))
|
|
if (!$util.isString(message.name))
|
|
return "name: string expected";
|
|
if (message.type != null && message.hasOwnProperty("type")) {
|
|
var error = $root.onnx.TypeProto.verify(message.type);
|
|
if (error)
|
|
return "type." + error;
|
|
}
|
|
if (message.docString != null && message.hasOwnProperty("docString"))
|
|
if (!$util.isString(message.docString))
|
|
return "docString: string expected";
|
|
return null;
|
|
};
|
|
|
|
/**
|
|
* Creates a ValueInfoProto message from a plain object. Also converts values to their respective internal types.
|
|
* @function fromObject
|
|
* @memberof onnx.ValueInfoProto
|
|
* @static
|
|
* @param {Object.<string,*>} object Plain object
|
|
* @returns {onnx.ValueInfoProto} ValueInfoProto
|
|
*/
|
|
ValueInfoProto.fromObject = function fromObject(object) {
|
|
if (object instanceof $root.onnx.ValueInfoProto)
|
|
return object;
|
|
var message = new $root.onnx.ValueInfoProto();
|
|
if (object.name != null)
|
|
message.name = String(object.name);
|
|
if (object.type != null) {
|
|
if (typeof object.type !== "object")
|
|
throw TypeError(".onnx.ValueInfoProto.type: object expected");
|
|
message.type = $root.onnx.TypeProto.fromObject(object.type);
|
|
}
|
|
if (object.docString != null)
|
|
message.docString = String(object.docString);
|
|
return message;
|
|
};
|
|
|
|
/**
|
|
* Creates a plain object from a ValueInfoProto message. Also converts values to other types if specified.
|
|
* @function toObject
|
|
* @memberof onnx.ValueInfoProto
|
|
* @static
|
|
* @param {onnx.ValueInfoProto} message ValueInfoProto
|
|
* @param {$protobuf.IConversionOptions} [options] Conversion options
|
|
* @returns {Object.<string,*>} Plain object
|
|
*/
|
|
ValueInfoProto.toObject = function toObject(message, options) {
|
|
if (!options)
|
|
options = {};
|
|
var object = {};
|
|
if (options.defaults) {
|
|
object.name = "";
|
|
object.type = null;
|
|
object.docString = "";
|
|
}
|
|
if (message.name != null && message.hasOwnProperty("name"))
|
|
object.name = message.name;
|
|
if (message.type != null && message.hasOwnProperty("type"))
|
|
object.type = $root.onnx.TypeProto.toObject(message.type, options);
|
|
if (message.docString != null && message.hasOwnProperty("docString"))
|
|
object.docString = message.docString;
|
|
return object;
|
|
};
|
|
|
|
/**
|
|
* Converts this ValueInfoProto to JSON.
|
|
* @function toJSON
|
|
* @memberof onnx.ValueInfoProto
|
|
* @instance
|
|
* @returns {Object.<string,*>} JSON object
|
|
*/
|
|
ValueInfoProto.prototype.toJSON = function toJSON() {
|
|
return this.constructor.toObject(this, $protobuf.util.toJSONOptions);
|
|
};
|
|
|
|
return ValueInfoProto;
|
|
})();
|
|
|
|
onnx.NodeProto = (function() {
|
|
|
|
/**
|
|
* Properties of a NodeProto.
|
|
* @memberof onnx
|
|
* @interface INodeProto
|
|
* @property {Array.<string>|null} [input] NodeProto input
|
|
* @property {Array.<string>|null} [output] NodeProto output
|
|
* @property {string|null} [name] NodeProto name
|
|
* @property {string|null} [opType] NodeProto opType
|
|
* @property {string|null} [domain] NodeProto domain
|
|
* @property {Array.<onnx.IAttributeProto>|null} [attribute] NodeProto attribute
|
|
* @property {string|null} [docString] NodeProto docString
|
|
*/
|
|
|
|
/**
|
|
* Constructs a new NodeProto.
|
|
* @memberof onnx
|
|
* @classdesc Represents a NodeProto.
|
|
* @implements INodeProto
|
|
* @constructor
|
|
* @param {onnx.INodeProto=} [properties] Properties to set
|
|
*/
|
|
function NodeProto(properties) {
|
|
this.input = [];
|
|
this.output = [];
|
|
this.attribute = [];
|
|
if (properties)
|
|
for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
|
|
if (properties[keys[i]] != null)
|
|
this[keys[i]] = properties[keys[i]];
|
|
}
|
|
|
|
/**
|
|
* NodeProto input.
|
|
* @member {Array.<string>} input
|
|
* @memberof onnx.NodeProto
|
|
* @instance
|
|
*/
|
|
NodeProto.prototype.input = $util.emptyArray;
|
|
|
|
/**
|
|
* NodeProto output.
|
|
* @member {Array.<string>} output
|
|
* @memberof onnx.NodeProto
|
|
* @instance
|
|
*/
|
|
NodeProto.prototype.output = $util.emptyArray;
|
|
|
|
/**
|
|
* NodeProto name.
|
|
* @member {string} name
|
|
* @memberof onnx.NodeProto
|
|
* @instance
|
|
*/
|
|
NodeProto.prototype.name = "";
|
|
|
|
/**
|
|
* NodeProto opType.
|
|
* @member {string} opType
|
|
* @memberof onnx.NodeProto
|
|
* @instance
|
|
*/
|
|
NodeProto.prototype.opType = "";
|
|
|
|
/**
|
|
* NodeProto domain.
|
|
* @member {string} domain
|
|
* @memberof onnx.NodeProto
|
|
* @instance
|
|
*/
|
|
NodeProto.prototype.domain = "";
|
|
|
|
/**
|
|
* NodeProto attribute.
|
|
* @member {Array.<onnx.IAttributeProto>} attribute
|
|
* @memberof onnx.NodeProto
|
|
* @instance
|
|
*/
|
|
NodeProto.prototype.attribute = $util.emptyArray;
|
|
|
|
/**
|
|
* NodeProto docString.
|
|
* @member {string} docString
|
|
* @memberof onnx.NodeProto
|
|
* @instance
|
|
*/
|
|
NodeProto.prototype.docString = "";
|
|
|
|
/**
|
|
* Creates a new NodeProto instance using the specified properties.
|
|
* @function create
|
|
* @memberof onnx.NodeProto
|
|
* @static
|
|
* @param {onnx.INodeProto=} [properties] Properties to set
|
|
* @returns {onnx.NodeProto} NodeProto instance
|
|
*/
|
|
NodeProto.create = function create(properties) {
|
|
return new NodeProto(properties);
|
|
};
|
|
|
|
/**
|
|
* Encodes the specified NodeProto message. Does not implicitly {@link onnx.NodeProto.verify|verify} messages.
|
|
* @function encode
|
|
* @memberof onnx.NodeProto
|
|
* @static
|
|
* @param {onnx.INodeProto} message NodeProto message or plain object to encode
|
|
* @param {$protobuf.Writer} [writer] Writer to encode to
|
|
* @returns {$protobuf.Writer} Writer
|
|
*/
|
|
NodeProto.encode = function encode(message, writer) {
|
|
if (!writer)
|
|
writer = $Writer.create();
|
|
if (message.input != null && message.input.length)
|
|
for (var i = 0; i < message.input.length; ++i)
|
|
writer.uint32(/* id 1, wireType 2 =*/10).string(message.input[i]);
|
|
if (message.output != null && message.output.length)
|
|
for (var i = 0; i < message.output.length; ++i)
|
|
writer.uint32(/* id 2, wireType 2 =*/18).string(message.output[i]);
|
|
if (message.name != null && message.hasOwnProperty("name"))
|
|
writer.uint32(/* id 3, wireType 2 =*/26).string(message.name);
|
|
if (message.opType != null && message.hasOwnProperty("opType"))
|
|
writer.uint32(/* id 4, wireType 2 =*/34).string(message.opType);
|
|
if (message.attribute != null && message.attribute.length)
|
|
for (var i = 0; i < message.attribute.length; ++i)
|
|
$root.onnx.AttributeProto.encode(message.attribute[i], writer.uint32(/* id 5, wireType 2 =*/42).fork()).ldelim();
|
|
if (message.docString != null && message.hasOwnProperty("docString"))
|
|
writer.uint32(/* id 6, wireType 2 =*/50).string(message.docString);
|
|
if (message.domain != null && message.hasOwnProperty("domain"))
|
|
writer.uint32(/* id 7, wireType 2 =*/58).string(message.domain);
|
|
return writer;
|
|
};
|
|
|
|
/**
|
|
* Encodes the specified NodeProto message, length delimited. Does not implicitly {@link onnx.NodeProto.verify|verify} messages.
|
|
* @function encodeDelimited
|
|
* @memberof onnx.NodeProto
|
|
* @static
|
|
* @param {onnx.INodeProto} message NodeProto message or plain object to encode
|
|
* @param {$protobuf.Writer} [writer] Writer to encode to
|
|
* @returns {$protobuf.Writer} Writer
|
|
*/
|
|
NodeProto.encodeDelimited = function encodeDelimited(message, writer) {
|
|
return this.encode(message, writer).ldelim();
|
|
};
|
|
|
|
/**
|
|
* Decodes a NodeProto message from the specified reader or buffer.
|
|
* @function decode
|
|
* @memberof onnx.NodeProto
|
|
* @static
|
|
* @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
|
|
* @param {number} [length] Message length if known beforehand
|
|
* @returns {onnx.NodeProto} NodeProto
|
|
* @throws {Error} If the payload is not a reader or valid buffer
|
|
* @throws {$protobuf.util.ProtocolError} If required fields are missing
|
|
*/
|
|
NodeProto.decode = function decode(reader, length) {
|
|
if (!(reader instanceof $Reader))
|
|
reader = $Reader.create(reader);
|
|
var end = length === undefined ? reader.len : reader.pos + length, message = new $root.onnx.NodeProto();
|
|
while (reader.pos < end) {
|
|
var tag = reader.uint32();
|
|
switch (tag >>> 3) {
|
|
case 1:
|
|
if (!(message.input && message.input.length))
|
|
message.input = [];
|
|
message.input.push(reader.string());
|
|
break;
|
|
case 2:
|
|
if (!(message.output && message.output.length))
|
|
message.output = [];
|
|
message.output.push(reader.string());
|
|
break;
|
|
case 3:
|
|
message.name = reader.string();
|
|
break;
|
|
case 4:
|
|
message.opType = reader.string();
|
|
break;
|
|
case 7:
|
|
message.domain = reader.string();
|
|
break;
|
|
case 5:
|
|
if (!(message.attribute && message.attribute.length))
|
|
message.attribute = [];
|
|
message.attribute.push($root.onnx.AttributeProto.decode(reader, reader.uint32()));
|
|
break;
|
|
case 6:
|
|
message.docString = reader.string();
|
|
break;
|
|
default:
|
|
reader.skipType(tag & 7);
|
|
break;
|
|
}
|
|
}
|
|
return message;
|
|
};
|
|
|
|
/**
|
|
* Decodes a NodeProto message from the specified reader or buffer, length delimited.
|
|
* @function decodeDelimited
|
|
* @memberof onnx.NodeProto
|
|
* @static
|
|
* @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
|
|
* @returns {onnx.NodeProto} NodeProto
|
|
* @throws {Error} If the payload is not a reader or valid buffer
|
|
* @throws {$protobuf.util.ProtocolError} If required fields are missing
|
|
*/
|
|
NodeProto.decodeDelimited = function decodeDelimited(reader) {
|
|
if (!(reader instanceof $Reader))
|
|
reader = new $Reader(reader);
|
|
return this.decode(reader, reader.uint32());
|
|
};
|
|
|
|
/**
|
|
* Verifies a NodeProto message.
|
|
* @function verify
|
|
* @memberof onnx.NodeProto
|
|
* @static
|
|
* @param {Object.<string,*>} message Plain object to verify
|
|
* @returns {string|null} `null` if valid, otherwise the reason why it is not
|
|
*/
|
|
NodeProto.verify = function verify(message) {
|
|
if (typeof message !== "object" || message === null)
|
|
return "object expected";
|
|
if (message.input != null && message.hasOwnProperty("input")) {
|
|
if (!Array.isArray(message.input))
|
|
return "input: array expected";
|
|
for (var i = 0; i < message.input.length; ++i)
|
|
if (!$util.isString(message.input[i]))
|
|
return "input: string[] expected";
|
|
}
|
|
if (message.output != null && message.hasOwnProperty("output")) {
|
|
if (!Array.isArray(message.output))
|
|
return "output: array expected";
|
|
for (var i = 0; i < message.output.length; ++i)
|
|
if (!$util.isString(message.output[i]))
|
|
return "output: string[] expected";
|
|
}
|
|
if (message.name != null && message.hasOwnProperty("name"))
|
|
if (!$util.isString(message.name))
|
|
return "name: string expected";
|
|
if (message.opType != null && message.hasOwnProperty("opType"))
|
|
if (!$util.isString(message.opType))
|
|
return "opType: string expected";
|
|
if (message.domain != null && message.hasOwnProperty("domain"))
|
|
if (!$util.isString(message.domain))
|
|
return "domain: string expected";
|
|
if (message.attribute != null && message.hasOwnProperty("attribute")) {
|
|
if (!Array.isArray(message.attribute))
|
|
return "attribute: array expected";
|
|
for (var i = 0; i < message.attribute.length; ++i) {
|
|
var error = $root.onnx.AttributeProto.verify(message.attribute[i]);
|
|
if (error)
|
|
return "attribute." + error;
|
|
}
|
|
}
|
|
if (message.docString != null && message.hasOwnProperty("docString"))
|
|
if (!$util.isString(message.docString))
|
|
return "docString: string expected";
|
|
return null;
|
|
};
|
|
|
|
/**
|
|
* Creates a NodeProto message from a plain object. Also converts values to their respective internal types.
|
|
* @function fromObject
|
|
* @memberof onnx.NodeProto
|
|
* @static
|
|
* @param {Object.<string,*>} object Plain object
|
|
* @returns {onnx.NodeProto} NodeProto
|
|
*/
|
|
NodeProto.fromObject = function fromObject(object) {
|
|
if (object instanceof $root.onnx.NodeProto)
|
|
return object;
|
|
var message = new $root.onnx.NodeProto();
|
|
if (object.input) {
|
|
if (!Array.isArray(object.input))
|
|
throw TypeError(".onnx.NodeProto.input: array expected");
|
|
message.input = [];
|
|
for (var i = 0; i < object.input.length; ++i)
|
|
message.input[i] = String(object.input[i]);
|
|
}
|
|
if (object.output) {
|
|
if (!Array.isArray(object.output))
|
|
throw TypeError(".onnx.NodeProto.output: array expected");
|
|
message.output = [];
|
|
for (var i = 0; i < object.output.length; ++i)
|
|
message.output[i] = String(object.output[i]);
|
|
}
|
|
if (object.name != null)
|
|
message.name = String(object.name);
|
|
if (object.opType != null)
|
|
message.opType = String(object.opType);
|
|
if (object.domain != null)
|
|
message.domain = String(object.domain);
|
|
if (object.attribute) {
|
|
if (!Array.isArray(object.attribute))
|
|
throw TypeError(".onnx.NodeProto.attribute: array expected");
|
|
message.attribute = [];
|
|
for (var i = 0; i < object.attribute.length; ++i) {
|
|
if (typeof object.attribute[i] !== "object")
|
|
throw TypeError(".onnx.NodeProto.attribute: object expected");
|
|
message.attribute[i] = $root.onnx.AttributeProto.fromObject(object.attribute[i]);
|
|
}
|
|
}
|
|
if (object.docString != null)
|
|
message.docString = String(object.docString);
|
|
return message;
|
|
};
|
|
|
|
/**
|
|
* Creates a plain object from a NodeProto message. Also converts values to other types if specified.
|
|
* @function toObject
|
|
* @memberof onnx.NodeProto
|
|
* @static
|
|
* @param {onnx.NodeProto} message NodeProto
|
|
* @param {$protobuf.IConversionOptions} [options] Conversion options
|
|
* @returns {Object.<string,*>} Plain object
|
|
*/
|
|
NodeProto.toObject = function toObject(message, options) {
|
|
if (!options)
|
|
options = {};
|
|
var object = {};
|
|
if (options.arrays || options.defaults) {
|
|
object.input = [];
|
|
object.output = [];
|
|
object.attribute = [];
|
|
}
|
|
if (options.defaults) {
|
|
object.name = "";
|
|
object.opType = "";
|
|
object.docString = "";
|
|
object.domain = "";
|
|
}
|
|
if (message.input && message.input.length) {
|
|
object.input = [];
|
|
for (var j = 0; j < message.input.length; ++j)
|
|
object.input[j] = message.input[j];
|
|
}
|
|
if (message.output && message.output.length) {
|
|
object.output = [];
|
|
for (var j = 0; j < message.output.length; ++j)
|
|
object.output[j] = message.output[j];
|
|
}
|
|
if (message.name != null && message.hasOwnProperty("name"))
|
|
object.name = message.name;
|
|
if (message.opType != null && message.hasOwnProperty("opType"))
|
|
object.opType = message.opType;
|
|
if (message.attribute && message.attribute.length) {
|
|
object.attribute = [];
|
|
for (var j = 0; j < message.attribute.length; ++j)
|
|
object.attribute[j] = $root.onnx.AttributeProto.toObject(message.attribute[j], options);
|
|
}
|
|
if (message.docString != null && message.hasOwnProperty("docString"))
|
|
object.docString = message.docString;
|
|
if (message.domain != null && message.hasOwnProperty("domain"))
|
|
object.domain = message.domain;
|
|
return object;
|
|
};
|
|
|
|
/**
|
|
* Converts this NodeProto to JSON.
|
|
* @function toJSON
|
|
* @memberof onnx.NodeProto
|
|
* @instance
|
|
* @returns {Object.<string,*>} JSON object
|
|
*/
|
|
NodeProto.prototype.toJSON = function toJSON() {
|
|
return this.constructor.toObject(this, $protobuf.util.toJSONOptions);
|
|
};
|
|
|
|
return NodeProto;
|
|
})();
|
|
|
|
onnx.ModelProto = (function() {
|
|
|
|
/**
|
|
* Properties of a ModelProto.
|
|
* @memberof onnx
|
|
* @interface IModelProto
|
|
* @property {number|Long|null} [irVersion] ModelProto irVersion
|
|
* @property {Array.<onnx.IOperatorSetIdProto>|null} [opsetImport] ModelProto opsetImport
|
|
* @property {string|null} [producerName] ModelProto producerName
|
|
* @property {string|null} [producerVersion] ModelProto producerVersion
|
|
* @property {string|null} [domain] ModelProto domain
|
|
* @property {number|Long|null} [modelVersion] ModelProto modelVersion
|
|
* @property {string|null} [docString] ModelProto docString
|
|
* @property {onnx.IGraphProto|null} [graph] ModelProto graph
|
|
* @property {Array.<onnx.IStringStringEntryProto>|null} [metadataProps] ModelProto metadataProps
|
|
*/
|
|
|
|
/**
|
|
* Constructs a new ModelProto.
|
|
* @memberof onnx
|
|
* @classdesc Represents a ModelProto.
|
|
* @implements IModelProto
|
|
* @constructor
|
|
* @param {onnx.IModelProto=} [properties] Properties to set
|
|
*/
|
|
function ModelProto(properties) {
|
|
this.opsetImport = [];
|
|
this.metadataProps = [];
|
|
if (properties)
|
|
for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
|
|
if (properties[keys[i]] != null)
|
|
this[keys[i]] = properties[keys[i]];
|
|
}
|
|
|
|
/**
|
|
* ModelProto irVersion.
|
|
* @member {number|Long} irVersion
|
|
* @memberof onnx.ModelProto
|
|
* @instance
|
|
*/
|
|
ModelProto.prototype.irVersion = $util.Long ? $util.Long.fromBits(0,0,false) : 0;
|
|
|
|
/**
|
|
* ModelProto opsetImport.
|
|
* @member {Array.<onnx.IOperatorSetIdProto>} opsetImport
|
|
* @memberof onnx.ModelProto
|
|
* @instance
|
|
*/
|
|
ModelProto.prototype.opsetImport = $util.emptyArray;
|
|
|
|
/**
|
|
* ModelProto producerName.
|
|
* @member {string} producerName
|
|
* @memberof onnx.ModelProto
|
|
* @instance
|
|
*/
|
|
ModelProto.prototype.producerName = "";
|
|
|
|
/**
|
|
* ModelProto producerVersion.
|
|
* @member {string} producerVersion
|
|
* @memberof onnx.ModelProto
|
|
* @instance
|
|
*/
|
|
ModelProto.prototype.producerVersion = "";
|
|
|
|
/**
|
|
* ModelProto domain.
|
|
* @member {string} domain
|
|
* @memberof onnx.ModelProto
|
|
* @instance
|
|
*/
|
|
ModelProto.prototype.domain = "";
|
|
|
|
/**
|
|
* ModelProto modelVersion.
|
|
* @member {number|Long} modelVersion
|
|
* @memberof onnx.ModelProto
|
|
* @instance
|
|
*/
|
|
ModelProto.prototype.modelVersion = $util.Long ? $util.Long.fromBits(0,0,false) : 0;
|
|
|
|
/**
|
|
* ModelProto docString.
|
|
* @member {string} docString
|
|
* @memberof onnx.ModelProto
|
|
* @instance
|
|
*/
|
|
ModelProto.prototype.docString = "";
|
|
|
|
/**
|
|
* ModelProto graph.
|
|
* @member {onnx.IGraphProto|null|undefined} graph
|
|
* @memberof onnx.ModelProto
|
|
* @instance
|
|
*/
|
|
ModelProto.prototype.graph = null;
|
|
|
|
/**
|
|
* ModelProto metadataProps.
|
|
* @member {Array.<onnx.IStringStringEntryProto>} metadataProps
|
|
* @memberof onnx.ModelProto
|
|
* @instance
|
|
*/
|
|
ModelProto.prototype.metadataProps = $util.emptyArray;
|
|
|
|
/**
|
|
* Creates a new ModelProto instance using the specified properties.
|
|
* @function create
|
|
* @memberof onnx.ModelProto
|
|
* @static
|
|
* @param {onnx.IModelProto=} [properties] Properties to set
|
|
* @returns {onnx.ModelProto} ModelProto instance
|
|
*/
|
|
ModelProto.create = function create(properties) {
|
|
return new ModelProto(properties);
|
|
};
|
|
|
|
/**
|
|
* Encodes the specified ModelProto message. Does not implicitly {@link onnx.ModelProto.verify|verify} messages.
|
|
* @function encode
|
|
* @memberof onnx.ModelProto
|
|
* @static
|
|
* @param {onnx.IModelProto} message ModelProto message or plain object to encode
|
|
* @param {$protobuf.Writer} [writer] Writer to encode to
|
|
* @returns {$protobuf.Writer} Writer
|
|
*/
|
|
ModelProto.encode = function encode(message, writer) {
|
|
if (!writer)
|
|
writer = $Writer.create();
|
|
if (message.irVersion != null && message.hasOwnProperty("irVersion"))
|
|
writer.uint32(/* id 1, wireType 0 =*/8).int64(message.irVersion);
|
|
if (message.producerName != null && message.hasOwnProperty("producerName"))
|
|
writer.uint32(/* id 2, wireType 2 =*/18).string(message.producerName);
|
|
if (message.producerVersion != null && message.hasOwnProperty("producerVersion"))
|
|
writer.uint32(/* id 3, wireType 2 =*/26).string(message.producerVersion);
|
|
if (message.domain != null && message.hasOwnProperty("domain"))
|
|
writer.uint32(/* id 4, wireType 2 =*/34).string(message.domain);
|
|
if (message.modelVersion != null && message.hasOwnProperty("modelVersion"))
|
|
writer.uint32(/* id 5, wireType 0 =*/40).int64(message.modelVersion);
|
|
if (message.docString != null && message.hasOwnProperty("docString"))
|
|
writer.uint32(/* id 6, wireType 2 =*/50).string(message.docString);
|
|
if (message.graph != null && message.hasOwnProperty("graph"))
|
|
$root.onnx.GraphProto.encode(message.graph, writer.uint32(/* id 7, wireType 2 =*/58).fork()).ldelim();
|
|
if (message.opsetImport != null && message.opsetImport.length)
|
|
for (var i = 0; i < message.opsetImport.length; ++i)
|
|
$root.onnx.OperatorSetIdProto.encode(message.opsetImport[i], writer.uint32(/* id 8, wireType 2 =*/66).fork()).ldelim();
|
|
if (message.metadataProps != null && message.metadataProps.length)
|
|
for (var i = 0; i < message.metadataProps.length; ++i)
|
|
$root.onnx.StringStringEntryProto.encode(message.metadataProps[i], writer.uint32(/* id 14, wireType 2 =*/114).fork()).ldelim();
|
|
return writer;
|
|
};
|
|
|
|
/**
|
|
* Encodes the specified ModelProto message, length delimited. Does not implicitly {@link onnx.ModelProto.verify|verify} messages.
|
|
* @function encodeDelimited
|
|
* @memberof onnx.ModelProto
|
|
* @static
|
|
* @param {onnx.IModelProto} message ModelProto message or plain object to encode
|
|
* @param {$protobuf.Writer} [writer] Writer to encode to
|
|
* @returns {$protobuf.Writer} Writer
|
|
*/
|
|
ModelProto.encodeDelimited = function encodeDelimited(message, writer) {
|
|
return this.encode(message, writer).ldelim();
|
|
};
|
|
|
|
/**
|
|
* Decodes a ModelProto message from the specified reader or buffer.
|
|
* @function decode
|
|
* @memberof onnx.ModelProto
|
|
* @static
|
|
* @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
|
|
* @param {number} [length] Message length if known beforehand
|
|
* @returns {onnx.ModelProto} ModelProto
|
|
* @throws {Error} If the payload is not a reader or valid buffer
|
|
* @throws {$protobuf.util.ProtocolError} If required fields are missing
|
|
*/
|
|
ModelProto.decode = function decode(reader, length) {
|
|
if (!(reader instanceof $Reader))
|
|
reader = $Reader.create(reader);
|
|
var end = length === undefined ? reader.len : reader.pos + length, message = new $root.onnx.ModelProto();
|
|
while (reader.pos < end) {
|
|
var tag = reader.uint32();
|
|
switch (tag >>> 3) {
|
|
case 1:
|
|
message.irVersion = reader.int64();
|
|
break;
|
|
case 8:
|
|
if (!(message.opsetImport && message.opsetImport.length))
|
|
message.opsetImport = [];
|
|
message.opsetImport.push($root.onnx.OperatorSetIdProto.decode(reader, reader.uint32()));
|
|
break;
|
|
case 2:
|
|
message.producerName = reader.string();
|
|
break;
|
|
case 3:
|
|
message.producerVersion = reader.string();
|
|
break;
|
|
case 4:
|
|
message.domain = reader.string();
|
|
break;
|
|
case 5:
|
|
message.modelVersion = reader.int64();
|
|
break;
|
|
case 6:
|
|
message.docString = reader.string();
|
|
break;
|
|
case 7:
|
|
message.graph = $root.onnx.GraphProto.decode(reader, reader.uint32());
|
|
break;
|
|
case 14:
|
|
if (!(message.metadataProps && message.metadataProps.length))
|
|
message.metadataProps = [];
|
|
message.metadataProps.push($root.onnx.StringStringEntryProto.decode(reader, reader.uint32()));
|
|
break;
|
|
default:
|
|
reader.skipType(tag & 7);
|
|
break;
|
|
}
|
|
}
|
|
return message;
|
|
};
|
|
|
|
/**
|
|
* Decodes a ModelProto message from the specified reader or buffer, length delimited.
|
|
* @function decodeDelimited
|
|
* @memberof onnx.ModelProto
|
|
* @static
|
|
* @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
|
|
* @returns {onnx.ModelProto} ModelProto
|
|
* @throws {Error} If the payload is not a reader or valid buffer
|
|
* @throws {$protobuf.util.ProtocolError} If required fields are missing
|
|
*/
|
|
ModelProto.decodeDelimited = function decodeDelimited(reader) {
|
|
if (!(reader instanceof $Reader))
|
|
reader = new $Reader(reader);
|
|
return this.decode(reader, reader.uint32());
|
|
};
|
|
|
|
/**
|
|
* Verifies a ModelProto message.
|
|
* @function verify
|
|
* @memberof onnx.ModelProto
|
|
* @static
|
|
* @param {Object.<string,*>} message Plain object to verify
|
|
* @returns {string|null} `null` if valid, otherwise the reason why it is not
|
|
*/
|
|
ModelProto.verify = function verify(message) {
|
|
if (typeof message !== "object" || message === null)
|
|
return "object expected";
|
|
if (message.irVersion != null && message.hasOwnProperty("irVersion"))
|
|
if (!$util.isInteger(message.irVersion) && !(message.irVersion && $util.isInteger(message.irVersion.low) && $util.isInteger(message.irVersion.high)))
|
|
return "irVersion: integer|Long expected";
|
|
if (message.opsetImport != null && message.hasOwnProperty("opsetImport")) {
|
|
if (!Array.isArray(message.opsetImport))
|
|
return "opsetImport: array expected";
|
|
for (var i = 0; i < message.opsetImport.length; ++i) {
|
|
var error = $root.onnx.OperatorSetIdProto.verify(message.opsetImport[i]);
|
|
if (error)
|
|
return "opsetImport." + error;
|
|
}
|
|
}
|
|
if (message.producerName != null && message.hasOwnProperty("producerName"))
|
|
if (!$util.isString(message.producerName))
|
|
return "producerName: string expected";
|
|
if (message.producerVersion != null && message.hasOwnProperty("producerVersion"))
|
|
if (!$util.isString(message.producerVersion))
|
|
return "producerVersion: string expected";
|
|
if (message.domain != null && message.hasOwnProperty("domain"))
|
|
if (!$util.isString(message.domain))
|
|
return "domain: string expected";
|
|
if (message.modelVersion != null && message.hasOwnProperty("modelVersion"))
|
|
if (!$util.isInteger(message.modelVersion) && !(message.modelVersion && $util.isInteger(message.modelVersion.low) && $util.isInteger(message.modelVersion.high)))
|
|
return "modelVersion: integer|Long expected";
|
|
if (message.docString != null && message.hasOwnProperty("docString"))
|
|
if (!$util.isString(message.docString))
|
|
return "docString: string expected";
|
|
if (message.graph != null && message.hasOwnProperty("graph")) {
|
|
var error = $root.onnx.GraphProto.verify(message.graph);
|
|
if (error)
|
|
return "graph." + error;
|
|
}
|
|
if (message.metadataProps != null && message.hasOwnProperty("metadataProps")) {
|
|
if (!Array.isArray(message.metadataProps))
|
|
return "metadataProps: array expected";
|
|
for (var i = 0; i < message.metadataProps.length; ++i) {
|
|
var error = $root.onnx.StringStringEntryProto.verify(message.metadataProps[i]);
|
|
if (error)
|
|
return "metadataProps." + error;
|
|
}
|
|
}
|
|
return null;
|
|
};
|
|
|
|
/**
|
|
* Creates a ModelProto message from a plain object. Also converts values to their respective internal types.
|
|
* @function fromObject
|
|
* @memberof onnx.ModelProto
|
|
* @static
|
|
* @param {Object.<string,*>} object Plain object
|
|
* @returns {onnx.ModelProto} ModelProto
|
|
*/
|
|
ModelProto.fromObject = function fromObject(object) {
|
|
if (object instanceof $root.onnx.ModelProto)
|
|
return object;
|
|
var message = new $root.onnx.ModelProto();
|
|
if (object.irVersion != null)
|
|
if ($util.Long)
|
|
(message.irVersion = $util.Long.fromValue(object.irVersion)).unsigned = false;
|
|
else if (typeof object.irVersion === "string")
|
|
message.irVersion = parseInt(object.irVersion, 10);
|
|
else if (typeof object.irVersion === "number")
|
|
message.irVersion = object.irVersion;
|
|
else if (typeof object.irVersion === "object")
|
|
message.irVersion = new $util.LongBits(object.irVersion.low >>> 0, object.irVersion.high >>> 0).toNumber();
|
|
if (object.opsetImport) {
|
|
if (!Array.isArray(object.opsetImport))
|
|
throw TypeError(".onnx.ModelProto.opsetImport: array expected");
|
|
message.opsetImport = [];
|
|
for (var i = 0; i < object.opsetImport.length; ++i) {
|
|
if (typeof object.opsetImport[i] !== "object")
|
|
throw TypeError(".onnx.ModelProto.opsetImport: object expected");
|
|
message.opsetImport[i] = $root.onnx.OperatorSetIdProto.fromObject(object.opsetImport[i]);
|
|
}
|
|
}
|
|
if (object.producerName != null)
|
|
message.producerName = String(object.producerName);
|
|
if (object.producerVersion != null)
|
|
message.producerVersion = String(object.producerVersion);
|
|
if (object.domain != null)
|
|
message.domain = String(object.domain);
|
|
if (object.modelVersion != null)
|
|
if ($util.Long)
|
|
(message.modelVersion = $util.Long.fromValue(object.modelVersion)).unsigned = false;
|
|
else if (typeof object.modelVersion === "string")
|
|
message.modelVersion = parseInt(object.modelVersion, 10);
|
|
else if (typeof object.modelVersion === "number")
|
|
message.modelVersion = object.modelVersion;
|
|
else if (typeof object.modelVersion === "object")
|
|
message.modelVersion = new $util.LongBits(object.modelVersion.low >>> 0, object.modelVersion.high >>> 0).toNumber();
|
|
if (object.docString != null)
|
|
message.docString = String(object.docString);
|
|
if (object.graph != null) {
|
|
if (typeof object.graph !== "object")
|
|
throw TypeError(".onnx.ModelProto.graph: object expected");
|
|
message.graph = $root.onnx.GraphProto.fromObject(object.graph);
|
|
}
|
|
if (object.metadataProps) {
|
|
if (!Array.isArray(object.metadataProps))
|
|
throw TypeError(".onnx.ModelProto.metadataProps: array expected");
|
|
message.metadataProps = [];
|
|
for (var i = 0; i < object.metadataProps.length; ++i) {
|
|
if (typeof object.metadataProps[i] !== "object")
|
|
throw TypeError(".onnx.ModelProto.metadataProps: object expected");
|
|
message.metadataProps[i] = $root.onnx.StringStringEntryProto.fromObject(object.metadataProps[i]);
|
|
}
|
|
}
|
|
return message;
|
|
};
|
|
|
|
/**
|
|
* Creates a plain object from a ModelProto message. Also converts values to other types if specified.
|
|
* @function toObject
|
|
* @memberof onnx.ModelProto
|
|
* @static
|
|
* @param {onnx.ModelProto} message ModelProto
|
|
* @param {$protobuf.IConversionOptions} [options] Conversion options
|
|
* @returns {Object.<string,*>} Plain object
|
|
*/
|
|
ModelProto.toObject = function toObject(message, options) {
|
|
if (!options)
|
|
options = {};
|
|
var object = {};
|
|
if (options.arrays || options.defaults) {
|
|
object.opsetImport = [];
|
|
object.metadataProps = [];
|
|
}
|
|
if (options.defaults) {
|
|
if ($util.Long) {
|
|
var long = new $util.Long(0, 0, false);
|
|
object.irVersion = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
|
|
} else
|
|
object.irVersion = options.longs === String ? "0" : 0;
|
|
object.producerName = "";
|
|
object.producerVersion = "";
|
|
object.domain = "";
|
|
if ($util.Long) {
|
|
var long = new $util.Long(0, 0, false);
|
|
object.modelVersion = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
|
|
} else
|
|
object.modelVersion = options.longs === String ? "0" : 0;
|
|
object.docString = "";
|
|
object.graph = null;
|
|
}
|
|
if (message.irVersion != null && message.hasOwnProperty("irVersion"))
|
|
if (typeof message.irVersion === "number")
|
|
object.irVersion = options.longs === String ? String(message.irVersion) : message.irVersion;
|
|
else
|
|
object.irVersion = options.longs === String ? $util.Long.prototype.toString.call(message.irVersion) : options.longs === Number ? new $util.LongBits(message.irVersion.low >>> 0, message.irVersion.high >>> 0).toNumber() : message.irVersion;
|
|
if (message.producerName != null && message.hasOwnProperty("producerName"))
|
|
object.producerName = message.producerName;
|
|
if (message.producerVersion != null && message.hasOwnProperty("producerVersion"))
|
|
object.producerVersion = message.producerVersion;
|
|
if (message.domain != null && message.hasOwnProperty("domain"))
|
|
object.domain = message.domain;
|
|
if (message.modelVersion != null && message.hasOwnProperty("modelVersion"))
|
|
if (typeof message.modelVersion === "number")
|
|
object.modelVersion = options.longs === String ? String(message.modelVersion) : message.modelVersion;
|
|
else
|
|
object.modelVersion = options.longs === String ? $util.Long.prototype.toString.call(message.modelVersion) : options.longs === Number ? new $util.LongBits(message.modelVersion.low >>> 0, message.modelVersion.high >>> 0).toNumber() : message.modelVersion;
|
|
if (message.docString != null && message.hasOwnProperty("docString"))
|
|
object.docString = message.docString;
|
|
if (message.graph != null && message.hasOwnProperty("graph"))
|
|
object.graph = $root.onnx.GraphProto.toObject(message.graph, options);
|
|
if (message.opsetImport && message.opsetImport.length) {
|
|
object.opsetImport = [];
|
|
for (var j = 0; j < message.opsetImport.length; ++j)
|
|
object.opsetImport[j] = $root.onnx.OperatorSetIdProto.toObject(message.opsetImport[j], options);
|
|
}
|
|
if (message.metadataProps && message.metadataProps.length) {
|
|
object.metadataProps = [];
|
|
for (var j = 0; j < message.metadataProps.length; ++j)
|
|
object.metadataProps[j] = $root.onnx.StringStringEntryProto.toObject(message.metadataProps[j], options);
|
|
}
|
|
return object;
|
|
};
|
|
|
|
/**
|
|
* Converts this ModelProto to JSON.
|
|
* @function toJSON
|
|
* @memberof onnx.ModelProto
|
|
* @instance
|
|
* @returns {Object.<string,*>} JSON object
|
|
*/
|
|
ModelProto.prototype.toJSON = function toJSON() {
|
|
return this.constructor.toObject(this, $protobuf.util.toJSONOptions);
|
|
};
|
|
|
|
return ModelProto;
|
|
})();
|
|
|
|
onnx.StringStringEntryProto = (function() {
|
|
|
|
/**
|
|
* Properties of a StringStringEntryProto.
|
|
* @memberof onnx
|
|
* @interface IStringStringEntryProto
|
|
* @property {string|null} [key] StringStringEntryProto key
|
|
* @property {string|null} [value] StringStringEntryProto value
|
|
*/
|
|
|
|
/**
|
|
* Constructs a new StringStringEntryProto.
|
|
* @memberof onnx
|
|
* @classdesc Represents a StringStringEntryProto.
|
|
* @implements IStringStringEntryProto
|
|
* @constructor
|
|
* @param {onnx.IStringStringEntryProto=} [properties] Properties to set
|
|
*/
|
|
function StringStringEntryProto(properties) {
|
|
if (properties)
|
|
for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
|
|
if (properties[keys[i]] != null)
|
|
this[keys[i]] = properties[keys[i]];
|
|
}
|
|
|
|
/**
|
|
* StringStringEntryProto key.
|
|
* @member {string} key
|
|
* @memberof onnx.StringStringEntryProto
|
|
* @instance
|
|
*/
|
|
StringStringEntryProto.prototype.key = "";
|
|
|
|
/**
|
|
* StringStringEntryProto value.
|
|
* @member {string} value
|
|
* @memberof onnx.StringStringEntryProto
|
|
* @instance
|
|
*/
|
|
StringStringEntryProto.prototype.value = "";
|
|
|
|
/**
|
|
* Creates a new StringStringEntryProto instance using the specified properties.
|
|
* @function create
|
|
* @memberof onnx.StringStringEntryProto
|
|
* @static
|
|
* @param {onnx.IStringStringEntryProto=} [properties] Properties to set
|
|
* @returns {onnx.StringStringEntryProto} StringStringEntryProto instance
|
|
*/
|
|
StringStringEntryProto.create = function create(properties) {
|
|
return new StringStringEntryProto(properties);
|
|
};
|
|
|
|
/**
|
|
* Encodes the specified StringStringEntryProto message. Does not implicitly {@link onnx.StringStringEntryProto.verify|verify} messages.
|
|
* @function encode
|
|
* @memberof onnx.StringStringEntryProto
|
|
* @static
|
|
* @param {onnx.IStringStringEntryProto} message StringStringEntryProto message or plain object to encode
|
|
* @param {$protobuf.Writer} [writer] Writer to encode to
|
|
* @returns {$protobuf.Writer} Writer
|
|
*/
|
|
StringStringEntryProto.encode = function encode(message, writer) {
|
|
if (!writer)
|
|
writer = $Writer.create();
|
|
if (message.key != null && message.hasOwnProperty("key"))
|
|
writer.uint32(/* id 1, wireType 2 =*/10).string(message.key);
|
|
if (message.value != null && message.hasOwnProperty("value"))
|
|
writer.uint32(/* id 2, wireType 2 =*/18).string(message.value);
|
|
return writer;
|
|
};
|
|
|
|
/**
|
|
* Encodes the specified StringStringEntryProto message, length delimited. Does not implicitly {@link onnx.StringStringEntryProto.verify|verify} messages.
|
|
* @function encodeDelimited
|
|
* @memberof onnx.StringStringEntryProto
|
|
* @static
|
|
* @param {onnx.IStringStringEntryProto} message StringStringEntryProto message or plain object to encode
|
|
* @param {$protobuf.Writer} [writer] Writer to encode to
|
|
* @returns {$protobuf.Writer} Writer
|
|
*/
|
|
StringStringEntryProto.encodeDelimited = function encodeDelimited(message, writer) {
|
|
return this.encode(message, writer).ldelim();
|
|
};
|
|
|
|
/**
|
|
* Decodes a StringStringEntryProto message from the specified reader or buffer.
|
|
* @function decode
|
|
* @memberof onnx.StringStringEntryProto
|
|
* @static
|
|
* @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
|
|
* @param {number} [length] Message length if known beforehand
|
|
* @returns {onnx.StringStringEntryProto} StringStringEntryProto
|
|
* @throws {Error} If the payload is not a reader or valid buffer
|
|
* @throws {$protobuf.util.ProtocolError} If required fields are missing
|
|
*/
|
|
StringStringEntryProto.decode = function decode(reader, length) {
|
|
if (!(reader instanceof $Reader))
|
|
reader = $Reader.create(reader);
|
|
var end = length === undefined ? reader.len : reader.pos + length, message = new $root.onnx.StringStringEntryProto();
|
|
while (reader.pos < end) {
|
|
var tag = reader.uint32();
|
|
switch (tag >>> 3) {
|
|
case 1:
|
|
message.key = reader.string();
|
|
break;
|
|
case 2:
|
|
message.value = reader.string();
|
|
break;
|
|
default:
|
|
reader.skipType(tag & 7);
|
|
break;
|
|
}
|
|
}
|
|
return message;
|
|
};
|
|
|
|
/**
|
|
* Decodes a StringStringEntryProto message from the specified reader or buffer, length delimited.
|
|
* @function decodeDelimited
|
|
* @memberof onnx.StringStringEntryProto
|
|
* @static
|
|
* @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
|
|
* @returns {onnx.StringStringEntryProto} StringStringEntryProto
|
|
* @throws {Error} If the payload is not a reader or valid buffer
|
|
* @throws {$protobuf.util.ProtocolError} If required fields are missing
|
|
*/
|
|
StringStringEntryProto.decodeDelimited = function decodeDelimited(reader) {
|
|
if (!(reader instanceof $Reader))
|
|
reader = new $Reader(reader);
|
|
return this.decode(reader, reader.uint32());
|
|
};
|
|
|
|
/**
|
|
* Verifies a StringStringEntryProto message.
|
|
* @function verify
|
|
* @memberof onnx.StringStringEntryProto
|
|
* @static
|
|
* @param {Object.<string,*>} message Plain object to verify
|
|
* @returns {string|null} `null` if valid, otherwise the reason why it is not
|
|
*/
|
|
StringStringEntryProto.verify = function verify(message) {
|
|
if (typeof message !== "object" || message === null)
|
|
return "object expected";
|
|
if (message.key != null && message.hasOwnProperty("key"))
|
|
if (!$util.isString(message.key))
|
|
return "key: string expected";
|
|
if (message.value != null && message.hasOwnProperty("value"))
|
|
if (!$util.isString(message.value))
|
|
return "value: string expected";
|
|
return null;
|
|
};
|
|
|
|
/**
|
|
* Creates a StringStringEntryProto message from a plain object. Also converts values to their respective internal types.
|
|
* @function fromObject
|
|
* @memberof onnx.StringStringEntryProto
|
|
* @static
|
|
* @param {Object.<string,*>} object Plain object
|
|
* @returns {onnx.StringStringEntryProto} StringStringEntryProto
|
|
*/
|
|
StringStringEntryProto.fromObject = function fromObject(object) {
|
|
if (object instanceof $root.onnx.StringStringEntryProto)
|
|
return object;
|
|
var message = new $root.onnx.StringStringEntryProto();
|
|
if (object.key != null)
|
|
message.key = String(object.key);
|
|
if (object.value != null)
|
|
message.value = String(object.value);
|
|
return message;
|
|
};
|
|
|
|
/**
|
|
* Creates a plain object from a StringStringEntryProto message. Also converts values to other types if specified.
|
|
* @function toObject
|
|
* @memberof onnx.StringStringEntryProto
|
|
* @static
|
|
* @param {onnx.StringStringEntryProto} message StringStringEntryProto
|
|
* @param {$protobuf.IConversionOptions} [options] Conversion options
|
|
* @returns {Object.<string,*>} Plain object
|
|
*/
|
|
StringStringEntryProto.toObject = function toObject(message, options) {
|
|
if (!options)
|
|
options = {};
|
|
var object = {};
|
|
if (options.defaults) {
|
|
object.key = "";
|
|
object.value = "";
|
|
}
|
|
if (message.key != null && message.hasOwnProperty("key"))
|
|
object.key = message.key;
|
|
if (message.value != null && message.hasOwnProperty("value"))
|
|
object.value = message.value;
|
|
return object;
|
|
};
|
|
|
|
/**
|
|
* Converts this StringStringEntryProto to JSON.
|
|
* @function toJSON
|
|
* @memberof onnx.StringStringEntryProto
|
|
* @instance
|
|
* @returns {Object.<string,*>} JSON object
|
|
*/
|
|
StringStringEntryProto.prototype.toJSON = function toJSON() {
|
|
return this.constructor.toObject(this, $protobuf.util.toJSONOptions);
|
|
};
|
|
|
|
return StringStringEntryProto;
|
|
})();
|
|
|
|
onnx.TensorAnnotation = (function() {
|
|
|
|
/**
|
|
* Properties of a TensorAnnotation.
|
|
* @memberof onnx
|
|
* @interface ITensorAnnotation
|
|
* @property {string|null} [tensorName] TensorAnnotation tensorName
|
|
* @property {Array.<onnx.IStringStringEntryProto>|null} [quantParameterTensorNames] TensorAnnotation quantParameterTensorNames
|
|
*/
|
|
|
|
/**
|
|
* Constructs a new TensorAnnotation.
|
|
* @memberof onnx
|
|
* @classdesc Represents a TensorAnnotation.
|
|
* @implements ITensorAnnotation
|
|
* @constructor
|
|
* @param {onnx.ITensorAnnotation=} [properties] Properties to set
|
|
*/
|
|
function TensorAnnotation(properties) {
|
|
this.quantParameterTensorNames = [];
|
|
if (properties)
|
|
for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
|
|
if (properties[keys[i]] != null)
|
|
this[keys[i]] = properties[keys[i]];
|
|
}
|
|
|
|
/**
|
|
* TensorAnnotation tensorName.
|
|
* @member {string} tensorName
|
|
* @memberof onnx.TensorAnnotation
|
|
* @instance
|
|
*/
|
|
TensorAnnotation.prototype.tensorName = "";
|
|
|
|
/**
|
|
* TensorAnnotation quantParameterTensorNames.
|
|
* @member {Array.<onnx.IStringStringEntryProto>} quantParameterTensorNames
|
|
* @memberof onnx.TensorAnnotation
|
|
* @instance
|
|
*/
|
|
TensorAnnotation.prototype.quantParameterTensorNames = $util.emptyArray;
|
|
|
|
/**
|
|
* Creates a new TensorAnnotation instance using the specified properties.
|
|
* @function create
|
|
* @memberof onnx.TensorAnnotation
|
|
* @static
|
|
* @param {onnx.ITensorAnnotation=} [properties] Properties to set
|
|
* @returns {onnx.TensorAnnotation} TensorAnnotation instance
|
|
*/
|
|
TensorAnnotation.create = function create(properties) {
|
|
return new TensorAnnotation(properties);
|
|
};
|
|
|
|
/**
|
|
* Encodes the specified TensorAnnotation message. Does not implicitly {@link onnx.TensorAnnotation.verify|verify} messages.
|
|
* @function encode
|
|
* @memberof onnx.TensorAnnotation
|
|
* @static
|
|
* @param {onnx.ITensorAnnotation} message TensorAnnotation message or plain object to encode
|
|
* @param {$protobuf.Writer} [writer] Writer to encode to
|
|
* @returns {$protobuf.Writer} Writer
|
|
*/
|
|
TensorAnnotation.encode = function encode(message, writer) {
|
|
if (!writer)
|
|
writer = $Writer.create();
|
|
if (message.tensorName != null && message.hasOwnProperty("tensorName"))
|
|
writer.uint32(/* id 1, wireType 2 =*/10).string(message.tensorName);
|
|
if (message.quantParameterTensorNames != null && message.quantParameterTensorNames.length)
|
|
for (var i = 0; i < message.quantParameterTensorNames.length; ++i)
|
|
$root.onnx.StringStringEntryProto.encode(message.quantParameterTensorNames[i], writer.uint32(/* id 2, wireType 2 =*/18).fork()).ldelim();
|
|
return writer;
|
|
};
|
|
|
|
/**
|
|
* Encodes the specified TensorAnnotation message, length delimited. Does not implicitly {@link onnx.TensorAnnotation.verify|verify} messages.
|
|
* @function encodeDelimited
|
|
* @memberof onnx.TensorAnnotation
|
|
* @static
|
|
* @param {onnx.ITensorAnnotation} message TensorAnnotation message or plain object to encode
|
|
* @param {$protobuf.Writer} [writer] Writer to encode to
|
|
* @returns {$protobuf.Writer} Writer
|
|
*/
|
|
TensorAnnotation.encodeDelimited = function encodeDelimited(message, writer) {
|
|
return this.encode(message, writer).ldelim();
|
|
};
|
|
|
|
/**
|
|
* Decodes a TensorAnnotation message from the specified reader or buffer.
|
|
* @function decode
|
|
* @memberof onnx.TensorAnnotation
|
|
* @static
|
|
* @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
|
|
* @param {number} [length] Message length if known beforehand
|
|
* @returns {onnx.TensorAnnotation} TensorAnnotation
|
|
* @throws {Error} If the payload is not a reader or valid buffer
|
|
* @throws {$protobuf.util.ProtocolError} If required fields are missing
|
|
*/
|
|
TensorAnnotation.decode = function decode(reader, length) {
|
|
if (!(reader instanceof $Reader))
|
|
reader = $Reader.create(reader);
|
|
var end = length === undefined ? reader.len : reader.pos + length, message = new $root.onnx.TensorAnnotation();
|
|
while (reader.pos < end) {
|
|
var tag = reader.uint32();
|
|
switch (tag >>> 3) {
|
|
case 1:
|
|
message.tensorName = reader.string();
|
|
break;
|
|
case 2:
|
|
if (!(message.quantParameterTensorNames && message.quantParameterTensorNames.length))
|
|
message.quantParameterTensorNames = [];
|
|
message.quantParameterTensorNames.push($root.onnx.StringStringEntryProto.decode(reader, reader.uint32()));
|
|
break;
|
|
default:
|
|
reader.skipType(tag & 7);
|
|
break;
|
|
}
|
|
}
|
|
return message;
|
|
};
|
|
|
|
/**
|
|
* Decodes a TensorAnnotation message from the specified reader or buffer, length delimited.
|
|
* @function decodeDelimited
|
|
* @memberof onnx.TensorAnnotation
|
|
* @static
|
|
* @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
|
|
* @returns {onnx.TensorAnnotation} TensorAnnotation
|
|
* @throws {Error} If the payload is not a reader or valid buffer
|
|
* @throws {$protobuf.util.ProtocolError} If required fields are missing
|
|
*/
|
|
TensorAnnotation.decodeDelimited = function decodeDelimited(reader) {
|
|
if (!(reader instanceof $Reader))
|
|
reader = new $Reader(reader);
|
|
return this.decode(reader, reader.uint32());
|
|
};
|
|
|
|
/**
|
|
* Verifies a TensorAnnotation message.
|
|
* @function verify
|
|
* @memberof onnx.TensorAnnotation
|
|
* @static
|
|
* @param {Object.<string,*>} message Plain object to verify
|
|
* @returns {string|null} `null` if valid, otherwise the reason why it is not
|
|
*/
|
|
TensorAnnotation.verify = function verify(message) {
|
|
if (typeof message !== "object" || message === null)
|
|
return "object expected";
|
|
if (message.tensorName != null && message.hasOwnProperty("tensorName"))
|
|
if (!$util.isString(message.tensorName))
|
|
return "tensorName: string expected";
|
|
if (message.quantParameterTensorNames != null && message.hasOwnProperty("quantParameterTensorNames")) {
|
|
if (!Array.isArray(message.quantParameterTensorNames))
|
|
return "quantParameterTensorNames: array expected";
|
|
for (var i = 0; i < message.quantParameterTensorNames.length; ++i) {
|
|
var error = $root.onnx.StringStringEntryProto.verify(message.quantParameterTensorNames[i]);
|
|
if (error)
|
|
return "quantParameterTensorNames." + error;
|
|
}
|
|
}
|
|
return null;
|
|
};
|
|
|
|
/**
|
|
* Creates a TensorAnnotation message from a plain object. Also converts values to their respective internal types.
|
|
* @function fromObject
|
|
* @memberof onnx.TensorAnnotation
|
|
* @static
|
|
* @param {Object.<string,*>} object Plain object
|
|
* @returns {onnx.TensorAnnotation} TensorAnnotation
|
|
*/
|
|
TensorAnnotation.fromObject = function fromObject(object) {
|
|
if (object instanceof $root.onnx.TensorAnnotation)
|
|
return object;
|
|
var message = new $root.onnx.TensorAnnotation();
|
|
if (object.tensorName != null)
|
|
message.tensorName = String(object.tensorName);
|
|
if (object.quantParameterTensorNames) {
|
|
if (!Array.isArray(object.quantParameterTensorNames))
|
|
throw TypeError(".onnx.TensorAnnotation.quantParameterTensorNames: array expected");
|
|
message.quantParameterTensorNames = [];
|
|
for (var i = 0; i < object.quantParameterTensorNames.length; ++i) {
|
|
if (typeof object.quantParameterTensorNames[i] !== "object")
|
|
throw TypeError(".onnx.TensorAnnotation.quantParameterTensorNames: object expected");
|
|
message.quantParameterTensorNames[i] = $root.onnx.StringStringEntryProto.fromObject(object.quantParameterTensorNames[i]);
|
|
}
|
|
}
|
|
return message;
|
|
};
|
|
|
|
/**
|
|
* Creates a plain object from a TensorAnnotation message. Also converts values to other types if specified.
|
|
* @function toObject
|
|
* @memberof onnx.TensorAnnotation
|
|
* @static
|
|
* @param {onnx.TensorAnnotation} message TensorAnnotation
|
|
* @param {$protobuf.IConversionOptions} [options] Conversion options
|
|
* @returns {Object.<string,*>} Plain object
|
|
*/
|
|
TensorAnnotation.toObject = function toObject(message, options) {
|
|
if (!options)
|
|
options = {};
|
|
var object = {};
|
|
if (options.arrays || options.defaults)
|
|
object.quantParameterTensorNames = [];
|
|
if (options.defaults)
|
|
object.tensorName = "";
|
|
if (message.tensorName != null && message.hasOwnProperty("tensorName"))
|
|
object.tensorName = message.tensorName;
|
|
if (message.quantParameterTensorNames && message.quantParameterTensorNames.length) {
|
|
object.quantParameterTensorNames = [];
|
|
for (var j = 0; j < message.quantParameterTensorNames.length; ++j)
|
|
object.quantParameterTensorNames[j] = $root.onnx.StringStringEntryProto.toObject(message.quantParameterTensorNames[j], options);
|
|
}
|
|
return object;
|
|
};
|
|
|
|
/**
|
|
* Converts this TensorAnnotation to JSON.
|
|
* @function toJSON
|
|
* @memberof onnx.TensorAnnotation
|
|
* @instance
|
|
* @returns {Object.<string,*>} JSON object
|
|
*/
|
|
TensorAnnotation.prototype.toJSON = function toJSON() {
|
|
return this.constructor.toObject(this, $protobuf.util.toJSONOptions);
|
|
};
|
|
|
|
return TensorAnnotation;
|
|
})();
|
|
|
|
onnx.GraphProto = (function() {
|
|
|
|
/**
|
|
* Properties of a GraphProto.
|
|
* @memberof onnx
|
|
* @interface IGraphProto
|
|
* @property {Array.<onnx.INodeProto>|null} [node] GraphProto node
|
|
* @property {string|null} [name] GraphProto name
|
|
* @property {Array.<onnx.ITensorProto>|null} [initializer] GraphProto initializer
|
|
* @property {string|null} [docString] GraphProto docString
|
|
* @property {Array.<onnx.IValueInfoProto>|null} [input] GraphProto input
|
|
* @property {Array.<onnx.IValueInfoProto>|null} [output] GraphProto output
|
|
* @property {Array.<onnx.IValueInfoProto>|null} [valueInfo] GraphProto valueInfo
|
|
* @property {Array.<onnx.ITensorAnnotation>|null} [quantizationAnnotation] GraphProto quantizationAnnotation
|
|
*/
|
|
|
|
/**
|
|
* Constructs a new GraphProto.
|
|
* @memberof onnx
|
|
* @classdesc Represents a GraphProto.
|
|
* @implements IGraphProto
|
|
* @constructor
|
|
* @param {onnx.IGraphProto=} [properties] Properties to set
|
|
*/
|
|
function GraphProto(properties) {
|
|
this.node = [];
|
|
this.initializer = [];
|
|
this.input = [];
|
|
this.output = [];
|
|
this.valueInfo = [];
|
|
this.quantizationAnnotation = [];
|
|
if (properties)
|
|
for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
|
|
if (properties[keys[i]] != null)
|
|
this[keys[i]] = properties[keys[i]];
|
|
}
|
|
|
|
/**
|
|
* GraphProto node.
|
|
* @member {Array.<onnx.INodeProto>} node
|
|
* @memberof onnx.GraphProto
|
|
* @instance
|
|
*/
|
|
GraphProto.prototype.node = $util.emptyArray;
|
|
|
|
/**
|
|
* GraphProto name.
|
|
* @member {string} name
|
|
* @memberof onnx.GraphProto
|
|
* @instance
|
|
*/
|
|
GraphProto.prototype.name = "";
|
|
|
|
/**
|
|
* GraphProto initializer.
|
|
* @member {Array.<onnx.ITensorProto>} initializer
|
|
* @memberof onnx.GraphProto
|
|
* @instance
|
|
*/
|
|
GraphProto.prototype.initializer = $util.emptyArray;
|
|
|
|
/**
|
|
* GraphProto docString.
|
|
* @member {string} docString
|
|
* @memberof onnx.GraphProto
|
|
* @instance
|
|
*/
|
|
GraphProto.prototype.docString = "";
|
|
|
|
/**
|
|
* GraphProto input.
|
|
* @member {Array.<onnx.IValueInfoProto>} input
|
|
* @memberof onnx.GraphProto
|
|
* @instance
|
|
*/
|
|
GraphProto.prototype.input = $util.emptyArray;
|
|
|
|
/**
|
|
* GraphProto output.
|
|
* @member {Array.<onnx.IValueInfoProto>} output
|
|
* @memberof onnx.GraphProto
|
|
* @instance
|
|
*/
|
|
GraphProto.prototype.output = $util.emptyArray;
|
|
|
|
/**
|
|
* GraphProto valueInfo.
|
|
* @member {Array.<onnx.IValueInfoProto>} valueInfo
|
|
* @memberof onnx.GraphProto
|
|
* @instance
|
|
*/
|
|
GraphProto.prototype.valueInfo = $util.emptyArray;
|
|
|
|
/**
|
|
* GraphProto quantizationAnnotation.
|
|
* @member {Array.<onnx.ITensorAnnotation>} quantizationAnnotation
|
|
* @memberof onnx.GraphProto
|
|
* @instance
|
|
*/
|
|
GraphProto.prototype.quantizationAnnotation = $util.emptyArray;
|
|
|
|
/**
|
|
* Creates a new GraphProto instance using the specified properties.
|
|
* @function create
|
|
* @memberof onnx.GraphProto
|
|
* @static
|
|
* @param {onnx.IGraphProto=} [properties] Properties to set
|
|
* @returns {onnx.GraphProto} GraphProto instance
|
|
*/
|
|
GraphProto.create = function create(properties) {
|
|
return new GraphProto(properties);
|
|
};
|
|
|
|
/**
|
|
* Encodes the specified GraphProto message. Does not implicitly {@link onnx.GraphProto.verify|verify} messages.
|
|
* @function encode
|
|
* @memberof onnx.GraphProto
|
|
* @static
|
|
* @param {onnx.IGraphProto} message GraphProto message or plain object to encode
|
|
* @param {$protobuf.Writer} [writer] Writer to encode to
|
|
* @returns {$protobuf.Writer} Writer
|
|
*/
|
|
GraphProto.encode = function encode(message, writer) {
|
|
if (!writer)
|
|
writer = $Writer.create();
|
|
if (message.node != null && message.node.length)
|
|
for (var i = 0; i < message.node.length; ++i)
|
|
$root.onnx.NodeProto.encode(message.node[i], writer.uint32(/* id 1, wireType 2 =*/10).fork()).ldelim();
|
|
if (message.name != null && message.hasOwnProperty("name"))
|
|
writer.uint32(/* id 2, wireType 2 =*/18).string(message.name);
|
|
if (message.initializer != null && message.initializer.length)
|
|
for (var i = 0; i < message.initializer.length; ++i)
|
|
$root.onnx.TensorProto.encode(message.initializer[i], writer.uint32(/* id 5, wireType 2 =*/42).fork()).ldelim();
|
|
if (message.docString != null && message.hasOwnProperty("docString"))
|
|
writer.uint32(/* id 10, wireType 2 =*/82).string(message.docString);
|
|
if (message.input != null && message.input.length)
|
|
for (var i = 0; i < message.input.length; ++i)
|
|
$root.onnx.ValueInfoProto.encode(message.input[i], writer.uint32(/* id 11, wireType 2 =*/90).fork()).ldelim();
|
|
if (message.output != null && message.output.length)
|
|
for (var i = 0; i < message.output.length; ++i)
|
|
$root.onnx.ValueInfoProto.encode(message.output[i], writer.uint32(/* id 12, wireType 2 =*/98).fork()).ldelim();
|
|
if (message.valueInfo != null && message.valueInfo.length)
|
|
for (var i = 0; i < message.valueInfo.length; ++i)
|
|
$root.onnx.ValueInfoProto.encode(message.valueInfo[i], writer.uint32(/* id 13, wireType 2 =*/106).fork()).ldelim();
|
|
if (message.quantizationAnnotation != null && message.quantizationAnnotation.length)
|
|
for (var i = 0; i < message.quantizationAnnotation.length; ++i)
|
|
$root.onnx.TensorAnnotation.encode(message.quantizationAnnotation[i], writer.uint32(/* id 14, wireType 2 =*/114).fork()).ldelim();
|
|
return writer;
|
|
};
|
|
|
|
/**
|
|
* Encodes the specified GraphProto message, length delimited. Does not implicitly {@link onnx.GraphProto.verify|verify} messages.
|
|
* @function encodeDelimited
|
|
* @memberof onnx.GraphProto
|
|
* @static
|
|
* @param {onnx.IGraphProto} message GraphProto message or plain object to encode
|
|
* @param {$protobuf.Writer} [writer] Writer to encode to
|
|
* @returns {$protobuf.Writer} Writer
|
|
*/
|
|
GraphProto.encodeDelimited = function encodeDelimited(message, writer) {
|
|
return this.encode(message, writer).ldelim();
|
|
};
|
|
|
|
/**
|
|
* Decodes a GraphProto message from the specified reader or buffer.
|
|
* @function decode
|
|
* @memberof onnx.GraphProto
|
|
* @static
|
|
* @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
|
|
* @param {number} [length] Message length if known beforehand
|
|
* @returns {onnx.GraphProto} GraphProto
|
|
* @throws {Error} If the payload is not a reader or valid buffer
|
|
* @throws {$protobuf.util.ProtocolError} If required fields are missing
|
|
*/
|
|
GraphProto.decode = function decode(reader, length) {
|
|
if (!(reader instanceof $Reader))
|
|
reader = $Reader.create(reader);
|
|
var end = length === undefined ? reader.len : reader.pos + length, message = new $root.onnx.GraphProto();
|
|
while (reader.pos < end) {
|
|
var tag = reader.uint32();
|
|
switch (tag >>> 3) {
|
|
case 1:
|
|
if (!(message.node && message.node.length))
|
|
message.node = [];
|
|
message.node.push($root.onnx.NodeProto.decode(reader, reader.uint32()));
|
|
break;
|
|
case 2:
|
|
message.name = reader.string();
|
|
break;
|
|
case 5:
|
|
if (!(message.initializer && message.initializer.length))
|
|
message.initializer = [];
|
|
message.initializer.push($root.onnx.TensorProto.decode(reader, reader.uint32()));
|
|
break;
|
|
case 10:
|
|
message.docString = reader.string();
|
|
break;
|
|
case 11:
|
|
if (!(message.input && message.input.length))
|
|
message.input = [];
|
|
message.input.push($root.onnx.ValueInfoProto.decode(reader, reader.uint32()));
|
|
break;
|
|
case 12:
|
|
if (!(message.output && message.output.length))
|
|
message.output = [];
|
|
message.output.push($root.onnx.ValueInfoProto.decode(reader, reader.uint32()));
|
|
break;
|
|
case 13:
|
|
if (!(message.valueInfo && message.valueInfo.length))
|
|
message.valueInfo = [];
|
|
message.valueInfo.push($root.onnx.ValueInfoProto.decode(reader, reader.uint32()));
|
|
break;
|
|
case 14:
|
|
if (!(message.quantizationAnnotation && message.quantizationAnnotation.length))
|
|
message.quantizationAnnotation = [];
|
|
message.quantizationAnnotation.push($root.onnx.TensorAnnotation.decode(reader, reader.uint32()));
|
|
break;
|
|
default:
|
|
reader.skipType(tag & 7);
|
|
break;
|
|
}
|
|
}
|
|
return message;
|
|
};
|
|
|
|
/**
|
|
* Decodes a GraphProto message from the specified reader or buffer, length delimited.
|
|
* @function decodeDelimited
|
|
* @memberof onnx.GraphProto
|
|
* @static
|
|
* @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
|
|
* @returns {onnx.GraphProto} GraphProto
|
|
* @throws {Error} If the payload is not a reader or valid buffer
|
|
* @throws {$protobuf.util.ProtocolError} If required fields are missing
|
|
*/
|
|
GraphProto.decodeDelimited = function decodeDelimited(reader) {
|
|
if (!(reader instanceof $Reader))
|
|
reader = new $Reader(reader);
|
|
return this.decode(reader, reader.uint32());
|
|
};
|
|
|
|
/**
|
|
* Verifies a GraphProto message.
|
|
* @function verify
|
|
* @memberof onnx.GraphProto
|
|
* @static
|
|
* @param {Object.<string,*>} message Plain object to verify
|
|
* @returns {string|null} `null` if valid, otherwise the reason why it is not
|
|
*/
|
|
GraphProto.verify = function verify(message) {
|
|
if (typeof message !== "object" || message === null)
|
|
return "object expected";
|
|
if (message.node != null && message.hasOwnProperty("node")) {
|
|
if (!Array.isArray(message.node))
|
|
return "node: array expected";
|
|
for (var i = 0; i < message.node.length; ++i) {
|
|
var error = $root.onnx.NodeProto.verify(message.node[i]);
|
|
if (error)
|
|
return "node." + error;
|
|
}
|
|
}
|
|
if (message.name != null && message.hasOwnProperty("name"))
|
|
if (!$util.isString(message.name))
|
|
return "name: string expected";
|
|
if (message.initializer != null && message.hasOwnProperty("initializer")) {
|
|
if (!Array.isArray(message.initializer))
|
|
return "initializer: array expected";
|
|
for (var i = 0; i < message.initializer.length; ++i) {
|
|
var error = $root.onnx.TensorProto.verify(message.initializer[i]);
|
|
if (error)
|
|
return "initializer." + error;
|
|
}
|
|
}
|
|
if (message.docString != null && message.hasOwnProperty("docString"))
|
|
if (!$util.isString(message.docString))
|
|
return "docString: string expected";
|
|
if (message.input != null && message.hasOwnProperty("input")) {
|
|
if (!Array.isArray(message.input))
|
|
return "input: array expected";
|
|
for (var i = 0; i < message.input.length; ++i) {
|
|
var error = $root.onnx.ValueInfoProto.verify(message.input[i]);
|
|
if (error)
|
|
return "input." + error;
|
|
}
|
|
}
|
|
if (message.output != null && message.hasOwnProperty("output")) {
|
|
if (!Array.isArray(message.output))
|
|
return "output: array expected";
|
|
for (var i = 0; i < message.output.length; ++i) {
|
|
var error = $root.onnx.ValueInfoProto.verify(message.output[i]);
|
|
if (error)
|
|
return "output." + error;
|
|
}
|
|
}
|
|
if (message.valueInfo != null && message.hasOwnProperty("valueInfo")) {
|
|
if (!Array.isArray(message.valueInfo))
|
|
return "valueInfo: array expected";
|
|
for (var i = 0; i < message.valueInfo.length; ++i) {
|
|
var error = $root.onnx.ValueInfoProto.verify(message.valueInfo[i]);
|
|
if (error)
|
|
return "valueInfo." + error;
|
|
}
|
|
}
|
|
if (message.quantizationAnnotation != null && message.hasOwnProperty("quantizationAnnotation")) {
|
|
if (!Array.isArray(message.quantizationAnnotation))
|
|
return "quantizationAnnotation: array expected";
|
|
for (var i = 0; i < message.quantizationAnnotation.length; ++i) {
|
|
var error = $root.onnx.TensorAnnotation.verify(message.quantizationAnnotation[i]);
|
|
if (error)
|
|
return "quantizationAnnotation." + error;
|
|
}
|
|
}
|
|
return null;
|
|
};
|
|
|
|
/**
|
|
* Creates a GraphProto message from a plain object. Also converts values to their respective internal types.
|
|
* @function fromObject
|
|
* @memberof onnx.GraphProto
|
|
* @static
|
|
* @param {Object.<string,*>} object Plain object
|
|
* @returns {onnx.GraphProto} GraphProto
|
|
*/
|
|
GraphProto.fromObject = function fromObject(object) {
|
|
if (object instanceof $root.onnx.GraphProto)
|
|
return object;
|
|
var message = new $root.onnx.GraphProto();
|
|
if (object.node) {
|
|
if (!Array.isArray(object.node))
|
|
throw TypeError(".onnx.GraphProto.node: array expected");
|
|
message.node = [];
|
|
for (var i = 0; i < object.node.length; ++i) {
|
|
if (typeof object.node[i] !== "object")
|
|
throw TypeError(".onnx.GraphProto.node: object expected");
|
|
message.node[i] = $root.onnx.NodeProto.fromObject(object.node[i]);
|
|
}
|
|
}
|
|
if (object.name != null)
|
|
message.name = String(object.name);
|
|
if (object.initializer) {
|
|
if (!Array.isArray(object.initializer))
|
|
throw TypeError(".onnx.GraphProto.initializer: array expected");
|
|
message.initializer = [];
|
|
for (var i = 0; i < object.initializer.length; ++i) {
|
|
if (typeof object.initializer[i] !== "object")
|
|
throw TypeError(".onnx.GraphProto.initializer: object expected");
|
|
message.initializer[i] = $root.onnx.TensorProto.fromObject(object.initializer[i]);
|
|
}
|
|
}
|
|
if (object.docString != null)
|
|
message.docString = String(object.docString);
|
|
if (object.input) {
|
|
if (!Array.isArray(object.input))
|
|
throw TypeError(".onnx.GraphProto.input: array expected");
|
|
message.input = [];
|
|
for (var i = 0; i < object.input.length; ++i) {
|
|
if (typeof object.input[i] !== "object")
|
|
throw TypeError(".onnx.GraphProto.input: object expected");
|
|
message.input[i] = $root.onnx.ValueInfoProto.fromObject(object.input[i]);
|
|
}
|
|
}
|
|
if (object.output) {
|
|
if (!Array.isArray(object.output))
|
|
throw TypeError(".onnx.GraphProto.output: array expected");
|
|
message.output = [];
|
|
for (var i = 0; i < object.output.length; ++i) {
|
|
if (typeof object.output[i] !== "object")
|
|
throw TypeError(".onnx.GraphProto.output: object expected");
|
|
message.output[i] = $root.onnx.ValueInfoProto.fromObject(object.output[i]);
|
|
}
|
|
}
|
|
if (object.valueInfo) {
|
|
if (!Array.isArray(object.valueInfo))
|
|
throw TypeError(".onnx.GraphProto.valueInfo: array expected");
|
|
message.valueInfo = [];
|
|
for (var i = 0; i < object.valueInfo.length; ++i) {
|
|
if (typeof object.valueInfo[i] !== "object")
|
|
throw TypeError(".onnx.GraphProto.valueInfo: object expected");
|
|
message.valueInfo[i] = $root.onnx.ValueInfoProto.fromObject(object.valueInfo[i]);
|
|
}
|
|
}
|
|
if (object.quantizationAnnotation) {
|
|
if (!Array.isArray(object.quantizationAnnotation))
|
|
throw TypeError(".onnx.GraphProto.quantizationAnnotation: array expected");
|
|
message.quantizationAnnotation = [];
|
|
for (var i = 0; i < object.quantizationAnnotation.length; ++i) {
|
|
if (typeof object.quantizationAnnotation[i] !== "object")
|
|
throw TypeError(".onnx.GraphProto.quantizationAnnotation: object expected");
|
|
message.quantizationAnnotation[i] = $root.onnx.TensorAnnotation.fromObject(object.quantizationAnnotation[i]);
|
|
}
|
|
}
|
|
return message;
|
|
};
|
|
|
|
/**
|
|
* Creates a plain object from a GraphProto message. Also converts values to other types if specified.
|
|
* @function toObject
|
|
* @memberof onnx.GraphProto
|
|
* @static
|
|
* @param {onnx.GraphProto} message GraphProto
|
|
* @param {$protobuf.IConversionOptions} [options] Conversion options
|
|
* @returns {Object.<string,*>} Plain object
|
|
*/
|
|
GraphProto.toObject = function toObject(message, options) {
|
|
if (!options)
|
|
options = {};
|
|
var object = {};
|
|
if (options.arrays || options.defaults) {
|
|
object.node = [];
|
|
object.initializer = [];
|
|
object.input = [];
|
|
object.output = [];
|
|
object.valueInfo = [];
|
|
object.quantizationAnnotation = [];
|
|
}
|
|
if (options.defaults) {
|
|
object.name = "";
|
|
object.docString = "";
|
|
}
|
|
if (message.node && message.node.length) {
|
|
object.node = [];
|
|
for (var j = 0; j < message.node.length; ++j)
|
|
object.node[j] = $root.onnx.NodeProto.toObject(message.node[j], options);
|
|
}
|
|
if (message.name != null && message.hasOwnProperty("name"))
|
|
object.name = message.name;
|
|
if (message.initializer && message.initializer.length) {
|
|
object.initializer = [];
|
|
for (var j = 0; j < message.initializer.length; ++j)
|
|
object.initializer[j] = $root.onnx.TensorProto.toObject(message.initializer[j], options);
|
|
}
|
|
if (message.docString != null && message.hasOwnProperty("docString"))
|
|
object.docString = message.docString;
|
|
if (message.input && message.input.length) {
|
|
object.input = [];
|
|
for (var j = 0; j < message.input.length; ++j)
|
|
object.input[j] = $root.onnx.ValueInfoProto.toObject(message.input[j], options);
|
|
}
|
|
if (message.output && message.output.length) {
|
|
object.output = [];
|
|
for (var j = 0; j < message.output.length; ++j)
|
|
object.output[j] = $root.onnx.ValueInfoProto.toObject(message.output[j], options);
|
|
}
|
|
if (message.valueInfo && message.valueInfo.length) {
|
|
object.valueInfo = [];
|
|
for (var j = 0; j < message.valueInfo.length; ++j)
|
|
object.valueInfo[j] = $root.onnx.ValueInfoProto.toObject(message.valueInfo[j], options);
|
|
}
|
|
if (message.quantizationAnnotation && message.quantizationAnnotation.length) {
|
|
object.quantizationAnnotation = [];
|
|
for (var j = 0; j < message.quantizationAnnotation.length; ++j)
|
|
object.quantizationAnnotation[j] = $root.onnx.TensorAnnotation.toObject(message.quantizationAnnotation[j], options);
|
|
}
|
|
return object;
|
|
};
|
|
|
|
/**
|
|
* Converts this GraphProto to JSON.
|
|
* @function toJSON
|
|
* @memberof onnx.GraphProto
|
|
* @instance
|
|
* @returns {Object.<string,*>} JSON object
|
|
*/
|
|
GraphProto.prototype.toJSON = function toJSON() {
|
|
return this.constructor.toObject(this, $protobuf.util.toJSONOptions);
|
|
};
|
|
|
|
return GraphProto;
|
|
})();
|
|
|
|
onnx.TensorProto = (function() {
|
|
|
|
/**
|
|
* Properties of a TensorProto.
|
|
* @memberof onnx
|
|
* @interface ITensorProto
|
|
* @property {Array.<number|Long>|null} [dims] TensorProto dims
|
|
* @property {number|null} [dataType] TensorProto dataType
|
|
* @property {onnx.TensorProto.ISegment|null} [segment] TensorProto segment
|
|
* @property {Array.<number>|null} [floatData] TensorProto floatData
|
|
* @property {Array.<number>|null} [int32Data] TensorProto int32Data
|
|
* @property {Array.<Uint8Array>|null} [stringData] TensorProto stringData
|
|
* @property {Array.<number|Long>|null} [int64Data] TensorProto int64Data
|
|
* @property {string|null} [name] TensorProto name
|
|
* @property {string|null} [docString] TensorProto docString
|
|
* @property {Uint8Array|null} [rawData] TensorProto rawData
|
|
* @property {Array.<onnx.IStringStringEntryProto>|null} [externalData] TensorProto externalData
|
|
* @property {onnx.TensorProto.DataLocation|null} [dataLocation] TensorProto dataLocation
|
|
* @property {Array.<number>|null} [doubleData] TensorProto doubleData
|
|
* @property {Array.<number|Long>|null} [uint64Data] TensorProto uint64Data
|
|
*/
|
|
|
|
/**
|
|
* Constructs a new TensorProto.
|
|
* @memberof onnx
|
|
* @classdesc Represents a TensorProto.
|
|
* @implements ITensorProto
|
|
* @constructor
|
|
* @param {onnx.ITensorProto=} [properties] Properties to set
|
|
*/
|
|
function TensorProto(properties) {
|
|
this.dims = [];
|
|
this.floatData = [];
|
|
this.int32Data = [];
|
|
this.stringData = [];
|
|
this.int64Data = [];
|
|
this.externalData = [];
|
|
this.doubleData = [];
|
|
this.uint64Data = [];
|
|
if (properties)
|
|
for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
|
|
if (properties[keys[i]] != null)
|
|
this[keys[i]] = properties[keys[i]];
|
|
}
|
|
|
|
/**
|
|
* TensorProto dims.
|
|
* @member {Array.<number|Long>} dims
|
|
* @memberof onnx.TensorProto
|
|
* @instance
|
|
*/
|
|
TensorProto.prototype.dims = $util.emptyArray;
|
|
|
|
/**
|
|
* TensorProto dataType.
|
|
* @member {number} dataType
|
|
* @memberof onnx.TensorProto
|
|
* @instance
|
|
*/
|
|
TensorProto.prototype.dataType = 0;
|
|
|
|
/**
|
|
* TensorProto segment.
|
|
* @member {onnx.TensorProto.ISegment|null|undefined} segment
|
|
* @memberof onnx.TensorProto
|
|
* @instance
|
|
*/
|
|
TensorProto.prototype.segment = null;
|
|
|
|
/**
|
|
* TensorProto floatData.
|
|
* @member {Array.<number>} floatData
|
|
* @memberof onnx.TensorProto
|
|
* @instance
|
|
*/
|
|
TensorProto.prototype.floatData = $util.emptyArray;
|
|
|
|
/**
|
|
* TensorProto int32Data.
|
|
* @member {Array.<number>} int32Data
|
|
* @memberof onnx.TensorProto
|
|
* @instance
|
|
*/
|
|
TensorProto.prototype.int32Data = $util.emptyArray;
|
|
|
|
/**
|
|
* TensorProto stringData.
|
|
* @member {Array.<Uint8Array>} stringData
|
|
* @memberof onnx.TensorProto
|
|
* @instance
|
|
*/
|
|
TensorProto.prototype.stringData = $util.emptyArray;
|
|
|
|
/**
|
|
* TensorProto int64Data.
|
|
* @member {Array.<number|Long>} int64Data
|
|
* @memberof onnx.TensorProto
|
|
* @instance
|
|
*/
|
|
TensorProto.prototype.int64Data = $util.emptyArray;
|
|
|
|
/**
|
|
* TensorProto name.
|
|
* @member {string} name
|
|
* @memberof onnx.TensorProto
|
|
* @instance
|
|
*/
|
|
TensorProto.prototype.name = "";
|
|
|
|
/**
|
|
* TensorProto docString.
|
|
* @member {string} docString
|
|
* @memberof onnx.TensorProto
|
|
* @instance
|
|
*/
|
|
TensorProto.prototype.docString = "";
|
|
|
|
/**
|
|
* TensorProto rawData.
|
|
* @member {Uint8Array} rawData
|
|
* @memberof onnx.TensorProto
|
|
* @instance
|
|
*/
|
|
TensorProto.prototype.rawData = $util.newBuffer([]);
|
|
|
|
/**
|
|
* TensorProto externalData.
|
|
* @member {Array.<onnx.IStringStringEntryProto>} externalData
|
|
* @memberof onnx.TensorProto
|
|
* @instance
|
|
*/
|
|
TensorProto.prototype.externalData = $util.emptyArray;
|
|
|
|
/**
|
|
* TensorProto dataLocation.
|
|
* @member {onnx.TensorProto.DataLocation} dataLocation
|
|
* @memberof onnx.TensorProto
|
|
* @instance
|
|
*/
|
|
TensorProto.prototype.dataLocation = 0;
|
|
|
|
/**
|
|
* TensorProto doubleData.
|
|
* @member {Array.<number>} doubleData
|
|
* @memberof onnx.TensorProto
|
|
* @instance
|
|
*/
|
|
TensorProto.prototype.doubleData = $util.emptyArray;
|
|
|
|
/**
|
|
* TensorProto uint64Data.
|
|
* @member {Array.<number|Long>} uint64Data
|
|
* @memberof onnx.TensorProto
|
|
* @instance
|
|
*/
|
|
TensorProto.prototype.uint64Data = $util.emptyArray;
|
|
|
|
/**
|
|
* Creates a new TensorProto instance using the specified properties.
|
|
* @function create
|
|
* @memberof onnx.TensorProto
|
|
* @static
|
|
* @param {onnx.ITensorProto=} [properties] Properties to set
|
|
* @returns {onnx.TensorProto} TensorProto instance
|
|
*/
|
|
TensorProto.create = function create(properties) {
|
|
return new TensorProto(properties);
|
|
};
|
|
|
|
/**
|
|
* Encodes the specified TensorProto message. Does not implicitly {@link onnx.TensorProto.verify|verify} messages.
|
|
* @function encode
|
|
* @memberof onnx.TensorProto
|
|
* @static
|
|
* @param {onnx.ITensorProto} message TensorProto message or plain object to encode
|
|
* @param {$protobuf.Writer} [writer] Writer to encode to
|
|
* @returns {$protobuf.Writer} Writer
|
|
*/
|
|
TensorProto.encode = function encode(message, writer) {
|
|
if (!writer)
|
|
writer = $Writer.create();
|
|
if (message.dims != null && message.dims.length) {
|
|
writer.uint32(/* id 1, wireType 2 =*/10).fork();
|
|
for (var i = 0; i < message.dims.length; ++i)
|
|
writer.int64(message.dims[i]);
|
|
writer.ldelim();
|
|
}
|
|
if (message.dataType != null && message.hasOwnProperty("dataType"))
|
|
writer.uint32(/* id 2, wireType 0 =*/16).int32(message.dataType);
|
|
if (message.segment != null && message.hasOwnProperty("segment"))
|
|
$root.onnx.TensorProto.Segment.encode(message.segment, writer.uint32(/* id 3, wireType 2 =*/26).fork()).ldelim();
|
|
if (message.floatData != null && message.floatData.length) {
|
|
writer.uint32(/* id 4, wireType 2 =*/34).fork();
|
|
for (var i = 0; i < message.floatData.length; ++i)
|
|
writer.float(message.floatData[i]);
|
|
writer.ldelim();
|
|
}
|
|
if (message.int32Data != null && message.int32Data.length) {
|
|
writer.uint32(/* id 5, wireType 2 =*/42).fork();
|
|
for (var i = 0; i < message.int32Data.length; ++i)
|
|
writer.int32(message.int32Data[i]);
|
|
writer.ldelim();
|
|
}
|
|
if (message.stringData != null && message.stringData.length)
|
|
for (var i = 0; i < message.stringData.length; ++i)
|
|
writer.uint32(/* id 6, wireType 2 =*/50).bytes(message.stringData[i]);
|
|
if (message.int64Data != null && message.int64Data.length) {
|
|
writer.uint32(/* id 7, wireType 2 =*/58).fork();
|
|
for (var i = 0; i < message.int64Data.length; ++i)
|
|
writer.int64(message.int64Data[i]);
|
|
writer.ldelim();
|
|
}
|
|
if (message.name != null && message.hasOwnProperty("name"))
|
|
writer.uint32(/* id 8, wireType 2 =*/66).string(message.name);
|
|
if (message.rawData != null && message.hasOwnProperty("rawData"))
|
|
writer.uint32(/* id 9, wireType 2 =*/74).bytes(message.rawData);
|
|
if (message.doubleData != null && message.doubleData.length) {
|
|
writer.uint32(/* id 10, wireType 2 =*/82).fork();
|
|
for (var i = 0; i < message.doubleData.length; ++i)
|
|
writer.double(message.doubleData[i]);
|
|
writer.ldelim();
|
|
}
|
|
if (message.uint64Data != null && message.uint64Data.length) {
|
|
writer.uint32(/* id 11, wireType 2 =*/90).fork();
|
|
for (var i = 0; i < message.uint64Data.length; ++i)
|
|
writer.uint64(message.uint64Data[i]);
|
|
writer.ldelim();
|
|
}
|
|
if (message.docString != null && message.hasOwnProperty("docString"))
|
|
writer.uint32(/* id 12, wireType 2 =*/98).string(message.docString);
|
|
if (message.externalData != null && message.externalData.length)
|
|
for (var i = 0; i < message.externalData.length; ++i)
|
|
$root.onnx.StringStringEntryProto.encode(message.externalData[i], writer.uint32(/* id 13, wireType 2 =*/106).fork()).ldelim();
|
|
if (message.dataLocation != null && message.hasOwnProperty("dataLocation"))
|
|
writer.uint32(/* id 14, wireType 0 =*/112).int32(message.dataLocation);
|
|
return writer;
|
|
};
|
|
|
|
/**
|
|
* Encodes the specified TensorProto message, length delimited. Does not implicitly {@link onnx.TensorProto.verify|verify} messages.
|
|
* @function encodeDelimited
|
|
* @memberof onnx.TensorProto
|
|
* @static
|
|
* @param {onnx.ITensorProto} message TensorProto message or plain object to encode
|
|
* @param {$protobuf.Writer} [writer] Writer to encode to
|
|
* @returns {$protobuf.Writer} Writer
|
|
*/
|
|
TensorProto.encodeDelimited = function encodeDelimited(message, writer) {
|
|
return this.encode(message, writer).ldelim();
|
|
};
|
|
|
|
/**
|
|
* Decodes a TensorProto message from the specified reader or buffer.
|
|
* @function decode
|
|
* @memberof onnx.TensorProto
|
|
* @static
|
|
* @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
|
|
* @param {number} [length] Message length if known beforehand
|
|
* @returns {onnx.TensorProto} TensorProto
|
|
* @throws {Error} If the payload is not a reader or valid buffer
|
|
* @throws {$protobuf.util.ProtocolError} If required fields are missing
|
|
*/
|
|
TensorProto.decode = function decode(reader, length) {
|
|
if (!(reader instanceof $Reader))
|
|
reader = $Reader.create(reader);
|
|
var end = length === undefined ? reader.len : reader.pos + length, message = new $root.onnx.TensorProto();
|
|
while (reader.pos < end) {
|
|
var tag = reader.uint32();
|
|
switch (tag >>> 3) {
|
|
case 1:
|
|
if (!(message.dims && message.dims.length))
|
|
message.dims = [];
|
|
if ((tag & 7) === 2) {
|
|
var end2 = reader.uint32() + reader.pos;
|
|
while (reader.pos < end2)
|
|
message.dims.push(reader.int64());
|
|
} else
|
|
message.dims.push(reader.int64());
|
|
break;
|
|
case 2:
|
|
message.dataType = reader.int32();
|
|
break;
|
|
case 3:
|
|
message.segment = $root.onnx.TensorProto.Segment.decode(reader, reader.uint32());
|
|
break;
|
|
case 4:
|
|
if (!(message.floatData && message.floatData.length))
|
|
message.floatData = [];
|
|
if ((tag & 7) === 2) {
|
|
var end2 = reader.uint32() + reader.pos;
|
|
while (reader.pos < end2)
|
|
message.floatData.push(reader.float());
|
|
} else
|
|
message.floatData.push(reader.float());
|
|
break;
|
|
case 5:
|
|
if (!(message.int32Data && message.int32Data.length))
|
|
message.int32Data = [];
|
|
if ((tag & 7) === 2) {
|
|
var end2 = reader.uint32() + reader.pos;
|
|
while (reader.pos < end2)
|
|
message.int32Data.push(reader.int32());
|
|
} else
|
|
message.int32Data.push(reader.int32());
|
|
break;
|
|
case 6:
|
|
if (!(message.stringData && message.stringData.length))
|
|
message.stringData = [];
|
|
message.stringData.push(reader.bytes());
|
|
break;
|
|
case 7:
|
|
if (!(message.int64Data && message.int64Data.length))
|
|
message.int64Data = [];
|
|
if ((tag & 7) === 2) {
|
|
var end2 = reader.uint32() + reader.pos;
|
|
while (reader.pos < end2)
|
|
message.int64Data.push(reader.int64());
|
|
} else
|
|
message.int64Data.push(reader.int64());
|
|
break;
|
|
case 8:
|
|
message.name = reader.string();
|
|
break;
|
|
case 12:
|
|
message.docString = reader.string();
|
|
break;
|
|
case 9:
|
|
message.rawData = reader.bytes();
|
|
break;
|
|
case 13:
|
|
if (!(message.externalData && message.externalData.length))
|
|
message.externalData = [];
|
|
message.externalData.push($root.onnx.StringStringEntryProto.decode(reader, reader.uint32()));
|
|
break;
|
|
case 14:
|
|
message.dataLocation = reader.int32();
|
|
break;
|
|
case 10:
|
|
if (!(message.doubleData && message.doubleData.length))
|
|
message.doubleData = [];
|
|
if ((tag & 7) === 2) {
|
|
var end2 = reader.uint32() + reader.pos;
|
|
while (reader.pos < end2)
|
|
message.doubleData.push(reader.double());
|
|
} else
|
|
message.doubleData.push(reader.double());
|
|
break;
|
|
case 11:
|
|
if (!(message.uint64Data && message.uint64Data.length))
|
|
message.uint64Data = [];
|
|
if ((tag & 7) === 2) {
|
|
var end2 = reader.uint32() + reader.pos;
|
|
while (reader.pos < end2)
|
|
message.uint64Data.push(reader.uint64());
|
|
} else
|
|
message.uint64Data.push(reader.uint64());
|
|
break;
|
|
default:
|
|
reader.skipType(tag & 7);
|
|
break;
|
|
}
|
|
}
|
|
return message;
|
|
};
|
|
|
|
/**
|
|
* Decodes a TensorProto message from the specified reader or buffer, length delimited.
|
|
* @function decodeDelimited
|
|
* @memberof onnx.TensorProto
|
|
* @static
|
|
* @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
|
|
* @returns {onnx.TensorProto} TensorProto
|
|
* @throws {Error} If the payload is not a reader or valid buffer
|
|
* @throws {$protobuf.util.ProtocolError} If required fields are missing
|
|
*/
|
|
TensorProto.decodeDelimited = function decodeDelimited(reader) {
|
|
if (!(reader instanceof $Reader))
|
|
reader = new $Reader(reader);
|
|
return this.decode(reader, reader.uint32());
|
|
};
|
|
|
|
/**
|
|
* Verifies a TensorProto message.
|
|
* @function verify
|
|
* @memberof onnx.TensorProto
|
|
* @static
|
|
* @param {Object.<string,*>} message Plain object to verify
|
|
* @returns {string|null} `null` if valid, otherwise the reason why it is not
|
|
*/
|
|
TensorProto.verify = function verify(message) {
|
|
if (typeof message !== "object" || message === null)
|
|
return "object expected";
|
|
if (message.dims != null && message.hasOwnProperty("dims")) {
|
|
if (!Array.isArray(message.dims))
|
|
return "dims: array expected";
|
|
for (var i = 0; i < message.dims.length; ++i)
|
|
if (!$util.isInteger(message.dims[i]) && !(message.dims[i] && $util.isInteger(message.dims[i].low) && $util.isInteger(message.dims[i].high)))
|
|
return "dims: integer|Long[] expected";
|
|
}
|
|
if (message.dataType != null && message.hasOwnProperty("dataType"))
|
|
if (!$util.isInteger(message.dataType))
|
|
return "dataType: integer expected";
|
|
if (message.segment != null && message.hasOwnProperty("segment")) {
|
|
var error = $root.onnx.TensorProto.Segment.verify(message.segment);
|
|
if (error)
|
|
return "segment." + error;
|
|
}
|
|
if (message.floatData != null && message.hasOwnProperty("floatData")) {
|
|
if (!Array.isArray(message.floatData))
|
|
return "floatData: array expected";
|
|
for (var i = 0; i < message.floatData.length; ++i)
|
|
if (typeof message.floatData[i] !== "number")
|
|
return "floatData: number[] expected";
|
|
}
|
|
if (message.int32Data != null && message.hasOwnProperty("int32Data")) {
|
|
if (!Array.isArray(message.int32Data))
|
|
return "int32Data: array expected";
|
|
for (var i = 0; i < message.int32Data.length; ++i)
|
|
if (!$util.isInteger(message.int32Data[i]))
|
|
return "int32Data: integer[] expected";
|
|
}
|
|
if (message.stringData != null && message.hasOwnProperty("stringData")) {
|
|
if (!Array.isArray(message.stringData))
|
|
return "stringData: array expected";
|
|
for (var i = 0; i < message.stringData.length; ++i)
|
|
if (!(message.stringData[i] && typeof message.stringData[i].length === "number" || $util.isString(message.stringData[i])))
|
|
return "stringData: buffer[] expected";
|
|
}
|
|
if (message.int64Data != null && message.hasOwnProperty("int64Data")) {
|
|
if (!Array.isArray(message.int64Data))
|
|
return "int64Data: array expected";
|
|
for (var i = 0; i < message.int64Data.length; ++i)
|
|
if (!$util.isInteger(message.int64Data[i]) && !(message.int64Data[i] && $util.isInteger(message.int64Data[i].low) && $util.isInteger(message.int64Data[i].high)))
|
|
return "int64Data: integer|Long[] expected";
|
|
}
|
|
if (message.name != null && message.hasOwnProperty("name"))
|
|
if (!$util.isString(message.name))
|
|
return "name: string expected";
|
|
if (message.docString != null && message.hasOwnProperty("docString"))
|
|
if (!$util.isString(message.docString))
|
|
return "docString: string expected";
|
|
if (message.rawData != null && message.hasOwnProperty("rawData"))
|
|
if (!(message.rawData && typeof message.rawData.length === "number" || $util.isString(message.rawData)))
|
|
return "rawData: buffer expected";
|
|
if (message.externalData != null && message.hasOwnProperty("externalData")) {
|
|
if (!Array.isArray(message.externalData))
|
|
return "externalData: array expected";
|
|
for (var i = 0; i < message.externalData.length; ++i) {
|
|
var error = $root.onnx.StringStringEntryProto.verify(message.externalData[i]);
|
|
if (error)
|
|
return "externalData." + error;
|
|
}
|
|
}
|
|
if (message.dataLocation != null && message.hasOwnProperty("dataLocation"))
|
|
switch (message.dataLocation) {
|
|
default:
|
|
return "dataLocation: enum value expected";
|
|
case 0:
|
|
case 1:
|
|
break;
|
|
}
|
|
if (message.doubleData != null && message.hasOwnProperty("doubleData")) {
|
|
if (!Array.isArray(message.doubleData))
|
|
return "doubleData: array expected";
|
|
for (var i = 0; i < message.doubleData.length; ++i)
|
|
if (typeof message.doubleData[i] !== "number")
|
|
return "doubleData: number[] expected";
|
|
}
|
|
if (message.uint64Data != null && message.hasOwnProperty("uint64Data")) {
|
|
if (!Array.isArray(message.uint64Data))
|
|
return "uint64Data: array expected";
|
|
for (var i = 0; i < message.uint64Data.length; ++i)
|
|
if (!$util.isInteger(message.uint64Data[i]) && !(message.uint64Data[i] && $util.isInteger(message.uint64Data[i].low) && $util.isInteger(message.uint64Data[i].high)))
|
|
return "uint64Data: integer|Long[] expected";
|
|
}
|
|
return null;
|
|
};
|
|
|
|
/**
|
|
* Creates a TensorProto message from a plain object. Also converts values to their respective internal types.
|
|
* @function fromObject
|
|
* @memberof onnx.TensorProto
|
|
* @static
|
|
* @param {Object.<string,*>} object Plain object
|
|
* @returns {onnx.TensorProto} TensorProto
|
|
*/
|
|
TensorProto.fromObject = function fromObject(object) {
|
|
if (object instanceof $root.onnx.TensorProto)
|
|
return object;
|
|
var message = new $root.onnx.TensorProto();
|
|
if (object.dims) {
|
|
if (!Array.isArray(object.dims))
|
|
throw TypeError(".onnx.TensorProto.dims: array expected");
|
|
message.dims = [];
|
|
for (var i = 0; i < object.dims.length; ++i)
|
|
if ($util.Long)
|
|
(message.dims[i] = $util.Long.fromValue(object.dims[i])).unsigned = false;
|
|
else if (typeof object.dims[i] === "string")
|
|
message.dims[i] = parseInt(object.dims[i], 10);
|
|
else if (typeof object.dims[i] === "number")
|
|
message.dims[i] = object.dims[i];
|
|
else if (typeof object.dims[i] === "object")
|
|
message.dims[i] = new $util.LongBits(object.dims[i].low >>> 0, object.dims[i].high >>> 0).toNumber();
|
|
}
|
|
if (object.dataType != null)
|
|
message.dataType = object.dataType | 0;
|
|
if (object.segment != null) {
|
|
if (typeof object.segment !== "object")
|
|
throw TypeError(".onnx.TensorProto.segment: object expected");
|
|
message.segment = $root.onnx.TensorProto.Segment.fromObject(object.segment);
|
|
}
|
|
if (object.floatData) {
|
|
if (!Array.isArray(object.floatData))
|
|
throw TypeError(".onnx.TensorProto.floatData: array expected");
|
|
message.floatData = [];
|
|
for (var i = 0; i < object.floatData.length; ++i)
|
|
message.floatData[i] = Number(object.floatData[i]);
|
|
}
|
|
if (object.int32Data) {
|
|
if (!Array.isArray(object.int32Data))
|
|
throw TypeError(".onnx.TensorProto.int32Data: array expected");
|
|
message.int32Data = [];
|
|
for (var i = 0; i < object.int32Data.length; ++i)
|
|
message.int32Data[i] = object.int32Data[i] | 0;
|
|
}
|
|
if (object.stringData) {
|
|
if (!Array.isArray(object.stringData))
|
|
throw TypeError(".onnx.TensorProto.stringData: array expected");
|
|
message.stringData = [];
|
|
for (var i = 0; i < object.stringData.length; ++i)
|
|
if (typeof object.stringData[i] === "string")
|
|
$util.base64.decode(object.stringData[i], message.stringData[i] = $util.newBuffer($util.base64.length(object.stringData[i])), 0);
|
|
else if (object.stringData[i].length)
|
|
message.stringData[i] = object.stringData[i];
|
|
}
|
|
if (object.int64Data) {
|
|
if (!Array.isArray(object.int64Data))
|
|
throw TypeError(".onnx.TensorProto.int64Data: array expected");
|
|
message.int64Data = [];
|
|
for (var i = 0; i < object.int64Data.length; ++i)
|
|
if ($util.Long)
|
|
(message.int64Data[i] = $util.Long.fromValue(object.int64Data[i])).unsigned = false;
|
|
else if (typeof object.int64Data[i] === "string")
|
|
message.int64Data[i] = parseInt(object.int64Data[i], 10);
|
|
else if (typeof object.int64Data[i] === "number")
|
|
message.int64Data[i] = object.int64Data[i];
|
|
else if (typeof object.int64Data[i] === "object")
|
|
message.int64Data[i] = new $util.LongBits(object.int64Data[i].low >>> 0, object.int64Data[i].high >>> 0).toNumber();
|
|
}
|
|
if (object.name != null)
|
|
message.name = String(object.name);
|
|
if (object.docString != null)
|
|
message.docString = String(object.docString);
|
|
if (object.rawData != null)
|
|
if (typeof object.rawData === "string")
|
|
$util.base64.decode(object.rawData, message.rawData = $util.newBuffer($util.base64.length(object.rawData)), 0);
|
|
else if (object.rawData.length)
|
|
message.rawData = object.rawData;
|
|
if (object.externalData) {
|
|
if (!Array.isArray(object.externalData))
|
|
throw TypeError(".onnx.TensorProto.externalData: array expected");
|
|
message.externalData = [];
|
|
for (var i = 0; i < object.externalData.length; ++i) {
|
|
if (typeof object.externalData[i] !== "object")
|
|
throw TypeError(".onnx.TensorProto.externalData: object expected");
|
|
message.externalData[i] = $root.onnx.StringStringEntryProto.fromObject(object.externalData[i]);
|
|
}
|
|
}
|
|
switch (object.dataLocation) {
|
|
case "DEFAULT":
|
|
case 0:
|
|
message.dataLocation = 0;
|
|
break;
|
|
case "EXTERNAL":
|
|
case 1:
|
|
message.dataLocation = 1;
|
|
break;
|
|
}
|
|
if (object.doubleData) {
|
|
if (!Array.isArray(object.doubleData))
|
|
throw TypeError(".onnx.TensorProto.doubleData: array expected");
|
|
message.doubleData = [];
|
|
for (var i = 0; i < object.doubleData.length; ++i)
|
|
message.doubleData[i] = Number(object.doubleData[i]);
|
|
}
|
|
if (object.uint64Data) {
|
|
if (!Array.isArray(object.uint64Data))
|
|
throw TypeError(".onnx.TensorProto.uint64Data: array expected");
|
|
message.uint64Data = [];
|
|
for (var i = 0; i < object.uint64Data.length; ++i)
|
|
if ($util.Long)
|
|
(message.uint64Data[i] = $util.Long.fromValue(object.uint64Data[i])).unsigned = true;
|
|
else if (typeof object.uint64Data[i] === "string")
|
|
message.uint64Data[i] = parseInt(object.uint64Data[i], 10);
|
|
else if (typeof object.uint64Data[i] === "number")
|
|
message.uint64Data[i] = object.uint64Data[i];
|
|
else if (typeof object.uint64Data[i] === "object")
|
|
message.uint64Data[i] = new $util.LongBits(object.uint64Data[i].low >>> 0, object.uint64Data[i].high >>> 0).toNumber(true);
|
|
}
|
|
return message;
|
|
};
|
|
|
|
/**
|
|
* Creates a plain object from a TensorProto message. Also converts values to other types if specified.
|
|
* @function toObject
|
|
* @memberof onnx.TensorProto
|
|
* @static
|
|
* @param {onnx.TensorProto} message TensorProto
|
|
* @param {$protobuf.IConversionOptions} [options] Conversion options
|
|
* @returns {Object.<string,*>} Plain object
|
|
*/
|
|
TensorProto.toObject = function toObject(message, options) {
|
|
if (!options)
|
|
options = {};
|
|
var object = {};
|
|
if (options.arrays || options.defaults) {
|
|
object.dims = [];
|
|
object.floatData = [];
|
|
object.int32Data = [];
|
|
object.stringData = [];
|
|
object.int64Data = [];
|
|
object.doubleData = [];
|
|
object.uint64Data = [];
|
|
object.externalData = [];
|
|
}
|
|
if (options.defaults) {
|
|
object.dataType = 0;
|
|
object.segment = null;
|
|
object.name = "";
|
|
if (options.bytes === String)
|
|
object.rawData = "";
|
|
else {
|
|
object.rawData = [];
|
|
if (options.bytes !== Array)
|
|
object.rawData = $util.newBuffer(object.rawData);
|
|
}
|
|
object.docString = "";
|
|
object.dataLocation = options.enums === String ? "DEFAULT" : 0;
|
|
}
|
|
if (message.dims && message.dims.length) {
|
|
object.dims = [];
|
|
for (var j = 0; j < message.dims.length; ++j)
|
|
if (typeof message.dims[j] === "number")
|
|
object.dims[j] = options.longs === String ? String(message.dims[j]) : message.dims[j];
|
|
else
|
|
object.dims[j] = options.longs === String ? $util.Long.prototype.toString.call(message.dims[j]) : options.longs === Number ? new $util.LongBits(message.dims[j].low >>> 0, message.dims[j].high >>> 0).toNumber() : message.dims[j];
|
|
}
|
|
if (message.dataType != null && message.hasOwnProperty("dataType"))
|
|
object.dataType = message.dataType;
|
|
if (message.segment != null && message.hasOwnProperty("segment"))
|
|
object.segment = $root.onnx.TensorProto.Segment.toObject(message.segment, options);
|
|
if (message.floatData && message.floatData.length) {
|
|
object.floatData = [];
|
|
for (var j = 0; j < message.floatData.length; ++j)
|
|
object.floatData[j] = options.json && !isFinite(message.floatData[j]) ? String(message.floatData[j]) : message.floatData[j];
|
|
}
|
|
if (message.int32Data && message.int32Data.length) {
|
|
object.int32Data = [];
|
|
for (var j = 0; j < message.int32Data.length; ++j)
|
|
object.int32Data[j] = message.int32Data[j];
|
|
}
|
|
if (message.stringData && message.stringData.length) {
|
|
object.stringData = [];
|
|
for (var j = 0; j < message.stringData.length; ++j)
|
|
object.stringData[j] = options.bytes === String ? $util.base64.encode(message.stringData[j], 0, message.stringData[j].length) : options.bytes === Array ? Array.prototype.slice.call(message.stringData[j]) : message.stringData[j];
|
|
}
|
|
if (message.int64Data && message.int64Data.length) {
|
|
object.int64Data = [];
|
|
for (var j = 0; j < message.int64Data.length; ++j)
|
|
if (typeof message.int64Data[j] === "number")
|
|
object.int64Data[j] = options.longs === String ? String(message.int64Data[j]) : message.int64Data[j];
|
|
else
|
|
object.int64Data[j] = options.longs === String ? $util.Long.prototype.toString.call(message.int64Data[j]) : options.longs === Number ? new $util.LongBits(message.int64Data[j].low >>> 0, message.int64Data[j].high >>> 0).toNumber() : message.int64Data[j];
|
|
}
|
|
if (message.name != null && message.hasOwnProperty("name"))
|
|
object.name = message.name;
|
|
if (message.rawData != null && message.hasOwnProperty("rawData"))
|
|
object.rawData = options.bytes === String ? $util.base64.encode(message.rawData, 0, message.rawData.length) : options.bytes === Array ? Array.prototype.slice.call(message.rawData) : message.rawData;
|
|
if (message.doubleData && message.doubleData.length) {
|
|
object.doubleData = [];
|
|
for (var j = 0; j < message.doubleData.length; ++j)
|
|
object.doubleData[j] = options.json && !isFinite(message.doubleData[j]) ? String(message.doubleData[j]) : message.doubleData[j];
|
|
}
|
|
if (message.uint64Data && message.uint64Data.length) {
|
|
object.uint64Data = [];
|
|
for (var j = 0; j < message.uint64Data.length; ++j)
|
|
if (typeof message.uint64Data[j] === "number")
|
|
object.uint64Data[j] = options.longs === String ? String(message.uint64Data[j]) : message.uint64Data[j];
|
|
else
|
|
object.uint64Data[j] = options.longs === String ? $util.Long.prototype.toString.call(message.uint64Data[j]) : options.longs === Number ? new $util.LongBits(message.uint64Data[j].low >>> 0, message.uint64Data[j].high >>> 0).toNumber(true) : message.uint64Data[j];
|
|
}
|
|
if (message.docString != null && message.hasOwnProperty("docString"))
|
|
object.docString = message.docString;
|
|
if (message.externalData && message.externalData.length) {
|
|
object.externalData = [];
|
|
for (var j = 0; j < message.externalData.length; ++j)
|
|
object.externalData[j] = $root.onnx.StringStringEntryProto.toObject(message.externalData[j], options);
|
|
}
|
|
if (message.dataLocation != null && message.hasOwnProperty("dataLocation"))
|
|
object.dataLocation = options.enums === String ? $root.onnx.TensorProto.DataLocation[message.dataLocation] : message.dataLocation;
|
|
return object;
|
|
};
|
|
|
|
/**
|
|
* Converts this TensorProto to JSON.
|
|
* @function toJSON
|
|
* @memberof onnx.TensorProto
|
|
* @instance
|
|
* @returns {Object.<string,*>} JSON object
|
|
*/
|
|
TensorProto.prototype.toJSON = function toJSON() {
|
|
return this.constructor.toObject(this, $protobuf.util.toJSONOptions);
|
|
};
|
|
|
|
/**
|
|
* DataType enum.
|
|
* @name onnx.TensorProto.DataType
|
|
* @enum {string}
|
|
* @property {number} UNDEFINED=0 UNDEFINED value
|
|
* @property {number} FLOAT=1 FLOAT value
|
|
* @property {number} UINT8=2 UINT8 value
|
|
* @property {number} INT8=3 INT8 value
|
|
* @property {number} UINT16=4 UINT16 value
|
|
* @property {number} INT16=5 INT16 value
|
|
* @property {number} INT32=6 INT32 value
|
|
* @property {number} INT64=7 INT64 value
|
|
* @property {number} STRING=8 STRING value
|
|
* @property {number} BOOL=9 BOOL value
|
|
* @property {number} FLOAT16=10 FLOAT16 value
|
|
* @property {number} DOUBLE=11 DOUBLE value
|
|
* @property {number} UINT32=12 UINT32 value
|
|
* @property {number} UINT64=13 UINT64 value
|
|
* @property {number} COMPLEX64=14 COMPLEX64 value
|
|
* @property {number} COMPLEX128=15 COMPLEX128 value
|
|
* @property {number} BFLOAT16=16 BFLOAT16 value
|
|
*/
|
|
TensorProto.DataType = (function() {
|
|
var valuesById = {}, values = Object.create(valuesById);
|
|
values[valuesById[0] = "UNDEFINED"] = 0;
|
|
values[valuesById[1] = "FLOAT"] = 1;
|
|
values[valuesById[2] = "UINT8"] = 2;
|
|
values[valuesById[3] = "INT8"] = 3;
|
|
values[valuesById[4] = "UINT16"] = 4;
|
|
values[valuesById[5] = "INT16"] = 5;
|
|
values[valuesById[6] = "INT32"] = 6;
|
|
values[valuesById[7] = "INT64"] = 7;
|
|
values[valuesById[8] = "STRING"] = 8;
|
|
values[valuesById[9] = "BOOL"] = 9;
|
|
values[valuesById[10] = "FLOAT16"] = 10;
|
|
values[valuesById[11] = "DOUBLE"] = 11;
|
|
values[valuesById[12] = "UINT32"] = 12;
|
|
values[valuesById[13] = "UINT64"] = 13;
|
|
values[valuesById[14] = "COMPLEX64"] = 14;
|
|
values[valuesById[15] = "COMPLEX128"] = 15;
|
|
values[valuesById[16] = "BFLOAT16"] = 16;
|
|
return values;
|
|
})();
|
|
|
|
TensorProto.Segment = (function() {
|
|
|
|
/**
|
|
* Properties of a Segment.
|
|
* @memberof onnx.TensorProto
|
|
* @interface ISegment
|
|
* @property {number|Long|null} [begin] Segment begin
|
|
* @property {number|Long|null} [end] Segment end
|
|
*/
|
|
|
|
/**
|
|
* Constructs a new Segment.
|
|
* @memberof onnx.TensorProto
|
|
* @classdesc Represents a Segment.
|
|
* @implements ISegment
|
|
* @constructor
|
|
* @param {onnx.TensorProto.ISegment=} [properties] Properties to set
|
|
*/
|
|
function Segment(properties) {
|
|
if (properties)
|
|
for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
|
|
if (properties[keys[i]] != null)
|
|
this[keys[i]] = properties[keys[i]];
|
|
}
|
|
|
|
/**
|
|
* Segment begin.
|
|
* @member {number|Long} begin
|
|
* @memberof onnx.TensorProto.Segment
|
|
* @instance
|
|
*/
|
|
Segment.prototype.begin = $util.Long ? $util.Long.fromBits(0,0,false) : 0;
|
|
|
|
/**
|
|
* Segment end.
|
|
* @member {number|Long} end
|
|
* @memberof onnx.TensorProto.Segment
|
|
* @instance
|
|
*/
|
|
Segment.prototype.end = $util.Long ? $util.Long.fromBits(0,0,false) : 0;
|
|
|
|
/**
|
|
* Creates a new Segment instance using the specified properties.
|
|
* @function create
|
|
* @memberof onnx.TensorProto.Segment
|
|
* @static
|
|
* @param {onnx.TensorProto.ISegment=} [properties] Properties to set
|
|
* @returns {onnx.TensorProto.Segment} Segment instance
|
|
*/
|
|
Segment.create = function create(properties) {
|
|
return new Segment(properties);
|
|
};
|
|
|
|
/**
|
|
* Encodes the specified Segment message. Does not implicitly {@link onnx.TensorProto.Segment.verify|verify} messages.
|
|
* @function encode
|
|
* @memberof onnx.TensorProto.Segment
|
|
* @static
|
|
* @param {onnx.TensorProto.ISegment} message Segment message or plain object to encode
|
|
* @param {$protobuf.Writer} [writer] Writer to encode to
|
|
* @returns {$protobuf.Writer} Writer
|
|
*/
|
|
Segment.encode = function encode(message, writer) {
|
|
if (!writer)
|
|
writer = $Writer.create();
|
|
if (message.begin != null && message.hasOwnProperty("begin"))
|
|
writer.uint32(/* id 1, wireType 0 =*/8).int64(message.begin);
|
|
if (message.end != null && message.hasOwnProperty("end"))
|
|
writer.uint32(/* id 2, wireType 0 =*/16).int64(message.end);
|
|
return writer;
|
|
};
|
|
|
|
/**
|
|
* Encodes the specified Segment message, length delimited. Does not implicitly {@link onnx.TensorProto.Segment.verify|verify} messages.
|
|
* @function encodeDelimited
|
|
* @memberof onnx.TensorProto.Segment
|
|
* @static
|
|
* @param {onnx.TensorProto.ISegment} message Segment message or plain object to encode
|
|
* @param {$protobuf.Writer} [writer] Writer to encode to
|
|
* @returns {$protobuf.Writer} Writer
|
|
*/
|
|
Segment.encodeDelimited = function encodeDelimited(message, writer) {
|
|
return this.encode(message, writer).ldelim();
|
|
};
|
|
|
|
/**
|
|
* Decodes a Segment message from the specified reader or buffer.
|
|
* @function decode
|
|
* @memberof onnx.TensorProto.Segment
|
|
* @static
|
|
* @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
|
|
* @param {number} [length] Message length if known beforehand
|
|
* @returns {onnx.TensorProto.Segment} Segment
|
|
* @throws {Error} If the payload is not a reader or valid buffer
|
|
* @throws {$protobuf.util.ProtocolError} If required fields are missing
|
|
*/
|
|
Segment.decode = function decode(reader, length) {
|
|
if (!(reader instanceof $Reader))
|
|
reader = $Reader.create(reader);
|
|
var end = length === undefined ? reader.len : reader.pos + length, message = new $root.onnx.TensorProto.Segment();
|
|
while (reader.pos < end) {
|
|
var tag = reader.uint32();
|
|
switch (tag >>> 3) {
|
|
case 1:
|
|
message.begin = reader.int64();
|
|
break;
|
|
case 2:
|
|
message.end = reader.int64();
|
|
break;
|
|
default:
|
|
reader.skipType(tag & 7);
|
|
break;
|
|
}
|
|
}
|
|
return message;
|
|
};
|
|
|
|
/**
|
|
* Decodes a Segment message from the specified reader or buffer, length delimited.
|
|
* @function decodeDelimited
|
|
* @memberof onnx.TensorProto.Segment
|
|
* @static
|
|
* @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
|
|
* @returns {onnx.TensorProto.Segment} Segment
|
|
* @throws {Error} If the payload is not a reader or valid buffer
|
|
* @throws {$protobuf.util.ProtocolError} If required fields are missing
|
|
*/
|
|
Segment.decodeDelimited = function decodeDelimited(reader) {
|
|
if (!(reader instanceof $Reader))
|
|
reader = new $Reader(reader);
|
|
return this.decode(reader, reader.uint32());
|
|
};
|
|
|
|
/**
|
|
* Verifies a Segment message.
|
|
* @function verify
|
|
* @memberof onnx.TensorProto.Segment
|
|
* @static
|
|
* @param {Object.<string,*>} message Plain object to verify
|
|
* @returns {string|null} `null` if valid, otherwise the reason why it is not
|
|
*/
|
|
Segment.verify = function verify(message) {
|
|
if (typeof message !== "object" || message === null)
|
|
return "object expected";
|
|
if (message.begin != null && message.hasOwnProperty("begin"))
|
|
if (!$util.isInteger(message.begin) && !(message.begin && $util.isInteger(message.begin.low) && $util.isInteger(message.begin.high)))
|
|
return "begin: integer|Long expected";
|
|
if (message.end != null && message.hasOwnProperty("end"))
|
|
if (!$util.isInteger(message.end) && !(message.end && $util.isInteger(message.end.low) && $util.isInteger(message.end.high)))
|
|
return "end: integer|Long expected";
|
|
return null;
|
|
};
|
|
|
|
/**
|
|
* Creates a Segment message from a plain object. Also converts values to their respective internal types.
|
|
* @function fromObject
|
|
* @memberof onnx.TensorProto.Segment
|
|
* @static
|
|
* @param {Object.<string,*>} object Plain object
|
|
* @returns {onnx.TensorProto.Segment} Segment
|
|
*/
|
|
Segment.fromObject = function fromObject(object) {
|
|
if (object instanceof $root.onnx.TensorProto.Segment)
|
|
return object;
|
|
var message = new $root.onnx.TensorProto.Segment();
|
|
if (object.begin != null)
|
|
if ($util.Long)
|
|
(message.begin = $util.Long.fromValue(object.begin)).unsigned = false;
|
|
else if (typeof object.begin === "string")
|
|
message.begin = parseInt(object.begin, 10);
|
|
else if (typeof object.begin === "number")
|
|
message.begin = object.begin;
|
|
else if (typeof object.begin === "object")
|
|
message.begin = new $util.LongBits(object.begin.low >>> 0, object.begin.high >>> 0).toNumber();
|
|
if (object.end != null)
|
|
if ($util.Long)
|
|
(message.end = $util.Long.fromValue(object.end)).unsigned = false;
|
|
else if (typeof object.end === "string")
|
|
message.end = parseInt(object.end, 10);
|
|
else if (typeof object.end === "number")
|
|
message.end = object.end;
|
|
else if (typeof object.end === "object")
|
|
message.end = new $util.LongBits(object.end.low >>> 0, object.end.high >>> 0).toNumber();
|
|
return message;
|
|
};
|
|
|
|
/**
|
|
* Creates a plain object from a Segment message. Also converts values to other types if specified.
|
|
* @function toObject
|
|
* @memberof onnx.TensorProto.Segment
|
|
* @static
|
|
* @param {onnx.TensorProto.Segment} message Segment
|
|
* @param {$protobuf.IConversionOptions} [options] Conversion options
|
|
* @returns {Object.<string,*>} Plain object
|
|
*/
|
|
Segment.toObject = function toObject(message, options) {
|
|
if (!options)
|
|
options = {};
|
|
var object = {};
|
|
if (options.defaults) {
|
|
if ($util.Long) {
|
|
var long = new $util.Long(0, 0, false);
|
|
object.begin = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
|
|
} else
|
|
object.begin = options.longs === String ? "0" : 0;
|
|
if ($util.Long) {
|
|
var long = new $util.Long(0, 0, false);
|
|
object.end = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
|
|
} else
|
|
object.end = options.longs === String ? "0" : 0;
|
|
}
|
|
if (message.begin != null && message.hasOwnProperty("begin"))
|
|
if (typeof message.begin === "number")
|
|
object.begin = options.longs === String ? String(message.begin) : message.begin;
|
|
else
|
|
object.begin = options.longs === String ? $util.Long.prototype.toString.call(message.begin) : options.longs === Number ? new $util.LongBits(message.begin.low >>> 0, message.begin.high >>> 0).toNumber() : message.begin;
|
|
if (message.end != null && message.hasOwnProperty("end"))
|
|
if (typeof message.end === "number")
|
|
object.end = options.longs === String ? String(message.end) : message.end;
|
|
else
|
|
object.end = options.longs === String ? $util.Long.prototype.toString.call(message.end) : options.longs === Number ? new $util.LongBits(message.end.low >>> 0, message.end.high >>> 0).toNumber() : message.end;
|
|
return object;
|
|
};
|
|
|
|
/**
|
|
* Converts this Segment to JSON.
|
|
* @function toJSON
|
|
* @memberof onnx.TensorProto.Segment
|
|
* @instance
|
|
* @returns {Object.<string,*>} JSON object
|
|
*/
|
|
Segment.prototype.toJSON = function toJSON() {
|
|
return this.constructor.toObject(this, $protobuf.util.toJSONOptions);
|
|
};
|
|
|
|
return Segment;
|
|
})();
|
|
|
|
/**
|
|
* DataLocation enum.
|
|
* @name onnx.TensorProto.DataLocation
|
|
* @enum {string}
|
|
* @property {number} DEFAULT=0 DEFAULT value
|
|
* @property {number} EXTERNAL=1 EXTERNAL value
|
|
*/
|
|
TensorProto.DataLocation = (function() {
|
|
var valuesById = {}, values = Object.create(valuesById);
|
|
values[valuesById[0] = "DEFAULT"] = 0;
|
|
values[valuesById[1] = "EXTERNAL"] = 1;
|
|
return values;
|
|
})();
|
|
|
|
return TensorProto;
|
|
})();
|
|
|
|
onnx.TensorShapeProto = (function() {
|
|
|
|
/**
|
|
* Properties of a TensorShapeProto.
|
|
* @memberof onnx
|
|
* @interface ITensorShapeProto
|
|
* @property {Array.<onnx.TensorShapeProto.IDimension>|null} [dim] TensorShapeProto dim
|
|
*/
|
|
|
|
/**
|
|
* Constructs a new TensorShapeProto.
|
|
* @memberof onnx
|
|
* @classdesc Represents a TensorShapeProto.
|
|
* @implements ITensorShapeProto
|
|
* @constructor
|
|
* @param {onnx.ITensorShapeProto=} [properties] Properties to set
|
|
*/
|
|
function TensorShapeProto(properties) {
|
|
this.dim = [];
|
|
if (properties)
|
|
for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
|
|
if (properties[keys[i]] != null)
|
|
this[keys[i]] = properties[keys[i]];
|
|
}
|
|
|
|
/**
|
|
* TensorShapeProto dim.
|
|
* @member {Array.<onnx.TensorShapeProto.IDimension>} dim
|
|
* @memberof onnx.TensorShapeProto
|
|
* @instance
|
|
*/
|
|
TensorShapeProto.prototype.dim = $util.emptyArray;
|
|
|
|
/**
|
|
* Creates a new TensorShapeProto instance using the specified properties.
|
|
* @function create
|
|
* @memberof onnx.TensorShapeProto
|
|
* @static
|
|
* @param {onnx.ITensorShapeProto=} [properties] Properties to set
|
|
* @returns {onnx.TensorShapeProto} TensorShapeProto instance
|
|
*/
|
|
TensorShapeProto.create = function create(properties) {
|
|
return new TensorShapeProto(properties);
|
|
};
|
|
|
|
/**
|
|
* Encodes the specified TensorShapeProto message. Does not implicitly {@link onnx.TensorShapeProto.verify|verify} messages.
|
|
* @function encode
|
|
* @memberof onnx.TensorShapeProto
|
|
* @static
|
|
* @param {onnx.ITensorShapeProto} message TensorShapeProto message or plain object to encode
|
|
* @param {$protobuf.Writer} [writer] Writer to encode to
|
|
* @returns {$protobuf.Writer} Writer
|
|
*/
|
|
TensorShapeProto.encode = function encode(message, writer) {
|
|
if (!writer)
|
|
writer = $Writer.create();
|
|
if (message.dim != null && message.dim.length)
|
|
for (var i = 0; i < message.dim.length; ++i)
|
|
$root.onnx.TensorShapeProto.Dimension.encode(message.dim[i], writer.uint32(/* id 1, wireType 2 =*/10).fork()).ldelim();
|
|
return writer;
|
|
};
|
|
|
|
/**
|
|
* Encodes the specified TensorShapeProto message, length delimited. Does not implicitly {@link onnx.TensorShapeProto.verify|verify} messages.
|
|
* @function encodeDelimited
|
|
* @memberof onnx.TensorShapeProto
|
|
* @static
|
|
* @param {onnx.ITensorShapeProto} message TensorShapeProto message or plain object to encode
|
|
* @param {$protobuf.Writer} [writer] Writer to encode to
|
|
* @returns {$protobuf.Writer} Writer
|
|
*/
|
|
TensorShapeProto.encodeDelimited = function encodeDelimited(message, writer) {
|
|
return this.encode(message, writer).ldelim();
|
|
};
|
|
|
|
/**
|
|
* Decodes a TensorShapeProto message from the specified reader or buffer.
|
|
* @function decode
|
|
* @memberof onnx.TensorShapeProto
|
|
* @static
|
|
* @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
|
|
* @param {number} [length] Message length if known beforehand
|
|
* @returns {onnx.TensorShapeProto} TensorShapeProto
|
|
* @throws {Error} If the payload is not a reader or valid buffer
|
|
* @throws {$protobuf.util.ProtocolError} If required fields are missing
|
|
*/
|
|
TensorShapeProto.decode = function decode(reader, length) {
|
|
if (!(reader instanceof $Reader))
|
|
reader = $Reader.create(reader);
|
|
var end = length === undefined ? reader.len : reader.pos + length, message = new $root.onnx.TensorShapeProto();
|
|
while (reader.pos < end) {
|
|
var tag = reader.uint32();
|
|
switch (tag >>> 3) {
|
|
case 1:
|
|
if (!(message.dim && message.dim.length))
|
|
message.dim = [];
|
|
message.dim.push($root.onnx.TensorShapeProto.Dimension.decode(reader, reader.uint32()));
|
|
break;
|
|
default:
|
|
reader.skipType(tag & 7);
|
|
break;
|
|
}
|
|
}
|
|
return message;
|
|
};
|
|
|
|
/**
|
|
* Decodes a TensorShapeProto message from the specified reader or buffer, length delimited.
|
|
* @function decodeDelimited
|
|
* @memberof onnx.TensorShapeProto
|
|
* @static
|
|
* @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
|
|
* @returns {onnx.TensorShapeProto} TensorShapeProto
|
|
* @throws {Error} If the payload is not a reader or valid buffer
|
|
* @throws {$protobuf.util.ProtocolError} If required fields are missing
|
|
*/
|
|
TensorShapeProto.decodeDelimited = function decodeDelimited(reader) {
|
|
if (!(reader instanceof $Reader))
|
|
reader = new $Reader(reader);
|
|
return this.decode(reader, reader.uint32());
|
|
};
|
|
|
|
/**
|
|
* Verifies a TensorShapeProto message.
|
|
* @function verify
|
|
* @memberof onnx.TensorShapeProto
|
|
* @static
|
|
* @param {Object.<string,*>} message Plain object to verify
|
|
* @returns {string|null} `null` if valid, otherwise the reason why it is not
|
|
*/
|
|
TensorShapeProto.verify = function verify(message) {
|
|
if (typeof message !== "object" || message === null)
|
|
return "object expected";
|
|
if (message.dim != null && message.hasOwnProperty("dim")) {
|
|
if (!Array.isArray(message.dim))
|
|
return "dim: array expected";
|
|
for (var i = 0; i < message.dim.length; ++i) {
|
|
var error = $root.onnx.TensorShapeProto.Dimension.verify(message.dim[i]);
|
|
if (error)
|
|
return "dim." + error;
|
|
}
|
|
}
|
|
return null;
|
|
};
|
|
|
|
/**
|
|
* Creates a TensorShapeProto message from a plain object. Also converts values to their respective internal types.
|
|
* @function fromObject
|
|
* @memberof onnx.TensorShapeProto
|
|
* @static
|
|
* @param {Object.<string,*>} object Plain object
|
|
* @returns {onnx.TensorShapeProto} TensorShapeProto
|
|
*/
|
|
TensorShapeProto.fromObject = function fromObject(object) {
|
|
if (object instanceof $root.onnx.TensorShapeProto)
|
|
return object;
|
|
var message = new $root.onnx.TensorShapeProto();
|
|
if (object.dim) {
|
|
if (!Array.isArray(object.dim))
|
|
throw TypeError(".onnx.TensorShapeProto.dim: array expected");
|
|
message.dim = [];
|
|
for (var i = 0; i < object.dim.length; ++i) {
|
|
if (typeof object.dim[i] !== "object")
|
|
throw TypeError(".onnx.TensorShapeProto.dim: object expected");
|
|
message.dim[i] = $root.onnx.TensorShapeProto.Dimension.fromObject(object.dim[i]);
|
|
}
|
|
}
|
|
return message;
|
|
};
|
|
|
|
/**
|
|
* Creates a plain object from a TensorShapeProto message. Also converts values to other types if specified.
|
|
* @function toObject
|
|
* @memberof onnx.TensorShapeProto
|
|
* @static
|
|
* @param {onnx.TensorShapeProto} message TensorShapeProto
|
|
* @param {$protobuf.IConversionOptions} [options] Conversion options
|
|
* @returns {Object.<string,*>} Plain object
|
|
*/
|
|
TensorShapeProto.toObject = function toObject(message, options) {
|
|
if (!options)
|
|
options = {};
|
|
var object = {};
|
|
if (options.arrays || options.defaults)
|
|
object.dim = [];
|
|
if (message.dim && message.dim.length) {
|
|
object.dim = [];
|
|
for (var j = 0; j < message.dim.length; ++j)
|
|
object.dim[j] = $root.onnx.TensorShapeProto.Dimension.toObject(message.dim[j], options);
|
|
}
|
|
return object;
|
|
};
|
|
|
|
/**
|
|
* Converts this TensorShapeProto to JSON.
|
|
* @function toJSON
|
|
* @memberof onnx.TensorShapeProto
|
|
* @instance
|
|
* @returns {Object.<string,*>} JSON object
|
|
*/
|
|
TensorShapeProto.prototype.toJSON = function toJSON() {
|
|
return this.constructor.toObject(this, $protobuf.util.toJSONOptions);
|
|
};
|
|
|
|
TensorShapeProto.Dimension = (function() {
|
|
|
|
/**
|
|
* Properties of a Dimension.
|
|
* @memberof onnx.TensorShapeProto
|
|
* @interface IDimension
|
|
* @property {number|Long|null} [dimValue] Dimension dimValue
|
|
* @property {string|null} [dimParam] Dimension dimParam
|
|
* @property {string|null} [denotation] Dimension denotation
|
|
*/
|
|
|
|
/**
|
|
* Constructs a new Dimension.
|
|
* @memberof onnx.TensorShapeProto
|
|
* @classdesc Represents a Dimension.
|
|
* @implements IDimension
|
|
* @constructor
|
|
* @param {onnx.TensorShapeProto.IDimension=} [properties] Properties to set
|
|
*/
|
|
function Dimension(properties) {
|
|
if (properties)
|
|
for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
|
|
if (properties[keys[i]] != null)
|
|
this[keys[i]] = properties[keys[i]];
|
|
}
|
|
|
|
/**
|
|
* Dimension dimValue.
|
|
* @member {number|Long} dimValue
|
|
* @memberof onnx.TensorShapeProto.Dimension
|
|
* @instance
|
|
*/
|
|
Dimension.prototype.dimValue = $util.Long ? $util.Long.fromBits(0,0,false) : 0;
|
|
|
|
/**
|
|
* Dimension dimParam.
|
|
* @member {string} dimParam
|
|
* @memberof onnx.TensorShapeProto.Dimension
|
|
* @instance
|
|
*/
|
|
Dimension.prototype.dimParam = "";
|
|
|
|
/**
|
|
* Dimension denotation.
|
|
* @member {string} denotation
|
|
* @memberof onnx.TensorShapeProto.Dimension
|
|
* @instance
|
|
*/
|
|
Dimension.prototype.denotation = "";
|
|
|
|
// OneOf field names bound to virtual getters and setters
|
|
var $oneOfFields;
|
|
|
|
/**
|
|
* Dimension value.
|
|
* @member {"dimValue"|"dimParam"|undefined} value
|
|
* @memberof onnx.TensorShapeProto.Dimension
|
|
* @instance
|
|
*/
|
|
Object.defineProperty(Dimension.prototype, "value", {
|
|
get: $util.oneOfGetter($oneOfFields = ["dimValue", "dimParam"]),
|
|
set: $util.oneOfSetter($oneOfFields)
|
|
});
|
|
|
|
/**
|
|
* Creates a new Dimension instance using the specified properties.
|
|
* @function create
|
|
* @memberof onnx.TensorShapeProto.Dimension
|
|
* @static
|
|
* @param {onnx.TensorShapeProto.IDimension=} [properties] Properties to set
|
|
* @returns {onnx.TensorShapeProto.Dimension} Dimension instance
|
|
*/
|
|
Dimension.create = function create(properties) {
|
|
return new Dimension(properties);
|
|
};
|
|
|
|
/**
|
|
* Encodes the specified Dimension message. Does not implicitly {@link onnx.TensorShapeProto.Dimension.verify|verify} messages.
|
|
* @function encode
|
|
* @memberof onnx.TensorShapeProto.Dimension
|
|
* @static
|
|
* @param {onnx.TensorShapeProto.IDimension} message Dimension message or plain object to encode
|
|
* @param {$protobuf.Writer} [writer] Writer to encode to
|
|
* @returns {$protobuf.Writer} Writer
|
|
*/
|
|
Dimension.encode = function encode(message, writer) {
|
|
if (!writer)
|
|
writer = $Writer.create();
|
|
if (message.dimValue != null && message.hasOwnProperty("dimValue"))
|
|
writer.uint32(/* id 1, wireType 0 =*/8).int64(message.dimValue);
|
|
if (message.dimParam != null && message.hasOwnProperty("dimParam"))
|
|
writer.uint32(/* id 2, wireType 2 =*/18).string(message.dimParam);
|
|
if (message.denotation != null && message.hasOwnProperty("denotation"))
|
|
writer.uint32(/* id 3, wireType 2 =*/26).string(message.denotation);
|
|
return writer;
|
|
};
|
|
|
|
/**
|
|
* Encodes the specified Dimension message, length delimited. Does not implicitly {@link onnx.TensorShapeProto.Dimension.verify|verify} messages.
|
|
* @function encodeDelimited
|
|
* @memberof onnx.TensorShapeProto.Dimension
|
|
* @static
|
|
* @param {onnx.TensorShapeProto.IDimension} message Dimension message or plain object to encode
|
|
* @param {$protobuf.Writer} [writer] Writer to encode to
|
|
* @returns {$protobuf.Writer} Writer
|
|
*/
|
|
Dimension.encodeDelimited = function encodeDelimited(message, writer) {
|
|
return this.encode(message, writer).ldelim();
|
|
};
|
|
|
|
/**
|
|
* Decodes a Dimension message from the specified reader or buffer.
|
|
* @function decode
|
|
* @memberof onnx.TensorShapeProto.Dimension
|
|
* @static
|
|
* @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
|
|
* @param {number} [length] Message length if known beforehand
|
|
* @returns {onnx.TensorShapeProto.Dimension} Dimension
|
|
* @throws {Error} If the payload is not a reader or valid buffer
|
|
* @throws {$protobuf.util.ProtocolError} If required fields are missing
|
|
*/
|
|
Dimension.decode = function decode(reader, length) {
|
|
if (!(reader instanceof $Reader))
|
|
reader = $Reader.create(reader);
|
|
var end = length === undefined ? reader.len : reader.pos + length, message = new $root.onnx.TensorShapeProto.Dimension();
|
|
while (reader.pos < end) {
|
|
var tag = reader.uint32();
|
|
switch (tag >>> 3) {
|
|
case 1:
|
|
message.dimValue = reader.int64();
|
|
break;
|
|
case 2:
|
|
message.dimParam = reader.string();
|
|
break;
|
|
case 3:
|
|
message.denotation = reader.string();
|
|
break;
|
|
default:
|
|
reader.skipType(tag & 7);
|
|
break;
|
|
}
|
|
}
|
|
return message;
|
|
};
|
|
|
|
/**
|
|
* Decodes a Dimension message from the specified reader or buffer, length delimited.
|
|
* @function decodeDelimited
|
|
* @memberof onnx.TensorShapeProto.Dimension
|
|
* @static
|
|
* @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
|
|
* @returns {onnx.TensorShapeProto.Dimension} Dimension
|
|
* @throws {Error} If the payload is not a reader or valid buffer
|
|
* @throws {$protobuf.util.ProtocolError} If required fields are missing
|
|
*/
|
|
Dimension.decodeDelimited = function decodeDelimited(reader) {
|
|
if (!(reader instanceof $Reader))
|
|
reader = new $Reader(reader);
|
|
return this.decode(reader, reader.uint32());
|
|
};
|
|
|
|
/**
|
|
* Verifies a Dimension message.
|
|
* @function verify
|
|
* @memberof onnx.TensorShapeProto.Dimension
|
|
* @static
|
|
* @param {Object.<string,*>} message Plain object to verify
|
|
* @returns {string|null} `null` if valid, otherwise the reason why it is not
|
|
*/
|
|
Dimension.verify = function verify(message) {
|
|
if (typeof message !== "object" || message === null)
|
|
return "object expected";
|
|
var properties = {};
|
|
if (message.dimValue != null && message.hasOwnProperty("dimValue")) {
|
|
properties.value = 1;
|
|
if (!$util.isInteger(message.dimValue) && !(message.dimValue && $util.isInteger(message.dimValue.low) && $util.isInteger(message.dimValue.high)))
|
|
return "dimValue: integer|Long expected";
|
|
}
|
|
if (message.dimParam != null && message.hasOwnProperty("dimParam")) {
|
|
if (properties.value === 1)
|
|
return "value: multiple values";
|
|
properties.value = 1;
|
|
if (!$util.isString(message.dimParam))
|
|
return "dimParam: string expected";
|
|
}
|
|
if (message.denotation != null && message.hasOwnProperty("denotation"))
|
|
if (!$util.isString(message.denotation))
|
|
return "denotation: string expected";
|
|
return null;
|
|
};
|
|
|
|
/**
|
|
* Creates a Dimension message from a plain object. Also converts values to their respective internal types.
|
|
* @function fromObject
|
|
* @memberof onnx.TensorShapeProto.Dimension
|
|
* @static
|
|
* @param {Object.<string,*>} object Plain object
|
|
* @returns {onnx.TensorShapeProto.Dimension} Dimension
|
|
*/
|
|
Dimension.fromObject = function fromObject(object) {
|
|
if (object instanceof $root.onnx.TensorShapeProto.Dimension)
|
|
return object;
|
|
var message = new $root.onnx.TensorShapeProto.Dimension();
|
|
if (object.dimValue != null)
|
|
if ($util.Long)
|
|
(message.dimValue = $util.Long.fromValue(object.dimValue)).unsigned = false;
|
|
else if (typeof object.dimValue === "string")
|
|
message.dimValue = parseInt(object.dimValue, 10);
|
|
else if (typeof object.dimValue === "number")
|
|
message.dimValue = object.dimValue;
|
|
else if (typeof object.dimValue === "object")
|
|
message.dimValue = new $util.LongBits(object.dimValue.low >>> 0, object.dimValue.high >>> 0).toNumber();
|
|
if (object.dimParam != null)
|
|
message.dimParam = String(object.dimParam);
|
|
if (object.denotation != null)
|
|
message.denotation = String(object.denotation);
|
|
return message;
|
|
};
|
|
|
|
/**
|
|
* Creates a plain object from a Dimension message. Also converts values to other types if specified.
|
|
* @function toObject
|
|
* @memberof onnx.TensorShapeProto.Dimension
|
|
* @static
|
|
* @param {onnx.TensorShapeProto.Dimension} message Dimension
|
|
* @param {$protobuf.IConversionOptions} [options] Conversion options
|
|
* @returns {Object.<string,*>} Plain object
|
|
*/
|
|
Dimension.toObject = function toObject(message, options) {
|
|
if (!options)
|
|
options = {};
|
|
var object = {};
|
|
if (options.defaults)
|
|
object.denotation = "";
|
|
if (message.dimValue != null && message.hasOwnProperty("dimValue")) {
|
|
if (typeof message.dimValue === "number")
|
|
object.dimValue = options.longs === String ? String(message.dimValue) : message.dimValue;
|
|
else
|
|
object.dimValue = options.longs === String ? $util.Long.prototype.toString.call(message.dimValue) : options.longs === Number ? new $util.LongBits(message.dimValue.low >>> 0, message.dimValue.high >>> 0).toNumber() : message.dimValue;
|
|
if (options.oneofs)
|
|
object.value = "dimValue";
|
|
}
|
|
if (message.dimParam != null && message.hasOwnProperty("dimParam")) {
|
|
object.dimParam = message.dimParam;
|
|
if (options.oneofs)
|
|
object.value = "dimParam";
|
|
}
|
|
if (message.denotation != null && message.hasOwnProperty("denotation"))
|
|
object.denotation = message.denotation;
|
|
return object;
|
|
};
|
|
|
|
/**
|
|
* Converts this Dimension to JSON.
|
|
* @function toJSON
|
|
* @memberof onnx.TensorShapeProto.Dimension
|
|
* @instance
|
|
* @returns {Object.<string,*>} JSON object
|
|
*/
|
|
Dimension.prototype.toJSON = function toJSON() {
|
|
return this.constructor.toObject(this, $protobuf.util.toJSONOptions);
|
|
};
|
|
|
|
return Dimension;
|
|
})();
|
|
|
|
return TensorShapeProto;
|
|
})();
|
|
|
|
onnx.TypeProto = (function() {
|
|
|
|
/**
|
|
* Properties of a TypeProto.
|
|
* @memberof onnx
|
|
* @interface ITypeProto
|
|
* @property {onnx.TypeProto.ITensor|null} [tensorType] TypeProto tensorType
|
|
* @property {string|null} [denotation] TypeProto denotation
|
|
*/
|
|
|
|
/**
|
|
* Constructs a new TypeProto.
|
|
* @memberof onnx
|
|
* @classdesc Represents a TypeProto.
|
|
* @implements ITypeProto
|
|
* @constructor
|
|
* @param {onnx.ITypeProto=} [properties] Properties to set
|
|
*/
|
|
function TypeProto(properties) {
|
|
if (properties)
|
|
for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
|
|
if (properties[keys[i]] != null)
|
|
this[keys[i]] = properties[keys[i]];
|
|
}
|
|
|
|
/**
|
|
* TypeProto tensorType.
|
|
* @member {onnx.TypeProto.ITensor|null|undefined} tensorType
|
|
* @memberof onnx.TypeProto
|
|
* @instance
|
|
*/
|
|
TypeProto.prototype.tensorType = null;
|
|
|
|
/**
|
|
* TypeProto denotation.
|
|
* @member {string} denotation
|
|
* @memberof onnx.TypeProto
|
|
* @instance
|
|
*/
|
|
TypeProto.prototype.denotation = "";
|
|
|
|
// OneOf field names bound to virtual getters and setters
|
|
var $oneOfFields;
|
|
|
|
/**
|
|
* TypeProto value.
|
|
* @member {"tensorType"|undefined} value
|
|
* @memberof onnx.TypeProto
|
|
* @instance
|
|
*/
|
|
Object.defineProperty(TypeProto.prototype, "value", {
|
|
get: $util.oneOfGetter($oneOfFields = ["tensorType"]),
|
|
set: $util.oneOfSetter($oneOfFields)
|
|
});
|
|
|
|
/**
|
|
* Creates a new TypeProto instance using the specified properties.
|
|
* @function create
|
|
* @memberof onnx.TypeProto
|
|
* @static
|
|
* @param {onnx.ITypeProto=} [properties] Properties to set
|
|
* @returns {onnx.TypeProto} TypeProto instance
|
|
*/
|
|
TypeProto.create = function create(properties) {
|
|
return new TypeProto(properties);
|
|
};
|
|
|
|
/**
|
|
* Encodes the specified TypeProto message. Does not implicitly {@link onnx.TypeProto.verify|verify} messages.
|
|
* @function encode
|
|
* @memberof onnx.TypeProto
|
|
* @static
|
|
* @param {onnx.ITypeProto} message TypeProto message or plain object to encode
|
|
* @param {$protobuf.Writer} [writer] Writer to encode to
|
|
* @returns {$protobuf.Writer} Writer
|
|
*/
|
|
TypeProto.encode = function encode(message, writer) {
|
|
if (!writer)
|
|
writer = $Writer.create();
|
|
if (message.tensorType != null && message.hasOwnProperty("tensorType"))
|
|
$root.onnx.TypeProto.Tensor.encode(message.tensorType, writer.uint32(/* id 1, wireType 2 =*/10).fork()).ldelim();
|
|
if (message.denotation != null && message.hasOwnProperty("denotation"))
|
|
writer.uint32(/* id 6, wireType 2 =*/50).string(message.denotation);
|
|
return writer;
|
|
};
|
|
|
|
/**
|
|
* Encodes the specified TypeProto message, length delimited. Does not implicitly {@link onnx.TypeProto.verify|verify} messages.
|
|
* @function encodeDelimited
|
|
* @memberof onnx.TypeProto
|
|
* @static
|
|
* @param {onnx.ITypeProto} message TypeProto message or plain object to encode
|
|
* @param {$protobuf.Writer} [writer] Writer to encode to
|
|
* @returns {$protobuf.Writer} Writer
|
|
*/
|
|
TypeProto.encodeDelimited = function encodeDelimited(message, writer) {
|
|
return this.encode(message, writer).ldelim();
|
|
};
|
|
|
|
/**
|
|
* Decodes a TypeProto message from the specified reader or buffer.
|
|
* @function decode
|
|
* @memberof onnx.TypeProto
|
|
* @static
|
|
* @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
|
|
* @param {number} [length] Message length if known beforehand
|
|
* @returns {onnx.TypeProto} TypeProto
|
|
* @throws {Error} If the payload is not a reader or valid buffer
|
|
* @throws {$protobuf.util.ProtocolError} If required fields are missing
|
|
*/
|
|
TypeProto.decode = function decode(reader, length) {
|
|
if (!(reader instanceof $Reader))
|
|
reader = $Reader.create(reader);
|
|
var end = length === undefined ? reader.len : reader.pos + length, message = new $root.onnx.TypeProto();
|
|
while (reader.pos < end) {
|
|
var tag = reader.uint32();
|
|
switch (tag >>> 3) {
|
|
case 1:
|
|
message.tensorType = $root.onnx.TypeProto.Tensor.decode(reader, reader.uint32());
|
|
break;
|
|
case 6:
|
|
message.denotation = reader.string();
|
|
break;
|
|
default:
|
|
reader.skipType(tag & 7);
|
|
break;
|
|
}
|
|
}
|
|
return message;
|
|
};
|
|
|
|
/**
|
|
* Decodes a TypeProto message from the specified reader or buffer, length delimited.
|
|
* @function decodeDelimited
|
|
* @memberof onnx.TypeProto
|
|
* @static
|
|
* @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
|
|
* @returns {onnx.TypeProto} TypeProto
|
|
* @throws {Error} If the payload is not a reader or valid buffer
|
|
* @throws {$protobuf.util.ProtocolError} If required fields are missing
|
|
*/
|
|
TypeProto.decodeDelimited = function decodeDelimited(reader) {
|
|
if (!(reader instanceof $Reader))
|
|
reader = new $Reader(reader);
|
|
return this.decode(reader, reader.uint32());
|
|
};
|
|
|
|
/**
|
|
* Verifies a TypeProto message.
|
|
* @function verify
|
|
* @memberof onnx.TypeProto
|
|
* @static
|
|
* @param {Object.<string,*>} message Plain object to verify
|
|
* @returns {string|null} `null` if valid, otherwise the reason why it is not
|
|
*/
|
|
TypeProto.verify = function verify(message) {
|
|
if (typeof message !== "object" || message === null)
|
|
return "object expected";
|
|
var properties = {};
|
|
if (message.tensorType != null && message.hasOwnProperty("tensorType")) {
|
|
properties.value = 1;
|
|
{
|
|
var error = $root.onnx.TypeProto.Tensor.verify(message.tensorType);
|
|
if (error)
|
|
return "tensorType." + error;
|
|
}
|
|
}
|
|
if (message.denotation != null && message.hasOwnProperty("denotation"))
|
|
if (!$util.isString(message.denotation))
|
|
return "denotation: string expected";
|
|
return null;
|
|
};
|
|
|
|
/**
|
|
* Creates a TypeProto message from a plain object. Also converts values to their respective internal types.
|
|
* @function fromObject
|
|
* @memberof onnx.TypeProto
|
|
* @static
|
|
* @param {Object.<string,*>} object Plain object
|
|
* @returns {onnx.TypeProto} TypeProto
|
|
*/
|
|
TypeProto.fromObject = function fromObject(object) {
|
|
if (object instanceof $root.onnx.TypeProto)
|
|
return object;
|
|
var message = new $root.onnx.TypeProto();
|
|
if (object.tensorType != null) {
|
|
if (typeof object.tensorType !== "object")
|
|
throw TypeError(".onnx.TypeProto.tensorType: object expected");
|
|
message.tensorType = $root.onnx.TypeProto.Tensor.fromObject(object.tensorType);
|
|
}
|
|
if (object.denotation != null)
|
|
message.denotation = String(object.denotation);
|
|
return message;
|
|
};
|
|
|
|
/**
|
|
* Creates a plain object from a TypeProto message. Also converts values to other types if specified.
|
|
* @function toObject
|
|
* @memberof onnx.TypeProto
|
|
* @static
|
|
* @param {onnx.TypeProto} message TypeProto
|
|
* @param {$protobuf.IConversionOptions} [options] Conversion options
|
|
* @returns {Object.<string,*>} Plain object
|
|
*/
|
|
TypeProto.toObject = function toObject(message, options) {
|
|
if (!options)
|
|
options = {};
|
|
var object = {};
|
|
if (options.defaults)
|
|
object.denotation = "";
|
|
if (message.tensorType != null && message.hasOwnProperty("tensorType")) {
|
|
object.tensorType = $root.onnx.TypeProto.Tensor.toObject(message.tensorType, options);
|
|
if (options.oneofs)
|
|
object.value = "tensorType";
|
|
}
|
|
if (message.denotation != null && message.hasOwnProperty("denotation"))
|
|
object.denotation = message.denotation;
|
|
return object;
|
|
};
|
|
|
|
/**
|
|
* Converts this TypeProto to JSON.
|
|
* @function toJSON
|
|
* @memberof onnx.TypeProto
|
|
* @instance
|
|
* @returns {Object.<string,*>} JSON object
|
|
*/
|
|
TypeProto.prototype.toJSON = function toJSON() {
|
|
return this.constructor.toObject(this, $protobuf.util.toJSONOptions);
|
|
};
|
|
|
|
TypeProto.Tensor = (function() {
|
|
|
|
/**
|
|
* Properties of a Tensor.
|
|
* @memberof onnx.TypeProto
|
|
* @interface ITensor
|
|
* @property {number|null} [elemType] Tensor elemType
|
|
* @property {onnx.ITensorShapeProto|null} [shape] Tensor shape
|
|
*/
|
|
|
|
/**
|
|
* Constructs a new Tensor.
|
|
* @memberof onnx.TypeProto
|
|
* @classdesc Represents a Tensor.
|
|
* @implements ITensor
|
|
* @constructor
|
|
* @param {onnx.TypeProto.ITensor=} [properties] Properties to set
|
|
*/
|
|
function Tensor(properties) {
|
|
if (properties)
|
|
for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
|
|
if (properties[keys[i]] != null)
|
|
this[keys[i]] = properties[keys[i]];
|
|
}
|
|
|
|
/**
|
|
* Tensor elemType.
|
|
* @member {number} elemType
|
|
* @memberof onnx.TypeProto.Tensor
|
|
* @instance
|
|
*/
|
|
Tensor.prototype.elemType = 0;
|
|
|
|
/**
|
|
* Tensor shape.
|
|
* @member {onnx.ITensorShapeProto|null|undefined} shape
|
|
* @memberof onnx.TypeProto.Tensor
|
|
* @instance
|
|
*/
|
|
Tensor.prototype.shape = null;
|
|
|
|
/**
|
|
* Creates a new Tensor instance using the specified properties.
|
|
* @function create
|
|
* @memberof onnx.TypeProto.Tensor
|
|
* @static
|
|
* @param {onnx.TypeProto.ITensor=} [properties] Properties to set
|
|
* @returns {onnx.TypeProto.Tensor} Tensor instance
|
|
*/
|
|
Tensor.create = function create(properties) {
|
|
return new Tensor(properties);
|
|
};
|
|
|
|
/**
|
|
* Encodes the specified Tensor message. Does not implicitly {@link onnx.TypeProto.Tensor.verify|verify} messages.
|
|
* @function encode
|
|
* @memberof onnx.TypeProto.Tensor
|
|
* @static
|
|
* @param {onnx.TypeProto.ITensor} message Tensor message or plain object to encode
|
|
* @param {$protobuf.Writer} [writer] Writer to encode to
|
|
* @returns {$protobuf.Writer} Writer
|
|
*/
|
|
Tensor.encode = function encode(message, writer) {
|
|
if (!writer)
|
|
writer = $Writer.create();
|
|
if (message.elemType != null && message.hasOwnProperty("elemType"))
|
|
writer.uint32(/* id 1, wireType 0 =*/8).int32(message.elemType);
|
|
if (message.shape != null && message.hasOwnProperty("shape"))
|
|
$root.onnx.TensorShapeProto.encode(message.shape, writer.uint32(/* id 2, wireType 2 =*/18).fork()).ldelim();
|
|
return writer;
|
|
};
|
|
|
|
/**
|
|
* Encodes the specified Tensor message, length delimited. Does not implicitly {@link onnx.TypeProto.Tensor.verify|verify} messages.
|
|
* @function encodeDelimited
|
|
* @memberof onnx.TypeProto.Tensor
|
|
* @static
|
|
* @param {onnx.TypeProto.ITensor} message Tensor message or plain object to encode
|
|
* @param {$protobuf.Writer} [writer] Writer to encode to
|
|
* @returns {$protobuf.Writer} Writer
|
|
*/
|
|
Tensor.encodeDelimited = function encodeDelimited(message, writer) {
|
|
return this.encode(message, writer).ldelim();
|
|
};
|
|
|
|
/**
|
|
* Decodes a Tensor message from the specified reader or buffer.
|
|
* @function decode
|
|
* @memberof onnx.TypeProto.Tensor
|
|
* @static
|
|
* @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
|
|
* @param {number} [length] Message length if known beforehand
|
|
* @returns {onnx.TypeProto.Tensor} Tensor
|
|
* @throws {Error} If the payload is not a reader or valid buffer
|
|
* @throws {$protobuf.util.ProtocolError} If required fields are missing
|
|
*/
|
|
Tensor.decode = function decode(reader, length) {
|
|
if (!(reader instanceof $Reader))
|
|
reader = $Reader.create(reader);
|
|
var end = length === undefined ? reader.len : reader.pos + length, message = new $root.onnx.TypeProto.Tensor();
|
|
while (reader.pos < end) {
|
|
var tag = reader.uint32();
|
|
switch (tag >>> 3) {
|
|
case 1:
|
|
message.elemType = reader.int32();
|
|
break;
|
|
case 2:
|
|
message.shape = $root.onnx.TensorShapeProto.decode(reader, reader.uint32());
|
|
break;
|
|
default:
|
|
reader.skipType(tag & 7);
|
|
break;
|
|
}
|
|
}
|
|
return message;
|
|
};
|
|
|
|
/**
|
|
* Decodes a Tensor message from the specified reader or buffer, length delimited.
|
|
* @function decodeDelimited
|
|
* @memberof onnx.TypeProto.Tensor
|
|
* @static
|
|
* @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
|
|
* @returns {onnx.TypeProto.Tensor} Tensor
|
|
* @throws {Error} If the payload is not a reader or valid buffer
|
|
* @throws {$protobuf.util.ProtocolError} If required fields are missing
|
|
*/
|
|
Tensor.decodeDelimited = function decodeDelimited(reader) {
|
|
if (!(reader instanceof $Reader))
|
|
reader = new $Reader(reader);
|
|
return this.decode(reader, reader.uint32());
|
|
};
|
|
|
|
/**
|
|
* Verifies a Tensor message.
|
|
* @function verify
|
|
* @memberof onnx.TypeProto.Tensor
|
|
* @static
|
|
* @param {Object.<string,*>} message Plain object to verify
|
|
* @returns {string|null} `null` if valid, otherwise the reason why it is not
|
|
*/
|
|
Tensor.verify = function verify(message) {
|
|
if (typeof message !== "object" || message === null)
|
|
return "object expected";
|
|
if (message.elemType != null && message.hasOwnProperty("elemType"))
|
|
if (!$util.isInteger(message.elemType))
|
|
return "elemType: integer expected";
|
|
if (message.shape != null && message.hasOwnProperty("shape")) {
|
|
var error = $root.onnx.TensorShapeProto.verify(message.shape);
|
|
if (error)
|
|
return "shape." + error;
|
|
}
|
|
return null;
|
|
};
|
|
|
|
/**
|
|
* Creates a Tensor message from a plain object. Also converts values to their respective internal types.
|
|
* @function fromObject
|
|
* @memberof onnx.TypeProto.Tensor
|
|
* @static
|
|
* @param {Object.<string,*>} object Plain object
|
|
* @returns {onnx.TypeProto.Tensor} Tensor
|
|
*/
|
|
Tensor.fromObject = function fromObject(object) {
|
|
if (object instanceof $root.onnx.TypeProto.Tensor)
|
|
return object;
|
|
var message = new $root.onnx.TypeProto.Tensor();
|
|
if (object.elemType != null)
|
|
message.elemType = object.elemType | 0;
|
|
if (object.shape != null) {
|
|
if (typeof object.shape !== "object")
|
|
throw TypeError(".onnx.TypeProto.Tensor.shape: object expected");
|
|
message.shape = $root.onnx.TensorShapeProto.fromObject(object.shape);
|
|
}
|
|
return message;
|
|
};
|
|
|
|
/**
|
|
* Creates a plain object from a Tensor message. Also converts values to other types if specified.
|
|
* @function toObject
|
|
* @memberof onnx.TypeProto.Tensor
|
|
* @static
|
|
* @param {onnx.TypeProto.Tensor} message Tensor
|
|
* @param {$protobuf.IConversionOptions} [options] Conversion options
|
|
* @returns {Object.<string,*>} Plain object
|
|
*/
|
|
Tensor.toObject = function toObject(message, options) {
|
|
if (!options)
|
|
options = {};
|
|
var object = {};
|
|
if (options.defaults) {
|
|
object.elemType = 0;
|
|
object.shape = null;
|
|
}
|
|
if (message.elemType != null && message.hasOwnProperty("elemType"))
|
|
object.elemType = message.elemType;
|
|
if (message.shape != null && message.hasOwnProperty("shape"))
|
|
object.shape = $root.onnx.TensorShapeProto.toObject(message.shape, options);
|
|
return object;
|
|
};
|
|
|
|
/**
|
|
* Converts this Tensor to JSON.
|
|
* @function toJSON
|
|
* @memberof onnx.TypeProto.Tensor
|
|
* @instance
|
|
* @returns {Object.<string,*>} JSON object
|
|
*/
|
|
Tensor.prototype.toJSON = function toJSON() {
|
|
return this.constructor.toObject(this, $protobuf.util.toJSONOptions);
|
|
};
|
|
|
|
return Tensor;
|
|
})();
|
|
|
|
return TypeProto;
|
|
})();
|
|
|
|
onnx.OperatorSetIdProto = (function() {
|
|
|
|
/**
|
|
* Properties of an OperatorSetIdProto.
|
|
* @memberof onnx
|
|
* @interface IOperatorSetIdProto
|
|
* @property {string|null} [domain] OperatorSetIdProto domain
|
|
* @property {number|Long|null} [version] OperatorSetIdProto version
|
|
*/
|
|
|
|
/**
|
|
* Constructs a new OperatorSetIdProto.
|
|
* @memberof onnx
|
|
* @classdesc Represents an OperatorSetIdProto.
|
|
* @implements IOperatorSetIdProto
|
|
* @constructor
|
|
* @param {onnx.IOperatorSetIdProto=} [properties] Properties to set
|
|
*/
|
|
function OperatorSetIdProto(properties) {
|
|
if (properties)
|
|
for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
|
|
if (properties[keys[i]] != null)
|
|
this[keys[i]] = properties[keys[i]];
|
|
}
|
|
|
|
/**
|
|
* OperatorSetIdProto domain.
|
|
* @member {string} domain
|
|
* @memberof onnx.OperatorSetIdProto
|
|
* @instance
|
|
*/
|
|
OperatorSetIdProto.prototype.domain = "";
|
|
|
|
/**
|
|
* OperatorSetIdProto version.
|
|
* @member {number|Long} version
|
|
* @memberof onnx.OperatorSetIdProto
|
|
* @instance
|
|
*/
|
|
OperatorSetIdProto.prototype.version = $util.Long ? $util.Long.fromBits(0,0,false) : 0;
|
|
|
|
/**
|
|
* Creates a new OperatorSetIdProto instance using the specified properties.
|
|
* @function create
|
|
* @memberof onnx.OperatorSetIdProto
|
|
* @static
|
|
* @param {onnx.IOperatorSetIdProto=} [properties] Properties to set
|
|
* @returns {onnx.OperatorSetIdProto} OperatorSetIdProto instance
|
|
*/
|
|
OperatorSetIdProto.create = function create(properties) {
|
|
return new OperatorSetIdProto(properties);
|
|
};
|
|
|
|
/**
|
|
* Encodes the specified OperatorSetIdProto message. Does not implicitly {@link onnx.OperatorSetIdProto.verify|verify} messages.
|
|
* @function encode
|
|
* @memberof onnx.OperatorSetIdProto
|
|
* @static
|
|
* @param {onnx.IOperatorSetIdProto} message OperatorSetIdProto message or plain object to encode
|
|
* @param {$protobuf.Writer} [writer] Writer to encode to
|
|
* @returns {$protobuf.Writer} Writer
|
|
*/
|
|
OperatorSetIdProto.encode = function encode(message, writer) {
|
|
if (!writer)
|
|
writer = $Writer.create();
|
|
if (message.domain != null && message.hasOwnProperty("domain"))
|
|
writer.uint32(/* id 1, wireType 2 =*/10).string(message.domain);
|
|
if (message.version != null && message.hasOwnProperty("version"))
|
|
writer.uint32(/* id 2, wireType 0 =*/16).int64(message.version);
|
|
return writer;
|
|
};
|
|
|
|
/**
|
|
* Encodes the specified OperatorSetIdProto message, length delimited. Does not implicitly {@link onnx.OperatorSetIdProto.verify|verify} messages.
|
|
* @function encodeDelimited
|
|
* @memberof onnx.OperatorSetIdProto
|
|
* @static
|
|
* @param {onnx.IOperatorSetIdProto} message OperatorSetIdProto message or plain object to encode
|
|
* @param {$protobuf.Writer} [writer] Writer to encode to
|
|
* @returns {$protobuf.Writer} Writer
|
|
*/
|
|
OperatorSetIdProto.encodeDelimited = function encodeDelimited(message, writer) {
|
|
return this.encode(message, writer).ldelim();
|
|
};
|
|
|
|
/**
|
|
* Decodes an OperatorSetIdProto message from the specified reader or buffer.
|
|
* @function decode
|
|
* @memberof onnx.OperatorSetIdProto
|
|
* @static
|
|
* @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
|
|
* @param {number} [length] Message length if known beforehand
|
|
* @returns {onnx.OperatorSetIdProto} OperatorSetIdProto
|
|
* @throws {Error} If the payload is not a reader or valid buffer
|
|
* @throws {$protobuf.util.ProtocolError} If required fields are missing
|
|
*/
|
|
OperatorSetIdProto.decode = function decode(reader, length) {
|
|
if (!(reader instanceof $Reader))
|
|
reader = $Reader.create(reader);
|
|
var end = length === undefined ? reader.len : reader.pos + length, message = new $root.onnx.OperatorSetIdProto();
|
|
while (reader.pos < end) {
|
|
var tag = reader.uint32();
|
|
switch (tag >>> 3) {
|
|
case 1:
|
|
message.domain = reader.string();
|
|
break;
|
|
case 2:
|
|
message.version = reader.int64();
|
|
break;
|
|
default:
|
|
reader.skipType(tag & 7);
|
|
break;
|
|
}
|
|
}
|
|
return message;
|
|
};
|
|
|
|
/**
|
|
* Decodes an OperatorSetIdProto message from the specified reader or buffer, length delimited.
|
|
* @function decodeDelimited
|
|
* @memberof onnx.OperatorSetIdProto
|
|
* @static
|
|
* @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
|
|
* @returns {onnx.OperatorSetIdProto} OperatorSetIdProto
|
|
* @throws {Error} If the payload is not a reader or valid buffer
|
|
* @throws {$protobuf.util.ProtocolError} If required fields are missing
|
|
*/
|
|
OperatorSetIdProto.decodeDelimited = function decodeDelimited(reader) {
|
|
if (!(reader instanceof $Reader))
|
|
reader = new $Reader(reader);
|
|
return this.decode(reader, reader.uint32());
|
|
};
|
|
|
|
/**
|
|
* Verifies an OperatorSetIdProto message.
|
|
* @function verify
|
|
* @memberof onnx.OperatorSetIdProto
|
|
* @static
|
|
* @param {Object.<string,*>} message Plain object to verify
|
|
* @returns {string|null} `null` if valid, otherwise the reason why it is not
|
|
*/
|
|
OperatorSetIdProto.verify = function verify(message) {
|
|
if (typeof message !== "object" || message === null)
|
|
return "object expected";
|
|
if (message.domain != null && message.hasOwnProperty("domain"))
|
|
if (!$util.isString(message.domain))
|
|
return "domain: string expected";
|
|
if (message.version != null && message.hasOwnProperty("version"))
|
|
if (!$util.isInteger(message.version) && !(message.version && $util.isInteger(message.version.low) && $util.isInteger(message.version.high)))
|
|
return "version: integer|Long expected";
|
|
return null;
|
|
};
|
|
|
|
/**
|
|
* Creates an OperatorSetIdProto message from a plain object. Also converts values to their respective internal types.
|
|
* @function fromObject
|
|
* @memberof onnx.OperatorSetIdProto
|
|
* @static
|
|
* @param {Object.<string,*>} object Plain object
|
|
* @returns {onnx.OperatorSetIdProto} OperatorSetIdProto
|
|
*/
|
|
OperatorSetIdProto.fromObject = function fromObject(object) {
|
|
if (object instanceof $root.onnx.OperatorSetIdProto)
|
|
return object;
|
|
var message = new $root.onnx.OperatorSetIdProto();
|
|
if (object.domain != null)
|
|
message.domain = String(object.domain);
|
|
if (object.version != null)
|
|
if ($util.Long)
|
|
(message.version = $util.Long.fromValue(object.version)).unsigned = false;
|
|
else if (typeof object.version === "string")
|
|
message.version = parseInt(object.version, 10);
|
|
else if (typeof object.version === "number")
|
|
message.version = object.version;
|
|
else if (typeof object.version === "object")
|
|
message.version = new $util.LongBits(object.version.low >>> 0, object.version.high >>> 0).toNumber();
|
|
return message;
|
|
};
|
|
|
|
/**
|
|
* Creates a plain object from an OperatorSetIdProto message. Also converts values to other types if specified.
|
|
* @function toObject
|
|
* @memberof onnx.OperatorSetIdProto
|
|
* @static
|
|
* @param {onnx.OperatorSetIdProto} message OperatorSetIdProto
|
|
* @param {$protobuf.IConversionOptions} [options] Conversion options
|
|
* @returns {Object.<string,*>} Plain object
|
|
*/
|
|
OperatorSetIdProto.toObject = function toObject(message, options) {
|
|
if (!options)
|
|
options = {};
|
|
var object = {};
|
|
if (options.defaults) {
|
|
object.domain = "";
|
|
if ($util.Long) {
|
|
var long = new $util.Long(0, 0, false);
|
|
object.version = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
|
|
} else
|
|
object.version = options.longs === String ? "0" : 0;
|
|
}
|
|
if (message.domain != null && message.hasOwnProperty("domain"))
|
|
object.domain = message.domain;
|
|
if (message.version != null && message.hasOwnProperty("version"))
|
|
if (typeof message.version === "number")
|
|
object.version = options.longs === String ? String(message.version) : message.version;
|
|
else
|
|
object.version = options.longs === String ? $util.Long.prototype.toString.call(message.version) : options.longs === Number ? new $util.LongBits(message.version.low >>> 0, message.version.high >>> 0).toNumber() : message.version;
|
|
return object;
|
|
};
|
|
|
|
/**
|
|
* Converts this OperatorSetIdProto to JSON.
|
|
* @function toJSON
|
|
* @memberof onnx.OperatorSetIdProto
|
|
* @instance
|
|
* @returns {Object.<string,*>} JSON object
|
|
*/
|
|
OperatorSetIdProto.prototype.toJSON = function toJSON() {
|
|
return this.constructor.toObject(this, $protobuf.util.toJSONOptions);
|
|
};
|
|
|
|
return OperatorSetIdProto;
|
|
})();
|
|
|
|
return onnx;
|
|
})();
|
|
|
|
module.exports = $root;
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/protobufjs/minimal.js":
|
|
/*!********************************************!*\
|
|
!*** ./node_modules/protobufjs/minimal.js ***!
|
|
\********************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
// minimal library entry point.
|
|
|
|
|
|
module.exports = __webpack_require__(/*! ./src/index-minimal */ "./node_modules/protobufjs/src/index-minimal.js");
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/protobufjs/src/index-minimal.js":
|
|
/*!******************************************************!*\
|
|
!*** ./node_modules/protobufjs/src/index-minimal.js ***!
|
|
\******************************************************/
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
var protobuf = exports;
|
|
|
|
/**
|
|
* Build type, one of `"full"`, `"light"` or `"minimal"`.
|
|
* @name build
|
|
* @type {string}
|
|
* @const
|
|
*/
|
|
protobuf.build = "minimal";
|
|
|
|
// Serialization
|
|
protobuf.Writer = __webpack_require__(/*! ./writer */ "./node_modules/protobufjs/src/writer.js");
|
|
protobuf.BufferWriter = __webpack_require__(/*! ./writer_buffer */ "./node_modules/protobufjs/src/writer_buffer.js");
|
|
protobuf.Reader = __webpack_require__(/*! ./reader */ "./node_modules/protobufjs/src/reader.js");
|
|
protobuf.BufferReader = __webpack_require__(/*! ./reader_buffer */ "./node_modules/protobufjs/src/reader_buffer.js");
|
|
|
|
// Utility
|
|
protobuf.util = __webpack_require__(/*! ./util/minimal */ "./node_modules/protobufjs/src/util/minimal.js");
|
|
protobuf.rpc = __webpack_require__(/*! ./rpc */ "./node_modules/protobufjs/src/rpc.js");
|
|
protobuf.roots = __webpack_require__(/*! ./roots */ "./node_modules/protobufjs/src/roots.js");
|
|
protobuf.configure = configure;
|
|
|
|
/* istanbul ignore next */
|
|
/**
|
|
* Reconfigures the library according to the environment.
|
|
* @returns {undefined}
|
|
*/
|
|
function configure() {
|
|
protobuf.util._configure();
|
|
protobuf.Writer._configure(protobuf.BufferWriter);
|
|
protobuf.Reader._configure(protobuf.BufferReader);
|
|
}
|
|
|
|
// Set up buffer utility according to the environment
|
|
configure();
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/protobufjs/src/reader.js":
|
|
/*!***********************************************!*\
|
|
!*** ./node_modules/protobufjs/src/reader.js ***!
|
|
\***********************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
module.exports = Reader;
|
|
|
|
var util = __webpack_require__(/*! ./util/minimal */ "./node_modules/protobufjs/src/util/minimal.js");
|
|
|
|
var BufferReader; // cyclic
|
|
|
|
var LongBits = util.LongBits,
|
|
utf8 = util.utf8;
|
|
|
|
/* istanbul ignore next */
|
|
function indexOutOfRange(reader, writeLength) {
|
|
return RangeError("index out of range: " + reader.pos + " + " + (writeLength || 1) + " > " + reader.len);
|
|
}
|
|
|
|
/**
|
|
* Constructs a new reader instance using the specified buffer.
|
|
* @classdesc Wire format reader using `Uint8Array` if available, otherwise `Array`.
|
|
* @constructor
|
|
* @param {Uint8Array} buffer Buffer to read from
|
|
*/
|
|
function Reader(buffer) {
|
|
|
|
/**
|
|
* Read buffer.
|
|
* @type {Uint8Array}
|
|
*/
|
|
this.buf = buffer;
|
|
|
|
/**
|
|
* Read buffer position.
|
|
* @type {number}
|
|
*/
|
|
this.pos = 0;
|
|
|
|
/**
|
|
* Read buffer length.
|
|
* @type {number}
|
|
*/
|
|
this.len = buffer.length;
|
|
}
|
|
|
|
var create_array = typeof Uint8Array !== "undefined"
|
|
? function create_typed_array(buffer) {
|
|
if (buffer instanceof Uint8Array || Array.isArray(buffer))
|
|
return new Reader(buffer);
|
|
throw Error("illegal buffer");
|
|
}
|
|
/* istanbul ignore next */
|
|
: function create_array(buffer) {
|
|
if (Array.isArray(buffer))
|
|
return new Reader(buffer);
|
|
throw Error("illegal buffer");
|
|
};
|
|
|
|
var create = function create() {
|
|
return util.Buffer
|
|
? function create_buffer_setup(buffer) {
|
|
return (Reader.create = function create_buffer(buffer) {
|
|
return util.Buffer.isBuffer(buffer)
|
|
? new BufferReader(buffer)
|
|
/* istanbul ignore next */
|
|
: create_array(buffer);
|
|
})(buffer);
|
|
}
|
|
/* istanbul ignore next */
|
|
: create_array;
|
|
};
|
|
|
|
/**
|
|
* Creates a new reader using the specified buffer.
|
|
* @function
|
|
* @param {Uint8Array|Buffer} buffer Buffer to read from
|
|
* @returns {Reader|BufferReader} A {@link BufferReader} if `buffer` is a Buffer, otherwise a {@link Reader}
|
|
* @throws {Error} If `buffer` is not a valid buffer
|
|
*/
|
|
Reader.create = create();
|
|
|
|
Reader.prototype._slice = util.Array.prototype.subarray || /* istanbul ignore next */ util.Array.prototype.slice;
|
|
|
|
/**
|
|
* Reads a varint as an unsigned 32 bit value.
|
|
* @function
|
|
* @returns {number} Value read
|
|
*/
|
|
Reader.prototype.uint32 = (function read_uint32_setup() {
|
|
var value = 4294967295; // optimizer type-hint, tends to deopt otherwise (?!)
|
|
return function read_uint32() {
|
|
value = ( this.buf[this.pos] & 127 ) >>> 0; if (this.buf[this.pos++] < 128) return value;
|
|
value = (value | (this.buf[this.pos] & 127) << 7) >>> 0; if (this.buf[this.pos++] < 128) return value;
|
|
value = (value | (this.buf[this.pos] & 127) << 14) >>> 0; if (this.buf[this.pos++] < 128) return value;
|
|
value = (value | (this.buf[this.pos] & 127) << 21) >>> 0; if (this.buf[this.pos++] < 128) return value;
|
|
value = (value | (this.buf[this.pos] & 15) << 28) >>> 0; if (this.buf[this.pos++] < 128) return value;
|
|
|
|
/* istanbul ignore if */
|
|
if ((this.pos += 5) > this.len) {
|
|
this.pos = this.len;
|
|
throw indexOutOfRange(this, 10);
|
|
}
|
|
return value;
|
|
};
|
|
})();
|
|
|
|
/**
|
|
* Reads a varint as a signed 32 bit value.
|
|
* @returns {number} Value read
|
|
*/
|
|
Reader.prototype.int32 = function read_int32() {
|
|
return this.uint32() | 0;
|
|
};
|
|
|
|
/**
|
|
* Reads a zig-zag encoded varint as a signed 32 bit value.
|
|
* @returns {number} Value read
|
|
*/
|
|
Reader.prototype.sint32 = function read_sint32() {
|
|
var value = this.uint32();
|
|
return value >>> 1 ^ -(value & 1) | 0;
|
|
};
|
|
|
|
/* eslint-disable no-invalid-this */
|
|
|
|
function readLongVarint() {
|
|
// tends to deopt with local vars for octet etc.
|
|
var bits = new LongBits(0, 0);
|
|
var i = 0;
|
|
if (this.len - this.pos > 4) { // fast route (lo)
|
|
for (; i < 4; ++i) {
|
|
// 1st..4th
|
|
bits.lo = (bits.lo | (this.buf[this.pos] & 127) << i * 7) >>> 0;
|
|
if (this.buf[this.pos++] < 128)
|
|
return bits;
|
|
}
|
|
// 5th
|
|
bits.lo = (bits.lo | (this.buf[this.pos] & 127) << 28) >>> 0;
|
|
bits.hi = (bits.hi | (this.buf[this.pos] & 127) >> 4) >>> 0;
|
|
if (this.buf[this.pos++] < 128)
|
|
return bits;
|
|
i = 0;
|
|
} else {
|
|
for (; i < 3; ++i) {
|
|
/* istanbul ignore if */
|
|
if (this.pos >= this.len)
|
|
throw indexOutOfRange(this);
|
|
// 1st..3th
|
|
bits.lo = (bits.lo | (this.buf[this.pos] & 127) << i * 7) >>> 0;
|
|
if (this.buf[this.pos++] < 128)
|
|
return bits;
|
|
}
|
|
// 4th
|
|
bits.lo = (bits.lo | (this.buf[this.pos++] & 127) << i * 7) >>> 0;
|
|
return bits;
|
|
}
|
|
if (this.len - this.pos > 4) { // fast route (hi)
|
|
for (; i < 5; ++i) {
|
|
// 6th..10th
|
|
bits.hi = (bits.hi | (this.buf[this.pos] & 127) << i * 7 + 3) >>> 0;
|
|
if (this.buf[this.pos++] < 128)
|
|
return bits;
|
|
}
|
|
} else {
|
|
for (; i < 5; ++i) {
|
|
/* istanbul ignore if */
|
|
if (this.pos >= this.len)
|
|
throw indexOutOfRange(this);
|
|
// 6th..10th
|
|
bits.hi = (bits.hi | (this.buf[this.pos] & 127) << i * 7 + 3) >>> 0;
|
|
if (this.buf[this.pos++] < 128)
|
|
return bits;
|
|
}
|
|
}
|
|
/* istanbul ignore next */
|
|
throw Error("invalid varint encoding");
|
|
}
|
|
|
|
/* eslint-enable no-invalid-this */
|
|
|
|
/**
|
|
* Reads a varint as a signed 64 bit value.
|
|
* @name Reader#int64
|
|
* @function
|
|
* @returns {Long} Value read
|
|
*/
|
|
|
|
/**
|
|
* Reads a varint as an unsigned 64 bit value.
|
|
* @name Reader#uint64
|
|
* @function
|
|
* @returns {Long} Value read
|
|
*/
|
|
|
|
/**
|
|
* Reads a zig-zag encoded varint as a signed 64 bit value.
|
|
* @name Reader#sint64
|
|
* @function
|
|
* @returns {Long} Value read
|
|
*/
|
|
|
|
/**
|
|
* Reads a varint as a boolean.
|
|
* @returns {boolean} Value read
|
|
*/
|
|
Reader.prototype.bool = function read_bool() {
|
|
return this.uint32() !== 0;
|
|
};
|
|
|
|
function readFixed32_end(buf, end) { // note that this uses `end`, not `pos`
|
|
return (buf[end - 4]
|
|
| buf[end - 3] << 8
|
|
| buf[end - 2] << 16
|
|
| buf[end - 1] << 24) >>> 0;
|
|
}
|
|
|
|
/**
|
|
* Reads fixed 32 bits as an unsigned 32 bit integer.
|
|
* @returns {number} Value read
|
|
*/
|
|
Reader.prototype.fixed32 = function read_fixed32() {
|
|
|
|
/* istanbul ignore if */
|
|
if (this.pos + 4 > this.len)
|
|
throw indexOutOfRange(this, 4);
|
|
|
|
return readFixed32_end(this.buf, this.pos += 4);
|
|
};
|
|
|
|
/**
|
|
* Reads fixed 32 bits as a signed 32 bit integer.
|
|
* @returns {number} Value read
|
|
*/
|
|
Reader.prototype.sfixed32 = function read_sfixed32() {
|
|
|
|
/* istanbul ignore if */
|
|
if (this.pos + 4 > this.len)
|
|
throw indexOutOfRange(this, 4);
|
|
|
|
return readFixed32_end(this.buf, this.pos += 4) | 0;
|
|
};
|
|
|
|
/* eslint-disable no-invalid-this */
|
|
|
|
function readFixed64(/* this: Reader */) {
|
|
|
|
/* istanbul ignore if */
|
|
if (this.pos + 8 > this.len)
|
|
throw indexOutOfRange(this, 8);
|
|
|
|
return new LongBits(readFixed32_end(this.buf, this.pos += 4), readFixed32_end(this.buf, this.pos += 4));
|
|
}
|
|
|
|
/* eslint-enable no-invalid-this */
|
|
|
|
/**
|
|
* Reads fixed 64 bits.
|
|
* @name Reader#fixed64
|
|
* @function
|
|
* @returns {Long} Value read
|
|
*/
|
|
|
|
/**
|
|
* Reads zig-zag encoded fixed 64 bits.
|
|
* @name Reader#sfixed64
|
|
* @function
|
|
* @returns {Long} Value read
|
|
*/
|
|
|
|
/**
|
|
* Reads a float (32 bit) as a number.
|
|
* @function
|
|
* @returns {number} Value read
|
|
*/
|
|
Reader.prototype.float = function read_float() {
|
|
|
|
/* istanbul ignore if */
|
|
if (this.pos + 4 > this.len)
|
|
throw indexOutOfRange(this, 4);
|
|
|
|
var value = util.float.readFloatLE(this.buf, this.pos);
|
|
this.pos += 4;
|
|
return value;
|
|
};
|
|
|
|
/**
|
|
* Reads a double (64 bit float) as a number.
|
|
* @function
|
|
* @returns {number} Value read
|
|
*/
|
|
Reader.prototype.double = function read_double() {
|
|
|
|
/* istanbul ignore if */
|
|
if (this.pos + 8 > this.len)
|
|
throw indexOutOfRange(this, 4);
|
|
|
|
var value = util.float.readDoubleLE(this.buf, this.pos);
|
|
this.pos += 8;
|
|
return value;
|
|
};
|
|
|
|
/**
|
|
* Reads a sequence of bytes preceeded by its length as a varint.
|
|
* @returns {Uint8Array} Value read
|
|
*/
|
|
Reader.prototype.bytes = function read_bytes() {
|
|
var length = this.uint32(),
|
|
start = this.pos,
|
|
end = this.pos + length;
|
|
|
|
/* istanbul ignore if */
|
|
if (end > this.len)
|
|
throw indexOutOfRange(this, length);
|
|
|
|
this.pos += length;
|
|
if (Array.isArray(this.buf)) // plain array
|
|
return this.buf.slice(start, end);
|
|
return start === end // fix for IE 10/Win8 and others' subarray returning array of size 1
|
|
? new this.buf.constructor(0)
|
|
: this._slice.call(this.buf, start, end);
|
|
};
|
|
|
|
/**
|
|
* Reads a string preceeded by its byte length as a varint.
|
|
* @returns {string} Value read
|
|
*/
|
|
Reader.prototype.string = function read_string() {
|
|
var bytes = this.bytes();
|
|
return utf8.read(bytes, 0, bytes.length);
|
|
};
|
|
|
|
/**
|
|
* Skips the specified number of bytes if specified, otherwise skips a varint.
|
|
* @param {number} [length] Length if known, otherwise a varint is assumed
|
|
* @returns {Reader} `this`
|
|
*/
|
|
Reader.prototype.skip = function skip(length) {
|
|
if (typeof length === "number") {
|
|
/* istanbul ignore if */
|
|
if (this.pos + length > this.len)
|
|
throw indexOutOfRange(this, length);
|
|
this.pos += length;
|
|
} else {
|
|
do {
|
|
/* istanbul ignore if */
|
|
if (this.pos >= this.len)
|
|
throw indexOutOfRange(this);
|
|
} while (this.buf[this.pos++] & 128);
|
|
}
|
|
return this;
|
|
};
|
|
|
|
/**
|
|
* Skips the next element of the specified wire type.
|
|
* @param {number} wireType Wire type received
|
|
* @returns {Reader} `this`
|
|
*/
|
|
Reader.prototype.skipType = function(wireType) {
|
|
switch (wireType) {
|
|
case 0:
|
|
this.skip();
|
|
break;
|
|
case 1:
|
|
this.skip(8);
|
|
break;
|
|
case 2:
|
|
this.skip(this.uint32());
|
|
break;
|
|
case 3:
|
|
while ((wireType = this.uint32() & 7) !== 4) {
|
|
this.skipType(wireType);
|
|
}
|
|
break;
|
|
case 5:
|
|
this.skip(4);
|
|
break;
|
|
|
|
/* istanbul ignore next */
|
|
default:
|
|
throw Error("invalid wire type " + wireType + " at offset " + this.pos);
|
|
}
|
|
return this;
|
|
};
|
|
|
|
Reader._configure = function(BufferReader_) {
|
|
BufferReader = BufferReader_;
|
|
Reader.create = create();
|
|
BufferReader._configure();
|
|
|
|
var fn = util.Long ? "toLong" : /* istanbul ignore next */ "toNumber";
|
|
util.merge(Reader.prototype, {
|
|
|
|
int64: function read_int64() {
|
|
return readLongVarint.call(this)[fn](false);
|
|
},
|
|
|
|
uint64: function read_uint64() {
|
|
return readLongVarint.call(this)[fn](true);
|
|
},
|
|
|
|
sint64: function read_sint64() {
|
|
return readLongVarint.call(this).zzDecode()[fn](false);
|
|
},
|
|
|
|
fixed64: function read_fixed64() {
|
|
return readFixed64.call(this)[fn](true);
|
|
},
|
|
|
|
sfixed64: function read_sfixed64() {
|
|
return readFixed64.call(this)[fn](false);
|
|
}
|
|
|
|
});
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/protobufjs/src/reader_buffer.js":
|
|
/*!******************************************************!*\
|
|
!*** ./node_modules/protobufjs/src/reader_buffer.js ***!
|
|
\******************************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
module.exports = BufferReader;
|
|
|
|
// extends Reader
|
|
var Reader = __webpack_require__(/*! ./reader */ "./node_modules/protobufjs/src/reader.js");
|
|
(BufferReader.prototype = Object.create(Reader.prototype)).constructor = BufferReader;
|
|
|
|
var util = __webpack_require__(/*! ./util/minimal */ "./node_modules/protobufjs/src/util/minimal.js");
|
|
|
|
/**
|
|
* Constructs a new buffer reader instance.
|
|
* @classdesc Wire format reader using node buffers.
|
|
* @extends Reader
|
|
* @constructor
|
|
* @param {Buffer} buffer Buffer to read from
|
|
*/
|
|
function BufferReader(buffer) {
|
|
Reader.call(this, buffer);
|
|
|
|
/**
|
|
* Read buffer.
|
|
* @name BufferReader#buf
|
|
* @type {Buffer}
|
|
*/
|
|
}
|
|
|
|
BufferReader._configure = function () {
|
|
/* istanbul ignore else */
|
|
if (util.Buffer)
|
|
BufferReader.prototype._slice = util.Buffer.prototype.slice;
|
|
};
|
|
|
|
|
|
/**
|
|
* @override
|
|
*/
|
|
BufferReader.prototype.string = function read_string_buffer() {
|
|
var len = this.uint32(); // modifies pos
|
|
return this.buf.utf8Slice
|
|
? this.buf.utf8Slice(this.pos, this.pos = Math.min(this.pos + len, this.len))
|
|
: this.buf.toString("utf-8", this.pos, this.pos = Math.min(this.pos + len, this.len));
|
|
};
|
|
|
|
/**
|
|
* Reads a sequence of bytes preceeded by its length as a varint.
|
|
* @name BufferReader#bytes
|
|
* @function
|
|
* @returns {Buffer} Value read
|
|
*/
|
|
|
|
BufferReader._configure();
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/protobufjs/src/roots.js":
|
|
/*!**********************************************!*\
|
|
!*** ./node_modules/protobufjs/src/roots.js ***!
|
|
\**********************************************/
|
|
/***/ ((module) => {
|
|
|
|
"use strict";
|
|
|
|
module.exports = {};
|
|
|
|
/**
|
|
* Named roots.
|
|
* This is where pbjs stores generated structures (the option `-r, --root` specifies a name).
|
|
* Can also be used manually to make roots available accross modules.
|
|
* @name roots
|
|
* @type {Object.<string,Root>}
|
|
* @example
|
|
* // pbjs -r myroot -o compiled.js ...
|
|
*
|
|
* // in another module:
|
|
* require("./compiled.js");
|
|
*
|
|
* // in any subsequent module:
|
|
* var root = protobuf.roots["myroot"];
|
|
*/
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/protobufjs/src/rpc.js":
|
|
/*!********************************************!*\
|
|
!*** ./node_modules/protobufjs/src/rpc.js ***!
|
|
\********************************************/
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
|
|
/**
|
|
* Streaming RPC helpers.
|
|
* @namespace
|
|
*/
|
|
var rpc = exports;
|
|
|
|
/**
|
|
* RPC implementation passed to {@link Service#create} performing a service request on network level, i.e. by utilizing http requests or websockets.
|
|
* @typedef RPCImpl
|
|
* @type {function}
|
|
* @param {Method|rpc.ServiceMethod<Message<{}>,Message<{}>>} method Reflected or static method being called
|
|
* @param {Uint8Array} requestData Request data
|
|
* @param {RPCImplCallback} callback Callback function
|
|
* @returns {undefined}
|
|
* @example
|
|
* function rpcImpl(method, requestData, callback) {
|
|
* if (protobuf.util.lcFirst(method.name) !== "myMethod") // compatible with static code
|
|
* throw Error("no such method");
|
|
* asynchronouslyObtainAResponse(requestData, function(err, responseData) {
|
|
* callback(err, responseData);
|
|
* });
|
|
* }
|
|
*/
|
|
|
|
/**
|
|
* Node-style callback as used by {@link RPCImpl}.
|
|
* @typedef RPCImplCallback
|
|
* @type {function}
|
|
* @param {Error|null} error Error, if any, otherwise `null`
|
|
* @param {Uint8Array|null} [response] Response data or `null` to signal end of stream, if there hasn't been an error
|
|
* @returns {undefined}
|
|
*/
|
|
|
|
rpc.Service = __webpack_require__(/*! ./rpc/service */ "./node_modules/protobufjs/src/rpc/service.js");
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/protobufjs/src/rpc/service.js":
|
|
/*!****************************************************!*\
|
|
!*** ./node_modules/protobufjs/src/rpc/service.js ***!
|
|
\****************************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
module.exports = Service;
|
|
|
|
var util = __webpack_require__(/*! ../util/minimal */ "./node_modules/protobufjs/src/util/minimal.js");
|
|
|
|
// Extends EventEmitter
|
|
(Service.prototype = Object.create(util.EventEmitter.prototype)).constructor = Service;
|
|
|
|
/**
|
|
* A service method callback as used by {@link rpc.ServiceMethod|ServiceMethod}.
|
|
*
|
|
* Differs from {@link RPCImplCallback} in that it is an actual callback of a service method which may not return `response = null`.
|
|
* @typedef rpc.ServiceMethodCallback
|
|
* @template TRes extends Message<TRes>
|
|
* @type {function}
|
|
* @param {Error|null} error Error, if any
|
|
* @param {TRes} [response] Response message
|
|
* @returns {undefined}
|
|
*/
|
|
|
|
/**
|
|
* A service method part of a {@link rpc.Service} as created by {@link Service.create}.
|
|
* @typedef rpc.ServiceMethod
|
|
* @template TReq extends Message<TReq>
|
|
* @template TRes extends Message<TRes>
|
|
* @type {function}
|
|
* @param {TReq|Properties<TReq>} request Request message or plain object
|
|
* @param {rpc.ServiceMethodCallback<TRes>} [callback] Node-style callback called with the error, if any, and the response message
|
|
* @returns {Promise<Message<TRes>>} Promise if `callback` has been omitted, otherwise `undefined`
|
|
*/
|
|
|
|
/**
|
|
* Constructs a new RPC service instance.
|
|
* @classdesc An RPC service as returned by {@link Service#create}.
|
|
* @exports rpc.Service
|
|
* @extends util.EventEmitter
|
|
* @constructor
|
|
* @param {RPCImpl} rpcImpl RPC implementation
|
|
* @param {boolean} [requestDelimited=false] Whether requests are length-delimited
|
|
* @param {boolean} [responseDelimited=false] Whether responses are length-delimited
|
|
*/
|
|
function Service(rpcImpl, requestDelimited, responseDelimited) {
|
|
|
|
if (typeof rpcImpl !== "function")
|
|
throw TypeError("rpcImpl must be a function");
|
|
|
|
util.EventEmitter.call(this);
|
|
|
|
/**
|
|
* RPC implementation. Becomes `null` once the service is ended.
|
|
* @type {RPCImpl|null}
|
|
*/
|
|
this.rpcImpl = rpcImpl;
|
|
|
|
/**
|
|
* Whether requests are length-delimited.
|
|
* @type {boolean}
|
|
*/
|
|
this.requestDelimited = Boolean(requestDelimited);
|
|
|
|
/**
|
|
* Whether responses are length-delimited.
|
|
* @type {boolean}
|
|
*/
|
|
this.responseDelimited = Boolean(responseDelimited);
|
|
}
|
|
|
|
/**
|
|
* Calls a service method through {@link rpc.Service#rpcImpl|rpcImpl}.
|
|
* @param {Method|rpc.ServiceMethod<TReq,TRes>} method Reflected or static method
|
|
* @param {Constructor<TReq>} requestCtor Request constructor
|
|
* @param {Constructor<TRes>} responseCtor Response constructor
|
|
* @param {TReq|Properties<TReq>} request Request message or plain object
|
|
* @param {rpc.ServiceMethodCallback<TRes>} callback Service callback
|
|
* @returns {undefined}
|
|
* @template TReq extends Message<TReq>
|
|
* @template TRes extends Message<TRes>
|
|
*/
|
|
Service.prototype.rpcCall = function rpcCall(method, requestCtor, responseCtor, request, callback) {
|
|
|
|
if (!request)
|
|
throw TypeError("request must be specified");
|
|
|
|
var self = this;
|
|
if (!callback)
|
|
return util.asPromise(rpcCall, self, method, requestCtor, responseCtor, request);
|
|
|
|
if (!self.rpcImpl) {
|
|
setTimeout(function() { callback(Error("already ended")); }, 0);
|
|
return undefined;
|
|
}
|
|
|
|
try {
|
|
return self.rpcImpl(
|
|
method,
|
|
requestCtor[self.requestDelimited ? "encodeDelimited" : "encode"](request).finish(),
|
|
function rpcCallback(err, response) {
|
|
|
|
if (err) {
|
|
self.emit("error", err, method);
|
|
return callback(err);
|
|
}
|
|
|
|
if (response === null) {
|
|
self.end(/* endedByRPC */ true);
|
|
return undefined;
|
|
}
|
|
|
|
if (!(response instanceof responseCtor)) {
|
|
try {
|
|
response = responseCtor[self.responseDelimited ? "decodeDelimited" : "decode"](response);
|
|
} catch (err) {
|
|
self.emit("error", err, method);
|
|
return callback(err);
|
|
}
|
|
}
|
|
|
|
self.emit("data", response, method);
|
|
return callback(null, response);
|
|
}
|
|
);
|
|
} catch (err) {
|
|
self.emit("error", err, method);
|
|
setTimeout(function() { callback(err); }, 0);
|
|
return undefined;
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Ends this service and emits the `end` event.
|
|
* @param {boolean} [endedByRPC=false] Whether the service has been ended by the RPC implementation.
|
|
* @returns {rpc.Service} `this`
|
|
*/
|
|
Service.prototype.end = function end(endedByRPC) {
|
|
if (this.rpcImpl) {
|
|
if (!endedByRPC) // signal end to rpcImpl
|
|
this.rpcImpl(null, null, null);
|
|
this.rpcImpl = null;
|
|
this.emit("end").off();
|
|
}
|
|
return this;
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/protobufjs/src/util/longbits.js":
|
|
/*!******************************************************!*\
|
|
!*** ./node_modules/protobufjs/src/util/longbits.js ***!
|
|
\******************************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
module.exports = LongBits;
|
|
|
|
var util = __webpack_require__(/*! ../util/minimal */ "./node_modules/protobufjs/src/util/minimal.js");
|
|
|
|
/**
|
|
* Constructs new long bits.
|
|
* @classdesc Helper class for working with the low and high bits of a 64 bit value.
|
|
* @memberof util
|
|
* @constructor
|
|
* @param {number} lo Low 32 bits, unsigned
|
|
* @param {number} hi High 32 bits, unsigned
|
|
*/
|
|
function LongBits(lo, hi) {
|
|
|
|
// note that the casts below are theoretically unnecessary as of today, but older statically
|
|
// generated converter code might still call the ctor with signed 32bits. kept for compat.
|
|
|
|
/**
|
|
* Low bits.
|
|
* @type {number}
|
|
*/
|
|
this.lo = lo >>> 0;
|
|
|
|
/**
|
|
* High bits.
|
|
* @type {number}
|
|
*/
|
|
this.hi = hi >>> 0;
|
|
}
|
|
|
|
/**
|
|
* Zero bits.
|
|
* @memberof util.LongBits
|
|
* @type {util.LongBits}
|
|
*/
|
|
var zero = LongBits.zero = new LongBits(0, 0);
|
|
|
|
zero.toNumber = function() { return 0; };
|
|
zero.zzEncode = zero.zzDecode = function() { return this; };
|
|
zero.length = function() { return 1; };
|
|
|
|
/**
|
|
* Zero hash.
|
|
* @memberof util.LongBits
|
|
* @type {string}
|
|
*/
|
|
var zeroHash = LongBits.zeroHash = "\0\0\0\0\0\0\0\0";
|
|
|
|
/**
|
|
* Constructs new long bits from the specified number.
|
|
* @param {number} value Value
|
|
* @returns {util.LongBits} Instance
|
|
*/
|
|
LongBits.fromNumber = function fromNumber(value) {
|
|
if (value === 0)
|
|
return zero;
|
|
var sign = value < 0;
|
|
if (sign)
|
|
value = -value;
|
|
var lo = value >>> 0,
|
|
hi = (value - lo) / 4294967296 >>> 0;
|
|
if (sign) {
|
|
hi = ~hi >>> 0;
|
|
lo = ~lo >>> 0;
|
|
if (++lo > 4294967295) {
|
|
lo = 0;
|
|
if (++hi > 4294967295)
|
|
hi = 0;
|
|
}
|
|
}
|
|
return new LongBits(lo, hi);
|
|
};
|
|
|
|
/**
|
|
* Constructs new long bits from a number, long or string.
|
|
* @param {Long|number|string} value Value
|
|
* @returns {util.LongBits} Instance
|
|
*/
|
|
LongBits.from = function from(value) {
|
|
if (typeof value === "number")
|
|
return LongBits.fromNumber(value);
|
|
if (util.isString(value)) {
|
|
/* istanbul ignore else */
|
|
if (util.Long)
|
|
value = util.Long.fromString(value);
|
|
else
|
|
return LongBits.fromNumber(parseInt(value, 10));
|
|
}
|
|
return value.low || value.high ? new LongBits(value.low >>> 0, value.high >>> 0) : zero;
|
|
};
|
|
|
|
/**
|
|
* Converts this long bits to a possibly unsafe JavaScript number.
|
|
* @param {boolean} [unsigned=false] Whether unsigned or not
|
|
* @returns {number} Possibly unsafe number
|
|
*/
|
|
LongBits.prototype.toNumber = function toNumber(unsigned) {
|
|
if (!unsigned && this.hi >>> 31) {
|
|
var lo = ~this.lo + 1 >>> 0,
|
|
hi = ~this.hi >>> 0;
|
|
if (!lo)
|
|
hi = hi + 1 >>> 0;
|
|
return -(lo + hi * 4294967296);
|
|
}
|
|
return this.lo + this.hi * 4294967296;
|
|
};
|
|
|
|
/**
|
|
* Converts this long bits to a long.
|
|
* @param {boolean} [unsigned=false] Whether unsigned or not
|
|
* @returns {Long} Long
|
|
*/
|
|
LongBits.prototype.toLong = function toLong(unsigned) {
|
|
return util.Long
|
|
? new util.Long(this.lo | 0, this.hi | 0, Boolean(unsigned))
|
|
/* istanbul ignore next */
|
|
: { low: this.lo | 0, high: this.hi | 0, unsigned: Boolean(unsigned) };
|
|
};
|
|
|
|
var charCodeAt = String.prototype.charCodeAt;
|
|
|
|
/**
|
|
* Constructs new long bits from the specified 8 characters long hash.
|
|
* @param {string} hash Hash
|
|
* @returns {util.LongBits} Bits
|
|
*/
|
|
LongBits.fromHash = function fromHash(hash) {
|
|
if (hash === zeroHash)
|
|
return zero;
|
|
return new LongBits(
|
|
( charCodeAt.call(hash, 0)
|
|
| charCodeAt.call(hash, 1) << 8
|
|
| charCodeAt.call(hash, 2) << 16
|
|
| charCodeAt.call(hash, 3) << 24) >>> 0
|
|
,
|
|
( charCodeAt.call(hash, 4)
|
|
| charCodeAt.call(hash, 5) << 8
|
|
| charCodeAt.call(hash, 6) << 16
|
|
| charCodeAt.call(hash, 7) << 24) >>> 0
|
|
);
|
|
};
|
|
|
|
/**
|
|
* Converts this long bits to a 8 characters long hash.
|
|
* @returns {string} Hash
|
|
*/
|
|
LongBits.prototype.toHash = function toHash() {
|
|
return String.fromCharCode(
|
|
this.lo & 255,
|
|
this.lo >>> 8 & 255,
|
|
this.lo >>> 16 & 255,
|
|
this.lo >>> 24 ,
|
|
this.hi & 255,
|
|
this.hi >>> 8 & 255,
|
|
this.hi >>> 16 & 255,
|
|
this.hi >>> 24
|
|
);
|
|
};
|
|
|
|
/**
|
|
* Zig-zag encodes this long bits.
|
|
* @returns {util.LongBits} `this`
|
|
*/
|
|
LongBits.prototype.zzEncode = function zzEncode() {
|
|
var mask = this.hi >> 31;
|
|
this.hi = ((this.hi << 1 | this.lo >>> 31) ^ mask) >>> 0;
|
|
this.lo = ( this.lo << 1 ^ mask) >>> 0;
|
|
return this;
|
|
};
|
|
|
|
/**
|
|
* Zig-zag decodes this long bits.
|
|
* @returns {util.LongBits} `this`
|
|
*/
|
|
LongBits.prototype.zzDecode = function zzDecode() {
|
|
var mask = -(this.lo & 1);
|
|
this.lo = ((this.lo >>> 1 | this.hi << 31) ^ mask) >>> 0;
|
|
this.hi = ( this.hi >>> 1 ^ mask) >>> 0;
|
|
return this;
|
|
};
|
|
|
|
/**
|
|
* Calculates the length of this longbits when encoded as a varint.
|
|
* @returns {number} Length
|
|
*/
|
|
LongBits.prototype.length = function length() {
|
|
var part0 = this.lo,
|
|
part1 = (this.lo >>> 28 | this.hi << 4) >>> 0,
|
|
part2 = this.hi >>> 24;
|
|
return part2 === 0
|
|
? part1 === 0
|
|
? part0 < 16384
|
|
? part0 < 128 ? 1 : 2
|
|
: part0 < 2097152 ? 3 : 4
|
|
: part1 < 16384
|
|
? part1 < 128 ? 5 : 6
|
|
: part1 < 2097152 ? 7 : 8
|
|
: part2 < 128 ? 9 : 10;
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/protobufjs/src/util/minimal.js":
|
|
/*!*****************************************************!*\
|
|
!*** ./node_modules/protobufjs/src/util/minimal.js ***!
|
|
\*****************************************************/
|
|
/***/ (function(__unused_webpack_module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
var util = exports;
|
|
|
|
// used to return a Promise where callback is omitted
|
|
util.asPromise = __webpack_require__(/*! @protobufjs/aspromise */ "./node_modules/@protobufjs/aspromise/index.js");
|
|
|
|
// converts to / from base64 encoded strings
|
|
util.base64 = __webpack_require__(/*! @protobufjs/base64 */ "./node_modules/@protobufjs/base64/index.js");
|
|
|
|
// base class of rpc.Service
|
|
util.EventEmitter = __webpack_require__(/*! @protobufjs/eventemitter */ "./node_modules/@protobufjs/eventemitter/index.js");
|
|
|
|
// float handling accross browsers
|
|
util.float = __webpack_require__(/*! @protobufjs/float */ "./node_modules/@protobufjs/float/index.js");
|
|
|
|
// requires modules optionally and hides the call from bundlers
|
|
util.inquire = __webpack_require__(/*! @protobufjs/inquire */ "./node_modules/@protobufjs/inquire/index.js");
|
|
|
|
// converts to / from utf8 encoded strings
|
|
util.utf8 = __webpack_require__(/*! @protobufjs/utf8 */ "./node_modules/@protobufjs/utf8/index.js");
|
|
|
|
// provides a node-like buffer pool in the browser
|
|
util.pool = __webpack_require__(/*! @protobufjs/pool */ "./node_modules/@protobufjs/pool/index.js");
|
|
|
|
// utility to work with the low and high bits of a 64 bit value
|
|
util.LongBits = __webpack_require__(/*! ./longbits */ "./node_modules/protobufjs/src/util/longbits.js");
|
|
|
|
/**
|
|
* Whether running within node or not.
|
|
* @memberof util
|
|
* @type {boolean}
|
|
*/
|
|
util.isNode = Boolean(typeof __webpack_require__.g !== "undefined"
|
|
&& __webpack_require__.g
|
|
&& __webpack_require__.g.process
|
|
&& __webpack_require__.g.process.versions
|
|
&& __webpack_require__.g.process.versions.node);
|
|
|
|
/**
|
|
* Global object reference.
|
|
* @memberof util
|
|
* @type {Object}
|
|
*/
|
|
util.global = util.isNode && __webpack_require__.g
|
|
|| typeof window !== "undefined" && window
|
|
|| typeof self !== "undefined" && self
|
|
|| this; // eslint-disable-line no-invalid-this
|
|
|
|
/**
|
|
* An immuable empty array.
|
|
* @memberof util
|
|
* @type {Array.<*>}
|
|
* @const
|
|
*/
|
|
util.emptyArray = Object.freeze ? Object.freeze([]) : /* istanbul ignore next */ []; // used on prototypes
|
|
|
|
/**
|
|
* An immutable empty object.
|
|
* @type {Object}
|
|
* @const
|
|
*/
|
|
util.emptyObject = Object.freeze ? Object.freeze({}) : /* istanbul ignore next */ {}; // used on prototypes
|
|
|
|
/**
|
|
* Tests if the specified value is an integer.
|
|
* @function
|
|
* @param {*} value Value to test
|
|
* @returns {boolean} `true` if the value is an integer
|
|
*/
|
|
util.isInteger = Number.isInteger || /* istanbul ignore next */ function isInteger(value) {
|
|
return typeof value === "number" && isFinite(value) && Math.floor(value) === value;
|
|
};
|
|
|
|
/**
|
|
* Tests if the specified value is a string.
|
|
* @param {*} value Value to test
|
|
* @returns {boolean} `true` if the value is a string
|
|
*/
|
|
util.isString = function isString(value) {
|
|
return typeof value === "string" || value instanceof String;
|
|
};
|
|
|
|
/**
|
|
* Tests if the specified value is a non-null object.
|
|
* @param {*} value Value to test
|
|
* @returns {boolean} `true` if the value is a non-null object
|
|
*/
|
|
util.isObject = function isObject(value) {
|
|
return value && typeof value === "object";
|
|
};
|
|
|
|
/**
|
|
* Checks if a property on a message is considered to be present.
|
|
* This is an alias of {@link util.isSet}.
|
|
* @function
|
|
* @param {Object} obj Plain object or message instance
|
|
* @param {string} prop Property name
|
|
* @returns {boolean} `true` if considered to be present, otherwise `false`
|
|
*/
|
|
util.isset =
|
|
|
|
/**
|
|
* Checks if a property on a message is considered to be present.
|
|
* @param {Object} obj Plain object or message instance
|
|
* @param {string} prop Property name
|
|
* @returns {boolean} `true` if considered to be present, otherwise `false`
|
|
*/
|
|
util.isSet = function isSet(obj, prop) {
|
|
var value = obj[prop];
|
|
if (value != null && obj.hasOwnProperty(prop)) // eslint-disable-line eqeqeq, no-prototype-builtins
|
|
return typeof value !== "object" || (Array.isArray(value) ? value.length : Object.keys(value).length) > 0;
|
|
return false;
|
|
};
|
|
|
|
/**
|
|
* Any compatible Buffer instance.
|
|
* This is a minimal stand-alone definition of a Buffer instance. The actual type is that exported by node's typings.
|
|
* @interface Buffer
|
|
* @extends Uint8Array
|
|
*/
|
|
|
|
/**
|
|
* Node's Buffer class if available.
|
|
* @type {Constructor<Buffer>}
|
|
*/
|
|
util.Buffer = (function() {
|
|
try {
|
|
var Buffer = util.inquire("buffer").Buffer;
|
|
// refuse to use non-node buffers if not explicitly assigned (perf reasons):
|
|
return Buffer.prototype.utf8Write ? Buffer : /* istanbul ignore next */ null;
|
|
} catch (e) {
|
|
/* istanbul ignore next */
|
|
return null;
|
|
}
|
|
})();
|
|
|
|
// Internal alias of or polyfull for Buffer.from.
|
|
util._Buffer_from = null;
|
|
|
|
// Internal alias of or polyfill for Buffer.allocUnsafe.
|
|
util._Buffer_allocUnsafe = null;
|
|
|
|
/**
|
|
* Creates a new buffer of whatever type supported by the environment.
|
|
* @param {number|number[]} [sizeOrArray=0] Buffer size or number array
|
|
* @returns {Uint8Array|Buffer} Buffer
|
|
*/
|
|
util.newBuffer = function newBuffer(sizeOrArray) {
|
|
/* istanbul ignore next */
|
|
return typeof sizeOrArray === "number"
|
|
? util.Buffer
|
|
? util._Buffer_allocUnsafe(sizeOrArray)
|
|
: new util.Array(sizeOrArray)
|
|
: util.Buffer
|
|
? util._Buffer_from(sizeOrArray)
|
|
: typeof Uint8Array === "undefined"
|
|
? sizeOrArray
|
|
: new Uint8Array(sizeOrArray);
|
|
};
|
|
|
|
/**
|
|
* Array implementation used in the browser. `Uint8Array` if supported, otherwise `Array`.
|
|
* @type {Constructor<Uint8Array>}
|
|
*/
|
|
util.Array = typeof Uint8Array !== "undefined" ? Uint8Array /* istanbul ignore next */ : Array;
|
|
|
|
/**
|
|
* Any compatible Long instance.
|
|
* This is a minimal stand-alone definition of a Long instance. The actual type is that exported by long.js.
|
|
* @interface Long
|
|
* @property {number} low Low bits
|
|
* @property {number} high High bits
|
|
* @property {boolean} unsigned Whether unsigned or not
|
|
*/
|
|
|
|
/**
|
|
* Long.js's Long class if available.
|
|
* @type {Constructor<Long>}
|
|
*/
|
|
util.Long = /* istanbul ignore next */ util.global.dcodeIO && /* istanbul ignore next */ util.global.dcodeIO.Long
|
|
|| /* istanbul ignore next */ util.global.Long
|
|
|| util.inquire("long");
|
|
|
|
/**
|
|
* Regular expression used to verify 2 bit (`bool`) map keys.
|
|
* @type {RegExp}
|
|
* @const
|
|
*/
|
|
util.key2Re = /^true|false|0|1$/;
|
|
|
|
/**
|
|
* Regular expression used to verify 32 bit (`int32` etc.) map keys.
|
|
* @type {RegExp}
|
|
* @const
|
|
*/
|
|
util.key32Re = /^-?(?:0|[1-9][0-9]*)$/;
|
|
|
|
/**
|
|
* Regular expression used to verify 64 bit (`int64` etc.) map keys.
|
|
* @type {RegExp}
|
|
* @const
|
|
*/
|
|
util.key64Re = /^(?:[\\x00-\\xff]{8}|-?(?:0|[1-9][0-9]*))$/;
|
|
|
|
/**
|
|
* Converts a number or long to an 8 characters long hash string.
|
|
* @param {Long|number} value Value to convert
|
|
* @returns {string} Hash
|
|
*/
|
|
util.longToHash = function longToHash(value) {
|
|
return value
|
|
? util.LongBits.from(value).toHash()
|
|
: util.LongBits.zeroHash;
|
|
};
|
|
|
|
/**
|
|
* Converts an 8 characters long hash string to a long or number.
|
|
* @param {string} hash Hash
|
|
* @param {boolean} [unsigned=false] Whether unsigned or not
|
|
* @returns {Long|number} Original value
|
|
*/
|
|
util.longFromHash = function longFromHash(hash, unsigned) {
|
|
var bits = util.LongBits.fromHash(hash);
|
|
if (util.Long)
|
|
return util.Long.fromBits(bits.lo, bits.hi, unsigned);
|
|
return bits.toNumber(Boolean(unsigned));
|
|
};
|
|
|
|
/**
|
|
* Merges the properties of the source object into the destination object.
|
|
* @memberof util
|
|
* @param {Object.<string,*>} dst Destination object
|
|
* @param {Object.<string,*>} src Source object
|
|
* @param {boolean} [ifNotSet=false] Merges only if the key is not already set
|
|
* @returns {Object.<string,*>} Destination object
|
|
*/
|
|
function merge(dst, src, ifNotSet) { // used by converters
|
|
for (var keys = Object.keys(src), i = 0; i < keys.length; ++i)
|
|
if (dst[keys[i]] === undefined || !ifNotSet)
|
|
dst[keys[i]] = src[keys[i]];
|
|
return dst;
|
|
}
|
|
|
|
util.merge = merge;
|
|
|
|
/**
|
|
* Converts the first character of a string to lower case.
|
|
* @param {string} str String to convert
|
|
* @returns {string} Converted string
|
|
*/
|
|
util.lcFirst = function lcFirst(str) {
|
|
return str.charAt(0).toLowerCase() + str.substring(1);
|
|
};
|
|
|
|
/**
|
|
* Creates a custom error constructor.
|
|
* @memberof util
|
|
* @param {string} name Error name
|
|
* @returns {Constructor<Error>} Custom error constructor
|
|
*/
|
|
function newError(name) {
|
|
|
|
function CustomError(message, properties) {
|
|
|
|
if (!(this instanceof CustomError))
|
|
return new CustomError(message, properties);
|
|
|
|
// Error.call(this, message);
|
|
// ^ just returns a new error instance because the ctor can be called as a function
|
|
|
|
Object.defineProperty(this, "message", { get: function() { return message; } });
|
|
|
|
/* istanbul ignore next */
|
|
if (Error.captureStackTrace) // node
|
|
Error.captureStackTrace(this, CustomError);
|
|
else
|
|
Object.defineProperty(this, "stack", { value: new Error().stack || "" });
|
|
|
|
if (properties)
|
|
merge(this, properties);
|
|
}
|
|
|
|
(CustomError.prototype = Object.create(Error.prototype)).constructor = CustomError;
|
|
|
|
Object.defineProperty(CustomError.prototype, "name", { get: function() { return name; } });
|
|
|
|
CustomError.prototype.toString = function toString() {
|
|
return this.name + ": " + this.message;
|
|
};
|
|
|
|
return CustomError;
|
|
}
|
|
|
|
util.newError = newError;
|
|
|
|
/**
|
|
* Constructs a new protocol error.
|
|
* @classdesc Error subclass indicating a protocol specifc error.
|
|
* @memberof util
|
|
* @extends Error
|
|
* @template T extends Message<T>
|
|
* @constructor
|
|
* @param {string} message Error message
|
|
* @param {Object.<string,*>} [properties] Additional properties
|
|
* @example
|
|
* try {
|
|
* MyMessage.decode(someBuffer); // throws if required fields are missing
|
|
* } catch (e) {
|
|
* if (e instanceof ProtocolError && e.instance)
|
|
* console.log("decoded so far: " + JSON.stringify(e.instance));
|
|
* }
|
|
*/
|
|
util.ProtocolError = newError("ProtocolError");
|
|
|
|
/**
|
|
* So far decoded message instance.
|
|
* @name util.ProtocolError#instance
|
|
* @type {Message<T>}
|
|
*/
|
|
|
|
/**
|
|
* A OneOf getter as returned by {@link util.oneOfGetter}.
|
|
* @typedef OneOfGetter
|
|
* @type {function}
|
|
* @returns {string|undefined} Set field name, if any
|
|
*/
|
|
|
|
/**
|
|
* Builds a getter for a oneof's present field name.
|
|
* @param {string[]} fieldNames Field names
|
|
* @returns {OneOfGetter} Unbound getter
|
|
*/
|
|
util.oneOfGetter = function getOneOf(fieldNames) {
|
|
var fieldMap = {};
|
|
for (var i = 0; i < fieldNames.length; ++i)
|
|
fieldMap[fieldNames[i]] = 1;
|
|
|
|
/**
|
|
* @returns {string|undefined} Set field name, if any
|
|
* @this Object
|
|
* @ignore
|
|
*/
|
|
return function() { // eslint-disable-line consistent-return
|
|
for (var keys = Object.keys(this), i = keys.length - 1; i > -1; --i)
|
|
if (fieldMap[keys[i]] === 1 && this[keys[i]] !== undefined && this[keys[i]] !== null)
|
|
return keys[i];
|
|
};
|
|
};
|
|
|
|
/**
|
|
* A OneOf setter as returned by {@link util.oneOfSetter}.
|
|
* @typedef OneOfSetter
|
|
* @type {function}
|
|
* @param {string|undefined} value Field name
|
|
* @returns {undefined}
|
|
*/
|
|
|
|
/**
|
|
* Builds a setter for a oneof's present field name.
|
|
* @param {string[]} fieldNames Field names
|
|
* @returns {OneOfSetter} Unbound setter
|
|
*/
|
|
util.oneOfSetter = function setOneOf(fieldNames) {
|
|
|
|
/**
|
|
* @param {string} name Field name
|
|
* @returns {undefined}
|
|
* @this Object
|
|
* @ignore
|
|
*/
|
|
return function(name) {
|
|
for (var i = 0; i < fieldNames.length; ++i)
|
|
if (fieldNames[i] !== name)
|
|
delete this[fieldNames[i]];
|
|
};
|
|
};
|
|
|
|
/**
|
|
* Default conversion options used for {@link Message#toJSON} implementations.
|
|
*
|
|
* These options are close to proto3's JSON mapping with the exception that internal types like Any are handled just like messages. More precisely:
|
|
*
|
|
* - Longs become strings
|
|
* - Enums become string keys
|
|
* - Bytes become base64 encoded strings
|
|
* - (Sub-)Messages become plain objects
|
|
* - Maps become plain objects with all string keys
|
|
* - Repeated fields become arrays
|
|
* - NaN and Infinity for float and double fields become strings
|
|
*
|
|
* @type {IConversionOptions}
|
|
* @see https://developers.google.com/protocol-buffers/docs/proto3?hl=en#json
|
|
*/
|
|
util.toJSONOptions = {
|
|
longs: String,
|
|
enums: String,
|
|
bytes: String,
|
|
json: true
|
|
};
|
|
|
|
// Sets up buffer utility according to the environment (called in index-minimal)
|
|
util._configure = function() {
|
|
var Buffer = util.Buffer;
|
|
/* istanbul ignore if */
|
|
if (!Buffer) {
|
|
util._Buffer_from = util._Buffer_allocUnsafe = null;
|
|
return;
|
|
}
|
|
// because node 4.x buffers are incompatible & immutable
|
|
// see: https://github.com/dcodeIO/protobuf.js/pull/665
|
|
util._Buffer_from = Buffer.from !== Uint8Array.from && Buffer.from ||
|
|
/* istanbul ignore next */
|
|
function Buffer_from(value, encoding) {
|
|
return new Buffer(value, encoding);
|
|
};
|
|
util._Buffer_allocUnsafe = Buffer.allocUnsafe ||
|
|
/* istanbul ignore next */
|
|
function Buffer_allocUnsafe(size) {
|
|
return new Buffer(size);
|
|
};
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/protobufjs/src/writer.js":
|
|
/*!***********************************************!*\
|
|
!*** ./node_modules/protobufjs/src/writer.js ***!
|
|
\***********************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
module.exports = Writer;
|
|
|
|
var util = __webpack_require__(/*! ./util/minimal */ "./node_modules/protobufjs/src/util/minimal.js");
|
|
|
|
var BufferWriter; // cyclic
|
|
|
|
var LongBits = util.LongBits,
|
|
base64 = util.base64,
|
|
utf8 = util.utf8;
|
|
|
|
/**
|
|
* Constructs a new writer operation instance.
|
|
* @classdesc Scheduled writer operation.
|
|
* @constructor
|
|
* @param {function(*, Uint8Array, number)} fn Function to call
|
|
* @param {number} len Value byte length
|
|
* @param {*} val Value to write
|
|
* @ignore
|
|
*/
|
|
function Op(fn, len, val) {
|
|
|
|
/**
|
|
* Function to call.
|
|
* @type {function(Uint8Array, number, *)}
|
|
*/
|
|
this.fn = fn;
|
|
|
|
/**
|
|
* Value byte length.
|
|
* @type {number}
|
|
*/
|
|
this.len = len;
|
|
|
|
/**
|
|
* Next operation.
|
|
* @type {Writer.Op|undefined}
|
|
*/
|
|
this.next = undefined;
|
|
|
|
/**
|
|
* Value to write.
|
|
* @type {*}
|
|
*/
|
|
this.val = val; // type varies
|
|
}
|
|
|
|
/* istanbul ignore next */
|
|
function noop() {} // eslint-disable-line no-empty-function
|
|
|
|
/**
|
|
* Constructs a new writer state instance.
|
|
* @classdesc Copied writer state.
|
|
* @memberof Writer
|
|
* @constructor
|
|
* @param {Writer} writer Writer to copy state from
|
|
* @ignore
|
|
*/
|
|
function State(writer) {
|
|
|
|
/**
|
|
* Current head.
|
|
* @type {Writer.Op}
|
|
*/
|
|
this.head = writer.head;
|
|
|
|
/**
|
|
* Current tail.
|
|
* @type {Writer.Op}
|
|
*/
|
|
this.tail = writer.tail;
|
|
|
|
/**
|
|
* Current buffer length.
|
|
* @type {number}
|
|
*/
|
|
this.len = writer.len;
|
|
|
|
/**
|
|
* Next state.
|
|
* @type {State|null}
|
|
*/
|
|
this.next = writer.states;
|
|
}
|
|
|
|
/**
|
|
* Constructs a new writer instance.
|
|
* @classdesc Wire format writer using `Uint8Array` if available, otherwise `Array`.
|
|
* @constructor
|
|
*/
|
|
function Writer() {
|
|
|
|
/**
|
|
* Current length.
|
|
* @type {number}
|
|
*/
|
|
this.len = 0;
|
|
|
|
/**
|
|
* Operations head.
|
|
* @type {Object}
|
|
*/
|
|
this.head = new Op(noop, 0, 0);
|
|
|
|
/**
|
|
* Operations tail
|
|
* @type {Object}
|
|
*/
|
|
this.tail = this.head;
|
|
|
|
/**
|
|
* Linked forked states.
|
|
* @type {Object|null}
|
|
*/
|
|
this.states = null;
|
|
|
|
// When a value is written, the writer calculates its byte length and puts it into a linked
|
|
// list of operations to perform when finish() is called. This both allows us to allocate
|
|
// buffers of the exact required size and reduces the amount of work we have to do compared
|
|
// to first calculating over objects and then encoding over objects. In our case, the encoding
|
|
// part is just a linked list walk calling operations with already prepared values.
|
|
}
|
|
|
|
var create = function create() {
|
|
return util.Buffer
|
|
? function create_buffer_setup() {
|
|
return (Writer.create = function create_buffer() {
|
|
return new BufferWriter();
|
|
})();
|
|
}
|
|
/* istanbul ignore next */
|
|
: function create_array() {
|
|
return new Writer();
|
|
};
|
|
};
|
|
|
|
/**
|
|
* Creates a new writer.
|
|
* @function
|
|
* @returns {BufferWriter|Writer} A {@link BufferWriter} when Buffers are supported, otherwise a {@link Writer}
|
|
*/
|
|
Writer.create = create();
|
|
|
|
/**
|
|
* Allocates a buffer of the specified size.
|
|
* @param {number} size Buffer size
|
|
* @returns {Uint8Array} Buffer
|
|
*/
|
|
Writer.alloc = function alloc(size) {
|
|
return new util.Array(size);
|
|
};
|
|
|
|
// Use Uint8Array buffer pool in the browser, just like node does with buffers
|
|
/* istanbul ignore else */
|
|
if (util.Array !== Array)
|
|
Writer.alloc = util.pool(Writer.alloc, util.Array.prototype.subarray);
|
|
|
|
/**
|
|
* Pushes a new operation to the queue.
|
|
* @param {function(Uint8Array, number, *)} fn Function to call
|
|
* @param {number} len Value byte length
|
|
* @param {number} val Value to write
|
|
* @returns {Writer} `this`
|
|
* @private
|
|
*/
|
|
Writer.prototype._push = function push(fn, len, val) {
|
|
this.tail = this.tail.next = new Op(fn, len, val);
|
|
this.len += len;
|
|
return this;
|
|
};
|
|
|
|
function writeByte(val, buf, pos) {
|
|
buf[pos] = val & 255;
|
|
}
|
|
|
|
function writeVarint32(val, buf, pos) {
|
|
while (val > 127) {
|
|
buf[pos++] = val & 127 | 128;
|
|
val >>>= 7;
|
|
}
|
|
buf[pos] = val;
|
|
}
|
|
|
|
/**
|
|
* Constructs a new varint writer operation instance.
|
|
* @classdesc Scheduled varint writer operation.
|
|
* @extends Op
|
|
* @constructor
|
|
* @param {number} len Value byte length
|
|
* @param {number} val Value to write
|
|
* @ignore
|
|
*/
|
|
function VarintOp(len, val) {
|
|
this.len = len;
|
|
this.next = undefined;
|
|
this.val = val;
|
|
}
|
|
|
|
VarintOp.prototype = Object.create(Op.prototype);
|
|
VarintOp.prototype.fn = writeVarint32;
|
|
|
|
/**
|
|
* Writes an unsigned 32 bit value as a varint.
|
|
* @param {number} value Value to write
|
|
* @returns {Writer} `this`
|
|
*/
|
|
Writer.prototype.uint32 = function write_uint32(value) {
|
|
// here, the call to this.push has been inlined and a varint specific Op subclass is used.
|
|
// uint32 is by far the most frequently used operation and benefits significantly from this.
|
|
this.len += (this.tail = this.tail.next = new VarintOp(
|
|
(value = value >>> 0)
|
|
< 128 ? 1
|
|
: value < 16384 ? 2
|
|
: value < 2097152 ? 3
|
|
: value < 268435456 ? 4
|
|
: 5,
|
|
value)).len;
|
|
return this;
|
|
};
|
|
|
|
/**
|
|
* Writes a signed 32 bit value as a varint.
|
|
* @function
|
|
* @param {number} value Value to write
|
|
* @returns {Writer} `this`
|
|
*/
|
|
Writer.prototype.int32 = function write_int32(value) {
|
|
return value < 0
|
|
? this._push(writeVarint64, 10, LongBits.fromNumber(value)) // 10 bytes per spec
|
|
: this.uint32(value);
|
|
};
|
|
|
|
/**
|
|
* Writes a 32 bit value as a varint, zig-zag encoded.
|
|
* @param {number} value Value to write
|
|
* @returns {Writer} `this`
|
|
*/
|
|
Writer.prototype.sint32 = function write_sint32(value) {
|
|
return this.uint32((value << 1 ^ value >> 31) >>> 0);
|
|
};
|
|
|
|
function writeVarint64(val, buf, pos) {
|
|
while (val.hi) {
|
|
buf[pos++] = val.lo & 127 | 128;
|
|
val.lo = (val.lo >>> 7 | val.hi << 25) >>> 0;
|
|
val.hi >>>= 7;
|
|
}
|
|
while (val.lo > 127) {
|
|
buf[pos++] = val.lo & 127 | 128;
|
|
val.lo = val.lo >>> 7;
|
|
}
|
|
buf[pos++] = val.lo;
|
|
}
|
|
|
|
/**
|
|
* Writes an unsigned 64 bit value as a varint.
|
|
* @param {Long|number|string} value Value to write
|
|
* @returns {Writer} `this`
|
|
* @throws {TypeError} If `value` is a string and no long library is present.
|
|
*/
|
|
Writer.prototype.uint64 = function write_uint64(value) {
|
|
var bits = LongBits.from(value);
|
|
return this._push(writeVarint64, bits.length(), bits);
|
|
};
|
|
|
|
/**
|
|
* Writes a signed 64 bit value as a varint.
|
|
* @function
|
|
* @param {Long|number|string} value Value to write
|
|
* @returns {Writer} `this`
|
|
* @throws {TypeError} If `value` is a string and no long library is present.
|
|
*/
|
|
Writer.prototype.int64 = Writer.prototype.uint64;
|
|
|
|
/**
|
|
* Writes a signed 64 bit value as a varint, zig-zag encoded.
|
|
* @param {Long|number|string} value Value to write
|
|
* @returns {Writer} `this`
|
|
* @throws {TypeError} If `value` is a string and no long library is present.
|
|
*/
|
|
Writer.prototype.sint64 = function write_sint64(value) {
|
|
var bits = LongBits.from(value).zzEncode();
|
|
return this._push(writeVarint64, bits.length(), bits);
|
|
};
|
|
|
|
/**
|
|
* Writes a boolish value as a varint.
|
|
* @param {boolean} value Value to write
|
|
* @returns {Writer} `this`
|
|
*/
|
|
Writer.prototype.bool = function write_bool(value) {
|
|
return this._push(writeByte, 1, value ? 1 : 0);
|
|
};
|
|
|
|
function writeFixed32(val, buf, pos) {
|
|
buf[pos ] = val & 255;
|
|
buf[pos + 1] = val >>> 8 & 255;
|
|
buf[pos + 2] = val >>> 16 & 255;
|
|
buf[pos + 3] = val >>> 24;
|
|
}
|
|
|
|
/**
|
|
* Writes an unsigned 32 bit value as fixed 32 bits.
|
|
* @param {number} value Value to write
|
|
* @returns {Writer} `this`
|
|
*/
|
|
Writer.prototype.fixed32 = function write_fixed32(value) {
|
|
return this._push(writeFixed32, 4, value >>> 0);
|
|
};
|
|
|
|
/**
|
|
* Writes a signed 32 bit value as fixed 32 bits.
|
|
* @function
|
|
* @param {number} value Value to write
|
|
* @returns {Writer} `this`
|
|
*/
|
|
Writer.prototype.sfixed32 = Writer.prototype.fixed32;
|
|
|
|
/**
|
|
* Writes an unsigned 64 bit value as fixed 64 bits.
|
|
* @param {Long|number|string} value Value to write
|
|
* @returns {Writer} `this`
|
|
* @throws {TypeError} If `value` is a string and no long library is present.
|
|
*/
|
|
Writer.prototype.fixed64 = function write_fixed64(value) {
|
|
var bits = LongBits.from(value);
|
|
return this._push(writeFixed32, 4, bits.lo)._push(writeFixed32, 4, bits.hi);
|
|
};
|
|
|
|
/**
|
|
* Writes a signed 64 bit value as fixed 64 bits.
|
|
* @function
|
|
* @param {Long|number|string} value Value to write
|
|
* @returns {Writer} `this`
|
|
* @throws {TypeError} If `value` is a string and no long library is present.
|
|
*/
|
|
Writer.prototype.sfixed64 = Writer.prototype.fixed64;
|
|
|
|
/**
|
|
* Writes a float (32 bit).
|
|
* @function
|
|
* @param {number} value Value to write
|
|
* @returns {Writer} `this`
|
|
*/
|
|
Writer.prototype.float = function write_float(value) {
|
|
return this._push(util.float.writeFloatLE, 4, value);
|
|
};
|
|
|
|
/**
|
|
* Writes a double (64 bit float).
|
|
* @function
|
|
* @param {number} value Value to write
|
|
* @returns {Writer} `this`
|
|
*/
|
|
Writer.prototype.double = function write_double(value) {
|
|
return this._push(util.float.writeDoubleLE, 8, value);
|
|
};
|
|
|
|
var writeBytes = util.Array.prototype.set
|
|
? function writeBytes_set(val, buf, pos) {
|
|
buf.set(val, pos); // also works for plain array values
|
|
}
|
|
/* istanbul ignore next */
|
|
: function writeBytes_for(val, buf, pos) {
|
|
for (var i = 0; i < val.length; ++i)
|
|
buf[pos + i] = val[i];
|
|
};
|
|
|
|
/**
|
|
* Writes a sequence of bytes.
|
|
* @param {Uint8Array|string} value Buffer or base64 encoded string to write
|
|
* @returns {Writer} `this`
|
|
*/
|
|
Writer.prototype.bytes = function write_bytes(value) {
|
|
var len = value.length >>> 0;
|
|
if (!len)
|
|
return this._push(writeByte, 1, 0);
|
|
if (util.isString(value)) {
|
|
var buf = Writer.alloc(len = base64.length(value));
|
|
base64.decode(value, buf, 0);
|
|
value = buf;
|
|
}
|
|
return this.uint32(len)._push(writeBytes, len, value);
|
|
};
|
|
|
|
/**
|
|
* Writes a string.
|
|
* @param {string} value Value to write
|
|
* @returns {Writer} `this`
|
|
*/
|
|
Writer.prototype.string = function write_string(value) {
|
|
var len = utf8.length(value);
|
|
return len
|
|
? this.uint32(len)._push(utf8.write, len, value)
|
|
: this._push(writeByte, 1, 0);
|
|
};
|
|
|
|
/**
|
|
* Forks this writer's state by pushing it to a stack.
|
|
* Calling {@link Writer#reset|reset} or {@link Writer#ldelim|ldelim} resets the writer to the previous state.
|
|
* @returns {Writer} `this`
|
|
*/
|
|
Writer.prototype.fork = function fork() {
|
|
this.states = new State(this);
|
|
this.head = this.tail = new Op(noop, 0, 0);
|
|
this.len = 0;
|
|
return this;
|
|
};
|
|
|
|
/**
|
|
* Resets this instance to the last state.
|
|
* @returns {Writer} `this`
|
|
*/
|
|
Writer.prototype.reset = function reset() {
|
|
if (this.states) {
|
|
this.head = this.states.head;
|
|
this.tail = this.states.tail;
|
|
this.len = this.states.len;
|
|
this.states = this.states.next;
|
|
} else {
|
|
this.head = this.tail = new Op(noop, 0, 0);
|
|
this.len = 0;
|
|
}
|
|
return this;
|
|
};
|
|
|
|
/**
|
|
* Resets to the last state and appends the fork state's current write length as a varint followed by its operations.
|
|
* @returns {Writer} `this`
|
|
*/
|
|
Writer.prototype.ldelim = function ldelim() {
|
|
var head = this.head,
|
|
tail = this.tail,
|
|
len = this.len;
|
|
this.reset().uint32(len);
|
|
if (len) {
|
|
this.tail.next = head.next; // skip noop
|
|
this.tail = tail;
|
|
this.len += len;
|
|
}
|
|
return this;
|
|
};
|
|
|
|
/**
|
|
* Finishes the write operation.
|
|
* @returns {Uint8Array} Finished buffer
|
|
*/
|
|
Writer.prototype.finish = function finish() {
|
|
var head = this.head.next, // skip noop
|
|
buf = this.constructor.alloc(this.len),
|
|
pos = 0;
|
|
while (head) {
|
|
head.fn(head.val, buf, pos);
|
|
pos += head.len;
|
|
head = head.next;
|
|
}
|
|
// this.head = this.tail = null;
|
|
return buf;
|
|
};
|
|
|
|
Writer._configure = function(BufferWriter_) {
|
|
BufferWriter = BufferWriter_;
|
|
Writer.create = create();
|
|
BufferWriter._configure();
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/protobufjs/src/writer_buffer.js":
|
|
/*!******************************************************!*\
|
|
!*** ./node_modules/protobufjs/src/writer_buffer.js ***!
|
|
\******************************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
module.exports = BufferWriter;
|
|
|
|
// extends Writer
|
|
var Writer = __webpack_require__(/*! ./writer */ "./node_modules/protobufjs/src/writer.js");
|
|
(BufferWriter.prototype = Object.create(Writer.prototype)).constructor = BufferWriter;
|
|
|
|
var util = __webpack_require__(/*! ./util/minimal */ "./node_modules/protobufjs/src/util/minimal.js");
|
|
|
|
/**
|
|
* Constructs a new buffer writer instance.
|
|
* @classdesc Wire format writer using node buffers.
|
|
* @extends Writer
|
|
* @constructor
|
|
*/
|
|
function BufferWriter() {
|
|
Writer.call(this);
|
|
}
|
|
|
|
BufferWriter._configure = function () {
|
|
/**
|
|
* Allocates a buffer of the specified size.
|
|
* @function
|
|
* @param {number} size Buffer size
|
|
* @returns {Buffer} Buffer
|
|
*/
|
|
BufferWriter.alloc = util._Buffer_allocUnsafe;
|
|
|
|
BufferWriter.writeBytesBuffer = util.Buffer && util.Buffer.prototype instanceof Uint8Array && util.Buffer.prototype.set.name === "set"
|
|
? function writeBytesBuffer_set(val, buf, pos) {
|
|
buf.set(val, pos); // faster than copy (requires node >= 4 where Buffers extend Uint8Array and set is properly inherited)
|
|
// also works for plain array values
|
|
}
|
|
/* istanbul ignore next */
|
|
: function writeBytesBuffer_copy(val, buf, pos) {
|
|
if (val.copy) // Buffer values
|
|
val.copy(buf, pos, 0, val.length);
|
|
else for (var i = 0; i < val.length;) // plain array values
|
|
buf[pos++] = val[i++];
|
|
};
|
|
};
|
|
|
|
|
|
/**
|
|
* @override
|
|
*/
|
|
BufferWriter.prototype.bytes = function write_bytes_buffer(value) {
|
|
if (util.isString(value))
|
|
value = util._Buffer_from(value, "base64");
|
|
var len = value.length >>> 0;
|
|
this.uint32(len);
|
|
if (len)
|
|
this._push(BufferWriter.writeBytesBuffer, len, value);
|
|
return this;
|
|
};
|
|
|
|
function writeStringBuffer(val, buf, pos) {
|
|
if (val.length < 40) // plain js is faster for short strings (probably due to redundant assertions)
|
|
util.utf8.write(val, buf, pos);
|
|
else if (buf.utf8Write)
|
|
buf.utf8Write(val, pos);
|
|
else
|
|
buf.write(val, pos);
|
|
}
|
|
|
|
/**
|
|
* @override
|
|
*/
|
|
BufferWriter.prototype.string = function write_string_buffer(value) {
|
|
var len = util.Buffer.byteLength(value);
|
|
this.uint32(len);
|
|
if (len)
|
|
this._push(writeStringBuffer, len, value);
|
|
return this;
|
|
};
|
|
|
|
|
|
/**
|
|
* Finishes the write operation.
|
|
* @name BufferWriter#finish
|
|
* @function
|
|
* @returns {Buffer} Finished buffer
|
|
*/
|
|
|
|
BufferWriter._configure();
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./lib/backend-onnxjs.ts":
|
|
/*!*******************************!*\
|
|
!*** ./lib/backend-onnxjs.ts ***!
|
|
\*******************************/
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
// Licensed under the MIT License.
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.onnxjsBackend = void 0;
|
|
const session_1 = __webpack_require__(/*! ./onnxjs/session */ "./lib/onnxjs/session.ts");
|
|
const session_handler_1 = __webpack_require__(/*! ./onnxjs/session-handler */ "./lib/onnxjs/session-handler.ts");
|
|
class OnnxjsBackend {
|
|
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
|
async init() { }
|
|
async createSessionHandler(pathOrBuffer, options) {
|
|
// NOTE: Session.Config(from onnx.js) is not compatible with InferenceSession.SessionOptions(from
|
|
// onnxruntime-common).
|
|
// In future we should remove Session.Config and use InferenceSession.SessionOptions.
|
|
// Currently we allow this to happen to make test runner work.
|
|
const session = new session_1.Session(options);
|
|
// typescript cannot merge method override correctly (so far in 4.2.3). need if-else to call the method.
|
|
if (typeof pathOrBuffer === 'string') {
|
|
await session.loadModel(pathOrBuffer);
|
|
}
|
|
else {
|
|
await session.loadModel(pathOrBuffer);
|
|
}
|
|
return new session_handler_1.OnnxjsSessionHandler(session);
|
|
}
|
|
}
|
|
exports.onnxjsBackend = new OnnxjsBackend();
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./lib/backend-wasm.ts":
|
|
/*!*****************************!*\
|
|
!*** ./lib/backend-wasm.ts ***!
|
|
\*****************************/
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
// Licensed under the MIT License.
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.wasmBackend = exports.initializeFlags = void 0;
|
|
const onnxruntime_common_1 = __webpack_require__(/*! onnxruntime-common */ "../common/dist/lib/index.js");
|
|
const os_1 = __webpack_require__(/*! os */ "?0757");
|
|
const proxy_wrapper_1 = __webpack_require__(/*! ./wasm/proxy-wrapper */ "./lib/wasm/proxy-wrapper.ts");
|
|
const session_handler_1 = __webpack_require__(/*! ./wasm/session-handler */ "./lib/wasm/session-handler.ts");
|
|
/**
|
|
* This function initializes all flags for WebAssembly.
|
|
*
|
|
* Those flags are accessible from `ort.env.wasm`. Users are allow to set those flags before the first inference session
|
|
* being created, to override default value.
|
|
*/
|
|
const initializeFlags = () => {
|
|
if (typeof onnxruntime_common_1.env.wasm.initTimeout !== 'number' || onnxruntime_common_1.env.wasm.initTimeout < 0) {
|
|
onnxruntime_common_1.env.wasm.initTimeout = 0;
|
|
}
|
|
if (typeof onnxruntime_common_1.env.wasm.simd !== 'boolean') {
|
|
onnxruntime_common_1.env.wasm.simd = true;
|
|
}
|
|
if (typeof onnxruntime_common_1.env.wasm.proxy !== 'boolean') {
|
|
onnxruntime_common_1.env.wasm.proxy = false;
|
|
}
|
|
if (typeof onnxruntime_common_1.env.wasm.numThreads !== 'number' || !Number.isInteger(onnxruntime_common_1.env.wasm.numThreads) || onnxruntime_common_1.env.wasm.numThreads <= 0) {
|
|
const numCpuLogicalCores = typeof navigator === 'undefined' ? (0, os_1.cpus)().length : navigator.hardwareConcurrency;
|
|
onnxruntime_common_1.env.wasm.numThreads = Math.min(4, Math.ceil((numCpuLogicalCores || 1) / 2));
|
|
}
|
|
};
|
|
exports.initializeFlags = initializeFlags;
|
|
class OnnxruntimeWebAssemblyBackend {
|
|
async init() {
|
|
// populate wasm flags
|
|
(0, exports.initializeFlags)();
|
|
// init wasm
|
|
await (0, proxy_wrapper_1.initWasm)();
|
|
}
|
|
async createSessionHandler(pathOrBuffer, options) {
|
|
const handler = new session_handler_1.OnnxruntimeWebAssemblySessionHandler();
|
|
await handler.loadModel(pathOrBuffer, options);
|
|
return Promise.resolve(handler);
|
|
}
|
|
}
|
|
exports.wasmBackend = new OnnxruntimeWebAssemblyBackend();
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./lib/index.ts":
|
|
/*!**********************!*\
|
|
!*** ./lib/index.ts ***!
|
|
\**********************/
|
|
/***/ (function(__unused_webpack_module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
// Licensed under the MIT License.
|
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
if (k2 === undefined) k2 = k;
|
|
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
}
|
|
Object.defineProperty(o, k2, desc);
|
|
}) : (function(o, m, k, k2) {
|
|
if (k2 === undefined) k2 = k;
|
|
o[k2] = m[k];
|
|
}));
|
|
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
};
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
/* eslint-disable @typescript-eslint/no-var-requires, @typescript-eslint/no-require-imports */
|
|
// We use "require" instead of "import" here because import statement must be put in top level. Our current code does
|
|
// not allow terser to tree-shaking code as expected because some codes are treated as having side effects.
|
|
// So we import code inside the if-clause to allow terser remove the code safely.
|
|
__exportStar(__webpack_require__(/*! onnxruntime-common */ "../common/dist/lib/index.js"), exports);
|
|
const onnxruntime_common_1 = __webpack_require__(/*! onnxruntime-common */ "../common/dist/lib/index.js");
|
|
if (true) {
|
|
const onnxjsBackend = (__webpack_require__(/*! ./backend-onnxjs */ "./lib/backend-onnxjs.ts").onnxjsBackend);
|
|
(0, onnxruntime_common_1.registerBackend)('webgl', onnxjsBackend, -10);
|
|
}
|
|
if (true) {
|
|
const wasmBackend = (__webpack_require__(/*! ./backend-wasm */ "./lib/backend-wasm.ts").wasmBackend);
|
|
(0, onnxruntime_common_1.registerBackend)('cpu', wasmBackend, 10);
|
|
(0, onnxruntime_common_1.registerBackend)('wasm', wasmBackend, 10);
|
|
(0, onnxruntime_common_1.registerBackend)('xnnpack', wasmBackend, 9);
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./lib/onnxjs/attribute-with-cache-key.ts":
|
|
/*!************************************************!*\
|
|
!*** ./lib/onnxjs/attribute-with-cache-key.ts ***!
|
|
\************************************************/
|
|
/***/ ((__unused_webpack_module, exports) => {
|
|
|
|
"use strict";
|
|
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
// Licensed under the MIT License.
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.createAttributeWithCacheKey = void 0;
|
|
class AttributeWithCacheKeyImpl {
|
|
constructor(attribute) {
|
|
Object.assign(this, attribute);
|
|
}
|
|
get cacheKey() {
|
|
if (!this._cacheKey) {
|
|
this._cacheKey =
|
|
Object.getOwnPropertyNames(this).sort().map(name => `${this[name]}`).join(';');
|
|
}
|
|
return this._cacheKey;
|
|
}
|
|
}
|
|
const createAttributeWithCacheKey = (attribute) => new AttributeWithCacheKeyImpl(attribute);
|
|
exports.createAttributeWithCacheKey = createAttributeWithCacheKey;
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./lib/onnxjs/attribute.ts":
|
|
/*!*********************************!*\
|
|
!*** ./lib/onnxjs/attribute.ts ***!
|
|
\*********************************/
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
// Licensed under the MIT License.
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.Attribute = void 0;
|
|
const onnx_proto_1 = __webpack_require__(/*! onnx-proto */ "./node_modules/onnx-proto/dist/onnx.js");
|
|
const ort_generated_1 = __webpack_require__(/*! ./ort-schema/ort-generated */ "./lib/onnxjs/ort-schema/ort-generated.ts");
|
|
const tensor_1 = __webpack_require__(/*! ./tensor */ "./lib/onnxjs/tensor.ts");
|
|
const util_1 = __webpack_require__(/*! ./util */ "./lib/onnxjs/util.ts");
|
|
var ortFbs = ort_generated_1.onnxruntime.experimental.fbs;
|
|
class Attribute {
|
|
constructor(attributes) {
|
|
this._attributes = new Map();
|
|
if (attributes !== null && attributes !== undefined) {
|
|
for (const attr of attributes) {
|
|
if (attr instanceof onnx_proto_1.onnx.AttributeProto) {
|
|
this._attributes.set(attr.name, [Attribute.getValue(attr), Attribute.getType(attr)]);
|
|
}
|
|
else if (attr instanceof ortFbs.Attribute) {
|
|
this._attributes.set(attr.name(), [Attribute.getValue(attr), Attribute.getType(attr)]);
|
|
}
|
|
}
|
|
if (this._attributes.size < attributes.length) {
|
|
throw new Error('duplicated attribute names');
|
|
}
|
|
}
|
|
}
|
|
set(key, type, value) {
|
|
this._attributes.set(key, [value, type]);
|
|
}
|
|
delete(key) {
|
|
this._attributes.delete(key);
|
|
}
|
|
getFloat(key, defaultValue) {
|
|
return this.get(key, 'float', defaultValue);
|
|
}
|
|
getInt(key, defaultValue) {
|
|
return this.get(key, 'int', defaultValue);
|
|
}
|
|
getString(key, defaultValue) {
|
|
return this.get(key, 'string', defaultValue);
|
|
}
|
|
getTensor(key, defaultValue) {
|
|
return this.get(key, 'tensor', defaultValue);
|
|
}
|
|
getFloats(key, defaultValue) {
|
|
return this.get(key, 'floats', defaultValue);
|
|
}
|
|
getInts(key, defaultValue) {
|
|
return this.get(key, 'ints', defaultValue);
|
|
}
|
|
getStrings(key, defaultValue) {
|
|
return this.get(key, 'strings', defaultValue);
|
|
}
|
|
getTensors(key, defaultValue) {
|
|
return this.get(key, 'tensors', defaultValue);
|
|
}
|
|
get(key, type, defaultValue) {
|
|
const valueAndType = this._attributes.get(key);
|
|
if (valueAndType === undefined) {
|
|
if (defaultValue !== undefined) {
|
|
return defaultValue;
|
|
}
|
|
throw new Error(`required attribute not found: ${key}`);
|
|
}
|
|
if (valueAndType[1] !== type) {
|
|
throw new Error(`type mismatch: expected ${type} but got ${valueAndType[1]}`);
|
|
}
|
|
return valueAndType[0];
|
|
}
|
|
static getType(attr) {
|
|
const type = attr instanceof onnx_proto_1.onnx.AttributeProto ? (attr).type : attr.type();
|
|
switch (type) {
|
|
case onnx_proto_1.onnx.AttributeProto.AttributeType.FLOAT:
|
|
return 'float';
|
|
case onnx_proto_1.onnx.AttributeProto.AttributeType.INT:
|
|
return 'int';
|
|
case onnx_proto_1.onnx.AttributeProto.AttributeType.STRING:
|
|
return 'string';
|
|
case onnx_proto_1.onnx.AttributeProto.AttributeType.TENSOR:
|
|
return 'tensor';
|
|
case onnx_proto_1.onnx.AttributeProto.AttributeType.FLOATS:
|
|
return 'floats';
|
|
case onnx_proto_1.onnx.AttributeProto.AttributeType.INTS:
|
|
return 'ints';
|
|
case onnx_proto_1.onnx.AttributeProto.AttributeType.STRINGS:
|
|
return 'strings';
|
|
case onnx_proto_1.onnx.AttributeProto.AttributeType.TENSORS:
|
|
return 'tensors';
|
|
default:
|
|
throw new Error(`attribute type is not supported yet: ${onnx_proto_1.onnx.AttributeProto.AttributeType[type]}`);
|
|
}
|
|
}
|
|
static getValue(attr) {
|
|
const attrType = attr instanceof onnx_proto_1.onnx.AttributeProto ? attr.type : attr.type();
|
|
if (attrType === onnx_proto_1.onnx.AttributeProto.AttributeType.GRAPH || attrType === onnx_proto_1.onnx.AttributeProto.AttributeType.GRAPHS) {
|
|
throw new Error('graph attribute is not supported yet');
|
|
}
|
|
const value = this.getValueNoCheck(attr);
|
|
// cast LONG to number
|
|
if (attrType === onnx_proto_1.onnx.AttributeProto.AttributeType.INT && util_1.LongUtil.isLong(value)) {
|
|
return util_1.LongUtil.longToNumber(value);
|
|
}
|
|
// cast LONG[] to number[]
|
|
if (attrType === onnx_proto_1.onnx.AttributeProto.AttributeType.INTS) {
|
|
const arr = value;
|
|
const numberValue = new Array(arr.length);
|
|
for (let i = 0; i < arr.length; i++) {
|
|
const maybeLong = arr[i];
|
|
numberValue[i] = util_1.LongUtil.longToNumber(maybeLong);
|
|
}
|
|
return numberValue;
|
|
}
|
|
// cast onnx.TensorProto to onnxjs.Tensor
|
|
if (attrType === onnx_proto_1.onnx.AttributeProto.AttributeType.TENSOR) {
|
|
return attr instanceof onnx_proto_1.onnx.AttributeProto ? tensor_1.Tensor.fromProto(value) :
|
|
tensor_1.Tensor.fromOrtTensor(value);
|
|
}
|
|
// cast onnx.TensorProto[] to onnxjs.Tensor[]
|
|
if (attrType === onnx_proto_1.onnx.AttributeProto.AttributeType.TENSORS) {
|
|
if (attr instanceof onnx_proto_1.onnx.AttributeProto) {
|
|
const tensorProtos = value;
|
|
return tensorProtos.map(value => tensor_1.Tensor.fromProto(value));
|
|
}
|
|
else if (attr instanceof ortFbs.Attribute) {
|
|
const tensorProtos = value;
|
|
return tensorProtos.map(value => tensor_1.Tensor.fromOrtTensor(value));
|
|
}
|
|
}
|
|
// cast Uint8Array to string
|
|
if (attrType === onnx_proto_1.onnx.AttributeProto.AttributeType.STRING) {
|
|
// string in onnx attribute is of uint8array type, so we need to convert it to string below. While in ort format,
|
|
// string attributes are returned as string, so no conversion is needed.
|
|
if (attr instanceof onnx_proto_1.onnx.AttributeProto) {
|
|
const utf8String = value;
|
|
return (0, util_1.decodeUtf8String)(utf8String);
|
|
}
|
|
}
|
|
// cast Uint8Array[] to string[]
|
|
if (attrType === onnx_proto_1.onnx.AttributeProto.AttributeType.STRINGS) {
|
|
// strings in onnx attribute is returned as uint8array[], so we need to convert it to string[] below. While in ort
|
|
// format strings attributes are returned as string[], so no conversion is needed.
|
|
if (attr instanceof onnx_proto_1.onnx.AttributeProto) {
|
|
const utf8Strings = value;
|
|
return utf8Strings.map(util_1.decodeUtf8String);
|
|
}
|
|
}
|
|
return value;
|
|
}
|
|
static getValueNoCheck(attr) {
|
|
return attr instanceof (onnx_proto_1.onnx.AttributeProto) ? this.getValueNoCheckFromOnnxFormat(attr) :
|
|
this.getValueNoCheckFromOrtFormat(attr);
|
|
}
|
|
static getValueNoCheckFromOnnxFormat(attr) {
|
|
switch (attr.type) {
|
|
case onnx_proto_1.onnx.AttributeProto.AttributeType.FLOAT:
|
|
return attr.f;
|
|
case onnx_proto_1.onnx.AttributeProto.AttributeType.INT:
|
|
return attr.i;
|
|
case onnx_proto_1.onnx.AttributeProto.AttributeType.STRING:
|
|
return attr.s;
|
|
case onnx_proto_1.onnx.AttributeProto.AttributeType.TENSOR:
|
|
return attr.t;
|
|
case onnx_proto_1.onnx.AttributeProto.AttributeType.GRAPH:
|
|
return attr.g;
|
|
case onnx_proto_1.onnx.AttributeProto.AttributeType.FLOATS:
|
|
return attr.floats;
|
|
case onnx_proto_1.onnx.AttributeProto.AttributeType.INTS:
|
|
return attr.ints;
|
|
case onnx_proto_1.onnx.AttributeProto.AttributeType.STRINGS:
|
|
return attr.strings;
|
|
case onnx_proto_1.onnx.AttributeProto.AttributeType.TENSORS:
|
|
return attr.tensors;
|
|
case onnx_proto_1.onnx.AttributeProto.AttributeType.GRAPHS:
|
|
return attr.graphs;
|
|
default:
|
|
throw new Error(`unsupported attribute type: ${onnx_proto_1.onnx.AttributeProto.AttributeType[attr.type]}`);
|
|
}
|
|
}
|
|
static getValueNoCheckFromOrtFormat(attr) {
|
|
switch (attr.type()) {
|
|
case ortFbs.AttributeType.FLOAT:
|
|
return attr.f();
|
|
case ortFbs.AttributeType.INT:
|
|
return attr.i();
|
|
case ortFbs.AttributeType.STRING:
|
|
return attr.s();
|
|
case ortFbs.AttributeType.TENSOR:
|
|
return attr.t();
|
|
case ortFbs.AttributeType.GRAPH:
|
|
return attr.g();
|
|
case ortFbs.AttributeType.FLOATS:
|
|
return attr.floatsArray();
|
|
case ortFbs.AttributeType.INTS: {
|
|
const ints = [];
|
|
for (let i = 0; i < attr.intsLength(); i++) {
|
|
ints.push(attr.ints(i));
|
|
}
|
|
return ints;
|
|
}
|
|
case ortFbs.AttributeType.STRINGS: {
|
|
const strings = [];
|
|
for (let i = 0; i < attr.stringsLength(); i++) {
|
|
strings.push(attr.strings(i));
|
|
}
|
|
return strings;
|
|
}
|
|
case ortFbs.AttributeType.TENSORS: {
|
|
const tensors = [];
|
|
for (let i = 0; i < attr.tensorsLength(); i++) {
|
|
tensors.push(attr.tensors(i));
|
|
}
|
|
return tensors;
|
|
}
|
|
// case ortFbs.AttributeType.GRAPHS:
|
|
// TODO: Subgraph not supported yet.
|
|
// const graphs = [];
|
|
// for (let i = 0; i < attr.graphsLength(); i++) {
|
|
// graphs.push(attr.graphs(i)!);
|
|
// }
|
|
// return graphs;
|
|
default:
|
|
throw new Error(`unsupported attribute type: ${ortFbs.AttributeType[attr.type()]}`);
|
|
}
|
|
}
|
|
}
|
|
exports.Attribute = Attribute;
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./lib/onnxjs/backend.ts":
|
|
/*!*******************************!*\
|
|
!*** ./lib/onnxjs/backend.ts ***!
|
|
\*******************************/
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
// Licensed under the MIT License.
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.resolveBackend = exports.backend = void 0;
|
|
const backend_webgl_1 = __webpack_require__(/*! ./backends/backend-webgl */ "./lib/onnxjs/backends/backend-webgl.ts");
|
|
// caches all initialized backend instances
|
|
const backendsCache = new Map();
|
|
exports.backend = {
|
|
webgl: new backend_webgl_1.WebGLBackend(),
|
|
};
|
|
/**
|
|
* Resolve a reference to the backend. If a hint is specified, the corresponding
|
|
* backend will be used.
|
|
*/
|
|
async function resolveBackend(hint) {
|
|
if (!hint) {
|
|
return resolveBackend(['webgl']);
|
|
}
|
|
else {
|
|
const hints = typeof hint === 'string' ? [hint] : hint;
|
|
for (const backendHint of hints) {
|
|
const cache = backendsCache.get(backendHint);
|
|
if (cache) {
|
|
return cache;
|
|
}
|
|
const backend = await tryLoadBackend(backendHint);
|
|
if (backend) {
|
|
return backend;
|
|
}
|
|
}
|
|
}
|
|
throw new Error('no available backend to use');
|
|
}
|
|
exports.resolveBackend = resolveBackend;
|
|
async function tryLoadBackend(backendHint) {
|
|
const backendObj = exports.backend;
|
|
if (typeof backendObj[backendHint] !== 'undefined' && isBackend(backendObj[backendHint])) {
|
|
const backend = backendObj[backendHint];
|
|
let init = backend.initialize();
|
|
if (typeof init === 'object' && 'then' in init) {
|
|
init = await init;
|
|
}
|
|
if (init) {
|
|
backendsCache.set(backendHint, backend);
|
|
return backend;
|
|
}
|
|
}
|
|
return undefined;
|
|
}
|
|
function isBackend(obj) {
|
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
const o = obj;
|
|
// check if an object is a Backend instance
|
|
if ('initialize' in o && typeof o.initialize === 'function' && // initialize()
|
|
'createSessionHandler' in o && typeof o.createSessionHandler === 'function' && // createSessionHandler()
|
|
'dispose' in o && typeof o.dispose === 'function' // dispose()
|
|
) {
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./lib/onnxjs/backends/backend-webgl.ts":
|
|
/*!**********************************************!*\
|
|
!*** ./lib/onnxjs/backends/backend-webgl.ts ***!
|
|
\**********************************************/
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
// Licensed under the MIT License.
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.WebGLBackend = void 0;
|
|
const onnxruntime_common_1 = __webpack_require__(/*! onnxruntime-common */ "../common/dist/lib/index.js");
|
|
const instrument_1 = __webpack_require__(/*! ../instrument */ "./lib/onnxjs/instrument.ts");
|
|
const session_handler_1 = __webpack_require__(/*! ./webgl/session-handler */ "./lib/onnxjs/backends/webgl/session-handler.ts");
|
|
const webgl_context_factory_1 = __webpack_require__(/*! ./webgl/webgl-context-factory */ "./lib/onnxjs/backends/webgl/webgl-context-factory.ts");
|
|
/**
|
|
* WebGLBackend is the entry point for all WebGL opeartions
|
|
* When it starts it created the WebGLRenderingContext
|
|
* and other main framework components such as Program and Texture Managers
|
|
*/
|
|
class WebGLBackend {
|
|
get contextId() {
|
|
return onnxruntime_common_1.env.webgl.contextId;
|
|
}
|
|
set contextId(value) {
|
|
onnxruntime_common_1.env.webgl.contextId = value;
|
|
}
|
|
get matmulMaxBatchSize() {
|
|
return onnxruntime_common_1.env.webgl.matmulMaxBatchSize;
|
|
}
|
|
set matmulMaxBatchSize(value) {
|
|
onnxruntime_common_1.env.webgl.matmulMaxBatchSize = value;
|
|
}
|
|
get textureCacheMode() {
|
|
return onnxruntime_common_1.env.webgl.textureCacheMode;
|
|
}
|
|
set textureCacheMode(value) {
|
|
onnxruntime_common_1.env.webgl.textureCacheMode = value;
|
|
}
|
|
get pack() {
|
|
return onnxruntime_common_1.env.webgl.pack;
|
|
}
|
|
set pack(value) {
|
|
onnxruntime_common_1.env.webgl.pack = value;
|
|
}
|
|
get async() {
|
|
return onnxruntime_common_1.env.webgl.async;
|
|
}
|
|
set async(value) {
|
|
onnxruntime_common_1.env.webgl.async = value;
|
|
}
|
|
initialize() {
|
|
try {
|
|
this.glContext = (0, webgl_context_factory_1.createWebGLContext)(this.contextId);
|
|
if (typeof this.matmulMaxBatchSize !== 'number') {
|
|
this.matmulMaxBatchSize = 16;
|
|
}
|
|
if (typeof this.textureCacheMode !== 'string') {
|
|
this.textureCacheMode = 'full';
|
|
}
|
|
if (typeof this.pack !== 'boolean') {
|
|
this.pack = false;
|
|
}
|
|
if (typeof this.async !== 'boolean') {
|
|
this.async = false;
|
|
}
|
|
instrument_1.Logger.setWithEnv(onnxruntime_common_1.env);
|
|
instrument_1.Logger.verbose('WebGLBackend', `Created WebGLContext: ${typeof this.glContext} with matmulMaxBatchSize: ${this.matmulMaxBatchSize}; textureCacheMode: ${this.textureCacheMode}; pack: ${this.pack}; async: ${this.async}.`);
|
|
return true;
|
|
}
|
|
catch (e) {
|
|
instrument_1.Logger.warning('WebGLBackend', `Unable to initialize WebGLBackend. ${e}`);
|
|
return false;
|
|
}
|
|
}
|
|
createSessionHandler(context) {
|
|
return new session_handler_1.WebGLSessionHandler(this, context);
|
|
}
|
|
dispose() {
|
|
this.glContext.dispose();
|
|
}
|
|
}
|
|
exports.WebGLBackend = WebGLBackend;
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./lib/onnxjs/backends/webgl/glsl-coordinate-lib.ts":
|
|
/*!**********************************************************!*\
|
|
!*** ./lib/onnxjs/backends/webgl/glsl-coordinate-lib.ts ***!
|
|
\**********************************************************/
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
// Licensed under the MIT License.
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.CoordsGlslLib = void 0;
|
|
const util_1 = __webpack_require__(/*! ../../util */ "./lib/onnxjs/util.ts");
|
|
const glsl_definitions_1 = __webpack_require__(/*! ./glsl-definitions */ "./lib/onnxjs/backends/webgl/glsl-definitions.ts");
|
|
const glsl_source_1 = __webpack_require__(/*! ./glsl-source */ "./lib/onnxjs/backends/webgl/glsl-source.ts");
|
|
const texture_layout_strategy_1 = __webpack_require__(/*! ./texture-layout-strategy */ "./lib/onnxjs/backends/webgl/texture-layout-strategy.ts");
|
|
const utils_1 = __webpack_require__(/*! ./utils */ "./lib/onnxjs/backends/webgl/utils.ts");
|
|
/**
|
|
* GLSL Library responsible for data types and routines for manipulating
|
|
* coordinates and mapping to/from tensor indices
|
|
*/
|
|
class CoordsGlslLib extends glsl_definitions_1.GlslLib {
|
|
constructor(context) {
|
|
super(context);
|
|
}
|
|
getFunctions() {
|
|
return Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({}, this.offsetToCoords()), this.coordsToOffset()), this.toVec()), this.valueFrom()), this.getCommonUtilFuncs()), this.getInputsSamplingSnippets()), this.getOutputSamplingSnippet());
|
|
}
|
|
getCustomTypes() {
|
|
return {};
|
|
}
|
|
/**
|
|
* Produces a function that can map from
|
|
* 2D normalzied coordinates (s,t) to a flat offset
|
|
*/
|
|
offsetToCoords() {
|
|
const funcName = 'offsetToCoords';
|
|
return {
|
|
offsetToCoords: new glsl_definitions_1.GlslLibRoutine(`
|
|
vec2 ${funcName}(int offset, int width, int height) {
|
|
int t = offset / width;
|
|
int s = offset - t*width;
|
|
vec2 coords = (vec2(s,t) + vec2(0.5,0.5)) / vec2(width, height);
|
|
return coords;
|
|
}
|
|
`)
|
|
};
|
|
}
|
|
/**
|
|
* Produces a function that can map from
|
|
* 2D normalzied coordinates (s,t) to a flat offset
|
|
*/
|
|
coordsToOffset() {
|
|
const funcName = 'coordsToOffset';
|
|
return {
|
|
coordsToOffset: new glsl_definitions_1.GlslLibRoutine(`
|
|
int ${funcName}(vec2 coords, int width, int height) {
|
|
float s = coords.s * float(width);
|
|
float t = coords.t * float(height);
|
|
int offset = int(t) * width + int(s);
|
|
return offset;
|
|
}
|
|
`)
|
|
};
|
|
}
|
|
/**
|
|
* Generates code for output sampler.
|
|
*/
|
|
getOutputSamplingSnippet() {
|
|
const outputLayout = this.context.outputTextureLayout;
|
|
if (outputLayout.isPacked) {
|
|
return this.getPackedOutputSamplingSnippet(outputLayout);
|
|
}
|
|
else {
|
|
return this.getUnpackedOutputSamplingSnippet(outputLayout);
|
|
}
|
|
}
|
|
/**
|
|
* Generates code for packed output sampler.
|
|
*/
|
|
getPackedOutputSamplingSnippet(outputLayout) {
|
|
const outShape = outputLayout.unpackedShape;
|
|
const outTexShape = [outputLayout.width, outputLayout.height];
|
|
const result = {};
|
|
const funcName = 'getOutputCoords';
|
|
switch (outShape.length) {
|
|
case 0:
|
|
result[funcName] = this.getOutputScalarCoords();
|
|
break;
|
|
case 1:
|
|
result[funcName] = this.getOutputPacked1DCoords(outShape, outTexShape);
|
|
break;
|
|
case 2:
|
|
result[funcName] = this.getOutputPacked2DCoords(outShape, outTexShape);
|
|
break;
|
|
case 3:
|
|
result[funcName] =
|
|
this.getOutputPacked3DCoords(outShape, outTexShape);
|
|
break;
|
|
default:
|
|
result[funcName] = this.getOutputPackedNDCoords(outShape, outTexShape);
|
|
}
|
|
const glsl = (0, glsl_source_1.getGlsl)(this.context.glContext.version);
|
|
// TODO we need this to properly return a packed vec4 from kernels.
|
|
// Replace all '{glsl.output} = result' with 'setOutput(result)' in all kernels.
|
|
const floatTextureSetRGBASource = `
|
|
void setOutput(vec4 val) {
|
|
${glsl.output} = val;
|
|
}
|
|
`;
|
|
const floatTextureSetRGBAFuncName = 'floatTextureSetRGBA';
|
|
result[floatTextureSetRGBAFuncName] = new glsl_definitions_1.GlslLibRoutine(floatTextureSetRGBASource);
|
|
return result;
|
|
}
|
|
/**
|
|
* Generates code for unpacked output sampler.
|
|
*/
|
|
getUnpackedOutputSamplingSnippet(outputLayout) {
|
|
const outShape = outputLayout.unpackedShape;
|
|
const outTexShape = [outputLayout.width, outputLayout.height];
|
|
const result = {};
|
|
const funcName = 'getOutputCoords';
|
|
switch (outShape.length) {
|
|
case 0:
|
|
result[funcName] = this.getOutputScalarCoords();
|
|
break;
|
|
case 1:
|
|
result[funcName] = this.getOutputUnpacked1DCoords(outShape, outTexShape);
|
|
break;
|
|
case 2:
|
|
result[funcName] =
|
|
this.getOutputUnpacked2DCoords(outShape, outTexShape);
|
|
break;
|
|
case 3:
|
|
result[funcName] =
|
|
this.getOutputUnpacked3DCoords(outShape, outTexShape);
|
|
break;
|
|
case 4:
|
|
result[funcName] = this.getOutputUnpacked4DCoords(outShape, outTexShape);
|
|
break;
|
|
case 5:
|
|
result[funcName] = this.getOutputUnpacked5DCoords(outShape, outTexShape);
|
|
break;
|
|
case 6:
|
|
result[funcName] = this.getOutputUnpacked6DCoords(outShape, outTexShape);
|
|
break;
|
|
default:
|
|
throw new Error(`Unsupported output dimensionality: ${outShape.length}`);
|
|
}
|
|
const glsl = (0, glsl_source_1.getGlsl)(this.context.glContext.version);
|
|
// TODO we need this to properly return a packed vec4 from kernels.
|
|
// Replace all '{glsl.output} = result' with 'setOutput(result)' in all kernels.
|
|
const floatTextureSetRSource = `
|
|
void setOutput(float val) {
|
|
${glsl.output} = vec4(val, 0, 0, 0);
|
|
}
|
|
`;
|
|
const floatTextureSetRFuncName = 'floatTextureSetR';
|
|
result[floatTextureSetRFuncName] = new glsl_definitions_1.GlslLibRoutine(floatTextureSetRSource);
|
|
return result;
|
|
}
|
|
/**
|
|
* Scalar output coordinates.
|
|
*/
|
|
getOutputScalarCoords() {
|
|
return new glsl_definitions_1.GlslLibRoutine(`
|
|
int getOutputCoords() {
|
|
return 0;
|
|
}
|
|
`);
|
|
}
|
|
/**
|
|
* 1D packed output coordinates.
|
|
*/
|
|
getOutputPacked1DCoords(shape, texShape) {
|
|
const packedTexShape = texShape;
|
|
let source = '';
|
|
if (packedTexShape[0] === 1) {
|
|
source = `
|
|
int getOutputCoords() {
|
|
return 2 * int(TexCoords.y * ${packedTexShape[1]}.0);
|
|
}
|
|
`;
|
|
return new glsl_definitions_1.GlslLibRoutine(source);
|
|
}
|
|
if (packedTexShape[1] === 1) {
|
|
source = `
|
|
int getOutputCoords() {
|
|
return 2 * int(TexCoords.x * ${packedTexShape[0]}.0);
|
|
}
|
|
`;
|
|
return new glsl_definitions_1.GlslLibRoutine(source);
|
|
}
|
|
source = `
|
|
int getOutputCoords() {
|
|
ivec2 resTexRC = ivec2(TexCoords.xy *
|
|
vec2(${packedTexShape[0]}, ${packedTexShape[1]}));
|
|
return 2 * (resTexRC.y * ${packedTexShape[0]} + resTexRC.x);
|
|
}
|
|
`;
|
|
return new glsl_definitions_1.GlslLibRoutine(source);
|
|
}
|
|
/**
|
|
* 2D packed output coordinates.
|
|
*/
|
|
getOutputPacked2DCoords(shape, texShape) {
|
|
let source = '';
|
|
if (util_1.ArrayUtil.arraysEqual(shape, texShape)) {
|
|
source = `
|
|
ivec2 getOutputCoords() {
|
|
return 2 * ivec2(TexCoords.xy * vec2(${texShape[0]}, ${texShape[1]}));
|
|
}
|
|
`;
|
|
return new glsl_definitions_1.GlslLibRoutine(source);
|
|
}
|
|
const packedTexShape = texShape;
|
|
// texels needed to accommodate a logical row
|
|
const texelsInLogicalRow = Math.ceil(shape[1] / 2);
|
|
/**
|
|
* getOutputCoords
|
|
*
|
|
* resTexRC: The rows and columns of the texels. If you move over one
|
|
* texel to the right in the packed texture, you are moving over one column
|
|
* (not two).
|
|
*
|
|
* index: The texel index
|
|
*/
|
|
source = `
|
|
ivec2 getOutputCoords() {
|
|
ivec2 resTexRC = ivec2(TexCoords.xy *
|
|
vec2(${packedTexShape[0]}, ${packedTexShape[1]}));
|
|
|
|
int index = resTexRC.y * ${packedTexShape[0]} + resTexRC.x;
|
|
|
|
// reverse r and c order for packed texture
|
|
int r = imod(index, ${texelsInLogicalRow}) * 2;
|
|
int c = 2 * (index / ${texelsInLogicalRow});
|
|
|
|
return ivec2(r, c);
|
|
}
|
|
`;
|
|
return new glsl_definitions_1.GlslLibRoutine(source);
|
|
}
|
|
/**
|
|
* 3D packed output coordinates.
|
|
*/
|
|
getOutputPacked3DCoords(shape, texShape) {
|
|
const packedTexShape = [texShape[0], texShape[1]];
|
|
const texelsInLogicalRow = Math.ceil(shape[2] / 2);
|
|
const texelsInBatch = texelsInLogicalRow * Math.ceil(shape[1] / 2);
|
|
const source = `
|
|
ivec3 getOutputCoords() {
|
|
ivec2 resTexRC = ivec2(TexCoords.xy *
|
|
vec2(${packedTexShape[0]}, ${packedTexShape[1]}));
|
|
int index = resTexRC.y * ${packedTexShape[0]} + resTexRC.x;
|
|
|
|
int b = index / ${texelsInBatch};
|
|
index -= b * ${texelsInBatch};
|
|
|
|
// reverse r and c order for packed texture
|
|
int r = imod(index, ${texelsInLogicalRow}) * 2;
|
|
int c = 2 * (index / ${texelsInLogicalRow});
|
|
|
|
return ivec3(b, r, c);
|
|
}
|
|
`;
|
|
return new glsl_definitions_1.GlslLibRoutine(source);
|
|
}
|
|
/**
|
|
* ND packed output coordinates.
|
|
*/
|
|
getOutputPackedNDCoords(shape, texShape) {
|
|
const packedTexShape = [texShape[0], texShape[1]];
|
|
const texelsInLogicalRow = Math.ceil(shape[shape.length - 1] / 2);
|
|
const texelsInBatch = texelsInLogicalRow * Math.ceil(shape[shape.length - 2] / 2);
|
|
let texelsInBatchN = texelsInBatch;
|
|
let batches = '';
|
|
let coords = 'b, r, c';
|
|
for (let b = 2; b < shape.length - 1; b++) {
|
|
texelsInBatchN *= shape[shape.length - b - 1];
|
|
batches = `
|
|
int b${b} = index / ${texelsInBatchN};
|
|
index -= b${b} * ${texelsInBatchN};
|
|
` + batches;
|
|
coords = `b${b}, ` + coords;
|
|
}
|
|
const source = `
|
|
ivec${shape.length} getOutputCoords() {
|
|
ivec2 resTexRC = ivec2(TexCoords.xy *
|
|
vec2(${packedTexShape[0]}, ${packedTexShape[1]}));
|
|
int index = resTexRC.y * ${packedTexShape[0]} + resTexRC.x;
|
|
|
|
${batches}
|
|
|
|
int b = index / ${texelsInBatch};
|
|
index -= b * ${texelsInBatch};
|
|
|
|
// reverse r and c order for packed texture
|
|
int r = imod(index, ${texelsInLogicalRow}) * 2;
|
|
int c = 2 * (index / ${texelsInLogicalRow});
|
|
|
|
return ivec${shape.length}(${coords});
|
|
}
|
|
`;
|
|
return new glsl_definitions_1.GlslLibRoutine(source);
|
|
}
|
|
/**
|
|
* Unpacked 1D output coordinates.
|
|
*/
|
|
getOutputUnpacked1DCoords(shape, texShape) {
|
|
const source = `
|
|
int getOutputCoords() {
|
|
ivec2 resTexRC = ivec2(TexCoords.xy *
|
|
vec2(${texShape[0]}, ${texShape[1]}));
|
|
return resTexRC.y * ${texShape[0]} + resTexRC.x;
|
|
}
|
|
`;
|
|
return new glsl_definitions_1.GlslLibRoutine(source);
|
|
}
|
|
/**
|
|
* Unpacked 2D output coordinates.
|
|
*/
|
|
getOutputUnpacked2DCoords(shape, texShape) {
|
|
const source = `
|
|
ivec2 getOutputCoords() {
|
|
ivec2 resTexRC = ivec2(TexCoords.xy *
|
|
vec2(${texShape[0]}, ${texShape[1]}));
|
|
int index = resTexRC.y * ${texShape[0]} + resTexRC.x;
|
|
int r = index / ${shape[1]};
|
|
int c = index - r * ${shape[1]};
|
|
return ivec2(r, c);
|
|
}
|
|
`;
|
|
return new glsl_definitions_1.GlslLibRoutine(source);
|
|
}
|
|
/**
|
|
* Unpacked 3D output coordinates.
|
|
*/
|
|
getOutputUnpacked3DCoords(shape, texShape) {
|
|
let source = '';
|
|
const rank = shape.length;
|
|
let strides = null;
|
|
if (rank < 2) {
|
|
strides = [];
|
|
}
|
|
strides = new Array(rank - 1);
|
|
strides[rank - 2] = shape[rank - 1];
|
|
for (let i = rank - 3; i >= 0; --i) {
|
|
strides[i] = strides[i + 1] * shape[i + 1];
|
|
}
|
|
const coordsToCompute = ['r', 'c', 'd'];
|
|
const coordsFromIndexSnippet = strides
|
|
.map((stride, i) => {
|
|
const line1 = `int ${coordsToCompute[i]} = index / ${stride}`;
|
|
const line2 = i === strides.length - 1 ?
|
|
`int ${coordsToCompute[i + 1]} = index - ${coordsToCompute[i]} * ${stride}` :
|
|
`index -= ${coordsToCompute[i]} * ${stride}`;
|
|
return `${line1}; ${line2};`;
|
|
})
|
|
.join('');
|
|
source = `
|
|
ivec3 getOutputCoords() {
|
|
ivec2 resTexRC = ivec2(TexCoords.xy *
|
|
vec2(${texShape[0]}, ${texShape[1]}));
|
|
int index = resTexRC.y * ${texShape[0]} + resTexRC.x;
|
|
${coordsFromIndexSnippet}
|
|
return ivec3(r, c, d);
|
|
}
|
|
`;
|
|
return new glsl_definitions_1.GlslLibRoutine(source);
|
|
}
|
|
/**
|
|
* Unpacked 4D output coordinates.
|
|
*/
|
|
getOutputUnpacked4DCoords(shape, texShape) {
|
|
let source = '';
|
|
const rank = shape.length;
|
|
let strides = null;
|
|
if (rank < 2) {
|
|
strides = [];
|
|
}
|
|
strides = new Array(rank - 1);
|
|
strides[rank - 2] = shape[rank - 1];
|
|
for (let i = rank - 3; i >= 0; --i) {
|
|
strides[i] = strides[i + 1] * shape[i + 1];
|
|
}
|
|
const coordsToCompute = ['r', 'c', 'd', 'd2'];
|
|
const coordsFromIndexSnippet = strides
|
|
.map((stride, i) => {
|
|
const line1 = `int ${coordsToCompute[i]} = index / ${stride}`;
|
|
const line2 = i === strides.length - 1 ?
|
|
`int ${coordsToCompute[i + 1]} = index - ${coordsToCompute[i]} * ${stride}` :
|
|
`index -= ${coordsToCompute[i]} * ${stride}`;
|
|
return `${line1}; ${line2};`;
|
|
})
|
|
.join('');
|
|
source = `
|
|
ivec4 getOutputCoords() {
|
|
ivec2 resTexRC = ivec2(TexCoords.xy *
|
|
vec2(${texShape[0]}, ${texShape[1]}));
|
|
int index = resTexRC.y * ${texShape[0]} + resTexRC.x;
|
|
${coordsFromIndexSnippet}
|
|
return ivec4(r, c, d, d2);
|
|
}
|
|
`;
|
|
return new glsl_definitions_1.GlslLibRoutine(source);
|
|
}
|
|
/**
|
|
* Unpacked 5D output coordinates.
|
|
*/
|
|
getOutputUnpacked5DCoords(shape, texShape) {
|
|
let source = '';
|
|
const rank = shape.length;
|
|
let strides = null;
|
|
if (rank < 2) {
|
|
strides = [];
|
|
}
|
|
strides = new Array(rank - 1);
|
|
strides[rank - 2] = shape[rank - 1];
|
|
for (let i = rank - 3; i >= 0; --i) {
|
|
strides[i] = strides[i + 1] * shape[i + 1];
|
|
}
|
|
const coordsToCompute = ['r', 'c', 'd', 'd2', 'd3'];
|
|
const coordsFromIndexSnippet = strides
|
|
.map((stride, i) => {
|
|
const line1 = `int ${coordsToCompute[i]} = index / ${stride}`;
|
|
const line2 = i === strides.length - 1 ?
|
|
`int ${coordsToCompute[i + 1]} = index - ${coordsToCompute[i]} * ${stride}` :
|
|
`index -= ${coordsToCompute[i]} * ${stride}`;
|
|
return `${line1}; ${line2};`;
|
|
})
|
|
.join('');
|
|
source = `
|
|
ivec5 getOutputCoords() {
|
|
ivec2 resTexRC = ivec2(TexCoords.xy *
|
|
vec2(${texShape[0]}, ${texShape[1]}));
|
|
int index = resTexRC.y * ${texShape[0]} + resTexRC.x;
|
|
${coordsFromIndexSnippet}
|
|
return ivec5(r, c, d, d2, d3);
|
|
}
|
|
`;
|
|
return new glsl_definitions_1.GlslLibRoutine(source);
|
|
}
|
|
/**
|
|
* Unpacked 6D output coordinates.
|
|
*/
|
|
getOutputUnpacked6DCoords(shape, texShape) {
|
|
let source = '';
|
|
const rank = shape.length;
|
|
let strides = null;
|
|
if (rank < 2) {
|
|
strides = [];
|
|
}
|
|
strides = new Array(rank - 1);
|
|
strides[rank - 2] = shape[rank - 1];
|
|
for (let i = rank - 3; i >= 0; --i) {
|
|
strides[i] = strides[i + 1] * shape[i + 1];
|
|
}
|
|
const coordsToCompute = ['r', 'c', 'd', 'd2', 'd3', 'd4'];
|
|
const coordsFromIndexSnippet = strides
|
|
.map((stride, i) => {
|
|
const line1 = `int ${coordsToCompute[i]} = index / ${stride}`;
|
|
const line2 = i === strides.length - 1 ?
|
|
`int ${coordsToCompute[i + 1]} = index - ${coordsToCompute[i]} * ${stride}` :
|
|
`index -= ${coordsToCompute[i]} * ${stride}`;
|
|
return `${line1}; ${line2};`;
|
|
})
|
|
.join('');
|
|
source = `
|
|
ivec6 getOutputCoords() {
|
|
ivec2 resTexRC = ivec2(TexCoords.xy *
|
|
vec2(${texShape[0]}, ${texShape[1]}));
|
|
int index = resTexRC.y * ${texShape[0]} + resTexRC.x;
|
|
${coordsFromIndexSnippet}
|
|
return ivec6(r, c, d, d2, d3, d4);
|
|
}
|
|
`;
|
|
return new glsl_definitions_1.GlslLibRoutine(source);
|
|
}
|
|
/**
|
|
* Generates code for common UV coords computation utility functions.
|
|
*/
|
|
getCommonUtilFuncs() {
|
|
const result = {};
|
|
let funcName = 'uvFromFlat';
|
|
result[funcName] = new glsl_definitions_1.GlslLibRoutine(`
|
|
vec2 uvFromFlat(int texNumR, int texNumC, int index) {
|
|
int texC = index / texNumR;
|
|
int texR = index - texC * texNumR;
|
|
// TODO: swap texR, texC order in following function so row is corresponding to u and column is corresponding to
|
|
// v.
|
|
return (vec2(texR, texC) + halfCR) / vec2(texNumR, texNumC);
|
|
}
|
|
`);
|
|
funcName = 'packedUVfrom1D';
|
|
result[funcName] = new glsl_definitions_1.GlslLibRoutine(`
|
|
vec2 packedUVfrom1D(int texNumR, int texNumC, int index) {
|
|
int texelIndex = index / 2;
|
|
int texR = texelIndex / texNumC;
|
|
int texC = texelIndex - texR * texNumC;
|
|
return (vec2(texC, texR) + halfCR) / vec2(texNumC, texNumR);
|
|
}
|
|
`);
|
|
funcName = 'packedUVfrom2D';
|
|
result[funcName] = new glsl_definitions_1.GlslLibRoutine(`
|
|
vec2 packedUVfrom2D(int texNumR, int texNumC, int texelsInLogicalRow, int row, int col) {
|
|
int texelIndex = (row / 2) * texelsInLogicalRow + (col / 2);
|
|
int texR = texelIndex / texNumC;
|
|
int texC = texelIndex - texR * texNumC;
|
|
return (vec2(texC, texR) + halfCR) / vec2(texNumC, texNumR);
|
|
}
|
|
`);
|
|
funcName = 'packedUVfrom3D';
|
|
result[funcName] = new glsl_definitions_1.GlslLibRoutine(`
|
|
vec2 packedUVfrom3D(int texNumR, int texNumC,
|
|
int texelsInBatch, int texelsInLogicalRow, int b,
|
|
int row, int col) {
|
|
int index = b * texelsInBatch + (row / 2) * texelsInLogicalRow + (col / 2);
|
|
int texR = index / texNumC;
|
|
int texC = index - texR * texNumC;
|
|
return (vec2(texC, texR) + halfCR) / vec2(texNumC, texNumR);
|
|
}
|
|
`);
|
|
funcName = 'sampleTexture';
|
|
const glsl = (0, glsl_source_1.getGlsl)(this.context.glContext.version);
|
|
result[funcName] = new glsl_definitions_1.GlslLibRoutine(`
|
|
float sampleTexture(sampler2D textureSampler, vec2 uv) {
|
|
return ${glsl.texture2D}(textureSampler, uv).r;
|
|
}`);
|
|
return result;
|
|
}
|
|
/**
|
|
* Constructing snippets for inputs
|
|
*/
|
|
getInputsSamplingSnippets() {
|
|
const result = {};
|
|
const outputLayout = this.context.outputTextureLayout;
|
|
this.context.programInfo.inputNames.forEach((samplerName, i) => {
|
|
const inputLayout = this.context.inputTextureLayouts[i];
|
|
const funcName = (0, utils_1.generateShaderFuncNameFromInputSamplerName)(samplerName);
|
|
if (inputLayout.isPacked) {
|
|
result[funcName] = this.getPackedSamplerFromInput(funcName, samplerName, inputLayout);
|
|
}
|
|
else {
|
|
result[funcName] = this.getUnpackedSamplerFromInput(funcName, samplerName, inputLayout);
|
|
}
|
|
const outCoordFuncName = (0, utils_1.generateShaderFuncNameFromInputSamplerNameAtOutCoords)(samplerName);
|
|
if (inputLayout.unpackedShape.length <= outputLayout.unpackedShape.length) {
|
|
if (inputLayout.isPacked) {
|
|
result[outCoordFuncName] =
|
|
this.getPackedSamplerAtOutputCoords(outCoordFuncName, inputLayout, outputLayout, samplerName);
|
|
}
|
|
else {
|
|
result[outCoordFuncName] =
|
|
this.getUnpackedSamplerAtOutputCoords(outCoordFuncName, inputLayout, outputLayout, samplerName);
|
|
}
|
|
}
|
|
});
|
|
return result;
|
|
}
|
|
/**
|
|
* Constructing snippets for output coordinates of samplers
|
|
*/
|
|
getPackedSamplerAtOutputCoords(funcName, inputLayout, outputLayout, name) {
|
|
const inShape = inputLayout.unpackedShape;
|
|
const outShape = outputLayout.unpackedShape;
|
|
const texName = name;
|
|
const texFuncSnippet = (0, utils_1.generateShaderFuncNameFromInputSamplerName)(texName);
|
|
const inRank = inShape.length;
|
|
const outRank = outShape.length;
|
|
const broadcastDims = util_1.BroadcastUtil.getBroadcastDims(inShape, outShape);
|
|
const type = (0, utils_1.getCoordsDataType)(outRank);
|
|
const rankDiff = outRank - inRank;
|
|
let coordsSnippet;
|
|
const fields = (0, utils_1.getGlChannels)();
|
|
if (inRank === 0) {
|
|
coordsSnippet = '';
|
|
}
|
|
else if (outRank < 2 && broadcastDims.length >= 1) {
|
|
coordsSnippet = 'coords = 0;';
|
|
}
|
|
else {
|
|
coordsSnippet = broadcastDims.map(d => `coords.${fields[d + rankDiff]} = 0;`).join('\n');
|
|
}
|
|
let unpackedCoordsSnippet = '';
|
|
if (outRank < 2 && inRank > 0) {
|
|
unpackedCoordsSnippet = 'coords';
|
|
}
|
|
else {
|
|
unpackedCoordsSnippet = inShape.map((s, i) => `coords.${fields[i + rankDiff]}`).join(', ');
|
|
}
|
|
let output = 'return outputValue;';
|
|
const inSize = util_1.ShapeUtil.size(inShape);
|
|
const isInputScalar = inSize === 1;
|
|
const outSize = util_1.ShapeUtil.size(outShape);
|
|
const isOutputScalar = outSize === 1;
|
|
if (inRank === 1 && !isInputScalar && !isOutputScalar) {
|
|
output = `
|
|
return vec4(outputValue.xy, outputValue.xy);
|
|
`;
|
|
}
|
|
else if (isInputScalar && !isOutputScalar) {
|
|
if (outRank === 1) {
|
|
output = `
|
|
return vec4(outputValue.x, outputValue.x, 0., 0.);
|
|
`;
|
|
}
|
|
else {
|
|
output = `
|
|
return vec4(outputValue.x);
|
|
`;
|
|
}
|
|
}
|
|
else if (broadcastDims.length) {
|
|
const rows = inRank - 2;
|
|
const cols = inRank - 1;
|
|
if (broadcastDims.indexOf(rows) > -1 && broadcastDims.indexOf(cols) > -1) {
|
|
output = 'return vec4(outputValue.x);';
|
|
}
|
|
else if (broadcastDims.indexOf(rows) > -1) {
|
|
output = 'return vec4(outputValue.x, outputValue.y, ' +
|
|
'outputValue.x, outputValue.y);';
|
|
}
|
|
else if (broadcastDims.indexOf(cols) > -1) {
|
|
output = 'return vec4(outputValue.xx, outputValue.zz);';
|
|
}
|
|
}
|
|
const swapLastDimsSnippet = `
|
|
int lastDim = coords.${fields[outRank - 1]};
|
|
coords.${fields[outRank - 1]} = coords.${fields[outRank - 2]};
|
|
coords.${fields[outRank - 2]} = lastDim;
|
|
`;
|
|
const source = `
|
|
vec4 ${funcName}() {
|
|
${type} coords = getOutputCoords();
|
|
${swapLastDimsSnippet}
|
|
${coordsSnippet}
|
|
vec4 outputValue = ${texFuncSnippet}(${unpackedCoordsSnippet});
|
|
${output}
|
|
}
|
|
`;
|
|
return new glsl_definitions_1.GlslLibRoutine(source, ['coordinates.getOutputCoords']);
|
|
}
|
|
/**
|
|
* Constructing snippets for unpacked output coordinates of samplers
|
|
*/
|
|
getUnpackedSamplerAtOutputCoords(funcName, inputLayout, outputLayout, name) {
|
|
const outTexShape = [outputLayout.width, outputLayout.height];
|
|
const inTexShape = [inputLayout.width, inputLayout.height];
|
|
const inRank = inputLayout.unpackedShape.length;
|
|
const outRank = outputLayout.unpackedShape.length;
|
|
const inShape = inputLayout.unpackedShape;
|
|
const outShape = outputLayout.unpackedShape;
|
|
const texFuncSnippet = (0, utils_1.generateShaderFuncNameFromInputSamplerName)(name);
|
|
if (inRank === outRank && util_1.ArrayUtil.arraysEqual(inTexShape, outTexShape)) {
|
|
const source = `
|
|
float ${funcName}() {
|
|
return sampleTexture(${name}, TexCoords);
|
|
}
|
|
`;
|
|
return new glsl_definitions_1.GlslLibRoutine(source, ['coordinates.sampleTexture']);
|
|
}
|
|
const type = (0, utils_1.getCoordsDataType)(outRank);
|
|
const broadcastDims = util_1.BroadcastUtil.getBroadcastDims(inShape, outShape);
|
|
const rankDiff = outRank - inRank;
|
|
let coordsSnippet;
|
|
const fields = (0, utils_1.getGlChannels)();
|
|
if (inRank === 0) {
|
|
coordsSnippet = '';
|
|
}
|
|
else if (outRank < 2 && broadcastDims.length >= 1) {
|
|
coordsSnippet = 'coords = 0;';
|
|
}
|
|
else {
|
|
coordsSnippet = broadcastDims.map(d => `coords.${fields[d + rankDiff]} = 0;`).join('\n');
|
|
}
|
|
let unpackedCoordsSnippet = '';
|
|
if (outRank < 2 && inRank > 0) {
|
|
unpackedCoordsSnippet = 'coords';
|
|
}
|
|
else {
|
|
unpackedCoordsSnippet = inputLayout.unpackedShape.map((s, i) => `coords.${fields[i + rankDiff]}`).join(', ');
|
|
}
|
|
const source = `
|
|
float ${funcName}() {
|
|
${type} coords = getOutputCoords();
|
|
${coordsSnippet}
|
|
return ${texFuncSnippet}(${unpackedCoordsSnippet});
|
|
}
|
|
`;
|
|
return new glsl_definitions_1.GlslLibRoutine(source, ['coordinates.getOutputCoords']);
|
|
}
|
|
/**
|
|
* Constructing snippets for packed operations.
|
|
*/
|
|
getPackedSamplerFromInput(funcName, name, inputLayout) {
|
|
switch (inputLayout.unpackedShape.length) {
|
|
case 0:
|
|
return this.getPackedSamplerScalar(funcName, name);
|
|
case 1:
|
|
return this.getPackedSampler1D(funcName, name, inputLayout);
|
|
case 2:
|
|
return this.getPackedSampler2D(funcName, name, inputLayout);
|
|
case 3:
|
|
return this.getPackedSampler3D(funcName, name, inputLayout);
|
|
default:
|
|
return this.getPackedSamplerND(funcName, name, inputLayout);
|
|
}
|
|
}
|
|
/**
|
|
* Constructing snippets for unpacked operations.
|
|
*/
|
|
getUnpackedSamplerFromInput(funcName, name, inputLayout) {
|
|
const shape = inputLayout.unpackedShape;
|
|
switch (shape.length) {
|
|
case 0:
|
|
return this.getUnpackedSamplerScalar(funcName, name, inputLayout);
|
|
case 1:
|
|
return this.getUnpackedSampler1D(funcName, name, inputLayout);
|
|
case 2:
|
|
return this.getUnpackedSampler2D(funcName, name, inputLayout);
|
|
case 3:
|
|
return this.getUnpackedSampler3D(funcName, name, inputLayout);
|
|
case 4:
|
|
return this.getUnpackedSampler4D(funcName, name, inputLayout);
|
|
case 5:
|
|
return this.getUnpackedSampler5D(funcName, name, inputLayout);
|
|
case 6:
|
|
return this.getUnpackedSampler6D(funcName, name, inputLayout);
|
|
default:
|
|
// TODO support more dimensionalities
|
|
throw new Error(`Unsupported dimension ${shape.length}-D`);
|
|
}
|
|
}
|
|
/**
|
|
* Packed scalar snippet.
|
|
*/
|
|
getPackedSamplerScalar(funcName, name) {
|
|
const glsl = (0, glsl_source_1.getGlsl)(this.context.glContext.version);
|
|
const source = `
|
|
vec4 ${funcName}() {
|
|
return ${glsl.texture2D}(${name}, halfCR);
|
|
}
|
|
`;
|
|
return new glsl_definitions_1.GlslLibRoutine(source);
|
|
}
|
|
/**
|
|
* Packed 1D snippet.
|
|
*/
|
|
getPackedSampler1D(funcName, name, inputLayout) {
|
|
const texShape = [inputLayout.width, inputLayout.height];
|
|
const packedTexShape = [texShape[1], texShape[0]];
|
|
const glsl = (0, glsl_source_1.getGlsl)(this.context.glContext.version);
|
|
const packedSampler = `vec4 ${funcName}(int index) {
|
|
vec2 uv = packedUVfrom1D(
|
|
${packedTexShape[0]}, ${packedTexShape[1]}, index);
|
|
return ${glsl.texture2D}(${name}, uv);
|
|
}`;
|
|
const source = packedSampler;
|
|
return new glsl_definitions_1.GlslLibRoutine(source, ['coordinates.packedUVfrom1D']);
|
|
}
|
|
/**
|
|
* Packed 2D snippet.
|
|
*/
|
|
getPackedSampler2D(funcName, name, inputLayout) {
|
|
const shape = inputLayout.unpackedShape;
|
|
const texShape = [inputLayout.width, inputLayout.height];
|
|
const glsl = (0, glsl_source_1.getGlsl)(this.context.glContext.version);
|
|
const texNumR = texShape[0];
|
|
const texNumC = texShape[1];
|
|
if (texShape != null && util_1.ArrayUtil.arraysEqual(shape, texShape)) {
|
|
const packedSampler = `vec4 ${funcName}(int row, int col) {
|
|
vec2 uv = (vec2(col, row) + halfCR) / vec2(${texNumC}.0, ${texNumR}.0);
|
|
return ${glsl.texture2D}(${name}, uv);
|
|
}`;
|
|
return new glsl_definitions_1.GlslLibRoutine(packedSampler);
|
|
}
|
|
const packedTexShape = texShape;
|
|
const valuesPerRow = Math.ceil(shape[1] / 2);
|
|
const packedSampler = `vec4 ${funcName}(int row, int col) {
|
|
vec2 uv = packedUVfrom2D(${packedTexShape[1]}, ${packedTexShape[0]}, ${valuesPerRow}, row, col);
|
|
return ${glsl.texture2D}(${name}, uv);
|
|
}`;
|
|
const source = packedSampler;
|
|
return new glsl_definitions_1.GlslLibRoutine(source, ['coordinates.packedUVfrom2D']);
|
|
}
|
|
/**
|
|
* Packed 3D snippet.
|
|
*/
|
|
getPackedSampler3D(funcName, name, inputLayout) {
|
|
const shape = inputLayout.unpackedShape;
|
|
const texShape = [inputLayout.width, inputLayout.height];
|
|
const packedTexShape = [texShape[0], texShape[1]];
|
|
const glsl = (0, glsl_source_1.getGlsl)(this.context.glContext.version);
|
|
if (shape[0] === 1) {
|
|
const squeezedShape = shape.slice(1);
|
|
const keptDims = [1, 2];
|
|
const newInputShape = (0, utils_1.squeezeInputShape)(shape, squeezedShape);
|
|
const params = ['b', 'row', 'col'];
|
|
// Deep copy of input texture layout.
|
|
const newInputLayout = JSON.parse(JSON.stringify(inputLayout));
|
|
newInputLayout.unpackedShape = newInputShape;
|
|
const samplerRoutine = this.getPackedSamplerFromInput(funcName, name, newInputLayout);
|
|
const packedSampler = `${samplerRoutine.routineBody}
|
|
vec4 ${funcName}(int b, int row, int col) {
|
|
return ${funcName}(${(0, utils_1.getSqueezedParams)(params, keptDims)});
|
|
} `;
|
|
const source = packedSampler;
|
|
return new glsl_definitions_1.GlslLibRoutine(source, samplerRoutine.dependencies);
|
|
}
|
|
const texNumR = packedTexShape[0];
|
|
const texNumC = packedTexShape[1];
|
|
const valuesPerRow = Math.ceil(shape[2] / 2);
|
|
const texelsInBatch = valuesPerRow * Math.ceil(shape[1] / 2);
|
|
const packedSampler = `vec4 ${funcName}(int b, int row, int col) {
|
|
vec2 uv = packedUVfrom3D(
|
|
${texNumC}, ${texNumR}, ${texelsInBatch}, ${valuesPerRow}, b, row, col);
|
|
return ${glsl.texture2D}(${name}, uv);}`;
|
|
const source = packedSampler;
|
|
return new glsl_definitions_1.GlslLibRoutine(source, ['coordinates.packedUVfrom3D']);
|
|
}
|
|
/*
|
|
* Packed ND snippet.
|
|
*/
|
|
getPackedSamplerND(funcName, name, inputLayout) {
|
|
const shape = inputLayout.unpackedShape;
|
|
const rank = shape.length;
|
|
const texShape = [inputLayout.width, inputLayout.height];
|
|
const glsl = (0, glsl_source_1.getGlsl)(this.context.glContext.version);
|
|
const packedTexShape = [texShape[0], texShape[1]];
|
|
const texNumR = packedTexShape[1];
|
|
const texNumC = packedTexShape[0];
|
|
const valuesPerRow = Math.ceil(shape[rank - 1] / 2);
|
|
let texelsInBatch = valuesPerRow * Math.ceil(shape[rank - 2] / 2);
|
|
let params = 'int b, int row, int col';
|
|
let index = `b * ${texelsInBatch} + (row / 2) * ${valuesPerRow} + (col / 2)`;
|
|
for (let b = 2; b < rank - 1; b++) {
|
|
params = `int b${b}, ` + params;
|
|
texelsInBatch *= shape[rank - b - 1];
|
|
index = `b${b} * ${texelsInBatch} + ` + index;
|
|
}
|
|
const packedSampler = `vec4 ${funcName}(${params}) {
|
|
int index = ${index};
|
|
int texR = index / ${texNumC};
|
|
int texC = index - texR * ${texNumC};
|
|
vec2 uv = (vec2(texC, texR) + halfCR) / vec2(${texNumC}, ${texNumR});
|
|
return ${glsl.texture2D}(${name}, uv);
|
|
}`;
|
|
const source = packedSampler;
|
|
return new glsl_definitions_1.GlslLibRoutine(source);
|
|
}
|
|
/**
|
|
* Unpacked scalar snippet.
|
|
*/
|
|
getUnpackedSamplerScalar(funcName, name, inputLayout) {
|
|
const [texNumR, texNumC] = [inputLayout.width, inputLayout.height];
|
|
if (texNumR === 1 && texNumC === 1) {
|
|
const source = `
|
|
float ${funcName}() {
|
|
return sampleTexture(${name}, halfCR);
|
|
}
|
|
`;
|
|
return new glsl_definitions_1.GlslLibRoutine(source, ['coordinates.sampleTexture']);
|
|
}
|
|
const source = `
|
|
float ${funcName}() {
|
|
int offset_${name} = coordsToOffset(TexCoords, ${texNumR}, ${texNumC});
|
|
vec2 uv = uvFromFlat(${texNumR}, ${texNumC}, offset_${name});
|
|
return sampleTexture(${name}, uv);
|
|
}
|
|
`;
|
|
return new glsl_definitions_1.GlslLibRoutine(source, ['coordinates.uvFromFlat', 'coordinates.sampleTexture', 'coordinates.coordsToOffset']);
|
|
}
|
|
/**
|
|
* Unpacked 1D snippet.
|
|
*/
|
|
getUnpackedSampler1D(funcName, name, inputLayout) {
|
|
const tNumR = inputLayout.width;
|
|
const tNumC = inputLayout.height;
|
|
if (tNumC === 1 && tNumR === 1) {
|
|
const source = `
|
|
float ${funcName}(int index) {
|
|
return sampleTexture(${name}, halfCR);
|
|
}
|
|
`;
|
|
return new glsl_definitions_1.GlslLibRoutine(source, ['coordinates.sampleTexture']);
|
|
}
|
|
if (tNumC === 1) {
|
|
const source = `
|
|
float ${funcName}(int index) {
|
|
vec2 uv = vec2((float(index) + 0.5) / ${tNumR}.0, 0.5);
|
|
return sampleTexture(${name}, uv);
|
|
}
|
|
`;
|
|
return new glsl_definitions_1.GlslLibRoutine(source, ['coordinates.sampleTexture']);
|
|
}
|
|
if (tNumR === 1) {
|
|
const source = `
|
|
float ${funcName}(int index) {
|
|
vec2 uv = vec2(0.5, (float(index) + 0.5) / ${tNumC}.0);
|
|
return sampleTexture(${name}, uv);
|
|
}
|
|
`;
|
|
return new glsl_definitions_1.GlslLibRoutine(source, ['coordinates.sampleTexture']);
|
|
}
|
|
const source = `
|
|
float ${funcName}(int index) {
|
|
vec2 uv = uvFromFlat(${tNumR}, ${tNumC}, index);
|
|
return sampleTexture(${name}, uv);
|
|
}
|
|
`;
|
|
return new glsl_definitions_1.GlslLibRoutine(source, ['coordinates.uvFromFlat', 'coordinates.sampleTexture']);
|
|
}
|
|
/**
|
|
* Unpacked 2D snippet.
|
|
*/
|
|
getUnpackedSampler2D(funcName, name, inputLayout) {
|
|
const shape = inputLayout.unpackedShape;
|
|
// TODO: modify row/col order for other dimensions.
|
|
const texShape = [inputLayout.height, inputLayout.width];
|
|
if (texShape != null && util_1.ArrayUtil.arraysEqual(shape, texShape)) {
|
|
const texNumR = texShape[1];
|
|
const texNumC = texShape[0];
|
|
const source = `
|
|
float ${funcName}(int row, int col) {
|
|
vec2 uv = (vec2(row, col) + halfCR) / vec2(${texNumR}.0, ${texNumC}.0);
|
|
return sampleTexture(${name}, uv);
|
|
}
|
|
`;
|
|
return new glsl_definitions_1.GlslLibRoutine(source, ['coordinates.sampleTexture']);
|
|
}
|
|
const { newShape, keptDims } = (0, texture_layout_strategy_1.squeezeShape)(shape);
|
|
const squeezedShape = newShape;
|
|
if (squeezedShape.length < shape.length) {
|
|
const newInputShape = (0, utils_1.squeezeInputShape)(shape, squeezedShape);
|
|
// Deep copy of input texture layout.
|
|
const newInputLayout = JSON.parse(JSON.stringify(inputLayout));
|
|
newInputLayout.unpackedShape = newInputShape;
|
|
const params = ['col', 'row'];
|
|
const source = `
|
|
${this.getUnpackedSamplerFromInput(funcName, name, newInputLayout).routineBody}
|
|
float ${funcName}(int row, int col) {
|
|
return ${funcName}(${(0, utils_1.getSqueezedParams)(params, keptDims)});
|
|
}
|
|
`;
|
|
return new glsl_definitions_1.GlslLibRoutine(source, ['coordinates.sampleTexture']);
|
|
}
|
|
const texNumR = texShape[1];
|
|
const texNumC = texShape[0];
|
|
if (texNumC === 1) {
|
|
const source = `
|
|
float ${funcName}(int row, int col) {
|
|
int offset_${name} = coordsToOffset(TexCoords, ${texNumR}, ${texNumC});
|
|
float index = dot(vec3(row, col, offset_${name}), vec3(${shape[1]}, 1, 1));
|
|
vec2 uv = vec2(0.5, (index + 0.5) / ${texNumR}.0);
|
|
return sampleTexture(${name}, uv);
|
|
}
|
|
`;
|
|
return new glsl_definitions_1.GlslLibRoutine(source, ['coordinates.sampleTexture', 'coordinates.coordsToOffset']);
|
|
}
|
|
if (texNumR === 1) {
|
|
const source = `
|
|
float ${funcName}(int row, int col) {
|
|
int offset_${name} = coordsToOffset(TexCoords, ${texNumR}, ${texNumC});
|
|
float index = dot(vec3(row, col, offset_${name}), vec3(${shape[1]}, 1, 1));
|
|
vec2 uv = vec2((index + 0.5) / ${texNumC}.0, 0.5);
|
|
return sampleTexture(${name}, uv);
|
|
}
|
|
`;
|
|
return new glsl_definitions_1.GlslLibRoutine(source, ['coordinates.sampleTexture', 'coordinates.coordsToOffset']);
|
|
}
|
|
const source = `
|
|
float ${funcName}(int row, int col) {
|
|
int index = col * ${shape[1]} + row;
|
|
vec2 uv = uvFromFlat(${texNumR}, ${texNumC}, index);
|
|
return sampleTexture(${name}, uv);
|
|
}
|
|
`;
|
|
return new glsl_definitions_1.GlslLibRoutine(source, ['coordinates.uvFromFlat', 'coordinates.sampleTexture', 'coordinates.coordsToOffset']);
|
|
}
|
|
/**
|
|
* Unpacked 3D snippet.
|
|
*/
|
|
getUnpackedSampler3D(funcName, name, inputLayout) {
|
|
const shape = inputLayout.unpackedShape;
|
|
const stride0 = shape[1] * shape[2];
|
|
const stride1 = shape[2];
|
|
const { newShape, keptDims } = (0, texture_layout_strategy_1.squeezeShape)(shape);
|
|
const squeezedShape = newShape;
|
|
if (squeezedShape.length < shape.length) {
|
|
const newInputShape = (0, utils_1.squeezeInputShape)(shape, squeezedShape);
|
|
const params = ['batch', 'col', 'row'];
|
|
// Deep copy of input texture layout.
|
|
const newInputLayout = JSON.parse(JSON.stringify(inputLayout));
|
|
newInputLayout.unpackedShape = newInputShape;
|
|
const routine = this.getUnpackedSamplerFromInput(funcName, name, newInputLayout);
|
|
// TODO: revisit the logic here to make it simpler
|
|
const revDims = keptDims.reverse();
|
|
const source = `
|
|
${routine.routineBody}
|
|
float ${funcName}(int batch, int row, int col) {
|
|
return ${funcName}(${(0, utils_1.getSqueezedParams)(params, revDims)});
|
|
}
|
|
`;
|
|
return new glsl_definitions_1.GlslLibRoutine(source, routine.dependencies);
|
|
}
|
|
const texNumR = inputLayout.width;
|
|
const texNumC = inputLayout.height;
|
|
const source = `
|
|
float ${funcName}(int depth, int row, int col) {
|
|
// Explicitly use integer operations as dot() only works on floats.
|
|
int index = depth * ${stride0} + col * ${stride1} + row;
|
|
vec2 uv = uvFromFlat(${texNumR}, ${texNumC}, index);
|
|
return sampleTexture(${name}, uv);
|
|
}
|
|
`;
|
|
return new glsl_definitions_1.GlslLibRoutine(source, ['coordinates.uvFromFlat', 'coordinates.sampleTexture', 'coordinates.coordsToOffset']);
|
|
}
|
|
/**
|
|
* Unpacked 4D snippet.
|
|
*/
|
|
getUnpackedSampler4D(funcName, name, inputLayout) {
|
|
const shape = inputLayout.unpackedShape;
|
|
const stride2 = shape[3];
|
|
const stride1 = shape[2] * stride2;
|
|
const stride0 = shape[1] * stride1;
|
|
//
|
|
// TODO: re-enable this shortcut once the index calculation bug is fixed.
|
|
//
|
|
// const {newShape, keptDims} = squeezeShape(shape as number[]);
|
|
// if (newShape.length < shape.length) {
|
|
// const newInputShape = squeezeInputShape(shape, newShape);
|
|
// const params = ['row', 'col', 'depth', 'depth2'];
|
|
// // Deep copy of input texture layout.
|
|
// const newInputLayout: TextureLayout = JSON.parse(JSON.stringify(inputLayout));
|
|
// newInputLayout.unpackedShape = newInputShape;
|
|
// const source = `
|
|
// ${this.getUnpackedSamplerFromInput(funcName, name, newInputLayout).routineBody}
|
|
// float ${funcName}(int row, int col, int depth, int depth2) {
|
|
// return ${funcName}(${getSqueezedParams(params, keptDims)});
|
|
// }
|
|
// `;
|
|
// return new GlslLibRoutine(
|
|
// source, ['coordinates.uvFromFlat', 'coordinates.sampleTexture', 'coordinates.coordsToOffset']);
|
|
// }
|
|
const texNumR = inputLayout.width;
|
|
const texNumC = inputLayout.height;
|
|
const source = `
|
|
float ${funcName}(int row, int col, int depth, int depth2) {
|
|
int index = row * ${stride0} + col * ${stride1} +
|
|
depth2 * ${stride2} + depth;
|
|
vec2 uv = uvFromFlat(${texNumR}, ${texNumC}, index);
|
|
return sampleTexture(${name}, uv);
|
|
}
|
|
`;
|
|
return new glsl_definitions_1.GlslLibRoutine(source, ['coordinates.uvFromFlat', 'coordinates.sampleTexture']);
|
|
}
|
|
/**
|
|
* Unpacked 5D snippet.
|
|
*/
|
|
getUnpackedSampler5D(funcName, name, inputLayout) {
|
|
const shape = inputLayout.unpackedShape;
|
|
const stride3 = shape[4];
|
|
const stride2 = shape[3] * stride3;
|
|
const stride1 = shape[2] * stride2;
|
|
const stride0 = shape[1] * stride1;
|
|
const { newShape, keptDims } = (0, texture_layout_strategy_1.squeezeShape)(shape);
|
|
if (newShape.length < shape.length) {
|
|
const newInputShape = (0, utils_1.squeezeInputShape)(shape, newShape);
|
|
const params = ['row', 'col', 'depth', 'depth2', 'depth3'];
|
|
// Deep copy of input texture layout.
|
|
const newInputLayout = JSON.parse(JSON.stringify(inputLayout));
|
|
newInputLayout.unpackedShape = newInputShape;
|
|
const source = `
|
|
${this.getUnpackedSamplerFromInput(funcName, name, newInputLayout).routineBody}
|
|
float ${funcName}(int row, int col, int depth, int depth2, int depth3) {
|
|
return ${funcName}(${(0, utils_1.getSqueezedParams)(params, keptDims)});
|
|
}
|
|
`;
|
|
return new glsl_definitions_1.GlslLibRoutine(source, ['coordinates.sampleTexture', 'coordinates.uvFromFlat']);
|
|
}
|
|
const texNumR = inputLayout.width;
|
|
const texNumC = inputLayout.height;
|
|
const source = `
|
|
float ${funcName}(int row, int col, int depth, int depth2, int depth3) {
|
|
int index = row * ${stride0} + col * ${stride1} + depth * ${stride2} +
|
|
depth3 * ${stride3} + depth2;
|
|
vec2 uv = uvFromFlat(${texNumR}, ${texNumC}, index);
|
|
return sampleTexture(${name}, uv);
|
|
}
|
|
`;
|
|
return new glsl_definitions_1.GlslLibRoutine(source, ['coordinates.sampleTexture', 'coordinates.uvFromFlat']);
|
|
}
|
|
/**
|
|
* Unpacked 6D snippet.
|
|
*/
|
|
getUnpackedSampler6D(funcName, name, inputLayout) {
|
|
const shape = inputLayout.unpackedShape;
|
|
const stride4 = shape[5];
|
|
const stride3 = shape[4] * stride4;
|
|
const stride2 = shape[3] * stride3;
|
|
const stride1 = shape[2] * stride2;
|
|
const stride0 = shape[1] * stride1;
|
|
const { newShape, keptDims } = (0, texture_layout_strategy_1.squeezeShape)(shape);
|
|
if (newShape.length < shape.length) {
|
|
const newInputShape = (0, utils_1.squeezeInputShape)(shape, newShape);
|
|
const params = ['row', 'col', 'depth', 'depth2', 'depth3', 'depth4'];
|
|
// Deep copy of input texture layout.
|
|
const newInputLayout = JSON.parse(JSON.stringify(inputLayout));
|
|
newInputLayout.unpackedShape = newInputShape;
|
|
const source = `
|
|
${this.getUnpackedSamplerFromInput(funcName, name, newInputLayout).routineBody}
|
|
float ${funcName}(int row, int col, int depth,
|
|
int depth2, int depth3, int depth4) {
|
|
return ${funcName}(${(0, utils_1.getSqueezedParams)(params, keptDims)});
|
|
}
|
|
`;
|
|
return new glsl_definitions_1.GlslLibRoutine(source, ['coordinates.sampleTexture', 'coordinates.uvFromFlat']);
|
|
}
|
|
const texNumR = inputLayout.width;
|
|
const texNumC = inputLayout.height;
|
|
const source = `
|
|
float ${funcName}(int row, int col, int depth,
|
|
int depth2, int depth3, int depth4) {
|
|
int index = row * ${stride0} + col * ${stride1} + depth * ${stride2} +
|
|
depth2 * ${stride3} + depth3 * ${stride4} + depth4;
|
|
vec2 uv = uvFromFlat(${texNumR}, ${texNumC}, index);
|
|
return sampleTexture(${name}, uv);
|
|
}
|
|
`;
|
|
return new glsl_definitions_1.GlslLibRoutine(source, ['coordinates.uvFromFlat', 'coordinates.sampleTexture', 'coordinates.coordsToOffset']);
|
|
}
|
|
/**
|
|
* This is the main function to map from the given texture coordiantes (s,t)
|
|
* to logical indices for the output
|
|
* There will only be one single variation of this
|
|
* Also see coordsToOffset and offsetToIndices for input-specific versions
|
|
*/
|
|
toVec() {
|
|
const output = this.context.outputTextureLayout;
|
|
const rank = output.shape.length;
|
|
const strides = output.strides;
|
|
const xScale = output.width;
|
|
const yScale = output.height;
|
|
const stridesBlock = [];
|
|
for (let i = 0; i < rank - 1; ++i) {
|
|
stridesBlock.push(`
|
|
c[${i}] = offset / ${strides[i]};`);
|
|
stridesBlock.push(`
|
|
offset -= c[${i}] * ${strides[i]};`);
|
|
}
|
|
stridesBlock.push(`
|
|
c[${rank - 1}] = offset;`);
|
|
const body = `
|
|
void toVec(vec2 texCoords, out int c[${rank}]) {
|
|
int offset = coordsToOffset(texCoords, ${xScale}, ${yScale});
|
|
${stridesBlock.join('')}
|
|
}
|
|
void toVec(int offset, out int c[${rank}]) {
|
|
${stridesBlock.join('')}
|
|
}
|
|
`;
|
|
return { toVec: new glsl_definitions_1.GlslLibRoutine(body, ['coordinates.coordsToOffset']) };
|
|
}
|
|
/**
|
|
* These are value getter functions generated for each input
|
|
* Each function is hardwired to the name and dimensions of the input
|
|
* An '_T' variation is also produced which accesses values as if the
|
|
* input was transposed
|
|
*/
|
|
valueFrom() {
|
|
const result = {};
|
|
this.context.programInfo.inputNames.forEach((name, i) => {
|
|
const layout = this.context.inputTextureLayouts[i];
|
|
const shape = layout.unpackedShape.length > 0 ? layout.unpackedShape : layout.shape;
|
|
const rank = shape.length;
|
|
let funcName = `_${name}`;
|
|
result[funcName] = new glsl_definitions_1.GlslLibRoutine(this.getValueFromSingle(name, rank, layout.width, layout.height, false), [`shapeUtils.indicesToOffset${funcName}`, 'coordinates.offsetToCoords', 'fragcolor.getColorAsFloat']);
|
|
funcName = funcName + '_T';
|
|
result[funcName] = new glsl_definitions_1.GlslLibRoutine(this.getValueFromSingle(name, rank, layout.width, layout.height, true), [`shapeUtils.indicesToOffset${funcName}`, 'coordinates.offsetToCoords', 'fragcolor.getColorAsFloat']);
|
|
});
|
|
return result;
|
|
}
|
|
/**
|
|
* Produces one value getter function for the name and rank given
|
|
* If a transpose is set proper offsetToCoords mapping will be used
|
|
* @param name name of the function
|
|
* @param rank rank of the input
|
|
* @param transpose whether or not should generate a transpose variation
|
|
*/
|
|
getValueFromSingle(varName, rank, width, height, transpose) {
|
|
let name = `_${varName}`;
|
|
if (transpose) {
|
|
name = name + '_T';
|
|
}
|
|
const glsl = (0, glsl_source_1.getGlsl)(this.context.glContext.version);
|
|
return `
|
|
float ${name}(int m[${rank}]) {
|
|
int offset = indicesToOffset${name}(m);
|
|
vec2 coords = offsetToCoords(offset, ${width}, ${height});
|
|
float value = getColorAsFloat(${glsl.texture2D}(${varName}, coords));
|
|
return value;
|
|
}
|
|
`;
|
|
}
|
|
/**
|
|
* Produces a packed value getter function for the name and rank given
|
|
* If a transpose is set proper offsetToCoords mapping will be used
|
|
* @param name name of the function
|
|
* @param rank rank of the input
|
|
* @param transpose whether or not should generate a transpose variation
|
|
*/
|
|
getPackedValueFrom(varName, rank, width, height, transpose) {
|
|
let name = `_${varName}_Pack`;
|
|
if (transpose) {
|
|
name = name + '_T';
|
|
}
|
|
const glsl = (0, glsl_source_1.getGlsl)(this.context.glContext.version);
|
|
return `
|
|
vec4 ${name}(int m[${rank}]) {
|
|
int offset = indicesToOffset_${varName}(m);
|
|
vec2 coords = offsetToCoords(offset, ${width}, ${height});
|
|
return ${glsl.texture2D}(${varName}, coords);
|
|
}
|
|
`;
|
|
}
|
|
}
|
|
exports.CoordsGlslLib = CoordsGlslLib;
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./lib/onnxjs/backends/webgl/glsl-definitions.ts":
|
|
/*!*******************************************************!*\
|
|
!*** ./lib/onnxjs/backends/webgl/glsl-definitions.ts ***!
|
|
\*******************************************************/
|
|
/***/ ((__unused_webpack_module, exports) => {
|
|
|
|
"use strict";
|
|
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
// Licensed under the MIT License.
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.TopologicalSortGlslRoutines = exports.GlslLibRoutineNode = exports.GlslLibRoutine = exports.GlslLib = exports.GlslContext = exports.FunctionType = void 0;
|
|
/* eslint-disable @typescript-eslint/naming-convention */
|
|
var FunctionType;
|
|
(function (FunctionType) {
|
|
FunctionType[FunctionType["ValueBased"] = 0] = "ValueBased";
|
|
FunctionType[FunctionType["Positional"] = 1] = "Positional";
|
|
})(FunctionType = exports.FunctionType || (exports.FunctionType = {}));
|
|
class GlslContext {
|
|
constructor(glContext, programInfo, inputTextureLayouts, outputTextureLayout) {
|
|
this.glContext = glContext;
|
|
this.programInfo = programInfo;
|
|
this.inputTextureLayouts = inputTextureLayouts;
|
|
this.outputTextureLayout = outputTextureLayout;
|
|
}
|
|
}
|
|
exports.GlslContext = GlslContext;
|
|
class GlslLib {
|
|
constructor(context) {
|
|
this.context = context;
|
|
}
|
|
}
|
|
exports.GlslLib = GlslLib;
|
|
// abstraction to represent a GLSL library routine and it's dependencies
|
|
class GlslLibRoutine {
|
|
constructor(routineBody, dependencies) {
|
|
this.routineBody = routineBody;
|
|
this.dependencies = dependencies;
|
|
}
|
|
}
|
|
exports.GlslLibRoutine = GlslLibRoutine;
|
|
// abstraction to represent a GLSL library routine and it's dependencies AS GRAPH Nodes
|
|
// this level of abstraction is used to topologically sort routines before fragment shade inclusion
|
|
class GlslLibRoutineNode {
|
|
constructor(name, routineBody, dependencies) {
|
|
this.name = name;
|
|
if (dependencies) {
|
|
this.dependencies = dependencies;
|
|
}
|
|
else {
|
|
this.dependencies = [];
|
|
}
|
|
if (routineBody) {
|
|
this.routineBody = routineBody;
|
|
}
|
|
}
|
|
addDependency(node) {
|
|
if (node) {
|
|
this.dependencies.push(node);
|
|
}
|
|
}
|
|
}
|
|
exports.GlslLibRoutineNode = GlslLibRoutineNode;
|
|
// topologically sort GLSL library routines (graph nodes abstraction) before shader script inclusion
|
|
class TopologicalSortGlslRoutines {
|
|
static returnOrderedNodes(nodes) {
|
|
if (!nodes || nodes.length === 0) {
|
|
return [];
|
|
}
|
|
if (nodes.length === 1) {
|
|
return nodes;
|
|
}
|
|
const cycleCheck = new Set();
|
|
const alreadyTraversed = new Set();
|
|
const result = new Array();
|
|
this.createOrderedNodes(nodes, cycleCheck, alreadyTraversed, result);
|
|
return result;
|
|
}
|
|
static createOrderedNodes(graphNodes, cycleCheck, alreadyTraversed, result) {
|
|
for (let i = 0; i < graphNodes.length; ++i) {
|
|
this.dfsTraverse(graphNodes[i], cycleCheck, alreadyTraversed, result);
|
|
}
|
|
}
|
|
static dfsTraverse(root, cycleCheck, alreadyTraversed, result) {
|
|
// if this root has already been traversed return
|
|
if (!root || alreadyTraversed.has(root.name)) {
|
|
return;
|
|
}
|
|
// cyclic dependency has been detected
|
|
if (cycleCheck.has(root.name)) {
|
|
throw new Error('Cyclic dependency detected. Can\'t topologically sort routines needed for shader.');
|
|
}
|
|
// hold this node to detect cycles if any
|
|
cycleCheck.add(root.name);
|
|
// traverse children in a dfs fashion
|
|
const dependencies = root.dependencies;
|
|
if (dependencies && dependencies.length > 0) {
|
|
for (let i = 0; i < dependencies.length; ++i) {
|
|
this.dfsTraverse(dependencies[i], cycleCheck, alreadyTraversed, result);
|
|
}
|
|
}
|
|
// add to result holder
|
|
result.push(root);
|
|
// mark this node as traversed so that we don't traverse from this again
|
|
alreadyTraversed.add(root.name);
|
|
// release the hold
|
|
cycleCheck.delete(root.name);
|
|
}
|
|
}
|
|
exports.TopologicalSortGlslRoutines = TopologicalSortGlslRoutines;
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./lib/onnxjs/backends/webgl/glsl-encoding-lib.ts":
|
|
/*!********************************************************!*\
|
|
!*** ./lib/onnxjs/backends/webgl/glsl-encoding-lib.ts ***!
|
|
\********************************************************/
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
// Licensed under the MIT License.
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.EncodingGlslLib = void 0;
|
|
const glsl_definitions_1 = __webpack_require__(/*! ./glsl-definitions */ "./lib/onnxjs/backends/webgl/glsl-definitions.ts");
|
|
/**
|
|
* This GLSL library handles routines converting
|
|
* float32 to/from Unsigned byte or float 16
|
|
*/
|
|
class EncodingGlslLib extends glsl_definitions_1.GlslLib {
|
|
constructor(context) {
|
|
super(context);
|
|
}
|
|
getFunctions() {
|
|
return Object.assign(Object.assign({}, this.encodeFloat32()), this.decodeFloat32());
|
|
}
|
|
getCustomTypes() {
|
|
return {};
|
|
}
|
|
encodeFloat32() {
|
|
return {
|
|
encode: new glsl_definitions_1.GlslLibRoutine(`highp vec4 encode(highp float f) {
|
|
return vec4(f, 0.0, 0.0, 0.0);
|
|
}
|
|
`)
|
|
};
|
|
}
|
|
decodeFloat32() {
|
|
return {
|
|
decode: new glsl_definitions_1.GlslLibRoutine(`highp float decode(highp vec4 rgba) {
|
|
return rgba.r;
|
|
}
|
|
`)
|
|
};
|
|
}
|
|
/**
|
|
* returns the routine to encode encode a 32bit float to a vec4 (of unsigned bytes)
|
|
* @credit: https://stackoverflow.com/questions/7059962/how-do-i-convert-a-vec4-rgba-value-to-a-float
|
|
*/
|
|
encodeUint8() {
|
|
const endianness = EncodingGlslLib.isLittleEndian() ? 'rgba.rgba=rgba.abgr;' : '';
|
|
return {
|
|
encode: new glsl_definitions_1.GlslLibRoutine(`
|
|
highp vec4 encode(highp float f) {
|
|
highp float F = abs(f);
|
|
highp float Sign = step(0.0,-f);
|
|
highp float Exponent = floor(log2(F));
|
|
highp float Mantissa = (exp2(- Exponent) * F);
|
|
Exponent = floor(log2(F) + 127.0) + floor(log2(Mantissa));
|
|
highp vec4 rgba;
|
|
rgba[0] = 128.0 * Sign + floor(Exponent*exp2(-1.0));
|
|
rgba[1] = 128.0 * mod(Exponent,2.0) + mod(floor(Mantissa*128.0),128.0);
|
|
rgba[2] = floor(mod(floor(Mantissa*exp2(23.0 -8.0)),exp2(8.0)));
|
|
rgba[3] = floor(exp2(23.0)*mod(Mantissa,exp2(-15.0)));
|
|
${endianness}
|
|
rgba = rgba / 255.0; // values need to be normalized to [0,1]
|
|
return rgba;
|
|
}
|
|
`)
|
|
};
|
|
}
|
|
/**
|
|
* returns the routine to encode a vec4 of unsigned bytes to float32
|
|
* @credit: https://stackoverflow.com/questions/7059962/how-do-i-convert-a-vec4-rgba-value-to-a-float
|
|
*/
|
|
decodeUint8() {
|
|
const endianness = EncodingGlslLib.isLittleEndian() ? 'rgba.rgba=rgba.abgr;' : '';
|
|
return {
|
|
decode: new glsl_definitions_1.GlslLibRoutine(`
|
|
highp float decode(highp vec4 rgba) {
|
|
rgba = rgba * 255.0; // values need to be de-normalized from [0,1] to [0,255]
|
|
${endianness}
|
|
highp float Sign = 1.0 - step(128.0,rgba[0])*2.0;
|
|
highp float Exponent = 2.0 * mod(rgba[0],128.0) + step(128.0,rgba[1]) - 127.0;
|
|
highp float Mantissa = mod(rgba[1],128.0)*65536.0 + rgba[2]*256.0 +rgba[3] + float(0x800000);
|
|
highp float Result = Sign * exp2(Exponent) * (Mantissa * exp2(-23.0 ));
|
|
return Result;
|
|
}
|
|
`)
|
|
};
|
|
}
|
|
/**
|
|
* Determines if the machine is little endian or not
|
|
* @credit: https://gist.github.com/TooTallNate/4750953
|
|
*/
|
|
static isLittleEndian() {
|
|
const b = new ArrayBuffer(4);
|
|
const a = new Uint32Array(b);
|
|
const c = new Uint8Array(b);
|
|
a[0] = 0xdeadbeef;
|
|
if (c[0] === 0xef) {
|
|
return true;
|
|
}
|
|
if (c[0] === 0xde) {
|
|
return false;
|
|
}
|
|
throw new Error('unknown endianness');
|
|
}
|
|
}
|
|
exports.EncodingGlslLib = EncodingGlslLib;
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./lib/onnxjs/backends/webgl/glsl-fragcolor-lib.ts":
|
|
/*!*********************************************************!*\
|
|
!*** ./lib/onnxjs/backends/webgl/glsl-fragcolor-lib.ts ***!
|
|
\*********************************************************/
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
// Licensed under the MIT License.
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.FragColorGlslLib = void 0;
|
|
const glsl_definitions_1 = __webpack_require__(/*! ./glsl-definitions */ "./lib/onnxjs/backends/webgl/glsl-definitions.ts");
|
|
const glsl_source_1 = __webpack_require__(/*! ./glsl-source */ "./lib/onnxjs/backends/webgl/glsl-source.ts");
|
|
/**
|
|
* This GLSL library handles routines around reading a texlet and writing to it
|
|
* Reading and writing could be more than just dealing with one channel
|
|
* It may require encoding/decoding to/from 4 channels into one
|
|
*/
|
|
class FragColorGlslLib extends glsl_definitions_1.GlslLib {
|
|
constructor(context) {
|
|
super(context);
|
|
}
|
|
getFunctions() {
|
|
return Object.assign(Object.assign({}, this.setFragColor()), this.getColorAsFloat());
|
|
}
|
|
getCustomTypes() {
|
|
return {};
|
|
}
|
|
setFragColor() {
|
|
const glsl = (0, glsl_source_1.getGlsl)(this.context.glContext.version);
|
|
return {
|
|
setFragColor: new glsl_definitions_1.GlslLibRoutine(`
|
|
void setFragColor(float value) {
|
|
${glsl.output} = encode(value);
|
|
}
|
|
`, ['encoding.encode'])
|
|
};
|
|
}
|
|
getColorAsFloat() {
|
|
return {
|
|
getColorAsFloat: new glsl_definitions_1.GlslLibRoutine(`
|
|
float getColorAsFloat(vec4 color) {
|
|
return decode(color);
|
|
}
|
|
`, ['encoding.decode'])
|
|
};
|
|
}
|
|
}
|
|
exports.FragColorGlslLib = FragColorGlslLib;
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./lib/onnxjs/backends/webgl/glsl-function-inliner.ts":
|
|
/*!************************************************************!*\
|
|
!*** ./lib/onnxjs/backends/webgl/glsl-function-inliner.ts ***!
|
|
\************************************************************/
|
|
/***/ ((__unused_webpack_module, exports) => {
|
|
|
|
"use strict";
|
|
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
// Licensed under the MIT License.
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.replaceInlines = void 0;
|
|
const INLINE_FUNC_DEF_REGEX = /@inline[\s\n\r]+(\w+)[\s\n\r]+([0-9a-zA-Z_]+)\s*\(([^)]*)\)\s*{(([^}]|[\n\r])*)}/gm;
|
|
const FUNC_CALL_REGEX = '(\\w+)?\\s+([_0-9a-zA-Z]+)\\s+=\\s+__FUNC__\\((.*)\\)\\s*;';
|
|
/**
|
|
* GLSL preprocessor responsible for resolving @inline directives
|
|
*/
|
|
function replaceInlines(script) {
|
|
const inlineDefs = {};
|
|
let match;
|
|
while ((match = INLINE_FUNC_DEF_REGEX.exec(script)) !== null) {
|
|
const params = match[3]
|
|
.split(',')
|
|
.map(s => {
|
|
const tokens = s.trim().split(' ');
|
|
if (tokens && tokens.length === 2) {
|
|
return { type: tokens[0], name: tokens[1] };
|
|
}
|
|
return null;
|
|
})
|
|
.filter(v => v !== null);
|
|
inlineDefs[match[2]] = { params, body: match[4] };
|
|
}
|
|
for (const name in inlineDefs) {
|
|
const regexString = FUNC_CALL_REGEX.replace('__FUNC__', name);
|
|
const regex = new RegExp(regexString, 'gm');
|
|
while ((match = regex.exec(script)) !== null) {
|
|
const type = match[1];
|
|
const variable = match[2];
|
|
const params = match[3].split(',');
|
|
const declLine = (type) ? `${type} ${variable};` : '';
|
|
let newBody = inlineDefs[name].body;
|
|
let paramRedecLine = '';
|
|
inlineDefs[name].params.forEach((v, i) => {
|
|
if (v) {
|
|
paramRedecLine += `${v.type} ${v.name} = ${params[i]};\n`;
|
|
}
|
|
});
|
|
newBody = `${paramRedecLine}\n ${newBody}`;
|
|
newBody = newBody.replace('return', `${variable} = `);
|
|
const replacement = `
|
|
${declLine}
|
|
{
|
|
${newBody}
|
|
}
|
|
`;
|
|
script = script.replace(match[0], replacement);
|
|
}
|
|
}
|
|
script = script.replace(INLINE_FUNC_DEF_REGEX, '');
|
|
return script;
|
|
}
|
|
exports.replaceInlines = replaceInlines;
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./lib/onnxjs/backends/webgl/glsl-preprocessor.ts":
|
|
/*!********************************************************!*\
|
|
!*** ./lib/onnxjs/backends/webgl/glsl-preprocessor.ts ***!
|
|
\********************************************************/
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
// Licensed under the MIT License.
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.GlslPreprocessor = void 0;
|
|
const glsl_definitions_1 = __webpack_require__(/*! ./glsl-definitions */ "./lib/onnxjs/backends/webgl/glsl-definitions.ts");
|
|
const glsl_function_inliner_1 = __webpack_require__(/*! ./glsl-function-inliner */ "./lib/onnxjs/backends/webgl/glsl-function-inliner.ts");
|
|
const glsl_registered_libs_1 = __webpack_require__(/*! ./glsl-registered-libs */ "./lib/onnxjs/backends/webgl/glsl-registered-libs.ts");
|
|
const glsl_source_1 = __webpack_require__(/*! ./glsl-source */ "./lib/onnxjs/backends/webgl/glsl-source.ts");
|
|
/**
|
|
* Preprocessor for the additions to the GLSL language
|
|
* It deals with:
|
|
* @include directives
|
|
* @inline
|
|
* Loop unrolling (not implemented)
|
|
* Macro resolution (not implemented)
|
|
*/
|
|
class GlslPreprocessor {
|
|
constructor(glContext, programInfo, inputTextureLayouts, outputTextureLayout) {
|
|
this.libs = {};
|
|
this.glslLibRoutineDependencyGraph = {};
|
|
this.context = new glsl_definitions_1.GlslContext(glContext, programInfo, inputTextureLayouts, outputTextureLayout);
|
|
// construct GlslLibs
|
|
Object.keys(glsl_registered_libs_1.glslRegistry).forEach((name) => {
|
|
const lib = new glsl_registered_libs_1.glslRegistry[name](this.context);
|
|
this.libs[name] = lib;
|
|
});
|
|
// construct GlslRoutineDependencyGraph
|
|
const map = this.glslLibRoutineDependencyGraph;
|
|
for (const libName in this.libs) {
|
|
const lib = this.libs[libName];
|
|
const routinesInLib = lib.getFunctions();
|
|
for (const routine in routinesInLib) {
|
|
const key = libName + '.' + routine;
|
|
let currentNode;
|
|
if (map[key]) {
|
|
currentNode = map[key];
|
|
currentNode.routineBody = routinesInLib[routine].routineBody;
|
|
}
|
|
else {
|
|
currentNode = new glsl_definitions_1.GlslLibRoutineNode(key, routinesInLib[routine].routineBody);
|
|
map[key] = currentNode;
|
|
}
|
|
const dependencies = routinesInLib[routine].dependencies;
|
|
if (dependencies) {
|
|
for (let i = 0; i < dependencies.length; ++i) {
|
|
if (!map[dependencies[i]]) {
|
|
const node = new glsl_definitions_1.GlslLibRoutineNode(dependencies[i]);
|
|
map[dependencies[i]] = node;
|
|
currentNode.addDependency(node);
|
|
}
|
|
else {
|
|
currentNode.addDependency(map[dependencies[i]]);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
preprocess() {
|
|
const programInfo = this.context.programInfo;
|
|
let source = programInfo.shaderSource;
|
|
// append main() function
|
|
if (!this.context.programInfo.hasMain) {
|
|
source = `${source}
|
|
${(0, glsl_source_1.getDefaultFragShaderMain)(this.context.glContext.version, this.context.outputTextureLayout.shape.length)}`;
|
|
}
|
|
// replace inlines
|
|
source = (0, glsl_function_inliner_1.replaceInlines)(source);
|
|
// concat final source string
|
|
return `${(0, glsl_source_1.getFragShaderPreamble)(this.context.glContext.version)}
|
|
${this.getUniforms(programInfo.inputNames, programInfo.variables)}
|
|
${this.getImports(source)}
|
|
${source}`;
|
|
}
|
|
getImports(script) {
|
|
const routinesIncluded = this.selectGlslLibRoutinesToBeIncluded(script);
|
|
if (routinesIncluded.length === 0) {
|
|
return '';
|
|
}
|
|
let routines = '';
|
|
for (let i = 0; i < routinesIncluded.length; ++i) {
|
|
if (routinesIncluded[i].routineBody) {
|
|
routines += routinesIncluded[i].routineBody + '\n';
|
|
}
|
|
else {
|
|
throw new Error(`Missing body for the Glsl Library routine: ${routinesIncluded[i].name}`);
|
|
}
|
|
}
|
|
return routines;
|
|
}
|
|
selectGlslLibRoutinesToBeIncluded(script) {
|
|
const nodes = [];
|
|
Object.keys(this.glslLibRoutineDependencyGraph).forEach(classAndRoutine => {
|
|
const routine = classAndRoutine.split('.')[1];
|
|
if (script.indexOf(routine) !== -1) {
|
|
nodes.push(this.glslLibRoutineDependencyGraph[classAndRoutine]);
|
|
}
|
|
});
|
|
return glsl_definitions_1.TopologicalSortGlslRoutines.returnOrderedNodes(nodes);
|
|
}
|
|
getUniforms(samplers, variables) {
|
|
const uniformLines = [];
|
|
if (samplers) {
|
|
for (const sampler of samplers) {
|
|
uniformLines.push(`uniform sampler2D ${sampler};`);
|
|
}
|
|
}
|
|
if (variables) {
|
|
for (const variable of variables) {
|
|
uniformLines.push(`uniform ${variable.type} ${variable.name}${variable.arrayLength ? `[${variable.arrayLength}]` : ''};`);
|
|
}
|
|
}
|
|
return uniformLines.join('\n');
|
|
}
|
|
}
|
|
exports.GlslPreprocessor = GlslPreprocessor;
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./lib/onnxjs/backends/webgl/glsl-registered-libs.ts":
|
|
/*!***********************************************************!*\
|
|
!*** ./lib/onnxjs/backends/webgl/glsl-registered-libs.ts ***!
|
|
\***********************************************************/
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
// Licensed under the MIT License.
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.glslRegistry = void 0;
|
|
const glsl_coordinate_lib_1 = __webpack_require__(/*! ./glsl-coordinate-lib */ "./lib/onnxjs/backends/webgl/glsl-coordinate-lib.ts");
|
|
const glsl_encoding_lib_1 = __webpack_require__(/*! ./glsl-encoding-lib */ "./lib/onnxjs/backends/webgl/glsl-encoding-lib.ts");
|
|
const glsl_fragcolor_lib_1 = __webpack_require__(/*! ./glsl-fragcolor-lib */ "./lib/onnxjs/backends/webgl/glsl-fragcolor-lib.ts");
|
|
const glsl_shape_utils_lib_1 = __webpack_require__(/*! ./glsl-shape-utils-lib */ "./lib/onnxjs/backends/webgl/glsl-shape-utils-lib.ts");
|
|
const glsl_vec_lib_1 = __webpack_require__(/*! ./glsl-vec-lib */ "./lib/onnxjs/backends/webgl/glsl-vec-lib.ts");
|
|
exports.glslRegistry = {
|
|
'encoding': glsl_encoding_lib_1.EncodingGlslLib,
|
|
'fragcolor': glsl_fragcolor_lib_1.FragColorGlslLib,
|
|
'vec': glsl_vec_lib_1.VecGlslLib,
|
|
'shapeUtils': glsl_shape_utils_lib_1.ShapeUtilsGlslLib,
|
|
'coordinates': glsl_coordinate_lib_1.CoordsGlslLib,
|
|
// 'arrays': ArrayGlslSLib
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./lib/onnxjs/backends/webgl/glsl-shape-utils-lib.ts":
|
|
/*!***********************************************************!*\
|
|
!*** ./lib/onnxjs/backends/webgl/glsl-shape-utils-lib.ts ***!
|
|
\***********************************************************/
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
// Licensed under the MIT License.
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.ShapeUtilsGlslLib = void 0;
|
|
const glsl_definitions_1 = __webpack_require__(/*! ./glsl-definitions */ "./lib/onnxjs/backends/webgl/glsl-definitions.ts");
|
|
/**
|
|
* GLSL Library responsible for data types and routines for manipulating
|
|
* coordinates and mapping to/from tensor indices
|
|
*/
|
|
class ShapeUtilsGlslLib extends glsl_definitions_1.GlslLib {
|
|
constructor(context) {
|
|
super(context);
|
|
}
|
|
getFunctions() {
|
|
return Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({}, this.bcastIndex()), this.bcastMatmulIndex()), this.offsetToIndices()), this.indicesToOffset()), this.incrementIndices());
|
|
}
|
|
getCustomTypes() {
|
|
return {};
|
|
}
|
|
bcastIndex() {
|
|
const outputRank = this.context.outputTextureLayout.shape.length;
|
|
const result = {};
|
|
this.context.programInfo.inputNames.forEach((name, i) => {
|
|
const shape = this.context.inputTextureLayouts[i].unpackedShape;
|
|
if (shape.length <= outputRank) {
|
|
const rank = shape.length;
|
|
const dimOffset = outputRank - rank;
|
|
const funcName = `bcastIndices_${name}`;
|
|
let block = '';
|
|
for (let i = 0; i < rank; ++i) {
|
|
block += `
|
|
realIndices[${i}] = int( mod(float(bcastedIndices[${dimOffset + i}]), ${shape[i]}.0) );
|
|
`;
|
|
}
|
|
const body = `
|
|
void ${funcName} (int bcastedIndices[${outputRank}], out int realIndices[${rank}]) {
|
|
${block}
|
|
}
|
|
`;
|
|
result[funcName] = new glsl_definitions_1.GlslLibRoutine(body);
|
|
}
|
|
});
|
|
return result;
|
|
}
|
|
bcastMatmulIndex() {
|
|
const outputRank = this.context.outputTextureLayout.shape.length;
|
|
const result = {};
|
|
this.context.programInfo.inputNames.forEach((name, i) => {
|
|
const shape = this.context.inputTextureLayouts[i].shape;
|
|
if (!(shape.length < 2 || shape.length > outputRank)) {
|
|
const rank = shape.length;
|
|
const dimOffset = outputRank - rank;
|
|
const funcName = `bcastMatmulIndices_${name}`;
|
|
let block = '';
|
|
for (let i = 0; i < rank - 2; ++i) {
|
|
block += `
|
|
realIndices[${i}] = int( mod(float(bcastedIndices[${dimOffset + i}]), ${shape[i]}.0) );
|
|
`;
|
|
}
|
|
const body = `
|
|
void ${funcName}(int bcastedIndices[${outputRank}], out int realIndices[${rank}]) {
|
|
${block}
|
|
realIndices[${rank - 1}] = bcastedIndices[${outputRank - 1}];
|
|
realIndices[${rank - 2}] = bcastedIndices[${outputRank - 2}];
|
|
}
|
|
`;
|
|
result[funcName] = new glsl_definitions_1.GlslLibRoutine(body);
|
|
}
|
|
});
|
|
return result;
|
|
}
|
|
indicesToOffset() {
|
|
const result = {};
|
|
this.context.programInfo.inputNames.forEach((name, i) => {
|
|
const shape = this.context.inputTextureLayouts[i].shape;
|
|
const strides = this.context.inputTextureLayouts[i].strides;
|
|
const rank = shape.length;
|
|
let funcName = `indicesToOffset_${name}`;
|
|
result[funcName] = new glsl_definitions_1.GlslLibRoutine(ShapeUtilsGlslLib.indexToOffsetSingle(funcName, rank, strides));
|
|
funcName = `indicesToOffset_${name}_T`;
|
|
result[funcName] =
|
|
new glsl_definitions_1.GlslLibRoutine(ShapeUtilsGlslLib.indexToOffsetSingle(funcName, rank, strides.slice().reverse()));
|
|
});
|
|
return result;
|
|
}
|
|
static indexToOffsetSingle(name, rank, strides) {
|
|
let block = '';
|
|
for (let i = rank - 1; i >= 0; --i) {
|
|
block += `
|
|
offset += indices[${i}] * ${strides[i]};
|
|
`;
|
|
}
|
|
return `
|
|
int ${name}(int indices[${rank}]) {
|
|
int offset = 0;
|
|
${block}
|
|
return offset;
|
|
}
|
|
`;
|
|
}
|
|
offsetToIndices() {
|
|
const result = {};
|
|
this.context.programInfo.inputNames.forEach((name, i) => {
|
|
const shape = this.context.inputTextureLayouts[i].shape;
|
|
const strides = this.context.inputTextureLayouts[i].strides;
|
|
const rank = shape.length;
|
|
let funcName = `offsetToIndices_${name}`;
|
|
result[funcName] = new glsl_definitions_1.GlslLibRoutine(ShapeUtilsGlslLib.offsetToIndicesSingle(funcName, rank, strides));
|
|
funcName = `offsetToIndices_${name}_T`;
|
|
result[funcName] =
|
|
new glsl_definitions_1.GlslLibRoutine(ShapeUtilsGlslLib.offsetToIndicesSingle(funcName, rank, strides.slice().reverse()));
|
|
});
|
|
return result;
|
|
}
|
|
static offsetToIndicesSingle(name, rank, strides) {
|
|
const stridesBlock = [];
|
|
for (let i = 0; i < rank - 1; ++i) {
|
|
stridesBlock.push(`
|
|
indices[${i}] = offset / ${strides[i]};`);
|
|
stridesBlock.push(`
|
|
offset -= indices[${i}] * ${strides[i]};`);
|
|
}
|
|
stridesBlock.push(`
|
|
indices[${rank - 1}] = offset;`);
|
|
return `
|
|
void ${name}(int offset, out int indices[${rank}]) {
|
|
${stridesBlock.join('')}
|
|
}
|
|
`;
|
|
}
|
|
incrementIndices() {
|
|
const result = {};
|
|
this.context.programInfo.inputNames.forEach((name, i) => {
|
|
const shape = this.context.inputTextureLayouts[i].shape;
|
|
const rank = shape.length;
|
|
const funcName = `incrementIndices_${name}`;
|
|
let shapeInit = '';
|
|
for (let i = 0; i < rank; ++i) {
|
|
shapeInit += `
|
|
shape[${i}] = ${shape[i]};`;
|
|
}
|
|
const body = `
|
|
void ${funcName}(int axis, out int indices[${rank}]) {
|
|
int shape[${rank}];
|
|
${shapeInit};
|
|
for(int i = ${rank} -1 ; i >= 0; --i) {
|
|
if(i > axis) continue;
|
|
indices[i] += 1;
|
|
if(indices[i] < shape[i]) {
|
|
break;
|
|
}
|
|
indices[i] = 0;
|
|
}
|
|
}
|
|
`;
|
|
result[funcName] = new glsl_definitions_1.GlslLibRoutine(body);
|
|
});
|
|
return result;
|
|
}
|
|
}
|
|
exports.ShapeUtilsGlslLib = ShapeUtilsGlslLib;
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./lib/onnxjs/backends/webgl/glsl-source.ts":
|
|
/*!**************************************************!*\
|
|
!*** ./lib/onnxjs/backends/webgl/glsl-source.ts ***!
|
|
\**************************************************/
|
|
/***/ ((__unused_webpack_module, exports) => {
|
|
|
|
"use strict";
|
|
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
// Licensed under the MIT License.
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.getDefaultFragShaderMain = exports.getFragShaderPreamble = exports.getVertexShaderSource = exports.getGlsl = void 0;
|
|
const GLSL_ES_2_0 = {
|
|
version: '',
|
|
attribute: 'attribute',
|
|
varyingVertex: 'varying',
|
|
varyingFrag: 'varying',
|
|
texture2D: 'texture2D',
|
|
output: 'gl_FragColor',
|
|
outputDeclaration: '',
|
|
};
|
|
const GLSL_ES_3_0 = {
|
|
version: '#version 300 es',
|
|
attribute: 'in',
|
|
varyingVertex: 'out',
|
|
varyingFrag: 'in',
|
|
texture2D: 'texture',
|
|
output: 'outputColor',
|
|
outputDeclaration: 'out vec4 outputColor;',
|
|
};
|
|
function getGlsl(version) {
|
|
return version === 1 ? GLSL_ES_2_0 : GLSL_ES_3_0;
|
|
}
|
|
exports.getGlsl = getGlsl;
|
|
function getVertexShaderSource(version) {
|
|
const glsl = getGlsl(version);
|
|
return `${glsl.version}
|
|
precision highp float;
|
|
${glsl.attribute} vec3 position;
|
|
${glsl.attribute} vec2 textureCoord;
|
|
|
|
${glsl.varyingVertex} vec2 TexCoords;
|
|
|
|
void main()
|
|
{
|
|
gl_Position = vec4(position, 1.0);
|
|
TexCoords = textureCoord;
|
|
}`;
|
|
}
|
|
exports.getVertexShaderSource = getVertexShaderSource;
|
|
function getFragShaderPreamble(version) {
|
|
const glsl = getGlsl(version);
|
|
return `${glsl.version}
|
|
precision highp float;
|
|
precision highp int;
|
|
precision highp sampler2D;
|
|
${glsl.varyingFrag} vec2 TexCoords;
|
|
${glsl.outputDeclaration}
|
|
const vec2 halfCR = vec2(0.5, 0.5);
|
|
|
|
// Custom vector types to handle higher dimenalities.
|
|
struct ivec5
|
|
{
|
|
int x;
|
|
int y;
|
|
int z;
|
|
int w;
|
|
int u;
|
|
};
|
|
|
|
struct ivec6
|
|
{
|
|
int x;
|
|
int y;
|
|
int z;
|
|
int w;
|
|
int u;
|
|
int v;
|
|
};
|
|
|
|
int imod(int x, int y) {
|
|
return x - y * (x / y);
|
|
}
|
|
|
|
`;
|
|
}
|
|
exports.getFragShaderPreamble = getFragShaderPreamble;
|
|
function getDefaultFragShaderMain(version, outputShapeLength) {
|
|
const glsl = getGlsl(version);
|
|
return `
|
|
void main() {
|
|
int indices[${outputShapeLength}];
|
|
toVec(TexCoords, indices);
|
|
vec4 result = vec4(process(indices));
|
|
${glsl.output} = result;
|
|
}
|
|
`;
|
|
}
|
|
exports.getDefaultFragShaderMain = getDefaultFragShaderMain;
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./lib/onnxjs/backends/webgl/glsl-vec-lib.ts":
|
|
/*!***************************************************!*\
|
|
!*** ./lib/onnxjs/backends/webgl/glsl-vec-lib.ts ***!
|
|
\***************************************************/
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
// Licensed under the MIT License.
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.VecGlslLib = void 0;
|
|
const glsl_definitions_1 = __webpack_require__(/*! ./glsl-definitions */ "./lib/onnxjs/backends/webgl/glsl-definitions.ts");
|
|
/**
|
|
* GLSL Library responsible for vec routines
|
|
* Vec is an varible length int array. The length is fixed at the time of
|
|
* generating the library functions from the dimensions of the output.
|
|
*/
|
|
class VecGlslLib extends glsl_definitions_1.GlslLib {
|
|
constructor(context) {
|
|
super(context);
|
|
}
|
|
getCustomTypes() {
|
|
return {};
|
|
}
|
|
getFunctions() {
|
|
return Object.assign(Object.assign(Object.assign(Object.assign({}, this.binaryVecFunctions()), this.copyVec()), this.setVecItem()), this.getVecItem());
|
|
}
|
|
binaryVecFunctions() {
|
|
const outputLayout = this.context.outputTextureLayout;
|
|
const rank = outputLayout.shape.length;
|
|
const nameOp = { add: '+=', sub: '-=', mul: '*=', div: '/=' };
|
|
const result = {};
|
|
for (const name in nameOp) {
|
|
const fname = `${name}Vec`;
|
|
let assignmentBlock = '';
|
|
for (let i = 0; i < rank; ++i) {
|
|
assignmentBlock += `
|
|
dest[${i}] ${nameOp[name]} src[${i}];
|
|
`;
|
|
}
|
|
const body = `
|
|
void ${fname}(int src[${rank}], out int dest[${rank}]) {
|
|
${assignmentBlock}
|
|
}
|
|
`;
|
|
result[fname] = new glsl_definitions_1.GlslLibRoutine(body);
|
|
}
|
|
return result;
|
|
}
|
|
copyVec() {
|
|
const outputLayout = this.context.outputTextureLayout;
|
|
const rank = outputLayout.shape.length;
|
|
let assignmentBlock = '';
|
|
for (let i = 0; i < rank; ++i) {
|
|
assignmentBlock += `
|
|
dest[${i}] = src[${i}];
|
|
`;
|
|
}
|
|
const body = `
|
|
void copyVec(int src[${rank}], out int dest[${rank}]) {
|
|
${assignmentBlock}
|
|
}
|
|
`;
|
|
return { copyVec: new glsl_definitions_1.GlslLibRoutine(body) };
|
|
}
|
|
setVecItem() {
|
|
const outputLayout = this.context.outputTextureLayout;
|
|
const rank = outputLayout.shape.length;
|
|
let block = `
|
|
if(index < 0)
|
|
index =${rank} + index;
|
|
if (index == 0)
|
|
m[0] = value;
|
|
`;
|
|
for (let i = 1; i < rank - 1; ++i) {
|
|
block += `
|
|
else if (index == ${i})
|
|
m[${i}] = value;
|
|
`;
|
|
}
|
|
block += `
|
|
else
|
|
m[${rank - 1}] = value;
|
|
`;
|
|
const body = `
|
|
void setVecItem(out int m[${rank}], int index, int value) {
|
|
${block}
|
|
}
|
|
`;
|
|
return { setVecItem: new glsl_definitions_1.GlslLibRoutine(body) };
|
|
}
|
|
getVecItem() {
|
|
const outputLayout = this.context.outputTextureLayout;
|
|
const rank = outputLayout.shape.length;
|
|
let block = `
|
|
if(index < 0)
|
|
index = ${rank} + index;
|
|
if (index == 0)
|
|
return m[0];
|
|
`;
|
|
for (let i = 1; i < rank - 1; ++i) {
|
|
block += `
|
|
else if (index == ${i})
|
|
return m[${i}];
|
|
`;
|
|
}
|
|
block += `
|
|
else
|
|
return m[${rank - 1}];
|
|
`;
|
|
const body = `
|
|
int getVecItem(int m[${rank}], int index) {
|
|
${block}
|
|
}
|
|
`;
|
|
return { getVecItem: new glsl_definitions_1.GlslLibRoutine(body) };
|
|
}
|
|
}
|
|
exports.VecGlslLib = VecGlslLib;
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./lib/onnxjs/backends/webgl/inference-handler.ts":
|
|
/*!********************************************************!*\
|
|
!*** ./lib/onnxjs/backends/webgl/inference-handler.ts ***!
|
|
\********************************************************/
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
// Licensed under the MIT License.
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.WebGLInferenceHandler = void 0;
|
|
const instrument_1 = __webpack_require__(/*! ../../instrument */ "./lib/onnxjs/instrument.ts");
|
|
const tensor_1 = __webpack_require__(/*! ../../tensor */ "./lib/onnxjs/tensor.ts");
|
|
const util_1 = __webpack_require__(/*! ../../util */ "./lib/onnxjs/util.ts");
|
|
const pack_1 = __webpack_require__(/*! ./ops/pack */ "./lib/onnxjs/backends/webgl/ops/pack.ts");
|
|
const reshape_packed_1 = __webpack_require__(/*! ./ops/reshape-packed */ "./lib/onnxjs/backends/webgl/ops/reshape-packed.ts");
|
|
const uint8_encode_1 = __webpack_require__(/*! ./ops/uint8-encode */ "./lib/onnxjs/backends/webgl/ops/uint8-encode.ts");
|
|
const unpack_1 = __webpack_require__(/*! ./ops/unpack */ "./lib/onnxjs/backends/webgl/ops/unpack.ts");
|
|
const texture_layout_1 = __webpack_require__(/*! ./texture-layout */ "./lib/onnxjs/backends/webgl/texture-layout.ts");
|
|
const types_1 = __webpack_require__(/*! ./types */ "./lib/onnxjs/backends/webgl/types.ts");
|
|
const getProgramInfoUniqueKey = (programInfo, inputTextureDatas) => {
|
|
const inputs = inputTextureDatas.map(texture => `${texture.unpackedShape.join(',')};${texture.width}x${texture.height}`)
|
|
.join('_');
|
|
let key = programInfo.name;
|
|
if (programInfo.cacheHint) {
|
|
key += '[' + programInfo.cacheHint + ']';
|
|
}
|
|
key += ':' + inputs;
|
|
return key;
|
|
};
|
|
class WebGLInferenceHandler {
|
|
constructor(session) {
|
|
this.session = session;
|
|
this.packedTextureDataCache = new Map();
|
|
this.unpackedTextureDataCache = new Map();
|
|
}
|
|
/**
|
|
* @returns [width, height]
|
|
*/
|
|
calculateTextureWidthAndHeight(shape, textureType) {
|
|
return (0, texture_layout_1.calculateTextureWidthAndHeight)(this.session.layoutStrategy, shape, textureType);
|
|
}
|
|
executeProgram(program, inputs) {
|
|
if (inputs.length < program.inputNames.length) {
|
|
throw new Error(`Input size mustn't be less than ${program.inputNames.length}.`);
|
|
}
|
|
if (program.inputNames.length !== program.inputTypes.length) {
|
|
throw new Error('input names size does not match input types');
|
|
}
|
|
// create texture info for input
|
|
const inputTextureDatas = [];
|
|
for (let i = 0; i < program.inputNames.length; ++i) {
|
|
inputTextureDatas[i] = this.getOrCreateTextureData(inputs[i], program.inputTypes[i]);
|
|
}
|
|
const key = getProgramInfoUniqueKey(program, inputTextureDatas);
|
|
let artifact = this.session.programManager.getArtifact(key);
|
|
const programInfo = artifact ?
|
|
artifact.programInfo :
|
|
(typeof program.get === 'function' ? program.get() :
|
|
program);
|
|
// create texture info for output
|
|
const outputTextureLayout = (0, texture_layout_1.createTextureLayoutFromTextureType)(this.session.layoutStrategy, programInfo.output.dims, programInfo.output.textureType);
|
|
const outputTextureData = this.createTextureData(outputTextureLayout, programInfo.output.type);
|
|
if (!artifact) {
|
|
artifact = this.session.programManager.build(programInfo, inputTextureDatas, outputTextureData);
|
|
this.session.programManager.setArtifact(key, artifact);
|
|
}
|
|
this.runProgram(artifact, inputTextureDatas, outputTextureData);
|
|
return outputTextureData;
|
|
}
|
|
run(program, inputs) {
|
|
const outputTextureData = this.executeProgram(program, inputs);
|
|
return outputTextureData.tensor;
|
|
}
|
|
runProgram(artifact, inputs, output) {
|
|
// input should match
|
|
for (let i = 0; i < inputs.length; ++i) {
|
|
if (!!inputs[i].isPacked !== (artifact.programInfo.inputTypes[i] === types_1.TextureType.packed)) {
|
|
throw new Error(`input[${i}] property packed inconsistent`);
|
|
}
|
|
}
|
|
// output should match
|
|
if (!!output.isPacked !== (artifact.programInfo.output.textureType === types_1.TextureType.packed)) {
|
|
throw new Error('output property packed inconsistent');
|
|
}
|
|
this.session.programManager.run(artifact, inputs, output);
|
|
}
|
|
/**
|
|
* Create a TextureData object from a tensor.
|
|
* Usage = Encoder.Usage.UploadOnly.
|
|
* If a related texture data is found in cache, returns it;
|
|
* Otherwise:
|
|
* Creates a new texture layout if not provided;
|
|
* Creates WebGLTexture with the layout;
|
|
* Upload tensor data to the texture;
|
|
* Creates a texture data object associated with the given tensor.
|
|
* @param tensor the tensor with data to upload
|
|
*/
|
|
getOrCreateTextureData(tensor, textureType) {
|
|
let td = this.getTextureData(tensor.dataId, textureType === types_1.TextureType.packed);
|
|
if (!td) {
|
|
// check if we have texture data in different type
|
|
td = this.getTextureData(tensor.dataId, textureType !== types_1.TextureType.packed);
|
|
if (td) {
|
|
if (textureType === types_1.TextureType.packed) {
|
|
return this.pack(td);
|
|
}
|
|
else {
|
|
return this.unpack(td);
|
|
}
|
|
}
|
|
}
|
|
if (!td) {
|
|
const layout = (0, texture_layout_1.createTextureLayoutFromTextureType)(this.session.layoutStrategy, tensor.dims, textureType);
|
|
if (textureType === types_1.TextureType.packedLastDimension) {
|
|
const group = 1;
|
|
const channels = 4;
|
|
const shape = tensor.dims;
|
|
if (shape.length === 4) {
|
|
// pre-processing for kernel data of Conv.
|
|
//
|
|
// TODO: currently this is a hacking to overwrite Conv's weight. The correct way to do this should be:
|
|
// 1. implement texture based const-folding
|
|
// 2. create a WebGL program "preprocessConvWeight" to do the same work as below
|
|
// 3. run the program before dotProduct.
|
|
//
|
|
const adjustedKernelShape = [shape[0], Math.ceil((shape[1] * shape[2] * shape[3]) / channels)];
|
|
const adjustedLayout = (0, texture_layout_1.createTextureLayoutFromTextureType)(this.session.layoutStrategy, adjustedKernelShape, textureType);
|
|
let buffer = tensor.numberData;
|
|
if (shape[1] * shape[2] * shape[3] % channels !== 0) {
|
|
const numFeatureMaps = shape[0];
|
|
const oldRowSize = shape[1] * shape[2] * shape[3];
|
|
const newRowSize = Math.ceil(oldRowSize * group / channels) * channels;
|
|
const newSize = numFeatureMaps * newRowSize;
|
|
buffer = new Float32Array(newSize);
|
|
for (let f = 0; f < numFeatureMaps; ++f) {
|
|
const oldOffset = f * oldRowSize;
|
|
const newOffset = f * newRowSize + f % group * oldRowSize;
|
|
buffer.set(tensor.numberData.subarray(oldOffset, oldOffset + oldRowSize), newOffset);
|
|
}
|
|
}
|
|
return this.createTextureData(adjustedLayout, tensor.type, buffer, tensor, 1 /* Encoder.Usage.UploadOnly */);
|
|
}
|
|
}
|
|
if (textureType === types_1.TextureType.packed) {
|
|
const unpackedTextureLayout = (0, texture_layout_1.createTextureLayoutFromShape)(this.session.layoutStrategy, tensor.dims, 1, [], { reverseWH: true });
|
|
const unpackedTextureData = this.createTextureData(unpackedTextureLayout, tensor.type, tensor.numberData, tensor, 1 /* Encoder.Usage.UploadOnly */);
|
|
td = this.pack(unpackedTextureData);
|
|
}
|
|
else {
|
|
td = this.createTextureData(layout, tensor.type, tensor.numberData, tensor, 1 /* Encoder.Usage.UploadOnly */);
|
|
}
|
|
}
|
|
return td;
|
|
}
|
|
/**
|
|
* Create a TextureData object using the given data and bind to the given tensor.
|
|
* Usage = Encoder.Usage.UploadOnly.
|
|
* NOTE: this function is a hack for Conv implementation. should remove this function, after rewriting Conv
|
|
* implementation by Graph.Transformer
|
|
* @param dataType the tensor data type
|
|
* @param data the actual data to upload
|
|
* @param tensor the tensor to bind. tensor's data is ignored.
|
|
*/
|
|
createTextureDataFromLayoutBindTensor(layout, dataType, data, tensor) {
|
|
return this.createTextureData(layout, dataType, data, tensor, 1 /* Encoder.Usage.UploadOnly */);
|
|
}
|
|
createTextureData(layout, dataType, data, tensor, usage) {
|
|
instrument_1.Logger.verbose('InferenceHandler', `Creating TextureData: layout:[${JSON.stringify(layout)}]`);
|
|
const texture = this.session.textureManager.createTextureFromLayout(dataType, layout, data, usage);
|
|
return this.createTextureDataFromTexture(layout, dataType, texture, tensor);
|
|
}
|
|
reshapeUnpacked(input, reshapedDims) {
|
|
const inputTD = this.getOrCreateTextureData(input, types_1.TextureType.unpacked);
|
|
const newTextureLayout = {
|
|
channels: inputTD.channels,
|
|
height: inputTD.height,
|
|
width: inputTD.width,
|
|
// handle reshaping into scalar Tensors
|
|
shape: reshapedDims.length !== 0 ? reshapedDims : [1],
|
|
strides: util_1.ShapeUtil.computeStrides(reshapedDims),
|
|
unpackedShape: reshapedDims,
|
|
};
|
|
const newTextureData = this.createTextureDataFromTexture(newTextureLayout, input.type, inputTD.texture);
|
|
return newTextureData.tensor;
|
|
}
|
|
reshapePacked(input, reshapedDims) {
|
|
const inputTD = this.getOrCreateTextureData(input, types_1.TextureType.packed);
|
|
// check if the reshape is 'cheap'
|
|
if ((0, reshape_packed_1.isReshapeCheap)(input.dims, reshapedDims)) {
|
|
const newTextureLayout = {
|
|
channels: inputTD.channels,
|
|
height: inputTD.height,
|
|
width: inputTD.width,
|
|
// handle reshaping into scalar Tensors
|
|
shape: reshapedDims.length !== 0 ? reshapedDims : [1],
|
|
strides: util_1.ShapeUtil.computeStrides(reshapedDims),
|
|
unpackedShape: reshapedDims,
|
|
isPacked: true
|
|
};
|
|
const newTextureData = this.createTextureDataFromTexture(newTextureLayout, input.type, inputTD.texture);
|
|
return newTextureData.tensor;
|
|
}
|
|
const squeezedInputShape = (0, reshape_packed_1.processDims3D)(input.dims);
|
|
const squeezedOutputShape = (0, reshape_packed_1.processDims3D)(reshapedDims);
|
|
const squeezedInputTensor = this.reshapePacked(input, squeezedInputShape);
|
|
const squeezedOutputTensor = this.run((0, reshape_packed_1.createPackedReshape3DProgramInfoLoader)(this, squeezedInputTensor, squeezedOutputShape), [squeezedInputTensor]);
|
|
const outputTensor = this.reshapePacked(squeezedOutputTensor, reshapedDims);
|
|
return outputTensor;
|
|
}
|
|
cast(input, type) {
|
|
const inputTD = this.getOrCreateTextureData(input, types_1.TextureType.unpacked);
|
|
const newTextureData = this.createTextureDataFromTexture(inputTD, type, inputTD.texture);
|
|
return newTextureData.tensor;
|
|
}
|
|
createTextureDataFromTexture(layout, dataType, texture, tensor, tensorId) {
|
|
const textureData = Object.assign(Object.assign({}, layout), { tensor: tensor ||
|
|
new tensor_1.Tensor(layout.unpackedShape, dataType, (_id) => this.readTexture(textureData), async (_id) => this.readTextureAsync(textureData), undefined, tensorId), texture });
|
|
this.setTextureData(textureData.tensor.dataId, textureData, layout.isPacked);
|
|
return textureData;
|
|
}
|
|
getTextureData(tensorId, isPacked = false) {
|
|
return this.session.isInitializer(tensorId) ? this.session.getTextureData(tensorId, isPacked) :
|
|
isPacked ? this.packedTextureDataCache.get(tensorId) :
|
|
this.unpackedTextureDataCache.get(tensorId);
|
|
}
|
|
setTextureData(tensorId, td, isPacked = false) {
|
|
if (this.session.isInitializer(tensorId)) {
|
|
this.session.setTextureData(tensorId, td, isPacked);
|
|
}
|
|
else {
|
|
(isPacked ? this.packedTextureDataCache : this.unpackedTextureDataCache).set(tensorId, td);
|
|
}
|
|
}
|
|
isTextureLayoutCached(tensor, isPacked = false) {
|
|
return !!this.getTextureData(tensor.dataId, isPacked);
|
|
}
|
|
dispose() {
|
|
this.session.textureManager.clearActiveTextures();
|
|
this.packedTextureDataCache.forEach(td => this.session.textureManager.releaseTexture(td));
|
|
this.packedTextureDataCache = new Map();
|
|
this.unpackedTextureDataCache.forEach(td => this.session.textureManager.releaseTexture(td));
|
|
this.unpackedTextureDataCache = new Map();
|
|
}
|
|
readTexture(textureData) {
|
|
if (textureData.isPacked) {
|
|
return this.readTexture(this.unpack(textureData));
|
|
}
|
|
if (!this.session.backend.glContext.isFloat32DownloadSupported) {
|
|
return this.session.textureManager.readUint8TextureAsFloat((0, uint8_encode_1.encodeAsUint8)(this, textureData));
|
|
}
|
|
return this.session.textureManager.readTexture(textureData, textureData.tensor.type, textureData.channels);
|
|
}
|
|
async readTextureAsync(textureData) {
|
|
if (textureData.isPacked) {
|
|
return this.readTextureAsync(this.unpack(textureData));
|
|
}
|
|
if (!this.session.backend.glContext.isFloat32DownloadSupported) {
|
|
return this.session.textureManager.readUint8TextureAsFloat((0, uint8_encode_1.encodeAsUint8)(this, textureData));
|
|
}
|
|
return this.session.textureManager.readTextureAsync(textureData, textureData.tensor.type, textureData.channels);
|
|
}
|
|
pack(input) {
|
|
const outputTextureData = this.executeProgram((0, pack_1.createPackProgramInfoLoader)(this, input.tensor), [input.tensor]);
|
|
return outputTextureData;
|
|
}
|
|
unpack(input) {
|
|
const outputTextureData = this.executeProgram((0, unpack_1.createUnpackProgramInfoLoader)(this, input.tensor), [input.tensor]);
|
|
return outputTextureData;
|
|
}
|
|
}
|
|
exports.WebGLInferenceHandler = WebGLInferenceHandler;
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./lib/onnxjs/backends/webgl/op-resolve-rules.ts":
|
|
/*!*******************************************************!*\
|
|
!*** ./lib/onnxjs/backends/webgl/op-resolve-rules.ts ***!
|
|
\*******************************************************/
|
|
/***/ (function(__unused_webpack_module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
// Licensed under the MIT License.
|
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
if (k2 === undefined) k2 = k;
|
|
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
}
|
|
Object.defineProperty(o, k2, desc);
|
|
}) : (function(o, m, k, k2) {
|
|
if (k2 === undefined) k2 = k;
|
|
o[k2] = m[k];
|
|
}));
|
|
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
}) : function(o, v) {
|
|
o["default"] = v;
|
|
});
|
|
var __importStar = (this && this.__importStar) || function (mod) {
|
|
if (mod && mod.__esModule) return mod;
|
|
var result = {};
|
|
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
__setModuleDefault(result, mod);
|
|
return result;
|
|
};
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.WEBGL_OP_RESOLVE_RULES = void 0;
|
|
const batch_normalization_1 = __webpack_require__(/*! ./ops/batch-normalization */ "./lib/onnxjs/backends/webgl/ops/batch-normalization.ts");
|
|
const binaryOps = __importStar(__webpack_require__(/*! ./ops/binary-op */ "./lib/onnxjs/backends/webgl/ops/binary-op.ts"));
|
|
const cast_1 = __webpack_require__(/*! ./ops/cast */ "./lib/onnxjs/backends/webgl/ops/cast.ts");
|
|
const concat_1 = __webpack_require__(/*! ./ops/concat */ "./lib/onnxjs/backends/webgl/ops/concat.ts");
|
|
const conv_1 = __webpack_require__(/*! ./ops/conv */ "./lib/onnxjs/backends/webgl/ops/conv.ts");
|
|
const conv_transpose_1 = __webpack_require__(/*! ./ops/conv-transpose */ "./lib/onnxjs/backends/webgl/ops/conv-transpose.ts");
|
|
const depth_to_space_1 = __webpack_require__(/*! ./ops/depth-to-space */ "./lib/onnxjs/backends/webgl/ops/depth-to-space.ts");
|
|
const flatten_1 = __webpack_require__(/*! ./ops/flatten */ "./lib/onnxjs/backends/webgl/ops/flatten.ts");
|
|
const gather_1 = __webpack_require__(/*! ./ops/gather */ "./lib/onnxjs/backends/webgl/ops/gather.ts");
|
|
const gemm_1 = __webpack_require__(/*! ./ops/gemm */ "./lib/onnxjs/backends/webgl/ops/gemm.ts");
|
|
const image_scaler_1 = __webpack_require__(/*! ./ops/image-scaler */ "./lib/onnxjs/backends/webgl/ops/image-scaler.ts");
|
|
const instance_normalization_1 = __webpack_require__(/*! ./ops/instance-normalization */ "./lib/onnxjs/backends/webgl/ops/instance-normalization.ts");
|
|
const matmul_1 = __webpack_require__(/*! ./ops/matmul */ "./lib/onnxjs/backends/webgl/ops/matmul.ts");
|
|
const pad_1 = __webpack_require__(/*! ./ops/pad */ "./lib/onnxjs/backends/webgl/ops/pad.ts");
|
|
const pool_1 = __webpack_require__(/*! ./ops/pool */ "./lib/onnxjs/backends/webgl/ops/pool.ts");
|
|
const reduce_1 = __webpack_require__(/*! ./ops/reduce */ "./lib/onnxjs/backends/webgl/ops/reduce.ts");
|
|
const reshape_1 = __webpack_require__(/*! ./ops/reshape */ "./lib/onnxjs/backends/webgl/ops/reshape.ts");
|
|
const resize_packed_1 = __webpack_require__(/*! ./ops/resize-packed */ "./lib/onnxjs/backends/webgl/ops/resize-packed.ts");
|
|
const shape_1 = __webpack_require__(/*! ./ops/shape */ "./lib/onnxjs/backends/webgl/ops/shape.ts");
|
|
const slice_1 = __webpack_require__(/*! ./ops/slice */ "./lib/onnxjs/backends/webgl/ops/slice.ts");
|
|
const softmax_1 = __webpack_require__(/*! ./ops/softmax */ "./lib/onnxjs/backends/webgl/ops/softmax.ts");
|
|
const split_1 = __webpack_require__(/*! ./ops/split */ "./lib/onnxjs/backends/webgl/ops/split.ts");
|
|
const squeeze_1 = __webpack_require__(/*! ./ops/squeeze */ "./lib/onnxjs/backends/webgl/ops/squeeze.ts");
|
|
const sum_1 = __webpack_require__(/*! ./ops/sum */ "./lib/onnxjs/backends/webgl/ops/sum.ts");
|
|
const tile_1 = __webpack_require__(/*! ./ops/tile */ "./lib/onnxjs/backends/webgl/ops/tile.ts");
|
|
const transpose_1 = __webpack_require__(/*! ./ops/transpose */ "./lib/onnxjs/backends/webgl/ops/transpose.ts");
|
|
const unaryOps = __importStar(__webpack_require__(/*! ./ops/unary-op */ "./lib/onnxjs/backends/webgl/ops/unary-op.ts"));
|
|
const unsqueeze_1 = __webpack_require__(/*! ./ops/unsqueeze */ "./lib/onnxjs/backends/webgl/ops/unsqueeze.ts");
|
|
const upsample_1 = __webpack_require__(/*! ./ops/upsample */ "./lib/onnxjs/backends/webgl/ops/upsample.ts");
|
|
exports.WEBGL_OP_RESOLVE_RULES = [
|
|
['Abs', '', '6+', unaryOps.abs],
|
|
['Acos', '', '7+', unaryOps.acos],
|
|
['Add', '', '7+', binaryOps.add],
|
|
['And', '', '7+', binaryOps.and],
|
|
['Asin', '', '7+', unaryOps.asin],
|
|
['Atan', '', '7+', unaryOps.atan],
|
|
// TODO: support new attributes for AveragePool-10
|
|
['AveragePool', '', '7+', pool_1.averagePool, pool_1.parseAveragePoolAttributes],
|
|
['BatchNormalization', '', '7+', batch_normalization_1.batchNormalization, batch_normalization_1.parseBatchNormalizationAttributes],
|
|
['Cast', '', '6+', cast_1.cast, cast_1.parseCastAttributes],
|
|
['Ceil', '', '6+', unaryOps.ceil],
|
|
['Clip', '', '6-10', unaryOps.clip, unaryOps.parseClipAttributes],
|
|
['Clip', '', '11+', unaryOps.clipV11],
|
|
['Concat', '', '4+', concat_1.concat, concat_1.parseConcatAttributes],
|
|
['Conv', '', '1+', conv_1.conv, conv_1.parseConvAttributes],
|
|
['ConvTranspose', '', '1+', conv_transpose_1.convTranspose, conv_transpose_1.parseConvTransposeAttributes],
|
|
['Cos', '', '7+', unaryOps.cos],
|
|
['Div', '', '7+', binaryOps.div],
|
|
['Dropout', '', '7+', unaryOps.identity],
|
|
['DepthToSpace', '', '1+', depth_to_space_1.depthToSpace, depth_to_space_1.parseDepthToSpaceAttributes],
|
|
['Equal', '', '7+', binaryOps.equal],
|
|
['Elu', '', '6+', unaryOps.elu, unaryOps.parseEluAttributes],
|
|
['Exp', '', '6+', unaryOps.exp],
|
|
['Flatten', '', '1+', flatten_1.flatten, flatten_1.parseFlattenAttributes],
|
|
['Floor', '', '6+', unaryOps.floor],
|
|
['FusedConv', 'com.microsoft', '1+', conv_1.conv, conv_1.parseConvAttributes],
|
|
['Gather', '', '1+', gather_1.gather, gather_1.parseGatherAttributes],
|
|
['Gemm', '', '7-10', gemm_1.gemm, gemm_1.parseGemmAttributesV7],
|
|
['Gemm', '', '11+', gemm_1.gemm, gemm_1.parseGemmAttributesV11],
|
|
['GlobalAveragePool', '', '1+', pool_1.globalAveragePool, pool_1.parseGlobalAveragePoolAttributes],
|
|
['GlobalMaxPool', '', '1+', pool_1.globalMaxPool],
|
|
['Greater', '', '7+', binaryOps.greater],
|
|
['Identity', '', '1+', unaryOps.identity],
|
|
['ImageScaler', '', '1+', image_scaler_1.imageScaler, image_scaler_1.parseImageScalerAttributes],
|
|
['InstanceNormalization', '', '6+', instance_normalization_1.instanceNormalization, instance_normalization_1.parseInstanceNormalizationAttributes],
|
|
['LeakyRelu', '', '6+', unaryOps.leakyRelu, unaryOps.parseLeakyReluAttributes],
|
|
['Less', '', '7+', binaryOps.less],
|
|
['Log', '', '6+', unaryOps.log],
|
|
['MatMul', '', '1+', matmul_1.matMul, matmul_1.parseMatMulAttributes],
|
|
// TODO: support new attributes for MaxPool-8 and MaxPool-10
|
|
['MaxPool', '', '1+', pool_1.maxPool, pool_1.parseMaxPoolAttributes],
|
|
['Mul', '', '7+', binaryOps.mul],
|
|
['Neg', '', '6+', unaryOps.neg],
|
|
['Not', '', '1+', unaryOps.not],
|
|
['Or', '', '7+', binaryOps.or],
|
|
['Pad', '', '2-10', pad_1.padV2, pad_1.parsePadAttributesV2],
|
|
['Pad', '', '11+', pad_1.padV11, pad_1.parsePadAttributesV11],
|
|
['Pow', '', '7+', binaryOps.pow],
|
|
['PRelu', '', '7+', binaryOps.pRelu],
|
|
['ReduceLogSum', '', '1+', reduce_1.reduceLogSum, reduce_1.parseReduceAttributes],
|
|
['ReduceMax', '', '1+', reduce_1.reduceMax, reduce_1.parseReduceAttributes],
|
|
['ReduceMean', '', '1+', reduce_1.reduceMean, reduce_1.parseReduceAttributes],
|
|
['ReduceMin', '', '1+', reduce_1.reduceMin, reduce_1.parseReduceAttributes],
|
|
['ReduceProd', '', '1+', reduce_1.reduceProd, reduce_1.parseReduceAttributes],
|
|
['ReduceSum', '', '1-12', reduce_1.reduceSum, reduce_1.parseReduceAttributes],
|
|
['ReduceSumSquare', '', '1+', reduce_1.reduceLogSumSquare, reduce_1.parseReduceAttributes],
|
|
['Relu', '', '6+', unaryOps.relu],
|
|
['Reshape', '', '5+', reshape_1.reshape],
|
|
['Resize', '', '10', resize_packed_1.resize, resize_packed_1.parseResizeAttributesV10],
|
|
['Resize', '', '11+', resize_packed_1.resize, resize_packed_1.parseResizeAttributesV11],
|
|
['Shape', '', '1+', shape_1.shape],
|
|
['Sigmoid', '', '6+', unaryOps.sigmoid],
|
|
['Sin', '', '7+', unaryOps.sin],
|
|
['Slice', '', '10+', slice_1.sliceV10],
|
|
['Slice', '', '1-9', slice_1.slice, slice_1.parseSliceAttributes],
|
|
// The "semantic" meaning of axis has changed in opset-13.
|
|
['Softmax', '', '1-12', softmax_1.softmax, softmax_1.parseSoftmaxAttributes],
|
|
['Softmax', '', '13+', softmax_1.softmaxV13, softmax_1.parseSoftmaxAttributesV13],
|
|
// 'Split' operator has an optional attribute 'split'
|
|
// this attribute determines how the specified axis of input data is split.
|
|
// When the attribute is missing, we need the count of number of outputs
|
|
// so that we can determine the 'split' attribute from the runtime input to the Operator
|
|
['Split', '', '2-12', split_1.split, split_1.parseSplitAttributes],
|
|
['Sqrt', '', '6+', unaryOps.sqrt],
|
|
['Squeeze', '', '1-12', squeeze_1.squeeze, squeeze_1.parseSqueezeAttributes],
|
|
['Squeeze', '', '13+', squeeze_1.squeezeV13],
|
|
['Sub', '', '7+', binaryOps.sub],
|
|
['Sum', '', '6+', sum_1.sum],
|
|
['Tan', '', '7+', unaryOps.tan],
|
|
['Tanh', '', '6+', unaryOps.tanh],
|
|
['Tile', '', '6+', tile_1.tile],
|
|
['Transpose', '', '1+', transpose_1.transpose, transpose_1.parseTransposeAttributes],
|
|
['Upsample', '', '7-8', upsample_1.upsample, upsample_1.parseUpsampleAttributesV7],
|
|
['Upsample', '', '9', upsample_1.upsample, upsample_1.parseUpsampleAttributesV9],
|
|
['Unsqueeze', '', '1-12', unsqueeze_1.unsqueeze, unsqueeze_1.parseUnsqueezeAttributes],
|
|
['Unsqueeze', '', '13+', unsqueeze_1.unsqueezeV13],
|
|
['Xor', '', '7+', binaryOps.xor],
|
|
];
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./lib/onnxjs/backends/webgl/ops/batch-normalization.ts":
|
|
/*!**************************************************************!*\
|
|
!*** ./lib/onnxjs/backends/webgl/ops/batch-normalization.ts ***!
|
|
\**************************************************************/
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
// Licensed under the MIT License.
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.parseBatchNormalizationAttributes = exports.batchNormalization = void 0;
|
|
const attribute_with_cache_key_1 = __webpack_require__(/*! ../../../attribute-with-cache-key */ "./lib/onnxjs/attribute-with-cache-key.ts");
|
|
const glsl_source_1 = __webpack_require__(/*! ../glsl-source */ "./lib/onnxjs/backends/webgl/glsl-source.ts");
|
|
const types_1 = __webpack_require__(/*! ../types */ "./lib/onnxjs/backends/webgl/types.ts");
|
|
const batchNormalizationProgramMetadata = {
|
|
name: 'BatchNormalization',
|
|
inputNames: ['A', 'Scale', 'B', 'Mean', 'Variance'],
|
|
inputTypes: [types_1.TextureType.unpacked, types_1.TextureType.unpacked, types_1.TextureType.unpacked, types_1.TextureType.unpacked, types_1.TextureType.unpacked]
|
|
};
|
|
const batchNormalization = (inferenceHandler, inputs, attributes) => {
|
|
validateInputs(inputs);
|
|
const output = inferenceHandler.run(Object.assign(Object.assign({}, batchNormalizationProgramMetadata), { cacheHint: attributes.cacheKey, get: () => createBatchNormalizationProgramInfo(inferenceHandler, inputs, attributes) }), inputs);
|
|
return [output];
|
|
};
|
|
exports.batchNormalization = batchNormalization;
|
|
const parseBatchNormalizationAttributes = (node) => {
|
|
const epsilon = node.attributes.getFloat('epsilon', 1e-5);
|
|
const momentum = node.attributes.getFloat('momentum', 0.9);
|
|
const spatial = node.attributes.getInt('spatial', 1);
|
|
return (0, attribute_with_cache_key_1.createAttributeWithCacheKey)({ epsilon, momentum, spatial });
|
|
};
|
|
exports.parseBatchNormalizationAttributes = parseBatchNormalizationAttributes;
|
|
const createBatchNormalizationProgramInfo = (inferenceHandler, inputs, attributes) => {
|
|
const glsl = (0, glsl_source_1.getGlsl)(inferenceHandler.session.backend.glContext.version);
|
|
const rank = inputs[0].dims.length;
|
|
const [scaleWidth, scaleHeight] = inferenceHandler.calculateTextureWidthAndHeight(inputs[1].dims, types_1.TextureType.unpacked);
|
|
const shaderSource = `
|
|
float process(int[${rank}] indices) {
|
|
vec2 position = offsetToCoords(indices[1], ${scaleWidth}, ${scaleHeight});
|
|
float scale = getColorAsFloat(${glsl.texture2D}(Scale, position));
|
|
float mean = getColorAsFloat(${glsl.texture2D}(Mean, position));
|
|
float variance = getColorAsFloat(${glsl.texture2D}(Variance, position));
|
|
float b = getColorAsFloat(${glsl.texture2D}(B, position));
|
|
|
|
return scale * ( (_A(indices) - mean) / sqrt(variance + float(${attributes.epsilon})) ) + b;
|
|
}`;
|
|
return Object.assign(Object.assign({}, batchNormalizationProgramMetadata), { output: { dims: inputs[0].dims, type: inputs[0].type, textureType: types_1.TextureType.unpacked }, shaderSource });
|
|
};
|
|
const validateInputs = (inputs) => {
|
|
if (!inputs || inputs.length !== 5) {
|
|
throw new Error('BatchNormalization requires 5 inputs.');
|
|
}
|
|
const X = inputs[0];
|
|
const scale = inputs[1];
|
|
const B = inputs[2];
|
|
const mean = inputs[3];
|
|
const var_ = inputs[4];
|
|
// input should atleast have three dimensions - N,C,dim1,...,dimn
|
|
// other inputs can have only one dimensions
|
|
if (X.dims.length < 3 || scale.dims.length !== 1 || B.dims.length !== 1 || mean.dims.length !== 1 ||
|
|
var_.dims.length !== 1) {
|
|
throw new Error('invalid input shape.');
|
|
}
|
|
if (scale.dims[0] !== X.dims[1] || B.dims[0] !== X.dims[1] || mean.dims[0] !== X.dims[1] ||
|
|
var_.dims[0] !== X.dims[1]) {
|
|
throw new Error('invalid input shape.');
|
|
}
|
|
if ((X.type !== 'float32' && X.type !== 'float64') || (scale.type !== 'float32' && scale.type !== 'float64') ||
|
|
(B.type !== 'float32' && B.type !== 'float64') || (mean.type !== 'float32' && mean.type !== 'float64') ||
|
|
(var_.type !== 'float32' && var_.type !== 'float64')) {
|
|
throw new Error('invalid input tensor types.');
|
|
}
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./lib/onnxjs/backends/webgl/ops/binary-op.ts":
|
|
/*!****************************************************!*\
|
|
!*** ./lib/onnxjs/backends/webgl/ops/binary-op.ts ***!
|
|
\****************************************************/
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
// Licensed under the MIT License.
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.xor = exports.sub = exports.pRelu = exports.pow = exports.or = exports.mul = exports.less = exports.greater = exports.equal = exports.div = exports.and = exports.add = exports.glslPRelu = exports.glslPow = exports.glslXor = exports.glslOr = exports.glslAnd = exports.glslLess = exports.glslGreater = exports.glslEqual = exports.glslSub = exports.glslMul = exports.glslDiv = exports.glslAdd = void 0;
|
|
const util_1 = __webpack_require__(/*! ../../../util */ "./lib/onnxjs/util.ts");
|
|
const glsl_definitions_1 = __webpack_require__(/*! ../glsl-definitions */ "./lib/onnxjs/backends/webgl/glsl-definitions.ts");
|
|
const glsl_source_1 = __webpack_require__(/*! ../glsl-source */ "./lib/onnxjs/backends/webgl/glsl-source.ts");
|
|
const types_1 = __webpack_require__(/*! ../types */ "./lib/onnxjs/backends/webgl/types.ts");
|
|
function glslAdd() {
|
|
const name = 'add_';
|
|
const body = `
|
|
float ${name}(float a, float b) {
|
|
return a + b;
|
|
}
|
|
vec4 ${name}(vec4 v1, vec4 v2) {
|
|
return v1 + v2;
|
|
}
|
|
`;
|
|
return { body, name, type: glsl_definitions_1.FunctionType.ValueBased };
|
|
}
|
|
exports.glslAdd = glslAdd;
|
|
function glslDiv() {
|
|
const name = 'div_';
|
|
const body = `
|
|
float ${name}(float a, float b) {
|
|
return a / b;
|
|
}
|
|
vec4 ${name}(vec4 v1, vec4 v2) {
|
|
return v1 / v2;
|
|
}
|
|
`;
|
|
return { body, name, type: glsl_definitions_1.FunctionType.ValueBased };
|
|
}
|
|
exports.glslDiv = glslDiv;
|
|
function glslMul() {
|
|
const name = 'mul_';
|
|
const body = `
|
|
float ${name}(float a, float b) {
|
|
return a * b;
|
|
}
|
|
vec4 ${name}(vec4 v1, vec4 v2) {
|
|
return v1 * v2;
|
|
}
|
|
`;
|
|
return { body, name, type: glsl_definitions_1.FunctionType.ValueBased };
|
|
}
|
|
exports.glslMul = glslMul;
|
|
function glslSub() {
|
|
const name = 'sub_';
|
|
const body = `
|
|
float ${name}(float a, float b) {
|
|
return a - b;
|
|
}
|
|
vec4 ${name}(vec4 v1, vec4 v2) {
|
|
return v1 - v2;
|
|
}
|
|
`;
|
|
return { body, name, type: glsl_definitions_1.FunctionType.ValueBased };
|
|
}
|
|
exports.glslSub = glslSub;
|
|
function glslEqual() {
|
|
const name = 'equal_';
|
|
const body = `
|
|
float ${name}(float a, float b) {
|
|
return float(a == b);
|
|
}
|
|
vec4 ${name}(vec4 v1, vec4 v2) {
|
|
return vec4(equal(v1, v2));
|
|
}
|
|
`;
|
|
return { body, name, type: glsl_definitions_1.FunctionType.ValueBased };
|
|
}
|
|
exports.glslEqual = glslEqual;
|
|
function glslGreater() {
|
|
const name = 'greater_';
|
|
const body = `
|
|
float ${name}(float a, float b) {
|
|
return float(a > b);
|
|
}
|
|
vec4 ${name}(vec4 v1, vec4 v2) {
|
|
return vec4( v1.r > v2.r ,
|
|
v1.g > v2.g,
|
|
v1.b > v2.b,
|
|
v1.a > v2.a );
|
|
}
|
|
`;
|
|
return { body, name, type: glsl_definitions_1.FunctionType.ValueBased };
|
|
}
|
|
exports.glslGreater = glslGreater;
|
|
function glslLess() {
|
|
const name = 'less_';
|
|
const body = `
|
|
float ${name}(float a, float b) {
|
|
return float(a < b);
|
|
}
|
|
vec4 ${name}(vec4 v1, vec4 v2) {
|
|
return vec4( v1.r < v2.r ,
|
|
v1.g < v2.g,
|
|
v1.b < v2.b,
|
|
v1.a < v2.a );
|
|
}
|
|
`;
|
|
return { body, name, type: glsl_definitions_1.FunctionType.ValueBased };
|
|
}
|
|
exports.glslLess = glslLess;
|
|
function glslAnd() {
|
|
const name = 'and_';
|
|
const body = `
|
|
float ${name}(float a, float b) {
|
|
return float( bool(a) && bool(b) );
|
|
}
|
|
vec4 ${name}(vec4 v1, vec4 v2) {
|
|
bvec4 b1 = bvec4(v1);
|
|
bvec4 b2 = bvec4(v2);
|
|
return vec4( b1.r && b2.r ,
|
|
b1.g && b2.g,
|
|
b1.b && b2.b,
|
|
b1.a && b2.a );
|
|
}
|
|
`;
|
|
return { body, name, type: glsl_definitions_1.FunctionType.ValueBased };
|
|
}
|
|
exports.glslAnd = glslAnd;
|
|
function glslOr() {
|
|
const name = 'or_';
|
|
const body = `
|
|
float ${name}(float a, float b) {
|
|
return float( bool(a) || bool(b) );
|
|
}
|
|
vec4 ${name}(vec4 v1, vec4 v2) {
|
|
bvec4 b1 = bvec4(v1);
|
|
bvec4 b2 = bvec4(v2);
|
|
return vec4( b1.r || b2.r ,
|
|
b1.g || b2.g,
|
|
b1.b || b2.b,
|
|
b1.a || b2.a );
|
|
}
|
|
`;
|
|
return { body, name, type: glsl_definitions_1.FunctionType.ValueBased };
|
|
}
|
|
exports.glslOr = glslOr;
|
|
function glslXor() {
|
|
const name = 'xor_';
|
|
const body = `
|
|
float ${name}(float a, float b) {
|
|
return float( bool(a) ^^ bool(b) );
|
|
}
|
|
vec4 ${name}(vec4 v1, vec4 v2) {
|
|
bvec4 b1 = bvec4(v1);
|
|
bvec4 b2 = bvec4(v2);
|
|
return vec4( b1.r ^^ b2.r ,
|
|
b1.g ^^ b2.g,
|
|
b1.b ^^ b2.b,
|
|
b1.a ^^ b2.a );
|
|
}
|
|
`;
|
|
return { body, name, type: glsl_definitions_1.FunctionType.ValueBased };
|
|
}
|
|
exports.glslXor = glslXor;
|
|
function glslPow() {
|
|
return glslBuiltinBinary('pow');
|
|
}
|
|
exports.glslPow = glslPow;
|
|
function glslPRelu() {
|
|
const name = 'prelu_';
|
|
const body = `
|
|
float ${name}(float a, float b) {
|
|
return a < 0.0 ? a * b: a;
|
|
}
|
|
vec4 ${name}(vec4 v1, vec4 v2) {
|
|
return vec4(
|
|
v1.r < 0.0 ? v1.r * v2.r: v1.r,
|
|
v1.g < 0.0 ? v1.g * v2.g: v1.g,
|
|
v1.b < 0.0 ? v1.b * v2.b: v1.b,
|
|
v1.a < 0.0 ? v1.a * v2.a: v1.a
|
|
);
|
|
}
|
|
`;
|
|
return { body, name, type: glsl_definitions_1.FunctionType.ValueBased };
|
|
}
|
|
exports.glslPRelu = glslPRelu;
|
|
function glslBuiltinBinary(fname) {
|
|
const name = `${fname}_`;
|
|
const body = `
|
|
float ${name}(float a, float b) {
|
|
return ${fname}(a, b);
|
|
}
|
|
vec4 ${name}(vec4 v1, vec4 v2) {
|
|
return ${fname}(v1, v2);
|
|
}
|
|
`;
|
|
return { body, name, type: glsl_definitions_1.FunctionType.ValueBased };
|
|
}
|
|
const createBinaryProgramInfoLoader = (handler, inputs, glslFunc, outputTensorType = inputs[0].type, cacheKey) => {
|
|
const textureType = handler.session.pack ? types_1.TextureType.packed : types_1.TextureType.unpacked;
|
|
return {
|
|
name: glslFunc.name,
|
|
inputNames: ['A', 'B'],
|
|
inputTypes: [textureType, textureType],
|
|
cacheHint: cacheKey,
|
|
get: () => createBinaryProgramInfo(handler, inputs, glslFunc, outputTensorType)
|
|
};
|
|
};
|
|
const createBinaryProgramInfo = (handler, inputs, glslFunc, outputTensorType = inputs[0].type) => {
|
|
const textureType = handler.session.pack ? types_1.TextureType.packed : types_1.TextureType.unpacked;
|
|
const isBroadcast = !util_1.ShapeUtil.areEqual(inputs[0].dims, inputs[1].dims);
|
|
let outputShape = inputs[0].dims;
|
|
const usePackedTexture = handler.session.pack;
|
|
if (isBroadcast) {
|
|
const calculatedShape = util_1.BroadcastUtil.calcShape(inputs[0].dims, inputs[1].dims, false);
|
|
if (!calculatedShape) {
|
|
throw new Error('Can\'t perform binary op on the given tensors');
|
|
}
|
|
outputShape = calculatedShape;
|
|
const outputRank = outputShape.length;
|
|
const aRank = inputs[0].dims.length !== 0 ? inputs[0].dims.length : 1;
|
|
const bRank = inputs[1].dims.length !== 0 ? inputs[1].dims.length : 1;
|
|
const aBcast = inputs[0].dims.length !== 0 ? 'bcastIndices_A(indices, aindices);' : 'aindices[0] = 0;';
|
|
const bBcast = inputs[1].dims.length !== 0 ? 'bcastIndices_B(indices, bindices);' : 'bindices[0] = 0;';
|
|
const glsl = (0, glsl_source_1.getGlsl)(handler.session.backend.glContext.version);
|
|
const shaderSource = usePackedTexture ? `
|
|
${glslFunc.body}
|
|
void main() {
|
|
vec4 a = getAAtOutCoords();
|
|
vec4 b = getBAtOutCoords();
|
|
vec4 result = ${glslFunc.name}(a, b);
|
|
${glsl.output} = result;
|
|
}` :
|
|
`
|
|
${glslFunc.body}
|
|
float process(int indices[${outputRank}]) {
|
|
int aindices[${aRank}];
|
|
int bindices[${bRank}];
|
|
${aBcast}
|
|
${bBcast}
|
|
return ${glslFunc.name}(_A(aindices), _B(bindices));
|
|
}`;
|
|
return {
|
|
name: glslFunc.name,
|
|
inputNames: ['A', 'B'],
|
|
inputTypes: [textureType, textureType],
|
|
output: { dims: outputShape, type: outputTensorType, textureType },
|
|
shaderSource,
|
|
hasMain: usePackedTexture
|
|
};
|
|
}
|
|
const glsl = (0, glsl_source_1.getGlsl)(handler.session.backend.glContext.version);
|
|
const shaderSource = `
|
|
${glslFunc.body}
|
|
void main() {
|
|
vec4 v1 = ${glsl.texture2D}(A, TexCoords);
|
|
vec4 v2 = ${glsl.texture2D}(B, TexCoords);
|
|
vec4 result = ${glslFunc.name}(v1, v2);
|
|
${glsl.output} = result;
|
|
}
|
|
`;
|
|
return {
|
|
name: glslFunc.name,
|
|
inputNames: ['A', 'B'],
|
|
inputTypes: [textureType, textureType],
|
|
output: { dims: inputs[0].dims, type: outputTensorType, textureType },
|
|
shaderSource,
|
|
hasMain: true
|
|
};
|
|
};
|
|
const add = (handler, inputs) => [handler.run(createBinaryProgramInfoLoader(handler, inputs, glslAdd()), inputs)];
|
|
exports.add = add;
|
|
const and = (handler, inputs) => [handler.run(createBinaryProgramInfoLoader(handler, inputs, glslAnd(), 'bool'), inputs)];
|
|
exports.and = and;
|
|
const div = (handler, inputs) => [handler.run(createBinaryProgramInfoLoader(handler, inputs, glslDiv()), inputs)];
|
|
exports.div = div;
|
|
const equal = (handler, inputs) => [handler.run(createBinaryProgramInfoLoader(handler, inputs, glslEqual(), 'bool'), inputs)];
|
|
exports.equal = equal;
|
|
const greater = (handler, inputs) => [handler.run(createBinaryProgramInfoLoader(handler, inputs, glslGreater(), 'bool'), inputs)];
|
|
exports.greater = greater;
|
|
const less = (handler, inputs) => [handler.run(createBinaryProgramInfoLoader(handler, inputs, glslLess(), 'bool'), inputs)];
|
|
exports.less = less;
|
|
const mul = (handler, inputs) => [handler.run(createBinaryProgramInfoLoader(handler, inputs, glslMul()), inputs)];
|
|
exports.mul = mul;
|
|
const or = (handler, inputs) => [handler.run(createBinaryProgramInfoLoader(handler, inputs, glslOr(), 'bool'), inputs)];
|
|
exports.or = or;
|
|
const pow = (handler, inputs) => [handler.run(createBinaryProgramInfoLoader(handler, inputs, glslPow()), inputs)];
|
|
exports.pow = pow;
|
|
const pRelu = (handler, inputs) => [handler.run(createBinaryProgramInfoLoader(handler, inputs, glslPRelu()), inputs)];
|
|
exports.pRelu = pRelu;
|
|
const sub = (handler, inputs) => [handler.run(createBinaryProgramInfoLoader(handler, inputs, glslSub()), inputs)];
|
|
exports.sub = sub;
|
|
const xor = (handler, inputs) => [handler.run(createBinaryProgramInfoLoader(handler, inputs, glslXor(), 'bool'), inputs)];
|
|
exports.xor = xor;
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./lib/onnxjs/backends/webgl/ops/cast.ts":
|
|
/*!***********************************************!*\
|
|
!*** ./lib/onnxjs/backends/webgl/ops/cast.ts ***!
|
|
\***********************************************/
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
// Licensed under the MIT License.
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.parseCastAttributes = exports.cast = void 0;
|
|
const util_1 = __webpack_require__(/*! ../../../util */ "./lib/onnxjs/util.ts");
|
|
const cast = (handler, inputs, to) => {
|
|
validateInputs(inputs);
|
|
return [handler.cast(inputs[0], to)];
|
|
};
|
|
exports.cast = cast;
|
|
const parseCastAttributes = (node) => util_1.ProtoUtil.tensorDataTypeFromProto(node.attributes.getInt('to'));
|
|
exports.parseCastAttributes = parseCastAttributes;
|
|
const validateInputs = (inputs) => {
|
|
if (!inputs || inputs.length !== 1) {
|
|
throw new Error('Cast requires 1 input.');
|
|
}
|
|
if (inputs[0].type === 'string') {
|
|
throw new Error('Invalid input type.');
|
|
}
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./lib/onnxjs/backends/webgl/ops/concat-packed.ts":
|
|
/*!********************************************************!*\
|
|
!*** ./lib/onnxjs/backends/webgl/ops/concat-packed.ts ***!
|
|
\********************************************************/
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
// Licensed under the MIT License.
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.createPackedConcatProgramInfoLoader = void 0;
|
|
const glsl_source_1 = __webpack_require__(/*! ../glsl-source */ "./lib/onnxjs/backends/webgl/glsl-source.ts");
|
|
const types_1 = __webpack_require__(/*! ../types */ "./lib/onnxjs/backends/webgl/types.ts");
|
|
const utils_1 = __webpack_require__(/*! ../utils */ "./lib/onnxjs/backends/webgl/utils.ts");
|
|
const packing_utils_1 = __webpack_require__(/*! ./packing-utils */ "./lib/onnxjs/backends/webgl/ops/packing-utils.ts");
|
|
const createPackedConcatProgramMetadata = (inputCount, cacheHint) => ({
|
|
name: 'Concat (packed)',
|
|
inputNames: Array.from({ length: inputCount }, (v, i) => `X${i}`),
|
|
inputTypes: Array(inputCount).fill(types_1.TextureType.packed),
|
|
cacheHint
|
|
});
|
|
const createPackedConcatProgramInfo = (handler, metadata, inputs, axis) => {
|
|
const inputShape = inputs[0].dims.slice();
|
|
if (axis >= inputShape.length || axis < (-1 * inputShape.length)) {
|
|
throw new Error('axis specified for concat doesn\'t match input dimensionality');
|
|
}
|
|
if (axis < 0) {
|
|
axis = inputShape.length + axis;
|
|
}
|
|
// ensure all of the non-concatenated axes match each other
|
|
// calculate the shape of the output tensor while we do that
|
|
const outputShape = inputShape.slice(0);
|
|
for (let i = 1; i < inputs.length; i++) {
|
|
const dataNShape = inputs[i].dims.slice();
|
|
for (let axisIndex = 0; axisIndex < inputShape.length; axisIndex++) {
|
|
// add to the placeholder for computing output shape
|
|
if (axisIndex === axis) {
|
|
outputShape[axis] += dataNShape[axisIndex];
|
|
}
|
|
// ensure all non-cancatenated axes match each other
|
|
else if (inputShape[axisIndex] !== dataNShape[axisIndex]) {
|
|
throw new Error('non concat dimensions must match');
|
|
}
|
|
}
|
|
}
|
|
const rank = outputShape.length;
|
|
const coords = (0, packing_utils_1.getChannels)('coords', rank);
|
|
const dtype = (0, utils_1.getCoordsDataType)(rank);
|
|
const unpackChannel = (0, packing_utils_1.unpackFromChannel)();
|
|
const shapes = inputs.map(i => i.dims);
|
|
const channels = (0, utils_1.getGlChannels)(rank);
|
|
const offsets = new Array(shapes.length - 1);
|
|
offsets[0] = shapes[0][axis];
|
|
for (let i = 1; i < offsets.length; i++) {
|
|
offsets[i] = offsets[i - 1] + shapes[i][axis];
|
|
}
|
|
const channel = channels[axis];
|
|
const lastChannels = channels.slice(-2);
|
|
const allChannels = channels.join();
|
|
let getValueSnippet = `if (${channel} < ${offsets[0]}) {
|
|
return getChannel(
|
|
getX0(${allChannels}), vec2(${lastChannels.join()}));
|
|
}`;
|
|
for (let i = 1; i < offsets.length; i++) {
|
|
const shift = offsets[i - 1];
|
|
getValueSnippet += `
|
|
if (${channel} < ${offsets[i]} && ${channel} >= ${offsets[i - 1]}) {
|
|
return getChannel(
|
|
getX${i}(${getShiftedChannelsSnippet(channels, channel, shift)}),
|
|
vec2(${getShiftedChannelsSnippet(lastChannels, channel, shift)}));
|
|
}`;
|
|
}
|
|
const lastIndex = offsets.length;
|
|
const shift = offsets[offsets.length - 1];
|
|
getValueSnippet += `
|
|
return getChannel(
|
|
getX${lastIndex}(${getShiftedChannelsSnippet(channels, channel, shift)}),
|
|
vec2(${getShiftedChannelsSnippet(lastChannels, channel, shift)}));`;
|
|
const glsl = (0, glsl_source_1.getGlsl)(handler.session.backend.glContext.version);
|
|
const shaderSource = `
|
|
${unpackChannel}
|
|
float getValue(${channels.map(x => 'int ' + x)}) {
|
|
${getValueSnippet}
|
|
}
|
|
|
|
void main() {
|
|
${dtype} coords = getOutputCoords();
|
|
int lastDim = coords.${channels[rank - 1]};
|
|
coords.${channels[rank - 1]} = coords.${channels[rank - 2]};
|
|
coords.${channels[rank - 2]} = lastDim;
|
|
|
|
vec4 result = vec4(getValue(${coords}), 0., 0., 0.);
|
|
|
|
${coords[rank - 1]} = ${coords[rank - 1]} + 1;
|
|
if (${coords[rank - 1]} < ${outputShape[rank - 1]}) {
|
|
result.g = getValue(${coords});
|
|
}
|
|
|
|
${coords[rank - 2]} = ${coords[rank - 2]} + 1;
|
|
if (${coords[rank - 2]} < ${outputShape[rank - 2]}) {
|
|
result.a = getValue(${coords});
|
|
}
|
|
|
|
${coords[rank - 1]} = ${coords[rank - 1]} - 1;
|
|
if (${coords[rank - 2]} < ${outputShape[rank - 2]} &&
|
|
${coords[rank - 1]} < ${outputShape[rank - 1]}) {
|
|
result.b = getValue(${coords});
|
|
}
|
|
${glsl.output} = result;
|
|
}
|
|
`;
|
|
return Object.assign(Object.assign({}, metadata), { output: { dims: outputShape, type: inputs[0].type, textureType: types_1.TextureType.packed }, shaderSource, hasMain: true });
|
|
};
|
|
const createPackedConcatProgramInfoLoader = (handler, inputs, attributes) => {
|
|
const metadata = createPackedConcatProgramMetadata(inputs.length, attributes.cacheKey);
|
|
return Object.assign(Object.assign({}, metadata), { get: () => createPackedConcatProgramInfo(handler, metadata, inputs, attributes.axis) });
|
|
};
|
|
exports.createPackedConcatProgramInfoLoader = createPackedConcatProgramInfoLoader;
|
|
const getShiftedChannelsSnippet = (channels, channel, shift) => {
|
|
const channelIdx = channels.indexOf(channel);
|
|
const res = channels.map((c, idx) => {
|
|
if (idx === channelIdx) {
|
|
return `${c} - ${shift}`;
|
|
}
|
|
else {
|
|
return c;
|
|
}
|
|
});
|
|
return res.join();
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./lib/onnxjs/backends/webgl/ops/concat.ts":
|
|
/*!*************************************************!*\
|
|
!*** ./lib/onnxjs/backends/webgl/ops/concat.ts ***!
|
|
\*************************************************/
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
// Licensed under the MIT License.
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.parseConcatAttributes = exports.concat = void 0;
|
|
const attribute_with_cache_key_1 = __webpack_require__(/*! ../../../attribute-with-cache-key */ "./lib/onnxjs/attribute-with-cache-key.ts");
|
|
const types_1 = __webpack_require__(/*! ../types */ "./lib/onnxjs/backends/webgl/types.ts");
|
|
const concat_packed_1 = __webpack_require__(/*! ./concat-packed */ "./lib/onnxjs/backends/webgl/ops/concat-packed.ts");
|
|
const concat = (inferenceHandler, inputs, attributes) => {
|
|
validateInputs(inputs);
|
|
if (inferenceHandler.session.pack && inputs[0].dims.length > 1) {
|
|
const output = inferenceHandler.run((0, concat_packed_1.createPackedConcatProgramInfoLoader)(inferenceHandler, inputs, attributes), inputs);
|
|
return [output];
|
|
}
|
|
else {
|
|
const output = inferenceHandler.run(createUnpackedConcatProgramInfoLoader(inferenceHandler, inputs, attributes), inputs);
|
|
return [output];
|
|
}
|
|
};
|
|
exports.concat = concat;
|
|
const createUnpackedConcatProgramMetadata = (inputCount, cacheHint) => ({
|
|
name: 'Concat',
|
|
inputNames: Array.from({ length: inputCount }, (v, i) => `X${i}`),
|
|
inputTypes: Array(inputCount).fill(types_1.TextureType.unpacked),
|
|
cacheHint
|
|
});
|
|
const createUnpackedConcatProgramInfo = (handler, metadata, inputs, axis) => {
|
|
const inputShape = inputs[0].dims.slice();
|
|
if (axis >= inputShape.length || axis < (-1 * inputShape.length)) {
|
|
throw new Error('axis specified for concat doesn\'t match input dimensionality');
|
|
}
|
|
if (axis < 0) {
|
|
axis = inputShape.length + axis;
|
|
}
|
|
// ensure all of the non-concatenated axes match each other
|
|
// calculate the shape of the output tensor while we do that
|
|
const outputShape = inputShape.slice(0);
|
|
for (let i = 1; i < inputs.length; i++) {
|
|
const dataNShape = inputs[i].dims.slice();
|
|
for (let axisIndex = 0; axisIndex < inputShape.length; axisIndex++) {
|
|
// add to the placeholder for computing output shape
|
|
if (axisIndex === axis) {
|
|
outputShape[axis] += dataNShape[axisIndex];
|
|
}
|
|
// ensure all non-cancatenated axes match each other
|
|
else if (inputShape[axisIndex] !== dataNShape[axisIndex]) {
|
|
throw new Error('non concat dimensions must match');
|
|
}
|
|
}
|
|
}
|
|
const rank = outputShape.length;
|
|
const sizeInConcatAxis = new Array(inputs.length);
|
|
let previousSum = 0;
|
|
for (let i = 0; i < sizeInConcatAxis.length; ++i) {
|
|
previousSum += inputs[i].dims[axis];
|
|
sizeInConcatAxis[i] = previousSum;
|
|
}
|
|
let getTextureIndexWhereDataResidesMethod = '';
|
|
// in most cases linear search is sufficient, as in most scenarios, only 2 tensors are concatenated
|
|
if (inputs.length < 5) {
|
|
getTextureIndexWhereDataResidesMethod = getTextureIndexWhereDataResidesLinearSearch(sizeInConcatAxis);
|
|
}
|
|
else {
|
|
getTextureIndexWhereDataResidesMethod = getTextureIndexWhereDataResidesBinarySearch(sizeInConcatAxis);
|
|
}
|
|
const fetchDataFromCorrectTextureMethod = getFetchDataFromCorrectTextureMethod(inputs.length, rank);
|
|
const getSizeInConcatAxisValueFromIndexMethod = getGetSizeInConcatAxisValueFromIndexMethod(sizeInConcatAxis);
|
|
const shaderSource = `
|
|
${fetchDataFromCorrectTextureMethod}
|
|
${getSizeInConcatAxisValueFromIndexMethod}
|
|
${getTextureIndexWhereDataResidesMethod}
|
|
float process(int indices[${rank}]) {
|
|
int textureIndex = getTextureWhereDataResides (indices[${axis}]);
|
|
|
|
if(textureIndex != 0) {
|
|
indices[${axis}] = indices[${axis}] - int(getSizeInConcatAxisValueFromIndex(textureIndex-int(1)));
|
|
}
|
|
|
|
return fetchDataFromCorrectTexture(textureIndex, indices);
|
|
}`;
|
|
return Object.assign(Object.assign({}, metadata), { output: { dims: outputShape, type: inputs[0].type, textureType: types_1.TextureType.unpacked }, shaderSource });
|
|
};
|
|
const createUnpackedConcatProgramInfoLoader = (handler, inputs, attributes) => {
|
|
const metadata = createUnpackedConcatProgramMetadata(inputs.length, attributes.cacheKey);
|
|
return Object.assign(Object.assign({}, metadata), { get: () => createUnpackedConcatProgramInfo(handler, metadata, inputs, attributes.axis) });
|
|
};
|
|
const getTextureIndexWhereDataResidesLinearSearch = (sizeInConcatAxis) => {
|
|
const searchAxis = sizeInConcatAxis.map((size, i) => `if(index<${size}) {return ${i};}
|
|
`);
|
|
return `int getTextureWhereDataResides(int index) {
|
|
${searchAxis.join('')}
|
|
}`;
|
|
};
|
|
// TODO: Implement BinarySearch in GLSL
|
|
const getTextureIndexWhereDataResidesBinarySearch = (sizeInConcatAxis) => getTextureIndexWhereDataResidesLinearSearch(sizeInConcatAxis);
|
|
const getFetchDataFromCorrectTextureMethod = (numberOfTensors, tensorRank) => {
|
|
const codeLines = [`float fetchDataFromCorrectTexture(int textureIndex, int indices[${tensorRank}]) {`];
|
|
for (let i = 0; i < numberOfTensors; ++i) {
|
|
if (i === 0) {
|
|
codeLines.push('\t' +
|
|
`if (textureIndex == ${i}) { return _X${i}(indices); }`);
|
|
}
|
|
else if (i === numberOfTensors - 1) {
|
|
codeLines.push('\t' +
|
|
`else { return _X${i}(indices); }`);
|
|
}
|
|
else {
|
|
codeLines.push('\t' +
|
|
`else if (textureIndex == ${i}) { return _X${i}(indices); }`);
|
|
}
|
|
}
|
|
codeLines.push('\t' +
|
|
'}');
|
|
return codeLines.join('\n');
|
|
};
|
|
const getGetSizeInConcatAxisValueFromIndexMethod = (sizeInConcatAxis) => {
|
|
const codeLines = ['int getSizeInConcatAxisValueFromIndex(int index) {'];
|
|
for (let i = 0; i < sizeInConcatAxis.length; ++i) {
|
|
if (i === 0) {
|
|
codeLines.push('\t' +
|
|
`if (index == ${i}) { return ${sizeInConcatAxis[i]}; }`);
|
|
}
|
|
else if (i === sizeInConcatAxis.length - 1) {
|
|
codeLines.push('\t' +
|
|
`else { return ${sizeInConcatAxis[i]}; }`);
|
|
}
|
|
else {
|
|
codeLines.push('\t' +
|
|
`else if (index == ${i}) { return ${sizeInConcatAxis[i]}; }`);
|
|
}
|
|
}
|
|
codeLines.push('\t' +
|
|
'}');
|
|
return codeLines.join('\n');
|
|
};
|
|
const parseConcatAttributes = (node) => (0, attribute_with_cache_key_1.createAttributeWithCacheKey)({ axis: node.attributes.getInt('axis') });
|
|
exports.parseConcatAttributes = parseConcatAttributes;
|
|
const validateInputs = (inputs) => {
|
|
if (!inputs || inputs.length < 1) {
|
|
throw new Error('too few inputs');
|
|
}
|
|
const inputType = inputs[0].type;
|
|
const inputDimensionality = inputs[0].dims.length;
|
|
// TODO: Support string concat
|
|
if (inputType === 'string') {
|
|
throw new Error('string tensor is not supported yet');
|
|
}
|
|
for (const input of inputs) {
|
|
// make sure types of all inputs match
|
|
if (input.type !== inputType) {
|
|
throw new Error('input tensors should be one type');
|
|
}
|
|
// make sure the dimensionality of all inputs are the same
|
|
if (input.dims.length !== inputDimensionality) {
|
|
throw new Error('input tensors should have the same shape');
|
|
}
|
|
}
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./lib/onnxjs/backends/webgl/ops/conv-grouped.ts":
|
|
/*!*******************************************************!*\
|
|
!*** ./lib/onnxjs/backends/webgl/ops/conv-grouped.ts ***!
|
|
\*******************************************************/
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
// Licensed under the MIT License.
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.createUnpackedGroupedConvProgramInfoLoader = void 0;
|
|
const instrument_1 = __webpack_require__(/*! ../../../instrument */ "./lib/onnxjs/instrument.ts");
|
|
const glsl_source_1 = __webpack_require__(/*! ../glsl-source */ "./lib/onnxjs/backends/webgl/glsl-source.ts");
|
|
const types_1 = __webpack_require__(/*! ../types */ "./lib/onnxjs/backends/webgl/types.ts");
|
|
const conv_1 = __webpack_require__(/*! ./conv */ "./lib/onnxjs/backends/webgl/ops/conv.ts");
|
|
const fuse_utils_1 = __webpack_require__(/*! ./fuse-utils */ "./lib/onnxjs/backends/webgl/ops/fuse-utils.ts");
|
|
const createUnpackedGroupedConvProgramMetadata = (hasBias, cacheHint) => ({
|
|
name: 'GroupedConv',
|
|
inputNames: hasBias ? ['X', 'W', 'Bias'] : ['X', 'W'],
|
|
inputTypes: hasBias ? [types_1.TextureType.unpacked, types_1.TextureType.unpacked, types_1.TextureType.unpacked] :
|
|
[types_1.TextureType.unpacked, types_1.TextureType.unpacked],
|
|
cacheHint
|
|
});
|
|
const createUnpackedGroupedConvProgramInfo = (inferenceHandler, inputs, metadata, attributes) => {
|
|
const hasBias = inputs.length > 2;
|
|
const processBias = hasBias ? 'value += getBias(output_channel);' : '';
|
|
const xShape = inputs[0].dims.slice();
|
|
const wShape = inputs[1].dims.slice();
|
|
const outputChannelsPerGroup = wShape[0] / attributes.group;
|
|
instrument_1.Logger.verbose('GroupedConv', `autpPad:${attributes.autoPad}, dilations:${attributes.dilations}, group:${attributes.group}, kernelShape:${attributes.kernelShape}, pads:${attributes.pads}, strides:${attributes.strides}`);
|
|
const outputShape = (0, conv_1.calculateOutputShape)(xShape, wShape, attributes.dilations, attributes.pads, attributes.strides);
|
|
const glsl = (0, glsl_source_1.getGlsl)(inferenceHandler.session.backend.glContext.version);
|
|
const { activationFunction, applyActivation } = (0, fuse_utils_1.getActivationSnippet)(attributes);
|
|
const shaderSource = `
|
|
const ivec2 strides = ivec2(${attributes.strides[0]}, ${attributes.strides[1]});
|
|
const ivec2 pads = ivec2(${attributes.pads[0]}, ${attributes.pads[1]});
|
|
${activationFunction}
|
|
void main() {
|
|
ivec4 coords = getOutputCoords();
|
|
int batch = coords.x;
|
|
int output_channel = coords.y;
|
|
ivec2 xRCCorner = coords.zw * strides - pads;
|
|
int group_id = output_channel / ${outputChannelsPerGroup};
|
|
|
|
float value = 0.0;
|
|
for (int wInChannel = 0; wInChannel < ${wShape[1]}; wInChannel++) {
|
|
int input_channel = group_id * ${wShape[1]} + wInChannel;
|
|
for (int wHeight = 0; wHeight < ${wShape[2]}; wHeight++) {
|
|
int xHeight = xRCCorner.x + wHeight * ${attributes.dilations[0]};
|
|
|
|
if (xHeight < 0 || xHeight >= ${xShape[2]}) {
|
|
continue;
|
|
}
|
|
|
|
for (int wWidth = 0; wWidth < ${wShape[3]}; wWidth++) {
|
|
int xWidth = xRCCorner.y + wWidth * ${attributes.dilations[1]};
|
|
if (xWidth < 0 || xWidth >= ${xShape[3]}) {
|
|
continue;
|
|
}
|
|
|
|
float xVal = getX(batch, input_channel, xWidth, xHeight);
|
|
float wVal = getW(output_channel, wInChannel, wWidth, wHeight);
|
|
value += xVal*wVal;
|
|
}
|
|
}
|
|
}
|
|
${processBias}
|
|
${applyActivation}
|
|
${glsl.output} = vec4(value, .0, .0, .0);
|
|
}
|
|
`;
|
|
return Object.assign(Object.assign({}, metadata), { output: { dims: outputShape, type: inputs[0].type, textureType: types_1.TextureType.unpacked }, shaderSource, hasMain: true });
|
|
};
|
|
const createUnpackedGroupedConvProgramInfoLoader = (inferenceHandler, inputs, attributes) => {
|
|
const metadata = createUnpackedGroupedConvProgramMetadata(inputs.length > 2, attributes.cacheKey);
|
|
return Object.assign(Object.assign({}, metadata), { get: () => createUnpackedGroupedConvProgramInfo(inferenceHandler, inputs, metadata, attributes) });
|
|
};
|
|
exports.createUnpackedGroupedConvProgramInfoLoader = createUnpackedGroupedConvProgramInfoLoader;
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./lib/onnxjs/backends/webgl/ops/conv-pack.ts":
|
|
/*!****************************************************!*\
|
|
!*** ./lib/onnxjs/backends/webgl/ops/conv-pack.ts ***!
|
|
\****************************************************/
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
// Licensed under the MIT License.
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.conv2DPacked = exports.conv2DPackedPointwise = void 0;
|
|
const conv_1 = __webpack_require__(/*! ./conv */ "./lib/onnxjs/backends/webgl/ops/conv.ts");
|
|
const im2col_pack_1 = __webpack_require__(/*! ./im2col-pack */ "./lib/onnxjs/backends/webgl/ops/im2col-pack.ts");
|
|
const matmul_pack_1 = __webpack_require__(/*! ./matmul-pack */ "./lib/onnxjs/backends/webgl/ops/matmul-pack.ts");
|
|
const conv2DPackedPointwise = (inferenceHandler, inputs, attributes) => {
|
|
const xshape = inputs[0].dims;
|
|
const kshape = inputs[1].dims;
|
|
const outputShape = (0, conv_1.calculateOutputShape)(xshape, kshape, attributes.dilations, attributes.pads, attributes.strides);
|
|
const reshapedX = inferenceHandler.reshapePacked(inputs[0], [xshape[1], xshape[2] * xshape[3]]);
|
|
const reshapedK = inferenceHandler.reshapePacked(inputs[1], [kshape[0], kshape[1]]);
|
|
const matmulInputs = inputs.length > 2 ? [reshapedK, reshapedX, inputs[2]] : [reshapedK, reshapedX];
|
|
const matmulOutput = inferenceHandler.run((0, matmul_pack_1.createPackedMatmulProgramInfoLoader)(inferenceHandler, matmulInputs, attributes), matmulInputs);
|
|
return inferenceHandler.reshapePacked(matmulOutput, outputShape);
|
|
};
|
|
exports.conv2DPackedPointwise = conv2DPackedPointwise;
|
|
const conv2DPacked = (inferenceHandler, inputs, attributes) => {
|
|
const xshape = inputs[0].dims;
|
|
const kshape = inputs[1].dims;
|
|
const outputShape = (0, conv_1.calculateOutputShape)(xshape, kshape, attributes.dilations, attributes.pads, attributes.strides);
|
|
// run im2col
|
|
const im2colOutput = inferenceHandler.run((0, im2col_pack_1.createPackedIm2ColProgramInfoLoader)(inferenceHandler, inputs[0], inputs[1], outputShape, attributes), [inputs[0]]);
|
|
// reshape kernel
|
|
const kernelReshaped = inferenceHandler.reshapePacked(inputs[1], [kshape[0], kshape[1] * kshape[2] * kshape[3]]);
|
|
// run matmul
|
|
const matmulInputs = (inputs.length === 3) ? [kernelReshaped, im2colOutput, inputs[2]] : [kernelReshaped, im2colOutput];
|
|
const matmulOutput = inferenceHandler.run((0, matmul_pack_1.createPackedMatmulProgramInfoLoader)(inferenceHandler, matmulInputs, attributes), matmulInputs);
|
|
// reshape output
|
|
const outputReshaped = inferenceHandler.reshapePacked(matmulOutput, outputShape);
|
|
return outputReshaped;
|
|
};
|
|
exports.conv2DPacked = conv2DPacked;
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./lib/onnxjs/backends/webgl/ops/conv-transpose.ts":
|
|
/*!*********************************************************!*\
|
|
!*** ./lib/onnxjs/backends/webgl/ops/conv-transpose.ts ***!
|
|
\*********************************************************/
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
// Licensed under the MIT License.
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.parseConvTransposeAttributes = exports.convTranspose = void 0;
|
|
const attribute_with_cache_key_1 = __webpack_require__(/*! ../../../attribute-with-cache-key */ "./lib/onnxjs/attribute-with-cache-key.ts");
|
|
const glsl_source_1 = __webpack_require__(/*! ../glsl-source */ "./lib/onnxjs/backends/webgl/glsl-source.ts");
|
|
const types_1 = __webpack_require__(/*! ../types */ "./lib/onnxjs/backends/webgl/types.ts");
|
|
const fuse_utils_1 = __webpack_require__(/*! ./fuse-utils */ "./lib/onnxjs/backends/webgl/ops/fuse-utils.ts");
|
|
const computeTotalPad = (inDim, stride, adj, kernel, dilation, outSize) => (inDim - 1) * stride + adj + (kernel - 1) * dilation + 1 - outSize;
|
|
const distributePadding = (totalPad, autoPad, pads, head, tail) => {
|
|
const smallPad = Math.floor(totalPad / 2);
|
|
if (autoPad === 'SAME_UPPER') {
|
|
pads[head] = smallPad;
|
|
pads[tail] = totalPad - smallPad;
|
|
}
|
|
else if (autoPad === 'SAME_LOWER') {
|
|
pads[head] = totalPad - smallPad;
|
|
pads[tail] = smallPad;
|
|
}
|
|
};
|
|
const calculateOutputShapeAndPads = (inputShape, kernelShape, dilations, autoPad, pads, strides, outputPadding, outputShape) => {
|
|
const spatialRank = inputShape.length - 2;
|
|
const updateShape = outputShape.length === 0;
|
|
for (let i = 0; i < spatialRank; ++i) {
|
|
const outSize = updateShape ? inputShape[i + 2] * strides[i] : outputShape[i];
|
|
const totalPad = computeTotalPad(inputShape[i + 2], strides[i], pads[i], kernelShape[i], dilations[i], outSize);
|
|
distributePadding(totalPad, autoPad, pads, i, i + spatialRank);
|
|
if (updateShape) {
|
|
outputShape.push(strides[i] * (inputShape[i + 2] - 1) + outputPadding[i] + (kernelShape[i] - 1) * dilations[i] + 1 -
|
|
pads[i] - pads[i + spatialRank]);
|
|
}
|
|
}
|
|
};
|
|
const convTranspose = (inferenceHandler, inputs, attributes) => {
|
|
validateInputs(inputs, attributes); // currently will fail if not convTranspose2D
|
|
return convTranspose2d(inferenceHandler, inputs, attributes);
|
|
};
|
|
exports.convTranspose = convTranspose;
|
|
const convTranspose2d = (inferenceHandler, inputs, attributes) => {
|
|
const adjustedAttributes = getAdjustedConvTransposeAttributes(attributes, inputs);
|
|
return [convTranspose2DUnpacked(inferenceHandler, inputs, adjustedAttributes)];
|
|
};
|
|
const createConvTransposeProgramMetadata = (hasBias, cacheHint) => ({
|
|
name: 'ConvTranspose',
|
|
inputNames: hasBias ? ['X', 'W', 'B'] : ['X', 'W'],
|
|
inputTypes: hasBias ? [types_1.TextureType.unpacked, types_1.TextureType.unpacked, types_1.TextureType.unpacked] :
|
|
[types_1.TextureType.unpacked, types_1.TextureType.unpacked],
|
|
cacheHint
|
|
});
|
|
const createUnpackedConvTransposeProgramInfo = (inferenceHandler, inputs, metadata, attributes) => {
|
|
const hasBias = inputs.length > 2;
|
|
const valueInit = hasBias ? 'getB(output_channel)' : '0.0';
|
|
const xShape = inputs[0].dims;
|
|
const wShape = inputs[1].dims;
|
|
const outputChannelsPerGroup = wShape[1];
|
|
const inputChannelsPerGroup = wShape[0] / attributes.group;
|
|
const outputShape = [inputs[0].dims[0], inputs[1].dims[1] * attributes.group, ...attributes.outputShape];
|
|
const glsl = (0, glsl_source_1.getGlsl)(inferenceHandler.session.backend.glContext.version);
|
|
const { activationFunction, applyActivation } = (0, fuse_utils_1.getActivationSnippet)(attributes);
|
|
const shaderSource = `
|
|
const ivec2 strides = ivec2(${attributes.strides[0]}, ${attributes.strides[1]});
|
|
const ivec2 pads = ivec2(${attributes.pads[0]}, ${attributes.pads[1]});
|
|
${activationFunction}
|
|
void main() {
|
|
ivec4 coords = getOutputCoords();
|
|
int batch = coords.x;
|
|
int output_channel = coords.y;
|
|
|
|
ivec2 loc = coords.zw + pads;
|
|
|
|
int group_id = output_channel / ${outputChannelsPerGroup};
|
|
int wOutChannel = output_channel - group_id * ${outputChannelsPerGroup};
|
|
|
|
float value = ${valueInit};
|
|
for (int inChannelOffset = 0; inChannelOffset < ${inputChannelsPerGroup}; inChannelOffset++) {
|
|
int input_channel = group_id * ${inputChannelsPerGroup} + inChannelOffset;
|
|
for (int wWOff = 0; wWOff < ${wShape[2]}; wWOff++) {
|
|
for (int wHOff = 0; wHOff < ${wShape[3]}; wHOff++) {
|
|
ivec2 wOff = ivec2(wWOff * ${attributes.dilations[0]}, wHOff * ${attributes.dilations[1]});
|
|
ivec2 wLoc = loc - wOff;
|
|
ivec2 wLocIn = wLoc / strides;
|
|
if (
|
|
wLocIn * strides == wLoc &&
|
|
wLocIn.x >= 0 && wLocIn.x < ${xShape[2]} &&
|
|
wLocIn.y >= 0 && wLocIn.y < ${xShape[3]}
|
|
) {
|
|
float xVal = getX(batch, input_channel, wLocIn.y, wLocIn.x);
|
|
float wVal = getW(input_channel, wOutChannel, wHOff, wWOff);
|
|
value += xVal * wVal;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
${applyActivation}
|
|
${glsl.output} = vec4(value, .0, .0, .0);
|
|
}
|
|
`;
|
|
return Object.assign(Object.assign({}, metadata), { output: { dims: outputShape, type: inputs[0].type, textureType: types_1.TextureType.unpacked }, shaderSource, hasMain: true });
|
|
};
|
|
const createUnpackedConvTransposeProgramInfoLoader = (inferenceHandler, inputs, attributes) => {
|
|
const metadata = createConvTransposeProgramMetadata(inputs.length > 2, attributes.cacheKey);
|
|
return Object.assign(Object.assign({}, metadata), { get: () => createUnpackedConvTransposeProgramInfo(inferenceHandler, inputs, metadata, attributes) });
|
|
};
|
|
const convTranspose2DUnpacked = (inferenceHandler, inputs, attributes) => {
|
|
const result = inferenceHandler.run(createUnpackedConvTransposeProgramInfoLoader(inferenceHandler, inputs, attributes), inputs);
|
|
return result;
|
|
};
|
|
const getAdjustedConvTransposeAttributes = (attributes, inputs) => {
|
|
const kernelShape = attributes.kernelShape.slice();
|
|
// if kernelShape is not specified in the attributes of this op, infer it from the weight tensor dims
|
|
if (attributes.kernelShape.length === 0) {
|
|
for (let i = 2; i < inputs[1].dims.length; ++i) {
|
|
kernelShape.push(inputs[1].dims[i]);
|
|
}
|
|
}
|
|
const pads = attributes.pads.slice();
|
|
const outputShape = attributes.outputShape.slice();
|
|
const inputShape = inputs[0].dims;
|
|
// If outputShape is not specified in the attributes of this op, infer it from the parameters
|
|
// Similarly, automatically infer pads if not specified
|
|
calculateOutputShapeAndPads(inputShape, kernelShape, attributes.dilations, attributes.autoPad, pads, attributes.strides, attributes.outputPadding, outputShape);
|
|
// always return a new object so does not modify the original attributes
|
|
const newAttributes = Object.assign({}, attributes);
|
|
Object.assign(newAttributes, { kernelShape, pads, outputShape, cacheKey: attributes.cacheKey });
|
|
return newAttributes;
|
|
};
|
|
const parseConvTransposeAttributes = (node) => {
|
|
const attributes = node.attributes;
|
|
const activationAttributes = (0, fuse_utils_1.parseInternalActivationAttributes)(attributes);
|
|
// TODO : Make this generic enough to compute default attributes for multi-dimensional conv
|
|
const autoPad = attributes.getString('auto_pad', 'NOTSET');
|
|
const dilations = attributes.getInts('dilations', [1, 1]);
|
|
const group = attributes.getInt('group', 1);
|
|
const kernelShape = attributes.getInts('kernel_shape', []);
|
|
const outputPadding = attributes.getInts('output_padding', [0, 0]);
|
|
const outputShape = attributes.getInts('output_shape', []);
|
|
const pads = attributes.getInts('pads', [0, 0, 0, 0]);
|
|
const strides = attributes.getInts('strides', [1, 1]);
|
|
return (0, attribute_with_cache_key_1.createAttributeWithCacheKey)(Object.assign({ autoPad, dilations, group, kernelShape, outputPadding, outputShape, pads, strides }, activationAttributes));
|
|
};
|
|
exports.parseConvTransposeAttributes = parseConvTransposeAttributes;
|
|
const validateInputs = (inputs, attributes) => {
|
|
// Refer to the below link for all input checks
|
|
// https://github.com/onnx/onnx/blob/main/docs/Operators.md#Conv
|
|
if (!inputs || (inputs.length !== 2 && inputs.length !== 3)) {
|
|
throw new Error('Conv requires 2 or 3 inputs');
|
|
}
|
|
// TODO : Need to add support for multi-dimensional conv
|
|
if (inputs[0].dims.length !== 4 || inputs[1].dims.length !== 4) {
|
|
throw new Error('currently only support 2-dimensional conv');
|
|
}
|
|
// FILTER_IN_CHANNEL should be equal to DATA_CHANNEL
|
|
const dataChannel = inputs[0].dims[1];
|
|
const filterInChannel = inputs[1].dims[0];
|
|
if (dataChannel !== filterInChannel) {
|
|
throw new Error('FILTER_IN_CHANNEL should be equal to DATA_CHANNEL');
|
|
}
|
|
const featureMaps = inputs[1].dims[1] * attributes.group;
|
|
// if bias is provided it should be 1D and the number of elements should be equal to the number of feature maps
|
|
if (inputs.length === 3 && (inputs[2].dims.length !== 1 || inputs[2].dims[0] !== featureMaps)) {
|
|
throw new Error('invalid bias');
|
|
}
|
|
const spatialRank = inputs[0].dims.length - 2;
|
|
// wrong dilations dimension
|
|
if (attributes.dilations.length !== spatialRank) {
|
|
throw new Error(`dilations should be ${spatialRank}D`);
|
|
}
|
|
// Wrong strides dimension
|
|
if (attributes.strides.length !== spatialRank) {
|
|
throw new Error(`strides should be ${spatialRank}D`);
|
|
}
|
|
// Wrong pads dimension
|
|
if (attributes.pads.length !== spatialRank * 2) {
|
|
throw new Error(`pads should be ${spatialRank * 2}D`);
|
|
}
|
|
// Wrong output padding dimension
|
|
if (attributes.outputPadding.length !== spatialRank) {
|
|
throw new Error(`output_padding should be ${spatialRank}D`);
|
|
}
|
|
// if kernelShape is specified, it's data length must be 2 less than dims length of the weights tensor
|
|
// (the first 2 dims are batch_size and channels)
|
|
if (attributes.kernelShape.length !== 0 && attributes.kernelShape.length !== inputs[1].dims.length - 2) {
|
|
throw new Error('invalid kernel shape');
|
|
}
|
|
// as with kernelShape, must have same number of spatial dims as input
|
|
if (attributes.outputShape.length !== 0 && attributes.outputShape.length !== inputs[0].dims.length - 2) {
|
|
throw new Error('invalid output shape');
|
|
}
|
|
// TODO : Need to add support for float64
|
|
if (inputs[0].type !== 'float32' || inputs[1].type !== 'float32') {
|
|
throw new Error('ConvTranspose input(X,W) should be float tensor');
|
|
}
|
|
if (inputs.length === 3 && inputs[2].type !== 'float32') {
|
|
throw new Error('ConvTranspose input(bias) should be float tensor');
|
|
}
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./lib/onnxjs/backends/webgl/ops/conv.ts":
|
|
/*!***********************************************!*\
|
|
!*** ./lib/onnxjs/backends/webgl/ops/conv.ts ***!
|
|
\***********************************************/
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
// Licensed under the MIT License.
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.parseConvAttributes = exports.conv = exports.calculateOutputShape = void 0;
|
|
const attribute_with_cache_key_1 = __webpack_require__(/*! ../../../attribute-with-cache-key */ "./lib/onnxjs/attribute-with-cache-key.ts");
|
|
const util_1 = __webpack_require__(/*! ../../../util */ "./lib/onnxjs/util.ts");
|
|
const conv_grouped_1 = __webpack_require__(/*! ./conv-grouped */ "./lib/onnxjs/backends/webgl/ops/conv-grouped.ts");
|
|
const conv_pack_1 = __webpack_require__(/*! ./conv-pack */ "./lib/onnxjs/backends/webgl/ops/conv-pack.ts");
|
|
const dot_product_1 = __webpack_require__(/*! ./dot-product */ "./lib/onnxjs/backends/webgl/ops/dot-product.ts");
|
|
const fuse_utils_1 = __webpack_require__(/*! ./fuse-utils */ "./lib/onnxjs/backends/webgl/ops/fuse-utils.ts");
|
|
const im2col_1 = __webpack_require__(/*! ./im2col */ "./lib/onnxjs/backends/webgl/ops/im2col.ts");
|
|
const matmul_1 = __webpack_require__(/*! ./matmul */ "./lib/onnxjs/backends/webgl/ops/matmul.ts");
|
|
const calculateOutputShape = (inputShape, kernelShape, dilations, adjustPads, strides) => {
|
|
const batchSize = inputShape[0];
|
|
const inputSpatialShape = inputShape.slice(2);
|
|
const spatialRank = inputSpatialShape.length;
|
|
const outChannels = kernelShape[0];
|
|
const kernelSpatialShape = kernelShape.slice(2);
|
|
const dilatedKernelShape = kernelSpatialShape.map((v, i) => v + (v - 1) * (dilations[i] - 1));
|
|
const inputSpatialShapeWithPad = inputSpatialShape.map((v, i) => v + adjustPads[i] + adjustPads[i + spatialRank]);
|
|
const outputSpatialShape = inputSpatialShapeWithPad.map((v, i) => Math.floor((v - dilatedKernelShape[i] + strides[i]) / strides[i]));
|
|
const outputShape = [batchSize, outChannels].concat(...outputSpatialShape);
|
|
return outputShape;
|
|
};
|
|
exports.calculateOutputShape = calculateOutputShape;
|
|
const conv = (inferenceHandler, inputs, attributes) => {
|
|
validateInputs(inputs, attributes); // currently will fail if not conv2D
|
|
return conv2d(inferenceHandler, inputs, attributes);
|
|
};
|
|
exports.conv = conv;
|
|
const conv2d = (inferenceHandler, inputs, attributes) => {
|
|
const adjustedAttributes = getAdjustedConvAttributes(attributes, inputs);
|
|
const packMode = inferenceHandler.session.pack;
|
|
const isPointwise = adjustedAttributes.kernelShape[0] === 1 && adjustedAttributes.kernelShape[1] === 1;
|
|
if (adjustedAttributes.group > 1) {
|
|
const result = inferenceHandler.run((0, conv_grouped_1.createUnpackedGroupedConvProgramInfoLoader)(inferenceHandler, inputs, adjustedAttributes), inputs);
|
|
return [result];
|
|
}
|
|
else if (isPointwise && packMode) {
|
|
return [conv2DUnpackedPointwise(inferenceHandler, inputs, adjustedAttributes)];
|
|
}
|
|
else if (packMode && inputs[0].dims.length === 4 && inputs[0].dims[0] === 1 && !isPointwise) {
|
|
return [(0, conv_pack_1.conv2DPacked)(inferenceHandler, inputs, adjustedAttributes)];
|
|
}
|
|
else {
|
|
return [conv2DUnpacked(inferenceHandler, inputs, adjustedAttributes)];
|
|
}
|
|
};
|
|
const conv2DUnpackedPointwise = (inferenceHandler, inputs, attributes) => {
|
|
const xshape = inputs[0].dims;
|
|
const kshape = inputs[1].dims;
|
|
const outputShape = (0, exports.calculateOutputShape)(xshape, kshape, attributes.dilations, attributes.pads, attributes.strides);
|
|
const reshapedX = inferenceHandler.reshapeUnpacked(inputs[0], [xshape[1], xshape[2] * xshape[3]]);
|
|
const reshapedK = inferenceHandler.reshapeUnpacked(inputs[1], [kshape[0], kshape[1]]);
|
|
const matmulInputs = inputs.length > 2 ? [reshapedK, reshapedX, inputs[2]] : [reshapedK, reshapedX];
|
|
const matmulOutput = inferenceHandler.run((0, matmul_1.createMatmulProgramInfoLoader)(matmulInputs, attributes), matmulInputs);
|
|
return inferenceHandler.reshapeUnpacked(matmulOutput, outputShape);
|
|
};
|
|
const conv2DUnpacked = (inferenceHandler, inputs, attributes) => {
|
|
const xshape = inputs[0].dims;
|
|
const kshape = inputs[1].dims;
|
|
const outputShape = (0, exports.calculateOutputShape)(xshape, kshape, attributes.dilations, attributes.pads, attributes.strides);
|
|
const xIm2Col = inferenceHandler.run((0, im2col_1.createIm2ColProgramInfoLoader)(inferenceHandler, inputs[0], inputs[1], outputShape, attributes), [inputs[0]]);
|
|
const dotProductInputs = inputs.length === 3 ? [xIm2Col, inputs[1], inputs[2]] : [xIm2Col, inputs[1]];
|
|
const output = inferenceHandler.run((0, dot_product_1.createDotProductProgramInfoLoader)(inferenceHandler, inputs, outputShape, attributes), dotProductInputs);
|
|
return output;
|
|
};
|
|
const getAdjustedConvAttributes = (attributes, inputs) => {
|
|
const kernelShape = attributes.kernelShape.slice();
|
|
// if kernelShape is not specified in the attributes of this op, infer it from the weight tensor dims
|
|
if (attributes.kernelShape.length === 0) {
|
|
for (let i = 2; i < inputs[1].dims.length; ++i) {
|
|
kernelShape.push(inputs[1].dims[i]);
|
|
}
|
|
}
|
|
const pads = attributes.pads.slice();
|
|
util_1.PoolConvUtil.adjustPadsBasedOnAutoPad(inputs[0].dims, attributes.strides, attributes.dilations, kernelShape, pads, attributes.autoPad);
|
|
// always return a new object so does not modify the original attributes
|
|
const newAttributes = Object.assign({}, attributes);
|
|
Object.assign(newAttributes, { kernelShape, pads, cacheKey: attributes.cacheKey });
|
|
return newAttributes;
|
|
};
|
|
const parseConvAttributes = (node) => {
|
|
const attributes = node.attributes;
|
|
const activationAttributes = (0, fuse_utils_1.parseInternalActivationAttributes)(attributes);
|
|
// TODO : Make this generic enough to compute default attributes for multi-dimensional conv
|
|
const autoPad = attributes.getString('auto_pad', 'NOTSET');
|
|
const dilations = attributes.getInts('dilations', [1, 1]);
|
|
const group = attributes.getInt('group', 1);
|
|
const kernelShape = attributes.getInts('kernel_shape', []);
|
|
const pads = attributes.getInts('pads', [0, 0, 0, 0]);
|
|
const strides = attributes.getInts('strides', [1, 1]);
|
|
return (0, attribute_with_cache_key_1.createAttributeWithCacheKey)(Object.assign({ autoPad, dilations, group, kernelShape, pads, strides }, activationAttributes));
|
|
};
|
|
exports.parseConvAttributes = parseConvAttributes;
|
|
const validateInputs = (inputs, attributes) => {
|
|
// Refer to the below link for all input checks
|
|
// https://github.com/onnx/onnx/blob/main/docs/Operators.md#Conv
|
|
if (!inputs || (inputs.length !== 2 && inputs.length !== 3)) {
|
|
throw new Error('Conv requires 2 or 3 inputs');
|
|
}
|
|
// TODO : Need to add support for multi-dimensional conv
|
|
if (inputs[0].dims.length !== 4 || inputs[1].dims.length !== 4) {
|
|
throw new Error('currently only support 2-dimensional conv');
|
|
}
|
|
// FILTER_IN_CHANNEL should be equal to DATA_CHANNEL
|
|
const dataChannel = inputs[0].dims[1];
|
|
const filterInChannel = inputs[1].dims[1] * attributes.group;
|
|
if (dataChannel !== filterInChannel) {
|
|
throw new Error('FILTER_IN_CHANNEL should be equal to DATA_CHANNEL');
|
|
}
|
|
// if bias is provided it should be 1D and the number of elements should be equal to the number of feature maps
|
|
if (inputs.length === 3 && (inputs[2].dims.length !== 1 || inputs[1].dims[0] !== inputs[2].dims[0])) {
|
|
throw new Error('invalid bias');
|
|
}
|
|
const spatialRank = inputs[0].dims.length - 2;
|
|
// wrong dilations dimension
|
|
if (attributes.dilations.length !== spatialRank) {
|
|
throw new Error(`dilations should be ${spatialRank}D`);
|
|
}
|
|
// Wrong strides dimension
|
|
if (attributes.strides.length !== spatialRank) {
|
|
throw new Error(`strides should be ${spatialRank}D`);
|
|
}
|
|
// Wrong pads dimension
|
|
if (attributes.pads.length !== spatialRank * 2) {
|
|
throw new Error(`pads should be ${spatialRank * 2}D`);
|
|
}
|
|
// if kernelShape is specified, it's data length must be 2 less than dims length of the weights tensor
|
|
// (the first 2 dims are batch_size and channels)
|
|
if (attributes.kernelShape.length !== 0 && attributes.kernelShape.length !== inputs[1].dims.length - 2) {
|
|
throw new Error('invalid kernel shape');
|
|
}
|
|
// TODO : Need to add support for float64
|
|
if (inputs[0].type !== 'float32' || inputs[1].type !== 'float32') {
|
|
throw new Error('Conv input(X,W) should be float tensor');
|
|
}
|
|
if (inputs.length === 3 && inputs[2].type !== 'float32') {
|
|
throw new Error('Conv input(bias) should be float tensor');
|
|
}
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./lib/onnxjs/backends/webgl/ops/depth-to-space.ts":
|
|
/*!*********************************************************!*\
|
|
!*** ./lib/onnxjs/backends/webgl/ops/depth-to-space.ts ***!
|
|
\*********************************************************/
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
// Licensed under the MIT License.
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.parseDepthToSpaceAttributes = exports.depthToSpace = void 0;
|
|
const transpose_1 = __webpack_require__(/*! ./transpose */ "./lib/onnxjs/backends/webgl/ops/transpose.ts");
|
|
const depthToSpace = (inferenceHandler, inputs, attributes) => {
|
|
validateInputs(inputs);
|
|
const blocksize = attributes.blocksize;
|
|
const blocksizeSqr = blocksize * blocksize;
|
|
const transposePerm = attributes.mode === 'DCR' ? [0, 3, 4, 1, 5, 2] : [0, 1, 4, 2, 5, 3];
|
|
const firstReshapeShape = attributes.mode === 'DCR' ?
|
|
[
|
|
inputs[0].dims[0], blocksize, blocksize, inputs[0].dims[1] / blocksizeSqr, inputs[0].dims[2],
|
|
inputs[0].dims[3]
|
|
] :
|
|
[
|
|
inputs[0].dims[0], inputs[0].dims[1] / blocksizeSqr, blocksize, blocksize, inputs[0].dims[2],
|
|
inputs[0].dims[3]
|
|
];
|
|
// const transpose = new WebGLTranspose();
|
|
// const attributes = new Attribute(undefined);
|
|
// attributes.set('perm', 'ints', transposePerm);
|
|
// transpose.initialize(attributes);
|
|
// First reshape
|
|
const firstReshapedTensor = inferenceHandler.reshapeUnpacked(inputs[0], firstReshapeShape);
|
|
// transpose
|
|
const transposeAttributes = { perm: transposePerm, cacheKey: `${transposePerm}` };
|
|
const [transposeOutput] = (0, transpose_1.transpose)(inferenceHandler, [firstReshapedTensor], transposeAttributes);
|
|
// Second reshape
|
|
const secondReshapeShape = [
|
|
inputs[0].dims[0], inputs[0].dims[1] / blocksizeSqr, inputs[0].dims[2] * blocksize,
|
|
inputs[0].dims[3] * blocksize
|
|
];
|
|
const result = inferenceHandler.reshapeUnpacked(transposeOutput, secondReshapeShape);
|
|
return [result];
|
|
};
|
|
exports.depthToSpace = depthToSpace;
|
|
const parseDepthToSpaceAttributes = (node) => {
|
|
// processing node attributes
|
|
const blocksize = node.attributes.getInt('blocksize');
|
|
if (blocksize < 1) {
|
|
throw new Error(`blocksize must be >= 1, but got : ${blocksize} for DepthToSpace`);
|
|
}
|
|
const mode = node.attributes.getString('mode', 'DCR');
|
|
if (mode !== 'DCR' && mode !== 'CRD') {
|
|
throw new Error(`unrecognized mode: ${mode} for DepthToSpace`);
|
|
}
|
|
return { mode, blocksize };
|
|
};
|
|
exports.parseDepthToSpaceAttributes = parseDepthToSpaceAttributes;
|
|
const validateInputs = (inputs) => {
|
|
if (inputs.length !== 1) {
|
|
throw new Error(`DepthToSpace expect 1 inputs, but got ${inputs.length}`);
|
|
}
|
|
// Input has to be a 4-D tensor
|
|
// TODO: Support string depth-to-space.
|
|
if (inputs[0].type === 'string' || inputs[0].dims.length !== 4) {
|
|
throw new TypeError('DepthToSpace input should be a 4-D numeric tensor');
|
|
}
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./lib/onnxjs/backends/webgl/ops/dot-product.ts":
|
|
/*!******************************************************!*\
|
|
!*** ./lib/onnxjs/backends/webgl/ops/dot-product.ts ***!
|
|
\******************************************************/
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
// Licensed under the MIT License.
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.createDotProductProgramInfoLoader = void 0;
|
|
const util_1 = __webpack_require__(/*! ../../../util */ "./lib/onnxjs/util.ts");
|
|
const glsl_source_1 = __webpack_require__(/*! ../glsl-source */ "./lib/onnxjs/backends/webgl/glsl-source.ts");
|
|
const types_1 = __webpack_require__(/*! ../types */ "./lib/onnxjs/backends/webgl/types.ts");
|
|
const fuse_utils_1 = __webpack_require__(/*! ./fuse-utils */ "./lib/onnxjs/backends/webgl/ops/fuse-utils.ts");
|
|
const im2col_1 = __webpack_require__(/*! ./im2col */ "./lib/onnxjs/backends/webgl/ops/im2col.ts");
|
|
const createDotProductProgramMetadata = (hasBias, attributes) => ({
|
|
name: 'ConvDotProduct',
|
|
inputNames: hasBias ? ['Im2Col', 'K', 'B'] : ['Im2Col', 'K'],
|
|
inputTypes: hasBias ? [types_1.TextureType.unpacked, types_1.TextureType.packedLastDimension, types_1.TextureType.unpacked] :
|
|
[types_1.TextureType.unpacked, types_1.TextureType.packedLastDimension],
|
|
cacheKey: attributes.activationCacheKey
|
|
});
|
|
const createDotProductProgramInfo = (inferenceHandler, metadata, inputs, outputShape, attributes) => {
|
|
const xshape = inputs[0].dims;
|
|
const kshape = inputs[1].dims;
|
|
const adjustedKernelShape = [kshape[0], Math.ceil((xshape[1] * kshape[2] * kshape[3]) / 4)];
|
|
const im2colShape = (0, im2col_1.calculateIm2ColDims)(xshape, kshape, outputShape);
|
|
const [kWidth, kHeight] = inferenceHandler.calculateTextureWidthAndHeight(adjustedKernelShape, types_1.TextureType.packedLastDimension);
|
|
const im2colStrides = util_1.ShapeUtil.computeStrides(im2colShape);
|
|
const [im2colWidth, im2colHeight] = inferenceHandler.calculateTextureWidthAndHeight(im2colShape, types_1.TextureType.packedLastDimension);
|
|
const rank = outputShape.length;
|
|
const initValue = (inputs.length < 3) ? '0.0' : '_B(b)';
|
|
const sharedDim = Math.ceil(xshape[1] * kshape[2] * kshape[3] / 4);
|
|
const { activationFunction, applyActivation } = (0, fuse_utils_1.getActivationSnippet)(attributes);
|
|
const glsl = (0, glsl_source_1.getGlsl)(inferenceHandler.session.backend.glContext.version);
|
|
const shaderSource = `
|
|
${activationFunction}
|
|
float process(int indices[${rank}]) {
|
|
int b[1];
|
|
b[0] = indices[1];
|
|
int im2col[4];
|
|
im2col[0] = indices[0];
|
|
im2col[1] = indices[2];
|
|
im2col[2] = indices[3];
|
|
int im2colOffset = im2col[0] * ${im2colStrides[0]} + im2col[1] * ${im2colStrides[1]} + im2col[2] * ${im2colStrides[2]};
|
|
int kernelOffset = indices[1] * ${adjustedKernelShape[1]};
|
|
float value = ${initValue};
|
|
for (int i = 0; i < ${sharedDim}; ++i) {
|
|
vec2 im2colCoords = offsetToCoords(im2colOffset, ${im2colWidth}, ${im2colHeight});
|
|
vec2 kernelCoords = offsetToCoords(kernelOffset, ${kWidth}, ${kHeight});
|
|
value += dot(${glsl.texture2D}(Im2Col, im2colCoords), ${glsl.texture2D}(K, kernelCoords));
|
|
++im2colOffset;
|
|
++kernelOffset;
|
|
}
|
|
${applyActivation}
|
|
return value;
|
|
}`;
|
|
return Object.assign(Object.assign({}, metadata), { output: { dims: outputShape, type: inputs[0].type, textureType: types_1.TextureType.unpacked }, shaderSource });
|
|
};
|
|
const createDotProductProgramInfoLoader = (inferenceHandler, inputs, outputShape, attributes) => {
|
|
const metadata = createDotProductProgramMetadata(inputs.length > 2, attributes);
|
|
return Object.assign(Object.assign({}, metadata), { get: () => createDotProductProgramInfo(inferenceHandler, metadata, inputs, outputShape, attributes) });
|
|
};
|
|
exports.createDotProductProgramInfoLoader = createDotProductProgramInfoLoader;
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./lib/onnxjs/backends/webgl/ops/flatten.ts":
|
|
/*!**************************************************!*\
|
|
!*** ./lib/onnxjs/backends/webgl/ops/flatten.ts ***!
|
|
\**************************************************/
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
// Licensed under the MIT License.
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.parseFlattenAttributes = exports.flatten = void 0;
|
|
const util_1 = __webpack_require__(/*! ../../../util */ "./lib/onnxjs/util.ts");
|
|
const flatten = (inferenceHandler, inputs, axis) => {
|
|
validateInputs(inputs, axis);
|
|
const outputDims = util_1.ShapeUtil.flattenShape(inputs[0].dims, axis);
|
|
return [inferenceHandler.reshapeUnpacked(inputs[0], outputDims)];
|
|
};
|
|
exports.flatten = flatten;
|
|
const parseFlattenAttributes = (node) => node.attributes.getInt('axis', 1); // default axis is 1
|
|
exports.parseFlattenAttributes = parseFlattenAttributes;
|
|
const validateInputs = (inputs, axis) => {
|
|
if (!inputs || inputs.length !== 1) {
|
|
throw new Error('Flatten requires 1 input.');
|
|
}
|
|
const r = inputs[0].dims.length;
|
|
if (r === 0) {
|
|
throw new Error('scalar tensor is not supported.');
|
|
}
|
|
if (axis < -r || axis > r) {
|
|
throw new Error('Invalid axis');
|
|
}
|
|
// TODO: Support string type
|
|
if (inputs[0].type === 'string') {
|
|
throw new Error('string tensor is not supported.');
|
|
}
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./lib/onnxjs/backends/webgl/ops/fuse-utils.ts":
|
|
/*!*****************************************************!*\
|
|
!*** ./lib/onnxjs/backends/webgl/ops/fuse-utils.ts ***!
|
|
\*****************************************************/
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
// Licensed under the MIT License.
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.parseInternalActivationAttributes = exports.getActivationSnippet = void 0;
|
|
const util_1 = __webpack_require__(/*! ../../../util */ "./lib/onnxjs/util.ts");
|
|
const unary_op_1 = __webpack_require__(/*! ./unary-op */ "./lib/onnxjs/backends/webgl/ops/unary-op.ts");
|
|
function getActivationSnippet(attributes) {
|
|
let func;
|
|
switch (attributes.activation) {
|
|
case 'Relu':
|
|
func = (0, unary_op_1.glslRelu)();
|
|
break;
|
|
case 'Sigmoid':
|
|
func = (0, unary_op_1.glslSigmoid)();
|
|
break;
|
|
case 'Clip':
|
|
func = (0, unary_op_1.glslClip)(attributes.clipMin, attributes.clipMax);
|
|
break;
|
|
// TODO: adding other activations that can be fused.
|
|
default:
|
|
return { activationFunction: '', applyActivation: '' };
|
|
}
|
|
const activationName = func.name;
|
|
const activationFunction = func.body;
|
|
const applyActivation = `value = ${activationName}_(value);`;
|
|
return { activationFunction, applyActivation };
|
|
}
|
|
exports.getActivationSnippet = getActivationSnippet;
|
|
const parseInternalActivationAttributes = (attributes) => {
|
|
const activation = attributes.getString('activation', '');
|
|
if (activation === 'Clip') {
|
|
const [clipMin, clipMax] = attributes.getFloats('activation_params', [util_1.MIN_CLIP, util_1.MAX_CLIP]);
|
|
return { activation, clipMax, clipMin, activationCacheKey: `${activation}:${clipMin},${clipMax}` };
|
|
}
|
|
return { activation, activationCacheKey: activation };
|
|
};
|
|
exports.parseInternalActivationAttributes = parseInternalActivationAttributes;
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./lib/onnxjs/backends/webgl/ops/gather.ts":
|
|
/*!*************************************************!*\
|
|
!*** ./lib/onnxjs/backends/webgl/ops/gather.ts ***!
|
|
\*************************************************/
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
// Licensed under the MIT License.
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.parseGatherAttributes = exports.gather = void 0;
|
|
const attribute_with_cache_key_1 = __webpack_require__(/*! ../../../attribute-with-cache-key */ "./lib/onnxjs/attribute-with-cache-key.ts");
|
|
const operators_1 = __webpack_require__(/*! ../../../operators */ "./lib/onnxjs/operators.ts");
|
|
const util_1 = __webpack_require__(/*! ../../../util */ "./lib/onnxjs/util.ts");
|
|
const types_1 = __webpack_require__(/*! ../types */ "./lib/onnxjs/backends/webgl/types.ts");
|
|
const gather = (inferenceHandler, inputs, attributes) => {
|
|
validateInputs(inputs, attributes.axis);
|
|
const output = inferenceHandler.run(createGatherProgramInfoLoader(inferenceHandler, inputs, attributes), inputs);
|
|
return [output];
|
|
};
|
|
exports.gather = gather;
|
|
const parseGatherAttributes = (node) => (0, attribute_with_cache_key_1.createAttributeWithCacheKey)({ axis: node.attributes.getInt('axis', 0) });
|
|
exports.parseGatherAttributes = parseGatherAttributes;
|
|
const gatherProgramMetadata = {
|
|
name: 'Gather',
|
|
inputNames: ['A', 'B'],
|
|
inputTypes: [types_1.TextureType.unpacked, types_1.TextureType.unpacked],
|
|
};
|
|
const createGatherProgramInfo = (handler, metadata, inputs, axis) => {
|
|
const inputShape = inputs[0].dims.slice();
|
|
const indexDataShape = inputs[1].dims.slice();
|
|
const outputShape = new Array(inputShape.length + indexDataShape.length - 1);
|
|
axis = util_1.ShapeUtil.normalizeAxis(axis, inputShape.length);
|
|
const indexCopyOps = [];
|
|
for (let i = 0; i < outputShape.length; i++) {
|
|
// outputShape is divided into three parts: A, B, C
|
|
// |0 axis| axis + indexDataShape.length | end|
|
|
// | A | B | C |
|
|
//
|
|
// inputIdx: [A, inputs[1][B], C]
|
|
if (i < axis) { // A
|
|
outputShape[i] = inputShape[i];
|
|
indexCopyOps.push(`inputIdx[${i}] = outputIdx[${i}];`);
|
|
}
|
|
else {
|
|
if (i < axis + indexDataShape.length) { // B
|
|
outputShape[i] = indexDataShape[i - axis];
|
|
indexCopyOps.push(`indexDataIdx[${i - axis}] = outputIdx[${i}];`);
|
|
}
|
|
else { // C
|
|
outputShape[i] = inputShape[i - indexDataShape.length + 1]; // skip 1 for axis
|
|
indexCopyOps.push(`inputIdx[${i - indexDataShape.length + 1}] = outputIdx[${i}];`);
|
|
}
|
|
}
|
|
}
|
|
const orank = outputShape.length || 1;
|
|
const irank = inputShape.length;
|
|
const iDrank = indexDataShape.length || 1;
|
|
const shaderSource = `
|
|
float process(int outputIdx[${orank}]) {
|
|
int inputIdx[${irank}];
|
|
int indexDataIdx[${iDrank}];
|
|
indexDataIdx[0] = 0;
|
|
${indexCopyOps.join('\n ')}
|
|
int idx = int(_B(indexDataIdx));
|
|
inputIdx[${axis}] = idx < 0 ? idx + ${inputShape[axis]} : idx;
|
|
return _A(inputIdx);
|
|
}`;
|
|
return Object.assign(Object.assign({}, metadata), { output: { dims: outputShape, type: inputs[0].type, textureType: types_1.TextureType.unpacked }, shaderSource });
|
|
};
|
|
const createGatherProgramInfoLoader = (handler, inputs, attributes) => {
|
|
const metadata = Object.assign(Object.assign({}, gatherProgramMetadata), { cacheHint: attributes.cacheKey });
|
|
return Object.assign(Object.assign({}, metadata), { get: () => createGatherProgramInfo(handler, metadata, inputs, attributes.axis) });
|
|
};
|
|
const validateInputs = (inputs, axis) => {
|
|
if (!inputs || inputs.length !== 2) {
|
|
throw new Error('Gather requires 2 inputs.');
|
|
}
|
|
const tensorRank = inputs[0].dims.length;
|
|
if (tensorRank < 1) {
|
|
throw new Error('Invalid input shape.');
|
|
}
|
|
if (axis < -tensorRank || axis > tensorRank - 1) {
|
|
throw new Error('Invalid axis.');
|
|
}
|
|
if (operators_1.NUMBER_TYPES.indexOf(inputs[0].type) === -1) {
|
|
throw new Error('Invaid input type.');
|
|
}
|
|
if (inputs[1].type !== 'int32' && inputs[1].type !== 'int16') {
|
|
throw new Error('Invaid input type.');
|
|
}
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./lib/onnxjs/backends/webgl/ops/gemm.ts":
|
|
/*!***********************************************!*\
|
|
!*** ./lib/onnxjs/backends/webgl/ops/gemm.ts ***!
|
|
\***********************************************/
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
// Licensed under the MIT License.
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.parseGemmAttributesV11 = exports.parseGemmAttributesV7 = exports.gemm = void 0;
|
|
const attribute_with_cache_key_1 = __webpack_require__(/*! ../../../attribute-with-cache-key */ "./lib/onnxjs/attribute-with-cache-key.ts");
|
|
const util_1 = __webpack_require__(/*! ../../../util */ "./lib/onnxjs/util.ts");
|
|
const types_1 = __webpack_require__(/*! ../types */ "./lib/onnxjs/backends/webgl/types.ts");
|
|
const gemm = (inferenceHandler, inputs, attributes) => {
|
|
validateInputs(inputs, attributes);
|
|
const output = inferenceHandler.run(createGemmProgramInfoLoader(inputs, attributes), inputs);
|
|
return [output];
|
|
};
|
|
exports.gemm = gemm;
|
|
const parseGemmAttributes = (node, isOptionalC) => {
|
|
const transA = node.attributes.getInt('transA', 0) !== 0;
|
|
const transB = node.attributes.getInt('transB', 0) !== 0;
|
|
const alpha = node.attributes.getFloat('alpha', 1.0);
|
|
const beta = node.attributes.getFloat('beta', 1.0);
|
|
return (0, attribute_with_cache_key_1.createAttributeWithCacheKey)({ transA, transB, alpha, beta, isOptionalC });
|
|
};
|
|
const parseGemmAttributesV7 = (node) => parseGemmAttributes(node, false);
|
|
exports.parseGemmAttributesV7 = parseGemmAttributesV7;
|
|
const parseGemmAttributesV11 = (node) => parseGemmAttributes(node, true);
|
|
exports.parseGemmAttributesV11 = parseGemmAttributesV11;
|
|
const createGemmProgramInfoLoader = (inputs, attributes) => {
|
|
const metadata = {
|
|
name: 'Gemm',
|
|
inputNames: inputs.length === 3 ? ['A', 'B', 'C'] : ['A', 'B'],
|
|
inputTypes: inputs.length === 3 ? [types_1.TextureType.unpacked, types_1.TextureType.unpacked, types_1.TextureType.unpacked] :
|
|
[types_1.TextureType.unpacked, types_1.TextureType.unpacked],
|
|
key: attributes.cacheKey
|
|
};
|
|
return Object.assign(Object.assign({}, metadata), { get: () => createGemmProgramInfo(metadata, inputs, attributes) });
|
|
};
|
|
const createGemmProgramInfo = (metadata, inputs, attributes) => {
|
|
const aShape = inputs[0].dims.slice();
|
|
const bShape = inputs[1].dims.slice();
|
|
const [M, N] = util_1.GemmUtil.getShapeOfGemmResult(aShape, attributes.transA, bShape, attributes.transB, inputs.length === 3 ? inputs[2].dims : undefined);
|
|
const outputShape = [M, N];
|
|
if (!outputShape) {
|
|
throw new Error('Can\'t use gemm on the given tensors');
|
|
}
|
|
let sharedDim = aShape[aShape.length - 1];
|
|
let line = '';
|
|
if (attributes.transA) {
|
|
sharedDim = aShape[0];
|
|
}
|
|
if (attributes.transA && attributes.transB) {
|
|
line = 'value += _A_T(a) * _B_T(b);';
|
|
}
|
|
else if (attributes.transA && !attributes.transB) {
|
|
line = 'value += _A_T(a) * _B(b);';
|
|
}
|
|
else if (!attributes.transA && attributes.transB) {
|
|
line = 'value += _A(a) * _B_T(b);';
|
|
}
|
|
else if (!attributes.transA && !attributes.transB) {
|
|
line = 'value += _A(a) * _B(b);';
|
|
}
|
|
const rank = outputShape.length;
|
|
const declareC = inputs.length === 3 ? `int c[${inputs[2].dims.length}];` : '';
|
|
const broadcastC = inputs.length === 3 ? 'bcastIndices_C(indices, c);' : '';
|
|
const calculateC = inputs.length === 3 ? 'value += beta * _C(c);' : '';
|
|
const shaderSource = `
|
|
float process(int indices[${rank}]) {
|
|
int a[${rank}];
|
|
int b[${rank}];
|
|
${declareC}
|
|
|
|
copyVec(indices, a);
|
|
copyVec(indices, b);
|
|
${broadcastC}
|
|
|
|
float value = 0.0;
|
|
for (int k=0; k<${sharedDim}; ++k) {
|
|
a[${rank - 1}] = k;
|
|
b[${rank - 2}] = k;
|
|
${line}
|
|
}
|
|
|
|
value = value * alpha;
|
|
${calculateC}
|
|
return value;
|
|
}`;
|
|
return Object.assign(Object.assign({}, metadata), { output: { dims: outputShape, type: inputs[0].type, textureType: types_1.TextureType.unpacked }, variables: [
|
|
{ name: 'alpha', type: 'float', data: attributes.alpha }, { name: 'beta', type: 'float', data: attributes.beta }
|
|
], shaderSource });
|
|
};
|
|
const validateInputs = (inputs, attributes) => {
|
|
if (!inputs) {
|
|
throw new Error('Input is missing');
|
|
}
|
|
if (attributes.isOptionalC && (inputs.length < 2 || inputs.length > 3)) {
|
|
throw new Error('Invaid input shape.');
|
|
}
|
|
if (!attributes.isOptionalC && inputs.length !== 3) {
|
|
throw new Error('Gemm requires 3 inputs');
|
|
}
|
|
// 'C' can be of dimensionality 1 or 2 only
|
|
if (inputs.length === 3 && inputs[2].dims.length !== 1 && inputs[2].dims.length !== 2) {
|
|
throw new Error('Invalid input shape of C');
|
|
}
|
|
if ((inputs[0].type !== 'float32' && inputs[0].type !== 'float64') ||
|
|
(inputs[1].type !== 'float32' && inputs[1].type !== 'float64') ||
|
|
(inputs.length === 3 && inputs[2].type !== 'float32' && inputs[2].type !== 'float64')) {
|
|
throw new Error('Invalid input type.');
|
|
}
|
|
if ((inputs[0].type !== inputs[1].type) || (inputs.length === 3 && inputs[0].type !== inputs[2].type)) {
|
|
throw new Error('Input types are mismatched');
|
|
}
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./lib/onnxjs/backends/webgl/ops/im2col-pack.ts":
|
|
/*!******************************************************!*\
|
|
!*** ./lib/onnxjs/backends/webgl/ops/im2col-pack.ts ***!
|
|
\******************************************************/
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
// Licensed under the MIT License.
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.createPackedIm2ColProgramInfoLoader = void 0;
|
|
const glsl_source_1 = __webpack_require__(/*! ../glsl-source */ "./lib/onnxjs/backends/webgl/glsl-source.ts");
|
|
const types_1 = __webpack_require__(/*! ../types */ "./lib/onnxjs/backends/webgl/types.ts");
|
|
const packing_utils_1 = __webpack_require__(/*! ./packing-utils */ "./lib/onnxjs/backends/webgl/ops/packing-utils.ts");
|
|
const createPackedIm2ColProgramMetadata = (cacheHint) => ({
|
|
name: 'Im2Col (packed)',
|
|
inputNames: ['A'],
|
|
inputTypes: [types_1.TextureType.packed],
|
|
cacheHint,
|
|
});
|
|
const createPackedIm2ColProgramInfo = (inferenceHandler, metadata, x, w, outputShape, attributes) => {
|
|
const xshape = x.dims;
|
|
const wshape = w.dims;
|
|
const rowDim = 2;
|
|
const colDim = 3;
|
|
const rank = outputShape.length;
|
|
const im2colShape = [wshape[1] * wshape[2] * wshape[3], outputShape[2] * outputShape[3]];
|
|
const kernelSize = wshape[2] * wshape[3];
|
|
const unpackChannel = (0, packing_utils_1.unpackFromChannel)();
|
|
const glsl = (0, glsl_source_1.getGlsl)(inferenceHandler.session.backend.glContext.version);
|
|
let unrolled = '';
|
|
for (let row = 0; row <= 1; row++) {
|
|
for (let col = 0; col <= 1; col++) {
|
|
unrolled += `
|
|
blockIndex = rc.x + ${col};
|
|
pos = rc.y + ${row};
|
|
|
|
if(blockIndex < ${im2colShape[1]} && pos < ${im2colShape[0]}) {
|
|
offsetY = int(blockIndex / (${outputShape[rank - 1]})) * ${attributes.strides[0]} -
|
|
${attributes.pads[0]};
|
|
d0 = offsetY + ${attributes.dilations[0]} * (imod(pos, ${kernelSize}) / ${wshape[2]});
|
|
|
|
if(d0 < ${xshape[rowDim]} && d0 >= 0) {
|
|
offsetX = imod(blockIndex, ${outputShape[rank - 1]}) * ${attributes.strides[1]} -
|
|
${attributes.pads[1]};
|
|
d1 = offsetX + ${attributes.dilations[1]} * imod(imod(pos, ${kernelSize}), ${wshape[2]});
|
|
|
|
if(d1 < ${xshape[colDim]} && d1 >= 0) {
|
|
|
|
ch = int(float(pos)/ ${kernelSize}.);
|
|
innerDims = vec2(d0, d1);
|
|
result[${row * 2 + col}] = getChannel(
|
|
getA(0, ch, int(innerDims.x),
|
|
int(innerDims.y)), innerDims);
|
|
}
|
|
}
|
|
}
|
|
|
|
`;
|
|
}
|
|
}
|
|
const shaderSource = `
|
|
${unpackChannel}
|
|
|
|
void main() {
|
|
ivec2 rc = getOutputCoords();
|
|
vec4 result = vec4(0.0);
|
|
int blockIndex, pos, offsetY, d0, offsetX, d1, ch;
|
|
vec2 innerDims;
|
|
${unrolled}
|
|
${glsl.output} = result;
|
|
}
|
|
`;
|
|
return Object.assign(Object.assign({}, metadata), { output: { dims: im2colShape, type: x.type, textureType: types_1.TextureType.packed }, shaderSource, hasMain: true });
|
|
};
|
|
const createPackedIm2ColProgramInfoLoader = (inferenceHandler, x, w, outputShape, attributes) => {
|
|
const metadata = createPackedIm2ColProgramMetadata(attributes.cacheKey);
|
|
return Object.assign(Object.assign({}, metadata), { get: () => createPackedIm2ColProgramInfo(inferenceHandler, metadata, x, w, outputShape, attributes) });
|
|
};
|
|
exports.createPackedIm2ColProgramInfoLoader = createPackedIm2ColProgramInfoLoader;
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./lib/onnxjs/backends/webgl/ops/im2col.ts":
|
|
/*!*************************************************!*\
|
|
!*** ./lib/onnxjs/backends/webgl/ops/im2col.ts ***!
|
|
\*************************************************/
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
// Licensed under the MIT License.
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.calculateIm2ColDims = exports.createIm2ColProgramInfoLoader = void 0;
|
|
const types_1 = __webpack_require__(/*! ../types */ "./lib/onnxjs/backends/webgl/types.ts");
|
|
const createIm2ColProgramMetadata = (cacheHint) => ({
|
|
name: 'Im2Col',
|
|
inputNames: ['X'],
|
|
inputTypes: [types_1.TextureType.unpacked],
|
|
cacheHint,
|
|
});
|
|
const createIm2ColProgramInfo = (inferenceHandler, metadata, x, w, outputShape, attributes) => {
|
|
const xshape = x.dims;
|
|
const wshape = w.dims;
|
|
const rank = outputShape.length;
|
|
const im2colDims = (0, exports.calculateIm2ColDims)(xshape, wshape, outputShape, 4);
|
|
const shaderSource = `
|
|
const int XC = ${xshape[1]};
|
|
const int XH = ${xshape[2]};
|
|
const int XW = ${xshape[3]};
|
|
const int KH = ${attributes.kernelShape[0]};
|
|
const int KW = ${attributes.kernelShape[1]};
|
|
const int dilationH = ${attributes.dilations[0]};
|
|
const int dilationW = ${attributes.dilations[1]};
|
|
const int strideH = ${attributes.strides[0]};
|
|
const int strideW = ${attributes.strides[1]};
|
|
const int padH = ${attributes.pads[0]};
|
|
const int padW = ${attributes.pads[1]};
|
|
const int KHKW = KH*KW;
|
|
const int XCKHKW = XC * KHKW;
|
|
const int outputChannels = 4;
|
|
vec4 process(int indices[${rank}]) {
|
|
int b = indices[0]; // batch size
|
|
int oh = indices[1] * strideH - padH; //output height
|
|
int ow = indices[2] * strideW - padW; //output width
|
|
int p = indices[3] * outputChannels; //patch
|
|
vec4 value = vec4(0.0);
|
|
for(int i=0; i < outputChannels; ++i) {
|
|
if(p < XCKHKW) {
|
|
int patchC = p / KHKW;
|
|
int patchH = (p - patchC*KHKW) / KW;
|
|
int patchW = (p - patchC*KHKW) - patchH * KW;
|
|
int xh2 = oh + patchH * dilationH;
|
|
int xw2 = ow + patchW * dilationW;
|
|
int x[${xshape.length}];
|
|
x[0] = b;
|
|
x[1] = patchC;
|
|
x[2] = xh2;
|
|
x[3] = xw2;
|
|
if(xh2 >= 0 &&
|
|
xh2 < XH &&
|
|
xw2 >= 0 &&
|
|
xw2 < XW) {
|
|
value[i] = _X(x);
|
|
}
|
|
}
|
|
++p;
|
|
}
|
|
return value;
|
|
}
|
|
`;
|
|
return Object.assign(Object.assign({}, metadata), { output: { dims: im2colDims, type: x.type, textureType: types_1.TextureType.packedLastDimension }, shaderSource });
|
|
};
|
|
const createIm2ColProgramInfoLoader = (inferenceHandler, x, w, outputShape, attributes) => {
|
|
const metadata = createIm2ColProgramMetadata(attributes.cacheKey);
|
|
return Object.assign(Object.assign({}, metadata), { get: () => createIm2ColProgramInfo(inferenceHandler, metadata, x, w, outputShape, attributes) });
|
|
};
|
|
exports.createIm2ColProgramInfoLoader = createIm2ColProgramInfoLoader;
|
|
const calculateIm2ColDims = (inputShape, kernelShape, outputShape, channels = 4) => [outputShape[0], outputShape[2], outputShape[3],
|
|
Math.ceil(inputShape[1] * kernelShape[2] * kernelShape[3] / channels)];
|
|
exports.calculateIm2ColDims = calculateIm2ColDims;
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./lib/onnxjs/backends/webgl/ops/image-scaler.ts":
|
|
/*!*******************************************************!*\
|
|
!*** ./lib/onnxjs/backends/webgl/ops/image-scaler.ts ***!
|
|
\*******************************************************/
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
// Licensed under the MIT License.
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.parseImageScalerAttributes = exports.imageScaler = void 0;
|
|
const attribute_with_cache_key_1 = __webpack_require__(/*! ../../../attribute-with-cache-key */ "./lib/onnxjs/attribute-with-cache-key.ts");
|
|
const types_1 = __webpack_require__(/*! ../types */ "./lib/onnxjs/backends/webgl/types.ts");
|
|
const imageScaler = (inferenceHandler, inputs, attributes) => {
|
|
validateInputs(inputs);
|
|
const output = inferenceHandler.run(createImageScalerProgramInfoLoader(inferenceHandler, inputs, attributes), inputs);
|
|
return [output];
|
|
};
|
|
exports.imageScaler = imageScaler;
|
|
const parseImageScalerAttributes = (node) => {
|
|
const scale = node.attributes.getFloat('scale');
|
|
const bias = node.attributes.getFloats('bias');
|
|
return (0, attribute_with_cache_key_1.createAttributeWithCacheKey)({ scale, bias });
|
|
};
|
|
exports.parseImageScalerAttributes = parseImageScalerAttributes;
|
|
const imageScalerProgramMetadata = {
|
|
name: 'ImageScaler',
|
|
inputNames: ['X'],
|
|
inputTypes: [types_1.TextureType.unpacked],
|
|
};
|
|
const createImageScalerProgramInfo = (handler, metadata, inputs, attributes) => {
|
|
const outputShape = inputs[0].dims.slice();
|
|
const rank = outputShape.length;
|
|
const getBiasMethod = createGetBiasMethod(attributes.bias.length);
|
|
const shaderSource = `
|
|
${getBiasMethod}
|
|
float process(int indices[${rank}]) {
|
|
return _X(indices) * scale + getBias(bias, indices[1]);
|
|
}`;
|
|
return Object.assign(Object.assign({}, metadata), { output: { dims: outputShape, type: inputs[0].type, textureType: types_1.TextureType.unpacked }, variables: [
|
|
{ name: 'bias', type: 'float', arrayLength: attributes.bias.length, data: attributes.bias },
|
|
{ name: 'scale', type: 'float', data: attributes.scale }
|
|
], shaderSource });
|
|
};
|
|
const createImageScalerProgramInfoLoader = (handler, inputs, attributes) => {
|
|
const metadata = Object.assign(Object.assign({}, imageScalerProgramMetadata), { cacheHint: attributes.cacheKey });
|
|
return Object.assign(Object.assign({}, metadata), { get: () => createImageScalerProgramInfo(handler, metadata, inputs, attributes) });
|
|
};
|
|
const createGetBiasMethod = (numChannels) => {
|
|
const codeLines = [`float getBias(float bias[${numChannels}], int channel) {`];
|
|
for (let i = 0; i < numChannels; ++i) {
|
|
if (i === 0) {
|
|
codeLines.push('\t' +
|
|
`if (channel == ${i}) { return bias[${i}]; }`);
|
|
}
|
|
else if (i === numChannels - 1) {
|
|
codeLines.push('\t' +
|
|
`else { return bias[${i}]; }`);
|
|
}
|
|
else {
|
|
codeLines.push('\t' +
|
|
`else if (channel == ${i}) { return bias[${i}]; }`);
|
|
}
|
|
}
|
|
codeLines.push('\t' +
|
|
'}');
|
|
return codeLines.join('\n');
|
|
};
|
|
const validateInputs = (inputs) => {
|
|
if (!inputs || inputs.length !== 1) {
|
|
throw new Error('ImageScaler requires 1 input.');
|
|
}
|
|
if (inputs[0].dims.length !== 4) {
|
|
throw new Error('Invalid input shape.');
|
|
}
|
|
if (inputs[0].type !== 'float32' && inputs[0].type !== 'float64') {
|
|
throw new Error('Invalid input type.');
|
|
}
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./lib/onnxjs/backends/webgl/ops/instance-normalization.ts":
|
|
/*!*****************************************************************!*\
|
|
!*** ./lib/onnxjs/backends/webgl/ops/instance-normalization.ts ***!
|
|
\*****************************************************************/
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
// Licensed under the MIT License.
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.parseInstanceNormalizationAttributes = exports.instanceNormalization = void 0;
|
|
const glsl_source_1 = __webpack_require__(/*! ../glsl-source */ "./lib/onnxjs/backends/webgl/glsl-source.ts");
|
|
const types_1 = __webpack_require__(/*! ../types */ "./lib/onnxjs/backends/webgl/types.ts");
|
|
const instanceNormalization = (inferenceHandler, inputs, epsilon) => {
|
|
validateInputs(inputs);
|
|
const meanAndVariance = inferenceHandler.run(createMeanAndVarianceProgramInfoLoader(inputs[0]), inputs);
|
|
const output = inferenceHandler.run(createComputeOutputProgramInfoLoader(inferenceHandler, inputs[0], epsilon, meanAndVariance.dims), [inputs[0], meanAndVariance, inputs[1], inputs[2]]);
|
|
return [output];
|
|
};
|
|
exports.instanceNormalization = instanceNormalization;
|
|
const parseInstanceNormalizationAttributes = (node) => node.attributes.getFloat('epsilon', 1e-5);
|
|
exports.parseInstanceNormalizationAttributes = parseInstanceNormalizationAttributes;
|
|
const meanAndVarianceProgramMetadata = {
|
|
name: 'InstanceNormalization_MeanAndVariance',
|
|
inputNames: ['X'],
|
|
inputTypes: [types_1.TextureType.unpacked],
|
|
};
|
|
const createMeanAndVarianceProgramInfo = (metadata, input) => {
|
|
const xDims = input.dims.slice();
|
|
const channel = xDims[1];
|
|
const channelSize = xDims[2] * xDims[3];
|
|
const outputShape = [xDims[0], channel];
|
|
const shaderSource = `
|
|
vec4 process(int[2] indices) {
|
|
vec4 v = vec4(0.0);
|
|
int a[4];
|
|
a[0] = indices[0];
|
|
a[1] = indices[1];
|
|
float temp = 0.0;
|
|
for(int a2=0; a2<${xDims[2]}; a2++) {
|
|
a[2] = a2;
|
|
for(int a3=0; a3<${xDims[3]}; a3++) {
|
|
a[3] = a3;
|
|
float x = _X(a);
|
|
temp += x;
|
|
}
|
|
}
|
|
float mean = temp / float(${channelSize});
|
|
temp = 0.0;
|
|
for(int a2=0; a2<${xDims[2]}; a2++) {
|
|
a[2] = a2;
|
|
for(int a3=0; a3<${xDims[3]}; a3++) {
|
|
a[3] = a3;
|
|
float x = _X(a);
|
|
temp += (x - mean) * (x - mean);
|
|
}
|
|
}
|
|
v.r = mean;
|
|
v.g = temp / float(${channelSize});
|
|
|
|
return v;
|
|
}`;
|
|
return Object.assign(Object.assign({}, metadata), { output: { dims: outputShape, type: input.type, textureType: types_1.TextureType.packedLastDimension }, shaderSource });
|
|
};
|
|
const createMeanAndVarianceProgramInfoLoader = (input) => (Object.assign(Object.assign({}, meanAndVarianceProgramMetadata), { get: () => createMeanAndVarianceProgramInfo(meanAndVarianceProgramMetadata, input) }));
|
|
const computeOutputProgramMetadata = {
|
|
name: 'InstanceNormalization_ComputeOutput',
|
|
inputNames: ['X', 'MeanAndVariance', 'Scale', 'B'],
|
|
inputTypes: [types_1.TextureType.unpacked, types_1.TextureType.packedLastDimension, types_1.TextureType.unpacked, types_1.TextureType.unpacked],
|
|
};
|
|
const createComputeOutputProgramInfo = (inferenceHandler, metadata, input, epsilon, meanAndVarianceShape) => {
|
|
const glsl = (0, glsl_source_1.getGlsl)(inferenceHandler.session.backend.glContext.version);
|
|
const [textureWidth, textureHeight] = inferenceHandler.calculateTextureWidthAndHeight(meanAndVarianceShape, types_1.TextureType.packedLastDimension);
|
|
const [meanAndVarianceWidth, meanAndVarianceHeight] = [textureWidth / 4, textureHeight];
|
|
const shaderSource = `
|
|
vec4 get_MeanAndVariance(int[2] mv) {
|
|
int offset = indicesToOffset_MeanAndVariance(mv);
|
|
vec2 coords = offsetToCoords(offset, ${meanAndVarianceWidth}, ${meanAndVarianceHeight});
|
|
return ${glsl.texture2D}(MeanAndVariance, coords);
|
|
}
|
|
|
|
float process(int[4] indices) {
|
|
int mv[2];
|
|
mv[0] = indices[0];
|
|
mv[1] = indices[1];
|
|
vec4 mean_and_variance = get_MeanAndVariance(mv);
|
|
float mean = mean_and_variance.r;
|
|
float variance = mean_and_variance.g;
|
|
|
|
int sb[1];
|
|
sb[0] = indices[1];
|
|
float scale = _Scale(sb);
|
|
float b = _B(sb);
|
|
|
|
return scale * (_X(indices) - mean) / sqrt(variance + epsilon) + b;
|
|
}`;
|
|
return Object.assign(Object.assign({}, metadata), { output: { dims: input.dims, type: input.type, textureType: types_1.TextureType.unpacked }, variables: [{ name: 'epsilon', type: 'float', data: epsilon }], shaderSource });
|
|
};
|
|
const createComputeOutputProgramInfoLoader = (inferenceHandler, input, epsilon, meanAndVarianceShape) => {
|
|
const metadata = Object.assign(Object.assign({}, computeOutputProgramMetadata), { cacheHint: `${epsilon}` });
|
|
return Object.assign(Object.assign({}, metadata), { get: () => createComputeOutputProgramInfo(inferenceHandler, metadata, input, epsilon, meanAndVarianceShape) });
|
|
};
|
|
const validateInputs = (inputs) => {
|
|
if (!inputs || inputs.length !== 3) {
|
|
throw new Error('InstanceNormalization requires 3 inputs.');
|
|
}
|
|
const X = inputs[0];
|
|
const scale = inputs[1];
|
|
const B = inputs[2];
|
|
// input should at least have three dimensions - N,C,dim1,...,dimn
|
|
// other inputs can have only one dimensions
|
|
if (X.dims.length < 3 || scale.dims.length !== 1 || B.dims.length !== 1) {
|
|
throw new Error('Invalid input shape.');
|
|
}
|
|
if (scale.dims[0] !== X.dims[1] || B.dims[0] !== X.dims[1]) {
|
|
throw new Error('Input shapes are mismatched.');
|
|
}
|
|
if ((X.type !== 'float32' && X.type !== 'float64') || (scale.type !== 'float32' && scale.type !== 'float64') ||
|
|
(B.type !== 'float32' && B.type !== 'float64')) {
|
|
throw new Error('Invalid input type.');
|
|
}
|
|
if (inputs[0].dims.length !== 4) {
|
|
throw new Error('Only support 4-D input shape.');
|
|
}
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./lib/onnxjs/backends/webgl/ops/matmul-pack.ts":
|
|
/*!******************************************************!*\
|
|
!*** ./lib/onnxjs/backends/webgl/ops/matmul-pack.ts ***!
|
|
\******************************************************/
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
// Licensed under the MIT License.
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.createPackedMatmulProgramInfoLoader = void 0;
|
|
const util_1 = __webpack_require__(/*! ../../../util */ "./lib/onnxjs/util.ts");
|
|
const glsl_source_1 = __webpack_require__(/*! ../glsl-source */ "./lib/onnxjs/backends/webgl/glsl-source.ts");
|
|
const types_1 = __webpack_require__(/*! ../types */ "./lib/onnxjs/backends/webgl/types.ts");
|
|
const utils_1 = __webpack_require__(/*! ../utils */ "./lib/onnxjs/backends/webgl/utils.ts");
|
|
const fuse_utils_1 = __webpack_require__(/*! ./fuse-utils */ "./lib/onnxjs/backends/webgl/ops/fuse-utils.ts");
|
|
const matmul_1 = __webpack_require__(/*! ./matmul */ "./lib/onnxjs/backends/webgl/ops/matmul.ts");
|
|
const createPackedMatmulProgramMetadata = (hasBias, cacheHint) => ({
|
|
name: 'MatMul (packed)',
|
|
inputNames: hasBias ? ['A', 'B', 'Bias'] : ['A', 'B'],
|
|
inputTypes: hasBias ? [types_1.TextureType.packed, types_1.TextureType.packed, types_1.TextureType.packed] :
|
|
[types_1.TextureType.packed, types_1.TextureType.packed],
|
|
cacheHint
|
|
});
|
|
const createPackedMatmulProgramInfo = (inferenceHandler, metadata, inputs, activationAttributes) => {
|
|
const hasBias = inputs.length > 2;
|
|
const processBias = hasBias ? 'value += getBiasForMatmul();' : '';
|
|
const aShape = inputs[0].dims;
|
|
const bShape = inputs[1].dims;
|
|
const outputShape = util_1.BroadcastUtil.calcShape(aShape, bShape, true);
|
|
const isBroadcast = !util_1.ShapeUtil.areEqual(inputs[0].dims, inputs[1].dims);
|
|
if (!outputShape) {
|
|
throw new Error('Can\'t use matmul on the given tensors');
|
|
}
|
|
const sharedDim = aShape[aShape.length - 1];
|
|
const sharedDimIndex = Math.ceil(sharedDim / 2);
|
|
const aRank = aShape.length;
|
|
const bRank = bShape.length;
|
|
const glsl = (0, glsl_source_1.getGlsl)(inferenceHandler.session.backend.glContext.version);
|
|
const coordsDataType = (0, utils_1.getCoordsDataType)(outputShape.length);
|
|
const outRank = outputShape.length;
|
|
const allGlChannels = (0, utils_1.getGlChannels)();
|
|
const { activationFunction, applyActivation } = (0, fuse_utils_1.getActivationSnippet)(activationAttributes);
|
|
const getBiasForMatmulSnippet = hasBias ? `${(0, matmul_1.getBiasForMatmul)(coordsDataType, allGlChannels, inputs[2].dims, outputShape, true)}` : '';
|
|
const getBcastedSamplerForMatmulSnippet = isBroadcast ? `${getBcastSamplerForMatmul(coordsDataType, allGlChannels, inputs, outputShape)}` : '';
|
|
const getSamplerAInLoopSnippet = isBroadcast ? 'getAAtOutCoordsMatmul(i)' : `getA(${getA(allGlChannels, aRank)})`;
|
|
const getSamplerBInLoopSnippet = isBroadcast ? 'getBAtOutCoordsMatmul(i)' : `getB(${getB(allGlChannels, bRank)})`;
|
|
const getOutputCoordsSnippet = isBroadcast ? '' : `${coordsDataType} rc =
|
|
getOutputCoords(); int lastDim = rc.${allGlChannels[outRank - 1]}; rc.${allGlChannels[outRank - 1]} =
|
|
rc.${allGlChannels[outRank - 2]}; rc.${allGlChannels[outRank - 2]} = lastDim;
|
|
`;
|
|
const shaderSource = `
|
|
${getBcastedSamplerForMatmulSnippet}
|
|
${getBiasForMatmulSnippet}
|
|
${activationFunction}
|
|
void main() {
|
|
${getOutputCoordsSnippet}
|
|
|
|
vec4 value = vec4(0);
|
|
for (int i = 0; i < ${sharedDimIndex}; i++) {
|
|
vec4 a = ${getSamplerAInLoopSnippet};
|
|
vec4 b = ${getSamplerBInLoopSnippet};
|
|
|
|
value += (a.rrbb * b.rgrg);
|
|
value += (a.ggaa * b.baba);
|
|
}
|
|
${processBias}
|
|
${applyActivation}
|
|
${glsl.output} = value;
|
|
}`;
|
|
return Object.assign(Object.assign({}, metadata), { output: { dims: outputShape, type: inputs[0].type, textureType: types_1.TextureType.packed }, shaderSource, hasMain: true });
|
|
};
|
|
const createPackedMatmulProgramInfoLoader = (inferenceHandler, inputs, activationAttributes) => {
|
|
const metadata = createPackedMatmulProgramMetadata(inputs.length > 2, activationAttributes.activationCacheKey);
|
|
return Object.assign(Object.assign({}, metadata), { get: () => createPackedMatmulProgramInfo(inferenceHandler, metadata, inputs, activationAttributes) });
|
|
};
|
|
exports.createPackedMatmulProgramInfoLoader = createPackedMatmulProgramInfoLoader;
|
|
function getBcastSamplerForMatmul(coordsDataType, allGlChannels, inputs, outShape) {
|
|
let unpackedACoordsSnippet = [];
|
|
let unpackedBCoordsSnippet = [];
|
|
const inAShape = inputs[0].dims;
|
|
const inBShape = inputs[1].dims;
|
|
const inARank = inAShape.length;
|
|
const inBRank = inBShape.length;
|
|
const outRank = outShape.length;
|
|
const rankADiff = outRank - inARank;
|
|
const rankBDiff = outRank - inBRank;
|
|
unpackedACoordsSnippet = inAShape.map((s, i) => `coords.${allGlChannels[i + rankADiff]}`);
|
|
unpackedACoordsSnippet[inARank - 1] = 'i*2';
|
|
unpackedACoordsSnippet.join(', ');
|
|
unpackedBCoordsSnippet = inBShape.map((s, i) => `coords.${allGlChannels[i + rankBDiff]}`);
|
|
unpackedBCoordsSnippet[inBRank - 2] = 'i*2';
|
|
unpackedBCoordsSnippet.join(', ');
|
|
const broadcastADims = util_1.BroadcastUtil.getBroadcastDims(inAShape, outShape);
|
|
const broadcastBDims = util_1.BroadcastUtil.getBroadcastDims(inBShape, outShape);
|
|
const coordsASnippet = broadcastADims.map(d => `coords.${allGlChannels[d + rankADiff]} = 0;`).join('\n');
|
|
const coordsBSnippet = broadcastBDims.map(d => `coords.${allGlChannels[d + rankBDiff]} = 0;`).join('\n');
|
|
const swapDimSnippet = `int lastDim = coords.${allGlChannels[outRank - 1]};
|
|
coords.${allGlChannels[outRank - 1]} = coords.${allGlChannels[outRank - 2]};
|
|
coords.${allGlChannels[outRank - 2]} = lastDim;`;
|
|
const getBcastSamplerMatmulSource = `
|
|
vec4 getAAtOutCoordsMatmul(int i) {
|
|
${coordsDataType} coords = getOutputCoords();
|
|
${swapDimSnippet}
|
|
${coordsASnippet}
|
|
vec4 outputValue = getA(${unpackedACoordsSnippet});
|
|
return outputValue;
|
|
}
|
|
|
|
vec4 getBAtOutCoordsMatmul(int i) {
|
|
${coordsDataType} coords = getOutputCoords();
|
|
${swapDimSnippet}
|
|
${coordsBSnippet}
|
|
vec4 outputValue = getB(${unpackedBCoordsSnippet});
|
|
return outputValue;
|
|
}`;
|
|
return getBcastSamplerMatmulSource;
|
|
}
|
|
function getA(allGlChannels, rank) {
|
|
let res = '';
|
|
for (let i = 0; i < rank - 2; i++) {
|
|
res += `rc.${allGlChannels[i]}, `;
|
|
}
|
|
res += `rc.${allGlChannels[rank - 2]}, ` +
|
|
'i*2';
|
|
return res;
|
|
}
|
|
function getB(allGlChannels, rank) {
|
|
let res = '';
|
|
for (let i = 0; i < rank - 2; i++) {
|
|
res += `rc.${allGlChannels[i]}, `;
|
|
}
|
|
res += 'i*2, ' +
|
|
`rc.${allGlChannels[rank - 1]}`;
|
|
return res;
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./lib/onnxjs/backends/webgl/ops/matmul.ts":
|
|
/*!*************************************************!*\
|
|
!*** ./lib/onnxjs/backends/webgl/ops/matmul.ts ***!
|
|
\*************************************************/
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
// Licensed under the MIT License.
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.getBiasForMatmul = exports.createMatmulProgramInfoLoader = exports.parseMatMulAttributes = exports.matMul = void 0;
|
|
const util_1 = __webpack_require__(/*! ../../../util */ "./lib/onnxjs/util.ts");
|
|
const types_1 = __webpack_require__(/*! ../types */ "./lib/onnxjs/backends/webgl/types.ts");
|
|
const utils_1 = __webpack_require__(/*! ../utils */ "./lib/onnxjs/backends/webgl/utils.ts");
|
|
const fuse_utils_1 = __webpack_require__(/*! ./fuse-utils */ "./lib/onnxjs/backends/webgl/ops/fuse-utils.ts");
|
|
const matmul_pack_1 = __webpack_require__(/*! ./matmul-pack */ "./lib/onnxjs/backends/webgl/ops/matmul-pack.ts");
|
|
const matMul = (inferenceHandler, inputs, attributes) => {
|
|
validateInputs(inputs);
|
|
if (inferenceHandler.session.pack) {
|
|
return [inferenceHandler.run((0, matmul_pack_1.createPackedMatmulProgramInfoLoader)(inferenceHandler, inputs, attributes), inputs)];
|
|
}
|
|
else {
|
|
return [inferenceHandler.run(createMatmulProgramInfoLoader(inputs, attributes), inputs)];
|
|
}
|
|
};
|
|
exports.matMul = matMul;
|
|
const parseMatMulAttributes = (node) => (0, fuse_utils_1.parseInternalActivationAttributes)(node.attributes);
|
|
exports.parseMatMulAttributes = parseMatMulAttributes;
|
|
const createMatmulProgramMetadata = (hasBias, cacheHint) => ({
|
|
name: 'MatMul',
|
|
inputNames: hasBias ? ['A', 'B', 'Bias'] : ['A', 'B'],
|
|
inputTypes: hasBias ? [types_1.TextureType.unpacked, types_1.TextureType.unpacked, types_1.TextureType.unpacked] :
|
|
[types_1.TextureType.unpacked, types_1.TextureType.unpacked],
|
|
cacheHint
|
|
});
|
|
function createMatmulProgramInfo(metadata, inputs, activationAttributes) {
|
|
const aShape = inputs[0].dims;
|
|
const bShape = inputs[1].dims;
|
|
const outputShape = util_1.BroadcastUtil.calcShape(aShape, bShape, true);
|
|
if (!outputShape) {
|
|
throw new Error('Can\'t use matmul on the given tensors');
|
|
}
|
|
const coordsDataType = (0, utils_1.getCoordsDataType)(outputShape.length);
|
|
const allGlChannels = (0, utils_1.getGlChannels)();
|
|
const { activationFunction, applyActivation } = (0, fuse_utils_1.getActivationSnippet)(activationAttributes);
|
|
const hasBias = inputs.length > 2;
|
|
const processBias = hasBias ? 'value += getBiasForMatmul();' : '';
|
|
const getBiasForMatmulSnippet = hasBias ? `${getBiasForMatmul(coordsDataType, allGlChannels, inputs[2].dims, outputShape, false)}` : '';
|
|
const rank = outputShape.length;
|
|
const arank = aShape.length;
|
|
const brank = bShape.length;
|
|
const sharedDim = aShape[aShape.length - 1];
|
|
const shaderSource = `
|
|
${activationFunction}
|
|
${getBiasForMatmulSnippet}
|
|
float process(int indices[${rank}]) {
|
|
int a[${arank}];
|
|
int b[${brank}];
|
|
bcastMatmulIndices_A(indices, a);
|
|
bcastMatmulIndices_B(indices, b);
|
|
|
|
float value;
|
|
for (int k=0; k<${sharedDim}; ++k) {
|
|
a[${arank - 1}] = k;
|
|
b[${brank - 2}] = k;
|
|
value += _A(a) * _B(b);
|
|
}
|
|
${processBias}
|
|
${applyActivation}
|
|
return value;
|
|
}`;
|
|
return Object.assign(Object.assign({}, metadata), { output: { dims: outputShape, type: inputs[0].type, textureType: types_1.TextureType.unpacked }, shaderSource });
|
|
}
|
|
function createMatmulProgramInfoLoader(inputs, activationAttributes) {
|
|
const metadata = createMatmulProgramMetadata(inputs.length > 2, activationAttributes.activationCacheKey);
|
|
return Object.assign(Object.assign({}, metadata), { get: () => createMatmulProgramInfo(metadata, inputs, activationAttributes) });
|
|
}
|
|
exports.createMatmulProgramInfoLoader = createMatmulProgramInfoLoader;
|
|
const validateInputs = (inputs) => {
|
|
if (!inputs || inputs.length !== 2) {
|
|
throw new Error('MatMul requires 2 inputs.');
|
|
}
|
|
if (inputs[0].dims[inputs[0].dims.length - 1] !== inputs[1].dims[inputs[1].dims.length - 2]) {
|
|
throw new Error('shared dimension does not match.');
|
|
}
|
|
if ((inputs[0].type !== 'float32' && inputs[0].type !== 'float64') ||
|
|
(inputs[1].type !== 'float32' && inputs[1].type !== 'float64')) {
|
|
throw new Error('inputs should be float type');
|
|
}
|
|
if (inputs[0].type !== inputs[1].type) {
|
|
throw new Error('inputs types should match');
|
|
}
|
|
};
|
|
function getBiasForMatmul(coordsDataType, allGlChannels, inShape, outShape, isPacked) {
|
|
let unpackedCoordsSnippet = '';
|
|
const inRank = inShape.length;
|
|
const outRank = outShape.length;
|
|
const rankDiff = outRank - inRank;
|
|
if (outRank < 2 && inRank > 0) {
|
|
unpackedCoordsSnippet = 'coords';
|
|
}
|
|
else {
|
|
unpackedCoordsSnippet = inShape.map((s, i) => `coords.${allGlChannels[i + rankDiff]}`).join(', ');
|
|
}
|
|
const broadcastDims = util_1.BroadcastUtil.getBroadcastDims(inShape, outShape);
|
|
const coordsSnippet = broadcastDims.map(d => `coords.${allGlChannels[d + rankDiff]} = 0;`).join('\n');
|
|
const inSize = util_1.ShapeUtil.size(inShape);
|
|
const isInputScalar = inSize === 1;
|
|
let output = 'vec4(outputValue.xx, outputValue.yy)';
|
|
if (isInputScalar) {
|
|
output = 'vec4(outputValue.x)';
|
|
}
|
|
const getBiasForMatmulSource = isPacked ? `
|
|
vec4 getBiasForMatmul() {
|
|
${coordsDataType} coords = getOutputCoords();
|
|
${coordsSnippet}
|
|
vec4 outputValue = getBias(${unpackedCoordsSnippet});
|
|
return ${output};
|
|
}` :
|
|
`
|
|
float getBiasForMatmul() {
|
|
${coordsDataType} coords = getOutputCoords();
|
|
${coordsSnippet}
|
|
return getBias(coords.x);
|
|
}`;
|
|
return getBiasForMatmulSource;
|
|
}
|
|
exports.getBiasForMatmul = getBiasForMatmul;
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./lib/onnxjs/backends/webgl/ops/pack.ts":
|
|
/*!***********************************************!*\
|
|
!*** ./lib/onnxjs/backends/webgl/ops/pack.ts ***!
|
|
\***********************************************/
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
// Licensed under the MIT License.
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.createPackProgramInfoLoader = void 0;
|
|
const glsl_source_1 = __webpack_require__(/*! ../glsl-source */ "./lib/onnxjs/backends/webgl/glsl-source.ts");
|
|
const types_1 = __webpack_require__(/*! ../types */ "./lib/onnxjs/backends/webgl/types.ts");
|
|
const utils_1 = __webpack_require__(/*! ../utils */ "./lib/onnxjs/backends/webgl/utils.ts");
|
|
const packing_utils_1 = __webpack_require__(/*! ./packing-utils */ "./lib/onnxjs/backends/webgl/ops/packing-utils.ts");
|
|
const packProgramMetadata = {
|
|
name: 'pack',
|
|
inputNames: ['A'],
|
|
inputTypes: [types_1.TextureType.unpackedReversed]
|
|
};
|
|
const createPackProgramInfo = (handler, input) => {
|
|
const glsl = (0, glsl_source_1.getGlsl)(handler.session.backend.glContext.version);
|
|
const inputShape = input.dims;
|
|
const inputRank = inputShape.length;
|
|
// createTextureLayoutFromShape won't change output rank. Need to verify by running tests
|
|
const outputRank = input.dims.length;
|
|
const coordsDataType = (0, utils_1.getCoordsDataType)(outputRank);
|
|
const channels = (0, packing_utils_1.getChannels)('rc', outputRank);
|
|
const setup = getSetup(outputRank, channels, inputShape[inputShape.length - 2], inputShape[inputShape.length - 1]);
|
|
let reversedInputWH;
|
|
if (inputRank === 0) {
|
|
reversedInputWH = [1, 1];
|
|
}
|
|
else if (inputRank === 1) {
|
|
reversedInputWH = [inputShape[0], 1];
|
|
}
|
|
else {
|
|
reversedInputWH = [inputShape[outputRank - 1], inputShape[outputRank - 2]];
|
|
}
|
|
const outOfBoundsCondition = getOutOfBoundsCondition(outputRank, reversedInputWH, channels);
|
|
const output = getOutput(inputShape, channels);
|
|
const shaderSource = `
|
|
void main() {
|
|
${coordsDataType} rc = getOutputCoords();
|
|
|
|
if(${outOfBoundsCondition}) {
|
|
${glsl.output} = vec4(0);
|
|
} else {
|
|
${setup}
|
|
|
|
${glsl.output} = vec4(${output});
|
|
}
|
|
}
|
|
`;
|
|
return Object.assign(Object.assign({}, packProgramMetadata), { hasMain: true, output: { dims: input.dims, type: input.type, textureType: types_1.TextureType.packed }, shaderSource });
|
|
};
|
|
const createPackProgramInfoLoader = (handler, input) => (Object.assign(Object.assign({}, packProgramMetadata), { get: () => createPackProgramInfo(handler, input) }));
|
|
exports.createPackProgramInfoLoader = createPackProgramInfoLoader;
|
|
/**
|
|
* check output coordinate location and return false if it is outside input's width/height boundary
|
|
*/
|
|
function getOutOfBoundsCondition(rank, shape, dims) {
|
|
if (rank === 0) {
|
|
return 'false';
|
|
}
|
|
if (rank === 1) {
|
|
return `rc > ${shape[0]}`;
|
|
}
|
|
let cond = '';
|
|
for (let i = rank - 2; i < rank; i++) {
|
|
cond += `${dims[i]} >= ${shape[i - rank + 2]}`;
|
|
if (i < rank - 1) {
|
|
cond += '||';
|
|
}
|
|
}
|
|
return cond;
|
|
}
|
|
/**
|
|
* code snippet to sample input texture with output coordiantes
|
|
*/
|
|
function getOutput(shape, dims) {
|
|
const rank = shape.length;
|
|
if (rank === 0) {
|
|
return 'getA(), 0, 0, 0';
|
|
}
|
|
if (rank === 1) {
|
|
return `getA(rc),
|
|
rc + 1 >= ${shape[0]} ? 0. : getA(rc + 1),
|
|
0, 0`;
|
|
}
|
|
const coord00 = 'r, c';
|
|
const coord01 = 'r, cp1';
|
|
const coord10 = 'rp1, c';
|
|
const coord11 = 'rp1, cp1';
|
|
let D = '';
|
|
if (rank > 2) {
|
|
for (let i = 0; i < rank - 2; ++i) {
|
|
D = D + `${dims[i]},`;
|
|
}
|
|
}
|
|
return `getA(${D}${coord00}),
|
|
rEdge ? 0. : getA(${D}${coord10}),
|
|
cEdge ? 0. : getA(${D}${coord01}),
|
|
rEdge || cEdge ? 0. : getA(${D}${coord11})`;
|
|
}
|
|
/**
|
|
* code snippet to setup 4 coordinates and edge conditions
|
|
*/
|
|
function getSetup(rank, dims, rows, cols) {
|
|
if (rank === 0 || rank === 1) {
|
|
return '';
|
|
}
|
|
// rank >= 2 for width+height pack.
|
|
else {
|
|
const setup = `
|
|
int r = ${dims[rank - 2]};
|
|
int c = ${dims[rank - 1]};
|
|
int rp1 = ${dims[rank - 2]} + 1;
|
|
int cp1 = ${dims[rank - 1]} + 1;
|
|
bool rEdge = rp1 >= ${cols};
|
|
bool cEdge = cp1 >= ${rows};
|
|
`;
|
|
return setup;
|
|
}
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./lib/onnxjs/backends/webgl/ops/packing-utils.ts":
|
|
/*!********************************************************!*\
|
|
!*** ./lib/onnxjs/backends/webgl/ops/packing-utils.ts ***!
|
|
\********************************************************/
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
// Licensed under the MIT License.
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.unpackFromChannel = exports.getChannels = exports.getVecChannels = void 0;
|
|
const utils_1 = __webpack_require__(/*! ../utils */ "./lib/onnxjs/backends/webgl/utils.ts");
|
|
function getVecChannels(name, rank) {
|
|
return (0, utils_1.getGlChannels)(rank).map(d => `${name}.${d}`);
|
|
}
|
|
exports.getVecChannels = getVecChannels;
|
|
function getChannels(name, rank) {
|
|
if (rank === 1) {
|
|
return [name];
|
|
}
|
|
return getVecChannels(name, rank);
|
|
}
|
|
exports.getChannels = getChannels;
|
|
function unpackFromChannel() {
|
|
return `
|
|
float getChannel(vec4 frag, int dim) {
|
|
int modCoord = imod(dim, 2);
|
|
return modCoord == 0 ? frag.r : frag.g;
|
|
}
|
|
|
|
float getChannel(vec4 frag, vec2 innerDims) {
|
|
vec2 modCoord = mod(innerDims, 2.);
|
|
return modCoord.x == 0. ?
|
|
(modCoord.y == 0. ? frag.r : frag.g) :
|
|
(modCoord.y == 0. ? frag.b : frag.a);
|
|
}
|
|
`;
|
|
}
|
|
exports.unpackFromChannel = unpackFromChannel;
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./lib/onnxjs/backends/webgl/ops/pad.ts":
|
|
/*!**********************************************!*\
|
|
!*** ./lib/onnxjs/backends/webgl/ops/pad.ts ***!
|
|
\**********************************************/
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
// Licensed under the MIT License.
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.parsePadAttributesV11 = exports.padV11 = exports.parsePadAttributesV2 = exports.padV2 = void 0;
|
|
const attribute_with_cache_key_1 = __webpack_require__(/*! ../../../attribute-with-cache-key */ "./lib/onnxjs/attribute-with-cache-key.ts");
|
|
const util_1 = __webpack_require__(/*! ../../../util */ "./lib/onnxjs/util.ts");
|
|
const glsl_source_1 = __webpack_require__(/*! ../glsl-source */ "./lib/onnxjs/backends/webgl/glsl-source.ts");
|
|
const types_1 = __webpack_require__(/*! ../types */ "./lib/onnxjs/backends/webgl/types.ts");
|
|
const padProgramMetadata = {
|
|
name: 'Pad',
|
|
inputNames: ['A'],
|
|
inputTypes: [types_1.TextureType.unpacked],
|
|
};
|
|
const padV2 = (inferenceHandler, inputs, attributes) => {
|
|
validateInputsV2(inputs);
|
|
const output = inferenceHandler.run(Object.assign(Object.assign({}, padProgramMetadata), { cacheHint: attributes.cacheKey, get: () => createPadProgramInfo(inferenceHandler, inputs[0], attributes) }), inputs);
|
|
return [output];
|
|
};
|
|
exports.padV2 = padV2;
|
|
const parsePadAttributesV2 = (node) => {
|
|
const mode = node.attributes.getString('mode', 'constant');
|
|
const value = node.attributes.getFloat('value', 0.0);
|
|
const pads = node.attributes.getInts('pads');
|
|
return (0, attribute_with_cache_key_1.createAttributeWithCacheKey)({ mode, value, pads });
|
|
};
|
|
exports.parsePadAttributesV2 = parsePadAttributesV2;
|
|
const padV11 = (inferenceHandler, inputs, mode) => {
|
|
validateInputsV11(inputs);
|
|
const attrubutes = generatePadAttributesFromInputs(inferenceHandler, inputs, mode);
|
|
return (0, exports.padV2)(inferenceHandler, [inputs[0]], attrubutes);
|
|
};
|
|
exports.padV11 = padV11;
|
|
const parsePadAttributesV11 = (node) => node.attributes.getString('mode', 'constant');
|
|
exports.parsePadAttributesV11 = parsePadAttributesV11;
|
|
const generatePadAttributesFromInputs = (inferenceHandler, inputs, mode) => {
|
|
if (!inferenceHandler.session.isInitializer(inputs[1].dataId) ||
|
|
(inputs.length >= 3 && !inferenceHandler.session.isInitializer(inputs[2].dataId))) {
|
|
throw new Error('dynamic pad attributes are not allowed');
|
|
}
|
|
const pads = Array.from(inputs[1].integerData);
|
|
const value = (inputs.length >= 3) ? inputs[2].floatData[0] : 0.0;
|
|
return (0, attribute_with_cache_key_1.createAttributeWithCacheKey)({ mode, pads, value });
|
|
};
|
|
const createPadProgramInfo = (inferenceHandler, input, attributes) => {
|
|
const outputShape = util_1.ShapeUtil.padShape(input.dims.slice(), attributes.pads);
|
|
const rank = outputShape.length;
|
|
const padFunction = getPadFunction(inferenceHandler, input, attributes);
|
|
const shaderSource = `
|
|
${padFunction}
|
|
float process(int[${rank}] indices) {
|
|
return padA(indices);
|
|
}`;
|
|
return {
|
|
name: 'Pad',
|
|
inputNames: ['A'],
|
|
inputTypes: [types_1.TextureType.unpacked],
|
|
output: { dims: outputShape, type: input.type, textureType: types_1.TextureType.unpacked },
|
|
shaderSource
|
|
};
|
|
};
|
|
const validateInputsV2 = (inputs) => {
|
|
if (!inputs || inputs.length !== 1) {
|
|
throw new Error('Pad requires 1 input');
|
|
}
|
|
if (inputs[0].type !== 'float32' && inputs[0].type !== 'float64') {
|
|
throw new Error('Invalid input type.');
|
|
}
|
|
};
|
|
const validateInputsV11 = (inputs) => {
|
|
if (!inputs || (inputs.length !== 2 && inputs.length !== 3)) {
|
|
throw new Error('Pad requires 2 or 3 inputs');
|
|
}
|
|
if (inputs[1].type !== 'int32') {
|
|
throw new Error('Invalid input type.');
|
|
}
|
|
if (inputs.length >= 3 && inputs[2].type === 'string') {
|
|
throw new Error('Invalid input type.');
|
|
}
|
|
};
|
|
const getPadFunction = (inferenceHandler, input, attributes) => {
|
|
const glsl = (0, glsl_source_1.getGlsl)(inferenceHandler.session.backend.glContext.version);
|
|
const [width, height] = inferenceHandler.calculateTextureWidthAndHeight(input.dims, types_1.TextureType.unpacked);
|
|
const strides = util_1.ShapeUtil.computeStrides(input.dims);
|
|
switch (attributes.mode) {
|
|
case 'constant':
|
|
return getPadConstant(glsl, input.dims, strides, width, height, attributes.pads, attributes.value);
|
|
case 'reflect':
|
|
return getPadReflect(glsl, input.dims, strides, width, height, attributes.pads);
|
|
case 'edge':
|
|
return getPadEdge(glsl, input.dims, strides, width, height, attributes.pads);
|
|
default:
|
|
throw new Error('Invalid mode');
|
|
}
|
|
};
|
|
const getPadConstant = (glsl, shape, strides, width, height, pads, value) => {
|
|
const rank = shape.length;
|
|
let block = '';
|
|
for (let i = rank - 1; i >= 0; --i) {
|
|
block += `
|
|
k = m[${i}] - ${pads[i]};
|
|
if (k < 0) return constant;
|
|
if (k >= ${shape[i]}) return constant;
|
|
offset += k * ${strides[i]};
|
|
`;
|
|
}
|
|
return `
|
|
float padA(int m[${rank}]) {
|
|
const float constant = float(${value});
|
|
int offset = 0;
|
|
int k = 0;
|
|
${block}
|
|
vec2 coords = offsetToCoords(offset, ${width}, ${height});
|
|
float value = getColorAsFloat(${glsl.texture2D}(A, coords));
|
|
return value;
|
|
}
|
|
`;
|
|
};
|
|
const getPadReflect = (glsl, shape, strides, width, height, pads) => {
|
|
const rank = shape.length;
|
|
let block = '';
|
|
for (let i = rank - 1; i >= 0; --i) {
|
|
block += `
|
|
k = m[${i}] - ${pads[i]};
|
|
if (k < 0) { k = -k; }
|
|
{
|
|
const int _2n_1 = ${2 * (shape[i] - 1)};
|
|
k = int( mod( float(k), float(_2n_1) ) ) ;
|
|
if(k >= ${shape[i]}) { k = _2n_1 - k; }
|
|
}
|
|
offset += k * ${strides[i]};
|
|
`;
|
|
}
|
|
return `
|
|
float padA(int m[${rank}]) {
|
|
int offset = 0;
|
|
int k = 0;
|
|
${block}
|
|
vec2 coords = offsetToCoords(offset, ${width}, ${height});
|
|
float value = getColorAsFloat(${glsl.texture2D}(A, coords));
|
|
return value;
|
|
}
|
|
`;
|
|
};
|
|
const getPadEdge = (glsl, shape, strides, width, height, pads) => {
|
|
const rank = shape.length;
|
|
let block = '';
|
|
for (let i = rank - 1; i >= 0; --i) {
|
|
block += `
|
|
k = m[${i}] - ${pads[i]};
|
|
if (k < 0) k = 0;
|
|
if (k >= ${shape[i]}) k = ${shape[i] - 1};
|
|
offset += k * ${strides[i]};
|
|
`;
|
|
}
|
|
return `
|
|
float padA(int m[${rank}]) {
|
|
int offset = 0;
|
|
int k = 0;
|
|
${block}
|
|
vec2 coords = offsetToCoords(offset, ${width}, ${height});
|
|
float value = getColorAsFloat(${glsl.texture2D}(A, coords));
|
|
return value;
|
|
}
|
|
`;
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./lib/onnxjs/backends/webgl/ops/pool.ts":
|
|
/*!***********************************************!*\
|
|
!*** ./lib/onnxjs/backends/webgl/ops/pool.ts ***!
|
|
\***********************************************/
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
// Licensed under the MIT License.
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.globalMaxPool = exports.parseMaxPoolAttributes = exports.maxPool = exports.parseGlobalAveragePoolAttributes = exports.globalAveragePool = exports.parseAveragePoolAttributes = exports.averagePool = void 0;
|
|
const attribute_with_cache_key_1 = __webpack_require__(/*! ../../../attribute-with-cache-key */ "./lib/onnxjs/attribute-with-cache-key.ts");
|
|
const util_1 = __webpack_require__(/*! ../../../util */ "./lib/onnxjs/util.ts");
|
|
const types_1 = __webpack_require__(/*! ../types */ "./lib/onnxjs/backends/webgl/types.ts");
|
|
const averagePool = (inferenceHandler, inputs, attributes) => {
|
|
validateInputs(inputs);
|
|
const metadata = { name: 'AveragePool', inputNames: ['X'], inputTypes: [types_1.TextureType.unpacked], cacheHint: attributes.cacheKey };
|
|
const output = inferenceHandler.run(Object.assign(Object.assign({}, metadata), { get: () => createAveragePoolProgramInfo(inputs, metadata, false, attributes) }), inputs);
|
|
return [output];
|
|
};
|
|
exports.averagePool = averagePool;
|
|
const parseAveragePoolAttributes = (node) => {
|
|
const autoPad = node.attributes.getString('auto_pad', 'NOTSET');
|
|
const ceilMode = node.attributes.getInt('ceil_mode', 0);
|
|
const countIncludePad = (node.attributes.getInt('count_include_pad', 0) === 0 ? false : true);
|
|
const kernelShape = node.attributes.getInts('kernel_shape');
|
|
const strides = node.attributes.getInts('strides', []);
|
|
const pads = node.attributes.getInts('pads', []);
|
|
// TODO: support attribute 'ceil_mode'
|
|
if (ceilMode !== 0) {
|
|
throw new Error('using ceil() in shape computation is not yet supported for AveragePool');
|
|
}
|
|
return (0, attribute_with_cache_key_1.createAttributeWithCacheKey)({ autoPad, ceilMode, countIncludePad, kernelShape, strides, pads });
|
|
};
|
|
exports.parseAveragePoolAttributes = parseAveragePoolAttributes;
|
|
const createAveragePoolProgramInfo = (inputs, metadata, isGlobalOperator, attributes) => {
|
|
const [adjustedAttributes, outputShape] = getAdjustedPoolAttributesAndOutputShape(inputs, attributes, isGlobalOperator);
|
|
const kernelSize = util_1.ShapeUtil.size(adjustedAttributes.kernelShape);
|
|
const op1 = 'value += _X(x);';
|
|
let op2 = '';
|
|
if (adjustedAttributes.countIncludePad) {
|
|
op2 += `value /= float(${kernelSize});`;
|
|
}
|
|
else {
|
|
op2 += `value /= float(${kernelSize} - pad);`;
|
|
}
|
|
const poolingCode = generatePoolingCode(inputs[0].dims, adjustedAttributes, op1, op2, '0.0');
|
|
const shaderSource = `
|
|
${poolingCode}
|
|
`;
|
|
return Object.assign(Object.assign({}, metadata), { output: { dims: outputShape, type: inputs[0].type, textureType: types_1.TextureType.unpacked }, shaderSource });
|
|
};
|
|
const globalAveragePool = (inferenceHandler, inputs, attributes) => {
|
|
validateInputs(inputs);
|
|
const metadata = {
|
|
name: 'GlobalAveragePool',
|
|
inputNames: ['X'],
|
|
inputTypes: [types_1.TextureType.unpacked],
|
|
cacheHint: `${attributes.countIncludePad}`
|
|
};
|
|
const output = inferenceHandler.run(Object.assign(Object.assign({}, metadata), { get: () => createAveragePoolProgramInfo(inputs, metadata, true, attributes) }), inputs);
|
|
return [output];
|
|
};
|
|
exports.globalAveragePool = globalAveragePool;
|
|
const parseGlobalAveragePoolAttributes = (node) => {
|
|
const countIncludePad = (node.attributes.getInt('count_include_pad', 0) === 0 ? false : true);
|
|
return (0, attribute_with_cache_key_1.createAttributeWithCacheKey)({ autoPad: '', ceilMode: 0, countIncludePad, kernelShape: [], strides: [], pads: [] });
|
|
};
|
|
exports.parseGlobalAveragePoolAttributes = parseGlobalAveragePoolAttributes;
|
|
const maxPool = (inferenceHandler, inputs, attributes) => {
|
|
validateInputs(inputs);
|
|
const metadata = { name: 'MaxPool', inputNames: ['X'], inputTypes: [types_1.TextureType.unpacked], cacheHint: attributes.cacheKey };
|
|
const output = inferenceHandler.run(Object.assign(Object.assign({}, metadata), { get: () => createMaxPoolProgramInfo(inputs, metadata, false, attributes) }), inputs);
|
|
return [output];
|
|
};
|
|
exports.maxPool = maxPool;
|
|
const parseMaxPoolAttributes = (node) => {
|
|
const autoPad = node.attributes.getString('auto_pad', 'NOTSET');
|
|
const ceilMode = node.attributes.getInt('ceil_mode', 0);
|
|
const kernelShape = node.attributes.getInts('kernel_shape');
|
|
const strides = node.attributes.getInts('strides', []);
|
|
const pads = node.attributes.getInts('pads', []);
|
|
const storageOrder = node.attributes.getInt('storage_order', 0);
|
|
const dilations = node.attributes.getInts('dilations', []);
|
|
// TODO: support attribute 'ceil_mode' and 'storage_order'
|
|
if (storageOrder !== 0) {
|
|
throw new Error('column major storage order is not yet supported for MaxPool');
|
|
}
|
|
if (ceilMode !== 0) {
|
|
throw new Error('using ceil() in shape computation is not yet supported for MaxPool');
|
|
}
|
|
return (0, attribute_with_cache_key_1.createAttributeWithCacheKey)({ autoPad, ceilMode, countIncludePad: false, kernelShape, strides, pads, storageOrder, dilations });
|
|
};
|
|
exports.parseMaxPoolAttributes = parseMaxPoolAttributes;
|
|
const createMaxPoolProgramInfo = (inputs, metadata, isGlobalOperator, attributes) => {
|
|
const [adjustedAttributes, outputShape] = getAdjustedPoolAttributesAndOutputShape(inputs, attributes, isGlobalOperator);
|
|
const op1 = `
|
|
value = max(_X(x), value);
|
|
`;
|
|
const op2 = '';
|
|
const poolingCode = generatePoolingCode(inputs[0].dims, adjustedAttributes, op1, op2, '-1e5');
|
|
const shaderSource = `
|
|
${poolingCode}
|
|
`;
|
|
return Object.assign(Object.assign({}, metadata), { output: { dims: outputShape, type: inputs[0].type, textureType: types_1.TextureType.unpacked }, shaderSource });
|
|
};
|
|
const getAdjustedPoolAttributesAndOutputShape = (inputs, attributes, isGlobalOperator) => {
|
|
const inputShape = inputs[0].dims.slice();
|
|
const hasDilations = Object.hasOwnProperty.call(attributes, 'dilations');
|
|
const kernelShape = attributes.kernelShape.slice();
|
|
const strides = attributes.strides.slice();
|
|
const dilations = hasDilations ? attributes.dilations.slice() : [];
|
|
const pads = attributes.pads.slice();
|
|
util_1.PoolConvUtil.adjustPoolAttributes(isGlobalOperator, inputShape, kernelShape, strides, dilations, pads);
|
|
const outputShape = util_1.PoolConvUtil.computePoolOutputShape(isGlobalOperator, inputShape, strides, dilations, kernelShape, pads, attributes.autoPad);
|
|
const newAttributes = Object.assign({}, attributes);
|
|
if (hasDilations) {
|
|
Object.assign(newAttributes, { kernelShape, strides, pads, dilations, cacheKey: attributes.cacheKey });
|
|
}
|
|
else {
|
|
Object.assign(newAttributes, { kernelShape, strides, pads, cacheKey: attributes.cacheKey });
|
|
}
|
|
return [newAttributes, outputShape];
|
|
};
|
|
const globalMaxPoolAttributes = {
|
|
autoPad: '',
|
|
ceilMode: 0,
|
|
countIncludePad: false,
|
|
kernelShape: [],
|
|
strides: [],
|
|
pads: [],
|
|
storageOrder: 0,
|
|
dilations: [],
|
|
cacheKey: ''
|
|
};
|
|
const globalMaxPoolMetadata = {
|
|
name: 'GlobalMaxPool',
|
|
inputNames: ['X'],
|
|
inputTypes: [types_1.TextureType.unpacked]
|
|
};
|
|
const globalMaxPool = (inferenceHandler, inputs) => {
|
|
validateInputs(inputs);
|
|
const output = inferenceHandler.run(Object.assign(Object.assign({}, globalMaxPoolMetadata), { get: () => createMaxPoolProgramInfo(inputs, globalMaxPoolMetadata, true, globalMaxPoolAttributes) }), inputs);
|
|
return [output];
|
|
};
|
|
exports.globalMaxPool = globalMaxPool;
|
|
const validateInputs = (inputs) => {
|
|
if (!inputs || inputs.length !== 1) {
|
|
throw new Error('Pool ops requires 1 input.');
|
|
}
|
|
if (inputs[0].type !== 'float32' && inputs[0].type !== 'float64') {
|
|
throw new Error('Invalid input type.');
|
|
}
|
|
};
|
|
const generatePoolingCode = (inputDims, attributes, op1, op2, start) => {
|
|
const rank = inputDims.length;
|
|
if (attributes.kernelShape.length <= 2) {
|
|
const kw = attributes.kernelShape[attributes.kernelShape.length - 1];
|
|
const sw = attributes.strides[attributes.strides.length - 1];
|
|
const pwStart = attributes.pads[attributes.pads.length / 2 - 1];
|
|
const pwEnd = attributes.pads[attributes.pads.length - 1];
|
|
const dimW = inputDims[rank - 1];
|
|
let codeW = '';
|
|
let codeH = '';
|
|
let codeHEnd = '';
|
|
if (pwStart + pwEnd !== 0) {
|
|
codeW = `
|
|
for (int i = 0; i < ${kw}; i++) {
|
|
x[${rank} - 1] = indices[${rank} - 1] * ${sw} - ${pwStart} + i;
|
|
if (x[${rank} - 1] < 0 || x[${rank} - 1] >= ${dimW}) {
|
|
pad++;
|
|
continue;
|
|
}
|
|
${op1}
|
|
}`;
|
|
}
|
|
else {
|
|
codeW = `
|
|
for (int i = 0; i < ${kw}; i++) {
|
|
x[${rank} - 1] = indices[${rank} - 1] * ${sw} - ${pwStart} + i;
|
|
${op1}
|
|
}`;
|
|
}
|
|
if (attributes.kernelShape.length === 2) {
|
|
const kh = attributes.kernelShape[attributes.kernelShape.length - 2];
|
|
const sh = attributes.strides[attributes.strides.length - 2];
|
|
const phStart = attributes.pads[attributes.pads.length / 2 - 2];
|
|
const phEnd = attributes.pads[attributes.pads.length - 2];
|
|
const dimH = inputDims[rank - 2];
|
|
if (phStart + phEnd !== 0) {
|
|
codeH = `
|
|
for (int j = 0; j < ${kh}; j++) {
|
|
x[${rank} - 2] = indices[${rank} - 2] * ${sh} - ${phStart} + j;
|
|
if (x[${rank} - 2] < 0 || x[${rank} - 2] >= ${dimH}) {
|
|
pad+= ${kw};
|
|
continue;
|
|
}
|
|
`;
|
|
}
|
|
else {
|
|
codeH = `
|
|
for (int j = 0; j < ${kh}; j++) {
|
|
x[${rank} - 2] = indices[${rank} - 2] * ${sh} - ${phStart} + j;
|
|
`;
|
|
}
|
|
codeHEnd = `
|
|
}
|
|
`;
|
|
}
|
|
const poolingCode = `
|
|
float process(int indices[${rank}]) {
|
|
int x[${rank}];
|
|
copyVec(indices, x);
|
|
|
|
float value = ${start};
|
|
int pad = 0;
|
|
${codeH}
|
|
${codeW}
|
|
${codeHEnd}
|
|
${op2}
|
|
return value;
|
|
}
|
|
`;
|
|
return poolingCode;
|
|
}
|
|
else {
|
|
const kernelSize = util_1.ShapeUtil.size(attributes.kernelShape);
|
|
const kernelStrides = util_1.ShapeUtil.computeStrides(attributes.kernelShape);
|
|
const stridesRank = kernelStrides.length;
|
|
const padsRank = attributes.pads.length;
|
|
const offsetToIndicesFunction = offsetToIndices(stridesRank);
|
|
const copyInputDims = copyArray(inputDims, 'inputDims');
|
|
const copyPads = copyArray(attributes.pads, 'pads');
|
|
const copyKernelStrides = copyArray(kernelStrides, 'kernelStrides');
|
|
const copyStrides = copyArray(attributes.strides, 'strides');
|
|
const hasPads = attributes.pads.reduce((sum, cur) => sum + cur);
|
|
let padCode = '';
|
|
if (hasPads) {
|
|
padCode = `
|
|
if (x[j] >= inputDims[j] || x[j] < 0) {
|
|
pad++;
|
|
isPad = true;
|
|
break;
|
|
}
|
|
}
|
|
if (!isPad) {
|
|
${op1}
|
|
}`;
|
|
}
|
|
else {
|
|
padCode = `
|
|
}
|
|
${op1}
|
|
`;
|
|
}
|
|
const poolingCode = `
|
|
${offsetToIndicesFunction}
|
|
float process(int indices[${rank}]) {
|
|
int x[${rank}];
|
|
copyVec(indices, x);
|
|
int offset[${stridesRank}];
|
|
int pads[${padsRank}];
|
|
int inputDims[${rank}];
|
|
int kernelStrides[${stridesRank}];
|
|
int strides[${stridesRank}];
|
|
${copyPads}
|
|
${copyInputDims}
|
|
${copyStrides}
|
|
${copyKernelStrides}
|
|
|
|
float value = ${start};
|
|
int pad = 0;
|
|
bool isPad = false;
|
|
for (int i = 0; i < ${kernelSize}; i++) {
|
|
offsetToIndices(i, kernelStrides, offset);
|
|
isPad = false;
|
|
for (int j = ${rank} - ${stridesRank}; j < ${rank}; j++) {
|
|
x[j] = indices[j] * strides[j - ${rank} + ${stridesRank}]
|
|
+ offset[j - ${rank} + ${stridesRank}] - pads[j - 2];
|
|
${padCode}
|
|
}
|
|
${op2}
|
|
|
|
return value;
|
|
}
|
|
`;
|
|
return poolingCode;
|
|
}
|
|
};
|
|
const copyArray = (array, arrayName) => {
|
|
let block = '';
|
|
for (let i = 0; i < array.length; i++) {
|
|
block += `
|
|
${arrayName}[${i}] = ${array[i]};
|
|
`;
|
|
}
|
|
return block;
|
|
};
|
|
const offsetToIndices = (rank) => `
|
|
void offsetToIndices(int offset, int[${rank}] strides, out int[${rank}] indices) {
|
|
if (${rank} == 0) {
|
|
return;
|
|
}
|
|
for (int i = 0; i < ${rank} - 1; ++i) {
|
|
indices[i] = offset / strides[i];
|
|
offset -= indices[i] * strides[i];
|
|
}
|
|
indices[${rank} - 1] = offset;
|
|
}`;
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./lib/onnxjs/backends/webgl/ops/reduce.ts":
|
|
/*!*************************************************!*\
|
|
!*** ./lib/onnxjs/backends/webgl/ops/reduce.ts ***!
|
|
\*************************************************/
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
// Licensed under the MIT License.
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.reduceLogSumSquare = exports.reduceLogSum = exports.reduceProd = exports.reduceMin = exports.reduceMax = exports.reduceMean = exports.reduceSum = exports.parseReduceAttributes = void 0;
|
|
const attribute_with_cache_key_1 = __webpack_require__(/*! ../../../attribute-with-cache-key */ "./lib/onnxjs/attribute-with-cache-key.ts");
|
|
const operators_1 = __webpack_require__(/*! ../../../operators */ "./lib/onnxjs/operators.ts");
|
|
const util_1 = __webpack_require__(/*! ../../../util */ "./lib/onnxjs/util.ts");
|
|
const types_1 = __webpack_require__(/*! ../types */ "./lib/onnxjs/backends/webgl/types.ts");
|
|
const reduce = (inferenceHandler, inputs, attributes, name, reduceOp) => {
|
|
validateInputs(inputs);
|
|
const reduceProgramMetadata = {
|
|
name,
|
|
inputNames: ['A'],
|
|
inputTypes: [types_1.TextureType.unpacked],
|
|
};
|
|
const output = inferenceHandler.run(Object.assign(Object.assign({}, reduceProgramMetadata), { cacheHint: attributes.cacheKey, get: () => createReduceProgramInfo(inferenceHandler, inputs, attributes, name, reduceOp, reduceProgramMetadata) }), inputs);
|
|
return [output];
|
|
};
|
|
const parseReduceAttributes = (node) => {
|
|
const axes = node.attributes.getInts('axes', []);
|
|
const keepDims = node.attributes.getInt('keepdims', 1) === 1;
|
|
return (0, attribute_with_cache_key_1.createAttributeWithCacheKey)({ axes, keepDims });
|
|
};
|
|
exports.parseReduceAttributes = parseReduceAttributes;
|
|
const createReduceProgramInfo = (handler, inputs, attributes, name, reduceOp, reduceProgramMetadata) => {
|
|
const outputShape = [];
|
|
const iRank = inputs[0].dims.length || 1;
|
|
const idxCopy = []; // copy output indexes to input indexes
|
|
const axes = util_1.ShapeUtil.normalizeAxes(attributes.axes, inputs[0].dims.length);
|
|
const ops = reduceOp(inputs, axes);
|
|
let reduceOps = ops[1];
|
|
for (let k = 0; k < inputs[0].dims.length; k++) {
|
|
// if this axis is reduced
|
|
if (axes.indexOf(k) >= 0 || axes.length === 0) {
|
|
if (attributes.keepDims) {
|
|
outputShape.push(1);
|
|
} // else { remove the axis from outputShape; }
|
|
// loop over the d-th axis
|
|
reduceOps = `
|
|
for(int j${k} = 0; j${k} < ${inputs[0].dims[k]}; j${k}++) {
|
|
inputIdx[${k}] = j${k};
|
|
${reduceOps}
|
|
}`;
|
|
}
|
|
else {
|
|
idxCopy.push(`inputIdx[${k}] = outputIdx[${outputShape.length}];`);
|
|
outputShape.push(inputs[0].dims[k]);
|
|
}
|
|
}
|
|
const oRank = outputShape.length || 1;
|
|
const shaderSource = `
|
|
float process(int outputIdx[${oRank}]) {
|
|
float value; // final result
|
|
int inputIdx[${iRank}]; // addressing input data
|
|
${idxCopy.join('\n')}
|
|
${ops[0]} // init ops for reduce max/min
|
|
${reduceOps}
|
|
${ops[2]} // final computation for reduce mean
|
|
return value;
|
|
}`;
|
|
return Object.assign(Object.assign({}, reduceProgramMetadata), { output: { dims: outputShape, type: inputs[0].type, textureType: types_1.TextureType.unpacked }, shaderSource });
|
|
};
|
|
const validateInputs = (inputs) => {
|
|
if (!inputs || inputs.length !== 1) {
|
|
throw new Error('Reduce op requires 1 input.');
|
|
}
|
|
if (operators_1.NUMBER_TYPES.indexOf(inputs[0].type) === -1) {
|
|
throw new Error('Invalid input type.');
|
|
}
|
|
};
|
|
const reduceSum = (inferenceHandler, inputs, attributes) => {
|
|
const reduceOp = () => ['value = 0.0;', 'value += _A(inputIdx);', ''];
|
|
return reduce(inferenceHandler, inputs, attributes, 'ReduceSum', reduceOp);
|
|
};
|
|
exports.reduceSum = reduceSum;
|
|
const reduceMean = (inferenceHandler, inputs, attributes) => {
|
|
const reduceOp = (inputs, axes) => {
|
|
let size = 1.0;
|
|
for (let k = 0; k < inputs[0].dims.length; k++) {
|
|
if (axes.indexOf(k) >= 0 || axes.length === 0) {
|
|
size *= inputs[0].dims[k];
|
|
}
|
|
}
|
|
return ['value = 0.0;', 'value += _A(inputIdx);', `value /= ${size}.;`]; // ensure real number with `.`
|
|
};
|
|
return reduce(inferenceHandler, inputs, attributes, 'ReduceMean', reduceOp);
|
|
};
|
|
exports.reduceMean = reduceMean;
|
|
const reduceMax = (inferenceHandler, inputs, attributes) => {
|
|
const reduceOp = (inputs, axes) => {
|
|
const idxZero = [];
|
|
for (let k = 0; k < inputs[0].dims.length; k++) {
|
|
if (axes.indexOf(k) >= 0 || axes.length === 0) {
|
|
idxZero.push(`inputIdx[${k}] = 0;`); // first element
|
|
}
|
|
}
|
|
return [`${idxZero.join('\n')}\nvalue = _A(inputIdx);`, 'value = max(value, _A(inputIdx));', ''];
|
|
};
|
|
return reduce(inferenceHandler, inputs, attributes, 'ReduceMax', reduceOp);
|
|
};
|
|
exports.reduceMax = reduceMax;
|
|
const reduceMin = (inferenceHandler, inputs, attributes) => {
|
|
const reduceOp = (inputs, axes) => {
|
|
const idxZero = [];
|
|
for (let k = 0; k < inputs[0].dims.length; k++) {
|
|
if (axes.indexOf(k) >= 0 || axes.length === 0) {
|
|
idxZero.push(`inputIdx[${k}] = 0;`); // first element
|
|
}
|
|
}
|
|
return [`${idxZero.join('\n')}\nvalue = _A(inputIdx);`, 'value = min(value, _A(inputIdx));', ''];
|
|
};
|
|
return reduce(inferenceHandler, inputs, attributes, 'ReduceMin', reduceOp);
|
|
};
|
|
exports.reduceMin = reduceMin;
|
|
const reduceProd = (inferenceHandler, inputs, attributes) => {
|
|
const reduceOp = () => ['value = 1.0;', 'value *= _A(inputIdx);', ''];
|
|
return reduce(inferenceHandler, inputs, attributes, 'ReduceProd', reduceOp);
|
|
};
|
|
exports.reduceProd = reduceProd;
|
|
const reduceLogSum = (inferenceHandler, inputs, attributes) => {
|
|
const reduceOp = () => ['value = 0.0;', 'value += _A(inputIdx);', 'value = log(value);'];
|
|
return reduce(inferenceHandler, inputs, attributes, 'ReduceLogSum', reduceOp);
|
|
};
|
|
exports.reduceLogSum = reduceLogSum;
|
|
const reduceLogSumSquare = (inferenceHandler, inputs, attributes) => {
|
|
const reduceOp = () => ['float t; value = 0.0;', 't = _A(inputIdx); value += t * t;', ''];
|
|
return reduce(inferenceHandler, inputs, attributes, 'ReduceLogSumSquare', reduceOp);
|
|
};
|
|
exports.reduceLogSumSquare = reduceLogSumSquare;
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./lib/onnxjs/backends/webgl/ops/reshape-packed.ts":
|
|
/*!*********************************************************!*\
|
|
!*** ./lib/onnxjs/backends/webgl/ops/reshape-packed.ts ***!
|
|
\*********************************************************/
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
// Licensed under the MIT License.
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.isReshapeCheap = exports.processDims3D = exports.createPackedReshape3DProgramInfoLoader = void 0;
|
|
const util_1 = __webpack_require__(/*! ../../../util */ "./lib/onnxjs/util.ts");
|
|
const glsl_source_1 = __webpack_require__(/*! ../glsl-source */ "./lib/onnxjs/backends/webgl/glsl-source.ts");
|
|
const types_1 = __webpack_require__(/*! ../types */ "./lib/onnxjs/backends/webgl/types.ts");
|
|
const packing_utils_1 = __webpack_require__(/*! ./packing-utils */ "./lib/onnxjs/backends/webgl/ops/packing-utils.ts");
|
|
const createPackedReshape3DProgramMetadata = (outputShape3D) => ({ name: 'Reshape (packed)', inputTypes: [types_1.TextureType.packed], inputNames: ['A'], cacheHint: `${outputShape3D}` });
|
|
const createPackedReshape3DProgramInfo = (handler, input3D, metadata, outputShape3D) => {
|
|
const inputShape3D = input3D.dims;
|
|
const squeezedOutputShape = outputShape3D;
|
|
let mainLoop = '';
|
|
for (let i = 0; i < 4; i++) {
|
|
let outputCoords = '';
|
|
switch (i) {
|
|
case 0:
|
|
outputCoords = 'outputCoords = rc;';
|
|
break;
|
|
case 1:
|
|
outputCoords = 'outputCoords = ivec3(rc.x, rc.y+1, rc.z);';
|
|
break;
|
|
case 2:
|
|
outputCoords = 'outputCoords = ivec3(rc.x, rc.y, rc.z+1);';
|
|
break;
|
|
case 3:
|
|
outputCoords = 'outputCoords = ivec3(rc.x, rc.y+1, rc.z+1);';
|
|
break;
|
|
default:
|
|
throw new Error();
|
|
}
|
|
mainLoop += `
|
|
${outputCoords}
|
|
${i > 0 ? 'if(outputCoords.y < rows && outputCoords.z < cols){' : ''}
|
|
int flattenedIndex = getFlattenedIndex(outputCoords);
|
|
|
|
ivec3 inputRC = inputCoordsFromReshapedOutCoords(flattenedIndex);
|
|
vec2 innerDims = vec2(float(inputRC.y),float(inputRC.z));
|
|
|
|
result[${i}] = getChannel(getA(inputRC.x, inputRC.y, inputRC.z), innerDims);
|
|
|
|
${i > 0 ? '}' : ''}
|
|
`;
|
|
}
|
|
const glsl = (0, glsl_source_1.getGlsl)(handler.session.backend.glContext.version);
|
|
const shaderSource = `
|
|
${getReshapedInputCoords(inputShape3D)}
|
|
${getFlattenedIndexFrom3D(squeezedOutputShape)}
|
|
${(0, packing_utils_1.unpackFromChannel)()}
|
|
|
|
void main() {
|
|
ivec3 rc = getOutputCoords();
|
|
|
|
vec4 result = vec4(0.0);
|
|
|
|
ivec3 outputCoords;
|
|
int rows = ${squeezedOutputShape[2]};
|
|
int cols = ${squeezedOutputShape[1]};
|
|
|
|
${mainLoop}
|
|
${glsl.output} = result;
|
|
}
|
|
`;
|
|
return Object.assign(Object.assign({}, metadata), { output: { dims: squeezedOutputShape, type: input3D.type, textureType: types_1.TextureType.packed }, shaderSource, hasMain: true });
|
|
};
|
|
const createPackedReshape3DProgramInfoLoader = (handler, input3D, outputShape3D) => {
|
|
const metadata = createPackedReshape3DProgramMetadata(outputShape3D);
|
|
return Object.assign(Object.assign({}, metadata), { get: () => createPackedReshape3DProgramInfo(handler, input3D, metadata, outputShape3D) });
|
|
};
|
|
exports.createPackedReshape3DProgramInfoLoader = createPackedReshape3DProgramInfoLoader;
|
|
function processDims3D(shape) {
|
|
if (shape.length === 0) {
|
|
return [1, 1, 1];
|
|
}
|
|
// TODO: squeeze other shapes to 2D case
|
|
let batch = 1;
|
|
for (let i = 0; i < shape.length - 2; ++i) {
|
|
batch *= shape[i];
|
|
}
|
|
return [batch, shape.length > 1 ? shape[shape.length - 2] : 1, shape[shape.length - 1]];
|
|
}
|
|
exports.processDims3D = processDims3D;
|
|
// For packed reshape, we need to re-arrange texel data for output shape.
|
|
// Our pack is designed to pack a 2x2 tile in last h and w dimension, so
|
|
// for the reshaped new tensor, we just need to re-arrange the last h and
|
|
// w dimension. For any shape that is not in 3D, i.e. [batch, W, H], we
|
|
// first convert it to 3D by collapsing other dimension to batch dim, then
|
|
// process with the last two dimensions.
|
|
// Note: we only need the shape tensor to calculate output shape, so the
|
|
// content in shape tensor is never uploaded to GPU. It is always kept in CPU.
|
|
// TODO: optimize the algorithm -- in some cases, if the last two dims are
|
|
// the same between input shape and output shape, the packed reshape can be
|
|
// treated as no-op.
|
|
function isReshapeCheap(dims, reshapedDims) {
|
|
let isCheapReshape = false;
|
|
if (dims.length === 0 || reshapedDims.length === 0) { // scalar
|
|
isCheapReshape = true;
|
|
}
|
|
else if (dims.length < 2 || reshapedDims.length < 2) { // 1D
|
|
isCheapReshape = dims[dims.length - 1] === reshapedDims[reshapedDims.length - 1];
|
|
}
|
|
else { // 2D +
|
|
isCheapReshape = dims[dims.length - 1] === reshapedDims[reshapedDims.length - 1] &&
|
|
dims[dims.length - 2] === reshapedDims[reshapedDims.length - 2];
|
|
}
|
|
return isCheapReshape;
|
|
}
|
|
exports.isReshapeCheap = isReshapeCheap;
|
|
function getReshapedInputCoords(shape) {
|
|
const strides = util_1.ShapeUtil.computeStrides(shape);
|
|
const coords = ['b', 'r', 'c'];
|
|
const index = 'index';
|
|
const coordsFromIndexSnippet = strides
|
|
.map((stride, i) => {
|
|
const line1 = `int ${coords[i]} = ${index} / ${stride}`;
|
|
const line2 = i === strides.length - 1 ?
|
|
`int ${coords[i + 1]} = ${index} - ${coords[i]} * ${stride}` :
|
|
`index -= ${coords[i]} * ${stride}`;
|
|
return `${line1}; ${line2};`;
|
|
})
|
|
.join('');
|
|
return `
|
|
ivec3 inputCoordsFromReshapedOutCoords(int index) {
|
|
${coordsFromIndexSnippet}
|
|
return ivec3(b, r, c);
|
|
}
|
|
`;
|
|
}
|
|
function getFlattenedIndexFrom3D(shape) {
|
|
const strides = util_1.ShapeUtil.computeStrides(shape);
|
|
return `
|
|
int getFlattenedIndex(ivec3 coords) {
|
|
// reverse y, z order
|
|
return coords.x * ${strides[0]} + coords.z * ${strides[1]} + coords.y;
|
|
}
|
|
`;
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./lib/onnxjs/backends/webgl/ops/reshape.ts":
|
|
/*!**************************************************!*\
|
|
!*** ./lib/onnxjs/backends/webgl/ops/reshape.ts ***!
|
|
\**************************************************/
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
// Licensed under the MIT License.
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.reshape = void 0;
|
|
const util_1 = __webpack_require__(/*! ../../../util */ "./lib/onnxjs/util.ts");
|
|
const reshape = (handler, inputs) => {
|
|
const reshapedDims = util_1.ShapeUtil.calculateReshapedDims(inputs[0].dims, inputs[1].integerData);
|
|
if (handler.session.pack) {
|
|
return [handler.reshapePacked(inputs[0], reshapedDims)];
|
|
}
|
|
else {
|
|
return [handler.reshapeUnpacked(inputs[0], reshapedDims)];
|
|
}
|
|
};
|
|
exports.reshape = reshape;
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./lib/onnxjs/backends/webgl/ops/resize-packed.ts":
|
|
/*!********************************************************!*\
|
|
!*** ./lib/onnxjs/backends/webgl/ops/resize-packed.ts ***!
|
|
\********************************************************/
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
// Licensed under the MIT License.
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.parseResizeAttributesV11 = exports.parseResizeAttributesV10 = exports.resize = void 0;
|
|
const glsl_source_1 = __webpack_require__(/*! ../glsl-source */ "./lib/onnxjs/backends/webgl/glsl-source.ts");
|
|
const types_1 = __webpack_require__(/*! ../types */ "./lib/onnxjs/backends/webgl/types.ts");
|
|
const utils_1 = __webpack_require__(/*! ../utils */ "./lib/onnxjs/backends/webgl/utils.ts");
|
|
const packing_utils_1 = __webpack_require__(/*! ./packing-utils */ "./lib/onnxjs/backends/webgl/ops/packing-utils.ts");
|
|
const upsample_1 = __webpack_require__(/*! ./upsample */ "./lib/onnxjs/backends/webgl/ops/upsample.ts");
|
|
const resizeProgramMetadata = {
|
|
name: 'Resize',
|
|
inputNames: ['A'],
|
|
inputTypes: [types_1.TextureType.packed]
|
|
};
|
|
const resize = (inferenceHandler, inputs, attributes) => {
|
|
(0, upsample_1.validateInputs)(inputs, attributes);
|
|
const output = inferenceHandler.run(Object.assign(Object.assign({}, resizeProgramMetadata), { cacheHint: attributes.cacheKey, get: () => createPackedResizeProgramInfo(inferenceHandler, inputs, attributes) }), inputs);
|
|
return [output];
|
|
};
|
|
exports.resize = resize;
|
|
const parseResizeAttributesV10 = (node) => (0, upsample_1.parseUpsampleAttributes)(node, 10);
|
|
exports.parseResizeAttributesV10 = parseResizeAttributesV10;
|
|
const parseResizeAttributesV11 = (node) => (0, upsample_1.parseUpsampleAttributes)(node, 11);
|
|
exports.parseResizeAttributesV11 = parseResizeAttributesV11;
|
|
const createPackedResizeProgramInfo = (inferenceHandler, inputs, attributes) => {
|
|
const glsl = (0, glsl_source_1.getGlsl)(inferenceHandler.session.backend.glContext.version);
|
|
const [scales, outputShape] = prepareInputs(inputs, attributes);
|
|
const isSame = scales.every((s) => s === 1) && attributes.coordinateTransformMode !== 'tf_crop_and_resize';
|
|
if (isSame) {
|
|
return Object.assign(Object.assign({}, resizeProgramMetadata), { output: { dims: outputShape, type: inputs[0].type, textureType: types_1.TextureType.packed }, hasMain: true, shaderSource: `void main() {
|
|
vec4 v = ${glsl.texture2D}(X, TexCoords);
|
|
${glsl.output} = v;
|
|
}` });
|
|
}
|
|
const dim = outputShape.length;
|
|
if (dim < 2) {
|
|
throw new Error(`output dimension should be at least 2, but got ${dim}`);
|
|
}
|
|
const outputHeight = outputShape[dim - 2];
|
|
const outputWidth = outputShape[dim - 1];
|
|
const inputShape = inputs[0].dims;
|
|
if (dim !== inputShape.length) {
|
|
throw new Error(`output dimension should match input ${inputShape.length}, but got ${dim}`);
|
|
}
|
|
const inputHeight = inputShape[dim - 2];
|
|
const inputWidth = inputShape[dim - 1];
|
|
const scalesHeight = scales[dim - 2];
|
|
const scalesWidth = scales[dim - 1];
|
|
let getSourceFracIndex = '';
|
|
if (attributes.mode !== 'linear') {
|
|
// TODO: support other modes
|
|
throw new Error(`resize (packed) does not support mode: '${attributes.mode}'`);
|
|
}
|
|
switch (attributes.coordinateTransformMode) {
|
|
case 'asymmetric':
|
|
getSourceFracIndex = `
|
|
vec4 getSourceFracIndex(ivec4 coords) {
|
|
return vec4(coords) / scaleWHWH;
|
|
}
|
|
`;
|
|
break;
|
|
case 'half_pixel':
|
|
getSourceFracIndex = `
|
|
vec4 getSourceFracIndex(ivec4 coords) {
|
|
return (vec4(coords) + 0.5) / scaleWHWH - 0.5;
|
|
}
|
|
`;
|
|
break;
|
|
case 'pytorch_half_pixel':
|
|
getSourceFracIndex = `
|
|
vec4 getSourceFracIndex(ivec4 coords) {
|
|
vec4 fcoords = vec4(coords);
|
|
return vec4(
|
|
${outputWidth}.0 > 1.0 ? (fcoords.x + 0.5) / scaleWHWH.x - 0.5 : 0.0,
|
|
${outputHeight}.0 > 1.0 ? (fcoords.y + 0.5) / scaleWHWH.y - 0.5 : 0.0,
|
|
${outputWidth}.0 > 1.0 ? (fcoords.z + 0.5) / scaleWHWH.z - 0.5 : 0.0,
|
|
${outputHeight}.0 > 1.0 ? (fcoords.w + 0.5) / scaleWHWH.w - 0.5 : 0.0
|
|
);
|
|
}
|
|
`;
|
|
break;
|
|
case 'align_corners':
|
|
getSourceFracIndex = `
|
|
vec4 getSourceFracIndex(ivec4 coords) {
|
|
vec4 resized = vec4(${outputWidth}.0 - 1.0, ${outputHeight}.0 - 1.0, ${outputWidth}.0 - 1.0,
|
|
${outputHeight}.0 - 1.0);
|
|
vec4 original = vec4(${inputWidth}.0 - 1.0, ${inputHeight}.0 - 1.0, ${inputWidth}.0 - 1.0,
|
|
${inputHeight}.0 - 1.0);
|
|
vec4 new_scale = original / resized;
|
|
return vec4(coords) * new_scale;
|
|
}
|
|
`;
|
|
break;
|
|
default:
|
|
// TODO:supporting other coordinateTransformModes
|
|
throw new Error(`resize (packed) does not support coordinateTransformMode: \
|
|
'${attributes.coordinateTransformMode}'`);
|
|
}
|
|
const coordsDataType = (0, utils_1.getCoordsDataType)(dim);
|
|
const unpackChannel = (0, packing_utils_1.unpackFromChannel)();
|
|
const shaderSource = `
|
|
const vec2 inputWH = vec2(${inputHeight}.0, ${inputWidth}.0);
|
|
const vec4 scaleWHWH = vec4(float(${scalesHeight}), float(${scalesWidth}), float(${scalesHeight}), float(${scalesWidth}));
|
|
${unpackChannel}
|
|
${getSourceFracIndex}
|
|
float getAValue(int x10, int r, int c, int d) {
|
|
return getChannel(getA(x10, r, c, d), vec2(c, d));
|
|
}
|
|
void main() {
|
|
${coordsDataType} rc = getOutputCoords();
|
|
|
|
int batch = rc[0];
|
|
int depth = rc[1];
|
|
|
|
// retrieve the 4 coordinates that is used in the 4 packed output values.
|
|
ivec4 coords = ivec4(rc.wz, rc.w + 1, rc.z + 1);
|
|
|
|
// calculate the source index in fraction
|
|
vec4 sourceFrac = getSourceFracIndex(coords);
|
|
|
|
// get the lower and upper bound of the 4 values that will be packed into one texel.
|
|
ivec4 x00 = ivec4(max(sourceFrac.xy, vec2(0.0)), min(inputWH - 1.0, ceil(sourceFrac.xy)));
|
|
ivec4 x01 = ivec4(max(sourceFrac.xw, vec2(0.0)), min(inputWH - 1.0, ceil(sourceFrac.xw)));
|
|
ivec4 x10 = ivec4(max(sourceFrac.zy, vec2(0.0)), min(inputWH - 1.0, ceil(sourceFrac.zy)));
|
|
ivec4 x11 = ivec4(max(sourceFrac.zw, vec2(0.0)), min(inputWH - 1.0, ceil(sourceFrac.zw)));
|
|
|
|
bool hasNextRow = rc.w < ${outputHeight - 1};
|
|
bool hasNextCol = rc.z < ${outputWidth - 1};
|
|
|
|
// pack x00, x01, x10, x11's top-left corner into one vec4 structure
|
|
vec4 topLeft = vec4(
|
|
getAValue(batch, depth, x00.x, x00.y),
|
|
hasNextCol ? getAValue(batch, depth, x01.x, x01.y) : 0.0,
|
|
hasNextRow ? getAValue(batch, depth, x10.x, x10.y) : 0.0,
|
|
(hasNextRow && hasNextCol) ? getAValue(batch, depth, x11.x, x11.y) : 0.0);
|
|
|
|
// pack x00, x01, x10, x11's top-right corner into one vec4 structure
|
|
vec4 topRight = vec4(
|
|
getAValue(batch, depth, x00.x, x00.w),
|
|
hasNextCol ? getAValue(batch, depth, x01.x, x01.w) : 0.0,
|
|
hasNextRow ? getAValue(batch, depth, x10.x, x10.w) : 0.0,
|
|
(hasNextRow && hasNextCol) ? getAValue(batch, depth, x11.x, x11.w) : 0.0);
|
|
|
|
// pack x00, x01, x10, x11's bottom-left corner into one vec4 structure
|
|
vec4 bottomLeft = vec4(
|
|
getAValue(batch, depth, x00.z, x00.y),
|
|
hasNextCol ? getAValue(batch, depth, x01.z, x01.y) : 0.0,
|
|
hasNextRow ? getAValue(batch, depth, x10.z, x10.y) : 0.0,
|
|
(hasNextRow && hasNextCol) ? getAValue(batch, depth, x11.z, x11.y) : 0.0);
|
|
|
|
// pack x00, x01, x10, x11's bottom-right corner into one vec4 structure
|
|
vec4 bottomRight = vec4(
|
|
getAValue(batch, depth, x00.z, x00.w),
|
|
hasNextCol ? getAValue(batch, depth, x01.z, x01.w) : 0.0,
|
|
hasNextRow ? getAValue(batch, depth, x10.z, x10.w) : 0.0,
|
|
(hasNextRow && hasNextCol) ? getAValue(batch, depth, x11.z, x11.w) : 0.0);
|
|
|
|
// calculate the interpolation fraction on u and v direction
|
|
vec4 frac = vec4(sourceFrac) - floor(sourceFrac);
|
|
vec4 clampFrac = clamp(frac, vec4(0.0), vec4(1.0));
|
|
|
|
vec4 top = mix(topLeft, topRight, clampFrac.ywyw);
|
|
vec4 bottom = mix(bottomLeft, bottomRight, clampFrac.ywyw);
|
|
vec4 newValue = mix(top, bottom, clampFrac.xxzz);
|
|
|
|
${glsl.output} = vec4(newValue);
|
|
}
|
|
`;
|
|
return Object.assign(Object.assign({}, resizeProgramMetadata), { output: { dims: outputShape, type: inputs[0].type, textureType: types_1.TextureType.packed }, hasMain: true, shaderSource });
|
|
};
|
|
const prepareInputs = (inputs, attributes) => {
|
|
const x = inputs[0];
|
|
const xDims = x.dims;
|
|
let scales = attributes.scales;
|
|
let outputSizes;
|
|
if (scales.length === 0) {
|
|
const scalesTensor = inputs[attributes.scalesInputIdx];
|
|
if (scalesTensor && scalesTensor.size !== 0) {
|
|
if (inputs[attributes.sizesInputIdx]) {
|
|
throw new Error('Only one of scales or sizes must be provided as input.');
|
|
}
|
|
scales = parseScalesData(scalesTensor, attributes.mode, attributes.isResize);
|
|
}
|
|
else {
|
|
const sizesTensor = inputs[attributes.sizesInputIdx];
|
|
if (!sizesTensor || sizesTensor.size === 0) {
|
|
throw new Error('Either scales or sizes MUST be provided as input.');
|
|
}
|
|
outputSizes = Array.from(sizesTensor.integerData);
|
|
scales = parseScalesDataFromOutputSize(outputSizes, xDims, attributes.mode, attributes.isResize);
|
|
}
|
|
}
|
|
else {
|
|
if (inputs[attributes.sizesInputIdx]) {
|
|
throw new Error('Only one of scales or sizes must be provided as input.');
|
|
}
|
|
}
|
|
const yDims = outputSizes || (xDims.map((dim, i) => Math.floor(dim * scales[i])));
|
|
return [scales, yDims];
|
|
};
|
|
const parseScalesData = (scale, mode, isResize) => {
|
|
const scales = Array.from(scale.floatData);
|
|
(0, upsample_1.scalesValidation)(scales, mode, isResize);
|
|
return scales;
|
|
};
|
|
const parseScalesDataFromOutputSize = (yDims, xDims, mode, isResize) => {
|
|
const length = xDims.length;
|
|
const scales = new Array(length);
|
|
for (let i = 0, end = length; i < end; i++) {
|
|
if (xDims[i] === 0) {
|
|
if (yDims[i] !== 0) {
|
|
throw new Error('Input dim is zero but required output dim is non-zero.');
|
|
}
|
|
scales[i] = 1;
|
|
}
|
|
else {
|
|
scales[i] = yDims[i] / xDims[i];
|
|
}
|
|
}
|
|
(0, upsample_1.scalesValidation)(scales, mode, isResize);
|
|
return scales;
|
|
};
|
|
// roi data is not used yet. but leave here for future usage.
|
|
// const getRoi = (inputs: Tensor[], attributes: UpsampleAttributes) : number[] => {
|
|
// let roi: number[] = [];
|
|
// if (attributes.needRoiInput) {
|
|
// if (attributes.roiInputIdx <= 0) {
|
|
// throw new Error('Invalid roi input index.');
|
|
// }
|
|
// const roiTensor = inputs[attributes.roiInputIdx];
|
|
// roi = roiTensor.size > 0 ? Array.from(roiTensor.floatData) : [];
|
|
// } else {
|
|
// roi = new Array(inputs[0].dims.length * 2).fill(0);
|
|
// }
|
|
// return roi;
|
|
// };
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./lib/onnxjs/backends/webgl/ops/shape.ts":
|
|
/*!************************************************!*\
|
|
!*** ./lib/onnxjs/backends/webgl/ops/shape.ts ***!
|
|
\************************************************/
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
// Licensed under the MIT License.
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.shape = void 0;
|
|
const tensor_1 = __webpack_require__(/*! ../../../tensor */ "./lib/onnxjs/tensor.ts");
|
|
const shape = (inferenceHandler, inputs) => {
|
|
validateInputs(inputs);
|
|
return [new tensor_1.Tensor([inputs[0].dims.length], 'int32', undefined, undefined, new Int32Array(inputs[0].dims))];
|
|
};
|
|
exports.shape = shape;
|
|
const validateInputs = (inputs) => {
|
|
if (!inputs || inputs.length !== 1) {
|
|
throw new Error('Shape requires 1 input.');
|
|
}
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./lib/onnxjs/backends/webgl/ops/slice.ts":
|
|
/*!************************************************!*\
|
|
!*** ./lib/onnxjs/backends/webgl/ops/slice.ts ***!
|
|
\************************************************/
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
// Licensed under the MIT License.
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.sliceV10 = exports.parseSliceAttributes = exports.slice = void 0;
|
|
const attribute_with_cache_key_1 = __webpack_require__(/*! ../../../attribute-with-cache-key */ "./lib/onnxjs/attribute-with-cache-key.ts");
|
|
const operators_1 = __webpack_require__(/*! ../../../operators */ "./lib/onnxjs/operators.ts");
|
|
const util_1 = __webpack_require__(/*! ../../../util */ "./lib/onnxjs/util.ts");
|
|
const types_1 = __webpack_require__(/*! ../types */ "./lib/onnxjs/backends/webgl/types.ts");
|
|
const sliceProgramMetadata = {
|
|
name: 'Slice',
|
|
inputNames: ['A'],
|
|
inputTypes: [types_1.TextureType.unpacked]
|
|
};
|
|
const slice = (inferenceHandler, inputs, attributes) => {
|
|
validateInputs(inputs);
|
|
const output = inferenceHandler.run(Object.assign(Object.assign({}, sliceProgramMetadata), { cacheHint: attributes.cacheKey, get: () => createSliceProgramInfo(inferenceHandler, inputs[0], attributes) }), inputs);
|
|
return [output];
|
|
};
|
|
exports.slice = slice;
|
|
const parseSliceAttributes = (node) => {
|
|
const starts = node.attributes.getInts('starts');
|
|
const ends = node.attributes.getInts('ends');
|
|
const axes = node.attributes.getInts('axes', []);
|
|
return (0, attribute_with_cache_key_1.createAttributeWithCacheKey)({ starts, ends, axes });
|
|
};
|
|
exports.parseSliceAttributes = parseSliceAttributes;
|
|
const createSliceProgramInfo = (inferenceHandler, input, attributes) => {
|
|
const axes = (attributes.axes.length === 0) ? input.dims.slice(0).map((val, i) => i) : attributes.axes;
|
|
const normalizedAxes = util_1.ShapeUtil.normalizeAxes(axes, input.dims.length);
|
|
const starts = attributes.starts.map((start, i) => {
|
|
if (start > input.dims[normalizedAxes[i]] - 1) {
|
|
return input.dims[normalizedAxes[i]];
|
|
}
|
|
return util_1.ShapeUtil.normalizeAxis(start, input.dims[normalizedAxes[i]]);
|
|
});
|
|
const ends = attributes.ends.map((end, i) => {
|
|
if (end > input.dims[normalizedAxes[i]] - 1) {
|
|
return input.dims[normalizedAxes[i]];
|
|
}
|
|
return util_1.ShapeUtil.normalizeAxis(end, input.dims[normalizedAxes[i]]);
|
|
});
|
|
const outputShape = input.dims.slice();
|
|
const sliceOps = [];
|
|
for (let i = 0; i < normalizedAxes.length; i++) {
|
|
outputShape[normalizedAxes[i]] = ends[i] - starts[i];
|
|
if (starts[i] > 0) {
|
|
sliceOps.push(`outputIdx[${normalizedAxes[i]}] += ${starts[i]};`);
|
|
} // else { sliceOps.push(`outputIdx[${normalizedAxes[i]}] += 0;`); }
|
|
}
|
|
const rank = outputShape.length;
|
|
const shaderSource = `
|
|
float process(int outputIdx[${rank}]) {
|
|
${sliceOps.join('\n ')}
|
|
return _A(outputIdx);
|
|
}`;
|
|
return Object.assign(Object.assign({}, sliceProgramMetadata), { output: { dims: outputShape, type: input.type, textureType: types_1.TextureType.unpacked }, shaderSource });
|
|
};
|
|
const validateInputs = (inputs) => {
|
|
if (!inputs || inputs.length !== 1) {
|
|
throw new Error('Slice requires 1 input.');
|
|
}
|
|
if (operators_1.NUMBER_TYPES.indexOf(inputs[0].type) === -1) {
|
|
throw new Error('Invalid input type.');
|
|
}
|
|
};
|
|
const sliceV10 = (inferenceHandler, inputs) => {
|
|
validateInputsV10(inputs);
|
|
const attributes = generateSliceAttributesFromInputs(inferenceHandler, inputs);
|
|
const output = inferenceHandler.run(Object.assign(Object.assign({}, sliceProgramMetadata), { cacheHint: attributes.cacheKey, get: () => createSliceProgramInfo(inferenceHandler, inputs[0], attributes) }), [inputs[0]]);
|
|
return [output];
|
|
};
|
|
exports.sliceV10 = sliceV10;
|
|
const generateSliceAttributesFromInputs = (inferenceHandler, inputs) => {
|
|
if (!inferenceHandler.session.isInitializer(inputs[1].dataId) ||
|
|
!inferenceHandler.session.isInitializer(inputs[2].dataId) ||
|
|
(inputs.length >= 4 && !inferenceHandler.session.isInitializer(inputs[3].dataId)) ||
|
|
(inputs.length >= 5 && !inferenceHandler.session.isInitializer(inputs[4].dataId))) {
|
|
throw new Error('dynamic slice attributes are not allowed');
|
|
}
|
|
if (inputs.length >= 5 && inputs[4].integerData.some((i) => i !== 1)) {
|
|
throw new Error('currently non-1 steps is not supported for Slice');
|
|
}
|
|
const starts = Array.from(inputs[1].integerData);
|
|
const ends = Array.from(inputs[2].integerData);
|
|
const axes = inputs.length >= 4 ? Array.from(inputs[3].integerData) : [];
|
|
const cacheKey = `${axes};${starts};${ends}`;
|
|
return { starts, ends, axes, cacheKey };
|
|
};
|
|
const validateInputsV10 = (inputs) => {
|
|
if (!inputs || inputs.length < 3 || inputs.length > 5) {
|
|
throw new Error('Invalid input number.');
|
|
}
|
|
if (inputs[1].type !== 'int32' || inputs[1].dims.length !== 1) {
|
|
throw new Error('Invalid input type.');
|
|
}
|
|
if (inputs[2].type !== 'int32' || inputs[2].dims.length !== 1) {
|
|
throw new Error('Invalid input type.');
|
|
}
|
|
if (inputs.length >= 4 && (inputs[3].type !== 'int32' || inputs[3].dims.length !== 1)) {
|
|
throw new Error('Invalid input type.');
|
|
}
|
|
if (inputs.length >= 5 && (inputs[4].type !== 'int32' || inputs[4].dims.length !== 1)) {
|
|
throw new Error('Invalid input type.');
|
|
}
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./lib/onnxjs/backends/webgl/ops/softmax.ts":
|
|
/*!**************************************************!*\
|
|
!*** ./lib/onnxjs/backends/webgl/ops/softmax.ts ***!
|
|
\**************************************************/
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
// Licensed under the MIT License.
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.softmaxV13 = exports.parseSoftmaxAttributesV13 = exports.parseSoftmaxAttributes = exports.softmax = void 0;
|
|
const attribute_with_cache_key_1 = __webpack_require__(/*! ../../../attribute-with-cache-key */ "./lib/onnxjs/attribute-with-cache-key.ts");
|
|
const util_1 = __webpack_require__(/*! ../../../util */ "./lib/onnxjs/util.ts");
|
|
const glsl_source_1 = __webpack_require__(/*! ../glsl-source */ "./lib/onnxjs/backends/webgl/glsl-source.ts");
|
|
const types_1 = __webpack_require__(/*! ../types */ "./lib/onnxjs/backends/webgl/types.ts");
|
|
const transpose_1 = __webpack_require__(/*! ./transpose */ "./lib/onnxjs/backends/webgl/ops/transpose.ts");
|
|
const softmaxComputeMaxProgramMetadata = {
|
|
name: 'SoftmaxComputeMax',
|
|
inputNames: ['A'],
|
|
inputTypes: [types_1.TextureType.unpacked],
|
|
};
|
|
const softmaxComputeScaleProgramMetadata = {
|
|
name: 'SoftmaxComputeScale',
|
|
inputNames: ['A', 'Max'],
|
|
inputTypes: [types_1.TextureType.unpacked, types_1.TextureType.unpacked],
|
|
};
|
|
const softmaxProgramMetadata = {
|
|
name: 'SoftMax',
|
|
inputNames: ['A', 'Max', 'Norm'],
|
|
inputTypes: [types_1.TextureType.unpacked, types_1.TextureType.unpacked, types_1.TextureType.unpacked],
|
|
};
|
|
const softmax = (inferenceHandler, inputs, attributes) => {
|
|
validateInputs(inputs);
|
|
const inputShape = inputs[0].dims.slice();
|
|
const axis = util_1.ShapeUtil.normalizeAxis(attributes.axis, inputShape.length);
|
|
const logicalRowCount = util_1.ShapeUtil.sizeToDimension(inputShape, axis);
|
|
const featureCount = util_1.ShapeUtil.sizeFromDimension(inputShape, axis);
|
|
const output = computeSoftmax(inferenceHandler, inputs, attributes, logicalRowCount, featureCount);
|
|
return output;
|
|
};
|
|
exports.softmax = softmax;
|
|
const parseSoftmaxAttributes = (node) => (0, attribute_with_cache_key_1.createAttributeWithCacheKey)({ axis: node.attributes.getInt('axis', 1) });
|
|
exports.parseSoftmaxAttributes = parseSoftmaxAttributes;
|
|
const parseSoftmaxAttributesV13 = (node) => (0, attribute_with_cache_key_1.createAttributeWithCacheKey)({ axis: node.attributes.getInt('axis', -1) });
|
|
exports.parseSoftmaxAttributesV13 = parseSoftmaxAttributesV13;
|
|
// The "semantic" meaning of axis has changed in opset-13.
|
|
// Please compare: https://github.com/onnx/onnx/blob/main/docs/Operators.md#Softmax
|
|
// with https://github.com/onnx/onnx/blob/main/docs/Changelog.md#Softmax-11 for detailed explanations
|
|
// To account for the opset-13 behavior, our plan will be to transpose the "axis" dim to the innermost dim
|
|
// and perform softmax and then reverse the transpose. We can skip the transposing aspect if the axis is already
|
|
// the innermost dim
|
|
const softmaxV13 = (inferenceHandler, inputs, attributes) => {
|
|
validateInputs(inputs);
|
|
const inputShape = inputs[0].dims.slice();
|
|
const axis = util_1.ShapeUtil.normalizeAxis(attributes.axis, inputShape.length);
|
|
const rank = inputShape.length;
|
|
const isTransposeRequired = (axis !== rank - 1) ? true : false;
|
|
const transposedInputShape = [];
|
|
let perm = [];
|
|
let transposedInputs = [];
|
|
let transposeAttribute;
|
|
if (isTransposeRequired) {
|
|
perm = Array.from({ length: rank }).map((_, i) => i);
|
|
// swap the innermost dim with the dim corresponding to axis
|
|
perm[axis] = rank - 1;
|
|
perm[rank - 1] = axis;
|
|
perm.map(p => transposedInputShape.push(inputShape[p]));
|
|
transposeAttribute = (0, attribute_with_cache_key_1.createAttributeWithCacheKey)({ perm });
|
|
transposedInputs = (0, transpose_1.transpose)(inferenceHandler, inputs, transposeAttribute);
|
|
}
|
|
const logicalRowCount = isTransposeRequired ? util_1.ShapeUtil.sizeToDimension(transposedInputShape, rank - 1) :
|
|
util_1.ShapeUtil.sizeToDimension(inputShape, rank - 1);
|
|
const featureCount = isTransposeRequired ? util_1.ShapeUtil.sizeFromDimension(transposedInputShape, rank - 1) :
|
|
util_1.ShapeUtil.sizeFromDimension(inputShape, rank - 1);
|
|
const output = computeSoftmax(inferenceHandler, isTransposeRequired ? transposedInputs : inputs, attributes, logicalRowCount, featureCount);
|
|
if (isTransposeRequired) {
|
|
const reversedOutput = (0, transpose_1.transpose)(inferenceHandler, output, transposeAttribute);
|
|
return reversedOutput;
|
|
}
|
|
else {
|
|
return output;
|
|
}
|
|
};
|
|
exports.softmaxV13 = softmaxV13;
|
|
const computeSoftmax = (inferenceHandler, inputs, attributes, logicalRowCount, featureCount) => {
|
|
const computeMaxProgramInfo = createComputeMaxProgramInfo(inferenceHandler, inputs[0], logicalRowCount, featureCount, [logicalRowCount]);
|
|
const max = inferenceHandler.run(Object.assign(Object.assign({}, softmaxComputeMaxProgramMetadata), { cacheHint: attributes.cacheKey, get: () => computeMaxProgramInfo }), inputs);
|
|
const computeScaleProgramInfo = createComputScaleProgramInfo(inferenceHandler, inputs[0], logicalRowCount, featureCount, computeMaxProgramInfo.output.dims, [logicalRowCount]);
|
|
const scale = inferenceHandler.run(Object.assign(Object.assign({}, softmaxComputeScaleProgramMetadata), { cacheHint: attributes.cacheKey, get: () => computeScaleProgramInfo }), [inputs[0], max]);
|
|
const softMaxProgramInfo = createSoftMaxProgramInfo(inferenceHandler, inputs[0], logicalRowCount, featureCount, computeMaxProgramInfo.output.dims, computeScaleProgramInfo.output.dims);
|
|
const output = inferenceHandler.run(Object.assign(Object.assign({}, softmaxProgramMetadata), { cacheHint: attributes.cacheKey, get: () => softMaxProgramInfo }), [inputs[0], max, scale]);
|
|
return [output];
|
|
};
|
|
/**
|
|
* Create a texture that contains the maximum value of each of the 'N' rows
|
|
*/
|
|
const createComputeMaxProgramInfo = (inferenceHandler, input, logicalRowCount, featureCount, outputShape) => {
|
|
const [textureWidth, textureHeight] = inferenceHandler.calculateTextureWidthAndHeight(input.dims, types_1.TextureType.unpacked);
|
|
const rank = outputShape.length;
|
|
if (logicalRowCount < 1 || featureCount < 1) {
|
|
throw new Error('Logical row count N and feature count D must be greater than or equal to 1');
|
|
}
|
|
if (outputShape.length !== 1) {
|
|
throw new Error('Dimensionality of the output should be 1');
|
|
}
|
|
if (outputShape[0] !== logicalRowCount) {
|
|
throw new Error('Shape of the output should be equal to logical row count');
|
|
}
|
|
const glsl = (0, glsl_source_1.getGlsl)(inferenceHandler.session.backend.glContext.version);
|
|
const shaderSource = `
|
|
float process(int[${rank}] indices) {
|
|
int logical_row_start_offset = indices[0] * ${featureCount};
|
|
|
|
float max = getColorAsFloat(${glsl.texture2D}(A, offsetToCoords(logical_row_start_offset, ${textureWidth},
|
|
${textureHeight} )));
|
|
for(int i=1; i<${featureCount}; ++i)
|
|
{
|
|
float current = getColorAsFloat(${glsl.texture2D}(A, offsetToCoords(logical_row_start_offset + i,
|
|
${textureWidth}, ${textureHeight})));
|
|
if(current > max)
|
|
max = current;
|
|
}
|
|
|
|
return max;
|
|
}`;
|
|
return Object.assign(Object.assign({}, softmaxComputeMaxProgramMetadata), { output: { dims: outputShape, type: input.type, textureType: types_1.TextureType.unpacked }, shaderSource });
|
|
};
|
|
/**
|
|
* Create a texture that contains the normalization factor for each of the 'N' rows
|
|
*/
|
|
const createComputScaleProgramInfo = (inferenceHandler, input, logicalRowCount, featureCount, maxElementPerLogicalRow, outputShape) => {
|
|
const [textureWidth, textureHeight] = inferenceHandler.calculateTextureWidthAndHeight(input.dims, types_1.TextureType.unpacked);
|
|
const rank = outputShape.length;
|
|
if (logicalRowCount < 1 || featureCount < 1) {
|
|
throw new Error('Logical row count N and feature count D must be greater than or equal to 1');
|
|
}
|
|
if (outputShape.length !== 1) {
|
|
throw new Error('Dimensionality of the output should be 1');
|
|
}
|
|
if (outputShape[0] !== logicalRowCount) {
|
|
throw new Error('Shape of the output should be equal to logical row count');
|
|
}
|
|
if (maxElementPerLogicalRow.length !== 1) {
|
|
throw new Error('Dimensionality of the intermediate results should be 1');
|
|
}
|
|
if (maxElementPerLogicalRow[0] !== logicalRowCount) {
|
|
throw new Error('Shape of the intermediate results should be equal to logical row count');
|
|
}
|
|
const glsl = (0, glsl_source_1.getGlsl)(inferenceHandler.session.backend.glContext.version);
|
|
const shaderSource = `
|
|
float process(int[${rank}] indices) {
|
|
int logical_row_start_offset = indices[0] * ${featureCount};
|
|
|
|
float norm_factor = 0.0;
|
|
float max = _Max(indices);
|
|
for(int i=0; i<${featureCount}; ++i)
|
|
{
|
|
norm_factor += exp(getColorAsFloat(${glsl.texture2D}(A, offsetToCoords(logical_row_start_offset + i,
|
|
${textureWidth}, ${textureHeight}))) - max);
|
|
}
|
|
|
|
return norm_factor;
|
|
}`;
|
|
return Object.assign(Object.assign({}, softmaxComputeScaleProgramMetadata), { output: { dims: outputShape, type: input.type, textureType: types_1.TextureType.unpacked }, shaderSource });
|
|
};
|
|
const createSoftMaxProgramInfo = (inferenceHandler, input, logicalRowCount, featureCount, maxElementPerLogicalRow, normalizationPerLogicalRow) => {
|
|
const [textureWidth, textureHeight] = inferenceHandler.calculateTextureWidthAndHeight(input.dims, types_1.TextureType.unpacked);
|
|
const rank = input.dims.length;
|
|
if (logicalRowCount < 1 || featureCount < 1) {
|
|
throw new Error('Logical row count N and feature count D must be greater than or equal to 1');
|
|
}
|
|
if (maxElementPerLogicalRow.length !== 1 || normalizationPerLogicalRow.length !== 1) {
|
|
throw new Error('Dimensionality of the intermediate results should be 1');
|
|
}
|
|
if (maxElementPerLogicalRow[0] !== logicalRowCount || normalizationPerLogicalRow[0] !== logicalRowCount) {
|
|
throw new Error('Shape of the intermediate results should be equal to logical row count');
|
|
}
|
|
const shaderSource = `
|
|
float process(int[${rank}] indices) {
|
|
|
|
// get offset of current logical tensor index from the 2-D texture coordinates (TexCoords)
|
|
int offset = coordsToOffset(TexCoords, ${textureWidth}, ${textureHeight});
|
|
|
|
//determine the logical row for this index
|
|
int logical_row_index[1];
|
|
logical_row_index[0] = offset / ${featureCount};
|
|
|
|
float norm_factor = _Norm(logical_row_index);
|
|
|
|
// avoid possible division by 0
|
|
// if norm_facor is 0, all elements are zero
|
|
// if so, return 0
|
|
if(norm_factor == 0.0)
|
|
return 0.0;
|
|
|
|
return exp(_A(indices) - _Max(logical_row_index)) / norm_factor;
|
|
}`;
|
|
return Object.assign(Object.assign({}, softmaxProgramMetadata), { output: { dims: input.dims, type: input.type, textureType: types_1.TextureType.unpacked }, shaderSource });
|
|
};
|
|
const validateInputs = (inputs) => {
|
|
if (!inputs || inputs.length !== 1) {
|
|
throw new Error('Softmax requires 1 input.');
|
|
}
|
|
if (inputs[0].type !== 'float32' && inputs[0].type !== 'float64') {
|
|
throw new Error('Invalid input type');
|
|
}
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./lib/onnxjs/backends/webgl/ops/split.ts":
|
|
/*!************************************************!*\
|
|
!*** ./lib/onnxjs/backends/webgl/ops/split.ts ***!
|
|
\************************************************/
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
// Licensed under the MIT License.
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.parseSplitAttributes = exports.split = void 0;
|
|
const attribute_with_cache_key_1 = __webpack_require__(/*! ../../../attribute-with-cache-key */ "./lib/onnxjs/attribute-with-cache-key.ts");
|
|
const util_1 = __webpack_require__(/*! ../../../util */ "./lib/onnxjs/util.ts");
|
|
const types_1 = __webpack_require__(/*! ../types */ "./lib/onnxjs/backends/webgl/types.ts");
|
|
const splitProgramMetadata = {
|
|
name: 'Split',
|
|
inputNames: ['A'],
|
|
inputTypes: [types_1.TextureType.unpacked],
|
|
};
|
|
const split = (inferenceHandler, inputs, attributes) => {
|
|
validateInputs(inputs);
|
|
const axis = util_1.ShapeUtil.normalizeAxis(attributes.axis, inputs[0].dims.length);
|
|
const count = getProgramCount(inferenceHandler, inputs, axis, attributes);
|
|
const output = [];
|
|
for (let i = 0; i < count; ++i) {
|
|
output.push(inferenceHandler.run(Object.assign(Object.assign({}, splitProgramMetadata), { cacheHint: `${attributes.cacheKey};${i}`, get: () => createSplitProgramInfo(inferenceHandler, inputs[0], attributes, axis, i) }), inputs));
|
|
}
|
|
return output;
|
|
};
|
|
exports.split = split;
|
|
const parseSplitAttributes = (node) => {
|
|
const axis = node.attributes.getInt('axis', 0);
|
|
const split = node.attributes.getInts('split', []);
|
|
const numOutputs = node.outputs.length;
|
|
return (0, attribute_with_cache_key_1.createAttributeWithCacheKey)({ axis, split, numOutputs });
|
|
};
|
|
exports.parseSplitAttributes = parseSplitAttributes;
|
|
const getProgramCount = (inferenceHandler, inputs, axis, attributes) => {
|
|
const [, offsets] = util_1.SplitUtil.splitShape(inputs[0].dims, axis, attributes.split, attributes.numOutputs);
|
|
return offsets.length;
|
|
};
|
|
const createSplitProgramInfo = (inferenceHandler, input, attributes, axis, index) => {
|
|
const [shapes, offsets] = util_1.SplitUtil.splitShape(input.dims, axis, attributes.split, attributes.numOutputs);
|
|
const offset = offsets[index];
|
|
const outputShape = shapes[index];
|
|
const rank = outputShape.length;
|
|
const shaderSource = `
|
|
float process(int indices[${rank}]) {
|
|
indices[${axis}] += ${offset};
|
|
return _A(indices);
|
|
}
|
|
`;
|
|
return Object.assign(Object.assign({}, splitProgramMetadata), { cacheHint: `${attributes.cacheKey}:${index}`, output: { dims: outputShape, type: input.type, textureType: types_1.TextureType.unpacked }, shaderSource });
|
|
};
|
|
const validateInputs = (inputs) => {
|
|
if (!inputs || inputs.length !== 1) {
|
|
throw new Error('Split requires one input.');
|
|
}
|
|
if (inputs[0].type !== 'int8' && inputs[0].type !== 'uint8' && inputs[0].type !== 'int16' &&
|
|
inputs[0].type !== 'uint16' && inputs[0].type !== 'int32' && inputs[0].type !== 'uint32' &&
|
|
inputs[0].type !== 'float32' && inputs[0].type !== 'float64' && inputs[0].type !== 'bool') {
|
|
throw new Error('Invalid input type.');
|
|
}
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./lib/onnxjs/backends/webgl/ops/squeeze.ts":
|
|
/*!**************************************************!*\
|
|
!*** ./lib/onnxjs/backends/webgl/ops/squeeze.ts ***!
|
|
\**************************************************/
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
// Licensed under the MIT License.
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.parseSqueezeAttributes = exports.squeezeV13 = exports.squeeze = void 0;
|
|
const util_1 = __webpack_require__(/*! ../../../util */ "./lib/onnxjs/util.ts");
|
|
const squeeze = (inferenceHandler, inputs, axes) => {
|
|
validateInputs(inputs);
|
|
const outputShape = util_1.ShapeUtil.squeezeShape(inputs[0].dims, axes);
|
|
const output = inferenceHandler.reshapeUnpacked(inputs[0], outputShape);
|
|
return [output];
|
|
};
|
|
exports.squeeze = squeeze;
|
|
const squeezeV13 = (inferenceHandler, inputs) => {
|
|
validateInputsV13(inputs);
|
|
return (0, exports.squeeze)(inferenceHandler, [inputs[0]], Array.from(inputs[1].integerData));
|
|
};
|
|
exports.squeezeV13 = squeezeV13;
|
|
const parseSqueezeAttributes = (node) => node.attributes.getInts('axes');
|
|
exports.parseSqueezeAttributes = parseSqueezeAttributes;
|
|
const validateInputs = (inputs) => {
|
|
if (!inputs || inputs.length !== 1) {
|
|
throw new Error('Squeeze requires 1 input.');
|
|
}
|
|
if (inputs[0].type === 'string') {
|
|
throw new Error('invalid input tensor types.');
|
|
}
|
|
};
|
|
const validateInputsV13 = (inputs) => {
|
|
if (!inputs || inputs.length !== 2) {
|
|
throw new Error('Squeeze requires 2 inputs.');
|
|
}
|
|
if (inputs[1].type !== 'int32') {
|
|
throw new Error('Invalid input type.');
|
|
}
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./lib/onnxjs/backends/webgl/ops/sum.ts":
|
|
/*!**********************************************!*\
|
|
!*** ./lib/onnxjs/backends/webgl/ops/sum.ts ***!
|
|
\**********************************************/
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
// Licensed under the MIT License.
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.sum = void 0;
|
|
const glsl_source_1 = __webpack_require__(/*! ../glsl-source */ "./lib/onnxjs/backends/webgl/glsl-source.ts");
|
|
const types_1 = __webpack_require__(/*! ../types */ "./lib/onnxjs/backends/webgl/types.ts");
|
|
const sum = (inferenceHandler, inputs) => {
|
|
validateInputs(inputs);
|
|
const sumProgramMetadata = {
|
|
name: 'Sum',
|
|
inputNames: inputs.map((v, i) => `X${i}`),
|
|
inputTypes: new Array(inputs.length).fill(types_1.TextureType.unpacked)
|
|
};
|
|
const output = inferenceHandler.run(Object.assign(Object.assign({}, sumProgramMetadata), { get: () => createSumProgramInfo(inferenceHandler, inputs, sumProgramMetadata) }), inputs);
|
|
return [output];
|
|
};
|
|
exports.sum = sum;
|
|
const createSumProgramInfo = (inferenceHandler, inputs, sumProgramMetadata) => {
|
|
const glsl = (0, glsl_source_1.getGlsl)(inferenceHandler.session.backend.glContext.version);
|
|
const outputShape = inputs[0].dims.slice();
|
|
const sumLine = inputs.map((v, i) => `${glsl.texture2D}(X${i},TexCoords)`).join(' + ');
|
|
const shaderSource = `
|
|
void main() {
|
|
vec4 result = ${sumLine};
|
|
${glsl.output} = result;
|
|
}
|
|
`;
|
|
return Object.assign(Object.assign({}, sumProgramMetadata), { output: { dims: outputShape, type: inputs[0].type, textureType: types_1.TextureType.unpacked }, hasMain: true, shaderSource });
|
|
};
|
|
const validateInputs = (inputs) => {
|
|
if (!inputs || inputs.length === 0) {
|
|
throw new Error('Sum requires inputs.');
|
|
}
|
|
const length = inputs[0].dims.length;
|
|
for (let i = 1; i < inputs.length; i++) {
|
|
if (length !== inputs[i].dims.length) {
|
|
throw new Error('Input shapes are mismatched.');
|
|
}
|
|
for (let j = 0; j < length; j++) {
|
|
if (inputs[0].dims[j] !== inputs[i].dims[j]) {
|
|
throw new Error('Input shapes are not matched.');
|
|
}
|
|
}
|
|
}
|
|
if (inputs[0].type !== 'float32' && inputs[0].type !== 'float64') {
|
|
throw new Error('Invalid input type.');
|
|
}
|
|
for (let i = 1; i < inputs.length; i++) {
|
|
if (inputs[0].type !== inputs[i].type) {
|
|
throw new Error('Input types are not matched.');
|
|
}
|
|
}
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./lib/onnxjs/backends/webgl/ops/tile.ts":
|
|
/*!***********************************************!*\
|
|
!*** ./lib/onnxjs/backends/webgl/ops/tile.ts ***!
|
|
\***********************************************/
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
// Licensed under the MIT License.
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.tile = void 0;
|
|
const operators_1 = __webpack_require__(/*! ../../../operators */ "./lib/onnxjs/operators.ts");
|
|
const types_1 = __webpack_require__(/*! ../types */ "./lib/onnxjs/backends/webgl/types.ts");
|
|
const tile = (inferenceHandler, inputs) => {
|
|
validateInputs(inputs);
|
|
const tileProgramMetadata = {
|
|
name: 'Tile',
|
|
inputNames: ['A'],
|
|
inputTypes: [types_1.TextureType.unpacked],
|
|
};
|
|
const output = inferenceHandler.run(Object.assign(Object.assign({}, tileProgramMetadata), { get: () => createTileProgramInfo(inferenceHandler, inputs, tileProgramMetadata) }), inputs);
|
|
return [output];
|
|
};
|
|
exports.tile = tile;
|
|
const createTileProgramInfo = (handler, inputs, tileProgramMetadata) => {
|
|
const inputShape = inputs[0].dims.slice();
|
|
const outputShape = new Array(inputShape.length);
|
|
const tileOps = [];
|
|
for (let i = 0; i < inputShape.length; i++) {
|
|
outputShape[i] = inputShape[i] * inputs[1].numberData[i];
|
|
tileOps.push(`inputIdx[${i}] = int(mod(float(outputIdx[${i}]), ${inputShape[i]}.));`);
|
|
}
|
|
const rank = outputShape.length;
|
|
const shaderSource = `
|
|
float process(int outputIdx[${rank}]) {
|
|
int inputIdx[${rank}];
|
|
${tileOps.join('\n')}
|
|
return _A(inputIdx);
|
|
}
|
|
`;
|
|
return Object.assign(Object.assign({}, tileProgramMetadata), { output: { dims: outputShape, type: inputs[0].type, textureType: types_1.TextureType.unpacked }, shaderSource });
|
|
};
|
|
const validateInputs = (inputs) => {
|
|
if (!inputs || inputs.length !== 2) {
|
|
throw new Error('Tile requires 2 input.');
|
|
}
|
|
if (inputs[1].dims.length !== 1) {
|
|
throw new Error('The second input shape must 1 dimension.');
|
|
}
|
|
if (inputs[1].dims[0] !== inputs[0].dims.length) {
|
|
throw new Error('Invalid input shape.');
|
|
}
|
|
if (operators_1.NUMBER_TYPES.indexOf(inputs[0].type) === -1) {
|
|
throw new Error('Invalid input type.');
|
|
}
|
|
if (inputs[1].type !== 'int32' && inputs[1].type !== 'int16') {
|
|
throw new Error('Invalid repeat type.');
|
|
}
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./lib/onnxjs/backends/webgl/ops/transpose.ts":
|
|
/*!****************************************************!*\
|
|
!*** ./lib/onnxjs/backends/webgl/ops/transpose.ts ***!
|
|
\****************************************************/
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
// Licensed under the MIT License.
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.parseTransposeAttributes = exports.transpose = void 0;
|
|
const attribute_with_cache_key_1 = __webpack_require__(/*! ../../../attribute-with-cache-key */ "./lib/onnxjs/attribute-with-cache-key.ts");
|
|
const util_1 = __webpack_require__(/*! ../../../util */ "./lib/onnxjs/util.ts");
|
|
const types_1 = __webpack_require__(/*! ../types */ "./lib/onnxjs/backends/webgl/types.ts");
|
|
const transposeProgramMetadata = {
|
|
name: 'Transpose',
|
|
inputNames: ['A'],
|
|
inputTypes: [types_1.TextureType.unpacked]
|
|
};
|
|
const transpose = (inferenceHandler, inputs, attributes) => {
|
|
validateInputs(inputs);
|
|
const output = inferenceHandler.run(Object.assign(Object.assign({}, transposeProgramMetadata), { cacheHint: attributes.cacheKey, get: () => createTransposeProgramInfo(inferenceHandler, inputs[0], attributes.perm) }), inputs);
|
|
return [output];
|
|
};
|
|
exports.transpose = transpose;
|
|
const parseTransposeAttributes = (node) => (0, attribute_with_cache_key_1.createAttributeWithCacheKey)({ perm: node.attributes.getInts('perm', []) });
|
|
exports.parseTransposeAttributes = parseTransposeAttributes;
|
|
const createTransposeProgramInfo = (inferenceHandler, input, perm) => {
|
|
const inputShape = input.dims;
|
|
perm = getAdjustedPerm(inputShape, perm);
|
|
const unpackedOutputShape = getOutputShape(inputShape, perm);
|
|
const rank = inputShape.length;
|
|
// A dims=[${inputs[0].dims.toString()}]
|
|
// out Dims=[${unpackedOutputShape.toString()}]
|
|
// based on perm=[${perm.toString()}]
|
|
const shaderSource = `
|
|
${getPermFunctionBody('perm', perm, rank)}
|
|
float process(int indices[${rank}]) {
|
|
int a[${rank}];
|
|
perm(a, indices);
|
|
return _A(a);
|
|
}`;
|
|
return Object.assign(Object.assign({}, transposeProgramMetadata), { output: { dims: unpackedOutputShape, type: input.type, textureType: types_1.TextureType.unpacked }, shaderSource });
|
|
};
|
|
const getAdjustedPerm = (inputShape, perm) => {
|
|
if (perm && perm.length !== inputShape.length) {
|
|
perm = [...(inputShape.keys())].reverse();
|
|
}
|
|
return perm;
|
|
};
|
|
const getOutputShape = (inputShape, perm) => {
|
|
perm = getAdjustedPerm(inputShape, perm);
|
|
return util_1.ShapeUtil.sortBasedOnPerm(inputShape, perm);
|
|
};
|
|
const getPermFunctionBody = (name, perm, rank) => {
|
|
const reverseFunc = [];
|
|
reverseFunc.push(`void ${name}(out int a[${rank}], int src[${rank}]) {`);
|
|
for (let i = 0; i < rank; ++i) {
|
|
reverseFunc.push(`\ta[${perm[i]}]=src[${i}];`);
|
|
}
|
|
reverseFunc.push('\t}');
|
|
return reverseFunc.join('\n');
|
|
};
|
|
const validateInputs = (inputs) => {
|
|
if (!inputs || inputs.length !== 1) {
|
|
throw new Error('Transpose requires 1 input.');
|
|
}
|
|
if (inputs[0].type !== 'float32' && inputs[0].type !== 'float64') {
|
|
throw new Error('input should be float tensor');
|
|
}
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./lib/onnxjs/backends/webgl/ops/uint8-encode.ts":
|
|
/*!*******************************************************!*\
|
|
!*** ./lib/onnxjs/backends/webgl/ops/uint8-encode.ts ***!
|
|
\*******************************************************/
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
// Licensed under the MIT License.
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.encodeAsUint8 = void 0;
|
|
const glsl_source_1 = __webpack_require__(/*! ../glsl-source */ "./lib/onnxjs/backends/webgl/glsl-source.ts");
|
|
const types_1 = __webpack_require__(/*! ../types */ "./lib/onnxjs/backends/webgl/types.ts");
|
|
const encodeAsUint8 = (inferenceHandler, input) => {
|
|
const outputShape = input.shape;
|
|
const glsl = (0, glsl_source_1.getGlsl)(inferenceHandler.session.backend.glContext.version);
|
|
/**
|
|
* https://github.com/tensorflow/tfjs-core/blob/master/src/kernels/webgl/encode_float_gpu.ts
|
|
*/
|
|
const shaderSource = `
|
|
const float FLOAT_MAX = 1.70141184e38;
|
|
const float FLOAT_MIN = 1.17549435e-38;
|
|
|
|
bool isNaN(float val) {
|
|
return (val < 1.0 || 0.0 < val || val == 0.0) ? false : true;
|
|
}
|
|
|
|
highp vec4 encodeAsUint8(highp float v) {
|
|
if (isNaN(v)) {
|
|
return vec4(255, 255, 255, 255);
|
|
}
|
|
|
|
highp float av = abs(v);
|
|
|
|
if(av < FLOAT_MIN) {
|
|
return vec4(0.0, 0.0, 0.0, 0.0);
|
|
} else if(v > FLOAT_MAX) {
|
|
return vec4(0.0, 0.0, 128.0, 127.0) / 255.0;
|
|
} else if(v < -FLOAT_MAX) {
|
|
return vec4(0.0, 0.0, 128.0, 255.0) / 255.0;
|
|
}
|
|
|
|
highp vec4 c = vec4(0,0,0,0);
|
|
|
|
highp float e = floor(log2(av));
|
|
highp float m = exp2(fract(log2(av))) - 1.0;
|
|
|
|
c[2] = floor(128.0 * m);
|
|
m -= c[2] / 128.0;
|
|
c[1] = floor(32768.0 * m);
|
|
m -= c[1] / 32768.0;
|
|
c[0] = floor(8388608.0 * m);
|
|
|
|
highp float ebias = e + 127.0;
|
|
c[3] = floor(ebias / 2.0);
|
|
ebias -= c[3] * 2.0;
|
|
c[2] += floor(ebias) * 128.0;
|
|
|
|
c[3] += 128.0 * step(0.0, -v);
|
|
|
|
return c / 255.0;
|
|
}
|
|
|
|
void main() {
|
|
float value = ${glsl.texture2D}(X,TexCoords).r;
|
|
${glsl.output} = encodeAsUint8(value);
|
|
}`;
|
|
const programInfo = {
|
|
name: 'Uint8Encode',
|
|
inputTypes: [types_1.TextureType.unpacked],
|
|
inputNames: ['X'],
|
|
output: { dims: outputShape, type: input.tensor.type, textureType: types_1.TextureType.downloadUint8AsFloat },
|
|
shaderSource,
|
|
hasMain: true
|
|
};
|
|
return inferenceHandler.executeProgram(programInfo, [input.tensor]);
|
|
};
|
|
exports.encodeAsUint8 = encodeAsUint8;
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./lib/onnxjs/backends/webgl/ops/unary-op.ts":
|
|
/*!***************************************************!*\
|
|
!*** ./lib/onnxjs/backends/webgl/ops/unary-op.ts ***!
|
|
\***************************************************/
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
// Licensed under the MIT License.
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.tanh = exports.tan = exports.sqrt = exports.sin = exports.sigmoid = exports.relu = exports.not = exports.neg = exports.log = exports.parseLeakyReluAttributes = exports.leakyRelu = exports.identity = exports.floor = exports.exp = exports.parseEluAttributes = exports.elu = exports.cos = exports.ceil = exports.clipV11 = exports.parseClipAttributes = exports.clip = exports.atan = exports.asin = exports.acos = exports.abs = exports.glslTanh = exports.glslTan = exports.glslSqrt = exports.glslSigmoid = exports.glslRelu = exports.glslSin = exports.glslNot = exports.glslNeg = exports.glslLog = exports.glslLeakyRelu = exports.glslIdentity = exports.glslClip = exports.glslFloor = exports.glslExp = exports.glslElu = exports.glslCos = exports.glslCeil = exports.glslAtan = exports.glslAsin = exports.glslAcos = exports.glslAbs = void 0;
|
|
const attribute_with_cache_key_1 = __webpack_require__(/*! ../../../attribute-with-cache-key */ "./lib/onnxjs/attribute-with-cache-key.ts");
|
|
const util_1 = __webpack_require__(/*! ../../../util */ "./lib/onnxjs/util.ts");
|
|
const glsl_definitions_1 = __webpack_require__(/*! ../glsl-definitions */ "./lib/onnxjs/backends/webgl/glsl-definitions.ts");
|
|
const glsl_source_1 = __webpack_require__(/*! ../glsl-source */ "./lib/onnxjs/backends/webgl/glsl-source.ts");
|
|
const types_1 = __webpack_require__(/*! ../types */ "./lib/onnxjs/backends/webgl/types.ts");
|
|
function glslAbs() {
|
|
return glslBuiltinUnary('abs');
|
|
}
|
|
exports.glslAbs = glslAbs;
|
|
function glslAcos() {
|
|
return glslBuiltinUnary('acos');
|
|
}
|
|
exports.glslAcos = glslAcos;
|
|
function glslAsin() {
|
|
return glslBuiltinUnary('asin');
|
|
}
|
|
exports.glslAsin = glslAsin;
|
|
function glslAtan() {
|
|
return glslBuiltinUnary('atan');
|
|
}
|
|
exports.glslAtan = glslAtan;
|
|
function glslCeil() {
|
|
return glslBuiltinUnary('ceil');
|
|
}
|
|
exports.glslCeil = glslCeil;
|
|
function glslCos() {
|
|
return glslBuiltinUnary('cos');
|
|
}
|
|
exports.glslCos = glslCos;
|
|
function glslElu(alpha) {
|
|
const name = 'elu';
|
|
const body = `
|
|
const float alpha = float(${alpha});
|
|
|
|
float ${name}_(float a) {
|
|
return a >= 0.0 ? a: (exp(a) - 1.0) * alpha;
|
|
}
|
|
vec4 ${name}_(vec4 v) {
|
|
return vec4(${name}_(v.x), ${name}_(v.y), ${name}_(v.z), ${name}_(v.w));
|
|
}
|
|
`;
|
|
return { body, name, type: glsl_definitions_1.FunctionType.ValueBased };
|
|
}
|
|
exports.glslElu = glslElu;
|
|
function glslExp() {
|
|
return glslBuiltinUnary('exp');
|
|
}
|
|
exports.glslExp = glslExp;
|
|
function glslFloor() {
|
|
return glslBuiltinUnary('floor');
|
|
}
|
|
exports.glslFloor = glslFloor;
|
|
function glslClip(min, max) {
|
|
const name = 'clip';
|
|
const body = `
|
|
const float min = float(${min});
|
|
const float max = float(${max});
|
|
|
|
float ${name}_(float a) {
|
|
return clamp(a, min, max);
|
|
}
|
|
vec4 ${name}_(vec4 v) {
|
|
return clamp(v, min, max);
|
|
}
|
|
`;
|
|
return { body, name, type: glsl_definitions_1.FunctionType.ValueBased };
|
|
}
|
|
exports.glslClip = glslClip;
|
|
function glslIdentity() {
|
|
const name = 'indentity';
|
|
const body = `
|
|
float ${name}_(float a) {
|
|
return a;
|
|
}
|
|
vec4 ${name}_(vec4 v) {
|
|
return v;
|
|
}
|
|
`;
|
|
return { body, name, type: glsl_definitions_1.FunctionType.ValueBased };
|
|
}
|
|
exports.glslIdentity = glslIdentity;
|
|
function glslLeakyRelu(alpha) {
|
|
const name = 'leakyRelu';
|
|
const body = `
|
|
const float alpha = float(${alpha});
|
|
|
|
float ${name}_(float a) {
|
|
return a < 0.0 ? a * alpha : a;
|
|
}
|
|
vec4 ${name}_(vec4 v) {
|
|
return vec4(${name}_(v.x), ${name}_(v.y), ${name}_(v.z), ${name}_(v.w));
|
|
}
|
|
`;
|
|
return { body, name, type: glsl_definitions_1.FunctionType.ValueBased };
|
|
}
|
|
exports.glslLeakyRelu = glslLeakyRelu;
|
|
function glslLog() {
|
|
return glslBuiltinUnary('log');
|
|
}
|
|
exports.glslLog = glslLog;
|
|
function glslNeg() {
|
|
const name = 'neg';
|
|
const body = `
|
|
float ${name}_(float a) {
|
|
return -a;
|
|
}
|
|
vec4 ${name}_(vec4 v) {
|
|
return -v;
|
|
}
|
|
`;
|
|
return { body, name, type: glsl_definitions_1.FunctionType.ValueBased };
|
|
}
|
|
exports.glslNeg = glslNeg;
|
|
function glslNot() {
|
|
const name = 'not';
|
|
const body = `
|
|
float ${name}_(float a) {
|
|
return float( ! bool(a) );
|
|
}
|
|
bool ${name}_(bool a) {
|
|
return !a;
|
|
}
|
|
vec4 ${name}_(vec4 v) {
|
|
return vec4(!bool(v.x), !bool(v.y), !bool(v.z), !bool(v.w));
|
|
}
|
|
bvec4 ${name}_(bvec4 v) {
|
|
return bvec4(!v.x, !v.y, !v.z, !v.w);
|
|
}
|
|
`;
|
|
return { body, name, type: glsl_definitions_1.FunctionType.ValueBased };
|
|
}
|
|
exports.glslNot = glslNot;
|
|
function glslSin() {
|
|
return glslBuiltinUnary('sin');
|
|
}
|
|
exports.glslSin = glslSin;
|
|
function glslRelu() {
|
|
const name = 'relu';
|
|
const body = `
|
|
float ${name}_(float a) {
|
|
return max( a, 0.0 );
|
|
}
|
|
vec4 ${name}_(vec4 v) {
|
|
return max( v, 0.0 );
|
|
}
|
|
`;
|
|
return { body, name, type: glsl_definitions_1.FunctionType.ValueBased };
|
|
}
|
|
exports.glslRelu = glslRelu;
|
|
function glslSigmoid() {
|
|
const name = 'sigmoid';
|
|
const body = `
|
|
float ${name}_(float a) {
|
|
return 1.0 / (1.0 + exp(-a));
|
|
}
|
|
vec4 ${name}_(vec4 v) {
|
|
return 1.0 / (1.0 + exp(-v));
|
|
}
|
|
`;
|
|
return { body, name, type: glsl_definitions_1.FunctionType.ValueBased };
|
|
}
|
|
exports.glslSigmoid = glslSigmoid;
|
|
function glslSqrt() {
|
|
return glslBuiltinUnary('sqrt');
|
|
}
|
|
exports.glslSqrt = glslSqrt;
|
|
function glslTan() {
|
|
return glslBuiltinUnary('tan');
|
|
}
|
|
exports.glslTan = glslTan;
|
|
function glslTanh() {
|
|
const name = 'tanh';
|
|
const body = `
|
|
float ${name}_(float a) {
|
|
a = clamp(a, -10., 10.);
|
|
a = exp(2.*a);
|
|
return (a - 1.) / (a + 1.);
|
|
}
|
|
vec4 ${name}_(vec4 v) {
|
|
v = clamp(v, -10., 10.);
|
|
v = exp(2.*v);
|
|
return (v - 1.) / (v + 1.);
|
|
}
|
|
`;
|
|
return { body, name, type: glsl_definitions_1.FunctionType.ValueBased };
|
|
}
|
|
exports.glslTanh = glslTanh;
|
|
function glslBuiltinUnary(name) {
|
|
const body = `
|
|
float ${name}_(float a) {
|
|
return ${name}(a);
|
|
}
|
|
vec4 ${name}_(vec4 v) {
|
|
return ${name}(v);
|
|
}
|
|
`;
|
|
return { body, name, type: glsl_definitions_1.FunctionType.ValueBased };
|
|
}
|
|
/////
|
|
/////
|
|
/////
|
|
const createElementwiseProgramInfo = (handler, metadata, input, glslFunc) => {
|
|
const textureType = handler.session.pack ? types_1.TextureType.packed : types_1.TextureType.unpacked;
|
|
const glsl = (0, glsl_source_1.getGlsl)(handler.session.backend.glContext.version);
|
|
return Object.assign(Object.assign({}, metadata), { output: { dims: input.dims, type: input.type, textureType }, shaderSource: `
|
|
${glslFunc.body}
|
|
void main() {
|
|
vec4 v = ${glsl.texture2D}(A, TexCoords);
|
|
v = ${glslFunc.name}_(v);
|
|
${glsl.output} = v;
|
|
}
|
|
`, hasMain: true });
|
|
};
|
|
const createElementwiseProgramInfoLoader = (handler, input, glslFunc, cacheKey) => {
|
|
const textureType = handler.session.pack ? types_1.TextureType.packed : types_1.TextureType.unpacked;
|
|
const metadata = { name: glslFunc.name, inputTypes: [textureType], inputNames: ['A'], cacheHint: cacheKey };
|
|
return Object.assign(Object.assign({}, metadata), { get: () => createElementwiseProgramInfo(handler, metadata, input, glslFunc) });
|
|
};
|
|
const abs = (handler, inputs) => [handler.run(createElementwiseProgramInfoLoader(handler, inputs[0], glslAbs()), inputs)];
|
|
exports.abs = abs;
|
|
const acos = (handler, inputs) => [handler.run(createElementwiseProgramInfoLoader(handler, inputs[0], glslAcos()), inputs)];
|
|
exports.acos = acos;
|
|
const asin = (handler, inputs) => [handler.run(createElementwiseProgramInfoLoader(handler, inputs[0], glslAsin()), inputs)];
|
|
exports.asin = asin;
|
|
const atan = (handler, inputs) => [handler.run(createElementwiseProgramInfoLoader(handler, inputs[0], glslAtan()), inputs)];
|
|
exports.atan = atan;
|
|
const clip = (handler, inputs, attributes) => [handler.run(createElementwiseProgramInfoLoader(handler, inputs[0], glslClip(attributes.min, attributes.max), attributes.cacheKey), inputs)];
|
|
exports.clip = clip;
|
|
const parseClipAttributes = (node) => (0, attribute_with_cache_key_1.createAttributeWithCacheKey)({ min: node.attributes.getFloat('min', util_1.MIN_CLIP), max: node.attributes.getFloat('max', util_1.MAX_CLIP) });
|
|
exports.parseClipAttributes = parseClipAttributes;
|
|
const clipV11 = (handler, inputs) => {
|
|
const attributes = generateClipAttributesFromInputs(handler, inputs);
|
|
return (0, exports.clip)(handler, [inputs[0]], attributes);
|
|
};
|
|
exports.clipV11 = clipV11;
|
|
const generateClipAttributesFromInputs = (handler, inputs) => {
|
|
if (inputs.length >= 3 &&
|
|
(!handler.session.isInitializer(inputs[1].dataId) || !handler.session.isInitializer(inputs[2].dataId))) {
|
|
throw new Error('dynamic clip attributes are not allowed');
|
|
}
|
|
const min = (inputs.length >= 3) ? inputs[1].numberData[0] : util_1.MIN_CLIP;
|
|
const max = (inputs.length >= 3) ? inputs[2].numberData[0] : util_1.MAX_CLIP;
|
|
return (0, attribute_with_cache_key_1.createAttributeWithCacheKey)({ min, max });
|
|
};
|
|
const ceil = (handler, inputs) => [handler.run(createElementwiseProgramInfoLoader(handler, inputs[0], glslCeil()), inputs)];
|
|
exports.ceil = ceil;
|
|
const cos = (handler, inputs) => [handler.run(createElementwiseProgramInfoLoader(handler, inputs[0], glslCos()), inputs)];
|
|
exports.cos = cos;
|
|
const elu = (handler, inputs, attributes) => [handler.run(createElementwiseProgramInfoLoader(handler, inputs[0], glslElu(attributes.alpha), attributes.cacheKey), inputs)];
|
|
exports.elu = elu;
|
|
const parseEluAttributes = (node) => (0, attribute_with_cache_key_1.createAttributeWithCacheKey)({ alpha: node.attributes.getFloat('alpha', 1.0) });
|
|
exports.parseEluAttributes = parseEluAttributes;
|
|
const exp = (handler, inputs) => [handler.run(createElementwiseProgramInfoLoader(handler, inputs[0], glslExp()), inputs)];
|
|
exports.exp = exp;
|
|
const floor = (handler, inputs) => [handler.run(createElementwiseProgramInfoLoader(handler, inputs[0], glslFloor()), inputs)];
|
|
exports.floor = floor;
|
|
const identity = (handler, inputs) => [handler.run(createElementwiseProgramInfoLoader(handler, inputs[0], glslIdentity()), inputs)];
|
|
exports.identity = identity;
|
|
const leakyRelu = (handler, inputs, attributes) => [handler.run(createElementwiseProgramInfoLoader(handler, inputs[0], glslLeakyRelu(attributes.alpha), attributes.cacheKey), inputs)];
|
|
exports.leakyRelu = leakyRelu;
|
|
const parseLeakyReluAttributes = (node) => (0, attribute_with_cache_key_1.createAttributeWithCacheKey)({ alpha: node.attributes.getFloat('alpha', 0.01) });
|
|
exports.parseLeakyReluAttributes = parseLeakyReluAttributes;
|
|
const log = (handler, inputs) => [handler.run(createElementwiseProgramInfoLoader(handler, inputs[0], glslLog()), inputs)];
|
|
exports.log = log;
|
|
const neg = (handler, inputs) => [handler.run(createElementwiseProgramInfoLoader(handler, inputs[0], glslNeg()), inputs)];
|
|
exports.neg = neg;
|
|
const not = (handler, inputs) => [handler.run(createElementwiseProgramInfoLoader(handler, inputs[0], glslNot()), inputs)];
|
|
exports.not = not;
|
|
const relu = (handler, inputs) => [handler.run(createElementwiseProgramInfoLoader(handler, inputs[0], glslRelu()), inputs)];
|
|
exports.relu = relu;
|
|
const sigmoid = (handler, inputs) => [handler.run(createElementwiseProgramInfoLoader(handler, inputs[0], glslSigmoid()), inputs)];
|
|
exports.sigmoid = sigmoid;
|
|
const sin = (handler, inputs) => [handler.run(createElementwiseProgramInfoLoader(handler, inputs[0], glslSin()), inputs)];
|
|
exports.sin = sin;
|
|
const sqrt = (handler, inputs) => [handler.run(createElementwiseProgramInfoLoader(handler, inputs[0], glslSqrt()), inputs)];
|
|
exports.sqrt = sqrt;
|
|
const tan = (handler, inputs) => [handler.run(createElementwiseProgramInfoLoader(handler, inputs[0], glslTan()), inputs)];
|
|
exports.tan = tan;
|
|
const tanh = (handler, inputs) => [handler.run(createElementwiseProgramInfoLoader(handler, inputs[0], glslTanh()), inputs)];
|
|
exports.tanh = tanh;
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./lib/onnxjs/backends/webgl/ops/unpack.ts":
|
|
/*!*************************************************!*\
|
|
!*** ./lib/onnxjs/backends/webgl/ops/unpack.ts ***!
|
|
\*************************************************/
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
// Licensed under the MIT License.
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.createUnpackProgramInfoLoader = exports.createUnpackProgramInfo = void 0;
|
|
const glsl_source_1 = __webpack_require__(/*! ../glsl-source */ "./lib/onnxjs/backends/webgl/glsl-source.ts");
|
|
const types_1 = __webpack_require__(/*! ../types */ "./lib/onnxjs/backends/webgl/types.ts");
|
|
const utils_1 = __webpack_require__(/*! ../utils */ "./lib/onnxjs/backends/webgl/utils.ts");
|
|
const packing_utils_1 = __webpack_require__(/*! ./packing-utils */ "./lib/onnxjs/backends/webgl/ops/packing-utils.ts");
|
|
const unpackProgramMetadata = {
|
|
name: 'unpack',
|
|
inputNames: ['A'],
|
|
inputTypes: [types_1.TextureType.packed]
|
|
};
|
|
const createUnpackProgramInfo = (handler, input) => {
|
|
const rank = input.dims.length;
|
|
const channels = (0, packing_utils_1.getChannels)('rc', rank);
|
|
const innerDims = channels.slice(-2);
|
|
const coordsDataType = (0, utils_1.getCoordsDataType)(rank);
|
|
const unpackChannel = (0, packing_utils_1.unpackFromChannel)();
|
|
const isScalar = (input.dims.length === 0);
|
|
const sourceCoords = isScalar ? '' : getSourceCoords(rank, channels);
|
|
const coords = rank <= 1 ? 'rc' : `vec2(${innerDims.join(',')})`;
|
|
const glsl = (0, glsl_source_1.getGlsl)(handler.session.backend.glContext.version);
|
|
const shaderSource = `
|
|
${unpackChannel}
|
|
void main() {
|
|
${coordsDataType} rc = getOutputCoords();
|
|
|
|
// Sample the texture with the coords to get the rgba channel value.
|
|
vec4 packedInput = getA(${sourceCoords});
|
|
|
|
${glsl.output} = vec4(getChannel(packedInput, ${coords}), 0, 0, 0);
|
|
}
|
|
`;
|
|
return Object.assign(Object.assign({}, unpackProgramMetadata), { hasMain: true, output: { dims: input.dims, type: input.type, textureType: types_1.TextureType.unpacked }, shaderSource });
|
|
};
|
|
exports.createUnpackProgramInfo = createUnpackProgramInfo;
|
|
const createUnpackProgramInfoLoader = (handler, input) => (Object.assign(Object.assign({}, unpackProgramMetadata), { get: () => (0, exports.createUnpackProgramInfo)(handler, input) }));
|
|
exports.createUnpackProgramInfoLoader = createUnpackProgramInfoLoader;
|
|
function getSourceCoords(rank, dims) {
|
|
if (rank === 1) {
|
|
return 'rc';
|
|
}
|
|
let coords = '';
|
|
for (let i = 0; i < rank; i++) {
|
|
coords += dims[i];
|
|
if (i < rank - 1) {
|
|
coords += ',';
|
|
}
|
|
}
|
|
return coords;
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./lib/onnxjs/backends/webgl/ops/unsqueeze.ts":
|
|
/*!****************************************************!*\
|
|
!*** ./lib/onnxjs/backends/webgl/ops/unsqueeze.ts ***!
|
|
\****************************************************/
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
// Licensed under the MIT License.
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.parseUnsqueezeAttributes = exports.unsqueezeV13 = exports.unsqueeze = void 0;
|
|
const util_1 = __webpack_require__(/*! ../../../util */ "./lib/onnxjs/util.ts");
|
|
const unsqueeze = (inferenceHandler, inputs, axes) => {
|
|
validateInputs(inputs);
|
|
const outputShape = util_1.ShapeUtil.unsqueezeShape(inputs[0].dims, axes);
|
|
const output = inferenceHandler.reshapeUnpacked(inputs[0], outputShape);
|
|
return [output];
|
|
};
|
|
exports.unsqueeze = unsqueeze;
|
|
const unsqueezeV13 = (inferenceHandler, inputs) => {
|
|
validateInputsV13(inputs);
|
|
return (0, exports.unsqueeze)(inferenceHandler, [inputs[0]], Array.from(inputs[1].integerData));
|
|
};
|
|
exports.unsqueezeV13 = unsqueezeV13;
|
|
const parseUnsqueezeAttributes = (node) => node.attributes.getInts('axes');
|
|
exports.parseUnsqueezeAttributes = parseUnsqueezeAttributes;
|
|
const validateInputs = (inputs) => {
|
|
if (!inputs || inputs.length !== 1) {
|
|
throw new Error('Unsqueeze requires 1 input.');
|
|
}
|
|
if (inputs[0].type === 'string') {
|
|
throw new Error('invalid input tensor types.');
|
|
}
|
|
};
|
|
const validateInputsV13 = (inputs) => {
|
|
if (!inputs || inputs.length !== 2) {
|
|
throw new Error('Unsqueeze requires 2 inputs.');
|
|
}
|
|
if (inputs[1].type !== 'int32') {
|
|
throw new Error('Invalid input type.');
|
|
}
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./lib/onnxjs/backends/webgl/ops/upsample.ts":
|
|
/*!***************************************************!*\
|
|
!*** ./lib/onnxjs/backends/webgl/ops/upsample.ts ***!
|
|
\***************************************************/
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
// Licensed under the MIT License.
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.scalesValidation = exports.validateInputs = exports.parseUpsampleAttributes = exports.parseUpsampleAttributesV9 = exports.parseUpsampleAttributesV7 = exports.upsample = void 0;
|
|
const attribute_with_cache_key_1 = __webpack_require__(/*! ../../../attribute-with-cache-key */ "./lib/onnxjs/attribute-with-cache-key.ts");
|
|
const glsl_source_1 = __webpack_require__(/*! ../glsl-source */ "./lib/onnxjs/backends/webgl/glsl-source.ts");
|
|
const types_1 = __webpack_require__(/*! ../types */ "./lib/onnxjs/backends/webgl/types.ts");
|
|
const upsampleProgramMetadata = {
|
|
name: 'Upsample',
|
|
inputNames: ['X'],
|
|
inputTypes: [types_1.TextureType.unpacked],
|
|
};
|
|
const upsample = (inferenceHandler, inputs, attributes) => {
|
|
(0, exports.validateInputs)(inputs, attributes);
|
|
const output = inferenceHandler.run(Object.assign(Object.assign({}, upsampleProgramMetadata), { cacheHint: attributes.cacheKey, get: () => createUpsampleProgramInfo(inferenceHandler, inputs, attributes) }), inputs);
|
|
return [output];
|
|
};
|
|
exports.upsample = upsample;
|
|
const parseUpsampleAttributesV7 = (node) => (0, exports.parseUpsampleAttributes)(node, 7);
|
|
exports.parseUpsampleAttributesV7 = parseUpsampleAttributesV7;
|
|
const parseUpsampleAttributesV9 = (node) => (0, exports.parseUpsampleAttributes)(node, 9);
|
|
exports.parseUpsampleAttributesV9 = parseUpsampleAttributesV9;
|
|
const parseUpsampleAttributes = (node, opset) => {
|
|
const isResize = (opset >= 10);
|
|
// processing node attributes
|
|
const mode = node.attributes.getString('mode', 'nearest');
|
|
if (mode !== 'nearest' && mode !== 'linear' && (opset < 11 || mode !== 'cubic')) {
|
|
throw new Error(`unrecognized mode: ${mode}`);
|
|
}
|
|
let scales = [];
|
|
if (opset < 9) {
|
|
scales = node.attributes.getFloats('scales');
|
|
(0, exports.scalesValidation)(scales, mode, isResize);
|
|
}
|
|
const extrapolationValue = node.attributes.getFloat('extrapolation_value', 0.0);
|
|
const coordinateTransformMode = opset > 10 ? node.attributes.getString('coordinate_transformation_mode', 'half_pixel') : 'asymmetric';
|
|
if ([
|
|
'asymmetric', 'pytorch_half_pixel', 'tf_half_pixel_for_nn', 'align_corners', 'tf_crop_and_resize', 'half_pixel'
|
|
].indexOf(coordinateTransformMode) === -1) {
|
|
throw new Error(`coordinate_transform_mode '${coordinateTransformMode}' is not supported`);
|
|
}
|
|
const needRoiInput = (coordinateTransformMode === 'tf_crop_and_resize');
|
|
const useExtrapolation = needRoiInput;
|
|
const nearestMode = (mode === 'nearest' && opset >= 11) ? node.attributes.getString('nearest_mode', 'round_prefer_floor') : '';
|
|
if (['round_prefer_floor', 'round_prefer_ceil', 'floor', 'ceil', ''].indexOf(nearestMode) === -1) {
|
|
throw new Error(`nearest_mode '${nearestMode}' is not supported`);
|
|
}
|
|
const cubicCoefficientA = node.attributes.getFloat('cubic_coeff_a', -0.75);
|
|
const excludeOutside = node.attributes.getInt('exclude_outside', 0) !== 0;
|
|
if (excludeOutside && mode !== 'cubic') {
|
|
throw new Error('exclude_outside can be set to 1 only when mode is CUBIC.');
|
|
}
|
|
const useNearest2xOptimization = (opset < 11) ? true : (mode === 'nearest' && coordinateTransformMode === 'asymmetric' && nearestMode === 'floor');
|
|
let roiInputIdx = 0;
|
|
let scalesInputIdx = 0;
|
|
let sizesInputIdx = 0;
|
|
if (opset > 10) {
|
|
// handle when roiInput is not given
|
|
if (node.inputs.length > 2) {
|
|
roiInputIdx = 1;
|
|
scalesInputIdx = 2;
|
|
sizesInputIdx = 3;
|
|
}
|
|
else {
|
|
scalesInputIdx = 1;
|
|
sizesInputIdx = 2;
|
|
}
|
|
}
|
|
else if (opset === 9) {
|
|
scalesInputIdx = 1;
|
|
}
|
|
return (0, attribute_with_cache_key_1.createAttributeWithCacheKey)({
|
|
opset,
|
|
isResize,
|
|
mode,
|
|
scales,
|
|
extrapolationValue,
|
|
coordinateTransformMode,
|
|
useExtrapolation,
|
|
needRoiInput,
|
|
nearestMode,
|
|
cubicCoefficientA,
|
|
excludeOutside,
|
|
useNearest2xOptimization,
|
|
roiInputIdx,
|
|
scalesInputIdx,
|
|
sizesInputIdx
|
|
});
|
|
};
|
|
exports.parseUpsampleAttributes = parseUpsampleAttributes;
|
|
const createUpsampleProgramInfo = (inferenceHandler, inputs, attributes) => {
|
|
const glsl = (0, glsl_source_1.getGlsl)(inferenceHandler.session.backend.glContext.version);
|
|
const [inputWidth, inputHeight] = inferenceHandler.calculateTextureWidthAndHeight(inputs[0].dims, types_1.TextureType.unpacked);
|
|
const outputShape = inputs[0].dims.map((dim, i) => Math.floor(dim * attributes.scales[i]));
|
|
const [outputWidth, outputHeight] = inferenceHandler.calculateTextureWidthAndHeight(outputShape, types_1.TextureType.unpacked);
|
|
const dim = outputShape.length;
|
|
const outputPitches = new Array(dim);
|
|
const inputPitches = new Array(dim);
|
|
let precalculatedPitches = `
|
|
int output_pitches[${dim}];
|
|
int input_pitches[${dim}];
|
|
`;
|
|
for (let d = dim - 1; d >= 0; d--) {
|
|
outputPitches[d] = (d === dim - 1) ? 1 : outputPitches[d + 1] * outputShape[d + 1];
|
|
inputPitches[d] = (d === dim - 1) ? 1 : inputPitches[d + 1] * inputs[0].dims[d + 1];
|
|
precalculatedPitches += `
|
|
output_pitches[${d}] = ${outputPitches[d]};
|
|
input_pitches[${d}] = ${inputPitches[d]};
|
|
`;
|
|
}
|
|
const getInputFloatFunction = `
|
|
float getInputFloat(int index) {
|
|
vec2 coords = offsetToCoords(index, ${inputWidth}, ${inputHeight});
|
|
float value = getColorAsFloat(${glsl.texture2D}(X, coords));
|
|
return value;
|
|
}
|
|
`;
|
|
const shaderSource = attributes.mode === 'nearest' ?
|
|
// nearest
|
|
`
|
|
${getInputFloatFunction}
|
|
float process(int indices[${dim}]) {
|
|
int input_index = 0;
|
|
int output_index = coordsToOffset(TexCoords, ${outputWidth}, ${outputHeight});
|
|
|
|
${precalculatedPitches}
|
|
|
|
int d, m;
|
|
for (int dim = 0; dim < ${dim}; ++dim) {
|
|
d = output_index / output_pitches[dim];
|
|
m = output_index - d * output_pitches[dim];
|
|
output_index = m;
|
|
|
|
if (scales[dim] != 1 && d > 0) {
|
|
int d2 = d / scales[dim];
|
|
m = d - d2 * scales[dim];
|
|
d = d2;
|
|
}
|
|
input_index += input_pitches[dim] * d;
|
|
}
|
|
|
|
return getInputFloat(input_index);
|
|
}` :
|
|
dim === 4 ?
|
|
// bilinear 4D
|
|
`
|
|
${getInputFloatFunction}
|
|
float process(int indices[4]) {
|
|
int input_index = 0;
|
|
int output_index = coordsToOffset(TexCoords, ${outputWidth}, ${outputHeight});
|
|
|
|
${precalculatedPitches}
|
|
|
|
int m;
|
|
int index_of_dim0, index_of_dim1, index_of_dim2, index_of_dim3;
|
|
index_of_dim0 = output_index / output_pitches[0];
|
|
m = output_index - index_of_dim0 * output_pitches[0];
|
|
index_of_dim1 = m / output_pitches[1];
|
|
m = m - index_of_dim1 * output_pitches[1];
|
|
index_of_dim2 = m / output_pitches[2];
|
|
m = m - index_of_dim2 * output_pitches[2];
|
|
index_of_dim3 = m;
|
|
|
|
int index_of_input_dim2, index_of_input_dim3, x_offset, y_offset;
|
|
index_of_input_dim2 = index_of_dim2 / scales[2];
|
|
y_offset = index_of_dim2 - index_of_input_dim2 * scales[2];
|
|
index_of_input_dim3 = index_of_dim3 / scales[3];
|
|
x_offset = index_of_dim3 - index_of_input_dim3 * scales[3];
|
|
|
|
input_index = index_of_dim0 * input_pitches[0] +
|
|
index_of_dim1 * input_pitches[1] +
|
|
index_of_input_dim2 * input_pitches[2] +
|
|
index_of_input_dim3;
|
|
|
|
float x00 = getInputFloat(input_index);
|
|
float x10, x01, x11;
|
|
|
|
bool end_of_dim2 = false;
|
|
if (index_of_input_dim2 == (${inputs[0].dims[2]} - 1)) {
|
|
// It's the end in dimension 2
|
|
x01 = x00;
|
|
end_of_dim2 = true;
|
|
} else {
|
|
x01 = getInputFloat(input_index + input_pitches[2]);
|
|
}
|
|
|
|
if (index_of_input_dim3 == (input_pitches[2] - 1)) {
|
|
// It's the end in dimension 3
|
|
x10 = x00;
|
|
x11 = x01;
|
|
}
|
|
else {
|
|
x10 = getInputFloat(input_index + 1);
|
|
x11 = end_of_dim2 ? x10 : getInputFloat(input_index + input_pitches[2] + 1);
|
|
}
|
|
|
|
float y0 = x00 + float(y_offset) * (x01 - x00) / float(scales[2]);
|
|
float y1 = x10 + float(y_offset) * (x11 - x10) / float(scales[2]);
|
|
return y0 + float(x_offset) * (y1 - y0) / float(scales[3]);
|
|
}` :
|
|
// bilinear 2D
|
|
`
|
|
${getInputFloatFunction}
|
|
float process(int indices[2]) {
|
|
int input_index = 0;
|
|
int output_index = coordsToOffset(TexCoords, ${outputWidth}, ${outputHeight});
|
|
|
|
${precalculatedPitches}
|
|
|
|
int m;
|
|
int index_of_dim0, index_of_dim1;
|
|
index_of_dim0 = output_index / output_pitches[0];
|
|
m = output_index - index_of_dim0 * output_pitches[0];
|
|
index_of_dim1 = m;
|
|
|
|
int index_of_input_dim0, index_of_input_dim1, x_offset, y_offset;
|
|
index_of_input_dim0 = index_of_dim0 / scales[0];
|
|
y_offset = index_of_dim0 - index_of_input_dim0 * scales[0];
|
|
index_of_input_dim1 = index_of_dim1 / scales[1];
|
|
x_offset = index_of_dim1 - index_of_input_dim1 * scales[1];
|
|
|
|
input_index = index_of_input_dim0 * input_pitches[0] + index_of_input_dim1;
|
|
|
|
float x00 = getInputFloat(input_index);
|
|
float x10, x01, x11;
|
|
|
|
bool end_of_dim0 = false;
|
|
if (index_of_input_dim0 == (${inputs[0].dims[0]} - 1)) {
|
|
// It's the end in dimension 0
|
|
x01 = x00;
|
|
end_of_dim0 = true;
|
|
} else {
|
|
x01 = getInputFloat(input_index + input_pitches[0]);
|
|
}
|
|
|
|
if (index_of_input_dim1 == (input_pitches[0] - 1)) {
|
|
// It's the end in dimension 1
|
|
x10 = x00;
|
|
x11 = x01;
|
|
}
|
|
else {
|
|
x10 = getInputFloat(input_index + 1);
|
|
x11 = end_of_dim0 ? x10 : getInputFloat(input_index + input_pitches[0] + 1);
|
|
}
|
|
|
|
float y0 = x00 + float(y_offset) * (x01 - x00) / float(scales[0]);
|
|
float y1 = x10 + float(y_offset) * (x11 - x10) / float(scales[0]);
|
|
return y0 + float(x_offset) * (y1 - y0) / float(scales[1]);
|
|
}`;
|
|
return Object.assign(Object.assign({}, upsampleProgramMetadata), { output: { dims: outputShape, type: inputs[0].type, textureType: types_1.TextureType.unpacked }, shaderSource, variables: [{
|
|
name: 'scales',
|
|
type: 'int',
|
|
arrayLength: attributes.scales.length,
|
|
data: attributes.scales.map(x => Math.ceil(x))
|
|
}] });
|
|
};
|
|
const validateInputs = (inputs, attribute) => {
|
|
if (!inputs || (attribute.opset < 9 && inputs.length !== 1) ||
|
|
(attribute.opset >= 9 && attribute.opset < 11 && inputs.length !== 2) ||
|
|
(attribute.opset >= 11 && inputs.length < 2)) {
|
|
throw new Error('invalid inputs.');
|
|
}
|
|
if (attribute.scales.length > 0 && inputs[0].dims.length !== attribute.scales.length) {
|
|
throw new Error('Invalid input shape.');
|
|
}
|
|
if (inputs[0].type === 'string') {
|
|
throw new Error('Invalid input tensor types.');
|
|
}
|
|
};
|
|
exports.validateInputs = validateInputs;
|
|
const scalesValidation = (scales, mode, isResize) => {
|
|
if (!isResize) {
|
|
for (const scale of scales) {
|
|
if (scale < 1) {
|
|
throw new Error('Scale value should be greater than or equal to 1.');
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
for (const scale of scales) {
|
|
if (scale <= 0) {
|
|
throw new Error('Scale value should be greater than 0.');
|
|
}
|
|
}
|
|
}
|
|
if (mode === 'linear' || mode === 'cubic') {
|
|
if (scales.length !== 2 && (scales.length !== 4 || scales[0] !== 1 || scales[1] !== 1)) {
|
|
throw new Error(`'Linear' mode and 'Cubic' mode only support 2-D inputs ('Bilinear', 'Bicubic') \
|
|
or 4-D inputs with the corresponding outermost 2 scale values being 1 \
|
|
in the ${isResize ? 'Resize' : 'Upsample'} opeartor.`);
|
|
}
|
|
}
|
|
};
|
|
exports.scalesValidation = scalesValidation;
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./lib/onnxjs/backends/webgl/program-manager.ts":
|
|
/*!******************************************************!*\
|
|
!*** ./lib/onnxjs/backends/webgl/program-manager.ts ***!
|
|
\******************************************************/
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
// Licensed under the MIT License.
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.ProgramManager = void 0;
|
|
const onnxruntime_common_1 = __webpack_require__(/*! onnxruntime-common */ "../common/dist/lib/index.js");
|
|
const instrument_1 = __webpack_require__(/*! ../../instrument */ "./lib/onnxjs/instrument.ts");
|
|
const glsl_preprocessor_1 = __webpack_require__(/*! ./glsl-preprocessor */ "./lib/onnxjs/backends/webgl/glsl-preprocessor.ts");
|
|
const glsl_source_1 = __webpack_require__(/*! ./glsl-source */ "./lib/onnxjs/backends/webgl/glsl-source.ts");
|
|
/**
|
|
* ProgramManager is the main class behind running computations
|
|
* It builds ProgramInfo's into Artifacts
|
|
* It compiles given ProgramInfo's into WebGL Prorams (cached as Artifacts)
|
|
* Uses the artifact to run the computation by calling Draw on
|
|
* the WebGL drawing buffer
|
|
* ProgramManager automatically maps (binds) input variables to their
|
|
* corresponding Location's in the binary program
|
|
*/
|
|
class ProgramManager {
|
|
constructor(profiler, glContext, textureLayoutStrategy) {
|
|
this.profiler = profiler;
|
|
this.glContext = glContext;
|
|
this.textureLayoutStrategy = textureLayoutStrategy;
|
|
this.repo = new Map();
|
|
this.attributesBound = false;
|
|
}
|
|
getArtifact(key) {
|
|
return this.repo.get(key);
|
|
}
|
|
setArtifact(key, artifact) {
|
|
this.repo.set(key, artifact);
|
|
}
|
|
run(buildArtifact, inputs, output) {
|
|
var _a;
|
|
this.profiler.event('op', `ProgramManager.run ${(_a = buildArtifact.programInfo.name) !== null && _a !== void 0 ? _a : 'unknown kernel'}`, () => {
|
|
var _a;
|
|
const gl = this.glContext.gl;
|
|
const program = buildArtifact.program;
|
|
gl.useProgram(program);
|
|
try {
|
|
this.bindOutput(output);
|
|
if (!this.attributesBound) {
|
|
this.bindAttributes(buildArtifact.attribLocations);
|
|
}
|
|
this.bindUniforms(buildArtifact.uniformLocations, (_a = buildArtifact.programInfo.variables) !== null && _a !== void 0 ? _a : [], inputs);
|
|
}
|
|
catch (err) {
|
|
instrument_1.Logger.error('ProgramManager', buildArtifact.programInfo.shaderSource);
|
|
throw err;
|
|
}
|
|
this.profiler.event('backend', 'GlContext.draw()', () => {
|
|
this.glContext.draw();
|
|
});
|
|
}, this.glContext);
|
|
}
|
|
dispose() {
|
|
if (this.vertexShader) {
|
|
this.glContext.deleteShader(this.vertexShader);
|
|
}
|
|
this.repo.forEach(a => this.glContext.deleteProgram(a.program));
|
|
}
|
|
build(programInfo, inputTextureLayouts, outputTextureLayout) {
|
|
return this.profiler.event('backend', 'ProgramManager.build', () => {
|
|
const preprocessor = new glsl_preprocessor_1.GlslPreprocessor(this.glContext, programInfo, inputTextureLayouts, outputTextureLayout);
|
|
const fragScript = preprocessor.preprocess();
|
|
const program = this.compile(fragScript);
|
|
const artifact = {
|
|
programInfo,
|
|
program,
|
|
uniformLocations: this.getUniformLocations(program, preprocessor.context.programInfo.inputNames, preprocessor.context.programInfo.variables),
|
|
attribLocations: this.getAttribLocations(program)
|
|
};
|
|
return artifact;
|
|
});
|
|
}
|
|
compile(fragShaderScript) {
|
|
if (!this.vertexShader) {
|
|
instrument_1.Logger.verbose('ProrgramManager', 'Compiling and caching Vertex shader for the first time');
|
|
const vertexShaderScript = (0, glsl_source_1.getVertexShaderSource)(this.glContext.version);
|
|
this.vertexShader = this.glContext.compileShader(vertexShaderScript, this.glContext.gl.VERTEX_SHADER);
|
|
}
|
|
if (onnxruntime_common_1.env.debug) {
|
|
instrument_1.Logger.verbose('ProrgramManager', `FragShader:
|
|
${fragShaderScript}
|
|
`);
|
|
}
|
|
const fragShader = this.glContext.compileShader(fragShaderScript, this.glContext.gl.FRAGMENT_SHADER);
|
|
const program = this.glContext.createProgram(this.vertexShader, fragShader);
|
|
this.glContext.deleteShader(fragShader);
|
|
return program;
|
|
}
|
|
bindOutput(td) {
|
|
const width = td.width;
|
|
const height = td.height;
|
|
instrument_1.Logger.verbose('ProrgramManager', `Binding output texture to Framebuffer: w/h=${width}/${height}, shape=${td.shape}, type=${td.tensor.type}`);
|
|
this.glContext.attachFramebuffer(td.texture, width, height);
|
|
}
|
|
bindAttributes(attribLocations) {
|
|
const positionHandle = attribLocations.position;
|
|
const textureCoordHandle = attribLocations.textureCoord;
|
|
this.glContext.setVertexAttributes(positionHandle, textureCoordHandle);
|
|
this.attributesBound = true;
|
|
}
|
|
bindUniforms(uniformLocations, variables, textures) {
|
|
var _a;
|
|
const gl = this.glContext.gl;
|
|
let texturePosition = 0;
|
|
for (const { name, type, location, arrayLength } of uniformLocations) {
|
|
const value = (_a = variables.find(v => v.name === name)) === null || _a === void 0 ? void 0 : _a.data;
|
|
if (type !== 'sampler2D' && !value) {
|
|
throw new Error(`variable '${name}' does not have data defined in program info`);
|
|
}
|
|
switch (type) {
|
|
case 'sampler2D':
|
|
this.bindTexture(textures[texturePosition], location, texturePosition);
|
|
texturePosition++;
|
|
break;
|
|
case 'float':
|
|
if (arrayLength) {
|
|
gl.uniform1fv(location, value);
|
|
}
|
|
else {
|
|
gl.uniform1f(location, value);
|
|
}
|
|
break;
|
|
case 'int':
|
|
if (arrayLength) {
|
|
gl.uniform1iv(location, value);
|
|
}
|
|
else {
|
|
gl.uniform1i(location, value);
|
|
}
|
|
break;
|
|
default:
|
|
throw new Error(`Uniform not implemented: ${type}`);
|
|
}
|
|
}
|
|
}
|
|
bindTexture(td, uniformHandle, position) {
|
|
this.glContext.bindTextureToUniform(td.texture, position, uniformHandle);
|
|
}
|
|
getAttribLocations(program) {
|
|
return {
|
|
position: this.getAttribLocation(program, 'position'),
|
|
textureCoord: this.getAttribLocation(program, 'textureCoord')
|
|
};
|
|
}
|
|
getUniformLocations(program, samplers, variables) {
|
|
const uniformLocations = [];
|
|
if (samplers) {
|
|
for (const sampler of samplers) {
|
|
uniformLocations.push({ name: sampler, type: 'sampler2D', location: this.getUniformLocation(program, sampler) });
|
|
}
|
|
}
|
|
if (variables) {
|
|
for (const variable of variables) {
|
|
uniformLocations.push(Object.assign(Object.assign({}, variable), { location: this.getUniformLocation(program, variable.name) }));
|
|
}
|
|
}
|
|
return uniformLocations;
|
|
}
|
|
getUniformLocation(program, name) {
|
|
const gl = this.glContext.gl;
|
|
const reference = gl.getUniformLocation(program, name);
|
|
if (reference === null) {
|
|
throw new Error(`Uniform ${name} not found.`);
|
|
}
|
|
return reference;
|
|
}
|
|
getAttribLocation(program, name) {
|
|
const gl = this.glContext.gl;
|
|
const attributeLocation = gl.getAttribLocation(program, name);
|
|
return attributeLocation;
|
|
}
|
|
}
|
|
exports.ProgramManager = ProgramManager;
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./lib/onnxjs/backends/webgl/session-handler.ts":
|
|
/*!******************************************************!*\
|
|
!*** ./lib/onnxjs/backends/webgl/session-handler.ts ***!
|
|
\******************************************************/
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
// Licensed under the MIT License.
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.WebGLSessionHandler = void 0;
|
|
const instrument_1 = __webpack_require__(/*! ../../instrument */ "./lib/onnxjs/instrument.ts");
|
|
const opset_1 = __webpack_require__(/*! ../../opset */ "./lib/onnxjs/opset.ts");
|
|
const inference_handler_1 = __webpack_require__(/*! ./inference-handler */ "./lib/onnxjs/backends/webgl/inference-handler.ts");
|
|
const op_resolve_rules_1 = __webpack_require__(/*! ./op-resolve-rules */ "./lib/onnxjs/backends/webgl/op-resolve-rules.ts");
|
|
const program_manager_1 = __webpack_require__(/*! ./program-manager */ "./lib/onnxjs/backends/webgl/program-manager.ts");
|
|
const texture_layout_strategy_1 = __webpack_require__(/*! ./texture-layout-strategy */ "./lib/onnxjs/backends/webgl/texture-layout-strategy.ts");
|
|
const texture_manager_1 = __webpack_require__(/*! ./texture-manager */ "./lib/onnxjs/backends/webgl/texture-manager.ts");
|
|
class WebGLSessionHandler {
|
|
constructor(backend, context) {
|
|
this.backend = backend;
|
|
this.context = context;
|
|
this.layoutStrategy = new texture_layout_strategy_1.PreferLogicalStrategy(backend.glContext.maxTextureSize);
|
|
this.programManager = new program_manager_1.ProgramManager(this.context.profiler, backend.glContext, this.layoutStrategy);
|
|
this.textureManager = new texture_manager_1.TextureManager(backend.glContext, this.layoutStrategy, this.context.profiler, { reuseTextures: backend.textureCacheMode === 'full' });
|
|
this.packedTextureDataCache = new Map();
|
|
this.unpackedTextureDataCache = new Map();
|
|
this.pack = backend.pack;
|
|
this.pack2unpackMap = new Map();
|
|
this.unpack2packMap = new Map();
|
|
}
|
|
createInferenceHandler() {
|
|
return new inference_handler_1.WebGLInferenceHandler(this);
|
|
}
|
|
onGraphInitialized(graph) {
|
|
const initializers = graph.getValues().filter(v => v.from === -1 && v.tensor).map(v => v.tensor.dataId);
|
|
this.initializers = new Set(initializers);
|
|
}
|
|
isInitializer(tensorId) {
|
|
return this.initializers ? this.initializers.has(tensorId) : false;
|
|
}
|
|
addInitializer(tensorId) {
|
|
this.initializers.add(tensorId);
|
|
}
|
|
getTextureData(tensorId, isPacked) {
|
|
if (isPacked) {
|
|
return this.packedTextureDataCache.get(tensorId);
|
|
}
|
|
else {
|
|
return this.unpackedTextureDataCache.get(tensorId);
|
|
}
|
|
}
|
|
setTextureData(tensorId, textureData, isPacked = false) {
|
|
instrument_1.Logger.verbose('WebGLSessionHandler', 'Storing Texture data in cache');
|
|
if (isPacked) {
|
|
this.packedTextureDataCache.set(tensorId, textureData);
|
|
}
|
|
else {
|
|
this.unpackedTextureDataCache.set(tensorId, textureData);
|
|
}
|
|
}
|
|
dispose() {
|
|
this.programManager.dispose();
|
|
this.textureManager.clearActiveTextures();
|
|
this.packedTextureDataCache.forEach(td => this.textureManager.releaseTexture(td, true));
|
|
this.packedTextureDataCache = new Map();
|
|
this.unpackedTextureDataCache.forEach(td => this.textureManager.releaseTexture(td, true));
|
|
this.unpackedTextureDataCache = new Map();
|
|
}
|
|
resolve(node, opsets, graph) {
|
|
const op = (0, opset_1.resolveOperator)(node, opsets, op_resolve_rules_1.WEBGL_OP_RESOLVE_RULES);
|
|
return { impl: op.opImpl, context: op.opInit ? op.opInit(node, graph) : node };
|
|
}
|
|
}
|
|
exports.WebGLSessionHandler = WebGLSessionHandler;
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./lib/onnxjs/backends/webgl/texture-data-encoder.ts":
|
|
/*!***********************************************************!*\
|
|
!*** ./lib/onnxjs/backends/webgl/texture-data-encoder.ts ***!
|
|
\***********************************************************/
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
// Licensed under the MIT License.
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.Uint8DataEncoder = exports.RGBAFloatDataEncoder = exports.RedFloat32DataEncoder = void 0;
|
|
const instrument_1 = __webpack_require__(/*! ../../instrument */ "./lib/onnxjs/instrument.ts");
|
|
/**
|
|
* WebGL2 data encoder
|
|
* Uses R32F as the format for texlet
|
|
*/
|
|
class RedFloat32DataEncoder {
|
|
constructor(gl, channels = 1) {
|
|
if (channels === 1) {
|
|
this.internalFormat = gl.R32F;
|
|
this.format = gl.RED;
|
|
this.textureType = gl.FLOAT;
|
|
this.channelSize = channels;
|
|
}
|
|
else if (channels === 4) {
|
|
this.internalFormat = gl.RGBA32F;
|
|
this.format = gl.RGBA;
|
|
this.textureType = gl.FLOAT;
|
|
this.channelSize = channels;
|
|
}
|
|
else {
|
|
throw new Error(`Invalid number of channels: ${channels}`);
|
|
}
|
|
}
|
|
encode(src, textureSize) {
|
|
let result;
|
|
let source;
|
|
if (src.constructor !== Float32Array) {
|
|
instrument_1.Logger.warning('Encoder', 'data was not of type Float32; creating new Float32Array');
|
|
source = new Float32Array(src);
|
|
}
|
|
if (textureSize * this.channelSize > src.length) {
|
|
instrument_1.Logger.warning('Encoder', 'Source data too small. Allocating larger array');
|
|
source = src;
|
|
result = this.allocate(textureSize * this.channelSize);
|
|
source.forEach((v, i) => result[i] = v);
|
|
}
|
|
else {
|
|
source = src;
|
|
result = source;
|
|
}
|
|
return result;
|
|
}
|
|
allocate(size) {
|
|
return new Float32Array(size * 4);
|
|
}
|
|
decode(buffer, dataSize) {
|
|
if (this.channelSize === 1) {
|
|
const filteredData = buffer.filter((value, index) => index % 4 === 0).subarray(0, dataSize);
|
|
return filteredData;
|
|
}
|
|
return buffer.subarray(0, dataSize);
|
|
}
|
|
}
|
|
exports.RedFloat32DataEncoder = RedFloat32DataEncoder;
|
|
/**
|
|
* Data encoder for WebGL 1 with support for floating point texture
|
|
*/
|
|
class RGBAFloatDataEncoder {
|
|
constructor(gl, channels = 1, textureType) {
|
|
if (channels !== 1 && channels !== 4) {
|
|
throw new Error(`Invalid number of channels: ${channels}`);
|
|
}
|
|
this.internalFormat = gl.RGBA;
|
|
this.format = gl.RGBA;
|
|
this.channelSize = channels;
|
|
this.textureType = textureType || gl.FLOAT;
|
|
}
|
|
encode(src, textureSize) {
|
|
let dest = src;
|
|
if (this.channelSize === 1) {
|
|
instrument_1.Logger.verbose('Encoder', 'Exploding into a larger array');
|
|
dest = this.allocate(textureSize);
|
|
src.forEach((v, i) => dest[i * 4] = v);
|
|
}
|
|
return dest;
|
|
}
|
|
allocate(size) {
|
|
return new Float32Array(size * 4);
|
|
}
|
|
decode(buffer, dataSize) {
|
|
if (this.channelSize === 1) {
|
|
const filteredData = buffer.filter((value, index) => index % 4 === 0).subarray(0, dataSize);
|
|
return filteredData;
|
|
}
|
|
return buffer.subarray(0, dataSize);
|
|
}
|
|
}
|
|
exports.RGBAFloatDataEncoder = RGBAFloatDataEncoder;
|
|
class Uint8DataEncoder {
|
|
constructor(gl, channels = 1) {
|
|
this.channelSize = 4;
|
|
if (channels === 1) {
|
|
this.internalFormat = gl.ALPHA;
|
|
this.format = gl.ALPHA; // not tested
|
|
this.textureType = gl.UNSIGNED_BYTE;
|
|
this.channelSize = channels;
|
|
}
|
|
else if (channels === 4) {
|
|
this.internalFormat = gl.RGBA;
|
|
this.format = gl.RGBA;
|
|
this.textureType = gl.UNSIGNED_BYTE;
|
|
this.channelSize = channels;
|
|
}
|
|
else {
|
|
throw new Error(`Invalid number of channels: ${channels}`);
|
|
}
|
|
}
|
|
encode(src, _textureSize) {
|
|
return new Uint8Array(src.buffer, src.byteOffset, src.byteLength);
|
|
}
|
|
allocate(size) {
|
|
return new Uint8Array(size * this.channelSize);
|
|
}
|
|
decode(buffer, dataSize) {
|
|
if (buffer instanceof Uint8Array) {
|
|
return buffer.subarray(0, dataSize);
|
|
}
|
|
throw new Error(`Invalid array type: ${buffer.constructor}`);
|
|
}
|
|
}
|
|
exports.Uint8DataEncoder = Uint8DataEncoder;
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./lib/onnxjs/backends/webgl/texture-layout-strategy.ts":
|
|
/*!**************************************************************!*\
|
|
!*** ./lib/onnxjs/backends/webgl/texture-layout-strategy.ts ***!
|
|
\**************************************************************/
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
// Licensed under the MIT License.
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.getBatchDim = exports.sizeToSquarishShape = exports.getRowsCols = exports.sizeFromShape = exports.isInt = exports.parseAxisParam = exports.squeezeShape = exports.PreferLogicalStrategy = exports.AlwaysKeepOriginalSizeStrategy = void 0;
|
|
const instrument_1 = __webpack_require__(/*! ../../instrument */ "./lib/onnxjs/instrument.ts");
|
|
const util_1 = __webpack_require__(/*! ../../util */ "./lib/onnxjs/util.ts");
|
|
/**
|
|
* This strategy try to find the minimal max(W,H) that fulfills (W * H == totalSize)
|
|
*/
|
|
class AlwaysKeepOriginalSizeStrategy {
|
|
constructor(maxTextureSize) {
|
|
this.maxTextureSize = maxTextureSize;
|
|
}
|
|
computeTextureWH(shape, prefs) {
|
|
// scalar tensor
|
|
if (shape.length === 0) {
|
|
return [1, 1];
|
|
}
|
|
const maxTextureSize = this.maxTextureSize;
|
|
if (prefs && prefs.breakAxis !== undefined) {
|
|
// check to see if dims fit
|
|
const wsize = prefs.breakAxis >= shape.length ? 1 : shape.slice(prefs.breakAxis).reduce((a, b) => a * b);
|
|
const hsize = prefs.breakAxis <= 0 ? 1 : shape.slice(0, prefs.breakAxis).reduce((a, b) => a * b);
|
|
if (wsize > maxTextureSize || hsize > maxTextureSize) {
|
|
// ignore preferences
|
|
// continue with default layout
|
|
instrument_1.Logger.verbose('TextureLayout', `Given width/height preferences were unattainable: shape:${shape}, breakAxis:${prefs.breakAxis}`);
|
|
}
|
|
else {
|
|
return [wsize, hsize];
|
|
}
|
|
}
|
|
const totalSize = shape.reduce((a, b) => a * b);
|
|
let width = Math.floor(Math.sqrt(totalSize));
|
|
for (; width < maxTextureSize && width < totalSize; width++) {
|
|
if (totalSize % width === 0) {
|
|
break;
|
|
}
|
|
}
|
|
if (width >= maxTextureSize || totalSize % width !== 0) {
|
|
throw new Error(`The given dimensions are outside this GPU's boundaries: ${shape}`);
|
|
}
|
|
return [width, totalSize / width];
|
|
}
|
|
}
|
|
exports.AlwaysKeepOriginalSizeStrategy = AlwaysKeepOriginalSizeStrategy;
|
|
class PreferLogicalStrategy {
|
|
constructor(maxTextureSize) {
|
|
this.maxTextureSize = maxTextureSize;
|
|
}
|
|
computeTextureWH(shape, prefs) {
|
|
const wh = this.computeTexture(shape, prefs);
|
|
if (prefs && prefs.isPacked) {
|
|
wh[0] /= 2;
|
|
wh[1] /= 2;
|
|
}
|
|
if (prefs && prefs.reverseWH) {
|
|
return [wh[1], wh[0]];
|
|
}
|
|
return wh;
|
|
}
|
|
computeTexture(shape, prefs) {
|
|
const isPacked = prefs && prefs.isPacked;
|
|
// scalar tensor
|
|
if (shape.length === 0) {
|
|
return isPacked ? [2, 2] : [1, 1];
|
|
}
|
|
let maxTextureSize = this.maxTextureSize;
|
|
if (prefs && prefs.breakAxis !== undefined) {
|
|
// check to see if dims fit
|
|
const wsize = prefs.breakAxis >= shape.length ? 1 : shape.slice(prefs.breakAxis).reduce((a, b) => a * b);
|
|
const hsize = prefs.breakAxis <= 0 ? 1 : shape.slice(0, prefs.breakAxis).reduce((a, b) => a * b);
|
|
if (wsize > maxTextureSize || hsize > maxTextureSize) {
|
|
// ignore preferences
|
|
// continue with default layout
|
|
instrument_1.Logger.verbose('TextureLayout', `Given width/height preferences were unattainable: shape:${shape}, breakAxis:${prefs.breakAxis}`);
|
|
}
|
|
else {
|
|
return [wsize, hsize];
|
|
}
|
|
}
|
|
let logShape = shape.slice(0);
|
|
if (isPacked) {
|
|
maxTextureSize = maxTextureSize * 2;
|
|
// This logic ensures we accurately count the number of packed texels needed
|
|
// to accommodate the tensor. We can only pack values in the same texel if
|
|
// they are from adjacent pairs of rows/cols within the same batch. So if a
|
|
// tensor has 3 rows, we pretend it has 4 rows in order to account for the
|
|
// fact that the texels containing the third row are half empty.
|
|
logShape = logShape.map((d, i) => i >= logShape.length - 2 ? (logShape[i] % 2 === 0 ? logShape[i] : logShape[i] + 1) : logShape[i]);
|
|
// Packed texture height is at least 2 (the channel height of a single
|
|
// texel).
|
|
if (logShape.length === 1) {
|
|
logShape = [2, logShape[0]];
|
|
}
|
|
}
|
|
// If logical shape is 2, we don't squeeze, since we want to match physical.
|
|
if (logShape.length !== 2) {
|
|
const squeezeResult = squeezeShape(logShape);
|
|
logShape = squeezeResult.newShape;
|
|
}
|
|
const size = sizeFromShape(logShape);
|
|
if (logShape.length <= 1 && size <= maxTextureSize) {
|
|
return [1, size];
|
|
}
|
|
else if (logShape.length === 2 && logShape[0] <= maxTextureSize && logShape[1] <= maxTextureSize) {
|
|
return logShape;
|
|
}
|
|
else if (logShape.length === 3 && logShape[0] * logShape[1] <= maxTextureSize && logShape[2] <= maxTextureSize) {
|
|
return [logShape[0] * logShape[1], logShape[2]];
|
|
}
|
|
else if (logShape.length === 3 && logShape[0] <= maxTextureSize && logShape[1] * logShape[2] <= maxTextureSize) {
|
|
return [logShape[0], logShape[1] * logShape[2]];
|
|
}
|
|
else if (logShape.length === 4 && logShape[0] * logShape[1] * logShape[2] <= maxTextureSize &&
|
|
logShape[3] <= maxTextureSize) {
|
|
return [logShape[0] * logShape[1] * logShape[2], logShape[3]];
|
|
}
|
|
else if (logShape.length === 4 && logShape[0] <= maxTextureSize &&
|
|
logShape[1] * logShape[2] * logShape[3] <= maxTextureSize) {
|
|
return [logShape[0], logShape[1] * logShape[2] * logShape[3]];
|
|
}
|
|
else {
|
|
if (isPacked) {
|
|
// For packed textures size equals the number of channels required to
|
|
// accommodate the texture data. However in order to squarify such that
|
|
// inner dimensions stay even, we rewrite size to equal the number of
|
|
// texels. Then in the return statement we rehydrate the squarified
|
|
// dimensions to channel units.
|
|
return sizeToSquarishShape(size / 4).map(d => d * 2);
|
|
}
|
|
return sizeToSquarishShape(size);
|
|
}
|
|
}
|
|
}
|
|
exports.PreferLogicalStrategy = PreferLogicalStrategy;
|
|
function squeezeShape(shape, axis) {
|
|
const newShape = [];
|
|
const keptDims = [];
|
|
const isEmptyArray = axis != null && Array.isArray(axis) && axis.length === 0;
|
|
const axes = (axis == null || isEmptyArray) ? null : parseAxisParam(axis, shape).sort();
|
|
let j = 0;
|
|
for (let i = 0; i < shape.length; ++i) {
|
|
if (axes != null) {
|
|
if (axes[j] === i && shape[i] !== 1) {
|
|
throw new Error(`Can't squeeze axis ${i} since its dim '${shape[i]}' is not 1`);
|
|
}
|
|
if ((axes[j] == null || axes[j] > i) && shape[i] === 1) {
|
|
newShape.push(shape[i]);
|
|
keptDims.push(i);
|
|
}
|
|
if (axes[j] <= i) {
|
|
j++;
|
|
}
|
|
}
|
|
if (shape[i] !== 1) {
|
|
newShape.push(shape[i]);
|
|
keptDims.push(i);
|
|
}
|
|
}
|
|
return { newShape, keptDims };
|
|
}
|
|
exports.squeezeShape = squeezeShape;
|
|
function parseAxisParam(axis, shape) {
|
|
const rank = shape.length;
|
|
// Normalize input
|
|
axis = axis == null ? shape.map((s, i) => i) : [].concat(axis);
|
|
// Check for valid range
|
|
(0, util_1.assert)(axis.every(ax => ax >= -rank && ax < rank), () => `All values in axis param must be in range [-${rank}, ${rank}) but ` +
|
|
`got axis ${axis}`);
|
|
// Check for only integers
|
|
(0, util_1.assert)(axis.every(isInt), () => 'All values in axis param must be integers but ' +
|
|
`got axis ${axis}`);
|
|
// Handle negative axis.
|
|
return axis.map(a => a < 0 ? rank + a : a);
|
|
}
|
|
exports.parseAxisParam = parseAxisParam;
|
|
function isInt(a) {
|
|
return a % 1 === 0;
|
|
}
|
|
exports.isInt = isInt;
|
|
function sizeFromShape(shape) {
|
|
if (shape.length === 0) {
|
|
// Scalar.
|
|
return 1;
|
|
}
|
|
let size = shape[0];
|
|
for (let i = 1; i < shape.length; i++) {
|
|
size *= shape[i];
|
|
}
|
|
return size;
|
|
}
|
|
exports.sizeFromShape = sizeFromShape;
|
|
function getRowsCols(shape) {
|
|
if (shape.length === 0) {
|
|
throw Error('Cannot get rows and columns of an empty shape array.');
|
|
}
|
|
return [shape.length > 1 ? shape[shape.length - 2] : 1, shape[shape.length - 1]];
|
|
}
|
|
exports.getRowsCols = getRowsCols;
|
|
function sizeToSquarishShape(size) {
|
|
const width = Math.ceil(Math.sqrt(size));
|
|
return [width, Math.ceil(size / width)];
|
|
}
|
|
exports.sizeToSquarishShape = sizeToSquarishShape;
|
|
function getBatchDim(shape, dimsToSkip = 2) {
|
|
return sizeFromShape(shape.slice(0, shape.length - dimsToSkip));
|
|
}
|
|
exports.getBatchDim = getBatchDim;
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./lib/onnxjs/backends/webgl/texture-layout.ts":
|
|
/*!*****************************************************!*\
|
|
!*** ./lib/onnxjs/backends/webgl/texture-layout.ts ***!
|
|
\*****************************************************/
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
// Licensed under the MIT License.
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.createTextureLayoutFromShape = exports.calculateTextureWidthAndHeight = exports.createTextureLayoutFromTextureType = void 0;
|
|
const util_1 = __webpack_require__(/*! ../../util */ "./lib/onnxjs/util.ts");
|
|
const types_1 = __webpack_require__(/*! ./types */ "./lib/onnxjs/backends/webgl/types.ts");
|
|
const createTextureLayoutFromTextureType = (textureLayoutStrategy, shape, textureType) => {
|
|
const channel = (textureType === types_1.TextureType.unpacked || textureType === types_1.TextureType.unpackedReversed) ? 1 : 4;
|
|
const isPacked = textureType === types_1.TextureType.packed;
|
|
const reverseWH = (textureType === types_1.TextureType.unpackedReversed || textureType === types_1.TextureType.packed);
|
|
const breakAxis = textureType === types_1.TextureType.packedLastDimension ? shape.length - 1 : undefined;
|
|
const unpackedShape = textureType === types_1.TextureType.packedLastDimension ?
|
|
shape.map((d, i) => i === shape.length - 1 ? d * 4 : d) :
|
|
undefined;
|
|
return (0, exports.createTextureLayoutFromShape)(textureLayoutStrategy, shape, channel, unpackedShape, { isPacked, reverseWH, breakAxis });
|
|
};
|
|
exports.createTextureLayoutFromTextureType = createTextureLayoutFromTextureType;
|
|
const calculateTextureWidthAndHeight = (textureLayoutStrategy, shape, textureType) => {
|
|
const layout = (0, exports.createTextureLayoutFromTextureType)(textureLayoutStrategy, shape, textureType);
|
|
return [layout.width, layout.height];
|
|
};
|
|
exports.calculateTextureWidthAndHeight = calculateTextureWidthAndHeight;
|
|
/**
|
|
* Create a TextureLayout object from shape.
|
|
*/
|
|
const createTextureLayoutFromShape = (textureLayoutStrategy, shape, channels = 1, unpackedShape, prefs) => {
|
|
const isPacked = !!(prefs && prefs.isPacked);
|
|
const [width, height] = textureLayoutStrategy.computeTextureWH(isPacked ? unpackedShape || shape : shape, prefs);
|
|
const rank = shape.length;
|
|
let inferredDims = shape.slice(0);
|
|
if (rank === 0) {
|
|
inferredDims = [1];
|
|
}
|
|
if (channels === 1) {
|
|
// unpackedShape will take `shape` and not `inferredDims` so as to create a scalar Tensor if need be
|
|
unpackedShape = shape;
|
|
}
|
|
else if (isPacked) {
|
|
if (channels !== 4) {
|
|
throw new Error('a packed texture must be 4-channel');
|
|
}
|
|
unpackedShape = shape;
|
|
if (rank > 0) {
|
|
inferredDims[rank - 1] = Math.ceil(inferredDims[rank - 1] / 2);
|
|
}
|
|
if (rank > 1) {
|
|
inferredDims[rank - 2] = Math.ceil(inferredDims[rank - 2] / 2);
|
|
}
|
|
}
|
|
else if (!unpackedShape) {
|
|
throw new Error('Unpacked shape is needed when using channels > 1');
|
|
}
|
|
return {
|
|
width,
|
|
height,
|
|
channels,
|
|
isPacked,
|
|
shape: inferredDims,
|
|
strides: util_1.ShapeUtil.computeStrides(inferredDims),
|
|
unpackedShape,
|
|
reversedWH: (prefs && prefs.reverseWH)
|
|
};
|
|
};
|
|
exports.createTextureLayoutFromShape = createTextureLayoutFromShape;
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./lib/onnxjs/backends/webgl/texture-manager.ts":
|
|
/*!******************************************************!*\
|
|
!*** ./lib/onnxjs/backends/webgl/texture-manager.ts ***!
|
|
\******************************************************/
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
// Licensed under the MIT License.
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.TextureManager = void 0;
|
|
const instrument_1 = __webpack_require__(/*! ../../instrument */ "./lib/onnxjs/instrument.ts");
|
|
/**
|
|
* TextureManager is the mainly responsible for caching Textures
|
|
* Textures are cached in 2 levels:
|
|
* 1. the texures which are associated with a dataId (from Tensor)
|
|
* Caching these is crucial to performance. These are In-use Textures
|
|
* 2. textures which are not in use by any current ProgramInfo/Tensor
|
|
* These are called Free Textures
|
|
* TextureManager is also used to help creating textures. For this it
|
|
* uses WebGLContext and TextureLayoutStrategy
|
|
*/
|
|
class TextureManager {
|
|
constructor(glContext, layoutStrategy, profiler, config) {
|
|
this.glContext = glContext;
|
|
this.layoutStrategy = layoutStrategy;
|
|
this.profiler = profiler;
|
|
this.config = config;
|
|
this.pendingRead = new Map();
|
|
if (config.reuseTextures) {
|
|
this.inUseTextures = new Map();
|
|
this.idleTextures = new Map();
|
|
this.textureLookup = new Map();
|
|
}
|
|
}
|
|
createTextureFromLayout(dataType, layout, data, usage) {
|
|
const textureDataType = this.toEncoderType(dataType);
|
|
const encoder = this.glContext.getEncoder(textureDataType, layout.channels || 1, usage);
|
|
if (layout.isPacked && usage === 1 /* Encoder.Usage.UploadOnly */) {
|
|
throw new Error('not implemented');
|
|
}
|
|
const width = layout.width;
|
|
const height = layout.height;
|
|
let key;
|
|
let inUseTextures;
|
|
if (this.config.reuseTextures) {
|
|
key = `${width}x${height}_${encoder.format}_${encoder.internalFormat}_${encoder.textureType}`;
|
|
inUseTextures = this.inUseTextures.get(key);
|
|
if (!inUseTextures) {
|
|
inUseTextures = [];
|
|
this.inUseTextures.set(key, inUseTextures);
|
|
}
|
|
const idleTextures = this.idleTextures.get(key);
|
|
if (idleTextures && idleTextures.length > 0) {
|
|
const texture = idleTextures.pop();
|
|
inUseTextures.push(texture);
|
|
if (usage === 1 /* Encoder.Usage.UploadOnly */) {
|
|
this.glContext.updateTexture(texture, width, height, encoder, this.toTextureData(dataType, data));
|
|
}
|
|
return texture;
|
|
}
|
|
}
|
|
instrument_1.Logger.verbose('TextureManager', `Creating new texture of size ${layout.width}x${layout.height}`);
|
|
const texture = this.glContext.allocateTexture(width, height, encoder, this.toTextureData(dataType, data));
|
|
if (this.config.reuseTextures) {
|
|
inUseTextures.push(texture);
|
|
this.textureLookup.set(texture, key);
|
|
}
|
|
return texture;
|
|
}
|
|
readTexture(td, dataType, channels) {
|
|
if (!channels) {
|
|
channels = 1;
|
|
}
|
|
return this.profiler.event('backend', 'TextureManager.readTexture', () => {
|
|
const dataSize = td.shape.reduce((a, b) => a * b) * channels;
|
|
const data = this.glContext.readTexture(td.texture, td.width, td.height, dataSize, this.toEncoderType(dataType), channels);
|
|
return this.toTensorData(dataType, data);
|
|
});
|
|
}
|
|
async readTextureAsync(td, dataType, channels) {
|
|
const dataId = td.tensor.dataId;
|
|
if (!channels) {
|
|
channels = 1;
|
|
}
|
|
if (this.pendingRead.has(dataId)) {
|
|
const subscribers = this.pendingRead.get(dataId);
|
|
return new Promise(resolve => subscribers === null || subscribers === void 0 ? void 0 : subscribers.push(resolve));
|
|
}
|
|
return this.profiler.event('backend', 'TextureManager.readTextureAsync', async () => {
|
|
this.pendingRead.set(dataId, []);
|
|
const dataSize = td.shape.reduce((a, b) => a * b) * channels;
|
|
// add a fence waiting for the data to be ready
|
|
await this.glContext.createAndWaitForFence();
|
|
const data = this.glContext.readTexture(td.texture, td.width, td.height, dataSize, this.toEncoderType(dataType), channels);
|
|
const tensorData = this.toTensorData(dataType, data);
|
|
const subscribers = this.pendingRead.get(dataId);
|
|
this.pendingRead.delete(dataId);
|
|
subscribers === null || subscribers === void 0 ? void 0 : subscribers.forEach(resolve => resolve(tensorData));
|
|
return tensorData;
|
|
});
|
|
}
|
|
readUint8TextureAsFloat(td) {
|
|
return this.profiler.event('backend', 'TextureManager.readUint8TextureAsFloat', () => {
|
|
const dataSize = td.shape.reduce((a, b) => a * b);
|
|
const data = this.glContext.readTexture(td.texture, td.width, td.height, dataSize * 4, 'byte', 4);
|
|
return new Float32Array(data.buffer, data.byteOffset, dataSize);
|
|
});
|
|
}
|
|
releaseTexture(textureData, deleteTexture) {
|
|
let key;
|
|
if (this.config.reuseTextures) {
|
|
key = this.textureLookup.get(textureData.texture);
|
|
if (key) {
|
|
if (deleteTexture) {
|
|
this.textureLookup.delete(key);
|
|
}
|
|
const inUseTextures = this.inUseTextures.get(key);
|
|
if (inUseTextures) {
|
|
const index = inUseTextures.indexOf(textureData.texture);
|
|
if (index !== -1) {
|
|
inUseTextures.splice(index, 1);
|
|
let idleTextures = this.idleTextures.get(key);
|
|
if (!idleTextures) {
|
|
idleTextures = [];
|
|
this.idleTextures.set(key, idleTextures);
|
|
}
|
|
idleTextures.push(textureData.texture);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (!key || deleteTexture) {
|
|
instrument_1.Logger.verbose('TextureManager', `Deleting texture of size ${textureData.width}x${textureData.height}`);
|
|
this.glContext.deleteTexture(textureData.texture);
|
|
}
|
|
}
|
|
toTensorData(dataType, data) {
|
|
switch (dataType) {
|
|
case 'int16':
|
|
return data instanceof Int16Array ? data : Int16Array.from(data);
|
|
case 'int32':
|
|
return data instanceof Int32Array ? data : Int32Array.from(data);
|
|
case 'int8':
|
|
return data instanceof Int8Array ? data : Int8Array.from(data);
|
|
case 'uint16':
|
|
return data instanceof Uint16Array ? data : Uint16Array.from(data);
|
|
case 'uint32':
|
|
return data instanceof Uint32Array ? data : Uint32Array.from(data);
|
|
case 'uint8':
|
|
case 'bool':
|
|
return data instanceof Uint8Array ? data : Uint8Array.from(data);
|
|
case 'float32':
|
|
return data instanceof Float32Array ? data : Float32Array.from(data);
|
|
case 'float64':
|
|
return data instanceof Float64Array ? data : Float64Array.from(data);
|
|
default:
|
|
throw new Error(`TensorData type ${dataType} is not supported`);
|
|
}
|
|
}
|
|
toTextureData(dataType, data) {
|
|
if (!data) {
|
|
return undefined;
|
|
}
|
|
return (data instanceof Float32Array) ? data : new Float32Array(data);
|
|
/*
|
|
switch (dataType) {
|
|
case 'int16':
|
|
case 'int32':
|
|
case 'uint16':
|
|
case 'uint32':
|
|
return (data.constructor === Uint32Array) ? data as Uint32Array : new Uint32Array(data);
|
|
case 'int8':
|
|
case 'uint8':
|
|
case 'bool':
|
|
return (data.constructor === Uint8Array) ? data as Uint8Array : new Uint8Array(data);
|
|
case 'float32':
|
|
case 'float64':
|
|
return (data.constructor === Float32Array) ? data as Float32Array : new Float32Array(data);
|
|
default:
|
|
throw new Error(`TensorData type ${dataType} is not supported`);
|
|
}
|
|
*/
|
|
}
|
|
toEncoderType(_dataType) {
|
|
return 'float';
|
|
// switch (dataType) {
|
|
// case 'int16':
|
|
// case 'int32':
|
|
// case 'uint16':
|
|
// case 'uint32':
|
|
// return 'int';
|
|
// case 'uint8':
|
|
// case 'bool':
|
|
// return 'byte';
|
|
// case 'float32':
|
|
// case 'float64':
|
|
// return 'float';
|
|
// default:
|
|
// throw new Error(`TensorData type ${dataType} is not supported`);
|
|
// }
|
|
}
|
|
clearActiveTextures() {
|
|
this.glContext.clearActiveTextures();
|
|
}
|
|
}
|
|
exports.TextureManager = TextureManager;
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./lib/onnxjs/backends/webgl/types.ts":
|
|
/*!********************************************!*\
|
|
!*** ./lib/onnxjs/backends/webgl/types.ts ***!
|
|
\********************************************/
|
|
/***/ ((__unused_webpack_module, exports) => {
|
|
|
|
"use strict";
|
|
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
// Licensed under the MIT License.
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.TextureType = void 0;
|
|
var TextureType;
|
|
(function (TextureType) {
|
|
TextureType[TextureType["unpacked"] = 0] = "unpacked";
|
|
TextureType[TextureType["unpackedReversed"] = 1] = "unpackedReversed";
|
|
TextureType[TextureType["packed"] = 2] = "packed";
|
|
TextureType[TextureType["downloadUint8AsFloat"] = 3] = "downloadUint8AsFloat";
|
|
TextureType[TextureType["packedLastDimension"] = 4] = "packedLastDimension"; // <-- ONLY used in old ONNX.js Conv implementation for input W (deprecated)
|
|
})(TextureType = exports.TextureType || (exports.TextureType = {}));
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./lib/onnxjs/backends/webgl/utils.ts":
|
|
/*!********************************************!*\
|
|
!*** ./lib/onnxjs/backends/webgl/utils.ts ***!
|
|
\********************************************/
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
// Licensed under the MIT License.
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.getGlChannels = exports.getCoordsDataType = exports.getSqueezedParams = exports.squeezeInputShape = exports.generateShaderFuncNameFromInputSamplerNameAtOutCoords = exports.generateShaderFuncNameFromInputSamplerName = exports.repeatedTry = exports.getPackedShape = void 0;
|
|
const util_1 = __webpack_require__(/*! ../../util */ "./lib/onnxjs/util.ts");
|
|
/**
|
|
* Given a non RGBA shape calculate the R version
|
|
* It is assumed that the dimensions are multiples of given channels
|
|
* NOTE: it is always the last dim that gets packed.
|
|
* @param unpackedShape original shape to create a packed version from
|
|
*/
|
|
function getPackedShape(unpackedShape) {
|
|
const len = unpackedShape.length;
|
|
return unpackedShape.slice(0, len - 1).concat(unpackedShape[len - 1] / 4);
|
|
}
|
|
exports.getPackedShape = getPackedShape;
|
|
async function repeatedTry(checkFn, delayFn = (_counter) => 0, maxCounter) {
|
|
return new Promise((resolve, reject) => {
|
|
let tryCount = 0;
|
|
const tryFn = () => {
|
|
if (checkFn()) {
|
|
resolve();
|
|
return;
|
|
}
|
|
tryCount++;
|
|
const nextBackoff = delayFn(tryCount);
|
|
if (maxCounter != null && tryCount >= maxCounter) {
|
|
reject();
|
|
return;
|
|
}
|
|
setTimeout(tryFn, nextBackoff);
|
|
};
|
|
tryFn();
|
|
});
|
|
}
|
|
exports.repeatedTry = repeatedTry;
|
|
/**
|
|
* Generates the function name from an input sampler name.
|
|
* @param samplerName Name of the sampler.
|
|
*/
|
|
function generateShaderFuncNameFromInputSamplerName(samplerName) {
|
|
(0, util_1.assert)(typeof samplerName !== 'undefined' && samplerName.length !== 0, () => 'empty string found for sampler name');
|
|
return 'get' + samplerName.charAt(0).toUpperCase() + samplerName.slice(1);
|
|
}
|
|
exports.generateShaderFuncNameFromInputSamplerName = generateShaderFuncNameFromInputSamplerName;
|
|
/**
|
|
* Generates the function name from an input sampler name at output coordinates.
|
|
* @param samplerName Name of the sampler.
|
|
*/
|
|
function generateShaderFuncNameFromInputSamplerNameAtOutCoords(samplerName) {
|
|
(0, util_1.assert)(typeof samplerName !== 'undefined' && samplerName.length !== 0, () => 'empty string found for sampler name');
|
|
return 'get' + samplerName.charAt(0).toUpperCase() + samplerName.slice(1) + 'AtOutCoords';
|
|
}
|
|
exports.generateShaderFuncNameFromInputSamplerNameAtOutCoords = generateShaderFuncNameFromInputSamplerNameAtOutCoords;
|
|
/** Returns a new input shape (a copy) that has a squeezed logical shape. */
|
|
function squeezeInputShape(inputShape, squeezedShape) {
|
|
// Deep copy.
|
|
let newInputShape = JSON.parse(JSON.stringify(inputShape));
|
|
newInputShape = squeezedShape;
|
|
return newInputShape;
|
|
}
|
|
exports.squeezeInputShape = squeezeInputShape;
|
|
/** Returns a list of squeezed parameters for shader functions */
|
|
function getSqueezedParams(params, keptDims) {
|
|
return keptDims.map(d => params[d]).join(', ');
|
|
}
|
|
exports.getSqueezedParams = getSqueezedParams;
|
|
/** Returns the data type for different ranks. */
|
|
function getCoordsDataType(rank) {
|
|
if (rank <= 1) {
|
|
return 'int';
|
|
}
|
|
else if (rank === 2) {
|
|
return 'ivec2';
|
|
}
|
|
else if (rank === 3) {
|
|
return 'ivec3';
|
|
}
|
|
else if (rank === 4) {
|
|
return 'ivec4';
|
|
}
|
|
else if (rank === 5) {
|
|
return 'ivec5';
|
|
}
|
|
else if (rank === 6) {
|
|
return 'ivec6';
|
|
}
|
|
else {
|
|
throw Error(`GPU for rank ${rank} is not yet supported`);
|
|
}
|
|
}
|
|
exports.getCoordsDataType = getCoordsDataType;
|
|
function getGlChannels(rank = 6) {
|
|
return ['x', 'y', 'z', 'w', 'u', 'v'].slice(0, rank);
|
|
}
|
|
exports.getGlChannels = getGlChannels;
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./lib/onnxjs/backends/webgl/webgl-context-factory.ts":
|
|
/*!************************************************************!*\
|
|
!*** ./lib/onnxjs/backends/webgl/webgl-context-factory.ts ***!
|
|
\************************************************************/
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
// Licensed under the MIT License.
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.createNewWebGLContext = exports.createWebGLContext = void 0;
|
|
const instrument_1 = __webpack_require__(/*! ../../instrument */ "./lib/onnxjs/instrument.ts");
|
|
const webgl_context_1 = __webpack_require__(/*! ./webgl-context */ "./lib/onnxjs/backends/webgl/webgl-context.ts");
|
|
const cache = {};
|
|
/**
|
|
* This factory function creates proper WebGLRenderingContext based on
|
|
* the current browsers capabilities
|
|
* The order is from higher/most recent versions to most basic
|
|
*/
|
|
function createWebGLContext(contextId) {
|
|
let context;
|
|
if ((!contextId || contextId === 'webgl2') && 'webgl2' in cache) {
|
|
context = cache.webgl2;
|
|
}
|
|
else if ((!contextId || contextId === 'webgl') && 'webgl' in cache) {
|
|
context = cache.webgl;
|
|
}
|
|
context = context || createNewWebGLContext(contextId);
|
|
contextId = contextId || context.version === 1 ? 'webgl' : 'webgl2';
|
|
const gl = context.gl;
|
|
cache[contextId] = context;
|
|
if (gl.isContextLost()) {
|
|
delete cache[contextId];
|
|
return createWebGLContext(contextId);
|
|
}
|
|
gl.disable(gl.DEPTH_TEST);
|
|
gl.disable(gl.STENCIL_TEST);
|
|
gl.disable(gl.BLEND);
|
|
gl.disable(gl.DITHER);
|
|
gl.disable(gl.POLYGON_OFFSET_FILL);
|
|
gl.disable(gl.SAMPLE_COVERAGE);
|
|
gl.enable(gl.SCISSOR_TEST);
|
|
gl.enable(gl.CULL_FACE);
|
|
gl.cullFace(gl.BACK);
|
|
return context;
|
|
}
|
|
exports.createWebGLContext = createWebGLContext;
|
|
function createNewWebGLContext(contextId) {
|
|
const canvas = createCanvas();
|
|
const contextAttributes = {
|
|
alpha: false,
|
|
depth: false,
|
|
antialias: false,
|
|
stencil: false,
|
|
preserveDrawingBuffer: false,
|
|
premultipliedAlpha: false,
|
|
failIfMajorPerformanceCaveat: false
|
|
};
|
|
let gl;
|
|
const ca = contextAttributes;
|
|
if (!contextId || contextId === 'webgl2') {
|
|
gl = canvas.getContext('webgl2', ca);
|
|
if (gl) {
|
|
try {
|
|
return new webgl_context_1.WebGLContext(gl, 2);
|
|
}
|
|
catch (err) {
|
|
instrument_1.Logger.warning('GlContextFactory', `failed to create WebGLContext using contextId 'webgl2'. Error: ${err}`);
|
|
}
|
|
}
|
|
}
|
|
if (!contextId || contextId === 'webgl') {
|
|
gl = canvas.getContext('webgl', ca) || canvas.getContext('experimental-webgl', ca);
|
|
if (gl) {
|
|
try {
|
|
return new webgl_context_1.WebGLContext(gl, 1);
|
|
}
|
|
catch (err) {
|
|
instrument_1.Logger.warning('GlContextFactory', `failed to create WebGLContext using contextId 'webgl' or 'experimental-webgl'. Error: ${err}`);
|
|
}
|
|
}
|
|
}
|
|
throw new Error('WebGL is not supported');
|
|
}
|
|
exports.createNewWebGLContext = createNewWebGLContext;
|
|
function createCanvas() {
|
|
if (typeof document === 'undefined') {
|
|
if (typeof OffscreenCanvas === 'undefined') {
|
|
throw new TypeError('failed to create canvas: OffscreenCanvas is not supported');
|
|
}
|
|
return new OffscreenCanvas(1, 1);
|
|
}
|
|
const canvas = document.createElement('canvas');
|
|
canvas.width = 1;
|
|
canvas.height = 1;
|
|
return canvas;
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./lib/onnxjs/backends/webgl/webgl-context.ts":
|
|
/*!****************************************************!*\
|
|
!*** ./lib/onnxjs/backends/webgl/webgl-context.ts ***!
|
|
\****************************************************/
|
|
/***/ (function(__unused_webpack_module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
// Licensed under the MIT License.
|
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
if (k2 === undefined) k2 = k;
|
|
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
}
|
|
Object.defineProperty(o, k2, desc);
|
|
}) : (function(o, m, k, k2) {
|
|
if (k2 === undefined) k2 = k;
|
|
o[k2] = m[k];
|
|
}));
|
|
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
}) : function(o, v) {
|
|
o["default"] = v;
|
|
});
|
|
var __importStar = (this && this.__importStar) || function (mod) {
|
|
if (mod && mod.__esModule) return mod;
|
|
var result = {};
|
|
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
__setModuleDefault(result, mod);
|
|
return result;
|
|
};
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.WebGLContext = exports.linearSearchLastTrue = void 0;
|
|
const onnxruntime_common_1 = __webpack_require__(/*! onnxruntime-common */ "../common/dist/lib/index.js");
|
|
const DataEncoders = __importStar(__webpack_require__(/*! ./texture-data-encoder */ "./lib/onnxjs/backends/webgl/texture-data-encoder.ts"));
|
|
const utils_1 = __webpack_require__(/*! ./utils */ "./lib/onnxjs/backends/webgl/utils.ts");
|
|
function linearSearchLastTrue(arr) {
|
|
let i = 0;
|
|
for (; i < arr.length; ++i) {
|
|
const isDone = arr[i]();
|
|
if (!isDone) {
|
|
break;
|
|
}
|
|
}
|
|
return i - 1;
|
|
}
|
|
exports.linearSearchLastTrue = linearSearchLastTrue;
|
|
/**
|
|
* Abstraction and wrapper around WebGLRenderingContext and its operations
|
|
*/
|
|
class WebGLContext {
|
|
constructor(gl, version) {
|
|
this.frameBufferBound = false;
|
|
this.itemsToPoll = [];
|
|
this.gl = gl;
|
|
this.version = version;
|
|
this.getExtensions();
|
|
this.vertexbuffer = this.createVertexbuffer();
|
|
this.framebuffer = this.createFramebuffer();
|
|
this.queryVitalParameters();
|
|
}
|
|
allocateTexture(width, height, encoder, data) {
|
|
const gl = this.gl;
|
|
// create the texture
|
|
const texture = gl.createTexture();
|
|
// bind the texture so the following methods effect this texture.
|
|
gl.bindTexture(gl.TEXTURE_2D, texture);
|
|
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
|
|
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
|
|
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
|
|
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
|
|
const buffer = data ? encoder.encode(data, width * height) : null;
|
|
gl.texImage2D(gl.TEXTURE_2D, 0, // Level of detail.
|
|
encoder.internalFormat, width, height, 0, // Always 0 in OpenGL ES.
|
|
encoder.format, encoder.textureType, buffer);
|
|
this.checkError();
|
|
return texture;
|
|
}
|
|
updateTexture(texture, width, height, encoder, data) {
|
|
const gl = this.gl;
|
|
gl.bindTexture(gl.TEXTURE_2D, texture);
|
|
const buffer = encoder.encode(data, width * height);
|
|
gl.texSubImage2D(gl.TEXTURE_2D, 0, // level
|
|
0, // xoffset
|
|
0, // yoffset
|
|
width, height, encoder.format, encoder.textureType, buffer);
|
|
this.checkError();
|
|
}
|
|
attachFramebuffer(texture, width, height) {
|
|
const gl = this.gl;
|
|
// Make it the target for framebuffer operations - including rendering.
|
|
gl.bindTexture(gl.TEXTURE_2D, texture);
|
|
gl.bindFramebuffer(gl.FRAMEBUFFER, this.framebuffer);
|
|
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0); // 0, we aren't using MIPMAPs
|
|
this.checkError();
|
|
gl.viewport(0, 0, width, height);
|
|
gl.scissor(0, 0, width, height);
|
|
}
|
|
readTexture(texture, width, height, dataSize, dataType, channels) {
|
|
const gl = this.gl;
|
|
if (!channels) {
|
|
channels = 1;
|
|
}
|
|
if (!this.frameBufferBound) {
|
|
this.attachFramebuffer(texture, width, height);
|
|
}
|
|
const encoder = this.getEncoder(dataType, channels);
|
|
const buffer = encoder.allocate(width * height);
|
|
// bind texture to framebuffer
|
|
gl.bindTexture(gl.TEXTURE_2D, texture);
|
|
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0); // 0, we aren't using MIPMAPs
|
|
// TODO: Check if framebuffer is ready
|
|
gl.readPixels(0, 0, width, height, gl.RGBA, encoder.textureType, buffer);
|
|
this.checkError();
|
|
// unbind FB
|
|
return encoder.decode(buffer, dataSize);
|
|
}
|
|
isFramebufferReady() {
|
|
// TODO: Implement logic to check if the framebuffer is ready
|
|
return true;
|
|
}
|
|
getActiveTexture() {
|
|
const gl = this.gl;
|
|
const n = gl.getParameter(this.gl.ACTIVE_TEXTURE);
|
|
return `TEXTURE${(n - gl.TEXTURE0)}`;
|
|
}
|
|
getTextureBinding() {
|
|
return this.gl.getParameter(this.gl.TEXTURE_BINDING_2D);
|
|
}
|
|
getFramebufferBinding() {
|
|
return this.gl.getParameter(this.gl.FRAMEBUFFER_BINDING);
|
|
}
|
|
setVertexAttributes(positionHandle, textureCoordHandle) {
|
|
const gl = this.gl;
|
|
gl.vertexAttribPointer(positionHandle, 3, gl.FLOAT, false, 20, 0);
|
|
gl.enableVertexAttribArray(positionHandle);
|
|
if (textureCoordHandle !== -1) {
|
|
gl.vertexAttribPointer(textureCoordHandle, 2, gl.FLOAT, false, 20, 12);
|
|
gl.enableVertexAttribArray(textureCoordHandle);
|
|
}
|
|
this.checkError();
|
|
}
|
|
createProgram(vertexShader, fragShader) {
|
|
const gl = this.gl;
|
|
const program = gl.createProgram();
|
|
// the program consists of our shaders
|
|
gl.attachShader(program, vertexShader);
|
|
gl.attachShader(program, fragShader);
|
|
gl.linkProgram(program);
|
|
return program;
|
|
}
|
|
compileShader(shaderSource, shaderType) {
|
|
const gl = this.gl;
|
|
const shader = gl.createShader(shaderType);
|
|
if (!shader) {
|
|
throw new Error(`createShader() returned null with type ${shaderType}`);
|
|
}
|
|
gl.shaderSource(shader, shaderSource);
|
|
gl.compileShader(shader);
|
|
if (gl.getShaderParameter(shader, gl.COMPILE_STATUS) === false) {
|
|
throw new Error(`Failed to compile shader: ${gl.getShaderInfoLog(shader)}
|
|
Shader source:
|
|
${shaderSource}`);
|
|
}
|
|
return shader;
|
|
}
|
|
deleteShader(shader) {
|
|
this.gl.deleteShader(shader);
|
|
}
|
|
bindTextureToUniform(texture, position, uniformHandle) {
|
|
const gl = this.gl;
|
|
gl.activeTexture(gl.TEXTURE0 + position);
|
|
this.checkError();
|
|
gl.bindTexture(gl.TEXTURE_2D, texture);
|
|
this.checkError();
|
|
gl.uniform1i(uniformHandle, position);
|
|
this.checkError();
|
|
}
|
|
draw() {
|
|
this.gl.drawArrays(this.gl.TRIANGLE_STRIP, 0, 4);
|
|
this.checkError();
|
|
}
|
|
checkError() {
|
|
if (onnxruntime_common_1.env.debug) {
|
|
const gl = this.gl;
|
|
const error = gl.getError();
|
|
let label = '';
|
|
switch (error) {
|
|
case (gl.NO_ERROR):
|
|
return;
|
|
case (gl.INVALID_ENUM):
|
|
label = 'INVALID_ENUM';
|
|
break;
|
|
case (gl.INVALID_VALUE):
|
|
label = 'INVALID_VALUE';
|
|
break;
|
|
case (gl.INVALID_OPERATION):
|
|
label = 'INVALID_OPERATION';
|
|
break;
|
|
case (gl.INVALID_FRAMEBUFFER_OPERATION):
|
|
label = 'INVALID_FRAMEBUFFER_OPERATION';
|
|
break;
|
|
case (gl.OUT_OF_MEMORY):
|
|
label = 'OUT_OF_MEMORY';
|
|
break;
|
|
case (gl.CONTEXT_LOST_WEBGL):
|
|
label = 'CONTEXT_LOST_WEBGL';
|
|
break;
|
|
default:
|
|
label = `Unknown WebGL Error: ${error.toString(16)}`;
|
|
}
|
|
throw new Error(label);
|
|
}
|
|
}
|
|
deleteTexture(texture) {
|
|
this.gl.deleteTexture(texture);
|
|
}
|
|
deleteProgram(program) {
|
|
this.gl.deleteProgram(program);
|
|
}
|
|
getEncoder(dataType, channels, usage = 0 /* Encoder.Usage.Default */) {
|
|
if (this.version === 2) {
|
|
return new DataEncoders.RedFloat32DataEncoder(this.gl, channels);
|
|
}
|
|
switch (dataType) {
|
|
case 'float':
|
|
if (usage === 1 /* Encoder.Usage.UploadOnly */ || this.isRenderFloat32Supported) {
|
|
return new DataEncoders.RGBAFloatDataEncoder(this.gl, channels);
|
|
}
|
|
else {
|
|
return new DataEncoders.RGBAFloatDataEncoder(this.gl, channels, this.textureHalfFloatExtension.HALF_FLOAT_OES);
|
|
}
|
|
case 'int':
|
|
throw new Error('not implemented');
|
|
case 'byte':
|
|
return new DataEncoders.Uint8DataEncoder(this.gl, channels);
|
|
default:
|
|
throw new Error(`Invalid dataType: ${dataType}`);
|
|
}
|
|
}
|
|
clearActiveTextures() {
|
|
const gl = this.gl;
|
|
for (let unit = 0; unit < this.maxTextureImageUnits; ++unit) {
|
|
gl.activeTexture(gl.TEXTURE0 + unit);
|
|
gl.bindTexture(gl.TEXTURE_2D, null);
|
|
}
|
|
}
|
|
dispose() {
|
|
if (this.disposed) {
|
|
return;
|
|
}
|
|
const gl = this.gl;
|
|
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
|
|
gl.deleteFramebuffer(this.framebuffer);
|
|
gl.bindBuffer(gl.ARRAY_BUFFER, null);
|
|
gl.deleteBuffer(this.vertexbuffer);
|
|
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);
|
|
gl.finish();
|
|
this.disposed = true;
|
|
}
|
|
createDefaultGeometry() {
|
|
// Sets of x,y,z(=0),s,t coordinates.
|
|
return new Float32Array([
|
|
-1.0, 1.0, 0.0, 0.0, 1.0,
|
|
-1.0, -1.0, 0.0, 0.0, 0.0,
|
|
1.0, 1.0, 0.0, 1.0, 1.0,
|
|
1.0, -1.0, 0.0, 1.0, 0.0 // lower right
|
|
]);
|
|
}
|
|
createVertexbuffer() {
|
|
const gl = this.gl;
|
|
const buffer = gl.createBuffer();
|
|
if (!buffer) {
|
|
throw new Error('createBuffer() returned null');
|
|
}
|
|
const geometry = this.createDefaultGeometry();
|
|
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
|
|
gl.bufferData(gl.ARRAY_BUFFER, geometry, gl.STATIC_DRAW);
|
|
this.checkError();
|
|
return buffer;
|
|
}
|
|
createFramebuffer() {
|
|
const fb = this.gl.createFramebuffer();
|
|
if (!fb) {
|
|
throw new Error('createFramebuffer returned null');
|
|
}
|
|
return fb;
|
|
}
|
|
queryVitalParameters() {
|
|
const gl = this.gl;
|
|
this.isFloatTextureAttachableToFrameBuffer = this.checkFloatTextureAttachableToFrameBuffer();
|
|
this.isRenderFloat32Supported = this.checkRenderFloat32();
|
|
this.isFloat32DownloadSupported = this.checkFloat32Download();
|
|
if (this.version === 1 && !this.textureHalfFloatExtension && !this.isRenderFloat32Supported) {
|
|
throw new Error('both float32 and float16 TextureType are not supported');
|
|
}
|
|
this.isBlendSupported = !this.isRenderFloat32Supported || this.checkFloat32Blend();
|
|
// this.maxCombinedTextureImageUnits = gl.getParameter(gl.MAX_COMBINED_TEXTURE_IMAGE_UNITS);
|
|
this.maxTextureSize = gl.getParameter(gl.MAX_TEXTURE_SIZE);
|
|
this.maxTextureImageUnits = gl.getParameter(gl.MAX_TEXTURE_IMAGE_UNITS);
|
|
// this.maxCubeMapTextureSize = gl.getParameter(gl.MAX_CUBE_MAP_TEXTURE_SIZE);
|
|
// this.shadingLanguageVersion = gl.getParameter(gl.SHADING_LANGUAGE_VERSION);
|
|
// this.webglVendor = gl.getParameter(gl.VENDOR);
|
|
// this.webglVersion = gl.getParameter(gl.VERSION);
|
|
if (this.version === 2) {
|
|
// this.max3DTextureSize = gl.getParameter(WebGL2RenderingContext.MAX_3D_TEXTURE_SIZE);
|
|
// this.maxArrayTextureLayers = gl.getParameter(WebGL2RenderingContext.MAX_ARRAY_TEXTURE_LAYERS);
|
|
// this.maxColorAttachments = gl.getParameter(WebGL2RenderingContext.MAX_COLOR_ATTACHMENTS);
|
|
// this.maxDrawBuffers = gl.getParameter(WebGL2RenderingContext.MAX_DRAW_BUFFERS);
|
|
}
|
|
}
|
|
getExtensions() {
|
|
if (this.version === 2) {
|
|
this.colorBufferFloatExtension = this.gl.getExtension('EXT_color_buffer_float');
|
|
this.disjointTimerQueryWebgl2Extension = this.gl.getExtension('EXT_disjoint_timer_query_webgl2');
|
|
}
|
|
else {
|
|
this.textureFloatExtension = this.gl.getExtension('OES_texture_float');
|
|
this.textureHalfFloatExtension = this.gl.getExtension('OES_texture_half_float');
|
|
}
|
|
}
|
|
checkFloatTextureAttachableToFrameBuffer() {
|
|
// test whether Float32 texture is supported:
|
|
// STEP.1 create a float texture
|
|
const gl = this.gl;
|
|
const texture = gl.createTexture();
|
|
gl.bindTexture(gl.TEXTURE_2D, texture);
|
|
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
const internalFormat = this.version === 2 ? gl.RGBA32F : gl.RGBA;
|
|
gl.texImage2D(gl.TEXTURE_2D, 0, internalFormat, 1, 1, 0, gl.RGBA, gl.FLOAT, null);
|
|
// STEP.2 bind a frame buffer
|
|
const frameBuffer = gl.createFramebuffer();
|
|
gl.bindFramebuffer(gl.FRAMEBUFFER, frameBuffer);
|
|
// STEP.3 attach texture to framebuffer
|
|
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0);
|
|
// STEP.4 test whether framebuffer is complete
|
|
const isComplete = gl.checkFramebufferStatus(gl.FRAMEBUFFER) === gl.FRAMEBUFFER_COMPLETE;
|
|
gl.bindTexture(gl.TEXTURE_2D, null);
|
|
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
|
|
gl.deleteTexture(texture);
|
|
gl.deleteFramebuffer(frameBuffer);
|
|
return isComplete;
|
|
}
|
|
checkRenderFloat32() {
|
|
if (this.version === 2) {
|
|
if (!this.colorBufferFloatExtension) {
|
|
return false;
|
|
}
|
|
}
|
|
else {
|
|
if (!this.textureFloatExtension) {
|
|
return false;
|
|
}
|
|
}
|
|
return this.isFloatTextureAttachableToFrameBuffer;
|
|
}
|
|
checkFloat32Download() {
|
|
if (this.version === 2) {
|
|
if (!this.colorBufferFloatExtension) {
|
|
return false;
|
|
}
|
|
}
|
|
else {
|
|
if (!this.textureFloatExtension) {
|
|
return false;
|
|
}
|
|
if (!this.gl.getExtension('WEBGL_color_buffer_float')) {
|
|
return false;
|
|
}
|
|
}
|
|
return this.isFloatTextureAttachableToFrameBuffer;
|
|
}
|
|
/**
|
|
* Check whether GL_BLEND is supported
|
|
*/
|
|
checkFloat32Blend() {
|
|
// it looks like currently (2019-05-08) there is no easy way to detect whether BLEND is supported
|
|
// https://github.com/microsoft/onnxjs/issues/145
|
|
const gl = this.gl;
|
|
let texture;
|
|
let frameBuffer;
|
|
let vertexShader;
|
|
let fragmentShader;
|
|
let program;
|
|
try {
|
|
texture = gl.createTexture();
|
|
frameBuffer = gl.createFramebuffer();
|
|
gl.bindTexture(gl.TEXTURE_2D, texture);
|
|
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
const internalFormat = this.version === 2 ? gl.RGBA32F : gl.RGBA;
|
|
gl.texImage2D(gl.TEXTURE_2D, 0, internalFormat, 1, 1, 0, gl.RGBA, gl.FLOAT, null);
|
|
gl.bindFramebuffer(gl.FRAMEBUFFER, frameBuffer);
|
|
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0);
|
|
gl.enable(gl.BLEND);
|
|
vertexShader = gl.createShader(gl.VERTEX_SHADER);
|
|
if (!vertexShader) {
|
|
return false;
|
|
}
|
|
gl.shaderSource(vertexShader, 'void main(){}');
|
|
gl.compileShader(vertexShader);
|
|
fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
|
|
if (!fragmentShader) {
|
|
return false;
|
|
}
|
|
gl.shaderSource(fragmentShader, 'precision highp float;void main(){gl_FragColor=vec4(0.5);}');
|
|
gl.compileShader(fragmentShader);
|
|
program = gl.createProgram();
|
|
if (!program) {
|
|
return false;
|
|
}
|
|
gl.attachShader(program, vertexShader);
|
|
gl.attachShader(program, fragmentShader);
|
|
gl.linkProgram(program);
|
|
gl.useProgram(program);
|
|
gl.drawArrays(gl.POINTS, 0, 1);
|
|
return gl.getError() === gl.NO_ERROR;
|
|
}
|
|
finally {
|
|
gl.disable(gl.BLEND);
|
|
if (program) {
|
|
gl.deleteProgram(program);
|
|
}
|
|
if (vertexShader) {
|
|
gl.deleteShader(vertexShader);
|
|
}
|
|
if (fragmentShader) {
|
|
gl.deleteShader(fragmentShader);
|
|
}
|
|
if (frameBuffer) {
|
|
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
|
|
gl.deleteFramebuffer(frameBuffer);
|
|
}
|
|
if (texture) {
|
|
gl.bindTexture(gl.TEXTURE_2D, null);
|
|
gl.deleteTexture(texture);
|
|
}
|
|
}
|
|
}
|
|
beginTimer() {
|
|
if (this.version === 2 && this.disjointTimerQueryWebgl2Extension) {
|
|
const gl2 = this.gl;
|
|
const ext = this.disjointTimerQueryWebgl2Extension;
|
|
const query = gl2.createQuery();
|
|
gl2.beginQuery(ext.TIME_ELAPSED_EXT, query);
|
|
return query;
|
|
}
|
|
else {
|
|
// TODO: add webgl 1 handling.
|
|
throw new Error('WebGL1 profiling currently not supported.');
|
|
}
|
|
}
|
|
endTimer() {
|
|
if (this.version === 2 && this.disjointTimerQueryWebgl2Extension) {
|
|
const gl2 = this.gl;
|
|
const ext = this.disjointTimerQueryWebgl2Extension;
|
|
gl2.endQuery(ext.TIME_ELAPSED_EXT);
|
|
return;
|
|
}
|
|
else {
|
|
// TODO: add webgl 1 handling.
|
|
throw new Error('WebGL1 profiling currently not supported');
|
|
}
|
|
}
|
|
isTimerResultAvailable(query) {
|
|
let available = false, disjoint = false;
|
|
if (this.version === 2 && this.disjointTimerQueryWebgl2Extension) {
|
|
const gl2 = this.gl;
|
|
const ext = this.disjointTimerQueryWebgl2Extension;
|
|
available = gl2.getQueryParameter(query, gl2.QUERY_RESULT_AVAILABLE);
|
|
disjoint = gl2.getParameter(ext.GPU_DISJOINT_EXT);
|
|
}
|
|
else {
|
|
// TODO: add webgl 1 handling.
|
|
throw new Error('WebGL1 profiling currently not supported');
|
|
}
|
|
return available && !disjoint;
|
|
}
|
|
getTimerResult(query) {
|
|
let timeElapsed = 0;
|
|
if (this.version === 2) {
|
|
const gl2 = this.gl;
|
|
timeElapsed = gl2.getQueryParameter(query, gl2.QUERY_RESULT);
|
|
gl2.deleteQuery(query);
|
|
}
|
|
else {
|
|
// TODO: add webgl 1 handling.
|
|
throw new Error('WebGL1 profiling currently not supported');
|
|
}
|
|
// return miliseconds
|
|
return timeElapsed / 1000000;
|
|
}
|
|
async waitForQueryAndGetTime(query) {
|
|
await (0, utils_1.repeatedTry)(() => this.isTimerResultAvailable(query));
|
|
return this.getTimerResult(query);
|
|
}
|
|
async createAndWaitForFence() {
|
|
const fenceContext = this.createFence(this.gl);
|
|
return this.pollFence(fenceContext);
|
|
}
|
|
createFence(gl) {
|
|
let isFencePassed;
|
|
const gl2 = gl;
|
|
const query = gl2.fenceSync(gl2.SYNC_GPU_COMMANDS_COMPLETE, 0);
|
|
gl.flush();
|
|
if (query === null) {
|
|
isFencePassed = () => true;
|
|
}
|
|
else {
|
|
isFencePassed = () => {
|
|
const status = gl2.clientWaitSync(query, 0, 0);
|
|
return status === gl2.ALREADY_SIGNALED || status === gl2.CONDITION_SATISFIED;
|
|
};
|
|
}
|
|
return { query, isFencePassed };
|
|
}
|
|
async pollFence(fenceContext) {
|
|
return new Promise(resolve => {
|
|
void this.addItemToPoll(() => fenceContext.isFencePassed(), () => resolve());
|
|
});
|
|
}
|
|
pollItems() {
|
|
// Find the last query that has finished.
|
|
const index = linearSearchLastTrue(this.itemsToPoll.map(x => x.isDoneFn));
|
|
for (let i = 0; i <= index; ++i) {
|
|
const { resolveFn } = this.itemsToPoll[i];
|
|
resolveFn();
|
|
}
|
|
this.itemsToPoll = this.itemsToPoll.slice(index + 1);
|
|
}
|
|
async addItemToPoll(isDoneFn, resolveFn) {
|
|
this.itemsToPoll.push({ isDoneFn, resolveFn });
|
|
if (this.itemsToPoll.length > 1) {
|
|
// We already have a running loop that polls.
|
|
return;
|
|
}
|
|
// Start a new loop that polls.
|
|
await (0, utils_1.repeatedTry)(() => {
|
|
this.pollItems();
|
|
// End the loop if no more items to poll.
|
|
return this.itemsToPoll.length === 0;
|
|
});
|
|
}
|
|
}
|
|
exports.WebGLContext = WebGLContext;
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./lib/onnxjs/execution-plan.ts":
|
|
/*!**************************************!*\
|
|
!*** ./lib/onnxjs/execution-plan.ts ***!
|
|
\**************************************/
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
// Licensed under the MIT License.
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.ExecutionPlan = void 0;
|
|
const instrument_1 = __webpack_require__(/*! ./instrument */ "./lib/onnxjs/instrument.ts");
|
|
class KernelOp {
|
|
constructor(op, node) {
|
|
this.op = op;
|
|
this.node = node;
|
|
}
|
|
}
|
|
class ExecutionPlan {
|
|
constructor(graph, ops, profiler) {
|
|
this.graph = graph;
|
|
this.profiler = profiler;
|
|
this.initialize(ops);
|
|
}
|
|
initialize(ops) {
|
|
this.profiler.event('session', 'ExecutionPlan.initialize', () => {
|
|
const graphNodes = this.graph.getNodes();
|
|
if (graphNodes.length !== ops.length) {
|
|
throw new Error('The size of nodes and OPs do not match.');
|
|
}
|
|
this._ops = ops.map((op, i) => new KernelOp(op, graphNodes[i]));
|
|
this.reset();
|
|
// look for starter node(s)
|
|
this._starter = [];
|
|
this._ops.forEach((op, i) => {
|
|
let resolved = true;
|
|
for (const input of op.node.inputs) {
|
|
if (!this._values[input] // not an initialized input
|
|
&& this.graph.getInputIndices().indexOf(input) === -1 // not model input
|
|
) {
|
|
resolved = false;
|
|
break;
|
|
}
|
|
}
|
|
if (resolved) {
|
|
this._starter.push(i);
|
|
}
|
|
});
|
|
});
|
|
}
|
|
reset() {
|
|
this._values = this.graph.getValues().map(i => i.tensor);
|
|
}
|
|
async execute(sessionHandler, modelInputs) {
|
|
return this.profiler.event('session', 'ExecutionPlan.execute', async () => {
|
|
// reset mediem result
|
|
this.reset();
|
|
// create inference handler
|
|
const inferenceHandler = sessionHandler.createInferenceHandler();
|
|
// populate inputs value
|
|
const graphInputs = this.graph.getInputIndices();
|
|
if (modelInputs.length !== graphInputs.length) {
|
|
throw new Error(`number of input tensors don't match the number of inputs to the model: actual: ${modelInputs.length} expected: ${graphInputs.length}`);
|
|
}
|
|
modelInputs.forEach((input, i) => {
|
|
const index = graphInputs[i];
|
|
this._values[index] = input;
|
|
});
|
|
// prepare running sequence
|
|
const sequence = this._starter.slice(0);
|
|
// execution iterations
|
|
const graphValues = this.graph.getValues();
|
|
const graphNodes = this.graph.getNodes();
|
|
let rear = 0;
|
|
while (rear < sequence.length) {
|
|
const thisOpIndex = sequence[rear++];
|
|
const thisOp = this._ops[thisOpIndex];
|
|
// check input
|
|
const inputList = thisOp.node.inputs.map(i => this._values[i]);
|
|
if (inputList.indexOf(undefined) !== -1) {
|
|
throw new Error(`unresolved input detected: op: ${thisOp.node}`);
|
|
}
|
|
// run
|
|
const inputTensors = inputList;
|
|
instrument_1.Logger.verbose('ExecPlan', `Runing op:${thisOp.node.name} (${inputTensors.map((t, i) => `'${thisOp.node.inputs[i]}': ${t.type}[${t.dims.join(',')}]`).join(', ')})`);
|
|
const outputList = await this.profiler.event('node', thisOp.node.name, async () => thisOp.op.impl(inferenceHandler, inputTensors, thisOp.op.context));
|
|
// check output
|
|
if (outputList.length !== thisOp.node.outputs.length) {
|
|
throw new Error('the size of output does not match model definition.');
|
|
}
|
|
// fill value
|
|
outputList.forEach((output, i) => {
|
|
const j = thisOp.node.outputs[i];
|
|
if (this._values[j]) {
|
|
throw new Error(`output [${j}] already has value: op:${thisOp.node.name}`);
|
|
}
|
|
this._values[j] = output;
|
|
});
|
|
// resolve downstream nodes
|
|
const downstreamNodes = new Set();
|
|
outputList.forEach((output, i) => {
|
|
const j = thisOp.node.outputs[i];
|
|
for (const currentDownstreamNodeIndex of graphValues[j].to) {
|
|
const currentDownstreamNode = graphNodes[currentDownstreamNodeIndex];
|
|
let resolved = true;
|
|
for (const k of currentDownstreamNode.inputs) {
|
|
if (!this._values[k]) {
|
|
resolved = false;
|
|
break;
|
|
}
|
|
}
|
|
if (resolved) {
|
|
downstreamNodes.add(currentDownstreamNodeIndex);
|
|
}
|
|
}
|
|
});
|
|
sequence.push(...downstreamNodes);
|
|
}
|
|
const output = [];
|
|
for (let i = 0; i < this.graph.getOutputIndices().length; i++) {
|
|
const outputIndex = this.graph.getOutputIndices()[i];
|
|
const outputTensor = this._values[outputIndex];
|
|
if (outputTensor === undefined) {
|
|
throw new Error(`required output [${outputIndex}] does not have value`);
|
|
}
|
|
if (outputIndex === 0) {
|
|
await outputTensor.getData();
|
|
}
|
|
else {
|
|
// eslint-disable-next-line no-unused-expressions
|
|
outputTensor.data;
|
|
}
|
|
output.push(outputTensor);
|
|
}
|
|
instrument_1.Logger.verbose('ExecPlan', 'disposing of inferenceHandler');
|
|
inferenceHandler.dispose();
|
|
return output;
|
|
});
|
|
}
|
|
}
|
|
exports.ExecutionPlan = ExecutionPlan;
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./lib/onnxjs/graph.ts":
|
|
/*!*****************************!*\
|
|
!*** ./lib/onnxjs/graph.ts ***!
|
|
\*****************************/
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
// Licensed under the MIT License.
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.Graph = void 0;
|
|
const onnx_proto_1 = __webpack_require__(/*! onnx-proto */ "./node_modules/onnx-proto/dist/onnx.js");
|
|
const attribute_1 = __webpack_require__(/*! ./attribute */ "./lib/onnxjs/attribute.ts");
|
|
const ort_generated_1 = __webpack_require__(/*! ./ort-schema/ort-generated */ "./lib/onnxjs/ort-schema/ort-generated.ts");
|
|
const tensor_1 = __webpack_require__(/*! ./tensor */ "./lib/onnxjs/tensor.ts");
|
|
const util_1 = __webpack_require__(/*! ./util */ "./lib/onnxjs/util.ts");
|
|
var ortFbs = ort_generated_1.onnxruntime.experimental.fbs;
|
|
// eslint-disable-next-line @typescript-eslint/naming-convention, @typescript-eslint/no-redeclare
|
|
exports.Graph = {
|
|
/**
|
|
* construct a graph from a graph protobuf type
|
|
*/
|
|
from: (graphProto, initializer) => new GraphImpl(graphProto, initializer),
|
|
};
|
|
class Value {
|
|
constructor(valueInfo) {
|
|
this._from = undefined;
|
|
this._to = [];
|
|
this.tensor = undefined;
|
|
this.type = undefined;
|
|
if (valueInfo) {
|
|
this.type = util_1.ProtoUtil.tensorValueTypeFromProto(valueInfo.type.tensorType);
|
|
}
|
|
}
|
|
get from() {
|
|
return this._from;
|
|
}
|
|
get to() {
|
|
return this._to;
|
|
}
|
|
}
|
|
class Node {
|
|
constructor(_nodeProto, name) {
|
|
if (_nodeProto instanceof onnx_proto_1.onnx.NodeProto) {
|
|
this.name = _nodeProto.name;
|
|
this.opType = _nodeProto.opType;
|
|
this.attributes = new attribute_1.Attribute(_nodeProto.attribute);
|
|
}
|
|
else if (_nodeProto instanceof ortFbs.Node) {
|
|
this.name = name !== null && name !== void 0 ? name : _nodeProto.name();
|
|
this.opType = _nodeProto.opType();
|
|
this.attributes = new attribute_1.Attribute(util_1.ProtoUtil.tensorAttributesFromORTFormat(_nodeProto));
|
|
}
|
|
this.inputs = [];
|
|
this.outputs = [];
|
|
this.executeNode = true;
|
|
}
|
|
}
|
|
class GraphImpl {
|
|
constructor(graph, graphInitializer) {
|
|
if (!graph) {
|
|
throw new TypeError('graph is empty');
|
|
}
|
|
// build the graph - will throw exceptions if something fatal is detected
|
|
this.buildGraph(graph);
|
|
// execute any transformation logic for the graph (if applicable)
|
|
this.transformGraph(graphInitializer);
|
|
// check for cycles and other inconsistencies - will throw exceptions if something fatal is detected
|
|
this.checkIsAcyclic();
|
|
}
|
|
getInputIndices() {
|
|
return this._allInputIndices;
|
|
}
|
|
getInputNames() {
|
|
return this._allInputNames;
|
|
}
|
|
getOutputIndices() {
|
|
return this._allOutputIndices;
|
|
}
|
|
getOutputNames() {
|
|
return this._allOutputNames;
|
|
}
|
|
getValues() {
|
|
return this._allData;
|
|
}
|
|
getNodes() {
|
|
return this._nodes;
|
|
}
|
|
buildGraph(graph) {
|
|
// build the graph - will throw exceptions if something fatal is detected
|
|
if (graph instanceof onnx_proto_1.onnx.GraphProto) {
|
|
this.buildGraphFromOnnxFormat(graph);
|
|
}
|
|
else if (graph instanceof ortFbs.Graph) {
|
|
this.buildGraphFromOrtFormat(graph);
|
|
}
|
|
else {
|
|
throw new TypeError('Graph type is not supported.');
|
|
}
|
|
}
|
|
buildGraphFromOnnxFormat(graph) {
|
|
const dataIndices = new Map();
|
|
this._allData = [];
|
|
this._allInputIndices = [];
|
|
this._allInputNames = [];
|
|
this._allOutputIndices = [];
|
|
this._allOutputNames = [];
|
|
this._nodes = [];
|
|
const nodesIndices = new Map();
|
|
// scan all inputs
|
|
if (!graph.input) {
|
|
throw new Error('missing information in graph: input');
|
|
}
|
|
const inputValueNames = [];
|
|
for (const i of graph.input) {
|
|
if (dataIndices.has(i.name)) {
|
|
throw new Error(`duplicated input name: ${i.name}`);
|
|
}
|
|
const currentIndex = this._allData.push(new Value(i)) - 1;
|
|
dataIndices.set(i.name, currentIndex);
|
|
inputValueNames.push(i.name);
|
|
}
|
|
// scan all initializers
|
|
if (!graph.initializer) {
|
|
throw new Error('missing information in graph: initializer');
|
|
}
|
|
for (const i of graph.initializer) {
|
|
let index = dataIndices.get(i.name);
|
|
if (index === undefined) {
|
|
const value = new Value();
|
|
value.type = {
|
|
shape: { dims: util_1.ProtoUtil.tensorDimsFromProto(i.dims) },
|
|
tensorType: util_1.ProtoUtil.tensorDataTypeFromProto(i.dataType)
|
|
};
|
|
index = this._allData.push(value) - 1;
|
|
dataIndices.set(i.name, index);
|
|
}
|
|
this._allData[index]._from = -1;
|
|
this._allData[index].tensor = tensor_1.Tensor.fromProto(i);
|
|
}
|
|
// filter out input indices
|
|
for (let i = 0; i < this._allData.length; i++) {
|
|
if (!this._allData[i].tensor) {
|
|
this._allInputIndices.push(i);
|
|
this._allInputNames.push(inputValueNames[i]);
|
|
}
|
|
}
|
|
// scan all outputs
|
|
if (!graph.output) {
|
|
throw new Error('missing information in graph: output');
|
|
}
|
|
for (const i of graph.output) {
|
|
if (dataIndices.has(i.name)) {
|
|
throw new Error(`duplicated output name: ${i.name}`);
|
|
}
|
|
const currentIndex = this._allData.push(new Value(i)) - 1;
|
|
dataIndices.set(i.name, currentIndex);
|
|
this._allOutputIndices.push(currentIndex);
|
|
this._allOutputNames.push(i.name);
|
|
}
|
|
// scan all nodes
|
|
if (!graph.node) {
|
|
throw new Error('missing information in graph: node');
|
|
}
|
|
for (const nodeProto of graph.node) {
|
|
if (!nodeProto.name) {
|
|
// assign a name to the node if it doesn't have one
|
|
for (let pick = 0;; pick++) {
|
|
const name = `unnamed_${nodeProto.opType}_${pick}`;
|
|
if (!nodesIndices.has(name)) {
|
|
nodeProto.name = name;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (nodesIndices.has(nodeProto.name)) {
|
|
throw new Error(`duplicated node name: ${nodeProto.name}`);
|
|
}
|
|
const currentIndex = this._nodes.push(new Node(nodeProto)) - 1;
|
|
nodesIndices.set(nodeProto.name, currentIndex);
|
|
}
|
|
// scan node's outputs
|
|
for (let i = 0; i < this._nodes.length; i++) {
|
|
const node = this._nodes[i];
|
|
const nodeProto = graph.node[i];
|
|
if (!nodeProto.output) {
|
|
throw new Error(`missing output for node: ${nodeProto.name}`);
|
|
}
|
|
for (const output of nodeProto.output) {
|
|
let dataIndex = dataIndices.get(output);
|
|
if (typeof dataIndex === 'undefined') {
|
|
dataIndex = this._allData.push(new Value()) - 1;
|
|
dataIndices.set(output, dataIndex);
|
|
}
|
|
node.outputs.push(dataIndex);
|
|
if (this._allData[dataIndex]._from !== undefined) {
|
|
throw new Error(`multiple nodes output to one data value: ${dataIndex}`);
|
|
}
|
|
this._allData[dataIndex]._from = i;
|
|
// for the 'Constant' operator, just create a new edge in the graph corresponding to the 'output' of the
|
|
// operator and ignore the node from the graph
|
|
if (nodeProto.opType === 'Constant') {
|
|
if (!nodeProto.attribute || nodeProto.attribute.length !== 1 || !nodeProto.attribute[0].t) {
|
|
throw new Error('missing attributes or missing tensor value in attributes for this Constant operator');
|
|
}
|
|
if (!nodeProto.output || nodeProto.output.length !== 1) {
|
|
throw new Error('missing output or incorrect number of outputs for this Constant operator');
|
|
}
|
|
node.outputs.pop();
|
|
node.executeNode = false;
|
|
this._allData[dataIndex]._from = -1;
|
|
this._allData[dataIndex].tensor = tensor_1.Tensor.fromProto(nodeProto.attribute[0].t);
|
|
}
|
|
}
|
|
}
|
|
// scan node's inputs
|
|
for (let i = 0; i < this._nodes.length; i++) {
|
|
const node = this._nodes[i];
|
|
const nodeProto = graph.node[i];
|
|
if (!nodeProto.input) {
|
|
throw new Error(`missing input for node: ${nodeProto.name}`);
|
|
}
|
|
for (const input of nodeProto.input) {
|
|
const dataIndex = dataIndices.get(input);
|
|
if (typeof dataIndex === 'undefined') {
|
|
// handle exception when opset > 9 and roi not given
|
|
if (input === '' && nodeProto.input.length === 3 && nodeProto.opType === 'Resize') {
|
|
continue;
|
|
}
|
|
throw new Error(`unrecognized input '${input}' for node: ${nodeProto.name}`);
|
|
}
|
|
node.inputs.push(dataIndex);
|
|
this._allData[dataIndex]._to.push(i);
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
buildGraphFromOrtFormat(graph) {
|
|
var _a, _b, _c;
|
|
const dataIndices = new Map();
|
|
this._allData = [];
|
|
this._allInputIndices = [];
|
|
this._allInputNames = [];
|
|
this._allOutputIndices = [];
|
|
this._allOutputNames = [];
|
|
this._nodes = [];
|
|
const nodesIndices = new Map();
|
|
// scan all inputs
|
|
const inputValueNames = [];
|
|
for (let i = 0; i < graph.inputsLength(); i++) {
|
|
const inputName = graph.inputs(i);
|
|
if (dataIndices.has(inputName)) {
|
|
throw new Error(`duplicated input name: ${inputName}`);
|
|
}
|
|
// Find the input typeInfo from nodeargs
|
|
for (let j = 0; j < graph.nodeArgsLength(); j++) {
|
|
if (((_a = graph.nodeArgs(j)) === null || _a === void 0 ? void 0 : _a.name()) === inputName) {
|
|
const value = new Value();
|
|
const valueType = (_c = (_b = graph.nodeArgs(j)) === null || _b === void 0 ? void 0 : _b.type()) === null || _c === void 0 ? void 0 : _c.valueType();
|
|
if (valueType !== ortFbs.TypeInfoValue.tensor_type) {
|
|
throw new Error('Unexpected value type for the nodeArg.');
|
|
}
|
|
const valueInfo = graph.nodeArgs(j).type().value(new ortFbs.TensorTypeAndShape());
|
|
const type = util_1.ProtoUtil.tensorDataTypeFromProto(valueInfo.elemType());
|
|
const shape = valueInfo.shape();
|
|
const dims = [];
|
|
for (let k = 0; k < shape.dimLength(); k++) {
|
|
dims.push(util_1.LongUtil.longToNumber(shape.dim(k).value().dimValue()));
|
|
}
|
|
value.type = { shape: { dims }, tensorType: type };
|
|
const currentIndex = this._allData.push(value) - 1;
|
|
dataIndices.set(inputName, currentIndex);
|
|
inputValueNames.push(inputName);
|
|
}
|
|
}
|
|
}
|
|
// check initializers
|
|
for (let i = 0; i < graph.initializersLength(); i++) {
|
|
const initializer = graph.initializers(i);
|
|
let index = dataIndices.get(initializer.name());
|
|
if (index === undefined) {
|
|
const value = new Value();
|
|
const dims = util_1.ProtoUtil.tensorDimsFromORTFormat(initializer);
|
|
const type = util_1.ProtoUtil.tensorDataTypeFromProto(initializer.dataType());
|
|
value.type = { shape: { dims }, tensorType: type };
|
|
index = this._allData.push(value) - 1;
|
|
dataIndices.set(initializer.name(), index);
|
|
}
|
|
this._allData[index]._from = -1;
|
|
this._allData[index].tensor = tensor_1.Tensor.fromOrtTensor(initializer);
|
|
}
|
|
// filter out input indices
|
|
for (let i = 0; i < this._allData.length; i++) {
|
|
if (!this._allData[i].tensor) {
|
|
this._allInputIndices.push(i);
|
|
this._allInputNames.push(inputValueNames[i]);
|
|
}
|
|
}
|
|
// scan all outputs
|
|
for (let i = 0; i < graph.outputsLength(); i++) {
|
|
const outputName = graph.outputs(i);
|
|
if (dataIndices.has(outputName)) {
|
|
throw new Error(`duplicated output name: ${outputName}`);
|
|
}
|
|
const currentIndex = this._allData.push(new Value()) - 1;
|
|
dataIndices.set(outputName, currentIndex);
|
|
this._allOutputIndices.push(currentIndex);
|
|
this._allOutputNames.push(outputName);
|
|
}
|
|
// scan all nodes
|
|
if (!graph.nodes) {
|
|
throw new Error('missing information in graph: node');
|
|
}
|
|
for (let i = 0; i < graph.nodesLength(); i++) {
|
|
const nodeProto = graph.nodes(i);
|
|
let name = nodeProto.name();
|
|
if (!name) {
|
|
// assign a name to the node if it doesn't have one
|
|
for (let pick = 0;; pick++) {
|
|
name = `unnamed_${nodeProto.opType()}_${pick}`;
|
|
if (!nodesIndices.has(name)) {
|
|
// an unique name is found. break.
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (nodesIndices.has(name)) {
|
|
throw new Error(`duplicated node name: ${name}`);
|
|
}
|
|
const currentIndex = this._nodes.push(new Node(nodeProto, name)) - 1;
|
|
nodesIndices.set(name, currentIndex);
|
|
}
|
|
// scan node's outputs
|
|
for (let i = 0; i < this._nodes.length; i++) {
|
|
const node = this._nodes[i];
|
|
const nodeProto = graph.nodes(i);
|
|
if (nodeProto == null) {
|
|
throw new Error(`No node exists at index ${i}`);
|
|
}
|
|
if ((nodeProto === null || nodeProto === void 0 ? void 0 : nodeProto.outputsLength()) === 0) {
|
|
throw new Error(`missing output for node: ${nodeProto.name}`);
|
|
}
|
|
for (let j = 0; j < (nodeProto === null || nodeProto === void 0 ? void 0 : nodeProto.outputsLength()); j++) {
|
|
const output = nodeProto === null || nodeProto === void 0 ? void 0 : nodeProto.outputs(j);
|
|
let dataIndex = dataIndices.get(output);
|
|
if (typeof dataIndex === 'undefined') {
|
|
dataIndex = this._allData.push(new Value()) - 1;
|
|
dataIndices.set(output, dataIndex);
|
|
}
|
|
node.outputs.push(dataIndex);
|
|
if (this._allData[dataIndex]._from !== undefined) {
|
|
throw new Error(`multiple nodes output to one data value: ${dataIndex}`);
|
|
}
|
|
this._allData[dataIndex]._from = i;
|
|
// for the 'Constant' operator, just create a new edge in the graph corresponding to the 'output' of the
|
|
// operator and ignore the node from the graph
|
|
if (nodeProto.opType() === 'Constant') {
|
|
if (nodeProto.attributesLength() !== 1 || !nodeProto.attributes(0).t()) {
|
|
throw new Error('missing attributes or missing tensor value in attributes for this Constant operator');
|
|
}
|
|
if (nodeProto.outputsLength() !== 1) {
|
|
throw new Error('missing output or incorrect number of outputs for this Constant operator');
|
|
}
|
|
node.outputs.pop();
|
|
node.executeNode = false;
|
|
this._allData[dataIndex]._from = -1;
|
|
this._allData[dataIndex].tensor = tensor_1.Tensor.fromOrtTensor(nodeProto.attributes(0).t());
|
|
}
|
|
}
|
|
}
|
|
// scan node's inputs
|
|
for (let i = 0; i < this._nodes.length; i++) {
|
|
const node = this._nodes[i];
|
|
const nodeProto = graph.nodes(i);
|
|
if (nodeProto.inputsLength() === 0) {
|
|
throw new Error(`missing input for node: ${nodeProto.name}`);
|
|
}
|
|
for (let j = 0; j < nodeProto.inputsLength(); j++) {
|
|
const input = nodeProto.inputs(j);
|
|
const dataIndex = dataIndices.get(input);
|
|
if (typeof dataIndex === 'undefined') {
|
|
throw new Error(`unrecognized input '${input}' for node: ${nodeProto.name()}`);
|
|
}
|
|
node.inputs.push(dataIndex);
|
|
this._allData[dataIndex]._to.push(i);
|
|
}
|
|
}
|
|
}
|
|
checkIsAcyclic() {
|
|
// go through the graph and check for cycles or other fatal inconsistencies
|
|
const starters = new Set();
|
|
this._allInputIndices.forEach(i => {
|
|
const data = this._allData[i];
|
|
data._to.forEach(j => {
|
|
starters.add(j);
|
|
});
|
|
});
|
|
// Iterative DFS to check for cycles
|
|
const nodesStack = Array.from(starters);
|
|
const nodesState = new Array(this._nodes.length).fill('white');
|
|
while (nodesStack.length > 0) {
|
|
const nodeIndex = nodesStack.pop();
|
|
// this node has now been processed completely. Mark this node 'black' to denote this.
|
|
if (nodesState[nodeIndex] === 'gray') {
|
|
nodesState[nodeIndex] = 'black';
|
|
}
|
|
else {
|
|
// this node is under processing stage. mark this node 'gray' to denote this.
|
|
nodesStack.push(nodeIndex);
|
|
nodesState[nodeIndex] = 'gray';
|
|
this._nodes[nodeIndex].outputs.forEach((outgoingEdgeIndex) => {
|
|
const data = this._allData[outgoingEdgeIndex];
|
|
if (typeof data.tensor !== 'undefined') {
|
|
throw new Error('node outputs should not be initialized');
|
|
}
|
|
if (data._from !== nodeIndex) {
|
|
throw new Error('from property of the Value object doesn\'t match index of Node being processed');
|
|
}
|
|
data._to.forEach((downstreamNodeIndex) => {
|
|
// back edge found - cyclic
|
|
if (nodesState[downstreamNodeIndex] === 'gray') {
|
|
throw new Error('model graph is cyclic');
|
|
}
|
|
// tree edge found - continue processing by adding it to stack
|
|
else if (nodesState[downstreamNodeIndex] === 'white') {
|
|
nodesStack.push(downstreamNodeIndex);
|
|
}
|
|
});
|
|
});
|
|
}
|
|
}
|
|
}
|
|
transformGraph(graphInitializer) {
|
|
// apply common transform
|
|
this.removeAllIdentityNodes();
|
|
this.removeAllDropoutNodes();
|
|
this.fuseConvActivationNodes();
|
|
// apply initializer specific transform
|
|
if (graphInitializer) {
|
|
graphInitializer.transformGraph(this);
|
|
}
|
|
// finalize graph
|
|
this.finalizeGraph();
|
|
}
|
|
/**
|
|
* finalize the graph.
|
|
*
|
|
* this function should be called after all the transformation completed.
|
|
* this function removes all unnecessary nodes and values from the graph
|
|
*/
|
|
finalizeGraph() {
|
|
let offset = 0;
|
|
// delete all nodes that are not being executed
|
|
for (let i = 0; i < this._nodes.length; i++) {
|
|
if (!this._nodes[i].executeNode) {
|
|
// delete this node and shift all subsequent nodes up
|
|
offset++;
|
|
// delete all output values
|
|
this._nodes[i].outputs.forEach(ind => {
|
|
this._allData[ind]._from = -2;
|
|
});
|
|
this._nodes.splice(i, 1);
|
|
i--;
|
|
continue;
|
|
}
|
|
if (offset > 0) {
|
|
// update the value table
|
|
this._nodes[i].inputs.forEach(value => {
|
|
const ind = this._allData[value]._to.indexOf(i + offset);
|
|
if (ind !== -1) {
|
|
this._allData[value]._to[ind] = i;
|
|
}
|
|
});
|
|
this._nodes[i].outputs.forEach(value => {
|
|
if (this._allData[value]._from && this._allData[value]._from === i + offset) {
|
|
this._allData[value]._from = i;
|
|
}
|
|
});
|
|
}
|
|
}
|
|
offset = 0;
|
|
// delete all values that are not being referenced
|
|
for (let i = 0; i < this._allData.length; i++) {
|
|
// if current value is neither linked to next node, nor an output value, remove it.
|
|
if (this._allData[i].from === -2 && this._allOutputIndices.indexOf(i + offset) === -1) {
|
|
offset++;
|
|
this._allData.splice(i, 1);
|
|
i--;
|
|
continue;
|
|
}
|
|
if (offset > 0) {
|
|
let ind = -1;
|
|
// if current value is neither an input value nor an initializer, find the node it's
|
|
// coming from and update the corresponding node output
|
|
if (this._allData[i].from !== undefined && this._allData[i].from !== -1) {
|
|
ind = this._nodes[this._allData[i].from].outputs.indexOf(i + offset);
|
|
if (ind !== -1) {
|
|
this._nodes[this._allData[i].from].outputs[ind] = i;
|
|
}
|
|
}
|
|
else {
|
|
// if current value is an input value, update its reference in inputIndices
|
|
ind = this._allInputIndices.indexOf(i + offset);
|
|
if (ind !== -1) {
|
|
this._allInputIndices[ind] = i;
|
|
}
|
|
}
|
|
// find the node that the current value is linking to and update its input reference
|
|
this._allData[i].to.forEach(node => {
|
|
ind = this._nodes[node].inputs.indexOf(i + offset);
|
|
if (ind !== -1) {
|
|
this._nodes[node].inputs[ind] = i;
|
|
}
|
|
});
|
|
if (this._allData[i].to.length === 0) {
|
|
// if current value is a graph output, update its reference in outputIndices
|
|
ind = this._allOutputIndices.indexOf(i + offset);
|
|
if (ind !== -1) {
|
|
this._allOutputIndices[ind] = i;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
/**
|
|
* Delete the specifed node. Assume the node has one incoming input and the first output connected to other nodes.
|
|
* An input validation must be done before calling this function.
|
|
* @param nodeIndex The index of node to be deleted
|
|
*/
|
|
deleteNode(nodeIndex) {
|
|
const node = this._nodes[nodeIndex];
|
|
if (node.outputs.length > 1) {
|
|
for (let i = 1; i < node.outputs.length; i++) {
|
|
if (this._allData[node.outputs[i]].to.length > 0) {
|
|
throw new Error('Node deletion with more than one output connected to other nodes is not supported. ');
|
|
}
|
|
}
|
|
}
|
|
// this node wil not be executed
|
|
node.executeNode = false;
|
|
const inputValueIndex = node.inputs[0];
|
|
const outputValueIndex = node.outputs[0];
|
|
const nodesConsumingOutput = this._allData[outputValueIndex].to;
|
|
// remove this node from the to property of the input Value
|
|
const delIndex = this._allData[inputValueIndex].to.indexOf(nodeIndex);
|
|
// should not happen
|
|
if (delIndex === -1) {
|
|
throw new Error('The Value object doesn\'t have the current Node in it\'s \'to\' property ');
|
|
}
|
|
this._allData[inputValueIndex].to.splice(delIndex, 1);
|
|
// clear node indices consuming this output Value
|
|
this._allData[outputValueIndex]._to = [];
|
|
// if the output of this node is a graph output, adjust the index appropriately
|
|
const index = this._allOutputIndices.indexOf(outputValueIndex);
|
|
if (index !== -1) {
|
|
this._allOutputIndices[index] = inputValueIndex;
|
|
}
|
|
// override the inputs for nodes consuming this node's output with the input to this node
|
|
if (nodesConsumingOutput && nodesConsumingOutput.length > 0) {
|
|
for (const nodeIndex of nodesConsumingOutput) {
|
|
const replaceIndex = this._nodes[nodeIndex].inputs.indexOf(outputValueIndex);
|
|
// should not happen
|
|
if (replaceIndex === -1) {
|
|
throw new Error('The Node object doesn\'t have the output Value in it\'s \'inputs\' property ');
|
|
}
|
|
this._nodes[nodeIndex].inputs[replaceIndex] = inputValueIndex;
|
|
this._allData[inputValueIndex].to.push(nodeIndex);
|
|
}
|
|
}
|
|
}
|
|
removeAllDropoutNodes() {
|
|
let nodeIndex = 0;
|
|
for (const node of this._nodes) {
|
|
// weed out 'Dropout' nodes so that no time is wasted in execution
|
|
if (node.opType === 'Dropout') {
|
|
// the node should have exactly 1 input and 1 or 2 outputs
|
|
if (node.inputs.length !== 1) {
|
|
throw new Error('Dropout nodes should only contain one input. ');
|
|
}
|
|
if (node.outputs.length !== 1 && node.outputs.length !== 2) {
|
|
throw new Error('Dropout nodes should contain either 1 or 2 output(s)');
|
|
}
|
|
// the second output should not be referenced by any other node
|
|
if (node.outputs.length === 2 && this._allData[node.outputs[1]]._to.length !== 0) {
|
|
throw new Error('Dropout nodes\'s second output should not be referenced by other nodes');
|
|
}
|
|
this.deleteNode(nodeIndex);
|
|
}
|
|
nodeIndex++;
|
|
}
|
|
}
|
|
removeAllIdentityNodes() {
|
|
let nodeIndex = 0;
|
|
for (const node of this._nodes) {
|
|
// weed out 'Identity' nodes so that no time is wasted in execution
|
|
if (node.opType === 'Identity') {
|
|
this.deleteNode(nodeIndex);
|
|
}
|
|
nodeIndex++;
|
|
}
|
|
}
|
|
isActivation(n) {
|
|
switch (n.opType) {
|
|
// TODO: add other activation methods
|
|
case 'Relu':
|
|
case 'Sigmoid':
|
|
case 'Clip':
|
|
return true;
|
|
default:
|
|
return false;
|
|
}
|
|
}
|
|
fuseConvActivationNodes() {
|
|
for (const node of this._nodes) {
|
|
if (node.opType === 'Conv') {
|
|
const next = this._allData[node.outputs[0]]._to;
|
|
if (next.length === 1 && this.isActivation(this._nodes[next[0]])) {
|
|
const child = this._nodes[next[0]];
|
|
if (child.opType === 'Clip') {
|
|
if (child.inputs.length === 1) {
|
|
try {
|
|
node.attributes.set('activation_params', 'floats', [child.attributes.getFloat('min'), child.attributes.getFloat('max')]);
|
|
}
|
|
catch (e) {
|
|
node.attributes.set('activation_params', 'floats', [util_1.MIN_CLIP, util_1.MAX_CLIP]);
|
|
}
|
|
}
|
|
else if (child.inputs.length >= 3 && this._allData[child.inputs[1]].tensor !== undefined &&
|
|
this._allData[child.inputs[2]].tensor !== undefined) {
|
|
node.attributes.set('activation_params', 'floats', [
|
|
this._allData[child.inputs[1]].tensor.floatData[0], this._allData[child.inputs[2]].tensor.floatData[0]
|
|
]);
|
|
}
|
|
else {
|
|
// Skip fusion with clip node since clip min and clip max are not coming from initializer
|
|
continue;
|
|
}
|
|
}
|
|
node.attributes.set('activation', 'string', (child.opType));
|
|
this.deleteNode(next[0]);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./lib/onnxjs/instrument.ts":
|
|
/*!**********************************!*\
|
|
!*** ./lib/onnxjs/instrument.ts ***!
|
|
\**********************************/
|
|
/***/ ((__unused_webpack_module, exports) => {
|
|
|
|
"use strict";
|
|
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
// Licensed under the MIT License.
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.now = exports.Profiler = exports.Logger = void 0;
|
|
class NoOpLoggerProvider {
|
|
log(_severity, _content, _category) {
|
|
// do nothing
|
|
}
|
|
}
|
|
class ConsoleLoggerProvider {
|
|
log(severity, content, category) {
|
|
// eslint-disable-next-line no-console
|
|
console.log(`${this.color(severity)} ${category ? '\x1b[35m' + category + '\x1b[0m ' : ''}${content}`);
|
|
}
|
|
color(severity) {
|
|
switch (severity) {
|
|
case 'verbose':
|
|
return '\x1b[34;40mv\x1b[0m';
|
|
case 'info':
|
|
return '\x1b[32mi\x1b[0m';
|
|
case 'warning':
|
|
return '\x1b[30;43mw\x1b[0m';
|
|
case 'error':
|
|
return '\x1b[31;40me\x1b[0m';
|
|
case 'fatal':
|
|
return '\x1b[101mf\x1b[0m';
|
|
default:
|
|
throw new Error(`unsupported severity: ${severity}`);
|
|
}
|
|
}
|
|
}
|
|
const SEVERITY_VALUE = {
|
|
verbose: 1000,
|
|
info: 2000,
|
|
warning: 4000,
|
|
error: 5000,
|
|
fatal: 6000
|
|
};
|
|
const LOGGER_PROVIDER_MAP = {
|
|
['none']: new NoOpLoggerProvider(),
|
|
['console']: new ConsoleLoggerProvider()
|
|
};
|
|
const LOGGER_DEFAULT_CONFIG = {
|
|
provider: 'console',
|
|
minimalSeverity: 'warning',
|
|
logDateTime: true,
|
|
logSourceLocation: false
|
|
};
|
|
let LOGGER_CONFIG_MAP = { ['']: LOGGER_DEFAULT_CONFIG };
|
|
function log(arg0, arg1, arg2, arg3) {
|
|
if (arg1 === undefined) {
|
|
// log(category: string): Logger.CategorizedLogger;
|
|
return createCategorizedLogger(arg0);
|
|
}
|
|
else if (arg2 === undefined) {
|
|
// log(severity, content);
|
|
logInternal(arg0, arg1, 1);
|
|
}
|
|
else if (typeof arg2 === 'number' && arg3 === undefined) {
|
|
// log(severity, content, stack)
|
|
logInternal(arg0, arg1, arg2);
|
|
}
|
|
else if (typeof arg2 === 'string' && arg3 === undefined) {
|
|
// log(severity, category, content)
|
|
logInternal(arg0, arg2, 1, arg1);
|
|
}
|
|
else if (typeof arg2 === 'string' && typeof arg3 === 'number') {
|
|
// log(severity, category, content, stack)
|
|
logInternal(arg0, arg2, arg3, arg1);
|
|
}
|
|
else {
|
|
throw new TypeError('input is valid');
|
|
}
|
|
}
|
|
function createCategorizedLogger(category) {
|
|
return {
|
|
verbose: log.verbose.bind(null, category),
|
|
info: log.info.bind(null, category),
|
|
warning: log.warning.bind(null, category),
|
|
error: log.error.bind(null, category),
|
|
fatal: log.fatal.bind(null, category)
|
|
};
|
|
}
|
|
// NOTE: argument 'category' is put the last parameter beacause typescript
|
|
// doesn't allow optional argument put in front of required argument. This
|
|
// order is different from a usual logging API.
|
|
function logInternal(severity, content, stack, category) {
|
|
const config = LOGGER_CONFIG_MAP[category || ''] || LOGGER_CONFIG_MAP[''];
|
|
if (SEVERITY_VALUE[severity] < SEVERITY_VALUE[config.minimalSeverity]) {
|
|
return;
|
|
}
|
|
if (config.logDateTime) {
|
|
content = `${new Date().toISOString()}|${content}`;
|
|
}
|
|
if (config.logSourceLocation) {
|
|
// TODO: calculate source location from 'stack'
|
|
}
|
|
LOGGER_PROVIDER_MAP[config.provider].log(severity, content, category);
|
|
}
|
|
// eslint-disable-next-line @typescript-eslint/no-namespace
|
|
(function (log) {
|
|
function verbose(arg0, arg1) {
|
|
log('verbose', arg0, arg1);
|
|
}
|
|
log.verbose = verbose;
|
|
function info(arg0, arg1) {
|
|
log('info', arg0, arg1);
|
|
}
|
|
log.info = info;
|
|
function warning(arg0, arg1) {
|
|
log('warning', arg0, arg1);
|
|
}
|
|
log.warning = warning;
|
|
function error(arg0, arg1) {
|
|
log('error', arg0, arg1);
|
|
}
|
|
log.error = error;
|
|
function fatal(arg0, arg1) {
|
|
log('fatal', arg0, arg1);
|
|
}
|
|
log.fatal = fatal;
|
|
function reset(config) {
|
|
LOGGER_CONFIG_MAP = {};
|
|
set('', config || {});
|
|
}
|
|
log.reset = reset;
|
|
function set(category, config) {
|
|
if (category === '*') {
|
|
reset(config);
|
|
}
|
|
else {
|
|
const previousConfig = LOGGER_CONFIG_MAP[category] || LOGGER_DEFAULT_CONFIG;
|
|
LOGGER_CONFIG_MAP[category] = {
|
|
provider: config.provider || previousConfig.provider,
|
|
minimalSeverity: config.minimalSeverity || previousConfig.minimalSeverity,
|
|
logDateTime: (config.logDateTime === undefined) ? previousConfig.logDateTime : config.logDateTime,
|
|
logSourceLocation: (config.logSourceLocation === undefined) ? previousConfig.logSourceLocation :
|
|
config.logSourceLocation
|
|
};
|
|
}
|
|
// TODO: we want to support wildcard or regex?
|
|
}
|
|
log.set = set;
|
|
function setWithEnv(env) {
|
|
const config = {};
|
|
if (env.logLevel) {
|
|
config.minimalSeverity = env.logLevel;
|
|
}
|
|
set('', config);
|
|
}
|
|
log.setWithEnv = setWithEnv;
|
|
})(log || (log = {}));
|
|
// eslint-disable-next-line @typescript-eslint/no-redeclare, @typescript-eslint/naming-convention
|
|
exports.Logger = log;
|
|
// TODO
|
|
// class WebGLEvent implements Profiler.Event {}
|
|
class Event {
|
|
constructor(category, name, startTime, endCallback, timer, ctx) {
|
|
this.category = category;
|
|
this.name = name;
|
|
this.startTime = startTime;
|
|
this.endCallback = endCallback;
|
|
this.timer = timer;
|
|
this.ctx = ctx;
|
|
}
|
|
end() {
|
|
return this.endCallback(this);
|
|
}
|
|
async checkTimer() {
|
|
if (this.ctx === undefined || this.timer === undefined) {
|
|
throw new Error('No webgl timer found');
|
|
}
|
|
else {
|
|
this.ctx.endTimer();
|
|
return this.ctx.waitForQueryAndGetTime(this.timer);
|
|
}
|
|
}
|
|
}
|
|
class EventRecord {
|
|
constructor(category, name, startTime, endTime) {
|
|
this.category = category;
|
|
this.name = name;
|
|
this.startTime = startTime;
|
|
this.endTime = endTime;
|
|
}
|
|
}
|
|
class Profiler {
|
|
static create(config) {
|
|
if (config === undefined) {
|
|
return new this();
|
|
}
|
|
return new this(config.maxNumberEvents, config.flushBatchSize, config.flushIntervalInMilliseconds);
|
|
}
|
|
constructor(maxNumberEvents, flushBatchSize, flushIntervalInMilliseconds) {
|
|
this._started = false;
|
|
this._flushPointer = 0;
|
|
this._started = false;
|
|
this._maxNumberEvents = maxNumberEvents === undefined ? 10000 : maxNumberEvents;
|
|
this._flushBatchSize = flushBatchSize === undefined ? 10 : flushBatchSize;
|
|
this._flushIntervalInMilliseconds = flushIntervalInMilliseconds === undefined ? 5000 : flushIntervalInMilliseconds;
|
|
}
|
|
// start profiling
|
|
start() {
|
|
this._started = true;
|
|
this._timingEvents = [];
|
|
this._flushTime = (0, exports.now)();
|
|
this._flushPointer = 0;
|
|
}
|
|
// stop profiling
|
|
stop() {
|
|
this._started = false;
|
|
for (; this._flushPointer < this._timingEvents.length; this._flushPointer++) {
|
|
this.logOneEvent(this._timingEvents[this._flushPointer]);
|
|
}
|
|
}
|
|
event(category, name, func, ctx) {
|
|
const event = this._started ? this.begin(category, name, ctx) : undefined;
|
|
let isPromise = false;
|
|
const res = func();
|
|
// we consider a then-able object is a promise
|
|
if (res && typeof res.then === 'function') {
|
|
isPromise = true;
|
|
return new Promise((resolve, reject) => {
|
|
res
|
|
.then(async (value) => {
|
|
if (event) {
|
|
await event.end();
|
|
}
|
|
resolve(value);
|
|
}, async (reason) => {
|
|
if (event) {
|
|
await event.end();
|
|
}
|
|
reject(reason);
|
|
});
|
|
});
|
|
}
|
|
if (!isPromise && event) {
|
|
const eventRes = event.end();
|
|
if (eventRes && typeof eventRes.then === 'function') {
|
|
return new Promise((resolve, reject) => {
|
|
(eventRes).then(() => {
|
|
resolve(res);
|
|
}, (reason) => {
|
|
reject(reason);
|
|
});
|
|
});
|
|
}
|
|
}
|
|
return res;
|
|
}
|
|
// begin an event
|
|
begin(category, name, ctx) {
|
|
if (!this._started) {
|
|
throw new Error('profiler is not started yet');
|
|
}
|
|
if (ctx === undefined) {
|
|
const startTime = (0, exports.now)();
|
|
this.flush(startTime);
|
|
return new Event(category, name, startTime, e => this.endSync(e));
|
|
}
|
|
else {
|
|
const timer = ctx.beginTimer();
|
|
return new Event(category, name, 0, async (e) => this.end(e), timer, ctx);
|
|
}
|
|
}
|
|
// end the specific event
|
|
async end(event) {
|
|
const endTime = await event.checkTimer();
|
|
if (this._timingEvents.length < this._maxNumberEvents) {
|
|
this._timingEvents.push(new EventRecord(event.category, event.name, event.startTime, endTime));
|
|
this.flush(endTime);
|
|
}
|
|
}
|
|
endSync(event) {
|
|
const endTime = (0, exports.now)();
|
|
if (this._timingEvents.length < this._maxNumberEvents) {
|
|
this._timingEvents.push(new EventRecord(event.category, event.name, event.startTime, endTime));
|
|
this.flush(endTime);
|
|
}
|
|
}
|
|
logOneEvent(event) {
|
|
exports.Logger.verbose(`Profiler.${event.category}`, `${(event.endTime - event.startTime).toFixed(2)}ms on event '${event.name}' at ${event.endTime.toFixed(2)}`);
|
|
}
|
|
flush(currentTime) {
|
|
if (this._timingEvents.length - this._flushPointer >= this._flushBatchSize ||
|
|
currentTime - this._flushTime >= this._flushIntervalInMilliseconds) {
|
|
// should flush when either batch size accumlated or interval elepsed
|
|
for (const previousPointer = this._flushPointer; this._flushPointer < previousPointer + this._flushBatchSize &&
|
|
this._flushPointer < this._timingEvents.length; this._flushPointer++) {
|
|
this.logOneEvent(this._timingEvents[this._flushPointer]);
|
|
}
|
|
this._flushTime = (0, exports.now)();
|
|
}
|
|
}
|
|
get started() {
|
|
return this._started;
|
|
}
|
|
}
|
|
exports.Profiler = Profiler;
|
|
/**
|
|
* returns a number to represent the current timestamp in a resolution as high as possible.
|
|
*/
|
|
exports.now = (typeof performance !== 'undefined' && performance.now) ? () => performance.now() : Date.now;
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./lib/onnxjs/model.ts":
|
|
/*!*****************************!*\
|
|
!*** ./lib/onnxjs/model.ts ***!
|
|
\*****************************/
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
// Licensed under the MIT License.
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.Model = void 0;
|
|
const flatbuffers_1 = __webpack_require__(/*! flatbuffers */ "./node_modules/flatbuffers/js/flatbuffers.mjs");
|
|
const onnx_proto_1 = __webpack_require__(/*! onnx-proto */ "./node_modules/onnx-proto/dist/onnx.js");
|
|
const graph_1 = __webpack_require__(/*! ./graph */ "./lib/onnxjs/graph.ts");
|
|
const ort_generated_1 = __webpack_require__(/*! ./ort-schema/ort-generated */ "./lib/onnxjs/ort-schema/ort-generated.ts");
|
|
const util_1 = __webpack_require__(/*! ./util */ "./lib/onnxjs/util.ts");
|
|
var ortFbs = ort_generated_1.onnxruntime.experimental.fbs;
|
|
class Model {
|
|
// empty model
|
|
constructor() { }
|
|
load(buf, graphInitializer, isOrtFormat) {
|
|
if (!isOrtFormat) {
|
|
// isOrtFormat === false || isOrtFormat === undefined
|
|
try {
|
|
this.loadFromOnnxFormat(buf, graphInitializer);
|
|
return;
|
|
}
|
|
catch (e) {
|
|
if (isOrtFormat !== undefined) {
|
|
throw e;
|
|
}
|
|
}
|
|
}
|
|
this.loadFromOrtFormat(buf, graphInitializer);
|
|
}
|
|
loadFromOnnxFormat(buf, graphInitializer) {
|
|
const modelProto = onnx_proto_1.onnx.ModelProto.decode(buf);
|
|
const irVersion = util_1.LongUtil.longToNumber(modelProto.irVersion);
|
|
if (irVersion < 3) {
|
|
throw new Error('only support ONNX model with IR_VERSION>=3');
|
|
}
|
|
this._opsets =
|
|
modelProto.opsetImport.map(i => ({ domain: i.domain, version: util_1.LongUtil.longToNumber(i.version) }));
|
|
this._graph = graph_1.Graph.from(modelProto.graph, graphInitializer);
|
|
}
|
|
loadFromOrtFormat(buf, graphInitializer) {
|
|
const fb = new flatbuffers_1.flatbuffers.ByteBuffer(buf);
|
|
const ortModel = ortFbs.InferenceSession.getRootAsInferenceSession(fb).model();
|
|
const irVersion = util_1.LongUtil.longToNumber(ortModel.irVersion());
|
|
if (irVersion < 3) {
|
|
throw new Error('only support ONNX model with IR_VERSION>=3');
|
|
}
|
|
this._opsets = [];
|
|
for (let i = 0; i < ortModel.opsetImportLength(); i++) {
|
|
const opsetId = ortModel.opsetImport(i);
|
|
this._opsets.push({ domain: opsetId === null || opsetId === void 0 ? void 0 : opsetId.domain(), version: util_1.LongUtil.longToNumber(opsetId.version()) });
|
|
}
|
|
this._graph = graph_1.Graph.from(ortModel.graph(), graphInitializer);
|
|
}
|
|
get graph() {
|
|
return this._graph;
|
|
}
|
|
get opsets() {
|
|
return this._opsets;
|
|
}
|
|
}
|
|
exports.Model = Model;
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./lib/onnxjs/operators.ts":
|
|
/*!*********************************!*\
|
|
!*** ./lib/onnxjs/operators.ts ***!
|
|
\*********************************/
|
|
/***/ ((__unused_webpack_module, exports) => {
|
|
|
|
"use strict";
|
|
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
// Licensed under the MIT License.
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.FLOAT_TYPES = exports.INT_TYPES = exports.NUMBER_TYPES = void 0;
|
|
exports.NUMBER_TYPES = ['float32', 'float64', 'int32', 'int16', 'int8', 'uint16', 'uint32', 'uint8'];
|
|
exports.INT_TYPES = ['int32', 'int16', 'int8', 'uint16', 'uint32', 'uint8'];
|
|
exports.FLOAT_TYPES = ['float32', 'float64'];
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./lib/onnxjs/opset.ts":
|
|
/*!*****************************!*\
|
|
!*** ./lib/onnxjs/opset.ts ***!
|
|
\*****************************/
|
|
/***/ ((__unused_webpack_module, exports) => {
|
|
|
|
"use strict";
|
|
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
// Licensed under the MIT License.
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.resolveOperator = void 0;
|
|
function resolveOperator(node, opsets, rules) {
|
|
for (const rule of rules) {
|
|
const opType = rule[0];
|
|
const domain = rule[1];
|
|
const versionSelector = rule[2];
|
|
const opImpl = rule[3];
|
|
const opInit = rule[4];
|
|
if (node.opType === opType) { // operator type matches
|
|
for (const opset of opsets) {
|
|
// opset '' and 'ai.onnx' are considered the same.
|
|
if (opset.domain === domain || (opset.domain === 'ai.onnx' && domain === '')) { // opset domain found
|
|
if (matchSelector(opset.version, versionSelector)) {
|
|
return { opImpl, opInit };
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
throw new TypeError(`cannot resolve operator '${node.opType}' with opsets: ${opsets.map(set => `${set.domain || 'ai.onnx'} v${set.version}`).join(', ')}`);
|
|
}
|
|
exports.resolveOperator = resolveOperator;
|
|
function matchSelector(version, selector) {
|
|
if (selector.endsWith('+')) {
|
|
// minimum version match ('7+' expects version>=7)
|
|
const rangeStart = Number.parseInt(selector.substring(0, selector.length - 1), 10);
|
|
return !isNaN(rangeStart) && rangeStart <= version;
|
|
}
|
|
else if (selector.split('-').length === 2) {
|
|
// range match ('6-8' expects 6<=version<=8)
|
|
const pair = selector.split('-');
|
|
const rangeStart = Number.parseInt(pair[0], 10);
|
|
const rangeEnd = Number.parseInt(pair[1], 10);
|
|
return !isNaN(rangeStart) && !isNaN(rangeEnd) && rangeStart <= version && version <= rangeEnd;
|
|
}
|
|
else {
|
|
// exact match ('7' expects version===7)
|
|
return Number.parseInt(selector, 10) === version;
|
|
}
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./lib/onnxjs/ort-schema/ort-generated.ts":
|
|
/*!************************************************!*\
|
|
!*** ./lib/onnxjs/ort-schema/ort-generated.ts ***!
|
|
\************************************************/
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
// automatically generated by the FlatBuffers compiler, do not modify
|
|
/* eslint-disable */
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.onnxruntime = void 0;
|
|
const flatbuffers_1 = __webpack_require__(/*! flatbuffers */ "./node_modules/flatbuffers/js/flatbuffers.mjs");
|
|
/**
|
|
* @enum {number}
|
|
*/
|
|
var onnxruntime;
|
|
(function (onnxruntime) {
|
|
var experimental;
|
|
(function (experimental) {
|
|
var fbs;
|
|
(function (fbs) {
|
|
let AttributeType;
|
|
(function (AttributeType) {
|
|
AttributeType[AttributeType["UNDEFINED"] = 0] = "UNDEFINED";
|
|
AttributeType[AttributeType["FLOAT"] = 1] = "FLOAT";
|
|
AttributeType[AttributeType["INT"] = 2] = "INT";
|
|
AttributeType[AttributeType["STRING"] = 3] = "STRING";
|
|
AttributeType[AttributeType["TENSOR"] = 4] = "TENSOR";
|
|
AttributeType[AttributeType["GRAPH"] = 5] = "GRAPH";
|
|
AttributeType[AttributeType["FLOATS"] = 6] = "FLOATS";
|
|
AttributeType[AttributeType["INTS"] = 7] = "INTS";
|
|
AttributeType[AttributeType["STRINGS"] = 8] = "STRINGS";
|
|
AttributeType[AttributeType["TENSORS"] = 9] = "TENSORS";
|
|
AttributeType[AttributeType["GRAPHS"] = 10] = "GRAPHS";
|
|
AttributeType[AttributeType["SPARSE_TENSOR"] = 11] = "SPARSE_TENSOR";
|
|
AttributeType[AttributeType["SPARSE_TENSORS"] = 12] = "SPARSE_TENSORS";
|
|
})(AttributeType = fbs.AttributeType || (fbs.AttributeType = {}));
|
|
})(fbs = experimental.fbs || (experimental.fbs = {}));
|
|
})(experimental = onnxruntime.experimental || (onnxruntime.experimental = {}));
|
|
})(onnxruntime = exports.onnxruntime || (exports.onnxruntime = {}));
|
|
/**
|
|
* @enum {number}
|
|
*/
|
|
(function (onnxruntime) {
|
|
var experimental;
|
|
(function (experimental) {
|
|
var fbs;
|
|
(function (fbs) {
|
|
let DimensionValueType;
|
|
(function (DimensionValueType) {
|
|
DimensionValueType[DimensionValueType["UNKNOWN"] = 0] = "UNKNOWN";
|
|
DimensionValueType[DimensionValueType["VALUE"] = 1] = "VALUE";
|
|
DimensionValueType[DimensionValueType["PARAM"] = 2] = "PARAM";
|
|
})(DimensionValueType = fbs.DimensionValueType || (fbs.DimensionValueType = {}));
|
|
})(fbs = experimental.fbs || (experimental.fbs = {}));
|
|
})(experimental = onnxruntime.experimental || (onnxruntime.experimental = {}));
|
|
})(onnxruntime = exports.onnxruntime || (exports.onnxruntime = {}));
|
|
/**
|
|
* @enum {number}
|
|
*/
|
|
(function (onnxruntime) {
|
|
var experimental;
|
|
(function (experimental) {
|
|
var fbs;
|
|
(function (fbs) {
|
|
let TensorDataType;
|
|
(function (TensorDataType) {
|
|
TensorDataType[TensorDataType["UNDEFINED"] = 0] = "UNDEFINED";
|
|
TensorDataType[TensorDataType["FLOAT"] = 1] = "FLOAT";
|
|
TensorDataType[TensorDataType["UINT8"] = 2] = "UINT8";
|
|
TensorDataType[TensorDataType["INT8"] = 3] = "INT8";
|
|
TensorDataType[TensorDataType["UINT16"] = 4] = "UINT16";
|
|
TensorDataType[TensorDataType["INT16"] = 5] = "INT16";
|
|
TensorDataType[TensorDataType["INT32"] = 6] = "INT32";
|
|
TensorDataType[TensorDataType["INT64"] = 7] = "INT64";
|
|
TensorDataType[TensorDataType["STRING"] = 8] = "STRING";
|
|
TensorDataType[TensorDataType["BOOL"] = 9] = "BOOL";
|
|
TensorDataType[TensorDataType["FLOAT16"] = 10] = "FLOAT16";
|
|
TensorDataType[TensorDataType["DOUBLE"] = 11] = "DOUBLE";
|
|
TensorDataType[TensorDataType["UINT32"] = 12] = "UINT32";
|
|
TensorDataType[TensorDataType["UINT64"] = 13] = "UINT64";
|
|
TensorDataType[TensorDataType["COMPLEX64"] = 14] = "COMPLEX64";
|
|
TensorDataType[TensorDataType["COMPLEX128"] = 15] = "COMPLEX128";
|
|
TensorDataType[TensorDataType["BFLOAT16"] = 16] = "BFLOAT16";
|
|
})(TensorDataType = fbs.TensorDataType || (fbs.TensorDataType = {}));
|
|
})(fbs = experimental.fbs || (experimental.fbs = {}));
|
|
})(experimental = onnxruntime.experimental || (onnxruntime.experimental = {}));
|
|
})(onnxruntime = exports.onnxruntime || (exports.onnxruntime = {}));
|
|
/**
|
|
* @enum {number}
|
|
*/
|
|
(function (onnxruntime) {
|
|
var experimental;
|
|
(function (experimental) {
|
|
var fbs;
|
|
(function (fbs) {
|
|
let NodeType;
|
|
(function (NodeType) {
|
|
NodeType[NodeType["Primitive"] = 0] = "Primitive";
|
|
NodeType[NodeType["Fused"] = 1] = "Fused";
|
|
})(NodeType = fbs.NodeType || (fbs.NodeType = {}));
|
|
})(fbs = experimental.fbs || (experimental.fbs = {}));
|
|
})(experimental = onnxruntime.experimental || (onnxruntime.experimental = {}));
|
|
})(onnxruntime = exports.onnxruntime || (exports.onnxruntime = {}));
|
|
/**
|
|
* @enum {number}
|
|
*/
|
|
(function (onnxruntime) {
|
|
var experimental;
|
|
(function (experimental) {
|
|
var fbs;
|
|
(function (fbs) {
|
|
let TypeInfoValue;
|
|
(function (TypeInfoValue) {
|
|
TypeInfoValue[TypeInfoValue["NONE"] = 0] = "NONE";
|
|
TypeInfoValue[TypeInfoValue["tensor_type"] = 1] = "tensor_type";
|
|
TypeInfoValue[TypeInfoValue["sequence_type"] = 2] = "sequence_type";
|
|
TypeInfoValue[TypeInfoValue["map_type"] = 3] = "map_type";
|
|
})(TypeInfoValue = fbs.TypeInfoValue || (fbs.TypeInfoValue = {}));
|
|
})(fbs = experimental.fbs || (experimental.fbs = {}));
|
|
})(experimental = onnxruntime.experimental || (onnxruntime.experimental = {}));
|
|
})(onnxruntime = exports.onnxruntime || (exports.onnxruntime = {}));
|
|
/**
|
|
* @constructor
|
|
*/
|
|
(function (onnxruntime) {
|
|
var experimental;
|
|
(function (experimental) {
|
|
var fbs;
|
|
(function (fbs) {
|
|
class Shape {
|
|
constructor() {
|
|
this.bb = null;
|
|
this.bb_pos = 0;
|
|
}
|
|
/**
|
|
* @param number i
|
|
* @param flatbuffers.ByteBuffer bb
|
|
* @returns Shape
|
|
*/
|
|
__init(i, bb) {
|
|
this.bb_pos = i;
|
|
this.bb = bb;
|
|
return this;
|
|
}
|
|
/**
|
|
* @param flatbuffers.ByteBuffer bb
|
|
* @param Shape= obj
|
|
* @returns Shape
|
|
*/
|
|
static getRootAsShape(bb, obj) {
|
|
return (obj || new Shape()).__init(bb.readInt32(bb.position()) + bb.position(), bb);
|
|
}
|
|
/**
|
|
* @param flatbuffers.ByteBuffer bb
|
|
* @param Shape= obj
|
|
* @returns Shape
|
|
*/
|
|
static getSizePrefixedRootAsShape(bb, obj) {
|
|
bb.setPosition(bb.position() + flatbuffers_1.flatbuffers.SIZE_PREFIX_LENGTH);
|
|
return (obj || new Shape()).__init(bb.readInt32(bb.position()) + bb.position(), bb);
|
|
}
|
|
/**
|
|
* @param number index
|
|
* @param onnxruntime.experimental.fbs.Dimension= obj
|
|
* @returns onnxruntime.experimental.fbs.Dimension
|
|
*/
|
|
dim(index, obj) {
|
|
let offset = this.bb.__offset(this.bb_pos, 4);
|
|
return offset ? (obj || new onnxruntime.experimental.fbs.Dimension())
|
|
.__init(this.bb.__indirect(this.bb.__vector(this.bb_pos + offset) + index * 4), this.bb) :
|
|
null;
|
|
}
|
|
/**
|
|
* @returns number
|
|
*/
|
|
dimLength() {
|
|
let offset = this.bb.__offset(this.bb_pos, 4);
|
|
return offset ? this.bb.__vector_len(this.bb_pos + offset) : 0;
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
*/
|
|
static startShape(builder) {
|
|
builder.startObject(1);
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @param flatbuffers.Offset dimOffset
|
|
*/
|
|
static addDim(builder, dimOffset) {
|
|
builder.addFieldOffset(0, dimOffset, 0);
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @param Array.<flatbuffers.Offset> data
|
|
* @returns flatbuffers.Offset
|
|
*/
|
|
static createDimVector(builder, data) {
|
|
builder.startVector(4, data.length, 4);
|
|
for (let i = data.length - 1; i >= 0; i--) {
|
|
builder.addOffset(data[i]);
|
|
}
|
|
return builder.endVector();
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @param number numElems
|
|
*/
|
|
static startDimVector(builder, numElems) {
|
|
builder.startVector(4, numElems, 4);
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @returns flatbuffers.Offset
|
|
*/
|
|
static endShape(builder) {
|
|
let offset = builder.endObject();
|
|
return offset;
|
|
}
|
|
static createShape(builder, dimOffset) {
|
|
Shape.startShape(builder);
|
|
Shape.addDim(builder, dimOffset);
|
|
return Shape.endShape(builder);
|
|
}
|
|
}
|
|
fbs.Shape = Shape;
|
|
})(fbs = experimental.fbs || (experimental.fbs = {}));
|
|
})(experimental = onnxruntime.experimental || (onnxruntime.experimental = {}));
|
|
})(onnxruntime = exports.onnxruntime || (exports.onnxruntime = {}));
|
|
/**
|
|
* @constructor
|
|
*/
|
|
(function (onnxruntime) {
|
|
var experimental;
|
|
(function (experimental) {
|
|
var fbs;
|
|
(function (fbs) {
|
|
class Dimension {
|
|
constructor() {
|
|
this.bb = null;
|
|
this.bb_pos = 0;
|
|
}
|
|
/**
|
|
* @param number i
|
|
* @param flatbuffers.ByteBuffer bb
|
|
* @returns Dimension
|
|
*/
|
|
__init(i, bb) {
|
|
this.bb_pos = i;
|
|
this.bb = bb;
|
|
return this;
|
|
}
|
|
/**
|
|
* @param flatbuffers.ByteBuffer bb
|
|
* @param Dimension= obj
|
|
* @returns Dimension
|
|
*/
|
|
static getRootAsDimension(bb, obj) {
|
|
return (obj || new Dimension()).__init(bb.readInt32(bb.position()) + bb.position(), bb);
|
|
}
|
|
/**
|
|
* @param flatbuffers.ByteBuffer bb
|
|
* @param Dimension= obj
|
|
* @returns Dimension
|
|
*/
|
|
static getSizePrefixedRootAsDimension(bb, obj) {
|
|
bb.setPosition(bb.position() + flatbuffers_1.flatbuffers.SIZE_PREFIX_LENGTH);
|
|
return (obj || new Dimension()).__init(bb.readInt32(bb.position()) + bb.position(), bb);
|
|
}
|
|
/**
|
|
* @param onnxruntime.experimental.fbs.DimensionValue= obj
|
|
* @returns onnxruntime.experimental.fbs.DimensionValue|null
|
|
*/
|
|
value(obj) {
|
|
let offset = this.bb.__offset(this.bb_pos, 4);
|
|
return offset ? (obj || new onnxruntime.experimental.fbs.DimensionValue())
|
|
.__init(this.bb.__indirect(this.bb_pos + offset), this.bb) :
|
|
null;
|
|
}
|
|
denotation(optionalEncoding) {
|
|
let offset = this.bb.__offset(this.bb_pos, 6);
|
|
return offset ? this.bb.__string(this.bb_pos + offset, optionalEncoding) : null;
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
*/
|
|
static startDimension(builder) {
|
|
builder.startObject(2);
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @param flatbuffers.Offset valueOffset
|
|
*/
|
|
static addValue(builder, valueOffset) {
|
|
builder.addFieldOffset(0, valueOffset, 0);
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @param flatbuffers.Offset denotationOffset
|
|
*/
|
|
static addDenotation(builder, denotationOffset) {
|
|
builder.addFieldOffset(1, denotationOffset, 0);
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @returns flatbuffers.Offset
|
|
*/
|
|
static endDimension(builder) {
|
|
let offset = builder.endObject();
|
|
return offset;
|
|
}
|
|
static createDimension(builder, valueOffset, denotationOffset) {
|
|
Dimension.startDimension(builder);
|
|
Dimension.addValue(builder, valueOffset);
|
|
Dimension.addDenotation(builder, denotationOffset);
|
|
return Dimension.endDimension(builder);
|
|
}
|
|
}
|
|
fbs.Dimension = Dimension;
|
|
})(fbs = experimental.fbs || (experimental.fbs = {}));
|
|
})(experimental = onnxruntime.experimental || (onnxruntime.experimental = {}));
|
|
})(onnxruntime = exports.onnxruntime || (exports.onnxruntime = {}));
|
|
/**
|
|
* @constructor
|
|
*/
|
|
(function (onnxruntime) {
|
|
var experimental;
|
|
(function (experimental) {
|
|
var fbs;
|
|
(function (fbs) {
|
|
class DimensionValue {
|
|
constructor() {
|
|
this.bb = null;
|
|
this.bb_pos = 0;
|
|
}
|
|
/**
|
|
* @param number i
|
|
* @param flatbuffers.ByteBuffer bb
|
|
* @returns DimensionValue
|
|
*/
|
|
__init(i, bb) {
|
|
this.bb_pos = i;
|
|
this.bb = bb;
|
|
return this;
|
|
}
|
|
/**
|
|
* @param flatbuffers.ByteBuffer bb
|
|
* @param DimensionValue= obj
|
|
* @returns DimensionValue
|
|
*/
|
|
static getRootAsDimensionValue(bb, obj) {
|
|
return (obj || new DimensionValue()).__init(bb.readInt32(bb.position()) + bb.position(), bb);
|
|
}
|
|
/**
|
|
* @param flatbuffers.ByteBuffer bb
|
|
* @param DimensionValue= obj
|
|
* @returns DimensionValue
|
|
*/
|
|
static getSizePrefixedRootAsDimensionValue(bb, obj) {
|
|
bb.setPosition(bb.position() + flatbuffers_1.flatbuffers.SIZE_PREFIX_LENGTH);
|
|
return (obj || new DimensionValue()).__init(bb.readInt32(bb.position()) + bb.position(), bb);
|
|
}
|
|
/**
|
|
* @returns onnxruntime.experimental.fbs.DimensionValueType
|
|
*/
|
|
dimType() {
|
|
let offset = this.bb.__offset(this.bb_pos, 4);
|
|
return offset ? /** */ (this.bb.readInt8(this.bb_pos + offset)) :
|
|
onnxruntime.experimental.fbs.DimensionValueType.UNKNOWN;
|
|
}
|
|
/**
|
|
* @returns flatbuffers.Long
|
|
*/
|
|
dimValue() {
|
|
let offset = this.bb.__offset(this.bb_pos, 6);
|
|
return offset ? this.bb.readInt64(this.bb_pos + offset) : this.bb.createLong(0, 0);
|
|
}
|
|
dimParam(optionalEncoding) {
|
|
let offset = this.bb.__offset(this.bb_pos, 8);
|
|
return offset ? this.bb.__string(this.bb_pos + offset, optionalEncoding) : null;
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
*/
|
|
static startDimensionValue(builder) {
|
|
builder.startObject(3);
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @param onnxruntime.experimental.fbs.DimensionValueType dimType
|
|
*/
|
|
static addDimType(builder, dimType) {
|
|
builder.addFieldInt8(0, dimType, onnxruntime.experimental.fbs.DimensionValueType.UNKNOWN);
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @param flatbuffers.Long dimValue
|
|
*/
|
|
static addDimValue(builder, dimValue) {
|
|
builder.addFieldInt64(1, dimValue, builder.createLong(0, 0));
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @param flatbuffers.Offset dimParamOffset
|
|
*/
|
|
static addDimParam(builder, dimParamOffset) {
|
|
builder.addFieldOffset(2, dimParamOffset, 0);
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @returns flatbuffers.Offset
|
|
*/
|
|
static endDimensionValue(builder) {
|
|
let offset = builder.endObject();
|
|
return offset;
|
|
}
|
|
static createDimensionValue(builder, dimType, dimValue, dimParamOffset) {
|
|
DimensionValue.startDimensionValue(builder);
|
|
DimensionValue.addDimType(builder, dimType);
|
|
DimensionValue.addDimValue(builder, dimValue);
|
|
DimensionValue.addDimParam(builder, dimParamOffset);
|
|
return DimensionValue.endDimensionValue(builder);
|
|
}
|
|
}
|
|
fbs.DimensionValue = DimensionValue;
|
|
})(fbs = experimental.fbs || (experimental.fbs = {}));
|
|
})(experimental = onnxruntime.experimental || (onnxruntime.experimental = {}));
|
|
})(onnxruntime = exports.onnxruntime || (exports.onnxruntime = {}));
|
|
/**
|
|
* @constructor
|
|
*/
|
|
(function (onnxruntime) {
|
|
var experimental;
|
|
(function (experimental) {
|
|
var fbs;
|
|
(function (fbs) {
|
|
class TensorTypeAndShape {
|
|
constructor() {
|
|
this.bb = null;
|
|
this.bb_pos = 0;
|
|
}
|
|
/**
|
|
* @param number i
|
|
* @param flatbuffers.ByteBuffer bb
|
|
* @returns TensorTypeAndShape
|
|
*/
|
|
__init(i, bb) {
|
|
this.bb_pos = i;
|
|
this.bb = bb;
|
|
return this;
|
|
}
|
|
/**
|
|
* @param flatbuffers.ByteBuffer bb
|
|
* @param TensorTypeAndShape= obj
|
|
* @returns TensorTypeAndShape
|
|
*/
|
|
static getRootAsTensorTypeAndShape(bb, obj) {
|
|
return (obj || new TensorTypeAndShape()).__init(bb.readInt32(bb.position()) + bb.position(), bb);
|
|
}
|
|
/**
|
|
* @param flatbuffers.ByteBuffer bb
|
|
* @param TensorTypeAndShape= obj
|
|
* @returns TensorTypeAndShape
|
|
*/
|
|
static getSizePrefixedRootAsTensorTypeAndShape(bb, obj) {
|
|
bb.setPosition(bb.position() + flatbuffers_1.flatbuffers.SIZE_PREFIX_LENGTH);
|
|
return (obj || new TensorTypeAndShape()).__init(bb.readInt32(bb.position()) + bb.position(), bb);
|
|
}
|
|
/**
|
|
* @returns onnxruntime.experimental.fbs.TensorDataType
|
|
*/
|
|
elemType() {
|
|
let offset = this.bb.__offset(this.bb_pos, 4);
|
|
return offset ? /** */ (this.bb.readInt32(this.bb_pos + offset)) :
|
|
onnxruntime.experimental.fbs.TensorDataType.UNDEFINED;
|
|
}
|
|
/**
|
|
* @param onnxruntime.experimental.fbs.Shape= obj
|
|
* @returns onnxruntime.experimental.fbs.Shape|null
|
|
*/
|
|
shape(obj) {
|
|
let offset = this.bb.__offset(this.bb_pos, 6);
|
|
return offset ? (obj || new onnxruntime.experimental.fbs.Shape())
|
|
.__init(this.bb.__indirect(this.bb_pos + offset), this.bb) :
|
|
null;
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
*/
|
|
static startTensorTypeAndShape(builder) {
|
|
builder.startObject(2);
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @param onnxruntime.experimental.fbs.TensorDataType elemType
|
|
*/
|
|
static addElemType(builder, elemType) {
|
|
builder.addFieldInt32(0, elemType, onnxruntime.experimental.fbs.TensorDataType.UNDEFINED);
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @param flatbuffers.Offset shapeOffset
|
|
*/
|
|
static addShape(builder, shapeOffset) {
|
|
builder.addFieldOffset(1, shapeOffset, 0);
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @returns flatbuffers.Offset
|
|
*/
|
|
static endTensorTypeAndShape(builder) {
|
|
let offset = builder.endObject();
|
|
return offset;
|
|
}
|
|
static createTensorTypeAndShape(builder, elemType, shapeOffset) {
|
|
TensorTypeAndShape.startTensorTypeAndShape(builder);
|
|
TensorTypeAndShape.addElemType(builder, elemType);
|
|
TensorTypeAndShape.addShape(builder, shapeOffset);
|
|
return TensorTypeAndShape.endTensorTypeAndShape(builder);
|
|
}
|
|
}
|
|
fbs.TensorTypeAndShape = TensorTypeAndShape;
|
|
})(fbs = experimental.fbs || (experimental.fbs = {}));
|
|
})(experimental = onnxruntime.experimental || (onnxruntime.experimental = {}));
|
|
})(onnxruntime = exports.onnxruntime || (exports.onnxruntime = {}));
|
|
/**
|
|
* @constructor
|
|
*/
|
|
(function (onnxruntime) {
|
|
var experimental;
|
|
(function (experimental) {
|
|
var fbs;
|
|
(function (fbs) {
|
|
class MapType {
|
|
constructor() {
|
|
this.bb = null;
|
|
this.bb_pos = 0;
|
|
}
|
|
/**
|
|
* @param number i
|
|
* @param flatbuffers.ByteBuffer bb
|
|
* @returns MapType
|
|
*/
|
|
__init(i, bb) {
|
|
this.bb_pos = i;
|
|
this.bb = bb;
|
|
return this;
|
|
}
|
|
/**
|
|
* @param flatbuffers.ByteBuffer bb
|
|
* @param MapType= obj
|
|
* @returns MapType
|
|
*/
|
|
static getRootAsMapType(bb, obj) {
|
|
return (obj || new MapType()).__init(bb.readInt32(bb.position()) + bb.position(), bb);
|
|
}
|
|
/**
|
|
* @param flatbuffers.ByteBuffer bb
|
|
* @param MapType= obj
|
|
* @returns MapType
|
|
*/
|
|
static getSizePrefixedRootAsMapType(bb, obj) {
|
|
bb.setPosition(bb.position() + flatbuffers_1.flatbuffers.SIZE_PREFIX_LENGTH);
|
|
return (obj || new MapType()).__init(bb.readInt32(bb.position()) + bb.position(), bb);
|
|
}
|
|
/**
|
|
* @returns onnxruntime.experimental.fbs.TensorDataType
|
|
*/
|
|
keyType() {
|
|
let offset = this.bb.__offset(this.bb_pos, 4);
|
|
return offset ? /** */ (this.bb.readInt32(this.bb_pos + offset)) :
|
|
onnxruntime.experimental.fbs.TensorDataType.UNDEFINED;
|
|
}
|
|
/**
|
|
* @param onnxruntime.experimental.fbs.TypeInfo= obj
|
|
* @returns onnxruntime.experimental.fbs.TypeInfo|null
|
|
*/
|
|
valueType(obj) {
|
|
let offset = this.bb.__offset(this.bb_pos, 6);
|
|
return offset ? (obj || new onnxruntime.experimental.fbs.TypeInfo())
|
|
.__init(this.bb.__indirect(this.bb_pos + offset), this.bb) :
|
|
null;
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
*/
|
|
static startMapType(builder) {
|
|
builder.startObject(2);
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @param onnxruntime.experimental.fbs.TensorDataType keyType
|
|
*/
|
|
static addKeyType(builder, keyType) {
|
|
builder.addFieldInt32(0, keyType, onnxruntime.experimental.fbs.TensorDataType.UNDEFINED);
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @param flatbuffers.Offset valueTypeOffset
|
|
*/
|
|
static addValueType(builder, valueTypeOffset) {
|
|
builder.addFieldOffset(1, valueTypeOffset, 0);
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @returns flatbuffers.Offset
|
|
*/
|
|
static endMapType(builder) {
|
|
let offset = builder.endObject();
|
|
return offset;
|
|
}
|
|
static createMapType(builder, keyType, valueTypeOffset) {
|
|
MapType.startMapType(builder);
|
|
MapType.addKeyType(builder, keyType);
|
|
MapType.addValueType(builder, valueTypeOffset);
|
|
return MapType.endMapType(builder);
|
|
}
|
|
}
|
|
fbs.MapType = MapType;
|
|
})(fbs = experimental.fbs || (experimental.fbs = {}));
|
|
})(experimental = onnxruntime.experimental || (onnxruntime.experimental = {}));
|
|
})(onnxruntime = exports.onnxruntime || (exports.onnxruntime = {}));
|
|
/**
|
|
* @constructor
|
|
*/
|
|
(function (onnxruntime) {
|
|
var experimental;
|
|
(function (experimental) {
|
|
var fbs;
|
|
(function (fbs) {
|
|
class SequenceType {
|
|
constructor() {
|
|
this.bb = null;
|
|
this.bb_pos = 0;
|
|
}
|
|
/**
|
|
* @param number i
|
|
* @param flatbuffers.ByteBuffer bb
|
|
* @returns SequenceType
|
|
*/
|
|
__init(i, bb) {
|
|
this.bb_pos = i;
|
|
this.bb = bb;
|
|
return this;
|
|
}
|
|
/**
|
|
* @param flatbuffers.ByteBuffer bb
|
|
* @param SequenceType= obj
|
|
* @returns SequenceType
|
|
*/
|
|
static getRootAsSequenceType(bb, obj) {
|
|
return (obj || new SequenceType()).__init(bb.readInt32(bb.position()) + bb.position(), bb);
|
|
}
|
|
/**
|
|
* @param flatbuffers.ByteBuffer bb
|
|
* @param SequenceType= obj
|
|
* @returns SequenceType
|
|
*/
|
|
static getSizePrefixedRootAsSequenceType(bb, obj) {
|
|
bb.setPosition(bb.position() + flatbuffers_1.flatbuffers.SIZE_PREFIX_LENGTH);
|
|
return (obj || new SequenceType()).__init(bb.readInt32(bb.position()) + bb.position(), bb);
|
|
}
|
|
/**
|
|
* @param onnxruntime.experimental.fbs.TypeInfo= obj
|
|
* @returns onnxruntime.experimental.fbs.TypeInfo|null
|
|
*/
|
|
elemType(obj) {
|
|
let offset = this.bb.__offset(this.bb_pos, 4);
|
|
return offset ? (obj || new onnxruntime.experimental.fbs.TypeInfo())
|
|
.__init(this.bb.__indirect(this.bb_pos + offset), this.bb) :
|
|
null;
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
*/
|
|
static startSequenceType(builder) {
|
|
builder.startObject(1);
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @param flatbuffers.Offset elemTypeOffset
|
|
*/
|
|
static addElemType(builder, elemTypeOffset) {
|
|
builder.addFieldOffset(0, elemTypeOffset, 0);
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @returns flatbuffers.Offset
|
|
*/
|
|
static endSequenceType(builder) {
|
|
let offset = builder.endObject();
|
|
return offset;
|
|
}
|
|
static createSequenceType(builder, elemTypeOffset) {
|
|
SequenceType.startSequenceType(builder);
|
|
SequenceType.addElemType(builder, elemTypeOffset);
|
|
return SequenceType.endSequenceType(builder);
|
|
}
|
|
}
|
|
fbs.SequenceType = SequenceType;
|
|
})(fbs = experimental.fbs || (experimental.fbs = {}));
|
|
})(experimental = onnxruntime.experimental || (onnxruntime.experimental = {}));
|
|
})(onnxruntime = exports.onnxruntime || (exports.onnxruntime = {}));
|
|
/**
|
|
* @constructor
|
|
*/
|
|
(function (onnxruntime) {
|
|
var experimental;
|
|
(function (experimental) {
|
|
var fbs;
|
|
(function (fbs) {
|
|
class EdgeEnd {
|
|
constructor() {
|
|
this.bb = null;
|
|
this.bb_pos = 0;
|
|
}
|
|
/**
|
|
* @param number i
|
|
* @param flatbuffers.ByteBuffer bb
|
|
* @returns EdgeEnd
|
|
*/
|
|
__init(i, bb) {
|
|
this.bb_pos = i;
|
|
this.bb = bb;
|
|
return this;
|
|
}
|
|
/**
|
|
* @returns number
|
|
*/
|
|
nodeIndex() {
|
|
return this.bb.readUint32(this.bb_pos);
|
|
}
|
|
/**
|
|
* @returns number
|
|
*/
|
|
srcArgIndex() {
|
|
return this.bb.readInt32(this.bb_pos + 4);
|
|
}
|
|
/**
|
|
* @returns number
|
|
*/
|
|
dstArgIndex() {
|
|
return this.bb.readInt32(this.bb_pos + 8);
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @param number node_index
|
|
* @param number src_arg_index
|
|
* @param number dst_arg_index
|
|
* @returns flatbuffers.Offset
|
|
*/
|
|
static createEdgeEnd(builder, node_index, src_arg_index, dst_arg_index) {
|
|
builder.prep(4, 12);
|
|
builder.writeInt32(dst_arg_index);
|
|
builder.writeInt32(src_arg_index);
|
|
builder.writeInt32(node_index);
|
|
return builder.offset();
|
|
}
|
|
}
|
|
fbs.EdgeEnd = EdgeEnd;
|
|
})(fbs = experimental.fbs || (experimental.fbs = {}));
|
|
})(experimental = onnxruntime.experimental || (onnxruntime.experimental = {}));
|
|
})(onnxruntime = exports.onnxruntime || (exports.onnxruntime = {}));
|
|
/**
|
|
* @constructor
|
|
*/
|
|
(function (onnxruntime) {
|
|
var experimental;
|
|
(function (experimental) {
|
|
var fbs;
|
|
(function (fbs) {
|
|
class NodeEdge {
|
|
constructor() {
|
|
this.bb = null;
|
|
this.bb_pos = 0;
|
|
}
|
|
/**
|
|
* @param number i
|
|
* @param flatbuffers.ByteBuffer bb
|
|
* @returns NodeEdge
|
|
*/
|
|
__init(i, bb) {
|
|
this.bb_pos = i;
|
|
this.bb = bb;
|
|
return this;
|
|
}
|
|
/**
|
|
* @param flatbuffers.ByteBuffer bb
|
|
* @param NodeEdge= obj
|
|
* @returns NodeEdge
|
|
*/
|
|
static getRootAsNodeEdge(bb, obj) {
|
|
return (obj || new NodeEdge()).__init(bb.readInt32(bb.position()) + bb.position(), bb);
|
|
}
|
|
/**
|
|
* @param flatbuffers.ByteBuffer bb
|
|
* @param NodeEdge= obj
|
|
* @returns NodeEdge
|
|
*/
|
|
static getSizePrefixedRootAsNodeEdge(bb, obj) {
|
|
bb.setPosition(bb.position() + flatbuffers_1.flatbuffers.SIZE_PREFIX_LENGTH);
|
|
return (obj || new NodeEdge()).__init(bb.readInt32(bb.position()) + bb.position(), bb);
|
|
}
|
|
/**
|
|
* @returns number
|
|
*/
|
|
nodeIndex() {
|
|
let offset = this.bb.__offset(this.bb_pos, 4);
|
|
return offset ? this.bb.readUint32(this.bb_pos + offset) : 0;
|
|
}
|
|
/**
|
|
* @param number index
|
|
* @param onnxruntime.experimental.fbs.EdgeEnd= obj
|
|
* @returns onnxruntime.experimental.fbs.EdgeEnd
|
|
*/
|
|
inputEdges(index, obj) {
|
|
let offset = this.bb.__offset(this.bb_pos, 6);
|
|
return offset ? (obj || new onnxruntime.experimental.fbs.EdgeEnd())
|
|
.__init(this.bb.__vector(this.bb_pos + offset) + index * 12, this.bb) :
|
|
null;
|
|
}
|
|
/**
|
|
* @returns number
|
|
*/
|
|
inputEdgesLength() {
|
|
let offset = this.bb.__offset(this.bb_pos, 6);
|
|
return offset ? this.bb.__vector_len(this.bb_pos + offset) : 0;
|
|
}
|
|
/**
|
|
* @param number index
|
|
* @param onnxruntime.experimental.fbs.EdgeEnd= obj
|
|
* @returns onnxruntime.experimental.fbs.EdgeEnd
|
|
*/
|
|
outputEdges(index, obj) {
|
|
let offset = this.bb.__offset(this.bb_pos, 8);
|
|
return offset ? (obj || new onnxruntime.experimental.fbs.EdgeEnd())
|
|
.__init(this.bb.__vector(this.bb_pos + offset) + index * 12, this.bb) :
|
|
null;
|
|
}
|
|
/**
|
|
* @returns number
|
|
*/
|
|
outputEdgesLength() {
|
|
let offset = this.bb.__offset(this.bb_pos, 8);
|
|
return offset ? this.bb.__vector_len(this.bb_pos + offset) : 0;
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
*/
|
|
static startNodeEdge(builder) {
|
|
builder.startObject(3);
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @param number nodeIndex
|
|
*/
|
|
static addNodeIndex(builder, nodeIndex) {
|
|
builder.addFieldInt32(0, nodeIndex, 0);
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @param flatbuffers.Offset inputEdgesOffset
|
|
*/
|
|
static addInputEdges(builder, inputEdgesOffset) {
|
|
builder.addFieldOffset(1, inputEdgesOffset, 0);
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @param number numElems
|
|
*/
|
|
static startInputEdgesVector(builder, numElems) {
|
|
builder.startVector(12, numElems, 4);
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @param flatbuffers.Offset outputEdgesOffset
|
|
*/
|
|
static addOutputEdges(builder, outputEdgesOffset) {
|
|
builder.addFieldOffset(2, outputEdgesOffset, 0);
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @param number numElems
|
|
*/
|
|
static startOutputEdgesVector(builder, numElems) {
|
|
builder.startVector(12, numElems, 4);
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @returns flatbuffers.Offset
|
|
*/
|
|
static endNodeEdge(builder) {
|
|
let offset = builder.endObject();
|
|
return offset;
|
|
}
|
|
static createNodeEdge(builder, nodeIndex, inputEdgesOffset, outputEdgesOffset) {
|
|
NodeEdge.startNodeEdge(builder);
|
|
NodeEdge.addNodeIndex(builder, nodeIndex);
|
|
NodeEdge.addInputEdges(builder, inputEdgesOffset);
|
|
NodeEdge.addOutputEdges(builder, outputEdgesOffset);
|
|
return NodeEdge.endNodeEdge(builder);
|
|
}
|
|
}
|
|
fbs.NodeEdge = NodeEdge;
|
|
})(fbs = experimental.fbs || (experimental.fbs = {}));
|
|
})(experimental = onnxruntime.experimental || (onnxruntime.experimental = {}));
|
|
})(onnxruntime = exports.onnxruntime || (exports.onnxruntime = {}));
|
|
/**
|
|
* @constructor
|
|
*/
|
|
(function (onnxruntime) {
|
|
var experimental;
|
|
(function (experimental) {
|
|
var fbs;
|
|
(function (fbs) {
|
|
class Node {
|
|
constructor() {
|
|
this.bb = null;
|
|
this.bb_pos = 0;
|
|
}
|
|
/**
|
|
* @param number i
|
|
* @param flatbuffers.ByteBuffer bb
|
|
* @returns Node
|
|
*/
|
|
__init(i, bb) {
|
|
this.bb_pos = i;
|
|
this.bb = bb;
|
|
return this;
|
|
}
|
|
/**
|
|
* @param flatbuffers.ByteBuffer bb
|
|
* @param Node= obj
|
|
* @returns Node
|
|
*/
|
|
static getRootAsNode(bb, obj) {
|
|
return (obj || new Node()).__init(bb.readInt32(bb.position()) + bb.position(), bb);
|
|
}
|
|
/**
|
|
* @param flatbuffers.ByteBuffer bb
|
|
* @param Node= obj
|
|
* @returns Node
|
|
*/
|
|
static getSizePrefixedRootAsNode(bb, obj) {
|
|
bb.setPosition(bb.position() + flatbuffers_1.flatbuffers.SIZE_PREFIX_LENGTH);
|
|
return (obj || new Node()).__init(bb.readInt32(bb.position()) + bb.position(), bb);
|
|
}
|
|
name(optionalEncoding) {
|
|
let offset = this.bb.__offset(this.bb_pos, 4);
|
|
return offset ? this.bb.__string(this.bb_pos + offset, optionalEncoding) : null;
|
|
}
|
|
docString(optionalEncoding) {
|
|
let offset = this.bb.__offset(this.bb_pos, 6);
|
|
return offset ? this.bb.__string(this.bb_pos + offset, optionalEncoding) : null;
|
|
}
|
|
domain(optionalEncoding) {
|
|
let offset = this.bb.__offset(this.bb_pos, 8);
|
|
return offset ? this.bb.__string(this.bb_pos + offset, optionalEncoding) : null;
|
|
}
|
|
/**
|
|
* @returns number
|
|
*/
|
|
sinceVersion() {
|
|
let offset = this.bb.__offset(this.bb_pos, 10);
|
|
return offset ? this.bb.readInt32(this.bb_pos + offset) : 0;
|
|
}
|
|
/**
|
|
* @returns number
|
|
*/
|
|
index() {
|
|
let offset = this.bb.__offset(this.bb_pos, 12);
|
|
return offset ? this.bb.readUint32(this.bb_pos + offset) : 0;
|
|
}
|
|
opType(optionalEncoding) {
|
|
let offset = this.bb.__offset(this.bb_pos, 14);
|
|
return offset ? this.bb.__string(this.bb_pos + offset, optionalEncoding) : null;
|
|
}
|
|
/**
|
|
* @returns onnxruntime.experimental.fbs.NodeType
|
|
*/
|
|
type() {
|
|
let offset = this.bb.__offset(this.bb_pos, 16);
|
|
return offset ? /** */ (this.bb.readInt32(this.bb_pos + offset)) :
|
|
onnxruntime.experimental.fbs.NodeType.Primitive;
|
|
}
|
|
executionProviderType(optionalEncoding) {
|
|
let offset = this.bb.__offset(this.bb_pos, 18);
|
|
return offset ? this.bb.__string(this.bb_pos + offset, optionalEncoding) : null;
|
|
}
|
|
inputs(index, optionalEncoding) {
|
|
let offset = this.bb.__offset(this.bb_pos, 20);
|
|
return offset ? this.bb.__string(this.bb.__vector(this.bb_pos + offset) + index * 4, optionalEncoding) : null;
|
|
}
|
|
/**
|
|
* @returns number
|
|
*/
|
|
inputsLength() {
|
|
let offset = this.bb.__offset(this.bb_pos, 20);
|
|
return offset ? this.bb.__vector_len(this.bb_pos + offset) : 0;
|
|
}
|
|
outputs(index, optionalEncoding) {
|
|
let offset = this.bb.__offset(this.bb_pos, 22);
|
|
return offset ? this.bb.__string(this.bb.__vector(this.bb_pos + offset) + index * 4, optionalEncoding) : null;
|
|
}
|
|
/**
|
|
* @returns number
|
|
*/
|
|
outputsLength() {
|
|
let offset = this.bb.__offset(this.bb_pos, 22);
|
|
return offset ? this.bb.__vector_len(this.bb_pos + offset) : 0;
|
|
}
|
|
/**
|
|
* @param number index
|
|
* @param onnxruntime.experimental.fbs.Attribute= obj
|
|
* @returns onnxruntime.experimental.fbs.Attribute
|
|
*/
|
|
attributes(index, obj) {
|
|
let offset = this.bb.__offset(this.bb_pos, 24);
|
|
return offset ? (obj || new onnxruntime.experimental.fbs.Attribute())
|
|
.__init(this.bb.__indirect(this.bb.__vector(this.bb_pos + offset) + index * 4), this.bb) :
|
|
null;
|
|
}
|
|
/**
|
|
* @returns number
|
|
*/
|
|
attributesLength() {
|
|
let offset = this.bb.__offset(this.bb_pos, 24);
|
|
return offset ? this.bb.__vector_len(this.bb_pos + offset) : 0;
|
|
}
|
|
/**
|
|
* @param number index
|
|
* @returns number
|
|
*/
|
|
inputArgCounts(index) {
|
|
let offset = this.bb.__offset(this.bb_pos, 26);
|
|
return offset ? this.bb.readInt32(this.bb.__vector(this.bb_pos + offset) + index * 4) : 0;
|
|
}
|
|
/**
|
|
* @returns number
|
|
*/
|
|
inputArgCountsLength() {
|
|
let offset = this.bb.__offset(this.bb_pos, 26);
|
|
return offset ? this.bb.__vector_len(this.bb_pos + offset) : 0;
|
|
}
|
|
/**
|
|
* @returns Int32Array
|
|
*/
|
|
inputArgCountsArray() {
|
|
let offset = this.bb.__offset(this.bb_pos, 26);
|
|
return offset ?
|
|
new Int32Array(this.bb.bytes().buffer, this.bb.bytes().byteOffset + this.bb.__vector(this.bb_pos + offset), this.bb.__vector_len(this.bb_pos + offset)) :
|
|
null;
|
|
}
|
|
implicitInputs(index, optionalEncoding) {
|
|
let offset = this.bb.__offset(this.bb_pos, 28);
|
|
return offset ? this.bb.__string(this.bb.__vector(this.bb_pos + offset) + index * 4, optionalEncoding) : null;
|
|
}
|
|
/**
|
|
* @returns number
|
|
*/
|
|
implicitInputsLength() {
|
|
let offset = this.bb.__offset(this.bb_pos, 28);
|
|
return offset ? this.bb.__vector_len(this.bb_pos + offset) : 0;
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
*/
|
|
static startNode(builder) {
|
|
builder.startObject(13);
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @param flatbuffers.Offset nameOffset
|
|
*/
|
|
static addName(builder, nameOffset) {
|
|
builder.addFieldOffset(0, nameOffset, 0);
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @param flatbuffers.Offset docStringOffset
|
|
*/
|
|
static addDocString(builder, docStringOffset) {
|
|
builder.addFieldOffset(1, docStringOffset, 0);
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @param flatbuffers.Offset domainOffset
|
|
*/
|
|
static addDomain(builder, domainOffset) {
|
|
builder.addFieldOffset(2, domainOffset, 0);
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @param number sinceVersion
|
|
*/
|
|
static addSinceVersion(builder, sinceVersion) {
|
|
builder.addFieldInt32(3, sinceVersion, 0);
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @param number index
|
|
*/
|
|
static addIndex(builder, index) {
|
|
builder.addFieldInt32(4, index, 0);
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @param flatbuffers.Offset opTypeOffset
|
|
*/
|
|
static addOpType(builder, opTypeOffset) {
|
|
builder.addFieldOffset(5, opTypeOffset, 0);
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @param onnxruntime.experimental.fbs.NodeType type
|
|
*/
|
|
static addType(builder, type) {
|
|
builder.addFieldInt32(6, type, onnxruntime.experimental.fbs.NodeType.Primitive);
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @param flatbuffers.Offset executionProviderTypeOffset
|
|
*/
|
|
static addExecutionProviderType(builder, executionProviderTypeOffset) {
|
|
builder.addFieldOffset(7, executionProviderTypeOffset, 0);
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @param flatbuffers.Offset inputsOffset
|
|
*/
|
|
static addInputs(builder, inputsOffset) {
|
|
builder.addFieldOffset(8, inputsOffset, 0);
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @param Array.<flatbuffers.Offset> data
|
|
* @returns flatbuffers.Offset
|
|
*/
|
|
static createInputsVector(builder, data) {
|
|
builder.startVector(4, data.length, 4);
|
|
for (let i = data.length - 1; i >= 0; i--) {
|
|
builder.addOffset(data[i]);
|
|
}
|
|
return builder.endVector();
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @param number numElems
|
|
*/
|
|
static startInputsVector(builder, numElems) {
|
|
builder.startVector(4, numElems, 4);
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @param flatbuffers.Offset outputsOffset
|
|
*/
|
|
static addOutputs(builder, outputsOffset) {
|
|
builder.addFieldOffset(9, outputsOffset, 0);
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @param Array.<flatbuffers.Offset> data
|
|
* @returns flatbuffers.Offset
|
|
*/
|
|
static createOutputsVector(builder, data) {
|
|
builder.startVector(4, data.length, 4);
|
|
for (let i = data.length - 1; i >= 0; i--) {
|
|
builder.addOffset(data[i]);
|
|
}
|
|
return builder.endVector();
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @param number numElems
|
|
*/
|
|
static startOutputsVector(builder, numElems) {
|
|
builder.startVector(4, numElems, 4);
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @param flatbuffers.Offset attributesOffset
|
|
*/
|
|
static addAttributes(builder, attributesOffset) {
|
|
builder.addFieldOffset(10, attributesOffset, 0);
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @param Array.<flatbuffers.Offset> data
|
|
* @returns flatbuffers.Offset
|
|
*/
|
|
static createAttributesVector(builder, data) {
|
|
builder.startVector(4, data.length, 4);
|
|
for (let i = data.length - 1; i >= 0; i--) {
|
|
builder.addOffset(data[i]);
|
|
}
|
|
return builder.endVector();
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @param number numElems
|
|
*/
|
|
static startAttributesVector(builder, numElems) {
|
|
builder.startVector(4, numElems, 4);
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @param flatbuffers.Offset inputArgCountsOffset
|
|
*/
|
|
static addInputArgCounts(builder, inputArgCountsOffset) {
|
|
builder.addFieldOffset(11, inputArgCountsOffset, 0);
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @param Array.<number> data
|
|
* @returns flatbuffers.Offset
|
|
*/
|
|
static createInputArgCountsVector(builder, data) {
|
|
builder.startVector(4, data.length, 4);
|
|
for (let i = data.length - 1; i >= 0; i--) {
|
|
builder.addInt32(data[i]);
|
|
}
|
|
return builder.endVector();
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @param number numElems
|
|
*/
|
|
static startInputArgCountsVector(builder, numElems) {
|
|
builder.startVector(4, numElems, 4);
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @param flatbuffers.Offset implicitInputsOffset
|
|
*/
|
|
static addImplicitInputs(builder, implicitInputsOffset) {
|
|
builder.addFieldOffset(12, implicitInputsOffset, 0);
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @param Array.<flatbuffers.Offset> data
|
|
* @returns flatbuffers.Offset
|
|
*/
|
|
static createImplicitInputsVector(builder, data) {
|
|
builder.startVector(4, data.length, 4);
|
|
for (let i = data.length - 1; i >= 0; i--) {
|
|
builder.addOffset(data[i]);
|
|
}
|
|
return builder.endVector();
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @param number numElems
|
|
*/
|
|
static startImplicitInputsVector(builder, numElems) {
|
|
builder.startVector(4, numElems, 4);
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @returns flatbuffers.Offset
|
|
*/
|
|
static endNode(builder) {
|
|
let offset = builder.endObject();
|
|
return offset;
|
|
}
|
|
static createNode(builder, nameOffset, docStringOffset, domainOffset, sinceVersion, index, opTypeOffset, type, executionProviderTypeOffset, inputsOffset, outputsOffset, attributesOffset, inputArgCountsOffset, implicitInputsOffset) {
|
|
Node.startNode(builder);
|
|
Node.addName(builder, nameOffset);
|
|
Node.addDocString(builder, docStringOffset);
|
|
Node.addDomain(builder, domainOffset);
|
|
Node.addSinceVersion(builder, sinceVersion);
|
|
Node.addIndex(builder, index);
|
|
Node.addOpType(builder, opTypeOffset);
|
|
Node.addType(builder, type);
|
|
Node.addExecutionProviderType(builder, executionProviderTypeOffset);
|
|
Node.addInputs(builder, inputsOffset);
|
|
Node.addOutputs(builder, outputsOffset);
|
|
Node.addAttributes(builder, attributesOffset);
|
|
Node.addInputArgCounts(builder, inputArgCountsOffset);
|
|
Node.addImplicitInputs(builder, implicitInputsOffset);
|
|
return Node.endNode(builder);
|
|
}
|
|
}
|
|
fbs.Node = Node;
|
|
})(fbs = experimental.fbs || (experimental.fbs = {}));
|
|
})(experimental = onnxruntime.experimental || (onnxruntime.experimental = {}));
|
|
})(onnxruntime = exports.onnxruntime || (exports.onnxruntime = {}));
|
|
/**
|
|
* @constructor
|
|
*/
|
|
(function (onnxruntime) {
|
|
var experimental;
|
|
(function (experimental) {
|
|
var fbs;
|
|
(function (fbs) {
|
|
class ValueInfo {
|
|
constructor() {
|
|
this.bb = null;
|
|
this.bb_pos = 0;
|
|
}
|
|
/**
|
|
* @param number i
|
|
* @param flatbuffers.ByteBuffer bb
|
|
* @returns ValueInfo
|
|
*/
|
|
__init(i, bb) {
|
|
this.bb_pos = i;
|
|
this.bb = bb;
|
|
return this;
|
|
}
|
|
/**
|
|
* @param flatbuffers.ByteBuffer bb
|
|
* @param ValueInfo= obj
|
|
* @returns ValueInfo
|
|
*/
|
|
static getRootAsValueInfo(bb, obj) {
|
|
return (obj || new ValueInfo()).__init(bb.readInt32(bb.position()) + bb.position(), bb);
|
|
}
|
|
/**
|
|
* @param flatbuffers.ByteBuffer bb
|
|
* @param ValueInfo= obj
|
|
* @returns ValueInfo
|
|
*/
|
|
static getSizePrefixedRootAsValueInfo(bb, obj) {
|
|
bb.setPosition(bb.position() + flatbuffers_1.flatbuffers.SIZE_PREFIX_LENGTH);
|
|
return (obj || new ValueInfo()).__init(bb.readInt32(bb.position()) + bb.position(), bb);
|
|
}
|
|
name(optionalEncoding) {
|
|
let offset = this.bb.__offset(this.bb_pos, 4);
|
|
return offset ? this.bb.__string(this.bb_pos + offset, optionalEncoding) : null;
|
|
}
|
|
docString(optionalEncoding) {
|
|
let offset = this.bb.__offset(this.bb_pos, 6);
|
|
return offset ? this.bb.__string(this.bb_pos + offset, optionalEncoding) : null;
|
|
}
|
|
/**
|
|
* @param onnxruntime.experimental.fbs.TypeInfo= obj
|
|
* @returns onnxruntime.experimental.fbs.TypeInfo|null
|
|
*/
|
|
type(obj) {
|
|
let offset = this.bb.__offset(this.bb_pos, 8);
|
|
return offset ? (obj || new onnxruntime.experimental.fbs.TypeInfo())
|
|
.__init(this.bb.__indirect(this.bb_pos + offset), this.bb) :
|
|
null;
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
*/
|
|
static startValueInfo(builder) {
|
|
builder.startObject(3);
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @param flatbuffers.Offset nameOffset
|
|
*/
|
|
static addName(builder, nameOffset) {
|
|
builder.addFieldOffset(0, nameOffset, 0);
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @param flatbuffers.Offset docStringOffset
|
|
*/
|
|
static addDocString(builder, docStringOffset) {
|
|
builder.addFieldOffset(1, docStringOffset, 0);
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @param flatbuffers.Offset typeOffset
|
|
*/
|
|
static addType(builder, typeOffset) {
|
|
builder.addFieldOffset(2, typeOffset, 0);
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @returns flatbuffers.Offset
|
|
*/
|
|
static endValueInfo(builder) {
|
|
let offset = builder.endObject();
|
|
return offset;
|
|
}
|
|
static createValueInfo(builder, nameOffset, docStringOffset, typeOffset) {
|
|
ValueInfo.startValueInfo(builder);
|
|
ValueInfo.addName(builder, nameOffset);
|
|
ValueInfo.addDocString(builder, docStringOffset);
|
|
ValueInfo.addType(builder, typeOffset);
|
|
return ValueInfo.endValueInfo(builder);
|
|
}
|
|
}
|
|
fbs.ValueInfo = ValueInfo;
|
|
})(fbs = experimental.fbs || (experimental.fbs = {}));
|
|
})(experimental = onnxruntime.experimental || (onnxruntime.experimental = {}));
|
|
})(onnxruntime = exports.onnxruntime || (exports.onnxruntime = {}));
|
|
/**
|
|
* @constructor
|
|
*/
|
|
(function (onnxruntime) {
|
|
var experimental;
|
|
(function (experimental) {
|
|
var fbs;
|
|
(function (fbs) {
|
|
class TypeInfo {
|
|
constructor() {
|
|
this.bb = null;
|
|
this.bb_pos = 0;
|
|
}
|
|
/**
|
|
* @param number i
|
|
* @param flatbuffers.ByteBuffer bb
|
|
* @returns TypeInfo
|
|
*/
|
|
__init(i, bb) {
|
|
this.bb_pos = i;
|
|
this.bb = bb;
|
|
return this;
|
|
}
|
|
/**
|
|
* @param flatbuffers.ByteBuffer bb
|
|
* @param TypeInfo= obj
|
|
* @returns TypeInfo
|
|
*/
|
|
static getRootAsTypeInfo(bb, obj) {
|
|
return (obj || new TypeInfo()).__init(bb.readInt32(bb.position()) + bb.position(), bb);
|
|
}
|
|
/**
|
|
* @param flatbuffers.ByteBuffer bb
|
|
* @param TypeInfo= obj
|
|
* @returns TypeInfo
|
|
*/
|
|
static getSizePrefixedRootAsTypeInfo(bb, obj) {
|
|
bb.setPosition(bb.position() + flatbuffers_1.flatbuffers.SIZE_PREFIX_LENGTH);
|
|
return (obj || new TypeInfo()).__init(bb.readInt32(bb.position()) + bb.position(), bb);
|
|
}
|
|
denotation(optionalEncoding) {
|
|
let offset = this.bb.__offset(this.bb_pos, 4);
|
|
return offset ? this.bb.__string(this.bb_pos + offset, optionalEncoding) : null;
|
|
}
|
|
/**
|
|
* @returns onnxruntime.experimental.fbs.TypeInfoValue
|
|
*/
|
|
valueType() {
|
|
let offset = this.bb.__offset(this.bb_pos, 6);
|
|
return offset ? /** */ (this.bb.readUint8(this.bb_pos + offset)) :
|
|
onnxruntime.experimental.fbs.TypeInfoValue.NONE;
|
|
}
|
|
/**
|
|
* @param flatbuffers.Table obj
|
|
* @returns ?flatbuffers.Table
|
|
*/
|
|
value(obj) {
|
|
let offset = this.bb.__offset(this.bb_pos, 8);
|
|
return offset ? this.bb.__union(obj, this.bb_pos + offset) : null;
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
*/
|
|
static startTypeInfo(builder) {
|
|
builder.startObject(3);
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @param flatbuffers.Offset denotationOffset
|
|
*/
|
|
static addDenotation(builder, denotationOffset) {
|
|
builder.addFieldOffset(0, denotationOffset, 0);
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @param onnxruntime.experimental.fbs.TypeInfoValue valueType
|
|
*/
|
|
static addValueType(builder, valueType) {
|
|
builder.addFieldInt8(1, valueType, onnxruntime.experimental.fbs.TypeInfoValue.NONE);
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @param flatbuffers.Offset valueOffset
|
|
*/
|
|
static addValue(builder, valueOffset) {
|
|
builder.addFieldOffset(2, valueOffset, 0);
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @returns flatbuffers.Offset
|
|
*/
|
|
static endTypeInfo(builder) {
|
|
let offset = builder.endObject();
|
|
return offset;
|
|
}
|
|
static createTypeInfo(builder, denotationOffset, valueType, valueOffset) {
|
|
TypeInfo.startTypeInfo(builder);
|
|
TypeInfo.addDenotation(builder, denotationOffset);
|
|
TypeInfo.addValueType(builder, valueType);
|
|
TypeInfo.addValue(builder, valueOffset);
|
|
return TypeInfo.endTypeInfo(builder);
|
|
}
|
|
}
|
|
fbs.TypeInfo = TypeInfo;
|
|
})(fbs = experimental.fbs || (experimental.fbs = {}));
|
|
})(experimental = onnxruntime.experimental || (onnxruntime.experimental = {}));
|
|
})(onnxruntime = exports.onnxruntime || (exports.onnxruntime = {}));
|
|
/**
|
|
* @constructor
|
|
*/
|
|
(function (onnxruntime) {
|
|
var experimental;
|
|
(function (experimental) {
|
|
var fbs;
|
|
(function (fbs) {
|
|
class OperatorSetId {
|
|
constructor() {
|
|
this.bb = null;
|
|
this.bb_pos = 0;
|
|
}
|
|
/**
|
|
* @param number i
|
|
* @param flatbuffers.ByteBuffer bb
|
|
* @returns OperatorSetId
|
|
*/
|
|
__init(i, bb) {
|
|
this.bb_pos = i;
|
|
this.bb = bb;
|
|
return this;
|
|
}
|
|
/**
|
|
* @param flatbuffers.ByteBuffer bb
|
|
* @param OperatorSetId= obj
|
|
* @returns OperatorSetId
|
|
*/
|
|
static getRootAsOperatorSetId(bb, obj) {
|
|
return (obj || new OperatorSetId()).__init(bb.readInt32(bb.position()) + bb.position(), bb);
|
|
}
|
|
/**
|
|
* @param flatbuffers.ByteBuffer bb
|
|
* @param OperatorSetId= obj
|
|
* @returns OperatorSetId
|
|
*/
|
|
static getSizePrefixedRootAsOperatorSetId(bb, obj) {
|
|
bb.setPosition(bb.position() + flatbuffers_1.flatbuffers.SIZE_PREFIX_LENGTH);
|
|
return (obj || new OperatorSetId()).__init(bb.readInt32(bb.position()) + bb.position(), bb);
|
|
}
|
|
domain(optionalEncoding) {
|
|
let offset = this.bb.__offset(this.bb_pos, 4);
|
|
return offset ? this.bb.__string(this.bb_pos + offset, optionalEncoding) : null;
|
|
}
|
|
/**
|
|
* @returns flatbuffers.Long
|
|
*/
|
|
version() {
|
|
let offset = this.bb.__offset(this.bb_pos, 6);
|
|
return offset ? this.bb.readInt64(this.bb_pos + offset) : this.bb.createLong(0, 0);
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
*/
|
|
static startOperatorSetId(builder) {
|
|
builder.startObject(2);
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @param flatbuffers.Offset domainOffset
|
|
*/
|
|
static addDomain(builder, domainOffset) {
|
|
builder.addFieldOffset(0, domainOffset, 0);
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @param flatbuffers.Long version
|
|
*/
|
|
static addVersion(builder, version) {
|
|
builder.addFieldInt64(1, version, builder.createLong(0, 0));
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @returns flatbuffers.Offset
|
|
*/
|
|
static endOperatorSetId(builder) {
|
|
let offset = builder.endObject();
|
|
return offset;
|
|
}
|
|
static createOperatorSetId(builder, domainOffset, version) {
|
|
OperatorSetId.startOperatorSetId(builder);
|
|
OperatorSetId.addDomain(builder, domainOffset);
|
|
OperatorSetId.addVersion(builder, version);
|
|
return OperatorSetId.endOperatorSetId(builder);
|
|
}
|
|
}
|
|
fbs.OperatorSetId = OperatorSetId;
|
|
})(fbs = experimental.fbs || (experimental.fbs = {}));
|
|
})(experimental = onnxruntime.experimental || (onnxruntime.experimental = {}));
|
|
})(onnxruntime = exports.onnxruntime || (exports.onnxruntime = {}));
|
|
/**
|
|
* @constructor
|
|
*/
|
|
(function (onnxruntime) {
|
|
var experimental;
|
|
(function (experimental) {
|
|
var fbs;
|
|
(function (fbs) {
|
|
class Tensor {
|
|
constructor() {
|
|
this.bb = null;
|
|
this.bb_pos = 0;
|
|
}
|
|
/**
|
|
* @param number i
|
|
* @param flatbuffers.ByteBuffer bb
|
|
* @returns Tensor
|
|
*/
|
|
__init(i, bb) {
|
|
this.bb_pos = i;
|
|
this.bb = bb;
|
|
return this;
|
|
}
|
|
/**
|
|
* @param flatbuffers.ByteBuffer bb
|
|
* @param Tensor= obj
|
|
* @returns Tensor
|
|
*/
|
|
static getRootAsTensor(bb, obj) {
|
|
return (obj || new Tensor()).__init(bb.readInt32(bb.position()) + bb.position(), bb);
|
|
}
|
|
/**
|
|
* @param flatbuffers.ByteBuffer bb
|
|
* @param Tensor= obj
|
|
* @returns Tensor
|
|
*/
|
|
static getSizePrefixedRootAsTensor(bb, obj) {
|
|
bb.setPosition(bb.position() + flatbuffers_1.flatbuffers.SIZE_PREFIX_LENGTH);
|
|
return (obj || new Tensor()).__init(bb.readInt32(bb.position()) + bb.position(), bb);
|
|
}
|
|
name(optionalEncoding) {
|
|
let offset = this.bb.__offset(this.bb_pos, 4);
|
|
return offset ? this.bb.__string(this.bb_pos + offset, optionalEncoding) : null;
|
|
}
|
|
docString(optionalEncoding) {
|
|
let offset = this.bb.__offset(this.bb_pos, 6);
|
|
return offset ? this.bb.__string(this.bb_pos + offset, optionalEncoding) : null;
|
|
}
|
|
/**
|
|
* @param number index
|
|
* @returns flatbuffers.Long
|
|
*/
|
|
dims(index) {
|
|
let offset = this.bb.__offset(this.bb_pos, 8);
|
|
return offset ? this.bb.readInt64(this.bb.__vector(this.bb_pos + offset) + index * 8) :
|
|
this.bb.createLong(0, 0);
|
|
}
|
|
/**
|
|
* @returns number
|
|
*/
|
|
dimsLength() {
|
|
let offset = this.bb.__offset(this.bb_pos, 8);
|
|
return offset ? this.bb.__vector_len(this.bb_pos + offset) : 0;
|
|
}
|
|
/**
|
|
* @returns onnxruntime.experimental.fbs.TensorDataType
|
|
*/
|
|
dataType() {
|
|
let offset = this.bb.__offset(this.bb_pos, 10);
|
|
return offset ? /** */ (this.bb.readInt32(this.bb_pos + offset)) :
|
|
onnxruntime.experimental.fbs.TensorDataType.UNDEFINED;
|
|
}
|
|
/**
|
|
* @param number index
|
|
* @returns number
|
|
*/
|
|
rawData(index) {
|
|
let offset = this.bb.__offset(this.bb_pos, 12);
|
|
return offset ? this.bb.readUint8(this.bb.__vector(this.bb_pos + offset) + index) : 0;
|
|
}
|
|
/**
|
|
* @returns number
|
|
*/
|
|
rawDataLength() {
|
|
let offset = this.bb.__offset(this.bb_pos, 12);
|
|
return offset ? this.bb.__vector_len(this.bb_pos + offset) : 0;
|
|
}
|
|
/**
|
|
* @returns Uint8Array
|
|
*/
|
|
rawDataArray() {
|
|
let offset = this.bb.__offset(this.bb_pos, 12);
|
|
return offset ?
|
|
new Uint8Array(this.bb.bytes().buffer, this.bb.bytes().byteOffset + this.bb.__vector(this.bb_pos + offset), this.bb.__vector_len(this.bb_pos + offset)) :
|
|
null;
|
|
}
|
|
stringData(index, optionalEncoding) {
|
|
let offset = this.bb.__offset(this.bb_pos, 14);
|
|
return offset ? this.bb.__string(this.bb.__vector(this.bb_pos + offset) + index * 4, optionalEncoding) : null;
|
|
}
|
|
/**
|
|
* @returns number
|
|
*/
|
|
stringDataLength() {
|
|
let offset = this.bb.__offset(this.bb_pos, 14);
|
|
return offset ? this.bb.__vector_len(this.bb_pos + offset) : 0;
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
*/
|
|
static startTensor(builder) {
|
|
builder.startObject(6);
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @param flatbuffers.Offset nameOffset
|
|
*/
|
|
static addName(builder, nameOffset) {
|
|
builder.addFieldOffset(0, nameOffset, 0);
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @param flatbuffers.Offset docStringOffset
|
|
*/
|
|
static addDocString(builder, docStringOffset) {
|
|
builder.addFieldOffset(1, docStringOffset, 0);
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @param flatbuffers.Offset dimsOffset
|
|
*/
|
|
static addDims(builder, dimsOffset) {
|
|
builder.addFieldOffset(2, dimsOffset, 0);
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @param Array.<flatbuffers.Long> data
|
|
* @returns flatbuffers.Offset
|
|
*/
|
|
static createDimsVector(builder, data) {
|
|
builder.startVector(8, data.length, 8);
|
|
for (let i = data.length - 1; i >= 0; i--) {
|
|
builder.addInt64(data[i]);
|
|
}
|
|
return builder.endVector();
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @param number numElems
|
|
*/
|
|
static startDimsVector(builder, numElems) {
|
|
builder.startVector(8, numElems, 8);
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @param onnxruntime.experimental.fbs.TensorDataType dataType
|
|
*/
|
|
static addDataType(builder, dataType) {
|
|
builder.addFieldInt32(3, dataType, onnxruntime.experimental.fbs.TensorDataType.UNDEFINED);
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @param flatbuffers.Offset rawDataOffset
|
|
*/
|
|
static addRawData(builder, rawDataOffset) {
|
|
builder.addFieldOffset(4, rawDataOffset, 0);
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @param Array.<number> data
|
|
* @returns flatbuffers.Offset
|
|
*/
|
|
static createRawDataVector(builder, data) {
|
|
builder.startVector(1, data.length, 1);
|
|
for (let i = data.length - 1; i >= 0; i--) {
|
|
builder.addInt8(data[i]);
|
|
}
|
|
return builder.endVector();
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @param number numElems
|
|
*/
|
|
static startRawDataVector(builder, numElems) {
|
|
builder.startVector(1, numElems, 1);
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @param flatbuffers.Offset stringDataOffset
|
|
*/
|
|
static addStringData(builder, stringDataOffset) {
|
|
builder.addFieldOffset(5, stringDataOffset, 0);
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @param Array.<flatbuffers.Offset> data
|
|
* @returns flatbuffers.Offset
|
|
*/
|
|
static createStringDataVector(builder, data) {
|
|
builder.startVector(4, data.length, 4);
|
|
for (let i = data.length - 1; i >= 0; i--) {
|
|
builder.addOffset(data[i]);
|
|
}
|
|
return builder.endVector();
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @param number numElems
|
|
*/
|
|
static startStringDataVector(builder, numElems) {
|
|
builder.startVector(4, numElems, 4);
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @returns flatbuffers.Offset
|
|
*/
|
|
static endTensor(builder) {
|
|
let offset = builder.endObject();
|
|
return offset;
|
|
}
|
|
static createTensor(builder, nameOffset, docStringOffset, dimsOffset, dataType, rawDataOffset, stringDataOffset) {
|
|
Tensor.startTensor(builder);
|
|
Tensor.addName(builder, nameOffset);
|
|
Tensor.addDocString(builder, docStringOffset);
|
|
Tensor.addDims(builder, dimsOffset);
|
|
Tensor.addDataType(builder, dataType);
|
|
Tensor.addRawData(builder, rawDataOffset);
|
|
Tensor.addStringData(builder, stringDataOffset);
|
|
return Tensor.endTensor(builder);
|
|
}
|
|
}
|
|
fbs.Tensor = Tensor;
|
|
})(fbs = experimental.fbs || (experimental.fbs = {}));
|
|
})(experimental = onnxruntime.experimental || (onnxruntime.experimental = {}));
|
|
})(onnxruntime = exports.onnxruntime || (exports.onnxruntime = {}));
|
|
/**
|
|
* @constructor
|
|
*/
|
|
(function (onnxruntime) {
|
|
var experimental;
|
|
(function (experimental) {
|
|
var fbs;
|
|
(function (fbs) {
|
|
class SparseTensor {
|
|
constructor() {
|
|
this.bb = null;
|
|
this.bb_pos = 0;
|
|
}
|
|
/**
|
|
* @param number i
|
|
* @param flatbuffers.ByteBuffer bb
|
|
* @returns SparseTensor
|
|
*/
|
|
__init(i, bb) {
|
|
this.bb_pos = i;
|
|
this.bb = bb;
|
|
return this;
|
|
}
|
|
/**
|
|
* @param flatbuffers.ByteBuffer bb
|
|
* @param SparseTensor= obj
|
|
* @returns SparseTensor
|
|
*/
|
|
static getRootAsSparseTensor(bb, obj) {
|
|
return (obj || new SparseTensor()).__init(bb.readInt32(bb.position()) + bb.position(), bb);
|
|
}
|
|
/**
|
|
* @param flatbuffers.ByteBuffer bb
|
|
* @param SparseTensor= obj
|
|
* @returns SparseTensor
|
|
*/
|
|
static getSizePrefixedRootAsSparseTensor(bb, obj) {
|
|
bb.setPosition(bb.position() + flatbuffers_1.flatbuffers.SIZE_PREFIX_LENGTH);
|
|
return (obj || new SparseTensor()).__init(bb.readInt32(bb.position()) + bb.position(), bb);
|
|
}
|
|
/**
|
|
* @param onnxruntime.experimental.fbs.Tensor= obj
|
|
* @returns onnxruntime.experimental.fbs.Tensor|null
|
|
*/
|
|
values(obj) {
|
|
let offset = this.bb.__offset(this.bb_pos, 4);
|
|
return offset ? (obj || new onnxruntime.experimental.fbs.Tensor())
|
|
.__init(this.bb.__indirect(this.bb_pos + offset), this.bb) :
|
|
null;
|
|
}
|
|
/**
|
|
* @param onnxruntime.experimental.fbs.Tensor= obj
|
|
* @returns onnxruntime.experimental.fbs.Tensor|null
|
|
*/
|
|
indices(obj) {
|
|
let offset = this.bb.__offset(this.bb_pos, 6);
|
|
return offset ? (obj || new onnxruntime.experimental.fbs.Tensor())
|
|
.__init(this.bb.__indirect(this.bb_pos + offset), this.bb) :
|
|
null;
|
|
}
|
|
/**
|
|
* @param number index
|
|
* @returns flatbuffers.Long
|
|
*/
|
|
dims(index) {
|
|
let offset = this.bb.__offset(this.bb_pos, 8);
|
|
return offset ? this.bb.readInt64(this.bb.__vector(this.bb_pos + offset) + index * 8) :
|
|
this.bb.createLong(0, 0);
|
|
}
|
|
/**
|
|
* @returns number
|
|
*/
|
|
dimsLength() {
|
|
let offset = this.bb.__offset(this.bb_pos, 8);
|
|
return offset ? this.bb.__vector_len(this.bb_pos + offset) : 0;
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
*/
|
|
static startSparseTensor(builder) {
|
|
builder.startObject(3);
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @param flatbuffers.Offset valuesOffset
|
|
*/
|
|
static addValues(builder, valuesOffset) {
|
|
builder.addFieldOffset(0, valuesOffset, 0);
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @param flatbuffers.Offset indicesOffset
|
|
*/
|
|
static addIndices(builder, indicesOffset) {
|
|
builder.addFieldOffset(1, indicesOffset, 0);
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @param flatbuffers.Offset dimsOffset
|
|
*/
|
|
static addDims(builder, dimsOffset) {
|
|
builder.addFieldOffset(2, dimsOffset, 0);
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @param Array.<flatbuffers.Long> data
|
|
* @returns flatbuffers.Offset
|
|
*/
|
|
static createDimsVector(builder, data) {
|
|
builder.startVector(8, data.length, 8);
|
|
for (let i = data.length - 1; i >= 0; i--) {
|
|
builder.addInt64(data[i]);
|
|
}
|
|
return builder.endVector();
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @param number numElems
|
|
*/
|
|
static startDimsVector(builder, numElems) {
|
|
builder.startVector(8, numElems, 8);
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @returns flatbuffers.Offset
|
|
*/
|
|
static endSparseTensor(builder) {
|
|
let offset = builder.endObject();
|
|
return offset;
|
|
}
|
|
static createSparseTensor(builder, valuesOffset, indicesOffset, dimsOffset) {
|
|
SparseTensor.startSparseTensor(builder);
|
|
SparseTensor.addValues(builder, valuesOffset);
|
|
SparseTensor.addIndices(builder, indicesOffset);
|
|
SparseTensor.addDims(builder, dimsOffset);
|
|
return SparseTensor.endSparseTensor(builder);
|
|
}
|
|
}
|
|
fbs.SparseTensor = SparseTensor;
|
|
})(fbs = experimental.fbs || (experimental.fbs = {}));
|
|
})(experimental = onnxruntime.experimental || (onnxruntime.experimental = {}));
|
|
})(onnxruntime = exports.onnxruntime || (exports.onnxruntime = {}));
|
|
/**
|
|
* @constructor
|
|
*/
|
|
(function (onnxruntime) {
|
|
var experimental;
|
|
(function (experimental) {
|
|
var fbs;
|
|
(function (fbs) {
|
|
class Attribute {
|
|
constructor() {
|
|
this.bb = null;
|
|
this.bb_pos = 0;
|
|
}
|
|
/**
|
|
* @param number i
|
|
* @param flatbuffers.ByteBuffer bb
|
|
* @returns Attribute
|
|
*/
|
|
__init(i, bb) {
|
|
this.bb_pos = i;
|
|
this.bb = bb;
|
|
return this;
|
|
}
|
|
/**
|
|
* @param flatbuffers.ByteBuffer bb
|
|
* @param Attribute= obj
|
|
* @returns Attribute
|
|
*/
|
|
static getRootAsAttribute(bb, obj) {
|
|
return (obj || new Attribute()).__init(bb.readInt32(bb.position()) + bb.position(), bb);
|
|
}
|
|
/**
|
|
* @param flatbuffers.ByteBuffer bb
|
|
* @param Attribute= obj
|
|
* @returns Attribute
|
|
*/
|
|
static getSizePrefixedRootAsAttribute(bb, obj) {
|
|
bb.setPosition(bb.position() + flatbuffers_1.flatbuffers.SIZE_PREFIX_LENGTH);
|
|
return (obj || new Attribute()).__init(bb.readInt32(bb.position()) + bb.position(), bb);
|
|
}
|
|
name(optionalEncoding) {
|
|
let offset = this.bb.__offset(this.bb_pos, 4);
|
|
return offset ? this.bb.__string(this.bb_pos + offset, optionalEncoding) : null;
|
|
}
|
|
docString(optionalEncoding) {
|
|
let offset = this.bb.__offset(this.bb_pos, 6);
|
|
return offset ? this.bb.__string(this.bb_pos + offset, optionalEncoding) : null;
|
|
}
|
|
/**
|
|
* @returns onnxruntime.experimental.fbs.AttributeType
|
|
*/
|
|
type() {
|
|
let offset = this.bb.__offset(this.bb_pos, 8);
|
|
return offset ? /** */ (this.bb.readInt32(this.bb_pos + offset)) :
|
|
onnxruntime.experimental.fbs.AttributeType.UNDEFINED;
|
|
}
|
|
/**
|
|
* @returns number
|
|
*/
|
|
f() {
|
|
let offset = this.bb.__offset(this.bb_pos, 10);
|
|
return offset ? this.bb.readFloat32(this.bb_pos + offset) : 0.0;
|
|
}
|
|
/**
|
|
* @returns flatbuffers.Long
|
|
*/
|
|
i() {
|
|
let offset = this.bb.__offset(this.bb_pos, 12);
|
|
return offset ? this.bb.readInt64(this.bb_pos + offset) : this.bb.createLong(0, 0);
|
|
}
|
|
s(optionalEncoding) {
|
|
let offset = this.bb.__offset(this.bb_pos, 14);
|
|
return offset ? this.bb.__string(this.bb_pos + offset, optionalEncoding) : null;
|
|
}
|
|
/**
|
|
* @param onnxruntime.experimental.fbs.Tensor= obj
|
|
* @returns onnxruntime.experimental.fbs.Tensor|null
|
|
*/
|
|
t(obj) {
|
|
let offset = this.bb.__offset(this.bb_pos, 16);
|
|
return offset ? (obj || new onnxruntime.experimental.fbs.Tensor())
|
|
.__init(this.bb.__indirect(this.bb_pos + offset), this.bb) :
|
|
null;
|
|
}
|
|
/**
|
|
* @param onnxruntime.experimental.fbs.Graph= obj
|
|
* @returns onnxruntime.experimental.fbs.Graph|null
|
|
*/
|
|
g(obj) {
|
|
let offset = this.bb.__offset(this.bb_pos, 18);
|
|
return offset ? (obj || new onnxruntime.experimental.fbs.Graph())
|
|
.__init(this.bb.__indirect(this.bb_pos + offset), this.bb) :
|
|
null;
|
|
}
|
|
/**
|
|
* @param number index
|
|
* @returns number
|
|
*/
|
|
floats(index) {
|
|
let offset = this.bb.__offset(this.bb_pos, 20);
|
|
return offset ? this.bb.readFloat32(this.bb.__vector(this.bb_pos + offset) + index * 4) : 0;
|
|
}
|
|
/**
|
|
* @returns number
|
|
*/
|
|
floatsLength() {
|
|
let offset = this.bb.__offset(this.bb_pos, 20);
|
|
return offset ? this.bb.__vector_len(this.bb_pos + offset) : 0;
|
|
}
|
|
/**
|
|
* @returns Float32Array
|
|
*/
|
|
floatsArray() {
|
|
let offset = this.bb.__offset(this.bb_pos, 20);
|
|
return offset ?
|
|
new Float32Array(this.bb.bytes().buffer, this.bb.bytes().byteOffset + this.bb.__vector(this.bb_pos + offset), this.bb.__vector_len(this.bb_pos + offset)) :
|
|
null;
|
|
}
|
|
/**
|
|
* @param number index
|
|
* @returns flatbuffers.Long
|
|
*/
|
|
ints(index) {
|
|
let offset = this.bb.__offset(this.bb_pos, 22);
|
|
return offset ? this.bb.readInt64(this.bb.__vector(this.bb_pos + offset) + index * 8) :
|
|
this.bb.createLong(0, 0);
|
|
}
|
|
/**
|
|
* @returns number
|
|
*/
|
|
intsLength() {
|
|
let offset = this.bb.__offset(this.bb_pos, 22);
|
|
return offset ? this.bb.__vector_len(this.bb_pos + offset) : 0;
|
|
}
|
|
strings(index, optionalEncoding) {
|
|
let offset = this.bb.__offset(this.bb_pos, 24);
|
|
return offset ? this.bb.__string(this.bb.__vector(this.bb_pos + offset) + index * 4, optionalEncoding) : null;
|
|
}
|
|
/**
|
|
* @returns number
|
|
*/
|
|
stringsLength() {
|
|
let offset = this.bb.__offset(this.bb_pos, 24);
|
|
return offset ? this.bb.__vector_len(this.bb_pos + offset) : 0;
|
|
}
|
|
/**
|
|
* @param number index
|
|
* @param onnxruntime.experimental.fbs.Tensor= obj
|
|
* @returns onnxruntime.experimental.fbs.Tensor
|
|
*/
|
|
tensors(index, obj) {
|
|
let offset = this.bb.__offset(this.bb_pos, 26);
|
|
return offset ? (obj || new onnxruntime.experimental.fbs.Tensor())
|
|
.__init(this.bb.__indirect(this.bb.__vector(this.bb_pos + offset) + index * 4), this.bb) :
|
|
null;
|
|
}
|
|
/**
|
|
* @returns number
|
|
*/
|
|
tensorsLength() {
|
|
let offset = this.bb.__offset(this.bb_pos, 26);
|
|
return offset ? this.bb.__vector_len(this.bb_pos + offset) : 0;
|
|
}
|
|
/**
|
|
* @param number index
|
|
* @param onnxruntime.experimental.fbs.Graph= obj
|
|
* @returns onnxruntime.experimental.fbs.Graph
|
|
*/
|
|
graphs(index, obj) {
|
|
let offset = this.bb.__offset(this.bb_pos, 28);
|
|
return offset ? (obj || new onnxruntime.experimental.fbs.Graph())
|
|
.__init(this.bb.__indirect(this.bb.__vector(this.bb_pos + offset) + index * 4), this.bb) :
|
|
null;
|
|
}
|
|
/**
|
|
* @returns number
|
|
*/
|
|
graphsLength() {
|
|
let offset = this.bb.__offset(this.bb_pos, 28);
|
|
return offset ? this.bb.__vector_len(this.bb_pos + offset) : 0;
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
*/
|
|
static startAttribute(builder) {
|
|
builder.startObject(13);
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @param flatbuffers.Offset nameOffset
|
|
*/
|
|
static addName(builder, nameOffset) {
|
|
builder.addFieldOffset(0, nameOffset, 0);
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @param flatbuffers.Offset docStringOffset
|
|
*/
|
|
static addDocString(builder, docStringOffset) {
|
|
builder.addFieldOffset(1, docStringOffset, 0);
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @param onnxruntime.experimental.fbs.AttributeType type
|
|
*/
|
|
static addType(builder, type) {
|
|
builder.addFieldInt32(2, type, onnxruntime.experimental.fbs.AttributeType.UNDEFINED);
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @param number f
|
|
*/
|
|
static addF(builder, f) {
|
|
builder.addFieldFloat32(3, f, 0.0);
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @param flatbuffers.Long i
|
|
*/
|
|
static addI(builder, i) {
|
|
builder.addFieldInt64(4, i, builder.createLong(0, 0));
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @param flatbuffers.Offset sOffset
|
|
*/
|
|
static addS(builder, sOffset) {
|
|
builder.addFieldOffset(5, sOffset, 0);
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @param flatbuffers.Offset tOffset
|
|
*/
|
|
static addT(builder, tOffset) {
|
|
builder.addFieldOffset(6, tOffset, 0);
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @param flatbuffers.Offset gOffset
|
|
*/
|
|
static addG(builder, gOffset) {
|
|
builder.addFieldOffset(7, gOffset, 0);
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @param flatbuffers.Offset floatsOffset
|
|
*/
|
|
static addFloats(builder, floatsOffset) {
|
|
builder.addFieldOffset(8, floatsOffset, 0);
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @param Array.<number> data
|
|
* @returns flatbuffers.Offset
|
|
*/
|
|
static createFloatsVector(builder, data) {
|
|
builder.startVector(4, data.length, 4);
|
|
for (let i = data.length - 1; i >= 0; i--) {
|
|
builder.addFloat32(data[i]);
|
|
}
|
|
return builder.endVector();
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @param number numElems
|
|
*/
|
|
static startFloatsVector(builder, numElems) {
|
|
builder.startVector(4, numElems, 4);
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @param flatbuffers.Offset intsOffset
|
|
*/
|
|
static addInts(builder, intsOffset) {
|
|
builder.addFieldOffset(9, intsOffset, 0);
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @param Array.<flatbuffers.Long> data
|
|
* @returns flatbuffers.Offset
|
|
*/
|
|
static createIntsVector(builder, data) {
|
|
builder.startVector(8, data.length, 8);
|
|
for (let i = data.length - 1; i >= 0; i--) {
|
|
builder.addInt64(data[i]);
|
|
}
|
|
return builder.endVector();
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @param number numElems
|
|
*/
|
|
static startIntsVector(builder, numElems) {
|
|
builder.startVector(8, numElems, 8);
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @param flatbuffers.Offset stringsOffset
|
|
*/
|
|
static addStrings(builder, stringsOffset) {
|
|
builder.addFieldOffset(10, stringsOffset, 0);
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @param Array.<flatbuffers.Offset> data
|
|
* @returns flatbuffers.Offset
|
|
*/
|
|
static createStringsVector(builder, data) {
|
|
builder.startVector(4, data.length, 4);
|
|
for (let i = data.length - 1; i >= 0; i--) {
|
|
builder.addOffset(data[i]);
|
|
}
|
|
return builder.endVector();
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @param number numElems
|
|
*/
|
|
static startStringsVector(builder, numElems) {
|
|
builder.startVector(4, numElems, 4);
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @param flatbuffers.Offset tensorsOffset
|
|
*/
|
|
static addTensors(builder, tensorsOffset) {
|
|
builder.addFieldOffset(11, tensorsOffset, 0);
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @param Array.<flatbuffers.Offset> data
|
|
* @returns flatbuffers.Offset
|
|
*/
|
|
static createTensorsVector(builder, data) {
|
|
builder.startVector(4, data.length, 4);
|
|
for (let i = data.length - 1; i >= 0; i--) {
|
|
builder.addOffset(data[i]);
|
|
}
|
|
return builder.endVector();
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @param number numElems
|
|
*/
|
|
static startTensorsVector(builder, numElems) {
|
|
builder.startVector(4, numElems, 4);
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @param flatbuffers.Offset graphsOffset
|
|
*/
|
|
static addGraphs(builder, graphsOffset) {
|
|
builder.addFieldOffset(12, graphsOffset, 0);
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @param Array.<flatbuffers.Offset> data
|
|
* @returns flatbuffers.Offset
|
|
*/
|
|
static createGraphsVector(builder, data) {
|
|
builder.startVector(4, data.length, 4);
|
|
for (let i = data.length - 1; i >= 0; i--) {
|
|
builder.addOffset(data[i]);
|
|
}
|
|
return builder.endVector();
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @param number numElems
|
|
*/
|
|
static startGraphsVector(builder, numElems) {
|
|
builder.startVector(4, numElems, 4);
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @returns flatbuffers.Offset
|
|
*/
|
|
static endAttribute(builder) {
|
|
let offset = builder.endObject();
|
|
return offset;
|
|
}
|
|
static createAttribute(builder, nameOffset, docStringOffset, type, f, i, sOffset, tOffset, gOffset, floatsOffset, intsOffset, stringsOffset, tensorsOffset, graphsOffset) {
|
|
Attribute.startAttribute(builder);
|
|
Attribute.addName(builder, nameOffset);
|
|
Attribute.addDocString(builder, docStringOffset);
|
|
Attribute.addType(builder, type);
|
|
Attribute.addF(builder, f);
|
|
Attribute.addI(builder, i);
|
|
Attribute.addS(builder, sOffset);
|
|
Attribute.addT(builder, tOffset);
|
|
Attribute.addG(builder, gOffset);
|
|
Attribute.addFloats(builder, floatsOffset);
|
|
Attribute.addInts(builder, intsOffset);
|
|
Attribute.addStrings(builder, stringsOffset);
|
|
Attribute.addTensors(builder, tensorsOffset);
|
|
Attribute.addGraphs(builder, graphsOffset);
|
|
return Attribute.endAttribute(builder);
|
|
}
|
|
}
|
|
fbs.Attribute = Attribute;
|
|
})(fbs = experimental.fbs || (experimental.fbs = {}));
|
|
})(experimental = onnxruntime.experimental || (onnxruntime.experimental = {}));
|
|
})(onnxruntime = exports.onnxruntime || (exports.onnxruntime = {}));
|
|
/**
|
|
* @constructor
|
|
*/
|
|
(function (onnxruntime) {
|
|
var experimental;
|
|
(function (experimental) {
|
|
var fbs;
|
|
(function (fbs) {
|
|
class Graph {
|
|
constructor() {
|
|
this.bb = null;
|
|
this.bb_pos = 0;
|
|
}
|
|
/**
|
|
* @param number i
|
|
* @param flatbuffers.ByteBuffer bb
|
|
* @returns Graph
|
|
*/
|
|
__init(i, bb) {
|
|
this.bb_pos = i;
|
|
this.bb = bb;
|
|
return this;
|
|
}
|
|
/**
|
|
* @param flatbuffers.ByteBuffer bb
|
|
* @param Graph= obj
|
|
* @returns Graph
|
|
*/
|
|
static getRootAsGraph(bb, obj) {
|
|
return (obj || new Graph()).__init(bb.readInt32(bb.position()) + bb.position(), bb);
|
|
}
|
|
/**
|
|
* @param flatbuffers.ByteBuffer bb
|
|
* @param Graph= obj
|
|
* @returns Graph
|
|
*/
|
|
static getSizePrefixedRootAsGraph(bb, obj) {
|
|
bb.setPosition(bb.position() + flatbuffers_1.flatbuffers.SIZE_PREFIX_LENGTH);
|
|
return (obj || new Graph()).__init(bb.readInt32(bb.position()) + bb.position(), bb);
|
|
}
|
|
/**
|
|
* @param number index
|
|
* @param onnxruntime.experimental.fbs.Tensor= obj
|
|
* @returns onnxruntime.experimental.fbs.Tensor
|
|
*/
|
|
initializers(index, obj) {
|
|
let offset = this.bb.__offset(this.bb_pos, 4);
|
|
return offset ? (obj || new onnxruntime.experimental.fbs.Tensor())
|
|
.__init(this.bb.__indirect(this.bb.__vector(this.bb_pos + offset) + index * 4), this.bb) :
|
|
null;
|
|
}
|
|
/**
|
|
* @returns number
|
|
*/
|
|
initializersLength() {
|
|
let offset = this.bb.__offset(this.bb_pos, 4);
|
|
return offset ? this.bb.__vector_len(this.bb_pos + offset) : 0;
|
|
}
|
|
/**
|
|
* @param number index
|
|
* @param onnxruntime.experimental.fbs.ValueInfo= obj
|
|
* @returns onnxruntime.experimental.fbs.ValueInfo
|
|
*/
|
|
nodeArgs(index, obj) {
|
|
let offset = this.bb.__offset(this.bb_pos, 6);
|
|
return offset ? (obj || new onnxruntime.experimental.fbs.ValueInfo())
|
|
.__init(this.bb.__indirect(this.bb.__vector(this.bb_pos + offset) + index * 4), this.bb) :
|
|
null;
|
|
}
|
|
/**
|
|
* @returns number
|
|
*/
|
|
nodeArgsLength() {
|
|
let offset = this.bb.__offset(this.bb_pos, 6);
|
|
return offset ? this.bb.__vector_len(this.bb_pos + offset) : 0;
|
|
}
|
|
/**
|
|
* @param number index
|
|
* @param onnxruntime.experimental.fbs.Node= obj
|
|
* @returns onnxruntime.experimental.fbs.Node
|
|
*/
|
|
nodes(index, obj) {
|
|
let offset = this.bb.__offset(this.bb_pos, 8);
|
|
return offset ? (obj || new onnxruntime.experimental.fbs.Node())
|
|
.__init(this.bb.__indirect(this.bb.__vector(this.bb_pos + offset) + index * 4), this.bb) :
|
|
null;
|
|
}
|
|
/**
|
|
* @returns number
|
|
*/
|
|
nodesLength() {
|
|
let offset = this.bb.__offset(this.bb_pos, 8);
|
|
return offset ? this.bb.__vector_len(this.bb_pos + offset) : 0;
|
|
}
|
|
/**
|
|
* @returns number
|
|
*/
|
|
maxNodeIndex() {
|
|
let offset = this.bb.__offset(this.bb_pos, 10);
|
|
return offset ? this.bb.readUint32(this.bb_pos + offset) : 0;
|
|
}
|
|
/**
|
|
* @param number index
|
|
* @param onnxruntime.experimental.fbs.NodeEdge= obj
|
|
* @returns onnxruntime.experimental.fbs.NodeEdge
|
|
*/
|
|
nodeEdges(index, obj) {
|
|
let offset = this.bb.__offset(this.bb_pos, 12);
|
|
return offset ? (obj || new onnxruntime.experimental.fbs.NodeEdge())
|
|
.__init(this.bb.__indirect(this.bb.__vector(this.bb_pos + offset) + index * 4), this.bb) :
|
|
null;
|
|
}
|
|
/**
|
|
* @returns number
|
|
*/
|
|
nodeEdgesLength() {
|
|
let offset = this.bb.__offset(this.bb_pos, 12);
|
|
return offset ? this.bb.__vector_len(this.bb_pos + offset) : 0;
|
|
}
|
|
inputs(index, optionalEncoding) {
|
|
let offset = this.bb.__offset(this.bb_pos, 14);
|
|
return offset ? this.bb.__string(this.bb.__vector(this.bb_pos + offset) + index * 4, optionalEncoding) : null;
|
|
}
|
|
/**
|
|
* @returns number
|
|
*/
|
|
inputsLength() {
|
|
let offset = this.bb.__offset(this.bb_pos, 14);
|
|
return offset ? this.bb.__vector_len(this.bb_pos + offset) : 0;
|
|
}
|
|
outputs(index, optionalEncoding) {
|
|
let offset = this.bb.__offset(this.bb_pos, 16);
|
|
return offset ? this.bb.__string(this.bb.__vector(this.bb_pos + offset) + index * 4, optionalEncoding) : null;
|
|
}
|
|
/**
|
|
* @returns number
|
|
*/
|
|
outputsLength() {
|
|
let offset = this.bb.__offset(this.bb_pos, 16);
|
|
return offset ? this.bb.__vector_len(this.bb_pos + offset) : 0;
|
|
}
|
|
/**
|
|
* @param number index
|
|
* @param onnxruntime.experimental.fbs.SparseTensor= obj
|
|
* @returns onnxruntime.experimental.fbs.SparseTensor
|
|
*/
|
|
sparseInitializers(index, obj) {
|
|
let offset = this.bb.__offset(this.bb_pos, 18);
|
|
return offset ? (obj || new onnxruntime.experimental.fbs.SparseTensor())
|
|
.__init(this.bb.__indirect(this.bb.__vector(this.bb_pos + offset) + index * 4), this.bb) :
|
|
null;
|
|
}
|
|
/**
|
|
* @returns number
|
|
*/
|
|
sparseInitializersLength() {
|
|
let offset = this.bb.__offset(this.bb_pos, 18);
|
|
return offset ? this.bb.__vector_len(this.bb_pos + offset) : 0;
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
*/
|
|
static startGraph(builder) {
|
|
builder.startObject(8);
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @param flatbuffers.Offset initializersOffset
|
|
*/
|
|
static addInitializers(builder, initializersOffset) {
|
|
builder.addFieldOffset(0, initializersOffset, 0);
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @param Array.<flatbuffers.Offset> data
|
|
* @returns flatbuffers.Offset
|
|
*/
|
|
static createInitializersVector(builder, data) {
|
|
builder.startVector(4, data.length, 4);
|
|
for (let i = data.length - 1; i >= 0; i--) {
|
|
builder.addOffset(data[i]);
|
|
}
|
|
return builder.endVector();
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @param number numElems
|
|
*/
|
|
static startInitializersVector(builder, numElems) {
|
|
builder.startVector(4, numElems, 4);
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @param flatbuffers.Offset nodeArgsOffset
|
|
*/
|
|
static addNodeArgs(builder, nodeArgsOffset) {
|
|
builder.addFieldOffset(1, nodeArgsOffset, 0);
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @param Array.<flatbuffers.Offset> data
|
|
* @returns flatbuffers.Offset
|
|
*/
|
|
static createNodeArgsVector(builder, data) {
|
|
builder.startVector(4, data.length, 4);
|
|
for (let i = data.length - 1; i >= 0; i--) {
|
|
builder.addOffset(data[i]);
|
|
}
|
|
return builder.endVector();
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @param number numElems
|
|
*/
|
|
static startNodeArgsVector(builder, numElems) {
|
|
builder.startVector(4, numElems, 4);
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @param flatbuffers.Offset nodesOffset
|
|
*/
|
|
static addNodes(builder, nodesOffset) {
|
|
builder.addFieldOffset(2, nodesOffset, 0);
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @param Array.<flatbuffers.Offset> data
|
|
* @returns flatbuffers.Offset
|
|
*/
|
|
static createNodesVector(builder, data) {
|
|
builder.startVector(4, data.length, 4);
|
|
for (let i = data.length - 1; i >= 0; i--) {
|
|
builder.addOffset(data[i]);
|
|
}
|
|
return builder.endVector();
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @param number numElems
|
|
*/
|
|
static startNodesVector(builder, numElems) {
|
|
builder.startVector(4, numElems, 4);
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @param number maxNodeIndex
|
|
*/
|
|
static addMaxNodeIndex(builder, maxNodeIndex) {
|
|
builder.addFieldInt32(3, maxNodeIndex, 0);
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @param flatbuffers.Offset nodeEdgesOffset
|
|
*/
|
|
static addNodeEdges(builder, nodeEdgesOffset) {
|
|
builder.addFieldOffset(4, nodeEdgesOffset, 0);
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @param Array.<flatbuffers.Offset> data
|
|
* @returns flatbuffers.Offset
|
|
*/
|
|
static createNodeEdgesVector(builder, data) {
|
|
builder.startVector(4, data.length, 4);
|
|
for (let i = data.length - 1; i >= 0; i--) {
|
|
builder.addOffset(data[i]);
|
|
}
|
|
return builder.endVector();
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @param number numElems
|
|
*/
|
|
static startNodeEdgesVector(builder, numElems) {
|
|
builder.startVector(4, numElems, 4);
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @param flatbuffers.Offset inputsOffset
|
|
*/
|
|
static addInputs(builder, inputsOffset) {
|
|
builder.addFieldOffset(5, inputsOffset, 0);
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @param Array.<flatbuffers.Offset> data
|
|
* @returns flatbuffers.Offset
|
|
*/
|
|
static createInputsVector(builder, data) {
|
|
builder.startVector(4, data.length, 4);
|
|
for (let i = data.length - 1; i >= 0; i--) {
|
|
builder.addOffset(data[i]);
|
|
}
|
|
return builder.endVector();
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @param number numElems
|
|
*/
|
|
static startInputsVector(builder, numElems) {
|
|
builder.startVector(4, numElems, 4);
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @param flatbuffers.Offset outputsOffset
|
|
*/
|
|
static addOutputs(builder, outputsOffset) {
|
|
builder.addFieldOffset(6, outputsOffset, 0);
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @param Array.<flatbuffers.Offset> data
|
|
* @returns flatbuffers.Offset
|
|
*/
|
|
static createOutputsVector(builder, data) {
|
|
builder.startVector(4, data.length, 4);
|
|
for (let i = data.length - 1; i >= 0; i--) {
|
|
builder.addOffset(data[i]);
|
|
}
|
|
return builder.endVector();
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @param number numElems
|
|
*/
|
|
static startOutputsVector(builder, numElems) {
|
|
builder.startVector(4, numElems, 4);
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @param flatbuffers.Offset sparseInitializersOffset
|
|
*/
|
|
static addSparseInitializers(builder, sparseInitializersOffset) {
|
|
builder.addFieldOffset(7, sparseInitializersOffset, 0);
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @param Array.<flatbuffers.Offset> data
|
|
* @returns flatbuffers.Offset
|
|
*/
|
|
static createSparseInitializersVector(builder, data) {
|
|
builder.startVector(4, data.length, 4);
|
|
for (let i = data.length - 1; i >= 0; i--) {
|
|
builder.addOffset(data[i]);
|
|
}
|
|
return builder.endVector();
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @param number numElems
|
|
*/
|
|
static startSparseInitializersVector(builder, numElems) {
|
|
builder.startVector(4, numElems, 4);
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @returns flatbuffers.Offset
|
|
*/
|
|
static endGraph(builder) {
|
|
let offset = builder.endObject();
|
|
return offset;
|
|
}
|
|
static createGraph(builder, initializersOffset, nodeArgsOffset, nodesOffset, maxNodeIndex, nodeEdgesOffset, inputsOffset, outputsOffset, sparseInitializersOffset) {
|
|
Graph.startGraph(builder);
|
|
Graph.addInitializers(builder, initializersOffset);
|
|
Graph.addNodeArgs(builder, nodeArgsOffset);
|
|
Graph.addNodes(builder, nodesOffset);
|
|
Graph.addMaxNodeIndex(builder, maxNodeIndex);
|
|
Graph.addNodeEdges(builder, nodeEdgesOffset);
|
|
Graph.addInputs(builder, inputsOffset);
|
|
Graph.addOutputs(builder, outputsOffset);
|
|
Graph.addSparseInitializers(builder, sparseInitializersOffset);
|
|
return Graph.endGraph(builder);
|
|
}
|
|
}
|
|
fbs.Graph = Graph;
|
|
})(fbs = experimental.fbs || (experimental.fbs = {}));
|
|
})(experimental = onnxruntime.experimental || (onnxruntime.experimental = {}));
|
|
})(onnxruntime = exports.onnxruntime || (exports.onnxruntime = {}));
|
|
/**
|
|
* @constructor
|
|
*/
|
|
(function (onnxruntime) {
|
|
var experimental;
|
|
(function (experimental) {
|
|
var fbs;
|
|
(function (fbs) {
|
|
class Model {
|
|
constructor() {
|
|
this.bb = null;
|
|
this.bb_pos = 0;
|
|
}
|
|
/**
|
|
* @param number i
|
|
* @param flatbuffers.ByteBuffer bb
|
|
* @returns Model
|
|
*/
|
|
__init(i, bb) {
|
|
this.bb_pos = i;
|
|
this.bb = bb;
|
|
return this;
|
|
}
|
|
/**
|
|
* @param flatbuffers.ByteBuffer bb
|
|
* @param Model= obj
|
|
* @returns Model
|
|
*/
|
|
static getRootAsModel(bb, obj) {
|
|
return (obj || new Model()).__init(bb.readInt32(bb.position()) + bb.position(), bb);
|
|
}
|
|
/**
|
|
* @param flatbuffers.ByteBuffer bb
|
|
* @param Model= obj
|
|
* @returns Model
|
|
*/
|
|
static getSizePrefixedRootAsModel(bb, obj) {
|
|
bb.setPosition(bb.position() + flatbuffers_1.flatbuffers.SIZE_PREFIX_LENGTH);
|
|
return (obj || new Model()).__init(bb.readInt32(bb.position()) + bb.position(), bb);
|
|
}
|
|
/**
|
|
* @returns flatbuffers.Long
|
|
*/
|
|
irVersion() {
|
|
let offset = this.bb.__offset(this.bb_pos, 4);
|
|
return offset ? this.bb.readInt64(this.bb_pos + offset) : this.bb.createLong(0, 0);
|
|
}
|
|
/**
|
|
* @param number index
|
|
* @param onnxruntime.experimental.fbs.OperatorSetId= obj
|
|
* @returns onnxruntime.experimental.fbs.OperatorSetId
|
|
*/
|
|
opsetImport(index, obj) {
|
|
let offset = this.bb.__offset(this.bb_pos, 6);
|
|
return offset ? (obj || new onnxruntime.experimental.fbs.OperatorSetId())
|
|
.__init(this.bb.__indirect(this.bb.__vector(this.bb_pos + offset) + index * 4), this.bb) :
|
|
null;
|
|
}
|
|
/**
|
|
* @returns number
|
|
*/
|
|
opsetImportLength() {
|
|
let offset = this.bb.__offset(this.bb_pos, 6);
|
|
return offset ? this.bb.__vector_len(this.bb_pos + offset) : 0;
|
|
}
|
|
producerName(optionalEncoding) {
|
|
let offset = this.bb.__offset(this.bb_pos, 8);
|
|
return offset ? this.bb.__string(this.bb_pos + offset, optionalEncoding) : null;
|
|
}
|
|
producerVersion(optionalEncoding) {
|
|
let offset = this.bb.__offset(this.bb_pos, 10);
|
|
return offset ? this.bb.__string(this.bb_pos + offset, optionalEncoding) : null;
|
|
}
|
|
domain(optionalEncoding) {
|
|
let offset = this.bb.__offset(this.bb_pos, 12);
|
|
return offset ? this.bb.__string(this.bb_pos + offset, optionalEncoding) : null;
|
|
}
|
|
/**
|
|
* @returns flatbuffers.Long
|
|
*/
|
|
modelVersion() {
|
|
let offset = this.bb.__offset(this.bb_pos, 14);
|
|
return offset ? this.bb.readInt64(this.bb_pos + offset) : this.bb.createLong(0, 0);
|
|
}
|
|
docString(optionalEncoding) {
|
|
let offset = this.bb.__offset(this.bb_pos, 16);
|
|
return offset ? this.bb.__string(this.bb_pos + offset, optionalEncoding) : null;
|
|
}
|
|
/**
|
|
* @param onnxruntime.experimental.fbs.Graph= obj
|
|
* @returns onnxruntime.experimental.fbs.Graph|null
|
|
*/
|
|
graph(obj) {
|
|
let offset = this.bb.__offset(this.bb_pos, 18);
|
|
return offset ? (obj || new onnxruntime.experimental.fbs.Graph())
|
|
.__init(this.bb.__indirect(this.bb_pos + offset), this.bb) :
|
|
null;
|
|
}
|
|
graphDocString(optionalEncoding) {
|
|
let offset = this.bb.__offset(this.bb_pos, 20);
|
|
return offset ? this.bb.__string(this.bb_pos + offset, optionalEncoding) : null;
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
*/
|
|
static startModel(builder) {
|
|
builder.startObject(9);
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @param flatbuffers.Long irVersion
|
|
*/
|
|
static addIrVersion(builder, irVersion) {
|
|
builder.addFieldInt64(0, irVersion, builder.createLong(0, 0));
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @param flatbuffers.Offset opsetImportOffset
|
|
*/
|
|
static addOpsetImport(builder, opsetImportOffset) {
|
|
builder.addFieldOffset(1, opsetImportOffset, 0);
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @param Array.<flatbuffers.Offset> data
|
|
* @returns flatbuffers.Offset
|
|
*/
|
|
static createOpsetImportVector(builder, data) {
|
|
builder.startVector(4, data.length, 4);
|
|
for (let i = data.length - 1; i >= 0; i--) {
|
|
builder.addOffset(data[i]);
|
|
}
|
|
return builder.endVector();
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @param number numElems
|
|
*/
|
|
static startOpsetImportVector(builder, numElems) {
|
|
builder.startVector(4, numElems, 4);
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @param flatbuffers.Offset producerNameOffset
|
|
*/
|
|
static addProducerName(builder, producerNameOffset) {
|
|
builder.addFieldOffset(2, producerNameOffset, 0);
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @param flatbuffers.Offset producerVersionOffset
|
|
*/
|
|
static addProducerVersion(builder, producerVersionOffset) {
|
|
builder.addFieldOffset(3, producerVersionOffset, 0);
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @param flatbuffers.Offset domainOffset
|
|
*/
|
|
static addDomain(builder, domainOffset) {
|
|
builder.addFieldOffset(4, domainOffset, 0);
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @param flatbuffers.Long modelVersion
|
|
*/
|
|
static addModelVersion(builder, modelVersion) {
|
|
builder.addFieldInt64(5, modelVersion, builder.createLong(0, 0));
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @param flatbuffers.Offset docStringOffset
|
|
*/
|
|
static addDocString(builder, docStringOffset) {
|
|
builder.addFieldOffset(6, docStringOffset, 0);
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @param flatbuffers.Offset graphOffset
|
|
*/
|
|
static addGraph(builder, graphOffset) {
|
|
builder.addFieldOffset(7, graphOffset, 0);
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @param flatbuffers.Offset graphDocStringOffset
|
|
*/
|
|
static addGraphDocString(builder, graphDocStringOffset) {
|
|
builder.addFieldOffset(8, graphDocStringOffset, 0);
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @returns flatbuffers.Offset
|
|
*/
|
|
static endModel(builder) {
|
|
let offset = builder.endObject();
|
|
return offset;
|
|
}
|
|
static createModel(builder, irVersion, opsetImportOffset, producerNameOffset, producerVersionOffset, domainOffset, modelVersion, docStringOffset, graphOffset, graphDocStringOffset) {
|
|
Model.startModel(builder);
|
|
Model.addIrVersion(builder, irVersion);
|
|
Model.addOpsetImport(builder, opsetImportOffset);
|
|
Model.addProducerName(builder, producerNameOffset);
|
|
Model.addProducerVersion(builder, producerVersionOffset);
|
|
Model.addDomain(builder, domainOffset);
|
|
Model.addModelVersion(builder, modelVersion);
|
|
Model.addDocString(builder, docStringOffset);
|
|
Model.addGraph(builder, graphOffset);
|
|
Model.addGraphDocString(builder, graphDocStringOffset);
|
|
return Model.endModel(builder);
|
|
}
|
|
}
|
|
fbs.Model = Model;
|
|
})(fbs = experimental.fbs || (experimental.fbs = {}));
|
|
})(experimental = onnxruntime.experimental || (onnxruntime.experimental = {}));
|
|
})(onnxruntime = exports.onnxruntime || (exports.onnxruntime = {}));
|
|
/**
|
|
* @constructor
|
|
*/
|
|
(function (onnxruntime) {
|
|
var experimental;
|
|
(function (experimental) {
|
|
var fbs;
|
|
(function (fbs) {
|
|
class KernelCreateInfos {
|
|
constructor() {
|
|
this.bb = null;
|
|
this.bb_pos = 0;
|
|
}
|
|
/**
|
|
* @param number i
|
|
* @param flatbuffers.ByteBuffer bb
|
|
* @returns KernelCreateInfos
|
|
*/
|
|
__init(i, bb) {
|
|
this.bb_pos = i;
|
|
this.bb = bb;
|
|
return this;
|
|
}
|
|
/**
|
|
* @param flatbuffers.ByteBuffer bb
|
|
* @param KernelCreateInfos= obj
|
|
* @returns KernelCreateInfos
|
|
*/
|
|
static getRootAsKernelCreateInfos(bb, obj) {
|
|
return (obj || new KernelCreateInfos()).__init(bb.readInt32(bb.position()) + bb.position(), bb);
|
|
}
|
|
/**
|
|
* @param flatbuffers.ByteBuffer bb
|
|
* @param KernelCreateInfos= obj
|
|
* @returns KernelCreateInfos
|
|
*/
|
|
static getSizePrefixedRootAsKernelCreateInfos(bb, obj) {
|
|
bb.setPosition(bb.position() + flatbuffers_1.flatbuffers.SIZE_PREFIX_LENGTH);
|
|
return (obj || new KernelCreateInfos()).__init(bb.readInt32(bb.position()) + bb.position(), bb);
|
|
}
|
|
/**
|
|
* @param number index
|
|
* @returns number
|
|
*/
|
|
nodeIndices(index) {
|
|
let offset = this.bb.__offset(this.bb_pos, 4);
|
|
return offset ? this.bb.readUint32(this.bb.__vector(this.bb_pos + offset) + index * 4) : 0;
|
|
}
|
|
/**
|
|
* @returns number
|
|
*/
|
|
nodeIndicesLength() {
|
|
let offset = this.bb.__offset(this.bb_pos, 4);
|
|
return offset ? this.bb.__vector_len(this.bb_pos + offset) : 0;
|
|
}
|
|
/**
|
|
* @returns Uint32Array
|
|
*/
|
|
nodeIndicesArray() {
|
|
let offset = this.bb.__offset(this.bb_pos, 4);
|
|
return offset ?
|
|
new Uint32Array(this.bb.bytes().buffer, this.bb.bytes().byteOffset + this.bb.__vector(this.bb_pos + offset), this.bb.__vector_len(this.bb_pos + offset)) :
|
|
null;
|
|
}
|
|
/**
|
|
* @param number index
|
|
* @returns flatbuffers.Long
|
|
*/
|
|
kernelDefHashes(index) {
|
|
let offset = this.bb.__offset(this.bb_pos, 6);
|
|
return offset ? this.bb.readUint64(this.bb.__vector(this.bb_pos + offset) + index * 8) :
|
|
this.bb.createLong(0, 0);
|
|
}
|
|
/**
|
|
* @returns number
|
|
*/
|
|
kernelDefHashesLength() {
|
|
let offset = this.bb.__offset(this.bb_pos, 6);
|
|
return offset ? this.bb.__vector_len(this.bb_pos + offset) : 0;
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
*/
|
|
static startKernelCreateInfos(builder) {
|
|
builder.startObject(2);
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @param flatbuffers.Offset nodeIndicesOffset
|
|
*/
|
|
static addNodeIndices(builder, nodeIndicesOffset) {
|
|
builder.addFieldOffset(0, nodeIndicesOffset, 0);
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @param Array.<number> data
|
|
* @returns flatbuffers.Offset
|
|
*/
|
|
static createNodeIndicesVector(builder, data) {
|
|
builder.startVector(4, data.length, 4);
|
|
for (let i = data.length - 1; i >= 0; i--) {
|
|
builder.addInt32(data[i]);
|
|
}
|
|
return builder.endVector();
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @param number numElems
|
|
*/
|
|
static startNodeIndicesVector(builder, numElems) {
|
|
builder.startVector(4, numElems, 4);
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @param flatbuffers.Offset kernelDefHashesOffset
|
|
*/
|
|
static addKernelDefHashes(builder, kernelDefHashesOffset) {
|
|
builder.addFieldOffset(1, kernelDefHashesOffset, 0);
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @param Array.<flatbuffers.Long> data
|
|
* @returns flatbuffers.Offset
|
|
*/
|
|
static createKernelDefHashesVector(builder, data) {
|
|
builder.startVector(8, data.length, 8);
|
|
for (let i = data.length - 1; i >= 0; i--) {
|
|
builder.addInt64(data[i]);
|
|
}
|
|
return builder.endVector();
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @param number numElems
|
|
*/
|
|
static startKernelDefHashesVector(builder, numElems) {
|
|
builder.startVector(8, numElems, 8);
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @returns flatbuffers.Offset
|
|
*/
|
|
static endKernelCreateInfos(builder) {
|
|
let offset = builder.endObject();
|
|
return offset;
|
|
}
|
|
static createKernelCreateInfos(builder, nodeIndicesOffset, kernelDefHashesOffset) {
|
|
KernelCreateInfos.startKernelCreateInfos(builder);
|
|
KernelCreateInfos.addNodeIndices(builder, nodeIndicesOffset);
|
|
KernelCreateInfos.addKernelDefHashes(builder, kernelDefHashesOffset);
|
|
return KernelCreateInfos.endKernelCreateInfos(builder);
|
|
}
|
|
}
|
|
fbs.KernelCreateInfos = KernelCreateInfos;
|
|
})(fbs = experimental.fbs || (experimental.fbs = {}));
|
|
})(experimental = onnxruntime.experimental || (onnxruntime.experimental = {}));
|
|
})(onnxruntime = exports.onnxruntime || (exports.onnxruntime = {}));
|
|
/**
|
|
* @constructor
|
|
*/
|
|
(function (onnxruntime) {
|
|
var experimental;
|
|
(function (experimental) {
|
|
var fbs;
|
|
(function (fbs) {
|
|
class SubGraphSessionState {
|
|
constructor() {
|
|
this.bb = null;
|
|
this.bb_pos = 0;
|
|
}
|
|
/**
|
|
* @param number i
|
|
* @param flatbuffers.ByteBuffer bb
|
|
* @returns SubGraphSessionState
|
|
*/
|
|
__init(i, bb) {
|
|
this.bb_pos = i;
|
|
this.bb = bb;
|
|
return this;
|
|
}
|
|
/**
|
|
* @param flatbuffers.ByteBuffer bb
|
|
* @param SubGraphSessionState= obj
|
|
* @returns SubGraphSessionState
|
|
*/
|
|
static getRootAsSubGraphSessionState(bb, obj) {
|
|
return (obj || new SubGraphSessionState()).__init(bb.readInt32(bb.position()) + bb.position(), bb);
|
|
}
|
|
/**
|
|
* @param flatbuffers.ByteBuffer bb
|
|
* @param SubGraphSessionState= obj
|
|
* @returns SubGraphSessionState
|
|
*/
|
|
static getSizePrefixedRootAsSubGraphSessionState(bb, obj) {
|
|
bb.setPosition(bb.position() + flatbuffers_1.flatbuffers.SIZE_PREFIX_LENGTH);
|
|
return (obj || new SubGraphSessionState()).__init(bb.readInt32(bb.position()) + bb.position(), bb);
|
|
}
|
|
graphId(optionalEncoding) {
|
|
let offset = this.bb.__offset(this.bb_pos, 4);
|
|
return offset ? this.bb.__string(this.bb_pos + offset, optionalEncoding) : null;
|
|
}
|
|
/**
|
|
* @param onnxruntime.experimental.fbs.SessionState= obj
|
|
* @returns onnxruntime.experimental.fbs.SessionState|null
|
|
*/
|
|
sessionState(obj) {
|
|
let offset = this.bb.__offset(this.bb_pos, 6);
|
|
return offset ? (obj || new onnxruntime.experimental.fbs.SessionState())
|
|
.__init(this.bb.__indirect(this.bb_pos + offset), this.bb) :
|
|
null;
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
*/
|
|
static startSubGraphSessionState(builder) {
|
|
builder.startObject(2);
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @param flatbuffers.Offset graphIdOffset
|
|
*/
|
|
static addGraphId(builder, graphIdOffset) {
|
|
builder.addFieldOffset(0, graphIdOffset, 0);
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @param flatbuffers.Offset sessionStateOffset
|
|
*/
|
|
static addSessionState(builder, sessionStateOffset) {
|
|
builder.addFieldOffset(1, sessionStateOffset, 0);
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @returns flatbuffers.Offset
|
|
*/
|
|
static endSubGraphSessionState(builder) {
|
|
let offset = builder.endObject();
|
|
builder.requiredField(offset, 4); // graph_id
|
|
return offset;
|
|
}
|
|
static createSubGraphSessionState(builder, graphIdOffset, sessionStateOffset) {
|
|
SubGraphSessionState.startSubGraphSessionState(builder);
|
|
SubGraphSessionState.addGraphId(builder, graphIdOffset);
|
|
SubGraphSessionState.addSessionState(builder, sessionStateOffset);
|
|
return SubGraphSessionState.endSubGraphSessionState(builder);
|
|
}
|
|
}
|
|
fbs.SubGraphSessionState = SubGraphSessionState;
|
|
})(fbs = experimental.fbs || (experimental.fbs = {}));
|
|
})(experimental = onnxruntime.experimental || (onnxruntime.experimental = {}));
|
|
})(onnxruntime = exports.onnxruntime || (exports.onnxruntime = {}));
|
|
/**
|
|
* @constructor
|
|
*/
|
|
(function (onnxruntime) {
|
|
var experimental;
|
|
(function (experimental) {
|
|
var fbs;
|
|
(function (fbs) {
|
|
class SessionState {
|
|
constructor() {
|
|
this.bb = null;
|
|
this.bb_pos = 0;
|
|
}
|
|
/**
|
|
* @param number i
|
|
* @param flatbuffers.ByteBuffer bb
|
|
* @returns SessionState
|
|
*/
|
|
__init(i, bb) {
|
|
this.bb_pos = i;
|
|
this.bb = bb;
|
|
return this;
|
|
}
|
|
/**
|
|
* @param flatbuffers.ByteBuffer bb
|
|
* @param SessionState= obj
|
|
* @returns SessionState
|
|
*/
|
|
static getRootAsSessionState(bb, obj) {
|
|
return (obj || new SessionState()).__init(bb.readInt32(bb.position()) + bb.position(), bb);
|
|
}
|
|
/**
|
|
* @param flatbuffers.ByteBuffer bb
|
|
* @param SessionState= obj
|
|
* @returns SessionState
|
|
*/
|
|
static getSizePrefixedRootAsSessionState(bb, obj) {
|
|
bb.setPosition(bb.position() + flatbuffers_1.flatbuffers.SIZE_PREFIX_LENGTH);
|
|
return (obj || new SessionState()).__init(bb.readInt32(bb.position()) + bb.position(), bb);
|
|
}
|
|
/**
|
|
* @param onnxruntime.experimental.fbs.KernelCreateInfos= obj
|
|
* @returns onnxruntime.experimental.fbs.KernelCreateInfos|null
|
|
*/
|
|
kernels(obj) {
|
|
let offset = this.bb.__offset(this.bb_pos, 4);
|
|
return offset ? (obj || new onnxruntime.experimental.fbs.KernelCreateInfos())
|
|
.__init(this.bb.__indirect(this.bb_pos + offset), this.bb) :
|
|
null;
|
|
}
|
|
/**
|
|
* @param number index
|
|
* @param onnxruntime.experimental.fbs.SubGraphSessionState= obj
|
|
* @returns onnxruntime.experimental.fbs.SubGraphSessionState
|
|
*/
|
|
subGraphSessionStates(index, obj) {
|
|
let offset = this.bb.__offset(this.bb_pos, 6);
|
|
return offset ? (obj || new onnxruntime.experimental.fbs.SubGraphSessionState())
|
|
.__init(this.bb.__indirect(this.bb.__vector(this.bb_pos + offset) + index * 4), this.bb) :
|
|
null;
|
|
}
|
|
/**
|
|
* @returns number
|
|
*/
|
|
subGraphSessionStatesLength() {
|
|
let offset = this.bb.__offset(this.bb_pos, 6);
|
|
return offset ? this.bb.__vector_len(this.bb_pos + offset) : 0;
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
*/
|
|
static startSessionState(builder) {
|
|
builder.startObject(2);
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @param flatbuffers.Offset kernelsOffset
|
|
*/
|
|
static addKernels(builder, kernelsOffset) {
|
|
builder.addFieldOffset(0, kernelsOffset, 0);
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @param flatbuffers.Offset subGraphSessionStatesOffset
|
|
*/
|
|
static addSubGraphSessionStates(builder, subGraphSessionStatesOffset) {
|
|
builder.addFieldOffset(1, subGraphSessionStatesOffset, 0);
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @param Array.<flatbuffers.Offset> data
|
|
* @returns flatbuffers.Offset
|
|
*/
|
|
static createSubGraphSessionStatesVector(builder, data) {
|
|
builder.startVector(4, data.length, 4);
|
|
for (let i = data.length - 1; i >= 0; i--) {
|
|
builder.addOffset(data[i]);
|
|
}
|
|
return builder.endVector();
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @param number numElems
|
|
*/
|
|
static startSubGraphSessionStatesVector(builder, numElems) {
|
|
builder.startVector(4, numElems, 4);
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @returns flatbuffers.Offset
|
|
*/
|
|
static endSessionState(builder) {
|
|
let offset = builder.endObject();
|
|
return offset;
|
|
}
|
|
static createSessionState(builder, kernelsOffset, subGraphSessionStatesOffset) {
|
|
SessionState.startSessionState(builder);
|
|
SessionState.addKernels(builder, kernelsOffset);
|
|
SessionState.addSubGraphSessionStates(builder, subGraphSessionStatesOffset);
|
|
return SessionState.endSessionState(builder);
|
|
}
|
|
}
|
|
fbs.SessionState = SessionState;
|
|
})(fbs = experimental.fbs || (experimental.fbs = {}));
|
|
})(experimental = onnxruntime.experimental || (onnxruntime.experimental = {}));
|
|
})(onnxruntime = exports.onnxruntime || (exports.onnxruntime = {}));
|
|
/**
|
|
* @constructor
|
|
*/
|
|
(function (onnxruntime) {
|
|
var experimental;
|
|
(function (experimental) {
|
|
var fbs;
|
|
(function (fbs) {
|
|
class InferenceSession {
|
|
constructor() {
|
|
this.bb = null;
|
|
this.bb_pos = 0;
|
|
}
|
|
/**
|
|
* @param number i
|
|
* @param flatbuffers.ByteBuffer bb
|
|
* @returns InferenceSession
|
|
*/
|
|
__init(i, bb) {
|
|
this.bb_pos = i;
|
|
this.bb = bb;
|
|
return this;
|
|
}
|
|
/**
|
|
* @param flatbuffers.ByteBuffer bb
|
|
* @param InferenceSession= obj
|
|
* @returns InferenceSession
|
|
*/
|
|
static getRootAsInferenceSession(bb, obj) {
|
|
return (obj || new InferenceSession()).__init(bb.readInt32(bb.position()) + bb.position(), bb);
|
|
}
|
|
/**
|
|
* @param flatbuffers.ByteBuffer bb
|
|
* @param InferenceSession= obj
|
|
* @returns InferenceSession
|
|
*/
|
|
static getSizePrefixedRootAsInferenceSession(bb, obj) {
|
|
bb.setPosition(bb.position() + flatbuffers_1.flatbuffers.SIZE_PREFIX_LENGTH);
|
|
return (obj || new InferenceSession()).__init(bb.readInt32(bb.position()) + bb.position(), bb);
|
|
}
|
|
/**
|
|
* @param flatbuffers.ByteBuffer bb
|
|
* @returns boolean
|
|
*/
|
|
static bufferHasIdentifier(bb) {
|
|
return bb.__has_identifier('ORTM');
|
|
}
|
|
ortVersion(optionalEncoding) {
|
|
let offset = this.bb.__offset(this.bb_pos, 4);
|
|
return offset ? this.bb.__string(this.bb_pos + offset, optionalEncoding) : null;
|
|
}
|
|
/**
|
|
* @param onnxruntime.experimental.fbs.Model= obj
|
|
* @returns onnxruntime.experimental.fbs.Model|null
|
|
*/
|
|
model(obj) {
|
|
let offset = this.bb.__offset(this.bb_pos, 6);
|
|
return offset ? (obj || new onnxruntime.experimental.fbs.Model())
|
|
.__init(this.bb.__indirect(this.bb_pos + offset), this.bb) :
|
|
null;
|
|
}
|
|
/**
|
|
* @param onnxruntime.experimental.fbs.SessionState= obj
|
|
* @returns onnxruntime.experimental.fbs.SessionState|null
|
|
*/
|
|
sessionState(obj) {
|
|
let offset = this.bb.__offset(this.bb_pos, 8);
|
|
return offset ? (obj || new onnxruntime.experimental.fbs.SessionState())
|
|
.__init(this.bb.__indirect(this.bb_pos + offset), this.bb) :
|
|
null;
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
*/
|
|
static startInferenceSession(builder) {
|
|
builder.startObject(3);
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @param flatbuffers.Offset ortVersionOffset
|
|
*/
|
|
static addOrtVersion(builder, ortVersionOffset) {
|
|
builder.addFieldOffset(0, ortVersionOffset, 0);
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @param flatbuffers.Offset modelOffset
|
|
*/
|
|
static addModel(builder, modelOffset) {
|
|
builder.addFieldOffset(1, modelOffset, 0);
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @param flatbuffers.Offset sessionStateOffset
|
|
*/
|
|
static addSessionState(builder, sessionStateOffset) {
|
|
builder.addFieldOffset(2, sessionStateOffset, 0);
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @returns flatbuffers.Offset
|
|
*/
|
|
static endInferenceSession(builder) {
|
|
let offset = builder.endObject();
|
|
return offset;
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @param flatbuffers.Offset offset
|
|
*/
|
|
static finishInferenceSessionBuffer(builder, offset) {
|
|
builder.finish(offset, 'ORTM');
|
|
}
|
|
/**
|
|
* @param flatbuffers.Builder builder
|
|
* @param flatbuffers.Offset offset
|
|
*/
|
|
static finishSizePrefixedInferenceSessionBuffer(builder, offset) {
|
|
builder.finish(offset, 'ORTM', true);
|
|
}
|
|
static createInferenceSession(builder, ortVersionOffset, modelOffset, sessionStateOffset) {
|
|
InferenceSession.startInferenceSession(builder);
|
|
InferenceSession.addOrtVersion(builder, ortVersionOffset);
|
|
InferenceSession.addModel(builder, modelOffset);
|
|
InferenceSession.addSessionState(builder, sessionStateOffset);
|
|
return InferenceSession.endInferenceSession(builder);
|
|
}
|
|
}
|
|
fbs.InferenceSession = InferenceSession;
|
|
})(fbs = experimental.fbs || (experimental.fbs = {}));
|
|
})(experimental = onnxruntime.experimental || (onnxruntime.experimental = {}));
|
|
})(onnxruntime = exports.onnxruntime || (exports.onnxruntime = {}));
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./lib/onnxjs/session-handler.ts":
|
|
/*!***************************************!*\
|
|
!*** ./lib/onnxjs/session-handler.ts ***!
|
|
\***************************************/
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
// Licensed under the MIT License.
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.OnnxjsSessionHandler = void 0;
|
|
const onnxruntime_common_1 = __webpack_require__(/*! onnxruntime-common */ "../common/dist/lib/index.js");
|
|
const tensor_1 = __webpack_require__(/*! ./tensor */ "./lib/onnxjs/tensor.ts");
|
|
class OnnxjsSessionHandler {
|
|
constructor(session) {
|
|
this.session = session;
|
|
this.inputNames = this.session.inputNames;
|
|
this.outputNames = this.session.outputNames;
|
|
}
|
|
async dispose() { }
|
|
async run(feeds, _fetches, _options) {
|
|
const inputMap = new Map();
|
|
for (const name in feeds) {
|
|
if (Object.hasOwnProperty.call(feeds, name)) {
|
|
const feed = feeds[name];
|
|
inputMap.set(name, new tensor_1.Tensor(feed.dims, feed.type, undefined, undefined, feed.data));
|
|
}
|
|
}
|
|
const outputMap = await this.session.run(inputMap);
|
|
const output = {};
|
|
outputMap.forEach((tensor, name) => {
|
|
output[name] = new onnxruntime_common_1.Tensor(tensor.type, tensor.data, tensor.dims);
|
|
});
|
|
return output;
|
|
}
|
|
startProfiling() {
|
|
this.session.startProfiling();
|
|
}
|
|
endProfiling() {
|
|
this.session.endProfiling();
|
|
}
|
|
}
|
|
exports.OnnxjsSessionHandler = OnnxjsSessionHandler;
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./lib/onnxjs/session.ts":
|
|
/*!*******************************!*\
|
|
!*** ./lib/onnxjs/session.ts ***!
|
|
\*******************************/
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
// Licensed under the MIT License.
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.Session = void 0;
|
|
const fs_1 = __webpack_require__(/*! fs */ "?6c45");
|
|
const util_1 = __webpack_require__(/*! util */ "?b3a2");
|
|
const backend_1 = __webpack_require__(/*! ./backend */ "./lib/onnxjs/backend.ts");
|
|
const execution_plan_1 = __webpack_require__(/*! ./execution-plan */ "./lib/onnxjs/execution-plan.ts");
|
|
const instrument_1 = __webpack_require__(/*! ./instrument */ "./lib/onnxjs/instrument.ts");
|
|
const model_1 = __webpack_require__(/*! ./model */ "./lib/onnxjs/model.ts");
|
|
class Session {
|
|
constructor(config = {}) {
|
|
this._initialized = false;
|
|
this.backendHint = config.backendHint;
|
|
this.profiler = instrument_1.Profiler.create(config.profiler);
|
|
this.context = { profiler: this.profiler, graphInputTypes: [], graphInputDims: [] };
|
|
}
|
|
get inputNames() {
|
|
return this._model.graph.getInputNames();
|
|
}
|
|
get outputNames() {
|
|
return this._model.graph.getOutputNames();
|
|
}
|
|
startProfiling() {
|
|
this.profiler.start();
|
|
}
|
|
endProfiling() {
|
|
this.profiler.stop();
|
|
}
|
|
async loadModel(arg, byteOffset, length) {
|
|
await this.profiler.event('session', 'Session.loadModel', async () => {
|
|
// resolve backend and session handler
|
|
const backend = await (0, backend_1.resolveBackend)(this.backendHint);
|
|
this.sessionHandler = backend.createSessionHandler(this.context);
|
|
this._model = new model_1.Model();
|
|
if (typeof arg === 'string') {
|
|
const isOrtFormat = arg.endsWith('.ort');
|
|
if (typeof fetch === 'undefined') {
|
|
// node
|
|
const buf = await (0, util_1.promisify)(fs_1.readFile)(arg);
|
|
this.initialize(buf, isOrtFormat);
|
|
}
|
|
else {
|
|
// browser
|
|
const response = await fetch(arg);
|
|
const buf = await response.arrayBuffer();
|
|
this.initialize(new Uint8Array(buf), isOrtFormat);
|
|
}
|
|
}
|
|
else if (!ArrayBuffer.isView(arg)) {
|
|
// load model from ArrayBuffer
|
|
const arr = new Uint8Array(arg, byteOffset || 0, length || arg.byteLength);
|
|
this.initialize(arr);
|
|
}
|
|
else {
|
|
// load model from Uint8array
|
|
this.initialize(arg);
|
|
}
|
|
});
|
|
}
|
|
initialize(modelProtoBlob, isOrtFormat) {
|
|
if (this._initialized) {
|
|
throw new Error('already initialized');
|
|
}
|
|
this.profiler.event('session', 'Session.initialize', () => {
|
|
// load graph
|
|
const graphInitializer = this.sessionHandler.transformGraph ? this.sessionHandler : undefined;
|
|
this._model.load(modelProtoBlob, graphInitializer, isOrtFormat);
|
|
// graph is completely initialzied at this stage , let the interested handlers know
|
|
if (this.sessionHandler.onGraphInitialized) {
|
|
this.sessionHandler.onGraphInitialized(this._model.graph);
|
|
}
|
|
// initialize each operator in the graph
|
|
this.initializeOps(this._model.graph);
|
|
// instantiate an ExecutionPlan object to be used by the Session object
|
|
this._executionPlan = new execution_plan_1.ExecutionPlan(this._model.graph, this._ops, this.profiler);
|
|
});
|
|
this._initialized = true;
|
|
}
|
|
async run(inputs) {
|
|
if (!this._initialized) {
|
|
throw new Error('session not initialized yet');
|
|
}
|
|
return this.profiler.event('session', 'Session.run', async () => {
|
|
const inputTensors = this.normalizeAndValidateInputs(inputs);
|
|
const outputTensors = await this._executionPlan.execute(this.sessionHandler, inputTensors);
|
|
return this.createOutput(outputTensors);
|
|
});
|
|
}
|
|
normalizeAndValidateInputs(inputs) {
|
|
const modelInputNames = this._model.graph.getInputNames();
|
|
// normalize inputs
|
|
// inputs: Tensor[]
|
|
if (Array.isArray(inputs)) {
|
|
if (inputs.length !== modelInputNames.length) {
|
|
throw new Error(`incorrect input array length: expected ${modelInputNames.length} but got ${inputs.length}`);
|
|
}
|
|
}
|
|
// convert map to array
|
|
// inputs: Map<string, Tensor>
|
|
else {
|
|
if (inputs.size !== modelInputNames.length) {
|
|
throw new Error(`incorrect input map size: expected ${modelInputNames.length} but got ${inputs.size}`);
|
|
}
|
|
const sortedInputs = new Array(inputs.size);
|
|
let sortedInputsIndex = 0;
|
|
for (let i = 0; i < modelInputNames.length; ++i) {
|
|
const tensor = inputs.get(modelInputNames[i]);
|
|
if (!tensor) {
|
|
throw new Error(`missing input tensor for: '${name}'`);
|
|
}
|
|
sortedInputs[sortedInputsIndex++] = tensor;
|
|
}
|
|
inputs = sortedInputs;
|
|
}
|
|
// validate dims requirements
|
|
// First session run - graph input data is not cached for the session
|
|
if (!this.context.graphInputTypes || this.context.graphInputTypes.length === 0 || !this.context.graphInputDims ||
|
|
this.context.graphInputDims.length === 0) {
|
|
const modelInputIndices = this._model.graph.getInputIndices();
|
|
const modelValues = this._model.graph.getValues();
|
|
const graphInputDims = new Array(modelInputIndices.length);
|
|
for (let i = 0; i < modelInputIndices.length; ++i) {
|
|
const graphInput = modelValues[modelInputIndices[i]];
|
|
graphInputDims[i] = graphInput.type.shape.dims;
|
|
// cached for second and subsequent runs.
|
|
// Some parts of the framework works on the assumption that the graph and types and shapes are static
|
|
this.context.graphInputTypes.push(graphInput.type.tensorType);
|
|
this.context.graphInputDims.push(inputs[i].dims);
|
|
}
|
|
this.validateInputTensorDims(graphInputDims, inputs, true);
|
|
}
|
|
// Second and subsequent session runs - graph input data is cached for the session
|
|
else {
|
|
this.validateInputTensorDims(this.context.graphInputDims, inputs, false);
|
|
}
|
|
// validate types requirement
|
|
this.validateInputTensorTypes(this.context.graphInputTypes, inputs);
|
|
return inputs;
|
|
}
|
|
validateInputTensorTypes(graphInputTypes, givenInputs) {
|
|
for (let i = 0; i < givenInputs.length; i++) {
|
|
const expectedType = graphInputTypes[i];
|
|
const actualType = givenInputs[i].type;
|
|
if (expectedType !== actualType) {
|
|
throw new Error(`input tensor[${i}] check failed: expected type '${expectedType}' but got ${actualType}`);
|
|
}
|
|
}
|
|
}
|
|
validateInputTensorDims(graphInputDims, givenInputs, noneDimSupported) {
|
|
for (let i = 0; i < givenInputs.length; i++) {
|
|
const expectedDims = graphInputDims[i];
|
|
const actualDims = givenInputs[i].dims;
|
|
if (!this.compareTensorDims(expectedDims, actualDims, noneDimSupported)) {
|
|
throw new Error(`input tensor[${i}] check failed: expected shape '[${expectedDims.join(',')}]' but got [${actualDims.join(',')}]`);
|
|
}
|
|
}
|
|
}
|
|
compareTensorDims(expectedDims, actualDims, noneDimSupported) {
|
|
if (expectedDims.length !== actualDims.length) {
|
|
return false;
|
|
}
|
|
for (let i = 0; i < expectedDims.length; ++i) {
|
|
if (expectedDims[i] !== actualDims[i] && (!noneDimSupported || expectedDims[i] !== 0)) {
|
|
// data shape mis-match AND not a 'None' dimension.
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
createOutput(outputTensors) {
|
|
const modelOutputNames = this._model.graph.getOutputNames();
|
|
if (outputTensors.length !== modelOutputNames.length) {
|
|
throw new Error('expected number of outputs do not match number of generated outputs');
|
|
}
|
|
const output = new Map();
|
|
for (let i = 0; i < modelOutputNames.length; ++i) {
|
|
output.set(modelOutputNames[i], outputTensors[i]);
|
|
}
|
|
return output;
|
|
}
|
|
initializeOps(graph) {
|
|
const nodes = graph.getNodes();
|
|
this._ops = new Array(nodes.length);
|
|
for (let i = 0; i < nodes.length; i++) {
|
|
this._ops[i] = this.sessionHandler.resolve(nodes[i], this._model.opsets, graph);
|
|
}
|
|
}
|
|
}
|
|
exports.Session = Session;
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./lib/onnxjs/tensor.ts":
|
|
/*!******************************!*\
|
|
!*** ./lib/onnxjs/tensor.ts ***!
|
|
\******************************/
|
|
/***/ (function(__unused_webpack_module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
// Licensed under the MIT License.
|
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
};
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.Tensor = void 0;
|
|
const guid_typescript_1 = __webpack_require__(/*! guid-typescript */ "./node_modules/guid-typescript/dist/guid.js");
|
|
const long_1 = __importDefault(__webpack_require__(/*! long */ "./node_modules/long/src/long.js"));
|
|
const onnx_proto_1 = __webpack_require__(/*! onnx-proto */ "./node_modules/onnx-proto/dist/onnx.js");
|
|
const ort_generated_1 = __webpack_require__(/*! ./ort-schema/ort-generated */ "./lib/onnxjs/ort-schema/ort-generated.ts");
|
|
const util_1 = __webpack_require__(/*! ./util */ "./lib/onnxjs/util.ts");
|
|
var ortFbs = ort_generated_1.onnxruntime.experimental.fbs;
|
|
class Tensor {
|
|
/**
|
|
* get the underlying tensor data
|
|
*/
|
|
get data() {
|
|
if (this.cache === undefined) {
|
|
const data = this.dataProvider(this.dataId);
|
|
if (data.length !== this.size) {
|
|
throw new Error('Length of data provided by the Data Provider is inconsistent with the dims of this Tensor.');
|
|
}
|
|
this.cache = data;
|
|
}
|
|
return this.cache;
|
|
}
|
|
/**
|
|
* get the underlying string tensor data. Should only use when type is STRING
|
|
*/
|
|
get stringData() {
|
|
if (this.type !== 'string') {
|
|
throw new TypeError('data type is not string');
|
|
}
|
|
return this.data;
|
|
}
|
|
/**
|
|
* get the underlying integer tensor data. Should only use when type is one of the following: (UINT8, INT8, UINT16,
|
|
* INT16, INT32, UINT32, BOOL)
|
|
*/
|
|
get integerData() {
|
|
switch (this.type) {
|
|
case 'uint8':
|
|
case 'int8':
|
|
case 'uint16':
|
|
case 'int16':
|
|
case 'int32':
|
|
case 'uint32':
|
|
case 'bool':
|
|
return this.data;
|
|
default:
|
|
throw new TypeError('data type is not integer (uint8, int8, uint16, int16, int32, uint32, bool)');
|
|
}
|
|
}
|
|
/**
|
|
* get the underlying float tensor data. Should only use when type is one of the following: (FLOAT, DOUBLE)
|
|
*/
|
|
get floatData() {
|
|
switch (this.type) {
|
|
case 'float32':
|
|
case 'float64':
|
|
return this.data;
|
|
default:
|
|
throw new TypeError('data type is not float (float32, float64)');
|
|
}
|
|
}
|
|
/**
|
|
* get the underlying number tensor data. Should only use when type is one of the following: (UINT8, INT8, UINT16,
|
|
* INT16, INT32, UINT32, BOOL, FLOAT, DOUBLE)
|
|
*/
|
|
get numberData() {
|
|
if (this.type !== 'string') {
|
|
return this.data;
|
|
}
|
|
throw new TypeError('type cannot be non-number (string)');
|
|
}
|
|
/**
|
|
* get value of an element at the given indices
|
|
*/
|
|
get(indices) {
|
|
return this.data[util_1.ShapeUtil.indicesToOffset(indices, this.strides)];
|
|
}
|
|
/**
|
|
* set value of an element at the given indices
|
|
*/
|
|
set(indices, value) {
|
|
this.data[util_1.ShapeUtil.indicesToOffset(indices, this.strides)] = value;
|
|
}
|
|
/**
|
|
* get the underlying tensor data asynchronously
|
|
*/
|
|
async getData() {
|
|
if (this.cache === undefined) {
|
|
this.cache = await this.asyncDataProvider(this.dataId);
|
|
}
|
|
return this.cache;
|
|
}
|
|
/**
|
|
* get the strides for each dimension
|
|
*/
|
|
get strides() {
|
|
if (!this._strides) {
|
|
this._strides = util_1.ShapeUtil.computeStrides(this.dims);
|
|
}
|
|
return this._strides;
|
|
}
|
|
constructor(
|
|
/**
|
|
* get the dimensions of the tensor
|
|
*/
|
|
dims,
|
|
/**
|
|
* get the type of the tensor
|
|
*/
|
|
type, dataProvider, asyncDataProvider, cache,
|
|
/**
|
|
* get the data ID that used to map to a tensor data
|
|
*/
|
|
dataId = guid_typescript_1.Guid.create()) {
|
|
this.dims = dims;
|
|
this.type = type;
|
|
this.dataProvider = dataProvider;
|
|
this.asyncDataProvider = asyncDataProvider;
|
|
this.cache = cache;
|
|
this.dataId = dataId;
|
|
this.size = util_1.ShapeUtil.validateDimsAndCalcSize(dims);
|
|
const size = this.size;
|
|
const empty = (dataProvider === undefined && asyncDataProvider === undefined && cache === undefined);
|
|
if (cache !== undefined) {
|
|
if (cache.length !== size) {
|
|
throw new RangeError('Input dims doesn\'t match data length.');
|
|
}
|
|
}
|
|
if (type === 'string') {
|
|
if (cache !== undefined && (!Array.isArray(cache) || !cache.every(i => typeof i === 'string'))) {
|
|
throw new TypeError('cache should be a string array');
|
|
}
|
|
if (empty) {
|
|
this.cache = new Array(size);
|
|
}
|
|
}
|
|
else {
|
|
if (cache !== undefined) {
|
|
const constructor = dataviewConstructor(type);
|
|
if (!(cache instanceof constructor)) {
|
|
throw new TypeError(`cache should be type ${constructor.name}`);
|
|
}
|
|
}
|
|
if (empty) {
|
|
const buf = new ArrayBuffer(size * sizeof(type));
|
|
this.cache = createView(buf, type);
|
|
}
|
|
}
|
|
}
|
|
/**
|
|
* Construct new Tensor from a ONNX Tensor object
|
|
* @param tensorProto the ONNX Tensor
|
|
*/
|
|
static fromProto(tensorProto) {
|
|
if (!tensorProto) {
|
|
throw new Error('cannot construct Value from an empty tensor');
|
|
}
|
|
const type = util_1.ProtoUtil.tensorDataTypeFromProto(tensorProto.dataType);
|
|
const dims = util_1.ProtoUtil.tensorDimsFromProto(tensorProto.dims);
|
|
const value = new Tensor(dims, type);
|
|
if (type === 'string') {
|
|
// When it's STRING type, the value should always be stored in field
|
|
// 'stringData'
|
|
tensorProto.stringData.forEach((str, i) => {
|
|
value.data[i] = (0, util_1.decodeUtf8String)(str);
|
|
});
|
|
}
|
|
else if (tensorProto.rawData && typeof tensorProto.rawData.byteLength === 'number' &&
|
|
tensorProto.rawData.byteLength > 0) {
|
|
// NOT considering segment for now (IMPORTANT)
|
|
// populate value from rawData
|
|
const dataDest = value.data;
|
|
const dataSource = new DataView(tensorProto.rawData.buffer, tensorProto.rawData.byteOffset, tensorProto.rawData.byteLength);
|
|
const elementSize = sizeofProto(tensorProto.dataType);
|
|
const length = tensorProto.rawData.byteLength / elementSize;
|
|
if (tensorProto.rawData.byteLength % elementSize !== 0) {
|
|
throw new Error('invalid buffer length');
|
|
}
|
|
if (dataDest.length !== length) {
|
|
throw new Error('buffer length mismatch');
|
|
}
|
|
for (let i = 0; i < length; i++) {
|
|
const n = readProto(dataSource, tensorProto.dataType, i * elementSize);
|
|
dataDest[i] = n;
|
|
}
|
|
}
|
|
else {
|
|
// populate value from array
|
|
let array;
|
|
switch (tensorProto.dataType) {
|
|
case onnx_proto_1.onnx.TensorProto.DataType.FLOAT:
|
|
array = tensorProto.floatData;
|
|
break;
|
|
case onnx_proto_1.onnx.TensorProto.DataType.INT32:
|
|
case onnx_proto_1.onnx.TensorProto.DataType.INT16:
|
|
case onnx_proto_1.onnx.TensorProto.DataType.UINT16:
|
|
case onnx_proto_1.onnx.TensorProto.DataType.INT8:
|
|
case onnx_proto_1.onnx.TensorProto.DataType.UINT8:
|
|
case onnx_proto_1.onnx.TensorProto.DataType.BOOL:
|
|
array = tensorProto.int32Data;
|
|
break;
|
|
case onnx_proto_1.onnx.TensorProto.DataType.INT64:
|
|
array = tensorProto.int64Data;
|
|
break;
|
|
case onnx_proto_1.onnx.TensorProto.DataType.DOUBLE:
|
|
array = tensorProto.doubleData;
|
|
break;
|
|
case onnx_proto_1.onnx.TensorProto.DataType.UINT32:
|
|
case onnx_proto_1.onnx.TensorProto.DataType.UINT64:
|
|
array = tensorProto.uint64Data;
|
|
break;
|
|
default:
|
|
// should never run here
|
|
throw new Error('unspecific error');
|
|
}
|
|
if (array === null || array === undefined) {
|
|
throw new Error('failed to populate data from a tensorproto value');
|
|
}
|
|
const data = value.data;
|
|
if (data.length !== array.length) {
|
|
throw new Error('array length mismatch');
|
|
}
|
|
for (let i = 0; i < array.length; i++) {
|
|
const element = array[i];
|
|
if (long_1.default.isLong(element)) {
|
|
data[i] = longToNumber(element, tensorProto.dataType);
|
|
}
|
|
else {
|
|
data[i] = element;
|
|
}
|
|
}
|
|
}
|
|
return value;
|
|
}
|
|
/**
|
|
* Construct new Tensor from raw data
|
|
* @param data the raw data object. Should be a string array for 'string' tensor, and the corresponding typed array
|
|
* for other types of tensor.
|
|
* @param dims the dimensions of the tensor
|
|
* @param type the type of the tensor
|
|
*/
|
|
static fromData(data, dims, type) {
|
|
return new Tensor(dims, type, undefined, undefined, data);
|
|
}
|
|
static fromOrtTensor(ortTensor) {
|
|
if (!ortTensor) {
|
|
throw new Error('cannot construct Value from an empty tensor');
|
|
}
|
|
const dims = util_1.ProtoUtil.tensorDimsFromORTFormat(ortTensor);
|
|
const type = util_1.ProtoUtil.tensorDataTypeFromProto(ortTensor.dataType());
|
|
const value = new Tensor(dims, type);
|
|
if (type === 'string') {
|
|
// When it's STRING type, the value should always be stored in field
|
|
// 'stringData'
|
|
for (let i = 0; i < ortTensor.stringDataLength(); i++) {
|
|
value.data[i] = ortTensor.stringData(i);
|
|
}
|
|
}
|
|
else if (ortTensor.rawDataArray() && typeof ortTensor.rawDataLength() === 'number' && ortTensor.rawDataLength() > 0) {
|
|
// NOT considering segment for now (IMPORTANT)
|
|
// populate value from rawData
|
|
const dataDest = value.data;
|
|
const dataSource = new DataView(ortTensor.rawDataArray().buffer, ortTensor.rawDataArray().byteOffset, ortTensor.rawDataLength());
|
|
const elementSize = sizeofProto(ortTensor.dataType());
|
|
const length = ortTensor.rawDataLength() / elementSize;
|
|
if (ortTensor.rawDataLength() % elementSize !== 0) {
|
|
throw new Error('invalid buffer length');
|
|
}
|
|
if (dataDest.length !== length) {
|
|
throw new Error('buffer length mismatch');
|
|
}
|
|
for (let i = 0; i < length; i++) {
|
|
const n = readProto(dataSource, ortTensor.dataType(), i * elementSize);
|
|
dataDest[i] = n;
|
|
}
|
|
}
|
|
return value;
|
|
}
|
|
}
|
|
exports.Tensor = Tensor;
|
|
function sizeof(type) {
|
|
switch (type) {
|
|
case 'bool':
|
|
case 'int8':
|
|
case 'uint8':
|
|
return 1;
|
|
case 'int16':
|
|
case 'uint16':
|
|
return 2;
|
|
case 'int32':
|
|
case 'uint32':
|
|
case 'float32':
|
|
return 4;
|
|
case 'float64':
|
|
return 8;
|
|
default:
|
|
throw new Error(`cannot calculate sizeof() on type ${type}`);
|
|
}
|
|
}
|
|
function sizeofProto(type) {
|
|
switch (type) {
|
|
case onnx_proto_1.onnx.TensorProto.DataType.UINT8:
|
|
case onnx_proto_1.onnx.TensorProto.DataType.INT8:
|
|
case onnx_proto_1.onnx.TensorProto.DataType.BOOL:
|
|
return 1;
|
|
case onnx_proto_1.onnx.TensorProto.DataType.UINT16:
|
|
case onnx_proto_1.onnx.TensorProto.DataType.INT16:
|
|
return 2;
|
|
case onnx_proto_1.onnx.TensorProto.DataType.FLOAT:
|
|
case onnx_proto_1.onnx.TensorProto.DataType.INT32:
|
|
case onnx_proto_1.onnx.TensorProto.DataType.UINT32:
|
|
return 4;
|
|
case onnx_proto_1.onnx.TensorProto.DataType.INT64:
|
|
case onnx_proto_1.onnx.TensorProto.DataType.DOUBLE:
|
|
case onnx_proto_1.onnx.TensorProto.DataType.UINT64:
|
|
return 8;
|
|
default:
|
|
throw new Error(`cannot calculate sizeof() on type ${onnx_proto_1.onnx.TensorProto.DataType[type]}`);
|
|
}
|
|
}
|
|
function createView(dataBuffer, type) {
|
|
return new (dataviewConstructor(type))(dataBuffer);
|
|
}
|
|
function dataviewConstructor(type) {
|
|
switch (type) {
|
|
case 'bool':
|
|
case 'uint8':
|
|
return Uint8Array;
|
|
case 'int8':
|
|
return Int8Array;
|
|
case 'int16':
|
|
return Int16Array;
|
|
case 'uint16':
|
|
return Uint16Array;
|
|
case 'int32':
|
|
return Int32Array;
|
|
case 'uint32':
|
|
return Uint32Array;
|
|
case 'float32':
|
|
return Float32Array;
|
|
case 'float64':
|
|
return Float64Array;
|
|
default:
|
|
// should never run to here
|
|
throw new Error('unspecified error');
|
|
}
|
|
}
|
|
// convert a long number to a 32-bit integer (cast-down)
|
|
function longToNumber(i, type) {
|
|
// INT64, UINT32, UINT64
|
|
if (type === onnx_proto_1.onnx.TensorProto.DataType.INT64 || type === ortFbs.TensorDataType.INT64) {
|
|
if (i.greaterThanOrEqual(2147483648) || i.lessThan(-2147483648)) {
|
|
throw new TypeError('int64 is not supported');
|
|
}
|
|
}
|
|
else if (type === onnx_proto_1.onnx.TensorProto.DataType.UINT32 || type === ortFbs.TensorDataType.UINT32 ||
|
|
type === onnx_proto_1.onnx.TensorProto.DataType.UINT64 || type === ortFbs.TensorDataType.UINT64) {
|
|
if (i.greaterThanOrEqual(4294967296) || i.lessThan(0)) {
|
|
throw new TypeError('uint64 is not supported');
|
|
}
|
|
}
|
|
else {
|
|
throw new TypeError(`not a LONG type: ${onnx_proto_1.onnx.TensorProto.DataType[type]}`);
|
|
}
|
|
return i.toNumber();
|
|
}
|
|
// read one value from TensorProto
|
|
function readProto(view, type, byteOffset) {
|
|
switch (type) {
|
|
case onnx_proto_1.onnx.TensorProto.DataType.BOOL:
|
|
case onnx_proto_1.onnx.TensorProto.DataType.UINT8:
|
|
return view.getUint8(byteOffset);
|
|
case onnx_proto_1.onnx.TensorProto.DataType.INT8:
|
|
return view.getInt8(byteOffset);
|
|
case onnx_proto_1.onnx.TensorProto.DataType.UINT16:
|
|
return view.getUint16(byteOffset, true);
|
|
case onnx_proto_1.onnx.TensorProto.DataType.INT16:
|
|
return view.getInt16(byteOffset, true);
|
|
case onnx_proto_1.onnx.TensorProto.DataType.FLOAT:
|
|
return view.getFloat32(byteOffset, true);
|
|
case onnx_proto_1.onnx.TensorProto.DataType.INT32:
|
|
return view.getInt32(byteOffset, true);
|
|
case onnx_proto_1.onnx.TensorProto.DataType.UINT32:
|
|
return view.getUint32(byteOffset, true);
|
|
case onnx_proto_1.onnx.TensorProto.DataType.INT64:
|
|
return longToNumber(long_1.default.fromBits(view.getUint32(byteOffset, true), view.getUint32(byteOffset + 4, true), false), type);
|
|
case onnx_proto_1.onnx.TensorProto.DataType.DOUBLE:
|
|
return view.getFloat64(byteOffset, true);
|
|
case onnx_proto_1.onnx.TensorProto.DataType.UINT64:
|
|
return longToNumber(long_1.default.fromBits(view.getUint32(byteOffset, true), view.getUint32(byteOffset + 4, true), true), type);
|
|
default:
|
|
throw new Error(`cannot read from DataView for type ${onnx_proto_1.onnx.TensorProto.DataType[type]}`);
|
|
}
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./lib/onnxjs/util.ts":
|
|
/*!****************************!*\
|
|
!*** ./lib/onnxjs/util.ts ***!
|
|
\****************************/
|
|
/***/ (function(__unused_webpack_module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
// Licensed under the MIT License.
|
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
};
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.decodeUtf8String = exports.MAX_CLIP = exports.MIN_CLIP = exports.PoolConvUtil = exports.ReduceUtil = exports.SplitUtil = exports.MathUtil = exports.ShapeUtil = exports.LongUtil = exports.ProtoUtil = exports.GemmUtil = exports.arrayCopyHelper = exports.BroadcastUtil = exports.MatMulUtil = exports.ArrayUtil = exports.assert = exports.checkInputsShape = void 0;
|
|
const flatbuffers_1 = __webpack_require__(/*! flatbuffers */ "./node_modules/flatbuffers/js/flatbuffers.mjs");
|
|
const long_1 = __importDefault(__webpack_require__(/*! long */ "./node_modules/long/src/long.js"));
|
|
const onnx_proto_1 = __webpack_require__(/*! onnx-proto */ "./node_modules/onnx-proto/dist/onnx.js");
|
|
const tensor_1 = __webpack_require__(/*! ./tensor */ "./lib/onnxjs/tensor.ts");
|
|
// check the inputs shape before running an OP.
|
|
// return true when the inputs pass the check
|
|
// return false when the inputs do not fit the requirement
|
|
// throw exception when fatal error or not implemented
|
|
function checkInputsShape(inputs, ...expectedDimensions) {
|
|
if (!inputs || inputs.length !== expectedDimensions.length) {
|
|
return false;
|
|
}
|
|
for (let i = 0; i < inputs.length; i++) {
|
|
if (!inputs[i].dims || inputs[i].dims.length !== expectedDimensions[i]) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
exports.checkInputsShape = checkInputsShape;
|
|
// Evaluates the given expression and asserts error message if condition is unmet.
|
|
function assert(expr, msg) {
|
|
if (!expr) {
|
|
throw new Error(typeof msg === 'string' ? msg : msg());
|
|
}
|
|
}
|
|
exports.assert = assert;
|
|
class ArrayUtil {
|
|
/**
|
|
* Verifies if 2 input arrays contain the same elements.
|
|
* @param n1 Array 1
|
|
* @param n2 Array 2
|
|
* @returns Whether these 2 are equal
|
|
*/
|
|
static arraysEqual(n1, n2) {
|
|
if (n1.length !== n2.length) {
|
|
return false;
|
|
}
|
|
for (let i = 0; i < n1.length; i++) {
|
|
if (n1[i] !== n2[i]) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
}
|
|
exports.ArrayUtil = ArrayUtil;
|
|
class MatMulUtil {
|
|
/**
|
|
* Fix the input shapes for MatMul operation if they need fixing
|
|
* @param dimsA The shape of tensor A. Should be an array of positive integers
|
|
* @param dimsB The shape of tensor B. Should be an array of positive integers
|
|
* @returns A tuple containing the preprocessed input shapes as required by ONNX specifications
|
|
*/
|
|
static preprocessInputShapes(dimsA, dimsB) {
|
|
// If the first argument is 1-D, it is promoted to a matrix by prepending
|
|
// a 1 to its dimensions. After matrix multiplication the prepended 1 is
|
|
// removed.
|
|
const a = (dimsA.length === 1) ? [1, dimsA[0]] : dimsA;
|
|
// If the second argument is 1-D, it is promoted to a matrix by appending
|
|
// a 1 to its dimensions. After matrix multiplication the appended 1 is
|
|
// removed.
|
|
const b = (dimsB.length === 1) ? [dimsB[0], 1] : dimsB;
|
|
return [a, b];
|
|
}
|
|
/**
|
|
* Fix the output shape computed for MatMul operation if it needs fixing
|
|
* @param outputShape The computed outputShape. Should be an array (atleast of length 2) of positive integers.
|
|
* This will be mutated.
|
|
* @param aRank The rank of tensor A.
|
|
* @param bRank The rank of tensor B.
|
|
*/
|
|
static postprocessOutputShape(outputShape, aRank, bRank) {
|
|
// Remove prepended dimension if first input is 1d
|
|
if (aRank === 1) {
|
|
// outputShape = outputShape.slice(0, outputShape.length - 2).concat(outputShape.slice(outputShape.length - 1));
|
|
outputShape.splice(outputShape.length - 2, 1);
|
|
}
|
|
// Remove appended dimension if second input is 1d
|
|
if (bRank === 1) {
|
|
outputShape.pop();
|
|
}
|
|
}
|
|
/**
|
|
* Calculate the expected shape when matrix multiplication
|
|
* @param a The shape of tensor A. Should be a tuple of 2 positive integers
|
|
* @param b The shape of tensor B. Should be a tuple of 2 positive integers
|
|
* @returns The expected shape of the result, or undefined if N/A
|
|
*/
|
|
static calcMatMulShape(a, b) {
|
|
return (a[1] !== b[0]) ? undefined : [a[0], b[1]];
|
|
}
|
|
}
|
|
exports.MatMulUtil = MatMulUtil;
|
|
class BroadcastUtil {
|
|
/**
|
|
* Calculate the expected shape when broadcasting 2 tensors
|
|
* @param a The shape of tensor A. Should be an array of positive integers
|
|
* @param b The shape of tensor B. Should be an array of positive integers
|
|
* @param isMatMul Whether the operation is MatMul
|
|
* @returns The expected shape of the result, or undefined if N/A
|
|
*/
|
|
static calcShape(adims, bdims, isMatMul = false) {
|
|
const arank = adims.length;
|
|
const brank = bdims.length;
|
|
if (arank === 0) {
|
|
return bdims;
|
|
}
|
|
if (brank === 0) {
|
|
return adims;
|
|
}
|
|
const crank = Math.max(adims.length, bdims.length);
|
|
const cdims = new Array(crank);
|
|
// calculate the last 2 dimension if it is MatMul
|
|
if (isMatMul) {
|
|
if (arank < 2 || brank < 2) {
|
|
return undefined;
|
|
}
|
|
const cShapeMatMul = MatMulUtil.calcMatMulShape([adims[arank - 2], adims[arank - 1]], [bdims[brank - 2], bdims[brank - 1]]);
|
|
if (cShapeMatMul === undefined) {
|
|
return undefined;
|
|
}
|
|
[cdims[crank - 2], cdims[crank - 1]] = cShapeMatMul;
|
|
}
|
|
for (let i = isMatMul ? 3 : 1; i <= crank; i++) {
|
|
const aLen = arank - i < 0 ? 1 : adims[arank - i];
|
|
const bLen = brank - i < 0 ? 1 : bdims[brank - i];
|
|
if (aLen !== bLen && aLen > 1 && bLen > 1) {
|
|
return undefined;
|
|
}
|
|
cdims[crank - i] = Math.max(aLen, bLen);
|
|
}
|
|
return cdims;
|
|
}
|
|
/**
|
|
* Given the indices of a broadcasted tensor, calculate the original indices
|
|
* @param broadcastedIndices The given indices of the broadcasted tensor.
|
|
* @param originalShape The original shape of the tensor before broadcas
|
|
* @returns The calculated indices that maps to the original tensor.
|
|
*/
|
|
static index(broadcastedIndices, originalShape) {
|
|
// NOTE 1: we assume the parameter broadcastedIndices is valid. ie. it should have the same
|
|
// length as the broadcasted shape, and for each dimension the index should
|
|
// not be out of range.
|
|
const originalIndices = new Array(originalShape.length);
|
|
BroadcastUtil.fillIndex(broadcastedIndices, originalShape, originalIndices);
|
|
return originalIndices;
|
|
}
|
|
/**
|
|
* Given the indices of a broadcasted tensor, calculate the original indices
|
|
* @param broadcastedIndices The given indices of the broadcasted tensor.
|
|
* @param originalShape The original shape of the tensor before broadcast
|
|
* @param originalIndices The mapping of broadcastedIndices to the originalIndices (output parameter - will be
|
|
* mutated).
|
|
*/
|
|
static fillIndex(broadcastedIndices, originalShape, originalIndices) {
|
|
// NOTE 1: we assume the parameter broadcastedIndices is valid. ie. it should have the same length as the
|
|
// broadcasted shape, and for each dimension the index should not be out of range.
|
|
// NOTE 2: we assume the parameter originalIndices has the same length as the originalShape
|
|
const dimOffset = broadcastedIndices.length - originalShape.length;
|
|
for (let i = 0; i < originalShape.length; i++) {
|
|
originalIndices[i] = broadcastedIndices[dimOffset + i] % originalShape[i];
|
|
}
|
|
}
|
|
/**
|
|
* Perform the broadcasting operation on the specific operator
|
|
* @param a The input tensor A
|
|
* @param b The input tensor B
|
|
* @param op The operator lambda function
|
|
* @param inplace Whether to write the result back to A.
|
|
* @returns The result tensor, or undefined if input not broadcastable.
|
|
*/
|
|
static calc(a, b, op, inplace, resultType) {
|
|
const outputShape = BroadcastUtil.calcShape(a.dims, b.dims);
|
|
if (outputShape) {
|
|
if (inplace && !ShapeUtil.areEqual(outputShape, a.dims)) {
|
|
// B is not broadcastable to A, failed to calculate inplace.
|
|
return undefined;
|
|
}
|
|
const size = ShapeUtil.size(outputShape);
|
|
const c = inplace ? a : new tensor_1.Tensor(outputShape, resultType || a.type);
|
|
// both inputs are scalars
|
|
if (outputShape.length === 0) {
|
|
c.set([], op(a.get([]), b.get([])));
|
|
}
|
|
// atleast one input is a non-scalar
|
|
else {
|
|
const outputIndices = new Array(outputShape.length);
|
|
const originalIndicesA = new Array(a.dims.length);
|
|
const originalIndicesB = new Array(b.dims.length);
|
|
let valA = 0;
|
|
let valB = 0;
|
|
let isAScalar = false;
|
|
let isBScalar = false;
|
|
if (a.dims.length === 0) {
|
|
valA = a.get([]);
|
|
isAScalar = true;
|
|
}
|
|
if (b.dims.length === 0) {
|
|
valB = b.get([]);
|
|
isBScalar = true;
|
|
}
|
|
let rest;
|
|
for (let i = 0; i < size; i++) {
|
|
// traversal indices
|
|
rest = i;
|
|
for (let j = outputShape.length - 1; j >= 0; j--) {
|
|
outputIndices[j] = rest % outputShape[j];
|
|
rest = Math.floor(rest / outputShape[j]);
|
|
}
|
|
if (!isAScalar) {
|
|
// map outputIndices (which is actually broadcasted) to the originalIndices
|
|
BroadcastUtil.fillIndex(outputIndices, a.dims, originalIndicesA);
|
|
valA = a.get(originalIndicesA);
|
|
}
|
|
if (!isBScalar) {
|
|
BroadcastUtil.fillIndex(outputIndices, b.dims, originalIndicesB);
|
|
valB = b.get(originalIndicesB);
|
|
}
|
|
c.set(outputIndices, op(valA, valB));
|
|
}
|
|
}
|
|
return c;
|
|
}
|
|
return undefined;
|
|
}
|
|
/**
|
|
* Determine if a shape is unidirectional broadcastable to another shape
|
|
* @param shape The input shape
|
|
* @param finalShape The desired shape after broadcasting
|
|
*/
|
|
static isValidBroadcast(shape, finalShape) {
|
|
// align shape to the right
|
|
const inputRank = shape.length;
|
|
const finalRank = finalShape.length;
|
|
if (inputRank > finalRank) {
|
|
return false;
|
|
}
|
|
for (let i = 1; i <= inputRank; i++) {
|
|
if (shape[inputRank - i] !== 1 && shape[inputRank - i] !== finalShape[finalRank - i]) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
/**
|
|
* Determine the broadcasted dims in input shape based on the given output shape.
|
|
* Note that this function only returns the broadcasted dims.
|
|
* @param inputShape The input shape
|
|
* @param outputShape The output shape
|
|
* @returns The broadcasted dims in input shape.
|
|
*/
|
|
static getBroadcastDims(inputShape, outputShape) {
|
|
const inRank = inputShape.length;
|
|
const dims = [];
|
|
for (let i = 0; i < inRank; i++) {
|
|
const dim = inRank - 1 - i;
|
|
const a = inputShape[dim] || 1;
|
|
const b = outputShape[outputShape.length - 1 - i] || 1;
|
|
if (b > 1 && a === 1) {
|
|
dims.unshift(dim);
|
|
}
|
|
}
|
|
return dims;
|
|
}
|
|
}
|
|
exports.BroadcastUtil = BroadcastUtil;
|
|
// copy array helper
|
|
// mimics memcpy as much as possible
|
|
function arrayCopyHelper(target, source, targetIndex, sourceIndex, blockSize) {
|
|
if (sourceIndex < 0 || sourceIndex >= source.length) {
|
|
throw new Error('sourceIndex out of bounds');
|
|
}
|
|
if (targetIndex < 0 || targetIndex >= target.length) {
|
|
throw new Error('targetIndex out of bounds');
|
|
}
|
|
if (sourceIndex + blockSize > source.length) {
|
|
throw new Error('source indices to be copied are outside bounds');
|
|
}
|
|
if (targetIndex + blockSize > target.length) {
|
|
throw new Error('target array is too small to hold result');
|
|
}
|
|
for (let offset = 0; offset < blockSize; offset++) {
|
|
target[targetIndex + offset] = source[sourceIndex + offset];
|
|
}
|
|
}
|
|
exports.arrayCopyHelper = arrayCopyHelper;
|
|
class GemmUtil {
|
|
// will make sure input shapes are compatible for this op
|
|
// and return back the shape of the output in the form of a tuple
|
|
// will throw exception if the input shapes are not compatible
|
|
static getShapeOfGemmResult(leftShape, transLeft, rightShape, transRight, biasShape) {
|
|
if (leftShape.length !== 2 || rightShape.length !== 2) {
|
|
throw new Error('shape need to be of size 2');
|
|
}
|
|
let M;
|
|
let K;
|
|
let N;
|
|
if (transLeft) {
|
|
M = leftShape[1];
|
|
K = leftShape[0];
|
|
}
|
|
else {
|
|
M = leftShape[0];
|
|
K = leftShape[1];
|
|
}
|
|
let kDim = -1;
|
|
if (transRight) {
|
|
N = rightShape[0];
|
|
kDim = 1;
|
|
}
|
|
else {
|
|
N = rightShape[1];
|
|
kDim = 0;
|
|
}
|
|
if (rightShape[kDim] !== K) {
|
|
throw new Error('dimension mismatch');
|
|
}
|
|
if (M <= 0 || N <= 0 || K <= 0) {
|
|
throw new Error('invalid shape specified');
|
|
}
|
|
if (biasShape && !BroadcastUtil.isValidBroadcast(biasShape, [M, N])) {
|
|
throw new Error('gemm: invalid bias shape for broadcast');
|
|
}
|
|
return [M, N, K];
|
|
}
|
|
}
|
|
exports.GemmUtil = GemmUtil;
|
|
class ProtoUtil {
|
|
static tensorDataTypeFromProto(typeProto) {
|
|
switch (typeProto) {
|
|
case onnx_proto_1.onnx.TensorProto.DataType.INT8:
|
|
return 'int8';
|
|
case onnx_proto_1.onnx.TensorProto.DataType.UINT8:
|
|
return 'uint8';
|
|
case onnx_proto_1.onnx.TensorProto.DataType.BOOL:
|
|
return 'bool';
|
|
case onnx_proto_1.onnx.TensorProto.DataType.INT16:
|
|
return 'int16';
|
|
case onnx_proto_1.onnx.TensorProto.DataType.UINT16:
|
|
return 'uint16';
|
|
case onnx_proto_1.onnx.TensorProto.DataType.INT32:
|
|
return 'int32';
|
|
case onnx_proto_1.onnx.TensorProto.DataType.UINT32:
|
|
return 'uint32';
|
|
case onnx_proto_1.onnx.TensorProto.DataType.FLOAT:
|
|
return 'float32';
|
|
case onnx_proto_1.onnx.TensorProto.DataType.DOUBLE:
|
|
return 'float64';
|
|
case onnx_proto_1.onnx.TensorProto.DataType.STRING:
|
|
return 'string';
|
|
// For INT64/UINT64, reduce their value to 32-bits.
|
|
// Should throw exception when overflow
|
|
case onnx_proto_1.onnx.TensorProto.DataType.INT64:
|
|
return 'int32';
|
|
case onnx_proto_1.onnx.TensorProto.DataType.UINT64:
|
|
return 'uint32';
|
|
default:
|
|
throw new Error(`unsupported data type: ${onnx_proto_1.onnx.TensorProto.DataType[typeProto]}`);
|
|
}
|
|
}
|
|
static tensorDataTypeStringToEnum(type) {
|
|
switch (type) {
|
|
case 'int8':
|
|
return onnx_proto_1.onnx.TensorProto.DataType.INT8;
|
|
case 'uint8':
|
|
return onnx_proto_1.onnx.TensorProto.DataType.UINT8;
|
|
case 'bool':
|
|
return onnx_proto_1.onnx.TensorProto.DataType.BOOL;
|
|
case 'int16':
|
|
return onnx_proto_1.onnx.TensorProto.DataType.INT16;
|
|
case 'uint16':
|
|
return onnx_proto_1.onnx.TensorProto.DataType.UINT16;
|
|
case 'int32':
|
|
return onnx_proto_1.onnx.TensorProto.DataType.INT32;
|
|
case 'uint32':
|
|
return onnx_proto_1.onnx.TensorProto.DataType.UINT32;
|
|
case 'float32':
|
|
return onnx_proto_1.onnx.TensorProto.DataType.FLOAT;
|
|
case 'float64':
|
|
return onnx_proto_1.onnx.TensorProto.DataType.DOUBLE;
|
|
case 'string':
|
|
return onnx_proto_1.onnx.TensorProto.DataType.STRING;
|
|
case 'int64':
|
|
return onnx_proto_1.onnx.TensorProto.DataType.INT64;
|
|
case 'uint64':
|
|
return onnx_proto_1.onnx.TensorProto.DataType.UINT64;
|
|
default:
|
|
throw new Error(`unsupported data type: ${type}`);
|
|
}
|
|
}
|
|
static tensorDimsFromProto(dims) {
|
|
// get rid of Long type for dims
|
|
return dims.map(d => long_1.default.isLong(d) ? d.toNumber() : d);
|
|
}
|
|
static tensorValueTypeFromProto(valueType) {
|
|
return {
|
|
tensorType: ProtoUtil.tensorDataTypeFromProto(valueType.elemType),
|
|
shape: { dims: ProtoUtil.tensorDimsFromProto(valueType.shape.dim.map(d => d.dimValue)) }
|
|
};
|
|
}
|
|
static tensorDimsFromORTFormat(tensor) {
|
|
const dims = [];
|
|
for (let i = 0; i < tensor.dimsLength(); i++) {
|
|
dims.push(LongUtil.longToNumber(tensor.dims(i)));
|
|
}
|
|
return dims;
|
|
}
|
|
static tensorAttributesFromORTFormat(node) {
|
|
const attributes = [];
|
|
for (let i = 0; i < node.attributesLength(); i++) {
|
|
attributes.push(node.attributes(i));
|
|
}
|
|
return attributes;
|
|
}
|
|
}
|
|
exports.ProtoUtil = ProtoUtil;
|
|
class LongUtil {
|
|
// This function is called to get a number from long type of data for attribute, dim, and ir version,
|
|
// which values are signed integers.
|
|
// To make it more generic, add an optional paramter to convert to a unsigned number.
|
|
static longToNumber(n, unsigned) {
|
|
if (long_1.default.isLong(n)) {
|
|
return n.toNumber();
|
|
}
|
|
else if (n instanceof flatbuffers_1.flatbuffers.Long) {
|
|
return long_1.default.fromValue({ low: n.low, high: n.high, unsigned: unsigned !== null && unsigned !== void 0 ? unsigned : false }).toNumber();
|
|
}
|
|
return n;
|
|
}
|
|
static isLong(n) {
|
|
return long_1.default.isLong(n) || n instanceof flatbuffers_1.flatbuffers.Long;
|
|
}
|
|
}
|
|
exports.LongUtil = LongUtil;
|
|
class ShapeUtil {
|
|
static size(dims) {
|
|
return ShapeUtil.getSizeFromDimensionRange(dims, 0, dims.length);
|
|
}
|
|
// `axis` inclusive
|
|
static sizeFromDimension(dims, axis) {
|
|
if (axis < 0 || axis > dims.length) {
|
|
throw new Error(`invalid dimension of ${axis} for sizeFromDimension as Tensor has ${dims.length} dimensions.`);
|
|
}
|
|
return ShapeUtil.getSizeFromDimensionRange(dims, axis, dims.length);
|
|
}
|
|
// `axis` exclusive
|
|
static sizeToDimension(dims, axis) {
|
|
if (axis < 0 || axis > dims.length) {
|
|
throw new Error(`invalid dimension of ${axis} for sizeToDimension as Tensor has ${dims.length} dimensions.`);
|
|
}
|
|
return ShapeUtil.getSizeFromDimensionRange(dims, 0, axis);
|
|
}
|
|
static getSizeFromDimensionRange(dims, start, end) {
|
|
let size = 1;
|
|
for (let i = start; i < end; i++) {
|
|
// safety check as this method is called by multiple other methods requiring size.
|
|
// size cannot be 0 or negative.
|
|
if (dims[i] <= 0) {
|
|
throw new Error(
|
|
// eslint-disable-next-line max-len
|
|
'cannot get valid size from specified dimension range. Most likely the range contains 0 or negative values in them.');
|
|
}
|
|
size *= dims[i];
|
|
}
|
|
return size;
|
|
}
|
|
static computeStrides(dims) {
|
|
const rank = dims.length;
|
|
if (rank === 0) {
|
|
return [];
|
|
}
|
|
else if (rank === 1) {
|
|
return [1];
|
|
}
|
|
const strides = new Array(rank);
|
|
strides[rank - 1] = 1;
|
|
strides[rank - 2] = dims[rank - 1];
|
|
for (let i = rank - 3; i >= 0; --i) {
|
|
strides[i] = strides[i + 1] * dims[i + 1];
|
|
}
|
|
return strides;
|
|
}
|
|
static transpose(dims) {
|
|
const copy = dims.slice();
|
|
return copy.reverse();
|
|
}
|
|
static indicesToOffset(indices, strides, axis) {
|
|
if (axis === undefined) {
|
|
axis = indices.length;
|
|
}
|
|
let offset = 0;
|
|
for (let i = 0; i < axis; ++i) {
|
|
offset += strides[i] * indices[i];
|
|
}
|
|
return offset;
|
|
}
|
|
static offsetToIndices(offset, strides) {
|
|
const rank = strides.length;
|
|
if (rank === 0) {
|
|
return [];
|
|
}
|
|
else if (rank === 1) {
|
|
return [offset * strides[0]];
|
|
}
|
|
const indices = new Array(strides.length);
|
|
for (let i = 0; i < indices.length - 1; ++i) {
|
|
indices[i] = Math.floor(offset / strides[i]);
|
|
offset -= indices[i] * strides[i];
|
|
}
|
|
indices[indices.length - 1] = offset;
|
|
return indices;
|
|
}
|
|
/**
|
|
* normailze axis of range [-r, r) into [0, r).
|
|
*/
|
|
static normalizeAxis(axis, tensorRank) {
|
|
if (axis < -tensorRank && axis >= tensorRank) {
|
|
throw new Error('unsupported axis for this operation.');
|
|
}
|
|
return axis < 0 ? axis + tensorRank : axis;
|
|
}
|
|
static normalizeAxes(axes, tensorRank) {
|
|
return axes.map(x => this.normalizeAxis(x, tensorRank));
|
|
}
|
|
// Increment an index into a tensor (in lexicographic
|
|
// ordering), wrapping around the specified upper_bound.
|
|
/**
|
|
* Increment an index into a tensor (in lexicographic ordering), wrapping around the specified upper_bound.
|
|
* @param index Given index to increment (Will be mutated)
|
|
* @param dims The dimensions of the tensor for which the given index corresponds to
|
|
* @param axisToIncrementOn The 1-indexed axis to increment on. If undefined, axisToIncrementOn == rank
|
|
*/
|
|
static incrementIndex(index, dims, axisToIncrementOn) {
|
|
if (dims.length === 0 || index.length === 0) {
|
|
throw new Error('Index incrementing unsupported for scalar Tensor');
|
|
}
|
|
if (axisToIncrementOn === undefined) {
|
|
axisToIncrementOn = dims.length;
|
|
}
|
|
else {
|
|
if (axisToIncrementOn <= 0 || axisToIncrementOn > dims.length) {
|
|
throw new Error('Incorrect axis to increment on');
|
|
}
|
|
}
|
|
for (let k = axisToIncrementOn - 1; k >= 0; --k) {
|
|
index[k]++;
|
|
if (index[k] < dims[k]) {
|
|
break;
|
|
}
|
|
index[k] = 0;
|
|
}
|
|
}
|
|
/**
|
|
* Produces a new dimensions array based on the values in the 'originalDimensions' and 'shape' array
|
|
* Used in Reshape
|
|
* @param originalDims Original Shape array
|
|
* @param shapeHints array containing values to compute the new dimensions
|
|
* For example:
|
|
* originalDims = [2,2] and shapeHints = [0,-1] will return [2,2]
|
|
* originalDims = [2,2] and shapeHints = [4] will return [4]
|
|
* originalDims = [2,2] and shapeHints = [5] will throw an exception
|
|
* https://github.com/onnx/onnx/blob/main/docs/Operators.md#Reshape
|
|
*/
|
|
static calculateReshapedDims(originalDims, shapeHints) {
|
|
// reshape to a Scalar Tensor
|
|
if (shapeHints.length === 0) {
|
|
if (originalDims.length === 0 || ShapeUtil.size(originalDims) === 1) {
|
|
return [];
|
|
}
|
|
else {
|
|
throw new Error('cannot reshape to a scalar Tensor');
|
|
}
|
|
}
|
|
const nDims = shapeHints.length;
|
|
const reshapedDims = new Array(nDims);
|
|
let unknownDimension = -1;
|
|
let newTensorSize = 1;
|
|
for (let i = 0; i < nDims; i++) {
|
|
if (shapeHints[i] < -1) {
|
|
throw new Error('a dimension in shape hints cannot be less than -1');
|
|
}
|
|
if (shapeHints[i] === -1) {
|
|
if (unknownDimension !== -1) {
|
|
throw new Error('at most one dimension in shape hints can be -1');
|
|
}
|
|
unknownDimension = i;
|
|
}
|
|
else {
|
|
if (shapeHints[i] === 0) {
|
|
if (i >= originalDims.length) {
|
|
throw new Error('the dimension with value zero exceeds the dimension size of the input tensor');
|
|
}
|
|
reshapedDims[i] = originalDims[i];
|
|
}
|
|
else {
|
|
reshapedDims[i] = shapeHints[i];
|
|
}
|
|
newTensorSize *= reshapedDims[i];
|
|
}
|
|
}
|
|
const oldTensorSize = ShapeUtil.size(originalDims);
|
|
if (unknownDimension !== -1) {
|
|
if (oldTensorSize % newTensorSize !== 0) {
|
|
throw new Error(`the input tensor cannot be reshaped to the requested shape. Input shape: [${originalDims}] Output shape: [${shapeHints}]`);
|
|
}
|
|
reshapedDims[unknownDimension] = oldTensorSize / newTensorSize;
|
|
}
|
|
// validate sizes from originalDims and reshapedDims match
|
|
else {
|
|
if (newTensorSize !== oldTensorSize) {
|
|
throw new Error('reshapedDims and originalDims don\'t have matching sizes');
|
|
}
|
|
}
|
|
return reshapedDims;
|
|
}
|
|
/**
|
|
* Sorts a given array based on the indices in the Perm array
|
|
* Used in Transpose
|
|
* @param a Array to be sorted such as dims or strides
|
|
* @param perm Perm given; if null a will be reversed
|
|
*/
|
|
static sortBasedOnPerm(a, perm) {
|
|
if (perm) {
|
|
return perm.map((v) => a[v]);
|
|
}
|
|
else {
|
|
return a.slice().reverse();
|
|
}
|
|
}
|
|
/**
|
|
* Pads a given shape according to the padding values
|
|
* @param dims shape of the Tensor to be padded
|
|
* @param pad pad values
|
|
*/
|
|
static padShape(dims, pad) {
|
|
const rank = dims.length;
|
|
return dims.map((v, i) => v + pad[i] + pad[i + rank]);
|
|
}
|
|
/**
|
|
* Determines if the two shapes are identical
|
|
* @param shape1
|
|
* @param shape2
|
|
*/
|
|
static areEqual(shape1, shape2) {
|
|
if (shape1.length !== shape2.length) {
|
|
return false;
|
|
}
|
|
return shape1.every((v, i) => v === shape2[i]);
|
|
}
|
|
/**
|
|
* Validates if the given `dims` or `shape` is valid in ONNX.js context and returns data size
|
|
* @param dims - input `dims` that needs to be checked
|
|
*/
|
|
static validateDimsAndCalcSize(dims) {
|
|
if (dims.length > 6) {
|
|
throw new TypeError('Only rank 0 to 6 is supported for tensor shape.');
|
|
}
|
|
let size = 1;
|
|
for (const n of dims) {
|
|
if (!Number.isInteger(n)) {
|
|
throw new TypeError(`Invalid shape: ${n} is not an integer`);
|
|
}
|
|
if (n < 0 || n > 2147483647) {
|
|
throw new TypeError(`Invalid shape: length ${n} is not allowed`);
|
|
}
|
|
size *= n;
|
|
}
|
|
return size;
|
|
}
|
|
/**
|
|
* Determines the shape of output tensor y = flatten(x, axis)
|
|
* @param dims - shape of input tensor
|
|
* @param axis - flatten axis, in the range [-r, r]
|
|
*/
|
|
static flattenShape(dims, axis) {
|
|
if (axis < 0) {
|
|
axis += dims.length;
|
|
}
|
|
const total = dims.reduce((x, y) => x * y, 1);
|
|
const right = dims.slice(axis).reduce((x, y) => x * y, 1);
|
|
const outputDims = [total / right, right];
|
|
return outputDims;
|
|
}
|
|
/**
|
|
* Determines the shape of output tensor y = squeeze(x, axes)
|
|
* @param dims - shape of input tensor
|
|
* @param axes - squeeze axes
|
|
*/
|
|
static squeezeShape(dims, axes) {
|
|
const outputDims = new Array();
|
|
// sanity check
|
|
axes = ShapeUtil.normalizeAxes(axes, dims.length);
|
|
for (let i = 0; i < dims.length; i++) {
|
|
const inSqueezeList = axes.indexOf(i) >= 0;
|
|
if (inSqueezeList && dims[i] !== 1) {
|
|
throw new Error('squeeze an axis of size different than 1');
|
|
}
|
|
if ((axes.length === 0 && dims[i] > 1) || (axes.length > 0 && !inSqueezeList)) {
|
|
outputDims.push(dims[i]);
|
|
}
|
|
}
|
|
return outputDims;
|
|
}
|
|
/**
|
|
* Determines the shape of output tensor y = unsqueeze(x, axes)
|
|
* @param dims - shape of input tensor
|
|
* @param axes - unsqueeze axes
|
|
*/
|
|
static unsqueezeShape(dims, axes) {
|
|
const outputDims = new Array(dims.length + axes.length);
|
|
// initialize the array elements to 0
|
|
outputDims.fill(0);
|
|
// set all axes indices to 1 in outputDims and check for duplicates
|
|
for (let i = 0; i < axes.length; i++) {
|
|
const axis = ShapeUtil.normalizeAxis(axes[i], outputDims.length);
|
|
if (axis >= outputDims.length) {
|
|
throw new Error('\'axes\' has an out of range axis');
|
|
}
|
|
if (outputDims[axis] !== 0) {
|
|
throw new Error('\'axes\' has a duplicate axis');
|
|
}
|
|
outputDims[axis] = 1;
|
|
}
|
|
// fill in the zero entries of outputDims with the input tensor's shape
|
|
let inputDimsIterator = 0;
|
|
for (let i = 0; i < outputDims.length; i++) {
|
|
if (outputDims[i] === 0) {
|
|
outputDims[i] = dims[inputDimsIterator++];
|
|
}
|
|
}
|
|
// sanity check assertion. 'inputDimsIterator'
|
|
// should be equal to the length of 'dims'
|
|
if (inputDimsIterator !== dims.length) {
|
|
throw new Error('the unsqueezed dimension could not be established');
|
|
}
|
|
return outputDims;
|
|
}
|
|
}
|
|
exports.ShapeUtil = ShapeUtil;
|
|
// bunch of helper methods that do a variety of math operations
|
|
class MathUtil {
|
|
// y = (x*x) + y
|
|
static sqr(target, source, targetIndex, sourceIndex, blockSize) {
|
|
if (sourceIndex < 0 || sourceIndex >= source.length) {
|
|
throw new Error('sourceIndex out of bounds');
|
|
}
|
|
if (targetIndex < 0 || targetIndex >= target.length) {
|
|
throw new Error('targetIndex out of bounds');
|
|
}
|
|
if (sourceIndex + blockSize > source.length) {
|
|
throw new Error('source indices to be copied are outside bounds');
|
|
}
|
|
if (targetIndex + blockSize > target.length) {
|
|
throw new Error('target array is too small to hold result');
|
|
}
|
|
for (let offset = 0; offset < blockSize; offset++) {
|
|
target[targetIndex + offset] += Math.pow(source[sourceIndex + offset], 2);
|
|
}
|
|
}
|
|
// y = ax + y
|
|
static axpy(target, source, targetIndex, sourceIndex, blockSize, alpha) {
|
|
if (sourceIndex < 0 || sourceIndex >= source.length) {
|
|
throw new Error('sourceIndex out of bounds');
|
|
}
|
|
if (targetIndex < 0 || targetIndex >= target.length) {
|
|
throw new Error('targetIndex out of bounds');
|
|
}
|
|
if (sourceIndex + blockSize > source.length) {
|
|
throw new Error('source indices to be copied are outside bounds');
|
|
}
|
|
if (targetIndex + blockSize > target.length) {
|
|
throw new Error('target array is too small to hold result');
|
|
}
|
|
for (let offset = 0; offset < blockSize; offset++) {
|
|
target[targetIndex + offset] += (alpha * source[sourceIndex + offset]);
|
|
}
|
|
}
|
|
// y = pow(x, b)
|
|
static powx(target, source, targetIndex, sourceIndex, blockSize, b) {
|
|
if (sourceIndex < 0 || sourceIndex >= source.length) {
|
|
throw new Error('sourceIndex out of bounds');
|
|
}
|
|
if (targetIndex < 0 || targetIndex >= target.length) {
|
|
throw new Error('targetIndex out of bounds');
|
|
}
|
|
if (sourceIndex + blockSize > source.length) {
|
|
throw new Error('source indices to be copied are outside bounds');
|
|
}
|
|
if (targetIndex + blockSize > target.length) {
|
|
throw new Error('target array is too small to hold result');
|
|
}
|
|
for (let offset = 0; offset < blockSize; offset++) {
|
|
target[targetIndex + offset] = Math.pow(source[sourceIndex + offset], b);
|
|
}
|
|
}
|
|
// y = x * y
|
|
static mul(target, source, targetIndex, sourceIndex, blockSize) {
|
|
if (sourceIndex < 0 || sourceIndex >= source.length) {
|
|
throw new Error('sourceIndex out of bounds');
|
|
}
|
|
if (targetIndex < 0 || targetIndex >= target.length) {
|
|
throw new Error('targetIndex out of bounds');
|
|
}
|
|
if (sourceIndex + blockSize > source.length) {
|
|
throw new Error('source indices to be copied are outside bounds');
|
|
}
|
|
if (targetIndex + blockSize > target.length) {
|
|
throw new Error('target array is too small to hold result');
|
|
}
|
|
for (let offset = 0; offset < blockSize; offset++) {
|
|
target[targetIndex + offset] = (source[sourceIndex + offset] * target[targetIndex + offset]);
|
|
}
|
|
}
|
|
}
|
|
exports.MathUtil = MathUtil;
|
|
class SplitUtil {
|
|
/**
|
|
* Calculates new Shapes from existing one and the splits given along the axis provides
|
|
* @param dims Shape of the Tensor to be splitted into two or more Shapes
|
|
* @param axis The dimension along which the Tensor will be split
|
|
* @param splits Offsets for the start of each split
|
|
*/
|
|
static splitShape(dims, axis, split, numOutputs) {
|
|
if (split.length === 0) {
|
|
if (!numOutputs) {
|
|
throw new Error('need to know number of outputs when the \'split\' attribute is not specified');
|
|
}
|
|
SplitUtil.determineSplit(dims[axis], numOutputs, split);
|
|
}
|
|
const shapes = [];
|
|
const offsets = [0];
|
|
for (let i = 0; i < split.length; ++i) {
|
|
if (i !== 0) {
|
|
offsets.push(offsets[i - 1] + split[i - 1]);
|
|
}
|
|
const shape = dims.slice();
|
|
shape[axis] = split[i];
|
|
shapes.push(shape);
|
|
}
|
|
return [shapes, offsets];
|
|
}
|
|
static determineSplit(numElementsAlongAxis, numOutputs, split) {
|
|
// If 'split' is not specified by the user, we need to partition the number of elements equally among the outputs
|
|
if (numElementsAlongAxis % numOutputs !== 0) {
|
|
throw new Error('cannot split tensor to equal sized parts');
|
|
}
|
|
for (let i = 0; i < numOutputs; ++i) {
|
|
split.push(numElementsAlongAxis / numOutputs);
|
|
}
|
|
}
|
|
}
|
|
exports.SplitUtil = SplitUtil;
|
|
class ReduceUtil {
|
|
/**
|
|
* Perform reduce operations on the specific operator
|
|
* @param a Input tensor data
|
|
* @param axes The dimensions along which the Tensor will be reduced
|
|
* @param keepdims If set to true, the axes which are reduced are left in the
|
|
* result as dimensions with size one.
|
|
* @param op1 The operation to be performed on each element in the tensor
|
|
* @param op2 The operation to be performed between elements in the tensor
|
|
*/
|
|
static calcReduce(a, axes, keepdims, op1, op2) {
|
|
const dims = a.dims.slice(0);
|
|
// if axes is not set, perform reduce on all axes
|
|
if (axes.length === 0) {
|
|
dims.forEach((d, ind) => axes.push(ind));
|
|
}
|
|
// get a temporary broadcastable output shape
|
|
const outputDims = ReduceUtil.calcReduceShape(dims, axes, true);
|
|
// loop through the output and calculate result one by one
|
|
const size = ShapeUtil.size(outputDims);
|
|
const y = new tensor_1.Tensor(outputDims, a.type);
|
|
const strides = ShapeUtil.computeStrides(outputDims);
|
|
const inputStrides = ShapeUtil.computeStrides(dims);
|
|
const indicesY = new Array(dims.length);
|
|
for (let i = 0; i < size; i++) {
|
|
const indices = ShapeUtil.offsetToIndices(i, strides);
|
|
// map index
|
|
BroadcastUtil.fillIndex(indices, dims, indicesY);
|
|
y.set(indices, ReduceUtil.calcReduceByAxis(a.numberData, axes, dims, 0, ShapeUtil.indicesToOffset(indicesY, inputStrides), op1, op2));
|
|
}
|
|
if (keepdims) {
|
|
return y;
|
|
}
|
|
else {
|
|
// keepdims == 0, calculate the expected shape
|
|
return new tensor_1.Tensor(ReduceUtil.calcReduceShape(dims, axes, keepdims), y.type, undefined, undefined, y.data, y.dataId);
|
|
}
|
|
}
|
|
/**
|
|
* Perform reduce operations on the specific operator on specific axes
|
|
* @param a Input tensor data
|
|
* @param axes The dimensions along which the Tensor will be reduced
|
|
* @param dims The input dimension.
|
|
* @param curAxisInd Index in axes specifying the current dimension along
|
|
* which the tensor will be reduced
|
|
* @param pos The current index of element to perform operation
|
|
* @param op1 The operation to be performed on each element in the tensor
|
|
* @param op2 The operation to be performed between elements in the tensor
|
|
*/
|
|
static calcReduceByAxis(input, axes, dims, curAxisInd, pos, op1, op2) {
|
|
let res = 0;
|
|
if (curAxisInd >= axes.length) {
|
|
return op1(input[pos]);
|
|
}
|
|
const axis = axes[curAxisInd];
|
|
const step = axis >= dims.length ? 1 : ShapeUtil.size(dims.slice(axis + 1));
|
|
for (let i = 0; i < dims[axis]; i++) {
|
|
res = i === 0 ? ReduceUtil.calcReduceByAxis(input, axes, dims, curAxisInd + 1, pos, op1, op2) :
|
|
op2(res, ReduceUtil.calcReduceByAxis(input, axes, dims, curAxisInd + 1, pos, op1, op2));
|
|
pos += step;
|
|
}
|
|
return res;
|
|
}
|
|
/**
|
|
* Calculate the expected shape of a reduce operation
|
|
* @param dims The input tensor dimension
|
|
* @param axes The dimensions along which the Tensor will be reduced
|
|
* @param keepdims If set to true, the axes which are reduced are left in the
|
|
* result as dimensions with size one.
|
|
*/
|
|
static calcReduceShape(dims, axes, keepDims) {
|
|
const outputDims = dims.slice();
|
|
for (let i = 0; i < axes.length; i++) {
|
|
if (keepDims) {
|
|
outputDims[axes[i]] = 1;
|
|
}
|
|
else {
|
|
outputDims[axes[i]] = 0;
|
|
}
|
|
}
|
|
return outputDims.filter(dim => dim !== 0);
|
|
}
|
|
}
|
|
exports.ReduceUtil = ReduceUtil;
|
|
class PoolConvUtil {
|
|
/**
|
|
* Adjust the kernel, strides, pads to correct rank. Set to default value if not present
|
|
* @param isGlobalOperator If true, perform global pooling.
|
|
* @param inputDims The input tensor dimension.
|
|
* @param kernelShape The size of the kernel along each axis.
|
|
* @param strides Stride along each axis.
|
|
* @param dilations Dilation along each axis.
|
|
* @param pads Padding for the beginning and ending along each axis.
|
|
*/
|
|
static adjustPoolAttributes(isGlobalOperator, inputDims, kernelShape, strides, dilations, pads) {
|
|
if (!isGlobalOperator && kernelShape.length !== inputDims.length - 2) {
|
|
throw new Error('length of specified kernel shapes should be 2 less than length of input dimensions');
|
|
}
|
|
if (isGlobalOperator) {
|
|
// adjust kernel shape to cover the input dims
|
|
for (let dim = 0; dim < inputDims.length - 2; dim++) {
|
|
if (dim >= kernelShape.length) {
|
|
kernelShape.push(inputDims[dim + 2]);
|
|
}
|
|
else {
|
|
kernelShape[dim] = inputDims[dim + 2];
|
|
}
|
|
}
|
|
}
|
|
// adjust strides length to match kernel shape length
|
|
for (let dim = 0; dim < kernelShape.length; dim++) {
|
|
if (dim < strides.length) {
|
|
if (strides[dim] < 0) {
|
|
throw new Error('strides should be greater than or equal to 1');
|
|
}
|
|
}
|
|
else {
|
|
strides.push(1);
|
|
}
|
|
}
|
|
// adjust dilation value
|
|
for (let dim = 0; dim < kernelShape.length; dim++) {
|
|
if (dim < dilations.length) {
|
|
if (dilations[dim] < 0) {
|
|
throw new Error('dilations should be greater than or equal to 1');
|
|
}
|
|
}
|
|
else {
|
|
dilations.push(1);
|
|
}
|
|
}
|
|
// adjust pads length to match 2 * kernel shape length
|
|
for (let dim = 0; dim < kernelShape.length * 2; dim++) {
|
|
if (dim < pads.length) {
|
|
if (pads[dim] < 0) {
|
|
throw new Error('pad should be greater than or equal to 1');
|
|
}
|
|
}
|
|
else {
|
|
pads.push(0);
|
|
}
|
|
}
|
|
// sanity checks for values in kernel shapes and pads
|
|
for (let dim = 0; dim < kernelShape.length; dim++) {
|
|
if (kernelShape[dim] <= 0) {
|
|
throw new Error('kernel shapes need to be greater than 0');
|
|
}
|
|
if (pads[dim] >= kernelShape[dim] || pads[dim + kernelShape.length] >= kernelShape[dim]) {
|
|
throw new Error('pads should be smaller than kernel');
|
|
}
|
|
}
|
|
}
|
|
// adjust pad values based on 'autoPad' attribute
|
|
static adjustPadsBasedOnAutoPad(inputDims, strides, dilations, kernelShape, pads, autoPad) {
|
|
if (!autoPad) {
|
|
return;
|
|
}
|
|
if (pads.length !== 2 * (inputDims.length - 2)) {
|
|
throw new Error('length of pads should be twice the length of data dimensions');
|
|
}
|
|
if (strides.length !== (inputDims.length - 2)) {
|
|
throw new Error('length of strides should be the length of data dimensions');
|
|
}
|
|
if (kernelShape.length !== (inputDims.length - 2)) {
|
|
throw new Error('length of kernel shapes should be the length of data dimensions');
|
|
}
|
|
for (let dim = 0; dim < inputDims.length - 2; dim++) {
|
|
PoolConvUtil.adjustPadAndReturnShape(inputDims[dim + 2], strides[dim], dilations[dim], kernelShape[dim], pads, dim, dim + inputDims.length - 2, autoPad);
|
|
}
|
|
}
|
|
/**
|
|
* Calculate the output shape for Pool ops based on input attributes. (Should be used only for Pool ops)
|
|
* @param isGlobalOperator If true, perform global pooling.
|
|
* @param inputDims The input tensor dimension. (inputs[0].dims)
|
|
* @param strides Stride along each axis.
|
|
* @param dilations Dilation along each axis.
|
|
* @param kernelShape The size of the kernel along each axis.
|
|
* @param pads Padding for the beginning and ending along each axis.
|
|
* @param autoPad DEPRECATED attribute supported for legacy models. Specifies how to implicitly calculate pads in each
|
|
* dimension. Can take values NOTSET, SAME_UPPER, SAME_LOWER, or VALID.
|
|
*/
|
|
static computePoolOutputShape(isGlobalOperator, inputDims, strides, dilations, kernelShape, pads, autoPad) {
|
|
if (inputDims.length <= 0) {
|
|
throw new Error('input shape must be of size greater than 0');
|
|
}
|
|
// Add batch size and number of channels of output
|
|
const outputDims = [inputDims[0], inputDims[1]];
|
|
PoolConvUtil.computeShapeHelper(isGlobalOperator, inputDims, outputDims, strides, dilations, kernelShape, pads, autoPad);
|
|
return outputDims;
|
|
}
|
|
/**
|
|
* Calculate the output shape for Conv op based on input attributes. (Should be used only for Conv op)
|
|
* @param inputDims The input tensor dimension. (inputs[0].dims)
|
|
* @param filterDims The filter tensor dimension. (inputs[1].dims)
|
|
* @param strides Stride along each axis.
|
|
* @param kernelShape The size of the kernel along each axis.
|
|
* @param pads Padding for the beginning and ending along each axis.
|
|
* @param autoPad DEPRECATED attribute supported for legacy models. Specifies how to implicitly calculate pads in each
|
|
* dimension. Can take values NOTSET, SAME_UPPER, SAME_LOWER, or VALID.
|
|
*/
|
|
static computeConvOutputShape(inputDims, filterDims, strides, dilations, kernelShape, pads, autoPad) {
|
|
if (inputDims.length <= 0 || filterDims.length <= 0) {
|
|
throw new Error('invalid input tensor dims or invalid filter tensor dims');
|
|
}
|
|
// Add batch size and number of channels of output
|
|
const outputDims = [inputDims[0], filterDims[0]];
|
|
PoolConvUtil.computeShapeHelper(false, inputDims, outputDims, strides, dilations, kernelShape, pads, autoPad);
|
|
return outputDims;
|
|
}
|
|
// will compute output shapes for data dimensions ONLY (i.e.) no batch size and channels
|
|
// called by computePoolOutputShape() and computeConvOutputShape()
|
|
// adjust pads based on 'autoPad' attribute prior to shape computation
|
|
static computeShapeHelper(isGlobalOperator, inputDims, outputDims, strides, dilations, kernelShape, pads, autoPad) {
|
|
if (isGlobalOperator) {
|
|
for (let dim = 0; dim < inputDims.length - 2; dim++) {
|
|
outputDims.push(1);
|
|
}
|
|
}
|
|
else {
|
|
for (let dim = 0; dim < inputDims.length - 2; dim++) {
|
|
outputDims.push(PoolConvUtil.adjustPadAndReturnShape(inputDims[dim + 2], strides[dim], dilations[dim], kernelShape[dim], pads, dim, dim + inputDims.length - 2, autoPad));
|
|
}
|
|
}
|
|
}
|
|
// helper for computeShapeHelper() and adjustPadsBasedOnAutoPad()
|
|
// adjusts pad value for given 'autoPad' string and computes output shape along a particular dimension
|
|
static adjustPadAndReturnShape(inSize, stride, dilation, kernel, pads, padHeadIndex, padTailIndex, autoPad) {
|
|
const dkernel = dilation * (kernel - 1) + 1;
|
|
if (autoPad && autoPad !== 'NOTSET') {
|
|
switch (autoPad) {
|
|
case 'VALID':
|
|
pads[padHeadIndex] = 0;
|
|
pads[padTailIndex] = 0;
|
|
return Math.floor(((inSize - dkernel) / stride) + 1);
|
|
case 'SAME_LOWER':
|
|
case 'SAME_UPPER':
|
|
if (dilation !== 1) {
|
|
throw new Error('Dilation not supported for SAME_UPPER or SAME_LOWER');
|
|
}
|
|
else {
|
|
const legacyTargetSize = (inSize + stride - 1) / stride;
|
|
const padNeeded = (legacyTargetSize - 1) * stride + kernel - inSize;
|
|
pads[padHeadIndex] =
|
|
(autoPad === 'SAME_LOWER') ? Math.floor((padNeeded + 1) / 2) : Math.floor(padNeeded / 2);
|
|
pads[padTailIndex] = padNeeded - pads[padHeadIndex];
|
|
return Math.floor(((inSize + padNeeded - kernel) / stride) + 1);
|
|
}
|
|
default:
|
|
throw new Error('Unsupported AutoPad type');
|
|
}
|
|
}
|
|
else {
|
|
return Math.floor(((inSize + pads[padHeadIndex] + pads[padTailIndex] - dkernel) / stride) + 1);
|
|
}
|
|
}
|
|
}
|
|
exports.PoolConvUtil = PoolConvUtil;
|
|
exports.MIN_CLIP = -3.4028234663852886e+38;
|
|
exports.MAX_CLIP = 3.4028234663852886e+38;
|
|
function decodeUtf8String(buffer) {
|
|
return new TextDecoder().decode(buffer);
|
|
}
|
|
exports.decodeUtf8String = decodeUtf8String;
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./lib/wasm/options-utils.ts":
|
|
/*!***********************************!*\
|
|
!*** ./lib/wasm/options-utils.ts ***!
|
|
\***********************************/
|
|
/***/ ((__unused_webpack_module, exports) => {
|
|
|
|
"use strict";
|
|
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
// Licensed under the MIT License.
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.iterateExtraOptions = void 0;
|
|
const iterateExtraOptions = (options, prefix, seen, handler) => {
|
|
if (typeof options == 'object' && options !== null) {
|
|
if (seen.has(options)) {
|
|
throw new Error('Circular reference in options');
|
|
}
|
|
else {
|
|
seen.add(options);
|
|
}
|
|
}
|
|
Object.entries(options).forEach(([key, value]) => {
|
|
const name = (prefix) ? prefix + key : key;
|
|
if (typeof value === 'object') {
|
|
(0, exports.iterateExtraOptions)(value, name + '.', seen, handler);
|
|
}
|
|
else if (typeof value === 'string' || typeof value === 'number') {
|
|
handler(name, value.toString());
|
|
}
|
|
else if (typeof value === 'boolean') {
|
|
handler(name, (value) ? '1' : '0');
|
|
}
|
|
else {
|
|
throw new Error(`Can't handle extra config type: ${typeof value}`);
|
|
}
|
|
});
|
|
};
|
|
exports.iterateExtraOptions = iterateExtraOptions;
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./lib/wasm/proxy-wrapper.ts":
|
|
/*!***********************************!*\
|
|
!*** ./lib/wasm/proxy-wrapper.ts ***!
|
|
\***********************************/
|
|
/***/ (function(__unused_webpack_module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
// Licensed under the MIT License.
|
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
if (k2 === undefined) k2 = k;
|
|
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
}
|
|
Object.defineProperty(o, k2, desc);
|
|
}) : (function(o, m, k, k2) {
|
|
if (k2 === undefined) k2 = k;
|
|
o[k2] = m[k];
|
|
}));
|
|
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
}) : function(o, v) {
|
|
o["default"] = v;
|
|
});
|
|
var __importStar = (this && this.__importStar) || function (mod) {
|
|
if (mod && mod.__esModule) return mod;
|
|
var result = {};
|
|
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
__setModuleDefault(result, mod);
|
|
return result;
|
|
};
|
|
var _a;
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.endProfiling = exports.run = exports.releaseSession = exports.createSession = exports.createSessionFinalize = exports.createSessionAllocate = exports.initOrt = exports.initWasm = void 0;
|
|
const onnxruntime_common_1 = __webpack_require__(/*! onnxruntime-common */ "../common/dist/lib/index.js");
|
|
const core = __importStar(__webpack_require__(/*! ./wasm-core-impl */ "./lib/wasm/wasm-core-impl.ts"));
|
|
const wasm_factory_1 = __webpack_require__(/*! ./wasm-factory */ "./lib/wasm/wasm-factory.ts");
|
|
const isProxy = () => !!onnxruntime_common_1.env.wasm.proxy && typeof document !== 'undefined';
|
|
let proxyWorker;
|
|
let initializing = false;
|
|
let initialized = false;
|
|
let aborted = false;
|
|
let initWasmCallbacks;
|
|
let initOrtCallbacks;
|
|
const createSessionAllocateCallbacks = [];
|
|
const createSessionFinalizeCallbacks = [];
|
|
const createSessionCallbacks = [];
|
|
const releaseSessionCallbacks = [];
|
|
const runCallbacks = [];
|
|
const endProfilingCallbacks = [];
|
|
const ensureWorker = () => {
|
|
if (initializing || !initialized || aborted || !proxyWorker) {
|
|
throw new Error('worker not ready');
|
|
}
|
|
};
|
|
const onProxyWorkerMessage = (ev) => {
|
|
switch (ev.data.type) {
|
|
case 'init-wasm':
|
|
initializing = false;
|
|
if (ev.data.err) {
|
|
aborted = true;
|
|
initWasmCallbacks[1](ev.data.err);
|
|
}
|
|
else {
|
|
initialized = true;
|
|
initWasmCallbacks[0]();
|
|
}
|
|
break;
|
|
case 'init-ort':
|
|
if (ev.data.err) {
|
|
initOrtCallbacks[1](ev.data.err);
|
|
}
|
|
else {
|
|
initOrtCallbacks[0]();
|
|
}
|
|
break;
|
|
case 'create_allocate':
|
|
if (ev.data.err) {
|
|
createSessionAllocateCallbacks.shift()[1](ev.data.err);
|
|
}
|
|
else {
|
|
createSessionAllocateCallbacks.shift()[0](ev.data.out);
|
|
}
|
|
break;
|
|
case 'create_finalize':
|
|
if (ev.data.err) {
|
|
createSessionFinalizeCallbacks.shift()[1](ev.data.err);
|
|
}
|
|
else {
|
|
createSessionFinalizeCallbacks.shift()[0](ev.data.out);
|
|
}
|
|
break;
|
|
case 'create':
|
|
if (ev.data.err) {
|
|
createSessionCallbacks.shift()[1](ev.data.err);
|
|
}
|
|
else {
|
|
createSessionCallbacks.shift()[0](ev.data.out);
|
|
}
|
|
break;
|
|
case 'release':
|
|
if (ev.data.err) {
|
|
releaseSessionCallbacks.shift()[1](ev.data.err);
|
|
}
|
|
else {
|
|
releaseSessionCallbacks.shift()[0]();
|
|
}
|
|
break;
|
|
case 'run':
|
|
if (ev.data.err) {
|
|
runCallbacks.shift()[1](ev.data.err);
|
|
}
|
|
else {
|
|
runCallbacks.shift()[0](ev.data.out);
|
|
}
|
|
break;
|
|
case 'end-profiling':
|
|
if (ev.data.err) {
|
|
endProfilingCallbacks.shift()[1](ev.data.err);
|
|
}
|
|
else {
|
|
endProfilingCallbacks.shift()[0]();
|
|
}
|
|
break;
|
|
default:
|
|
}
|
|
};
|
|
const scriptSrc = typeof document !== 'undefined' ? (_a = document === null || document === void 0 ? void 0 : document.currentScript) === null || _a === void 0 ? void 0 : _a.src : undefined;
|
|
const initWasm = async () => {
|
|
if ( true && isProxy()) {
|
|
if (initialized) {
|
|
return;
|
|
}
|
|
if (initializing) {
|
|
throw new Error('multiple calls to \'initWasm()\' detected.');
|
|
}
|
|
if (aborted) {
|
|
throw new Error('previous call to \'initWasm()\' failed.');
|
|
}
|
|
initializing = true;
|
|
// overwrite wasm filepaths
|
|
if (onnxruntime_common_1.env.wasm.wasmPaths === undefined) {
|
|
if (scriptSrc && scriptSrc.indexOf('blob:') !== 0) {
|
|
onnxruntime_common_1.env.wasm.wasmPaths = scriptSrc.substr(0, +(scriptSrc).lastIndexOf('/') + 1);
|
|
}
|
|
}
|
|
return new Promise((resolve, reject) => {
|
|
proxyWorker === null || proxyWorker === void 0 ? void 0 : proxyWorker.terminate();
|
|
// eslint-disable-next-line @typescript-eslint/no-var-requires, @typescript-eslint/no-require-imports
|
|
proxyWorker = (__webpack_require__(/*! worker-loader?inline=no-fallback!./proxy-worker/main */ "./node_modules/worker-loader/dist/cjs.js?inline=no-fallback!./lib/wasm/proxy-worker/main.ts")["default"])();
|
|
proxyWorker.onmessage = onProxyWorkerMessage;
|
|
initWasmCallbacks = [resolve, reject];
|
|
const message = { type: 'init-wasm', in: onnxruntime_common_1.env.wasm };
|
|
proxyWorker.postMessage(message);
|
|
});
|
|
}
|
|
else {
|
|
return (0, wasm_factory_1.initializeWebAssembly)(onnxruntime_common_1.env.wasm);
|
|
}
|
|
};
|
|
exports.initWasm = initWasm;
|
|
const initOrt = async (numThreads, loggingLevel) => {
|
|
if ( true && isProxy()) {
|
|
ensureWorker();
|
|
return new Promise((resolve, reject) => {
|
|
initOrtCallbacks = [resolve, reject];
|
|
const message = { type: 'init-ort', in: { numThreads, loggingLevel } };
|
|
proxyWorker.postMessage(message);
|
|
});
|
|
}
|
|
else {
|
|
core.initOrt(numThreads, loggingLevel);
|
|
}
|
|
};
|
|
exports.initOrt = initOrt;
|
|
const createSessionAllocate = async (model) => {
|
|
if ( true && isProxy()) {
|
|
ensureWorker();
|
|
return new Promise((resolve, reject) => {
|
|
createSessionAllocateCallbacks.push([resolve, reject]);
|
|
const message = { type: 'create_allocate', in: { model } };
|
|
proxyWorker.postMessage(message, [model.buffer]);
|
|
});
|
|
}
|
|
else {
|
|
return core.createSessionAllocate(model);
|
|
}
|
|
};
|
|
exports.createSessionAllocate = createSessionAllocate;
|
|
const createSessionFinalize = async (modeldata, options) => {
|
|
if ( true && isProxy()) {
|
|
ensureWorker();
|
|
return new Promise((resolve, reject) => {
|
|
createSessionFinalizeCallbacks.push([resolve, reject]);
|
|
const message = { type: 'create_finalize', in: { modeldata, options } };
|
|
proxyWorker.postMessage(message);
|
|
});
|
|
}
|
|
else {
|
|
return core.createSessionFinalize(modeldata, options);
|
|
}
|
|
};
|
|
exports.createSessionFinalize = createSessionFinalize;
|
|
const createSession = async (model, options) => {
|
|
if ( true && isProxy()) {
|
|
ensureWorker();
|
|
return new Promise((resolve, reject) => {
|
|
createSessionCallbacks.push([resolve, reject]);
|
|
const message = { type: 'create', in: { model, options } };
|
|
proxyWorker.postMessage(message, [model.buffer]);
|
|
});
|
|
}
|
|
else {
|
|
return core.createSession(model, options);
|
|
}
|
|
};
|
|
exports.createSession = createSession;
|
|
const releaseSession = async (sessionId) => {
|
|
if ( true && isProxy()) {
|
|
ensureWorker();
|
|
return new Promise((resolve, reject) => {
|
|
releaseSessionCallbacks.push([resolve, reject]);
|
|
const message = { type: 'release', in: sessionId };
|
|
proxyWorker.postMessage(message);
|
|
});
|
|
}
|
|
else {
|
|
core.releaseSession(sessionId);
|
|
}
|
|
};
|
|
exports.releaseSession = releaseSession;
|
|
const run = async (sessionId, inputIndices, inputs, outputIndices, options) => {
|
|
if ( true && isProxy()) {
|
|
ensureWorker();
|
|
return new Promise((resolve, reject) => {
|
|
runCallbacks.push([resolve, reject]);
|
|
const message = { type: 'run', in: { sessionId, inputIndices, inputs, outputIndices, options } };
|
|
proxyWorker.postMessage(message, core.extractTransferableBuffers(inputs));
|
|
});
|
|
}
|
|
else {
|
|
return core.run(sessionId, inputIndices, inputs, outputIndices, options);
|
|
}
|
|
};
|
|
exports.run = run;
|
|
const endProfiling = async (sessionId) => {
|
|
if ( true && isProxy()) {
|
|
ensureWorker();
|
|
return new Promise((resolve, reject) => {
|
|
endProfilingCallbacks.push([resolve, reject]);
|
|
const message = { type: 'end-profiling', in: sessionId };
|
|
proxyWorker.postMessage(message);
|
|
});
|
|
}
|
|
else {
|
|
core.endProfiling(sessionId);
|
|
}
|
|
};
|
|
exports.endProfiling = endProfiling;
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./lib/wasm/run-options.ts":
|
|
/*!*********************************!*\
|
|
!*** ./lib/wasm/run-options.ts ***!
|
|
\*********************************/
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
// Licensed under the MIT License.
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.setRunOptions = void 0;
|
|
const options_utils_1 = __webpack_require__(/*! ./options-utils */ "./lib/wasm/options-utils.ts");
|
|
const string_utils_1 = __webpack_require__(/*! ./string-utils */ "./lib/wasm/string-utils.ts");
|
|
const wasm_factory_1 = __webpack_require__(/*! ./wasm-factory */ "./lib/wasm/wasm-factory.ts");
|
|
const setRunOptions = (options) => {
|
|
const wasm = (0, wasm_factory_1.getInstance)();
|
|
let runOptionsHandle = 0;
|
|
const allocs = [];
|
|
const runOptions = options || {};
|
|
try {
|
|
if ((options === null || options === void 0 ? void 0 : options.logSeverityLevel) === undefined) {
|
|
runOptions.logSeverityLevel = 2; // Default to warning
|
|
}
|
|
else if (typeof options.logSeverityLevel !== 'number' || !Number.isInteger(options.logSeverityLevel) ||
|
|
options.logSeverityLevel < 0 || options.logSeverityLevel > 4) {
|
|
throw new Error(`log serverity level is not valid: ${options.logSeverityLevel}`);
|
|
}
|
|
if ((options === null || options === void 0 ? void 0 : options.logVerbosityLevel) === undefined) {
|
|
runOptions.logVerbosityLevel = 0; // Default to 0
|
|
}
|
|
else if (typeof options.logVerbosityLevel !== 'number' || !Number.isInteger(options.logVerbosityLevel)) {
|
|
throw new Error(`log verbosity level is not valid: ${options.logVerbosityLevel}`);
|
|
}
|
|
if ((options === null || options === void 0 ? void 0 : options.terminate) === undefined) {
|
|
runOptions.terminate = false;
|
|
}
|
|
let tagDataOffset = 0;
|
|
if ((options === null || options === void 0 ? void 0 : options.tag) !== undefined) {
|
|
tagDataOffset = (0, string_utils_1.allocWasmString)(options.tag, allocs);
|
|
}
|
|
runOptionsHandle = wasm._OrtCreateRunOptions(runOptions.logSeverityLevel, runOptions.logVerbosityLevel, !!runOptions.terminate, tagDataOffset);
|
|
if (runOptionsHandle === 0) {
|
|
throw new Error('Can\'t create run options');
|
|
}
|
|
if ((options === null || options === void 0 ? void 0 : options.extra) !== undefined) {
|
|
(0, options_utils_1.iterateExtraOptions)(options.extra, '', new WeakSet(), (key, value) => {
|
|
const keyDataOffset = (0, string_utils_1.allocWasmString)(key, allocs);
|
|
const valueDataOffset = (0, string_utils_1.allocWasmString)(value, allocs);
|
|
if (wasm._OrtAddRunConfigEntry(runOptionsHandle, keyDataOffset, valueDataOffset) !== 0) {
|
|
throw new Error(`Can't set a run config entry: ${key} - ${value}`);
|
|
}
|
|
});
|
|
}
|
|
return [runOptionsHandle, allocs];
|
|
}
|
|
catch (e) {
|
|
if (runOptionsHandle !== 0) {
|
|
wasm._OrtReleaseRunOptions(runOptionsHandle);
|
|
}
|
|
allocs.forEach(wasm._free);
|
|
throw e;
|
|
}
|
|
};
|
|
exports.setRunOptions = setRunOptions;
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./lib/wasm/session-handler.ts":
|
|
/*!*************************************!*\
|
|
!*** ./lib/wasm/session-handler.ts ***!
|
|
\*************************************/
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
// Licensed under the MIT License.
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.OnnxruntimeWebAssemblySessionHandler = void 0;
|
|
const fs_1 = __webpack_require__(/*! fs */ "?295d");
|
|
const onnxruntime_common_1 = __webpack_require__(/*! onnxruntime-common */ "../common/dist/lib/index.js");
|
|
const util_1 = __webpack_require__(/*! util */ "?cf98");
|
|
const proxy_wrapper_1 = __webpack_require__(/*! ./proxy-wrapper */ "./lib/wasm/proxy-wrapper.ts");
|
|
let ortInit;
|
|
const getLogLevel = (logLevel) => {
|
|
switch (logLevel) {
|
|
case 'verbose':
|
|
return 0;
|
|
case 'info':
|
|
return 1;
|
|
case 'warning':
|
|
return 2;
|
|
case 'error':
|
|
return 3;
|
|
case 'fatal':
|
|
return 4;
|
|
default:
|
|
throw new Error(`unsupported logging level: ${logLevel}`);
|
|
}
|
|
};
|
|
class OnnxruntimeWebAssemblySessionHandler {
|
|
async createSessionAllocate(path) {
|
|
// fetch model from url and move to wasm heap. The arraybufffer that held the http
|
|
// response is freed once we return
|
|
const response = await fetch(path);
|
|
const arrayBuffer = await response.arrayBuffer();
|
|
return (0, proxy_wrapper_1.createSessionAllocate)(new Uint8Array(arrayBuffer));
|
|
}
|
|
async loadModel(pathOrBuffer, options) {
|
|
if (!ortInit) {
|
|
await (0, proxy_wrapper_1.initOrt)(onnxruntime_common_1.env.wasm.numThreads, getLogLevel(onnxruntime_common_1.env.logLevel));
|
|
ortInit = true;
|
|
}
|
|
if (typeof pathOrBuffer === 'string') {
|
|
if (typeof fetch === 'undefined') {
|
|
// node
|
|
const model = await (0, util_1.promisify)(fs_1.readFile)(pathOrBuffer);
|
|
[this.sessionId, this.inputNames, this.outputNames] = await (0, proxy_wrapper_1.createSession)(model, options);
|
|
}
|
|
else {
|
|
// browser
|
|
// fetch model and move to wasm heap.
|
|
const modelData = await this.createSessionAllocate(pathOrBuffer);
|
|
// create the session
|
|
[this.sessionId, this.inputNames, this.outputNames] = await (0, proxy_wrapper_1.createSessionFinalize)(modelData, options);
|
|
}
|
|
}
|
|
else {
|
|
[this.sessionId, this.inputNames, this.outputNames] = await (0, proxy_wrapper_1.createSession)(pathOrBuffer, options);
|
|
}
|
|
}
|
|
async dispose() {
|
|
return (0, proxy_wrapper_1.releaseSession)(this.sessionId);
|
|
}
|
|
async run(feeds, fetches, options) {
|
|
const inputArray = [];
|
|
const inputIndices = [];
|
|
Object.entries(feeds).forEach(kvp => {
|
|
const name = kvp[0];
|
|
const tensor = kvp[1];
|
|
const index = this.inputNames.indexOf(name);
|
|
if (index === -1) {
|
|
throw new Error(`invalid input '${name}'`);
|
|
}
|
|
inputArray.push(tensor);
|
|
inputIndices.push(index);
|
|
});
|
|
const outputIndices = [];
|
|
Object.entries(fetches).forEach(kvp => {
|
|
const name = kvp[0];
|
|
// TODO: support pre-allocated output
|
|
const index = this.outputNames.indexOf(name);
|
|
if (index === -1) {
|
|
throw new Error(`invalid output '${name}'`);
|
|
}
|
|
outputIndices.push(index);
|
|
});
|
|
const outputs = await (0, proxy_wrapper_1.run)(this.sessionId, inputIndices, inputArray.map(t => [t.type, t.dims, t.data]), outputIndices, options);
|
|
const result = {};
|
|
for (let i = 0; i < outputs.length; i++) {
|
|
result[this.outputNames[outputIndices[i]]] = new onnxruntime_common_1.Tensor(outputs[i][0], outputs[i][2], outputs[i][1]);
|
|
}
|
|
return result;
|
|
}
|
|
startProfiling() {
|
|
// TODO: implement profiling
|
|
}
|
|
endProfiling() {
|
|
void (0, proxy_wrapper_1.endProfiling)(this.sessionId);
|
|
}
|
|
}
|
|
exports.OnnxruntimeWebAssemblySessionHandler = OnnxruntimeWebAssemblySessionHandler;
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./lib/wasm/session-options.ts":
|
|
/*!*************************************!*\
|
|
!*** ./lib/wasm/session-options.ts ***!
|
|
\*************************************/
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
// Licensed under the MIT License.
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.setSessionOptions = void 0;
|
|
const options_utils_1 = __webpack_require__(/*! ./options-utils */ "./lib/wasm/options-utils.ts");
|
|
const string_utils_1 = __webpack_require__(/*! ./string-utils */ "./lib/wasm/string-utils.ts");
|
|
const wasm_factory_1 = __webpack_require__(/*! ./wasm-factory */ "./lib/wasm/wasm-factory.ts");
|
|
const getGraphOptimzationLevel = (graphOptimizationLevel) => {
|
|
switch (graphOptimizationLevel) {
|
|
case 'disabled':
|
|
return 0;
|
|
case 'basic':
|
|
return 1;
|
|
case 'extended':
|
|
return 2;
|
|
case 'all':
|
|
return 99;
|
|
default:
|
|
throw new Error(`unsupported graph optimization level: ${graphOptimizationLevel}`);
|
|
}
|
|
};
|
|
const getExecutionMode = (executionMode) => {
|
|
switch (executionMode) {
|
|
case 'sequential':
|
|
return 0;
|
|
case 'parallel':
|
|
return 1;
|
|
default:
|
|
throw new Error(`unsupported execution mode: ${executionMode}`);
|
|
}
|
|
};
|
|
const appendDefaultOptions = (options) => {
|
|
if (!options.extra) {
|
|
options.extra = {};
|
|
}
|
|
if (!options.extra.session) {
|
|
options.extra.session = {};
|
|
}
|
|
const session = options.extra.session;
|
|
if (!session.use_ort_model_bytes_directly) {
|
|
// eslint-disable-next-line camelcase
|
|
session.use_ort_model_bytes_directly = '1';
|
|
}
|
|
};
|
|
const setExecutionProviders = (sessionOptionsHandle, executionProviders, allocs) => {
|
|
for (const ep of executionProviders) {
|
|
let epName = typeof ep === 'string' ? ep : ep.name;
|
|
// check EP name
|
|
switch (epName) {
|
|
case 'xnnpack':
|
|
epName = 'XNNPACK';
|
|
break;
|
|
case 'wasm':
|
|
case 'cpu':
|
|
continue;
|
|
default:
|
|
throw new Error(`not supported EP: ${epName}`);
|
|
}
|
|
const epNameDataOffset = (0, string_utils_1.allocWasmString)(epName, allocs);
|
|
if ((0, wasm_factory_1.getInstance)()._OrtAppendExecutionProvider(sessionOptionsHandle, epNameDataOffset) !== 0) {
|
|
throw new Error(`Can't append execution provider: ${epName}`);
|
|
}
|
|
}
|
|
};
|
|
const setSessionOptions = (options) => {
|
|
const wasm = (0, wasm_factory_1.getInstance)();
|
|
let sessionOptionsHandle = 0;
|
|
const allocs = [];
|
|
const sessionOptions = options || {};
|
|
appendDefaultOptions(sessionOptions);
|
|
try {
|
|
if ((options === null || options === void 0 ? void 0 : options.graphOptimizationLevel) === undefined) {
|
|
sessionOptions.graphOptimizationLevel = 'all';
|
|
}
|
|
const graphOptimizationLevel = getGraphOptimzationLevel(sessionOptions.graphOptimizationLevel);
|
|
if ((options === null || options === void 0 ? void 0 : options.enableCpuMemArena) === undefined) {
|
|
sessionOptions.enableCpuMemArena = true;
|
|
}
|
|
if ((options === null || options === void 0 ? void 0 : options.enableMemPattern) === undefined) {
|
|
sessionOptions.enableMemPattern = true;
|
|
}
|
|
if ((options === null || options === void 0 ? void 0 : options.executionMode) === undefined) {
|
|
sessionOptions.executionMode = 'sequential';
|
|
}
|
|
const executionMode = getExecutionMode(sessionOptions.executionMode);
|
|
let logIdDataOffset = 0;
|
|
if ((options === null || options === void 0 ? void 0 : options.logId) !== undefined) {
|
|
logIdDataOffset = (0, string_utils_1.allocWasmString)(options.logId, allocs);
|
|
}
|
|
if ((options === null || options === void 0 ? void 0 : options.logSeverityLevel) === undefined) {
|
|
sessionOptions.logSeverityLevel = 2; // Default to warning
|
|
}
|
|
else if (typeof options.logSeverityLevel !== 'number' || !Number.isInteger(options.logSeverityLevel) ||
|
|
options.logSeverityLevel < 0 || options.logSeverityLevel > 4) {
|
|
throw new Error(`log serverity level is not valid: ${options.logSeverityLevel}`);
|
|
}
|
|
if ((options === null || options === void 0 ? void 0 : options.logVerbosityLevel) === undefined) {
|
|
sessionOptions.logVerbosityLevel = 0; // Default to 0
|
|
}
|
|
else if (typeof options.logVerbosityLevel !== 'number' || !Number.isInteger(options.logVerbosityLevel)) {
|
|
throw new Error(`log verbosity level is not valid: ${options.logVerbosityLevel}`);
|
|
}
|
|
if ((options === null || options === void 0 ? void 0 : options.enableProfiling) === undefined) {
|
|
sessionOptions.enableProfiling = false;
|
|
}
|
|
sessionOptionsHandle = wasm._OrtCreateSessionOptions(graphOptimizationLevel, !!sessionOptions.enableCpuMemArena, !!sessionOptions.enableMemPattern, executionMode, !!sessionOptions.enableProfiling, 0, logIdDataOffset, sessionOptions.logSeverityLevel, sessionOptions.logVerbosityLevel);
|
|
if (sessionOptionsHandle === 0) {
|
|
throw new Error('Can\'t create session options');
|
|
}
|
|
if (options === null || options === void 0 ? void 0 : options.executionProviders) {
|
|
setExecutionProviders(sessionOptionsHandle, options.executionProviders, allocs);
|
|
}
|
|
if ((options === null || options === void 0 ? void 0 : options.extra) !== undefined) {
|
|
(0, options_utils_1.iterateExtraOptions)(options.extra, '', new WeakSet(), (key, value) => {
|
|
const keyDataOffset = (0, string_utils_1.allocWasmString)(key, allocs);
|
|
const valueDataOffset = (0, string_utils_1.allocWasmString)(value, allocs);
|
|
if (wasm._OrtAddSessionConfigEntry(sessionOptionsHandle, keyDataOffset, valueDataOffset) !== 0) {
|
|
throw new Error(`Can't set a session config entry: ${key} - ${value}`);
|
|
}
|
|
});
|
|
}
|
|
return [sessionOptionsHandle, allocs];
|
|
}
|
|
catch (e) {
|
|
if (sessionOptionsHandle !== 0) {
|
|
wasm._OrtReleaseSessionOptions(sessionOptionsHandle);
|
|
}
|
|
allocs.forEach(wasm._free);
|
|
throw e;
|
|
}
|
|
};
|
|
exports.setSessionOptions = setSessionOptions;
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./lib/wasm/string-utils.ts":
|
|
/*!**********************************!*\
|
|
!*** ./lib/wasm/string-utils.ts ***!
|
|
\**********************************/
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
// Licensed under the MIT License.
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.allocWasmString = void 0;
|
|
const wasm_factory_1 = __webpack_require__(/*! ./wasm-factory */ "./lib/wasm/wasm-factory.ts");
|
|
const allocWasmString = (data, allocs) => {
|
|
const wasm = (0, wasm_factory_1.getInstance)();
|
|
const dataLength = wasm.lengthBytesUTF8(data) + 1;
|
|
const dataOffset = wasm._malloc(dataLength);
|
|
wasm.stringToUTF8(data, dataOffset, dataLength);
|
|
allocs.push(dataOffset);
|
|
return dataOffset;
|
|
};
|
|
exports.allocWasmString = allocWasmString;
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./lib/wasm/wasm-core-impl.ts":
|
|
/*!************************************!*\
|
|
!*** ./lib/wasm/wasm-core-impl.ts ***!
|
|
\************************************/
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
// Licensed under the MIT License.
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.extractTransferableBuffers = exports.endProfiling = exports.run = exports.releaseSession = exports.createSession = exports.createSessionFinalize = exports.createSessionAllocate = exports.initOrt = void 0;
|
|
const run_options_1 = __webpack_require__(/*! ./run-options */ "./lib/wasm/run-options.ts");
|
|
const session_options_1 = __webpack_require__(/*! ./session-options */ "./lib/wasm/session-options.ts");
|
|
const string_utils_1 = __webpack_require__(/*! ./string-utils */ "./lib/wasm/string-utils.ts");
|
|
const wasm_factory_1 = __webpack_require__(/*! ./wasm-factory */ "./lib/wasm/wasm-factory.ts");
|
|
/**
|
|
* initialize ORT environment.
|
|
* @param numThreads SetGlobalIntraOpNumThreads(numThreads)
|
|
* @param loggingLevel CreateEnv(static_cast<OrtLoggingLevel>(logging_level))
|
|
*/
|
|
const initOrt = (numThreads, loggingLevel) => {
|
|
const errorCode = (0, wasm_factory_1.getInstance)()._OrtInit(numThreads, loggingLevel);
|
|
if (errorCode !== 0) {
|
|
throw new Error(`Can't initialize onnxruntime. error code = ${errorCode}`);
|
|
}
|
|
};
|
|
exports.initOrt = initOrt;
|
|
const activeSessions = new Map();
|
|
/**
|
|
* create an instance of InferenceSession.
|
|
* @returns the metadata of InferenceSession. 0-value handle for failure.
|
|
*/
|
|
const createSessionAllocate = (model) => {
|
|
const wasm = (0, wasm_factory_1.getInstance)();
|
|
const modelDataOffset = wasm._malloc(model.byteLength);
|
|
wasm.HEAPU8.set(model, modelDataOffset);
|
|
return [modelDataOffset, model.byteLength];
|
|
};
|
|
exports.createSessionAllocate = createSessionAllocate;
|
|
const createSessionFinalize = (modelData, options) => {
|
|
const wasm = (0, wasm_factory_1.getInstance)();
|
|
let sessionHandle = 0;
|
|
let sessionOptionsHandle = 0;
|
|
let allocs = [];
|
|
try {
|
|
[sessionOptionsHandle, allocs] = (0, session_options_1.setSessionOptions)(options);
|
|
sessionHandle = wasm._OrtCreateSession(modelData[0], modelData[1], sessionOptionsHandle);
|
|
if (sessionHandle === 0) {
|
|
throw new Error('Can\'t create a session');
|
|
}
|
|
}
|
|
finally {
|
|
wasm._free(modelData[0]);
|
|
wasm._OrtReleaseSessionOptions(sessionOptionsHandle);
|
|
allocs.forEach(wasm._free);
|
|
}
|
|
const inputCount = wasm._OrtGetInputCount(sessionHandle);
|
|
const outputCount = wasm._OrtGetOutputCount(sessionHandle);
|
|
const inputNames = [];
|
|
const inputNamesUTF8Encoded = [];
|
|
const outputNames = [];
|
|
const outputNamesUTF8Encoded = [];
|
|
for (let i = 0; i < inputCount; i++) {
|
|
const name = wasm._OrtGetInputName(sessionHandle, i);
|
|
if (name === 0) {
|
|
throw new Error('Can\'t get an input name');
|
|
}
|
|
inputNamesUTF8Encoded.push(name);
|
|
inputNames.push(wasm.UTF8ToString(name));
|
|
}
|
|
for (let i = 0; i < outputCount; i++) {
|
|
const name = wasm._OrtGetOutputName(sessionHandle, i);
|
|
if (name === 0) {
|
|
throw new Error('Can\'t get an output name');
|
|
}
|
|
outputNamesUTF8Encoded.push(name);
|
|
outputNames.push(wasm.UTF8ToString(name));
|
|
}
|
|
activeSessions.set(sessionHandle, [sessionHandle, inputNamesUTF8Encoded, outputNamesUTF8Encoded]);
|
|
return [sessionHandle, inputNames, outputNames];
|
|
};
|
|
exports.createSessionFinalize = createSessionFinalize;
|
|
/**
|
|
* create an instance of InferenceSession.
|
|
* @returns the metadata of InferenceSession. 0-value handle for failure.
|
|
*/
|
|
const createSession = (model, options) => {
|
|
const modelData = (0, exports.createSessionAllocate)(model);
|
|
return (0, exports.createSessionFinalize)(modelData, options);
|
|
};
|
|
exports.createSession = createSession;
|
|
const releaseSession = (sessionId) => {
|
|
const wasm = (0, wasm_factory_1.getInstance)();
|
|
const session = activeSessions.get(sessionId);
|
|
if (!session) {
|
|
throw new Error('invalid session id');
|
|
}
|
|
const sessionHandle = session[0];
|
|
const inputNamesUTF8Encoded = session[1];
|
|
const outputNamesUTF8Encoded = session[2];
|
|
inputNamesUTF8Encoded.forEach(wasm._OrtFree);
|
|
outputNamesUTF8Encoded.forEach(wasm._OrtFree);
|
|
wasm._OrtReleaseSession(sessionHandle);
|
|
activeSessions.delete(sessionId);
|
|
};
|
|
exports.releaseSession = releaseSession;
|
|
const tensorDataTypeStringToEnum = (type) => {
|
|
switch (type) {
|
|
case 'int8':
|
|
return 3 /* DataType.int8 */;
|
|
case 'uint8':
|
|
return 2 /* DataType.uint8 */;
|
|
case 'bool':
|
|
return 9 /* DataType.bool */;
|
|
case 'int16':
|
|
return 5 /* DataType.int16 */;
|
|
case 'uint16':
|
|
return 4 /* DataType.uint16 */;
|
|
case 'int32':
|
|
return 6 /* DataType.int32 */;
|
|
case 'uint32':
|
|
return 12 /* DataType.uint32 */;
|
|
case 'float32':
|
|
return 1 /* DataType.float */;
|
|
case 'float64':
|
|
return 11 /* DataType.double */;
|
|
case 'string':
|
|
return 8 /* DataType.string */;
|
|
case 'int64':
|
|
return 7 /* DataType.int64 */;
|
|
case 'uint64':
|
|
return 13 /* DataType.uint64 */;
|
|
default:
|
|
throw new Error(`unsupported data type: ${type}`);
|
|
}
|
|
};
|
|
const tensorDataTypeEnumToString = (typeProto) => {
|
|
switch (typeProto) {
|
|
case 3 /* DataType.int8 */:
|
|
return 'int8';
|
|
case 2 /* DataType.uint8 */:
|
|
return 'uint8';
|
|
case 9 /* DataType.bool */:
|
|
return 'bool';
|
|
case 5 /* DataType.int16 */:
|
|
return 'int16';
|
|
case 4 /* DataType.uint16 */:
|
|
return 'uint16';
|
|
case 6 /* DataType.int32 */:
|
|
return 'int32';
|
|
case 12 /* DataType.uint32 */:
|
|
return 'uint32';
|
|
case 1 /* DataType.float */:
|
|
return 'float32';
|
|
case 11 /* DataType.double */:
|
|
return 'float64';
|
|
case 8 /* DataType.string */:
|
|
return 'string';
|
|
case 7 /* DataType.int64 */:
|
|
return 'int64';
|
|
case 13 /* DataType.uint64 */:
|
|
return 'uint64';
|
|
default:
|
|
throw new Error(`unsupported data type: ${typeProto}`);
|
|
}
|
|
};
|
|
const numericTensorTypeToTypedArray = (type) => {
|
|
switch (type) {
|
|
case 'float32':
|
|
return Float32Array;
|
|
case 'uint8':
|
|
return Uint8Array;
|
|
case 'int8':
|
|
return Int8Array;
|
|
case 'uint16':
|
|
return Uint16Array;
|
|
case 'int16':
|
|
return Int16Array;
|
|
case 'int32':
|
|
return Int32Array;
|
|
case 'bool':
|
|
return Uint8Array;
|
|
case 'float64':
|
|
return Float64Array;
|
|
case 'uint32':
|
|
return Uint32Array;
|
|
case 'int64':
|
|
return BigInt64Array;
|
|
case 'uint64':
|
|
return BigUint64Array;
|
|
default:
|
|
throw new Error(`unsupported type: ${type}`);
|
|
}
|
|
};
|
|
/**
|
|
* perform inference run
|
|
*/
|
|
const run = (sessionId, inputIndices, inputs, outputIndices, options) => {
|
|
const wasm = (0, wasm_factory_1.getInstance)();
|
|
const session = activeSessions.get(sessionId);
|
|
if (!session) {
|
|
throw new Error('invalid session id');
|
|
}
|
|
const sessionHandle = session[0];
|
|
const inputNamesUTF8Encoded = session[1];
|
|
const outputNamesUTF8Encoded = session[2];
|
|
const inputCount = inputIndices.length;
|
|
const outputCount = outputIndices.length;
|
|
let runOptionsHandle = 0;
|
|
let runOptionsAllocs = [];
|
|
const inputValues = [];
|
|
const inputAllocs = [];
|
|
try {
|
|
[runOptionsHandle, runOptionsAllocs] = (0, run_options_1.setRunOptions)(options);
|
|
// create input tensors
|
|
for (let i = 0; i < inputCount; i++) {
|
|
const dataType = inputs[i][0];
|
|
const dims = inputs[i][1];
|
|
const data = inputs[i][2];
|
|
let dataOffset;
|
|
let dataByteLength;
|
|
if (Array.isArray(data)) {
|
|
// string tensor
|
|
dataByteLength = 4 * data.length;
|
|
dataOffset = wasm._malloc(dataByteLength);
|
|
inputAllocs.push(dataOffset);
|
|
let dataIndex = dataOffset / 4;
|
|
for (let i = 0; i < data.length; i++) {
|
|
if (typeof data[i] !== 'string') {
|
|
throw new TypeError(`tensor data at index ${i} is not a string`);
|
|
}
|
|
wasm.HEAPU32[dataIndex++] = (0, string_utils_1.allocWasmString)(data[i], inputAllocs);
|
|
}
|
|
}
|
|
else {
|
|
dataByteLength = data.byteLength;
|
|
dataOffset = wasm._malloc(dataByteLength);
|
|
inputAllocs.push(dataOffset);
|
|
wasm.HEAPU8.set(new Uint8Array(data.buffer, data.byteOffset, dataByteLength), dataOffset);
|
|
}
|
|
const stack = wasm.stackSave();
|
|
const dimsOffset = wasm.stackAlloc(4 * dims.length);
|
|
try {
|
|
let dimIndex = dimsOffset / 4;
|
|
dims.forEach(d => wasm.HEAP32[dimIndex++] = d);
|
|
const tensor = wasm._OrtCreateTensor(tensorDataTypeStringToEnum(dataType), dataOffset, dataByteLength, dimsOffset, dims.length);
|
|
if (tensor === 0) {
|
|
throw new Error('Can\'t create a tensor');
|
|
}
|
|
inputValues.push(tensor);
|
|
}
|
|
finally {
|
|
wasm.stackRestore(stack);
|
|
}
|
|
}
|
|
const beforeRunStack = wasm.stackSave();
|
|
const inputValuesOffset = wasm.stackAlloc(inputCount * 4);
|
|
const inputNamesOffset = wasm.stackAlloc(inputCount * 4);
|
|
const outputValuesOffset = wasm.stackAlloc(outputCount * 4);
|
|
const outputNamesOffset = wasm.stackAlloc(outputCount * 4);
|
|
try {
|
|
let inputValuesIndex = inputValuesOffset / 4;
|
|
let inputNamesIndex = inputNamesOffset / 4;
|
|
let outputValuesIndex = outputValuesOffset / 4;
|
|
let outputNamesIndex = outputNamesOffset / 4;
|
|
for (let i = 0; i < inputCount; i++) {
|
|
wasm.HEAPU32[inputValuesIndex++] = inputValues[i];
|
|
wasm.HEAPU32[inputNamesIndex++] = inputNamesUTF8Encoded[inputIndices[i]];
|
|
}
|
|
for (let i = 0; i < outputCount; i++) {
|
|
wasm.HEAPU32[outputValuesIndex++] = 0;
|
|
wasm.HEAPU32[outputNamesIndex++] = outputNamesUTF8Encoded[outputIndices[i]];
|
|
}
|
|
// support RunOptions
|
|
let errorCode = wasm._OrtRun(sessionHandle, inputNamesOffset, inputValuesOffset, inputCount, outputNamesOffset, outputCount, outputValuesOffset, runOptionsHandle);
|
|
const output = [];
|
|
if (errorCode === 0) {
|
|
for (let i = 0; i < outputCount; i++) {
|
|
const tensor = wasm.HEAPU32[outputValuesOffset / 4 + i];
|
|
const beforeGetTensorDataStack = wasm.stackSave();
|
|
// stack allocate 4 pointer value
|
|
const tensorDataOffset = wasm.stackAlloc(4 * 4);
|
|
let type, dataOffset = 0;
|
|
try {
|
|
errorCode = wasm._OrtGetTensorData(tensor, tensorDataOffset, tensorDataOffset + 4, tensorDataOffset + 8, tensorDataOffset + 12);
|
|
if (errorCode !== 0) {
|
|
throw new Error(`Can't access output tensor data. error code = ${errorCode}`);
|
|
}
|
|
let tensorDataIndex = tensorDataOffset / 4;
|
|
const dataType = wasm.HEAPU32[tensorDataIndex++];
|
|
dataOffset = wasm.HEAPU32[tensorDataIndex++];
|
|
const dimsOffset = wasm.HEAPU32[tensorDataIndex++];
|
|
const dimsLength = wasm.HEAPU32[tensorDataIndex++];
|
|
const dims = [];
|
|
for (let i = 0; i < dimsLength; i++) {
|
|
dims.push(wasm.HEAPU32[dimsOffset / 4 + i]);
|
|
}
|
|
wasm._OrtFree(dimsOffset);
|
|
const size = dims.length === 0 ? 1 : dims.reduce((a, b) => a * b);
|
|
type = tensorDataTypeEnumToString(dataType);
|
|
if (type === 'string') {
|
|
const stringData = [];
|
|
let dataIndex = dataOffset / 4;
|
|
for (let i = 0; i < size; i++) {
|
|
const offset = wasm.HEAPU32[dataIndex++];
|
|
const maxBytesToRead = i === size - 1 ? undefined : wasm.HEAPU32[dataIndex] - offset;
|
|
stringData.push(wasm.UTF8ToString(offset, maxBytesToRead));
|
|
}
|
|
output.push([type, dims, stringData]);
|
|
}
|
|
else {
|
|
const typedArrayConstructor = numericTensorTypeToTypedArray(type);
|
|
const data = new typedArrayConstructor(size);
|
|
new Uint8Array(data.buffer, data.byteOffset, data.byteLength)
|
|
.set(wasm.HEAPU8.subarray(dataOffset, dataOffset + data.byteLength));
|
|
output.push([type, dims, data]);
|
|
}
|
|
}
|
|
finally {
|
|
wasm.stackRestore(beforeGetTensorDataStack);
|
|
if (type === 'string' && dataOffset) {
|
|
wasm._free(dataOffset);
|
|
}
|
|
wasm._OrtReleaseTensor(tensor);
|
|
}
|
|
}
|
|
}
|
|
if (errorCode === 0) {
|
|
return output;
|
|
}
|
|
else {
|
|
throw new Error(`failed to call OrtRun(). error code = ${errorCode}.`);
|
|
}
|
|
}
|
|
finally {
|
|
wasm.stackRestore(beforeRunStack);
|
|
}
|
|
}
|
|
finally {
|
|
inputValues.forEach(wasm._OrtReleaseTensor);
|
|
inputAllocs.forEach(wasm._free);
|
|
wasm._OrtReleaseRunOptions(runOptionsHandle);
|
|
runOptionsAllocs.forEach(wasm._free);
|
|
}
|
|
};
|
|
exports.run = run;
|
|
/**
|
|
* end profiling
|
|
*/
|
|
const endProfiling = (sessionId) => {
|
|
const wasm = (0, wasm_factory_1.getInstance)();
|
|
const session = activeSessions.get(sessionId);
|
|
if (!session) {
|
|
throw new Error('invalid session id');
|
|
}
|
|
const sessionHandle = session[0];
|
|
// profile file name is not used yet, but it must be freed.
|
|
const profileFileName = wasm._OrtEndProfiling(sessionHandle);
|
|
if (profileFileName === 0) {
|
|
throw new Error('Can\'t get an profile file name');
|
|
}
|
|
wasm._OrtFree(profileFileName);
|
|
};
|
|
exports.endProfiling = endProfiling;
|
|
const extractTransferableBuffers = (tensors) => {
|
|
const buffers = [];
|
|
for (const tensor of tensors) {
|
|
const data = tensor[2];
|
|
if (!Array.isArray(data) && data.buffer) {
|
|
buffers.push(data.buffer);
|
|
}
|
|
}
|
|
return buffers;
|
|
};
|
|
exports.extractTransferableBuffers = extractTransferableBuffers;
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./lib/wasm/wasm-factory.ts":
|
|
/*!**********************************!*\
|
|
!*** ./lib/wasm/wasm-factory.ts ***!
|
|
\**********************************/
|
|
/***/ (function(__unused_webpack_module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
var __dirname = "/";
|
|
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
// Licensed under the MIT License.
|
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
if (k2 === undefined) k2 = k;
|
|
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
}
|
|
Object.defineProperty(o, k2, desc);
|
|
}) : (function(o, m, k, k2) {
|
|
if (k2 === undefined) k2 = k;
|
|
o[k2] = m[k];
|
|
}));
|
|
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
}) : function(o, v) {
|
|
o["default"] = v;
|
|
});
|
|
var __importStar = (this && this.__importStar) || function (mod) {
|
|
if (mod && mod.__esModule) return mod;
|
|
var result = {};
|
|
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
__setModuleDefault(result, mod);
|
|
return result;
|
|
};
|
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
};
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.dispose = exports.getInstance = exports.initializeWebAssembly = void 0;
|
|
const path = __importStar(__webpack_require__(/*! path */ "?7aa5"));
|
|
const ort_wasm_js_1 = __importDefault(__webpack_require__(/*! ./binding/ort-wasm.js */ "./lib/wasm/binding/ort-wasm.js"));
|
|
const ortWasmFactoryThreaded =
|
|
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
true ? __webpack_require__(/*! ./binding/ort-wasm-threaded.js */ "./lib/wasm/binding/ort-wasm-threaded.js") : 0;
|
|
let wasm;
|
|
let initialized = false;
|
|
let initializing = false;
|
|
let aborted = false;
|
|
const isMultiThreadSupported = () => {
|
|
try {
|
|
// If 'SharedArrayBuffer' is not available, WebAssembly threads will not work.
|
|
if (typeof SharedArrayBuffer === 'undefined') {
|
|
return false;
|
|
}
|
|
// Test for transferability of SABs (for browsers. needed for Firefox)
|
|
// https://groups.google.com/forum/#!msg/mozilla.dev.platform/IHkBZlHETpA/dwsMNchWEQAJ
|
|
if (typeof MessageChannel !== 'undefined') {
|
|
new MessageChannel().port1.postMessage(new SharedArrayBuffer(1));
|
|
}
|
|
// Test for WebAssembly threads capability (for both browsers and Node.js)
|
|
// This typed array is a WebAssembly program containing threaded instructions.
|
|
return WebAssembly.validate(new Uint8Array([
|
|
0, 97, 115, 109, 1, 0, 0, 0, 1, 4, 1, 96, 0, 0, 3, 2, 1, 0, 5,
|
|
4, 1, 3, 1, 1, 10, 11, 1, 9, 0, 65, 0, 254, 16, 2, 0, 26, 11
|
|
]));
|
|
}
|
|
catch (e) {
|
|
return false;
|
|
}
|
|
};
|
|
const isSimdSupported = () => {
|
|
try {
|
|
// Test for WebAssembly SIMD capability (for both browsers and Node.js)
|
|
// This typed array is a WebAssembly program containing SIMD instructions.
|
|
// The binary data is generated from the following code by wat2wasm:
|
|
//
|
|
// (module
|
|
// (type $t0 (func))
|
|
// (func $f0 (type $t0)
|
|
// (drop
|
|
// (i32x4.dot_i16x8_s
|
|
// (i8x16.splat
|
|
// (i32.const 0))
|
|
// (v128.const i32x4 0x00000000 0x00000000 0x00000000 0x00000000)))))
|
|
return WebAssembly.validate(new Uint8Array([
|
|
0, 97, 115, 109, 1, 0, 0, 0, 1, 4, 1, 96, 0, 0, 3, 2, 1, 0, 10, 30, 1, 28, 0, 65, 0,
|
|
253, 15, 253, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 253, 186, 1, 26, 11
|
|
]));
|
|
}
|
|
catch (e) {
|
|
return false;
|
|
}
|
|
};
|
|
const getWasmFileName = (useSimd, useThreads) => {
|
|
if (useThreads) {
|
|
return useSimd ? 'ort-wasm-simd-threaded.wasm' : 'ort-wasm-threaded.wasm';
|
|
}
|
|
else {
|
|
return useSimd ? 'ort-wasm-simd.wasm' : 'ort-wasm.wasm';
|
|
}
|
|
};
|
|
const initializeWebAssembly = async (flags) => {
|
|
if (initialized) {
|
|
return Promise.resolve();
|
|
}
|
|
if (initializing) {
|
|
throw new Error('multiple calls to \'initializeWebAssembly()\' detected.');
|
|
}
|
|
if (aborted) {
|
|
throw new Error('previous call to \'initializeWebAssembly()\' failed.');
|
|
}
|
|
initializing = true;
|
|
// wasm flags are already initialized
|
|
const timeout = flags.initTimeout;
|
|
const numThreads = flags.numThreads;
|
|
const simd = flags.simd;
|
|
const useThreads = numThreads > 1 && isMultiThreadSupported();
|
|
const useSimd = simd && isSimdSupported();
|
|
const wasmPrefixOverride = typeof flags.wasmPaths === 'string' ? flags.wasmPaths : undefined;
|
|
const wasmFileName = getWasmFileName(false, useThreads);
|
|
const wasmOverrideFileName = getWasmFileName(useSimd, useThreads);
|
|
const wasmPathOverride = typeof flags.wasmPaths === 'object' ? flags.wasmPaths[wasmOverrideFileName] : undefined;
|
|
let isTimeout = false;
|
|
const tasks = [];
|
|
// promise for timeout
|
|
if (timeout > 0) {
|
|
tasks.push(new Promise((resolve) => {
|
|
setTimeout(() => {
|
|
isTimeout = true;
|
|
resolve();
|
|
}, timeout);
|
|
}));
|
|
}
|
|
// promise for module initialization
|
|
tasks.push(new Promise((resolve, reject) => {
|
|
const factory = useThreads ? ortWasmFactoryThreaded : ort_wasm_js_1.default;
|
|
const config = {
|
|
locateFile: (fileName, scriptDirectory) => {
|
|
if ( true && useThreads && fileName.endsWith('.worker.js') &&
|
|
typeof Blob !== 'undefined') {
|
|
return URL.createObjectURL(new Blob([
|
|
// This require() function is handled by webpack to load file content of the corresponding .worker.js
|
|
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
__webpack_require__(/*! ./binding/ort-wasm-threaded.worker.js */ "./lib/wasm/binding/ort-wasm-threaded.worker.js")
|
|
], { type: 'text/javascript' }));
|
|
}
|
|
if (fileName === wasmFileName) {
|
|
const prefix = wasmPrefixOverride !== null && wasmPrefixOverride !== void 0 ? wasmPrefixOverride : scriptDirectory;
|
|
return wasmPathOverride !== null && wasmPathOverride !== void 0 ? wasmPathOverride : prefix + wasmOverrideFileName;
|
|
}
|
|
return scriptDirectory + fileName;
|
|
}
|
|
};
|
|
if ( true && useThreads) {
|
|
if (typeof Blob === 'undefined') {
|
|
config.mainScriptUrlOrBlob = path.join(__dirname, 'ort-wasm-threaded.js');
|
|
}
|
|
else {
|
|
const scriptSourceCode = `var ortWasmThreaded=(function(){var _scriptDir;return ${factory.toString()}})();`;
|
|
config.mainScriptUrlOrBlob = new Blob([scriptSourceCode], { type: 'text/javascript' });
|
|
}
|
|
}
|
|
factory(config).then(
|
|
// wasm module initialized successfully
|
|
module => {
|
|
initializing = false;
|
|
initialized = true;
|
|
wasm = module;
|
|
resolve();
|
|
},
|
|
// wasm module failed to initialize
|
|
(what) => {
|
|
initializing = false;
|
|
aborted = true;
|
|
reject(what);
|
|
});
|
|
}));
|
|
await Promise.race(tasks);
|
|
if (isTimeout) {
|
|
throw new Error(`WebAssembly backend initializing failed due to timeout: ${timeout}ms`);
|
|
}
|
|
};
|
|
exports.initializeWebAssembly = initializeWebAssembly;
|
|
const getInstance = () => {
|
|
if (initialized && wasm) {
|
|
return wasm;
|
|
}
|
|
throw new Error('WebAssembly is not initialized yet.');
|
|
};
|
|
exports.getInstance = getInstance;
|
|
const dispose = () => {
|
|
var _a;
|
|
if (initialized && !initializing && !aborted) {
|
|
initializing = true;
|
|
(_a = wasm.PThread) === null || _a === void 0 ? void 0 : _a.terminateAllThreads();
|
|
wasm = undefined;
|
|
initializing = false;
|
|
initialized = false;
|
|
aborted = true;
|
|
}
|
|
};
|
|
exports.dispose = dispose;
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/worker-loader/dist/cjs.js?inline=no-fallback!./lib/wasm/proxy-worker/main.ts":
|
|
/*!***************************************************************************************************!*\
|
|
!*** ./node_modules/worker-loader/dist/cjs.js?inline=no-fallback!./lib/wasm/proxy-worker/main.ts ***!
|
|
\***************************************************************************************************/
|
|
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
__webpack_require__.r(__webpack_exports__);
|
|
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
|
/* harmony export */ "default": () => (/* binding */ Worker_fn)
|
|
/* harmony export */ });
|
|
/* harmony import */ var _node_modules_worker_loader_dist_runtime_inline_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! !!../../../node_modules/worker-loader/dist/runtime/inline.js */ "./node_modules/worker-loader/dist/runtime/inline.js");
|
|
/* harmony import */ var _node_modules_worker_loader_dist_runtime_inline_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_worker_loader_dist_runtime_inline_js__WEBPACK_IMPORTED_MODULE_0__);
|
|
|
|
|
|
|
|
function Worker_fn() {
|
|
return _node_modules_worker_loader_dist_runtime_inline_js__WEBPACK_IMPORTED_MODULE_0___default()("/*!\n* ONNX Runtime Web v1.14.0\n* Copyright (c) Microsoft Corporation. All rights reserved.\n* Licensed under the MIT License.\n*/\n/******/ (() => { // webpackBootstrap\n/******/ \tvar __webpack_modules__ = ({\n\n/***/ \"./lib/wasm/binding/ort-wasm-threaded.js\":\n/*!***********************************************!*\\\n !*** ./lib/wasm/binding/ort-wasm-threaded.js ***!\n \\***********************************************/\n/***/ ((module, __unused_webpack_exports, __webpack_require__) => {\n\nvar __filename = \"/index.js\";\nvar __dirname = \"/\";\n\r\nvar ortWasmThreaded = (() => {\r\n var _scriptDir = typeof document !== 'undefined' && document.currentScript ? document.currentScript.src : undefined;\r\n if (true) _scriptDir = _scriptDir || __filename;\r\n return (\r\nfunction(ortWasmThreaded) {\r\n ortWasmThreaded = ortWasmThreaded || {};\r\n\r\n\r\nfunction d(){m.buffer!=n&&p(m.buffer);return aa}function q(){m.buffer!=n&&p(m.buffer);return ba}function r(){m.buffer!=n&&p(m.buffer);return ca}function v(){m.buffer!=n&&p(m.buffer);return da}function ea(){m.buffer!=n&&p(m.buffer);return fa}var x;x||(x=typeof ortWasmThreaded !== 'undefined' ? ortWasmThreaded : {});var ha,ia;x.ready=new Promise(function(a,b){ha=a;ia=b});\r\nvar ja=Object.assign({},x),ka=\"./this.program\",la=(a,b)=>{throw b;},ma=\"object\"==typeof window,y=\"function\"==typeof importScripts,B=\"object\"==typeof process&&\"object\"==typeof process.versions&&\"string\"==typeof process.versions.node,C=x.ENVIRONMENT_IS_PTHREAD||!1,D=\"\";function na(a){return x.locateFile?x.locateFile(a,D):D+a}var oa,pa,qa,fs,ra,sa;\r\nif(B){D=y?(__webpack_require__(/*! path */ \"?75c6\").dirname)(D)+\"/\":__dirname+\"/\";sa=()=>{ra||(fs=__webpack_require__(/*! fs */ \"?63c8\"),ra=__webpack_require__(/*! path */ \"?75c6\"))};oa=function(b,c){sa();b=ra.normalize(b);return fs.readFileSync(b,c?void 0:\"utf8\")};qa=b=>{b=oa(b,!0);b.buffer||(b=new Uint8Array(b));return b};pa=(b,c,e)=>{sa();b=ra.normalize(b);fs.readFile(b,function(f,h){f?e(f):c(h.buffer)})};1<process.argv.length&&(ka=process.argv[1].replace(/\\\\/g,\"/\"));process.argv.slice(2);process.on(\"uncaughtException\",function(b){if(!(b instanceof E))throw b;});process.on(\"unhandledRejection\",\r\nfunction(b){throw b;});la=(b,c)=>{if(F())throw process.exitCode=b,c;c instanceof E||G(\"exiting due to exception: \"+c);process.exit(b)};x.inspect=function(){return\"[Emscripten Module object]\"};let a;try{a=__webpack_require__(/*! worker_threads */ \"?c6f7\")}catch(b){throw console.error('The \"worker_threads\" module is not supported in this node.js build - perhaps a newer version is needed?'),b;}__webpack_require__.g.Worker=a.Worker}else if(ma||y)y?D=self.location.href:\"undefined\"!=typeof document&&document.currentScript&&(D=document.currentScript.src),\r\n_scriptDir&&(D=_scriptDir),0!==D.indexOf(\"blob:\")?D=D.substr(0,D.replace(/[?#].*/,\"\").lastIndexOf(\"/\")+1):D=\"\",B||(oa=a=>{var b=new XMLHttpRequest;b.open(\"GET\",a,!1);b.send(null);return b.responseText},y&&(qa=a=>{var b=new XMLHttpRequest;b.open(\"GET\",a,!1);b.responseType=\"arraybuffer\";b.send(null);return new Uint8Array(b.response)}),pa=(a,b,c)=>{var e=new XMLHttpRequest;e.open(\"GET\",a,!0);e.responseType=\"arraybuffer\";e.onload=()=>{200==e.status||0==e.status&&e.response?b(e.response):c()};e.onerror=\r\nc;e.send(null)});B&&\"undefined\"==typeof performance&&(__webpack_require__.g.performance=(__webpack_require__(/*! perf_hooks */ \"?674f\").performance));var ta=console.log.bind(console),ua=console.warn.bind(console);B&&(sa(),ta=a=>fs.writeSync(1,a+\"\\n\"),ua=a=>fs.writeSync(2,a+\"\\n\"));var va=x.print||ta,G=x.printErr||ua;Object.assign(x,ja);ja=null;x.thisProgram&&(ka=x.thisProgram);x.quit&&(la=x.quit);var H;x.wasmBinary&&(H=x.wasmBinary);var noExitRuntime=x.noExitRuntime||!1;\"object\"!=typeof WebAssembly&&I(\"no native wasm support detected\");\r\nvar m,wa,xa=!1,ya=\"undefined\"!=typeof TextDecoder?new TextDecoder(\"utf8\"):void 0;\r\nfunction za(a,b,c){b>>>=0;var e=b+c;for(c=b;a[c]&&!(c>=e);)++c;if(16<c-b&&a.buffer&&ya)return ya.decode(a.buffer instanceof SharedArrayBuffer?a.slice(b,c):a.subarray(b,c));for(e=\"\";b<c;){var f=a[b++];if(f&128){var h=a[b++]&63;if(192==(f&224))e+=String.fromCharCode((f&31)<<6|h);else{var k=a[b++]&63;f=224==(f&240)?(f&15)<<12|h<<6|k:(f&7)<<18|h<<12|k<<6|a[b++]&63;65536>f?e+=String.fromCharCode(f):(f-=65536,e+=String.fromCharCode(55296|f>>10,56320|f&1023))}}else e+=String.fromCharCode(f)}return e}\r\nfunction Aa(a,b){return(a>>>=0)?za(q(),a,b):\"\"}\r\nfunction Ba(a,b,c,e){c>>>=0;if(!(0<e))return 0;var f=c;e=c+e-1;for(var h=0;h<a.length;++h){var k=a.charCodeAt(h);if(55296<=k&&57343>=k){var l=a.charCodeAt(++h);k=65536+((k&1023)<<10)|l&1023}if(127>=k){if(c>=e)break;b[c++>>>0]=k}else{if(2047>=k){if(c+1>=e)break;b[c++>>>0]=192|k>>6}else{if(65535>=k){if(c+2>=e)break;b[c++>>>0]=224|k>>12}else{if(c+3>=e)break;b[c++>>>0]=240|k>>18;b[c++>>>0]=128|k>>12&63}b[c++>>>0]=128|k>>6&63}b[c++>>>0]=128|k&63}}b[c>>>0]=0;return c-f}\r\nfunction Ca(a){for(var b=0,c=0;c<a.length;++c){var e=a.charCodeAt(c);127>=e?b++:2047>=e?b+=2:55296<=e&&57343>=e?(b+=4,++c):b+=3}return b}var n,aa,ba,ca,da,fa;C&&(n=x.buffer);function p(a){n=a;x.HEAP8=aa=new Int8Array(a);x.HEAP16=new Int16Array(a);x.HEAP32=ca=new Int32Array(a);x.HEAPU8=ba=new Uint8Array(a);x.HEAPU16=new Uint16Array(a);x.HEAPU32=da=new Uint32Array(a);x.HEAPF32=new Float32Array(a);x.HEAPF64=fa=new Float64Array(a)}var Da=x.INITIAL_MEMORY||16777216;\r\nif(C)m=x.wasmMemory,n=x.buffer;else if(x.wasmMemory)m=x.wasmMemory;else if(m=new WebAssembly.Memory({initial:Da/65536,maximum:65536,shared:!0}),!(m.buffer instanceof SharedArrayBuffer))throw G(\"requested a shared WebAssembly.Memory but the returned buffer is not a SharedArrayBuffer, indicating that while the browser has SharedArrayBuffer it does not have WebAssembly threads support - you may need to set a flag\"),B&&console.log(\"(on node you may need: --experimental-wasm-threads --experimental-wasm-bulk-memory and also use a recent version)\"),\r\nError(\"bad memory\");m&&(n=m.buffer);Da=n.byteLength;p(n);var Ea,Fa=[],Ga=[],Ha=[],Ia=[],Ja=0;function F(){return noExitRuntime||0<Ja}function Ka(){var a=x.preRun.shift();Fa.unshift(a)}var L=0,La=null,M=null;function I(a){if(C)postMessage({cmd:\"onAbort\",arg:a});else if(x.onAbort)x.onAbort(a);a=\"Aborted(\"+a+\")\";G(a);xa=!0;a=new WebAssembly.RuntimeError(a+\". Build with -sASSERTIONS for more info.\");ia(a);throw a;}function Ma(){return O.startsWith(\"data:application/octet-stream;base64,\")}var O;O=\"ort-wasm-threaded.wasm\";\r\nMa()||(O=na(O));function Na(){var a=O;try{if(a==O&&H)return new Uint8Array(H);if(qa)return qa(a);throw\"both async and sync fetching of the wasm failed\";}catch(b){I(b)}}\r\nfunction Oa(){if(!H&&(ma||y)){if(\"function\"==typeof fetch&&!O.startsWith(\"file://\"))return fetch(O,{credentials:\"same-origin\"}).then(function(a){if(!a.ok)throw\"failed to load wasm binary file at '\"+O+\"'\";return a.arrayBuffer()}).catch(function(){return Na()});if(pa)return new Promise(function(a,b){pa(O,function(c){a(new Uint8Array(c))},b)})}return Promise.resolve().then(function(){return Na()})}var Pa={};\r\nfunction E(a){this.name=\"ExitStatus\";this.message=\"Program terminated with exit(\"+a+\")\";this.status=a}function Qa(a){(a=P.Vb[a])||I();P.mc(a)}function Ra(a){var b=P.Cc();if(!b)return 6;P.ac.push(b);P.Vb[a.Ub]=b;b.Ub=a.Ub;var c={cmd:\"run\",start_routine:a.Ic,arg:a.zc,pthread_ptr:a.Ub};b.$b=()=>{c.time=performance.now();b.postMessage(c,a.Nc)};b.loaded&&(b.$b(),delete b.$b);return 0}function Sa(a){if(C)return Q(1,1,a);if(!F()){P.oc();if(x.onExit)x.onExit(a);xa=!0}la(a,new E(a))}\r\nfunction Ta(a,b){if(!b&&C)throw Ua(a),\"unwind\";F()||C||(Va(),R(Ha),Wa(0),Xa[1].length&&Ya(1,10),Xa[2].length&&Ya(2,10),P.oc());Sa(a)}\r\nvar P={Yb:[],ac:[],qc:[],Vb:{},fc:function(){C&&P.Ec()},Pc:function(){},Ec:function(){P.receiveObjectTransfer=P.Gc;P.threadInitTLS=P.pc;P.setExitStatus=P.nc;noExitRuntime=!1},nc:function(){},oc:function(){for(var a of Object.values(P.Vb))P.mc(a);for(a of P.Yb)a.terminate();P.Yb=[]},mc:function(a){var b=a.Ub;delete P.Vb[b];P.Yb.push(a);P.ac.splice(P.ac.indexOf(a),1);a.Ub=0;Za(b)},Gc:function(){},pc:function(){P.qc.forEach(a=>a())},Fc:function(a,b){a.onmessage=c=>{c=c.data;var e=c.cmd;a.Ub&&(P.Bc=a.Ub);\r\nif(c.targetThread&&c.targetThread!=$a()){var f=P.Vb[c.Qc];f?f.postMessage(c,c.transferList):G('Internal error! Worker sent a message \"'+e+'\" to target pthread '+c.targetThread+\", but that thread no longer exists!\")}else if(\"processProxyingQueue\"===e)ab(c.queue);else if(\"spawnThread\"===e)Ra(c);else if(\"cleanupThread\"===e)Qa(c.thread);else if(\"killThread\"===e)c=c.thread,e=P.Vb[c],delete P.Vb[c],e.terminate(),Za(c),P.ac.splice(P.ac.indexOf(e),1),e.Ub=0;else if(\"cancelThread\"===e)P.Vb[c.thread].postMessage({cmd:\"cancel\"});\r\nelse if(\"loaded\"===e)a.loaded=!0,b&&b(a),a.$b&&(a.$b(),delete a.$b);else if(\"print\"===e)va(\"Thread \"+c.threadId+\": \"+c.text);else if(\"printErr\"===e)G(\"Thread \"+c.threadId+\": \"+c.text);else if(\"alert\"===e)alert(\"Thread \"+c.threadId+\": \"+c.text);else if(\"setimmediate\"===c.target)a.postMessage(c);else if(\"onAbort\"===e){if(x.onAbort)x.onAbort(c.arg)}else e&&G(\"worker sent an unknown command \"+e);P.Bc=void 0};a.onerror=c=>{G(\"worker sent an error! \"+c.filename+\":\"+c.lineno+\": \"+c.message);throw c;};B&&\r\n(a.on(\"message\",function(c){a.onmessage({data:c})}),a.on(\"error\",function(c){a.onerror(c)}),a.on(\"detachedExit\",function(){}));a.postMessage({cmd:\"load\",urlOrBlob:x.mainScriptUrlOrBlob||_scriptDir,wasmMemory:m,wasmModule:wa})},yc:function(){var a=na(\"ort-wasm-threaded.worker.js\");P.Yb.push(new Worker(a))},Cc:function(){0==P.Yb.length&&(P.yc(),P.Fc(P.Yb[0]));return P.Yb.pop()}};x.PThread=P;function R(a){for(;0<a.length;)a.shift()(x)}function bb(a){var b=S();a=a();U(b);return a}\r\nx.establishStackSpace=function(){var a=$a(),b=r()[a+44>>2>>>0];a=r()[a+48>>2>>>0];cb(b,b-a);U(b)};function Ua(a){if(C)return Q(2,0,a);try{Ta(a)}catch(b){b instanceof E||\"unwind\"==b||la(1,b)}}var db=[];function V(a){var b=db[a];b||(a>=db.length&&(db.length=a+1),db[a]=b=Ea.get(a));return b}x.invokeEntryPoint=function(a,b){a=V(a)(b);F()?P.nc(a):eb(a)};function fb(a,b){d().set(a,b>>>0)}var gb=[],hb=0,W=0;\r\nfunction X(a){this.Zb=a;this.Sb=a-24;this.xc=function(b){v()[this.Sb+4>>2>>>0]=b};this.bc=function(){return v()[this.Sb+4>>2>>>0]};this.wc=function(b){v()[this.Sb+8>>2>>>0]=b};this.Dc=function(){return v()[this.Sb+8>>2>>>0]};this.rc=function(){r()[this.Sb>>2>>>0]=0};this.hc=function(b){b=b?1:0;d()[this.Sb+12>>0>>>0]=b};this.uc=function(){return 0!=d()[this.Sb+12>>0>>>0]};this.ic=function(b){b=b?1:0;d()[this.Sb+13>>0>>>0]=b};this.kc=function(){return 0!=d()[this.Sb+13>>0>>>0]};this.fc=function(b,c){this.cc(0);\r\nthis.xc(b);this.wc(c);this.rc();this.hc(!1);this.ic(!1)};this.sc=function(){Atomics.add(r(),this.Sb>>2,1)};this.Hc=function(){return 1===Atomics.sub(r(),this.Sb>>2,1)};this.cc=function(b){v()[this.Sb+16>>2>>>0]=b};this.tc=function(){return v()[this.Sb+16>>2>>>0]};this.vc=function(){if(ib(this.bc()))return v()[this.Zb>>2>>>0];var b=this.tc();return 0!==b?b:this.Zb}}function jb(a){return kb((new X(a)).Sb)}function lb(a,b,c,e){return C?Q(3,1,a,b,c,e):mb(a,b,c,e)}\r\nfunction mb(a,b,c,e){if(\"undefined\"==typeof SharedArrayBuffer)return G(\"Current environment does not support SharedArrayBuffer, pthreads are not available!\"),6;var f=[];if(C&&0===f.length)return lb(a,b,c,e);a={Ic:c,Ub:a,zc:e,Nc:f};return C?(a.Oc=\"spawnThread\",postMessage(a,f),0):Ra(a)}function nb(a,b,c){return C?Q(4,1,a,b,c):0}function ob(a,b){if(C)return Q(5,1,a,b)}function pb(a,b){if(C)return Q(6,1,a,b)}function qb(a,b,c){if(C)return Q(7,1,a,b,c)}function rb(a,b,c){return C?Q(8,1,a,b,c):0}\r\nfunction sb(a,b){if(C)return Q(9,1,a,b)}function tb(a,b,c){if(C)return Q(10,1,a,b,c)}function ub(a,b,c,e){if(C)return Q(11,1,a,b,c,e)}function vb(a,b,c,e){if(C)return Q(12,1,a,b,c,e)}function wb(a,b,c,e){if(C)return Q(13,1,a,b,c,e)}function xb(a){if(C)return Q(14,1,a)}function yb(a,b){if(C)return Q(15,1,a,b)}function zb(a,b,c){if(C)return Q(16,1,a,b,c)}function ab(a){Atomics.store(r(),a>>2,1);$a()&&Ab(a);Atomics.compareExchange(r(),a>>2,1,0)}x.executeNotifiedProxyingQueue=ab;\r\nfunction Bb(a){return v()[a>>>2]+4294967296*r()[a+4>>>2]}function Cb(a,b,c,e,f,h){return C?Q(17,1,a,b,c,e,f,h):-52}function Db(a,b,c,e,f,h){if(C)return Q(18,1,a,b,c,e,f,h)}function Eb(a){var b=Ca(a)+1,c=Fb(b);c&&Ba(a,d(),c,b);return c}\r\nfunction Gb(a,b,c){function e(t){return(t=t.toTimeString().match(/\\(([A-Za-z ]+)\\)$/))?t[1]:\"GMT\"}if(C)return Q(19,1,a,b,c);var f=(new Date).getFullYear(),h=new Date(f,0,1),k=new Date(f,6,1);f=h.getTimezoneOffset();var l=k.getTimezoneOffset(),u=Math.max(f,l);r()[a>>2>>>0]=60*u;r()[b>>2>>>0]=Number(f!=l);a=e(h);b=e(k);a=Eb(a);b=Eb(b);l<f?(v()[c>>2>>>0]=a,v()[c+4>>2>>>0]=b):(v()[c>>2>>>0]=b,v()[c+4>>2>>>0]=a)}function Hb(a,b,c){Hb.Ac||(Hb.Ac=!0,Gb(a,b,c))}var Ib,Jb;\r\nJb=B?()=>{var a=process.hrtime();return 1E3*a[0]+a[1]/1E6}:C?()=>performance.now()-x.__performance_now_clock_drift:()=>performance.now();function Q(a,b){var c=arguments.length-2,e=arguments;return bb(()=>{for(var f=Kb(8*c),h=f>>3,k=0;k<c;k++){var l=e[2+k];ea()[h+k>>>0]=l}return Lb(a,c,f,b)})}var Mb=[],Nb={};\r\nfunction Ob(){if(!Pb){var a={USER:\"web_user\",LOGNAME:\"web_user\",PATH:\"/\",PWD:\"/\",HOME:\"/home/web_user\",LANG:(\"object\"==typeof navigator&&navigator.languages&&navigator.languages[0]||\"C\").replace(\"-\",\"_\")+\".UTF-8\",_:ka||\"./this.program\"},b;for(b in Nb)void 0===Nb[b]?delete a[b]:a[b]=Nb[b];var c=[];for(b in a)c.push(b+\"=\"+a[b]);Pb=c}return Pb}var Pb;\r\nfunction Qb(a,b){if(C)return Q(20,1,a,b);var c=0;Ob().forEach(function(e,f){var h=b+c;f=v()[a+4*f>>2>>>0]=h;for(h=0;h<e.length;++h)d()[f++>>0>>>0]=e.charCodeAt(h);d()[f>>0>>>0]=0;c+=e.length+1});return 0}function Rb(a,b){if(C)return Q(21,1,a,b);var c=Ob();v()[a>>2>>>0]=c.length;var e=0;c.forEach(function(f){e+=f.length+1});v()[b>>2>>>0]=e;return 0}function Sb(a){return C?Q(22,1,a):52}function Tb(a,b,c,e){return C?Q(23,1,a,b,c,e):52}function Ub(a,b,c,e,f){return C?Q(24,1,a,b,c,e,f):70}\r\nvar Xa=[null,[],[]];function Ya(a,b){var c=Xa[a];0===b||10===b?((1===a?va:G)(za(c,0)),c.length=0):c.push(b)}function Vb(a,b,c,e){if(C)return Q(25,1,a,b,c,e);for(var f=0,h=0;h<c;h++){var k=v()[b>>2>>>0],l=v()[b+4>>2>>>0];b+=8;for(var u=0;u<l;u++)Ya(a,q()[k+u>>>0]);f+=l}v()[e>>2>>>0]=f;return 0}var Y=0;\r\nfunction Wb(){if(\"object\"==typeof crypto&&\"function\"==typeof crypto.getRandomValues){var a=new Uint8Array(1);return()=>{crypto.getRandomValues(a);return a[0]}}if(B)try{var b=__webpack_require__(Object(function webpackMissingModule() { var e = new Error(\"Cannot find module 'crypto'\"); e.code = 'MODULE_NOT_FOUND'; throw e; }()));return()=>b.randomBytes(1)[0]}catch(c){}return()=>I(\"randomDevice\")}function Xb(a,b){Xb.lc||(Xb.lc=Wb());for(var c=0;c<b;c++)d()[a+c>>0>>>0]=Xb.lc();return 0}function Yb(a){return 0===a%4&&(0!==a%100||0===a%400)}var Zb=[31,29,31,30,31,30,31,31,30,31,30,31],$b=[31,28,31,30,31,30,31,31,30,31,30,31];\r\nfunction ac(a){var b=Array(Ca(a)+1);Ba(a,b,0,b.length);return b}\r\nfunction bc(a,b,c,e){function f(g,w,z){for(g=\"number\"==typeof g?g.toString():g||\"\";g.length<w;)g=z[0]+g;return g}function h(g,w){return f(g,w,\"0\")}function k(g,w){function z(T){return 0>T?-1:0<T?1:0}var N;0===(N=z(g.getFullYear()-w.getFullYear()))&&0===(N=z(g.getMonth()-w.getMonth()))&&(N=z(g.getDate()-w.getDate()));return N}function l(g){switch(g.getDay()){case 0:return new Date(g.getFullYear()-1,11,29);case 1:return g;case 2:return new Date(g.getFullYear(),0,3);case 3:return new Date(g.getFullYear(),\r\n0,2);case 4:return new Date(g.getFullYear(),0,1);case 5:return new Date(g.getFullYear()-1,11,31);case 6:return new Date(g.getFullYear()-1,11,30)}}function u(g){var w=g.Wb;for(g=new Date((new Date(g.Xb+1900,0,1)).getTime());0<w;){var z=g.getMonth(),N=(Yb(g.getFullYear())?Zb:$b)[z];if(w>N-g.getDate())w-=N-g.getDate()+1,g.setDate(1),11>z?g.setMonth(z+1):(g.setMonth(0),g.setFullYear(g.getFullYear()+1));else{g.setDate(g.getDate()+w);break}}z=new Date(g.getFullYear()+1,0,4);w=l(new Date(g.getFullYear(),\r\n0,4));z=l(z);return 0>=k(w,g)?0>=k(z,g)?g.getFullYear()+1:g.getFullYear():g.getFullYear()-1}var t=r()[e+40>>2>>>0];e={Lc:r()[e>>2>>>0],Kc:r()[e+4>>2>>>0],dc:r()[e+8>>2>>>0],jc:r()[e+12>>2>>>0],ec:r()[e+16>>2>>>0],Xb:r()[e+20>>2>>>0],Tb:r()[e+24>>2>>>0],Wb:r()[e+28>>2>>>0],Rc:r()[e+32>>2>>>0],Jc:r()[e+36>>2>>>0],Mc:t?Aa(t):\"\"};c=Aa(c);t={\"%c\":\"%a %b %d %H:%M:%S %Y\",\"%D\":\"%m/%d/%y\",\"%F\":\"%Y-%m-%d\",\"%h\":\"%b\",\"%r\":\"%I:%M:%S %p\",\"%R\":\"%H:%M\",\"%T\":\"%H:%M:%S\",\"%x\":\"%m/%d/%y\",\"%X\":\"%H:%M:%S\",\"%Ec\":\"%c\",\"%EC\":\"%C\",\r\n\"%Ex\":\"%m/%d/%y\",\"%EX\":\"%H:%M:%S\",\"%Ey\":\"%y\",\"%EY\":\"%Y\",\"%Od\":\"%d\",\"%Oe\":\"%e\",\"%OH\":\"%H\",\"%OI\":\"%I\",\"%Om\":\"%m\",\"%OM\":\"%M\",\"%OS\":\"%S\",\"%Ou\":\"%u\",\"%OU\":\"%U\",\"%OV\":\"%V\",\"%Ow\":\"%w\",\"%OW\":\"%W\",\"%Oy\":\"%y\"};for(var A in t)c=c.replace(new RegExp(A,\"g\"),t[A]);var K=\"Sunday Monday Tuesday Wednesday Thursday Friday Saturday\".split(\" \"),J=\"January February March April May June July August September October November December\".split(\" \");t={\"%a\":function(g){return K[g.Tb].substring(0,3)},\"%A\":function(g){return K[g.Tb]},\r\n\"%b\":function(g){return J[g.ec].substring(0,3)},\"%B\":function(g){return J[g.ec]},\"%C\":function(g){return h((g.Xb+1900)/100|0,2)},\"%d\":function(g){return h(g.jc,2)},\"%e\":function(g){return f(g.jc,2,\" \")},\"%g\":function(g){return u(g).toString().substring(2)},\"%G\":function(g){return u(g)},\"%H\":function(g){return h(g.dc,2)},\"%I\":function(g){g=g.dc;0==g?g=12:12<g&&(g-=12);return h(g,2)},\"%j\":function(g){for(var w=0,z=0;z<=g.ec-1;w+=(Yb(g.Xb+1900)?Zb:$b)[z++]);return h(g.jc+w,3)},\"%m\":function(g){return h(g.ec+\r\n1,2)},\"%M\":function(g){return h(g.Kc,2)},\"%n\":function(){return\"\\n\"},\"%p\":function(g){return 0<=g.dc&&12>g.dc?\"AM\":\"PM\"},\"%S\":function(g){return h(g.Lc,2)},\"%t\":function(){return\"\\t\"},\"%u\":function(g){return g.Tb||7},\"%U\":function(g){return h(Math.floor((g.Wb+7-g.Tb)/7),2)},\"%V\":function(g){var w=Math.floor((g.Wb+7-(g.Tb+6)%7)/7);2>=(g.Tb+371-g.Wb-2)%7&&w++;if(w)53==w&&(z=(g.Tb+371-g.Wb)%7,4==z||3==z&&Yb(g.Xb)||(w=1));else{w=52;var z=(g.Tb+7-g.Wb-1)%7;(4==z||5==z&&Yb(g.Xb%400-1))&&w++}return h(w,\r\n2)},\"%w\":function(g){return g.Tb},\"%W\":function(g){return h(Math.floor((g.Wb+7-(g.Tb+6)%7)/7),2)},\"%y\":function(g){return(g.Xb+1900).toString().substring(2)},\"%Y\":function(g){return g.Xb+1900},\"%z\":function(g){g=g.Jc;var w=0<=g;g=Math.abs(g)/60;return(w?\"+\":\"-\")+String(\"0000\"+(g/60*100+g%60)).slice(-4)},\"%Z\":function(g){return g.Mc},\"%%\":function(){return\"%\"}};c=c.replace(/%%/g,\"\\x00\\x00\");for(A in t)c.includes(A)&&(c=c.replace(new RegExp(A,\"g\"),t[A](e)));c=c.replace(/\\0\\0/g,\"%\");A=ac(c);if(A.length>\r\nb)return 0;fb(A,a);return A.length-1}P.fc();\r\nvar cc=[null,Sa,Ua,lb,nb,ob,pb,qb,rb,sb,tb,ub,vb,wb,xb,yb,zb,Cb,Db,Gb,Qb,Rb,Sb,Tb,Ub,Vb],Pc={b:function(a){return Fb(a+24)+24},n:function(a){a=new X(a);a.uc()||(a.hc(!0),hb--);a.ic(!1);gb.push(a);a.sc();return a.vc()},ma:function(a){G(\"Unexpected exception thrown, this is not properly supported - aborting\");xa=!0;throw a;},x:function(){Z(0);var a=gb.pop();if(a.Hc()&&!a.kc()){var b=a.Dc();b&&V(b)(a.Zb);jb(a.Zb)}W=0},e:function(){var a=W;if(!a)return Y=0;var b=new X(a);b.cc(a);var c=b.bc();if(!c)return Y=\r\n0,a;for(var e=Array.prototype.slice.call(arguments),f=0;f<e.length;f++){var h=e[f];if(0===h||h===c)break;if(dc(h,c,b.Sb+16))return Y=h,a}Y=c;return a},l:function(){var a=W;if(!a)return Y=0;var b=new X(a);b.cc(a);var c=b.bc();if(!c)return Y=0,a;for(var e=Array.prototype.slice.call(arguments),f=0;f<e.length;f++){var h=e[f];if(0===h||h===c)break;if(dc(h,c,b.Sb+16))return Y=h,a}Y=c;return a},h:function(){var a=W;if(!a)return Y=0;var b=new X(a);b.cc(a);var c=b.bc();if(!c)return Y=0,a;for(var e=Array.prototype.slice.call(arguments),\r\nf=0;f<e.length;f++){var h=e[f];if(0===h||h===c)break;if(dc(h,c,b.Sb+16))return Y=h,a}Y=c;return a},t:jb,M:function(){var a=gb.pop();a||I(\"no exception to throw\");var b=a.Zb;a.kc()||(gb.push(a),a.ic(!0),a.hc(!1),hb++);W=b;throw b;},c:function(a,b,c){(new X(a)).fc(b,c);W=a;hb++;throw a;},pa:function(){return hb},Fa:function(a){ec(a,!y,1,!ma);P.pc()},T:function(a){C?postMessage({cmd:\"cleanupThread\",thread:a}):Qa(a)},xa:mb,j:function(a){W||(W=a);throw a;},H:nb,Ma:ob,ua:pb,wa:qb,oa:rb,Ka:sb,Ca:tb,Ja:ub,\r\nV:vb,va:wb,sa:xb,La:yb,ta:zb,Ta:function(){},X:function(){I(\"To use dlopen, you need enable dynamic linking, see https://github.com/emscripten-core/emscripten/wiki/Linking\")},Ua:function(){I(\"To use dlopen, you need enable dynamic linking, see https://github.com/emscripten-core/emscripten/wiki/Linking\")},W:function(){return Date.now()},ya:function(){return 2097152},Oa:function(){return!0},za:function(a,b,c,e){if(a==b)setTimeout(()=>ab(e));else if(C)postMessage({targetThread:a,cmd:\"processProxyingQueue\",\r\nqueue:e});else{a=P.Vb[a];if(!a)return;a.postMessage({cmd:\"processProxyingQueue\",queue:e})}return 1},Ea:function(){return-1},Pa:function(a,b){a=new Date(1E3*Bb(a));r()[b>>2>>>0]=a.getUTCSeconds();r()[b+4>>2>>>0]=a.getUTCMinutes();r()[b+8>>2>>>0]=a.getUTCHours();r()[b+12>>2>>>0]=a.getUTCDate();r()[b+16>>2>>>0]=a.getUTCMonth();r()[b+20>>2>>>0]=a.getUTCFullYear()-1900;r()[b+24>>2>>>0]=a.getUTCDay();a=(a.getTime()-Date.UTC(a.getUTCFullYear(),0,1,0,0,0,0))/864E5|0;r()[b+28>>2>>>0]=a},Qa:function(a,b){a=\r\nnew Date(1E3*Bb(a));r()[b>>2>>>0]=a.getSeconds();r()[b+4>>2>>>0]=a.getMinutes();r()[b+8>>2>>>0]=a.getHours();r()[b+12>>2>>>0]=a.getDate();r()[b+16>>2>>>0]=a.getMonth();r()[b+20>>2>>>0]=a.getFullYear()-1900;r()[b+24>>2>>>0]=a.getDay();var c=new Date(a.getFullYear(),0,1),e=(a.getTime()-c.getTime())/864E5|0;r()[b+28>>2>>>0]=e;r()[b+36>>2>>>0]=-(60*a.getTimezoneOffset());e=(new Date(a.getFullYear(),6,1)).getTimezoneOffset();c=c.getTimezoneOffset();a=(e!=c&&a.getTimezoneOffset()==Math.min(c,e))|0;r()[b+\r\n32>>2>>>0]=a},Ra:function(a){var b=new Date(r()[a+20>>2>>>0]+1900,r()[a+16>>2>>>0],r()[a+12>>2>>>0],r()[a+8>>2>>>0],r()[a+4>>2>>>0],r()[a>>2>>>0],0),c=r()[a+32>>2>>>0],e=b.getTimezoneOffset(),f=new Date(b.getFullYear(),0,1),h=(new Date(b.getFullYear(),6,1)).getTimezoneOffset(),k=f.getTimezoneOffset(),l=Math.min(k,h);0>c?r()[a+32>>2>>>0]=Number(h!=k&&l==e):0<c!=(l==e)&&(h=Math.max(k,h),b.setTime(b.getTime()+6E4*((0<c?l:h)-e)));r()[a+24>>2>>>0]=b.getDay();c=(b.getTime()-f.getTime())/864E5|0;r()[a+28>>\r\n2>>>0]=c;r()[a>>2>>>0]=b.getSeconds();r()[a+4>>2>>>0]=b.getMinutes();r()[a+8>>2>>>0]=b.getHours();r()[a+12>>2>>>0]=b.getDate();r()[a+16>>2>>>0]=b.getMonth();return b.getTime()/1E3|0},Aa:Cb,Ba:Db,Sa:Hb,y:function(){I(\"\")},U:function(){if(!B&&!y){var a=\"Blocking on the main thread is very dangerous, see https://emscripten.org/docs/porting/pthreads.html#blocking-on-the-main-browser-thread\";Ib||(Ib={});Ib[a]||(Ib[a]=1,B&&(a=\"warning: \"+a),G(a))}},ra:function(){return 4294901760},B:Jb,Ia:function(a,b,\r\nc){q().copyWithin(a>>>0,b>>>0,b+c>>>0)},F:function(){return B?(__webpack_require__(/*! os */ \"?aedb\").cpus)().length:navigator.hardwareConcurrency},Da:function(a,b,c){Mb.length=b;c>>=3;for(var e=0;e<b;e++)Mb[e]=ea()[c+e>>>0];return(0>a?Pa[-a-1]:cc[a]).apply(null,Mb)},qa:function(a){var b=q().length;a>>>=0;if(a<=b||4294901760<a)return!1;for(var c=1;4>=c;c*=2){var e=b*(1+.2/c);e=Math.min(e,a+100663296);var f=Math;e=Math.max(a,e);f=f.min.call(f,4294901760,e+(65536-e%65536)%65536);a:{try{m.grow(f-n.byteLength+65535>>>16);p(m.buffer);\r\nvar h=1;break a}catch(k){}h=void 0}if(h)return!0}return!1},Na:function(){throw\"unwind\";},Ga:Qb,Ha:Rb,J:Ta,I:Sb,S:Tb,ga:Ub,R:Vb,d:function(){return Y},na:Xb,ia:fc,ja:gc,K:hc,f:ic,P:jc,Q:kc,k:lc,p:mc,q:nc,N:oc,s:pc,w:qc,L:rc,E:sc,aa:tc,_:uc,Z:vc,ca:wc,$:xc,ba:yc,Y:zc,g:Ac,r:Bc,i:Cc,ha:Dc,m:Ec,v:Fc,u:Gc,O:Hc,A:Ic,ka:Jc,C:Kc,D:Lc,fa:Mc,da:Nc,ea:Oc,o:function(a){return a},a:m||x.wasmMemory,G:function(a){Y=a},la:bc,z:function(a,b,c,e){return bc(a,b,c,e)}};\r\n(function(){function a(f,h){x.asm=f.exports;P.qc.push(x.asm.sb);Ea=x.asm.ub;Ga.unshift(x.asm.Va);wa=h;C||(L--,x.monitorRunDependencies&&x.monitorRunDependencies(L),0==L&&(null!==La&&(clearInterval(La),La=null),M&&(f=M,M=null,f())))}function b(f){a(f.instance,f.module)}function c(f){return Oa().then(function(h){return WebAssembly.instantiate(h,e)}).then(function(h){return h}).then(f,function(h){G(\"failed to asynchronously prepare wasm: \"+h);I(h)})}var e={a:Pc};C||(L++,x.monitorRunDependencies&&x.monitorRunDependencies(L));\r\nif(x.instantiateWasm)try{return x.instantiateWasm(e,a)}catch(f){return G(\"Module.instantiateWasm callback failed with error: \"+f),!1}(function(){return H||\"function\"!=typeof WebAssembly.instantiateStreaming||Ma()||O.startsWith(\"file://\")||B||\"function\"!=typeof fetch?c(b):fetch(O,{credentials:\"same-origin\"}).then(function(f){return WebAssembly.instantiateStreaming(f,e).then(b,function(h){G(\"wasm streaming compile failed: \"+h);G(\"falling back to ArrayBuffer instantiation\");return c(b)})})})().catch(ia);\r\nreturn{}})();x.___wasm_call_ctors=function(){return(x.___wasm_call_ctors=x.asm.Va).apply(null,arguments)};x._OrtInit=function(){return(x._OrtInit=x.asm.Wa).apply(null,arguments)};x._OrtCreateSessionOptions=function(){return(x._OrtCreateSessionOptions=x.asm.Xa).apply(null,arguments)};x._OrtAppendExecutionProvider=function(){return(x._OrtAppendExecutionProvider=x.asm.Ya).apply(null,arguments)};x._OrtAddSessionConfigEntry=function(){return(x._OrtAddSessionConfigEntry=x.asm.Za).apply(null,arguments)};\r\nx._OrtReleaseSessionOptions=function(){return(x._OrtReleaseSessionOptions=x.asm._a).apply(null,arguments)};x._OrtCreateSession=function(){return(x._OrtCreateSession=x.asm.$a).apply(null,arguments)};x._OrtReleaseSession=function(){return(x._OrtReleaseSession=x.asm.ab).apply(null,arguments)};x._OrtGetInputCount=function(){return(x._OrtGetInputCount=x.asm.bb).apply(null,arguments)};x._OrtGetOutputCount=function(){return(x._OrtGetOutputCount=x.asm.cb).apply(null,arguments)};\r\nx._OrtGetInputName=function(){return(x._OrtGetInputName=x.asm.db).apply(null,arguments)};x._OrtGetOutputName=function(){return(x._OrtGetOutputName=x.asm.eb).apply(null,arguments)};x._OrtFree=function(){return(x._OrtFree=x.asm.fb).apply(null,arguments)};x._OrtCreateTensor=function(){return(x._OrtCreateTensor=x.asm.gb).apply(null,arguments)};x._OrtGetTensorData=function(){return(x._OrtGetTensorData=x.asm.hb).apply(null,arguments)};\r\nx._OrtReleaseTensor=function(){return(x._OrtReleaseTensor=x.asm.ib).apply(null,arguments)};x._OrtCreateRunOptions=function(){return(x._OrtCreateRunOptions=x.asm.jb).apply(null,arguments)};x._OrtAddRunConfigEntry=function(){return(x._OrtAddRunConfigEntry=x.asm.kb).apply(null,arguments)};x._OrtReleaseRunOptions=function(){return(x._OrtReleaseRunOptions=x.asm.lb).apply(null,arguments)};x._OrtRun=function(){return(x._OrtRun=x.asm.mb).apply(null,arguments)};\r\nx._OrtEndProfiling=function(){return(x._OrtEndProfiling=x.asm.nb).apply(null,arguments)};var $a=x._pthread_self=function(){return($a=x._pthread_self=x.asm.ob).apply(null,arguments)},Fb=x._malloc=function(){return(Fb=x._malloc=x.asm.pb).apply(null,arguments)},kb=x._free=function(){return(kb=x._free=x.asm.qb).apply(null,arguments)},Wa=x._fflush=function(){return(Wa=x._fflush=x.asm.rb).apply(null,arguments)};x.__emscripten_tls_init=function(){return(x.__emscripten_tls_init=x.asm.sb).apply(null,arguments)};\r\nvar Va=x.___funcs_on_exit=function(){return(Va=x.___funcs_on_exit=x.asm.tb).apply(null,arguments)},ec=x.__emscripten_thread_init=function(){return(ec=x.__emscripten_thread_init=x.asm.vb).apply(null,arguments)};x.__emscripten_thread_crashed=function(){return(x.__emscripten_thread_crashed=x.asm.wb).apply(null,arguments)};\r\nvar Lb=x._emscripten_run_in_main_runtime_thread_js=function(){return(Lb=x._emscripten_run_in_main_runtime_thread_js=x.asm.xb).apply(null,arguments)},Ab=x.__emscripten_proxy_execute_task_queue=function(){return(Ab=x.__emscripten_proxy_execute_task_queue=x.asm.yb).apply(null,arguments)},Za=x.__emscripten_thread_free_data=function(){return(Za=x.__emscripten_thread_free_data=x.asm.zb).apply(null,arguments)},eb=x.__emscripten_thread_exit=function(){return(eb=x.__emscripten_thread_exit=x.asm.Ab).apply(null,\r\narguments)},Z=x._setThrew=function(){return(Z=x._setThrew=x.asm.Bb).apply(null,arguments)},cb=x._emscripten_stack_set_limits=function(){return(cb=x._emscripten_stack_set_limits=x.asm.Cb).apply(null,arguments)},S=x.stackSave=function(){return(S=x.stackSave=x.asm.Db).apply(null,arguments)},U=x.stackRestore=function(){return(U=x.stackRestore=x.asm.Eb).apply(null,arguments)},Kb=x.stackAlloc=function(){return(Kb=x.stackAlloc=x.asm.Fb).apply(null,arguments)},dc=x.___cxa_can_catch=function(){return(dc=x.___cxa_can_catch=\r\nx.asm.Gb).apply(null,arguments)},ib=x.___cxa_is_pointer_type=function(){return(ib=x.___cxa_is_pointer_type=x.asm.Hb).apply(null,arguments)},Qc=x.dynCall_j=function(){return(Qc=x.dynCall_j=x.asm.Ib).apply(null,arguments)},Rc=x.dynCall_iiiiij=function(){return(Rc=x.dynCall_iiiiij=x.asm.Jb).apply(null,arguments)},Sc=x.dynCall_jii=function(){return(Sc=x.dynCall_jii=x.asm.Kb).apply(null,arguments)},Tc=x.dynCall_viiiiij=function(){return(Tc=x.dynCall_viiiiij=x.asm.Lb).apply(null,arguments)},Uc=x.dynCall_vjji=\r\nfunction(){return(Uc=x.dynCall_vjji=x.asm.Mb).apply(null,arguments)},Vc=x.dynCall_viiijjjii=function(){return(Vc=x.dynCall_viiijjjii=x.asm.Nb).apply(null,arguments)},Wc=x.dynCall_iij=function(){return(Wc=x.dynCall_iij=x.asm.Ob).apply(null,arguments)},Xc=x.dynCall_ji=function(){return(Xc=x.dynCall_ji=x.asm.Pb).apply(null,arguments)},Yc=x.dynCall_iiiiiij=function(){return(Yc=x.dynCall_iiiiiij=x.asm.Qb).apply(null,arguments)},Zc=x.dynCall_iiij=function(){return(Zc=x.dynCall_iiij=x.asm.Rb).apply(null,\r\narguments)};function ic(a,b){var c=S();try{return V(a)(b)}catch(e){U(c);if(e!==e+0)throw e;Z(1,0)}}function Bc(a,b){var c=S();try{V(a)(b)}catch(e){U(c);if(e!==e+0)throw e;Z(1,0)}}function Cc(a,b,c){var e=S();try{V(a)(b,c)}catch(f){U(e);if(f!==f+0)throw f;Z(1,0)}}function lc(a,b,c){var e=S();try{return V(a)(b,c)}catch(f){U(e);if(f!==f+0)throw f;Z(1,0)}}function mc(a,b,c,e){var f=S();try{return V(a)(b,c,e)}catch(h){U(f);if(h!==h+0)throw h;Z(1,0)}}\r\nfunction qc(a,b,c,e,f,h,k){var l=S();try{return V(a)(b,c,e,f,h,k)}catch(u){U(l);if(u!==u+0)throw u;Z(1,0)}}function Ac(a){var b=S();try{V(a)()}catch(c){U(b);if(c!==c+0)throw c;Z(1,0)}}function pc(a,b,c,e,f,h){var k=S();try{return V(a)(b,c,e,f,h)}catch(l){U(k);if(l!==l+0)throw l;Z(1,0)}}function nc(a,b,c,e,f){var h=S();try{return V(a)(b,c,e,f)}catch(k){U(h);if(k!==k+0)throw k;Z(1,0)}}function Ec(a,b,c,e){var f=S();try{V(a)(b,c,e)}catch(h){U(f);if(h!==h+0)throw h;Z(1,0)}}\r\nfunction Gc(a,b,c,e,f,h){var k=S();try{V(a)(b,c,e,f,h)}catch(l){U(k);if(l!==l+0)throw l;Z(1,0)}}function Fc(a,b,c,e,f){var h=S();try{V(a)(b,c,e,f)}catch(k){U(h);if(k!==k+0)throw k;Z(1,0)}}function Ic(a,b,c,e,f,h,k,l){var u=S();try{V(a)(b,c,e,f,h,k,l)}catch(t){U(u);if(t!==t+0)throw t;Z(1,0)}}function kc(a,b,c){var e=S();try{return V(a)(b,c)}catch(f){U(e);if(f!==f+0)throw f;Z(1,0)}}function jc(a,b,c){var e=S();try{return V(a)(b,c)}catch(f){U(e);if(f!==f+0)throw f;Z(1,0)}}\r\nfunction Jc(a,b,c,e,f,h,k,l,u){var t=S();try{V(a)(b,c,e,f,h,k,l,u)}catch(A){U(t);if(A!==A+0)throw A;Z(1,0)}}function Hc(a,b,c,e,f,h,k){var l=S();try{V(a)(b,c,e,f,h,k)}catch(u){U(l);if(u!==u+0)throw u;Z(1,0)}}function oc(a,b,c,e,f,h){var k=S();try{return V(a)(b,c,e,f,h)}catch(l){U(k);if(l!==l+0)throw l;Z(1,0)}}function rc(a,b,c,e,f,h,k,l){var u=S();try{return V(a)(b,c,e,f,h,k,l)}catch(t){U(u);if(t!==t+0)throw t;Z(1,0)}}\r\nfunction sc(a,b,c,e,f,h,k,l,u,t,A,K){var J=S();try{return V(a)(b,c,e,f,h,k,l,u,t,A,K)}catch(g){U(J);if(g!==g+0)throw g;Z(1,0)}}function Kc(a,b,c,e,f,h,k,l,u,t,A){var K=S();try{V(a)(b,c,e,f,h,k,l,u,t,A)}catch(J){U(K);if(J!==J+0)throw J;Z(1,0)}}function Lc(a,b,c,e,f,h,k,l,u,t,A,K,J,g,w,z){var N=S();try{V(a)(b,c,e,f,h,k,l,u,t,A,K,J,g,w,z)}catch(T){U(N);if(T!==T+0)throw T;Z(1,0)}}function hc(a){var b=S();try{return V(a)()}catch(c){U(b);if(c!==c+0)throw c;Z(1,0)}}\r\nfunction gc(a,b,c){var e=S();try{return V(a)(b,c)}catch(f){U(e);if(f!==f+0)throw f;Z(1,0)}}function fc(a,b,c){var e=S();try{return V(a)(b,c)}catch(f){U(e);if(f!==f+0)throw f;Z(1,0)}}function Dc(a,b,c,e){var f=S();try{V(a)(b,c,e)}catch(h){U(f);if(h!==h+0)throw h;Z(1,0)}}function Mc(a,b,c,e,f,h,k,l){var u=S();try{Tc(a,b,c,e,f,h,k,l)}catch(t){U(u);if(t!==t+0)throw t;Z(1,0)}}function Oc(a,b,c,e,f,h){var k=S();try{Uc(a,b,c,e,f,h)}catch(l){U(k);if(l!==l+0)throw l;Z(1,0)}}\r\nfunction Nc(a,b,c,e,f,h,k,l,u,t,A,K){var J=S();try{Vc(a,b,c,e,f,h,k,l,u,t,A,K)}catch(g){U(J);if(g!==g+0)throw g;Z(1,0)}}function wc(a,b,c,e){var f=S();try{return Wc(a,b,c,e)}catch(h){U(f);if(h!==h+0)throw h;Z(1,0)}}function yc(a,b){var c=S();try{return Xc(a,b)}catch(e){U(c);if(e!==e+0)throw e;Z(1,0)}}function tc(a,b,c,e,f,h,k,l){var u=S();try{return Yc(a,b,c,e,f,h,k,l)}catch(t){U(u);if(t!==t+0)throw t;Z(1,0)}}function xc(a){var b=S();try{return Qc(a)}catch(c){U(b);if(c!==c+0)throw c;Z(1,0)}}\r\nfunction uc(a,b,c,e,f,h,k){var l=S();try{return Rc(a,b,c,e,f,h,k)}catch(u){U(l);if(u!==u+0)throw u;Z(1,0)}}function vc(a,b,c,e,f){var h=S();try{return Zc(a,b,c,e,f)}catch(k){U(h);if(k!==k+0)throw k;Z(1,0)}}function zc(a,b,c){var e=S();try{return Sc(a,b,c)}catch(f){U(e);if(f!==f+0)throw f;Z(1,0)}}x.UTF8ToString=Aa;x.stringToUTF8=function(a,b,c){return Ba(a,q(),b,c)};x.lengthBytesUTF8=Ca;x.keepRuntimeAlive=F;x.wasmMemory=m;x.stackSave=S;x.stackRestore=U;x.stackAlloc=Kb;x.ExitStatus=E;x.PThread=P;var $c;\r\nM=function ad(){$c||bd();$c||(M=ad)};\r\nfunction bd(){function a(){if(!$c&&($c=!0,x.calledRun=!0,!xa)){C||R(Ga);ha(x);if(x.onRuntimeInitialized)x.onRuntimeInitialized();if(!C){if(x.postRun)for(\"function\"==typeof x.postRun&&(x.postRun=[x.postRun]);x.postRun.length;){var b=x.postRun.shift();Ia.unshift(b)}R(Ia)}}}if(!(0<L))if(C)ha(x),C||R(Ga),postMessage({cmd:\"loaded\"});else{if(x.preRun)for(\"function\"==typeof x.preRun&&(x.preRun=[x.preRun]);x.preRun.length;)Ka();R(Fa);0<L||(x.setStatus?(x.setStatus(\"Running...\"),setTimeout(function(){setTimeout(function(){x.setStatus(\"\")},\r\n1);a()},1)):a())}}if(x.preInit)for(\"function\"==typeof x.preInit&&(x.preInit=[x.preInit]);0<x.preInit.length;)x.preInit.pop()();bd();\r\n\r\n\r\n return ortWasmThreaded.ready\r\n}\r\n);\r\n})();\r\nif (true)\r\n module.exports = ortWasmThreaded;\r\nelse {}\r\n\n\n/***/ }),\n\n/***/ \"./lib/wasm/binding/ort-wasm.js\":\n/*!**************************************!*\\\n !*** ./lib/wasm/binding/ort-wasm.js ***!\n \\**************************************/\n/***/ ((module, __unused_webpack_exports, __webpack_require__) => {\n\nvar __filename = \"/index.js\";\nvar __dirname = \"/\";\n\r\nvar ortWasm = (() => {\r\n var _scriptDir = typeof document !== 'undefined' && document.currentScript ? document.currentScript.src : undefined;\r\n if (true) _scriptDir = _scriptDir || __filename;\r\n return (\r\nfunction(ortWasm) {\r\n ortWasm = ortWasm || {};\r\n\r\n\r\nvar d;d||(d=typeof ortWasm !== 'undefined' ? ortWasm : {});var aa,ba;d.ready=new Promise(function(a,b){aa=a;ba=b});var ca=Object.assign({},d),da=\"./this.program\",ea=(a,b)=>{throw b;},fa=\"object\"==typeof window,m=\"function\"==typeof importScripts,p=\"object\"==typeof process&&\"object\"==typeof process.versions&&\"string\"==typeof process.versions.node,q=\"\",ha,r,v,fs,y,ia;\r\nif(p)q=m?(__webpack_require__(/*! path */ \"?75c6\").dirname)(q)+\"/\":__dirname+\"/\",ia=()=>{y||(fs=__webpack_require__(/*! fs */ \"?63c8\"),y=__webpack_require__(/*! path */ \"?75c6\"))},ha=function(a,b){ia();a=y.normalize(a);return fs.readFileSync(a,b?void 0:\"utf8\")},v=a=>{a=ha(a,!0);a.buffer||(a=new Uint8Array(a));return a},r=(a,b,c)=>{ia();a=y.normalize(a);fs.readFile(a,function(e,f){e?c(e):b(f.buffer)})},1<process.argv.length&&(da=process.argv[1].replace(/\\\\/g,\"/\")),process.argv.slice(2),process.on(\"uncaughtException\",function(a){if(!(a instanceof ja))throw a;}),process.on(\"unhandledRejection\",\r\nfunction(a){throw a;}),ea=(a,b)=>{if(noExitRuntime||0<ka)throw process.exitCode=a,b;b instanceof ja||z(\"exiting due to exception: \"+b);process.exit(a)},d.inspect=function(){return\"[Emscripten Module object]\"};else if(fa||m)m?q=self.location.href:\"undefined\"!=typeof document&&document.currentScript&&(q=document.currentScript.src),_scriptDir&&(q=_scriptDir),0!==q.indexOf(\"blob:\")?q=q.substr(0,q.replace(/[?#].*/,\"\").lastIndexOf(\"/\")+1):q=\"\",ha=a=>{var b=new XMLHttpRequest;b.open(\"GET\",a,!1);b.send(null);\r\nreturn b.responseText},m&&(v=a=>{var b=new XMLHttpRequest;b.open(\"GET\",a,!1);b.responseType=\"arraybuffer\";b.send(null);return new Uint8Array(b.response)}),r=(a,b,c)=>{var e=new XMLHttpRequest;e.open(\"GET\",a,!0);e.responseType=\"arraybuffer\";e.onload=()=>{200==e.status||0==e.status&&e.response?b(e.response):c()};e.onerror=c;e.send(null)};var la=d.print||console.log.bind(console),z=d.printErr||console.warn.bind(console);Object.assign(d,ca);ca=null;d.thisProgram&&(da=d.thisProgram);d.quit&&(ea=d.quit);\r\nvar A;d.wasmBinary&&(A=d.wasmBinary);var noExitRuntime=d.noExitRuntime||!1;\"object\"!=typeof WebAssembly&&B(\"no native wasm support detected\");var ma,D=!1,na=\"undefined\"!=typeof TextDecoder?new TextDecoder(\"utf8\"):void 0;\r\nfunction oa(a,b,c){b>>>=0;var e=b+c;for(c=b;a[c]&&!(c>=e);)++c;if(16<c-b&&a.buffer&&na)return na.decode(a.subarray(b,c));for(e=\"\";b<c;){var f=a[b++];if(f&128){var h=a[b++]&63;if(192==(f&224))e+=String.fromCharCode((f&31)<<6|h);else{var k=a[b++]&63;f=224==(f&240)?(f&15)<<12|h<<6|k:(f&7)<<18|h<<12|k<<6|a[b++]&63;65536>f?e+=String.fromCharCode(f):(f-=65536,e+=String.fromCharCode(55296|f>>10,56320|f&1023))}}else e+=String.fromCharCode(f)}return e}function pa(a,b){return(a>>>=0)?oa(G,a,b):\"\"}\r\nfunction qa(a,b,c,e){c>>>=0;if(!(0<e))return 0;var f=c;e=c+e-1;for(var h=0;h<a.length;++h){var k=a.charCodeAt(h);if(55296<=k&&57343>=k){var l=a.charCodeAt(++h);k=65536+((k&1023)<<10)|l&1023}if(127>=k){if(c>=e)break;b[c++>>>0]=k}else{if(2047>=k){if(c+1>=e)break;b[c++>>>0]=192|k>>6}else{if(65535>=k){if(c+2>=e)break;b[c++>>>0]=224|k>>12}else{if(c+3>=e)break;b[c++>>>0]=240|k>>18;b[c++>>>0]=128|k>>12&63}b[c++>>>0]=128|k>>6&63}b[c++>>>0]=128|k&63}}b[c>>>0]=0;return c-f}\r\nfunction ra(a){for(var b=0,c=0;c<a.length;++c){var e=a.charCodeAt(c);127>=e?b++:2047>=e?b+=2:55296<=e&&57343>=e?(b+=4,++c):b+=3}return b}var sa,H,G,I,J;function ta(){var a=ma.buffer;sa=a;d.HEAP8=H=new Int8Array(a);d.HEAP16=new Int16Array(a);d.HEAP32=I=new Int32Array(a);d.HEAPU8=G=new Uint8Array(a);d.HEAPU16=new Uint16Array(a);d.HEAPU32=J=new Uint32Array(a);d.HEAPF32=new Float32Array(a);d.HEAPF64=new Float64Array(a)}var ua,va=[],wa=[],xa=[],ya=[],ka=0;\r\nfunction za(){var a=d.preRun.shift();va.unshift(a)}var K=0,Aa=null,L=null;function B(a){if(d.onAbort)d.onAbort(a);a=\"Aborted(\"+a+\")\";z(a);D=!0;a=new WebAssembly.RuntimeError(a+\". Build with -sASSERTIONS for more info.\");ba(a);throw a;}function Ba(){return N.startsWith(\"data:application/octet-stream;base64,\")}var N;N=\"ort-wasm.wasm\";if(!Ba()){var Ca=N;N=d.locateFile?d.locateFile(Ca,q):q+Ca}\r\nfunction Da(){var a=N;try{if(a==N&&A)return new Uint8Array(A);if(v)return v(a);throw\"both async and sync fetching of the wasm failed\";}catch(b){B(b)}}\r\nfunction Ea(){if(!A&&(fa||m)){if(\"function\"==typeof fetch&&!N.startsWith(\"file://\"))return fetch(N,{credentials:\"same-origin\"}).then(function(a){if(!a.ok)throw\"failed to load wasm binary file at '\"+N+\"'\";return a.arrayBuffer()}).catch(function(){return Da()});if(r)return new Promise(function(a,b){r(N,function(c){a(new Uint8Array(c))},b)})}return Promise.resolve().then(function(){return Da()})}function ja(a){this.name=\"ExitStatus\";this.message=\"Program terminated with exit(\"+a+\")\";this.status=a}\r\nfunction O(a){for(;0<a.length;)a.shift()(d)}var P=[],Q=0,R=0;\r\nfunction S(a){this.Db=a;this.zb=a-24;this.Ub=function(b){J[this.zb+4>>2>>>0]=b};this.Eb=function(){return J[this.zb+4>>2>>>0]};this.Sb=function(b){J[this.zb+8>>2>>>0]=b};this.Wb=function(){return J[this.zb+8>>2>>>0]};this.Tb=function(){I[this.zb>>2>>>0]=0};this.Ib=function(b){H[this.zb+12>>0>>>0]=b?1:0};this.Pb=function(){return 0!=H[this.zb+12>>0>>>0]};this.Jb=function(b){H[this.zb+13>>0>>>0]=b?1:0};this.Lb=function(){return 0!=H[this.zb+13>>0>>>0]};this.Rb=function(b,c){this.Fb(0);this.Ub(b);this.Sb(c);\r\nthis.Tb();this.Ib(!1);this.Jb(!1)};this.Nb=function(){I[this.zb>>2>>>0]+=1};this.Xb=function(){var b=I[this.zb>>2>>>0];I[this.zb>>2>>>0]=b-1;return 1===b};this.Fb=function(b){J[this.zb+16>>2>>>0]=b};this.Ob=function(){return J[this.zb+16>>2>>>0]};this.Qb=function(){if(Fa(this.Eb()))return J[this.Db>>2>>>0];var b=this.Ob();return 0!==b?b:this.Db}}function Ga(a){return Ha((new S(a)).zb)}var T=[];function U(a){var b=T[a];b||(a>=T.length&&(T.length=a+1),T[a]=b=ua.get(a));return b}\r\nfunction Ia(a){var b=ra(a)+1,c=Ja(b);c&&qa(a,H,c,b);return c}function Ka(a,b,c){function e(n){return(n=n.toTimeString().match(/\\(([A-Za-z ]+)\\)$/))?n[1]:\"GMT\"}var f=(new Date).getFullYear(),h=new Date(f,0,1),k=new Date(f,6,1);f=h.getTimezoneOffset();var l=k.getTimezoneOffset();I[a>>2>>>0]=60*Math.max(f,l);I[b>>2>>>0]=Number(f!=l);a=e(h);b=e(k);a=Ia(a);b=Ia(b);l<f?(J[c>>2>>>0]=a,J[c+4>>2>>>0]=b):(J[c>>2>>>0]=b,J[c+4>>2>>>0]=a)}function La(a,b,c){La.Vb||(La.Vb=!0,Ka(a,b,c))}var Ma={};\r\nfunction Na(){if(!Oa){var a={USER:\"web_user\",LOGNAME:\"web_user\",PATH:\"/\",PWD:\"/\",HOME:\"/home/web_user\",LANG:(\"object\"==typeof navigator&&navigator.languages&&navigator.languages[0]||\"C\").replace(\"-\",\"_\")+\".UTF-8\",_:da||\"./this.program\"},b;for(b in Ma)void 0===Ma[b]?delete a[b]:a[b]=Ma[b];var c=[];for(b in a)c.push(b+\"=\"+a[b]);Oa=c}return Oa}var Oa,Pa=[null,[],[]];function Qa(a,b){var c=Pa[a];0===b||10===b?((1===a?la:z)(oa(c,0)),c.length=0):c.push(b)}var V=0;\r\nfunction Ra(){if(\"object\"==typeof crypto&&\"function\"==typeof crypto.getRandomValues){var a=new Uint8Array(1);return()=>{crypto.getRandomValues(a);return a[0]}}if(p)try{var b=__webpack_require__(Object(function webpackMissingModule() { var e = new Error(\"Cannot find module 'crypto'\"); e.code = 'MODULE_NOT_FOUND'; throw e; }()));return()=>b.randomBytes(1)[0]}catch(c){}return()=>B(\"randomDevice\")}function W(a,b){W.Mb||(W.Mb=Ra());for(var c=0;c<b;c++)H[a+c>>0>>>0]=W.Mb();return 0}function Sa(a){return 0===a%4&&(0!==a%100||0===a%400)}var Ta=[31,29,31,30,31,30,31,31,30,31,30,31],Ua=[31,28,31,30,31,30,31,31,30,31,30,31];\r\nfunction Va(a){var b=Array(ra(a)+1);qa(a,b,0,b.length);return b}\r\nfunction Wa(a,b,c,e){function f(g,u,w){for(g=\"number\"==typeof g?g.toString():g||\"\";g.length<u;)g=w[0]+g;return g}function h(g,u){return f(g,u,\"0\")}function k(g,u){function w(M){return 0>M?-1:0<M?1:0}var F;0===(F=w(g.getFullYear()-u.getFullYear()))&&0===(F=w(g.getMonth()-u.getMonth()))&&(F=w(g.getDate()-u.getDate()));return F}function l(g){switch(g.getDay()){case 0:return new Date(g.getFullYear()-1,11,29);case 1:return g;case 2:return new Date(g.getFullYear(),0,3);case 3:return new Date(g.getFullYear(),\r\n0,2);case 4:return new Date(g.getFullYear(),0,1);case 5:return new Date(g.getFullYear()-1,11,31);case 6:return new Date(g.getFullYear()-1,11,30)}}function n(g){var u=g.Bb;for(g=new Date((new Date(g.Cb+1900,0,1)).getTime());0<u;){var w=g.getMonth(),F=(Sa(g.getFullYear())?Ta:Ua)[w];if(u>F-g.getDate())u-=F-g.getDate()+1,g.setDate(1),11>w?g.setMonth(w+1):(g.setMonth(0),g.setFullYear(g.getFullYear()+1));else{g.setDate(g.getDate()+u);break}}w=new Date(g.getFullYear()+1,0,4);u=l(new Date(g.getFullYear(),\r\n0,4));w=l(w);return 0>=k(u,g)?0>=k(w,g)?g.getFullYear()+1:g.getFullYear():g.getFullYear()-1}var t=I[e+40>>2>>>0];e={$b:I[e>>2>>>0],Zb:I[e+4>>2>>>0],Gb:I[e+8>>2>>>0],Kb:I[e+12>>2>>>0],Hb:I[e+16>>2>>>0],Cb:I[e+20>>2>>>0],Ab:I[e+24>>2>>>0],Bb:I[e+28>>2>>>0],bc:I[e+32>>2>>>0],Yb:I[e+36>>2>>>0],ac:t?pa(t):\"\"};c=pa(c);t={\"%c\":\"%a %b %d %H:%M:%S %Y\",\"%D\":\"%m/%d/%y\",\"%F\":\"%Y-%m-%d\",\"%h\":\"%b\",\"%r\":\"%I:%M:%S %p\",\"%R\":\"%H:%M\",\"%T\":\"%H:%M:%S\",\"%x\":\"%m/%d/%y\",\"%X\":\"%H:%M:%S\",\"%Ec\":\"%c\",\"%EC\":\"%C\",\"%Ex\":\"%m/%d/%y\",\r\n\"%EX\":\"%H:%M:%S\",\"%Ey\":\"%y\",\"%EY\":\"%Y\",\"%Od\":\"%d\",\"%Oe\":\"%e\",\"%OH\":\"%H\",\"%OI\":\"%I\",\"%Om\":\"%m\",\"%OM\":\"%M\",\"%OS\":\"%S\",\"%Ou\":\"%u\",\"%OU\":\"%U\",\"%OV\":\"%V\",\"%Ow\":\"%w\",\"%OW\":\"%W\",\"%Oy\":\"%y\"};for(var x in t)c=c.replace(new RegExp(x,\"g\"),t[x]);var E=\"Sunday Monday Tuesday Wednesday Thursday Friday Saturday\".split(\" \"),C=\"January February March April May June July August September October November December\".split(\" \");t={\"%a\":function(g){return E[g.Ab].substring(0,3)},\"%A\":function(g){return E[g.Ab]},\"%b\":function(g){return C[g.Hb].substring(0,\r\n3)},\"%B\":function(g){return C[g.Hb]},\"%C\":function(g){return h((g.Cb+1900)/100|0,2)},\"%d\":function(g){return h(g.Kb,2)},\"%e\":function(g){return f(g.Kb,2,\" \")},\"%g\":function(g){return n(g).toString().substring(2)},\"%G\":function(g){return n(g)},\"%H\":function(g){return h(g.Gb,2)},\"%I\":function(g){g=g.Gb;0==g?g=12:12<g&&(g-=12);return h(g,2)},\"%j\":function(g){for(var u=0,w=0;w<=g.Hb-1;u+=(Sa(g.Cb+1900)?Ta:Ua)[w++]);return h(g.Kb+u,3)},\"%m\":function(g){return h(g.Hb+1,2)},\"%M\":function(g){return h(g.Zb,\r\n2)},\"%n\":function(){return\"\\n\"},\"%p\":function(g){return 0<=g.Gb&&12>g.Gb?\"AM\":\"PM\"},\"%S\":function(g){return h(g.$b,2)},\"%t\":function(){return\"\\t\"},\"%u\":function(g){return g.Ab||7},\"%U\":function(g){return h(Math.floor((g.Bb+7-g.Ab)/7),2)},\"%V\":function(g){var u=Math.floor((g.Bb+7-(g.Ab+6)%7)/7);2>=(g.Ab+371-g.Bb-2)%7&&u++;if(u)53==u&&(w=(g.Ab+371-g.Bb)%7,4==w||3==w&&Sa(g.Cb)||(u=1));else{u=52;var w=(g.Ab+7-g.Bb-1)%7;(4==w||5==w&&Sa(g.Cb%400-1))&&u++}return h(u,2)},\"%w\":function(g){return g.Ab},\"%W\":function(g){return h(Math.floor((g.Bb+\r\n7-(g.Ab+6)%7)/7),2)},\"%y\":function(g){return(g.Cb+1900).toString().substring(2)},\"%Y\":function(g){return g.Cb+1900},\"%z\":function(g){g=g.Yb;var u=0<=g;g=Math.abs(g)/60;return(u?\"+\":\"-\")+String(\"0000\"+(g/60*100+g%60)).slice(-4)},\"%Z\":function(g){return g.ac},\"%%\":function(){return\"%\"}};c=c.replace(/%%/g,\"\\x00\\x00\");for(x in t)c.includes(x)&&(c=c.replace(new RegExp(x,\"g\"),t[x](e)));c=c.replace(/\\0\\0/g,\"%\");x=Va(c);if(x.length>b)return 0;H.set(x,a>>>0);return x.length-1}\r\nvar Jb={a:function(a){return Ja(a+24)+24},m:function(a){a=new S(a);a.Pb()||(a.Ib(!0),Q--);a.Jb(!1);P.push(a);a.Nb();return a.Qb()},ia:function(a){z(\"Unexpected exception thrown, this is not properly supported - aborting\");D=!0;throw a;},w:function(){X(0);var a=P.pop();if(a.Xb()&&!a.Lb()){var b=a.Wb();b&&U(b)(a.Db);Ga(a.Db)}R=0},d:function(){var a=R;if(!a)return V=0;var b=new S(a);b.Fb(a);var c=b.Eb();if(!c)return V=0,a;for(var e=Array.prototype.slice.call(arguments),f=0;f<e.length;f++){var h=e[f];\r\nif(0===h||h===c)break;if(Xa(h,c,b.zb+16))return V=h,a}V=c;return a},k:function(){var a=R;if(!a)return V=0;var b=new S(a);b.Fb(a);var c=b.Eb();if(!c)return V=0,a;for(var e=Array.prototype.slice.call(arguments),f=0;f<e.length;f++){var h=e[f];if(0===h||h===c)break;if(Xa(h,c,b.zb+16))return V=h,a}V=c;return a},g:function(){var a=R;if(!a)return V=0;var b=new S(a);b.Fb(a);var c=b.Eb();if(!c)return V=0,a;for(var e=Array.prototype.slice.call(arguments),f=0;f<e.length;f++){var h=e[f];if(0===h||h===c)break;\r\nif(Xa(h,c,b.zb+16))return V=h,a}V=c;return a},s:Ga,L:function(){var a=P.pop();a||B(\"no exception to throw\");var b=a.Db;a.Lb()||(P.push(a),a.Jb(!0),a.Ib(!1),Q++);R=b;throw b;},b:function(a,b,c){(new S(a)).Rb(b,c);R=a;Q++;throw a;},la:function(){return Q},i:function(a){R||(R=a);throw a;},H:function(){return 0},Ba:function(){},pa:function(){},ra:function(){},ka:function(){return 0},za:function(){},ua:function(){},ya:function(){},R:function(){},qa:function(){},na:function(){},Aa:function(){},oa:function(){},\r\nHa:function(){},Ja:function(){B(\"To use dlopen, you need enable dynamic linking, see https://github.com/emscripten-core/emscripten/wiki/Linking\")},Ia:function(){B(\"To use dlopen, you need enable dynamic linking, see https://github.com/emscripten-core/emscripten/wiki/Linking\")},S:function(){return Date.now()},Ca:function(){return!0},Da:function(a,b){a=new Date(1E3*(J[a>>>2]+4294967296*I[a+4>>>2]));I[b>>2>>>0]=a.getUTCSeconds();I[b+4>>2>>>0]=a.getUTCMinutes();I[b+8>>2>>>0]=a.getUTCHours();I[b+12>>2>>>\r\n0]=a.getUTCDate();I[b+16>>2>>>0]=a.getUTCMonth();I[b+20>>2>>>0]=a.getUTCFullYear()-1900;I[b+24>>2>>>0]=a.getUTCDay();I[b+28>>2>>>0]=(a.getTime()-Date.UTC(a.getUTCFullYear(),0,1,0,0,0,0))/864E5|0},Ea:function(a,b){a=new Date(1E3*(J[a>>>2]+4294967296*I[a+4>>>2]));I[b>>2>>>0]=a.getSeconds();I[b+4>>2>>>0]=a.getMinutes();I[b+8>>2>>>0]=a.getHours();I[b+12>>2>>>0]=a.getDate();I[b+16>>2>>>0]=a.getMonth();I[b+20>>2>>>0]=a.getFullYear()-1900;I[b+24>>2>>>0]=a.getDay();var c=new Date(a.getFullYear(),0,1);I[b+\r\n28>>2>>>0]=(a.getTime()-c.getTime())/864E5|0;I[b+36>>2>>>0]=-(60*a.getTimezoneOffset());var e=(new Date(a.getFullYear(),6,1)).getTimezoneOffset();c=c.getTimezoneOffset();I[b+32>>2>>>0]=(e!=c&&a.getTimezoneOffset()==Math.min(c,e))|0},Fa:function(a){var b=new Date(I[a+20>>2>>>0]+1900,I[a+16>>2>>>0],I[a+12>>2>>>0],I[a+8>>2>>>0],I[a+4>>2>>>0],I[a>>2>>>0],0),c=I[a+32>>2>>>0],e=b.getTimezoneOffset(),f=new Date(b.getFullYear(),0,1),h=(new Date(b.getFullYear(),6,1)).getTimezoneOffset(),k=f.getTimezoneOffset(),\r\nl=Math.min(k,h);0>c?I[a+32>>2>>>0]=Number(h!=k&&l==e):0<c!=(l==e)&&(h=Math.max(k,h),b.setTime(b.getTime()+6E4*((0<c?l:h)-e)));I[a+24>>2>>>0]=b.getDay();I[a+28>>2>>>0]=(b.getTime()-f.getTime())/864E5|0;I[a>>2>>>0]=b.getSeconds();I[a+4>>2>>>0]=b.getMinutes();I[a+8>>2>>>0]=b.getHours();I[a+12>>2>>>0]=b.getDate();I[a+16>>2>>>0]=b.getMonth();return b.getTime()/1E3|0},sa:function(){return-52},ta:function(){},Ga:La,B:function(){B(\"\")},ma:function(){return 4294901760},I:p?()=>{var a=process.hrtime();return 1E3*\r\na[0]+a[1]/1E6}:()=>performance.now(),xa:function(a,b,c){G.copyWithin(a>>>0,b>>>0,b+c>>>0)},G:function(a){var b=G.length;a>>>=0;if(4294901760<a)return!1;for(var c=1;4>=c;c*=2){var e=b*(1+.2/c);e=Math.min(e,a+100663296);var f=Math;e=Math.max(a,e);f=f.min.call(f,4294901760,e+(65536-e%65536)%65536);a:{try{ma.grow(f-sa.byteLength+65535>>>16);ta();var h=1;break a}catch(k){}h=void 0}if(h)return!0}return!1},va:function(a,b){var c=0;Na().forEach(function(e,f){var h=b+c;f=J[a+4*f>>2>>>0]=h;for(h=0;h<e.length;++h)H[f++>>\r\n0>>>0]=e.charCodeAt(h);H[f>>0>>>0]=0;c+=e.length+1});return 0},wa:function(a,b){var c=Na();J[a>>2>>>0]=c.length;var e=0;c.forEach(function(f){e+=f.length+1});J[b>>2>>>0]=e;return 0},ba:function(a){noExitRuntime||0<ka||(Ya(),O(xa),Za(0),Pa[1].length&&Qa(1,10),Pa[2].length&&Qa(2,10));if(!(noExitRuntime||0<ka)){if(d.onExit)d.onExit(a);D=!0}ea(a,new ja(a))},E:function(){return 52},Q:function(){return 52},ca:function(){return 70},P:function(a,b,c,e){for(var f=0,h=0;h<c;h++){var k=J[b>>2>>>0],l=J[b+4>>\r\n2>>>0];b+=8;for(var n=0;n<l;n++)Qa(a,G[k+n>>>0]);f+=l}J[e>>2>>>0]=f;return 0},c:function(){return V},ja:W,ea:$a,fa:ab,J:bb,e:cb,N:db,O:eb,j:fb,o:gb,p:hb,M:ib,r:jb,v:kb,K:lb,D:mb,X:nb,V:ob,U:pb,Z:qb,W:rb,Y:sb,T:tb,f:ub,q:vb,h:wb,da:xb,l:yb,t:zb,u:Ab,x:Bb,z:Cb,ga:Db,A:Eb,C:Fb,aa:Gb,_:Hb,$:Ib,n:function(a){return a},F:function(a){V=a},ha:Wa,y:function(a,b,c,e){return Wa(a,b,c,e)}};\r\n(function(){function a(f){d.asm=f.exports;ma=d.asm.Ka;ta();ua=d.asm.ib;wa.unshift(d.asm.La);K--;d.monitorRunDependencies&&d.monitorRunDependencies(K);0==K&&(null!==Aa&&(clearInterval(Aa),Aa=null),L&&(f=L,L=null,f()))}function b(f){a(f.instance)}function c(f){return Ea().then(function(h){return WebAssembly.instantiate(h,e)}).then(function(h){return h}).then(f,function(h){z(\"failed to asynchronously prepare wasm: \"+h);B(h)})}var e={a:Jb};K++;d.monitorRunDependencies&&d.monitorRunDependencies(K);if(d.instantiateWasm)try{return d.instantiateWasm(e,\r\na)}catch(f){return z(\"Module.instantiateWasm callback failed with error: \"+f),!1}(function(){return A||\"function\"!=typeof WebAssembly.instantiateStreaming||Ba()||N.startsWith(\"file://\")||p||\"function\"!=typeof fetch?c(b):fetch(N,{credentials:\"same-origin\"}).then(function(f){return WebAssembly.instantiateStreaming(f,e).then(b,function(h){z(\"wasm streaming compile failed: \"+h);z(\"falling back to ArrayBuffer instantiation\");return c(b)})})})().catch(ba);return{}})();\r\nd.___wasm_call_ctors=function(){return(d.___wasm_call_ctors=d.asm.La).apply(null,arguments)};d._OrtInit=function(){return(d._OrtInit=d.asm.Ma).apply(null,arguments)};d._OrtCreateSessionOptions=function(){return(d._OrtCreateSessionOptions=d.asm.Na).apply(null,arguments)};d._OrtAppendExecutionProvider=function(){return(d._OrtAppendExecutionProvider=d.asm.Oa).apply(null,arguments)};d._OrtAddSessionConfigEntry=function(){return(d._OrtAddSessionConfigEntry=d.asm.Pa).apply(null,arguments)};\r\nd._OrtReleaseSessionOptions=function(){return(d._OrtReleaseSessionOptions=d.asm.Qa).apply(null,arguments)};d._OrtCreateSession=function(){return(d._OrtCreateSession=d.asm.Ra).apply(null,arguments)};d._OrtReleaseSession=function(){return(d._OrtReleaseSession=d.asm.Sa).apply(null,arguments)};d._OrtGetInputCount=function(){return(d._OrtGetInputCount=d.asm.Ta).apply(null,arguments)};d._OrtGetOutputCount=function(){return(d._OrtGetOutputCount=d.asm.Ua).apply(null,arguments)};\r\nd._OrtGetInputName=function(){return(d._OrtGetInputName=d.asm.Va).apply(null,arguments)};d._OrtGetOutputName=function(){return(d._OrtGetOutputName=d.asm.Wa).apply(null,arguments)};d._OrtFree=function(){return(d._OrtFree=d.asm.Xa).apply(null,arguments)};d._OrtCreateTensor=function(){return(d._OrtCreateTensor=d.asm.Ya).apply(null,arguments)};d._OrtGetTensorData=function(){return(d._OrtGetTensorData=d.asm.Za).apply(null,arguments)};\r\nd._OrtReleaseTensor=function(){return(d._OrtReleaseTensor=d.asm._a).apply(null,arguments)};d._OrtCreateRunOptions=function(){return(d._OrtCreateRunOptions=d.asm.$a).apply(null,arguments)};d._OrtAddRunConfigEntry=function(){return(d._OrtAddRunConfigEntry=d.asm.ab).apply(null,arguments)};d._OrtReleaseRunOptions=function(){return(d._OrtReleaseRunOptions=d.asm.bb).apply(null,arguments)};d._OrtRun=function(){return(d._OrtRun=d.asm.cb).apply(null,arguments)};\r\nd._OrtEndProfiling=function(){return(d._OrtEndProfiling=d.asm.db).apply(null,arguments)};\r\nvar Ja=d._malloc=function(){return(Ja=d._malloc=d.asm.eb).apply(null,arguments)},Ha=d._free=function(){return(Ha=d._free=d.asm.fb).apply(null,arguments)},Za=d._fflush=function(){return(Za=d._fflush=d.asm.gb).apply(null,arguments)},Ya=d.___funcs_on_exit=function(){return(Ya=d.___funcs_on_exit=d.asm.hb).apply(null,arguments)},X=d._setThrew=function(){return(X=d._setThrew=d.asm.jb).apply(null,arguments)},Y=d.stackSave=function(){return(Y=d.stackSave=d.asm.kb).apply(null,arguments)},Z=d.stackRestore=\r\nfunction(){return(Z=d.stackRestore=d.asm.lb).apply(null,arguments)},Kb=d.stackAlloc=function(){return(Kb=d.stackAlloc=d.asm.mb).apply(null,arguments)},Xa=d.___cxa_can_catch=function(){return(Xa=d.___cxa_can_catch=d.asm.nb).apply(null,arguments)},Fa=d.___cxa_is_pointer_type=function(){return(Fa=d.___cxa_is_pointer_type=d.asm.ob).apply(null,arguments)},Lb=d.dynCall_j=function(){return(Lb=d.dynCall_j=d.asm.pb).apply(null,arguments)},Mb=d.dynCall_iiiiij=function(){return(Mb=d.dynCall_iiiiij=d.asm.qb).apply(null,\r\narguments)},Nb=d.dynCall_jii=function(){return(Nb=d.dynCall_jii=d.asm.rb).apply(null,arguments)},Ob=d.dynCall_viiiiij=function(){return(Ob=d.dynCall_viiiiij=d.asm.sb).apply(null,arguments)},Pb=d.dynCall_vjji=function(){return(Pb=d.dynCall_vjji=d.asm.tb).apply(null,arguments)},Qb=d.dynCall_viiijjjii=function(){return(Qb=d.dynCall_viiijjjii=d.asm.ub).apply(null,arguments)},Rb=d.dynCall_iij=function(){return(Rb=d.dynCall_iij=d.asm.vb).apply(null,arguments)},Sb=d.dynCall_ji=function(){return(Sb=d.dynCall_ji=\r\nd.asm.wb).apply(null,arguments)},Tb=d.dynCall_iiiiiij=function(){return(Tb=d.dynCall_iiiiiij=d.asm.xb).apply(null,arguments)},Ub=d.dynCall_iiij=function(){return(Ub=d.dynCall_iiij=d.asm.yb).apply(null,arguments)};function cb(a,b){var c=Y();try{return U(a)(b)}catch(e){Z(c);if(e!==e+0)throw e;X(1,0)}}function vb(a,b){var c=Y();try{U(a)(b)}catch(e){Z(c);if(e!==e+0)throw e;X(1,0)}}function wb(a,b,c){var e=Y();try{U(a)(b,c)}catch(f){Z(e);if(f!==f+0)throw f;X(1,0)}}\r\nfunction fb(a,b,c){var e=Y();try{return U(a)(b,c)}catch(f){Z(e);if(f!==f+0)throw f;X(1,0)}}function gb(a,b,c,e){var f=Y();try{return U(a)(b,c,e)}catch(h){Z(f);if(h!==h+0)throw h;X(1,0)}}function kb(a,b,c,e,f,h,k){var l=Y();try{return U(a)(b,c,e,f,h,k)}catch(n){Z(l);if(n!==n+0)throw n;X(1,0)}}function ub(a){var b=Y();try{U(a)()}catch(c){Z(b);if(c!==c+0)throw c;X(1,0)}}function jb(a,b,c,e,f,h){var k=Y();try{return U(a)(b,c,e,f,h)}catch(l){Z(k);if(l!==l+0)throw l;X(1,0)}}\r\nfunction hb(a,b,c,e,f){var h=Y();try{return U(a)(b,c,e,f)}catch(k){Z(h);if(k!==k+0)throw k;X(1,0)}}function yb(a,b,c,e){var f=Y();try{U(a)(b,c,e)}catch(h){Z(f);if(h!==h+0)throw h;X(1,0)}}function Ab(a,b,c,e,f,h){var k=Y();try{U(a)(b,c,e,f,h)}catch(l){Z(k);if(l!==l+0)throw l;X(1,0)}}function zb(a,b,c,e,f){var h=Y();try{U(a)(b,c,e,f)}catch(k){Z(h);if(k!==k+0)throw k;X(1,0)}}function Bb(a,b,c,e,f,h,k){var l=Y();try{U(a)(b,c,e,f,h,k)}catch(n){Z(l);if(n!==n+0)throw n;X(1,0)}}\r\nfunction Cb(a,b,c,e,f,h,k,l){var n=Y();try{U(a)(b,c,e,f,h,k,l)}catch(t){Z(n);if(t!==t+0)throw t;X(1,0)}}function eb(a,b,c){var e=Y();try{return U(a)(b,c)}catch(f){Z(e);if(f!==f+0)throw f;X(1,0)}}function db(a,b,c){var e=Y();try{return U(a)(b,c)}catch(f){Z(e);if(f!==f+0)throw f;X(1,0)}}function Db(a,b,c,e,f,h,k,l,n){var t=Y();try{U(a)(b,c,e,f,h,k,l,n)}catch(x){Z(t);if(x!==x+0)throw x;X(1,0)}}function ib(a,b,c,e,f,h){var k=Y();try{return U(a)(b,c,e,f,h)}catch(l){Z(k);if(l!==l+0)throw l;X(1,0)}}\r\nfunction lb(a,b,c,e,f,h,k,l){var n=Y();try{return U(a)(b,c,e,f,h,k,l)}catch(t){Z(n);if(t!==t+0)throw t;X(1,0)}}function mb(a,b,c,e,f,h,k,l,n,t,x,E){var C=Y();try{return U(a)(b,c,e,f,h,k,l,n,t,x,E)}catch(g){Z(C);if(g!==g+0)throw g;X(1,0)}}function Eb(a,b,c,e,f,h,k,l,n,t,x){var E=Y();try{U(a)(b,c,e,f,h,k,l,n,t,x)}catch(C){Z(E);if(C!==C+0)throw C;X(1,0)}}function Fb(a,b,c,e,f,h,k,l,n,t,x,E,C,g,u,w){var F=Y();try{U(a)(b,c,e,f,h,k,l,n,t,x,E,C,g,u,w)}catch(M){Z(F);if(M!==M+0)throw M;X(1,0)}}\r\nfunction bb(a){var b=Y();try{return U(a)()}catch(c){Z(b);if(c!==c+0)throw c;X(1,0)}}function ab(a,b,c){var e=Y();try{return U(a)(b,c)}catch(f){Z(e);if(f!==f+0)throw f;X(1,0)}}function $a(a,b,c){var e=Y();try{return U(a)(b,c)}catch(f){Z(e);if(f!==f+0)throw f;X(1,0)}}function xb(a,b,c,e){var f=Y();try{U(a)(b,c,e)}catch(h){Z(f);if(h!==h+0)throw h;X(1,0)}}function Gb(a,b,c,e,f,h,k,l){var n=Y();try{Ob(a,b,c,e,f,h,k,l)}catch(t){Z(n);if(t!==t+0)throw t;X(1,0)}}\r\nfunction Ib(a,b,c,e,f,h){var k=Y();try{Pb(a,b,c,e,f,h)}catch(l){Z(k);if(l!==l+0)throw l;X(1,0)}}function Hb(a,b,c,e,f,h,k,l,n,t,x,E){var C=Y();try{Qb(a,b,c,e,f,h,k,l,n,t,x,E)}catch(g){Z(C);if(g!==g+0)throw g;X(1,0)}}function qb(a,b,c,e){var f=Y();try{return Rb(a,b,c,e)}catch(h){Z(f);if(h!==h+0)throw h;X(1,0)}}function sb(a,b){var c=Y();try{return Sb(a,b)}catch(e){Z(c);if(e!==e+0)throw e;X(1,0)}}\r\nfunction nb(a,b,c,e,f,h,k,l){var n=Y();try{return Tb(a,b,c,e,f,h,k,l)}catch(t){Z(n);if(t!==t+0)throw t;X(1,0)}}function rb(a){var b=Y();try{return Lb(a)}catch(c){Z(b);if(c!==c+0)throw c;X(1,0)}}function ob(a,b,c,e,f,h,k){var l=Y();try{return Mb(a,b,c,e,f,h,k)}catch(n){Z(l);if(n!==n+0)throw n;X(1,0)}}function pb(a,b,c,e,f){var h=Y();try{return Ub(a,b,c,e,f)}catch(k){Z(h);if(k!==k+0)throw k;X(1,0)}}function tb(a,b,c){var e=Y();try{return Nb(a,b,c)}catch(f){Z(e);if(f!==f+0)throw f;X(1,0)}}\r\nd.UTF8ToString=pa;d.stringToUTF8=function(a,b,c){return qa(a,G,b,c)};d.lengthBytesUTF8=ra;d.stackSave=Y;d.stackRestore=Z;d.stackAlloc=Kb;var Vb;L=function Wb(){Vb||Xb();Vb||(L=Wb)};\r\nfunction Xb(){function a(){if(!Vb&&(Vb=!0,d.calledRun=!0,!D)){O(wa);aa(d);if(d.onRuntimeInitialized)d.onRuntimeInitialized();if(d.postRun)for(\"function\"==typeof d.postRun&&(d.postRun=[d.postRun]);d.postRun.length;){var b=d.postRun.shift();ya.unshift(b)}O(ya)}}if(!(0<K)){if(d.preRun)for(\"function\"==typeof d.preRun&&(d.preRun=[d.preRun]);d.preRun.length;)za();O(va);0<K||(d.setStatus?(d.setStatus(\"Running...\"),setTimeout(function(){setTimeout(function(){d.setStatus(\"\")},1);a()},1)):a())}}\r\nif(d.preInit)for(\"function\"==typeof d.preInit&&(d.preInit=[d.preInit]);0<d.preInit.length;)d.preInit.pop()();Xb();\r\n\r\n\r\n return ortWasm.ready\r\n}\r\n);\r\n})();\r\nif (true)\r\n module.exports = ortWasm;\r\nelse {}\r\n\n\n/***/ }),\n\n/***/ \"./lib/wasm/options-utils.ts\":\n/*!***********************************!*\\\n !*** ./lib/wasm/options-utils.ts ***!\n \\***********************************/\n/***/ ((__unused_webpack_module, exports) => {\n\n\"use strict\";\n\n// Copyright (c) Microsoft Corporation. All rights reserved.\n// Licensed under the MIT License.\nObject.defineProperty(exports, \"__esModule\", ({ value: true }));\nexports.iterateExtraOptions = void 0;\nconst iterateExtraOptions = (options, prefix, seen, handler) => {\n if (typeof options == 'object' && options !== null) {\n if (seen.has(options)) {\n throw new Error('Circular reference in options');\n }\n else {\n seen.add(options);\n }\n }\n Object.entries(options).forEach(([key, value]) => {\n const name = (prefix) ? prefix + key : key;\n if (typeof value === 'object') {\n (0, exports.iterateExtraOptions)(value, name + '.', seen, handler);\n }\n else if (typeof value === 'string' || typeof value === 'number') {\n handler(name, value.toString());\n }\n else if (typeof value === 'boolean') {\n handler(name, (value) ? '1' : '0');\n }\n else {\n throw new Error(`Can't handle extra config type: ${typeof value}`);\n }\n });\n};\nexports.iterateExtraOptions = iterateExtraOptions;\n\n\n/***/ }),\n\n/***/ \"./lib/wasm/run-options.ts\":\n/*!*********************************!*\\\n !*** ./lib/wasm/run-options.ts ***!\n \\*********************************/\n/***/ ((__unused_webpack_module, exports, __webpack_require__) => {\n\n\"use strict\";\n\n// Copyright (c) Microsoft Corporation. All rights reserved.\n// Licensed under the MIT License.\nObject.defineProperty(exports, \"__esModule\", ({ value: true }));\nexports.setRunOptions = void 0;\nconst options_utils_1 = __webpack_require__(/*! ./options-utils */ \"./lib/wasm/options-utils.ts\");\nconst string_utils_1 = __webpack_require__(/*! ./string-utils */ \"./lib/wasm/string-utils.ts\");\nconst wasm_factory_1 = __webpack_require__(/*! ./wasm-factory */ \"./lib/wasm/wasm-factory.ts\");\nconst setRunOptions = (options) => {\n const wasm = (0, wasm_factory_1.getInstance)();\n let runOptionsHandle = 0;\n const allocs = [];\n const runOptions = options || {};\n try {\n if ((options === null || options === void 0 ? void 0 : options.logSeverityLevel) === undefined) {\n runOptions.logSeverityLevel = 2; // Default to warning\n }\n else if (typeof options.logSeverityLevel !== 'number' || !Number.isInteger(options.logSeverityLevel) ||\n options.logSeverityLevel < 0 || options.logSeverityLevel > 4) {\n throw new Error(`log serverity level is not valid: ${options.logSeverityLevel}`);\n }\n if ((options === null || options === void 0 ? void 0 : options.logVerbosityLevel) === undefined) {\n runOptions.logVerbosityLevel = 0; // Default to 0\n }\n else if (typeof options.logVerbosityLevel !== 'number' || !Number.isInteger(options.logVerbosityLevel)) {\n throw new Error(`log verbosity level is not valid: ${options.logVerbosityLevel}`);\n }\n if ((options === null || options === void 0 ? void 0 : options.terminate) === undefined) {\n runOptions.terminate = false;\n }\n let tagDataOffset = 0;\n if ((options === null || options === void 0 ? void 0 : options.tag) !== undefined) {\n tagDataOffset = (0, string_utils_1.allocWasmString)(options.tag, allocs);\n }\n runOptionsHandle = wasm._OrtCreateRunOptions(runOptions.logSeverityLevel, runOptions.logVerbosityLevel, !!runOptions.terminate, tagDataOffset);\n if (runOptionsHandle === 0) {\n throw new Error('Can\\'t create run options');\n }\n if ((options === null || options === void 0 ? void 0 : options.extra) !== undefined) {\n (0, options_utils_1.iterateExtraOptions)(options.extra, '', new WeakSet(), (key, value) => {\n const keyDataOffset = (0, string_utils_1.allocWasmString)(key, allocs);\n const valueDataOffset = (0, string_utils_1.allocWasmString)(value, allocs);\n if (wasm._OrtAddRunConfigEntry(runOptionsHandle, keyDataOffset, valueDataOffset) !== 0) {\n throw new Error(`Can't set a run config entry: ${key} - ${value}`);\n }\n });\n }\n return [runOptionsHandle, allocs];\n }\n catch (e) {\n if (runOptionsHandle !== 0) {\n wasm._OrtReleaseRunOptions(runOptionsHandle);\n }\n allocs.forEach(wasm._free);\n throw e;\n }\n};\nexports.setRunOptions = setRunOptions;\n\n\n/***/ }),\n\n/***/ \"./lib/wasm/session-options.ts\":\n/*!*************************************!*\\\n !*** ./lib/wasm/session-options.ts ***!\n \\*************************************/\n/***/ ((__unused_webpack_module, exports, __webpack_require__) => {\n\n\"use strict\";\n\n// Copyright (c) Microsoft Corporation. All rights reserved.\n// Licensed under the MIT License.\nObject.defineProperty(exports, \"__esModule\", ({ value: true }));\nexports.setSessionOptions = void 0;\nconst options_utils_1 = __webpack_require__(/*! ./options-utils */ \"./lib/wasm/options-utils.ts\");\nconst string_utils_1 = __webpack_require__(/*! ./string-utils */ \"./lib/wasm/string-utils.ts\");\nconst wasm_factory_1 = __webpack_require__(/*! ./wasm-factory */ \"./lib/wasm/wasm-factory.ts\");\nconst getGraphOptimzationLevel = (graphOptimizationLevel) => {\n switch (graphOptimizationLevel) {\n case 'disabled':\n return 0;\n case 'basic':\n return 1;\n case 'extended':\n return 2;\n case 'all':\n return 99;\n default:\n throw new Error(`unsupported graph optimization level: ${graphOptimizationLevel}`);\n }\n};\nconst getExecutionMode = (executionMode) => {\n switch (executionMode) {\n case 'sequential':\n return 0;\n case 'parallel':\n return 1;\n default:\n throw new Error(`unsupported execution mode: ${executionMode}`);\n }\n};\nconst appendDefaultOptions = (options) => {\n if (!options.extra) {\n options.extra = {};\n }\n if (!options.extra.session) {\n options.extra.session = {};\n }\n const session = options.extra.session;\n if (!session.use_ort_model_bytes_directly) {\n // eslint-disable-next-line camelcase\n session.use_ort_model_bytes_directly = '1';\n }\n};\nconst setExecutionProviders = (sessionOptionsHandle, executionProviders, allocs) => {\n for (const ep of executionProviders) {\n let epName = typeof ep === 'string' ? ep : ep.name;\n // check EP name\n switch (epName) {\n case 'xnnpack':\n epName = 'XNNPACK';\n break;\n case 'wasm':\n case 'cpu':\n continue;\n default:\n throw new Error(`not supported EP: ${epName}`);\n }\n const epNameDataOffset = (0, string_utils_1.allocWasmString)(epName, allocs);\n if ((0, wasm_factory_1.getInstance)()._OrtAppendExecutionProvider(sessionOptionsHandle, epNameDataOffset) !== 0) {\n throw new Error(`Can't append execution provider: ${epName}`);\n }\n }\n};\nconst setSessionOptions = (options) => {\n const wasm = (0, wasm_factory_1.getInstance)();\n let sessionOptionsHandle = 0;\n const allocs = [];\n const sessionOptions = options || {};\n appendDefaultOptions(sessionOptions);\n try {\n if ((options === null || options === void 0 ? void 0 : options.graphOptimizationLevel) === undefined) {\n sessionOptions.graphOptimizationLevel = 'all';\n }\n const graphOptimizationLevel = getGraphOptimzationLevel(sessionOptions.graphOptimizationLevel);\n if ((options === null || options === void 0 ? void 0 : options.enableCpuMemArena) === undefined) {\n sessionOptions.enableCpuMemArena = true;\n }\n if ((options === null || options === void 0 ? void 0 : options.enableMemPattern) === undefined) {\n sessionOptions.enableMemPattern = true;\n }\n if ((options === null || options === void 0 ? void 0 : options.executionMode) === undefined) {\n sessionOptions.executionMode = 'sequential';\n }\n const executionMode = getExecutionMode(sessionOptions.executionMode);\n let logIdDataOffset = 0;\n if ((options === null || options === void 0 ? void 0 : options.logId) !== undefined) {\n logIdDataOffset = (0, string_utils_1.allocWasmString)(options.logId, allocs);\n }\n if ((options === null || options === void 0 ? void 0 : options.logSeverityLevel) === undefined) {\n sessionOptions.logSeverityLevel = 2; // Default to warning\n }\n else if (typeof options.logSeverityLevel !== 'number' || !Number.isInteger(options.logSeverityLevel) ||\n options.logSeverityLevel < 0 || options.logSeverityLevel > 4) {\n throw new Error(`log serverity level is not valid: ${options.logSeverityLevel}`);\n }\n if ((options === null || options === void 0 ? void 0 : options.logVerbosityLevel) === undefined) {\n sessionOptions.logVerbosityLevel = 0; // Default to 0\n }\n else if (typeof options.logVerbosityLevel !== 'number' || !Number.isInteger(options.logVerbosityLevel)) {\n throw new Error(`log verbosity level is not valid: ${options.logVerbosityLevel}`);\n }\n if ((options === null || options === void 0 ? void 0 : options.enableProfiling) === undefined) {\n sessionOptions.enableProfiling = false;\n }\n sessionOptionsHandle = wasm._OrtCreateSessionOptions(graphOptimizationLevel, !!sessionOptions.enableCpuMemArena, !!sessionOptions.enableMemPattern, executionMode, !!sessionOptions.enableProfiling, 0, logIdDataOffset, sessionOptions.logSeverityLevel, sessionOptions.logVerbosityLevel);\n if (sessionOptionsHandle === 0) {\n throw new Error('Can\\'t create session options');\n }\n if (options === null || options === void 0 ? void 0 : options.executionProviders) {\n setExecutionProviders(sessionOptionsHandle, options.executionProviders, allocs);\n }\n if ((options === null || options === void 0 ? void 0 : options.extra) !== undefined) {\n (0, options_utils_1.iterateExtraOptions)(options.extra, '', new WeakSet(), (key, value) => {\n const keyDataOffset = (0, string_utils_1.allocWasmString)(key, allocs);\n const valueDataOffset = (0, string_utils_1.allocWasmString)(value, allocs);\n if (wasm._OrtAddSessionConfigEntry(sessionOptionsHandle, keyDataOffset, valueDataOffset) !== 0) {\n throw new Error(`Can't set a session config entry: ${key} - ${value}`);\n }\n });\n }\n return [sessionOptionsHandle, allocs];\n }\n catch (e) {\n if (sessionOptionsHandle !== 0) {\n wasm._OrtReleaseSessionOptions(sessionOptionsHandle);\n }\n allocs.forEach(wasm._free);\n throw e;\n }\n};\nexports.setSessionOptions = setSessionOptions;\n\n\n/***/ }),\n\n/***/ \"./lib/wasm/string-utils.ts\":\n/*!**********************************!*\\\n !*** ./lib/wasm/string-utils.ts ***!\n \\**********************************/\n/***/ ((__unused_webpack_module, exports, __webpack_require__) => {\n\n\"use strict\";\n\n// Copyright (c) Microsoft Corporation. All rights reserved.\n// Licensed under the MIT License.\nObject.defineProperty(exports, \"__esModule\", ({ value: true }));\nexports.allocWasmString = void 0;\nconst wasm_factory_1 = __webpack_require__(/*! ./wasm-factory */ \"./lib/wasm/wasm-factory.ts\");\nconst allocWasmString = (data, allocs) => {\n const wasm = (0, wasm_factory_1.getInstance)();\n const dataLength = wasm.lengthBytesUTF8(data) + 1;\n const dataOffset = wasm._malloc(dataLength);\n wasm.stringToUTF8(data, dataOffset, dataLength);\n allocs.push(dataOffset);\n return dataOffset;\n};\nexports.allocWasmString = allocWasmString;\n\n\n/***/ }),\n\n/***/ \"./lib/wasm/wasm-core-impl.ts\":\n/*!************************************!*\\\n !*** ./lib/wasm/wasm-core-impl.ts ***!\n \\************************************/\n/***/ ((__unused_webpack_module, exports, __webpack_require__) => {\n\n\"use strict\";\n\n// Copyright (c) Microsoft Corporation. All rights reserved.\n// Licensed under the MIT License.\nObject.defineProperty(exports, \"__esModule\", ({ value: true }));\nexports.extractTransferableBuffers = exports.endProfiling = exports.run = exports.releaseSession = exports.createSession = exports.createSessionFinalize = exports.createSessionAllocate = exports.initOrt = void 0;\nconst run_options_1 = __webpack_require__(/*! ./run-options */ \"./lib/wasm/run-options.ts\");\nconst session_options_1 = __webpack_require__(/*! ./session-options */ \"./lib/wasm/session-options.ts\");\nconst string_utils_1 = __webpack_require__(/*! ./string-utils */ \"./lib/wasm/string-utils.ts\");\nconst wasm_factory_1 = __webpack_require__(/*! ./wasm-factory */ \"./lib/wasm/wasm-factory.ts\");\n/**\n * initialize ORT environment.\n * @param numThreads SetGlobalIntraOpNumThreads(numThreads)\n * @param loggingLevel CreateEnv(static_cast<OrtLoggingLevel>(logging_level))\n */\nconst initOrt = (numThreads, loggingLevel) => {\n const errorCode = (0, wasm_factory_1.getInstance)()._OrtInit(numThreads, loggingLevel);\n if (errorCode !== 0) {\n throw new Error(`Can't initialize onnxruntime. error code = ${errorCode}`);\n }\n};\nexports.initOrt = initOrt;\nconst activeSessions = new Map();\n/**\n * create an instance of InferenceSession.\n * @returns the metadata of InferenceSession. 0-value handle for failure.\n */\nconst createSessionAllocate = (model) => {\n const wasm = (0, wasm_factory_1.getInstance)();\n const modelDataOffset = wasm._malloc(model.byteLength);\n wasm.HEAPU8.set(model, modelDataOffset);\n return [modelDataOffset, model.byteLength];\n};\nexports.createSessionAllocate = createSessionAllocate;\nconst createSessionFinalize = (modelData, options) => {\n const wasm = (0, wasm_factory_1.getInstance)();\n let sessionHandle = 0;\n let sessionOptionsHandle = 0;\n let allocs = [];\n try {\n [sessionOptionsHandle, allocs] = (0, session_options_1.setSessionOptions)(options);\n sessionHandle = wasm._OrtCreateSession(modelData[0], modelData[1], sessionOptionsHandle);\n if (sessionHandle === 0) {\n throw new Error('Can\\'t create a session');\n }\n }\n finally {\n wasm._free(modelData[0]);\n wasm._OrtReleaseSessionOptions(sessionOptionsHandle);\n allocs.forEach(wasm._free);\n }\n const inputCount = wasm._OrtGetInputCount(sessionHandle);\n const outputCount = wasm._OrtGetOutputCount(sessionHandle);\n const inputNames = [];\n const inputNamesUTF8Encoded = [];\n const outputNames = [];\n const outputNamesUTF8Encoded = [];\n for (let i = 0; i < inputCount; i++) {\n const name = wasm._OrtGetInputName(sessionHandle, i);\n if (name === 0) {\n throw new Error('Can\\'t get an input name');\n }\n inputNamesUTF8Encoded.push(name);\n inputNames.push(wasm.UTF8ToString(name));\n }\n for (let i = 0; i < outputCount; i++) {\n const name = wasm._OrtGetOutputName(sessionHandle, i);\n if (name === 0) {\n throw new Error('Can\\'t get an output name');\n }\n outputNamesUTF8Encoded.push(name);\n outputNames.push(wasm.UTF8ToString(name));\n }\n activeSessions.set(sessionHandle, [sessionHandle, inputNamesUTF8Encoded, outputNamesUTF8Encoded]);\n return [sessionHandle, inputNames, outputNames];\n};\nexports.createSessionFinalize = createSessionFinalize;\n/**\n * create an instance of InferenceSession.\n * @returns the metadata of InferenceSession. 0-value handle for failure.\n */\nconst createSession = (model, options) => {\n const modelData = (0, exports.createSessionAllocate)(model);\n return (0, exports.createSessionFinalize)(modelData, options);\n};\nexports.createSession = createSession;\nconst releaseSession = (sessionId) => {\n const wasm = (0, wasm_factory_1.getInstance)();\n const session = activeSessions.get(sessionId);\n if (!session) {\n throw new Error('invalid session id');\n }\n const sessionHandle = session[0];\n const inputNamesUTF8Encoded = session[1];\n const outputNamesUTF8Encoded = session[2];\n inputNamesUTF8Encoded.forEach(wasm._OrtFree);\n outputNamesUTF8Encoded.forEach(wasm._OrtFree);\n wasm._OrtReleaseSession(sessionHandle);\n activeSessions.delete(sessionId);\n};\nexports.releaseSession = releaseSession;\nconst tensorDataTypeStringToEnum = (type) => {\n switch (type) {\n case 'int8':\n return 3 /* DataType.int8 */;\n case 'uint8':\n return 2 /* DataType.uint8 */;\n case 'bool':\n return 9 /* DataType.bool */;\n case 'int16':\n return 5 /* DataType.int16 */;\n case 'uint16':\n return 4 /* DataType.uint16 */;\n case 'int32':\n return 6 /* DataType.int32 */;\n case 'uint32':\n return 12 /* DataType.uint32 */;\n case 'float32':\n return 1 /* DataType.float */;\n case 'float64':\n return 11 /* DataType.double */;\n case 'string':\n return 8 /* DataType.string */;\n case 'int64':\n return 7 /* DataType.int64 */;\n case 'uint64':\n return 13 /* DataType.uint64 */;\n default:\n throw new Error(`unsupported data type: ${type}`);\n }\n};\nconst tensorDataTypeEnumToString = (typeProto) => {\n switch (typeProto) {\n case 3 /* DataType.int8 */:\n return 'int8';\n case 2 /* DataType.uint8 */:\n return 'uint8';\n case 9 /* DataType.bool */:\n return 'bool';\n case 5 /* DataType.int16 */:\n return 'int16';\n case 4 /* DataType.uint16 */:\n return 'uint16';\n case 6 /* DataType.int32 */:\n return 'int32';\n case 12 /* DataType.uint32 */:\n return 'uint32';\n case 1 /* DataType.float */:\n return 'float32';\n case 11 /* DataType.double */:\n return 'float64';\n case 8 /* DataType.string */:\n return 'string';\n case 7 /* DataType.int64 */:\n return 'int64';\n case 13 /* DataType.uint64 */:\n return 'uint64';\n default:\n throw new Error(`unsupported data type: ${typeProto}`);\n }\n};\nconst numericTensorTypeToTypedArray = (type) => {\n switch (type) {\n case 'float32':\n return Float32Array;\n case 'uint8':\n return Uint8Array;\n case 'int8':\n return Int8Array;\n case 'uint16':\n return Uint16Array;\n case 'int16':\n return Int16Array;\n case 'int32':\n return Int32Array;\n case 'bool':\n return Uint8Array;\n case 'float64':\n return Float64Array;\n case 'uint32':\n return Uint32Array;\n case 'int64':\n return BigInt64Array;\n case 'uint64':\n return BigUint64Array;\n default:\n throw new Error(`unsupported type: ${type}`);\n }\n};\n/**\n * perform inference run\n */\nconst run = (sessionId, inputIndices, inputs, outputIndices, options) => {\n const wasm = (0, wasm_factory_1.getInstance)();\n const session = activeSessions.get(sessionId);\n if (!session) {\n throw new Error('invalid session id');\n }\n const sessionHandle = session[0];\n const inputNamesUTF8Encoded = session[1];\n const outputNamesUTF8Encoded = session[2];\n const inputCount = inputIndices.length;\n const outputCount = outputIndices.length;\n let runOptionsHandle = 0;\n let runOptionsAllocs = [];\n const inputValues = [];\n const inputAllocs = [];\n try {\n [runOptionsHandle, runOptionsAllocs] = (0, run_options_1.setRunOptions)(options);\n // create input tensors\n for (let i = 0; i < inputCount; i++) {\n const dataType = inputs[i][0];\n const dims = inputs[i][1];\n const data = inputs[i][2];\n let dataOffset;\n let dataByteLength;\n if (Array.isArray(data)) {\n // string tensor\n dataByteLength = 4 * data.length;\n dataOffset = wasm._malloc(dataByteLength);\n inputAllocs.push(dataOffset);\n let dataIndex = dataOffset / 4;\n for (let i = 0; i < data.length; i++) {\n if (typeof data[i] !== 'string') {\n throw new TypeError(`tensor data at index ${i} is not a string`);\n }\n wasm.HEAPU32[dataIndex++] = (0, string_utils_1.allocWasmString)(data[i], inputAllocs);\n }\n }\n else {\n dataByteLength = data.byteLength;\n dataOffset = wasm._malloc(dataByteLength);\n inputAllocs.push(dataOffset);\n wasm.HEAPU8.set(new Uint8Array(data.buffer, data.byteOffset, dataByteLength), dataOffset);\n }\n const stack = wasm.stackSave();\n const dimsOffset = wasm.stackAlloc(4 * dims.length);\n try {\n let dimIndex = dimsOffset / 4;\n dims.forEach(d => wasm.HEAP32[dimIndex++] = d);\n const tensor = wasm._OrtCreateTensor(tensorDataTypeStringToEnum(dataType), dataOffset, dataByteLength, dimsOffset, dims.length);\n if (tensor === 0) {\n throw new Error('Can\\'t create a tensor');\n }\n inputValues.push(tensor);\n }\n finally {\n wasm.stackRestore(stack);\n }\n }\n const beforeRunStack = wasm.stackSave();\n const inputValuesOffset = wasm.stackAlloc(inputCount * 4);\n const inputNamesOffset = wasm.stackAlloc(inputCount * 4);\n const outputValuesOffset = wasm.stackAlloc(outputCount * 4);\n const outputNamesOffset = wasm.stackAlloc(outputCount * 4);\n try {\n let inputValuesIndex = inputValuesOffset / 4;\n let inputNamesIndex = inputNamesOffset / 4;\n let outputValuesIndex = outputValuesOffset / 4;\n let outputNamesIndex = outputNamesOffset / 4;\n for (let i = 0; i < inputCount; i++) {\n wasm.HEAPU32[inputValuesIndex++] = inputValues[i];\n wasm.HEAPU32[inputNamesIndex++] = inputNamesUTF8Encoded[inputIndices[i]];\n }\n for (let i = 0; i < outputCount; i++) {\n wasm.HEAPU32[outputValuesIndex++] = 0;\n wasm.HEAPU32[outputNamesIndex++] = outputNamesUTF8Encoded[outputIndices[i]];\n }\n // support RunOptions\n let errorCode = wasm._OrtRun(sessionHandle, inputNamesOffset, inputValuesOffset, inputCount, outputNamesOffset, outputCount, outputValuesOffset, runOptionsHandle);\n const output = [];\n if (errorCode === 0) {\n for (let i = 0; i < outputCount; i++) {\n const tensor = wasm.HEAPU32[outputValuesOffset / 4 + i];\n const beforeGetTensorDataStack = wasm.stackSave();\n // stack allocate 4 pointer value\n const tensorDataOffset = wasm.stackAlloc(4 * 4);\n let type, dataOffset = 0;\n try {\n errorCode = wasm._OrtGetTensorData(tensor, tensorDataOffset, tensorDataOffset + 4, tensorDataOffset + 8, tensorDataOffset + 12);\n if (errorCode !== 0) {\n throw new Error(`Can't access output tensor data. error code = ${errorCode}`);\n }\n let tensorDataIndex = tensorDataOffset / 4;\n const dataType = wasm.HEAPU32[tensorDataIndex++];\n dataOffset = wasm.HEAPU32[tensorDataIndex++];\n const dimsOffset = wasm.HEAPU32[tensorDataIndex++];\n const dimsLength = wasm.HEAPU32[tensorDataIndex++];\n const dims = [];\n for (let i = 0; i < dimsLength; i++) {\n dims.push(wasm.HEAPU32[dimsOffset / 4 + i]);\n }\n wasm._OrtFree(dimsOffset);\n const size = dims.length === 0 ? 1 : dims.reduce((a, b) => a * b);\n type = tensorDataTypeEnumToString(dataType);\n if (type === 'string') {\n const stringData = [];\n let dataIndex = dataOffset / 4;\n for (let i = 0; i < size; i++) {\n const offset = wasm.HEAPU32[dataIndex++];\n const maxBytesToRead = i === size - 1 ? undefined : wasm.HEAPU32[dataIndex] - offset;\n stringData.push(wasm.UTF8ToString(offset, maxBytesToRead));\n }\n output.push([type, dims, stringData]);\n }\n else {\n const typedArrayConstructor = numericTensorTypeToTypedArray(type);\n const data = new typedArrayConstructor(size);\n new Uint8Array(data.buffer, data.byteOffset, data.byteLength)\n .set(wasm.HEAPU8.subarray(dataOffset, dataOffset + data.byteLength));\n output.push([type, dims, data]);\n }\n }\n finally {\n wasm.stackRestore(beforeGetTensorDataStack);\n if (type === 'string' && dataOffset) {\n wasm._free(dataOffset);\n }\n wasm._OrtReleaseTensor(tensor);\n }\n }\n }\n if (errorCode === 0) {\n return output;\n }\n else {\n throw new Error(`failed to call OrtRun(). error code = ${errorCode}.`);\n }\n }\n finally {\n wasm.stackRestore(beforeRunStack);\n }\n }\n finally {\n inputValues.forEach(wasm._OrtReleaseTensor);\n inputAllocs.forEach(wasm._free);\n wasm._OrtReleaseRunOptions(runOptionsHandle);\n runOptionsAllocs.forEach(wasm._free);\n }\n};\nexports.run = run;\n/**\n * end profiling\n */\nconst endProfiling = (sessionId) => {\n const wasm = (0, wasm_factory_1.getInstance)();\n const session = activeSessions.get(sessionId);\n if (!session) {\n throw new Error('invalid session id');\n }\n const sessionHandle = session[0];\n // profile file name is not used yet, but it must be freed.\n const profileFileName = wasm._OrtEndProfiling(sessionHandle);\n if (profileFileName === 0) {\n throw new Error('Can\\'t get an profile file name');\n }\n wasm._OrtFree(profileFileName);\n};\nexports.endProfiling = endProfiling;\nconst extractTransferableBuffers = (tensors) => {\n const buffers = [];\n for (const tensor of tensors) {\n const data = tensor[2];\n if (!Array.isArray(data) && data.buffer) {\n buffers.push(data.buffer);\n }\n }\n return buffers;\n};\nexports.extractTransferableBuffers = extractTransferableBuffers;\n\n\n/***/ }),\n\n/***/ \"./lib/wasm/wasm-factory.ts\":\n/*!**********************************!*\\\n !*** ./lib/wasm/wasm-factory.ts ***!\n \\**********************************/\n/***/ (function(__unused_webpack_module, exports, __webpack_require__) {\n\n\"use strict\";\nvar __dirname = \"/\";\n\n// Copyright (c) Microsoft Corporation. All rights reserved.\n// Licensed under the MIT License.\nvar __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {\n if (k2 === undefined) k2 = k;\n var desc = Object.getOwnPropertyDescriptor(m, k);\n if (!desc || (\"get\" in desc ? !m.__esModule : desc.writable || desc.configurable)) {\n desc = { enumerable: true, get: function() { return m[k]; } };\n }\n Object.defineProperty(o, k2, desc);\n}) : (function(o, m, k, k2) {\n if (k2 === undefined) k2 = k;\n o[k2] = m[k];\n}));\nvar __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {\n Object.defineProperty(o, \"default\", { enumerable: true, value: v });\n}) : function(o, v) {\n o[\"default\"] = v;\n});\nvar __importStar = (this && this.__importStar) || function (mod) {\n if (mod && mod.__esModule) return mod;\n var result = {};\n if (mod != null) for (var k in mod) if (k !== \"default\" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);\n __setModuleDefault(result, mod);\n return result;\n};\nvar __importDefault = (this && this.__importDefault) || function (mod) {\n return (mod && mod.__esModule) ? mod : { \"default\": mod };\n};\nObject.defineProperty(exports, \"__esModule\", ({ value: true }));\nexports.dispose = exports.getInstance = exports.initializeWebAssembly = void 0;\nconst path = __importStar(__webpack_require__(/*! path */ \"?7aa5\"));\nconst ort_wasm_js_1 = __importDefault(__webpack_require__(/*! ./binding/ort-wasm.js */ \"./lib/wasm/binding/ort-wasm.js\"));\nconst ortWasmFactoryThreaded = \n// eslint-disable-next-line @typescript-eslint/no-require-imports\n true ? __webpack_require__(/*! ./binding/ort-wasm-threaded.js */ \"./lib/wasm/binding/ort-wasm-threaded.js\") : 0;\nlet wasm;\nlet initialized = false;\nlet initializing = false;\nlet aborted = false;\nconst isMultiThreadSupported = () => {\n try {\n // If 'SharedArrayBuffer' is not available, WebAssembly threads will not work.\n if (typeof SharedArrayBuffer === 'undefined') {\n return false;\n }\n // Test for transferability of SABs (for browsers. needed for Firefox)\n // https://groups.google.com/forum/#!msg/mozilla.dev.platform/IHkBZlHETpA/dwsMNchWEQAJ\n if (typeof MessageChannel !== 'undefined') {\n new MessageChannel().port1.postMessage(new SharedArrayBuffer(1));\n }\n // Test for WebAssembly threads capability (for both browsers and Node.js)\n // This typed array is a WebAssembly program containing threaded instructions.\n return WebAssembly.validate(new Uint8Array([\n 0, 97, 115, 109, 1, 0, 0, 0, 1, 4, 1, 96, 0, 0, 3, 2, 1, 0, 5,\n 4, 1, 3, 1, 1, 10, 11, 1, 9, 0, 65, 0, 254, 16, 2, 0, 26, 11\n ]));\n }\n catch (e) {\n return false;\n }\n};\nconst isSimdSupported = () => {\n try {\n // Test for WebAssembly SIMD capability (for both browsers and Node.js)\n // This typed array is a WebAssembly program containing SIMD instructions.\n // The binary data is generated from the following code by wat2wasm:\n //\n // (module\n // (type $t0 (func))\n // (func $f0 (type $t0)\n // (drop\n // (i32x4.dot_i16x8_s\n // (i8x16.splat\n // (i32.const 0))\n // (v128.const i32x4 0x00000000 0x00000000 0x00000000 0x00000000)))))\n return WebAssembly.validate(new Uint8Array([\n 0, 97, 115, 109, 1, 0, 0, 0, 1, 4, 1, 96, 0, 0, 3, 2, 1, 0, 10, 30, 1, 28, 0, 65, 0,\n 253, 15, 253, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 253, 186, 1, 26, 11\n ]));\n }\n catch (e) {\n return false;\n }\n};\nconst getWasmFileName = (useSimd, useThreads) => {\n if (useThreads) {\n return useSimd ? 'ort-wasm-simd-threaded.wasm' : 'ort-wasm-threaded.wasm';\n }\n else {\n return useSimd ? 'ort-wasm-simd.wasm' : 'ort-wasm.wasm';\n }\n};\nconst initializeWebAssembly = async (flags) => {\n if (initialized) {\n return Promise.resolve();\n }\n if (initializing) {\n throw new Error('multiple calls to \\'initializeWebAssembly()\\' detected.');\n }\n if (aborted) {\n throw new Error('previous call to \\'initializeWebAssembly()\\' failed.');\n }\n initializing = true;\n // wasm flags are already initialized\n const timeout = flags.initTimeout;\n const numThreads = flags.numThreads;\n const simd = flags.simd;\n const useThreads = numThreads > 1 && isMultiThreadSupported();\n const useSimd = simd && isSimdSupported();\n const wasmPrefixOverride = typeof flags.wasmPaths === 'string' ? flags.wasmPaths : undefined;\n const wasmFileName = getWasmFileName(false, useThreads);\n const wasmOverrideFileName = getWasmFileName(useSimd, useThreads);\n const wasmPathOverride = typeof flags.wasmPaths === 'object' ? flags.wasmPaths[wasmOverrideFileName] : undefined;\n let isTimeout = false;\n const tasks = [];\n // promise for timeout\n if (timeout > 0) {\n tasks.push(new Promise((resolve) => {\n setTimeout(() => {\n isTimeout = true;\n resolve();\n }, timeout);\n }));\n }\n // promise for module initialization\n tasks.push(new Promise((resolve, reject) => {\n const factory = useThreads ? ortWasmFactoryThreaded : ort_wasm_js_1.default;\n const config = {\n locateFile: (fileName, scriptDirectory) => {\n if ( true && useThreads && fileName.endsWith('.worker.js') &&\n typeof Blob !== 'undefined') {\n return URL.createObjectURL(new Blob([\n // This require() function is handled by webpack to load file content of the corresponding .worker.js\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n __webpack_require__(/*! ./binding/ort-wasm-threaded.worker.js */ \"./lib/wasm/binding/ort-wasm-threaded.worker.js\")\n ], { type: 'text/javascript' }));\n }\n if (fileName === wasmFileName) {\n const prefix = wasmPrefixOverride !== null && wasmPrefixOverride !== void 0 ? wasmPrefixOverride : scriptDirectory;\n return wasmPathOverride !== null && wasmPathOverride !== void 0 ? wasmPathOverride : prefix + wasmOverrideFileName;\n }\n return scriptDirectory + fileName;\n }\n };\n if ( true && useThreads) {\n if (typeof Blob === 'undefined') {\n config.mainScriptUrlOrBlob = path.join(__dirname, 'ort-wasm-threaded.js');\n }\n else {\n const scriptSourceCode = `var ortWasmThreaded=(function(){var _scriptDir;return ${factory.toString()}})();`;\n config.mainScriptUrlOrBlob = new Blob([scriptSourceCode], { type: 'text/javascript' });\n }\n }\n factory(config).then(\n // wasm module initialized successfully\n module => {\n initializing = false;\n initialized = true;\n wasm = module;\n resolve();\n }, \n // wasm module failed to initialize\n (what) => {\n initializing = false;\n aborted = true;\n reject(what);\n });\n }));\n await Promise.race(tasks);\n if (isTimeout) {\n throw new Error(`WebAssembly backend initializing failed due to timeout: ${timeout}ms`);\n }\n};\nexports.initializeWebAssembly = initializeWebAssembly;\nconst getInstance = () => {\n if (initialized && wasm) {\n return wasm;\n }\n throw new Error('WebAssembly is not initialized yet.');\n};\nexports.getInstance = getInstance;\nconst dispose = () => {\n var _a;\n if (initialized && !initializing && !aborted) {\n initializing = true;\n (_a = wasm.PThread) === null || _a === void 0 ? void 0 : _a.terminateAllThreads();\n wasm = undefined;\n initializing = false;\n initialized = false;\n aborted = true;\n }\n};\nexports.dispose = dispose;\n\n\n/***/ }),\n\n/***/ \"./lib/wasm/binding/ort-wasm-threaded.worker.js\":\n/*!******************************************************!*\\\n !*** ./lib/wasm/binding/ort-wasm-threaded.worker.js ***!\n \\******************************************************/\n/***/ ((module) => {\n\n\"use strict\";\nmodule.exports = \"\\\"use strict\\\";var Module={};var ENVIRONMENT_IS_NODE=typeof process==\\\"object\\\"&&typeof process.versions==\\\"object\\\"&&typeof process.versions.node==\\\"string\\\";if(ENVIRONMENT_IS_NODE){var nodeWorkerThreads=require(\\\"worker_threads\\\");var parentPort=nodeWorkerThreads.parentPort;parentPort.on(\\\"message\\\",data=>onmessage({data:data}));var fs=require(\\\"fs\\\");Object.assign(global,{self:global,require:require,Module:Module,location:{href:__filename},Worker:nodeWorkerThreads.Worker,importScripts:function(f){(0,eval)(fs.readFileSync(f,\\\"utf8\\\"))},postMessage:function(msg){parentPort.postMessage(msg)},performance:global.performance||{now:function(){return Date.now()}}})}var initializedJS=false;var pendingNotifiedProxyingQueues=[];function threadPrintErr(){var text=Array.prototype.slice.call(arguments).join(\\\" \\\");if(ENVIRONMENT_IS_NODE){fs.writeSync(2,text+\\\"\\\\n\\\");return}console.error(text)}function threadAlert(){var text=Array.prototype.slice.call(arguments).join(\\\" \\\");postMessage({cmd:\\\"alert\\\",text:text,threadId:Module[\\\"_pthread_self\\\"]()})}var err=threadPrintErr;self.alert=threadAlert;Module[\\\"instantiateWasm\\\"]=(info,receiveInstance)=>{var instance=new WebAssembly.Instance(Module[\\\"wasmModule\\\"],info);receiveInstance(instance);Module[\\\"wasmModule\\\"]=null;return instance.exports};self.onunhandledrejection=e=>{throw e.reason??e};self.onmessage=e=>{try{if(e.data.cmd===\\\"load\\\"){Module[\\\"wasmModule\\\"]=e.data.wasmModule;Module[\\\"wasmMemory\\\"]=e.data.wasmMemory;Module[\\\"buffer\\\"]=Module[\\\"wasmMemory\\\"].buffer;Module[\\\"ENVIRONMENT_IS_PTHREAD\\\"]=true;if(typeof e.data.urlOrBlob==\\\"string\\\"){importScripts(e.data.urlOrBlob)}else{var objectUrl=URL.createObjectURL(e.data.urlOrBlob);importScripts(objectUrl);URL.revokeObjectURL(objectUrl)}ortWasmThreaded(Module).then(function(instance){Module=instance})}else if(e.data.cmd===\\\"run\\\"){Module[\\\"__performance_now_clock_drift\\\"]=performance.now()-e.data.time;Module[\\\"__emscripten_thread_init\\\"](e.data.pthread_ptr,/*isMainBrowserThread=*/0,/*isMainRuntimeThread=*/0,/*canBlock=*/1);Module[\\\"establishStackSpace\\\"]();Module[\\\"PThread\\\"].receiveObjectTransfer(e.data);Module[\\\"PThread\\\"].threadInitTLS();if(!initializedJS){pendingNotifiedProxyingQueues.forEach(queue=>{Module[\\\"executeNotifiedProxyingQueue\\\"](queue)});pendingNotifiedProxyingQueues=[];initializedJS=true}try{Module[\\\"invokeEntryPoint\\\"](e.data.start_routine,e.data.arg)}catch(ex){if(ex!=\\\"unwind\\\"){if(ex instanceof Module[\\\"ExitStatus\\\"]){if(Module[\\\"keepRuntimeAlive\\\"]()){}else{Module[\\\"__emscripten_thread_exit\\\"](ex.status)}}else{throw ex}}}}else if(e.data.cmd===\\\"cancel\\\"){if(Module[\\\"_pthread_self\\\"]()){Module[\\\"__emscripten_thread_exit\\\"](-1)}}else if(e.data.target===\\\"setimmediate\\\"){}else if(e.data.cmd===\\\"processProxyingQueue\\\"){if(initializedJS){Module[\\\"executeNotifiedProxyingQueue\\\"](e.data.queue)}else{pendingNotifiedProxyingQueues.push(e.data.queue)}}else{err(\\\"worker.js received unknown command \\\"+e.data.cmd);err(e.data)}}catch(ex){err(\\\"worker.js onmessage() captured an uncaught exception: \\\"+ex);if(ex&&ex.stack)err(ex.stack);if(Module[\\\"__emscripten_thread_crashed\\\"]){Module[\\\"__emscripten_thread_crashed\\\"]()}throw ex}};\\r\\n\";\n\n/***/ }),\n\n/***/ \"?63c8\":\n/*!********************!*\\\n !*** fs (ignored) ***!\n \\********************/\n/***/ (() => {\n\n/* (ignored) */\n\n/***/ }),\n\n/***/ \"?aedb\":\n/*!********************!*\\\n !*** os (ignored) ***!\n \\********************/\n/***/ (() => {\n\n/* (ignored) */\n\n/***/ }),\n\n/***/ \"?75c6\":\n/*!**********************!*\\\n !*** path (ignored) ***!\n \\**********************/\n/***/ (() => {\n\n/* (ignored) */\n\n/***/ }),\n\n/***/ \"?674f\":\n/*!****************************!*\\\n !*** perf_hooks (ignored) ***!\n \\****************************/\n/***/ (() => {\n\n/* (ignored) */\n\n/***/ }),\n\n/***/ \"?c6f7\":\n/*!********************************!*\\\n !*** worker_threads (ignored) ***!\n \\********************************/\n/***/ (() => {\n\n/* (ignored) */\n\n/***/ }),\n\n/***/ \"?7aa5\":\n/*!**********************!*\\\n !*** path (ignored) ***!\n \\**********************/\n/***/ (() => {\n\n/* (ignored) */\n\n/***/ })\n\n/******/ \t});\n/************************************************************************/\n/******/ \t// The module cache\n/******/ \tvar __webpack_module_cache__ = {};\n/******/ \t\n/******/ \t// The require function\n/******/ \tfunction __webpack_require__(moduleId) {\n/******/ \t\t// Check if module is in cache\n/******/ \t\tvar cachedModule = __webpack_module_cache__[moduleId];\n/******/ \t\tif (cachedModule !== undefined) {\n/******/ \t\t\treturn cachedModule.exports;\n/******/ \t\t}\n/******/ \t\t// Create a new module (and put it into the cache)\n/******/ \t\tvar module = __webpack_module_cache__[moduleId] = {\n/******/ \t\t\t// no module.id needed\n/******/ \t\t\t// no module.loaded needed\n/******/ \t\t\texports: {}\n/******/ \t\t};\n/******/ \t\n/******/ \t\t// Execute the module function\n/******/ \t\t__webpack_modules__[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n/******/ \t\n/******/ \t\t// Return the exports of the module\n/******/ \t\treturn module.exports;\n/******/ \t}\n/******/ \t\n/************************************************************************/\n/******/ \t/* webpack/runtime/global */\n/******/ \t(() => {\n/******/ \t\t__webpack_require__.g = (function() {\n/******/ \t\t\tif (typeof globalThis === 'object') return globalThis;\n/******/ \t\t\ttry {\n/******/ \t\t\t\treturn this || new Function('return this')();\n/******/ \t\t\t} catch (e) {\n/******/ \t\t\t\tif (typeof window === 'object') return window;\n/******/ \t\t\t}\n/******/ \t\t})();\n/******/ \t})();\n/******/ \t\n/************************************************************************/\nvar __webpack_exports__ = {};\n// This entry need to be wrapped in an IIFE because it need to be in strict mode.\n(() => {\n\"use strict\";\nvar exports = __webpack_exports__;\n/*!*****************************************************************************************************!*\\\n !*** ./node_modules/ts-loader/index.js??ruleSet[1].rules[0].use[0]!./lib/wasm/proxy-worker/main.ts ***!\n \\*****************************************************************************************************/\n\n// Copyright (c) Microsoft Corporation. All rights reserved.\n// Licensed under the MIT License.\nObject.defineProperty(exports, \"__esModule\", ({ value: true }));\nconst wasm_core_impl_1 = __webpack_require__(/*! ../wasm-core-impl */ \"./lib/wasm/wasm-core-impl.ts\");\nconst wasm_factory_1 = __webpack_require__(/*! ../wasm-factory */ \"./lib/wasm/wasm-factory.ts\");\nself.onmessage = (ev) => {\n switch (ev.data.type) {\n case 'init-wasm':\n (0, wasm_factory_1.initializeWebAssembly)(ev.data.in)\n .then(() => postMessage({ type: 'init-wasm' }), err => postMessage({ type: 'init-wasm', err }));\n break;\n case 'init-ort':\n try {\n const { numThreads, loggingLevel } = ev.data.in;\n (0, wasm_core_impl_1.initOrt)(numThreads, loggingLevel);\n postMessage({ type: 'init-ort' });\n }\n catch (err) {\n postMessage({ type: 'init-ort', err });\n }\n break;\n case 'create_allocate':\n try {\n const { model } = ev.data.in;\n const modeldata = (0, wasm_core_impl_1.createSessionAllocate)(model);\n postMessage({ type: 'create_allocate', out: modeldata });\n }\n catch (err) {\n postMessage({ type: 'create_allocate', err });\n }\n break;\n case 'create_finalize':\n try {\n const { modeldata, options } = ev.data.in;\n const sessionMetadata = (0, wasm_core_impl_1.createSessionFinalize)(modeldata, options);\n postMessage({ type: 'create_finalize', out: sessionMetadata });\n }\n catch (err) {\n postMessage({ type: 'create_finalize', err });\n }\n break;\n case 'create':\n try {\n const { model, options } = ev.data.in;\n const sessionMetadata = (0, wasm_core_impl_1.createSession)(model, options);\n postMessage({ type: 'create', out: sessionMetadata });\n }\n catch (err) {\n postMessage({ type: 'create', err });\n }\n break;\n case 'release':\n try {\n const handler = ev.data.in;\n (0, wasm_core_impl_1.releaseSession)(handler);\n postMessage({ type: 'release' });\n }\n catch (err) {\n postMessage({ type: 'release', err });\n }\n break;\n case 'run':\n try {\n const { sessionId, inputIndices, inputs, outputIndices, options } = ev.data.in;\n const outputs = (0, wasm_core_impl_1.run)(sessionId, inputIndices, inputs, outputIndices, options);\n postMessage({ type: 'run', out: outputs }, (0, wasm_core_impl_1.extractTransferableBuffers)(outputs));\n }\n catch (err) {\n postMessage({ type: 'run', err });\n }\n break;\n case 'end-profiling':\n try {\n const handler = ev.data.in;\n (0, wasm_core_impl_1.endProfiling)(handler);\n postMessage({ type: 'end-profiling' });\n }\n catch (err) {\n postMessage({ type: 'end-profiling', err });\n }\n break;\n default:\n }\n};\n\n})();\n\n/******/ })()\n;\n", "Worker", undefined, undefined);
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/worker-loader/dist/runtime/inline.js":
|
|
/*!***********************************************************!*\
|
|
!*** ./node_modules/worker-loader/dist/runtime/inline.js ***!
|
|
\***********************************************************/
|
|
/***/ ((module) => {
|
|
|
|
"use strict";
|
|
|
|
|
|
/* eslint-env browser */
|
|
|
|
/* eslint-disable no-undef, no-use-before-define, new-cap */
|
|
module.exports = function (content, workerConstructor, workerOptions, url) {
|
|
var globalScope = self || window;
|
|
|
|
try {
|
|
try {
|
|
var blob;
|
|
|
|
try {
|
|
// New API
|
|
blob = new globalScope.Blob([content]);
|
|
} catch (e) {
|
|
// BlobBuilder = Deprecated, but widely implemented
|
|
var BlobBuilder = globalScope.BlobBuilder || globalScope.WebKitBlobBuilder || globalScope.MozBlobBuilder || globalScope.MSBlobBuilder;
|
|
blob = new BlobBuilder();
|
|
blob.append(content);
|
|
blob = blob.getBlob();
|
|
}
|
|
|
|
var URL = globalScope.URL || globalScope.webkitURL;
|
|
var objectURL = URL.createObjectURL(blob);
|
|
var worker = new globalScope[workerConstructor](objectURL, workerOptions);
|
|
URL.revokeObjectURL(objectURL);
|
|
return worker;
|
|
} catch (e) {
|
|
return new globalScope[workerConstructor]("data:application/javascript,".concat(encodeURIComponent(content)), workerOptions);
|
|
}
|
|
} catch (e) {
|
|
if (!url) {
|
|
throw Error("Inline worker is not supported");
|
|
}
|
|
|
|
return new globalScope[workerConstructor](url, workerOptions);
|
|
}
|
|
};
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./lib/wasm/binding/ort-wasm-threaded.worker.js":
|
|
/*!******************************************************!*\
|
|
!*** ./lib/wasm/binding/ort-wasm-threaded.worker.js ***!
|
|
\******************************************************/
|
|
/***/ ((module) => {
|
|
|
|
"use strict";
|
|
module.exports = "\"use strict\";var Module={};var ENVIRONMENT_IS_NODE=typeof process==\"object\"&&typeof process.versions==\"object\"&&typeof process.versions.node==\"string\";if(ENVIRONMENT_IS_NODE){var nodeWorkerThreads=require(\"worker_threads\");var parentPort=nodeWorkerThreads.parentPort;parentPort.on(\"message\",data=>onmessage({data:data}));var fs=require(\"fs\");Object.assign(global,{self:global,require:require,Module:Module,location:{href:__filename},Worker:nodeWorkerThreads.Worker,importScripts:function(f){(0,eval)(fs.readFileSync(f,\"utf8\"))},postMessage:function(msg){parentPort.postMessage(msg)},performance:global.performance||{now:function(){return Date.now()}}})}var initializedJS=false;var pendingNotifiedProxyingQueues=[];function threadPrintErr(){var text=Array.prototype.slice.call(arguments).join(\" \");if(ENVIRONMENT_IS_NODE){fs.writeSync(2,text+\"\\n\");return}console.error(text)}function threadAlert(){var text=Array.prototype.slice.call(arguments).join(\" \");postMessage({cmd:\"alert\",text:text,threadId:Module[\"_pthread_self\"]()})}var err=threadPrintErr;self.alert=threadAlert;Module[\"instantiateWasm\"]=(info,receiveInstance)=>{var instance=new WebAssembly.Instance(Module[\"wasmModule\"],info);receiveInstance(instance);Module[\"wasmModule\"]=null;return instance.exports};self.onunhandledrejection=e=>{throw e.reason??e};self.onmessage=e=>{try{if(e.data.cmd===\"load\"){Module[\"wasmModule\"]=e.data.wasmModule;Module[\"wasmMemory\"]=e.data.wasmMemory;Module[\"buffer\"]=Module[\"wasmMemory\"].buffer;Module[\"ENVIRONMENT_IS_PTHREAD\"]=true;if(typeof e.data.urlOrBlob==\"string\"){importScripts(e.data.urlOrBlob)}else{var objectUrl=URL.createObjectURL(e.data.urlOrBlob);importScripts(objectUrl);URL.revokeObjectURL(objectUrl)}ortWasmThreaded(Module).then(function(instance){Module=instance})}else if(e.data.cmd===\"run\"){Module[\"__performance_now_clock_drift\"]=performance.now()-e.data.time;Module[\"__emscripten_thread_init\"](e.data.pthread_ptr,/*isMainBrowserThread=*/0,/*isMainRuntimeThread=*/0,/*canBlock=*/1);Module[\"establishStackSpace\"]();Module[\"PThread\"].receiveObjectTransfer(e.data);Module[\"PThread\"].threadInitTLS();if(!initializedJS){pendingNotifiedProxyingQueues.forEach(queue=>{Module[\"executeNotifiedProxyingQueue\"](queue)});pendingNotifiedProxyingQueues=[];initializedJS=true}try{Module[\"invokeEntryPoint\"](e.data.start_routine,e.data.arg)}catch(ex){if(ex!=\"unwind\"){if(ex instanceof Module[\"ExitStatus\"]){if(Module[\"keepRuntimeAlive\"]()){}else{Module[\"__emscripten_thread_exit\"](ex.status)}}else{throw ex}}}}else if(e.data.cmd===\"cancel\"){if(Module[\"_pthread_self\"]()){Module[\"__emscripten_thread_exit\"](-1)}}else if(e.data.target===\"setimmediate\"){}else if(e.data.cmd===\"processProxyingQueue\"){if(initializedJS){Module[\"executeNotifiedProxyingQueue\"](e.data.queue)}else{pendingNotifiedProxyingQueues.push(e.data.queue)}}else{err(\"worker.js received unknown command \"+e.data.cmd);err(e.data)}}catch(ex){err(\"worker.js onmessage() captured an uncaught exception: \"+ex);if(ex&&ex.stack)err(ex.stack);if(Module[\"__emscripten_thread_crashed\"]){Module[\"__emscripten_thread_crashed\"]()}throw ex}};\r\n";
|
|
|
|
/***/ }),
|
|
|
|
/***/ "?6c45":
|
|
/*!********************!*\
|
|
!*** fs (ignored) ***!
|
|
\********************/
|
|
/***/ (() => {
|
|
|
|
/* (ignored) */
|
|
|
|
/***/ }),
|
|
|
|
/***/ "?b3a2":
|
|
/*!**********************!*\
|
|
!*** util (ignored) ***!
|
|
\**********************/
|
|
/***/ (() => {
|
|
|
|
/* (ignored) */
|
|
|
|
/***/ }),
|
|
|
|
/***/ "?63c8":
|
|
/*!********************!*\
|
|
!*** fs (ignored) ***!
|
|
\********************/
|
|
/***/ (() => {
|
|
|
|
/* (ignored) */
|
|
|
|
/***/ }),
|
|
|
|
/***/ "?aedb":
|
|
/*!********************!*\
|
|
!*** os (ignored) ***!
|
|
\********************/
|
|
/***/ (() => {
|
|
|
|
/* (ignored) */
|
|
|
|
/***/ }),
|
|
|
|
/***/ "?75c6":
|
|
/*!**********************!*\
|
|
!*** path (ignored) ***!
|
|
\**********************/
|
|
/***/ (() => {
|
|
|
|
/* (ignored) */
|
|
|
|
/***/ }),
|
|
|
|
/***/ "?674f":
|
|
/*!****************************!*\
|
|
!*** perf_hooks (ignored) ***!
|
|
\****************************/
|
|
/***/ (() => {
|
|
|
|
/* (ignored) */
|
|
|
|
/***/ }),
|
|
|
|
/***/ "?c6f7":
|
|
/*!********************************!*\
|
|
!*** worker_threads (ignored) ***!
|
|
\********************************/
|
|
/***/ (() => {
|
|
|
|
/* (ignored) */
|
|
|
|
/***/ }),
|
|
|
|
/***/ "?295d":
|
|
/*!********************!*\
|
|
!*** fs (ignored) ***!
|
|
\********************/
|
|
/***/ (() => {
|
|
|
|
/* (ignored) */
|
|
|
|
/***/ }),
|
|
|
|
/***/ "?7aa5":
|
|
/*!**********************!*\
|
|
!*** path (ignored) ***!
|
|
\**********************/
|
|
/***/ (() => {
|
|
|
|
/* (ignored) */
|
|
|
|
/***/ }),
|
|
|
|
/***/ "?cf98":
|
|
/*!**********************!*\
|
|
!*** util (ignored) ***!
|
|
\**********************/
|
|
/***/ (() => {
|
|
|
|
/* (ignored) */
|
|
|
|
/***/ }),
|
|
|
|
/***/ "?0757":
|
|
/*!********************!*\
|
|
!*** os (ignored) ***!
|
|
\********************/
|
|
/***/ (() => {
|
|
|
|
/* (ignored) */
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/flatbuffers/js/flatbuffers.mjs":
|
|
/*!*****************************************************!*\
|
|
!*** ./node_modules/flatbuffers/js/flatbuffers.mjs ***!
|
|
\*****************************************************/
|
|
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
__webpack_require__.r(__webpack_exports__);
|
|
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
|
/* harmony export */ "flatbuffers": () => (/* binding */ flatbuffers)
|
|
/* harmony export */ });
|
|
/// @file
|
|
/// @addtogroup flatbuffers_javascript_api
|
|
/// @{
|
|
/// @cond FLATBUFFERS_INTERNAL
|
|
|
|
/**
|
|
* @fileoverview
|
|
*
|
|
* Need to suppress 'global this' error so the Node.js export line doesn't cause
|
|
* closure compile to error out.
|
|
* @suppress {globalThis}
|
|
*/
|
|
|
|
/**
|
|
* @const
|
|
* @namespace
|
|
*/
|
|
var flatbuffers = {};
|
|
|
|
/**
|
|
* @typedef {number}
|
|
*/
|
|
flatbuffers.Offset;
|
|
|
|
/**
|
|
* @typedef {{
|
|
* bb: flatbuffers.ByteBuffer,
|
|
* bb_pos: number
|
|
* }}
|
|
*/
|
|
flatbuffers.Table;
|
|
|
|
/**
|
|
* @type {number}
|
|
* @const
|
|
*/
|
|
flatbuffers.SIZEOF_SHORT = 2;
|
|
|
|
/**
|
|
* @type {number}
|
|
* @const
|
|
*/
|
|
flatbuffers.SIZEOF_INT = 4;
|
|
|
|
/**
|
|
* @type {number}
|
|
* @const
|
|
*/
|
|
flatbuffers.FILE_IDENTIFIER_LENGTH = 4;
|
|
|
|
/**
|
|
* @type {number}
|
|
* @const
|
|
*/
|
|
flatbuffers.SIZE_PREFIX_LENGTH = 4;
|
|
|
|
/**
|
|
* @enum {number}
|
|
*/
|
|
flatbuffers.Encoding = {
|
|
UTF8_BYTES: 1,
|
|
UTF16_STRING: 2
|
|
};
|
|
|
|
/**
|
|
* @type {Int32Array}
|
|
* @const
|
|
*/
|
|
flatbuffers.int32 = new Int32Array(2);
|
|
|
|
/**
|
|
* @type {Float32Array}
|
|
* @const
|
|
*/
|
|
flatbuffers.float32 = new Float32Array(flatbuffers.int32.buffer);
|
|
|
|
/**
|
|
* @type {Float64Array}
|
|
* @const
|
|
*/
|
|
flatbuffers.float64 = new Float64Array(flatbuffers.int32.buffer);
|
|
|
|
/**
|
|
* @type {boolean}
|
|
* @const
|
|
*/
|
|
flatbuffers.isLittleEndian = new Uint16Array(new Uint8Array([1, 0]).buffer)[0] === 1;
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
/**
|
|
* @constructor
|
|
* @param {number} low
|
|
* @param {number} high
|
|
*/
|
|
flatbuffers.Long = function(low, high) {
|
|
/**
|
|
* @type {number}
|
|
* @const
|
|
*/
|
|
this.low = low | 0;
|
|
|
|
/**
|
|
* @type {number}
|
|
* @const
|
|
*/
|
|
this.high = high | 0;
|
|
};
|
|
|
|
/**
|
|
* @param {number} low
|
|
* @param {number} high
|
|
* @returns {!flatbuffers.Long}
|
|
*/
|
|
flatbuffers.Long.create = function(low, high) {
|
|
// Special-case zero to avoid GC overhead for default values
|
|
return low == 0 && high == 0 ? flatbuffers.Long.ZERO : new flatbuffers.Long(low, high);
|
|
};
|
|
|
|
/**
|
|
* @returns {number}
|
|
*/
|
|
flatbuffers.Long.prototype.toFloat64 = function() {
|
|
return (this.low >>> 0) + this.high * 0x100000000;
|
|
};
|
|
|
|
/**
|
|
* @param {flatbuffers.Long} other
|
|
* @returns {boolean}
|
|
*/
|
|
flatbuffers.Long.prototype.equals = function(other) {
|
|
return this.low == other.low && this.high == other.high;
|
|
};
|
|
|
|
/**
|
|
* @type {!flatbuffers.Long}
|
|
* @const
|
|
*/
|
|
flatbuffers.Long.ZERO = new flatbuffers.Long(0, 0);
|
|
|
|
/// @endcond
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/**
|
|
* Create a FlatBufferBuilder.
|
|
*
|
|
* @constructor
|
|
* @param {number=} opt_initial_size
|
|
*/
|
|
flatbuffers.Builder = function(opt_initial_size) {
|
|
if (!opt_initial_size) {
|
|
var initial_size = 1024;
|
|
} else {
|
|
var initial_size = opt_initial_size;
|
|
}
|
|
|
|
/**
|
|
* @type {flatbuffers.ByteBuffer}
|
|
* @private
|
|
*/
|
|
this.bb = flatbuffers.ByteBuffer.allocate(initial_size);
|
|
|
|
/**
|
|
* Remaining space in the ByteBuffer.
|
|
*
|
|
* @type {number}
|
|
* @private
|
|
*/
|
|
this.space = initial_size;
|
|
|
|
/**
|
|
* Minimum alignment encountered so far.
|
|
*
|
|
* @type {number}
|
|
* @private
|
|
*/
|
|
this.minalign = 1;
|
|
|
|
/**
|
|
* The vtable for the current table.
|
|
*
|
|
* @type {Array.<number>}
|
|
* @private
|
|
*/
|
|
this.vtable = null;
|
|
|
|
/**
|
|
* The amount of fields we're actually using.
|
|
*
|
|
* @type {number}
|
|
* @private
|
|
*/
|
|
this.vtable_in_use = 0;
|
|
|
|
/**
|
|
* Whether we are currently serializing a table.
|
|
*
|
|
* @type {boolean}
|
|
* @private
|
|
*/
|
|
this.isNested = false;
|
|
|
|
/**
|
|
* Starting offset of the current struct/table.
|
|
*
|
|
* @type {number}
|
|
* @private
|
|
*/
|
|
this.object_start = 0;
|
|
|
|
/**
|
|
* List of offsets of all vtables.
|
|
*
|
|
* @type {Array.<number>}
|
|
* @private
|
|
*/
|
|
this.vtables = [];
|
|
|
|
/**
|
|
* For the current vector being built.
|
|
*
|
|
* @type {number}
|
|
* @private
|
|
*/
|
|
this.vector_num_elems = 0;
|
|
|
|
/**
|
|
* False omits default values from the serialized data
|
|
*
|
|
* @type {boolean}
|
|
* @private
|
|
*/
|
|
this.force_defaults = false;
|
|
};
|
|
|
|
flatbuffers.Builder.prototype.clear = function() {
|
|
this.bb.clear();
|
|
this.space = this.bb.capacity();
|
|
this.minalign = 1;
|
|
this.vtable = null;
|
|
this.vtable_in_use = 0;
|
|
this.isNested = false;
|
|
this.object_start = 0;
|
|
this.vtables = [];
|
|
this.vector_num_elems = 0;
|
|
this.force_defaults = false;
|
|
};
|
|
|
|
/**
|
|
* In order to save space, fields that are set to their default value
|
|
* don't get serialized into the buffer. Forcing defaults provides a
|
|
* way to manually disable this optimization.
|
|
*
|
|
* @param {boolean} forceDefaults true always serializes default values
|
|
*/
|
|
flatbuffers.Builder.prototype.forceDefaults = function(forceDefaults) {
|
|
this.force_defaults = forceDefaults;
|
|
};
|
|
|
|
/**
|
|
* Get the ByteBuffer representing the FlatBuffer. Only call this after you've
|
|
* called finish(). The actual data starts at the ByteBuffer's current position,
|
|
* not necessarily at 0.
|
|
*
|
|
* @returns {flatbuffers.ByteBuffer}
|
|
*/
|
|
flatbuffers.Builder.prototype.dataBuffer = function() {
|
|
return this.bb;
|
|
};
|
|
|
|
/**
|
|
* Get the bytes representing the FlatBuffer. Only call this after you've
|
|
* called finish().
|
|
*
|
|
* @returns {!Uint8Array}
|
|
*/
|
|
flatbuffers.Builder.prototype.asUint8Array = function() {
|
|
return this.bb.bytes().subarray(this.bb.position(), this.bb.position() + this.offset());
|
|
};
|
|
|
|
/// @cond FLATBUFFERS_INTERNAL
|
|
/**
|
|
* Prepare to write an element of `size` after `additional_bytes` have been
|
|
* written, e.g. if you write a string, you need to align such the int length
|
|
* field is aligned to 4 bytes, and the string data follows it directly. If all
|
|
* you need to do is alignment, `additional_bytes` will be 0.
|
|
*
|
|
* @param {number} size This is the of the new element to write
|
|
* @param {number} additional_bytes The padding size
|
|
*/
|
|
flatbuffers.Builder.prototype.prep = function(size, additional_bytes) {
|
|
// Track the biggest thing we've ever aligned to.
|
|
if (size > this.minalign) {
|
|
this.minalign = size;
|
|
}
|
|
|
|
// Find the amount of alignment needed such that `size` is properly
|
|
// aligned after `additional_bytes`
|
|
var align_size = ((~(this.bb.capacity() - this.space + additional_bytes)) + 1) & (size - 1);
|
|
|
|
// Reallocate the buffer if needed.
|
|
while (this.space < align_size + size + additional_bytes) {
|
|
var old_buf_size = this.bb.capacity();
|
|
this.bb = flatbuffers.Builder.growByteBuffer(this.bb);
|
|
this.space += this.bb.capacity() - old_buf_size;
|
|
}
|
|
|
|
this.pad(align_size);
|
|
};
|
|
|
|
/**
|
|
* @param {number} byte_size
|
|
*/
|
|
flatbuffers.Builder.prototype.pad = function(byte_size) {
|
|
for (var i = 0; i < byte_size; i++) {
|
|
this.bb.writeInt8(--this.space, 0);
|
|
}
|
|
};
|
|
|
|
/**
|
|
* @param {number} value
|
|
*/
|
|
flatbuffers.Builder.prototype.writeInt8 = function(value) {
|
|
this.bb.writeInt8(this.space -= 1, value);
|
|
};
|
|
|
|
/**
|
|
* @param {number} value
|
|
*/
|
|
flatbuffers.Builder.prototype.writeInt16 = function(value) {
|
|
this.bb.writeInt16(this.space -= 2, value);
|
|
};
|
|
|
|
/**
|
|
* @param {number} value
|
|
*/
|
|
flatbuffers.Builder.prototype.writeInt32 = function(value) {
|
|
this.bb.writeInt32(this.space -= 4, value);
|
|
};
|
|
|
|
/**
|
|
* @param {flatbuffers.Long} value
|
|
*/
|
|
flatbuffers.Builder.prototype.writeInt64 = function(value) {
|
|
this.bb.writeInt64(this.space -= 8, value);
|
|
};
|
|
|
|
/**
|
|
* @param {number} value
|
|
*/
|
|
flatbuffers.Builder.prototype.writeFloat32 = function(value) {
|
|
this.bb.writeFloat32(this.space -= 4, value);
|
|
};
|
|
|
|
/**
|
|
* @param {number} value
|
|
*/
|
|
flatbuffers.Builder.prototype.writeFloat64 = function(value) {
|
|
this.bb.writeFloat64(this.space -= 8, value);
|
|
};
|
|
/// @endcond
|
|
|
|
/**
|
|
* Add an `int8` to the buffer, properly aligned, and grows the buffer (if necessary).
|
|
* @param {number} value The `int8` to add the the buffer.
|
|
*/
|
|
flatbuffers.Builder.prototype.addInt8 = function(value) {
|
|
this.prep(1, 0);
|
|
this.writeInt8(value);
|
|
};
|
|
|
|
/**
|
|
* Add an `int16` to the buffer, properly aligned, and grows the buffer (if necessary).
|
|
* @param {number} value The `int16` to add the the buffer.
|
|
*/
|
|
flatbuffers.Builder.prototype.addInt16 = function(value) {
|
|
this.prep(2, 0);
|
|
this.writeInt16(value);
|
|
};
|
|
|
|
/**
|
|
* Add an `int32` to the buffer, properly aligned, and grows the buffer (if necessary).
|
|
* @param {number} value The `int32` to add the the buffer.
|
|
*/
|
|
flatbuffers.Builder.prototype.addInt32 = function(value) {
|
|
this.prep(4, 0);
|
|
this.writeInt32(value);
|
|
};
|
|
|
|
/**
|
|
* Add an `int64` to the buffer, properly aligned, and grows the buffer (if necessary).
|
|
* @param {flatbuffers.Long} value The `int64` to add the the buffer.
|
|
*/
|
|
flatbuffers.Builder.prototype.addInt64 = function(value) {
|
|
this.prep(8, 0);
|
|
this.writeInt64(value);
|
|
};
|
|
|
|
/**
|
|
* Add a `float32` to the buffer, properly aligned, and grows the buffer (if necessary).
|
|
* @param {number} value The `float32` to add the the buffer.
|
|
*/
|
|
flatbuffers.Builder.prototype.addFloat32 = function(value) {
|
|
this.prep(4, 0);
|
|
this.writeFloat32(value);
|
|
};
|
|
|
|
/**
|
|
* Add a `float64` to the buffer, properly aligned, and grows the buffer (if necessary).
|
|
* @param {number} value The `float64` to add the the buffer.
|
|
*/
|
|
flatbuffers.Builder.prototype.addFloat64 = function(value) {
|
|
this.prep(8, 0);
|
|
this.writeFloat64(value);
|
|
};
|
|
|
|
/// @cond FLATBUFFERS_INTERNAL
|
|
/**
|
|
* @param {number} voffset
|
|
* @param {number} value
|
|
* @param {number} defaultValue
|
|
*/
|
|
flatbuffers.Builder.prototype.addFieldInt8 = function(voffset, value, defaultValue) {
|
|
if (this.force_defaults || value != defaultValue) {
|
|
this.addInt8(value);
|
|
this.slot(voffset);
|
|
}
|
|
};
|
|
|
|
/**
|
|
* @param {number} voffset
|
|
* @param {number} value
|
|
* @param {number} defaultValue
|
|
*/
|
|
flatbuffers.Builder.prototype.addFieldInt16 = function(voffset, value, defaultValue) {
|
|
if (this.force_defaults || value != defaultValue) {
|
|
this.addInt16(value);
|
|
this.slot(voffset);
|
|
}
|
|
};
|
|
|
|
/**
|
|
* @param {number} voffset
|
|
* @param {number} value
|
|
* @param {number} defaultValue
|
|
*/
|
|
flatbuffers.Builder.prototype.addFieldInt32 = function(voffset, value, defaultValue) {
|
|
if (this.force_defaults || value != defaultValue) {
|
|
this.addInt32(value);
|
|
this.slot(voffset);
|
|
}
|
|
};
|
|
|
|
/**
|
|
* @param {number} voffset
|
|
* @param {flatbuffers.Long} value
|
|
* @param {flatbuffers.Long} defaultValue
|
|
*/
|
|
flatbuffers.Builder.prototype.addFieldInt64 = function(voffset, value, defaultValue) {
|
|
if (this.force_defaults || !value.equals(defaultValue)) {
|
|
this.addInt64(value);
|
|
this.slot(voffset);
|
|
}
|
|
};
|
|
|
|
/**
|
|
* @param {number} voffset
|
|
* @param {number} value
|
|
* @param {number} defaultValue
|
|
*/
|
|
flatbuffers.Builder.prototype.addFieldFloat32 = function(voffset, value, defaultValue) {
|
|
if (this.force_defaults || value != defaultValue) {
|
|
this.addFloat32(value);
|
|
this.slot(voffset);
|
|
}
|
|
};
|
|
|
|
/**
|
|
* @param {number} voffset
|
|
* @param {number} value
|
|
* @param {number} defaultValue
|
|
*/
|
|
flatbuffers.Builder.prototype.addFieldFloat64 = function(voffset, value, defaultValue) {
|
|
if (this.force_defaults || value != defaultValue) {
|
|
this.addFloat64(value);
|
|
this.slot(voffset);
|
|
}
|
|
};
|
|
|
|
/**
|
|
* @param {number} voffset
|
|
* @param {flatbuffers.Offset} value
|
|
* @param {flatbuffers.Offset} defaultValue
|
|
*/
|
|
flatbuffers.Builder.prototype.addFieldOffset = function(voffset, value, defaultValue) {
|
|
if (this.force_defaults || value != defaultValue) {
|
|
this.addOffset(value);
|
|
this.slot(voffset);
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Structs are stored inline, so nothing additional is being added. `d` is always 0.
|
|
*
|
|
* @param {number} voffset
|
|
* @param {flatbuffers.Offset} value
|
|
* @param {flatbuffers.Offset} defaultValue
|
|
*/
|
|
flatbuffers.Builder.prototype.addFieldStruct = function(voffset, value, defaultValue) {
|
|
if (value != defaultValue) {
|
|
this.nested(value);
|
|
this.slot(voffset);
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Structures are always stored inline, they need to be created right
|
|
* where they're used. You'll get this assertion failure if you
|
|
* created it elsewhere.
|
|
*
|
|
* @param {flatbuffers.Offset} obj The offset of the created object
|
|
*/
|
|
flatbuffers.Builder.prototype.nested = function(obj) {
|
|
if (obj != this.offset()) {
|
|
throw new Error('FlatBuffers: struct must be serialized inline.');
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Should not be creating any other object, string or vector
|
|
* while an object is being constructed
|
|
*/
|
|
flatbuffers.Builder.prototype.notNested = function() {
|
|
if (this.isNested) {
|
|
throw new Error('FlatBuffers: object serialization must not be nested.');
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Set the current vtable at `voffset` to the current location in the buffer.
|
|
*
|
|
* @param {number} voffset
|
|
*/
|
|
flatbuffers.Builder.prototype.slot = function(voffset) {
|
|
this.vtable[voffset] = this.offset();
|
|
};
|
|
|
|
/**
|
|
* @returns {flatbuffers.Offset} Offset relative to the end of the buffer.
|
|
*/
|
|
flatbuffers.Builder.prototype.offset = function() {
|
|
return this.bb.capacity() - this.space;
|
|
};
|
|
|
|
/**
|
|
* Doubles the size of the backing ByteBuffer and copies the old data towards
|
|
* the end of the new buffer (since we build the buffer backwards).
|
|
*
|
|
* @param {flatbuffers.ByteBuffer} bb The current buffer with the existing data
|
|
* @returns {!flatbuffers.ByteBuffer} A new byte buffer with the old data copied
|
|
* to it. The data is located at the end of the buffer.
|
|
*
|
|
* uint8Array.set() formally takes {Array<number>|ArrayBufferView}, so to pass
|
|
* it a uint8Array we need to suppress the type check:
|
|
* @suppress {checkTypes}
|
|
*/
|
|
flatbuffers.Builder.growByteBuffer = function(bb) {
|
|
var old_buf_size = bb.capacity();
|
|
|
|
// Ensure we don't grow beyond what fits in an int.
|
|
if (old_buf_size & 0xC0000000) {
|
|
throw new Error('FlatBuffers: cannot grow buffer beyond 2 gigabytes.');
|
|
}
|
|
|
|
var new_buf_size = old_buf_size << 1;
|
|
var nbb = flatbuffers.ByteBuffer.allocate(new_buf_size);
|
|
nbb.setPosition(new_buf_size - old_buf_size);
|
|
nbb.bytes().set(bb.bytes(), new_buf_size - old_buf_size);
|
|
return nbb;
|
|
};
|
|
/// @endcond
|
|
|
|
/**
|
|
* Adds on offset, relative to where it will be written.
|
|
*
|
|
* @param {flatbuffers.Offset} offset The offset to add.
|
|
*/
|
|
flatbuffers.Builder.prototype.addOffset = function(offset) {
|
|
this.prep(flatbuffers.SIZEOF_INT, 0); // Ensure alignment is already done.
|
|
this.writeInt32(this.offset() - offset + flatbuffers.SIZEOF_INT);
|
|
};
|
|
|
|
/// @cond FLATBUFFERS_INTERNAL
|
|
/**
|
|
* Start encoding a new object in the buffer. Users will not usually need to
|
|
* call this directly. The FlatBuffers compiler will generate helper methods
|
|
* that call this method internally.
|
|
*
|
|
* @param {number} numfields
|
|
*/
|
|
flatbuffers.Builder.prototype.startObject = function(numfields) {
|
|
this.notNested();
|
|
if (this.vtable == null) {
|
|
this.vtable = [];
|
|
}
|
|
this.vtable_in_use = numfields;
|
|
for (var i = 0; i < numfields; i++) {
|
|
this.vtable[i] = 0; // This will push additional elements as needed
|
|
}
|
|
this.isNested = true;
|
|
this.object_start = this.offset();
|
|
};
|
|
|
|
/**
|
|
* Finish off writing the object that is under construction.
|
|
*
|
|
* @returns {flatbuffers.Offset} The offset to the object inside `dataBuffer`
|
|
*/
|
|
flatbuffers.Builder.prototype.endObject = function() {
|
|
if (this.vtable == null || !this.isNested) {
|
|
throw new Error('FlatBuffers: endObject called without startObject');
|
|
}
|
|
|
|
this.addInt32(0);
|
|
var vtableloc = this.offset();
|
|
|
|
// Trim trailing zeroes.
|
|
var i = this.vtable_in_use - 1;
|
|
for (; i >= 0 && this.vtable[i] == 0; i--) {}
|
|
var trimmed_size = i + 1;
|
|
|
|
// Write out the current vtable.
|
|
for (; i >= 0; i--) {
|
|
// Offset relative to the start of the table.
|
|
this.addInt16(this.vtable[i] != 0 ? vtableloc - this.vtable[i] : 0);
|
|
}
|
|
|
|
var standard_fields = 2; // The fields below:
|
|
this.addInt16(vtableloc - this.object_start);
|
|
var len = (trimmed_size + standard_fields) * flatbuffers.SIZEOF_SHORT;
|
|
this.addInt16(len);
|
|
|
|
// Search for an existing vtable that matches the current one.
|
|
var existing_vtable = 0;
|
|
var vt1 = this.space;
|
|
outer_loop:
|
|
for (i = 0; i < this.vtables.length; i++) {
|
|
var vt2 = this.bb.capacity() - this.vtables[i];
|
|
if (len == this.bb.readInt16(vt2)) {
|
|
for (var j = flatbuffers.SIZEOF_SHORT; j < len; j += flatbuffers.SIZEOF_SHORT) {
|
|
if (this.bb.readInt16(vt1 + j) != this.bb.readInt16(vt2 + j)) {
|
|
continue outer_loop;
|
|
}
|
|
}
|
|
existing_vtable = this.vtables[i];
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (existing_vtable) {
|
|
// Found a match:
|
|
// Remove the current vtable.
|
|
this.space = this.bb.capacity() - vtableloc;
|
|
|
|
// Point table to existing vtable.
|
|
this.bb.writeInt32(this.space, existing_vtable - vtableloc);
|
|
} else {
|
|
// No match:
|
|
// Add the location of the current vtable to the list of vtables.
|
|
this.vtables.push(this.offset());
|
|
|
|
// Point table to current vtable.
|
|
this.bb.writeInt32(this.bb.capacity() - vtableloc, this.offset() - vtableloc);
|
|
}
|
|
|
|
this.isNested = false;
|
|
return vtableloc;
|
|
};
|
|
/// @endcond
|
|
|
|
/**
|
|
* Finalize a buffer, poiting to the given `root_table`.
|
|
*
|
|
* @param {flatbuffers.Offset} root_table
|
|
* @param {string=} opt_file_identifier
|
|
* @param {boolean=} opt_size_prefix
|
|
*/
|
|
flatbuffers.Builder.prototype.finish = function(root_table, opt_file_identifier, opt_size_prefix) {
|
|
var size_prefix = opt_size_prefix ? flatbuffers.SIZE_PREFIX_LENGTH : 0;
|
|
if (opt_file_identifier) {
|
|
var file_identifier = opt_file_identifier;
|
|
this.prep(this.minalign, flatbuffers.SIZEOF_INT +
|
|
flatbuffers.FILE_IDENTIFIER_LENGTH + size_prefix);
|
|
if (file_identifier.length != flatbuffers.FILE_IDENTIFIER_LENGTH) {
|
|
throw new Error('FlatBuffers: file identifier must be length ' +
|
|
flatbuffers.FILE_IDENTIFIER_LENGTH);
|
|
}
|
|
for (var i = flatbuffers.FILE_IDENTIFIER_LENGTH - 1; i >= 0; i--) {
|
|
this.writeInt8(file_identifier.charCodeAt(i));
|
|
}
|
|
}
|
|
this.prep(this.minalign, flatbuffers.SIZEOF_INT + size_prefix);
|
|
this.addOffset(root_table);
|
|
if (size_prefix) {
|
|
this.addInt32(this.bb.capacity() - this.space);
|
|
}
|
|
this.bb.setPosition(this.space);
|
|
};
|
|
|
|
/**
|
|
* Finalize a size prefixed buffer, pointing to the given `root_table`.
|
|
*
|
|
* @param {flatbuffers.Offset} root_table
|
|
* @param {string=} opt_file_identifier
|
|
*/
|
|
flatbuffers.Builder.prototype.finishSizePrefixed = function (root_table, opt_file_identifier) {
|
|
this.finish(root_table, opt_file_identifier, true);
|
|
};
|
|
|
|
/// @cond FLATBUFFERS_INTERNAL
|
|
/**
|
|
* This checks a required field has been set in a given table that has
|
|
* just been constructed.
|
|
*
|
|
* @param {flatbuffers.Offset} table
|
|
* @param {number} field
|
|
*/
|
|
flatbuffers.Builder.prototype.requiredField = function(table, field) {
|
|
var table_start = this.bb.capacity() - table;
|
|
var vtable_start = table_start - this.bb.readInt32(table_start);
|
|
var ok = this.bb.readInt16(vtable_start + field) != 0;
|
|
|
|
// If this fails, the caller will show what field needs to be set.
|
|
if (!ok) {
|
|
throw new Error('FlatBuffers: field ' + field + ' must be set');
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Start a new array/vector of objects. Users usually will not call
|
|
* this directly. The FlatBuffers compiler will create a start/end
|
|
* method for vector types in generated code.
|
|
*
|
|
* @param {number} elem_size The size of each element in the array
|
|
* @param {number} num_elems The number of elements in the array
|
|
* @param {number} alignment The alignment of the array
|
|
*/
|
|
flatbuffers.Builder.prototype.startVector = function(elem_size, num_elems, alignment) {
|
|
this.notNested();
|
|
this.vector_num_elems = num_elems;
|
|
this.prep(flatbuffers.SIZEOF_INT, elem_size * num_elems);
|
|
this.prep(alignment, elem_size * num_elems); // Just in case alignment > int.
|
|
};
|
|
|
|
/**
|
|
* Finish off the creation of an array and all its elements. The array must be
|
|
* created with `startVector`.
|
|
*
|
|
* @returns {flatbuffers.Offset} The offset at which the newly created array
|
|
* starts.
|
|
*/
|
|
flatbuffers.Builder.prototype.endVector = function() {
|
|
this.writeInt32(this.vector_num_elems);
|
|
return this.offset();
|
|
};
|
|
/// @endcond
|
|
|
|
/**
|
|
* Encode the string `s` in the buffer using UTF-8. If a Uint8Array is passed
|
|
* instead of a string, it is assumed to contain valid UTF-8 encoded data.
|
|
*
|
|
* @param {string|Uint8Array} s The string to encode
|
|
* @return {flatbuffers.Offset} The offset in the buffer where the encoded string starts
|
|
*/
|
|
flatbuffers.Builder.prototype.createString = function(s) {
|
|
if (s instanceof Uint8Array) {
|
|
var utf8 = s;
|
|
} else {
|
|
var utf8 = [];
|
|
var i = 0;
|
|
|
|
while (i < s.length) {
|
|
var codePoint;
|
|
|
|
// Decode UTF-16
|
|
var a = s.charCodeAt(i++);
|
|
if (a < 0xD800 || a >= 0xDC00) {
|
|
codePoint = a;
|
|
} else {
|
|
var b = s.charCodeAt(i++);
|
|
codePoint = (a << 10) + b + (0x10000 - (0xD800 << 10) - 0xDC00);
|
|
}
|
|
|
|
// Encode UTF-8
|
|
if (codePoint < 0x80) {
|
|
utf8.push(codePoint);
|
|
} else {
|
|
if (codePoint < 0x800) {
|
|
utf8.push(((codePoint >> 6) & 0x1F) | 0xC0);
|
|
} else {
|
|
if (codePoint < 0x10000) {
|
|
utf8.push(((codePoint >> 12) & 0x0F) | 0xE0);
|
|
} else {
|
|
utf8.push(
|
|
((codePoint >> 18) & 0x07) | 0xF0,
|
|
((codePoint >> 12) & 0x3F) | 0x80);
|
|
}
|
|
utf8.push(((codePoint >> 6) & 0x3F) | 0x80);
|
|
}
|
|
utf8.push((codePoint & 0x3F) | 0x80);
|
|
}
|
|
}
|
|
}
|
|
|
|
this.addInt8(0);
|
|
this.startVector(1, utf8.length, 1);
|
|
this.bb.setPosition(this.space -= utf8.length);
|
|
for (var i = 0, offset = this.space, bytes = this.bb.bytes(); i < utf8.length; i++) {
|
|
bytes[offset++] = utf8[i];
|
|
}
|
|
return this.endVector();
|
|
};
|
|
|
|
/**
|
|
* A helper function to avoid generated code depending on this file directly.
|
|
*
|
|
* @param {number} low
|
|
* @param {number} high
|
|
* @returns {!flatbuffers.Long}
|
|
*/
|
|
flatbuffers.Builder.prototype.createLong = function(low, high) {
|
|
return flatbuffers.Long.create(low, high);
|
|
};
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @cond FLATBUFFERS_INTERNAL
|
|
/**
|
|
* Create a new ByteBuffer with a given array of bytes (`Uint8Array`).
|
|
*
|
|
* @constructor
|
|
* @param {Uint8Array} bytes
|
|
*/
|
|
flatbuffers.ByteBuffer = function(bytes) {
|
|
/**
|
|
* @type {Uint8Array}
|
|
* @private
|
|
*/
|
|
this.bytes_ = bytes;
|
|
|
|
/**
|
|
* @type {number}
|
|
* @private
|
|
*/
|
|
this.position_ = 0;
|
|
};
|
|
|
|
/**
|
|
* Create and allocate a new ByteBuffer with a given size.
|
|
*
|
|
* @param {number} byte_size
|
|
* @returns {!flatbuffers.ByteBuffer}
|
|
*/
|
|
flatbuffers.ByteBuffer.allocate = function(byte_size) {
|
|
return new flatbuffers.ByteBuffer(new Uint8Array(byte_size));
|
|
};
|
|
|
|
flatbuffers.ByteBuffer.prototype.clear = function() {
|
|
this.position_ = 0;
|
|
};
|
|
|
|
/**
|
|
* Get the underlying `Uint8Array`.
|
|
*
|
|
* @returns {Uint8Array}
|
|
*/
|
|
flatbuffers.ByteBuffer.prototype.bytes = function() {
|
|
return this.bytes_;
|
|
};
|
|
|
|
/**
|
|
* Get the buffer's position.
|
|
*
|
|
* @returns {number}
|
|
*/
|
|
flatbuffers.ByteBuffer.prototype.position = function() {
|
|
return this.position_;
|
|
};
|
|
|
|
/**
|
|
* Set the buffer's position.
|
|
*
|
|
* @param {number} position
|
|
*/
|
|
flatbuffers.ByteBuffer.prototype.setPosition = function(position) {
|
|
this.position_ = position;
|
|
};
|
|
|
|
/**
|
|
* Get the buffer's capacity.
|
|
*
|
|
* @returns {number}
|
|
*/
|
|
flatbuffers.ByteBuffer.prototype.capacity = function() {
|
|
return this.bytes_.length;
|
|
};
|
|
|
|
/**
|
|
* @param {number} offset
|
|
* @returns {number}
|
|
*/
|
|
flatbuffers.ByteBuffer.prototype.readInt8 = function(offset) {
|
|
return this.readUint8(offset) << 24 >> 24;
|
|
};
|
|
|
|
/**
|
|
* @param {number} offset
|
|
* @returns {number}
|
|
*/
|
|
flatbuffers.ByteBuffer.prototype.readUint8 = function(offset) {
|
|
return this.bytes_[offset];
|
|
};
|
|
|
|
/**
|
|
* @param {number} offset
|
|
* @returns {number}
|
|
*/
|
|
flatbuffers.ByteBuffer.prototype.readInt16 = function(offset) {
|
|
return this.readUint16(offset) << 16 >> 16;
|
|
};
|
|
|
|
/**
|
|
* @param {number} offset
|
|
* @returns {number}
|
|
*/
|
|
flatbuffers.ByteBuffer.prototype.readUint16 = function(offset) {
|
|
return this.bytes_[offset] | this.bytes_[offset + 1] << 8;
|
|
};
|
|
|
|
/**
|
|
* @param {number} offset
|
|
* @returns {number}
|
|
*/
|
|
flatbuffers.ByteBuffer.prototype.readInt32 = function(offset) {
|
|
return this.bytes_[offset] | this.bytes_[offset + 1] << 8 | this.bytes_[offset + 2] << 16 | this.bytes_[offset + 3] << 24;
|
|
};
|
|
|
|
/**
|
|
* @param {number} offset
|
|
* @returns {number}
|
|
*/
|
|
flatbuffers.ByteBuffer.prototype.readUint32 = function(offset) {
|
|
return this.readInt32(offset) >>> 0;
|
|
};
|
|
|
|
/**
|
|
* @param {number} offset
|
|
* @returns {!flatbuffers.Long}
|
|
*/
|
|
flatbuffers.ByteBuffer.prototype.readInt64 = function(offset) {
|
|
return new flatbuffers.Long(this.readInt32(offset), this.readInt32(offset + 4));
|
|
};
|
|
|
|
/**
|
|
* @param {number} offset
|
|
* @returns {!flatbuffers.Long}
|
|
*/
|
|
flatbuffers.ByteBuffer.prototype.readUint64 = function(offset) {
|
|
return new flatbuffers.Long(this.readUint32(offset), this.readUint32(offset + 4));
|
|
};
|
|
|
|
/**
|
|
* @param {number} offset
|
|
* @returns {number}
|
|
*/
|
|
flatbuffers.ByteBuffer.prototype.readFloat32 = function(offset) {
|
|
flatbuffers.int32[0] = this.readInt32(offset);
|
|
return flatbuffers.float32[0];
|
|
};
|
|
|
|
/**
|
|
* @param {number} offset
|
|
* @returns {number}
|
|
*/
|
|
flatbuffers.ByteBuffer.prototype.readFloat64 = function(offset) {
|
|
flatbuffers.int32[flatbuffers.isLittleEndian ? 0 : 1] = this.readInt32(offset);
|
|
flatbuffers.int32[flatbuffers.isLittleEndian ? 1 : 0] = this.readInt32(offset + 4);
|
|
return flatbuffers.float64[0];
|
|
};
|
|
|
|
/**
|
|
* @param {number} offset
|
|
* @param {number|boolean} value
|
|
*/
|
|
flatbuffers.ByteBuffer.prototype.writeInt8 = function(offset, value) {
|
|
this.bytes_[offset] = /** @type {number} */(value);
|
|
};
|
|
|
|
/**
|
|
* @param {number} offset
|
|
* @param {number} value
|
|
*/
|
|
flatbuffers.ByteBuffer.prototype.writeUint8 = function(offset, value) {
|
|
this.bytes_[offset] = value;
|
|
};
|
|
|
|
/**
|
|
* @param {number} offset
|
|
* @param {number} value
|
|
*/
|
|
flatbuffers.ByteBuffer.prototype.writeInt16 = function(offset, value) {
|
|
this.bytes_[offset] = value;
|
|
this.bytes_[offset + 1] = value >> 8;
|
|
};
|
|
|
|
/**
|
|
* @param {number} offset
|
|
* @param {number} value
|
|
*/
|
|
flatbuffers.ByteBuffer.prototype.writeUint16 = function(offset, value) {
|
|
this.bytes_[offset] = value;
|
|
this.bytes_[offset + 1] = value >> 8;
|
|
};
|
|
|
|
/**
|
|
* @param {number} offset
|
|
* @param {number} value
|
|
*/
|
|
flatbuffers.ByteBuffer.prototype.writeInt32 = function(offset, value) {
|
|
this.bytes_[offset] = value;
|
|
this.bytes_[offset + 1] = value >> 8;
|
|
this.bytes_[offset + 2] = value >> 16;
|
|
this.bytes_[offset + 3] = value >> 24;
|
|
};
|
|
|
|
/**
|
|
* @param {number} offset
|
|
* @param {number} value
|
|
*/
|
|
flatbuffers.ByteBuffer.prototype.writeUint32 = function(offset, value) {
|
|
this.bytes_[offset] = value;
|
|
this.bytes_[offset + 1] = value >> 8;
|
|
this.bytes_[offset + 2] = value >> 16;
|
|
this.bytes_[offset + 3] = value >> 24;
|
|
};
|
|
|
|
/**
|
|
* @param {number} offset
|
|
* @param {flatbuffers.Long} value
|
|
*/
|
|
flatbuffers.ByteBuffer.prototype.writeInt64 = function(offset, value) {
|
|
this.writeInt32(offset, value.low);
|
|
this.writeInt32(offset + 4, value.high);
|
|
};
|
|
|
|
/**
|
|
* @param {number} offset
|
|
* @param {flatbuffers.Long} value
|
|
*/
|
|
flatbuffers.ByteBuffer.prototype.writeUint64 = function(offset, value) {
|
|
this.writeUint32(offset, value.low);
|
|
this.writeUint32(offset + 4, value.high);
|
|
};
|
|
|
|
/**
|
|
* @param {number} offset
|
|
* @param {number} value
|
|
*/
|
|
flatbuffers.ByteBuffer.prototype.writeFloat32 = function(offset, value) {
|
|
flatbuffers.float32[0] = value;
|
|
this.writeInt32(offset, flatbuffers.int32[0]);
|
|
};
|
|
|
|
/**
|
|
* @param {number} offset
|
|
* @param {number} value
|
|
*/
|
|
flatbuffers.ByteBuffer.prototype.writeFloat64 = function(offset, value) {
|
|
flatbuffers.float64[0] = value;
|
|
this.writeInt32(offset, flatbuffers.int32[flatbuffers.isLittleEndian ? 0 : 1]);
|
|
this.writeInt32(offset + 4, flatbuffers.int32[flatbuffers.isLittleEndian ? 1 : 0]);
|
|
};
|
|
|
|
/**
|
|
* Return the file identifier. Behavior is undefined for FlatBuffers whose
|
|
* schema does not include a file_identifier (likely points at padding or the
|
|
* start of a the root vtable).
|
|
* @returns {string}
|
|
*/
|
|
flatbuffers.ByteBuffer.prototype.getBufferIdentifier = function() {
|
|
if (this.bytes_.length < this.position_ + flatbuffers.SIZEOF_INT +
|
|
flatbuffers.FILE_IDENTIFIER_LENGTH) {
|
|
throw new Error(
|
|
'FlatBuffers: ByteBuffer is too short to contain an identifier.');
|
|
}
|
|
var result = "";
|
|
for (var i = 0; i < flatbuffers.FILE_IDENTIFIER_LENGTH; i++) {
|
|
result += String.fromCharCode(
|
|
this.readInt8(this.position_ + flatbuffers.SIZEOF_INT + i));
|
|
}
|
|
return result;
|
|
};
|
|
|
|
/**
|
|
* Look up a field in the vtable, return an offset into the object, or 0 if the
|
|
* field is not present.
|
|
*
|
|
* @param {number} bb_pos
|
|
* @param {number} vtable_offset
|
|
* @returns {number}
|
|
*/
|
|
flatbuffers.ByteBuffer.prototype.__offset = function(bb_pos, vtable_offset) {
|
|
var vtable = bb_pos - this.readInt32(bb_pos);
|
|
return vtable_offset < this.readInt16(vtable) ? this.readInt16(vtable + vtable_offset) : 0;
|
|
};
|
|
|
|
/**
|
|
* Initialize any Table-derived type to point to the union at the given offset.
|
|
*
|
|
* @param {flatbuffers.Table} t
|
|
* @param {number} offset
|
|
* @returns {flatbuffers.Table}
|
|
*/
|
|
flatbuffers.ByteBuffer.prototype.__union = function(t, offset) {
|
|
t.bb_pos = offset + this.readInt32(offset);
|
|
t.bb = this;
|
|
return t;
|
|
};
|
|
|
|
/**
|
|
* Create a JavaScript string from UTF-8 data stored inside the FlatBuffer.
|
|
* This allocates a new string and converts to wide chars upon each access.
|
|
*
|
|
* To avoid the conversion to UTF-16, pass flatbuffers.Encoding.UTF8_BYTES as
|
|
* the "optionalEncoding" argument. This is useful for avoiding conversion to
|
|
* and from UTF-16 when the data will just be packaged back up in another
|
|
* FlatBuffer later on.
|
|
*
|
|
* @param {number} offset
|
|
* @param {flatbuffers.Encoding=} opt_encoding Defaults to UTF16_STRING
|
|
* @returns {string|!Uint8Array}
|
|
*/
|
|
flatbuffers.ByteBuffer.prototype.__string = function(offset, opt_encoding) {
|
|
offset += this.readInt32(offset);
|
|
|
|
var length = this.readInt32(offset);
|
|
var result = '';
|
|
var i = 0;
|
|
|
|
offset += flatbuffers.SIZEOF_INT;
|
|
|
|
if (opt_encoding === flatbuffers.Encoding.UTF8_BYTES) {
|
|
return this.bytes_.subarray(offset, offset + length);
|
|
}
|
|
|
|
while (i < length) {
|
|
var codePoint;
|
|
|
|
// Decode UTF-8
|
|
var a = this.readUint8(offset + i++);
|
|
if (a < 0xC0) {
|
|
codePoint = a;
|
|
} else {
|
|
var b = this.readUint8(offset + i++);
|
|
if (a < 0xE0) {
|
|
codePoint =
|
|
((a & 0x1F) << 6) |
|
|
(b & 0x3F);
|
|
} else {
|
|
var c = this.readUint8(offset + i++);
|
|
if (a < 0xF0) {
|
|
codePoint =
|
|
((a & 0x0F) << 12) |
|
|
((b & 0x3F) << 6) |
|
|
(c & 0x3F);
|
|
} else {
|
|
var d = this.readUint8(offset + i++);
|
|
codePoint =
|
|
((a & 0x07) << 18) |
|
|
((b & 0x3F) << 12) |
|
|
((c & 0x3F) << 6) |
|
|
(d & 0x3F);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Encode UTF-16
|
|
if (codePoint < 0x10000) {
|
|
result += String.fromCharCode(codePoint);
|
|
} else {
|
|
codePoint -= 0x10000;
|
|
result += String.fromCharCode(
|
|
(codePoint >> 10) + 0xD800,
|
|
(codePoint & ((1 << 10) - 1)) + 0xDC00);
|
|
}
|
|
}
|
|
|
|
return result;
|
|
};
|
|
|
|
/**
|
|
* Retrieve the relative offset stored at "offset"
|
|
* @param {number} offset
|
|
* @returns {number}
|
|
*/
|
|
flatbuffers.ByteBuffer.prototype.__indirect = function(offset) {
|
|
return offset + this.readInt32(offset);
|
|
};
|
|
|
|
/**
|
|
* Get the start of data of a vector whose offset is stored at "offset" in this object.
|
|
*
|
|
* @param {number} offset
|
|
* @returns {number}
|
|
*/
|
|
flatbuffers.ByteBuffer.prototype.__vector = function(offset) {
|
|
return offset + this.readInt32(offset) + flatbuffers.SIZEOF_INT; // data starts after the length
|
|
};
|
|
|
|
/**
|
|
* Get the length of a vector whose offset is stored at "offset" in this object.
|
|
*
|
|
* @param {number} offset
|
|
* @returns {number}
|
|
*/
|
|
flatbuffers.ByteBuffer.prototype.__vector_len = function(offset) {
|
|
return this.readInt32(offset + this.readInt32(offset));
|
|
};
|
|
|
|
/**
|
|
* @param {string} ident
|
|
* @returns {boolean}
|
|
*/
|
|
flatbuffers.ByteBuffer.prototype.__has_identifier = function(ident) {
|
|
if (ident.length != flatbuffers.FILE_IDENTIFIER_LENGTH) {
|
|
throw new Error('FlatBuffers: file identifier must be length ' +
|
|
flatbuffers.FILE_IDENTIFIER_LENGTH);
|
|
}
|
|
for (var i = 0; i < flatbuffers.FILE_IDENTIFIER_LENGTH; i++) {
|
|
if (ident.charCodeAt(i) != this.readInt8(this.position_ + flatbuffers.SIZEOF_INT + i)) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
};
|
|
|
|
/**
|
|
* A helper function to avoid generated code depending on this file directly.
|
|
*
|
|
* @param {number} low
|
|
* @param {number} high
|
|
* @returns {!flatbuffers.Long}
|
|
*/
|
|
flatbuffers.ByteBuffer.prototype.createLong = function(low, high) {
|
|
return flatbuffers.Long.create(low, high);
|
|
};
|
|
|
|
// Exports for Node.js and RequireJS
|
|
|
|
|
|
/// @endcond
|
|
/// @}
|
|
|
|
|
|
/***/ })
|
|
|
|
/******/ });
|
|
/************************************************************************/
|
|
/******/ // The module cache
|
|
/******/ var __webpack_module_cache__ = {};
|
|
/******/
|
|
/******/ // The require function
|
|
/******/ function __webpack_require__(moduleId) {
|
|
/******/ // Check if module is in cache
|
|
/******/ var cachedModule = __webpack_module_cache__[moduleId];
|
|
/******/ if (cachedModule !== undefined) {
|
|
/******/ return cachedModule.exports;
|
|
/******/ }
|
|
/******/ // Create a new module (and put it into the cache)
|
|
/******/ var module = __webpack_module_cache__[moduleId] = {
|
|
/******/ // no module.id needed
|
|
/******/ // no module.loaded needed
|
|
/******/ exports: {}
|
|
/******/ };
|
|
/******/
|
|
/******/ // Execute the module function
|
|
/******/ __webpack_modules__[moduleId].call(module.exports, module, module.exports, __webpack_require__);
|
|
/******/
|
|
/******/ // Return the exports of the module
|
|
/******/ return module.exports;
|
|
/******/ }
|
|
/******/
|
|
/************************************************************************/
|
|
/******/ /* webpack/runtime/compat get default export */
|
|
/******/ (() => {
|
|
/******/ // getDefaultExport function for compatibility with non-harmony modules
|
|
/******/ __webpack_require__.n = (module) => {
|
|
/******/ var getter = module && module.__esModule ?
|
|
/******/ () => (module['default']) :
|
|
/******/ () => (module);
|
|
/******/ __webpack_require__.d(getter, { a: getter });
|
|
/******/ return getter;
|
|
/******/ };
|
|
/******/ })();
|
|
/******/
|
|
/******/ /* webpack/runtime/define property getters */
|
|
/******/ (() => {
|
|
/******/ // define getter functions for harmony exports
|
|
/******/ __webpack_require__.d = (exports, definition) => {
|
|
/******/ for(var key in definition) {
|
|
/******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
|
|
/******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
|
|
/******/ }
|
|
/******/ }
|
|
/******/ };
|
|
/******/ })();
|
|
/******/
|
|
/******/ /* webpack/runtime/global */
|
|
/******/ (() => {
|
|
/******/ __webpack_require__.g = (function() {
|
|
/******/ if (typeof globalThis === 'object') return globalThis;
|
|
/******/ try {
|
|
/******/ return this || new Function('return this')();
|
|
/******/ } catch (e) {
|
|
/******/ if (typeof window === 'object') return window;
|
|
/******/ }
|
|
/******/ })();
|
|
/******/ })();
|
|
/******/
|
|
/******/ /* webpack/runtime/hasOwnProperty shorthand */
|
|
/******/ (() => {
|
|
/******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))
|
|
/******/ })();
|
|
/******/
|
|
/******/ /* webpack/runtime/make namespace object */
|
|
/******/ (() => {
|
|
/******/ // define __esModule on exports
|
|
/******/ __webpack_require__.r = (exports) => {
|
|
/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
|
|
/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
/******/ }
|
|
/******/ Object.defineProperty(exports, '__esModule', { value: true });
|
|
/******/ };
|
|
/******/ })();
|
|
/******/
|
|
/************************************************************************/
|
|
/******/
|
|
/******/ // startup
|
|
/******/ // Load entry module and return exports
|
|
/******/ // This entry module is referenced by other modules so it can't be inlined
|
|
/******/ var __webpack_exports__ = __webpack_require__("./lib/index.ts");
|
|
/******/
|
|
/******/ return __webpack_exports__;
|
|
/******/ })()
|
|
;
|
|
});
|
|
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib3J0LmpzIiwibWFwcGluZ3MiOiI7Ozs7O0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQztBQUNEOzs7Ozs7Ozs7Ozs7Ozs7QUNWQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ087QUFDUDtBQUNBO0FBQ0E7QUFDQSwrQkFBK0I7QUFDL0I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSw0REFBNEQsS0FBSyxtQkFBbUIsU0FBUztBQUM3RjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDRCQUE0QixxQ0FBcUM7QUFDakU7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDTztBQUNQO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDBCQUEwQixtQ0FBbUM7QUFDN0Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esa0NBQWtDLDJCQUEyQjtBQUM3RDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esd0RBQXdELG9CQUFvQixPQUFPLElBQUksTUFBTSxjQUFjO0FBQzNHO0FBQ0E7Ozs7Ozs7Ozs7Ozs7Ozs7QUN4RkE7QUFDQTtBQUNpRDtBQUNqRDs7Ozs7Ozs7Ozs7Ozs7O0FDSEE7QUFDQTtBQUNPO0FBQ1A7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDBEQUEwRCxNQUFNO0FBQ2hFO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7Ozs7Ozs7Ozs7QUN0QkE7QUFDQTtBQUNxQztBQUNyQztBQUNBO0FBQ0E7QUFDTyxnQkFBZ0IsOENBQU87QUFDOUI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FDUEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUMwQjtBQUNKO0FBQ2M7QUFDWDtBQUNJO0FBQzdCOzs7Ozs7Ozs7Ozs7Ozs7OztBQ3RCQTtBQUNBO0FBQ2dEO0FBQ2Q7QUFDM0I7QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDRFQUE0RSwyQ0FBTTtBQUNsRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsZ0NBQWdDLDJDQUFNO0FBQ3RDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esd0ZBQXdGLEtBQUs7QUFDN0Y7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsdURBQXVELDJDQUFNO0FBQzdEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsMENBQTBDLEtBQUs7QUFDL0M7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSx1Q0FBdUMsMkNBQU07QUFDN0M7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7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Q0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FB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Q3JCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSyxLQUFLO0FBQ1Y7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLLEtBQUs7QUFDVjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsY0FBYztB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QUFDQSxVQUFVO0FBQ1Y7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsVUFBVTtBQUNWO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsVUFBVTtBQUNWO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFVBQVU7QUFDVjtBQUNBO0FBQ0E7QUFDQTtBQUNBLFVBQVU7QUFDVjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxVQUFVO0FBQ1Y7QUFDQTtBQUNBO0FBQ0E7QUFDQSxVQUFVO0FBQ1Y7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsVUFBVTtBQUNWO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsVUFBVTtBQUNWO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFVBQVU7QUFDVjtBQUNBO0FBQ0E7QUFDQTtBQUNBLFVBQVU7QUFDVjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxVQUFVO0FBQ1Y7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXLFNBQVM7QUFDcEIsYUFBYTtBQUNiO0FBQ0EsWUFBWSxZQUFZO0FBQ3hCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsNkJBQTZCO0FBQzdCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsVUFBVTtBQUNWO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYSxRQUFRO0FBQ3JCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYSxRQUFRO0FBQ3JCO0FBQ0E7QUFD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QUFDQTtBQUNBO0FBQ0EsbUNBQW1DO0FBQ25DLGVBQWUsT0FBTztBQUN0QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsTUFBTTtBQUNOLGVBQWUsT0FBTztBQUN0QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhLE1BQU07QUFDbkI7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhLE1BQU07QUFDbkI7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhLE1BQU07QUFDbkI7O0FBRUE7QUFDQTtBQUNBLGFBQWEsU0FBUztBQUN0QjtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxxQ0FBcUM7QUFDckM7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsYUFBYSxRQUFRO0FBQ3JCO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLGFBQWEsUUFBUTtBQUNyQjtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYSxNQUFNO0FBQ25COztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYSxNQUFNO0FBQ25COztBQUVBO0FBQ0E7QUFDQTtBQUNBLGFBQWEsUUFBUTtBQUNyQjtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxhQUFhLFFBQVE7QUFDckI7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLGFBQWEsWUFBWTtBQUN6QjtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FB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QUFJLENBQUMsTUFBTSxLQUFLLENBQUMsSUFBSSxDQUFDLENBQUMsSUFBSSxDQUFDLE1BQU0sS0FBSyxDQUFDLElBQUksSUFBSSxDQUFDLElBQUksQ0FBQyxNQUFNLEtBQUssQ0FBQztRQUM3RixJQUFJLENBQUMsSUFBSSxDQUFDLE1BQU0sS0FBSyxDQUFDLEVBQUU7UUFDMUIsTUFBTSxJQUFJLEtBQUssQ0FBQyxzQkFBc0IsQ0FBQyxDQUFDO0tBQ3pDO0lBQ0QsSUFBSSxLQUFLLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxJQUFJLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUM7UUFDcEYsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFO1FBQzlCLE1BQU0sSUFBSSxLQUFLLENBQUMsc0JBQXNCLENBQUMsQ0FBQztLQUN6QztJQUNELElBQUksQ0FBQyxDQUFDLENBQUMsSUFBSSxLQUFLLFNBQVMsSUFBSSxDQUFDLENBQUMsSUFBSSxLQUFLLFNBQVMsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksS0FBSyxTQUFTLElBQUksS0FBSyxDQUFDLElBQUksS0FBSyxTQUFTLENBQUM7UUFDeEcsQ0FBQyxDQUFDLENBQUMsSUFBSSxLQUFLLFNBQVMsSUFBSSxDQUFDLENBQUMsSUFBSSxLQUFLLFNBQVMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksS0FBSyxTQUFTLElBQUksSUFBSSxDQUFDLElBQUksS0FBSyxTQUFTLENBQUM7UUFDdEcsQ0FBQyxJQUFJLENBQUMsSUFBSSxLQUFLLFNBQVMsSUFBSSxJQUFJLENBQUMsSUFBSSxLQUFLLFNBQVMsQ0FBQyxFQUFF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cUIsQ0FBQyxDQUFDO0tBQ3hDO0lBQ0QsSUFBSSxDQUFDLFVBQVUsQ0FBQyxXQUFXLElBQUksTUFBTSxDQUFDLE1BQU0sS0FBSyxDQUFDLEVBQUU7UUFDbEQsTUFBTSxJQUFJLEtBQUssQ0FBQyx3QkFBd0IsQ0FBQyxDQUFDO0tBQzNDO0lBRUQsMkNBQTJDO0lBQzNDLElBQUksTUFBTSxDQUFDLE1BQU0sS0FBSyxDQUFDLElBQUksTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxNQUFNLEtBQUssQ0FBQyxJQUFJLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsTUFBTSxLQUFLLENBQUMsRUFBRTtRQUNyRixNQUFNLElBQUksS0FBSyxDQUFDLDBCQUEwQixDQUFDLENBQUM7S0FDN0M7SUFFRCxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksS0FBSyxTQUFTLElBQUksTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksS0FBSyxTQUFTLENBQUM7UUFDOUQsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxLQUFLLFNBQVMsSUFBSSxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxLQUFLLFNBQVMsQ0FBQztRQUM5RCxDQUFDLE1BQU0sQ0FBQyxNQUFNLEtBQUssQ0FBQyxJQUFJLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLEtBQUssU0FBUyxJQUFJLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLEtBQUssU0FBUyxDQUFDLEVBQUU7UUFDekYsTUFBTSxJQUFJLEtBQUssQ0FBQyxxQkFBcUIsQ0FBQyxDQUFDO0tBQ3hDO0lBRUQsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLEtBQUssTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLE1BQU0sS0FBSyxDQUFDLElBQUksTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksS0FBSyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLEVBQUU7UUFDckcsTUFBTSxJQUFJLEtBQUssQ0FBQyw0QkFBNEIsQ0FBQyxDQUFDO0tBQy9DO0FBQ0gsQ0FBQyxDQUFDOzs7Ozs7Ozs7Ozs7O0FDeElGLDREQUE0RDtBQUM1RCxrQ0FBa0M7OztBQUdsQyw4R0FBdUM7QUFFdkMsNEZBQXNGO0FBR3RGLHVIQUFrRDtBQUVsRCxNQUFNLGlDQUFpQyxHQUFHLENBQUMsU0FBaUIsRUFBRSxFQUFFLENBQUMsQ0FBQztJQUNoRSxJQUFJLEVBQUUsaUJBQWlCO0lBQ3ZCLFVBQVUsRUFBRSxDQUFDLEdBQUcsQ0FBQztJQUNqQixVQUFVLEVBQUUsQ0FBQyxtQkFBVyxDQUFDLE1BQU0sQ0FBQztJQUNoQyxTQUFTO0NBQ1YsQ0FBQyxDQUFDO0FBRUgsTUFBTSw2QkFBNkIsR0FDL0IsQ0FBQyxnQkFBdUMsRUFBRSxRQUF5QixFQUFFLENBQVMsRUFBRSxDQUFTLEVBQ3hGLFdBQThCLEVBQUUsVUFBMEIsRUFBZSxFQUFFO0lBQzFFLE1BQU0sTUFBTSxHQUFHLENBQUMsQ0FBQyxJQUFJLENBQUM7SUFDdEIsTUFBTSxNQUFNLEdBQUcsQ0FBQyxDQUFDLElBQUksQ0FBQztJQUN0QixNQUFNLE1BQU0sR0FBRyxDQUFDLENBQUM7SUFDakIsTUFBTSxNQUFNLEdBQUcsQ0FBQyxDQUFDO0lBQ2pCLE1BQU0sSUFBSSxHQUFHLFdBQVcsQ0FBQyxNQUFNLENBQUM7SUFDaEMsTUFBTSxXQUFXLEdBQUcsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLEdBQUcsTUFBTSxDQUFDLENBQUMsQ0FBQyxHQUFHLE1BQU0sQ0FBQyxDQUFDLENBQUMsRUFBRSxXQUFXLENBQUMsQ0FBQyxDQUFDLEdBQUcsV0FBVyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDekYsTUFBTSxVQUFVLEdBQUcsTUFBTSxDQUFDLENBQUMsQ0FBQyxHQUFHLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUN6QyxNQUFNLGFBQWEsR0FBRyxxQ0FBaUIsR0FBRSxDQUFDO0lBQzFDLE1BQU0sSUFBSSxHQUFHLHlCQUFPLEVBQUMsZ0JBQWdCLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxTQUFTLENBQUMsT0FBTyxDQUFDLENBQUM7SUFDekUsSUFBSSxRQUFRLEdBQUcsRUFBRSxDQUFDO0lBRWxCLEtBQUssSUFBSSxHQUFHLEdBQUcsQ0FBQyxFQUFFLEdBQUcsSUFBSSxDQUFDLEVBQUUsR0FBRyxFQUFFLEVBQUU7UUFDakMsS0FBSyxJQUFJLEdBQUcsR0FBRyxDQUFDLEVBQUUsR0FBRyxJQUFJLENBQUMsRUFBRSxHQUFHLEVBQUUsRUFBRTtZQUNqQyxRQUFRLElBQUk7a0NBQ1ksR0FBRzsyQkFDVixHQUFHOzs4QkFFQSxXQUFXLENBQUMsQ0FBQyxDQUFDLGFBQWEsV0FBVyxDQUFDLENBQUMsQ0FBQzs0Q0FDM0IsV0FBVyxDQUFDLElBQUksR0FBRyxDQUFDLENBQUMsUUFBUSxVQUFVLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQztrQkFDNUUsVUFBVSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUM7K0JBQ0wsVUFBVSxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsaUJBQWlCLFVBQVUsT0FBTyxNQUFNLENBQUMsQ0FBQyxDQUFDOzt3QkFFekUsTUFBTSxDQUFDLE1BQU0sQ0FBQzs2Q0FDTyxXQUFXLENBQUMsSUFBSSxHQUFHLENBQUMsQ0FBQyxPQUFPLFVBQVUsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDO29CQUMxRSxVQUFVLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQztpQ0FDTCxVQUFVLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxxQkFBcUIsVUFBVSxNQUFNLE1BQU0sQ0FBQyxDQUFDLENBQUM7OzBCQUU1RSxNQUFNLENBQUMsTUFBTSxDQUFDOzt5Q0FFQyxVQUFVOzs2QkFFdEIsR0FBRyxHQUFHLENBQUMsR0FBRyxHQUFHOzs7Ozs7O1dBTy9CLENBQUM7U0FDSDtLQUNGO0lBRUQsTUFBTSxZQUFZLEdBQUc7UUFDbkIsYUFBYTs7Ozs7OztZQU9ULFFBQVE7WUFDUixJQUFJLENBQUMsTUFBTTs7YUFFVixDQUFDO0lBQ1IsdUNBQ0ssUUFBUSxLQUNYLE1BQU0sRUFBRSxFQUFDLElBQUksRUFBRSxXQUFXLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQyxJQUFJLEVBQUUsV0FBVyxFQUFFLG1CQUFXLENBQUMsTUFBTSxFQUFDLEVBQzFFLFlBQVksRUFDWixPQUFPLEVBQUUsSUFBSSxJQUNiO0FBQ0osQ0FBQyxDQUFDO0FBRUMsTUFBTSxtQ0FBbUMsR0FDNUMsQ0FBQyxnQkFBdUMsRUFBRSxDQUFTLEVBQUUsQ0FBUyxFQUFFLFdBQThCLEVBQzdGLFVBQTBCLEVBQXFCLEVBQUU7SUFDaEQsTUFBTSxRQUFRLEdBQUcsaUNBQWlDLENBQUMsVUFBVSxDQUFDLFFBQVEsQ0FBQyxDQUFDO0lBQ3hFLHVDQUNLLFFBQVEsS0FDWCxHQUFHLEVBQUUsR0FBRyxFQUFFLENBQUMsNkJBQTZCLENBQUMsZ0JBQWdCLEVBQUUsUUFBUSxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsV0FBVyxFQUFFLFVBQVUsQ0FBQyxJQUNuRztBQUNKLENBQUMsQ0FBQztBQVJPLDJDQUFtQyx1Q0FRMUM7Ozs7Ozs7Ozs7Ozs7QUMzRk4sNERBQTREO0FBQzVELGtDQUFrQzs7O0FBSWxDLDRGQUFzRjtBQUl0RixNQUFNLDJCQUEyQixHQUFHLENBQUMsU0FBaUIsRUFBRSxFQUFFLENBQUMsQ0FBQztJQUMxRCxJQUFJLEVBQUUsUUFBUTtJQUNkLFVBQVUsRUFBRSxDQUFDLEdBQUcsQ0FBQztJQUNqQixVQUFVLEVBQUUsQ0FBQyxtQkFBVyxDQUFDLFFBQVEsQ0FBQztJQUNsQyxTQUFTO0NBQ1YsQ0FBQyxDQUFDO0FBRUgsTUFBTSx1QkFBdUIsR0FDekIsQ0FBQyxnQkFBdUMsRUFBRSxRQUF5QixFQUFFLENBQVMsRUFBRSxDQUFTLEVBQ3hGLFdBQThCLEVBQUUsVUFBMEIsRUFBZSxFQUFFO0lBQzFFLE1BQU0sTUFBTSxHQUFHLENBQUMsQ0FBQyxJQUFJLENBQUM7SUFDdEIsTUFBTSxNQUFNLEdBQUcsQ0FBQyxDQUFDLElBQUksQ0FBQztJQUV0QixNQUFNLElBQUksR0FBRyxXQUFXLENBQUMsTUFBTSxDQUFDO0lBQ2hDLE1BQU0sVUFBVSxHQUFHLCtCQUFtQixFQUFDLE1BQU0sRUFBRSxNQUFNLEVBQUUsV0FBVyxFQUFFLENBQUMsQ0FBQyxDQUFDO0lBRXZFLE1BQU0sWUFBWSxHQUFHO3lCQUNGLE1BQU0sQ0FBQyxDQUFDLENBQUM7eUJBQ1QsTUFBTSxDQUFDLENBQUMsQ0FBQzt5QkFDVCxNQUFNLENBQUMsQ0FBQyxDQUFDO3lCQUNULFVBQVUsQ0FBQyxXQUFXLENBQUMsQ0FBQyxDQUFDO3lCQUN6QixVQUFVLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBQztnQ0FDbEIsVUFBVSxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUM7Z0NBQ3ZCLFVBQVUsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDOzhCQUN6QixVQUFVLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQzs4QkFDckIsVUFBVSxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUM7MkJBQ3hCLFVBQVUsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDOzJCQUNsQixVQUFVLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQzs7OzttQ0FJVixJQUFJOzs7Ozs7Ozs7Ozs7O3NCQWFqQixNQUFNLENBQUMsTUFBTTs7Ozs7Ozs7Ozs7Ozs7OztTQWdCMUIsQ0FBQztJQUNKLHVDQUNLLFFBQVEsS0FDWCxNQUFNLEVBQUUsRUFBQyxJQUFJLEVBQUUsVUFBVSxFQUFFLElBQUksRUFBRSxDQUFDLENBQUMsSUFBSSxFQUFFLFdBQVcsRUFBRSxtQkFBVyxDQUFDLG1CQUFtQixFQUFDLEVBQ3RGLFlBQVksSUFDWjtBQUNKLENBQUMsQ0FBQztBQUVDLE1BQU0sNkJBQTZCLEdBQ3RDLENBQUMsZ0JBQXVDLEVBQUUsQ0FBUyxFQUFFLENBQVMsRUFBRSxXQUE4QixFQUM3RixVQUEwQixFQUFxQixFQUFFO0lBQ2hELE1BQU0sUUFBUSxHQUFHLDJCQUEyQixDQUFDLFVBQVUsQ0FBQyxRQUFRLENBQUMsQ0FBQztJQUNsRSx1Q0FDSyxRQUFRLEtBQ1gsR0FBRyxFQUFFLEdBQUcsRUFBRSxDQUFDLHVCQUF1QixDQUFDLGdCQUFnQixFQUFFLFFBQVEsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLFdBQVcsRUFBRSxVQUFVLENBQUMsSUFDN0Y7QUFDSixDQUFDLENBQUM7QUFSTyxxQ0FBNkIsaUNBUXBDO0FBR0MsTUFBTSxtQkFBbUIsR0FDNUIsQ0FBQyxVQUE2QixFQUFFLFdBQThCLEVBQUUsV0FBOEIsRUFBRSxRQUFRLEdBQUcsQ0FBQyxFQUMvRixFQUFFLENBQ1AsQ0FBQyxXQUFXLENBQUMsQ0FBQyxDQUFDLEVBQUUsV0FBVyxDQUFDLENBQUMsQ0FBQyxFQUFFLFdBQVcsQ0FBQyxDQUFDLENBQUM7SUFDOUMsSUFBSSxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDLEdBQUcsV0FBVyxDQUFDLENBQUMsQ0FBQyxHQUFHLFdBQVcsQ0FBQyxDQUFDLENBQUMsR0FBRyxRQUFRLENBQUMsQ0FBQyxDQUFDO0FBSnZFLDJCQUFtQix1QkFJb0Q7Ozs7Ozs7Ozs7Ozs7QUM1RnBGLDREQUE0RDtBQUM1RCxrQ0FBa0M7OztBQUVsQyw0SUFBcUc7QUFLckcsNEZBQXNGO0FBTy9FLE1BQU0sV0FBVyxHQUNwQixDQUFDLGdCQUF1QyxFQUFFLE1BQWdCLEVBQUUsVUFBaUMsRUFBWSxFQUFFO0lBQ3pHLGNBQWMsQ0FBQyxNQUFNLENBQUMsQ0FBQztJQUN2QixNQUFNLE1BQU0sR0FDUixnQkFBZ0IsQ0FBQyxHQUFHLENBQUMsa0NBQWtDLENBQUMsZ0JBQWdCLEVBQUUsTUFBTSxFQUFFLFVBQVUsQ0FBQyxFQUFFLE1BQU0sQ0FBQyxDQUFDO0lBQzNHLE9BQU8sQ0FBQyxNQUFNLENBQUMsQ0FBQztBQUNsQixDQUFDLENBQUM7QUFOTyxtQkFBVyxlQU1sQjtBQUVDLE1BQU0sMEJBQTBCLEdBQ25DLENBQUMsSUFBZ0IsRUFBeUIsRUFBRTtJQUMxQyxNQUFNLEtBQUssR0FBRyxJQUFJLENBQUMsVUFBVSxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsQ0FBQztJQUNoRCxNQUFNLElBQUksR0FBRyxJQUFJLENBQUMsVUFBVSxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsQ0FBQztJQUMvQyxPQUFPLDBEQUEyQixFQUFDLEVBQUMsS0FBSyxFQUFFLElBQUksRUFBQyxDQUFDLENBQUM7QUFDcEQsQ0FBQyxDQUFDO0FBTE8sa0NBQTBCLDhCQUtqQztBQUVOLE1BQU0sMEJBQTBCLEdBQUc7SUFDakMsSUFBSSxFQUFFLGFBQWE7SUFDbkIsVUFBVSxFQUFFLENBQUMsR0FBRyxDQUFDO0lBQ2pCLFVBQVUsRUFBRSxDQUFDLG1CQUFXLENBQUMsUUFBUSxDQUFDO0NBQ25DLENBQUM7QUFFRixNQUFNLDRCQUE0QixHQUM5QixDQUFDLE9BQThCLEVBQUUsUUFBeUIsRUFBRSxNQUFnQixFQUFFLFVBQWlDLEVBQy9GLEVBQUU7SUFDWixNQUFNLFdBQVcsR0FBRyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLEtBQUssRUFBRSxDQUFDO0lBQzNDLE1BQU0sSUFBSSxHQUFHLFdBQVcsQ0FBQyxNQUFNLENBQUM7SUFDaEMsTUFBTSxhQUFhLEdBQUcsbUJBQW1CLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQztJQUNsRSxNQUFNLFlBQVksR0FBRztRQUN2QixhQUFhO2tDQUNhLElBQUk7O1FBRTlCLENBQUM7SUFDQyx1Q0FDSyxRQUFRLEtBQ1gsTUFBTSxFQUFFLEVBQUMsSUFBSSxFQUFFLFdBQVcsRUFBRSxJQUFJLEVBQUUsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksRUFBRSxXQUFXLEVBQUUsbUJBQVcsQ0FBQyxRQUFRLEVBQUMsRUFDcEYsU0FBUyxFQUFFO1lBQ1QsRUFBQyxJQUFJLEVBQUUsTUFBTSxFQUFFLElBQUksRUFBRSxPQUFPLEVBQUUsV0FBVyxFQUFFLFVBQVUsQ0FBQyxJQUFJLENBQUMsTUFBTSxFQUFFLElBQUksRUFBRSxVQUFVLENBQUMsSUFBSSxFQUFDO1lBQ3pGLEVBQUMsSUFBSSxFQUFFLE9BQU8sRUFBRSxJQUFJLEVBQUUsT0FBTyxFQUFFLElBQUksRUFBRSxVQUFVLENBQUMsS0FBSyxFQUFDO1NBQ3ZELEVBQ0QsWUFBWSxJQUNaO0FBQ0osQ0FBQyxDQUFDO0FBRVYsTUFBTSxrQ0FBa0MsR0FDcEMsQ0FBQyxPQUE4QixFQUFFLE1BQWdCLEVBQUUsVUFBaUMsRUFBcUIsRUFBRTtJQUN6RyxNQUFNLFFBQVEsbUNBQU8sMEJBQTBCLEtBQUUsU0FBUyxFQUFFLFVBQVUsQ0FBQyxRQUFRLEdBQUMsQ0FBQztJQUNqRix1Q0FBVyxRQUFRLEtBQUUsR0FBRyxFQUFFLEdBQUcsRUFBRSxDQUFDLDRCQUE0QixDQUFDLE9BQU8sRUFBRSxRQUFRLEVBQUUsTUFBTSxFQUFFLFVBQVUsQ0FBQyxJQUFFO0FBQ3ZHLENBQUMsQ0FBQztBQUVOLE1BQU0sbUJBQW1CLEdBQUcsQ0FBQyxXQUFtQixFQUFVLEVBQUU7SUFDMUQsTUFBTSxTQUFTLEdBQWEsQ0FBQyw0QkFBNEIsV0FBVyxtQkFBbUIsQ0FBQyxDQUFDO0lBQ3pGLEtBQUssSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxXQUFXLEVBQUUsRUFBRSxDQUFDLEVBQUU7UUFDcEMsSUFBSSxDQUFDLEtBQUssQ0FBQyxFQUFFO1lBQ1gsU0FBUyxDQUFDLElBQUksQ0FDVixJQUFJO2dCQUNKLGtCQUFrQixDQUFDLG1CQUFtQixDQUFDLE1BQU0sQ0FBQyxDQUFDO1NBQ3BEO2FBQU0sSUFBSSxDQUFDLEtBQUssV0FBVyxHQUFHLENBQUMsRUFBRTtZQUNoQyxTQUFTLENBQUMsSUFBSSxDQUNWLElBQUk7Z0JBQ0osc0JBQXNCLENBQUMsTUFBTSxDQUFDLENBQUM7U0FDcEM7YUFBTTtZQUNMLFNBQVMsQ0FBQyxJQUFJLENBQ1YsSUFBSTtnQkFDSix1QkFBdUIsQ0FBQyxtQkFBbUIsQ0FBQyxNQUFNLENBQUMsQ0FBQztTQUN6RDtLQUNGO0lBQ0QsU0FBUyxDQUFDLElBQUksQ0FDVixJQUFJO1FBQ0osR0FBRyxDQUFDLENBQUM7SUFDVCxPQUFPLFNBQVMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7QUFDOUIsQ0FBQyxDQUFDO0FBRUYsTUFBTSxjQUFjLEdBQUcsQ0FBQyxNQUFnQixFQUFRLEVBQUU7SUFDaEQsSUFBSSxDQUFDLE1BQU0sSUFBSSxNQUFNLENBQUMsTUFBTSxLQUFLLENBQUMsRUFBRTtRQUNsQyxNQUFNLElBQUksS0FBSyxDQUFDLCtCQUErQixDQUFDLENBQUM7S0FDbEQ7SUFDRCxJQUFJLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsTUFBTSxLQUFLLENBQUMsRUFBRTtRQUMvQixNQUFNLElBQUksS0FBSyxDQUFDLHNCQUFzQixDQUFDLENBQUM7S0FDekM7SUFDRCxJQUFJLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLEtBQUssU0FBUyxJQUFJLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLEtBQUssU0FBUyxFQUFFO1FBQ2hFLE1BQU0sSUFBSSxLQUFLLENBQUMscUJBQXFCLENBQUMsQ0FBQztLQUN4QztBQUNILENBQUMsQ0FBQzs7Ozs7Ozs7Ozs7OztBQ2pHRiw0REFBNEQ7QUFDNUQsa0NBQWtDOzs7QUFLbEMsOEdBQXVDO0FBRXZDLDRGQUFzRjtBQUUvRSxNQUFNLHFCQUFxQixHQUM5QixDQUFDLGdCQUF1QyxFQUFFLE1BQWdCLEVBQUUsT0FBZSxFQUFZLEVBQUU7SUFDdkYsY0FBYyxDQUFDLE1BQU0sQ0FBQyxDQUFDO0lBRXZCLE1BQU0sZUFBZSxHQUFHLGdCQUFnQixDQUFDLEdBQUcsQ0FBQyxzQ0FBc0MsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxNQUFNLENBQUMsQ0FBQztJQUN4RyxNQUFNLE1BQU0sR0FBRyxnQkFBZ0IsQ0FBQyxHQUFHLENBQy9CLG9DQUFvQyxDQUFDLGdCQUFnQixFQUFFLE1BQU0sQ0FBQyxDQUFDLENBQUMsRUFBRSxPQUFPLEVBQUUsZUFBZSxDQUFDLElBQUksQ0FBQyxFQUNoRyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsRUFBRSxlQUFlLEVBQUUsTUFBTSxDQUFDLENBQUMsQ0FBQyxFQUFFLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDeEQsT0FBTyxDQUFDLE1BQU0sQ0FBQyxDQUFDO0FBQ2xCLENBQUMsQ0FBQztBQVRPLDZCQUFxQix5QkFTNUI7QUFFQyxNQUFNLG9DQUFvQyxHQUFtQyxDQUFDLElBQWdCLEVBQVUsRUFBRSxDQUM3RyxJQUFJLENBQUMsVUFBVSxDQUFDLFFBQVEsQ0FBQyxTQUFTLEVBQUUsSUFBSSxDQUFDLENBQUM7QUFEakMsNENBQW9DLHdDQUNIO0FBRTlDLE1BQU0sOEJBQThCLEdBQUc7SUFDckMsSUFBSSxFQUFFLHVDQUF1QztJQUM3QyxVQUFVLEVBQUUsQ0FBQyxHQUFHLENBQUM7SUFDakIsVUFBVSxFQUFFLENBQUMsbUJBQVcsQ0FBQyxRQUFRLENBQUM7Q0FDbkMsQ0FBQztBQUVGLE1BQU0sZ0NBQWdDLEdBQUcsQ0FBQyxRQUF5QixFQUFFLEtBQWEsRUFBZSxFQUFFO0lBQ2pHLE1BQU0sS0FBSyxHQUFHLEtBQUssQ0FBQyxJQUFJLENBQUMsS0FBSyxFQUFFLENBQUM7SUFDakMsTUFBTSxPQUFPLEdBQUcsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ3pCLE1BQU0sV0FBVyxHQUFHLEtBQUssQ0FBQyxDQUFDLENBQUMsR0FBRyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDeEMsTUFBTSxXQUFXLEdBQUcsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLEVBQUUsT0FBTyxDQUFDLENBQUM7SUFFeEMsTUFBTSxZQUFZLEdBQUc7Ozs7Ozs7MkJBT0ksS0FBSyxDQUFDLENBQUMsQ0FBQzs7NkJBRU4sS0FBSyxDQUFDLENBQUMsQ0FBQzs7Ozs7O29DQU1ELFdBQVc7OzJCQUVwQixLQUFLLENBQUMsQ0FBQyxDQUFDOzs2QkFFTixLQUFLLENBQUMsQ0FBQyxDQUFDOzs7Ozs7OzZCQU9SLFdBQVc7OztRQUdoQyxDQUFDO0lBQ1AsdUNBQ0ssUUFBUSxLQUNYLE1BQU0sRUFBRSxFQUFDLElBQUksRUFBRSxXQUFXLEVBQUUsSUFBSSxFQUFFLEtBQUssQ0FBQyxJQUFJLEVBQUUsV0FBVyxFQUFFLG1CQUFXLENBQUMsbUJBQW1CLEVBQUMsRUFDM0YsWUFBWSxJQUNaO0FBQ0osQ0FBQyxDQUFDO0FBRUYsTUFBTSxzQ0FBc0MsR0FBRyxDQUFDLEtBQWEsRUFBcUIsRUFBRSxDQUFDLGlDQUNoRiw4QkFBOEIsS0FDakMsR0FBRyxFQUFFLEdBQUcsRUFBRSxDQUFDLGdDQUFnQyxDQUFDLDhCQUE4QixFQUFFLEtBQUssQ0FBQyxJQUNsRixDQUFDO0FBRUgsTUFBTSw0QkFBNEIsR0FBRztJQUNuQyxJQUFJLEVBQUUscUNBQXFDO0lBQzNDLFVBQVUsRUFBRSxDQUFDLEdBQUcsRUFBRSxpQkFBaUIsRUFBRSxPQUFPLEVBQUUsR0FBRyxDQUFDO0lBQ2xELFVBQVUsRUFBRSxDQUFDLG1CQUFXLENBQUMsUUFBUSxFQUFFLG1CQUFXLENBQUMsbUJBQW1CLEVBQUUsbUJBQVcsQ0FBQyxRQUFRLEVBQUUsbUJBQVcsQ0FBQyxRQUFRLENBQUM7Q0FDaEgsQ0FBQztBQUVGLE1BQU0sOEJBQThCLEdBQ2hDLENBQUMsZ0JBQXVDLEVBQUUsUUFBeUIsRUFBRSxLQUFhLEVBQUUsT0FBZSxFQUNsRyxvQkFBdUMsRUFBZSxFQUFFO0lBQ3ZELE1BQU0sSUFBSSxHQUFHLHlCQUFPLEVBQUMsZ0JBQWdCLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxTQUFTLENBQUMsT0FBTyxDQUFDLENBQUM7SUFDekUsTUFBTSxDQUFDLFlBQVksRUFBRSxhQUFhLENBQUMsR0FDL0IsZ0JBQWdCLENBQUMsOEJBQThCLENBQUMsb0JBQW9CLEVBQUUsbUJBQVcsQ0FBQyxtQkFBbUIsQ0FBQyxDQUFDO0lBQzNHLE1BQU0sQ0FBQyxvQkFBb0IsRUFBRSxxQkFBcUIsQ0FBQyxHQUFHLENBQUMsWUFBWSxHQUFHLENBQUMsRUFBRSxhQUFhLENBQUMsQ0FBQztJQUN4RixNQUFNLFlBQVksR0FBRzs7OytDQUdvQixvQkFBb0IsS0FBSyxxQkFBcUI7aUJBQzVFLElBQUksQ0FBQyxTQUFTOzs7Ozs7Ozs7Ozs7Ozs7OztRQWlCdkIsQ0FBQztJQUNILHVDQUNLLFFBQVEsS0FDWCxNQUFNLEVBQUUsRUFBQyxJQUFJLEVBQUUsS0FBSyxDQUFDLElBQUksRUFBRSxJQUFJLEVBQUUsS0FBSyxDQUFDLElBQUksRUFBRSxXQUFXLEVBQUUsbUJBQVcsQ0FBQyxRQUFRLEVBQUMsRUFDL0UsU0FBUyxFQUFFLENBQUMsRUFBQyxJQUFJLEVBQUUsU0FBUyxFQUFFLElBQUksRUFBRSxPQUFPLEVBQUUsSUFBSSxFQUFFLE9BQU8sRUFBQyxDQUFDLEVBQzVELFlBQVksSUFDWjtBQUNKLENBQUMsQ0FBQztBQUVOLE1BQU0sb0NBQW9DLEdBQ3RDLENBQUMsZ0JBQXVDLEVBQUUsS0FBYSxFQUFFLE9BQWUsRUFBRSxvQkFBdUMsRUFDM0YsRUFBRTtJQUNsQixNQUFNLFFBQVEsbUNBQU8sNEJBQTRCLEtBQUUsU0FBUyxFQUFFLEdBQUcsT0FBTyxFQUFFLEdBQUMsQ0FBQztJQUM1RSx1Q0FDSyxRQUFRLEtBQ1gsR0FBRyxFQUFFLEdBQUcsRUFBRSxDQUFDLDhCQUE4QixDQUFDLGdCQUFnQixFQUFFLFFBQVEsRUFBRSxLQUFLLEVBQUUsT0FBTyxFQUFFLG9CQUFvQixDQUFDLElBQzNHO0FBQ0osQ0FBQyxDQUFDO0FBRVYsTUFBTSxjQUFjLEdBQUcsQ0FBQyxNQUFnQixFQUFRLEVBQUU7SUFDaEQsSUFBSSxDQUFDLE1BQU0sSUFBSSxNQUFNLENBQUMsTUFBTSxLQUFLLENBQUMsRUFBRTtRQUNsQyxNQUFNLElBQUksS0FBSyxDQUFDLDBDQUEwQyxDQUFDLENBQUM7S0FDN0Q7SUFFRCxNQUFNLENBQUMsR0FBRyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDcEIsTUFBTSxLQUFLLEdBQUcsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ3hCLE1BQU0sQ0FBQyxHQUFHLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUVwQixrRUFBa0U7SUFDbEUsNENBQTRDO0lBQzVDLElBQUksQ0FBQyxDQUFDLElBQUksQ0FBQyxNQUFNLEdBQUcsQ0FBQyxJQUFJLEtBQUssQ0FBQyxJQUFJLENBQUMsTUFBTSxLQUFLLENBQUMsSUFBSSxDQUFDLENBQUMsSUFBSSxDQUFDLE1BQU0sS0FBSyxDQUFDLEVBQUU7UUFDdkUsTUFBTSxJQUFJLEtBQUssQ0FBQyxzQkFBc0IsQ0FBQyxDQUFDO0tBQ3pDO0lBQ0QsSUFBSSxLQUFLLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFO1FBQzFELE1BQU0sSUFBSSxLQUFLLENBQUMsOEJBQThCLENBQUMsQ0FBQztLQUNqRDtJQUNELElBQUksQ0FBQyxDQUFDLENBQUMsSUFBSSxLQUFLLFNBQVMsSUFBSSxDQUFDLENBQUMsSUFBSSxLQUFLLFNBQVMsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksS0FBSyxTQUFTLElBQUksS0FBSyxDQUFDLElBQUksS0FBSyxTQUFTLENBQUM7UUFDeEcsQ0FBQyxDQUFDLENBQUMsSUFBSSxLQUFLLFNBQVMsSUFBSSxDQUFDLENBQUMsSUFBSSxLQUFLLFNBQVMsQ0FBQyxFQUFFO1FBQ2xELE1BQU0sSUFBSSxLQUFLLENBQUMscUJBQXFCLENBQUMsQ0FBQztLQUN4QztJQUNELElBQUksTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxNQUFNLEtBQUssQ0FBQyxFQUFFO1FBQy9CLE1BQU0sSUFBSSxLQUFLLENBQUMsK0JBQStCLENBQUMsQ0FBQztLQUNsRDtBQUNILENBQUMsQ0FBQzs7Ozs7Ozs7Ozs7OztBQzNKRiw0REFBNEQ7QUFDNUQsa0NBQWtDOzs7QUFHbEMsZ0ZBQXVEO0FBQ3ZELDhHQUF1QztBQUV2Qyw0RkFBc0Y7QUFDdEYsNEZBQTBEO0FBRTFELDhHQUFnRjtBQUNoRixrR0FBMEM7QUFFMUMsTUFBTSxpQ0FBaUMsR0FBRyxDQUFDLE9BQWdCLEVBQUUsU0FBaUIsRUFBRSxFQUFFLENBQUMsQ0FBQztJQUNsRixJQUFJLEVBQUUsaUJBQWlCO0lBQ3ZCLFVBQVUsRUFBRSxPQUFPLENBQUMsQ0FBQyxDQUFDLENBQUMsR0FBRyxFQUFFLEdBQUcsRUFBRSxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxHQUFHLEVBQUUsR0FBRyxDQUFDO0lBQ3JELFVBQVUsRUFBRSxPQUFPLENBQUMsQ0FBQyxDQUFDLENBQUMsbUJBQVcsQ0FBQyxNQUFNLEVBQUUsbUJBQVcsQ0FBQyxNQUFNLEVBQUUsbUJBQVcsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDO1FBQzlELENBQUMsbUJBQVcsQ0FBQyxNQUFNLEVBQUUsbUJBQVcsQ0FBQyxNQUFNLENBQUM7SUFDOUQsU0FBUztDQUNWLENBQUMsQ0FBQztBQUVILE1BQU0sNkJBQTZCLEdBQy9CLENBQUMsZ0JBQXVDLEVBQUUsUUFBeUIsRUFBRSxNQUFnQixFQUNwRixvQkFBa0QsRUFBZSxFQUFFO0lBQ2xFLE1BQU0sT0FBTyxHQUFHLE1BQU0sQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFDO0lBQ2xDLE1BQU0sV0FBVyxHQUFHLE9BQU8sQ0FBQyxDQUFDLENBQUMsOEJBQThCLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQztJQUNsRSxNQUFNLE1BQU0sR0FBRyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDO0lBQzlCLE1BQU0sTUFBTSxHQUFHLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUM7SUFDOUIsTUFBTSxXQUFXLEdBQUcsb0JBQWEsQ0FBQyxTQUFTLENBQUMsTUFBTSxFQUFFLE1BQU0sRUFBRSxJQUFJLENBQUMsQ0FBQztJQUNsRSxNQUFNLFdBQVcsR0FBRyxDQUFDLGdCQUFTLENBQUMsUUFBUSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLEVBQUUsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDO0lBRXhFLElBQUksQ0FBQyxXQUFXLEVBQUU7UUFDaEIsTUFBTSxJQUFJLEtBQUssQ0FBQyx3Q0FBd0MsQ0FBQyxDQUFDO0tBQzNEO0lBQ0QsTUFBTSxTQUFTLEdBQUcsTUFBTSxDQUFDLE1BQU0sQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFDLENBQUM7SUFDNUMsTUFBTSxjQUFjLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxTQUFTLEdBQUcsQ0FBQyxDQUFDLENBQUM7SUFDaEQsTUFBTSxLQUFLLEdBQUcsTUFBTSxDQUFDLE1BQU0sQ0FBQztJQUM1QixNQUFNLEtBQUssR0FBRyxNQUFNLENBQUMsTUFBTSxDQUFDO0lBRTVCLE1BQU0sSUFBSSxHQUFHLHlCQUFPLEVBQUMsZ0JBQWdCLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxTQUFTLENBQUMsT0FBTyxDQUFDLENBQUM7SUFDekUsTUFBTSxjQUFjLEdBQUcsNkJBQWlCLEVBQUMsV0FBVyxDQUFDLE1BQU0sQ0FBQyxDQUFDO0lBQzdELE1BQU0sT0FBTyxHQUFHLFdBQVcsQ0FBQyxNQUFNLENBQUM7SUFDbkMsTUFBTSxhQUFhLEdBQUcseUJBQWEsR0FBRSxDQUFDO0lBQ3RDLE1BQU0sRUFBQyxrQkFBa0IsRUFBRSxlQUFlLEVBQUMsR0FBRyxxQ0FBb0IsRUFBQyxvQkFBb0IsQ0FBQyxDQUFDO0lBRXpGLE1BQU0sdUJBQXVCLEdBQ3pCLE9BQU8sQ0FBQyxDQUFDLENBQUMsR0FBRyw2QkFBZ0IsRUFBQyxjQUFjLEVBQUUsYUFBYSxFQUFFLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLEVBQUUsV0FBVyxFQUFFLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQztJQUUzRyxNQUFNLGlDQUFpQyxHQUNuQyxXQUFXLENBQUMsQ0FBQyxDQUFDLEdBQUcsd0JBQXdCLENBQUMsY0FBYyxFQUFFLGFBQWEsRUFBRSxNQUFNLEVBQUUsV0FBVyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO0lBRXpHLE1BQU0sd0JBQXdCLEdBQUcsV0FBVyxDQUFDLENBQUMsQ0FBQywwQkFBMEIsQ0FBQyxDQUFDLENBQUMsUUFBUSxJQUFJLENBQUMsYUFBYSxFQUFFLEtBQUssQ0FBQyxHQUFHLENBQUM7SUFDbEgsTUFBTSx3QkFBd0IsR0FBRyxXQUFXLENBQUMsQ0FBQyxDQUFDLDBCQUEwQixDQUFDLENBQUMsQ0FBQyxRQUFRLElBQUksQ0FBQyxhQUFhLEVBQUUsS0FBSyxDQUFDLEdBQUcsQ0FBQztJQUNsSCxNQUFNLHNCQUFzQixHQUFHLFdBQVcsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxHQUFHLGNBQWM7Z0RBQ3pCLGFBQWEsQ0FBQyxPQUFPLEdBQUcsQ0FBQyxDQUFDLFFBQVEsYUFBYSxDQUFDLE9BQU8sR0FBRyxDQUFDLENBQUM7ZUFDN0YsYUFBYSxDQUFDLE9BQU8sR0FBRyxDQUFDLENBQUMsUUFBUSxhQUFhLENBQUMsT0FBTyxHQUFHLENBQUMsQ0FBQztPQUNwRSxDQUFDO0lBQ0YsTUFBTSxZQUFZLEdBQUc7Y0FDYixpQ0FBaUM7Y0FDakMsdUJBQXVCO2NBQ3ZCLGtCQUFrQjs7Z0JBRWhCLHNCQUFzQjs7O29DQUdGLGNBQWM7MkJBQ3ZCLHdCQUF3QjsyQkFDeEIsd0JBQXdCOzs7OztnQkFLbkMsV0FBVztnQkFDWCxlQUFlO2dCQUNmLElBQUksQ0FBQyxNQUFNO2NBQ2IsQ0FBQztJQUNULHVDQUNLLFFBQVEsS0FDWCxNQUFNLEVBQUUsRUFBQyxJQUFJLEVBQUUsV0FBVyxFQUFFLElBQUksRUFBRSxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxFQUFFLFdBQVcsRUFBRSxtQkFBVyxDQUFDLE1BQU0sRUFBQyxFQUNsRixZQUFZLEVBQ1osT0FBTyxFQUFFLElBQUksSUFDYjtBQUNKLENBQUMsQ0FBQztBQUVDLE1BQU0sbUNBQW1DLEdBQzVDLENBQUMsZ0JBQXVDLEVBQUUsTUFBZ0IsRUFDekQsb0JBQWtELEVBQXFCLEVBQUU7SUFDeEUsTUFBTSxRQUFRLEdBQUcsaUNBQWlDLENBQUMsTUFBTSxDQUFDLE1BQU0sR0FBRyxDQUFDLEVBQUUsb0JBQW9CLENBQUMsa0JBQWtCLENBQUMsQ0FBQztJQUMvRyx1Q0FDSyxRQUFRLEtBQ1gsR0FBRyxFQUFFLEdBQUcsRUFBRSxDQUFDLDZCQUE2QixDQUFDLGdCQUFnQixFQUFFLFFBQVEsRUFBRSxNQUFNLEVBQUUsb0JBQW9CLENBQUMsSUFDbEc7QUFDSixDQUFDLENBQUM7QUFSTywyQ0FBbUMsdUNBUTFDO0FBRU4sU0FBUyx3QkFBd0IsQ0FDN0IsY0FBc0IsRUFBRSxhQUFnQyxFQUFFLE1BQWdCLEVBQUUsUUFBMkI7SUFDekcsSUFBSSxzQkFBc0IsR0FBRyxFQUFFLENBQUM7SUFDaEMsSUFBSSxzQkFBc0IsR0FBRyxFQUFFLENBQUM7SUFFaEMsTUFBTSxRQUFRLEdBQUcsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQztJQUNoQyxNQUFNLFFBQVEsR0FBRyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDO0lBRWhDLE1BQU0sT0FBTyxHQUFHLFFBQVEsQ0FBQyxNQUFNLENBQUM7SUFDaEMsTUFBTSxPQUFPLEdBQUcsUUFBUSxDQUFDLE1BQU0sQ0FBQztJQUVoQyxNQUFNLE9BQU8sR0FBRyxRQUFRLENBQUMsTUFBTSxDQUFDO0lBQ2hDLE1BQU0sU0FBUyxHQUFHLE9BQU8sR0FBRyxPQUFPLENBQUM7SUFDcEMsTUFBTSxTQUFTLEdBQUcsT0FBTyxHQUFHLE9BQU8sQ0FBQztJQUVwQyxzQkFBc0IsR0FBRyxRQUFRLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxFQUFFLENBQUMsVUFBVSxhQUFhLENBQUMsQ0FBQyxHQUFHLFNBQVMsQ0FBQyxFQUFFLENBQUMsQ0FBQztJQUMxRixzQkFBc0IsQ0FBQyxPQUFPLEdBQUcsQ0FBQyxDQUFDLEdBQUcsS0FBSyxDQUFDO0lBQzVDLHNCQUFzQixDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUNsQyxzQkFBc0IsR0FBRyxRQUFRLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxFQUFFLENBQUMsVUFBVSxhQUFhLENBQUMsQ0FBQyxHQUFHLFNBQVMsQ0FBQyxFQUFFLENBQUMsQ0FBQztJQUMxRixzQkFBc0IsQ0FBQyxPQUFPLEdBQUcsQ0FBQyxDQUFDLEdBQUcsS0FBSyxDQUFDO0lBQzVDLHNCQUFzQixDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUVsQyxNQUFNLGNBQWMsR0FBRyxvQkFBYSxDQUFDLGdCQUFnQixDQUFDLFFBQVEsRUFBRSxRQUFRLENBQUMsQ0FBQztJQUMxRSxNQUFNLGNBQWMsR0FBRyxvQkFBYSxDQUFDLGdCQUFnQixDQUFDLFFBQVEsRUFBRSxRQUFRLENBQUMsQ0FBQztJQUUxRSxNQUFNLGNBQWMsR0FBRyxjQUFjLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsVUFBVSxhQUFhLENBQUMsQ0FBQyxHQUFHLFNBQVMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDekcsTUFBTSxjQUFjLEdBQUcsY0FBYyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLFVBQVUsYUFBYSxDQUFDLENBQUMsR0FBRyxTQUFTLENBQUMsT0FBTyxDQUFDLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQ3pHLE1BQU0sY0FBYyxHQUFHLHdCQUF3QixhQUFhLENBQUMsT0FBTyxHQUFHLENBQUMsQ0FBQztXQUNoRSxhQUFhLENBQUMsT0FBTyxHQUFHLENBQUMsQ0FBQyxhQUFhLGFBQWEsQ0FBQyxPQUFPLEdBQUcsQ0FBQyxDQUFDO1dBQ2pFLGFBQWEsQ0FBQyxPQUFPLEdBQUcsQ0FBQyxDQUFDLGFBQWEsQ0FBQztJQUVqRCxNQUFNLDJCQUEyQixHQUFHOztJQUVsQyxjQUFjO0lBQ2QsY0FBYztJQUNkLGNBQWM7NEJBQ1Usc0JBQXNCOzs7OztJQUs5QyxjQUFjO0lBQ2QsY0FBYztJQUNkLGNBQWM7NEJBQ1Usc0JBQXNCOztFQUVoRCxDQUFDO0lBRUQsT0FBTywyQkFBMkIsQ0FBQztBQUNyQyxDQUFDO0FBRUQsU0FBUyxJQUFJLENBQUMsYUFBdUIsRUFBRSxJQUFZO0lBQ2pELElBQUksR0FBRyxHQUFHLEVBQUUsQ0FBQztJQUNiLEtBQUssSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxJQUFJLEdBQUcsQ0FBQyxFQUFFLENBQUMsRUFBRSxFQUFFO1FBQ2pDLEdBQUcsSUFBSSxNQUFNLGFBQWEsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDO0tBQ25DO0lBQ0QsR0FBRyxJQUFJLE1BQU0sYUFBYSxDQUFDLElBQUksR0FBRyxDQUFDLENBQUMsSUFBSTtRQUNwQyxLQUFLLENBQUM7SUFDVixPQUFPLEdBQUcsQ0FBQztBQUNiLENBQUM7QUFFRCxTQUFTLElBQUksQ0FBQyxhQUF1QixFQUFFLElBQVk7SUFDakQsSUFBSSxHQUFHLEdBQUcsRUFBRSxDQUFDO0lBQ2IsS0FBSyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLElBQUksR0FBRyxDQUFDLEVBQUUsQ0FBQyxFQUFFLEVBQUU7UUFDakMsR0FBRyxJQUFJLE1BQU0sYUFBYSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUM7S0FDbkM7SUFDRCxHQUFHLElBQUksT0FBTztRQUNWLE1BQU0sYUFBYSxDQUFDLElBQUksR0FBRyxDQUFDLENBQUMsRUFBRSxDQUFDO0lBQ3BDLE9BQU8sR0FBRyxDQUFDO0FBQ2IsQ0FBQzs7Ozs7Ozs7Ozs7OztBQ25LRCw0REFBNEQ7QUFDNUQsa0NBQWtDOzs7QUFLbEMsZ0ZBQXVEO0FBRXZELDRGQUFzRjtBQUN0Riw0RkFBMEQ7QUFFMUQsOEdBQW1IO0FBQ25ILGlIQUFrRTtBQUUzRCxNQUFNLE1BQU0sR0FDZixDQUFDLGdCQUF1QyxFQUFFLE1BQWdCLEVBQUUsVUFBd0MsRUFBWSxFQUFFO0lBQ2hILGNBQWMsQ0FBQyxNQUFNLENBQUMsQ0FBQztJQUV2QixJQUFJLGdCQUFnQixDQUFDLE9BQU8sQ0FBQyxJQUFJLEVBQUU7UUFDakMsT0FBTyxDQUFDLGdCQUFnQixDQUFDLEdBQUcsQ0FDeEIscURBQW1DLEVBQUMsZ0JBQWdCLEVBQUUsTUFBTSxFQUFFLFVBQVUsQ0FBQyxFQUFFLE1BQU0sQ0FBQyxDQUFDLENBQUM7S0FDekY7U0FBTTtRQUNMLE9BQU8sQ0FBQyxnQkFBZ0IsQ0FBQyxHQUFHLENBQUMsNkJBQTZCLENBQUMsTUFBTSxFQUFFLFVBQVUsQ0FBQyxFQUFFLE1BQU0sQ0FBQyxDQUFDLENBQUM7S0FDMUY7QUFDSCxDQUFDLENBQUM7QUFWTyxjQUFNLFVBVWI7QUFFQyxNQUFNLHFCQUFxQixHQUM5QixDQUFDLElBQWdCLEVBQWdDLEVBQUUsQ0FBQyxrREFBaUMsRUFBQyxJQUFJLENBQUMsVUFBVSxDQUFDLENBQUM7QUFEOUYsNkJBQXFCLHlCQUN5RTtBQUUzRyxNQUFNLDJCQUEyQixHQUFHLENBQUMsT0FBZ0IsRUFBRSxTQUFpQixFQUFFLEVBQUUsQ0FBQyxDQUFDO0lBQzVFLElBQUksRUFBRSxRQUFRO0lBQ2QsVUFBVSxFQUFFLE9BQU8sQ0FBQyxDQUFDLENBQUMsQ0FBQyxHQUFHLEVBQUUsR0FBRyxFQUFFLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEdBQUcsRUFBRSxHQUFHLENBQUM7SUFDckQsVUFBVSxFQUFFLE9BQU8sQ0FBQyxDQUFDLENBQUMsQ0FBQyxtQkFBVyxDQUFDLFFBQVEsRUFBRSxtQkFBVyxDQUFDLFFBQVEsRUFBRSxtQkFBVyxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUM7UUFDcEUsQ0FBQyxtQkFBVyxDQUFDLFFBQVEsRUFBRSxtQkFBVyxDQUFDLFFBQVEsQ0FBQztJQUNsRSxTQUFTO0NBQ1YsQ0FBQyxDQUFDO0FBRUgsU0FBUyx1QkFBdUIsQ0FDNUIsUUFBeUIsRUFBRSxNQUFnQixFQUFFLG9CQUFrRDtJQUNqRyxNQUFNLE1BQU0sR0FBRyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDO0lBQzlCLE1BQU0sTUFBTSxHQUFHLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUM7SUFDOUIsTUFBTSxXQUFXLEdBQUcsb0JBQWEsQ0FBQyxTQUFTLENBQUMsTUFBTSxFQUFFLE1BQU0sRUFBRSxJQUFJLENBQUMsQ0FBQztJQUNsRSxJQUFJLENBQUMsV0FBVyxFQUFFO1FBQ2hCLE1BQU0sSUFBSSxLQUFLLENBQUMsd0NBQXdDLENBQUMsQ0FBQztLQUMzRDtJQUNELE1BQU0sY0FBYyxHQUFHLDZCQUFpQixFQUFDLFdBQVcsQ0FBQyxNQUFNLENBQUMsQ0FBQztJQUM3RCxNQUFNLGFBQWEsR0FBRyx5QkFBYSxHQUFFLENBQUM7SUFDdEMsTUFBTSxFQUFDLGtCQUFrQixFQUFFLGVBQWUsRUFBQyxHQUFHLHFDQUFvQixFQUFDLG9CQUFvQixDQUFDLENBQUM7SUFFekYsTUFBTSxPQUFPLEdBQUcsTUFBTSxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUM7SUFDbEMsTUFBTSxXQUFXLEdBQUcsT0FBTyxDQUFDLENBQUMsQ0FBQyw4QkFBOEIsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO0lBQ2xFLE1BQU0sdUJBQXVCLEdBQ3pCLE9BQU8sQ0FBQyxDQUFDLENBQUMsR0FBRyxnQkFBZ0IsQ0FBQyxjQUFjLEVBQUUsYUFBYSxFQUFFLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLEVBQUUsV0FBVyxFQUFFLEtBQUssQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQztJQUU1RyxNQUFNLElBQUksR0FBRyxXQUFXLENBQUMsTUFBTSxDQUFDO0lBQ2hDLE1BQU0sS0FBSyxHQUFHLE1BQU0sQ0FBQyxNQUFNLENBQUM7SUFDNUIsTUFBTSxLQUFLLEdBQUcsTUFBTSxDQUFDLE1BQU0sQ0FBQztJQUM1QixNQUFNLFNBQVMsR0FBRyxNQUFNLENBQUMsTUFBTSxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUMsQ0FBQztJQUM1QyxNQUFNLFlBQVksR0FBRztNQUNqQixrQkFBa0I7TUFDbEIsdUJBQXVCO2dDQUNHLElBQUk7Z0JBQ3BCLEtBQUs7Z0JBQ0wsS0FBSzs7Ozs7MEJBS0ssU0FBUztnQkFDbkIsS0FBSyxHQUFHLENBQUM7Z0JBQ1QsS0FBSyxHQUFHLENBQUM7OztVQUdmLFdBQVc7VUFDWCxlQUFlOztNQUVuQixDQUFDO0lBQ0wsdUNBQ0ssUUFBUSxLQUNYLE1BQU0sRUFBRSxFQUFDLElBQUksRUFBRSxXQUFXLEVBQUUsSUFBSSxFQUFFLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLEVBQUUsV0FBVyxFQUFFLG1CQUFXLENBQUMsUUFBUSxFQUFDLEVBQ3BGLFlBQVksSUFDWjtBQUNKLENBQUM7QUFFRCxTQUFnQiw2QkFBNkIsQ0FDekMsTUFBZ0IsRUFBRSxvQkFBa0Q7SUFDdEUsTUFBTSxRQUFRLEdBQUcsMkJBQTJCLENBQUMsTUFBTSxDQUFDLE1BQU0sR0FBRyxDQUFDLEVBQUUsb0JBQW9CLENBQUMsa0JBQWtCLENBQUMsQ0FBQztJQUN6Ryx1Q0FBVyxRQUFRLEtBQUUsR0FBRyxFQUFFLEdBQUcsRUFBRSxDQUFDLHVCQUF1QixDQUFDLFFBQVEsRUFBRSxNQUFNLEVBQUUsb0JBQW9CLENBQUMsSUFBRTtBQUNuRyxDQUFDO0FBSkQsc0VBSUM7QUFFRCxNQUFNLGNBQWMsR0FBRyxDQUFDLE1BQWdCLEVBQVEsRUFBRTtJQUNoRCxJQUFJLENBQUMsTUFBTSxJQUFJLE1BQU0sQ0FBQyxNQUFNLEtBQUssQ0FBQyxFQUFFO1FBQ2xDLE1BQU0sSUFBSSxLQUFLLENBQUMsMkJBQTJCLENBQUMsQ0FBQztLQUM5QztJQUVELElBQUksTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUMsS0FBSyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQyxFQUFFO1FBQzNGLE1BQU0sSUFBSSxLQUFLLENBQUMsa0NBQWtDLENBQUMsQ0FBQztLQUNyRDtJQUVELElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxLQUFLLFNBQVMsSUFBSSxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxLQUFLLFNBQVMsQ0FBQztRQUM5RCxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLEtBQUssU0FBUyxJQUFJLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLEtBQUssU0FBUyxDQUFDLEVBQUU7UUFDbEUsTUFBTSxJQUFJLEtBQUssQ0FBQyw2QkFBNkIsQ0FBQyxDQUFDO0tBQ2hEO0lBRUQsSUFBSSxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxLQUFLLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLEVBQUU7UUFDckMsTUFBTSxJQUFJLEtBQUssQ0FBQywyQkFBMkIsQ0FBQyxDQUFDO0tBQzlDO0FBQ0gsQ0FBQyxDQUFDO0FBRUYsU0FBZ0IsZ0JBQWdCLENBQzVCLGNBQXNCLEVBQUUsYUFBZ0MsRUFBRSxPQUEwQixFQUFFLFFBQTJCLEVBQ2pILFFBQWlCO0lBQ25CLElBQUkscUJBQXFCLEdBQUcsRUFBRSxDQUFDO0lBQy9CLE1BQU0sTUFBTSxHQUFHLE9BQU8sQ0FBQyxNQUFNLENBQUM7SUFDOUIsTUFBTSxPQUFPLEdBQUcsUUFBUSxDQUFDLE1BQU0sQ0FBQztJQUNoQyxNQUFNLFFBQVEsR0FBRyxPQUFPLEdBQUcsTUFBTSxDQUFDO0lBQ2xDLElBQUksT0FBTyxHQUFHLENBQUMsSUFBSSxNQUFNLEdBQUcsQ0FBQyxFQUFFO1FBQzdCLHFCQUFxQixHQUFHLFFBQVEsQ0FBQztLQUNsQztTQUFNO1FBQ0wscUJBQXFCLEdBQUcsT0FBTyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDLFVBQVUsYUFBYSxDQUFDLENBQUMsR0FBRyxRQUFRLENBQUMsRUFBRSxDQUFDLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO0tBQ25HO0lBQ0QsTUFBTSxhQUFhLEdBQUcsb0JBQWEsQ0FBQyxnQkFBZ0IsQ0FBQyxPQUFPLEVBQUUsUUFBUSxDQUFDLENBQUM7SUFDeEUsTUFBTSxhQUFhLEdBQUcsYUFBYSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLFVBQVUsYUFBYSxDQUFDLENBQUMsR0FBRyxRQUFRLENBQUMsT0FBTyxDQUFDLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQ3RHLE1BQU0sTUFBTSxHQUFHLGdCQUFTLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDO0lBQ3ZDLE1BQU0sYUFBYSxHQUFHLE1BQU0sS0FBSyxDQUFDLENBQUM7SUFDbkMsSUFBSSxNQUFNLEdBQUcsc0NBQXNDLENBQUM7SUFDcEQsSUFBSSxhQUFhLEVBQUU7UUFDakIsTUFBTSxHQUFHLHFCQUFxQixDQUFDO0tBQ2hDO0lBQ0QsTUFBTSxzQkFBc0IsR0FBRyxRQUFRLENBQUMsQ0FBQyxDQUFDOztJQUV4QyxjQUFjO0lBQ2QsYUFBYTsrQkFDYyxxQkFBcUI7V0FDekMsTUFBTTtFQUNmLENBQUMsQ0FBQztRQUN3Qzs7SUFFeEMsY0FBYztJQUNkLGFBQWE7O0VBRWYsQ0FBQztJQUVELE9BQU8sc0JBQXNCLENBQUM7QUFDaEMsQ0FBQztBQW5DRCw0Q0FtQ0M7Ozs7Ozs7Ozs7Ozs7QUNoSkQsNERBQTREO0FBQzVELGtDQUFrQzs7O0FBR2xDLDhHQUF1QztBQUV2Qyw0RkFBcUU7QUFDckUsNEZBQTJDO0FBRTNDLHVIQUE0QztBQUU1QyxNQUFNLG1CQUFtQixHQUFHO0lBQzFCLElBQUksRUFBRSxNQUFNO0lBQ1osVUFBVSxFQUFFLENBQUMsR0FBRyxDQUFDO0lBQ2pCLFVBQVUsRUFBRSxDQUFDLG1CQUFXLENBQUMsZ0JBQWdCLENBQUM7Q0FDM0MsQ0FBQztBQUVGLE1BQU0scUJBQXFCLEdBQUcsQ0FBQyxPQUE4QixFQUFFLEtBQWEsRUFBZSxFQUFFO0lBQzNGLE1BQU0sSUFBSSxHQUFHLHlCQUFPLEVBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsU0FBUyxDQUFDLE9BQU8sQ0FBQyxDQUFDO0lBQ2hFLE1BQU0sVUFBVSxHQUFHLEtBQUssQ0FBQyxJQUFJLENBQUM7SUFFOUIsTUFBTSxTQUFTLEdBQUcsVUFBVSxDQUFDLE1BQU0sQ0FBQztJQUNwQyx5RkFBeUY7SUFDekYsTUFBTSxVQUFVLEdBQUcsS0FBSyxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUM7SUFFckMsTUFBTSxjQUFjLEdBQUcsNkJBQWlCLEVBQUMsVUFBVSxDQUFDLENBQUM7SUFDckQsTUFBTSxRQUFRLEdBQUcsK0JBQVcsRUFBQyxJQUFJLEVBQUUsVUFBVSxDQUFDLENBQUM7SUFDL0MsTUFBTSxLQUFLLEdBQUcsUUFBUSxDQUFDLFVBQVUsRUFBRSxRQUFRLEVBQUUsVUFBVSxDQUFDLFVBQVUsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFDLEVBQUUsVUFBVSxDQUFDLFVBQVUsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUVuSCxJQUFJLGVBQWUsQ0FBQztJQUNwQixJQUFJLFNBQVMsS0FBSyxDQUFDLEVBQUU7UUFDbkIsZUFBZSxHQUFHLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO0tBQzFCO1NBQU0sSUFBSSxTQUFTLEtBQUssQ0FBQyxFQUFFO1FBQzFCLGVBQWUsR0FBRyxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztLQUN0QztTQUFNO1FBQ0wsZUFBZSxHQUFHLENBQUMsVUFBVSxDQUFDLFVBQVUsR0FBRyxDQUFDLENBQUMsRUFBRSxVQUFVLENBQUMsVUFBVSxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUM7S0FDNUU7SUFDRCxNQUFNLG9CQUFvQixHQUFHLHVCQUF1QixDQUFDLFVBQVUsRUFBRSxlQUFlLEVBQUUsUUFBUSxDQUFDLENBQUM7SUFDNUYsTUFBTSxNQUFNLEdBQUcsU0FBUyxDQUFDLFVBQVUsRUFBRSxRQUFRLENBQUMsQ0FBQztJQUUvQyxNQUFNLFlBQVksR0FBRzs7WUFFWCxjQUFjOztlQUVYLG9CQUFvQjtjQUNyQixJQUFJLENBQUMsTUFBTTs7Y0FFWCxLQUFLOztjQUVMLElBQUksQ0FBQyxNQUFNLFdBQVcsTUFBTTs7O09BR25DLENBQUM7SUFDTix1Q0FDSyxtQkFBbUIsS0FDdEIsT0FBTyxFQUFFLElBQUksRUFDYixNQUFNLEVBQUUsRUFBQyxJQUFJLEVBQUUsS0FBSyxDQUFDLElBQUksRUFBRSxJQUFJLEVBQUUsS0FBSyxDQUFDLElBQUksRUFBRSxXQUFXLEVBQUUsbUJBQVcsQ0FBQyxNQUFNLEVBQUMsRUFDN0UsWUFBWSxJQUNaO0FBQ0osQ0FBQyxDQUFDO0FBRUssTUFBTSwyQkFBMkIsR0FBRyxDQUFDLE9BQThCLEVBQUUsS0FBYSxFQUFxQixFQUFFLENBQzVHLGlDQUFLLG1CQUFtQixLQUFFLEdBQUcsRUFBRSxHQUFHLEVBQUUsQ0FBQyxxQkFBcUIsQ0FBQyxPQUFPLEVBQUUsS0FBSyxDQUFDLElBQUUsQ0FBQztBQURwRSxtQ0FBMkIsK0JBQ3lDO0FBRWpGOztHQUVHO0FBQ0gsU0FBUyx1QkFBdUIsQ0FBQyxJQUFZLEVBQUUsS0FBd0IsRUFBRSxJQUFjO0lBQ3JGLElBQUksSUFBSSxLQUFLLENBQUMsRUFBRTtRQUNkLE9BQU8sT0FBTyxDQUFDO0tBQ2hCO0lBQ0QsSUFBSSxJQUFJLEtBQUssQ0FBQyxFQUFFO1FBQ2QsT0FBTyxRQUFRLEtBQUssQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO0tBQzNCO0lBRUQsSUFBSSxJQUFJLEdBQUcsRUFBRSxDQUFDO0lBQ2QsS0FBSyxJQUFJLENBQUMsR0FBRyxJQUFJLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxJQUFJLEVBQUUsQ0FBQyxFQUFFLEVBQUU7UUFDcEMsSUFBSSxJQUFJLEdBQUcsSUFBSSxDQUFDLENBQUMsQ0FBQyxPQUFPLEtBQUssQ0FBQyxDQUFDLEdBQUcsSUFBSSxHQUFHLENBQUMsQ0FBQyxFQUFFLENBQUM7UUFDL0MsSUFBSSxDQUFDLEdBQUcsSUFBSSxHQUFHLENBQUMsRUFBRTtZQUNoQixJQUFJLElBQUksSUFBSSxDQUFDO1NBQ2Q7S0FDRjtJQUVELE9BQU8sSUFBSSxDQUFDO0FBQ2QsQ0FBQztBQUVEOztHQUVHO0FBQ0gsU0FBUyxTQUFTLENBQUMsS0FBd0IsRUFBRSxJQUFjO0lBQ3pELE1BQU0sSUFBSSxHQUFHLEtBQUssQ0FBQyxNQUFNLENBQUM7SUFFMUIsSUFBSSxJQUFJLEtBQUssQ0FBQyxFQUFFO1FBQ2QsT0FBTyxpQkFBaUIsQ0FBQztLQUMxQjtJQUVELElBQUksSUFBSSxLQUFLLENBQUMsRUFBRTtRQUNkLE9BQU87d0JBQ2EsS0FBSyxDQUFDLENBQUMsQ0FBQztpQkFDZixDQUFDO0tBQ2Y7SUFFRCxNQUFNLE9BQU8sR0FBRyxNQUFNLENBQUM7SUFDdkIsTUFBTSxPQUFPLEdBQUcsUUFBUSxDQUFDO0lBQ3pCLE1BQU0sT0FBTyxHQUFHLFFBQVEsQ0FBQztJQUN6QixNQUFNLE9BQU8sR0FBRyxVQUFVLENBQUM7SUFDM0IsSUFBSSxDQUFDLEdBQUcsRUFBRSxDQUFDO0lBQ1gsSUFBSSxJQUFJLEdBQUcsQ0FBQyxFQUFFO1FBQ1osS0FBSyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLElBQUksR0FBRyxDQUFDLEVBQUUsRUFBRSxDQUFDLEVBQUU7WUFDakMsQ0FBQyxHQUFHLENBQUMsR0FBRyxHQUFHLElBQUksQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDO1NBQ3ZCO0tBQ0Y7SUFDRCxPQUFPLFFBQVEsQ0FBQyxHQUFHLE9BQU87OEJBQ0UsQ0FBQyxHQUFHLE9BQU87OEJBQ1gsQ0FBQyxHQUFHLE9BQU87dUNBQ0YsQ0FBQyxHQUFHLE9BQU8sR0FBRyxDQUFDO0FBQ3RELENBQUM7QUFFRDs7R0FFRztBQUNILFNBQVMsUUFBUSxDQUFDLElBQVksRUFBRSxJQUFjLEVBQUUsSUFBWSxFQUFFLElBQVk7SUFDeEUsSUFBSSxJQUFJLEtBQUssQ0FBQyxJQUFJLElBQUksS0FBSyxDQUFDLEVBQUU7UUFDNUIsT0FBTyxFQUFFLENBQUM7S0FDWDtJQUNELG1DQUFtQztTQUM5QjtRQUNILE1BQU0sS0FBSyxHQUFHO2NBQ0osSUFBSSxDQUFDLElBQUksR0FBRyxDQUFDLENBQUM7Y0FDZCxJQUFJLENBQUMsSUFBSSxHQUFHLENBQUMsQ0FBQztnQkFDWixJQUFJLENBQUMsSUFBSSxHQUFHLENBQUMsQ0FBQztnQkFDZCxJQUFJLENBQUMsSUFBSSxHQUFHLENBQUMsQ0FBQzswQkFDSixJQUFJOzBCQUNKLElBQUk7S0FDekIsQ0FBQztRQUNGLE9BQU8sS0FBSyxDQUFDO0tBQ2Q7QUFDSCxDQUFDOzs7Ozs7Ozs7Ozs7O0FDeklELDREQUE0RDtBQUM1RCxrQ0FBa0M7OztBQUVsQyw0RkFBdUM7QUFFdkMsU0FBZ0IsY0FBYyxDQUFDLElBQVksRUFBRSxJQUFZO0lBQ3ZELE9BQU8seUJBQWEsRUFBQyxJQUFJLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxHQUFHLElBQUksSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDO0FBQ3RELENBQUM7QUFGRCx3Q0FFQztBQUVELFNBQWdCLFdBQVcsQ0FBQyxJQUFZLEVBQUUsSUFBWTtJQUNwRCxJQUFJLElBQUksS0FBSyxDQUFDLEVBQUU7UUFDZCxPQUFPLENBQUMsSUFBSSxDQUFDLENBQUM7S0FDZjtJQUNELE9BQU8sY0FBYyxDQUFDLElBQUksRUFBRSxJQUFJLENBQUMsQ0FBQztBQUNwQyxDQUFDO0FBTEQsa0NBS0M7QUFFRCxTQUFnQixpQkFBaUI7SUFDL0IsT0FBTzs7Ozs7Ozs7Ozs7O0dBWU4sQ0FBQztBQUNKLENBQUM7QUFkRCw4Q0FjQzs7Ozs7Ozs7Ozs7OztBQzlCRCw0REFBNEQ7QUFDNUQsa0NBQWtDOzs7QUFFbEMsNElBQXFHO0FBSXJHLGdGQUF3QztBQUN4Qyw4R0FBNkM7QUFFN0MsNEZBQWtEO0FBUWxELE1BQU0sa0JBQWtCLEdBQUc7SUFDekIsSUFBSSxFQUFFLEtBQUs7SUFDWCxVQUFVLEVBQUUsQ0FBQyxHQUFHLENBQUM7SUFDakIsVUFBVSxFQUFFLENBQUMsbUJBQVcsQ0FBQyxRQUFRLENBQUM7Q0FDbkMsQ0FBQztBQUVLLE1BQU0sS0FBSyxHQUNkLENBQUMsZ0JBQXVDLEVBQUUsTUFBZ0IsRUFBRSxVQUF5QixFQUFZLEVBQUU7SUFDakcsZ0JBQWdCLENBQUMsTUFBTSxDQUFDLENBQUM7SUFDekIsTUFBTSxNQUFNLEdBQUcsZ0JBQWdCLENBQUMsR0FBRyxpQ0FFMUIsa0JBQWtCLEtBQ3JCLFNBQVMsRUFBRSxVQUFVLENBQUMsUUFBUSxFQUM5QixHQUFHLEVBQUUsR0FBRyxFQUFFLENBQUMsb0JBQW9CLENBQUMsZ0JBQWdCLEVBQUUsTUFBTSxDQUFDLENBQUMsQ0FBQyxFQUFFLFVBQVUsQ0FBQyxLQUUxRSxNQUFNLENBQUMsQ0FBQztJQUNaLE9BQU8sQ0FBQyxNQUFNLENBQUMsQ0FBQztBQUNsQixDQUFDLENBQUM7QUFYTyxhQUFLLFNBV1o7QUFFQyxNQUFNLG9CQUFvQixHQUEwQyxDQUFDLElBQWdCLEVBQWlCLEVBQUU7SUFDN0csTUFBTSxJQUFJLEdBQUcsSUFBSSxDQUFDLFVBQVUsQ0FBQyxTQUFTLENBQUMsTUFBTSxFQUFFLFVBQVUsQ0FBQyxDQUFDO0lBQzNELE1BQU0sS0FBSyxHQUFHLElBQUksQ0FBQyxVQUFVLENBQUMsUUFBUSxDQUFDLE9BQU8sRUFBRSxHQUFHLENBQUMsQ0FBQztJQUNyRCxNQUFNLElBQUksR0FBRyxJQUFJLENBQUMsVUFBVSxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsQ0FBQztJQUM3QyxPQUFPLDBEQUEyQixFQUFDLEVBQUMsSUFBSSxFQUFFLEtBQUssRUFBRSxJQUFJLEVBQUMsQ0FBQyxDQUFDO0FBQzFELENBQUMsQ0FBQztBQUxXLDRCQUFvQix3QkFLL0I7QUFFSyxNQUFNLE1BQU0sR0FDZixDQUFDLGdCQUF1QyxFQUFFLE1BQWdCLEVBQUUsSUFBWSxFQUFZLEVBQUU7SUFDcEYsaUJBQWlCLENBQUMsTUFBTSxDQUFDLENBQUM7SUFDMUIsTUFBTSxVQUFVLEdBQUcsK0JBQStCLENBQUMsZ0JBQWdCLEVBQUUsTUFBTSxFQUFFLElBQUksQ0FBQyxDQUFDO0lBQ25GLE9BQU8saUJBQUssRUFBQyxnQkFBZ0IsRUFBRSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLFVBQVUsQ0FBQyxDQUFDO0FBQzFELENBQUMsQ0FBQztBQUxPLGNBQU0sVUFLYjtBQUVDLE1BQU0scUJBQXFCLEdBQW1DLENBQUMsSUFBZ0IsRUFBVSxFQUFFLENBQzlGLElBQUksQ0FBQyxVQUFVLENBQUMsU0FBUyxDQUFDLE1BQU0sRUFBRSxVQUFVLENBQUMsQ0FBQztBQURyQyw2QkFBcUIseUJBQ2dCO0FBRWxELE1BQU0sK0JBQStCLEdBQ2pDLENBQUMsZ0JBQXVDLEVBQUUsTUFBZ0IsRUFBRSxJQUFZLEVBQWlCLEVBQUU7SUFDekYsSUFBSSxDQUFDLGdCQUFnQixDQUFDLE9BQU8sQ0FBQyxhQUFhLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQztRQUN6RCxDQUFDLE1BQU0sQ0FBQyxNQUFNLElBQUksQ0FBQyxJQUFJLENBQUMsZ0JBQWdCLENBQUMsT0FBTyxDQUFDLGFBQWEsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUMsRUFBRTtRQUNyRixNQUFNLElBQUksS0FBSyxDQUFDLHdDQUF3QyxDQUFDLENBQUM7S0FDM0Q7SUFFRCxNQUFNLElBQUksR0FBRyxLQUFLLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxXQUFXLENBQUMsQ0FBQztJQUMvQyxNQUFNLEtBQUssR0FBRyxDQUFDLE1BQU0sQ0FBQyxNQUFNLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQztJQUVsRSxPQUFPLDBEQUEyQixFQUFDLEVBQUMsSUFBSSxFQUFFLElBQUksRUFBRSxLQUFLLEVBQUMsQ0FBQyxDQUFDO0FBQzFELENBQUMsQ0FBQztBQUVOLE1BQU0sb0JBQW9CLEdBQ3RCLENBQUMsZ0JBQXVDLEVBQUUsS0FBYSxFQUFFLFVBQXlCLEVBQWUsRUFBRTtJQUNqRyxNQUFNLFdBQVcsR0FBRyxnQkFBUyxDQUFDLFFBQVEsQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLEtBQUssRUFBRSxFQUFFLFVBQVUsQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUM1RSxNQUFNLElBQUksR0FBRyxXQUFXLENBQUMsTUFBTSxDQUFDO0lBQ2hDLE1BQU0sV0FBVyxHQUFHLGNBQWMsQ0FBQyxnQkFBZ0IsRUFBRSxLQUFLLEVBQUUsVUFBVSxDQUFDLENBQUM7SUFDeEUsTUFBTSxZQUFZLEdBQUc7UUFDbkIsV0FBVzswQkFDTyxJQUFJOztRQUV0QixDQUFDO0lBQ0gsT0FBTztRQUNMLElBQUksRUFBRSxLQUFLO1FBQ1gsVUFBVSxFQUFFLENBQUMsR0FBRyxDQUFDO1FBQ2pCLFVBQVUsRUFBRSxDQUFDLG1CQUFXLENBQUMsUUFBUSxDQUFDO1FBQ2xDLE1BQU0sRUFBRSxFQUFDLElBQUksRUFBRSxXQUFXLEVBQUUsSUFBSSxFQUFFLEtBQUssQ0FBQyxJQUFJLEVBQUUsV0FBVyxFQUFFLG1CQUFXLENBQUMsUUFBUSxFQUFDO1FBQ2hGLFlBQVk7S0FDYixDQUFDO0FBQ0osQ0FBQyxDQUFDO0FBRU4sTUFBTSxnQkFBZ0IsR0FBRyxDQUFDLE1BQWdCLEVBQVEsRUFBRTtJQUNsRCxJQUFJLENBQUMsTUFBTSxJQUFJLE1BQU0sQ0FBQyxNQUFNLEtBQUssQ0FBQyxFQUFFO1FBQ2xDLE1BQU0sSUFBSSxLQUFLLENBQUMsc0JBQXNCLENBQUMsQ0FBQztLQUN6QztJQUNELElBQUksTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksS0FBSyxTQUFTLElBQUksTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksS0FBSyxTQUFTLEVBQUU7UUFDaEUsTUFBTSxJQUFJLEtBQUssQ0FBQyxxQkFBcUIsQ0FBQyxDQUFDO0tBQ3hDO0FBQ0gsQ0FBQyxDQUFDO0FBRUYsTUFBTSxpQkFBaUIsR0FBRyxDQUFDLE1BQWdCLEVBQVEsRUFBRTtJQUNuRCxJQUFJLENBQUMsTUFBTSxJQUFJLENBQUMsTUFBTSxDQUFDLE1BQU0sS0FBSyxDQUFDLElBQUksTUFBTSxDQUFDLE1BQU0sS0FBSyxDQUFDLENBQUMsRUFBRTtRQUMzRCxNQUFNLElBQUksS0FBSyxDQUFDLDRCQUE0QixDQUFDLENBQUM7S0FDL0M7SUFDRCxJQUFJLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLEtBQUssT0FBTyxFQUFFO1FBQzlCLE1BQU0sSUFBSSxLQUFLLENBQUMscUJBQXFCLENBQUMsQ0FBQztLQUN4QztJQUNELElBQUksTUFBTSxDQUFDLE1BQU0sSUFBSSxDQUFDLElBQUksTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksS0FBSyxRQUFRLEVBQUU7UUFDckQsTUFBTSxJQUFJLEtBQUssQ0FBQyxxQkFBcUIsQ0FBQyxDQUFDO0tBQ3hDO0FBQ0gsQ0FBQyxDQUFDO0FBRUYsTUFBTSxjQUFjLEdBQUcsQ0FBQyxnQkFBdUMsRUFBRSxLQUFhLEVBQUUsVUFBeUIsRUFBVSxFQUFFO0lBQ25ILE1BQU0sSUFBSSxHQUFHLHlCQUFPLEVBQUMsZ0JBQWdCLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxTQUFTLENBQUMsT0FBTyxDQUFDLENBQUM7SUFDekUsTUFBTSxDQUFDLEtBQUssRUFBRSxNQUFNLENBQUMsR0FBRyxnQkFBZ0IsQ0FBQyw4QkFBOEIsQ0FBQyxLQUFLLENBQUMsSUFBSSxFQUFFLG1CQUFXLENBQUMsUUFBUSxDQUFDLENBQUM7SUFDMUcsTUFBTSxPQUFPLEdBQUcsZ0JBQVMsQ0FBQyxjQUFjLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxDQUFDO0lBRXJELFFBQVEsVUFBVSxDQUFDLElBQUksRUFBRTtRQUN2QixLQUFLLFVBQVU7WUFDYixPQUFPLGNBQWMsQ0FBQyxJQUFJLEVBQUUsS0FBSyxDQUFDLElBQUksRUFBRSxPQUFPLEVBQUUsS0FBSyxFQUFFLE1BQU0sRUFBRSxVQUFVLENBQUMsSUFBSSxFQUFFLFVBQVUsQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUNyRyxLQUFLLFNBQVM7WUFDWixPQUFPLGFBQWEsQ0FBQyxJQUFJLEVBQUUsS0FBSyxDQUFDLElBQUksRUFBRSxPQUFPLEVBQUUsS0FBSyxFQUFFLE1BQU0sRUFBRSxVQUFVLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDbEYsS0FBSyxNQUFNO1lBQ1QsT0FBTyxVQUFVLENBQUMsSUFBSSxFQUFFLEtBQUssQ0FBQyxJQUFJLEVBQUUsT0FBTyxFQUFFLEtBQUssRUFBRSxNQUFNLEVBQUUsVUFBVSxDQUFDLElBQUksQ0FBQyxDQUFDO1FBQy9FO1lBQ0UsTUFBTSxJQUFJLEtBQUssQ0FBQyxjQUFjLENBQUMsQ0FBQztLQUNuQztBQUNILENBQUMsQ0FBQztBQUVGLE1BQU0sY0FBYyxHQUNoQixDQUFDLElBQVUsRUFBRSxLQUF3QixFQUFFLE9BQTBCLEVBQUUsS0FBYSxFQUFFLE1BQWMsRUFBRSxJQUFjLEVBQy9HLEtBQWEsRUFBVSxFQUFFO0lBQ3hCLE1BQU0sSUFBSSxHQUFHLEtBQUssQ0FBQyxNQUFNLENBQUM7SUFDMUIsSUFBSSxLQUFLLEdBQUcsRUFBRSxDQUFDO0lBQ2YsS0FBSyxJQUFJLENBQUMsR0FBRyxJQUFJLEdBQUcsQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLEVBQUUsRUFBRSxDQUFDLEVBQUU7UUFDbEMsS0FBSyxJQUFJO2dCQUNELENBQUMsT0FBTyxJQUFJLENBQUMsQ0FBQyxDQUFDOzttQkFFWixLQUFLLENBQUMsQ0FBQyxDQUFDO3dCQUNILE9BQU8sQ0FBQyxDQUFDLENBQUM7U0FDekIsQ0FBQztLQUNIO0lBQ0QsT0FBTzt5QkFDWSxJQUFJO3VDQUNVLEtBQUs7OztVQUdsQyxLQUFLOytDQUNnQyxLQUFLLEtBQUssTUFBTTt3Q0FDdkIsSUFBSSxDQUFDLFNBQVM7OztPQUcvQyxDQUFDO0FBQ0osQ0FBQyxDQUFDO0FBRU4sTUFBTSxhQUFhLEdBQ2YsQ0FBQyxJQUFVLEVBQUUsS0FBd0IsRUFBRSxPQUEwQixFQUFFLEtBQWEsRUFBRSxNQUFjLEVBQUUsSUFBYyxFQUNyRyxFQUFFO0lBQ1AsTUFBTSxJQUFJLEdBQUcsS0FBSyxDQUFDLE1BQU0sQ0FBQztJQUUxQixJQUFJLEtBQUssR0FBRyxFQUFFLENBQUM7SUFDZixLQUFLLElBQUksQ0FBQyxHQUFHLElBQUksR0FBRyxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsRUFBRSxFQUFFLENBQUMsRUFBRTtRQUNsQyxLQUFLLElBQUk7Z0JBQ0wsQ0FBQyxPQUFPLElBQUksQ0FBQyxDQUFDLENBQUM7Ozs4QkFHRCxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDOztvQkFFNUIsS0FBSyxDQUFDLENBQUMsQ0FBQzs7d0JBRUosT0FBTyxDQUFDLENBQUMsQ0FBQztTQUN6QixDQUFDO0tBQ0M7SUFDRCxPQUFPO3lCQUNRLElBQUk7OztVQUduQixLQUFLOytDQUNnQyxLQUFLLEtBQUssTUFBTTt3Q0FDdkIsSUFBSSxDQUFDLFNBQVM7OztPQUcvQyxDQUFDO0FBQ0EsQ0FBQyxDQUFDO0FBRVYsTUFBTSxVQUFVLEdBQ1osQ0FBQyxJQUFVLEVBQUUsS0FBd0IsRUFBRSxPQUEwQixFQUFFLEtBQWEsRUFBRSxNQUFjLEVBQUUsSUFBYyxFQUNyRyxFQUFFO0lBQ1AsTUFBTSxJQUFJLEdBQUcsS0FBSyxDQUFDLE1BQU0sQ0FBQztJQUUxQixJQUFJLEtBQUssR0FBRyxFQUFFLENBQUM7SUFDZixLQUFLLElBQUksQ0FBQyxHQUFHLElBQUksR0FBRyxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsRUFBRSxFQUFFLENBQUMsRUFBRTtRQUNsQyxLQUFLLElBQUk7Z0JBQ0wsQ0FBQyxPQUFPLElBQUksQ0FBQyxDQUFDLENBQUM7O21CQUVaLEtBQUssQ0FBQyxDQUFDLENBQUMsU0FBUyxLQUFLLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQzt3QkFDeEIsT0FBTyxDQUFDLENBQUMsQ0FBQztPQUMzQixDQUFDO0tBQ0c7SUFDRCxPQUFPO3lCQUNRLElBQUk7OztVQUduQixLQUFLOytDQUNnQyxLQUFLLEtBQUssTUFBTTt3Q0FDdkIsSUFBSSxDQUFDLFNBQVM7OztPQUcvQyxDQUFDO0FBQ0EsQ0FBQyxDQUFDOzs7Ozs7Ozs7Ozs7O0FDNU1WLDREQUE0RDtBQUM1RCxrQ0FBa0M7OztBQUVsQyw0SUFBcUc7QUFJckcsZ0ZBQXNEO0FBRXRELDRGQUFtRTtBQVc1RCxNQUFNLFdBQVcsR0FDcEIsQ0FBQyxnQkFBdUMsRUFBRSxNQUFnQixFQUFFLFVBQWlDLEVBQVksRUFBRTtJQUN6RyxjQUFjLENBQUMsTUFBTSxDQUFDLENBQUM7SUFDdkIsTUFBTSxRQUFRLEdBQ1YsRUFBQyxJQUFJLEVBQUUsYUFBYSxFQUFFLFVBQVUsRUFBRSxDQUFDLEdBQUcsQ0FBQyxFQUFFLFVBQVUsRUFBRSxDQUFDLG1CQUFXLENBQUMsUUFBUSxDQUFDLEVBQUUsU0FBUyxFQUFFLFVBQVUsQ0FBQyxRQUFRLEVBQUMsQ0FBQztJQUNqSCxNQUFNLE1BQU0sR0FBRyxnQkFBZ0IsQ0FBQyxHQUFHLGlDQUMzQixRQUFRLEtBQUUsR0FBRyxFQUFFLEdBQUcsRUFBRSxDQUFDLDRCQUE0QixDQUFDLE1BQU0sRUFBRSxRQUFRLEVBQUUsS0FBSyxFQUFFLFVBQVUsQ0FBQyxLQUFHLE1BQU0sQ0FBQyxDQUFDO0lBQ3pHLE9BQU8sQ0FBQyxNQUFNLENBQUMsQ0FBQztBQUNsQixDQUFDLENBQUM7QUFSTyxtQkFBVyxlQVFsQjtBQUVDLE1BQU0sMEJBQTBCLEdBQ25DLENBQUMsSUFBZ0IsRUFBeUIsRUFBRTtJQUMxQyxNQUFNLE9BQU8sR0FBRyxJQUFJLENBQUMsVUFBVSxDQUFDLFNBQVMsQ0FBQyxVQUFVLEVBQUUsUUFBUSxDQUFDLENBQUM7SUFDaEUsTUFBTSxRQUFRLEdBQUcsSUFBSSxDQUFDLFVBQVUsQ0FBQyxNQUFNLENBQUMsV0FBVyxFQUFFLENBQUMsQ0FBQyxDQUFDO0lBQ3hELE1BQU0sZUFBZSxHQUFHLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxNQUFNLENBQUMsbUJBQW1CLEVBQUUsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQzlGLE1BQU0sV0FBVyxHQUFHLElBQUksQ0FBQyxVQUFVLENBQUMsT0FBTyxDQUFDLGNBQWMsQ0FBQyxDQUFDO0lBQzVELE1BQU0sT0FBTyxHQUFHLElBQUksQ0FBQyxVQUFVLENBQUMsT0FBTyxDQUFDLFNBQVMsRUFBRSxFQUFFLENBQUMsQ0FBQztJQUN2RCxNQUFNLElBQUksR0FBRyxJQUFJLENBQUMsVUFBVSxDQUFDLE9BQU8sQ0FBQyxNQUFNLEVBQUUsRUFBRSxDQUFDLENBQUM7SUFFakQsc0NBQXNDO0lBQ3RDLElBQUksUUFBUSxLQUFLLENBQUMsRUFBRTtRQUNsQixNQUFNLElBQUksS0FBSyxDQUFDLHdFQUF3RSxDQUFDLENBQUM7S0FDM0Y7SUFFRCxPQUFPLDBEQUEyQixFQUFDLEVBQUMsT0FBTyxFQUFFLFFBQVEsRUFBRSxlQUFlLEVBQUUsV0FBVyxFQUFFLE9BQU8sRUFBRSxJQUFJLEVBQUMsQ0FBQyxDQUFDO0FBQ3ZHLENBQUMsQ0FBQztBQWZPLGtDQUEwQiw4QkFlakM7QUFFTixNQUFNLDRCQUE0QixHQUM5QixDQUFDLE1BQWdCLEVBQUUsUUFBeUIsRUFBRSxnQkFBeUIsRUFBRSxVQUFpQyxFQUMxRixFQUFFO0lBQ1osTUFBTSxDQUFDLGtCQUFrQixFQUFFLFdBQVcsQ0FBQyxHQUNuQyx1Q0FBdUMsQ0FBQyxNQUFNLEVBQUUsVUFBVSxFQUFFLGdCQUFnQixDQUFDLENBQUM7SUFDbEYsTUFBTSxVQUFVLEdBQUcsZ0JBQVMsQ0FBQyxJQUFJLENBQUMsa0JBQWtCLENBQUMsV0FBVyxDQUFDLENBQUM7SUFDbEUsTUFBTSxHQUFHLEdBQUcsaUJBQWlCLENBQUM7SUFDOUIsSUFBSSxHQUFHLEdBQUcsRUFBRSxDQUFDO0lBQ2IsSUFBSSxrQkFBa0IsQ0FBQyxlQUFlLEVBQUU7UUFDdEMsR0FBRyxJQUFJLGtCQUFrQixVQUFVLElBQUksQ0FBQztLQUN6QztTQUFNO1FBQ0wsR0FBRyxJQUFJLGtCQUFrQixVQUFVLFVBQVUsQ0FBQztLQUMvQztJQUNELE1BQU0sV0FBVyxHQUFHLG1CQUFtQixDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLEVBQUUsa0JBQWtCLEVBQUUsR0FBRyxFQUFFLEdBQUcsRUFBRSxLQUFLLENBQUMsQ0FBQztJQUM3RixNQUFNLFlBQVksR0FBRztVQUNyQixXQUFXO09BQ2QsQ0FBQztJQUNFLHVDQUNLLFFBQVEsS0FDWCxNQUFNLEVBQUUsRUFBQyxJQUFJLEVBQUUsV0FBVyxFQUFFLElBQUksRUFBRSxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxFQUFFLFdBQVcsRUFBRSxtQkFBVyxDQUFDLFFBQVEsRUFBQyxFQUNwRixZQUFZLElBQ1o7QUFDSixDQUFDLENBQUM7QUFFSCxNQUFNLGlCQUFpQixHQUMxQixDQUFDLGdCQUF1QyxFQUFFLE1BQWdCLEVBQUUsVUFBaUMsRUFBWSxFQUFFO0lBQ3pHLGNBQWMsQ0FBQyxNQUFNLENBQUMsQ0FBQztJQUN2QixNQUFNLFFBQVEsR0FBRztRQUNmLElBQUksRUFBRSxtQkFBbUI7UUFDekIsVUFBVSxFQUFFLENBQUMsR0FBRyxDQUFDO1FBQ2pCLFVBQVUsRUFBRSxDQUFDLG1CQUFXLENBQUMsUUFBUSxDQUFDO1FBQ2xDLFNBQVMsRUFBRSxHQUFHLFVBQVUsQ0FBQyxlQUFlLEVBQUU7S0FDM0MsQ0FBQztJQUNGLE1BQU0sTUFBTSxHQUFHLGdCQUFnQixDQUFDLEdBQUcsaUNBQzNCLFFBQVEsS0FBRSxHQUFHLEVBQUUsR0FBRyxFQUFFLENBQUMsNEJBQTRCLENBQUMsTUFBTSxFQUFFLFFBQVEsRUFBRSxJQUFJLEVBQUUsVUFBVSxDQUFDLEtBQUcsTUFBTSxDQUFDLENBQUM7SUFDeEcsT0FBTyxDQUFDLE1BQU0sQ0FBQyxDQUFDO0FBQ2xCLENBQUMsQ0FBQztBQVpPLHlCQUFpQixxQkFZeEI7QUFFQyxNQUFNLGdDQUFnQyxHQUN6QyxDQUFDLElBQWdCLEVBQXlCLEVBQUU7SUFDMUMsTUFBTSxlQUFlLEdBQUcsQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLE1BQU0sQ0FBQyxtQkFBbUIsRUFBRSxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDOUYsT0FBTywwREFBMkIsRUFDOUIsRUFBQyxPQUFPLEVBQUUsRUFBRSxFQUFFLFFBQVEsRUFBRSxDQUFDLEVBQUUsZUFBZSxFQUFFLFdBQVcsRUFBRSxFQUFFLEVBQUUsT0FBTyxFQUFFLEVBQUUsRUFBRSxJQUFJLEVBQUUsRUFBRSxFQUFDLENBQUMsQ0FBQztBQUMzRixDQUFDLENBQUM7QUFMTyx3Q0FBZ0Msb0NBS3ZDO0FBT0MsTUFBTSxPQUFPLEdBQ2hCLENBQUMsZ0JBQXVDLEVBQUUsTUFBZ0IsRUFBRSxVQUE2QixFQUFZLEVBQUU7SUFDckcsY0FBYyxDQUFDLE1BQU0sQ0FBQyxDQUFDO0lBQ3ZCLE1BQU0sUUFBUSxHQUNWLEVBQUMsSUFBSSxFQUFFLFNBQVMsRUFBRSxVQUFVLEVBQUUsQ0FBQyxHQUFHLENBQUMsRUFBRSxVQUFVLEVBQUUsQ0FBQyxtQkFBVyxDQUFDLFFBQVEsQ0FBQyxFQUFFLFNBQVMsRUFBRSxVQUFVLENBQUMsUUFBUSxFQUFDLENBQUM7SUFDN0csTUFBTSxNQUFNLEdBQUcsZ0JBQWdCLENBQUMsR0FBRyxpQ0FDM0IsUUFBUSxLQUFFLEdBQUcsRUFBRSxHQUFHLEVBQUUsQ0FBQyx3QkFBd0IsQ0FBQyxNQUFNLEVBQUUsUUFBUSxFQUFFLEtBQUssRUFBRSxVQUFVLENBQUMsS0FBRyxNQUFNLENBQUMsQ0FBQztJQUNyRyxPQUFPLENBQUMsTUFBTSxDQUFDLENBQUM7QUFDbEIsQ0FBQyxDQUFDO0FBUk8sZUFBTyxXQVFkO0FBRUMsTUFBTSxzQkFBc0IsR0FDL0IsQ0FBQyxJQUFnQixFQUFxQixFQUFFO0lBQ3RDLE1BQU0sT0FBTyxHQUFHLElBQUksQ0FBQyxVQUFVLENBQUMsU0FBUyxDQUFDLFVBQVUsRUFBRSxRQUFRLENBQUMsQ0FBQztJQUNoRSxNQUFNLFFBQVEsR0FBRyxJQUFJLENBQUMsVUFBVSxDQUFDLE1BQU0sQ0FBQyxXQUFXLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDeEQsTUFBTSxXQUFXLEdBQUcsSUFBSSxDQUFDLFVBQVUsQ0FBQyxPQUFPLENBQUMsY0FBYyxDQUFDLENBQUM7SUFDNUQsTUFBTSxPQUFPLEdBQUcsSUFBSSxDQUFDLFVBQVUsQ0FBQyxPQUFPLENBQUMsU0FBUyxFQUFFLEVBQUUsQ0FBQyxDQUFDO0lBQ3ZELE1BQU0sSUFBSSxHQUFHLElBQUksQ0FBQyxVQUFVLENBQUMsT0FBTyxDQUFDLE1BQU0sRUFBRSxFQUFFLENBQUMsQ0FBQztJQUNqRCxNQUFNLFlBQVksR0FBRyxJQUFJLENBQUMsVUFBVSxDQUFDLE1BQU0sQ0FBQyxlQUFlLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDaEUsTUFBTSxTQUFTLEdBQUcsSUFBSSxDQUFDLFVBQVUsQ0FBQyxPQUFPLENBQUMsV0FBVyxFQUFFLEVBQUUsQ0FBQyxDQUFDO0lBRTNELDBEQUEwRDtJQUMxRCxJQUFJLFlBQVksS0FBSyxDQUFDLEVBQUU7UUFDdEIsTUFBTSxJQUFJLEtBQUssQ0FBQyw2REFBNkQsQ0FBQyxDQUFDO0tBQ2hGO0lBQ0QsSUFBSSxRQUFRLEtBQUssQ0FBQyxFQUFFO1FBQ2xCLE1BQU0sSUFBSSxLQUFLLENBQUMsb0VBQW9FLENBQUMsQ0FBQztLQUN2RjtJQUVELE9BQU8sMERBQTJCLEVBQzlCLEVBQUMsT0FBTyxFQUFFLFFBQVEsRUFBRSxlQUFlLEVBQUUsS0FBSyxFQUFFLFdBQVcsRUFBRSxPQUFPLEVBQUUsSUFBSSxFQUFFLFlBQVksRUFBRSxTQUFTLEVBQUMsQ0FBQyxDQUFDO0FBQ3hHLENBQUMsQ0FBQztBQXBCTyw4QkFBc0IsMEJBb0I3QjtBQUVOLE1BQU0sd0JBQXdCLEdBQzFCLENBQUMsTUFBZ0IsRUFBRSxRQUF5QixFQUFFLGdCQUF5QixFQUFFLFVBQTZCLEVBQ3RGLEVBQUU7SUFDWixNQUFNLENBQUMsa0JBQWtCLEVBQUUsV0FBVyxDQUFDLEdBQ25DLHVDQUF1QyxDQUFDLE1BQU0sRUFBRSxVQUFVLEVBQUUsZ0JBQWdCLENBQUMsQ0FBQztJQUNsRixNQUFNLEdBQUcsR0FBRzs7S0FFakIsQ0FBQztJQUNJLE1BQU0sR0FBRyxHQUFHLEVBQUUsQ0FBQztJQUNmLE1BQU0sV0FBVyxHQUFHLG1CQUFtQixDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLEVBQUUsa0JBQWtCLEVBQUUsR0FBRyxFQUFFLEdBQUcsRUFBRSxNQUFNLENBQUMsQ0FBQztJQUM5RixNQUFNLFlBQVksR0FBRztRQUN2QixXQUFXO0tBQ2QsQ0FBQztJQUNJLHVDQUNLLFFBQVEsS0FDWCxNQUFNLEVBQUUsRUFBQyxJQUFJLEVBQUUsV0FBVyxFQUFFLElBQUksRUFBRSxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxFQUFFLFdBQVcsRUFBRSxtQkFBVyxDQUFDLFFBQVEsRUFBQyxFQUNwRixZQUFZLElBQ1o7QUFDSixDQUFDLENBQUM7QUFFVixNQUFNLHVDQUF1QyxHQUN6QyxDQUFDLE1BQWdCLEVBQUUsVUFBbUQsRUFBRSxnQkFBeUIsRUFDekMsRUFBRTtJQUNwRCxNQUFNLFVBQVUsR0FBRyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLEtBQUssRUFBRSxDQUFDO0lBQzFDLE1BQU0sWUFBWSxHQUFHLE1BQU0sQ0FBQyxjQUFjLENBQUMsSUFBSSxDQUFDLFVBQVUsRUFBRSxXQUFXLENBQUMsQ0FBQztJQUN6RSxNQUFNLFdBQVcsR0FBRyxVQUFVLENBQUMsV0FBVyxDQUFDLEtBQUssRUFBRSxDQUFDO0lBQ25ELE1BQU0sT0FBTyxHQUFHLFVBQVUsQ0FBQyxPQUFPLENBQUMsS0FBSyxFQUFFLENBQUM7SUFDM0MsTUFBTSxTQUFTLEdBQWEsWUFBWSxDQUFDLENBQUMsQ0FBRSxVQUFnQyxDQUFDLFNBQVMsQ0FBQyxLQUFLLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO0lBQ3BHLE1BQU0sSUFBSSxHQUFHLFVBQVUsQ0FBQyxJQUFJLENBQUMsS0FBSyxFQUFFLENBQUM7SUFDckMsbUJBQVksQ0FBQyxvQkFBb0IsQ0FBQyxnQkFBZ0IsRUFBRSxVQUFVLEVBQUUsV0FBVyxFQUFFLE9BQU8sRUFBRSxTQUFTLEVBQUUsSUFBSSxDQUFDLENBQUM7SUFFdkcsTUFBTSxXQUFXLEdBQUcsbUJBQVksQ0FBQyxzQkFBc0IsQ0FDbkQsZ0JBQWdCLEVBQUUsVUFBVSxFQUFFLE9BQU8sRUFBRSxTQUFTLEVBQUUsV0FBVyxFQUFFLElBQUksRUFBRSxVQUFVLENBQUMsT0FBTyxDQUFDLENBQUM7SUFFN0YsTUFBTSxhQUFhLEdBQUcsTUFBTSxDQUFDLE1BQU0sQ0FBQyxFQUFFLEVBQUUsVUFBVSxDQUFDLENBQUM7SUFDcEQsSUFBSSxZQUFZLEVBQUU7UUFDaEIsTUFBTSxDQUFDLE1BQU0sQ0FBQyxhQUFhLEVBQUUsRUFBQyxXQUFXLEVBQUUsT0FBTyxFQUFFLElBQUksRUFBRSxTQUFTLEVBQUUsUUFBUSxFQUFFLFVBQVUsQ0FBQyxRQUFRLEVBQUMsQ0FBQyxDQUFDO0tBQ3RHO1NBQU07UUFDTCxNQUFNLENBQUMsTUFBTSxDQUFDLGFBQWEsRUFBRSxFQUFDLFdBQVcsRUFBRSxPQUFPLEVBQUUsSUFBSSxFQUFFLFFBQVEsRUFBRSxVQUFVLENBQUMsUUFBUSxFQUFDLENBQUMsQ0FBQztLQUMzRjtJQUNELE9BQU8sQ0FBQyxhQUFhLEVBQUUsV0FBVyxDQUFDLENBQUM7QUFDdEMsQ0FBQyxDQUFDO0FBRVYsTUFBTSx1QkFBdUIsR0FBRztJQUM5QixPQUFPLEVBQUUsRUFBRTtJQUNYLFFBQVEsRUFBRSxDQUFDO0lBQ1gsZUFBZSxFQUFFLEtBQUs7SUFDdEIsV0FBVyxFQUFFLEVBQUU7SUFDZixPQUFPLEVBQUUsRUFBRTtJQUNYLElBQUksRUFBRSxFQUFFO0lBQ1IsWUFBWSxFQUFFLENBQUM7SUFDZixTQUFTLEVBQUUsRUFBRTtJQUNiLFFBQVEsRUFBRSxFQUFFO0NBQ2IsQ0FBQztBQUVGLE1BQU0scUJBQXFCLEdBQUc7SUFDNUIsSUFBSSxFQUFFLGVBQWU7SUFDckIsVUFBVSxFQUFFLENBQUMsR0FBRyxDQUFDO0lBQ2pCLFVBQVUsRUFBRSxDQUFDLG1CQUFXLENBQUMsUUFBUSxDQUFDO0NBQ25DLENBQUM7QUFFSyxNQUFNLGFBQWEsR0FBRyxDQUFDLGdCQUF1QyxFQUFFLE1BQWdCLEVBQVksRUFBRTtJQUNuRyxjQUFjLENBQUMsTUFBTSxDQUFDLENBQUM7SUFDdkIsTUFBTSxNQUFNLEdBQUcsZ0JBQWdCLENBQUMsR0FBRyxpQ0FFMUIscUJBQXFCLEtBQ3hCLEdBQUcsRUFBRSxHQUFHLEVBQUUsQ0FBQyx3QkFBd0IsQ0FBQyxNQUFNLEVBQUUscUJBQXFCLEVBQUUsSUFBSSxFQUFFLHVCQUF1QixDQUFDLEtBRW5HLE1BQU0sQ0FBQyxDQUFDO0lBQ1osT0FBTyxDQUFDLE1BQU0sQ0FBQyxDQUFDO0FBQ2xCLENBQUMsQ0FBQztBQVRXLHFCQUFhLGlCQVN4QjtBQUVGLE1BQU0sY0FBYyxHQUFHLENBQUMsTUFBZ0IsRUFBUSxFQUFFO0lBQ2hELElBQUksQ0FBQyxNQUFNLElBQUksTUFBTSxDQUFDLE1BQU0sS0FBSyxDQUFDLEVBQUU7UUFDbEMsTUFBTSxJQUFJLEtBQUssQ0FBQyw0QkFBNEIsQ0FBQyxDQUFDO0tBQy9DO0lBQ0QsSUFBSSxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxLQUFLLFNBQVMsSUFBSSxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxLQUFLLFNBQVMsRUFBRTtRQUNoRSxNQUFNLElBQUksS0FBSyxDQUFDLHFCQUFxQixDQUFDLENBQUM7S0FDeEM7QUFDSCxDQUFDLENBQUM7QUFFRixNQUFNLG1CQUFtQixHQUNyQixDQUFDLFNBQTRCLEVBQUUsVUFBaUMsRUFBRSxHQUFXLEVBQUUsR0FBVyxFQUFFLEtBQWEsRUFDOUYsRUFBRTtJQUNQLE1BQU0sSUFBSSxHQUFHLFNBQVMsQ0FBQyxNQUFNLENBQUM7SUFDOUIsSUFBSSxVQUFVLENBQUMsV0FBVyxDQUFDLE1BQU0sSUFBSSxDQUFDLEVBQUU7UUFDdEMsTUFBTSxFQUFFLEdBQUcsVUFBVSxDQUFDLFdBQVcsQ0FBQyxVQUFVLENBQUMsV0FBVyxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUMsQ0FBQztRQUNyRSxNQUFNLEVBQUUsR0FBRyxVQUFVLENBQUMsT0FBTyxDQUFDLFVBQVUsQ0FBQyxPQUFPLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQyxDQUFDO1FBQzdELE1BQU0sT0FBTyxHQUFHLFVBQVUsQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxNQUFNLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDO1FBQ2hFLE1BQU0sS0FBSyxHQUFHLFVBQVUsQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFDLENBQUM7UUFDMUQsTUFBTSxJQUFJLEdBQUcsU0FBUyxDQUFDLElBQUksR0FBRyxDQUFDLENBQUMsQ0FBQztRQUNqQyxJQUFJLEtBQUssR0FBRyxFQUFFLENBQUM7UUFDZixJQUFJLEtBQUssR0FBRyxFQUFFLENBQUM7UUFDZixJQUFJLFFBQVEsR0FBRyxFQUFFLENBQUM7UUFDbEIsSUFBSSxPQUFPLEdBQUcsS0FBSyxLQUFLLENBQUMsRUFBRTtZQUN6QixLQUFLLEdBQUc7Z0NBQ1UsRUFBRTtnQkFDbEIsSUFBSSxtQkFBbUIsSUFBSSxXQUFXLEVBQUUsTUFBTSxPQUFPO29CQUNqRCxJQUFJLGtCQUFrQixJQUFJLFlBQVksSUFBSTs7OztjQUloRCxHQUFHO1lBQ0wsQ0FBQztTQUNBO2FBQU07WUFDTCxLQUFLLEdBQUc7Z0NBQ1UsRUFBRTtnQkFDbEIsSUFBSSxtQkFBbUIsSUFBSSxXQUFXLEVBQUUsTUFBTSxPQUFPO2NBQ3ZELEdBQUc7WUFDTCxDQUFDO1NBQ0E7UUFFRCxJQUFJLFVBQVUsQ0FBQyxXQUFXLENBQUMsTUFBTSxLQUFLLENBQUMsRUFBRTtZQUN2QyxNQUFNLEVBQUUsR0FBRyxVQUFVLENBQUMsV0FBVyxDQUFDLFVBQVUsQ0FBQyxXQUFXLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQyxDQUFDO1lBQ3JFLE1BQU0sRUFBRSxHQUFHLFVBQVUsQ0FBQyxPQUFPLENBQUMsVUFBVSxDQUFDLE9BQU8sQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFDLENBQUM7WUFDN0QsTUFBTSxPQUFPLEdBQUcsVUFBVSxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLE1BQU0sR0FBRyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUM7WUFDaEUsTUFBTSxLQUFLLEdBQUcsVUFBVSxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUMsQ0FBQztZQUMxRCxNQUFNLElBQUksR0FBRyxTQUFTLENBQUMsSUFBSSxHQUFHLENBQUMsQ0FBQyxDQUFDO1lBQ2pDLElBQUksT0FBTyxHQUFHLEtBQUssS0FBSyxDQUFDLEVBQUU7Z0JBQ3pCLEtBQUssR0FBRztrQ0FDVSxFQUFFO2tCQUNsQixJQUFJLG1CQUFtQixJQUFJLFdBQVcsRUFBRSxNQUFNLE9BQU87c0JBQ2pELElBQUksa0JBQWtCLElBQUksWUFBWSxJQUFJO3dCQUN4QyxFQUFFOzs7V0FHZixDQUFDO2FBQ0c7aUJBQU07Z0JBQ0wsS0FBSyxHQUFHO2tDQUNVLEVBQUU7a0JBQ2xCLElBQUksbUJBQW1CLElBQUksV0FBVyxFQUFFLE1BQU0sT0FBTzthQUMxRCxDQUFDO2FBQ0M7WUFDRCxRQUFRLEdBQUc7O1NBRWhCLENBQUM7U0FDRztRQUVELE1BQU0sV0FBVyxHQUFHO29DQUNJLElBQUk7a0JBQ3RCLElBQUk7OzswQkFHSSxLQUFLOztZQUVuQixLQUFLO1lBQ0wsS0FBSztZQUNMLFFBQVE7WUFDUixHQUFHOzs7T0FHUixDQUFDO1FBQ0ksT0FBTyxXQUFXLENBQUM7S0FDcEI7U0FBTTtRQUNMLE1BQU0sVUFBVSxHQUFHLGdCQUFTLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxXQUFXLENBQUMsQ0FBQztRQUMxRCxNQUFNLGFBQWEsR0FBRyxnQkFBUyxDQUFDLGNBQWMsQ0FBQyxVQUFVLENBQUMsV0FBVyxDQUFDLENBQUM7UUFDdkUsTUFBTSxXQUFXLEdBQUcsYUFBYSxDQUFDLE1BQU0sQ0FBQztRQUN6QyxNQUFNLFFBQVEsR0FBRyxVQUFVLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQztRQUN4QyxNQUFNLHVCQUF1QixHQUFHLGVBQWUsQ0FBQyxXQUFXLENBQUMsQ0FBQztRQUM3RCxNQUFNLGFBQWEsR0FBRyxTQUFTLENBQUMsU0FBUyxFQUFFLFdBQVcsQ0FBQyxDQUFDO1FBQ3hELE1BQU0sUUFBUSxHQUFHLFNBQVMsQ0FBQyxVQUFVLENBQUMsSUFBSSxFQUFFLE1BQU0sQ0FBQyxDQUFDO1FBQ3BELE1BQU0saUJBQWlCLEdBQUcsU0FBUyxDQUFDLGFBQWEsRUFBRSxlQUFlLENBQUMsQ0FBQztRQUNwRSxNQUFNLFdBQVcsR0FBRyxTQUFTLENBQUMsVUFBVSxDQUFDLE9BQU8sRUFBRSxTQUFTLENBQUMsQ0FBQztRQUM3RCxNQUFNLE9BQU8sR0FBRyxVQUFVLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDLEdBQUcsRUFBRSxHQUFHLEVBQUUsRUFBRSxDQUFDLEdBQUcsR0FBRyxHQUFHLENBQUMsQ0FBQztRQUNoRSxJQUFJLE9BQU8sR0FBRyxFQUFFLENBQUM7UUFDakIsSUFBSSxPQUFPLEVBQUU7WUFDWCxPQUFPLEdBQUc7Ozs7Ozs7O2NBUVYsR0FBRztZQUNMLENBQUM7U0FDQTthQUFNO1lBQ0wsT0FBTyxHQUFHOztZQUVaLEdBQUc7U0FDTixDQUFDO1NBQ0c7UUFDRCxNQUFNLFdBQVcsR0FBRztVQUN0Qix1QkFBdUI7b0NBQ0csSUFBSTtrQkFDdEIsSUFBSTs7dUJBRUMsV0FBVztxQkFDYixRQUFROzBCQUNILElBQUk7OEJBQ0EsV0FBVzt3QkFDakIsV0FBVztZQUN2QixRQUFRO1lBQ1IsYUFBYTtZQUNiLFdBQVc7WUFDWCxpQkFBaUI7OzBCQUVILEtBQUs7OztnQ0FHQyxVQUFVOzs7MkJBR2YsSUFBSSxNQUFNLFdBQVcsU0FBUyxJQUFJO2dEQUNiLElBQUksTUFBTSxXQUFXOytCQUN0QyxJQUFJLE1BQU0sV0FBVztnQkFDcEMsT0FBTzs7WUFFWCxHQUFHOzs7O09BSVIsQ0FBQztRQUNJLE9BQU8sV0FBVyxDQUFDO0tBQ3BCO0FBQ0gsQ0FBQyxDQUFDO0FBRVYsTUFBTSxTQUFTLEdBQUcsQ0FBQyxLQUF3QixFQUFFLFNBQWlCLEVBQVUsRUFBRTtJQUN4RSxJQUFJLEtBQUssR0FBRyxFQUFFLENBQUM7SUFDZixLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsS0FBSyxDQUFDLE1BQU0sRUFBRSxDQUFDLEVBQUUsRUFBRTtRQUNyQyxLQUFLLElBQUk7UUFDTCxTQUFTLElBQUksQ0FBQyxPQUFPLEtBQUssQ0FBQyxDQUFDLENBQUM7S0FDaEMsQ0FBQztLQUNIO0lBQ0QsT0FBTyxLQUFLLENBQUM7QUFDZixDQUFDLENBQUM7QUFFRixNQUFNLGVBQWUsR0FBRyxDQUFDLElBQVksRUFBVSxFQUFFLENBQUM7eUNBQ1QsSUFBSSxzQkFBc0IsSUFBSTtVQUM3RCxJQUFJOzs7MEJBR1ksSUFBSTs7OztjQUloQixJQUFJO0lBQ2QsQ0FBQzs7Ozs7Ozs7Ozs7OztBQzlXTCw0REFBNEQ7QUFDNUQsa0NBQWtDOzs7QUFFbEMsNElBQXFHO0FBRXJHLCtGQUFnRztBQUVoRyxnRkFBd0M7QUFFeEMsNEZBQW1FO0FBVW5FLE1BQU0sTUFBTSxHQUNSLENBQUMsZ0JBQXVDLEVBQUUsTUFBZ0IsRUFBRSxVQUE0QixFQUFFLElBQVksRUFDckcsUUFBa0IsRUFBWSxFQUFFO0lBQy9CLGNBQWMsQ0FBQyxNQUFNLENBQUMsQ0FBQztJQUV2QixNQUFNLHFCQUFxQixHQUFHO1FBQzVCLElBQUk7UUFDSixVQUFVLEVBQUUsQ0FBQyxHQUFHLENBQUM7UUFDakIsVUFBVSxFQUFFLENBQUMsbUJBQVcsQ0FBQyxRQUFRLENBQUM7S0FDbkMsQ0FBQztJQUVGLE1BQU0sTUFBTSxHQUFHLGdCQUFnQixDQUFDLEdBQUcsaUNBRTFCLHFCQUFxQixLQUN4QixTQUFTLEVBQUUsVUFBVSxDQUFDLFFBQVEsRUFDOUIsR0FBRyxFQUFFLEdBQUcsRUFBRSxDQUNOLHVCQUF1QixDQUFDLGdCQUFnQixFQUFFLE1BQU0sRUFBRSxVQUFVLEVBQUUsSUFBSSxFQUFFLFFBQVEsRUFBRSxxQkFBcUIsQ0FBQyxLQUUxRyxNQUFNLENBQUMsQ0FBQztJQUNaLE9BQU8sQ0FBQyxNQUFNLENBQUMsQ0FBQztBQUNsQixDQUFDLENBQUM7QUFFQyxNQUFNLHFCQUFxQixHQUE2QyxDQUFDLElBQWdCLEVBQW9CLEVBQUU7SUFDcEgsTUFBTSxJQUFJLEdBQUcsSUFBSSxDQUFDLFVBQVUsQ0FBQyxPQUFPLENBQUMsTUFBTSxFQUFFLEVBQUUsQ0FBQyxDQUFDO0lBQ2pELE1BQU0sUUFBUSxHQUFHLElBQUksQ0FBQyxVQUFVLENBQUMsTUFBTSxDQUFDLFVBQVUsRUFBRSxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUM7SUFDN0QsT0FBTywwREFBMkIsRUFBQyxFQUFDLElBQUksRUFBRSxRQUFRLEVBQUMsQ0FBQyxDQUFDO0FBQ3ZELENBQUMsQ0FBQztBQUpXLDZCQUFxQix5QkFJaEM7QUFFRixNQUFNLHVCQUF1QixHQUN6QixDQUFDLE9BQThCLEVBQUUsTUFBZ0IsRUFBRSxVQUE0QixFQUFFLElBQVksRUFBRSxRQUFrQixFQUNoSCxxQkFBc0MsRUFBZSxFQUFFO0lBQ3RELE1BQU0sV0FBVyxHQUFhLEVBQUUsQ0FBQztJQUNqQyxNQUFNLEtBQUssR0FBRyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLE1BQU0sSUFBSSxDQUFDLENBQUM7SUFFekMsTUFBTSxPQUFPLEdBQUcsRUFBRSxDQUFDLENBQUUsdUNBQXVDO0lBRTVELE1BQU0sSUFBSSxHQUFHLGdCQUFTLENBQUMsYUFBYSxDQUFDLFVBQVUsQ0FBQyxJQUFJLEVBQUUsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQztJQUM3RSxNQUFNLEdBQUcsR0FBRyxRQUFRLENBQUMsTUFBTSxFQUFFLElBQUksQ0FBQyxDQUFDO0lBQ25DLElBQUksU0FBUyxHQUFHLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUV2QixLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQyxFQUFFLEVBQUU7UUFDOUMsMEJBQTBCO1FBQzFCLElBQUksSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLElBQUksSUFBSSxDQUFDLE1BQU0sS0FBSyxDQUFDLEVBQUU7WUFDN0MsSUFBSSxVQUFVLENBQUMsUUFBUSxFQUFFO2dCQUN2QixXQUFXLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDO2FBQ3JCLENBQUUsNkNBQTZDO1lBRWhELDBCQUEwQjtZQUMxQixTQUFTLEdBQUc7cUJBQ0QsQ0FBQyxVQUFVLENBQUMsTUFBTSxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUM7dUJBQ3hDLENBQUMsUUFBUSxDQUFDO2NBQ25CLFNBQVM7WUFDWCxDQUFDO1NBQ0o7YUFBTTtZQUNMLE9BQU8sQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDLGlCQUFpQixXQUFXLENBQUMsTUFBTSxJQUFJLENBQUMsQ0FBQztZQUVuRSxXQUFXLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztTQUNyQztLQUNGO0lBRUQsTUFBTSxLQUFLLEdBQUcsV0FBVyxDQUFDLE1BQU0sSUFBSSxDQUFDLENBQUM7SUFFdEMsTUFBTSxZQUFZLEdBQUc7b0NBQ1MsS0FBSzs7dUJBRWxCLEtBQUs7VUFDbEIsT0FBTyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUM7VUFDbEIsR0FBRyxDQUFDLENBQUMsQ0FBQztVQUNOLFNBQVM7VUFDVCxHQUFHLENBQUMsQ0FBQyxDQUFDOztRQUVSLENBQUM7SUFFSCx1Q0FDSyxxQkFBcUIsS0FDeEIsTUFBTSxFQUFFLEVBQUMsSUFBSSxFQUFFLFdBQVcsRUFBRSxJQUFJLEVBQUUsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksRUFBRSxXQUFXLEVBQUUsbUJBQVcsQ0FBQyxRQUFRLEVBQUMsRUFDcEYsWUFBWSxJQUNaO0FBQ0osQ0FBQyxDQUFDO0FBRU4sTUFBTSxjQUFjLEdBQUcsQ0FBQyxNQUFnQixFQUFRLEVBQUU7SUFDaEQsSUFBSSxDQUFDLE1BQU0sSUFBSSxNQUFNLENBQUMsTUFBTSxLQUFLLENBQUMsRUFBRTtRQUNsQyxNQUFNLElBQUksS0FBSyxDQUFDLDZCQUE2QixDQUFDLENBQUM7S0FDaEQ7SUFFRCxJQUFJLHdCQUFZLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsRUFBRTtRQUMvQyxNQUFNLElBQUksS0FBSyxDQUFDLHFCQUFxQixDQUFDLENBQUM7S0FDeEM7QUFDSCxDQUFDLENBQUM7QUFFSyxNQUFNLFNBQVMsR0FDbEIsQ0FBQyxnQkFBdUMsRUFBRSxNQUFnQixFQUFFLFVBQTRCLEVBQVksRUFBRTtJQUNwRyxNQUFNLFFBQVEsR0FBYSxHQUFhLEVBQUUsQ0FBQyxDQUFDLGNBQWMsRUFBRSx3QkFBd0IsRUFBRSxFQUFFLENBQUMsQ0FBQztJQUMxRixPQUFPLE1BQU0sQ0FBQyxnQkFBZ0IsRUFBRSxNQUFNLEVBQUUsVUFBVSxFQUFFLFdBQVcsRUFBRSxRQUFRLENBQUMsQ0FBQztBQUM3RSxDQUFDLENBQUM7QUFKTyxpQkFBUyxhQUloQjtBQUVDLE1BQU0sVUFBVSxHQUNuQixDQUFDLGdCQUF1QyxFQUFFLE1BQWdCLEVBQUUsVUFBNEIsRUFBWSxFQUFFO0lBQ3BHLE1BQU0sUUFBUSxHQUFhLENBQUMsTUFBZ0IsRUFBRSxJQUFjLEVBQVksRUFBRTtRQUN4RSxJQUFJLElBQUksR0FBRyxHQUFHLENBQUM7UUFDZixLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQyxFQUFFLEVBQUU7WUFDOUMsSUFBSSxJQUFJLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsSUFBSSxJQUFJLENBQUMsTUFBTSxLQUFLLENBQUMsRUFBRTtnQkFDN0MsSUFBSSxJQUFJLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUM7YUFDM0I7U0FDRjtRQUVELE9BQU8sQ0FBQyxjQUFjLEVBQUUsd0JBQXdCLEVBQUUsWUFBWSxJQUFJLElBQUksQ0FBQyxDQUFDLENBQUUsOEJBQThCO0lBQzFHLENBQUMsQ0FBQztJQUNGLE9BQU8sTUFBTSxDQUFDLGdCQUFnQixFQUFFLE1BQU0sRUFBRSxVQUFVLEVBQUUsWUFBWSxFQUFFLFFBQVEsQ0FBQyxDQUFDO0FBQzlFLENBQUMsQ0FBQztBQWJPLGtCQUFVLGNBYWpCO0FBRUMsTUFBTSxTQUFTLEdBQ2xCLENBQUMsZ0JBQXVDLEVBQUUsTUFBZ0IsRUFBRSxVQUE0QixFQUFZLEVBQUU7SUFDcEcsTUFBTSxRQUFRLEdBQWEsQ0FBQyxNQUFnQixFQUFFLElBQWMsRUFBWSxFQUFFO1FBQ3hFLE1BQU0sT0FBTyxHQUFHLEVBQUUsQ0FBQztRQUNuQixLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQyxFQUFFLEVBQUU7WUFDOUMsSUFBSSxJQUFJLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsSUFBSSxJQUFJLENBQUMsTUFBTSxLQUFLLENBQUMsRUFBRTtnQkFDN0MsT0FBTyxDQUFDLElBQUksQ0FBQyxZQUFZLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBRSxnQkFBZ0I7YUFDdkQ7U0FDRjtRQUVELE9BQU8sQ0FBQyxHQUFHLE9BQU8sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLHlCQUF5QixFQUFFLG1DQUFtQyxFQUFFLEVBQUUsQ0FBQyxDQUFDO0lBQ25HLENBQUMsQ0FBQztJQUNGLE9BQU8sTUFBTSxDQUFDLGdCQUFnQixFQUFFLE1BQU0sRUFBRSxVQUFVLEVBQUUsV0FBVyxFQUFFLFFBQVEsQ0FBQyxDQUFDO0FBQzdFLENBQUMsQ0FBQztBQWJPLGlCQUFTLGFBYWhCO0FBRUMsTUFBTSxTQUFTLEdBQ2xCLENBQUMsZ0JBQXVDLEVBQUUsTUFBZ0IsRUFBRSxVQUE0QixFQUFZLEVBQUU7SUFDcEcsTUFBTSxRQUFRLEdBQWEsQ0FBQyxNQUFnQixFQUFFLElBQWMsRUFBWSxFQUFFO1FBQ3hFLE1BQU0sT0FBTyxHQUFHLEVBQUUsQ0FBQztRQUNuQixLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQyxFQUFFLEVBQUU7WUFDOUMsSUFBSSxJQUFJLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsSUFBSSxJQUFJLENBQUMsTUFBTSxLQUFLLENBQUMsRUFBRTtnQkFDN0MsT0FBTyxDQUFDLElBQUksQ0FBQyxZQUFZLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBRSxnQkFBZ0I7YUFDdkQ7U0FDRjtRQUVELE9BQU8sQ0FBQyxHQUFHLE9BQU8sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLHlCQUF5QixFQUFFLG1DQUFtQyxFQUFFLEVBQUUsQ0FBQyxDQUFDO0lBQ25HLENBQUMsQ0FBQztJQUNGLE9BQU8sTUFBTSxDQUFDLGdCQUFnQixFQUFFLE1BQU0sRUFBRSxVQUFVLEVBQUUsV0FBVyxFQUFFLFFBQVEsQ0FBQyxDQUFDO0FBQzdFLENBQUMsQ0FBQztBQWJPLGlCQUFTLGFBYWhCO0FBRUMsTUFBTSxVQUFVLEdBQ25CLENBQUMsZ0JBQXVDLEVBQUUsTUFBZ0IsRUFBRSxVQUE0QixFQUFZLEVBQUU7SUFDcEcsTUFBTSxRQUFRLEdBQWEsR0FBYSxFQUFFLENBQUMsQ0FBQyxjQUFjLEVBQUUsd0JBQXdCLEVBQUUsRUFBRSxDQUFDLENBQUM7SUFDMUYsT0FBTyxNQUFNLENBQUMsZ0JBQWdCLEVBQUUsTUFBTSxFQUFFLFVBQVUsRUFBRSxZQUFZLEVBQUUsUUFBUSxDQUFDLENBQUM7QUFDOUUsQ0FBQyxDQUFDO0FBSk8sa0JBQVUsY0FJakI7QUFFQyxNQUFNLFlBQVksR0FDckIsQ0FBQyxnQkFBdUMsRUFBRSxNQUFnQixFQUFFLFVBQTRCLEVBQVksRUFBRTtJQUNwRyxNQUFNLFFBQVEsR0FBYSxHQUFhLEVBQUUsQ0FBQyxDQUFDLGNBQWMsRUFBRSx3QkFBd0IsRUFBRSxxQkFBcUIsQ0FBQyxDQUFDO0lBQzdHLE9BQU8sTUFBTSxDQUFDLGdCQUFnQixFQUFFLE1BQU0sRUFBRSxVQUFVLEVBQUUsY0FBYyxFQUFFLFFBQVEsQ0FBQyxDQUFDO0FBQ2hGLENBQUMsQ0FBQztBQUpPLG9CQUFZLGdCQUluQjtBQUVDLE1BQU0sa0JBQWtCLEdBQzNCLENBQUMsZ0JBQXVDLEVBQUUsTUFBZ0IsRUFBRSxVQUE0QixFQUFZLEVBQUU7SUFDcEcsTUFBTSxRQUFRLEdBQWEsR0FBYSxFQUFFLENBQUMsQ0FBQyx1QkFBdUIsRUFBRSxtQ0FBbUMsRUFBRSxFQUFFLENBQUMsQ0FBQztJQUM5RyxPQUFPLE1BQU0sQ0FBQyxnQkFBZ0IsRUFBRSxNQUFNLEVBQUUsVUFBVSxFQUFFLG9CQUFvQixFQUFFLFFBQVEsQ0FBQyxDQUFDO0FBQ3RGLENBQUMsQ0FBQztBQUpPLDBCQUFrQixzQkFJekI7Ozs7Ozs7Ozs7Ozs7QUNoTE4sNERBQTREO0FBQzVELGtDQUFrQzs7O0FBR2xDLGdGQUF3QztBQUN4Qyw4R0FBdUM7QUFFdkMsNEZBQXNGO0FBRXRGLHVIQUFrRDtBQUVsRCxNQUFNLG9DQUFvQyxHQUFHLENBQUMsYUFBZ0MsRUFBRSxFQUFFLENBQzlFLENBQUMsRUFBQyxJQUFJLEVBQUUsa0JBQWtCLEVBQUUsVUFBVSxFQUFFLENBQUMsbUJBQVcsQ0FBQyxNQUFNLENBQUMsRUFBRSxVQUFVLEVBQUUsQ0FBQyxHQUFHLENBQUMsRUFBRSxTQUFTLEVBQUUsR0FBRyxhQUFhLEVBQUUsRUFBQyxDQUFDLENBQUM7QUFFckgsTUFBTSxnQ0FBZ0MsR0FDbEMsQ0FBQyxPQUE4QixFQUFFLE9BQWUsRUFBRSxRQUF5QixFQUFFLGFBQWdDLEVBQzdGLEVBQUU7SUFDWixNQUFNLFlBQVksR0FBRyxPQUFPLENBQUMsSUFBZ0MsQ0FBQztJQUM5RCxNQUFNLG1CQUFtQixHQUFHLGFBQXlDLENBQUM7SUFFdEUsSUFBSSxRQUFRLEdBQUcsRUFBRSxDQUFDO0lBQ2xCLEtBQUssSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxFQUFFLEVBQUU7UUFDMUIsSUFBSSxZQUFZLEdBQUcsRUFBRSxDQUFDO1FBQ3RCLFFBQVEsQ0FBQyxFQUFFO1lBQ1QsS0FBSyxDQUFDO2dCQUNKLFlBQVksR0FBRyxvQkFBb0IsQ0FBQztnQkFDcEMsTUFBTTtZQUNSLEtBQUssQ0FBQztnQkFDSixZQUFZLEdBQUcsMkNBQTJDLENBQUM7Z0JBQzNELE1BQU07WUFDUixLQUFLLENBQUM7Z0JBQ0osWUFBWSxHQUFHLDJDQUEyQyxDQUFDO2dCQUMzRCxNQUFNO1lBQ1IsS0FBSyxDQUFDO2dCQUNKLFlBQVksR0FBRyw2Q0FBNkMsQ0FBQztnQkFDN0QsTUFBTTtZQUNSO2dCQUNFLE1BQU0sSUFBSSxLQUFLLEVBQUUsQ0FBQztTQUNyQjtRQUVELFFBQVEsSUFBSTtVQUNkLFlBQVk7VUFDWixDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxxREFBcUQsQ0FBQyxDQUFDLENBQUMsRUFBRTs7Ozs7O21CQU16RCxDQUFDOztVQUVWLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRTtPQUNuQixDQUFDO0tBQ0c7SUFDRCxNQUFNLElBQUksR0FBRyx5QkFBTyxFQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLFNBQVMsQ0FBQyxPQUFPLENBQUMsQ0FBQztJQUVoRSxNQUFNLFlBQVksR0FBRztRQUN2QixzQkFBc0IsQ0FBQyxZQUFZLENBQUM7UUFDcEMsdUJBQXVCLENBQUMsbUJBQW1CLENBQUM7UUFDNUMscUNBQWlCLEdBQUU7Ozs7Ozs7O3FCQVFOLG1CQUFtQixDQUFDLENBQUMsQ0FBQztxQkFDdEIsbUJBQW1CLENBQUMsQ0FBQyxDQUFDOztVQUVqQyxRQUFRO1VBQ1IsSUFBSSxDQUFDLE1BQU07O0tBRWhCLENBQUM7SUFFSSx1Q0FDSyxRQUFRLEtBQ1gsTUFBTSxFQUFFLEVBQUMsSUFBSSxFQUFFLG1CQUFtQixFQUFFLElBQUksRUFBRSxPQUFPLENBQUMsSUFBSSxFQUFFLFdBQVcsRUFBRSxtQkFBVyxDQUFDLE1BQU0sRUFBQyxFQUN4RixZQUFZLEVBQ1osT0FBTyxFQUFFLElBQUksSUFDYjtBQUNKLENBQUMsQ0FBQztBQUVILE1BQU0sc0NBQXNDLEdBQy9DLENBQUMsT0FBOEIsRUFBRSxPQUFlLEVBQUUsYUFBZ0MsRUFBcUIsRUFBRTtJQUN2RyxNQUFNLFFBQVEsR0FBRyxvQ0FBb0MsQ0FBQyxhQUFhLENBQUMsQ0FBQztJQUNyRSx1Q0FBVyxRQUFRLEtBQUUsR0FBRyxFQUFFLEdBQUcsRUFBRSxDQUFDLGdDQUFnQyxDQUFDLE9BQU8sRUFBRSxPQUFPLEVBQUUsUUFBUSxFQUFFLGFBQWEsQ0FBQyxJQUFFO0FBQy9HLENBQUMsQ0FBQztBQUpPLDhDQUFzQywwQ0FJN0M7QUFFTixTQUFnQixhQUFhLENBQUMsS0FBd0I7SUFDcEQsSUFBSSxLQUFLLENBQUMsTUFBTSxLQUFLLENBQUMsRUFBRTtRQUN0QixPQUFPLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztLQUNsQjtJQUNELHdDQUF3QztJQUN4QyxJQUFJLEtBQUssR0FBRyxDQUFDLENBQUM7SUFDZCxLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsS0FBSyxDQUFDLE1BQU0sR0FBRyxDQUFDLEVBQUUsRUFBRSxDQUFDLEVBQUU7UUFDekMsS0FBSyxJQUFJLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQztLQUNuQjtJQUNELE9BQU8sQ0FBQyxLQUFLLEVBQUUsS0FBSyxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsS0FBSyxDQUFDLEtBQUssQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQztBQUMxRixDQUFDO0FBVkQsc0NBVUM7QUFFRCx5RUFBeUU7QUFDekUsd0VBQXdFO0FBQ3hFLHlFQUF5RTtBQUN6RSx1RUFBdUU7QUFDdkUsMEVBQTBFO0FBQzFFLHdDQUF3QztBQUN4Qyx3RUFBd0U7QUFDeEUsOEVBQThFO0FBQzlFLDBFQUEwRTtBQUMxRSwyRUFBMkU7QUFDM0Usb0JBQW9CO0FBQ3BCLFNBQWdCLGNBQWMsQ0FBQyxJQUF1QixFQUFFLFlBQStCO0lBQ3JGLElBQUksY0FBYyxHQUFHLEtBQUssQ0FBQztJQUMzQixJQUFJLElBQUksQ0FBQyxNQUFNLEtBQUssQ0FBQyxJQUFJLFlBQVksQ0FBQyxNQUFNLEtBQUssQ0FBQyxFQUFFLEVBQUcsU0FBUztRQUM5RCxjQUFjLEdBQUcsSUFBSSxDQUFDO0tBQ3ZCO1NBQU0sSUFBSSxJQUFJLENBQUMsTUFBTSxHQUFHLENBQUMsSUFBSSxZQUFZLENBQUMsTUFBTSxHQUFHLENBQUMsRUFBRSxFQUFHLEtBQUs7UUFDN0QsY0FBYyxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQyxLQUFLLFlBQVksQ0FBQyxZQUFZLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQyxDQUFDO0tBQ2xGO1NBQU0sRUFBRyxPQUFPO1FBQ2YsY0FBYyxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQyxLQUFLLFlBQVksQ0FBQyxZQUFZLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQztZQUM1RSxJQUFJLENBQUMsSUFBSSxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUMsS0FBSyxZQUFZLENBQUMsWUFBWSxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUMsQ0FBQztLQUNyRTtJQUVELE9BQU8sY0FBYyxDQUFDO0FBQ3hCLENBQUM7QUFaRCx3Q0FZQztBQUVELFNBQVMsc0JBQXNCLENBQUMsS0FBK0I7SUFDN0QsTUFBTSxPQUFPLEdBQUcsZ0JBQVMsQ0FBQyxjQUFjLENBQUMsS0FBSyxDQUFDLENBQUM7SUFDaEQsTUFBTSxNQUFNLEdBQUcsQ0FBQyxHQUFHLEVBQUUsR0FBRyxFQUFFLEdBQUcsQ0FBQyxDQUFDO0lBQy9CLE1BQU0sS0FBSyxHQUFHLE9BQU8sQ0FBQztJQUN0QixNQUFNLHNCQUFzQixHQUFHLE9BQU87U0FDRixHQUFHLENBQUMsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxFQUFFLEVBQUU7UUFDakIsTUFBTSxLQUFLLEdBQUcsT0FBTyxNQUFNLENBQUMsQ0FBQyxDQUFDLE1BQU0sS0FBSyxNQUFNLE1BQU0sRUFBRSxDQUFDO1FBQ3hELE1BQU0sS0FBSyxHQUFHLENBQUMsS0FBSyxPQUFPLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQyxDQUFDO1lBQ3BDLE9BQU8sTUFBTSxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsTUFBTSxLQUFLLE1BQU0sTUFBTSxDQUFDLENBQUMsQ0FBQyxNQUFNLE1BQU0sRUFBRSxDQUFDLENBQUM7WUFDOUQsWUFBWSxNQUFNLENBQUMsQ0FBQyxDQUFDLE1BQU0sTUFBTSxFQUFFLENBQUM7UUFDeEMsT0FBTyxHQUFHLEtBQUssS0FBSyxLQUFLLEdBQUcsQ0FBQztJQUMvQixDQUFDLENBQUM7U0FDRCxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUM7SUFFN0MsT0FBTzs7UUFFRCxzQkFBc0I7OztHQUczQixDQUFDO0FBQ0osQ0FBQztBQUVELFNBQVMsdUJBQXVCLENBQUMsS0FBK0I7SUFDOUQsTUFBTSxPQUFPLEdBQUcsZ0JBQVMsQ0FBQyxjQUFjLENBQUMsS0FBSyxDQUFDLENBQUM7SUFFaEQsT0FBTzs7O3dCQUdlLE9BQU8sQ0FBQyxDQUFDLENBQUMsaUJBQWlCLE9BQU8sQ0FBQyxDQUFDLENBQUM7O0NBRTVELENBQUM7QUFDRixDQUFDOzs7Ozs7Ozs7Ozs7O0FDNUpELDREQUE0RDtBQUM1RCxrQ0FBa0M7OztBQUdsQyxnRkFBd0M7QUFHakMsTUFBTSxPQUFPLEdBQUcsQ0FBQyxPQUE4QixFQUFFLE1BQWdCLEVBQVksRUFBRTtJQUNwRixNQUFNLFlBQVksR0FBRyxnQkFBUyxDQUFDLHFCQUFxQixDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLEVBQUUsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLFdBQVcsQ0FBQyxDQUFDO0lBQzVGLElBQUksT0FBTyxDQUFDLE9BQU8sQ0FBQyxJQUFJLEVBQUU7UUFDeEIsT0FBTyxDQUFDLE9BQU8sQ0FBQyxhQUFhLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxFQUFFLFlBQVksQ0FBQyxDQUFDLENBQUM7S0FDekQ7U0FBTTtRQUNMLE9BQU8sQ0FBQyxPQUFPLENBQUMsZUFBZSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsRUFBRSxZQUFZLENBQUMsQ0FBQyxDQUFDO0tBQzNEO0FBQ0gsQ0FBQyxDQUFDO0FBUFcsZUFBTyxXQU9sQjs7Ozs7Ozs7Ozs7OztBQ2RGLDREQUE0RDtBQUM1RCxrQ0FBa0M7OztBQUtsQyw4R0FBdUM7QUFFdkMsNEZBQWtEO0FBQ2xELDRGQUEyQztBQUUzQyx1SEFBa0Q7QUFDbEQsd0dBQXlHO0FBRXpHLE1BQU0scUJBQXFCLEdBQUc7SUFDNUIsSUFBSSxFQUFFLFFBQVE7SUFDZCxVQUFVLEVBQUUsQ0FBQyxHQUFHLENBQUM7SUFDakIsVUFBVSxFQUFFLENBQUMsbUJBQVcsQ0FBQyxNQUFNLENBQUM7Q0FDakMsQ0FBQztBQUVLLE1BQU0sTUFBTSxHQUNmLENBQUMsZ0JBQXVDLEVBQUUsTUFBZ0IsRUFBRSxVQUE4QixFQUFZLEVBQUU7SUFDdEcsNkJBQWMsRUFBQyxNQUFNLEVBQUUsVUFBVSxDQUFDLENBQUM7SUFDbkMsTUFBTSxNQUFNLEdBQUcsZ0JBQWdCLENBQUMsR0FBRyxpQ0FFMUIscUJBQXFCLEtBQ3hCLFNBQVMsRUFBRSxVQUFVLENBQUMsUUFBUSxFQUM5QixHQUFHLEVBQUUsR0FBRyxFQUFFLENBQUMsNkJBQTZCLENBQUMsZ0JBQWdCLEVBQUUsTUFBTSxFQUFFLFVBQVUsQ0FBQyxLQUVoRixNQUFNLENBQUMsQ0FBQztJQUNaLE9BQU8sQ0FBQyxNQUFNLENBQUMsQ0FBQztBQUNsQixDQUFDLENBQUM7QUFYTyxjQUFNLFVBV2I7QUFFQyxNQUFNLHdCQUF3QixHQUNqQyxDQUFDLElBQWdCLEVBQXNCLEVBQUUsQ0FBQyxzQ0FBdUIsRUFBQyxJQUFJLEVBQUUsRUFBRSxDQUFDLENBQUM7QUFEbkUsZ0NBQXdCLDRCQUMyQztBQUV6RSxNQUFNLHdCQUF3QixHQUNqQyxDQUFDLElBQWdCLEVBQXNCLEVBQUUsQ0FBQyxzQ0FBdUIsRUFBQyxJQUFJLEVBQUUsRUFBRSxDQUFDLENBQUM7QUFEbkUsZ0NBQXdCLDRCQUMyQztBQUVoRixNQUFNLDZCQUE2QixHQUMvQixDQUFDLGdCQUF1QyxFQUFFLE1BQWdCLEVBQUUsVUFBOEIsRUFBZSxFQUFFO0lBQ3pHLE1BQU0sSUFBSSxHQUFHLHlCQUFPLEVBQUMsZ0JBQWdCLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxTQUFTLENBQUMsT0FBTyxDQUFDLENBQUM7SUFDekUsTUFBTSxDQUFDLE1BQU0sRUFBRSxXQUFXLENBQUMsR0FBRyxhQUFhLENBQUMsTUFBTSxFQUFFLFVBQVUsQ0FBQyxDQUFDO0lBRWhFLE1BQU0sTUFBTSxHQUNSLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFTLEVBQUUsRUFBRSxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsSUFBSSxVQUFVLENBQUMsdUJBQXVCLEtBQUssb0JBQW9CLENBQUM7SUFDeEcsSUFBSSxNQUFNLEVBQUU7UUFDVix1Q0FDSyxxQkFBcUIsS0FDeEIsTUFBTSxFQUFFLEVBQUMsSUFBSSxFQUFFLFdBQVcsRUFBRSxJQUFJLEVBQUUsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksRUFBRSxXQUFXLEVBQUUsbUJBQVcsQ0FBQyxNQUFNLEVBQUMsRUFDbEYsT0FBTyxFQUFFLElBQUksRUFDYixZQUFZLEVBQUU7K0JBQ08sSUFBSSxDQUFDLFNBQVM7c0JBQ3ZCLElBQUksQ0FBQyxNQUFNO2tCQUNmLElBQ1I7S0FDSDtJQUVELE1BQU0sR0FBRyxHQUFHLFdBQVcsQ0FBQyxNQUFNLENBQUM7SUFDL0IsSUFBSSxHQUFHLEdBQUcsQ0FBQyxFQUFFO1FBQ1gsTUFBTSxJQUFJLEtBQUssQ0FBQyxrREFBa0QsR0FBRyxFQUFFLENBQUMsQ0FBQztLQUMxRTtJQUVELE1BQU0sWUFBWSxHQUFHLFdBQVcsQ0FBQyxHQUFHLEdBQUcsQ0FBQyxDQUFDLENBQUM7SUFDMUMsTUFBTSxXQUFXLEdBQUcsV0FBVyxDQUFDLEdBQUcsR0FBRyxDQUFDLENBQUMsQ0FBQztJQUV6QyxNQUFNLFVBQVUsR0FBRyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDO0lBQ2xDLElBQUksR0FBRyxLQUFLLFVBQVUsQ0FBQyxNQUFNLEVBQUU7UUFDN0IsTUFBTSxJQUFJLEtBQUssQ0FBQyx1Q0FBdUMsVUFBVSxDQUFDLE1BQU0sYUFBYSxHQUFHLEVBQUUsQ0FBQyxDQUFDO0tBQzdGO0lBQ0QsTUFBTSxXQUFXLEdBQUcsVUFBVSxDQUFDLEdBQUcsR0FBRyxDQUFDLENBQUMsQ0FBQztJQUN4QyxNQUFNLFVBQVUsR0FBRyxVQUFVLENBQUMsR0FBRyxHQUFHLENBQUMsQ0FBQyxDQUFDO0lBRXZDLE1BQU0sWUFBWSxHQUFHLE1BQU0sQ0FBQyxHQUFHLEdBQUcsQ0FBQyxDQUFDLENBQUM7SUFDckMsTUFBTSxXQUFXLEdBQUcsTUFBTSxDQUFDLEdBQUcsR0FBRyxDQUFDLENBQUMsQ0FBQztJQUVwQyxJQUFJLGtCQUFrQixHQUFHLEVBQUUsQ0FBQztJQUU1QixJQUFJLFVBQVUsQ0FBQyxJQUFJLEtBQUssUUFBUSxFQUFFO1FBQ2hDLDRCQUE0QjtRQUM1QixNQUFNLElBQUksS0FBSyxDQUFDLDJDQUEyQyxVQUFVLENBQUMsSUFBSSxHQUFHLENBQUMsQ0FBQztLQUNoRjtJQUNELFFBQVEsVUFBVSxDQUFDLHVCQUF1QixFQUFFO1FBQzFDLEtBQUssWUFBWTtZQUNmLGtCQUFrQixHQUFHOzs7O2lCQUlkLENBQUM7WUFDUixNQUFNO1FBQ1IsS0FBSyxZQUFZO1lBQ2Ysa0JBQWtCLEdBQUc7Ozs7aUJBSWQsQ0FBQztZQUNSLE1BQU07UUFDUixLQUFLLG9CQUFvQjtZQUN2QixrQkFBa0IsR0FBRzs7Ozs4QkFJRCxXQUFXOzhCQUNYLFlBQVk7OEJBQ1osV0FBVzs4QkFDWCxZQUFZOzs7aUJBR3pCLENBQUM7WUFDUixNQUFNO1FBQ1IsS0FBSyxlQUFlO1lBQ2xCLGtCQUFrQixHQUFHOzs4Q0FFZSxXQUFXLGFBQWEsWUFBWSxhQUFhLFdBQVc7OEJBQzVFLFlBQVk7K0NBQ0ssVUFBVSxhQUFhLFdBQVcsYUFBYSxVQUFVOzhCQUMxRSxXQUFXOzs7O2lCQUl4QixDQUFDO1lBQ1IsTUFBTTtRQUNSO1lBQ0UsaURBQWlEO1lBQ2pELE1BQU0sSUFBSSxLQUFLLENBQUM7bUNBQ1MsVUFBVSxDQUFDLHVCQUF1QixHQUFHLENBQUMsQ0FBQztLQUNuRTtJQUVELE1BQU0sY0FBYyxHQUFHLDZCQUFpQixFQUFDLEdBQUcsQ0FBQyxDQUFDO0lBQzlDLE1BQU0sYUFBYSxHQUFHLHFDQUFpQixHQUFFLENBQUM7SUFDMUMsTUFBTSxZQUFZLEdBQUc7d0NBQ2EsV0FBVyxPQUFPLFVBQVU7Z0RBQ3BCLFlBQVksWUFBWSxXQUFXLFlBQVksWUFBWSxZQUNqRyxXQUFXO2NBQ1AsYUFBYTtjQUNiLGtCQUFrQjs7Ozs7a0JBS2QsY0FBYzs7Ozs7Ozs7Ozs7Ozs7Ozs7MkNBaUJXLFlBQVksR0FBRyxDQUFDOzJDQUNoQixXQUFXLEdBQUcsQ0FBQzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7a0JBc0N4QyxJQUFJLENBQUMsTUFBTTs7U0FFcEIsQ0FBQztJQUNKLHVDQUNLLHFCQUFxQixLQUN4QixNQUFNLEVBQUUsRUFBQyxJQUFJLEVBQUUsV0FBVyxFQUFFLElBQUksRUFBRSxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxFQUFFLFdBQVcsRUFBRSxtQkFBVyxDQUFDLE1BQU0sRUFBQyxFQUNsRixPQUFPLEVBQUUsSUFBSSxFQUNiLFlBQVksSUFDWjtBQUNKLENBQUMsQ0FBQztBQUdOLE1BQU0sYUFBYSxHQUFHLENBQUMsTUFBZ0IsRUFBRSxVQUE4QixFQUEwQyxFQUFFO0lBQ2pILE1BQU0sQ0FBQyxHQUFHLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUNwQixNQUFNLEtBQUssR0FBRyxDQUFDLENBQUMsSUFBSSxDQUFDO0lBRXJCLElBQUksTUFBTSxHQUFHLFVBQVUsQ0FBQyxNQUFNLENBQUM7SUFDL0IsSUFBSSxXQUErQixDQUFDO0lBQ3BDLElBQUksTUFBTSxDQUFDLE1BQU0sS0FBSyxDQUFDLEVBQUU7UUFDdkIsTUFBTSxZQUFZLEdBQUcsTUFBTSxDQUFDLFVBQVUsQ0FBQyxjQUFjLENBQUMsQ0FBQztRQUN2RCxJQUFJLFlBQVksSUFBSSxZQUFZLENBQUMsSUFBSSxLQUFLLENBQUMsRUFBRTtZQUMzQyxJQUFJLE1BQU0sQ0FBQyxVQUFVLENBQUMsYUFBYSxDQUFDLEVBQUU7Z0JBQ3BDLE1BQU0sSUFBSSxLQUFLLENBQUMsd0RBQXdELENBQUMsQ0FBQzthQUMzRTtZQUNELE1BQU0sR0FBRyxlQUFlLENBQUMsWUFBWSxFQUFFLFVBQVUsQ0FBQyxJQUFJLEVBQUUsVUFBVSxDQUFDLFFBQVEsQ0FBQyxDQUFDO1NBQzlFO2FBQU07WUFDTCxNQUFNLFdBQVcsR0FBRyxNQUFNLENBQUMsVUFBVSxDQUFDLGFBQWEsQ0FBQyxDQUFDO1lBQ3JELElBQUksQ0FBQyxXQUFXLElBQUksV0FBVyxDQUFDLElBQUksS0FBSyxDQUFDLEVBQUU7Z0JBQzFDLE1BQU0sSUFBSSxLQUFLLENBQUMsbURBQW1ELENBQUMsQ0FBQzthQUN0RTtZQUVELFdBQVcsR0FBRyxLQUFLLENBQUMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxXQUFXLENBQUMsQ0FBQztZQUNsRCxNQUFNLEdBQUcsNkJBQTZCLENBQUMsV0FBVyxFQUFFLEtBQUssRUFBRSxVQUFVLENBQUMsSUFBSSxFQUFFLFVBQVUsQ0FBQyxRQUFRLENBQUMsQ0FBQztTQUNsRztLQUNGO1NBQU07UUFDTCxJQUFJLE1BQU0sQ0FBQyxVQUFVLENBQUMsYUFBYSxDQUFDLEVBQUU7WUFDcEMsTUFBTSxJQUFJLEtBQUssQ0FBQyx3REFBd0QsQ0FBQyxDQUFDO1NBQzNFO0tBQ0Y7SUFFRCxNQUFNLEtBQUssR0FBRyxXQUFXLElBQUksQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUMsR0FBRyxFQUFFLENBQUMsRUFBRSxFQUFFLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxHQUFHLEdBQUcsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBRWxGLE9BQU8sQ0FBQyxNQUFNLEVBQUUsS0FBSyxDQUFDLENBQUM7QUFDekIsQ0FBQyxDQUFDO0FBRUYsTUFBTSxlQUFlLEdBQUcsQ0FBQyxLQUFhLEVBQUUsSUFBWSxFQUFFLFFBQWlCLEVBQVksRUFBRTtJQUNuRixNQUFNLE1BQU0sR0FBRyxLQUFLLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxTQUFTLENBQUMsQ0FBQztJQUMzQywrQkFBZ0IsRUFBQyxNQUFNLEVBQUUsSUFBSSxFQUFFLFFBQVEsQ0FBQyxDQUFDO0lBQ3pDLE9BQU8sTUFBTSxDQUFDO0FBQ2hCLENBQUMsQ0FBQztBQUVGLE1BQU0sNkJBQTZCLEdBQy9CLENBQUMsS0FBd0IsRUFBRSxLQUF3QixFQUFFLElBQVksRUFBRSxRQUFpQixFQUFZLEVBQUU7SUFDaEcsTUFBTSxNQUFNLEdBQUcsS0FBSyxDQUFDLE1BQU0sQ0FBQztJQUM1QixNQUFNLE1BQU0sR0FBRyxJQUFJLEtBQUssQ0FBUyxNQUFNLENBQUMsQ0FBQztJQUV6QyxLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxHQUFHLEdBQUcsTUFBTSxFQUFFLENBQUMsR0FBRyxHQUFHLEVBQUUsQ0FBQyxFQUFFLEVBQUU7UUFDMUMsSUFBSSxLQUFLLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxFQUFFO1lBQ2xCLElBQUksS0FBSyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsRUFBRTtnQkFDbEIsTUFBTSxJQUFJLEtBQUssQ0FBQyx3REFBd0QsQ0FBQyxDQUFDO2FBQzNFO1lBQ0QsTUFBTSxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQztTQUNmO2FBQU07WUFDTCxNQUFNLENBQUMsQ0FBQyxDQUFDLEdBQUcsS0FBSyxDQUFDLENBQUMsQ0FBQyxHQUFHLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQztTQUNqQztLQUNGO0lBQ0QsK0JBQWdCLEVBQUMsTUFBTSxFQUFFLElBQUksRUFBRSxRQUFRLENBQUMsQ0FBQztJQUN6QyxPQUFPLE1BQU0sQ0FBQztBQUNoQixDQUFDLENBQUM7QUFFTiw2REFBNkQ7QUFDN0Qsb0ZBQW9GO0FBQ3BGLDhCQUE4QjtBQUM5QixxQ0FBcUM7QUFDckMsNkNBQTZDO0FBQzdDLDJEQUEyRDtBQUMzRCxZQUFZO0FBQ1osNERBQTREO0FBQzVELDJFQUEyRTtBQUMzRSxlQUFlO0FBQ2YsOERBQThEO0FBQzlELFFBQVE7QUFDUixrQkFBa0I7QUFDbEIsS0FBSzs7Ozs7Ozs7Ozs7OztBQ3ZSTCw0REFBNEQ7QUFDNUQsa0NBQWtDOzs7QUFFbEMsc0ZBQXVDO0FBR2hDLE1BQU0sS0FBSyxHQUFHLENBQUMsZ0JBQXVDLEVBQUUsTUFBZ0IsRUFBWSxFQUFFO0lBQzNGLGNBQWMsQ0FBQyxNQUFNLENBQUMsQ0FBQztJQUN2QixPQUFPLENBQUMsSUFBSSxlQUFNLENBQUMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxFQUFFLE9BQU8sRUFBRSxTQUFTLEVBQUUsU0FBUyxFQUFFLElBQUksVUFBVSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUM7QUFDOUcsQ0FBQyxDQUFDO0FBSFcsYUFBSyxTQUdoQjtBQUVGLE1BQU0sY0FBYyxHQUFHLENBQUMsTUFBZ0IsRUFBUSxFQUFFO0lBQ2hELElBQUksQ0FBQyxNQUFNLElBQUksTUFBTSxDQUFDLE1BQU0sS0FBSyxDQUFDLEVBQUU7UUFDbEMsTUFBTSxJQUFJLEtBQUssQ0FBQyx5QkFBeUIsQ0FBQyxDQUFDO0tBQzVDO0FBQ0gsQ0FBQyxDQUFDOzs7Ozs7Ozs7Ozs7O0FDZkYsNERBQTREO0FBQzVELGtDQUFrQzs7O0FBRWxDLDRJQUFxRztBQUVyRywrRkFBZ0c7QUFFaEcsZ0ZBQXdDO0FBRXhDLDRGQUFrRDtBQVFsRCxNQUFNLG9CQUFvQixHQUFHO0lBQzNCLElBQUksRUFBRSxPQUFPO0lBQ2IsVUFBVSxFQUFFLENBQUMsR0FBRyxDQUFDO0lBQ2pCLFVBQVUsRUFBRSxDQUFDLG1CQUFXLENBQUMsUUFBUSxDQUFDO0NBQ25DLENBQUM7QUFFSyxNQUFNLEtBQUssR0FDZCxDQUFDLGdCQUF1QyxFQUFFLE1BQWdCLEVBQUUsVUFBMkIsRUFBWSxFQUFFO0lBQ25HLGNBQWMsQ0FBQyxNQUFNLENBQUMsQ0FBQztJQUN2QixNQUFNLE1BQU0sR0FBRyxnQkFBZ0IsQ0FBQyxHQUFHLGlDQUUxQixvQkFBb0IsS0FDdkIsU0FBUyxFQUFFLFVBQVUsQ0FBQyxRQUFRLEVBQzlCLEdBQUcsRUFBRSxHQUFHLEVBQUUsQ0FBQyxzQkFBc0IsQ0FBQyxnQkFBZ0IsRUFBRSxNQUFNLENBQUMsQ0FBQyxDQUFDLEVBQUUsVUFBVSxDQUFDLEtBRTVFLE1BQU0sQ0FBQyxDQUFDO0lBQ1osT0FBTyxDQUFDLE1BQU0sQ0FBQyxDQUFDO0FBQ2xCLENBQUMsQ0FBQztBQVhPLGFBQUssU0FXWjtBQUVDLE1BQU0sb0JBQW9CLEdBQTRDLENBQUMsSUFBZ0IsRUFBbUIsRUFBRTtJQUNqSCxNQUFNLE1BQU0sR0FBRyxJQUFJLENBQUMsVUFBVSxDQUFDLE9BQU8sQ0FBQyxRQUFRLENBQUMsQ0FBQztJQUNqRCxNQUFNLElBQUksR0FBRyxJQUFJLENBQUMsVUFBVSxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsQ0FBQztJQUM3QyxNQUFNLElBQUksR0FBRyxJQUFJLENBQUMsVUFBVSxDQUFDLE9BQU8sQ0FBQyxNQUFNLEVBQUUsRUFBRSxDQUFDLENBQUM7SUFDakQsT0FBTywwREFBMkIsRUFBQyxFQUFDLE1BQU0sRUFBRSxJQUFJLEVBQUUsSUFBSSxFQUFDLENBQUMsQ0FBQztBQUMzRCxDQUFDLENBQUM7QUFMVyw0QkFBb0Isd0JBSy9CO0FBRUYsTUFBTSxzQkFBc0IsR0FDeEIsQ0FBQyxnQkFBdUMsRUFBRSxLQUFhLEVBQUUsVUFBMkIsRUFBZSxFQUFFO0lBQ25HLE1BQU0sSUFBSSxHQUFHLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxNQUFNLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLEdBQUcsRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDO0lBQ3ZHLE1BQU0sY0FBYyxHQUFHLGdCQUFTLENBQUMsYUFBYSxDQUFDLElBQUksRUFBRSxLQUFLLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDO0lBQ3hFLE1BQU0sTUFBTSxHQUFHLFVBQVUsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsS0FBSyxFQUFFLENBQUMsRUFBRSxFQUFFO1FBQ2hELElBQUksS0FBSyxHQUFHLEtBQUssQ0FBQyxJQUFJLENBQUMsY0FBYyxDQUFDLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxFQUFFO1lBQzdDLE9BQU8sS0FBSyxDQUFDLElBQUksQ0FBQyxjQUFjLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztTQUN0QztRQUNELE9BQU8sZ0JBQVMsQ0FBQyxhQUFhLENBQUMsS0FBSyxFQUFFLEtBQUssQ0FBQyxJQUFJLENBQUMsY0FBYyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUN2RSxDQUFDLENBQUMsQ0FBQztJQUNILE1BQU0sSUFBSSxHQUFHLFVBQVUsQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUMsR0FBRyxFQUFFLENBQUMsRUFBRSxFQUFFO1FBQzFDLElBQUksR0FBRyxHQUFHLEtBQUssQ0FBQyxJQUFJLENBQUMsY0FBYyxDQUFDLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxFQUFFO1lBQzNDLE9BQU8sS0FBSyxDQUFDLElBQUksQ0FBQyxjQUFjLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztTQUN0QztRQUNELE9BQU8sZ0JBQVMsQ0FBQyxhQUFhLENBQUMsR0FBRyxFQUFFLEtBQUssQ0FB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QUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxRQUFRO0FBQ1I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxNQUFNO0FBQ047QUFDQTtBQUNBLElBQUk7QUFDSjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUN0Q0E7Ozs7Ozs7Ozs7QUNBQTs7Ozs7Ozs7OztBQ0FBOzs7Ozs7Ozs7O0FDQUE7Ozs7Ozs7Ozs7QUNBQTs7Ozs7Ozs7OztBQ0FBOzs7Ozs7Ozs7O0FDQUE7Ozs7Ozs7Ozs7QUNBQTs7Ozs7Ozs7OztBQ0FBOzs7Ozs7Ozs7O0FDQUE7Ozs7Ozs7Ozs7QUNBQTs7Ozs7Ozs7Ozs7Ozs7O0FDQUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGNBQWM7QUFDZDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxVQUFVO0FBQ1Y7QUFDQTtBQUNBOztBQUVBO0FBQ0EsVUFBVTtBQUNWO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLFVBQVU7QUFDVjtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxVQUFVO0FBQ1Y7QUFDQTtBQUNBOztBQUVBO0FBQ0EsVUFBVTtBQUNWO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxVQUFVO0FBQ1Y7QUFDQTtBQUNBOztBQUVBO0FBQ0EsVUFBVTtBQUNWO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLFVBQVU7QUFDVjtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxVQUFVO0FBQ1Y7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQSxXQUFXLFFBQVE7QUFDbkIsV0FBVyxRQUFRO0FBQ25CO0FBQ0E7QUFDQTtBQUNBLFlBQVk7QUFDWjtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxZQUFZO0FBQ1o7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxXQUFXLFFBQVE7QUFDbkIsV0FBVyxRQUFRO0FBQ25CLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsV0FBVyxrQkFBa0I7QUFDN0IsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsVUFBVTtBQUNWO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXLFNBQVM7QUFDcEI7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQTs7QUFFQTtBQUNBLFlBQVk7QUFDWjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsWUFBWTtBQUNaO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxZQUFZO0FBQ1o7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLFlBQVk7QUFDWjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsWUFBWTtBQUNaO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxZQUFZO0FBQ1o7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLFlBQVk7QUFDWjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsWUFBWTtBQUNaO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxZQUFZO0FBQ1o7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLFlBQVk7QUFDWjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVcsU0FBUztBQUNwQjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVyxRQUFRO0FBQ25CLFdBQVcsUUFBUTtBQUNuQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0EsV0FBVyxRQUFRO0FBQ25CO0FBQ0E7QUFDQSxrQkFBa0IsZUFBZTtBQUNqQztBQUNBO0FBQ0E7O0FBRUE7QUFDQSxXQUFXLFFBQVE7QUFDbkI7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxXQUFXLFFBQVE7QUFDbkI7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxXQUFXLFFBQVE7QUFDbkI7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxXQUFXLGtCQUFrQjtBQUM3QjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLFdBQVcsUUFBUTtBQUNuQjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLFdBQVcsUUFBUTtBQUNuQjtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxXQUFXLFFBQVE7QUFDbkI7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsV0FBVyxRQUFRO0FBQ25CO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLFdBQVcsUUFBUTtBQUNuQjtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxXQUFXLGtCQUFrQjtBQUM3QjtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxXQUFXLFFBQVE7QUFDbkI7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsV0FBVyxRQUFRO0FBQ25CO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLFdBQVcsUUFBUTtBQUNuQixXQUFXLFFBQVE7QUFDbkIsV0FBVyxRQUFRO0FBQ25CO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtB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RUE7QUFDQTtBQUNBO0FBQ0EsV0FBVyxRQUFRO0FBQ25CLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxXQUFXLFFBQVE7QUFDbkI7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsV0FBVyxRQUFRO0FBQ25CLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLFdBQVcsUUFBUTtBQUNuQixhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxXQUFXLFFBQVE7QUFDbkIsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsV0FBVyxRQUFRO0FBQ25CLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLFdBQVcsUUFBUTtBQUNuQixhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxXQUFXLFFBQVE7QUFDbkIsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsV0FBVyxRQUFRO0FBQ25CLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLFdBQVcsUUFBUTtBQUNuQixhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxXQUFXLFFBQVE7QUFDbkIsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxXQUFXLFFBQVE7QUFDbkIsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLFdBQVcsUUFBUTtBQUNuQixXQUFXLGdCQUFnQjtBQUMzQjtBQUNBO0FBQ0EsbUNBQW1DLFFBQVE7QUFDM0M7O0FBRUE7QUFDQSxXQUFXLFFBQVE7QUFDbkIs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QTs7Ozs7V0NQQTtXQUNBO1dBQ0E7V0FDQTtXQUNBLHlDQUF5Qyx3Q0FBd0M7V0FDakY7V0FDQTtXQUNBOzs7OztXQ1BBO1dBQ0E7V0FDQTtXQUNBO1dBQ0EsR0FBRztXQUNIO1dBQ0E7V0FDQSxDQUFDOzs7OztXQ1BEOzs7OztXQ0FBO1dBQ0E7V0FDQTtXQUNBLHVEQUF1RCxpQkFBaUI7V0FDeEU7V0FDQSxnREFBZ0QsYUFBYTtXQUM3RDs7Ozs7VUVOQTtVQUNBO1VBQ0E7VUFDQSIsInNvdXJjZXMiOlsid2VicGFjazovL29ydC93ZWJwYWNrL3VuaXZlcnNhbE1vZHVsZURlZmluaXRpb24iLCJ3ZWJwYWNrOi8vb3J0Ly4uL2NvbW1vbi9kaXN0L2xpYi9iYWNrZW5kLWltcGwuanMiLCJ3ZWJwYWNrOi8vb3J0Ly4uL2NvbW1vbi9kaXN0L2xpYi9iYWNrZW5kLmpzIiwid2VicGFjazovL29ydC8uLi9jb21tb24vZGlzdC9saWIvZW52LWltcGwuanMiLCJ3ZWJwYWNrOi8vb3J0Ly4uL2NvbW1vbi9kaXN0L2xpYi9lbnYuanMiLCJ3ZWJwYWNrOi8vb3J0Ly4uL2NvbW1vbi9kaXN0L2xpYi9pbmRleC5qcyIsIndlYnBhY2s6Ly9vcnQvLi4vY29tbW9uL2Rpc3QvbGliL2luZmVyZW5jZS1zZXNzaW9uLWltcGwuanMiLCJ3ZWJwYWNrOi8vb3J0Ly4uL2NvbW1vbi9kaXN0L2xpYi9pbmZlcmVuY2Utc2Vzc2lvbi5qcyIsIndlYnBhY2s6Ly9vcnQvLi4vY29tbW9uL2Rpc3QvbGliL29ubngtdmFsdWUuanMiLCJ3ZWJwYWNrOi8vb3J0Ly4uL2NvbW1vbi9kaXN0L2xpYi90ZW5zb3ItaW1wbC5qcyIsIndlYnBhY2s6Ly9vcnQvLi4vY29tbW9uL2Rpc3QvbGliL3RlbnNvci5qcyIsIndlYnBhY2s6Ly9vcnQvLi9saWIvd2FzbS9iaW5kaW5nL29ydC13YXNtLXRocmVhZGVkLmpzIiwid2VicGFjazovL29ydC8uL2xpYi93YXNtL2JpbmRpbmcvb3J0LXdhc20uanMiLCJ3ZWJwYWNrOi8vb3J0Ly4vbm9kZV9tb2R1bGVzL0Bwcm90b2J1ZmpzL2FzcHJvbWlzZS9pbmRleC5qcyIsIndlYnBhY2s6Ly9vcnQvLi9ub2RlX21vZHVsZXMvQHByb3RvYnVmanMvYmFzZTY0L2luZGV4LmpzIiwid2VicGFjazovL29ydC8uL25vZGVfbW9kdWxlcy9AcHJvdG9idWZqcy9ldmVudGVtaXR0ZXIvaW5kZXguanMiLCJ3ZWJwYWNrOi8vb3J0Ly4vbm9kZV9tb2R1bGVzL0Bwcm90b2J1ZmpzL2Zsb2F0L2luZGV4LmpzIiwid2VicGFjazovL29ydC8uL25vZGVfbW9kdWxlcy9AcHJvdG9idWZqcy9pbnF1aXJlL2luZGV4LmpzIiwid2VicGFjazovL29ydC8uL25vZGVfbW9kdWxlcy9AcHJvdG9idWZqcy9wb29sL2luZGV4LmpzIiwid2VicGFjazovL29ydC8uL25vZGVfbW9kdWxlcy9AcHJvdG9idWZqcy91dGY4L2luZGV4LmpzIiwid2VicGFjazovL29ydC8uL25vZGVfbW9kdWxlcy9ndWlkLXR5cGVzY3JpcHQvZGlzdC9ndWlkLmpzIiwid2VicGFjazovL29ydC8uL25vZGVfbW9kdWxlcy9sb25nL3NyYy9sb25nLmpzIiwid2VicGFjazovL29ydC8uL25vZGVfbW9kdWxlcy9vbm54LXByb3RvL2Rpc3Qvb25ueC5qcyIsIndlYnBhY2s6Ly9vcnQvLi9ub2RlX21vZHVsZXMvcHJvdG9idWZqcy9taW5pbWFsLmpzIiwid2VicGFjazovL29ydC8uL25vZGVfbW9kdWxlcy9wcm90b2J1ZmpzL3NyYy9pbmRleC1taW5pbWFsLmpzIiwid2VicGFjazovL29ydC8uL25vZGVfbW9kdWxlcy9wcm90b2J1ZmpzL3NyYy9yZWFkZXIuanMiLCJ3ZWJwYWNrOi8vb3J0Ly4vbm9kZV9tb2R1bGVzL3Byb3RvYnVmanMvc3JjL3JlYWRlcl9idWZmZXIuanMiLCJ3ZWJwYWNrOi8vb3J0Ly4vbm9kZV9tb2R1bGVzL3Byb3RvYnVmanMvc3JjL3Jvb3RzLmpzIiwid2VicGFjazovL29ydC8uL25vZGVfbW9kdWxlcy9wcm90b2J1ZmpzL3NyYy9ycGMuanMiLCJ3ZWJwYWNrOi8vb3J0Ly4vbm9kZV9tb2R1bGVzL3Byb3RvYnVmanMvc3JjL3JwYy9zZXJ2aWNlLmpzIiwid2VicGFjazovL29ydC8uL25vZGVfbW9kdWxlcy9wcm90b2J1ZmpzL3NyYy91dGlsL2xvbmdiaXRzLmpzIiwid2VicGFjazovL29ydC8uL25vZGVfbW9kdWxlcy9wcm90b2J1ZmpzL3NyYy91dGlsL21pbmltYWwuanMiLCJ3ZWJwYWNrOi8vb3J0Ly4vbm9kZV9tb2R1bGVzL3Byb3RvYnVmanMvc3JjL3dyaXRlci5qcyIsIndlYnBhY2s6Ly9vcnQvLi9ub2RlX21vZHVsZXMvcHJvdG9idWZqcy9zcmMvd3JpdGVyX2J1ZmZlci5qcyIsIndlYnBhY2s6Ly9vcnQvLi9saWIvYmFja2VuZC1vbm54anMudHMiLCJ3ZWJwYWNrOi8vb3J0Ly4vbGliL2JhY2tlbmQtd2FzbS50cyIsIndlYnBhY2s6Ly9vcnQvLi9saWIvaW5kZXgudHMiLCJ3ZWJwYWNrOi8vb3J0Ly4vbGliL29ubnhqcy9hdHRyaWJ1dGUtd2l0aC1jYWNoZS1rZXkudHMiLCJ3ZWJwYWNrOi8vb3J0Ly4vbGliL29ubnhqcy9hdHRyaWJ1dGUudHMiLCJ3ZWJwYWNrOi8vb3J0Ly4vbGliL29ubnhqcy9iYWNrZW5kLnRzIiwid2VicGFjazovL29ydC8uL2xpYi9vbm54anMvYmFja2VuZHMvYmFja2VuZC13ZWJnbC50cyIsIndlYnBhY2s6Ly9vcnQvLi9saWIvb25ueGpzL2JhY2tlbmRzL3dlYmdsL2dsc2wtY29vcmRpbmF0ZS1saWIudHMiLCJ3ZWJwYWNrOi8vb3J0Ly4vbGliL29ubnhqcy9iYWNrZW5kcy93ZWJnbC9nbHNsLWRlZmluaXRpb25zLnRzIiwid2VicGFjazovL29ydC8uL2xpYi9vbm54anMvYmFja2VuZHMvd2ViZ2wvZ2xzbC1lbmNvZGluZy1saWIudHMiLCJ3ZWJwYWNrOi8vb3J0Ly4vbGliL29ubnhqcy9iYWNrZW5kcy93ZWJnbC9nbHNsLWZyYWdjb2xvci1saWIudHMiLCJ3ZWJwYWNrOi8vb3J0Ly4vbGliL29ubnhqcy9iYWNrZW5kcy93ZWJnbC9nbHNsLWZ1bmN0aW9uLWlubGluZXIudHMiLCJ3ZWJwYWNrOi8vb3J0Ly4vbGliL29ubnhqcy9iYWNrZW5kcy93ZWJnbC9nbHNsLXByZXByb2Nlc3Nvci50cyIsIndlYnBhY2s6Ly9vcnQvLi9saWIvb25ueGpzL2JhY2tlbmRzL3dlYmdsL2dsc2wtcmVnaXN0ZXJlZC1saWJzLnRzIiwid2VicGFjazovL29ydC8uL2xpYi9vbm54anMvYmFja2VuZHMvd2ViZ2wvZ2xzbC1zaGFwZS11dGlscy1saWIudHMiLCJ3ZWJwYWNrOi8vb3J0Ly4vbGliL29ubnhqcy9iYWNrZW5kcy93ZWJnbC9nbHNsLXNvdXJjZS50cyIsIndlYnBhY2s6Ly9vcnQvLi9saWIvb25ueGpzL2JhY2tlbmRzL3dlYmdsL2dsc2wtdmVjLWxpYi50cyIsIndlYnBhY2s6Ly9vcnQvLi9saWIvb25ueGpzL2JhY2tlbmRzL3dlYmdsL2luZmVyZW5jZS1oYW5kbGVyLnRzIiwid2VicGFjazovL29ydC8uL2xpYi9vbm54anMvYmFja2VuZHMvd2ViZ2wvb3AtcmVzb2x2ZS1ydWxlcy50cyIsIndlYnBhY2s6Ly9vcnQvLi9saWIvb25ueGpzL2JhY2tlbmRzL3dlYmdsL29wcy9iYXRjaC1ub3JtYWxpemF0aW9uLnRzIiwid2VicGFjazovL29ydC8uL2xpYi9vbm54anMvYmFja2VuZHMvd2ViZ2wvb3BzL2JpbmFyeS1vcC50cyIsIndlYnBhY2s6Ly9vcnQvLi9saWIvb25ueGpzL2JhY2tlbmRzL3dlYmdsL29wcy9jYXN0LnRzIiwid2VicGFjazovL29ydC8uL2xpYi9vbm54anMvYmFja2VuZHMvd2ViZ2wvb3BzL2NvbmNhdC1wYWNrZWQudHMiLCJ3ZWJwYWNrOi8vb3J0Ly4vbGliL29ubnhqcy9iYWNrZW5kcy93ZWJnbC9vcHMvY29uY2F0LnRzIiwid2VicGFjazovL29ydC8uL2xpYi9vbm54anMvYmFja2VuZHMvd2ViZ2wvb3BzL2NvbnYtZ3JvdXBlZC50cyIsIndlYnBhY2s6Ly9vcnQvLi9saWIvb25ueGpzL2JhY2tlbmRzL3dlYmdsL29wcy9jb252LXBhY2sudHMiLCJ3ZWJwYWNrOi8vb3J0Ly4vbGliL29ubnhqcy9iYWNrZW5kcy93ZWJnbC9vcHMvY29udi10cmFuc3Bvc2UudHMiLCJ3ZWJwYWNrOi8vb3J0Ly4vbGliL29ubnhqcy9iYWNrZW5kcy93ZWJnbC9vcHMvY29udi50cyIsIndlYnBhY2s6Ly9vcnQvLi9saWIvb25ueGpzL2JhY2tlbmRzL3dlYmdsL29wcy9kZXB0aC10by1zcGFjZS50cyIsIndlYnBhY2s6Ly9vcnQvLi9saWIvb25ueGpzL2JhY2tlbmRzL3dlYmdsL29wcy9kb3QtcHJvZHVjdC50cyIsIndlYnBhY2s6Ly9vcnQvLi9saWIvb25ueGpzL2JhY2tlbmRzL3dlYmdsL29wcy9mbGF0dGVuLnRzIiwid2VicGFjazovL29ydC8uL2xpYi9vbm54anMvYmFja2VuZHMvd2ViZ2wvb3BzL2Z1c2UtdXRpbHMudHMiLCJ3ZWJwYWNrOi8vb3J0Ly4vbGliL29ubnhqcy9iYWNrZW5kcy93ZWJnbC9vcHMvZ2F0aGVyLnRzIiwid2VicGFjazovL29ydC8uL2xpYi9vbm54anMvYmFja2VuZHMvd2ViZ2wvb3BzL2dlbW0udHMiLCJ3ZWJwYWNrOi8vb3J0Ly4vbGliL29ubnhqcy9iYWNrZW5kcy93ZWJnbC9vcHMvaW0yY29sLXBhY2sudHMiLCJ3ZWJwYWNrOi8vb3J0Ly4vbGliL29ubnhqcy9iYWNrZW5kcy93ZWJnbC9vcHMvaW0yY29sLnRzIiwid2VicGFjazovL29ydC8uL2xpYi9vbm54anMvYmFja2VuZHMvd2ViZ2wvb3BzL2ltYWdlLXNjYWxlci50cyIsIndlYnBhY2s6Ly9vcnQvLi9saWIvb25ueGpzL2JhY2tlbmRzL3dlYmdsL29wcy9pbnN0YW5jZS1ub3JtYWxpemF0aW9uLnRzIiwid2VicGFjazovL29ydC8uL2xpYi9vbm54anMvYmFja2VuZHMvd2ViZ2wvb3BzL21hdG11bC1wYWNrLnRzIiwid2VicGFjazovL29ydC8uL2xpYi9vbm54anMvYmFja2VuZHMvd2ViZ2wvb3BzL21hdG11bC50cyIsIndlYnBhY2s6Ly9vcnQvLi9saWIvb25ueGpzL2JhY2tlbmRzL3dlYmdsL29wcy9wYWNrLnRzIiwid2VicGFjazovL29ydC8uL2xpYi9vbm54anMvYmFja2VuZHMvd2ViZ2wvb3BzL3BhY2tpbmctdXRpbHMudHMiLCJ3ZWJwYWNrOi8vb3J0Ly4vbGliL29ubnhqcy9iYWNrZW5kcy93ZWJnbC9vcHMvcGFkLnRzIiwid2VicGFjazovL29ydC8uL2xpYi9vbm54anMvYmFja2VuZHMvd2ViZ2wvb3BzL3Bvb2wudHMiLCJ3ZWJwYWNrOi8vb3J0Ly4vbGliL29ubnhqcy9iYWNrZW5kcy93ZWJnbC9vcHMvcmVkdWNlLnRzIiwid2VicGFjazovL29ydC8uL2xpYi9vbm54anMvYmFja2VuZHMvd2ViZ2wvb3BzL3Jlc2hhcGUtcGFja2VkLnRzIiwid2VicGFjazovL29ydC8uL2xpYi9vbm54anMvYmFja2VuZHMvd2ViZ2wvb3BzL3Jlc2hhcGUudHMiLCJ3ZWJwYWNrOi8vb3J0Ly4vbGliL29ubnhqcy9iYWNrZW5kcy93ZWJnbC9vcHMvcmVzaXplLXBhY2tlZC50cyIsIndlYnBhY2s6Ly9vcnQvLi9saWIvb25ueGpzL2JhY2tlbmRzL3dlYmdsL29wcy9zaGFwZS50cyIsIndlYnBhY2s6Ly9vcnQvLi9saWIvb25ueGpzL2JhY2tlbmRzL3dlYmdsL29wcy9zbGljZS50cyIsIndlYnBhY2s6Ly9vcnQvLi9saWIvb25ueGpzL2JhY2tlbmRzL3dlYmdsL29wcy9zb2Z0bWF4LnRzIiwid2VicGFjazovL29ydC8uL2xpYi9vbm54anMvYmFja2VuZHMvd2ViZ2wvb3BzL3NwbGl0LnRzIiwid2VicGFjazovL29ydC8uL2xpYi9vbm54anMvYmFja2VuZHMvd2ViZ2wvb3BzL3NxdWVlemUudHMiLCJ3ZWJwYWNrOi8vb3J0Ly4vbGliL29ubnhqcy9iYWNrZW5kcy93ZWJnbC9vcHMvc3VtLnRzIiwid2VicGFjazovL29ydC8uL2xpYi9vbm54anMvYmFja2VuZHMvd2ViZ2wvb3BzL3RpbGUudHMiLCJ3ZWJwYWNrOi8vb3J0Ly4vbGliL29ubnhqcy9iYWNrZW5kcy93ZWJnbC9vcHMvdHJhbnNwb3NlLnRzIiwid2VicGFjazovL29ydC8uL2xpYi9vbm54anMvYmFja2VuZHMvd2ViZ2wvb3BzL3VpbnQ4LWVuY29kZS50cyIsIndlYnBhY2s6Ly9vcnQvLi9saWIvb25ueGpzL2JhY2tlbmRzL3dlYmdsL29wcy91bmFyeS1vcC50cyIsIndlYnBhY2s6Ly9vcnQvLi9saWIvb25ueGpzL2JhY2tlbmRzL3dlYmdsL29wcy91bnBhY2sudHMiLCJ3ZWJwYWNrOi8vb3J0Ly4vbGliL29ubnhqcy9iYWNrZW5kcy93ZWJnbC9vcHMvdW5zcXVlZXplLnRzIiwid2VicGFjazovL29ydC8uL2xpYi9vbm54anMvYmFja2VuZHMvd2ViZ2wvb3BzL3Vwc2FtcGxlLnRzIiwid2VicGFjazovL29ydC8uL2xpYi9vbm54anMvYmFja2VuZHMvd2ViZ2wvcHJvZ3JhbS1tYW5hZ2VyLnRzIiwid2VicGFjazovL29ydC8uL2xpYi9vbm54anMvYmFja2VuZHMvd2ViZ2wvc2Vzc2lvbi1oYW5kbGVyLnRzIiwid2VicGFjazovL29ydC8uL2xpYi9vbm54anMvYmFja2VuZHMvd2ViZ2wvdGV4dHVyZS1kYXRhLWVuY29kZXIudHMiLCJ3ZWJwYWNrOi8vb3J0Ly4vbGliL29ubnhqcy9iYWNrZW5kcy93ZWJnbC90ZXh0dXJlLWxheW91dC1zdHJhdGVneS50cyIsIndlYnBhY2s6Ly9vcnQvLi9saWIvb25ueGpzL2JhY2tlbmRzL3dlYmdsL3RleHR1cmUtbGF5b3V0LnRzIiwid2VicGFjazovL29ydC8uL2xpYi9vbm54anMvYmFja2VuZHMvd2ViZ2wvdGV4dHVyZS1tYW5hZ2VyLnRzIiwid2VicGFjazovL29ydC8uL2xpYi9vbm54anMvYmFja2VuZHMvd2ViZ2wvdHlwZXMudHMiLCJ3ZWJwYWNrOi8vb3J0Ly4vbGliL29ubnhqcy9iYWNrZW5kcy93ZWJnbC91dGlscy50cyIsIndlYnBhY2s6Ly9vcnQvLi9saWIvb25ueGpzL2JhY2tlbmRzL3dlYmdsL3dlYmdsLWNvbnRleHQtZmFjdG9yeS50cyIsIndlYnBhY2s6Ly9vcnQvLi9saWIvb25ueGpzL2JhY2tlbmRzL3dlYmdsL3dlYmdsLWNvbnRleHQudHMiLCJ3ZWJwYWNrOi8vb3J0Ly4vbGliL29ubnhqcy9leGVjdXRpb24tcGxhbi50cyIsIndlYnBhY2s6Ly9vcnQvLi9saWIvb25ueGpzL2dyYXBoLnRzIiwid2VicGFjazovL29ydC8uL2xpYi9vbm54anMvaW5zdHJ1bWVudC50cyIsIndlYnBhY2s6Ly9vcnQvLi9saWIvb25ueGpzL21vZGVsLnRzIiwid2VicGFjazovL29ydC8uL2xpYi9vbm54anMvb3BlcmF0b3JzLnRzIiwid2VicGFjazovL29ydC8uL2xpYi9vbm54anMvb3BzZXQudHMiLCJ3ZWJwYWNrOi8vb3J0Ly4vbGliL29ubnhqcy9vcnQtc2NoZW1hL29ydC1nZW5lcmF0ZWQudHMiLCJ3ZWJwYWNrOi8vb3J0Ly4vbGliL29ubnhqcy9zZXNzaW9uLWhhbmRsZXIudHMiLCJ3ZWJwYWNrOi8vb3J0Ly4vbGliL29ubnhqcy9zZXNzaW9uLnRzIiwid2VicGFjazovL29ydC8uL2xpYi9vbm54anMvdGVuc29yLnRzIiwid2VicGFjazovL29ydC8uL2xpYi9vbm54anMvdXRpbC50cyIsIndlYnBhY2s6Ly9vcnQvLi9saWIvd2FzbS9vcHRpb25zLXV0aWxzLnRzIiwid2VicGFjazovL29ydC8uL2xpYi93YXNtL3Byb3h5LXdyYXBwZXIudHMiLCJ3ZWJwYWNrOi8vb3J0Ly4vbGliL3dhc20vcnVuLW9wdGlvbnMudHMiLCJ3ZWJwYWNrOi8vb3J0Ly4vbGliL3dhc20vc2Vzc2lvbi1oYW5kbGVyLnRzIiwid2VicGFjazovL29ydC8uL2xpYi93YXNtL3Nlc3Npb24tb3B0aW9ucy50cyIsIndlYnBhY2s6Ly9vcnQvLi9saWIvd2FzbS9zdHJpbmctdXRpbHMudHMiLCJ3ZWJwYWNrOi8vb3J0Ly4vbGliL3dhc20vd2FzbS1jb3JlLWltcGwudHMiLCJ3ZWJwYWNrOi8vb3J0Ly4vbGliL3dhc20vd2FzbS1mYWN0b3J5LnRzIiwid2VicGFjazovL29ydC8uL2xpYi93YXNtL3Byb3h5LXdvcmtlci9tYWluLnRzIiwid2VicGFjazovL29ydC8uL25vZGVfbW9kdWxlcy93b3JrZXItbG9hZGVyL2Rpc3QvcnVudGltZS9pbmxpbmUuanMiLCJ3ZWJwYWNrOi8vb3J0L2lnbm9yZWR8RDpcXGFcXF93b3JrXFwxXFxzXFxqc1xcd2ViXFxsaWJcXG9ubnhqc3xmcyIsIndlYnBhY2s6Ly9vcnQvaWdub3JlZHxEOlxcYVxcX3dvcmtcXDFcXHNcXGpzXFx3ZWJcXGxpYlxcb25ueGpzfHV0aWwiLCJ3ZWJwYWNrOi8vb3J0L2lnbm9yZWR8RDpcXGFcXF93b3JrXFwxXFxzXFxqc1xcd2ViXFxsaWJcXHdhc21cXGJpbmRpbmd8ZnMiLCJ3ZWJwYWNrOi8vb3J0L2lnbm9yZWR8RDpcXGFcXF93b3JrXFwxXFxzXFxqc1xcd2ViXFxsaWJcXHdhc21cXGJpbmRpbmd8b3MiLCJ3ZWJwYWNrOi8vb3J0L2lnbm9yZWR8RDpcXGFcXF93b3JrXFwxXFxzXFxqc1xcd2ViXFxsaWJcXHdhc21cXGJpbmRpbmd8cGF0aCIsIndlYnBhY2s6Ly9vcnQvaWdub3JlZHxEOlxcYVxcX3dvcmtcXDFcXHNcXGpzXFx3ZWJcXGxpYlxcd2FzbVxcYmluZGluZ3xwZXJmX2hvb2tzIiwid2VicGFjazovL29ydC9pZ25vcmVkfEQ6XFxhXFxfd29ya1xcMVxcc1xcanNcXHdlYlxcbGliXFx3YXNtXFxiaW5kaW5nfHdvcmtlcl90aHJlYWRzIiwid2VicGFjazovL29ydC9pZ25vcmVkfEQ6XFxhXFxfd29ya1xcMVxcc1xcanNcXHdlYlxcbGliXFx3YXNtfGZzIiwid2VicGFjazovL29ydC9pZ25vcmVkfEQ6XFxhXFxfd29ya1xcMVxcc1xcanNcXHdlYlxcbGliXFx3YXNtfHBhdGgiLCJ3ZWJwYWNrOi8vb3J0L2lnbm9yZWR8RDpcXGFcXF93b3JrXFwxXFxzXFxqc1xcd2ViXFxsaWJcXHdhc218dXRpbCIsIndlYnBhY2s6Ly9vcnQvaWdub3JlZHxEOlxcYVxcX3dvcmtcXDFcXHNcXGpzXFx3ZWJcXGxpYnxvcyIsIndlYnBhY2s6Ly9vcnQvLi9ub2RlX21vZHVsZXMvZmxhdGJ1ZmZlcnMvanMvZmxhdGJ1ZmZlcnMubWpzIiwid2VicGFjazovL29ydC93ZWJwYWNrL2Jvb3RzdHJhcCIsIndlYnBhY2s6Ly9vcnQvd2VicGFjay9ydW50aW1lL2NvbXBhdCBnZXQgZGVmYXVsdCBleHBvcnQiLCJ3ZWJwYWNrOi8vb3J0L3dlYnBhY2svcnVudGltZS9kZWZpbmUgcHJvcGVydHkgZ2V0dGVycyIsIndlYnBhY2s6Ly9vcnQvd2VicGFjay9ydW50aW1lL2dsb2JhbCIsIndlYnBhY2s6Ly9vcnQvd2VicGFjay9ydW50aW1lL2hhc093blByb3BlcnR5IHNob3J0aGFuZCIsIndlYnBhY2s6Ly9vcnQvd2VicGFjay9ydW50aW1lL21ha2UgbmFtZXNwYWNlIG9iamVjdCIsIndlYnBhY2s6Ly9vcnQvd2VicGFjay9iZWZvcmUtc3RhcnR1cCIsIndlYnBhY2s6Ly9vcnQvd2VicGFjay9zdGFydHVwIiwid2VicGFjazovL29ydC93ZWJwYWNrL2FmdGVyLXN0YXJ0dXAiXSwic291cmNlc0NvbnRlbnQiOlsiKGZ1bmN0aW9uIHdlYnBhY2tVbml2ZXJzYWxNb2R1bGVEZWZpbml0aW9uKHJvb3QsIGZhY3RvcnkpIHtcblx0aWYodHlwZW9mIGV4cG9ydHMgPT09ICdvYmplY3QnICYmIHR5cGVvZiBtb2R1bGUgPT09ICdvYmplY3QnKVxuXHRcdG1vZHVsZS5leHBvcnRzID0gZmFjdG9yeSgpO1xuXHRlbHNlIGlmKHR5cGVvZiBkZWZpbmUgPT09ICdmdW5jdGlvbicgJiYgZGVmaW5lLmFtZClcblx0XHRkZWZpbmUoW10sIGZhY3RvcnkpO1xuXHRlbHNlIGlmKHR5cGVvZiBleHBvcnRzID09PSAnb2JqZWN0Jylcblx0XHRleHBvcnRzW1wib3J0XCJdID0gZmFjdG9yeSgpO1xuXHRlbHNlXG5cdFx0cm9vdFtcIm9ydFwiXSA9IGZhY3RvcnkoKTtcbn0pKHNlbGYsICgpID0+IHtcbnJldHVybiAiLCIvLyBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cbmNvbnN0IGJhY2tlbmRzID0ge307XG5jb25zdCBiYWNrZW5kc1NvcnRlZEJ5UHJpb3JpdHkgPSBbXTtcbi8qKlxuICogUmVnaXN0ZXIgYSBiYWNrZW5kLlxuICpcbiAqIEBwYXJhbSBuYW1lIC0gdGhlIG5hbWUgYXMgYSBrZXkgdG8gbG9va3VwIGFzIGFuIGV4ZWN1dGlvbiBwcm92aWRlci5cbiAqIEBwYXJhbSBiYWNrZW5kIC0gdGhlIGJhY2tlbmQgb2JqZWN0LlxuICogQHBhcmFtIHByaW9yaXR5IC0gYW4gaW50ZWdlciBpbmRpY2F0aW5nIHRoZSBwcmlvcml0eSBvZiB0aGUgYmFja2VuZC4gSGlnaGVyIG51bWJlciBtZWFucyBoaWdoZXIgcHJpb3JpdHkuIGlmIHByaW9yaXR5XG4gKiA8IDAsIGl0IHdpbGwgYmUgY29uc2lkZXJlZCBhcyBhICdiZXRhJyB2ZXJzaW9uIGFuZCB3aWxsIG5vdCBiZSB1c2VkIGFzIGEgZmFsbGJhY2sgYmFja2VuZCBieSBkZWZhdWx0LlxuICpcbiAqIEBpbnRlcm5hbFxuICovXG5leHBvcnQgY29uc3QgcmVnaXN0ZXJCYWNrZW5kID0gKG5hbWUsIGJhY2tlbmQsIHByaW9yaXR5KSA9PiB7XG4gICAgaWYgKGJhY2tlbmQgJiYgdHlwZW9mIGJhY2tlbmQuaW5pdCA9PT0gJ2Z1bmN0aW9uJyAmJiB0eXBlb2YgYmFja2VuZC5jcmVhdGVTZXNzaW9uSGFuZGxlciA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICBjb25zdCBjdXJyZW50QmFja2VuZCA9IGJhY2tlbmRzW25hbWVdO1xuICAgICAgICBpZiAoY3VycmVudEJhY2tlbmQgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgYmFja2VuZHNbbmFtZV0gPSB7IGJhY2tlbmQsIHByaW9yaXR5IH07XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAoY3VycmVudEJhY2tlbmQucHJpb3JpdHkgPiBwcmlvcml0eSkge1xuICAgICAgICAgICAgLy8gc2FtZSBuYW1lIGlzIGFscmVhZHkgcmVnaXN0ZXJlZCB3aXRoIGEgaGlnaGVyIHByaW9yaXR5LiBza2lwIHJlZ2lzdGVyYXRpb24uXG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAoY3VycmVudEJhY2tlbmQucHJpb3JpdHkgPT09IHByaW9yaXR5KSB7XG4gICAgICAgICAgICBpZiAoY3VycmVudEJhY2tlbmQuYmFja2VuZCAhPT0gYmFja2VuZCkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgY2Fubm90IHJlZ2lzdGVyIGJhY2tlbmQgXCIke25hbWV9XCIgdXNpbmcgcHJpb3JpdHkgJHtwcmlvcml0eX1gKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAocHJpb3JpdHkgPj0gMCkge1xuICAgICAgICAgICAgY29uc3QgaSA9IGJhY2tlbmRzU29ydGVkQnlQcmlvcml0eS5pbmRleE9mKG5hbWUpO1xuICAgICAgICAgICAgaWYgKGkgIT09IC0xKSB7XG4gICAgICAgICAgICAgICAgYmFja2VuZHNTb3J0ZWRCeVByaW9yaXR5LnNwbGljZShpLCAxKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgYmFja2VuZHNTb3J0ZWRCeVByaW9yaXR5Lmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgaWYgKGJhY2tlbmRzW2JhY2tlbmRzU29ydGVkQnlQcmlvcml0eVtpXV0ucHJpb3JpdHkgPD0gcHJpb3JpdHkpIHtcbiAgICAgICAgICAgICAgICAgICAgYmFja2VuZHNTb3J0ZWRCeVByaW9yaXR5LnNwbGljZShpLCAwLCBuYW1lKTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGJhY2tlbmRzU29ydGVkQnlQcmlvcml0eS5wdXNoKG5hbWUpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybjtcbiAgICB9XG4gICAgdGhyb3cgbmV3IFR5cGVFcnJvcignbm90IGEgdmFsaWQgYmFja2VuZCcpO1xufTtcbi8qKlxuICogUmVzb2x2ZSBiYWNrZW5kIGJ5IHNwZWNpZmllZCBoaW50cy5cbiAqXG4gKiBAcGFyYW0gYmFja2VuZEhpbnRzIC0gYSBsaXN0IG9mIGV4ZWN1dGlvbiBwcm92aWRlciBuYW1lcyB0byBsb29rdXAuIElmIG9taXR0ZWQgdXNlIHJlZ2lzdGVyZWQgYmFja2VuZHMgYXMgbGlzdC5cbiAqIEByZXR1cm5zIGEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHRvIHRoZSBiYWNrZW5kLlxuICpcbiAqIEBpbnRlcm5hbFxuICovXG5leHBvcnQgY29uc3QgcmVzb2x2ZUJhY2tlbmQgPSBhc3luYyAoYmFja2VuZEhpbnRzKSA9PiB7XG4gICAgY29uc3QgYmFja2VuZE5hbWVzID0gYmFja2VuZEhpbnRzLmxlbmd0aCA9PT0gMCA/IGJhY2tlbmRzU29ydGVkQnlQcmlvcml0eSA6IGJhY2tlbmRIaW50cztcbiAgICBjb25zdCBlcnJvcnMgPSBbXTtcbiAgICBmb3IgKGNvbnN0IGJhY2tlbmROYW1lIG9mIGJhY2tlbmROYW1lcykge1xuICAgICAgICBjb25zdCBiYWNrZW5kSW5mbyA9IGJhY2tlbmRzW2JhY2tlbmROYW1lXTtcbiAgICAgICAgaWYgKGJhY2tlbmRJbmZvKSB7XG4gICAgICAgICAgICBpZiAoYmFja2VuZEluZm8uaW5pdGlhbGl6ZWQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gYmFja2VuZEluZm8uYmFja2VuZDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2UgaWYgKGJhY2tlbmRJbmZvLmFib3J0ZWQpIHtcbiAgICAgICAgICAgICAgICBjb250aW51ZTsgLy8gY3VycmVudCBiYWNrZW5kIGlzIHVuYXZhaWxhYmxlOyB0cnkgbmV4dFxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3QgaXNJbml0aWFsaXppbmcgPSAhIWJhY2tlbmRJbmZvLmluaXRQcm9taXNlO1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICBpZiAoIWlzSW5pdGlhbGl6aW5nKSB7XG4gICAgICAgICAgICAgICAgICAgIGJhY2tlbmRJbmZvLmluaXRQcm9taXNlID0gYmFja2VuZEluZm8uYmFja2VuZC5pbml0KCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGF3YWl0IGJhY2tlbmRJbmZvLmluaXRQcm9taXNlO1xuICAgICAgICAgICAgICAgIGJhY2tlbmRJbmZvLmluaXRpYWxpemVkID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICByZXR1cm4gYmFja2VuZEluZm8uYmFja2VuZDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNhdGNoIChlKSB7XG4gICAgICAgICAgICAgICAgaWYgKCFpc0luaXRpYWxpemluZykge1xuICAgICAgICAgICAgICAgICAgICBlcnJvcnMucHVzaCh7IG5hbWU6IGJhY2tlbmROYW1lLCBlcnI6IGUgfSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGJhY2tlbmRJbmZvLmFib3J0ZWQgPSB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZmluYWxseSB7XG4gICAgICAgICAgICAgICAgZGVsZXRlIGJhY2tlbmRJbmZvLmluaXRQcm9taXNlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuICAgIHRocm93IG5ldyBFcnJvcihgbm8gYXZhaWxhYmxlIGJhY2tlbmQgZm91bmQuIEVSUjogJHtlcnJvcnMubWFwKGUgPT4gYFske2UubmFtZX1dICR7ZS5lcnJ9YCkuam9pbignLCAnKX1gKTtcbn07XG4vLyMgc291cmNlTWFwcGluZ1VSTD1iYWNrZW5kLWltcGwuanMubWFwIiwiLy8gQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXG5leHBvcnQgeyByZWdpc3RlckJhY2tlbmQgfSBmcm9tICcuL2JhY2tlbmQtaW1wbCc7XG4vLyMgc291cmNlTWFwcGluZ1VSTD1iYWNrZW5kLmpzLm1hcCIsIi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxuZXhwb3J0IGNsYXNzIEVudkltcGwge1xuICAgIGNvbnN0cnVjdG9yKCkge1xuICAgICAgICB0aGlzLndhc20gPSB7fTtcbiAgICAgICAgdGhpcy53ZWJnbCA9IHt9O1xuICAgICAgICB0aGlzLmxvZ0xldmVsSW50ZXJuYWwgPSAnd2FybmluZyc7XG4gICAgfVxuICAgIC8vIFRPRE8gc3RhbmRhZGl6ZSB0aGUgZ2V0dGVyIGFuZCBzZXR0ZXIgY29udmVudGlvbiBpbiBlbnYgZm9yIG90aGVyIGZpZWxkcy5cbiAgICBzZXQgbG9nTGV2ZWwodmFsdWUpIHtcbiAgICAgICAgaWYgKHZhbHVlID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBpZiAodHlwZW9mIHZhbHVlICE9PSAnc3RyaW5nJyB8fCBbJ3ZlcmJvc2UnLCAnaW5mbycsICd3YXJuaW5nJywgJ2Vycm9yJywgJ2ZhdGFsJ10uaW5kZXhPZih2YWx1ZSkgPT09IC0xKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYFVuc3VwcG9ydGVkIGxvZ2dpbmcgbGV2ZWw6ICR7dmFsdWV9YCk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5sb2dMZXZlbEludGVybmFsID0gdmFsdWU7XG4gICAgfVxuICAgIGdldCBsb2dMZXZlbCgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMubG9nTGV2ZWxJbnRlcm5hbDtcbiAgICB9XG59XG4vLyMgc291cmNlTWFwcGluZ1VSTD1lbnYtaW1wbC5qcy5tYXAiLCIvLyBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cbmltcG9ydCB7IEVudkltcGwgfSBmcm9tICcuL2Vudi1pbXBsJztcbi8qKlxuICogUmVwcmVzZW50IGEgc2V0IG9mIGZsYWdzIGFzIGEgZ2xvYmFsIHNpbmdsZXRvbi5cbiAqL1xuZXhwb3J0IGNvbnN0IGVudiA9IG5ldyBFbnZJbXBsKCk7XG4vLyMgc291cmNlTWFwcGluZ1VSTD1lbnYuanMubWFwIiwiLy8gQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXG4vKipcbiAqICMgT05OWCBSdW50aW1lIEphdmFTY3JpcHQgQVBJXG4gKlxuICogT05OWCBSdW50aW1lIEphdmFTY3JpcHQgQVBJIGlzIGEgdW5pZmllZCBBUEkgZm9yIGFsbCBKYXZhU2NyaXB0IHVzYWdlcywgaW5jbHVkaW5nIHRoZSBmb2xsb3dpbmcgTlBNIHBhY2thZ2VzOlxuICpcbiAqIC0gW29ubnhydW50aW1lLW5vZGVdKGh0dHBzOi8vd3d3Lm5wbWpzLmNvbS9wYWNrYWdlL29ubnhydW50aW1lLW5vZGUpXG4gKiAtIFtvbm54cnVudGltZS13ZWJdKGh0dHBzOi8vd3d3Lm5wbWpzLmNvbS9wYWNrYWdlL29ubnhydW50aW1lLXdlYilcbiAqIC0gW29ubnhydW50aW1lLXJlYWN0LW5hdGl2ZV0oaHR0cHM6Ly93d3cubnBtanMuY29tL3BhY2thZ2Uvb25ueHJ1bnRpbWUtcmVhY3QtbmF0aXZlKVxuICpcbiAqIFNlZSBhbHNvOlxuICogLSBbR2V0IFN0YXJ0ZWRdKGh0dHBzOi8vb25ueHJ1bnRpbWUuYWkvZG9jcy9nZXQtc3RhcnRlZC93aXRoLWphdmFzY3JpcHQuaHRtbClcbiAqIC0gW0luZmVyZW5jZSBleGFtcGxlc10oaHR0cHM6Ly9naXRodWIuY29tL21pY3Jvc29mdC9vbm54cnVudGltZS1pbmZlcmVuY2UtZXhhbXBsZXMvdHJlZS9tYWluL2pzKVxuICpcbiAqIEBwYWNrYWdlRG9jdW1lbnRhdGlvblxuICovXG5leHBvcnQgKiBmcm9tICcuL2JhY2tlbmQnO1xuZXhwb3J0ICogZnJvbSAnLi9lbnYnO1xuZXhwb3J0ICogZnJvbSAnLi9pbmZlcmVuY2Utc2Vzc2lvbic7XG5leHBvcnQgKiBmcm9tICcuL3RlbnNvcic7XG5leHBvcnQgKiBmcm9tICcuL29ubngtdmFsdWUnO1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9aW5kZXguanMubWFwIiwiLy8gQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXG5pbXBvcnQgeyByZXNvbHZlQmFja2VuZCB9IGZyb20gJy4vYmFja2VuZC1pbXBsJztcbmltcG9ydCB7IFRlbnNvciB9IGZyb20gJy4vdGVuc29yJztcbmV4cG9ydCBjbGFzcyBJbmZlcmVuY2VTZXNzaW9uIHtcbiAgICBjb25zdHJ1Y3RvcihoYW5kbGVyKSB7XG4gICAgICAgIHRoaXMuaGFuZGxlciA9IGhhbmRsZXI7XG4gICAgfVxuICAgIGFzeW5jIHJ1bihmZWVkcywgYXJnMSwgYXJnMikge1xuICAgICAgICBjb25zdCBmZXRjaGVzID0ge307XG4gICAgICAgIGxldCBvcHRpb25zID0ge307XG4gICAgICAgIC8vIGNoZWNrIGlucHV0c1xuICAgICAgICBpZiAodHlwZW9mIGZlZWRzICE9PSAnb2JqZWN0JyB8fCBmZWVkcyA9PT0gbnVsbCB8fCBmZWVkcyBpbnN0YW5jZW9mIFRlbnNvciB8fCBBcnJheS5pc0FycmF5KGZlZWRzKSkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignXFwnZmVlZHNcXCcgbXVzdCBiZSBhbiBvYmplY3QgdGhhdCB1c2UgaW5wdXQgbmFtZXMgYXMga2V5cyBhbmQgT25ueFZhbHVlIGFzIGNvcnJlc3BvbmRpbmcgdmFsdWVzLicpO1xuICAgICAgICB9XG4gICAgICAgIGxldCBpc0ZldGNoZXNFbXB0eSA9IHRydWU7XG4gICAgICAgIC8vIGRldGVybWluZSB3aGljaCBvdmVycmlkZSBpcyBiZWluZyB1c2VkXG4gICAgICAgIGlmICh0eXBlb2YgYXJnMSA9PT0gJ29iamVjdCcpIHtcbiAgICAgICAgICAgIGlmIChhcmcxID09PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignVW5leHBlY3RlZCBhcmd1bWVudFsxXTogY2Fubm90IGJlIG51bGwuJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoYXJnMSBpbnN0YW5jZW9mIFRlbnNvcikge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ1xcJ2ZldGNoZXNcXCcgY2Fubm90IGJlIGEgVGVuc29yJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoQXJyYXkuaXNBcnJheShhcmcxKSkge1xuICAgICAgICAgICAgICAgIGlmIChhcmcxLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdcXCdmZXRjaGVzXFwnIGNhbm5vdCBiZSBhbiBlbXB0eSBhcnJheS4nKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaXNGZXRjaGVzRW1wdHkgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICAvLyBvdXRwdXQgbmFtZXNcbiAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IG5hbWUgb2YgYXJnMSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAodHlwZW9mIG5hbWUgIT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdcXCdmZXRjaGVzXFwnIG11c3QgYmUgYSBzdHJpbmcgYXJyYXkgb3IgYW4gb2JqZWN0LicpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLm91dHB1dE5hbWVzLmluZGV4T2YobmFtZSkgPT09IC0xKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgUmFuZ2VFcnJvcihgJ2ZldGNoZXMnIGNvbnRhaW5zIGludmFsaWQgb3V0cHV0IG5hbWU6ICR7bmFtZX0uYCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZmV0Y2hlc1tuYW1lXSA9IG51bGw7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgYXJnMiA9PT0gJ29iamVjdCcgJiYgYXJnMiAhPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgICAgICBvcHRpb25zID0gYXJnMjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSBpZiAodHlwZW9mIGFyZzIgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ1xcJ29wdGlvbnNcXCcgbXVzdCBiZSBhbiBvYmplY3QuJyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgLy8gZGVjaWRlIHdoZXRoZXIgYXJnMSBpcyBmZXRjaGVzIG9yIG9wdGlvbnNcbiAgICAgICAgICAgICAgICAvLyBpZiBhbnkgb3V0cHV0IG5hbWUgaXMgcHJlc2VudCBhbmQgaXRzIHZhbHVlIGlzIHZhbGlkIE9ubnhWYWx1ZSwgd2UgY29uc2lkZXIgaXQgZmV0Y2hlc1xuICAgICAgICAgICAgICAgIGxldCBpc0ZldGNoZXMgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICBjb25zdCBhcmcxS2V5cyA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eU5hbWVzKGFyZzEpO1xuICAgICAgICAgICAgICAgIGZvciAoY29uc3QgbmFtZSBvZiB0aGlzLm91dHB1dE5hbWVzKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChhcmcxS2V5cy5pbmRleE9mKG5hbWUpICE9PSAtMSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgdiA9IGFyZzFbbmFtZV07XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAodiA9PT0gbnVsbCB8fCB2IGluc3RhbmNlb2YgVGVuc29yKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaXNGZXRjaGVzID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpc0ZldGNoZXNFbXB0eSA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZldGNoZXNbbmFtZV0gPSB2O1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChpc0ZldGNoZXMpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBhcmcyID09PSAnb2JqZWN0JyAmJiBhcmcyICE9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBvcHRpb25zID0gYXJnMjtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBlbHNlIGlmICh0eXBlb2YgYXJnMiAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ1xcJ29wdGlvbnNcXCcgbXVzdCBiZSBhbiBvYmplY3QuJyk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIG9wdGlvbnMgPSBhcmcxO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmICh0eXBlb2YgYXJnMSAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ1VuZXhwZWN0ZWQgYXJndW1lbnRbMV06IG11c3QgYmUgXFwnZmV0Y2hlc1xcJyBvciBcXCdvcHRpb25zXFwnLicpO1xuICAgICAgICB9XG4gICAgICAgIC8vIGNoZWNrIGlmIGFsbCBpbnB1dHMgYXJlIGluIGZlZWRcbiAgICAgICAgZm9yIChjb25zdCBuYW1lIG9mIHRoaXMuaW5wdXROYW1lcykge1xuICAgICAgICAgICAgaWYgKHR5cGVvZiBmZWVkc1tuYW1lXSA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYGlucHV0ICcke25hbWV9JyBpcyBtaXNzaW5nIGluICdmZWVkcycuYCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgLy8gaWYgbm8gZmV0Y2hlcyBpcyBzcGVjaWZpZWQsIHdlIHVzZSB0aGUgZnVsbCBvdXRwdXQgbmFtZXMgbGlzdFxuICAgICAgICBpZiAoaXNGZXRjaGVzRW1wdHkpIHtcbiAgICAgICAgICAgIGZvciAoY29uc3QgbmFtZSBvZiB0aGlzLm91dHB1dE5hbWVzKSB7XG4gICAgICAgICAgICAgICAgZmV0Y2hlc1tuYW1lXSA9IG51bGw7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgLy8gZmVlZHMsIGZldGNoZXMgYW5kIG9wdGlvbnMgYXJlIHByZXBhcmVkXG4gICAgICAgIGNvbnN0IHJlc3VsdHMgPSBhd2FpdCB0aGlzLmhhbmRsZXIucnVuKGZlZWRzLCBmZXRjaGVzLCBvcHRpb25zKTtcbiAgICAgICAgY29uc3QgcmV0dXJuVmFsdWUgPSB7fTtcbiAgICAgICAgZm9yIChjb25zdCBrZXkgaW4gcmVzdWx0cykge1xuICAgICAgICAgICAgaWYgKE9iamVjdC5oYXNPd25Qcm9wZXJ0eS5jYWxsKHJlc3VsdHMsIGtleSkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm5WYWx1ZVtrZXldID0gbmV3IFRlbnNvcihyZXN1bHRzW2tleV0udHlwZSwgcmVzdWx0c1trZXldLmRhdGEsIHJlc3VsdHNba2V5XS5kaW1zKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcmV0dXJuVmFsdWU7XG4gICAgfVxuICAgIHN0YXRpYyBhc3luYyBjcmVhdGUoYXJnMCwgYXJnMSwgYXJnMiwgYXJnMykge1xuICAgICAgICAvLyBlaXRoZXIgbG9hZCBmcm9tIGEgZmlsZSBvciBidWZmZXJcbiAgICAgICAgbGV0IGZpbGVQYXRoT3JVaW50OEFycmF5O1xuICAgICAgICBsZXQgb3B0aW9ucyA9IHt9O1xuICAgICAgICBpZiAodHlwZW9mIGFyZzAgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICBmaWxlUGF0aE9yVWludDhBcnJheSA9IGFyZzA7XG4gICAgICAgICAgICBpZiAodHlwZW9mIGFyZzEgPT09ICdvYmplY3QnICYmIGFyZzEgIT09IG51bGwpIHtcbiAgICAgICAgICAgICAgICBvcHRpb25zID0gYXJnMTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2UgaWYgKHR5cGVvZiBhcmcxICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ1xcJ29wdGlvbnNcXCcgbXVzdCBiZSBhbiBvYmplY3QuJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAoYXJnMCBpbnN0YW5jZW9mIFVpbnQ4QXJyYXkpIHtcbiAgICAgICAgICAgIGZpbGVQYXRoT3JVaW50OEFycmF5ID0gYXJnMDtcbiAgICAgICAgICAgIGlmICh0eXBlb2YgYXJnMSA9PT0gJ29iamVjdCcgJiYgYXJnMSAhPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIG9wdGlvbnMgPSBhcmcxO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSBpZiAodHlwZW9mIGFyZzEgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignXFwnb3B0aW9uc1xcJyBtdXN0IGJlIGFuIG9iamVjdC4nKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmIChhcmcwIGluc3RhbmNlb2YgQXJyYXlCdWZmZXIgfHxcbiAgICAgICAgICAgICh0eXBlb2YgU2hhcmVkQXJyYXlCdWZmZXIgIT09ICd1bmRlZmluZWQnICYmIGFyZzAgaW5zdGFuY2VvZiBTaGFyZWRBcnJheUJ1ZmZlcikpIHtcbiAgICAgICAgICAgIGNvbnN0IGJ1ZmZlciA9IGFyZzA7XG4gICAgICAgICAgICBsZXQgYnl0ZU9mZnNldCA9IDA7XG4gICAgICAgICAgICBsZXQgYnl0ZUxlbmd0aCA9IGFyZzAuYnl0ZUxlbmd0aDtcbiAgICAgICAgICAgIGlmICh0eXBlb2YgYXJnMSA9PT0gJ29iamVjdCcgJiYgYXJnMSAhPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIG9wdGlvbnMgPSBhcmcxO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSBpZiAodHlwZW9mIGFyZzEgPT09ICdudW1iZXInKSB7XG4gICAgICAgICAgICAgICAgYnl0ZU9mZnNldCA9IGFyZzE7XG4gICAgICAgICAgICAgICAgaWYgKCFOdW1iZXIuaXNTYWZlSW50ZWdlcihieXRlT2Zmc2V0KSkge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgUmFuZ2VFcnJvcignXFwnYnl0ZU9mZnNldFxcJyBtdXN0IGJlIGFuIGludGVnZXIuJyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChieXRlT2Zmc2V0IDwgMCB8fCBieXRlT2Zmc2V0ID49IGJ1ZmZlci5ieXRlTGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBSYW5nZUVycm9yKGAnYnl0ZU9mZnNldCcgaXMgb3V0IG9mIHJhbmdlIFswLCAke2J1ZmZlci5ieXRlTGVuZ3RofSkuYCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGJ5dGVMZW5ndGggPSBhcmcwLmJ5dGVMZW5ndGggLSBieXRlT2Zmc2V0O1xuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgYXJnMiA9PT0gJ251bWJlcicpIHtcbiAgICAgICAgICAgICAgICAgICAgYnl0ZUxlbmd0aCA9IGFyZzI7XG4gICAgICAgICAgICAgICAgICAgIGlmICghTnVtYmVyLmlzU2FmZUludGVnZXIoYnl0ZUxlbmd0aCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBSYW5nZUVycm9yKCdcXCdieXRlTGVuZ3RoXFwnIG11c3QgYmUgYW4gaW50ZWdlci4nKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBpZiAoYnl0ZUxlbmd0aCA8PSAwIHx8IGJ5dGVPZmZzZXQgKyBieXRlTGVuZ3RoID4gYnVmZmVyLmJ5dGVMZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBSYW5nZUVycm9yKGAnYnl0ZUxlbmd0aCcgaXMgb3V0IG9mIHJhbmdlICgwLCAke2J1ZmZlci5ieXRlTGVuZ3RoIC0gYnl0ZU9mZnNldH1dLmApO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgYXJnMyA9PT0gJ29iamVjdCcgJiYgYXJnMyAhPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgb3B0aW9ucyA9IGFyZzM7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZWxzZSBpZiAodHlwZW9mIGFyZzMgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdcXCdvcHRpb25zXFwnIG11c3QgYmUgYW4gb2JqZWN0LicpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2UgaWYgKHR5cGVvZiBhcmcyICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdcXCdieXRlTGVuZ3RoXFwnIG11c3QgYmUgYSBudW1iZXIuJyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSBpZiAodHlwZW9mIGFyZzEgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignXFwnb3B0aW9uc1xcJyBtdXN0IGJlIGFuIG9iamVjdC4nKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGZpbGVQYXRoT3JVaW50OEFycmF5ID0gbmV3IFVpbnQ4QXJyYXkoYnVmZmVyLCBieXRlT2Zmc2V0LCBieXRlTGVuZ3RoKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ1VuZXhwZWN0ZWQgYXJndW1lbnRbMF06IG11c3QgYmUgXFwncGF0aFxcJyBvciBcXCdidWZmZXJcXCcuJyk7XG4gICAgICAgIH1cbiAgICAgICAgLy8gZ2V0IGJhY2tlbmQgaGludHNcbiAgICAgICAgY29uc3QgZXBzID0gb3B0aW9ucy5leGVjdXRpb25Qcm92aWRlcnMgfHwgW107XG4gICAgICAgIGNvbnN0IGJhY2tlbmRIaW50cyA9IGVwcy5tYXAoaSA9PiB0eXBlb2YgaSA9PT0gJ3N0cmluZycgPyBpIDogaS5uYW1lKTtcbiAgICAgICAgY29uc3QgYmFja2VuZCA9IGF3YWl0IHJlc29sdmVCYWNrZW5kKGJhY2tlbmRIaW50cyk7XG4gICAgICAgIGNvbnN0IGhhbmRsZXIgPSBhd2FpdCBiYWNrZW5kLmNyZWF0ZVNlc3Npb25IYW5kbGVyKGZpbGVQYXRoT3JVaW50OEFycmF5LCBvcHRpb25zKTtcbiAgICAgICAgcmV0dXJuIG5ldyBJbmZlcmVuY2VTZXNzaW9uKGhhbmRsZXIpO1xuICAgIH1cbiAgICBzdGFydFByb2ZpbGluZygpIHtcbiAgICAgICAgdGhpcy5oYW5kbGVyLnN0YXJ0UHJvZmlsaW5nKCk7XG4gICAgfVxuICAgIGVuZFByb2ZpbGluZygpIHtcbiAgICAgICAgdGhpcy5oYW5kbGVyLmVuZFByb2ZpbGluZygpO1xuICAgIH1cbiAgICBnZXQgaW5wdXROYW1lcygpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuaGFuZGxlci5pbnB1dE5hbWVzO1xuICAgIH1cbiAgICBnZXQgb3V0cHV0TmFtZXMoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmhhbmRsZXIub3V0cHV0TmFtZXM7XG4gICAgfVxufVxuLy8jIHNvdXJjZU1hcHBpbmdVUkw9aW5mZXJlbmNlLXNlc3Npb24taW1wbC5qcy5tYXAiLCIvLyBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cbmltcG9ydCB7IEluZmVyZW5jZVNlc3Npb24gYXMgSW5mZXJlbmNlU2Vzc2lvbkltcGwgfSBmcm9tICcuL2luZmVyZW5jZS1zZXNzaW9uLWltcGwnO1xuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uYW1pbmctY29udmVudGlvblxuZXhwb3J0IGNvbnN0IEluZmVyZW5jZVNlc3Npb24gPSBJbmZlcmVuY2VTZXNzaW9uSW1wbDtcbi8vIyBzb3VyY2VNYXBwaW5nVVJMPWluZmVyZW5jZS1zZXNzaW9uLmpzLm1hcCIsIi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxuZXhwb3J0IHt9O1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9b25ueC12YWx1ZS5qcy5tYXAiLCIvLyBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cbmNvbnN0IGlzQmlnSW50NjRBcnJheUF2YWlsYWJsZSA9IHR5cGVvZiBCaWdJbnQ2NEFycmF5ICE9PSAndW5kZWZpbmVkJyAmJiB0eXBlb2YgQmlnSW50NjRBcnJheS5mcm9tID09PSAnZnVuY3Rpb24nO1xuY29uc3QgaXNCaWdVaW50NjRBcnJheUF2YWlsYWJsZSA9IHR5cGVvZiBCaWdVaW50NjRBcnJheSAhPT0gJ3VuZGVmaW5lZCcgJiYgdHlwZW9mIEJpZ1VpbnQ2NEFycmF5LmZyb20gPT09ICdmdW5jdGlvbic7XG4vLyBhIHJ1bnRpbWUgbWFwIHRoYXQgbWFwcyB0eXBlIHN0cmluZyB0byBUeXBlZEFycmF5IGNvbnN0cnVjdG9yLiBTaG91bGQgbWF0Y2ggVGVuc29yLkRhdGFUeXBlTWFwLlxuY29uc3QgTlVNRVJJQ19URU5TT1JfVFlQRV9UT19UWVBFREFSUkFZX01BUCA9IG5ldyBNYXAoW1xuICAgIFsnZmxvYXQzMicsIEZsb2F0MzJBcnJheV0sXG4gICAgWyd1aW50OCcsIFVpbnQ4QXJyYXldLFxuICAgIFsnaW50OCcsIEludDhBcnJheV0sXG4gICAgWyd1aW50MTYnLCBVaW50MTZBcnJheV0sXG4gICAgWydpbnQxNicsIEludDE2QXJyYXldLFxuICAgIFsnaW50MzInLCBJbnQzMkFycmF5XSxcbiAgICBbJ2Jvb2wnLCBVaW50OEFycmF5XSxcbiAgICBbJ2Zsb2F0NjQnLCBGbG9hdDY0QXJyYXldLFxuICAgIFsndWludDMyJywgVWludDMyQXJyYXldLFxuXSk7XG4vLyBhIHJ1bnRpbWUgbWFwIHRoYXQgbWFwcyB0eXBlIHN0cmluZyB0byBUeXBlZEFycmF5IGNvbnN0cnVjdG9yLiBTaG91bGQgbWF0Y2ggVGVuc29yLkRhdGFUeXBlTWFwLlxuY29uc3QgTlVNRVJJQ19URU5TT1JfVFlQRURBUlJBWV9UT19UWVBFX01BUCA9IG5ldyBNYXAoW1xuICAgIFtGbG9hdDMyQXJyYXksICdmbG9hdDMyJ10sXG4gICAgW1VpbnQ4QXJyYXksICd1aW50OCddLFxuICAgIFtJbnQ4QXJyYXksICdpbnQ4J10sXG4gICAgW1VpbnQxNkFycmF5LCAndWludDE2J10sXG4gICAgW0ludDE2QXJyYXksICdpbnQxNiddLFxuICAgIFtJbnQzMkFycmF5LCAnaW50MzInXSxcbiAgICBbRmxvYXQ2NEFycmF5LCAnZmxvYXQ2NCddLFxuICAgIFtVaW50MzJBcnJheSwgJ3VpbnQzMiddLFxuXSk7XG5pZiAoaXNCaWdJbnQ2NEFycmF5QXZhaWxhYmxlKSB7XG4gICAgTlVNRVJJQ19URU5TT1JfVFlQRV9UT19UWVBFREFSUkFZX01BUC5zZXQoJ2ludDY0JywgQmlnSW50NjRBcnJheSk7XG4gICAgTlVNRVJJQ19URU5TT1JfVFlQRURBUlJBWV9UT19UWVBFX01BUC5zZXQoQmlnSW50NjRBcnJheSwgJ2ludDY0Jyk7XG59XG5pZiAoaXNCaWdVaW50NjRBcnJheUF2YWlsYWJsZSkge1xuICAgIE5VTUVSSUNfVEVOU09SX1RZUEVfVE9fVFlQRURBUlJBWV9NQVAuc2V0KCd1aW50NjQnLCBCaWdVaW50NjRBcnJheSk7XG4gICAgTlVNRVJJQ19URU5TT1JfVFlQRURBUlJBWV9UT19UWVBFX01BUC5zZXQoQmlnVWludDY0QXJyYXksICd1aW50NjQnKTtcbn1cbi8qKlxuICogY2FsY3VsYXRlIHNpemUgZnJvbSBkaW1zLlxuICpcbiAqIEBwYXJhbSBkaW1zIHRoZSBkaW1zIGFycmF5LiBNYXkgYmUgYW4gaWxsZWdhbCBpbnB1dC5cbiAqL1xuY29uc3QgY2FsY3VsYXRlU2l6ZSA9IChkaW1zKSA9PiB7XG4gICAgbGV0IHNpemUgPSAxO1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgZGltcy5sZW5ndGg7IGkrKykge1xuICAgICAgICBjb25zdCBkaW0gPSBkaW1zW2ldO1xuICAgICAgICBpZiAodHlwZW9mIGRpbSAhPT0gJ251bWJlcicgfHwgIU51bWJlci5pc1NhZmVJbnRlZ2VyKGRpbSkpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoYGRpbXNbJHtpfV0gbXVzdCBiZSBhbiBpbnRlZ2VyLCBnb3Q6ICR7ZGltfWApO1xuICAgICAgICB9XG4gICAgICAgIGlmIChkaW0gPCAwKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgUmFuZ2VFcnJvcihgZGltc1ske2l9XSBtdXN0IGJlIGEgbm9uLW5lZ2F0aXZlIGludGVnZXIsIGdvdDogJHtkaW19YCk7XG4gICAgICAgIH1cbiAgICAgICAgc2l6ZSAqPSBkaW07XG4gICAgfVxuICAgIHJldHVybiBzaXplO1xufTtcbmV4cG9ydCBjbGFzcyBUZW5zb3Ige1xuICAgIGNvbnN0cnVjdG9yKGFyZzAsIGFyZzEsIGFyZzIpIHtcbiAgICAgICAgbGV0IHR5cGU7XG4gICAgICAgIGxldCBkYXRhO1xuICAgICAgICBsZXQgZGltcztcbiAgICAgICAgLy8gY2hlY2sgd2hldGhlciBhcmcwIGlzIHR5cGUgb3IgZGF0YVxuICAgICAgICBpZiAodHlwZW9mIGFyZzAgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICAvL1xuICAgICAgICAgICAgLy8gT3ZlcnJpZGU6IGNvbnN0cnVjdG9yKHR5cGUsIGRhdGEsIC4uLilcbiAgICAgICAgICAgIC8vXG4gICAgICAgICAgICB0eXBlID0gYXJnMDtcbiAgICAgICAgICAgIGRpbXMgPSBhcmcyO1xuICAgICAgICAgICAgaWYgKGFyZzAgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICAgICAgLy8gc3RyaW5nIHRlbnNvclxuICAgICAgICAgICAgICAgIGlmICghQXJyYXkuaXNBcnJheShhcmcxKSkge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdBIHN0cmluZyB0ZW5zb3JcXCdzIGRhdGEgbXVzdCBiZSBhIHN0cmluZyBhcnJheS4nKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgLy8gd2UgZG9uJ3QgY2hlY2sgd2hldGhlciBldmVyeSBlbGVtZW50IGluIHRoZSBhcnJheSBpcyBzdHJpbmc7IHRoaXMgaXMgdG9vIHNsb3cuIHdlIGFzc3VtZSBpdCdzIGNvcnJlY3QgYW5kXG4gICAgICAgICAgICAgICAgLy8gZXJyb3Igd2lsbCBiZSBwb3B1bGF0ZWQgYXQgaW5mZXJlbmNlXG4gICAgICAgICAgICAgICAgZGF0YSA9IGFyZzE7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAvLyBudW1lcmljIHRlbnNvclxuICAgICAgICAgICAgICAgIGNvbnN0IHR5cGVkQXJyYXlDb25zdHJ1Y3RvciA9IE5VTUVSSUNfVEVOU09SX1RZUEVfVE9fVFlQRURBUlJBWV9NQVAuZ2V0KGFyZzApO1xuICAgICAgICAgICAgICAgIGlmICh0eXBlZEFycmF5Q29uc3RydWN0b3IgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKGBVbnN1cHBvcnRlZCB0ZW5zb3IgdHlwZTogJHthcmcwfS5gKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKEFycmF5LmlzQXJyYXkoYXJnMSkpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gdXNlICdhcyBhbnknIGhlcmUgYmVjYXVzZSBUeXBlU2NyaXB0J3MgY2hlY2sgb24gdHlwZSBvZiAnU3VwcG9ydGVkVHlwZWRBcnJheUNvbnN0cnVjdG9ycy5mcm9tKCknIHByb2R1Y2VzXG4gICAgICAgICAgICAgICAgICAgIC8vIGluY29ycmVjdCByZXN1bHRzLlxuICAgICAgICAgICAgICAgICAgICAvLyAndHlwZWRBcnJheUNvbnN0cnVjdG9yJyBzaG91bGQgYmUgb25lIG9mIHRoZSB0eXBlZCBhcnJheSBwcm90b3R5cGUgb2JqZWN0cy5cbiAgICAgICAgICAgICAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby1leHBsaWNpdC1hbnlcbiAgICAgICAgICAgICAgICAgICAgZGF0YSA9IHR5cGVkQXJyYXlDb25zdHJ1Y3Rvci5mcm9tKGFyZzEpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIGlmIChhcmcxIGluc3RhbmNlb2YgdHlwZWRBcnJheUNvbnN0cnVjdG9yKSB7XG4gICAgICAgICAgICAgICAgICAgIGRhdGEgPSBhcmcxO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihgQSAke3R5cGV9IHRlbnNvcidzIGRhdGEgbXVzdCBiZSB0eXBlIG9mICR7dHlwZWRBcnJheUNvbnN0cnVjdG9yfWApO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIC8vXG4gICAgICAgICAgICAvLyBPdmVycmlkZTogY29uc3RydWN0b3IoZGF0YSwgLi4uKVxuICAgICAgICAgICAgLy9cbiAgICAgICAgICAgIGRpbXMgPSBhcmcxO1xuICAgICAgICAgICAgaWYgKEFycmF5LmlzQXJyYXkoYXJnMCkpIHtcbiAgICAgICAgICAgICAgICAvLyBvbmx5IGJvb2xlYW5bXSBhbmQgc3RyaW5nW10gaXMgc3VwcG9ydGVkXG4gICAgICAgICAgICAgICAgaWYgKGFyZzAubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ1RlbnNvciB0eXBlIGNhbm5vdCBiZSBpbmZlcnJlZCBmcm9tIGFuIGVtcHR5IGFycmF5LicpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBjb25zdCBmaXJzdEVsZW1lbnRUeXBlID0gdHlwZW9mIGFyZzBbMF07XG4gICAgICAgICAgICAgICAgaWYgKGZpcnN0RWxlbWVudFR5cGUgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICAgICAgICAgIHR5cGUgPSAnc3RyaW5nJztcbiAgICAgICAgICAgICAgICAgICAgZGF0YSA9IGFyZzA7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2UgaWYgKGZpcnN0RWxlbWVudFR5cGUgPT09ICdib29sZWFuJykge1xuICAgICAgICAgICAgICAgICAgICB0eXBlID0gJ2Jvb2wnO1xuICAgICAgICAgICAgICAgICAgICAvLyAnYXJnMCcgaXMgb2YgdHlwZSAnYm9vbGVhbltdJy4gVWludDhBcnJheS5mcm9tKGJvb2xlYW5bXSkgYWN0dWFsbHkgd29ya3MsIGJ1dCB0eXBlc2NyaXB0IHRoaW5rcyB0aGlzIGlzXG4gICAgICAgICAgICAgICAgICAgIC8vIHdyb25nIHR5cGUuIFdlIHVzZSAnYXMgYW55JyB0byBtYWtlIGl0IGhhcHB5LlxuICAgICAgICAgICAgICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLWV4cGxpY2l0LWFueVxuICAgICAgICAgICAgICAgICAgICBkYXRhID0gVWludDhBcnJheS5mcm9tKGFyZzApO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihgSW52YWxpZCBlbGVtZW50IHR5cGUgb2YgZGF0YSBhcnJheTogJHtmaXJzdEVsZW1lbnRUeXBlfS5gKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAvLyBnZXQgdGVuc29yIHR5cGUgZnJvbSBUeXBlZEFycmF5XG4gICAgICAgICAgICAgICAgY29uc3QgbWFwcGVkVHlwZSA9IE5VTUVSSUNfVEVOU09SX1RZUEVEQVJSQVlfVE9fVFlQRV9NQVAuZ2V0KGFyZzAuY29uc3RydWN0b3IpO1xuICAgICAgICAgICAgICAgIGlmIChtYXBwZWRUeXBlID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihgVW5zdXBwb3J0ZWQgdHlwZSBmb3IgdGVuc29yIGRhdGE6ICR7YXJnMC5jb25zdHJ1Y3Rvcn0uYCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHR5cGUgPSBtYXBwZWRUeXBlO1xuICAgICAgICAgICAgICAgIGRhdGEgPSBhcmcwO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIC8vIHR5cGUgYW5kIGRhdGEgaXMgcHJvY2Vzc2VkLCBub3cgcHJvY2Vzc2luZyBkaW1zXG4gICAgICAgIGlmIChkaW1zID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIC8vIGFzc3VtZSAxLUQgdGVuc29yIGlmIGRpbXMgb21pdHRlZFxuICAgICAgICAgICAgZGltcyA9IFtkYXRhLmxlbmd0aF07XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAoIUFycmF5LmlzQXJyYXkoZGltcykpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ0EgdGVuc29yXFwncyBkaW1zIG11c3QgYmUgYSBudW1iZXIgYXJyYXknKTtcbiAgICAgICAgfVxuICAgICAgICAvLyBwZXJmb3JtIGNoZWNrXG4gICAgICAgIGNvbnN0IHNpemUgPSBjYWxjdWxhdGVTaXplKGRpbXMpO1xuICAgICAgICBpZiAoc2l6ZSAhPT0gZGF0YS5sZW5ndGgpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgVGVuc29yJ3Mgc2l6ZSgke3NpemV9KSBkb2VzIG5vdCBtYXRjaCBkYXRhIGxlbmd0aCgke2RhdGEubGVuZ3RofSkuYCk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5kaW1zID0gZGltcztcbiAgICAgICAgdGhpcy50eXBlID0gdHlwZTtcbiAgICAgICAgdGhpcy5kYXRhID0gZGF0YTtcbiAgICAgICAgdGhpcy5zaXplID0gc2l6ZTtcbiAgICB9XG4gICAgLy8gI2VuZHJlZ2lvblxuICAgIC8qKlxuICAgICAqIENyZWF0ZSBhIG5ldyB0ZW5zb3Igb2JqZWN0IGZyb20gaW1hZ2Ugb2JqZWN0XG4gICAgICpcbiAgICAgKiBAcGFyYW0gYnVmZmVyIC0gRXh0cmFjdGVkIGltYWdlIGJ1ZmZlciBkYXRhIC0gYXNzdW1pbmcgUkdCQSBmb3JtYXRcbiAgICAgKiBAcGFyYW0gaW1hZ2VGb3JtYXQgLSBpbnB1dCBpbWFnZSBjb25maWd1cmF0aW9uIC0gcmVxdWlyZWQgY29uZmlndXJhdGlvbnMgaGVpZ2h0LCB3aWR0aCwgZm9ybWF0XG4gICAgICogQHBhcmFtIHRlbnNvckZvcm1hdCAtIG91dHB1dCB0ZW5zb3IgY29uZmlndXJhdGlvbiAtIERlZmF1bHQgaXMgUkdCIGZvcm1hdFxuICAgICAqL1xuICAgIHN0YXRpYyBidWZmZXJUb1RlbnNvcihidWZmZXIsIG9wdGlvbnMpIHtcbiAgICAgICAgaWYgKGJ1ZmZlciA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ltYWdlIGJ1ZmZlciBtdXN0IGJlIGRlZmluZWQnKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAob3B0aW9ucy5oZWlnaHQgPT09IHVuZGVmaW5lZCB8fCBvcHRpb25zLndpZHRoID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignSW1hZ2UgaGVpZ2h0IGFuZCB3aWR0aCBtdXN0IGJlIGRlZmluZWQnKTtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCB7IGhlaWdodCwgd2lkdGggfSA9IG9wdGlvbnM7XG4gICAgICAgIGNvbnN0IG5vcm0gPSBvcHRpb25zLm5vcm07XG4gICAgICAgIGxldCBub3JtTWVhbjtcbiAgICAgICAgbGV0IG5vcm1CaWFzO1xuICAgICAgICBpZiAobm9ybSA9PT0gdW5kZWZpbmVkIHx8IG5vcm0ubWVhbiA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICBub3JtTWVhbiA9IDI1NTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIG5vcm1NZWFuID0gbm9ybS5tZWFuO1xuICAgICAgICB9XG4gICAgICAgIGlmIChub3JtID09PSB1bmRlZmluZWQgfHwgbm9ybS5iaWFzID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIG5vcm1CaWFzID0gMDtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIG5vcm1CaWFzID0gbm9ybS5iaWFzO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IGlucHV0Zm9ybWF0ID0gb3B0aW9ucy5iaXRtYXBGb3JtYXQgIT09IHVuZGVmaW5lZCA/IG9wdGlvbnMuYml0bWFwRm9ybWF0IDogJ1JHQkEnO1xuICAgICAgICAvLyBkZWZhdWx0IHZhbHVlIGlzIFJHQkEgc2luY2UgaW1hZ2VkYXRhIGFuZCBIVE1MSW1hZ2VFbGVtZW50IHVzZXMgaXRcbiAgICAgICAgY29uc3Qgb3V0cHV0Zm9ybWF0ID0gb3B0aW9ucy50ZW5zb3JGb3JtYXQgIT09IHVuZGVmaW5lZCA/XG4gICAgICAgICAgICAob3B0aW9ucy50ZW5zb3JGb3JtYXQgIT09IHVuZGVmaW5lZCA/IG9wdGlvbnMudGVuc29yRm9ybWF0IDogJ1JHQicpIDpcbiAgICAgICAgICAgICdSR0InO1xuICAgICAgICBjb25zdCBvZmZzZXQgPSBoZWlnaHQgKiB3aWR0aDtcbiAgICAgICAgY29uc3QgZmxvYXQzMkRhdGEgPSBvdXRwdXRmb3JtYXQgPT09ICdSR0JBJyA/IG5ldyBGbG9hdDMyQXJyYXkob2Zmc2V0ICogNCkgOiBuZXcgRmxvYXQzMkFycmF5KG9mZnNldCAqIDMpO1xuICAgICAgICAvLyBEZWZhdWx0IHBvaW50ZXIgYXNzaWdubWVudHNcbiAgICAgICAgbGV0IHN0ZXAgPSA0LCBySW1hZ2VQb2ludGVyID0gMCwgZ0ltYWdlUG9pbnRlciA9IDEsIGJJbWFnZVBvaW50ZXIgPSAyLCBhSW1hZ2VQb2ludGVyID0gMztcbiAgICAgICAgbGV0IHJUZW5zb3JQb2ludGVyID0gMCwgZ1RlbnNvclBvaW50ZXIgPSBvZmZzZXQsIGJUZW5zb3JQb2ludGVyID0gb2Zmc2V0ICogMiwgYVRlbnNvclBvaW50ZXIgPSAtMTtcbiAgICAgICAgLy8gVXBkYXRpbmcgdGhlIHBvaW50ZXIgYXNzaWdubWVudHMgYmFzZWQgb24gdGhlIGlucHV0IGltYWdlIGZvcm1hdFxuICAgICAgICBpZiAoaW5wdXRmb3JtYXQgPT09ICdSR0InKSB7XG4gICAgICAgICAgICBzdGVwID0gMztcbiAgICAgICAgICAgIHJJbWFnZVBvaW50ZXIgPSAwO1xuICAgICAgICAgICAgZ0ltYWdlUG9pbnRlciA9IDE7XG4gICAgICAgICAgICBiSW1hZ2VQb2ludGVyID0gMjtcbiAgICAgICAgICAgIGFJbWFnZVBvaW50ZXIgPSAtMTtcbiAgICAgICAgfVxuICAgICAgICAvLyBVcGRhdGluZyB0aGUgcG9pbnRlciBhc3NpZ25tZW50cyBiYXNlZCBvbiB0aGUgb3V0cHV0IHRlbnNvciBmb3JtYXRcbiAgICAgICAgaWYgKG91dHB1dGZvcm1hdCA9PT0gJ1JHQkEnKSB7XG4gICAgICAgICAgICBhVGVuc29yUG9pbnRlciA9IG9mZnNldCAqIDM7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAob3V0cHV0Zm9ybWF0ID09PSAnUkJHJykge1xuICAgICAgICAgICAgclRlbnNvclBvaW50ZXIgPSAwO1xuICAgICAgICAgICAgYlRlbnNvclBvaW50ZXIgPSBvZmZzZXQ7XG4gICAgICAgICAgICBnVGVuc29yUG9pbnRlciA9IG9mZnNldCAqIDI7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAob3V0cHV0Zm9ybWF0ID09PSAnQkdSJykge1xuICAgICAgICAgICAgYlRlbnNvclBvaW50ZXIgPSAwO1xuICAgICAgICAgICAgZ1RlbnNvclBvaW50ZXIgPSBvZmZzZXQ7XG4gICAgICAgICAgICByVGVuc29yUG9pbnRlciA9IG9mZnNldCAqIDI7XG4gICAgICAgIH1cbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBvZmZzZXQ7IGkrKywgckltYWdlUG9pbnRlciArPSBzdGVwLCBiSW1hZ2VQb2ludGVyICs9IHN0ZXAsIGdJbWFnZVBvaW50ZXIgKz0gc3RlcCwgYUltYWdlUG9pbnRlciArPSBzdGVwKSB7XG4gICAgICAgICAgICBmbG9hdDMyRGF0YVtyVGVuc29yUG9pbnRlcisrXSA9IChidWZmZXJbckltYWdlUG9pbnRlcl0gKyBub3JtQmlhcykgLyBub3JtTWVhbjtcbiAgICAgICAgICAgIGZsb2F0MzJEYXRhW2dUZW5zb3JQb2ludGVyKytdID0gKGJ1ZmZlcltnSW1hZ2VQb2ludGVyXSArIG5vcm1CaWFzKSAvIG5vcm1NZWFuO1xuICAgICAgICAgICAgZmxvYXQzMkRhdGFbYlRlbnNvclBvaW50ZXIrK10gPSAoYnVmZmVyW2JJbWFnZVBvaW50ZXJdICsgbm9ybUJpYXMpIC8gbm9ybU1lYW47XG4gICAgICAgICAgICBpZiAoYVRlbnNvclBvaW50ZXIgIT09IC0xICYmIGFJbWFnZVBvaW50ZXIgIT09IC0xKSB7XG4gICAgICAgICAgICAgICAgZmxvYXQzMkRhdGFbYVRlbnNvclBvaW50ZXIrK10gPSAoYnVmZmVyW2FJbWFnZVBvaW50ZXJdICsgbm9ybUJpYXMpIC8gbm9ybU1lYW47XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgLy8gRmxvYXQzMkFycmF5IC0+IG9ydC5UZW5zb3JcbiAgICAgICAgY29uc3Qgb3V0cHV0VGVuc29yID0gb3V0cHV0Zm9ybWF0ID09PSAnUkdCQScgPyBuZXcgVGVuc29yKCdmbG9hdDMyJywgZmxvYXQzMkRhdGEsIFsxLCA0LCBoZWlnaHQsIHdpZHRoXSkgOlxuICAgICAgICAgICAgbmV3IFRlbnNvcignZmxvYXQzMicsIGZsb2F0MzJEYXRhLCBbMSwgMywgaGVpZ2h0LCB3aWR0aF0pO1xuICAgICAgICByZXR1cm4gb3V0cHV0VGVuc29yO1xuICAgIH1cbiAgICBzdGF0aWMgYXN5bmMgZnJvbUltYWdlKGltYWdlLCBvcHRpb25zKSB7XG4gICAgICAgIC8vIGNoZWNraW5nIHRoZSB0eXBlIG9mIGltYWdlIG9iamVjdFxuICAgICAgICBjb25zdCBpc0hUTUxJbWFnZUVsZSA9IHR5cGVvZiAoSFRNTEltYWdlRWxlbWVudCkgIT09ICd1bmRlZmluZWQnICYmIGltYWdlIGluc3RhbmNlb2YgSFRNTEltYWdlRWxlbWVudDtcbiAgICAgICAgY29uc3QgaXNJbWFnZURhdGFFbGUgPSB0eXBlb2YgKEltYWdlRGF0YSkgIT09ICd1bmRlZmluZWQnICYmIGltYWdlIGluc3RhbmNlb2YgSW1hZ2VEYXRhO1xuICAgICAgICBjb25zdCBpc0ltYWdlQml0bWFwID0gdHlwZW9mIChJbWFnZUJpdG1hcCkgIT09ICd1bmRlZmluZWQnICYmIGltYWdlIGluc3RhbmNlb2YgSW1hZ2VCaXRtYXA7XG4gICAgICAgIGNvbnN0IGlzVVJMID0gdHlwZW9mIChTdHJpbmcpICE9PSAndW5kZWZpbmVkJyAmJiAoaW1hZ2UgaW5zdGFuY2VvZiBTdHJpbmcgfHwgdHlwZW9mIGltYWdlID09PSAnc3RyaW5nJyk7XG4gICAgICAgIGxldCBkYXRhO1xuICAgICAgICBsZXQgdGVuc29yQ29uZmlnID0ge307XG4gICAgICAgIC8vIGZpbGxpbmcgYW5kIGNoZWNraW5nIGltYWdlIGNvbmZpZ3VyYXRpb24gb3B0aW9uc1xuICAgICAgICBpZiAoaXNIVE1MSW1hZ2VFbGUpIHtcbiAgICAgICAgICAgIC8vIEhUTUxJbWFnZUVsZW1lbnQgLSBpbWFnZSBvYmplY3QgLSBmb3JtYXQgaXMgUkdCQSBieSBkZWZhdWx0XG4gICAgICAgICAgICBjb25zdCBjYW52YXMgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdjYW52YXMnKTtcbiAgICAgICAgICAgIGNvbnN0IHBpeGVsczJEQ29udGV4dCA9IGNhbnZhcy5nZXRDb250ZXh0KCcyZCcpO1xuICAgICAgICAgICAgaWYgKHBpeGVsczJEQ29udGV4dCAhPSBudWxsKSB7XG4gICAgICAgICAgICAgICAgbGV0IGhlaWdodCA9IGltYWdlLm5hdHVyYWxIZWlnaHQ7XG4gICAgICAgICAgICAgICAgbGV0IHdpZHRoID0gaW1hZ2UubmF0dXJhbFdpZHRoO1xuICAgICAgICAgICAgICAgIGlmIChvcHRpb25zICE9PSB1bmRlZmluZWQgJiYgb3B0aW9ucy5yZXNpemVkSGVpZ2h0ICE9PSB1bmRlZmluZWQgJiYgb3B0aW9ucy5yZXNpemVkV2lkdGggIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICBoZWlnaHQgPSBvcHRpb25zLnJlc2l6ZWRIZWlnaHQ7XG4gICAgICAgICAgICAgICAgICAgIHdpZHRoID0gb3B0aW9ucy5yZXNpemVkV2lkdGg7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChvcHRpb25zICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgdGVuc29yQ29uZmlnID0gb3B0aW9ucztcbiAgICAgICAgICAgICAgICAgICAgaWYgKG9wdGlvbnMudGVuc29yRm9ybWF0ICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignSW1hZ2UgaW5wdXQgY29uZmlnIGZvcm1hdCBtdXN0IGJlIFJHQkEgZm9yIEhUTUxJbWFnZUVsZW1lbnQnKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRlbnNvckNvbmZpZy50ZW5zb3JGb3JtYXQgPSAnUkdCQSc7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgaWYgKG9wdGlvbnMuaGVpZ2h0ICE9PSB1bmRlZmluZWQgJiYgb3B0aW9ucy5oZWlnaHQgIT09IGhlaWdodCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbWFnZSBpbnB1dCBjb25maWcgaGVpZ2h0IGRvZXNuXFwndCBtYXRjaCBIVE1MSW1hZ2VFbGVtZW50IGhlaWdodCcpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGVuc29yQ29uZmlnLmhlaWdodCA9IGhlaWdodDtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBpZiAob3B0aW9ucy53aWR0aCAhPT0gdW5kZWZpbmVkICYmIG9wdGlvbnMud2lkdGggIT09IHdpZHRoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ltYWdlIGlucHV0IGNvbmZpZyB3aWR0aCBkb2VzblxcJ3QgbWF0Y2ggSFRNTEltYWdlRWxlbWVudCB3aWR0aCcpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGVuc29yQ29uZmlnLndpZHRoID0gd2lkdGg7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHRlbnNvckNvbmZpZy50ZW5zb3JGb3JtYXQgPSAnUkdCQSc7XG4gICAgICAgICAgICAgICAgICAgIHRlbnNvckNvbmZpZy5oZWlnaHQgPSBoZWlnaHQ7XG4gICAgICAgICAgICAgICAgICAgIHRlbnNvckNvbmZpZy53aWR0aCA9IHdpZHRoO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBjYW52YXMud2lkdGggPSB3aWR0aDtcbiAgICAgICAgICAgICAgICBjYW52YXMuaGVpZ2h0ID0gaGVpZ2h0O1xuICAgICAgICAgICAgICAgIHBpeGVsczJEQ29udGV4dC5kcmF3SW1hZ2UoaW1hZ2UsIDAsIDAsIHdpZHRoLCBoZWlnaHQpO1xuICAgICAgICAgICAgICAgIGRhdGEgPSBwaXhlbHMyRENvbnRleHQuZ2V0SW1hZ2VEYXRhKDAsIDAsIHdpZHRoLCBoZWlnaHQpLmRhdGE7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0NhbiBub3QgYWNjZXNzIGltYWdlIGRhdGEnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmIChpc0ltYWdlRGF0YUVsZSkge1xuICAgICAgICAgICAgLy8gSW1hZ2VEYXRhIC0gaW1hZ2Ugb2JqZWN0IC0gZm9ybWF0IGlzIFJHQkEgYnkgZGVmYXVsdFxuICAgICAgICAgICAgY29uc3QgZm9ybWF0ID0gJ1JHQkEnO1xuICAgICAgICAgICAgbGV0IGhlaWdodDtcbiAgICAgICAgICAgIGxldCB3aWR0aDtcbiAgICAgICAgICAgIGlmIChvcHRpb25zICE9PSB1bmRlZmluZWQgJiYgb3B0aW9ucy5yZXNpemVkV2lkdGggIT09IHVuZGVmaW5lZCAmJiBvcHRpb25zLnJlc2l6ZWRIZWlnaHQgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgIGhlaWdodCA9IG9wdGlvbnMucmVzaXplZEhlaWdodDtcbiAgICAgICAgICAgICAgICB3aWR0aCA9IG9wdGlvbnMucmVzaXplZFdpZHRoO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgaGVpZ2h0ID0gaW1hZ2UuaGVpZ2h0O1xuICAgICAgICAgICAgICAgIHdpZHRoID0gaW1hZ2Uud2lkdGg7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAob3B0aW9ucyAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgdGVuc29yQ29uZmlnID0gb3B0aW9ucztcbiAgICAgICAgICAgICAgICBpZiAob3B0aW9ucy5iaXRtYXBGb3JtYXQgIT09IHVuZGVmaW5lZCAmJiBvcHRpb25zLmJpdG1hcEZvcm1hdCAhPT0gZm9ybWF0KSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignSW1hZ2UgaW5wdXQgY29uZmlnIGZvcm1hdCBtdXN0IGJlIFJHQkEgZm9yIEltYWdlRGF0YScpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdGVuc29yQ29uZmlnLmJpdG1hcEZvcm1hdCA9ICdSR0JBJztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICB0ZW5zb3JDb25maWcuYml0bWFwRm9ybWF0ID0gJ1JHQkEnO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGVuc29yQ29uZmlnLmhlaWdodCA9IGhlaWdodDtcbiAgICAgICAgICAgIHRlbnNvckNvbmZpZy53aWR0aCA9IHdpZHRoO1xuICAgICAgICAgICAgaWYgKG9wdGlvbnMgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgIGNvbnN0IHRlbXBDYW52YXMgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdjYW52YXMnKTtcbiAgICAgICAgICAgICAgICB0ZW1wQ2FudmFzLndpZHRoID0gd2lkdGg7XG4gICAgICAgICAgICAgICAgdGVtcENhbnZhcy5oZWlnaHQgPSBoZWlnaHQ7XG4gICAgICAgICAgICAgICAgY29uc3QgcGl4ZWxzMkRDb250ZXh0ID0gdGVtcENhbnZhcy5nZXRDb250ZXh0KCcyZCcpO1xuICAgICAgICAgICAgICAgIGlmIChwaXhlbHMyRENvbnRleHQgIT0gbnVsbCkge1xuICAgICAgICAgICAgICAgICAgICBwaXhlbHMyRENvbnRleHQucHV0SW1hZ2VEYXRhKGltYWdlLCAwLCAwKTtcbiAgICAgICAgICAgICAgICAgICAgZGF0YSA9IHBpeGVsczJEQ29udGV4dC5nZXRJbWFnZURhdGEoMCwgMCwgd2lkdGgsIGhlaWdodCkuZGF0YTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignQ2FuIG5vdCBhY2Nlc3MgaW1hZ2UgZGF0YScpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIGRhdGEgPSBpbWFnZS5kYXRhO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKGlzSW1hZ2VCaXRtYXApIHtcbiAgICAgICAgICAgIC8vIEltYWdlQml0bWFwIC0gaW1hZ2Ugb2JqZWN0IC0gZm9ybWF0IG11c3QgYmUgcHJvdmlkZWQgYnkgdXNlclxuICAgICAgICAgICAgaWYgKG9wdGlvbnMgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignUGxlYXNlIHByb3ZpZGUgaW1hZ2UgY29uZmlnIHdpdGggZm9ybWF0IGZvciBJbWFnZWJpdG1hcCcpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG9wdGlvbnMuYml0bWFwRm9ybWF0ICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ltYWdlIGlucHV0IGNvbmZpZyBmb3JtYXQgbXVzdCBiZSBkZWZpbmVkIGZvciBJbWFnZUJpdG1hcCcpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3QgcGl4ZWxzMkRDb250ZXh0ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnY2FudmFzJykuZ2V0Q29udGV4dCgnMmQnKTtcbiAgICAgICAgICAgIGlmIChwaXhlbHMyRENvbnRleHQgIT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIGNvbnN0IGhlaWdodCA9IGltYWdlLmhlaWdodDtcbiAgICAgICAgICAgICAgICBjb25zdCB3aWR0aCA9IGltYWdlLndpZHRoO1xuICAgICAgICAgICAgICAgIHBpeGVsczJEQ29udGV4dC5kcmF3SW1hZ2UoaW1hZ2UsIDAsIDAsIHdpZHRoLCBoZWlnaHQpO1xuICAgICAgICAgICAgICAgIGRhdGEgPSBwaXhlbHMyRENvbnRleHQuZ2V0SW1hZ2VEYXRhKDAsIDAsIHdpZHRoLCBoZWlnaHQpLmRhdGE7XG4gICAgICAgICAgICAgICAgaWYgKG9wdGlvbnMgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICAvLyB1c2luZyBzcXVhcmUgYnJhY2tldHMgdG8gYXZvaWQgVFMgZXJyb3IgLSB0eXBlICduZXZlcidcbiAgICAgICAgICAgICAgICAgICAgaWYgKG9wdGlvbnMuaGVpZ2h0ICE9PSB1bmRlZmluZWQgJiYgb3B0aW9ucy5oZWlnaHQgIT09IGhlaWdodCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbWFnZSBpbnB1dCBjb25maWcgaGVpZ2h0IGRvZXNuXFwndCBtYXRjaCBJbWFnZUJpdG1hcCBoZWlnaHQnKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRlbnNvckNvbmZpZy5oZWlnaHQgPSBoZWlnaHQ7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgLy8gdXNpbmcgc3F1YXJlIGJyYWNrZXRzIHRvIGF2b2lkIFRTIGVycm9yIC0gdHlwZSAnbmV2ZXInXG4gICAgICAgICAgICAgICAgICAgIGlmIChvcHRpb25zLndpZHRoICE9PSB1bmRlZmluZWQgJiYgb3B0aW9ucy53aWR0aCAhPT0gd2lkdGgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignSW1hZ2UgaW5wdXQgY29uZmlnIHdpZHRoIGRvZXNuXFwndCBtYXRjaCBJbWFnZUJpdG1hcCB3aWR0aCcpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGVuc29yQ29uZmlnLndpZHRoID0gd2lkdGg7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHRlbnNvckNvbmZpZy5oZWlnaHQgPSBoZWlnaHQ7XG4gICAgICAgICAgICAgICAgICAgIHRlbnNvckNvbmZpZy53aWR0aCA9IHdpZHRoO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm4gVGVuc29yLmJ1ZmZlclRvVGVuc29yKGRhdGEsIHRlbnNvckNvbmZpZyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0NhbiBub3QgYWNjZXNzIGltYWdlIGRhdGEnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmIChpc1VSTCkge1xuICAgICAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgICAgICBjb25zdCBjYW52YXMgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdjYW52YXMnKTtcbiAgICAgICAgICAgICAgICBjb25zdCBjb250ZXh0ID0gY2FudmFzLmdldENvbnRleHQoJzJkJyk7XG4gICAgICAgICAgICAgICAgaWYgKCFpbWFnZSB8fCAhY29udGV4dCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVqZWN0KCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGNvbnN0IG5ld0ltYWdlID0gbmV3IEltYWdlKCk7XG4gICAgICAgICAgICAgICAgbmV3SW1hZ2UuY3Jvc3NPcmlnaW4gPSAnQW5vbnltb3VzJztcbiAgICAgICAgICAgICAgICBuZXdJbWFnZS5zcmMgPSBpbWFnZTtcbiAgICAgICAgICAgICAgICBuZXdJbWFnZS5vbmxvYWQgPSAoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGNhbnZhcy53aWR0aCA9IG5ld0ltYWdlLndpZHRoO1xuICAgICAgICAgICAgICAgICAgICBjYW52YXMuaGVpZ2h0ID0gbmV3SW1hZ2UuaGVpZ2h0O1xuICAgICAgICAgICAgICAgICAgICBjb250ZXh0LmRyYXdJbWFnZShuZXdJbWFnZSwgMCwgMCwgY2FudmFzLndpZHRoLCBjYW52YXMuaGVpZ2h0KTtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgaW1nID0gY29udGV4dC5nZXRJbWFnZURhdGEoMCwgMCwgY2FudmFzLndpZHRoLCBjYW52YXMuaGVpZ2h0KTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKG9wdGlvbnMgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gdXNpbmcgc3F1YXJlIGJyYWNrZXRzIHRvIGF2b2lkIFRTIGVycm9yIC0gdHlwZSAnbmV2ZXInXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAob3B0aW9ucy5oZWlnaHQgIT09IHVuZGVmaW5lZCAmJiBvcHRpb25zLmhlaWdodCAhPT0gY2FudmFzLmhlaWdodCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignSW1hZ2UgaW5wdXQgY29uZmlnIGhlaWdodCBkb2VzblxcJ3QgbWF0Y2ggSW1hZ2VCaXRtYXAgaGVpZ2h0Jyk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0ZW5zb3JDb25maWcuaGVpZ2h0ID0gY2FudmFzLmhlaWdodDtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIHVzaW5nIHNxdWFyZSBicmFja2V0cyB0byBhdm9pZCBUUyBlcnJvciAtIHR5cGUgJ25ldmVyJ1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG9wdGlvbnMud2lkdGggIT09IHVuZGVmaW5lZCAmJiBvcHRpb25zLndpZHRoICE9PSBjYW52YXMud2lkdGgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ltYWdlIGlucHV0IGNvbmZpZyB3aWR0aCBkb2VzblxcJ3QgbWF0Y2ggSW1hZ2VCaXRtYXAgd2lkdGgnKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRlbnNvckNvbmZpZy53aWR0aCA9IGNhbnZhcy53aWR0aDtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRlbnNvckNvbmZpZy5oZWlnaHQgPSBjYW52YXMuaGVpZ2h0O1xuICAgICAgICAgICAgICAgICAgICAgICAgdGVuc29yQ29uZmlnLndpZHRoID0gY2FudmFzLndpZHRoO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHJlc29sdmUoVGVuc29yLmJ1ZmZlclRvVGVuc29yKGltZy5kYXRhLCB0ZW5zb3JDb25maWcpKTtcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0lucHV0IGRhdGEgcHJvdmlkZWQgaXMgbm90IHN1cHBvcnRlZCAtIGFib3J0ZWQgdGVuc29yIGNyZWF0aW9uJyk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGRhdGEgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgcmV0dXJuIFRlbnNvci5idWZmZXJUb1RlbnNvcihkYXRhLCB0ZW5zb3JDb25maWcpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnB1dCBkYXRhIHByb3ZpZGVkIGlzIG5vdCBzdXBwb3J0ZWQgLSBhYm9ydGVkIHRlbnNvciBjcmVhdGlvbicpO1xuICAgICAgICB9XG4gICAgfVxuICAgIHRvSW1hZ2VEYXRhKG9wdGlvbnMpIHtcbiAgICAgICAgdmFyIF9hLCBfYjtcbiAgICAgICAgY29uc3QgcGl4ZWxzMkRDb250ZXh0ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnY2FudmFzJykuZ2V0Q29udGV4dCgnMmQnKTtcbiAgICAgICAgbGV0IGltYWdlO1xuICAgICAgICBpZiAocGl4ZWxzMkRDb250ZXh0ICE9IG51bGwpIHtcbiAgICAgICAgICAgIC8vIERlZmF1bHQgdmFsdWVzIGZvciBoZWlnaHQgYW5kIHdpZHRoICYgZm9ybWF0XG4gICAgICAgICAgICBjb25zdCB3aWR0aCA9IHRoaXMuZGltc1szXTtcbiAgICAgICAgICAgIGNvbnN0IGhlaWdodCA9IHRoaXMuZGltc1syXTtcbiAgICAgICAgICAgIGNvbnN0IGNoYW5uZWxzID0gdGhpcy5kaW1zWzFdO1xuICAgICAgICAgICAgY29uc3QgaW5wdXRmb3JtYXQgPSBvcHRpb25zICE9PSB1bmRlZmluZWQgPyAob3B0aW9ucy5mb3JtYXQgIT09IHVuZGVmaW5lZCA/IG9wdGlvbnMuZm9ybWF0IDogJ1JHQicpIDogJ1JHQic7XG4gICAgICAgICAgICBjb25zdCBub3JtTWVhbiA9IG9wdGlvbnMgIT09IHVuZGVmaW5lZCA/ICgoKF9hID0gb3B0aW9ucy5ub3JtKSA9PT0gbnVsbCB8fCBfYSA9PT0gdm9pZCAwID8gdm9pZCAwIDogX2EubWVhbikgIT09IHVuZGVmaW5lZCA/IG9wdGlvbnMubm9ybS5tZWFuIDogMjU1KSA6IDI1NTtcbiAgICAgICAgICAgIGNvbnN0IG5vcm1CaWFzID0gb3B0aW9ucyAhPT0gdW5kZWZpbmVkID8gKCgoX2IgPSBvcHRpb25zLm5vcm0pID09PSBudWxsIHx8IF9iID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfYi5iaWFzKSAhPT0gdW5kZWZpbmVkID8gb3B0aW9ucy5ub3JtLmJpYXMgOiAwKSA6IDA7XG4gICAgICAgICAgICBjb25zdCBvZmZzZXQgPSBoZWlnaHQgKiB3aWR0aDtcbiAgICAgICAgICAgIGlmIChvcHRpb25zICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICBpZiAob3B0aW9ucy5oZWlnaHQgIT09IHVuZGVmaW5lZCAmJiBvcHRpb25zLmhlaWdodCAhPT0gaGVpZ2h0KSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignSW1hZ2Ugb3V0cHV0IGNvbmZpZyBoZWlnaHQgZG9lc25cXCd0IG1hdGNoIHRlbnNvciBoZWlnaHQnKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKG9wdGlvbnMud2lkdGggIT09IHVuZGVmaW5lZCAmJiBvcHRpb25zLndpZHRoICE9PSB3aWR0aCkge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ltYWdlIG91dHB1dCBjb25maWcgd2lkdGggZG9lc25cXCd0IG1hdGNoIHRlbnNvciB3aWR0aCcpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAob3B0aW9ucy5mb3JtYXQgIT09IHVuZGVmaW5lZCAmJiAoY2hhbm5lbHMgPT09IDQgJiYgb3B0aW9ucy5mb3JtYXQgIT09ICdSR0JBJykgfHxcbiAgICAgICAgICAgICAgICAgICAgKGNoYW5uZWxzID09PSAzICYmIChvcHRpb25zLmZvcm1hdCAhPT0gJ1JHQicgJiYgb3B0aW9ucy5mb3JtYXQgIT09ICdCR1InKSkpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdUZW5zb3IgZm9ybWF0IGRvZXNuXFwndCBtYXRjaCBpbnB1dCB0ZW5zb3IgZGltcycpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIERlZmF1bHQgcG9pbnRlciBhc3NpZ25tZW50c1xuICAgICAgICAgICAgY29uc3Qgc3RlcCA9IDQ7XG4gICAgICAgICAgICBsZXQgckltYWdlUG9pbnRlciA9IDAsIGdJbWFnZVBvaW50ZXIgPSAxLCBiSW1hZ2VQb2ludGVyID0gMiwgYUltYWdlUG9pbnRlciA9IDM7XG4gICAgICAgICAgICBsZXQgclRlbnNvclBvaW50ZXIgPSAwLCBnVGVuc29yUG9pbnRlciA9IG9mZnNldCwgYlRlbnNvclBvaW50ZXIgPSBvZmZzZXQgKiAyLCBhVGVuc29yUG9pbnRlciA9IC0xO1xuICAgICAgICAgICAgLy8gVXBkYXRpbmcgdGhlIHBvaW50ZXIgYXNzaWdubWVudHMgYmFzZWQgb24gdGhlIGlucHV0IGltYWdlIGZvcm1hdFxuICAgICAgICAgICAgaWYgKGlucHV0Zm9ybWF0ID09PSAnUkdCQScpIHtcbiAgICAgICAgICAgICAgICByVGVuc29yUG9pbnRlciA9IDA7XG4gICAgICAgICAgICAgICAgZ1RlbnNvclBvaW50ZXIgPSBvZmZzZXQ7XG4gICAgICAgICAgICAgICAgYlRlbnNvclBvaW50ZXIgPSBvZmZzZXQgKiAyO1xuICAgICAgICAgICAgICAgIGFUZW5zb3JQb2ludGVyID0gb2Zmc2V0ICogMztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2UgaWYgKGlucHV0Zm9ybWF0ID09PSAnUkdCJykge1xuICAgICAgICAgICAgICAgIHJUZW5zb3JQb2ludGVyID0gMDtcbiAgICAgICAgICAgICAgICBnVGVuc29yUG9pbnRlciA9IG9mZnNldDtcbiAgICAgICAgICAgICAgICBiVGVuc29yUG9pbnRlciA9IG9mZnNldCAqIDI7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIGlmIChpbnB1dGZvcm1hdCA9PT0gJ1JCRycpIHtcbiAgICAgICAgICAgICAgICByVGVuc29yUG9pbnRlciA9IDA7XG4gICAgICAgICAgICAgICAgYlRlbnNvclBvaW50ZXIgPSBvZmZzZXQ7XG4gICAgICAgICAgICAgICAgZ1RlbnNvclBvaW50ZXIgPSBvZmZzZXQgKiAyO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaW1hZ2UgPSBwaXhlbHMyRENvbnRleHQuY3JlYXRlSW1hZ2VEYXRhKHdpZHRoLCBoZWlnaHQpO1xuICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBoZWlnaHQgKiB3aWR0aDsgckltYWdlUG9pbnRlciArPSBzdGVwLCBnSW1hZ2VQb2ludGVyICs9IHN0ZXAsIGJJbWFnZVBvaW50ZXIgKz0gc3RlcCwgYUltYWdlUG9pbnRlciArPSBzdGVwLCBpKyspIHtcbiAgICAgICAgICAgICAgICBpbWFnZS5kYXRhW3JJbWFnZVBvaW50ZXJdID0gKHRoaXMuZGF0YVtyVGVuc29yUG9pbnRlcisrXSAtIG5vcm1CaWFzKSAqIG5vcm1NZWFuOyAvLyBSIHZhbHVlXG4gICAgICAgICAgICAgICAgaW1hZ2UuZGF0YVtnSW1hZ2VQb2ludGVyXSA9ICh0aGlzLmRhdGFbZ1RlbnNvclBvaW50ZXIrK10gLSBub3JtQmlhcykgKiBub3JtTWVhbjsgLy8gRyB2YWx1ZVxuICAgICAgICAgICAgICAgIGltYWdlLmRhdGFbYkltYWdlUG9pbnRlcl0gPSAodGhpcy5kYXRhW2JUZW5zb3JQb2ludGVyKytdIC0gbm9ybUJpYXMpICogbm9ybU1lYW47IC8vIEIgdmFsdWVcbiAgICAgICAgICAgICAgICBpbWFnZS5kYXRhW2FJbWFnZVBvaW50ZXJdID1cbiAgICAgICAgICAgICAgICAgICAgYVRlbnNvclBvaW50ZXIgPT09IC0xID8gMjU1IDogKHRoaXMuZGF0YVthVGVuc29yUG9pbnRlcisrXSAtIG5vcm1CaWFzKSAqIG5vcm1NZWFuOyAvLyBBIHZhbHVlXG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0NhbiBub3QgYWNjZXNzIGltYWdlIGRhdGEnKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gaW1hZ2U7XG4gICAgfVxuICAgIC8vICNlbmRyZWdpb25cbiAgICAvLyAjcmVnaW9uIHRlbnNvciB1dGlsaXRpZXNcbiAgICByZXNoYXBlKGRpbXMpIHtcbiAgICAgICAgcmV0dXJuIG5ldyBUZW5zb3IodGhpcy50eXBlLCB0aGlzLmRhdGEsIGRpbXMpO1xuICAgIH1cbn1cbi8vIyBzb3VyY2VNYXBwaW5nVVJMPXRlbnNvci1pbXBsLmpzLm1hcCIsIi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxuaW1wb3J0IHsgVGVuc29yIGFzIFRlbnNvckltcGwgfSBmcm9tICcuL3RlbnNvci1pbXBsJztcbi8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbmFtaW5nLWNvbnZlbnRpb25cbmV4cG9ydCBjb25zdCBUZW5zb3IgPSBUZW5zb3JJbXBsO1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9dGVuc29yLmpzLm1hcCIsIlxyXG52YXIgb3J0V2FzbVRocmVhZGVkID0gKCgpID0+IHtcclxuICB2YXIgX3NjcmlwdERpciA9IHR5cGVvZiBkb2N1bWVudCAhPT0gJ3VuZGVmaW5lZCcgJiYgZG9jdW1lbnQuY3VycmVudFNjcmlwdCA/IGRvY3VtZW50LmN1cnJlbnRTY3JpcHQuc3JjIDogdW5kZWZpbmVkO1xyXG4gIGlmICh0eXBlb2YgX19maWxlbmFtZSAhPT0gJ3VuZGVmaW5lZCcpIF9zY3JpcHREaXIgPSBfc2NyaXB0RGlyIHx8IF9fZmlsZW5hbWU7XHJcbiAgcmV0dXJuIChcclxuZnVuY3Rpb24ob3J0V2FzbVRocmVhZGVkKSB7XHJcbiAgb3J0V2FzbVRocmVhZGVkID0gb3J0V2FzbVRocmVhZGVkIHx8IHt9O1xyXG5cclxuXHJcbmZ1bmN0aW9uIGQoKXttLmJ1ZmZlciE9biYmcChtLmJ1ZmZlcik7cmV0dXJuIGFhfWZ1bmN0aW9uIHEoKXttLmJ1ZmZlciE9biYmcChtLmJ1ZmZlcik7cmV0dXJuIGJhfWZ1bmN0aW9uIHIoKXttLmJ1ZmZlciE9biYmcChtLmJ1ZmZlcik7cmV0dXJuIGNhfWZ1bmN0aW9uIHYoKXttLmJ1ZmZlciE9biYmcChtLmJ1ZmZlcik7cmV0dXJuIGRhfWZ1bmN0aW9uIGVhKCl7bS5idWZmZXIhPW4mJnAobS5idWZmZXIpO3JldHVybiBmYX12YXIgeDt4fHwoeD10eXBlb2Ygb3J0V2FzbVRocmVhZGVkICE9PSAndW5kZWZpbmVkJyA/IG9ydFdhc21UaHJlYWRlZCA6IHt9KTt2YXIgaGEsaWE7eC5yZWFkeT1uZXcgUHJvbWlzZShmdW5jdGlvbihhLGIpe2hhPWE7aWE9Yn0pO1xyXG52YXIgamE9T2JqZWN0LmFzc2lnbih7fSx4KSxrYT1cIi4vdGhpcy5wcm9ncmFtXCIsbGE9KGEsYik9Pnt0aHJvdyBiO30sbWE9XCJvYmplY3RcIj09dHlwZW9mIHdpbmRvdyx5PVwiZnVuY3Rpb25cIj09dHlwZW9mIGltcG9ydFNjcmlwdHMsQj1cIm9iamVjdFwiPT10eXBlb2YgcHJvY2VzcyYmXCJvYmplY3RcIj09dHlwZW9mIHByb2Nlc3MudmVyc2lvbnMmJlwic3RyaW5nXCI9PXR5cGVvZiBwcm9jZXNzLnZlcnNpb25zLm5vZGUsQz14LkVOVklST05NRU5UX0lTX1BUSFJFQUR8fCExLEQ9XCJcIjtmdW5jdGlvbiBuYShhKXtyZXR1cm4geC5sb2NhdGVGaWxlP3gubG9jYXRlRmlsZShhLEQpOkQrYX12YXIgb2EscGEscWEsZnMscmEsc2E7XHJcbmlmKEIpe0Q9eT9yZXF1aXJlKFwicGF0aFwiKS5kaXJuYW1lKEQpK1wiL1wiOl9fZGlybmFtZStcIi9cIjtzYT0oKT0+e3JhfHwoZnM9cmVxdWlyZShcImZzXCIpLHJhPXJlcXVpcmUoXCJwYXRoXCIpKX07b2E9ZnVuY3Rpb24oYixjKXtzYSgpO2I9cmEubm9ybWFsaXplKGIpO3JldHVybiBmcy5yZWFkRmlsZVN5bmMoYixjP3ZvaWQgMDpcInV0ZjhcIil9O3FhPWI9PntiPW9hKGIsITApO2IuYnVmZmVyfHwoYj1uZXcgVWludDhBcnJheShiKSk7cmV0dXJuIGJ9O3BhPShiLGMsZSk9PntzYSgpO2I9cmEubm9ybWFsaXplKGIpO2ZzLnJlYWRGaWxlKGIsZnVuY3Rpb24oZixoKXtmP2UoZik6YyhoLmJ1ZmZlcil9KX07MTxwcm9jZXNzLmFyZ3YubGVuZ3RoJiYoa2E9cHJvY2Vzcy5hcmd2WzFdLnJlcGxhY2UoL1xcXFwvZyxcIi9cIikpO3Byb2Nlc3MuYXJndi5zbGljZSgyKTtwcm9jZXNzLm9uKFwidW5jYXVnaHRFeGNlcHRpb25cIixmdW5jdGlvbihiKXtpZighKGIgaW5zdGFuY2VvZiBFKSl0aHJvdyBiO30pO3Byb2Nlc3Mub24oXCJ1bmhhbmRsZWRSZWplY3Rpb25cIixcclxuZnVuY3Rpb24oYil7dGhyb3cgYjt9KTtsYT0oYixjKT0+e2lmKEYoKSl0aHJvdyBwcm9jZXNzLmV4aXRDb2RlPWIsYztjIGluc3RhbmNlb2YgRXx8RyhcImV4aXRpbmcgZHVlIHRvIGV4Y2VwdGlvbjogXCIrYyk7cHJvY2Vzcy5leGl0KGIpfTt4Lmluc3BlY3Q9ZnVuY3Rpb24oKXtyZXR1cm5cIltFbXNjcmlwdGVuIE1vZHVsZSBvYmplY3RdXCJ9O2xldCBhO3RyeXthPXJlcXVpcmUoXCJ3b3JrZXJfdGhyZWFkc1wiKX1jYXRjaChiKXt0aHJvdyBjb25zb2xlLmVycm9yKCdUaGUgXCJ3b3JrZXJfdGhyZWFkc1wiIG1vZHVsZSBpcyBub3Qgc3VwcG9ydGVkIGluIHRoaXMgbm9kZS5qcyBidWlsZCAtIHBlcmhhcHMgYSBuZXdlciB2ZXJzaW9uIGlzIG5lZWRlZD8nKSxiO31nbG9iYWwuV29ya2VyPWEuV29ya2VyfWVsc2UgaWYobWF8fHkpeT9EPXNlbGYubG9jYXRpb24uaHJlZjpcInVuZGVmaW5lZFwiIT10eXBlb2YgZG9jdW1lbnQmJmRvY3VtZW50LmN1cnJlbnRTY3JpcHQmJihEPWRvY3VtZW50LmN1cnJlbnRTY3JpcHQuc3JjKSxcclxuX3NjcmlwdERpciYmKEQ9X3NjcmlwdERpciksMCE9PUQuaW5kZXhPZihcImJsb2I6XCIpP0Q9RC5zdWJzdHIoMCxELnJlcGxhY2UoL1s/I10uKi8sXCJcIikubGFzdEluZGV4T2YoXCIvXCIpKzEpOkQ9XCJcIixCfHwob2E9YT0+e3ZhciBiPW5ldyBYTUxIdHRwUmVxdWVzdDtiLm9wZW4oXCJHRVRcIixhLCExKTtiLnNlbmQobnVsbCk7cmV0dXJuIGIucmVzcG9uc2VUZXh0fSx5JiYocWE9YT0+e3ZhciBiPW5ldyBYTUxIdHRwUmVxdWVzdDtiLm9wZW4oXCJHRVRcIixhLCExKTtiLnJlc3BvbnNlVHlwZT1cImFycmF5YnVmZmVyXCI7Yi5zZW5kKG51bGwpO3JldHVybiBuZXcgVWludDhBcnJheShiLnJlc3BvbnNlKX0pLHBhPShhLGIsYyk9Pnt2YXIgZT1uZXcgWE1MSHR0cFJlcXVlc3Q7ZS5vcGVuKFwiR0VUXCIsYSwhMCk7ZS5yZXNwb25zZVR5cGU9XCJhcnJheWJ1ZmZlclwiO2Uub25sb2FkPSgpPT57MjAwPT1lLnN0YXR1c3x8MD09ZS5zdGF0dXMmJmUucmVzcG9uc2U/YihlLnJlc3BvbnNlKTpjKCl9O2Uub25lcnJvcj1cclxuYztlLnNlbmQobnVsbCl9KTtCJiZcInVuZGVmaW5lZFwiPT10eXBlb2YgcGVyZm9ybWFuY2UmJihnbG9iYWwucGVyZm9ybWFuY2U9cmVxdWlyZShcInBlcmZfaG9va3NcIikucGVyZm9ybWFuY2UpO3ZhciB0YT1jb25zb2xlLmxvZy5iaW5kKGNvbnNvbGUpLHVhPWNvbnNvbGUud2Fybi5iaW5kKGNvbnNvbGUpO0ImJihzYSgpLHRhPWE9PmZzLndyaXRlU3luYygxLGErXCJcXG5cIiksdWE9YT0+ZnMud3JpdGVTeW5jKDIsYStcIlxcblwiKSk7dmFyIHZhPXgucHJpbnR8fHRhLEc9eC5wcmludEVycnx8dWE7T2JqZWN0LmFzc2lnbih4LGphKTtqYT1udWxsO3gudGhpc1Byb2dyYW0mJihrYT14LnRoaXNQcm9ncmFtKTt4LnF1aXQmJihsYT14LnF1aXQpO3ZhciBIO3gud2FzbUJpbmFyeSYmKEg9eC53YXNtQmluYXJ5KTt2YXIgbm9FeGl0UnVudGltZT14Lm5vRXhpdFJ1bnRpbWV8fCExO1wib2JqZWN0XCIhPXR5cGVvZiBXZWJBc3NlbWJseSYmSShcIm5vIG5hdGl2ZSB3YXNtIHN1cHBvcnQgZGV0ZWN0ZWRcIik7XHJcbnZhciBtLHdhLHhhPSExLHlhPVwidW5kZWZpbmVkXCIhPXR5cGVvZiBUZXh0RGVjb2Rlcj9uZXcgVGV4dERlY29kZXIoXCJ1dGY4XCIpOnZvaWQgMDtcclxuZnVuY3Rpb24gemEoYSxiLGMpe2I+Pj49MDt2YXIgZT1iK2M7Zm9yKGM9YjthW2NdJiYhKGM+PWUpOykrK2M7aWYoMTY8Yy1iJiZhLmJ1ZmZlciYmeWEpcmV0dXJuIHlhLmRlY29kZShhLmJ1ZmZlciBpbnN0YW5jZW9mIFNoYXJlZEFycmF5QnVmZmVyP2Euc2xpY2UoYixjKTphLnN1YmFycmF5KGIsYykpO2ZvcihlPVwiXCI7YjxjOyl7dmFyIGY9YVtiKytdO2lmKGYmMTI4KXt2YXIgaD1hW2IrK10mNjM7aWYoMTkyPT0oZiYyMjQpKWUrPVN0cmluZy5mcm9tQ2hhckNvZGUoKGYmMzEpPDw2fGgpO2Vsc2V7dmFyIGs9YVtiKytdJjYzO2Y9MjI0PT0oZiYyNDApPyhmJjE1KTw8MTJ8aDw8NnxrOihmJjcpPDwxOHxoPDwxMnxrPDw2fGFbYisrXSY2Mzs2NTUzNj5mP2UrPVN0cmluZy5mcm9tQ2hhckNvZGUoZik6KGYtPTY1NTM2LGUrPVN0cmluZy5mcm9tQ2hhckNvZGUoNTUyOTZ8Zj4+MTAsNTYzMjB8ZiYxMDIzKSl9fWVsc2UgZSs9U3RyaW5nLmZyb21DaGFyQ29kZShmKX1yZXR1cm4gZX1cclxuZnVuY3Rpb24gQWEoYSxiKXtyZXR1cm4oYT4+Pj0wKT96YShxKCksYSxiKTpcIlwifVxyXG5mdW5jdGlvbiBCYShhLGIsYyxlKXtjPj4+PTA7aWYoISgwPGUpKXJldHVybiAwO3ZhciBmPWM7ZT1jK2UtMTtmb3IodmFyIGg9MDtoPGEubGVuZ3RoOysraCl7dmFyIGs9YS5jaGFyQ29kZUF0KGgpO2lmKDU1Mjk2PD1rJiY1NzM0Mz49ayl7dmFyIGw9YS5jaGFyQ29kZUF0KCsraCk7az02NTUzNisoKGsmMTAyMyk8PDEwKXxsJjEwMjN9aWYoMTI3Pj1rKXtpZihjPj1lKWJyZWFrO2JbYysrPj4+MF09a31lbHNle2lmKDIwNDc+PWspe2lmKGMrMT49ZSlicmVhaztiW2MrKz4+PjBdPTE5MnxrPj42fWVsc2V7aWYoNjU1MzU+PWspe2lmKGMrMj49ZSlicmVhaztiW2MrKz4+PjBdPTIyNHxrPj4xMn1lbHNle2lmKGMrMz49ZSlicmVhaztiW2MrKz4+PjBdPTI0MHxrPj4xODtiW2MrKz4+PjBdPTEyOHxrPj4xMiY2M31iW2MrKz4+PjBdPTEyOHxrPj42JjYzfWJbYysrPj4+MF09MTI4fGsmNjN9fWJbYz4+PjBdPTA7cmV0dXJuIGMtZn1cclxuZnVuY3Rpb24gQ2EoYSl7Zm9yKHZhciBiPTAsYz0wO2M8YS5sZW5ndGg7KytjKXt2YXIgZT1hLmNoYXJDb2RlQXQoYyk7MTI3Pj1lP2IrKzoyMDQ3Pj1lP2IrPTI6NTUyOTY8PWUmJjU3MzQzPj1lPyhiKz00LCsrYyk6Yis9M31yZXR1cm4gYn12YXIgbixhYSxiYSxjYSxkYSxmYTtDJiYobj14LmJ1ZmZlcik7ZnVuY3Rpb24gcChhKXtuPWE7eC5IRUFQOD1hYT1uZXcgSW50OEFycmF5KGEpO3guSEVBUDE2PW5ldyBJbnQxNkFycmF5KGEpO3guSEVBUDMyPWNhPW5ldyBJbnQzMkFycmF5KGEpO3guSEVBUFU4PWJhPW5ldyBVaW50OEFycmF5KGEpO3guSEVBUFUxNj1uZXcgVWludDE2QXJyYXkoYSk7eC5IRUFQVTMyPWRhPW5ldyBVaW50MzJBcnJheShhKTt4LkhFQVBGMzI9bmV3IEZsb2F0MzJBcnJheShhKTt4LkhFQVBGNjQ9ZmE9bmV3IEZsb2F0NjRBcnJheShhKX12YXIgRGE9eC5JTklUSUFMX01FTU9SWXx8MTY3NzcyMTY7XHJcbmlmKEMpbT14Lndhc21NZW1vcnksbj14LmJ1ZmZlcjtlbHNlIGlmKHgud2FzbU1lbW9yeSltPXgud2FzbU1lbW9yeTtlbHNlIGlmKG09bmV3IFdlYkFzc2VtYmx5Lk1lbW9yeSh7aW5pdGlhbDpEYS82NTUzNixtYXhpbXVtOjY1NTM2LHNoYXJlZDohMH0pLCEobS5idWZmZXIgaW5zdGFuY2VvZiBTaGFyZWRBcnJheUJ1ZmZlcikpdGhyb3cgRyhcInJlcXVlc3RlZCBhIHNoYXJlZCBXZWJBc3NlbWJseS5NZW1vcnkgYnV0IHRoZSByZXR1cm5lZCBidWZmZXIgaXMgbm90IGEgU2hhcmVkQXJyYXlCdWZmZXIsIGluZGljYXRpbmcgdGhhdCB3aGlsZSB0aGUgYnJvd3NlciBoYXMgU2hhcmVkQXJyYXlCdWZmZXIgaXQgZG9lcyBub3QgaGF2ZSBXZWJBc3NlbWJseSB0aHJlYWRzIHN1cHBvcnQgLSB5b3UgbWF5IG5lZWQgdG8gc2V0IGEgZmxhZ1wiKSxCJiZjb25zb2xlLmxvZyhcIihvbiBub2RlIHlvdSBtYXkgbmVlZDogLS1leHBlcmltZW50YWwtd2FzbS10aHJlYWRzIC0tZXhwZXJpbWVudGFsLXdhc20tYnVsay1tZW1vcnkgYW5kIGFsc28gdXNlIGEgcmVjZW50IHZlcnNpb24pXCIpLFxyXG5FcnJvcihcImJhZCBtZW1vcnlcIik7bSYmKG49bS5idWZmZXIpO0RhPW4uYnl0ZUxlbmd0aDtwKG4pO3ZhciBFYSxGYT1bXSxHYT1bXSxIYT1bXSxJYT1bXSxKYT0wO2Z1bmN0aW9uIEYoKXtyZXR1cm4gbm9FeGl0UnVudGltZXx8MDxKYX1mdW5jdGlvbiBLYSgpe3ZhciBhPXgucHJlUnVuLnNoaWZ0KCk7RmEudW5zaGlmdChhKX12YXIgTD0wLExhPW51bGwsTT1udWxsO2Z1bmN0aW9uIEkoYSl7aWYoQylwb3N0TWVzc2FnZSh7Y21kOlwib25BYm9ydFwiLGFyZzphfSk7ZWxzZSBpZih4Lm9uQWJvcnQpeC5vbkFib3J0KGEpO2E9XCJBYm9ydGVkKFwiK2ErXCIpXCI7RyhhKTt4YT0hMDthPW5ldyBXZWJBc3NlbWJseS5SdW50aW1lRXJyb3IoYStcIi4gQnVpbGQgd2l0aCAtc0FTU0VSVElPTlMgZm9yIG1vcmUgaW5mby5cIik7aWEoYSk7dGhyb3cgYTt9ZnVuY3Rpb24gTWEoKXtyZXR1cm4gTy5zdGFydHNXaXRoKFwiZGF0YTphcHBsaWNhdGlvbi9vY3RldC1zdHJlYW07YmFzZTY0LFwiKX12YXIgTztPPVwib3J0LXdhc20tdGhyZWFkZWQud2FzbVwiO1xyXG5NYSgpfHwoTz1uYShPKSk7ZnVuY3Rpb24gTmEoKXt2YXIgYT1PO3RyeXtpZihhPT1PJiZIKXJldHVybiBuZXcgVWludDhBcnJheShIKTtpZihxYSlyZXR1cm4gcWEoYSk7dGhyb3dcImJvdGggYXN5bmMgYW5kIHN5bmMgZmV0Y2hpbmcgb2YgdGhlIHdhc20gZmFpbGVkXCI7fWNhdGNoKGIpe0koYil9fVxyXG5mdW5jdGlvbiBPYSgpe2lmKCFIJiYobWF8fHkpKXtpZihcImZ1bmN0aW9uXCI9PXR5cGVvZiBmZXRjaCYmIU8uc3RhcnRzV2l0aChcImZpbGU6Ly9cIikpcmV0dXJuIGZldGNoKE8se2NyZWRlbnRpYWxzOlwic2FtZS1vcmlnaW5cIn0pLnRoZW4oZnVuY3Rpb24oYSl7aWYoIWEub2spdGhyb3dcImZhaWxlZCB0byBsb2FkIHdhc20gYmluYXJ5IGZpbGUgYXQgJ1wiK08rXCInXCI7cmV0dXJuIGEuYXJyYXlCdWZmZXIoKX0pLmNhdGNoKGZ1bmN0aW9uKCl7cmV0dXJuIE5hKCl9KTtpZihwYSlyZXR1cm4gbmV3IFByb21pc2UoZnVuY3Rpb24oYSxiKXtwYShPLGZ1bmN0aW9uKGMpe2EobmV3IFVpbnQ4QXJyYXkoYykpfSxiKX0pfXJldHVybiBQcm9taXNlLnJlc29sdmUoKS50aGVuKGZ1bmN0aW9uKCl7cmV0dXJuIE5hKCl9KX12YXIgUGE9e307XHJcbmZ1bmN0aW9uIEUoYSl7dGhpcy5uYW1lPVwiRXhpdFN0YXR1c1wiO3RoaXMubWVzc2FnZT1cIlByb2dyYW0gdGVybWluYXRlZCB3aXRoIGV4aXQoXCIrYStcIilcIjt0aGlzLnN0YXR1cz1hfWZ1bmN0aW9uIFFhKGEpeyhhPVAuVmJbYV0pfHxJKCk7UC5tYyhhKX1mdW5jdGlvbiBSYShhKXt2YXIgYj1QLkNjKCk7aWYoIWIpcmV0dXJuIDY7UC5hYy5wdXNoKGIpO1AuVmJbYS5VYl09YjtiLlViPWEuVWI7dmFyIGM9e2NtZDpcInJ1blwiLHN0YXJ0X3JvdXRpbmU6YS5JYyxhcmc6YS56YyxwdGhyZWFkX3B0cjphLlVifTtiLiRiPSgpPT57Yy50aW1lPXBlcmZvcm1hbmNlLm5vdygpO2IucG9zdE1lc3NhZ2UoYyxhLk5jKX07Yi5sb2FkZWQmJihiLiRiKCksZGVsZXRlIGIuJGIpO3JldHVybiAwfWZ1bmN0aW9uIFNhKGEpe2lmKEMpcmV0dXJuIFEoMSwxLGEpO2lmKCFGKCkpe1Aub2MoKTtpZih4Lm9uRXhpdCl4Lm9uRXhpdChhKTt4YT0hMH1sYShhLG5ldyBFKGEpKX1cclxuZnVuY3Rpb24gVGEoYSxiKXtpZighYiYmQyl0aHJvdyBVYShhKSxcInVud2luZFwiO0YoKXx8Q3x8KFZhKCksUihIYSksV2EoMCksWGFbMV0ubGVuZ3RoJiZZYSgxLDEwKSxYYVsyXS5sZW5ndGgmJllhKDIsMTApLFAub2MoKSk7U2EoYSl9XHJcbnZhciBQPXtZYjpbXSxhYzpbXSxxYzpbXSxWYjp7fSxmYzpmdW5jdGlvbigpe0MmJlAuRWMoKX0sUGM6ZnVuY3Rpb24oKXt9LEVjOmZ1bmN0aW9uKCl7UC5yZWNlaXZlT2JqZWN0VHJhbnNmZXI9UC5HYztQLnRocmVhZEluaXRUTFM9UC5wYztQLnNldEV4aXRTdGF0dXM9UC5uYztub0V4aXRSdW50aW1lPSExfSxuYzpmdW5jdGlvbigpe30sb2M6ZnVuY3Rpb24oKXtmb3IodmFyIGEgb2YgT2JqZWN0LnZhbHVlcyhQLlZiKSlQLm1jKGEpO2ZvcihhIG9mIFAuWWIpYS50ZXJtaW5hdGUoKTtQLlliPVtdfSxtYzpmdW5jdGlvbihhKXt2YXIgYj1hLlViO2RlbGV0ZSBQLlZiW2JdO1AuWWIucHVzaChhKTtQLmFjLnNwbGljZShQLmFjLmluZGV4T2YoYSksMSk7YS5VYj0wO1phKGIpfSxHYzpmdW5jdGlvbigpe30scGM6ZnVuY3Rpb24oKXtQLnFjLmZvckVhY2goYT0+YSgpKX0sRmM6ZnVuY3Rpb24oYSxiKXthLm9ubWVzc2FnZT1jPT57Yz1jLmRhdGE7dmFyIGU9Yy5jbWQ7YS5VYiYmKFAuQmM9YS5VYik7XHJcbmlmKGMudGFyZ2V0VGhyZWFkJiZjLnRhcmdldFRocmVhZCE9JGEoKSl7dmFyIGY9UC5WYltjLlFjXTtmP2YucG9zdE1lc3NhZ2UoYyxjLnRyYW5zZmVyTGlzdCk6RygnSW50ZXJuYWwgZXJyb3IhIFdvcmtlciBzZW50IGEgbWVzc2FnZSBcIicrZSsnXCIgdG8gdGFyZ2V0IHB0aHJlYWQgJytjLnRhcmdldFRocmVhZCtcIiwgYnV0IHRoYXQgdGhyZWFkIG5vIGxvbmdlciBleGlzdHMhXCIpfWVsc2UgaWYoXCJwcm9jZXNzUHJveHlpbmdRdWV1ZVwiPT09ZSlhYihjLnF1ZXVlKTtlbHNlIGlmKFwic3Bhd25UaHJlYWRcIj09PWUpUmEoYyk7ZWxzZSBpZihcImNsZWFudXBUaHJlYWRcIj09PWUpUWEoYy50aHJlYWQpO2Vsc2UgaWYoXCJraWxsVGhyZWFkXCI9PT1lKWM9Yy50aHJlYWQsZT1QLlZiW2NdLGRlbGV0ZSBQLlZiW2NdLGUudGVybWluYXRlKCksWmEoYyksUC5hYy5zcGxpY2UoUC5hYy5pbmRleE9mKGUpLDEpLGUuVWI9MDtlbHNlIGlmKFwiY2FuY2VsVGhyZWFkXCI9PT1lKVAuVmJbYy50aHJlYWRdLnBvc3RNZXNzYWdlKHtjbWQ6XCJjYW5jZWxcIn0pO1xyXG5lbHNlIGlmKFwibG9hZGVkXCI9PT1lKWEubG9hZGVkPSEwLGImJmIoYSksYS4kYiYmKGEuJGIoKSxkZWxldGUgYS4kYik7ZWxzZSBpZihcInByaW50XCI9PT1lKXZhKFwiVGhyZWFkIFwiK2MudGhyZWFkSWQrXCI6IFwiK2MudGV4dCk7ZWxzZSBpZihcInByaW50RXJyXCI9PT1lKUcoXCJUaHJlYWQgXCIrYy50aHJlYWRJZCtcIjogXCIrYy50ZXh0KTtlbHNlIGlmKFwiYWxlcnRcIj09PWUpYWxlcnQoXCJUaHJlYWQgXCIrYy50aHJlYWRJZCtcIjogXCIrYy50ZXh0KTtlbHNlIGlmKFwic2V0aW1tZWRpYXRlXCI9PT1jLnRhcmdldClhLnBvc3RNZXNzYWdlKGMpO2Vsc2UgaWYoXCJvbkFib3J0XCI9PT1lKXtpZih4Lm9uQWJvcnQpeC5vbkFib3J0KGMuYXJnKX1lbHNlIGUmJkcoXCJ3b3JrZXIgc2VudCBhbiB1bmtub3duIGNvbW1hbmQgXCIrZSk7UC5CYz12b2lkIDB9O2Eub25lcnJvcj1jPT57RyhcIndvcmtlciBzZW50IGFuIGVycm9yISBcIitjLmZpbGVuYW1lK1wiOlwiK2MubGluZW5vK1wiOiBcIitjLm1lc3NhZ2UpO3Rocm93IGM7fTtCJiZcclxuKGEub24oXCJtZXNzYWdlXCIsZnVuY3Rpb24oYyl7YS5vbm1lc3NhZ2Uoe2RhdGE6Y30pfSksYS5vbihcImVycm9yXCIsZnVuY3Rpb24oYyl7YS5vbmVycm9yKGMpfSksYS5vbihcImRldGFjaGVkRXhpdFwiLGZ1bmN0aW9uKCl7fSkpO2EucG9zdE1lc3NhZ2Uoe2NtZDpcImxvYWRcIix1cmxPckJsb2I6eC5tYWluU2NyaXB0VXJsT3JCbG9ifHxfc2NyaXB0RGlyLHdhc21NZW1vcnk6bSx3YXNtTW9kdWxlOndhfSl9LHljOmZ1bmN0aW9uKCl7dmFyIGE9bmEoXCJvcnQtd2FzbS10aHJlYWRlZC53b3JrZXIuanNcIik7UC5ZYi5wdXNoKG5ldyBXb3JrZXIoYSkpfSxDYzpmdW5jdGlvbigpezA9PVAuWWIubGVuZ3RoJiYoUC55YygpLFAuRmMoUC5ZYlswXSkpO3JldHVybiBQLlliLnBvcCgpfX07eC5QVGhyZWFkPVA7ZnVuY3Rpb24gUihhKXtmb3IoOzA8YS5sZW5ndGg7KWEuc2hpZnQoKSh4KX1mdW5jdGlvbiBiYihhKXt2YXIgYj1TKCk7YT1hKCk7VShiKTtyZXR1cm4gYX1cclxueC5lc3RhYmxpc2hTdGFja1NwYWNlPWZ1bmN0aW9uKCl7dmFyIGE9JGEoKSxiPXIoKVthKzQ0Pj4yPj4+MF07YT1yKClbYSs0OD4+Mj4+PjBdO2NiKGIsYi1hKTtVKGIpfTtmdW5jdGlvbiBVYShhKXtpZihDKXJldHVybiBRKDIsMCxhKTt0cnl7VGEoYSl9Y2F0Y2goYil7YiBpbnN0YW5jZW9mIEV8fFwidW53aW5kXCI9PWJ8fGxhKDEsYil9fXZhciBkYj1bXTtmdW5jdGlvbiBWKGEpe3ZhciBiPWRiW2FdO2J8fChhPj1kYi5sZW5ndGgmJihkYi5sZW5ndGg9YSsxKSxkYlthXT1iPUVhLmdldChhKSk7cmV0dXJuIGJ9eC5pbnZva2VFbnRyeVBvaW50PWZ1bmN0aW9uKGEsYil7YT1WKGEpKGIpO0YoKT9QLm5jKGEpOmViKGEpfTtmdW5jdGlvbiBmYihhLGIpe2QoKS5zZXQoYSxiPj4+MCl9dmFyIGdiPVtdLGhiPTAsVz0wO1xyXG5mdW5jdGlvbiBYKGEpe3RoaXMuWmI9YTt0aGlzLlNiPWEtMjQ7dGhpcy54Yz1mdW5jdGlvbihiKXt2KClbdGhpcy5TYis0Pj4yPj4+MF09Yn07dGhpcy5iYz1mdW5jdGlvbigpe3JldHVybiB2KClbdGhpcy5TYis0Pj4yPj4+MF19O3RoaXMud2M9ZnVuY3Rpb24oYil7digpW3RoaXMuU2IrOD4+Mj4+PjBdPWJ9O3RoaXMuRGM9ZnVuY3Rpb24oKXtyZXR1cm4gdigpW3RoaXMuU2IrOD4+Mj4+PjBdfTt0aGlzLnJjPWZ1bmN0aW9uKCl7cigpW3RoaXMuU2I+PjI+Pj4wXT0wfTt0aGlzLmhjPWZ1bmN0aW9uKGIpe2I9Yj8xOjA7ZCgpW3RoaXMuU2IrMTI+PjA+Pj4wXT1ifTt0aGlzLnVjPWZ1bmN0aW9uKCl7cmV0dXJuIDAhPWQoKVt0aGlzLlNiKzEyPj4wPj4+MF19O3RoaXMuaWM9ZnVuY3Rpb24oYil7Yj1iPzE6MDtkKClbdGhpcy5TYisxMz4+MD4+PjBdPWJ9O3RoaXMua2M9ZnVuY3Rpb24oKXtyZXR1cm4gMCE9ZCgpW3RoaXMuU2IrMTM+PjA+Pj4wXX07dGhpcy5mYz1mdW5jdGlvbihiLGMpe3RoaXMuY2MoMCk7XHJcbnRoaXMueGMoYik7dGhpcy53YyhjKTt0aGlzLnJjKCk7dGhpcy5oYyghMSk7dGhpcy5pYyghMSl9O3RoaXMuc2M9ZnVuY3Rpb24oKXtBdG9taWNzLmFkZChyKCksdGhpcy5TYj4+MiwxKX07dGhpcy5IYz1mdW5jdGlvbigpe3JldHVybiAxPT09QXRvbWljcy5zdWIocigpLHRoaXMuU2I+PjIsMSl9O3RoaXMuY2M9ZnVuY3Rpb24oYil7digpW3RoaXMuU2IrMTY+PjI+Pj4wXT1ifTt0aGlzLnRjPWZ1bmN0aW9uKCl7cmV0dXJuIHYoKVt0aGlzLlNiKzE2Pj4yPj4+MF19O3RoaXMudmM9ZnVuY3Rpb24oKXtpZihpYih0aGlzLmJjKCkpKXJldHVybiB2KClbdGhpcy5aYj4+Mj4+PjBdO3ZhciBiPXRoaXMudGMoKTtyZXR1cm4gMCE9PWI/Yjp0aGlzLlpifX1mdW5jdGlvbiBqYihhKXtyZXR1cm4ga2IoKG5ldyBYKGEpKS5TYil9ZnVuY3Rpb24gbGIoYSxiLGMsZSl7cmV0dXJuIEM/USgzLDEsYSxiLGMsZSk6bWIoYSxiLGMsZSl9XHJcbmZ1bmN0aW9uIG1iKGEsYixjLGUpe2lmKFwidW5kZWZpbmVkXCI9PXR5cGVvZiBTaGFyZWRBcnJheUJ1ZmZlcilyZXR1cm4gRyhcIkN1cnJlbnQgZW52aXJvbm1lbnQgZG9lcyBub3Qgc3VwcG9ydCBTaGFyZWRBcnJheUJ1ZmZlciwgcHRocmVhZHMgYXJlIG5vdCBhdmFpbGFibGUhXCIpLDY7dmFyIGY9W107aWYoQyYmMD09PWYubGVuZ3RoKXJldHVybiBsYihhLGIsYyxlKTthPXtJYzpjLFViOmEsemM6ZSxOYzpmfTtyZXR1cm4gQz8oYS5PYz1cInNwYXduVGhyZWFkXCIscG9zdE1lc3NhZ2UoYSxmKSwwKTpSYShhKX1mdW5jdGlvbiBuYihhLGIsYyl7cmV0dXJuIEM/USg0LDEsYSxiLGMpOjB9ZnVuY3Rpb24gb2IoYSxiKXtpZihDKXJldHVybiBRKDUsMSxhLGIpfWZ1bmN0aW9uIHBiKGEsYil7aWYoQylyZXR1cm4gUSg2LDEsYSxiKX1mdW5jdGlvbiBxYihhLGIsYyl7aWYoQylyZXR1cm4gUSg3LDEsYSxiLGMpfWZ1bmN0aW9uIHJiKGEsYixjKXtyZXR1cm4gQz9RKDgsMSxhLGIsYyk6MH1cclxuZnVuY3Rpb24gc2IoYSxiKXtpZihDKXJldHVybiBRKDksMSxhLGIpfWZ1bmN0aW9uIHRiKGEsYixjKXtpZihDKXJldHVybiBRKDEwLDEsYSxiLGMpfWZ1bmN0aW9uIHViKGEsYixjLGUpe2lmKEMpcmV0dXJuIFEoMTEsMSxhLGIsYyxlKX1mdW5jdGlvbiB2YihhLGIsYyxlKXtpZihDKXJldHVybiBRKDEyLDEsYSxiLGMsZSl9ZnVuY3Rpb24gd2IoYSxiLGMsZSl7aWYoQylyZXR1cm4gUSgxMywxLGEsYixjLGUpfWZ1bmN0aW9uIHhiKGEpe2lmKEMpcmV0dXJuIFEoMTQsMSxhKX1mdW5jdGlvbiB5YihhLGIpe2lmKEMpcmV0dXJuIFEoMTUsMSxhLGIpfWZ1bmN0aW9uIHpiKGEsYixjKXtpZihDKXJldHVybiBRKDE2LDEsYSxiLGMpfWZ1bmN0aW9uIGFiKGEpe0F0b21pY3Muc3RvcmUocigpLGE+PjIsMSk7JGEoKSYmQWIoYSk7QXRvbWljcy5jb21wYXJlRXhjaGFuZ2UocigpLGE+PjIsMSwwKX14LmV4ZWN1dGVOb3RpZmllZFByb3h5aW5nUXVldWU9YWI7XHJcbmZ1bmN0aW9uIEJiKGEpe3JldHVybiB2KClbYT4+PjJdKzQyOTQ5NjcyOTYqcigpW2ErND4+PjJdfWZ1bmN0aW9uIENiKGEsYixjLGUsZixoKXtyZXR1cm4gQz9RKDE3LDEsYSxiLGMsZSxmLGgpOi01Mn1mdW5jdGlvbiBEYihhLGIsYyxlLGYsaCl7aWYoQylyZXR1cm4gUSgxOCwxLGEsYixjLGUsZixoKX1mdW5jdGlvbiBFYihhKXt2YXIgYj1DYShhKSsxLGM9RmIoYik7YyYmQmEoYSxkKCksYyxiKTtyZXR1cm4gY31cclxuZnVuY3Rpb24gR2IoYSxiLGMpe2Z1bmN0aW9uIGUodCl7cmV0dXJuKHQ9dC50b1RpbWVTdHJpbmcoKS5tYXRjaCgvXFwoKFtBLVphLXogXSspXFwpJC8pKT90WzFdOlwiR01UXCJ9aWYoQylyZXR1cm4gUSgxOSwxLGEsYixjKTt2YXIgZj0obmV3IERhdGUpLmdldEZ1bGxZZWFyKCksaD1uZXcgRGF0ZShmLDAsMSksaz1uZXcgRGF0ZShmLDYsMSk7Zj1oLmdldFRpbWV6b25lT2Zmc2V0KCk7dmFyIGw9ay5nZXRUaW1lem9uZU9mZnNldCgpLHU9TWF0aC5tYXgoZixsKTtyKClbYT4+Mj4+PjBdPTYwKnU7cigpW2I+PjI+Pj4wXT1OdW1iZXIoZiE9bCk7YT1lKGgpO2I9ZShrKTthPUViKGEpO2I9RWIoYik7bDxmPyh2KClbYz4+Mj4+PjBdPWEsdigpW2MrND4+Mj4+PjBdPWIpOih2KClbYz4+Mj4+PjBdPWIsdigpW2MrND4+Mj4+PjBdPWEpfWZ1bmN0aW9uIEhiKGEsYixjKXtIYi5BY3x8KEhiLkFjPSEwLEdiKGEsYixjKSl9dmFyIEliLEpiO1xyXG5KYj1CPygpPT57dmFyIGE9cHJvY2Vzcy5ocnRpbWUoKTtyZXR1cm4gMUUzKmFbMF0rYVsxXS8xRTZ9OkM/KCk9PnBlcmZvcm1hbmNlLm5vdygpLXguX19wZXJmb3JtYW5jZV9ub3dfY2xvY2tfZHJpZnQ6KCk9PnBlcmZvcm1hbmNlLm5vdygpO2Z1bmN0aW9uIFEoYSxiKXt2YXIgYz1hcmd1bWVudHMubGVuZ3RoLTIsZT1hcmd1bWVudHM7cmV0dXJuIGJiKCgpPT57Zm9yKHZhciBmPUtiKDgqYyksaD1mPj4zLGs9MDtrPGM7aysrKXt2YXIgbD1lWzIra107ZWEoKVtoK2s+Pj4wXT1sfXJldHVybiBMYihhLGMsZixiKX0pfXZhciBNYj1bXSxOYj17fTtcclxuZnVuY3Rpb24gT2IoKXtpZighUGIpe3ZhciBhPXtVU0VSOlwid2ViX3VzZXJcIixMT0dOQU1FOlwid2ViX3VzZXJcIixQQVRIOlwiL1wiLFBXRDpcIi9cIixIT01FOlwiL2hvbWUvd2ViX3VzZXJcIixMQU5HOihcIm9iamVjdFwiPT10eXBlb2YgbmF2aWdhdG9yJiZuYXZpZ2F0b3IubGFuZ3VhZ2VzJiZuYXZpZ2F0b3IubGFuZ3VhZ2VzWzBdfHxcIkNcIikucmVwbGFjZShcIi1cIixcIl9cIikrXCIuVVRGLThcIixfOmthfHxcIi4vdGhpcy5wcm9ncmFtXCJ9LGI7Zm9yKGIgaW4gTmIpdm9pZCAwPT09TmJbYl0/ZGVsZXRlIGFbYl06YVtiXT1OYltiXTt2YXIgYz1bXTtmb3IoYiBpbiBhKWMucHVzaChiK1wiPVwiK2FbYl0pO1BiPWN9cmV0dXJuIFBifXZhciBQYjtcclxuZnVuY3Rpb24gUWIoYSxiKXtpZihDKXJldHVybiBRKDIwLDEsYSxiKTt2YXIgYz0wO09iKCkuZm9yRWFjaChmdW5jdGlvbihlLGYpe3ZhciBoPWIrYztmPXYoKVthKzQqZj4+Mj4+PjBdPWg7Zm9yKGg9MDtoPGUubGVuZ3RoOysraClkKClbZisrPj4wPj4+MF09ZS5jaGFyQ29kZUF0KGgpO2QoKVtmPj4wPj4+MF09MDtjKz1lLmxlbmd0aCsxfSk7cmV0dXJuIDB9ZnVuY3Rpb24gUmIoYSxiKXtpZihDKXJldHVybiBRKDIxLDEsYSxiKTt2YXIgYz1PYigpO3YoKVthPj4yPj4+MF09Yy5sZW5ndGg7dmFyIGU9MDtjLmZvckVhY2goZnVuY3Rpb24oZil7ZSs9Zi5sZW5ndGgrMX0pO3YoKVtiPj4yPj4+MF09ZTtyZXR1cm4gMH1mdW5jdGlvbiBTYihhKXtyZXR1cm4gQz9RKDIyLDEsYSk6NTJ9ZnVuY3Rpb24gVGIoYSxiLGMsZSl7cmV0dXJuIEM/USgyMywxLGEsYixjLGUpOjUyfWZ1bmN0aW9uIFViKGEsYixjLGUsZil7cmV0dXJuIEM/USgyNCwxLGEsYixjLGUsZik6NzB9XHJcbnZhciBYYT1bbnVsbCxbXSxbXV07ZnVuY3Rpb24gWWEoYSxiKXt2YXIgYz1YYVthXTswPT09Ynx8MTA9PT1iPygoMT09PWE/dmE6RykoemEoYywwKSksYy5sZW5ndGg9MCk6Yy5wdXNoKGIpfWZ1bmN0aW9uIFZiKGEsYixjLGUpe2lmKEMpcmV0dXJuIFEoMjUsMSxhLGIsYyxlKTtmb3IodmFyIGY9MCxoPTA7aDxjO2grKyl7dmFyIGs9digpW2I+PjI+Pj4wXSxsPXYoKVtiKzQ+PjI+Pj4wXTtiKz04O2Zvcih2YXIgdT0wO3U8bDt1KyspWWEoYSxxKClbayt1Pj4+MF0pO2YrPWx9digpW2U+PjI+Pj4wXT1mO3JldHVybiAwfXZhciBZPTA7XHJcbmZ1bmN0aW9uIFdiKCl7aWYoXCJvYmplY3RcIj09dHlwZW9mIGNyeXB0byYmXCJmdW5jdGlvblwiPT10eXBlb2YgY3J5cHRvLmdldFJhbmRvbVZhbHVlcyl7dmFyIGE9bmV3IFVpbnQ4QXJyYXkoMSk7cmV0dXJuKCk9PntjcnlwdG8uZ2V0UmFuZG9tVmFsdWVzKGEpO3JldHVybiBhWzBdfX1pZihCKXRyeXt2YXIgYj1yZXF1aXJlKFwiY3J5cHRvXCIpO3JldHVybigpPT5iLnJhbmRvbUJ5dGVzKDEpWzBdfWNhdGNoKGMpe31yZXR1cm4oKT0+SShcInJhbmRvbURldmljZVwiKX1mdW5jdGlvbiBYYihhLGIpe1hiLmxjfHwoWGIubGM9V2IoKSk7Zm9yKHZhciBjPTA7YzxiO2MrKylkKClbYStjPj4wPj4+MF09WGIubGMoKTtyZXR1cm4gMH1mdW5jdGlvbiBZYihhKXtyZXR1cm4gMD09PWElNCYmKDAhPT1hJTEwMHx8MD09PWElNDAwKX12YXIgWmI9WzMxLDI5LDMxLDMwLDMxLDMwLDMxLDMxLDMwLDMxLDMwLDMxXSwkYj1bMzEsMjgsMzEsMzAsMzEsMzAsMzEsMzEsMzAsMzEsMzAsMzFdO1xyXG5mdW5jdGlvbiBhYyhhKXt2YXIgYj1BcnJheShDYShhKSsxKTtCYShhLGIsMCxiLmxlbmd0aCk7cmV0dXJuIGJ9XHJcbmZ1bmN0aW9uIGJjKGEsYixjLGUpe2Z1bmN0aW9uIGYoZyx3LHope2ZvcihnPVwibnVtYmVyXCI9PXR5cGVvZiBnP2cudG9TdHJpbmcoKTpnfHxcIlwiO2cubGVuZ3RoPHc7KWc9elswXStnO3JldHVybiBnfWZ1bmN0aW9uIGgoZyx3KXtyZXR1cm4gZihnLHcsXCIwXCIpfWZ1bmN0aW9uIGsoZyx3KXtmdW5jdGlvbiB6KFQpe3JldHVybiAwPlQ/LTE6MDxUPzE6MH12YXIgTjswPT09KE49eihnLmdldEZ1bGxZZWFyKCktdy5nZXRGdWxsWWVhcigpKSkmJjA9PT0oTj16KGcuZ2V0TW9udGgoKS13LmdldE1vbnRoKCkpKSYmKE49eihnLmdldERhdGUoKS13LmdldERhdGUoKSkpO3JldHVybiBOfWZ1bmN0aW9uIGwoZyl7c3dpdGNoKGcuZ2V0RGF5KCkpe2Nhc2UgMDpyZXR1cm4gbmV3IERhdGUoZy5nZXRGdWxsWWVhcigpLTEsMTEsMjkpO2Nhc2UgMTpyZXR1cm4gZztjYXNlIDI6cmV0dXJuIG5ldyBEYXRlKGcuZ2V0RnVsbFllYXIoKSwwLDMpO2Nhc2UgMzpyZXR1cm4gbmV3IERhdGUoZy5nZXRGdWxsWWVhcigpLFxyXG4wLDIpO2Nhc2UgNDpyZXR1cm4gbmV3IERhdGUoZy5nZXRGdWxsWWVhcigpLDAsMSk7Y2FzZSA1OnJldHVybiBuZXcgRGF0ZShnLmdldEZ1bGxZZWFyKCktMSwxMSwzMSk7Y2FzZSA2OnJldHVybiBuZXcgRGF0ZShnLmdldEZ1bGxZZWFyKCktMSwxMSwzMCl9fWZ1bmN0aW9uIHUoZyl7dmFyIHc9Zy5XYjtmb3IoZz1uZXcgRGF0ZSgobmV3IERhdGUoZy5YYisxOTAwLDAsMSkpLmdldFRpbWUoKSk7MDx3Oyl7dmFyIHo9Zy5nZXRNb250aCgpLE49KFliKGcuZ2V0RnVsbFllYXIoKSk/WmI6JGIpW3pdO2lmKHc+Ti1nLmdldERhdGUoKSl3LT1OLWcuZ2V0RGF0ZSgpKzEsZy5zZXREYXRlKDEpLDExPno/Zy5zZXRNb250aCh6KzEpOihnLnNldE1vbnRoKDApLGcuc2V0RnVsbFllYXIoZy5nZXRGdWxsWWVhcigpKzEpKTtlbHNle2cuc2V0RGF0ZShnLmdldERhdGUoKSt3KTticmVha319ej1uZXcgRGF0ZShnLmdldEZ1bGxZZWFyKCkrMSwwLDQpO3c9bChuZXcgRGF0ZShnLmdldEZ1bGxZZWFyKCksXHJcbjAsNCkpO3o9bCh6KTtyZXR1cm4gMD49ayh3LGcpPzA+PWsoeixnKT9nLmdldEZ1bGxZZWFyKCkrMTpnLmdldEZ1bGxZZWFyKCk6Zy5nZXRGdWxsWWVhcigpLTF9dmFyIHQ9cigpW2UrNDA+PjI+Pj4wXTtlPXtMYzpyKClbZT4+Mj4+PjBdLEtjOnIoKVtlKzQ+PjI+Pj4wXSxkYzpyKClbZSs4Pj4yPj4+MF0samM6cigpW2UrMTI+PjI+Pj4wXSxlYzpyKClbZSsxNj4+Mj4+PjBdLFhiOnIoKVtlKzIwPj4yPj4+MF0sVGI6cigpW2UrMjQ+PjI+Pj4wXSxXYjpyKClbZSsyOD4+Mj4+PjBdLFJjOnIoKVtlKzMyPj4yPj4+MF0sSmM6cigpW2UrMzY+PjI+Pj4wXSxNYzp0P0FhKHQpOlwiXCJ9O2M9QWEoYyk7dD17XCIlY1wiOlwiJWEgJWIgJWQgJUg6JU06JVMgJVlcIixcIiVEXCI6XCIlbS8lZC8leVwiLFwiJUZcIjpcIiVZLSVtLSVkXCIsXCIlaFwiOlwiJWJcIixcIiVyXCI6XCIlSTolTTolUyAlcFwiLFwiJVJcIjpcIiVIOiVNXCIsXCIlVFwiOlwiJUg6JU06JVNcIixcIiV4XCI6XCIlbS8lZC8leVwiLFwiJVhcIjpcIiVIOiVNOiVTXCIsXCIlRWNcIjpcIiVjXCIsXCIlRUNcIjpcIiVDXCIsXHJcblwiJUV4XCI6XCIlbS8lZC8leVwiLFwiJUVYXCI6XCIlSDolTTolU1wiLFwiJUV5XCI6XCIleVwiLFwiJUVZXCI6XCIlWVwiLFwiJU9kXCI6XCIlZFwiLFwiJU9lXCI6XCIlZVwiLFwiJU9IXCI6XCIlSFwiLFwiJU9JXCI6XCIlSVwiLFwiJU9tXCI6XCIlbVwiLFwiJU9NXCI6XCIlTVwiLFwiJU9TXCI6XCIlU1wiLFwiJU91XCI6XCIldVwiLFwiJU9VXCI6XCIlVVwiLFwiJU9WXCI6XCIlVlwiLFwiJU93XCI6XCIld1wiLFwiJU9XXCI6XCIlV1wiLFwiJU95XCI6XCIleVwifTtmb3IodmFyIEEgaW4gdCljPWMucmVwbGFjZShuZXcgUmVnRXhwKEEsXCJnXCIpLHRbQV0pO3ZhciBLPVwiU3VuZGF5IE1vbmRheSBUdWVzZGF5IFdlZG5lc2RheSBUaHVyc2RheSBGcmlkYXkgU2F0dXJkYXlcIi5zcGxpdChcIiBcIiksSj1cIkphbnVhcnkgRmVicnVhcnkgTWFyY2ggQXByaWwgTWF5IEp1bmUgSnVseSBBdWd1c3QgU2VwdGVtYmVyIE9jdG9iZXIgTm92ZW1iZXIgRGVjZW1iZXJcIi5zcGxpdChcIiBcIik7dD17XCIlYVwiOmZ1bmN0aW9uKGcpe3JldHVybiBLW2cuVGJdLnN1YnN0cmluZygwLDMpfSxcIiVBXCI6ZnVuY3Rpb24oZyl7cmV0dXJuIEtbZy5UYl19LFxyXG5cIiViXCI6ZnVuY3Rpb24oZyl7cmV0dXJuIEpbZy5lY10uc3Vic3RyaW5nKDAsMyl9LFwiJUJcIjpmdW5jdGlvbihnKXtyZXR1cm4gSltnLmVjXX0sXCIlQ1wiOmZ1bmN0aW9uKGcpe3JldHVybiBoKChnLlhiKzE5MDApLzEwMHwwLDIpfSxcIiVkXCI6ZnVuY3Rpb24oZyl7cmV0dXJuIGgoZy5qYywyKX0sXCIlZVwiOmZ1bmN0aW9uKGcpe3JldHVybiBmKGcuamMsMixcIiBcIil9LFwiJWdcIjpmdW5jdGlvbihnKXtyZXR1cm4gdShnKS50b1N0cmluZygpLnN1YnN0cmluZygyKX0sXCIlR1wiOmZ1bmN0aW9uKGcpe3JldHVybiB1KGcpfSxcIiVIXCI6ZnVuY3Rpb24oZyl7cmV0dXJuIGgoZy5kYywyKX0sXCIlSVwiOmZ1bmN0aW9uKGcpe2c9Zy5kYzswPT1nP2c9MTI6MTI8ZyYmKGctPTEyKTtyZXR1cm4gaChnLDIpfSxcIiVqXCI6ZnVuY3Rpb24oZyl7Zm9yKHZhciB3PTAsej0wO3o8PWcuZWMtMTt3Kz0oWWIoZy5YYisxOTAwKT9aYjokYilbeisrXSk7cmV0dXJuIGgoZy5qYyt3LDMpfSxcIiVtXCI6ZnVuY3Rpb24oZyl7cmV0dXJuIGgoZy5lYytcclxuMSwyKX0sXCIlTVwiOmZ1bmN0aW9uKGcpe3JldHVybiBoKGcuS2MsMil9LFwiJW5cIjpmdW5jdGlvbigpe3JldHVyblwiXFxuXCJ9LFwiJXBcIjpmdW5jdGlvbihnKXtyZXR1cm4gMDw9Zy5kYyYmMTI+Zy5kYz9cIkFNXCI6XCJQTVwifSxcIiVTXCI6ZnVuY3Rpb24oZyl7cmV0dXJuIGgoZy5MYywyKX0sXCIldFwiOmZ1bmN0aW9uKCl7cmV0dXJuXCJcXHRcIn0sXCIldVwiOmZ1bmN0aW9uKGcpe3JldHVybiBnLlRifHw3fSxcIiVVXCI6ZnVuY3Rpb24oZyl7cmV0dXJuIGgoTWF0aC5mbG9vcigoZy5XYis3LWcuVGIpLzcpLDIpfSxcIiVWXCI6ZnVuY3Rpb24oZyl7dmFyIHc9TWF0aC5mbG9vcigoZy5XYis3LShnLlRiKzYpJTcpLzcpOzI+PShnLlRiKzM3MS1nLldiLTIpJTcmJncrKztpZih3KTUzPT13JiYoej0oZy5UYiszNzEtZy5XYiklNyw0PT16fHwzPT16JiZZYihnLlhiKXx8KHc9MSkpO2Vsc2V7dz01Mjt2YXIgej0oZy5UYis3LWcuV2ItMSklNzsoND09enx8NT09eiYmWWIoZy5YYiU0MDAtMSkpJiZ3Kyt9cmV0dXJuIGgodyxcclxuMil9LFwiJXdcIjpmdW5jdGlvbihnKXtyZXR1cm4gZy5UYn0sXCIlV1wiOmZ1bmN0aW9uKGcpe3JldHVybiBoKE1hdGguZmxvb3IoKGcuV2IrNy0oZy5UYis2KSU3KS83KSwyKX0sXCIleVwiOmZ1bmN0aW9uKGcpe3JldHVybihnLlhiKzE5MDApLnRvU3RyaW5nKCkuc3Vic3RyaW5nKDIpfSxcIiVZXCI6ZnVuY3Rpb24oZyl7cmV0dXJuIGcuWGIrMTkwMH0sXCIlelwiOmZ1bmN0aW9uKGcpe2c9Zy5KYzt2YXIgdz0wPD1nO2c9TWF0aC5hYnMoZykvNjA7cmV0dXJuKHc/XCIrXCI6XCItXCIpK1N0cmluZyhcIjAwMDBcIisoZy82MCoxMDArZyU2MCkpLnNsaWNlKC00KX0sXCIlWlwiOmZ1bmN0aW9uKGcpe3JldHVybiBnLk1jfSxcIiUlXCI6ZnVuY3Rpb24oKXtyZXR1cm5cIiVcIn19O2M9Yy5yZXBsYWNlKC8lJS9nLFwiXFx4MDBcXHgwMFwiKTtmb3IoQSBpbiB0KWMuaW5jbHVkZXMoQSkmJihjPWMucmVwbGFjZShuZXcgUmVnRXhwKEEsXCJnXCIpLHRbQV0oZSkpKTtjPWMucmVwbGFjZSgvXFwwXFwwL2csXCIlXCIpO0E9YWMoYyk7aWYoQS5sZW5ndGg+XHJcbmIpcmV0dXJuIDA7ZmIoQSxhKTtyZXR1cm4gQS5sZW5ndGgtMX1QLmZjKCk7XHJcbnZhciBjYz1bbnVsbCxTYSxVYSxsYixuYixvYixwYixxYixyYixzYix0Yix1Yix2Yix3Yix4Yix5Yix6YixDYixEYixHYixRYixSYixTYixUYixVYixWYl0sUGM9e2I6ZnVuY3Rpb24oYSl7cmV0dXJuIEZiKGErMjQpKzI0fSxuOmZ1bmN0aW9uKGEpe2E9bmV3IFgoYSk7YS51YygpfHwoYS5oYyghMCksaGItLSk7YS5pYyghMSk7Z2IucHVzaChhKTthLnNjKCk7cmV0dXJuIGEudmMoKX0sbWE6ZnVuY3Rpb24oYSl7RyhcIlVuZXhwZWN0ZWQgZXhjZXB0aW9uIHRocm93biwgdGhpcyBpcyBub3QgcHJvcGVybHkgc3VwcG9ydGVkIC0gYWJvcnRpbmdcIik7eGE9ITA7dGhyb3cgYTt9LHg6ZnVuY3Rpb24oKXtaKDApO3ZhciBhPWdiLnBvcCgpO2lmKGEuSGMoKSYmIWEua2MoKSl7dmFyIGI9YS5EYygpO2ImJlYoYikoYS5aYik7amIoYS5aYil9Vz0wfSxlOmZ1bmN0aW9uKCl7dmFyIGE9VztpZighYSlyZXR1cm4gWT0wO3ZhciBiPW5ldyBYKGEpO2IuY2MoYSk7dmFyIGM9Yi5iYygpO2lmKCFjKXJldHVybiBZPVxyXG4wLGE7Zm9yKHZhciBlPUFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGFyZ3VtZW50cyksZj0wO2Y8ZS5sZW5ndGg7ZisrKXt2YXIgaD1lW2ZdO2lmKDA9PT1ofHxoPT09YylicmVhaztpZihkYyhoLGMsYi5TYisxNikpcmV0dXJuIFk9aCxhfVk9YztyZXR1cm4gYX0sbDpmdW5jdGlvbigpe3ZhciBhPVc7aWYoIWEpcmV0dXJuIFk9MDt2YXIgYj1uZXcgWChhKTtiLmNjKGEpO3ZhciBjPWIuYmMoKTtpZighYylyZXR1cm4gWT0wLGE7Zm9yKHZhciBlPUFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGFyZ3VtZW50cyksZj0wO2Y8ZS5sZW5ndGg7ZisrKXt2YXIgaD1lW2ZdO2lmKDA9PT1ofHxoPT09YylicmVhaztpZihkYyhoLGMsYi5TYisxNikpcmV0dXJuIFk9aCxhfVk9YztyZXR1cm4gYX0saDpmdW5jdGlvbigpe3ZhciBhPVc7aWYoIWEpcmV0dXJuIFk9MDt2YXIgYj1uZXcgWChhKTtiLmNjKGEpO3ZhciBjPWIuYmMoKTtpZighYylyZXR1cm4gWT0wLGE7Zm9yKHZhciBlPUFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGFyZ3VtZW50cyksXHJcbmY9MDtmPGUubGVuZ3RoO2YrKyl7dmFyIGg9ZVtmXTtpZigwPT09aHx8aD09PWMpYnJlYWs7aWYoZGMoaCxjLGIuU2IrMTYpKXJldHVybiBZPWgsYX1ZPWM7cmV0dXJuIGF9LHQ6amIsTTpmdW5jdGlvbigpe3ZhciBhPWdiLnBvcCgpO2F8fEkoXCJubyBleGNlcHRpb24gdG8gdGhyb3dcIik7dmFyIGI9YS5aYjthLmtjKCl8fChnYi5wdXNoKGEpLGEuaWMoITApLGEuaGMoITEpLGhiKyspO1c9Yjt0aHJvdyBiO30sYzpmdW5jdGlvbihhLGIsYyl7KG5ldyBYKGEpKS5mYyhiLGMpO1c9YTtoYisrO3Rocm93IGE7fSxwYTpmdW5jdGlvbigpe3JldHVybiBoYn0sRmE6ZnVuY3Rpb24oYSl7ZWMoYSwheSwxLCFtYSk7UC5wYygpfSxUOmZ1bmN0aW9uKGEpe0M/cG9zdE1lc3NhZ2Uoe2NtZDpcImNsZWFudXBUaHJlYWRcIix0aHJlYWQ6YX0pOlFhKGEpfSx4YTptYixqOmZ1bmN0aW9uKGEpe1d8fChXPWEpO3Rocm93IGE7fSxIOm5iLE1hOm9iLHVhOnBiLHdhOnFiLG9hOnJiLEthOnNiLENhOnRiLEphOnViLFxyXG5WOnZiLHZhOndiLHNhOnhiLExhOnliLHRhOnpiLFRhOmZ1bmN0aW9uKCl7fSxYOmZ1bmN0aW9uKCl7SShcIlRvIHVzZSBkbG9wZW4sIHlvdSBuZWVkIGVuYWJsZSBkeW5hbWljIGxpbmtpbmcsIHNlZSBodHRwczovL2dpdGh1Yi5jb20vZW1zY3JpcHRlbi1jb3JlL2Vtc2NyaXB0ZW4vd2lraS9MaW5raW5nXCIpfSxVYTpmdW5jdGlvbigpe0koXCJUbyB1c2UgZGxvcGVuLCB5b3UgbmVlZCBlbmFibGUgZHluYW1pYyBsaW5raW5nLCBzZWUgaHR0cHM6Ly9naXRodWIuY29tL2Vtc2NyaXB0ZW4tY29yZS9lbXNjcmlwdGVuL3dpa2kvTGlua2luZ1wiKX0sVzpmdW5jdGlvbigpe3JldHVybiBEYXRlLm5vdygpfSx5YTpmdW5jdGlvbigpe3JldHVybiAyMDk3MTUyfSxPYTpmdW5jdGlvbigpe3JldHVybiEwfSx6YTpmdW5jdGlvbihhLGIsYyxlKXtpZihhPT1iKXNldFRpbWVvdXQoKCk9PmFiKGUpKTtlbHNlIGlmKEMpcG9zdE1lc3NhZ2Uoe3RhcmdldFRocmVhZDphLGNtZDpcInByb2Nlc3NQcm94eWluZ1F1ZXVlXCIsXHJcbnF1ZXVlOmV9KTtlbHNle2E9UC5WYlthXTtpZighYSlyZXR1cm47YS5wb3N0TWVzc2FnZSh7Y21kOlwicHJvY2Vzc1Byb3h5aW5nUXVldWVcIixxdWV1ZTplfSl9cmV0dXJuIDF9LEVhOmZ1bmN0aW9uKCl7cmV0dXJuLTF9LFBhOmZ1bmN0aW9uKGEsYil7YT1uZXcgRGF0ZSgxRTMqQmIoYSkpO3IoKVtiPj4yPj4+MF09YS5nZXRVVENTZWNvbmRzKCk7cigpW2IrND4+Mj4+PjBdPWEuZ2V0VVRDTWludXRlcygpO3IoKVtiKzg+PjI+Pj4wXT1hLmdldFVUQ0hvdXJzKCk7cigpW2IrMTI+PjI+Pj4wXT1hLmdldFVUQ0RhdGUoKTtyKClbYisxNj4+Mj4+PjBdPWEuZ2V0VVRDTW9udGgoKTtyKClbYisyMD4+Mj4+PjBdPWEuZ2V0VVRDRnVsbFllYXIoKS0xOTAwO3IoKVtiKzI0Pj4yPj4+MF09YS5nZXRVVENEYXkoKTthPShhLmdldFRpbWUoKS1EYXRlLlVUQyhhLmdldFVUQ0Z1bGxZZWFyKCksMCwxLDAsMCwwLDApKS84NjRFNXwwO3IoKVtiKzI4Pj4yPj4+MF09YX0sUWE6ZnVuY3Rpb24oYSxiKXthPVxyXG5uZXcgRGF0ZSgxRTMqQmIoYSkpO3IoKVtiPj4yPj4+MF09YS5nZXRTZWNvbmRzKCk7cigpW2IrND4+Mj4+PjBdPWEuZ2V0TWludXRlcygpO3IoKVtiKzg+PjI+Pj4wXT1hLmdldEhvdXJzKCk7cigpW2IrMTI+PjI+Pj4wXT1hLmdldERhdGUoKTtyKClbYisxNj4+Mj4+PjBdPWEuZ2V0TW9udGgoKTtyKClbYisyMD4+Mj4+PjBdPWEuZ2V0RnVsbFllYXIoKS0xOTAwO3IoKVtiKzI0Pj4yPj4+MF09YS5nZXREYXkoKTt2YXIgYz1uZXcgRGF0ZShhLmdldEZ1bGxZZWFyKCksMCwxKSxlPShhLmdldFRpbWUoKS1jLmdldFRpbWUoKSkvODY0RTV8MDtyKClbYisyOD4+Mj4+PjBdPWU7cigpW2IrMzY+PjI+Pj4wXT0tKDYwKmEuZ2V0VGltZXpvbmVPZmZzZXQoKSk7ZT0obmV3IERhdGUoYS5nZXRGdWxsWWVhcigpLDYsMSkpLmdldFRpbWV6b25lT2Zmc2V0KCk7Yz1jLmdldFRpbWV6b25lT2Zmc2V0KCk7YT0oZSE9YyYmYS5nZXRUaW1lem9uZU9mZnNldCgpPT1NYXRoLm1pbihjLGUpKXwwO3IoKVtiK1xyXG4zMj4+Mj4+PjBdPWF9LFJhOmZ1bmN0aW9uKGEpe3ZhciBiPW5ldyBEYXRlKHIoKVthKzIwPj4yPj4+MF0rMTkwMCxyKClbYSsxNj4+Mj4+PjBdLHIoKVthKzEyPj4yPj4+MF0scigpW2ErOD4+Mj4+PjBdLHIoKVthKzQ+PjI+Pj4wXSxyKClbYT4+Mj4+PjBdLDApLGM9cigpW2ErMzI+PjI+Pj4wXSxlPWIuZ2V0VGltZXpvbmVPZmZzZXQoKSxmPW5ldyBEYXRlKGIuZ2V0RnVsbFllYXIoKSwwLDEpLGg9KG5ldyBEYXRlKGIuZ2V0RnVsbFllYXIoKSw2LDEpKS5nZXRUaW1lem9uZU9mZnNldCgpLGs9Zi5nZXRUaW1lem9uZU9mZnNldCgpLGw9TWF0aC5taW4oayxoKTswPmM/cigpW2ErMzI+PjI+Pj4wXT1OdW1iZXIoaCE9ayYmbD09ZSk6MDxjIT0obD09ZSkmJihoPU1hdGgubWF4KGssaCksYi5zZXRUaW1lKGIuZ2V0VGltZSgpKzZFNCooKDA8Yz9sOmgpLWUpKSk7cigpW2ErMjQ+PjI+Pj4wXT1iLmdldERheSgpO2M9KGIuZ2V0VGltZSgpLWYuZ2V0VGltZSgpKS84NjRFNXwwO3IoKVthKzI4Pj5cclxuMj4+PjBdPWM7cigpW2E+PjI+Pj4wXT1iLmdldFNlY29uZHMoKTtyKClbYSs0Pj4yPj4+MF09Yi5nZXRNaW51dGVzKCk7cigpW2ErOD4+Mj4+PjBdPWIuZ2V0SG91cnMoKTtyKClbYSsxMj4+Mj4+PjBdPWIuZ2V0RGF0ZSgpO3IoKVthKzE2Pj4yPj4+MF09Yi5nZXRNb250aCgpO3JldHVybiBiLmdldFRpbWUoKS8xRTN8MH0sQWE6Q2IsQmE6RGIsU2E6SGIseTpmdW5jdGlvbigpe0koXCJcIil9LFU6ZnVuY3Rpb24oKXtpZighQiYmIXkpe3ZhciBhPVwiQmxvY2tpbmcgb24gdGhlIG1haW4gdGhyZWFkIGlzIHZlcnkgZGFuZ2Vyb3VzLCBzZWUgaHR0cHM6Ly9lbXNjcmlwdGVuLm9yZy9kb2NzL3BvcnRpbmcvcHRocmVhZHMuaHRtbCNibG9ja2luZy1vbi10aGUtbWFpbi1icm93c2VyLXRocmVhZFwiO0lifHwoSWI9e30pO0liW2FdfHwoSWJbYV09MSxCJiYoYT1cIndhcm5pbmc6IFwiK2EpLEcoYSkpfX0scmE6ZnVuY3Rpb24oKXtyZXR1cm4gNDI5NDkwMTc2MH0sQjpKYixJYTpmdW5jdGlvbihhLGIsXHJcbmMpe3EoKS5jb3B5V2l0aGluKGE+Pj4wLGI+Pj4wLGIrYz4+PjApfSxGOmZ1bmN0aW9uKCl7cmV0dXJuIEI/cmVxdWlyZShcIm9zXCIpLmNwdXMoKS5sZW5ndGg6bmF2aWdhdG9yLmhhcmR3YXJlQ29uY3VycmVuY3l9LERhOmZ1bmN0aW9uKGEsYixjKXtNYi5sZW5ndGg9YjtjPj49Mztmb3IodmFyIGU9MDtlPGI7ZSsrKU1iW2VdPWVhKClbYytlPj4+MF07cmV0dXJuKDA+YT9QYVstYS0xXTpjY1thXSkuYXBwbHkobnVsbCxNYil9LHFhOmZ1bmN0aW9uKGEpe3ZhciBiPXEoKS5sZW5ndGg7YT4+Pj0wO2lmKGE8PWJ8fDQyOTQ5MDE3NjA8YSlyZXR1cm4hMTtmb3IodmFyIGM9MTs0Pj1jO2MqPTIpe3ZhciBlPWIqKDErLjIvYyk7ZT1NYXRoLm1pbihlLGErMTAwNjYzMjk2KTt2YXIgZj1NYXRoO2U9TWF0aC5tYXgoYSxlKTtmPWYubWluLmNhbGwoZiw0Mjk0OTAxNzYwLGUrKDY1NTM2LWUlNjU1MzYpJTY1NTM2KTthOnt0cnl7bS5ncm93KGYtbi5ieXRlTGVuZ3RoKzY1NTM1Pj4+MTYpO3AobS5idWZmZXIpO1xyXG52YXIgaD0xO2JyZWFrIGF9Y2F0Y2goayl7fWg9dm9pZCAwfWlmKGgpcmV0dXJuITB9cmV0dXJuITF9LE5hOmZ1bmN0aW9uKCl7dGhyb3dcInVud2luZFwiO30sR2E6UWIsSGE6UmIsSjpUYSxJOlNiLFM6VGIsZ2E6VWIsUjpWYixkOmZ1bmN0aW9uKCl7cmV0dXJuIFl9LG5hOlhiLGlhOmZjLGphOmdjLEs6aGMsZjppYyxQOmpjLFE6a2MsazpsYyxwOm1jLHE6bmMsTjpvYyxzOnBjLHc6cWMsTDpyYyxFOnNjLGFhOnRjLF86dWMsWjp2YyxjYTp3YywkOnhjLGJhOnljLFk6emMsZzpBYyxyOkJjLGk6Q2MsaGE6RGMsbTpFYyx2OkZjLHU6R2MsTzpIYyxBOkljLGthOkpjLEM6S2MsRDpMYyxmYTpNYyxkYTpOYyxlYTpPYyxvOmZ1bmN0aW9uKGEpe3JldHVybiBhfSxhOm18fHgud2FzbU1lbW9yeSxHOmZ1bmN0aW9uKGEpe1k9YX0sbGE6YmMsejpmdW5jdGlvbihhLGIsYyxlKXtyZXR1cm4gYmMoYSxiLGMsZSl9fTtcclxuKGZ1bmN0aW9uKCl7ZnVuY3Rpb24gYShmLGgpe3guYXNtPWYuZXhwb3J0cztQLnFjLnB1c2goeC5hc20uc2IpO0VhPXguYXNtLnViO0dhLnVuc2hpZnQoeC5hc20uVmEpO3dhPWg7Q3x8KEwtLSx4Lm1vbml0b3JSdW5EZXBlbmRlbmNpZXMmJngubW9uaXRvclJ1bkRlcGVuZGVuY2llcyhMKSwwPT1MJiYobnVsbCE9PUxhJiYoY2xlYXJJbnRlcnZhbChMYSksTGE9bnVsbCksTSYmKGY9TSxNPW51bGwsZigpKSkpfWZ1bmN0aW9uIGIoZil7YShmLmluc3RhbmNlLGYubW9kdWxlKX1mdW5jdGlvbiBjKGYpe3JldHVybiBPYSgpLnRoZW4oZnVuY3Rpb24oaCl7cmV0dXJuIFdlYkFzc2VtYmx5Lmluc3RhbnRpYXRlKGgsZSl9KS50aGVuKGZ1bmN0aW9uKGgpe3JldHVybiBofSkudGhlbihmLGZ1bmN0aW9uKGgpe0coXCJmYWlsZWQgdG8gYXN5bmNocm9ub3VzbHkgcHJlcGFyZSB3YXNtOiBcIitoKTtJKGgpfSl9dmFyIGU9e2E6UGN9O0N8fChMKysseC5tb25pdG9yUnVuRGVwZW5kZW5jaWVzJiZ4Lm1vbml0b3JSdW5EZXBlbmRlbmNpZXMoTCkpO1xyXG5pZih4Lmluc3RhbnRpYXRlV2FzbSl0cnl7cmV0dXJuIHguaW5zdGFudGlhdGVXYXNtKGUsYSl9Y2F0Y2goZil7cmV0dXJuIEcoXCJNb2R1bGUuaW5zdGFudGlhdGVXYXNtIGNhbGxiYWNrIGZhaWxlZCB3aXRoIGVycm9yOiBcIitmKSwhMX0oZnVuY3Rpb24oKXtyZXR1cm4gSHx8XCJmdW5jdGlvblwiIT10eXBlb2YgV2ViQXNzZW1ibHkuaW5zdGFudGlhdGVTdHJlYW1pbmd8fE1hKCl8fE8uc3RhcnRzV2l0aChcImZpbGU6Ly9cIil8fEJ8fFwiZnVuY3Rpb25cIiE9dHlwZW9mIGZldGNoP2MoYik6ZmV0Y2goTyx7Y3JlZGVudGlhbHM6XCJzYW1lLW9yaWdpblwifSkudGhlbihmdW5jdGlvbihmKXtyZXR1cm4gV2ViQXNzZW1ibHkuaW5zdGFudGlhdGVTdHJlYW1pbmcoZixlKS50aGVuKGIsZnVuY3Rpb24oaCl7RyhcIndhc20gc3RyZWFtaW5nIGNvbXBpbGUgZmFpbGVkOiBcIitoKTtHKFwiZmFsbGluZyBiYWNrIHRvIEFycmF5QnVmZmVyIGluc3RhbnRpYXRpb25cIik7cmV0dXJuIGMoYil9KX0pfSkoKS5jYXRjaChpYSk7XHJcbnJldHVybnt9fSkoKTt4Ll9fX3dhc21fY2FsbF9jdG9ycz1mdW5jdGlvbigpe3JldHVybih4Ll9fX3dhc21fY2FsbF9jdG9ycz14LmFzbS5WYSkuYXBwbHkobnVsbCxhcmd1bWVudHMpfTt4Ll9PcnRJbml0PWZ1bmN0aW9uKCl7cmV0dXJuKHguX09ydEluaXQ9eC5hc20uV2EpLmFwcGx5KG51bGwsYXJndW1lbnRzKX07eC5fT3J0Q3JlYXRlU2Vzc2lvbk9wdGlvbnM9ZnVuY3Rpb24oKXtyZXR1cm4oeC5fT3J0Q3JlYXRlU2Vzc2lvbk9wdGlvbnM9eC5hc20uWGEpLmFwcGx5KG51bGwsYXJndW1lbnRzKX07eC5fT3J0QXBwZW5kRXhlY3V0aW9uUHJvdmlkZXI9ZnVuY3Rpb24oKXtyZXR1cm4oeC5fT3J0QXBwZW5kRXhlY3V0aW9uUHJvdmlkZXI9eC5hc20uWWEpLmFwcGx5KG51bGwsYXJndW1lbnRzKX07eC5fT3J0QWRkU2Vzc2lvbkNvbmZpZ0VudHJ5PWZ1bmN0aW9uKCl7cmV0dXJuKHguX09ydEFkZFNlc3Npb25Db25maWdFbnRyeT14LmFzbS5aYSkuYXBwbHkobnVsbCxhcmd1bWVudHMpfTtcclxueC5fT3J0UmVsZWFzZVNlc3Npb25PcHRpb25zPWZ1bmN0aW9uKCl7cmV0dXJuKHguX09ydFJlbGVhc2VTZXNzaW9uT3B0aW9ucz14LmFzbS5fYSkuYXBwbHkobnVsbCxhcmd1bWVudHMpfTt4Ll9PcnRDcmVhdGVTZXNzaW9uPWZ1bmN0aW9uKCl7cmV0dXJuKHguX09ydENyZWF0ZVNlc3Npb249eC5hc20uJGEpLmFwcGx5KG51bGwsYXJndW1lbnRzKX07eC5fT3J0UmVsZWFzZVNlc3Npb249ZnVuY3Rpb24oKXtyZXR1cm4oeC5fT3J0UmVsZWFzZVNlc3Npb249eC5hc20uYWIpLmFwcGx5KG51bGwsYXJndW1lbnRzKX07eC5fT3J0R2V0SW5wdXRDb3VudD1mdW5jdGlvbigpe3JldHVybih4Ll9PcnRHZXRJbnB1dENvdW50PXguYXNtLmJiKS5hcHBseShudWxsLGFyZ3VtZW50cyl9O3guX09ydEdldE91dHB1dENvdW50PWZ1bmN0aW9uKCl7cmV0dXJuKHguX09ydEdldE91dHB1dENvdW50PXguYXNtLmNiKS5hcHBseShudWxsLGFyZ3VtZW50cyl9O1xyXG54Ll9PcnRHZXRJbnB1dE5hbWU9ZnVuY3Rpb24oKXtyZXR1cm4oeC5fT3J0R2V0SW5wdXROYW1lPXguYXNtLmRiKS5hcHBseShudWxsLGFyZ3VtZW50cyl9O3guX09ydEdldE91dHB1dE5hbWU9ZnVuY3Rpb24oKXtyZXR1cm4oeC5fT3J0R2V0T3V0cHV0TmFtZT14LmFzbS5lYikuYXBwbHkobnVsbCxhcmd1bWVudHMpfTt4Ll9PcnRGcmVlPWZ1bmN0aW9uKCl7cmV0dXJuKHguX09ydEZyZWU9eC5hc20uZmIpLmFwcGx5KG51bGwsYXJndW1lbnRzKX07eC5fT3J0Q3JlYXRlVGVuc29yPWZ1bmN0aW9uKCl7cmV0dXJuKHguX09ydENyZWF0ZVRlbnNvcj14LmFzbS5nYikuYXBwbHkobnVsbCxhcmd1bWVudHMpfTt4Ll9PcnRHZXRUZW5zb3JEYXRhPWZ1bmN0aW9uKCl7cmV0dXJuKHguX09ydEdldFRlbnNvckRhdGE9eC5hc20uaGIpLmFwcGx5KG51bGwsYXJndW1lbnRzKX07XHJcbnguX09ydFJlbGVhc2VUZW5zb3I9ZnVuY3Rpb24oKXtyZXR1cm4oeC5fT3J0UmVsZWFzZVRlbnNvcj14LmFzbS5pYikuYXBwbHkobnVsbCxhcmd1bWVudHMpfTt4Ll9PcnRDcmVhdGVSdW5PcHRpb25zPWZ1bmN0aW9uKCl7cmV0dXJuKHguX09ydENyZWF0ZVJ1bk9wdGlvbnM9eC5hc20uamIpLmFwcGx5KG51bGwsYXJndW1lbnRzKX07eC5fT3J0QWRkUnVuQ29uZmlnRW50cnk9ZnVuY3Rpb24oKXtyZXR1cm4oeC5fT3J0QWRkUnVuQ29uZmlnRW50cnk9eC5hc20ua2IpLmFwcGx5KG51bGwsYXJndW1lbnRzKX07eC5fT3J0UmVsZWFzZVJ1bk9wdGlvbnM9ZnVuY3Rpb24oKXtyZXR1cm4oeC5fT3J0UmVsZWFzZVJ1bk9wdGlvbnM9eC5hc20ubGIpLmFwcGx5KG51bGwsYXJndW1lbnRzKX07eC5fT3J0UnVuPWZ1bmN0aW9uKCl7cmV0dXJuKHguX09ydFJ1bj14LmFzbS5tYikuYXBwbHkobnVsbCxhcmd1bWVudHMpfTtcclxueC5fT3J0RW5kUHJvZmlsaW5nPWZ1bmN0aW9uKCl7cmV0dXJuKHguX09ydEVuZFByb2ZpbGluZz14LmFzbS5uYikuYXBwbHkobnVsbCxhcmd1bWVudHMpfTt2YXIgJGE9eC5fcHRocmVhZF9zZWxmPWZ1bmN0aW9uKCl7cmV0dXJuKCRhPXguX3B0aHJlYWRfc2VsZj14LmFzbS5vYikuYXBwbHkobnVsbCxhcmd1bWVudHMpfSxGYj14Ll9tYWxsb2M9ZnVuY3Rpb24oKXtyZXR1cm4oRmI9eC5fbWFsbG9jPXguYXNtLnBiKS5hcHBseShudWxsLGFyZ3VtZW50cyl9LGtiPXguX2ZyZWU9ZnVuY3Rpb24oKXtyZXR1cm4oa2I9eC5fZnJlZT14LmFzbS5xYikuYXBwbHkobnVsbCxhcmd1bWVudHMpfSxXYT14Ll9mZmx1c2g9ZnVuY3Rpb24oKXtyZXR1cm4oV2E9eC5fZmZsdXNoPXguYXNtLnJiKS5hcHBseShudWxsLGFyZ3VtZW50cyl9O3guX19lbXNjcmlwdGVuX3Rsc19pbml0PWZ1bmN0aW9uKCl7cmV0dXJuKHguX19lbXNjcmlwdGVuX3Rsc19pbml0PXguYXNtLnNiKS5hcHBseShudWxsLGFyZ3VtZW50cyl9O1xyXG52YXIgVmE9eC5fX19mdW5jc19vbl9leGl0PWZ1bmN0aW9uKCl7cmV0dXJuKFZhPXguX19fZnVuY3Nfb25fZXhpdD14LmFzbS50YikuYXBwbHkobnVsbCxhcmd1bWVudHMpfSxlYz14Ll9fZW1zY3JpcHRlbl90aHJlYWRfaW5pdD1mdW5jdGlvbigpe3JldHVybihlYz14Ll9fZW1zY3JpcHRlbl90aHJlYWRfaW5pdD14LmFzbS52YikuYXBwbHkobnVsbCxhcmd1bWVudHMpfTt4Ll9fZW1zY3JpcHRlbl90aHJlYWRfY3Jhc2hlZD1mdW5jdGlvbigpe3JldHVybih4Ll9fZW1zY3JpcHRlbl90aHJlYWRfY3Jhc2hlZD14LmFzbS53YikuYXBwbHkobnVsbCxhcmd1bWVudHMpfTtcclxudmFyIExiPXguX2Vtc2NyaXB0ZW5fcnVuX2luX21haW5fcnVudGltZV90aHJlYWRfanM9ZnVuY3Rpb24oKXtyZXR1cm4oTGI9eC5fZW1zY3JpcHRlbl9ydW5faW5fbWFpbl9ydW50aW1lX3RocmVhZF9qcz14LmFzbS54YikuYXBwbHkobnVsbCxhcmd1bWVudHMpfSxBYj14Ll9fZW1zY3JpcHRlbl9wcm94eV9leGVjdXRlX3Rhc2tfcXVldWU9ZnVuY3Rpb24oKXtyZXR1cm4oQWI9eC5fX2Vtc2NyaXB0ZW5fcHJveHlfZXhlY3V0ZV90YXNrX3F1ZXVlPXguYXNtLnliKS5hcHBseShudWxsLGFyZ3VtZW50cyl9LFphPXguX19lbXNjcmlwdGVuX3RocmVhZF9mcmVlX2RhdGE9ZnVuY3Rpb24oKXtyZXR1cm4oWmE9eC5fX2Vtc2NyaXB0ZW5fdGhyZWFkX2ZyZWVfZGF0YT14LmFzbS56YikuYXBwbHkobnVsbCxhcmd1bWVudHMpfSxlYj14Ll9fZW1zY3JpcHRlbl90aHJlYWRfZXhpdD1mdW5jdGlvbigpe3JldHVybihlYj14Ll9fZW1zY3JpcHRlbl90aHJlYWRfZXhpdD14LmFzbS5BYikuYXBwbHkobnVsbCxcclxuYXJndW1lbnRzKX0sWj14Ll9zZXRUaHJldz1mdW5jdGlvbigpe3JldHVybihaPXguX3NldFRocmV3PXguYXNtLkJiKS5hcHBseShudWxsLGFyZ3VtZW50cyl9LGNiPXguX2Vtc2NyaXB0ZW5fc3RhY2tfc2V0X2xpbWl0cz1mdW5jdGlvbigpe3JldHVybihjYj14Ll9lbXNjcmlwdGVuX3N0YWNrX3NldF9saW1pdHM9eC5hc20uQ2IpLmFwcGx5KG51bGwsYXJndW1lbnRzKX0sUz14LnN0YWNrU2F2ZT1mdW5jdGlvbigpe3JldHVybihTPXguc3RhY2tTYXZlPXguYXNtLkRiKS5hcHBseShudWxsLGFyZ3VtZW50cyl9LFU9eC5zdGFja1Jlc3RvcmU9ZnVuY3Rpb24oKXtyZXR1cm4oVT14LnN0YWNrUmVzdG9yZT14LmFzbS5FYikuYXBwbHkobnVsbCxhcmd1bWVudHMpfSxLYj14LnN0YWNrQWxsb2M9ZnVuY3Rpb24oKXtyZXR1cm4oS2I9eC5zdGFja0FsbG9jPXguYXNtLkZiKS5hcHBseShudWxsLGFyZ3VtZW50cyl9LGRjPXguX19fY3hhX2Nhbl9jYXRjaD1mdW5jdGlvbigpe3JldHVybihkYz14Ll9fX2N4YV9jYW5fY2F0Y2g9XHJcbnguYXNtLkdiKS5hcHBseShudWxsLGFyZ3VtZW50cyl9LGliPXguX19fY3hhX2lzX3BvaW50ZXJfdHlwZT1mdW5jdGlvbigpe3JldHVybihpYj14Ll9fX2N4YV9pc19wb2ludGVyX3R5cGU9eC5hc20uSGIpLmFwcGx5KG51bGwsYXJndW1lbnRzKX0sUWM9eC5keW5DYWxsX2o9ZnVuY3Rpb24oKXtyZXR1cm4oUWM9eC5keW5DYWxsX2o9eC5hc20uSWIpLmFwcGx5KG51bGwsYXJndW1lbnRzKX0sUmM9eC5keW5DYWxsX2lpaWlpaj1mdW5jdGlvbigpe3JldHVybihSYz14LmR5bkNhbGxfaWlpaWlqPXguYXNtLkpiKS5hcHBseShudWxsLGFyZ3VtZW50cyl9LFNjPXguZHluQ2FsbF9qaWk9ZnVuY3Rpb24oKXtyZXR1cm4oU2M9eC5keW5DYWxsX2ppaT14LmFzbS5LYikuYXBwbHkobnVsbCxhcmd1bWVudHMpfSxUYz14LmR5bkNhbGxfdmlpaWlpaj1mdW5jdGlvbigpe3JldHVybihUYz14LmR5bkNhbGxfdmlpaWlpaj14LmFzbS5MYikuYXBwbHkobnVsbCxhcmd1bWVudHMpfSxVYz14LmR5bkNhbGxfdmpqaT1cclxuZnVuY3Rpb24oKXtyZXR1cm4oVWM9eC5keW5DYWxsX3Zqamk9eC5hc20uTWIpLmFwcGx5KG51bGwsYXJndW1lbnRzKX0sVmM9eC5keW5DYWxsX3ZpaWlqamppaT1mdW5jdGlvbigpe3JldHVybihWYz14LmR5bkNhbGxfdmlpaWpqamlpPXguYXNtLk5iKS5hcHBseShudWxsLGFyZ3VtZW50cyl9LFdjPXguZHluQ2FsbF9paWo9ZnVuY3Rpb24oKXtyZXR1cm4oV2M9eC5keW5DYWxsX2lpaj14LmFzbS5PYikuYXBwbHkobnVsbCxhcmd1bWVudHMpfSxYYz14LmR5bkNhbGxfamk9ZnVuY3Rpb24oKXtyZXR1cm4oWGM9eC5keW5DYWxsX2ppPXguYXNtLlBiKS5hcHBseShudWxsLGFyZ3VtZW50cyl9LFljPXguZHluQ2FsbF9paWlpaWlqPWZ1bmN0aW9uKCl7cmV0dXJuKFljPXguZHluQ2FsbF9paWlpaWlqPXguYXNtLlFiKS5hcHBseShudWxsLGFyZ3VtZW50cyl9LFpjPXguZHluQ2FsbF9paWlqPWZ1bmN0aW9uKCl7cmV0dXJuKFpjPXguZHluQ2FsbF9paWlqPXguYXNtLlJiKS5hcHBseShudWxsLFxyXG5hcmd1bWVudHMpfTtmdW5jdGlvbiBpYyhhLGIpe3ZhciBjPVMoKTt0cnl7cmV0dXJuIFYoYSkoYil9Y2F0Y2goZSl7VShjKTtpZihlIT09ZSswKXRocm93IGU7WigxLDApfX1mdW5jdGlvbiBCYyhhLGIpe3ZhciBjPVMoKTt0cnl7VihhKShiKX1jYXRjaChlKXtVKGMpO2lmKGUhPT1lKzApdGhyb3cgZTtaKDEsMCl9fWZ1bmN0aW9uIENjKGEsYixjKXt2YXIgZT1TKCk7dHJ5e1YoYSkoYixjKX1jYXRjaChmKXtVKGUpO2lmKGYhPT1mKzApdGhyb3cgZjtaKDEsMCl9fWZ1bmN0aW9uIGxjKGEsYixjKXt2YXIgZT1TKCk7dHJ5e3JldHVybiBWKGEpKGIsYyl9Y2F0Y2goZil7VShlKTtpZihmIT09ZiswKXRocm93IGY7WigxLDApfX1mdW5jdGlvbiBtYyhhLGIsYyxlKXt2YXIgZj1TKCk7dHJ5e3JldHVybiBWKGEpKGIsYyxlKX1jYXRjaChoKXtVKGYpO2lmKGghPT1oKzApdGhyb3cgaDtaKDEsMCl9fVxyXG5mdW5jdGlvbiBxYyhhLGIsYyxlLGYsaCxrKXt2YXIgbD1TKCk7dHJ5e3JldHVybiBWKGEpKGIsYyxlLGYsaCxrKX1jYXRjaCh1KXtVKGwpO2lmKHUhPT11KzApdGhyb3cgdTtaKDEsMCl9fWZ1bmN0aW9uIEFjKGEpe3ZhciBiPVMoKTt0cnl7VihhKSgpfWNhdGNoKGMpe1UoYik7aWYoYyE9PWMrMCl0aHJvdyBjO1ooMSwwKX19ZnVuY3Rpb24gcGMoYSxiLGMsZSxmLGgpe3ZhciBrPVMoKTt0cnl7cmV0dXJuIFYoYSkoYixjLGUsZixoKX1jYXRjaChsKXtVKGspO2lmKGwhPT1sKzApdGhyb3cgbDtaKDEsMCl9fWZ1bmN0aW9uIG5jKGEsYixjLGUsZil7dmFyIGg9UygpO3RyeXtyZXR1cm4gVihhKShiLGMsZSxmKX1jYXRjaChrKXtVKGgpO2lmKGshPT1rKzApdGhyb3cgaztaKDEsMCl9fWZ1bmN0aW9uIEVjKGEsYixjLGUpe3ZhciBmPVMoKTt0cnl7VihhKShiLGMsZSl9Y2F0Y2goaCl7VShmKTtpZihoIT09aCswKXRocm93IGg7WigxLDApfX1cclxuZnVuY3Rpb24gR2MoYSxiLGMsZSxmLGgpe3ZhciBrPVMoKTt0cnl7VihhKShiLGMsZSxmLGgpfWNhdGNoKGwpe1Uoayk7aWYobCE9PWwrMCl0aHJvdyBsO1ooMSwwKX19ZnVuY3Rpb24gRmMoYSxiLGMsZSxmKXt2YXIgaD1TKCk7dHJ5e1YoYSkoYixjLGUsZil9Y2F0Y2goayl7VShoKTtpZihrIT09ayswKXRocm93IGs7WigxLDApfX1mdW5jdGlvbiBJYyhhLGIsYyxlLGYsaCxrLGwpe3ZhciB1PVMoKTt0cnl7VihhKShiLGMsZSxmLGgsayxsKX1jYXRjaCh0KXtVKHUpO2lmKHQhPT10KzApdGhyb3cgdDtaKDEsMCl9fWZ1bmN0aW9uIGtjKGEsYixjKXt2YXIgZT1TKCk7dHJ5e3JldHVybiBWKGEpKGIsYyl9Y2F0Y2goZil7VShlKTtpZihmIT09ZiswKXRocm93IGY7WigxLDApfX1mdW5jdGlvbiBqYyhhLGIsYyl7dmFyIGU9UygpO3RyeXtyZXR1cm4gVihhKShiLGMpfWNhdGNoKGYpe1UoZSk7aWYoZiE9PWYrMCl0aHJvdyBmO1ooMSwwKX19XHJcbmZ1bmN0aW9uIEpjKGEsYixjLGUsZixoLGssbCx1KXt2YXIgdD1TKCk7dHJ5e1YoYSkoYixjLGUsZixoLGssbCx1KX1jYXRjaChBKXtVKHQpO2lmKEEhPT1BKzApdGhyb3cgQTtaKDEsMCl9fWZ1bmN0aW9uIEhjKGEsYixjLGUsZixoLGspe3ZhciBsPVMoKTt0cnl7VihhKShiLGMsZSxmLGgsayl9Y2F0Y2godSl7VShsKTtpZih1IT09dSswKXRocm93IHU7WigxLDApfX1mdW5jdGlvbiBvYyhhLGIsYyxlLGYsaCl7dmFyIGs9UygpO3RyeXtyZXR1cm4gVihhKShiLGMsZSxmLGgpfWNhdGNoKGwpe1Uoayk7aWYobCE9PWwrMCl0aHJvdyBsO1ooMSwwKX19ZnVuY3Rpb24gcmMoYSxiLGMsZSxmLGgsayxsKXt2YXIgdT1TKCk7dHJ5e3JldHVybiBWKGEpKGIsYyxlLGYsaCxrLGwpfWNhdGNoKHQpe1UodSk7aWYodCE9PXQrMCl0aHJvdyB0O1ooMSwwKX19XHJcbmZ1bmN0aW9uIHNjKGEsYixjLGUsZixoLGssbCx1LHQsQSxLKXt2YXIgSj1TKCk7dHJ5e3JldHVybiBWKGEpKGIsYyxlLGYsaCxrLGwsdSx0LEEsSyl9Y2F0Y2goZyl7VShKKTtpZihnIT09ZyswKXRocm93IGc7WigxLDApfX1mdW5jdGlvbiBLYyhhLGIsYyxlLGYsaCxrLGwsdSx0LEEpe3ZhciBLPVMoKTt0cnl7VihhKShiLGMsZSxmLGgsayxsLHUsdCxBKX1jYXRjaChKKXtVKEspO2lmKEohPT1KKzApdGhyb3cgSjtaKDEsMCl9fWZ1bmN0aW9uIExjKGEsYixjLGUsZixoLGssbCx1LHQsQSxLLEosZyx3LHope3ZhciBOPVMoKTt0cnl7VihhKShiLGMsZSxmLGgsayxsLHUsdCxBLEssSixnLHcseil9Y2F0Y2goVCl7VShOKTtpZihUIT09VCswKXRocm93IFQ7WigxLDApfX1mdW5jdGlvbiBoYyhhKXt2YXIgYj1TKCk7dHJ5e3JldHVybiBWKGEpKCl9Y2F0Y2goYyl7VShiKTtpZihjIT09YyswKXRocm93IGM7WigxLDApfX1cclxuZnVuY3Rpb24gZ2MoYSxiLGMpe3ZhciBlPVMoKTt0cnl7cmV0dXJuIFYoYSkoYixjKX1jYXRjaChmKXtVKGUpO2lmKGYhPT1mKzApdGhyb3cgZjtaKDEsMCl9fWZ1bmN0aW9uIGZjKGEsYixjKXt2YXIgZT1TKCk7dHJ5e3JldHVybiBWKGEpKGIsYyl9Y2F0Y2goZil7VShlKTtpZihmIT09ZiswKXRocm93IGY7WigxLDApfX1mdW5jdGlvbiBEYyhhLGIsYyxlKXt2YXIgZj1TKCk7dHJ5e1YoYSkoYixjLGUpfWNhdGNoKGgpe1UoZik7aWYoaCE9PWgrMCl0aHJvdyBoO1ooMSwwKX19ZnVuY3Rpb24gTWMoYSxiLGMsZSxmLGgsayxsKXt2YXIgdT1TKCk7dHJ5e1RjKGEsYixjLGUsZixoLGssbCl9Y2F0Y2godCl7VSh1KTtpZih0IT09dCswKXRocm93IHQ7WigxLDApfX1mdW5jdGlvbiBPYyhhLGIsYyxlLGYsaCl7dmFyIGs9UygpO3RyeXtVYyhhLGIsYyxlLGYsaCl9Y2F0Y2gobCl7VShrKTtpZihsIT09bCswKXRocm93IGw7WigxLDApfX1cclxuZnVuY3Rpb24gTmMoYSxiLGMsZSxmLGgsayxsLHUsdCxBLEspe3ZhciBKPVMoKTt0cnl7VmMoYSxiLGMsZSxmLGgsayxsLHUsdCxBLEspfWNhdGNoKGcpe1UoSik7aWYoZyE9PWcrMCl0aHJvdyBnO1ooMSwwKX19ZnVuY3Rpb24gd2MoYSxiLGMsZSl7dmFyIGY9UygpO3RyeXtyZXR1cm4gV2MoYSxiLGMsZSl9Y2F0Y2goaCl7VShmKTtpZihoIT09aCswKXRocm93IGg7WigxLDApfX1mdW5jdGlvbiB5YyhhLGIpe3ZhciBjPVMoKTt0cnl7cmV0dXJuIFhjKGEsYil9Y2F0Y2goZSl7VShjKTtpZihlIT09ZSswKXRocm93IGU7WigxLDApfX1mdW5jdGlvbiB0YyhhLGIsYyxlLGYsaCxrLGwpe3ZhciB1PVMoKTt0cnl7cmV0dXJuIFljKGEsYixjLGUsZixoLGssbCl9Y2F0Y2godCl7VSh1KTtpZih0IT09dCswKXRocm93IHQ7WigxLDApfX1mdW5jdGlvbiB4YyhhKXt2YXIgYj1TKCk7dHJ5e3JldHVybiBRYyhhKX1jYXRjaChjKXtVKGIpO2lmKGMhPT1jKzApdGhyb3cgYztaKDEsMCl9fVxyXG5mdW5jdGlvbiB1YyhhLGIsYyxlLGYsaCxrKXt2YXIgbD1TKCk7dHJ5e3JldHVybiBSYyhhLGIsYyxlLGYsaCxrKX1jYXRjaCh1KXtVKGwpO2lmKHUhPT11KzApdGhyb3cgdTtaKDEsMCl9fWZ1bmN0aW9uIHZjKGEsYixjLGUsZil7dmFyIGg9UygpO3RyeXtyZXR1cm4gWmMoYSxiLGMsZSxmKX1jYXRjaChrKXtVKGgpO2lmKGshPT1rKzApdGhyb3cgaztaKDEsMCl9fWZ1bmN0aW9uIHpjKGEsYixjKXt2YXIgZT1TKCk7dHJ5e3JldHVybiBTYyhhLGIsYyl9Y2F0Y2goZil7VShlKTtpZihmIT09ZiswKXRocm93IGY7WigxLDApfX14LlVURjhUb1N0cmluZz1BYTt4LnN0cmluZ1RvVVRGOD1mdW5jdGlvbihhLGIsYyl7cmV0dXJuIEJhKGEscSgpLGIsYyl9O3gubGVuZ3RoQnl0ZXNVVEY4PUNhO3gua2VlcFJ1bnRpbWVBbGl2ZT1GO3gud2FzbU1lbW9yeT1tO3guc3RhY2tTYXZlPVM7eC5zdGFja1Jlc3RvcmU9VTt4LnN0YWNrQWxsb2M9S2I7eC5FeGl0U3RhdHVzPUU7eC5QVGhyZWFkPVA7dmFyICRjO1xyXG5NPWZ1bmN0aW9uIGFkKCl7JGN8fGJkKCk7JGN8fChNPWFkKX07XHJcbmZ1bmN0aW9uIGJkKCl7ZnVuY3Rpb24gYSgpe2lmKCEkYyYmKCRjPSEwLHguY2FsbGVkUnVuPSEwLCF4YSkpe0N8fFIoR2EpO2hhKHgpO2lmKHgub25SdW50aW1lSW5pdGlhbGl6ZWQpeC5vblJ1bnRpbWVJbml0aWFsaXplZCgpO2lmKCFDKXtpZih4LnBvc3RSdW4pZm9yKFwiZnVuY3Rpb25cIj09dHlwZW9mIHgucG9zdFJ1biYmKHgucG9zdFJ1bj1beC5wb3N0UnVuXSk7eC5wb3N0UnVuLmxlbmd0aDspe3ZhciBiPXgucG9zdFJ1bi5zaGlmdCgpO0lhLnVuc2hpZnQoYil9UihJYSl9fX1pZighKDA8TCkpaWYoQyloYSh4KSxDfHxSKEdhKSxwb3N0TWVzc2FnZSh7Y21kOlwibG9hZGVkXCJ9KTtlbHNle2lmKHgucHJlUnVuKWZvcihcImZ1bmN0aW9uXCI9PXR5cGVvZiB4LnByZVJ1biYmKHgucHJlUnVuPVt4LnByZVJ1bl0pO3gucHJlUnVuLmxlbmd0aDspS2EoKTtSKEZhKTswPEx8fCh4LnNldFN0YXR1cz8oeC5zZXRTdGF0dXMoXCJSdW5uaW5nLi4uXCIpLHNldFRpbWVvdXQoZnVuY3Rpb24oKXtzZXRUaW1lb3V0KGZ1bmN0aW9uKCl7eC5zZXRTdGF0dXMoXCJcIil9LFxyXG4xKTthKCl9LDEpKTphKCkpfX1pZih4LnByZUluaXQpZm9yKFwiZnVuY3Rpb25cIj09dHlwZW9mIHgucHJlSW5pdCYmKHgucHJlSW5pdD1beC5wcmVJbml0XSk7MDx4LnByZUluaXQubGVuZ3RoOyl4LnByZUluaXQucG9wKCkoKTtiZCgpO1xyXG5cclxuXHJcbiAgcmV0dXJuIG9ydFdhc21UaHJlYWRlZC5yZWFkeVxyXG59XHJcbik7XHJcbn0pKCk7XHJcbmlmICh0eXBlb2YgZXhwb3J0cyA9PT0gJ29iamVjdCcgJiYgdHlwZW9mIG1vZHVsZSA9PT0gJ29iamVjdCcpXHJcbiAgbW9kdWxlLmV4cG9ydHMgPSBvcnRXYXNtVGhyZWFkZWQ7XHJcbmVsc2UgaWYgKHR5cGVvZiBkZWZpbmUgPT09ICdmdW5jdGlvbicgJiYgZGVmaW5lWydhbWQnXSlcclxuICBkZWZpbmUoW10sIGZ1bmN0aW9uKCkgeyByZXR1cm4gb3J0V2FzbVRocmVhZGVkOyB9KTtcclxuZWxzZSBpZiAodHlwZW9mIGV4cG9ydHMgPT09ICdvYmplY3QnKVxyXG4gIGV4cG9ydHNbXCJvcnRXYXNtVGhyZWFkZWRcIl0gPSBvcnRXYXNtVGhyZWFkZWQ7XHJcbiIsIlxyXG52YXIgb3J0V2FzbSA9ICgoKSA9PiB7XHJcbiAgdmFyIF9zY3JpcHREaXIgPSB0eXBlb2YgZG9jdW1lbnQgIT09ICd1bmRlZmluZWQnICYmIGRvY3VtZW50LmN1cnJlbnRTY3JpcHQgPyBkb2N1bWVudC5jdXJyZW50U2NyaXB0LnNyYyA6IHVuZGVmaW5lZDtcclxuICBpZiAodHlwZW9mIF9fZmlsZW5hbWUgIT09ICd1bmRlZmluZWQnKSBfc2NyaXB0RGlyID0gX3NjcmlwdERpciB8fCBfX2ZpbGVuYW1lO1xyXG4gIHJldHVybiAoXHJcbmZ1bmN0aW9uKG9ydFdhc20pIHtcclxuICBvcnRXYXNtID0gb3J0V2FzbSB8fCB7fTtcclxuXHJcblxyXG52YXIgZDtkfHwoZD10eXBlb2Ygb3J0V2FzbSAhPT0gJ3VuZGVmaW5lZCcgPyBvcnRXYXNtIDoge30pO3ZhciBhYSxiYTtkLnJlYWR5PW5ldyBQcm9taXNlKGZ1bmN0aW9uKGEsYil7YWE9YTtiYT1ifSk7dmFyIGNhPU9iamVjdC5hc3NpZ24oe30sZCksZGE9XCIuL3RoaXMucHJvZ3JhbVwiLGVhPShhLGIpPT57dGhyb3cgYjt9LGZhPVwib2JqZWN0XCI9PXR5cGVvZiB3aW5kb3csbT1cImZ1bmN0aW9uXCI9PXR5cGVvZiBpbXBvcnRTY3JpcHRzLHA9XCJvYmplY3RcIj09dHlwZW9mIHByb2Nlc3MmJlwib2JqZWN0XCI9PXR5cGVvZiBwcm9jZXNzLnZlcnNpb25zJiZcInN0cmluZ1wiPT10eXBlb2YgcHJvY2Vzcy52ZXJzaW9ucy5ub2RlLHE9XCJcIixoYSxyLHYsZnMseSxpYTtcclxuaWYocClxPW0/cmVxdWlyZShcInBhdGhcIikuZGlybmFtZShxKStcIi9cIjpfX2Rpcm5hbWUrXCIvXCIsaWE9KCk9Pnt5fHwoZnM9cmVxdWlyZShcImZzXCIpLHk9cmVxdWlyZShcInBhdGhcIikpfSxoYT1mdW5jdGlvbihhLGIpe2lhKCk7YT15Lm5vcm1hbGl6ZShhKTtyZXR1cm4gZnMucmVhZEZpbGVTeW5jKGEsYj92b2lkIDA6XCJ1dGY4XCIpfSx2PWE9PnthPWhhKGEsITApO2EuYnVmZmVyfHwoYT1uZXcgVWludDhBcnJheShhKSk7cmV0dXJuIGF9LHI9KGEsYixjKT0+e2lhKCk7YT15Lm5vcm1hbGl6ZShhKTtmcy5yZWFkRmlsZShhLGZ1bmN0aW9uKGUsZil7ZT9jKGUpOmIoZi5idWZmZXIpfSl9LDE8cHJvY2Vzcy5hcmd2Lmxlbmd0aCYmKGRhPXByb2Nlc3MuYXJndlsxXS5yZXBsYWNlKC9cXFxcL2csXCIvXCIpKSxwcm9jZXNzLmFyZ3Yuc2xpY2UoMikscHJvY2Vzcy5vbihcInVuY2F1Z2h0RXhjZXB0aW9uXCIsZnVuY3Rpb24oYSl7aWYoIShhIGluc3RhbmNlb2YgamEpKXRocm93IGE7fSkscHJvY2Vzcy5vbihcInVuaGFuZGxlZFJlamVjdGlvblwiLFxyXG5mdW5jdGlvbihhKXt0aHJvdyBhO30pLGVhPShhLGIpPT57aWYobm9FeGl0UnVudGltZXx8MDxrYSl0aHJvdyBwcm9jZXNzLmV4aXRDb2RlPWEsYjtiIGluc3RhbmNlb2YgamF8fHooXCJleGl0aW5nIGR1ZSB0byBleGNlcHRpb246IFwiK2IpO3Byb2Nlc3MuZXhpdChhKX0sZC5pbnNwZWN0PWZ1bmN0aW9uKCl7cmV0dXJuXCJbRW1zY3JpcHRlbiBNb2R1bGUgb2JqZWN0XVwifTtlbHNlIGlmKGZhfHxtKW0/cT1zZWxmLmxvY2F0aW9uLmhyZWY6XCJ1bmRlZmluZWRcIiE9dHlwZW9mIGRvY3VtZW50JiZkb2N1bWVudC5jdXJyZW50U2NyaXB0JiYocT1kb2N1bWVudC5jdXJyZW50U2NyaXB0LnNyYyksX3NjcmlwdERpciYmKHE9X3NjcmlwdERpciksMCE9PXEuaW5kZXhPZihcImJsb2I6XCIpP3E9cS5zdWJzdHIoMCxxLnJlcGxhY2UoL1s/I10uKi8sXCJcIikubGFzdEluZGV4T2YoXCIvXCIpKzEpOnE9XCJcIixoYT1hPT57dmFyIGI9bmV3IFhNTEh0dHBSZXF1ZXN0O2Iub3BlbihcIkdFVFwiLGEsITEpO2Iuc2VuZChudWxsKTtcclxucmV0dXJuIGIucmVzcG9uc2VUZXh0fSxtJiYodj1hPT57dmFyIGI9bmV3IFhNTEh0dHBSZXF1ZXN0O2Iub3BlbihcIkdFVFwiLGEsITEpO2IucmVzcG9uc2VUeXBlPVwiYXJyYXlidWZmZXJcIjtiLnNlbmQobnVsbCk7cmV0dXJuIG5ldyBVaW50OEFycmF5KGIucmVzcG9uc2UpfSkscj0oYSxiLGMpPT57dmFyIGU9bmV3IFhNTEh0dHBSZXF1ZXN0O2Uub3BlbihcIkdFVFwiLGEsITApO2UucmVzcG9uc2VUeXBlPVwiYXJyYXlidWZmZXJcIjtlLm9ubG9hZD0oKT0+ezIwMD09ZS5zdGF0dXN8fDA9PWUuc3RhdHVzJiZlLnJlc3BvbnNlP2IoZS5yZXNwb25zZSk6YygpfTtlLm9uZXJyb3I9YztlLnNlbmQobnVsbCl9O3ZhciBsYT1kLnByaW50fHxjb25zb2xlLmxvZy5iaW5kKGNvbnNvbGUpLHo9ZC5wcmludEVycnx8Y29uc29sZS53YXJuLmJpbmQoY29uc29sZSk7T2JqZWN0LmFzc2lnbihkLGNhKTtjYT1udWxsO2QudGhpc1Byb2dyYW0mJihkYT1kLnRoaXNQcm9ncmFtKTtkLnF1aXQmJihlYT1kLnF1aXQpO1xyXG52YXIgQTtkLndhc21CaW5hcnkmJihBPWQud2FzbUJpbmFyeSk7dmFyIG5vRXhpdFJ1bnRpbWU9ZC5ub0V4aXRSdW50aW1lfHwhMTtcIm9iamVjdFwiIT10eXBlb2YgV2ViQXNzZW1ibHkmJkIoXCJubyBuYXRpdmUgd2FzbSBzdXBwb3J0IGRldGVjdGVkXCIpO3ZhciBtYSxEPSExLG5hPVwidW5kZWZpbmVkXCIhPXR5cGVvZiBUZXh0RGVjb2Rlcj9uZXcgVGV4dERlY29kZXIoXCJ1dGY4XCIpOnZvaWQgMDtcclxuZnVuY3Rpb24gb2EoYSxiLGMpe2I+Pj49MDt2YXIgZT1iK2M7Zm9yKGM9YjthW2NdJiYhKGM+PWUpOykrK2M7aWYoMTY8Yy1iJiZhLmJ1ZmZlciYmbmEpcmV0dXJuIG5hLmRlY29kZShhLnN1YmFycmF5KGIsYykpO2ZvcihlPVwiXCI7YjxjOyl7dmFyIGY9YVtiKytdO2lmKGYmMTI4KXt2YXIgaD1hW2IrK10mNjM7aWYoMTkyPT0oZiYyMjQpKWUrPVN0cmluZy5mcm9tQ2hhckNvZGUoKGYmMzEpPDw2fGgpO2Vsc2V7dmFyIGs9YVtiKytdJjYzO2Y9MjI0PT0oZiYyNDApPyhmJjE1KTw8MTJ8aDw8NnxrOihmJjcpPDwxOHxoPDwxMnxrPDw2fGFbYisrXSY2Mzs2NTUzNj5mP2UrPVN0cmluZy5mcm9tQ2hhckNvZGUoZik6KGYtPTY1NTM2LGUrPVN0cmluZy5mcm9tQ2hhckNvZGUoNTUyOTZ8Zj4+MTAsNTYzMjB8ZiYxMDIzKSl9fWVsc2UgZSs9U3RyaW5nLmZyb21DaGFyQ29kZShmKX1yZXR1cm4gZX1mdW5jdGlvbiBwYShhLGIpe3JldHVybihhPj4+PTApP29hKEcsYSxiKTpcIlwifVxyXG5mdW5jdGlvbiBxYShhLGIsYyxlKXtjPj4+PTA7aWYoISgwPGUpKXJldHVybiAwO3ZhciBmPWM7ZT1jK2UtMTtmb3IodmFyIGg9MDtoPGEubGVuZ3RoOysraCl7dmFyIGs9YS5jaGFyQ29kZUF0KGgpO2lmKDU1Mjk2PD1rJiY1NzM0Mz49ayl7dmFyIGw9YS5jaGFyQ29kZUF0KCsraCk7az02NTUzNisoKGsmMTAyMyk8PDEwKXxsJjEwMjN9aWYoMTI3Pj1rKXtpZihjPj1lKWJyZWFrO2JbYysrPj4+MF09a31lbHNle2lmKDIwNDc+PWspe2lmKGMrMT49ZSlicmVhaztiW2MrKz4+PjBdPTE5MnxrPj42fWVsc2V7aWYoNjU1MzU+PWspe2lmKGMrMj49ZSlicmVhaztiW2MrKz4+PjBdPTIyNHxrPj4xMn1lbHNle2lmKGMrMz49ZSlicmVhaztiW2MrKz4+PjBdPTI0MHxrPj4xODtiW2MrKz4+PjBdPTEyOHxrPj4xMiY2M31iW2MrKz4+PjBdPTEyOHxrPj42JjYzfWJbYysrPj4+MF09MTI4fGsmNjN9fWJbYz4+PjBdPTA7cmV0dXJuIGMtZn1cclxuZnVuY3Rpb24gcmEoYSl7Zm9yKHZhciBiPTAsYz0wO2M8YS5sZW5ndGg7KytjKXt2YXIgZT1hLmNoYXJDb2RlQXQoYyk7MTI3Pj1lP2IrKzoyMDQ3Pj1lP2IrPTI6NTUyOTY8PWUmJjU3MzQzPj1lPyhiKz00LCsrYyk6Yis9M31yZXR1cm4gYn12YXIgc2EsSCxHLEksSjtmdW5jdGlvbiB0YSgpe3ZhciBhPW1hLmJ1ZmZlcjtzYT1hO2QuSEVBUDg9SD1uZXcgSW50OEFycmF5KGEpO2QuSEVBUDE2PW5ldyBJbnQxNkFycmF5KGEpO2QuSEVBUDMyPUk9bmV3IEludDMyQXJyYXkoYSk7ZC5IRUFQVTg9Rz1uZXcgVWludDhBcnJheShhKTtkLkhFQVBVMTY9bmV3IFVpbnQxNkFycmF5KGEpO2QuSEVBUFUzMj1KPW5ldyBVaW50MzJBcnJheShhKTtkLkhFQVBGMzI9bmV3IEZsb2F0MzJBcnJheShhKTtkLkhFQVBGNjQ9bmV3IEZsb2F0NjRBcnJheShhKX12YXIgdWEsdmE9W10sd2E9W10seGE9W10seWE9W10sa2E9MDtcclxuZnVuY3Rpb24gemEoKXt2YXIgYT1kLnByZVJ1bi5zaGlmdCgpO3ZhLnVuc2hpZnQoYSl9dmFyIEs9MCxBYT1udWxsLEw9bnVsbDtmdW5jdGlvbiBCKGEpe2lmKGQub25BYm9ydClkLm9uQWJvcnQoYSk7YT1cIkFib3J0ZWQoXCIrYStcIilcIjt6KGEpO0Q9ITA7YT1uZXcgV2ViQXNzZW1ibHkuUnVudGltZUVycm9yKGErXCIuIEJ1aWxkIHdpdGggLXNBU1NFUlRJT05TIGZvciBtb3JlIGluZm8uXCIpO2JhKGEpO3Rocm93IGE7fWZ1bmN0aW9uIEJhKCl7cmV0dXJuIE4uc3RhcnRzV2l0aChcImRhdGE6YXBwbGljYXRpb24vb2N0ZXQtc3RyZWFtO2Jhc2U2NCxcIil9dmFyIE47Tj1cIm9ydC13YXNtLndhc21cIjtpZighQmEoKSl7dmFyIENhPU47Tj1kLmxvY2F0ZUZpbGU/ZC5sb2NhdGVGaWxlKENhLHEpOnErQ2F9XHJcbmZ1bmN0aW9uIERhKCl7dmFyIGE9Tjt0cnl7aWYoYT09TiYmQSlyZXR1cm4gbmV3IFVpbnQ4QXJyYXkoQSk7aWYodilyZXR1cm4gdihhKTt0aHJvd1wiYm90aCBhc3luYyBhbmQgc3luYyBmZXRjaGluZyBvZiB0aGUgd2FzbSBmYWlsZWRcIjt9Y2F0Y2goYil7QihiKX19XHJcbmZ1bmN0aW9uIEVhKCl7aWYoIUEmJihmYXx8bSkpe2lmKFwiZnVuY3Rpb25cIj09dHlwZW9mIGZldGNoJiYhTi5zdGFydHNXaXRoKFwiZmlsZTovL1wiKSlyZXR1cm4gZmV0Y2goTix7Y3JlZGVudGlhbHM6XCJzYW1lLW9yaWdpblwifSkudGhlbihmdW5jdGlvbihhKXtpZighYS5vayl0aHJvd1wiZmFpbGVkIHRvIGxvYWQgd2FzbSBiaW5hcnkgZmlsZSBhdCAnXCIrTitcIidcIjtyZXR1cm4gYS5hcnJheUJ1ZmZlcigpfSkuY2F0Y2goZnVuY3Rpb24oKXtyZXR1cm4gRGEoKX0pO2lmKHIpcmV0dXJuIG5ldyBQcm9taXNlKGZ1bmN0aW9uKGEsYil7cihOLGZ1bmN0aW9uKGMpe2EobmV3IFVpbnQ4QXJyYXkoYykpfSxiKX0pfXJldHVybiBQcm9taXNlLnJlc29sdmUoKS50aGVuKGZ1bmN0aW9uKCl7cmV0dXJuIERhKCl9KX1mdW5jdGlvbiBqYShhKXt0aGlzLm5hbWU9XCJFeGl0U3RhdHVzXCI7dGhpcy5tZXNzYWdlPVwiUHJvZ3JhbSB0ZXJtaW5hdGVkIHdpdGggZXhpdChcIithK1wiKVwiO3RoaXMuc3RhdHVzPWF9XHJcbmZ1bmN0aW9uIE8oYSl7Zm9yKDswPGEubGVuZ3RoOylhLnNoaWZ0KCkoZCl9dmFyIFA9W10sUT0wLFI9MDtcclxuZnVuY3Rpb24gUyhhKXt0aGlzLkRiPWE7dGhpcy56Yj1hLTI0O3RoaXMuVWI9ZnVuY3Rpb24oYil7Slt0aGlzLnpiKzQ+PjI+Pj4wXT1ifTt0aGlzLkViPWZ1bmN0aW9uKCl7cmV0dXJuIEpbdGhpcy56Yis0Pj4yPj4+MF19O3RoaXMuU2I9ZnVuY3Rpb24oYil7Slt0aGlzLnpiKzg+PjI+Pj4wXT1ifTt0aGlzLldiPWZ1bmN0aW9uKCl7cmV0dXJuIEpbdGhpcy56Yis4Pj4yPj4+MF19O3RoaXMuVGI9ZnVuY3Rpb24oKXtJW3RoaXMuemI+PjI+Pj4wXT0wfTt0aGlzLkliPWZ1bmN0aW9uKGIpe0hbdGhpcy56YisxMj4+MD4+PjBdPWI/MTowfTt0aGlzLlBiPWZ1bmN0aW9uKCl7cmV0dXJuIDAhPUhbdGhpcy56YisxMj4+MD4+PjBdfTt0aGlzLkpiPWZ1bmN0aW9uKGIpe0hbdGhpcy56YisxMz4+MD4+PjBdPWI/MTowfTt0aGlzLkxiPWZ1bmN0aW9uKCl7cmV0dXJuIDAhPUhbdGhpcy56YisxMz4+MD4+PjBdfTt0aGlzLlJiPWZ1bmN0aW9uKGIsYyl7dGhpcy5GYigwKTt0aGlzLlViKGIpO3RoaXMuU2IoYyk7XHJcbnRoaXMuVGIoKTt0aGlzLkliKCExKTt0aGlzLkpiKCExKX07dGhpcy5OYj1mdW5jdGlvbigpe0lbdGhpcy56Yj4+Mj4+PjBdKz0xfTt0aGlzLlhiPWZ1bmN0aW9uKCl7dmFyIGI9SVt0aGlzLnpiPj4yPj4+MF07SVt0aGlzLnpiPj4yPj4+MF09Yi0xO3JldHVybiAxPT09Yn07dGhpcy5GYj1mdW5jdGlvbihiKXtKW3RoaXMuemIrMTY+PjI+Pj4wXT1ifTt0aGlzLk9iPWZ1bmN0aW9uKCl7cmV0dXJuIEpbdGhpcy56YisxNj4+Mj4+PjBdfTt0aGlzLlFiPWZ1bmN0aW9uKCl7aWYoRmEodGhpcy5FYigpKSlyZXR1cm4gSlt0aGlzLkRiPj4yPj4+MF07dmFyIGI9dGhpcy5PYigpO3JldHVybiAwIT09Yj9iOnRoaXMuRGJ9fWZ1bmN0aW9uIEdhKGEpe3JldHVybiBIYSgobmV3IFMoYSkpLnpiKX12YXIgVD1bXTtmdW5jdGlvbiBVKGEpe3ZhciBiPVRbYV07Ynx8KGE+PVQubGVuZ3RoJiYoVC5sZW5ndGg9YSsxKSxUW2FdPWI9dWEuZ2V0KGEpKTtyZXR1cm4gYn1cclxuZnVuY3Rpb24gSWEoYSl7dmFyIGI9cmEoYSkrMSxjPUphKGIpO2MmJnFhKGEsSCxjLGIpO3JldHVybiBjfWZ1bmN0aW9uIEthKGEsYixjKXtmdW5jdGlvbiBlKG4pe3JldHVybihuPW4udG9UaW1lU3RyaW5nKCkubWF0Y2goL1xcKChbQS1aYS16IF0rKVxcKSQvKSk/blsxXTpcIkdNVFwifXZhciBmPShuZXcgRGF0ZSkuZ2V0RnVsbFllYXIoKSxoPW5ldyBEYXRlKGYsMCwxKSxrPW5ldyBEYXRlKGYsNiwxKTtmPWguZ2V0VGltZXpvbmVPZmZzZXQoKTt2YXIgbD1rLmdldFRpbWV6b25lT2Zmc2V0KCk7SVthPj4yPj4+MF09NjAqTWF0aC5tYXgoZixsKTtJW2I+PjI+Pj4wXT1OdW1iZXIoZiE9bCk7YT1lKGgpO2I9ZShrKTthPUlhKGEpO2I9SWEoYik7bDxmPyhKW2M+PjI+Pj4wXT1hLEpbYys0Pj4yPj4+MF09Yik6KEpbYz4+Mj4+PjBdPWIsSltjKzQ+PjI+Pj4wXT1hKX1mdW5jdGlvbiBMYShhLGIsYyl7TGEuVmJ8fChMYS5WYj0hMCxLYShhLGIsYykpfXZhciBNYT17fTtcclxuZnVuY3Rpb24gTmEoKXtpZighT2Epe3ZhciBhPXtVU0VSOlwid2ViX3VzZXJcIixMT0dOQU1FOlwid2ViX3VzZXJcIixQQVRIOlwiL1wiLFBXRDpcIi9cIixIT01FOlwiL2hvbWUvd2ViX3VzZXJcIixMQU5HOihcIm9iamVjdFwiPT10eXBlb2YgbmF2aWdhdG9yJiZuYXZpZ2F0b3IubGFuZ3VhZ2VzJiZuYXZpZ2F0b3IubGFuZ3VhZ2VzWzBdfHxcIkNcIikucmVwbGFjZShcIi1cIixcIl9cIikrXCIuVVRGLThcIixfOmRhfHxcIi4vdGhpcy5wcm9ncmFtXCJ9LGI7Zm9yKGIgaW4gTWEpdm9pZCAwPT09TWFbYl0/ZGVsZXRlIGFbYl06YVtiXT1NYVtiXTt2YXIgYz1bXTtmb3IoYiBpbiBhKWMucHVzaChiK1wiPVwiK2FbYl0pO09hPWN9cmV0dXJuIE9hfXZhciBPYSxQYT1bbnVsbCxbXSxbXV07ZnVuY3Rpb24gUWEoYSxiKXt2YXIgYz1QYVthXTswPT09Ynx8MTA9PT1iPygoMT09PWE/bGE6eikob2EoYywwKSksYy5sZW5ndGg9MCk6Yy5wdXNoKGIpfXZhciBWPTA7XHJcbmZ1bmN0aW9uIFJhKCl7aWYoXCJvYmplY3RcIj09dHlwZW9mIGNyeXB0byYmXCJmdW5jdGlvblwiPT10eXBlb2YgY3J5cHRvLmdldFJhbmRvbVZhbHVlcyl7dmFyIGE9bmV3IFVpbnQ4QXJyYXkoMSk7cmV0dXJuKCk9PntjcnlwdG8uZ2V0UmFuZG9tVmFsdWVzKGEpO3JldHVybiBhWzBdfX1pZihwKXRyeXt2YXIgYj1yZXF1aXJlKFwiY3J5cHRvXCIpO3JldHVybigpPT5iLnJhbmRvbUJ5dGVzKDEpWzBdfWNhdGNoKGMpe31yZXR1cm4oKT0+QihcInJhbmRvbURldmljZVwiKX1mdW5jdGlvbiBXKGEsYil7Vy5NYnx8KFcuTWI9UmEoKSk7Zm9yKHZhciBjPTA7YzxiO2MrKylIW2ErYz4+MD4+PjBdPVcuTWIoKTtyZXR1cm4gMH1mdW5jdGlvbiBTYShhKXtyZXR1cm4gMD09PWElNCYmKDAhPT1hJTEwMHx8MD09PWElNDAwKX12YXIgVGE9WzMxLDI5LDMxLDMwLDMxLDMwLDMxLDMxLDMwLDMxLDMwLDMxXSxVYT1bMzEsMjgsMzEsMzAsMzEsMzAsMzEsMzEsMzAsMzEsMzAsMzFdO1xyXG5mdW5jdGlvbiBWYShhKXt2YXIgYj1BcnJheShyYShhKSsxKTtxYShhLGIsMCxiLmxlbmd0aCk7cmV0dXJuIGJ9XHJcbmZ1bmN0aW9uIFdhKGEsYixjLGUpe2Z1bmN0aW9uIGYoZyx1LHcpe2ZvcihnPVwibnVtYmVyXCI9PXR5cGVvZiBnP2cudG9TdHJpbmcoKTpnfHxcIlwiO2cubGVuZ3RoPHU7KWc9d1swXStnO3JldHVybiBnfWZ1bmN0aW9uIGgoZyx1KXtyZXR1cm4gZihnLHUsXCIwXCIpfWZ1bmN0aW9uIGsoZyx1KXtmdW5jdGlvbiB3KE0pe3JldHVybiAwPk0/LTE6MDxNPzE6MH12YXIgRjswPT09KEY9dyhnLmdldEZ1bGxZZWFyKCktdS5nZXRGdWxsWWVhcigpKSkmJjA9PT0oRj13KGcuZ2V0TW9udGgoKS11LmdldE1vbnRoKCkpKSYmKEY9dyhnLmdldERhdGUoKS11LmdldERhdGUoKSkpO3JldHVybiBGfWZ1bmN0aW9uIGwoZyl7c3dpdGNoKGcuZ2V0RGF5KCkpe2Nhc2UgMDpyZXR1cm4gbmV3IERhdGUoZy5nZXRGdWxsWWVhcigpLTEsMTEsMjkpO2Nhc2UgMTpyZXR1cm4gZztjYXNlIDI6cmV0dXJuIG5ldyBEYXRlKGcuZ2V0RnVsbFllYXIoKSwwLDMpO2Nhc2UgMzpyZXR1cm4gbmV3IERhdGUoZy5nZXRGdWxsWWVhcigpLFxyXG4wLDIpO2Nhc2UgNDpyZXR1cm4gbmV3IERhdGUoZy5nZXRGdWxsWWVhcigpLDAsMSk7Y2FzZSA1OnJldHVybiBuZXcgRGF0ZShnLmdldEZ1bGxZZWFyKCktMSwxMSwzMSk7Y2FzZSA2OnJldHVybiBuZXcgRGF0ZShnLmdldEZ1bGxZZWFyKCktMSwxMSwzMCl9fWZ1bmN0aW9uIG4oZyl7dmFyIHU9Zy5CYjtmb3IoZz1uZXcgRGF0ZSgobmV3IERhdGUoZy5DYisxOTAwLDAsMSkpLmdldFRpbWUoKSk7MDx1Oyl7dmFyIHc9Zy5nZXRNb250aCgpLEY9KFNhKGcuZ2V0RnVsbFllYXIoKSk/VGE6VWEpW3ddO2lmKHU+Ri1nLmdldERhdGUoKSl1LT1GLWcuZ2V0RGF0ZSgpKzEsZy5zZXREYXRlKDEpLDExPnc/Zy5zZXRNb250aCh3KzEpOihnLnNldE1vbnRoKDApLGcuc2V0RnVsbFllYXIoZy5nZXRGdWxsWWVhcigpKzEpKTtlbHNle2cuc2V0RGF0ZShnLmdldERhdGUoKSt1KTticmVha319dz1uZXcgRGF0ZShnLmdldEZ1bGxZZWFyKCkrMSwwLDQpO3U9bChuZXcgRGF0ZShnLmdldEZ1bGxZZWFyKCksXHJcbjAsNCkpO3c9bCh3KTtyZXR1cm4gMD49ayh1LGcpPzA+PWsodyxnKT9nLmdldEZ1bGxZZWFyKCkrMTpnLmdldEZ1bGxZZWFyKCk6Zy5nZXRGdWxsWWVhcigpLTF9dmFyIHQ9SVtlKzQwPj4yPj4+MF07ZT17JGI6SVtlPj4yPj4+MF0sWmI6SVtlKzQ+PjI+Pj4wXSxHYjpJW2UrOD4+Mj4+PjBdLEtiOklbZSsxMj4+Mj4+PjBdLEhiOklbZSsxNj4+Mj4+PjBdLENiOklbZSsyMD4+Mj4+PjBdLEFiOklbZSsyND4+Mj4+PjBdLEJiOklbZSsyOD4+Mj4+PjBdLGJjOklbZSszMj4+Mj4+PjBdLFliOklbZSszNj4+Mj4+PjBdLGFjOnQ/cGEodCk6XCJcIn07Yz1wYShjKTt0PXtcIiVjXCI6XCIlYSAlYiAlZCAlSDolTTolUyAlWVwiLFwiJURcIjpcIiVtLyVkLyV5XCIsXCIlRlwiOlwiJVktJW0tJWRcIixcIiVoXCI6XCIlYlwiLFwiJXJcIjpcIiVJOiVNOiVTICVwXCIsXCIlUlwiOlwiJUg6JU1cIixcIiVUXCI6XCIlSDolTTolU1wiLFwiJXhcIjpcIiVtLyVkLyV5XCIsXCIlWFwiOlwiJUg6JU06JVNcIixcIiVFY1wiOlwiJWNcIixcIiVFQ1wiOlwiJUNcIixcIiVFeFwiOlwiJW0vJWQvJXlcIixcclxuXCIlRVhcIjpcIiVIOiVNOiVTXCIsXCIlRXlcIjpcIiV5XCIsXCIlRVlcIjpcIiVZXCIsXCIlT2RcIjpcIiVkXCIsXCIlT2VcIjpcIiVlXCIsXCIlT0hcIjpcIiVIXCIsXCIlT0lcIjpcIiVJXCIsXCIlT21cIjpcIiVtXCIsXCIlT01cIjpcIiVNXCIsXCIlT1NcIjpcIiVTXCIsXCIlT3VcIjpcIiV1XCIsXCIlT1VcIjpcIiVVXCIsXCIlT1ZcIjpcIiVWXCIsXCIlT3dcIjpcIiV3XCIsXCIlT1dcIjpcIiVXXCIsXCIlT3lcIjpcIiV5XCJ9O2Zvcih2YXIgeCBpbiB0KWM9Yy5yZXBsYWNlKG5ldyBSZWdFeHAoeCxcImdcIiksdFt4XSk7dmFyIEU9XCJTdW5kYXkgTW9uZGF5IFR1ZXNkYXkgV2VkbmVzZGF5IFRodXJzZGF5IEZyaWRheSBTYXR1cmRheVwiLnNwbGl0KFwiIFwiKSxDPVwiSmFudWFyeSBGZWJydWFyeSBNYXJjaCBBcHJpbCBNYXkgSnVuZSBKdWx5IEF1Z3VzdCBTZXB0ZW1iZXIgT2N0b2JlciBOb3ZlbWJlciBEZWNlbWJlclwiLnNwbGl0KFwiIFwiKTt0PXtcIiVhXCI6ZnVuY3Rpb24oZyl7cmV0dXJuIEVbZy5BYl0uc3Vic3RyaW5nKDAsMyl9LFwiJUFcIjpmdW5jdGlvbihnKXtyZXR1cm4gRVtnLkFiXX0sXCIlYlwiOmZ1bmN0aW9uKGcpe3JldHVybiBDW2cuSGJdLnN1YnN0cmluZygwLFxyXG4zKX0sXCIlQlwiOmZ1bmN0aW9uKGcpe3JldHVybiBDW2cuSGJdfSxcIiVDXCI6ZnVuY3Rpb24oZyl7cmV0dXJuIGgoKGcuQ2IrMTkwMCkvMTAwfDAsMil9LFwiJWRcIjpmdW5jdGlvbihnKXtyZXR1cm4gaChnLktiLDIpfSxcIiVlXCI6ZnVuY3Rpb24oZyl7cmV0dXJuIGYoZy5LYiwyLFwiIFwiKX0sXCIlZ1wiOmZ1bmN0aW9uKGcpe3JldHVybiBuKGcpLnRvU3RyaW5nKCkuc3Vic3RyaW5nKDIpfSxcIiVHXCI6ZnVuY3Rpb24oZyl7cmV0dXJuIG4oZyl9LFwiJUhcIjpmdW5jdGlvbihnKXtyZXR1cm4gaChnLkdiLDIpfSxcIiVJXCI6ZnVuY3Rpb24oZyl7Zz1nLkdiOzA9PWc/Zz0xMjoxMjxnJiYoZy09MTIpO3JldHVybiBoKGcsMil9LFwiJWpcIjpmdW5jdGlvbihnKXtmb3IodmFyIHU9MCx3PTA7dzw9Zy5IYi0xO3UrPShTYShnLkNiKzE5MDApP1RhOlVhKVt3KytdKTtyZXR1cm4gaChnLktiK3UsMyl9LFwiJW1cIjpmdW5jdGlvbihnKXtyZXR1cm4gaChnLkhiKzEsMil9LFwiJU1cIjpmdW5jdGlvbihnKXtyZXR1cm4gaChnLlpiLFxyXG4yKX0sXCIlblwiOmZ1bmN0aW9uKCl7cmV0dXJuXCJcXG5cIn0sXCIlcFwiOmZ1bmN0aW9uKGcpe3JldHVybiAwPD1nLkdiJiYxMj5nLkdiP1wiQU1cIjpcIlBNXCJ9LFwiJVNcIjpmdW5jdGlvbihnKXtyZXR1cm4gaChnLiRiLDIpfSxcIiV0XCI6ZnVuY3Rpb24oKXtyZXR1cm5cIlxcdFwifSxcIiV1XCI6ZnVuY3Rpb24oZyl7cmV0dXJuIGcuQWJ8fDd9LFwiJVVcIjpmdW5jdGlvbihnKXtyZXR1cm4gaChNYXRoLmZsb29yKChnLkJiKzctZy5BYikvNyksMil9LFwiJVZcIjpmdW5jdGlvbihnKXt2YXIgdT1NYXRoLmZsb29yKChnLkJiKzctKGcuQWIrNiklNykvNyk7Mj49KGcuQWIrMzcxLWcuQmItMiklNyYmdSsrO2lmKHUpNTM9PXUmJih3PShnLkFiKzM3MS1nLkJiKSU3LDQ9PXd8fDM9PXcmJlNhKGcuQ2IpfHwodT0xKSk7ZWxzZXt1PTUyO3ZhciB3PShnLkFiKzctZy5CYi0xKSU3Oyg0PT13fHw1PT13JiZTYShnLkNiJTQwMC0xKSkmJnUrK31yZXR1cm4gaCh1LDIpfSxcIiV3XCI6ZnVuY3Rpb24oZyl7cmV0dXJuIGcuQWJ9LFwiJVdcIjpmdW5jdGlvbihnKXtyZXR1cm4gaChNYXRoLmZsb29yKChnLkJiK1xyXG43LShnLkFiKzYpJTcpLzcpLDIpfSxcIiV5XCI6ZnVuY3Rpb24oZyl7cmV0dXJuKGcuQ2IrMTkwMCkudG9TdHJpbmcoKS5zdWJzdHJpbmcoMil9LFwiJVlcIjpmdW5jdGlvbihnKXtyZXR1cm4gZy5DYisxOTAwfSxcIiV6XCI6ZnVuY3Rpb24oZyl7Zz1nLlliO3ZhciB1PTA8PWc7Zz1NYXRoLmFicyhnKS82MDtyZXR1cm4odT9cIitcIjpcIi1cIikrU3RyaW5nKFwiMDAwMFwiKyhnLzYwKjEwMCtnJTYwKSkuc2xpY2UoLTQpfSxcIiVaXCI6ZnVuY3Rpb24oZyl7cmV0dXJuIGcuYWN9LFwiJSVcIjpmdW5jdGlvbigpe3JldHVyblwiJVwifX07Yz1jLnJlcGxhY2UoLyUlL2csXCJcXHgwMFxceDAwXCIpO2Zvcih4IGluIHQpYy5pbmNsdWRlcyh4KSYmKGM9Yy5yZXBsYWNlKG5ldyBSZWdFeHAoeCxcImdcIiksdFt4XShlKSkpO2M9Yy5yZXBsYWNlKC9cXDBcXDAvZyxcIiVcIik7eD1WYShjKTtpZih4Lmxlbmd0aD5iKXJldHVybiAwO0guc2V0KHgsYT4+PjApO3JldHVybiB4Lmxlbmd0aC0xfVxyXG52YXIgSmI9e2E6ZnVuY3Rpb24oYSl7cmV0dXJuIEphKGErMjQpKzI0fSxtOmZ1bmN0aW9uKGEpe2E9bmV3IFMoYSk7YS5QYigpfHwoYS5JYighMCksUS0tKTthLkpiKCExKTtQLnB1c2goYSk7YS5OYigpO3JldHVybiBhLlFiKCl9LGlhOmZ1bmN0aW9uKGEpe3ooXCJVbmV4cGVjdGVkIGV4Y2VwdGlvbiB0aHJvd24sIHRoaXMgaXMgbm90IHByb3Blcmx5IHN1cHBvcnRlZCAtIGFib3J0aW5nXCIpO0Q9ITA7dGhyb3cgYTt9LHc6ZnVuY3Rpb24oKXtYKDApO3ZhciBhPVAucG9wKCk7aWYoYS5YYigpJiYhYS5MYigpKXt2YXIgYj1hLldiKCk7YiYmVShiKShhLkRiKTtHYShhLkRiKX1SPTB9LGQ6ZnVuY3Rpb24oKXt2YXIgYT1SO2lmKCFhKXJldHVybiBWPTA7dmFyIGI9bmV3IFMoYSk7Yi5GYihhKTt2YXIgYz1iLkViKCk7aWYoIWMpcmV0dXJuIFY9MCxhO2Zvcih2YXIgZT1BcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMpLGY9MDtmPGUubGVuZ3RoO2YrKyl7dmFyIGg9ZVtmXTtcclxuaWYoMD09PWh8fGg9PT1jKWJyZWFrO2lmKFhhKGgsYyxiLnpiKzE2KSlyZXR1cm4gVj1oLGF9Vj1jO3JldHVybiBhfSxrOmZ1bmN0aW9uKCl7dmFyIGE9UjtpZighYSlyZXR1cm4gVj0wO3ZhciBiPW5ldyBTKGEpO2IuRmIoYSk7dmFyIGM9Yi5FYigpO2lmKCFjKXJldHVybiBWPTAsYTtmb3IodmFyIGU9QXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoYXJndW1lbnRzKSxmPTA7ZjxlLmxlbmd0aDtmKyspe3ZhciBoPWVbZl07aWYoMD09PWh8fGg9PT1jKWJyZWFrO2lmKFhhKGgsYyxiLnpiKzE2KSlyZXR1cm4gVj1oLGF9Vj1jO3JldHVybiBhfSxnOmZ1bmN0aW9uKCl7dmFyIGE9UjtpZighYSlyZXR1cm4gVj0wO3ZhciBiPW5ldyBTKGEpO2IuRmIoYSk7dmFyIGM9Yi5FYigpO2lmKCFjKXJldHVybiBWPTAsYTtmb3IodmFyIGU9QXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoYXJndW1lbnRzKSxmPTA7ZjxlLmxlbmd0aDtmKyspe3ZhciBoPWVbZl07aWYoMD09PWh8fGg9PT1jKWJyZWFrO1xyXG5pZihYYShoLGMsYi56YisxNikpcmV0dXJuIFY9aCxhfVY9YztyZXR1cm4gYX0sczpHYSxMOmZ1bmN0aW9uKCl7dmFyIGE9UC5wb3AoKTthfHxCKFwibm8gZXhjZXB0aW9uIHRvIHRocm93XCIpO3ZhciBiPWEuRGI7YS5MYigpfHwoUC5wdXNoKGEpLGEuSmIoITApLGEuSWIoITEpLFErKyk7Uj1iO3Rocm93IGI7fSxiOmZ1bmN0aW9uKGEsYixjKXsobmV3IFMoYSkpLlJiKGIsYyk7Uj1hO1ErKzt0aHJvdyBhO30sbGE6ZnVuY3Rpb24oKXtyZXR1cm4gUX0saTpmdW5jdGlvbihhKXtSfHwoUj1hKTt0aHJvdyBhO30sSDpmdW5jdGlvbigpe3JldHVybiAwfSxCYTpmdW5jdGlvbigpe30scGE6ZnVuY3Rpb24oKXt9LHJhOmZ1bmN0aW9uKCl7fSxrYTpmdW5jdGlvbigpe3JldHVybiAwfSx6YTpmdW5jdGlvbigpe30sdWE6ZnVuY3Rpb24oKXt9LHlhOmZ1bmN0aW9uKCl7fSxSOmZ1bmN0aW9uKCl7fSxxYTpmdW5jdGlvbigpe30sbmE6ZnVuY3Rpb24oKXt9LEFhOmZ1bmN0aW9uKCl7fSxvYTpmdW5jdGlvbigpe30sXHJcbkhhOmZ1bmN0aW9uKCl7fSxKYTpmdW5jdGlvbigpe0IoXCJUbyB1c2UgZGxvcGVuLCB5b3UgbmVlZCBlbmFibGUgZHluYW1pYyBsaW5raW5nLCBzZWUgaHR0cHM6Ly9naXRodWIuY29tL2Vtc2NyaXB0ZW4tY29yZS9lbXNjcmlwdGVuL3dpa2kvTGlua2luZ1wiKX0sSWE6ZnVuY3Rpb24oKXtCKFwiVG8gdXNlIGRsb3BlbiwgeW91IG5lZWQgZW5hYmxlIGR5bmFtaWMgbGlua2luZywgc2VlIGh0dHBzOi8vZ2l0aHViLmNvbS9lbXNjcmlwdGVuLWNvcmUvZW1zY3JpcHRlbi93aWtpL0xpbmtpbmdcIil9LFM6ZnVuY3Rpb24oKXtyZXR1cm4gRGF0ZS5ub3coKX0sQ2E6ZnVuY3Rpb24oKXtyZXR1cm4hMH0sRGE6ZnVuY3Rpb24oYSxiKXthPW5ldyBEYXRlKDFFMyooSlthPj4+Ml0rNDI5NDk2NzI5NipJW2ErND4+PjJdKSk7SVtiPj4yPj4+MF09YS5nZXRVVENTZWNvbmRzKCk7SVtiKzQ+PjI+Pj4wXT1hLmdldFVUQ01pbnV0ZXMoKTtJW2IrOD4+Mj4+PjBdPWEuZ2V0VVRDSG91cnMoKTtJW2IrMTI+PjI+Pj5cclxuMF09YS5nZXRVVENEYXRlKCk7SVtiKzE2Pj4yPj4+MF09YS5nZXRVVENNb250aCgpO0lbYisyMD4+Mj4+PjBdPWEuZ2V0VVRDRnVsbFllYXIoKS0xOTAwO0lbYisyND4+Mj4+PjBdPWEuZ2V0VVRDRGF5KCk7SVtiKzI4Pj4yPj4+MF09KGEuZ2V0VGltZSgpLURhdGUuVVRDKGEuZ2V0VVRDRnVsbFllYXIoKSwwLDEsMCwwLDAsMCkpLzg2NEU1fDB9LEVhOmZ1bmN0aW9uKGEsYil7YT1uZXcgRGF0ZSgxRTMqKEpbYT4+PjJdKzQyOTQ5NjcyOTYqSVthKzQ+Pj4yXSkpO0lbYj4+Mj4+PjBdPWEuZ2V0U2Vjb25kcygpO0lbYis0Pj4yPj4+MF09YS5nZXRNaW51dGVzKCk7SVtiKzg+PjI+Pj4wXT1hLmdldEhvdXJzKCk7SVtiKzEyPj4yPj4+MF09YS5nZXREYXRlKCk7SVtiKzE2Pj4yPj4+MF09YS5nZXRNb250aCgpO0lbYisyMD4+Mj4+PjBdPWEuZ2V0RnVsbFllYXIoKS0xOTAwO0lbYisyND4+Mj4+PjBdPWEuZ2V0RGF5KCk7dmFyIGM9bmV3IERhdGUoYS5nZXRGdWxsWWVhcigpLDAsMSk7SVtiK1xyXG4yOD4+Mj4+PjBdPShhLmdldFRpbWUoKS1jLmdldFRpbWUoKSkvODY0RTV8MDtJW2IrMzY+PjI+Pj4wXT0tKDYwKmEuZ2V0VGltZXpvbmVPZmZzZXQoKSk7dmFyIGU9KG5ldyBEYXRlKGEuZ2V0RnVsbFllYXIoKSw2LDEpKS5nZXRUaW1lem9uZU9mZnNldCgpO2M9Yy5nZXRUaW1lem9uZU9mZnNldCgpO0lbYiszMj4+Mj4+PjBdPShlIT1jJiZhLmdldFRpbWV6b25lT2Zmc2V0KCk9PU1hdGgubWluKGMsZSkpfDB9LEZhOmZ1bmN0aW9uKGEpe3ZhciBiPW5ldyBEYXRlKElbYSsyMD4+Mj4+PjBdKzE5MDAsSVthKzE2Pj4yPj4+MF0sSVthKzEyPj4yPj4+MF0sSVthKzg+PjI+Pj4wXSxJW2ErND4+Mj4+PjBdLElbYT4+Mj4+PjBdLDApLGM9SVthKzMyPj4yPj4+MF0sZT1iLmdldFRpbWV6b25lT2Zmc2V0KCksZj1uZXcgRGF0ZShiLmdldEZ1bGxZZWFyKCksMCwxKSxoPShuZXcgRGF0ZShiLmdldEZ1bGxZZWFyKCksNiwxKSkuZ2V0VGltZXpvbmVPZmZzZXQoKSxrPWYuZ2V0VGltZXpvbmVPZmZzZXQoKSxcclxubD1NYXRoLm1pbihrLGgpOzA+Yz9JW2ErMzI+PjI+Pj4wXT1OdW1iZXIoaCE9ayYmbD09ZSk6MDxjIT0obD09ZSkmJihoPU1hdGgubWF4KGssaCksYi5zZXRUaW1lKGIuZ2V0VGltZSgpKzZFNCooKDA8Yz9sOmgpLWUpKSk7SVthKzI0Pj4yPj4+MF09Yi5nZXREYXkoKTtJW2ErMjg+PjI+Pj4wXT0oYi5nZXRUaW1lKCktZi5nZXRUaW1lKCkpLzg2NEU1fDA7SVthPj4yPj4+MF09Yi5nZXRTZWNvbmRzKCk7SVthKzQ+PjI+Pj4wXT1iLmdldE1pbnV0ZXMoKTtJW2ErOD4+Mj4+PjBdPWIuZ2V0SG91cnMoKTtJW2ErMTI+PjI+Pj4wXT1iLmdldERhdGUoKTtJW2ErMTY+PjI+Pj4wXT1iLmdldE1vbnRoKCk7cmV0dXJuIGIuZ2V0VGltZSgpLzFFM3wwfSxzYTpmdW5jdGlvbigpe3JldHVybi01Mn0sdGE6ZnVuY3Rpb24oKXt9LEdhOkxhLEI6ZnVuY3Rpb24oKXtCKFwiXCIpfSxtYTpmdW5jdGlvbigpe3JldHVybiA0Mjk0OTAxNzYwfSxJOnA/KCk9Pnt2YXIgYT1wcm9jZXNzLmhydGltZSgpO3JldHVybiAxRTMqXHJcbmFbMF0rYVsxXS8xRTZ9OigpPT5wZXJmb3JtYW5jZS5ub3coKSx4YTpmdW5jdGlvbihhLGIsYyl7Ry5jb3B5V2l0aGluKGE+Pj4wLGI+Pj4wLGIrYz4+PjApfSxHOmZ1bmN0aW9uKGEpe3ZhciBiPUcubGVuZ3RoO2E+Pj49MDtpZig0Mjk0OTAxNzYwPGEpcmV0dXJuITE7Zm9yKHZhciBjPTE7ND49YztjKj0yKXt2YXIgZT1iKigxKy4yL2MpO2U9TWF0aC5taW4oZSxhKzEwMDY2MzI5Nik7dmFyIGY9TWF0aDtlPU1hdGgubWF4KGEsZSk7Zj1mLm1pbi5jYWxsKGYsNDI5NDkwMTc2MCxlKyg2NTUzNi1lJTY1NTM2KSU2NTUzNik7YTp7dHJ5e21hLmdyb3coZi1zYS5ieXRlTGVuZ3RoKzY1NTM1Pj4+MTYpO3RhKCk7dmFyIGg9MTticmVhayBhfWNhdGNoKGspe31oPXZvaWQgMH1pZihoKXJldHVybiEwfXJldHVybiExfSx2YTpmdW5jdGlvbihhLGIpe3ZhciBjPTA7TmEoKS5mb3JFYWNoKGZ1bmN0aW9uKGUsZil7dmFyIGg9YitjO2Y9SlthKzQqZj4+Mj4+PjBdPWg7Zm9yKGg9MDtoPGUubGVuZ3RoOysraClIW2YrKz4+XHJcbjA+Pj4wXT1lLmNoYXJDb2RlQXQoaCk7SFtmPj4wPj4+MF09MDtjKz1lLmxlbmd0aCsxfSk7cmV0dXJuIDB9LHdhOmZ1bmN0aW9uKGEsYil7dmFyIGM9TmEoKTtKW2E+PjI+Pj4wXT1jLmxlbmd0aDt2YXIgZT0wO2MuZm9yRWFjaChmdW5jdGlvbihmKXtlKz1mLmxlbmd0aCsxfSk7SltiPj4yPj4+MF09ZTtyZXR1cm4gMH0sYmE6ZnVuY3Rpb24oYSl7bm9FeGl0UnVudGltZXx8MDxrYXx8KFlhKCksTyh4YSksWmEoMCksUGFbMV0ubGVuZ3RoJiZRYSgxLDEwKSxQYVsyXS5sZW5ndGgmJlFhKDIsMTApKTtpZighKG5vRXhpdFJ1bnRpbWV8fDA8a2EpKXtpZihkLm9uRXhpdClkLm9uRXhpdChhKTtEPSEwfWVhKGEsbmV3IGphKGEpKX0sRTpmdW5jdGlvbigpe3JldHVybiA1Mn0sUTpmdW5jdGlvbigpe3JldHVybiA1Mn0sY2E6ZnVuY3Rpb24oKXtyZXR1cm4gNzB9LFA6ZnVuY3Rpb24oYSxiLGMsZSl7Zm9yKHZhciBmPTAsaD0wO2g8YztoKyspe3ZhciBrPUpbYj4+Mj4+PjBdLGw9SltiKzQ+PlxyXG4yPj4+MF07Yis9ODtmb3IodmFyIG49MDtuPGw7bisrKVFhKGEsR1trK24+Pj4wXSk7Zis9bH1KW2U+PjI+Pj4wXT1mO3JldHVybiAwfSxjOmZ1bmN0aW9uKCl7cmV0dXJuIFZ9LGphOlcsZWE6JGEsZmE6YWIsSjpiYixlOmNiLE46ZGIsTzplYixqOmZiLG86Z2IscDpoYixNOmliLHI6amIsdjprYixLOmxiLEQ6bWIsWDpuYixWOm9iLFU6cGIsWjpxYixXOnJiLFk6c2IsVDp0YixmOnViLHE6dmIsaDp3YixkYTp4YixsOnliLHQ6emIsdTpBYix4OkJiLHo6Q2IsZ2E6RGIsQTpFYixDOkZiLGFhOkdiLF86SGIsJDpJYixuOmZ1bmN0aW9uKGEpe3JldHVybiBhfSxGOmZ1bmN0aW9uKGEpe1Y9YX0saGE6V2EseTpmdW5jdGlvbihhLGIsYyxlKXtyZXR1cm4gV2EoYSxiLGMsZSl9fTtcclxuKGZ1bmN0aW9uKCl7ZnVuY3Rpb24gYShmKXtkLmFzbT1mLmV4cG9ydHM7bWE9ZC5hc20uS2E7dGEoKTt1YT1kLmFzbS5pYjt3YS51bnNoaWZ0KGQuYXNtLkxhKTtLLS07ZC5tb25pdG9yUnVuRGVwZW5kZW5jaWVzJiZkLm1vbml0b3JSdW5EZXBlbmRlbmNpZXMoSyk7MD09SyYmKG51bGwhPT1BYSYmKGNsZWFySW50ZXJ2YWwoQWEpLEFhPW51bGwpLEwmJihmPUwsTD1udWxsLGYoKSkpfWZ1bmN0aW9uIGIoZil7YShmLmluc3RhbmNlKX1mdW5jdGlvbiBjKGYpe3JldHVybiBFYSgpLnRoZW4oZnVuY3Rpb24oaCl7cmV0dXJuIFdlYkFzc2VtYmx5Lmluc3RhbnRpYXRlKGgsZSl9KS50aGVuKGZ1bmN0aW9uKGgpe3JldHVybiBofSkudGhlbihmLGZ1bmN0aW9uKGgpe3ooXCJmYWlsZWQgdG8gYXN5bmNocm9ub3VzbHkgcHJlcGFyZSB3YXNtOiBcIitoKTtCKGgpfSl9dmFyIGU9e2E6SmJ9O0srKztkLm1vbml0b3JSdW5EZXBlbmRlbmNpZXMmJmQubW9uaXRvclJ1bkRlcGVuZGVuY2llcyhLKTtpZihkLmluc3RhbnRpYXRlV2FzbSl0cnl7cmV0dXJuIGQuaW5zdGFudGlhdGVXYXNtKGUsXHJcbmEpfWNhdGNoKGYpe3JldHVybiB6KFwiTW9kdWxlLmluc3RhbnRpYXRlV2FzbSBjYWxsYmFjayBmYWlsZWQgd2l0aCBlcnJvcjogXCIrZiksITF9KGZ1bmN0aW9uKCl7cmV0dXJuIEF8fFwiZnVuY3Rpb25cIiE9dHlwZW9mIFdlYkFzc2VtYmx5Lmluc3RhbnRpYXRlU3RyZWFtaW5nfHxCYSgpfHxOLnN0YXJ0c1dpdGgoXCJmaWxlOi8vXCIpfHxwfHxcImZ1bmN0aW9uXCIhPXR5cGVvZiBmZXRjaD9jKGIpOmZldGNoKE4se2NyZWRlbnRpYWxzOlwic2FtZS1vcmlnaW5cIn0pLnRoZW4oZnVuY3Rpb24oZil7cmV0dXJuIFdlYkFzc2VtYmx5Lmluc3RhbnRpYXRlU3RyZWFtaW5nKGYsZSkudGhlbihiLGZ1bmN0aW9uKGgpe3ooXCJ3YXNtIHN0cmVhbWluZyBjb21waWxlIGZhaWxlZDogXCIraCk7eihcImZhbGxpbmcgYmFjayB0byBBcnJheUJ1ZmZlciBpbnN0YW50aWF0aW9uXCIpO3JldHVybiBjKGIpfSl9KX0pKCkuY2F0Y2goYmEpO3JldHVybnt9fSkoKTtcclxuZC5fX193YXNtX2NhbGxfY3RvcnM9ZnVuY3Rpb24oKXtyZXR1cm4oZC5fX193YXNtX2NhbGxfY3RvcnM9ZC5hc20uTGEpLmFwcGx5KG51bGwsYXJndW1lbnRzKX07ZC5fT3J0SW5pdD1mdW5jdGlvbigpe3JldHVybihkLl9PcnRJbml0PWQuYXNtLk1hKS5hcHBseShudWxsLGFyZ3VtZW50cyl9O2QuX09ydENyZWF0ZVNlc3Npb25PcHRpb25zPWZ1bmN0aW9uKCl7cmV0dXJuKGQuX09ydENyZWF0ZVNlc3Npb25PcHRpb25zPWQuYXNtLk5hKS5hcHBseShudWxsLGFyZ3VtZW50cyl9O2QuX09ydEFwcGVuZEV4ZWN1dGlvblByb3ZpZGVyPWZ1bmN0aW9uKCl7cmV0dXJuKGQuX09ydEFwcGVuZEV4ZWN1dGlvblByb3ZpZGVyPWQuYXNtLk9hKS5hcHBseShudWxsLGFyZ3VtZW50cyl9O2QuX09ydEFkZFNlc3Npb25Db25maWdFbnRyeT1mdW5jdGlvbigpe3JldHVybihkLl9PcnRBZGRTZXNzaW9uQ29uZmlnRW50cnk9ZC5hc20uUGEpLmFwcGx5KG51bGwsYXJndW1lbnRzKX07XHJcbmQuX09ydFJlbGVhc2VTZXNzaW9uT3B0aW9ucz1mdW5jdGlvbigpe3JldHVybihkLl9PcnRSZWxlYXNlU2Vzc2lvbk9wdGlvbnM9ZC5hc20uUWEpLmFwcGx5KG51bGwsYXJndW1lbnRzKX07ZC5fT3J0Q3JlYXRlU2Vzc2lvbj1mdW5jdGlvbigpe3JldHVybihkLl9PcnRDcmVhdGVTZXNzaW9uPWQuYXNtLlJhKS5hcHBseShudWxsLGFyZ3VtZW50cyl9O2QuX09ydFJlbGVhc2VTZXNzaW9uPWZ1bmN0aW9uKCl7cmV0dXJuKGQuX09ydFJlbGVhc2VTZXNzaW9uPWQuYXNtLlNhKS5hcHBseShudWxsLGFyZ3VtZW50cyl9O2QuX09ydEdldElucHV0Q291bnQ9ZnVuY3Rpb24oKXtyZXR1cm4oZC5fT3J0R2V0SW5wdXRDb3VudD1kLmFzbS5UYSkuYXBwbHkobnVsbCxhcmd1bWVudHMpfTtkLl9PcnRHZXRPdXRwdXRDb3VudD1mdW5jdGlvbigpe3JldHVybihkLl9PcnRHZXRPdXRwdXRDb3VudD1kLmFzbS5VYSkuYXBwbHkobnVsbCxhcmd1bWVudHMpfTtcclxuZC5fT3J0R2V0SW5wdXROYW1lPWZ1bmN0aW9uKCl7cmV0dXJuKGQuX09ydEdldElucHV0TmFtZT1kLmFzbS5WYSkuYXBwbHkobnVsbCxhcmd1bWVudHMpfTtkLl9PcnRHZXRPdXRwdXROYW1lPWZ1bmN0aW9uKCl7cmV0dXJuKGQuX09ydEdldE91dHB1dE5hbWU9ZC5hc20uV2EpLmFwcGx5KG51bGwsYXJndW1lbnRzKX07ZC5fT3J0RnJlZT1mdW5jdGlvbigpe3JldHVybihkLl9PcnRGcmVlPWQuYXNtLlhhKS5hcHBseShudWxsLGFyZ3VtZW50cyl9O2QuX09ydENyZWF0ZVRlbnNvcj1mdW5jdGlvbigpe3JldHVybihkLl9PcnRDcmVhdGVUZW5zb3I9ZC5hc20uWWEpLmFwcGx5KG51bGwsYXJndW1lbnRzKX07ZC5fT3J0R2V0VGVuc29yRGF0YT1mdW5jdGlvbigpe3JldHVybihkLl9PcnRHZXRUZW5zb3JEYXRhPWQuYXNtLlphKS5hcHBseShudWxsLGFyZ3VtZW50cyl9O1xyXG5kLl9PcnRSZWxlYXNlVGVuc29yPWZ1bmN0aW9uKCl7cmV0dXJuKGQuX09ydFJlbGVhc2VUZW5zb3I9ZC5hc20uX2EpLmFwcGx5KG51bGwsYXJndW1lbnRzKX07ZC5fT3J0Q3JlYXRlUnVuT3B0aW9ucz1mdW5jdGlvbigpe3JldHVybihkLl9PcnRDcmVhdGVSdW5PcHRpb25zPWQuYXNtLiRhKS5hcHBseShudWxsLGFyZ3VtZW50cyl9O2QuX09ydEFkZFJ1bkNvbmZpZ0VudHJ5PWZ1bmN0aW9uKCl7cmV0dXJuKGQuX09ydEFkZFJ1bkNvbmZpZ0VudHJ5PWQuYXNtLmFiKS5hcHBseShudWxsLGFyZ3VtZW50cyl9O2QuX09ydFJlbGVhc2VSdW5PcHRpb25zPWZ1bmN0aW9uKCl7cmV0dXJuKGQuX09ydFJlbGVhc2VSdW5PcHRpb25zPWQuYXNtLmJiKS5hcHBseShudWxsLGFyZ3VtZW50cyl9O2QuX09ydFJ1bj1mdW5jdGlvbigpe3JldHVybihkLl9PcnRSdW49ZC5hc20uY2IpLmFwcGx5KG51bGwsYXJndW1lbnRzKX07XHJcbmQuX09ydEVuZFByb2ZpbGluZz1mdW5jdGlvbigpe3JldHVybihkLl9PcnRFbmRQcm9maWxpbmc9ZC5hc20uZGIpLmFwcGx5KG51bGwsYXJndW1lbnRzKX07XHJcbnZhciBKYT1kLl9tYWxsb2M9ZnVuY3Rpb24oKXtyZXR1cm4oSmE9ZC5fbWFsbG9jPWQuYXNtLmViKS5hcHBseShudWxsLGFyZ3VtZW50cyl9LEhhPWQuX2ZyZWU9ZnVuY3Rpb24oKXtyZXR1cm4oSGE9ZC5fZnJlZT1kLmFzbS5mYikuYXBwbHkobnVsbCxhcmd1bWVudHMpfSxaYT1kLl9mZmx1c2g9ZnVuY3Rpb24oKXtyZXR1cm4oWmE9ZC5fZmZsdXNoPWQuYXNtLmdiKS5hcHBseShudWxsLGFyZ3VtZW50cyl9LFlhPWQuX19fZnVuY3Nfb25fZXhpdD1mdW5jdGlvbigpe3JldHVybihZYT1kLl9fX2Z1bmNzX29uX2V4aXQ9ZC5hc20uaGIpLmFwcGx5KG51bGwsYXJndW1lbnRzKX0sWD1kLl9zZXRUaHJldz1mdW5jdGlvbigpe3JldHVybihYPWQuX3NldFRocmV3PWQuYXNtLmpiKS5hcHBseShudWxsLGFyZ3VtZW50cyl9LFk9ZC5zdGFja1NhdmU9ZnVuY3Rpb24oKXtyZXR1cm4oWT1kLnN0YWNrU2F2ZT1kLmFzbS5rYikuYXBwbHkobnVsbCxhcmd1bWVudHMpfSxaPWQuc3RhY2tSZXN0b3JlPVxyXG5mdW5jdGlvbigpe3JldHVybihaPWQuc3RhY2tSZXN0b3JlPWQuYXNtLmxiKS5hcHBseShudWxsLGFyZ3VtZW50cyl9LEtiPWQuc3RhY2tBbGxvYz1mdW5jdGlvbigpe3JldHVybihLYj1kLnN0YWNrQWxsb2M9ZC5hc20ubWIpLmFwcGx5KG51bGwsYXJndW1lbnRzKX0sWGE9ZC5fX19jeGFfY2FuX2NhdGNoPWZ1bmN0aW9uKCl7cmV0dXJuKFhhPWQuX19fY3hhX2Nhbl9jYXRjaD1kLmFzbS5uYikuYXBwbHkobnVsbCxhcmd1bWVudHMpfSxGYT1kLl9fX2N4YV9pc19wb2ludGVyX3R5cGU9ZnVuY3Rpb24oKXtyZXR1cm4oRmE9ZC5fX19jeGFfaXNfcG9pbnRlcl90eXBlPWQuYXNtLm9iKS5hcHBseShudWxsLGFyZ3VtZW50cyl9LExiPWQuZHluQ2FsbF9qPWZ1bmN0aW9uKCl7cmV0dXJuKExiPWQuZHluQ2FsbF9qPWQuYXNtLnBiKS5hcHBseShudWxsLGFyZ3VtZW50cyl9LE1iPWQuZHluQ2FsbF9paWlpaWo9ZnVuY3Rpb24oKXtyZXR1cm4oTWI9ZC5keW5DYWxsX2lpaWlpaj1kLmFzbS5xYikuYXBwbHkobnVsbCxcclxuYXJndW1lbnRzKX0sTmI9ZC5keW5DYWxsX2ppaT1mdW5jdGlvbigpe3JldHVybihOYj1kLmR5bkNhbGxfamlpPWQuYXNtLnJiKS5hcHBseShudWxsLGFyZ3VtZW50cyl9LE9iPWQuZHluQ2FsbF92aWlpaWlqPWZ1bmN0aW9uKCl7cmV0dXJuKE9iPWQuZHluQ2FsbF92aWlpaWlqPWQuYXNtLnNiKS5hcHBseShudWxsLGFyZ3VtZW50cyl9LFBiPWQuZHluQ2FsbF92amppPWZ1bmN0aW9uKCl7cmV0dXJuKFBiPWQuZHluQ2FsbF92amppPWQuYXNtLnRiKS5hcHBseShudWxsLGFyZ3VtZW50cyl9LFFiPWQuZHluQ2FsbF92aWlpampqaWk9ZnVuY3Rpb24oKXtyZXR1cm4oUWI9ZC5keW5DYWxsX3ZpaWlqamppaT1kLmFzbS51YikuYXBwbHkobnVsbCxhcmd1bWVudHMpfSxSYj1kLmR5bkNhbGxfaWlqPWZ1bmN0aW9uKCl7cmV0dXJuKFJiPWQuZHluQ2FsbF9paWo9ZC5hc20udmIpLmFwcGx5KG51bGwsYXJndW1lbnRzKX0sU2I9ZC5keW5DYWxsX2ppPWZ1bmN0aW9uKCl7cmV0dXJuKFNiPWQuZHluQ2FsbF9qaT1cclxuZC5hc20ud2IpLmFwcGx5KG51bGwsYXJndW1lbnRzKX0sVGI9ZC5keW5DYWxsX2lpaWlpaWo9ZnVuY3Rpb24oKXtyZXR1cm4oVGI9ZC5keW5DYWxsX2lpaWlpaWo9ZC5hc20ueGIpLmFwcGx5KG51bGwsYXJndW1lbnRzKX0sVWI9ZC5keW5DYWxsX2lpaWo9ZnVuY3Rpb24oKXtyZXR1cm4oVWI9ZC5keW5DYWxsX2lpaWo9ZC5hc20ueWIpLmFwcGx5KG51bGwsYXJndW1lbnRzKX07ZnVuY3Rpb24gY2IoYSxiKXt2YXIgYz1ZKCk7dHJ5e3JldHVybiBVKGEpKGIpfWNhdGNoKGUpe1ooYyk7aWYoZSE9PWUrMCl0aHJvdyBlO1goMSwwKX19ZnVuY3Rpb24gdmIoYSxiKXt2YXIgYz1ZKCk7dHJ5e1UoYSkoYil9Y2F0Y2goZSl7WihjKTtpZihlIT09ZSswKXRocm93IGU7WCgxLDApfX1mdW5jdGlvbiB3YihhLGIsYyl7dmFyIGU9WSgpO3RyeXtVKGEpKGIsYyl9Y2F0Y2goZil7WihlKTtpZihmIT09ZiswKXRocm93IGY7WCgxLDApfX1cclxuZnVuY3Rpb24gZmIoYSxiLGMpe3ZhciBlPVkoKTt0cnl7cmV0dXJuIFUoYSkoYixjKX1jYXRjaChmKXtaKGUpO2lmKGYhPT1mKzApdGhyb3cgZjtYKDEsMCl9fWZ1bmN0aW9uIGdiKGEsYixjLGUpe3ZhciBmPVkoKTt0cnl7cmV0dXJuIFUoYSkoYixjLGUpfWNhdGNoKGgpe1ooZik7aWYoaCE9PWgrMCl0aHJvdyBoO1goMSwwKX19ZnVuY3Rpb24ga2IoYSxiLGMsZSxmLGgsayl7dmFyIGw9WSgpO3RyeXtyZXR1cm4gVShhKShiLGMsZSxmLGgsayl9Y2F0Y2gobil7WihsKTtpZihuIT09biswKXRocm93IG47WCgxLDApfX1mdW5jdGlvbiB1YihhKXt2YXIgYj1ZKCk7dHJ5e1UoYSkoKX1jYXRjaChjKXtaKGIpO2lmKGMhPT1jKzApdGhyb3cgYztYKDEsMCl9fWZ1bmN0aW9uIGpiKGEsYixjLGUsZixoKXt2YXIgaz1ZKCk7dHJ5e3JldHVybiBVKGEpKGIsYyxlLGYsaCl9Y2F0Y2gobCl7WihrKTtpZihsIT09bCswKXRocm93IGw7WCgxLDApfX1cclxuZnVuY3Rpb24gaGIoYSxiLGMsZSxmKXt2YXIgaD1ZKCk7dHJ5e3JldHVybiBVKGEpKGIsYyxlLGYpfWNhdGNoKGspe1ooaCk7aWYoayE9PWsrMCl0aHJvdyBrO1goMSwwKX19ZnVuY3Rpb24geWIoYSxiLGMsZSl7dmFyIGY9WSgpO3RyeXtVKGEpKGIsYyxlKX1jYXRjaChoKXtaKGYpO2lmKGghPT1oKzApdGhyb3cgaDtYKDEsMCl9fWZ1bmN0aW9uIEFiKGEsYixjLGUsZixoKXt2YXIgaz1ZKCk7dHJ5e1UoYSkoYixjLGUsZixoKX1jYXRjaChsKXtaKGspO2lmKGwhPT1sKzApdGhyb3cgbDtYKDEsMCl9fWZ1bmN0aW9uIHpiKGEsYixjLGUsZil7dmFyIGg9WSgpO3RyeXtVKGEpKGIsYyxlLGYpfWNhdGNoKGspe1ooaCk7aWYoayE9PWsrMCl0aHJvdyBrO1goMSwwKX19ZnVuY3Rpb24gQmIoYSxiLGMsZSxmLGgsayl7dmFyIGw9WSgpO3RyeXtVKGEpKGIsYyxlLGYsaCxrKX1jYXRjaChuKXtaKGwpO2lmKG4hPT1uKzApdGhyb3cgbjtYKDEsMCl9fVxyXG5mdW5jdGlvbiBDYihhLGIsYyxlLGYsaCxrLGwpe3ZhciBuPVkoKTt0cnl7VShhKShiLGMsZSxmLGgsayxsKX1jYXRjaCh0KXtaKG4pO2lmKHQhPT10KzApdGhyb3cgdDtYKDEsMCl9fWZ1bmN0aW9uIGViKGEsYixjKXt2YXIgZT1ZKCk7dHJ5e3JldHVybiBVKGEpKGIsYyl9Y2F0Y2goZil7WihlKTtpZihmIT09ZiswKXRocm93IGY7WCgxLDApfX1mdW5jdGlvbiBkYihhLGIsYyl7dmFyIGU9WSgpO3RyeXtyZXR1cm4gVShhKShiLGMpfWNhdGNoKGYpe1ooZSk7aWYoZiE9PWYrMCl0aHJvdyBmO1goMSwwKX19ZnVuY3Rpb24gRGIoYSxiLGMsZSxmLGgsayxsLG4pe3ZhciB0PVkoKTt0cnl7VShhKShiLGMsZSxmLGgsayxsLG4pfWNhdGNoKHgpe1oodCk7aWYoeCE9PXgrMCl0aHJvdyB4O1goMSwwKX19ZnVuY3Rpb24gaWIoYSxiLGMsZSxmLGgpe3ZhciBrPVkoKTt0cnl7cmV0dXJuIFUoYSkoYixjLGUsZixoKX1jYXRjaChsKXtaKGspO2lmKGwhPT1sKzApdGhyb3cgbDtYKDEsMCl9fVxyXG5mdW5jdGlvbiBsYihhLGIsYyxlLGYsaCxrLGwpe3ZhciBuPVkoKTt0cnl7cmV0dXJuIFUoYSkoYixjLGUsZixoLGssbCl9Y2F0Y2godCl7WihuKTtpZih0IT09dCswKXRocm93IHQ7WCgxLDApfX1mdW5jdGlvbiBtYihhLGIsYyxlLGYsaCxrLGwsbix0LHgsRSl7dmFyIEM9WSgpO3RyeXtyZXR1cm4gVShhKShiLGMsZSxmLGgsayxsLG4sdCx4LEUpfWNhdGNoKGcpe1ooQyk7aWYoZyE9PWcrMCl0aHJvdyBnO1goMSwwKX19ZnVuY3Rpb24gRWIoYSxiLGMsZSxmLGgsayxsLG4sdCx4KXt2YXIgRT1ZKCk7dHJ5e1UoYSkoYixjLGUsZixoLGssbCxuLHQseCl9Y2F0Y2goQyl7WihFKTtpZihDIT09QyswKXRocm93IEM7WCgxLDApfX1mdW5jdGlvbiBGYihhLGIsYyxlLGYsaCxrLGwsbix0LHgsRSxDLGcsdSx3KXt2YXIgRj1ZKCk7dHJ5e1UoYSkoYixjLGUsZixoLGssbCxuLHQseCxFLEMsZyx1LHcpfWNhdGNoKE0pe1ooRik7aWYoTSE9PU0rMCl0aHJvdyBNO1goMSwwKX19XHJcbmZ1bmN0aW9uIGJiKGEpe3ZhciBiPVkoKTt0cnl7cmV0dXJuIFUoYSkoKX1jYXRjaChjKXtaKGIpO2lmKGMhPT1jKzApdGhyb3cgYztYKDEsMCl9fWZ1bmN0aW9uIGFiKGEsYixjKXt2YXIgZT1ZKCk7dHJ5e3JldHVybiBVKGEpKGIsYyl9Y2F0Y2goZil7WihlKTtpZihmIT09ZiswKXRocm93IGY7WCgxLDApfX1mdW5jdGlvbiAkYShhLGIsYyl7dmFyIGU9WSgpO3RyeXtyZXR1cm4gVShhKShiLGMpfWNhdGNoKGYpe1ooZSk7aWYoZiE9PWYrMCl0aHJvdyBmO1goMSwwKX19ZnVuY3Rpb24geGIoYSxiLGMsZSl7dmFyIGY9WSgpO3RyeXtVKGEpKGIsYyxlKX1jYXRjaChoKXtaKGYpO2lmKGghPT1oKzApdGhyb3cgaDtYKDEsMCl9fWZ1bmN0aW9uIEdiKGEsYixjLGUsZixoLGssbCl7dmFyIG49WSgpO3RyeXtPYihhLGIsYyxlLGYsaCxrLGwpfWNhdGNoKHQpe1oobik7aWYodCE9PXQrMCl0aHJvdyB0O1goMSwwKX19XHJcbmZ1bmN0aW9uIEliKGEsYixjLGUsZixoKXt2YXIgaz1ZKCk7dHJ5e1BiKGEsYixjLGUsZixoKX1jYXRjaChsKXtaKGspO2lmKGwhPT1sKzApdGhyb3cgbDtYKDEsMCl9fWZ1bmN0aW9uIEhiKGEsYixjLGUsZixoLGssbCxuLHQseCxFKXt2YXIgQz1ZKCk7dHJ5e1FiKGEsYixjLGUsZixoLGssbCxuLHQseCxFKX1jYXRjaChnKXtaKEMpO2lmKGchPT1nKzApdGhyb3cgZztYKDEsMCl9fWZ1bmN0aW9uIHFiKGEsYixjLGUpe3ZhciBmPVkoKTt0cnl7cmV0dXJuIFJiKGEsYixjLGUpfWNhdGNoKGgpe1ooZik7aWYoaCE9PWgrMCl0aHJvdyBoO1goMSwwKX19ZnVuY3Rpb24gc2IoYSxiKXt2YXIgYz1ZKCk7dHJ5e3JldHVybiBTYihhLGIpfWNhdGNoKGUpe1ooYyk7aWYoZSE9PWUrMCl0aHJvdyBlO1goMSwwKX19XHJcbmZ1bmN0aW9uIG5iKGEsYixjLGUsZixoLGssbCl7dmFyIG49WSgpO3RyeXtyZXR1cm4gVGIoYSxiLGMsZSxmLGgsayxsKX1jYXRjaCh0KXtaKG4pO2lmKHQhPT10KzApdGhyb3cgdDtYKDEsMCl9fWZ1bmN0aW9uIHJiKGEpe3ZhciBiPVkoKTt0cnl7cmV0dXJuIExiKGEpfWNhdGNoKGMpe1ooYik7aWYoYyE9PWMrMCl0aHJvdyBjO1goMSwwKX19ZnVuY3Rpb24gb2IoYSxiLGMsZSxmLGgsayl7dmFyIGw9WSgpO3RyeXtyZXR1cm4gTWIoYSxiLGMsZSxmLGgsayl9Y2F0Y2gobil7WihsKTtpZihuIT09biswKXRocm93IG47WCgxLDApfX1mdW5jdGlvbiBwYihhLGIsYyxlLGYpe3ZhciBoPVkoKTt0cnl7cmV0dXJuIFViKGEsYixjLGUsZil9Y2F0Y2goayl7WihoKTtpZihrIT09ayswKXRocm93IGs7WCgxLDApfX1mdW5jdGlvbiB0YihhLGIsYyl7dmFyIGU9WSgpO3RyeXtyZXR1cm4gTmIoYSxiLGMpfWNhdGNoKGYpe1ooZSk7aWYoZiE9PWYrMCl0aHJvdyBmO1goMSwwKX19XHJcbmQuVVRGOFRvU3RyaW5nPXBhO2Quc3RyaW5nVG9VVEY4PWZ1bmN0aW9uKGEsYixjKXtyZXR1cm4gcWEoYSxHLGIsYyl9O2QubGVuZ3RoQnl0ZXNVVEY4PXJhO2Quc3RhY2tTYXZlPVk7ZC5zdGFja1Jlc3RvcmU9WjtkLnN0YWNrQWxsb2M9S2I7dmFyIFZiO0w9ZnVuY3Rpb24gV2IoKXtWYnx8WGIoKTtWYnx8KEw9V2IpfTtcclxuZnVuY3Rpb24gWGIoKXtmdW5jdGlvbiBhKCl7aWYoIVZiJiYoVmI9ITAsZC5jYWxsZWRSdW49ITAsIUQpKXtPKHdhKTthYShkKTtpZihkLm9uUnVudGltZUluaXRpYWxpemVkKWQub25SdW50aW1lSW5pdGlhbGl6ZWQoKTtpZihkLnBvc3RSdW4pZm9yKFwiZnVuY3Rpb25cIj09dHlwZW9mIGQucG9zdFJ1biYmKGQucG9zdFJ1bj1bZC5wb3N0UnVuXSk7ZC5wb3N0UnVuLmxlbmd0aDspe3ZhciBiPWQucG9zdFJ1bi5zaGlmdCgpO3lhLnVuc2hpZnQoYil9Tyh5YSl9fWlmKCEoMDxLKSl7aWYoZC5wcmVSdW4pZm9yKFwiZnVuY3Rpb25cIj09dHlwZW9mIGQucHJlUnVuJiYoZC5wcmVSdW49W2QucHJlUnVuXSk7ZC5wcmVSdW4ubGVuZ3RoOyl6YSgpO08odmEpOzA8S3x8KGQuc2V0U3RhdHVzPyhkLnNldFN0YXR1cyhcIlJ1bm5pbmcuLi5cIiksc2V0VGltZW91dChmdW5jdGlvbigpe3NldFRpbWVvdXQoZnVuY3Rpb24oKXtkLnNldFN0YXR1cyhcIlwiKX0sMSk7YSgpfSwxKSk6YSgpKX19XHJcbmlmKGQucHJlSW5pdClmb3IoXCJmdW5jdGlvblwiPT10eXBlb2YgZC5wcmVJbml0JiYoZC5wcmVJbml0PVtkLnByZUluaXRdKTswPGQucHJlSW5pdC5sZW5ndGg7KWQucHJlSW5pdC5wb3AoKSgpO1hiKCk7XHJcblxyXG5cclxuICByZXR1cm4gb3J0V2FzbS5yZWFkeVxyXG59XHJcbik7XHJcbn0pKCk7XHJcbmlmICh0eXBlb2YgZXhwb3J0cyA9PT0gJ29iamVjdCcgJiYgdHlwZW9mIG1vZHVsZSA9PT0gJ29iamVjdCcpXHJcbiAgbW9kdWxlLmV4cG9ydHMgPSBvcnRXYXNtO1xyXG5lbHNlIGlmICh0eXBlb2YgZGVmaW5lID09PSAnZnVuY3Rpb24nICYmIGRlZmluZVsnYW1kJ10pXHJcbiAgZGVmaW5lKFtdLCBmdW5jdGlvbigpIHsgcmV0dXJuIG9ydFdhc207IH0pO1xyXG5lbHNlIGlmICh0eXBlb2YgZXhwb3J0cyA9PT0gJ29iamVjdCcpXHJcbiAgZXhwb3J0c1tcIm9ydFdhc21cIl0gPSBvcnRXYXNtO1xyXG4iLCJcInVzZSBzdHJpY3RcIjtcclxubW9kdWxlLmV4cG9ydHMgPSBhc1Byb21pc2U7XHJcblxyXG4vKipcclxuICogQ2FsbGJhY2sgYXMgdXNlZCBieSB7QGxpbmsgdXRpbC5hc1Byb21pc2V9LlxyXG4gKiBAdHlwZWRlZiBhc1Byb21pc2VDYWxsYmFja1xyXG4gKiBAdHlwZSB7ZnVuY3Rpb259XHJcbiAqIEBwYXJhbSB7RXJyb3J8bnVsbH0gZXJyb3IgRXJyb3IsIGlmIGFueVxyXG4gKiBAcGFyYW0gey4uLip9IHBhcmFtcyBBZGRpdGlvbmFsIGFyZ3VtZW50c1xyXG4gKiBAcmV0dXJucyB7dW5kZWZpbmVkfVxyXG4gKi9cclxuXHJcbi8qKlxyXG4gKiBSZXR1cm5zIGEgcHJvbWlzZSBmcm9tIGEgbm9kZS1zdHlsZSBjYWxsYmFjayBmdW5jdGlvbi5cclxuICogQG1lbWJlcm9mIHV0aWxcclxuICogQHBhcmFtIHthc1Byb21pc2VDYWxsYmFja30gZm4gRnVuY3Rpb24gdG8gY2FsbFxyXG4gKiBAcGFyYW0geyp9IGN0eCBGdW5jdGlvbiBjb250ZXh0XHJcbiAqIEBwYXJhbSB7Li4uKn0gcGFyYW1zIEZ1bmN0aW9uIGFyZ3VtZW50c1xyXG4gKiBAcmV0dXJucyB7UHJvbWlzZTwqPn0gUHJvbWlzaWZpZWQgZnVuY3Rpb25cclxuICovXHJcbmZ1bmN0aW9uIGFzUHJvbWlzZShmbiwgY3R4LyosIHZhcmFyZ3MgKi8pIHtcclxuICAgIHZhciBwYXJhbXMgID0gbmV3IEFycmF5KGFyZ3VtZW50cy5sZW5ndGggLSAxKSxcclxuICAgICAgICBvZmZzZXQgID0gMCxcclxuICAgICAgICBpbmRleCAgID0gMixcclxuICAgICAgICBwZW5kaW5nID0gdHJ1ZTtcclxuICAgIHdoaWxlIChpbmRleCA8IGFyZ3VtZW50cy5sZW5ndGgpXHJcbiAgICAgICAgcGFyYW1zW29mZnNldCsrXSA9IGFyZ3VtZW50c1tpbmRleCsrXTtcclxuICAgIHJldHVybiBuZXcgUHJvbWlzZShmdW5jdGlvbiBleGVjdXRvcihyZXNvbHZlLCByZWplY3QpIHtcclxuICAgICAgICBwYXJhbXNbb2Zmc2V0XSA9IGZ1bmN0aW9uIGNhbGxiYWNrKGVyci8qLCB2YXJhcmdzICovKSB7XHJcbiAgICAgICAgICAgIGlmIChwZW5kaW5nKSB7XHJcbiAgICAgICAgICAgICAgICBwZW5kaW5nID0gZmFsc2U7XHJcbiAgICAgICAgICAgICAgICBpZiAoZXJyKVxyXG4gICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnIpO1xyXG4gICAgICAgICAgICAgICAgZWxzZSB7XHJcbiAgICAgICAgICAgICAgICAgICAgdmFyIHBhcmFtcyA9IG5ldyBBcnJheShhcmd1bWVudHMubGVuZ3RoIC0gMSksXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIG9mZnNldCA9IDA7XHJcbiAgICAgICAgICAgICAgICAgICAgd2hpbGUgKG9mZnNldCA8IHBhcmFtcy5sZW5ndGgpXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHBhcmFtc1tvZmZzZXQrK10gPSBhcmd1bWVudHNbb2Zmc2V0XTtcclxuICAgICAgICAgICAgICAgICAgICByZXNvbHZlLmFwcGx5KG51bGwsIHBhcmFtcyk7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9O1xyXG4gICAgICAgIHRyeSB7XHJcbiAgICAgICAgICAgIGZuLmFwcGx5KGN0eCB8fCBudWxsLCBwYXJhbXMpO1xyXG4gICAgICAgIH0gY2F0Y2ggKGVycikge1xyXG4gICAgICAgICAgICBpZiAocGVuZGluZykge1xyXG4gICAgICAgICAgICAgICAgcGVuZGluZyA9IGZhbHNlO1xyXG4gICAgICAgICAgICAgICAgcmVqZWN0KGVycik7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICB9KTtcclxufVxyXG4iLCJcInVzZSBzdHJpY3RcIjtcclxuXHJcbi8qKlxyXG4gKiBBIG1pbmltYWwgYmFzZTY0IGltcGxlbWVudGF0aW9uIGZvciBudW1iZXIgYXJyYXlzLlxyXG4gKiBAbWVtYmVyb2YgdXRpbFxyXG4gKiBAbmFtZXNwYWNlXHJcbiAqL1xyXG52YXIgYmFzZTY0ID0gZXhwb3J0cztcclxuXHJcbi8qKlxyXG4gKiBDYWxjdWxhdGVzIHRoZSBieXRlIGxlbmd0aCBvZiBhIGJhc2U2NCBlbmNvZGVkIHN0cmluZy5cclxuICogQHBhcmFtIHtzdHJpbmd9IHN0cmluZyBCYXNlNjQgZW5jb2RlZCBzdHJpbmdcclxuICogQHJldHVybnMge251bWJlcn0gQnl0ZSBsZW5ndGhcclxuICovXHJcbmJhc2U2NC5sZW5ndGggPSBmdW5jdGlvbiBsZW5ndGgoc3RyaW5nKSB7XHJcbiAgICB2YXIgcCA9IHN0cmluZy5sZW5ndGg7XHJcbiAgICBpZiAoIXApXHJcbiAgICAgICAgcmV0dXJuIDA7XHJcbiAgICB2YXIgbiA9IDA7XHJcbiAgICB3aGlsZSAoLS1wICUgNCA+IDEgJiYgc3RyaW5nLmNoYXJBdChwKSA9PT0gXCI9XCIpXHJcbiAgICAgICAgKytuO1xyXG4gICAgcmV0dXJuIE1hdGguY2VpbChzdHJpbmcubGVuZ3RoICogMykgLyA0IC0gbjtcclxufTtcclxuXHJcbi8vIEJhc2U2NCBlbmNvZGluZyB0YWJsZVxyXG52YXIgYjY0ID0gbmV3IEFycmF5KDY0KTtcclxuXHJcbi8vIEJhc2U2NCBkZWNvZGluZyB0YWJsZVxyXG52YXIgczY0ID0gbmV3IEFycmF5KDEyMyk7XHJcblxyXG4vLyA2NS4uOTAsIDk3Li4xMjIsIDQ4Li41NywgNDMsIDQ3XHJcbmZvciAodmFyIGkgPSAwOyBpIDwgNjQ7KVxyXG4gICAgczY0W2I2NFtpXSA9IGkgPCAyNiA/IGkgKyA2NSA6IGkgPCA1MiA/IGkgKyA3MSA6IGkgPCA2MiA/IGkgLSA0IDogaSAtIDU5IHwgNDNdID0gaSsrO1xyXG5cclxuLyoqXHJcbiAqIEVuY29kZXMgYSBidWZmZXIgdG8gYSBiYXNlNjQgZW5jb2RlZCBzdHJpbmcuXHJcbiAqIEBwYXJhbSB7VWludDhBcnJheX0gYnVmZmVyIFNvdXJjZSBidWZmZXJcclxuICogQHBhcmFtIHtudW1iZXJ9IHN0YXJ0IFNvdXJjZSBzdGFydFxyXG4gKiBAcGFyYW0ge251bWJlcn0gZW5kIFNvdXJjZSBlbmRcclxuICogQHJldHVybnMge3N0cmluZ30gQmFzZTY0IGVuY29kZWQgc3RyaW5nXHJcbiAqL1xyXG5iYXNlNjQuZW5jb2RlID0gZnVuY3Rpb24gZW5jb2RlKGJ1ZmZlciwgc3RhcnQsIGVuZCkge1xyXG4gICAgdmFyIHBhcnRzID0gbnVsbCxcclxuICAgICAgICBjaHVuayA9IFtdO1xyXG4gICAgdmFyIGkgPSAwLCAvLyBvdXRwdXQgaW5kZXhcclxuICAgICAgICBqID0gMCwgLy8gZ290byBpbmRleFxyXG4gICAgICAgIHQ7ICAgICAvLyB0ZW1wb3JhcnlcclxuICAgIHdoaWxlIChzdGFydCA8IGVuZCkge1xyXG4gICAgICAgIHZhciBiID0gYnVmZmVyW3N0YXJ0KytdO1xyXG4gICAgICAgIHN3aXRjaCAoaikge1xyXG4gICAgICAgICAgICBjYXNlIDA6XHJcbiAgICAgICAgICAgICAgICBjaHVua1tpKytdID0gYjY0W2IgPj4gMl07XHJcbiAgICAgICAgICAgICAgICB0ID0gKGIgJiAzKSA8PCA0O1xyXG4gICAgICAgICAgICAgICAgaiA9IDE7XHJcbiAgICAgICAgICAgICAgICBicmVhaztcclxuICAgICAgICAgICAgY2FzZSAxOlxyXG4gICAgICAgICAgICAgICAgY2h1bmtbaSsrXSA9IGI2NFt0IHwgYiA+PiA0XTtcclxuICAgICAgICAgICAgICAgIHQgPSAoYiAmIDE1KSA8PCAyO1xyXG4gICAgICAgICAgICAgICAgaiA9IDI7XHJcbiAgICAgICAgICAgICAgICBicmVhaztcclxuICAgICAgICAgICAgY2FzZSAyOlxyXG4gICAgICAgICAgICAgICAgY2h1bmtbaSsrXSA9IGI2NFt0IHwgYiA+PiA2XTtcclxuICAgICAgICAgICAgICAgIGNodW5rW2krK10gPSBiNjRbYiAmIDYzXTtcclxuICAgICAgICAgICAgICAgIGogPSAwO1xyXG4gICAgICAgICAgICAgICAgYnJlYWs7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGlmIChpID4gODE5MSkge1xyXG4gICAgICAgICAgICAocGFydHMgfHwgKHBhcnRzID0gW10pKS5wdXNoKFN0cmluZy5mcm9tQ2hhckNvZGUuYXBwbHkoU3RyaW5nLCBjaHVuaykpO1xyXG4gICAgICAgICAgICBpID0gMDtcclxuICAgICAgICB9XHJcbiAgICB9XHJcbiAgICBpZiAoaikge1xyXG4gICAgICAgIGNodW5rW2krK10gPSBiNjRbdF07XHJcbiAgICAgICAgY2h1bmtbaSsrXSA9IDYxO1xyXG4gICAgICAgIGlmIChqID09PSAxKVxyXG4gICAgICAgICAgICBjaHVua1tpKytdID0gNjE7XHJcbiAgICB9XHJcbiAgICBpZiAocGFydHMpIHtcclxuICAgICAgICBpZiAoaSlcclxuICAgICAgICAgICAgcGFydHMucHVzaChTdHJpbmcuZnJvbUNoYXJDb2RlLmFwcGx5KFN0cmluZywgY2h1bmsuc2xpY2UoMCwgaSkpKTtcclxuICAgICAgICByZXR1cm4gcGFydHMuam9pbihcIlwiKTtcclxuICAgIH1cclxuICAgIHJldHVybiBTdHJpbmcuZnJvbUNoYXJDb2RlLmFwcGx5KFN0cmluZywgY2h1bmsuc2xpY2UoMCwgaSkpO1xyXG59O1xyXG5cclxudmFyIGludmFsaWRFbmNvZGluZyA9IFwiaW52YWxpZCBlbmNvZGluZ1wiO1xyXG5cclxuLyoqXHJcbiAqIERlY29kZXMgYSBiYXNlNjQgZW5jb2RlZCBzdHJpbmcgdG8gYSBidWZmZXIuXHJcbiAqIEBwYXJhbSB7c3RyaW5nfSBzdHJpbmcgU291cmNlIHN0cmluZ1xyXG4gKiBAcGFyYW0ge1VpbnQ4QXJyYXl9IGJ1ZmZlciBEZXN0aW5hdGlvbiBidWZmZXJcclxuICogQHBhcmFtIHtudW1iZXJ9IG9mZnNldCBEZXN0aW5hdGlvbiBvZmZzZXRcclxuICogQHJldHVybnMge251bWJlcn0gTnVtYmVyIG9mIGJ5dGVzIHdyaXR0ZW5cclxuICogQHRocm93cyB7RXJyb3J9IElmIGVuY29kaW5nIGlzIGludmFsaWRcclxuICovXHJcbmJhc2U2NC5kZWNvZGUgPSBmdW5jdGlvbiBkZWNvZGUoc3RyaW5nLCBidWZmZXIsIG9mZnNldCkge1xyXG4gICAgdmFyIHN0YXJ0ID0gb2Zmc2V0O1xyXG4gICAgdmFyIGogPSAwLCAvLyBnb3RvIGluZGV4XHJcbiAgICAgICAgdDsgICAgIC8vIHRlbXBvcmFyeVxyXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBzdHJpbmcubGVuZ3RoOykge1xyXG4gICAgICAgIHZhciBjID0gc3RyaW5nLmNoYXJDb2RlQXQoaSsrKTtcclxuICAgICAgICBpZiAoYyA9PT0gNjEgJiYgaiA+IDEpXHJcbiAgICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgIGlmICgoYyA9IHM2NFtjXSkgPT09IHVuZGVmaW5lZClcclxuICAgICAgICAgICAgdGhyb3cgRXJyb3IoaW52YWxpZEVuY29kaW5nKTtcclxuICAgICAgICBzd2l0Y2ggKGopIHtcclxuICAgICAgICAgICAgY2FzZSAwOlxyXG4gICAgICAgICAgICAgICAgdCA9IGM7XHJcbiAgICAgICAgICAgICAgICBqID0gMTtcclxuICAgICAgICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgICAgICBjYXNlIDE6XHJcbiAgICAgICAgICAgICAgICBidWZmZXJbb2Zmc2V0KytdID0gdCA8PCAyIHwgKGMgJiA0OCkgPj4gNDtcclxuICAgICAgICAgICAgICAgIHQgPSBjO1xyXG4gICAgICAgICAgICAgICAgaiA9IDI7XHJcbiAgICAgICAgICAgICAgICBicmVhaztcclxuICAgICAgICAgICAgY2FzZSAyOlxyXG4gICAgICAgICAgICAgICAgYnVmZmVyW29mZnNldCsrXSA9ICh0ICYgMTUpIDw8IDQgfCAoYyAmIDYwKSA+PiAyO1xyXG4gICAgICAgICAgICAgICAgdCA9IGM7XHJcbiAgICAgICAgICAgICAgICBqID0gMztcclxuICAgICAgICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgICAgICBjYXNlIDM6XHJcbiAgICAgICAgICAgICAgICBidWZmZXJbb2Zmc2V0KytdID0gKHQgJiAzKSA8PCA2IHwgYztcclxuICAgICAgICAgICAgICAgIGogPSAwO1xyXG4gICAgICAgICAgICAgICAgYnJlYWs7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG4gICAgaWYgKGogPT09IDEpXHJcbiAgICAgICAgdGhyb3cgRXJyb3IoaW52YWxpZEVuY29kaW5nKTtcclxuICAgIHJldHVybiBvZmZzZXQgLSBzdGFydDtcclxufTtcclxuXHJcbi8qKlxyXG4gKiBUZXN0cyBpZiB0aGUgc3BlY2lmaWVkIHN0cmluZyBhcHBlYXJzIHRvIGJlIGJhc2U2NCBlbmNvZGVkLlxyXG4gKiBAcGFyYW0ge3N0cmluZ30gc3RyaW5nIFN0cmluZyB0byB0ZXN0XHJcbiAqIEByZXR1cm5zIHtib29sZWFufSBgdHJ1ZWAgaWYgcHJvYmFibHkgYmFzZTY0IGVuY29kZWQsIG90aGVyd2lzZSBmYWxzZVxyXG4gKi9cclxuYmFzZTY0LnRlc3QgPSBmdW5jdGlvbiB0ZXN0KHN0cmluZykge1xyXG4gICAgcmV0dXJuIC9eKD86W0EtWmEtejAtOSsvXXs0fSkqKD86W0EtWmEtejAtOSsvXXsyfT09fFtBLVphLXowLTkrL117M309KT8kLy50ZXN0KHN0cmluZyk7XHJcbn07XHJcbiIsIlwidXNlIHN0cmljdFwiO1xyXG5tb2R1bGUuZXhwb3J0cyA9IEV2ZW50RW1pdHRlcjtcclxuXHJcbi8qKlxyXG4gKiBDb25zdHJ1Y3RzIGEgbmV3IGV2ZW50IGVtaXR0ZXIgaW5zdGFuY2UuXHJcbiAqIEBjbGFzc2Rlc2MgQSBtaW5pbWFsIGV2ZW50IGVtaXR0ZXIuXHJcbiAqIEBtZW1iZXJvZiB1dGlsXHJcbiAqIEBjb25zdHJ1Y3RvclxyXG4gKi9cclxuZnVuY3Rpb24gRXZlbnRFbWl0dGVyKCkge1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogUmVnaXN0ZXJlZCBsaXN0ZW5lcnMuXHJcbiAgICAgKiBAdHlwZSB7T2JqZWN0LjxzdHJpbmcsKj59XHJcbiAgICAgKiBAcHJpdmF0ZVxyXG4gICAgICovXHJcbiAgICB0aGlzLl9saXN0ZW5lcnMgPSB7fTtcclxufVxyXG5cclxuLyoqXHJcbiAqIFJlZ2lzdGVycyBhbiBldmVudCBsaXN0ZW5lci5cclxuICogQHBhcmFtIHtzdHJpbmd9IGV2dCBFdmVudCBuYW1lXHJcbiAqIEBwYXJhbSB7ZnVuY3Rpb259IGZuIExpc3RlbmVyXHJcbiAqIEBwYXJhbSB7Kn0gW2N0eF0gTGlzdGVuZXIgY29udGV4dFxyXG4gKiBAcmV0dXJucyB7dXRpbC5FdmVudEVtaXR0ZXJ9IGB0aGlzYFxyXG4gKi9cclxuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5vbiA9IGZ1bmN0aW9uIG9uKGV2dCwgZm4sIGN0eCkge1xyXG4gICAgKHRoaXMuX2xpc3RlbmVyc1tldnRdIHx8ICh0aGlzLl9saXN0ZW5lcnNbZXZ0XSA9IFtdKSkucHVzaCh7XHJcbiAgICAgICAgZm4gIDogZm4sXHJcbiAgICAgICAgY3R4IDogY3R4IHx8IHRoaXNcclxuICAgIH0pO1xyXG4gICAgcmV0dXJuIHRoaXM7XHJcbn07XHJcblxyXG4vKipcclxuICogUmVtb3ZlcyBhbiBldmVudCBsaXN0ZW5lciBvciBhbnkgbWF0Y2hpbmcgbGlzdGVuZXJzIGlmIGFyZ3VtZW50cyBhcmUgb21pdHRlZC5cclxuICogQHBhcmFtIHtzdHJpbmd9IFtldnRdIEV2ZW50IG5hbWUuIFJlbW92ZXMgYWxsIGxpc3RlbmVycyBpZiBvbWl0dGVkLlxyXG4gKiBAcGFyYW0ge2Z1bmN0aW9ufSBbZm5dIExpc3RlbmVyIHRvIHJlbW92ZS4gUmVtb3ZlcyBhbGwgbGlzdGVuZXJzIG9mIGBldnRgIGlmIG9taXR0ZWQuXHJcbiAqIEByZXR1cm5zIHt1dGlsLkV2ZW50RW1pdHRlcn0gYHRoaXNgXHJcbiAqL1xyXG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLm9mZiA9IGZ1bmN0aW9uIG9mZihldnQsIGZuKSB7XHJcbiAgICBpZiAoZXZ0ID09PSB1bmRlZmluZWQpXHJcbiAgICAgICAgdGhpcy5fbGlzdGVuZXJzID0ge307XHJcbiAgICBlbHNlIHtcclxuICAgICAgICBpZiAoZm4gPT09IHVuZGVmaW5lZClcclxuICAgICAgICAgICAgdGhpcy5fbGlzdGVuZXJzW2V2dF0gPSBbXTtcclxuICAgICAgICBlbHNlIHtcclxuICAgICAgICAgICAgdmFyIGxpc3RlbmVycyA9IHRoaXMuX2xpc3RlbmVyc1tldnRdO1xyXG4gICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxpc3RlbmVycy5sZW5ndGg7KVxyXG4gICAgICAgICAgICAgICAgaWYgKGxpc3RlbmVyc1tpXS5mbiA9PT0gZm4pXHJcbiAgICAgICAgICAgICAgICAgICAgbGlzdGVuZXJzLnNwbGljZShpLCAxKTtcclxuICAgICAgICAgICAgICAgIGVsc2VcclxuICAgICAgICAgICAgICAgICAgICArK2k7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG4gICAgcmV0dXJuIHRoaXM7XHJcbn07XHJcblxyXG4vKipcclxuICogRW1pdHMgYW4gZXZlbnQgYnkgY2FsbGluZyBpdHMgbGlzdGVuZXJzIHdpdGggdGhlIHNwZWNpZmllZCBhcmd1bWVudHMuXHJcbiAqIEBwYXJhbSB7c3RyaW5nfSBldnQgRXZlbnQgbmFtZVxyXG4gKiBAcGFyYW0gey4uLip9IGFyZ3MgQXJndW1lbnRzXHJcbiAqIEByZXR1cm5zIHt1dGlsLkV2ZW50RW1pdHRlcn0gYHRoaXNgXHJcbiAqL1xyXG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLmVtaXQgPSBmdW5jdGlvbiBlbWl0KGV2dCkge1xyXG4gICAgdmFyIGxpc3RlbmVycyA9IHRoaXMuX2xpc3RlbmVyc1tldnRdO1xyXG4gICAgaWYgKGxpc3RlbmVycykge1xyXG4gICAgICAgIHZhciBhcmdzID0gW10sXHJcbiAgICAgICAgICAgIGkgPSAxO1xyXG4gICAgICAgIGZvciAoOyBpIDwgYXJndW1lbnRzLmxlbmd0aDspXHJcbiAgICAgICAgICAgIGFyZ3MucHVzaChhcmd1bWVudHNbaSsrXSk7XHJcbiAgICAgICAgZm9yIChpID0gMDsgaSA8IGxpc3RlbmVycy5sZW5ndGg7KVxyXG4gICAgICAgICAgICBsaXN0ZW5lcnNbaV0uZm4uYXBwbHkobGlzdGVuZXJzW2krK10uY3R4LCBhcmdzKTtcclxuICAgIH1cclxuICAgIHJldHVybiB0aGlzO1xyXG59O1xyXG4iLCJcInVzZSBzdHJpY3RcIjtcclxuXHJcbm1vZHVsZS5leHBvcnRzID0gZmFjdG9yeShmYWN0b3J5KTtcclxuXHJcbi8qKlxyXG4gKiBSZWFkcyAvIHdyaXRlcyBmbG9hdHMgLyBkb3VibGVzIGZyb20gLyB0byBidWZmZXJzLlxyXG4gKiBAbmFtZSB1dGlsLmZsb2F0XHJcbiAqIEBuYW1lc3BhY2VcclxuICovXHJcblxyXG4vKipcclxuICogV3JpdGVzIGEgMzIgYml0IGZsb2F0IHRvIGEgYnVmZmVyIHVzaW5nIGxpdHRsZSBlbmRpYW4gYnl0ZSBvcmRlci5cclxuICogQG5hbWUgdXRpbC5mbG9hdC53cml0ZUZsb2F0TEVcclxuICogQGZ1bmN0aW9uXHJcbiAqIEBwYXJhbSB7bnVtYmVyfSB2YWwgVmFsdWUgdG8gd3JpdGVcclxuICogQHBhcmFtIHtVaW50OEFycmF5fSBidWYgVGFyZ2V0IGJ1ZmZlclxyXG4gKiBAcGFyYW0ge251bWJlcn0gcG9zIFRhcmdldCBidWZmZXIgb2Zmc2V0XHJcbiAqIEByZXR1cm5zIHt1bmRlZmluZWR9XHJcbiAqL1xyXG5cclxuLyoqXHJcbiAqIFdyaXRlcyBhIDMyIGJpdCBmbG9hdCB0byBhIGJ1ZmZlciB1c2luZyBiaWcgZW5kaWFuIGJ5dGUgb3JkZXIuXHJcbiAqIEBuYW1lIHV0aWwuZmxvYXQud3JpdGVGbG9hdEJFXHJcbiAqIEBmdW5jdGlvblxyXG4gKiBAcGFyYW0ge251bWJlcn0gdmFsIFZhbHVlIHRvIHdyaXRlXHJcbiAqIEBwYXJhbSB7VWludDhBcnJheX0gYnVmIFRhcmdldCBidWZmZXJcclxuICogQHBhcmFtIHtudW1iZXJ9IHBvcyBUYXJnZXQgYnVmZmVyIG9mZnNldFxyXG4gKiBAcmV0dXJucyB7dW5kZWZpbmVkfVxyXG4gKi9cclxuXHJcbi8qKlxyXG4gKiBSZWFkcyBhIDMyIGJpdCBmbG9hdCBmcm9tIGEgYnVmZmVyIHVzaW5nIGxpdHRsZSBlbmRpYW4gYnl0ZSBvcmRlci5cclxuICogQG5hbWUgdXRpbC5mbG9hdC5yZWFkRmxvYXRMRVxyXG4gKiBAZnVuY3Rpb25cclxuICogQHBhcmFtIHtVaW50OEFycmF5fSBidWYgU291cmNlIGJ1ZmZlclxyXG4gKiBAcGFyYW0ge251bWJlcn0gcG9zIFNvdXJjZSBidWZmZXIgb2Zmc2V0XHJcbiAqIEByZXR1cm5zIHtudW1iZXJ9IFZhbHVlIHJlYWRcclxuICovXHJcblxyXG4vKipcclxuICogUmVhZHMgYSAzMiBiaXQgZmxvYXQgZnJvbSBhIGJ1ZmZlciB1c2luZyBiaWcgZW5kaWFuIGJ5dGUgb3JkZXIuXHJcbiAqIEBuYW1lIHV0aWwuZmxvYXQucmVhZEZsb2F0QkVcclxuICogQGZ1bmN0aW9uXHJcbiAqIEBwYXJhbSB7VWludDhBcnJheX0gYnVmIFNvdXJjZSBidWZmZXJcclxuICogQHBhcmFtIHtudW1iZXJ9IHBvcyBTb3VyY2UgYnVmZmVyIG9mZnNldFxyXG4gKiBAcmV0dXJucyB7bnVtYmVyfSBWYWx1ZSByZWFkXHJcbiAqL1xyXG5cclxuLyoqXHJcbiAqIFdyaXRlcyBhIDY0IGJpdCBkb3VibGUgdG8gYSBidWZmZXIgdXNpbmcgbGl0dGxlIGVuZGlhbiBieXRlIG9yZGVyLlxyXG4gKiBAbmFtZSB1dGlsLmZsb2F0LndyaXRlRG91YmxlTEVcclxuICogQGZ1bmN0aW9uXHJcbiAqIEBwYXJhbSB7bnVtYmVyfSB2YWwgVmFsdWUgdG8gd3JpdGVcclxuICogQHBhcmFtIHtVaW50OEFycmF5fSBidWYgVGFyZ2V0IGJ1ZmZlclxyXG4gKiBAcGFyYW0ge251bWJlcn0gcG9zIFRhcmdldCBidWZmZXIgb2Zmc2V0XHJcbiAqIEByZXR1cm5zIHt1bmRlZmluZWR9XHJcbiAqL1xyXG5cclxuLyoqXHJcbiAqIFdyaXRlcyBhIDY0IGJpdCBkb3VibGUgdG8gYSBidWZmZXIgdXNpbmcgYmlnIGVuZGlhbiBieXRlIG9yZGVyLlxyXG4gKiBAbmFtZSB1dGlsLmZsb2F0LndyaXRlRG91YmxlQkVcclxuICogQGZ1bmN0aW9uXHJcbiAqIEBwYXJhbSB7bnVtYmVyfSB2YWwgVmFsdWUgdG8gd3JpdGVcclxuICogQHBhcmFtIHtVaW50OEFycmF5fSBidWYgVGFyZ2V0IGJ1ZmZlclxyXG4gKiBAcGFyYW0ge251bWJlcn0gcG9zIFRhcmdldCBidWZmZXIgb2Zmc2V0XHJcbiAqIEByZXR1cm5zIHt1bmRlZmluZWR9XHJcbiAqL1xyXG5cclxuLyoqXHJcbiAqIFJlYWRzIGEgNjQgYml0IGRvdWJsZSBmcm9tIGEgYnVmZmVyIHVzaW5nIGxpdHRsZSBlbmRpYW4gYnl0ZSBvcmRlci5cclxuICogQG5hbWUgdXRpbC5mbG9hdC5yZWFkRG91YmxlTEVcclxuICogQGZ1bmN0aW9uXHJcbiAqIEBwYXJhbSB7VWludDhBcnJheX0gYnVmIFNvdXJjZSBidWZmZXJcclxuICogQHBhcmFtIHtudW1iZXJ9IHBvcyBTb3VyY2UgYnVmZmVyIG9mZnNldFxyXG4gKiBAcmV0dXJucyB7bnVtYmVyfSBWYWx1ZSByZWFkXHJcbiAqL1xyXG5cclxuLyoqXHJcbiAqIFJlYWRzIGEgNjQgYml0IGRvdWJsZSBmcm9tIGEgYnVmZmVyIHVzaW5nIGJpZyBlbmRpYW4gYnl0ZSBvcmRlci5cclxuICogQG5hbWUgdXRpbC5mbG9hdC5yZWFkRG91YmxlQkVcclxuICogQGZ1bmN0aW9uXHJcbiAqIEBwYXJhbSB7VWludDhBcnJheX0gYnVmIFNvdXJjZSBidWZmZXJcclxuICogQHBhcmFtIHtudW1iZXJ9IHBvcyBTb3VyY2UgYnVmZmVyIG9mZnNldFxyXG4gKiBAcmV0dXJucyB7bnVtYmVyfSBWYWx1ZSByZWFkXHJcbiAqL1xyXG5cclxuLy8gRmFjdG9yeSBmdW5jdGlvbiBmb3IgdGhlIHB1cnBvc2Ugb2Ygbm9kZS1iYXNlZCB0ZXN0aW5nIGluIG1vZGlmaWVkIGdsb2JhbCBlbnZpcm9ubWVudHNcclxuZnVuY3Rpb24gZmFjdG9yeShleHBvcnRzKSB7XHJcblxyXG4gICAgLy8gZmxvYXQ6IHR5cGVkIGFycmF5XHJcbiAgICBpZiAodHlwZW9mIEZsb2F0MzJBcnJheSAhPT0gXCJ1bmRlZmluZWRcIikgKGZ1bmN0aW9uKCkge1xyXG5cclxuICAgICAgICB2YXIgZjMyID0gbmV3IEZsb2F0MzJBcnJheShbIC0wIF0pLFxyXG4gICAgICAgICAgICBmOGIgPSBuZXcgVWludDhBcnJheShmMzIuYnVmZmVyKSxcclxuICAgICAgICAgICAgbGUgID0gZjhiWzNdID09PSAxMjg7XHJcblxyXG4gICAgICAgIGZ1bmN0aW9uIHdyaXRlRmxvYXRfZjMyX2NweSh2YWwsIGJ1ZiwgcG9zKSB7XHJcbiAgICAgICAgICAgIGYzMlswXSA9IHZhbDtcclxuICAgICAgICAgICAgYnVmW3BvcyAgICBdID0gZjhiWzBdO1xyXG4gICAgICAgICAgICBidWZbcG9zICsgMV0gPSBmOGJbMV07XHJcbiAgICAgICAgICAgIGJ1Zltwb3MgKyAyXSA9IGY4YlsyXTtcclxuICAgICAgICAgICAgYnVmW3BvcyArIDNdID0gZjhiWzNdO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgZnVuY3Rpb24gd3JpdGVGbG9hdF9mMzJfcmV2KHZhbCwgYnVmLCBwb3MpIHtcclxuICAgICAgICAgICAgZjMyWzBdID0gdmFsO1xyXG4gICAgICAgICAgICBidWZbcG9zICAgIF0gPSBmOGJbM107XHJcbiAgICAgICAgICAgIGJ1Zltwb3MgKyAxXSA9IGY4YlsyXTtcclxuICAgICAgICAgICAgYnVmW3BvcyArIDJdID0gZjhiWzFdO1xyXG4gICAgICAgICAgICBidWZbcG9zICsgM10gPSBmOGJbMF07XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICAvKiBpc3RhbmJ1bCBpZ25vcmUgbmV4dCAqL1xyXG4gICAgICAgIGV4cG9ydHMud3JpdGVGbG9hdExFID0gbGUgPyB3cml0ZUZsb2F0X2YzMl9jcHkgOiB3cml0ZUZsb2F0X2YzMl9yZXY7XHJcbiAgICAgICAgLyogaXN0YW5idWwgaWdub3JlIG5leHQgKi9cclxuICAgICAgICBleHBvcnRzLndyaXRlRmxvYXRCRSA9IGxlID8gd3JpdGVGbG9hdF9mMzJfcmV2IDogd3JpdGVGbG9hdF9mMzJfY3B5O1xyXG5cclxuICAgICAgICBmdW5jdGlvbiByZWFkRmxvYXRfZjMyX2NweShidWYsIHBvcykge1xyXG4gICAgICAgICAgICBmOGJbMF0gPSBidWZbcG9zICAgIF07XHJcbiAgICAgICAgICAgIGY4YlsxXSA9IGJ1Zltwb3MgKyAxXTtcclxuICAgICAgICAgICAgZjhiWzJdID0gYnVmW3BvcyArIDJdO1xyXG4gICAgICAgICAgICBmOGJbM10gPSBidWZbcG9zICsgM107XHJcbiAgICAgICAgICAgIHJldHVybiBmMzJbMF07XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBmdW5jdGlvbiByZWFkRmxvYXRfZjMyX3JldihidWYsIHBvcykge1xyXG4gICAgICAgICAgICBmOGJbM10gPSBidWZbcG9zICAgIF07XHJcbiAgICAgICAgICAgIGY4YlsyXSA9IGJ1Zltwb3MgKyAxXTtcclxuICAgICAgICAgICAgZjhiWzFdID0gYnVmW3BvcyArIDJdO1xyXG4gICAgICAgICAgICBmOGJbMF0gPSBidWZbcG9zICsgM107XHJcbiAgICAgICAgICAgIHJldHVybiBmMzJbMF07XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICAvKiBpc3RhbmJ1bCBpZ25vcmUgbmV4dCAqL1xyXG4gICAgICAgIGV4cG9ydHMucmVhZEZsb2F0TEUgPSBsZSA/IHJlYWRGbG9hdF9mMzJfY3B5IDogcmVhZEZsb2F0X2YzMl9yZXY7XHJcbiAgICAgICAgLyogaXN0YW5idWwgaWdub3JlIG5leHQgKi9cclxuICAgICAgICBleHBvcnRzLnJlYWRGbG9hdEJFID0gbGUgPyByZWFkRmxvYXRfZjMyX3JldiA6IHJlYWRGbG9hdF9mMzJfY3B5O1xyXG5cclxuICAgIC8vIGZsb2F0OiBpZWVlNzU0XHJcbiAgICB9KSgpOyBlbHNlIChmdW5jdGlvbigpIHtcclxuXHJcbiAgICAgICAgZnVuY3Rpb24gd3JpdGVGbG9hdF9pZWVlNzU0KHdyaXRlVWludCwgdmFsLCBidWYsIHBvcykge1xyXG4gICAgICAgICAgICB2YXIgc2lnbiA9IHZhbCA8IDAgPyAxIDogMDtcclxuICAgICAgICAgICAgaWYgKHNpZ24pXHJcbiAgICAgICAgICAgICAgICB2YWwgPSAtdmFsO1xyXG4gICAgICAgICAgICBpZiAodmFsID09PSAwKVxyXG4gICAgICAgICAgICAgICAgd3JpdGVVaW50KDEgLyB2YWwgPiAwID8gLyogcG9zaXRpdmUgKi8gMCA6IC8qIG5lZ2F0aXZlIDAgKi8gMjE0NzQ4MzY0OCwgYnVmLCBwb3MpO1xyXG4gICAgICAgICAgICBlbHNlIGlmIChpc05hTih2YWwpKVxyXG4gICAgICAgICAgICAgICAgd3JpdGVVaW50KDIxNDMyODkzNDQsIGJ1ZiwgcG9zKTtcclxuICAgICAgICAgICAgZWxzZSBpZiAodmFsID4gMy40MDI4MjM0NjYzODUyODg2ZSszOCkgLy8gKy1JbmZpbml0eVxyXG4gICAgICAgICAgICAgICAgd3JpdGVVaW50KChzaWduIDw8IDMxIHwgMjEzOTA5NTA0MCkgPj4+IDAsIGJ1ZiwgcG9zKTtcclxuICAgICAgICAgICAgZWxzZSBpZiAodmFsIDwgMS4xNzU0OTQzNTA4MjIyODc1ZS0zOCkgLy8gZGVub3JtYWxcclxuICAgICAgICAgICAgICAgIHdyaXRlVWludCgoc2lnbiA8PCAzMSB8IE1hdGgucm91bmQodmFsIC8gMS40MDEyOTg0NjQzMjQ4MTdlLTQ1KSkgPj4+IDAsIGJ1ZiwgcG9zKTtcclxuICAgICAgICAgICAgZWxzZSB7XHJcbiAgICAgICAgICAgICAgICB2YXIgZXhwb25lbnQgPSBNYXRoLmZsb29yKE1hdGgubG9nKHZhbCkgLyBNYXRoLkxOMiksXHJcbiAgICAgICAgICAgICAgICAgICAgbWFudGlzc2EgPSBNYXRoLnJvdW5kKHZhbCAqIE1hdGgucG93KDIsIC1leHBvbmVudCkgKiA4Mzg4NjA4KSAmIDgzODg2MDc7XHJcbiAgICAgICAgICAgICAgICB3cml0ZVVpbnQoKHNpZ24gPDwgMzEgfCBleHBvbmVudCArIDEyNyA8PCAyMyB8IG1hbnRpc3NhKSA+Pj4gMCwgYnVmLCBwb3MpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBleHBvcnRzLndyaXRlRmxvYXRMRSA9IHdyaXRlRmxvYXRfaWVlZTc1NC5iaW5kKG51bGwsIHdyaXRlVWludExFKTtcclxuICAgICAgICBleHBvcnRzLndyaXRlRmxvYXRCRSA9IHdyaXRlRmxvYXRfaWVlZTc1NC5iaW5kKG51bGwsIHdyaXRlVWludEJFKTtcclxuXHJcbiAgICAgICAgZnVuY3Rpb24gcmVhZEZsb2F0X2llZWU3NTQocmVhZFVpbnQsIGJ1ZiwgcG9zKSB7XHJcbiAgICAgICAgICAgIHZhciB1aW50ID0gcmVhZFVpbnQoYnVmLCBwb3MpLFxyXG4gICAgICAgICAgICAgICAgc2lnbiA9ICh1aW50ID4+IDMxKSAqIDIgKyAxLFxyXG4gICAgICAgICAgICAgICAgZXhwb25lbnQgPSB1aW50ID4+PiAyMyAmIDI1NSxcclxuICAgICAgICAgICAgICAgIG1hbnRpc3NhID0gdWludCAmIDgzODg2MDc7XHJcbiAgICAgICAgICAgIHJldHVybiBleHBvbmVudCA9PT0gMjU1XHJcbiAgICAgICAgICAgICAgICA/IG1hbnRpc3NhXHJcbiAgICAgICAgICAgICAgICA/IE5hTlxyXG4gICAgICAgICAgICAgICAgOiBzaWduICogSW5maW5pdHlcclxuICAgICAgICAgICAgICAgIDogZXhwb25lbnQgPT09IDAgLy8gZGVub3JtYWxcclxuICAgICAgICAgICAgICAgID8gc2lnbiAqIDEuNDAxMjk4NDY0MzI0ODE3ZS00NSAqIG1hbnRpc3NhXHJcbiAgICAgICAgICAgICAgICA6IHNpZ24gKiBNYXRoLnBvdygyLCBleHBvbmVudCAtIDE1MCkgKiAobWFudGlzc2EgKyA4Mzg4NjA4KTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGV4cG9ydHMucmVhZEZsb2F0TEUgPSByZWFkRmxvYXRfaWVlZTc1NC5iaW5kKG51bGwsIHJlYWRVaW50TEUpO1xyXG4gICAgICAgIGV4cG9ydHMucmVhZEZsb2F0QkUgPSByZWFkRmxvYXRfaWVlZTc1NC5iaW5kKG51bGwsIHJlYWRVaW50QkUpO1xyXG5cclxuICAgIH0pKCk7XHJcblxyXG4gICAgLy8gZG91YmxlOiB0eXBlZCBhcnJheVxyXG4gICAgaWYgKHR5cGVvZiBGbG9hdDY0QXJyYXkgIT09IFwidW5kZWZpbmVkXCIpIChmdW5jdGlvbigpIHtcclxuXHJcbiAgICAgICAgdmFyIGY2NCA9IG5ldyBGbG9hdDY0QXJyYXkoWy0wXSksXHJcbiAgICAgICAgICAgIGY4YiA9IG5ldyBVaW50OEFycmF5KGY2NC5idWZmZXIpLFxyXG4gICAgICAgICAgICBsZSAgPSBmOGJbN10gPT09IDEyODtcclxuXHJcbiAgICAgICAgZnVuY3Rpb24gd3JpdGVEb3VibGVfZjY0X2NweSh2YWwsIGJ1ZiwgcG9zKSB7XHJcbiAgICAgICAgICAgIGY2NFswXSA9IHZhbDtcclxuICAgICAgICAgICAgYnVmW3BvcyAgICBdID0gZjhiWzBdO1xyXG4gICAgICAgICAgICBidWZbcG9zICsgMV0gPSBmOGJbMV07XHJcbiAgICAgICAgICAgIGJ1Zltwb3MgKyAyXSA9IGY4YlsyXTtcclxuICAgICAgICAgICAgYnVmW3BvcyArIDNdID0gZjhiWzNdO1xyXG4gICAgICAgICAgICBidWZbcG9zICsgNF0gPSBmOGJbNF07XHJcbiAgICAgICAgICAgIGJ1Zltwb3MgKyA1XSA9IGY4Yls1XTtcclxuICAgICAgICAgICAgYnVmW3BvcyArIDZdID0gZjhiWzZdO1xyXG4gICAgICAgICAgICBidWZbcG9zICsgN10gPSBmOGJbN107XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBmdW5jdGlvbiB3cml0ZURvdWJsZV9mNjRfcmV2KHZhbCwgYnVmLCBwb3MpIHtcclxuICAgICAgICAgICAgZjY0WzBdID0gdmFsO1xyXG4gICAgICAgICAgICBidWZbcG9zICAgIF0gPSBmOGJbN107XHJcbiAgICAgICAgICAgIGJ1Zltwb3MgKyAxXSA9IGY4Yls2XTtcclxuICAgICAgICAgICAgYnVmW3BvcyArIDJdID0gZjhiWzVdO1xyXG4gICAgICAgICAgICBidWZbcG9zICsgM10gPSBmOGJbNF07XHJcbiAgICAgICAgICAgIGJ1Zltwb3MgKyA0XSA9IGY4YlszXTtcclxuICAgICAgICAgICAgYnVmW3BvcyArIDVdID0gZjhiWzJdO1xyXG4gICAgICAgICAgICBidWZbcG9zICsgNl0gPSBmOGJbMV07XHJcbiAgICAgICAgICAgIGJ1Zltwb3MgKyA3XSA9IGY4YlswXTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0ICovXHJcbiAgICAgICAgZXhwb3J0cy53cml0ZURvdWJsZUxFID0gbGUgPyB3cml0ZURvdWJsZV9mNjRfY3B5IDogd3JpdGVEb3VibGVfZjY0X3JldjtcclxuICAgICAgICAvKiBpc3RhbmJ1bCBpZ25vcmUgbmV4dCAqL1xyXG4gICAgICAgIGV4cG9ydHMud3JpdGVEb3VibGVCRSA9IGxlID8gd3JpdGVEb3VibGVfZjY0X3JldiA6IHdyaXRlRG91YmxlX2Y2NF9jcHk7XHJcblxyXG4gICAgICAgIGZ1bmN0aW9uIHJlYWREb3VibGVfZjY0X2NweShidWYsIHBvcykge1xyXG4gICAgICAgICAgICBmOGJbMF0gPSBidWZbcG9zICAgIF07XHJcbiAgICAgICAgICAgIGY4YlsxXSA9IGJ1Zltwb3MgKyAxXTtcclxuICAgICAgICAgICAgZjhiWzJdID0gYnVmW3BvcyArIDJdO1xyXG4gICAgICAgICAgICBmOGJbM10gPSBidWZbcG9zICsgM107XHJcbiAgICAgICAgICAgIGY4Yls0XSA9IGJ1Zltwb3MgKyA0XTtcclxuICAgICAgICAgICAgZjhiWzVdID0gYnVmW3BvcyArIDVdO1xyXG4gICAgICAgICAgICBmOGJbNl0gPSBidWZbcG9zICsgNl07XHJcbiAgICAgICAgICAgIGY4Yls3XSA9IGJ1Zltwb3MgKyA3XTtcclxuICAgICAgICAgICAgcmV0dXJuIGY2NFswXTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGZ1bmN0aW9uIHJlYWREb3VibGVfZjY0X3JldihidWYsIHBvcykge1xyXG4gICAgICAgICAgICBmOGJbN10gPSBidWZbcG9zICAgIF07XHJcbiAgICAgICAgICAgIGY4Yls2XSA9IGJ1Zltwb3MgKyAxXTtcclxuICAgICAgICAgICAgZjhiWzVdID0gYnVmW3BvcyArIDJdO1xyXG4gICAgICAgICAgICBmOGJbNF0gPSBidWZbcG9zICsgM107XHJcbiAgICAgICAgICAgIGY4YlszXSA9IGJ1Zltwb3MgKyA0XTtcclxuICAgICAgICAgICAgZjhiWzJdID0gYnVmW3BvcyArIDVdO1xyXG4gICAgICAgICAgICBmOGJbMV0gPSBidWZbcG9zICsgNl07XHJcbiAgICAgICAgICAgIGY4YlswXSA9IGJ1Zltwb3MgKyA3XTtcclxuICAgICAgICAgICAgcmV0dXJuIGY2NFswXTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0ICovXHJcbiAgICAgICAgZXhwb3J0cy5yZWFkRG91YmxlTEUgPSBsZSA/IHJlYWREb3VibGVfZjY0X2NweSA6IHJlYWREb3VibGVfZjY0X3JldjtcclxuICAgICAgICAvKiBpc3RhbmJ1bCBpZ25vcmUgbmV4dCAqL1xyXG4gICAgICAgIGV4cG9ydHMucmVhZERvdWJsZUJFID0gbGUgPyByZWFkRG91YmxlX2Y2NF9yZXYgOiByZWFkRG91YmxlX2Y2NF9jcHk7XHJcblxyXG4gICAgLy8gZG91YmxlOiBpZWVlNzU0XHJcbiAgICB9KSgpOyBlbHNlIChmdW5jdGlvbigpIHtcclxuXHJcbiAgICAgICAgZnVuY3Rpb24gd3JpdGVEb3VibGVfaWVlZTc1NCh3cml0ZVVpbnQsIG9mZjAsIG9mZjEsIHZhbCwgYnVmLCBwb3MpIHtcclxuICAgICAgICAgICAgdmFyIHNpZ24gPSB2YWwgPCAwID8gMSA6IDA7XHJcbiAgICAgICAgICAgIGlmIChzaWduKVxyXG4gICAgICAgICAgICAgICAgdmFsID0gLXZhbDtcclxuICAgICAgICAgICAgaWYgKHZhbCA9PT0gMCkge1xyXG4gICAgICAgICAgICAgICAgd3JpdGVVaW50KDAsIGJ1ZiwgcG9zICsgb2ZmMCk7XHJcbiAgICAgICAgICAgICAgICB3cml0ZVVpbnQoMSAvIHZhbCA+IDAgPyAvKiBwb3NpdGl2ZSAqLyAwIDogLyogbmVnYXRpdmUgMCAqLyAyMTQ3NDgzNjQ4LCBidWYsIHBvcyArIG9mZjEpO1xyXG4gICAgICAgICAgICB9IGVsc2UgaWYgKGlzTmFOKHZhbCkpIHtcclxuICAgICAgICAgICAgICAgIHdyaXRlVWludCgwLCBidWYsIHBvcyArIG9mZjApO1xyXG4gICAgICAgICAgICAgICAgd3JpdGVVaW50KDIxNDY5NTkzNjAsIGJ1ZiwgcG9zICsgb2ZmMSk7XHJcbiAgICAgICAgICAgIH0gZWxzZSBpZiAodmFsID4gMS43OTc2OTMxMzQ4NjIzMTU3ZSszMDgpIHsgLy8gKy1JbmZpbml0eVxyXG4gICAgICAgICAgICAgICAgd3JpdGVVaW50KDAsIGJ1ZiwgcG9zICsgb2ZmMCk7XHJcbiAgICAgICAgICAgICAgICB3cml0ZVVpbnQoKHNpZ24gPDwgMzEgfCAyMTQ2NDM1MDcyKSA+Pj4gMCwgYnVmLCBwb3MgKyBvZmYxKTtcclxuICAgICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgICAgIHZhciBtYW50aXNzYTtcclxuICAgICAgICAgICAgICAgIGlmICh2YWwgPCAyLjIyNTA3Mzg1ODUwNzIwMTRlLTMwOCkgeyAvLyBkZW5vcm1hbFxyXG4gICAgICAgICAgICAgICAgICAgIG1hbnRpc3NhID0gdmFsIC8gNWUtMzI0O1xyXG4gICAgICAgICAgICAgICAgICAgIHdyaXRlVWludChtYW50aXNzYSA+Pj4gMCwgYnVmLCBwb3MgKyBvZmYwKTtcclxuICAgICAgICAgICAgICAgICAgICB3cml0ZVVpbnQoKHNpZ24gPDwgMzEgfCBtYW50aXNzYSAvIDQyOTQ5NjcyOTYpID4+PiAwLCBidWYsIHBvcyArIG9mZjEpO1xyXG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgICAgICAgICB2YXIgZXhwb25lbnQgPSBNYXRoLmZsb29yKE1hdGgubG9nKHZhbCkgLyBNYXRoLkxOMik7XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKGV4cG9uZW50ID09PSAxMDI0KVxyXG4gICAgICAgICAgICAgICAgICAgICAgICBleHBvbmVudCA9IDEwMjM7XHJcbiAgICAgICAgICAgICAgICAgICAgbWFudGlzc2EgPSB2YWwgKiBNYXRoLnBvdygyLCAtZXhwb25lbnQpO1xyXG4gICAgICAgICAgICAgICAgICAgIHdyaXRlVWludChtYW50aXNzYSAqIDQ1MDM1OTk2MjczNzA0OTYgPj4+IDAsIGJ1ZiwgcG9zICsgb2ZmMCk7XHJcbiAgICAgICAgICAgICAgICAgICAgd3JpdGVVaW50KChzaWduIDw8IDMxIHwgZXhwb25lbnQgKyAxMDIzIDw8IDIwIHwgbWFudGlzc2EgKiAxMDQ4NTc2ICYgMTA0ODU3NSkgPj4+IDAsIGJ1ZiwgcG9zICsgb2ZmMSk7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGV4cG9ydHMud3JpdGVEb3VibGVMRSA9IHdyaXRlRG91YmxlX2llZWU3NTQuYmluZChudWxsLCB3cml0ZVVpbnRMRSwgMCwgNCk7XHJcbiAgICAgICAgZXhwb3J0cy53cml0ZURvdWJsZUJFID0gd3JpdGVEb3VibGVfaWVlZTc1NC5iaW5kKG51bGwsIHdyaXRlVWludEJFLCA0LCAwKTtcclxuXHJcbiAgICAgICAgZnVuY3Rpb24gcmVhZERvdWJsZV9pZWVlNzU0KHJlYWRVaW50LCBvZmYwLCBvZmYxLCBidWYsIHBvcykge1xyXG4gICAgICAgICAgICB2YXIgbG8gPSByZWFkVWludChidWYsIHBvcyArIG9mZjApLFxyXG4gICAgICAgICAgICAgICAgaGkgPSByZWFkVWludChidWYsIHBvcyArIG9mZjEpO1xyXG4gICAgICAgICAgICB2YXIgc2lnbiA9IChoaSA+PiAzMSkgKiAyICsgMSxcclxuICAgICAgICAgICAgICAgIGV4cG9uZW50ID0gaGkgPj4+IDIwICYgMjA0NyxcclxuICAgICAgICAgICAgICAgIG1hbnRpc3NhID0gNDI5NDk2NzI5NiAqIChoaSAmIDEwNDg1NzUpICsgbG87XHJcbiAgICAgICAgICAgIHJldHVybiBleHBvbmVudCA9PT0gMjA0N1xyXG4gICAgICAgICAgICAgICAgPyBtYW50aXNzYVxyXG4gICAgICAgICAgICAgICAgPyBOYU5cclxuICAgICAgICAgICAgICAgIDogc2lnbiAqIEluZmluaXR5XHJcbiAgICAgICAgICAgICAgICA6IGV4cG9uZW50ID09PSAwIC8vIGRlbm9ybWFsXHJcbiAgICAgICAgICAgICAgICA/IHNpZ24gKiA1ZS0zMjQgKiBtYW50aXNzYVxyXG4gICAgICAgICAgICAgICAgOiBzaWduICogTWF0aC5wb3coMiwgZXhwb25lbnQgLSAxMDc1KSAqIChtYW50aXNzYSArIDQ1MDM1OTk2MjczNzA0OTYpO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgZXhwb3J0cy5yZWFkRG91YmxlTEUgPSByZWFkRG91YmxlX2llZWU3NTQuYmluZChudWxsLCByZWFkVWludExFLCAwLCA0KTtcclxuICAgICAgICBleHBvcnRzLnJlYWREb3VibGVCRSA9IHJlYWREb3VibGVfaWVlZTc1NC5iaW5kKG51bGwsIHJlYWRVaW50QkUsIDQsIDApO1xyXG5cclxuICAgIH0pKCk7XHJcblxyXG4gICAgcmV0dXJuIGV4cG9ydHM7XHJcbn1cclxuXHJcbi8vIHVpbnQgaGVscGVyc1xyXG5cclxuZnVuY3Rpb24gd3JpdGVVaW50TEUodmFsLCBidWYsIHBvcykge1xyXG4gICAgYnVmW3BvcyAgICBdID0gIHZhbCAgICAgICAgJiAyNTU7XHJcbiAgICBidWZbcG9zICsgMV0gPSAgdmFsID4+PiA4ICAmIDI1NTtcclxuICAgIGJ1Zltwb3MgKyAyXSA9ICB2YWwgPj4+IDE2ICYgMjU1O1xyXG4gICAgYnVmW3BvcyArIDNdID0gIHZhbCA+Pj4gMjQ7XHJcbn1cclxuXHJcbmZ1bmN0aW9uIHdyaXRlVWludEJFKHZhbCwgYnVmLCBwb3MpIHtcclxuICAgIGJ1Zltwb3MgICAgXSA9ICB2YWwgPj4+IDI0O1xyXG4gICAgYnVmW3BvcyArIDFdID0gIHZhbCA+Pj4gMTYgJiAyNTU7XHJcbiAgICBidWZbcG9zICsgMl0gPSAgdmFsID4+PiA4ICAmIDI1NTtcclxuICAgIGJ1Zltwb3MgKyAzXSA9ICB2YWwgICAgICAgICYgMjU1O1xyXG59XHJcblxyXG5mdW5jdGlvbiByZWFkVWludExFKGJ1ZiwgcG9zKSB7XHJcbiAgICByZXR1cm4gKGJ1Zltwb3MgICAgXVxyXG4gICAgICAgICAgfCBidWZbcG9zICsgMV0gPDwgOFxyXG4gICAgICAgICAgfCBidWZbcG9zICsgMl0gPDwgMTZcclxuICAgICAgICAgIHwgYnVmW3BvcyArIDNdIDw8IDI0KSA+Pj4gMDtcclxufVxyXG5cclxuZnVuY3Rpb24gcmVhZFVpbnRCRShidWYsIHBvcykge1xyXG4gICAgcmV0dXJuIChidWZbcG9zICAgIF0gPDwgMjRcclxuICAgICAgICAgIHwgYnVmW3BvcyArIDFdIDw8IDE2XHJcbiAgICAgICAgICB8IGJ1Zltwb3MgKyAyXSA8PCA4XHJcbiAgICAgICAgICB8IGJ1Zltwb3MgKyAzXSkgPj4+IDA7XHJcbn1cclxuIiwiXCJ1c2Ugc3RyaWN0XCI7XHJcbm1vZHVsZS5leHBvcnRzID0gaW5xdWlyZTtcclxuXHJcbi8qKlxyXG4gKiBSZXF1aXJlcyBhIG1vZHVsZSBvbmx5IGlmIGF2YWlsYWJsZS5cclxuICogQG1lbWJlcm9mIHV0aWxcclxuICogQHBhcmFtIHtzdHJpbmd9IG1vZHVsZU5hbWUgTW9kdWxlIHRvIHJlcXVpcmVcclxuICogQHJldHVybnMgez9PYmplY3R9IFJlcXVpcmVkIG1vZHVsZSBpZiBhdmFpbGFibGUgYW5kIG5vdCBlbXB0eSwgb3RoZXJ3aXNlIGBudWxsYFxyXG4gKi9cclxuZnVuY3Rpb24gaW5xdWlyZShtb2R1bGVOYW1lKSB7XHJcbiAgICB0cnkge1xyXG4gICAgICAgIHZhciBtb2QgPSBldmFsKFwicXVpcmVcIi5yZXBsYWNlKC9eLyxcInJlXCIpKShtb2R1bGVOYW1lKTsgLy8gZXNsaW50LWRpc2FibGUtbGluZSBuby1ldmFsXHJcbiAgICAgICAgaWYgKG1vZCAmJiAobW9kLmxlbmd0aCB8fCBPYmplY3Qua2V5cyhtb2QpLmxlbmd0aCkpXHJcbiAgICAgICAgICAgIHJldHVybiBtb2Q7XHJcbiAgICB9IGNhdGNoIChlKSB7fSAvLyBlc2xpbnQtZGlzYWJsZS1saW5lIG5vLWVtcHR5XHJcbiAgICByZXR1cm4gbnVsbDtcclxufVxyXG4iLCJcInVzZSBzdHJpY3RcIjtcclxubW9kdWxlLmV4cG9ydHMgPSBwb29sO1xyXG5cclxuLyoqXHJcbiAqIEFuIGFsbG9jYXRvciBhcyB1c2VkIGJ5IHtAbGluayB1dGlsLnBvb2x9LlxyXG4gKiBAdHlwZWRlZiBQb29sQWxsb2NhdG9yXHJcbiAqIEB0eXBlIHtmdW5jdGlvbn1cclxuICogQHBhcmFtIHtudW1iZXJ9IHNpemUgQnVmZmVyIHNpemVcclxuICogQHJldHVybnMge1VpbnQ4QXJyYXl9IEJ1ZmZlclxyXG4gKi9cclxuXHJcbi8qKlxyXG4gKiBBIHNsaWNlciBhcyB1c2VkIGJ5IHtAbGluayB1dGlsLnBvb2x9LlxyXG4gKiBAdHlwZWRlZiBQb29sU2xpY2VyXHJcbiAqIEB0eXBlIHtmdW5jdGlvbn1cclxuICogQHBhcmFtIHtudW1iZXJ9IHN0YXJ0IFN0YXJ0IG9mZnNldFxyXG4gKiBAcGFyYW0ge251bWJlcn0gZW5kIEVuZCBvZmZzZXRcclxuICogQHJldHVybnMge1VpbnQ4QXJyYXl9IEJ1ZmZlciBzbGljZVxyXG4gKiBAdGhpcyB7VWludDhBcnJheX1cclxuICovXHJcblxyXG4vKipcclxuICogQSBnZW5lcmFsIHB1cnBvc2UgYnVmZmVyIHBvb2wuXHJcbiAqIEBtZW1iZXJvZiB1dGlsXHJcbiAqIEBmdW5jdGlvblxyXG4gKiBAcGFyYW0ge1Bvb2xBbGxvY2F0b3J9IGFsbG9jIEFsbG9jYXRvclxyXG4gKiBAcGFyYW0ge1Bvb2xTbGljZXJ9IHNsaWNlIFNsaWNlclxyXG4gKiBAcGFyYW0ge251bWJlcn0gW3NpemU9ODE5Ml0gU2xhYiBzaXplXHJcbiAqIEByZXR1cm5zIHtQb29sQWxsb2NhdG9yfSBQb29sZWQgYWxsb2NhdG9yXHJcbiAqL1xyXG5mdW5jdGlvbiBwb29sKGFsbG9jLCBzbGljZSwgc2l6ZSkge1xyXG4gICAgdmFyIFNJWkUgICA9IHNpemUgfHwgODE5MjtcclxuICAgIHZhciBNQVggICAgPSBTSVpFID4+PiAxO1xyXG4gICAgdmFyIHNsYWIgICA9IG51bGw7XHJcbiAgICB2YXIgb2Zmc2V0ID0gU0laRTtcclxuICAgIHJldHVybiBmdW5jdGlvbiBwb29sX2FsbG9jKHNpemUpIHtcclxuICAgICAgICBpZiAoc2l6ZSA8IDEgfHwgc2l6ZSA+IE1BWClcclxuICAgICAgICAgICAgcmV0dXJuIGFsbG9jKHNpemUpO1xyXG4gICAgICAgIGlmIChvZmZzZXQgKyBzaXplID4gU0laRSkge1xyXG4gICAgICAgICAgICBzbGFiID0gYWxsb2MoU0laRSk7XHJcbiAgICAgICAgICAgIG9mZnNldCA9IDA7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHZhciBidWYgPSBzbGljZS5jYWxsKHNsYWIsIG9mZnNldCwgb2Zmc2V0ICs9IHNpemUpO1xyXG4gICAgICAgIGlmIChvZmZzZXQgJiA3KSAvLyBhbGlnbiB0byAzMiBiaXRcclxuICAgICAgICAgICAgb2Zmc2V0ID0gKG9mZnNldCB8IDcpICsgMTtcclxuICAgICAgICByZXR1cm4gYnVmO1xyXG4gICAgfTtcclxufVxyXG4iLCJcInVzZSBzdHJpY3RcIjtcclxuXHJcbi8qKlxyXG4gKiBBIG1pbmltYWwgVVRGOCBpbXBsZW1lbnRhdGlvbiBmb3IgbnVtYmVyIGFycmF5cy5cclxuICogQG1lbWJlcm9mIHV0aWxcclxuICogQG5hbWVzcGFjZVxyXG4gKi9cclxudmFyIHV0ZjggPSBleHBvcnRzO1xyXG5cclxuLyoqXHJcbiAqIENhbGN1bGF0ZXMgdGhlIFVURjggYnl0ZSBsZW5ndGggb2YgYSBzdHJpbmcuXHJcbiAqIEBwYXJhbSB7c3RyaW5nfSBzdHJpbmcgU3RyaW5nXHJcbiAqIEByZXR1cm5zIHtudW1iZXJ9IEJ5dGUgbGVuZ3RoXHJcbiAqL1xyXG51dGY4Lmxlbmd0aCA9IGZ1bmN0aW9uIHV0ZjhfbGVuZ3RoKHN0cmluZykge1xyXG4gICAgdmFyIGxlbiA9IDAsXHJcbiAgICAgICAgYyA9IDA7XHJcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHN0cmluZy5sZW5ndGg7ICsraSkge1xyXG4gICAgICAgIGMgPSBzdHJpbmcuY2hhckNvZGVBdChpKTtcclxuICAgICAgICBpZiAoYyA8IDEyOClcclxuICAgICAgICAgICAgbGVuICs9IDE7XHJcbiAgICAgICAgZWxzZSBpZiAoYyA8IDIwNDgpXHJcbiAgICAgICAgICAgIGxlbiArPSAyO1xyXG4gICAgICAgIGVsc2UgaWYgKChjICYgMHhGQzAwKSA9PT0gMHhEODAwICYmIChzdHJpbmcuY2hhckNvZGVBdChpICsgMSkgJiAweEZDMDApID09PSAweERDMDApIHtcclxuICAgICAgICAgICAgKytpO1xyXG4gICAgICAgICAgICBsZW4gKz0gNDtcclxuICAgICAgICB9IGVsc2VcclxuICAgICAgICAgICAgbGVuICs9IDM7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gbGVuO1xyXG59O1xyXG5cclxuLyoqXHJcbiAqIFJlYWRzIFVURjggYnl0ZXMgYXMgYSBzdHJpbmcuXHJcbiAqIEBwYXJhbSB7VWludDhBcnJheX0gYnVmZmVyIFNvdXJjZSBidWZmZXJcclxuICogQHBhcmFtIHtudW1iZXJ9IHN0YXJ0IFNvdXJjZSBzdGFydFxyXG4gKiBAcGFyYW0ge251bWJlcn0gZW5kIFNvdXJjZSBlbmRcclxuICogQHJldHVybnMge3N0cmluZ30gU3RyaW5nIHJlYWRcclxuICovXHJcbnV0ZjgucmVhZCA9IGZ1bmN0aW9uIHV0ZjhfcmVhZChidWZmZXIsIHN0YXJ0LCBlbmQpIHtcclxuICAgIHZhciBsZW4gPSBlbmQgLSBzdGFydDtcclxuICAgIGlmIChsZW4gPCAxKVxyXG4gICAgICAgIHJldHVybiBcIlwiO1xyXG4gICAgdmFyIHBhcnRzID0gbnVsbCxcclxuICAgICAgICBjaHVuayA9IFtdLFxyXG4gICAgICAgIGkgPSAwLCAvLyBjaGFyIG9mZnNldFxyXG4gICAgICAgIHQ7ICAgICAvLyB0ZW1wb3JhcnlcclxuICAgIHdoaWxlIChzdGFydCA8IGVuZCkge1xyXG4gICAgICAgIHQgPSBidWZmZXJbc3RhcnQrK107XHJcbiAgICAgICAgaWYgKHQgPCAxMjgpXHJcbiAgICAgICAgICAgIGNodW5rW2krK10gPSB0O1xyXG4gICAgICAgIGVsc2UgaWYgKHQgPiAxOTEgJiYgdCA8IDIyNClcclxuICAgICAgICAgICAgY2h1bmtbaSsrXSA9ICh0ICYgMzEpIDw8IDYgfCBidWZmZXJbc3RhcnQrK10gJiA2MztcclxuICAgICAgICBlbHNlIGlmICh0ID4gMjM5ICYmIHQgPCAzNjUpIHtcclxuICAgICAgICAgICAgdCA9ICgodCAmIDcpIDw8IDE4IHwgKGJ1ZmZlcltzdGFydCsrXSAmIDYzKSA8PCAxMiB8IChidWZmZXJbc3RhcnQrK10gJiA2MykgPDwgNiB8IGJ1ZmZlcltzdGFydCsrXSAmIDYzKSAtIDB4MTAwMDA7XHJcbiAgICAgICAgICAgIGNodW5rW2krK10gPSAweEQ4MDAgKyAodCA+PiAxMCk7XHJcbiAgICAgICAgICAgIGNodW5rW2krK10gPSAweERDMDAgKyAodCAmIDEwMjMpO1xyXG4gICAgICAgIH0gZWxzZVxyXG4gICAgICAgICAgICBjaHVua1tpKytdID0gKHQgJiAxNSkgPDwgMTIgfCAoYnVmZmVyW3N0YXJ0KytdICYgNjMpIDw8IDYgfCBidWZmZXJbc3RhcnQrK10gJiA2MztcclxuICAgICAgICBpZiAoaSA+IDgxOTEpIHtcclxuICAgICAgICAgICAgKHBhcnRzIHx8IChwYXJ0cyA9IFtdKSkucHVzaChTdHJpbmcuZnJvbUNoYXJDb2RlLmFwcGx5KFN0cmluZywgY2h1bmspKTtcclxuICAgICAgICAgICAgaSA9IDA7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG4gICAgaWYgKHBhcnRzKSB7XHJcbiAgICAgICAgaWYgKGkpXHJcbiAgICAgICAgICAgIHBhcnRzLnB1c2goU3RyaW5nLmZyb21DaGFyQ29kZS5hcHBseShTdHJpbmcsIGNodW5rLnNsaWNlKDAsIGkpKSk7XHJcbiAgICAgICAgcmV0dXJuIHBhcnRzLmpvaW4oXCJcIik7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gU3RyaW5nLmZyb21DaGFyQ29kZS5hcHBseShTdHJpbmcsIGNodW5rLnNsaWNlKDAsIGkpKTtcclxufTtcclxuXHJcbi8qKlxyXG4gKiBXcml0ZXMgYSBzdHJpbmcgYXMgVVRGOCBieXRlcy5cclxuICogQHBhcmFtIHtzdHJpbmd9IHN0cmluZyBTb3VyY2Ugc3RyaW5nXHJcbiAqIEBwYXJhbSB7VWludDhBcnJheX0gYnVmZmVyIERlc3RpbmF0aW9uIGJ1ZmZlclxyXG4gKiBAcGFyYW0ge251bWJlcn0gb2Zmc2V0IERlc3RpbmF0aW9uIG9mZnNldFxyXG4gKiBAcmV0dXJucyB7bnVtYmVyfSBCeXRlcyB3cml0dGVuXHJcbiAqL1xyXG51dGY4LndyaXRlID0gZnVuY3Rpb24gdXRmOF93cml0ZShzdHJpbmcsIGJ1ZmZlciwgb2Zmc2V0KSB7XHJcbiAgICB2YXIgc3RhcnQgPSBvZmZzZXQsXHJcbiAgICAgICAgYzEsIC8vIGNoYXJhY3RlciAxXHJcbiAgICAgICAgYzI7IC8vIGNoYXJhY3RlciAyXHJcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHN0cmluZy5sZW5ndGg7ICsraSkge1xyXG4gICAgICAgIGMxID0gc3RyaW5nLmNoYXJDb2RlQXQoaSk7XHJcbiAgICAgICAgaWYgKGMxIDwgMTI4KSB7XHJcbiAgICAgICAgICAgIGJ1ZmZlcltvZmZzZXQrK10gPSBjMTtcclxuICAgICAgICB9IGVsc2UgaWYgKGMxIDwgMjA0OCkge1xyXG4gICAgICAgICAgICBidWZmZXJbb2Zmc2V0KytdID0gYzEgPj4gNiAgICAgICB8IDE5MjtcclxuICAgICAgICAgICAgYnVmZmVyW29mZnNldCsrXSA9IGMxICAgICAgICYgNjMgfCAxMjg7XHJcbiAgICAgICAgfSBlbHNlIGlmICgoYzEgJiAweEZDMDApID09PSAweEQ4MDAgJiYgKChjMiA9IHN0cmluZy5jaGFyQ29kZUF0KGkgKyAxKSkgJiAweEZDMDApID09PSAweERDMDApIHtcclxuICAgICAgICAgICAgYzEgPSAweDEwMDAwICsgKChjMSAmIDB4MDNGRikgPDwgMTApICsgKGMyICYgMHgwM0ZGKTtcclxuICAgICAgICAgICAgKytpO1xyXG4gICAgICAgICAgICBidWZmZXJbb2Zmc2V0KytdID0gYzEgPj4gMTggICAgICB8IDI0MDtcclxuICAgICAgICAgICAgYnVmZmVyW29mZnNldCsrXSA9IGMxID4+IDEyICYgNjMgfCAxMjg7XHJcbiAgICAgICAgICAgIGJ1ZmZlcltvZmZzZXQrK10gPSBjMSA+PiA2ICAmIDYzIHwgMTI4O1xyXG4gICAgICAgICAgICBidWZmZXJbb2Zmc2V0KytdID0gYzEgICAgICAgJiA2MyB8IDEyODtcclxuICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICBidWZmZXJbb2Zmc2V0KytdID0gYzEgPj4gMTIgICAgICB8IDIyNDtcclxuICAgICAgICAgICAgYnVmZmVyW29mZnNldCsrXSA9IGMxID4+IDYgICYgNjMgfCAxMjg7XHJcbiAgICAgICAgICAgIGJ1ZmZlcltvZmZzZXQrK10gPSBjMSAgICAgICAmIDYzIHwgMTI4O1xyXG4gICAgICAgIH1cclxuICAgIH1cclxuICAgIHJldHVybiBvZmZzZXQgLSBzdGFydDtcclxufTtcclxuIiwiXCJ1c2Ugc3RyaWN0XCI7XHJcbmV4cG9ydHMuX19lc01vZHVsZSA9IHRydWU7XHJcbnZhciBHdWlkID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKCkge1xyXG4gICAgZnVuY3Rpb24gR3VpZChndWlkKSB7XHJcbiAgICAgICAgaWYgKCFndWlkKSB7XHJcbiAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCJJbnZhbGlkIGFyZ3VtZW50OyBgdmFsdWVgIGhhcyBubyB2YWx1ZS5cIik7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHRoaXMudmFsdWUgPSBHdWlkLkVNUFRZO1xyXG4gICAgICAgIGlmIChndWlkICYmIEd1aWQuaXNHdWlkKGd1aWQpKSB7XHJcbiAgICAgICAgICAgIHRoaXMudmFsdWUgPSBndWlkO1xyXG4gICAgICAgIH1cclxuICAgIH1cclxuICAgIEd1aWQuaXNHdWlkID0gZnVuY3Rpb24gKGd1aWQpIHtcclxuICAgICAgICB2YXIgdmFsdWUgPSBndWlkLnRvU3RyaW5nKCk7XHJcbiAgICAgICAgcmV0dXJuIGd1aWQgJiYgKGd1aWQgaW5zdGFuY2VvZiBHdWlkIHx8IEd1aWQudmFsaWRhdG9yLnRlc3QodmFsdWUpKTtcclxuICAgIH07XHJcbiAgICBHdWlkLmNyZWF0ZSA9IGZ1bmN0aW9uICgpIHtcclxuICAgICAgICByZXR1cm4gbmV3IEd1aWQoW0d1aWQuZ2VuKDIpLCBHdWlkLmdlbigxKSwgR3VpZC5nZW4oMSksIEd1aWQuZ2VuKDEpLCBHdWlkLmdlbigzKV0uam9pbihcIi1cIikpO1xyXG4gICAgfTtcclxuICAgIEd1aWQuY3JlYXRlRW1wdHkgPSBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgcmV0dXJuIG5ldyBHdWlkKFwiZW1wdHlndWlkXCIpO1xyXG4gICAgfTtcclxuICAgIEd1aWQucGFyc2UgPSBmdW5jdGlvbiAoZ3VpZCkge1xyXG4gICAgICAgIHJldHVybiBuZXcgR3VpZChndWlkKTtcclxuICAgIH07XHJcbiAgICBHdWlkLnJhdyA9IGZ1bmN0aW9uICgpIHtcclxuICAgICAgICByZXR1cm4gW0d1aWQuZ2VuKDIpLCBHdWlkLmdlbigxKSwgR3VpZC5nZW4oMSksIEd1aWQuZ2VuKDEpLCBHdWlkLmdlbigzKV0uam9pbihcIi1cIik7XHJcbiAgICB9O1xyXG4gICAgR3VpZC5nZW4gPSBmdW5jdGlvbiAoY291bnQpIHtcclxuICAgICAgICB2YXIgb3V0ID0gXCJcIjtcclxuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGNvdW50OyBpKyspIHtcclxuICAgICAgICAgICAgLy8gdHNsaW50OmRpc2FibGUtbmV4dC1saW5lOm5vLWJpdHdpc2VcclxuICAgICAgICAgICAgb3V0ICs9ICgoKDEgKyBNYXRoLnJhbmRvbSgpKSAqIDB4MTAwMDApIHwgMCkudG9TdHJpbmcoMTYpLnN1YnN0cmluZygxKTtcclxuICAgICAgICB9XHJcbiAgICAgICAgcmV0dXJuIG91dDtcclxuICAgIH07XHJcbiAgICBHdWlkLnByb3RvdHlwZS5lcXVhbHMgPSBmdW5jdGlvbiAob3RoZXIpIHtcclxuICAgICAgICAvLyBDb21wYXJpbmcgc3RyaW5nIGB2YWx1ZWAgYWdhaW5zdCBwcm92aWRlZCBgZ3VpZGAgd2lsbCBhdXRvLWNhbGxcclxuICAgICAgICAvLyB0b1N0cmluZyBvbiBgZ3VpZGAgZm9yIGNvbXBhcmlzb25cclxuICAgICAgICByZXR1cm4gR3VpZC5pc0d1aWQob3RoZXIpICYmIHRoaXMudmFsdWUgPT09IG90aGVyLnRvU3RyaW5nKCk7XHJcbiAgICB9O1xyXG4gICAgR3VpZC5wcm90b3R5cGUuaXNFbXB0eSA9IGZ1bmN0aW9uICgpIHtcclxuICAgICAgICByZXR1cm4gdGhpcy52YWx1ZSA9PT0gR3VpZC5FTVBUWTtcclxuICAgIH07XHJcbiAgICBHdWlkLnByb3RvdHlwZS50b1N0cmluZyA9IGZ1bmN0aW9uICgpIHtcclxuICAgICAgICByZXR1cm4gdGhpcy52YWx1ZTtcclxuICAgIH07XHJcbiAgICBHdWlkLnByb3RvdHlwZS50b0pTT04gPSBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgcmV0dXJuIHtcclxuICAgICAgICAgICAgdmFsdWU6IHRoaXMudmFsdWVcclxuICAgICAgICB9O1xyXG4gICAgfTtcclxuICAgIEd1aWQudmFsaWRhdG9yID0gbmV3IFJlZ0V4cChcIl5bYS16MC05XXs4fS1bYS16MC05XXs0fS1bYS16MC05XXs0fS1bYS16MC05XXs0fS1bYS16MC05XXsxMn0kXCIsIFwiaVwiKTtcclxuICAgIEd1aWQuRU1QVFkgPSBcIjAwMDAwMDAwLTAwMDAtMDAwMC0wMDAwLTAwMDAwMDAwMDAwMFwiO1xyXG4gICAgcmV0dXJuIEd1aWQ7XHJcbn0oKSk7XHJcbmV4cG9ydHMuR3VpZCA9IEd1aWQ7XHJcbiIsIm1vZHVsZS5leHBvcnRzID0gTG9uZztcclxuXHJcbi8qKlxyXG4gKiB3YXNtIG9wdGltaXphdGlvbnMsIHRvIGRvIG5hdGl2ZSBpNjQgbXVsdGlwbGljYXRpb24gYW5kIGRpdmlkZVxyXG4gKi9cclxudmFyIHdhc20gPSBudWxsO1xyXG5cclxudHJ5IHtcclxuICB3YXNtID0gbmV3IFdlYkFzc2VtYmx5Lkluc3RhbmNlKG5ldyBXZWJBc3NlbWJseS5Nb2R1bGUobmV3IFVpbnQ4QXJyYXkoW1xyXG4gICAgMCwgOTcsIDExNSwgMTA5LCAxLCAwLCAwLCAwLCAxLCAxMywgMiwgOTYsIDAsIDEsIDEyNywgOTYsIDQsIDEyNywgMTI3LCAxMjcsIDEyNywgMSwgMTI3LCAzLCA3LCA2LCAwLCAxLCAxLCAxLCAxLCAxLCA2LCA2LCAxLCAxMjcsIDEsIDY1LCAwLCAxMSwgNywgNTAsIDYsIDMsIDEwOSwgMTE3LCAxMDgsIDAsIDEsIDUsIDEwMCwgMTA1LCAxMTgsIDk1LCAxMTUsIDAsIDIsIDUsIDEwMCwgMTA1LCAxMTgsIDk1LCAxMTcsIDAsIDMsIDUsIDExNCwgMTAxLCAxMDksIDk1LCAxMTUsIDAsIDQsIDUsIDExNCwgMTAxLCAxMDksIDk1LCAxMTcsIDAsIDUsIDgsIDEwMywgMTAxLCAxMTYsIDk1LCAxMDQsIDEwNSwgMTAzLCAxMDQsIDAsIDAsIDEwLCAxOTEsIDEsIDYsIDQsIDAsIDM1LCAwLCAxMSwgMzYsIDEsIDEsIDEyNiwgMzIsIDAsIDE3MywgMzIsIDEsIDE3MywgNjYsIDMyLCAxMzQsIDEzMiwgMzIsIDIsIDE3MywgMzIsIDMsIDE3MywgNjYsIDMyLCAxMzQsIDEzMiwgMTI2LCAzNCwgNCwgNjYsIDMyLCAxMzUsIDE2NywgMzYsIDAsIDMyLCA0LCAxNjcsIDExLCAzNiwgMSwgMSwgMTI2LCAzMiwgMCwgMTczLCAzMiwgMSwgMTczLCA2NiwgMzIsIDEzNCwgMTMyLCAzMiwgMiwgMTczLCAzMiwgMywgMTczLCA2NiwgMzIsIDEzNCwgMTMyLCAxMjcsIDM0LCA0LCA2NiwgMzIsIDEzNSwgMTY3LCAzNiwgMCwgMzIsIDQsIDE2NywgMTEsIDM2LCAxLCAxLCAxMjYsIDMyLCAwLCAxNzMsIDMyLCAxLCAxNzMsIDY2LCAzMiwgMTM0LCAxMzIsIDMyLCAyLCAxNzMsIDMyLCAzLCAxNzMsIDY2LCAzMiwgMTM0LCAxMzIsIDEyOCwgMzQsIDQsIDY2LCAzMiwgMTM1LCAxNjcsIDM2LCAwLCAzMiwgNCwgMTY3LCAxMSwgMzYsIDEsIDEsIDEyNiwgMzIsIDAsIDE3MywgMzIsIDEsIDE3MywgNjYsIDMyLCAxMzQsIDEzMiwgMzIsIDIsIDE3MywgMzIsIDMsIDE3MywgNjYsIDMyLCAxMzQsIDEzMiwgMTI5LCAzNCwgNCwgNjYsIDMyLCAxMzUsIDE2NywgMzYsIDAsIDMyLCA0LCAxNjcsIDExLCAzNiwgMSwgMSwgMTI2LCAzMiwgMCwgMTczLCAzMiwgMSwgMTczLCA2NiwgMzIsIDEzNCwgMTMyLCAzMiwgMiwgMTczLCAzMiwgMywgMTczLCA2NiwgMzIsIDEzNCwgMTMyLCAxMzAsIDM0LCA0LCA2NiwgMzIsIDEzNSwgMTY3LCAzNiwgMCwgMzIsIDQsIDE2NywgMTFcclxuICBdKSksIHt9KS5leHBvcnRzO1xyXG59IGNhdGNoIChlKSB7XHJcbiAgLy8gbm8gd2FzbSBzdXBwb3J0IDooXHJcbn1cclxuXHJcbi8qKlxyXG4gKiBDb25zdHJ1Y3RzIGEgNjQgYml0IHR3bydzLWNvbXBsZW1lbnQgaW50ZWdlciwgZ2l2ZW4gaXRzIGxvdyBhbmQgaGlnaCAzMiBiaXQgdmFsdWVzIGFzICpzaWduZWQqIGludGVnZXJzLlxyXG4gKiAgU2VlIHRoZSBmcm9tKiBmdW5jdGlvbnMgYmVsb3cgZm9yIG1vcmUgY29udmVuaWVudCB3YXlzIG9mIGNvbnN0cnVjdGluZyBMb25ncy5cclxuICogQGV4cG9ydHMgTG9uZ1xyXG4gKiBAY2xhc3MgQSBMb25nIGNsYXNzIGZvciByZXByZXNlbnRpbmcgYSA2NCBiaXQgdHdvJ3MtY29tcGxlbWVudCBpbnRlZ2VyIHZhbHVlLlxyXG4gKiBAcGFyYW0ge251bWJlcn0gbG93IFRoZSBsb3cgKHNpZ25lZCkgMzIgYml0cyBvZiB0aGUgbG9uZ1xyXG4gKiBAcGFyYW0ge251bWJlcn0gaGlnaCBUaGUgaGlnaCAoc2lnbmVkKSAzMiBiaXRzIG9mIHRoZSBsb25nXHJcbiAqIEBwYXJhbSB7Ym9vbGVhbj19IHVuc2lnbmVkIFdoZXRoZXIgdW5zaWduZWQgb3Igbm90LCBkZWZhdWx0cyB0byBzaWduZWRcclxuICogQGNvbnN0cnVjdG9yXHJcbiAqL1xyXG5mdW5jdGlvbiBMb25nKGxvdywgaGlnaCwgdW5zaWduZWQpIHtcclxuXHJcbiAgICAvKipcclxuICAgICAqIFRoZSBsb3cgMzIgYml0cyBhcyBhIHNpZ25lZCB2YWx1ZS5cclxuICAgICAqIEB0eXBlIHtudW1iZXJ9XHJcbiAgICAgKi9cclxuICAgIHRoaXMubG93ID0gbG93IHwgMDtcclxuXHJcbiAgICAvKipcclxuICAgICAqIFRoZSBoaWdoIDMyIGJpdHMgYXMgYSBzaWduZWQgdmFsdWUuXHJcbiAgICAgKiBAdHlwZSB7bnVtYmVyfVxyXG4gICAgICovXHJcbiAgICB0aGlzLmhpZ2ggPSBoaWdoIHwgMDtcclxuXHJcbiAgICAvKipcclxuICAgICAqIFdoZXRoZXIgdW5zaWduZWQgb3Igbm90LlxyXG4gICAgICogQHR5cGUge2Jvb2xlYW59XHJcbiAgICAgKi9cclxuICAgIHRoaXMudW5zaWduZWQgPSAhIXVuc2lnbmVkO1xyXG59XHJcblxyXG4vLyBUaGUgaW50ZXJuYWwgcmVwcmVzZW50YXRpb24gb2YgYSBsb25nIGlzIHRoZSB0d28gZ2l2ZW4gc2lnbmVkLCAzMi1iaXQgdmFsdWVzLlxyXG4vLyBXZSB1c2UgMzItYml0IHBpZWNlcyBiZWNhdXNlIHRoZXNlIGFyZSB0aGUgc2l6ZSBvZiBpbnRlZ2VycyBvbiB3aGljaFxyXG4vLyBKYXZhc2NyaXB0IHBlcmZvcm1zIGJpdC1vcGVyYXRpb25zLiAgRm9yIG9wZXJhdGlvbnMgbGlrZSBhZGRpdGlvbiBhbmRcclxuLy8gbXVsdGlwbGljYXRpb24sIHdlIHNwbGl0IGVhY2ggbnVtYmVyIGludG8gMTYgYml0IHBpZWNlcywgd2hpY2ggY2FuIGVhc2lseSBiZVxyXG4vLyBtdWx0aXBsaWVkIHdpdGhpbiBKYXZhc2NyaXB0J3MgZmxvYXRpbmctcG9pbnQgcmVwcmVzZW50YXRpb24gd2l0aG91dCBvdmVyZmxvd1xyXG4vLyBvciBjaGFuZ2UgaW4gc2lnbi5cclxuLy9cclxuLy8gSW4gdGhlIGFsZ29yaXRobXMgYmVsb3csIHdlIGZyZXF1ZW50bHkgcmVkdWNlIHRoZSBuZWdhdGl2ZSBjYXNlIHRvIHRoZVxyXG4vLyBwb3NpdGl2ZSBjYXNlIGJ5IG5lZ2F0aW5nIHRoZSBpbnB1dChzKSBhbmQgdGhlbiBwb3N0LXByb2Nlc3NpbmcgdGhlIHJlc3VsdC5cclxuLy8gTm90ZSB0aGF0IHdlIG11c3QgQUxXQVlTIGNoZWNrIHNwZWNpYWxseSB3aGV0aGVyIHRob3NlIHZhbHVlcyBhcmUgTUlOX1ZBTFVFXHJcbi8vICgtMl42MykgYmVjYXVzZSAtTUlOX1ZBTFVFID09IE1JTl9WQUxVRSAoc2luY2UgMl42MyBjYW5ub3QgYmUgcmVwcmVzZW50ZWQgYXNcclxuLy8gYSBwb3NpdGl2ZSBudW1iZXIsIGl0IG92ZXJmbG93cyBiYWNrIGludG8gYSBuZWdhdGl2ZSkuICBOb3QgaGFuZGxpbmcgdGhpc1xyXG4vLyBjYXNlIHdvdWxkIG9mdGVuIHJlc3VsdCBpbiBpbmZpbml0ZSByZWN1cnNpb24uXHJcbi8vXHJcbi8vIENvbW1vbiBjb25zdGFudCB2YWx1ZXMgWkVSTywgT05FLCBORUdfT05FLCBldGMuIGFyZSBkZWZpbmVkIGJlbG93IHRoZSBmcm9tKlxyXG4vLyBtZXRob2RzIG9uIHdoaWNoIHRoZXkgZGVwZW5kLlxyXG5cclxuLyoqXHJcbiAqIEFuIGluZGljYXRvciB1c2VkIHRvIHJlbGlhYmx5IGRldGVybWluZSBpZiBhbiBvYmplY3QgaXMgYSBMb25nIG9yIG5vdC5cclxuICogQHR5cGUge2Jvb2xlYW59XHJcbiAqIEBjb25zdFxyXG4gKiBAcHJpdmF0ZVxyXG4gKi9cclxuTG9uZy5wcm90b3R5cGUuX19pc0xvbmdfXztcclxuXHJcbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShMb25nLnByb3RvdHlwZSwgXCJfX2lzTG9uZ19fXCIsIHsgdmFsdWU6IHRydWUgfSk7XHJcblxyXG4vKipcclxuICogQGZ1bmN0aW9uXHJcbiAqIEBwYXJhbSB7Kn0gb2JqIE9iamVjdFxyXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn1cclxuICogQGlubmVyXHJcbiAqL1xyXG5mdW5jdGlvbiBpc0xvbmcob2JqKSB7XHJcbiAgICByZXR1cm4gKG9iaiAmJiBvYmpbXCJfX2lzTG9uZ19fXCJdKSA9PT0gdHJ1ZTtcclxufVxyXG5cclxuLyoqXHJcbiAqIFRlc3RzIGlmIHRoZSBzcGVjaWZpZWQgb2JqZWN0IGlzIGEgTG9uZy5cclxuICogQGZ1bmN0aW9uXHJcbiAqIEBwYXJhbSB7Kn0gb2JqIE9iamVjdFxyXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn1cclxuICovXHJcbkxvbmcuaXNMb25nID0gaXNMb25nO1xyXG5cclxuLyoqXHJcbiAqIEEgY2FjaGUgb2YgdGhlIExvbmcgcmVwcmVzZW50YXRpb25zIG9mIHNtYWxsIGludGVnZXIgdmFsdWVzLlxyXG4gKiBAdHlwZSB7IU9iamVjdH1cclxuICogQGlubmVyXHJcbiAqL1xyXG52YXIgSU5UX0NBQ0hFID0ge307XHJcblxyXG4vKipcclxuICogQSBjYWNoZSBvZiB0aGUgTG9uZyByZXByZXNlbnRhdGlvbnMgb2Ygc21hbGwgdW5zaWduZWQgaW50ZWdlciB2YWx1ZXMuXHJcbiAqIEB0eXBlIHshT2JqZWN0fVxyXG4gKiBAaW5uZXJcclxuICovXHJcbnZhciBVSU5UX0NBQ0hFID0ge307XHJcblxyXG4vKipcclxuICogQHBhcmFtIHtudW1iZXJ9IHZhbHVlXHJcbiAqIEBwYXJhbSB7Ym9vbGVhbj19IHVuc2lnbmVkXHJcbiAqIEByZXR1cm5zIHshTG9uZ31cclxuICogQGlubmVyXHJcbiAqL1xyXG5mdW5jdGlvbiBmcm9tSW50KHZhbHVlLCB1bnNpZ25lZCkge1xyXG4gICAgdmFyIG9iaiwgY2FjaGVkT2JqLCBjYWNoZTtcclxuICAgIGlmICh1bnNpZ25lZCkge1xyXG4gICAgICAgIHZhbHVlID4+Pj0gMDtcclxuICAgICAgICBpZiAoY2FjaGUgPSAoMCA8PSB2YWx1ZSAmJiB2YWx1ZSA8IDI1NikpIHtcclxuICAgICAgICAgICAgY2FjaGVkT2JqID0gVUlOVF9DQUNIRVt2YWx1ZV07XHJcbiAgICAgICAgICAgIGlmIChjYWNoZWRPYmopXHJcbiAgICAgICAgICAgICAgICByZXR1cm4gY2FjaGVkT2JqO1xyXG4gICAgICAgIH1cclxuICAgICAgICBvYmogPSBmcm9tQml0cyh2YWx1ZSwgKHZhbHVlIHwgMCkgPCAwID8gLTEgOiAwLCB0cnVlKTtcclxuICAgICAgICBpZiAoY2FjaGUpXHJcbiAgICAgICAgICAgIFVJTlRfQ0FDSEVbdmFsdWVdID0gb2JqO1xyXG4gICAgICAgIHJldHVybiBvYmo7XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICAgIHZhbHVlIHw9IDA7XHJcbiAgICAgICAgaWYgKGNhY2hlID0gKC0xMjggPD0gdmFsdWUgJiYgdmFsdWUgPCAxMjgpKSB7XHJcbiAgICAgICAgICAgIGNhY2hlZE9iaiA9IElOVF9DQUNIRVt2YWx1ZV07XHJcbiAgICAgICAgICAgIGlmIChjYWNoZWRPYmopXHJcbiAgICAgICAgICAgICAgICByZXR1cm4gY2FjaGVkT2JqO1xyXG4gICAgICAgIH1cclxuICAgICAgICBvYmogPSBmcm9tQml0cyh2YWx1ZSwgdmFsdWUgPCAwID8gLTEgOiAwLCBmYWxzZSk7XHJcbiAgICAgICAgaWYgKGNhY2hlKVxyXG4gICAgICAgICAgICBJTlRfQ0FDSEVbdmFsdWVdID0gb2JqO1xyXG4gICAgICAgIHJldHVybiBvYmo7XHJcbiAgICB9XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBSZXR1cm5zIGEgTG9uZyByZXByZXNlbnRpbmcgdGhlIGdpdmVuIDMyIGJpdCBpbnRlZ2VyIHZhbHVlLlxyXG4gKiBAZnVuY3Rpb25cclxuICogQHBhcmFtIHtudW1iZXJ9IHZhbHVlIFRoZSAzMiBiaXQgaW50ZWdlciBpbiBxdWVzdGlvblxyXG4gKiBAcGFyYW0ge2Jvb2xlYW49fSB1bnNpZ25lZCBXaGV0aGVyIHVuc2lnbmVkIG9yIG5vdCwgZGVmYXVsdHMgdG8gc2lnbmVkXHJcbiAqIEByZXR1cm5zIHshTG9uZ30gVGhlIGNvcnJlc3BvbmRpbmcgTG9uZyB2YWx1ZVxyXG4gKi9cclxuTG9uZy5mcm9tSW50ID0gZnJvbUludDtcclxuXHJcbi8qKlxyXG4gKiBAcGFyYW0ge251bWJlcn0gdmFsdWVcclxuICogQHBhcmFtIHtib29sZWFuPX0gdW5zaWduZWRcclxuICogQHJldHVybnMgeyFMb25nfVxyXG4gKiBAaW5uZXJcclxuICovXHJcbmZ1bmN0aW9uIGZyb21OdW1iZXIodmFsdWUsIHVuc2lnbmVkKSB7XHJcbiAgICBpZiAoaXNOYU4odmFsdWUpKVxyXG4gICAgICAgIHJldHVybiB1bnNpZ25lZCA/IFVaRVJPIDogWkVSTztcclxuICAgIGlmICh1bnNpZ25lZCkge1xyXG4gICAgICAgIGlmICh2YWx1ZSA8IDApXHJcbiAgICAgICAgICAgIHJldHVybiBVWkVSTztcclxuICAgICAgICBpZiAodmFsdWUgPj0gVFdPX1BXUl82NF9EQkwpXHJcbiAgICAgICAgICAgIHJldHVybiBNQVhfVU5TSUdORURfVkFMVUU7XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICAgIGlmICh2YWx1ZSA8PSAtVFdPX1BXUl82M19EQkwpXHJcbiAgICAgICAgICAgIHJldHVybiBNSU5fVkFMVUU7XHJcbiAgICAgICAgaWYgKHZhbHVlICsgMSA+PSBUV09fUFdSXzYzX0RCTClcclxuICAgICAgICAgICAgcmV0dXJuIE1BWF9WQUxVRTtcclxuICAgIH1cclxuICAgIGlmICh2YWx1ZSA8IDApXHJcbiAgICAgICAgcmV0dXJuIGZyb21OdW1iZXIoLXZhbHVlLCB1bnNpZ25lZCkubmVnKCk7XHJcbiAgICByZXR1cm4gZnJvbUJpdHMoKHZhbHVlICUgVFdPX1BXUl8zMl9EQkwpIHwgMCwgKHZhbHVlIC8gVFdPX1BXUl8zMl9EQkwpIHwgMCwgdW5zaWduZWQpO1xyXG59XHJcblxyXG4vKipcclxuICogUmV0dXJucyBhIExvbmcgcmVwcmVzZW50aW5nIHRoZSBnaXZlbiB2YWx1ZSwgcHJvdmlkZWQgdGhhdCBpdCBpcyBhIGZpbml0ZSBudW1iZXIuIE90aGVyd2lzZSwgemVybyBpcyByZXR1cm5lZC5cclxuICogQGZ1bmN0aW9uXHJcbiAqIEBwYXJhbSB7bnVtYmVyfSB2YWx1ZSBUaGUgbnVtYmVyIGluIHF1ZXN0aW9uXHJcbiAqIEBwYXJhbSB7Ym9vbGVhbj19IHVuc2lnbmVkIFdoZXRoZXIgdW5zaWduZWQgb3Igbm90LCBkZWZhdWx0cyB0byBzaWduZWRcclxuICogQHJldHVybnMgeyFMb25nfSBUaGUgY29ycmVzcG9uZGluZyBMb25nIHZhbHVlXHJcbiAqL1xyXG5Mb25nLmZyb21OdW1iZXIgPSBmcm9tTnVtYmVyO1xyXG5cclxuLyoqXHJcbiAqIEBwYXJhbSB7bnVtYmVyfSBsb3dCaXRzXHJcbiAqIEBwYXJhbSB7bnVtYmVyfSBoaWdoQml0c1xyXG4gKiBAcGFyYW0ge2Jvb2xlYW49fSB1bnNpZ25lZFxyXG4gKiBAcmV0dXJucyB7IUxvbmd9XHJcbiAqIEBpbm5lclxyXG4gKi9cclxuZnVuY3Rpb24gZnJvbUJpdHMobG93Qml0cywgaGlnaEJpdHMsIHVuc2lnbmVkKSB7XHJcbiAgICByZXR1cm4gbmV3IExvbmcobG93Qml0cywgaGlnaEJpdHMsIHVuc2lnbmVkKTtcclxufVxyXG5cclxuLyoqXHJcbiAqIFJldHVybnMgYSBMb25nIHJlcHJlc2VudGluZyB0aGUgNjQgYml0IGludGVnZXIgdGhhdCBjb21lcyBieSBjb25jYXRlbmF0aW5nIHRoZSBnaXZlbiBsb3cgYW5kIGhpZ2ggYml0cy4gRWFjaCBpc1xyXG4gKiAgYXNzdW1lZCB0byB1c2UgMzIgYml0cy5cclxuICogQGZ1bmN0aW9uXHJcbiAqIEBwYXJhbSB7bnVtYmVyfSBsb3dCaXRzIFRoZSBsb3cgMzIgYml0c1xyXG4gKiBAcGFyYW0ge251bWJlcn0gaGlnaEJpdHMgVGhlIGhpZ2ggMzIgYml0c1xyXG4gKiBAcGFyYW0ge2Jvb2xlYW49fSB1bnNpZ25lZCBXaGV0aGVyIHVuc2lnbmVkIG9yIG5vdCwgZGVmYXVsdHMgdG8gc2lnbmVkXHJcbiAqIEByZXR1cm5zIHshTG9uZ30gVGhlIGNvcnJlc3BvbmRpbmcgTG9uZyB2YWx1ZVxyXG4gKi9cclxuTG9uZy5mcm9tQml0cyA9IGZyb21CaXRzO1xyXG5cclxuLyoqXHJcbiAqIEBmdW5jdGlvblxyXG4gKiBAcGFyYW0ge251bWJlcn0gYmFzZVxyXG4gKiBAcGFyYW0ge251bWJlcn0gZXhwb25lbnRcclxuICogQHJldHVybnMge251bWJlcn1cclxuICogQGlubmVyXHJcbiAqL1xyXG52YXIgcG93X2RibCA9IE1hdGgucG93OyAvLyBVc2VkIDQgdGltZXMgKDQqOCB0byAxNSs0KVxyXG5cclxuLyoqXHJcbiAqIEBwYXJhbSB7c3RyaW5nfSBzdHJcclxuICogQHBhcmFtIHsoYm9vbGVhbnxudW1iZXIpPX0gdW5zaWduZWRcclxuICogQHBhcmFtIHtudW1iZXI9fSByYWRpeFxyXG4gKiBAcmV0dXJucyB7IUxvbmd9XHJcbiAqIEBpbm5lclxyXG4gKi9cclxuZnVuY3Rpb24gZnJvbVN0cmluZyhzdHIsIHVuc2lnbmVkLCByYWRpeCkge1xyXG4gICAgaWYgKHN0ci5sZW5ndGggPT09IDApXHJcbiAgICAgICAgdGhyb3cgRXJyb3IoJ2VtcHR5IHN0cmluZycpO1xyXG4gICAgaWYgKHN0ciA9PT0gXCJOYU5cIiB8fCBzdHIgPT09IFwiSW5maW5pdHlcIiB8fCBzdHIgPT09IFwiK0luZmluaXR5XCIgfHwgc3RyID09PSBcIi1JbmZpbml0eVwiKVxyXG4gICAgICAgIHJldHVybiBaRVJPO1xyXG4gICAgaWYgKHR5cGVvZiB1bnNpZ25lZCA9PT0gJ251bWJlcicpIHtcclxuICAgICAgICAvLyBGb3IgZ29vZy5tYXRoLmxvbmcgY29tcGF0aWJpbGl0eVxyXG4gICAgICAgIHJhZGl4ID0gdW5zaWduZWQsXHJcbiAgICAgICAgdW5zaWduZWQgPSBmYWxzZTtcclxuICAgIH0gZWxzZSB7XHJcbiAgICAgICAgdW5zaWduZWQgPSAhISB1bnNpZ25lZDtcclxuICAgIH1cclxuICAgIHJhZGl4ID0gcmFkaXggfHwgMTA7XHJcbiAgICBpZiAocmFkaXggPCAyIHx8IDM2IDwgcmFkaXgpXHJcbiAgICAgICAgdGhyb3cgUmFuZ2VFcnJvcigncmFkaXgnKTtcclxuXHJcbiAgICB2YXIgcDtcclxuICAgIGlmICgocCA9IHN0ci5pbmRleE9mKCctJykpID4gMClcclxuICAgICAgICB0aHJvdyBFcnJvcignaW50ZXJpb3IgaHlwaGVuJyk7XHJcbiAgICBlbHNlIGlmIChwID09PSAwKSB7XHJcbiAgICAgICAgcmV0dXJuIGZyb21TdHJpbmcoc3RyLnN1YnN0cmluZygxKSwgdW5zaWduZWQsIHJhZGl4KS5uZWcoKTtcclxuICAgIH1cclxuXHJcbiAgICAvLyBEbyBzZXZlcmFsICg4KSBkaWdpdHMgZWFjaCB0aW1lIHRocm91Z2ggdGhlIGxvb3AsIHNvIGFzIHRvXHJcbiAgICAvLyBtaW5pbWl6ZSB0aGUgY2FsbHMgdG8gdGhlIHZlcnkgZXhwZW5zaXZlIGVtdWxhdGVkIGRpdi5cclxuICAgIHZhciByYWRpeFRvUG93ZXIgPSBmcm9tTnVtYmVyKHBvd19kYmwocmFkaXgsIDgpKTtcclxuXHJcbiAgICB2YXIgcmVzdWx0ID0gWkVSTztcclxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgc3RyLmxlbmd0aDsgaSArPSA4KSB7XHJcbiAgICAgICAgdmFyIHNpemUgPSBNYXRoLm1pbig4LCBzdHIubGVuZ3RoIC0gaSksXHJcbiAgICAgICAgICAgIHZhbHVlID0gcGFyc2VJbnQoc3RyLnN1YnN0cmluZyhpLCBpICsgc2l6ZSksIHJhZGl4KTtcclxuICAgICAgICBpZiAoc2l6ZSA8IDgpIHtcclxuICAgICAgICAgICAgdmFyIHBvd2VyID0gZnJvbU51bWJlcihwb3dfZGJsKHJhZGl4LCBzaXplKSk7XHJcbiAgICAgICAgICAgIHJlc3VsdCA9IHJlc3VsdC5tdWwocG93ZXIpLmFkZChmcm9tTnVtYmVyKHZhbHVlKSk7XHJcbiAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgcmVzdWx0ID0gcmVzdWx0Lm11bChyYWRpeFRvUG93ZXIpO1xyXG4gICAgICAgICAgICByZXN1bHQgPSByZXN1bHQuYWRkKGZyb21OdW1iZXIodmFsdWUpKTtcclxuICAgICAgICB9XHJcbiAgICB9XHJcbiAgICByZXN1bHQudW5zaWduZWQgPSB1bnNpZ25lZDtcclxuICAgIHJldHVybiByZXN1bHQ7XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBSZXR1cm5zIGEgTG9uZyByZXByZXNlbnRhdGlvbiBvZiB0aGUgZ2l2ZW4gc3RyaW5nLCB3cml0dGVuIHVzaW5nIHRoZSBzcGVjaWZpZWQgcmFkaXguXHJcbiAqIEBmdW5jdGlvblxyXG4gKiBAcGFyYW0ge3N0cmluZ30gc3RyIFRoZSB0ZXh0dWFsIHJlcHJlc2VudGF0aW9uIG9mIHRoZSBMb25nXHJcbiAqIEBwYXJhbSB7KGJvb2xlYW58bnVtYmVyKT19IHVuc2lnbmVkIFdoZXRoZXIgdW5zaWduZWQgb3Igbm90LCBkZWZhdWx0cyB0byBzaWduZWRcclxuICogQHBhcmFtIHtudW1iZXI9fSByYWRpeCBUaGUgcmFkaXggaW4gd2hpY2ggdGhlIHRleHQgaXMgd3JpdHRlbiAoMi0zNiksIGRlZmF1bHRzIHRvIDEwXHJcbiAqIEByZXR1cm5zIHshTG9uZ30gVGhlIGNvcnJlc3BvbmRpbmcgTG9uZyB2YWx1ZVxyXG4gKi9cclxuTG9uZy5mcm9tU3RyaW5nID0gZnJvbVN0cmluZztcclxuXHJcbi8qKlxyXG4gKiBAZnVuY3Rpb25cclxuICogQHBhcmFtIHshTG9uZ3xudW1iZXJ8c3RyaW5nfCF7bG93OiBudW1iZXIsIGhpZ2g6IG51bWJlciwgdW5zaWduZWQ6IGJvb2xlYW59fSB2YWxcclxuICogQHBhcmFtIHtib29sZWFuPX0gdW5zaWduZWRcclxuICogQHJldHVybnMgeyFMb25nfVxyXG4gKiBAaW5uZXJcclxuICovXHJcbmZ1bmN0aW9uIGZyb21WYWx1ZSh2YWwsIHVuc2lnbmVkKSB7XHJcbiAgICBpZiAodHlwZW9mIHZhbCA9PT0gJ251bWJlcicpXHJcbiAgICAgICAgcmV0dXJuIGZyb21OdW1iZXIodmFsLCB1bnNpZ25lZCk7XHJcbiAgICBpZiAodHlwZW9mIHZhbCA9PT0gJ3N0cmluZycpXHJcbiAgICAgICAgcmV0dXJuIGZyb21TdHJpbmcodmFsLCB1bnNpZ25lZCk7XHJcbiAgICAvLyBUaHJvd3MgZm9yIG5vbi1vYmplY3RzLCBjb252ZXJ0cyBub24taW5zdGFuY2VvZiBMb25nOlxyXG4gICAgcmV0dXJuIGZyb21CaXRzKHZhbC5sb3csIHZhbC5oaWdoLCB0eXBlb2YgdW5zaWduZWQgPT09ICdib29sZWFuJyA/IHVuc2lnbmVkIDogdmFsLnVuc2lnbmVkKTtcclxufVxyXG5cclxuLyoqXHJcbiAqIENvbnZlcnRzIHRoZSBzcGVjaWZpZWQgdmFsdWUgdG8gYSBMb25nIHVzaW5nIHRoZSBhcHByb3ByaWF0ZSBmcm9tKiBmdW5jdGlvbiBmb3IgaXRzIHR5cGUuXHJcbiAqIEBmdW5jdGlvblxyXG4gKiBAcGFyYW0geyFMb25nfG51bWJlcnxzdHJpbmd8IXtsb3c6IG51bWJlciwgaGlnaDogbnVtYmVyLCB1bnNpZ25lZDogYm9vbGVhbn19IHZhbCBWYWx1ZVxyXG4gKiBAcGFyYW0ge2Jvb2xlYW49fSB1bnNpZ25lZCBXaGV0aGVyIHVuc2lnbmVkIG9yIG5vdCwgZGVmYXVsdHMgdG8gc2lnbmVkXHJcbiAqIEByZXR1cm5zIHshTG9uZ31cclxuICovXHJcbkxvbmcuZnJvbVZhbHVlID0gZnJvbVZhbHVlO1xyXG5cclxuLy8gTk9URTogdGhlIGNvbXBpbGVyIHNob3VsZCBpbmxpbmUgdGhlc2UgY29uc3RhbnQgdmFsdWVzIGJlbG93IGFuZCB0aGVuIHJlbW92ZSB0aGVzZSB2YXJpYWJsZXMsIHNvIHRoZXJlIHNob3VsZCBiZVxyXG4vLyBubyBydW50aW1lIHBlbmFsdHkgZm9yIHRoZXNlLlxyXG5cclxuLyoqXHJcbiAqIEB0eXBlIHtudW1iZXJ9XHJcbiAqIEBjb25zdFxyXG4gKiBAaW5uZXJcclxuICovXHJcbnZhciBUV09fUFdSXzE2X0RCTCA9IDEgPDwgMTY7XHJcblxyXG4vKipcclxuICogQHR5cGUge251bWJlcn1cclxuICogQGNvbnN0XHJcbiAqIEBpbm5lclxyXG4gKi9cclxudmFyIFRXT19QV1JfMjRfREJMID0gMSA8PCAyNDtcclxuXHJcbi8qKlxyXG4gKiBAdHlwZSB7bnVtYmVyfVxyXG4gKiBAY29uc3RcclxuICogQGlubmVyXHJcbiAqL1xyXG52YXIgVFdPX1BXUl8zMl9EQkwgPSBUV09fUFdSXzE2X0RCTCAqIFRXT19QV1JfMTZfREJMO1xyXG5cclxuLyoqXHJcbiAqIEB0eXBlIHtudW1iZXJ9XHJcbiAqIEBjb25zdFxyXG4gKiBAaW5uZXJcclxuICovXHJcbnZhciBUV09fUFdSXzY0X0RCTCA9IFRXT19QV1JfMzJfREJMICogVFdPX1BXUl8zMl9EQkw7XHJcblxyXG4vKipcclxuICogQHR5cGUge251bWJlcn1cclxuICogQGNvbnN0XHJcbiAqIEBpbm5lclxyXG4gKi9cclxudmFyIFRXT19QV1JfNjNfREJMID0gVFdPX1BXUl82NF9EQkwgLyAyO1xyXG5cclxuLyoqXHJcbiAqIEB0eXBlIHshTG9uZ31cclxuICogQGNvbnN0XHJcbiAqIEBpbm5lclxyXG4gKi9cclxudmFyIFRXT19QV1JfMjQgPSBmcm9tSW50KFRXT19QV1JfMjRfREJMKTtcclxuXHJcbi8qKlxyXG4gKiBAdHlwZSB7IUxvbmd9XHJcbiAqIEBpbm5lclxyXG4gKi9cclxudmFyIFpFUk8gPSBmcm9tSW50KDApO1xyXG5cclxuLyoqXHJcbiAqIFNpZ25lZCB6ZXJvLlxyXG4gKiBAdHlwZSB7IUxvbmd9XHJcbiAqL1xyXG5Mb25nLlpFUk8gPSBaRVJPO1xyXG5cclxuLyoqXHJcbiAqIEB0eXBlIHshTG9uZ31cclxuICogQGlubmVyXHJcbiAqL1xyXG52YXIgVVpFUk8gPSBmcm9tSW50KDAsIHRydWUpO1xyXG5cclxuLyoqXHJcbiAqIFVuc2lnbmVkIHplcm8uXHJcbiAqIEB0eXBlIHshTG9uZ31cclxuICovXHJcbkxvbmcuVVpFUk8gPSBVWkVSTztcclxuXHJcbi8qKlxyXG4gKiBAdHlwZSB7IUxvbmd9XHJcbiAqIEBpbm5lclxyXG4gKi9cclxudmFyIE9ORSA9IGZyb21JbnQoMSk7XHJcblxyXG4vKipcclxuICogU2lnbmVkIG9uZS5cclxuICogQHR5cGUgeyFMb25nfVxyXG4gKi9cclxuTG9uZy5PTkUgPSBPTkU7XHJcblxyXG4vKipcclxuICogQHR5cGUgeyFMb25nfVxyXG4gKiBAaW5uZXJcclxuICovXHJcbnZhciBVT05FID0gZnJvbUludCgxLCB0cnVlKTtcclxuXHJcbi8qKlxyXG4gKiBVbnNpZ25lZCBvbmUuXHJcbiAqIEB0eXBlIHshTG9uZ31cclxuICovXHJcbkxvbmcuVU9ORSA9IFVPTkU7XHJcblxyXG4vKipcclxuICogQHR5cGUgeyFMb25nfVxyXG4gKiBAaW5uZXJcclxuICovXHJcbnZhciBORUdfT05FID0gZnJvbUludCgtMSk7XHJcblxyXG4vKipcclxuICogU2lnbmVkIG5lZ2F0aXZlIG9uZS5cclxuICogQHR5cGUgeyFMb25nfVxyXG4gKi9cclxuTG9uZy5ORUdfT05FID0gTkVHX09ORTtcclxuXHJcbi8qKlxyXG4gKiBAdHlwZSB7IUxvbmd9XHJcbiAqIEBpbm5lclxyXG4gKi9cclxudmFyIE1BWF9WQUxVRSA9IGZyb21CaXRzKDB4RkZGRkZGRkZ8MCwgMHg3RkZGRkZGRnwwLCBmYWxzZSk7XHJcblxyXG4vKipcclxuICogTWF4aW11bSBzaWduZWQgdmFsdWUuXHJcbiAqIEB0eXBlIHshTG9uZ31cclxuICovXHJcbkxvbmcuTUFYX1ZBTFVFID0gTUFYX1ZBTFVFO1xyXG5cclxuLyoqXHJcbiAqIEB0eXBlIHshTG9uZ31cclxuICogQGlubmVyXHJcbiAqL1xyXG52YXIgTUFYX1VOU0lHTkVEX1ZBTFVFID0gZnJvbUJpdHMoMHhGRkZGRkZGRnwwLCAweEZGRkZGRkZGfDAsIHRydWUpO1xyXG5cclxuLyoqXHJcbiAqIE1heGltdW0gdW5zaWduZWQgdmFsdWUuXHJcbiAqIEB0eXBlIHshTG9uZ31cclxuICovXHJcbkxvbmcuTUFYX1VOU0lHTkVEX1ZBTFVFID0gTUFYX1VOU0lHTkVEX1ZBTFVFO1xyXG5cclxuLyoqXHJcbiAqIEB0eXBlIHshTG9uZ31cclxuICogQGlubmVyXHJcbiAqL1xyXG52YXIgTUlOX1ZBTFVFID0gZnJvbUJpdHMoMCwgMHg4MDAwMDAwMHwwLCBmYWxzZSk7XHJcblxyXG4vKipcclxuICogTWluaW11bSBzaWduZWQgdmFsdWUuXHJcbiAqIEB0eXBlIHshTG9uZ31cclxuICovXHJcbkxvbmcuTUlOX1ZBTFVFID0gTUlOX1ZBTFVFO1xyXG5cclxuLyoqXHJcbiAqIEBhbGlhcyBMb25nLnByb3RvdHlwZVxyXG4gKiBAaW5uZXJcclxuICovXHJcbnZhciBMb25nUHJvdG90eXBlID0gTG9uZy5wcm90b3R5cGU7XHJcblxyXG4vKipcclxuICogQ29udmVydHMgdGhlIExvbmcgdG8gYSAzMiBiaXQgaW50ZWdlciwgYXNzdW1pbmcgaXQgaXMgYSAzMiBiaXQgaW50ZWdlci5cclxuICogQHJldHVybnMge251bWJlcn1cclxuICovXHJcbkxvbmdQcm90b3R5cGUudG9JbnQgPSBmdW5jdGlvbiB0b0ludCgpIHtcclxuICAgIHJldHVybiB0aGlzLnVuc2lnbmVkID8gdGhpcy5sb3cgPj4+IDAgOiB0aGlzLmxvdztcclxufTtcclxuXHJcbi8qKlxyXG4gKiBDb252ZXJ0cyB0aGUgTG9uZyB0byBhIHRoZSBuZWFyZXN0IGZsb2F0aW5nLXBvaW50IHJlcHJlc2VudGF0aW9uIG9mIHRoaXMgdmFsdWUgKGRvdWJsZSwgNTMgYml0IG1hbnRpc3NhKS5cclxuICogQHJldHVybnMge251bWJlcn1cclxuICovXHJcbkxvbmdQcm90b3R5cGUudG9OdW1iZXIgPSBmdW5jdGlvbiB0b051bWJlcigpIHtcclxuICAgIGlmICh0aGlzLnVuc2lnbmVkKVxyXG4gICAgICAgIHJldHVybiAoKHRoaXMuaGlnaCA+Pj4gMCkgKiBUV09fUFdSXzMyX0RCTCkgKyAodGhpcy5sb3cgPj4+IDApO1xyXG4gICAgcmV0dXJuIHRoaXMuaGlnaCAqIFRXT19QV1JfMzJfREJMICsgKHRoaXMubG93ID4+PiAwKTtcclxufTtcclxuXHJcbi8qKlxyXG4gKiBDb252ZXJ0cyB0aGUgTG9uZyB0byBhIHN0cmluZyB3cml0dGVuIGluIHRoZSBzcGVjaWZpZWQgcmFkaXguXHJcbiAqIEBwYXJhbSB7bnVtYmVyPX0gcmFkaXggUmFkaXggKDItMzYpLCBkZWZhdWx0cyB0byAxMFxyXG4gKiBAcmV0dXJucyB7c3RyaW5nfVxyXG4gKiBAb3ZlcnJpZGVcclxuICogQHRocm93cyB7UmFuZ2VFcnJvcn0gSWYgYHJhZGl4YCBpcyBvdXQgb2YgcmFuZ2VcclxuICovXHJcbkxvbmdQcm90b3R5cGUudG9TdHJpbmcgPSBmdW5jdGlvbiB0b1N0cmluZyhyYWRpeCkge1xyXG4gICAgcmFkaXggPSByYWRpeCB8fCAxMDtcclxuICAgIGlmIChyYWRpeCA8IDIgfHwgMzYgPCByYWRpeClcclxuICAgICAgICB0aHJvdyBSYW5nZUVycm9yKCdyYWRpeCcpO1xyXG4gICAgaWYgKHRoaXMuaXNaZXJvKCkpXHJcbiAgICAgICAgcmV0dXJuICcwJztcclxuICAgIGlmICh0aGlzLmlzTmVnYXRpdmUoKSkgeyAvLyBVbnNpZ25lZCBMb25ncyBhcmUgbmV2ZXIgbmVnYXRpdmVcclxuICAgICAgICBpZiAodGhpcy5lcShNSU5fVkFMVUUpKSB7XHJcbiAgICAgICAgICAgIC8vIFdlIG5lZWQgdG8gY2hhbmdlIHRoZSBMb25nIHZhbHVlIGJlZm9yZSBpdCBjYW4gYmUgbmVnYXRlZCwgc28gd2UgcmVtb3ZlXHJcbiAgICAgICAgICAgIC8vIHRoZSBib3R0b20tbW9zdCBkaWdpdCBpbiB0aGlzIGJhc2UgYW5kIHRoZW4gcmVjdXJzZSB0byBkbyB0aGUgcmVzdC5cclxuICAgICAgICAgICAgdmFyIHJhZGl4TG9uZyA9IGZyb21OdW1iZXIocmFkaXgpLFxyXG4gICAgICAgICAgICAgICAgZGl2ID0gdGhpcy5kaXYocmFkaXhMb25nKSxcclxuICAgICAgICAgICAgICAgIHJlbTEgPSBkaXYubXVsKHJhZGl4TG9uZykuc3ViKHRoaXMpO1xyXG4gICAgICAgICAgICByZXR1cm4gZGl2LnRvU3RyaW5nKHJhZGl4KSArIHJlbTEudG9JbnQoKS50b1N0cmluZyhyYWRpeCk7XHJcbiAgICAgICAgfSBlbHNlXHJcbiAgICAgICAgICAgIHJldHVybiAnLScgKyB0aGlzLm5lZygpLnRvU3RyaW5nKHJhZGl4KTtcclxuICAgIH1cclxuXHJcbiAgICAvLyBEbyBzZXZlcmFsICg2KSBkaWdpdHMgZWFjaCB0aW1lIHRocm91Z2ggdGhlIGxvb3AsIHNvIGFzIHRvXHJcbiAgICAvLyBtaW5pbWl6ZSB0aGUgY2FsbHMgdG8gdGhlIHZlcnkgZXhwZW5zaXZlIGVtdWxhdGVkIGRpdi5cclxuICAgIHZhciByYWRpeFRvUG93ZXIgPSBmcm9tTnVtYmVyKHBvd19kYmwocmFkaXgsIDYpLCB0aGlzLnVuc2lnbmVkKSxcclxuICAgICAgICByZW0gPSB0aGlzO1xyXG4gICAgdmFyIHJlc3VsdCA9ICcnO1xyXG4gICAgd2hpbGUgKHRydWUpIHtcclxuICAgICAgICB2YXIgcmVtRGl2ID0gcmVtLmRpdihyYWRpeFRvUG93ZXIpLFxyXG4gICAgICAgICAgICBpbnR2YWwgPSByZW0uc3ViKHJlbURpdi5tdWwocmFkaXhUb1Bvd2VyKSkudG9JbnQoKSA+Pj4gMCxcclxuICAgICAgICAgICAgZGlnaXRzID0gaW50dmFsLnRvU3RyaW5nKHJhZGl4KTtcclxuICAgICAgICByZW0gPSByZW1EaXY7XHJcbiAgICAgICAgaWYgKHJlbS5pc1plcm8oKSlcclxuICAgICAgICAgICAgcmV0dXJuIGRpZ2l0cyArIHJlc3VsdDtcclxuICAgICAgICBlbHNlIHtcclxuICAgICAgICAgICAgd2hpbGUgKGRpZ2l0cy5sZW5ndGggPCA2KVxyXG4gICAgICAgICAgICAgICAgZGlnaXRzID0gJzAnICsgZGlnaXRzO1xyXG4gICAgICAgICAgICByZXN1bHQgPSAnJyArIGRpZ2l0cyArIHJlc3VsdDtcclxuICAgICAgICB9XHJcbiAgICB9XHJcbn07XHJcblxyXG4vKipcclxuICogR2V0cyB0aGUgaGlnaCAzMiBiaXRzIGFzIGEgc2lnbmVkIGludGVnZXIuXHJcbiAqIEByZXR1cm5zIHtudW1iZXJ9IFNpZ25lZCBoaWdoIGJpdHNcclxuICovXHJcbkxvbmdQcm90b3R5cGUuZ2V0SGlnaEJpdHMgPSBmdW5jdGlvbiBnZXRIaWdoQml0cygpIHtcclxuICAgIHJldHVybiB0aGlzLmhpZ2g7XHJcbn07XHJcblxyXG4vKipcclxuICogR2V0cyB0aGUgaGlnaCAzMiBiaXRzIGFzIGFuIHVuc2lnbmVkIGludGVnZXIuXHJcbiAqIEByZXR1cm5zIHtudW1iZXJ9IFVuc2lnbmVkIGhpZ2ggYml0c1xyXG4gKi9cclxuTG9uZ1Byb3RvdHlwZS5nZXRIaWdoQml0c1Vuc2lnbmVkID0gZnVuY3Rpb24gZ2V0SGlnaEJpdHNVbnNpZ25lZCgpIHtcclxuICAgIHJldHVybiB0aGlzLmhpZ2ggPj4+IDA7XHJcbn07XHJcblxyXG4vKipcclxuICogR2V0cyB0aGUgbG93IDMyIGJpdHMgYXMgYSBzaWduZWQgaW50ZWdlci5cclxuICogQHJldHVybnMge251bWJlcn0gU2lnbmVkIGxvdyBiaXRzXHJcbiAqL1xyXG5Mb25nUHJvdG90eXBlLmdldExvd0JpdHMgPSBmdW5jdGlvbiBnZXRMb3dCaXRzKCkge1xyXG4gICAgcmV0dXJuIHRoaXMubG93O1xyXG59O1xyXG5cclxuLyoqXHJcbiAqIEdldHMgdGhlIGxvdyAzMiBiaXRzIGFzIGFuIHVuc2lnbmVkIGludGVnZXIuXHJcbiAqIEByZXR1cm5zIHtudW1iZXJ9IFVuc2lnbmVkIGxvdyBiaXRzXHJcbiAqL1xyXG5Mb25nUHJvdG90eXBlLmdldExvd0JpdHNVbnNpZ25lZCA9IGZ1bmN0aW9uIGdldExvd0JpdHNVbnNpZ25lZCgpIHtcclxuICAgIHJldHVybiB0aGlzLmxvdyA+Pj4gMDtcclxufTtcclxuXHJcbi8qKlxyXG4gKiBHZXRzIHRoZSBudW1iZXIgb2YgYml0cyBuZWVkZWQgdG8gcmVwcmVzZW50IHRoZSBhYnNvbHV0ZSB2YWx1ZSBvZiB0aGlzIExvbmcuXHJcbiAqIEByZXR1cm5zIHtudW1iZXJ9XHJcbiAqL1xyXG5Mb25nUHJvdG90eXBlLmdldE51bUJpdHNBYnMgPSBmdW5jdGlvbiBnZXROdW1CaXRzQWJzKCkge1xyXG4gICAgaWYgKHRoaXMuaXNOZWdhdGl2ZSgpKSAvLyBVbnNpZ25lZCBMb25ncyBhcmUgbmV2ZXIgbmVnYXRpdmVcclxuICAgICAgICByZXR1cm4gdGhpcy5lcShNSU5fVkFMVUUpID8gNjQgOiB0aGlzLm5lZygpLmdldE51bUJpdHNBYnMoKTtcclxuICAgIHZhciB2YWwgPSB0aGlzLmhpZ2ggIT0gMCA/IHRoaXMuaGlnaCA6IHRoaXMubG93O1xyXG4gICAgZm9yICh2YXIgYml0ID0gMzE7IGJpdCA+IDA7IGJpdC0tKVxyXG4gICAgICAgIGlmICgodmFsICYgKDEgPDwgYml0KSkgIT0gMClcclxuICAgICAgICAgICAgYnJlYWs7XHJcbiAgICByZXR1cm4gdGhpcy5oaWdoICE9IDAgPyBiaXQgKyAzMyA6IGJpdCArIDE7XHJcbn07XHJcblxyXG4vKipcclxuICogVGVzdHMgaWYgdGhpcyBMb25nJ3MgdmFsdWUgZXF1YWxzIHplcm8uXHJcbiAqIEByZXR1cm5zIHtib29sZWFufVxyXG4gKi9cclxuTG9uZ1Byb3RvdHlwZS5pc1plcm8gPSBmdW5jdGlvbiBpc1plcm8oKSB7XHJcbiAgICByZXR1cm4gdGhpcy5oaWdoID09PSAwICYmIHRoaXMubG93ID09PSAwO1xyXG59O1xyXG5cclxuLyoqXHJcbiAqIFRlc3RzIGlmIHRoaXMgTG9uZydzIHZhbHVlIGVxdWFscyB6ZXJvLiBUaGlzIGlzIGFuIGFsaWFzIG9mIHtAbGluayBMb25nI2lzWmVyb30uXHJcbiAqIEByZXR1cm5zIHtib29sZWFufVxyXG4gKi9cclxuTG9uZ1Byb3RvdHlwZS5lcXogPSBMb25nUHJvdG90eXBlLmlzWmVybztcclxuXHJcbi8qKlxyXG4gKiBUZXN0cyBpZiB0aGlzIExvbmcncyB2YWx1ZSBpcyBuZWdhdGl2ZS5cclxuICogQHJldHVybnMge2Jvb2xlYW59XHJcbiAqL1xyXG5Mb25nUHJvdG90eXBlLmlzTmVnYXRpdmUgPSBmdW5jdGlvbiBpc05lZ2F0aXZlKCkge1xyXG4gICAgcmV0dXJuICF0aGlzLnVuc2lnbmVkICYmIHRoaXMuaGlnaCA8IDA7XHJcbn07XHJcblxyXG4vKipcclxuICogVGVzdHMgaWYgdGhpcyBMb25nJ3MgdmFsdWUgaXMgcG9zaXRpdmUuXHJcbiAqIEByZXR1cm5zIHtib29sZWFufVxyXG4gKi9cclxuTG9uZ1Byb3RvdHlwZS5pc1Bvc2l0aXZlID0gZnVuY3Rpb24gaXNQb3NpdGl2ZSgpIHtcclxuICAgIHJldHVybiB0aGlzLnVuc2lnbmVkIHx8IHRoaXMuaGlnaCA+PSAwO1xyXG59O1xyXG5cclxuLyoqXHJcbiAqIFRlc3RzIGlmIHRoaXMgTG9uZydzIHZhbHVlIGlzIG9kZC5cclxuICogQHJldHVybnMge2Jvb2xlYW59XHJcbiAqL1xyXG5Mb25nUHJvdG90eXBlLmlzT2RkID0gZnVuY3Rpb24gaXNPZGQoKSB7XHJcbiAgICByZXR1cm4gKHRoaXMubG93ICYgMSkgPT09IDE7XHJcbn07XHJcblxyXG4vKipcclxuICogVGVzdHMgaWYgdGhpcyBMb25nJ3MgdmFsdWUgaXMgZXZlbi5cclxuICogQHJldHVybnMge2Jvb2xlYW59XHJcbiAqL1xyXG5Mb25nUHJvdG90eXBlLmlzRXZlbiA9IGZ1bmN0aW9uIGlzRXZlbigpIHtcclxuICAgIHJldHVybiAodGhpcy5sb3cgJiAxKSA9PT0gMDtcclxufTtcclxuXHJcbi8qKlxyXG4gKiBUZXN0cyBpZiB0aGlzIExvbmcncyB2YWx1ZSBlcXVhbHMgdGhlIHNwZWNpZmllZCdzLlxyXG4gKiBAcGFyYW0geyFMb25nfG51bWJlcnxzdHJpbmd9IG90aGVyIE90aGVyIHZhbHVlXHJcbiAqIEByZXR1cm5zIHtib29sZWFufVxyXG4gKi9cclxuTG9uZ1Byb3RvdHlwZS5lcXVhbHMgPSBmdW5jdGlvbiBlcXVhbHMob3RoZXIpIHtcclxuICAgIGlmICghaXNMb25nKG90aGVyKSlcclxuICAgICAgICBvdGhlciA9IGZyb21WYWx1ZShvdGhlcik7XHJcbiAgICBpZiAodGhpcy51bnNpZ25lZCAhPT0gb3RoZXIudW5zaWduZWQgJiYgKHRoaXMuaGlnaCA+Pj4gMzEpID09PSAxICYmIChvdGhlci5oaWdoID4+PiAzMSkgPT09IDEpXHJcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xyXG4gICAgcmV0dXJuIHRoaXMuaGlnaCA9PT0gb3RoZXIuaGlnaCAmJiB0aGlzLmxvdyA9PT0gb3RoZXIubG93O1xyXG59O1xyXG5cclxuLyoqXHJcbiAqIFRlc3RzIGlmIHRoaXMgTG9uZydzIHZhbHVlIGVxdWFscyB0aGUgc3BlY2lmaWVkJ3MuIFRoaXMgaXMgYW4gYWxpYXMgb2Yge0BsaW5rIExvbmcjZXF1YWxzfS5cclxuICogQGZ1bmN0aW9uXHJcbiAqIEBwYXJhbSB7IUxvbmd8bnVtYmVyfHN0cmluZ30gb3RoZXIgT3RoZXIgdmFsdWVcclxuICogQHJldHVybnMge2Jvb2xlYW59XHJcbiAqL1xyXG5Mb25nUHJvdG90eXBlLmVxID0gTG9uZ1Byb3RvdHlwZS5lcXVhbHM7XHJcblxyXG4vKipcclxuICogVGVzdHMgaWYgdGhpcyBMb25nJ3MgdmFsdWUgZGlmZmVycyBmcm9tIHRoZSBzcGVjaWZpZWQncy5cclxuICogQHBhcmFtIHshTG9uZ3xudW1iZXJ8c3RyaW5nfSBvdGhlciBPdGhlciB2YWx1ZVxyXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn1cclxuICovXHJcbkxvbmdQcm90b3R5cGUubm90RXF1YWxzID0gZnVuY3Rpb24gbm90RXF1YWxzKG90aGVyKSB7XHJcbiAgICByZXR1cm4gIXRoaXMuZXEoLyogdmFsaWRhdGVzICovIG90aGVyKTtcclxufTtcclxuXHJcbi8qKlxyXG4gKiBUZXN0cyBpZiB0aGlzIExvbmcncyB2YWx1ZSBkaWZmZXJzIGZyb20gdGhlIHNwZWNpZmllZCdzLiBUaGlzIGlzIGFuIGFsaWFzIG9mIHtAbGluayBMb25nI25vdEVxdWFsc30uXHJcbiAqIEBmdW5jdGlvblxyXG4gKiBAcGFyYW0geyFMb25nfG51bWJlcnxzdHJpbmd9IG90aGVyIE90aGVyIHZhbHVlXHJcbiAqIEByZXR1cm5zIHtib29sZWFufVxyXG4gKi9cclxuTG9uZ1Byb3RvdHlwZS5uZXEgPSBMb25nUHJvdG90eXBlLm5vdEVxdWFscztcclxuXHJcbi8qKlxyXG4gKiBUZXN0cyBpZiB0aGlzIExvbmcncyB2YWx1ZSBkaWZmZXJzIGZyb20gdGhlIHNwZWNpZmllZCdzLiBUaGlzIGlzIGFuIGFsaWFzIG9mIHtAbGluayBMb25nI25vdEVxdWFsc30uXHJcbiAqIEBmdW5jdGlvblxyXG4gKiBAcGFyYW0geyFMb25nfG51bWJlcnxzdHJpbmd9IG90aGVyIE90aGVyIHZhbHVlXHJcbiAqIEByZXR1cm5zIHtib29sZWFufVxyXG4gKi9cclxuTG9uZ1Byb3RvdHlwZS5uZSA9IExvbmdQcm90b3R5cGUubm90RXF1YWxzO1xyXG5cclxuLyoqXHJcbiAqIFRlc3RzIGlmIHRoaXMgTG9uZydzIHZhbHVlIGlzIGxlc3MgdGhhbiB0aGUgc3BlY2lmaWVkJ3MuXHJcbiAqIEBwYXJhbSB7IUxvbmd8bnVtYmVyfHN0cmluZ30gb3RoZXIgT3RoZXIgdmFsdWVcclxuICogQHJldHVybnMge2Jvb2xlYW59XHJcbiAqL1xyXG5Mb25nUHJvdG90eXBlLmxlc3NUaGFuID0gZnVuY3Rpb24gbGVzc1RoYW4ob3RoZXIpIHtcclxuICAgIHJldHVybiB0aGlzLmNvbXAoLyogdmFsaWRhdGVzICovIG90aGVyKSA8IDA7XHJcbn07XHJcblxyXG4vKipcclxuICogVGVzdHMgaWYgdGhpcyBMb25nJ3MgdmFsdWUgaXMgbGVzcyB0aGFuIHRoZSBzcGVjaWZpZWQncy4gVGhpcyBpcyBhbiBhbGlhcyBvZiB7QGxpbmsgTG9uZyNsZXNzVGhhbn0uXHJcbiAqIEBmdW5jdGlvblxyXG4gKiBAcGFyYW0geyFMb25nfG51bWJlcnxzdHJpbmd9IG90aGVyIE90aGVyIHZhbHVlXHJcbiAqIEByZXR1cm5zIHtib29sZWFufVxyXG4gKi9cclxuTG9uZ1Byb3RvdHlwZS5sdCA9IExvbmdQcm90b3R5cGUubGVzc1RoYW47XHJcblxyXG4vKipcclxuICogVGVzdHMgaWYgdGhpcyBMb25nJ3MgdmFsdWUgaXMgbGVzcyB0aGFuIG9yIGVxdWFsIHRoZSBzcGVjaWZpZWQncy5cclxuICogQHBhcmFtIHshTG9uZ3xudW1iZXJ8c3RyaW5nfSBvdGhlciBPdGhlciB2YWx1ZVxyXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn1cclxuICovXHJcbkxvbmdQcm90b3R5cGUubGVzc1RoYW5PckVxdWFsID0gZnVuY3Rpb24gbGVzc1RoYW5PckVxdWFsKG90aGVyKSB7XHJcbiAgICByZXR1cm4gdGhpcy5jb21wKC8qIHZhbGlkYXRlcyAqLyBvdGhlcikgPD0gMDtcclxufTtcclxuXHJcbi8qKlxyXG4gKiBUZXN0cyBpZiB0aGlzIExvbmcncyB2YWx1ZSBpcyBsZXNzIHRoYW4gb3IgZXF1YWwgdGhlIHNwZWNpZmllZCdzLiBUaGlzIGlzIGFuIGFsaWFzIG9mIHtAbGluayBMb25nI2xlc3NUaGFuT3JFcXVhbH0uXHJcbiAqIEBmdW5jdGlvblxyXG4gKiBAcGFyYW0geyFMb25nfG51bWJlcnxzdHJpbmd9IG90aGVyIE90aGVyIHZhbHVlXHJcbiAqIEByZXR1cm5zIHtib29sZWFufVxyXG4gKi9cclxuTG9uZ1Byb3RvdHlwZS5sdGUgPSBMb25nUHJvdG90eXBlLmxlc3NUaGFuT3JFcXVhbDtcclxuXHJcbi8qKlxyXG4gKiBUZXN0cyBpZiB0aGlzIExvbmcncyB2YWx1ZSBpcyBsZXNzIHRoYW4gb3IgZXF1YWwgdGhlIHNwZWNpZmllZCdzLiBUaGlzIGlzIGFuIGFsaWFzIG9mIHtAbGluayBMb25nI2xlc3NUaGFuT3JFcXVhbH0uXHJcbiAqIEBmdW5jdGlvblxyXG4gKiBAcGFyYW0geyFMb25nfG51bWJlcnxzdHJpbmd9IG90aGVyIE90aGVyIHZhbHVlXHJcbiAqIEByZXR1cm5zIHtib29sZWFufVxyXG4gKi9cclxuTG9uZ1Byb3RvdHlwZS5sZSA9IExvbmdQcm90b3R5cGUubGVzc1RoYW5PckVxdWFsO1xyXG5cclxuLyoqXHJcbiAqIFRlc3RzIGlmIHRoaXMgTG9uZydzIHZhbHVlIGlzIGdyZWF0ZXIgdGhhbiB0aGUgc3BlY2lmaWVkJ3MuXHJcbiAqIEBwYXJhbSB7IUxvbmd8bnVtYmVyfHN0cmluZ30gb3RoZXIgT3RoZXIgdmFsdWVcclxuICogQHJldHVybnMge2Jvb2xlYW59XHJcbiAqL1xyXG5Mb25nUHJvdG90eXBlLmdyZWF0ZXJUaGFuID0gZnVuY3Rpb24gZ3JlYXRlclRoYW4ob3RoZXIpIHtcclxuICAgIHJldHVybiB0aGlzLmNvbXAoLyogdmFsaWRhdGVzICovIG90aGVyKSA+IDA7XHJcbn07XHJcblxyXG4vKipcclxuICogVGVzdHMgaWYgdGhpcyBMb25nJ3MgdmFsdWUgaXMgZ3JlYXRlciB0aGFuIHRoZSBzcGVjaWZpZWQncy4gVGhpcyBpcyBhbiBhbGlhcyBvZiB7QGxpbmsgTG9uZyNncmVhdGVyVGhhbn0uXHJcbiAqIEBmdW5jdGlvblxyXG4gKiBAcGFyYW0geyFMb25nfG51bWJlcnxzdHJpbmd9IG90aGVyIE90aGVyIHZhbHVlXHJcbiAqIEByZXR1cm5zIHtib29sZWFufVxyXG4gKi9cclxuTG9uZ1Byb3RvdHlwZS5ndCA9IExvbmdQcm90b3R5cGUuZ3JlYXRlclRoYW47XHJcblxyXG4vKipcclxuICogVGVzdHMgaWYgdGhpcyBMb25nJ3MgdmFsdWUgaXMgZ3JlYXRlciB0aGFuIG9yIGVxdWFsIHRoZSBzcGVjaWZpZWQncy5cclxuICogQHBhcmFtIHshTG9uZ3xudW1iZXJ8c3RyaW5nfSBvdGhlciBPdGhlciB2YWx1ZVxyXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn1cclxuICovXHJcbkxvbmdQcm90b3R5cGUuZ3JlYXRlclRoYW5PckVxdWFsID0gZnVuY3Rpb24gZ3JlYXRlclRoYW5PckVxdWFsKG90aGVyKSB7XHJcbiAgICByZXR1cm4gdGhpcy5jb21wKC8qIHZhbGlkYXRlcyAqLyBvdGhlcikgPj0gMDtcclxufTtcclxuXHJcbi8qKlxyXG4gKiBUZXN0cyBpZiB0aGlzIExvbmcncyB2YWx1ZSBpcyBncmVhdGVyIHRoYW4gb3IgZXF1YWwgdGhlIHNwZWNpZmllZCdzLiBUaGlzIGlzIGFuIGFsaWFzIG9mIHtAbGluayBMb25nI2dyZWF0ZXJUaGFuT3JFcXVhbH0uXHJcbiAqIEBmdW5jdGlvblxyXG4gKiBAcGFyYW0geyFMb25nfG51bWJlcnxzdHJpbmd9IG90aGVyIE90aGVyIHZhbHVlXHJcbiAqIEByZXR1cm5zIHtib29sZWFufVxyXG4gKi9cclxuTG9uZ1Byb3RvdHlwZS5ndGUgPSBMb25nUHJvdG90eXBlLmdyZWF0ZXJUaGFuT3JFcXVhbDtcclxuXHJcbi8qKlxyXG4gKiBUZXN0cyBpZiB0aGlzIExvbmcncyB2YWx1ZSBpcyBncmVhdGVyIHRoYW4gb3IgZXF1YWwgdGhlIHNwZWNpZmllZCdzLiBUaGlzIGlzIGFuIGFsaWFzIG9mIHtAbGluayBMb25nI2dyZWF0ZXJUaGFuT3JFcXVhbH0uXHJcbiAqIEBmdW5jdGlvblxyXG4gKiBAcGFyYW0geyFMb25nfG51bWJlcnxzdHJpbmd9IG90aGVyIE90aGVyIHZhbHVlXHJcbiAqIEByZXR1cm5zIHtib29sZWFufVxyXG4gKi9cclxuTG9uZ1Byb3RvdHlwZS5nZSA9IExvbmdQcm90b3R5cGUuZ3JlYXRlclRoYW5PckVxdWFsO1xyXG5cclxuLyoqXHJcbiAqIENvbXBhcmVzIHRoaXMgTG9uZydzIHZhbHVlIHdpdGggdGhlIHNwZWNpZmllZCdzLlxyXG4gKiBAcGFyYW0geyFMb25nfG51bWJlcnxzdHJpbmd9IG90aGVyIE90aGVyIHZhbHVlXHJcbiAqIEByZXR1cm5zIHtudW1iZXJ9IDAgaWYgdGhleSBhcmUgdGhlIHNhbWUsIDEgaWYgdGhlIHRoaXMgaXMgZ3JlYXRlciBhbmQgLTFcclxuICogIGlmIHRoZSBnaXZlbiBvbmUgaXMgZ3JlYXRlclxyXG4gKi9cclxuTG9uZ1Byb3RvdHlwZS5jb21wYXJlID0gZnVuY3Rpb24gY29tcGFyZShvdGhlcikge1xyXG4gICAgaWYgKCFpc0xvbmcob3RoZXIpKVxyXG4gICAgICAgIG90aGVyID0gZnJvbVZhbHVlKG90aGVyKTtcclxuICAgIGlmICh0aGlzLmVxKG90aGVyKSlcclxuICAgICAgICByZXR1cm4gMDtcclxuICAgIHZhciB0aGlzTmVnID0gdGhpcy5pc05lZ2F0aXZlKCksXHJcbiAgICAgICAgb3RoZXJOZWcgPSBvdGhlci5pc05lZ2F0aXZlKCk7XHJcbiAgICBpZiAodGhpc05lZyAmJiAhb3RoZXJOZWcpXHJcbiAgICAgICAgcmV0dXJuIC0xO1xyXG4gICAgaWYgKCF0aGlzTmVnICYmIG90aGVyTmVnKVxyXG4gICAgICAgIHJldHVybiAxO1xyXG4gICAgLy8gQXQgdGhpcyBwb2ludCB0aGUgc2lnbiBiaXRzIGFyZSB0aGUgc2FtZVxyXG4gICAgaWYgKCF0aGlzLnVuc2lnbmVkKVxyXG4gICAgICAgIHJldHVybiB0aGlzLnN1YihvdGhlcikuaXNOZWdhdGl2ZSgpID8gLTEgOiAxO1xyXG4gICAgLy8gQm90aCBhcmUgcG9zaXRpdmUgaWYgYXQgbGVhc3Qgb25lIGlzIHVuc2lnbmVkXHJcbiAgICByZXR1cm4gKG90aGVyLmhpZ2ggPj4+IDApID4gKHRoaXMuaGlnaCA+Pj4gMCkgfHwgKG90aGVyLmhpZ2ggPT09IHRoaXMuaGlnaCAmJiAob3RoZXIubG93ID4+PiAwKSA+ICh0aGlzLmxvdyA+Pj4gMCkpID8gLTEgOiAxO1xyXG59O1xyXG5cclxuLyoqXHJcbiAqIENvbXBhcmVzIHRoaXMgTG9uZydzIHZhbHVlIHdpdGggdGhlIHNwZWNpZmllZCdzLiBUaGlzIGlzIGFuIGFsaWFzIG9mIHtAbGluayBMb25nI2NvbXBhcmV9LlxyXG4gKiBAZnVuY3Rpb25cclxuICogQHBhcmFtIHshTG9uZ3xudW1iZXJ8c3RyaW5nfSBvdGhlciBPdGhlciB2YWx1ZVxyXG4gKiBAcmV0dXJucyB7bnVtYmVyfSAwIGlmIHRoZXkgYXJlIHRoZSBzYW1lLCAxIGlmIHRoZSB0aGlzIGlzIGdyZWF0ZXIgYW5kIC0xXHJcbiAqICBpZiB0aGUgZ2l2ZW4gb25lIGlzIGdyZWF0ZXJcclxuICovXHJcbkxvbmdQcm90b3R5cGUuY29tcCA9IExvbmdQcm90b3R5cGUuY29tcGFyZTtcclxuXHJcbi8qKlxyXG4gKiBOZWdhdGVzIHRoaXMgTG9uZydzIHZhbHVlLlxyXG4gKiBAcmV0dXJucyB7IUxvbmd9IE5lZ2F0ZWQgTG9uZ1xyXG4gKi9cclxuTG9uZ1Byb3RvdHlwZS5uZWdhdGUgPSBmdW5jdGlvbiBuZWdhdGUoKSB7XHJcbiAgICBpZiAoIXRoaXMudW5zaWduZWQgJiYgdGhpcy5lcShNSU5fVkFMVUUpKVxyXG4gICAgICAgIHJldHVybiBNSU5fVkFMVUU7XHJcbiAgICByZXR1cm4gdGhpcy5ub3QoKS5hZGQoT05FKTtcclxufTtcclxuXHJcbi8qKlxyXG4gKiBOZWdhdGVzIHRoaXMgTG9uZydzIHZhbHVlLiBUaGlzIGlzIGFuIGFsaWFzIG9mIHtAbGluayBMb25nI25lZ2F0ZX0uXHJcbiAqIEBmdW5jdGlvblxyXG4gKiBAcmV0dXJucyB7IUxvbmd9IE5lZ2F0ZWQgTG9uZ1xyXG4gKi9cclxuTG9uZ1Byb3RvdHlwZS5uZWcgPSBMb25nUHJvdG90eXBlLm5lZ2F0ZTtcclxuXHJcbi8qKlxyXG4gKiBSZXR1cm5zIHRoZSBzdW0gb2YgdGhpcyBhbmQgdGhlIHNwZWNpZmllZCBMb25nLlxyXG4gKiBAcGFyYW0geyFMb25nfG51bWJlcnxzdHJpbmd9IGFkZGVuZCBBZGRlbmRcclxuICogQHJldHVybnMgeyFMb25nfSBTdW1cclxuICovXHJcbkxvbmdQcm90b3R5cGUuYWRkID0gZnVuY3Rpb24gYWRkKGFkZGVuZCkge1xyXG4gICAgaWYgKCFpc0xvbmcoYWRkZW5kKSlcclxuICAgICAgICBhZGRlbmQgPSBmcm9tVmFsdWUoYWRkZW5kKTtcclxuXHJcbiAgICAvLyBEaXZpZGUgZWFjaCBudW1iZXIgaW50byA0IGNodW5rcyBvZiAxNiBiaXRzLCBhbmQgdGhlbiBzdW0gdGhlIGNodW5rcy5cclxuXHJcbiAgICB2YXIgYTQ4ID0gdGhpcy5oaWdoID4+PiAxNjtcclxuICAgIHZhciBhMzIgPSB0aGlzLmhpZ2ggJiAweEZGRkY7XHJcbiAgICB2YXIgYTE2ID0gdGhpcy5sb3cgPj4+IDE2O1xyXG4gICAgdmFyIGEwMCA9IHRoaXMubG93ICYgMHhGRkZGO1xyXG5cclxuICAgIHZhciBiNDggPSBhZGRlbmQuaGlnaCA+Pj4gMTY7XHJcbiAgICB2YXIgYjMyID0gYWRkZW5kLmhpZ2ggJiAweEZGRkY7XHJcbiAgICB2YXIgYjE2ID0gYWRkZW5kLmxvdyA+Pj4gMTY7XHJcbiAgICB2YXIgYjAwID0gYWRkZW5kLmxvdyAmIDB4RkZGRjtcclxuXHJcbiAgICB2YXIgYzQ4ID0gMCwgYzMyID0gMCwgYzE2ID0gMCwgYzAwID0gMDtcclxuICAgIGMwMCArPSBhMDAgKyBiMDA7XHJcbiAgICBjMTYgKz0gYzAwID4+PiAxNjtcclxuICAgIGMwMCAmPSAweEZGRkY7XHJcbiAgICBjMTYgKz0gYTE2ICsgYjE2O1xyXG4gICAgYzMyICs9IGMxNiA+Pj4gMTY7XHJcbiAgICBjMTYgJj0gMHhGRkZGO1xyXG4gICAgYzMyICs9IGEzMiArIGIzMjtcclxuICAgIGM0OCArPSBjMzIgPj4+IDE2O1xyXG4gICAgYzMyICY9IDB4RkZGRjtcclxuICAgIGM0OCArPSBhNDggKyBiNDg7XHJcbiAgICBjNDggJj0gMHhGRkZGO1xyXG4gICAgcmV0dXJuIGZyb21CaXRzKChjMTYgPDwgMTYpIHwgYzAwLCAoYzQ4IDw8IDE2KSB8IGMzMiwgdGhpcy51bnNpZ25lZCk7XHJcbn07XHJcblxyXG4vKipcclxuICogUmV0dXJucyB0aGUgZGlmZmVyZW5jZSBvZiB0aGlzIGFuZCB0aGUgc3BlY2lmaWVkIExvbmcuXHJcbiAqIEBwYXJhbSB7IUxvbmd8bnVtYmVyfHN0cmluZ30gc3VidHJhaGVuZCBTdWJ0cmFoZW5kXHJcbiAqIEByZXR1cm5zIHshTG9uZ30gRGlmZmVyZW5jZVxyXG4gKi9cclxuTG9uZ1Byb3RvdHlwZS5zdWJ0cmFjdCA9IGZ1bmN0aW9uIHN1YnRyYWN0KHN1YnRyYWhlbmQpIHtcclxuICAgIGlmICghaXNMb25nKHN1YnRyYWhlbmQpKVxyXG4gICAgICAgIHN1YnRyYWhlbmQgPSBmcm9tVmFsdWUoc3VidHJhaGVuZCk7XHJcbiAgICByZXR1cm4gdGhpcy5hZGQoc3VidHJhaGVuZC5uZWcoKSk7XHJcbn07XHJcblxyXG4vKipcclxuICogUmV0dXJucyB0aGUgZGlmZmVyZW5jZSBvZiB0aGlzIGFuZCB0aGUgc3BlY2lmaWVkIExvbmcuIFRoaXMgaXMgYW4gYWxpYXMgb2Yge0BsaW5rIExvbmcjc3VidHJhY3R9LlxyXG4gKiBAZnVuY3Rpb25cclxuICogQHBhcmFtIHshTG9uZ3xudW1iZXJ8c3RyaW5nfSBzdWJ0cmFoZW5kIFN1YnRyYWhlbmRcclxuICogQHJldHVybnMgeyFMb25nfSBEaWZmZXJlbmNlXHJcbiAqL1xyXG5Mb25nUHJvdG90eXBlLnN1YiA9IExvbmdQcm90b3R5cGUuc3VidHJhY3Q7XHJcblxyXG4vKipcclxuICogUmV0dXJucyB0aGUgcHJvZHVjdCBvZiB0aGlzIGFuZCB0aGUgc3BlY2lmaWVkIExvbmcuXHJcbiAqIEBwYXJhbSB7IUxvbmd8bnVtYmVyfHN0cmluZ30gbXVsdGlwbGllciBNdWx0aXBsaWVyXHJcbiAqIEByZXR1cm5zIHshTG9uZ30gUHJvZHVjdFxyXG4gKi9cclxuTG9uZ1Byb3RvdHlwZS5tdWx0aXBseSA9IGZ1bmN0aW9uIG11bHRpcGx5KG11bHRpcGxpZXIpIHtcclxuICAgIGlmICh0aGlzLmlzWmVybygpKVxyXG4gICAgICAgIHJldHVybiBaRVJPO1xyXG4gICAgaWYgKCFpc0xvbmcobXVsdGlwbGllcikpXHJcbiAgICAgICAgbXVsdGlwbGllciA9IGZyb21WYWx1ZShtdWx0aXBsaWVyKTtcclxuXHJcbiAgICAvLyB1c2Ugd2FzbSBzdXBwb3J0IGlmIHByZXNlbnRcclxuICAgIGlmICh3YXNtKSB7XHJcbiAgICAgICAgdmFyIGxvdyA9IHdhc20ubXVsKHRoaXMubG93LFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmhpZ2gsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgIG11bHRpcGxpZXIubG93LFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICBtdWx0aXBsaWVyLmhpZ2gpO1xyXG4gICAgICAgIHJldHVybiBmcm9tQml0cyhsb3csIHdhc20uZ2V0X2hpZ2goKSwgdGhpcy51bnNpZ25lZCk7XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKG11bHRpcGxpZXIuaXNaZXJvKCkpXHJcbiAgICAgICAgcmV0dXJuIFpFUk87XHJcbiAgICBpZiAodGhpcy5lcShNSU5fVkFMVUUpKVxyXG4gICAgICAgIHJldHVybiBtdWx0aXBsaWVyLmlzT2RkKCkgPyBNSU5fVkFMVUUgOiBaRVJPO1xyXG4gICAgaWYgKG11bHRpcGxpZXIuZXEoTUlOX1ZBTFVFKSlcclxuICAgICAgICByZXR1cm4gdGhpcy5pc09kZCgpID8gTUlOX1ZBTFVFIDogWkVSTztcclxuXHJcbiAgICBpZiAodGhpcy5pc05lZ2F0aXZlKCkpIHtcclxuICAgICAgICBpZiAobXVsdGlwbGllci5pc05lZ2F0aXZlKCkpXHJcbiAgICAgICAgICAgIHJldHVybiB0aGlzLm5lZygpLm11bChtdWx0aXBsaWVyLm5lZygpKTtcclxuICAgICAgICBlbHNlXHJcbiAgICAgICAgICAgIHJldHVybiB0aGlzLm5lZygpLm11bChtdWx0aXBsaWVyKS5uZWcoKTtcclxuICAgIH0gZWxzZSBpZiAobXVsdGlwbGllci5pc05lZ2F0aXZlKCkpXHJcbiAgICAgICAgcmV0dXJuIHRoaXMubXVsKG11bHRpcGxpZXIubmVnKCkpLm5lZygpO1xyXG5cclxuICAgIC8vIElmIGJvdGggbG9uZ3MgYXJlIHNtYWxsLCB1c2UgZmxvYXQgbXVsdGlwbGljYXRpb25cclxuICAgIGlmICh0aGlzLmx0KFRXT19QV1JfMjQpICYmIG11bHRpcGxpZXIubHQoVFdPX1BXUl8yNCkpXHJcbiAgICAgICAgcmV0dXJuIGZyb21OdW1iZXIodGhpcy50b051bWJlcigpICogbXVsdGlwbGllci50b051bWJlcigpLCB0aGlzLnVuc2lnbmVkKTtcclxuXHJcbiAgICAvLyBEaXZpZGUgZWFjaCBsb25nIGludG8gNCBjaHVua3Mgb2YgMTYgYml0cywgYW5kIHRoZW4gYWRkIHVwIDR4NCBwcm9kdWN0cy5cclxuICAgIC8vIFdlIGNhbiBza2lwIHByb2R1Y3RzIHRoYXQgd291bGQgb3ZlcmZsb3cuXHJcblxyXG4gICAgdmFyIGE0OCA9IHRoaXMuaGlnaCA+Pj4gMTY7XHJcbiAgICB2YXIgYTMyID0gdGhpcy5oaWdoICYgMHhGRkZGO1xyXG4gICAgdmFyIGExNiA9IHRoaXMubG93ID4+PiAxNjtcclxuICAgIHZhciBhMDAgPSB0aGlzLmxvdyAmIDB4RkZGRjtcclxuXHJcbiAgICB2YXIgYjQ4ID0gbXVsdGlwbGllci5oaWdoID4+PiAxNjtcclxuICAgIHZhciBiMzIgPSBtdWx0aXBsaWVyLmhpZ2ggJiAweEZGRkY7XHJcbiAgICB2YXIgYjE2ID0gbXVsdGlwbGllci5sb3cgPj4+IDE2O1xyXG4gICAgdmFyIGIwMCA9IG11bHRpcGxpZXIubG93ICYgMHhGRkZGO1xyXG5cclxuICAgIHZhciBjNDggPSAwLCBjMzIgPSAwLCBjMTYgPSAwLCBjMDAgPSAwO1xyXG4gICAgYzAwICs9IGEwMCAqIGIwMDtcclxuICAgIGMxNiArPSBjMDAgPj4+IDE2O1xyXG4gICAgYzAwICY9IDB4RkZGRjtcclxuICAgIGMxNiArPSBhMTYgKiBiMDA7XHJcbiAgICBjMzIgKz0gYzE2ID4+PiAxNjtcclxuICAgIGMxNiAmPSAweEZGRkY7XHJcbiAgICBjMTYgKz0gYTAwICogYjE2O1xyXG4gICAgYzMyICs9IGMxNiA+Pj4gMTY7XHJcbiAgICBjMTYgJj0gMHhGRkZGO1xyXG4gICAgYzMyICs9IGEzMiAqIGIwMDtcclxuICAgIGM0OCArPSBjMzIgPj4+IDE2O1xyXG4gICAgYzMyICY9IDB4RkZGRjtcclxuICAgIGMzMiArPSBhMTYgKiBiMTY7XHJcbiAgICBjNDggKz0gYzMyID4+PiAxNjtcclxuICAgIGMzMiAmPSAweEZGRkY7XHJcbiAgICBjMzIgKz0gYTAwICogYjMyO1xyXG4gICAgYzQ4ICs9IGMzMiA+Pj4gMTY7XHJcbiAgICBjMzIgJj0gMHhGRkZGO1xyXG4gICAgYzQ4ICs9IGE0OCAqIGIwMCArIGEzMiAqIGIxNiArIGExNiAqIGIzMiArIGEwMCAqIGI0ODtcclxuICAgIGM0OCAmPSAweEZGRkY7XHJcbiAgICByZXR1cm4gZnJvbUJpdHMoKGMxNiA8PCAxNikgfCBjMDAsIChjNDggPDwgMTYpIHwgYzMyLCB0aGlzLnVuc2lnbmVkKTtcclxufTtcclxuXHJcbi8qKlxyXG4gKiBSZXR1cm5zIHRoZSBwcm9kdWN0IG9mIHRoaXMgYW5kIHRoZSBzcGVjaWZpZWQgTG9uZy4gVGhpcyBpcyBhbiBhbGlhcyBvZiB7QGxpbmsgTG9uZyNtdWx0aXBseX0uXHJcbiAqIEBmdW5jdGlvblxyXG4gKiBAcGFyYW0geyFMb25nfG51bWJlcnxzdHJpbmd9IG11bHRpcGxpZXIgTXVsdGlwbGllclxyXG4gKiBAcmV0dXJucyB7IUxvbmd9IFByb2R1Y3RcclxuICovXHJcbkxvbmdQcm90b3R5cGUubXVsID0gTG9uZ1Byb3RvdHlwZS5tdWx0aXBseTtcclxuXHJcbi8qKlxyXG4gKiBSZXR1cm5zIHRoaXMgTG9uZyBkaXZpZGVkIGJ5IHRoZSBzcGVjaWZpZWQuIFRoZSByZXN1bHQgaXMgc2lnbmVkIGlmIHRoaXMgTG9uZyBpcyBzaWduZWQgb3JcclxuICogIHVuc2lnbmVkIGlmIHRoaXMgTG9uZyBpcyB1bnNpZ25lZC5cclxuICogQHBhcmFtIHshTG9uZ3xudW1iZXJ8c3RyaW5nfSBkaXZpc29yIERpdmlzb3JcclxuICogQHJldHVybnMgeyFMb25nfSBRdW90aWVudFxyXG4gKi9cclxuTG9uZ1Byb3RvdHlwZS5kaXZpZGUgPSBmdW5jdGlvbiBkaXZpZGUoZGl2aXNvcikge1xyXG4gICAgaWYgKCFpc0xvbmcoZGl2aXNvcikpXHJcbiAgICAgICAgZGl2aXNvciA9IGZyb21WYWx1ZShkaXZpc29yKTtcclxuICAgIGlmIChkaXZpc29yLmlzWmVybygpKVxyXG4gICAgICAgIHRocm93IEVycm9yKCdkaXZpc2lvbiBieSB6ZXJvJyk7XHJcblxyXG4gICAgLy8gdXNlIHdhc20gc3VwcG9ydCBpZiBwcmVzZW50XHJcbiAgICBpZiAod2FzbSkge1xyXG4gICAgICAgIC8vIGd1YXJkIGFnYWluc3Qgc2lnbmVkIGRpdmlzaW9uIG92ZXJmbG93OiB0aGUgbGFyZ2VzdFxyXG4gICAgICAgIC8vIG5lZ2F0aXZlIG51bWJlciAvIC0xIHdvdWxkIGJlIDEgbGFyZ2VyIHRoYW4gdGhlIGxhcmdlc3RcclxuICAgICAgICAvLyBwb3NpdGl2ZSBudW1iZXIsIGR1ZSB0byB0d28ncyBjb21wbGVtZW50LlxyXG4gICAgICAgIGlmICghdGhpcy51bnNpZ25lZCAmJlxyXG4gICAgICAgICAgICB0aGlzLmhpZ2ggPT09IC0weDgwMDAwMDAwICYmXHJcbiAgICAgICAgICAgIGRpdmlzb3IubG93ID09PSAtMSAmJiBkaXZpc29yLmhpZ2ggPT09IC0xKSB7XHJcbiAgICAgICAgICAgIC8vIGJlIGNvbnNpc3RlbnQgd2l0aCBub24td2FzbSBjb2RlIHBhdGhcclxuICAgICAgICAgICAgcmV0dXJuIHRoaXM7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHZhciBsb3cgPSAodGhpcy51bnNpZ25lZCA/IHdhc20uZGl2X3UgOiB3YXNtLmRpdl9zKShcclxuICAgICAgICAgICAgdGhpcy5sb3csXHJcbiAgICAgICAgICAgIHRoaXMuaGlnaCxcclxuICAgICAgICAgICAgZGl2aXNvci5sb3csXHJcbiAgICAgICAgICAgIGRpdmlzb3IuaGlnaFxyXG4gICAgICAgICk7XHJcbiAgICAgICAgcmV0dXJuIGZyb21CaXRzKGxvdywgd2FzbS5nZXRfaGlnaCgpLCB0aGlzLnVuc2lnbmVkKTtcclxuICAgIH1cclxuXHJcbiAgICBpZiAodGhpcy5pc1plcm8oKSlcclxuICAgICAgICByZXR1cm4gdGhpcy51bnNpZ25lZCA/IFVaRVJPIDogWkVSTztcclxuICAgIHZhciBhcHByb3gsIHJlbSwgcmVzO1xyXG4gICAgaWYgKCF0aGlzLnVuc2lnbmVkKSB7XHJcbiAgICAgICAgLy8gVGhpcyBzZWN0aW9uIGlzIG9ubHkgcmVsZXZhbnQgZm9yIHNpZ25lZCBsb25ncyBhbmQgaXMgZGVyaXZlZCBmcm9tIHRoZVxyXG4gICAgICAgIC8vIGNsb3N1cmUgbGlicmFyeSBhcyBhIHdob2xlLlxyXG4gICAgICAgIGlmICh0aGlzLmVxKE1JTl9WQUxVRSkpIHtcclxuICAgICAgICAgICAgaWYgKGRpdmlzb3IuZXEoT05FKSB8fCBkaXZpc29yLmVxKE5FR19PTkUpKVxyXG4gICAgICAgICAgICAgICAgcmV0dXJuIE1JTl9WQUxVRTsgIC8vIHJlY2FsbCB0aGF0IC1NSU5fVkFMVUUgPT0gTUlOX1ZBTFVFXHJcbiAgICAgICAgICAgIGVsc2UgaWYgKGRpdmlzb3IuZXEoTUlOX1ZBTFVFKSlcclxuICAgICAgICAgICAgICAgIHJldHVybiBPTkU7XHJcbiAgICAgICAgICAgIGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgLy8gQXQgdGhpcyBwb2ludCwgd2UgaGF2ZSB8b3RoZXJ8ID49IDIsIHNvIHx0aGlzL290aGVyfCA8IHxNSU5fVkFMVUV8LlxyXG4gICAgICAgICAgICAgICAgdmFyIGhhbGZUaGlzID0gdGhpcy5zaHIoMSk7XHJcbiAgICAgICAgICAgICAgICBhcHByb3ggPSBoYWxmVGhpcy5kaXYoZGl2aXNvcikuc2hsKDEpO1xyXG4gICAgICAgICAgICAgICAgaWYgKGFwcHJveC5lcShaRVJPKSkge1xyXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBkaXZpc29yLmlzTmVnYXRpdmUoKSA/IE9ORSA6IE5FR19PTkU7XHJcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgICAgIHJlbSA9IHRoaXMuc3ViKGRpdmlzb3IubXVsKGFwcHJveCkpO1xyXG4gICAgICAgICAgICAgICAgICAgIHJlcyA9IGFwcHJveC5hZGQocmVtLmRpdihkaXZpc29yKSk7XHJcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlcztcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH0gZWxzZSBpZiAoZGl2aXNvci5lcShNSU5fVkFMVUUpKVxyXG4gICAgICAgICAgICByZXR1cm4gdGhpcy51bnNpZ25lZCA/IFVaRVJPIDogWkVSTztcclxuICAgICAgICBpZiAodGhpcy5pc05lZ2F0aXZlKCkpIHtcclxuICAgICAgICAgICAgaWYgKGRpdmlzb3IuaXNOZWdhdGl2ZSgpKVxyXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMubmVnKCkuZGl2KGRpdmlzb3IubmVnKCkpO1xyXG4gICAgICAgICAgICByZXR1cm4gdGhpcy5uZWcoKS5kaXYoZGl2aXNvcikubmVnKCk7XHJcbiAgICAgICAgfSBlbHNlIGlmIChkaXZpc29yLmlzTmVnYXRpdmUoKSlcclxuICAgICAgICAgICAgcmV0dXJuIHRoaXMuZGl2KGRpdmlzb3IubmVnKCkpLm5lZygpO1xyXG4gICAgICAgIHJlcyA9IFpFUk87XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICAgIC8vIFRoZSBhbGdvcml0aG0gYmVsb3cgaGFzIG5vdCBiZWVuIG1hZGUgZm9yIHVuc2lnbmVkIGxvbmdzLiBJdCdzIHRoZXJlZm9yZVxyXG4gICAgICAgIC8vIHJlcXVpcmVkIHRvIHRha2Ugc3BlY2lhbCBjYXJlIG9mIHRoZSBNU0IgcHJpb3IgdG8gcnVubmluZyBpdC5cclxuICAgICAgICBpZiAoIWRpdmlzb3IudW5zaWduZWQpXHJcbiAgICAgICAgICAgIGRpdmlzb3IgPSBkaXZpc29yLnRvVW5zaWduZWQoKTtcclxuICAgICAgICBpZiAoZGl2aXNvci5ndCh0aGlzKSlcclxuICAgICAgICAgICAgcmV0dXJuIFVaRVJPO1xyXG4gICAgICAgIGlmIChkaXZpc29yLmd0KHRoaXMuc2hydSgxKSkpIC8vIDE1ID4+PiAxID0gNyA7IHdpdGggZGl2aXNvciA9IDggOyB0cnVlXHJcbiAgICAgICAgICAgIHJldHVybiBVT05FO1xyXG4gICAgICAgIHJlcyA9IFVaRVJPO1xyXG4gICAgfVxyXG5cclxuICAgIC8vIFJlcGVhdCB0aGUgZm9sbG93aW5nIHVudGlsIHRoZSByZW1haW5kZXIgaXMgbGVzcyB0aGFuIG90aGVyOiAgZmluZCBhXHJcbiAgICAvLyBmbG9hdGluZy1wb2ludCB0aGF0IGFwcHJveGltYXRlcyByZW1haW5kZXIgLyBvdGhlciAqZnJvbSBiZWxvdyosIGFkZCB0aGlzXHJcbiAgICAvLyBpbnRvIHRoZSByZXN1bHQsIGFuZCBzdWJ0cmFjdCBpdCBmcm9tIHRoZSByZW1haW5kZXIuICBJdCBpcyBjcml0aWNhbCB0aGF0XHJcbiAgICAvLyB0aGUgYXBwcm94aW1hdGUgdmFsdWUgaXMgbGVzcyB0aGFuIG9yIGVxdWFsIHRvIHRoZSByZWFsIHZhbHVlIHNvIHRoYXQgdGhlXHJcbiAgICAvLyByZW1haW5kZXIgbmV2ZXIgYmVjb21lcyBuZWdhdGl2ZS5cclxuICAgIHJlbSA9IHRoaXM7XHJcbiAgICB3aGlsZSAocmVtLmd0ZShkaXZpc29yKSkge1xyXG4gICAgICAgIC8vIEFwcHJveGltYXRlIHRoZSByZXN1bHQgb2YgZGl2aXNpb24uIFRoaXMgbWF5IGJlIGEgbGl0dGxlIGdyZWF0ZXIgb3JcclxuICAgICAgICAvLyBzbWFsbGVyIHRoYW4gdGhlIGFjdHVhbCB2YWx1ZS5cclxuICAgICAgICBhcHByb3ggPSBNYXRoLm1heCgxLCBNYXRoLmZsb29yKHJlbS50b051bWJlcigpIC8gZGl2aXNvci50b051bWJlcigpKSk7XHJcblxyXG4gICAgICAgIC8vIFdlIHdpbGwgdHdlYWsgdGhlIGFwcHJveGltYXRlIHJlc3VsdCBieSBjaGFuZ2luZyBpdCBpbiB0aGUgNDgtdGggZGlnaXQgb3JcclxuICAgICAgICAvLyB0aGUgc21hbGxlc3Qgbm9uLWZyYWN0aW9uYWwgZGlnaXQsIHdoaWNoZXZlciBpcyBsYXJnZXIuXHJcbiAgICAgICAgdmFyIGxvZzIgPSBNYXRoLmNlaWwoTWF0aC5sb2coYXBwcm94KSAvIE1hdGguTE4yKSxcclxuICAgICAgICAgICAgZGVsdGEgPSAobG9nMiA8PSA0OCkgPyAxIDogcG93X2RibCgyLCBsb2cyIC0gNDgpLFxyXG5cclxuICAgICAgICAvLyBEZWNyZWFzZSB0aGUgYXBwcm94aW1hdGlvbiB1bnRpbCBpdCBpcyBzbWFsbGVyIHRoYW4gdGhlIHJlbWFpbmRlci4gIE5vdGVcclxuICAgICAgICAvLyB0aGF0IGlmIGl0IGlzIHRvbyBsYXJnZSwgdGhlIHByb2R1Y3Qgb3ZlcmZsb3dzIGFuZCBpcyBuZWdhdGl2ZS5cclxuICAgICAgICAgICAgYXBwcm94UmVzID0gZnJvbU51bWJlcihhcHByb3gpLFxyXG4gICAgICAgICAgICBhcHByb3hSZW0gPSBhcHByb3hSZXMubXVsKGRpdmlzb3IpO1xyXG4gICAgICAgIHdoaWxlIChhcHByb3hSZW0uaXNOZWdhdGl2ZSgpIHx8IGFwcHJveFJlbS5ndChyZW0pKSB7XHJcbiAgICAgICAgICAgIGFwcHJveCAtPSBkZWx0YTtcclxuICAgICAgICAgICAgYXBwcm94UmVzID0gZnJvbU51bWJlcihhcHByb3gsIHRoaXMudW5zaWduZWQpO1xyXG4gICAgICAgICAgICBhcHByb3hSZW0gPSBhcHByb3hSZXMubXVsKGRpdmlzb3IpO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgLy8gV2Uga25vdyB0aGUgYW5zd2VyIGNhbid0IGJlIHplcm8uLi4gYW5kIGFjdHVhbGx5LCB6ZXJvIHdvdWxkIGNhdXNlXHJcbiAgICAgICAgLy8gaW5maW5pdGUgcmVjdXJzaW9uIHNpbmNlIHdlIHdvdWxkIG1ha2Ugbm8gcHJvZ3Jlc3MuXHJcbiAgICAgICAgaWYgKGFwcHJveFJlcy5pc1plcm8oKSlcclxuICAgICAgICAgICAgYXBwcm94UmVzID0gT05FO1xyXG5cclxuICAgICAgICByZXMgPSByZXMuYWRkKGFwcHJveFJlcyk7XHJcbiAgICAgICAgcmVtID0gcmVtLnN1YihhcHByb3hSZW0pO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIHJlcztcclxufTtcclxuXHJcbi8qKlxyXG4gKiBSZXR1cm5zIHRoaXMgTG9uZyBkaXZpZGVkIGJ5IHRoZSBzcGVjaWZpZWQuIFRoaXMgaXMgYW4gYWxpYXMgb2Yge0BsaW5rIExvbmcjZGl2aWRlfS5cclxuICogQGZ1bmN0aW9uXHJcbiAqIEBwYXJhbSB7IUxvbmd8bnVtYmVyfHN0cmluZ30gZGl2aXNvciBEaXZpc29yXHJcbiAqIEByZXR1cm5zIHshTG9uZ30gUXVvdGllbnRcclxuICovXHJcbkxvbmdQcm90b3R5cGUuZGl2ID0gTG9uZ1Byb3RvdHlwZS5kaXZpZGU7XHJcblxyXG4vKipcclxuICogUmV0dXJucyB0aGlzIExvbmcgbW9kdWxvIHRoZSBzcGVjaWZpZWQuXHJcbiAqIEBwYXJhbSB7IUxvbmd8bnVtYmVyfHN0cmluZ30gZGl2aXNvciBEaXZpc29yXHJcbiAqIEByZXR1cm5zIHshTG9uZ30gUmVtYWluZGVyXHJcbiAqL1xyXG5Mb25nUHJvdG90eXBlLm1vZHVsbyA9IGZ1bmN0aW9uIG1vZHVsbyhkaXZpc29yKSB7XHJcbiAgICBpZiAoIWlzTG9uZyhkaXZpc29yKSlcclxuICAgICAgICBkaXZpc29yID0gZnJvbVZhbHVlKGRpdmlzb3IpO1xyXG5cclxuICAgIC8vIHVzZSB3YXNtIHN1cHBvcnQgaWYgcHJlc2VudFxyXG4gICAgaWYgKHdhc20pIHtcclxuICAgICAgICB2YXIgbG93ID0gKHRoaXMudW5zaWduZWQgPyB3YXNtLnJlbV91IDogd2FzbS5yZW1fcykoXHJcbiAgICAgICAgICAgIHRoaXMubG93LFxyXG4gICAgICAgICAgICB0aGlzLmhpZ2gsXHJcbiAgICAgICAgICAgIGRpdmlzb3IubG93LFxyXG4gICAgICAgICAgICBkaXZpc29yLmhpZ2hcclxuICAgICAgICApO1xyXG4gICAgICAgIHJldHVybiBmcm9tQml0cyhsb3csIHdhc20uZ2V0X2hpZ2goKSwgdGhpcy51bnNpZ25lZCk7XHJcbiAgICB9XHJcblxyXG4gICAgcmV0dXJuIHRoaXMuc3ViKHRoaXMuZGl2KGRpdmlzb3IpLm11bChkaXZpc29yKSk7XHJcbn07XHJcblxyXG4vKipcclxuICogUmV0dXJucyB0aGlzIExvbmcgbW9kdWxvIHRoZSBzcGVjaWZpZWQuIFRoaXMgaXMgYW4gYWxpYXMgb2Yge0BsaW5rIExvbmcjbW9kdWxvfS5cclxuICogQGZ1bmN0aW9uXHJcbiAqIEBwYXJhbSB7IUxvbmd8bnVtYmVyfHN0cmluZ30gZGl2aXNvciBEaXZpc29yXHJcbiAqIEByZXR1cm5zIHshTG9uZ30gUmVtYWluZGVyXHJcbiAqL1xyXG5Mb25nUHJvdG90eXBlLm1vZCA9IExvbmdQcm90b3R5cGUubW9kdWxvO1xyXG5cclxuLyoqXHJcbiAqIFJldHVybnMgdGhpcyBMb25nIG1vZHVsbyB0aGUgc3BlY2lmaWVkLiBUaGlzIGlzIGFuIGFsaWFzIG9mIHtAbGluayBMb25nI21vZHVsb30uXHJcbiAqIEBmdW5jdGlvblxyXG4gKiBAcGFyYW0geyFMb25nfG51bWJlcnxzdHJpbmd9IGRpdmlzb3IgRGl2aXNvclxyXG4gKiBAcmV0dXJucyB7IUxvbmd9IFJlbWFpbmRlclxyXG4gKi9cclxuTG9uZ1Byb3RvdHlwZS5yZW0gPSBMb25nUHJvdG90eXBlLm1vZHVsbztcclxuXHJcbi8qKlxyXG4gKiBSZXR1cm5zIHRoZSBiaXR3aXNlIE5PVCBvZiB0aGlzIExvbmcuXHJcbiAqIEByZXR1cm5zIHshTG9uZ31cclxuICovXHJcbkxvbmdQcm90b3R5cGUubm90ID0gZnVuY3Rpb24gbm90KCkge1xyXG4gICAgcmV0dXJuIGZyb21CaXRzKH50aGlzLmxvdywgfnRoaXMuaGlnaCwgdGhpcy51bnNpZ25lZCk7XHJcbn07XHJcblxyXG4vKipcclxuICogUmV0dXJucyB0aGUgYml0d2lzZSBBTkQgb2YgdGhpcyBMb25nIGFuZCB0aGUgc3BlY2lmaWVkLlxyXG4gKiBAcGFyYW0geyFMb25nfG51bWJlcnxzdHJpbmd9IG90aGVyIE90aGVyIExvbmdcclxuICogQHJldHVybnMgeyFMb25nfVxyXG4gKi9cclxuTG9uZ1Byb3RvdHlwZS5hbmQgPSBmdW5jdGlvbiBhbmQob3RoZXIpIHtcclxuICAgIGlmICghaXNMb25nKG90aGVyKSlcclxuICAgICAgICBvdGhlciA9IGZyb21WYWx1ZShvdGhlcik7XHJcbiAgICByZXR1cm4gZnJvbUJpdHModGhpcy5sb3cgJiBvdGhlci5sb3csIHRoaXMuaGlnaCAmIG90aGVyLmhpZ2gsIHRoaXMudW5zaWduZWQpO1xyXG59O1xyXG5cclxuLyoqXHJcbiAqIFJldHVybnMgdGhlIGJpdHdpc2UgT1Igb2YgdGhpcyBMb25nIGFuZCB0aGUgc3BlY2lmaWVkLlxyXG4gKiBAcGFyYW0geyFMb25nfG51bWJlcnxzdHJpbmd9IG90aGVyIE90aGVyIExvbmdcclxuICogQHJldHVybnMgeyFMb25nfVxyXG4gKi9cclxuTG9uZ1Byb3RvdHlwZS5vciA9IGZ1bmN0aW9uIG9yKG90aGVyKSB7XHJcbiAgICBpZiAoIWlzTG9uZyhvdGhlcikpXHJcbiAgICAgICAgb3RoZXIgPSBmcm9tVmFsdWUob3RoZXIpO1xyXG4gICAgcmV0dXJuIGZyb21CaXRzKHRoaXMubG93IHwgb3RoZXIubG93LCB0aGlzLmhpZ2ggfCBvdGhlci5oaWdoLCB0aGlzLnVuc2lnbmVkKTtcclxufTtcclxuXHJcbi8qKlxyXG4gKiBSZXR1cm5zIHRoZSBiaXR3aXNlIFhPUiBvZiB0aGlzIExvbmcgYW5kIHRoZSBnaXZlbiBvbmUuXHJcbiAqIEBwYXJhbSB7IUxvbmd8bnVtYmVyfHN0cmluZ30gb3RoZXIgT3RoZXIgTG9uZ1xyXG4gKiBAcmV0dXJucyB7IUxvbmd9XHJcbiAqL1xyXG5Mb25nUHJvdG90eXBlLnhvciA9IGZ1bmN0aW9uIHhvcihvdGhlcikge1xyXG4gICAgaWYgKCFpc0xvbmcob3RoZXIpKVxyXG4gICAgICAgIG90aGVyID0gZnJvbVZhbHVlKG90aGVyKTtcclxuICAgIHJldHVybiBmcm9tQml0cyh0aGlzLmxvdyBeIG90aGVyLmxvdywgdGhpcy5oaWdoIF4gb3RoZXIuaGlnaCwgdGhpcy51bnNpZ25lZCk7XHJcbn07XHJcblxyXG4vKipcclxuICogUmV0dXJucyB0aGlzIExvbmcgd2l0aCBiaXRzIHNoaWZ0ZWQgdG8gdGhlIGxlZnQgYnkgdGhlIGdpdmVuIGFtb3VudC5cclxuICogQHBhcmFtIHtudW1iZXJ8IUxvbmd9IG51bUJpdHMgTnVtYmVyIG9mIGJpdHNcclxuICogQHJldHVybnMgeyFMb25nfSBTaGlmdGVkIExvbmdcclxuICovXHJcbkxvbmdQcm90b3R5cGUuc2hpZnRMZWZ0ID0gZnVuY3Rpb24gc2hpZnRMZWZ0KG51bUJpdHMpIHtcclxuICAgIGlmIChpc0xvbmcobnVtQml0cykpXHJcbiAgICAgICAgbnVtQml0cyA9IG51bUJpdHMudG9JbnQoKTtcclxuICAgIGlmICgobnVtQml0cyAmPSA2MykgPT09IDApXHJcbiAgICAgICAgcmV0dXJuIHRoaXM7XHJcbiAgICBlbHNlIGlmIChudW1CaXRzIDwgMzIpXHJcbiAgICAgICAgcmV0dXJuIGZyb21CaXRzKHRoaXMubG93IDw8IG51bUJpdHMsICh0aGlzLmhpZ2ggPDwgbnVtQml0cykgfCAodGhpcy5sb3cgPj4+ICgzMiAtIG51bUJpdHMpKSwgdGhpcy51bnNpZ25lZCk7XHJcbiAgICBlbHNlXHJcbiAgICAgICAgcmV0dXJuIGZyb21CaXRzKDAsIHRoaXMubG93IDw8IChudW1CaXRzIC0gMzIpLCB0aGlzLnVuc2lnbmVkKTtcclxufTtcclxuXHJcbi8qKlxyXG4gKiBSZXR1cm5zIHRoaXMgTG9uZyB3aXRoIGJpdHMgc2hpZnRlZCB0byB0aGUgbGVmdCBieSB0aGUgZ2l2ZW4gYW1vdW50LiBUaGlzIGlzIGFuIGFsaWFzIG9mIHtAbGluayBMb25nI3NoaWZ0TGVmdH0uXHJcbiAqIEBmdW5jdGlvblxyXG4gKiBAcGFyYW0ge251bWJlcnwhTG9uZ30gbnVtQml0cyBOdW1iZXIgb2YgYml0c1xyXG4gKiBAcmV0dXJucyB7IUxvbmd9IFNoaWZ0ZWQgTG9uZ1xyXG4gKi9cclxuTG9uZ1Byb3RvdHlwZS5zaGwgPSBMb25nUHJvdG90eXBlLnNoaWZ0TGVmdDtcclxuXHJcbi8qKlxyXG4gKiBSZXR1cm5zIHRoaXMgTG9uZyB3aXRoIGJpdHMgYXJpdGhtZXRpY2FsbHkgc2hpZnRlZCB0byB0aGUgcmlnaHQgYnkgdGhlIGdpdmVuIGFtb3VudC5cclxuICogQHBhcmFtIHtudW1iZXJ8IUxvbmd9IG51bUJpdHMgTnVtYmVyIG9mIGJpdHNcclxuICogQHJldHVybnMgeyFMb25nfSBTaGlmdGVkIExvbmdcclxuICovXHJcbkxvbmdQcm90b3R5cGUuc2hpZnRSaWdodCA9IGZ1bmN0aW9uIHNoaWZ0UmlnaHQobnVtQml0cykge1xyXG4gICAgaWYgKGlzTG9uZyhudW1CaXRzKSlcclxuICAgICAgICBudW1CaXRzID0gbnVtQml0cy50b0ludCgpO1xyXG4gICAgaWYgKChudW1CaXRzICY9IDYzKSA9PT0gMClcclxuICAgICAgICByZXR1cm4gdGhpcztcclxuICAgIGVsc2UgaWYgKG51bUJpdHMgPCAzMilcclxuICAgICAgICByZXR1cm4gZnJvbUJpdHMoKHRoaXMubG93ID4+PiBudW1CaXRzKSB8ICh0aGlzLmhpZ2ggPDwgKDMyIC0gbnVtQml0cykpLCB0aGlzLmhpZ2ggPj4gbnVtQml0cywgdGhpcy51bnNpZ25lZCk7XHJcbiAgICBlbHNlXHJcbiAgICAgICAgcmV0dXJuIGZyb21CaXRzKHRoaXMuaGlnaCA+PiAobnVtQml0cyAtIDMyKSwgdGhpcy5oaWdoID49IDAgPyAwIDogLTEsIHRoaXMudW5zaWduZWQpO1xyXG59O1xyXG5cclxuLyoqXHJcbiAqIFJldHVybnMgdGhpcyBMb25nIHdpdGggYml0cyBhcml0aG1ldGljYWxseSBzaGlmdGVkIHRvIHRoZSByaWdodCBieSB0aGUgZ2l2ZW4gYW1vdW50LiBUaGlzIGlzIGFuIGFsaWFzIG9mIHtAbGluayBMb25nI3NoaWZ0UmlnaHR9LlxyXG4gKiBAZnVuY3Rpb25cclxuICogQHBhcmFtIHtudW1iZXJ8IUxvbmd9IG51bUJpdHMgTnVtYmVyIG9mIGJpdHNcclxuICogQHJldHVybnMgeyFMb25nfSBTaGlmdGVkIExvbmdcclxuICovXHJcbkxvbmdQcm90b3R5cGUuc2hyID0gTG9uZ1Byb3RvdHlwZS5zaGlmdFJpZ2h0O1xyXG5cclxuLyoqXHJcbiAqIFJldHVybnMgdGhpcyBMb25nIHdpdGggYml0cyBsb2dpY2FsbHkgc2hpZnRlZCB0byB0aGUgcmlnaHQgYnkgdGhlIGdpdmVuIGFtb3VudC5cclxuICogQHBhcmFtIHtudW1iZXJ8IUxvbmd9IG51bUJpdHMgTnVtYmVyIG9mIGJpdHNcclxuICogQHJldHVybnMgeyFMb25nfSBTaGlmdGVkIExvbmdcclxuICovXHJcbkxvbmdQcm90b3R5cGUuc2hpZnRSaWdodFVuc2lnbmVkID0gZnVuY3Rpb24gc2hpZnRSaWdodFVuc2lnbmVkKG51bUJpdHMpIHtcclxuICAgIGlmIChpc0xvbmcobnVtQml0cykpXHJcbiAgICAgICAgbnVtQml0cyA9IG51bUJpdHMudG9JbnQoKTtcclxuICAgIG51bUJpdHMgJj0gNjM7XHJcbiAgICBpZiAobnVtQml0cyA9PT0gMClcclxuICAgICAgICByZXR1cm4gdGhpcztcclxuICAgIGVsc2Uge1xyXG4gICAgICAgIHZhciBoaWdoID0gdGhpcy5oaWdoO1xyXG4gICAgICAgIGlmIChudW1CaXRzIDwgMzIpIHtcclxuICAgICAgICAgICAgdmFyIGxvdyA9IHRoaXMubG93O1xyXG4gICAgICAgICAgICByZXR1cm4gZnJvbUJpdHMoKGxvdyA+Pj4gbnVtQml0cykgfCAoaGlnaCA8PCAoMzIgLSBudW1CaXRzKSksIGhpZ2ggPj4+IG51bUJpdHMsIHRoaXMudW5zaWduZWQpO1xyXG4gICAgICAgIH0gZWxzZSBpZiAobnVtQml0cyA9PT0gMzIpXHJcbiAgICAgICAgICAgIHJldHVybiBmcm9tQml0cyhoaWdoLCAwLCB0aGlzLnVuc2lnbmVkKTtcclxuICAgICAgICBlbHNlXHJcbiAgICAgICAgICAgIHJldHVybiBmcm9tQml0cyhoaWdoID4+PiAobnVtQml0cyAtIDMyKSwgMCwgdGhpcy51bnNpZ25lZCk7XHJcbiAgICB9XHJcbn07XHJcblxyXG4vKipcclxuICogUmV0dXJucyB0aGlzIExvbmcgd2l0aCBiaXRzIGxvZ2ljYWxseSBzaGlmdGVkIHRvIHRoZSByaWdodCBieSB0aGUgZ2l2ZW4gYW1vdW50LiBUaGlzIGlzIGFuIGFsaWFzIG9mIHtAbGluayBMb25nI3NoaWZ0UmlnaHRVbnNpZ25lZH0uXHJcbiAqIEBmdW5jdGlvblxyXG4gKiBAcGFyYW0ge251bWJlcnwhTG9uZ30gbnVtQml0cyBOdW1iZXIgb2YgYml0c1xyXG4gKiBAcmV0dXJucyB7IUxvbmd9IFNoaWZ0ZWQgTG9uZ1xyXG4gKi9cclxuTG9uZ1Byb3RvdHlwZS5zaHJ1ID0gTG9uZ1Byb3RvdHlwZS5zaGlmdFJpZ2h0VW5zaWduZWQ7XHJcblxyXG4vKipcclxuICogUmV0dXJucyB0aGlzIExvbmcgd2l0aCBiaXRzIGxvZ2ljYWxseSBzaGlmdGVkIHRvIHRoZSByaWdodCBieSB0aGUgZ2l2ZW4gYW1vdW50LiBUaGlzIGlzIGFuIGFsaWFzIG9mIHtAbGluayBMb25nI3NoaWZ0UmlnaHRVbnNpZ25lZH0uXHJcbiAqIEBmdW5jdGlvblxyXG4gKiBAcGFyYW0ge251bWJlcnwhTG9uZ30gbnVtQml0cyBOdW1iZXIgb2YgYml0c1xyXG4gKiBAcmV0dXJucyB7IUxvbmd9IFNoaWZ0ZWQgTG9uZ1xyXG4gKi9cclxuTG9uZ1Byb3RvdHlwZS5zaHJfdSA9IExvbmdQcm90b3R5cGUuc2hpZnRSaWdodFVuc2lnbmVkO1xyXG5cclxuLyoqXHJcbiAqIENvbnZlcnRzIHRoaXMgTG9uZyB0byBzaWduZWQuXHJcbiAqIEByZXR1cm5zIHshTG9uZ30gU2lnbmVkIGxvbmdcclxuICovXHJcbkxvbmdQcm90b3R5cGUudG9TaWduZWQgPSBmdW5jdGlvbiB0b1NpZ25lZCgpIHtcclxuICAgIGlmICghdGhpcy51bnNpZ25lZClcclxuICAgICAgICByZXR1cm4gdGhpcztcclxuICAgIHJldHVybiBmcm9tQml0cyh0aGlzLmxvdywgdGhpcy5oaWdoLCBmYWxzZSk7XHJcbn07XHJcblxyXG4vKipcclxuICogQ29udmVydHMgdGhpcyBMb25nIHRvIHVuc2lnbmVkLlxyXG4gKiBAcmV0dXJucyB7IUxvbmd9IFVuc2lnbmVkIGxvbmdcclxuICovXHJcbkxvbmdQcm90b3R5cGUudG9VbnNpZ25lZCA9IGZ1bmN0aW9uIHRvVW5zaWduZWQoKSB7XHJcbiAgICBpZiAodGhpcy51bnNpZ25lZClcclxuICAgICAgICByZXR1cm4gdGhpcztcclxuICAgIHJldHVybiBmcm9tQml0cyh0aGlzLmxvdywgdGhpcy5oaWdoLCB0cnVlKTtcclxufTtcclxuXHJcbi8qKlxyXG4gKiBDb252ZXJ0cyB0aGlzIExvbmcgdG8gaXRzIGJ5dGUgcmVwcmVzZW50YXRpb24uXHJcbiAqIEBwYXJhbSB7Ym9vbGVhbj19IGxlIFdoZXRoZXIgbGl0dGxlIG9yIGJpZyBlbmRpYW4sIGRlZmF1bHRzIHRvIGJpZyBlbmRpYW5cclxuICogQHJldHVybnMgeyFBcnJheS48bnVtYmVyPn0gQnl0ZSByZXByZXNlbnRhdGlvblxyXG4gKi9cclxuTG9uZ1Byb3RvdHlwZS50b0J5dGVzID0gZnVuY3Rpb24gdG9CeXRlcyhsZSkge1xyXG4gICAgcmV0dXJuIGxlID8gdGhpcy50b0J5dGVzTEUoKSA6IHRoaXMudG9CeXRlc0JFKCk7XHJcbn07XHJcblxyXG4vKipcclxuICogQ29udmVydHMgdGhpcyBMb25nIHRvIGl0cyBsaXR0bGUgZW5kaWFuIGJ5dGUgcmVwcmVzZW50YXRpb24uXHJcbiAqIEByZXR1cm5zIHshQXJyYXkuPG51bWJlcj59IExpdHRsZSBlbmRpYW4gYnl0ZSByZXByZXNlbnRhdGlvblxyXG4gKi9cclxuTG9uZ1Byb3RvdHlwZS50b0J5dGVzTEUgPSBmdW5jdGlvbiB0b0J5dGVzTEUoKSB7XHJcbiAgICB2YXIgaGkgPSB0aGlzLmhpZ2gsXHJcbiAgICAgICAgbG8gPSB0aGlzLmxvdztcclxuICAgIHJldHVybiBbXHJcbiAgICAgICAgbG8gICAgICAgICYgMHhmZixcclxuICAgICAgICBsbyA+Pj4gIDggJiAweGZmLFxyXG4gICAgICAgIGxvID4+PiAxNiAmIDB4ZmYsXHJcbiAgICAgICAgbG8gPj4+IDI0ICAgICAgICxcclxuICAgICAgICBoaSAgICAgICAgJiAweGZmLFxyXG4gICAgICAgIGhpID4+PiAgOCAmIDB4ZmYsXHJcbiAgICAgICAgaGkgPj4+IDE2ICYgMHhmZixcclxuICAgICAgICBoaSA+Pj4gMjRcclxuICAgIF07XHJcbn07XHJcblxyXG4vKipcclxuICogQ29udmVydHMgdGhpcyBMb25nIHRvIGl0cyBiaWcgZW5kaWFuIGJ5dGUgcmVwcmVzZW50YXRpb24uXHJcbiAqIEByZXR1cm5zIHshQXJyYXkuPG51bWJlcj59IEJpZyBlbmRpYW4gYnl0ZSByZXByZXNlbnRhdGlvblxyXG4gKi9cclxuTG9uZ1Byb3RvdHlwZS50b0J5dGVzQkUgPSBmdW5jdGlvbiB0b0J5dGVzQkUoKSB7XHJcbiAgICB2YXIgaGkgPSB0aGlzLmhpZ2gsXHJcbiAgICAgICAgbG8gPSB0aGlzLmxvdztcclxuICAgIHJldHVybiBbXHJcbiAgICAgICAgaGkgPj4+IDI0ICAgICAgICxcclxuICAgICAgICBoaSA+Pj4gMTYgJiAweGZmLFxyXG4gICAgICAgIGhpID4+PiAgOCAmIDB4ZmYsXHJcbiAgICAgICAgaGkgICAgICAgICYgMHhmZixcclxuICAgICAgICBsbyA+Pj4gMjQgICAgICAgLFxyXG4gICAgICAgIGxvID4+PiAxNiAmIDB4ZmYsXHJcbiAgICAgICAgbG8gPj4+ICA4ICYgMHhmZixcclxuICAgICAgICBsbyAgICAgICAgJiAweGZmXHJcbiAgICBdO1xyXG59O1xyXG5cclxuLyoqXHJcbiAqIENyZWF0ZXMgYSBMb25nIGZyb20gaXRzIGJ5dGUgcmVwcmVzZW50YXRpb24uXHJcbiAqIEBwYXJhbSB7IUFycmF5LjxudW1iZXI+fSBieXRlcyBCeXRlIHJlcHJlc2VudGF0aW9uXHJcbiAqIEBwYXJhbSB7Ym9vbGVhbj19IHVuc2lnbmVkIFdoZXRoZXIgdW5zaWduZWQgb3Igbm90LCBkZWZhdWx0cyB0byBzaWduZWRcclxuICogQHBhcmFtIHtib29sZWFuPX0gbGUgV2hldGhlciBsaXR0bGUgb3IgYmlnIGVuZGlhbiwgZGVmYXVsdHMgdG8gYmlnIGVuZGlhblxyXG4gKiBAcmV0dXJucyB7TG9uZ30gVGhlIGNvcnJlc3BvbmRpbmcgTG9uZyB2YWx1ZVxyXG4gKi9cclxuTG9uZy5mcm9tQnl0ZXMgPSBmdW5jdGlvbiBmcm9tQnl0ZXMoYnl0ZXMsIHVuc2lnbmVkLCBsZSkge1xyXG4gICAgcmV0dXJuIGxlID8gTG9uZy5mcm9tQnl0ZXNMRShieXRlcywgdW5zaWduZWQpIDogTG9uZy5mcm9tQnl0ZXNCRShieXRlcywgdW5zaWduZWQpO1xyXG59O1xyXG5cclxuLyoqXHJcbiAqIENyZWF0ZXMgYSBMb25nIGZyb20gaXRzIGxpdHRsZSBlbmRpYW4gYnl0ZSByZXByZXNlbnRhdGlvbi5cclxuICogQHBhcmFtIHshQXJyYXkuPG51bWJlcj59IGJ5dGVzIExpdHRsZSBlbmRpYW4gYnl0ZSByZXByZXNlbnRhdGlvblxyXG4gKiBAcGFyYW0ge2Jvb2xlYW49fSB1bnNpZ25lZCBXaGV0aGVyIHVuc2lnbmVkIG9yIG5vdCwgZGVmYXVsdHMgdG8gc2lnbmVkXHJcbiAqIEByZXR1cm5zIHtMb25nfSBUaGUgY29ycmVzcG9uZGluZyBMb25nIHZhbHVlXHJcbiAqL1xyXG5Mb25nLmZyb21CeXRlc0xFID0gZnVuY3Rpb24gZnJvbUJ5dGVzTEUoYnl0ZXMsIHVuc2lnbmVkKSB7XHJcbiAgICByZXR1cm4gbmV3IExvbmcoXHJcbiAgICAgICAgYnl0ZXNbMF0gICAgICAgfFxyXG4gICAgICAgIGJ5dGVzWzFdIDw8ICA4IHxcclxuICAgICAgICBieXRlc1syXSA8PCAxNiB8XHJcbiAgICAgICAgYnl0ZXNbM10gPDwgMjQsXHJcbiAgICAgICAgYnl0ZXNbNF0gICAgICAgfFxyXG4gICAgICAgIGJ5dGVzWzVdIDw8ICA4IHxcclxuICAgICAgICBieXRlc1s2XSA8PCAxNiB8XHJcbiAgICAgICAgYnl0ZXNbN10gPDwgMjQsXHJcbiAgICAgICAgdW5zaWduZWRcclxuICAgICk7XHJcbn07XHJcblxyXG4vKipcclxuICogQ3JlYXRlcyBhIExvbmcgZnJvbSBpdHMgYmlnIGVuZGlhbiBieXRlIHJlcHJlc2VudGF0aW9uLlxyXG4gKiBAcGFyYW0geyFBcnJheS48bnVtYmVyPn0gYnl0ZXMgQmlnIGVuZGlhbiBieXRlIHJlcHJlc2VudGF0aW9uXHJcbiAqIEBwYXJhbSB7Ym9vbGVhbj19IHVuc2lnbmVkIFdoZXRoZXIgdW5zaWduZWQgb3Igbm90LCBkZWZhdWx0cyB0byBzaWduZWRcclxuICogQHJldHVybnMge0xvbmd9IFRoZSBjb3JyZXNwb25kaW5nIExvbmcgdmFsdWVcclxuICovXHJcbkxvbmcuZnJvbUJ5dGVzQkUgPSBmdW5jdGlvbiBmcm9tQnl0ZXNCRShieXRlcywgdW5zaWduZWQpIHtcclxuICAgIHJldHVybiBuZXcgTG9uZyhcclxuICAgICAgICBieXRlc1s0XSA8PCAyNCB8XHJcbiAgICAgICAgYnl0ZXNbNV0gPDwgMTYgfFxyXG4gICAgICAgIGJ5dGVzWzZdIDw8ICA4IHxcclxuICAgICAgICBieXRlc1s3XSxcclxuICAgICAgICBieXRlc1swXSA8PCAyNCB8XHJcbiAgICAgICAgYnl0ZXNbMV0gPDwgMTYgfFxyXG4gICAgICAgIGJ5dGVzWzJdIDw8ICA4IHxcclxuICAgICAgICBieXRlc1szXSxcclxuICAgICAgICB1bnNpZ25lZFxyXG4gICAgKTtcclxufTtcclxuIiwiLyplc2xpbnQtZGlzYWJsZSBibG9jay1zY29wZWQtdmFyLCBpZC1sZW5ndGgsIG5vLWNvbnRyb2wtcmVnZXgsIG5vLW1hZ2ljLW51bWJlcnMsIG5vLXByb3RvdHlwZS1idWlsdGlucywgbm8tcmVkZWNsYXJlLCBuby1zaGFkb3csIG5vLXZhciwgc29ydC12YXJzKi9cblwidXNlIHN0cmljdFwiO1xuXG52YXIgJHByb3RvYnVmID0gcmVxdWlyZShcInByb3RvYnVmanMvbWluaW1hbFwiKTtcblxuLy8gQ29tbW9uIGFsaWFzZXNcbnZhciAkUmVhZGVyID0gJHByb3RvYnVmLlJlYWRlciwgJFdyaXRlciA9ICRwcm90b2J1Zi5Xcml0ZXIsICR1dGlsID0gJHByb3RvYnVmLnV0aWw7XG5cbi8vIEV4cG9ydGVkIHJvb3QgbmFtZXNwYWNlXG52YXIgJHJvb3QgPSAkcHJvdG9idWYucm9vdHNbXCJkZWZhdWx0XCJdIHx8ICgkcHJvdG9idWYucm9vdHNbXCJkZWZhdWx0XCJdID0ge30pO1xuXG4kcm9vdC5vbm54ID0gKGZ1bmN0aW9uKCkge1xuXG4gICAgLyoqXG4gICAgICogTmFtZXNwYWNlIG9ubnguXG4gICAgICogQGV4cG9ydHMgb25ueFxuICAgICAqIEBuYW1lc3BhY2VcbiAgICAgKi9cbiAgICB2YXIgb25ueCA9IHt9O1xuXG4gICAgLyoqXG4gICAgICogVmVyc2lvbiBlbnVtLlxuICAgICAqIEBuYW1lIG9ubnguVmVyc2lvblxuICAgICAqIEBlbnVtIHtzdHJpbmd9XG4gICAgICogQHByb3BlcnR5IHtudW1iZXJ9IF9TVEFSVF9WRVJTSU9OPTAgX1NUQVJUX1ZFUlNJT04gdmFsdWVcbiAgICAgKiBAcHJvcGVydHkge251bWJlcn0gSVJfVkVSU0lPTl8yMDE3XzEwXzEwPTEgSVJfVkVSU0lPTl8yMDE3XzEwXzEwIHZhbHVlXG4gICAgICogQHByb3BlcnR5IHtudW1iZXJ9IElSX1ZFUlNJT05fMjAxN18xMF8zMD0yIElSX1ZFUlNJT05fMjAxN18xMF8zMCB2YWx1ZVxuICAgICAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBJUl9WRVJTSU9OXzIwMTdfMTFfMz0zIElSX1ZFUlNJT05fMjAxN18xMV8zIHZhbHVlXG4gICAgICogQHByb3BlcnR5IHtudW1iZXJ9IElSX1ZFUlNJT05fMjAxOV8xXzIyPTQgSVJfVkVSU0lPTl8yMDE5XzFfMjIgdmFsdWVcbiAgICAgKiBAcHJvcGVydHkge251bWJlcn0gSVJfVkVSU0lPTj01IElSX1ZFUlNJT04gdmFsdWVcbiAgICAgKi9cbiAgICBvbm54LlZlcnNpb24gPSAoZnVuY3Rpb24oKSB7XG4gICAgICAgIHZhciB2YWx1ZXNCeUlkID0ge30sIHZhbHVlcyA9IE9iamVjdC5jcmVhdGUodmFsdWVzQnlJZCk7XG4gICAgICAgIHZhbHVlc1t2YWx1ZXNCeUlkWzBdID0gXCJfU1RBUlRfVkVSU0lPTlwiXSA9IDA7XG4gICAgICAgIHZhbHVlc1t2YWx1ZXNCeUlkWzFdID0gXCJJUl9WRVJTSU9OXzIwMTdfMTBfMTBcIl0gPSAxO1xuICAgICAgICB2YWx1ZXNbdmFsdWVzQnlJZFsyXSA9IFwiSVJfVkVSU0lPTl8yMDE3XzEwXzMwXCJdID0gMjtcbiAgICAgICAgdmFsdWVzW3ZhbHVlc0J5SWRbM10gPSBcIklSX1ZFUlNJT05fMjAxN18xMV8zXCJdID0gMztcbiAgICAgICAgdmFsdWVzW3ZhbHVlc0J5SWRbNF0gPSBcIklSX1ZFUlNJT05fMjAxOV8xXzIyXCJdID0gNDtcbiAgICAgICAgdmFsdWVzW3ZhbHVlc0J5SWRbNV0gPSBcIklSX1ZFUlNJT05cIl0gPSA1O1xuICAgICAgICByZXR1cm4gdmFsdWVzO1xuICAgIH0pKCk7XG5cbiAgICBvbm54LkF0dHJpYnV0ZVByb3RvID0gKGZ1bmN0aW9uKCkge1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBQcm9wZXJ0aWVzIG9mIGFuIEF0dHJpYnV0ZVByb3RvLlxuICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueFxuICAgICAgICAgKiBAaW50ZXJmYWNlIElBdHRyaWJ1dGVQcm90b1xuICAgICAgICAgKiBAcHJvcGVydHkge3N0cmluZ3xudWxsfSBbbmFtZV0gQXR0cmlidXRlUHJvdG8gbmFtZVxuICAgICAgICAgKiBAcHJvcGVydHkge3N0cmluZ3xudWxsfSBbcmVmQXR0ck5hbWVdIEF0dHJpYnV0ZVByb3RvIHJlZkF0dHJOYW1lXG4gICAgICAgICAqIEBwcm9wZXJ0eSB7c3RyaW5nfG51bGx9IFtkb2NTdHJpbmddIEF0dHJpYnV0ZVByb3RvIGRvY1N0cmluZ1xuICAgICAgICAgKiBAcHJvcGVydHkge29ubnguQXR0cmlidXRlUHJvdG8uQXR0cmlidXRlVHlwZXxudWxsfSBbdHlwZV0gQXR0cmlidXRlUHJvdG8gdHlwZVxuICAgICAgICAgKiBAcHJvcGVydHkge251bWJlcnxudWxsfSBbZl0gQXR0cmlidXRlUHJvdG8gZlxuICAgICAgICAgKiBAcHJvcGVydHkge251bWJlcnxMb25nfG51bGx9IFtpXSBBdHRyaWJ1dGVQcm90byBpXG4gICAgICAgICAqIEBwcm9wZXJ0eSB7VWludDhBcnJheXxudWxsfSBbc10gQXR0cmlidXRlUHJvdG8gc1xuICAgICAgICAgKiBAcHJvcGVydHkge29ubnguSVRlbnNvclByb3RvfG51bGx9IFt0XSBBdHRyaWJ1dGVQcm90byB0XG4gICAgICAgICAqIEBwcm9wZXJ0eSB7b25ueC5JR3JhcGhQcm90b3xudWxsfSBbZ10gQXR0cmlidXRlUHJvdG8gZ1xuICAgICAgICAgKiBAcHJvcGVydHkge0FycmF5LjxudW1iZXI+fG51bGx9IFtmbG9hdHNdIEF0dHJpYnV0ZVByb3RvIGZsb2F0c1xuICAgICAgICAgKiBAcHJvcGVydHkge0FycmF5LjxudW1iZXJ8TG9uZz58bnVsbH0gW2ludHNdIEF0dHJpYnV0ZVByb3RvIGludHNcbiAgICAgICAgICogQHByb3BlcnR5IHtBcnJheS48VWludDhBcnJheT58bnVsbH0gW3N0cmluZ3NdIEF0dHJpYnV0ZVByb3RvIHN0cmluZ3NcbiAgICAgICAgICogQHByb3BlcnR5IHtBcnJheS48b25ueC5JVGVuc29yUHJvdG8+fG51bGx9IFt0ZW5zb3JzXSBBdHRyaWJ1dGVQcm90byB0ZW5zb3JzXG4gICAgICAgICAqIEBwcm9wZXJ0eSB7QXJyYXkuPG9ubnguSUdyYXBoUHJvdG8+fG51bGx9IFtncmFwaHNdIEF0dHJpYnV0ZVByb3RvIGdyYXBoc1xuICAgICAgICAgKi9cblxuICAgICAgICAvKipcbiAgICAgICAgICogQ29uc3RydWN0cyBhIG5ldyBBdHRyaWJ1dGVQcm90by5cbiAgICAgICAgICogQG1lbWJlcm9mIG9ubnhcbiAgICAgICAgICogQGNsYXNzZGVzYyBSZXByZXNlbnRzIGFuIEF0dHJpYnV0ZVByb3RvLlxuICAgICAgICAgKiBAaW1wbGVtZW50cyBJQXR0cmlidXRlUHJvdG9cbiAgICAgICAgICogQGNvbnN0cnVjdG9yXG4gICAgICAgICAqIEBwYXJhbSB7b25ueC5JQXR0cmlidXRlUHJvdG89fSBbcHJvcGVydGllc10gUHJvcGVydGllcyB0byBzZXRcbiAgICAgICAgICovXG4gICAgICAgIGZ1bmN0aW9uIEF0dHJpYnV0ZVByb3RvKHByb3BlcnRpZXMpIHtcbiAgICAgICAgICAgIHRoaXMuZmxvYXRzID0gW107XG4gICAgICAgICAgICB0aGlzLmludHMgPSBbXTtcbiAgICAgICAgICAgIHRoaXMuc3RyaW5ncyA9IFtdO1xuICAgICAgICAgICAgdGhpcy50ZW5zb3JzID0gW107XG4gICAgICAgICAgICB0aGlzLmdyYXBocyA9IFtdO1xuICAgICAgICAgICAgaWYgKHByb3BlcnRpZXMpXG4gICAgICAgICAgICAgICAgZm9yICh2YXIga2V5cyA9IE9iamVjdC5rZXlzKHByb3BlcnRpZXMpLCBpID0gMDsgaSA8IGtleXMubGVuZ3RoOyArK2kpXG4gICAgICAgICAgICAgICAgICAgIGlmIChwcm9wZXJ0aWVzW2tleXNbaV1dICE9IG51bGwpXG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzW2tleXNbaV1dID0gcHJvcGVydGllc1trZXlzW2ldXTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBBdHRyaWJ1dGVQcm90byBuYW1lLlxuICAgICAgICAgKiBAbWVtYmVyIHtzdHJpbmd9IG5hbWVcbiAgICAgICAgICogQG1lbWJlcm9mIG9ubnguQXR0cmlidXRlUHJvdG9cbiAgICAgICAgICogQGluc3RhbmNlXG4gICAgICAgICAqL1xuICAgICAgICBBdHRyaWJ1dGVQcm90by5wcm90b3R5cGUubmFtZSA9IFwiXCI7XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEF0dHJpYnV0ZVByb3RvIHJlZkF0dHJOYW1lLlxuICAgICAgICAgKiBAbWVtYmVyIHtzdHJpbmd9IHJlZkF0dHJOYW1lXG4gICAgICAgICAqIEBtZW1iZXJvZiBvbm54LkF0dHJpYnV0ZVByb3RvXG4gICAgICAgICAqIEBpbnN0YW5jZVxuICAgICAgICAgKi9cbiAgICAgICAgQXR0cmlidXRlUHJvdG8ucHJvdG90eXBlLnJlZkF0dHJOYW1lID0gXCJcIjtcblxuICAgICAgICAvKipcbiAgICAgICAgICogQXR0cmlidXRlUHJvdG8gZG9jU3RyaW5nLlxuICAgICAgICAgKiBAbWVtYmVyIHtzdHJpbmd9IGRvY1N0cmluZ1xuICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueC5BdHRyaWJ1dGVQcm90b1xuICAgICAgICAgKiBAaW5zdGFuY2VcbiAgICAgICAgICovXG4gICAgICAgIEF0dHJpYnV0ZVByb3RvLnByb3RvdHlwZS5kb2NTdHJpbmcgPSBcIlwiO1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBBdHRyaWJ1dGVQcm90byB0eXBlLlxuICAgICAgICAgKiBAbWVtYmVyIHtvbm54LkF0dHJpYnV0ZVByb3RvLkF0dHJpYnV0ZVR5cGV9IHR5cGVcbiAgICAgICAgICogQG1lbWJlcm9mIG9ubnguQXR0cmlidXRlUHJvdG9cbiAgICAgICAgICogQGluc3RhbmNlXG4gICAgICAgICAqL1xuICAgICAgICBBdHRyaWJ1dGVQcm90by5wcm90b3R5cGUudHlwZSA9IDA7XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEF0dHJpYnV0ZVByb3RvIGYuXG4gICAgICAgICAqIEBtZW1iZXIge251bWJlcn0gZlxuICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueC5BdHRyaWJ1dGVQcm90b1xuICAgICAgICAgKiBAaW5zdGFuY2VcbiAgICAgICAgICovXG4gICAgICAgIEF0dHJpYnV0ZVByb3RvLnByb3RvdHlwZS5mID0gMDtcblxuICAgICAgICAvKipcbiAgICAgICAgICogQXR0cmlidXRlUHJvdG8gaS5cbiAgICAgICAgICogQG1lbWJlciB7bnVtYmVyfExvbmd9IGlcbiAgICAgICAgICogQG1lbWJlcm9mIG9ubnguQXR0cmlidXRlUHJvdG9cbiAgICAgICAgICogQGluc3RhbmNlXG4gICAgICAgICAqL1xuICAgICAgICBBdHRyaWJ1dGVQcm90by5wcm90b3R5cGUuaSA9ICR1dGlsLkxvbmcgPyAkdXRpbC5Mb25nLmZyb21CaXRzKDAsMCxmYWxzZSkgOiAwO1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBBdHRyaWJ1dGVQcm90byBzLlxuICAgICAgICAgKiBAbWVtYmVyIHtVaW50OEFycmF5fSBzXG4gICAgICAgICAqIEBtZW1iZXJvZiBvbm54LkF0dHJpYnV0ZVByb3RvXG4gICAgICAgICAqIEBpbnN0YW5jZVxuICAgICAgICAgKi9cbiAgICAgICAgQXR0cmlidXRlUHJvdG8ucHJvdG90eXBlLnMgPSAkdXRpbC5uZXdCdWZmZXIoW10pO1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBBdHRyaWJ1dGVQcm90byB0LlxuICAgICAgICAgKiBAbWVtYmVyIHtvbm54LklUZW5zb3JQcm90b3xudWxsfHVuZGVmaW5lZH0gdFxuICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueC5BdHRyaWJ1dGVQcm90b1xuICAgICAgICAgKiBAaW5zdGFuY2VcbiAgICAgICAgICovXG4gICAgICAgIEF0dHJpYnV0ZVByb3RvLnByb3RvdHlwZS50ID0gbnVsbDtcblxuICAgICAgICAvKipcbiAgICAgICAgICogQXR0cmlidXRlUHJvdG8gZy5cbiAgICAgICAgICogQG1lbWJlciB7b25ueC5JR3JhcGhQcm90b3xudWxsfHVuZGVmaW5lZH0gZ1xuICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueC5BdHRyaWJ1dGVQcm90b1xuICAgICAgICAgKiBAaW5zdGFuY2VcbiAgICAgICAgICovXG4gICAgICAgIEF0dHJpYnV0ZVByb3RvLnByb3RvdHlwZS5nID0gbnVsbDtcblxuICAgICAgICAvKipcbiAgICAgICAgICogQXR0cmlidXRlUHJvdG8gZmxvYXRzLlxuICAgICAgICAgKiBAbWVtYmVyIHtBcnJheS48bnVtYmVyPn0gZmxvYXRzXG4gICAgICAgICAqIEBtZW1iZXJvZiBvbm54LkF0dHJpYnV0ZVByb3RvXG4gICAgICAgICAqIEBpbnN0YW5jZVxuICAgICAgICAgKi9cbiAgICAgICAgQXR0cmlidXRlUHJvdG8ucHJvdG90eXBlLmZsb2F0cyA9ICR1dGlsLmVtcHR5QXJyYXk7XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEF0dHJpYnV0ZVByb3RvIGludHMuXG4gICAgICAgICAqIEBtZW1iZXIge0FycmF5LjxudW1iZXJ8TG9uZz59IGludHNcbiAgICAgICAgICogQG1lbWJlcm9mIG9ubnguQXR0cmlidXRlUHJvdG9cbiAgICAgICAgICogQGluc3RhbmNlXG4gICAgICAgICAqL1xuICAgICAgICBBdHRyaWJ1dGVQcm90by5wcm90b3R5cGUuaW50cyA9ICR1dGlsLmVtcHR5QXJyYXk7XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEF0dHJpYnV0ZVByb3RvIHN0cmluZ3MuXG4gICAgICAgICAqIEBtZW1iZXIge0FycmF5LjxVaW50OEFycmF5Pn0gc3RyaW5nc1xuICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueC5BdHRyaWJ1dGVQcm90b1xuICAgICAgICAgKiBAaW5zdGFuY2VcbiAgICAgICAgICovXG4gICAgICAgIEF0dHJpYnV0ZVByb3RvLnByb3RvdHlwZS5zdHJpbmdzID0gJHV0aWwuZW1wdHlBcnJheTtcblxuICAgICAgICAvKipcbiAgICAgICAgICogQXR0cmlidXRlUHJvdG8gdGVuc29ycy5cbiAgICAgICAgICogQG1lbWJlciB7QXJyYXkuPG9ubnguSVRlbnNvclByb3RvPn0gdGVuc29yc1xuICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueC5BdHRyaWJ1dGVQcm90b1xuICAgICAgICAgKiBAaW5zdGFuY2VcbiAgICAgICAgICovXG4gICAgICAgIEF0dHJpYnV0ZVByb3RvLnByb3RvdHlwZS50ZW5zb3JzID0gJHV0aWwuZW1wdHlBcnJheTtcblxuICAgICAgICAvKipcbiAgICAgICAgICogQXR0cmlidXRlUHJvdG8gZ3JhcGhzLlxuICAgICAgICAgKiBAbWVtYmVyIHtBcnJheS48b25ueC5JR3JhcGhQcm90bz59IGdyYXBoc1xuICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueC5BdHRyaWJ1dGVQcm90b1xuICAgICAgICAgKiBAaW5zdGFuY2VcbiAgICAgICAgICovXG4gICAgICAgIEF0dHJpYnV0ZVByb3RvLnByb3RvdHlwZS5ncmFwaHMgPSAkdXRpbC5lbXB0eUFycmF5O1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBDcmVhdGVzIGEgbmV3IEF0dHJpYnV0ZVByb3RvIGluc3RhbmNlIHVzaW5nIHRoZSBzcGVjaWZpZWQgcHJvcGVydGllcy5cbiAgICAgICAgICogQGZ1bmN0aW9uIGNyZWF0ZVxuICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueC5BdHRyaWJ1dGVQcm90b1xuICAgICAgICAgKiBAc3RhdGljXG4gICAgICAgICAqIEBwYXJhbSB7b25ueC5JQXR0cmlidXRlUHJvdG89fSBbcHJvcGVydGllc10gUHJvcGVydGllcyB0byBzZXRcbiAgICAgICAgICogQHJldHVybnMge29ubnguQXR0cmlidXRlUHJvdG99IEF0dHJpYnV0ZVByb3RvIGluc3RhbmNlXG4gICAgICAgICAqL1xuICAgICAgICBBdHRyaWJ1dGVQcm90by5jcmVhdGUgPSBmdW5jdGlvbiBjcmVhdGUocHJvcGVydGllcykge1xuICAgICAgICAgICAgcmV0dXJuIG5ldyBBdHRyaWJ1dGVQcm90byhwcm9wZXJ0aWVzKTtcbiAgICAgICAgfTtcblxuICAgICAgICAvKipcbiAgICAgICAgICogRW5jb2RlcyB0aGUgc3BlY2lmaWVkIEF0dHJpYnV0ZVByb3RvIG1lc3NhZ2UuIERvZXMgbm90IGltcGxpY2l0bHkge0BsaW5rIG9ubnguQXR0cmlidXRlUHJvdG8udmVyaWZ5fHZlcmlmeX0gbWVzc2FnZXMuXG4gICAgICAgICAqIEBmdW5jdGlvbiBlbmNvZGVcbiAgICAgICAgICogQG1lbWJlcm9mIG9ubnguQXR0cmlidXRlUHJvdG9cbiAgICAgICAgICogQHN0YXRpY1xuICAgICAgICAgKiBAcGFyYW0ge29ubnguSUF0dHJpYnV0ZVByb3RvfSBtZXNzYWdlIEF0dHJpYnV0ZVByb3RvIG1lc3NhZ2Ugb3IgcGxhaW4gb2JqZWN0IHRvIGVuY29kZVxuICAgICAgICAgKiBAcGFyYW0geyRwcm90b2J1Zi5Xcml0ZXJ9IFt3cml0ZXJdIFdyaXRlciB0byBlbmNvZGUgdG9cbiAgICAgICAgICogQHJldHVybnMgeyRwcm90b2J1Zi5Xcml0ZXJ9IFdyaXRlclxuICAgICAgICAgKi9cbiAgICAgICAgQXR0cmlidXRlUHJvdG8uZW5jb2RlID0gZnVuY3Rpb24gZW5jb2RlKG1lc3NhZ2UsIHdyaXRlcikge1xuICAgICAgICAgICAgaWYgKCF3cml0ZXIpXG4gICAgICAgICAgICAgICAgd3JpdGVyID0gJFdyaXRlci5jcmVhdGUoKTtcbiAgICAgICAgICAgIGlmIChtZXNzYWdlLm5hbWUgIT0gbnVsbCAmJiBtZXNzYWdlLmhhc093blByb3BlcnR5KFwibmFtZVwiKSlcbiAgICAgICAgICAgICAgICB3cml0ZXIudWludDMyKC8qIGlkIDEsIHdpcmVUeXBlIDIgPSovMTApLnN0cmluZyhtZXNzYWdlLm5hbWUpO1xuICAgICAgICAgICAgaWYgKG1lc3NhZ2UuZiAhPSBudWxsICYmIG1lc3NhZ2UuaGFzT3duUHJvcGVydHkoXCJmXCIpKVxuICAgICAgICAgICAgICAgIHdyaXRlci51aW50MzIoLyogaWQgMiwgd2lyZVR5cGUgNSA9Ki8yMSkuZmxvYXQobWVzc2FnZS5mKTtcbiAgICAgICAgICAgIGlmIChtZXNzYWdlLmkgIT0gbnVsbCAmJiBtZXNzYWdlLmhhc093blByb3BlcnR5KFwiaVwiKSlcbiAgICAgICAgICAgICAgICB3cml0ZXIudWludDMyKC8qIGlkIDMsIHdpcmVUeXBlIDAgPSovMjQpLmludDY0KG1lc3NhZ2UuaSk7XG4gICAgICAgICAgICBpZiAobWVzc2FnZS5zICE9IG51bGwgJiYgbWVzc2FnZS5oYXNPd25Qcm9wZXJ0eShcInNcIikpXG4gICAgICAgICAgICAgICAgd3JpdGVyLnVpbnQzMigvKiBpZCA0LCB3aXJlVHlwZSAyID0qLzM0KS5ieXRlcyhtZXNzYWdlLnMpO1xuICAgICAgICAgICAgaWYgKG1lc3NhZ2UudCAhPSBudWxsICYmIG1lc3NhZ2UuaGFzT3duUHJvcGVydHkoXCJ0XCIpKVxuICAgICAgICAgICAgICAgICRyb290Lm9ubnguVGVuc29yUHJvdG8uZW5jb2RlKG1lc3NhZ2UudCwgd3JpdGVyLnVpbnQzMigvKiBpZCA1LCB3aXJlVHlwZSAyID0qLzQyKS5mb3JrKCkpLmxkZWxpbSgpO1xuICAgICAgICAgICAgaWYgKG1lc3NhZ2UuZyAhPSBudWxsICYmIG1lc3NhZ2UuaGFzT3duUHJvcGVydHkoXCJnXCIpKVxuICAgICAgICAgICAgICAgICRyb290Lm9ubnguR3JhcGhQcm90by5lbmNvZGUobWVzc2FnZS5nLCB3cml0ZXIudWludDMyKC8qIGlkIDYsIHdpcmVUeXBlIDIgPSovNTApLmZvcmsoKSkubGRlbGltKCk7XG4gICAgICAgICAgICBpZiAobWVzc2FnZS5mbG9hdHMgIT0gbnVsbCAmJiBtZXNzYWdlLmZsb2F0cy5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICB3cml0ZXIudWludDMyKC8qIGlkIDcsIHdpcmVUeXBlIDIgPSovNTgpLmZvcmsoKTtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG1lc3NhZ2UuZmxvYXRzLmxlbmd0aDsgKytpKVxuICAgICAgICAgICAgICAgICAgICB3cml0ZXIuZmxvYXQobWVzc2FnZS5mbG9hdHNbaV0pO1xuICAgICAgICAgICAgICAgIHdyaXRlci5sZGVsaW0oKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChtZXNzYWdlLmludHMgIT0gbnVsbCAmJiBtZXNzYWdlLmludHMubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgd3JpdGVyLnVpbnQzMigvKiBpZCA4LCB3aXJlVHlwZSAyID0qLzY2KS5mb3JrKCk7XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBtZXNzYWdlLmludHMubGVuZ3RoOyArK2kpXG4gICAgICAgICAgICAgICAgICAgIHdyaXRlci5pbnQ2NChtZXNzYWdlLmludHNbaV0pO1xuICAgICAgICAgICAgICAgIHdyaXRlci5sZGVsaW0oKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChtZXNzYWdlLnN0cmluZ3MgIT0gbnVsbCAmJiBtZXNzYWdlLnN0cmluZ3MubGVuZ3RoKVxuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbWVzc2FnZS5zdHJpbmdzLmxlbmd0aDsgKytpKVxuICAgICAgICAgICAgICAgICAgICB3cml0ZXIudWludDMyKC8qIGlkIDksIHdpcmVUeXBlIDIgPSovNzQpLmJ5dGVzKG1lc3NhZ2Uuc3RyaW5nc1tpXSk7XG4gICAgICAgICAgICBpZiAobWVzc2FnZS50ZW5zb3JzICE9IG51bGwgJiYgbWVzc2FnZS50ZW5zb3JzLmxlbmd0aClcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG1lc3NhZ2UudGVuc29ycy5sZW5ndGg7ICsraSlcbiAgICAgICAgICAgICAgICAgICAgJHJvb3Qub25ueC5UZW5zb3JQcm90by5lbmNvZGUobWVzc2FnZS50ZW5zb3JzW2ldLCB3cml0ZXIudWludDMyKC8qIGlkIDEwLCB3aXJlVHlwZSAyID0qLzgyKS5mb3JrKCkpLmxkZWxpbSgpO1xuICAgICAgICAgICAgaWYgKG1lc3NhZ2UuZ3JhcGhzICE9IG51bGwgJiYgbWVzc2FnZS5ncmFwaHMubGVuZ3RoKVxuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbWVzc2FnZS5ncmFwaHMubGVuZ3RoOyArK2kpXG4gICAgICAgICAgICAgICAgICAgICRyb290Lm9ubnguR3JhcGhQcm90by5lbmNvZGUobWVzc2FnZS5ncmFwaHNbaV0sIHdyaXRlci51aW50MzIoLyogaWQgMTEsIHdpcmVUeXBlIDIgPSovOTApLmZvcmsoKSkubGRlbGltKCk7XG4gICAgICAgICAgICBpZiAobWVzc2FnZS5kb2NTdHJpbmcgIT0gbnVsbCAmJiBtZXNzYWdlLmhhc093blByb3BlcnR5KFwiZG9jU3RyaW5nXCIpKVxuICAgICAgICAgICAgICAgIHdyaXRlci51aW50MzIoLyogaWQgMTMsIHdpcmVUeXBlIDIgPSovMTA2KS5zdHJpbmcobWVzc2FnZS5kb2NTdHJpbmcpO1xuICAgICAgICAgICAgaWYgKG1lc3NhZ2UudHlwZSAhPSBudWxsICYmIG1lc3NhZ2UuaGFzT3duUHJvcGVydHkoXCJ0eXBlXCIpKVxuICAgICAgICAgICAgICAgIHdyaXRlci51aW50MzIoLyogaWQgMjAsIHdpcmVUeXBlIDAgPSovMTYwKS5pbnQzMihtZXNzYWdlLnR5cGUpO1xuICAgICAgICAgICAgaWYgKG1lc3NhZ2UucmVmQXR0ck5hbWUgIT0gbnVsbCAmJiBtZXNzYWdlLmhhc093blByb3BlcnR5KFwicmVmQXR0ck5hbWVcIikpXG4gICAgICAgICAgICAgICAgd3JpdGVyLnVpbnQzMigvKiBpZCAyMSwgd2lyZVR5cGUgMiA9Ki8xNzApLnN0cmluZyhtZXNzYWdlLnJlZkF0dHJOYW1lKTtcbiAgICAgICAgICAgIHJldHVybiB3cml0ZXI7XG4gICAgICAgIH07XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEVuY29kZXMgdGhlIHNwZWNpZmllZCBBdHRyaWJ1dGVQcm90byBtZXNzYWdlLCBsZW5ndGggZGVsaW1pdGVkLiBEb2VzIG5vdCBpbXBsaWNpdGx5IHtAbGluayBvbm54LkF0dHJpYnV0ZVByb3RvLnZlcmlmeXx2ZXJpZnl9IG1lc3NhZ2VzLlxuICAgICAgICAgKiBAZnVuY3Rpb24gZW5jb2RlRGVsaW1pdGVkXG4gICAgICAgICAqIEBtZW1iZXJvZiBvbm54LkF0dHJpYnV0ZVByb3RvXG4gICAgICAgICAqIEBzdGF0aWNcbiAgICAgICAgICogQHBhcmFtIHtvbm54LklBdHRyaWJ1dGVQcm90b30gbWVzc2FnZSBBdHRyaWJ1dGVQcm90byBtZXNzYWdlIG9yIHBsYWluIG9iamVjdCB0byBlbmNvZGVcbiAgICAgICAgICogQHBhcmFtIHskcHJvdG9idWYuV3JpdGVyfSBbd3JpdGVyXSBXcml0ZXIgdG8gZW5jb2RlIHRvXG4gICAgICAgICAqIEByZXR1cm5zIHskcHJvdG9idWYuV3JpdGVyfSBXcml0ZXJcbiAgICAgICAgICovXG4gICAgICAgIEF0dHJpYnV0ZVByb3RvLmVuY29kZURlbGltaXRlZCA9IGZ1bmN0aW9uIGVuY29kZURlbGltaXRlZChtZXNzYWdlLCB3cml0ZXIpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmVuY29kZShtZXNzYWdlLCB3cml0ZXIpLmxkZWxpbSgpO1xuICAgICAgICB9O1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBEZWNvZGVzIGFuIEF0dHJpYnV0ZVByb3RvIG1lc3NhZ2UgZnJvbSB0aGUgc3BlY2lmaWVkIHJlYWRlciBvciBidWZmZXIuXG4gICAgICAgICAqIEBmdW5jdGlvbiBkZWNvZGVcbiAgICAgICAgICogQG1lbWJlcm9mIG9ubnguQXR0cmlidXRlUHJvdG9cbiAgICAgICAgICogQHN0YXRpY1xuICAgICAgICAgKiBAcGFyYW0geyRwcm90b2J1Zi5SZWFkZXJ8VWludDhBcnJheX0gcmVhZGVyIFJlYWRlciBvciBidWZmZXIgdG8gZGVjb2RlIGZyb21cbiAgICAgICAgICogQHBhcmFtIHtudW1iZXJ9IFtsZW5ndGhdIE1lc3NhZ2UgbGVuZ3RoIGlmIGtub3duIGJlZm9yZWhhbmRcbiAgICAgICAgICogQHJldHVybnMge29ubnguQXR0cmlidXRlUHJvdG99IEF0dHJpYnV0ZVByb3RvXG4gICAgICAgICAqIEB0aHJvd3Mge0Vycm9yfSBJZiB0aGUgcGF5bG9hZCBpcyBub3QgYSByZWFkZXIgb3IgdmFsaWQgYnVmZmVyXG4gICAgICAgICAqIEB0aHJvd3MgeyRwcm90b2J1Zi51dGlsLlByb3RvY29sRXJyb3J9IElmIHJlcXVpcmVkIGZpZWxkcyBhcmUgbWlzc2luZ1xuICAgICAgICAgKi9cbiAgICAgICAgQXR0cmlidXRlUHJvdG8uZGVjb2RlID0gZnVuY3Rpb24gZGVjb2RlKHJlYWRlciwgbGVuZ3RoKSB7XG4gICAgICAgICAgICBpZiAoIShyZWFkZXIgaW5zdGFuY2VvZiAkUmVhZGVyKSlcbiAgICAgICAgICAgICAgICByZWFkZXIgPSAkUmVhZGVyLmNyZWF0ZShyZWFkZXIpO1xuICAgICAgICAgICAgdmFyIGVuZCA9IGxlbmd0aCA9PT0gdW5kZWZpbmVkID8gcmVhZGVyLmxlbiA6IHJlYWRlci5wb3MgKyBsZW5ndGgsIG1lc3NhZ2UgPSBuZXcgJHJvb3Qub25ueC5BdHRyaWJ1dGVQcm90bygpO1xuICAgICAgICAgICAgd2hpbGUgKHJlYWRlci5wb3MgPCBlbmQpIHtcbiAgICAgICAgICAgICAgICB2YXIgdGFnID0gcmVhZGVyLnVpbnQzMigpO1xuICAgICAgICAgICAgICAgIHN3aXRjaCAodGFnID4+PiAzKSB7XG4gICAgICAgICAgICAgICAgY2FzZSAxOlxuICAgICAgICAgICAgICAgICAgICBtZXNzYWdlLm5hbWUgPSByZWFkZXIuc3RyaW5nKCk7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgMjE6XG4gICAgICAgICAgICAgICAgICAgIG1lc3NhZ2UucmVmQXR0ck5hbWUgPSByZWFkZXIuc3RyaW5nKCk7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgMTM6XG4gICAgICAgICAgICAgICAgICAgIG1lc3NhZ2UuZG9jU3RyaW5nID0gcmVhZGVyLnN0cmluZygpO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlIDIwOlxuICAgICAgICAgICAgICAgICAgICBtZXNzYWdlLnR5cGUgPSByZWFkZXIuaW50MzIoKTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSAyOlxuICAgICAgICAgICAgICAgICAgICBtZXNzYWdlLmYgPSByZWFkZXIuZmxvYXQoKTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSAzOlxuICAgICAgICAgICAgICAgICAgICBtZXNzYWdlLmkgPSByZWFkZXIuaW50NjQoKTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSA0OlxuICAgICAgICAgICAgICAgICAgICBtZXNzYWdlLnMgPSByZWFkZXIuYnl0ZXMoKTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSA1OlxuICAgICAgICAgICAgICAgICAgICBtZXNzYWdlLnQgPSAkcm9vdC5vbm54LlRlbnNvclByb3RvLmRlY29kZShyZWFkZXIsIHJlYWRlci51aW50MzIoKSk7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgNjpcbiAgICAgICAgICAgICAgICAgICAgbWVzc2FnZS5nID0gJHJvb3Qub25ueC5HcmFwaFByb3RvLmRlY29kZShyZWFkZXIsIHJlYWRlci51aW50MzIoKSk7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgNzpcbiAgICAgICAgICAgICAgICAgICAgaWYgKCEobWVzc2FnZS5mbG9hdHMgJiYgbWVzc2FnZS5mbG9hdHMubGVuZ3RoKSlcbiAgICAgICAgICAgICAgICAgICAgICAgIG1lc3NhZ2UuZmxvYXRzID0gW107XG4gICAgICAgICAgICAgICAgICAgIGlmICgodGFnICYgNykgPT09IDIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBlbmQyID0gcmVhZGVyLnVpbnQzMigpICsgcmVhZGVyLnBvcztcbiAgICAgICAgICAgICAgICAgICAgICAgIHdoaWxlIChyZWFkZXIucG9zIDwgZW5kMilcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZXNzYWdlLmZsb2F0cy5wdXNoKHJlYWRlci5mbG9hdCgpKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlXG4gICAgICAgICAgICAgICAgICAgICAgICBtZXNzYWdlLmZsb2F0cy5wdXNoKHJlYWRlci5mbG9hdCgpKTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSA4OlxuICAgICAgICAgICAgICAgICAgICBpZiAoIShtZXNzYWdlLmludHMgJiYgbWVzc2FnZS5pbnRzLmxlbmd0aCkpXG4gICAgICAgICAgICAgICAgICAgICAgICBtZXNzYWdlLmludHMgPSBbXTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCh0YWcgJiA3KSA9PT0gMikge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGVuZDIgPSByZWFkZXIudWludDMyKCkgKyByZWFkZXIucG9zO1xuICAgICAgICAgICAgICAgICAgICAgICAgd2hpbGUgKHJlYWRlci5wb3MgPCBlbmQyKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1lc3NhZ2UuaW50cy5wdXNoKHJlYWRlci5pbnQ2NCgpKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlXG4gICAgICAgICAgICAgICAgICAgICAgICBtZXNzYWdlLmludHMucHVzaChyZWFkZXIuaW50NjQoKSk7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgOTpcbiAgICAgICAgICAgICAgICAgICAgaWYgKCEobWVzc2FnZS5zdHJpbmdzICYmIG1lc3NhZ2Uuc3RyaW5ncy5sZW5ndGgpKVxuICAgICAgICAgICAgICAgICAgICAgICAgbWVzc2FnZS5zdHJpbmdzID0gW107XG4gICAgICAgICAgICAgICAgICAgIG1lc3NhZ2Uuc3RyaW5ncy5wdXNoKHJlYWRlci5ieXRlcygpKTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSAxMDpcbiAgICAgICAgICAgICAgICAgICAgaWYgKCEobWVzc2FnZS50ZW5zb3JzICYmIG1lc3NhZ2UudGVuc29ycy5sZW5ndGgpKVxuICAgICAgICAgICAgICAgICAgICAgICAgbWVzc2FnZS50ZW5zb3JzID0gW107XG4gICAgICAgICAgICAgICAgICAgIG1lc3NhZ2UudGVuc29ycy5wdXNoKCRyb290Lm9ubnguVGVuc29yUHJvdG8uZGVjb2RlKHJlYWRlciwgcmVhZGVyLnVpbnQzMigpKSk7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgMTE6XG4gICAgICAgICAgICAgICAgICAgIGlmICghKG1lc3NhZ2UuZ3JhcGhzICYmIG1lc3NhZ2UuZ3JhcGhzLmxlbmd0aCkpXG4gICAgICAgICAgICAgICAgICAgICAgICBtZXNzYWdlLmdyYXBocyA9IFtdO1xuICAgICAgICAgICAgICAgICAgICBtZXNzYWdlLmdyYXBocy5wdXNoKCRyb290Lm9ubnguR3JhcGhQcm90by5kZWNvZGUocmVhZGVyLCByZWFkZXIudWludDMyKCkpKTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICAgICAgcmVhZGVyLnNraXBUeXBlKHRhZyAmIDcpO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gbWVzc2FnZTtcbiAgICAgICAgfTtcblxuICAgICAgICAvKipcbiAgICAgICAgICogRGVjb2RlcyBhbiBBdHRyaWJ1dGVQcm90byBtZXNzYWdlIGZyb20gdGhlIHNwZWNpZmllZCByZWFkZXIgb3IgYnVmZmVyLCBsZW5ndGggZGVsaW1pdGVkLlxuICAgICAgICAgKiBAZnVuY3Rpb24gZGVjb2RlRGVsaW1pdGVkXG4gICAgICAgICAqIEBtZW1iZXJvZiBvbm54LkF0dHJpYnV0ZVByb3RvXG4gICAgICAgICAqIEBzdGF0aWNcbiAgICAgICAgICogQHBhcmFtIHskcHJvdG9idWYuUmVhZGVyfFVpbnQ4QXJyYXl9IHJlYWRlciBSZWFkZXIgb3IgYnVmZmVyIHRvIGRlY29kZSBmcm9tXG4gICAgICAgICAqIEByZXR1cm5zIHtvbm54LkF0dHJpYnV0ZVByb3RvfSBBdHRyaWJ1dGVQcm90b1xuICAgICAgICAgKiBAdGhyb3dzIHtFcnJvcn0gSWYgdGhlIHBheWxvYWQgaXMgbm90IGEgcmVhZGVyIG9yIHZhbGlkIGJ1ZmZlclxuICAgICAgICAgKiBAdGhyb3dzIHskcHJvdG9idWYudXRpbC5Qcm90b2NvbEVycm9yfSBJZiByZXF1aXJlZCBmaWVsZHMgYXJlIG1pc3NpbmdcbiAgICAgICAgICovXG4gICAgICAgIEF0dHJpYnV0ZVByb3RvLmRlY29kZURlbGltaXRlZCA9IGZ1bmN0aW9uIGRlY29kZURlbGltaXRlZChyZWFkZXIpIHtcbiAgICAgICAgICAgIGlmICghKHJlYWRlciBpbnN0YW5jZW9mICRSZWFkZXIpKVxuICAgICAgICAgICAgICAgIHJlYWRlciA9IG5ldyAkUmVhZGVyKHJlYWRlcik7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5kZWNvZGUocmVhZGVyLCByZWFkZXIudWludDMyKCkpO1xuICAgICAgICB9O1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBWZXJpZmllcyBhbiBBdHRyaWJ1dGVQcm90byBtZXNzYWdlLlxuICAgICAgICAgKiBAZnVuY3Rpb24gdmVyaWZ5XG4gICAgICAgICAqIEBtZW1iZXJvZiBvbm54LkF0dHJpYnV0ZVByb3RvXG4gICAgICAgICAqIEBzdGF0aWNcbiAgICAgICAgICogQHBhcmFtIHtPYmplY3QuPHN0cmluZywqPn0gbWVzc2FnZSBQbGFpbiBvYmplY3QgdG8gdmVyaWZ5XG4gICAgICAgICAqIEByZXR1cm5zIHtzdHJpbmd8bnVsbH0gYG51bGxgIGlmIHZhbGlkLCBvdGhlcndpc2UgdGhlIHJlYXNvbiB3aHkgaXQgaXMgbm90XG4gICAgICAgICAqL1xuICAgICAgICBBdHRyaWJ1dGVQcm90by52ZXJpZnkgPSBmdW5jdGlvbiB2ZXJpZnkobWVzc2FnZSkge1xuICAgICAgICAgICAgaWYgKHR5cGVvZiBtZXNzYWdlICE9PSBcIm9iamVjdFwiIHx8IG1lc3NhZ2UgPT09IG51bGwpXG4gICAgICAgICAgICAgICAgcmV0dXJuIFwib2JqZWN0IGV4cGVjdGVkXCI7XG4gICAgICAgICAgICBpZiAobWVzc2FnZS5uYW1lICE9IG51bGwgJiYgbWVzc2FnZS5oYXNPd25Qcm9wZXJ0eShcIm5hbWVcIikpXG4gICAgICAgICAgICAgICAgaWYgKCEkdXRpbC5pc1N0cmluZyhtZXNzYWdlLm5hbWUpKVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gXCJuYW1lOiBzdHJpbmcgZXhwZWN0ZWRcIjtcbiAgICAgICAgICAgIGlmIChtZXNzYWdlLnJlZkF0dHJOYW1lICE9IG51bGwgJiYgbWVzc2FnZS5oYXNPd25Qcm9wZXJ0eShcInJlZkF0dHJOYW1lXCIpKVxuICAgICAgICAgICAgICAgIGlmICghJHV0aWwuaXNTdHJpbmcobWVzc2FnZS5yZWZBdHRyTmFtZSkpXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBcInJlZkF0dHJOYW1lOiBzdHJpbmcgZXhwZWN0ZWRcIjtcbiAgICAgICAgICAgIGlmIChtZXNzYWdlLmRvY1N0cmluZyAhPSBudWxsICYmIG1lc3NhZ2UuaGFzT3duUHJvcGVydHkoXCJkb2NTdHJpbmdcIikpXG4gICAgICAgICAgICAgICAgaWYgKCEkdXRpbC5pc1N0cmluZyhtZXNzYWdlLmRvY1N0cmluZykpXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBcImRvY1N0cmluZzogc3RyaW5nIGV4cGVjdGVkXCI7XG4gICAgICAgICAgICBpZiAobWVzc2FnZS50eXBlICE9IG51bGwgJiYgbWVzc2FnZS5oYXNPd25Qcm9wZXJ0eShcInR5cGVcIikpXG4gICAgICAgICAgICAgICAgc3dpdGNoIChtZXNzYWdlLnR5cGUpIHtcbiAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gXCJ0eXBlOiBlbnVtIHZhbHVlIGV4cGVjdGVkXCI7XG4gICAgICAgICAgICAgICAgY2FzZSAwOlxuICAgICAgICAgICAgICAgIGNhc2UgMTpcbiAgICAgICAgICAgICAgICBjYXNlIDI6XG4gICAgICAgICAgICAgICAgY2FzZSAzOlxuICAgICAgICAgICAgICAgIGNhc2UgNDpcbiAgICAgICAgICAgICAgICBjYXNlIDU6XG4gICAgICAgICAgICAgICAgY2FzZSA2OlxuICAgICAgICAgICAgICAgIGNhc2UgNzpcbiAgICAgICAgICAgICAgICBjYXNlIDg6XG4gICAgICAgICAgICAgICAgY2FzZSA5OlxuICAgICAgICAgICAgICAgIGNhc2UgMTA6XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChtZXNzYWdlLmYgIT0gbnVsbCAmJiBtZXNzYWdlLmhhc093blByb3BlcnR5KFwiZlwiKSlcbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIG1lc3NhZ2UuZiAhPT0gXCJudW1iZXJcIilcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFwiZjogbnVtYmVyIGV4cGVjdGVkXCI7XG4gICAgICAgICAgICBpZiAobWVzc2FnZS5pICE9IG51bGwgJiYgbWVzc2FnZS5oYXNPd25Qcm9wZXJ0eShcImlcIikpXG4gICAgICAgICAgICAgICAgaWYgKCEkdXRpbC5pc0ludGVnZXIobWVzc2FnZS5pKSAmJiAhKG1lc3NhZ2UuaSAmJiAkdXRpbC5pc0ludGVnZXIobWVzc2FnZS5pLmxvdykgJiYgJHV0aWwuaXNJbnRlZ2VyKG1lc3NhZ2UuaS5oaWdoKSkpXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBcImk6IGludGVnZXJ8TG9uZyBleHBlY3RlZFwiO1xuICAgICAgICAgICAgaWYgKG1lc3NhZ2UucyAhPSBudWxsICYmIG1lc3NhZ2UuaGFzT3duUHJvcGVydHkoXCJzXCIpKVxuICAgICAgICAgICAgICAgIGlmICghKG1lc3NhZ2UucyAmJiB0eXBlb2YgbWVzc2FnZS5zLmxlbmd0aCA9PT0gXCJudW1iZXJcIiB8fCAkdXRpbC5pc1N0cmluZyhtZXNzYWdlLnMpKSlcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFwiczogYnVmZmVyIGV4cGVjdGVkXCI7XG4gICAgICAgICAgICBpZiAobWVzc2FnZS50ICE9IG51bGwgJiYgbWVzc2FnZS5oYXNPd25Qcm9wZXJ0eShcInRcIikpIHtcbiAgICAgICAgICAgICAgICB2YXIgZXJyb3IgPSAkcm9vdC5vbm54LlRlbnNvclByb3RvLnZlcmlmeShtZXNzYWdlLnQpO1xuICAgICAgICAgICAgICAgIGlmIChlcnJvcilcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFwidC5cIiArIGVycm9yO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG1lc3NhZ2UuZyAhPSBudWxsICYmIG1lc3NhZ2UuaGFzT3duUHJvcGVydHkoXCJnXCIpKSB7XG4gICAgICAgICAgICAgICAgdmFyIGVycm9yID0gJHJvb3Qub25ueC5HcmFwaFByb3RvLnZlcmlmeShtZXNzYWdlLmcpO1xuICAgICAgICAgICAgICAgIGlmIChlcnJvcilcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFwiZy5cIiArIGVycm9yO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG1lc3NhZ2UuZmxvYXRzICE9IG51bGwgJiYgbWVzc2FnZS5oYXNPd25Qcm9wZXJ0eShcImZsb2F0c1wiKSkge1xuICAgICAgICAgICAgICAgIGlmICghQXJyYXkuaXNBcnJheShtZXNzYWdlLmZsb2F0cykpXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBcImZsb2F0czogYXJyYXkgZXhwZWN0ZWRcIjtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG1lc3NhZ2UuZmxvYXRzLmxlbmd0aDsgKytpKVxuICAgICAgICAgICAgICAgICAgICBpZiAodHlwZW9mIG1lc3NhZ2UuZmxvYXRzW2ldICE9PSBcIm51bWJlclwiKVxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFwiZmxvYXRzOiBudW1iZXJbXSBleHBlY3RlZFwiO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG1lc3NhZ2UuaW50cyAhPSBudWxsICYmIG1lc3NhZ2UuaGFzT3duUHJvcGVydHkoXCJpbnRzXCIpKSB7XG4gICAgICAgICAgICAgICAgaWYgKCFBcnJheS5pc0FycmF5KG1lc3NhZ2UuaW50cykpXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBcImludHM6IGFycmF5IGV4cGVjdGVkXCI7XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBtZXNzYWdlLmludHMubGVuZ3RoOyArK2kpXG4gICAgICAgICAgICAgICAgICAgIGlmICghJHV0aWwuaXNJbnRlZ2VyKG1lc3NhZ2UuaW50c1tpXSkgJiYgIShtZXNzYWdlLmludHNbaV0gJiYgJHV0aWwuaXNJbnRlZ2VyKG1lc3NhZ2UuaW50c1tpXS5sb3cpICYmICR1dGlsLmlzSW50ZWdlcihtZXNzYWdlLmludHNbaV0uaGlnaCkpKVxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFwiaW50czogaW50ZWdlcnxMb25nW10gZXhwZWN0ZWRcIjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChtZXNzYWdlLnN0cmluZ3MgIT0gbnVsbCAmJiBtZXNzYWdlLmhhc093blByb3BlcnR5KFwic3RyaW5nc1wiKSkge1xuICAgICAgICAgICAgICAgIGlmICghQXJyYXkuaXNBcnJheShtZXNzYWdlLnN0cmluZ3MpKVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gXCJzdHJpbmdzOiBhcnJheSBleHBlY3RlZFwiO1xuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbWVzc2FnZS5zdHJpbmdzLmxlbmd0aDsgKytpKVxuICAgICAgICAgICAgICAgICAgICBpZiAoIShtZXNzYWdlLnN0cmluZ3NbaV0gJiYgdHlwZW9mIG1lc3NhZ2Uuc3RyaW5nc1tpXS5sZW5ndGggPT09IFwibnVtYmVyXCIgfHwgJHV0aWwuaXNTdHJpbmcobWVzc2FnZS5zdHJpbmdzW2ldKSkpXG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gXCJzdHJpbmdzOiBidWZmZXJbXSBleHBlY3RlZFwiO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG1lc3NhZ2UudGVuc29ycyAhPSBudWxsICYmIG1lc3NhZ2UuaGFzT3duUHJvcGVydHkoXCJ0ZW5zb3JzXCIpKSB7XG4gICAgICAgICAgICAgICAgaWYgKCFBcnJheS5pc0FycmF5KG1lc3NhZ2UudGVuc29ycykpXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBcInRlbnNvcnM6IGFycmF5IGV4cGVjdGVkXCI7XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBtZXNzYWdlLnRlbnNvcnMubGVuZ3RoOyArK2kpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGVycm9yID0gJHJvb3Qub25ueC5UZW5zb3JQcm90by52ZXJpZnkobWVzc2FnZS50ZW5zb3JzW2ldKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGVycm9yKVxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFwidGVuc29ycy5cIiArIGVycm9yO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChtZXNzYWdlLmdyYXBocyAhPSBudWxsICYmIG1lc3NhZ2UuaGFzT3duUHJvcGVydHkoXCJncmFwaHNcIikpIHtcbiAgICAgICAgICAgICAgICBpZiAoIUFycmF5LmlzQXJyYXkobWVzc2FnZS5ncmFwaHMpKVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gXCJncmFwaHM6IGFycmF5IGV4cGVjdGVkXCI7XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBtZXNzYWdlLmdyYXBocy5sZW5ndGg7ICsraSkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgZXJyb3IgPSAkcm9vdC5vbm54LkdyYXBoUHJvdG8udmVyaWZ5KG1lc3NhZ2UuZ3JhcGhzW2ldKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGVycm9yKVxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFwiZ3JhcGhzLlwiICsgZXJyb3I7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgIH07XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIENyZWF0ZXMgYW4gQXR0cmlidXRlUHJvdG8gbWVzc2FnZSBmcm9tIGEgcGxhaW4gb2JqZWN0LiBBbHNvIGNvbnZlcnRzIHZhbHVlcyB0byB0aGVpciByZXNwZWN0aXZlIGludGVybmFsIHR5cGVzLlxuICAgICAgICAgKiBAZnVuY3Rpb24gZnJvbU9iamVjdFxuICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueC5BdHRyaWJ1dGVQcm90b1xuICAgICAgICAgKiBAc3RhdGljXG4gICAgICAgICAqIEBwYXJhbSB7T2JqZWN0LjxzdHJpbmcsKj59IG9iamVjdCBQbGFpbiBvYmplY3RcbiAgICAgICAgICogQHJldHVybnMge29ubnguQXR0cmlidXRlUHJvdG99IEF0dHJpYnV0ZVByb3RvXG4gICAgICAgICAqL1xuICAgICAgICBBdHRyaWJ1dGVQcm90by5mcm9tT2JqZWN0ID0gZnVuY3Rpb24gZnJvbU9iamVjdChvYmplY3QpIHtcbiAgICAgICAgICAgIGlmIChvYmplY3QgaW5zdGFuY2VvZiAkcm9vdC5vbm54LkF0dHJpYnV0ZVByb3RvKVxuICAgICAgICAgICAgICAgIHJldHVybiBvYmplY3Q7XG4gICAgICAgICAgICB2YXIgbWVzc2FnZSA9IG5ldyAkcm9vdC5vbm54LkF0dHJpYnV0ZVByb3RvKCk7XG4gICAgICAgICAgICBpZiAob2JqZWN0Lm5hbWUgIT0gbnVsbClcbiAgICAgICAgICAgICAgICBtZXNzYWdlLm5hbWUgPSBTdHJpbmcob2JqZWN0Lm5hbWUpO1xuICAgICAgICAgICAgaWYgKG9iamVjdC5yZWZBdHRyTmFtZSAhPSBudWxsKVxuICAgICAgICAgICAgICAgIG1lc3NhZ2UucmVmQXR0ck5hbWUgPSBTdHJpbmcob2JqZWN0LnJlZkF0dHJOYW1lKTtcbiAgICAgICAgICAgIGlmIChvYmplY3QuZG9jU3RyaW5nICE9IG51bGwpXG4gICAgICAgICAgICAgICAgbWVzc2FnZS5kb2NTdHJpbmcgPSBTdHJpbmcob2JqZWN0LmRvY1N0cmluZyk7XG4gICAgICAgICAgICBzd2l0Y2ggKG9iamVjdC50eXBlKSB7XG4gICAgICAgICAgICBjYXNlIFwiVU5ERUZJTkVEXCI6XG4gICAgICAgICAgICBjYXNlIDA6XG4gICAgICAgICAgICAgICAgbWVzc2FnZS50eXBlID0gMDtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgXCJGTE9BVFwiOlxuICAgICAgICAgICAgY2FzZSAxOlxuICAgICAgICAgICAgICAgIG1lc3NhZ2UudHlwZSA9IDE7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIFwiSU5UXCI6XG4gICAgICAgICAgICBjYXNlIDI6XG4gICAgICAgICAgICAgICAgbWVzc2FnZS50eXBlID0gMjtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgXCJTVFJJTkdcIjpcbiAgICAgICAgICAgIGNhc2UgMzpcbiAgICAgICAgICAgICAgICBtZXNzYWdlLnR5cGUgPSAzO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBcIlRFTlNPUlwiOlxuICAgICAgICAgICAgY2FzZSA0OlxuICAgICAgICAgICAgICAgIG1lc3NhZ2UudHlwZSA9IDQ7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIFwiR1JBUEhcIjpcbiAgICAgICAgICAgIGNhc2UgNTpcbiAgICAgICAgICAgICAgICBtZXNzYWdlLnR5cGUgPSA1O1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBcIkZMT0FUU1wiOlxuICAgICAgICAgICAgY2FzZSA2OlxuICAgICAgICAgICAgICAgIG1lc3NhZ2UudHlwZSA9IDY7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIFwiSU5UU1wiOlxuICAgICAgICAgICAgY2FzZSA3OlxuICAgICAgICAgICAgICAgIG1lc3NhZ2UudHlwZSA9IDc7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIFwiU1RSSU5HU1wiOlxuICAgICAgICAgICAgY2FzZSA4OlxuICAgICAgICAgICAgICAgIG1lc3NhZ2UudHlwZSA9IDg7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIFwiVEVOU09SU1wiOlxuICAgICAgICAgICAgY2FzZSA5OlxuICAgICAgICAgICAgICAgIG1lc3NhZ2UudHlwZSA9IDk7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIFwiR1JBUEhTXCI6XG4gICAgICAgICAgICBjYXNlIDEwOlxuICAgICAgICAgICAgICAgIG1lc3NhZ2UudHlwZSA9IDEwO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG9iamVjdC5mICE9IG51bGwpXG4gICAgICAgICAgICAgICAgbWVzc2FnZS5mID0gTnVtYmVyKG9iamVjdC5mKTtcbiAgICAgICAgICAgIGlmIChvYmplY3QuaSAhPSBudWxsKVxuICAgICAgICAgICAgICAgIGlmICgkdXRpbC5Mb25nKVxuICAgICAgICAgICAgICAgICAgICAobWVzc2FnZS5pID0gJHV0aWwuTG9uZy5mcm9tVmFsdWUob2JqZWN0LmkpKS51bnNpZ25lZCA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIGVsc2UgaWYgKHR5cGVvZiBvYmplY3QuaSA9PT0gXCJzdHJpbmdcIilcbiAgICAgICAgICAgICAgICAgICAgbWVzc2FnZS5pID0gcGFyc2VJbnQob2JqZWN0LmksIDEwKTtcbiAgICAgICAgICAgICAgICBlbHNlIGlmICh0eXBlb2Ygb2JqZWN0LmkgPT09IFwibnVtYmVyXCIpXG4gICAgICAgICAgICAgICAgICAgIG1lc3NhZ2UuaSA9IG9iamVjdC5pO1xuICAgICAgICAgICAgICAgIGVsc2UgaWYgKHR5cGVvZiBvYmplY3QuaSA9PT0gXCJvYmplY3RcIilcbiAgICAgICAgICAgICAgICAgICAgbWVzc2FnZS5pID0gbmV3ICR1dGlsLkxvbmdCaXRzKG9iamVjdC5pLmxvdyA+Pj4gMCwgb2JqZWN0LmkuaGlnaCA+Pj4gMCkudG9OdW1iZXIoKTtcbiAgICAgICAgICAgIGlmIChvYmplY3QucyAhPSBudWxsKVxuICAgICAgICAgICAgICAgIGlmICh0eXBlb2Ygb2JqZWN0LnMgPT09IFwic3RyaW5nXCIpXG4gICAgICAgICAgICAgICAgICAgICR1dGlsLmJhc2U2NC5kZWNvZGUob2JqZWN0LnMsIG1lc3NhZ2UucyA9ICR1dGlsLm5ld0J1ZmZlcigkdXRpbC5iYXNlNjQubGVuZ3RoKG9iamVjdC5zKSksIDApO1xuICAgICAgICAgICAgICAgIGVsc2UgaWYgKG9iamVjdC5zLmxlbmd0aClcbiAgICAgICAgICAgICAgICAgICAgbWVzc2FnZS5zID0gb2JqZWN0LnM7XG4gICAgICAgICAgICBpZiAob2JqZWN0LnQgIT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIGlmICh0eXBlb2Ygb2JqZWN0LnQgIT09IFwib2JqZWN0XCIpXG4gICAgICAgICAgICAgICAgICAgIHRocm93IFR5cGVFcnJvcihcIi5vbm54LkF0dHJpYnV0ZVByb3RvLnQ6IG9iamVjdCBleHBlY3RlZFwiKTtcbiAgICAgICAgICAgICAgICBtZXNzYWdlLnQgPSAkcm9vdC5vbm54LlRlbnNvclByb3RvLmZyb21PYmplY3Qob2JqZWN0LnQpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG9iamVjdC5nICE9IG51bGwpIHtcbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIG9iamVjdC5nICE9PSBcIm9iamVjdFwiKVxuICAgICAgICAgICAgICAgICAgICB0aHJvdyBUeXBlRXJyb3IoXCIub25ueC5BdHRyaWJ1dGVQcm90by5nOiBvYmplY3QgZXhwZWN0ZWRcIik7XG4gICAgICAgICAgICAgICAgbWVzc2FnZS5nID0gJHJvb3Qub25ueC5HcmFwaFByb3RvLmZyb21PYmplY3Qob2JqZWN0LmcpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG9iamVjdC5mbG9hdHMpIHtcbiAgICAgICAgICAgICAgICBpZiAoIUFycmF5LmlzQXJyYXkob2JqZWN0LmZsb2F0cykpXG4gICAgICAgICAgICAgICAgICAgIHRocm93IFR5cGVFcnJvcihcIi5vbm54LkF0dHJpYnV0ZVByb3RvLmZsb2F0czogYXJyYXkgZXhwZWN0ZWRcIik7XG4gICAgICAgICAgICAgICAgbWVzc2FnZS5mbG9hdHMgPSBbXTtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG9iamVjdC5mbG9hdHMubGVuZ3RoOyArK2kpXG4gICAgICAgICAgICAgICAgICAgIG1lc3NhZ2UuZmxvYXRzW2ldID0gTnVtYmVyKG9iamVjdC5mbG9hdHNbaV0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG9iamVjdC5pbnRzKSB7XG4gICAgICAgICAgICAgICAgaWYgKCFBcnJheS5pc0FycmF5KG9iamVjdC5pbnRzKSlcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgVHlwZUVycm9yKFwiLm9ubnguQXR0cmlidXRlUHJvdG8uaW50czogYXJyYXkgZXhwZWN0ZWRcIik7XG4gICAgICAgICAgICAgICAgbWVzc2FnZS5pbnRzID0gW107XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBvYmplY3QuaW50cy5sZW5ndGg7ICsraSlcbiAgICAgICAgICAgICAgICAgICAgaWYgKCR1dGlsLkxvbmcpXG4gICAgICAgICAgICAgICAgICAgICAgICAobWVzc2FnZS5pbnRzW2ldID0gJHV0aWwuTG9uZy5mcm9tVmFsdWUob2JqZWN0LmludHNbaV0pKS51bnNpZ25lZCA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICBlbHNlIGlmICh0eXBlb2Ygb2JqZWN0LmludHNbaV0gPT09IFwic3RyaW5nXCIpXG4gICAgICAgICAgICAgICAgICAgICAgICBtZXNzYWdlLmludHNbaV0gPSBwYXJzZUludChvYmplY3QuaW50c1tpXSwgMTApO1xuICAgICAgICAgICAgICAgICAgICBlbHNlIGlmICh0eXBlb2Ygb2JqZWN0LmludHNbaV0gPT09IFwibnVtYmVyXCIpXG4gICAgICAgICAgICAgICAgICAgICAgICBtZXNzYWdlLmludHNbaV0gPSBvYmplY3QuaW50c1tpXTtcbiAgICAgICAgICAgICAgICAgICAgZWxzZSBpZiAodHlwZW9mIG9iamVjdC5pbnRzW2ldID09PSBcIm9iamVjdFwiKVxuICAgICAgICAgICAgICAgICAgICAgICAgbWVzc2FnZS5pbnRzW2ldID0gbmV3ICR1dGlsLkxvbmdCaXRzKG9iamVjdC5pbnRzW2ldLmxvdyA+Pj4gMCwgb2JqZWN0LmludHNbaV0uaGlnaCA+Pj4gMCkudG9OdW1iZXIoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChvYmplY3Quc3RyaW5ncykge1xuICAgICAgICAgICAgICAgIGlmICghQXJyYXkuaXNBcnJheShvYmplY3Quc3RyaW5ncykpXG4gICAgICAgICAgICAgICAgICAgIHRocm93IFR5cGVFcnJvcihcIi5vbm54LkF0dHJpYnV0ZVByb3RvLnN0cmluZ3M6IGFycmF5IGV4cGVjdGVkXCIpO1xuICAgICAgICAgICAgICAgIG1lc3NhZ2Uuc3RyaW5ncyA9IFtdO1xuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgb2JqZWN0LnN0cmluZ3MubGVuZ3RoOyArK2kpXG4gICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2Ygb2JqZWN0LnN0cmluZ3NbaV0gPT09IFwic3RyaW5nXCIpXG4gICAgICAgICAgICAgICAgICAgICAgICAkdXRpbC5iYXNlNjQuZGVjb2RlKG9iamVjdC5zdHJpbmdzW2ldLCBtZXNzYWdlLnN0cmluZ3NbaV0gPSAkdXRpbC5uZXdCdWZmZXIoJHV0aWwuYmFzZTY0Lmxlbmd0aChvYmplY3Quc3RyaW5nc1tpXSkpLCAwKTtcbiAgICAgICAgICAgICAgICAgICAgZWxzZSBpZiAob2JqZWN0LnN0cmluZ3NbaV0ubGVuZ3RoKVxuICAgICAgICAgICAgICAgICAgICAgICAgbWVzc2FnZS5zdHJpbmdzW2ldID0gb2JqZWN0LnN0cmluZ3NbaV07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAob2JqZWN0LnRlbnNvcnMpIHtcbiAgICAgICAgICAgICAgICBpZiAoIUFycmF5LmlzQXJyYXkob2JqZWN0LnRlbnNvcnMpKVxuICAgICAgICAgICAgICAgICAgICB0aHJvdyBUeXBlRXJyb3IoXCIub25ueC5BdHRyaWJ1dGVQcm90by50ZW5zb3JzOiBhcnJheSBleHBlY3RlZFwiKTtcbiAgICAgICAgICAgICAgICBtZXNzYWdlLnRlbnNvcnMgPSBbXTtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG9iamVjdC50ZW5zb3JzLmxlbmd0aDsgKytpKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2Ygb2JqZWN0LnRlbnNvcnNbaV0gIT09IFwib2JqZWN0XCIpXG4gICAgICAgICAgICAgICAgICAgICAgICB0aHJvdyBUeXBlRXJyb3IoXCIub25ueC5BdHRyaWJ1dGVQcm90by50ZW5zb3JzOiBvYmplY3QgZXhwZWN0ZWRcIik7XG4gICAgICAgICAgICAgICAgICAgIG1lc3NhZ2UudGVuc29yc1tpXSA9ICRyb290Lm9ubnguVGVuc29yUHJvdG8uZnJvbU9iamVjdChvYmplY3QudGVuc29yc1tpXSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG9iamVjdC5ncmFwaHMpIHtcbiAgICAgICAgICAgICAgICBpZiAoIUFycmF5LmlzQXJyYXkob2JqZWN0LmdyYXBocykpXG4gICAgICAgICAgICAgICAgICAgIHRocm93IFR5cGVFcnJvcihcIi5vbm54LkF0dHJpYnV0ZVByb3RvLmdyYXBoczogYXJyYXkgZXhwZWN0ZWRcIik7XG4gICAgICAgICAgICAgICAgbWVzc2FnZS5ncmFwaHMgPSBbXTtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG9iamVjdC5ncmFwaHMubGVuZ3RoOyArK2kpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBvYmplY3QuZ3JhcGhzW2ldICE9PSBcIm9iamVjdFwiKVxuICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3cgVHlwZUVycm9yKFwiLm9ubnguQXR0cmlidXRlUHJvdG8uZ3JhcGhzOiBvYmplY3QgZXhwZWN0ZWRcIik7XG4gICAgICAgICAgICAgICAgICAgIG1lc3NhZ2UuZ3JhcGhzW2ldID0gJHJvb3Qub25ueC5HcmFwaFByb3RvLmZyb21PYmplY3Qob2JqZWN0LmdyYXBoc1tpXSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIG1lc3NhZ2U7XG4gICAgICAgIH07XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIENyZWF0ZXMgYSBwbGFpbiBvYmplY3QgZnJvbSBhbiBBdHRyaWJ1dGVQcm90byBtZXNzYWdlLiBBbHNvIGNvbnZlcnRzIHZhbHVlcyB0byBvdGhlciB0eXBlcyBpZiBzcGVjaWZpZWQuXG4gICAgICAgICAqIEBmdW5jdGlvbiB0b09iamVjdFxuICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueC5BdHRyaWJ1dGVQcm90b1xuICAgICAgICAgKiBAc3RhdGljXG4gICAgICAgICAqIEBwYXJhbSB7b25ueC5BdHRyaWJ1dGVQcm90b30gbWVzc2FnZSBBdHRyaWJ1dGVQcm90b1xuICAgICAgICAgKiBAcGFyYW0geyRwcm90b2J1Zi5JQ29udmVyc2lvbk9wdGlvbnN9IFtvcHRpb25zXSBDb252ZXJzaW9uIG9wdGlvbnNcbiAgICAgICAgICogQHJldHVybnMge09iamVjdC48c3RyaW5nLCo+fSBQbGFpbiBvYmplY3RcbiAgICAgICAgICovXG4gICAgICAgIEF0dHJpYnV0ZVByb3RvLnRvT2JqZWN0ID0gZnVuY3Rpb24gdG9PYmplY3QobWVzc2FnZSwgb3B0aW9ucykge1xuICAgICAgICAgICAgaWYgKCFvcHRpb25zKVxuICAgICAgICAgICAgICAgIG9wdGlvbnMgPSB7fTtcbiAgICAgICAgICAgIHZhciBvYmplY3QgPSB7fTtcbiAgICAgICAgICAgIGlmIChvcHRpb25zLmFycmF5cyB8fCBvcHRpb25zLmRlZmF1bHRzKSB7XG4gICAgICAgICAgICAgICAgb2JqZWN0LmZsb2F0cyA9IFtdO1xuICAgICAgICAgICAgICAgIG9iamVjdC5pbnRzID0gW107XG4gICAgICAgICAgICAgICAgb2JqZWN0LnN0cmluZ3MgPSBbXTtcbiAgICAgICAgICAgICAgICBvYmplY3QudGVuc29ycyA9IFtdO1xuICAgICAgICAgICAgICAgIG9iamVjdC5ncmFwaHMgPSBbXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChvcHRpb25zLmRlZmF1bHRzKSB7XG4gICAgICAgICAgICAgICAgb2JqZWN0Lm5hbWUgPSBcIlwiO1xuICAgICAgICAgICAgICAgIG9iamVjdC5mID0gMDtcbiAgICAgICAgICAgICAgICBpZiAoJHV0aWwuTG9uZykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgbG9uZyA9IG5ldyAkdXRpbC5Mb25nKDAsIDAsIGZhbHNlKTtcbiAgICAgICAgICAgICAgICAgICAgb2JqZWN0LmkgPSBvcHRpb25zLmxvbmdzID09PSBTdHJpbmcgPyBsb25nLnRvU3RyaW5nKCkgOiBvcHRpb25zLmxvbmdzID09PSBOdW1iZXIgPyBsb25nLnRvTnVtYmVyKCkgOiBsb25nO1xuICAgICAgICAgICAgICAgIH0gZWxzZVxuICAgICAgICAgICAgICAgICAgICBvYmplY3QuaSA9IG9wdGlvbnMubG9uZ3MgPT09IFN0cmluZyA/IFwiMFwiIDogMDtcbiAgICAgICAgICAgICAgICBpZiAob3B0aW9ucy5ieXRlcyA9PT0gU3RyaW5nKVxuICAgICAgICAgICAgICAgICAgICBvYmplY3QucyA9IFwiXCI7XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIG9iamVjdC5zID0gW107XG4gICAgICAgICAgICAgICAgICAgIGlmIChvcHRpb25zLmJ5dGVzICE9PSBBcnJheSlcbiAgICAgICAgICAgICAgICAgICAgICAgIG9iamVjdC5zID0gJHV0aWwubmV3QnVmZmVyKG9iamVjdC5zKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgb2JqZWN0LnQgPSBudWxsO1xuICAgICAgICAgICAgICAgIG9iamVjdC5nID0gbnVsbDtcbiAgICAgICAgICAgICAgICBvYmplY3QuZG9jU3RyaW5nID0gXCJcIjtcbiAgICAgICAgICAgICAgICBvYmplY3QudHlwZSA9IG9wdGlvbnMuZW51bXMgPT09IFN0cmluZyA/IFwiVU5ERUZJTkVEXCIgOiAwO1xuICAgICAgICAgICAgICAgIG9iamVjdC5yZWZBdHRyTmFtZSA9IFwiXCI7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAobWVzc2FnZS5uYW1lICE9IG51bGwgJiYgbWVzc2FnZS5oYXNPd25Qcm9wZXJ0eShcIm5hbWVcIikpXG4gICAgICAgICAgICAgICAgb2JqZWN0Lm5hbWUgPSBtZXNzYWdlLm5hbWU7XG4gICAgICAgICAgICBpZiAobWVzc2FnZS5mICE9IG51bGwgJiYgbWVzc2FnZS5oYXNPd25Qcm9wZXJ0eShcImZcIikpXG4gICAgICAgICAgICAgICAgb2JqZWN0LmYgPSBvcHRpb25zLmpzb24gJiYgIWlzRmluaXRlKG1lc3NhZ2UuZikgPyBTdHJpbmcobWVzc2FnZS5mKSA6IG1lc3NhZ2UuZjtcbiAgICAgICAgICAgIGlmIChtZXNzYWdlLmkgIT0gbnVsbCAmJiBtZXNzYWdlLmhhc093blByb3BlcnR5KFwiaVwiKSlcbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIG1lc3NhZ2UuaSA9PT0gXCJudW1iZXJcIilcbiAgICAgICAgICAgICAgICAgICAgb2JqZWN0LmkgPSBvcHRpb25zLmxvbmdzID09PSBTdHJpbmcgPyBTdHJpbmcobWVzc2FnZS5pKSA6IG1lc3NhZ2UuaTtcbiAgICAgICAgICAgICAgICBlbHNlXG4gICAgICAgICAgICAgICAgICAgIG9iamVjdC5pID0gb3B0aW9ucy5sb25ncyA9PT0gU3RyaW5nID8gJHV0aWwuTG9uZy5wcm90b3R5cGUudG9TdHJpbmcuY2FsbChtZXNzYWdlLmkpIDogb3B0aW9ucy5sb25ncyA9PT0gTnVtYmVyID8gbmV3ICR1dGlsLkxvbmdCaXRzKG1lc3NhZ2UuaS5sb3cgPj4+IDAsIG1lc3NhZ2UuaS5oaWdoID4+PiAwKS50b051bWJlcigpIDogbWVzc2FnZS5pO1xuICAgICAgICAgICAgaWYgKG1lc3NhZ2UucyAhPSBudWxsICYmIG1lc3NhZ2UuaGFzT3duUHJvcGVydHkoXCJzXCIpKVxuICAgICAgICAgICAgICAgIG9iamVjdC5zID0gb3B0aW9ucy5ieXRlcyA9PT0gU3RyaW5nID8gJHV0aWwuYmFzZTY0LmVuY29kZShtZXNzYWdlLnMsIDAsIG1lc3NhZ2Uucy5sZW5ndGgpIDogb3B0aW9ucy5ieXRlcyA9PT0gQXJyYXkgPyBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChtZXNzYWdlLnMpIDogbWVzc2FnZS5zO1xuICAgICAgICAgICAgaWYgKG1lc3NhZ2UudCAhPSBudWxsICYmIG1lc3NhZ2UuaGFzT3duUHJvcGVydHkoXCJ0XCIpKVxuICAgICAgICAgICAgICAgIG9iamVjdC50ID0gJHJvb3Qub25ueC5UZW5zb3JQcm90by50b09iamVjdChtZXNzYWdlLnQsIG9wdGlvbnMpO1xuICAgICAgICAgICAgaWYgKG1lc3NhZ2UuZyAhPSBudWxsICYmIG1lc3NhZ2UuaGFzT3duUHJvcGVydHkoXCJnXCIpKVxuICAgICAgICAgICAgICAgIG9iamVjdC5nID0gJHJvb3Qub25ueC5HcmFwaFByb3RvLnRvT2JqZWN0KG1lc3NhZ2UuZywgb3B0aW9ucyk7XG4gICAgICAgICAgICBpZiAobWVzc2FnZS5mbG9hdHMgJiYgbWVzc2FnZS5mbG9hdHMubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgb2JqZWN0LmZsb2F0cyA9IFtdO1xuICAgICAgICAgICAgICAgIGZvciAodmFyIGogPSAwOyBqIDwgbWVzc2FnZS5mbG9hdHMubGVuZ3RoOyArK2opXG4gICAgICAgICAgICAgICAgICAgIG9iamVjdC5mbG9hdHNbal0gPSBvcHRpb25zLmpzb24gJiYgIWlzRmluaXRlKG1lc3NhZ2UuZmxvYXRzW2pdKSA/IFN0cmluZyhtZXNzYWdlLmZsb2F0c1tqXSkgOiBtZXNzYWdlLmZsb2F0c1tqXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChtZXNzYWdlLmludHMgJiYgbWVzc2FnZS5pbnRzLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgIG9iamVjdC5pbnRzID0gW107XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaiA9IDA7IGogPCBtZXNzYWdlLmludHMubGVuZ3RoOyArK2opXG4gICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgbWVzc2FnZS5pbnRzW2pdID09PSBcIm51bWJlclwiKVxuICAgICAgICAgICAgICAgICAgICAgICAgb2JqZWN0LmludHNbal0gPSBvcHRpb25zLmxvbmdzID09PSBTdHJpbmcgPyBTdHJpbmcobWVzc2FnZS5pbnRzW2pdKSA6IG1lc3NhZ2UuaW50c1tqXTtcbiAgICAgICAgICAgICAgICAgICAgZWxzZVxuICAgICAgICAgICAgICAgICAgICAgICAgb2JqZWN0LmludHNbal0gPSBvcHRpb25zLmxvbmdzID09PSBTdHJpbmcgPyAkdXRpbC5Mb25nLnByb3RvdHlwZS50b1N0cmluZy5jYWxsKG1lc3NhZ2UuaW50c1tqXSkgOiBvcHRpb25zLmxvbmdzID09PSBOdW1iZXIgPyBuZXcgJHV0aWwuTG9uZ0JpdHMobWVzc2FnZS5pbnRzW2pdLmxvdyA+Pj4gMCwgbWVzc2FnZS5pbnRzW2pdLmhpZ2ggPj4+IDApLnRvTnVtYmVyKCkgOiBtZXNzYWdlLmludHNbal07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAobWVzc2FnZS5zdHJpbmdzICYmIG1lc3NhZ2Uuc3RyaW5ncy5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICBvYmplY3Quc3RyaW5ncyA9IFtdO1xuICAgICAgICAgICAgICAgIGZvciAodmFyIGogPSAwOyBqIDwgbWVzc2FnZS5zdHJpbmdzLmxlbmd0aDsgKytqKVxuICAgICAgICAgICAgICAgICAgICBvYmplY3Quc3RyaW5nc1tqXSA9IG9wdGlvbnMuYnl0ZXMgPT09IFN0cmluZyA/ICR1dGlsLmJhc2U2NC5lbmNvZGUobWVzc2FnZS5zdHJpbmdzW2pdLCAwLCBtZXNzYWdlLnN0cmluZ3Nbal0ubGVuZ3RoKSA6IG9wdGlvbnMuYnl0ZXMgPT09IEFycmF5ID8gQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwobWVzc2FnZS5zdHJpbmdzW2pdKSA6IG1lc3NhZ2Uuc3RyaW5nc1tqXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChtZXNzYWdlLnRlbnNvcnMgJiYgbWVzc2FnZS50ZW5zb3JzLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgIG9iamVjdC50ZW5zb3JzID0gW107XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaiA9IDA7IGogPCBtZXNzYWdlLnRlbnNvcnMubGVuZ3RoOyArK2opXG4gICAgICAgICAgICAgICAgICAgIG9iamVjdC50ZW5zb3JzW2pdID0gJHJvb3Qub25ueC5UZW5zb3JQcm90by50b09iamVjdChtZXNzYWdlLnRlbnNvcnNbal0sIG9wdGlvbnMpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG1lc3NhZ2UuZ3JhcGhzICYmIG1lc3NhZ2UuZ3JhcGhzLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgIG9iamVjdC5ncmFwaHMgPSBbXTtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBqID0gMDsgaiA8IG1lc3NhZ2UuZ3JhcGhzLmxlbmd0aDsgKytqKVxuICAgICAgICAgICAgICAgICAgICBvYmplY3QuZ3JhcGhzW2pdID0gJHJvb3Qub25ueC5HcmFwaFByb3RvLnRvT2JqZWN0KG1lc3NhZ2UuZ3JhcGhzW2pdLCBvcHRpb25zKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChtZXNzYWdlLmRvY1N0cmluZyAhPSBudWxsICYmIG1lc3NhZ2UuaGFzT3duUHJvcGVydHkoXCJkb2NTdHJpbmdcIikpXG4gICAgICAgICAgICAgICAgb2JqZWN0LmRvY1N0cmluZyA9IG1lc3NhZ2UuZG9jU3RyaW5nO1xuICAgICAgICAgICAgaWYgKG1lc3NhZ2UudHlwZSAhPSBudWxsICYmIG1lc3NhZ2UuaGFzT3duUHJvcGVydHkoXCJ0eXBlXCIpKVxuICAgICAgICAgICAgICAgIG9iamVjdC50eXBlID0gb3B0aW9ucy5lbnVtcyA9PT0gU3RyaW5nID8gJHJvb3Qub25ueC5BdHRyaWJ1dGVQcm90by5BdHRyaWJ1dGVUeXBlW21lc3NhZ2UudHlwZV0gOiBtZXNzYWdlLnR5cGU7XG4gICAgICAgICAgICBpZiAobWVzc2FnZS5yZWZBdHRyTmFtZSAhPSBudWxsICYmIG1lc3NhZ2UuaGFzT3duUHJvcGVydHkoXCJyZWZBdHRyTmFtZVwiKSlcbiAgICAgICAgICAgICAgICBvYmplY3QucmVmQXR0ck5hbWUgPSBtZXNzYWdlLnJlZkF0dHJOYW1lO1xuICAgICAgICAgICAgcmV0dXJuIG9iamVjdDtcbiAgICAgICAgfTtcblxuICAgICAgICAvKipcbiAgICAgICAgICogQ29udmVydHMgdGhpcyBBdHRyaWJ1dGVQcm90byB0byBKU09OLlxuICAgICAgICAgKiBAZnVuY3Rpb24gdG9KU09OXG4gICAgICAgICAqIEBtZW1iZXJvZiBvbm54LkF0dHJpYnV0ZVByb3RvXG4gICAgICAgICAqIEBpbnN0YW5jZVxuICAgICAgICAgKiBAcmV0dXJucyB7T2JqZWN0LjxzdHJpbmcsKj59IEpTT04gb2JqZWN0XG4gICAgICAgICAqL1xuICAgICAgICBBdHRyaWJ1dGVQcm90by5wcm90b3R5cGUudG9KU09OID0gZnVuY3Rpb24gdG9KU09OKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuY29uc3RydWN0b3IudG9PYmplY3QodGhpcywgJHByb3RvYnVmLnV0aWwudG9KU09OT3B0aW9ucyk7XG4gICAgICAgIH07XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEF0dHJpYnV0ZVR5cGUgZW51bS5cbiAgICAgICAgICogQG5hbWUgb25ueC5BdHRyaWJ1dGVQcm90by5BdHRyaWJ1dGVUeXBlXG4gICAgICAgICAqIEBlbnVtIHtzdHJpbmd9XG4gICAgICAgICAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBVTkRFRklORUQ9MCBVTkRFRklORUQgdmFsdWVcbiAgICAgICAgICogQHByb3BlcnR5IHtudW1iZXJ9IEZMT0FUPTEgRkxPQVQgdmFsdWVcbiAgICAgICAgICogQHByb3BlcnR5IHtudW1iZXJ9IElOVD0yIElOVCB2YWx1ZVxuICAgICAgICAgKiBAcHJvcGVydHkge251bWJlcn0gU1RSSU5HPTMgU1RSSU5HIHZhbHVlXG4gICAgICAgICAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBURU5TT1I9NCBURU5TT1IgdmFsdWVcbiAgICAgICAgICogQHByb3BlcnR5IHtudW1iZXJ9IEdSQVBIPTUgR1JBUEggdmFsdWVcbiAgICAgICAgICogQHByb3BlcnR5IHtudW1iZXJ9IEZMT0FUUz02IEZMT0FUUyB2YWx1ZVxuICAgICAgICAgKiBAcHJvcGVydHkge251bWJlcn0gSU5UUz03IElOVFMgdmFsdWVcbiAgICAgICAgICogQHByb3BlcnR5IHtudW1iZXJ9IFNUUklOR1M9OCBTVFJJTkdTIHZhbHVlXG4gICAgICAgICAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBURU5TT1JTPTkgVEVOU09SUyB2YWx1ZVxuICAgICAgICAgKiBAcHJvcGVydHkge251bWJlcn0gR1JBUEhTPTEwIEdSQVBIUyB2YWx1ZVxuICAgICAgICAgKi9cbiAgICAgICAgQXR0cmlidXRlUHJvdG8uQXR0cmlidXRlVHlwZSA9IChmdW5jdGlvbigpIHtcbiAgICAgICAgICAgIHZhciB2YWx1ZXNCeUlkID0ge30sIHZhbHVlcyA9IE9iamVjdC5jcmVhdGUodmFsdWVzQnlJZCk7XG4gICAgICAgICAgICB2YWx1ZXNbdmFsdWVzQnlJZFswXSA9IFwiVU5ERUZJTkVEXCJdID0gMDtcbiAgICAgICAgICAgIHZhbHVlc1t2YWx1ZXNCeUlkWzFdID0gXCJGTE9BVFwiXSA9IDE7XG4gICAgICAgICAgICB2YWx1ZXNbdmFsdWVzQnlJZFsyXSA9IFwiSU5UXCJdID0gMjtcbiAgICAgICAgICAgIHZhbHVlc1t2YWx1ZXNCeUlkWzNdID0gXCJTVFJJTkdcIl0gPSAzO1xuICAgICAgICAgICAgdmFsdWVzW3ZhbHVlc0J5SWRbNF0gPSBcIlRFTlNPUlwiXSA9IDQ7XG4gICAgICAgICAgICB2YWx1ZXNbdmFsdWVzQnlJZFs1XSA9IFwiR1JBUEhcIl0gPSA1O1xuICAgICAgICAgICAgdmFsdWVzW3ZhbHVlc0J5SWRbNl0gPSBcIkZMT0FUU1wiXSA9IDY7XG4gICAgICAgICAgICB2YWx1ZXNbdmFsdWVzQnlJZFs3XSA9IFwiSU5UU1wiXSA9IDc7XG4gICAgICAgICAgICB2YWx1ZXNbdmFsdWVzQnlJZFs4XSA9IFwiU1RSSU5HU1wiXSA9IDg7XG4gICAgICAgICAgICB2YWx1ZXNbdmFsdWVzQnlJZFs5XSA9IFwiVEVOU09SU1wiXSA9IDk7XG4gICAgICAgICAgICB2YWx1ZXNbdmFsdWVzQnlJZFsxMF0gPSBcIkdSQVBIU1wiXSA9IDEwO1xuICAgICAgICAgICAgcmV0dXJuIHZhbHVlcztcbiAgICAgICAgfSkoKTtcblxuICAgICAgICByZXR1cm4gQXR0cmlidXRlUHJvdG87XG4gICAgfSkoKTtcblxuICAgIG9ubnguVmFsdWVJbmZvUHJvdG8gPSAoZnVuY3Rpb24oKSB7XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIFByb3BlcnRpZXMgb2YgYSBWYWx1ZUluZm9Qcm90by5cbiAgICAgICAgICogQG1lbWJlcm9mIG9ubnhcbiAgICAgICAgICogQGludGVyZmFjZSBJVmFsdWVJbmZvUHJvdG9cbiAgICAgICAgICogQHByb3BlcnR5IHtzdHJpbmd8bnVsbH0gW25hbWVdIFZhbHVlSW5mb1Byb3RvIG5hbWVcbiAgICAgICAgICogQHByb3BlcnR5IHtvbm54LklUeXBlUHJvdG98bnVsbH0gW3R5cGVdIFZhbHVlSW5mb1Byb3RvIHR5cGVcbiAgICAgICAgICogQHByb3BlcnR5IHtzdHJpbmd8bnVsbH0gW2RvY1N0cmluZ10gVmFsdWVJbmZvUHJvdG8gZG9jU3RyaW5nXG4gICAgICAgICAqL1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBDb25zdHJ1Y3RzIGEgbmV3IFZhbHVlSW5mb1Byb3RvLlxuICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueFxuICAgICAgICAgKiBAY2xhc3NkZXNjIFJlcHJlc2VudHMgYSBWYWx1ZUluZm9Qcm90by5cbiAgICAgICAgICogQGltcGxlbWVudHMgSVZhbHVlSW5mb1Byb3RvXG4gICAgICAgICAqIEBjb25zdHJ1Y3RvclxuICAgICAgICAgKiBAcGFyYW0ge29ubnguSVZhbHVlSW5mb1Byb3RvPX0gW3Byb3BlcnRpZXNdIFByb3BlcnRpZXMgdG8gc2V0XG4gICAgICAgICAqL1xuICAgICAgICBmdW5jdGlvbiBWYWx1ZUluZm9Qcm90byhwcm9wZXJ0aWVzKSB7XG4gICAgICAgICAgICBpZiAocHJvcGVydGllcylcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBrZXlzID0gT2JqZWN0LmtleXMocHJvcGVydGllcyksIGkgPSAwOyBpIDwga2V5cy5sZW5ndGg7ICsraSlcbiAgICAgICAgICAgICAgICAgICAgaWYgKHByb3BlcnRpZXNba2V5c1tpXV0gIT0gbnVsbClcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXNba2V5c1tpXV0gPSBwcm9wZXJ0aWVzW2tleXNbaV1dO1xuICAgICAgICB9XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIFZhbHVlSW5mb1Byb3RvIG5hbWUuXG4gICAgICAgICAqIEBtZW1iZXIge3N0cmluZ30gbmFtZVxuICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueC5WYWx1ZUluZm9Qcm90b1xuICAgICAgICAgKiBAaW5zdGFuY2VcbiAgICAgICAgICovXG4gICAgICAgIFZhbHVlSW5mb1Byb3RvLnByb3RvdHlwZS5uYW1lID0gXCJcIjtcblxuICAgICAgICAvKipcbiAgICAgICAgICogVmFsdWVJbmZvUHJvdG8gdHlwZS5cbiAgICAgICAgICogQG1lbWJlciB7b25ueC5JVHlwZVByb3RvfG51bGx8dW5kZWZpbmVkfSB0eXBlXG4gICAgICAgICAqIEBtZW1iZXJvZiBvbm54LlZhbHVlSW5mb1Byb3RvXG4gICAgICAgICAqIEBpbnN0YW5jZVxuICAgICAgICAgKi9cbiAgICAgICAgVmFsdWVJbmZvUHJvdG8ucHJvdG90eXBlLnR5cGUgPSBudWxsO1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBWYWx1ZUluZm9Qcm90byBkb2NTdHJpbmcuXG4gICAgICAgICAqIEBtZW1iZXIge3N0cmluZ30gZG9jU3RyaW5nXG4gICAgICAgICAqIEBtZW1iZXJvZiBvbm54LlZhbHVlSW5mb1Byb3RvXG4gICAgICAgICAqIEBpbnN0YW5jZVxuICAgICAgICAgKi9cbiAgICAgICAgVmFsdWVJbmZvUHJvdG8ucHJvdG90eXBlLmRvY1N0cmluZyA9IFwiXCI7XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIENyZWF0ZXMgYSBuZXcgVmFsdWVJbmZvUHJvdG8gaW5zdGFuY2UgdXNpbmcgdGhlIHNwZWNpZmllZCBwcm9wZXJ0aWVzLlxuICAgICAgICAgKiBAZnVuY3Rpb24gY3JlYXRlXG4gICAgICAgICAqIEBtZW1iZXJvZiBvbm54LlZhbHVlSW5mb1Byb3RvXG4gICAgICAgICAqIEBzdGF0aWNcbiAgICAgICAgICogQHBhcmFtIHtvbm54LklWYWx1ZUluZm9Qcm90bz19IFtwcm9wZXJ0aWVzXSBQcm9wZXJ0aWVzIHRvIHNldFxuICAgICAgICAgKiBAcmV0dXJucyB7b25ueC5WYWx1ZUluZm9Qcm90b30gVmFsdWVJbmZvUHJvdG8gaW5zdGFuY2VcbiAgICAgICAgICovXG4gICAgICAgIFZhbHVlSW5mb1Byb3RvLmNyZWF0ZSA9IGZ1bmN0aW9uIGNyZWF0ZShwcm9wZXJ0aWVzKSB7XG4gICAgICAgICAgICByZXR1cm4gbmV3IFZhbHVlSW5mb1Byb3RvKHByb3BlcnRpZXMpO1xuICAgICAgICB9O1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBFbmNvZGVzIHRoZSBzcGVjaWZpZWQgVmFsdWVJbmZvUHJvdG8gbWVzc2FnZS4gRG9lcyBub3QgaW1wbGljaXRseSB7QGxpbmsgb25ueC5WYWx1ZUluZm9Qcm90by52ZXJpZnl8dmVyaWZ5fSBtZXNzYWdlcy5cbiAgICAgICAgICogQGZ1bmN0aW9uIGVuY29kZVxuICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueC5WYWx1ZUluZm9Qcm90b1xuICAgICAgICAgKiBAc3RhdGljXG4gICAgICAgICAqIEBwYXJhbSB7b25ueC5JVmFsdWVJbmZvUHJvdG99IG1lc3NhZ2UgVmFsdWVJbmZvUHJvdG8gbWVzc2FnZSBvciBwbGFpbiBvYmplY3QgdG8gZW5jb2RlXG4gICAgICAgICAqIEBwYXJhbSB7JHByb3RvYnVmLldyaXRlcn0gW3dyaXRlcl0gV3JpdGVyIHRvIGVuY29kZSB0b1xuICAgICAgICAgKiBAcmV0dXJucyB7JHByb3RvYnVmLldyaXRlcn0gV3JpdGVyXG4gICAgICAgICAqL1xuICAgICAgICBWYWx1ZUluZm9Qcm90by5lbmNvZGUgPSBmdW5jdGlvbiBlbmNvZGUobWVzc2FnZSwgd3JpdGVyKSB7XG4gICAgICAgICAgICBpZiAoIXdyaXRlcilcbiAgICAgICAgICAgICAgICB3cml0ZXIgPSAkV3JpdGVyLmNyZWF0ZSgpO1xuICAgICAgICAgICAgaWYgKG1lc3NhZ2UubmFtZSAhPSBudWxsICYmIG1lc3NhZ2UuaGFzT3duUHJvcGVydHkoXCJuYW1lXCIpKVxuICAgICAgICAgICAgICAgIHdyaXRlci51aW50MzIoLyogaWQgMSwgd2lyZVR5cGUgMiA9Ki8xMCkuc3RyaW5nKG1lc3NhZ2UubmFtZSk7XG4gICAgICAgICAgICBpZiAobWVzc2FnZS50eXBlICE9IG51bGwgJiYgbWVzc2FnZS5oYXNPd25Qcm9wZXJ0eShcInR5cGVcIikpXG4gICAgICAgICAgICAgICAgJHJvb3Qub25ueC5UeXBlUHJvdG8uZW5jb2RlKG1lc3NhZ2UudHlwZSwgd3JpdGVyLnVpbnQzMigvKiBpZCAyLCB3aXJlVHlwZSAyID0qLzE4KS5mb3JrKCkpLmxkZWxpbSgpO1xuICAgICAgICAgICAgaWYgKG1lc3NhZ2UuZG9jU3RyaW5nICE9IG51bGwgJiYgbWVzc2FnZS5oYXNPd25Qcm9wZXJ0eShcImRvY1N0cmluZ1wiKSlcbiAgICAgICAgICAgICAgICB3cml0ZXIudWludDMyKC8qIGlkIDMsIHdpcmVUeXBlIDIgPSovMjYpLnN0cmluZyhtZXNzYWdlLmRvY1N0cmluZyk7XG4gICAgICAgICAgICByZXR1cm4gd3JpdGVyO1xuICAgICAgICB9O1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBFbmNvZGVzIHRoZSBzcGVjaWZpZWQgVmFsdWVJbmZvUHJvdG8gbWVzc2FnZSwgbGVuZ3RoIGRlbGltaXRlZC4gRG9lcyBub3QgaW1wbGljaXRseSB7QGxpbmsgb25ueC5WYWx1ZUluZm9Qcm90by52ZXJpZnl8dmVyaWZ5fSBtZXNzYWdlcy5cbiAgICAgICAgICogQGZ1bmN0aW9uIGVuY29kZURlbGltaXRlZFxuICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueC5WYWx1ZUluZm9Qcm90b1xuICAgICAgICAgKiBAc3RhdGljXG4gICAgICAgICAqIEBwYXJhbSB7b25ueC5JVmFsdWVJbmZvUHJvdG99IG1lc3NhZ2UgVmFsdWVJbmZvUHJvdG8gbWVzc2FnZSBvciBwbGFpbiBvYmplY3QgdG8gZW5jb2RlXG4gICAgICAgICAqIEBwYXJhbSB7JHByb3RvYnVmLldyaXRlcn0gW3dyaXRlcl0gV3JpdGVyIHRvIGVuY29kZSB0b1xuICAgICAgICAgKiBAcmV0dXJucyB7JHByb3RvYnVmLldyaXRlcn0gV3JpdGVyXG4gICAgICAgICAqL1xuICAgICAgICBWYWx1ZUluZm9Qcm90by5lbmNvZGVEZWxpbWl0ZWQgPSBmdW5jdGlvbiBlbmNvZGVEZWxpbWl0ZWQobWVzc2FnZSwgd3JpdGVyKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5lbmNvZGUobWVzc2FnZSwgd3JpdGVyKS5sZGVsaW0oKTtcbiAgICAgICAgfTtcblxuICAgICAgICAvKipcbiAgICAgICAgICogRGVjb2RlcyBhIFZhbHVlSW5mb1Byb3RvIG1lc3NhZ2UgZnJvbSB0aGUgc3BlY2lmaWVkIHJlYWRlciBvciBidWZmZXIuXG4gICAgICAgICAqIEBmdW5jdGlvbiBkZWNvZGVcbiAgICAgICAgICogQG1lbWJlcm9mIG9ubnguVmFsdWVJbmZvUHJvdG9cbiAgICAgICAgICogQHN0YXRpY1xuICAgICAgICAgKiBAcGFyYW0geyRwcm90b2J1Zi5SZWFkZXJ8VWludDhBcnJheX0gcmVhZGVyIFJlYWRlciBvciBidWZmZXIgdG8gZGVjb2RlIGZyb21cbiAgICAgICAgICogQHBhcmFtIHtudW1iZXJ9IFtsZW5ndGhdIE1lc3NhZ2UgbGVuZ3RoIGlmIGtub3duIGJlZm9yZWhhbmRcbiAgICAgICAgICogQHJldHVybnMge29ubnguVmFsdWVJbmZvUHJvdG99IFZhbHVlSW5mb1Byb3RvXG4gICAgICAgICAqIEB0aHJvd3Mge0Vycm9yfSBJZiB0aGUgcGF5bG9hZCBpcyBub3QgYSByZWFkZXIgb3IgdmFsaWQgYnVmZmVyXG4gICAgICAgICAqIEB0aHJvd3MgeyRwcm90b2J1Zi51dGlsLlByb3RvY29sRXJyb3J9IElmIHJlcXVpcmVkIGZpZWxkcyBhcmUgbWlzc2luZ1xuICAgICAgICAgKi9cbiAgICAgICAgVmFsdWVJbmZvUHJvdG8uZGVjb2RlID0gZnVuY3Rpb24gZGVjb2RlKHJlYWRlciwgbGVuZ3RoKSB7XG4gICAgICAgICAgICBpZiAoIShyZWFkZXIgaW5zdGFuY2VvZiAkUmVhZGVyKSlcbiAgICAgICAgICAgICAgICByZWFkZXIgPSAkUmVhZGVyLmNyZWF0ZShyZWFkZXIpO1xuICAgICAgICAgICAgdmFyIGVuZCA9IGxlbmd0aCA9PT0gdW5kZWZpbmVkID8gcmVhZGVyLmxlbiA6IHJlYWRlci5wb3MgKyBsZW5ndGgsIG1lc3NhZ2UgPSBuZXcgJHJvb3Qub25ueC5WYWx1ZUluZm9Qcm90bygpO1xuICAgICAgICAgICAgd2hpbGUgKHJlYWRlci5wb3MgPCBlbmQpIHtcbiAgICAgICAgICAgICAgICB2YXIgdGFnID0gcmVhZGVyLnVpbnQzMigpO1xuICAgICAgICAgICAgICAgIHN3aXRjaCAodGFnID4+PiAzKSB7XG4gICAgICAgICAgICAgICAgY2FzZSAxOlxuICAgICAgICAgICAgICAgICAgICBtZXNzYWdlLm5hbWUgPSByZWFkZXIuc3RyaW5nKCk7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgMjpcbiAgICAgICAgICAgICAgICAgICAgbWVzc2FnZS50eXBlID0gJHJvb3Qub25ueC5UeXBlUHJvdG8uZGVjb2RlKHJlYWRlciwgcmVhZGVyLnVpbnQzMigpKTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSAzOlxuICAgICAgICAgICAgICAgICAgICBtZXNzYWdlLmRvY1N0cmluZyA9IHJlYWRlci5zdHJpbmcoKTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICAgICAgcmVhZGVyLnNraXBUeXBlKHRhZyAmIDcpO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gbWVzc2FnZTtcbiAgICAgICAgfTtcblxuICAgICAgICAvKipcbiAgICAgICAgICogRGVjb2RlcyBhIFZhbHVlSW5mb1Byb3RvIG1lc3NhZ2UgZnJvbSB0aGUgc3BlY2lmaWVkIHJlYWRlciBvciBidWZmZXIsIGxlbmd0aCBkZWxpbWl0ZWQuXG4gICAgICAgICAqIEBmdW5jdGlvbiBkZWNvZGVEZWxpbWl0ZWRcbiAgICAgICAgICogQG1lbWJlcm9mIG9ubnguVmFsdWVJbmZvUHJvdG9cbiAgICAgICAgICogQHN0YXRpY1xuICAgICAgICAgKiBAcGFyYW0geyRwcm90b2J1Zi5SZWFkZXJ8VWludDhBcnJheX0gcmVhZGVyIFJlYWRlciBvciBidWZmZXIgdG8gZGVjb2RlIGZyb21cbiAgICAgICAgICogQHJldHVybnMge29ubnguVmFsdWVJbmZvUHJvdG99IFZhbHVlSW5mb1Byb3RvXG4gICAgICAgICAqIEB0aHJvd3Mge0Vycm9yfSBJZiB0aGUgcGF5bG9hZCBpcyBub3QgYSByZWFkZXIgb3IgdmFsaWQgYnVmZmVyXG4gICAgICAgICAqIEB0aHJvd3MgeyRwcm90b2J1Zi51dGlsLlByb3RvY29sRXJyb3J9IElmIHJlcXVpcmVkIGZpZWxkcyBhcmUgbWlzc2luZ1xuICAgICAgICAgKi9cbiAgICAgICAgVmFsdWVJbmZvUHJvdG8uZGVjb2RlRGVsaW1pdGVkID0gZnVuY3Rpb24gZGVjb2RlRGVsaW1pdGVkKHJlYWRlcikge1xuICAgICAgICAgICAgaWYgKCEocmVhZGVyIGluc3RhbmNlb2YgJFJlYWRlcikpXG4gICAgICAgICAgICAgICAgcmVhZGVyID0gbmV3ICRSZWFkZXIocmVhZGVyKTtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmRlY29kZShyZWFkZXIsIHJlYWRlci51aW50MzIoKSk7XG4gICAgICAgIH07XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIFZlcmlmaWVzIGEgVmFsdWVJbmZvUHJvdG8gbWVzc2FnZS5cbiAgICAgICAgICogQGZ1bmN0aW9uIHZlcmlmeVxuICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueC5WYWx1ZUluZm9Qcm90b1xuICAgICAgICAgKiBAc3RhdGljXG4gICAgICAgICAqIEBwYXJhbSB7T2JqZWN0LjxzdHJpbmcsKj59IG1lc3NhZ2UgUGxhaW4gb2JqZWN0IHRvIHZlcmlmeVxuICAgICAgICAgKiBAcmV0dXJucyB7c3RyaW5nfG51bGx9IGBudWxsYCBpZiB2YWxpZCwgb3RoZXJ3aXNlIHRoZSByZWFzb24gd2h5IGl0IGlzIG5vdFxuICAgICAgICAgKi9cbiAgICAgICAgVmFsdWVJbmZvUHJvdG8udmVyaWZ5ID0gZnVuY3Rpb24gdmVyaWZ5KG1lc3NhZ2UpIHtcbiAgICAgICAgICAgIGlmICh0eXBlb2YgbWVzc2FnZSAhPT0gXCJvYmplY3RcIiB8fCBtZXNzYWdlID09PSBudWxsKVxuICAgICAgICAgICAgICAgIHJldHVybiBcIm9iamVjdCBleHBlY3RlZFwiO1xuICAgICAgICAgICAgaWYgKG1lc3NhZ2UubmFtZSAhPSBudWxsICYmIG1lc3NhZ2UuaGFzT3duUHJvcGVydHkoXCJuYW1lXCIpKVxuICAgICAgICAgICAgICAgIGlmICghJHV0aWwuaXNTdHJpbmcobWVzc2FnZS5uYW1lKSlcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFwibmFtZTogc3RyaW5nIGV4cGVjdGVkXCI7XG4gICAgICAgICAgICBpZiAobWVzc2FnZS50eXBlICE9IG51bGwgJiYgbWVzc2FnZS5oYXNPd25Qcm9wZXJ0eShcInR5cGVcIikpIHtcbiAgICAgICAgICAgICAgICB2YXIgZXJyb3IgPSAkcm9vdC5vbm54LlR5cGVQcm90by52ZXJpZnkobWVzc2FnZS50eXBlKTtcbiAgICAgICAgICAgICAgICBpZiAoZXJyb3IpXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBcInR5cGUuXCIgKyBlcnJvcjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChtZXNzYWdlLmRvY1N0cmluZyAhPSBudWxsICYmIG1lc3NhZ2UuaGFzT3duUHJvcGVydHkoXCJkb2NTdHJpbmdcIikpXG4gICAgICAgICAgICAgICAgaWYgKCEkdXRpbC5pc1N0cmluZyhtZXNzYWdlLmRvY1N0cmluZykpXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBcImRvY1N0cmluZzogc3RyaW5nIGV4cGVjdGVkXCI7XG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfTtcblxuICAgICAgICAvKipcbiAgICAgICAgICogQ3JlYXRlcyBhIFZhbHVlSW5mb1Byb3RvIG1lc3NhZ2UgZnJvbSBhIHBsYWluIG9iamVjdC4gQWxzbyBjb252ZXJ0cyB2YWx1ZXMgdG8gdGhlaXIgcmVzcGVjdGl2ZSBpbnRlcm5hbCB0eXBlcy5cbiAgICAgICAgICogQGZ1bmN0aW9uIGZyb21PYmplY3RcbiAgICAgICAgICogQG1lbWJlcm9mIG9ubnguVmFsdWVJbmZvUHJvdG9cbiAgICAgICAgICogQHN0YXRpY1xuICAgICAgICAgKiBAcGFyYW0ge09iamVjdC48c3RyaW5nLCo+fSBvYmplY3QgUGxhaW4gb2JqZWN0XG4gICAgICAgICAqIEByZXR1cm5zIHtvbm54LlZhbHVlSW5mb1Byb3RvfSBWYWx1ZUluZm9Qcm90b1xuICAgICAgICAgKi9cbiAgICAgICAgVmFsdWVJbmZvUHJvdG8uZnJvbU9iamVjdCA9IGZ1bmN0aW9uIGZyb21PYmplY3Qob2JqZWN0KSB7XG4gICAgICAgICAgICBpZiAob2JqZWN0IGluc3RhbmNlb2YgJHJvb3Qub25ueC5WYWx1ZUluZm9Qcm90bylcbiAgICAgICAgICAgICAgICByZXR1cm4gb2JqZWN0O1xuICAgICAgICAgICAgdmFyIG1lc3NhZ2UgPSBuZXcgJHJvb3Qub25ueC5WYWx1ZUluZm9Qcm90bygpO1xuICAgICAgICAgICAgaWYgKG9iamVjdC5uYW1lICE9IG51bGwpXG4gICAgICAgICAgICAgICAgbWVzc2FnZS5uYW1lID0gU3RyaW5nKG9iamVjdC5uYW1lKTtcbiAgICAgICAgICAgIGlmIChvYmplY3QudHlwZSAhPSBudWxsKSB7XG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBvYmplY3QudHlwZSAhPT0gXCJvYmplY3RcIilcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgVHlwZUVycm9yKFwiLm9ubnguVmFsdWVJbmZvUHJvdG8udHlwZTogb2JqZWN0IGV4cGVjdGVkXCIpO1xuICAgICAgICAgICAgICAgIG1lc3NhZ2UudHlwZSA9ICRyb290Lm9ubnguVHlwZVByb3RvLmZyb21PYmplY3Qob2JqZWN0LnR5cGUpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG9iamVjdC5kb2NTdHJpbmcgIT0gbnVsbClcbiAgICAgICAgICAgICAgICBtZXNzYWdlLmRvY1N0cmluZyA9IFN0cmluZyhvYmplY3QuZG9jU3RyaW5nKTtcbiAgICAgICAgICAgIHJldHVybiBtZXNzYWdlO1xuICAgICAgICB9O1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBDcmVhdGVzIGEgcGxhaW4gb2JqZWN0IGZyb20gYSBWYWx1ZUluZm9Qcm90byBtZXNzYWdlLiBBbHNvIGNvbnZlcnRzIHZhbHVlcyB0byBvdGhlciB0eXBlcyBpZiBzcGVjaWZpZWQuXG4gICAgICAgICAqIEBmdW5jdGlvbiB0b09iamVjdFxuICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueC5WYWx1ZUluZm9Qcm90b1xuICAgICAgICAgKiBAc3RhdGljXG4gICAgICAgICAqIEBwYXJhbSB7b25ueC5WYWx1ZUluZm9Qcm90b30gbWVzc2FnZSBWYWx1ZUluZm9Qcm90b1xuICAgICAgICAgKiBAcGFyYW0geyRwcm90b2J1Zi5JQ29udmVyc2lvbk9wdGlvbnN9IFtvcHRpb25zXSBDb252ZXJzaW9uIG9wdGlvbnNcbiAgICAgICAgICogQHJldHVybnMge09iamVjdC48c3RyaW5nLCo+fSBQbGFpbiBvYmplY3RcbiAgICAgICAgICovXG4gICAgICAgIFZhbHVlSW5mb1Byb3RvLnRvT2JqZWN0ID0gZnVuY3Rpb24gdG9PYmplY3QobWVzc2FnZSwgb3B0aW9ucykge1xuICAgICAgICAgICAgaWYgKCFvcHRpb25zKVxuICAgICAgICAgICAgICAgIG9wdGlvbnMgPSB7fTtcbiAgICAgICAgICAgIHZhciBvYmplY3QgPSB7fTtcbiAgICAgICAgICAgIGlmIChvcHRpb25zLmRlZmF1bHRzKSB7XG4gICAgICAgICAgICAgICAgb2JqZWN0Lm5hbWUgPSBcIlwiO1xuICAgICAgICAgICAgICAgIG9iamVjdC50eXBlID0gbnVsbDtcbiAgICAgICAgICAgICAgICBvYmplY3QuZG9jU3RyaW5nID0gXCJcIjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChtZXNzYWdlLm5hbWUgIT0gbnVsbCAmJiBtZXNzYWdlLmhhc093blByb3BlcnR5KFwibmFtZVwiKSlcbiAgICAgICAgICAgICAgICBvYmplY3QubmFtZSA9IG1lc3NhZ2UubmFtZTtcbiAgICAgICAgICAgIGlmIChtZXNzYWdlLnR5cGUgIT0gbnVsbCAmJiBtZXNzYWdlLmhhc093blByb3BlcnR5KFwidHlwZVwiKSlcbiAgICAgICAgICAgICAgICBvYmplY3QudHlwZSA9ICRyb290Lm9ubnguVHlwZVByb3RvLnRvT2JqZWN0KG1lc3NhZ2UudHlwZSwgb3B0aW9ucyk7XG4gICAgICAgICAgICBpZiAobWVzc2FnZS5kb2NTdHJpbmcgIT0gbnVsbCAmJiBtZXNzYWdlLmhhc093blByb3BlcnR5KFwiZG9jU3RyaW5nXCIpKVxuICAgICAgICAgICAgICAgIG9iamVjdC5kb2NTdHJpbmcgPSBtZXNzYWdlLmRvY1N0cmluZztcbiAgICAgICAgICAgIHJldHVybiBvYmplY3Q7XG4gICAgICAgIH07XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIENvbnZlcnRzIHRoaXMgVmFsdWVJbmZvUHJvdG8gdG8gSlNPTi5cbiAgICAgICAgICogQGZ1bmN0aW9uIHRvSlNPTlxuICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueC5WYWx1ZUluZm9Qcm90b1xuICAgICAgICAgKiBAaW5zdGFuY2VcbiAgICAgICAgICogQHJldHVybnMge09iamVjdC48c3RyaW5nLCo+fSBKU09OIG9iamVjdFxuICAgICAgICAgKi9cbiAgICAgICAgVmFsdWVJbmZvUHJvdG8ucHJvdG90eXBlLnRvSlNPTiA9IGZ1bmN0aW9uIHRvSlNPTigpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmNvbnN0cnVjdG9yLnRvT2JqZWN0KHRoaXMsICRwcm90b2J1Zi51dGlsLnRvSlNPTk9wdGlvbnMpO1xuICAgICAgICB9O1xuXG4gICAgICAgIHJldHVybiBWYWx1ZUluZm9Qcm90bztcbiAgICB9KSgpO1xuXG4gICAgb25ueC5Ob2RlUHJvdG8gPSAoZnVuY3Rpb24oKSB7XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIFByb3BlcnRpZXMgb2YgYSBOb2RlUHJvdG8uXG4gICAgICAgICAqIEBtZW1iZXJvZiBvbm54XG4gICAgICAgICAqIEBpbnRlcmZhY2UgSU5vZGVQcm90b1xuICAgICAgICAgKiBAcHJvcGVydHkge0FycmF5LjxzdHJpbmc+fG51bGx9IFtpbnB1dF0gTm9kZVByb3RvIGlucHV0XG4gICAgICAgICAqIEBwcm9wZXJ0eSB7QXJyYXkuPHN0cmluZz58bnVsbH0gW291dHB1dF0gTm9kZVByb3RvIG91dHB1dFxuICAgICAgICAgKiBAcHJvcGVydHkge3N0cmluZ3xudWxsfSBbbmFtZV0gTm9kZVByb3RvIG5hbWVcbiAgICAgICAgICogQHByb3BlcnR5IHtzdHJpbmd8bnVsbH0gW29wVHlwZV0gTm9kZVByb3RvIG9wVHlwZVxuICAgICAgICAgKiBAcHJvcGVydHkge3N0cmluZ3xudWxsfSBbZG9tYWluXSBOb2RlUHJvdG8gZG9tYWluXG4gICAgICAgICAqIEBwcm9wZXJ0eSB7QXJyYXkuPG9ubnguSUF0dHJpYnV0ZVByb3RvPnxudWxsfSBbYXR0cmlidXRlXSBOb2RlUHJvdG8gYXR0cmlidXRlXG4gICAgICAgICAqIEBwcm9wZXJ0eSB7c3RyaW5nfG51bGx9IFtkb2NTdHJpbmddIE5vZGVQcm90byBkb2NTdHJpbmdcbiAgICAgICAgICovXG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIENvbnN0cnVjdHMgYSBuZXcgTm9kZVByb3RvLlxuICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueFxuICAgICAgICAgKiBAY2xhc3NkZXNjIFJlcHJlc2VudHMgYSBOb2RlUHJvdG8uXG4gICAgICAgICAqIEBpbXBsZW1lbnRzIElOb2RlUHJvdG9cbiAgICAgICAgICogQGNvbnN0cnVjdG9yXG4gICAgICAgICAqIEBwYXJhbSB7b25ueC5JTm9kZVByb3RvPX0gW3Byb3BlcnRpZXNdIFByb3BlcnRpZXMgdG8gc2V0XG4gICAgICAgICAqL1xuICAgICAgICBmdW5jdGlvbiBOb2RlUHJvdG8ocHJvcGVydGllcykge1xuICAgICAgICAgICAgdGhpcy5pbnB1dCA9IFtdO1xuICAgICAgICAgICAgdGhpcy5vdXRwdXQgPSBbXTtcbiAgICAgICAgICAgIHRoaXMuYXR0cmlidXRlID0gW107XG4gICAgICAgICAgICBpZiAocHJvcGVydGllcylcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBrZXlzID0gT2JqZWN0LmtleXMocHJvcGVydGllcyksIGkgPSAwOyBpIDwga2V5cy5sZW5ndGg7ICsraSlcbiAgICAgICAgICAgICAgICAgICAgaWYgKHByb3BlcnRpZXNba2V5c1tpXV0gIT0gbnVsbClcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXNba2V5c1tpXV0gPSBwcm9wZXJ0aWVzW2tleXNbaV1dO1xuICAgICAgICB9XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIE5vZGVQcm90byBpbnB1dC5cbiAgICAgICAgICogQG1lbWJlciB7QXJyYXkuPHN0cmluZz59IGlucHV0XG4gICAgICAgICAqIEBtZW1iZXJvZiBvbm54Lk5vZGVQcm90b1xuICAgICAgICAgKiBAaW5zdGFuY2VcbiAgICAgICAgICovXG4gICAgICAgIE5vZGVQcm90by5wcm90b3R5cGUuaW5wdXQgPSAkdXRpbC5lbXB0eUFycmF5O1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBOb2RlUHJvdG8gb3V0cHV0LlxuICAgICAgICAgKiBAbWVtYmVyIHtBcnJheS48c3RyaW5nPn0gb3V0cHV0XG4gICAgICAgICAqIEBtZW1iZXJvZiBvbm54Lk5vZGVQcm90b1xuICAgICAgICAgKiBAaW5zdGFuY2VcbiAgICAgICAgICovXG4gICAgICAgIE5vZGVQcm90by5wcm90b3R5cGUub3V0cHV0ID0gJHV0aWwuZW1wdHlBcnJheTtcblxuICAgICAgICAvKipcbiAgICAgICAgICogTm9kZVByb3RvIG5hbWUuXG4gICAgICAgICAqIEBtZW1iZXIge3N0cmluZ30gbmFtZVxuICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueC5Ob2RlUHJvdG9cbiAgICAgICAgICogQGluc3RhbmNlXG4gICAgICAgICAqL1xuICAgICAgICBOb2RlUHJvdG8ucHJvdG90eXBlLm5hbWUgPSBcIlwiO1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBOb2RlUHJvdG8gb3BUeXBlLlxuICAgICAgICAgKiBAbWVtYmVyIHtzdHJpbmd9IG9wVHlwZVxuICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueC5Ob2RlUHJvdG9cbiAgICAgICAgICogQGluc3RhbmNlXG4gICAgICAgICAqL1xuICAgICAgICBOb2RlUHJvdG8ucHJvdG90eXBlLm9wVHlwZSA9IFwiXCI7XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIE5vZGVQcm90byBkb21haW4uXG4gICAgICAgICAqIEBtZW1iZXIge3N0cmluZ30gZG9tYWluXG4gICAgICAgICAqIEBtZW1iZXJvZiBvbm54Lk5vZGVQcm90b1xuICAgICAgICAgKiBAaW5zdGFuY2VcbiAgICAgICAgICovXG4gICAgICAgIE5vZGVQcm90by5wcm90b3R5cGUuZG9tYWluID0gXCJcIjtcblxuICAgICAgICAvKipcbiAgICAgICAgICogTm9kZVByb3RvIGF0dHJpYnV0ZS5cbiAgICAgICAgICogQG1lbWJlciB7QXJyYXkuPG9ubnguSUF0dHJpYnV0ZVByb3RvPn0gYXR0cmlidXRlXG4gICAgICAgICAqIEBtZW1iZXJvZiBvbm54Lk5vZGVQcm90b1xuICAgICAgICAgKiBAaW5zdGFuY2VcbiAgICAgICAgICovXG4gICAgICAgIE5vZGVQcm90by5wcm90b3R5cGUuYXR0cmlidXRlID0gJHV0aWwuZW1wdHlBcnJheTtcblxuICAgICAgICAvKipcbiAgICAgICAgICogTm9kZVByb3RvIGRvY1N0cmluZy5cbiAgICAgICAgICogQG1lbWJlciB7c3RyaW5nfSBkb2NTdHJpbmdcbiAgICAgICAgICogQG1lbWJlcm9mIG9ubnguTm9kZVByb3RvXG4gICAgICAgICAqIEBpbnN0YW5jZVxuICAgICAgICAgKi9cbiAgICAgICAgTm9kZVByb3RvLnByb3RvdHlwZS5kb2NTdHJpbmcgPSBcIlwiO1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBDcmVhdGVzIGEgbmV3IE5vZGVQcm90byBpbnN0YW5jZSB1c2luZyB0aGUgc3BlY2lmaWVkIHByb3BlcnRpZXMuXG4gICAgICAgICAqIEBmdW5jdGlvbiBjcmVhdGVcbiAgICAgICAgICogQG1lbWJlcm9mIG9ubnguTm9kZVByb3RvXG4gICAgICAgICAqIEBzdGF0aWNcbiAgICAgICAgICogQHBhcmFtIHtvbm54LklOb2RlUHJvdG89fSBbcHJvcGVydGllc10gUHJvcGVydGllcyB0byBzZXRcbiAgICAgICAgICogQHJldHVybnMge29ubnguTm9kZVByb3RvfSBOb2RlUHJvdG8gaW5zdGFuY2VcbiAgICAgICAgICovXG4gICAgICAgIE5vZGVQcm90by5jcmVhdGUgPSBmdW5jdGlvbiBjcmVhdGUocHJvcGVydGllcykge1xuICAgICAgICAgICAgcmV0dXJuIG5ldyBOb2RlUHJvdG8ocHJvcGVydGllcyk7XG4gICAgICAgIH07XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEVuY29kZXMgdGhlIHNwZWNpZmllZCBOb2RlUHJvdG8gbWVzc2FnZS4gRG9lcyBub3QgaW1wbGljaXRseSB7QGxpbmsgb25ueC5Ob2RlUHJvdG8udmVyaWZ5fHZlcmlmeX0gbWVzc2FnZXMuXG4gICAgICAgICAqIEBmdW5jdGlvbiBlbmNvZGVcbiAgICAgICAgICogQG1lbWJlcm9mIG9ubnguTm9kZVByb3RvXG4gICAgICAgICAqIEBzdGF0aWNcbiAgICAgICAgICogQHBhcmFtIHtvbm54LklOb2RlUHJvdG99IG1lc3NhZ2UgTm9kZVByb3RvIG1lc3NhZ2Ugb3IgcGxhaW4gb2JqZWN0IHRvIGVuY29kZVxuICAgICAgICAgKiBAcGFyYW0geyRwcm90b2J1Zi5Xcml0ZXJ9IFt3cml0ZXJdIFdyaXRlciB0byBlbmNvZGUgdG9cbiAgICAgICAgICogQHJldHVybnMgeyRwcm90b2J1Zi5Xcml0ZXJ9IFdyaXRlclxuICAgICAgICAgKi9cbiAgICAgICAgTm9kZVByb3RvLmVuY29kZSA9IGZ1bmN0aW9uIGVuY29kZShtZXNzYWdlLCB3cml0ZXIpIHtcbiAgICAgICAgICAgIGlmICghd3JpdGVyKVxuICAgICAgICAgICAgICAgIHdyaXRlciA9ICRXcml0ZXIuY3JlYXRlKCk7XG4gICAgICAgICAgICBpZiAobWVzc2FnZS5pbnB1dCAhPSBudWxsICYmIG1lc3NhZ2UuaW5wdXQubGVuZ3RoKVxuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbWVzc2FnZS5pbnB1dC5sZW5ndGg7ICsraSlcbiAgICAgICAgICAgICAgICAgICAgd3JpdGVyLnVpbnQzMigvKiBpZCAxLCB3aXJlVHlwZSAyID0qLzEwKS5zdHJpbmcobWVzc2FnZS5pbnB1dFtpXSk7XG4gICAgICAgICAgICBpZiAobWVzc2FnZS5vdXRwdXQgIT0gbnVsbCAmJiBtZXNzYWdlLm91dHB1dC5sZW5ndGgpXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBtZXNzYWdlLm91dHB1dC5sZW5ndGg7ICsraSlcbiAgICAgICAgICAgICAgICAgICAgd3JpdGVyLnVpbnQzMigvKiBpZCAyLCB3aXJlVHlwZSAyID0qLzE4KS5zdHJpbmcobWVzc2FnZS5vdXRwdXRbaV0pO1xuICAgICAgICAgICAgaWYgKG1lc3NhZ2UubmFtZSAhPSBudWxsICYmIG1lc3NhZ2UuaGFzT3duUHJvcGVydHkoXCJuYW1lXCIpKVxuICAgICAgICAgICAgICAgIHdyaXRlci51aW50MzIoLyogaWQgMywgd2lyZVR5cGUgMiA9Ki8yNikuc3RyaW5nKG1lc3NhZ2UubmFtZSk7XG4gICAgICAgICAgICBpZiAobWVzc2FnZS5vcFR5cGUgIT0gbnVsbCAmJiBtZXNzYWdlLmhhc093blByb3BlcnR5KFwib3BUeXBlXCIpKVxuICAgICAgICAgICAgICAgIHdyaXRlci51aW50MzIoLyogaWQgNCwgd2lyZVR5cGUgMiA9Ki8zNCkuc3RyaW5nKG1lc3NhZ2Uub3BUeXBlKTtcbiAgICAgICAgICAgIGlmIChtZXNzYWdlLmF0dHJpYnV0ZSAhPSBudWxsICYmIG1lc3NhZ2UuYXR0cmlidXRlLmxlbmd0aClcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG1lc3NhZ2UuYXR0cmlidXRlLmxlbmd0aDsgKytpKVxuICAgICAgICAgICAgICAgICAgICAkcm9vdC5vbm54LkF0dHJpYnV0ZVByb3RvLmVuY29kZShtZXNzYWdlLmF0dHJpYnV0ZVtpXSwgd3JpdGVyLnVpbnQzMigvKiBpZCA1LCB3aXJlVHlwZSAyID0qLzQyKS5mb3JrKCkpLmxkZWxpbSgpO1xuICAgICAgICAgICAgaWYgKG1lc3NhZ2UuZG9jU3RyaW5nICE9IG51bGwgJiYgbWVzc2FnZS5oYXNPd25Qcm9wZXJ0eShcImRvY1N0cmluZ1wiKSlcbiAgICAgICAgICAgICAgICB3cml0ZXIudWludDMyKC8qIGlkIDYsIHdpcmVUeXBlIDIgPSovNTApLnN0cmluZyhtZXNzYWdlLmRvY1N0cmluZyk7XG4gICAgICAgICAgICBpZiAobWVzc2FnZS5kb21haW4gIT0gbnVsbCAmJiBtZXNzYWdlLmhhc093blByb3BlcnR5KFwiZG9tYWluXCIpKVxuICAgICAgICAgICAgICAgIHdyaXRlci51aW50MzIoLyogaWQgNywgd2lyZVR5cGUgMiA9Ki81OCkuc3RyaW5nKG1lc3NhZ2UuZG9tYWluKTtcbiAgICAgICAgICAgIHJldHVybiB3cml0ZXI7XG4gICAgICAgIH07XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEVuY29kZXMgdGhlIHNwZWNpZmllZCBOb2RlUHJvdG8gbWVzc2FnZSwgbGVuZ3RoIGRlbGltaXRlZC4gRG9lcyBub3QgaW1wbGljaXRseSB7QGxpbmsgb25ueC5Ob2RlUHJvdG8udmVyaWZ5fHZlcmlmeX0gbWVzc2FnZXMuXG4gICAgICAgICAqIEBmdW5jdGlvbiBlbmNvZGVEZWxpbWl0ZWRcbiAgICAgICAgICogQG1lbWJlcm9mIG9ubnguTm9kZVByb3RvXG4gICAgICAgICAqIEBzdGF0aWNcbiAgICAgICAgICogQHBhcmFtIHtvbm54LklOb2RlUHJvdG99IG1lc3NhZ2UgTm9kZVByb3RvIG1lc3NhZ2Ugb3IgcGxhaW4gb2JqZWN0IHRvIGVuY29kZVxuICAgICAgICAgKiBAcGFyYW0geyRwcm90b2J1Zi5Xcml0ZXJ9IFt3cml0ZXJdIFdyaXRlciB0byBlbmNvZGUgdG9cbiAgICAgICAgICogQHJldHVybnMgeyRwcm90b2J1Zi5Xcml0ZXJ9IFdyaXRlclxuICAgICAgICAgKi9cbiAgICAgICAgTm9kZVByb3RvLmVuY29kZURlbGltaXRlZCA9IGZ1bmN0aW9uIGVuY29kZURlbGltaXRlZChtZXNzYWdlLCB3cml0ZXIpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmVuY29kZShtZXNzYWdlLCB3cml0ZXIpLmxkZWxpbSgpO1xuICAgICAgICB9O1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBEZWNvZGVzIGEgTm9kZVByb3RvIG1lc3NhZ2UgZnJvbSB0aGUgc3BlY2lmaWVkIHJlYWRlciBvciBidWZmZXIuXG4gICAgICAgICAqIEBmdW5jdGlvbiBkZWNvZGVcbiAgICAgICAgICogQG1lbWJlcm9mIG9ubnguTm9kZVByb3RvXG4gICAgICAgICAqIEBzdGF0aWNcbiAgICAgICAgICogQHBhcmFtIHskcHJvdG9idWYuUmVhZGVyfFVpbnQ4QXJyYXl9IHJlYWRlciBSZWFkZXIgb3IgYnVmZmVyIHRvIGRlY29kZSBmcm9tXG4gICAgICAgICAqIEBwYXJhbSB7bnVtYmVyfSBbbGVuZ3RoXSBNZXNzYWdlIGxlbmd0aCBpZiBrbm93biBiZWZvcmVoYW5kXG4gICAgICAgICAqIEByZXR1cm5zIHtvbm54Lk5vZGVQcm90b30gTm9kZVByb3RvXG4gICAgICAgICAqIEB0aHJvd3Mge0Vycm9yfSBJZiB0aGUgcGF5bG9hZCBpcyBub3QgYSByZWFkZXIgb3IgdmFsaWQgYnVmZmVyXG4gICAgICAgICAqIEB0aHJvd3MgeyRwcm90b2J1Zi51dGlsLlByb3RvY29sRXJyb3J9IElmIHJlcXVpcmVkIGZpZWxkcyBhcmUgbWlzc2luZ1xuICAgICAgICAgKi9cbiAgICAgICAgTm9kZVByb3RvLmRlY29kZSA9IGZ1bmN0aW9uIGRlY29kZShyZWFkZXIsIGxlbmd0aCkge1xuICAgICAgICAgICAgaWYgKCEocmVhZGVyIGluc3RhbmNlb2YgJFJlYWRlcikpXG4gICAgICAgICAgICAgICAgcmVhZGVyID0gJFJlYWRlci5jcmVhdGUocmVhZGVyKTtcbiAgICAgICAgICAgIHZhciBlbmQgPSBsZW5ndGggPT09IHVuZGVmaW5lZCA/IHJlYWRlci5sZW4gOiByZWFkZXIucG9zICsgbGVuZ3RoLCBtZXNzYWdlID0gbmV3ICRyb290Lm9ubnguTm9kZVByb3RvKCk7XG4gICAgICAgICAgICB3aGlsZSAocmVhZGVyLnBvcyA8IGVuZCkge1xuICAgICAgICAgICAgICAgIHZhciB0YWcgPSByZWFkZXIudWludDMyKCk7XG4gICAgICAgICAgICAgICAgc3dpdGNoICh0YWcgPj4+IDMpIHtcbiAgICAgICAgICAgICAgICBjYXNlIDE6XG4gICAgICAgICAgICAgICAgICAgIGlmICghKG1lc3NhZ2UuaW5wdXQgJiYgbWVzc2FnZS5pbnB1dC5sZW5ndGgpKVxuICAgICAgICAgICAgICAgICAgICAgICAgbWVzc2FnZS5pbnB1dCA9IFtdO1xuICAgICAgICAgICAgICAgICAgICBtZXNzYWdlLmlucHV0LnB1c2gocmVhZGVyLnN0cmluZygpKTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSAyOlxuICAgICAgICAgICAgICAgICAgICBpZiAoIShtZXNzYWdlLm91dHB1dCAmJiBtZXNzYWdlLm91dHB1dC5sZW5ndGgpKVxuICAgICAgICAgICAgICAgICAgICAgICAgbWVzc2FnZS5vdXRwdXQgPSBbXTtcbiAgICAgICAgICAgICAgICAgICAgbWVzc2FnZS5vdXRwdXQucHVzaChyZWFkZXIuc3RyaW5nKCkpO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlIDM6XG4gICAgICAgICAgICAgICAgICAgIG1lc3NhZ2UubmFtZSA9IHJlYWRlci5zdHJpbmcoKTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSA0OlxuICAgICAgICAgICAgICAgICAgICBtZXNzYWdlLm9wVHlwZSA9IHJlYWRlci5zdHJpbmcoKTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSA3OlxuICAgICAgICAgICAgICAgICAgICBtZXNzYWdlLmRvbWFpbiA9IHJlYWRlci5zdHJpbmcoKTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSA1OlxuICAgICAgICAgICAgICAgICAgICBpZiAoIShtZXNzYWdlLmF0dHJpYnV0ZSAmJiBtZXNzYWdlLmF0dHJpYnV0ZS5sZW5ndGgpKVxuICAgICAgICAgICAgICAgICAgICAgICAgbWVzc2FnZS5hdHRyaWJ1dGUgPSBbXTtcbiAgICAgICAgICAgICAgICAgICAgbWVzc2FnZS5hdHRyaWJ1dGUucHVzaCgkcm9vdC5vbm54LkF0dHJpYnV0ZVByb3RvLmRlY29kZShyZWFkZXIsIHJlYWRlci51aW50MzIoKSkpO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlIDY6XG4gICAgICAgICAgICAgICAgICAgIG1lc3NhZ2UuZG9jU3RyaW5nID0gcmVhZGVyLnN0cmluZygpO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgICAgICByZWFkZXIuc2tpcFR5cGUodGFnICYgNyk7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBtZXNzYWdlO1xuICAgICAgICB9O1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBEZWNvZGVzIGEgTm9kZVByb3RvIG1lc3NhZ2UgZnJvbSB0aGUgc3BlY2lmaWVkIHJlYWRlciBvciBidWZmZXIsIGxlbmd0aCBkZWxpbWl0ZWQuXG4gICAgICAgICAqIEBmdW5jdGlvbiBkZWNvZGVEZWxpbWl0ZWRcbiAgICAgICAgICogQG1lbWJlcm9mIG9ubnguTm9kZVByb3RvXG4gICAgICAgICAqIEBzdGF0aWNcbiAgICAgICAgICogQHBhcmFtIHskcHJvdG9idWYuUmVhZGVyfFVpbnQ4QXJyYXl9IHJlYWRlciBSZWFkZXIgb3IgYnVmZmVyIHRvIGRlY29kZSBmcm9tXG4gICAgICAgICAqIEByZXR1cm5zIHtvbm54Lk5vZGVQcm90b30gTm9kZVByb3RvXG4gICAgICAgICAqIEB0aHJvd3Mge0Vycm9yfSBJZiB0aGUgcGF5bG9hZCBpcyBub3QgYSByZWFkZXIgb3IgdmFsaWQgYnVmZmVyXG4gICAgICAgICAqIEB0aHJvd3MgeyRwcm90b2J1Zi51dGlsLlByb3RvY29sRXJyb3J9IElmIHJlcXVpcmVkIGZpZWxkcyBhcmUgbWlzc2luZ1xuICAgICAgICAgKi9cbiAgICAgICAgTm9kZVByb3RvLmRlY29kZURlbGltaXRlZCA9IGZ1bmN0aW9uIGRlY29kZURlbGltaXRlZChyZWFkZXIpIHtcbiAgICAgICAgICAgIGlmICghKHJlYWRlciBpbnN0YW5jZW9mICRSZWFkZXIpKVxuICAgICAgICAgICAgICAgIHJlYWRlciA9IG5ldyAkUmVhZGVyKHJlYWRlcik7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5kZWNvZGUocmVhZGVyLCByZWFkZXIudWludDMyKCkpO1xuICAgICAgICB9O1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBWZXJpZmllcyBhIE5vZGVQcm90byBtZXNzYWdlLlxuICAgICAgICAgKiBAZnVuY3Rpb24gdmVyaWZ5XG4gICAgICAgICAqIEBtZW1iZXJvZiBvbm54Lk5vZGVQcm90b1xuICAgICAgICAgKiBAc3RhdGljXG4gICAgICAgICAqIEBwYXJhbSB7T2JqZWN0LjxzdHJpbmcsKj59IG1lc3NhZ2UgUGxhaW4gb2JqZWN0IHRvIHZlcmlmeVxuICAgICAgICAgKiBAcmV0dXJucyB7c3RyaW5nfG51bGx9IGBudWxsYCBpZiB2YWxpZCwgb3RoZXJ3aXNlIHRoZSByZWFzb24gd2h5IGl0IGlzIG5vdFxuICAgICAgICAgKi9cbiAgICAgICAgTm9kZVByb3RvLnZlcmlmeSA9IGZ1bmN0aW9uIHZlcmlmeShtZXNzYWdlKSB7XG4gICAgICAgICAgICBpZiAodHlwZW9mIG1lc3NhZ2UgIT09IFwib2JqZWN0XCIgfHwgbWVzc2FnZSA9PT0gbnVsbClcbiAgICAgICAgICAgICAgICByZXR1cm4gXCJvYmplY3QgZXhwZWN0ZWRcIjtcbiAgICAgICAgICAgIGlmIChtZXNzYWdlLmlucHV0ICE9IG51bGwgJiYgbWVzc2FnZS5oYXNPd25Qcm9wZXJ0eShcImlucHV0XCIpKSB7XG4gICAgICAgICAgICAgICAgaWYgKCFBcnJheS5pc0FycmF5KG1lc3NhZ2UuaW5wdXQpKVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gXCJpbnB1dDogYXJyYXkgZXhwZWN0ZWRcIjtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG1lc3NhZ2UuaW5wdXQubGVuZ3RoOyArK2kpXG4gICAgICAgICAgICAgICAgICAgIGlmICghJHV0aWwuaXNTdHJpbmcobWVzc2FnZS5pbnB1dFtpXSkpXG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gXCJpbnB1dDogc3RyaW5nW10gZXhwZWN0ZWRcIjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChtZXNzYWdlLm91dHB1dCAhPSBudWxsICYmIG1lc3NhZ2UuaGFzT3duUHJvcGVydHkoXCJvdXRwdXRcIikpIHtcbiAgICAgICAgICAgICAgICBpZiAoIUFycmF5LmlzQXJyYXkobWVzc2FnZS5vdXRwdXQpKVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gXCJvdXRwdXQ6IGFycmF5IGV4cGVjdGVkXCI7XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBtZXNzYWdlLm91dHB1dC5sZW5ndGg7ICsraSlcbiAgICAgICAgICAgICAgICAgICAgaWYgKCEkdXRpbC5pc1N0cmluZyhtZXNzYWdlLm91dHB1dFtpXSkpXG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gXCJvdXRwdXQ6IHN0cmluZ1tdIGV4cGVjdGVkXCI7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAobWVzc2FnZS5uYW1lICE9IG51bGwgJiYgbWVzc2FnZS5oYXNPd25Qcm9wZXJ0eShcIm5hbWVcIikpXG4gICAgICAgICAgICAgICAgaWYgKCEkdXRpbC5pc1N0cmluZyhtZXNzYWdlLm5hbWUpKVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gXCJuYW1lOiBzdHJpbmcgZXhwZWN0ZWRcIjtcbiAgICAgICAgICAgIGlmIChtZXNzYWdlLm9wVHlwZSAhPSBudWxsICYmIG1lc3NhZ2UuaGFzT3duUHJvcGVydHkoXCJvcFR5cGVcIikpXG4gICAgICAgICAgICAgICAgaWYgKCEkdXRpbC5pc1N0cmluZyhtZXNzYWdlLm9wVHlwZSkpXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBcIm9wVHlwZTogc3RyaW5nIGV4cGVjdGVkXCI7XG4gICAgICAgICAgICBpZiAobWVzc2FnZS5kb21haW4gIT0gbnVsbCAmJiBtZXNzYWdlLmhhc093blByb3BlcnR5KFwiZG9tYWluXCIpKVxuICAgICAgICAgICAgICAgIGlmICghJHV0aWwuaXNTdHJpbmcobWVzc2FnZS5kb21haW4pKVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gXCJkb21haW46IHN0cmluZyBleHBlY3RlZFwiO1xuICAgICAgICAgICAgaWYgKG1lc3NhZ2UuYXR0cmlidXRlICE9IG51bGwgJiYgbWVzc2FnZS5oYXNPd25Qcm9wZXJ0eShcImF0dHJpYnV0ZVwiKSkge1xuICAgICAgICAgICAgICAgIGlmICghQXJyYXkuaXNBcnJheShtZXNzYWdlLmF0dHJpYnV0ZSkpXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBcImF0dHJpYnV0ZTogYXJyYXkgZXhwZWN0ZWRcIjtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG1lc3NhZ2UuYXR0cmlidXRlLmxlbmd0aDsgKytpKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBlcnJvciA9ICRyb290Lm9ubnguQXR0cmlidXRlUHJvdG8udmVyaWZ5KG1lc3NhZ2UuYXR0cmlidXRlW2ldKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGVycm9yKVxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFwiYXR0cmlidXRlLlwiICsgZXJyb3I7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG1lc3NhZ2UuZG9jU3RyaW5nICE9IG51bGwgJiYgbWVzc2FnZS5oYXNPd25Qcm9wZXJ0eShcImRvY1N0cmluZ1wiKSlcbiAgICAgICAgICAgICAgICBpZiAoISR1dGlsLmlzU3RyaW5nKG1lc3NhZ2UuZG9jU3RyaW5nKSlcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFwiZG9jU3RyaW5nOiBzdHJpbmcgZXhwZWN0ZWRcIjtcbiAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9O1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBDcmVhdGVzIGEgTm9kZVByb3RvIG1lc3NhZ2UgZnJvbSBhIHBsYWluIG9iamVjdC4gQWxzbyBjb252ZXJ0cyB2YWx1ZXMgdG8gdGhlaXIgcmVzcGVjdGl2ZSBpbnRlcm5hbCB0eXBlcy5cbiAgICAgICAgICogQGZ1bmN0aW9uIGZyb21PYmplY3RcbiAgICAgICAgICogQG1lbWJlcm9mIG9ubnguTm9kZVByb3RvXG4gICAgICAgICAqIEBzdGF0aWNcbiAgICAgICAgICogQHBhcmFtIHtPYmplY3QuPHN0cmluZywqPn0gb2JqZWN0IFBsYWluIG9iamVjdFxuICAgICAgICAgKiBAcmV0dXJucyB7b25ueC5Ob2RlUHJvdG99IE5vZGVQcm90b1xuICAgICAgICAgKi9cbiAgICAgICAgTm9kZVByb3RvLmZyb21PYmplY3QgPSBmdW5jdGlvbiBmcm9tT2JqZWN0KG9iamVjdCkge1xuICAgICAgICAgICAgaWYgKG9iamVjdCBpbnN0YW5jZW9mICRyb290Lm9ubnguTm9kZVByb3RvKVxuICAgICAgICAgICAgICAgIHJldHVybiBvYmplY3Q7XG4gICAgICAgICAgICB2YXIgbWVzc2FnZSA9IG5ldyAkcm9vdC5vbm54Lk5vZGVQcm90bygpO1xuICAgICAgICAgICAgaWYgKG9iamVjdC5pbnB1dCkge1xuICAgICAgICAgICAgICAgIGlmICghQXJyYXkuaXNBcnJheShvYmplY3QuaW5wdXQpKVxuICAgICAgICAgICAgICAgICAgICB0aHJvdyBUeXBlRXJyb3IoXCIub25ueC5Ob2RlUHJvdG8uaW5wdXQ6IGFycmF5IGV4cGVjdGVkXCIpO1xuICAgICAgICAgICAgICAgIG1lc3NhZ2UuaW5wdXQgPSBbXTtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG9iamVjdC5pbnB1dC5sZW5ndGg7ICsraSlcbiAgICAgICAgICAgICAgICAgICAgbWVzc2FnZS5pbnB1dFtpXSA9IFN0cmluZyhvYmplY3QuaW5wdXRbaV0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG9iamVjdC5vdXRwdXQpIHtcbiAgICAgICAgICAgICAgICBpZiAoIUFycmF5LmlzQXJyYXkob2JqZWN0Lm91dHB1dCkpXG4gICAgICAgICAgICAgICAgICAgIHRocm93IFR5cGVFcnJvcihcIi5vbm54Lk5vZGVQcm90by5vdXRwdXQ6IGFycmF5IGV4cGVjdGVkXCIpO1xuICAgICAgICAgICAgICAgIG1lc3NhZ2Uub3V0cHV0ID0gW107XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBvYmplY3Qub3V0cHV0Lmxlbmd0aDsgKytpKVxuICAgICAgICAgICAgICAgICAgICBtZXNzYWdlLm91dHB1dFtpXSA9IFN0cmluZyhvYmplY3Qub3V0cHV0W2ldKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChvYmplY3QubmFtZSAhPSBudWxsKVxuICAgICAgICAgICAgICAgIG1lc3NhZ2UubmFtZSA9IFN0cmluZyhvYmplY3QubmFtZSk7XG4gICAgICAgICAgICBpZiAob2JqZWN0Lm9wVHlwZSAhPSBudWxsKVxuICAgICAgICAgICAgICAgIG1lc3NhZ2Uub3BUeXBlID0gU3RyaW5nKG9iamVjdC5vcFR5cGUpO1xuICAgICAgICAgICAgaWYgKG9iamVjdC5kb21haW4gIT0gbnVsbClcbiAgICAgICAgICAgICAgICBtZXNzYWdlLmRvbWFpbiA9IFN0cmluZyhvYmplY3QuZG9tYWluKTtcbiAgICAgICAgICAgIGlmIChvYmplY3QuYXR0cmlidXRlKSB7XG4gICAgICAgICAgICAgICAgaWYgKCFBcnJheS5pc0FycmF5KG9iamVjdC5hdHRyaWJ1dGUpKVxuICAgICAgICAgICAgICAgICAgICB0aHJvdyBUeXBlRXJyb3IoXCIub25ueC5Ob2RlUHJvdG8uYXR0cmlidXRlOiBhcnJheSBleHBlY3RlZFwiKTtcbiAgICAgICAgICAgICAgICBtZXNzYWdlLmF0dHJpYnV0ZSA9IFtdO1xuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgb2JqZWN0LmF0dHJpYnV0ZS5sZW5ndGg7ICsraSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAodHlwZW9mIG9iamVjdC5hdHRyaWJ1dGVbaV0gIT09IFwib2JqZWN0XCIpXG4gICAgICAgICAgICAgICAgICAgICAgICB0aHJvdyBUeXBlRXJyb3IoXCIub25ueC5Ob2RlUHJvdG8uYXR0cmlidXRlOiBvYmplY3QgZXhwZWN0ZWRcIik7XG4gICAgICAgICAgICAgICAgICAgIG1lc3NhZ2UuYXR0cmlidXRlW2ldID0gJHJvb3Qub25ueC5BdHRyaWJ1dGVQcm90by5mcm9tT2JqZWN0KG9iamVjdC5hdHRyaWJ1dGVbaV0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChvYmplY3QuZG9jU3RyaW5nICE9IG51bGwpXG4gICAgICAgICAgICAgICAgbWVzc2FnZS5kb2NTdHJpbmcgPSBTdHJpbmcob2JqZWN0LmRvY1N0cmluZyk7XG4gICAgICAgICAgICByZXR1cm4gbWVzc2FnZTtcbiAgICAgICAgfTtcblxuICAgICAgICAvKipcbiAgICAgICAgICogQ3JlYXRlcyBhIHBsYWluIG9iamVjdCBmcm9tIGEgTm9kZVByb3RvIG1lc3NhZ2UuIEFsc28gY29udmVydHMgdmFsdWVzIHRvIG90aGVyIHR5cGVzIGlmIHNwZWNpZmllZC5cbiAgICAgICAgICogQGZ1bmN0aW9uIHRvT2JqZWN0XG4gICAgICAgICAqIEBtZW1iZXJvZiBvbm54Lk5vZGVQcm90b1xuICAgICAgICAgKiBAc3RhdGljXG4gICAgICAgICAqIEBwYXJhbSB7b25ueC5Ob2RlUHJvdG99IG1lc3NhZ2UgTm9kZVByb3RvXG4gICAgICAgICAqIEBwYXJhbSB7JHByb3RvYnVmLklDb252ZXJzaW9uT3B0aW9uc30gW29wdGlvbnNdIENvbnZlcnNpb24gb3B0aW9uc1xuICAgICAgICAgKiBAcmV0dXJucyB7T2JqZWN0LjxzdHJpbmcsKj59IFBsYWluIG9iamVjdFxuICAgICAgICAgKi9cbiAgICAgICAgTm9kZVByb3RvLnRvT2JqZWN0ID0gZnVuY3Rpb24gdG9PYmplY3QobWVzc2FnZSwgb3B0aW9ucykge1xuICAgICAgICAgICAgaWYgKCFvcHRpb25zKVxuICAgICAgICAgICAgICAgIG9wdGlvbnMgPSB7fTtcbiAgICAgICAgICAgIHZhciBvYmplY3QgPSB7fTtcbiAgICAgICAgICAgIGlmIChvcHRpb25zLmFycmF5cyB8fCBvcHRpb25zLmRlZmF1bHRzKSB7XG4gICAgICAgICAgICAgICAgb2JqZWN0LmlucHV0ID0gW107XG4gICAgICAgICAgICAgICAgb2JqZWN0Lm91dHB1dCA9IFtdO1xuICAgICAgICAgICAgICAgIG9iamVjdC5hdHRyaWJ1dGUgPSBbXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChvcHRpb25zLmRlZmF1bHRzKSB7XG4gICAgICAgICAgICAgICAgb2JqZWN0Lm5hbWUgPSBcIlwiO1xuICAgICAgICAgICAgICAgIG9iamVjdC5vcFR5cGUgPSBcIlwiO1xuICAgICAgICAgICAgICAgIG9iamVjdC5kb2NTdHJpbmcgPSBcIlwiO1xuICAgICAgICAgICAgICAgIG9iamVjdC5kb21haW4gPSBcIlwiO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG1lc3NhZ2UuaW5wdXQgJiYgbWVzc2FnZS5pbnB1dC5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICBvYmplY3QuaW5wdXQgPSBbXTtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBqID0gMDsgaiA8IG1lc3NhZ2UuaW5wdXQubGVuZ3RoOyArK2opXG4gICAgICAgICAgICAgICAgICAgIG9iamVjdC5pbnB1dFtqXSA9IG1lc3NhZ2UuaW5wdXRbal07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAobWVzc2FnZS5vdXRwdXQgJiYgbWVzc2FnZS5vdXRwdXQubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgb2JqZWN0Lm91dHB1dCA9IFtdO1xuICAgICAgICAgICAgICAgIGZvciAodmFyIGogPSAwOyBqIDwgbWVzc2FnZS5vdXRwdXQubGVuZ3RoOyArK2opXG4gICAgICAgICAgICAgICAgICAgIG9iamVjdC5vdXRwdXRbal0gPSBtZXNzYWdlLm91dHB1dFtqXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChtZXNzYWdlLm5hbWUgIT0gbnVsbCAmJiBtZXNzYWdlLmhhc093blByb3BlcnR5KFwibmFtZVwiKSlcbiAgICAgICAgICAgICAgICBvYmplY3QubmFtZSA9IG1lc3NhZ2UubmFtZTtcbiAgICAgICAgICAgIGlmIChtZXNzYWdlLm9wVHlwZSAhPSBudWxsICYmIG1lc3NhZ2UuaGFzT3duUHJvcGVydHkoXCJvcFR5cGVcIikpXG4gICAgICAgICAgICAgICAgb2JqZWN0Lm9wVHlwZSA9IG1lc3NhZ2Uub3BUeXBlO1xuICAgICAgICAgICAgaWYgKG1lc3NhZ2UuYXR0cmlidXRlICYmIG1lc3NhZ2UuYXR0cmlidXRlLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgIG9iamVjdC5hdHRyaWJ1dGUgPSBbXTtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBqID0gMDsgaiA8IG1lc3NhZ2UuYXR0cmlidXRlLmxlbmd0aDsgKytqKVxuICAgICAgICAgICAgICAgICAgICBvYmplY3QuYXR0cmlidXRlW2pdID0gJHJvb3Qub25ueC5BdHRyaWJ1dGVQcm90by50b09iamVjdChtZXNzYWdlLmF0dHJpYnV0ZVtqXSwgb3B0aW9ucyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAobWVzc2FnZS5kb2NTdHJpbmcgIT0gbnVsbCAmJiBtZXNzYWdlLmhhc093blByb3BlcnR5KFwiZG9jU3RyaW5nXCIpKVxuICAgICAgICAgICAgICAgIG9iamVjdC5kb2NTdHJpbmcgPSBtZXNzYWdlLmRvY1N0cmluZztcbiAgICAgICAgICAgIGlmIChtZXNzYWdlLmRvbWFpbiAhPSBudWxsICYmIG1lc3NhZ2UuaGFzT3duUHJvcGVydHkoXCJkb21haW5cIikpXG4gICAgICAgICAgICAgICAgb2JqZWN0LmRvbWFpbiA9IG1lc3NhZ2UuZG9tYWluO1xuICAgICAgICAgICAgcmV0dXJuIG9iamVjdDtcbiAgICAgICAgfTtcblxuICAgICAgICAvKipcbiAgICAgICAgICogQ29udmVydHMgdGhpcyBOb2RlUHJvdG8gdG8gSlNPTi5cbiAgICAgICAgICogQGZ1bmN0aW9uIHRvSlNPTlxuICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueC5Ob2RlUHJvdG9cbiAgICAgICAgICogQGluc3RhbmNlXG4gICAgICAgICAqIEByZXR1cm5zIHtPYmplY3QuPHN0cmluZywqPn0gSlNPTiBvYmplY3RcbiAgICAgICAgICovXG4gICAgICAgIE5vZGVQcm90by5wcm90b3R5cGUudG9KU09OID0gZnVuY3Rpb24gdG9KU09OKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuY29uc3RydWN0b3IudG9PYmplY3QodGhpcywgJHByb3RvYnVmLnV0aWwudG9KU09OT3B0aW9ucyk7XG4gICAgICAgIH07XG5cbiAgICAgICAgcmV0dXJuIE5vZGVQcm90bztcbiAgICB9KSgpO1xuXG4gICAgb25ueC5Nb2RlbFByb3RvID0gKGZ1bmN0aW9uKCkge1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBQcm9wZXJ0aWVzIG9mIGEgTW9kZWxQcm90by5cbiAgICAgICAgICogQG1lbWJlcm9mIG9ubnhcbiAgICAgICAgICogQGludGVyZmFjZSBJTW9kZWxQcm90b1xuICAgICAgICAgKiBAcHJvcGVydHkge251bWJlcnxMb25nfG51bGx9IFtpclZlcnNpb25dIE1vZGVsUHJvdG8gaXJWZXJzaW9uXG4gICAgICAgICAqIEBwcm9wZXJ0eSB7QXJyYXkuPG9ubnguSU9wZXJhdG9yU2V0SWRQcm90bz58bnVsbH0gW29wc2V0SW1wb3J0XSBNb2RlbFByb3RvIG9wc2V0SW1wb3J0XG4gICAgICAgICAqIEBwcm9wZXJ0eSB7c3RyaW5nfG51bGx9IFtwcm9kdWNlck5hbWVdIE1vZGVsUHJvdG8gcHJvZHVjZXJOYW1lXG4gICAgICAgICAqIEBwcm9wZXJ0eSB7c3RyaW5nfG51bGx9IFtwcm9kdWNlclZlcnNpb25dIE1vZGVsUHJvdG8gcHJvZHVjZXJWZXJzaW9uXG4gICAgICAgICAqIEBwcm9wZXJ0eSB7c3RyaW5nfG51bGx9IFtkb21haW5dIE1vZGVsUHJvdG8gZG9tYWluXG4gICAgICAgICAqIEBwcm9wZXJ0eSB7bnVtYmVyfExvbmd8bnVsbH0gW21vZGVsVmVyc2lvbl0gTW9kZWxQcm90byBtb2RlbFZlcnNpb25cbiAgICAgICAgICogQHByb3BlcnR5IHtzdHJpbmd8bnVsbH0gW2RvY1N0cmluZ10gTW9kZWxQcm90byBkb2NTdHJpbmdcbiAgICAgICAgICogQHByb3BlcnR5IHtvbm54LklHcmFwaFByb3RvfG51bGx9IFtncmFwaF0gTW9kZWxQcm90byBncmFwaFxuICAgICAgICAgKiBAcHJvcGVydHkge0FycmF5Ljxvbm54LklTdHJpbmdTdHJpbmdFbnRyeVByb3RvPnxudWxsfSBbbWV0YWRhdGFQcm9wc10gTW9kZWxQcm90byBtZXRhZGF0YVByb3BzXG4gICAgICAgICAqL1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBDb25zdHJ1Y3RzIGEgbmV3IE1vZGVsUHJvdG8uXG4gICAgICAgICAqIEBtZW1iZXJvZiBvbm54XG4gICAgICAgICAqIEBjbGFzc2Rlc2MgUmVwcmVzZW50cyBhIE1vZGVsUHJvdG8uXG4gICAgICAgICAqIEBpbXBsZW1lbnRzIElNb2RlbFByb3RvXG4gICAgICAgICAqIEBjb25zdHJ1Y3RvclxuICAgICAgICAgKiBAcGFyYW0ge29ubnguSU1vZGVsUHJvdG89fSBbcHJvcGVydGllc10gUHJvcGVydGllcyB0byBzZXRcbiAgICAgICAgICovXG4gICAgICAgIGZ1bmN0aW9uIE1vZGVsUHJvdG8ocHJvcGVydGllcykge1xuICAgICAgICAgICAgdGhpcy5vcHNldEltcG9ydCA9IFtdO1xuICAgICAgICAgICAgdGhpcy5tZXRhZGF0YVByb3BzID0gW107XG4gICAgICAgICAgICBpZiAocHJvcGVydGllcylcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBrZXlzID0gT2JqZWN0LmtleXMocHJvcGVydGllcyksIGkgPSAwOyBpIDwga2V5cy5sZW5ndGg7ICsraSlcbiAgICAgICAgICAgICAgICAgICAgaWYgKHByb3BlcnRpZXNba2V5c1tpXV0gIT0gbnVsbClcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXNba2V5c1tpXV0gPSBwcm9wZXJ0aWVzW2tleXNbaV1dO1xuICAgICAgICB9XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIE1vZGVsUHJvdG8gaXJWZXJzaW9uLlxuICAgICAgICAgKiBAbWVtYmVyIHtudW1iZXJ8TG9uZ30gaXJWZXJzaW9uXG4gICAgICAgICAqIEBtZW1iZXJvZiBvbm54Lk1vZGVsUHJvdG9cbiAgICAgICAgICogQGluc3RhbmNlXG4gICAgICAgICAqL1xuICAgICAgICBNb2RlbFByb3RvLnByb3RvdHlwZS5pclZlcnNpb24gPSAkdXRpbC5Mb25nID8gJHV0aWwuTG9uZy5mcm9tQml0cygwLDAsZmFsc2UpIDogMDtcblxuICAgICAgICAvKipcbiAgICAgICAgICogTW9kZWxQcm90byBvcHNldEltcG9ydC5cbiAgICAgICAgICogQG1lbWJlciB7QXJyYXkuPG9ubnguSU9wZXJhdG9yU2V0SWRQcm90bz59IG9wc2V0SW1wb3J0XG4gICAgICAgICAqIEBtZW1iZXJvZiBvbm54Lk1vZGVsUHJvdG9cbiAgICAgICAgICogQGluc3RhbmNlXG4gICAgICAgICAqL1xuICAgICAgICBNb2RlbFByb3RvLnByb3RvdHlwZS5vcHNldEltcG9ydCA9ICR1dGlsLmVtcHR5QXJyYXk7XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIE1vZGVsUHJvdG8gcHJvZHVjZXJOYW1lLlxuICAgICAgICAgKiBAbWVtYmVyIHtzdHJpbmd9IHByb2R1Y2VyTmFtZVxuICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueC5Nb2RlbFByb3RvXG4gICAgICAgICAqIEBpbnN0YW5jZVxuICAgICAgICAgKi9cbiAgICAgICAgTW9kZWxQcm90by5wcm90b3R5cGUucHJvZHVjZXJOYW1lID0gXCJcIjtcblxuICAgICAgICAvKipcbiAgICAgICAgICogTW9kZWxQcm90byBwcm9kdWNlclZlcnNpb24uXG4gICAgICAgICAqIEBtZW1iZXIge3N0cmluZ30gcHJvZHVjZXJWZXJzaW9uXG4gICAgICAgICAqIEBtZW1iZXJvZiBvbm54Lk1vZGVsUHJvdG9cbiAgICAgICAgICogQGluc3RhbmNlXG4gICAgICAgICAqL1xuICAgICAgICBNb2RlbFByb3RvLnByb3RvdHlwZS5wcm9kdWNlclZlcnNpb24gPSBcIlwiO1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBNb2RlbFByb3RvIGRvbWFpbi5cbiAgICAgICAgICogQG1lbWJlciB7c3RyaW5nfSBkb21haW5cbiAgICAgICAgICogQG1lbWJlcm9mIG9ubnguTW9kZWxQcm90b1xuICAgICAgICAgKiBAaW5zdGFuY2VcbiAgICAgICAgICovXG4gICAgICAgIE1vZGVsUHJvdG8ucHJvdG90eXBlLmRvbWFpbiA9IFwiXCI7XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIE1vZGVsUHJvdG8gbW9kZWxWZXJzaW9uLlxuICAgICAgICAgKiBAbWVtYmVyIHtudW1iZXJ8TG9uZ30gbW9kZWxWZXJzaW9uXG4gICAgICAgICAqIEBtZW1iZXJvZiBvbm54Lk1vZGVsUHJvdG9cbiAgICAgICAgICogQGluc3RhbmNlXG4gICAgICAgICAqL1xuICAgICAgICBNb2RlbFByb3RvLnByb3RvdHlwZS5tb2RlbFZlcnNpb24gPSAkdXRpbC5Mb25nID8gJHV0aWwuTG9uZy5mcm9tQml0cygwLDAsZmFsc2UpIDogMDtcblxuICAgICAgICAvKipcbiAgICAgICAgICogTW9kZWxQcm90byBkb2NTdHJpbmcuXG4gICAgICAgICAqIEBtZW1iZXIge3N0cmluZ30gZG9jU3RyaW5nXG4gICAgICAgICAqIEBtZW1iZXJvZiBvbm54Lk1vZGVsUHJvdG9cbiAgICAgICAgICogQGluc3RhbmNlXG4gICAgICAgICAqL1xuICAgICAgICBNb2RlbFByb3RvLnByb3RvdHlwZS5kb2NTdHJpbmcgPSBcIlwiO1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBNb2RlbFByb3RvIGdyYXBoLlxuICAgICAgICAgKiBAbWVtYmVyIHtvbm54LklHcmFwaFByb3RvfG51bGx8dW5kZWZpbmVkfSBncmFwaFxuICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueC5Nb2RlbFByb3RvXG4gICAgICAgICAqIEBpbnN0YW5jZVxuICAgICAgICAgKi9cbiAgICAgICAgTW9kZWxQcm90by5wcm90b3R5cGUuZ3JhcGggPSBudWxsO1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBNb2RlbFByb3RvIG1ldGFkYXRhUHJvcHMuXG4gICAgICAgICAqIEBtZW1iZXIge0FycmF5Ljxvbm54LklTdHJpbmdTdHJpbmdFbnRyeVByb3RvPn0gbWV0YWRhdGFQcm9wc1xuICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueC5Nb2RlbFByb3RvXG4gICAgICAgICAqIEBpbnN0YW5jZVxuICAgICAgICAgKi9cbiAgICAgICAgTW9kZWxQcm90by5wcm90b3R5cGUubWV0YWRhdGFQcm9wcyA9ICR1dGlsLmVtcHR5QXJyYXk7XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIENyZWF0ZXMgYSBuZXcgTW9kZWxQcm90byBpbnN0YW5jZSB1c2luZyB0aGUgc3BlY2lmaWVkIHByb3BlcnRpZXMuXG4gICAgICAgICAqIEBmdW5jdGlvbiBjcmVhdGVcbiAgICAgICAgICogQG1lbWJlcm9mIG9ubnguTW9kZWxQcm90b1xuICAgICAgICAgKiBAc3RhdGljXG4gICAgICAgICAqIEBwYXJhbSB7b25ueC5JTW9kZWxQcm90bz19IFtwcm9wZXJ0aWVzXSBQcm9wZXJ0aWVzIHRvIHNldFxuICAgICAgICAgKiBAcmV0dXJucyB7b25ueC5Nb2RlbFByb3RvfSBNb2RlbFByb3RvIGluc3RhbmNlXG4gICAgICAgICAqL1xuICAgICAgICBNb2RlbFByb3RvLmNyZWF0ZSA9IGZ1bmN0aW9uIGNyZWF0ZShwcm9wZXJ0aWVzKSB7XG4gICAgICAgICAgICByZXR1cm4gbmV3IE1vZGVsUHJvdG8ocHJvcGVydGllcyk7XG4gICAgICAgIH07XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEVuY29kZXMgdGhlIHNwZWNpZmllZCBNb2RlbFByb3RvIG1lc3NhZ2UuIERvZXMgbm90IGltcGxpY2l0bHkge0BsaW5rIG9ubnguTW9kZWxQcm90by52ZXJpZnl8dmVyaWZ5fSBtZXNzYWdlcy5cbiAgICAgICAgICogQGZ1bmN0aW9uIGVuY29kZVxuICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueC5Nb2RlbFByb3RvXG4gICAgICAgICAqIEBzdGF0aWNcbiAgICAgICAgICogQHBhcmFtIHtvbm54LklNb2RlbFByb3RvfSBtZXNzYWdlIE1vZGVsUHJvdG8gbWVzc2FnZSBvciBwbGFpbiBvYmplY3QgdG8gZW5jb2RlXG4gICAgICAgICAqIEBwYXJhbSB7JHByb3RvYnVmLldyaXRlcn0gW3dyaXRlcl0gV3JpdGVyIHRvIGVuY29kZSB0b1xuICAgICAgICAgKiBAcmV0dXJucyB7JHByb3RvYnVmLldyaXRlcn0gV3JpdGVyXG4gICAgICAgICAqL1xuICAgICAgICBNb2RlbFByb3RvLmVuY29kZSA9IGZ1bmN0aW9uIGVuY29kZShtZXNzYWdlLCB3cml0ZXIpIHtcbiAgICAgICAgICAgIGlmICghd3JpdGVyKVxuICAgICAgICAgICAgICAgIHdyaXRlciA9ICRXcml0ZXIuY3JlYXRlKCk7XG4gICAgICAgICAgICBpZiAobWVzc2FnZS5pclZlcnNpb24gIT0gbnVsbCAmJiBtZXNzYWdlLmhhc093blByb3BlcnR5KFwiaXJWZXJzaW9uXCIpKVxuICAgICAgICAgICAgICAgIHdyaXRlci51aW50MzIoLyogaWQgMSwgd2lyZVR5cGUgMCA9Ki84KS5pbnQ2NChtZXNzYWdlLmlyVmVyc2lvbik7XG4gICAgICAgICAgICBpZiAobWVzc2FnZS5wcm9kdWNlck5hbWUgIT0gbnVsbCAmJiBtZXNzYWdlLmhhc093blByb3BlcnR5KFwicHJvZHVjZXJOYW1lXCIpKVxuICAgICAgICAgICAgICAgIHdyaXRlci51aW50MzIoLyogaWQgMiwgd2lyZVR5cGUgMiA9Ki8xOCkuc3RyaW5nKG1lc3NhZ2UucHJvZHVjZXJOYW1lKTtcbiAgICAgICAgICAgIGlmIChtZXNzYWdlLnByb2R1Y2VyVmVyc2lvbiAhPSBudWxsICYmIG1lc3NhZ2UuaGFzT3duUHJvcGVydHkoXCJwcm9kdWNlclZlcnNpb25cIikpXG4gICAgICAgICAgICAgICAgd3JpdGVyLnVpbnQzMigvKiBpZCAzLCB3aXJlVHlwZSAyID0qLzI2KS5zdHJpbmcobWVzc2FnZS5wcm9kdWNlclZlcnNpb24pO1xuICAgICAgICAgICAgaWYgKG1lc3NhZ2UuZG9tYWluICE9IG51bGwgJiYgbWVzc2FnZS5oYXNPd25Qcm9wZXJ0eShcImRvbWFpblwiKSlcbiAgICAgICAgICAgICAgICB3cml0ZXIudWludDMyKC8qIGlkIDQsIHdpcmVUeXBlIDIgPSovMzQpLnN0cmluZyhtZXNzYWdlLmRvbWFpbik7XG4gICAgICAgICAgICBpZiAobWVzc2FnZS5tb2RlbFZlcnNpb24gIT0gbnVsbCAmJiBtZXNzYWdlLmhhc093blByb3BlcnR5KFwibW9kZWxWZXJzaW9uXCIpKVxuICAgICAgICAgICAgICAgIHdyaXRlci51aW50MzIoLyogaWQgNSwgd2lyZVR5cGUgMCA9Ki80MCkuaW50NjQobWVzc2FnZS5tb2RlbFZlcnNpb24pO1xuICAgICAgICAgICAgaWYgKG1lc3NhZ2UuZG9jU3RyaW5nICE9IG51bGwgJiYgbWVzc2FnZS5oYXNPd25Qcm9wZXJ0eShcImRvY1N0cmluZ1wiKSlcbiAgICAgICAgICAgICAgICB3cml0ZXIudWludDMyKC8qIGlkIDYsIHdpcmVUeXBlIDIgPSovNTApLnN0cmluZyhtZXNzYWdlLmRvY1N0cmluZyk7XG4gICAgICAgICAgICBpZiAobWVzc2FnZS5ncmFwaCAhPSBudWxsICYmIG1lc3NhZ2UuaGFzT3duUHJvcGVydHkoXCJncmFwaFwiKSlcbiAgICAgICAgICAgICAgICAkcm9vdC5vbm54LkdyYXBoUHJvdG8uZW5jb2RlKG1lc3NhZ2UuZ3JhcGgsIHdyaXRlci51aW50MzIoLyogaWQgNywgd2lyZVR5cGUgMiA9Ki81OCkuZm9yaygpKS5sZGVsaW0oKTtcbiAgICAgICAgICAgIGlmIChtZXNzYWdlLm9wc2V0SW1wb3J0ICE9IG51bGwgJiYgbWVzc2FnZS5vcHNldEltcG9ydC5sZW5ndGgpXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBtZXNzYWdlLm9wc2V0SW1wb3J0Lmxlbmd0aDsgKytpKVxuICAgICAgICAgICAgICAgICAgICAkcm9vdC5vbm54Lk9wZXJhdG9yU2V0SWRQcm90by5lbmNvZGUobWVzc2FnZS5vcHNldEltcG9ydFtpXSwgd3JpdGVyLnVpbnQzMigvKiBpZCA4LCB3aXJlVHlwZSAyID0qLzY2KS5mb3JrKCkpLmxkZWxpbSgpO1xuICAgICAgICAgICAgaWYgKG1lc3NhZ2UubWV0YWRhdGFQcm9wcyAhPSBudWxsICYmIG1lc3NhZ2UubWV0YWRhdGFQcm9wcy5sZW5ndGgpXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBtZXNzYWdlLm1ldGFkYXRhUHJvcHMubGVuZ3RoOyArK2kpXG4gICAgICAgICAgICAgICAgICAgICRyb290Lm9ubnguU3RyaW5nU3RyaW5nRW50cnlQcm90by5lbmNvZGUobWVzc2FnZS5tZXRhZGF0YVByb3BzW2ldLCB3cml0ZXIudWludDMyKC8qIGlkIDE0LCB3aXJlVHlwZSAyID0qLzExNCkuZm9yaygpKS5sZGVsaW0oKTtcbiAgICAgICAgICAgIHJldHVybiB3cml0ZXI7XG4gICAgICAgIH07XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEVuY29kZXMgdGhlIHNwZWNpZmllZCBNb2RlbFByb3RvIG1lc3NhZ2UsIGxlbmd0aCBkZWxpbWl0ZWQuIERvZXMgbm90IGltcGxpY2l0bHkge0BsaW5rIG9ubnguTW9kZWxQcm90by52ZXJpZnl8dmVyaWZ5fSBtZXNzYWdlcy5cbiAgICAgICAgICogQGZ1bmN0aW9uIGVuY29kZURlbGltaXRlZFxuICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueC5Nb2RlbFByb3RvXG4gICAgICAgICAqIEBzdGF0aWNcbiAgICAgICAgICogQHBhcmFtIHtvbm54LklNb2RlbFByb3RvfSBtZXNzYWdlIE1vZGVsUHJvdG8gbWVzc2FnZSBvciBwbGFpbiBvYmplY3QgdG8gZW5jb2RlXG4gICAgICAgICAqIEBwYXJhbSB7JHByb3RvYnVmLldyaXRlcn0gW3dyaXRlcl0gV3JpdGVyIHRvIGVuY29kZSB0b1xuICAgICAgICAgKiBAcmV0dXJucyB7JHByb3RvYnVmLldyaXRlcn0gV3JpdGVyXG4gICAgICAgICAqL1xuICAgICAgICBNb2RlbFByb3RvLmVuY29kZURlbGltaXRlZCA9IGZ1bmN0aW9uIGVuY29kZURlbGltaXRlZChtZXNzYWdlLCB3cml0ZXIpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmVuY29kZShtZXNzYWdlLCB3cml0ZXIpLmxkZWxpbSgpO1xuICAgICAgICB9O1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBEZWNvZGVzIGEgTW9kZWxQcm90byBtZXNzYWdlIGZyb20gdGhlIHNwZWNpZmllZCByZWFkZXIgb3IgYnVmZmVyLlxuICAgICAgICAgKiBAZnVuY3Rpb24gZGVjb2RlXG4gICAgICAgICAqIEBtZW1iZXJvZiBvbm54Lk1vZGVsUHJvdG9cbiAgICAgICAgICogQHN0YXRpY1xuICAgICAgICAgKiBAcGFyYW0geyRwcm90b2J1Zi5SZWFkZXJ8VWludDhBcnJheX0gcmVhZGVyIFJlYWRlciBvciBidWZmZXIgdG8gZGVjb2RlIGZyb21cbiAgICAgICAgICogQHBhcmFtIHtudW1iZXJ9IFtsZW5ndGhdIE1lc3NhZ2UgbGVuZ3RoIGlmIGtub3duIGJlZm9yZWhhbmRcbiAgICAgICAgICogQHJldHVybnMge29ubnguTW9kZWxQcm90b30gTW9kZWxQcm90b1xuICAgICAgICAgKiBAdGhyb3dzIHtFcnJvcn0gSWYgdGhlIHBheWxvYWQgaXMgbm90IGEgcmVhZGVyIG9yIHZhbGlkIGJ1ZmZlclxuICAgICAgICAgKiBAdGhyb3dzIHskcHJvdG9idWYudXRpbC5Qcm90b2NvbEVycm9yfSBJZiByZXF1aXJlZCBmaWVsZHMgYXJlIG1pc3NpbmdcbiAgICAgICAgICovXG4gICAgICAgIE1vZGVsUHJvdG8uZGVjb2RlID0gZnVuY3Rpb24gZGVjb2RlKHJlYWRlciwgbGVuZ3RoKSB7XG4gICAgICAgICAgICBpZiAoIShyZWFkZXIgaW5zdGFuY2VvZiAkUmVhZGVyKSlcbiAgICAgICAgICAgICAgICByZWFkZXIgPSAkUmVhZGVyLmNyZWF0ZShyZWFkZXIpO1xuICAgICAgICAgICAgdmFyIGVuZCA9IGxlbmd0aCA9PT0gdW5kZWZpbmVkID8gcmVhZGVyLmxlbiA6IHJlYWRlci5wb3MgKyBsZW5ndGgsIG1lc3NhZ2UgPSBuZXcgJHJvb3Qub25ueC5Nb2RlbFByb3RvKCk7XG4gICAgICAgICAgICB3aGlsZSAocmVhZGVyLnBvcyA8IGVuZCkge1xuICAgICAgICAgICAgICAgIHZhciB0YWcgPSByZWFkZXIudWludDMyKCk7XG4gICAgICAgICAgICAgICAgc3dpdGNoICh0YWcgPj4+IDMpIHtcbiAgICAgICAgICAgICAgICBjYXNlIDE6XG4gICAgICAgICAgICAgICAgICAgIG1lc3NhZ2UuaXJWZXJzaW9uID0gcmVhZGVyLmludDY0KCk7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgODpcbiAgICAgICAgICAgICAgICAgICAgaWYgKCEobWVzc2FnZS5vcHNldEltcG9ydCAmJiBtZXNzYWdlLm9wc2V0SW1wb3J0Lmxlbmd0aCkpXG4gICAgICAgICAgICAgICAgICAgICAgICBtZXNzYWdlLm9wc2V0SW1wb3J0ID0gW107XG4gICAgICAgICAgICAgICAgICAgIG1lc3NhZ2Uub3BzZXRJbXBvcnQucHVzaCgkcm9vdC5vbm54Lk9wZXJhdG9yU2V0SWRQcm90by5kZWNvZGUocmVhZGVyLCByZWFkZXIudWludDMyKCkpKTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSAyOlxuICAgICAgICAgICAgICAgICAgICBtZXNzYWdlLnByb2R1Y2VyTmFtZSA9IHJlYWRlci5zdHJpbmcoKTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSAzOlxuICAgICAgICAgICAgICAgICAgICBtZXNzYWdlLnByb2R1Y2VyVmVyc2lvbiA9IHJlYWRlci5zdHJpbmcoKTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSA0OlxuICAgICAgICAgICAgICAgICAgICBtZXNzYWdlLmRvbWFpbiA9IHJlYWRlci5zdHJpbmcoKTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSA1OlxuICAgICAgICAgICAgICAgICAgICBtZXNzYWdlLm1vZGVsVmVyc2lvbiA9IHJlYWRlci5pbnQ2NCgpO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlIDY6XG4gICAgICAgICAgICAgICAgICAgIG1lc3NhZ2UuZG9jU3RyaW5nID0gcmVhZGVyLnN0cmluZygpO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlIDc6XG4gICAgICAgICAgICAgICAgICAgIG1lc3NhZ2UuZ3JhcGggPSAkcm9vdC5vbm54LkdyYXBoUHJvdG8uZGVjb2RlKHJlYWRlciwgcmVhZGVyLnVpbnQzMigpKTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSAxNDpcbiAgICAgICAgICAgICAgICAgICAgaWYgKCEobWVzc2FnZS5tZXRhZGF0YVByb3BzICYmIG1lc3NhZ2UubWV0YWRhdGFQcm9wcy5sZW5ndGgpKVxuICAgICAgICAgICAgICAgICAgICAgICAgbWVzc2FnZS5tZXRhZGF0YVByb3BzID0gW107XG4gICAgICAgICAgICAgICAgICAgIG1lc3NhZ2UubWV0YWRhdGFQcm9wcy5wdXNoKCRyb290Lm9ubnguU3RyaW5nU3RyaW5nRW50cnlQcm90by5kZWNvZGUocmVhZGVyLCByZWFkZXIudWludDMyKCkpKTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICAgICAgcmVhZGVyLnNraXBUeXBlKHRhZyAmIDcpO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gbWVzc2FnZTtcbiAgICAgICAgfTtcblxuICAgICAgICAvKipcbiAgICAgICAgICogRGVjb2RlcyBhIE1vZGVsUHJvdG8gbWVzc2FnZSBmcm9tIHRoZSBzcGVjaWZpZWQgcmVhZGVyIG9yIGJ1ZmZlciwgbGVuZ3RoIGRlbGltaXRlZC5cbiAgICAgICAgICogQGZ1bmN0aW9uIGRlY29kZURlbGltaXRlZFxuICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueC5Nb2RlbFByb3RvXG4gICAgICAgICAqIEBzdGF0aWNcbiAgICAgICAgICogQHBhcmFtIHskcHJvdG9idWYuUmVhZGVyfFVpbnQ4QXJyYXl9IHJlYWRlciBSZWFkZXIgb3IgYnVmZmVyIHRvIGRlY29kZSBmcm9tXG4gICAgICAgICAqIEByZXR1cm5zIHtvbm54Lk1vZGVsUHJvdG99IE1vZGVsUHJvdG9cbiAgICAgICAgICogQHRocm93cyB7RXJyb3J9IElmIHRoZSBwYXlsb2FkIGlzIG5vdCBhIHJlYWRlciBvciB2YWxpZCBidWZmZXJcbiAgICAgICAgICogQHRocm93cyB7JHByb3RvYnVmLnV0aWwuUHJvdG9jb2xFcnJvcn0gSWYgcmVxdWlyZWQgZmllbGRzIGFyZSBtaXNzaW5nXG4gICAgICAgICAqL1xuICAgICAgICBNb2RlbFByb3RvLmRlY29kZURlbGltaXRlZCA9IGZ1bmN0aW9uIGRlY29kZURlbGltaXRlZChyZWFkZXIpIHtcbiAgICAgICAgICAgIGlmICghKHJlYWRlciBpbnN0YW5jZW9mICRSZWFkZXIpKVxuICAgICAgICAgICAgICAgIHJlYWRlciA9IG5ldyAkUmVhZGVyKHJlYWRlcik7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5kZWNvZGUocmVhZGVyLCByZWFkZXIudWludDMyKCkpO1xuICAgICAgICB9O1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBWZXJpZmllcyBhIE1vZGVsUHJvdG8gbWVzc2FnZS5cbiAgICAgICAgICogQGZ1bmN0aW9uIHZlcmlmeVxuICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueC5Nb2RlbFByb3RvXG4gICAgICAgICAqIEBzdGF0aWNcbiAgICAgICAgICogQHBhcmFtIHtPYmplY3QuPHN0cmluZywqPn0gbWVzc2FnZSBQbGFpbiBvYmplY3QgdG8gdmVyaWZ5XG4gICAgICAgICAqIEByZXR1cm5zIHtzdHJpbmd8bnVsbH0gYG51bGxgIGlmIHZhbGlkLCBvdGhlcndpc2UgdGhlIHJlYXNvbiB3aHkgaXQgaXMgbm90XG4gICAgICAgICAqL1xuICAgICAgICBNb2RlbFByb3RvLnZlcmlmeSA9IGZ1bmN0aW9uIHZlcmlmeShtZXNzYWdlKSB7XG4gICAgICAgICAgICBpZiAodHlwZW9mIG1lc3NhZ2UgIT09IFwib2JqZWN0XCIgfHwgbWVzc2FnZSA9PT0gbnVsbClcbiAgICAgICAgICAgICAgICByZXR1cm4gXCJvYmplY3QgZXhwZWN0ZWRcIjtcbiAgICAgICAgICAgIGlmIChtZXNzYWdlLmlyVmVyc2lvbiAhPSBudWxsICYmIG1lc3NhZ2UuaGFzT3duUHJvcGVydHkoXCJpclZlcnNpb25cIikpXG4gICAgICAgICAgICAgICAgaWYgKCEkdXRpbC5pc0ludGVnZXIobWVzc2FnZS5pclZlcnNpb24pICYmICEobWVzc2FnZS5pclZlcnNpb24gJiYgJHV0aWwuaXNJbnRlZ2VyKG1lc3NhZ2UuaXJWZXJzaW9uLmxvdykgJiYgJHV0aWwuaXNJbnRlZ2VyKG1lc3NhZ2UuaXJWZXJzaW9uLmhpZ2gpKSlcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFwiaXJWZXJzaW9uOiBpbnRlZ2VyfExvbmcgZXhwZWN0ZWRcIjtcbiAgICAgICAgICAgIGlmIChtZXNzYWdlLm9wc2V0SW1wb3J0ICE9IG51bGwgJiYgbWVzc2FnZS5oYXNPd25Qcm9wZXJ0eShcIm9wc2V0SW1wb3J0XCIpKSB7XG4gICAgICAgICAgICAgICAgaWYgKCFBcnJheS5pc0FycmF5KG1lc3NhZ2Uub3BzZXRJbXBvcnQpKVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gXCJvcHNldEltcG9ydDogYXJyYXkgZXhwZWN0ZWRcIjtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG1lc3NhZ2Uub3BzZXRJbXBvcnQubGVuZ3RoOyArK2kpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGVycm9yID0gJHJvb3Qub25ueC5PcGVyYXRvclNldElkUHJvdG8udmVyaWZ5KG1lc3NhZ2Uub3BzZXRJbXBvcnRbaV0pO1xuICAgICAgICAgICAgICAgICAgICBpZiAoZXJyb3IpXG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gXCJvcHNldEltcG9ydC5cIiArIGVycm9yO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChtZXNzYWdlLnByb2R1Y2VyTmFtZSAhPSBudWxsICYmIG1lc3NhZ2UuaGFzT3duUHJvcGVydHkoXCJwcm9kdWNlck5hbWVcIikpXG4gICAgICAgICAgICAgICAgaWYgKCEkdXRpbC5pc1N0cmluZyhtZXNzYWdlLnByb2R1Y2VyTmFtZSkpXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBcInByb2R1Y2VyTmFtZTogc3RyaW5nIGV4cGVjdGVkXCI7XG4gICAgICAgICAgICBpZiAobWVzc2FnZS5wcm9kdWNlclZlcnNpb24gIT0gbnVsbCAmJiBtZXNzYWdlLmhhc093blByb3BlcnR5KFwicHJvZHVjZXJWZXJzaW9uXCIpKVxuICAgICAgICAgICAgICAgIGlmICghJHV0aWwuaXNTdHJpbmcobWVzc2FnZS5wcm9kdWNlclZlcnNpb24pKVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gXCJwcm9kdWNlclZlcnNpb246IHN0cmluZyBleHBlY3RlZFwiO1xuICAgICAgICAgICAgaWYgKG1lc3NhZ2UuZG9tYWluICE9IG51bGwgJiYgbWVzc2FnZS5oYXNPd25Qcm9wZXJ0eShcImRvbWFpblwiKSlcbiAgICAgICAgICAgICAgICBpZiAoISR1dGlsLmlzU3RyaW5nKG1lc3NhZ2UuZG9tYWluKSlcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFwiZG9tYWluOiBzdHJpbmcgZXhwZWN0ZWRcIjtcbiAgICAgICAgICAgIGlmIChtZXNzYWdlLm1vZGVsVmVyc2lvbiAhPSBudWxsICYmIG1lc3NhZ2UuaGFzT3duUHJvcGVydHkoXCJtb2RlbFZlcnNpb25cIikpXG4gICAgICAgICAgICAgICAgaWYgKCEkdXRpbC5pc0ludGVnZXIobWVzc2FnZS5tb2RlbFZlcnNpb24pICYmICEobWVzc2FnZS5tb2RlbFZlcnNpb24gJiYgJHV0aWwuaXNJbnRlZ2VyKG1lc3NhZ2UubW9kZWxWZXJzaW9uLmxvdykgJiYgJHV0aWwuaXNJbnRlZ2VyKG1lc3NhZ2UubW9kZWxWZXJzaW9uLmhpZ2gpKSlcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFwibW9kZWxWZXJzaW9uOiBpbnRlZ2VyfExvbmcgZXhwZWN0ZWRcIjtcbiAgICAgICAgICAgIGlmIChtZXNzYWdlLmRvY1N0cmluZyAhPSBudWxsICYmIG1lc3NhZ2UuaGFzT3duUHJvcGVydHkoXCJkb2NTdHJpbmdcIikpXG4gICAgICAgICAgICAgICAgaWYgKCEkdXRpbC5pc1N0cmluZyhtZXNzYWdlLmRvY1N0cmluZykpXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBcImRvY1N0cmluZzogc3RyaW5nIGV4cGVjdGVkXCI7XG4gICAgICAgICAgICBpZiAobWVzc2FnZS5ncmFwaCAhPSBudWxsICYmIG1lc3NhZ2UuaGFzT3duUHJvcGVydHkoXCJncmFwaFwiKSkge1xuICAgICAgICAgICAgICAgIHZhciBlcnJvciA9ICRyb290Lm9ubnguR3JhcGhQcm90by52ZXJpZnkobWVzc2FnZS5ncmFwaCk7XG4gICAgICAgICAgICAgICAgaWYgKGVycm9yKVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gXCJncmFwaC5cIiArIGVycm9yO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG1lc3NhZ2UubWV0YWRhdGFQcm9wcyAhPSBudWxsICYmIG1lc3NhZ2UuaGFzT3duUHJvcGVydHkoXCJtZXRhZGF0YVByb3BzXCIpKSB7XG4gICAgICAgICAgICAgICAgaWYgKCFBcnJheS5pc0FycmF5KG1lc3NhZ2UubWV0YWRhdGFQcm9wcykpXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBcIm1ldGFkYXRhUHJvcHM6IGFycmF5IGV4cGVjdGVkXCI7XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBtZXNzYWdlLm1ldGFkYXRhUHJvcHMubGVuZ3RoOyArK2kpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGVycm9yID0gJHJvb3Qub25ueC5TdHJpbmdTdHJpbmdFbnRyeVByb3RvLnZlcmlmeShtZXNzYWdlLm1ldGFkYXRhUHJvcHNbaV0pO1xuICAgICAgICAgICAgICAgICAgICBpZiAoZXJyb3IpXG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gXCJtZXRhZGF0YVByb3BzLlwiICsgZXJyb3I7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgIH07XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIENyZWF0ZXMgYSBNb2RlbFByb3RvIG1lc3NhZ2UgZnJvbSBhIHBsYWluIG9iamVjdC4gQWxzbyBjb252ZXJ0cyB2YWx1ZXMgdG8gdGhlaXIgcmVzcGVjdGl2ZSBpbnRlcm5hbCB0eXBlcy5cbiAgICAgICAgICogQGZ1bmN0aW9uIGZyb21PYmplY3RcbiAgICAgICAgICogQG1lbWJlcm9mIG9ubnguTW9kZWxQcm90b1xuICAgICAgICAgKiBAc3RhdGljXG4gICAgICAgICAqIEBwYXJhbSB7T2JqZWN0LjxzdHJpbmcsKj59IG9iamVjdCBQbGFpbiBvYmplY3RcbiAgICAgICAgICogQHJldHVybnMge29ubnguTW9kZWxQcm90b30gTW9kZWxQcm90b1xuICAgICAgICAgKi9cbiAgICAgICAgTW9kZWxQcm90by5mcm9tT2JqZWN0ID0gZnVuY3Rpb24gZnJvbU9iamVjdChvYmplY3QpIHtcbiAgICAgICAgICAgIGlmIChvYmplY3QgaW5zdGFuY2VvZiAkcm9vdC5vbm54Lk1vZGVsUHJvdG8pXG4gICAgICAgICAgICAgICAgcmV0dXJuIG9iamVjdDtcbiAgICAgICAgICAgIHZhciBtZXNzYWdlID0gbmV3ICRyb290Lm9ubnguTW9kZWxQcm90bygpO1xuICAgICAgICAgICAgaWYgKG9iamVjdC5pclZlcnNpb24gIT0gbnVsbClcbiAgICAgICAgICAgICAgICBpZiAoJHV0aWwuTG9uZylcbiAgICAgICAgICAgICAgICAgICAgKG1lc3NhZ2UuaXJWZXJzaW9uID0gJHV0aWwuTG9uZy5mcm9tVmFsdWUob2JqZWN0LmlyVmVyc2lvbikpLnVuc2lnbmVkID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgZWxzZSBpZiAodHlwZW9mIG9iamVjdC5pclZlcnNpb24gPT09IFwic3RyaW5nXCIpXG4gICAgICAgICAgICAgICAgICAgIG1lc3NhZ2UuaXJWZXJzaW9uID0gcGFyc2VJbnQob2JqZWN0LmlyVmVyc2lvbiwgMTApO1xuICAgICAgICAgICAgICAgIGVsc2UgaWYgKHR5cGVvZiBvYmplY3QuaXJWZXJzaW9uID09PSBcIm51bWJlclwiKVxuICAgICAgICAgICAgICAgICAgICBtZXNzYWdlLmlyVmVyc2lvbiA9IG9iamVjdC5pclZlcnNpb247XG4gICAgICAgICAgICAgICAgZWxzZSBpZiAodHlwZW9mIG9iamVjdC5pclZlcnNpb24gPT09IFwib2JqZWN0XCIpXG4gICAgICAgICAgICAgICAgICAgIG1lc3NhZ2UuaXJWZXJzaW9uID0gbmV3ICR1dGlsLkxvbmdCaXRzKG9iamVjdC5pclZlcnNpb24ubG93ID4+PiAwLCBvYmplY3QuaXJWZXJzaW9uLmhpZ2ggPj4+IDApLnRvTnVtYmVyKCk7XG4gICAgICAgICAgICBpZiAob2JqZWN0Lm9wc2V0SW1wb3J0KSB7XG4gICAgICAgICAgICAgICAgaWYgKCFBcnJheS5pc0FycmF5KG9iamVjdC5vcHNldEltcG9ydCkpXG4gICAgICAgICAgICAgICAgICAgIHRocm93IFR5cGVFcnJvcihcIi5vbm54Lk1vZGVsUHJvdG8ub3BzZXRJbXBvcnQ6IGFycmF5IGV4cGVjdGVkXCIpO1xuICAgICAgICAgICAgICAgIG1lc3NhZ2Uub3BzZXRJbXBvcnQgPSBbXTtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG9iamVjdC5vcHNldEltcG9ydC5sZW5ndGg7ICsraSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAodHlwZW9mIG9iamVjdC5vcHNldEltcG9ydFtpXSAhPT0gXCJvYmplY3RcIilcbiAgICAgICAgICAgICAgICAgICAgICAgIHRocm93IFR5cGVFcnJvcihcIi5vbm54Lk1vZGVsUHJvdG8ub3BzZXRJbXBvcnQ6IG9iamVjdCBleHBlY3RlZFwiKTtcbiAgICAgICAgICAgICAgICAgICAgbWVzc2FnZS5vcHNldEltcG9ydFtpXSA9ICRyb290Lm9ubnguT3BlcmF0b3JTZXRJZFByb3RvLmZyb21PYmplY3Qob2JqZWN0Lm9wc2V0SW1wb3J0W2ldKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAob2JqZWN0LnByb2R1Y2VyTmFtZSAhPSBudWxsKVxuICAgICAgICAgICAgICAgIG1lc3NhZ2UucHJvZHVjZXJOYW1lID0gU3RyaW5nKG9iamVjdC5wcm9kdWNlck5hbWUpO1xuICAgICAgICAgICAgaWYgKG9iamVjdC5wcm9kdWNlclZlcnNpb24gIT0gbnVsbClcbiAgICAgICAgICAgICAgICBtZXNzYWdlLnByb2R1Y2VyVmVyc2lvbiA9IFN0cmluZyhvYmplY3QucHJvZHVjZXJWZXJzaW9uKTtcbiAgICAgICAgICAgIGlmIChvYmplY3QuZG9tYWluICE9IG51bGwpXG4gICAgICAgICAgICAgICAgbWVzc2FnZS5kb21haW4gPSBTdHJpbmcob2JqZWN0LmRvbWFpbik7XG4gICAgICAgICAgICBpZiAob2JqZWN0Lm1vZGVsVmVyc2lvbiAhPSBudWxsKVxuICAgICAgICAgICAgICAgIGlmICgkdXRpbC5Mb25nKVxuICAgICAgICAgICAgICAgICAgICAobWVzc2FnZS5tb2RlbFZlcnNpb24gPSAkdXRpbC5Mb25nLmZyb21WYWx1ZShvYmplY3QubW9kZWxWZXJzaW9uKSkudW5zaWduZWQgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICBlbHNlIGlmICh0eXBlb2Ygb2JqZWN0Lm1vZGVsVmVyc2lvbiA9PT0gXCJzdHJpbmdcIilcbiAgICAgICAgICAgICAgICAgICAgbWVzc2FnZS5tb2RlbFZlcnNpb24gPSBwYXJzZUludChvYmplY3QubW9kZWxWZXJzaW9uLCAxMCk7XG4gICAgICAgICAgICAgICAgZWxzZSBpZiAodHlwZW9mIG9iamVjdC5tb2RlbFZlcnNpb24gPT09IFwibnVtYmVyXCIpXG4gICAgICAgICAgICAgICAgICAgIG1lc3NhZ2UubW9kZWxWZXJzaW9uID0gb2JqZWN0Lm1vZGVsVmVyc2lvbjtcbiAgICAgICAgICAgICAgICBlbHNlIGlmICh0eXBlb2Ygb2JqZWN0Lm1vZGVsVmVyc2lvbiA9PT0gXCJvYmplY3RcIilcbiAgICAgICAgICAgICAgICAgICAgbWVzc2FnZS5tb2RlbFZlcnNpb24gPSBuZXcgJHV0aWwuTG9uZ0JpdHMob2JqZWN0Lm1vZGVsVmVyc2lvbi5sb3cgPj4+IDAsIG9iamVjdC5tb2RlbFZlcnNpb24uaGlnaCA+Pj4gMCkudG9OdW1iZXIoKTtcbiAgICAgICAgICAgIGlmIChvYmplY3QuZG9jU3RyaW5nICE9IG51bGwpXG4gICAgICAgICAgICAgICAgbWVzc2FnZS5kb2NTdHJpbmcgPSBTdHJpbmcob2JqZWN0LmRvY1N0cmluZyk7XG4gICAgICAgICAgICBpZiAob2JqZWN0LmdyYXBoICE9IG51bGwpIHtcbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIG9iamVjdC5ncmFwaCAhPT0gXCJvYmplY3RcIilcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgVHlwZUVycm9yKFwiLm9ubnguTW9kZWxQcm90by5ncmFwaDogb2JqZWN0IGV4cGVjdGVkXCIpO1xuICAgICAgICAgICAgICAgIG1lc3NhZ2UuZ3JhcGggPSAkcm9vdC5vbm54LkdyYXBoUHJvdG8uZnJvbU9iamVjdChvYmplY3QuZ3JhcGgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG9iamVjdC5tZXRhZGF0YVByb3BzKSB7XG4gICAgICAgICAgICAgICAgaWYgKCFBcnJheS5pc0FycmF5KG9iamVjdC5tZXRhZGF0YVByb3BzKSlcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgVHlwZUVycm9yKFwiLm9ubnguTW9kZWxQcm90by5tZXRhZGF0YVByb3BzOiBhcnJheSBleHBlY3RlZFwiKTtcbiAgICAgICAgICAgICAgICBtZXNzYWdlLm1ldGFkYXRhUHJvcHMgPSBbXTtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG9iamVjdC5tZXRhZGF0YVByb3BzLmxlbmd0aDsgKytpKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2Ygb2JqZWN0Lm1ldGFkYXRhUHJvcHNbaV0gIT09IFwib2JqZWN0XCIpXG4gICAgICAgICAgICAgICAgICAgICAgICB0aHJvdyBUeXBlRXJyb3IoXCIub25ueC5Nb2RlbFByb3RvLm1ldGFkYXRhUHJvcHM6IG9iamVjdCBleHBlY3RlZFwiKTtcbiAgICAgICAgICAgICAgICAgICAgbWVzc2FnZS5tZXRhZGF0YVByb3BzW2ldID0gJHJvb3Qub25ueC5TdHJpbmdTdHJpbmdFbnRyeVByb3RvLmZyb21PYmplY3Qob2JqZWN0Lm1ldGFkYXRhUHJvcHNbaV0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBtZXNzYWdlO1xuICAgICAgICB9O1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBDcmVhdGVzIGEgcGxhaW4gb2JqZWN0IGZyb20gYSBNb2RlbFByb3RvIG1lc3NhZ2UuIEFsc28gY29udmVydHMgdmFsdWVzIHRvIG90aGVyIHR5cGVzIGlmIHNwZWNpZmllZC5cbiAgICAgICAgICogQGZ1bmN0aW9uIHRvT2JqZWN0XG4gICAgICAgICAqIEBtZW1iZXJvZiBvbm54Lk1vZGVsUHJvdG9cbiAgICAgICAgICogQHN0YXRpY1xuICAgICAgICAgKiBAcGFyYW0ge29ubnguTW9kZWxQcm90b30gbWVzc2FnZSBNb2RlbFByb3RvXG4gICAgICAgICAqIEBwYXJhbSB7JHByb3RvYnVmLklDb252ZXJzaW9uT3B0aW9uc30gW29wdGlvbnNdIENvbnZlcnNpb24gb3B0aW9uc1xuICAgICAgICAgKiBAcmV0dXJucyB7T2JqZWN0LjxzdHJpbmcsKj59IFBsYWluIG9iamVjdFxuICAgICAgICAgKi9cbiAgICAgICAgTW9kZWxQcm90by50b09iamVjdCA9IGZ1bmN0aW9uIHRvT2JqZWN0KG1lc3NhZ2UsIG9wdGlvbnMpIHtcbiAgICAgICAgICAgIGlmICghb3B0aW9ucylcbiAgICAgICAgICAgICAgICBvcHRpb25zID0ge307XG4gICAgICAgICAgICB2YXIgb2JqZWN0ID0ge307XG4gICAgICAgICAgICBpZiAob3B0aW9ucy5hcnJheXMgfHwgb3B0aW9ucy5kZWZhdWx0cykge1xuICAgICAgICAgICAgICAgIG9iamVjdC5vcHNldEltcG9ydCA9IFtdO1xuICAgICAgICAgICAgICAgIG9iamVjdC5tZXRhZGF0YVByb3BzID0gW107XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAob3B0aW9ucy5kZWZhdWx0cykge1xuICAgICAgICAgICAgICAgIGlmICgkdXRpbC5Mb25nKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBsb25nID0gbmV3ICR1dGlsLkxvbmcoMCwgMCwgZmFsc2UpO1xuICAgICAgICAgICAgICAgICAgICBvYmplY3QuaXJWZXJzaW9uID0gb3B0aW9ucy5sb25ncyA9PT0gU3RyaW5nID8gbG9uZy50b1N0cmluZygpIDogb3B0aW9ucy5sb25ncyA9PT0gTnVtYmVyID8gbG9uZy50b051bWJlcigpIDogbG9uZztcbiAgICAgICAgICAgICAgICB9IGVsc2VcbiAgICAgICAgICAgICAgICAgICAgb2JqZWN0LmlyVmVyc2lvbiA9IG9wdGlvbnMubG9uZ3MgPT09IFN0cmluZyA/IFwiMFwiIDogMDtcbiAgICAgICAgICAgICAgICBvYmplY3QucHJvZHVjZXJOYW1lID0gXCJcIjtcbiAgICAgICAgICAgICAgICBvYmplY3QucHJvZHVjZXJWZXJzaW9uID0gXCJcIjtcbiAgICAgICAgICAgICAgICBvYmplY3QuZG9tYWluID0gXCJcIjtcbiAgICAgICAgICAgICAgICBpZiAoJHV0aWwuTG9uZykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgbG9uZyA9IG5ldyAkdXRpbC5Mb25nKDAsIDAsIGZhbHNlKTtcbiAgICAgICAgICAgICAgICAgICAgb2JqZWN0Lm1vZGVsVmVyc2lvbiA9IG9wdGlvbnMubG9uZ3MgPT09IFN0cmluZyA/IGxvbmcudG9TdHJpbmcoKSA6IG9wdGlvbnMubG9uZ3MgPT09IE51bWJlciA/IGxvbmcudG9OdW1iZXIoKSA6IGxvbmc7XG4gICAgICAgICAgICAgICAgfSBlbHNlXG4gICAgICAgICAgICAgICAgICAgIG9iamVjdC5tb2RlbFZlcnNpb24gPSBvcHRpb25zLmxvbmdzID09PSBTdHJpbmcgPyBcIjBcIiA6IDA7XG4gICAgICAgICAgICAgICAgb2JqZWN0LmRvY1N0cmluZyA9IFwiXCI7XG4gICAgICAgICAgICAgICAgb2JqZWN0LmdyYXBoID0gbnVsbDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChtZXNzYWdlLmlyVmVyc2lvbiAhPSBudWxsICYmIG1lc3NhZ2UuaGFzT3duUHJvcGVydHkoXCJpclZlcnNpb25cIikpXG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBtZXNzYWdlLmlyVmVyc2lvbiA9PT0gXCJudW1iZXJcIilcbiAgICAgICAgICAgICAgICAgICAgb2JqZWN0LmlyVmVyc2lvbiA9IG9wdGlvbnMubG9uZ3MgPT09IFN0cmluZyA/IFN0cmluZyhtZXNzYWdlLmlyVmVyc2lvbikgOiBtZXNzYWdlLmlyVmVyc2lvbjtcbiAgICAgICAgICAgICAgICBlbHNlXG4gICAgICAgICAgICAgICAgICAgIG9iamVjdC5pclZlcnNpb24gPSBvcHRpb25zLmxvbmdzID09PSBTdHJpbmcgPyAkdXRpbC5Mb25nLnByb3RvdHlwZS50b1N0cmluZy5jYWxsKG1lc3NhZ2UuaXJWZXJzaW9uKSA6IG9wdGlvbnMubG9uZ3MgPT09IE51bWJlciA/IG5ldyAkdXRpbC5Mb25nQml0cyhtZXNzYWdlLmlyVmVyc2lvbi5sb3cgPj4+IDAsIG1lc3NhZ2UuaXJWZXJzaW9uLmhpZ2ggPj4+IDApLnRvTnVtYmVyKCkgOiBtZXNzYWdlLmlyVmVyc2lvbjtcbiAgICAgICAgICAgIGlmIChtZXNzYWdlLnByb2R1Y2VyTmFtZSAhPSBudWxsICYmIG1lc3NhZ2UuaGFzT3duUHJvcGVydHkoXCJwcm9kdWNlck5hbWVcIikpXG4gICAgICAgICAgICAgICAgb2JqZWN0LnByb2R1Y2VyTmFtZSA9IG1lc3NhZ2UucHJvZHVjZXJOYW1lO1xuICAgICAgICAgICAgaWYgKG1lc3NhZ2UucHJvZHVjZXJWZXJzaW9uICE9IG51bGwgJiYgbWVzc2FnZS5oYXNPd25Qcm9wZXJ0eShcInByb2R1Y2VyVmVyc2lvblwiKSlcbiAgICAgICAgICAgICAgICBvYmplY3QucHJvZHVjZXJWZXJzaW9uID0gbWVzc2FnZS5wcm9kdWNlclZlcnNpb247XG4gICAgICAgICAgICBpZiAobWVzc2FnZS5kb21haW4gIT0gbnVsbCAmJiBtZXNzYWdlLmhhc093blByb3BlcnR5KFwiZG9tYWluXCIpKVxuICAgICAgICAgICAgICAgIG9iamVjdC5kb21haW4gPSBtZXNzYWdlLmRvbWFpbjtcbiAgICAgICAgICAgIGlmIChtZXNzYWdlLm1vZGVsVmVyc2lvbiAhPSBudWxsICYmIG1lc3NhZ2UuaGFzT3duUHJvcGVydHkoXCJtb2RlbFZlcnNpb25cIikpXG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBtZXNzYWdlLm1vZGVsVmVyc2lvbiA9PT0gXCJudW1iZXJcIilcbiAgICAgICAgICAgICAgICAgICAgb2JqZWN0Lm1vZGVsVmVyc2lvbiA9IG9wdGlvbnMubG9uZ3MgPT09IFN0cmluZyA/IFN0cmluZyhtZXNzYWdlLm1vZGVsVmVyc2lvbikgOiBtZXNzYWdlLm1vZGVsVmVyc2lvbjtcbiAgICAgICAgICAgICAgICBlbHNlXG4gICAgICAgICAgICAgICAgICAgIG9iamVjdC5tb2RlbFZlcnNpb24gPSBvcHRpb25zLmxvbmdzID09PSBTdHJpbmcgPyAkdXRpbC5Mb25nLnByb3RvdHlwZS50b1N0cmluZy5jYWxsKG1lc3NhZ2UubW9kZWxWZXJzaW9uKSA6IG9wdGlvbnMubG9uZ3MgPT09IE51bWJlciA/IG5ldyAkdXRpbC5Mb25nQml0cyhtZXNzYWdlLm1vZGVsVmVyc2lvbi5sb3cgPj4+IDAsIG1lc3NhZ2UubW9kZWxWZXJzaW9uLmhpZ2ggPj4+IDApLnRvTnVtYmVyKCkgOiBtZXNzYWdlLm1vZGVsVmVyc2lvbjtcbiAgICAgICAgICAgIGlmIChtZXNzYWdlLmRvY1N0cmluZyAhPSBudWxsICYmIG1lc3NhZ2UuaGFzT3duUHJvcGVydHkoXCJkb2NTdHJpbmdcIikpXG4gICAgICAgICAgICAgICAgb2JqZWN0LmRvY1N0cmluZyA9IG1lc3NhZ2UuZG9jU3RyaW5nO1xuICAgICAgICAgICAgaWYgKG1lc3NhZ2UuZ3JhcGggIT0gbnVsbCAmJiBtZXNzYWdlLmhhc093blByb3BlcnR5KFwiZ3JhcGhcIikpXG4gICAgICAgICAgICAgICAgb2JqZWN0LmdyYXBoID0gJHJvb3Qub25ueC5HcmFwaFByb3RvLnRvT2JqZWN0KG1lc3NhZ2UuZ3JhcGgsIG9wdGlvbnMpO1xuICAgICAgICAgICAgaWYgKG1lc3NhZ2Uub3BzZXRJbXBvcnQgJiYgbWVzc2FnZS5vcHNldEltcG9ydC5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICBvYmplY3Qub3BzZXRJbXBvcnQgPSBbXTtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBqID0gMDsgaiA8IG1lc3NhZ2Uub3BzZXRJbXBvcnQubGVuZ3RoOyArK2opXG4gICAgICAgICAgICAgICAgICAgIG9iamVjdC5vcHNldEltcG9ydFtqXSA9ICRyb290Lm9ubnguT3BlcmF0b3JTZXRJZFByb3RvLnRvT2JqZWN0KG1lc3NhZ2Uub3BzZXRJbXBvcnRbal0sIG9wdGlvbnMpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG1lc3NhZ2UubWV0YWRhdGFQcm9wcyAmJiBtZXNzYWdlLm1ldGFkYXRhUHJvcHMubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgb2JqZWN0Lm1ldGFkYXRhUHJvcHMgPSBbXTtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBqID0gMDsgaiA8IG1lc3NhZ2UubWV0YWRhdGFQcm9wcy5sZW5ndGg7ICsrailcbiAgICAgICAgICAgICAgICAgICAgb2JqZWN0Lm1ldGFkYXRhUHJvcHNbal0gPSAkcm9vdC5vbm54LlN0cmluZ1N0cmluZ0VudHJ5UHJvdG8udG9PYmplY3QobWVzc2FnZS5tZXRhZGF0YVByb3BzW2pdLCBvcHRpb25zKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBvYmplY3Q7XG4gICAgICAgIH07XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIENvbnZlcnRzIHRoaXMgTW9kZWxQcm90byB0byBKU09OLlxuICAgICAgICAgKiBAZnVuY3Rpb24gdG9KU09OXG4gICAgICAgICAqIEBtZW1iZXJvZiBvbm54Lk1vZGVsUHJvdG9cbiAgICAgICAgICogQGluc3RhbmNlXG4gICAgICAgICAqIEByZXR1cm5zIHtPYmplY3QuPHN0cmluZywqPn0gSlNPTiBvYmplY3RcbiAgICAgICAgICovXG4gICAgICAgIE1vZGVsUHJvdG8ucHJvdG90eXBlLnRvSlNPTiA9IGZ1bmN0aW9uIHRvSlNPTigpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmNvbnN0cnVjdG9yLnRvT2JqZWN0KHRoaXMsICRwcm90b2J1Zi51dGlsLnRvSlNPTk9wdGlvbnMpO1xuICAgICAgICB9O1xuXG4gICAgICAgIHJldHVybiBNb2RlbFByb3RvO1xuICAgIH0pKCk7XG5cbiAgICBvbm54LlN0cmluZ1N0cmluZ0VudHJ5UHJvdG8gPSAoZnVuY3Rpb24oKSB7XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIFByb3BlcnRpZXMgb2YgYSBTdHJpbmdTdHJpbmdFbnRyeVByb3RvLlxuICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueFxuICAgICAgICAgKiBAaW50ZXJmYWNlIElTdHJpbmdTdHJpbmdFbnRyeVByb3RvXG4gICAgICAgICAqIEBwcm9wZXJ0eSB7c3RyaW5nfG51bGx9IFtrZXldIFN0cmluZ1N0cmluZ0VudHJ5UHJvdG8ga2V5XG4gICAgICAgICAqIEBwcm9wZXJ0eSB7c3RyaW5nfG51bGx9IFt2YWx1ZV0gU3RyaW5nU3RyaW5nRW50cnlQcm90byB2YWx1ZVxuICAgICAgICAgKi9cblxuICAgICAgICAvKipcbiAgICAgICAgICogQ29uc3RydWN0cyBhIG5ldyBTdHJpbmdTdHJpbmdFbnRyeVByb3RvLlxuICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueFxuICAgICAgICAgKiBAY2xhc3NkZXNjIFJlcHJlc2VudHMgYSBTdHJpbmdTdHJpbmdFbnRyeVByb3RvLlxuICAgICAgICAgKiBAaW1wbGVtZW50cyBJU3RyaW5nU3RyaW5nRW50cnlQcm90b1xuICAgICAgICAgKiBAY29uc3RydWN0b3JcbiAgICAgICAgICogQHBhcmFtIHtvbm54LklTdHJpbmdTdHJpbmdFbnRyeVByb3RvPX0gW3Byb3BlcnRpZXNdIFByb3BlcnRpZXMgdG8gc2V0XG4gICAgICAgICAqL1xuICAgICAgICBmdW5jdGlvbiBTdHJpbmdTdHJpbmdFbnRyeVByb3RvKHByb3BlcnRpZXMpIHtcbiAgICAgICAgICAgIGlmIChwcm9wZXJ0aWVzKVxuICAgICAgICAgICAgICAgIGZvciAodmFyIGtleXMgPSBPYmplY3Qua2V5cyhwcm9wZXJ0aWVzKSwgaSA9IDA7IGkgPCBrZXlzLmxlbmd0aDsgKytpKVxuICAgICAgICAgICAgICAgICAgICBpZiAocHJvcGVydGllc1trZXlzW2ldXSAhPSBudWxsKVxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpc1trZXlzW2ldXSA9IHByb3BlcnRpZXNba2V5c1tpXV07XG4gICAgICAgIH1cblxuICAgICAgICAvKipcbiAgICAgICAgICogU3RyaW5nU3RyaW5nRW50cnlQcm90byBrZXkuXG4gICAgICAgICAqIEBtZW1iZXIge3N0cmluZ30ga2V5XG4gICAgICAgICAqIEBtZW1iZXJvZiBvbm54LlN0cmluZ1N0cmluZ0VudHJ5UHJvdG9cbiAgICAgICAgICogQGluc3RhbmNlXG4gICAgICAgICAqL1xuICAgICAgICBTdHJpbmdTdHJpbmdFbnRyeVByb3RvLnByb3RvdHlwZS5rZXkgPSBcIlwiO1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBTdHJpbmdTdHJpbmdFbnRyeVByb3RvIHZhbHVlLlxuICAgICAgICAgKiBAbWVtYmVyIHtzdHJpbmd9IHZhbHVlXG4gICAgICAgICAqIEBtZW1iZXJvZiBvbm54LlN0cmluZ1N0cmluZ0VudHJ5UHJvdG9cbiAgICAgICAgICogQGluc3RhbmNlXG4gICAgICAgICAqL1xuICAgICAgICBTdHJpbmdTdHJpbmdFbnRyeVByb3RvLnByb3RvdHlwZS52YWx1ZSA9IFwiXCI7XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIENyZWF0ZXMgYSBuZXcgU3RyaW5nU3RyaW5nRW50cnlQcm90byBpbnN0YW5jZSB1c2luZyB0aGUgc3BlY2lmaWVkIHByb3BlcnRpZXMuXG4gICAgICAgICAqIEBmdW5jdGlvbiBjcmVhdGVcbiAgICAgICAgICogQG1lbWJlcm9mIG9ubnguU3RyaW5nU3RyaW5nRW50cnlQcm90b1xuICAgICAgICAgKiBAc3RhdGljXG4gICAgICAgICAqIEBwYXJhbSB7b25ueC5JU3RyaW5nU3RyaW5nRW50cnlQcm90bz19IFtwcm9wZXJ0aWVzXSBQcm9wZXJ0aWVzIHRvIHNldFxuICAgICAgICAgKiBAcmV0dXJucyB7b25ueC5TdHJpbmdTdHJpbmdFbnRyeVByb3RvfSBTdHJpbmdTdHJpbmdFbnRyeVByb3RvIGluc3RhbmNlXG4gICAgICAgICAqL1xuICAgICAgICBTdHJpbmdTdHJpbmdFbnRyeVByb3RvLmNyZWF0ZSA9IGZ1bmN0aW9uIGNyZWF0ZShwcm9wZXJ0aWVzKSB7XG4gICAgICAgICAgICByZXR1cm4gbmV3IFN0cmluZ1N0cmluZ0VudHJ5UHJvdG8ocHJvcGVydGllcyk7XG4gICAgICAgIH07XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEVuY29kZXMgdGhlIHNwZWNpZmllZCBTdHJpbmdTdHJpbmdFbnRyeVByb3RvIG1lc3NhZ2UuIERvZXMgbm90IGltcGxpY2l0bHkge0BsaW5rIG9ubnguU3RyaW5nU3RyaW5nRW50cnlQcm90by52ZXJpZnl8dmVyaWZ5fSBtZXNzYWdlcy5cbiAgICAgICAgICogQGZ1bmN0aW9uIGVuY29kZVxuICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueC5TdHJpbmdTdHJpbmdFbnRyeVByb3RvXG4gICAgICAgICAqIEBzdGF0aWNcbiAgICAgICAgICogQHBhcmFtIHtvbm54LklTdHJpbmdTdHJpbmdFbnRyeVByb3RvfSBtZXNzYWdlIFN0cmluZ1N0cmluZ0VudHJ5UHJvdG8gbWVzc2FnZSBvciBwbGFpbiBvYmplY3QgdG8gZW5jb2RlXG4gICAgICAgICAqIEBwYXJhbSB7JHByb3RvYnVmLldyaXRlcn0gW3dyaXRlcl0gV3JpdGVyIHRvIGVuY29kZSB0b1xuICAgICAgICAgKiBAcmV0dXJucyB7JHByb3RvYnVmLldyaXRlcn0gV3JpdGVyXG4gICAgICAgICAqL1xuICAgICAgICBTdHJpbmdTdHJpbmdFbnRyeVByb3RvLmVuY29kZSA9IGZ1bmN0aW9uIGVuY29kZShtZXNzYWdlLCB3cml0ZXIpIHtcbiAgICAgICAgICAgIGlmICghd3JpdGVyKVxuICAgICAgICAgICAgICAgIHdyaXRlciA9ICRXcml0ZXIuY3JlYXRlKCk7XG4gICAgICAgICAgICBpZiAobWVzc2FnZS5rZXkgIT0gbnVsbCAmJiBtZXNzYWdlLmhhc093blByb3BlcnR5KFwia2V5XCIpKVxuICAgICAgICAgICAgICAgIHdyaXRlci51aW50MzIoLyogaWQgMSwgd2lyZVR5cGUgMiA9Ki8xMCkuc3RyaW5nKG1lc3NhZ2Uua2V5KTtcbiAgICAgICAgICAgIGlmIChtZXNzYWdlLnZhbHVlICE9IG51bGwgJiYgbWVzc2FnZS5oYXNPd25Qcm9wZXJ0eShcInZhbHVlXCIpKVxuICAgICAgICAgICAgICAgIHdyaXRlci51aW50MzIoLyogaWQgMiwgd2lyZVR5cGUgMiA9Ki8xOCkuc3RyaW5nKG1lc3NhZ2UudmFsdWUpO1xuICAgICAgICAgICAgcmV0dXJuIHdyaXRlcjtcbiAgICAgICAgfTtcblxuICAgICAgICAvKipcbiAgICAgICAgICogRW5jb2RlcyB0aGUgc3BlY2lmaWVkIFN0cmluZ1N0cmluZ0VudHJ5UHJvdG8gbWVzc2FnZSwgbGVuZ3RoIGRlbGltaXRlZC4gRG9lcyBub3QgaW1wbGljaXRseSB7QGxpbmsgb25ueC5TdHJpbmdTdHJpbmdFbnRyeVByb3RvLnZlcmlmeXx2ZXJpZnl9IG1lc3NhZ2VzLlxuICAgICAgICAgKiBAZnVuY3Rpb24gZW5jb2RlRGVsaW1pdGVkXG4gICAgICAgICAqIEBtZW1iZXJvZiBvbm54LlN0cmluZ1N0cmluZ0VudHJ5UHJvdG9cbiAgICAgICAgICogQHN0YXRpY1xuICAgICAgICAgKiBAcGFyYW0ge29ubnguSVN0cmluZ1N0cmluZ0VudHJ5UHJvdG99IG1lc3NhZ2UgU3RyaW5nU3RyaW5nRW50cnlQcm90byBtZXNzYWdlIG9yIHBsYWluIG9iamVjdCB0byBlbmNvZGVcbiAgICAgICAgICogQHBhcmFtIHskcHJvdG9idWYuV3JpdGVyfSBbd3JpdGVyXSBXcml0ZXIgdG8gZW5jb2RlIHRvXG4gICAgICAgICAqIEByZXR1cm5zIHskcHJvdG9idWYuV3JpdGVyfSBXcml0ZXJcbiAgICAgICAgICovXG4gICAgICAgIFN0cmluZ1N0cmluZ0VudHJ5UHJvdG8uZW5jb2RlRGVsaW1pdGVkID0gZnVuY3Rpb24gZW5jb2RlRGVsaW1pdGVkKG1lc3NhZ2UsIHdyaXRlcikge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuZW5jb2RlKG1lc3NhZ2UsIHdyaXRlcikubGRlbGltKCk7XG4gICAgICAgIH07XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIERlY29kZXMgYSBTdHJpbmdTdHJpbmdFbnRyeVByb3RvIG1lc3NhZ2UgZnJvbSB0aGUgc3BlY2lmaWVkIHJlYWRlciBvciBidWZmZXIuXG4gICAgICAgICAqIEBmdW5jdGlvbiBkZWNvZGVcbiAgICAgICAgICogQG1lbWJlcm9mIG9ubnguU3RyaW5nU3RyaW5nRW50cnlQcm90b1xuICAgICAgICAgKiBAc3RhdGljXG4gICAgICAgICAqIEBwYXJhbSB7JHByb3RvYnVmLlJlYWRlcnxVaW50OEFycmF5fSByZWFkZXIgUmVhZGVyIG9yIGJ1ZmZlciB0byBkZWNvZGUgZnJvbVxuICAgICAgICAgKiBAcGFyYW0ge251bWJlcn0gW2xlbmd0aF0gTWVzc2FnZSBsZW5ndGggaWYga25vd24gYmVmb3JlaGFuZFxuICAgICAgICAgKiBAcmV0dXJucyB7b25ueC5TdHJpbmdTdHJpbmdFbnRyeVByb3RvfSBTdHJpbmdTdHJpbmdFbnRyeVByb3RvXG4gICAgICAgICAqIEB0aHJvd3Mge0Vycm9yfSBJZiB0aGUgcGF5bG9hZCBpcyBub3QgYSByZWFkZXIgb3IgdmFsaWQgYnVmZmVyXG4gICAgICAgICAqIEB0aHJvd3MgeyRwcm90b2J1Zi51dGlsLlByb3RvY29sRXJyb3J9IElmIHJlcXVpcmVkIGZpZWxkcyBhcmUgbWlzc2luZ1xuICAgICAgICAgKi9cbiAgICAgICAgU3RyaW5nU3RyaW5nRW50cnlQcm90by5kZWNvZGUgPSBmdW5jdGlvbiBkZWNvZGUocmVhZGVyLCBsZW5ndGgpIHtcbiAgICAgICAgICAgIGlmICghKHJlYWRlciBpbnN0YW5jZW9mICRSZWFkZXIpKVxuICAgICAgICAgICAgICAgIHJlYWRlciA9ICRSZWFkZXIuY3JlYXRlKHJlYWRlcik7XG4gICAgICAgICAgICB2YXIgZW5kID0gbGVuZ3RoID09PSB1bmRlZmluZWQgPyByZWFkZXIubGVuIDogcmVhZGVyLnBvcyArIGxlbmd0aCwgbWVzc2FnZSA9IG5ldyAkcm9vdC5vbm54LlN0cmluZ1N0cmluZ0VudHJ5UHJvdG8oKTtcbiAgICAgICAgICAgIHdoaWxlIChyZWFkZXIucG9zIDwgZW5kKSB7XG4gICAgICAgICAgICAgICAgdmFyIHRhZyA9IHJlYWRlci51aW50MzIoKTtcbiAgICAgICAgICAgICAgICBzd2l0Y2ggKHRhZyA+Pj4gMykge1xuICAgICAgICAgICAgICAgIGNhc2UgMTpcbiAgICAgICAgICAgICAgICAgICAgbWVzc2FnZS5rZXkgPSByZWFkZXIuc3RyaW5nKCk7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgMjpcbiAgICAgICAgICAgICAgICAgICAgbWVzc2FnZS52YWx1ZSA9IHJlYWRlci5zdHJpbmcoKTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICAgICAgcmVhZGVyLnNraXBUeXBlKHRhZyAmIDcpO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gbWVzc2FnZTtcbiAgICAgICAgfTtcblxuICAgICAgICAvKipcbiAgICAgICAgICogRGVjb2RlcyBhIFN0cmluZ1N0cmluZ0VudHJ5UHJvdG8gbWVzc2FnZSBmcm9tIHRoZSBzcGVjaWZpZWQgcmVhZGVyIG9yIGJ1ZmZlciwgbGVuZ3RoIGRlbGltaXRlZC5cbiAgICAgICAgICogQGZ1bmN0aW9uIGRlY29kZURlbGltaXRlZFxuICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueC5TdHJpbmdTdHJpbmdFbnRyeVByb3RvXG4gICAgICAgICAqIEBzdGF0aWNcbiAgICAgICAgICogQHBhcmFtIHskcHJvdG9idWYuUmVhZGVyfFVpbnQ4QXJyYXl9IHJlYWRlciBSZWFkZXIgb3IgYnVmZmVyIHRvIGRlY29kZSBmcm9tXG4gICAgICAgICAqIEByZXR1cm5zIHtvbm54LlN0cmluZ1N0cmluZ0VudHJ5UHJvdG99IFN0cmluZ1N0cmluZ0VudHJ5UHJvdG9cbiAgICAgICAgICogQHRocm93cyB7RXJyb3J9IElmIHRoZSBwYXlsb2FkIGlzIG5vdCBhIHJlYWRlciBvciB2YWxpZCBidWZmZXJcbiAgICAgICAgICogQHRocm93cyB7JHByb3RvYnVmLnV0aWwuUHJvdG9jb2xFcnJvcn0gSWYgcmVxdWlyZWQgZmllbGRzIGFyZSBtaXNzaW5nXG4gICAgICAgICAqL1xuICAgICAgICBTdHJpbmdTdHJpbmdFbnRyeVByb3RvLmRlY29kZURlbGltaXRlZCA9IGZ1bmN0aW9uIGRlY29kZURlbGltaXRlZChyZWFkZXIpIHtcbiAgICAgICAgICAgIGlmICghKHJlYWRlciBpbnN0YW5jZW9mICRSZWFkZXIpKVxuICAgICAgICAgICAgICAgIHJlYWRlciA9IG5ldyAkUmVhZGVyKHJlYWRlcik7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5kZWNvZGUocmVhZGVyLCByZWFkZXIudWludDMyKCkpO1xuICAgICAgICB9O1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBWZXJpZmllcyBhIFN0cmluZ1N0cmluZ0VudHJ5UHJvdG8gbWVzc2FnZS5cbiAgICAgICAgICogQGZ1bmN0aW9uIHZlcmlmeVxuICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueC5TdHJpbmdTdHJpbmdFbnRyeVByb3RvXG4gICAgICAgICAqIEBzdGF0aWNcbiAgICAgICAgICogQHBhcmFtIHtPYmplY3QuPHN0cmluZywqPn0gbWVzc2FnZSBQbGFpbiBvYmplY3QgdG8gdmVyaWZ5XG4gICAgICAgICAqIEByZXR1cm5zIHtzdHJpbmd8bnVsbH0gYG51bGxgIGlmIHZhbGlkLCBvdGhlcndpc2UgdGhlIHJlYXNvbiB3aHkgaXQgaXMgbm90XG4gICAgICAgICAqL1xuICAgICAgICBTdHJpbmdTdHJpbmdFbnRyeVByb3RvLnZlcmlmeSA9IGZ1bmN0aW9uIHZlcmlmeShtZXNzYWdlKSB7XG4gICAgICAgICAgICBpZiAodHlwZW9mIG1lc3NhZ2UgIT09IFwib2JqZWN0XCIgfHwgbWVzc2FnZSA9PT0gbnVsbClcbiAgICAgICAgICAgICAgICByZXR1cm4gXCJvYmplY3QgZXhwZWN0ZWRcIjtcbiAgICAgICAgICAgIGlmIChtZXNzYWdlLmtleSAhPSBudWxsICYmIG1lc3NhZ2UuaGFzT3duUHJvcGVydHkoXCJrZXlcIikpXG4gICAgICAgICAgICAgICAgaWYgKCEkdXRpbC5pc1N0cmluZyhtZXNzYWdlLmtleSkpXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBcImtleTogc3RyaW5nIGV4cGVjdGVkXCI7XG4gICAgICAgICAgICBpZiAobWVzc2FnZS52YWx1ZSAhPSBudWxsICYmIG1lc3NhZ2UuaGFzT3duUHJvcGVydHkoXCJ2YWx1ZVwiKSlcbiAgICAgICAgICAgICAgICBpZiAoISR1dGlsLmlzU3RyaW5nKG1lc3NhZ2UudmFsdWUpKVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gXCJ2YWx1ZTogc3RyaW5nIGV4cGVjdGVkXCI7XG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfTtcblxuICAgICAgICAvKipcbiAgICAgICAgICogQ3JlYXRlcyBhIFN0cmluZ1N0cmluZ0VudHJ5UHJvdG8gbWVzc2FnZSBmcm9tIGEgcGxhaW4gb2JqZWN0LiBBbHNvIGNvbnZlcnRzIHZhbHVlcyB0byB0aGVpciByZXNwZWN0aXZlIGludGVybmFsIHR5cGVzLlxuICAgICAgICAgKiBAZnVuY3Rpb24gZnJvbU9iamVjdFxuICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueC5TdHJpbmdTdHJpbmdFbnRyeVByb3RvXG4gICAgICAgICAqIEBzdGF0aWNcbiAgICAgICAgICogQHBhcmFtIHtPYmplY3QuPHN0cmluZywqPn0gb2JqZWN0IFBsYWluIG9iamVjdFxuICAgICAgICAgKiBAcmV0dXJucyB7b25ueC5TdHJpbmdTdHJpbmdFbnRyeVByb3RvfSBTdHJpbmdTdHJpbmdFbnRyeVByb3RvXG4gICAgICAgICAqL1xuICAgICAgICBTdHJpbmdTdHJpbmdFbnRyeVByb3RvLmZyb21PYmplY3QgPSBmdW5jdGlvbiBmcm9tT2JqZWN0KG9iamVjdCkge1xuICAgICAgICAgICAgaWYgKG9iamVjdCBpbnN0YW5jZW9mICRyb290Lm9ubnguU3RyaW5nU3RyaW5nRW50cnlQcm90bylcbiAgICAgICAgICAgICAgICByZXR1cm4gb2JqZWN0O1xuICAgICAgICAgICAgdmFyIG1lc3NhZ2UgPSBuZXcgJHJvb3Qub25ueC5TdHJpbmdTdHJpbmdFbnRyeVByb3RvKCk7XG4gICAgICAgICAgICBpZiAob2JqZWN0LmtleSAhPSBudWxsKVxuICAgICAgICAgICAgICAgIG1lc3NhZ2Uua2V5ID0gU3RyaW5nKG9iamVjdC5rZXkpO1xuICAgICAgICAgICAgaWYgKG9iamVjdC52YWx1ZSAhPSBudWxsKVxuICAgICAgICAgICAgICAgIG1lc3NhZ2UudmFsdWUgPSBTdHJpbmcob2JqZWN0LnZhbHVlKTtcbiAgICAgICAgICAgIHJldHVybiBtZXNzYWdlO1xuICAgICAgICB9O1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBDcmVhdGVzIGEgcGxhaW4gb2JqZWN0IGZyb20gYSBTdHJpbmdTdHJpbmdFbnRyeVByb3RvIG1lc3NhZ2UuIEFsc28gY29udmVydHMgdmFsdWVzIHRvIG90aGVyIHR5cGVzIGlmIHNwZWNpZmllZC5cbiAgICAgICAgICogQGZ1bmN0aW9uIHRvT2JqZWN0XG4gICAgICAgICAqIEBtZW1iZXJvZiBvbm54LlN0cmluZ1N0cmluZ0VudHJ5UHJvdG9cbiAgICAgICAgICogQHN0YXRpY1xuICAgICAgICAgKiBAcGFyYW0ge29ubnguU3RyaW5nU3RyaW5nRW50cnlQcm90b30gbWVzc2FnZSBTdHJpbmdTdHJpbmdFbnRyeVByb3RvXG4gICAgICAgICAqIEBwYXJhbSB7JHByb3RvYnVmLklDb252ZXJzaW9uT3B0aW9uc30gW29wdGlvbnNdIENvbnZlcnNpb24gb3B0aW9uc1xuICAgICAgICAgKiBAcmV0dXJucyB7T2JqZWN0LjxzdHJpbmcsKj59IFBsYWluIG9iamVjdFxuICAgICAgICAgKi9cbiAgICAgICAgU3RyaW5nU3RyaW5nRW50cnlQcm90by50b09iamVjdCA9IGZ1bmN0aW9uIHRvT2JqZWN0KG1lc3NhZ2UsIG9wdGlvbnMpIHtcbiAgICAgICAgICAgIGlmICghb3B0aW9ucylcbiAgICAgICAgICAgICAgICBvcHRpb25zID0ge307XG4gICAgICAgICAgICB2YXIgb2JqZWN0ID0ge307XG4gICAgICAgICAgICBpZiAob3B0aW9ucy5kZWZhdWx0cykge1xuICAgICAgICAgICAgICAgIG9iamVjdC5rZXkgPSBcIlwiO1xuICAgICAgICAgICAgICAgIG9iamVjdC52YWx1ZSA9IFwiXCI7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAobWVzc2FnZS5rZXkgIT0gbnVsbCAmJiBtZXNzYWdlLmhhc093blByb3BlcnR5KFwia2V5XCIpKVxuICAgICAgICAgICAgICAgIG9iamVjdC5rZXkgPSBtZXNzYWdlLmtleTtcbiAgICAgICAgICAgIGlmIChtZXNzYWdlLnZhbHVlICE9IG51bGwgJiYgbWVzc2FnZS5oYXNPd25Qcm9wZXJ0eShcInZhbHVlXCIpKVxuICAgICAgICAgICAgICAgIG9iamVjdC52YWx1ZSA9IG1lc3NhZ2UudmFsdWU7XG4gICAgICAgICAgICByZXR1cm4gb2JqZWN0O1xuICAgICAgICB9O1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBDb252ZXJ0cyB0aGlzIFN0cmluZ1N0cmluZ0VudHJ5UHJvdG8gdG8gSlNPTi5cbiAgICAgICAgICogQGZ1bmN0aW9uIHRvSlNPTlxuICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueC5TdHJpbmdTdHJpbmdFbnRyeVByb3RvXG4gICAgICAgICAqIEBpbnN0YW5jZVxuICAgICAgICAgKiBAcmV0dXJucyB7T2JqZWN0LjxzdHJpbmcsKj59IEpTT04gb2JqZWN0XG4gICAgICAgICAqL1xuICAgICAgICBTdHJpbmdTdHJpbmdFbnRyeVByb3RvLnByb3RvdHlwZS50b0pTT04gPSBmdW5jdGlvbiB0b0pTT04oKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5jb25zdHJ1Y3Rvci50b09iamVjdCh0aGlzLCAkcHJvdG9idWYudXRpbC50b0pTT05PcHRpb25zKTtcbiAgICAgICAgfTtcblxuICAgICAgICByZXR1cm4gU3RyaW5nU3RyaW5nRW50cnlQcm90bztcbiAgICB9KSgpO1xuXG4gICAgb25ueC5UZW5zb3JBbm5vdGF0aW9uID0gKGZ1bmN0aW9uKCkge1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBQcm9wZXJ0aWVzIG9mIGEgVGVuc29yQW5ub3RhdGlvbi5cbiAgICAgICAgICogQG1lbWJlcm9mIG9ubnhcbiAgICAgICAgICogQGludGVyZmFjZSBJVGVuc29yQW5ub3RhdGlvblxuICAgICAgICAgKiBAcHJvcGVydHkge3N0cmluZ3xudWxsfSBbdGVuc29yTmFtZV0gVGVuc29yQW5ub3RhdGlvbiB0ZW5zb3JOYW1lXG4gICAgICAgICAqIEBwcm9wZXJ0eSB7QXJyYXkuPG9ubnguSVN0cmluZ1N0cmluZ0VudHJ5UHJvdG8+fG51bGx9IFtxdWFudFBhcmFtZXRlclRlbnNvck5hbWVzXSBUZW5zb3JBbm5vdGF0aW9uIHF1YW50UGFyYW1ldGVyVGVuc29yTmFtZXNcbiAgICAgICAgICovXG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIENvbnN0cnVjdHMgYSBuZXcgVGVuc29yQW5ub3RhdGlvbi5cbiAgICAgICAgICogQG1lbWJlcm9mIG9ubnhcbiAgICAgICAgICogQGNsYXNzZGVzYyBSZXByZXNlbnRzIGEgVGVuc29yQW5ub3RhdGlvbi5cbiAgICAgICAgICogQGltcGxlbWVudHMgSVRlbnNvckFubm90YXRpb25cbiAgICAgICAgICogQGNvbnN0cnVjdG9yXG4gICAgICAgICAqIEBwYXJhbSB7b25ueC5JVGVuc29yQW5ub3RhdGlvbj19IFtwcm9wZXJ0aWVzXSBQcm9wZXJ0aWVzIHRvIHNldFxuICAgICAgICAgKi9cbiAgICAgICAgZnVuY3Rpb24gVGVuc29yQW5ub3RhdGlvbihwcm9wZXJ0aWVzKSB7XG4gICAgICAgICAgICB0aGlzLnF1YW50UGFyYW1ldGVyVGVuc29yTmFtZXMgPSBbXTtcbiAgICAgICAgICAgIGlmIChwcm9wZXJ0aWVzKVxuICAgICAgICAgICAgICAgIGZvciAodmFyIGtleXMgPSBPYmplY3Qua2V5cyhwcm9wZXJ0aWVzKSwgaSA9IDA7IGkgPCBrZXlzLmxlbmd0aDsgKytpKVxuICAgICAgICAgICAgICAgICAgICBpZiAocHJvcGVydGllc1trZXlzW2ldXSAhPSBudWxsKVxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpc1trZXlzW2ldXSA9IHByb3BlcnRpZXNba2V5c1tpXV07XG4gICAgICAgIH1cblxuICAgICAgICAvKipcbiAgICAgICAgICogVGVuc29yQW5ub3RhdGlvbiB0ZW5zb3JOYW1lLlxuICAgICAgICAgKiBAbWVtYmVyIHtzdHJpbmd9IHRlbnNvck5hbWVcbiAgICAgICAgICogQG1lbWJlcm9mIG9ubnguVGVuc29yQW5ub3RhdGlvblxuICAgICAgICAgKiBAaW5zdGFuY2VcbiAgICAgICAgICovXG4gICAgICAgIFRlbnNvckFubm90YXRpb24ucHJvdG90eXBlLnRlbnNvck5hbWUgPSBcIlwiO1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBUZW5zb3JBbm5vdGF0aW9uIHF1YW50UGFyYW1ldGVyVGVuc29yTmFtZXMuXG4gICAgICAgICAqIEBtZW1iZXIge0FycmF5Ljxvbm54LklTdHJpbmdTdHJpbmdFbnRyeVByb3RvPn0gcXVhbnRQYXJhbWV0ZXJUZW5zb3JOYW1lc1xuICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueC5UZW5zb3JBbm5vdGF0aW9uXG4gICAgICAgICAqIEBpbnN0YW5jZVxuICAgICAgICAgKi9cbiAgICAgICAgVGVuc29yQW5ub3RhdGlvbi5wcm90b3R5cGUucXVhbnRQYXJhbWV0ZXJUZW5zb3JOYW1lcyA9ICR1dGlsLmVtcHR5QXJyYXk7XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIENyZWF0ZXMgYSBuZXcgVGVuc29yQW5ub3RhdGlvbiBpbnN0YW5jZSB1c2luZyB0aGUgc3BlY2lmaWVkIHByb3BlcnRpZXMuXG4gICAgICAgICAqIEBmdW5jdGlvbiBjcmVhdGVcbiAgICAgICAgICogQG1lbWJlcm9mIG9ubnguVGVuc29yQW5ub3RhdGlvblxuICAgICAgICAgKiBAc3RhdGljXG4gICAgICAgICAqIEBwYXJhbSB7b25ueC5JVGVuc29yQW5ub3RhdGlvbj19IFtwcm9wZXJ0aWVzXSBQcm9wZXJ0aWVzIHRvIHNldFxuICAgICAgICAgKiBAcmV0dXJucyB7b25ueC5UZW5zb3JBbm5vdGF0aW9ufSBUZW5zb3JBbm5vdGF0aW9uIGluc3RhbmNlXG4gICAgICAgICAqL1xuICAgICAgICBUZW5zb3JBbm5vdGF0aW9uLmNyZWF0ZSA9IGZ1bmN0aW9uIGNyZWF0ZShwcm9wZXJ0aWVzKSB7XG4gICAgICAgICAgICByZXR1cm4gbmV3IFRlbnNvckFubm90YXRpb24ocHJvcGVydGllcyk7XG4gICAgICAgIH07XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEVuY29kZXMgdGhlIHNwZWNpZmllZCBUZW5zb3JBbm5vdGF0aW9uIG1lc3NhZ2UuIERvZXMgbm90IGltcGxpY2l0bHkge0BsaW5rIG9ubnguVGVuc29yQW5ub3RhdGlvbi52ZXJpZnl8dmVyaWZ5fSBtZXNzYWdlcy5cbiAgICAgICAgICogQGZ1bmN0aW9uIGVuY29kZVxuICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueC5UZW5zb3JBbm5vdGF0aW9uXG4gICAgICAgICAqIEBzdGF0aWNcbiAgICAgICAgICogQHBhcmFtIHtvbm54LklUZW5zb3JBbm5vdGF0aW9ufSBtZXNzYWdlIFRlbnNvckFubm90YXRpb24gbWVzc2FnZSBvciBwbGFpbiBvYmplY3QgdG8gZW5jb2RlXG4gICAgICAgICAqIEBwYXJhbSB7JHByb3RvYnVmLldyaXRlcn0gW3dyaXRlcl0gV3JpdGVyIHRvIGVuY29kZSB0b1xuICAgICAgICAgKiBAcmV0dXJucyB7JHByb3RvYnVmLldyaXRlcn0gV3JpdGVyXG4gICAgICAgICAqL1xuICAgICAgICBUZW5zb3JBbm5vdGF0aW9uLmVuY29kZSA9IGZ1bmN0aW9uIGVuY29kZShtZXNzYWdlLCB3cml0ZXIpIHtcbiAgICAgICAgICAgIGlmICghd3JpdGVyKVxuICAgICAgICAgICAgICAgIHdyaXRlciA9ICRXcml0ZXIuY3JlYXRlKCk7XG4gICAgICAgICAgICBpZiAobWVzc2FnZS50ZW5zb3JOYW1lICE9IG51bGwgJiYgbWVzc2FnZS5oYXNPd25Qcm9wZXJ0eShcInRlbnNvck5hbWVcIikpXG4gICAgICAgICAgICAgICAgd3JpdGVyLnVpbnQzMigvKiBpZCAxLCB3aXJlVHlwZSAyID0qLzEwKS5zdHJpbmcobWVzc2FnZS50ZW5zb3JOYW1lKTtcbiAgICAgICAgICAgIGlmIChtZXNzYWdlLnF1YW50UGFyYW1ldGVyVGVuc29yTmFtZXMgIT0gbnVsbCAmJiBtZXNzYWdlLnF1YW50UGFyYW1ldGVyVGVuc29yTmFtZXMubGVuZ3RoKVxuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbWVzc2FnZS5xdWFudFBhcmFtZXRlclRlbnNvck5hbWVzLmxlbmd0aDsgKytpKVxuICAgICAgICAgICAgICAgICAgICAkcm9vdC5vbm54LlN0cmluZ1N0cmluZ0VudHJ5UHJvdG8uZW5jb2RlKG1lc3NhZ2UucXVhbnRQYXJhbWV0ZXJUZW5zb3JOYW1lc1tpXSwgd3JpdGVyLnVpbnQzMigvKiBpZCAyLCB3aXJlVHlwZSAyID0qLzE4KS5mb3JrKCkpLmxkZWxpbSgpO1xuICAgICAgICAgICAgcmV0dXJuIHdyaXRlcjtcbiAgICAgICAgfTtcblxuICAgICAgICAvKipcbiAgICAgICAgICogRW5jb2RlcyB0aGUgc3BlY2lmaWVkIFRlbnNvckFubm90YXRpb24gbWVzc2FnZSwgbGVuZ3RoIGRlbGltaXRlZC4gRG9lcyBub3QgaW1wbGljaXRseSB7QGxpbmsgb25ueC5UZW5zb3JBbm5vdGF0aW9uLnZlcmlmeXx2ZXJpZnl9IG1lc3NhZ2VzLlxuICAgICAgICAgKiBAZnVuY3Rpb24gZW5jb2RlRGVsaW1pdGVkXG4gICAgICAgICAqIEBtZW1iZXJvZiBvbm54LlRlbnNvckFubm90YXRpb25cbiAgICAgICAgICogQHN0YXRpY1xuICAgICAgICAgKiBAcGFyYW0ge29ubnguSVRlbnNvckFubm90YXRpb259IG1lc3NhZ2UgVGVuc29yQW5ub3RhdGlvbiBtZXNzYWdlIG9yIHBsYWluIG9iamVjdCB0byBlbmNvZGVcbiAgICAgICAgICogQHBhcmFtIHskcHJvdG9idWYuV3JpdGVyfSBbd3JpdGVyXSBXcml0ZXIgdG8gZW5jb2RlIHRvXG4gICAgICAgICAqIEByZXR1cm5zIHskcHJvdG9idWYuV3JpdGVyfSBXcml0ZXJcbiAgICAgICAgICovXG4gICAgICAgIFRlbnNvckFubm90YXRpb24uZW5jb2RlRGVsaW1pdGVkID0gZnVuY3Rpb24gZW5jb2RlRGVsaW1pdGVkKG1lc3NhZ2UsIHdyaXRlcikge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuZW5jb2RlKG1lc3NhZ2UsIHdyaXRlcikubGRlbGltKCk7XG4gICAgICAgIH07XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIERlY29kZXMgYSBUZW5zb3JBbm5vdGF0aW9uIG1lc3NhZ2UgZnJvbSB0aGUgc3BlY2lmaWVkIHJlYWRlciBvciBidWZmZXIuXG4gICAgICAgICAqIEBmdW5jdGlvbiBkZWNvZGVcbiAgICAgICAgICogQG1lbWJlcm9mIG9ubnguVGVuc29yQW5ub3RhdGlvblxuICAgICAgICAgKiBAc3RhdGljXG4gICAgICAgICAqIEBwYXJhbSB7JHByb3RvYnVmLlJlYWRlcnxVaW50OEFycmF5fSByZWFkZXIgUmVhZGVyIG9yIGJ1ZmZlciB0byBkZWNvZGUgZnJvbVxuICAgICAgICAgKiBAcGFyYW0ge251bWJlcn0gW2xlbmd0aF0gTWVzc2FnZSBsZW5ndGggaWYga25vd24gYmVmb3JlaGFuZFxuICAgICAgICAgKiBAcmV0dXJucyB7b25ueC5UZW5zb3JBbm5vdGF0aW9ufSBUZW5zb3JBbm5vdGF0aW9uXG4gICAgICAgICAqIEB0aHJvd3Mge0Vycm9yfSBJZiB0aGUgcGF5bG9hZCBpcyBub3QgYSByZWFkZXIgb3IgdmFsaWQgYnVmZmVyXG4gICAgICAgICAqIEB0aHJvd3MgeyRwcm90b2J1Zi51dGlsLlByb3RvY29sRXJyb3J9IElmIHJlcXVpcmVkIGZpZWxkcyBhcmUgbWlzc2luZ1xuICAgICAgICAgKi9cbiAgICAgICAgVGVuc29yQW5ub3RhdGlvbi5kZWNvZGUgPSBmdW5jdGlvbiBkZWNvZGUocmVhZGVyLCBsZW5ndGgpIHtcbiAgICAgICAgICAgIGlmICghKHJlYWRlciBpbnN0YW5jZW9mICRSZWFkZXIpKVxuICAgICAgICAgICAgICAgIHJlYWRlciA9ICRSZWFkZXIuY3JlYXRlKHJlYWRlcik7XG4gICAgICAgICAgICB2YXIgZW5kID0gbGVuZ3RoID09PSB1bmRlZmluZWQgPyByZWFkZXIubGVuIDogcmVhZGVyLnBvcyArIGxlbmd0aCwgbWVzc2FnZSA9IG5ldyAkcm9vdC5vbm54LlRlbnNvckFubm90YXRpb24oKTtcbiAgICAgICAgICAgIHdoaWxlIChyZWFkZXIucG9zIDwgZW5kKSB7XG4gICAgICAgICAgICAgICAgdmFyIHRhZyA9IHJlYWRlci51aW50MzIoKTtcbiAgICAgICAgICAgICAgICBzd2l0Y2ggKHRhZyA+Pj4gMykge1xuICAgICAgICAgICAgICAgIGNhc2UgMTpcbiAgICAgICAgICAgICAgICAgICAgbWVzc2FnZS50ZW5zb3JOYW1lID0gcmVhZGVyLnN0cmluZygpO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlIDI6XG4gICAgICAgICAgICAgICAgICAgIGlmICghKG1lc3NhZ2UucXVhbnRQYXJhbWV0ZXJUZW5zb3JOYW1lcyAmJiBtZXNzYWdlLnF1YW50UGFyYW1ldGVyVGVuc29yTmFtZXMubGVuZ3RoKSlcbiAgICAgICAgICAgICAgICAgICAgICAgIG1lc3NhZ2UucXVhbnRQYXJhbWV0ZXJUZW5zb3JOYW1lcyA9IFtdO1xuICAgICAgICAgICAgICAgICAgICBtZXNzYWdlLnF1YW50UGFyYW1ldGVyVGVuc29yTmFtZXMucHVzaCgkcm9vdC5vbm54LlN0cmluZ1N0cmluZ0VudHJ5UHJvdG8uZGVjb2RlKHJlYWRlciwgcmVhZGVyLnVpbnQzMigpKSk7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgICAgIHJlYWRlci5za2lwVHlwZSh0YWcgJiA3KTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIG1lc3NhZ2U7XG4gICAgICAgIH07XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIERlY29kZXMgYSBUZW5zb3JBbm5vdGF0aW9uIG1lc3NhZ2UgZnJvbSB0aGUgc3BlY2lmaWVkIHJlYWRlciBvciBidWZmZXIsIGxlbmd0aCBkZWxpbWl0ZWQuXG4gICAgICAgICAqIEBmdW5jdGlvbiBkZWNvZGVEZWxpbWl0ZWRcbiAgICAgICAgICogQG1lbWJlcm9mIG9ubnguVGVuc29yQW5ub3RhdGlvblxuICAgICAgICAgKiBAc3RhdGljXG4gICAgICAgICAqIEBwYXJhbSB7JHByb3RvYnVmLlJlYWRlcnxVaW50OEFycmF5fSByZWFkZXIgUmVhZGVyIG9yIGJ1ZmZlciB0byBkZWNvZGUgZnJvbVxuICAgICAgICAgKiBAcmV0dXJucyB7b25ueC5UZW5zb3JBbm5vdGF0aW9ufSBUZW5zb3JBbm5vdGF0aW9uXG4gICAgICAgICAqIEB0aHJvd3Mge0Vycm9yfSBJZiB0aGUgcGF5bG9hZCBpcyBub3QgYSByZWFkZXIgb3IgdmFsaWQgYnVmZmVyXG4gICAgICAgICAqIEB0aHJvd3MgeyRwcm90b2J1Zi51dGlsLlByb3RvY29sRXJyb3J9IElmIHJlcXVpcmVkIGZpZWxkcyBhcmUgbWlzc2luZ1xuICAgICAgICAgKi9cbiAgICAgICAgVGVuc29yQW5ub3RhdGlvbi5kZWNvZGVEZWxpbWl0ZWQgPSBmdW5jdGlvbiBkZWNvZGVEZWxpbWl0ZWQocmVhZGVyKSB7XG4gICAgICAgICAgICBpZiAoIShyZWFkZXIgaW5zdGFuY2VvZiAkUmVhZGVyKSlcbiAgICAgICAgICAgICAgICByZWFkZXIgPSBuZXcgJFJlYWRlcihyZWFkZXIpO1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuZGVjb2RlKHJlYWRlciwgcmVhZGVyLnVpbnQzMigpKTtcbiAgICAgICAgfTtcblxuICAgICAgICAvKipcbiAgICAgICAgICogVmVyaWZpZXMgYSBUZW5zb3JBbm5vdGF0aW9uIG1lc3NhZ2UuXG4gICAgICAgICAqIEBmdW5jdGlvbiB2ZXJpZnlcbiAgICAgICAgICogQG1lbWJlcm9mIG9ubnguVGVuc29yQW5ub3RhdGlvblxuICAgICAgICAgKiBAc3RhdGljXG4gICAgICAgICAqIEBwYXJhbSB7T2JqZWN0LjxzdHJpbmcsKj59IG1lc3NhZ2UgUGxhaW4gb2JqZWN0IHRvIHZlcmlmeVxuICAgICAgICAgKiBAcmV0dXJucyB7c3RyaW5nfG51bGx9IGBudWxsYCBpZiB2YWxpZCwgb3RoZXJ3aXNlIHRoZSByZWFzb24gd2h5IGl0IGlzIG5vdFxuICAgICAgICAgKi9cbiAgICAgICAgVGVuc29yQW5ub3RhdGlvbi52ZXJpZnkgPSBmdW5jdGlvbiB2ZXJpZnkobWVzc2FnZSkge1xuICAgICAgICAgICAgaWYgKHR5cGVvZiBtZXNzYWdlICE9PSBcIm9iamVjdFwiIHx8IG1lc3NhZ2UgPT09IG51bGwpXG4gICAgICAgICAgICAgICAgcmV0dXJuIFwib2JqZWN0IGV4cGVjdGVkXCI7XG4gICAgICAgICAgICBpZiAobWVzc2FnZS50ZW5zb3JOYW1lICE9IG51bGwgJiYgbWVzc2FnZS5oYXNPd25Qcm9wZXJ0eShcInRlbnNvck5hbWVcIikpXG4gICAgICAgICAgICAgICAgaWYgKCEkdXRpbC5pc1N0cmluZyhtZXNzYWdlLnRlbnNvck5hbWUpKVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gXCJ0ZW5zb3JOYW1lOiBzdHJpbmcgZXhwZWN0ZWRcIjtcbiAgICAgICAgICAgIGlmIChtZXNzYWdlLnF1YW50UGFyYW1ldGVyVGVuc29yTmFtZXMgIT0gbnVsbCAmJiBtZXNzYWdlLmhhc093blByb3BlcnR5KFwicXVhbnRQYXJhbWV0ZXJUZW5zb3JOYW1lc1wiKSkge1xuICAgICAgICAgICAgICAgIGlmICghQXJyYXkuaXNBcnJheShtZXNzYWdlLnF1YW50UGFyYW1ldGVyVGVuc29yTmFtZXMpKVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gXCJxdWFudFBhcmFtZXRlclRlbnNvck5hbWVzOiBhcnJheSBleHBlY3RlZFwiO1xuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbWVzc2FnZS5xdWFudFBhcmFtZXRlclRlbnNvck5hbWVzLmxlbmd0aDsgKytpKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBlcnJvciA9ICRyb290Lm9ubnguU3RyaW5nU3RyaW5nRW50cnlQcm90by52ZXJpZnkobWVzc2FnZS5xdWFudFBhcmFtZXRlclRlbnNvck5hbWVzW2ldKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGVycm9yKVxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFwicXVhbnRQYXJhbWV0ZXJUZW5zb3JOYW1lcy5cIiArIGVycm9yO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9O1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBDcmVhdGVzIGEgVGVuc29yQW5ub3RhdGlvbiBtZXNzYWdlIGZyb20gYSBwbGFpbiBvYmplY3QuIEFsc28gY29udmVydHMgdmFsdWVzIHRvIHRoZWlyIHJlc3BlY3RpdmUgaW50ZXJuYWwgdHlwZXMuXG4gICAgICAgICAqIEBmdW5jdGlvbiBmcm9tT2JqZWN0XG4gICAgICAgICAqIEBtZW1iZXJvZiBvbm54LlRlbnNvckFubm90YXRpb25cbiAgICAgICAgICogQHN0YXRpY1xuICAgICAgICAgKiBAcGFyYW0ge09iamVjdC48c3RyaW5nLCo+fSBvYmplY3QgUGxhaW4gb2JqZWN0XG4gICAgICAgICAqIEByZXR1cm5zIHtvbm54LlRlbnNvckFubm90YXRpb259IFRlbnNvckFubm90YXRpb25cbiAgICAgICAgICovXG4gICAgICAgIFRlbnNvckFubm90YXRpb24uZnJvbU9iamVjdCA9IGZ1bmN0aW9uIGZyb21PYmplY3Qob2JqZWN0KSB7XG4gICAgICAgICAgICBpZiAob2JqZWN0IGluc3RhbmNlb2YgJHJvb3Qub25ueC5UZW5zb3JBbm5vdGF0aW9uKVxuICAgICAgICAgICAgICAgIHJldHVybiBvYmplY3Q7XG4gICAgICAgICAgICB2YXIgbWVzc2FnZSA9IG5ldyAkcm9vdC5vbm54LlRlbnNvckFubm90YXRpb24oKTtcbiAgICAgICAgICAgIGlmIChvYmplY3QudGVuc29yTmFtZSAhPSBudWxsKVxuICAgICAgICAgICAgICAgIG1lc3NhZ2UudGVuc29yTmFtZSA9IFN0cmluZyhvYmplY3QudGVuc29yTmFtZSk7XG4gICAgICAgICAgICBpZiAob2JqZWN0LnF1YW50UGFyYW1ldGVyVGVuc29yTmFtZXMpIHtcbiAgICAgICAgICAgICAgICBpZiAoIUFycmF5LmlzQXJyYXkob2JqZWN0LnF1YW50UGFyYW1ldGVyVGVuc29yTmFtZXMpKVxuICAgICAgICAgICAgICAgICAgICB0aHJvdyBUeXBlRXJyb3IoXCIub25ueC5UZW5zb3JBbm5vdGF0aW9uLnF1YW50UGFyYW1ldGVyVGVuc29yTmFtZXM6IGFycmF5IGV4cGVjdGVkXCIpO1xuICAgICAgICAgICAgICAgIG1lc3NhZ2UucXVhbnRQYXJhbWV0ZXJUZW5zb3JOYW1lcyA9IFtdO1xuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgb2JqZWN0LnF1YW50UGFyYW1ldGVyVGVuc29yTmFtZXMubGVuZ3RoOyArK2kpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBvYmplY3QucXVhbnRQYXJhbWV0ZXJUZW5zb3JOYW1lc1tpXSAhPT0gXCJvYmplY3RcIilcbiAgICAgICAgICAgICAgICAgICAgICAgIHRocm93IFR5cGVFcnJvcihcIi5vbm54LlRlbnNvckFubm90YXRpb24ucXVhbnRQYXJhbWV0ZXJUZW5zb3JOYW1lczogb2JqZWN0IGV4cGVjdGVkXCIpO1xuICAgICAgICAgICAgICAgICAgICBtZXNzYWdlLnF1YW50UGFyYW1ldGVyVGVuc29yTmFtZXNbaV0gPSAkcm9vdC5vbm54LlN0cmluZ1N0cmluZ0VudHJ5UHJvdG8uZnJvbU9iamVjdChvYmplY3QucXVhbnRQYXJhbWV0ZXJUZW5zb3JOYW1lc1tpXSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIG1lc3NhZ2U7XG4gICAgICAgIH07XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIENyZWF0ZXMgYSBwbGFpbiBvYmplY3QgZnJvbSBhIFRlbnNvckFubm90YXRpb24gbWVzc2FnZS4gQWxzbyBjb252ZXJ0cyB2YWx1ZXMgdG8gb3RoZXIgdHlwZXMgaWYgc3BlY2lmaWVkLlxuICAgICAgICAgKiBAZnVuY3Rpb24gdG9PYmplY3RcbiAgICAgICAgICogQG1lbWJlcm9mIG9ubnguVGVuc29yQW5ub3RhdGlvblxuICAgICAgICAgKiBAc3RhdGljXG4gICAgICAgICAqIEBwYXJhbSB7b25ueC5UZW5zb3JBbm5vdGF0aW9ufSBtZXNzYWdlIFRlbnNvckFubm90YXRpb25cbiAgICAgICAgICogQHBhcmFtIHskcHJvdG9idWYuSUNvbnZlcnNpb25PcHRpb25zfSBbb3B0aW9uc10gQ29udmVyc2lvbiBvcHRpb25zXG4gICAgICAgICAqIEByZXR1cm5zIHtPYmplY3QuPHN0cmluZywqPn0gUGxhaW4gb2JqZWN0XG4gICAgICAgICAqL1xuICAgICAgICBUZW5zb3JBbm5vdGF0aW9uLnRvT2JqZWN0ID0gZnVuY3Rpb24gdG9PYmplY3QobWVzc2FnZSwgb3B0aW9ucykge1xuICAgICAgICAgICAgaWYgKCFvcHRpb25zKVxuICAgICAgICAgICAgICAgIG9wdGlvbnMgPSB7fTtcbiAgICAgICAgICAgIHZhciBvYmplY3QgPSB7fTtcbiAgICAgICAgICAgIGlmIChvcHRpb25zLmFycmF5cyB8fCBvcHRpb25zLmRlZmF1bHRzKVxuICAgICAgICAgICAgICAgIG9iamVjdC5xdWFudFBhcmFtZXRlclRlbnNvck5hbWVzID0gW107XG4gICAgICAgICAgICBpZiAob3B0aW9ucy5kZWZhdWx0cylcbiAgICAgICAgICAgICAgICBvYmplY3QudGVuc29yTmFtZSA9IFwiXCI7XG4gICAgICAgICAgICBpZiAobWVzc2FnZS50ZW5zb3JOYW1lICE9IG51bGwgJiYgbWVzc2FnZS5oYXNPd25Qcm9wZXJ0eShcInRlbnNvck5hbWVcIikpXG4gICAgICAgICAgICAgICAgb2JqZWN0LnRlbnNvck5hbWUgPSBtZXNzYWdlLnRlbnNvck5hbWU7XG4gICAgICAgICAgICBpZiAobWVzc2FnZS5xdWFudFBhcmFtZXRlclRlbnNvck5hbWVzICYmIG1lc3NhZ2UucXVhbnRQYXJhbWV0ZXJUZW5zb3JOYW1lcy5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICBvYmplY3QucXVhbnRQYXJhbWV0ZXJUZW5zb3JOYW1lcyA9IFtdO1xuICAgICAgICAgICAgICAgIGZvciAodmFyIGogPSAwOyBqIDwgbWVzc2FnZS5xdWFudFBhcmFtZXRlclRlbnNvck5hbWVzLmxlbmd0aDsgKytqKVxuICAgICAgICAgICAgICAgICAgICBvYmplY3QucXVhbnRQYXJhbWV0ZXJUZW5zb3JOYW1lc1tqXSA9ICRyb290Lm9ubnguU3RyaW5nU3RyaW5nRW50cnlQcm90by50b09iamVjdChtZXNzYWdlLnF1YW50UGFyYW1ldGVyVGVuc29yTmFtZXNbal0sIG9wdGlvbnMpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIG9iamVjdDtcbiAgICAgICAgfTtcblxuICAgICAgICAvKipcbiAgICAgICAgICogQ29udmVydHMgdGhpcyBUZW5zb3JBbm5vdGF0aW9uIHRvIEpTT04uXG4gICAgICAgICAqIEBmdW5jdGlvbiB0b0pTT05cbiAgICAgICAgICogQG1lbWJlcm9mIG9ubnguVGVuc29yQW5ub3RhdGlvblxuICAgICAgICAgKiBAaW5zdGFuY2VcbiAgICAgICAgICogQHJldHVybnMge09iamVjdC48c3RyaW5nLCo+fSBKU09OIG9iamVjdFxuICAgICAgICAgKi9cbiAgICAgICAgVGVuc29yQW5ub3RhdGlvbi5wcm90b3R5cGUudG9KU09OID0gZnVuY3Rpb24gdG9KU09OKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuY29uc3RydWN0b3IudG9PYmplY3QodGhpcywgJHByb3RvYnVmLnV0aWwudG9KU09OT3B0aW9ucyk7XG4gICAgICAgIH07XG5cbiAgICAgICAgcmV0dXJuIFRlbnNvckFubm90YXRpb247XG4gICAgfSkoKTtcblxuICAgIG9ubnguR3JhcGhQcm90byA9IChmdW5jdGlvbigpIHtcblxuICAgICAgICAvKipcbiAgICAgICAgICogUHJvcGVydGllcyBvZiBhIEdyYXBoUHJvdG8uXG4gICAgICAgICAqIEBtZW1iZXJvZiBvbm54XG4gICAgICAgICAqIEBpbnRlcmZhY2UgSUdyYXBoUHJvdG9cbiAgICAgICAgICogQHByb3BlcnR5IHtBcnJheS48b25ueC5JTm9kZVByb3RvPnxudWxsfSBbbm9kZV0gR3JhcGhQcm90byBub2RlXG4gICAgICAgICAqIEBwcm9wZXJ0eSB7c3RyaW5nfG51bGx9IFtuYW1lXSBHcmFwaFByb3RvIG5hbWVcbiAgICAgICAgICogQHByb3BlcnR5IHtBcnJheS48b25ueC5JVGVuc29yUHJvdG8+fG51bGx9IFtpbml0aWFsaXplcl0gR3JhcGhQcm90byBpbml0aWFsaXplclxuICAgICAgICAgKiBAcHJvcGVydHkge3N0cmluZ3xudWxsfSBbZG9jU3RyaW5nXSBHcmFwaFByb3RvIGRvY1N0cmluZ1xuICAgICAgICAgKiBAcHJvcGVydHkge0FycmF5Ljxvbm54LklWYWx1ZUluZm9Qcm90bz58bnVsbH0gW2lucHV0XSBHcmFwaFByb3RvIGlucHV0XG4gICAgICAgICAqIEBwcm9wZXJ0eSB7QXJyYXkuPG9ubnguSVZhbHVlSW5mb1Byb3RvPnxudWxsfSBbb3V0cHV0XSBHcmFwaFByb3RvIG91dHB1dFxuICAgICAgICAgKiBAcHJvcGVydHkge0FycmF5Ljxvbm54LklWYWx1ZUluZm9Qcm90bz58bnVsbH0gW3ZhbHVlSW5mb10gR3JhcGhQcm90byB2YWx1ZUluZm9cbiAgICAgICAgICogQHByb3BlcnR5IHtBcnJheS48b25ueC5JVGVuc29yQW5ub3RhdGlvbj58bnVsbH0gW3F1YW50aXphdGlvbkFubm90YXRpb25dIEdyYXBoUHJvdG8gcXVhbnRpemF0aW9uQW5ub3RhdGlvblxuICAgICAgICAgKi9cblxuICAgICAgICAvKipcbiAgICAgICAgICogQ29uc3RydWN0cyBhIG5ldyBHcmFwaFByb3RvLlxuICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueFxuICAgICAgICAgKiBAY2xhc3NkZXNjIFJlcHJlc2VudHMgYSBHcmFwaFByb3RvLlxuICAgICAgICAgKiBAaW1wbGVtZW50cyBJR3JhcGhQcm90b1xuICAgICAgICAgKiBAY29uc3RydWN0b3JcbiAgICAgICAgICogQHBhcmFtIHtvbm54LklHcmFwaFByb3RvPX0gW3Byb3BlcnRpZXNdIFByb3BlcnRpZXMgdG8gc2V0XG4gICAgICAgICAqL1xuICAgICAgICBmdW5jdGlvbiBHcmFwaFByb3RvKHByb3BlcnRpZXMpIHtcbiAgICAgICAgICAgIHRoaXMubm9kZSA9IFtdO1xuICAgICAgICAgICAgdGhpcy5pbml0aWFsaXplciA9IFtdO1xuICAgICAgICAgICAgdGhpcy5pbnB1dCA9IFtdO1xuICAgICAgICAgICAgdGhpcy5vdXRwdXQgPSBbXTtcbiAgICAgICAgICAgIHRoaXMudmFsdWVJbmZvID0gW107XG4gICAgICAgICAgICB0aGlzLnF1YW50aXphdGlvbkFubm90YXRpb24gPSBbXTtcbiAgICAgICAgICAgIGlmIChwcm9wZXJ0aWVzKVxuICAgICAgICAgICAgICAgIGZvciAodmFyIGtleXMgPSBPYmplY3Qua2V5cyhwcm9wZXJ0aWVzKSwgaSA9IDA7IGkgPCBrZXlzLmxlbmd0aDsgKytpKVxuICAgICAgICAgICAgICAgICAgICBpZiAocHJvcGVydGllc1trZXlzW2ldXSAhPSBudWxsKVxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpc1trZXlzW2ldXSA9IHByb3BlcnRpZXNba2V5c1tpXV07XG4gICAgICAgIH1cblxuICAgICAgICAvKipcbiAgICAgICAgICogR3JhcGhQcm90byBub2RlLlxuICAgICAgICAgKiBAbWVtYmVyIHtBcnJheS48b25ueC5JTm9kZVByb3RvPn0gbm9kZVxuICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueC5HcmFwaFByb3RvXG4gICAgICAgICAqIEBpbnN0YW5jZVxuICAgICAgICAgKi9cbiAgICAgICAgR3JhcGhQcm90by5wcm90b3R5cGUubm9kZSA9ICR1dGlsLmVtcHR5QXJyYXk7XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEdyYXBoUHJvdG8gbmFtZS5cbiAgICAgICAgICogQG1lbWJlciB7c3RyaW5nfSBuYW1lXG4gICAgICAgICAqIEBtZW1iZXJvZiBvbm54LkdyYXBoUHJvdG9cbiAgICAgICAgICogQGluc3RhbmNlXG4gICAgICAgICAqL1xuICAgICAgICBHcmFwaFByb3RvLnByb3RvdHlwZS5uYW1lID0gXCJcIjtcblxuICAgICAgICAvKipcbiAgICAgICAgICogR3JhcGhQcm90byBpbml0aWFsaXplci5cbiAgICAgICAgICogQG1lbWJlciB7QXJyYXkuPG9ubnguSVRlbnNvclByb3RvPn0gaW5pdGlhbGl6ZXJcbiAgICAgICAgICogQG1lbWJlcm9mIG9ubnguR3JhcGhQcm90b1xuICAgICAgICAgKiBAaW5zdGFuY2VcbiAgICAgICAgICovXG4gICAgICAgIEdyYXBoUHJvdG8ucHJvdG90eXBlLmluaXRpYWxpemVyID0gJHV0aWwuZW1wdHlBcnJheTtcblxuICAgICAgICAvKipcbiAgICAgICAgICogR3JhcGhQcm90byBkb2NTdHJpbmcuXG4gICAgICAgICAqIEBtZW1iZXIge3N0cmluZ30gZG9jU3RyaW5nXG4gICAgICAgICAqIEBtZW1iZXJvZiBvbm54LkdyYXBoUHJvdG9cbiAgICAgICAgICogQGluc3RhbmNlXG4gICAgICAgICAqL1xuICAgICAgICBHcmFwaFByb3RvLnByb3RvdHlwZS5kb2NTdHJpbmcgPSBcIlwiO1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBHcmFwaFByb3RvIGlucHV0LlxuICAgICAgICAgKiBAbWVtYmVyIHtBcnJheS48b25ueC5JVmFsdWVJbmZvUHJvdG8+fSBpbnB1dFxuICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueC5HcmFwaFByb3RvXG4gICAgICAgICAqIEBpbnN0YW5jZVxuICAgICAgICAgKi9cbiAgICAgICAgR3JhcGhQcm90by5wcm90b3R5cGUuaW5wdXQgPSAkdXRpbC5lbXB0eUFycmF5O1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBHcmFwaFByb3RvIG91dHB1dC5cbiAgICAgICAgICogQG1lbWJlciB7QXJyYXkuPG9ubnguSVZhbHVlSW5mb1Byb3RvPn0gb3V0cHV0XG4gICAgICAgICAqIEBtZW1iZXJvZiBvbm54LkdyYXBoUHJvdG9cbiAgICAgICAgICogQGluc3RhbmNlXG4gICAgICAgICAqL1xuICAgICAgICBHcmFwaFByb3RvLnByb3RvdHlwZS5vdXRwdXQgPSAkdXRpbC5lbXB0eUFycmF5O1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBHcmFwaFByb3RvIHZhbHVlSW5mby5cbiAgICAgICAgICogQG1lbWJlciB7QXJyYXkuPG9ubnguSVZhbHVlSW5mb1Byb3RvPn0gdmFsdWVJbmZvXG4gICAgICAgICAqIEBtZW1iZXJvZiBvbm54LkdyYXBoUHJvdG9cbiAgICAgICAgICogQGluc3RhbmNlXG4gICAgICAgICAqL1xuICAgICAgICBHcmFwaFByb3RvLnByb3RvdHlwZS52YWx1ZUluZm8gPSAkdXRpbC5lbXB0eUFycmF5O1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBHcmFwaFByb3RvIHF1YW50aXphdGlvbkFubm90YXRpb24uXG4gICAgICAgICAqIEBtZW1iZXIge0FycmF5Ljxvbm54LklUZW5zb3JBbm5vdGF0aW9uPn0gcXVhbnRpemF0aW9uQW5ub3RhdGlvblxuICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueC5HcmFwaFByb3RvXG4gICAgICAgICAqIEBpbnN0YW5jZVxuICAgICAgICAgKi9cbiAgICAgICAgR3JhcGhQcm90by5wcm90b3R5cGUucXVhbnRpemF0aW9uQW5ub3RhdGlvbiA9ICR1dGlsLmVtcHR5QXJyYXk7XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIENyZWF0ZXMgYSBuZXcgR3JhcGhQcm90byBpbnN0YW5jZSB1c2luZyB0aGUgc3BlY2lmaWVkIHByb3BlcnRpZXMuXG4gICAgICAgICAqIEBmdW5jdGlvbiBjcmVhdGVcbiAgICAgICAgICogQG1lbWJlcm9mIG9ubnguR3JhcGhQcm90b1xuICAgICAgICAgKiBAc3RhdGljXG4gICAgICAgICAqIEBwYXJhbSB7b25ueC5JR3JhcGhQcm90bz19IFtwcm9wZXJ0aWVzXSBQcm9wZXJ0aWVzIHRvIHNldFxuICAgICAgICAgKiBAcmV0dXJucyB7b25ueC5HcmFwaFByb3RvfSBHcmFwaFByb3RvIGluc3RhbmNlXG4gICAgICAgICAqL1xuICAgICAgICBHcmFwaFByb3RvLmNyZWF0ZSA9IGZ1bmN0aW9uIGNyZWF0ZShwcm9wZXJ0aWVzKSB7XG4gICAgICAgICAgICByZXR1cm4gbmV3IEdyYXBoUHJvdG8ocHJvcGVydGllcyk7XG4gICAgICAgIH07XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEVuY29kZXMgdGhlIHNwZWNpZmllZCBHcmFwaFByb3RvIG1lc3NhZ2UuIERvZXMgbm90IGltcGxpY2l0bHkge0BsaW5rIG9ubnguR3JhcGhQcm90by52ZXJpZnl8dmVyaWZ5fSBtZXNzYWdlcy5cbiAgICAgICAgICogQGZ1bmN0aW9uIGVuY29kZVxuICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueC5HcmFwaFByb3RvXG4gICAgICAgICAqIEBzdGF0aWNcbiAgICAgICAgICogQHBhcmFtIHtvbm54LklHcmFwaFByb3RvfSBtZXNzYWdlIEdyYXBoUHJvdG8gbWVzc2FnZSBvciBwbGFpbiBvYmplY3QgdG8gZW5jb2RlXG4gICAgICAgICAqIEBwYXJhbSB7JHByb3RvYnVmLldyaXRlcn0gW3dyaXRlcl0gV3JpdGVyIHRvIGVuY29kZSB0b1xuICAgICAgICAgKiBAcmV0dXJucyB7JHByb3RvYnVmLldyaXRlcn0gV3JpdGVyXG4gICAgICAgICAqL1xuICAgICAgICBHcmFwaFByb3RvLmVuY29kZSA9IGZ1bmN0aW9uIGVuY29kZShtZXNzYWdlLCB3cml0ZXIpIHtcbiAgICAgICAgICAgIGlmICghd3JpdGVyKVxuICAgICAgICAgICAgICAgIHdyaXRlciA9ICRXcml0ZXIuY3JlYXRlKCk7XG4gICAgICAgICAgICBpZiAobWVzc2FnZS5ub2RlICE9IG51bGwgJiYgbWVzc2FnZS5ub2RlLmxlbmd0aClcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG1lc3NhZ2Uubm9kZS5sZW5ndGg7ICsraSlcbiAgICAgICAgICAgICAgICAgICAgJHJvb3Qub25ueC5Ob2RlUHJvdG8uZW5jb2RlKG1lc3NhZ2Uubm9kZVtpXSwgd3JpdGVyLnVpbnQzMigvKiBpZCAxLCB3aXJlVHlwZSAyID0qLzEwKS5mb3JrKCkpLmxkZWxpbSgpO1xuICAgICAgICAgICAgaWYgKG1lc3NhZ2UubmFtZSAhPSBudWxsICYmIG1lc3NhZ2UuaGFzT3duUHJvcGVydHkoXCJuYW1lXCIpKVxuICAgICAgICAgICAgICAgIHdyaXRlci51aW50MzIoLyogaWQgMiwgd2lyZVR5cGUgMiA9Ki8xOCkuc3RyaW5nKG1lc3NhZ2UubmFtZSk7XG4gICAgICAgICAgICBpZiAobWVzc2FnZS5pbml0aWFsaXplciAhPSBudWxsICYmIG1lc3NhZ2UuaW5pdGlhbGl6ZXIubGVuZ3RoKVxuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbWVzc2FnZS5pbml0aWFsaXplci5sZW5ndGg7ICsraSlcbiAgICAgICAgICAgICAgICAgICAgJHJvb3Qub25ueC5UZW5zb3JQcm90by5lbmNvZGUobWVzc2FnZS5pbml0aWFsaXplcltpXSwgd3JpdGVyLnVpbnQzMigvKiBpZCA1LCB3aXJlVHlwZSAyID0qLzQyKS5mb3JrKCkpLmxkZWxpbSgpO1xuICAgICAgICAgICAgaWYgKG1lc3NhZ2UuZG9jU3RyaW5nICE9IG51bGwgJiYgbWVzc2FnZS5oYXNPd25Qcm9wZXJ0eShcImRvY1N0cmluZ1wiKSlcbiAgICAgICAgICAgICAgICB3cml0ZXIudWludDMyKC8qIGlkIDEwLCB3aXJlVHlwZSAyID0qLzgyKS5zdHJpbmcobWVzc2FnZS5kb2NTdHJpbmcpO1xuICAgICAgICAgICAgaWYgKG1lc3NhZ2UuaW5wdXQgIT0gbnVsbCAmJiBtZXNzYWdlLmlucHV0Lmxlbmd0aClcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG1lc3NhZ2UuaW5wdXQubGVuZ3RoOyArK2kpXG4gICAgICAgICAgICAgICAgICAgICRyb290Lm9ubnguVmFsdWVJbmZvUHJvdG8uZW5jb2RlKG1lc3NhZ2UuaW5wdXRbaV0sIHdyaXRlci51aW50MzIoLyogaWQgMTEsIHdpcmVUeXBlIDIgPSovOTApLmZvcmsoKSkubGRlbGltKCk7XG4gICAgICAgICAgICBpZiAobWVzc2FnZS5vdXRwdXQgIT0gbnVsbCAmJiBtZXNzYWdlLm91dHB1dC5sZW5ndGgpXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBtZXNzYWdlLm91dHB1dC5sZW5ndGg7ICsraSlcbiAgICAgICAgICAgICAgICAgICAgJHJvb3Qub25ueC5WYWx1ZUluZm9Qcm90by5lbmNvZGUobWVzc2FnZS5vdXRwdXRbaV0sIHdyaXRlci51aW50MzIoLyogaWQgMTIsIHdpcmVUeXBlIDIgPSovOTgpLmZvcmsoKSkubGRlbGltKCk7XG4gICAgICAgICAgICBpZiAobWVzc2FnZS52YWx1ZUluZm8gIT0gbnVsbCAmJiBtZXNzYWdlLnZhbHVlSW5mby5sZW5ndGgpXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBtZXNzYWdlLnZhbHVlSW5mby5sZW5ndGg7ICsraSlcbiAgICAgICAgICAgICAgICAgICAgJHJvb3Qub25ueC5WYWx1ZUluZm9Qcm90by5lbmNvZGUobWVzc2FnZS52YWx1ZUluZm9baV0sIHdyaXRlci51aW50MzIoLyogaWQgMTMsIHdpcmVUeXBlIDIgPSovMTA2KS5mb3JrKCkpLmxkZWxpbSgpO1xuICAgICAgICAgICAgaWYgKG1lc3NhZ2UucXVhbnRpemF0aW9uQW5ub3RhdGlvbiAhPSBudWxsICYmIG1lc3NhZ2UucXVhbnRpemF0aW9uQW5ub3RhdGlvbi5sZW5ndGgpXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBtZXNzYWdlLnF1YW50aXphdGlvbkFubm90YXRpb24ubGVuZ3RoOyArK2kpXG4gICAgICAgICAgICAgICAgICAgICRyb290Lm9ubnguVGVuc29yQW5ub3RhdGlvbi5lbmNvZGUobWVzc2FnZS5xdWFudGl6YXRpb25Bbm5vdGF0aW9uW2ldLCB3cml0ZXIudWludDMyKC8qIGlkIDE0LCB3aXJlVHlwZSAyID0qLzExNCkuZm9yaygpKS5sZGVsaW0oKTtcbiAgICAgICAgICAgIHJldHVybiB3cml0ZXI7XG4gICAgICAgIH07XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEVuY29kZXMgdGhlIHNwZWNpZmllZCBHcmFwaFByb3RvIG1lc3NhZ2UsIGxlbmd0aCBkZWxpbWl0ZWQuIERvZXMgbm90IGltcGxpY2l0bHkge0BsaW5rIG9ubnguR3JhcGhQcm90by52ZXJpZnl8dmVyaWZ5fSBtZXNzYWdlcy5cbiAgICAgICAgICogQGZ1bmN0aW9uIGVuY29kZURlbGltaXRlZFxuICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueC5HcmFwaFByb3RvXG4gICAgICAgICAqIEBzdGF0aWNcbiAgICAgICAgICogQHBhcmFtIHtvbm54LklHcmFwaFByb3RvfSBtZXNzYWdlIEdyYXBoUHJvdG8gbWVzc2FnZSBvciBwbGFpbiBvYmplY3QgdG8gZW5jb2RlXG4gICAgICAgICAqIEBwYXJhbSB7JHByb3RvYnVmLldyaXRlcn0gW3dyaXRlcl0gV3JpdGVyIHRvIGVuY29kZSB0b1xuICAgICAgICAgKiBAcmV0dXJucyB7JHByb3RvYnVmLldyaXRlcn0gV3JpdGVyXG4gICAgICAgICAqL1xuICAgICAgICBHcmFwaFByb3RvLmVuY29kZURlbGltaXRlZCA9IGZ1bmN0aW9uIGVuY29kZURlbGltaXRlZChtZXNzYWdlLCB3cml0ZXIpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmVuY29kZShtZXNzYWdlLCB3cml0ZXIpLmxkZWxpbSgpO1xuICAgICAgICB9O1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBEZWNvZGVzIGEgR3JhcGhQcm90byBtZXNzYWdlIGZyb20gdGhlIHNwZWNpZmllZCByZWFkZXIgb3IgYnVmZmVyLlxuICAgICAgICAgKiBAZnVuY3Rpb24gZGVjb2RlXG4gICAgICAgICAqIEBtZW1iZXJvZiBvbm54LkdyYXBoUHJvdG9cbiAgICAgICAgICogQHN0YXRpY1xuICAgICAgICAgKiBAcGFyYW0geyRwcm90b2J1Zi5SZWFkZXJ8VWludDhBcnJheX0gcmVhZGVyIFJlYWRlciBvciBidWZmZXIgdG8gZGVjb2RlIGZyb21cbiAgICAgICAgICogQHBhcmFtIHtudW1iZXJ9IFtsZW5ndGhdIE1lc3NhZ2UgbGVuZ3RoIGlmIGtub3duIGJlZm9yZWhhbmRcbiAgICAgICAgICogQHJldHVybnMge29ubnguR3JhcGhQcm90b30gR3JhcGhQcm90b1xuICAgICAgICAgKiBAdGhyb3dzIHtFcnJvcn0gSWYgdGhlIHBheWxvYWQgaXMgbm90IGEgcmVhZGVyIG9yIHZhbGlkIGJ1ZmZlclxuICAgICAgICAgKiBAdGhyb3dzIHskcHJvdG9idWYudXRpbC5Qcm90b2NvbEVycm9yfSBJZiByZXF1aXJlZCBmaWVsZHMgYXJlIG1pc3NpbmdcbiAgICAgICAgICovXG4gICAgICAgIEdyYXBoUHJvdG8uZGVjb2RlID0gZnVuY3Rpb24gZGVjb2RlKHJlYWRlciwgbGVuZ3RoKSB7XG4gICAgICAgICAgICBpZiAoIShyZWFkZXIgaW5zdGFuY2VvZiAkUmVhZGVyKSlcbiAgICAgICAgICAgICAgICByZWFkZXIgPSAkUmVhZGVyLmNyZWF0ZShyZWFkZXIpO1xuICAgICAgICAgICAgdmFyIGVuZCA9IGxlbmd0aCA9PT0gdW5kZWZpbmVkID8gcmVhZGVyLmxlbiA6IHJlYWRlci5wb3MgKyBsZW5ndGgsIG1lc3NhZ2UgPSBuZXcgJHJvb3Qub25ueC5HcmFwaFByb3RvKCk7XG4gICAgICAgICAgICB3aGlsZSAocmVhZGVyLnBvcyA8IGVuZCkge1xuICAgICAgICAgICAgICAgIHZhciB0YWcgPSByZWFkZXIudWludDMyKCk7XG4gICAgICAgICAgICAgICAgc3dpdGNoICh0YWcgPj4+IDMpIHtcbiAgICAgICAgICAgICAgICBjYXNlIDE6XG4gICAgICAgICAgICAgICAgICAgIGlmICghKG1lc3NhZ2Uubm9kZSAmJiBtZXNzYWdlLm5vZGUubGVuZ3RoKSlcbiAgICAgICAgICAgICAgICAgICAgICAgIG1lc3NhZ2Uubm9kZSA9IFtdO1xuICAgICAgICAgICAgICAgICAgICBtZXNzYWdlLm5vZGUucHVzaCgkcm9vdC5vbm54Lk5vZGVQcm90by5kZWNvZGUocmVhZGVyLCByZWFkZXIudWludDMyKCkpKTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSAyOlxuICAgICAgICAgICAgICAgICAgICBtZXNzYWdlLm5hbWUgPSByZWFkZXIuc3RyaW5nKCk7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgNTpcbiAgICAgICAgICAgICAgICAgICAgaWYgKCEobWVzc2FnZS5pbml0aWFsaXplciAmJiBtZXNzYWdlLmluaXRpYWxpemVyLmxlbmd0aCkpXG4gICAgICAgICAgICAgICAgICAgICAgICBtZXNzYWdlLmluaXRpYWxpemVyID0gW107XG4gICAgICAgICAgICAgICAgICAgIG1lc3NhZ2UuaW5pdGlhbGl6ZXIucHVzaCgkcm9vdC5vbm54LlRlbnNvclByb3RvLmRlY29kZShyZWFkZXIsIHJlYWRlci51aW50MzIoKSkpO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlIDEwOlxuICAgICAgICAgICAgICAgICAgICBtZXNzYWdlLmRvY1N0cmluZyA9IHJlYWRlci5zdHJpbmcoKTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSAxMTpcbiAgICAgICAgICAgICAgICAgICAgaWYgKCEobWVzc2FnZS5pbnB1dCAmJiBtZXNzYWdlLmlucHV0Lmxlbmd0aCkpXG4gICAgICAgICAgICAgICAgICAgICAgICBtZXNzYWdlLmlucHV0ID0gW107XG4gICAgICAgICAgICAgICAgICAgIG1lc3NhZ2UuaW5wdXQucHVzaCgkcm9vdC5vbm54LlZhbHVlSW5mb1Byb3RvLmRlY29kZShyZWFkZXIsIHJlYWRlci51aW50MzIoKSkpO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlIDEyOlxuICAgICAgICAgICAgICAgICAgICBpZiAoIShtZXNzYWdlLm91dHB1dCAmJiBtZXNzYWdlLm91dHB1dC5sZW5ndGgpKVxuICAgICAgICAgICAgICAgICAgICAgICAgbWVzc2FnZS5vdXRwdXQgPSBbXTtcbiAgICAgICAgICAgICAgICAgICAgbWVzc2FnZS5vdXRwdXQucHVzaCgkcm9vdC5vbm54LlZhbHVlSW5mb1Byb3RvLmRlY29kZShyZWFkZXIsIHJlYWRlci51aW50MzIoKSkpO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlIDEzOlxuICAgICAgICAgICAgICAgICAgICBpZiAoIShtZXNzYWdlLnZhbHVlSW5mbyAmJiBtZXNzYWdlLnZhbHVlSW5mby5sZW5ndGgpKVxuICAgICAgICAgICAgICAgICAgICAgICAgbWVzc2FnZS52YWx1ZUluZm8gPSBbXTtcbiAgICAgICAgICAgICAgICAgICAgbWVzc2FnZS52YWx1ZUluZm8ucHVzaCgkcm9vdC5vbm54LlZhbHVlSW5mb1Byb3RvLmRlY29kZShyZWFkZXIsIHJlYWRlci51aW50MzIoKSkpO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlIDE0OlxuICAgICAgICAgICAgICAgICAgICBpZiAoIShtZXNzYWdlLnF1YW50aXphdGlvbkFubm90YXRpb24gJiYgbWVzc2FnZS5xdWFudGl6YXRpb25Bbm5vdGF0aW9uLmxlbmd0aCkpXG4gICAgICAgICAgICAgICAgICAgICAgICBtZXNzYWdlLnF1YW50aXphdGlvbkFubm90YXRpb24gPSBbXTtcbiAgICAgICAgICAgICAgICAgICAgbWVzc2FnZS5xdWFudGl6YXRpb25Bbm5vdGF0aW9uLnB1c2goJHJvb3Qub25ueC5UZW5zb3JBbm5vdGF0aW9uLmRlY29kZShyZWFkZXIsIHJlYWRlci51aW50MzIoKSkpO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgICAgICByZWFkZXIuc2tpcFR5cGUodGFnICYgNyk7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBtZXNzYWdlO1xuICAgICAgICB9O1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBEZWNvZGVzIGEgR3JhcGhQcm90byBtZXNzYWdlIGZyb20gdGhlIHNwZWNpZmllZCByZWFkZXIgb3IgYnVmZmVyLCBsZW5ndGggZGVsaW1pdGVkLlxuICAgICAgICAgKiBAZnVuY3Rpb24gZGVjb2RlRGVsaW1pdGVkXG4gICAgICAgICAqIEBtZW1iZXJvZiBvbm54LkdyYXBoUHJvdG9cbiAgICAgICAgICogQHN0YXRpY1xuICAgICAgICAgKiBAcGFyYW0geyRwcm90b2J1Zi5SZWFkZXJ8VWludDhBcnJheX0gcmVhZGVyIFJlYWRlciBvciBidWZmZXIgdG8gZGVjb2RlIGZyb21cbiAgICAgICAgICogQHJldHVybnMge29ubnguR3JhcGhQcm90b30gR3JhcGhQcm90b1xuICAgICAgICAgKiBAdGhyb3dzIHtFcnJvcn0gSWYgdGhlIHBheWxvYWQgaXMgbm90IGEgcmVhZGVyIG9yIHZhbGlkIGJ1ZmZlclxuICAgICAgICAgKiBAdGhyb3dzIHskcHJvdG9idWYudXRpbC5Qcm90b2NvbEVycm9yfSBJZiByZXF1aXJlZCBmaWVsZHMgYXJlIG1pc3NpbmdcbiAgICAgICAgICovXG4gICAgICAgIEdyYXBoUHJvdG8uZGVjb2RlRGVsaW1pdGVkID0gZnVuY3Rpb24gZGVjb2RlRGVsaW1pdGVkKHJlYWRlcikge1xuICAgICAgICAgICAgaWYgKCEocmVhZGVyIGluc3RhbmNlb2YgJFJlYWRlcikpXG4gICAgICAgICAgICAgICAgcmVhZGVyID0gbmV3ICRSZWFkZXIocmVhZGVyKTtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmRlY29kZShyZWFkZXIsIHJlYWRlci51aW50MzIoKSk7XG4gICAgICAgIH07XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIFZlcmlmaWVzIGEgR3JhcGhQcm90byBtZXNzYWdlLlxuICAgICAgICAgKiBAZnVuY3Rpb24gdmVyaWZ5XG4gICAgICAgICAqIEBtZW1iZXJvZiBvbm54LkdyYXBoUHJvdG9cbiAgICAgICAgICogQHN0YXRpY1xuICAgICAgICAgKiBAcGFyYW0ge09iamVjdC48c3RyaW5nLCo+fSBtZXNzYWdlIFBsYWluIG9iamVjdCB0byB2ZXJpZnlcbiAgICAgICAgICogQHJldHVybnMge3N0cmluZ3xudWxsfSBgbnVsbGAgaWYgdmFsaWQsIG90aGVyd2lzZSB0aGUgcmVhc29uIHdoeSBpdCBpcyBub3RcbiAgICAgICAgICovXG4gICAgICAgIEdyYXBoUHJvdG8udmVyaWZ5ID0gZnVuY3Rpb24gdmVyaWZ5KG1lc3NhZ2UpIHtcbiAgICAgICAgICAgIGlmICh0eXBlb2YgbWVzc2FnZSAhPT0gXCJvYmplY3RcIiB8fCBtZXNzYWdlID09PSBudWxsKVxuICAgICAgICAgICAgICAgIHJldHVybiBcIm9iamVjdCBleHBlY3RlZFwiO1xuICAgICAgICAgICAgaWYgKG1lc3NhZ2Uubm9kZSAhPSBudWxsICYmIG1lc3NhZ2UuaGFzT3duUHJvcGVydHkoXCJub2RlXCIpKSB7XG4gICAgICAgICAgICAgICAgaWYgKCFBcnJheS5pc0FycmF5KG1lc3NhZ2Uubm9kZSkpXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBcIm5vZGU6IGFycmF5IGV4cGVjdGVkXCI7XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBtZXNzYWdlLm5vZGUubGVuZ3RoOyArK2kpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGVycm9yID0gJHJvb3Qub25ueC5Ob2RlUHJvdG8udmVyaWZ5KG1lc3NhZ2Uubm9kZVtpXSk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChlcnJvcilcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBcIm5vZGUuXCIgKyBlcnJvcjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAobWVzc2FnZS5uYW1lICE9IG51bGwgJiYgbWVzc2FnZS5oYXNPd25Qcm9wZXJ0eShcIm5hbWVcIikpXG4gICAgICAgICAgICAgICAgaWYgKCEkdXRpbC5pc1N0cmluZyhtZXNzYWdlLm5hbWUpKVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gXCJuYW1lOiBzdHJpbmcgZXhwZWN0ZWRcIjtcbiAgICAgICAgICAgIGlmIChtZXNzYWdlLmluaXRpYWxpemVyICE9IG51bGwgJiYgbWVzc2FnZS5oYXNPd25Qcm9wZXJ0eShcImluaXRpYWxpemVyXCIpKSB7XG4gICAgICAgICAgICAgICAgaWYgKCFBcnJheS5pc0FycmF5KG1lc3NhZ2UuaW5pdGlhbGl6ZXIpKVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gXCJpbml0aWFsaXplcjogYXJyYXkgZXhwZWN0ZWRcIjtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG1lc3NhZ2UuaW5pdGlhbGl6ZXIubGVuZ3RoOyArK2kpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGVycm9yID0gJHJvb3Qub25ueC5UZW5zb3JQcm90by52ZXJpZnkobWVzc2FnZS5pbml0aWFsaXplcltpXSk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChlcnJvcilcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBcImluaXRpYWxpemVyLlwiICsgZXJyb3I7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG1lc3NhZ2UuZG9jU3RyaW5nICE9IG51bGwgJiYgbWVzc2FnZS5oYXNPd25Qcm9wZXJ0eShcImRvY1N0cmluZ1wiKSlcbiAgICAgICAgICAgICAgICBpZiAoISR1dGlsLmlzU3RyaW5nKG1lc3NhZ2UuZG9jU3RyaW5nKSlcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFwiZG9jU3RyaW5nOiBzdHJpbmcgZXhwZWN0ZWRcIjtcbiAgICAgICAgICAgIGlmIChtZXNzYWdlLmlucHV0ICE9IG51bGwgJiYgbWVzc2FnZS5oYXNPd25Qcm9wZXJ0eShcImlucHV0XCIpKSB7XG4gICAgICAgICAgICAgICAgaWYgKCFBcnJheS5pc0FycmF5KG1lc3NhZ2UuaW5wdXQpKVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gXCJpbnB1dDogYXJyYXkgZXhwZWN0ZWRcIjtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG1lc3NhZ2UuaW5wdXQubGVuZ3RoOyArK2kpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGVycm9yID0gJHJvb3Qub25ueC5WYWx1ZUluZm9Qcm90by52ZXJpZnkobWVzc2FnZS5pbnB1dFtpXSk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChlcnJvcilcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBcImlucHV0LlwiICsgZXJyb3I7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG1lc3NhZ2Uub3V0cHV0ICE9IG51bGwgJiYgbWVzc2FnZS5oYXNPd25Qcm9wZXJ0eShcIm91dHB1dFwiKSkge1xuICAgICAgICAgICAgICAgIGlmICghQXJyYXkuaXNBcnJheShtZXNzYWdlLm91dHB1dCkpXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBcIm91dHB1dDogYXJyYXkgZXhwZWN0ZWRcIjtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG1lc3NhZ2Uub3V0cHV0Lmxlbmd0aDsgKytpKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBlcnJvciA9ICRyb290Lm9ubnguVmFsdWVJbmZvUHJvdG8udmVyaWZ5KG1lc3NhZ2Uub3V0cHV0W2ldKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGVycm9yKVxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFwib3V0cHV0LlwiICsgZXJyb3I7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG1lc3NhZ2UudmFsdWVJbmZvICE9IG51bGwgJiYgbWVzc2FnZS5oYXNPd25Qcm9wZXJ0eShcInZhbHVlSW5mb1wiKSkge1xuICAgICAgICAgICAgICAgIGlmICghQXJyYXkuaXNBcnJheShtZXNzYWdlLnZhbHVlSW5mbykpXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBcInZhbHVlSW5mbzogYXJyYXkgZXhwZWN0ZWRcIjtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG1lc3NhZ2UudmFsdWVJbmZvLmxlbmd0aDsgKytpKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBlcnJvciA9ICRyb290Lm9ubnguVmFsdWVJbmZvUHJvdG8udmVyaWZ5KG1lc3NhZ2UudmFsdWVJbmZvW2ldKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGVycm9yKVxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFwidmFsdWVJbmZvLlwiICsgZXJyb3I7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG1lc3NhZ2UucXVhbnRpemF0aW9uQW5ub3RhdGlvbiAhPSBudWxsICYmIG1lc3NhZ2UuaGFzT3duUHJvcGVydHkoXCJxdWFudGl6YXRpb25Bbm5vdGF0aW9uXCIpKSB7XG4gICAgICAgICAgICAgICAgaWYgKCFBcnJheS5pc0FycmF5KG1lc3NhZ2UucXVhbnRpemF0aW9uQW5ub3RhdGlvbikpXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBcInF1YW50aXphdGlvbkFubm90YXRpb246IGFycmF5IGV4cGVjdGVkXCI7XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBtZXNzYWdlLnF1YW50aXphdGlvbkFubm90YXRpb24ubGVuZ3RoOyArK2kpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGVycm9yID0gJHJvb3Qub25ueC5UZW5zb3JBbm5vdGF0aW9uLnZlcmlmeShtZXNzYWdlLnF1YW50aXphdGlvbkFubm90YXRpb25baV0pO1xuICAgICAgICAgICAgICAgICAgICBpZiAoZXJyb3IpXG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gXCJxdWFudGl6YXRpb25Bbm5vdGF0aW9uLlwiICsgZXJyb3I7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgIH07XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIENyZWF0ZXMgYSBHcmFwaFByb3RvIG1lc3NhZ2UgZnJvbSBhIHBsYWluIG9iamVjdC4gQWxzbyBjb252ZXJ0cyB2YWx1ZXMgdG8gdGhlaXIgcmVzcGVjdGl2ZSBpbnRlcm5hbCB0eXBlcy5cbiAgICAgICAgICogQGZ1bmN0aW9uIGZyb21PYmplY3RcbiAgICAgICAgICogQG1lbWJlcm9mIG9ubnguR3JhcGhQcm90b1xuICAgICAgICAgKiBAc3RhdGljXG4gICAgICAgICAqIEBwYXJhbSB7T2JqZWN0LjxzdHJpbmcsKj59IG9iamVjdCBQbGFpbiBvYmplY3RcbiAgICAgICAgICogQHJldHVybnMge29ubnguR3JhcGhQcm90b30gR3JhcGhQcm90b1xuICAgICAgICAgKi9cbiAgICAgICAgR3JhcGhQcm90by5mcm9tT2JqZWN0ID0gZnVuY3Rpb24gZnJvbU9iamVjdChvYmplY3QpIHtcbiAgICAgICAgICAgIGlmIChvYmplY3QgaW5zdGFuY2VvZiAkcm9vdC5vbm54LkdyYXBoUHJvdG8pXG4gICAgICAgICAgICAgICAgcmV0dXJuIG9iamVjdDtcbiAgICAgICAgICAgIHZhciBtZXNzYWdlID0gbmV3ICRyb290Lm9ubnguR3JhcGhQcm90bygpO1xuICAgICAgICAgICAgaWYgKG9iamVjdC5ub2RlKSB7XG4gICAgICAgICAgICAgICAgaWYgKCFBcnJheS5pc0FycmF5KG9iamVjdC5ub2RlKSlcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgVHlwZUVycm9yKFwiLm9ubnguR3JhcGhQcm90by5ub2RlOiBhcnJheSBleHBlY3RlZFwiKTtcbiAgICAgICAgICAgICAgICBtZXNzYWdlLm5vZGUgPSBbXTtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG9iamVjdC5ub2RlLmxlbmd0aDsgKytpKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2Ygb2JqZWN0Lm5vZGVbaV0gIT09IFwib2JqZWN0XCIpXG4gICAgICAgICAgICAgICAgICAgICAgICB0aHJvdyBUeXBlRXJyb3IoXCIub25ueC5HcmFwaFByb3RvLm5vZGU6IG9iamVjdCBleHBlY3RlZFwiKTtcbiAgICAgICAgICAgICAgICAgICAgbWVzc2FnZS5ub2RlW2ldID0gJHJvb3Qub25ueC5Ob2RlUHJvdG8uZnJvbU9iamVjdChvYmplY3Qubm9kZVtpXSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG9iamVjdC5uYW1lICE9IG51bGwpXG4gICAgICAgICAgICAgICAgbWVzc2FnZS5uYW1lID0gU3RyaW5nKG9iamVjdC5uYW1lKTtcbiAgICAgICAgICAgIGlmIChvYmplY3QuaW5pdGlhbGl6ZXIpIHtcbiAgICAgICAgICAgICAgICBpZiAoIUFycmF5LmlzQXJyYXkob2JqZWN0LmluaXRpYWxpemVyKSlcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgVHlwZUVycm9yKFwiLm9ubnguR3JhcGhQcm90by5pbml0aWFsaXplcjogYXJyYXkgZXhwZWN0ZWRcIik7XG4gICAgICAgICAgICAgICAgbWVzc2FnZS5pbml0aWFsaXplciA9IFtdO1xuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgb2JqZWN0LmluaXRpYWxpemVyLmxlbmd0aDsgKytpKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2Ygb2JqZWN0LmluaXRpYWxpemVyW2ldICE9PSBcIm9iamVjdFwiKVxuICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3cgVHlwZUVycm9yKFwiLm9ubnguR3JhcGhQcm90by5pbml0aWFsaXplcjogb2JqZWN0IGV4cGVjdGVkXCIpO1xuICAgICAgICAgICAgICAgICAgICBtZXNzYWdlLmluaXRpYWxpemVyW2ldID0gJHJvb3Qub25ueC5UZW5zb3JQcm90by5mcm9tT2JqZWN0KG9iamVjdC5pbml0aWFsaXplcltpXSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG9iamVjdC5kb2NTdHJpbmcgIT0gbnVsbClcbiAgICAgICAgICAgICAgICBtZXNzYWdlLmRvY1N0cmluZyA9IFN0cmluZyhvYmplY3QuZG9jU3RyaW5nKTtcbiAgICAgICAgICAgIGlmIChvYmplY3QuaW5wdXQpIHtcbiAgICAgICAgICAgICAgICBpZiAoIUFycmF5LmlzQXJyYXkob2JqZWN0LmlucHV0KSlcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgVHlwZUVycm9yKFwiLm9ubnguR3JhcGhQcm90by5pbnB1dDogYXJyYXkgZXhwZWN0ZWRcIik7XG4gICAgICAgICAgICAgICAgbWVzc2FnZS5pbnB1dCA9IFtdO1xuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgb2JqZWN0LmlucHV0Lmxlbmd0aDsgKytpKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2Ygb2JqZWN0LmlucHV0W2ldICE9PSBcIm9iamVjdFwiKVxuICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3cgVHlwZUVycm9yKFwiLm9ubnguR3JhcGhQcm90by5pbnB1dDogb2JqZWN0IGV4cGVjdGVkXCIpO1xuICAgICAgICAgICAgICAgICAgICBtZXNzYWdlLmlucHV0W2ldID0gJHJvb3Qub25ueC5WYWx1ZUluZm9Qcm90by5mcm9tT2JqZWN0KG9iamVjdC5pbnB1dFtpXSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG9iamVjdC5vdXRwdXQpIHtcbiAgICAgICAgICAgICAgICBpZiAoIUFycmF5LmlzQXJyYXkob2JqZWN0Lm91dHB1dCkpXG4gICAgICAgICAgICAgICAgICAgIHRocm93IFR5cGVFcnJvcihcIi5vbm54LkdyYXBoUHJvdG8ub3V0cHV0OiBhcnJheSBleHBlY3RlZFwiKTtcbiAgICAgICAgICAgICAgICBtZXNzYWdlLm91dHB1dCA9IFtdO1xuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgb2JqZWN0Lm91dHB1dC5sZW5ndGg7ICsraSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAodHlwZW9mIG9iamVjdC5vdXRwdXRbaV0gIT09IFwib2JqZWN0XCIpXG4gICAgICAgICAgICAgICAgICAgICAgICB0aHJvdyBUeXBlRXJyb3IoXCIub25ueC5HcmFwaFByb3RvLm91dHB1dDogb2JqZWN0IGV4cGVjdGVkXCIpO1xuICAgICAgICAgICAgICAgICAgICBtZXNzYWdlLm91dHB1dFtpXSA9ICRyb290Lm9ubnguVmFsdWVJbmZvUHJvdG8uZnJvbU9iamVjdChvYmplY3Qub3V0cHV0W2ldKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAob2JqZWN0LnZhbHVlSW5mbykge1xuICAgICAgICAgICAgICAgIGlmICghQXJyYXkuaXNBcnJheShvYmplY3QudmFsdWVJbmZvKSlcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgVHlwZUVycm9yKFwiLm9ubnguR3JhcGhQcm90by52YWx1ZUluZm86IGFycmF5IGV4cGVjdGVkXCIpO1xuICAgICAgICAgICAgICAgIG1lc3NhZ2UudmFsdWVJbmZvID0gW107XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBvYmplY3QudmFsdWVJbmZvLmxlbmd0aDsgKytpKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2Ygb2JqZWN0LnZhbHVlSW5mb1tpXSAhPT0gXCJvYmplY3RcIilcbiAgICAgICAgICAgICAgICAgICAgICAgIHRocm93IFR5cGVFcnJvcihcIi5vbm54LkdyYXBoUHJvdG8udmFsdWVJbmZvOiBvYmplY3QgZXhwZWN0ZWRcIik7XG4gICAgICAgICAgICAgICAgICAgIG1lc3NhZ2UudmFsdWVJbmZvW2ldID0gJHJvb3Qub25ueC5WYWx1ZUluZm9Qcm90by5mcm9tT2JqZWN0KG9iamVjdC52YWx1ZUluZm9baV0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChvYmplY3QucXVhbnRpemF0aW9uQW5ub3RhdGlvbikge1xuICAgICAgICAgICAgICAgIGlmICghQXJyYXkuaXNBcnJheShvYmplY3QucXVhbnRpemF0aW9uQW5ub3RhdGlvbikpXG4gICAgICAgICAgICAgICAgICAgIHRocm93IFR5cGVFcnJvcihcIi5vbm54LkdyYXBoUHJvdG8ucXVhbnRpemF0aW9uQW5ub3RhdGlvbjogYXJyYXkgZXhwZWN0ZWRcIik7XG4gICAgICAgICAgICAgICAgbWVzc2FnZS5xdWFudGl6YXRpb25Bbm5vdGF0aW9uID0gW107XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBvYmplY3QucXVhbnRpemF0aW9uQW5ub3RhdGlvbi5sZW5ndGg7ICsraSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAodHlwZW9mIG9iamVjdC5xdWFudGl6YXRpb25Bbm5vdGF0aW9uW2ldICE9PSBcIm9iamVjdFwiKVxuICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3cgVHlwZUVycm9yKFwiLm9ubnguR3JhcGhQcm90by5xdWFudGl6YXRpb25Bbm5vdGF0aW9uOiBvYmplY3QgZXhwZWN0ZWRcIik7XG4gICAgICAgICAgICAgICAgICAgIG1lc3NhZ2UucXVhbnRpemF0aW9uQW5ub3RhdGlvbltpXSA9ICRyb290Lm9ubnguVGVuc29yQW5ub3RhdGlvbi5mcm9tT2JqZWN0KG9iamVjdC5xdWFudGl6YXRpb25Bbm5vdGF0aW9uW2ldKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gbWVzc2FnZTtcbiAgICAgICAgfTtcblxuICAgICAgICAvKipcbiAgICAgICAgICogQ3JlYXRlcyBhIHBsYWluIG9iamVjdCBmcm9tIGEgR3JhcGhQcm90byBtZXNzYWdlLiBBbHNvIGNvbnZlcnRzIHZhbHVlcyB0byBvdGhlciB0eXBlcyBpZiBzcGVjaWZpZWQuXG4gICAgICAgICAqIEBmdW5jdGlvbiB0b09iamVjdFxuICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueC5HcmFwaFByb3RvXG4gICAgICAgICAqIEBzdGF0aWNcbiAgICAgICAgICogQHBhcmFtIHtvbm54LkdyYXBoUHJvdG99IG1lc3NhZ2UgR3JhcGhQcm90b1xuICAgICAgICAgKiBAcGFyYW0geyRwcm90b2J1Zi5JQ29udmVyc2lvbk9wdGlvbnN9IFtvcHRpb25zXSBDb252ZXJzaW9uIG9wdGlvbnNcbiAgICAgICAgICogQHJldHVybnMge09iamVjdC48c3RyaW5nLCo+fSBQbGFpbiBvYmplY3RcbiAgICAgICAgICovXG4gICAgICAgIEdyYXBoUHJvdG8udG9PYmplY3QgPSBmdW5jdGlvbiB0b09iamVjdChtZXNzYWdlLCBvcHRpb25zKSB7XG4gICAgICAgICAgICBpZiAoIW9wdGlvbnMpXG4gICAgICAgICAgICAgICAgb3B0aW9ucyA9IHt9O1xuICAgICAgICAgICAgdmFyIG9iamVjdCA9IHt9O1xuICAgICAgICAgICAgaWYgKG9wdGlvbnMuYXJyYXlzIHx8IG9wdGlvbnMuZGVmYXVsdHMpIHtcbiAgICAgICAgICAgICAgICBvYmplY3Qubm9kZSA9IFtdO1xuICAgICAgICAgICAgICAgIG9iamVjdC5pbml0aWFsaXplciA9IFtdO1xuICAgICAgICAgICAgICAgIG9iamVjdC5pbnB1dCA9IFtdO1xuICAgICAgICAgICAgICAgIG9iamVjdC5vdXRwdXQgPSBbXTtcbiAgICAgICAgICAgICAgICBvYmplY3QudmFsdWVJbmZvID0gW107XG4gICAgICAgICAgICAgICAgb2JqZWN0LnF1YW50aXphdGlvbkFubm90YXRpb24gPSBbXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChvcHRpb25zLmRlZmF1bHRzKSB7XG4gICAgICAgICAgICAgICAgb2JqZWN0Lm5hbWUgPSBcIlwiO1xuICAgICAgICAgICAgICAgIG9iamVjdC5kb2NTdHJpbmcgPSBcIlwiO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG1lc3NhZ2Uubm9kZSAmJiBtZXNzYWdlLm5vZGUubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgb2JqZWN0Lm5vZGUgPSBbXTtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBqID0gMDsgaiA8IG1lc3NhZ2Uubm9kZS5sZW5ndGg7ICsrailcbiAgICAgICAgICAgICAgICAgICAgb2JqZWN0Lm5vZGVbal0gPSAkcm9vdC5vbm54Lk5vZGVQcm90by50b09iamVjdChtZXNzYWdlLm5vZGVbal0sIG9wdGlvbnMpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG1lc3NhZ2UubmFtZSAhPSBudWxsICYmIG1lc3NhZ2UuaGFzT3duUHJvcGVydHkoXCJuYW1lXCIpKVxuICAgICAgICAgICAgICAgIG9iamVjdC5uYW1lID0gbWVzc2FnZS5uYW1lO1xuICAgICAgICAgICAgaWYgKG1lc3NhZ2UuaW5pdGlhbGl6ZXIgJiYgbWVzc2FnZS5pbml0aWFsaXplci5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICBvYmplY3QuaW5pdGlhbGl6ZXIgPSBbXTtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBqID0gMDsgaiA8IG1lc3NhZ2UuaW5pdGlhbGl6ZXIubGVuZ3RoOyArK2opXG4gICAgICAgICAgICAgICAgICAgIG9iamVjdC5pbml0aWFsaXplcltqXSA9ICRyb290Lm9ubnguVGVuc29yUHJvdG8udG9PYmplY3QobWVzc2FnZS5pbml0aWFsaXplcltqXSwgb3B0aW9ucyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAobWVzc2FnZS5kb2NTdHJpbmcgIT0gbnVsbCAmJiBtZXNzYWdlLmhhc093blByb3BlcnR5KFwiZG9jU3RyaW5nXCIpKVxuICAgICAgICAgICAgICAgIG9iamVjdC5kb2NTdHJpbmcgPSBtZXNzYWdlLmRvY1N0cmluZztcbiAgICAgICAgICAgIGlmIChtZXNzYWdlLmlucHV0ICYmIG1lc3NhZ2UuaW5wdXQubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgb2JqZWN0LmlucHV0ID0gW107XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaiA9IDA7IGogPCBtZXNzYWdlLmlucHV0Lmxlbmd0aDsgKytqKVxuICAgICAgICAgICAgICAgICAgICBvYmplY3QuaW5wdXRbal0gPSAkcm9vdC5vbm54LlZhbHVlSW5mb1Byb3RvLnRvT2JqZWN0KG1lc3NhZ2UuaW5wdXRbal0sIG9wdGlvbnMpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG1lc3NhZ2Uub3V0cHV0ICYmIG1lc3NhZ2Uub3V0cHV0Lmxlbmd0aCkge1xuICAgICAgICAgICAgICAgIG9iamVjdC5vdXRwdXQgPSBbXTtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBqID0gMDsgaiA8IG1lc3NhZ2Uub3V0cHV0Lmxlbmd0aDsgKytqKVxuICAgICAgICAgICAgICAgICAgICBvYmplY3Qub3V0cHV0W2pdID0gJHJvb3Qub25ueC5WYWx1ZUluZm9Qcm90by50b09iamVjdChtZXNzYWdlLm91dHB1dFtqXSwgb3B0aW9ucyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAobWVzc2FnZS52YWx1ZUluZm8gJiYgbWVzc2FnZS52YWx1ZUluZm8ubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgb2JqZWN0LnZhbHVlSW5mbyA9IFtdO1xuICAgICAgICAgICAgICAgIGZvciAodmFyIGogPSAwOyBqIDwgbWVzc2FnZS52YWx1ZUluZm8ubGVuZ3RoOyArK2opXG4gICAgICAgICAgICAgICAgICAgIG9iamVjdC52YWx1ZUluZm9bal0gPSAkcm9vdC5vbm54LlZhbHVlSW5mb1Byb3RvLnRvT2JqZWN0KG1lc3NhZ2UudmFsdWVJbmZvW2pdLCBvcHRpb25zKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChtZXNzYWdlLnF1YW50aXphdGlvbkFubm90YXRpb24gJiYgbWVzc2FnZS5xdWFudGl6YXRpb25Bbm5vdGF0aW9uLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgIG9iamVjdC5xdWFudGl6YXRpb25Bbm5vdGF0aW9uID0gW107XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaiA9IDA7IGogPCBtZXNzYWdlLnF1YW50aXphdGlvbkFubm90YXRpb24ubGVuZ3RoOyArK2opXG4gICAgICAgICAgICAgICAgICAgIG9iamVjdC5xdWFudGl6YXRpb25Bbm5vdGF0aW9uW2pdID0gJHJvb3Qub25ueC5UZW5zb3JBbm5vdGF0aW9uLnRvT2JqZWN0KG1lc3NhZ2UucXVhbnRpemF0aW9uQW5ub3RhdGlvbltqXSwgb3B0aW9ucyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gb2JqZWN0O1xuICAgICAgICB9O1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBDb252ZXJ0cyB0aGlzIEdyYXBoUHJvdG8gdG8gSlNPTi5cbiAgICAgICAgICogQGZ1bmN0aW9uIHRvSlNPTlxuICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueC5HcmFwaFByb3RvXG4gICAgICAgICAqIEBpbnN0YW5jZVxuICAgICAgICAgKiBAcmV0dXJucyB7T2JqZWN0LjxzdHJpbmcsKj59IEpTT04gb2JqZWN0XG4gICAgICAgICAqL1xuICAgICAgICBHcmFwaFByb3RvLnByb3RvdHlwZS50b0pTT04gPSBmdW5jdGlvbiB0b0pTT04oKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5jb25zdHJ1Y3Rvci50b09iamVjdCh0aGlzLCAkcHJvdG9idWYudXRpbC50b0pTT05PcHRpb25zKTtcbiAgICAgICAgfTtcblxuICAgICAgICByZXR1cm4gR3JhcGhQcm90bztcbiAgICB9KSgpO1xuXG4gICAgb25ueC5UZW5zb3JQcm90byA9IChmdW5jdGlvbigpIHtcblxuICAgICAgICAvKipcbiAgICAgICAgICogUHJvcGVydGllcyBvZiBhIFRlbnNvclByb3RvLlxuICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueFxuICAgICAgICAgKiBAaW50ZXJmYWNlIElUZW5zb3JQcm90b1xuICAgICAgICAgKiBAcHJvcGVydHkge0FycmF5LjxudW1iZXJ8TG9uZz58bnVsbH0gW2RpbXNdIFRlbnNvclByb3RvIGRpbXNcbiAgICAgICAgICogQHByb3BlcnR5IHtudW1iZXJ8bnVsbH0gW2RhdGFUeXBlXSBUZW5zb3JQcm90byBkYXRhVHlwZVxuICAgICAgICAgKiBAcHJvcGVydHkge29ubnguVGVuc29yUHJvdG8uSVNlZ21lbnR8bnVsbH0gW3NlZ21lbnRdIFRlbnNvclByb3RvIHNlZ21lbnRcbiAgICAgICAgICogQHByb3BlcnR5IHtBcnJheS48bnVtYmVyPnxudWxsfSBbZmxvYXREYXRhXSBUZW5zb3JQcm90byBmbG9hdERhdGFcbiAgICAgICAgICogQHByb3BlcnR5IHtBcnJheS48bnVtYmVyPnxudWxsfSBbaW50MzJEYXRhXSBUZW5zb3JQcm90byBpbnQzMkRhdGFcbiAgICAgICAgICogQHByb3BlcnR5IHtBcnJheS48VWludDhBcnJheT58bnVsbH0gW3N0cmluZ0RhdGFdIFRlbnNvclByb3RvIHN0cmluZ0RhdGFcbiAgICAgICAgICogQHByb3BlcnR5IHtBcnJheS48bnVtYmVyfExvbmc+fG51bGx9IFtpbnQ2NERhdGFdIFRlbnNvclByb3RvIGludDY0RGF0YVxuICAgICAgICAgKiBAcHJvcGVydHkge3N0cmluZ3xudWxsfSBbbmFtZV0gVGVuc29yUHJvdG8gbmFtZVxuICAgICAgICAgKiBAcHJvcGVydHkge3N0cmluZ3xudWxsfSBbZG9jU3RyaW5nXSBUZW5zb3JQcm90byBkb2NTdHJpbmdcbiAgICAgICAgICogQHByb3BlcnR5IHtVaW50OEFycmF5fG51bGx9IFtyYXdEYXRhXSBUZW5zb3JQcm90byByYXdEYXRhXG4gICAgICAgICAqIEBwcm9wZXJ0eSB7QXJyYXkuPG9ubnguSVN0cmluZ1N0cmluZ0VudHJ5UHJvdG8+fG51bGx9IFtleHRlcm5hbERhdGFdIFRlbnNvclByb3RvIGV4dGVybmFsRGF0YVxuICAgICAgICAgKiBAcHJvcGVydHkge29ubnguVGVuc29yUHJvdG8uRGF0YUxvY2F0aW9ufG51bGx9IFtkYXRhTG9jYXRpb25dIFRlbnNvclByb3RvIGRhdGFMb2NhdGlvblxuICAgICAgICAgKiBAcHJvcGVydHkge0FycmF5LjxudW1iZXI+fG51bGx9IFtkb3VibGVEYXRhXSBUZW5zb3JQcm90byBkb3VibGVEYXRhXG4gICAgICAgICAqIEBwcm9wZXJ0eSB7QXJyYXkuPG51bWJlcnxMb25nPnxudWxsfSBbdWludDY0RGF0YV0gVGVuc29yUHJvdG8gdWludDY0RGF0YVxuICAgICAgICAgKi9cblxuICAgICAgICAvKipcbiAgICAgICAgICogQ29uc3RydWN0cyBhIG5ldyBUZW5zb3JQcm90by5cbiAgICAgICAgICogQG1lbWJlcm9mIG9ubnhcbiAgICAgICAgICogQGNsYXNzZGVzYyBSZXByZXNlbnRzIGEgVGVuc29yUHJvdG8uXG4gICAgICAgICAqIEBpbXBsZW1lbnRzIElUZW5zb3JQcm90b1xuICAgICAgICAgKiBAY29uc3RydWN0b3JcbiAgICAgICAgICogQHBhcmFtIHtvbm54LklUZW5zb3JQcm90bz19IFtwcm9wZXJ0aWVzXSBQcm9wZXJ0aWVzIHRvIHNldFxuICAgICAgICAgKi9cbiAgICAgICAgZnVuY3Rpb24gVGVuc29yUHJvdG8ocHJvcGVydGllcykge1xuICAgICAgICAgICAgdGhpcy5kaW1zID0gW107XG4gICAgICAgICAgICB0aGlzLmZsb2F0RGF0YSA9IFtdO1xuICAgICAgICAgICAgdGhpcy5pbnQzMkRhdGEgPSBbXTtcbiAgICAgICAgICAgIHRoaXMuc3RyaW5nRGF0YSA9IFtdO1xuICAgICAgICAgICAgdGhpcy5pbnQ2NERhdGEgPSBbXTtcbiAgICAgICAgICAgIHRoaXMuZXh0ZXJuYWxEYXRhID0gW107XG4gICAgICAgICAgICB0aGlzLmRvdWJsZURhdGEgPSBbXTtcbiAgICAgICAgICAgIHRoaXMudWludDY0RGF0YSA9IFtdO1xuICAgICAgICAgICAgaWYgKHByb3BlcnRpZXMpXG4gICAgICAgICAgICAgICAgZm9yICh2YXIga2V5cyA9IE9iamVjdC5rZXlzKHByb3BlcnRpZXMpLCBpID0gMDsgaSA8IGtleXMubGVuZ3RoOyArK2kpXG4gICAgICAgICAgICAgICAgICAgIGlmIChwcm9wZXJ0aWVzW2tleXNbaV1dICE9IG51bGwpXG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzW2tleXNbaV1dID0gcHJvcGVydGllc1trZXlzW2ldXTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBUZW5zb3JQcm90byBkaW1zLlxuICAgICAgICAgKiBAbWVtYmVyIHtBcnJheS48bnVtYmVyfExvbmc+fSBkaW1zXG4gICAgICAgICAqIEBtZW1iZXJvZiBvbm54LlRlbnNvclByb3RvXG4gICAgICAgICAqIEBpbnN0YW5jZVxuICAgICAgICAgKi9cbiAgICAgICAgVGVuc29yUHJvdG8ucHJvdG90eXBlLmRpbXMgPSAkdXRpbC5lbXB0eUFycmF5O1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBUZW5zb3JQcm90byBkYXRhVHlwZS5cbiAgICAgICAgICogQG1lbWJlciB7bnVtYmVyfSBkYXRhVHlwZVxuICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueC5UZW5zb3JQcm90b1xuICAgICAgICAgKiBAaW5zdGFuY2VcbiAgICAgICAgICovXG4gICAgICAgIFRlbnNvclByb3RvLnByb3RvdHlwZS5kYXRhVHlwZSA9IDA7XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIFRlbnNvclByb3RvIHNlZ21lbnQuXG4gICAgICAgICAqIEBtZW1iZXIge29ubnguVGVuc29yUHJvdG8uSVNlZ21lbnR8bnVsbHx1bmRlZmluZWR9IHNlZ21lbnRcbiAgICAgICAgICogQG1lbWJlcm9mIG9ubnguVGVuc29yUHJvdG9cbiAgICAgICAgICogQGluc3RhbmNlXG4gICAgICAgICAqL1xuICAgICAgICBUZW5zb3JQcm90by5wcm90b3R5cGUuc2VnbWVudCA9IG51bGw7XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIFRlbnNvclByb3RvIGZsb2F0RGF0YS5cbiAgICAgICAgICogQG1lbWJlciB7QXJyYXkuPG51bWJlcj59IGZsb2F0RGF0YVxuICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueC5UZW5zb3JQcm90b1xuICAgICAgICAgKiBAaW5zdGFuY2VcbiAgICAgICAgICovXG4gICAgICAgIFRlbnNvclByb3RvLnByb3RvdHlwZS5mbG9hdERhdGEgPSAkdXRpbC5lbXB0eUFycmF5O1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBUZW5zb3JQcm90byBpbnQzMkRhdGEuXG4gICAgICAgICAqIEBtZW1iZXIge0FycmF5LjxudW1iZXI+fSBpbnQzMkRhdGFcbiAgICAgICAgICogQG1lbWJlcm9mIG9ubnguVGVuc29yUHJvdG9cbiAgICAgICAgICogQGluc3RhbmNlXG4gICAgICAgICAqL1xuICAgICAgICBUZW5zb3JQcm90by5wcm90b3R5cGUuaW50MzJEYXRhID0gJHV0aWwuZW1wdHlBcnJheTtcblxuICAgICAgICAvKipcbiAgICAgICAgICogVGVuc29yUHJvdG8gc3RyaW5nRGF0YS5cbiAgICAgICAgICogQG1lbWJlciB7QXJyYXkuPFVpbnQ4QXJyYXk+fSBzdHJpbmdEYXRhXG4gICAgICAgICAqIEBtZW1iZXJvZiBvbm54LlRlbnNvclByb3RvXG4gICAgICAgICAqIEBpbnN0YW5jZVxuICAgICAgICAgKi9cbiAgICAgICAgVGVuc29yUHJvdG8ucHJvdG90eXBlLnN0cmluZ0RhdGEgPSAkdXRpbC5lbXB0eUFycmF5O1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBUZW5zb3JQcm90byBpbnQ2NERhdGEuXG4gICAgICAgICAqIEBtZW1iZXIge0FycmF5LjxudW1iZXJ8TG9uZz59IGludDY0RGF0YVxuICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueC5UZW5zb3JQcm90b1xuICAgICAgICAgKiBAaW5zdGFuY2VcbiAgICAgICAgICovXG4gICAgICAgIFRlbnNvclByb3RvLnByb3RvdHlwZS5pbnQ2NERhdGEgPSAkdXRpbC5lbXB0eUFycmF5O1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBUZW5zb3JQcm90byBuYW1lLlxuICAgICAgICAgKiBAbWVtYmVyIHtzdHJpbmd9IG5hbWVcbiAgICAgICAgICogQG1lbWJlcm9mIG9ubnguVGVuc29yUHJvdG9cbiAgICAgICAgICogQGluc3RhbmNlXG4gICAgICAgICAqL1xuICAgICAgICBUZW5zb3JQcm90by5wcm90b3R5cGUubmFtZSA9IFwiXCI7XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIFRlbnNvclByb3RvIGRvY1N0cmluZy5cbiAgICAgICAgICogQG1lbWJlciB7c3RyaW5nfSBkb2NTdHJpbmdcbiAgICAgICAgICogQG1lbWJlcm9mIG9ubnguVGVuc29yUHJvdG9cbiAgICAgICAgICogQGluc3RhbmNlXG4gICAgICAgICAqL1xuICAgICAgICBUZW5zb3JQcm90by5wcm90b3R5cGUuZG9jU3RyaW5nID0gXCJcIjtcblxuICAgICAgICAvKipcbiAgICAgICAgICogVGVuc29yUHJvdG8gcmF3RGF0YS5cbiAgICAgICAgICogQG1lbWJlciB7VWludDhBcnJheX0gcmF3RGF0YVxuICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueC5UZW5zb3JQcm90b1xuICAgICAgICAgKiBAaW5zdGFuY2VcbiAgICAgICAgICovXG4gICAgICAgIFRlbnNvclByb3RvLnByb3RvdHlwZS5yYXdEYXRhID0gJHV0aWwubmV3QnVmZmVyKFtdKTtcblxuICAgICAgICAvKipcbiAgICAgICAgICogVGVuc29yUHJvdG8gZXh0ZXJuYWxEYXRhLlxuICAgICAgICAgKiBAbWVtYmVyIHtBcnJheS48b25ueC5JU3RyaW5nU3RyaW5nRW50cnlQcm90bz59IGV4dGVybmFsRGF0YVxuICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueC5UZW5zb3JQcm90b1xuICAgICAgICAgKiBAaW5zdGFuY2VcbiAgICAgICAgICovXG4gICAgICAgIFRlbnNvclByb3RvLnByb3RvdHlwZS5leHRlcm5hbERhdGEgPSAkdXRpbC5lbXB0eUFycmF5O1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBUZW5zb3JQcm90byBkYXRhTG9jYXRpb24uXG4gICAgICAgICAqIEBtZW1iZXIge29ubnguVGVuc29yUHJvdG8uRGF0YUxvY2F0aW9ufSBkYXRhTG9jYXRpb25cbiAgICAgICAgICogQG1lbWJlcm9mIG9ubnguVGVuc29yUHJvdG9cbiAgICAgICAgICogQGluc3RhbmNlXG4gICAgICAgICAqL1xuICAgICAgICBUZW5zb3JQcm90by5wcm90b3R5cGUuZGF0YUxvY2F0aW9uID0gMDtcblxuICAgICAgICAvKipcbiAgICAgICAgICogVGVuc29yUHJvdG8gZG91YmxlRGF0YS5cbiAgICAgICAgICogQG1lbWJlciB7QXJyYXkuPG51bWJlcj59IGRvdWJsZURhdGFcbiAgICAgICAgICogQG1lbWJlcm9mIG9ubnguVGVuc29yUHJvdG9cbiAgICAgICAgICogQGluc3RhbmNlXG4gICAgICAgICAqL1xuICAgICAgICBUZW5zb3JQcm90by5wcm90b3R5cGUuZG91YmxlRGF0YSA9ICR1dGlsLmVtcHR5QXJyYXk7XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIFRlbnNvclByb3RvIHVpbnQ2NERhdGEuXG4gICAgICAgICAqIEBtZW1iZXIge0FycmF5LjxudW1iZXJ8TG9uZz59IHVpbnQ2NERhdGFcbiAgICAgICAgICogQG1lbWJlcm9mIG9ubnguVGVuc29yUHJvdG9cbiAgICAgICAgICogQGluc3RhbmNlXG4gICAgICAgICAqL1xuICAgICAgICBUZW5zb3JQcm90by5wcm90b3R5cGUudWludDY0RGF0YSA9ICR1dGlsLmVtcHR5QXJyYXk7XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIENyZWF0ZXMgYSBuZXcgVGVuc29yUHJvdG8gaW5zdGFuY2UgdXNpbmcgdGhlIHNwZWNpZmllZCBwcm9wZXJ0aWVzLlxuICAgICAgICAgKiBAZnVuY3Rpb24gY3JlYXRlXG4gICAgICAgICAqIEBtZW1iZXJvZiBvbm54LlRlbnNvclByb3RvXG4gICAgICAgICAqIEBzdGF0aWNcbiAgICAgICAgICogQHBhcmFtIHtvbm54LklUZW5zb3JQcm90bz19IFtwcm9wZXJ0aWVzXSBQcm9wZXJ0aWVzIHRvIHNldFxuICAgICAgICAgKiBAcmV0dXJucyB7b25ueC5UZW5zb3JQcm90b30gVGVuc29yUHJvdG8gaW5zdGFuY2VcbiAgICAgICAgICovXG4gICAgICAgIFRlbnNvclByb3RvLmNyZWF0ZSA9IGZ1bmN0aW9uIGNyZWF0ZShwcm9wZXJ0aWVzKSB7XG4gICAgICAgICAgICByZXR1cm4gbmV3IFRlbnNvclByb3RvKHByb3BlcnRpZXMpO1xuICAgICAgICB9O1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBFbmNvZGVzIHRoZSBzcGVjaWZpZWQgVGVuc29yUHJvdG8gbWVzc2FnZS4gRG9lcyBub3QgaW1wbGljaXRseSB7QGxpbmsgb25ueC5UZW5zb3JQcm90by52ZXJpZnl8dmVyaWZ5fSBtZXNzYWdlcy5cbiAgICAgICAgICogQGZ1bmN0aW9uIGVuY29kZVxuICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueC5UZW5zb3JQcm90b1xuICAgICAgICAgKiBAc3RhdGljXG4gICAgICAgICAqIEBwYXJhbSB7b25ueC5JVGVuc29yUHJvdG99IG1lc3NhZ2UgVGVuc29yUHJvdG8gbWVzc2FnZSBvciBwbGFpbiBvYmplY3QgdG8gZW5jb2RlXG4gICAgICAgICAqIEBwYXJhbSB7JHByb3RvYnVmLldyaXRlcn0gW3dyaXRlcl0gV3JpdGVyIHRvIGVuY29kZSB0b1xuICAgICAgICAgKiBAcmV0dXJucyB7JHByb3RvYnVmLldyaXRlcn0gV3JpdGVyXG4gICAgICAgICAqL1xuICAgICAgICBUZW5zb3JQcm90by5lbmNvZGUgPSBmdW5jdGlvbiBlbmNvZGUobWVzc2FnZSwgd3JpdGVyKSB7XG4gICAgICAgICAgICBpZiAoIXdyaXRlcilcbiAgICAgICAgICAgICAgICB3cml0ZXIgPSAkV3JpdGVyLmNyZWF0ZSgpO1xuICAgICAgICAgICAgaWYgKG1lc3NhZ2UuZGltcyAhPSBudWxsICYmIG1lc3NhZ2UuZGltcy5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICB3cml0ZXIudWludDMyKC8qIGlkIDEsIHdpcmVUeXBlIDIgPSovMTApLmZvcmsoKTtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG1lc3NhZ2UuZGltcy5sZW5ndGg7ICsraSlcbiAgICAgICAgICAgICAgICAgICAgd3JpdGVyLmludDY0KG1lc3NhZ2UuZGltc1tpXSk7XG4gICAgICAgICAgICAgICAgd3JpdGVyLmxkZWxpbSgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG1lc3NhZ2UuZGF0YVR5cGUgIT0gbnVsbCAmJiBtZXNzYWdlLmhhc093blByb3BlcnR5KFwiZGF0YVR5cGVcIikpXG4gICAgICAgICAgICAgICAgd3JpdGVyLnVpbnQzMigvKiBpZCAyLCB3aXJlVHlwZSAwID0qLzE2KS5pbnQzMihtZXNzYWdlLmRhdGFUeXBlKTtcbiAgICAgICAgICAgIGlmIChtZXNzYWdlLnNlZ21lbnQgIT0gbnVsbCAmJiBtZXNzYWdlLmhhc093blByb3BlcnR5KFwic2VnbWVudFwiKSlcbiAgICAgICAgICAgICAgICAkcm9vdC5vbm54LlRlbnNvclByb3RvLlNlZ21lbnQuZW5jb2RlKG1lc3NhZ2Uuc2VnbWVudCwgd3JpdGVyLnVpbnQzMigvKiBpZCAzLCB3aXJlVHlwZSAyID0qLzI2KS5mb3JrKCkpLmxkZWxpbSgpO1xuICAgICAgICAgICAgaWYgKG1lc3NhZ2UuZmxvYXREYXRhICE9IG51bGwgJiYgbWVzc2FnZS5mbG9hdERhdGEubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgd3JpdGVyLnVpbnQzMigvKiBpZCA0LCB3aXJlVHlwZSAyID0qLzM0KS5mb3JrKCk7XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBtZXNzYWdlLmZsb2F0RGF0YS5sZW5ndGg7ICsraSlcbiAgICAgICAgICAgICAgICAgICAgd3JpdGVyLmZsb2F0KG1lc3NhZ2UuZmxvYXREYXRhW2ldKTtcbiAgICAgICAgICAgICAgICB3cml0ZXIubGRlbGltKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAobWVzc2FnZS5pbnQzMkRhdGEgIT0gbnVsbCAmJiBtZXNzYWdlLmludDMyRGF0YS5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICB3cml0ZXIudWludDMyKC8qIGlkIDUsIHdpcmVUeXBlIDIgPSovNDIpLmZvcmsoKTtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG1lc3NhZ2UuaW50MzJEYXRhLmxlbmd0aDsgKytpKVxuICAgICAgICAgICAgICAgICAgICB3cml0ZXIuaW50MzIobWVzc2FnZS5pbnQzMkRhdGFbaV0pO1xuICAgICAgICAgICAgICAgIHdyaXRlci5sZGVsaW0oKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChtZXNzYWdlLnN0cmluZ0RhdGEgIT0gbnVsbCAmJiBtZXNzYWdlLnN0cmluZ0RhdGEubGVuZ3RoKVxuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbWVzc2FnZS5zdHJpbmdEYXRhLmxlbmd0aDsgKytpKVxuICAgICAgICAgICAgICAgICAgICB3cml0ZXIudWludDMyKC8qIGlkIDYsIHdpcmVUeXBlIDIgPSovNTApLmJ5dGVzKG1lc3NhZ2Uuc3RyaW5nRGF0YVtpXSk7XG4gICAgICAgICAgICBpZiAobWVzc2FnZS5pbnQ2NERhdGEgIT0gbnVsbCAmJiBtZXNzYWdlLmludDY0RGF0YS5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICB3cml0ZXIudWludDMyKC8qIGlkIDcsIHdpcmVUeXBlIDIgPSovNTgpLmZvcmsoKTtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG1lc3NhZ2UuaW50NjREYXRhLmxlbmd0aDsgKytpKVxuICAgICAgICAgICAgICAgICAgICB3cml0ZXIuaW50NjQobWVzc2FnZS5pbnQ2NERhdGFbaV0pO1xuICAgICAgICAgICAgICAgIHdyaXRlci5sZGVsaW0oKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChtZXNzYWdlLm5hbWUgIT0gbnVsbCAmJiBtZXNzYWdlLmhhc093blByb3BlcnR5KFwibmFtZVwiKSlcbiAgICAgICAgICAgICAgICB3cml0ZXIudWludDMyKC8qIGlkIDgsIHdpcmVUeXBlIDIgPSovNjYpLnN0cmluZyhtZXNzYWdlLm5hbWUpO1xuICAgICAgICAgICAgaWYgKG1lc3NhZ2UucmF3RGF0YSAhPSBudWxsICYmIG1lc3NhZ2UuaGFzT3duUHJvcGVydHkoXCJyYXdEYXRhXCIpKVxuICAgICAgICAgICAgICAgIHdyaXRlci51aW50MzIoLyogaWQgOSwgd2lyZVR5cGUgMiA9Ki83NCkuYnl0ZXMobWVzc2FnZS5yYXdEYXRhKTtcbiAgICAgICAgICAgIGlmIChtZXNzYWdlLmRvdWJsZURhdGEgIT0gbnVsbCAmJiBtZXNzYWdlLmRvdWJsZURhdGEubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgd3JpdGVyLnVpbnQzMigvKiBpZCAxMCwgd2lyZVR5cGUgMiA9Ki84MikuZm9yaygpO1xuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbWVzc2FnZS5kb3VibGVEYXRhLmxlbmd0aDsgKytpKVxuICAgICAgICAgICAgICAgICAgICB3cml0ZXIuZG91YmxlKG1lc3NhZ2UuZG91YmxlRGF0YVtpXSk7XG4gICAgICAgICAgICAgICAgd3JpdGVyLmxkZWxpbSgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG1lc3NhZ2UudWludDY0RGF0YSAhPSBudWxsICYmIG1lc3NhZ2UudWludDY0RGF0YS5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICB3cml0ZXIudWludDMyKC8qIGlkIDExLCB3aXJlVHlwZSAyID0qLzkwKS5mb3JrKCk7XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBtZXNzYWdlLnVpbnQ2NERhdGEubGVuZ3RoOyArK2kpXG4gICAgICAgICAgICAgICAgICAgIHdyaXRlci51aW50NjQobWVzc2FnZS51aW50NjREYXRhW2ldKTtcbiAgICAgICAgICAgICAgICB3cml0ZXIubGRlbGltKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAobWVzc2FnZS5kb2NTdHJpbmcgIT0gbnVsbCAmJiBtZXNzYWdlLmhhc093blByb3BlcnR5KFwiZG9jU3RyaW5nXCIpKVxuICAgICAgICAgICAgICAgIHdyaXRlci51aW50MzIoLyogaWQgMTIsIHdpcmVUeXBlIDIgPSovOTgpLnN0cmluZyhtZXNzYWdlLmRvY1N0cmluZyk7XG4gICAgICAgICAgICBpZiAobWVzc2FnZS5leHRlcm5hbERhdGEgIT0gbnVsbCAmJiBtZXNzYWdlLmV4dGVybmFsRGF0YS5sZW5ndGgpXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBtZXNzYWdlLmV4dGVybmFsRGF0YS5sZW5ndGg7ICsraSlcbiAgICAgICAgICAgICAgICAgICAgJHJvb3Qub25ueC5TdHJpbmdTdHJpbmdFbnRyeVByb3RvLmVuY29kZShtZXNzYWdlLmV4dGVybmFsRGF0YVtpXSwgd3JpdGVyLnVpbnQzMigvKiBpZCAxMywgd2lyZVR5cGUgMiA9Ki8xMDYpLmZvcmsoKSkubGRlbGltKCk7XG4gICAgICAgICAgICBpZiAobWVzc2FnZS5kYXRhTG9jYXRpb24gIT0gbnVsbCAmJiBtZXNzYWdlLmhhc093blByb3BlcnR5KFwiZGF0YUxvY2F0aW9uXCIpKVxuICAgICAgICAgICAgICAgIHdyaXRlci51aW50MzIoLyogaWQgMTQsIHdpcmVUeXBlIDAgPSovMTEyKS5pbnQzMihtZXNzYWdlLmRhdGFMb2NhdGlvbik7XG4gICAgICAgICAgICByZXR1cm4gd3JpdGVyO1xuICAgICAgICB9O1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBFbmNvZGVzIHRoZSBzcGVjaWZpZWQgVGVuc29yUHJvdG8gbWVzc2FnZSwgbGVuZ3RoIGRlbGltaXRlZC4gRG9lcyBub3QgaW1wbGljaXRseSB7QGxpbmsgb25ueC5UZW5zb3JQcm90by52ZXJpZnl8dmVyaWZ5fSBtZXNzYWdlcy5cbiAgICAgICAgICogQGZ1bmN0aW9uIGVuY29kZURlbGltaXRlZFxuICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueC5UZW5zb3JQcm90b1xuICAgICAgICAgKiBAc3RhdGljXG4gICAgICAgICAqIEBwYXJhbSB7b25ueC5JVGVuc29yUHJvdG99IG1lc3NhZ2UgVGVuc29yUHJvdG8gbWVzc2FnZSBvciBwbGFpbiBvYmplY3QgdG8gZW5jb2RlXG4gICAgICAgICAqIEBwYXJhbSB7JHByb3RvYnVmLldyaXRlcn0gW3dyaXRlcl0gV3JpdGVyIHRvIGVuY29kZSB0b1xuICAgICAgICAgKiBAcmV0dXJucyB7JHByb3RvYnVmLldyaXRlcn0gV3JpdGVyXG4gICAgICAgICAqL1xuICAgICAgICBUZW5zb3JQcm90by5lbmNvZGVEZWxpbWl0ZWQgPSBmdW5jdGlvbiBlbmNvZGVEZWxpbWl0ZWQobWVzc2FnZSwgd3JpdGVyKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5lbmNvZGUobWVzc2FnZSwgd3JpdGVyKS5sZGVsaW0oKTtcbiAgICAgICAgfTtcblxuICAgICAgICAvKipcbiAgICAgICAgICogRGVjb2RlcyBhIFRlbnNvclByb3RvIG1lc3NhZ2UgZnJvbSB0aGUgc3BlY2lmaWVkIHJlYWRlciBvciBidWZmZXIuXG4gICAgICAgICAqIEBmdW5jdGlvbiBkZWNvZGVcbiAgICAgICAgICogQG1lbWJlcm9mIG9ubnguVGVuc29yUHJvdG9cbiAgICAgICAgICogQHN0YXRpY1xuICAgICAgICAgKiBAcGFyYW0geyRwcm90b2J1Zi5SZWFkZXJ8VWludDhBcnJheX0gcmVhZGVyIFJlYWRlciBvciBidWZmZXIgdG8gZGVjb2RlIGZyb21cbiAgICAgICAgICogQHBhcmFtIHtudW1iZXJ9IFtsZW5ndGhdIE1lc3NhZ2UgbGVuZ3RoIGlmIGtub3duIGJlZm9yZWhhbmRcbiAgICAgICAgICogQHJldHVybnMge29ubnguVGVuc29yUHJvdG99IFRlbnNvclByb3RvXG4gICAgICAgICAqIEB0aHJvd3Mge0Vycm9yfSBJZiB0aGUgcGF5bG9hZCBpcyBub3QgYSByZWFkZXIgb3IgdmFsaWQgYnVmZmVyXG4gICAgICAgICAqIEB0aHJvd3MgeyRwcm90b2J1Zi51dGlsLlByb3RvY29sRXJyb3J9IElmIHJlcXVpcmVkIGZpZWxkcyBhcmUgbWlzc2luZ1xuICAgICAgICAgKi9cbiAgICAgICAgVGVuc29yUHJvdG8uZGVjb2RlID0gZnVuY3Rpb24gZGVjb2RlKHJlYWRlciwgbGVuZ3RoKSB7XG4gICAgICAgICAgICBpZiAoIShyZWFkZXIgaW5zdGFuY2VvZiAkUmVhZGVyKSlcbiAgICAgICAgICAgICAgICByZWFkZXIgPSAkUmVhZGVyLmNyZWF0ZShyZWFkZXIpO1xuICAgICAgICAgICAgdmFyIGVuZCA9IGxlbmd0aCA9PT0gdW5kZWZpbmVkID8gcmVhZGVyLmxlbiA6IHJlYWRlci5wb3MgKyBsZW5ndGgsIG1lc3NhZ2UgPSBuZXcgJHJvb3Qub25ueC5UZW5zb3JQcm90bygpO1xuICAgICAgICAgICAgd2hpbGUgKHJlYWRlci5wb3MgPCBlbmQpIHtcbiAgICAgICAgICAgICAgICB2YXIgdGFnID0gcmVhZGVyLnVpbnQzMigpO1xuICAgICAgICAgICAgICAgIHN3aXRjaCAodGFnID4+PiAzKSB7XG4gICAgICAgICAgICAgICAgY2FzZSAxOlxuICAgICAgICAgICAgICAgICAgICBpZiAoIShtZXNzYWdlLmRpbXMgJiYgbWVzc2FnZS5kaW1zLmxlbmd0aCkpXG4gICAgICAgICAgICAgICAgICAgICAgICBtZXNzYWdlLmRpbXMgPSBbXTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCh0YWcgJiA3KSA9PT0gMikge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGVuZDIgPSByZWFkZXIudWludDMyKCkgKyByZWFkZXIucG9zO1xuICAgICAgICAgICAgICAgICAgICAgICAgd2hpbGUgKHJlYWRlci5wb3MgPCBlbmQyKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1lc3NhZ2UuZGltcy5wdXNoKHJlYWRlci5pbnQ2NCgpKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlXG4gICAgICAgICAgICAgICAgICAgICAgICBtZXNzYWdlLmRpbXMucHVzaChyZWFkZXIuaW50NjQoKSk7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgMjpcbiAgICAgICAgICAgICAgICAgICAgbWVzc2FnZS5kYXRhVHlwZSA9IHJlYWRlci5pbnQzMigpO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlIDM6XG4gICAgICAgICAgICAgICAgICAgIG1lc3NhZ2Uuc2VnbWVudCA9ICRyb290Lm9ubnguVGVuc29yUHJvdG8uU2VnbWVudC5kZWNvZGUocmVhZGVyLCByZWFkZXIudWludDMyKCkpO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlIDQ6XG4gICAgICAgICAgICAgICAgICAgIGlmICghKG1lc3NhZ2UuZmxvYXREYXRhICYmIG1lc3NhZ2UuZmxvYXREYXRhLmxlbmd0aCkpXG4gICAgICAgICAgICAgICAgICAgICAgICBtZXNzYWdlLmZsb2F0RGF0YSA9IFtdO1xuICAgICAgICAgICAgICAgICAgICBpZiAoKHRhZyAmIDcpID09PSAyKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgZW5kMiA9IHJlYWRlci51aW50MzIoKSArIHJlYWRlci5wb3M7XG4gICAgICAgICAgICAgICAgICAgICAgICB3aGlsZSAocmVhZGVyLnBvcyA8IGVuZDIpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbWVzc2FnZS5mbG9hdERhdGEucHVzaChyZWFkZXIuZmxvYXQoKSk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZVxuICAgICAgICAgICAgICAgICAgICAgICAgbWVzc2FnZS5mbG9hdERhdGEucHVzaChyZWFkZXIuZmxvYXQoKSk7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgNTpcbiAgICAgICAgICAgICAgICAgICAgaWYgKCEobWVzc2FnZS5pbnQzMkRhdGEgJiYgbWVzc2FnZS5pbnQzMkRhdGEubGVuZ3RoKSlcbiAgICAgICAgICAgICAgICAgICAgICAgIG1lc3NhZ2UuaW50MzJEYXRhID0gW107XG4gICAgICAgICAgICAgICAgICAgIGlmICgodGFnICYgNykgPT09IDIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBlbmQyID0gcmVhZGVyLnVpbnQzMigpICsgcmVhZGVyLnBvcztcbiAgICAgICAgICAgICAgICAgICAgICAgIHdoaWxlIChyZWFkZXIucG9zIDwgZW5kMilcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZXNzYWdlLmludDMyRGF0YS5wdXNoKHJlYWRlci5pbnQzMigpKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlXG4gICAgICAgICAgICAgICAgICAgICAgICBtZXNzYWdlLmludDMyRGF0YS5wdXNoKHJlYWRlci5pbnQzMigpKTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSA2OlxuICAgICAgICAgICAgICAgICAgICBpZiAoIShtZXNzYWdlLnN0cmluZ0RhdGEgJiYgbWVzc2FnZS5zdHJpbmdEYXRhLmxlbmd0aCkpXG4gICAgICAgICAgICAgICAgICAgICAgICBtZXNzYWdlLnN0cmluZ0RhdGEgPSBbXTtcbiAgICAgICAgICAgICAgICAgICAgbWVzc2FnZS5zdHJpbmdEYXRhLnB1c2gocmVhZGVyLmJ5dGVzKCkpO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlIDc6XG4gICAgICAgICAgICAgICAgICAgIGlmICghKG1lc3NhZ2UuaW50NjREYXRhICYmIG1lc3NhZ2UuaW50NjREYXRhLmxlbmd0aCkpXG4gICAgICAgICAgICAgICAgICAgICAgICBtZXNzYWdlLmludDY0RGF0YSA9IFtdO1xuICAgICAgICAgICAgICAgICAgICBpZiAoKHRhZyAmIDcpID09PSAyKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgZW5kMiA9IHJlYWRlci51aW50MzIoKSArIHJlYWRlci5wb3M7XG4gICAgICAgICAgICAgICAgICAgICAgICB3aGlsZSAocmVhZGVyLnBvcyA8IGVuZDIpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbWVzc2FnZS5pbnQ2NERhdGEucHVzaChyZWFkZXIuaW50NjQoKSk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZVxuICAgICAgICAgICAgICAgICAgICAgICAgbWVzc2FnZS5pbnQ2NERhdGEucHVzaChyZWFkZXIuaW50NjQoKSk7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgODpcbiAgICAgICAgICAgICAgICAgICAgbWVzc2FnZS5uYW1lID0gcmVhZGVyLnN0cmluZygpO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlIDEyOlxuICAgICAgICAgICAgICAgICAgICBtZXNzYWdlLmRvY1N0cmluZyA9IHJlYWRlci5zdHJpbmcoKTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSA5OlxuICAgICAgICAgICAgICAgICAgICBtZXNzYWdlLnJhd0RhdGEgPSByZWFkZXIuYnl0ZXMoKTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSAxMzpcbiAgICAgICAgICAgICAgICAgICAgaWYgKCEobWVzc2FnZS5leHRlcm5hbERhdGEgJiYgbWVzc2FnZS5leHRlcm5hbERhdGEubGVuZ3RoKSlcbiAgICAgICAgICAgICAgICAgICAgICAgIG1lc3NhZ2UuZXh0ZXJuYWxEYXRhID0gW107XG4gICAgICAgICAgICAgICAgICAgIG1lc3NhZ2UuZXh0ZXJuYWxEYXRhLnB1c2goJHJvb3Qub25ueC5TdHJpbmdTdHJpbmdFbnRyeVByb3RvLmRlY29kZShyZWFkZXIsIHJlYWRlci51aW50MzIoKSkpO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlIDE0OlxuICAgICAgICAgICAgICAgICAgICBtZXNzYWdlLmRhdGFMb2NhdGlvbiA9IHJlYWRlci5pbnQzMigpO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlIDEwOlxuICAgICAgICAgICAgICAgICAgICBpZiAoIShtZXNzYWdlLmRvdWJsZURhdGEgJiYgbWVzc2FnZS5kb3VibGVEYXRhLmxlbmd0aCkpXG4gICAgICAgICAgICAgICAgICAgICAgICBtZXNzYWdlLmRvdWJsZURhdGEgPSBbXTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCh0YWcgJiA3KSA9PT0gMikge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGVuZDIgPSByZWFkZXIudWludDMyKCkgKyByZWFkZXIucG9zO1xuICAgICAgICAgICAgICAgICAgICAgICAgd2hpbGUgKHJlYWRlci5wb3MgPCBlbmQyKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1lc3NhZ2UuZG91YmxlRGF0YS5wdXNoKHJlYWRlci5kb3VibGUoKSk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZVxuICAgICAgICAgICAgICAgICAgICAgICAgbWVzc2FnZS5kb3VibGVEYXRhLnB1c2gocmVhZGVyLmRvdWJsZSgpKTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSAxMTpcbiAgICAgICAgICAgICAgICAgICAgaWYgKCEobWVzc2FnZS51aW50NjREYXRhICYmIG1lc3NhZ2UudWludDY0RGF0YS5sZW5ndGgpKVxuICAgICAgICAgICAgICAgICAgICAgICAgbWVzc2FnZS51aW50NjREYXRhID0gW107XG4gICAgICAgICAgICAgICAgICAgIGlmICgodGFnICYgNykgPT09IDIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBlbmQyID0gcmVhZGVyLnVpbnQzMigpICsgcmVhZGVyLnBvcztcbiAgICAgICAgICAgICAgICAgICAgICAgIHdoaWxlIChyZWFkZXIucG9zIDwgZW5kMilcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZXNzYWdlLnVpbnQ2NERhdGEucHVzaChyZWFkZXIudWludDY0KCkpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2VcbiAgICAgICAgICAgICAgICAgICAgICAgIG1lc3NhZ2UudWludDY0RGF0YS5wdXNoKHJlYWRlci51aW50NjQoKSk7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgICAgIHJlYWRlci5za2lwVHlwZSh0YWcgJiA3KTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIG1lc3NhZ2U7XG4gICAgICAgIH07XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIERlY29kZXMgYSBUZW5zb3JQcm90byBtZXNzYWdlIGZyb20gdGhlIHNwZWNpZmllZCByZWFkZXIgb3IgYnVmZmVyLCBsZW5ndGggZGVsaW1pdGVkLlxuICAgICAgICAgKiBAZnVuY3Rpb24gZGVjb2RlRGVsaW1pdGVkXG4gICAgICAgICAqIEBtZW1iZXJvZiBvbm54LlRlbnNvclByb3RvXG4gICAgICAgICAqIEBzdGF0aWNcbiAgICAgICAgICogQHBhcmFtIHskcHJvdG9idWYuUmVhZGVyfFVpbnQ4QXJyYXl9IHJlYWRlciBSZWFkZXIgb3IgYnVmZmVyIHRvIGRlY29kZSBmcm9tXG4gICAgICAgICAqIEByZXR1cm5zIHtvbm54LlRlbnNvclByb3RvfSBUZW5zb3JQcm90b1xuICAgICAgICAgKiBAdGhyb3dzIHtFcnJvcn0gSWYgdGhlIHBheWxvYWQgaXMgbm90IGEgcmVhZGVyIG9yIHZhbGlkIGJ1ZmZlclxuICAgICAgICAgKiBAdGhyb3dzIHskcHJvdG9idWYudXRpbC5Qcm90b2NvbEVycm9yfSBJZiByZXF1aXJlZCBmaWVsZHMgYXJlIG1pc3NpbmdcbiAgICAgICAgICovXG4gICAgICAgIFRlbnNvclByb3RvLmRlY29kZURlbGltaXRlZCA9IGZ1bmN0aW9uIGRlY29kZURlbGltaXRlZChyZWFkZXIpIHtcbiAgICAgICAgICAgIGlmICghKHJlYWRlciBpbnN0YW5jZW9mICRSZWFkZXIpKVxuICAgICAgICAgICAgICAgIHJlYWRlciA9IG5ldyAkUmVhZGVyKHJlYWRlcik7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5kZWNvZGUocmVhZGVyLCByZWFkZXIudWludDMyKCkpO1xuICAgICAgICB9O1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBWZXJpZmllcyBhIFRlbnNvclByb3RvIG1lc3NhZ2UuXG4gICAgICAgICAqIEBmdW5jdGlvbiB2ZXJpZnlcbiAgICAgICAgICogQG1lbWJlcm9mIG9ubnguVGVuc29yUHJvdG9cbiAgICAgICAgICogQHN0YXRpY1xuICAgICAgICAgKiBAcGFyYW0ge09iamVjdC48c3RyaW5nLCo+fSBtZXNzYWdlIFBsYWluIG9iamVjdCB0byB2ZXJpZnlcbiAgICAgICAgICogQHJldHVybnMge3N0cmluZ3xudWxsfSBgbnVsbGAgaWYgdmFsaWQsIG90aGVyd2lzZSB0aGUgcmVhc29uIHdoeSBpdCBpcyBub3RcbiAgICAgICAgICovXG4gICAgICAgIFRlbnNvclByb3RvLnZlcmlmeSA9IGZ1bmN0aW9uIHZlcmlmeShtZXNzYWdlKSB7XG4gICAgICAgICAgICBpZiAodHlwZW9mIG1lc3NhZ2UgIT09IFwib2JqZWN0XCIgfHwgbWVzc2FnZSA9PT0gbnVsbClcbiAgICAgICAgICAgICAgICByZXR1cm4gXCJvYmplY3QgZXhwZWN0ZWRcIjtcbiAgICAgICAgICAgIGlmIChtZXNzYWdlLmRpbXMgIT0gbnVsbCAmJiBtZXNzYWdlLmhhc093blByb3BlcnR5KFwiZGltc1wiKSkge1xuICAgICAgICAgICAgICAgIGlmICghQXJyYXkuaXNBcnJheShtZXNzYWdlLmRpbXMpKVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gXCJkaW1zOiBhcnJheSBleHBlY3RlZFwiO1xuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbWVzc2FnZS5kaW1zLmxlbmd0aDsgKytpKVxuICAgICAgICAgICAgICAgICAgICBpZiAoISR1dGlsLmlzSW50ZWdlcihtZXNzYWdlLmRpbXNbaV0pICYmICEobWVzc2FnZS5kaW1zW2ldICYmICR1dGlsLmlzSW50ZWdlcihtZXNzYWdlLmRpbXNbaV0ubG93KSAmJiAkdXRpbC5pc0ludGVnZXIobWVzc2FnZS5kaW1zW2ldLmhpZ2gpKSlcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBcImRpbXM6IGludGVnZXJ8TG9uZ1tdIGV4cGVjdGVkXCI7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAobWVzc2FnZS5kYXRhVHlwZSAhPSBudWxsICYmIG1lc3NhZ2UuaGFzT3duUHJvcGVydHkoXCJkYXRhVHlwZVwiKSlcbiAgICAgICAgICAgICAgICBpZiAoISR1dGlsLmlzSW50ZWdlcihtZXNzYWdlLmRhdGFUeXBlKSlcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFwiZGF0YVR5cGU6IGludGVnZXIgZXhwZWN0ZWRcIjtcbiAgICAgICAgICAgIGlmIChtZXNzYWdlLnNlZ21lbnQgIT0gbnVsbCAmJiBtZXNzYWdlLmhhc093blByb3BlcnR5KFwic2VnbWVudFwiKSkge1xuICAgICAgICAgICAgICAgIHZhciBlcnJvciA9ICRyb290Lm9ubnguVGVuc29yUHJvdG8uU2VnbWVudC52ZXJpZnkobWVzc2FnZS5zZWdtZW50KTtcbiAgICAgICAgICAgICAgICBpZiAoZXJyb3IpXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBcInNlZ21lbnQuXCIgKyBlcnJvcjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChtZXNzYWdlLmZsb2F0RGF0YSAhPSBudWxsICYmIG1lc3NhZ2UuaGFzT3duUHJvcGVydHkoXCJmbG9hdERhdGFcIikpIHtcbiAgICAgICAgICAgICAgICBpZiAoIUFycmF5LmlzQXJyYXkobWVzc2FnZS5mbG9hdERhdGEpKVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gXCJmbG9hdERhdGE6IGFycmF5IGV4cGVjdGVkXCI7XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBtZXNzYWdlLmZsb2F0RGF0YS5sZW5ndGg7ICsraSlcbiAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBtZXNzYWdlLmZsb2F0RGF0YVtpXSAhPT0gXCJudW1iZXJcIilcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBcImZsb2F0RGF0YTogbnVtYmVyW10gZXhwZWN0ZWRcIjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChtZXNzYWdlLmludDMyRGF0YSAhPSBudWxsICYmIG1lc3NhZ2UuaGFzT3duUHJvcGVydHkoXCJpbnQzMkRhdGFcIikpIHtcbiAgICAgICAgICAgICAgICBpZiAoIUFycmF5LmlzQXJyYXkobWVzc2FnZS5pbnQzMkRhdGEpKVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gXCJpbnQzMkRhdGE6IGFycmF5IGV4cGVjdGVkXCI7XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBtZXNzYWdlLmludDMyRGF0YS5sZW5ndGg7ICsraSlcbiAgICAgICAgICAgICAgICAgICAgaWYgKCEkdXRpbC5pc0ludGVnZXIobWVzc2FnZS5pbnQzMkRhdGFbaV0pKVxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFwiaW50MzJEYXRhOiBpbnRlZ2VyW10gZXhwZWN0ZWRcIjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChtZXNzYWdlLnN0cmluZ0RhdGEgIT0gbnVsbCAmJiBtZXNzYWdlLmhhc093blByb3BlcnR5KFwic3RyaW5nRGF0YVwiKSkge1xuICAgICAgICAgICAgICAgIGlmICghQXJyYXkuaXNBcnJheShtZXNzYWdlLnN0cmluZ0RhdGEpKVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gXCJzdHJpbmdEYXRhOiBhcnJheSBleHBlY3RlZFwiO1xuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbWVzc2FnZS5zdHJpbmdEYXRhLmxlbmd0aDsgKytpKVxuICAgICAgICAgICAgICAgICAgICBpZiAoIShtZXNzYWdlLnN0cmluZ0RhdGFbaV0gJiYgdHlwZW9mIG1lc3NhZ2Uuc3RyaW5nRGF0YVtpXS5sZW5ndGggPT09IFwibnVtYmVyXCIgfHwgJHV0aWwuaXNTdHJpbmcobWVzc2FnZS5zdHJpbmdEYXRhW2ldKSkpXG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gXCJzdHJpbmdEYXRhOiBidWZmZXJbXSBleHBlY3RlZFwiO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG1lc3NhZ2UuaW50NjREYXRhICE9IG51bGwgJiYgbWVzc2FnZS5oYXNPd25Qcm9wZXJ0eShcImludDY0RGF0YVwiKSkge1xuICAgICAgICAgICAgICAgIGlmICghQXJyYXkuaXNBcnJheShtZXNzYWdlLmludDY0RGF0YSkpXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBcImludDY0RGF0YTogYXJyYXkgZXhwZWN0ZWRcIjtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG1lc3NhZ2UuaW50NjREYXRhLmxlbmd0aDsgKytpKVxuICAgICAgICAgICAgICAgICAgICBpZiAoISR1dGlsLmlzSW50ZWdlcihtZXNzYWdlLmludDY0RGF0YVtpXSkgJiYgIShtZXNzYWdlLmludDY0RGF0YVtpXSAmJiAkdXRpbC5pc0ludGVnZXIobWVzc2FnZS5pbnQ2NERhdGFbaV0ubG93KSAmJiAkdXRpbC5pc0ludGVnZXIobWVzc2FnZS5pbnQ2NERhdGFbaV0uaGlnaCkpKVxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFwiaW50NjREYXRhOiBpbnRlZ2VyfExvbmdbXSBleHBlY3RlZFwiO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG1lc3NhZ2UubmFtZSAhPSBudWxsICYmIG1lc3NhZ2UuaGFzT3duUHJvcGVydHkoXCJuYW1lXCIpKVxuICAgICAgICAgICAgICAgIGlmICghJHV0aWwuaXNTdHJpbmcobWVzc2FnZS5uYW1lKSlcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFwibmFtZTogc3RyaW5nIGV4cGVjdGVkXCI7XG4gICAgICAgICAgICBpZiAobWVzc2FnZS5kb2NTdHJpbmcgIT0gbnVsbCAmJiBtZXNzYWdlLmhhc093blByb3BlcnR5KFwiZG9jU3RyaW5nXCIpKVxuICAgICAgICAgICAgICAgIGlmICghJHV0aWwuaXNTdHJpbmcobWVzc2FnZS5kb2NTdHJpbmcpKVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gXCJkb2NTdHJpbmc6IHN0cmluZyBleHBlY3RlZFwiO1xuICAgICAgICAgICAgaWYgKG1lc3NhZ2UucmF3RGF0YSAhPSBudWxsICYmIG1lc3NhZ2UuaGFzT3duUHJvcGVydHkoXCJyYXdEYXRhXCIpKVxuICAgICAgICAgICAgICAgIGlmICghKG1lc3NhZ2UucmF3RGF0YSAmJiB0eXBlb2YgbWVzc2FnZS5yYXdEYXRhLmxlbmd0aCA9PT0gXCJudW1iZXJcIiB8fCAkdXRpbC5pc1N0cmluZyhtZXNzYWdlLnJhd0RhdGEpKSlcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFwicmF3RGF0YTogYnVmZmVyIGV4cGVjdGVkXCI7XG4gICAgICAgICAgICBpZiAobWVzc2FnZS5leHRlcm5hbERhdGEgIT0gbnVsbCAmJiBtZXNzYWdlLmhhc093blByb3BlcnR5KFwiZXh0ZXJuYWxEYXRhXCIpKSB7XG4gICAgICAgICAgICAgICAgaWYgKCFBcnJheS5pc0FycmF5KG1lc3NhZ2UuZXh0ZXJuYWxEYXRhKSlcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFwiZXh0ZXJuYWxEYXRhOiBhcnJheSBleHBlY3RlZFwiO1xuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbWVzc2FnZS5leHRlcm5hbERhdGEubGVuZ3RoOyArK2kpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGVycm9yID0gJHJvb3Qub25ueC5TdHJpbmdTdHJpbmdFbnRyeVByb3RvLnZlcmlmeShtZXNzYWdlLmV4dGVybmFsRGF0YVtpXSk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChlcnJvcilcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBcImV4dGVybmFsRGF0YS5cIiArIGVycm9yO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChtZXNzYWdlLmRhdGFMb2NhdGlvbiAhPSBudWxsICYmIG1lc3NhZ2UuaGFzT3duUHJvcGVydHkoXCJkYXRhTG9jYXRpb25cIikpXG4gICAgICAgICAgICAgICAgc3dpdGNoIChtZXNzYWdlLmRhdGFMb2NhdGlvbikge1xuICAgICAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBcImRhdGFMb2NhdGlvbjogZW51bSB2YWx1ZSBleHBlY3RlZFwiO1xuICAgICAgICAgICAgICAgIGNhc2UgMDpcbiAgICAgICAgICAgICAgICBjYXNlIDE6XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChtZXNzYWdlLmRvdWJsZURhdGEgIT0gbnVsbCAmJiBtZXNzYWdlLmhhc093blByb3BlcnR5KFwiZG91YmxlRGF0YVwiKSkge1xuICAgICAgICAgICAgICAgIGlmICghQXJyYXkuaXNBcnJheShtZXNzYWdlLmRvdWJsZURhdGEpKVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gXCJkb3VibGVEYXRhOiBhcnJheSBleHBlY3RlZFwiO1xuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbWVzc2FnZS5kb3VibGVEYXRhLmxlbmd0aDsgKytpKVxuICAgICAgICAgICAgICAgICAgICBpZiAodHlwZW9mIG1lc3NhZ2UuZG91YmxlRGF0YVtpXSAhPT0gXCJudW1iZXJcIilcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBcImRvdWJsZURhdGE6IG51bWJlcltdIGV4cGVjdGVkXCI7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAobWVzc2FnZS51aW50NjREYXRhICE9IG51bGwgJiYgbWVzc2FnZS5oYXNPd25Qcm9wZXJ0eShcInVpbnQ2NERhdGFcIikpIHtcbiAgICAgICAgICAgICAgICBpZiAoIUFycmF5LmlzQXJyYXkobWVzc2FnZS51aW50NjREYXRhKSlcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFwidWludDY0RGF0YTogYXJyYXkgZXhwZWN0ZWRcIjtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG1lc3NhZ2UudWludDY0RGF0YS5sZW5ndGg7ICsraSlcbiAgICAgICAgICAgICAgICAgICAgaWYgKCEkdXRpbC5pc0ludGVnZXIobWVzc2FnZS51aW50NjREYXRhW2ldKSAmJiAhKG1lc3NhZ2UudWludDY0RGF0YVtpXSAmJiAkdXRpbC5pc0ludGVnZXIobWVzc2FnZS51aW50NjREYXRhW2ldLmxvdykgJiYgJHV0aWwuaXNJbnRlZ2VyKG1lc3NhZ2UudWludDY0RGF0YVtpXS5oaWdoKSkpXG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gXCJ1aW50NjREYXRhOiBpbnRlZ2VyfExvbmdbXSBleHBlY3RlZFwiO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgIH07XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIENyZWF0ZXMgYSBUZW5zb3JQcm90byBtZXNzYWdlIGZyb20gYSBwbGFpbiBvYmplY3QuIEFsc28gY29udmVydHMgdmFsdWVzIHRvIHRoZWlyIHJlc3BlY3RpdmUgaW50ZXJuYWwgdHlwZXMuXG4gICAgICAgICAqIEBmdW5jdGlvbiBmcm9tT2JqZWN0XG4gICAgICAgICAqIEBtZW1iZXJvZiBvbm54LlRlbnNvclByb3RvXG4gICAgICAgICAqIEBzdGF0aWNcbiAgICAgICAgICogQHBhcmFtIHtPYmplY3QuPHN0cmluZywqPn0gb2JqZWN0IFBsYWluIG9iamVjdFxuICAgICAgICAgKiBAcmV0dXJucyB7b25ueC5UZW5zb3JQcm90b30gVGVuc29yUHJvdG9cbiAgICAgICAgICovXG4gICAgICAgIFRlbnNvclByb3RvLmZyb21PYmplY3QgPSBmdW5jdGlvbiBmcm9tT2JqZWN0KG9iamVjdCkge1xuICAgICAgICAgICAgaWYgKG9iamVjdCBpbnN0YW5jZW9mICRyb290Lm9ubnguVGVuc29yUHJvdG8pXG4gICAgICAgICAgICAgICAgcmV0dXJuIG9iamVjdDtcbiAgICAgICAgICAgIHZhciBtZXNzYWdlID0gbmV3ICRyb290Lm9ubnguVGVuc29yUHJvdG8oKTtcbiAgICAgICAgICAgIGlmIChvYmplY3QuZGltcykge1xuICAgICAgICAgICAgICAgIGlmICghQXJyYXkuaXNBcnJheShvYmplY3QuZGltcykpXG4gICAgICAgICAgICAgICAgICAgIHRocm93IFR5cGVFcnJvcihcIi5vbm54LlRlbnNvclByb3RvLmRpbXM6IGFycmF5IGV4cGVjdGVkXCIpO1xuICAgICAgICAgICAgICAgIG1lc3NhZ2UuZGltcyA9IFtdO1xuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgb2JqZWN0LmRpbXMubGVuZ3RoOyArK2kpXG4gICAgICAgICAgICAgICAgICAgIGlmICgkdXRpbC5Mb25nKVxuICAgICAgICAgICAgICAgICAgICAgICAgKG1lc3NhZ2UuZGltc1tpXSA9ICR1dGlsLkxvbmcuZnJvbVZhbHVlKG9iamVjdC5kaW1zW2ldKSkudW5zaWduZWQgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgZWxzZSBpZiAodHlwZW9mIG9iamVjdC5kaW1zW2ldID09PSBcInN0cmluZ1wiKVxuICAgICAgICAgICAgICAgICAgICAgICAgbWVzc2FnZS5kaW1zW2ldID0gcGFyc2VJbnQob2JqZWN0LmRpbXNbaV0sIDEwKTtcbiAgICAgICAgICAgICAgICAgICAgZWxzZSBpZiAodHlwZW9mIG9iamVjdC5kaW1zW2ldID09PSBcIm51bWJlclwiKVxuICAgICAgICAgICAgICAgICAgICAgICAgbWVzc2FnZS5kaW1zW2ldID0gb2JqZWN0LmRpbXNbaV07XG4gICAgICAgICAgICAgICAgICAgIGVsc2UgaWYgKHR5cGVvZiBvYmplY3QuZGltc1tpXSA9PT0gXCJvYmplY3RcIilcbiAgICAgICAgICAgICAgICAgICAgICAgIG1lc3NhZ2UuZGltc1tpXSA9IG5ldyAkdXRpbC5Mb25nQml0cyhvYmplY3QuZGltc1tpXS5sb3cgPj4+IDAsIG9iamVjdC5kaW1zW2ldLmhpZ2ggPj4+IDApLnRvTnVtYmVyKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAob2JqZWN0LmRhdGFUeXBlICE9IG51bGwpXG4gICAgICAgICAgICAgICAgbWVzc2FnZS5kYXRhVHlwZSA9IG9iamVjdC5kYXRhVHlwZSB8IDA7XG4gICAgICAgICAgICBpZiAob2JqZWN0LnNlZ21lbnQgIT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIGlmICh0eXBlb2Ygb2JqZWN0LnNlZ21lbnQgIT09IFwib2JqZWN0XCIpXG4gICAgICAgICAgICAgICAgICAgIHRocm93IFR5cGVFcnJvcihcIi5vbm54LlRlbnNvclByb3RvLnNlZ21lbnQ6IG9iamVjdCBleHBlY3RlZFwiKTtcbiAgICAgICAgICAgICAgICBtZXNzYWdlLnNlZ21lbnQgPSAkcm9vdC5vbm54LlRlbnNvclByb3RvLlNlZ21lbnQuZnJvbU9iamVjdChvYmplY3Quc2VnbWVudCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAob2JqZWN0LmZsb2F0RGF0YSkge1xuICAgICAgICAgICAgICAgIGlmICghQXJyYXkuaXNBcnJheShvYmplY3QuZmxvYXREYXRhKSlcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgVHlwZUVycm9yKFwiLm9ubnguVGVuc29yUHJvdG8uZmxvYXREYXRhOiBhcnJheSBleHBlY3RlZFwiKTtcbiAgICAgICAgICAgICAgICBtZXNzYWdlLmZsb2F0RGF0YSA9IFtdO1xuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgb2JqZWN0LmZsb2F0RGF0YS5sZW5ndGg7ICsraSlcbiAgICAgICAgICAgICAgICAgICAgbWVzc2FnZS5mbG9hdERhdGFbaV0gPSBOdW1iZXIob2JqZWN0LmZsb2F0RGF0YVtpXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAob2JqZWN0LmludDMyRGF0YSkge1xuICAgICAgICAgICAgICAgIGlmICghQXJyYXkuaXNBcnJheShvYmplY3QuaW50MzJEYXRhKSlcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgVHlwZUVycm9yKFwiLm9ubnguVGVuc29yUHJvdG8uaW50MzJEYXRhOiBhcnJheSBleHBlY3RlZFwiKTtcbiAgICAgICAgICAgICAgICBtZXNzYWdlLmludDMyRGF0YSA9IFtdO1xuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgb2JqZWN0LmludDMyRGF0YS5sZW5ndGg7ICsraSlcbiAgICAgICAgICAgICAgICAgICAgbWVzc2FnZS5pbnQzMkRhdGFbaV0gPSBvYmplY3QuaW50MzJEYXRhW2ldIHwgMDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChvYmplY3Quc3RyaW5nRGF0YSkge1xuICAgICAgICAgICAgICAgIGlmICghQXJyYXkuaXNBcnJheShvYmplY3Quc3RyaW5nRGF0YSkpXG4gICAgICAgICAgICAgICAgICAgIHRocm93IFR5cGVFcnJvcihcIi5vbm54LlRlbnNvclByb3RvLnN0cmluZ0RhdGE6IGFycmF5IGV4cGVjdGVkXCIpO1xuICAgICAgICAgICAgICAgIG1lc3NhZ2Uuc3RyaW5nRGF0YSA9IFtdO1xuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgb2JqZWN0LnN0cmluZ0RhdGEubGVuZ3RoOyArK2kpXG4gICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2Ygb2JqZWN0LnN0cmluZ0RhdGFbaV0gPT09IFwic3RyaW5nXCIpXG4gICAgICAgICAgICAgICAgICAgICAgICAkdXRpbC5iYXNlNjQuZGVjb2RlKG9iamVjdC5zdHJpbmdEYXRhW2ldLCBtZXNzYWdlLnN0cmluZ0RhdGFbaV0gPSAkdXRpbC5uZXdCdWZmZXIoJHV0aWwuYmFzZTY0Lmxlbmd0aChvYmplY3Quc3RyaW5nRGF0YVtpXSkpLCAwKTtcbiAgICAgICAgICAgICAgICAgICAgZWxzZSBpZiAob2JqZWN0LnN0cmluZ0RhdGFbaV0ubGVuZ3RoKVxuICAgICAgICAgICAgICAgICAgICAgICAgbWVzc2FnZS5zdHJpbmdEYXRhW2ldID0gb2JqZWN0LnN0cmluZ0RhdGFbaV07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAob2JqZWN0LmludDY0RGF0YSkge1xuICAgICAgICAgICAgICAgIGlmICghQXJyYXkuaXNBcnJheShvYmplY3QuaW50NjREYXRhKSlcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgVHlwZUVycm9yKFwiLm9ubnguVGVuc29yUHJvdG8uaW50NjREYXRhOiBhcnJheSBleHBlY3RlZFwiKTtcbiAgICAgICAgICAgICAgICBtZXNzYWdlLmludDY0RGF0YSA9IFtdO1xuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgb2JqZWN0LmludDY0RGF0YS5sZW5ndGg7ICsraSlcbiAgICAgICAgICAgICAgICAgICAgaWYgKCR1dGlsLkxvbmcpXG4gICAgICAgICAgICAgICAgICAgICAgICAobWVzc2FnZS5pbnQ2NERhdGFbaV0gPSAkdXRpbC5Mb25nLmZyb21WYWx1ZShvYmplY3QuaW50NjREYXRhW2ldKSkudW5zaWduZWQgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgZWxzZSBpZiAodHlwZW9mIG9iamVjdC5pbnQ2NERhdGFbaV0gPT09IFwic3RyaW5nXCIpXG4gICAgICAgICAgICAgICAgICAgICAgICBtZXNzYWdlLmludDY0RGF0YVtpXSA9IHBhcnNlSW50KG9iamVjdC5pbnQ2NERhdGFbaV0sIDEwKTtcbiAgICAgICAgICAgICAgICAgICAgZWxzZSBpZiAodHlwZW9mIG9iamVjdC5pbnQ2NERhdGFbaV0gPT09IFwibnVtYmVyXCIpXG4gICAgICAgICAgICAgICAgICAgICAgICBtZXNzYWdlLmludDY0RGF0YVtpXSA9IG9iamVjdC5pbnQ2NERhdGFbaV07XG4gICAgICAgICAgICAgICAgICAgIGVsc2UgaWYgKHR5cGVvZiBvYmplY3QuaW50NjREYXRhW2ldID09PSBcIm9iamVjdFwiKVxuICAgICAgICAgICAgICAgICAgICAgICAgbWVzc2FnZS5pbnQ2NERhdGFbaV0gPSBuZXcgJHV0aWwuTG9uZ0JpdHMob2JqZWN0LmludDY0RGF0YVtpXS5sb3cgPj4+IDAsIG9iamVjdC5pbnQ2NERhdGFbaV0uaGlnaCA+Pj4gMCkudG9OdW1iZXIoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChvYmplY3QubmFtZSAhPSBudWxsKVxuICAgICAgICAgICAgICAgIG1lc3NhZ2UubmFtZSA9IFN0cmluZyhvYmplY3QubmFtZSk7XG4gICAgICAgICAgICBpZiAob2JqZWN0LmRvY1N0cmluZyAhPSBudWxsKVxuICAgICAgICAgICAgICAgIG1lc3NhZ2UuZG9jU3RyaW5nID0gU3RyaW5nKG9iamVjdC5kb2NTdHJpbmcpO1xuICAgICAgICAgICAgaWYgKG9iamVjdC5yYXdEYXRhICE9IG51bGwpXG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBvYmplY3QucmF3RGF0YSA9PT0gXCJzdHJpbmdcIilcbiAgICAgICAgICAgICAgICAgICAgJHV0aWwuYmFzZTY0LmRlY29kZShvYmplY3QucmF3RGF0YSwgbWVzc2FnZS5yYXdEYXRhID0gJHV0aWwubmV3QnVmZmVyKCR1dGlsLmJhc2U2NC5sZW5ndGgob2JqZWN0LnJhd0RhdGEpKSwgMCk7XG4gICAgICAgICAgICAgICAgZWxzZSBpZiAob2JqZWN0LnJhd0RhdGEubGVuZ3RoKVxuICAgICAgICAgICAgICAgICAgICBtZXNzYWdlLnJhd0RhdGEgPSBvYmplY3QucmF3RGF0YTtcbiAgICAgICAgICAgIGlmIChvYmplY3QuZXh0ZXJuYWxEYXRhKSB7XG4gICAgICAgICAgICAgICAgaWYgKCFBcnJheS5pc0FycmF5KG9iamVjdC5leHRlcm5hbERhdGEpKVxuICAgICAgICAgICAgICAgICAgICB0aHJvdyBUeXBlRXJyb3IoXCIub25ueC5UZW5zb3JQcm90by5leHRlcm5hbERhdGE6IGFycmF5IGV4cGVjdGVkXCIpO1xuICAgICAgICAgICAgICAgIG1lc3NhZ2UuZXh0ZXJuYWxEYXRhID0gW107XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBvYmplY3QuZXh0ZXJuYWxEYXRhLmxlbmd0aDsgKytpKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2Ygb2JqZWN0LmV4dGVybmFsRGF0YVtpXSAhPT0gXCJvYmplY3RcIilcbiAgICAgICAgICAgICAgICAgICAgICAgIHRocm93IFR5cGVFcnJvcihcIi5vbm54LlRlbnNvclByb3RvLmV4dGVybmFsRGF0YTogb2JqZWN0IGV4cGVjdGVkXCIpO1xuICAgICAgICAgICAgICAgICAgICBtZXNzYWdlLmV4dGVybmFsRGF0YVtpXSA9ICRyb290Lm9ubnguU3RyaW5nU3RyaW5nRW50cnlQcm90by5mcm9tT2JqZWN0KG9iamVjdC5leHRlcm5hbERhdGFbaV0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHN3aXRjaCAob2JqZWN0LmRhdGFMb2NhdGlvbikge1xuICAgICAgICAgICAgY2FzZSBcIkRFRkFVTFRcIjpcbiAgICAgICAgICAgIGNhc2UgMDpcbiAgICAgICAgICAgICAgICBtZXNzYWdlLmRhdGFMb2NhdGlvbiA9IDA7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIFwiRVhURVJOQUxcIjpcbiAgICAgICAgICAgIGNhc2UgMTpcbiAgICAgICAgICAgICAgICBtZXNzYWdlLmRhdGFMb2NhdGlvbiA9IDE7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAob2JqZWN0LmRvdWJsZURhdGEpIHtcbiAgICAgICAgICAgICAgICBpZiAoIUFycmF5LmlzQXJyYXkob2JqZWN0LmRvdWJsZURhdGEpKVxuICAgICAgICAgICAgICAgICAgICB0aHJvdyBUeXBlRXJyb3IoXCIub25ueC5UZW5zb3JQcm90by5kb3VibGVEYXRhOiBhcnJheSBleHBlY3RlZFwiKTtcbiAgICAgICAgICAgICAgICBtZXNzYWdlLmRvdWJsZURhdGEgPSBbXTtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG9iamVjdC5kb3VibGVEYXRhLmxlbmd0aDsgKytpKVxuICAgICAgICAgICAgICAgICAgICBtZXNzYWdlLmRvdWJsZURhdGFbaV0gPSBOdW1iZXIob2JqZWN0LmRvdWJsZURhdGFbaV0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG9iamVjdC51aW50NjREYXRhKSB7XG4gICAgICAgICAgICAgICAgaWYgKCFBcnJheS5pc0FycmF5KG9iamVjdC51aW50NjREYXRhKSlcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgVHlwZUVycm9yKFwiLm9ubnguVGVuc29yUHJvdG8udWludDY0RGF0YTogYXJyYXkgZXhwZWN0ZWRcIik7XG4gICAgICAgICAgICAgICAgbWVzc2FnZS51aW50NjREYXRhID0gW107XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBvYmplY3QudWludDY0RGF0YS5sZW5ndGg7ICsraSlcbiAgICAgICAgICAgICAgICAgICAgaWYgKCR1dGlsLkxvbmcpXG4gICAgICAgICAgICAgICAgICAgICAgICAobWVzc2FnZS51aW50NjREYXRhW2ldID0gJHV0aWwuTG9uZy5mcm9tVmFsdWUob2JqZWN0LnVpbnQ2NERhdGFbaV0pKS51bnNpZ25lZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIGVsc2UgaWYgKHR5cGVvZiBvYmplY3QudWludDY0RGF0YVtpXSA9PT0gXCJzdHJpbmdcIilcbiAgICAgICAgICAgICAgICAgICAgICAgIG1lc3NhZ2UudWludDY0RGF0YVtpXSA9IHBhcnNlSW50KG9iamVjdC51aW50NjREYXRhW2ldLCAxMCk7XG4gICAgICAgICAgICAgICAgICAgIGVsc2UgaWYgKHR5cGVvZiBvYmplY3QudWludDY0RGF0YVtpXSA9PT0gXCJudW1iZXJcIilcbiAgICAgICAgICAgICAgICAgICAgICAgIG1lc3NhZ2UudWludDY0RGF0YVtpXSA9IG9iamVjdC51aW50NjREYXRhW2ldO1xuICAgICAgICAgICAgICAgICAgICBlbHNlIGlmICh0eXBlb2Ygb2JqZWN0LnVpbnQ2NERhdGFbaV0gPT09IFwib2JqZWN0XCIpXG4gICAgICAgICAgICAgICAgICAgICAgICBtZXNzYWdlLnVpbnQ2NERhdGFbaV0gPSBuZXcgJHV0aWwuTG9uZ0JpdHMob2JqZWN0LnVpbnQ2NERhdGFbaV0ubG93ID4+PiAwLCBvYmplY3QudWludDY0RGF0YVtpXS5oaWdoID4+PiAwKS50b051bWJlcih0cnVlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBtZXNzYWdlO1xuICAgICAgICB9O1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBDcmVhdGVzIGEgcGxhaW4gb2JqZWN0IGZyb20gYSBUZW5zb3JQcm90byBtZXNzYWdlLiBBbHNvIGNvbnZlcnRzIHZhbHVlcyB0byBvdGhlciB0eXBlcyBpZiBzcGVjaWZpZWQuXG4gICAgICAgICAqIEBmdW5jdGlvbiB0b09iamVjdFxuICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueC5UZW5zb3JQcm90b1xuICAgICAgICAgKiBAc3RhdGljXG4gICAgICAgICAqIEBwYXJhbSB7b25ueC5UZW5zb3JQcm90b30gbWVzc2FnZSBUZW5zb3JQcm90b1xuICAgICAgICAgKiBAcGFyYW0geyRwcm90b2J1Zi5JQ29udmVyc2lvbk9wdGlvbnN9IFtvcHRpb25zXSBDb252ZXJzaW9uIG9wdGlvbnNcbiAgICAgICAgICogQHJldHVybnMge09iamVjdC48c3RyaW5nLCo+fSBQbGFpbiBvYmplY3RcbiAgICAgICAgICovXG4gICAgICAgIFRlbnNvclByb3RvLnRvT2JqZWN0ID0gZnVuY3Rpb24gdG9PYmplY3QobWVzc2FnZSwgb3B0aW9ucykge1xuICAgICAgICAgICAgaWYgKCFvcHRpb25zKVxuICAgICAgICAgICAgICAgIG9wdGlvbnMgPSB7fTtcbiAgICAgICAgICAgIHZhciBvYmplY3QgPSB7fTtcbiAgICAgICAgICAgIGlmIChvcHRpb25zLmFycmF5cyB8fCBvcHRpb25zLmRlZmF1bHRzKSB7XG4gICAgICAgICAgICAgICAgb2JqZWN0LmRpbXMgPSBbXTtcbiAgICAgICAgICAgICAgICBvYmplY3QuZmxvYXREYXRhID0gW107XG4gICAgICAgICAgICAgICAgb2JqZWN0LmludDMyRGF0YSA9IFtdO1xuICAgICAgICAgICAgICAgIG9iamVjdC5zdHJpbmdEYXRhID0gW107XG4gICAgICAgICAgICAgICAgb2JqZWN0LmludDY0RGF0YSA9IFtdO1xuICAgICAgICAgICAgICAgIG9iamVjdC5kb3VibGVEYXRhID0gW107XG4gICAgICAgICAgICAgICAgb2JqZWN0LnVpbnQ2NERhdGEgPSBbXTtcbiAgICAgICAgICAgICAgICBvYmplY3QuZXh0ZXJuYWxEYXRhID0gW107XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAob3B0aW9ucy5kZWZhdWx0cykge1xuICAgICAgICAgICAgICAgIG9iamVjdC5kYXRhVHlwZSA9IDA7XG4gICAgICAgICAgICAgICAgb2JqZWN0LnNlZ21lbnQgPSBudWxsO1xuICAgICAgICAgICAgICAgIG9iamVjdC5uYW1lID0gXCJcIjtcbiAgICAgICAgICAgICAgICBpZiAob3B0aW9ucy5ieXRlcyA9PT0gU3RyaW5nKVxuICAgICAgICAgICAgICAgICAgICBvYmplY3QucmF3RGF0YSA9IFwiXCI7XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIG9iamVjdC5yYXdEYXRhID0gW107XG4gICAgICAgICAgICAgICAgICAgIGlmIChvcHRpb25zLmJ5dGVzICE9PSBBcnJheSlcbiAgICAgICAgICAgICAgICAgICAgICAgIG9iamVjdC5yYXdEYXRhID0gJHV0aWwubmV3QnVmZmVyKG9iamVjdC5yYXdEYXRhKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgb2JqZWN0LmRvY1N0cmluZyA9IFwiXCI7XG4gICAgICAgICAgICAgICAgb2JqZWN0LmRhdGFMb2NhdGlvbiA9IG9wdGlvbnMuZW51bXMgPT09IFN0cmluZyA/IFwiREVGQVVMVFwiIDogMDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChtZXNzYWdlLmRpbXMgJiYgbWVzc2FnZS5kaW1zLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgIG9iamVjdC5kaW1zID0gW107XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaiA9IDA7IGogPCBtZXNzYWdlLmRpbXMubGVuZ3RoOyArK2opXG4gICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgbWVzc2FnZS5kaW1zW2pdID09PSBcIm51bWJlclwiKVxuICAgICAgICAgICAgICAgICAgICAgICAgb2JqZWN0LmRpbXNbal0gPSBvcHRpb25zLmxvbmdzID09PSBTdHJpbmcgPyBTdHJpbmcobWVzc2FnZS5kaW1zW2pdKSA6IG1lc3NhZ2UuZGltc1tqXTtcbiAgICAgICAgICAgICAgICAgICAgZWxzZVxuICAgICAgICAgICAgICAgICAgICAgICAgb2JqZWN0LmRpbXNbal0gPSBvcHRpb25zLmxvbmdzID09PSBTdHJpbmcgPyAkdXRpbC5Mb25nLnByb3RvdHlwZS50b1N0cmluZy5jYWxsKG1lc3NhZ2UuZGltc1tqXSkgOiBvcHRpb25zLmxvbmdzID09PSBOdW1iZXIgPyBuZXcgJHV0aWwuTG9uZ0JpdHMobWVzc2FnZS5kaW1zW2pdLmxvdyA+Pj4gMCwgbWVzc2FnZS5kaW1zW2pdLmhpZ2ggPj4+IDApLnRvTnVtYmVyKCkgOiBtZXNzYWdlLmRpbXNbal07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAobWVzc2FnZS5kYXRhVHlwZSAhPSBudWxsICYmIG1lc3NhZ2UuaGFzT3duUHJvcGVydHkoXCJkYXRhVHlwZVwiKSlcbiAgICAgICAgICAgICAgICBvYmplY3QuZGF0YVR5cGUgPSBtZXNzYWdlLmRhdGFUeXBlO1xuICAgICAgICAgICAgaWYgKG1lc3NhZ2Uuc2VnbWVudCAhPSBudWxsICYmIG1lc3NhZ2UuaGFzT3duUHJvcGVydHkoXCJzZWdtZW50XCIpKVxuICAgICAgICAgICAgICAgIG9iamVjdC5zZWdtZW50ID0gJHJvb3Qub25ueC5UZW5zb3JQcm90by5TZWdtZW50LnRvT2JqZWN0KG1lc3NhZ2Uuc2VnbWVudCwgb3B0aW9ucyk7XG4gICAgICAgICAgICBpZiAobWVzc2FnZS5mbG9hdERhdGEgJiYgbWVzc2FnZS5mbG9hdERhdGEubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgb2JqZWN0LmZsb2F0RGF0YSA9IFtdO1xuICAgICAgICAgICAgICAgIGZvciAodmFyIGogPSAwOyBqIDwgbWVzc2FnZS5mbG9hdERhdGEubGVuZ3RoOyArK2opXG4gICAgICAgICAgICAgICAgICAgIG9iamVjdC5mbG9hdERhdGFbal0gPSBvcHRpb25zLmpzb24gJiYgIWlzRmluaXRlKG1lc3NhZ2UuZmxvYXREYXRhW2pdKSA/IFN0cmluZyhtZXNzYWdlLmZsb2F0RGF0YVtqXSkgOiBtZXNzYWdlLmZsb2F0RGF0YVtqXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChtZXNzYWdlLmludDMyRGF0YSAmJiBtZXNzYWdlLmludDMyRGF0YS5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICBvYmplY3QuaW50MzJEYXRhID0gW107XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaiA9IDA7IGogPCBtZXNzYWdlLmludDMyRGF0YS5sZW5ndGg7ICsrailcbiAgICAgICAgICAgICAgICAgICAgb2JqZWN0LmludDMyRGF0YVtqXSA9IG1lc3NhZ2UuaW50MzJEYXRhW2pdO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG1lc3NhZ2Uuc3RyaW5nRGF0YSAmJiBtZXNzYWdlLnN0cmluZ0RhdGEubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgb2JqZWN0LnN0cmluZ0RhdGEgPSBbXTtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBqID0gMDsgaiA8IG1lc3NhZ2Uuc3RyaW5nRGF0YS5sZW5ndGg7ICsrailcbiAgICAgICAgICAgICAgICAgICAgb2JqZWN0LnN0cmluZ0RhdGFbal0gPSBvcHRpb25zLmJ5dGVzID09PSBTdHJpbmcgPyAkdXRpbC5iYXNlNjQuZW5jb2RlKG1lc3NhZ2Uuc3RyaW5nRGF0YVtqXSwgMCwgbWVzc2FnZS5zdHJpbmdEYXRhW2pdLmxlbmd0aCkgOiBvcHRpb25zLmJ5dGVzID09PSBBcnJheSA/IEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKG1lc3NhZ2Uuc3RyaW5nRGF0YVtqXSkgOiBtZXNzYWdlLnN0cmluZ0RhdGFbal07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAobWVzc2FnZS5pbnQ2NERhdGEgJiYgbWVzc2FnZS5pbnQ2NERhdGEubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgb2JqZWN0LmludDY0RGF0YSA9IFtdO1xuICAgICAgICAgICAgICAgIGZvciAodmFyIGogPSAwOyBqIDwgbWVzc2FnZS5pbnQ2NERhdGEubGVuZ3RoOyArK2opXG4gICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgbWVzc2FnZS5pbnQ2NERhdGFbal0gPT09IFwibnVtYmVyXCIpXG4gICAgICAgICAgICAgICAgICAgICAgICBvYmplY3QuaW50NjREYXRhW2pdID0gb3B0aW9ucy5sb25ncyA9PT0gU3RyaW5nID8gU3RyaW5nKG1lc3NhZ2UuaW50NjREYXRhW2pdKSA6IG1lc3NhZ2UuaW50NjREYXRhW2pdO1xuICAgICAgICAgICAgICAgICAgICBlbHNlXG4gICAgICAgICAgICAgICAgICAgICAgICBvYmplY3QuaW50NjREYXRhW2pdID0gb3B0aW9ucy5sb25ncyA9PT0gU3RyaW5nID8gJHV0aWwuTG9uZy5wcm90b3R5cGUudG9TdHJpbmcuY2FsbChtZXNzYWdlLmludDY0RGF0YVtqXSkgOiBvcHRpb25zLmxvbmdzID09PSBOdW1iZXIgPyBuZXcgJHV0aWwuTG9uZ0JpdHMobWVzc2FnZS5pbnQ2NERhdGFbal0ubG93ID4+PiAwLCBtZXNzYWdlLmludDY0RGF0YVtqXS5oaWdoID4+PiAwKS50b051bWJlcigpIDogbWVzc2FnZS5pbnQ2NERhdGFbal07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAobWVzc2FnZS5uYW1lICE9IG51bGwgJiYgbWVzc2FnZS5oYXNPd25Qcm9wZXJ0eShcIm5hbWVcIikpXG4gICAgICAgICAgICAgICAgb2JqZWN0Lm5hbWUgPSBtZXNzYWdlLm5hbWU7XG4gICAgICAgICAgICBpZiAobWVzc2FnZS5yYXdEYXRhICE9IG51bGwgJiYgbWVzc2FnZS5oYXNPd25Qcm9wZXJ0eShcInJhd0RhdGFcIikpXG4gICAgICAgICAgICAgICAgb2JqZWN0LnJhd0RhdGEgPSBvcHRpb25zLmJ5dGVzID09PSBTdHJpbmcgPyAkdXRpbC5iYXNlNjQuZW5jb2RlKG1lc3NhZ2UucmF3RGF0YSwgMCwgbWVzc2FnZS5yYXdEYXRhLmxlbmd0aCkgOiBvcHRpb25zLmJ5dGVzID09PSBBcnJheSA/IEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKG1lc3NhZ2UucmF3RGF0YSkgOiBtZXNzYWdlLnJhd0RhdGE7XG4gICAgICAgICAgICBpZiAobWVzc2FnZS5kb3VibGVEYXRhICYmIG1lc3NhZ2UuZG91YmxlRGF0YS5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICBvYmplY3QuZG91YmxlRGF0YSA9IFtdO1xuICAgICAgICAgICAgICAgIGZvciAodmFyIGogPSAwOyBqIDwgbWVzc2FnZS5kb3VibGVEYXRhLmxlbmd0aDsgKytqKVxuICAgICAgICAgICAgICAgICAgICBvYmplY3QuZG91YmxlRGF0YVtqXSA9IG9wdGlvbnMuanNvbiAmJiAhaXNGaW5pdGUobWVzc2FnZS5kb3VibGVEYXRhW2pdKSA/IFN0cmluZyhtZXNzYWdlLmRvdWJsZURhdGFbal0pIDogbWVzc2FnZS5kb3VibGVEYXRhW2pdO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG1lc3NhZ2UudWludDY0RGF0YSAmJiBtZXNzYWdlLnVpbnQ2NERhdGEubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgb2JqZWN0LnVpbnQ2NERhdGEgPSBbXTtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBqID0gMDsgaiA8IG1lc3NhZ2UudWludDY0RGF0YS5sZW5ndGg7ICsrailcbiAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBtZXNzYWdlLnVpbnQ2NERhdGFbal0gPT09IFwibnVtYmVyXCIpXG4gICAgICAgICAgICAgICAgICAgICAgICBvYmplY3QudWludDY0RGF0YVtqXSA9IG9wdGlvbnMubG9uZ3MgPT09IFN0cmluZyA/IFN0cmluZyhtZXNzYWdlLnVpbnQ2NERhdGFbal0pIDogbWVzc2FnZS51aW50NjREYXRhW2pdO1xuICAgICAgICAgICAgICAgICAgICBlbHNlXG4gICAgICAgICAgICAgICAgICAgICAgICBvYmplY3QudWludDY0RGF0YVtqXSA9IG9wdGlvbnMubG9uZ3MgPT09IFN0cmluZyA/ICR1dGlsLkxvbmcucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwobWVzc2FnZS51aW50NjREYXRhW2pdKSA6IG9wdGlvbnMubG9uZ3MgPT09IE51bWJlciA/IG5ldyAkdXRpbC5Mb25nQml0cyhtZXNzYWdlLnVpbnQ2NERhdGFbal0ubG93ID4+PiAwLCBtZXNzYWdlLnVpbnQ2NERhdGFbal0uaGlnaCA+Pj4gMCkudG9OdW1iZXIodHJ1ZSkgOiBtZXNzYWdlLnVpbnQ2NERhdGFbal07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAobWVzc2FnZS5kb2NTdHJpbmcgIT0gbnVsbCAmJiBtZXNzYWdlLmhhc093blByb3BlcnR5KFwiZG9jU3RyaW5nXCIpKVxuICAgICAgICAgICAgICAgIG9iamVjdC5kb2NTdHJpbmcgPSBtZXNzYWdlLmRvY1N0cmluZztcbiAgICAgICAgICAgIGlmIChtZXNzYWdlLmV4dGVybmFsRGF0YSAmJiBtZXNzYWdlLmV4dGVybmFsRGF0YS5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICBvYmplY3QuZXh0ZXJuYWxEYXRhID0gW107XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaiA9IDA7IGogPCBtZXNzYWdlLmV4dGVybmFsRGF0YS5sZW5ndGg7ICsrailcbiAgICAgICAgICAgICAgICAgICAgb2JqZWN0LmV4dGVybmFsRGF0YVtqXSA9ICRyb290Lm9ubnguU3RyaW5nU3RyaW5nRW50cnlQcm90by50b09iamVjdChtZXNzYWdlLmV4dGVybmFsRGF0YVtqXSwgb3B0aW9ucyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAobWVzc2FnZS5kYXRhTG9jYXRpb24gIT0gbnVsbCAmJiBtZXNzYWdlLmhhc093blByb3BlcnR5KFwiZGF0YUxvY2F0aW9uXCIpKVxuICAgICAgICAgICAgICAgIG9iamVjdC5kYXRhTG9jYXRpb24gPSBvcHRpb25zLmVudW1zID09PSBTdHJpbmcgPyAkcm9vdC5vbm54LlRlbnNvclByb3RvLkRhdGFMb2NhdGlvblttZXNzYWdlLmRhdGFMb2NhdGlvbl0gOiBtZXNzYWdlLmRhdGFMb2NhdGlvbjtcbiAgICAgICAgICAgIHJldHVybiBvYmplY3Q7XG4gICAgICAgIH07XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIENvbnZlcnRzIHRoaXMgVGVuc29yUHJvdG8gdG8gSlNPTi5cbiAgICAgICAgICogQGZ1bmN0aW9uIHRvSlNPTlxuICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueC5UZW5zb3JQcm90b1xuICAgICAgICAgKiBAaW5zdGFuY2VcbiAgICAgICAgICogQHJldHVybnMge09iamVjdC48c3RyaW5nLCo+fSBKU09OIG9iamVjdFxuICAgICAgICAgKi9cbiAgICAgICAgVGVuc29yUHJvdG8ucHJvdG90eXBlLnRvSlNPTiA9IGZ1bmN0aW9uIHRvSlNPTigpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmNvbnN0cnVjdG9yLnRvT2JqZWN0KHRoaXMsICRwcm90b2J1Zi51dGlsLnRvSlNPTk9wdGlvbnMpO1xuICAgICAgICB9O1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBEYXRhVHlwZSBlbnVtLlxuICAgICAgICAgKiBAbmFtZSBvbm54LlRlbnNvclByb3RvLkRhdGFUeXBlXG4gICAgICAgICAqIEBlbnVtIHtzdHJpbmd9XG4gICAgICAgICAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBVTkRFRklORUQ9MCBVTkRFRklORUQgdmFsdWVcbiAgICAgICAgICogQHByb3BlcnR5IHtudW1iZXJ9IEZMT0FUPTEgRkxPQVQgdmFsdWVcbiAgICAgICAgICogQHByb3BlcnR5IHtudW1iZXJ9IFVJTlQ4PTIgVUlOVDggdmFsdWVcbiAgICAgICAgICogQHByb3BlcnR5IHtudW1iZXJ9IElOVDg9MyBJTlQ4IHZhbHVlXG4gICAgICAgICAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBVSU5UMTY9NCBVSU5UMTYgdmFsdWVcbiAgICAgICAgICogQHByb3BlcnR5IHtudW1iZXJ9IElOVDE2PTUgSU5UMTYgdmFsdWVcbiAgICAgICAgICogQHByb3BlcnR5IHtudW1iZXJ9IElOVDMyPTYgSU5UMzIgdmFsdWVcbiAgICAgICAgICogQHByb3BlcnR5IHtudW1iZXJ9IElOVDY0PTcgSU5UNjQgdmFsdWVcbiAgICAgICAgICogQHByb3BlcnR5IHtudW1iZXJ9IFNUUklORz04IFNUUklORyB2YWx1ZVxuICAgICAgICAgKiBAcHJvcGVydHkge251bWJlcn0gQk9PTD05IEJPT0wgdmFsdWVcbiAgICAgICAgICogQHByb3BlcnR5IHtudW1iZXJ9IEZMT0FUMTY9MTAgRkxPQVQxNiB2YWx1ZVxuICAgICAgICAgKiBAcHJvcGVydHkge251bWJlcn0gRE9VQkxFPTExIERPVUJMRSB2YWx1ZVxuICAgICAgICAgKiBAcHJvcGVydHkge251bWJlcn0gVUlOVDMyPTEyIFVJTlQzMiB2YWx1ZVxuICAgICAgICAgKiBAcHJvcGVydHkge251bWJlcn0gVUlOVDY0PTEzIFVJTlQ2NCB2YWx1ZVxuICAgICAgICAgKiBAcHJvcGVydHkge251bWJlcn0gQ09NUExFWDY0PTE0IENPTVBMRVg2NCB2YWx1ZVxuICAgICAgICAgKiBAcHJvcGVydHkge251bWJlcn0gQ09NUExFWDEyOD0xNSBDT01QTEVYMTI4IHZhbHVlXG4gICAgICAgICAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBCRkxPQVQxNj0xNiBCRkxPQVQxNiB2YWx1ZVxuICAgICAgICAgKi9cbiAgICAgICAgVGVuc29yUHJvdG8uRGF0YVR5cGUgPSAoZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICB2YXIgdmFsdWVzQnlJZCA9IHt9LCB2YWx1ZXMgPSBPYmplY3QuY3JlYXRlKHZhbHVlc0J5SWQpO1xuICAgICAgICAgICAgdmFsdWVzW3ZhbHVlc0J5SWRbMF0gPSBcIlVOREVGSU5FRFwiXSA9IDA7XG4gICAgICAgICAgICB2YWx1ZXNbdmFsdWVzQnlJZFsxXSA9IFwiRkxPQVRcIl0gPSAxO1xuICAgICAgICAgICAgdmFsdWVzW3ZhbHVlc0J5SWRbMl0gPSBcIlVJTlQ4XCJdID0gMjtcbiAgICAgICAgICAgIHZhbHVlc1t2YWx1ZXNCeUlkWzNdID0gXCJJTlQ4XCJdID0gMztcbiAgICAgICAgICAgIHZhbHVlc1t2YWx1ZXNCeUlkWzRdID0gXCJVSU5UMTZcIl0gPSA0O1xuICAgICAgICAgICAgdmFsdWVzW3ZhbHVlc0J5SWRbNV0gPSBcIklOVDE2XCJdID0gNTtcbiAgICAgICAgICAgIHZhbHVlc1t2YWx1ZXNCeUlkWzZdID0gXCJJTlQzMlwiXSA9IDY7XG4gICAgICAgICAgICB2YWx1ZXNbdmFsdWVzQnlJZFs3XSA9IFwiSU5UNjRcIl0gPSA3O1xuICAgICAgICAgICAgdmFsdWVzW3ZhbHVlc0J5SWRbOF0gPSBcIlNUUklOR1wiXSA9IDg7XG4gICAgICAgICAgICB2YWx1ZXNbdmFsdWVzQnlJZFs5XSA9IFwiQk9PTFwiXSA9IDk7XG4gICAgICAgICAgICB2YWx1ZXNbdmFsdWVzQnlJZFsxMF0gPSBcIkZMT0FUMTZcIl0gPSAxMDtcbiAgICAgICAgICAgIHZhbHVlc1t2YWx1ZXNCeUlkWzExXSA9IFwiRE9VQkxFXCJdID0gMTE7XG4gICAgICAgICAgICB2YWx1ZXNbdmFsdWVzQnlJZFsxMl0gPSBcIlVJTlQzMlwiXSA9IDEyO1xuICAgICAgICAgICAgdmFsdWVzW3ZhbHVlc0J5SWRbMTNdID0gXCJVSU5UNjRcIl0gPSAxMztcbiAgICAgICAgICAgIHZhbHVlc1t2YWx1ZXNCeUlkWzE0XSA9IFwiQ09NUExFWDY0XCJdID0gMTQ7XG4gICAgICAgICAgICB2YWx1ZXNbdmFsdWVzQnlJZFsxNV0gPSBcIkNPTVBMRVgxMjhcIl0gPSAxNTtcbiAgICAgICAgICAgIHZhbHVlc1t2YWx1ZXNCeUlkWzE2XSA9IFwiQkZMT0FUMTZcIl0gPSAxNjtcbiAgICAgICAgICAgIHJldHVybiB2YWx1ZXM7XG4gICAgICAgIH0pKCk7XG5cbiAgICAgICAgVGVuc29yUHJvdG8uU2VnbWVudCA9IChmdW5jdGlvbigpIHtcblxuICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgKiBQcm9wZXJ0aWVzIG9mIGEgU2VnbWVudC5cbiAgICAgICAgICAgICAqIEBtZW1iZXJvZiBvbm54LlRlbnNvclByb3RvXG4gICAgICAgICAgICAgKiBAaW50ZXJmYWNlIElTZWdtZW50XG4gICAgICAgICAgICAgKiBAcHJvcGVydHkge251bWJlcnxMb25nfG51bGx9IFtiZWdpbl0gU2VnbWVudCBiZWdpblxuICAgICAgICAgICAgICogQHByb3BlcnR5IHtudW1iZXJ8TG9uZ3xudWxsfSBbZW5kXSBTZWdtZW50IGVuZFxuICAgICAgICAgICAgICovXG5cbiAgICAgICAgICAgIC8qKlxuICAgICAgICAgICAgICogQ29uc3RydWN0cyBhIG5ldyBTZWdtZW50LlxuICAgICAgICAgICAgICogQG1lbWJlcm9mIG9ubnguVGVuc29yUHJvdG9cbiAgICAgICAgICAgICAqIEBjbGFzc2Rlc2MgUmVwcmVzZW50cyBhIFNlZ21lbnQuXG4gICAgICAgICAgICAgKiBAaW1wbGVtZW50cyBJU2VnbWVudFxuICAgICAgICAgICAgICogQGNvbnN0cnVjdG9yXG4gICAgICAgICAgICAgKiBAcGFyYW0ge29ubnguVGVuc29yUHJvdG8uSVNlZ21lbnQ9fSBbcHJvcGVydGllc10gUHJvcGVydGllcyB0byBzZXRcbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgZnVuY3Rpb24gU2VnbWVudChwcm9wZXJ0aWVzKSB7XG4gICAgICAgICAgICAgICAgaWYgKHByb3BlcnRpZXMpXG4gICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGtleXMgPSBPYmplY3Qua2V5cyhwcm9wZXJ0aWVzKSwgaSA9IDA7IGkgPCBrZXlzLmxlbmd0aDsgKytpKVxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHByb3BlcnRpZXNba2V5c1tpXV0gIT0gbnVsbClcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzW2tleXNbaV1dID0gcHJvcGVydGllc1trZXlzW2ldXTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgKiBTZWdtZW50IGJlZ2luLlxuICAgICAgICAgICAgICogQG1lbWJlciB7bnVtYmVyfExvbmd9IGJlZ2luXG4gICAgICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueC5UZW5zb3JQcm90by5TZWdtZW50XG4gICAgICAgICAgICAgKiBAaW5zdGFuY2VcbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgU2VnbWVudC5wcm90b3R5cGUuYmVnaW4gPSAkdXRpbC5Mb25nID8gJHV0aWwuTG9uZy5mcm9tQml0cygwLDAsZmFsc2UpIDogMDtcblxuICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgKiBTZWdtZW50IGVuZC5cbiAgICAgICAgICAgICAqIEBtZW1iZXIge251bWJlcnxMb25nfSBlbmRcbiAgICAgICAgICAgICAqIEBtZW1iZXJvZiBvbm54LlRlbnNvclByb3RvLlNlZ21lbnRcbiAgICAgICAgICAgICAqIEBpbnN0YW5jZVxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBTZWdtZW50LnByb3RvdHlwZS5lbmQgPSAkdXRpbC5Mb25nID8gJHV0aWwuTG9uZy5mcm9tQml0cygwLDAsZmFsc2UpIDogMDtcblxuICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgKiBDcmVhdGVzIGEgbmV3IFNlZ21lbnQgaW5zdGFuY2UgdXNpbmcgdGhlIHNwZWNpZmllZCBwcm9wZXJ0aWVzLlxuICAgICAgICAgICAgICogQGZ1bmN0aW9uIGNyZWF0ZVxuICAgICAgICAgICAgICogQG1lbWJlcm9mIG9ubnguVGVuc29yUHJvdG8uU2VnbWVudFxuICAgICAgICAgICAgICogQHN0YXRpY1xuICAgICAgICAgICAgICogQHBhcmFtIHtvbm54LlRlbnNvclByb3RvLklTZWdtZW50PX0gW3Byb3BlcnRpZXNdIFByb3BlcnRpZXMgdG8gc2V0XG4gICAgICAgICAgICAgKiBAcmV0dXJucyB7b25ueC5UZW5zb3JQcm90by5TZWdtZW50fSBTZWdtZW50IGluc3RhbmNlXG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIFNlZ21lbnQuY3JlYXRlID0gZnVuY3Rpb24gY3JlYXRlKHByb3BlcnRpZXMpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbmV3IFNlZ21lbnQocHJvcGVydGllcyk7XG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICAvKipcbiAgICAgICAgICAgICAqIEVuY29kZXMgdGhlIHNwZWNpZmllZCBTZWdtZW50IG1lc3NhZ2UuIERvZXMgbm90IGltcGxpY2l0bHkge0BsaW5rIG9ubnguVGVuc29yUHJvdG8uU2VnbWVudC52ZXJpZnl8dmVyaWZ5fSBtZXNzYWdlcy5cbiAgICAgICAgICAgICAqIEBmdW5jdGlvbiBlbmNvZGVcbiAgICAgICAgICAgICAqIEBtZW1iZXJvZiBvbm54LlRlbnNvclByb3RvLlNlZ21lbnRcbiAgICAgICAgICAgICAqIEBzdGF0aWNcbiAgICAgICAgICAgICAqIEBwYXJhbSB7b25ueC5UZW5zb3JQcm90by5JU2VnbWVudH0gbWVzc2FnZSBTZWdtZW50IG1lc3NhZ2Ugb3IgcGxhaW4gb2JqZWN0IHRvIGVuY29kZVxuICAgICAgICAgICAgICogQHBhcmFtIHskcHJvdG9idWYuV3JpdGVyfSBbd3JpdGVyXSBXcml0ZXIgdG8gZW5jb2RlIHRvXG4gICAgICAgICAgICAgKiBAcmV0dXJucyB7JHByb3RvYnVmLldyaXRlcn0gV3JpdGVyXG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIFNlZ21lbnQuZW5jb2RlID0gZnVuY3Rpb24gZW5jb2RlKG1lc3NhZ2UsIHdyaXRlcikge1xuICAgICAgICAgICAgICAgIGlmICghd3JpdGVyKVxuICAgICAgICAgICAgICAgICAgICB3cml0ZXIgPSAkV3JpdGVyLmNyZWF0ZSgpO1xuICAgICAgICAgICAgICAgIGlmIChtZXNzYWdlLmJlZ2luICE9IG51bGwgJiYgbWVzc2FnZS5oYXNPd25Qcm9wZXJ0eShcImJlZ2luXCIpKVxuICAgICAgICAgICAgICAgICAgICB3cml0ZXIudWludDMyKC8qIGlkIDEsIHdpcmVUeXBlIDAgPSovOCkuaW50NjQobWVzc2FnZS5iZWdpbik7XG4gICAgICAgICAgICAgICAgaWYgKG1lc3NhZ2UuZW5kICE9IG51bGwgJiYgbWVzc2FnZS5oYXNPd25Qcm9wZXJ0eShcImVuZFwiKSlcbiAgICAgICAgICAgICAgICAgICAgd3JpdGVyLnVpbnQzMigvKiBpZCAyLCB3aXJlVHlwZSAwID0qLzE2KS5pbnQ2NChtZXNzYWdlLmVuZCk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHdyaXRlcjtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIC8qKlxuICAgICAgICAgICAgICogRW5jb2RlcyB0aGUgc3BlY2lmaWVkIFNlZ21lbnQgbWVzc2FnZSwgbGVuZ3RoIGRlbGltaXRlZC4gRG9lcyBub3QgaW1wbGljaXRseSB7QGxpbmsgb25ueC5UZW5zb3JQcm90by5TZWdtZW50LnZlcmlmeXx2ZXJpZnl9IG1lc3NhZ2VzLlxuICAgICAgICAgICAgICogQGZ1bmN0aW9uIGVuY29kZURlbGltaXRlZFxuICAgICAgICAgICAgICogQG1lbWJlcm9mIG9ubnguVGVuc29yUHJvdG8uU2VnbWVudFxuICAgICAgICAgICAgICogQHN0YXRpY1xuICAgICAgICAgICAgICogQHBhcmFtIHtvbm54LlRlbnNvclByb3RvLklTZWdtZW50fSBtZXNzYWdlIFNlZ21lbnQgbWVzc2FnZSBvciBwbGFpbiBvYmplY3QgdG8gZW5jb2RlXG4gICAgICAgICAgICAgKiBAcGFyYW0geyRwcm90b2J1Zi5Xcml0ZXJ9IFt3cml0ZXJdIFdyaXRlciB0byBlbmNvZGUgdG9cbiAgICAgICAgICAgICAqIEByZXR1cm5zIHskcHJvdG9idWYuV3JpdGVyfSBXcml0ZXJcbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgU2VnbWVudC5lbmNvZGVEZWxpbWl0ZWQgPSBmdW5jdGlvbiBlbmNvZGVEZWxpbWl0ZWQobWVzc2FnZSwgd3JpdGVyKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuZW5jb2RlKG1lc3NhZ2UsIHdyaXRlcikubGRlbGltKCk7XG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICAvKipcbiAgICAgICAgICAgICAqIERlY29kZXMgYSBTZWdtZW50IG1lc3NhZ2UgZnJvbSB0aGUgc3BlY2lmaWVkIHJlYWRlciBvciBidWZmZXIuXG4gICAgICAgICAgICAgKiBAZnVuY3Rpb24gZGVjb2RlXG4gICAgICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueC5UZW5zb3JQcm90by5TZWdtZW50XG4gICAgICAgICAgICAgKiBAc3RhdGljXG4gICAgICAgICAgICAgKiBAcGFyYW0geyRwcm90b2J1Zi5SZWFkZXJ8VWludDhBcnJheX0gcmVhZGVyIFJlYWRlciBvciBidWZmZXIgdG8gZGVjb2RlIGZyb21cbiAgICAgICAgICAgICAqIEBwYXJhbSB7bnVtYmVyfSBbbGVuZ3RoXSBNZXNzYWdlIGxlbmd0aCBpZiBrbm93biBiZWZvcmVoYW5kXG4gICAgICAgICAgICAgKiBAcmV0dXJucyB7b25ueC5UZW5zb3JQcm90by5TZWdtZW50fSBTZWdtZW50XG4gICAgICAgICAgICAgKiBAdGhyb3dzIHtFcnJvcn0gSWYgdGhlIHBheWxvYWQgaXMgbm90IGEgcmVhZGVyIG9yIHZhbGlkIGJ1ZmZlclxuICAgICAgICAgICAgICogQHRocm93cyB7JHByb3RvYnVmLnV0aWwuUHJvdG9jb2xFcnJvcn0gSWYgcmVxdWlyZWQgZmllbGRzIGFyZSBtaXNzaW5nXG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIFNlZ21lbnQuZGVjb2RlID0gZnVuY3Rpb24gZGVjb2RlKHJlYWRlciwgbGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgaWYgKCEocmVhZGVyIGluc3RhbmNlb2YgJFJlYWRlcikpXG4gICAgICAgICAgICAgICAgICAgIHJlYWRlciA9ICRSZWFkZXIuY3JlYXRlKHJlYWRlcik7XG4gICAgICAgICAgICAgICAgdmFyIGVuZCA9IGxlbmd0aCA9PT0gdW5kZWZpbmVkID8gcmVhZGVyLmxlbiA6IHJlYWRlci5wb3MgKyBsZW5ndGgsIG1lc3NhZ2UgPSBuZXcgJHJvb3Qub25ueC5UZW5zb3JQcm90by5TZWdtZW50KCk7XG4gICAgICAgICAgICAgICAgd2hpbGUgKHJlYWRlci5wb3MgPCBlbmQpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHRhZyA9IHJlYWRlci51aW50MzIoKTtcbiAgICAgICAgICAgICAgICAgICAgc3dpdGNoICh0YWcgPj4+IDMpIHtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAxOlxuICAgICAgICAgICAgICAgICAgICAgICAgbWVzc2FnZS5iZWdpbiA9IHJlYWRlci5pbnQ2NCgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgMjpcbiAgICAgICAgICAgICAgICAgICAgICAgIG1lc3NhZ2UuZW5kID0gcmVhZGVyLmludDY0KCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlYWRlci5za2lwVHlwZSh0YWcgJiA3KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiBtZXNzYWdlO1xuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgKiBEZWNvZGVzIGEgU2VnbWVudCBtZXNzYWdlIGZyb20gdGhlIHNwZWNpZmllZCByZWFkZXIgb3IgYnVmZmVyLCBsZW5ndGggZGVsaW1pdGVkLlxuICAgICAgICAgICAgICogQGZ1bmN0aW9uIGRlY29kZURlbGltaXRlZFxuICAgICAgICAgICAgICogQG1lbWJlcm9mIG9ubnguVGVuc29yUHJvdG8uU2VnbWVudFxuICAgICAgICAgICAgICogQHN0YXRpY1xuICAgICAgICAgICAgICogQHBhcmFtIHskcHJvdG9idWYuUmVhZGVyfFVpbnQ4QXJyYXl9IHJlYWRlciBSZWFkZXIgb3IgYnVmZmVyIHRvIGRlY29kZSBmcm9tXG4gICAgICAgICAgICAgKiBAcmV0dXJucyB7b25ueC5UZW5zb3JQcm90by5TZWdtZW50fSBTZWdtZW50XG4gICAgICAgICAgICAgKiBAdGhyb3dzIHtFcnJvcn0gSWYgdGhlIHBheWxvYWQgaXMgbm90IGEgcmVhZGVyIG9yIHZhbGlkIGJ1ZmZlclxuICAgICAgICAgICAgICogQHRocm93cyB7JHByb3RvYnVmLnV0aWwuUHJvdG9jb2xFcnJvcn0gSWYgcmVxdWlyZWQgZmllbGRzIGFyZSBtaXNzaW5nXG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIFNlZ21lbnQuZGVjb2RlRGVsaW1pdGVkID0gZnVuY3Rpb24gZGVjb2RlRGVsaW1pdGVkKHJlYWRlcikge1xuICAgICAgICAgICAgICAgIGlmICghKHJlYWRlciBpbnN0YW5jZW9mICRSZWFkZXIpKVxuICAgICAgICAgICAgICAgICAgICByZWFkZXIgPSBuZXcgJFJlYWRlcihyZWFkZXIpO1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmRlY29kZShyZWFkZXIsIHJlYWRlci51aW50MzIoKSk7XG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICAvKipcbiAgICAgICAgICAgICAqIFZlcmlmaWVzIGEgU2VnbWVudCBtZXNzYWdlLlxuICAgICAgICAgICAgICogQGZ1bmN0aW9uIHZlcmlmeVxuICAgICAgICAgICAgICogQG1lbWJlcm9mIG9ubnguVGVuc29yUHJvdG8uU2VnbWVudFxuICAgICAgICAgICAgICogQHN0YXRpY1xuICAgICAgICAgICAgICogQHBhcmFtIHtPYmplY3QuPHN0cmluZywqPn0gbWVzc2FnZSBQbGFpbiBvYmplY3QgdG8gdmVyaWZ5XG4gICAgICAgICAgICAgKiBAcmV0dXJucyB7c3RyaW5nfG51bGx9IGBudWxsYCBpZiB2YWxpZCwgb3RoZXJ3aXNlIHRoZSByZWFzb24gd2h5IGl0IGlzIG5vdFxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBTZWdtZW50LnZlcmlmeSA9IGZ1bmN0aW9uIHZlcmlmeShtZXNzYWdlKSB7XG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBtZXNzYWdlICE9PSBcIm9iamVjdFwiIHx8IG1lc3NhZ2UgPT09IG51bGwpXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBcIm9iamVjdCBleHBlY3RlZFwiO1xuICAgICAgICAgICAgICAgIGlmIChtZXNzYWdlLmJlZ2luICE9IG51bGwgJiYgbWVzc2FnZS5oYXNPd25Qcm9wZXJ0eShcImJlZ2luXCIpKVxuICAgICAgICAgICAgICAgICAgICBpZiAoISR1dGlsLmlzSW50ZWdlcihtZXNzYWdlLmJlZ2luKSAmJiAhKG1lc3NhZ2UuYmVnaW4gJiYgJHV0aWwuaXNJbnRlZ2VyKG1lc3NhZ2UuYmVnaW4ubG93KSAmJiAkdXRpbC5pc0ludGVnZXIobWVzc2FnZS5iZWdpbi5oaWdoKSkpXG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gXCJiZWdpbjogaW50ZWdlcnxMb25nIGV4cGVjdGVkXCI7XG4gICAgICAgICAgICAgICAgaWYgKG1lc3NhZ2UuZW5kICE9IG51bGwgJiYgbWVzc2FnZS5oYXNPd25Qcm9wZXJ0eShcImVuZFwiKSlcbiAgICAgICAgICAgICAgICAgICAgaWYgKCEkdXRpbC5pc0ludGVnZXIobWVzc2FnZS5lbmQpICYmICEobWVzc2FnZS5lbmQgJiYgJHV0aWwuaXNJbnRlZ2VyKG1lc3NhZ2UuZW5kLmxvdykgJiYgJHV0aWwuaXNJbnRlZ2VyKG1lc3NhZ2UuZW5kLmhpZ2gpKSlcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBcImVuZDogaW50ZWdlcnxMb25nIGV4cGVjdGVkXCI7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICAvKipcbiAgICAgICAgICAgICAqIENyZWF0ZXMgYSBTZWdtZW50IG1lc3NhZ2UgZnJvbSBhIHBsYWluIG9iamVjdC4gQWxzbyBjb252ZXJ0cyB2YWx1ZXMgdG8gdGhlaXIgcmVzcGVjdGl2ZSBpbnRlcm5hbCB0eXBlcy5cbiAgICAgICAgICAgICAqIEBmdW5jdGlvbiBmcm9tT2JqZWN0XG4gICAgICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueC5UZW5zb3JQcm90by5TZWdtZW50XG4gICAgICAgICAgICAgKiBAc3RhdGljXG4gICAgICAgICAgICAgKiBAcGFyYW0ge09iamVjdC48c3RyaW5nLCo+fSBvYmplY3QgUGxhaW4gb2JqZWN0XG4gICAgICAgICAgICAgKiBAcmV0dXJucyB7b25ueC5UZW5zb3JQcm90by5TZWdtZW50fSBTZWdtZW50XG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIFNlZ21lbnQuZnJvbU9iamVjdCA9IGZ1bmN0aW9uIGZyb21PYmplY3Qob2JqZWN0KSB7XG4gICAgICAgICAgICAgICAgaWYgKG9iamVjdCBpbnN0YW5jZW9mICRyb290Lm9ubnguVGVuc29yUHJvdG8uU2VnbWVudClcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG9iamVjdDtcbiAgICAgICAgICAgICAgICB2YXIgbWVzc2FnZSA9IG5ldyAkcm9vdC5vbm54LlRlbnNvclByb3RvLlNlZ21lbnQoKTtcbiAgICAgICAgICAgICAgICBpZiAob2JqZWN0LmJlZ2luICE9IG51bGwpXG4gICAgICAgICAgICAgICAgICAgIGlmICgkdXRpbC5Mb25nKVxuICAgICAgICAgICAgICAgICAgICAgICAgKG1lc3NhZ2UuYmVnaW4gPSAkdXRpbC5Mb25nLmZyb21WYWx1ZShvYmplY3QuYmVnaW4pKS51bnNpZ25lZCA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICBlbHNlIGlmICh0eXBlb2Ygb2JqZWN0LmJlZ2luID09PSBcInN0cmluZ1wiKVxuICAgICAgICAgICAgICAgICAgICAgICAgbWVzc2FnZS5iZWdpbiA9IHBhcnNlSW50KG9iamVjdC5iZWdpbiwgMTApO1xuICAgICAgICAgICAgICAgICAgICBlbHNlIGlmICh0eXBlb2Ygb2JqZWN0LmJlZ2luID09PSBcIm51bWJlclwiKVxuICAgICAgICAgICAgICAgICAgICAgICAgbWVzc2FnZS5iZWdpbiA9IG9iamVjdC5iZWdpbjtcbiAgICAgICAgICAgICAgICAgICAgZWxzZSBpZiAodHlwZW9mIG9iamVjdC5iZWdpbiA9PT0gXCJvYmplY3RcIilcbiAgICAgICAgICAgICAgICAgICAgICAgIG1lc3NhZ2UuYmVnaW4gPSBuZXcgJHV0aWwuTG9uZ0JpdHMob2JqZWN0LmJlZ2luLmxvdyA+Pj4gMCwgb2JqZWN0LmJlZ2luLmhpZ2ggPj4+IDApLnRvTnVtYmVyKCk7XG4gICAgICAgICAgICAgICAgaWYgKG9iamVjdC5lbmQgIT0gbnVsbClcbiAgICAgICAgICAgICAgICAgICAgaWYgKCR1dGlsLkxvbmcpXG4gICAgICAgICAgICAgICAgICAgICAgICAobWVzc2FnZS5lbmQgPSAkdXRpbC5Mb25nLmZyb21WYWx1ZShvYmplY3QuZW5kKSkudW5zaWduZWQgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgZWxzZSBpZiAodHlwZW9mIG9iamVjdC5lbmQgPT09IFwic3RyaW5nXCIpXG4gICAgICAgICAgICAgICAgICAgICAgICBtZXNzYWdlLmVuZCA9IHBhcnNlSW50KG9iamVjdC5lbmQsIDEwKTtcbiAgICAgICAgICAgICAgICAgICAgZWxzZSBpZiAodHlwZW9mIG9iamVjdC5lbmQgPT09IFwibnVtYmVyXCIpXG4gICAgICAgICAgICAgICAgICAgICAgICBtZXNzYWdlLmVuZCA9IG9iamVjdC5lbmQ7XG4gICAgICAgICAgICAgICAgICAgIGVsc2UgaWYgKHR5cGVvZiBvYmplY3QuZW5kID09PSBcIm9iamVjdFwiKVxuICAgICAgICAgICAgICAgICAgICAgICAgbWVzc2FnZS5lbmQgPSBuZXcgJHV0aWwuTG9uZ0JpdHMob2JqZWN0LmVuZC5sb3cgPj4+IDAsIG9iamVjdC5lbmQuaGlnaCA+Pj4gMCkudG9OdW1iZXIoKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gbWVzc2FnZTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIC8qKlxuICAgICAgICAgICAgICogQ3JlYXRlcyBhIHBsYWluIG9iamVjdCBmcm9tIGEgU2VnbWVudCBtZXNzYWdlLiBBbHNvIGNvbnZlcnRzIHZhbHVlcyB0byBvdGhlciB0eXBlcyBpZiBzcGVjaWZpZWQuXG4gICAgICAgICAgICAgKiBAZnVuY3Rpb24gdG9PYmplY3RcbiAgICAgICAgICAgICAqIEBtZW1iZXJvZiBvbm54LlRlbnNvclByb3RvLlNlZ21lbnRcbiAgICAgICAgICAgICAqIEBzdGF0aWNcbiAgICAgICAgICAgICAqIEBwYXJhbSB7b25ueC5UZW5zb3JQcm90by5TZWdtZW50fSBtZXNzYWdlIFNlZ21lbnRcbiAgICAgICAgICAgICAqIEBwYXJhbSB7JHByb3RvYnVmLklDb252ZXJzaW9uT3B0aW9uc30gW29wdGlvbnNdIENvbnZlcnNpb24gb3B0aW9uc1xuICAgICAgICAgICAgICogQHJldHVybnMge09iamVjdC48c3RyaW5nLCo+fSBQbGFpbiBvYmplY3RcbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgU2VnbWVudC50b09iamVjdCA9IGZ1bmN0aW9uIHRvT2JqZWN0KG1lc3NhZ2UsIG9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICBpZiAoIW9wdGlvbnMpXG4gICAgICAgICAgICAgICAgICAgIG9wdGlvbnMgPSB7fTtcbiAgICAgICAgICAgICAgICB2YXIgb2JqZWN0ID0ge307XG4gICAgICAgICAgICAgICAgaWYgKG9wdGlvbnMuZGVmYXVsdHMpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCR1dGlsLkxvbmcpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBsb25nID0gbmV3ICR1dGlsLkxvbmcoMCwgMCwgZmFsc2UpO1xuICAgICAgICAgICAgICAgICAgICAgICAgb2JqZWN0LmJlZ2luID0gb3B0aW9ucy5sb25ncyA9PT0gU3RyaW5nID8gbG9uZy50b1N0cmluZygpIDogb3B0aW9ucy5sb25ncyA9PT0gTnVtYmVyID8gbG9uZy50b051bWJlcigpIDogbG9uZztcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlXG4gICAgICAgICAgICAgICAgICAgICAgICBvYmplY3QuYmVnaW4gPSBvcHRpb25zLmxvbmdzID09PSBTdHJpbmcgPyBcIjBcIiA6IDA7XG4gICAgICAgICAgICAgICAgICAgIGlmICgkdXRpbC5Mb25nKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgbG9uZyA9IG5ldyAkdXRpbC5Mb25nKDAsIDAsIGZhbHNlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIG9iamVjdC5lbmQgPSBvcHRpb25zLmxvbmdzID09PSBTdHJpbmcgPyBsb25nLnRvU3RyaW5nKCkgOiBvcHRpb25zLmxvbmdzID09PSBOdW1iZXIgPyBsb25nLnRvTnVtYmVyKCkgOiBsb25nO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2VcbiAgICAgICAgICAgICAgICAgICAgICAgIG9iamVjdC5lbmQgPSBvcHRpb25zLmxvbmdzID09PSBTdHJpbmcgPyBcIjBcIiA6IDA7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChtZXNzYWdlLmJlZ2luICE9IG51bGwgJiYgbWVzc2FnZS5oYXNPd25Qcm9wZXJ0eShcImJlZ2luXCIpKVxuICAgICAgICAgICAgICAgICAgICBpZiAodHlwZW9mIG1lc3NhZ2UuYmVnaW4gPT09IFwibnVtYmVyXCIpXG4gICAgICAgICAgICAgICAgICAgICAgICBvYmplY3QuYmVnaW4gPSBvcHRpb25zLmxvbmdzID09PSBTdHJpbmcgPyBTdHJpbmcobWVzc2FnZS5iZWdpbikgOiBtZXNzYWdlLmJlZ2luO1xuICAgICAgICAgICAgICAgICAgICBlbHNlXG4gICAgICAgICAgICAgICAgICAgICAgICBvYmplY3QuYmVnaW4gPSBvcHRpb25zLmxvbmdzID09PSBTdHJpbmcgPyAkdXRpbC5Mb25nLnByb3RvdHlwZS50b1N0cmluZy5jYWxsKG1lc3NhZ2UuYmVnaW4pIDogb3B0aW9ucy5sb25ncyA9PT0gTnVtYmVyID8gbmV3ICR1dGlsLkxvbmdCaXRzKG1lc3NhZ2UuYmVnaW4ubG93ID4+PiAwLCBtZXNzYWdlLmJlZ2luLmhpZ2ggPj4+IDApLnRvTnVtYmVyKCkgOiBtZXNzYWdlLmJlZ2luO1xuICAgICAgICAgICAgICAgIGlmIChtZXNzYWdlLmVuZCAhPSBudWxsICYmIG1lc3NhZ2UuaGFzT3duUHJvcGVydHkoXCJlbmRcIikpXG4gICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgbWVzc2FnZS5lbmQgPT09IFwibnVtYmVyXCIpXG4gICAgICAgICAgICAgICAgICAgICAgICBvYmplY3QuZW5kID0gb3B0aW9ucy5sb25ncyA9PT0gU3RyaW5nID8gU3RyaW5nKG1lc3NhZ2UuZW5kKSA6IG1lc3NhZ2UuZW5kO1xuICAgICAgICAgICAgICAgICAgICBlbHNlXG4gICAgICAgICAgICAgICAgICAgICAgICBvYmplY3QuZW5kID0gb3B0aW9ucy5sb25ncyA9PT0gU3RyaW5nID8gJHV0aWwuTG9uZy5wcm90b3R5cGUudG9TdHJpbmcuY2FsbChtZXNzYWdlLmVuZCkgOiBvcHRpb25zLmxvbmdzID09PSBOdW1iZXIgPyBuZXcgJHV0aWwuTG9uZ0JpdHMobWVzc2FnZS5lbmQubG93ID4+PiAwLCBtZXNzYWdlLmVuZC5oaWdoID4+PiAwKS50b051bWJlcigpIDogbWVzc2FnZS5lbmQ7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG9iamVjdDtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIC8qKlxuICAgICAgICAgICAgICogQ29udmVydHMgdGhpcyBTZWdtZW50IHRvIEpTT04uXG4gICAgICAgICAgICAgKiBAZnVuY3Rpb24gdG9KU09OXG4gICAgICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueC5UZW5zb3JQcm90by5TZWdtZW50XG4gICAgICAgICAgICAgKiBAaW5zdGFuY2VcbiAgICAgICAgICAgICAqIEByZXR1cm5zIHtPYmplY3QuPHN0cmluZywqPn0gSlNPTiBvYmplY3RcbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgU2VnbWVudC5wcm90b3R5cGUudG9KU09OID0gZnVuY3Rpb24gdG9KU09OKCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmNvbnN0cnVjdG9yLnRvT2JqZWN0KHRoaXMsICRwcm90b2J1Zi51dGlsLnRvSlNPTk9wdGlvbnMpO1xuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgcmV0dXJuIFNlZ21lbnQ7XG4gICAgICAgIH0pKCk7XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIERhdGFMb2NhdGlvbiBlbnVtLlxuICAgICAgICAgKiBAbmFtZSBvbm54LlRlbnNvclByb3RvLkRhdGFMb2NhdGlvblxuICAgICAgICAgKiBAZW51bSB7c3RyaW5nfVxuICAgICAgICAgKiBAcHJvcGVydHkge251bWJlcn0gREVGQVVMVD0wIERFRkFVTFQgdmFsdWVcbiAgICAgICAgICogQHByb3BlcnR5IHtudW1iZXJ9IEVYVEVSTkFMPTEgRVhURVJOQUwgdmFsdWVcbiAgICAgICAgICovXG4gICAgICAgIFRlbnNvclByb3RvLkRhdGFMb2NhdGlvbiA9IChmdW5jdGlvbigpIHtcbiAgICAgICAgICAgIHZhciB2YWx1ZXNCeUlkID0ge30sIHZhbHVlcyA9IE9iamVjdC5jcmVhdGUodmFsdWVzQnlJZCk7XG4gICAgICAgICAgICB2YWx1ZXNbdmFsdWVzQnlJZFswXSA9IFwiREVGQVVMVFwiXSA9IDA7XG4gICAgICAgICAgICB2YWx1ZXNbdmFsdWVzQnlJZFsxXSA9IFwiRVhURVJOQUxcIl0gPSAxO1xuICAgICAgICAgICAgcmV0dXJuIHZhbHVlcztcbiAgICAgICAgfSkoKTtcblxuICAgICAgICByZXR1cm4gVGVuc29yUHJvdG87XG4gICAgfSkoKTtcblxuICAgIG9ubnguVGVuc29yU2hhcGVQcm90byA9IChmdW5jdGlvbigpIHtcblxuICAgICAgICAvKipcbiAgICAgICAgICogUHJvcGVydGllcyBvZiBhIFRlbnNvclNoYXBlUHJvdG8uXG4gICAgICAgICAqIEBtZW1iZXJvZiBvbm54XG4gICAgICAgICAqIEBpbnRlcmZhY2UgSVRlbnNvclNoYXBlUHJvdG9cbiAgICAgICAgICogQHByb3BlcnR5IHtBcnJheS48b25ueC5UZW5zb3JTaGFwZVByb3RvLklEaW1lbnNpb24+fG51bGx9IFtkaW1dIFRlbnNvclNoYXBlUHJvdG8gZGltXG4gICAgICAgICAqL1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBDb25zdHJ1Y3RzIGEgbmV3IFRlbnNvclNoYXBlUHJvdG8uXG4gICAgICAgICAqIEBtZW1iZXJvZiBvbm54XG4gICAgICAgICAqIEBjbGFzc2Rlc2MgUmVwcmVzZW50cyBhIFRlbnNvclNoYXBlUHJvdG8uXG4gICAgICAgICAqIEBpbXBsZW1lbnRzIElUZW5zb3JTaGFwZVByb3RvXG4gICAgICAgICAqIEBjb25zdHJ1Y3RvclxuICAgICAgICAgKiBAcGFyYW0ge29ubnguSVRlbnNvclNoYXBlUHJvdG89fSBbcHJvcGVydGllc10gUHJvcGVydGllcyB0byBzZXRcbiAgICAgICAgICovXG4gICAgICAgIGZ1bmN0aW9uIFRlbnNvclNoYXBlUHJvdG8ocHJvcGVydGllcykge1xuICAgICAgICAgICAgdGhpcy5kaW0gPSBbXTtcbiAgICAgICAgICAgIGlmIChwcm9wZXJ0aWVzKVxuICAgICAgICAgICAgICAgIGZvciAodmFyIGtleXMgPSBPYmplY3Qua2V5cyhwcm9wZXJ0aWVzKSwgaSA9IDA7IGkgPCBrZXlzLmxlbmd0aDsgKytpKVxuICAgICAgICAgICAgICAgICAgICBpZiAocHJvcGVydGllc1trZXlzW2ldXSAhPSBudWxsKVxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpc1trZXlzW2ldXSA9IHByb3BlcnRpZXNba2V5c1tpXV07XG4gICAgICAgIH1cblxuICAgICAgICAvKipcbiAgICAgICAgICogVGVuc29yU2hhcGVQcm90byBkaW0uXG4gICAgICAgICAqIEBtZW1iZXIge0FycmF5Ljxvbm54LlRlbnNvclNoYXBlUHJvdG8uSURpbWVuc2lvbj59IGRpbVxuICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueC5UZW5zb3JTaGFwZVByb3RvXG4gICAgICAgICAqIEBpbnN0YW5jZVxuICAgICAgICAgKi9cbiAgICAgICAgVGVuc29yU2hhcGVQcm90by5wcm90b3R5cGUuZGltID0gJHV0aWwuZW1wdHlBcnJheTtcblxuICAgICAgICAvKipcbiAgICAgICAgICogQ3JlYXRlcyBhIG5ldyBUZW5zb3JTaGFwZVByb3RvIGluc3RhbmNlIHVzaW5nIHRoZSBzcGVjaWZpZWQgcHJvcGVydGllcy5cbiAgICAgICAgICogQGZ1bmN0aW9uIGNyZWF0ZVxuICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueC5UZW5zb3JTaGFwZVByb3RvXG4gICAgICAgICAqIEBzdGF0aWNcbiAgICAgICAgICogQHBhcmFtIHtvbm54LklUZW5zb3JTaGFwZVByb3RvPX0gW3Byb3BlcnRpZXNdIFByb3BlcnRpZXMgdG8gc2V0XG4gICAgICAgICAqIEByZXR1cm5zIHtvbm54LlRlbnNvclNoYXBlUHJvdG99IFRlbnNvclNoYXBlUHJvdG8gaW5zdGFuY2VcbiAgICAgICAgICovXG4gICAgICAgIFRlbnNvclNoYXBlUHJvdG8uY3JlYXRlID0gZnVuY3Rpb24gY3JlYXRlKHByb3BlcnRpZXMpIHtcbiAgICAgICAgICAgIHJldHVybiBuZXcgVGVuc29yU2hhcGVQcm90byhwcm9wZXJ0aWVzKTtcbiAgICAgICAgfTtcblxuICAgICAgICAvKipcbiAgICAgICAgICogRW5jb2RlcyB0aGUgc3BlY2lmaWVkIFRlbnNvclNoYXBlUHJvdG8gbWVzc2FnZS4gRG9lcyBub3QgaW1wbGljaXRseSB7QGxpbmsgb25ueC5UZW5zb3JTaGFwZVByb3RvLnZlcmlmeXx2ZXJpZnl9IG1lc3NhZ2VzLlxuICAgICAgICAgKiBAZnVuY3Rpb24gZW5jb2RlXG4gICAgICAgICAqIEBtZW1iZXJvZiBvbm54LlRlbnNvclNoYXBlUHJvdG9cbiAgICAgICAgICogQHN0YXRpY1xuICAgICAgICAgKiBAcGFyYW0ge29ubnguSVRlbnNvclNoYXBlUHJvdG99IG1lc3NhZ2UgVGVuc29yU2hhcGVQcm90byBtZXNzYWdlIG9yIHBsYWluIG9iamVjdCB0byBlbmNvZGVcbiAgICAgICAgICogQHBhcmFtIHskcHJvdG9idWYuV3JpdGVyfSBbd3JpdGVyXSBXcml0ZXIgdG8gZW5jb2RlIHRvXG4gICAgICAgICAqIEByZXR1cm5zIHskcHJvdG9idWYuV3JpdGVyfSBXcml0ZXJcbiAgICAgICAgICovXG4gICAgICAgIFRlbnNvclNoYXBlUHJvdG8uZW5jb2RlID0gZnVuY3Rpb24gZW5jb2RlKG1lc3NhZ2UsIHdyaXRlcikge1xuICAgICAgICAgICAgaWYgKCF3cml0ZXIpXG4gICAgICAgICAgICAgICAgd3JpdGVyID0gJFdyaXRlci5jcmVhdGUoKTtcbiAgICAgICAgICAgIGlmIChtZXNzYWdlLmRpbSAhPSBudWxsICYmIG1lc3NhZ2UuZGltLmxlbmd0aClcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG1lc3NhZ2UuZGltLmxlbmd0aDsgKytpKVxuICAgICAgICAgICAgICAgICAgICAkcm9vdC5vbm54LlRlbnNvclNoYXBlUHJvdG8uRGltZW5zaW9uLmVuY29kZShtZXNzYWdlLmRpbVtpXSwgd3JpdGVyLnVpbnQzMigvKiBpZCAxLCB3aXJlVHlwZSAyID0qLzEwKS5mb3JrKCkpLmxkZWxpbSgpO1xuICAgICAgICAgICAgcmV0dXJuIHdyaXRlcjtcbiAgICAgICAgfTtcblxuICAgICAgICAvKipcbiAgICAgICAgICogRW5jb2RlcyB0aGUgc3BlY2lmaWVkIFRlbnNvclNoYXBlUHJvdG8gbWVzc2FnZSwgbGVuZ3RoIGRlbGltaXRlZC4gRG9lcyBub3QgaW1wbGljaXRseSB7QGxpbmsgb25ueC5UZW5zb3JTaGFwZVByb3RvLnZlcmlmeXx2ZXJpZnl9IG1lc3NhZ2VzLlxuICAgICAgICAgKiBAZnVuY3Rpb24gZW5jb2RlRGVsaW1pdGVkXG4gICAgICAgICAqIEBtZW1iZXJvZiBvbm54LlRlbnNvclNoYXBlUHJvdG9cbiAgICAgICAgICogQHN0YXRpY1xuICAgICAgICAgKiBAcGFyYW0ge29ubnguSVRlbnNvclNoYXBlUHJvdG99IG1lc3NhZ2UgVGVuc29yU2hhcGVQcm90byBtZXNzYWdlIG9yIHBsYWluIG9iamVjdCB0byBlbmNvZGVcbiAgICAgICAgICogQHBhcmFtIHskcHJvdG9idWYuV3JpdGVyfSBbd3JpdGVyXSBXcml0ZXIgdG8gZW5jb2RlIHRvXG4gICAgICAgICAqIEByZXR1cm5zIHskcHJvdG9idWYuV3JpdGVyfSBXcml0ZXJcbiAgICAgICAgICovXG4gICAgICAgIFRlbnNvclNoYXBlUHJvdG8uZW5jb2RlRGVsaW1pdGVkID0gZnVuY3Rpb24gZW5jb2RlRGVsaW1pdGVkKG1lc3NhZ2UsIHdyaXRlcikge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuZW5jb2RlKG1lc3NhZ2UsIHdyaXRlcikubGRlbGltKCk7XG4gICAgICAgIH07XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIERlY29kZXMgYSBUZW5zb3JTaGFwZVByb3RvIG1lc3NhZ2UgZnJvbSB0aGUgc3BlY2lmaWVkIHJlYWRlciBvciBidWZmZXIuXG4gICAgICAgICAqIEBmdW5jdGlvbiBkZWNvZGVcbiAgICAgICAgICogQG1lbWJlcm9mIG9ubnguVGVuc29yU2hhcGVQcm90b1xuICAgICAgICAgKiBAc3RhdGljXG4gICAgICAgICAqIEBwYXJhbSB7JHByb3RvYnVmLlJlYWRlcnxVaW50OEFycmF5fSByZWFkZXIgUmVhZGVyIG9yIGJ1ZmZlciB0byBkZWNvZGUgZnJvbVxuICAgICAgICAgKiBAcGFyYW0ge251bWJlcn0gW2xlbmd0aF0gTWVzc2FnZSBsZW5ndGggaWYga25vd24gYmVmb3JlaGFuZFxuICAgICAgICAgKiBAcmV0dXJucyB7b25ueC5UZW5zb3JTaGFwZVByb3RvfSBUZW5zb3JTaGFwZVByb3RvXG4gICAgICAgICAqIEB0aHJvd3Mge0Vycm9yfSBJZiB0aGUgcGF5bG9hZCBpcyBub3QgYSByZWFkZXIgb3IgdmFsaWQgYnVmZmVyXG4gICAgICAgICAqIEB0aHJvd3MgeyRwcm90b2J1Zi51dGlsLlByb3RvY29sRXJyb3J9IElmIHJlcXVpcmVkIGZpZWxkcyBhcmUgbWlzc2luZ1xuICAgICAgICAgKi9cbiAgICAgICAgVGVuc29yU2hhcGVQcm90by5kZWNvZGUgPSBmdW5jdGlvbiBkZWNvZGUocmVhZGVyLCBsZW5ndGgpIHtcbiAgICAgICAgICAgIGlmICghKHJlYWRlciBpbnN0YW5jZW9mICRSZWFkZXIpKVxuICAgICAgICAgICAgICAgIHJlYWRlciA9ICRSZWFkZXIuY3JlYXRlKHJlYWRlcik7XG4gICAgICAgICAgICB2YXIgZW5kID0gbGVuZ3RoID09PSB1bmRlZmluZWQgPyByZWFkZXIubGVuIDogcmVhZGVyLnBvcyArIGxlbmd0aCwgbWVzc2FnZSA9IG5ldyAkcm9vdC5vbm54LlRlbnNvclNoYXBlUHJvdG8oKTtcbiAgICAgICAgICAgIHdoaWxlIChyZWFkZXIucG9zIDwgZW5kKSB7XG4gICAgICAgICAgICAgICAgdmFyIHRhZyA9IHJlYWRlci51aW50MzIoKTtcbiAgICAgICAgICAgICAgICBzd2l0Y2ggKHRhZyA+Pj4gMykge1xuICAgICAgICAgICAgICAgIGNhc2UgMTpcbiAgICAgICAgICAgICAgICAgICAgaWYgKCEobWVzc2FnZS5kaW0gJiYgbWVzc2FnZS5kaW0ubGVuZ3RoKSlcbiAgICAgICAgICAgICAgICAgICAgICAgIG1lc3NhZ2UuZGltID0gW107XG4gICAgICAgICAgICAgICAgICAgIG1lc3NhZ2UuZGltLnB1c2goJHJvb3Qub25ueC5UZW5zb3JTaGFwZVByb3RvLkRpbWVuc2lvbi5kZWNvZGUocmVhZGVyLCByZWFkZXIudWludDMyKCkpKTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICAgICAgcmVhZGVyLnNraXBUeXBlKHRhZyAmIDcpO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gbWVzc2FnZTtcbiAgICAgICAgfTtcblxuICAgICAgICAvKipcbiAgICAgICAgICogRGVjb2RlcyBhIFRlbnNvclNoYXBlUHJvdG8gbWVzc2FnZSBmcm9tIHRoZSBzcGVjaWZpZWQgcmVhZGVyIG9yIGJ1ZmZlciwgbGVuZ3RoIGRlbGltaXRlZC5cbiAgICAgICAgICogQGZ1bmN0aW9uIGRlY29kZURlbGltaXRlZFxuICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueC5UZW5zb3JTaGFwZVByb3RvXG4gICAgICAgICAqIEBzdGF0aWNcbiAgICAgICAgICogQHBhcmFtIHskcHJvdG9idWYuUmVhZGVyfFVpbnQ4QXJyYXl9IHJlYWRlciBSZWFkZXIgb3IgYnVmZmVyIHRvIGRlY29kZSBmcm9tXG4gICAgICAgICAqIEByZXR1cm5zIHtvbm54LlRlbnNvclNoYXBlUHJvdG99IFRlbnNvclNoYXBlUHJvdG9cbiAgICAgICAgICogQHRocm93cyB7RXJyb3J9IElmIHRoZSBwYXlsb2FkIGlzIG5vdCBhIHJlYWRlciBvciB2YWxpZCBidWZmZXJcbiAgICAgICAgICogQHRocm93cyB7JHByb3RvYnVmLnV0aWwuUHJvdG9jb2xFcnJvcn0gSWYgcmVxdWlyZWQgZmllbGRzIGFyZSBtaXNzaW5nXG4gICAgICAgICAqL1xuICAgICAgICBUZW5zb3JTaGFwZVByb3RvLmRlY29kZURlbGltaXRlZCA9IGZ1bmN0aW9uIGRlY29kZURlbGltaXRlZChyZWFkZXIpIHtcbiAgICAgICAgICAgIGlmICghKHJlYWRlciBpbnN0YW5jZW9mICRSZWFkZXIpKVxuICAgICAgICAgICAgICAgIHJlYWRlciA9IG5ldyAkUmVhZGVyKHJlYWRlcik7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5kZWNvZGUocmVhZGVyLCByZWFkZXIudWludDMyKCkpO1xuICAgICAgICB9O1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBWZXJpZmllcyBhIFRlbnNvclNoYXBlUHJvdG8gbWVzc2FnZS5cbiAgICAgICAgICogQGZ1bmN0aW9uIHZlcmlmeVxuICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueC5UZW5zb3JTaGFwZVByb3RvXG4gICAgICAgICAqIEBzdGF0aWNcbiAgICAgICAgICogQHBhcmFtIHtPYmplY3QuPHN0cmluZywqPn0gbWVzc2FnZSBQbGFpbiBvYmplY3QgdG8gdmVyaWZ5XG4gICAgICAgICAqIEByZXR1cm5zIHtzdHJpbmd8bnVsbH0gYG51bGxgIGlmIHZhbGlkLCBvdGhlcndpc2UgdGhlIHJlYXNvbiB3aHkgaXQgaXMgbm90XG4gICAgICAgICAqL1xuICAgICAgICBUZW5zb3JTaGFwZVByb3RvLnZlcmlmeSA9IGZ1bmN0aW9uIHZlcmlmeShtZXNzYWdlKSB7XG4gICAgICAgICAgICBpZiAodHlwZW9mIG1lc3NhZ2UgIT09IFwib2JqZWN0XCIgfHwgbWVzc2FnZSA9PT0gbnVsbClcbiAgICAgICAgICAgICAgICByZXR1cm4gXCJvYmplY3QgZXhwZWN0ZWRcIjtcbiAgICAgICAgICAgIGlmIChtZXNzYWdlLmRpbSAhPSBudWxsICYmIG1lc3NhZ2UuaGFzT3duUHJvcGVydHkoXCJkaW1cIikpIHtcbiAgICAgICAgICAgICAgICBpZiAoIUFycmF5LmlzQXJyYXkobWVzc2FnZS5kaW0pKVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gXCJkaW06IGFycmF5IGV4cGVjdGVkXCI7XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBtZXNzYWdlLmRpbS5sZW5ndGg7ICsraSkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgZXJyb3IgPSAkcm9vdC5vbm54LlRlbnNvclNoYXBlUHJvdG8uRGltZW5zaW9uLnZlcmlmeShtZXNzYWdlLmRpbVtpXSk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChlcnJvcilcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBcImRpbS5cIiArIGVycm9yO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9O1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBDcmVhdGVzIGEgVGVuc29yU2hhcGVQcm90byBtZXNzYWdlIGZyb20gYSBwbGFpbiBvYmplY3QuIEFsc28gY29udmVydHMgdmFsdWVzIHRvIHRoZWlyIHJlc3BlY3RpdmUgaW50ZXJuYWwgdHlwZXMuXG4gICAgICAgICAqIEBmdW5jdGlvbiBmcm9tT2JqZWN0XG4gICAgICAgICAqIEBtZW1iZXJvZiBvbm54LlRlbnNvclNoYXBlUHJvdG9cbiAgICAgICAgICogQHN0YXRpY1xuICAgICAgICAgKiBAcGFyYW0ge09iamVjdC48c3RyaW5nLCo+fSBvYmplY3QgUGxhaW4gb2JqZWN0XG4gICAgICAgICAqIEByZXR1cm5zIHtvbm54LlRlbnNvclNoYXBlUHJvdG99IFRlbnNvclNoYXBlUHJvdG9cbiAgICAgICAgICovXG4gICAgICAgIFRlbnNvclNoYXBlUHJvdG8uZnJvbU9iamVjdCA9IGZ1bmN0aW9uIGZyb21PYmplY3Qob2JqZWN0KSB7XG4gICAgICAgICAgICBpZiAob2JqZWN0IGluc3RhbmNlb2YgJHJvb3Qub25ueC5UZW5zb3JTaGFwZVByb3RvKVxuICAgICAgICAgICAgICAgIHJldHVybiBvYmplY3Q7XG4gICAgICAgICAgICB2YXIgbWVzc2FnZSA9IG5ldyAkcm9vdC5vbm54LlRlbnNvclNoYXBlUHJvdG8oKTtcbiAgICAgICAgICAgIGlmIChvYmplY3QuZGltKSB7XG4gICAgICAgICAgICAgICAgaWYgKCFBcnJheS5pc0FycmF5KG9iamVjdC5kaW0pKVxuICAgICAgICAgICAgICAgICAgICB0aHJvdyBUeXBlRXJyb3IoXCIub25ueC5UZW5zb3JTaGFwZVByb3RvLmRpbTogYXJyYXkgZXhwZWN0ZWRcIik7XG4gICAgICAgICAgICAgICAgbWVzc2FnZS5kaW0gPSBbXTtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG9iamVjdC5kaW0ubGVuZ3RoOyArK2kpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBvYmplY3QuZGltW2ldICE9PSBcIm9iamVjdFwiKVxuICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3cgVHlwZUVycm9yKFwiLm9ubnguVGVuc29yU2hhcGVQcm90by5kaW06IG9iamVjdCBleHBlY3RlZFwiKTtcbiAgICAgICAgICAgICAgICAgICAgbWVzc2FnZS5kaW1baV0gPSAkcm9vdC5vbm54LlRlbnNvclNoYXBlUHJvdG8uRGltZW5zaW9uLmZyb21PYmplY3Qob2JqZWN0LmRpbVtpXSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIG1lc3NhZ2U7XG4gICAgICAgIH07XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIENyZWF0ZXMgYSBwbGFpbiBvYmplY3QgZnJvbSBhIFRlbnNvclNoYXBlUHJvdG8gbWVzc2FnZS4gQWxzbyBjb252ZXJ0cyB2YWx1ZXMgdG8gb3RoZXIgdHlwZXMgaWYgc3BlY2lmaWVkLlxuICAgICAgICAgKiBAZnVuY3Rpb24gdG9PYmplY3RcbiAgICAgICAgICogQG1lbWJlcm9mIG9ubnguVGVuc29yU2hhcGVQcm90b1xuICAgICAgICAgKiBAc3RhdGljXG4gICAgICAgICAqIEBwYXJhbSB7b25ueC5UZW5zb3JTaGFwZVByb3RvfSBtZXNzYWdlIFRlbnNvclNoYXBlUHJvdG9cbiAgICAgICAgICogQHBhcmFtIHskcHJvdG9idWYuSUNvbnZlcnNpb25PcHRpb25zfSBbb3B0aW9uc10gQ29udmVyc2lvbiBvcHRpb25zXG4gICAgICAgICAqIEByZXR1cm5zIHtPYmplY3QuPHN0cmluZywqPn0gUGxhaW4gb2JqZWN0XG4gICAgICAgICAqL1xuICAgICAgICBUZW5zb3JTaGFwZVByb3RvLnRvT2JqZWN0ID0gZnVuY3Rpb24gdG9PYmplY3QobWVzc2FnZSwgb3B0aW9ucykge1xuICAgICAgICAgICAgaWYgKCFvcHRpb25zKVxuICAgICAgICAgICAgICAgIG9wdGlvbnMgPSB7fTtcbiAgICAgICAgICAgIHZhciBvYmplY3QgPSB7fTtcbiAgICAgICAgICAgIGlmIChvcHRpb25zLmFycmF5cyB8fCBvcHRpb25zLmRlZmF1bHRzKVxuICAgICAgICAgICAgICAgIG9iamVjdC5kaW0gPSBbXTtcbiAgICAgICAgICAgIGlmIChtZXNzYWdlLmRpbSAmJiBtZXNzYWdlLmRpbS5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICBvYmplY3QuZGltID0gW107XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaiA9IDA7IGogPCBtZXNzYWdlLmRpbS5sZW5ndGg7ICsrailcbiAgICAgICAgICAgICAgICAgICAgb2JqZWN0LmRpbVtqXSA9ICRyb290Lm9ubnguVGVuc29yU2hhcGVQcm90by5EaW1lbnNpb24udG9PYmplY3QobWVzc2FnZS5kaW1bal0sIG9wdGlvbnMpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIG9iamVjdDtcbiAgICAgICAgfTtcblxuICAgICAgICAvKipcbiAgICAgICAgICogQ29udmVydHMgdGhpcyBUZW5zb3JTaGFwZVByb3RvIHRvIEpTT04uXG4gICAgICAgICAqIEBmdW5jdGlvbiB0b0pTT05cbiAgICAgICAgICogQG1lbWJlcm9mIG9ubnguVGVuc29yU2hhcGVQcm90b1xuICAgICAgICAgKiBAaW5zdGFuY2VcbiAgICAgICAgICogQHJldHVybnMge09iamVjdC48c3RyaW5nLCo+fSBKU09OIG9iamVjdFxuICAgICAgICAgKi9cbiAgICAgICAgVGVuc29yU2hhcGVQcm90by5wcm90b3R5cGUudG9KU09OID0gZnVuY3Rpb24gdG9KU09OKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuY29uc3RydWN0b3IudG9PYmplY3QodGhpcywgJHByb3RvYnVmLnV0aWwudG9KU09OT3B0aW9ucyk7XG4gICAgICAgIH07XG5cbiAgICAgICAgVGVuc29yU2hhcGVQcm90by5EaW1lbnNpb24gPSAoZnVuY3Rpb24oKSB7XG5cbiAgICAgICAgICAgIC8qKlxuICAgICAgICAgICAgICogUHJvcGVydGllcyBvZiBhIERpbWVuc2lvbi5cbiAgICAgICAgICAgICAqIEBtZW1iZXJvZiBvbm54LlRlbnNvclNoYXBlUHJvdG9cbiAgICAgICAgICAgICAqIEBpbnRlcmZhY2UgSURpbWVuc2lvblxuICAgICAgICAgICAgICogQHByb3BlcnR5IHtudW1iZXJ8TG9uZ3xudWxsfSBbZGltVmFsdWVdIERpbWVuc2lvbiBkaW1WYWx1ZVxuICAgICAgICAgICAgICogQHByb3BlcnR5IHtzdHJpbmd8bnVsbH0gW2RpbVBhcmFtXSBEaW1lbnNpb24gZGltUGFyYW1cbiAgICAgICAgICAgICAqIEBwcm9wZXJ0eSB7c3RyaW5nfG51bGx9IFtkZW5vdGF0aW9uXSBEaW1lbnNpb24gZGVub3RhdGlvblxuICAgICAgICAgICAgICovXG5cbiAgICAgICAgICAgIC8qKlxuICAgICAgICAgICAgICogQ29uc3RydWN0cyBhIG5ldyBEaW1lbnNpb24uXG4gICAgICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueC5UZW5zb3JTaGFwZVByb3RvXG4gICAgICAgICAgICAgKiBAY2xhc3NkZXNjIFJlcHJlc2VudHMgYSBEaW1lbnNpb24uXG4gICAgICAgICAgICAgKiBAaW1wbGVtZW50cyBJRGltZW5zaW9uXG4gICAgICAgICAgICAgKiBAY29uc3RydWN0b3JcbiAgICAgICAgICAgICAqIEBwYXJhbSB7b25ueC5UZW5zb3JTaGFwZVByb3RvLklEaW1lbnNpb249fSBbcHJvcGVydGllc10gUHJvcGVydGllcyB0byBzZXRcbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgZnVuY3Rpb24gRGltZW5zaW9uKHByb3BlcnRpZXMpIHtcbiAgICAgICAgICAgICAgICBpZiAocHJvcGVydGllcylcbiAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIga2V5cyA9IE9iamVjdC5rZXlzKHByb3BlcnRpZXMpLCBpID0gMDsgaSA8IGtleXMubGVuZ3RoOyArK2kpXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAocHJvcGVydGllc1trZXlzW2ldXSAhPSBudWxsKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXNba2V5c1tpXV0gPSBwcm9wZXJ0aWVzW2tleXNbaV1dO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvKipcbiAgICAgICAgICAgICAqIERpbWVuc2lvbiBkaW1WYWx1ZS5cbiAgICAgICAgICAgICAqIEBtZW1iZXIge251bWJlcnxMb25nfSBkaW1WYWx1ZVxuICAgICAgICAgICAgICogQG1lbWJlcm9mIG9ubnguVGVuc29yU2hhcGVQcm90by5EaW1lbnNpb25cbiAgICAgICAgICAgICAqIEBpbnN0YW5jZVxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBEaW1lbnNpb24ucHJvdG90eXBlLmRpbVZhbHVlID0gJHV0aWwuTG9uZyA/ICR1dGlsLkxvbmcuZnJvbUJpdHMoMCwwLGZhbHNlKSA6IDA7XG5cbiAgICAgICAgICAgIC8qKlxuICAgICAgICAgICAgICogRGltZW5zaW9uIGRpbVBhcmFtLlxuICAgICAgICAgICAgICogQG1lbWJlciB7c3RyaW5nfSBkaW1QYXJhbVxuICAgICAgICAgICAgICogQG1lbWJlcm9mIG9ubnguVGVuc29yU2hhcGVQcm90by5EaW1lbnNpb25cbiAgICAgICAgICAgICAqIEBpbnN0YW5jZVxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBEaW1lbnNpb24ucHJvdG90eXBlLmRpbVBhcmFtID0gXCJcIjtcblxuICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgKiBEaW1lbnNpb24gZGVub3RhdGlvbi5cbiAgICAgICAgICAgICAqIEBtZW1iZXIge3N0cmluZ30gZGVub3RhdGlvblxuICAgICAgICAgICAgICogQG1lbWJlcm9mIG9ubnguVGVuc29yU2hhcGVQcm90by5EaW1lbnNpb25cbiAgICAgICAgICAgICAqIEBpbnN0YW5jZVxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBEaW1lbnNpb24ucHJvdG90eXBlLmRlbm90YXRpb24gPSBcIlwiO1xuXG4gICAgICAgICAgICAvLyBPbmVPZiBmaWVsZCBuYW1lcyBib3VuZCB0byB2aXJ0dWFsIGdldHRlcnMgYW5kIHNldHRlcnNcbiAgICAgICAgICAgIHZhciAkb25lT2ZGaWVsZHM7XG5cbiAgICAgICAgICAgIC8qKlxuICAgICAgICAgICAgICogRGltZW5zaW9uIHZhbHVlLlxuICAgICAgICAgICAgICogQG1lbWJlciB7XCJkaW1WYWx1ZVwifFwiZGltUGFyYW1cInx1bmRlZmluZWR9IHZhbHVlXG4gICAgICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueC5UZW5zb3JTaGFwZVByb3RvLkRpbWVuc2lvblxuICAgICAgICAgICAgICogQGluc3RhbmNlXG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShEaW1lbnNpb24ucHJvdG90eXBlLCBcInZhbHVlXCIsIHtcbiAgICAgICAgICAgICAgICBnZXQ6ICR1dGlsLm9uZU9mR2V0dGVyKCRvbmVPZkZpZWxkcyA9IFtcImRpbVZhbHVlXCIsIFwiZGltUGFyYW1cIl0pLFxuICAgICAgICAgICAgICAgIHNldDogJHV0aWwub25lT2ZTZXR0ZXIoJG9uZU9mRmllbGRzKVxuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgIC8qKlxuICAgICAgICAgICAgICogQ3JlYXRlcyBhIG5ldyBEaW1lbnNpb24gaW5zdGFuY2UgdXNpbmcgdGhlIHNwZWNpZmllZCBwcm9wZXJ0aWVzLlxuICAgICAgICAgICAgICogQGZ1bmN0aW9uIGNyZWF0ZVxuICAgICAgICAgICAgICogQG1lbWJlcm9mIG9ubnguVGVuc29yU2hhcGVQcm90by5EaW1lbnNpb25cbiAgICAgICAgICAgICAqIEBzdGF0aWNcbiAgICAgICAgICAgICAqIEBwYXJhbSB7b25ueC5UZW5zb3JTaGFwZVByb3RvLklEaW1lbnNpb249fSBbcHJvcGVydGllc10gUHJvcGVydGllcyB0byBzZXRcbiAgICAgICAgICAgICAqIEByZXR1cm5zIHtvbm54LlRlbnNvclNoYXBlUHJvdG8uRGltZW5zaW9ufSBEaW1lbnNpb24gaW5zdGFuY2VcbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgRGltZW5zaW9uLmNyZWF0ZSA9IGZ1bmN0aW9uIGNyZWF0ZShwcm9wZXJ0aWVzKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBEaW1lbnNpb24ocHJvcGVydGllcyk7XG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICAvKipcbiAgICAgICAgICAgICAqIEVuY29kZXMgdGhlIHNwZWNpZmllZCBEaW1lbnNpb24gbWVzc2FnZS4gRG9lcyBub3QgaW1wbGljaXRseSB7QGxpbmsgb25ueC5UZW5zb3JTaGFwZVByb3RvLkRpbWVuc2lvbi52ZXJpZnl8dmVyaWZ5fSBtZXNzYWdlcy5cbiAgICAgICAgICAgICAqIEBmdW5jdGlvbiBlbmNvZGVcbiAgICAgICAgICAgICAqIEBtZW1iZXJvZiBvbm54LlRlbnNvclNoYXBlUHJvdG8uRGltZW5zaW9uXG4gICAgICAgICAgICAgKiBAc3RhdGljXG4gICAgICAgICAgICAgKiBAcGFyYW0ge29ubnguVGVuc29yU2hhcGVQcm90by5JRGltZW5zaW9ufSBtZXNzYWdlIERpbWVuc2lvbiBtZXNzYWdlIG9yIHBsYWluIG9iamVjdCB0byBlbmNvZGVcbiAgICAgICAgICAgICAqIEBwYXJhbSB7JHByb3RvYnVmLldyaXRlcn0gW3dyaXRlcl0gV3JpdGVyIHRvIGVuY29kZSB0b1xuICAgICAgICAgICAgICogQHJldHVybnMgeyRwcm90b2J1Zi5Xcml0ZXJ9IFdyaXRlclxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBEaW1lbnNpb24uZW5jb2RlID0gZnVuY3Rpb24gZW5jb2RlKG1lc3NhZ2UsIHdyaXRlcikge1xuICAgICAgICAgICAgICAgIGlmICghd3JpdGVyKVxuICAgICAgICAgICAgICAgICAgICB3cml0ZXIgPSAkV3JpdGVyLmNyZWF0ZSgpO1xuICAgICAgICAgICAgICAgIGlmIChtZXNzYWdlLmRpbVZhbHVlICE9IG51bGwgJiYgbWVzc2FnZS5oYXNPd25Qcm9wZXJ0eShcImRpbVZhbHVlXCIpKVxuICAgICAgICAgICAgICAgICAgICB3cml0ZXIudWludDMyKC8qIGlkIDEsIHdpcmVUeXBlIDAgPSovOCkuaW50NjQobWVzc2FnZS5kaW1WYWx1ZSk7XG4gICAgICAgICAgICAgICAgaWYgKG1lc3NhZ2UuZGltUGFyYW0gIT0gbnVsbCAmJiBtZXNzYWdlLmhhc093blByb3BlcnR5KFwiZGltUGFyYW1cIikpXG4gICAgICAgICAgICAgICAgICAgIHdyaXRlci51aW50MzIoLyogaWQgMiwgd2lyZVR5cGUgMiA9Ki8xOCkuc3RyaW5nKG1lc3NhZ2UuZGltUGFyYW0pO1xuICAgICAgICAgICAgICAgIGlmIChtZXNzYWdlLmRlbm90YXRpb24gIT0gbnVsbCAmJiBtZXNzYWdlLmhhc093blByb3BlcnR5KFwiZGVub3RhdGlvblwiKSlcbiAgICAgICAgICAgICAgICAgICAgd3JpdGVyLnVpbnQzMigvKiBpZCAzLCB3aXJlVHlwZSAyID0qLzI2KS5zdHJpbmcobWVzc2FnZS5kZW5vdGF0aW9uKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gd3JpdGVyO1xuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgKiBFbmNvZGVzIHRoZSBzcGVjaWZpZWQgRGltZW5zaW9uIG1lc3NhZ2UsIGxlbmd0aCBkZWxpbWl0ZWQuIERvZXMgbm90IGltcGxpY2l0bHkge0BsaW5rIG9ubnguVGVuc29yU2hhcGVQcm90by5EaW1lbnNpb24udmVyaWZ5fHZlcmlmeX0gbWVzc2FnZXMuXG4gICAgICAgICAgICAgKiBAZnVuY3Rpb24gZW5jb2RlRGVsaW1pdGVkXG4gICAgICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueC5UZW5zb3JTaGFwZVByb3RvLkRpbWVuc2lvblxuICAgICAgICAgICAgICogQHN0YXRpY1xuICAgICAgICAgICAgICogQHBhcmFtIHtvbm54LlRlbnNvclNoYXBlUHJvdG8uSURpbWVuc2lvbn0gbWVzc2FnZSBEaW1lbnNpb24gbWVzc2FnZSBvciBwbGFpbiBvYmplY3QgdG8gZW5jb2RlXG4gICAgICAgICAgICAgKiBAcGFyYW0geyRwcm90b2J1Zi5Xcml0ZXJ9IFt3cml0ZXJdIFdyaXRlciB0byBlbmNvZGUgdG9cbiAgICAgICAgICAgICAqIEByZXR1cm5zIHskcHJvdG9idWYuV3JpdGVyfSBXcml0ZXJcbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgRGltZW5zaW9uLmVuY29kZURlbGltaXRlZCA9IGZ1bmN0aW9uIGVuY29kZURlbGltaXRlZChtZXNzYWdlLCB3cml0ZXIpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5lbmNvZGUobWVzc2FnZSwgd3JpdGVyKS5sZGVsaW0oKTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIC8qKlxuICAgICAgICAgICAgICogRGVjb2RlcyBhIERpbWVuc2lvbiBtZXNzYWdlIGZyb20gdGhlIHNwZWNpZmllZCByZWFkZXIgb3IgYnVmZmVyLlxuICAgICAgICAgICAgICogQGZ1bmN0aW9uIGRlY29kZVxuICAgICAgICAgICAgICogQG1lbWJlcm9mIG9ubnguVGVuc29yU2hhcGVQcm90by5EaW1lbnNpb25cbiAgICAgICAgICAgICAqIEBzdGF0aWNcbiAgICAgICAgICAgICAqIEBwYXJhbSB7JHByb3RvYnVmLlJlYWRlcnxVaW50OEFycmF5fSByZWFkZXIgUmVhZGVyIG9yIGJ1ZmZlciB0byBkZWNvZGUgZnJvbVxuICAgICAgICAgICAgICogQHBhcmFtIHtudW1iZXJ9IFtsZW5ndGhdIE1lc3NhZ2UgbGVuZ3RoIGlmIGtub3duIGJlZm9yZWhhbmRcbiAgICAgICAgICAgICAqIEByZXR1cm5zIHtvbm54LlRlbnNvclNoYXBlUHJvdG8uRGltZW5zaW9ufSBEaW1lbnNpb25cbiAgICAgICAgICAgICAqIEB0aHJvd3Mge0Vycm9yfSBJZiB0aGUgcGF5bG9hZCBpcyBub3QgYSByZWFkZXIgb3IgdmFsaWQgYnVmZmVyXG4gICAgICAgICAgICAgKiBAdGhyb3dzIHskcHJvdG9idWYudXRpbC5Qcm90b2NvbEVycm9yfSBJZiByZXF1aXJlZCBmaWVsZHMgYXJlIG1pc3NpbmdcbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgRGltZW5zaW9uLmRlY29kZSA9IGZ1bmN0aW9uIGRlY29kZShyZWFkZXIsIGxlbmd0aCkge1xuICAgICAgICAgICAgICAgIGlmICghKHJlYWRlciBpbnN0YW5jZW9mICRSZWFkZXIpKVxuICAgICAgICAgICAgICAgICAgICByZWFkZXIgPSAkUmVhZGVyLmNyZWF0ZShyZWFkZXIpO1xuICAgICAgICAgICAgICAgIHZhciBlbmQgPSBsZW5ndGggPT09IHVuZGVmaW5lZCA/IHJlYWRlci5sZW4gOiByZWFkZXIucG9zICsgbGVuZ3RoLCBtZXNzYWdlID0gbmV3ICRyb290Lm9ubnguVGVuc29yU2hhcGVQcm90by5EaW1lbnNpb24oKTtcbiAgICAgICAgICAgICAgICB3aGlsZSAocmVhZGVyLnBvcyA8IGVuZCkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgdGFnID0gcmVhZGVyLnVpbnQzMigpO1xuICAgICAgICAgICAgICAgICAgICBzd2l0Y2ggKHRhZyA+Pj4gMykge1xuICAgICAgICAgICAgICAgICAgICBjYXNlIDE6XG4gICAgICAgICAgICAgICAgICAgICAgICBtZXNzYWdlLmRpbVZhbHVlID0gcmVhZGVyLmludDY0KCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAyOlxuICAgICAgICAgICAgICAgICAgICAgICAgbWVzc2FnZS5kaW1QYXJhbSA9IHJlYWRlci5zdHJpbmcoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIDM6XG4gICAgICAgICAgICAgICAgICAgICAgICBtZXNzYWdlLmRlbm90YXRpb24gPSByZWFkZXIuc3RyaW5nKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlYWRlci5za2lwVHlwZSh0YWcgJiA3KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiBtZXNzYWdlO1xuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgKiBEZWNvZGVzIGEgRGltZW5zaW9uIG1lc3NhZ2UgZnJvbSB0aGUgc3BlY2lmaWVkIHJlYWRlciBvciBidWZmZXIsIGxlbmd0aCBkZWxpbWl0ZWQuXG4gICAgICAgICAgICAgKiBAZnVuY3Rpb24gZGVjb2RlRGVsaW1pdGVkXG4gICAgICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueC5UZW5zb3JTaGFwZVByb3RvLkRpbWVuc2lvblxuICAgICAgICAgICAgICogQHN0YXRpY1xuICAgICAgICAgICAgICogQHBhcmFtIHskcHJvdG9idWYuUmVhZGVyfFVpbnQ4QXJyYXl9IHJlYWRlciBSZWFkZXIgb3IgYnVmZmVyIHRvIGRlY29kZSBmcm9tXG4gICAgICAgICAgICAgKiBAcmV0dXJucyB7b25ueC5UZW5zb3JTaGFwZVByb3RvLkRpbWVuc2lvbn0gRGltZW5zaW9uXG4gICAgICAgICAgICAgKiBAdGhyb3dzIHtFcnJvcn0gSWYgdGhlIHBheWxvYWQgaXMgbm90IGEgcmVhZGVyIG9yIHZhbGlkIGJ1ZmZlclxuICAgICAgICAgICAgICogQHRocm93cyB7JHByb3RvYnVmLnV0aWwuUHJvdG9jb2xFcnJvcn0gSWYgcmVxdWlyZWQgZmllbGRzIGFyZSBtaXNzaW5nXG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIERpbWVuc2lvbi5kZWNvZGVEZWxpbWl0ZWQgPSBmdW5jdGlvbiBkZWNvZGVEZWxpbWl0ZWQocmVhZGVyKSB7XG4gICAgICAgICAgICAgICAgaWYgKCEocmVhZGVyIGluc3RhbmNlb2YgJFJlYWRlcikpXG4gICAgICAgICAgICAgICAgICAgIHJlYWRlciA9IG5ldyAkUmVhZGVyKHJlYWRlcik7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuZGVjb2RlKHJlYWRlciwgcmVhZGVyLnVpbnQzMigpKTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIC8qKlxuICAgICAgICAgICAgICogVmVyaWZpZXMgYSBEaW1lbnNpb24gbWVzc2FnZS5cbiAgICAgICAgICAgICAqIEBmdW5jdGlvbiB2ZXJpZnlcbiAgICAgICAgICAgICAqIEBtZW1iZXJvZiBvbm54LlRlbnNvclNoYXBlUHJvdG8uRGltZW5zaW9uXG4gICAgICAgICAgICAgKiBAc3RhdGljXG4gICAgICAgICAgICAgKiBAcGFyYW0ge09iamVjdC48c3RyaW5nLCo+fSBtZXNzYWdlIFBsYWluIG9iamVjdCB0byB2ZXJpZnlcbiAgICAgICAgICAgICAqIEByZXR1cm5zIHtzdHJpbmd8bnVsbH0gYG51bGxgIGlmIHZhbGlkLCBvdGhlcndpc2UgdGhlIHJlYXNvbiB3aHkgaXQgaXMgbm90XG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIERpbWVuc2lvbi52ZXJpZnkgPSBmdW5jdGlvbiB2ZXJpZnkobWVzc2FnZSkge1xuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgbWVzc2FnZSAhPT0gXCJvYmplY3RcIiB8fCBtZXNzYWdlID09PSBudWxsKVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gXCJvYmplY3QgZXhwZWN0ZWRcIjtcbiAgICAgICAgICAgICAgICB2YXIgcHJvcGVydGllcyA9IHt9O1xuICAgICAgICAgICAgICAgIGlmIChtZXNzYWdlLmRpbVZhbHVlICE9IG51bGwgJiYgbWVzc2FnZS5oYXNPd25Qcm9wZXJ0eShcImRpbVZhbHVlXCIpKSB7XG4gICAgICAgICAgICAgICAgICAgIHByb3BlcnRpZXMudmFsdWUgPSAxO1xuICAgICAgICAgICAgICAgICAgICBpZiAoISR1dGlsLmlzSW50ZWdlcihtZXNzYWdlLmRpbVZhbHVlKSAmJiAhKG1lc3NhZ2UuZGltVmFsdWUgJiYgJHV0aWwuaXNJbnRlZ2VyKG1lc3NhZ2UuZGltVmFsdWUubG93KSAmJiAkdXRpbC5pc0ludGVnZXIobWVzc2FnZS5kaW1WYWx1ZS5oaWdoKSkpXG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gXCJkaW1WYWx1ZTogaW50ZWdlcnxMb25nIGV4cGVjdGVkXCI7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChtZXNzYWdlLmRpbVBhcmFtICE9IG51bGwgJiYgbWVzc2FnZS5oYXNPd25Qcm9wZXJ0eShcImRpbVBhcmFtXCIpKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChwcm9wZXJ0aWVzLnZhbHVlID09PSAxKVxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFwidmFsdWU6IG11bHRpcGxlIHZhbHVlc1wiO1xuICAgICAgICAgICAgICAgICAgICBwcm9wZXJ0aWVzLnZhbHVlID0gMTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCEkdXRpbC5pc1N0cmluZyhtZXNzYWdlLmRpbVBhcmFtKSlcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBcImRpbVBhcmFtOiBzdHJpbmcgZXhwZWN0ZWRcIjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKG1lc3NhZ2UuZGVub3RhdGlvbiAhPSBudWxsICYmIG1lc3NhZ2UuaGFzT3duUHJvcGVydHkoXCJkZW5vdGF0aW9uXCIpKVxuICAgICAgICAgICAgICAgICAgICBpZiAoISR1dGlsLmlzU3RyaW5nKG1lc3NhZ2UuZGVub3RhdGlvbikpXG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gXCJkZW5vdGF0aW9uOiBzdHJpbmcgZXhwZWN0ZWRcIjtcbiAgICAgICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIC8qKlxuICAgICAgICAgICAgICogQ3JlYXRlcyBhIERpbWVuc2lvbiBtZXNzYWdlIGZyb20gYSBwbGFpbiBvYmplY3QuIEFsc28gY29udmVydHMgdmFsdWVzIHRvIHRoZWlyIHJlc3BlY3RpdmUgaW50ZXJuYWwgdHlwZXMuXG4gICAgICAgICAgICAgKiBAZnVuY3Rpb24gZnJvbU9iamVjdFxuICAgICAgICAgICAgICogQG1lbWJlcm9mIG9ubnguVGVuc29yU2hhcGVQcm90by5EaW1lbnNpb25cbiAgICAgICAgICAgICAqIEBzdGF0aWNcbiAgICAgICAgICAgICAqIEBwYXJhbSB7T2JqZWN0LjxzdHJpbmcsKj59IG9iamVjdCBQbGFpbiBvYmplY3RcbiAgICAgICAgICAgICAqIEByZXR1cm5zIHtvbm54LlRlbnNvclNoYXBlUHJvdG8uRGltZW5zaW9ufSBEaW1lbnNpb25cbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgRGltZW5zaW9uLmZyb21PYmplY3QgPSBmdW5jdGlvbiBmcm9tT2JqZWN0KG9iamVjdCkge1xuICAgICAgICAgICAgICAgIGlmIChvYmplY3QgaW5zdGFuY2VvZiAkcm9vdC5vbm54LlRlbnNvclNoYXBlUHJvdG8uRGltZW5zaW9uKVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gb2JqZWN0O1xuICAgICAgICAgICAgICAgIHZhciBtZXNzYWdlID0gbmV3ICRyb290Lm9ubnguVGVuc29yU2hhcGVQcm90by5EaW1lbnNpb24oKTtcbiAgICAgICAgICAgICAgICBpZiAob2JqZWN0LmRpbVZhbHVlICE9IG51bGwpXG4gICAgICAgICAgICAgICAgICAgIGlmICgkdXRpbC5Mb25nKVxuICAgICAgICAgICAgICAgICAgICAgICAgKG1lc3NhZ2UuZGltVmFsdWUgPSAkdXRpbC5Mb25nLmZyb21WYWx1ZShvYmplY3QuZGltVmFsdWUpKS51bnNpZ25lZCA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICBlbHNlIGlmICh0eXBlb2Ygb2JqZWN0LmRpbVZhbHVlID09PSBcInN0cmluZ1wiKVxuICAgICAgICAgICAgICAgICAgICAgICAgbWVzc2FnZS5kaW1WYWx1ZSA9IHBhcnNlSW50KG9iamVjdC5kaW1WYWx1ZSwgMTApO1xuICAgICAgICAgICAgICAgICAgICBlbHNlIGlmICh0eXBlb2Ygb2JqZWN0LmRpbVZhbHVlID09PSBcIm51bWJlclwiKVxuICAgICAgICAgICAgICAgICAgICAgICAgbWVzc2FnZS5kaW1WYWx1ZSA9IG9iamVjdC5kaW1WYWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgZWxzZSBpZiAodHlwZW9mIG9iamVjdC5kaW1WYWx1ZSA9PT0gXCJvYmplY3RcIilcbiAgICAgICAgICAgICAgICAgICAgICAgIG1lc3NhZ2UuZGltVmFsdWUgPSBuZXcgJHV0aWwuTG9uZ0JpdHMob2JqZWN0LmRpbVZhbHVlLmxvdyA+Pj4gMCwgb2JqZWN0LmRpbVZhbHVlLmhpZ2ggPj4+IDApLnRvTnVtYmVyKCk7XG4gICAgICAgICAgICAgICAgaWYgKG9iamVjdC5kaW1QYXJhbSAhPSBudWxsKVxuICAgICAgICAgICAgICAgICAgICBtZXNzYWdlLmRpbVBhcmFtID0gU3RyaW5nKG9iamVjdC5kaW1QYXJhbSk7XG4gICAgICAgICAgICAgICAgaWYgKG9iamVjdC5kZW5vdGF0aW9uICE9IG51bGwpXG4gICAgICAgICAgICAgICAgICAgIG1lc3NhZ2UuZGVub3RhdGlvbiA9IFN0cmluZyhvYmplY3QuZGVub3RhdGlvbik7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG1lc3NhZ2U7XG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICAvKipcbiAgICAgICAgICAgICAqIENyZWF0ZXMgYSBwbGFpbiBvYmplY3QgZnJvbSBhIERpbWVuc2lvbiBtZXNzYWdlLiBBbHNvIGNvbnZlcnRzIHZhbHVlcyB0byBvdGhlciB0eXBlcyBpZiBzcGVjaWZpZWQuXG4gICAgICAgICAgICAgKiBAZnVuY3Rpb24gdG9PYmplY3RcbiAgICAgICAgICAgICAqIEBtZW1iZXJvZiBvbm54LlRlbnNvclNoYXBlUHJvdG8uRGltZW5zaW9uXG4gICAgICAgICAgICAgKiBAc3RhdGljXG4gICAgICAgICAgICAgKiBAcGFyYW0ge29ubnguVGVuc29yU2hhcGVQcm90by5EaW1lbnNpb259IG1lc3NhZ2UgRGltZW5zaW9uXG4gICAgICAgICAgICAgKiBAcGFyYW0geyRwcm90b2J1Zi5JQ29udmVyc2lvbk9wdGlvbnN9IFtvcHRpb25zXSBDb252ZXJzaW9uIG9wdGlvbnNcbiAgICAgICAgICAgICAqIEByZXR1cm5zIHtPYmplY3QuPHN0cmluZywqPn0gUGxhaW4gb2JqZWN0XG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIERpbWVuc2lvbi50b09iamVjdCA9IGZ1bmN0aW9uIHRvT2JqZWN0KG1lc3NhZ2UsIG9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICBpZiAoIW9wdGlvbnMpXG4gICAgICAgICAgICAgICAgICAgIG9wdGlvbnMgPSB7fTtcbiAgICAgICAgICAgICAgICB2YXIgb2JqZWN0ID0ge307XG4gICAgICAgICAgICAgICAgaWYgKG9wdGlvbnMuZGVmYXVsdHMpXG4gICAgICAgICAgICAgICAgICAgIG9iamVjdC5kZW5vdGF0aW9uID0gXCJcIjtcbiAgICAgICAgICAgICAgICBpZiAobWVzc2FnZS5kaW1WYWx1ZSAhPSBudWxsICYmIG1lc3NhZ2UuaGFzT3duUHJvcGVydHkoXCJkaW1WYWx1ZVwiKSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAodHlwZW9mIG1lc3NhZ2UuZGltVmFsdWUgPT09IFwibnVtYmVyXCIpXG4gICAgICAgICAgICAgICAgICAgICAgICBvYmplY3QuZGltVmFsdWUgPSBvcHRpb25zLmxvbmdzID09PSBTdHJpbmcgPyBTdHJpbmcobWVzc2FnZS5kaW1WYWx1ZSkgOiBtZXNzYWdlLmRpbVZhbHVlO1xuICAgICAgICAgICAgICAgICAgICBlbHNlXG4gICAgICAgICAgICAgICAgICAgICAgICBvYmplY3QuZGltVmFsdWUgPSBvcHRpb25zLmxvbmdzID09PSBTdHJpbmcgPyAkdXRpbC5Mb25nLnByb3RvdHlwZS50b1N0cmluZy5jYWxsKG1lc3NhZ2UuZGltVmFsdWUpIDogb3B0aW9ucy5sb25ncyA9PT0gTnVtYmVyID8gbmV3ICR1dGlsLkxvbmdCaXRzKG1lc3NhZ2UuZGltVmFsdWUubG93ID4+PiAwLCBtZXNzYWdlLmRpbVZhbHVlLmhpZ2ggPj4+IDApLnRvTnVtYmVyKCkgOiBtZXNzYWdlLmRpbVZhbHVlO1xuICAgICAgICAgICAgICAgICAgICBpZiAob3B0aW9ucy5vbmVvZnMpXG4gICAgICAgICAgICAgICAgICAgICAgICBvYmplY3QudmFsdWUgPSBcImRpbVZhbHVlXCI7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChtZXNzYWdlLmRpbVBhcmFtICE9IG51bGwgJiYgbWVzc2FnZS5oYXNPd25Qcm9wZXJ0eShcImRpbVBhcmFtXCIpKSB7XG4gICAgICAgICAgICAgICAgICAgIG9iamVjdC5kaW1QYXJhbSA9IG1lc3NhZ2UuZGltUGFyYW07XG4gICAgICAgICAgICAgICAgICAgIGlmIChvcHRpb25zLm9uZW9mcylcbiAgICAgICAgICAgICAgICAgICAgICAgIG9iamVjdC52YWx1ZSA9IFwiZGltUGFyYW1cIjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKG1lc3NhZ2UuZGVub3RhdGlvbiAhPSBudWxsICYmIG1lc3NhZ2UuaGFzT3duUHJvcGVydHkoXCJkZW5vdGF0aW9uXCIpKVxuICAgICAgICAgICAgICAgICAgICBvYmplY3QuZGVub3RhdGlvbiA9IG1lc3NhZ2UuZGVub3RhdGlvbjtcbiAgICAgICAgICAgICAgICByZXR1cm4gb2JqZWN0O1xuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgKiBDb252ZXJ0cyB0aGlzIERpbWVuc2lvbiB0byBKU09OLlxuICAgICAgICAgICAgICogQGZ1bmN0aW9uIHRvSlNPTlxuICAgICAgICAgICAgICogQG1lbWJlcm9mIG9ubnguVGVuc29yU2hhcGVQcm90by5EaW1lbnNpb25cbiAgICAgICAgICAgICAqIEBpbnN0YW5jZVxuICAgICAgICAgICAgICogQHJldHVybnMge09iamVjdC48c3RyaW5nLCo+fSBKU09OIG9iamVjdFxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBEaW1lbnNpb24ucHJvdG90eXBlLnRvSlNPTiA9IGZ1bmN0aW9uIHRvSlNPTigpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5jb25zdHJ1Y3Rvci50b09iamVjdCh0aGlzLCAkcHJvdG9idWYudXRpbC50b0pTT05PcHRpb25zKTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIHJldHVybiBEaW1lbnNpb247XG4gICAgICAgIH0pKCk7XG5cbiAgICAgICAgcmV0dXJuIFRlbnNvclNoYXBlUHJvdG87XG4gICAgfSkoKTtcblxuICAgIG9ubnguVHlwZVByb3RvID0gKGZ1bmN0aW9uKCkge1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBQcm9wZXJ0aWVzIG9mIGEgVHlwZVByb3RvLlxuICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueFxuICAgICAgICAgKiBAaW50ZXJmYWNlIElUeXBlUHJvdG9cbiAgICAgICAgICogQHByb3BlcnR5IHtvbm54LlR5cGVQcm90by5JVGVuc29yfG51bGx9IFt0ZW5zb3JUeXBlXSBUeXBlUHJvdG8gdGVuc29yVHlwZVxuICAgICAgICAgKiBAcHJvcGVydHkge3N0cmluZ3xudWxsfSBbZGVub3RhdGlvbl0gVHlwZVByb3RvIGRlbm90YXRpb25cbiAgICAgICAgICovXG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIENvbnN0cnVjdHMgYSBuZXcgVHlwZVByb3RvLlxuICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueFxuICAgICAgICAgKiBAY2xhc3NkZXNjIFJlcHJlc2VudHMgYSBUeXBlUHJvdG8uXG4gICAgICAgICAqIEBpbXBsZW1lbnRzIElUeXBlUHJvdG9cbiAgICAgICAgICogQGNvbnN0cnVjdG9yXG4gICAgICAgICAqIEBwYXJhbSB7b25ueC5JVHlwZVByb3RvPX0gW3Byb3BlcnRpZXNdIFByb3BlcnRpZXMgdG8gc2V0XG4gICAgICAgICAqL1xuICAgICAgICBmdW5jdGlvbiBUeXBlUHJvdG8ocHJvcGVydGllcykge1xuICAgICAgICAgICAgaWYgKHByb3BlcnRpZXMpXG4gICAgICAgICAgICAgICAgZm9yICh2YXIga2V5cyA9IE9iamVjdC5rZXlzKHByb3BlcnRpZXMpLCBpID0gMDsgaSA8IGtleXMubGVuZ3RoOyArK2kpXG4gICAgICAgICAgICAgICAgICAgIGlmIChwcm9wZXJ0aWVzW2tleXNbaV1dICE9IG51bGwpXG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzW2tleXNbaV1dID0gcHJvcGVydGllc1trZXlzW2ldXTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBUeXBlUHJvdG8gdGVuc29yVHlwZS5cbiAgICAgICAgICogQG1lbWJlciB7b25ueC5UeXBlUHJvdG8uSVRlbnNvcnxudWxsfHVuZGVmaW5lZH0gdGVuc29yVHlwZVxuICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueC5UeXBlUHJvdG9cbiAgICAgICAgICogQGluc3RhbmNlXG4gICAgICAgICAqL1xuICAgICAgICBUeXBlUHJvdG8ucHJvdG90eXBlLnRlbnNvclR5cGUgPSBudWxsO1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBUeXBlUHJvdG8gZGVub3RhdGlvbi5cbiAgICAgICAgICogQG1lbWJlciB7c3RyaW5nfSBkZW5vdGF0aW9uXG4gICAgICAgICAqIEBtZW1iZXJvZiBvbm54LlR5cGVQcm90b1xuICAgICAgICAgKiBAaW5zdGFuY2VcbiAgICAgICAgICovXG4gICAgICAgIFR5cGVQcm90by5wcm90b3R5cGUuZGVub3RhdGlvbiA9IFwiXCI7XG5cbiAgICAgICAgLy8gT25lT2YgZmllbGQgbmFtZXMgYm91bmQgdG8gdmlydHVhbCBnZXR0ZXJzIGFuZCBzZXR0ZXJzXG4gICAgICAgIHZhciAkb25lT2ZGaWVsZHM7XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIFR5cGVQcm90byB2YWx1ZS5cbiAgICAgICAgICogQG1lbWJlciB7XCJ0ZW5zb3JUeXBlXCJ8dW5kZWZpbmVkfSB2YWx1ZVxuICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueC5UeXBlUHJvdG9cbiAgICAgICAgICogQGluc3RhbmNlXG4gICAgICAgICAqL1xuICAgICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoVHlwZVByb3RvLnByb3RvdHlwZSwgXCJ2YWx1ZVwiLCB7XG4gICAgICAgICAgICBnZXQ6ICR1dGlsLm9uZU9mR2V0dGVyKCRvbmVPZkZpZWxkcyA9IFtcInRlbnNvclR5cGVcIl0pLFxuICAgICAgICAgICAgc2V0OiAkdXRpbC5vbmVPZlNldHRlcigkb25lT2ZGaWVsZHMpXG4gICAgICAgIH0pO1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBDcmVhdGVzIGEgbmV3IFR5cGVQcm90byBpbnN0YW5jZSB1c2luZyB0aGUgc3BlY2lmaWVkIHByb3BlcnRpZXMuXG4gICAgICAgICAqIEBmdW5jdGlvbiBjcmVhdGVcbiAgICAgICAgICogQG1lbWJlcm9mIG9ubnguVHlwZVByb3RvXG4gICAgICAgICAqIEBzdGF0aWNcbiAgICAgICAgICogQHBhcmFtIHtvbm54LklUeXBlUHJvdG89fSBbcHJvcGVydGllc10gUHJvcGVydGllcyB0byBzZXRcbiAgICAgICAgICogQHJldHVybnMge29ubnguVHlwZVByb3RvfSBUeXBlUHJvdG8gaW5zdGFuY2VcbiAgICAgICAgICovXG4gICAgICAgIFR5cGVQcm90by5jcmVhdGUgPSBmdW5jdGlvbiBjcmVhdGUocHJvcGVydGllcykge1xuICAgICAgICAgICAgcmV0dXJuIG5ldyBUeXBlUHJvdG8ocHJvcGVydGllcyk7XG4gICAgICAgIH07XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEVuY29kZXMgdGhlIHNwZWNpZmllZCBUeXBlUHJvdG8gbWVzc2FnZS4gRG9lcyBub3QgaW1wbGljaXRseSB7QGxpbmsgb25ueC5UeXBlUHJvdG8udmVyaWZ5fHZlcmlmeX0gbWVzc2FnZXMuXG4gICAgICAgICAqIEBmdW5jdGlvbiBlbmNvZGVcbiAgICAgICAgICogQG1lbWJlcm9mIG9ubnguVHlwZVByb3RvXG4gICAgICAgICAqIEBzdGF0aWNcbiAgICAgICAgICogQHBhcmFtIHtvbm54LklUeXBlUHJvdG99IG1lc3NhZ2UgVHlwZVByb3RvIG1lc3NhZ2Ugb3IgcGxhaW4gb2JqZWN0IHRvIGVuY29kZVxuICAgICAgICAgKiBAcGFyYW0geyRwcm90b2J1Zi5Xcml0ZXJ9IFt3cml0ZXJdIFdyaXRlciB0byBlbmNvZGUgdG9cbiAgICAgICAgICogQHJldHVybnMgeyRwcm90b2J1Zi5Xcml0ZXJ9IFdyaXRlclxuICAgICAgICAgKi9cbiAgICAgICAgVHlwZVByb3RvLmVuY29kZSA9IGZ1bmN0aW9uIGVuY29kZShtZXNzYWdlLCB3cml0ZXIpIHtcbiAgICAgICAgICAgIGlmICghd3JpdGVyKVxuICAgICAgICAgICAgICAgIHdyaXRlciA9ICRXcml0ZXIuY3JlYXRlKCk7XG4gICAgICAgICAgICBpZiAobWVzc2FnZS50ZW5zb3JUeXBlICE9IG51bGwgJiYgbWVzc2FnZS5oYXNPd25Qcm9wZXJ0eShcInRlbnNvclR5cGVcIikpXG4gICAgICAgICAgICAgICAgJHJvb3Qub25ueC5UeXBlUHJvdG8uVGVuc29yLmVuY29kZShtZXNzYWdlLnRlbnNvclR5cGUsIHdyaXRlci51aW50MzIoLyogaWQgMSwgd2lyZVR5cGUgMiA9Ki8xMCkuZm9yaygpKS5sZGVsaW0oKTtcbiAgICAgICAgICAgIGlmIChtZXNzYWdlLmRlbm90YXRpb24gIT0gbnVsbCAmJiBtZXNzYWdlLmhhc093blByb3BlcnR5KFwiZGVub3RhdGlvblwiKSlcbiAgICAgICAgICAgICAgICB3cml0ZXIudWludDMyKC8qIGlkIDYsIHdpcmVUeXBlIDIgPSovNTApLnN0cmluZyhtZXNzYWdlLmRlbm90YXRpb24pO1xuICAgICAgICAgICAgcmV0dXJuIHdyaXRlcjtcbiAgICAgICAgfTtcblxuICAgICAgICAvKipcbiAgICAgICAgICogRW5jb2RlcyB0aGUgc3BlY2lmaWVkIFR5cGVQcm90byBtZXNzYWdlLCBsZW5ndGggZGVsaW1pdGVkLiBEb2VzIG5vdCBpbXBsaWNpdGx5IHtAbGluayBvbm54LlR5cGVQcm90by52ZXJpZnl8dmVyaWZ5fSBtZXNzYWdlcy5cbiAgICAgICAgICogQGZ1bmN0aW9uIGVuY29kZURlbGltaXRlZFxuICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueC5UeXBlUHJvdG9cbiAgICAgICAgICogQHN0YXRpY1xuICAgICAgICAgKiBAcGFyYW0ge29ubnguSVR5cGVQcm90b30gbWVzc2FnZSBUeXBlUHJvdG8gbWVzc2FnZSBvciBwbGFpbiBvYmplY3QgdG8gZW5jb2RlXG4gICAgICAgICAqIEBwYXJhbSB7JHByb3RvYnVmLldyaXRlcn0gW3dyaXRlcl0gV3JpdGVyIHRvIGVuY29kZSB0b1xuICAgICAgICAgKiBAcmV0dXJucyB7JHByb3RvYnVmLldyaXRlcn0gV3JpdGVyXG4gICAgICAgICAqL1xuICAgICAgICBUeXBlUHJvdG8uZW5jb2RlRGVsaW1pdGVkID0gZnVuY3Rpb24gZW5jb2RlRGVsaW1pdGVkKG1lc3NhZ2UsIHdyaXRlcikge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuZW5jb2RlKG1lc3NhZ2UsIHdyaXRlcikubGRlbGltKCk7XG4gICAgICAgIH07XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIERlY29kZXMgYSBUeXBlUHJvdG8gbWVzc2FnZSBmcm9tIHRoZSBzcGVjaWZpZWQgcmVhZGVyIG9yIGJ1ZmZlci5cbiAgICAgICAgICogQGZ1bmN0aW9uIGRlY29kZVxuICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueC5UeXBlUHJvdG9cbiAgICAgICAgICogQHN0YXRpY1xuICAgICAgICAgKiBAcGFyYW0geyRwcm90b2J1Zi5SZWFkZXJ8VWludDhBcnJheX0gcmVhZGVyIFJlYWRlciBvciBidWZmZXIgdG8gZGVjb2RlIGZyb21cbiAgICAgICAgICogQHBhcmFtIHtudW1iZXJ9IFtsZW5ndGhdIE1lc3NhZ2UgbGVuZ3RoIGlmIGtub3duIGJlZm9yZWhhbmRcbiAgICAgICAgICogQHJldHVybnMge29ubnguVHlwZVByb3RvfSBUeXBlUHJvdG9cbiAgICAgICAgICogQHRocm93cyB7RXJyb3J9IElmIHRoZSBwYXlsb2FkIGlzIG5vdCBhIHJlYWRlciBvciB2YWxpZCBidWZmZXJcbiAgICAgICAgICogQHRocm93cyB7JHByb3RvYnVmLnV0aWwuUHJvdG9jb2xFcnJvcn0gSWYgcmVxdWlyZWQgZmllbGRzIGFyZSBtaXNzaW5nXG4gICAgICAgICAqL1xuICAgICAgICBUeXBlUHJvdG8uZGVjb2RlID0gZnVuY3Rpb24gZGVjb2RlKHJlYWRlciwgbGVuZ3RoKSB7XG4gICAgICAgICAgICBpZiAoIShyZWFkZXIgaW5zdGFuY2VvZiAkUmVhZGVyKSlcbiAgICAgICAgICAgICAgICByZWFkZXIgPSAkUmVhZGVyLmNyZWF0ZShyZWFkZXIpO1xuICAgICAgICAgICAgdmFyIGVuZCA9IGxlbmd0aCA9PT0gdW5kZWZpbmVkID8gcmVhZGVyLmxlbiA6IHJlYWRlci5wb3MgKyBsZW5ndGgsIG1lc3NhZ2UgPSBuZXcgJHJvb3Qub25ueC5UeXBlUHJvdG8oKTtcbiAgICAgICAgICAgIHdoaWxlIChyZWFkZXIucG9zIDwgZW5kKSB7XG4gICAgICAgICAgICAgICAgdmFyIHRhZyA9IHJlYWRlci51aW50MzIoKTtcbiAgICAgICAgICAgICAgICBzd2l0Y2ggKHRhZyA+Pj4gMykge1xuICAgICAgICAgICAgICAgIGNhc2UgMTpcbiAgICAgICAgICAgICAgICAgICAgbWVzc2FnZS50ZW5zb3JUeXBlID0gJHJvb3Qub25ueC5UeXBlUHJvdG8uVGVuc29yLmRlY29kZShyZWFkZXIsIHJlYWRlci51aW50MzIoKSk7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgNjpcbiAgICAgICAgICAgICAgICAgICAgbWVzc2FnZS5kZW5vdGF0aW9uID0gcmVhZGVyLnN0cmluZygpO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgICAgICByZWFkZXIuc2tpcFR5cGUodGFnICYgNyk7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBtZXNzYWdlO1xuICAgICAgICB9O1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBEZWNvZGVzIGEgVHlwZVByb3RvIG1lc3NhZ2UgZnJvbSB0aGUgc3BlY2lmaWVkIHJlYWRlciBvciBidWZmZXIsIGxlbmd0aCBkZWxpbWl0ZWQuXG4gICAgICAgICAqIEBmdW5jdGlvbiBkZWNvZGVEZWxpbWl0ZWRcbiAgICAgICAgICogQG1lbWJlcm9mIG9ubnguVHlwZVByb3RvXG4gICAgICAgICAqIEBzdGF0aWNcbiAgICAgICAgICogQHBhcmFtIHskcHJvdG9idWYuUmVhZGVyfFVpbnQ4QXJyYXl9IHJlYWRlciBSZWFkZXIgb3IgYnVmZmVyIHRvIGRlY29kZSBmcm9tXG4gICAgICAgICAqIEByZXR1cm5zIHtvbm54LlR5cGVQcm90b30gVHlwZVByb3RvXG4gICAgICAgICAqIEB0aHJvd3Mge0Vycm9yfSBJZiB0aGUgcGF5bG9hZCBpcyBub3QgYSByZWFkZXIgb3IgdmFsaWQgYnVmZmVyXG4gICAgICAgICAqIEB0aHJvd3MgeyRwcm90b2J1Zi51dGlsLlByb3RvY29sRXJyb3J9IElmIHJlcXVpcmVkIGZpZWxkcyBhcmUgbWlzc2luZ1xuICAgICAgICAgKi9cbiAgICAgICAgVHlwZVByb3RvLmRlY29kZURlbGltaXRlZCA9IGZ1bmN0aW9uIGRlY29kZURlbGltaXRlZChyZWFkZXIpIHtcbiAgICAgICAgICAgIGlmICghKHJlYWRlciBpbnN0YW5jZW9mICRSZWFkZXIpKVxuICAgICAgICAgICAgICAgIHJlYWRlciA9IG5ldyAkUmVhZGVyKHJlYWRlcik7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5kZWNvZGUocmVhZGVyLCByZWFkZXIudWludDMyKCkpO1xuICAgICAgICB9O1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBWZXJpZmllcyBhIFR5cGVQcm90byBtZXNzYWdlLlxuICAgICAgICAgKiBAZnVuY3Rpb24gdmVyaWZ5XG4gICAgICAgICAqIEBtZW1iZXJvZiBvbm54LlR5cGVQcm90b1xuICAgICAgICAgKiBAc3RhdGljXG4gICAgICAgICAqIEBwYXJhbSB7T2JqZWN0LjxzdHJpbmcsKj59IG1lc3NhZ2UgUGxhaW4gb2JqZWN0IHRvIHZlcmlmeVxuICAgICAgICAgKiBAcmV0dXJucyB7c3RyaW5nfG51bGx9IGBudWxsYCBpZiB2YWxpZCwgb3RoZXJ3aXNlIHRoZSByZWFzb24gd2h5IGl0IGlzIG5vdFxuICAgICAgICAgKi9cbiAgICAgICAgVHlwZVByb3RvLnZlcmlmeSA9IGZ1bmN0aW9uIHZlcmlmeShtZXNzYWdlKSB7XG4gICAgICAgICAgICBpZiAodHlwZW9mIG1lc3NhZ2UgIT09IFwib2JqZWN0XCIgfHwgbWVzc2FnZSA9PT0gbnVsbClcbiAgICAgICAgICAgICAgICByZXR1cm4gXCJvYmplY3QgZXhwZWN0ZWRcIjtcbiAgICAgICAgICAgIHZhciBwcm9wZXJ0aWVzID0ge307XG4gICAgICAgICAgICBpZiAobWVzc2FnZS50ZW5zb3JUeXBlICE9IG51bGwgJiYgbWVzc2FnZS5oYXNPd25Qcm9wZXJ0eShcInRlbnNvclR5cGVcIikpIHtcbiAgICAgICAgICAgICAgICBwcm9wZXJ0aWVzLnZhbHVlID0gMTtcbiAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBlcnJvciA9ICRyb290Lm9ubnguVHlwZVByb3RvLlRlbnNvci52ZXJpZnkobWVzc2FnZS50ZW5zb3JUeXBlKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGVycm9yKVxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFwidGVuc29yVHlwZS5cIiArIGVycm9yO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChtZXNzYWdlLmRlbm90YXRpb24gIT0gbnVsbCAmJiBtZXNzYWdlLmhhc093blByb3BlcnR5KFwiZGVub3RhdGlvblwiKSlcbiAgICAgICAgICAgICAgICBpZiAoISR1dGlsLmlzU3RyaW5nKG1lc3NhZ2UuZGVub3RhdGlvbikpXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBcImRlbm90YXRpb246IHN0cmluZyBleHBlY3RlZFwiO1xuICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgIH07XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIENyZWF0ZXMgYSBUeXBlUHJvdG8gbWVzc2FnZSBmcm9tIGEgcGxhaW4gb2JqZWN0LiBBbHNvIGNvbnZlcnRzIHZhbHVlcyB0byB0aGVpciByZXNwZWN0aXZlIGludGVybmFsIHR5cGVzLlxuICAgICAgICAgKiBAZnVuY3Rpb24gZnJvbU9iamVjdFxuICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueC5UeXBlUHJvdG9cbiAgICAgICAgICogQHN0YXRpY1xuICAgICAgICAgKiBAcGFyYW0ge09iamVjdC48c3RyaW5nLCo+fSBvYmplY3QgUGxhaW4gb2JqZWN0XG4gICAgICAgICAqIEByZXR1cm5zIHtvbm54LlR5cGVQcm90b30gVHlwZVByb3RvXG4gICAgICAgICAqL1xuICAgICAgICBUeXBlUHJvdG8uZnJvbU9iamVjdCA9IGZ1bmN0aW9uIGZyb21PYmplY3Qob2JqZWN0KSB7XG4gICAgICAgICAgICBpZiAob2JqZWN0IGluc3RhbmNlb2YgJHJvb3Qub25ueC5UeXBlUHJvdG8pXG4gICAgICAgICAgICAgICAgcmV0dXJuIG9iamVjdDtcbiAgICAgICAgICAgIHZhciBtZXNzYWdlID0gbmV3ICRyb290Lm9ubnguVHlwZVByb3RvKCk7XG4gICAgICAgICAgICBpZiAob2JqZWN0LnRlbnNvclR5cGUgIT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIGlmICh0eXBlb2Ygb2JqZWN0LnRlbnNvclR5cGUgIT09IFwib2JqZWN0XCIpXG4gICAgICAgICAgICAgICAgICAgIHRocm93IFR5cGVFcnJvcihcIi5vbm54LlR5cGVQcm90by50ZW5zb3JUeXBlOiBvYmplY3QgZXhwZWN0ZWRcIik7XG4gICAgICAgICAgICAgICAgbWVzc2FnZS50ZW5zb3JUeXBlID0gJHJvb3Qub25ueC5UeXBlUHJvdG8uVGVuc29yLmZyb21PYmplY3Qob2JqZWN0LnRlbnNvclR5cGUpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG9iamVjdC5kZW5vdGF0aW9uICE9IG51bGwpXG4gICAgICAgICAgICAgICAgbWVzc2FnZS5kZW5vdGF0aW9uID0gU3RyaW5nKG9iamVjdC5kZW5vdGF0aW9uKTtcbiAgICAgICAgICAgIHJldHVybiBtZXNzYWdlO1xuICAgICAgICB9O1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBDcmVhdGVzIGEgcGxhaW4gb2JqZWN0IGZyb20gYSBUeXBlUHJvdG8gbWVzc2FnZS4gQWxzbyBjb252ZXJ0cyB2YWx1ZXMgdG8gb3RoZXIgdHlwZXMgaWYgc3BlY2lmaWVkLlxuICAgICAgICAgKiBAZnVuY3Rpb24gdG9PYmplY3RcbiAgICAgICAgICogQG1lbWJlcm9mIG9ubnguVHlwZVByb3RvXG4gICAgICAgICAqIEBzdGF0aWNcbiAgICAgICAgICogQHBhcmFtIHtvbm54LlR5cGVQcm90b30gbWVzc2FnZSBUeXBlUHJvdG9cbiAgICAgICAgICogQHBhcmFtIHskcHJvdG9idWYuSUNvbnZlcnNpb25PcHRpb25zfSBbb3B0aW9uc10gQ29udmVyc2lvbiBvcHRpb25zXG4gICAgICAgICAqIEByZXR1cm5zIHtPYmplY3QuPHN0cmluZywqPn0gUGxhaW4gb2JqZWN0XG4gICAgICAgICAqL1xuICAgICAgICBUeXBlUHJvdG8udG9PYmplY3QgPSBmdW5jdGlvbiB0b09iamVjdChtZXNzYWdlLCBvcHRpb25zKSB7XG4gICAgICAgICAgICBpZiAoIW9wdGlvbnMpXG4gICAgICAgICAgICAgICAgb3B0aW9ucyA9IHt9O1xuICAgICAgICAgICAgdmFyIG9iamVjdCA9IHt9O1xuICAgICAgICAgICAgaWYgKG9wdGlvbnMuZGVmYXVsdHMpXG4gICAgICAgICAgICAgICAgb2JqZWN0LmRlbm90YXRpb24gPSBcIlwiO1xuICAgICAgICAgICAgaWYgKG1lc3NhZ2UudGVuc29yVHlwZSAhPSBudWxsICYmIG1lc3NhZ2UuaGFzT3duUHJvcGVydHkoXCJ0ZW5zb3JUeXBlXCIpKSB7XG4gICAgICAgICAgICAgICAgb2JqZWN0LnRlbnNvclR5cGUgPSAkcm9vdC5vbm54LlR5cGVQcm90by5UZW5zb3IudG9PYmplY3QobWVzc2FnZS50ZW5zb3JUeXBlLCBvcHRpb25zKTtcbiAgICAgICAgICAgICAgICBpZiAob3B0aW9ucy5vbmVvZnMpXG4gICAgICAgICAgICAgICAgICAgIG9iamVjdC52YWx1ZSA9IFwidGVuc29yVHlwZVwiO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG1lc3NhZ2UuZGVub3RhdGlvbiAhPSBudWxsICYmIG1lc3NhZ2UuaGFzT3duUHJvcGVydHkoXCJkZW5vdGF0aW9uXCIpKVxuICAgICAgICAgICAgICAgIG9iamVjdC5kZW5vdGF0aW9uID0gbWVzc2FnZS5kZW5vdGF0aW9uO1xuICAgICAgICAgICAgcmV0dXJuIG9iamVjdDtcbiAgICAgICAgfTtcblxuICAgICAgICAvKipcbiAgICAgICAgICogQ29udmVydHMgdGhpcyBUeXBlUHJvdG8gdG8gSlNPTi5cbiAgICAgICAgICogQGZ1bmN0aW9uIHRvSlNPTlxuICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueC5UeXBlUHJvdG9cbiAgICAgICAgICogQGluc3RhbmNlXG4gICAgICAgICAqIEByZXR1cm5zIHtPYmplY3QuPHN0cmluZywqPn0gSlNPTiBvYmplY3RcbiAgICAgICAgICovXG4gICAgICAgIFR5cGVQcm90by5wcm90b3R5cGUudG9KU09OID0gZnVuY3Rpb24gdG9KU09OKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuY29uc3RydWN0b3IudG9PYmplY3QodGhpcywgJHByb3RvYnVmLnV0aWwudG9KU09OT3B0aW9ucyk7XG4gICAgICAgIH07XG5cbiAgICAgICAgVHlwZVByb3RvLlRlbnNvciA9IChmdW5jdGlvbigpIHtcblxuICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgKiBQcm9wZXJ0aWVzIG9mIGEgVGVuc29yLlxuICAgICAgICAgICAgICogQG1lbWJlcm9mIG9ubnguVHlwZVByb3RvXG4gICAgICAgICAgICAgKiBAaW50ZXJmYWNlIElUZW5zb3JcbiAgICAgICAgICAgICAqIEBwcm9wZXJ0eSB7bnVtYmVyfG51bGx9IFtlbGVtVHlwZV0gVGVuc29yIGVsZW1UeXBlXG4gICAgICAgICAgICAgKiBAcHJvcGVydHkge29ubnguSVRlbnNvclNoYXBlUHJvdG98bnVsbH0gW3NoYXBlXSBUZW5zb3Igc2hhcGVcbiAgICAgICAgICAgICAqL1xuXG4gICAgICAgICAgICAvKipcbiAgICAgICAgICAgICAqIENvbnN0cnVjdHMgYSBuZXcgVGVuc29yLlxuICAgICAgICAgICAgICogQG1lbWJlcm9mIG9ubnguVHlwZVByb3RvXG4gICAgICAgICAgICAgKiBAY2xhc3NkZXNjIFJlcHJlc2VudHMgYSBUZW5zb3IuXG4gICAgICAgICAgICAgKiBAaW1wbGVtZW50cyBJVGVuc29yXG4gICAgICAgICAgICAgKiBAY29uc3RydWN0b3JcbiAgICAgICAgICAgICAqIEBwYXJhbSB7b25ueC5UeXBlUHJvdG8uSVRlbnNvcj19IFtwcm9wZXJ0aWVzXSBQcm9wZXJ0aWVzIHRvIHNldFxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBmdW5jdGlvbiBUZW5zb3IocHJvcGVydGllcykge1xuICAgICAgICAgICAgICAgIGlmIChwcm9wZXJ0aWVzKVxuICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBrZXlzID0gT2JqZWN0LmtleXMocHJvcGVydGllcyksIGkgPSAwOyBpIDwga2V5cy5sZW5ndGg7ICsraSlcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChwcm9wZXJ0aWVzW2tleXNbaV1dICE9IG51bGwpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpc1trZXlzW2ldXSA9IHByb3BlcnRpZXNba2V5c1tpXV07XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8qKlxuICAgICAgICAgICAgICogVGVuc29yIGVsZW1UeXBlLlxuICAgICAgICAgICAgICogQG1lbWJlciB7bnVtYmVyfSBlbGVtVHlwZVxuICAgICAgICAgICAgICogQG1lbWJlcm9mIG9ubnguVHlwZVByb3RvLlRlbnNvclxuICAgICAgICAgICAgICogQGluc3RhbmNlXG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIFRlbnNvci5wcm90b3R5cGUuZWxlbVR5cGUgPSAwO1xuXG4gICAgICAgICAgICAvKipcbiAgICAgICAgICAgICAqIFRlbnNvciBzaGFwZS5cbiAgICAgICAgICAgICAqIEBtZW1iZXIge29ubnguSVRlbnNvclNoYXBlUHJvdG98bnVsbHx1bmRlZmluZWR9IHNoYXBlXG4gICAgICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueC5UeXBlUHJvdG8uVGVuc29yXG4gICAgICAgICAgICAgKiBAaW5zdGFuY2VcbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgVGVuc29yLnByb3RvdHlwZS5zaGFwZSA9IG51bGw7XG5cbiAgICAgICAgICAgIC8qKlxuICAgICAgICAgICAgICogQ3JlYXRlcyBhIG5ldyBUZW5zb3IgaW5zdGFuY2UgdXNpbmcgdGhlIHNwZWNpZmllZCBwcm9wZXJ0aWVzLlxuICAgICAgICAgICAgICogQGZ1bmN0aW9uIGNyZWF0ZVxuICAgICAgICAgICAgICogQG1lbWJlcm9mIG9ubnguVHlwZVByb3RvLlRlbnNvclxuICAgICAgICAgICAgICogQHN0YXRpY1xuICAgICAgICAgICAgICogQHBhcmFtIHtvbm54LlR5cGVQcm90by5JVGVuc29yPX0gW3Byb3BlcnRpZXNdIFByb3BlcnRpZXMgdG8gc2V0XG4gICAgICAgICAgICAgKiBAcmV0dXJucyB7b25ueC5UeXBlUHJvdG8uVGVuc29yfSBUZW5zb3IgaW5zdGFuY2VcbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgVGVuc29yLmNyZWF0ZSA9IGZ1bmN0aW9uIGNyZWF0ZShwcm9wZXJ0aWVzKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBUZW5zb3IocHJvcGVydGllcyk7XG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICAvKipcbiAgICAgICAgICAgICAqIEVuY29kZXMgdGhlIHNwZWNpZmllZCBUZW5zb3IgbWVzc2FnZS4gRG9lcyBub3QgaW1wbGljaXRseSB7QGxpbmsgb25ueC5UeXBlUHJvdG8uVGVuc29yLnZlcmlmeXx2ZXJpZnl9IG1lc3NhZ2VzLlxuICAgICAgICAgICAgICogQGZ1bmN0aW9uIGVuY29kZVxuICAgICAgICAgICAgICogQG1lbWJlcm9mIG9ubnguVHlwZVByb3RvLlRlbnNvclxuICAgICAgICAgICAgICogQHN0YXRpY1xuICAgICAgICAgICAgICogQHBhcmFtIHtvbm54LlR5cGVQcm90by5JVGVuc29yfSBtZXNzYWdlIFRlbnNvciBtZXNzYWdlIG9yIHBsYWluIG9iamVjdCB0byBlbmNvZGVcbiAgICAgICAgICAgICAqIEBwYXJhbSB7JHByb3RvYnVmLldyaXRlcn0gW3dyaXRlcl0gV3JpdGVyIHRvIGVuY29kZSB0b1xuICAgICAgICAgICAgICogQHJldHVybnMgeyRwcm90b2J1Zi5Xcml0ZXJ9IFdyaXRlclxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBUZW5zb3IuZW5jb2RlID0gZnVuY3Rpb24gZW5jb2RlKG1lc3NhZ2UsIHdyaXRlcikge1xuICAgICAgICAgICAgICAgIGlmICghd3JpdGVyKVxuICAgICAgICAgICAgICAgICAgICB3cml0ZXIgPSAkV3JpdGVyLmNyZWF0ZSgpO1xuICAgICAgICAgICAgICAgIGlmIChtZXNzYWdlLmVsZW1UeXBlICE9IG51bGwgJiYgbWVzc2FnZS5oYXNPd25Qcm9wZXJ0eShcImVsZW1UeXBlXCIpKVxuICAgICAgICAgICAgICAgICAgICB3cml0ZXIudWludDMyKC8qIGlkIDEsIHdpcmVUeXBlIDAgPSovOCkuaW50MzIobWVzc2FnZS5lbGVtVHlwZSk7XG4gICAgICAgICAgICAgICAgaWYgKG1lc3NhZ2Uuc2hhcGUgIT0gbnVsbCAmJiBtZXNzYWdlLmhhc093blByb3BlcnR5KFwic2hhcGVcIikpXG4gICAgICAgICAgICAgICAgICAgICRyb290Lm9ubnguVGVuc29yU2hhcGVQcm90by5lbmNvZGUobWVzc2FnZS5zaGFwZSwgd3JpdGVyLnVpbnQzMigvKiBpZCAyLCB3aXJlVHlwZSAyID0qLzE4KS5mb3JrKCkpLmxkZWxpbSgpO1xuICAgICAgICAgICAgICAgIHJldHVybiB3cml0ZXI7XG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICAvKipcbiAgICAgICAgICAgICAqIEVuY29kZXMgdGhlIHNwZWNpZmllZCBUZW5zb3IgbWVzc2FnZSwgbGVuZ3RoIGRlbGltaXRlZC4gRG9lcyBub3QgaW1wbGljaXRseSB7QGxpbmsgb25ueC5UeXBlUHJvdG8uVGVuc29yLnZlcmlmeXx2ZXJpZnl9IG1lc3NhZ2VzLlxuICAgICAgICAgICAgICogQGZ1bmN0aW9uIGVuY29kZURlbGltaXRlZFxuICAgICAgICAgICAgICogQG1lbWJlcm9mIG9ubnguVHlwZVByb3RvLlRlbnNvclxuICAgICAgICAgICAgICogQHN0YXRpY1xuICAgICAgICAgICAgICogQHBhcmFtIHtvbm54LlR5cGVQcm90by5JVGVuc29yfSBtZXNzYWdlIFRlbnNvciBtZXNzYWdlIG9yIHBsYWluIG9iamVjdCB0byBlbmNvZGVcbiAgICAgICAgICAgICAqIEBwYXJhbSB7JHByb3RvYnVmLldyaXRlcn0gW3dyaXRlcl0gV3JpdGVyIHRvIGVuY29kZSB0b1xuICAgICAgICAgICAgICogQHJldHVybnMgeyRwcm90b2J1Zi5Xcml0ZXJ9IFdyaXRlclxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBUZW5zb3IuZW5jb2RlRGVsaW1pdGVkID0gZnVuY3Rpb24gZW5jb2RlRGVsaW1pdGVkKG1lc3NhZ2UsIHdyaXRlcikge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmVuY29kZShtZXNzYWdlLCB3cml0ZXIpLmxkZWxpbSgpO1xuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgKiBEZWNvZGVzIGEgVGVuc29yIG1lc3NhZ2UgZnJvbSB0aGUgc3BlY2lmaWVkIHJlYWRlciBvciBidWZmZXIuXG4gICAgICAgICAgICAgKiBAZnVuY3Rpb24gZGVjb2RlXG4gICAgICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueC5UeXBlUHJvdG8uVGVuc29yXG4gICAgICAgICAgICAgKiBAc3RhdGljXG4gICAgICAgICAgICAgKiBAcGFyYW0geyRwcm90b2J1Zi5SZWFkZXJ8VWludDhBcnJheX0gcmVhZGVyIFJlYWRlciBvciBidWZmZXIgdG8gZGVjb2RlIGZyb21cbiAgICAgICAgICAgICAqIEBwYXJhbSB7bnVtYmVyfSBbbGVuZ3RoXSBNZXNzYWdlIGxlbmd0aCBpZiBrbm93biBiZWZvcmVoYW5kXG4gICAgICAgICAgICAgKiBAcmV0dXJucyB7b25ueC5UeXBlUHJvdG8uVGVuc29yfSBUZW5zb3JcbiAgICAgICAgICAgICAqIEB0aHJvd3Mge0Vycm9yfSBJZiB0aGUgcGF5bG9hZCBpcyBub3QgYSByZWFkZXIgb3IgdmFsaWQgYnVmZmVyXG4gICAgICAgICAgICAgKiBAdGhyb3dzIHskcHJvdG9idWYudXRpbC5Qcm90b2NvbEVycm9yfSBJZiByZXF1aXJlZCBmaWVsZHMgYXJlIG1pc3NpbmdcbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgVGVuc29yLmRlY29kZSA9IGZ1bmN0aW9uIGRlY29kZShyZWFkZXIsIGxlbmd0aCkge1xuICAgICAgICAgICAgICAgIGlmICghKHJlYWRlciBpbnN0YW5jZW9mICRSZWFkZXIpKVxuICAgICAgICAgICAgICAgICAgICByZWFkZXIgPSAkUmVhZGVyLmNyZWF0ZShyZWFkZXIpO1xuICAgICAgICAgICAgICAgIHZhciBlbmQgPSBsZW5ndGggPT09IHVuZGVmaW5lZCA/IHJlYWRlci5sZW4gOiByZWFkZXIucG9zICsgbGVuZ3RoLCBtZXNzYWdlID0gbmV3ICRyb290Lm9ubnguVHlwZVByb3RvLlRlbnNvcigpO1xuICAgICAgICAgICAgICAgIHdoaWxlIChyZWFkZXIucG9zIDwgZW5kKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciB0YWcgPSByZWFkZXIudWludDMyKCk7XG4gICAgICAgICAgICAgICAgICAgIHN3aXRjaCAodGFnID4+PiAzKSB7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgMTpcbiAgICAgICAgICAgICAgICAgICAgICAgIG1lc3NhZ2UuZWxlbVR5cGUgPSByZWFkZXIuaW50MzIoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIDI6XG4gICAgICAgICAgICAgICAgICAgICAgICBtZXNzYWdlLnNoYXBlID0gJHJvb3Qub25ueC5UZW5zb3JTaGFwZVByb3RvLmRlY29kZShyZWFkZXIsIHJlYWRlci51aW50MzIoKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlYWRlci5za2lwVHlwZSh0YWcgJiA3KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiBtZXNzYWdlO1xuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgKiBEZWNvZGVzIGEgVGVuc29yIG1lc3NhZ2UgZnJvbSB0aGUgc3BlY2lmaWVkIHJlYWRlciBvciBidWZmZXIsIGxlbmd0aCBkZWxpbWl0ZWQuXG4gICAgICAgICAgICAgKiBAZnVuY3Rpb24gZGVjb2RlRGVsaW1pdGVkXG4gICAgICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueC5UeXBlUHJvdG8uVGVuc29yXG4gICAgICAgICAgICAgKiBAc3RhdGljXG4gICAgICAgICAgICAgKiBAcGFyYW0geyRwcm90b2J1Zi5SZWFkZXJ8VWludDhBcnJheX0gcmVhZGVyIFJlYWRlciBvciBidWZmZXIgdG8gZGVjb2RlIGZyb21cbiAgICAgICAgICAgICAqIEByZXR1cm5zIHtvbm54LlR5cGVQcm90by5UZW5zb3J9IFRlbnNvclxuICAgICAgICAgICAgICogQHRocm93cyB7RXJyb3J9IElmIHRoZSBwYXlsb2FkIGlzIG5vdCBhIHJlYWRlciBvciB2YWxpZCBidWZmZXJcbiAgICAgICAgICAgICAqIEB0aHJvd3MgeyRwcm90b2J1Zi51dGlsLlByb3RvY29sRXJyb3J9IElmIHJlcXVpcmVkIGZpZWxkcyBhcmUgbWlzc2luZ1xuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBUZW5zb3IuZGVjb2RlRGVsaW1pdGVkID0gZnVuY3Rpb24gZGVjb2RlRGVsaW1pdGVkKHJlYWRlcikge1xuICAgICAgICAgICAgICAgIGlmICghKHJlYWRlciBpbnN0YW5jZW9mICRSZWFkZXIpKVxuICAgICAgICAgICAgICAgICAgICByZWFkZXIgPSBuZXcgJFJlYWRlcihyZWFkZXIpO1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmRlY29kZShyZWFkZXIsIHJlYWRlci51aW50MzIoKSk7XG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICAvKipcbiAgICAgICAgICAgICAqIFZlcmlmaWVzIGEgVGVuc29yIG1lc3NhZ2UuXG4gICAgICAgICAgICAgKiBAZnVuY3Rpb24gdmVyaWZ5XG4gICAgICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueC5UeXBlUHJvdG8uVGVuc29yXG4gICAgICAgICAgICAgKiBAc3RhdGljXG4gICAgICAgICAgICAgKiBAcGFyYW0ge09iamVjdC48c3RyaW5nLCo+fSBtZXNzYWdlIFBsYWluIG9iamVjdCB0byB2ZXJpZnlcbiAgICAgICAgICAgICAqIEByZXR1cm5zIHtzdHJpbmd8bnVsbH0gYG51bGxgIGlmIHZhbGlkLCBvdGhlcndpc2UgdGhlIHJlYXNvbiB3aHkgaXQgaXMgbm90XG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIFRlbnNvci52ZXJpZnkgPSBmdW5jdGlvbiB2ZXJpZnkobWVzc2FnZSkge1xuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgbWVzc2FnZSAhPT0gXCJvYmplY3RcIiB8fCBtZXNzYWdlID09PSBudWxsKVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gXCJvYmplY3QgZXhwZWN0ZWRcIjtcbiAgICAgICAgICAgICAgICBpZiAobWVzc2FnZS5lbGVtVHlwZSAhPSBudWxsICYmIG1lc3NhZ2UuaGFzT3duUHJvcGVydHkoXCJlbGVtVHlwZVwiKSlcbiAgICAgICAgICAgICAgICAgICAgaWYgKCEkdXRpbC5pc0ludGVnZXIobWVzc2FnZS5lbGVtVHlwZSkpXG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gXCJlbGVtVHlwZTogaW50ZWdlciBleHBlY3RlZFwiO1xuICAgICAgICAgICAgICAgIGlmIChtZXNzYWdlLnNoYXBlICE9IG51bGwgJiYgbWVzc2FnZS5oYXNPd25Qcm9wZXJ0eShcInNoYXBlXCIpKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBlcnJvciA9ICRyb290Lm9ubnguVGVuc29yU2hhcGVQcm90by52ZXJpZnkobWVzc2FnZS5zaGFwZSk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChlcnJvcilcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBcInNoYXBlLlwiICsgZXJyb3I7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgKiBDcmVhdGVzIGEgVGVuc29yIG1lc3NhZ2UgZnJvbSBhIHBsYWluIG9iamVjdC4gQWxzbyBjb252ZXJ0cyB2YWx1ZXMgdG8gdGhlaXIgcmVzcGVjdGl2ZSBpbnRlcm5hbCB0eXBlcy5cbiAgICAgICAgICAgICAqIEBmdW5jdGlvbiBmcm9tT2JqZWN0XG4gICAgICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueC5UeXBlUHJvdG8uVGVuc29yXG4gICAgICAgICAgICAgKiBAc3RhdGljXG4gICAgICAgICAgICAgKiBAcGFyYW0ge09iamVjdC48c3RyaW5nLCo+fSBvYmplY3QgUGxhaW4gb2JqZWN0XG4gICAgICAgICAgICAgKiBAcmV0dXJucyB7b25ueC5UeXBlUHJvdG8uVGVuc29yfSBUZW5zb3JcbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgVGVuc29yLmZyb21PYmplY3QgPSBmdW5jdGlvbiBmcm9tT2JqZWN0KG9iamVjdCkge1xuICAgICAgICAgICAgICAgIGlmIChvYmplY3QgaW5zdGFuY2VvZiAkcm9vdC5vbm54LlR5cGVQcm90by5UZW5zb3IpXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBvYmplY3Q7XG4gICAgICAgICAgICAgICAgdmFyIG1lc3NhZ2UgPSBuZXcgJHJvb3Qub25ueC5UeXBlUHJvdG8uVGVuc29yKCk7XG4gICAgICAgICAgICAgICAgaWYgKG9iamVjdC5lbGVtVHlwZSAhPSBudWxsKVxuICAgICAgICAgICAgICAgICAgICBtZXNzYWdlLmVsZW1UeXBlID0gb2JqZWN0LmVsZW1UeXBlIHwgMDtcbiAgICAgICAgICAgICAgICBpZiAob2JqZWN0LnNoYXBlICE9IG51bGwpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBvYmplY3Quc2hhcGUgIT09IFwib2JqZWN0XCIpXG4gICAgICAgICAgICAgICAgICAgICAgICB0aHJvdyBUeXBlRXJyb3IoXCIub25ueC5UeXBlUHJvdG8uVGVuc29yLnNoYXBlOiBvYmplY3QgZXhwZWN0ZWRcIik7XG4gICAgICAgICAgICAgICAgICAgIG1lc3NhZ2Uuc2hhcGUgPSAkcm9vdC5vbm54LlRlbnNvclNoYXBlUHJvdG8uZnJvbU9iamVjdChvYmplY3Quc2hhcGUpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm4gbWVzc2FnZTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIC8qKlxuICAgICAgICAgICAgICogQ3JlYXRlcyBhIHBsYWluIG9iamVjdCBmcm9tIGEgVGVuc29yIG1lc3NhZ2UuIEFsc28gY29udmVydHMgdmFsdWVzIHRvIG90aGVyIHR5cGVzIGlmIHNwZWNpZmllZC5cbiAgICAgICAgICAgICAqIEBmdW5jdGlvbiB0b09iamVjdFxuICAgICAgICAgICAgICogQG1lbWJlcm9mIG9ubnguVHlwZVByb3RvLlRlbnNvclxuICAgICAgICAgICAgICogQHN0YXRpY1xuICAgICAgICAgICAgICogQHBhcmFtIHtvbm54LlR5cGVQcm90by5UZW5zb3J9IG1lc3NhZ2UgVGVuc29yXG4gICAgICAgICAgICAgKiBAcGFyYW0geyRwcm90b2J1Zi5JQ29udmVyc2lvbk9wdGlvbnN9IFtvcHRpb25zXSBDb252ZXJzaW9uIG9wdGlvbnNcbiAgICAgICAgICAgICAqIEByZXR1cm5zIHtPYmplY3QuPHN0cmluZywqPn0gUGxhaW4gb2JqZWN0XG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIFRlbnNvci50b09iamVjdCA9IGZ1bmN0aW9uIHRvT2JqZWN0KG1lc3NhZ2UsIG9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICBpZiAoIW9wdGlvbnMpXG4gICAgICAgICAgICAgICAgICAgIG9wdGlvbnMgPSB7fTtcbiAgICAgICAgICAgICAgICB2YXIgb2JqZWN0ID0ge307XG4gICAgICAgICAgICAgICAgaWYgKG9wdGlvbnMuZGVmYXVsdHMpIHtcbiAgICAgICAgICAgICAgICAgICAgb2JqZWN0LmVsZW1UeXBlID0gMDtcbiAgICAgICAgICAgICAgICAgICAgb2JqZWN0LnNoYXBlID0gbnVsbDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKG1lc3NhZ2UuZWxlbVR5cGUgIT0gbnVsbCAmJiBtZXNzYWdlLmhhc093blByb3BlcnR5KFwiZWxlbVR5cGVcIikpXG4gICAgICAgICAgICAgICAgICAgIG9iamVjdC5lbGVtVHlwZSA9IG1lc3NhZ2UuZWxlbVR5cGU7XG4gICAgICAgICAgICAgICAgaWYgKG1lc3NhZ2Uuc2hhcGUgIT0gbnVsbCAmJiBtZXNzYWdlLmhhc093blByb3BlcnR5KFwic2hhcGVcIikpXG4gICAgICAgICAgICAgICAgICAgIG9iamVjdC5zaGFwZSA9ICRyb290Lm9ubnguVGVuc29yU2hhcGVQcm90by50b09iamVjdChtZXNzYWdlLnNoYXBlLCBvcHRpb25zKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gb2JqZWN0O1xuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgKiBDb252ZXJ0cyB0aGlzIFRlbnNvciB0byBKU09OLlxuICAgICAgICAgICAgICogQGZ1bmN0aW9uIHRvSlNPTlxuICAgICAgICAgICAgICogQG1lbWJlcm9mIG9ubnguVHlwZVByb3RvLlRlbnNvclxuICAgICAgICAgICAgICogQGluc3RhbmNlXG4gICAgICAgICAgICAgKiBAcmV0dXJucyB7T2JqZWN0LjxzdHJpbmcsKj59IEpTT04gb2JqZWN0XG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIFRlbnNvci5wcm90b3R5cGUudG9KU09OID0gZnVuY3Rpb24gdG9KU09OKCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmNvbnN0cnVjdG9yLnRvT2JqZWN0KHRoaXMsICRwcm90b2J1Zi51dGlsLnRvSlNPTk9wdGlvbnMpO1xuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgcmV0dXJuIFRlbnNvcjtcbiAgICAgICAgfSkoKTtcblxuICAgICAgICByZXR1cm4gVHlwZVByb3RvO1xuICAgIH0pKCk7XG5cbiAgICBvbm54Lk9wZXJhdG9yU2V0SWRQcm90byA9IChmdW5jdGlvbigpIHtcblxuICAgICAgICAvKipcbiAgICAgICAgICogUHJvcGVydGllcyBvZiBhbiBPcGVyYXRvclNldElkUHJvdG8uXG4gICAgICAgICAqIEBtZW1iZXJvZiBvbm54XG4gICAgICAgICAqIEBpbnRlcmZhY2UgSU9wZXJhdG9yU2V0SWRQcm90b1xuICAgICAgICAgKiBAcHJvcGVydHkge3N0cmluZ3xudWxsfSBbZG9tYWluXSBPcGVyYXRvclNldElkUHJvdG8gZG9tYWluXG4gICAgICAgICAqIEBwcm9wZXJ0eSB7bnVtYmVyfExvbmd8bnVsbH0gW3ZlcnNpb25dIE9wZXJhdG9yU2V0SWRQcm90byB2ZXJzaW9uXG4gICAgICAgICAqL1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBDb25zdHJ1Y3RzIGEgbmV3IE9wZXJhdG9yU2V0SWRQcm90by5cbiAgICAgICAgICogQG1lbWJlcm9mIG9ubnhcbiAgICAgICAgICogQGNsYXNzZGVzYyBSZXByZXNlbnRzIGFuIE9wZXJhdG9yU2V0SWRQcm90by5cbiAgICAgICAgICogQGltcGxlbWVudHMgSU9wZXJhdG9yU2V0SWRQcm90b1xuICAgICAgICAgKiBAY29uc3RydWN0b3JcbiAgICAgICAgICogQHBhcmFtIHtvbm54LklPcGVyYXRvclNldElkUHJvdG89fSBbcHJvcGVydGllc10gUHJvcGVydGllcyB0byBzZXRcbiAgICAgICAgICovXG4gICAgICAgIGZ1bmN0aW9uIE9wZXJhdG9yU2V0SWRQcm90byhwcm9wZXJ0aWVzKSB7XG4gICAgICAgICAgICBpZiAocHJvcGVydGllcylcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBrZXlzID0gT2JqZWN0LmtleXMocHJvcGVydGllcyksIGkgPSAwOyBpIDwga2V5cy5sZW5ndGg7ICsraSlcbiAgICAgICAgICAgICAgICAgICAgaWYgKHByb3BlcnRpZXNba2V5c1tpXV0gIT0gbnVsbClcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXNba2V5c1tpXV0gPSBwcm9wZXJ0aWVzW2tleXNbaV1dO1xuICAgICAgICB9XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIE9wZXJhdG9yU2V0SWRQcm90byBkb21haW4uXG4gICAgICAgICAqIEBtZW1iZXIge3N0cmluZ30gZG9tYWluXG4gICAgICAgICAqIEBtZW1iZXJvZiBvbm54Lk9wZXJhdG9yU2V0SWRQcm90b1xuICAgICAgICAgKiBAaW5zdGFuY2VcbiAgICAgICAgICovXG4gICAgICAgIE9wZXJhdG9yU2V0SWRQcm90by5wcm90b3R5cGUuZG9tYWluID0gXCJcIjtcblxuICAgICAgICAvKipcbiAgICAgICAgICogT3BlcmF0b3JTZXRJZFByb3RvIHZlcnNpb24uXG4gICAgICAgICAqIEBtZW1iZXIge251bWJlcnxMb25nfSB2ZXJzaW9uXG4gICAgICAgICAqIEBtZW1iZXJvZiBvbm54Lk9wZXJhdG9yU2V0SWRQcm90b1xuICAgICAgICAgKiBAaW5zdGFuY2VcbiAgICAgICAgICovXG4gICAgICAgIE9wZXJhdG9yU2V0SWRQcm90by5wcm90b3R5cGUudmVyc2lvbiA9ICR1dGlsLkxvbmcgPyAkdXRpbC5Mb25nLmZyb21CaXRzKDAsMCxmYWxzZSkgOiAwO1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBDcmVhdGVzIGEgbmV3IE9wZXJhdG9yU2V0SWRQcm90byBpbnN0YW5jZSB1c2luZyB0aGUgc3BlY2lmaWVkIHByb3BlcnRpZXMuXG4gICAgICAgICAqIEBmdW5jdGlvbiBjcmVhdGVcbiAgICAgICAgICogQG1lbWJlcm9mIG9ubnguT3BlcmF0b3JTZXRJZFByb3RvXG4gICAgICAgICAqIEBzdGF0aWNcbiAgICAgICAgICogQHBhcmFtIHtvbm54LklPcGVyYXRvclNldElkUHJvdG89fSBbcHJvcGVydGllc10gUHJvcGVydGllcyB0byBzZXRcbiAgICAgICAgICogQHJldHVybnMge29ubnguT3BlcmF0b3JTZXRJZFByb3RvfSBPcGVyYXRvclNldElkUHJvdG8gaW5zdGFuY2VcbiAgICAgICAgICovXG4gICAgICAgIE9wZXJhdG9yU2V0SWRQcm90by5jcmVhdGUgPSBmdW5jdGlvbiBjcmVhdGUocHJvcGVydGllcykge1xuICAgICAgICAgICAgcmV0dXJuIG5ldyBPcGVyYXRvclNldElkUHJvdG8ocHJvcGVydGllcyk7XG4gICAgICAgIH07XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEVuY29kZXMgdGhlIHNwZWNpZmllZCBPcGVyYXRvclNldElkUHJvdG8gbWVzc2FnZS4gRG9lcyBub3QgaW1wbGljaXRseSB7QGxpbmsgb25ueC5PcGVyYXRvclNldElkUHJvdG8udmVyaWZ5fHZlcmlmeX0gbWVzc2FnZXMuXG4gICAgICAgICAqIEBmdW5jdGlvbiBlbmNvZGVcbiAgICAgICAgICogQG1lbWJlcm9mIG9ubnguT3BlcmF0b3JTZXRJZFByb3RvXG4gICAgICAgICAqIEBzdGF0aWNcbiAgICAgICAgICogQHBhcmFtIHtvbm54LklPcGVyYXRvclNldElkUHJvdG99IG1lc3NhZ2UgT3BlcmF0b3JTZXRJZFByb3RvIG1lc3NhZ2Ugb3IgcGxhaW4gb2JqZWN0IHRvIGVuY29kZVxuICAgICAgICAgKiBAcGFyYW0geyRwcm90b2J1Zi5Xcml0ZXJ9IFt3cml0ZXJdIFdyaXRlciB0byBlbmNvZGUgdG9cbiAgICAgICAgICogQHJldHVybnMgeyRwcm90b2J1Zi5Xcml0ZXJ9IFdyaXRlclxuICAgICAgICAgKi9cbiAgICAgICAgT3BlcmF0b3JTZXRJZFByb3RvLmVuY29kZSA9IGZ1bmN0aW9uIGVuY29kZShtZXNzYWdlLCB3cml0ZXIpIHtcbiAgICAgICAgICAgIGlmICghd3JpdGVyKVxuICAgICAgICAgICAgICAgIHdyaXRlciA9ICRXcml0ZXIuY3JlYXRlKCk7XG4gICAgICAgICAgICBpZiAobWVzc2FnZS5kb21haW4gIT0gbnVsbCAmJiBtZXNzYWdlLmhhc093blByb3BlcnR5KFwiZG9tYWluXCIpKVxuICAgICAgICAgICAgICAgIHdyaXRlci51aW50MzIoLyogaWQgMSwgd2lyZVR5cGUgMiA9Ki8xMCkuc3RyaW5nKG1lc3NhZ2UuZG9tYWluKTtcbiAgICAgICAgICAgIGlmIChtZXNzYWdlLnZlcnNpb24gIT0gbnVsbCAmJiBtZXNzYWdlLmhhc093blByb3BlcnR5KFwidmVyc2lvblwiKSlcbiAgICAgICAgICAgICAgICB3cml0ZXIudWludDMyKC8qIGlkIDIsIHdpcmVUeXBlIDAgPSovMTYpLmludDY0KG1lc3NhZ2UudmVyc2lvbik7XG4gICAgICAgICAgICByZXR1cm4gd3JpdGVyO1xuICAgICAgICB9O1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBFbmNvZGVzIHRoZSBzcGVjaWZpZWQgT3BlcmF0b3JTZXRJZFByb3RvIG1lc3NhZ2UsIGxlbmd0aCBkZWxpbWl0ZWQuIERvZXMgbm90IGltcGxpY2l0bHkge0BsaW5rIG9ubnguT3BlcmF0b3JTZXRJZFByb3RvLnZlcmlmeXx2ZXJpZnl9IG1lc3NhZ2VzLlxuICAgICAgICAgKiBAZnVuY3Rpb24gZW5jb2RlRGVsaW1pdGVkXG4gICAgICAgICAqIEBtZW1iZXJvZiBvbm54Lk9wZXJhdG9yU2V0SWRQcm90b1xuICAgICAgICAgKiBAc3RhdGljXG4gICAgICAgICAqIEBwYXJhbSB7b25ueC5JT3BlcmF0b3JTZXRJZFByb3RvfSBtZXNzYWdlIE9wZXJhdG9yU2V0SWRQcm90byBtZXNzYWdlIG9yIHBsYWluIG9iamVjdCB0byBlbmNvZGVcbiAgICAgICAgICogQHBhcmFtIHskcHJvdG9idWYuV3JpdGVyfSBbd3JpdGVyXSBXcml0ZXIgdG8gZW5jb2RlIHRvXG4gICAgICAgICAqIEByZXR1cm5zIHskcHJvdG9idWYuV3JpdGVyfSBXcml0ZXJcbiAgICAgICAgICovXG4gICAgICAgIE9wZXJhdG9yU2V0SWRQcm90by5lbmNvZGVEZWxpbWl0ZWQgPSBmdW5jdGlvbiBlbmNvZGVEZWxpbWl0ZWQobWVzc2FnZSwgd3JpdGVyKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5lbmNvZGUobWVzc2FnZSwgd3JpdGVyKS5sZGVsaW0oKTtcbiAgICAgICAgfTtcblxuICAgICAgICAvKipcbiAgICAgICAgICogRGVjb2RlcyBhbiBPcGVyYXRvclNldElkUHJvdG8gbWVzc2FnZSBmcm9tIHRoZSBzcGVjaWZpZWQgcmVhZGVyIG9yIGJ1ZmZlci5cbiAgICAgICAgICogQGZ1bmN0aW9uIGRlY29kZVxuICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueC5PcGVyYXRvclNldElkUHJvdG9cbiAgICAgICAgICogQHN0YXRpY1xuICAgICAgICAgKiBAcGFyYW0geyRwcm90b2J1Zi5SZWFkZXJ8VWludDhBcnJheX0gcmVhZGVyIFJlYWRlciBvciBidWZmZXIgdG8gZGVjb2RlIGZyb21cbiAgICAgICAgICogQHBhcmFtIHtudW1iZXJ9IFtsZW5ndGhdIE1lc3NhZ2UgbGVuZ3RoIGlmIGtub3duIGJlZm9yZWhhbmRcbiAgICAgICAgICogQHJldHVybnMge29ubnguT3BlcmF0b3JTZXRJZFByb3RvfSBPcGVyYXRvclNldElkUHJvdG9cbiAgICAgICAgICogQHRocm93cyB7RXJyb3J9IElmIHRoZSBwYXlsb2FkIGlzIG5vdCBhIHJlYWRlciBvciB2YWxpZCBidWZmZXJcbiAgICAgICAgICogQHRocm93cyB7JHByb3RvYnVmLnV0aWwuUHJvdG9jb2xFcnJvcn0gSWYgcmVxdWlyZWQgZmllbGRzIGFyZSBtaXNzaW5nXG4gICAgICAgICAqL1xuICAgICAgICBPcGVyYXRvclNldElkUHJvdG8uZGVjb2RlID0gZnVuY3Rpb24gZGVjb2RlKHJlYWRlciwgbGVuZ3RoKSB7XG4gICAgICAgICAgICBpZiAoIShyZWFkZXIgaW5zdGFuY2VvZiAkUmVhZGVyKSlcbiAgICAgICAgICAgICAgICByZWFkZXIgPSAkUmVhZGVyLmNyZWF0ZShyZWFkZXIpO1xuICAgICAgICAgICAgdmFyIGVuZCA9IGxlbmd0aCA9PT0gdW5kZWZpbmVkID8gcmVhZGVyLmxlbiA6IHJlYWRlci5wb3MgKyBsZW5ndGgsIG1lc3NhZ2UgPSBuZXcgJHJvb3Qub25ueC5PcGVyYXRvclNldElkUHJvdG8oKTtcbiAgICAgICAgICAgIHdoaWxlIChyZWFkZXIucG9zIDwgZW5kKSB7XG4gICAgICAgICAgICAgICAgdmFyIHRhZyA9IHJlYWRlci51aW50MzIoKTtcbiAgICAgICAgICAgICAgICBzd2l0Y2ggKHRhZyA+Pj4gMykge1xuICAgICAgICAgICAgICAgIGNhc2UgMTpcbiAgICAgICAgICAgICAgICAgICAgbWVzc2FnZS5kb21haW4gPSByZWFkZXIuc3RyaW5nKCk7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgMjpcbiAgICAgICAgICAgICAgICAgICAgbWVzc2FnZS52ZXJzaW9uID0gcmVhZGVyLmludDY0KCk7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgICAgIHJlYWRlci5za2lwVHlwZSh0YWcgJiA3KTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIG1lc3NhZ2U7XG4gICAgICAgIH07XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIERlY29kZXMgYW4gT3BlcmF0b3JTZXRJZFByb3RvIG1lc3NhZ2UgZnJvbSB0aGUgc3BlY2lmaWVkIHJlYWRlciBvciBidWZmZXIsIGxlbmd0aCBkZWxpbWl0ZWQuXG4gICAgICAgICAqIEBmdW5jdGlvbiBkZWNvZGVEZWxpbWl0ZWRcbiAgICAgICAgICogQG1lbWJlcm9mIG9ubnguT3BlcmF0b3JTZXRJZFByb3RvXG4gICAgICAgICAqIEBzdGF0aWNcbiAgICAgICAgICogQHBhcmFtIHskcHJvdG9idWYuUmVhZGVyfFVpbnQ4QXJyYXl9IHJlYWRlciBSZWFkZXIgb3IgYnVmZmVyIHRvIGRlY29kZSBmcm9tXG4gICAgICAgICAqIEByZXR1cm5zIHtvbm54Lk9wZXJhdG9yU2V0SWRQcm90b30gT3BlcmF0b3JTZXRJZFByb3RvXG4gICAgICAgICAqIEB0aHJvd3Mge0Vycm9yfSBJZiB0aGUgcGF5bG9hZCBpcyBub3QgYSByZWFkZXIgb3IgdmFsaWQgYnVmZmVyXG4gICAgICAgICAqIEB0aHJvd3MgeyRwcm90b2J1Zi51dGlsLlByb3RvY29sRXJyb3J9IElmIHJlcXVpcmVkIGZpZWxkcyBhcmUgbWlzc2luZ1xuICAgICAgICAgKi9cbiAgICAgICAgT3BlcmF0b3JTZXRJZFByb3RvLmRlY29kZURlbGltaXRlZCA9IGZ1bmN0aW9uIGRlY29kZURlbGltaXRlZChyZWFkZXIpIHtcbiAgICAgICAgICAgIGlmICghKHJlYWRlciBpbnN0YW5jZW9mICRSZWFkZXIpKVxuICAgICAgICAgICAgICAgIHJlYWRlciA9IG5ldyAkUmVhZGVyKHJlYWRlcik7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5kZWNvZGUocmVhZGVyLCByZWFkZXIudWludDMyKCkpO1xuICAgICAgICB9O1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBWZXJpZmllcyBhbiBPcGVyYXRvclNldElkUHJvdG8gbWVzc2FnZS5cbiAgICAgICAgICogQGZ1bmN0aW9uIHZlcmlmeVxuICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueC5PcGVyYXRvclNldElkUHJvdG9cbiAgICAgICAgICogQHN0YXRpY1xuICAgICAgICAgKiBAcGFyYW0ge09iamVjdC48c3RyaW5nLCo+fSBtZXNzYWdlIFBsYWluIG9iamVjdCB0byB2ZXJpZnlcbiAgICAgICAgICogQHJldHVybnMge3N0cmluZ3xudWxsfSBgbnVsbGAgaWYgdmFsaWQsIG90aGVyd2lzZSB0aGUgcmVhc29uIHdoeSBpdCBpcyBub3RcbiAgICAgICAgICovXG4gICAgICAgIE9wZXJhdG9yU2V0SWRQcm90by52ZXJpZnkgPSBmdW5jdGlvbiB2ZXJpZnkobWVzc2FnZSkge1xuICAgICAgICAgICAgaWYgKHR5cGVvZiBtZXNzYWdlICE9PSBcIm9iamVjdFwiIHx8IG1lc3NhZ2UgPT09IG51bGwpXG4gICAgICAgICAgICAgICAgcmV0dXJuIFwib2JqZWN0IGV4cGVjdGVkXCI7XG4gICAgICAgICAgICBpZiAobWVzc2FnZS5kb21haW4gIT0gbnVsbCAmJiBtZXNzYWdlLmhhc093blByb3BlcnR5KFwiZG9tYWluXCIpKVxuICAgICAgICAgICAgICAgIGlmICghJHV0aWwuaXNTdHJpbmcobWVzc2FnZS5kb21haW4pKVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gXCJkb21haW46IHN0cmluZyBleHBlY3RlZFwiO1xuICAgICAgICAgICAgaWYgKG1lc3NhZ2UudmVyc2lvbiAhPSBudWxsICYmIG1lc3NhZ2UuaGFzT3duUHJvcGVydHkoXCJ2ZXJzaW9uXCIpKVxuICAgICAgICAgICAgICAgIGlmICghJHV0aWwuaXNJbnRlZ2VyKG1lc3NhZ2UudmVyc2lvbikgJiYgIShtZXNzYWdlLnZlcnNpb24gJiYgJHV0aWwuaXNJbnRlZ2VyKG1lc3NhZ2UudmVyc2lvbi5sb3cpICYmICR1dGlsLmlzSW50ZWdlcihtZXNzYWdlLnZlcnNpb24uaGlnaCkpKVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gXCJ2ZXJzaW9uOiBpbnRlZ2VyfExvbmcgZXhwZWN0ZWRcIjtcbiAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9O1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBDcmVhdGVzIGFuIE9wZXJhdG9yU2V0SWRQcm90byBtZXNzYWdlIGZyb20gYSBwbGFpbiBvYmplY3QuIEFsc28gY29udmVydHMgdmFsdWVzIHRvIHRoZWlyIHJlc3BlY3RpdmUgaW50ZXJuYWwgdHlwZXMuXG4gICAgICAgICAqIEBmdW5jdGlvbiBmcm9tT2JqZWN0XG4gICAgICAgICAqIEBtZW1iZXJvZiBvbm54Lk9wZXJhdG9yU2V0SWRQcm90b1xuICAgICAgICAgKiBAc3RhdGljXG4gICAgICAgICAqIEBwYXJhbSB7T2JqZWN0LjxzdHJpbmcsKj59IG9iamVjdCBQbGFpbiBvYmplY3RcbiAgICAgICAgICogQHJldHVybnMge29ubnguT3BlcmF0b3JTZXRJZFByb3RvfSBPcGVyYXRvclNldElkUHJvdG9cbiAgICAgICAgICovXG4gICAgICAgIE9wZXJhdG9yU2V0SWRQcm90by5mcm9tT2JqZWN0ID0gZnVuY3Rpb24gZnJvbU9iamVjdChvYmplY3QpIHtcbiAgICAgICAgICAgIGlmIChvYmplY3QgaW5zdGFuY2VvZiAkcm9vdC5vbm54Lk9wZXJhdG9yU2V0SWRQcm90bylcbiAgICAgICAgICAgICAgICByZXR1cm4gb2JqZWN0O1xuICAgICAgICAgICAgdmFyIG1lc3NhZ2UgPSBuZXcgJHJvb3Qub25ueC5PcGVyYXRvclNldElkUHJvdG8oKTtcbiAgICAgICAgICAgIGlmIChvYmplY3QuZG9tYWluICE9IG51bGwpXG4gICAgICAgICAgICAgICAgbWVzc2FnZS5kb21haW4gPSBTdHJpbmcob2JqZWN0LmRvbWFpbik7XG4gICAgICAgICAgICBpZiAob2JqZWN0LnZlcnNpb24gIT0gbnVsbClcbiAgICAgICAgICAgICAgICBpZiAoJHV0aWwuTG9uZylcbiAgICAgICAgICAgICAgICAgICAgKG1lc3NhZ2UudmVyc2lvbiA9ICR1dGlsLkxvbmcuZnJvbVZhbHVlKG9iamVjdC52ZXJzaW9uKSkudW5zaWduZWQgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICBlbHNlIGlmICh0eXBlb2Ygb2JqZWN0LnZlcnNpb24gPT09IFwic3RyaW5nXCIpXG4gICAgICAgICAgICAgICAgICAgIG1lc3NhZ2UudmVyc2lvbiA9IHBhcnNlSW50KG9iamVjdC52ZXJzaW9uLCAxMCk7XG4gICAgICAgICAgICAgICAgZWxzZSBpZiAodHlwZW9mIG9iamVjdC52ZXJzaW9uID09PSBcIm51bWJlclwiKVxuICAgICAgICAgICAgICAgICAgICBtZXNzYWdlLnZlcnNpb24gPSBvYmplY3QudmVyc2lvbjtcbiAgICAgICAgICAgICAgICBlbHNlIGlmICh0eXBlb2Ygb2JqZWN0LnZlcnNpb24gPT09IFwib2JqZWN0XCIpXG4gICAgICAgICAgICAgICAgICAgIG1lc3NhZ2UudmVyc2lvbiA9IG5ldyAkdXRpbC5Mb25nQml0cyhvYmplY3QudmVyc2lvbi5sb3cgPj4+IDAsIG9iamVjdC52ZXJzaW9uLmhpZ2ggPj4+IDApLnRvTnVtYmVyKCk7XG4gICAgICAgICAgICByZXR1cm4gbWVzc2FnZTtcbiAgICAgICAgfTtcblxuICAgICAgICAvKipcbiAgICAgICAgICogQ3JlYXRlcyBhIHBsYWluIG9iamVjdCBmcm9tIGFuIE9wZXJhdG9yU2V0SWRQcm90byBtZXNzYWdlLiBBbHNvIGNvbnZlcnRzIHZhbHVlcyB0byBvdGhlciB0eXBlcyBpZiBzcGVjaWZpZWQuXG4gICAgICAgICAqIEBmdW5jdGlvbiB0b09iamVjdFxuICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueC5PcGVyYXRvclNldElkUHJvdG9cbiAgICAgICAgICogQHN0YXRpY1xuICAgICAgICAgKiBAcGFyYW0ge29ubnguT3BlcmF0b3JTZXRJZFByb3RvfSBtZXNzYWdlIE9wZXJhdG9yU2V0SWRQcm90b1xuICAgICAgICAgKiBAcGFyYW0geyRwcm90b2J1Zi5JQ29udmVyc2lvbk9wdGlvbnN9IFtvcHRpb25zXSBDb252ZXJzaW9uIG9wdGlvbnNcbiAgICAgICAgICogQHJldHVybnMge09iamVjdC48c3RyaW5nLCo+fSBQbGFpbiBvYmplY3RcbiAgICAgICAgICovXG4gICAgICAgIE9wZXJhdG9yU2V0SWRQcm90by50b09iamVjdCA9IGZ1bmN0aW9uIHRvT2JqZWN0KG1lc3NhZ2UsIG9wdGlvbnMpIHtcbiAgICAgICAgICAgIGlmICghb3B0aW9ucylcbiAgICAgICAgICAgICAgICBvcHRpb25zID0ge307XG4gICAgICAgICAgICB2YXIgb2JqZWN0ID0ge307XG4gICAgICAgICAgICBpZiAob3B0aW9ucy5kZWZhdWx0cykge1xuICAgICAgICAgICAgICAgIG9iamVjdC5kb21haW4gPSBcIlwiO1xuICAgICAgICAgICAgICAgIGlmICgkdXRpbC5Mb25nKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBsb25nID0gbmV3ICR1dGlsLkxvbmcoMCwgMCwgZmFsc2UpO1xuICAgICAgICAgICAgICAgICAgICBvYmplY3QudmVyc2lvbiA9IG9wdGlvbnMubG9uZ3MgPT09IFN0cmluZyA/IGxvbmcudG9TdHJpbmcoKSA6IG9wdGlvbnMubG9uZ3MgPT09IE51bWJlciA/IGxvbmcudG9OdW1iZXIoKSA6IGxvbmc7XG4gICAgICAgICAgICAgICAgfSBlbHNlXG4gICAgICAgICAgICAgICAgICAgIG9iamVjdC52ZXJzaW9uID0gb3B0aW9ucy5sb25ncyA9PT0gU3RyaW5nID8gXCIwXCIgOiAwO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG1lc3NhZ2UuZG9tYWluICE9IG51bGwgJiYgbWVzc2FnZS5oYXNPd25Qcm9wZXJ0eShcImRvbWFpblwiKSlcbiAgICAgICAgICAgICAgICBvYmplY3QuZG9tYWluID0gbWVzc2FnZS5kb21haW47XG4gICAgICAgICAgICBpZiAobWVzc2FnZS52ZXJzaW9uICE9IG51bGwgJiYgbWVzc2FnZS5oYXNPd25Qcm9wZXJ0eShcInZlcnNpb25cIikpXG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBtZXNzYWdlLnZlcnNpb24gPT09IFwibnVtYmVyXCIpXG4gICAgICAgICAgICAgICAgICAgIG9iamVjdC52ZXJzaW9uID0gb3B0aW9ucy5sb25ncyA9PT0gU3RyaW5nID8gU3RyaW5nKG1lc3NhZ2UudmVyc2lvbikgOiBtZXNzYWdlLnZlcnNpb247XG4gICAgICAgICAgICAgICAgZWxzZVxuICAgICAgICAgICAgICAgICAgICBvYmplY3QudmVyc2lvbiA9IG9wdGlvbnMubG9uZ3MgPT09IFN0cmluZyA/ICR1dGlsLkxvbmcucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwobWVzc2FnZS52ZXJzaW9uKSA6IG9wdGlvbnMubG9uZ3MgPT09IE51bWJlciA/IG5ldyAkdXRpbC5Mb25nQml0cyhtZXNzYWdlLnZlcnNpb24ubG93ID4+PiAwLCBtZXNzYWdlLnZlcnNpb24uaGlnaCA+Pj4gMCkudG9OdW1iZXIoKSA6IG1lc3NhZ2UudmVyc2lvbjtcbiAgICAgICAgICAgIHJldHVybiBvYmplY3Q7XG4gICAgICAgIH07XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIENvbnZlcnRzIHRoaXMgT3BlcmF0b3JTZXRJZFByb3RvIHRvIEpTT04uXG4gICAgICAgICAqIEBmdW5jdGlvbiB0b0pTT05cbiAgICAgICAgICogQG1lbWJlcm9mIG9ubnguT3BlcmF0b3JTZXRJZFByb3RvXG4gICAgICAgICAqIEBpbnN0YW5jZVxuICAgICAgICAgKiBAcmV0dXJucyB7T2JqZWN0LjxzdHJpbmcsKj59IEpTT04gb2JqZWN0XG4gICAgICAgICAqL1xuICAgICAgICBPcGVyYXRvclNldElkUHJvdG8ucHJvdG90eXBlLnRvSlNPTiA9IGZ1bmN0aW9uIHRvSlNPTigpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmNvbnN0cnVjdG9yLnRvT2JqZWN0KHRoaXMsICRwcm90b2J1Zi51dGlsLnRvSlNPTk9wdGlvbnMpO1xuICAgICAgICB9O1xuXG4gICAgICAgIHJldHVybiBPcGVyYXRvclNldElkUHJvdG87XG4gICAgfSkoKTtcblxuICAgIHJldHVybiBvbm54O1xufSkoKTtcblxubW9kdWxlLmV4cG9ydHMgPSAkcm9vdDtcbiIsIi8vIG1pbmltYWwgbGlicmFyeSBlbnRyeSBwb2ludC5cblxuXCJ1c2Ugc3RyaWN0XCI7XG5tb2R1bGUuZXhwb3J0cyA9IHJlcXVpcmUoXCIuL3NyYy9pbmRleC1taW5pbWFsXCIpO1xuIiwiXCJ1c2Ugc3RyaWN0XCI7XG52YXIgcHJvdG9idWYgPSBleHBvcnRzO1xuXG4vKipcbiAqIEJ1aWxkIHR5cGUsIG9uZSBvZiBgXCJmdWxsXCJgLCBgXCJsaWdodFwiYCBvciBgXCJtaW5pbWFsXCJgLlxuICogQG5hbWUgYnVpbGRcbiAqIEB0eXBlIHtzdHJpbmd9XG4gKiBAY29uc3RcbiAqL1xucHJvdG9idWYuYnVpbGQgPSBcIm1pbmltYWxcIjtcblxuLy8gU2VyaWFsaXphdGlvblxucHJvdG9idWYuV3JpdGVyICAgICAgID0gcmVxdWlyZShcIi4vd3JpdGVyXCIpO1xucHJvdG9idWYuQnVmZmVyV3JpdGVyID0gcmVxdWlyZShcIi4vd3JpdGVyX2J1ZmZlclwiKTtcbnByb3RvYnVmLlJlYWRlciAgICAgICA9IHJlcXVpcmUoXCIuL3JlYWRlclwiKTtcbnByb3RvYnVmLkJ1ZmZlclJlYWRlciA9IHJlcXVpcmUoXCIuL3JlYWRlcl9idWZmZXJcIik7XG5cbi8vIFV0aWxpdHlcbnByb3RvYnVmLnV0aWwgICAgICAgICA9IHJlcXVpcmUoXCIuL3V0aWwvbWluaW1hbFwiKTtcbnByb3RvYnVmLnJwYyAgICAgICAgICA9IHJlcXVpcmUoXCIuL3JwY1wiKTtcbnByb3RvYnVmLnJvb3RzICAgICAgICA9IHJlcXVpcmUoXCIuL3Jvb3RzXCIpO1xucHJvdG9idWYuY29uZmlndXJlICAgID0gY29uZmlndXJlO1xuXG4vKiBpc3RhbmJ1bCBpZ25vcmUgbmV4dCAqL1xuLyoqXG4gKiBSZWNvbmZpZ3VyZXMgdGhlIGxpYnJhcnkgYWNjb3JkaW5nIHRvIHRoZSBlbnZpcm9ubWVudC5cbiAqIEByZXR1cm5zIHt1bmRlZmluZWR9XG4gKi9cbmZ1bmN0aW9uIGNvbmZpZ3VyZSgpIHtcbiAgICBwcm90b2J1Zi51dGlsLl9jb25maWd1cmUoKTtcbiAgICBwcm90b2J1Zi5Xcml0ZXIuX2NvbmZpZ3VyZShwcm90b2J1Zi5CdWZmZXJXcml0ZXIpO1xuICAgIHByb3RvYnVmLlJlYWRlci5fY29uZmlndXJlKHByb3RvYnVmLkJ1ZmZlclJlYWRlcik7XG59XG5cbi8vIFNldCB1cCBidWZmZXIgdXRpbGl0eSBhY2NvcmRpbmcgdG8gdGhlIGVudmlyb25tZW50XG5jb25maWd1cmUoKTtcbiIsIlwidXNlIHN0cmljdFwiO1xubW9kdWxlLmV4cG9ydHMgPSBSZWFkZXI7XG5cbnZhciB1dGlsICAgICAgPSByZXF1aXJlKFwiLi91dGlsL21pbmltYWxcIik7XG5cbnZhciBCdWZmZXJSZWFkZXI7IC8vIGN5Y2xpY1xuXG52YXIgTG9uZ0JpdHMgID0gdXRpbC5Mb25nQml0cyxcbiAgICB1dGY4ICAgICAgPSB1dGlsLnV0Zjg7XG5cbi8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0ICovXG5mdW5jdGlvbiBpbmRleE91dE9mUmFuZ2UocmVhZGVyLCB3cml0ZUxlbmd0aCkge1xuICAgIHJldHVybiBSYW5nZUVycm9yKFwiaW5kZXggb3V0IG9mIHJhbmdlOiBcIiArIHJlYWRlci5wb3MgKyBcIiArIFwiICsgKHdyaXRlTGVuZ3RoIHx8IDEpICsgXCIgPiBcIiArIHJlYWRlci5sZW4pO1xufVxuXG4vKipcbiAqIENvbnN0cnVjdHMgYSBuZXcgcmVhZGVyIGluc3RhbmNlIHVzaW5nIHRoZSBzcGVjaWZpZWQgYnVmZmVyLlxuICogQGNsYXNzZGVzYyBXaXJlIGZvcm1hdCByZWFkZXIgdXNpbmcgYFVpbnQ4QXJyYXlgIGlmIGF2YWlsYWJsZSwgb3RoZXJ3aXNlIGBBcnJheWAuXG4gKiBAY29uc3RydWN0b3JcbiAqIEBwYXJhbSB7VWludDhBcnJheX0gYnVmZmVyIEJ1ZmZlciB0byByZWFkIGZyb21cbiAqL1xuZnVuY3Rpb24gUmVhZGVyKGJ1ZmZlcikge1xuXG4gICAgLyoqXG4gICAgICogUmVhZCBidWZmZXIuXG4gICAgICogQHR5cGUge1VpbnQ4QXJyYXl9XG4gICAgICovXG4gICAgdGhpcy5idWYgPSBidWZmZXI7XG5cbiAgICAvKipcbiAgICAgKiBSZWFkIGJ1ZmZlciBwb3NpdGlvbi5cbiAgICAgKiBAdHlwZSB7bnVtYmVyfVxuICAgICAqL1xuICAgIHRoaXMucG9zID0gMDtcblxuICAgIC8qKlxuICAgICAqIFJlYWQgYnVmZmVyIGxlbmd0aC5cbiAgICAgKiBAdHlwZSB7bnVtYmVyfVxuICAgICAqL1xuICAgIHRoaXMubGVuID0gYnVmZmVyLmxlbmd0aDtcbn1cblxudmFyIGNyZWF0ZV9hcnJheSA9IHR5cGVvZiBVaW50OEFycmF5ICE9PSBcInVuZGVmaW5lZFwiXG4gICAgPyBmdW5jdGlvbiBjcmVhdGVfdHlwZWRfYXJyYXkoYnVmZmVyKSB7XG4gICAgICAgIGlmIChidWZmZXIgaW5zdGFuY2VvZiBVaW50OEFycmF5IHx8IEFycmF5LmlzQXJyYXkoYnVmZmVyKSlcbiAgICAgICAgICAgIHJldHVybiBuZXcgUmVhZGVyKGJ1ZmZlcik7XG4gICAgICAgIHRocm93IEVycm9yKFwiaWxsZWdhbCBidWZmZXJcIik7XG4gICAgfVxuICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0ICovXG4gICAgOiBmdW5jdGlvbiBjcmVhdGVfYXJyYXkoYnVmZmVyKSB7XG4gICAgICAgIGlmIChBcnJheS5pc0FycmF5KGJ1ZmZlcikpXG4gICAgICAgICAgICByZXR1cm4gbmV3IFJlYWRlcihidWZmZXIpO1xuICAgICAgICB0aHJvdyBFcnJvcihcImlsbGVnYWwgYnVmZmVyXCIpO1xuICAgIH07XG5cbnZhciBjcmVhdGUgPSBmdW5jdGlvbiBjcmVhdGUoKSB7XG4gICAgcmV0dXJuIHV0aWwuQnVmZmVyXG4gICAgICAgID8gZnVuY3Rpb24gY3JlYXRlX2J1ZmZlcl9zZXR1cChidWZmZXIpIHtcbiAgICAgICAgICAgIHJldHVybiAoUmVhZGVyLmNyZWF0ZSA9IGZ1bmN0aW9uIGNyZWF0ZV9idWZmZXIoYnVmZmVyKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHV0aWwuQnVmZmVyLmlzQnVmZmVyKGJ1ZmZlcilcbiAgICAgICAgICAgICAgICAgICAgPyBuZXcgQnVmZmVyUmVhZGVyKGJ1ZmZlcilcbiAgICAgICAgICAgICAgICAgICAgLyogaXN0YW5idWwgaWdub3JlIG5leHQgKi9cbiAgICAgICAgICAgICAgICAgICAgOiBjcmVhdGVfYXJyYXkoYnVmZmVyKTtcbiAgICAgICAgICAgIH0pKGJ1ZmZlcik7XG4gICAgICAgIH1cbiAgICAgICAgLyogaXN0YW5idWwgaWdub3JlIG5leHQgKi9cbiAgICAgICAgOiBjcmVhdGVfYXJyYXk7XG59O1xuXG4vKipcbiAqIENyZWF0ZXMgYSBuZXcgcmVhZGVyIHVzaW5nIHRoZSBzcGVjaWZpZWQgYnVmZmVyLlxuICogQGZ1bmN0aW9uXG4gKiBAcGFyYW0ge1VpbnQ4QXJyYXl8QnVmZmVyfSBidWZmZXIgQnVmZmVyIHRvIHJlYWQgZnJvbVxuICogQHJldHVybnMge1JlYWRlcnxCdWZmZXJSZWFkZXJ9IEEge0BsaW5rIEJ1ZmZlclJlYWRlcn0gaWYgYGJ1ZmZlcmAgaXMgYSBCdWZmZXIsIG90aGVyd2lzZSBhIHtAbGluayBSZWFkZXJ9XG4gKiBAdGhyb3dzIHtFcnJvcn0gSWYgYGJ1ZmZlcmAgaXMgbm90IGEgdmFsaWQgYnVmZmVyXG4gKi9cblJlYWRlci5jcmVhdGUgPSBjcmVhdGUoKTtcblxuUmVhZGVyLnByb3RvdHlwZS5fc2xpY2UgPSB1dGlsLkFycmF5LnByb3RvdHlwZS5zdWJhcnJheSB8fCAvKiBpc3RhbmJ1bCBpZ25vcmUgbmV4dCAqLyB1dGlsLkFycmF5LnByb3RvdHlwZS5zbGljZTtcblxuLyoqXG4gKiBSZWFkcyBhIHZhcmludCBhcyBhbiB1bnNpZ25lZCAzMiBiaXQgdmFsdWUuXG4gKiBAZnVuY3Rpb25cbiAqIEByZXR1cm5zIHtudW1iZXJ9IFZhbHVlIHJlYWRcbiAqL1xuUmVhZGVyLnByb3RvdHlwZS51aW50MzIgPSAoZnVuY3Rpb24gcmVhZF91aW50MzJfc2V0dXAoKSB7XG4gICAgdmFyIHZhbHVlID0gNDI5NDk2NzI5NTsgLy8gb3B0aW1pemVyIHR5cGUtaGludCwgdGVuZHMgdG8gZGVvcHQgb3RoZXJ3aXNlICg/ISlcbiAgICByZXR1cm4gZnVuY3Rpb24gcmVhZF91aW50MzIoKSB7XG4gICAgICAgIHZhbHVlID0gKCAgICAgICAgIHRoaXMuYnVmW3RoaXMucG9zXSAmIDEyNyAgICAgICApID4+PiAwOyBpZiAodGhpcy5idWZbdGhpcy5wb3MrK10gPCAxMjgpIHJldHVybiB2YWx1ZTtcbiAgICAgICAgdmFsdWUgPSAodmFsdWUgfCAodGhpcy5idWZbdGhpcy5wb3NdICYgMTI3KSA8PCAgNykgPj4+IDA7IGlmICh0aGlzLmJ1Zlt0aGlzLnBvcysrXSA8IDEyOCkgcmV0dXJuIHZhbHVlO1xuICAgICAgICB2YWx1ZSA9ICh2YWx1ZSB8ICh0aGlzLmJ1Zlt0aGlzLnBvc10gJiAxMjcpIDw8IDE0KSA+Pj4gMDsgaWYgKHRoaXMuYnVmW3RoaXMucG9zKytdIDwgMTI4KSByZXR1cm4gdmFsdWU7XG4gICAgICAgIHZhbHVlID0gKHZhbHVlIHwgKHRoaXMuYnVmW3RoaXMucG9zXSAmIDEyNykgPDwgMjEpID4+PiAwOyBpZiAodGhpcy5idWZbdGhpcy5wb3MrK10gPCAxMjgpIHJldHVybiB2YWx1ZTtcbiAgICAgICAgdmFsdWUgPSAodmFsdWUgfCAodGhpcy5idWZbdGhpcy5wb3NdICYgIDE1KSA8PCAyOCkgPj4+IDA7IGlmICh0aGlzLmJ1Zlt0aGlzLnBvcysrXSA8IDEyOCkgcmV0dXJuIHZhbHVlO1xuXG4gICAgICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBpZiAqL1xuICAgICAgICBpZiAoKHRoaXMucG9zICs9IDUpID4gdGhpcy5sZW4pIHtcbiAgICAgICAgICAgIHRoaXMucG9zID0gdGhpcy5sZW47XG4gICAgICAgICAgICB0aHJvdyBpbmRleE91dE9mUmFuZ2UodGhpcywgMTApO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB2YWx1ZTtcbiAgICB9O1xufSkoKTtcblxuLyoqXG4gKiBSZWFkcyBhIHZhcmludCBhcyBhIHNpZ25lZCAzMiBiaXQgdmFsdWUuXG4gKiBAcmV0dXJucyB7bnVtYmVyfSBWYWx1ZSByZWFkXG4gKi9cblJlYWRlci5wcm90b3R5cGUuaW50MzIgPSBmdW5jdGlvbiByZWFkX2ludDMyKCkge1xuICAgIHJldHVybiB0aGlzLnVpbnQzMigpIHwgMDtcbn07XG5cbi8qKlxuICogUmVhZHMgYSB6aWctemFnIGVuY29kZWQgdmFyaW50IGFzIGEgc2lnbmVkIDMyIGJpdCB2YWx1ZS5cbiAqIEByZXR1cm5zIHtudW1iZXJ9IFZhbHVlIHJlYWRcbiAqL1xuUmVhZGVyLnByb3RvdHlwZS5zaW50MzIgPSBmdW5jdGlvbiByZWFkX3NpbnQzMigpIHtcbiAgICB2YXIgdmFsdWUgPSB0aGlzLnVpbnQzMigpO1xuICAgIHJldHVybiB2YWx1ZSA+Pj4gMSBeIC0odmFsdWUgJiAxKSB8IDA7XG59O1xuXG4vKiBlc2xpbnQtZGlzYWJsZSBuby1pbnZhbGlkLXRoaXMgKi9cblxuZnVuY3Rpb24gcmVhZExvbmdWYXJpbnQoKSB7XG4gICAgLy8gdGVuZHMgdG8gZGVvcHQgd2l0aCBsb2NhbCB2YXJzIGZvciBvY3RldCBldGMuXG4gICAgdmFyIGJpdHMgPSBuZXcgTG9uZ0JpdHMoMCwgMCk7XG4gICAgdmFyIGkgPSAwO1xuICAgIGlmICh0aGlzLmxlbiAtIHRoaXMucG9zID4gNCkgeyAvLyBmYXN0IHJvdXRlIChsbylcbiAgICAgICAgZm9yICg7IGkgPCA0OyArK2kpIHtcbiAgICAgICAgICAgIC8vIDFzdC4uNHRoXG4gICAgICAgICAgICBiaXRzLmxvID0gKGJpdHMubG8gfCAodGhpcy5idWZbdGhpcy5wb3NdICYgMTI3KSA8PCBpICogNykgPj4+IDA7XG4gICAgICAgICAgICBpZiAodGhpcy5idWZbdGhpcy5wb3MrK10gPCAxMjgpXG4gICAgICAgICAgICAgICAgcmV0dXJuIGJpdHM7XG4gICAgICAgIH1cbiAgICAgICAgLy8gNXRoXG4gICAgICAgIGJpdHMubG8gPSAoYml0cy5sbyB8ICh0aGlzLmJ1Zlt0aGlzLnBvc10gJiAxMjcpIDw8IDI4KSA+Pj4gMDtcbiAgICAgICAgYml0cy5oaSA9IChiaXRzLmhpIHwgKHRoaXMuYnVmW3RoaXMucG9zXSAmIDEyNykgPj4gIDQpID4+PiAwO1xuICAgICAgICBpZiAodGhpcy5idWZbdGhpcy5wb3MrK10gPCAxMjgpXG4gICAgICAgICAgICByZXR1cm4gYml0cztcbiAgICAgICAgaSA9IDA7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgZm9yICg7IGkgPCAzOyArK2kpIHtcbiAgICAgICAgICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBpZiAqL1xuICAgICAgICAgICAgaWYgKHRoaXMucG9zID49IHRoaXMubGVuKVxuICAgICAgICAgICAgICAgIHRocm93IGluZGV4T3V0T2ZSYW5nZSh0aGlzKTtcbiAgICAgICAgICAgIC8vIDFzdC4uM3RoXG4gICAgICAgICAgICBiaXRzLmxvID0gKGJpdHMubG8gfCAodGhpcy5idWZbdGhpcy5wb3NdICYgMTI3KSA8PCBpICogNykgPj4+IDA7XG4gICAgICAgICAgICBpZiAodGhpcy5idWZbdGhpcy5wb3MrK10gPCAxMjgpXG4gICAgICAgICAgICAgICAgcmV0dXJuIGJpdHM7XG4gICAgICAgIH1cbiAgICAgICAgLy8gNHRoXG4gICAgICAgIGJpdHMubG8gPSAoYml0cy5sbyB8ICh0aGlzLmJ1Zlt0aGlzLnBvcysrXSAmIDEyNykgPDwgaSAqIDcpID4+PiAwO1xuICAgICAgICByZXR1cm4gYml0cztcbiAgICB9XG4gICAgaWYgKHRoaXMubGVuIC0gdGhpcy5wb3MgPiA0KSB7IC8vIGZhc3Qgcm91dGUgKGhpKVxuICAgICAgICBmb3IgKDsgaSA8IDU7ICsraSkge1xuICAgICAgICAgICAgLy8gNnRoLi4xMHRoXG4gICAgICAgICAgICBiaXRzLmhpID0gKGJpdHMuaGkgfCAodGhpcy5idWZbdGhpcy5wb3NdICYgMTI3KSA8PCBpICogNyArIDMpID4+PiAwO1xuICAgICAgICAgICAgaWYgKHRoaXMuYnVmW3RoaXMucG9zKytdIDwgMTI4KVxuICAgICAgICAgICAgICAgIHJldHVybiBiaXRzO1xuICAgICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgICAgZm9yICg7IGkgPCA1OyArK2kpIHtcbiAgICAgICAgICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBpZiAqL1xuICAgICAgICAgICAgaWYgKHRoaXMucG9zID49IHRoaXMubGVuKVxuICAgICAgICAgICAgICAgIHRocm93IGluZGV4T3V0T2ZSYW5nZSh0aGlzKTtcbiAgICAgICAgICAgIC8vIDZ0aC4uMTB0aFxuICAgICAgICAgICAgYml0cy5oaSA9IChiaXRzLmhpIHwgKHRoaXMuYnVmW3RoaXMucG9zXSAmIDEyNykgPDwgaSAqIDcgKyAzKSA+Pj4gMDtcbiAgICAgICAgICAgIGlmICh0aGlzLmJ1Zlt0aGlzLnBvcysrXSA8IDEyOClcbiAgICAgICAgICAgICAgICByZXR1cm4gYml0cztcbiAgICAgICAgfVxuICAgIH1cbiAgICAvKiBpc3RhbmJ1bCBpZ25vcmUgbmV4dCAqL1xuICAgIHRocm93IEVycm9yKFwiaW52YWxpZCB2YXJpbnQgZW5jb2RpbmdcIik7XG59XG5cbi8qIGVzbGludC1lbmFibGUgbm8taW52YWxpZC10aGlzICovXG5cbi8qKlxuICogUmVhZHMgYSB2YXJpbnQgYXMgYSBzaWduZWQgNjQgYml0IHZhbHVlLlxuICogQG5hbWUgUmVhZGVyI2ludDY0XG4gKiBAZnVuY3Rpb25cbiAqIEByZXR1cm5zIHtMb25nfSBWYWx1ZSByZWFkXG4gKi9cblxuLyoqXG4gKiBSZWFkcyBhIHZhcmludCBhcyBhbiB1bnNpZ25lZCA2NCBiaXQgdmFsdWUuXG4gKiBAbmFtZSBSZWFkZXIjdWludDY0XG4gKiBAZnVuY3Rpb25cbiAqIEByZXR1cm5zIHtMb25nfSBWYWx1ZSByZWFkXG4gKi9cblxuLyoqXG4gKiBSZWFkcyBhIHppZy16YWcgZW5jb2RlZCB2YXJpbnQgYXMgYSBzaWduZWQgNjQgYml0IHZhbHVlLlxuICogQG5hbWUgUmVhZGVyI3NpbnQ2NFxuICogQGZ1bmN0aW9uXG4gKiBAcmV0dXJucyB7TG9uZ30gVmFsdWUgcmVhZFxuICovXG5cbi8qKlxuICogUmVhZHMgYSB2YXJpbnQgYXMgYSBib29sZWFuLlxuICogQHJldHVybnMge2Jvb2xlYW59IFZhbHVlIHJlYWRcbiAqL1xuUmVhZGVyLnByb3RvdHlwZS5ib29sID0gZnVuY3Rpb24gcmVhZF9ib29sKCkge1xuICAgIHJldHVybiB0aGlzLnVpbnQzMigpICE9PSAwO1xufTtcblxuZnVuY3Rpb24gcmVhZEZpeGVkMzJfZW5kKGJ1ZiwgZW5kKSB7IC8vIG5vdGUgdGhhdCB0aGlzIHVzZXMgYGVuZGAsIG5vdCBgcG9zYFxuICAgIHJldHVybiAoYnVmW2VuZCAtIDRdXG4gICAgICAgICAgfCBidWZbZW5kIC0gM10gPDwgOFxuICAgICAgICAgIHwgYnVmW2VuZCAtIDJdIDw8IDE2XG4gICAgICAgICAgfCBidWZbZW5kIC0gMV0gPDwgMjQpID4+PiAwO1xufVxuXG4vKipcbiAqIFJlYWRzIGZpeGVkIDMyIGJpdHMgYXMgYW4gdW5zaWduZWQgMzIgYml0IGludGVnZXIuXG4gKiBAcmV0dXJucyB7bnVtYmVyfSBWYWx1ZSByZWFkXG4gKi9cblJlYWRlci5wcm90b3R5cGUuZml4ZWQzMiA9IGZ1bmN0aW9uIHJlYWRfZml4ZWQzMigpIHtcblxuICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBpZiAqL1xuICAgIGlmICh0aGlzLnBvcyArIDQgPiB0aGlzLmxlbilcbiAgICAgICAgdGhyb3cgaW5kZXhPdXRPZlJhbmdlKHRoaXMsIDQpO1xuXG4gICAgcmV0dXJuIHJlYWRGaXhlZDMyX2VuZCh0aGlzLmJ1ZiwgdGhpcy5wb3MgKz0gNCk7XG59O1xuXG4vKipcbiAqIFJlYWRzIGZpeGVkIDMyIGJpdHMgYXMgYSBzaWduZWQgMzIgYml0IGludGVnZXIuXG4gKiBAcmV0dXJucyB7bnVtYmVyfSBWYWx1ZSByZWFkXG4gKi9cblJlYWRlci5wcm90b3R5cGUuc2ZpeGVkMzIgPSBmdW5jdGlvbiByZWFkX3NmaXhlZDMyKCkge1xuXG4gICAgLyogaXN0YW5idWwgaWdub3JlIGlmICovXG4gICAgaWYgKHRoaXMucG9zICsgNCA+IHRoaXMubGVuKVxuICAgICAgICB0aHJvdyBpbmRleE91dE9mUmFuZ2UodGhpcywgNCk7XG5cbiAgICByZXR1cm4gcmVhZEZpeGVkMzJfZW5kKHRoaXMuYnVmLCB0aGlzLnBvcyArPSA0KSB8IDA7XG59O1xuXG4vKiBlc2xpbnQtZGlzYWJsZSBuby1pbnZhbGlkLXRoaXMgKi9cblxuZnVuY3Rpb24gcmVhZEZpeGVkNjQoLyogdGhpczogUmVhZGVyICovKSB7XG5cbiAgICAvKiBpc3RhbmJ1bCBpZ25vcmUgaWYgKi9cbiAgICBpZiAodGhpcy5wb3MgKyA4ID4gdGhpcy5sZW4pXG4gICAgICAgIHRocm93IGluZGV4T3V0T2ZSYW5nZSh0aGlzLCA4KTtcblxuICAgIHJldHVybiBuZXcgTG9uZ0JpdHMocmVhZEZpeGVkMzJfZW5kKHRoaXMuYnVmLCB0aGlzLnBvcyArPSA0KSwgcmVhZEZpeGVkMzJfZW5kKHRoaXMuYnVmLCB0aGlzLnBvcyArPSA0KSk7XG59XG5cbi8qIGVzbGludC1lbmFibGUgbm8taW52YWxpZC10aGlzICovXG5cbi8qKlxuICogUmVhZHMgZml4ZWQgNjQgYml0cy5cbiAqIEBuYW1lIFJlYWRlciNmaXhlZDY0XG4gKiBAZnVuY3Rpb25cbiAqIEByZXR1cm5zIHtMb25nfSBWYWx1ZSByZWFkXG4gKi9cblxuLyoqXG4gKiBSZWFkcyB6aWctemFnIGVuY29kZWQgZml4ZWQgNjQgYml0cy5cbiAqIEBuYW1lIFJlYWRlciNzZml4ZWQ2NFxuICogQGZ1bmN0aW9uXG4gKiBAcmV0dXJucyB7TG9uZ30gVmFsdWUgcmVhZFxuICovXG5cbi8qKlxuICogUmVhZHMgYSBmbG9hdCAoMzIgYml0KSBhcyBhIG51bWJlci5cbiAqIEBmdW5jdGlvblxuICogQHJldHVybnMge251bWJlcn0gVmFsdWUgcmVhZFxuICovXG5SZWFkZXIucHJvdG90eXBlLmZsb2F0ID0gZnVuY3Rpb24gcmVhZF9mbG9hdCgpIHtcblxuICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBpZiAqL1xuICAgIGlmICh0aGlzLnBvcyArIDQgPiB0aGlzLmxlbilcbiAgICAgICAgdGhyb3cgaW5kZXhPdXRPZlJhbmdlKHRoaXMsIDQpO1xuXG4gICAgdmFyIHZhbHVlID0gdXRpbC5mbG9hdC5yZWFkRmxvYXRMRSh0aGlzLmJ1ZiwgdGhpcy5wb3MpO1xuICAgIHRoaXMucG9zICs9IDQ7XG4gICAgcmV0dXJuIHZhbHVlO1xufTtcblxuLyoqXG4gKiBSZWFkcyBhIGRvdWJsZSAoNjQgYml0IGZsb2F0KSBhcyBhIG51bWJlci5cbiAqIEBmdW5jdGlvblxuICogQHJldHVybnMge251bWJlcn0gVmFsdWUgcmVhZFxuICovXG5SZWFkZXIucHJvdG90eXBlLmRvdWJsZSA9IGZ1bmN0aW9uIHJlYWRfZG91YmxlKCkge1xuXG4gICAgLyogaXN0YW5idWwgaWdub3JlIGlmICovXG4gICAgaWYgKHRoaXMucG9zICsgOCA+IHRoaXMubGVuKVxuICAgICAgICB0aHJvdyBpbmRleE91dE9mUmFuZ2UodGhpcywgNCk7XG5cbiAgICB2YXIgdmFsdWUgPSB1dGlsLmZsb2F0LnJlYWREb3VibGVMRSh0aGlzLmJ1ZiwgdGhpcy5wb3MpO1xuICAgIHRoaXMucG9zICs9IDg7XG4gICAgcmV0dXJuIHZhbHVlO1xufTtcblxuLyoqXG4gKiBSZWFkcyBhIHNlcXVlbmNlIG9mIGJ5dGVzIHByZWNlZWRlZCBieSBpdHMgbGVuZ3RoIGFzIGEgdmFyaW50LlxuICogQHJldHVybnMge1VpbnQ4QXJyYXl9IFZhbHVlIHJlYWRcbiAqL1xuUmVhZGVyLnByb3RvdHlwZS5ieXRlcyA9IGZ1bmN0aW9uIHJlYWRfYnl0ZXMoKSB7XG4gICAgdmFyIGxlbmd0aCA9IHRoaXMudWludDMyKCksXG4gICAgICAgIHN0YXJ0ICA9IHRoaXMucG9zLFxuICAgICAgICBlbmQgICAgPSB0aGlzLnBvcyArIGxlbmd0aDtcblxuICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBpZiAqL1xuICAgIGlmIChlbmQgPiB0aGlzLmxlbilcbiAgICAgICAgdGhyb3cgaW5kZXhPdXRPZlJhbmdlKHRoaXMsIGxlbmd0aCk7XG5cbiAgICB0aGlzLnBvcyArPSBsZW5ndGg7XG4gICAgaWYgKEFycmF5LmlzQXJyYXkodGhpcy5idWYpKSAvLyBwbGFpbiBhcnJheVxuICAgICAgICByZXR1cm4gdGhpcy5idWYuc2xpY2Uoc3RhcnQsIGVuZCk7XG4gICAgcmV0dXJuIHN0YXJ0ID09PSBlbmQgLy8gZml4IGZvciBJRSAxMC9XaW44IGFuZCBvdGhlcnMnIHN1YmFycmF5IHJldHVybmluZyBhcnJheSBvZiBzaXplIDFcbiAgICAgICAgPyBuZXcgdGhpcy5idWYuY29uc3RydWN0b3IoMClcbiAgICAgICAgOiB0aGlzLl9zbGljZS5jYWxsKHRoaXMuYnVmLCBzdGFydCwgZW5kKTtcbn07XG5cbi8qKlxuICogUmVhZHMgYSBzdHJpbmcgcHJlY2VlZGVkIGJ5IGl0cyBieXRlIGxlbmd0aCBhcyBhIHZhcmludC5cbiAqIEByZXR1cm5zIHtzdHJpbmd9IFZhbHVlIHJlYWRcbiAqL1xuUmVhZGVyLnByb3RvdHlwZS5zdHJpbmcgPSBmdW5jdGlvbiByZWFkX3N0cmluZygpIHtcbiAgICB2YXIgYnl0ZXMgPSB0aGlzLmJ5dGVzKCk7XG4gICAgcmV0dXJuIHV0ZjgucmVhZChieXRlcywgMCwgYnl0ZXMubGVuZ3RoKTtcbn07XG5cbi8qKlxuICogU2tpcHMgdGhlIHNwZWNpZmllZCBudW1iZXIgb2YgYnl0ZXMgaWYgc3BlY2lmaWVkLCBvdGhlcndpc2Ugc2tpcHMgYSB2YXJpbnQuXG4gKiBAcGFyYW0ge251bWJlcn0gW2xlbmd0aF0gTGVuZ3RoIGlmIGtub3duLCBvdGhlcndpc2UgYSB2YXJpbnQgaXMgYXNzdW1lZFxuICogQHJldHVybnMge1JlYWRlcn0gYHRoaXNgXG4gKi9cblJlYWRlci5wcm90b3R5cGUuc2tpcCA9IGZ1bmN0aW9uIHNraXAobGVuZ3RoKSB7XG4gICAgaWYgKHR5cGVvZiBsZW5ndGggPT09IFwibnVtYmVyXCIpIHtcbiAgICAgICAgLyogaXN0YW5idWwgaWdub3JlIGlmICovXG4gICAgICAgIGlmICh0aGlzLnBvcyArIGxlbmd0aCA+IHRoaXMubGVuKVxuICAgICAgICAgICAgdGhyb3cgaW5kZXhPdXRPZlJhbmdlKHRoaXMsIGxlbmd0aCk7XG4gICAgICAgIHRoaXMucG9zICs9IGxlbmd0aDtcbiAgICB9IGVsc2Uge1xuICAgICAgICBkbyB7XG4gICAgICAgICAgICAvKiBpc3RhbmJ1bCBpZ25vcmUgaWYgKi9cbiAgICAgICAgICAgIGlmICh0aGlzLnBvcyA+PSB0aGlzLmxlbilcbiAgICAgICAgICAgICAgICB0aHJvdyBpbmRleE91dE9mUmFuZ2UodGhpcyk7XG4gICAgICAgIH0gd2hpbGUgKHRoaXMuYnVmW3RoaXMucG9zKytdICYgMTI4KTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXM7XG59O1xuXG4vKipcbiAqIFNraXBzIHRoZSBuZXh0IGVsZW1lbnQgb2YgdGhlIHNwZWNpZmllZCB3aXJlIHR5cGUuXG4gKiBAcGFyYW0ge251bWJlcn0gd2lyZVR5cGUgV2lyZSB0eXBlIHJlY2VpdmVkXG4gKiBAcmV0dXJucyB7UmVhZGVyfSBgdGhpc2BcbiAqL1xuUmVhZGVyLnByb3RvdHlwZS5za2lwVHlwZSA9IGZ1bmN0aW9uKHdpcmVUeXBlKSB7XG4gICAgc3dpdGNoICh3aXJlVHlwZSkge1xuICAgICAgICBjYXNlIDA6XG4gICAgICAgICAgICB0aGlzLnNraXAoKTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlIDE6XG4gICAgICAgICAgICB0aGlzLnNraXAoOCk7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSAyOlxuICAgICAgICAgICAgdGhpcy5za2lwKHRoaXMudWludDMyKCkpO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgMzpcbiAgICAgICAgICAgIHdoaWxlICgod2lyZVR5cGUgPSB0aGlzLnVpbnQzMigpICYgNykgIT09IDQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnNraXBUeXBlKHdpcmVUeXBlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlIDU6XG4gICAgICAgICAgICB0aGlzLnNraXAoNCk7XG4gICAgICAgICAgICBicmVhaztcblxuICAgICAgICAvKiBpc3RhbmJ1bCBpZ25vcmUgbmV4dCAqL1xuICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgdGhyb3cgRXJyb3IoXCJpbnZhbGlkIHdpcmUgdHlwZSBcIiArIHdpcmVUeXBlICsgXCIgYXQgb2Zmc2V0IFwiICsgdGhpcy5wb3MpO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcztcbn07XG5cblJlYWRlci5fY29uZmlndXJlID0gZnVuY3Rpb24oQnVmZmVyUmVhZGVyXykge1xuICAgIEJ1ZmZlclJlYWRlciA9IEJ1ZmZlclJlYWRlcl87XG4gICAgUmVhZGVyLmNyZWF0ZSA9IGNyZWF0ZSgpO1xuICAgIEJ1ZmZlclJlYWRlci5fY29uZmlndXJlKCk7XG5cbiAgICB2YXIgZm4gPSB1dGlsLkxvbmcgPyBcInRvTG9uZ1wiIDogLyogaXN0YW5idWwgaWdub3JlIG5leHQgKi8gXCJ0b051bWJlclwiO1xuICAgIHV0aWwubWVyZ2UoUmVhZGVyLnByb3RvdHlwZSwge1xuXG4gICAgICAgIGludDY0OiBmdW5jdGlvbiByZWFkX2ludDY0KCkge1xuICAgICAgICAgICAgcmV0dXJuIHJlYWRMb25nVmFyaW50LmNhbGwodGhpcylbZm5dKGZhbHNlKTtcbiAgICAgICAgfSxcblxuICAgICAgICB1aW50NjQ6IGZ1bmN0aW9uIHJlYWRfdWludDY0KCkge1xuICAgICAgICAgICAgcmV0dXJuIHJlYWRMb25nVmFyaW50LmNhbGwodGhpcylbZm5dKHRydWUpO1xuICAgICAgICB9LFxuXG4gICAgICAgIHNpbnQ2NDogZnVuY3Rpb24gcmVhZF9zaW50NjQoKSB7XG4gICAgICAgICAgICByZXR1cm4gcmVhZExvbmdWYXJpbnQuY2FsbCh0aGlzKS56ekRlY29kZSgpW2ZuXShmYWxzZSk7XG4gICAgICAgIH0sXG5cbiAgICAgICAgZml4ZWQ2NDogZnVuY3Rpb24gcmVhZF9maXhlZDY0KCkge1xuICAgICAgICAgICAgcmV0dXJuIHJlYWRGaXhlZDY0LmNhbGwodGhpcylbZm5dKHRydWUpO1xuICAgICAgICB9LFxuXG4gICAgICAgIHNmaXhlZDY0OiBmdW5jdGlvbiByZWFkX3NmaXhlZDY0KCkge1xuICAgICAgICAgICAgcmV0dXJuIHJlYWRGaXhlZDY0LmNhbGwodGhpcylbZm5dKGZhbHNlKTtcbiAgICAgICAgfVxuXG4gICAgfSk7XG59O1xuIiwiXCJ1c2Ugc3RyaWN0XCI7XG5tb2R1bGUuZXhwb3J0cyA9IEJ1ZmZlclJlYWRlcjtcblxuLy8gZXh0ZW5kcyBSZWFkZXJcbnZhciBSZWFkZXIgPSByZXF1aXJlKFwiLi9yZWFkZXJcIik7XG4oQnVmZmVyUmVhZGVyLnByb3RvdHlwZSA9IE9iamVjdC5jcmVhdGUoUmVhZGVyLnByb3RvdHlwZSkpLmNvbnN0cnVjdG9yID0gQnVmZmVyUmVhZGVyO1xuXG52YXIgdXRpbCA9IHJlcXVpcmUoXCIuL3V0aWwvbWluaW1hbFwiKTtcblxuLyoqXG4gKiBDb25zdHJ1Y3RzIGEgbmV3IGJ1ZmZlciByZWFkZXIgaW5zdGFuY2UuXG4gKiBAY2xhc3NkZXNjIFdpcmUgZm9ybWF0IHJlYWRlciB1c2luZyBub2RlIGJ1ZmZlcnMuXG4gKiBAZXh0ZW5kcyBSZWFkZXJcbiAqIEBjb25zdHJ1Y3RvclxuICogQHBhcmFtIHtCdWZmZXJ9IGJ1ZmZlciBCdWZmZXIgdG8gcmVhZCBmcm9tXG4gKi9cbmZ1bmN0aW9uIEJ1ZmZlclJlYWRlcihidWZmZXIpIHtcbiAgICBSZWFkZXIuY2FsbCh0aGlzLCBidWZmZXIpO1xuXG4gICAgLyoqXG4gICAgICogUmVhZCBidWZmZXIuXG4gICAgICogQG5hbWUgQnVmZmVyUmVhZGVyI2J1ZlxuICAgICAqIEB0eXBlIHtCdWZmZXJ9XG4gICAgICovXG59XG5cbkJ1ZmZlclJlYWRlci5fY29uZmlndXJlID0gZnVuY3Rpb24gKCkge1xuICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBlbHNlICovXG4gICAgaWYgKHV0aWwuQnVmZmVyKVxuICAgICAgICBCdWZmZXJSZWFkZXIucHJvdG90eXBlLl9zbGljZSA9IHV0aWwuQnVmZmVyLnByb3RvdHlwZS5zbGljZTtcbn07XG5cblxuLyoqXG4gKiBAb3ZlcnJpZGVcbiAqL1xuQnVmZmVyUmVhZGVyLnByb3RvdHlwZS5zdHJpbmcgPSBmdW5jdGlvbiByZWFkX3N0cmluZ19idWZmZXIoKSB7XG4gICAgdmFyIGxlbiA9IHRoaXMudWludDMyKCk7IC8vIG1vZGlmaWVzIHBvc1xuICAgIHJldHVybiB0aGlzLmJ1Zi51dGY4U2xpY2VcbiAgICAgICAgPyB0aGlzLmJ1Zi51dGY4U2xpY2UodGhpcy5wb3MsIHRoaXMucG9zID0gTWF0aC5taW4odGhpcy5wb3MgKyBsZW4sIHRoaXMubGVuKSlcbiAgICAgICAgOiB0aGlzLmJ1Zi50b1N0cmluZyhcInV0Zi04XCIsIHRoaXMucG9zLCB0aGlzLnBvcyA9IE1hdGgubWluKHRoaXMucG9zICsgbGVuLCB0aGlzLmxlbikpO1xufTtcblxuLyoqXG4gKiBSZWFkcyBhIHNlcXVlbmNlIG9mIGJ5dGVzIHByZWNlZWRlZCBieSBpdHMgbGVuZ3RoIGFzIGEgdmFyaW50LlxuICogQG5hbWUgQnVmZmVyUmVhZGVyI2J5dGVzXG4gKiBAZnVuY3Rpb25cbiAqIEByZXR1cm5zIHtCdWZmZXJ9IFZhbHVlIHJlYWRcbiAqL1xuXG5CdWZmZXJSZWFkZXIuX2NvbmZpZ3VyZSgpO1xuIiwiXCJ1c2Ugc3RyaWN0XCI7XG5tb2R1bGUuZXhwb3J0cyA9IHt9O1xuXG4vKipcbiAqIE5hbWVkIHJvb3RzLlxuICogVGhpcyBpcyB3aGVyZSBwYmpzIHN0b3JlcyBnZW5lcmF0ZWQgc3RydWN0dXJlcyAodGhlIG9wdGlvbiBgLXIsIC0tcm9vdGAgc3BlY2lmaWVzIGEgbmFtZSkuXG4gKiBDYW4gYWxzbyBiZSB1c2VkIG1hbnVhbGx5IHRvIG1ha2Ugcm9vdHMgYXZhaWxhYmxlIGFjY3Jvc3MgbW9kdWxlcy5cbiAqIEBuYW1lIHJvb3RzXG4gKiBAdHlwZSB7T2JqZWN0LjxzdHJpbmcsUm9vdD59XG4gKiBAZXhhbXBsZVxuICogLy8gcGJqcyAtciBteXJvb3QgLW8gY29tcGlsZWQuanMgLi4uXG4gKlxuICogLy8gaW4gYW5vdGhlciBtb2R1bGU6XG4gKiByZXF1aXJlKFwiLi9jb21waWxlZC5qc1wiKTtcbiAqXG4gKiAvLyBpbiBhbnkgc3Vic2VxdWVudCBtb2R1bGU6XG4gKiB2YXIgcm9vdCA9IHByb3RvYnVmLnJvb3RzW1wibXlyb290XCJdO1xuICovXG4iLCJcInVzZSBzdHJpY3RcIjtcblxuLyoqXG4gKiBTdHJlYW1pbmcgUlBDIGhlbHBlcnMuXG4gKiBAbmFtZXNwYWNlXG4gKi9cbnZhciBycGMgPSBleHBvcnRzO1xuXG4vKipcbiAqIFJQQyBpbXBsZW1lbnRhdGlvbiBwYXNzZWQgdG8ge0BsaW5rIFNlcnZpY2UjY3JlYXRlfSBwZXJmb3JtaW5nIGEgc2VydmljZSByZXF1ZXN0IG9uIG5ldHdvcmsgbGV2ZWwsIGkuZS4gYnkgdXRpbGl6aW5nIGh0dHAgcmVxdWVzdHMgb3Igd2Vic29ja2V0cy5cbiAqIEB0eXBlZGVmIFJQQ0ltcGxcbiAqIEB0eXBlIHtmdW5jdGlvbn1cbiAqIEBwYXJhbSB7TWV0aG9kfHJwYy5TZXJ2aWNlTWV0aG9kPE1lc3NhZ2U8e30+LE1lc3NhZ2U8e30+Pn0gbWV0aG9kIFJlZmxlY3RlZCBvciBzdGF0aWMgbWV0aG9kIGJlaW5nIGNhbGxlZFxuICogQHBhcmFtIHtVaW50OEFycmF5fSByZXF1ZXN0RGF0YSBSZXF1ZXN0IGRhdGFcbiAqIEBwYXJhbSB7UlBDSW1wbENhbGxiYWNrfSBjYWxsYmFjayBDYWxsYmFjayBmdW5jdGlvblxuICogQHJldHVybnMge3VuZGVmaW5lZH1cbiAqIEBleGFtcGxlXG4gKiBmdW5jdGlvbiBycGNJbXBsKG1ldGhvZCwgcmVxdWVzdERhdGEsIGNhbGxiYWNrKSB7XG4gKiAgICAgaWYgKHByb3RvYnVmLnV0aWwubGNGaXJzdChtZXRob2QubmFtZSkgIT09IFwibXlNZXRob2RcIikgLy8gY29tcGF0aWJsZSB3aXRoIHN0YXRpYyBjb2RlXG4gKiAgICAgICAgIHRocm93IEVycm9yKFwibm8gc3VjaCBtZXRob2RcIik7XG4gKiAgICAgYXN5bmNocm9ub3VzbHlPYnRhaW5BUmVzcG9uc2UocmVxdWVzdERhdGEsIGZ1bmN0aW9uKGVyciwgcmVzcG9uc2VEYXRhKSB7XG4gKiAgICAgICAgIGNhbGxiYWNrKGVyciwgcmVzcG9uc2VEYXRhKTtcbiAqICAgICB9KTtcbiAqIH1cbiAqL1xuXG4vKipcbiAqIE5vZGUtc3R5bGUgY2FsbGJhY2sgYXMgdXNlZCBieSB7QGxpbmsgUlBDSW1wbH0uXG4gKiBAdHlwZWRlZiBSUENJbXBsQ2FsbGJhY2tcbiAqIEB0eXBlIHtmdW5jdGlvbn1cbiAqIEBwYXJhbSB7RXJyb3J8bnVsbH0gZXJyb3IgRXJyb3IsIGlmIGFueSwgb3RoZXJ3aXNlIGBudWxsYFxuICogQHBhcmFtIHtVaW50OEFycmF5fG51bGx9IFtyZXNwb25zZV0gUmVzcG9uc2UgZGF0YSBvciBgbnVsbGAgdG8gc2lnbmFsIGVuZCBvZiBzdHJlYW0sIGlmIHRoZXJlIGhhc24ndCBiZWVuIGFuIGVycm9yXG4gKiBAcmV0dXJucyB7dW5kZWZpbmVkfVxuICovXG5cbnJwYy5TZXJ2aWNlID0gcmVxdWlyZShcIi4vcnBjL3NlcnZpY2VcIik7XG4iLCJcInVzZSBzdHJpY3RcIjtcbm1vZHVsZS5leHBvcnRzID0gU2VydmljZTtcblxudmFyIHV0aWwgPSByZXF1aXJlKFwiLi4vdXRpbC9taW5pbWFsXCIpO1xuXG4vLyBFeHRlbmRzIEV2ZW50RW1pdHRlclxuKFNlcnZpY2UucHJvdG90eXBlID0gT2JqZWN0LmNyZWF0ZSh1dGlsLkV2ZW50RW1pdHRlci5wcm90b3R5cGUpKS5jb25zdHJ1Y3RvciA9IFNlcnZpY2U7XG5cbi8qKlxuICogQSBzZXJ2aWNlIG1ldGhvZCBjYWxsYmFjayBhcyB1c2VkIGJ5IHtAbGluayBycGMuU2VydmljZU1ldGhvZHxTZXJ2aWNlTWV0aG9kfS5cbiAqXG4gKiBEaWZmZXJzIGZyb20ge0BsaW5rIFJQQ0ltcGxDYWxsYmFja30gaW4gdGhhdCBpdCBpcyBhbiBhY3R1YWwgY2FsbGJhY2sgb2YgYSBzZXJ2aWNlIG1ldGhvZCB3aGljaCBtYXkgbm90IHJldHVybiBgcmVzcG9uc2UgPSBudWxsYC5cbiAqIEB0eXBlZGVmIHJwYy5TZXJ2aWNlTWV0aG9kQ2FsbGJhY2tcbiAqIEB0ZW1wbGF0ZSBUUmVzIGV4dGVuZHMgTWVzc2FnZTxUUmVzPlxuICogQHR5cGUge2Z1bmN0aW9ufVxuICogQHBhcmFtIHtFcnJvcnxudWxsfSBlcnJvciBFcnJvciwgaWYgYW55XG4gKiBAcGFyYW0ge1RSZXN9IFtyZXNwb25zZV0gUmVzcG9uc2UgbWVzc2FnZVxuICogQHJldHVybnMge3VuZGVmaW5lZH1cbiAqL1xuXG4vKipcbiAqIEEgc2VydmljZSBtZXRob2QgcGFydCBvZiBhIHtAbGluayBycGMuU2VydmljZX0gYXMgY3JlYXRlZCBieSB7QGxpbmsgU2VydmljZS5jcmVhdGV9LlxuICogQHR5cGVkZWYgcnBjLlNlcnZpY2VNZXRob2RcbiAqIEB0ZW1wbGF0ZSBUUmVxIGV4dGVuZHMgTWVzc2FnZTxUUmVxPlxuICogQHRlbXBsYXRlIFRSZXMgZXh0ZW5kcyBNZXNzYWdlPFRSZXM+XG4gKiBAdHlwZSB7ZnVuY3Rpb259XG4gKiBAcGFyYW0ge1RSZXF8UHJvcGVydGllczxUUmVxPn0gcmVxdWVzdCBSZXF1ZXN0IG1lc3NhZ2Ugb3IgcGxhaW4gb2JqZWN0XG4gKiBAcGFyYW0ge3JwYy5TZXJ2aWNlTWV0aG9kQ2FsbGJhY2s8VFJlcz59IFtjYWxsYmFja10gTm9kZS1zdHlsZSBjYWxsYmFjayBjYWxsZWQgd2l0aCB0aGUgZXJyb3IsIGlmIGFueSwgYW5kIHRoZSByZXNwb25zZSBtZXNzYWdlXG4gKiBAcmV0dXJucyB7UHJvbWlzZTxNZXNzYWdlPFRSZXM+Pn0gUHJvbWlzZSBpZiBgY2FsbGJhY2tgIGhhcyBiZWVuIG9taXR0ZWQsIG90aGVyd2lzZSBgdW5kZWZpbmVkYFxuICovXG5cbi8qKlxuICogQ29uc3RydWN0cyBhIG5ldyBSUEMgc2VydmljZSBpbnN0YW5jZS5cbiAqIEBjbGFzc2Rlc2MgQW4gUlBDIHNlcnZpY2UgYXMgcmV0dXJuZWQgYnkge0BsaW5rIFNlcnZpY2UjY3JlYXRlfS5cbiAqIEBleHBvcnRzIHJwYy5TZXJ2aWNlXG4gKiBAZXh0ZW5kcyB1dGlsLkV2ZW50RW1pdHRlclxuICogQGNvbnN0cnVjdG9yXG4gKiBAcGFyYW0ge1JQQ0ltcGx9IHJwY0ltcGwgUlBDIGltcGxlbWVudGF0aW9uXG4gKiBAcGFyYW0ge2Jvb2xlYW59IFtyZXF1ZXN0RGVsaW1pdGVkPWZhbHNlXSBXaGV0aGVyIHJlcXVlc3RzIGFyZSBsZW5ndGgtZGVsaW1pdGVkXG4gKiBAcGFyYW0ge2Jvb2xlYW59IFtyZXNwb25zZURlbGltaXRlZD1mYWxzZV0gV2hldGhlciByZXNwb25zZXMgYXJlIGxlbmd0aC1kZWxpbWl0ZWRcbiAqL1xuZnVuY3Rpb24gU2VydmljZShycGNJbXBsLCByZXF1ZXN0RGVsaW1pdGVkLCByZXNwb25zZURlbGltaXRlZCkge1xuXG4gICAgaWYgKHR5cGVvZiBycGNJbXBsICE9PSBcImZ1bmN0aW9uXCIpXG4gICAgICAgIHRocm93IFR5cGVFcnJvcihcInJwY0ltcGwgbXVzdCBiZSBhIGZ1bmN0aW9uXCIpO1xuXG4gICAgdXRpbC5FdmVudEVtaXR0ZXIuY2FsbCh0aGlzKTtcblxuICAgIC8qKlxuICAgICAqIFJQQyBpbXBsZW1lbnRhdGlvbi4gQmVjb21lcyBgbnVsbGAgb25jZSB0aGUgc2VydmljZSBpcyBlbmRlZC5cbiAgICAgKiBAdHlwZSB7UlBDSW1wbHxudWxsfVxuICAgICAqL1xuICAgIHRoaXMucnBjSW1wbCA9IHJwY0ltcGw7XG5cbiAgICAvKipcbiAgICAgKiBXaGV0aGVyIHJlcXVlc3RzIGFyZSBsZW5ndGgtZGVsaW1pdGVkLlxuICAgICAqIEB0eXBlIHtib29sZWFufVxuICAgICAqL1xuICAgIHRoaXMucmVxdWVzdERlbGltaXRlZCA9IEJvb2xlYW4ocmVxdWVzdERlbGltaXRlZCk7XG5cbiAgICAvKipcbiAgICAgKiBXaGV0aGVyIHJlc3BvbnNlcyBhcmUgbGVuZ3RoLWRlbGltaXRlZC5cbiAgICAgKiBAdHlwZSB7Ym9vbGVhbn1cbiAgICAgKi9cbiAgICB0aGlzLnJlc3BvbnNlRGVsaW1pdGVkID0gQm9vbGVhbihyZXNwb25zZURlbGltaXRlZCk7XG59XG5cbi8qKlxuICogQ2FsbHMgYSBzZXJ2aWNlIG1ldGhvZCB0aHJvdWdoIHtAbGluayBycGMuU2VydmljZSNycGNJbXBsfHJwY0ltcGx9LlxuICogQHBhcmFtIHtNZXRob2R8cnBjLlNlcnZpY2VNZXRob2Q8VFJlcSxUUmVzPn0gbWV0aG9kIFJlZmxlY3RlZCBvciBzdGF0aWMgbWV0aG9kXG4gKiBAcGFyYW0ge0NvbnN0cnVjdG9yPFRSZXE+fSByZXF1ZXN0Q3RvciBSZXF1ZXN0IGNvbnN0cnVjdG9yXG4gKiBAcGFyYW0ge0NvbnN0cnVjdG9yPFRSZXM+fSByZXNwb25zZUN0b3IgUmVzcG9uc2UgY29uc3RydWN0b3JcbiAqIEBwYXJhbSB7VFJlcXxQcm9wZXJ0aWVzPFRSZXE+fSByZXF1ZXN0IFJlcXVlc3QgbWVzc2FnZSBvciBwbGFpbiBvYmplY3RcbiAqIEBwYXJhbSB7cnBjLlNlcnZpY2VNZXRob2RDYWxsYmFjazxUUmVzPn0gY2FsbGJhY2sgU2VydmljZSBjYWxsYmFja1xuICogQHJldHVybnMge3VuZGVmaW5lZH1cbiAqIEB0ZW1wbGF0ZSBUUmVxIGV4dGVuZHMgTWVzc2FnZTxUUmVxPlxuICogQHRlbXBsYXRlIFRSZXMgZXh0ZW5kcyBNZXNzYWdlPFRSZXM+XG4gKi9cblNlcnZpY2UucHJvdG90eXBlLnJwY0NhbGwgPSBmdW5jdGlvbiBycGNDYWxsKG1ldGhvZCwgcmVxdWVzdEN0b3IsIHJlc3BvbnNlQ3RvciwgcmVxdWVzdCwgY2FsbGJhY2spIHtcblxuICAgIGlmICghcmVxdWVzdClcbiAgICAgICAgdGhyb3cgVHlwZUVycm9yKFwicmVxdWVzdCBtdXN0IGJlIHNwZWNpZmllZFwiKTtcblxuICAgIHZhciBzZWxmID0gdGhpcztcbiAgICBpZiAoIWNhbGxiYWNrKVxuICAgICAgICByZXR1cm4gdXRpbC5hc1Byb21pc2UocnBjQ2FsbCwgc2VsZiwgbWV0aG9kLCByZXF1ZXN0Q3RvciwgcmVzcG9uc2VDdG9yLCByZXF1ZXN0KTtcblxuICAgIGlmICghc2VsZi5ycGNJbXBsKSB7XG4gICAgICAgIHNldFRpbWVvdXQoZnVuY3Rpb24oKSB7IGNhbGxiYWNrKEVycm9yKFwiYWxyZWFkeSBlbmRlZFwiKSk7IH0sIDApO1xuICAgICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgIH1cblxuICAgIHRyeSB7XG4gICAgICAgIHJldHVybiBzZWxmLnJwY0ltcGwoXG4gICAgICAgICAgICBtZXRob2QsXG4gICAgICAgICAgICByZXF1ZXN0Q3RvcltzZWxmLnJlcXVlc3REZWxpbWl0ZWQgPyBcImVuY29kZURlbGltaXRlZFwiIDogXCJlbmNvZGVcIl0ocmVxdWVzdCkuZmluaXNoKCksXG4gICAgICAgICAgICBmdW5jdGlvbiBycGNDYWxsYmFjayhlcnIsIHJlc3BvbnNlKSB7XG5cbiAgICAgICAgICAgICAgICBpZiAoZXJyKSB7XG4gICAgICAgICAgICAgICAgICAgIHNlbGYuZW1pdChcImVycm9yXCIsIGVyciwgbWV0aG9kKTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGNhbGxiYWNrKGVycik7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKHJlc3BvbnNlID09PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgICAgIHNlbGYuZW5kKC8qIGVuZGVkQnlSUEMgKi8gdHJ1ZSk7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKCEocmVzcG9uc2UgaW5zdGFuY2VvZiByZXNwb25zZUN0b3IpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXNwb25zZSA9IHJlc3BvbnNlQ3RvcltzZWxmLnJlc3BvbnNlRGVsaW1pdGVkID8gXCJkZWNvZGVEZWxpbWl0ZWRcIiA6IFwiZGVjb2RlXCJdKHJlc3BvbnNlKTtcbiAgICAgICAgICAgICAgICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzZWxmLmVtaXQoXCJlcnJvclwiLCBlcnIsIG1ldGhvZCk7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gY2FsbGJhY2soZXJyKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHNlbGYuZW1pdChcImRhdGFcIiwgcmVzcG9uc2UsIG1ldGhvZCk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGNhbGxiYWNrKG51bGwsIHJlc3BvbnNlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgKTtcbiAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgc2VsZi5lbWl0KFwiZXJyb3JcIiwgZXJyLCBtZXRob2QpO1xuICAgICAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uKCkgeyBjYWxsYmFjayhlcnIpOyB9LCAwKTtcbiAgICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICB9XG59O1xuXG4vKipcbiAqIEVuZHMgdGhpcyBzZXJ2aWNlIGFuZCBlbWl0cyB0aGUgYGVuZGAgZXZlbnQuXG4gKiBAcGFyYW0ge2Jvb2xlYW59IFtlbmRlZEJ5UlBDPWZhbHNlXSBXaGV0aGVyIHRoZSBzZXJ2aWNlIGhhcyBiZWVuIGVuZGVkIGJ5IHRoZSBSUEMgaW1wbGVtZW50YXRpb24uXG4gKiBAcmV0dXJucyB7cnBjLlNlcnZpY2V9IGB0aGlzYFxuICovXG5TZXJ2aWNlLnByb3RvdHlwZS5lbmQgPSBmdW5jdGlvbiBlbmQoZW5kZWRCeVJQQykge1xuICAgIGlmICh0aGlzLnJwY0ltcGwpIHtcbiAgICAgICAgaWYgKCFlbmRlZEJ5UlBDKSAvLyBzaWduYWwgZW5kIHRvIHJwY0ltcGxcbiAgICAgICAgICAgIHRoaXMucnBjSW1wbChudWxsLCBudWxsLCBudWxsKTtcbiAgICAgICAgdGhpcy5ycGNJbXBsID0gbnVsbDtcbiAgICAgICAgdGhpcy5lbWl0KFwiZW5kXCIpLm9mZigpO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcztcbn07XG4iLCJcInVzZSBzdHJpY3RcIjtcbm1vZHVsZS5leHBvcnRzID0gTG9uZ0JpdHM7XG5cbnZhciB1dGlsID0gcmVxdWlyZShcIi4uL3V0aWwvbWluaW1hbFwiKTtcblxuLyoqXG4gKiBDb25zdHJ1Y3RzIG5ldyBsb25nIGJpdHMuXG4gKiBAY2xhc3NkZXNjIEhlbHBlciBjbGFzcyBmb3Igd29ya2luZyB3aXRoIHRoZSBsb3cgYW5kIGhpZ2ggYml0cyBvZiBhIDY0IGJpdCB2YWx1ZS5cbiAqIEBtZW1iZXJvZiB1dGlsXG4gKiBAY29uc3RydWN0b3JcbiAqIEBwYXJhbSB7bnVtYmVyfSBsbyBMb3cgMzIgYml0cywgdW5zaWduZWRcbiAqIEBwYXJhbSB7bnVtYmVyfSBoaSBIaWdoIDMyIGJpdHMsIHVuc2lnbmVkXG4gKi9cbmZ1bmN0aW9uIExvbmdCaXRzKGxvLCBoaSkge1xuXG4gICAgLy8gbm90ZSB0aGF0IHRoZSBjYXN0cyBiZWxvdyBhcmUgdGhlb3JldGljYWxseSB1bm5lY2Vzc2FyeSBhcyBvZiB0b2RheSwgYnV0IG9sZGVyIHN0YXRpY2FsbHlcbiAgICAvLyBnZW5lcmF0ZWQgY29udmVydGVyIGNvZGUgbWlnaHQgc3RpbGwgY2FsbCB0aGUgY3RvciB3aXRoIHNpZ25lZCAzMmJpdHMuIGtlcHQgZm9yIGNvbXBhdC5cblxuICAgIC8qKlxuICAgICAqIExvdyBiaXRzLlxuICAgICAqIEB0eXBlIHtudW1iZXJ9XG4gICAgICovXG4gICAgdGhpcy5sbyA9IGxvID4+PiAwO1xuXG4gICAgLyoqXG4gICAgICogSGlnaCBiaXRzLlxuICAgICAqIEB0eXBlIHtudW1iZXJ9XG4gICAgICovXG4gICAgdGhpcy5oaSA9IGhpID4+PiAwO1xufVxuXG4vKipcbiAqIFplcm8gYml0cy5cbiAqIEBtZW1iZXJvZiB1dGlsLkxvbmdCaXRzXG4gKiBAdHlwZSB7dXRpbC5Mb25nQml0c31cbiAqL1xudmFyIHplcm8gPSBMb25nQml0cy56ZXJvID0gbmV3IExvbmdCaXRzKDAsIDApO1xuXG56ZXJvLnRvTnVtYmVyID0gZnVuY3Rpb24oKSB7IHJldHVybiAwOyB9O1xuemVyby56ekVuY29kZSA9IHplcm8uenpEZWNvZGUgPSBmdW5jdGlvbigpIHsgcmV0dXJuIHRoaXM7IH07XG56ZXJvLmxlbmd0aCA9IGZ1bmN0aW9uKCkgeyByZXR1cm4gMTsgfTtcblxuLyoqXG4gKiBaZXJvIGhhc2guXG4gKiBAbWVtYmVyb2YgdXRpbC5Mb25nQml0c1xuICogQHR5cGUge3N0cmluZ31cbiAqL1xudmFyIHplcm9IYXNoID0gTG9uZ0JpdHMuemVyb0hhc2ggPSBcIlxcMFxcMFxcMFxcMFxcMFxcMFxcMFxcMFwiO1xuXG4vKipcbiAqIENvbnN0cnVjdHMgbmV3IGxvbmcgYml0cyBmcm9tIHRoZSBzcGVjaWZpZWQgbnVtYmVyLlxuICogQHBhcmFtIHtudW1iZXJ9IHZhbHVlIFZhbHVlXG4gKiBAcmV0dXJucyB7dXRpbC5Mb25nQml0c30gSW5zdGFuY2VcbiAqL1xuTG9uZ0JpdHMuZnJvbU51bWJlciA9IGZ1bmN0aW9uIGZyb21OdW1iZXIodmFsdWUpIHtcbiAgICBpZiAodmFsdWUgPT09IDApXG4gICAgICAgIHJldHVybiB6ZXJvO1xuICAgIHZhciBzaWduID0gdmFsdWUgPCAwO1xuICAgIGlmIChzaWduKVxuICAgICAgICB2YWx1ZSA9IC12YWx1ZTtcbiAgICB2YXIgbG8gPSB2YWx1ZSA+Pj4gMCxcbiAgICAgICAgaGkgPSAodmFsdWUgLSBsbykgLyA0Mjk0OTY3Mjk2ID4+PiAwO1xuICAgIGlmIChzaWduKSB7XG4gICAgICAgIGhpID0gfmhpID4+PiAwO1xuICAgICAgICBsbyA9IH5sbyA+Pj4gMDtcbiAgICAgICAgaWYgKCsrbG8gPiA0Mjk0OTY3Mjk1KSB7XG4gICAgICAgICAgICBsbyA9IDA7XG4gICAgICAgICAgICBpZiAoKytoaSA+IDQyOTQ5NjcyOTUpXG4gICAgICAgICAgICAgICAgaGkgPSAwO1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiBuZXcgTG9uZ0JpdHMobG8sIGhpKTtcbn07XG5cbi8qKlxuICogQ29uc3RydWN0cyBuZXcgbG9uZyBiaXRzIGZyb20gYSBudW1iZXIsIGxvbmcgb3Igc3RyaW5nLlxuICogQHBhcmFtIHtMb25nfG51bWJlcnxzdHJpbmd9IHZhbHVlIFZhbHVlXG4gKiBAcmV0dXJucyB7dXRpbC5Mb25nQml0c30gSW5zdGFuY2VcbiAqL1xuTG9uZ0JpdHMuZnJvbSA9IGZ1bmN0aW9uIGZyb20odmFsdWUpIHtcbiAgICBpZiAodHlwZW9mIHZhbHVlID09PSBcIm51bWJlclwiKVxuICAgICAgICByZXR1cm4gTG9uZ0JpdHMuZnJvbU51bWJlcih2YWx1ZSk7XG4gICAgaWYgKHV0aWwuaXNTdHJpbmcodmFsdWUpKSB7XG4gICAgICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBlbHNlICovXG4gICAgICAgIGlmICh1dGlsLkxvbmcpXG4gICAgICAgICAgICB2YWx1ZSA9IHV0aWwuTG9uZy5mcm9tU3RyaW5nKHZhbHVlKTtcbiAgICAgICAgZWxzZVxuICAgICAgICAgICAgcmV0dXJuIExvbmdCaXRzLmZyb21OdW1iZXIocGFyc2VJbnQodmFsdWUsIDEwKSk7XG4gICAgfVxuICAgIHJldHVybiB2YWx1ZS5sb3cgfHwgdmFsdWUuaGlnaCA/IG5ldyBMb25nQml0cyh2YWx1ZS5sb3cgPj4+IDAsIHZhbHVlLmhpZ2ggPj4+IDApIDogemVybztcbn07XG5cbi8qKlxuICogQ29udmVydHMgdGhpcyBsb25nIGJpdHMgdG8gYSBwb3NzaWJseSB1bnNhZmUgSmF2YVNjcmlwdCBudW1iZXIuXG4gKiBAcGFyYW0ge2Jvb2xlYW59IFt1bnNpZ25lZD1mYWxzZV0gV2hldGhlciB1bnNpZ25lZCBvciBub3RcbiAqIEByZXR1cm5zIHtudW1iZXJ9IFBvc3NpYmx5IHVuc2FmZSBudW1iZXJcbiAqL1xuTG9uZ0JpdHMucHJvdG90eXBlLnRvTnVtYmVyID0gZnVuY3Rpb24gdG9OdW1iZXIodW5zaWduZWQpIHtcbiAgICBpZiAoIXVuc2lnbmVkICYmIHRoaXMuaGkgPj4+IDMxKSB7XG4gICAgICAgIHZhciBsbyA9IH50aGlzLmxvICsgMSA+Pj4gMCxcbiAgICAgICAgICAgIGhpID0gfnRoaXMuaGkgICAgID4+PiAwO1xuICAgICAgICBpZiAoIWxvKVxuICAgICAgICAgICAgaGkgPSBoaSArIDEgPj4+IDA7XG4gICAgICAgIHJldHVybiAtKGxvICsgaGkgKiA0Mjk0OTY3Mjk2KTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMubG8gKyB0aGlzLmhpICogNDI5NDk2NzI5Njtcbn07XG5cbi8qKlxuICogQ29udmVydHMgdGhpcyBsb25nIGJpdHMgdG8gYSBsb25nLlxuICogQHBhcmFtIHtib29sZWFufSBbdW5zaWduZWQ9ZmFsc2VdIFdoZXRoZXIgdW5zaWduZWQgb3Igbm90XG4gKiBAcmV0dXJucyB7TG9uZ30gTG9uZ1xuICovXG5Mb25nQml0cy5wcm90b3R5cGUudG9Mb25nID0gZnVuY3Rpb24gdG9Mb25nKHVuc2lnbmVkKSB7XG4gICAgcmV0dXJuIHV0aWwuTG9uZ1xuICAgICAgICA/IG5ldyB1dGlsLkxvbmcodGhpcy5sbyB8IDAsIHRoaXMuaGkgfCAwLCBCb29sZWFuKHVuc2lnbmVkKSlcbiAgICAgICAgLyogaXN0YW5idWwgaWdub3JlIG5leHQgKi9cbiAgICAgICAgOiB7IGxvdzogdGhpcy5sbyB8IDAsIGhpZ2g6IHRoaXMuaGkgfCAwLCB1bnNpZ25lZDogQm9vbGVhbih1bnNpZ25lZCkgfTtcbn07XG5cbnZhciBjaGFyQ29kZUF0ID0gU3RyaW5nLnByb3RvdHlwZS5jaGFyQ29kZUF0O1xuXG4vKipcbiAqIENvbnN0cnVjdHMgbmV3IGxvbmcgYml0cyBmcm9tIHRoZSBzcGVjaWZpZWQgOCBjaGFyYWN0ZXJzIGxvbmcgaGFzaC5cbiAqIEBwYXJhbSB7c3RyaW5nfSBoYXNoIEhhc2hcbiAqIEByZXR1cm5zIHt1dGlsLkxvbmdCaXRzfSBCaXRzXG4gKi9cbkxvbmdCaXRzLmZyb21IYXNoID0gZnVuY3Rpb24gZnJvbUhhc2goaGFzaCkge1xuICAgIGlmIChoYXNoID09PSB6ZXJvSGFzaClcbiAgICAgICAgcmV0dXJuIHplcm87XG4gICAgcmV0dXJuIG5ldyBMb25nQml0cyhcbiAgICAgICAgKCBjaGFyQ29kZUF0LmNhbGwoaGFzaCwgMClcbiAgICAgICAgfCBjaGFyQ29kZUF0LmNhbGwoaGFzaCwgMSkgPDwgOFxuICAgICAgICB8IGNoYXJDb2RlQXQuY2FsbChoYXNoLCAyKSA8PCAxNlxuICAgICAgICB8IGNoYXJDb2RlQXQuY2FsbChoYXNoLCAzKSA8PCAyNCkgPj4+IDBcbiAgICAsXG4gICAgICAgICggY2hhckNvZGVBdC5jYWxsKGhhc2gsIDQpXG4gICAgICAgIHwgY2hhckNvZGVBdC5jYWxsKGhhc2gsIDUpIDw8IDhcbiAgICAgICAgfCBjaGFyQ29kZUF0LmNhbGwoaGFzaCwgNikgPDwgMTZcbiAgICAgICAgfCBjaGFyQ29kZUF0LmNhbGwoaGFzaCwgNykgPDwgMjQpID4+PiAwXG4gICAgKTtcbn07XG5cbi8qKlxuICogQ29udmVydHMgdGhpcyBsb25nIGJpdHMgdG8gYSA4IGNoYXJhY3RlcnMgbG9uZyBoYXNoLlxuICogQHJldHVybnMge3N0cmluZ30gSGFzaFxuICovXG5Mb25nQml0cy5wcm90b3R5cGUudG9IYXNoID0gZnVuY3Rpb24gdG9IYXNoKCkge1xuICAgIHJldHVybiBTdHJpbmcuZnJvbUNoYXJDb2RlKFxuICAgICAgICB0aGlzLmxvICAgICAgICAmIDI1NSxcbiAgICAgICAgdGhpcy5sbyA+Pj4gOCAgJiAyNTUsXG4gICAgICAgIHRoaXMubG8gPj4+IDE2ICYgMjU1LFxuICAgICAgICB0aGlzLmxvID4+PiAyNCAgICAgICxcbiAgICAgICAgdGhpcy5oaSAgICAgICAgJiAyNTUsXG4gICAgICAgIHRoaXMuaGkgPj4+IDggICYgMjU1LFxuICAgICAgICB0aGlzLmhpID4+PiAxNiAmIDI1NSxcbiAgICAgICAgdGhpcy5oaSA+Pj4gMjRcbiAgICApO1xufTtcblxuLyoqXG4gKiBaaWctemFnIGVuY29kZXMgdGhpcyBsb25nIGJpdHMuXG4gKiBAcmV0dXJucyB7dXRpbC5Mb25nQml0c30gYHRoaXNgXG4gKi9cbkxvbmdCaXRzLnByb3RvdHlwZS56ekVuY29kZSA9IGZ1bmN0aW9uIHp6RW5jb2RlKCkge1xuICAgIHZhciBtYXNrID0gICB0aGlzLmhpID4+IDMxO1xuICAgIHRoaXMuaGkgID0gKCh0aGlzLmhpIDw8IDEgfCB0aGlzLmxvID4+PiAzMSkgXiBtYXNrKSA+Pj4gMDtcbiAgICB0aGlzLmxvICA9ICggdGhpcy5sbyA8PCAxICAgICAgICAgICAgICAgICAgIF4gbWFzaykgPj4+IDA7XG4gICAgcmV0dXJuIHRoaXM7XG59O1xuXG4vKipcbiAqIFppZy16YWcgZGVjb2RlcyB0aGlzIGxvbmcgYml0cy5cbiAqIEByZXR1cm5zIHt1dGlsLkxvbmdCaXRzfSBgdGhpc2BcbiAqL1xuTG9uZ0JpdHMucHJvdG90eXBlLnp6RGVjb2RlID0gZnVuY3Rpb24genpEZWNvZGUoKSB7XG4gICAgdmFyIG1hc2sgPSAtKHRoaXMubG8gJiAxKTtcbiAgICB0aGlzLmxvICA9ICgodGhpcy5sbyA+Pj4gMSB8IHRoaXMuaGkgPDwgMzEpIF4gbWFzaykgPj4+IDA7XG4gICAgdGhpcy5oaSAgPSAoIHRoaXMuaGkgPj4+IDEgICAgICAgICAgICAgICAgICBeIG1hc2spID4+PiAwO1xuICAgIHJldHVybiB0aGlzO1xufTtcblxuLyoqXG4gKiBDYWxjdWxhdGVzIHRoZSBsZW5ndGggb2YgdGhpcyBsb25nYml0cyB3aGVuIGVuY29kZWQgYXMgYSB2YXJpbnQuXG4gKiBAcmV0dXJucyB7bnVtYmVyfSBMZW5ndGhcbiAqL1xuTG9uZ0JpdHMucHJvdG90eXBlLmxlbmd0aCA9IGZ1bmN0aW9uIGxlbmd0aCgpIHtcbiAgICB2YXIgcGFydDAgPSAgdGhpcy5sbyxcbiAgICAgICAgcGFydDEgPSAodGhpcy5sbyA+Pj4gMjggfCB0aGlzLmhpIDw8IDQpID4+PiAwLFxuICAgICAgICBwYXJ0MiA9ICB0aGlzLmhpID4+PiAyNDtcbiAgICByZXR1cm4gcGFydDIgPT09IDBcbiAgICAgICAgID8gcGFydDEgPT09IDBcbiAgICAgICAgICAgPyBwYXJ0MCA8IDE2Mzg0XG4gICAgICAgICAgICAgPyBwYXJ0MCA8IDEyOCA/IDEgOiAyXG4gICAgICAgICAgICAgOiBwYXJ0MCA8IDIwOTcxNTIgPyAzIDogNFxuICAgICAgICAgICA6IHBhcnQxIDwgMTYzODRcbiAgICAgICAgICAgICA/IHBhcnQxIDwgMTI4ID8gNSA6IDZcbiAgICAgICAgICAgICA6IHBhcnQxIDwgMjA5NzE1MiA/IDcgOiA4XG4gICAgICAgICA6IHBhcnQyIDwgMTI4ID8gOSA6IDEwO1xufTtcbiIsIlwidXNlIHN0cmljdFwiO1xudmFyIHV0aWwgPSBleHBvcnRzO1xuXG4vLyB1c2VkIHRvIHJldHVybiBhIFByb21pc2Ugd2hlcmUgY2FsbGJhY2sgaXMgb21pdHRlZFxudXRpbC5hc1Byb21pc2UgPSByZXF1aXJlKFwiQHByb3RvYnVmanMvYXNwcm9taXNlXCIpO1xuXG4vLyBjb252ZXJ0cyB0byAvIGZyb20gYmFzZTY0IGVuY29kZWQgc3RyaW5nc1xudXRpbC5iYXNlNjQgPSByZXF1aXJlKFwiQHByb3RvYnVmanMvYmFzZTY0XCIpO1xuXG4vLyBiYXNlIGNsYXNzIG9mIHJwYy5TZXJ2aWNlXG51dGlsLkV2ZW50RW1pdHRlciA9IHJlcXVpcmUoXCJAcHJvdG9idWZqcy9ldmVudGVtaXR0ZXJcIik7XG5cbi8vIGZsb2F0IGhhbmRsaW5nIGFjY3Jvc3MgYnJvd3NlcnNcbnV0aWwuZmxvYXQgPSByZXF1aXJlKFwiQHByb3RvYnVmanMvZmxvYXRcIik7XG5cbi8vIHJlcXVpcmVzIG1vZHVsZXMgb3B0aW9uYWxseSBhbmQgaGlkZXMgdGhlIGNhbGwgZnJvbSBidW5kbGVyc1xudXRpbC5pbnF1aXJlID0gcmVxdWlyZShcIkBwcm90b2J1ZmpzL2lucXVpcmVcIik7XG5cbi8vIGNvbnZlcnRzIHRvIC8gZnJvbSB1dGY4IGVuY29kZWQgc3RyaW5nc1xudXRpbC51dGY4ID0gcmVxdWlyZShcIkBwcm90b2J1ZmpzL3V0ZjhcIik7XG5cbi8vIHByb3ZpZGVzIGEgbm9kZS1saWtlIGJ1ZmZlciBwb29sIGluIHRoZSBicm93c2VyXG51dGlsLnBvb2wgPSByZXF1aXJlKFwiQHByb3RvYnVmanMvcG9vbFwiKTtcblxuLy8gdXRpbGl0eSB0byB3b3JrIHdpdGggdGhlIGxvdyBhbmQgaGlnaCBiaXRzIG9mIGEgNjQgYml0IHZhbHVlXG51dGlsLkxvbmdCaXRzID0gcmVxdWlyZShcIi4vbG9uZ2JpdHNcIik7XG5cbi8qKlxuICogV2hldGhlciBydW5uaW5nIHdpdGhpbiBub2RlIG9yIG5vdC5cbiAqIEBtZW1iZXJvZiB1dGlsXG4gKiBAdHlwZSB7Ym9vbGVhbn1cbiAqL1xudXRpbC5pc05vZGUgPSBCb29sZWFuKHR5cGVvZiBnbG9iYWwgIT09IFwidW5kZWZpbmVkXCJcbiAgICAgICAgICAgICAgICAgICAmJiBnbG9iYWxcbiAgICAgICAgICAgICAgICAgICAmJiBnbG9iYWwucHJvY2Vzc1xuICAgICAgICAgICAgICAgICAgICYmIGdsb2JhbC5wcm9jZXNzLnZlcnNpb25zXG4gICAgICAgICAgICAgICAgICAgJiYgZ2xvYmFsLnByb2Nlc3MudmVyc2lvbnMubm9kZSk7XG5cbi8qKlxuICogR2xvYmFsIG9iamVjdCByZWZlcmVuY2UuXG4gKiBAbWVtYmVyb2YgdXRpbFxuICogQHR5cGUge09iamVjdH1cbiAqL1xudXRpbC5nbG9iYWwgPSB1dGlsLmlzTm9kZSAmJiBnbG9iYWxcbiAgICAgICAgICAgfHwgdHlwZW9mIHdpbmRvdyAhPT0gXCJ1bmRlZmluZWRcIiAmJiB3aW5kb3dcbiAgICAgICAgICAgfHwgdHlwZW9mIHNlbGYgICAhPT0gXCJ1bmRlZmluZWRcIiAmJiBzZWxmXG4gICAgICAgICAgIHx8IHRoaXM7IC8vIGVzbGludC1kaXNhYmxlLWxpbmUgbm8taW52YWxpZC10aGlzXG5cbi8qKlxuICogQW4gaW1tdWFibGUgZW1wdHkgYXJyYXkuXG4gKiBAbWVtYmVyb2YgdXRpbFxuICogQHR5cGUge0FycmF5LjwqPn1cbiAqIEBjb25zdFxuICovXG51dGlsLmVtcHR5QXJyYXkgPSBPYmplY3QuZnJlZXplID8gT2JqZWN0LmZyZWV6ZShbXSkgOiAvKiBpc3RhbmJ1bCBpZ25vcmUgbmV4dCAqLyBbXTsgLy8gdXNlZCBvbiBwcm90b3R5cGVzXG5cbi8qKlxuICogQW4gaW1tdXRhYmxlIGVtcHR5IG9iamVjdC5cbiAqIEB0eXBlIHtPYmplY3R9XG4gKiBAY29uc3RcbiAqL1xudXRpbC5lbXB0eU9iamVjdCA9IE9iamVjdC5mcmVlemUgPyBPYmplY3QuZnJlZXplKHt9KSA6IC8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0ICovIHt9OyAvLyB1c2VkIG9uIHByb3RvdHlwZXNcblxuLyoqXG4gKiBUZXN0cyBpZiB0aGUgc3BlY2lmaWVkIHZhbHVlIGlzIGFuIGludGVnZXIuXG4gKiBAZnVuY3Rpb25cbiAqIEBwYXJhbSB7Kn0gdmFsdWUgVmFsdWUgdG8gdGVzdFxuICogQHJldHVybnMge2Jvb2xlYW59IGB0cnVlYCBpZiB0aGUgdmFsdWUgaXMgYW4gaW50ZWdlclxuICovXG51dGlsLmlzSW50ZWdlciA9IE51bWJlci5pc0ludGVnZXIgfHwgLyogaXN0YW5idWwgaWdub3JlIG5leHQgKi8gZnVuY3Rpb24gaXNJbnRlZ2VyKHZhbHVlKSB7XG4gICAgcmV0dXJuIHR5cGVvZiB2YWx1ZSA9PT0gXCJudW1iZXJcIiAmJiBpc0Zpbml0ZSh2YWx1ZSkgJiYgTWF0aC5mbG9vcih2YWx1ZSkgPT09IHZhbHVlO1xufTtcblxuLyoqXG4gKiBUZXN0cyBpZiB0aGUgc3BlY2lmaWVkIHZhbHVlIGlzIGEgc3RyaW5nLlxuICogQHBhcmFtIHsqfSB2YWx1ZSBWYWx1ZSB0byB0ZXN0XG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gYHRydWVgIGlmIHRoZSB2YWx1ZSBpcyBhIHN0cmluZ1xuICovXG51dGlsLmlzU3RyaW5nID0gZnVuY3Rpb24gaXNTdHJpbmcodmFsdWUpIHtcbiAgICByZXR1cm4gdHlwZW9mIHZhbHVlID09PSBcInN0cmluZ1wiIHx8IHZhbHVlIGluc3RhbmNlb2YgU3RyaW5nO1xufTtcblxuLyoqXG4gKiBUZXN0cyBpZiB0aGUgc3BlY2lmaWVkIHZhbHVlIGlzIGEgbm9uLW51bGwgb2JqZWN0LlxuICogQHBhcmFtIHsqfSB2YWx1ZSBWYWx1ZSB0byB0ZXN0XG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gYHRydWVgIGlmIHRoZSB2YWx1ZSBpcyBhIG5vbi1udWxsIG9iamVjdFxuICovXG51dGlsLmlzT2JqZWN0ID0gZnVuY3Rpb24gaXNPYmplY3QodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWUgJiYgdHlwZW9mIHZhbHVlID09PSBcIm9iamVjdFwiO1xufTtcblxuLyoqXG4gKiBDaGVja3MgaWYgYSBwcm9wZXJ0eSBvbiBhIG1lc3NhZ2UgaXMgY29uc2lkZXJlZCB0byBiZSBwcmVzZW50LlxuICogVGhpcyBpcyBhbiBhbGlhcyBvZiB7QGxpbmsgdXRpbC5pc1NldH0uXG4gKiBAZnVuY3Rpb25cbiAqIEBwYXJhbSB7T2JqZWN0fSBvYmogUGxhaW4gb2JqZWN0IG9yIG1lc3NhZ2UgaW5zdGFuY2VcbiAqIEBwYXJhbSB7c3RyaW5nfSBwcm9wIFByb3BlcnR5IG5hbWVcbiAqIEByZXR1cm5zIHtib29sZWFufSBgdHJ1ZWAgaWYgY29uc2lkZXJlZCB0byBiZSBwcmVzZW50LCBvdGhlcndpc2UgYGZhbHNlYFxuICovXG51dGlsLmlzc2V0ID1cblxuLyoqXG4gKiBDaGVja3MgaWYgYSBwcm9wZXJ0eSBvbiBhIG1lc3NhZ2UgaXMgY29uc2lkZXJlZCB0byBiZSBwcmVzZW50LlxuICogQHBhcmFtIHtPYmplY3R9IG9iaiBQbGFpbiBvYmplY3Qgb3IgbWVzc2FnZSBpbnN0YW5jZVxuICogQHBhcmFtIHtzdHJpbmd9IHByb3AgUHJvcGVydHkgbmFtZVxuICogQHJldHVybnMge2Jvb2xlYW59IGB0cnVlYCBpZiBjb25zaWRlcmVkIHRvIGJlIHByZXNlbnQsIG90aGVyd2lzZSBgZmFsc2VgXG4gKi9cbnV0aWwuaXNTZXQgPSBmdW5jdGlvbiBpc1NldChvYmosIHByb3ApIHtcbiAgICB2YXIgdmFsdWUgPSBvYmpbcHJvcF07XG4gICAgaWYgKHZhbHVlICE9IG51bGwgJiYgb2JqLmhhc093blByb3BlcnR5KHByb3ApKSAvLyBlc2xpbnQtZGlzYWJsZS1saW5lIGVxZXFlcSwgbm8tcHJvdG90eXBlLWJ1aWx0aW5zXG4gICAgICAgIHJldHVybiB0eXBlb2YgdmFsdWUgIT09IFwib2JqZWN0XCIgfHwgKEFycmF5LmlzQXJyYXkodmFsdWUpID8gdmFsdWUubGVuZ3RoIDogT2JqZWN0LmtleXModmFsdWUpLmxlbmd0aCkgPiAwO1xuICAgIHJldHVybiBmYWxzZTtcbn07XG5cbi8qKlxuICogQW55IGNvbXBhdGlibGUgQnVmZmVyIGluc3RhbmNlLlxuICogVGhpcyBpcyBhIG1pbmltYWwgc3RhbmQtYWxvbmUgZGVmaW5pdGlvbiBvZiBhIEJ1ZmZlciBpbnN0YW5jZS4gVGhlIGFjdHVhbCB0eXBlIGlzIHRoYXQgZXhwb3J0ZWQgYnkgbm9kZSdzIHR5cGluZ3MuXG4gKiBAaW50ZXJmYWNlIEJ1ZmZlclxuICogQGV4dGVuZHMgVWludDhBcnJheVxuICovXG5cbi8qKlxuICogTm9kZSdzIEJ1ZmZlciBjbGFzcyBpZiBhdmFpbGFibGUuXG4gKiBAdHlwZSB7Q29uc3RydWN0b3I8QnVmZmVyPn1cbiAqL1xudXRpbC5CdWZmZXIgPSAoZnVuY3Rpb24oKSB7XG4gICAgdHJ5IHtcbiAgICAgICAgdmFyIEJ1ZmZlciA9IHV0aWwuaW5xdWlyZShcImJ1ZmZlclwiKS5CdWZmZXI7XG4gICAgICAgIC8vIHJlZnVzZSB0byB1c2Ugbm9uLW5vZGUgYnVmZmVycyBpZiBub3QgZXhwbGljaXRseSBhc3NpZ25lZCAocGVyZiByZWFzb25zKTpcbiAgICAgICAgcmV0dXJuIEJ1ZmZlci5wcm90b3R5cGUudXRmOFdyaXRlID8gQnVmZmVyIDogLyogaXN0YW5idWwgaWdub3JlIG5leHQgKi8gbnVsbDtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0ICovXG4gICAgICAgIHJldHVybiBudWxsO1xuICAgIH1cbn0pKCk7XG5cbi8vIEludGVybmFsIGFsaWFzIG9mIG9yIHBvbHlmdWxsIGZvciBCdWZmZXIuZnJvbS5cbnV0aWwuX0J1ZmZlcl9mcm9tID0gbnVsbDtcblxuLy8gSW50ZXJuYWwgYWxpYXMgb2Ygb3IgcG9seWZpbGwgZm9yIEJ1ZmZlci5hbGxvY1Vuc2FmZS5cbnV0aWwuX0J1ZmZlcl9hbGxvY1Vuc2FmZSA9IG51bGw7XG5cbi8qKlxuICogQ3JlYXRlcyBhIG5ldyBidWZmZXIgb2Ygd2hhdGV2ZXIgdHlwZSBzdXBwb3J0ZWQgYnkgdGhlIGVudmlyb25tZW50LlxuICogQHBhcmFtIHtudW1iZXJ8bnVtYmVyW119IFtzaXplT3JBcnJheT0wXSBCdWZmZXIgc2l6ZSBvciBudW1iZXIgYXJyYXlcbiAqIEByZXR1cm5zIHtVaW50OEFycmF5fEJ1ZmZlcn0gQnVmZmVyXG4gKi9cbnV0aWwubmV3QnVmZmVyID0gZnVuY3Rpb24gbmV3QnVmZmVyKHNpemVPckFycmF5KSB7XG4gICAgLyogaXN0YW5idWwgaWdub3JlIG5leHQgKi9cbiAgICByZXR1cm4gdHlwZW9mIHNpemVPckFycmF5ID09PSBcIm51bWJlclwiXG4gICAgICAgID8gdXRpbC5CdWZmZXJcbiAgICAgICAgICAgID8gdXRpbC5fQnVmZmVyX2FsbG9jVW5zYWZlKHNpemVPckFycmF5KVxuICAgICAgICAgICAgOiBuZXcgdXRpbC5BcnJheShzaXplT3JBcnJheSlcbiAgICAgICAgOiB1dGlsLkJ1ZmZlclxuICAgICAgICAgICAgPyB1dGlsLl9CdWZmZXJfZnJvbShzaXplT3JBcnJheSlcbiAgICAgICAgICAgIDogdHlwZW9mIFVpbnQ4QXJyYXkgPT09IFwidW5kZWZpbmVkXCJcbiAgICAgICAgICAgICAgICA/IHNpemVPckFycmF5XG4gICAgICAgICAgICAgICAgOiBuZXcgVWludDhBcnJheShzaXplT3JBcnJheSk7XG59O1xuXG4vKipcbiAqIEFycmF5IGltcGxlbWVudGF0aW9uIHVzZWQgaW4gdGhlIGJyb3dzZXIuIGBVaW50OEFycmF5YCBpZiBzdXBwb3J0ZWQsIG90aGVyd2lzZSBgQXJyYXlgLlxuICogQHR5cGUge0NvbnN0cnVjdG9yPFVpbnQ4QXJyYXk+fVxuICovXG51dGlsLkFycmF5ID0gdHlwZW9mIFVpbnQ4QXJyYXkgIT09IFwidW5kZWZpbmVkXCIgPyBVaW50OEFycmF5IC8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0ICovIDogQXJyYXk7XG5cbi8qKlxuICogQW55IGNvbXBhdGlibGUgTG9uZyBpbnN0YW5jZS5cbiAqIFRoaXMgaXMgYSBtaW5pbWFsIHN0YW5kLWFsb25lIGRlZmluaXRpb24gb2YgYSBMb25nIGluc3RhbmNlLiBUaGUgYWN0dWFsIHR5cGUgaXMgdGhhdCBleHBvcnRlZCBieSBsb25nLmpzLlxuICogQGludGVyZmFjZSBMb25nXG4gKiBAcHJvcGVydHkge251bWJlcn0gbG93IExvdyBiaXRzXG4gKiBAcHJvcGVydHkge251bWJlcn0gaGlnaCBIaWdoIGJpdHNcbiAqIEBwcm9wZXJ0eSB7Ym9vbGVhbn0gdW5zaWduZWQgV2hldGhlciB1bnNpZ25lZCBvciBub3RcbiAqL1xuXG4vKipcbiAqIExvbmcuanMncyBMb25nIGNsYXNzIGlmIGF2YWlsYWJsZS5cbiAqIEB0eXBlIHtDb25zdHJ1Y3RvcjxMb25nPn1cbiAqL1xudXRpbC5Mb25nID0gLyogaXN0YW5idWwgaWdub3JlIG5leHQgKi8gdXRpbC5nbG9iYWwuZGNvZGVJTyAmJiAvKiBpc3RhbmJ1bCBpZ25vcmUgbmV4dCAqLyB1dGlsLmdsb2JhbC5kY29kZUlPLkxvbmdcbiAgICAgICAgIHx8IC8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0ICovIHV0aWwuZ2xvYmFsLkxvbmdcbiAgICAgICAgIHx8IHV0aWwuaW5xdWlyZShcImxvbmdcIik7XG5cbi8qKlxuICogUmVndWxhciBleHByZXNzaW9uIHVzZWQgdG8gdmVyaWZ5IDIgYml0IChgYm9vbGApIG1hcCBrZXlzLlxuICogQHR5cGUge1JlZ0V4cH1cbiAqIEBjb25zdFxuICovXG51dGlsLmtleTJSZSA9IC9edHJ1ZXxmYWxzZXwwfDEkLztcblxuLyoqXG4gKiBSZWd1bGFyIGV4cHJlc3Npb24gdXNlZCB0byB2ZXJpZnkgMzIgYml0IChgaW50MzJgIGV0Yy4pIG1hcCBrZXlzLlxuICogQHR5cGUge1JlZ0V4cH1cbiAqIEBjb25zdFxuICovXG51dGlsLmtleTMyUmUgPSAvXi0/KD86MHxbMS05XVswLTldKikkLztcblxuLyoqXG4gKiBSZWd1bGFyIGV4cHJlc3Npb24gdXNlZCB0byB2ZXJpZnkgNjQgYml0IChgaW50NjRgIGV0Yy4pIG1hcCBrZXlzLlxuICogQHR5cGUge1JlZ0V4cH1cbiAqIEBjb25zdFxuICovXG51dGlsLmtleTY0UmUgPSAvXig/OltcXFxceDAwLVxcXFx4ZmZdezh9fC0/KD86MHxbMS05XVswLTldKikpJC87XG5cbi8qKlxuICogQ29udmVydHMgYSBudW1iZXIgb3IgbG9uZyB0byBhbiA4IGNoYXJhY3RlcnMgbG9uZyBoYXNoIHN0cmluZy5cbiAqIEBwYXJhbSB7TG9uZ3xudW1iZXJ9IHZhbHVlIFZhbHVlIHRvIGNvbnZlcnRcbiAqIEByZXR1cm5zIHtzdHJpbmd9IEhhc2hcbiAqL1xudXRpbC5sb25nVG9IYXNoID0gZnVuY3Rpb24gbG9uZ1RvSGFzaCh2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZVxuICAgICAgICA/IHV0aWwuTG9uZ0JpdHMuZnJvbSh2YWx1ZSkudG9IYXNoKClcbiAgICAgICAgOiB1dGlsLkxvbmdCaXRzLnplcm9IYXNoO1xufTtcblxuLyoqXG4gKiBDb252ZXJ0cyBhbiA4IGNoYXJhY3RlcnMgbG9uZyBoYXNoIHN0cmluZyB0byBhIGxvbmcgb3IgbnVtYmVyLlxuICogQHBhcmFtIHtzdHJpbmd9IGhhc2ggSGFzaFxuICogQHBhcmFtIHtib29sZWFufSBbdW5zaWduZWQ9ZmFsc2VdIFdoZXRoZXIgdW5zaWduZWQgb3Igbm90XG4gKiBAcmV0dXJucyB7TG9uZ3xudW1iZXJ9IE9yaWdpbmFsIHZhbHVlXG4gKi9cbnV0aWwubG9uZ0Zyb21IYXNoID0gZnVuY3Rpb24gbG9uZ0Zyb21IYXNoKGhhc2gsIHVuc2lnbmVkKSB7XG4gICAgdmFyIGJpdHMgPSB1dGlsLkxvbmdCaXRzLmZyb21IYXNoKGhhc2gpO1xuICAgIGlmICh1dGlsLkxvbmcpXG4gICAgICAgIHJldHVybiB1dGlsLkxvbmcuZnJvbUJpdHMoYml0cy5sbywgYml0cy5oaSwgdW5zaWduZWQpO1xuICAgIHJldHVybiBiaXRzLnRvTnVtYmVyKEJvb2xlYW4odW5zaWduZWQpKTtcbn07XG5cbi8qKlxuICogTWVyZ2VzIHRoZSBwcm9wZXJ0aWVzIG9mIHRoZSBzb3VyY2Ugb2JqZWN0IGludG8gdGhlIGRlc3RpbmF0aW9uIG9iamVjdC5cbiAqIEBtZW1iZXJvZiB1dGlsXG4gKiBAcGFyYW0ge09iamVjdC48c3RyaW5nLCo+fSBkc3QgRGVzdGluYXRpb24gb2JqZWN0XG4gKiBAcGFyYW0ge09iamVjdC48c3RyaW5nLCo+fSBzcmMgU291cmNlIG9iamVjdFxuICogQHBhcmFtIHtib29sZWFufSBbaWZOb3RTZXQ9ZmFsc2VdIE1lcmdlcyBvbmx5IGlmIHRoZSBrZXkgaXMgbm90IGFscmVhZHkgc2V0XG4gKiBAcmV0dXJucyB7T2JqZWN0LjxzdHJpbmcsKj59IERlc3RpbmF0aW9uIG9iamVjdFxuICovXG5mdW5jdGlvbiBtZXJnZShkc3QsIHNyYywgaWZOb3RTZXQpIHsgLy8gdXNlZCBieSBjb252ZXJ0ZXJzXG4gICAgZm9yICh2YXIga2V5cyA9IE9iamVjdC5rZXlzKHNyYyksIGkgPSAwOyBpIDwga2V5cy5sZW5ndGg7ICsraSlcbiAgICAgICAgaWYgKGRzdFtrZXlzW2ldXSA9PT0gdW5kZWZpbmVkIHx8ICFpZk5vdFNldClcbiAgICAgICAgICAgIGRzdFtrZXlzW2ldXSA9IHNyY1trZXlzW2ldXTtcbiAgICByZXR1cm4gZHN0O1xufVxuXG51dGlsLm1lcmdlID0gbWVyZ2U7XG5cbi8qKlxuICogQ29udmVydHMgdGhlIGZpcnN0IGNoYXJhY3RlciBvZiBhIHN0cmluZyB0byBsb3dlciBjYXNlLlxuICogQHBhcmFtIHtzdHJpbmd9IHN0ciBTdHJpbmcgdG8gY29udmVydFxuICogQHJldHVybnMge3N0cmluZ30gQ29udmVydGVkIHN0cmluZ1xuICovXG51dGlsLmxjRmlyc3QgPSBmdW5jdGlvbiBsY0ZpcnN0KHN0cikge1xuICAgIHJldHVybiBzdHIuY2hhckF0KDApLnRvTG93ZXJDYXNlKCkgKyBzdHIuc3Vic3RyaW5nKDEpO1xufTtcblxuLyoqXG4gKiBDcmVhdGVzIGEgY3VzdG9tIGVycm9yIGNvbnN0cnVjdG9yLlxuICogQG1lbWJlcm9mIHV0aWxcbiAqIEBwYXJhbSB7c3RyaW5nfSBuYW1lIEVycm9yIG5hbWVcbiAqIEByZXR1cm5zIHtDb25zdHJ1Y3RvcjxFcnJvcj59IEN1c3RvbSBlcnJvciBjb25zdHJ1Y3RvclxuICovXG5mdW5jdGlvbiBuZXdFcnJvcihuYW1lKSB7XG5cbiAgICBmdW5jdGlvbiBDdXN0b21FcnJvcihtZXNzYWdlLCBwcm9wZXJ0aWVzKSB7XG5cbiAgICAgICAgaWYgKCEodGhpcyBpbnN0YW5jZW9mIEN1c3RvbUVycm9yKSlcbiAgICAgICAgICAgIHJldHVybiBuZXcgQ3VzdG9tRXJyb3IobWVzc2FnZSwgcHJvcGVydGllcyk7XG5cbiAgICAgICAgLy8gRXJyb3IuY2FsbCh0aGlzLCBtZXNzYWdlKTtcbiAgICAgICAgLy8gXiBqdXN0IHJldHVybnMgYSBuZXcgZXJyb3IgaW5zdGFuY2UgYmVjYXVzZSB0aGUgY3RvciBjYW4gYmUgY2FsbGVkIGFzIGEgZnVuY3Rpb25cblxuICAgICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkodGhpcywgXCJtZXNzYWdlXCIsIHsgZ2V0OiBmdW5jdGlvbigpIHsgcmV0dXJuIG1lc3NhZ2U7IH0gfSk7XG5cbiAgICAgICAgLyogaXN0YW5idWwgaWdub3JlIG5leHQgKi9cbiAgICAgICAgaWYgKEVycm9yLmNhcHR1cmVTdGFja1RyYWNlKSAvLyBub2RlXG4gICAgICAgICAgICBFcnJvci5jYXB0dXJlU3RhY2tUcmFjZSh0aGlzLCBDdXN0b21FcnJvcik7XG4gICAgICAgIGVsc2VcbiAgICAgICAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0aGlzLCBcInN0YWNrXCIsIHsgdmFsdWU6IG5ldyBFcnJvcigpLnN0YWNrIHx8IFwiXCIgfSk7XG5cbiAgICAgICAgaWYgKHByb3BlcnRpZXMpXG4gICAgICAgICAgICBtZXJnZSh0aGlzLCBwcm9wZXJ0aWVzKTtcbiAgICB9XG5cbiAgICAoQ3VzdG9tRXJyb3IucHJvdG90eXBlID0gT2JqZWN0LmNyZWF0ZShFcnJvci5wcm90b3R5cGUpKS5jb25zdHJ1Y3RvciA9IEN1c3RvbUVycm9yO1xuXG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KEN1c3RvbUVycm9yLnByb3RvdHlwZSwgXCJuYW1lXCIsIHsgZ2V0OiBmdW5jdGlvbigpIHsgcmV0dXJuIG5hbWU7IH0gfSk7XG5cbiAgICBDdXN0b21FcnJvci5wcm90b3R5cGUudG9TdHJpbmcgPSBmdW5jdGlvbiB0b1N0cmluZygpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMubmFtZSArIFwiOiBcIiArIHRoaXMubWVzc2FnZTtcbiAgICB9O1xuXG4gICAgcmV0dXJuIEN1c3RvbUVycm9yO1xufVxuXG51dGlsLm5ld0Vycm9yID0gbmV3RXJyb3I7XG5cbi8qKlxuICogQ29uc3RydWN0cyBhIG5ldyBwcm90b2NvbCBlcnJvci5cbiAqIEBjbGFzc2Rlc2MgRXJyb3Igc3ViY2xhc3MgaW5kaWNhdGluZyBhIHByb3RvY29sIHNwZWNpZmMgZXJyb3IuXG4gKiBAbWVtYmVyb2YgdXRpbFxuICogQGV4dGVuZHMgRXJyb3JcbiAqIEB0ZW1wbGF0ZSBUIGV4dGVuZHMgTWVzc2FnZTxUPlxuICogQGNvbnN0cnVjdG9yXG4gKiBAcGFyYW0ge3N0cmluZ30gbWVzc2FnZSBFcnJvciBtZXNzYWdlXG4gKiBAcGFyYW0ge09iamVjdC48c3RyaW5nLCo+fSBbcHJvcGVydGllc10gQWRkaXRpb25hbCBwcm9wZXJ0aWVzXG4gKiBAZXhhbXBsZVxuICogdHJ5IHtcbiAqICAgICBNeU1lc3NhZ2UuZGVjb2RlKHNvbWVCdWZmZXIpOyAvLyB0aHJvd3MgaWYgcmVxdWlyZWQgZmllbGRzIGFyZSBtaXNzaW5nXG4gKiB9IGNhdGNoIChlKSB7XG4gKiAgICAgaWYgKGUgaW5zdGFuY2VvZiBQcm90b2NvbEVycm9yICYmIGUuaW5zdGFuY2UpXG4gKiAgICAgICAgIGNvbnNvbGUubG9nKFwiZGVjb2RlZCBzbyBmYXI6IFwiICsgSlNPTi5zdHJpbmdpZnkoZS5pbnN0YW5jZSkpO1xuICogfVxuICovXG51dGlsLlByb3RvY29sRXJyb3IgPSBuZXdFcnJvcihcIlByb3RvY29sRXJyb3JcIik7XG5cbi8qKlxuICogU28gZmFyIGRlY29kZWQgbWVzc2FnZSBpbnN0YW5jZS5cbiAqIEBuYW1lIHV0aWwuUHJvdG9jb2xFcnJvciNpbnN0YW5jZVxuICogQHR5cGUge01lc3NhZ2U8VD59XG4gKi9cblxuLyoqXG4gKiBBIE9uZU9mIGdldHRlciBhcyByZXR1cm5lZCBieSB7QGxpbmsgdXRpbC5vbmVPZkdldHRlcn0uXG4gKiBAdHlwZWRlZiBPbmVPZkdldHRlclxuICogQHR5cGUge2Z1bmN0aW9ufVxuICogQHJldHVybnMge3N0cmluZ3x1bmRlZmluZWR9IFNldCBmaWVsZCBuYW1lLCBpZiBhbnlcbiAqL1xuXG4vKipcbiAqIEJ1aWxkcyBhIGdldHRlciBmb3IgYSBvbmVvZidzIHByZXNlbnQgZmllbGQgbmFtZS5cbiAqIEBwYXJhbSB7c3RyaW5nW119IGZpZWxkTmFtZXMgRmllbGQgbmFtZXNcbiAqIEByZXR1cm5zIHtPbmVPZkdldHRlcn0gVW5ib3VuZCBnZXR0ZXJcbiAqL1xudXRpbC5vbmVPZkdldHRlciA9IGZ1bmN0aW9uIGdldE9uZU9mKGZpZWxkTmFtZXMpIHtcbiAgICB2YXIgZmllbGRNYXAgPSB7fTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGZpZWxkTmFtZXMubGVuZ3RoOyArK2kpXG4gICAgICAgIGZpZWxkTWFwW2ZpZWxkTmFtZXNbaV1dID0gMTtcblxuICAgIC8qKlxuICAgICAqIEByZXR1cm5zIHtzdHJpbmd8dW5kZWZpbmVkfSBTZXQgZmllbGQgbmFtZSwgaWYgYW55XG4gICAgICogQHRoaXMgT2JqZWN0XG4gICAgICogQGlnbm9yZVxuICAgICAqL1xuICAgIHJldHVybiBmdW5jdGlvbigpIHsgLy8gZXNsaW50LWRpc2FibGUtbGluZSBjb25zaXN0ZW50LXJldHVyblxuICAgICAgICBmb3IgKHZhciBrZXlzID0gT2JqZWN0LmtleXModGhpcyksIGkgPSBrZXlzLmxlbmd0aCAtIDE7IGkgPiAtMTsgLS1pKVxuICAgICAgICAgICAgaWYgKGZpZWxkTWFwW2tleXNbaV1dID09PSAxICYmIHRoaXNba2V5c1tpXV0gIT09IHVuZGVmaW5lZCAmJiB0aGlzW2tleXNbaV1dICE9PSBudWxsKVxuICAgICAgICAgICAgICAgIHJldHVybiBrZXlzW2ldO1xuICAgIH07XG59O1xuXG4vKipcbiAqIEEgT25lT2Ygc2V0dGVyIGFzIHJldHVybmVkIGJ5IHtAbGluayB1dGlsLm9uZU9mU2V0dGVyfS5cbiAqIEB0eXBlZGVmIE9uZU9mU2V0dGVyXG4gKiBAdHlwZSB7ZnVuY3Rpb259XG4gKiBAcGFyYW0ge3N0cmluZ3x1bmRlZmluZWR9IHZhbHVlIEZpZWxkIG5hbWVcbiAqIEByZXR1cm5zIHt1bmRlZmluZWR9XG4gKi9cblxuLyoqXG4gKiBCdWlsZHMgYSBzZXR0ZXIgZm9yIGEgb25lb2YncyBwcmVzZW50IGZpZWxkIG5hbWUuXG4gKiBAcGFyYW0ge3N0cmluZ1tdfSBmaWVsZE5hbWVzIEZpZWxkIG5hbWVzXG4gKiBAcmV0dXJucyB7T25lT2ZTZXR0ZXJ9IFVuYm91bmQgc2V0dGVyXG4gKi9cbnV0aWwub25lT2ZTZXR0ZXIgPSBmdW5jdGlvbiBzZXRPbmVPZihmaWVsZE5hbWVzKSB7XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gbmFtZSBGaWVsZCBuYW1lXG4gICAgICogQHJldHVybnMge3VuZGVmaW5lZH1cbiAgICAgKiBAdGhpcyBPYmplY3RcbiAgICAgKiBAaWdub3JlXG4gICAgICovXG4gICAgcmV0dXJuIGZ1bmN0aW9uKG5hbWUpIHtcbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBmaWVsZE5hbWVzLmxlbmd0aDsgKytpKVxuICAgICAgICAgICAgaWYgKGZpZWxkTmFtZXNbaV0gIT09IG5hbWUpXG4gICAgICAgICAgICAgICAgZGVsZXRlIHRoaXNbZmllbGROYW1lc1tpXV07XG4gICAgfTtcbn07XG5cbi8qKlxuICogRGVmYXVsdCBjb252ZXJzaW9uIG9wdGlvbnMgdXNlZCBmb3Ige0BsaW5rIE1lc3NhZ2UjdG9KU09OfSBpbXBsZW1lbnRhdGlvbnMuXG4gKlxuICogVGhlc2Ugb3B0aW9ucyBhcmUgY2xvc2UgdG8gcHJvdG8zJ3MgSlNPTiBtYXBwaW5nIHdpdGggdGhlIGV4Y2VwdGlvbiB0aGF0IGludGVybmFsIHR5cGVzIGxpa2UgQW55IGFyZSBoYW5kbGVkIGp1c3QgbGlrZSBtZXNzYWdlcy4gTW9yZSBwcmVjaXNlbHk6XG4gKlxuICogLSBMb25ncyBiZWNvbWUgc3RyaW5nc1xuICogLSBFbnVtcyBiZWNvbWUgc3RyaW5nIGtleXNcbiAqIC0gQnl0ZXMgYmVjb21lIGJhc2U2NCBlbmNvZGVkIHN0cmluZ3NcbiAqIC0gKFN1Yi0pTWVzc2FnZXMgYmVjb21lIHBsYWluIG9iamVjdHNcbiAqIC0gTWFwcyBiZWNvbWUgcGxhaW4gb2JqZWN0cyB3aXRoIGFsbCBzdHJpbmcga2V5c1xuICogLSBSZXBlYXRlZCBmaWVsZHMgYmVjb21lIGFycmF5c1xuICogLSBOYU4gYW5kIEluZmluaXR5IGZvciBmbG9hdCBhbmQgZG91YmxlIGZpZWxkcyBiZWNvbWUgc3RyaW5nc1xuICpcbiAqIEB0eXBlIHtJQ29udmVyc2lvbk9wdGlvbnN9XG4gKiBAc2VlIGh0dHBzOi8vZGV2ZWxvcGVycy5nb29nbGUuY29tL3Byb3RvY29sLWJ1ZmZlcnMvZG9jcy9wcm90bzM/aGw9ZW4janNvblxuICovXG51dGlsLnRvSlNPTk9wdGlvbnMgPSB7XG4gICAgbG9uZ3M6IFN0cmluZyxcbiAgICBlbnVtczogU3RyaW5nLFxuICAgIGJ5dGVzOiBTdHJpbmcsXG4gICAganNvbjogdHJ1ZVxufTtcblxuLy8gU2V0cyB1cCBidWZmZXIgdXRpbGl0eSBhY2NvcmRpbmcgdG8gdGhlIGVudmlyb25tZW50IChjYWxsZWQgaW4gaW5kZXgtbWluaW1hbClcbnV0aWwuX2NvbmZpZ3VyZSA9IGZ1bmN0aW9uKCkge1xuICAgIHZhciBCdWZmZXIgPSB1dGlsLkJ1ZmZlcjtcbiAgICAvKiBpc3RhbmJ1bCBpZ25vcmUgaWYgKi9cbiAgICBpZiAoIUJ1ZmZlcikge1xuICAgICAgICB1dGlsLl9CdWZmZXJfZnJvbSA9IHV0aWwuX0J1ZmZlcl9hbGxvY1Vuc2FmZSA9IG51bGw7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG4gICAgLy8gYmVjYXVzZSBub2RlIDQueCBidWZmZXJzIGFyZSBpbmNvbXBhdGlibGUgJiBpbW11dGFibGVcbiAgICAvLyBzZWU6IGh0dHBzOi8vZ2l0aHViLmNvbS9kY29kZUlPL3Byb3RvYnVmLmpzL3B1bGwvNjY1XG4gICAgdXRpbC5fQnVmZmVyX2Zyb20gPSBCdWZmZXIuZnJvbSAhPT0gVWludDhBcnJheS5mcm9tICYmIEJ1ZmZlci5mcm9tIHx8XG4gICAgICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0ICovXG4gICAgICAgIGZ1bmN0aW9uIEJ1ZmZlcl9mcm9tKHZhbHVlLCBlbmNvZGluZykge1xuICAgICAgICAgICAgcmV0dXJuIG5ldyBCdWZmZXIodmFsdWUsIGVuY29kaW5nKTtcbiAgICAgICAgfTtcbiAgICB1dGlsLl9CdWZmZXJfYWxsb2NVbnNhZmUgPSBCdWZmZXIuYWxsb2NVbnNhZmUgfHxcbiAgICAgICAgLyogaXN0YW5idWwgaWdub3JlIG5leHQgKi9cbiAgICAgICAgZnVuY3Rpb24gQnVmZmVyX2FsbG9jVW5zYWZlKHNpemUpIHtcbiAgICAgICAgICAgIHJldHVybiBuZXcgQnVmZmVyKHNpemUpO1xuICAgICAgICB9O1xufTtcbiIsIlwidXNlIHN0cmljdFwiO1xubW9kdWxlLmV4cG9ydHMgPSBXcml0ZXI7XG5cbnZhciB1dGlsICAgICAgPSByZXF1aXJlKFwiLi91dGlsL21pbmltYWxcIik7XG5cbnZhciBCdWZmZXJXcml0ZXI7IC8vIGN5Y2xpY1xuXG52YXIgTG9uZ0JpdHMgID0gdXRpbC5Mb25nQml0cyxcbiAgICBiYXNlNjQgICAgPSB1dGlsLmJhc2U2NCxcbiAgICB1dGY4ICAgICAgPSB1dGlsLnV0Zjg7XG5cbi8qKlxuICogQ29uc3RydWN0cyBhIG5ldyB3cml0ZXIgb3BlcmF0aW9uIGluc3RhbmNlLlxuICogQGNsYXNzZGVzYyBTY2hlZHVsZWQgd3JpdGVyIG9wZXJhdGlvbi5cbiAqIEBjb25zdHJ1Y3RvclxuICogQHBhcmFtIHtmdW5jdGlvbigqLCBVaW50OEFycmF5LCBudW1iZXIpfSBmbiBGdW5jdGlvbiB0byBjYWxsXG4gKiBAcGFyYW0ge251bWJlcn0gbGVuIFZhbHVlIGJ5dGUgbGVuZ3RoXG4gKiBAcGFyYW0geyp9IHZhbCBWYWx1ZSB0byB3cml0ZVxuICogQGlnbm9yZVxuICovXG5mdW5jdGlvbiBPcChmbiwgbGVuLCB2YWwpIHtcblxuICAgIC8qKlxuICAgICAqIEZ1bmN0aW9uIHRvIGNhbGwuXG4gICAgICogQHR5cGUge2Z1bmN0aW9uKFVpbnQ4QXJyYXksIG51bWJlciwgKil9XG4gICAgICovXG4gICAgdGhpcy5mbiA9IGZuO1xuXG4gICAgLyoqXG4gICAgICogVmFsdWUgYnl0ZSBsZW5ndGguXG4gICAgICogQHR5cGUge251bWJlcn1cbiAgICAgKi9cbiAgICB0aGlzLmxlbiA9IGxlbjtcblxuICAgIC8qKlxuICAgICAqIE5leHQgb3BlcmF0aW9uLlxuICAgICAqIEB0eXBlIHtXcml0ZXIuT3B8dW5kZWZpbmVkfVxuICAgICAqL1xuICAgIHRoaXMubmV4dCA9IHVuZGVmaW5lZDtcblxuICAgIC8qKlxuICAgICAqIFZhbHVlIHRvIHdyaXRlLlxuICAgICAqIEB0eXBlIHsqfVxuICAgICAqL1xuICAgIHRoaXMudmFsID0gdmFsOyAvLyB0eXBlIHZhcmllc1xufVxuXG4vKiBpc3RhbmJ1bCBpZ25vcmUgbmV4dCAqL1xuZnVuY3Rpb24gbm9vcCgpIHt9IC8vIGVzbGludC1kaXNhYmxlLWxpbmUgbm8tZW1wdHktZnVuY3Rpb25cblxuLyoqXG4gKiBDb25zdHJ1Y3RzIGEgbmV3IHdyaXRlciBzdGF0ZSBpbnN0YW5jZS5cbiAqIEBjbGFzc2Rlc2MgQ29waWVkIHdyaXRlciBzdGF0ZS5cbiAqIEBtZW1iZXJvZiBXcml0ZXJcbiAqIEBjb25zdHJ1Y3RvclxuICogQHBhcmFtIHtXcml0ZXJ9IHdyaXRlciBXcml0ZXIgdG8gY29weSBzdGF0ZSBmcm9tXG4gKiBAaWdub3JlXG4gKi9cbmZ1bmN0aW9uIFN0YXRlKHdyaXRlcikge1xuXG4gICAgLyoqXG4gICAgICogQ3VycmVudCBoZWFkLlxuICAgICAqIEB0eXBlIHtXcml0ZXIuT3B9XG4gICAgICovXG4gICAgdGhpcy5oZWFkID0gd3JpdGVyLmhlYWQ7XG5cbiAgICAvKipcbiAgICAgKiBDdXJyZW50IHRhaWwuXG4gICAgICogQHR5cGUge1dyaXRlci5PcH1cbiAgICAgKi9cbiAgICB0aGlzLnRhaWwgPSB3cml0ZXIudGFpbDtcblxuICAgIC8qKlxuICAgICAqIEN1cnJlbnQgYnVmZmVyIGxlbmd0aC5cbiAgICAgKiBAdHlwZSB7bnVtYmVyfVxuICAgICAqL1xuICAgIHRoaXMubGVuID0gd3JpdGVyLmxlbjtcblxuICAgIC8qKlxuICAgICAqIE5leHQgc3RhdGUuXG4gICAgICogQHR5cGUge1N0YXRlfG51bGx9XG4gICAgICovXG4gICAgdGhpcy5uZXh0ID0gd3JpdGVyLnN0YXRlcztcbn1cblxuLyoqXG4gKiBDb25zdHJ1Y3RzIGEgbmV3IHdyaXRlciBpbnN0YW5jZS5cbiAqIEBjbGFzc2Rlc2MgV2lyZSBmb3JtYXQgd3JpdGVyIHVzaW5nIGBVaW50OEFycmF5YCBpZiBhdmFpbGFibGUsIG90aGVyd2lzZSBgQXJyYXlgLlxuICogQGNvbnN0cnVjdG9yXG4gKi9cbmZ1bmN0aW9uIFdyaXRlcigpIHtcblxuICAgIC8qKlxuICAgICAqIEN1cnJlbnQgbGVuZ3RoLlxuICAgICAqIEB0eXBlIHtudW1iZXJ9XG4gICAgICovXG4gICAgdGhpcy5sZW4gPSAwO1xuXG4gICAgLyoqXG4gICAgICogT3BlcmF0aW9ucyBoZWFkLlxuICAgICAqIEB0eXBlIHtPYmplY3R9XG4gICAgICovXG4gICAgdGhpcy5oZWFkID0gbmV3IE9wKG5vb3AsIDAsIDApO1xuXG4gICAgLyoqXG4gICAgICogT3BlcmF0aW9ucyB0YWlsXG4gICAgICogQHR5cGUge09iamVjdH1cbiAgICAgKi9cbiAgICB0aGlzLnRhaWwgPSB0aGlzLmhlYWQ7XG5cbiAgICAvKipcbiAgICAgKiBMaW5rZWQgZm9ya2VkIHN0YXRlcy5cbiAgICAgKiBAdHlwZSB7T2JqZWN0fG51bGx9XG4gICAgICovXG4gICAgdGhpcy5zdGF0ZXMgPSBudWxsO1xuXG4gICAgLy8gV2hlbiBhIHZhbHVlIGlzIHdyaXR0ZW4sIHRoZSB3cml0ZXIgY2FsY3VsYXRlcyBpdHMgYnl0ZSBsZW5ndGggYW5kIHB1dHMgaXQgaW50byBhIGxpbmtlZFxuICAgIC8vIGxpc3Qgb2Ygb3BlcmF0aW9ucyB0byBwZXJmb3JtIHdoZW4gZmluaXNoKCkgaXMgY2FsbGVkLiBUaGlzIGJvdGggYWxsb3dzIHVzIHRvIGFsbG9jYXRlXG4gICAgLy8gYnVmZmVycyBvZiB0aGUgZXhhY3QgcmVxdWlyZWQgc2l6ZSBhbmQgcmVkdWNlcyB0aGUgYW1vdW50IG9mIHdvcmsgd2UgaGF2ZSB0byBkbyBjb21wYXJlZFxuICAgIC8vIHRvIGZpcnN0IGNhbGN1bGF0aW5nIG92ZXIgb2JqZWN0cyBhbmQgdGhlbiBlbmNvZGluZyBvdmVyIG9iamVjdHMuIEluIG91ciBjYXNlLCB0aGUgZW5jb2RpbmdcbiAgICAvLyBwYXJ0IGlzIGp1c3QgYSBsaW5rZWQgbGlzdCB3YWxrIGNhbGxpbmcgb3BlcmF0aW9ucyB3aXRoIGFscmVhZHkgcHJlcGFyZWQgdmFsdWVzLlxufVxuXG52YXIgY3JlYXRlID0gZnVuY3Rpb24gY3JlYXRlKCkge1xuICAgIHJldHVybiB1dGlsLkJ1ZmZlclxuICAgICAgICA/IGZ1bmN0aW9uIGNyZWF0ZV9idWZmZXJfc2V0dXAoKSB7XG4gICAgICAgICAgICByZXR1cm4gKFdyaXRlci5jcmVhdGUgPSBmdW5jdGlvbiBjcmVhdGVfYnVmZmVyKCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBuZXcgQnVmZmVyV3JpdGVyKCk7XG4gICAgICAgICAgICB9KSgpO1xuICAgICAgICB9XG4gICAgICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0ICovXG4gICAgICAgIDogZnVuY3Rpb24gY3JlYXRlX2FycmF5KCkge1xuICAgICAgICAgICAgcmV0dXJuIG5ldyBXcml0ZXIoKTtcbiAgICAgICAgfTtcbn07XG5cbi8qKlxuICogQ3JlYXRlcyBhIG5ldyB3cml0ZXIuXG4gKiBAZnVuY3Rpb25cbiAqIEByZXR1cm5zIHtCdWZmZXJXcml0ZXJ8V3JpdGVyfSBBIHtAbGluayBCdWZmZXJXcml0ZXJ9IHdoZW4gQnVmZmVycyBhcmUgc3VwcG9ydGVkLCBvdGhlcndpc2UgYSB7QGxpbmsgV3JpdGVyfVxuICovXG5Xcml0ZXIuY3JlYXRlID0gY3JlYXRlKCk7XG5cbi8qKlxuICogQWxsb2NhdGVzIGEgYnVmZmVyIG9mIHRoZSBzcGVjaWZpZWQgc2l6ZS5cbiAqIEBwYXJhbSB7bnVtYmVyfSBzaXplIEJ1ZmZlciBzaXplXG4gKiBAcmV0dXJucyB7VWludDhBcnJheX0gQnVmZmVyXG4gKi9cbldyaXRlci5hbGxvYyA9IGZ1bmN0aW9uIGFsbG9jKHNpemUpIHtcbiAgICByZXR1cm4gbmV3IHV0aWwuQXJyYXkoc2l6ZSk7XG59O1xuXG4vLyBVc2UgVWludDhBcnJheSBidWZmZXIgcG9vbCBpbiB0aGUgYnJvd3NlciwganVzdCBsaWtlIG5vZGUgZG9lcyB3aXRoIGJ1ZmZlcnNcbi8qIGlzdGFuYnVsIGlnbm9yZSBlbHNlICovXG5pZiAodXRpbC5BcnJheSAhPT0gQXJyYXkpXG4gICAgV3JpdGVyLmFsbG9jID0gdXRpbC5wb29sKFdyaXRlci5hbGxvYywgdXRpbC5BcnJheS5wcm90b3R5cGUuc3ViYXJyYXkpO1xuXG4vKipcbiAqIFB1c2hlcyBhIG5ldyBvcGVyYXRpb24gdG8gdGhlIHF1ZXVlLlxuICogQHBhcmFtIHtmdW5jdGlvbihVaW50OEFycmF5LCBudW1iZXIsICopfSBmbiBGdW5jdGlvbiB0byBjYWxsXG4gKiBAcGFyYW0ge251bWJlcn0gbGVuIFZhbHVlIGJ5dGUgbGVuZ3RoXG4gKiBAcGFyYW0ge251bWJlcn0gdmFsIFZhbHVlIHRvIHdyaXRlXG4gKiBAcmV0dXJucyB7V3JpdGVyfSBgdGhpc2BcbiAqIEBwcml2YXRlXG4gKi9cbldyaXRlci5wcm90b3R5cGUuX3B1c2ggPSBmdW5jdGlvbiBwdXNoKGZuLCBsZW4sIHZhbCkge1xuICAgIHRoaXMudGFpbCA9IHRoaXMudGFpbC5uZXh0ID0gbmV3IE9wKGZuLCBsZW4sIHZhbCk7XG4gICAgdGhpcy5sZW4gKz0gbGVuO1xuICAgIHJldHVybiB0aGlzO1xufTtcblxuZnVuY3Rpb24gd3JpdGVCeXRlKHZhbCwgYnVmLCBwb3MpIHtcbiAgICBidWZbcG9zXSA9IHZhbCAmIDI1NTtcbn1cblxuZnVuY3Rpb24gd3JpdGVWYXJpbnQzMih2YWwsIGJ1ZiwgcG9zKSB7XG4gICAgd2hpbGUgKHZhbCA+IDEyNykge1xuICAgICAgICBidWZbcG9zKytdID0gdmFsICYgMTI3IHwgMTI4O1xuICAgICAgICB2YWwgPj4+PSA3O1xuICAgIH1cbiAgICBidWZbcG9zXSA9IHZhbDtcbn1cblxuLyoqXG4gKiBDb25zdHJ1Y3RzIGEgbmV3IHZhcmludCB3cml0ZXIgb3BlcmF0aW9uIGluc3RhbmNlLlxuICogQGNsYXNzZGVzYyBTY2hlZHVsZWQgdmFyaW50IHdyaXRlciBvcGVyYXRpb24uXG4gKiBAZXh0ZW5kcyBPcFxuICogQGNvbnN0cnVjdG9yXG4gKiBAcGFyYW0ge251bWJlcn0gbGVuIFZhbHVlIGJ5dGUgbGVuZ3RoXG4gKiBAcGFyYW0ge251bWJlcn0gdmFsIFZhbHVlIHRvIHdyaXRlXG4gKiBAaWdub3JlXG4gKi9cbmZ1bmN0aW9uIFZhcmludE9wKGxlbiwgdmFsKSB7XG4gICAgdGhpcy5sZW4gPSBsZW47XG4gICAgdGhpcy5uZXh0ID0gdW5kZWZpbmVkO1xuICAgIHRoaXMudmFsID0gdmFsO1xufVxuXG5WYXJpbnRPcC5wcm90b3R5cGUgPSBPYmplY3QuY3JlYXRlKE9wLnByb3RvdHlwZSk7XG5WYXJpbnRPcC5wcm90b3R5cGUuZm4gPSB3cml0ZVZhcmludDMyO1xuXG4vKipcbiAqIFdyaXRlcyBhbiB1bnNpZ25lZCAzMiBiaXQgdmFsdWUgYXMgYSB2YXJpbnQuXG4gKiBAcGFyYW0ge251bWJlcn0gdmFsdWUgVmFsdWUgdG8gd3JpdGVcbiAqIEByZXR1cm5zIHtXcml0ZXJ9IGB0aGlzYFxuICovXG5Xcml0ZXIucHJvdG90eXBlLnVpbnQzMiA9IGZ1bmN0aW9uIHdyaXRlX3VpbnQzMih2YWx1ZSkge1xuICAgIC8vIGhlcmUsIHRoZSBjYWxsIHRvIHRoaXMucHVzaCBoYXMgYmVlbiBpbmxpbmVkIGFuZCBhIHZhcmludCBzcGVjaWZpYyBPcCBzdWJjbGFzcyBpcyB1c2VkLlxuICAgIC8vIHVpbnQzMiBpcyBieSBmYXIgdGhlIG1vc3QgZnJlcXVlbnRseSB1c2VkIG9wZXJhdGlvbiBhbmQgYmVuZWZpdHMgc2lnbmlmaWNhbnRseSBmcm9tIHRoaXMuXG4gICAgdGhpcy5sZW4gKz0gKHRoaXMudGFpbCA9IHRoaXMudGFpbC5uZXh0ID0gbmV3IFZhcmludE9wKFxuICAgICAgICAodmFsdWUgPSB2YWx1ZSA+Pj4gMClcbiAgICAgICAgICAgICAgICA8IDEyOCAgICAgICA/IDFcbiAgICAgICAgOiB2YWx1ZSA8IDE2Mzg0ICAgICA/IDJcbiAgICAgICAgOiB2YWx1ZSA8IDIwOTcxNTIgICA/IDNcbiAgICAgICAgOiB2YWx1ZSA8IDI2ODQzNTQ1NiA/IDRcbiAgICAgICAgOiAgICAgICAgICAgICAgICAgICAgIDUsXG4gICAgdmFsdWUpKS5sZW47XG4gICAgcmV0dXJuIHRoaXM7XG59O1xuXG4vKipcbiAqIFdyaXRlcyBhIHNpZ25lZCAzMiBiaXQgdmFsdWUgYXMgYSB2YXJpbnQuXG4gKiBAZnVuY3Rpb25cbiAqIEBwYXJhbSB7bnVtYmVyfSB2YWx1ZSBWYWx1ZSB0byB3cml0ZVxuICogQHJldHVybnMge1dyaXRlcn0gYHRoaXNgXG4gKi9cbldyaXRlci5wcm90b3R5cGUuaW50MzIgPSBmdW5jdGlvbiB3cml0ZV9pbnQzMih2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZSA8IDBcbiAgICAgICAgPyB0aGlzLl9wdXNoKHdyaXRlVmFyaW50NjQsIDEwLCBMb25nQml0cy5mcm9tTnVtYmVyKHZhbHVlKSkgLy8gMTAgYnl0ZXMgcGVyIHNwZWNcbiAgICAgICAgOiB0aGlzLnVpbnQzMih2YWx1ZSk7XG59O1xuXG4vKipcbiAqIFdyaXRlcyBhIDMyIGJpdCB2YWx1ZSBhcyBhIHZhcmludCwgemlnLXphZyBlbmNvZGVkLlxuICogQHBhcmFtIHtudW1iZXJ9IHZhbHVlIFZhbHVlIHRvIHdyaXRlXG4gKiBAcmV0dXJucyB7V3JpdGVyfSBgdGhpc2BcbiAqL1xuV3JpdGVyLnByb3RvdHlwZS5zaW50MzIgPSBmdW5jdGlvbiB3cml0ZV9zaW50MzIodmFsdWUpIHtcbiAgICByZXR1cm4gdGhpcy51aW50MzIoKHZhbHVlIDw8IDEgXiB2YWx1ZSA+PiAzMSkgPj4+IDApO1xufTtcblxuZnVuY3Rpb24gd3JpdGVWYXJpbnQ2NCh2YWwsIGJ1ZiwgcG9zKSB7XG4gICAgd2hpbGUgKHZhbC5oaSkge1xuICAgICAgICBidWZbcG9zKytdID0gdmFsLmxvICYgMTI3IHwgMTI4O1xuICAgICAgICB2YWwubG8gPSAodmFsLmxvID4+PiA3IHwgdmFsLmhpIDw8IDI1KSA+Pj4gMDtcbiAgICAgICAgdmFsLmhpID4+Pj0gNztcbiAgICB9XG4gICAgd2hpbGUgKHZhbC5sbyA+IDEyNykge1xuICAgICAgICBidWZbcG9zKytdID0gdmFsLmxvICYgMTI3IHwgMTI4O1xuICAgICAgICB2YWwubG8gPSB2YWwubG8gPj4+IDc7XG4gICAgfVxuICAgIGJ1Zltwb3MrK10gPSB2YWwubG87XG59XG5cbi8qKlxuICogV3JpdGVzIGFuIHVuc2lnbmVkIDY0IGJpdCB2YWx1ZSBhcyBhIHZhcmludC5cbiAqIEBwYXJhbSB7TG9uZ3xudW1iZXJ8c3RyaW5nfSB2YWx1ZSBWYWx1ZSB0byB3cml0ZVxuICogQHJldHVybnMge1dyaXRlcn0gYHRoaXNgXG4gKiBAdGhyb3dzIHtUeXBlRXJyb3J9IElmIGB2YWx1ZWAgaXMgYSBzdHJpbmcgYW5kIG5vIGxvbmcgbGlicmFyeSBpcyBwcmVzZW50LlxuICovXG5Xcml0ZXIucHJvdG90eXBlLnVpbnQ2NCA9IGZ1bmN0aW9uIHdyaXRlX3VpbnQ2NCh2YWx1ZSkge1xuICAgIHZhciBiaXRzID0gTG9uZ0JpdHMuZnJvbSh2YWx1ZSk7XG4gICAgcmV0dXJuIHRoaXMuX3B1c2god3JpdGVWYXJpbnQ2NCwgYml0cy5sZW5ndGgoKSwgYml0cyk7XG59O1xuXG4vKipcbiAqIFdyaXRlcyBhIHNpZ25lZCA2NCBiaXQgdmFsdWUgYXMgYSB2YXJpbnQuXG4gKiBAZnVuY3Rpb25cbiAqIEBwYXJhbSB7TG9uZ3xudW1iZXJ8c3RyaW5nfSB2YWx1ZSBWYWx1ZSB0byB3cml0ZVxuICogQHJldHVybnMge1dyaXRlcn0gYHRoaXNgXG4gKiBAdGhyb3dzIHtUeXBlRXJyb3J9IElmIGB2YWx1ZWAgaXMgYSBzdHJpbmcgYW5kIG5vIGxvbmcgbGlicmFyeSBpcyBwcmVzZW50LlxuICovXG5Xcml0ZXIucHJvdG90eXBlLmludDY0ID0gV3JpdGVyLnByb3RvdHlwZS51aW50NjQ7XG5cbi8qKlxuICogV3JpdGVzIGEgc2lnbmVkIDY0IGJpdCB2YWx1ZSBhcyBhIHZhcmludCwgemlnLXphZyBlbmNvZGVkLlxuICogQHBhcmFtIHtMb25nfG51bWJlcnxzdHJpbmd9IHZhbHVlIFZhbHVlIHRvIHdyaXRlXG4gKiBAcmV0dXJucyB7V3JpdGVyfSBgdGhpc2BcbiAqIEB0aHJvd3Mge1R5cGVFcnJvcn0gSWYgYHZhbHVlYCBpcyBhIHN0cmluZyBhbmQgbm8gbG9uZyBsaWJyYXJ5IGlzIHByZXNlbnQuXG4gKi9cbldyaXRlci5wcm90b3R5cGUuc2ludDY0ID0gZnVuY3Rpb24gd3JpdGVfc2ludDY0KHZhbHVlKSB7XG4gICAgdmFyIGJpdHMgPSBMb25nQml0cy5mcm9tKHZhbHVlKS56ekVuY29kZSgpO1xuICAgIHJldHVybiB0aGlzLl9wdXNoKHdyaXRlVmFyaW50NjQsIGJpdHMubGVuZ3RoKCksIGJpdHMpO1xufTtcblxuLyoqXG4gKiBXcml0ZXMgYSBib29saXNoIHZhbHVlIGFzIGEgdmFyaW50LlxuICogQHBhcmFtIHtib29sZWFufSB2YWx1ZSBWYWx1ZSB0byB3cml0ZVxuICogQHJldHVybnMge1dyaXRlcn0gYHRoaXNgXG4gKi9cbldyaXRlci5wcm90b3R5cGUuYm9vbCA9IGZ1bmN0aW9uIHdyaXRlX2Jvb2wodmFsdWUpIHtcbiAgICByZXR1cm4gdGhpcy5fcHVzaCh3cml0ZUJ5dGUsIDEsIHZhbHVlID8gMSA6IDApO1xufTtcblxuZnVuY3Rpb24gd3JpdGVGaXhlZDMyKHZhbCwgYnVmLCBwb3MpIHtcbiAgICBidWZbcG9zICAgIF0gPSAgdmFsICAgICAgICAgJiAyNTU7XG4gICAgYnVmW3BvcyArIDFdID0gIHZhbCA+Pj4gOCAgICYgMjU1O1xuICAgIGJ1Zltwb3MgKyAyXSA9ICB2YWwgPj4+IDE2ICAmIDI1NTtcbiAgICBidWZbcG9zICsgM10gPSAgdmFsID4+PiAyNDtcbn1cblxuLyoqXG4gKiBXcml0ZXMgYW4gdW5zaWduZWQgMzIgYml0IHZhbHVlIGFzIGZpeGVkIDMyIGJpdHMuXG4gKiBAcGFyYW0ge251bWJlcn0gdmFsdWUgVmFsdWUgdG8gd3JpdGVcbiAqIEByZXR1cm5zIHtXcml0ZXJ9IGB0aGlzYFxuICovXG5Xcml0ZXIucHJvdG90eXBlLmZpeGVkMzIgPSBmdW5jdGlvbiB3cml0ZV9maXhlZDMyKHZhbHVlKSB7XG4gICAgcmV0dXJuIHRoaXMuX3B1c2god3JpdGVGaXhlZDMyLCA0LCB2YWx1ZSA+Pj4gMCk7XG59O1xuXG4vKipcbiAqIFdyaXRlcyBhIHNpZ25lZCAzMiBiaXQgdmFsdWUgYXMgZml4ZWQgMzIgYml0cy5cbiAqIEBmdW5jdGlvblxuICogQHBhcmFtIHtudW1iZXJ9IHZhbHVlIFZhbHVlIHRvIHdyaXRlXG4gKiBAcmV0dXJucyB7V3JpdGVyfSBgdGhpc2BcbiAqL1xuV3JpdGVyLnByb3RvdHlwZS5zZml4ZWQzMiA9IFdyaXRlci5wcm90b3R5cGUuZml4ZWQzMjtcblxuLyoqXG4gKiBXcml0ZXMgYW4gdW5zaWduZWQgNjQgYml0IHZhbHVlIGFzIGZpeGVkIDY0IGJpdHMuXG4gKiBAcGFyYW0ge0xvbmd8bnVtYmVyfHN0cmluZ30gdmFsdWUgVmFsdWUgdG8gd3JpdGVcbiAqIEByZXR1cm5zIHtXcml0ZXJ9IGB0aGlzYFxuICogQHRocm93cyB7VHlwZUVycm9yfSBJZiBgdmFsdWVgIGlzIGEgc3RyaW5nIGFuZCBubyBsb25nIGxpYnJhcnkgaXMgcHJlc2VudC5cbiAqL1xuV3JpdGVyLnByb3RvdHlwZS5maXhlZDY0ID0gZnVuY3Rpb24gd3JpdGVfZml4ZWQ2NCh2YWx1ZSkge1xuICAgIHZhciBiaXRzID0gTG9uZ0JpdHMuZnJvbSh2YWx1ZSk7XG4gICAgcmV0dXJuIHRoaXMuX3B1c2god3JpdGVGaXhlZDMyLCA0LCBiaXRzLmxvKS5fcHVzaCh3cml0ZUZpeGVkMzIsIDQsIGJpdHMuaGkpO1xufTtcblxuLyoqXG4gKiBXcml0ZXMgYSBzaWduZWQgNjQgYml0IHZhbHVlIGFzIGZpeGVkIDY0IGJpdHMuXG4gKiBAZnVuY3Rpb25cbiAqIEBwYXJhbSB7TG9uZ3xudW1iZXJ8c3RyaW5nfSB2YWx1ZSBWYWx1ZSB0byB3cml0ZVxuICogQHJldHVybnMge1dyaXRlcn0gYHRoaXNgXG4gKiBAdGhyb3dzIHtUeXBlRXJyb3J9IElmIGB2YWx1ZWAgaXMgYSBzdHJpbmcgYW5kIG5vIGxvbmcgbGlicmFyeSBpcyBwcmVzZW50LlxuICovXG5Xcml0ZXIucHJvdG90eXBlLnNmaXhlZDY0ID0gV3JpdGVyLnByb3RvdHlwZS5maXhlZDY0O1xuXG4vKipcbiAqIFdyaXRlcyBhIGZsb2F0ICgzMiBiaXQpLlxuICogQGZ1bmN0aW9uXG4gKiBAcGFyYW0ge251bWJlcn0gdmFsdWUgVmFsdWUgdG8gd3JpdGVcbiAqIEByZXR1cm5zIHtXcml0ZXJ9IGB0aGlzYFxuICovXG5Xcml0ZXIucHJvdG90eXBlLmZsb2F0ID0gZnVuY3Rpb24gd3JpdGVfZmxvYXQodmFsdWUpIHtcbiAgICByZXR1cm4gdGhpcy5fcHVzaCh1dGlsLmZsb2F0LndyaXRlRmxvYXRMRSwgNCwgdmFsdWUpO1xufTtcblxuLyoqXG4gKiBXcml0ZXMgYSBkb3VibGUgKDY0IGJpdCBmbG9hdCkuXG4gKiBAZnVuY3Rpb25cbiAqIEBwYXJhbSB7bnVtYmVyfSB2YWx1ZSBWYWx1ZSB0byB3cml0ZVxuICogQHJldHVybnMge1dyaXRlcn0gYHRoaXNgXG4gKi9cbldyaXRlci5wcm90b3R5cGUuZG91YmxlID0gZnVuY3Rpb24gd3JpdGVfZG91YmxlKHZhbHVlKSB7XG4gICAgcmV0dXJuIHRoaXMuX3B1c2godXRpbC5mbG9hdC53cml0ZURvdWJsZUxFLCA4LCB2YWx1ZSk7XG59O1xuXG52YXIgd3JpdGVCeXRlcyA9IHV0aWwuQXJyYXkucHJvdG90eXBlLnNldFxuICAgID8gZnVuY3Rpb24gd3JpdGVCeXRlc19zZXQodmFsLCBidWYsIHBvcykge1xuICAgICAgICBidWYuc2V0KHZhbCwgcG9zKTsgLy8gYWxzbyB3b3JrcyBmb3IgcGxhaW4gYXJyYXkgdmFsdWVzXG4gICAgfVxuICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0ICovXG4gICAgOiBmdW5jdGlvbiB3cml0ZUJ5dGVzX2Zvcih2YWwsIGJ1ZiwgcG9zKSB7XG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdmFsLmxlbmd0aDsgKytpKVxuICAgICAgICAgICAgYnVmW3BvcyArIGldID0gdmFsW2ldO1xuICAgIH07XG5cbi8qKlxuICogV3JpdGVzIGEgc2VxdWVuY2Ugb2YgYnl0ZXMuXG4gKiBAcGFyYW0ge1VpbnQ4QXJyYXl8c3RyaW5nfSB2YWx1ZSBCdWZmZXIgb3IgYmFzZTY0IGVuY29kZWQgc3RyaW5nIHRvIHdyaXRlXG4gKiBAcmV0dXJucyB7V3JpdGVyfSBgdGhpc2BcbiAqL1xuV3JpdGVyLnByb3RvdHlwZS5ieXRlcyA9IGZ1bmN0aW9uIHdyaXRlX2J5dGVzKHZhbHVlKSB7XG4gICAgdmFyIGxlbiA9IHZhbHVlLmxlbmd0aCA+Pj4gMDtcbiAgICBpZiAoIWxlbilcbiAgICAgICAgcmV0dXJuIHRoaXMuX3B1c2god3JpdGVCeXRlLCAxLCAwKTtcbiAgICBpZiAodXRpbC5pc1N0cmluZyh2YWx1ZSkpIHtcbiAgICAgICAgdmFyIGJ1ZiA9IFdyaXRlci5hbGxvYyhsZW4gPSBiYXNlNjQubGVuZ3RoKHZhbHVlKSk7XG4gICAgICAgIGJhc2U2NC5kZWNvZGUodmFsdWUsIGJ1ZiwgMCk7XG4gICAgICAgIHZhbHVlID0gYnVmO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy51aW50MzIobGVuKS5fcHVzaCh3cml0ZUJ5dGVzLCBsZW4sIHZhbHVlKTtcbn07XG5cbi8qKlxuICogV3JpdGVzIGEgc3RyaW5nLlxuICogQHBhcmFtIHtzdHJpbmd9IHZhbHVlIFZhbHVlIHRvIHdyaXRlXG4gKiBAcmV0dXJucyB7V3JpdGVyfSBgdGhpc2BcbiAqL1xuV3JpdGVyLnByb3RvdHlwZS5zdHJpbmcgPSBmdW5jdGlvbiB3cml0ZV9zdHJpbmcodmFsdWUpIHtcbiAgICB2YXIgbGVuID0gdXRmOC5sZW5ndGgodmFsdWUpO1xuICAgIHJldHVybiBsZW5cbiAgICAgICAgPyB0aGlzLnVpbnQzMihsZW4pLl9wdXNoKHV0Zjgud3JpdGUsIGxlbiwgdmFsdWUpXG4gICAgICAgIDogdGhpcy5fcHVzaCh3cml0ZUJ5dGUsIDEsIDApO1xufTtcblxuLyoqXG4gKiBGb3JrcyB0aGlzIHdyaXRlcidzIHN0YXRlIGJ5IHB1c2hpbmcgaXQgdG8gYSBzdGFjay5cbiAqIENhbGxpbmcge0BsaW5rIFdyaXRlciNyZXNldHxyZXNldH0gb3Ige0BsaW5rIFdyaXRlciNsZGVsaW18bGRlbGltfSByZXNldHMgdGhlIHdyaXRlciB0byB0aGUgcHJldmlvdXMgc3RhdGUuXG4gKiBAcmV0dXJucyB7V3JpdGVyfSBgdGhpc2BcbiAqL1xuV3JpdGVyLnByb3RvdHlwZS5mb3JrID0gZnVuY3Rpb24gZm9yaygpIHtcbiAgICB0aGlzLnN0YXRlcyA9IG5ldyBTdGF0ZSh0aGlzKTtcbiAgICB0aGlzLmhlYWQgPSB0aGlzLnRhaWwgPSBuZXcgT3Aobm9vcCwgMCwgMCk7XG4gICAgdGhpcy5sZW4gPSAwO1xuICAgIHJldHVybiB0aGlzO1xufTtcblxuLyoqXG4gKiBSZXNldHMgdGhpcyBpbnN0YW5jZSB0byB0aGUgbGFzdCBzdGF0ZS5cbiAqIEByZXR1cm5zIHtXcml0ZXJ9IGB0aGlzYFxuICovXG5Xcml0ZXIucHJvdG90eXBlLnJlc2V0ID0gZnVuY3Rpb24gcmVzZXQoKSB7XG4gICAgaWYgKHRoaXMuc3RhdGVzKSB7XG4gICAgICAgIHRoaXMuaGVhZCAgID0gdGhpcy5zdGF0ZXMuaGVhZDtcbiAgICAgICAgdGhpcy50YWlsICAgPSB0aGlzLnN0YXRlcy50YWlsO1xuICAgICAgICB0aGlzLmxlbiAgICA9IHRoaXMuc3RhdGVzLmxlbjtcbiAgICAgICAgdGhpcy5zdGF0ZXMgPSB0aGlzLnN0YXRlcy5uZXh0O1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHRoaXMuaGVhZCA9IHRoaXMudGFpbCA9IG5ldyBPcChub29wLCAwLCAwKTtcbiAgICAgICAgdGhpcy5sZW4gID0gMDtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXM7XG59O1xuXG4vKipcbiAqIFJlc2V0cyB0byB0aGUgbGFzdCBzdGF0ZSBhbmQgYXBwZW5kcyB0aGUgZm9yayBzdGF0ZSdzIGN1cnJlbnQgd3JpdGUgbGVuZ3RoIGFzIGEgdmFyaW50IGZvbGxvd2VkIGJ5IGl0cyBvcGVyYXRpb25zLlxuICogQHJldHVybnMge1dyaXRlcn0gYHRoaXNgXG4gKi9cbldyaXRlci5wcm90b3R5cGUubGRlbGltID0gZnVuY3Rpb24gbGRlbGltKCkge1xuICAgIHZhciBoZWFkID0gdGhpcy5oZWFkLFxuICAgICAgICB0YWlsID0gdGhpcy50YWlsLFxuICAgICAgICBsZW4gID0gdGhpcy5sZW47XG4gICAgdGhpcy5yZXNldCgpLnVpbnQzMihsZW4pO1xuICAgIGlmIChsZW4pIHtcbiAgICAgICAgdGhpcy50YWlsLm5leHQgPSBoZWFkLm5leHQ7IC8vIHNraXAgbm9vcFxuICAgICAgICB0aGlzLnRhaWwgPSB0YWlsO1xuICAgICAgICB0aGlzLmxlbiArPSBsZW47XG4gICAgfVxuICAgIHJldHVybiB0aGlzO1xufTtcblxuLyoqXG4gKiBGaW5pc2hlcyB0aGUgd3JpdGUgb3BlcmF0aW9uLlxuICogQHJldHVybnMge1VpbnQ4QXJyYXl9IEZpbmlzaGVkIGJ1ZmZlclxuICovXG5Xcml0ZXIucHJvdG90eXBlLmZpbmlzaCA9IGZ1bmN0aW9uIGZpbmlzaCgpIHtcbiAgICB2YXIgaGVhZCA9IHRoaXMuaGVhZC5uZXh0LCAvLyBza2lwIG5vb3BcbiAgICAgICAgYnVmICA9IHRoaXMuY29uc3RydWN0b3IuYWxsb2ModGhpcy5sZW4pLFxuICAgICAgICBwb3MgID0gMDtcbiAgICB3aGlsZSAoaGVhZCkge1xuICAgICAgICBoZWFkLmZuKGhlYWQudmFsLCBidWYsIHBvcyk7XG4gICAgICAgIHBvcyArPSBoZWFkLmxlbjtcbiAgICAgICAgaGVhZCA9IGhlYWQubmV4dDtcbiAgICB9XG4gICAgLy8gdGhpcy5oZWFkID0gdGhpcy50YWlsID0gbnVsbDtcbiAgICByZXR1cm4gYnVmO1xufTtcblxuV3JpdGVyLl9jb25maWd1cmUgPSBmdW5jdGlvbihCdWZmZXJXcml0ZXJfKSB7XG4gICAgQnVmZmVyV3JpdGVyID0gQnVmZmVyV3JpdGVyXztcbiAgICBXcml0ZXIuY3JlYXRlID0gY3JlYXRlKCk7XG4gICAgQnVmZmVyV3JpdGVyLl9jb25maWd1cmUoKTtcbn07XG4iLCJcInVzZSBzdHJpY3RcIjtcbm1vZHVsZS5leHBvcnRzID0gQnVmZmVyV3JpdGVyO1xuXG4vLyBleHRlbmRzIFdyaXRlclxudmFyIFdyaXRlciA9IHJlcXVpcmUoXCIuL3dyaXRlclwiKTtcbihCdWZmZXJXcml0ZXIucHJvdG90eXBlID0gT2JqZWN0LmNyZWF0ZShXcml0ZXIucHJvdG90eXBlKSkuY29uc3RydWN0b3IgPSBCdWZmZXJXcml0ZXI7XG5cbnZhciB1dGlsID0gcmVxdWlyZShcIi4vdXRpbC9taW5pbWFsXCIpO1xuXG4vKipcbiAqIENvbnN0cnVjdHMgYSBuZXcgYnVmZmVyIHdyaXRlciBpbnN0YW5jZS5cbiAqIEBjbGFzc2Rlc2MgV2lyZSBmb3JtYXQgd3JpdGVyIHVzaW5nIG5vZGUgYnVmZmVycy5cbiAqIEBleHRlbmRzIFdyaXRlclxuICogQGNvbnN0cnVjdG9yXG4gKi9cbmZ1bmN0aW9uIEJ1ZmZlcldyaXRlcigpIHtcbiAgICBXcml0ZXIuY2FsbCh0aGlzKTtcbn1cblxuQnVmZmVyV3JpdGVyLl9jb25maWd1cmUgPSBmdW5jdGlvbiAoKSB7XG4gICAgLyoqXG4gICAgICogQWxsb2NhdGVzIGEgYnVmZmVyIG9mIHRoZSBzcGVjaWZpZWQgc2l6ZS5cbiAgICAgKiBAZnVuY3Rpb25cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gc2l6ZSBCdWZmZXIgc2l6ZVxuICAgICAqIEByZXR1cm5zIHtCdWZmZXJ9IEJ1ZmZlclxuICAgICAqL1xuICAgIEJ1ZmZlcldyaXRlci5hbGxvYyA9IHV0aWwuX0J1ZmZlcl9hbGxvY1Vuc2FmZTtcblxuICAgIEJ1ZmZlcldyaXRlci53cml0ZUJ5dGVzQnVmZmVyID0gdXRpbC5CdWZmZXIgJiYgdXRpbC5CdWZmZXIucHJvdG90eXBlIGluc3RhbmNlb2YgVWludDhBcnJheSAmJiB1dGlsLkJ1ZmZlci5wcm90b3R5cGUuc2V0Lm5hbWUgPT09IFwic2V0XCJcbiAgICAgICAgPyBmdW5jdGlvbiB3cml0ZUJ5dGVzQnVmZmVyX3NldCh2YWwsIGJ1ZiwgcG9zKSB7XG4gICAgICAgICAgYnVmLnNldCh2YWwsIHBvcyk7IC8vIGZhc3RlciB0aGFuIGNvcHkgKHJlcXVpcmVzIG5vZGUgPj0gNCB3aGVyZSBCdWZmZXJzIGV4dGVuZCBVaW50OEFycmF5IGFuZCBzZXQgaXMgcHJvcGVybHkgaW5oZXJpdGVkKVxuICAgICAgICAgIC8vIGFsc28gd29ya3MgZm9yIHBsYWluIGFycmF5IHZhbHVlc1xuICAgICAgICB9XG4gICAgICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0ICovXG4gICAgICAgIDogZnVuY3Rpb24gd3JpdGVCeXRlc0J1ZmZlcl9jb3B5KHZhbCwgYnVmLCBwb3MpIHtcbiAgICAgICAgICBpZiAodmFsLmNvcHkpIC8vIEJ1ZmZlciB2YWx1ZXNcbiAgICAgICAgICAgIHZhbC5jb3B5KGJ1ZiwgcG9zLCAwLCB2YWwubGVuZ3RoKTtcbiAgICAgICAgICBlbHNlIGZvciAodmFyIGkgPSAwOyBpIDwgdmFsLmxlbmd0aDspIC8vIHBsYWluIGFycmF5IHZhbHVlc1xuICAgICAgICAgICAgYnVmW3BvcysrXSA9IHZhbFtpKytdO1xuICAgICAgICB9O1xufTtcblxuXG4vKipcbiAqIEBvdmVycmlkZVxuICovXG5CdWZmZXJXcml0ZXIucHJvdG90eXBlLmJ5dGVzID0gZnVuY3Rpb24gd3JpdGVfYnl0ZXNfYnVmZmVyKHZhbHVlKSB7XG4gICAgaWYgKHV0aWwuaXNTdHJpbmcodmFsdWUpKVxuICAgICAgICB2YWx1ZSA9IHV0aWwuX0J1ZmZlcl9mcm9tKHZhbHVlLCBcImJhc2U2NFwiKTtcbiAgICB2YXIgbGVuID0gdmFsdWUubGVuZ3RoID4+PiAwO1xuICAgIHRoaXMudWludDMyKGxlbik7XG4gICAgaWYgKGxlbilcbiAgICAgICAgdGhpcy5fcHVzaChCdWZmZXJXcml0ZXIud3JpdGVCeXRlc0J1ZmZlciwgbGVuLCB2YWx1ZSk7XG4gICAgcmV0dXJuIHRoaXM7XG59O1xuXG5mdW5jdGlvbiB3cml0ZVN0cmluZ0J1ZmZlcih2YWwsIGJ1ZiwgcG9zKSB7XG4gICAgaWYgKHZhbC5sZW5ndGggPCA0MCkgLy8gcGxhaW4ganMgaXMgZmFzdGVyIGZvciBzaG9ydCBzdHJpbmdzIChwcm9iYWJseSBkdWUgdG8gcmVkdW5kYW50IGFzc2VydGlvbnMpXG4gICAgICAgIHV0aWwudXRmOC53cml0ZSh2YWwsIGJ1ZiwgcG9zKTtcbiAgICBlbHNlIGlmIChidWYudXRmOFdyaXRlKVxuICAgICAgICBidWYudXRmOFdyaXRlKHZhbCwgcG9zKTtcbiAgICBlbHNlXG4gICAgICAgIGJ1Zi53cml0ZSh2YWwsIHBvcyk7XG59XG5cbi8qKlxuICogQG92ZXJyaWRlXG4gKi9cbkJ1ZmZlcldyaXRlci5wcm90b3R5cGUuc3RyaW5nID0gZnVuY3Rpb24gd3JpdGVfc3RyaW5nX2J1ZmZlcih2YWx1ZSkge1xuICAgIHZhciBsZW4gPSB1dGlsLkJ1ZmZlci5ieXRlTGVuZ3RoKHZhbHVlKTtcbiAgICB0aGlzLnVpbnQzMihsZW4pO1xuICAgIGlmIChsZW4pXG4gICAgICAgIHRoaXMuX3B1c2god3JpdGVTdHJpbmdCdWZmZXIsIGxlbiwgdmFsdWUpO1xuICAgIHJldHVybiB0aGlzO1xufTtcblxuXG4vKipcbiAqIEZpbmlzaGVzIHRoZSB3cml0ZSBvcGVyYXRpb24uXG4gKiBAbmFtZSBCdWZmZXJXcml0ZXIjZmluaXNoXG4gKiBAZnVuY3Rpb25cbiAqIEByZXR1cm5zIHtCdWZmZXJ9IEZpbmlzaGVkIGJ1ZmZlclxuICovXG5cbkJ1ZmZlcldyaXRlci5fY29uZmlndXJlKCk7XG4iLCIvLyBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cblxuLyogZXNsaW50LWRpc2FibGUgaW1wb3J0L25vLWludGVybmFsLW1vZHVsZXMgKi9cbmltcG9ydCB7QmFja2VuZCwgSW5mZXJlbmNlU2Vzc2lvbiwgU2Vzc2lvbkhhbmRsZXJ9IGZyb20gJ29ubnhydW50aW1lLWNvbW1vbic7XG5cbmltcG9ydCB7U2Vzc2lvbn0gZnJvbSAnLi9vbm54anMvc2Vzc2lvbic7XG5pbXBvcnQge09ubnhqc1Nlc3Npb25IYW5kbGVyfSBmcm9tICcuL29ubnhqcy9zZXNzaW9uLWhhbmRsZXInO1xuXG5jbGFzcyBPbm54anNCYWNrZW5kIGltcGxlbWVudHMgQmFja2VuZCB7XG4gIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tZW1wdHktZnVuY3Rpb25cbiAgYXN5bmMgaW5pdCgpOiBQcm9taXNlPHZvaWQ+IHt9XG5cbiAgYXN5bmMgY3JlYXRlU2Vzc2lvbkhhbmRsZXIocGF0aE9yQnVmZmVyOiBzdHJpbmd8VWludDhBcnJheSwgb3B0aW9ucz86IEluZmVyZW5jZVNlc3Npb24uU2Vzc2lvbk9wdGlvbnMpOlxuICAgICAgUHJvbWlzZTxTZXNzaW9uSGFuZGxlcj4ge1xuICAgIC8vIE5PVEU6IFNlc3Npb24uQ29uZmlnKGZyb20gb25ueC5qcykgaXMgbm90IGNvbXBhdGlibGUgd2l0aCBJbmZlcmVuY2VTZXNzaW9uLlNlc3Npb25PcHRpb25zKGZyb21cbiAgICAvLyBvbm54cnVudGltZS1jb21tb24pLlxuICAgIC8vICAgICAgIEluIGZ1dHVyZSB3ZSBzaG91bGQgcmVtb3ZlIFNlc3Npb24uQ29uZmlnIGFuZCB1c2UgSW5mZXJlbmNlU2Vzc2lvbi5TZXNzaW9uT3B0aW9ucy5cbiAgICAvLyAgICAgICBDdXJyZW50bHkgd2UgYWxsb3cgdGhpcyB0byBoYXBwZW4gdG8gbWFrZSB0ZXN0IHJ1bm5lciB3b3JrLlxuICAgIGNvbnN0IHNlc3Npb24gPSBuZXcgU2Vzc2lvbihvcHRpb25zIGFzIHVua25vd24gYXMgU2Vzc2lvbi5Db25maWcpO1xuXG4gICAgLy8gdHlwZXNjcmlwdCBjYW5ub3QgbWVyZ2UgbWV0aG9kIG92ZXJyaWRlIGNvcnJlY3RseSAoc28gZmFyIGluIDQuMi4zKS4gbmVlZCBpZi1lbHNlIHRvIGNhbGwgdGhlIG1ldGhvZC5cbiAgICBpZiAodHlwZW9mIHBhdGhPckJ1ZmZlciA9PT0gJ3N0cmluZycpIHtcbiAgICAgIGF3YWl0IHNlc3Npb24ubG9hZE1vZGVsKHBhdGhPckJ1ZmZlcik7XG4gICAgfSBlbHNlIHtcbiAgICAgIGF3YWl0IHNlc3Npb24ubG9hZE1vZGVsKHBhdGhPckJ1ZmZlcik7XG4gICAgfVxuXG4gICAgcmV0dXJuIG5ldyBPbm54anNTZXNzaW9uSGFuZGxlcihzZXNzaW9uKTtcbiAgfVxufVxuXG5leHBvcnQgY29uc3Qgb25ueGpzQmFja2VuZCA9IG5ldyBPbm54anNCYWNrZW5kKCk7XG4iLCIvLyBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cblxuaW1wb3J0IHtCYWNrZW5kLCBlbnYsIEluZmVyZW5jZVNlc3Npb24sIFNlc3Npb25IYW5kbGVyfSBmcm9tICdvbm54cnVudGltZS1jb21tb24nO1xuaW1wb3J0IHtjcHVzfSBmcm9tICdvcyc7XG5cbmltcG9ydCB7aW5pdFdhc219IGZyb20gJy4vd2FzbS9wcm94eS13cmFwcGVyJztcbmltcG9ydCB7T25ueHJ1bnRpbWVXZWJBc3NlbWJseVNlc3Npb25IYW5kbGVyfSBmcm9tICcuL3dhc20vc2Vzc2lvbi1oYW5kbGVyJztcblxuLyoqXG4gKiBUaGlzIGZ1bmN0aW9uIGluaXRpYWxpemVzIGFsbCBmbGFncyBmb3IgV2ViQXNzZW1ibHkuXG4gKlxuICogVGhvc2UgZmxhZ3MgYXJlIGFjY2Vzc2libGUgZnJvbSBgb3J0LmVudi53YXNtYC4gVXNlcnMgYXJlIGFsbG93IHRvIHNldCB0aG9zZSBmbGFncyBiZWZvcmUgdGhlIGZpcnN0IGluZmVyZW5jZSBzZXNzaW9uXG4gKiBiZWluZyBjcmVhdGVkLCB0byBvdmVycmlkZSBkZWZhdWx0IHZhbHVlLlxuICovXG5leHBvcnQgY29uc3QgaW5pdGlhbGl6ZUZsYWdzID0gKCk6IHZvaWQgPT4ge1xuICBpZiAodHlwZW9mIGVudi53YXNtLmluaXRUaW1lb3V0ICE9PSAnbnVtYmVyJyB8fCBlbnYud2FzbS5pbml0VGltZW91dCA8IDApIHtcbiAgICBlbnYud2FzbS5pbml0VGltZW91dCA9IDA7XG4gIH1cblxuICBpZiAodHlwZW9mIGVudi53YXNtLnNpbWQgIT09ICdib29sZWFuJykge1xuICAgIGVudi53YXNtLnNpbWQgPSB0cnVlO1xuICB9XG5cbiAgaWYgKHR5cGVvZiBlbnYud2FzbS5wcm94eSAhPT0gJ2Jvb2xlYW4nKSB7XG4gICAgZW52Lndhc20ucHJveHkgPSBmYWxzZTtcbiAgfVxuXG4gIGlmICh0eXBlb2YgZW52Lndhc20ubnVtVGhyZWFkcyAhPT0gJ251bWJlcicgfHwgIU51bWJlci5pc0ludGVnZXIoZW52Lndhc20ubnVtVGhyZWFkcykgfHwgZW52Lndhc20ubnVtVGhyZWFkcyA8PSAwKSB7XG4gICAgY29uc3QgbnVtQ3B1TG9naWNhbENvcmVzID0gdHlwZW9mIG5hdmlnYXRvciA9PT0gJ3VuZGVmaW5lZCcgPyBjcHVzKCkubGVuZ3RoIDogbmF2aWdhdG9yLmhhcmR3YXJlQ29uY3VycmVuY3k7XG4gICAgZW52Lndhc20ubnVtVGhyZWFkcyA9IE1hdGgubWluKDQsIE1hdGguY2VpbCgobnVtQ3B1TG9naWNhbENvcmVzIHx8IDEpIC8gMikpO1xuICB9XG59O1xuXG5jbGFzcyBPbm54cnVudGltZVdlYkFzc2VtYmx5QmFja2VuZCBpbXBsZW1lbnRzIEJhY2tlbmQge1xuICBhc3luYyBpbml0KCk6IFByb21pc2U8dm9pZD4ge1xuICAgIC8vIHBvcHVsYXRlIHdhc20gZmxhZ3NcbiAgICBpbml0aWFsaXplRmxhZ3MoKTtcblxuICAgIC8vIGluaXQgd2FzbVxuICAgIGF3YWl0IGluaXRXYXNtKCk7XG4gIH1cbiAgY3JlYXRlU2Vzc2lvbkhhbmRsZXIocGF0aDogc3RyaW5nLCBvcHRpb25zPzogSW5mZXJlbmNlU2Vzc2lvbi5TZXNzaW9uT3B0aW9ucyk6IFByb21pc2U8U2Vzc2lvbkhhbmRsZXI+O1xuICBjcmVhdGVTZXNzaW9uSGFuZGxlcihidWZmZXI6IFVpbnQ4QXJyYXksIG9wdGlvbnM/OiBJbmZlcmVuY2VTZXNzaW9uLlNlc3Npb25PcHRpb25zKTogUHJvbWlzZTxTZXNzaW9uSGFuZGxlcj47XG4gIGFzeW5jIGNyZWF0ZVNlc3Npb25IYW5kbGVyKHBhdGhPckJ1ZmZlcjogc3RyaW5nfFVpbnQ4QXJyYXksIG9wdGlvbnM/OiBJbmZlcmVuY2VTZXNzaW9uLlNlc3Npb25PcHRpb25zKTpcbiAgICAgIFByb21pc2U8U2Vzc2lvbkhhbmRsZXI+IHtcbiAgICBjb25zdCBoYW5kbGVyID0gbmV3IE9ubnhydW50aW1lV2ViQXNzZW1ibHlTZXNzaW9uSGFuZGxlcigpO1xuICAgIGF3YWl0IGhhbmRsZXIubG9hZE1vZGVsKHBhdGhPckJ1ZmZlciwgb3B0aW9ucyk7XG4gICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZShoYW5kbGVyKTtcbiAgfVxufVxuXG5leHBvcnQgY29uc3Qgd2FzbUJhY2tlbmQgPSBuZXcgT25ueHJ1bnRpbWVXZWJBc3NlbWJseUJhY2tlbmQoKTtcbiIsIi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxuXG4vKiBlc2xpbnQtZGlzYWJsZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tdmFyLXJlcXVpcmVzLCBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tcmVxdWlyZS1pbXBvcnRzICovXG4vLyBXZSB1c2UgXCJyZXF1aXJlXCIgaW5zdGVhZCBvZiBcImltcG9ydFwiIGhlcmUgYmVjYXVzZSBpbXBvcnQgc3RhdGVtZW50IG11c3QgYmUgcHV0IGluIHRvcCBsZXZlbC4gT3VyIGN1cnJlbnQgY29kZSBkb2VzXG4vLyBub3QgYWxsb3cgdGVyc2VyIHRvIHRyZWUtc2hha2luZyBjb2RlIGFzIGV4cGVjdGVkIGJlY2F1c2Ugc29tZSBjb2RlcyBhcmUgdHJlYXRlZCBhcyBoYXZpbmcgc2lkZSBlZmZlY3RzLlxuLy8gU28gd2UgaW1wb3J0IGNvZGUgaW5zaWRlIHRoZSBpZi1jbGF1c2UgdG8gYWxsb3cgdGVyc2VyIHJlbW92ZSB0aGUgY29kZSBzYWZlbHkuXG5cbmV4cG9ydCAqIGZyb20gJ29ubnhydW50aW1lLWNvbW1vbic7XG5pbXBvcnQge3JlZ2lzdGVyQmFja2VuZH0gZnJvbSAnb25ueHJ1bnRpbWUtY29tbW9uJztcblxuaWYgKCFCVUlMRF9ERUZTLkRJU0FCTEVfV0VCR0wpIHtcbiAgY29uc3Qgb25ueGpzQmFja2VuZCA9IHJlcXVpcmUoJy4vYmFja2VuZC1vbm54anMnKS5vbm54anNCYWNrZW5kO1xuICByZWdpc3RlckJhY2tlbmQoJ3dlYmdsJywgb25ueGpzQmFja2VuZCwgLTEwKTtcbn1cbmlmICghQlVJTERfREVGUy5ESVNBQkxFX1dBU00pIHtcbiAgY29uc3Qgd2FzbUJhY2tlbmQgPSByZXF1aXJlKCcuL2JhY2tlbmQtd2FzbScpLndhc21CYWNrZW5kO1xuICByZWdpc3RlckJhY2tlbmQoJ2NwdScsIHdhc21CYWNrZW5kLCAxMCk7XG4gIHJlZ2lzdGVyQmFja2VuZCgnd2FzbScsIHdhc21CYWNrZW5kLCAxMCk7XG4gIHJlZ2lzdGVyQmFja2VuZCgneG5ucGFjaycsIHdhc21CYWNrZW5kLCA5KTtcbn1cbiIsIi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxuXG5jbGFzcyBBdHRyaWJ1dGVXaXRoQ2FjaGVLZXlJbXBsIHtcbiAgY29uc3RydWN0b3IoYXR0cmlidXRlOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPikge1xuICAgIE9iamVjdC5hc3NpZ24odGhpcywgYXR0cmlidXRlKTtcbiAgfVxuXG4gIHByaXZhdGUgX2NhY2hlS2V5OiBzdHJpbmc7XG4gIHB1YmxpYyBnZXQgY2FjaGVLZXkoKTogc3RyaW5nIHtcbiAgICBpZiAoIXRoaXMuX2NhY2hlS2V5KSB7XG4gICAgICB0aGlzLl9jYWNoZUtleSA9XG4gICAgICAgICAgT2JqZWN0LmdldE93blByb3BlcnR5TmFtZXModGhpcykuc29ydCgpLm1hcChuYW1lID0+IGAkeyh0aGlzIGFzIFJlY29yZDxzdHJpbmcsIHVua25vd24+KVtuYW1lXX1gKS5qb2luKCc7Jyk7XG4gICAgfVxuICAgIHJldHVybiB0aGlzLl9jYWNoZUtleTtcbiAgfVxufVxuXG5leHBvcnQgaW50ZXJmYWNlIEF0dHJpYnV0ZVdpdGhDYWNoZUtleSB7XG4gIHJlYWRvbmx5IGNhY2hlS2V5OiBzdHJpbmc7XG59XG5cbmV4cG9ydCBjb25zdCBjcmVhdGVBdHRyaWJ1dGVXaXRoQ2FjaGVLZXkgPSA8VCBleHRlbmRzIFJlY29yZDxzdHJpbmcsIHVua25vd24+PihhdHRyaWJ1dGU6IFQpOiBUJkF0dHJpYnV0ZVdpdGhDYWNoZUtleSA9PlxuICAgIG5ldyBBdHRyaWJ1dGVXaXRoQ2FjaGVLZXlJbXBsKGF0dHJpYnV0ZSkgYXMgdW5rbm93biBhcyBUICYgQXR0cmlidXRlV2l0aENhY2hlS2V5O1xuIiwiLy8gQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXG5cbmltcG9ydCBMb25nIGZyb20gJ2xvbmcnO1xuaW1wb3J0IHtvbm54fSBmcm9tICdvbm54LXByb3RvJztcblxuaW1wb3J0IHtvbm54cnVudGltZX0gZnJvbSAnLi9vcnQtc2NoZW1hL29ydC1nZW5lcmF0ZWQnO1xuaW1wb3J0IHtUZW5zb3J9IGZyb20gJy4vdGVuc29yJztcbmltcG9ydCB7ZGVjb2RlVXRmOFN0cmluZywgTG9uZ1V0aWx9IGZyb20gJy4vdXRpbCc7XG5cbmltcG9ydCBvcnRGYnMgPSBvbm54cnVudGltZS5leHBlcmltZW50YWwuZmJzO1xuXG5leHBvcnQgZGVjbGFyZSBuYW1lc3BhY2UgQXR0cmlidXRlIHtcbiAgZXhwb3J0IGludGVyZmFjZSBEYXRhVHlwZU1hcCB7XG4gICAgZmxvYXQ6IG51bWJlcjtcbiAgICBpbnQ6IG51bWJlcjtcbiAgICBzdHJpbmc6IHN0cmluZztcbiAgICB0ZW5zb3I6IFRlbnNvcjtcbiAgICBmbG9hdHM6IG51bWJlcltdO1xuICAgIGludHM6IG51bWJlcltdO1xuICAgIHN0cmluZ3M6IHN0cmluZ1tdO1xuICAgIHRlbnNvcnM6IFRlbnNvcltdO1xuICB9XG5cbiAgZXhwb3J0IHR5cGUgRGF0YVR5cGUgPSBrZXlvZiBEYXRhVHlwZU1hcDtcbn1cblxudHlwZSBWYWx1ZVR5cGVzID0gQXR0cmlidXRlLkRhdGFUeXBlTWFwW0F0dHJpYnV0ZS5EYXRhVHlwZV07XG5cbnR5cGUgVmFsdWUgPSBbVmFsdWVUeXBlcywgQXR0cmlidXRlLkRhdGFUeXBlXTtcblxuZXhwb3J0IGNsYXNzIEF0dHJpYnV0ZSB7XG4gIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXM6IG9ubnguSUF0dHJpYnV0ZVByb3RvW118b3J0RmJzLkF0dHJpYnV0ZVtdfG51bGx8dW5kZWZpbmVkKSB7XG4gICAgdGhpcy5fYXR0cmlidXRlcyA9IG5ldyBNYXAoKTtcbiAgICBpZiAoYXR0cmlidXRlcyAhPT0gbnVsbCAmJiBhdHRyaWJ1dGVzICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIGZvciAoY29uc3QgYXR0ciBvZiBhdHRyaWJ1dGVzKSB7XG4gICAgICAgIGlmIChhdHRyIGluc3RhbmNlb2Ygb25ueC5BdHRyaWJ1dGVQcm90bykge1xuICAgICAgICAgIHRoaXMuX2F0dHJpYnV0ZXMuc2V0KGF0dHIubmFtZSwgW0F0dHJpYnV0ZS5nZXRWYWx1ZShhdHRyKSwgQXR0cmlidXRlLmdldFR5cGUoYXR0cildKTtcbiAgICAgICAgfSBlbHNlIGlmIChhdHRyIGluc3RhbmNlb2Ygb3J0RmJzLkF0dHJpYnV0ZSkge1xuICAgICAgICAgIHRoaXMuX2F0dHJpYnV0ZXMuc2V0KGF0dHIubmFtZSgpISwgW0F0dHJpYnV0ZS5nZXRWYWx1ZShhdHRyKSwgQXR0cmlidXRlLmdldFR5cGUoYXR0cildKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgaWYgKHRoaXMuX2F0dHJpYnV0ZXMuc2l6ZSA8IGF0dHJpYnV0ZXMubGVuZ3RoKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignZHVwbGljYXRlZCBhdHRyaWJ1dGUgbmFtZXMnKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBzZXQoa2V5OiBzdHJpbmcsIHR5cGU6IEF0dHJpYnV0ZS5EYXRhVHlwZSwgdmFsdWU6IFZhbHVlVHlwZXMpOiB2b2lkIHtcbiAgICB0aGlzLl9hdHRyaWJ1dGVzLnNldChrZXksIFt2YWx1ZSwgdHlwZV0pO1xuICB9XG4gIGRlbGV0ZShrZXk6IHN0cmluZyk6IHZvaWQge1xuICAgIHRoaXMuX2F0dHJpYnV0ZXMuZGVsZXRlKGtleSk7XG4gIH1cbiAgZ2V0RmxvYXQoa2V5OiBzdHJpbmcsIGRlZmF1bHRWYWx1ZT86IEF0dHJpYnV0ZS5EYXRhVHlwZU1hcFsnZmxvYXQnXSkge1xuICAgIHJldHVybiB0aGlzLmdldChrZXksICdmbG9hdCcsIGRlZmF1bHRWYWx1ZSk7XG4gIH1cblxuICBnZXRJbnQoa2V5OiBzdHJpbmcsIGRlZmF1bHRWYWx1ZT86IEF0dHJpYnV0ZS5EYXRhVHlwZU1hcFsnaW50J10pIHtcbiAgICByZXR1cm4gdGhpcy5nZXQoa2V5LCAnaW50JywgZGVmYXVsdFZhbHVlKTtcbiAgfVxuXG4gIGdldFN0cmluZyhrZXk6IHN0cmluZywgZGVmYXVsdFZhbHVlPzogQXR0cmlidXRlLkRhdGFUeXBlTWFwWydzdHJpbmcnXSkge1xuICAgIHJldHVybiB0aGlzLmdldChrZXksICdzdHJpbmcnLCBkZWZhdWx0VmFsdWUpO1xuICB9XG5cbiAgZ2V0VGVuc29yKGtleTogc3RyaW5nLCBkZWZhdWx0VmFsdWU/OiBBdHRyaWJ1dGUuRGF0YVR5cGVNYXBbJ3RlbnNvciddKSB7XG4gICAgcmV0dXJuIHRoaXMuZ2V0KGtleSwgJ3RlbnNvcicsIGRlZmF1bHRWYWx1ZSk7XG4gIH1cblxuICBnZXRGbG9hdHMoa2V5OiBzdHJpbmcsIGRlZmF1bHRWYWx1ZT86IEF0dHJpYnV0ZS5EYXRhVHlwZU1hcFsnZmxvYXRzJ10pIHtcbiAgICByZXR1cm4gdGhpcy5nZXQoa2V5LCAnZmxvYXRzJywgZGVmYXVsdFZhbHVlKTtcbiAgfVxuXG4gIGdldEludHMoa2V5OiBzdHJpbmcsIGRlZmF1bHRWYWx1ZT86IEF0dHJpYnV0ZS5EYXRhVHlwZU1hcFsnaW50cyddKSB7XG4gICAgcmV0dXJuIHRoaXMuZ2V0KGtleSwgJ2ludHMnLCBkZWZhdWx0VmFsdWUpO1xuICB9XG5cbiAgZ2V0U3RyaW5ncyhrZXk6IHN0cmluZywgZGVmYXVsdFZhbHVlPzogQXR0cmlidXRlLkRhdGFUeXBlTWFwWydzdHJpbmdzJ10pIHtcbiAgICByZXR1cm4gdGhpcy5nZXQoa2V5LCAnc3RyaW5ncycsIGRlZmF1bHRWYWx1ZSk7XG4gIH1cblxuICBnZXRUZW5zb3JzKGtleTogc3RyaW5nLCBkZWZhdWx0VmFsdWU/OiBBdHRyaWJ1dGUuRGF0YVR5cGVNYXBbJ3RlbnNvcnMnXSkge1xuICAgIHJldHVybiB0aGlzLmdldChrZXksICd0ZW5zb3JzJywgZGVmYXVsdFZhbHVlKTtcbiAgfVxuXG4gIHByaXZhdGUgZ2V0PFYgZXh0ZW5kcyBBdHRyaWJ1dGUuRGF0YVR5cGVNYXBbQXR0cmlidXRlLkRhdGFUeXBlXT4oXG4gICAgICBrZXk6IHN0cmluZywgdHlwZTogQXR0cmlidXRlLkRhdGFUeXBlLCBkZWZhdWx0VmFsdWU/OiBWKTogViB7XG4gICAgY29uc3QgdmFsdWVBbmRUeXBlID0gdGhpcy5fYXR0cmlidXRlcy5nZXQoa2V5KTtcbiAgICBpZiAodmFsdWVBbmRUeXBlID09PSB1bmRlZmluZWQpIHtcbiAgICAgIGlmIChkZWZhdWx0VmFsdWUgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICByZXR1cm4gZGVmYXVsdFZhbHVlO1xuICAgICAgfVxuICAgICAgdGhyb3cgbmV3IEVycm9yKGByZXF1aXJlZCBhdHRyaWJ1dGUgbm90IGZvdW5kOiAke2tleX1gKTtcbiAgICB9XG4gICAgaWYgKHZhbHVlQW5kVHlwZVsxXSAhPT0gdHlwZSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGB0eXBlIG1pc21hdGNoOiBleHBlY3RlZCAke3R5cGV9IGJ1dCBnb3QgJHt2YWx1ZUFuZFR5cGVbMV19YCk7XG4gICAgfVxuICAgIHJldHVybiB2YWx1ZUFuZFR5cGVbMF0gYXMgVjtcbiAgfVxuXG4gIHByaXZhdGUgc3RhdGljIGdldFR5cGUoYXR0cjogb25ueC5JQXR0cmlidXRlUHJvdG98b3J0RmJzLkF0dHJpYnV0ZSk6IEF0dHJpYnV0ZS5EYXRhVHlwZSB7XG4gICAgY29uc3QgdHlwZSA9IGF0dHIgaW5zdGFuY2VvZiBvbm54LkF0dHJpYnV0ZVByb3RvID8gKGF0dHIpLnR5cGUgOiAoYXR0ciBhcyBvcnRGYnMuQXR0cmlidXRlKS50eXBlKCk7XG4gICAgc3dpdGNoICh0eXBlKSB7XG4gICAgICBjYXNlIG9ubnguQXR0cmlidXRlUHJvdG8uQXR0cmlidXRlVHlwZS5GTE9BVDpcbiAgICAgICAgcmV0dXJuICdmbG9hdCc7XG4gICAgICBjYXNlIG9ubnguQXR0cmlidXRlUHJvdG8uQXR0cmlidXRlVHlwZS5JTlQ6XG4gICAgICAgIHJldHVybiAnaW50JztcbiAgICAgIGNhc2Ugb25ueC5BdHRyaWJ1dGVQcm90by5BdHRyaWJ1dGVUeXBlLlNUUklORzpcbiAgICAgICAgcmV0dXJuICdzdHJpbmcnO1xuICAgICAgY2FzZSBvbm54LkF0dHJpYnV0ZVByb3RvLkF0dHJpYnV0ZVR5cGUuVEVOU09SOlxuICAgICAgICByZXR1cm4gJ3RlbnNvcic7XG4gICAgICBjYXNlIG9ubnguQXR0cmlidXRlUHJvdG8uQXR0cmlidXRlVHlwZS5GTE9BVFM6XG4gICAgICAgIHJldHVybiAnZmxvYXRzJztcbiAgICAgIGNhc2Ugb25ueC5BdHRyaWJ1dGVQcm90by5BdHRyaWJ1dGVUeXBlLklOVFM6XG4gICAgICAgIHJldHVybiAnaW50cyc7XG4gICAgICBjYXNlIG9ubnguQXR0cmlidXRlUHJvdG8uQXR0cmlidXRlVHlwZS5TVFJJTkdTOlxuICAgICAgICByZXR1cm4gJ3N0cmluZ3MnO1xuICAgICAgY2FzZSBvbm54LkF0dHJpYnV0ZVByb3RvLkF0dHJpYnV0ZVR5cGUuVEVOU09SUzpcbiAgICAgICAgcmV0dXJuICd0ZW5zb3JzJztcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgYXR0cmlidXRlIHR5cGUgaXMgbm90IHN1cHBvcnRlZCB5ZXQ6ICR7b25ueC5BdHRyaWJ1dGVQcm90by5BdHRyaWJ1dGVUeXBlW3R5cGVdfWApO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgc3RhdGljIGdldFZhbHVlKGF0dHI6IG9ubnguSUF0dHJpYnV0ZVByb3RvfG9ydEZicy5BdHRyaWJ1dGUpIHtcbiAgICBjb25zdCBhdHRyVHlwZSA9IGF0dHIgaW5zdGFuY2VvZiBvbm54LkF0dHJpYnV0ZVByb3RvID8gYXR0ci50eXBlIDogKGF0dHIgYXMgb3J0RmJzLkF0dHJpYnV0ZSkudHlwZSgpO1xuICAgIGlmIChhdHRyVHlwZSA9PT0gb25ueC5BdHRyaWJ1dGVQcm90by5BdHRyaWJ1dGVUeXBlLkdSQVBIIHx8IGF0dHJUeXBlID09PSBvbm54LkF0dHJpYnV0ZVByb3RvLkF0dHJpYnV0ZVR5cGUuR1JBUEhTKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ2dyYXBoIGF0dHJpYnV0ZSBpcyBub3Qgc3VwcG9ydGVkIHlldCcpO1xuICAgIH1cblxuICAgIGNvbnN0IHZhbHVlID0gdGhpcy5nZXRWYWx1ZU5vQ2hlY2soYXR0cik7XG5cbiAgICAvLyBjYXN0IExPTkcgdG8gbnVtYmVyXG4gICAgaWYgKGF0dHJUeXBlID09PSBvbm54LkF0dHJpYnV0ZVByb3RvLkF0dHJpYnV0ZVR5cGUuSU5UICYmIExvbmdVdGlsLmlzTG9uZyh2YWx1ZSkpIHtcbiAgICAgIHJldHVybiBMb25nVXRpbC5sb25nVG9OdW1iZXIodmFsdWUgYXMgTG9uZyB8IGZsYXRidWZmZXJzLkxvbmcpO1xuICAgIH1cblxuICAgIC8vIGNhc3QgTE9OR1tdIHRvIG51bWJlcltdXG4gICAgaWYgKGF0dHJUeXBlID09PSBvbm54LkF0dHJpYnV0ZVByb3RvLkF0dHJpYnV0ZVR5cGUuSU5UUykge1xuICAgICAgY29uc3QgYXJyID0gKHZhbHVlIGFzIEFycmF5PG51bWJlcnxMb25nfGZsYXRidWZmZXJzLkxvbmc+KTtcbiAgICAgIGNvbnN0IG51bWJlclZhbHVlOiBudW1iZXJbXSA9IG5ldyBBcnJheTxudW1iZXI+KGFyci5sZW5ndGgpO1xuXG4gICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGFyci5sZW5ndGg7IGkrKykge1xuICAgICAgICBjb25zdCBtYXliZUxvbmcgPSBhcnJbaV07XG4gICAgICAgIG51bWJlclZhbHVlW2ldID0gTG9uZ1V0aWwubG9uZ1RvTnVtYmVyKG1heWJlTG9uZyk7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBudW1iZXJWYWx1ZTtcbiAgICB9XG5cbiAgICAvLyBjYXN0IG9ubnguVGVuc29yUHJvdG8gdG8gb25ueGpzLlRlbnNvclxuICAgIGlmIChhdHRyVHlwZSA9PT0gb25ueC5BdHRyaWJ1dGVQcm90by5BdHRyaWJ1dGVUeXBlLlRFTlNPUikge1xuICAgICAgcmV0dXJuIGF0dHIgaW5zdGFuY2VvZiBvbm54LkF0dHJpYnV0ZVByb3RvID8gVGVuc29yLmZyb21Qcm90byh2YWx1ZSBhcyBvbm54LklUZW5zb3JQcm90bykgOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVGVuc29yLmZyb21PcnRUZW5zb3IodmFsdWUgYXMgb3J0RmJzLlRlbnNvcik7XG4gICAgfVxuXG4gICAgLy8gY2FzdCBvbm54LlRlbnNvclByb3RvW10gdG8gb25ueGpzLlRlbnNvcltdXG4gICAgaWYgKGF0dHJUeXBlID09PSBvbm54LkF0dHJpYnV0ZVByb3RvLkF0dHJpYnV0ZVR5cGUuVEVOU09SUykge1xuICAgICAgaWYgKGF0dHIgaW5zdGFuY2VvZiBvbm54LkF0dHJpYnV0ZVByb3RvKSB7XG4gICAgICAgIGNvbnN0IHRlbnNvclByb3RvcyA9IHZhbHVlIGFzIG9ubnguSVRlbnNvclByb3RvW107XG4gICAgICAgIHJldHVybiB0ZW5zb3JQcm90b3MubWFwKHZhbHVlID0+IFRlbnNvci5mcm9tUHJvdG8odmFsdWUpKTtcbiAgICAgIH0gZWxzZSBpZiAoYXR0ciBpbnN0YW5jZW9mIG9ydEZicy5BdHRyaWJ1dGUpIHtcbiAgICAgICAgY29uc3QgdGVuc29yUHJvdG9zID0gdmFsdWUgYXMgb3J0RmJzLlRlbnNvcltdO1xuICAgICAgICByZXR1cm4gdGVuc29yUHJvdG9zLm1hcCh2YWx1ZSA9PiBUZW5zb3IuZnJvbU9ydFRlbnNvcih2YWx1ZSkpO1xuICAgICAgfVxuICAgIH1cblxuICAgIC8vIGNhc3QgVWludDhBcnJheSB0byBzdHJpbmdcbiAgICBpZiAoYXR0clR5cGUgPT09IG9ubnguQXR0cmlidXRlUHJvdG8uQXR0cmlidXRlVHlwZS5TVFJJTkcpIHtcbiAgICAgIC8vIHN0cmluZyBpbiBvbm54IGF0dHJpYnV0ZSBpcyBvZiB1aW50OGFycmF5IHR5cGUsIHNvIHdlIG5lZWQgdG8gY29udmVydCBpdCB0byBzdHJpbmcgYmVsb3cuIFdoaWxlIGluIG9ydCBmb3JtYXQsXG4gICAgICAvLyBzdHJpbmcgYXR0cmlidXRlcyBhcmUgcmV0dXJuZWQgYXMgc3RyaW5nLCBzbyBubyBjb252ZXJzaW9uIGlzIG5lZWRlZC5cbiAgICAgIGlmIChhdHRyIGluc3RhbmNlb2Ygb25ueC5BdHRyaWJ1dGVQcm90bykge1xuICAgICAgICBjb25zdCB1dGY4U3RyaW5nID0gdmFsdWUgYXMgVWludDhBcnJheTtcbiAgICAgICAgcmV0dXJuIGRlY29kZVV0ZjhTdHJpbmcodXRmOFN0cmluZyk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gY2FzdCBVaW50OEFycmF5W10gdG8gc3RyaW5nW11cbiAgICBpZiAoYXR0clR5cGUgPT09IG9ubnguQXR0cmlidXRlUHJvdG8uQXR0cmlidXRlVHlwZS5TVFJJTkdTKSB7XG4gICAgICAvLyBzdHJpbmdzIGluIG9ubnggYXR0cmlidXRlIGlzIHJldHVybmVkIGFzIHVpbnQ4YXJyYXlbXSwgc28gd2UgbmVlZCB0byBjb252ZXJ0IGl0IHRvIHN0cmluZ1tdIGJlbG93LiBXaGlsZSBpbiBvcnRcbiAgICAgIC8vIGZvcm1hdCBzdHJpbmdzIGF0dHJpYnV0ZXMgYXJlIHJldHVybmVkIGFzIHN0cmluZ1tdLCBzbyBubyBjb252ZXJzaW9uIGlzIG5lZWRlZC5cbiAgICAgIGlmIChhdHRyIGluc3RhbmNlb2Ygb25ueC5BdHRyaWJ1dGVQcm90bykge1xuICAgICAgICBjb25zdCB1dGY4U3RyaW5ncyA9IHZhbHVlIGFzIFVpbnQ4QXJyYXlbXTtcbiAgICAgICAgcmV0dXJuIHV0ZjhTdHJpbmdzLm1hcChkZWNvZGVVdGY4U3RyaW5nKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gdmFsdWUgYXMgVmFsdWVUeXBlcztcbiAgfVxuXG4gIHByaXZhdGUgc3RhdGljIGdldFZhbHVlTm9DaGVjayhhdHRyOiBvbm54LklBdHRyaWJ1dGVQcm90b3xvcnRGYnMuQXR0cmlidXRlKSB7XG4gICAgcmV0dXJuIGF0dHIgaW5zdGFuY2VvZiAob25ueC5BdHRyaWJ1dGVQcm90bykgPyB0aGlzLmdldFZhbHVlTm9DaGVja0Zyb21Pbm54Rm9ybWF0KGF0dHIpIDpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZ2V0VmFsdWVOb0NoZWNrRnJvbU9ydEZvcm1hdChhdHRyIGFzIG9ydEZicy5BdHRyaWJ1dGUpO1xuICB9XG5cbiAgcHJpdmF0ZSBzdGF0aWMgZ2V0VmFsdWVOb0NoZWNrRnJvbU9ubnhGb3JtYXQoYXR0cjogb25ueC5JQXR0cmlidXRlUHJvdG8pIHtcbiAgICBzd2l0Y2ggKGF0dHIudHlwZSEpIHtcbiAgICAgIGNhc2Ugb25ueC5BdHRyaWJ1dGVQcm90by5BdHRyaWJ1dGVUeXBlLkZMT0FUOlxuICAgICAgICByZXR1cm4gYXR0ci5mO1xuICAgICAgY2FzZSBvbm54LkF0dHJpYnV0ZVByb3RvLkF0dHJpYnV0ZVR5cGUuSU5UOlxuICAgICAgICByZXR1cm4gYXR0ci5pO1xuICAgICAgY2FzZSBvbm54LkF0dHJpYnV0ZVByb3RvLkF0dHJpYnV0ZVR5cGUuU1RSSU5HOlxuICAgICAgICByZXR1cm4gYXR0ci5zO1xuICAgICAgY2FzZSBvbm54LkF0dHJpYnV0ZVByb3RvLkF0dHJpYnV0ZVR5cGUuVEVOU09SOlxuICAgICAgICByZXR1cm4gYXR0ci50O1xuICAgICAgY2FzZSBvbm54LkF0dHJpYnV0ZVByb3RvLkF0dHJpYnV0ZVR5cGUuR1JBUEg6XG4gICAgICAgIHJldHVybiBhdHRyLmc7XG4gICAgICBjYXNlIG9ubnguQXR0cmlidXRlUHJvdG8uQXR0cmlidXRlVHlwZS5GTE9BVFM6XG4gICAgICAgIHJldHVybiBhdHRyLmZsb2F0cztcbiAgICAgIGNhc2Ugb25ueC5BdHRyaWJ1dGVQcm90by5BdHRyaWJ1dGVUeXBlLklOVFM6XG4gICAgICAgIHJldHVybiBhdHRyLmludHM7XG4gICAgICBjYXNlIG9ubnguQXR0cmlidXRlUHJvdG8uQXR0cmlidXRlVHlwZS5TVFJJTkdTOlxuICAgICAgICByZXR1cm4gYXR0ci5zdHJpbmdzO1xuICAgICAgY2FzZSBvbm54LkF0dHJpYnV0ZVByb3RvLkF0dHJpYnV0ZVR5cGUuVEVOU09SUzpcbiAgICAgICAgcmV0dXJuIGF0dHIudGVuc29ycztcbiAgICAgIGNhc2Ugb25ueC5BdHRyaWJ1dGVQcm90by5BdHRyaWJ1dGVUeXBlLkdSQVBIUzpcbiAgICAgICAgcmV0dXJuIGF0dHIuZ3JhcGhzO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGB1bnN1cHBvcnRlZCBhdHRyaWJ1dGUgdHlwZTogJHtvbm54LkF0dHJpYnV0ZVByb3RvLkF0dHJpYnV0ZVR5cGVbYXR0ci50eXBlIV19YCk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBzdGF0aWMgZ2V0VmFsdWVOb0NoZWNrRnJvbU9ydEZvcm1hdChhdHRyOiBvcnRGYnMuQXR0cmlidXRlKSB7XG4gICAgc3dpdGNoIChhdHRyLnR5cGUoKSkge1xuICAgICAgY2FzZSBvcnRGYnMuQXR0cmlidXRlVHlwZS5GTE9BVDpcbiAgICAgICAgcmV0dXJuIGF0dHIuZigpO1xuICAgICAgY2FzZSBvcnRGYnMuQXR0cmlidXRlVHlwZS5JTlQ6XG4gICAgICAgIHJldHVybiBhdHRyLmkoKTtcbiAgICAgIGNhc2Ugb3J0RmJzLkF0dHJpYnV0ZVR5cGUuU1RSSU5HOlxuICAgICAgICByZXR1cm4gYXR0ci5zKCk7XG4gICAgICBjYXNlIG9ydEZicy5BdHRyaWJ1dGVUeXBlLlRFTlNPUjpcbiAgICAgICAgcmV0dXJuIGF0dHIudCgpO1xuICAgICAgY2FzZSBvcnRGYnMuQXR0cmlidXRlVHlwZS5HUkFQSDpcbiAgICAgICAgcmV0dXJuIGF0dHIuZygpO1xuICAgICAgY2FzZSBvcnRGYnMuQXR0cmlidXRlVHlwZS5GTE9BVFM6XG4gICAgICAgIHJldHVybiBhdHRyLmZsb2F0c0FycmF5KCk7XG4gICAgICBjYXNlIG9ydEZicy5BdHRyaWJ1dGVUeXBlLklOVFM6IHtcbiAgICAgICAgY29uc3QgaW50cyA9IFtdO1xuICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGF0dHIuaW50c0xlbmd0aCgpOyBpKyspIHtcbiAgICAgICAgICBpbnRzLnB1c2goYXR0ci5pbnRzKGkpISk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGludHM7XG4gICAgICB9XG4gICAgICBjYXNlIG9ydEZicy5BdHRyaWJ1dGVUeXBlLlNUUklOR1M6IHtcbiAgICAgICAgY29uc3Qgc3RyaW5ncyA9IFtdO1xuICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGF0dHIuc3RyaW5nc0xlbmd0aCgpOyBpKyspIHtcbiAgICAgICAgICBzdHJpbmdzLnB1c2goYXR0ci5zdHJpbmdzKGkpKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gc3RyaW5ncztcbiAgICAgIH1cbiAgICAgIGNhc2Ugb3J0RmJzLkF0dHJpYnV0ZVR5cGUuVEVOU09SUzoge1xuICAgICAgICBjb25zdCB0ZW5zb3JzID0gW107XG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgYXR0ci50ZW5zb3JzTGVuZ3RoKCk7IGkrKykge1xuICAgICAgICAgIHRlbnNvcnMucHVzaChhdHRyLnRlbnNvcnMoaSkhKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGVuc29ycztcbiAgICAgIH1cbiAgICAgIC8vIGNhc2Ugb3J0RmJzLkF0dHJpYnV0ZVR5cGUuR1JBUEhTOlxuICAgICAgLy8gVE9ETzogU3ViZ3JhcGggbm90IHN1cHBvcnRlZCB5ZXQuXG4gICAgICAvLyBjb25zdCBncmFwaHMgPSBbXTtcbiAgICAgIC8vIGZvciAobGV0IGkgPSAwOyBpIDwgYXR0ci5ncmFwaHNMZW5ndGgoKTsgaSsrKSB7XG4gICAgICAvLyAgIGdyYXBocy5wdXNoKGF0dHIuZ3JhcGhzKGkpISk7XG4gICAgICAvLyB9XG4gICAgICAvLyByZXR1cm4gZ3JhcGhzO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGB1bnN1cHBvcnRlZCBhdHRyaWJ1dGUgdHlwZTogJHtvcnRGYnMuQXR0cmlidXRlVHlwZVthdHRyLnR5cGUoKV19YCk7XG4gICAgfVxuICB9XG5cbiAgcHJvdGVjdGVkIF9hdHRyaWJ1dGVzOiBNYXA8c3RyaW5nLCBWYWx1ZT47XG59XG4iLCIvLyBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cblxuaW1wb3J0IHtXZWJHTEJhY2tlbmR9IGZyb20gJy4vYmFja2VuZHMvYmFja2VuZC13ZWJnbCc7XG5pbXBvcnQge0dyYXBofSBmcm9tICcuL2dyYXBoJztcbmltcG9ydCB7T3BlcmF0b3J9IGZyb20gJy4vb3BlcmF0b3JzJztcbmltcG9ydCB7T3BTZXR9IGZyb20gJy4vb3BzZXQnO1xuaW1wb3J0IHtTZXNzaW9ufSBmcm9tICcuL3Nlc3Npb24nO1xuXG5leHBvcnQgaW50ZXJmYWNlIEluZmVyZW5jZUhhbmRsZXIge1xuICAvKipcbiAgICogZGlzcG9zZSB0aGUgaW5mZXJlbmNlIGhhbmRsZXIuIGl0IHdpbGwgYmUgY2FsbGVkIGFzIHRoZSBsYXN0IHN0ZXAgaW4gU2Vzc2lvbi5ydW4oKVxuICAgKi9cbiAgZGlzcG9zZSgpOiB2b2lkO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFNlc3Npb25IYW5kbGVyIHtcbiAgLyoqXG4gICAqIHRyYW5zZm9ybSB0aGUgZ3JhcGggYXQgaW5pdGlhbGl6YXRpb24gdGltZVxuICAgKiBAcGFyYW0gZ3JhcGhUcmFuc2Zvcm1lciB0aGUgZ3JhcGggdHJhbnNmb3JtZXIgdG8gbWFuaXB1bGF0ZSB0aGUgbW9kZWwgZ3JhcGhcbiAgICovXG4gIHRyYW5zZm9ybUdyYXBoPyhncmFwaFRyYW5zZm9ybWVyOiBHcmFwaC5UcmFuc2Zvcm1lcik6IHZvaWQ7XG5cbiAgLyoqXG4gICAqIGNyZWF0ZSBhbiBpbnN0YW5jZSBvZiBJbmZlcmVuY2VIYW5kbGVyIHRvIHVzZSBpbiBhIFNlc3Npb24ucnVuKCkgY2FsbFxuICAgKi9cbiAgY3JlYXRlSW5mZXJlbmNlSGFuZGxlcigpOiBJbmZlcmVuY2VIYW5kbGVyO1xuXG4gIC8qKlxuICAgKiBkaXNwb3NlIHRoZSBzZXNzaW9uIGhhbmRsZXIuIGl0IHdpbGwgYmUgY2FsbGVkIHdoZW4gYSBzZXNzaW9uIGlzIGJlaW5nIGRpc3Bvc2VkIGV4cGxpY2l0bHlcbiAgICovXG4gIGRpc3Bvc2UoKTogdm9pZDtcblxuICAvKipcbiAgICogUmVzb2x2ZXMgdGhlIG9wZXJhdG9yIGZyb20gdGhlIG5hbWUgYW5kIG9wc2V0IHZlcnNpb247IGJhY2tlbmQgc3BlY2lmaWNcbiAgICogQHBhcmFtIG5vZGUgdGhlIG5vZGUgdG8gcmVzb2x2ZVxuICAgKiBAcGFyYW0gb3BzZXRzIGEgbGlzdCBvZiBvcHNldHMgdGhhdCBleHBvcnRlZCBmcm9tIHRoZSBtb2RlbFxuICAgKiBAcGFyYW0gZ3JhcGggdGhlIGNvbXBsZXRlbHkgaW5pdGlhbGl6ZWQgZ3JhcGhcbiAgICovXG4gIHJlc29sdmUobm9kZTogR3JhcGguTm9kZSwgb3BzZXRzOiByZWFkb25seSBPcFNldFtdLCBncmFwaDogR3JhcGgpOiBPcGVyYXRvcjtcblxuICAvKipcbiAgICogVGhpcyBtZXRob2QgbGV0J3MgdGhlIHNlc3Npb25IYW5kbGVyIGtub3cgdGhhdCB0aGUgZ3JhcGggaW5pdGlhbGl6YXRpb24gaXMgY29tcGxldGVcbiAgICogQHBhcmFtIGdyYXBoIHRoZSBjb21wbGV0ZWx5IGluaXRpYWxpemVkIGdyYXBoXG4gICAqL1xuICBvbkdyYXBoSW5pdGlhbGl6ZWQ/KGdyYXBoOiBHcmFwaCk6IHZvaWQ7XG5cbiAgLyoqXG4gICAqIGEgcmVmZXJlbmNlIHRvIHRoZSBjb3JyZXNwb25kaW5nIGJhY2tlbmRcbiAgICovXG4gIHJlYWRvbmx5IGJhY2tlbmQ6IEJhY2tlbmQ7XG5cbiAgLyoqXG4gICAqIGEgcmVmZXJlbmNlIHRvIHRoZSBzZXNzaW9uIGNvbnRleHRcbiAgICovXG4gIHJlYWRvbmx5IGNvbnRleHQ6IFNlc3Npb24uQ29udGV4dDtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBCYWNrZW5kIHtcbiAgLyoqXG4gICAqIGluaXRpYWxpemUgdGhlIGJhY2tlbmQuIHdpbGwgYmUgY2FsbGVkIG9ubHkgb25jZSwgd2hlbiB0aGUgZmlyc3QgdGltZSB0aGVcbiAgICogYmFja2VuZCBpdCB0byBiZSB1c2VkXG4gICAqL1xuICBpbml0aWFsaXplKCk6IGJvb2xlYW58UHJvbWlzZTxib29sZWFuPjtcblxuICAvKipcbiAgICogY3JlYXRlIGFuIGluc3RhbmNlIG9mIFNlc3Npb25IYW5kbGVyIHRvIHVzZSBpbiBhIFNlc3Npb24gb2JqZWN0J3MgbGlmZWN5Y2xlXG4gICAqL1xuICBjcmVhdGVTZXNzaW9uSGFuZGxlcihjb250ZXh0OiBTZXNzaW9uLkNvbnRleHQpOiBTZXNzaW9uSGFuZGxlcjtcblxuICAvKipcbiAgICogZGlzcG9zZSB0aGUgYmFja2VuZC4gY3VycmVudGx5IHRoaXMgd2lsbCBub3QgYmUgY2FsbGVkXG4gICAqL1xuICBkaXNwb3NlKCk6IHZvaWQ7XG59XG5cbi8vIGNhY2hlcyBhbGwgaW5pdGlhbGl6ZWQgYmFja2VuZCBpbnN0YW5jZXNcbmNvbnN0IGJhY2tlbmRzQ2FjaGU6IE1hcDxzdHJpbmcsIEJhY2tlbmQ+ID0gbmV3IE1hcCgpO1xuXG5leHBvcnQgY29uc3QgYmFja2VuZDoge1tuYW1lOiBzdHJpbmddOiBCYWNrZW5kfSA9IHtcbiAgd2ViZ2w6IG5ldyBXZWJHTEJhY2tlbmQoKSxcbn07XG5cbi8qKlxuICogUmVzb2x2ZSBhIHJlZmVyZW5jZSB0byB0aGUgYmFja2VuZC4gSWYgYSBoaW50IGlzIHNwZWNpZmllZCwgdGhlIGNvcnJlc3BvbmRpbmdcbiAqIGJhY2tlbmQgd2lsbCBiZSB1c2VkLlxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gcmVzb2x2ZUJhY2tlbmQoaGludD86IHN0cmluZ3xyZWFkb25seSBzdHJpbmdbXSk6IFByb21pc2U8QmFja2VuZD4ge1xuICBpZiAoIWhpbnQpIHtcbiAgICByZXR1cm4gcmVzb2x2ZUJhY2tlbmQoWyd3ZWJnbCddKTtcbiAgfSBlbHNlIHtcbiAgICBjb25zdCBoaW50cyA9IHR5cGVvZiBoaW50ID09PSAnc3RyaW5nJyA/IFtoaW50XSA6IGhpbnQ7XG5cbiAgICBmb3IgKGNvbnN0IGJhY2tlbmRIaW50IG9mIGhpbnRzKSB7XG4gICAgICBjb25zdCBjYWNoZSA9IGJhY2tlbmRzQ2FjaGUuZ2V0KGJhY2tlbmRIaW50KTtcbiAgICAgIGlmIChjYWNoZSkge1xuICAgICAgICByZXR1cm4gY2FjaGU7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IGJhY2tlbmQgPSBhd2FpdCB0cnlMb2FkQmFja2VuZChiYWNrZW5kSGludCk7XG4gICAgICBpZiAoYmFja2VuZCkge1xuICAgICAgICByZXR1cm4gYmFja2VuZDtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICB0aHJvdyBuZXcgRXJyb3IoJ25vIGF2YWlsYWJsZSBiYWNrZW5kIHRvIHVzZScpO1xufVxuXG5hc3luYyBmdW5jdGlvbiB0cnlMb2FkQmFja2VuZChiYWNrZW5kSGludDogc3RyaW5nKTogUHJvbWlzZTxCYWNrZW5kfHVuZGVmaW5lZD4ge1xuICBjb25zdCBiYWNrZW5kT2JqID0gYmFja2VuZDtcblxuICBpZiAodHlwZW9mIGJhY2tlbmRPYmpbYmFja2VuZEhpbnRdICE9PSAndW5kZWZpbmVkJyAmJiBpc0JhY2tlbmQoYmFja2VuZE9ialtiYWNrZW5kSGludF0pKSB7XG4gICAgY29uc3QgYmFja2VuZCA9IGJhY2tlbmRPYmpbYmFja2VuZEhpbnRdO1xuICAgIGxldCBpbml0ID0gYmFja2VuZC5pbml0aWFsaXplKCk7XG4gICAgaWYgKHR5cGVvZiBpbml0ID09PSAnb2JqZWN0JyAmJiAndGhlbicgaW4gaW5pdCkge1xuICAgICAgaW5pdCA9IGF3YWl0IGluaXQ7XG4gICAgfVxuICAgIGlmIChpbml0KSB7XG4gICAgICBiYWNrZW5kc0NhY2hlLnNldChiYWNrZW5kSGludCwgYmFja2VuZCk7XG4gICAgICByZXR1cm4gYmFja2VuZDtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gdW5kZWZpbmVkO1xufVxuXG5mdW5jdGlvbiBpc0JhY2tlbmQob2JqOiB1bmtub3duKSB7XG4gIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tZXhwbGljaXQtYW55XG4gIGNvbnN0IG8gPSBvYmogYXMgYW55O1xuXG4gIC8vIGNoZWNrIGlmIGFuIG9iamVjdCBpcyBhIEJhY2tlbmQgaW5zdGFuY2VcbiAgaWYgKFxuICAgICAgJ2luaXRpYWxpemUnIGluIG8gJiYgdHlwZW9mIG8uaW5pdGlhbGl6ZSA9PT0gJ2Z1bmN0aW9uJyAmJiAgICAgICAgICAgICAgICAgICAgICAvLyBpbml0aWFsaXplKClcbiAgICAgICdjcmVhdGVTZXNzaW9uSGFuZGxlcicgaW4gbyAmJiB0eXBlb2Ygby5jcmVhdGVTZXNzaW9uSGFuZGxlciA9PT0gJ2Z1bmN0aW9uJyAmJiAgLy8gY3JlYXRlU2Vzc2lvbkhhbmRsZXIoKVxuICAgICAgJ2Rpc3Bvc2UnIGluIG8gJiYgdHlwZW9mIG8uZGlzcG9zZSA9PT0gJ2Z1bmN0aW9uJyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBkaXNwb3NlKClcbiAgKSB7XG4gICAgcmV0dXJuIHRydWU7XG4gIH1cblxuICByZXR1cm4gZmFsc2U7XG59XG5cbmV4cG9ydCB0eXBlIEJhY2tlbmRUeXBlID0gQmFja2VuZDtcbmV4cG9ydCB0eXBlIFNlc3Npb25IYW5kbGVyVHlwZSA9IFJldHVyblR5cGU8QmFja2VuZFR5cGVbJ2NyZWF0ZVNlc3Npb25IYW5kbGVyJ10+O1xuZXhwb3J0IHR5cGUgSW5mZXJlbmNlSGFuZGxlclR5cGUgPSBSZXR1cm5UeXBlPFNlc3Npb25IYW5kbGVyVHlwZVsnY3JlYXRlSW5mZXJlbmNlSGFuZGxlciddPjtcbiIsIi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxuXG5pbXBvcnQge2Vudn0gZnJvbSAnb25ueHJ1bnRpbWUtY29tbW9uJztcblxuaW1wb3J0IHtCYWNrZW5kLCBTZXNzaW9uSGFuZGxlcn0gZnJvbSAnLi4vYmFja2VuZCc7XG5pbXBvcnQge0xvZ2dlcn0gZnJvbSAnLi4vaW5zdHJ1bWVudCc7XG5pbXBvcnQge1Nlc3Npb259IGZyb20gJy4uL3Nlc3Npb24nO1xuXG5pbXBvcnQge1dlYkdMU2Vzc2lvbkhhbmRsZXJ9IGZyb20gJy4vd2ViZ2wvc2Vzc2lvbi1oYW5kbGVyJztcbmltcG9ydCB7V2ViR0xDb250ZXh0fSBmcm9tICcuL3dlYmdsL3dlYmdsLWNvbnRleHQnO1xuaW1wb3J0IHtjcmVhdGVXZWJHTENvbnRleHR9IGZyb20gJy4vd2ViZ2wvd2ViZ2wtY29udGV4dC1mYWN0b3J5JztcblxuLyoqXG4gKiBXZWJHTEJhY2tlbmQgaXMgdGhlIGVudHJ5IHBvaW50IGZvciBhbGwgV2ViR0wgb3BlYXJ0aW9uc1xuICogV2hlbiBpdCBzdGFydHMgaXQgY3JlYXRlZCB0aGUgV2ViR0xSZW5kZXJpbmdDb250ZXh0XG4gKiBhbmQgb3RoZXIgbWFpbiBmcmFtZXdvcmsgY29tcG9uZW50cyBzdWNoIGFzIFByb2dyYW0gYW5kIFRleHR1cmUgTWFuYWdlcnNcbiAqL1xuZXhwb3J0IGNsYXNzIFdlYkdMQmFja2VuZCBpbXBsZW1lbnRzIEJhY2tlbmQge1xuICBnbENvbnRleHQ6IFdlYkdMQ29udGV4dDtcblxuICBnZXQgY29udGV4dElkKCk6ICd3ZWJnbCd8J3dlYmdsMid8dW5kZWZpbmVkIHtcbiAgICByZXR1cm4gZW52LndlYmdsLmNvbnRleHRJZDtcbiAgfVxuICBzZXQgY29udGV4dElkKHZhbHVlOiAnd2ViZ2wnfCd3ZWJnbDInfHVuZGVmaW5lZCkge1xuICAgIGVudi53ZWJnbC5jb250ZXh0SWQgPSB2YWx1ZTtcbiAgfVxuXG4gIGdldCBtYXRtdWxNYXhCYXRjaFNpemUoKTogbnVtYmVyfHVuZGVmaW5lZCB7XG4gICAgcmV0dXJuIGVudi53ZWJnbC5tYXRtdWxNYXhCYXRjaFNpemU7XG4gIH1cbiAgc2V0IG1hdG11bE1heEJhdGNoU2l6ZSh2YWx1ZTogbnVtYmVyfHVuZGVmaW5lZCkge1xuICAgIGVudi53ZWJnbC5tYXRtdWxNYXhCYXRjaFNpemUgPSB2YWx1ZTtcbiAgfVxuXG4gIGdldCB0ZXh0dXJlQ2FjaGVNb2RlKCk6ICdpbml0aWFsaXplck9ubHknfCdmdWxsJ3x1bmRlZmluZWQge1xuICAgIHJldHVybiBlbnYud2ViZ2wudGV4dHVyZUNhY2hlTW9kZTtcbiAgfVxuICBzZXQgdGV4dHVyZUNhY2hlTW9kZSh2YWx1ZTogJ2luaXRpYWxpemVyT25seSd8J2Z1bGwnfHVuZGVmaW5lZCkge1xuICAgIGVudi53ZWJnbC50ZXh0dXJlQ2FjaGVNb2RlID0gdmFsdWU7XG4gIH1cblxuICBnZXQgcGFjaygpOiBib29sZWFufHVuZGVmaW5lZCB7XG4gICAgcmV0dXJuIGVudi53ZWJnbC5wYWNrO1xuICB9XG4gIHNldCBwYWNrKHZhbHVlOiBib29sZWFufHVuZGVmaW5lZCkge1xuICAgIGVudi53ZWJnbC5wYWNrID0gdmFsdWU7XG4gIH1cblxuICBnZXQgYXN5bmMoKTogYm9vbGVhbnx1bmRlZmluZWQge1xuICAgIHJldHVybiBlbnYud2ViZ2wuYXN5bmM7XG4gIH1cbiAgc2V0IGFzeW5jKHZhbHVlOiBib29sZWFufHVuZGVmaW5lZCkge1xuICAgIGVudi53ZWJnbC5hc3luYyA9IHZhbHVlO1xuICB9XG5cbiAgaW5pdGlhbGl6ZSgpOiBib29sZWFuIHtcbiAgICB0cnkge1xuICAgICAgdGhpcy5nbENvbnRleHQgPSBjcmVhdGVXZWJHTENvbnRleHQodGhpcy5jb250ZXh0SWQpO1xuICAgICAgaWYgKHR5cGVvZiB0aGlzLm1hdG11bE1heEJhdGNoU2l6ZSAhPT0gJ251bWJlcicpIHtcbiAgICAgICAgdGhpcy5tYXRtdWxNYXhCYXRjaFNpemUgPSAxNjtcbiAgICAgIH1cbiAgICAgIGlmICh0eXBlb2YgdGhpcy50ZXh0dXJlQ2FjaGVNb2RlICE9PSAnc3RyaW5nJykge1xuICAgICAgICB0aGlzLnRleHR1cmVDYWNoZU1vZGUgPSAnZnVsbCc7XG4gICAgICB9XG4gICAgICBpZiAodHlwZW9mIHRoaXMucGFjayAhPT0gJ2Jvb2xlYW4nKSB7XG4gICAgICAgIHRoaXMucGFjayA9IGZhbHNlO1xuICAgICAgfVxuICAgICAgaWYgKHR5cGVvZiB0aGlzLmFzeW5jICE9PSAnYm9vbGVhbicpIHtcbiAgICAgICAgdGhpcy5hc3luYyA9IGZhbHNlO1xuICAgICAgfVxuXG4gICAgICBMb2dnZXIuc2V0V2l0aEVudihlbnYpO1xuXG4gICAgICBMb2dnZXIudmVyYm9zZShcbiAgICAgICAgICAnV2ViR0xCYWNrZW5kJyxcbiAgICAgICAgICBgQ3JlYXRlZCBXZWJHTENvbnRleHQ6ICR7dHlwZW9mIHRoaXMuZ2xDb250ZXh0fSB3aXRoIG1hdG11bE1heEJhdGNoU2l6ZTogJHtcbiAgICAgICAgICAgICAgdGhpcy5tYXRtdWxNYXhCYXRjaFNpemV9OyB0ZXh0dXJlQ2FjaGVNb2RlOiAke3RoaXMudGV4dHVyZUNhY2hlTW9kZX07IHBhY2s6ICR7dGhpcy5wYWNrfTsgYXN5bmM6ICR7XG4gICAgICAgICAgICAgIHRoaXMuYXN5bmN9LmApO1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgTG9nZ2VyLndhcm5pbmcoJ1dlYkdMQmFja2VuZCcsIGBVbmFibGUgdG8gaW5pdGlhbGl6ZSBXZWJHTEJhY2tlbmQuICR7ZX1gKTtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gIH1cbiAgY3JlYXRlU2Vzc2lvbkhhbmRsZXIoY29udGV4dDogU2Vzc2lvbi5Db250ZXh0KTogU2Vzc2lvbkhhbmRsZXIge1xuICAgIHJldHVybiBuZXcgV2ViR0xTZXNzaW9uSGFuZGxlcih0aGlzLCBjb250ZXh0KTtcbiAgfVxuICBkaXNwb3NlKCk6IHZvaWQge1xuICAgIHRoaXMuZ2xDb250ZXh0LmRpc3Bvc2UoKTtcbiAgfVxufVxuIiwiLy8gQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXG5cbmltcG9ydCB7QXJyYXlVdGlsLCBCcm9hZGNhc3RVdGlsLCBTaGFwZVV0aWx9IGZyb20gJy4uLy4uL3V0aWwnO1xuXG5pbXBvcnQge0dsc2xDb250ZXh0LCBHbHNsTGliLCBHbHNsTGliUm91dGluZX0gZnJvbSAnLi9nbHNsLWRlZmluaXRpb25zJztcbmltcG9ydCB7Z2V0R2xzbH0gZnJvbSAnLi9nbHNsLXNvdXJjZSc7XG5pbXBvcnQge3NxdWVlemVTaGFwZX0gZnJvbSAnLi90ZXh0dXJlLWxheW91dC1zdHJhdGVneSc7XG5pbXBvcnQge1RleHR1cmVMYXlvdXR9IGZyb20gJy4vdHlwZXMnO1xuaW1wb3J0IHtnZW5lcmF0ZVNoYWRlckZ1bmNOYW1lRnJvbUlucHV0U2FtcGxlck5hbWUsIGdlbmVyYXRlU2hhZGVyRnVuY05hbWVGcm9tSW5wdXRTYW1wbGVyTmFtZUF0T3V0Q29vcmRzLCBnZXRDb29yZHNEYXRhVHlwZSwgZ2V0R2xDaGFubmVscywgZ2V0U3F1ZWV6ZWRQYXJhbXMsIHNxdWVlemVJbnB1dFNoYXBlfSBmcm9tICcuL3V0aWxzJztcblxuLyoqXG4gKiBHTFNMIExpYnJhcnkgcmVzcG9uc2libGUgZm9yIGRhdGEgdHlwZXMgYW5kIHJvdXRpbmVzIGZvciBtYW5pcHVsYXRpbmdcbiAqIGNvb3JkaW5hdGVzIGFuZCBtYXBwaW5nIHRvL2Zyb20gdGVuc29yIGluZGljZXNcbiAqL1xuZXhwb3J0IGNsYXNzIENvb3Jkc0dsc2xMaWIgZXh0ZW5kcyBHbHNsTGliIHtcbiAgcmV0dXJuVHlwZTogc3RyaW5nO1xuXG4gIGNvbnN0cnVjdG9yKGNvbnRleHQ6IEdsc2xDb250ZXh0KSB7XG4gICAgc3VwZXIoY29udGV4dCk7XG4gIH1cbiAgZ2V0RnVuY3Rpb25zKCk6IHtbbmFtZTogc3RyaW5nXTogR2xzbExpYlJvdXRpbmV9IHtcbiAgICByZXR1cm4ge1xuICAgICAgLi4udGhpcy5vZmZzZXRUb0Nvb3JkcygpLFxuICAgICAgLi4udGhpcy5jb29yZHNUb09mZnNldCgpLFxuICAgICAgLi4udGhpcy50b1ZlYygpLFxuICAgICAgLi4udGhpcy52YWx1ZUZyb20oKSxcbiAgICAgIC8vIFRPRE8gcmV0dXJuIHRoZXNlIG9ubHkgd2hlbiBwYWNraW5nIGlzIGVuYWJsZWQuXG4gICAgICAuLi50aGlzLmdldENvbW1vblV0aWxGdW5jcygpLFxuICAgICAgLi4udGhpcy5nZXRJbnB1dHNTYW1wbGluZ1NuaXBwZXRzKCksXG4gICAgICAuLi50aGlzLmdldE91dHB1dFNhbXBsaW5nU25pcHBldCgpXG4gICAgfTtcbiAgfVxuICBnZXRDdXN0b21UeXBlcygpIHtcbiAgICByZXR1cm4ge307XG4gIH1cbiAgLyoqXG4gICAqIFByb2R1Y2VzIGEgZnVuY3Rpb24gdGhhdCBjYW4gbWFwIGZyb21cbiAgICogMkQgbm9ybWFsemllZCBjb29yZGluYXRlcyAocyx0KSB0byBhIGZsYXQgb2Zmc2V0XG4gICAqL1xuICBwcm90ZWN0ZWQgb2Zmc2V0VG9Db29yZHMoKToge1tuYW1lOiBzdHJpbmddOiBHbHNsTGliUm91dGluZX0ge1xuICAgIGNvbnN0IGZ1bmNOYW1lID0gJ29mZnNldFRvQ29vcmRzJztcbiAgICByZXR1cm4ge1xuICAgICAgb2Zmc2V0VG9Db29yZHM6IG5ldyBHbHNsTGliUm91dGluZShgXG4gICAgICB2ZWMyICR7ZnVuY05hbWV9KGludCBvZmZzZXQsIGludCB3aWR0aCwgaW50IGhlaWdodCkge1xuICAgICAgICBpbnQgdCA9IG9mZnNldCAvIHdpZHRoO1xuICAgICAgICBpbnQgcyA9IG9mZnNldCAtIHQqd2lkdGg7XG4gICAgICAgIHZlYzIgY29vcmRzID0gKHZlYzIocyx0KSArIHZlYzIoMC41LDAuNSkpIC8gdmVjMih3aWR0aCwgaGVpZ2h0KTtcbiAgICAgICAgcmV0dXJuIGNvb3JkcztcbiAgICAgIH1cbiAgICAgIGApXG4gICAgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBQcm9kdWNlcyBhIGZ1bmN0aW9uIHRoYXQgY2FuIG1hcCBmcm9tXG4gICAqIDJEIG5vcm1hbHppZWQgY29vcmRpbmF0ZXMgKHMsdCkgdG8gYSBmbGF0IG9mZnNldFxuICAgKi9cbiAgcHJvdGVjdGVkIGNvb3Jkc1RvT2Zmc2V0KCk6IHtbbmFtZTogc3RyaW5nXTogR2xzbExpYlJvdXRpbmV9IHtcbiAgICBjb25zdCBmdW5jTmFtZSA9ICdjb29yZHNUb09mZnNldCc7XG4gICAgcmV0dXJuIHtcbiAgICAgIGNvb3Jkc1RvT2Zmc2V0OiBuZXcgR2xzbExpYlJvdXRpbmUoYFxuICAgICAgaW50ICR7ZnVuY05hbWV9KHZlYzIgY29vcmRzLCBpbnQgd2lkdGgsIGludCBoZWlnaHQpIHtcbiAgICAgICAgZmxvYXQgcyA9IGNvb3Jkcy5zICogZmxvYXQod2lkdGgpO1xuICAgICAgICBmbG9hdCB0ID0gY29vcmRzLnQgKiBmbG9hdChoZWlnaHQpO1xuICAgICAgICBpbnQgb2Zmc2V0ID0gaW50KHQpICogd2lkdGggKyBpbnQocyk7XG4gICAgICAgIHJldHVybiBvZmZzZXQ7XG4gICAgICB9XG4gICAgICBgKVxuICAgIH07XG4gIH1cblxuICAvKipcbiAgICogR2VuZXJhdGVzIGNvZGUgZm9yIG91dHB1dCBzYW1wbGVyLlxuICAgKi9cblxuICBwcm90ZWN0ZWQgZ2V0T3V0cHV0U2FtcGxpbmdTbmlwcGV0KCk6IHtbbmFtZTogc3RyaW5nXTogR2xzbExpYlJvdXRpbmV9IHtcbiAgICBjb25zdCBvdXRwdXRMYXlvdXQgPSB0aGlzLmNvbnRleHQub3V0cHV0VGV4dHVyZUxheW91dDtcbiAgICBpZiAob3V0cHV0TGF5b3V0LmlzUGFja2VkKSB7XG4gICAgICByZXR1cm4gdGhpcy5nZXRQYWNrZWRPdXRwdXRTYW1wbGluZ1NuaXBwZXQob3V0cHV0TGF5b3V0KTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIHRoaXMuZ2V0VW5wYWNrZWRPdXRwdXRTYW1wbGluZ1NuaXBwZXQob3V0cHV0TGF5b3V0KTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogR2VuZXJhdGVzIGNvZGUgZm9yIHBhY2tlZCBvdXRwdXQgc2FtcGxlci5cbiAgICovXG4gIHByb3RlY3RlZCBnZXRQYWNrZWRPdXRwdXRTYW1wbGluZ1NuaXBwZXQob3V0cHV0TGF5b3V0OiBUZXh0dXJlTGF5b3V0KToge1tuYW1lOiBzdHJpbmddOiBHbHNsTGliUm91dGluZX0ge1xuICAgIGNvbnN0IG91dFNoYXBlID0gb3V0cHV0TGF5b3V0LnVucGFja2VkU2hhcGU7XG4gICAgY29uc3Qgb3V0VGV4U2hhcGUgPSBbb3V0cHV0TGF5b3V0LndpZHRoLCBvdXRwdXRMYXlvdXQuaGVpZ2h0XTtcbiAgICBjb25zdCByZXN1bHQ6IHtbbmFtZTogc3RyaW5nXTogR2xzbExpYlJvdXRpbmV9ID0ge307XG4gICAgY29uc3QgZnVuY05hbWUgPSAnZ2V0T3V0cHV0Q29vcmRzJztcbiAgICBzd2l0Y2ggKG91dFNoYXBlLmxlbmd0aCkge1xuICAgICAgY2FzZSAwOlxuICAgICAgICByZXN1bHRbZnVuY05hbWVdID0gdGhpcy5nZXRPdXRwdXRTY2FsYXJDb29yZHMoKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIDE6XG4gICAgICAgIHJlc3VsdFtmdW5jTmFtZV0gPSB0aGlzLmdldE91dHB1dFBhY2tlZDFEQ29vcmRzKG91dFNoYXBlIGFzIFtudW1iZXJdLCBvdXRUZXhTaGFwZSBhcyBbbnVtYmVyLCBudW1iZXJdKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIDI6XG4gICAgICAgIHJlc3VsdFtmdW5jTmFtZV0gPSB0aGlzLmdldE91dHB1dFBhY2tlZDJEQ29vcmRzKG91dFNoYXBlIGFzIFtudW1iZXIsIG51bWJlcl0sIG91dFRleFNoYXBlIGFzIFtudW1iZXIsIG51bWJlcl0pO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgMzpcbiAgICAgICAgcmVzdWx0W2Z1bmNOYW1lXSA9XG4gICAgICAgICAgICB0aGlzLmdldE91dHB1dFBhY2tlZDNEQ29vcmRzKG91dFNoYXBlIGFzIFtudW1iZXIsIG51bWJlciwgbnVtYmVyXSwgb3V0VGV4U2hhcGUgYXMgW251bWJlciwgbnVtYmVyXSk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgcmVzdWx0W2Z1bmNOYW1lXSA9IHRoaXMuZ2V0T3V0cHV0UGFja2VkTkRDb29yZHMob3V0U2hhcGUsIG91dFRleFNoYXBlIGFzIFtudW1iZXIsIG51bWJlcl0pO1xuICAgIH1cbiAgICBjb25zdCBnbHNsID0gZ2V0R2xzbCh0aGlzLmNvbnRleHQuZ2xDb250ZXh0LnZlcnNpb24pO1xuICAgIC8vIFRPRE8gd2UgbmVlZCB0aGlzIHRvIHByb3Blcmx5IHJldHVybiBhIHBhY2tlZCB2ZWM0IGZyb20ga2VybmVscy5cbiAgICAvLyBSZXBsYWNlIGFsbCAne2dsc2wub3V0cHV0fSA9IHJlc3VsdCcgd2l0aCAnc2V0T3V0cHV0KHJlc3VsdCknIGluIGFsbCBrZXJuZWxzLlxuICAgIGNvbnN0IGZsb2F0VGV4dHVyZVNldFJHQkFTb3VyY2UgPSBgXG4gICAgICB2b2lkIHNldE91dHB1dCh2ZWM0IHZhbCkge1xuICAgICAgICAke2dsc2wub3V0cHV0fSA9IHZhbDtcbiAgICAgIH1cbiAgICBgO1xuICAgIGNvbnN0IGZsb2F0VGV4dHVyZVNldFJHQkFGdW5jTmFtZSA9ICdmbG9hdFRleHR1cmVTZXRSR0JBJztcbiAgICByZXN1bHRbZmxvYXRUZXh0dXJlU2V0UkdCQUZ1bmNOYW1lXSA9IG5ldyBHbHNsTGliUm91dGluZShmbG9hdFRleHR1cmVTZXRSR0JBU291cmNlKTtcbiAgICByZXR1cm4gcmVzdWx0O1xuICB9XG5cbiAgLyoqXG4gICAqIEdlbmVyYXRlcyBjb2RlIGZvciB1bnBhY2tlZCBvdXRwdXQgc2FtcGxlci5cbiAgICovXG4gIHByb3RlY3RlZCBnZXRVbnBhY2tlZE91dHB1dFNhbXBsaW5nU25pcHBldChvdXRwdXRMYXlvdXQ6IFRleHR1cmVMYXlvdXQpOiB7W25hbWU6IHN0cmluZ106IEdsc2xMaWJSb3V0aW5lfSB7XG4gICAgY29uc3Qgb3V0U2hhcGUgPSBvdXRwdXRMYXlvdXQudW5wYWNrZWRTaGFwZTtcbiAgICBjb25zdCBvdXRUZXhTaGFwZSA9IFtvdXRwdXRMYXlvdXQud2lkdGgsIG91dHB1dExheW91dC5oZWlnaHRdO1xuICAgIGNvbnN0IHJlc3VsdDoge1tuYW1lOiBzdHJpbmddOiBHbHNsTGliUm91dGluZX0gPSB7fTtcbiAgICBjb25zdCBmdW5jTmFtZSA9ICdnZXRPdXRwdXRDb29yZHMnO1xuICAgIHN3aXRjaCAob3V0U2hhcGUubGVuZ3RoKSB7XG4gICAgICBjYXNlIDA6XG4gICAgICAgIHJlc3VsdFtmdW5jTmFtZV0gPSB0aGlzLmdldE91dHB1dFNjYWxhckNvb3JkcygpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgMTpcbiAgICAgICAgcmVzdWx0W2Z1bmNOYW1lXSA9IHRoaXMuZ2V0T3V0cHV0VW5wYWNrZWQxRENvb3JkcyhvdXRTaGFwZSBhcyBbbnVtYmVyXSwgb3V0VGV4U2hhcGUgYXMgW251bWJlciwgbnVtYmVyXSk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAyOlxuICAgICAgICByZXN1bHRbZnVuY05hbWVdID1cbiAgICAgICAgICAgIHRoaXMuZ2V0T3V0cHV0VW5wYWNrZWQyRENvb3JkcyhvdXRTaGFwZSBhcyBbbnVtYmVyLCBudW1iZXJdLCBvdXRUZXhTaGFwZSBhcyBbbnVtYmVyLCBudW1iZXJdKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIDM6XG4gICAgICAgIHJlc3VsdFtmdW5jTmFtZV0gPVxuICAgICAgICAgICAgdGhpcy5nZXRPdXRwdXRVbnBhY2tlZDNEQ29vcmRzKG91dFNoYXBlIGFzIFtudW1iZXIsIG51bWJlciwgbnVtYmVyXSwgb3V0VGV4U2hhcGUgYXMgW251bWJlciwgbnVtYmVyXSk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSA0OlxuICAgICAgICByZXN1bHRbZnVuY05hbWVdID0gdGhpcy5nZXRPdXRwdXRVbnBhY2tlZDREQ29vcmRzKFxuICAgICAgICAgICAgb3V0U2hhcGUgYXMgW251bWJlciwgbnVtYmVyLCBudW1iZXIsIG51bWJlcl0sIG91dFRleFNoYXBlIGFzIFtudW1iZXIsIG51bWJlcl0pO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgNTpcbiAgICAgICAgcmVzdWx0W2Z1bmNOYW1lXSA9IHRoaXMuZ2V0T3V0cHV0VW5wYWNrZWQ1RENvb3JkcyhcbiAgICAgICAgICAgIG91dFNoYXBlIGFzIFtudW1iZXIsIG51bWJlciwgbnVtYmVyLCBudW1iZXIsIG51bWJlcl0sIG91dFRleFNoYXBlIGFzIFtudW1iZXIsIG51bWJlcl0pO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgNjpcbiAgICAgICAgcmVzdWx0W2Z1bmNOYW1lXSA9IHRoaXMuZ2V0T3V0cHV0VW5wYWNrZWQ2RENvb3JkcyhcbiAgICAgICAgICAgIG91dFNoYXBlIGFzIFtudW1iZXIsIG51bWJlciwgbnVtYmVyLCBudW1iZXIsIG51bWJlciwgbnVtYmVyXSwgb3V0VGV4U2hhcGUgYXMgW251bWJlciwgbnVtYmVyXSk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBVbnN1cHBvcnRlZCBvdXRwdXQgZGltZW5zaW9uYWxpdHk6ICR7b3V0U2hhcGUubGVuZ3RofWApO1xuICAgIH1cbiAgICBjb25zdCBnbHNsID0gZ2V0R2xzbCh0aGlzLmNvbnRleHQuZ2xDb250ZXh0LnZlcnNpb24pO1xuICAgIC8vIFRPRE8gd2UgbmVlZCB0aGlzIHRvIHByb3Blcmx5IHJldHVybiBhIHBhY2tlZCB2ZWM0IGZyb20ga2VybmVscy5cbiAgICAvLyBSZXBsYWNlIGFsbCAne2dsc2wub3V0cHV0fSA9IHJlc3VsdCcgd2l0aCAnc2V0T3V0cHV0KHJlc3VsdCknIGluIGFsbCBrZXJuZWxzLlxuICAgIGNvbnN0IGZsb2F0VGV4dHVyZVNldFJTb3VyY2UgPSBgXG4gICAgICAgIHZvaWQgc2V0T3V0cHV0KGZsb2F0IHZhbCkge1xuICAgICAgICAgICR7Z2xzbC5vdXRwdXR9ID0gdmVjNCh2YWwsIDAsIDAsIDApO1xuICAgICAgICB9XG4gICAgYDtcbiAgICBjb25zdCBmbG9hdFRleHR1cmVTZXRSRnVuY05hbWUgPSAnZmxvYXRUZXh0dXJlU2V0Uic7XG4gICAgcmVzdWx0W2Zsb2F0VGV4dHVyZVNldFJGdW5jTmFtZV0gPSBuZXcgR2xzbExpYlJvdXRpbmUoZmxvYXRUZXh0dXJlU2V0UlNvdXJjZSk7XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfVxuXG4gIC8qKlxuICAgKiBTY2FsYXIgb3V0cHV0IGNvb3JkaW5hdGVzLlxuICAgKi9cbiAgcHJvdGVjdGVkIGdldE91dHB1dFNjYWxhckNvb3JkcygpOiBHbHNsTGliUm91dGluZSB7XG4gICAgcmV0dXJuIG5ldyBHbHNsTGliUm91dGluZShgXG4gICAgICBpbnQgZ2V0T3V0cHV0Q29vcmRzKCkge1xuICAgICAgICByZXR1cm4gMDtcbiAgICAgIH1cbiAgICBgKTtcbiAgfVxuXG4gIC8qKlxuICAgKiAxRCBwYWNrZWQgb3V0cHV0IGNvb3JkaW5hdGVzLlxuICAgKi9cbiAgcHJvdGVjdGVkIGdldE91dHB1dFBhY2tlZDFEQ29vcmRzKHNoYXBlOiBbbnVtYmVyXSwgdGV4U2hhcGU6IFtudW1iZXIsIG51bWJlcl0pOiBHbHNsTGliUm91dGluZSB7XG4gICAgY29uc3QgcGFja2VkVGV4U2hhcGUgPSB0ZXhTaGFwZTtcbiAgICBsZXQgc291cmNlID0gJyc7XG4gICAgaWYgKHBhY2tlZFRleFNoYXBlWzBdID09PSAxKSB7XG4gICAgICBzb3VyY2UgPSBgXG4gICAgICAgICAgaW50IGdldE91dHB1dENvb3JkcygpIHtcbiAgICAgICAgICAgIHJldHVybiAyICogaW50KFRleENvb3Jkcy55ICogJHtwYWNrZWRUZXhTaGFwZVsxXX0uMCk7XG4gICAgICAgICAgfVxuICAgICAgICBgO1xuICAgICAgcmV0dXJuIG5ldyBHbHNsTGliUm91dGluZShzb3VyY2UpO1xuICAgIH1cblxuICAgIGlmIChwYWNrZWRUZXhTaGFwZVsxXSA9PT0gMSkge1xuICAgICAgc291cmNlID0gYFxuICAgICAgICAgIGludCBnZXRPdXRwdXRDb29yZHMoKSB7XG4gICAgICAgICAgICByZXR1cm4gMiAqIGludChUZXhDb29yZHMueCAqICR7cGFja2VkVGV4U2hhcGVbMF19LjApO1xuICAgICAgICAgIH1cbiAgICAgICAgYDtcbiAgICAgIHJldHVybiBuZXcgR2xzbExpYlJvdXRpbmUoc291cmNlKTtcbiAgICB9XG5cbiAgICBzb3VyY2UgPSBgXG4gICAgICAgIGludCBnZXRPdXRwdXRDb29yZHMoKSB7XG4gICAgICAgICAgaXZlYzIgcmVzVGV4UkMgPSBpdmVjMihUZXhDb29yZHMueHkgKlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmVjMigke3BhY2tlZFRleFNoYXBlWzBdfSwgJHtwYWNrZWRUZXhTaGFwZVsxXX0pKTtcbiAgICAgICAgICByZXR1cm4gMiAqIChyZXNUZXhSQy55ICogJHtwYWNrZWRUZXhTaGFwZVswXX0gKyByZXNUZXhSQy54KTtcbiAgICAgICAgfVxuICAgICAgYDtcbiAgICByZXR1cm4gbmV3IEdsc2xMaWJSb3V0aW5lKHNvdXJjZSk7XG4gIH1cblxuICAvKipcbiAgICogMkQgcGFja2VkIG91dHB1dCBjb29yZGluYXRlcy5cbiAgICovXG4gIHByb3RlY3RlZCBnZXRPdXRwdXRQYWNrZWQyRENvb3JkcyhzaGFwZTogW251bWJlciwgbnVtYmVyXSwgdGV4U2hhcGU6IFtudW1iZXIsIG51bWJlcl0pOiBHbHNsTGliUm91dGluZSB7XG4gICAgbGV0IHNvdXJjZSA9ICcnO1xuICAgIGlmIChBcnJheVV0aWwuYXJyYXlzRXF1YWwoc2hhcGUsIHRleFNoYXBlKSkge1xuICAgICAgc291cmNlID0gYFxuICAgICAgICBpdmVjMiBnZXRPdXRwdXRDb29yZHMoKSB7XG4gICAgICAgICAgcmV0dXJuIDIgKiBpdmVjMihUZXhDb29yZHMueHkgKiB2ZWMyKCR7dGV4U2hhcGVbMF19LCAke3RleFNoYXBlWzFdfSkpO1xuICAgICAgICB9XG4gICAgICBgO1xuICAgICAgcmV0dXJuIG5ldyBHbHNsTGliUm91dGluZShzb3VyY2UpO1xuICAgIH1cblxuICAgIGNvbnN0IHBhY2tlZFRleFNoYXBlID0gdGV4U2hhcGU7XG4gICAgLy8gdGV4ZWxzIG5lZWRlZCB0byBhY2NvbW1vZGF0ZSBhIGxvZ2ljYWwgcm93XG4gICAgY29uc3QgdGV4ZWxzSW5Mb2dpY2FsUm93ID0gTWF0aC5jZWlsKHNoYXBlWzFdIC8gMik7XG5cbiAgICAvKipcbiAgICAgKiBnZXRPdXRwdXRDb29yZHNcbiAgICAgKlxuICAgICAqIHJlc1RleFJDOiBUaGUgcm93cyBhbmQgY29sdW1ucyBvZiB0aGUgdGV4ZWxzLiBJZiB5b3UgbW92ZSBvdmVyIG9uZVxuICAgICAqIHRleGVsIHRvIHRoZSByaWdodCBpbiB0aGUgcGFja2VkIHRleHR1cmUsIHlvdSBhcmUgbW92aW5nIG92ZXIgb25lIGNvbHVtblxuICAgICAqIChub3QgdHdvKS5cbiAgICAgKlxuICAgICAqIGluZGV4OiBUaGUgdGV4ZWwgaW5kZXhcbiAgICAgKi9cbiAgICBzb3VyY2UgPSBgXG4gICAgICAgIGl2ZWMyIGdldE91dHB1dENvb3JkcygpIHtcbiAgICAgICAgICBpdmVjMiByZXNUZXhSQyA9IGl2ZWMyKFRleENvb3Jkcy54eSAqXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZlYzIoJHtwYWNrZWRUZXhTaGFwZVswXX0sICR7cGFja2VkVGV4U2hhcGVbMV19KSk7XG5cbiAgICAgICAgICBpbnQgaW5kZXggPSByZXNUZXhSQy55ICogJHtwYWNrZWRUZXhTaGFwZVswXX0gKyByZXNUZXhSQy54O1xuXG4gICAgICAgICAgLy8gcmV2ZXJzZSByIGFuZCBjIG9yZGVyIGZvciBwYWNrZWQgdGV4dHVyZVxuICAgICAgICAgIGludCByID0gaW1vZChpbmRleCwgJHt0ZXhlbHNJbkxvZ2ljYWxSb3d9KSAqIDI7XG4gICAgICAgICAgaW50IGMgPSAyICogKGluZGV4IC8gJHt0ZXhlbHNJbkxvZ2ljYWxSb3d9KTtcblxuICAgICAgICAgIHJldHVybiBpdmVjMihyLCBjKTtcbiAgICAgICAgfVxuICAgICAgYDtcbiAgICByZXR1cm4gbmV3IEdsc2xMaWJSb3V0aW5lKHNvdXJjZSk7XG4gIH1cblxuICAvKipcbiAgICogM0QgcGFja2VkIG91dHB1dCBjb29yZGluYXRlcy5cbiAgICovXG4gIHByb3RlY3RlZCBnZXRPdXRwdXRQYWNrZWQzRENvb3JkcyhzaGFwZTogW251bWJlciwgbnVtYmVyLCBudW1iZXJdLCB0ZXhTaGFwZTogW251bWJlciwgbnVtYmVyXSk6IEdsc2xMaWJSb3V0aW5lIHtcbiAgICBjb25zdCBwYWNrZWRUZXhTaGFwZSA9IFt0ZXhTaGFwZVswXSwgdGV4U2hhcGVbMV1dO1xuICAgIGNvbnN0IHRleGVsc0luTG9naWNhbFJvdyA9IE1hdGguY2VpbChzaGFwZVsyXSAvIDIpO1xuICAgIGNvbnN0IHRleGVsc0luQmF0Y2ggPSB0ZXhlbHNJbkxvZ2ljYWxSb3cgKiBNYXRoLmNlaWwoc2hhcGVbMV0gLyAyKTtcbiAgICBjb25zdCBzb3VyY2UgPSBgXG4gICAgICAgIGl2ZWMzIGdldE91dHB1dENvb3JkcygpIHtcbiAgICAgICAgICBpdmVjMiByZXNUZXhSQyA9IGl2ZWMyKFRleENvb3Jkcy54eSAqXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZlYzIoJHtwYWNrZWRUZXhTaGFwZVswXX0sICR7cGFja2VkVGV4U2hhcGVbMV19KSk7XG4gICAgICAgICAgaW50IGluZGV4ID0gcmVzVGV4UkMueSAqICR7cGFja2VkVGV4U2hhcGVbMF19ICsgcmVzVGV4UkMueDtcblxuICAgICAgICAgIGludCBiID0gaW5kZXggLyAke3RleGVsc0luQmF0Y2h9O1xuICAgICAgICAgIGluZGV4IC09IGIgKiAke3RleGVsc0luQmF0Y2h9O1xuXG4gICAgICAgICAgLy8gcmV2ZXJzZSByIGFuZCBjIG9yZGVyIGZvciBwYWNrZWQgdGV4dHVyZVxuICAgICAgICAgIGludCByID0gaW1vZChpbmRleCwgJHt0ZXhlbHNJbkxvZ2ljYWxSb3d9KSAqIDI7XG4gICAgICAgICAgaW50IGMgPSAyICogKGluZGV4IC8gJHt0ZXhlbHNJbkxvZ2ljYWxSb3d9KTtcblxuICAgICAgICAgIHJldHVybiBpdmVjMyhiLCByLCBjKTtcbiAgICAgICAgfVxuICAgICAgYDtcbiAgICByZXR1cm4gbmV3IEdsc2xMaWJSb3V0aW5lKHNvdXJjZSk7XG4gIH1cblxuICAvKipcbiAgICogTkQgcGFja2VkIG91dHB1dCBjb29yZGluYXRlcy5cbiAgICovXG4gIHByb3RlY3RlZCBnZXRPdXRwdXRQYWNrZWRORENvb3JkcyhzaGFwZTogcmVhZG9ubHkgbnVtYmVyW10sIHRleFNoYXBlOiBbbnVtYmVyLCBudW1iZXJdKTogR2xzbExpYlJvdXRpbmUge1xuICAgIGNvbnN0IHBhY2tlZFRleFNoYXBlID0gW3RleFNoYXBlWzBdLCB0ZXhTaGFwZVsxXV07XG5cbiAgICBjb25zdCB0ZXhlbHNJbkxvZ2ljYWxSb3cgPSBNYXRoLmNlaWwoc2hhcGVbc2hhcGUubGVuZ3RoIC0gMV0gLyAyKTtcbiAgICBjb25zdCB0ZXhlbHNJbkJhdGNoID0gdGV4ZWxzSW5Mb2dpY2FsUm93ICogTWF0aC5jZWlsKHNoYXBlW3NoYXBlLmxlbmd0aCAtIDJdIC8gMik7XG4gICAgbGV0IHRleGVsc0luQmF0Y2hOID0gdGV4ZWxzSW5CYXRjaDtcbiAgICBsZXQgYmF0Y2hlcyA9ICcnO1xuICAgIGxldCBjb29yZHMgPSAnYiwgciwgYyc7XG5cbiAgICBmb3IgKGxldCBiID0gMjsgYiA8IHNoYXBlLmxlbmd0aCAtIDE7IGIrKykge1xuICAgICAgdGV4ZWxzSW5CYXRjaE4gKj0gc2hhcGVbc2hhcGUubGVuZ3RoIC0gYiAtIDFdO1xuICAgICAgYmF0Y2hlcyA9IGBcbiAgICAgIGludCBiJHtifSA9IGluZGV4IC8gJHt0ZXhlbHNJbkJhdGNoTn07XG4gICAgICBpbmRleCAtPSBiJHtifSAqICR7dGV4ZWxzSW5CYXRjaE59O1xuICAgIGAgKyBiYXRjaGVzO1xuICAgICAgY29vcmRzID0gYGIke2J9LCBgICsgY29vcmRzO1xuICAgIH1cbiAgICBjb25zdCBzb3VyY2UgPSBgXG4gICAgICBpdmVjJHtzaGFwZS5sZW5ndGh9IGdldE91dHB1dENvb3JkcygpIHtcbiAgICAgICAgaXZlYzIgcmVzVGV4UkMgPSBpdmVjMihUZXhDb29yZHMueHkgKlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmVjMigke3BhY2tlZFRleFNoYXBlWzBdfSwgJHtwYWNrZWRUZXhTaGFwZVsxXX0pKTtcbiAgICAgICAgaW50IGluZGV4ID0gcmVzVGV4UkMueSAqICR7cGFja2VkVGV4U2hhcGVbMF19ICsgcmVzVGV4UkMueDtcblxuICAgICAgICAke2JhdGNoZXN9XG5cbiAgICAgICAgaW50IGIgPSBpbmRleCAvICR7dGV4ZWxzSW5CYXRjaH07XG4gICAgICAgIGluZGV4IC09IGIgKiAke3RleGVsc0luQmF0Y2h9O1xuXG4gICAgICAgIC8vIHJldmVyc2UgciBhbmQgYyBvcmRlciBmb3IgcGFja2VkIHRleHR1cmVcbiAgICAgICAgaW50IHIgPSBpbW9kKGluZGV4LCAke3RleGVsc0luTG9naWNhbFJvd30pICogMjtcbiAgICAgICAgaW50IGMgPSAyICogKGluZGV4IC8gJHt0ZXhlbHNJbkxvZ2ljYWxSb3d9KTtcblxuICAgICAgICByZXR1cm4gaXZlYyR7c2hhcGUubGVuZ3RofSgke2Nvb3Jkc30pO1xuICAgICAgfVxuICAgIGA7XG4gICAgcmV0dXJuIG5ldyBHbHNsTGliUm91dGluZShzb3VyY2UpO1xuICB9XG5cbiAgLyoqXG4gICAqIFVucGFja2VkIDFEIG91dHB1dCBjb29yZGluYXRlcy5cbiAgICovXG4gIHByb3RlY3RlZCBnZXRPdXRwdXRVbnBhY2tlZDFEQ29vcmRzKHNoYXBlOiBbbnVtYmVyXSwgdGV4U2hhcGU6IFtudW1iZXIsIG51bWJlcl0pOiBHbHNsTGliUm91dGluZSB7XG4gICAgY29uc3Qgc291cmNlID0gYFxuICAgICAgICBpbnQgZ2V0T3V0cHV0Q29vcmRzKCkge1xuICAgICAgICAgIGl2ZWMyIHJlc1RleFJDID0gaXZlYzIoVGV4Q29vcmRzLnh5ICpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmVjMigke3RleFNoYXBlWzBdfSwgJHt0ZXhTaGFwZVsxXX0pKTtcbiAgICAgICAgICByZXR1cm4gcmVzVGV4UkMueSAqICR7dGV4U2hhcGVbMF19ICsgcmVzVGV4UkMueDtcbiAgICAgICAgfVxuICAgICAgYDtcbiAgICByZXR1cm4gbmV3IEdsc2xMaWJSb3V0aW5lKHNvdXJjZSk7XG4gIH1cblxuICAvKipcbiAgICogVW5wYWNrZWQgMkQgb3V0cHV0IGNvb3JkaW5hdGVzLlxuICAgKi9cbiAgcHJvdGVjdGVkIGdldE91dHB1dFVucGFja2VkMkRDb29yZHMoc2hhcGU6IFtudW1iZXIsIG51bWJlcl0sIHRleFNoYXBlOiBbbnVtYmVyLCBudW1iZXJdKTogR2xzbExpYlJvdXRpbmUge1xuICAgIGNvbnN0IHNvdXJjZSA9IGBcbiAgICAgICAgaXZlYzIgZ2V0T3V0cHV0Q29vcmRzKCkge1xuICAgICAgICAgIGl2ZWMyIHJlc1RleFJDID0gaXZlYzIoVGV4Q29vcmRzLnh5ICpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmVjMigke3RleFNoYXBlWzBdfSwgJHt0ZXhTaGFwZVsxXX0pKTtcbiAgICAgICAgICBpbnQgaW5kZXggPSByZXNUZXhSQy55ICogJHt0ZXhTaGFwZVswXX0gKyByZXNUZXhSQy54O1xuICAgICAgICAgIGludCByID0gaW5kZXggLyAke3NoYXBlWzFdfTtcbiAgICAgICAgICBpbnQgYyA9IGluZGV4IC0gciAqICR7c2hhcGVbMV19O1xuICAgICAgICAgIHJldHVybiBpdmVjMihyLCBjKTtcbiAgICAgICAgfVxuICAgICAgYDtcbiAgICByZXR1cm4gbmV3IEdsc2xMaWJSb3V0aW5lKHNvdXJjZSk7XG4gIH1cblxuICAvKipcbiAgICogVW5wYWNrZWQgM0Qgb3V0cHV0IGNvb3JkaW5hdGVzLlxuICAgKi9cbiAgcHJvdGVjdGVkIGdldE91dHB1dFVucGFja2VkM0RDb29yZHMoc2hhcGU6IFtudW1iZXIsIG51bWJlciwgbnVtYmVyXSwgdGV4U2hhcGU6IFtudW1iZXIsIG51bWJlcl0pOiBHbHNsTGliUm91dGluZSB7XG4gICAgbGV0IHNvdXJjZSA9ICcnO1xuICAgIGNvbnN0IHJhbmsgPSBzaGFwZS5sZW5ndGg7XG5cbiAgICBsZXQgc3RyaWRlcyA9IG51bGw7XG4gICAgaWYgKHJhbmsgPCAyKSB7XG4gICAgICBzdHJpZGVzID0gW107XG4gICAgfVxuXG4gICAgc3RyaWRlcyA9IG5ldyBBcnJheShyYW5rIC0gMSk7XG4gICAgc3RyaWRlc1tyYW5rIC0gMl0gPSBzaGFwZVtyYW5rIC0gMV07XG4gICAgZm9yIChsZXQgaSA9IHJhbmsgLSAzOyBpID49IDA7IC0taSkge1xuICAgICAgc3RyaWRlc1tpXSA9IHN0cmlkZXNbaSArIDFdICogc2hhcGVbaSArIDFdO1xuICAgIH1cbiAgICBjb25zdCBjb29yZHNUb0NvbXB1dGUgPSBbJ3InLCAnYycsICdkJ107XG4gICAgY29uc3QgY29vcmRzRnJvbUluZGV4U25pcHBldCA9XG4gICAgICAgIHN0cmlkZXNcbiAgICAgICAgICAgIC5tYXAoKHN0cmlkZSwgaSkgPT4ge1xuICAgICAgICAgICAgICBjb25zdCBsaW5lMSA9IGBpbnQgJHtjb29yZHNUb0NvbXB1dGVbaV19ID0gaW5kZXggLyAke3N0cmlkZX1gO1xuICAgICAgICAgICAgICBjb25zdCBsaW5lMiA9IGkgPT09IHN0cmlkZXMubGVuZ3RoIC0gMSA/XG4gICAgICAgICAgICAgICAgICBgaW50ICR7Y29vcmRzVG9Db21wdXRlW2kgKyAxXX0gPSBpbmRleCAtICR7Y29vcmRzVG9Db21wdXRlW2ldfSAqICR7c3RyaWRlfWAgOlxuICAgICAgICAgICAgICAgICAgYGluZGV4IC09ICR7Y29vcmRzVG9Db21wdXRlW2ldfSAqICR7c3RyaWRlfWA7XG4gICAgICAgICAgICAgIHJldHVybiBgJHtsaW5lMX07ICR7bGluZTJ9O2A7XG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgLmpvaW4oJycpO1xuXG4gICAgc291cmNlID0gYFxuICAgICAgICBpdmVjMyBnZXRPdXRwdXRDb29yZHMoKSB7XG4gICAgICAgICAgaXZlYzIgcmVzVGV4UkMgPSBpdmVjMihUZXhDb29yZHMueHkgKlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2ZWMyKCR7dGV4U2hhcGVbMF19LCAke3RleFNoYXBlWzFdfSkpO1xuICAgICAgICAgIGludCBpbmRleCA9IHJlc1RleFJDLnkgKiAke3RleFNoYXBlWzBdfSArIHJlc1RleFJDLng7XG4gICAgICAgICAgJHtjb29yZHNGcm9tSW5kZXhTbmlwcGV0fVxuICAgICAgICAgIHJldHVybiBpdmVjMyhyLCBjLCBkKTtcbiAgICAgICAgfVxuICAgICAgYDtcbiAgICByZXR1cm4gbmV3IEdsc2xMaWJSb3V0aW5lKHNvdXJjZSk7XG4gIH1cblxuICAvKipcbiAgICogVW5wYWNrZWQgNEQgb3V0cHV0IGNvb3JkaW5hdGVzLlxuICAgKi9cbiAgcHJvdGVjdGVkIGdldE91dHB1dFVucGFja2VkNERDb29yZHMoc2hhcGU6IFtudW1iZXIsIG51bWJlciwgbnVtYmVyLCBudW1iZXJdLCB0ZXhTaGFwZTogW251bWJlciwgbnVtYmVyXSk6XG4gICAgICBHbHNsTGliUm91dGluZSB7XG4gICAgbGV0IHNvdXJjZSA9ICcnO1xuICAgIGNvbnN0IHJhbmsgPSBzaGFwZS5sZW5ndGg7XG5cbiAgICBsZXQgc3RyaWRlcyA9IG51bGw7XG4gICAgaWYgKHJhbmsgPCAyKSB7XG4gICAgICBzdHJpZGVzID0gW107XG4gICAgfVxuXG4gICAgc3RyaWRlcyA9IG5ldyBBcnJheShyYW5rIC0gMSk7XG4gICAgc3RyaWRlc1tyYW5rIC0gMl0gPSBzaGFwZVtyYW5rIC0gMV07XG4gICAgZm9yIChsZXQgaSA9IHJhbmsgLSAzOyBpID49IDA7IC0taSkge1xuICAgICAgc3RyaWRlc1tpXSA9IHN0cmlkZXNbaSArIDFdICogc2hhcGVbaSArIDFdO1xuICAgIH1cbiAgICBjb25zdCBjb29yZHNUb0NvbXB1dGUgPSBbJ3InLCAnYycsICdkJywgJ2QyJ107XG4gICAgY29uc3QgY29vcmRzRnJvbUluZGV4U25pcHBldCA9XG4gICAgICAgIHN0cmlkZXNcbiAgICAgICAgICAgIC5tYXAoKHN0cmlkZSwgaSkgPT4ge1xuICAgICAgICAgICAgICBjb25zdCBsaW5lMSA9IGBpbnQgJHtjb29yZHNUb0NvbXB1dGVbaV19ID0gaW5kZXggLyAke3N0cmlkZX1gO1xuICAgICAgICAgICAgICBjb25zdCBsaW5lMiA9IGkgPT09IHN0cmlkZXMubGVuZ3RoIC0gMSA/XG4gICAgICAgICAgICAgICAgICBgaW50ICR7Y29vcmRzVG9Db21wdXRlW2kgKyAxXX0gPSBpbmRleCAtICR7Y29vcmRzVG9Db21wdXRlW2ldfSAqICR7c3RyaWRlfWAgOlxuICAgICAgICAgICAgICAgICAgYGluZGV4IC09ICR7Y29vcmRzVG9Db21wdXRlW2ldfSAqICR7c3RyaWRlfWA7XG4gICAgICAgICAgICAgIHJldHVybiBgJHtsaW5lMX07ICR7bGluZTJ9O2A7XG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgLmpvaW4oJycpO1xuXG4gICAgc291cmNlID0gYFxuICAgICAgaXZlYzQgZ2V0T3V0cHV0Q29vcmRzKCkge1xuICAgICAgICAgIGl2ZWMyIHJlc1RleFJDID0gaXZlYzIoVGV4Q29vcmRzLnh5ICpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmVjMigke3RleFNoYXBlWzBdfSwgJHt0ZXhTaGFwZVsxXX0pKTtcbiAgICAgICAgICBpbnQgaW5kZXggPSByZXNUZXhSQy55ICogJHt0ZXhTaGFwZVswXX0gKyByZXNUZXhSQy54O1xuICAgICAgICAgICR7Y29vcmRzRnJvbUluZGV4U25pcHBldH1cbiAgICAgICAgICByZXR1cm4gaXZlYzQociwgYywgZCwgZDIpO1xuICAgICAgICB9XG4gICAgICBgO1xuICAgIHJldHVybiBuZXcgR2xzbExpYlJvdXRpbmUoc291cmNlKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBVbnBhY2tlZCA1RCBvdXRwdXQgY29vcmRpbmF0ZXMuXG4gICAqL1xuICBwcm90ZWN0ZWQgZ2V0T3V0cHV0VW5wYWNrZWQ1RENvb3JkcyhzaGFwZTogW251bWJlciwgbnVtYmVyLCBudW1iZXIsIG51bWJlciwgbnVtYmVyXSwgdGV4U2hhcGU6IFtudW1iZXIsIG51bWJlcl0pOlxuICAgICAgR2xzbExpYlJvdXRpbmUge1xuICAgIGxldCBzb3VyY2UgPSAnJztcbiAgICBjb25zdCByYW5rID0gc2hhcGUubGVuZ3RoO1xuXG4gICAgbGV0IHN0cmlkZXMgPSBudWxsO1xuICAgIGlmIChyYW5rIDwgMikge1xuICAgICAgc3RyaWRlcyA9IFtdO1xuICAgIH1cblxuICAgIHN0cmlkZXMgPSBuZXcgQXJyYXkocmFuayAtIDEpO1xuICAgIHN0cmlkZXNbcmFuayAtIDJdID0gc2hhcGVbcmFuayAtIDFdO1xuICAgIGZvciAobGV0IGkgPSByYW5rIC0gMzsgaSA+PSAwOyAtLWkpIHtcbiAgICAgIHN0cmlkZXNbaV0gPSBzdHJpZGVzW2kgKyAxXSAqIHNoYXBlW2kgKyAxXTtcbiAgICB9XG4gICAgY29uc3QgY29vcmRzVG9Db21wdXRlID0gWydyJywgJ2MnLCAnZCcsICdkMicsICdkMyddO1xuICAgIGNvbnN0IGNvb3Jkc0Zyb21JbmRleFNuaXBwZXQgPVxuICAgICAgICBzdHJpZGVzXG4gICAgICAgICAgICAubWFwKChzdHJpZGUsIGkpID0+IHtcbiAgICAgICAgICAgICAgY29uc3QgbGluZTEgPSBgaW50ICR7Y29vcmRzVG9Db21wdXRlW2ldfSA9IGluZGV4IC8gJHtzdHJpZGV9YDtcbiAgICAgICAgICAgICAgY29uc3QgbGluZTIgPSBpID09PSBzdHJpZGVzLmxlbmd0aCAtIDEgP1xuICAgICAgICAgICAgICAgICAgYGludCAke2Nvb3Jkc1RvQ29tcHV0ZVtpICsgMV19ID0gaW5kZXggLSAke2Nvb3Jkc1RvQ29tcHV0ZVtpXX0gKiAke3N0cmlkZX1gIDpcbiAgICAgICAgICAgICAgICAgIGBpbmRleCAtPSAke2Nvb3Jkc1RvQ29tcHV0ZVtpXX0gKiAke3N0cmlkZX1gO1xuICAgICAgICAgICAgICByZXR1cm4gYCR7bGluZTF9OyAke2xpbmUyfTtgO1xuICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIC5qb2luKCcnKTtcblxuICAgIHNvdXJjZSA9IGBcbiAgICAgIGl2ZWM1IGdldE91dHB1dENvb3JkcygpIHtcbiAgICAgICAgICBpdmVjMiByZXNUZXhSQyA9IGl2ZWMyKFRleENvb3Jkcy54eSAqXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZlYzIoJHt0ZXhTaGFwZVswXX0sICR7dGV4U2hhcGVbMV19KSk7XG4gICAgICAgICAgaW50IGluZGV4ID0gcmVzVGV4UkMueSAqICR7dGV4U2hhcGVbMF19ICsgcmVzVGV4UkMueDtcbiAgICAgICAgICAke2Nvb3Jkc0Zyb21JbmRleFNuaXBwZXR9XG4gICAgICAgICAgcmV0dXJuIGl2ZWM1KHIsIGMsIGQsIGQyLCBkMyk7XG4gICAgICAgIH1cbiAgICAgIGA7XG4gICAgcmV0dXJuIG5ldyBHbHNsTGliUm91dGluZShzb3VyY2UpO1xuICB9XG5cbiAgLyoqXG4gICAqIFVucGFja2VkIDZEIG91dHB1dCBjb29yZGluYXRlcy5cbiAgICovXG4gIHByb3RlY3RlZCBnZXRPdXRwdXRVbnBhY2tlZDZEQ29vcmRzKHNoYXBlOiBbbnVtYmVyLCBudW1iZXIsIG51bWJlciwgbnVtYmVyLCBudW1iZXIsIG51bWJlcl0sIHRleFNoYXBlOiBbXG4gICAgbnVtYmVyLCBudW1iZXJcbiAgXSk6IEdsc2xMaWJSb3V0aW5lIHtcbiAgICBsZXQgc291cmNlID0gJyc7XG4gICAgY29uc3QgcmFuayA9IHNoYXBlLmxlbmd0aDtcblxuICAgIGxldCBzdHJpZGVzID0gbnVsbDtcbiAgICBpZiAocmFuayA8IDIpIHtcbiAgICAgIHN0cmlkZXMgPSBbXTtcbiAgICB9XG5cbiAgICBzdHJpZGVzID0gbmV3IEFycmF5KHJhbmsgLSAxKTtcbiAgICBzdHJpZGVzW3JhbmsgLSAyXSA9IHNoYXBlW3JhbmsgLSAxXTtcbiAgICBmb3IgKGxldCBpID0gcmFuayAtIDM7IGkgPj0gMDsgLS1pKSB7XG4gICAgICBzdHJpZGVzW2ldID0gc3RyaWRlc1tpICsgMV0gKiBzaGFwZVtpICsgMV07XG4gICAgfVxuICAgIGNvbnN0IGNvb3Jkc1RvQ29tcHV0ZSA9IFsncicsICdjJywgJ2QnLCAnZDInLCAnZDMnLCAnZDQnXTtcbiAgICBjb25zdCBjb29yZHNGcm9tSW5kZXhTbmlwcGV0ID1cbiAgICAgICAgc3RyaWRlc1xuICAgICAgICAgICAgLm1hcCgoc3RyaWRlLCBpKSA9PiB7XG4gICAgICAgICAgICAgIGNvbnN0IGxpbmUxID0gYGludCAke2Nvb3Jkc1RvQ29tcHV0ZVtpXX0gPSBpbmRleCAvICR7c3RyaWRlfWA7XG4gICAgICAgICAgICAgIGNvbnN0IGxpbmUyID0gaSA9PT0gc3RyaWRlcy5sZW5ndGggLSAxID9cbiAgICAgICAgICAgICAgICAgIGBpbnQgJHtjb29yZHNUb0NvbXB1dGVbaSArIDFdfSA9IGluZGV4IC0gJHtjb29yZHNUb0NvbXB1dGVbaV19ICogJHtzdHJpZGV9YCA6XG4gICAgICAgICAgICAgICAgICBgaW5kZXggLT0gJHtjb29yZHNUb0NvbXB1dGVbaV19ICogJHtzdHJpZGV9YDtcbiAgICAgICAgICAgICAgcmV0dXJuIGAke2xpbmUxfTsgJHtsaW5lMn07YDtcbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAuam9pbignJyk7XG5cbiAgICBzb3VyY2UgPSBgXG4gICAgIGl2ZWM2IGdldE91dHB1dENvb3JkcygpIHtcbiAgICAgICAgIGl2ZWMyIHJlc1RleFJDID0gaXZlYzIoVGV4Q29vcmRzLnh5ICpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2ZWMyKCR7dGV4U2hhcGVbMF19LCAke3RleFNoYXBlWzFdfSkpO1xuICAgICAgICAgaW50IGluZGV4ID0gcmVzVGV4UkMueSAqICR7dGV4U2hhcGVbMF19ICsgcmVzVGV4UkMueDtcbiAgICAgICAgICR7Y29vcmRzRnJvbUluZGV4U25pcHBldH1cbiAgICAgICAgIHJldHVybiBpdmVjNihyLCBjLCBkLCBkMiwgZDMsIGQ0KTtcbiAgICAgICB9XG4gICAgIGA7XG4gICAgcmV0dXJuIG5ldyBHbHNsTGliUm91dGluZShzb3VyY2UpO1xuICB9XG5cbiAgLyoqXG4gICAqIEdlbmVyYXRlcyBjb2RlIGZvciBjb21tb24gVVYgY29vcmRzIGNvbXB1dGF0aW9uIHV0aWxpdHkgZnVuY3Rpb25zLlxuICAgKi9cbiAgcHJvdGVjdGVkIGdldENvbW1vblV0aWxGdW5jcygpOiB7W25hbWU6IHN0cmluZ106IEdsc2xMaWJSb3V0aW5lfSB7XG4gICAgY29uc3QgcmVzdWx0OiB7W25hbWU6IHN0cmluZ106IEdsc2xMaWJSb3V0aW5lfSA9IHt9O1xuICAgIGxldCBmdW5jTmFtZSA9ICd1dkZyb21GbGF0JztcbiAgICByZXN1bHRbZnVuY05hbWVdID0gbmV3IEdsc2xMaWJSb3V0aW5lKGBcbiAgICB2ZWMyIHV2RnJvbUZsYXQoaW50IHRleE51bVIsIGludCB0ZXhOdW1DLCBpbnQgaW5kZXgpIHtcbiAgICAgIGludCB0ZXhDID0gaW5kZXggLyB0ZXhOdW1SO1xuICAgICAgaW50IHRleFIgPSBpbmRleCAtIHRleEMgKiB0ZXhOdW1SO1xuICAgICAgLy8gVE9ETzogc3dhcCB0ZXhSLCB0ZXhDIG9yZGVyIGluIGZvbGxvd2luZyBmdW5jdGlvbiBzbyByb3cgaXMgY29ycmVzcG9uZGluZyB0byB1IGFuZCBjb2x1bW4gaXMgY29ycmVzcG9uZGluZyB0b1xuICAgICAgLy8gICAgICAgdi5cbiAgICAgIHJldHVybiAodmVjMih0ZXhSLCB0ZXhDKSArIGhhbGZDUikgLyB2ZWMyKHRleE51bVIsIHRleE51bUMpO1xuICAgIH1cbiAgICBgKTtcbiAgICBmdW5jTmFtZSA9ICdwYWNrZWRVVmZyb20xRCc7XG4gICAgcmVzdWx0W2Z1bmNOYW1lXSA9IG5ldyBHbHNsTGliUm91dGluZShgXG4gICAgICB2ZWMyIHBhY2tlZFVWZnJvbTFEKGludCB0ZXhOdW1SLCBpbnQgdGV4TnVtQywgaW50IGluZGV4KSB7XG4gICAgICAgIGludCB0ZXhlbEluZGV4ID0gaW5kZXggLyAyO1xuICAgICAgICBpbnQgdGV4UiA9IHRleGVsSW5kZXggLyB0ZXhOdW1DO1xuICAgICAgICBpbnQgdGV4QyA9IHRleGVsSW5kZXggLSB0ZXhSICogdGV4TnVtQztcbiAgICAgICAgcmV0dXJuICh2ZWMyKHRleEMsIHRleFIpICsgaGFsZkNSKSAvIHZlYzIodGV4TnVtQywgdGV4TnVtUik7XG4gICAgICB9XG4gICAgICBgKTtcbiAgICBmdW5jTmFtZSA9ICdwYWNrZWRVVmZyb20yRCc7XG4gICAgcmVzdWx0W2Z1bmNOYW1lXSA9IG5ldyBHbHNsTGliUm91dGluZShgXG4gICAgICB2ZWMyIHBhY2tlZFVWZnJvbTJEKGludCB0ZXhOdW1SLCBpbnQgdGV4TnVtQywgaW50IHRleGVsc0luTG9naWNhbFJvdywgaW50IHJvdywgaW50IGNvbCkge1xuICAgICAgICBpbnQgdGV4ZWxJbmRleCA9IChyb3cgLyAyKSAqIHRleGVsc0luTG9naWNhbFJvdyArIChjb2wgLyAyKTtcbiAgICAgICAgaW50IHRleFIgPSB0ZXhlbEluZGV4IC8gdGV4TnVtQztcbiAgICAgICAgaW50IHRleEMgPSB0ZXhlbEluZGV4IC0gdGV4UiAqIHRleE51bUM7XG4gICAgICAgIHJldHVybiAodmVjMih0ZXhDLCB0ZXhSKSArIGhhbGZDUikgLyB2ZWMyKHRleE51bUMsIHRleE51bVIpO1xuICAgICAgfVxuICAgICAgYCk7XG4gICAgZnVuY05hbWUgPSAncGFja2VkVVZmcm9tM0QnO1xuICAgIHJlc3VsdFtmdW5jTmFtZV0gPSBuZXcgR2xzbExpYlJvdXRpbmUoYFxuICAgICAgdmVjMiBwYWNrZWRVVmZyb20zRChpbnQgdGV4TnVtUiwgaW50IHRleE51bUMsXG4gICAgICAgICAgaW50IHRleGVsc0luQmF0Y2gsIGludCB0ZXhlbHNJbkxvZ2ljYWxSb3csIGludCBiLFxuICAgICAgICAgIGludCByb3csIGludCBjb2wpIHtcbiAgICAgICAgaW50IGluZGV4ID0gYiAqIHRleGVsc0luQmF0Y2ggKyAocm93IC8gMikgKiB0ZXhlbHNJbkxvZ2ljYWxSb3cgKyAoY29sIC8gMik7XG4gICAgICAgIGludCB0ZXhSID0gaW5kZXggLyB0ZXhOdW1DO1xuICAgICAgICBpbnQgdGV4QyA9IGluZGV4IC0gdGV4UiAqIHRleE51bUM7XG4gICAgICAgIHJldHVybiAodmVjMih0ZXhDLCB0ZXhSKSArIGhhbGZDUikgLyB2ZWMyKHRleE51bUMsIHRleE51bVIpO1xuICAgICAgfVxuICAgICAgYCk7XG4gICAgZnVuY05hbWUgPSAnc2FtcGxlVGV4dHVyZSc7XG4gICAgY29uc3QgZ2xzbCA9IGdldEdsc2wodGhpcy5jb250ZXh0LmdsQ29udGV4dC52ZXJzaW9uKTtcbiAgICByZXN1bHRbZnVuY05hbWVdID0gbmV3IEdsc2xMaWJSb3V0aW5lKGBcbiAgICAgICAgZmxvYXQgc2FtcGxlVGV4dHVyZShzYW1wbGVyMkQgdGV4dHVyZVNhbXBsZXIsIHZlYzIgdXYpIHtcbiAgICAgICAgICAgIHJldHVybiAke2dsc2wudGV4dHVyZTJEfSh0ZXh0dXJlU2FtcGxlciwgdXYpLnI7XG4gICAgICAgIH1gKTtcbiAgICByZXR1cm4gcmVzdWx0O1xuICB9XG5cbiAgLyoqXG4gICAqIENvbnN0cnVjdGluZyBzbmlwcGV0cyBmb3IgaW5wdXRzXG4gICAqL1xuICBwcm90ZWN0ZWQgZ2V0SW5wdXRzU2FtcGxpbmdTbmlwcGV0cygpOiB7W25hbWU6IHN0cmluZ106IEdsc2xMaWJSb3V0aW5lfSB7XG4gICAgY29uc3QgcmVzdWx0OiB7W25hbWU6IHN0cmluZ106IEdsc2xMaWJSb3V0aW5lfSA9IHt9O1xuICAgIGNvbnN0IG91dHB1dExheW91dCA9IHRoaXMuY29udGV4dC5vdXRwdXRUZXh0dXJlTGF5b3V0O1xuICAgIHRoaXMuY29udGV4dC5wcm9ncmFtSW5mby5pbnB1dE5hbWVzLmZvckVhY2goKHNhbXBsZXJOYW1lLCBpKSA9PiB7XG4gICAgICBjb25zdCBpbnB1dExheW91dCA9IHRoaXMuY29udGV4dC5pbnB1dFRleHR1cmVMYXlvdXRzW2ldO1xuICAgICAgY29uc3QgZnVuY05hbWUgPSBnZW5lcmF0ZVNoYWRlckZ1bmNOYW1lRnJvbUlucHV0U2FtcGxlck5hbWUoc2FtcGxlck5hbWUpO1xuICAgICAgaWYgKGlucHV0TGF5b3V0LmlzUGFja2VkKSB7XG4gICAgICAgIHJlc3VsdFtmdW5jTmFtZV0gPSB0aGlzLmdldFBhY2tlZFNhbXBsZXJGcm9tSW5wdXQoZnVuY05hbWUsIHNhbXBsZXJOYW1lLCBpbnB1dExheW91dCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXN1bHRbZnVuY05hbWVdID0gdGhpcy5nZXRVbnBhY2tlZFNhbXBsZXJGcm9tSW5wdXQoZnVuY05hbWUsIHNhbXBsZXJOYW1lLCBpbnB1dExheW91dCk7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IG91dENvb3JkRnVuY05hbWUgPSBnZW5lcmF0ZVNoYWRlckZ1bmNOYW1lRnJvbUlucHV0U2FtcGxlck5hbWVBdE91dENvb3JkcyhzYW1wbGVyTmFtZSk7XG4gICAgICBpZiAoaW5wdXRMYXlvdXQudW5wYWNrZWRTaGFwZS5sZW5ndGggPD0gb3V0cHV0TGF5b3V0LnVucGFja2VkU2hhcGUubGVuZ3RoKSB7XG4gICAgICAgIGlmIChpbnB1dExheW91dC5pc1BhY2tlZCkge1xuICAgICAgICAgIHJlc3VsdFtvdXRDb29yZEZ1bmNOYW1lXSA9XG4gICAgICAgICAgICAgIHRoaXMuZ2V0UGFja2VkU2FtcGxlckF0T3V0cHV0Q29vcmRzKG91dENvb3JkRnVuY05hbWUsIGlucHV0TGF5b3V0LCBvdXRwdXRMYXlvdXQsIHNhbXBsZXJOYW1lKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICByZXN1bHRbb3V0Q29vcmRGdW5jTmFtZV0gPVxuICAgICAgICAgICAgICB0aGlzLmdldFVucGFja2VkU2FtcGxlckF0T3V0cHV0Q29vcmRzKG91dENvb3JkRnVuY05hbWUsIGlucHV0TGF5b3V0LCBvdXRwdXRMYXlvdXQsIHNhbXBsZXJOYW1lKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0pO1xuXG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfVxuXG4gIC8qKlxuICAgKiBDb25zdHJ1Y3Rpbmcgc25pcHBldHMgZm9yIG91dHB1dCBjb29yZGluYXRlcyBvZiBzYW1wbGVyc1xuICAgKi9cbiAgcHJvdGVjdGVkIGdldFBhY2tlZFNhbXBsZXJBdE91dHB1dENvb3JkcyhcbiAgICAgIGZ1bmNOYW1lOiBzdHJpbmcsIGlucHV0TGF5b3V0OiBUZXh0dXJlTGF5b3V0LCBvdXRwdXRMYXlvdXQ6IFRleHR1cmVMYXlvdXQsIG5hbWU6IHN0cmluZyk6IEdsc2xMaWJSb3V0aW5lIHtcbiAgICBjb25zdCBpblNoYXBlID0gaW5wdXRMYXlvdXQudW5wYWNrZWRTaGFwZTtcbiAgICBjb25zdCBvdXRTaGFwZSA9IG91dHB1dExheW91dC51bnBhY2tlZFNoYXBlO1xuICAgIGNvbnN0IHRleE5hbWUgPSBuYW1lO1xuICAgIGNvbnN0IHRleEZ1bmNTbmlwcGV0ID0gZ2VuZXJhdGVTaGFkZXJGdW5jTmFtZUZyb21JbnB1dFNhbXBsZXJOYW1lKHRleE5hbWUpO1xuXG4gICAgY29uc3QgaW5SYW5rID0gaW5TaGFwZS5sZW5ndGg7XG4gICAgY29uc3Qgb3V0UmFuayA9IG91dFNoYXBlLmxlbmd0aDtcblxuICAgIGNvbnN0IGJyb2FkY2FzdERpbXMgPSBCcm9hZGNhc3RVdGlsLmdldEJyb2FkY2FzdERpbXMoaW5TaGFwZSwgb3V0U2hhcGUpO1xuXG4gICAgY29uc3QgdHlwZSA9IGdldENvb3Jkc0RhdGFUeXBlKG91dFJhbmspO1xuICAgIGNvbnN0IHJhbmtEaWZmID0gb3V0UmFuayAtIGluUmFuaztcbiAgICBsZXQgY29vcmRzU25pcHBldDogc3RyaW5nO1xuICAgIGNvbnN0IGZpZWxkcyA9IGdldEdsQ2hhbm5lbHMoKTtcblxuICAgIGlmIChpblJhbmsgPT09IDApIHtcbiAgICAgIGNvb3Jkc1NuaXBwZXQgPSAnJztcbiAgICB9IGVsc2UgaWYgKG91dFJhbmsgPCAyICYmIGJyb2FkY2FzdERpbXMubGVuZ3RoID49IDEpIHtcbiAgICAgIGNvb3Jkc1NuaXBwZXQgPSAnY29vcmRzID0gMDsnO1xuICAgIH0gZWxzZSB7XG4gICAgICBjb29yZHNTbmlwcGV0ID0gYnJvYWRjYXN0RGltcy5tYXAoZCA9PiBgY29vcmRzLiR7ZmllbGRzW2QgKyByYW5rRGlmZl19ID0gMDtgKS5qb2luKCdcXG4nKTtcbiAgICB9XG4gICAgbGV0IHVucGFja2VkQ29vcmRzU25pcHBldCA9ICcnO1xuICAgIGlmIChvdXRSYW5rIDwgMiAmJiBpblJhbmsgPiAwKSB7XG4gICAgICB1bnBhY2tlZENvb3Jkc1NuaXBwZXQgPSAnY29vcmRzJztcbiAgICB9IGVsc2Uge1xuICAgICAgdW5wYWNrZWRDb29yZHNTbmlwcGV0ID0gaW5TaGFwZS5tYXAoKHMsIGkpID0+IGBjb29yZHMuJHtmaWVsZHNbaSArIHJhbmtEaWZmXX1gKS5qb2luKCcsICcpO1xuICAgIH1cblxuICAgIGxldCBvdXRwdXQgPSAncmV0dXJuIG91dHB1dFZhbHVlOyc7XG4gICAgY29uc3QgaW5TaXplID0gU2hhcGVVdGlsLnNpemUoaW5TaGFwZSk7XG4gICAgY29uc3QgaXNJbnB1dFNjYWxhciA9IGluU2l6ZSA9PT0gMTtcbiAgICBjb25zdCBvdXRTaXplID0gU2hhcGVVdGlsLnNpemUob3V0U2hhcGUpO1xuICAgIGNvbnN0IGlzT3V0cHV0U2NhbGFyID0gb3V0U2l6ZSA9PT0gMTtcblxuICAgIGlmIChpblJhbmsgPT09IDEgJiYgIWlzSW5wdXRTY2FsYXIgJiYgIWlzT3V0cHV0U2NhbGFyKSB7XG4gICAgICBvdXRwdXQgPSBgXG4gICAgICAgIHJldHVybiB2ZWM0KG91dHB1dFZhbHVlLnh5LCBvdXRwdXRWYWx1ZS54eSk7XG4gICAgICBgO1xuICAgIH0gZWxzZSBpZiAoaXNJbnB1dFNjYWxhciAmJiAhaXNPdXRwdXRTY2FsYXIpIHtcbiAgICAgIGlmIChvdXRSYW5rID09PSAxKSB7XG4gICAgICAgIG91dHB1dCA9IGBcbiAgICAgICAgICByZXR1cm4gdmVjNChvdXRwdXRWYWx1ZS54LCBvdXRwdXRWYWx1ZS54LCAwLiwgMC4pO1xuICAgICAgICBgO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgb3V0cHV0ID0gYFxuICAgICAgICAgIHJldHVybiB2ZWM0KG91dHB1dFZhbHVlLngpO1xuICAgICAgICBgO1xuICAgICAgfVxuICAgIH0gZWxzZSBpZiAoYnJvYWRjYXN0RGltcy5sZW5ndGgpIHtcbiAgICAgIGNvbnN0IHJvd3MgPSBpblJhbmsgLSAyO1xuICAgICAgY29uc3QgY29scyA9IGluUmFuayAtIDE7XG5cbiAgICAgIGlmIChicm9hZGNhc3REaW1zLmluZGV4T2Yocm93cykgPiAtMSAmJiBicm9hZGNhc3REaW1zLmluZGV4T2YoY29scykgPiAtMSkge1xuICAgICAgICBvdXRwdXQgPSAncmV0dXJuIHZlYzQob3V0cHV0VmFsdWUueCk7JztcbiAgICAgIH0gZWxzZSBpZiAoYnJvYWRjYXN0RGltcy5pbmRleE9mKHJvd3MpID4gLTEpIHtcbiAgICAgICAgb3V0cHV0ID0gJ3JldHVybiB2ZWM0KG91dHB1dFZhbHVlLngsIG91dHB1dFZhbHVlLnksICcgK1xuICAgICAgICAgICAgJ291dHB1dFZhbHVlLngsIG91dHB1dFZhbHVlLnkpOyc7XG4gICAgICB9IGVsc2UgaWYgKGJyb2FkY2FzdERpbXMuaW5kZXhPZihjb2xzKSA+IC0xKSB7XG4gICAgICAgIG91dHB1dCA9ICdyZXR1cm4gdmVjNChvdXRwdXRWYWx1ZS54eCwgb3V0cHV0VmFsdWUuenopOyc7XG4gICAgICB9XG4gICAgfVxuXG4gICAgY29uc3Qgc3dhcExhc3REaW1zU25pcHBldCA9IGBcbiAgICAgICAgaW50IGxhc3REaW0gPSBjb29yZHMuJHtmaWVsZHNbb3V0UmFuayAtIDFdfTtcbiAgICAgICAgY29vcmRzLiR7ZmllbGRzW291dFJhbmsgLSAxXX0gPSBjb29yZHMuJHtmaWVsZHNbb3V0UmFuayAtIDJdfTtcbiAgICAgICAgY29vcmRzLiR7ZmllbGRzW291dFJhbmsgLSAyXX0gPSBsYXN0RGltO1xuICAgICAgYDtcbiAgICBjb25zdCBzb3VyY2UgPSBgXG4gICAgICB2ZWM0ICR7ZnVuY05hbWV9KCkge1xuICAgICAgICAke3R5cGV9IGNvb3JkcyA9IGdldE91dHB1dENvb3JkcygpO1xuICAgICAgICAke3N3YXBMYXN0RGltc1NuaXBwZXR9XG4gICAgICAgICR7Y29vcmRzU25pcHBldH1cbiAgICAgICAgdmVjNCBvdXRwdXRWYWx1ZSA9ICR7dGV4RnVuY1NuaXBwZXR9KCR7dW5wYWNrZWRDb29yZHNTbmlwcGV0fSk7XG4gICAgICAgICR7b3V0cHV0fVxuICAgICAgfVxuICAgIGA7XG4gICAgcmV0dXJuIG5ldyBHbHNsTGliUm91dGluZShzb3VyY2UsIFsnY29vcmRpbmF0ZXMuZ2V0T3V0cHV0Q29vcmRzJ10pO1xuICB9XG5cbiAgLyoqXG4gICAqIENvbnN0cnVjdGluZyBzbmlwcGV0cyBmb3IgdW5wYWNrZWQgb3V0cHV0IGNvb3JkaW5hdGVzIG9mIHNhbXBsZXJzXG4gICAqL1xuICBwcm90ZWN0ZWQgZ2V0VW5wYWNrZWRTYW1wbGVyQXRPdXRwdXRDb29yZHMoXG4gICAgICBmdW5jTmFtZTogc3RyaW5nLCBpbnB1dExheW91dDogVGV4dHVyZUxheW91dCwgb3V0cHV0TGF5b3V0OiBUZXh0dXJlTGF5b3V0LCBuYW1lOiBzdHJpbmcpOiBHbHNsTGliUm91dGluZSB7XG4gICAgY29uc3Qgb3V0VGV4U2hhcGUgPSBbb3V0cHV0TGF5b3V0LndpZHRoLCBvdXRwdXRMYXlvdXQuaGVpZ2h0XTtcbiAgICBjb25zdCBpblRleFNoYXBlID0gW2lucHV0TGF5b3V0LndpZHRoLCBpbnB1dExheW91dC5oZWlnaHRdO1xuICAgIGNvbnN0IGluUmFuayA9IGlucHV0TGF5b3V0LnVucGFja2VkU2hhcGUubGVuZ3RoO1xuICAgIGNvbnN0IG91dFJhbmsgPSBvdXRwdXRMYXlvdXQudW5wYWNrZWRTaGFwZS5sZW5ndGg7XG4gICAgY29uc3QgaW5TaGFwZSA9IGlucHV0TGF5b3V0LnVucGFja2VkU2hhcGU7XG4gICAgY29uc3Qgb3V0U2hhcGUgPSBvdXRwdXRMYXlvdXQudW5wYWNrZWRTaGFwZTtcbiAgICBjb25zdCB0ZXhGdW5jU25pcHBldCA9IGdlbmVyYXRlU2hhZGVyRnVuY05hbWVGcm9tSW5wdXRTYW1wbGVyTmFtZShuYW1lKTtcblxuICAgIGlmIChpblJhbmsgPT09IG91dFJhbmsgJiYgQXJyYXlVdGlsLmFycmF5c0VxdWFsKGluVGV4U2hhcGUsIG91dFRleFNoYXBlKSkge1xuICAgICAgY29uc3Qgc291cmNlID0gYFxuICAgICAgICAgIGZsb2F0ICR7ZnVuY05hbWV9KCkge1xuICAgICAgICAgICAgcmV0dXJuIHNhbXBsZVRleHR1cmUoJHtuYW1lfSwgVGV4Q29vcmRzKTtcbiAgICAgICAgICB9XG4gICAgICAgIGA7XG4gICAgICByZXR1cm4gbmV3IEdsc2xMaWJSb3V0aW5lKHNvdXJjZSwgWydjb29yZGluYXRlcy5zYW1wbGVUZXh0dXJlJ10pO1xuICAgIH1cblxuICAgIGNvbnN0IHR5cGUgPSBnZXRDb29yZHNEYXRhVHlwZShvdXRSYW5rKTtcbiAgICBjb25zdCBicm9hZGNhc3REaW1zID0gQnJvYWRjYXN0VXRpbC5nZXRCcm9hZGNhc3REaW1zKGluU2hhcGUsIG91dFNoYXBlKTtcbiAgICBjb25zdCByYW5rRGlmZiA9IG91dFJhbmsgLSBpblJhbms7XG4gICAgbGV0IGNvb3Jkc1NuaXBwZXQ6IHN0cmluZztcbiAgICBjb25zdCBmaWVsZHMgPSBnZXRHbENoYW5uZWxzKCk7XG5cbiAgICBpZiAoaW5SYW5rID09PSAwKSB7XG4gICAgICBjb29yZHNTbmlwcGV0ID0gJyc7XG4gICAgfSBlbHNlIGlmIChvdXRSYW5rIDwgMiAmJiBicm9hZGNhc3REaW1zLmxlbmd0aCA+PSAxKSB7XG4gICAgICBjb29yZHNTbmlwcGV0ID0gJ2Nvb3JkcyA9IDA7JztcbiAgICB9IGVsc2Uge1xuICAgICAgY29vcmRzU25pcHBldCA9IGJyb2FkY2FzdERpbXMubWFwKGQgPT4gYGNvb3Jkcy4ke2ZpZWxkc1tkICsgcmFua0RpZmZdfSA9IDA7YCkuam9pbignXFxuJyk7XG4gICAgfVxuICAgIGxldCB1bnBhY2tlZENvb3Jkc1NuaXBwZXQgPSAnJztcbiAgICBpZiAob3V0UmFuayA8IDIgJiYgaW5SYW5rID4gMCkge1xuICAgICAgdW5wYWNrZWRDb29yZHNTbmlwcGV0ID0gJ2Nvb3Jkcyc7XG4gICAgfSBlbHNlIHtcbiAgICAgIHVucGFja2VkQ29vcmRzU25pcHBldCA9IGlucHV0TGF5b3V0LnVucGFja2VkU2hhcGUubWFwKChzLCBpKSA9PiBgY29vcmRzLiR7ZmllbGRzW2kgKyByYW5rRGlmZl19YCkuam9pbignLCAnKTtcbiAgICB9XG4gICAgY29uc3Qgc291cmNlID0gYFxuICAgICAgICBmbG9hdCAke2Z1bmNOYW1lfSgpIHtcbiAgICAgICAgICAke3R5cGV9IGNvb3JkcyA9IGdldE91dHB1dENvb3JkcygpO1xuICAgICAgICAgICR7Y29vcmRzU25pcHBldH1cbiAgICAgICAgICByZXR1cm4gJHt0ZXhGdW5jU25pcHBldH0oJHt1bnBhY2tlZENvb3Jkc1NuaXBwZXR9KTtcbiAgICAgICAgfVxuICAgICAgYDtcbiAgICByZXR1cm4gbmV3IEdsc2xMaWJSb3V0aW5lKHNvdXJjZSwgWydjb29yZGluYXRlcy5nZXRPdXRwdXRDb29yZHMnXSk7XG4gIH1cblxuICAvKipcbiAgICogQ29uc3RydWN0aW5nIHNuaXBwZXRzIGZvciBwYWNrZWQgb3BlcmF0aW9ucy5cbiAgICovXG4gIHByb3RlY3RlZCBnZXRQYWNrZWRTYW1wbGVyRnJvbUlucHV0KGZ1bmNOYW1lOiBzdHJpbmcsIG5hbWU6IHN0cmluZywgaW5wdXRMYXlvdXQ6IFRleHR1cmVMYXlvdXQpOiBHbHNsTGliUm91dGluZSB7XG4gICAgc3dpdGNoIChpbnB1dExheW91dC51bnBhY2tlZFNoYXBlLmxlbmd0aCkge1xuICAgICAgY2FzZSAwOlxuICAgICAgICByZXR1cm4gdGhpcy5nZXRQYWNrZWRTYW1wbGVyU2NhbGFyKGZ1bmNOYW1lLCBuYW1lKTtcbiAgICAgIGNhc2UgMTpcbiAgICAgICAgcmV0dXJuIHRoaXMuZ2V0UGFja2VkU2FtcGxlcjFEKGZ1bmNOYW1lLCBuYW1lLCBpbnB1dExheW91dCk7XG4gICAgICBjYXNlIDI6XG4gICAgICAgIHJldHVybiB0aGlzLmdldFBhY2tlZFNhbXBsZXIyRChmdW5jTmFtZSwgbmFtZSwgaW5wdXRMYXlvdXQpO1xuICAgICAgY2FzZSAzOlxuICAgICAgICByZXR1cm4gdGhpcy5nZXRQYWNrZWRTYW1wbGVyM0QoZnVuY05hbWUsIG5hbWUsIGlucHV0TGF5b3V0KTtcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHJldHVybiB0aGlzLmdldFBhY2tlZFNhbXBsZXJORChmdW5jTmFtZSwgbmFtZSwgaW5wdXRMYXlvdXQpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBDb25zdHJ1Y3Rpbmcgc25pcHBldHMgZm9yIHVucGFja2VkIG9wZXJhdGlvbnMuXG4gICAqL1xuICBwcm90ZWN0ZWQgZ2V0VW5wYWNrZWRTYW1wbGVyRnJvbUlucHV0KGZ1bmNOYW1lOiBzdHJpbmcsIG5hbWU6IHN0cmluZywgaW5wdXRMYXlvdXQ6IFRleHR1cmVMYXlvdXQpOiBHbHNsTGliUm91dGluZSB7XG4gICAgY29uc3Qgc2hhcGUgPSBpbnB1dExheW91dC51bnBhY2tlZFNoYXBlO1xuICAgIHN3aXRjaCAoc2hhcGUubGVuZ3RoKSB7XG4gICAgICBjYXNlIDA6XG4gICAgICAgIHJldHVybiB0aGlzLmdldFVucGFja2VkU2FtcGxlclNjYWxhcihmdW5jTmFtZSwgbmFtZSwgaW5wdXRMYXlvdXQpO1xuICAgICAgY2FzZSAxOlxuICAgICAgICByZXR1cm4gdGhpcy5nZXRVbnBhY2tlZFNhbXBsZXIxRChmdW5jTmFtZSwgbmFtZSwgaW5wdXRMYXlvdXQpO1xuICAgICAgY2FzZSAyOlxuICAgICAgICByZXR1cm4gdGhpcy5nZXRVbnBhY2tlZFNhbXBsZXIyRChmdW5jTmFtZSwgbmFtZSwgaW5wdXRMYXlvdXQpO1xuICAgICAgY2FzZSAzOlxuICAgICAgICByZXR1cm4gdGhpcy5nZXRVbnBhY2tlZFNhbXBsZXIzRChmdW5jTmFtZSwgbmFtZSwgaW5wdXRMYXlvdXQpO1xuICAgICAgY2FzZSA0OlxuICAgICAgICByZXR1cm4gdGhpcy5nZXRVbnBhY2tlZFNhbXBsZXI0RChmdW5jTmFtZSwgbmFtZSwgaW5wdXRMYXlvdXQpO1xuICAgICAgY2FzZSA1OlxuICAgICAgICByZXR1cm4gdGhpcy5nZXRVbnBhY2tlZFNhbXBsZXI1RChmdW5jTmFtZSwgbmFtZSwgaW5wdXRMYXlvdXQpO1xuICAgICAgY2FzZSA2OlxuICAgICAgICByZXR1cm4gdGhpcy5nZXRVbnBhY2tlZFNhbXBsZXI2RChmdW5jTmFtZSwgbmFtZSwgaW5wdXRMYXlvdXQpO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgLy8gVE9ETyBzdXBwb3J0IG1vcmUgZGltZW5zaW9uYWxpdGllc1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYFVuc3VwcG9ydGVkIGRpbWVuc2lvbiAke3NoYXBlLmxlbmd0aH0tRGApO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBQYWNrZWQgc2NhbGFyIHNuaXBwZXQuXG4gICAqL1xuICBwcm90ZWN0ZWQgZ2V0UGFja2VkU2FtcGxlclNjYWxhcihmdW5jTmFtZTogc3RyaW5nLCBuYW1lOiBzdHJpbmcpOiBHbHNsTGliUm91dGluZSB7XG4gICAgY29uc3QgZ2xzbCA9IGdldEdsc2wodGhpcy5jb250ZXh0LmdsQ29udGV4dC52ZXJzaW9uKTtcbiAgICBjb25zdCBzb3VyY2UgPSBgXG4gICAgICAgICAgdmVjNCAke2Z1bmNOYW1lfSgpIHtcbiAgICAgICAgICAgIHJldHVybiAke2dsc2wudGV4dHVyZTJEfSgke25hbWV9LCBoYWxmQ1IpO1xuICAgICAgICAgIH1cbiAgICAgICAgYDtcbiAgICByZXR1cm4gbmV3IEdsc2xMaWJSb3V0aW5lKHNvdXJjZSk7XG4gIH1cblxuICAvKipcbiAgICogUGFja2VkIDFEIHNuaXBwZXQuXG4gICAqL1xuICBwcm90ZWN0ZWQgZ2V0UGFja2VkU2FtcGxlcjFEKGZ1bmNOYW1lOiBzdHJpbmcsIG5hbWU6IHN0cmluZywgaW5wdXRMYXlvdXQ6IFRleHR1cmVMYXlvdXQpOiBHbHNsTGliUm91dGluZSB7XG4gICAgY29uc3QgdGV4U2hhcGUgPSBbaW5wdXRMYXlvdXQud2lkdGgsIGlucHV0TGF5b3V0LmhlaWdodF07XG4gICAgY29uc3QgcGFja2VkVGV4U2hhcGUgPSBbdGV4U2hhcGVbMV0sIHRleFNoYXBlWzBdXTtcbiAgICBjb25zdCBnbHNsID0gZ2V0R2xzbCh0aGlzLmNvbnRleHQuZ2xDb250ZXh0LnZlcnNpb24pO1xuXG4gICAgY29uc3QgcGFja2VkU2FtcGxlciA9IGB2ZWM0ICR7ZnVuY05hbWV9KGludCBpbmRleCkge1xuICAgICAgdmVjMiB1diA9IHBhY2tlZFVWZnJvbTFEKFxuICAgICAgJHtwYWNrZWRUZXhTaGFwZVswXX0sICR7cGFja2VkVGV4U2hhcGVbMV19LCBpbmRleCk7XG4gICAgICByZXR1cm4gJHtnbHNsLnRleHR1cmUyRH0oJHtuYW1lfSwgdXYpO1xuICAgIH1gO1xuICAgIGNvbnN0IHNvdXJjZSA9IHBhY2tlZFNhbXBsZXI7XG4gICAgcmV0dXJuIG5ldyBHbHNsTGliUm91dGluZShzb3VyY2UsIFsnY29vcmRpbmF0ZXMucGFja2VkVVZmcm9tMUQnXSk7XG4gIH1cblxuICAvKipcbiAgICogUGFja2VkIDJEIHNuaXBwZXQuXG4gICAqL1xuICBwcm90ZWN0ZWQgZ2V0UGFja2VkU2FtcGxlcjJEKGZ1bmNOYW1lOiBzdHJpbmcsIG5hbWU6IHN0cmluZywgaW5wdXRMYXlvdXQ6IFRleHR1cmVMYXlvdXQpOiBHbHNsTGliUm91dGluZSB7XG4gICAgY29uc3Qgc2hhcGUgPSBpbnB1dExheW91dC51bnBhY2tlZFNoYXBlO1xuICAgIGNvbnN0IHRleFNoYXBlID0gW2lucHV0TGF5b3V0LndpZHRoLCBpbnB1dExheW91dC5oZWlnaHRdO1xuICAgIGNvbnN0IGdsc2wgPSBnZXRHbHNsKHRoaXMuY29udGV4dC5nbENvbnRleHQudmVyc2lvbik7XG4gICAgY29uc3QgdGV4TnVtUiA9IHRleFNoYXBlWzBdO1xuICAgIGNvbnN0IHRleE51bUMgPSB0ZXhTaGFwZVsxXTtcblxuICAgIGlmICh0ZXhTaGFwZSAhPSBudWxsICYmIEFycmF5VXRpbC5hcnJheXNFcXVhbChzaGFwZSwgdGV4U2hhcGUpKSB7XG4gICAgICBjb25zdCBwYWNrZWRTYW1wbGVyID0gYHZlYzQgJHtmdW5jTmFtZX0oaW50IHJvdywgaW50IGNvbCkge1xuICAgICAgICB2ZWMyIHV2ID0gKHZlYzIoY29sLCByb3cpICsgaGFsZkNSKSAvIHZlYzIoJHt0ZXhOdW1DfS4wLCAke3RleE51bVJ9LjApO1xuICAgICAgICByZXR1cm4gJHtnbHNsLnRleHR1cmUyRH0oJHtuYW1lfSwgdXYpO1xuICAgICAgfWA7XG5cbiAgICAgIHJldHVybiBuZXcgR2xzbExpYlJvdXRpbmUocGFja2VkU2FtcGxlcik7XG4gICAgfVxuICAgIGNvbnN0IHBhY2tlZFRleFNoYXBlID0gdGV4U2hhcGU7XG4gICAgY29uc3QgdmFsdWVzUGVyUm93ID0gTWF0aC5jZWlsKHNoYXBlWzFdIC8gMik7XG4gICAgY29uc3QgcGFja2VkU2FtcGxlciA9IGB2ZWM0ICR7ZnVuY05hbWV9KGludCByb3csIGludCBjb2wpIHtcbiAgICAgIHZlYzIgdXYgPSBwYWNrZWRVVmZyb20yRCgke3BhY2tlZFRleFNoYXBlWzFdfSwgJHtwYWNrZWRUZXhTaGFwZVswXX0sICR7dmFsdWVzUGVyUm93fSwgcm93LCBjb2wpO1xuICAgICAgcmV0dXJuICR7Z2xzbC50ZXh0dXJlMkR9KCR7bmFtZX0sIHV2KTtcbiAgICB9YDtcbiAgICBjb25zdCBzb3VyY2UgPSBwYWNrZWRTYW1wbGVyO1xuICAgIHJldHVybiBuZXcgR2xzbExpYlJvdXRpbmUoc291cmNlLCBbJ2Nvb3JkaW5hdGVzLnBhY2tlZFVWZnJvbTJEJ10pO1xuICB9XG5cbiAgLyoqXG4gICAqIFBhY2tlZCAzRCBzbmlwcGV0LlxuICAgKi9cbiAgcHJvdGVjdGVkIGdldFBhY2tlZFNhbXBsZXIzRChmdW5jTmFtZTogc3RyaW5nLCBuYW1lOiBzdHJpbmcsIGlucHV0TGF5b3V0OiBUZXh0dXJlTGF5b3V0KTogR2xzbExpYlJvdXRpbmUge1xuICAgIGNvbnN0IHNoYXBlID0gaW5wdXRMYXlvdXQudW5wYWNrZWRTaGFwZTtcbiAgICBjb25zdCB0ZXhTaGFwZSA9IFtpbnB1dExheW91dC53aWR0aCwgaW5wdXRMYXlvdXQuaGVpZ2h0XTtcbiAgICBjb25zdCBwYWNrZWRUZXhTaGFwZSA9IFt0ZXhTaGFwZVswXSwgdGV4U2hhcGVbMV1dO1xuICAgIGNvbnN0IGdsc2wgPSBnZXRHbHNsKHRoaXMuY29udGV4dC5nbENvbnRleHQudmVyc2lvbik7XG5cbiAgICBpZiAoc2hhcGVbMF0gPT09IDEpIHtcbiAgICAgIGNvbnN0IHNxdWVlemVkU2hhcGUgPSBzaGFwZS5zbGljZSgxKTtcbiAgICAgIGNvbnN0IGtlcHREaW1zID0gWzEsIDJdO1xuICAgICAgY29uc3QgbmV3SW5wdXRTaGFwZSA9IHNxdWVlemVJbnB1dFNoYXBlKHNoYXBlLCBzcXVlZXplZFNoYXBlKTtcbiAgICAgIGNvbnN0IHBhcmFtcyA9IFsnYicsICdyb3cnLCAnY29sJ107XG4gICAgICAvLyBEZWVwIGNvcHkgb2YgaW5wdXQgdGV4dHVyZSBsYXlvdXQuXG4gICAgICBjb25zdCBuZXdJbnB1dExheW91dDogVGV4dHVyZUxheW91dCA9IEpTT04ucGFyc2UoSlNPTi5zdHJpbmdpZnkoaW5wdXRMYXlvdXQpKTtcbiAgICAgIG5ld0lucHV0TGF5b3V0LnVucGFja2VkU2hhcGUgPSBuZXdJbnB1dFNoYXBlO1xuICAgICAgY29uc3Qgc2FtcGxlclJvdXRpbmUgPSB0aGlzLmdldFBhY2tlZFNhbXBsZXJGcm9tSW5wdXQoZnVuY05hbWUsIG5hbWUsIG5ld0lucHV0TGF5b3V0KTtcbiAgICAgIGNvbnN0IHBhY2tlZFNhbXBsZXIgPSBgJHtzYW1wbGVyUm91dGluZS5yb3V0aW5lQm9keX1cbiAgICAgIHZlYzQgJHtmdW5jTmFtZX0oaW50IGIsIGludCByb3csIGludCBjb2wpIHtcbiAgICAgICAgcmV0dXJuICR7ZnVuY05hbWV9KCR7Z2V0U3F1ZWV6ZWRQYXJhbXMocGFyYW1zLCBrZXB0RGltcyl9KTtcbiAgICAgIH0gYDtcbiAgICAgIGNvbnN0IHNvdXJjZSA9IHBhY2tlZFNhbXBsZXI7XG4gICAgICByZXR1cm4gbmV3IEdsc2xMaWJSb3V0aW5lKHNvdXJjZSwgc2FtcGxlclJvdXRpbmUuZGVwZW5kZW5jaWVzKTtcbiAgICB9XG4gICAgY29uc3QgdGV4TnVtUiA9IHBhY2tlZFRleFNoYXBlWzBdO1xuICAgIGNvbnN0IHRleE51bUMgPSBwYWNrZWRUZXhTaGFwZVsxXTtcblxuICAgIGNvbnN0IHZhbHVlc1BlclJvdyA9IE1hdGguY2VpbChzaGFwZVsyXSAvIDIpO1xuICAgIGNvbnN0IHRleGVsc0luQmF0Y2ggPSB2YWx1ZXNQZXJSb3cgKiBNYXRoLmNlaWwoc2hhcGVbMV0gLyAyKTtcblxuICAgIGNvbnN0IHBhY2tlZFNhbXBsZXIgPSBgdmVjNCAke2Z1bmNOYW1lfShpbnQgYiwgaW50IHJvdywgaW50IGNvbCkge1xuICAgICAgdmVjMiB1diA9IHBhY2tlZFVWZnJvbTNEKFxuICAgICAgICAke3RleE51bUN9LCAke3RleE51bVJ9LCAke3RleGVsc0luQmF0Y2h9LCAke3ZhbHVlc1BlclJvd30sIGIsIHJvdywgY29sKTtcbiAgICAgIHJldHVybiAke2dsc2wudGV4dHVyZTJEfSgke25hbWV9LCB1dik7fWA7XG4gICAgY29uc3Qgc291cmNlID0gcGFja2VkU2FtcGxlcjtcbiAgICByZXR1cm4gbmV3IEdsc2xMaWJSb3V0aW5lKHNvdXJjZSwgWydjb29yZGluYXRlcy5wYWNrZWRVVmZyb20zRCddKTtcbiAgfVxuICAvKlxuICAgKiBQYWNrZWQgTkQgc25pcHBldC5cbiAgICovXG4gIHByb3RlY3RlZCBnZXRQYWNrZWRTYW1wbGVyTkQoZnVuY05hbWU6IHN0cmluZywgbmFtZTogc3RyaW5nLCBpbnB1dExheW91dDogVGV4dHVyZUxheW91dCk6IEdsc2xMaWJSb3V0aW5lIHtcbiAgICBjb25zdCBzaGFwZSA9IGlucHV0TGF5b3V0LnVucGFja2VkU2hhcGU7XG4gICAgY29uc3QgcmFuayA9IHNoYXBlLmxlbmd0aDtcbiAgICBjb25zdCB0ZXhTaGFwZSA9IFtpbnB1dExheW91dC53aWR0aCwgaW5wdXRMYXlvdXQuaGVpZ2h0XTtcbiAgICBjb25zdCBnbHNsID0gZ2V0R2xzbCh0aGlzLmNvbnRleHQuZ2xDb250ZXh0LnZlcnNpb24pO1xuXG4gICAgY29uc3QgcGFja2VkVGV4U2hhcGUgPSBbdGV4U2hhcGVbMF0sIHRleFNoYXBlWzFdXTtcbiAgICBjb25zdCB0ZXhOdW1SID0gcGFja2VkVGV4U2hhcGVbMV07XG4gICAgY29uc3QgdGV4TnVtQyA9IHBhY2tlZFRleFNoYXBlWzBdO1xuICAgIGNvbnN0IHZhbHVlc1BlclJvdyA9IE1hdGguY2VpbChzaGFwZVtyYW5rIC0gMV0gLyAyKTtcbiAgICBsZXQgdGV4ZWxzSW5CYXRjaCA9IHZhbHVlc1BlclJvdyAqIE1hdGguY2VpbChzaGFwZVtyYW5rIC0gMl0gLyAyKTtcbiAgICBsZXQgcGFyYW1zID0gJ2ludCBiLCBpbnQgcm93LCBpbnQgY29sJztcbiAgICBsZXQgaW5kZXggPSBgYiAqICR7dGV4ZWxzSW5CYXRjaH0gKyAocm93IC8gMikgKiAke3ZhbHVlc1BlclJvd30gKyAoY29sIC8gMilgO1xuICAgIGZvciAobGV0IGIgPSAyOyBiIDwgcmFuayAtIDE7IGIrKykge1xuICAgICAgcGFyYW1zID0gYGludCBiJHtifSwgYCArIHBhcmFtcztcbiAgICAgIHRleGVsc0luQmF0Y2ggKj0gc2hhcGVbcmFuayAtIGIgLSAxXTtcbiAgICAgIGluZGV4ID0gYGIke2J9ICogJHt0ZXhlbHNJbkJhdGNofSArIGAgKyBpbmRleDtcbiAgICB9XG4gICAgY29uc3QgcGFja2VkU2FtcGxlciA9IGB2ZWM0ICR7ZnVuY05hbWV9KCR7cGFyYW1zfSkge1xuICAgICAgaW50IGluZGV4ID0gJHtpbmRleH07XG4gICAgICBpbnQgdGV4UiA9IGluZGV4IC8gJHt0ZXhOdW1DfTtcbiAgICAgIGludCB0ZXhDID0gaW5kZXggLSB0ZXhSICogJHt0ZXhOdW1DfTtcbiAgICAgIHZlYzIgdXYgPSAodmVjMih0ZXhDLCB0ZXhSKSArIGhhbGZDUikgLyB2ZWMyKCR7dGV4TnVtQ30sICR7dGV4TnVtUn0pO1xuICAgICAgcmV0dXJuICR7Z2xzbC50ZXh0dXJlMkR9KCR7bmFtZX0sIHV2KTtcbiAgICB9YDtcbiAgICBjb25zdCBzb3VyY2UgPSBwYWNrZWRTYW1wbGVyO1xuICAgIHJldHVybiBuZXcgR2xzbExpYlJvdXRpbmUoc291cmNlKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBVbnBhY2tlZCBzY2FsYXIgc25pcHBldC5cbiAgICovXG4gIHByb3RlY3RlZCBnZXRVbnBhY2tlZFNhbXBsZXJTY2FsYXIoZnVuY05hbWU6IHN0cmluZywgbmFtZTogc3RyaW5nLCBpbnB1dExheW91dDogVGV4dHVyZUxheW91dCk6IEdsc2xMaWJSb3V0aW5lIHtcbiAgICBjb25zdCBbdGV4TnVtUiwgdGV4TnVtQ10gPSBbaW5wdXRMYXlvdXQud2lkdGgsIGlucHV0TGF5b3V0LmhlaWdodF07XG4gICAgaWYgKHRleE51bVIgPT09IDEgJiYgdGV4TnVtQyA9PT0gMSkge1xuICAgICAgY29uc3Qgc291cmNlID0gYFxuICAgICAgICAgIGZsb2F0ICR7ZnVuY05hbWV9KCkge1xuICAgICAgICAgICAgcmV0dXJuIHNhbXBsZVRleHR1cmUoJHtuYW1lfSwgaGFsZkNSKTtcbiAgICAgICAgICB9XG4gICAgICAgIGA7XG4gICAgICByZXR1cm4gbmV3IEdsc2xMaWJSb3V0aW5lKHNvdXJjZSwgWydjb29yZGluYXRlcy5zYW1wbGVUZXh0dXJlJ10pO1xuICAgIH1cblxuICAgIGNvbnN0IHNvdXJjZSA9IGBcbiAgICAgICAgZmxvYXQgJHtmdW5jTmFtZX0oKSB7XG4gICAgICAgICAgaW50IG9mZnNldF8ke25hbWV9ID0gY29vcmRzVG9PZmZzZXQoVGV4Q29vcmRzLCAke3RleE51bVJ9LCAke3RleE51bUN9KTtcbiAgICAgICAgICB2ZWMyIHV2ID0gdXZGcm9tRmxhdCgke3RleE51bVJ9LCAke3RleE51bUN9LCBvZmZzZXRfJHtuYW1lfSk7XG4gICAgICAgICAgcmV0dXJuIHNhbXBsZVRleHR1cmUoJHtuYW1lfSwgdXYpO1xuICAgICAgICB9XG4gICAgICBgO1xuICAgIHJldHVybiBuZXcgR2xzbExpYlJvdXRpbmUoXG4gICAgICAgIHNvdXJjZSwgWydjb29yZGluYXRlcy51dkZyb21GbGF0JywgJ2Nvb3JkaW5hdGVzLnNhbXBsZVRleHR1cmUnLCAnY29vcmRpbmF0ZXMuY29vcmRzVG9PZmZzZXQnXSk7XG4gIH1cblxuICAvKipcbiAgICogVW5wYWNrZWQgMUQgc25pcHBldC5cbiAgICovXG4gIHByb3RlY3RlZCBnZXRVbnBhY2tlZFNhbXBsZXIxRChmdW5jTmFtZTogc3RyaW5nLCBuYW1lOiBzdHJpbmcsIGlucHV0TGF5b3V0OiBUZXh0dXJlTGF5b3V0KTogR2xzbExpYlJvdXRpbmUge1xuICAgIGNvbnN0IHROdW1SID0gaW5wdXRMYXlvdXQud2lkdGg7XG4gICAgY29uc3QgdE51bUMgPSBpbnB1dExheW91dC5oZWlnaHQ7XG5cbiAgICBpZiAodE51bUMgPT09IDEgJiYgdE51bVIgPT09IDEpIHtcbiAgICAgIGNvbnN0IHNvdXJjZSA9IGBcbiAgICAgICAgZmxvYXQgJHtmdW5jTmFtZX0oaW50IGluZGV4KSB7XG4gICAgICAgICAgcmV0dXJuIHNhbXBsZVRleHR1cmUoJHtuYW1lfSwgaGFsZkNSKTtcbiAgICAgICAgfVxuICAgICAgYDtcbiAgICAgIHJldHVybiBuZXcgR2xzbExpYlJvdXRpbmUoc291cmNlLCBbJ2Nvb3JkaW5hdGVzLnNhbXBsZVRleHR1cmUnXSk7XG4gICAgfVxuXG4gICAgaWYgKHROdW1DID09PSAxKSB7XG4gICAgICBjb25zdCBzb3VyY2UgPSBgXG4gICAgICAgICAgZmxvYXQgJHtmdW5jTmFtZX0oaW50IGluZGV4KSB7XG4gICAgICAgICAgICB2ZWMyIHV2ID0gdmVjMigoZmxvYXQoaW5kZXgpICsgMC41KSAvICR7dE51bVJ9LjAsIDAuNSk7XG4gICAgICAgICAgICByZXR1cm4gc2FtcGxlVGV4dHVyZSgke25hbWV9LCB1dik7XG4gICAgICAgICAgfVxuICAgICAgICBgO1xuICAgICAgcmV0dXJuIG5ldyBHbHNsTGliUm91dGluZShzb3VyY2UsIFsnY29vcmRpbmF0ZXMuc2FtcGxlVGV4dHVyZSddKTtcbiAgICB9XG4gICAgaWYgKHROdW1SID09PSAxKSB7XG4gICAgICBjb25zdCBzb3VyY2UgPSBgXG4gICAgICAgICAgZmxvYXQgJHtmdW5jTmFtZX0oaW50IGluZGV4KSB7XG4gICAgICAgICAgICB2ZWMyIHV2ID0gdmVjMigwLjUsIChmbG9hdChpbmRleCkgKyAwLjUpIC8gJHt0TnVtQ30uMCk7XG4gICAgICAgICAgICByZXR1cm4gc2FtcGxlVGV4dHVyZSgke25hbWV9LCB1dik7XG4gICAgICAgICAgfVxuICAgICAgICBgO1xuICAgICAgcmV0dXJuIG5ldyBHbHNsTGliUm91dGluZShzb3VyY2UsIFsnY29vcmRpbmF0ZXMuc2FtcGxlVGV4dHVyZSddKTtcbiAgICB9XG4gICAgY29uc3Qgc291cmNlID0gYFxuICAgICAgICBmbG9hdCAke2Z1bmNOYW1lfShpbnQgaW5kZXgpIHtcbiAgICAgICAgICB2ZWMyIHV2ID0gdXZGcm9tRmxhdCgke3ROdW1SfSwgJHt0TnVtQ30sIGluZGV4KTtcbiAgICAgICAgICByZXR1cm4gc2FtcGxlVGV4dHVyZSgke25hbWV9LCB1dik7XG4gICAgICAgIH1cbiAgICAgIGA7XG4gICAgcmV0dXJuIG5ldyBHbHNsTGliUm91dGluZShzb3VyY2UsIFsnY29vcmRpbmF0ZXMudXZGcm9tRmxhdCcsICdjb29yZGluYXRlcy5zYW1wbGVUZXh0dXJlJ10pO1xuICB9XG5cbiAgLyoqXG4gICAqIFVucGFja2VkIDJEIHNuaXBwZXQuXG4gICAqL1xuXG4gIHByb3RlY3RlZCBnZXRVbnBhY2tlZFNhbXBsZXIyRChmdW5jTmFtZTogc3RyaW5nLCBuYW1lOiBzdHJpbmcsIGlucHV0TGF5b3V0OiBUZXh0dXJlTGF5b3V0KTogR2xzbExpYlJvdXRpbmUge1xuICAgIGNvbnN0IHNoYXBlID0gaW5wdXRMYXlvdXQudW5wYWNrZWRTaGFwZTtcblxuICAgIC8vIFRPRE86IG1vZGlmeSByb3cvY29sIG9yZGVyIGZvciBvdGhlciBkaW1lbnNpb25zLlxuICAgIGNvbnN0IHRleFNoYXBlID0gW2lucHV0TGF5b3V0LmhlaWdodCwgaW5wdXRMYXlvdXQud2lkdGhdO1xuXG4gICAgaWYgKHRleFNoYXBlICE9IG51bGwgJiYgQXJyYXlVdGlsLmFycmF5c0VxdWFsKHNoYXBlLCB0ZXhTaGFwZSkpIHtcbiAgICAgIGNvbnN0IHRleE51bVIgPSB0ZXhTaGFwZVsxXTtcbiAgICAgIGNvbnN0IHRleE51bUMgPSB0ZXhTaGFwZVswXTtcbiAgICAgIGNvbnN0IHNvdXJjZSA9IGBcbiAgICAgICAgICBmbG9hdCAke2Z1bmNOYW1lfShpbnQgcm93LCBpbnQgY29sKSB7XG4gICAgICAgICAgICB2ZWMyIHV2ID0gKHZlYzIocm93LCBjb2wpICsgaGFsZkNSKSAvIHZlYzIoJHt0ZXhOdW1SfS4wLCAke3RleE51bUN9LjApO1xuICAgICAgICAgICAgcmV0dXJuIHNhbXBsZVRleHR1cmUoJHtuYW1lfSwgdXYpO1xuICAgICAgICAgIH1cbiAgICAgICAgYDtcbiAgICAgIHJldHVybiBuZXcgR2xzbExpYlJvdXRpbmUoc291cmNlLCBbJ2Nvb3JkaW5hdGVzLnNhbXBsZVRleHR1cmUnXSk7XG4gICAgfVxuXG4gICAgY29uc3Qge25ld1NoYXBlLCBrZXB0RGltc30gPSBzcXVlZXplU2hhcGUoc2hhcGUgYXMgbnVtYmVyW10pO1xuICAgIGNvbnN0IHNxdWVlemVkU2hhcGUgPSBuZXdTaGFwZTtcbiAgICBpZiAoc3F1ZWV6ZWRTaGFwZS5sZW5ndGggPCBzaGFwZS5sZW5ndGgpIHtcbiAgICAgIGNvbnN0IG5ld0lucHV0U2hhcGUgPSBzcXVlZXplSW5wdXRTaGFwZShzaGFwZSwgc3F1ZWV6ZWRTaGFwZSk7XG4gICAgICAvLyBEZWVwIGNvcHkgb2YgaW5wdXQgdGV4dHVyZSBsYXlvdXQuXG4gICAgICBjb25zdCBuZXdJbnB1dExheW91dDogVGV4dHVyZUxheW91dCA9IEpTT04ucGFyc2UoSlNPTi5zdHJpbmdpZnkoaW5wdXRMYXlvdXQpKTtcbiAgICAgIG5ld0lucHV0TGF5b3V0LnVucGFja2VkU2hhcGUgPSBuZXdJbnB1dFNoYXBlO1xuXG4gICAgICBjb25zdCBwYXJhbXMgPSBbJ2NvbCcsICdyb3cnXTtcbiAgICAgIGNvbnN0IHNvdXJjZSA9IGBcbiAgICAgICAgICAke3RoaXMuZ2V0VW5wYWNrZWRTYW1wbGVyRnJvbUlucHV0KGZ1bmNOYW1lLCBuYW1lLCBuZXdJbnB1dExheW91dCkucm91dGluZUJvZHl9XG4gICAgICAgICAgZmxvYXQgJHtmdW5jTmFtZX0oaW50IHJvdywgaW50IGNvbCkge1xuICAgICAgICAgICAgcmV0dXJuICR7ZnVuY05hbWV9KCR7Z2V0U3F1ZWV6ZWRQYXJhbXMocGFyYW1zLCBrZXB0RGltcyl9KTtcbiAgICAgICAgICB9XG4gICAgICAgIGA7XG4gICAgICByZXR1cm4gbmV3IEdsc2xMaWJSb3V0aW5lKHNvdXJjZSwgWydjb29yZGluYXRlcy5zYW1wbGVUZXh0dXJlJ10pO1xuICAgIH1cblxuICAgIGNvbnN0IHRleE51bVIgPSB0ZXhTaGFwZVsxXTtcbiAgICBjb25zdCB0ZXhOdW1DID0gdGV4U2hhcGVbMF07XG4gICAgaWYgKHRleE51bUMgPT09IDEpIHtcbiAgICAgIGNvbnN0IHNvdXJjZSA9IGBcbiAgICAgICAgICBmbG9hdCAke2Z1bmNOYW1lfShpbnQgcm93LCBpbnQgY29sKSB7XG4gICAgICAgICAgICBpbnQgb2Zmc2V0XyR7bmFtZX0gPSBjb29yZHNUb09mZnNldChUZXhDb29yZHMsICR7dGV4TnVtUn0sICR7dGV4TnVtQ30pO1xuICAgICAgICAgICAgZmxvYXQgaW5kZXggPSBkb3QodmVjMyhyb3csIGNvbCwgb2Zmc2V0XyR7bmFtZX0pLCB2ZWMzKCR7c2hhcGVbMV19LCAxLCAxKSk7XG4gICAgICAgICAgICB2ZWMyIHV2ID0gdmVjMigwLjUsIChpbmRleCArIDAuNSkgLyAke3RleE51bVJ9LjApO1xuICAgICAgICAgICAgcmV0dXJuIHNhbXBsZVRleHR1cmUoJHtuYW1lfSwgdXYpO1xuICAgICAgICAgIH1cbiAgICAgICAgYDtcbiAgICAgIHJldHVybiBuZXcgR2xzbExpYlJvdXRpbmUoc291cmNlLCBbJ2Nvb3JkaW5hdGVzLnNhbXBsZVRleHR1cmUnLCAnY29vcmRpbmF0ZXMuY29vcmRzVG9PZmZzZXQnXSk7XG4gICAgfVxuXG4gICAgaWYgKHRleE51bVIgPT09IDEpIHtcbiAgICAgIGNvbnN0IHNvdXJjZSA9IGBcbiAgICAgICAgICBmbG9hdCAke2Z1bmNOYW1lfShpbnQgcm93LCBpbnQgY29sKSB7XG4gICAgICAgICAgICBpbnQgb2Zmc2V0XyR7bmFtZX0gPSBjb29yZHNUb09mZnNldChUZXhDb29yZHMsICR7dGV4TnVtUn0sICR7dGV4TnVtQ30pO1xuICAgICAgICAgICAgZmxvYXQgaW5kZXggPSBkb3QodmVjMyhyb3csIGNvbCwgb2Zmc2V0XyR7bmFtZX0pLCB2ZWMzKCR7c2hhcGVbMV19LCAxLCAxKSk7XG4gICAgICAgICAgICB2ZWMyIHV2ID0gdmVjMigoaW5kZXggKyAwLjUpIC8gJHt0ZXhOdW1DfS4wLCAwLjUpO1xuICAgICAgICAgICAgcmV0dXJuIHNhbXBsZVRleHR1cmUoJHtuYW1lfSwgdXYpO1xuICAgICAgICAgIH1cbiAgICAgICAgYDtcbiAgICAgIHJldHVybiBuZXcgR2xzbExpYlJvdXRpbmUoc291cmNlLCBbJ2Nvb3JkaW5hdGVzLnNhbXBsZVRleHR1cmUnLCAnY29vcmRpbmF0ZXMuY29vcmRzVG9PZmZzZXQnXSk7XG4gICAgfVxuXG4gICAgY29uc3Qgc291cmNlID0gYFxuICAgICAgICBmbG9hdCAke2Z1bmNOYW1lfShpbnQgcm93LCBpbnQgY29sKSB7XG4gICAgICAgICAgaW50IGluZGV4ID0gY29sICogJHtzaGFwZVsxXX0gKyByb3c7XG4gICAgICAgICAgdmVjMiB1diA9IHV2RnJvbUZsYXQoJHt0ZXhOdW1SfSwgJHt0ZXhOdW1DfSwgaW5kZXgpO1xuICAgICAgICAgIHJldHVybiBzYW1wbGVUZXh0dXJlKCR7bmFtZX0sIHV2KTtcbiAgICAgICAgfVxuICAgICAgYDtcbiAgICByZXR1cm4gbmV3IEdsc2xMaWJSb3V0aW5lKFxuICAgICAgICBzb3VyY2UsIFsnY29vcmRpbmF0ZXMudXZGcm9tRmxhdCcsICdjb29yZGluYXRlcy5zYW1wbGVUZXh0dXJlJywgJ2Nvb3JkaW5hdGVzLmNvb3Jkc1RvT2Zmc2V0J10pO1xuICB9XG5cbiAgLyoqXG4gICAqIFVucGFja2VkIDNEIHNuaXBwZXQuXG4gICAqL1xuXG4gIHByb3RlY3RlZCBnZXRVbnBhY2tlZFNhbXBsZXIzRChmdW5jTmFtZTogc3RyaW5nLCBuYW1lOiBzdHJpbmcsIGlucHV0TGF5b3V0OiBUZXh0dXJlTGF5b3V0KTogR2xzbExpYlJvdXRpbmUge1xuICAgIGNvbnN0IHNoYXBlID0gaW5wdXRMYXlvdXQudW5wYWNrZWRTaGFwZTtcbiAgICBjb25zdCBzdHJpZGUwID0gc2hhcGVbMV0gKiBzaGFwZVsyXTtcbiAgICBjb25zdCBzdHJpZGUxID0gc2hhcGVbMl07XG5cbiAgICBjb25zdCB7bmV3U2hhcGUsIGtlcHREaW1zfSA9IHNxdWVlemVTaGFwZShzaGFwZSBhcyBudW1iZXJbXSk7XG4gICAgY29uc3Qgc3F1ZWV6ZWRTaGFwZSA9IG5ld1NoYXBlO1xuICAgIGlmIChzcXVlZXplZFNoYXBlLmxlbmd0aCA8IHNoYXBlLmxlbmd0aCkge1xuICAgICAgY29uc3QgbmV3SW5wdXRTaGFwZSA9IHNxdWVlemVJbnB1dFNoYXBlKHNoYXBlLCBzcXVlZXplZFNoYXBlKTtcbiAgICAgIGNvbnN0IHBhcmFtcyA9IFsnYmF0Y2gnLCAnY29sJywgJ3JvdyddO1xuICAgICAgLy8gRGVlcCBjb3B5IG9mIGlucHV0IHRleHR1cmUgbGF5b3V0LlxuICAgICAgY29uc3QgbmV3SW5wdXRMYXlvdXQ6IFRleHR1cmVMYXlvdXQgPSBKU09OLnBhcnNlKEpTT04uc3RyaW5naWZ5KGlucHV0TGF5b3V0KSk7XG4gICAgICBuZXdJbnB1dExheW91dC51bnBhY2tlZFNoYXBlID0gbmV3SW5wdXRTaGFwZTtcbiAgICAgIGNvbnN0IHJvdXRpbmUgPSB0aGlzLmdldFVucGFja2VkU2FtcGxlckZyb21JbnB1dChmdW5jTmFtZSwgbmFtZSwgbmV3SW5wdXRMYXlvdXQpO1xuICAgICAgLy8gVE9ETzogcmV2aXNpdCB0aGUgbG9naWMgaGVyZSB0byBtYWtlIGl0IHNpbXBsZXJcbiAgICAgIGNvbnN0IHJldkRpbXMgPSBrZXB0RGltcy5yZXZlcnNlKCk7XG4gICAgICBjb25zdCBzb3VyY2UgPSBgXG4gICAgICAgICAgJHtyb3V0aW5lLnJvdXRpbmVCb2R5fVxuICAgICAgICAgIGZsb2F0ICR7ZnVuY05hbWV9KGludCBiYXRjaCwgaW50IHJvdywgaW50IGNvbCkge1xuICAgICAgICAgICAgcmV0dXJuICR7ZnVuY05hbWV9KCR7Z2V0U3F1ZWV6ZWRQYXJhbXMocGFyYW1zLCByZXZEaW1zKX0pO1xuICAgICAgICAgIH1cbiAgICAgICAgYDtcbiAgICAgIHJldHVybiBuZXcgR2xzbExpYlJvdXRpbmUoc291cmNlLCByb3V0aW5lLmRlcGVuZGVuY2llcyk7XG4gICAgfVxuXG4gICAgY29uc3QgdGV4TnVtUiA9IGlucHV0TGF5b3V0LndpZHRoO1xuICAgIGNvbnN0IHRleE51bUMgPSBpbnB1dExheW91dC5oZWlnaHQ7XG4gICAgY29uc3Qgc291cmNlID0gYFxuICAgICAgICAgIGZsb2F0ICR7ZnVuY05hbWV9KGludCBkZXB0aCwgaW50IHJvdywgaW50IGNvbCkge1xuICAgICAgICAgICAgLy8gRXhwbGljaXRseSB1c2UgaW50ZWdlciBvcGVyYXRpb25zIGFzIGRvdCgpIG9ubHkgd29ya3Mgb24gZmxvYXRzLlxuICAgICAgICAgICAgaW50IGluZGV4ID0gZGVwdGggKiAke3N0cmlkZTB9ICsgY29sICogJHtzdHJpZGUxfSArIHJvdztcbiAgICAgICAgICAgIHZlYzIgdXYgPSB1dkZyb21GbGF0KCR7dGV4TnVtUn0sICR7dGV4TnVtQ30sIGluZGV4KTtcbiAgICAgICAgICAgIHJldHVybiBzYW1wbGVUZXh0dXJlKCR7bmFtZX0sIHV2KTtcbiAgICAgICAgICB9XG4gICAgICBgO1xuICAgIHJldHVybiBuZXcgR2xzbExpYlJvdXRpbmUoXG4gICAgICAgIHNvdXJjZSwgWydjb29yZGluYXRlcy51dkZyb21GbGF0JywgJ2Nvb3JkaW5hdGVzLnNhbXBsZVRleHR1cmUnLCAnY29vcmRpbmF0ZXMuY29vcmRzVG9PZmZzZXQnXSk7XG4gIH1cblxuICAvKipcbiAgICogVW5wYWNrZWQgNEQgc25pcHBldC5cbiAgICovXG5cbiAgcHJvdGVjdGVkIGdldFVucGFja2VkU2FtcGxlcjREKGZ1bmNOYW1lOiBzdHJpbmcsIG5hbWU6IHN0cmluZywgaW5wdXRMYXlvdXQ6IFRleHR1cmVMYXlvdXQpOiBHbHNsTGliUm91dGluZSB7XG4gICAgY29uc3Qgc2hhcGUgPSBpbnB1dExheW91dC51bnBhY2tlZFNoYXBlO1xuICAgIGNvbnN0IHN0cmlkZTIgPSBzaGFwZVszXTtcbiAgICBjb25zdCBzdHJpZGUxID0gc2hhcGVbMl0gKiBzdHJpZGUyO1xuICAgIGNvbnN0IHN0cmlkZTAgPSBzaGFwZVsxXSAqIHN0cmlkZTE7XG5cbiAgICAvL1xuICAgIC8vIFRPRE86IHJlLWVuYWJsZSB0aGlzIHNob3J0Y3V0IG9uY2UgdGhlIGluZGV4IGNhbGN1bGF0aW9uIGJ1ZyBpcyBmaXhlZC5cbiAgICAvL1xuICAgIC8vIGNvbnN0IHtuZXdTaGFwZSwga2VwdERpbXN9ID0gc3F1ZWV6ZVNoYXBlKHNoYXBlIGFzIG51bWJlcltdKTtcbiAgICAvLyBpZiAobmV3U2hhcGUubGVuZ3RoIDwgc2hhcGUubGVuZ3RoKSB7XG4gICAgLy8gICBjb25zdCBuZXdJbnB1dFNoYXBlID0gc3F1ZWV6ZUlucHV0U2hhcGUoc2hhcGUsIG5ld1NoYXBlKTtcbiAgICAvLyAgIGNvbnN0IHBhcmFtcyA9IFsncm93JywgJ2NvbCcsICdkZXB0aCcsICdkZXB0aDInXTtcbiAgICAvLyAgIC8vIERlZXAgY29weSBvZiBpbnB1dCB0ZXh0dXJlIGxheW91dC5cbiAgICAvLyAgIGNvbnN0IG5ld0lucHV0TGF5b3V0OiBUZXh0dXJlTGF5b3V0ID0gSlNPTi5wYXJzZShKU09OLnN0cmluZ2lmeShpbnB1dExheW91dCkpO1xuICAgIC8vICAgbmV3SW5wdXRMYXlvdXQudW5wYWNrZWRTaGFwZSA9IG5ld0lucHV0U2hhcGU7XG4gICAgLy8gICBjb25zdCBzb3VyY2UgPSBgXG4gICAgLy8gICAgICAgJHt0aGlzLmdldFVucGFja2VkU2FtcGxlckZyb21JbnB1dChmdW5jTmFtZSwgbmFtZSwgbmV3SW5wdXRMYXlvdXQpLnJvdXRpbmVCb2R5fVxuICAgIC8vICAgICAgIGZsb2F0ICR7ZnVuY05hbWV9KGludCByb3csIGludCBjb2wsIGludCBkZXB0aCwgaW50IGRlcHRoMikge1xuICAgIC8vICAgICAgICAgcmV0dXJuICR7ZnVuY05hbWV9KCR7Z2V0U3F1ZWV6ZWRQYXJhbXMocGFyYW1zLCBrZXB0RGltcyl9KTtcbiAgICAvLyAgICAgICB9XG4gICAgLy8gICAgIGA7XG4gICAgLy8gICByZXR1cm4gbmV3IEdsc2xMaWJSb3V0aW5lKFxuICAgIC8vICAgICAgIHNvdXJjZSwgWydjb29yZGluYXRlcy51dkZyb21GbGF0JywgJ2Nvb3JkaW5hdGVzLnNhbXBsZVRleHR1cmUnLCAnY29vcmRpbmF0ZXMuY29vcmRzVG9PZmZzZXQnXSk7XG4gICAgLy8gfVxuXG4gICAgY29uc3QgdGV4TnVtUiA9IGlucHV0TGF5b3V0LndpZHRoO1xuICAgIGNvbnN0IHRleE51bUMgPSBpbnB1dExheW91dC5oZWlnaHQ7XG4gICAgY29uc3Qgc291cmNlID0gYFxuICAgICAgICBmbG9hdCAke2Z1bmNOYW1lfShpbnQgcm93LCBpbnQgY29sLCBpbnQgZGVwdGgsIGludCBkZXB0aDIpIHtcbiAgICAgICAgICBpbnQgaW5kZXggPSByb3cgKiAke3N0cmlkZTB9ICsgY29sICogJHtzdHJpZGUxfSArXG4gICAgICAgICAgICAgIGRlcHRoMiAqICR7c3RyaWRlMn0gKyBkZXB0aDtcbiAgICAgICAgICB2ZWMyIHV2ID0gdXZGcm9tRmxhdCgke3RleE51bVJ9LCAke3RleE51bUN9LCBpbmRleCk7XG4gICAgICAgICAgcmV0dXJuIHNhbXBsZVRleHR1cmUoJHtuYW1lfSwgdXYpO1xuICAgICAgICB9XG4gICAgICBgO1xuICAgIHJldHVybiBuZXcgR2xzbExpYlJvdXRpbmUoc291cmNlLCBbJ2Nvb3JkaW5hdGVzLnV2RnJvbUZsYXQnLCAnY29vcmRpbmF0ZXMuc2FtcGxlVGV4dHVyZSddKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBVbnBhY2tlZCA1RCBzbmlwcGV0LlxuICAgKi9cbiAgcHJvdGVjdGVkIGdldFVucGFja2VkU2FtcGxlcjVEKGZ1bmNOYW1lOiBzdHJpbmcsIG5hbWU6IHN0cmluZywgaW5wdXRMYXlvdXQ6IFRleHR1cmVMYXlvdXQpOiBHbHNsTGliUm91dGluZSB7XG4gICAgY29uc3Qgc2hhcGUgPSBpbnB1dExheW91dC51bnBhY2tlZFNoYXBlO1xuICAgIGNvbnN0IHN0cmlkZTMgPSBzaGFwZVs0XTtcbiAgICBjb25zdCBzdHJpZGUyID0gc2hhcGVbM10gKiBzdHJpZGUzO1xuICAgIGNvbnN0IHN0cmlkZTEgPSBzaGFwZVsyXSAqIHN0cmlkZTI7XG4gICAgY29uc3Qgc3RyaWRlMCA9IHNoYXBlWzFdICogc3RyaWRlMTtcblxuICAgIGNvbnN0IHtuZXdTaGFwZSwga2VwdERpbXN9ID0gc3F1ZWV6ZVNoYXBlKHNoYXBlIGFzIG51bWJlcltdKTtcbiAgICBpZiAobmV3U2hhcGUubGVuZ3RoIDwgc2hhcGUubGVuZ3RoKSB7XG4gICAgICBjb25zdCBuZXdJbnB1dFNoYXBlID0gc3F1ZWV6ZUlucHV0U2hhcGUoc2hhcGUsIG5ld1NoYXBlKTtcbiAgICAgIGNvbnN0IHBhcmFtcyA9IFsncm93JywgJ2NvbCcsICdkZXB0aCcsICdkZXB0aDInLCAnZGVwdGgzJ107XG4gICAgICAvLyBEZWVwIGNvcHkgb2YgaW5wdXQgdGV4dHVyZSBsYXlvdXQuXG4gICAgICBjb25zdCBuZXdJbnB1dExheW91dDogVGV4dHVyZUxheW91dCA9IEpTT04ucGFyc2UoSlNPTi5zdHJpbmdpZnkoaW5wdXRMYXlvdXQpKTtcbiAgICAgIG5ld0lucHV0TGF5b3V0LnVucGFja2VkU2hhcGUgPSBuZXdJbnB1dFNoYXBlO1xuXG4gICAgICBjb25zdCBzb3VyY2UgPSBgXG4gICAgICAgICAgJHt0aGlzLmdldFVucGFja2VkU2FtcGxlckZyb21JbnB1dChmdW5jTmFtZSwgbmFtZSwgbmV3SW5wdXRMYXlvdXQpLnJvdXRpbmVCb2R5fVxuICAgICAgICAgIGZsb2F0ICR7ZnVuY05hbWV9KGludCByb3csIGludCBjb2wsIGludCBkZXB0aCwgaW50IGRlcHRoMiwgaW50IGRlcHRoMykge1xuICAgICAgICAgICAgcmV0dXJuICR7ZnVuY05hbWV9KCR7Z2V0U3F1ZWV6ZWRQYXJhbXMocGFyYW1zLCBrZXB0RGltcyl9KTtcbiAgICAgICAgICB9XG4gICAgICAgIGA7XG4gICAgICByZXR1cm4gbmV3IEdsc2xMaWJSb3V0aW5lKHNvdXJjZSwgWydjb29yZGluYXRlcy5zYW1wbGVUZXh0dXJlJywgJ2Nvb3JkaW5hdGVzLnV2RnJvbUZsYXQnXSk7XG4gICAgfVxuXG4gICAgY29uc3QgdGV4TnVtUiA9IGlucHV0TGF5b3V0LndpZHRoO1xuICAgIGNvbnN0IHRleE51bUMgPSBpbnB1dExheW91dC5oZWlnaHQ7XG4gICAgY29uc3Qgc291cmNlID0gYFxuICAgICAgICBmbG9hdCAke2Z1bmNOYW1lfShpbnQgcm93LCBpbnQgY29sLCBpbnQgZGVwdGgsIGludCBkZXB0aDIsIGludCBkZXB0aDMpIHtcbiAgICAgICAgICBpbnQgaW5kZXggPSByb3cgKiAke3N0cmlkZTB9ICsgY29sICogJHtzdHJpZGUxfSArIGRlcHRoICogJHtzdHJpZGUyfSArXG4gICAgICAgICAgZGVwdGgzICogJHtzdHJpZGUzfSArIGRlcHRoMjtcbiAgICAgICAgICB2ZWMyIHV2ID0gdXZGcm9tRmxhdCgke3RleE51bVJ9LCAke3RleE51bUN9LCBpbmRleCk7XG4gICAgICAgICAgcmV0dXJuIHNhbXBsZVRleHR1cmUoJHtuYW1lfSwgdXYpO1xuICAgICAgICB9XG4gICAgICBgO1xuICAgIHJldHVybiBuZXcgR2xzbExpYlJvdXRpbmUoc291cmNlLCBbJ2Nvb3JkaW5hdGVzLnNhbXBsZVRleHR1cmUnLCAnY29vcmRpbmF0ZXMudXZGcm9tRmxhdCddKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBVbnBhY2tlZCA2RCBzbmlwcGV0LlxuICAgKi9cbiAgcHJvdGVjdGVkIGdldFVucGFja2VkU2FtcGxlcjZEKGZ1bmNOYW1lOiBzdHJpbmcsIG5hbWU6IHN0cmluZywgaW5wdXRMYXlvdXQ6IFRleHR1cmVMYXlvdXQpOiBHbHNsTGliUm91dGluZSB7XG4gICAgY29uc3Qgc2hhcGUgPSBpbnB1dExheW91dC51bnBhY2tlZFNoYXBlO1xuICAgIGNvbnN0IHN0cmlkZTQgPSBzaGFwZVs1XTtcbiAgICBjb25zdCBzdHJpZGUzID0gc2hhcGVbNF0gKiBzdHJpZGU0O1xuICAgIGNvbnN0IHN0cmlkZTIgPSBzaGFwZVszXSAqIHN0cmlkZTM7XG4gICAgY29uc3Qgc3RyaWRlMSA9IHNoYXBlWzJdICogc3RyaWRlMjtcbiAgICBjb25zdCBzdHJpZGUwID0gc2hhcGVbMV0gKiBzdHJpZGUxO1xuXG4gICAgY29uc3Qge25ld1NoYXBlLCBrZXB0RGltc30gPSBzcXVlZXplU2hhcGUoc2hhcGUgYXMgbnVtYmVyW10pO1xuICAgIGlmIChuZXdTaGFwZS5sZW5ndGggPCBzaGFwZS5sZW5ndGgpIHtcbiAgICAgIGNvbnN0IG5ld0lucHV0U2hhcGUgPSBzcXVlZXplSW5wdXRTaGFwZShzaGFwZSwgbmV3U2hhcGUpO1xuICAgICAgY29uc3QgcGFyYW1zID0gWydyb3cnLCAnY29sJywgJ2RlcHRoJywgJ2RlcHRoMicsICdkZXB0aDMnLCAnZGVwdGg0J107XG4gICAgICAvLyBEZWVwIGNvcHkgb2YgaW5wdXQgdGV4dHVyZSBsYXlvdXQuXG4gICAgICBjb25zdCBuZXdJbnB1dExheW91dDogVGV4dHVyZUxheW91dCA9IEpTT04ucGFyc2UoSlNPTi5zdHJpbmdpZnkoaW5wdXRMYXlvdXQpKTtcbiAgICAgIG5ld0lucHV0TGF5b3V0LnVucGFja2VkU2hhcGUgPSBuZXdJbnB1dFNoYXBlO1xuXG4gICAgICBjb25zdCBzb3VyY2UgPSBgXG4gICAgICAgICAgICAke3RoaXMuZ2V0VW5wYWNrZWRTYW1wbGVyRnJvbUlucHV0KGZ1bmNOYW1lLCBuYW1lLCBuZXdJbnB1dExheW91dCkucm91dGluZUJvZHl9XG4gICAgICAgICAgICBmbG9hdCAke2Z1bmNOYW1lfShpbnQgcm93LCBpbnQgY29sLCBpbnQgZGVwdGgsXG4gICAgICAgICAgICAgIGludCBkZXB0aDIsIGludCBkZXB0aDMsIGludCBkZXB0aDQpIHtcbiAgICAgICAgICAgICAgcmV0dXJuICR7ZnVuY05hbWV9KCR7Z2V0U3F1ZWV6ZWRQYXJhbXMocGFyYW1zLCBrZXB0RGltcyl9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICBgO1xuICAgICAgcmV0dXJuIG5ldyBHbHNsTGliUm91dGluZShzb3VyY2UsIFsnY29vcmRpbmF0ZXMuc2FtcGxlVGV4dHVyZScsICdjb29yZGluYXRlcy51dkZyb21GbGF0J10pO1xuICAgIH1cblxuICAgIGNvbnN0IHRleE51bVIgPSBpbnB1dExheW91dC53aWR0aDtcbiAgICBjb25zdCB0ZXhOdW1DID0gaW5wdXRMYXlvdXQuaGVpZ2h0O1xuICAgIGNvbnN0IHNvdXJjZSA9IGBcbiAgICAgICAgICBmbG9hdCAke2Z1bmNOYW1lfShpbnQgcm93LCBpbnQgY29sLCBpbnQgZGVwdGgsXG4gICAgICAgICAgICBpbnQgZGVwdGgyLCBpbnQgZGVwdGgzLCBpbnQgZGVwdGg0KSB7XG4gICAgICAgICAgICBpbnQgaW5kZXggPSByb3cgKiAke3N0cmlkZTB9ICsgY29sICogJHtzdHJpZGUxfSArIGRlcHRoICogJHtzdHJpZGUyfSArXG4gICAgICAgICAgICBkZXB0aDIgKiAke3N0cmlkZTN9ICsgZGVwdGgzICogJHtzdHJpZGU0fSArIGRlcHRoNDtcbiAgICAgICAgICAgIHZlYzIgdXYgPSB1dkZyb21GbGF0KCR7dGV4TnVtUn0sICR7dGV4TnVtQ30sIGluZGV4KTtcbiAgICAgICAgICAgIHJldHVybiBzYW1wbGVUZXh0dXJlKCR7bmFtZX0sIHV2KTtcbiAgICAgICAgICB9XG4gICAgICAgIGA7XG4gICAgcmV0dXJuIG5ldyBHbHNsTGliUm91dGluZShcbiAgICAgICAgc291cmNlLCBbJ2Nvb3JkaW5hdGVzLnV2RnJvbUZsYXQnLCAnY29vcmRpbmF0ZXMuc2FtcGxlVGV4dHVyZScsICdjb29yZGluYXRlcy5jb29yZHNUb09mZnNldCddKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBUaGlzIGlzIHRoZSBtYWluIGZ1bmN0aW9uIHRvIG1hcCBmcm9tIHRoZSBnaXZlbiB0ZXh0dXJlIGNvb3JkaWFudGVzIChzLHQpXG4gICAqIHRvIGxvZ2ljYWwgaW5kaWNlcyBmb3IgdGhlIG91dHB1dFxuICAgKiBUaGVyZSB3aWxsIG9ubHkgYmUgb25lIHNpbmdsZSB2YXJpYXRpb24gb2YgdGhpc1xuICAgKiBBbHNvIHNlZSBjb29yZHNUb09mZnNldCBhbmQgb2Zmc2V0VG9JbmRpY2VzIGZvciBpbnB1dC1zcGVjaWZpYyB2ZXJzaW9uc1xuICAgKi9cbiAgcHJvdGVjdGVkIHRvVmVjKCk6IHtbbmFtZTogc3RyaW5nXTogR2xzbExpYlJvdXRpbmV9IHtcbiAgICBjb25zdCBvdXRwdXQgPSB0aGlzLmNvbnRleHQub3V0cHV0VGV4dHVyZUxheW91dDtcbiAgICBjb25zdCByYW5rID0gb3V0cHV0LnNoYXBlLmxlbmd0aDtcbiAgICBjb25zdCBzdHJpZGVzID0gb3V0cHV0LnN0cmlkZXM7XG4gICAgY29uc3QgeFNjYWxlID0gb3V0cHV0LndpZHRoO1xuICAgIGNvbnN0IHlTY2FsZSA9IG91dHB1dC5oZWlnaHQ7XG5cbiAgICBjb25zdCBzdHJpZGVzQmxvY2sgPSBbXTtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHJhbmsgLSAxOyArK2kpIHtcbiAgICAgIHN0cmlkZXNCbG9jay5wdXNoKGBcbiAgICAgICAgY1ske2l9XSA9IG9mZnNldCAvICR7c3RyaWRlc1tpXX07YCk7XG4gICAgICBzdHJpZGVzQmxvY2sucHVzaChgXG4gICAgICAgIG9mZnNldCAtPSBjWyR7aX1dICogJHtzdHJpZGVzW2ldfTtgKTtcbiAgICB9XG4gICAgc3RyaWRlc0Jsb2NrLnB1c2goYFxuICAgICAgICBjWyR7cmFuayAtIDF9XSA9IG9mZnNldDtgKTtcbiAgICBjb25zdCBib2R5ID0gYFxuICAgICAgdm9pZCB0b1ZlYyh2ZWMyIHRleENvb3Jkcywgb3V0IGludCBjWyR7cmFua31dKSB7XG4gICAgICAgIGludCBvZmZzZXQgPSBjb29yZHNUb09mZnNldCh0ZXhDb29yZHMsICR7eFNjYWxlfSwgJHt5U2NhbGV9KTtcbiAgICAgICAgJHtzdHJpZGVzQmxvY2suam9pbignJyl9XG4gICAgICB9XG4gICAgICB2b2lkIHRvVmVjKGludCBvZmZzZXQsIG91dCBpbnQgY1ske3Jhbmt9XSkge1xuICAgICAgICAke3N0cmlkZXNCbG9jay5qb2luKCcnKX1cbiAgICAgIH1cbiAgICBgO1xuICAgIHJldHVybiB7dG9WZWM6IG5ldyBHbHNsTGliUm91dGluZShib2R5LCBbJ2Nvb3JkaW5hdGVzLmNvb3Jkc1RvT2Zmc2V0J10pfTtcbiAgfVxuICAvKipcbiAgICogVGhlc2UgYXJlIHZhbHVlIGdldHRlciBmdW5jdGlvbnMgZ2VuZXJhdGVkIGZvciBlYWNoIGlucHV0XG4gICAqIEVhY2ggZnVuY3Rpb24gaXMgaGFyZHdpcmVkIHRvIHRoZSBuYW1lIGFuZCBkaW1lbnNpb25zIG9mIHRoZSBpbnB1dFxuICAgKiBBbiAnX1QnIHZhcmlhdGlvbiBpcyBhbHNvIHByb2R1Y2VkIHdoaWNoIGFjY2Vzc2VzIHZhbHVlcyBhcyBpZiB0aGVcbiAgICogaW5wdXQgd2FzIHRyYW5zcG9zZWRcbiAgICovXG4gIHByb3RlY3RlZCB2YWx1ZUZyb20oKToge1tuYW1lOiBzdHJpbmddOiBHbHNsTGliUm91dGluZX0ge1xuICAgIGNvbnN0IHJlc3VsdDoge1tuYW1lOiBzdHJpbmddOiBHbHNsTGliUm91dGluZX0gPSB7fTtcbiAgICB0aGlzLmNvbnRleHQucHJvZ3JhbUluZm8uaW5wdXROYW1lcy5mb3JFYWNoKChuYW1lLCBpKSA9PiB7XG4gICAgICBjb25zdCBsYXlvdXQgPSB0aGlzLmNvbnRleHQuaW5wdXRUZXh0dXJlTGF5b3V0c1tpXTtcbiAgICAgIGNvbnN0IHNoYXBlID0gbGF5b3V0LnVucGFja2VkU2hhcGUubGVuZ3RoID4gMCA/IGxheW91dC51bnBhY2tlZFNoYXBlIDogbGF5b3V0LnNoYXBlO1xuICAgICAgY29uc3QgcmFuayA9IHNoYXBlLmxlbmd0aDtcbiAgICAgIGxldCBmdW5jTmFtZSA9IGBfJHtuYW1lfWA7XG4gICAgICByZXN1bHRbZnVuY05hbWVdID0gbmV3IEdsc2xMaWJSb3V0aW5lKFxuICAgICAgICAgIHRoaXMuZ2V0VmFsdWVGcm9tU2luZ2xlKG5hbWUsIHJhbmssIGxheW91dC53aWR0aCwgbGF5b3V0LmhlaWdodCwgZmFsc2UpLFxuICAgICAgICAgIFtgc2hhcGVVdGlscy5pbmRpY2VzVG9PZmZzZXQke2Z1bmNOYW1lfWAsICdjb29yZGluYXRlcy5vZmZzZXRUb0Nvb3JkcycsICdmcmFnY29sb3IuZ2V0Q29sb3JBc0Zsb2F0J10pO1xuICAgICAgZnVuY05hbWUgPSBmdW5jTmFtZSArICdfVCc7XG4gICAgICByZXN1bHRbZnVuY05hbWVdID0gbmV3IEdsc2xMaWJSb3V0aW5lKFxuICAgICAgICAgIHRoaXMuZ2V0VmFsdWVGcm9tU2luZ2xlKG5hbWUsIHJhbmssIGxheW91dC53aWR0aCwgbGF5b3V0LmhlaWdodCwgdHJ1ZSksXG4gICAgICAgICAgW2BzaGFwZVV0aWxzLmluZGljZXNUb09mZnNldCR7ZnVuY05hbWV9YCwgJ2Nvb3JkaW5hdGVzLm9mZnNldFRvQ29vcmRzJywgJ2ZyYWdjb2xvci5nZXRDb2xvckFzRmxvYXQnXSk7XG4gICAgfSk7XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfVxuICAvKipcbiAgICogUHJvZHVjZXMgb25lIHZhbHVlIGdldHRlciBmdW5jdGlvbiBmb3IgdGhlIG5hbWUgYW5kIHJhbmsgZ2l2ZW5cbiAgICogSWYgYSB0cmFuc3Bvc2UgaXMgc2V0IHByb3BlciBvZmZzZXRUb0Nvb3JkcyBtYXBwaW5nIHdpbGwgYmUgdXNlZFxuICAgKiBAcGFyYW0gbmFtZSBuYW1lIG9mIHRoZSBmdW5jdGlvblxuICAgKiBAcGFyYW0gcmFuayByYW5rIG9mIHRoZSBpbnB1dFxuICAgKiBAcGFyYW0gdHJhbnNwb3NlIHdoZXRoZXIgb3Igbm90IHNob3VsZCBnZW5lcmF0ZSBhIHRyYW5zcG9zZSB2YXJpYXRpb25cbiAgICovXG4gIHByb3RlY3RlZCBnZXRWYWx1ZUZyb21TaW5nbGUodmFyTmFtZTogc3RyaW5nLCByYW5rOiBudW1iZXIsIHdpZHRoOiBudW1iZXIsIGhlaWdodDogbnVtYmVyLCB0cmFuc3Bvc2U6IGJvb2xlYW4pOlxuICAgICAgc3RyaW5nIHtcbiAgICBsZXQgbmFtZSA9IGBfJHt2YXJOYW1lfWA7XG4gICAgaWYgKHRyYW5zcG9zZSkge1xuICAgICAgbmFtZSA9IG5hbWUgKyAnX1QnO1xuICAgIH1cbiAgICBjb25zdCBnbHNsID0gZ2V0R2xzbCh0aGlzLmNvbnRleHQuZ2xDb250ZXh0LnZlcnNpb24pO1xuICAgIHJldHVybiBgXG4gICAgICAgIGZsb2F0ICR7bmFtZX0oaW50IG1bJHtyYW5rfV0pIHtcbiAgICAgICAgICBpbnQgb2Zmc2V0ID0gaW5kaWNlc1RvT2Zmc2V0JHtuYW1lfShtKTtcbiAgICAgICAgICB2ZWMyIGNvb3JkcyA9IG9mZnNldFRvQ29vcmRzKG9mZnNldCwgJHt3aWR0aH0sICR7aGVpZ2h0fSk7XG4gICAgICAgICAgZmxvYXQgdmFsdWUgPSBnZXRDb2xvckFzRmxvYXQoJHtnbHNsLnRleHR1cmUyRH0oJHt2YXJOYW1lfSwgY29vcmRzKSk7XG4gICAgICAgICAgcmV0dXJuIHZhbHVlO1xuICAgICAgICB9XG4gICAgICAgIGA7XG4gIH1cblxuICAvKipcbiAgICogUHJvZHVjZXMgYSBwYWNrZWQgdmFsdWUgZ2V0dGVyIGZ1bmN0aW9uIGZvciB0aGUgbmFtZSBhbmQgcmFuayBnaXZlblxuICAgKiBJZiBhIHRyYW5zcG9zZSBpcyBzZXQgcHJvcGVyIG9mZnNldFRvQ29vcmRzIG1hcHBpbmcgd2lsbCBiZSB1c2VkXG4gICAqIEBwYXJhbSBuYW1lIG5hbWUgb2YgdGhlIGZ1bmN0aW9uXG4gICAqIEBwYXJhbSByYW5rIHJhbmsgb2YgdGhlIGlucHV0XG4gICAqIEBwYXJhbSB0cmFuc3Bvc2Ugd2hldGhlciBvciBub3Qgc2hvdWxkIGdlbmVyYXRlIGEgdHJhbnNwb3NlIHZhcmlhdGlvblxuICAgKi9cbiAgcHJvdGVjdGVkIGdldFBhY2tlZFZhbHVlRnJvbSh2YXJOYW1lOiBzdHJpbmcsIHJhbms6IG51bWJlciwgd2lkdGg6IG51bWJlciwgaGVpZ2h0OiBudW1iZXIsIHRyYW5zcG9zZTogYm9vbGVhbik6XG4gICAgICBzdHJpbmcge1xuICAgIGxldCBuYW1lID0gYF8ke3Zhck5hbWV9X1BhY2tgO1xuICAgIGlmICh0cmFuc3Bvc2UpIHtcbiAgICAgIG5hbWUgPSBuYW1lICsgJ19UJztcbiAgICB9XG4gICAgY29uc3QgZ2xzbCA9IGdldEdsc2wodGhpcy5jb250ZXh0LmdsQ29udGV4dC52ZXJzaW9uKTtcbiAgICByZXR1cm4gYFxuICAgICAgICB2ZWM0ICR7bmFtZX0oaW50IG1bJHtyYW5rfV0pIHtcbiAgICAgICAgICBpbnQgb2Zmc2V0ID0gaW5kaWNlc1RvT2Zmc2V0XyR7dmFyTmFtZX0obSk7XG4gICAgICAgICAgdmVjMiBjb29yZHMgPSBvZmZzZXRUb0Nvb3JkcyhvZmZzZXQsICR7d2lkdGh9LCAke2hlaWdodH0pO1xuICAgICAgICAgIHJldHVybiAke2dsc2wudGV4dHVyZTJEfSgke3Zhck5hbWV9LCBjb29yZHMpO1xuICAgICAgICB9XG4gICAgICAgIGA7XG4gIH1cbn1cbiIsIi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxuXG5pbXBvcnQge1Byb2dyYW1JbmZvLCBUZXh0dXJlTGF5b3V0fSBmcm9tICcuL3R5cGVzJztcbmltcG9ydCB7V2ViR0xDb250ZXh0fSBmcm9tICcuL3dlYmdsLWNvbnRleHQnO1xuXG4vKiBlc2xpbnQtZGlzYWJsZSBAdHlwZXNjcmlwdC1lc2xpbnQvbmFtaW5nLWNvbnZlbnRpb24gKi9cbmV4cG9ydCBlbnVtIEZ1bmN0aW9uVHlwZSB7XG4gIFZhbHVlQmFzZWQsXG4gIFBvc2l0aW9uYWxcbn1cbmV4cG9ydCBpbnRlcmZhY2UgR2xzbEZ1bmN0aW9uPFQgZXh0ZW5kcyBGdW5jdGlvblR5cGU+IHtcbiAgYm9keTogc3RyaW5nO1xuICBuYW1lOiBzdHJpbmc7XG4gIHR5cGU6IFQ7XG59XG5leHBvcnQgdHlwZSBHbHNsVmFsdWVGdW5jdGlvbiA9IEdsc2xGdW5jdGlvbjxGdW5jdGlvblR5cGUuVmFsdWVCYXNlZD47XG5leHBvcnQgaW50ZXJmYWNlIEdsc2xQb3NpdGlvbmFsRnVuY3Rpb24gZXh0ZW5kcyBHbHNsRnVuY3Rpb248RnVuY3Rpb25UeXBlLlBvc2l0aW9uYWw+IHtcbiAgaW5wdXRTaGFwZTogcmVhZG9ubHkgbnVtYmVyW107XG4gIG91dHB1dFNoYXBlOiByZWFkb25seSBudW1iZXJbXTtcbn1cblxuZXhwb3J0IGNsYXNzIEdsc2xDb250ZXh0IHtcbiAgY29uc3RydWN0b3IoXG4gICAgICBwdWJsaWMgZ2xDb250ZXh0OiBXZWJHTENvbnRleHQsIHB1YmxpYyBwcm9ncmFtSW5mbzogUHJvZ3JhbUluZm8sIHB1YmxpYyBpbnB1dFRleHR1cmVMYXlvdXRzOiBUZXh0dXJlTGF5b3V0W10sXG4gICAgICBwdWJsaWMgb3V0cHV0VGV4dHVyZUxheW91dDogVGV4dHVyZUxheW91dCkge31cbn1cbmV4cG9ydCBhYnN0cmFjdCBjbGFzcyBHbHNsTGliIHtcbiAgY29uc3RydWN0b3IocHVibGljIGNvbnRleHQ6IEdsc2xDb250ZXh0KSB7fVxuICBhYnN0cmFjdCBnZXRGdW5jdGlvbnMoKToge1tuYW1lOiBzdHJpbmddOiBHbHNsTGliUm91dGluZX07XG4gIGFic3RyYWN0IGdldEN1c3RvbVR5cGVzKCk6IHtbbmFtZTogc3RyaW5nXTogc3RyaW5nfTtcbn1cblxuLy8gYWJzdHJhY3Rpb24gdG8gcmVwcmVzZW50IGEgR0xTTCBsaWJyYXJ5IHJvdXRpbmUgYW5kIGl0J3MgZGVwZW5kZW5jaWVzXG5leHBvcnQgY2xhc3MgR2xzbExpYlJvdXRpbmUge1xuICBjb25zdHJ1Y3RvcihwdWJsaWMgcm91dGluZUJvZHk6IHN0cmluZywgcHVibGljIGRlcGVuZGVuY2llcz86IHN0cmluZ1tdKSB7fVxufVxuXG4vLyBhYnN0cmFjdGlvbiB0byByZXByZXNlbnQgYSBHTFNMIGxpYnJhcnkgcm91dGluZSBhbmQgaXQncyBkZXBlbmRlbmNpZXMgQVMgR1JBUEggTm9kZXNcbi8vIHRoaXMgbGV2ZWwgb2YgYWJzdHJhY3Rpb24gaXMgdXNlZCB0byB0b3BvbG9naWNhbGx5IHNvcnQgcm91dGluZXMgYmVmb3JlIGZyYWdtZW50IHNoYWRlIGluY2x1c2lvblxuZXhwb3J0IGNsYXNzIEdsc2xMaWJSb3V0aW5lTm9kZSB7XG4gIGRlcGVuZGVuY2llczogR2xzbExpYlJvdXRpbmVOb2RlW107XG4gIHJvdXRpbmVCb2R5OiBzdHJpbmc7XG4gIGNvbnN0cnVjdG9yKHB1YmxpYyBuYW1lOiBzdHJpbmcsIHJvdXRpbmVCb2R5Pzogc3RyaW5nLCBkZXBlbmRlbmNpZXM/OiBHbHNsTGliUm91dGluZU5vZGVbXSkge1xuICAgIGlmIChkZXBlbmRlbmNpZXMpIHtcbiAgICAgIHRoaXMuZGVwZW5kZW5jaWVzID0gZGVwZW5kZW5jaWVzO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLmRlcGVuZGVuY2llcyA9IFtdO1xuICAgIH1cblxuICAgIGlmIChyb3V0aW5lQm9keSkge1xuICAgICAgdGhpcy5yb3V0aW5lQm9keSA9IHJvdXRpbmVCb2R5O1xuICAgIH1cbiAgfVxuICBhZGREZXBlbmRlbmN5KG5vZGU6IEdsc2xMaWJSb3V0aW5lTm9kZSkge1xuICAgIGlmIChub2RlKSB7XG4gICAgICB0aGlzLmRlcGVuZGVuY2llcy5wdXNoKG5vZGUpO1xuICAgIH1cbiAgfVxufVxuXG4vLyB0b3BvbG9naWNhbGx5IHNvcnQgR0xTTCBsaWJyYXJ5IHJvdXRpbmVzIChncmFwaCBub2RlcyBhYnN0cmFjdGlvbikgYmVmb3JlIHNoYWRlciBzY3JpcHQgaW5jbHVzaW9uXG5leHBvcnQgY2xhc3MgVG9wb2xvZ2ljYWxTb3J0R2xzbFJvdXRpbmVzIHtcbiAgc3RhdGljIHJldHVybk9yZGVyZWROb2Rlcyhub2RlczogR2xzbExpYlJvdXRpbmVOb2RlW10pOiBHbHNsTGliUm91dGluZU5vZGVbXSB7XG4gICAgaWYgKCFub2RlcyB8fCBub2Rlcy5sZW5ndGggPT09IDApIHtcbiAgICAgIHJldHVybiBbXTtcbiAgICB9XG5cbiAgICBpZiAobm9kZXMubGVuZ3RoID09PSAxKSB7XG4gICAgICByZXR1cm4gbm9kZXM7XG4gICAgfVxuXG4gICAgY29uc3QgY3ljbGVDaGVjayA9IG5ldyBTZXQ8c3RyaW5nPigpO1xuICAgIGNvbnN0IGFscmVhZHlUcmF2ZXJzZWQgPSBuZXcgU2V0PHN0cmluZz4oKTtcbiAgICBjb25zdCByZXN1bHQgPSBuZXcgQXJyYXk8R2xzbExpYlJvdXRpbmVOb2RlPigpO1xuXG4gICAgdGhpcy5jcmVhdGVPcmRlcmVkTm9kZXMobm9kZXMsIGN5Y2xlQ2hlY2ssIGFscmVhZHlUcmF2ZXJzZWQsIHJlc3VsdCk7XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfVxuXG4gIHByaXZhdGUgc3RhdGljIGNyZWF0ZU9yZGVyZWROb2RlcyhcbiAgICAgIGdyYXBoTm9kZXM6IEdsc2xMaWJSb3V0aW5lTm9kZVtdLCBjeWNsZUNoZWNrOiBTZXQ8c3RyaW5nPiwgYWxyZWFkeVRyYXZlcnNlZDogU2V0PHN0cmluZz4sXG4gICAgICByZXN1bHQ6IEdsc2xMaWJSb3V0aW5lTm9kZVtdKSB7XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBncmFwaE5vZGVzLmxlbmd0aDsgKytpKSB7XG4gICAgICB0aGlzLmRmc1RyYXZlcnNlKGdyYXBoTm9kZXNbaV0sIGN5Y2xlQ2hlY2ssIGFscmVhZHlUcmF2ZXJzZWQsIHJlc3VsdCk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBzdGF0aWMgZGZzVHJhdmVyc2UoXG4gICAgICByb290OiBHbHNsTGliUm91dGluZU5vZGUsIGN5Y2xlQ2hlY2s6IFNldDxzdHJpbmc+LCBhbHJlYWR5VHJhdmVyc2VkOiBTZXQ8c3RyaW5nPiwgcmVzdWx0OiBHbHNsTGliUm91dGluZU5vZGVbXSkge1xuICAgIC8vIGlmIHRoaXMgcm9vdCBoYXMgYWxyZWFkeSBiZWVuIHRyYXZlcnNlZCByZXR1cm5cbiAgICBpZiAoIXJvb3QgfHwgYWxyZWFkeVRyYXZlcnNlZC5oYXMocm9vdC5uYW1lKSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIC8vIGN5Y2xpYyBkZXBlbmRlbmN5IGhhcyBiZWVuIGRldGVjdGVkXG4gICAgaWYgKGN5Y2xlQ2hlY2suaGFzKHJvb3QubmFtZSkpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignQ3ljbGljIGRlcGVuZGVuY3kgZGV0ZWN0ZWQuIENhblxcJ3QgdG9wb2xvZ2ljYWxseSBzb3J0IHJvdXRpbmVzIG5lZWRlZCBmb3Igc2hhZGVyLicpO1xuICAgIH1cblxuICAgIC8vIGhvbGQgdGhpcyBub2RlIHRvIGRldGVjdCBjeWNsZXMgaWYgYW55XG4gICAgY3ljbGVDaGVjay5hZGQocm9vdC5uYW1lKTtcblxuICAgIC8vIHRyYXZlcnNlIGNoaWxkcmVuIGluIGEgZGZzIGZhc2hpb25cbiAgICBjb25zdCBkZXBlbmRlbmNpZXMgPSByb290LmRlcGVuZGVuY2llcztcbiAgICBpZiAoZGVwZW5kZW5jaWVzICYmIGRlcGVuZGVuY2llcy5sZW5ndGggPiAwKSB7XG4gICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGRlcGVuZGVuY2llcy5sZW5ndGg7ICsraSkge1xuICAgICAgICB0aGlzLmRmc1RyYXZlcnNlKGRlcGVuZGVuY2llc1tpXSwgY3ljbGVDaGVjaywgYWxyZWFkeVRyYXZlcnNlZCwgcmVzdWx0KTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBhZGQgdG8gcmVzdWx0IGhvbGRlclxuICAgIHJlc3VsdC5wdXNoKHJvb3QpO1xuXG4gICAgLy8gbWFyayB0aGlzIG5vZGUgYXMgdHJhdmVyc2VkIHNvIHRoYXQgd2UgZG9uJ3QgdHJhdmVyc2UgZnJvbSB0aGlzIGFnYWluXG4gICAgYWxyZWFkeVRyYXZlcnNlZC5hZGQocm9vdC5uYW1lKTtcblxuICAgIC8vIHJlbGVhc2UgdGhlIGhvbGRcbiAgICBjeWNsZUNoZWNrLmRlbGV0ZShyb290Lm5hbWUpO1xuICB9XG59XG4iLCIvLyBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cblxuaW1wb3J0IHtHbHNsQ29udGV4dCwgR2xzbExpYiwgR2xzbExpYlJvdXRpbmV9IGZyb20gJy4vZ2xzbC1kZWZpbml0aW9ucyc7XG5cbi8qKlxuICogVGhpcyBHTFNMIGxpYnJhcnkgaGFuZGxlcyByb3V0aW5lcyBjb252ZXJ0aW5nXG4gKiBmbG9hdDMyIHRvL2Zyb20gVW5zaWduZWQgYnl0ZSBvciBmbG9hdCAxNlxuICovXG5leHBvcnQgY2xhc3MgRW5jb2RpbmdHbHNsTGliIGV4dGVuZHMgR2xzbExpYiB7XG4gIGNvbnN0cnVjdG9yKGNvbnRleHQ6IEdsc2xDb250ZXh0KSB7XG4gICAgc3VwZXIoY29udGV4dCk7XG4gIH1cbiAgZ2V0RnVuY3Rpb25zKCk6IHtbbmFtZTogc3RyaW5nXTogR2xzbExpYlJvdXRpbmV9IHtcbiAgICByZXR1cm4gey4uLnRoaXMuZW5jb2RlRmxvYXQzMigpLCAuLi50aGlzLmRlY29kZUZsb2F0MzIoKX07XG4gIH1cbiAgZ2V0Q3VzdG9tVHlwZXMoKToge1tuYW1lOiBzdHJpbmddOiBzdHJpbmd9IHtcbiAgICByZXR1cm4ge307XG4gIH1cbiAgcHJvdGVjdGVkIGVuY29kZUZsb2F0MzIoKToge1tuYW1lOiBzdHJpbmddOiBHbHNsTGliUm91dGluZX0ge1xuICAgIHJldHVybiB7XG4gICAgICBlbmNvZGU6IG5ldyBHbHNsTGliUm91dGluZShgaGlnaHAgdmVjNCBlbmNvZGUoaGlnaHAgZmxvYXQgZikge1xuICAgICAgICByZXR1cm4gdmVjNChmLCAwLjAsIDAuMCwgMC4wKTtcbiAgICAgIH1cbiAgICAgICAgYClcbiAgICB9O1xuICB9XG4gIHByb3RlY3RlZCBkZWNvZGVGbG9hdDMyKCk6IHtbbmFtZTogc3RyaW5nXTogR2xzbExpYlJvdXRpbmV9IHtcbiAgICByZXR1cm4ge1xuICAgICAgZGVjb2RlOiBuZXcgR2xzbExpYlJvdXRpbmUoYGhpZ2hwIGZsb2F0IGRlY29kZShoaWdocCB2ZWM0IHJnYmEpIHtcbiAgICAgICAgcmV0dXJuIHJnYmEucjtcbiAgICAgIH1cbiAgICAgICAgYClcbiAgICB9O1xuICB9XG4gIC8qKlxuICAgKiByZXR1cm5zIHRoZSByb3V0aW5lIHRvIGVuY29kZSBlbmNvZGUgYSAzMmJpdCBmbG9hdCB0byBhIHZlYzQgKG9mIHVuc2lnbmVkIGJ5dGVzKVxuICAgKiBAY3JlZGl0OiBodHRwczovL3N0YWNrb3ZlcmZsb3cuY29tL3F1ZXN0aW9ucy83MDU5OTYyL2hvdy1kby1pLWNvbnZlcnQtYS12ZWM0LXJnYmEtdmFsdWUtdG8tYS1mbG9hdFxuICAgKi9cbiAgcHJvdGVjdGVkIGVuY29kZVVpbnQ4KCk6IHtbbmFtZTogc3RyaW5nXTogR2xzbExpYlJvdXRpbmV9IHtcbiAgICBjb25zdCBlbmRpYW5uZXNzID0gRW5jb2RpbmdHbHNsTGliLmlzTGl0dGxlRW5kaWFuKCkgPyAncmdiYS5yZ2JhPXJnYmEuYWJncjsnIDogJyc7XG4gICAgcmV0dXJuIHtcbiAgICAgIGVuY29kZTogbmV3IEdsc2xMaWJSb3V0aW5lKGBcbiAgICAgIGhpZ2hwIHZlYzQgZW5jb2RlKGhpZ2hwIGZsb2F0IGYpIHtcbiAgICAgICAgaGlnaHAgZmxvYXQgRiA9IGFicyhmKTtcbiAgICAgICAgaGlnaHAgZmxvYXQgU2lnbiA9IHN0ZXAoMC4wLC1mKTtcbiAgICAgICAgaGlnaHAgZmxvYXQgRXhwb25lbnQgPSBmbG9vcihsb2cyKEYpKTtcbiAgICAgICAgaGlnaHAgZmxvYXQgTWFudGlzc2EgPSAoZXhwMigtIEV4cG9uZW50KSAqIEYpO1xuICAgICAgICBFeHBvbmVudCA9IGZsb29yKGxvZzIoRikgKyAxMjcuMCkgKyBmbG9vcihsb2cyKE1hbnRpc3NhKSk7XG4gICAgICAgIGhpZ2hwIHZlYzQgcmdiYTtcbiAgICAgICAgcmdiYVswXSA9IDEyOC4wICogU2lnbiAgKyBmbG9vcihFeHBvbmVudCpleHAyKC0xLjApKTtcbiAgICAgICAgcmdiYVsxXSA9IDEyOC4wICogbW9kKEV4cG9uZW50LDIuMCkgKyBtb2QoZmxvb3IoTWFudGlzc2EqMTI4LjApLDEyOC4wKTtcbiAgICAgICAgcmdiYVsyXSA9IGZsb29yKG1vZChmbG9vcihNYW50aXNzYSpleHAyKDIzLjAgLTguMCkpLGV4cDIoOC4wKSkpO1xuICAgICAgICByZ2JhWzNdID0gZmxvb3IoZXhwMigyMy4wKSptb2QoTWFudGlzc2EsZXhwMigtMTUuMCkpKTtcbiAgICAgICAgJHtlbmRpYW5uZXNzfVxuICAgICAgICByZ2JhID0gcmdiYSAvIDI1NS4wOyAvLyB2YWx1ZXMgbmVlZCB0byBiZSBub3JtYWxpemVkIHRvIFswLDFdXG4gICAgICAgIHJldHVybiByZ2JhO1xuICAgIH1cbiAgICAgICAgYClcbiAgICB9O1xuICB9XG4gIC8qKlxuICAgKiByZXR1cm5zIHRoZSByb3V0aW5lIHRvIGVuY29kZSBhIHZlYzQgb2YgdW5zaWduZWQgYnl0ZXMgdG8gZmxvYXQzMlxuICAgKiBAY3JlZGl0OiBodHRwczovL3N0YWNrb3ZlcmZsb3cuY29tL3F1ZXN0aW9ucy83MDU5OTYyL2hvdy1kby1pLWNvbnZlcnQtYS12ZWM0LXJnYmEtdmFsdWUtdG8tYS1mbG9hdFxuICAgKi9cbiAgcHJvdGVjdGVkIGRlY29kZVVpbnQ4KCk6IHtbbmFtZTogc3RyaW5nXTogR2xzbExpYlJvdXRpbmV9IHtcbiAgICBjb25zdCBlbmRpYW5uZXNzID0gRW5jb2RpbmdHbHNsTGliLmlzTGl0dGxlRW5kaWFuKCkgPyAncmdiYS5yZ2JhPXJnYmEuYWJncjsnIDogJyc7XG4gICAgcmV0dXJuIHtcbiAgICAgIGRlY29kZTogbmV3IEdsc2xMaWJSb3V0aW5lKGBcbiAgICAgICAgaGlnaHAgZmxvYXQgZGVjb2RlKGhpZ2hwIHZlYzQgcmdiYSkge1xuICAgICAgICAgIHJnYmEgPSByZ2JhICogMjU1LjA7IC8vIHZhbHVlcyBuZWVkIHRvIGJlIGRlLW5vcm1hbGl6ZWQgZnJvbSBbMCwxXSB0byBbMCwyNTVdXG4gICAgICAgICAgJHtlbmRpYW5uZXNzfVxuICAgICAgICAgIGhpZ2hwIGZsb2F0IFNpZ24gPSAxLjAgLSBzdGVwKDEyOC4wLHJnYmFbMF0pKjIuMDtcbiAgICAgICAgICBoaWdocCBmbG9hdCBFeHBvbmVudCA9IDIuMCAqIG1vZChyZ2JhWzBdLDEyOC4wKSArIHN0ZXAoMTI4LjAscmdiYVsxXSkgLSAxMjcuMDtcbiAgICAgICAgICBoaWdocCBmbG9hdCBNYW50aXNzYSA9IG1vZChyZ2JhWzFdLDEyOC4wKSo2NTUzNi4wICsgcmdiYVsyXSoyNTYuMCArcmdiYVszXSArIGZsb2F0KDB4ODAwMDAwKTtcbiAgICAgICAgICBoaWdocCBmbG9hdCBSZXN1bHQgPSAgU2lnbiAqIGV4cDIoRXhwb25lbnQpICogKE1hbnRpc3NhICogZXhwMigtMjMuMCApKTtcbiAgICAgICAgICByZXR1cm4gUmVzdWx0O1xuICAgICAgfVxuICAgICAgICBgKVxuICAgIH07XG4gIH1cbiAgLyoqXG4gICAqIERldGVybWluZXMgaWYgdGhlIG1hY2hpbmUgaXMgbGl0dGxlIGVuZGlhbiBvciBub3RcbiAgICogQGNyZWRpdDogaHR0cHM6Ly9naXN0LmdpdGh1Yi5jb20vVG9vVGFsbE5hdGUvNDc1MDk1M1xuICAgKi9cbiAgc3RhdGljIGlzTGl0dGxlRW5kaWFuKCk6IGJvb2xlYW4ge1xuICAgIGNvbnN0IGIgPSBuZXcgQXJyYXlCdWZmZXIoNCk7XG4gICAgY29uc3QgYSA9IG5ldyBVaW50MzJBcnJheShiKTtcbiAgICBjb25zdCBjID0gbmV3IFVpbnQ4QXJyYXkoYik7XG4gICAgYVswXSA9IDB4ZGVhZGJlZWY7XG4gICAgaWYgKGNbMF0gPT09IDB4ZWYpIHtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgICBpZiAoY1swXSA9PT0gMHhkZSkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICB0aHJvdyBuZXcgRXJyb3IoJ3Vua25vd24gZW5kaWFubmVzcycpO1xuICB9XG59XG4iLCIvLyBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cblxuaW1wb3J0IHtHbHNsQ29udGV4dCwgR2xzbExpYiwgR2xzbExpYlJvdXRpbmV9IGZyb20gJy4vZ2xzbC1kZWZpbml0aW9ucyc7XG5pbXBvcnQge2dldEdsc2x9IGZyb20gJy4vZ2xzbC1zb3VyY2UnO1xuXG4vKipcbiAqIFRoaXMgR0xTTCBsaWJyYXJ5IGhhbmRsZXMgcm91dGluZXMgYXJvdW5kIHJlYWRpbmcgYSB0ZXhsZXQgYW5kIHdyaXRpbmcgdG8gaXRcbiAqIFJlYWRpbmcgYW5kIHdyaXRpbmcgY291bGQgYmUgbW9yZSB0aGFuIGp1c3QgZGVhbGluZyB3aXRoIG9uZSBjaGFubmVsXG4gKiBJdCBtYXkgcmVxdWlyZSBlbmNvZGluZy9kZWNvZGluZyB0by9mcm9tIDQgY2hhbm5lbHMgaW50byBvbmVcbiAqL1xuZXhwb3J0IGNsYXNzIEZyYWdDb2xvckdsc2xMaWIgZXh0ZW5kcyBHbHNsTGliIHtcbiAgY29uc3RydWN0b3IoY29udGV4dDogR2xzbENvbnRleHQpIHtcbiAgICBzdXBlcihjb250ZXh0KTtcbiAgfVxuICBnZXRGdW5jdGlvbnMoKToge1tuYW1lOiBzdHJpbmddOiBHbHNsTGliUm91dGluZX0ge1xuICAgIHJldHVybiB7Li4udGhpcy5zZXRGcmFnQ29sb3IoKSwgLi4udGhpcy5nZXRDb2xvckFzRmxvYXQoKX07XG4gIH1cbiAgZ2V0Q3VzdG9tVHlwZXMoKToge1tuYW1lOiBzdHJpbmddOiBzdHJpbmd9IHtcbiAgICByZXR1cm4ge307XG4gIH1cbiAgcHJvdGVjdGVkIHNldEZyYWdDb2xvcigpOiB7W25hbWU6IHN0cmluZ106IEdsc2xMaWJSb3V0aW5lfSB7XG4gICAgY29uc3QgZ2xzbCA9IGdldEdsc2wodGhpcy5jb250ZXh0LmdsQ29udGV4dC52ZXJzaW9uKTtcbiAgICByZXR1cm4ge1xuICAgICAgc2V0RnJhZ0NvbG9yOiBuZXcgR2xzbExpYlJvdXRpbmUoXG4gICAgICAgICAgYFxuICAgICAgICB2b2lkIHNldEZyYWdDb2xvcihmbG9hdCB2YWx1ZSkge1xuICAgICAgICAgICAgJHtnbHNsLm91dHB1dH0gPSBlbmNvZGUodmFsdWUpO1xuICAgICAgICB9XG4gICAgICAgIGAsXG4gICAgICAgICAgWydlbmNvZGluZy5lbmNvZGUnXSlcbiAgICB9O1xuICB9XG4gIHByb3RlY3RlZCBnZXRDb2xvckFzRmxvYXQoKToge1tuYW1lOiBzdHJpbmddOiBHbHNsTGliUm91dGluZX0ge1xuICAgIHJldHVybiB7XG4gICAgICBnZXRDb2xvckFzRmxvYXQ6IG5ldyBHbHNsTGliUm91dGluZShcbiAgICAgICAgICBgXG4gICAgICAgIGZsb2F0IGdldENvbG9yQXNGbG9hdCh2ZWM0IGNvbG9yKSB7XG4gICAgICAgICAgICByZXR1cm4gZGVjb2RlKGNvbG9yKTtcbiAgICAgICAgfVxuICAgICAgICBgLFxuICAgICAgICAgIFsnZW5jb2RpbmcuZGVjb2RlJ10pXG4gICAgfTtcbiAgfVxufVxuIiwiLy8gQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXG5cbmNvbnN0IElOTElORV9GVU5DX0RFRl9SRUdFWCA9IC9AaW5saW5lW1xcc1xcblxccl0rKFxcdyspW1xcc1xcblxccl0rKFswLTlhLXpBLVpfXSspXFxzKlxcKChbXildKilcXClcXHMqeygoW159XXxbXFxuXFxyXSkqKX0vZ207XG5jb25zdCBGVU5DX0NBTExfUkVHRVggPSAnKFxcXFx3Kyk/XFxcXHMrKFtfMC05YS16QS1aXSspXFxcXHMrPVxcXFxzK19fRlVOQ19fXFxcXCgoLiopXFxcXClcXFxccyo7Jztcbi8qKlxuICogR0xTTCBwcmVwcm9jZXNzb3IgcmVzcG9uc2libGUgZm9yIHJlc29sdmluZyBAaW5saW5lIGRpcmVjdGl2ZXNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJlcGxhY2VJbmxpbmVzKHNjcmlwdDogc3RyaW5nKTogc3RyaW5nIHtcbiAgY29uc3QgaW5saW5lRGVmczoge1tuYW1lOiBzdHJpbmddOiB7cGFyYW1zOiBBcnJheTx7dHlwZTogc3RyaW5nOyBuYW1lOiBzdHJpbmd9fG51bGw+OyBib2R5OiBzdHJpbmd9fSA9IHt9O1xuICBsZXQgbWF0Y2g7XG4gIHdoaWxlICgobWF0Y2ggPSBJTkxJTkVfRlVOQ19ERUZfUkVHRVguZXhlYyhzY3JpcHQpKSAhPT0gbnVsbCkge1xuICAgIGNvbnN0IHBhcmFtcyA9IG1hdGNoWzNdXG4gICAgICAgICAgICAgICAgICAgICAgIC5zcGxpdCgnLCcpXG4gICAgICAgICAgICAgICAgICAgICAgIC5tYXAocyA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgdG9rZW5zID0gcy50cmltKCkuc3BsaXQoJyAnKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICBpZiAodG9rZW5zICYmIHRva2Vucy5sZW5ndGggPT09IDIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB7dHlwZTogdG9rZW5zWzBdLCBuYW1lOiB0b2tlbnNbMV19O1xuICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAgICAgICAgLmZpbHRlcih2ID0+IHYgIT09IG51bGwpO1xuICAgIGlubGluZURlZnNbbWF0Y2hbMl1dID0ge3BhcmFtcywgYm9keTogbWF0Y2hbNF19O1xuICB9XG4gIGZvciAoY29uc3QgbmFtZSBpbiBpbmxpbmVEZWZzKSB7XG4gICAgY29uc3QgcmVnZXhTdHJpbmcgPSBGVU5DX0NBTExfUkVHRVgucmVwbGFjZSgnX19GVU5DX18nLCBuYW1lKTtcbiAgICBjb25zdCByZWdleCA9IG5ldyBSZWdFeHAocmVnZXhTdHJpbmcsICdnbScpO1xuICAgIHdoaWxlICgobWF0Y2ggPSByZWdleC5leGVjKHNjcmlwdCkpICE9PSBudWxsKSB7XG4gICAgICBjb25zdCB0eXBlID0gbWF0Y2hbMV07XG4gICAgICBjb25zdCB2YXJpYWJsZSA9IG1hdGNoWzJdO1xuICAgICAgY29uc3QgcGFyYW1zID0gbWF0Y2hbM10uc3BsaXQoJywnKTtcbiAgICAgIGNvbnN0IGRlY2xMaW5lID0gKHR5cGUpID8gYCR7dHlwZX0gJHt2YXJpYWJsZX07YCA6ICcnO1xuICAgICAgbGV0IG5ld0JvZHk6IHN0cmluZyA9IGlubGluZURlZnNbbmFtZV0uYm9keTtcbiAgICAgIGxldCBwYXJhbVJlZGVjTGluZSA9ICcnO1xuICAgICAgaW5saW5lRGVmc1tuYW1lXS5wYXJhbXMuZm9yRWFjaCgodiwgaSkgPT4ge1xuICAgICAgICBpZiAodikge1xuICAgICAgICAgIHBhcmFtUmVkZWNMaW5lICs9IGAke3YudHlwZX0gJHt2Lm5hbWV9ID0gJHtwYXJhbXNbaV19O1xcbmA7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgICAgbmV3Qm9keSA9IGAke3BhcmFtUmVkZWNMaW5lfVxcbiAke25ld0JvZHl9YDtcbiAgICAgIG5ld0JvZHkgPSBuZXdCb2R5LnJlcGxhY2UoJ3JldHVybicsIGAke3ZhcmlhYmxlfSA9IGApO1xuICAgICAgY29uc3QgcmVwbGFjZW1lbnQgPSBgXG4gICAgICAke2RlY2xMaW5lfVxuICAgICAge1xuICAgICAgICAke25ld0JvZHl9XG4gICAgICB9XG4gICAgICBgO1xuICAgICAgc2NyaXB0ID0gc2NyaXB0LnJlcGxhY2UobWF0Y2hbMF0sIHJlcGxhY2VtZW50KTtcbiAgICB9XG4gIH1cbiAgc2NyaXB0ID0gc2NyaXB0LnJlcGxhY2UoSU5MSU5FX0ZVTkNfREVGX1JFR0VYLCAnJyk7XG4gIHJldHVybiBzY3JpcHQ7XG59XG4iLCIvLyBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cblxuaW1wb3J0IHtHbHNsQ29udGV4dCwgR2xzbExpYiwgR2xzbExpYlJvdXRpbmVOb2RlLCBUb3BvbG9naWNhbFNvcnRHbHNsUm91dGluZXN9IGZyb20gJy4vZ2xzbC1kZWZpbml0aW9ucyc7XG5pbXBvcnQge3JlcGxhY2VJbmxpbmVzfSBmcm9tICcuL2dsc2wtZnVuY3Rpb24taW5saW5lcic7XG5pbXBvcnQge2dsc2xSZWdpc3RyeX0gZnJvbSAnLi9nbHNsLXJlZ2lzdGVyZWQtbGlicyc7XG5pbXBvcnQge2dldERlZmF1bHRGcmFnU2hhZGVyTWFpbiwgZ2V0RnJhZ1NoYWRlclByZWFtYmxlfSBmcm9tICcuL2dsc2wtc291cmNlJztcbmltcG9ydCB7UHJvZ3JhbUluZm8sIFRleHR1cmVMYXlvdXQsIFZhcmlhYmxlSW5mb30gZnJvbSAnLi90eXBlcyc7XG5pbXBvcnQge1dlYkdMQ29udGV4dH0gZnJvbSAnLi93ZWJnbC1jb250ZXh0JztcblxuLyoqXG4gKiBQcmVwcm9jZXNzb3IgZm9yIHRoZSBhZGRpdGlvbnMgdG8gdGhlIEdMU0wgbGFuZ3VhZ2VcbiAqIEl0IGRlYWxzIHdpdGg6XG4gKiAgQGluY2x1ZGUgZGlyZWN0aXZlc1xuICogIEBpbmxpbmVcbiAqICBMb29wIHVucm9sbGluZyAobm90IGltcGxlbWVudGVkKVxuICogIE1hY3JvIHJlc29sdXRpb24gKG5vdCBpbXBsZW1lbnRlZClcbiAqL1xuZXhwb3J0IGNsYXNzIEdsc2xQcmVwcm9jZXNzb3Ige1xuICByZWFkb25seSBjb250ZXh0OiBHbHNsQ29udGV4dDtcbiAgcmVhZG9ubHkgbGliczoge1tuYW1lOiBzdHJpbmddOiBHbHNsTGlifSA9IHt9O1xuICByZWFkb25seSBnbHNsTGliUm91dGluZURlcGVuZGVuY3lHcmFwaDoge1tyb3V0aW5lTmFtZTogc3RyaW5nXTogR2xzbExpYlJvdXRpbmVOb2RlfSA9IHt9O1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgICAgZ2xDb250ZXh0OiBXZWJHTENvbnRleHQsIHByb2dyYW1JbmZvOiBQcm9ncmFtSW5mbywgaW5wdXRUZXh0dXJlTGF5b3V0czogVGV4dHVyZUxheW91dFtdLFxuICAgICAgb3V0cHV0VGV4dHVyZUxheW91dDogVGV4dHVyZUxheW91dCkge1xuICAgIHRoaXMuY29udGV4dCA9IG5ldyBHbHNsQ29udGV4dChnbENvbnRleHQsIHByb2dyYW1JbmZvLCBpbnB1dFRleHR1cmVMYXlvdXRzLCBvdXRwdXRUZXh0dXJlTGF5b3V0KTtcblxuICAgIC8vIGNvbnN0cnVjdCBHbHNsTGlic1xuICAgIE9iamVjdC5rZXlzKGdsc2xSZWdpc3RyeSkuZm9yRWFjaCgobmFtZTogc3RyaW5nKSA9PiB7XG4gICAgICBjb25zdCBsaWIgPSBuZXcgZ2xzbFJlZ2lzdHJ5W25hbWVdKHRoaXMuY29udGV4dCk7XG4gICAgICB0aGlzLmxpYnNbbmFtZV0gPSBsaWI7XG4gICAgfSk7XG5cbiAgICAvLyBjb25zdHJ1Y3QgR2xzbFJvdXRpbmVEZXBlbmRlbmN5R3JhcGhcbiAgICBjb25zdCBtYXAgPSB0aGlzLmdsc2xMaWJSb3V0aW5lRGVwZW5kZW5jeUdyYXBoO1xuICAgIGZvciAoY29uc3QgbGliTmFtZSBpbiB0aGlzLmxpYnMpIHtcbiAgICAgIGNvbnN0IGxpYiA9IHRoaXMubGlic1tsaWJOYW1lXTtcbiAgICAgIGNvbnN0IHJvdXRpbmVzSW5MaWIgPSBsaWIuZ2V0RnVuY3Rpb25zKCk7XG4gICAgICBmb3IgKGNvbnN0IHJvdXRpbmUgaW4gcm91dGluZXNJbkxpYikge1xuICAgICAgICBjb25zdCBrZXkgPSBsaWJOYW1lICsgJy4nICsgcm91dGluZTtcbiAgICAgICAgbGV0IGN1cnJlbnROb2RlOiBHbHNsTGliUm91dGluZU5vZGU7XG4gICAgICAgIGlmIChtYXBba2V5XSkge1xuICAgICAgICAgIGN1cnJlbnROb2RlID0gbWFwW2tleV07XG4gICAgICAgICAgY3VycmVudE5vZGUucm91dGluZUJvZHkgPSByb3V0aW5lc0luTGliW3JvdXRpbmVdLnJvdXRpbmVCb2R5O1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGN1cnJlbnROb2RlID0gbmV3IEdsc2xMaWJSb3V0aW5lTm9kZShrZXksIHJvdXRpbmVzSW5MaWJbcm91dGluZV0ucm91dGluZUJvZHkpO1xuICAgICAgICAgIG1hcFtrZXldID0gY3VycmVudE5vZGU7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgZGVwZW5kZW5jaWVzID0gcm91dGluZXNJbkxpYltyb3V0aW5lXS5kZXBlbmRlbmNpZXM7XG4gICAgICAgIGlmIChkZXBlbmRlbmNpZXMpIHtcbiAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGRlcGVuZGVuY2llcy5sZW5ndGg7ICsraSkge1xuICAgICAgICAgICAgaWYgKCFtYXBbZGVwZW5kZW5jaWVzW2ldXSkge1xuICAgICAgICAgICAgICBjb25zdCBub2RlID0gbmV3IEdsc2xMaWJSb3V0aW5lTm9kZShkZXBlbmRlbmNpZXNbaV0pO1xuICAgICAgICAgICAgICBtYXBbZGVwZW5kZW5jaWVzW2ldXSA9IG5vZGU7XG4gICAgICAgICAgICAgIGN1cnJlbnROb2RlLmFkZERlcGVuZGVuY3kobm9kZSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICBjdXJyZW50Tm9kZS5hZGREZXBlbmRlbmN5KG1hcFtkZXBlbmRlbmNpZXNbaV1dKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBwcmVwcm9jZXNzKCk6IHN0cmluZyB7XG4gICAgY29uc3QgcHJvZ3JhbUluZm8gPSB0aGlzLmNvbnRleHQucHJvZ3JhbUluZm87XG4gICAgbGV0IHNvdXJjZSA9IHByb2dyYW1JbmZvLnNoYWRlclNvdXJjZTtcblxuICAgIC8vIGFwcGVuZCBtYWluKCkgZnVuY3Rpb25cbiAgICBpZiAoIXRoaXMuY29udGV4dC5wcm9ncmFtSW5mby5oYXNNYWluKSB7XG4gICAgICBzb3VyY2UgPSBgJHtzb3VyY2V9XG4gICAgICAke2dldERlZmF1bHRGcmFnU2hhZGVyTWFpbih0aGlzLmNvbnRleHQuZ2xDb250ZXh0LnZlcnNpb24sIHRoaXMuY29udGV4dC5vdXRwdXRUZXh0dXJlTGF5b3V0LnNoYXBlLmxlbmd0aCl9YDtcbiAgICB9XG4gICAgLy8gcmVwbGFjZSBpbmxpbmVzXG4gICAgc291cmNlID0gcmVwbGFjZUlubGluZXMoc291cmNlKTtcblxuICAgIC8vIGNvbmNhdCBmaW5hbCBzb3VyY2Ugc3RyaW5nXG4gICAgcmV0dXJuIGAke2dldEZyYWdTaGFkZXJQcmVhbWJsZSh0aGlzLmNvbnRleHQuZ2xDb250ZXh0LnZlcnNpb24pfVxuICAgICR7dGhpcy5nZXRVbmlmb3Jtcyhwcm9ncmFtSW5mby5pbnB1dE5hbWVzLCBwcm9ncmFtSW5mby52YXJpYWJsZXMpfVxuICAgICR7dGhpcy5nZXRJbXBvcnRzKHNvdXJjZSl9XG4gICAgJHtzb3VyY2V9YDtcbiAgfVxuXG4gIHByb3RlY3RlZCBnZXRJbXBvcnRzKHNjcmlwdDogc3RyaW5nKTogc3RyaW5nIHtcbiAgICBjb25zdCByb3V0aW5lc0luY2x1ZGVkID0gdGhpcy5zZWxlY3RHbHNsTGliUm91dGluZXNUb0JlSW5jbHVkZWQoc2NyaXB0KTtcblxuICAgIGlmIChyb3V0aW5lc0luY2x1ZGVkLmxlbmd0aCA9PT0gMCkge1xuICAgICAgcmV0dXJuICcnO1xuICAgIH1cblxuICAgIGxldCByb3V0aW5lcyA9ICcnO1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgcm91dGluZXNJbmNsdWRlZC5sZW5ndGg7ICsraSkge1xuICAgICAgaWYgKHJvdXRpbmVzSW5jbHVkZWRbaV0ucm91dGluZUJvZHkpIHtcbiAgICAgICAgcm91dGluZXMgKz0gcm91dGluZXNJbmNsdWRlZFtpXS5yb3V0aW5lQm9keSArICdcXG4nO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBNaXNzaW5nIGJvZHkgZm9yIHRoZSBHbHNsIExpYnJhcnkgcm91dGluZTogJHtyb3V0aW5lc0luY2x1ZGVkW2ldLm5hbWV9YCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHJvdXRpbmVzO1xuICB9XG4gIHByaXZhdGUgc2VsZWN0R2xzbExpYlJvdXRpbmVzVG9CZUluY2x1ZGVkKHNjcmlwdDogc3RyaW5nKTogR2xzbExpYlJvdXRpbmVOb2RlW10ge1xuICAgIGNvbnN0IG5vZGVzOiBHbHNsTGliUm91dGluZU5vZGVbXSA9IFtdO1xuXG4gICAgT2JqZWN0LmtleXModGhpcy5nbHNsTGliUm91dGluZURlcGVuZGVuY3lHcmFwaCkuZm9yRWFjaChjbGFzc0FuZFJvdXRpbmUgPT4ge1xuICAgICAgY29uc3Qgcm91dGluZSA9IGNsYXNzQW5kUm91dGluZS5zcGxpdCgnLicpWzFdO1xuICAgICAgaWYgKHNjcmlwdC5pbmRleE9mKHJvdXRpbmUpICE9PSAtMSkge1xuICAgICAgICBub2Rlcy5wdXNoKHRoaXMuZ2xzbExpYlJvdXRpbmVEZXBlbmRlbmN5R3JhcGhbY2xhc3NBbmRSb3V0aW5lXSk7XG4gICAgICB9XG4gICAgfSk7XG5cbiAgICByZXR1cm4gVG9wb2xvZ2ljYWxTb3J0R2xzbFJvdXRpbmVzLnJldHVybk9yZGVyZWROb2Rlcyhub2Rlcyk7XG4gIH1cblxuICBwcm90ZWN0ZWQgZ2V0VW5pZm9ybXMoc2FtcGxlcnM/OiBzdHJpbmdbXSwgdmFyaWFibGVzPzogVmFyaWFibGVJbmZvW10pOiBzdHJpbmcge1xuICAgIGNvbnN0IHVuaWZvcm1MaW5lczogc3RyaW5nW10gPSBbXTtcbiAgICBpZiAoc2FtcGxlcnMpIHtcbiAgICAgIGZvciAoY29uc3Qgc2FtcGxlciBvZiBzYW1wbGVycykge1xuICAgICAgICB1bmlmb3JtTGluZXMucHVzaChgdW5pZm9ybSBzYW1wbGVyMkQgJHtzYW1wbGVyfTtgKTtcbiAgICAgIH1cbiAgICB9XG4gICAgaWYgKHZhcmlhYmxlcykge1xuICAgICAgZm9yIChjb25zdCB2YXJpYWJsZSBvZiB2YXJpYWJsZXMpIHtcbiAgICAgICAgdW5pZm9ybUxpbmVzLnB1c2goXG4gICAgICAgICAgICBgdW5pZm9ybSAke3ZhcmlhYmxlLnR5cGV9ICR7dmFyaWFibGUubmFtZX0ke3ZhcmlhYmxlLmFycmF5TGVuZ3RoID8gYFske3ZhcmlhYmxlLmFycmF5TGVuZ3RofV1gIDogJyd9O2ApO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gdW5pZm9ybUxpbmVzLmpvaW4oJ1xcbicpO1xuICB9XG59XG4iLCIvLyBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cblxuaW1wb3J0IHtDb29yZHNHbHNsTGlifSBmcm9tICcuL2dsc2wtY29vcmRpbmF0ZS1saWInO1xuaW1wb3J0IHtHbHNsQ29udGV4dCwgR2xzbExpYn0gZnJvbSAnLi9nbHNsLWRlZmluaXRpb25zJztcbmltcG9ydCB7RW5jb2RpbmdHbHNsTGlifSBmcm9tICcuL2dsc2wtZW5jb2RpbmctbGliJztcbmltcG9ydCB7RnJhZ0NvbG9yR2xzbExpYn0gZnJvbSAnLi9nbHNsLWZyYWdjb2xvci1saWInO1xuaW1wb3J0IHtTaGFwZVV0aWxzR2xzbExpYn0gZnJvbSAnLi9nbHNsLXNoYXBlLXV0aWxzLWxpYic7XG5pbXBvcnQge1ZlY0dsc2xMaWJ9IGZyb20gJy4vZ2xzbC12ZWMtbGliJztcblxuZXhwb3J0IGNvbnN0IGdsc2xSZWdpc3RyeToge1tuYW1lOiBzdHJpbmddOiBuZXcgKGNvbnRleHQ6IEdsc2xDb250ZXh0KSA9PiBHbHNsTGlifSA9IHtcbiAgJ2VuY29kaW5nJzogRW5jb2RpbmdHbHNsTGliLFxuICAnZnJhZ2NvbG9yJzogRnJhZ0NvbG9yR2xzbExpYixcbiAgJ3ZlYyc6IFZlY0dsc2xMaWIsXG4gICdzaGFwZVV0aWxzJzogU2hhcGVVdGlsc0dsc2xMaWIsXG4gICdjb29yZGluYXRlcyc6IENvb3Jkc0dsc2xMaWIsXG4gIC8vICAnYXJyYXlzJzogQXJyYXlHbHNsU0xpYlxufTtcbiIsIi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxuXG5pbXBvcnQge0dsc2xDb250ZXh0LCBHbHNsTGliLCBHbHNsTGliUm91dGluZX0gZnJvbSAnLi9nbHNsLWRlZmluaXRpb25zJztcblxuLyoqXG4gKiBHTFNMIExpYnJhcnkgcmVzcG9uc2libGUgZm9yIGRhdGEgdHlwZXMgYW5kIHJvdXRpbmVzIGZvciBtYW5pcHVsYXRpbmdcbiAqIGNvb3JkaW5hdGVzIGFuZCBtYXBwaW5nIHRvL2Zyb20gdGVuc29yIGluZGljZXNcbiAqL1xuZXhwb3J0IGNsYXNzIFNoYXBlVXRpbHNHbHNsTGliIGV4dGVuZHMgR2xzbExpYiB7XG4gIGNvbnN0cnVjdG9yKGNvbnRleHQ6IEdsc2xDb250ZXh0KSB7XG4gICAgc3VwZXIoY29udGV4dCk7XG4gIH1cbiAgZ2V0RnVuY3Rpb25zKCk6IHtbbmFtZTogc3RyaW5nXTogR2xzbExpYlJvdXRpbmV9IHtcbiAgICByZXR1cm4ge1xuICAgICAgLi4udGhpcy5iY2FzdEluZGV4KCksXG4gICAgICAuLi50aGlzLmJjYXN0TWF0bXVsSW5kZXgoKSxcbiAgICAgIC4uLnRoaXMub2Zmc2V0VG9JbmRpY2VzKCksXG4gICAgICAuLi50aGlzLmluZGljZXNUb09mZnNldCgpLFxuICAgICAgLi4udGhpcy5pbmNyZW1lbnRJbmRpY2VzKClcbiAgICB9O1xuICB9XG4gIGdldEN1c3RvbVR5cGVzKCkge1xuICAgIHJldHVybiB7fTtcbiAgfVxuICBwcm90ZWN0ZWQgYmNhc3RJbmRleCgpOiB7W25hbWU6IHN0cmluZ106IEdsc2xMaWJSb3V0aW5lfSB7XG4gICAgY29uc3Qgb3V0cHV0UmFuayA9IHRoaXMuY29udGV4dC5vdXRwdXRUZXh0dXJlTGF5b3V0LnNoYXBlLmxlbmd0aDtcbiAgICBjb25zdCByZXN1bHQ6IHtbbmFtZTogc3RyaW5nXTogR2xzbExpYlJvdXRpbmV9ID0ge307XG4gICAgdGhpcy5jb250ZXh0LnByb2dyYW1JbmZvLmlucHV0TmFtZXMuZm9yRWFjaCgobmFtZSwgaSkgPT4ge1xuICAgICAgY29uc3Qgc2hhcGUgPSB0aGlzLmNvbnRleHQuaW5wdXRUZXh0dXJlTGF5b3V0c1tpXS51bnBhY2tlZFNoYXBlO1xuICAgICAgaWYgKHNoYXBlLmxlbmd0aCA8PSBvdXRwdXRSYW5rKSB7XG4gICAgICAgIGNvbnN0IHJhbmsgPSBzaGFwZS5sZW5ndGg7XG4gICAgICAgIGNvbnN0IGRpbU9mZnNldCA9IG91dHB1dFJhbmsgLSByYW5rO1xuICAgICAgICBjb25zdCBmdW5jTmFtZSA9IGBiY2FzdEluZGljZXNfJHtuYW1lfWA7XG4gICAgICAgIGxldCBibG9jayA9ICcnO1xuICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHJhbms7ICsraSkge1xuICAgICAgICAgIGJsb2NrICs9IGBcbiAgICAgICAgICByZWFsSW5kaWNlc1ske2l9XSA9IGludCggbW9kKGZsb2F0KGJjYXN0ZWRJbmRpY2VzWyR7ZGltT2Zmc2V0ICsgaX1dKSwgJHtzaGFwZVtpXX0uMCkgKTtcbiAgICAgICAgICBgO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IGJvZHkgPSBgXG4gICAgICAgIHZvaWQgJHtmdW5jTmFtZX0gKGludCBiY2FzdGVkSW5kaWNlc1ske291dHB1dFJhbmt9XSwgb3V0IGludCByZWFsSW5kaWNlc1ske3Jhbmt9XSkge1xuICAgICAgICAgICR7YmxvY2t9XG4gICAgICAgIH1cbiAgICAgICAgYDtcbiAgICAgICAgcmVzdWx0W2Z1bmNOYW1lXSA9IG5ldyBHbHNsTGliUm91dGluZShib2R5KTtcbiAgICAgIH1cbiAgICB9KTtcbiAgICByZXR1cm4gcmVzdWx0O1xuICB9XG4gIHByb3RlY3RlZCBiY2FzdE1hdG11bEluZGV4KCk6IHtbbmFtZTogc3RyaW5nXTogR2xzbExpYlJvdXRpbmV9IHtcbiAgICBjb25zdCBvdXRwdXRSYW5rID0gdGhpcy5jb250ZXh0Lm91dHB1dFRleHR1cmVMYXlvdXQuc2hhcGUubGVuZ3RoO1xuICAgIGNvbnN0IHJlc3VsdDoge1tuYW1lOiBzdHJpbmddOiBHbHNsTGliUm91dGluZX0gPSB7fTtcbiAgICB0aGlzLmNvbnRleHQucHJvZ3JhbUluZm8uaW5wdXROYW1lcy5mb3JFYWNoKChuYW1lLCBpKSA9PiB7XG4gICAgICBjb25zdCBzaGFwZSA9IHRoaXMuY29udGV4dC5pbnB1dFRleHR1cmVMYXlvdXRzW2ldLnNoYXBlO1xuICAgICAgaWYgKCEoc2hhcGUubGVuZ3RoIDwgMiB8fCBzaGFwZS5sZW5ndGggPiBvdXRwdXRSYW5rKSkge1xuICAgICAgICBjb25zdCByYW5rID0gc2hhcGUubGVuZ3RoO1xuICAgICAgICBjb25zdCBkaW1PZmZzZXQgPSBvdXRwdXRSYW5rIC0gcmFuaztcbiAgICAgICAgY29uc3QgZnVuY05hbWUgPSBgYmNhc3RNYXRtdWxJbmRpY2VzXyR7bmFtZX1gO1xuICAgICAgICBsZXQgYmxvY2sgPSAnJztcbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCByYW5rIC0gMjsgKytpKSB7XG4gICAgICAgICAgYmxvY2sgKz0gYFxuICAgICAgICAgIHJlYWxJbmRpY2VzWyR7aX1dID0gaW50KCBtb2QoZmxvYXQoYmNhc3RlZEluZGljZXNbJHtkaW1PZmZzZXQgKyBpfV0pLCAke3NoYXBlW2ldfS4wKSApO1xuICAgICAgICAgIGA7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgYm9keSA9IGBcbiAgICAgICAgdm9pZCAke2Z1bmNOYW1lfShpbnQgYmNhc3RlZEluZGljZXNbJHtvdXRwdXRSYW5rfV0sIG91dCBpbnQgcmVhbEluZGljZXNbJHtyYW5rfV0pIHtcbiAgICAgICAgICAke2Jsb2NrfVxuICAgICAgICAgIHJlYWxJbmRpY2VzWyR7cmFuayAtIDF9XSA9IGJjYXN0ZWRJbmRpY2VzWyR7b3V0cHV0UmFuayAtIDF9XTtcbiAgICAgICAgICByZWFsSW5kaWNlc1ske3JhbmsgLSAyfV0gPSBiY2FzdGVkSW5kaWNlc1ske291dHB1dFJhbmsgLSAyfV07XG4gICAgICAgIH1cbiAgICAgICAgYDtcbiAgICAgICAgcmVzdWx0W2Z1bmNOYW1lXSA9IG5ldyBHbHNsTGliUm91dGluZShib2R5KTtcbiAgICAgIH1cbiAgICB9KTtcbiAgICByZXR1cm4gcmVzdWx0O1xuICB9XG4gIHByb3RlY3RlZCBpbmRpY2VzVG9PZmZzZXQoKToge1tuYW1lOiBzdHJpbmddOiBHbHNsTGliUm91dGluZX0ge1xuICAgIGNvbnN0IHJlc3VsdDoge1tuYW1lOiBzdHJpbmddOiBHbHNsTGliUm91dGluZX0gPSB7fTtcbiAgICB0aGlzLmNvbnRleHQucHJvZ3JhbUluZm8uaW5wdXROYW1lcy5mb3JFYWNoKChuYW1lLCBpKSA9PiB7XG4gICAgICBjb25zdCBzaGFwZSA9IHRoaXMuY29udGV4dC5pbnB1dFRleHR1cmVMYXlvdXRzW2ldLnNoYXBlO1xuICAgICAgY29uc3Qgc3RyaWRlcyA9IHRoaXMuY29udGV4dC5pbnB1dFRleHR1cmVMYXlvdXRzW2ldLnN0cmlkZXM7XG4gICAgICBjb25zdCByYW5rID0gc2hhcGUubGVuZ3RoO1xuICAgICAgbGV0IGZ1bmNOYW1lID0gYGluZGljZXNUb09mZnNldF8ke25hbWV9YDtcbiAgICAgIHJlc3VsdFtmdW5jTmFtZV0gPSBuZXcgR2xzbExpYlJvdXRpbmUoU2hhcGVVdGlsc0dsc2xMaWIuaW5kZXhUb09mZnNldFNpbmdsZShmdW5jTmFtZSwgcmFuaywgc3RyaWRlcykpO1xuICAgICAgZnVuY05hbWUgPSBgaW5kaWNlc1RvT2Zmc2V0XyR7bmFtZX1fVGA7XG4gICAgICByZXN1bHRbZnVuY05hbWVdID1cbiAgICAgICAgICBuZXcgR2xzbExpYlJvdXRpbmUoU2hhcGVVdGlsc0dsc2xMaWIuaW5kZXhUb09mZnNldFNpbmdsZShmdW5jTmFtZSwgcmFuaywgc3RyaWRlcy5zbGljZSgpLnJldmVyc2UoKSkpO1xuICAgIH0pO1xuICAgIHJldHVybiByZXN1bHQ7XG4gIH1cbiAgc3RhdGljIGluZGV4VG9PZmZzZXRTaW5nbGUobmFtZTogc3RyaW5nLCByYW5rOiBudW1iZXIsIHN0cmlkZXM6IHJlYWRvbmx5IG51bWJlcltdKTogc3RyaW5nIHtcbiAgICBsZXQgYmxvY2sgPSAnJztcbiAgICBmb3IgKGxldCBpID0gcmFuayAtIDE7IGkgPj0gMDsgLS1pKSB7XG4gICAgICBibG9jayArPSBgXG4gICAgICAgIG9mZnNldCArPSBpbmRpY2VzWyR7aX1dICogJHtzdHJpZGVzW2ldfTtcbiAgICAgICAgYDtcbiAgICB9XG4gICAgcmV0dXJuIGBcbiAgICAgIGludCAke25hbWV9KGludCBpbmRpY2VzWyR7cmFua31dKSB7XG4gICAgICAgIGludCBvZmZzZXQgPSAwO1xuICAgICAgICAke2Jsb2NrfVxuICAgICAgICByZXR1cm4gb2Zmc2V0O1xuICAgICAgfVxuICAgICAgYDtcbiAgfVxuICBwcm90ZWN0ZWQgb2Zmc2V0VG9JbmRpY2VzKCk6IHtbbmFtZTogc3RyaW5nXTogR2xzbExpYlJvdXRpbmV9IHtcbiAgICBjb25zdCByZXN1bHQ6IHtbbmFtZTogc3RyaW5nXTogR2xzbExpYlJvdXRpbmV9ID0ge307XG4gICAgdGhpcy5jb250ZXh0LnByb2dyYW1JbmZvLmlucHV0TmFtZXMuZm9yRWFjaCgobmFtZSwgaSkgPT4ge1xuICAgICAgY29uc3Qgc2hhcGUgPSB0aGlzLmNvbnRleHQuaW5wdXRUZXh0dXJlTGF5b3V0c1tpXS5zaGFwZTtcbiAgICAgIGNvbnN0IHN0cmlkZXMgPSB0aGlzLmNvbnRleHQuaW5wdXRUZXh0dXJlTGF5b3V0c1tpXS5zdHJpZGVzO1xuICAgICAgY29uc3QgcmFuayA9IHNoYXBlLmxlbmd0aDtcbiAgICAgIGxldCBmdW5jTmFtZSA9IGBvZmZzZXRUb0luZGljZXNfJHtuYW1lfWA7XG4gICAgICByZXN1bHRbZnVuY05hbWVdID0gbmV3IEdsc2xMaWJSb3V0aW5lKFNoYXBlVXRpbHNHbHNsTGliLm9mZnNldFRvSW5kaWNlc1NpbmdsZShmdW5jTmFtZSwgcmFuaywgc3RyaWRlcykpO1xuICAgICAgZnVuY05hbWUgPSBgb2Zmc2V0VG9JbmRpY2VzXyR7bmFtZX1fVGA7XG4gICAgICByZXN1bHRbZnVuY05hbWVdID1cbiAgICAgICAgICBuZXcgR2xzbExpYlJvdXRpbmUoU2hhcGVVdGlsc0dsc2xMaWIub2Zmc2V0VG9JbmRpY2VzU2luZ2xlKGZ1bmNOYW1lLCByYW5rLCBzdHJpZGVzLnNsaWNlKCkucmV2ZXJzZSgpKSk7XG4gICAgfSk7XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfVxuICBzdGF0aWMgb2Zmc2V0VG9JbmRpY2VzU2luZ2xlKG5hbWU6IHN0cmluZywgcmFuazogbnVtYmVyLCBzdHJpZGVzOiByZWFkb25seSBudW1iZXJbXSk6IHN0cmluZyB7XG4gICAgY29uc3Qgc3RyaWRlc0Jsb2NrID0gW107XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCByYW5rIC0gMTsgKytpKSB7XG4gICAgICBzdHJpZGVzQmxvY2sucHVzaChgXG4gICAgICBpbmRpY2VzWyR7aX1dID0gb2Zmc2V0IC8gJHtzdHJpZGVzW2ldfTtgKTtcbiAgICAgIHN0cmlkZXNCbG9jay5wdXNoKGBcbiAgICAgICAgb2Zmc2V0IC09IGluZGljZXNbJHtpfV0gKiAke3N0cmlkZXNbaV19O2ApO1xuICAgIH1cbiAgICBzdHJpZGVzQmxvY2sucHVzaChgXG4gICAgICBpbmRpY2VzWyR7cmFuayAtIDF9XSA9IG9mZnNldDtgKTtcbiAgICByZXR1cm4gYFxuICAgICAgdm9pZCAke25hbWV9KGludCBvZmZzZXQsIG91dCBpbnQgaW5kaWNlc1ske3Jhbmt9XSkge1xuICAgICAgICAke3N0cmlkZXNCbG9jay5qb2luKCcnKX1cbiAgICAgIH1cbiAgICAgIGA7XG4gIH1cbiAgcHJvdGVjdGVkIGluY3JlbWVudEluZGljZXMoKToge1tuYW1lOiBzdHJpbmddOiBHbHNsTGliUm91dGluZX0ge1xuICAgIGNvbnN0IHJlc3VsdDoge1tuYW1lOiBzdHJpbmddOiBHbHNsTGliUm91dGluZX0gPSB7fTtcbiAgICB0aGlzLmNvbnRleHQucHJvZ3JhbUluZm8uaW5wdXROYW1lcy5mb3JFYWNoKChuYW1lLCBpKSA9PiB7XG4gICAgICBjb25zdCBzaGFwZSA9IHRoaXMuY29udGV4dC5pbnB1dFRleHR1cmVMYXlvdXRzW2ldLnNoYXBlO1xuICAgICAgY29uc3QgcmFuayA9IHNoYXBlLmxlbmd0aDtcbiAgICAgIGNvbnN0IGZ1bmNOYW1lID0gYGluY3JlbWVudEluZGljZXNfJHtuYW1lfWA7XG4gICAgICBsZXQgc2hhcGVJbml0ID0gJyc7XG4gICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHJhbms7ICsraSkge1xuICAgICAgICBzaGFwZUluaXQgKz0gYFxuICAgICAgICBzaGFwZVske2l9XSA9ICR7c2hhcGVbaV19O2A7XG4gICAgICB9XG4gICAgICBjb25zdCBib2R5ID0gYFxuICAgICAgICB2b2lkICR7ZnVuY05hbWV9KGludCBheGlzLCBvdXQgaW50IGluZGljZXNbJHtyYW5rfV0pIHtcbiAgICAgICAgICBpbnQgc2hhcGVbJHtyYW5rfV07XG4gICAgICAgICAgJHtzaGFwZUluaXR9O1xuICAgICAgICAgIGZvcihpbnQgaSA9ICR7cmFua30gLTEgOyBpID49IDA7IC0taSkge1xuICAgICAgICAgICAgaWYoaSA+IGF4aXMpIGNvbnRpbnVlO1xuICAgICAgICAgICAgaW5kaWNlc1tpXSArPSAxO1xuICAgICAgICAgICAgaWYoaW5kaWNlc1tpXSA8IHNoYXBlW2ldKSB7XG4gICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaW5kaWNlc1tpXSA9IDA7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGA7XG4gICAgICByZXN1bHRbZnVuY05hbWVdID0gbmV3IEdsc2xMaWJSb3V0aW5lKGJvZHkpO1xuICAgIH0pO1xuICAgIHJldHVybiByZXN1bHQ7XG4gIH1cbn1cbiIsIi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxuXG4vKipcbiAqIHJlcHJlc2VudCBhIHZlcnNpb24gaXJyZWxldmFudCBhYnN0cmFjdGlvbiBvZiBmb3IgR0xTTCBzb3VyY2UgY29kZVxuICovXG5leHBvcnQgaW50ZXJmYWNlIEdsc2wge1xuICByZWFkb25seSB2ZXJzaW9uOiBzdHJpbmc7XG4gIHJlYWRvbmx5IGF0dHJpYnV0ZTogc3RyaW5nO1xuICByZWFkb25seSB2YXJ5aW5nVmVydGV4OiBzdHJpbmc7XG4gIHJlYWRvbmx5IHZhcnlpbmdGcmFnOiBzdHJpbmc7XG4gIHJlYWRvbmx5IHRleHR1cmUyRDogc3RyaW5nO1xuICByZWFkb25seSBvdXRwdXQ6IHN0cmluZztcbiAgcmVhZG9ubHkgb3V0cHV0RGVjbGFyYXRpb246IHN0cmluZztcbn1cblxuY29uc3QgR0xTTF9FU18yXzA6IEdsc2wgPSB7XG4gIHZlcnNpb246ICcnLFxuICBhdHRyaWJ1dGU6ICdhdHRyaWJ1dGUnLFxuICB2YXJ5aW5nVmVydGV4OiAndmFyeWluZycsXG4gIHZhcnlpbmdGcmFnOiAndmFyeWluZycsXG4gIHRleHR1cmUyRDogJ3RleHR1cmUyRCcsXG4gIG91dHB1dDogJ2dsX0ZyYWdDb2xvcicsXG4gIG91dHB1dERlY2xhcmF0aW9uOiAnJyxcbn07XG5jb25zdCBHTFNMX0VTXzNfMDogR2xzbCA9IHtcbiAgdmVyc2lvbjogJyN2ZXJzaW9uIDMwMCBlcycsXG4gIGF0dHJpYnV0ZTogJ2luJyxcbiAgdmFyeWluZ1ZlcnRleDogJ291dCcsXG4gIHZhcnlpbmdGcmFnOiAnaW4nLFxuICB0ZXh0dXJlMkQ6ICd0ZXh0dXJlJyxcbiAgb3V0cHV0OiAnb3V0cHV0Q29sb3InLFxuICBvdXRwdXREZWNsYXJhdGlvbjogJ291dCB2ZWM0IG91dHB1dENvbG9yOycsXG59O1xuXG5leHBvcnQgZnVuY3Rpb24gZ2V0R2xzbCh2ZXJzaW9uOiAxfDIpIHtcbiAgcmV0dXJuIHZlcnNpb24gPT09IDEgPyBHTFNMX0VTXzJfMCA6IEdMU0xfRVNfM18wO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZ2V0VmVydGV4U2hhZGVyU291cmNlKHZlcnNpb246IDF8Mik6IHN0cmluZyB7XG4gIGNvbnN0IGdsc2wgPSBnZXRHbHNsKHZlcnNpb24pO1xuICByZXR1cm4gYCR7Z2xzbC52ZXJzaW9ufVxuICAgICAgcHJlY2lzaW9uIGhpZ2hwIGZsb2F0O1xuICAgICAgJHtnbHNsLmF0dHJpYnV0ZX0gdmVjMyBwb3NpdGlvbjtcbiAgICAgICR7Z2xzbC5hdHRyaWJ1dGV9IHZlYzIgdGV4dHVyZUNvb3JkO1xuXG4gICAgICAke2dsc2wudmFyeWluZ1ZlcnRleH0gdmVjMiBUZXhDb29yZHM7XG5cbiAgICAgIHZvaWQgbWFpbigpXG4gICAgICB7XG4gICAgICAgICAgZ2xfUG9zaXRpb24gPSB2ZWM0KHBvc2l0aW9uLCAxLjApO1xuICAgICAgICAgIFRleENvb3JkcyA9IHRleHR1cmVDb29yZDtcbiAgICAgIH1gO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZ2V0RnJhZ1NoYWRlclByZWFtYmxlKHZlcnNpb246IDF8Mik6IHN0cmluZyB7XG4gIGNvbnN0IGdsc2wgPSBnZXRHbHNsKHZlcnNpb24pO1xuICByZXR1cm4gYCR7Z2xzbC52ZXJzaW9ufVxuICAgIHByZWNpc2lvbiBoaWdocCBmbG9hdDtcbiAgICBwcmVjaXNpb24gaGlnaHAgaW50O1xuICAgIHByZWNpc2lvbiBoaWdocCBzYW1wbGVyMkQ7XG4gICAgJHtnbHNsLnZhcnlpbmdGcmFnfSB2ZWMyIFRleENvb3JkcztcbiAgICAke2dsc2wub3V0cHV0RGVjbGFyYXRpb259XG4gICAgY29uc3QgdmVjMiBoYWxmQ1IgPSB2ZWMyKDAuNSwgMC41KTtcblxuICAgIC8vIEN1c3RvbSB2ZWN0b3IgdHlwZXMgdG8gaGFuZGxlIGhpZ2hlciBkaW1lbmFsaXRpZXMuXG4gICAgc3RydWN0IGl2ZWM1XG4gICAge1xuICAgICAgaW50IHg7XG4gICAgICBpbnQgeTtcbiAgICAgIGludCB6O1xuICAgICAgaW50IHc7XG4gICAgICBpbnQgdTtcbiAgICB9O1xuXG4gICAgc3RydWN0IGl2ZWM2XG4gICAge1xuICAgICAgaW50IHg7XG4gICAgICBpbnQgeTtcbiAgICAgIGludCB6O1xuICAgICAgaW50IHc7XG4gICAgICBpbnQgdTtcbiAgICAgIGludCB2O1xuICAgIH07XG5cbiAgICBpbnQgaW1vZChpbnQgeCwgaW50IHkpIHtcbiAgICAgIHJldHVybiB4IC0geSAqICh4IC8geSk7XG4gICAgfVxuXG4gICAgYDtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGdldERlZmF1bHRGcmFnU2hhZGVyTWFpbih2ZXJzaW9uOiAxfDIsIG91dHB1dFNoYXBlTGVuZ3RoOiBudW1iZXIpOiBzdHJpbmcge1xuICBjb25zdCBnbHNsID0gZ2V0R2xzbCh2ZXJzaW9uKTtcbiAgcmV0dXJuIGBcbiAgdm9pZCBtYWluKCkge1xuICAgIGludCBpbmRpY2VzWyR7b3V0cHV0U2hhcGVMZW5ndGh9XTtcbiAgICB0b1ZlYyhUZXhDb29yZHMsIGluZGljZXMpO1xuICAgIHZlYzQgcmVzdWx0ID0gdmVjNChwcm9jZXNzKGluZGljZXMpKTtcbiAgICAke2dsc2wub3V0cHV0fSA9IHJlc3VsdDtcbiAgfVxuICBgO1xufVxuIiwiLy8gQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXG5cbmltcG9ydCB7R2xzbENvbnRleHQsIEdsc2xMaWIsIEdsc2xMaWJSb3V0aW5lfSBmcm9tICcuL2dsc2wtZGVmaW5pdGlvbnMnO1xuXG4vKipcbiAqIEdMU0wgTGlicmFyeSByZXNwb25zaWJsZSBmb3IgdmVjIHJvdXRpbmVzXG4gKiBWZWMgaXMgYW4gdmFyaWJsZSBsZW5ndGggaW50IGFycmF5LiBUaGUgbGVuZ3RoIGlzIGZpeGVkIGF0IHRoZSB0aW1lIG9mXG4gKiBnZW5lcmF0aW5nIHRoZSBsaWJyYXJ5IGZ1bmN0aW9ucyBmcm9tIHRoZSBkaW1lbnNpb25zIG9mIHRoZSBvdXRwdXQuXG4gKi9cbmV4cG9ydCBjbGFzcyBWZWNHbHNsTGliIGV4dGVuZHMgR2xzbExpYiB7XG4gIGNvbnN0cnVjdG9yKGNvbnRleHQ6IEdsc2xDb250ZXh0KSB7XG4gICAgc3VwZXIoY29udGV4dCk7XG4gIH1cbiAgZ2V0Q3VzdG9tVHlwZXMoKToge1tuYW1lOiBzdHJpbmddOiBzdHJpbmd9IHtcbiAgICByZXR1cm4ge307XG4gIH1cbiAgZ2V0RnVuY3Rpb25zKCk6IHtbbmFtZTogc3RyaW5nXTogR2xzbExpYlJvdXRpbmV9IHtcbiAgICByZXR1cm4gey4uLnRoaXMuYmluYXJ5VmVjRnVuY3Rpb25zKCksIC4uLnRoaXMuY29weVZlYygpLCAuLi50aGlzLnNldFZlY0l0ZW0oKSwgLi4udGhpcy5nZXRWZWNJdGVtKCl9O1xuICB9XG4gIHByb3RlY3RlZCBiaW5hcnlWZWNGdW5jdGlvbnMoKToge1tuYW1lOiBzdHJpbmddOiBHbHNsTGliUm91dGluZX0ge1xuICAgIGNvbnN0IG91dHB1dExheW91dCA9IHRoaXMuY29udGV4dC5vdXRwdXRUZXh0dXJlTGF5b3V0O1xuICAgIGNvbnN0IHJhbmsgPSBvdXRwdXRMYXlvdXQuc2hhcGUubGVuZ3RoO1xuICAgIGNvbnN0IG5hbWVPcDoge1tuYW1lOiBzdHJpbmddOiBzdHJpbmd9ID0ge2FkZDogJys9Jywgc3ViOiAnLT0nLCBtdWw6ICcqPScsIGRpdjogJy89J307XG4gICAgY29uc3QgcmVzdWx0OiB7W25hbWU6IHN0cmluZ106IEdsc2xMaWJSb3V0aW5lfSA9IHt9O1xuICAgIGZvciAoY29uc3QgbmFtZSBpbiBuYW1lT3ApIHtcbiAgICAgIGNvbnN0IGZuYW1lID0gYCR7bmFtZX1WZWNgO1xuICAgICAgbGV0IGFzc2lnbm1lbnRCbG9jayA9ICcnO1xuICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCByYW5rOyArK2kpIHtcbiAgICAgICAgYXNzaWdubWVudEJsb2NrICs9IGBcbiAgICAgICAgICBkZXN0WyR7aX1dICR7bmFtZU9wW25hbWVdfSBzcmNbJHtpfV07XG4gICAgICAgICAgYDtcbiAgICAgIH1cbiAgICAgIGNvbnN0IGJvZHkgPSBgXG4gICAgICAgIHZvaWQgJHtmbmFtZX0oaW50IHNyY1ske3Jhbmt9XSwgb3V0IGludCBkZXN0WyR7cmFua31dKSB7XG4gICAgICAgICAgJHthc3NpZ25tZW50QmxvY2t9XG4gICAgICAgIH1cbiAgICAgICAgYDtcbiAgICAgIHJlc3VsdFtmbmFtZV0gPSBuZXcgR2xzbExpYlJvdXRpbmUoYm9keSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfVxuICBwcm90ZWN0ZWQgY29weVZlYygpOiB7W25hbWU6IHN0cmluZ106IEdsc2xMaWJSb3V0aW5lfSB7XG4gICAgY29uc3Qgb3V0cHV0TGF5b3V0ID0gdGhpcy5jb250ZXh0Lm91dHB1dFRleHR1cmVMYXlvdXQ7XG4gICAgY29uc3QgcmFuayA9IG91dHB1dExheW91dC5zaGFwZS5sZW5ndGg7XG4gICAgbGV0IGFzc2lnbm1lbnRCbG9jayA9ICcnO1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgcmFuazsgKytpKSB7XG4gICAgICBhc3NpZ25tZW50QmxvY2sgKz0gYFxuICAgICAgICBkZXN0WyR7aX1dID0gc3JjWyR7aX1dO1xuICAgICAgICBgO1xuICAgIH1cbiAgICBjb25zdCBib2R5ID0gYFxuICAgICAgdm9pZCBjb3B5VmVjKGludCBzcmNbJHtyYW5rfV0sIG91dCBpbnQgZGVzdFske3Jhbmt9XSkge1xuICAgICAgICAke2Fzc2lnbm1lbnRCbG9ja31cbiAgICAgIH1cbiAgICAgIGA7XG4gICAgcmV0dXJuIHtjb3B5VmVjOiBuZXcgR2xzbExpYlJvdXRpbmUoYm9keSl9O1xuICB9XG5cbiAgcHJvdGVjdGVkIHNldFZlY0l0ZW0oKToge1tuYW1lOiBzdHJpbmddOiBHbHNsTGliUm91dGluZX0ge1xuICAgIGNvbnN0IG91dHB1dExheW91dCA9IHRoaXMuY29udGV4dC5vdXRwdXRUZXh0dXJlTGF5b3V0O1xuICAgIGNvbnN0IHJhbmsgPSBvdXRwdXRMYXlvdXQuc2hhcGUubGVuZ3RoO1xuICAgIGxldCBibG9jayA9IGBcbiAgICAgICAgaWYoaW5kZXggPCAwKVxuICAgICAgICAgICAgaW5kZXggPSR7cmFua30gKyBpbmRleDtcbiAgICAgICAgaWYgKGluZGV4ID09IDApXG4gICAgICAgICAgICBtWzBdID0gdmFsdWU7XG4gICAgICAgIGA7XG4gICAgZm9yIChsZXQgaSA9IDE7IGkgPCByYW5rIC0gMTsgKytpKSB7XG4gICAgICBibG9jayArPSBgXG4gICAgICAgIGVsc2UgaWYgKGluZGV4ID09ICR7aX0pXG4gICAgICAgICAgICBtWyR7aX1dID0gdmFsdWU7XG4gICAgICAgICAgICBgO1xuICAgIH1cbiAgICBibG9jayArPSBgXG4gICAgICAgIGVsc2VcbiAgICAgICAgICAgIG1bJHtyYW5rIC0gMX1dID0gdmFsdWU7XG4gICAgICAgIGA7XG4gICAgY29uc3QgYm9keSA9IGBcbiAgICAgIHZvaWQgc2V0VmVjSXRlbShvdXQgaW50IG1bJHtyYW5rfV0sIGludCBpbmRleCwgaW50IHZhbHVlKSB7XG4gICAgICAgICR7YmxvY2t9XG4gICAgICB9XG4gICAgICAgIGA7XG4gICAgcmV0dXJuIHtzZXRWZWNJdGVtOiBuZXcgR2xzbExpYlJvdXRpbmUoYm9keSl9O1xuICB9XG4gIHByb3RlY3RlZCBnZXRWZWNJdGVtKCk6IHtbbmFtZTogc3RyaW5nXTogR2xzbExpYlJvdXRpbmV9IHtcbiAgICBjb25zdCBvdXRwdXRMYXlvdXQgPSB0aGlzLmNvbnRleHQub3V0cHV0VGV4dHVyZUxheW91dDtcbiAgICBjb25zdCByYW5rID0gb3V0cHV0TGF5b3V0LnNoYXBlLmxlbmd0aDtcbiAgICBsZXQgYmxvY2sgPSBgXG4gICAgICAgIGlmKGluZGV4IDwgMClcbiAgICAgICAgICAgIGluZGV4ID0gJHtyYW5rfSArIGluZGV4O1xuICAgICAgICBpZiAoaW5kZXggPT0gMClcbiAgICAgICAgICAgIHJldHVybiBtWzBdO1xuICAgICAgYDtcbiAgICBmb3IgKGxldCBpID0gMTsgaSA8IHJhbmsgLSAxOyArK2kpIHtcbiAgICAgIGJsb2NrICs9IGBcbiAgICAgICAgZWxzZSBpZiAoaW5kZXggPT0gJHtpfSlcbiAgICAgICAgICAgIHJldHVybiBtWyR7aX1dO1xuICAgICAgYDtcbiAgICB9XG4gICAgYmxvY2sgKz0gYFxuICAgICAgICBlbHNlXG4gICAgICAgICAgICByZXR1cm4gbVske3JhbmsgLSAxfV07XG4gICAgICAgIGA7XG4gICAgY29uc3QgYm9keSA9IGBcbiAgICAgIGludCBnZXRWZWNJdGVtKGludCBtWyR7cmFua31dLCBpbnQgaW5kZXgpIHtcbiAgICAgICAgJHtibG9ja31cbiAgICAgIH1cbiAgICBgO1xuICAgIHJldHVybiB7Z2V0VmVjSXRlbTogbmV3IEdsc2xMaWJSb3V0aW5lKGJvZHkpfTtcbiAgfVxufVxuIiwiLy8gQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXG5cbmltcG9ydCB7SW5mZXJlbmNlSGFuZGxlcn0gZnJvbSAnLi4vLi4vYmFja2VuZCc7XG5pbXBvcnQge0xvZ2dlcn0gZnJvbSAnLi4vLi4vaW5zdHJ1bWVudCc7XG5pbXBvcnQge1RlbnNvcn0gZnJvbSAnLi4vLi4vdGVuc29yJztcbmltcG9ydCB7U2hhcGVVdGlsfSBmcm9tICcuLi8uLi91dGlsJztcblxuaW1wb3J0IHtjcmVhdGVQYWNrUHJvZ3JhbUluZm9Mb2FkZXJ9IGZyb20gJy4vb3BzL3BhY2snO1xuaW1wb3J0IHtjcmVhdGVQYWNrZWRSZXNoYXBlM0RQcm9ncmFtSW5mb0xvYWRlciwgaXNSZXNoYXBlQ2hlYXAsIHByb2Nlc3NEaW1zM0R9IGZyb20gJy4vb3BzL3Jlc2hhcGUtcGFja2VkJztcbmltcG9ydCB7ZW5jb2RlQXNVaW50OH0gZnJvbSAnLi9vcHMvdWludDgtZW5jb2RlJztcbmltcG9ydCB7Y3JlYXRlVW5wYWNrUHJvZ3JhbUluZm9Mb2FkZXJ9IGZyb20gJy4vb3BzL3VucGFjayc7XG5pbXBvcnQge1dlYkdMU2Vzc2lvbkhhbmRsZXJ9IGZyb20gJy4vc2Vzc2lvbi1oYW5kbGVyJztcbmltcG9ydCB7RW5jb2Rlcn0gZnJvbSAnLi90ZXh0dXJlLWRhdGEtZW5jb2Rlcic7XG5pbXBvcnQge2NhbGN1bGF0ZVRleHR1cmVXaWR0aEFuZEhlaWdodCwgY3JlYXRlVGV4dHVyZUxheW91dEZyb21TaGFwZSwgY3JlYXRlVGV4dHVyZUxheW91dEZyb21UZXh0dXJlVHlwZX0gZnJvbSAnLi90ZXh0dXJlLWxheW91dCc7XG5pbXBvcnQge0FydGlmYWN0LCBQcm9ncmFtSW5mbywgUHJvZ3JhbUluZm9Mb2FkZXIsIFRleHR1cmVEYXRhLCBUZXh0dXJlTGF5b3V0LCBUZXh0dXJlVHlwZX0gZnJvbSAnLi90eXBlcyc7XG5cbmNvbnN0IGdldFByb2dyYW1JbmZvVW5pcXVlS2V5ID1cbiAgICAocHJvZ3JhbUluZm86IFByb2dyYW1JbmZvfFByb2dyYW1JbmZvTG9hZGVyLCBpbnB1dFRleHR1cmVEYXRhczogVGV4dHVyZURhdGFbXSk6IHN0cmluZyA9PiB7XG4gICAgICBjb25zdCBpbnB1dHMgPVxuICAgICAgICAgIGlucHV0VGV4dHVyZURhdGFzLm1hcCh0ZXh0dXJlID0+IGAke3RleHR1cmUudW5wYWNrZWRTaGFwZS5qb2luKCcsJyl9OyR7dGV4dHVyZS53aWR0aH14JHt0ZXh0dXJlLmhlaWdodH1gKVxuICAgICAgICAgICAgICAuam9pbignXycpO1xuICAgICAgbGV0IGtleSA9IHByb2dyYW1JbmZvLm5hbWU7XG4gICAgICBpZiAocHJvZ3JhbUluZm8uY2FjaGVIaW50KSB7XG4gICAgICAgIGtleSArPSAnWycgKyBwcm9ncmFtSW5mby5jYWNoZUhpbnQgKyAnXSc7XG4gICAgICB9XG4gICAgICBrZXkgKz0gJzonICsgaW5wdXRzO1xuICAgICAgcmV0dXJuIGtleTtcbiAgICB9O1xuXG5leHBvcnQgY2xhc3MgV2ViR0xJbmZlcmVuY2VIYW5kbGVyIGltcGxlbWVudHMgSW5mZXJlbmNlSGFuZGxlciB7XG4gIHByaXZhdGUgcGFja2VkVGV4dHVyZURhdGFDYWNoZTogTWFwPFRlbnNvci5JZCwgVGV4dHVyZURhdGE+O1xuICBwcml2YXRlIHVucGFja2VkVGV4dHVyZURhdGFDYWNoZTogTWFwPFRlbnNvci5JZCwgVGV4dHVyZURhdGE+O1xuICBjb25zdHJ1Y3RvcihwdWJsaWMgc2Vzc2lvbjogV2ViR0xTZXNzaW9uSGFuZGxlcikge1xuICAgIHRoaXMucGFja2VkVGV4dHVyZURhdGFDYWNoZSA9IG5ldyBNYXAoKTtcbiAgICB0aGlzLnVucGFja2VkVGV4dHVyZURhdGFDYWNoZSA9IG5ldyBNYXAoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcmV0dXJucyBbd2lkdGgsIGhlaWdodF1cbiAgICovXG4gIGNhbGN1bGF0ZVRleHR1cmVXaWR0aEFuZEhlaWdodChzaGFwZTogcmVhZG9ubHkgbnVtYmVyW10sIHRleHR1cmVUeXBlOiBUZXh0dXJlVHlwZSk6IFtudW1iZXIsIG51bWJlcl0ge1xuICAgIHJldHVybiBjYWxjdWxhdGVUZXh0dXJlV2lkdGhBbmRIZWlnaHQodGhpcy5zZXNzaW9uLmxheW91dFN0cmF0ZWd5LCBzaGFwZSwgdGV4dHVyZVR5cGUpO1xuICB9XG5cbiAgZXhlY3V0ZVByb2dyYW0ocHJvZ3JhbTogUHJvZ3JhbUluZm98UHJvZ3JhbUluZm9Mb2FkZXIsIGlucHV0czogcmVhZG9ubHkgVGVuc29yW10pOiBUZXh0dXJlRGF0YSB7XG4gICAgaWYgKGlucHV0cy5sZW5ndGggPCBwcm9ncmFtLmlucHV0TmFtZXMubGVuZ3RoKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYElucHV0IHNpemUgbXVzdG4ndCBiZSBsZXNzIHRoYW4gJHtwcm9ncmFtLmlucHV0TmFtZXMubGVuZ3RofS5gKTtcbiAgICB9XG4gICAgaWYgKHByb2dyYW0uaW5wdXROYW1lcy5sZW5ndGggIT09IHByb2dyYW0uaW5wdXRUeXBlcy5sZW5ndGgpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignaW5wdXQgbmFtZXMgc2l6ZSBkb2VzIG5vdCBtYXRjaCBpbnB1dCB0eXBlcycpO1xuICAgIH1cblxuICAgIC8vIGNyZWF0ZSB0ZXh0dXJlIGluZm8gZm9yIGlucHV0XG4gICAgY29uc3QgaW5wdXRUZXh0dXJlRGF0YXM6IFRleHR1cmVEYXRhW10gPSBbXTtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHByb2dyYW0uaW5wdXROYW1lcy5sZW5ndGg7ICsraSkge1xuICAgICAgaW5wdXRUZXh0dXJlRGF0YXNbaV0gPSB0aGlzLmdldE9yQ3JlYXRlVGV4dHVyZURhdGEoaW5wdXRzW2ldLCBwcm9ncmFtLmlucHV0VHlwZXNbaV0pO1xuICAgIH1cblxuICAgIGNvbnN0IGtleSA9IGdldFByb2dyYW1JbmZvVW5pcXVlS2V5KHByb2dyYW0sIGlucHV0VGV4dHVyZURhdGFzKTtcbiAgICBsZXQgYXJ0aWZhY3QgPSB0aGlzLnNlc3Npb24ucHJvZ3JhbU1hbmFnZXIuZ2V0QXJ0aWZhY3Qoa2V5KTtcbiAgICBjb25zdCBwcm9ncmFtSW5mbyA9IGFydGlmYWN0ID9cbiAgICAgICAgYXJ0aWZhY3QucHJvZ3JhbUluZm8gOlxuICAgICAgICAodHlwZW9mIChwcm9ncmFtIGFzIFByb2dyYW1JbmZvTG9hZGVyKS5nZXQgPT09ICdmdW5jdGlvbicgPyAocHJvZ3JhbSBhcyBQcm9ncmFtSW5mb0xvYWRlcikuZ2V0KCkgOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAocHJvZ3JhbSBhcyBQcm9ncmFtSW5mbykpO1xuXG4gICAgLy8gY3JlYXRlIHRleHR1cmUgaW5mbyBmb3Igb3V0cHV0XG4gICAgY29uc3Qgb3V0cHV0VGV4dHVyZUxheW91dCA9IGNyZWF0ZVRleHR1cmVMYXlvdXRGcm9tVGV4dHVyZVR5cGUoXG4gICAgICAgIHRoaXMuc2Vzc2lvbi5sYXlvdXRTdHJhdGVneSwgcHJvZ3JhbUluZm8ub3V0cHV0LmRpbXMsIHByb2dyYW1JbmZvLm91dHB1dC50ZXh0dXJlVHlwZSk7XG4gICAgY29uc3Qgb3V0cHV0VGV4dHVyZURhdGEgPSB0aGlzLmNyZWF0ZVRleHR1cmVEYXRhKG91dHB1dFRleHR1cmVMYXlvdXQsIHByb2dyYW1JbmZvLm91dHB1dC50eXBlKTtcblxuICAgIGlmICghYXJ0aWZhY3QpIHtcbiAgICAgIGFydGlmYWN0ID0gdGhpcy5zZXNzaW9uLnByb2dyYW1NYW5hZ2VyLmJ1aWxkKHByb2dyYW1JbmZvLCBpbnB1dFRleHR1cmVEYXRhcywgb3V0cHV0VGV4dHVyZURhdGEpO1xuICAgICAgdGhpcy5zZXNzaW9uLnByb2dyYW1NYW5hZ2VyLnNldEFydGlmYWN0KGtleSwgYXJ0aWZhY3QpO1xuICAgIH1cblxuICAgIHRoaXMucnVuUHJvZ3JhbShhcnRpZmFjdCwgaW5wdXRUZXh0dXJlRGF0YXMsIG91dHB1dFRleHR1cmVEYXRhKTtcbiAgICByZXR1cm4gb3V0cHV0VGV4dHVyZURhdGE7XG4gIH1cblxuICBydW4ocHJvZ3JhbTogUHJvZ3JhbUluZm9Mb2FkZXIsIGlucHV0czogcmVhZG9ubHkgVGVuc29yW10pOiBUZW5zb3Ige1xuICAgIGNvbnN0IG91dHB1dFRleHR1cmVEYXRhID0gdGhpcy5leGVjdXRlUHJvZ3JhbShwcm9ncmFtLCBpbnB1dHMpO1xuICAgIHJldHVybiBvdXRwdXRUZXh0dXJlRGF0YS50ZW5zb3I7XG4gIH1cblxuICBwcml2YXRlIHJ1blByb2dyYW0oYXJ0aWZhY3Q6IEFydGlmYWN0LCBpbnB1dHM6IFRleHR1cmVEYXRhW10sIG91dHB1dDogVGV4dHVyZURhdGEpOiB2b2lkIHtcbiAgICAvLyBpbnB1dCBzaG91bGQgbWF0Y2hcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGlucHV0cy5sZW5ndGg7ICsraSkge1xuICAgICAgaWYgKCEhaW5wdXRzW2ldLmlzUGFja2VkICE9PSAoYXJ0aWZhY3QucHJvZ3JhbUluZm8uaW5wdXRUeXBlc1tpXSA9PT0gVGV4dHVyZVR5cGUucGFja2VkKSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYGlucHV0WyR7aX1dIHByb3BlcnR5IHBhY2tlZCBpbmNvbnNpc3RlbnRgKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBvdXRwdXQgc2hvdWxkIG1hdGNoXG4gICAgaWYgKCEhb3V0cHV0LmlzUGFja2VkICE9PSAoYXJ0aWZhY3QucHJvZ3JhbUluZm8ub3V0cHV0LnRleHR1cmVUeXBlID09PSBUZXh0dXJlVHlwZS5wYWNrZWQpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ291dHB1dCBwcm9wZXJ0eSBwYWNrZWQgaW5jb25zaXN0ZW50Jyk7XG4gICAgfVxuXG4gICAgdGhpcy5zZXNzaW9uLnByb2dyYW1NYW5hZ2VyLnJ1bihhcnRpZmFjdCwgaW5wdXRzLCBvdXRwdXQpO1xuICB9XG5cbiAgLyoqXG4gICAqIENyZWF0ZSBhIFRleHR1cmVEYXRhIG9iamVjdCBmcm9tIGEgdGVuc29yLlxuICAgKiBVc2FnZSA9IEVuY29kZXIuVXNhZ2UuVXBsb2FkT25seS5cbiAgICogSWYgYSByZWxhdGVkIHRleHR1cmUgZGF0YSBpcyBmb3VuZCBpbiBjYWNoZSwgcmV0dXJucyBpdDtcbiAgICogT3RoZXJ3aXNlOlxuICAgKiAgIENyZWF0ZXMgYSBuZXcgdGV4dHVyZSBsYXlvdXQgaWYgbm90IHByb3ZpZGVkO1xuICAgKiAgIENyZWF0ZXMgV2ViR0xUZXh0dXJlIHdpdGggdGhlIGxheW91dDtcbiAgICogICBVcGxvYWQgdGVuc29yIGRhdGEgdG8gdGhlIHRleHR1cmU7XG4gICAqICAgQ3JlYXRlcyBhIHRleHR1cmUgZGF0YSBvYmplY3QgYXNzb2NpYXRlZCB3aXRoIHRoZSBnaXZlbiB0ZW5zb3IuXG4gICAqIEBwYXJhbSB0ZW5zb3IgdGhlIHRlbnNvciB3aXRoIGRhdGEgdG8gdXBsb2FkXG4gICAqL1xuICBwcml2YXRlIGdldE9yQ3JlYXRlVGV4dHVyZURhdGEodGVuc29yOiBUZW5zb3IsIHRleHR1cmVUeXBlOiBUZXh0dXJlVHlwZSkge1xuICAgIGxldCB0ZCA9IHRoaXMuZ2V0VGV4dHVyZURhdGEodGVuc29yLmRhdGFJZCwgdGV4dHVyZVR5cGUgPT09IFRleHR1cmVUeXBlLnBhY2tlZCk7XG5cbiAgICBpZiAoIXRkKSB7XG4gICAgICAvLyBjaGVjayBpZiB3ZSBoYXZlIHRleHR1cmUgZGF0YSBpbiBkaWZmZXJlbnQgdHlwZVxuICAgICAgdGQgPSB0aGlzLmdldFRleHR1cmVEYXRhKHRlbnNvci5kYXRhSWQsIHRleHR1cmVUeXBlICE9PSBUZXh0dXJlVHlwZS5wYWNrZWQpO1xuICAgICAgaWYgKHRkKSB7XG4gICAgICAgIGlmICh0ZXh0dXJlVHlwZSA9PT0gVGV4dHVyZVR5cGUucGFja2VkKSB7XG4gICAgICAgICAgcmV0dXJuIHRoaXMucGFjayh0ZCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgcmV0dXJuIHRoaXMudW5wYWNrKHRkKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cblxuICAgIGlmICghdGQpIHtcbiAgICAgIGNvbnN0IGxheW91dCA9IGNyZWF0ZVRleHR1cmVMYXlvdXRGcm9tVGV4dHVyZVR5cGUodGhpcy5zZXNzaW9uLmxheW91dFN0cmF0ZWd5LCB0ZW5zb3IuZGltcywgdGV4dHVyZVR5cGUpO1xuXG4gICAgICBpZiAodGV4dHVyZVR5cGUgPT09IFRleHR1cmVUeXBlLnBhY2tlZExhc3REaW1lbnNpb24pIHtcbiAgICAgICAgY29uc3QgZ3JvdXAgPSAxO1xuICAgICAgICBjb25zdCBjaGFubmVscyA9IDQ7XG4gICAgICAgIGNvbnN0IHNoYXBlID0gdGVuc29yLmRpbXM7XG4gICAgICAgIGlmIChzaGFwZS5sZW5ndGggPT09IDQpIHtcbiAgICAgICAgICAvLyBwcmUtcHJvY2Vzc2luZyBmb3Iga2VybmVsIGRhdGEgb2YgQ29udi5cbiAgICAgICAgICAvL1xuICAgICAgICAgIC8vIFRPRE86IGN1cnJlbnRseSB0aGlzIGlzIGEgaGFja2luZyB0byBvdmVyd3JpdGUgQ29udidzIHdlaWdodC4gVGhlIGNvcnJlY3Qgd2F5IHRvIGRvIHRoaXMgc2hvdWxkIGJlOlxuICAgICAgICAgIC8vIDEuIGltcGxlbWVudCB0ZXh0dXJlIGJhc2VkIGNvbnN0LWZvbGRpbmdcbiAgICAgICAgICAvLyAyLiBjcmVhdGUgYSBXZWJHTCBwcm9ncmFtIFwicHJlcHJvY2Vzc0NvbnZXZWlnaHRcIiB0byBkbyB0aGUgc2FtZSB3b3JrIGFzIGJlbG93XG4gICAgICAgICAgLy8gMy4gcnVuIHRoZSBwcm9ncmFtIGJlZm9yZSBkb3RQcm9kdWN0LlxuICAgICAgICAgIC8vXG4gICAgICAgICAgY29uc3QgYWRqdXN0ZWRLZXJuZWxTaGFwZSA9IFtzaGFwZVswXSwgTWF0aC5jZWlsKChzaGFwZVsxXSAqIHNoYXBlWzJdICogc2hhcGVbM10pIC8gY2hhbm5lbHMpXTtcbiAgICAgICAgICBjb25zdCBhZGp1c3RlZExheW91dCA9XG4gICAgICAgICAgICAgIGNyZWF0ZVRleHR1cmVMYXlvdXRGcm9tVGV4dHVyZVR5cGUodGhpcy5zZXNzaW9uLmxheW91dFN0cmF0ZWd5LCBhZGp1c3RlZEtlcm5lbFNoYXBlLCB0ZXh0dXJlVHlwZSk7XG4gICAgICAgICAgbGV0IGJ1ZmZlciA9IHRlbnNvci5udW1iZXJEYXRhO1xuICAgICAgICAgIGlmIChzaGFwZVsxXSAqIHNoYXBlWzJdICogc2hhcGVbM10gJSBjaGFubmVscyAhPT0gMCkge1xuICAgICAgICAgICAgY29uc3QgbnVtRmVhdHVyZU1hcHMgPSBzaGFwZVswXTtcbiAgICAgICAgICAgIGNvbnN0IG9sZFJvd1NpemUgPSBzaGFwZVsxXSAqIHNoYXBlWzJdICogc2hhcGVbM107XG4gICAgICAgICAgICBjb25zdCBuZXdSb3dTaXplID0gTWF0aC5jZWlsKG9sZFJvd1NpemUgKiBncm91cCAvIGNoYW5uZWxzKSAqIGNoYW5uZWxzO1xuICAgICAgICAgICAgY29uc3QgbmV3U2l6ZSA9IG51bUZlYXR1cmVNYXBzICogbmV3Um93U2l6ZTtcbiAgICAgICAgICAgIGJ1ZmZlciA9IG5ldyBGbG9hdDMyQXJyYXkobmV3U2l6ZSk7XG4gICAgICAgICAgICBmb3IgKGxldCBmID0gMDsgZiA8IG51bUZlYXR1cmVNYXBzOyArK2YpIHtcbiAgICAgICAgICAgICAgY29uc3Qgb2xkT2Zmc2V0ID0gZiAqIG9sZFJvd1NpemU7XG4gICAgICAgICAgICAgIGNvbnN0IG5ld09mZnNldCA9IGYgKiBuZXdSb3dTaXplICsgZiAlIGdyb3VwICogb2xkUm93U2l6ZTtcbiAgICAgICAgICAgICAgYnVmZmVyLnNldCh0ZW5zb3IubnVtYmVyRGF0YS5zdWJhcnJheShvbGRPZmZzZXQsIG9sZE9mZnNldCArIG9sZFJvd1NpemUpLCBuZXdPZmZzZXQpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgICByZXR1cm4gdGhpcy5jcmVhdGVUZXh0dXJlRGF0YShhZGp1c3RlZExheW91dCwgdGVuc29yLnR5cGUsIGJ1ZmZlciwgdGVuc29yLCBFbmNvZGVyLlVzYWdlLlVwbG9hZE9ubHkpO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGlmICh0ZXh0dXJlVHlwZSA9PT0gVGV4dHVyZVR5cGUucGFja2VkKSB7XG4gICAgICAgIGNvbnN0IHVucGFja2VkVGV4dHVyZUxheW91dCA9XG4gICAgICAgICAgICBjcmVhdGVUZXh0dXJlTGF5b3V0RnJvbVNoYXBlKHRoaXMuc2Vzc2lvbi5sYXlvdXRTdHJhdGVneSwgdGVuc29yLmRpbXMsIDEsIFtdLCB7cmV2ZXJzZVdIOiB0cnVlfSk7XG4gICAgICAgIGNvbnN0IHVucGFja2VkVGV4dHVyZURhdGEgPSB0aGlzLmNyZWF0ZVRleHR1cmVEYXRhKFxuICAgICAgICAgICAgdW5wYWNrZWRUZXh0dXJlTGF5b3V0LCB0ZW5zb3IudHlwZSwgdGVuc29yLm51bWJlckRhdGEsIHRlbnNvciwgRW5jb2Rlci5Vc2FnZS5VcGxvYWRPbmx5KTtcbiAgICAgICAgdGQgPSB0aGlzLnBhY2sodW5wYWNrZWRUZXh0dXJlRGF0YSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0ZCA9IHRoaXMuY3JlYXRlVGV4dHVyZURhdGEobGF5b3V0LCB0ZW5zb3IudHlwZSwgdGVuc29yLm51bWJlckRhdGEsIHRlbnNvciwgRW5jb2Rlci5Vc2FnZS5VcGxvYWRPbmx5KTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHRkO1xuICB9XG5cbiAgLyoqXG4gICAqIENyZWF0ZSBhIFRleHR1cmVEYXRhIG9iamVjdCB1c2luZyB0aGUgZ2l2ZW4gZGF0YSBhbmQgYmluZCB0byB0aGUgZ2l2ZW4gdGVuc29yLlxuICAgKiBVc2FnZSA9IEVuY29kZXIuVXNhZ2UuVXBsb2FkT25seS5cbiAgICogTk9URTogdGhpcyBmdW5jdGlvbiBpcyBhIGhhY2sgZm9yIENvbnYgaW1wbGVtZW50YXRpb24uIHNob3VsZCByZW1vdmUgdGhpcyBmdW5jdGlvbiwgYWZ0ZXIgcmV3cml0aW5nIENvbnZcbiAgICogaW1wbGVtZW50YXRpb24gYnkgR3JhcGguVHJhbnNmb3JtZXJcbiAgICogQHBhcmFtIGRhdGFUeXBlIHRoZSB0ZW5zb3IgZGF0YSB0eXBlXG4gICAqIEBwYXJhbSBkYXRhIHRoZSBhY3R1YWwgZGF0YSB0byB1cGxvYWRcbiAgICogQHBhcmFtIHRlbnNvciB0aGUgdGVuc29yIHRvIGJpbmQuIHRlbnNvcidzIGRhdGEgaXMgaWdub3JlZC5cbiAgICovXG4gIGNyZWF0ZVRleHR1cmVEYXRhRnJvbUxheW91dEJpbmRUZW5zb3IoXG4gICAgICBsYXlvdXQ6IFRleHR1cmVMYXlvdXQsIGRhdGFUeXBlOiBUZW5zb3IuRGF0YVR5cGUsIGRhdGE6IFRlbnNvci5OdW1iZXJUeXBlLCB0ZW5zb3I6IFRlbnNvcik6IFRleHR1cmVEYXRhIHtcbiAgICByZXR1cm4gdGhpcy5jcmVhdGVUZXh0dXJlRGF0YShsYXlvdXQsIGRhdGFUeXBlLCBkYXRhLCB0ZW5zb3IsIEVuY29kZXIuVXNhZ2UuVXBsb2FkT25seSk7XG4gIH1cblxuICBwcml2YXRlIGNyZWF0ZVRleHR1cmVEYXRhKFxuICAgICAgbGF5b3V0OiBUZXh0dXJlTGF5b3V0LCBkYXRhVHlwZTogVGVuc29yLkRhdGFUeXBlLCBkYXRhPzogVGVuc29yLk51bWJlclR5cGUsIHRlbnNvcj86IFRlbnNvcixcbiAgICAgIHVzYWdlPzogRW5jb2Rlci5Vc2FnZSk6IFRleHR1cmVEYXRhIHtcbiAgICBMb2dnZXIudmVyYm9zZSgnSW5mZXJlbmNlSGFuZGxlcicsIGBDcmVhdGluZyBUZXh0dXJlRGF0YTogbGF5b3V0Olske0pTT04uc3RyaW5naWZ5KGxheW91dCl9XWApO1xuICAgIGNvbnN0IHRleHR1cmUgPSB0aGlzLnNlc3Npb24udGV4dHVyZU1hbmFnZXIuY3JlYXRlVGV4dHVyZUZyb21MYXlvdXQoZGF0YVR5cGUsIGxheW91dCwgZGF0YSwgdXNhZ2UpO1xuICAgIHJldHVybiB0aGlzLmNyZWF0ZVRleHR1cmVEYXRhRnJvbVRleHR1cmUobGF5b3V0LCBkYXRhVHlwZSwgdGV4dHVyZSwgdGVuc29yKTtcbiAgfVxuXG4gIHJlc2hhcGVVbnBhY2tlZChpbnB1dDogVGVuc29yLCByZXNoYXBlZERpbXM6IHJlYWRvbmx5IG51bWJlcltdKTogVGVuc29yIHtcbiAgICBjb25zdCBpbnB1dFREID0gdGhpcy5nZXRPckNyZWF0ZVRleHR1cmVEYXRhKGlucHV0LCBUZXh0dXJlVHlwZS51bnBhY2tlZCk7XG4gICAgY29uc3QgbmV3VGV4dHVyZUxheW91dDogVGV4dHVyZUxheW91dCA9IHtcbiAgICAgIGNoYW5uZWxzOiBpbnB1dFRELmNoYW5uZWxzLFxuICAgICAgaGVpZ2h0OiBpbnB1dFRELmhlaWdodCxcbiAgICAgIHdpZHRoOiBpbnB1dFRELndpZHRoLFxuICAgICAgLy8gaGFuZGxlIHJlc2hhcGluZyBpbnRvIHNjYWxhciBUZW5zb3JzXG4gICAgICBzaGFwZTogcmVzaGFwZWREaW1zLmxlbmd0aCAhPT0gMCA/IHJlc2hhcGVkRGltcyA6IFsxXSxcbiAgICAgIHN0cmlkZXM6IFNoYXBlVXRpbC5jb21wdXRlU3RyaWRlcyhyZXNoYXBlZERpbXMpLFxuICAgICAgdW5wYWNrZWRTaGFwZTogcmVzaGFwZWREaW1zLFxuICAgIH07XG4gICAgY29uc3QgbmV3VGV4dHVyZURhdGEgPSB0aGlzLmNyZWF0ZVRleHR1cmVEYXRhRnJvbVRleHR1cmUobmV3VGV4dHVyZUxheW91dCwgaW5wdXQudHlwZSwgaW5wdXRURC50ZXh0dXJlKTtcbiAgICByZXR1cm4gbmV3VGV4dHVyZURhdGEudGVuc29yO1xuICB9XG5cbiAgcmVzaGFwZVBhY2tlZChpbnB1dDogVGVuc29yLCByZXNoYXBlZERpbXM6IHJlYWRvbmx5IG51bWJlcltdKTogVGVuc29yIHtcbiAgICBjb25zdCBpbnB1dFREID0gdGhpcy5nZXRPckNyZWF0ZVRleHR1cmVEYXRhKGlucHV0LCBUZXh0dXJlVHlwZS5wYWNrZWQpO1xuXG4gICAgLy8gY2hlY2sgaWYgdGhlIHJlc2hhcGUgaXMgJ2NoZWFwJ1xuICAgIGlmIChpc1Jlc2hhcGVDaGVhcChpbnB1dC5kaW1zLCByZXNoYXBlZERpbXMpKSB7XG4gICAgICBjb25zdCBuZXdUZXh0dXJlTGF5b3V0OiBUZXh0dXJlTGF5b3V0ID0ge1xuICAgICAgICBjaGFubmVsczogaW5wdXRURC5jaGFubmVscyxcbiAgICAgICAgaGVpZ2h0OiBpbnB1dFRELmhlaWdodCxcbiAgICAgICAgd2lkdGg6IGlucHV0VEQud2lkdGgsXG4gICAgICAgIC8vIGhhbmRsZSByZXNoYXBpbmcgaW50byBzY2FsYXIgVGVuc29yc1xuICAgICAgICBzaGFwZTogcmVzaGFwZWREaW1zLmxlbmd0aCAhPT0gMCA/IHJlc2hhcGVkRGltcyA6IFsxXSxcbiAgICAgICAgc3RyaWRlczogU2hhcGVVdGlsLmNvbXB1dGVTdHJpZGVzKHJlc2hhcGVkRGltcyksXG4gICAgICAgIHVucGFja2VkU2hhcGU6IHJlc2hhcGVkRGltcyxcbiAgICAgICAgaXNQYWNrZWQ6IHRydWVcbiAgICAgIH07XG4gICAgICBjb25zdCBuZXdUZXh0dXJlRGF0YSA9IHRoaXMuY3JlYXRlVGV4dHVyZURhdGFGcm9tVGV4dHVyZShuZXdUZXh0dXJlTGF5b3V0LCBpbnB1dC50eXBlLCBpbnB1dFRELnRleHR1cmUpO1xuICAgICAgcmV0dXJuIG5ld1RleHR1cmVEYXRhLnRlbnNvcjtcbiAgICB9XG5cbiAgICBjb25zdCBzcXVlZXplZElucHV0U2hhcGUgPSBwcm9jZXNzRGltczNEKGlucHV0LmRpbXMpO1xuICAgIGNvbnN0IHNxdWVlemVkT3V0cHV0U2hhcGUgPSBwcm9jZXNzRGltczNEKHJlc2hhcGVkRGltcyk7XG5cbiAgICBjb25zdCBzcXVlZXplZElucHV0VGVuc29yID0gdGhpcy5yZXNoYXBlUGFja2VkKGlucHV0LCBzcXVlZXplZElucHV0U2hhcGUpO1xuICAgIGNvbnN0IHNxdWVlemVkT3V0cHV0VGVuc29yID0gdGhpcy5ydW4oXG4gICAgICAgIGNyZWF0ZVBhY2tlZFJlc2hhcGUzRFByb2dyYW1JbmZvTG9hZGVyKHRoaXMsIHNxdWVlemVkSW5wdXRUZW5zb3IsIHNxdWVlemVkT3V0cHV0U2hhcGUpLCBbc3F1ZWV6ZWRJbnB1dFRlbnNvcl0pO1xuICAgIGNvbnN0IG91dHB1dFRlbnNvciA9IHRoaXMucmVzaGFwZVBhY2tlZChzcXVlZXplZE91dHB1dFRlbnNvciwgcmVzaGFwZWREaW1zKTtcbiAgICByZXR1cm4gb3V0cHV0VGVuc29yO1xuICB9XG5cbiAgY2FzdChpbnB1dDogVGVuc29yLCB0eXBlOiBUZW5zb3IuRGF0YVR5cGUpOiBUZW5zb3Ige1xuICAgIGNvbnN0IGlucHV0VEQgPSB0aGlzLmdldE9yQ3JlYXRlVGV4dHVyZURhdGEoaW5wdXQsIFRleHR1cmVUeXBlLnVucGFja2VkKTtcbiAgICBjb25zdCBuZXdUZXh0dXJlRGF0YSA9IHRoaXMuY3JlYXRlVGV4dHVyZURhdGFGcm9tVGV4dHVyZShpbnB1dFREIGFzIFRleHR1cmVMYXlvdXQsIHR5cGUsIGlucHV0VEQudGV4dHVyZSk7XG4gICAgcmV0dXJuIG5ld1RleHR1cmVEYXRhLnRlbnNvcjtcbiAgfVxuXG4gIHByaXZhdGUgY3JlYXRlVGV4dHVyZURhdGFGcm9tVGV4dHVyZShcbiAgICAgIGxheW91dDogVGV4dHVyZUxheW91dCwgZGF0YVR5cGU6IFRlbnNvci5EYXRhVHlwZSwgdGV4dHVyZTogV2ViR0xUZXh0dXJlLCB0ZW5zb3I/OiBUZW5zb3IsIHRlbnNvcklkPzogVGVuc29yLklkKSB7XG4gICAgY29uc3QgdGV4dHVyZURhdGE6IFRleHR1cmVEYXRhID0ge1xuICAgICAgLi4ubGF5b3V0LFxuICAgICAgdGVuc29yOiB0ZW5zb3IgfHxcbiAgICAgICAgICBuZXcgVGVuc29yKFxuICAgICAgICAgICAgICAgICAgbGF5b3V0LnVucGFja2VkU2hhcGUsIGRhdGFUeXBlLCAoX2lkOiBUZW5zb3IuSWQpID0+IHRoaXMucmVhZFRleHR1cmUodGV4dHVyZURhdGEpLFxuICAgICAgICAgICAgICAgICAgYXN5bmMgKF9pZDogVGVuc29yLklkKSA9PiB0aGlzLnJlYWRUZXh0dXJlQXN5bmModGV4dHVyZURhdGEpLCB1bmRlZmluZWQsIHRlbnNvcklkKSxcbiAgICAgIHRleHR1cmVcbiAgICB9O1xuICAgIHRoaXMuc2V0VGV4dHVyZURhdGEodGV4dHVyZURhdGEudGVuc29yLmRhdGFJZCwgdGV4dHVyZURhdGEsIGxheW91dC5pc1BhY2tlZCk7XG4gICAgcmV0dXJuIHRleHR1cmVEYXRhO1xuICB9XG5cbiAgcHJpdmF0ZSBnZXRUZXh0dXJlRGF0YSh0ZW5zb3JJZDogVGVuc29yLklkLCBpc1BhY2tlZCA9IGZhbHNlKTogVGV4dHVyZURhdGF8dW5kZWZpbmVkIHtcbiAgICByZXR1cm4gdGhpcy5zZXNzaW9uLmlzSW5pdGlhbGl6ZXIodGVuc29ySWQpID8gdGhpcy5zZXNzaW9uLmdldFRleHR1cmVEYXRhKHRlbnNvcklkLCBpc1BhY2tlZCkgOlxuICAgICAgICBpc1BhY2tlZCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPyB0aGlzLnBhY2tlZFRleHR1cmVEYXRhQ2FjaGUuZ2V0KHRlbnNvcklkKSA6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMudW5wYWNrZWRUZXh0dXJlRGF0YUNhY2hlLmdldCh0ZW5zb3JJZCk7XG4gIH1cbiAgc2V0VGV4dHVyZURhdGEodGVuc29ySWQ6IFRlbnNvci5JZCwgdGQ6IFRleHR1cmVEYXRhLCBpc1BhY2tlZCA9IGZhbHNlKTogdm9pZCB7XG4gICAgaWYgKHRoaXMuc2Vzc2lvbi5pc0luaXRpYWxpemVyKHRlbnNvcklkKSkge1xuICAgICAgdGhpcy5zZXNzaW9uLnNldFRleHR1cmVEYXRhKHRlbnNvcklkLCB0ZCwgaXNQYWNrZWQpO1xuICAgIH0gZWxzZSB7XG4gICAgICAoaXNQYWNrZWQgPyB0aGlzLnBhY2tlZFRleHR1cmVEYXRhQ2FjaGUgOiB0aGlzLnVucGFja2VkVGV4dHVyZURhdGFDYWNoZSkuc2V0KHRlbnNvcklkLCB0ZCk7XG4gICAgfVxuICB9XG4gIGlzVGV4dHVyZUxheW91dENhY2hlZCh0ZW5zb3I6IFRlbnNvciwgaXNQYWNrZWQgPSBmYWxzZSk6IGJvb2xlYW4ge1xuICAgIHJldHVybiAhIXRoaXMuZ2V0VGV4dHVyZURhdGEodGVuc29yLmRhdGFJZCwgaXNQYWNrZWQpO1xuICB9XG5cbiAgZGlzcG9zZSgpOiB2b2lkIHtcbiAgICB0aGlzLnNlc3Npb24udGV4dHVyZU1hbmFnZXIuY2xlYXJBY3RpdmVUZXh0dXJlcygpO1xuICAgIHRoaXMucGFja2VkVGV4dHVyZURhdGFDYWNoZS5mb3JFYWNoKHRkID0+IHRoaXMuc2Vzc2lvbi50ZXh0dXJlTWFuYWdlci5yZWxlYXNlVGV4dHVyZSh0ZCkpO1xuICAgIHRoaXMucGFja2VkVGV4dHVyZURhdGFDYWNoZSA9IG5ldyBNYXAoKTtcbiAgICB0aGlzLnVucGFja2VkVGV4dHVyZURhdGFDYWNoZS5mb3JFYWNoKHRkID0+IHRoaXMuc2Vzc2lvbi50ZXh0dXJlTWFuYWdlci5yZWxlYXNlVGV4dHVyZSh0ZCkpO1xuICAgIHRoaXMudW5wYWNrZWRUZXh0dXJlRGF0YUNhY2hlID0gbmV3IE1hcCgpO1xuICB9XG5cbiAgcmVhZFRleHR1cmUodGV4dHVyZURhdGE6IFRleHR1cmVEYXRhKTogVGVuc29yLk51bWJlclR5cGUge1xuICAgIGlmICh0ZXh0dXJlRGF0YS5pc1BhY2tlZCkge1xuICAgICAgcmV0dXJuIHRoaXMucmVhZFRleHR1cmUodGhpcy51bnBhY2sodGV4dHVyZURhdGEpKTtcbiAgICB9XG4gICAgaWYgKCF0aGlzLnNlc3Npb24uYmFja2VuZC5nbENvbnRleHQuaXNGbG9hdDMyRG93bmxvYWRTdXBwb3J0ZWQpIHtcbiAgICAgIHJldHVybiB0aGlzLnNlc3Npb24udGV4dHVyZU1hbmFnZXIucmVhZFVpbnQ4VGV4dHVyZUFzRmxvYXQoZW5jb2RlQXNVaW50OCh0aGlzLCB0ZXh0dXJlRGF0YSkpO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy5zZXNzaW9uLnRleHR1cmVNYW5hZ2VyLnJlYWRUZXh0dXJlKHRleHR1cmVEYXRhLCB0ZXh0dXJlRGF0YS50ZW5zb3IudHlwZSwgdGV4dHVyZURhdGEuY2hhbm5lbHMpO1xuICB9XG5cbiAgYXN5bmMgcmVhZFRleHR1cmVBc3luYyh0ZXh0dXJlRGF0YTogVGV4dHVyZURhdGEpOiBQcm9taXNlPFRlbnNvci5OdW1iZXJUeXBlPiB7XG4gICAgaWYgKHRleHR1cmVEYXRhLmlzUGFja2VkKSB7XG4gICAgICByZXR1cm4gdGhpcy5yZWFkVGV4dHVyZUFzeW5jKHRoaXMudW5wYWNrKHRleHR1cmVEYXRhKSk7XG4gICAgfVxuICAgIGlmICghdGhpcy5zZXNzaW9uLmJhY2tlbmQuZ2xDb250ZXh0LmlzRmxvYXQzMkRvd25sb2FkU3VwcG9ydGVkKSB7XG4gICAgICByZXR1cm4gdGhpcy5zZXNzaW9uLnRleHR1cmVNYW5hZ2VyLnJlYWRVaW50OFRleHR1cmVBc0Zsb2F0KGVuY29kZUFzVWludDgodGhpcywgdGV4dHVyZURhdGEpKTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuc2Vzc2lvbi50ZXh0dXJlTWFuYWdlci5yZWFkVGV4dHVyZUFzeW5jKHRleHR1cmVEYXRhLCB0ZXh0dXJlRGF0YS50ZW5zb3IudHlwZSwgdGV4dHVyZURhdGEuY2hhbm5lbHMpO1xuICB9XG5cbiAgcGFjayhpbnB1dDogVGV4dHVyZURhdGEpOiBUZXh0dXJlRGF0YSB7XG4gICAgY29uc3Qgb3V0cHV0VGV4dHVyZURhdGEgPSB0aGlzLmV4ZWN1dGVQcm9ncmFtKGNyZWF0ZVBhY2tQcm9ncmFtSW5mb0xvYWRlcih0aGlzLCBpbnB1dC50ZW5zb3IpLCBbaW5wdXQudGVuc29yXSk7XG4gICAgcmV0dXJuIG91dHB1dFRleHR1cmVEYXRhO1xuICB9XG5cbiAgdW5wYWNrKGlucHV0OiBUZXh0dXJlRGF0YSk6IFRleHR1cmVEYXRhIHtcbiAgICBjb25zdCBvdXRwdXRUZXh0dXJlRGF0YSA9IHRoaXMuZXhlY3V0ZVByb2dyYW0oY3JlYXRlVW5wYWNrUHJvZ3JhbUluZm9Mb2FkZXIodGhpcywgaW5wdXQudGVuc29yKSwgW2lucHV0LnRlbnNvcl0pO1xuICAgIHJldHVybiBvdXRwdXRUZXh0dXJlRGF0YTtcbiAgfVxufVxuIiwiLy8gQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXG5cbmltcG9ydCB7T3BTZXR9IGZyb20gJy4uLy4uL29wc2V0JztcblxuaW1wb3J0IHtiYXRjaE5vcm1hbGl6YXRpb24sIHBhcnNlQmF0Y2hOb3JtYWxpemF0aW9uQXR0cmlidXRlc30gZnJvbSAnLi9vcHMvYmF0Y2gtbm9ybWFsaXphdGlvbic7XG5pbXBvcnQgKiBhcyBiaW5hcnlPcHMgZnJvbSAnLi9vcHMvYmluYXJ5LW9wJztcbmltcG9ydCB7Y2FzdCwgcGFyc2VDYXN0QXR0cmlidXRlc30gZnJvbSAnLi9vcHMvY2FzdCc7XG5pbXBvcnQge2NvbmNhdCwgcGFyc2VDb25jYXRBdHRyaWJ1dGVzfSBmcm9tICcuL29wcy9jb25jYXQnO1xuaW1wb3J0IHtjb252LCBwYXJzZUNvbnZBdHRyaWJ1dGVzfSBmcm9tICcuL29wcy9jb252JztcbmltcG9ydCB7Y29udlRyYW5zcG9zZSwgcGFyc2VDb252VHJhbnNwb3NlQXR0cmlidXRlc30gZnJvbSAnLi9vcHMvY29udi10cmFuc3Bvc2UnO1xuaW1wb3J0IHtkZXB0aFRvU3BhY2UsIHBhcnNlRGVwdGhUb1NwYWNlQXR0cmlidXRlc30gZnJvbSAnLi9vcHMvZGVwdGgtdG8tc3BhY2UnO1xuaW1wb3J0IHtmbGF0dGVuLCBwYXJzZUZsYXR0ZW5BdHRyaWJ1dGVzfSBmcm9tICcuL29wcy9mbGF0dGVuJztcbmltcG9ydCB7Z2F0aGVyLCBwYXJzZUdhdGhlckF0dHJpYnV0ZXN9IGZyb20gJy4vb3BzL2dhdGhlcic7XG5pbXBvcnQge2dlbW0sIHBhcnNlR2VtbUF0dHJpYnV0ZXNWMTEsIHBhcnNlR2VtbUF0dHJpYnV0ZXNWN30gZnJvbSAnLi9vcHMvZ2VtbSc7XG5pbXBvcnQge2ltYWdlU2NhbGVyLCBwYXJzZUltYWdlU2NhbGVyQXR0cmlidXRlc30gZnJvbSAnLi9vcHMvaW1hZ2Utc2NhbGVyJztcbmltcG9ydCB7aW5zdGFuY2VOb3JtYWxpemF0aW9uLCBwYXJzZUluc3RhbmNlTm9ybWFsaXphdGlvbkF0dHJpYnV0ZXN9IGZyb20gJy4vb3BzL2luc3RhbmNlLW5vcm1hbGl6YXRpb24nO1xuaW1wb3J0IHttYXRNdWwsIHBhcnNlTWF0TXVsQXR0cmlidXRlc30gZnJvbSAnLi9vcHMvbWF0bXVsJztcbmltcG9ydCB7cGFkVjExLCBwYWRWMiwgcGFyc2VQYWRBdHRyaWJ1dGVzVjExLCBwYXJzZVBhZEF0dHJpYnV0ZXNWMn0gZnJvbSAnLi9vcHMvcGFkJztcbmltcG9ydCB7YXZlcmFnZVBvb2wsIGdsb2JhbEF2ZXJhZ2VQb29sLCBnbG9iYWxNYXhQb29sLCBtYXhQb29sLCBwYXJzZUF2ZXJhZ2VQb29sQXR0cmlidXRlcywgcGFyc2VHbG9iYWxBdmVyYWdlUG9vbEF0dHJpYnV0ZXMsIHBhcnNlTWF4UG9vbEF0dHJpYnV0ZXN9IGZyb20gJy4vb3BzL3Bvb2wnO1xuaW1wb3J0IHtwYXJzZVJlZHVjZUF0dHJpYnV0ZXMsIHJlZHVjZUxvZ1N1bSwgcmVkdWNlTG9nU3VtU3F1YXJlLCByZWR1Y2VNYXgsIHJlZHVjZU1lYW4sIHJlZHVjZU1pbiwgcmVkdWNlUHJvZCwgcmVkdWNlU3VtfSBmcm9tICcuL29wcy9yZWR1Y2UnO1xuaW1wb3J0IHtyZXNoYXBlfSBmcm9tICcuL29wcy9yZXNoYXBlJztcbmltcG9ydCB7cGFyc2VSZXNpemVBdHRyaWJ1dGVzVjEwLCBwYXJzZVJlc2l6ZUF0dHJpYnV0ZXNWMTEsIHJlc2l6ZX0gZnJvbSAnLi9vcHMvcmVzaXplLXBhY2tlZCc7XG5pbXBvcnQge3NoYXBlfSBmcm9tICcuL29wcy9zaGFwZSc7XG5pbXBvcnQge3BhcnNlU2xpY2VBdHRyaWJ1dGVzLCBzbGljZSwgc2xpY2VWMTB9IGZyb20gJy4vb3BzL3NsaWNlJztcbmltcG9ydCB7cGFyc2VTb2Z0bWF4QXR0cmlidXRlcywgcGFyc2VTb2Z0bWF4QXR0cmlidXRlc1YxMywgc29mdG1heCwgc29mdG1heFYxM30gZnJvbSAnLi9vcHMvc29mdG1heCc7XG5pbXBvcnQge3BhcnNlU3BsaXRBdHRyaWJ1dGVzLCBzcGxpdH0gZnJvbSAnLi9vcHMvc3BsaXQnO1xuaW1wb3J0IHtwYXJzZVNxdWVlemVBdHRyaWJ1dGVzLCBzcXVlZXplLCBzcXVlZXplVjEzfSBmcm9tICcuL29wcy9zcXVlZXplJztcbmltcG9ydCB7c3VtfSBmcm9tICcuL29wcy9zdW0nO1xuaW1wb3J0IHt0aWxlfSBmcm9tICcuL29wcy90aWxlJztcbmltcG9ydCB7cGFyc2VUcmFuc3Bvc2VBdHRyaWJ1dGVzLCB0cmFuc3Bvc2V9IGZyb20gJy4vb3BzL3RyYW5zcG9zZSc7XG5pbXBvcnQgKiBhcyB1bmFyeU9wcyBmcm9tICcuL29wcy91bmFyeS1vcCc7XG5pbXBvcnQge3BhcnNlVW5zcXVlZXplQXR0cmlidXRlcywgdW5zcXVlZXplLCB1bnNxdWVlemVWMTN9IGZyb20gJy4vb3BzL3Vuc3F1ZWV6ZSc7XG5pbXBvcnQge3BhcnNlVXBzYW1wbGVBdHRyaWJ1dGVzVjcsIHBhcnNlVXBzYW1wbGVBdHRyaWJ1dGVzVjksIHVwc2FtcGxlfSBmcm9tICcuL29wcy91cHNhbXBsZSc7XG5cbmV4cG9ydCBjb25zdCBXRUJHTF9PUF9SRVNPTFZFX1JVTEVTOiByZWFkb25seSBPcFNldC5SZXNvbHZlUnVsZVtdID0gW1xuICBbJ0FicycsICcnLCAnNisnLCB1bmFyeU9wcy5hYnNdLFxuICBbJ0Fjb3MnLCAnJywgJzcrJywgdW5hcnlPcHMuYWNvc10sXG4gIFsnQWRkJywgJycsICc3KycsIGJpbmFyeU9wcy5hZGRdLFxuICBbJ0FuZCcsICcnLCAnNysnLCBiaW5hcnlPcHMuYW5kXSxcbiAgWydBc2luJywgJycsICc3KycsIHVuYXJ5T3BzLmFzaW5dLFxuICBbJ0F0YW4nLCAnJywgJzcrJywgdW5hcnlPcHMuYXRhbl0sXG4gIC8vIFRPRE86IHN1cHBvcnQgbmV3IGF0dHJpYnV0ZXMgZm9yIEF2ZXJhZ2VQb29sLTEwXG4gIFsnQXZlcmFnZVBvb2wnLCAnJywgJzcrJywgYXZlcmFnZVBvb2wsIHBhcnNlQXZlcmFnZVBvb2xBdHRyaWJ1dGVzXSxcbiAgWydCYXRjaE5vcm1hbGl6YXRpb24nLCAnJywgJzcrJywgYmF0Y2hOb3JtYWxpemF0aW9uLCBwYXJzZUJhdGNoTm9ybWFsaXphdGlvbkF0dHJpYnV0ZXNdLFxuICBbJ0Nhc3QnLCAnJywgJzYrJywgY2FzdCwgcGFyc2VDYXN0QXR0cmlidXRlc10sXG4gIFsnQ2VpbCcsICcnLCAnNisnLCB1bmFyeU9wcy5jZWlsXSxcbiAgWydDbGlwJywgJycsICc2LTEwJywgdW5hcnlPcHMuY2xpcCwgdW5hcnlPcHMucGFyc2VDbGlwQXR0cmlidXRlc10sXG4gIFsnQ2xpcCcsICcnLCAnMTErJywgdW5hcnlPcHMuY2xpcFYxMV0sXG4gIFsnQ29uY2F0JywgJycsICc0KycsIGNvbmNhdCwgcGFyc2VDb25jYXRBdHRyaWJ1dGVzXSxcbiAgWydDb252JywgJycsICcxKycsIGNvbnYsIHBhcnNlQ29udkF0dHJpYnV0ZXNdLFxuICBbJ0NvbnZUcmFuc3Bvc2UnLCAnJywgJzErJywgY29udlRyYW5zcG9zZSwgcGFyc2VDb252VHJhbnNwb3NlQXR0cmlidXRlc10sXG4gIFsnQ29zJywgJycsICc3KycsIHVuYXJ5T3BzLmNvc10sXG4gIFsnRGl2JywgJycsICc3KycsIGJpbmFyeU9wcy5kaXZdLFxuICBbJ0Ryb3BvdXQnLCAnJywgJzcrJywgdW5hcnlPcHMuaWRlbnRpdHldLFxuICBbJ0RlcHRoVG9TcGFjZScsICcnLCAnMSsnLCBkZXB0aFRvU3BhY2UsIHBhcnNlRGVwdGhUb1NwYWNlQXR0cmlidXRlc10sXG4gIFsnRXF1YWwnLCAnJywgJzcrJywgYmluYXJ5T3BzLmVxdWFsXSxcbiAgWydFbHUnLCAnJywgJzYrJywgdW5hcnlPcHMuZWx1LCB1bmFyeU9wcy5wYXJzZUVsdUF0dHJpYnV0ZXNdLFxuICBbJ0V4cCcsICcnLCAnNisnLCB1bmFyeU9wcy5leHBdLFxuICBbJ0ZsYXR0ZW4nLCAnJywgJzErJywgZmxhdHRlbiwgcGFyc2VGbGF0dGVuQXR0cmlidXRlc10sXG4gIFsnRmxvb3InLCAnJywgJzYrJywgdW5hcnlPcHMuZmxvb3JdLFxuICBbJ0Z1c2VkQ29udicsICdjb20ubWljcm9zb2Z0JywgJzErJywgY29udiwgcGFyc2VDb252QXR0cmlidXRlc10sXG4gIFsnR2F0aGVyJywgJycsICcxKycsIGdhdGhlciwgcGFyc2VHYXRoZXJBdHRyaWJ1dGVzXSxcbiAgWydHZW1tJywgJycsICc3LTEwJywgZ2VtbSwgcGFyc2VHZW1tQXR0cmlidXRlc1Y3XSxcbiAgWydHZW1tJywgJycsICcxMSsnLCBnZW1tLCBwYXJzZUdlbW1BdHRyaWJ1dGVzVjExXSxcbiAgWydHbG9iYWxBdmVyYWdlUG9vbCcsICcnLCAnMSsnLCBnbG9iYWxBdmVyYWdlUG9vbCwgcGFyc2VHbG9iYWxBdmVyYWdlUG9vbEF0dHJpYnV0ZXNdLFxuICBbJ0dsb2JhbE1heFBvb2wnLCAnJywgJzErJywgZ2xvYmFsTWF4UG9vbF0sXG4gIFsnR3JlYXRlcicsICcnLCAnNysnLCBiaW5hcnlPcHMuZ3JlYXRlcl0sXG4gIFsnSWRlbnRpdHknLCAnJywgJzErJywgdW5hcnlPcHMuaWRlbnRpdHldLFxuICBbJ0ltYWdlU2NhbGVyJywgJycsICcxKycsIGltYWdlU2NhbGVyLCBwYXJzZUltYWdlU2NhbGVyQXR0cmlidXRlc10sXG4gIFsnSW5zdGFuY2VOb3JtYWxpemF0aW9uJywgJycsICc2KycsIGluc3RhbmNlTm9ybWFsaXphdGlvbiwgcGFyc2VJbnN0YW5jZU5vcm1hbGl6YXRpb25BdHRyaWJ1dGVzXSxcbiAgWydMZWFreVJlbHUnLCAnJywgJzYrJywgdW5hcnlPcHMubGVha3lSZWx1LCB1bmFyeU9wcy5wYXJzZUxlYWt5UmVsdUF0dHJpYnV0ZXNdLFxuICBbJ0xlc3MnLCAnJywgJzcrJywgYmluYXJ5T3BzLmxlc3NdLFxuICBbJ0xvZycsICcnLCAnNisnLCB1bmFyeU9wcy5sb2ddLFxuICBbJ01hdE11bCcsICcnLCAnMSsnLCBtYXRNdWwsIHBhcnNlTWF0TXVsQXR0cmlidXRlc10sXG4gIC8vIFRPRE86IHN1cHBvcnQgbmV3IGF0dHJpYnV0ZXMgZm9yIE1heFBvb2wtOCBhbmQgTWF4UG9vbC0xMFxuICBbJ01heFBvb2wnLCAnJywgJzErJywgbWF4UG9vbCwgcGFyc2VNYXhQb29sQXR0cmlidXRlc10sXG4gIFsnTXVsJywgJycsICc3KycsIGJpbmFyeU9wcy5tdWxdLFxuICBbJ05lZycsICcnLCAnNisnLCB1bmFyeU9wcy5uZWddLFxuICBbJ05vdCcsICcnLCAnMSsnLCB1bmFyeU9wcy5ub3RdLFxuICBbJ09yJywgJycsICc3KycsIGJpbmFyeU9wcy5vcl0sXG4gIFsnUGFkJywgJycsICcyLTEwJywgcGFkVjIsIHBhcnNlUGFkQXR0cmlidXRlc1YyXSxcbiAgWydQYWQnLCAnJywgJzExKycsIHBhZFYxMSwgcGFyc2VQYWRBdHRyaWJ1dGVzVjExXSxcbiAgWydQb3cnLCAnJywgJzcrJywgYmluYXJ5T3BzLnBvd10sXG4gIFsnUFJlbHUnLCAnJywgJzcrJywgYmluYXJ5T3BzLnBSZWx1XSxcbiAgWydSZWR1Y2VMb2dTdW0nLCAnJywgJzErJywgcmVkdWNlTG9nU3VtLCBwYXJzZVJlZHVjZUF0dHJpYnV0ZXNdLFxuICBbJ1JlZHVjZU1heCcsICcnLCAnMSsnLCByZWR1Y2VNYXgsIHBhcnNlUmVkdWNlQXR0cmlidXRlc10sXG4gIFsnUmVkdWNlTWVhbicsICcnLCAnMSsnLCByZWR1Y2VNZWFuLCBwYXJzZVJlZHVjZUF0dHJpYnV0ZXNdLFxuICBbJ1JlZHVjZU1pbicsICcnLCAnMSsnLCByZWR1Y2VNaW4sIHBhcnNlUmVkdWNlQXR0cmlidXRlc10sXG4gIFsnUmVkdWNlUHJvZCcsICcnLCAnMSsnLCByZWR1Y2VQcm9kLCBwYXJzZVJlZHVjZUF0dHJpYnV0ZXNdLFxuICBbJ1JlZHVjZVN1bScsICcnLCAnMS0xMicsIHJlZHVjZVN1bSwgcGFyc2VSZWR1Y2VBdHRyaWJ1dGVzXSxcbiAgWydSZWR1Y2VTdW1TcXVhcmUnLCAnJywgJzErJywgcmVkdWNlTG9nU3VtU3F1YXJlLCBwYXJzZVJlZHVjZUF0dHJpYnV0ZXNdLFxuICBbJ1JlbHUnLCAnJywgJzYrJywgdW5hcnlPcHMucmVsdV0sXG4gIFsnUmVzaGFwZScsICcnLCAnNSsnLCByZXNoYXBlXSxcbiAgWydSZXNpemUnLCAnJywgJzEwJywgcmVzaXplLCBwYXJzZVJlc2l6ZUF0dHJpYnV0ZXNWMTBdLFxuICBbJ1Jlc2l6ZScsICcnLCAnMTErJywgcmVzaXplLCBwYXJzZVJlc2l6ZUF0dHJpYnV0ZXNWMTFdLFxuICBbJ1NoYXBlJywgJycsICcxKycsIHNoYXBlXSxcbiAgWydTaWdtb2lkJywgJycsICc2KycsIHVuYXJ5T3BzLnNpZ21vaWRdLFxuICBbJ1NpbicsICcnLCAnNysnLCB1bmFyeU9wcy5zaW5dLFxuICBbJ1NsaWNlJywgJycsICcxMCsnLCBzbGljZVYxMF0sICAvLyBUT0RPOiBzdXBwb3J0ICdzdGVwcycgZm9yIFNsaWNlLTEwXG4gIFsnU2xpY2UnLCAnJywgJzEtOScsIHNsaWNlLCBwYXJzZVNsaWNlQXR0cmlidXRlc10sXG4gIC8vIFRoZSBcInNlbWFudGljXCIgbWVhbmluZyBvZiBheGlzIGhhcyBjaGFuZ2VkIGluIG9wc2V0LTEzLlxuICBbJ1NvZnRtYXgnLCAnJywgJzEtMTInLCBzb2Z0bWF4LCBwYXJzZVNvZnRtYXhBdHRyaWJ1dGVzXSxcbiAgWydTb2Z0bWF4JywgJycsICcxMysnLCBzb2Z0bWF4VjEzLCBwYXJzZVNvZnRtYXhBdHRyaWJ1dGVzVjEzXSxcbiAgLy8gJ1NwbGl0JyBvcGVyYXRvciBoYXMgYW4gb3B0aW9uYWwgYXR0cmlidXRlICdzcGxpdCdcbiAgLy8gdGhpcyBhdHRyaWJ1dGUgZGV0ZXJtaW5lcyBob3cgdGhlIHNwZWNpZmllZCBheGlzIG9mIGlucHV0IGRhdGEgaXMgc3BsaXQuXG4gIC8vIFdoZW4gdGhlIGF0dHJpYnV0ZSBpcyBtaXNzaW5nLCB3ZSBuZWVkIHRoZSBjb3VudCBvZiBudW1iZXIgb2Ygb3V0cHV0c1xuICAvLyBzbyB0aGF0IHdlIGNhbiBkZXRlcm1pbmUgdGhlICdzcGxpdCcgYXR0cmlidXRlIGZyb20gdGhlIHJ1bnRpbWUgaW5wdXQgdG8gdGhlIE9wZXJhdG9yXG4gIFsnU3BsaXQnLCAnJywgJzItMTInLCBzcGxpdCwgcGFyc2VTcGxpdEF0dHJpYnV0ZXNdLFxuICBbJ1NxcnQnLCAnJywgJzYrJywgdW5hcnlPcHMuc3FydF0sXG4gIFsnU3F1ZWV6ZScsICcnLCAnMS0xMicsIHNxdWVlemUsIHBhcnNlU3F1ZWV6ZUF0dHJpYnV0ZXNdLFxuICBbJ1NxdWVlemUnLCAnJywgJzEzKycsIHNxdWVlemVWMTNdLFxuICBbJ1N1YicsICcnLCAnNysnLCBiaW5hcnlPcHMuc3ViXSxcbiAgWydTdW0nLCAnJywgJzYrJywgc3VtXSxcbiAgWydUYW4nLCAnJywgJzcrJywgdW5hcnlPcHMudGFuXSxcbiAgWydUYW5oJywgJycsICc2KycsIHVuYXJ5T3BzLnRhbmhdLFxuICBbJ1RpbGUnLCAnJywgJzYrJywgdGlsZV0sXG4gIFsnVHJhbnNwb3NlJywgJycsICcxKycsIHRyYW5zcG9zZSwgcGFyc2VUcmFuc3Bvc2VBdHRyaWJ1dGVzXSxcbiAgWydVcHNhbXBsZScsICcnLCAnNy04JywgdXBzYW1wbGUsIHBhcnNlVXBzYW1wbGVBdHRyaWJ1dGVzVjddLFxuICBbJ1Vwc2FtcGxlJywgJycsICc5JywgdXBzYW1wbGUsIHBhcnNlVXBzYW1wbGVBdHRyaWJ1dGVzVjldLFxuICBbJ1Vuc3F1ZWV6ZScsICcnLCAnMS0xMicsIHVuc3F1ZWV6ZSwgcGFyc2VVbnNxdWVlemVBdHRyaWJ1dGVzXSxcbiAgWydVbnNxdWVlemUnLCAnJywgJzEzKycsIHVuc3F1ZWV6ZVYxM10sXG4gIFsnWG9yJywgJycsICc3KycsIGJpbmFyeU9wcy54b3JdLFxuXTtcbiIsIi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxuXG5pbXBvcnQge0F0dHJpYnV0ZVdpdGhDYWNoZUtleSwgY3JlYXRlQXR0cmlidXRlV2l0aENhY2hlS2V5fSBmcm9tICcuLi8uLi8uLi9hdHRyaWJ1dGUtd2l0aC1jYWNoZS1rZXknO1xuaW1wb3J0IHtHcmFwaH0gZnJvbSAnLi4vLi4vLi4vZ3JhcGgnO1xuaW1wb3J0IHtPcGVyYXRvckltcGxlbWVudGF0aW9uLCBPcGVyYXRvckluaXRpYWxpemF0aW9ufSBmcm9tICcuLi8uLi8uLi9vcGVyYXRvcnMnO1xuaW1wb3J0IHtUZW5zb3J9IGZyb20gJy4uLy4uLy4uL3RlbnNvcic7XG5pbXBvcnQge2dldEdsc2x9IGZyb20gJy4uL2dsc2wtc291cmNlJztcbmltcG9ydCB7V2ViR0xJbmZlcmVuY2VIYW5kbGVyfSBmcm9tICcuLi9pbmZlcmVuY2UtaGFuZGxlcic7XG5pbXBvcnQge1Byb2dyYW1JbmZvLCBUZXh0dXJlVHlwZX0gZnJvbSAnLi4vdHlwZXMnO1xuXG5leHBvcnQgaW50ZXJmYWNlIEJhdGNoTm9ybWFsaXphdGlvbkF0dHJpYnV0ZXMgZXh0ZW5kcyBBdHRyaWJ1dGVXaXRoQ2FjaGVLZXkge1xuICBlcHNpbG9uOiBudW1iZXI7XG4gIG1vbWVudHVtOiBudW1iZXI7XG4gIHNwYXRpYWw6IG51bWJlcjtcbn1cblxuY29uc3QgYmF0Y2hOb3JtYWxpemF0aW9uUHJvZ3JhbU1ldGFkYXRhID0ge1xuICBuYW1lOiAnQmF0Y2hOb3JtYWxpemF0aW9uJyxcbiAgaW5wdXROYW1lczogWydBJywgJ1NjYWxlJywgJ0InLCAnTWVhbicsICdWYXJpYW5jZSddLFxuICBpbnB1dFR5cGVzOlxuICAgICAgW1RleHR1cmVUeXBlLnVucGFja2VkLCBUZXh0dXJlVHlwZS51bnBhY2tlZCwgVGV4dHVyZVR5cGUudW5wYWNrZWQsIFRleHR1cmVUeXBlLnVucGFja2VkLCBUZXh0dXJlVHlwZS51bnBhY2tlZF1cbn07XG5cbmV4cG9ydCBjb25zdCBiYXRjaE5vcm1hbGl6YXRpb246IE9wZXJhdG9ySW1wbGVtZW50YXRpb248QmF0Y2hOb3JtYWxpemF0aW9uQXR0cmlidXRlcz4gPVxuICAgIChpbmZlcmVuY2VIYW5kbGVyOiBXZWJHTEluZmVyZW5jZUhhbmRsZXIsIGlucHV0czogVGVuc29yW10sIGF0dHJpYnV0ZXM6IEJhdGNoTm9ybWFsaXphdGlvbkF0dHJpYnV0ZXMpOiBUZW5zb3JbXSA9PiB7XG4gICAgICB2YWxpZGF0ZUlucHV0cyhpbnB1dHMpO1xuICAgICAgY29uc3Qgb3V0cHV0ID0gaW5mZXJlbmNlSGFuZGxlci5ydW4oXG4gICAgICAgICAge1xuICAgICAgICAgICAgLi4uYmF0Y2hOb3JtYWxpemF0aW9uUHJvZ3JhbU1ldGFkYXRhLFxuICAgICAgICAgICAgY2FjaGVIaW50OiBhdHRyaWJ1dGVzLmNhY2hlS2V5LFxuICAgICAgICAgICAgZ2V0OiAoKSA9PiBjcmVhdGVCYXRjaE5vcm1hbGl6YXRpb25Qcm9ncmFtSW5mbyhpbmZlcmVuY2VIYW5kbGVyLCBpbnB1dHMsIGF0dHJpYnV0ZXMpXG4gICAgICAgICAgfSxcbiAgICAgICAgICBpbnB1dHMpO1xuICAgICAgcmV0dXJuIFtvdXRwdXRdO1xuICAgIH07XG5cbmV4cG9ydCBjb25zdCBwYXJzZUJhdGNoTm9ybWFsaXphdGlvbkF0dHJpYnV0ZXM6IE9wZXJhdG9ySW5pdGlhbGl6YXRpb248QmF0Y2hOb3JtYWxpemF0aW9uQXR0cmlidXRlcz4gPVxuICAgIChub2RlOiBHcmFwaC5Ob2RlKTogQmF0Y2hOb3JtYWxpemF0aW9uQXR0cmlidXRlcyA9PiB7XG4gICAgICBjb25zdCBlcHNpbG9uID0gbm9kZS5hdHRyaWJ1dGVzLmdldEZsb2F0KCdlcHNpbG9uJywgMWUtNSk7XG4gICAgICBjb25zdCBtb21lbnR1bSA9IG5vZGUuYXR0cmlidXRlcy5nZXRGbG9hdCgnbW9tZW50dW0nLCAwLjkpO1xuICAgICAgY29uc3Qgc3BhdGlhbCA9IG5vZGUuYXR0cmlidXRlcy5nZXRJbnQoJ3NwYXRpYWwnLCAxKTtcbiAgICAgIHJldHVybiBjcmVhdGVBdHRyaWJ1dGVXaXRoQ2FjaGVLZXkoe2Vwc2lsb24sIG1vbWVudHVtLCBzcGF0aWFsfSk7XG4gICAgfTtcblxuY29uc3QgY3JlYXRlQmF0Y2hOb3JtYWxpemF0aW9uUHJvZ3JhbUluZm8gPVxuICAgIChpbmZlcmVuY2VIYW5kbGVyOiBXZWJHTEluZmVyZW5jZUhhbmRsZXIsIGlucHV0czogVGVuc29yW10sIGF0dHJpYnV0ZXM6IEJhdGNoTm9ybWFsaXphdGlvbkF0dHJpYnV0ZXMpOlxuICAgICAgICBQcm9ncmFtSW5mbyA9PiB7XG4gICAgICAgICAgY29uc3QgZ2xzbCA9IGdldEdsc2woaW5mZXJlbmNlSGFuZGxlci5zZXNzaW9uLmJhY2tlbmQuZ2xDb250ZXh0LnZlcnNpb24pO1xuICAgICAgICAgIGNvbnN0IHJhbmsgPSBpbnB1dHNbMF0uZGltcy5sZW5ndGg7XG4gICAgICAgICAgY29uc3QgW3NjYWxlV2lkdGgsIHNjYWxlSGVpZ2h0XSA9XG4gICAgICAgICAgICAgIGluZmVyZW5jZUhhbmRsZXIuY2FsY3VsYXRlVGV4dHVyZVdpZHRoQW5kSGVpZ2h0KGlucHV0c1sxXS5kaW1zLCBUZXh0dXJlVHlwZS51bnBhY2tlZCk7XG4gICAgICAgICAgY29uc3Qgc2hhZGVyU291cmNlID0gYFxuICBmbG9hdCBwcm9jZXNzKGludFske3Jhbmt9XSBpbmRpY2VzKSB7XG4gICAgdmVjMiBwb3NpdGlvbiA9IG9mZnNldFRvQ29vcmRzKGluZGljZXNbMV0sICR7c2NhbGVXaWR0aH0sICR7c2NhbGVIZWlnaHR9KTtcbiAgICBmbG9hdCBzY2FsZSA9IGdldENvbG9yQXNGbG9hdCgke2dsc2wudGV4dHVyZTJEfShTY2FsZSwgcG9zaXRpb24pKTtcbiAgICBmbG9hdCBtZWFuID0gZ2V0Q29sb3JBc0Zsb2F0KCR7Z2xzbC50ZXh0dXJlMkR9KE1lYW4sIHBvc2l0aW9uKSk7XG4gICAgZmxvYXQgdmFyaWFuY2UgPSBnZXRDb2xvckFzRmxvYXQoJHtnbHNsLnRleHR1cmUyRH0oVmFyaWFuY2UsIHBvc2l0aW9uKSk7XG4gICAgZmxvYXQgYiA9IGdldENvbG9yQXNGbG9hdCgke2dsc2wudGV4dHVyZTJEfShCLCBwb3NpdGlvbikpO1xuXG4gICAgcmV0dXJuIHNjYWxlICogKCAoX0EoaW5kaWNlcykgLSBtZWFuKSAvIHNxcnQodmFyaWFuY2UgKyBmbG9hdCgke2F0dHJpYnV0ZXMuZXBzaWxvbn0pKSApICsgYjtcbiAgfWA7XG4gICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIC4uLmJhdGNoTm9ybWFsaXphdGlvblByb2dyYW1NZXRhZGF0YSxcbiAgICAgICAgICAgIG91dHB1dDoge2RpbXM6IGlucHV0c1swXS5kaW1zLCB0eXBlOiBpbnB1dHNbMF0udHlwZSwgdGV4dHVyZVR5cGU6IFRleHR1cmVUeXBlLnVucGFja2VkfSxcbiAgICAgICAgICAgIHNoYWRlclNvdXJjZVxuICAgICAgICAgIH07XG4gICAgICAgIH07XG5cbmNvbnN0IHZhbGlkYXRlSW5wdXRzID0gKGlucHV0czogVGVuc29yW10pOiB2b2lkID0+IHtcbiAgaWYgKCFpbnB1dHMgfHwgaW5wdXRzLmxlbmd0aCAhPT0gNSkge1xuICAgIHRocm93IG5ldyBFcnJvcignQmF0Y2hOb3JtYWxpemF0aW9uIHJlcXVpcmVzIDUgaW5wdXRzLicpO1xuICB9XG5cbiAgY29uc3QgWCA9IGlucHV0c1swXTtcbiAgY29uc3Qgc2NhbGUgPSBpbnB1dHNbMV07XG4gIGNvbnN0IEIgPSBpbnB1dHNbMl07XG4gIGNvbnN0IG1lYW4gPSBpbnB1dHNbM107XG4gIGNvbnN0IHZhcl8gPSBpbnB1dHNbNF07XG5cbiAgLy8gaW5wdXQgc2hvdWxkIGF0bGVhc3QgaGF2ZSB0aHJlZSBkaW1lbnNpb25zIC0gTixDLGRpbTEsLi4uLGRpbW5cbiAgLy8gb3RoZXIgaW5wdXRzIGNhbiBoYXZlIG9ubHkgb25lIGRpbWVuc2lvbnNcbiAgaWYgKFguZGltcy5sZW5ndGggPCAzIHx8IHNjYWxlLmRpbXMubGVuZ3RoICE9PSAxIHx8IEIuZGltcy5sZW5ndGggIT09IDEgfHwgbWVhbi5kaW1zLmxlbmd0aCAhPT0gMSB8fFxuICAgICAgdmFyXy5kaW1zLmxlbmd0aCAhPT0gMSkge1xuICAgIHRocm93IG5ldyBFcnJvcignaW52YWxpZCBpbnB1dCBzaGFwZS4nKTtcbiAgfVxuICBpZiAoc2NhbGUuZGltc1swXSAhPT0gWC5kaW1zWzFdIHx8IEIuZGltc1swXSAhPT0gWC5kaW1zWzFdIHx8IG1lYW4uZGltc1swXSAhPT0gWC5kaW1zWzFdIHx8XG4gICAgICB2YXJfLmRpbXNbMF0gIT09IFguZGltc1sxXSkge1xuICAgIHRocm93IG5ldyBFcnJvcignaW52YWxpZCBpbnB1dCBzaGFwZS4nKTtcbiAgfVxuICBpZiAoKFgudHlwZSAhPT0gJ2Zsb2F0MzInICYmIFgudHlwZSAhPT0gJ2Zsb2F0NjQnKSB8fCAoc2NhbGUudHlwZSAhPT0gJ2Zsb2F0MzInICYmIHNjYWxlLnR5cGUgIT09ICdmbG9hdDY0JykgfHxcbiAgICAgIChCLnR5cGUgIT09ICdmbG9hdDMyJyAmJiBCLnR5cGUgIT09ICdmbG9hdDY0JykgfHwgKG1lYW4udHlwZSAhPT0gJ2Zsb2F0MzInICYmIG1lYW4udHlwZSAhPT0gJ2Zsb2F0NjQnKSB8fFxuICAgICAgKHZhcl8udHlwZSAhPT0gJ2Zsb2F0MzInICYmIHZhcl8udHlwZSAhPT0gJ2Zsb2F0NjQnKSkge1xuICAgIHRocm93IG5ldyBFcnJvcignaW52YWxpZCBpbnB1dCB0ZW5zb3IgdHlwZXMuJyk7XG4gIH1cbn07XG4iLCIvLyBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cblxuaW1wb3J0IHtUZW5zb3J9IGZyb20gJy4uLy4uLy4uL3RlbnNvcic7XG5pbXBvcnQge0Jyb2FkY2FzdFV0aWwsIFNoYXBlVXRpbH0gZnJvbSAnLi4vLi4vLi4vdXRpbCc7XG5pbXBvcnQge0Z1bmN0aW9uVHlwZSwgR2xzbFZhbHVlRnVuY3Rpb259IGZyb20gJy4uL2dsc2wtZGVmaW5pdGlvbnMnO1xuaW1wb3J0IHtnZXRHbHNsfSBmcm9tICcuLi9nbHNsLXNvdXJjZSc7XG5pbXBvcnQge1dlYkdMSW5mZXJlbmNlSGFuZGxlcn0gZnJvbSAnLi4vaW5mZXJlbmNlLWhhbmRsZXInO1xuaW1wb3J0IHtQcm9ncmFtSW5mbywgUHJvZ3JhbUluZm9Mb2FkZXIsIFRleHR1cmVUeXBlfSBmcm9tICcuLi90eXBlcyc7XG5cbmV4cG9ydCBmdW5jdGlvbiBnbHNsQWRkKCk6IEdsc2xWYWx1ZUZ1bmN0aW9uIHtcbiAgY29uc3QgbmFtZSA9ICdhZGRfJztcbiAgY29uc3QgYm9keSA9IGBcbiAgZmxvYXQgJHtuYW1lfShmbG9hdCBhLCBmbG9hdCBiKSB7XG4gICAgcmV0dXJuIGEgKyBiO1xuICB9XG4gIHZlYzQgJHtuYW1lfSh2ZWM0IHYxLCB2ZWM0IHYyKSB7XG4gICAgcmV0dXJuIHYxICsgdjI7XG4gIH1cbiAgYDtcbiAgcmV0dXJuIHtib2R5LCBuYW1lLCB0eXBlOiBGdW5jdGlvblR5cGUuVmFsdWVCYXNlZH07XG59XG5leHBvcnQgZnVuY3Rpb24gZ2xzbERpdigpOiBHbHNsVmFsdWVGdW5jdGlvbiB7XG4gIGNvbnN0IG5hbWUgPSAnZGl2Xyc7XG4gIGNvbnN0IGJvZHkgPSBgXG4gIGZsb2F0ICR7bmFtZX0oZmxvYXQgYSwgZmxvYXQgYikge1xuICAgIHJldHVybiBhIC8gYjtcbiAgfVxuICB2ZWM0ICR7bmFtZX0odmVjNCB2MSwgdmVjNCB2Mikge1xuICAgIHJldHVybiB2MSAvIHYyO1xuICB9XG4gIGA7XG4gIHJldHVybiB7Ym9keSwgbmFtZSwgdHlwZTogRnVuY3Rpb25UeXBlLlZhbHVlQmFzZWR9O1xufVxuZXhwb3J0IGZ1bmN0aW9uIGdsc2xNdWwoKTogR2xzbFZhbHVlRnVuY3Rpb24ge1xuICBjb25zdCBuYW1lID0gJ211bF8nO1xuICBjb25zdCBib2R5ID0gYFxuICBmbG9hdCAke25hbWV9KGZsb2F0IGEsIGZsb2F0IGIpIHtcbiAgICByZXR1cm4gYSAqIGI7XG4gIH1cbiAgdmVjNCAke25hbWV9KHZlYzQgdjEsIHZlYzQgdjIpIHtcbiAgICByZXR1cm4gdjEgKiB2MjtcbiAgfVxuICBgO1xuICByZXR1cm4ge2JvZHksIG5hbWUsIHR5cGU6IEZ1bmN0aW9uVHlwZS5WYWx1ZUJhc2VkfTtcbn1cbmV4cG9ydCBmdW5jdGlvbiBnbHNsU3ViKCk6IEdsc2xWYWx1ZUZ1bmN0aW9uIHtcbiAgY29uc3QgbmFtZSA9ICdzdWJfJztcbiAgY29uc3QgYm9keSA9IGBcbiAgZmxvYXQgJHtuYW1lfShmbG9hdCBhLCBmbG9hdCBiKSB7XG4gICAgcmV0dXJuIGEgLSBiO1xuICB9XG4gIHZlYzQgJHtuYW1lfSh2ZWM0IHYxLCB2ZWM0IHYyKSB7XG4gICAgcmV0dXJuIHYxIC0gdjI7XG4gIH1cbiAgYDtcbiAgcmV0dXJuIHtib2R5LCBuYW1lLCB0eXBlOiBGdW5jdGlvblR5cGUuVmFsdWVCYXNlZH07XG59XG5leHBvcnQgZnVuY3Rpb24gZ2xzbEVxdWFsKCk6IEdsc2xWYWx1ZUZ1bmN0aW9uIHtcbiAgY29uc3QgbmFtZSA9ICdlcXVhbF8nO1xuICBjb25zdCBib2R5ID0gYFxuICBmbG9hdCAke25hbWV9KGZsb2F0IGEsIGZsb2F0IGIpIHtcbiAgICByZXR1cm4gZmxvYXQoYSA9PSBiKTtcbiAgfVxuICB2ZWM0ICR7bmFtZX0odmVjNCB2MSwgdmVjNCB2Mikge1xuICAgIHJldHVybiB2ZWM0KGVxdWFsKHYxLCB2MikpO1xuICB9XG4gIGA7XG4gIHJldHVybiB7Ym9keSwgbmFtZSwgdHlwZTogRnVuY3Rpb25UeXBlLlZhbHVlQmFzZWR9O1xufVxuZXhwb3J0IGZ1bmN0aW9uIGdsc2xHcmVhdGVyKCk6IEdsc2xWYWx1ZUZ1bmN0aW9uIHtcbiAgY29uc3QgbmFtZSA9ICdncmVhdGVyXyc7XG4gIGNvbnN0IGJvZHkgPSBgXG4gIGZsb2F0ICR7bmFtZX0oZmxvYXQgYSwgZmxvYXQgYikge1xuICAgIHJldHVybiBmbG9hdChhID4gYik7XG4gIH1cbiAgdmVjNCAke25hbWV9KHZlYzQgdjEsIHZlYzQgdjIpIHtcbiAgICByZXR1cm4gdmVjNCggdjEuciA+IHYyLnIgLFxuICAgICAgdjEuZyA+IHYyLmcsXG4gICAgICB2MS5iID4gdjIuYixcbiAgICAgIHYxLmEgPiB2Mi5hICk7XG4gIH1cbiAgYDtcbiAgcmV0dXJuIHtib2R5LCBuYW1lLCB0eXBlOiBGdW5jdGlvblR5cGUuVmFsdWVCYXNlZH07XG59XG5leHBvcnQgZnVuY3Rpb24gZ2xzbExlc3MoKTogR2xzbFZhbHVlRnVuY3Rpb24ge1xuICBjb25zdCBuYW1lID0gJ2xlc3NfJztcbiAgY29uc3QgYm9keSA9IGBcbiAgZmxvYXQgJHtuYW1lfShmbG9hdCBhLCBmbG9hdCBiKSB7XG4gICAgcmV0dXJuIGZsb2F0KGEgPCBiKTtcbiAgfVxuICB2ZWM0ICR7bmFtZX0odmVjNCB2MSwgdmVjNCB2Mikge1xuICAgIHJldHVybiB2ZWM0KCB2MS5yIDwgdjIuciAsXG4gICAgICAgICAgICAgICAgdjEuZyA8IHYyLmcsXG4gICAgICAgICAgICAgICAgdjEuYiA8IHYyLmIsXG4gICAgICAgICAgICAgICAgdjEuYSA8IHYyLmEgKTtcbiAgfVxuICBgO1xuICByZXR1cm4ge2JvZHksIG5hbWUsIHR5cGU6IEZ1bmN0aW9uVHlwZS5WYWx1ZUJhc2VkfTtcbn1cbmV4cG9ydCBmdW5jdGlvbiBnbHNsQW5kKCk6IEdsc2xWYWx1ZUZ1bmN0aW9uIHtcbiAgY29uc3QgbmFtZSA9ICdhbmRfJztcbiAgY29uc3QgYm9keSA9IGBcbiAgZmxvYXQgJHtuYW1lfShmbG9hdCBhLCBmbG9hdCBiKSB7XG4gICAgcmV0dXJuIGZsb2F0KCBib29sKGEpICYmIGJvb2woYikgKTtcbiAgfVxuICB2ZWM0ICR7bmFtZX0odmVjNCB2MSwgdmVjNCB2Mikge1xuICAgIGJ2ZWM0IGIxID0gYnZlYzQodjEpO1xuICAgIGJ2ZWM0IGIyID0gYnZlYzQodjIpO1xuICAgIHJldHVybiB2ZWM0KCBiMS5yICYmIGIyLnIgLFxuICAgICAgICAgICAgICAgIGIxLmcgJiYgYjIuZyxcbiAgICAgICAgICAgICAgICBiMS5iICYmIGIyLmIsXG4gICAgICAgICAgICAgICAgYjEuYSAmJiBiMi5hICk7XG4gIH1cbiAgYDtcbiAgcmV0dXJuIHtib2R5LCBuYW1lLCB0eXBlOiBGdW5jdGlvblR5cGUuVmFsdWVCYXNlZH07XG59XG5leHBvcnQgZnVuY3Rpb24gZ2xzbE9yKCk6IEdsc2xWYWx1ZUZ1bmN0aW9uIHtcbiAgY29uc3QgbmFtZSA9ICdvcl8nO1xuICBjb25zdCBib2R5ID0gYFxuICBmbG9hdCAke25hbWV9KGZsb2F0IGEsIGZsb2F0IGIpIHtcbiAgICByZXR1cm4gZmxvYXQoIGJvb2woYSkgfHwgYm9vbChiKSApO1xuICB9XG4gIHZlYzQgJHtuYW1lfSh2ZWM0IHYxLCB2ZWM0IHYyKSB7XG4gICAgYnZlYzQgYjEgPSBidmVjNCh2MSk7XG4gICAgYnZlYzQgYjIgPSBidmVjNCh2Mik7XG4gICAgcmV0dXJuIHZlYzQoIGIxLnIgfHwgYjIuciAsXG4gICAgICAgICAgICAgICAgYjEuZyB8fCBiMi5nLFxuICAgICAgICAgICAgICAgIGIxLmIgfHwgYjIuYixcbiAgICAgICAgICAgICAgICBiMS5hIHx8IGIyLmEgKTtcbiAgfVxuICBgO1xuICByZXR1cm4ge2JvZHksIG5hbWUsIHR5cGU6IEZ1bmN0aW9uVHlwZS5WYWx1ZUJhc2VkfTtcbn1cbmV4cG9ydCBmdW5jdGlvbiBnbHNsWG9yKCk6IEdsc2xWYWx1ZUZ1bmN0aW9uIHtcbiAgY29uc3QgbmFtZSA9ICd4b3JfJztcbiAgY29uc3QgYm9keSA9IGBcbiAgZmxvYXQgJHtuYW1lfShmbG9hdCBhLCBmbG9hdCBiKSB7XG4gICAgcmV0dXJuIGZsb2F0KCBib29sKGEpIF5eIGJvb2woYikgKTtcbiAgfVxuICB2ZWM0ICR7bmFtZX0odmVjNCB2MSwgdmVjNCB2Mikge1xuICAgIGJ2ZWM0IGIxID0gYnZlYzQodjEpO1xuICAgIGJ2ZWM0IGIyID0gYnZlYzQodjIpO1xuICAgIHJldHVybiB2ZWM0KCBiMS5yIF5eIGIyLnIgLFxuICAgICAgICAgICAgICAgIGIxLmcgXl4gYjIuZyxcbiAgICAgICAgICAgICAgICBiMS5iIF5eIGIyLmIsXG4gICAgICAgICAgICAgICAgYjEuYSBeXiBiMi5hICk7XG4gIH1cbiAgYDtcbiAgcmV0dXJuIHtib2R5LCBuYW1lLCB0eXBlOiBGdW5jdGlvblR5cGUuVmFsdWVCYXNlZH07XG59XG5leHBvcnQgZnVuY3Rpb24gZ2xzbFBvdygpOiBHbHNsVmFsdWVGdW5jdGlvbiB7XG4gIHJldHVybiBnbHNsQnVpbHRpbkJpbmFyeSgncG93Jyk7XG59XG5leHBvcnQgZnVuY3Rpb24gZ2xzbFBSZWx1KCk6IEdsc2xWYWx1ZUZ1bmN0aW9uIHtcbiAgY29uc3QgbmFtZSA9ICdwcmVsdV8nO1xuICBjb25zdCBib2R5ID0gYFxuICBmbG9hdCAke25hbWV9KGZsb2F0IGEsIGZsb2F0IGIpIHtcbiAgICByZXR1cm4gYSA8IDAuMCA/IGEgKiBiOiBhO1xuICB9XG4gIHZlYzQgJHtuYW1lfSh2ZWM0IHYxLCB2ZWM0IHYyKSB7XG4gICAgcmV0dXJuIHZlYzQoXG4gICAgICB2MS5yIDwgMC4wID8gdjEuciAqIHYyLnI6IHYxLnIsXG4gICAgICB2MS5nIDwgMC4wID8gdjEuZyAqIHYyLmc6IHYxLmcsXG4gICAgICB2MS5iIDwgMC4wID8gdjEuYiAqIHYyLmI6IHYxLmIsXG4gICAgICB2MS5hIDwgMC4wID8gdjEuYSAqIHYyLmE6IHYxLmFcbiAgICAgICk7XG4gIH1cbiAgYDtcbiAgcmV0dXJuIHtib2R5LCBuYW1lLCB0eXBlOiBGdW5jdGlvblR5cGUuVmFsdWVCYXNlZH07XG59XG5cbmZ1bmN0aW9uIGdsc2xCdWlsdGluQmluYXJ5KGZuYW1lOiBzdHJpbmcpOiBHbHNsVmFsdWVGdW5jdGlvbiB7XG4gIGNvbnN0IG5hbWUgPSBgJHtmbmFtZX1fYDtcbiAgY29uc3QgYm9keSA9IGBcbiAgZmxvYXQgJHtuYW1lfShmbG9hdCBhLCBmbG9hdCBiKSB7XG4gICAgcmV0dXJuICR7Zm5hbWV9KGEsIGIpO1xuICB9XG4gIHZlYzQgJHtuYW1lfSh2ZWM0IHYxLCB2ZWM0IHYyKSB7XG4gICAgcmV0dXJuICR7Zm5hbWV9KHYxLCB2Mik7XG4gIH1cbiAgYDtcbiAgcmV0dXJuIHtib2R5LCBuYW1lLCB0eXBlOiBGdW5jdGlvblR5cGUuVmFsdWVCYXNlZH07XG59XG5cbmNvbnN0IGNyZWF0ZUJpbmFyeVByb2dyYW1JbmZvTG9hZGVyID1cbiAgICAoaGFuZGxlcjogV2ViR0xJbmZlcmVuY2VIYW5kbGVyLCBpbnB1dHM6IFRlbnNvcltdLCBnbHNsRnVuYzogR2xzbFZhbHVlRnVuY3Rpb24sXG4gICAgIG91dHB1dFRlbnNvclR5cGU6IFRlbnNvci5EYXRhVHlwZSA9IGlucHV0c1swXS50eXBlLCBjYWNoZUtleT86IHN0cmluZyk6IFByb2dyYW1JbmZvTG9hZGVyID0+IHtcbiAgICAgIGNvbnN0IHRleHR1cmVUeXBlID0gaGFuZGxlci5zZXNzaW9uLnBhY2sgPyBUZXh0dXJlVHlwZS5wYWNrZWQgOiBUZXh0dXJlVHlwZS51bnBhY2tlZDtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIG5hbWU6IGdsc2xGdW5jLm5hbWUsXG4gICAgICAgIGlucHV0TmFtZXM6IFsnQScsICdCJ10sXG4gICAgICAgIGlucHV0VHlwZXM6IFt0ZXh0dXJlVHlwZSwgdGV4dHVyZVR5cGVdLFxuICAgICAgICBjYWNoZUhpbnQ6IGNhY2hlS2V5LFxuICAgICAgICBnZXQ6ICgpID0+IGNyZWF0ZUJpbmFyeVByb2dyYW1JbmZvKGhhbmRsZXIsIGlucHV0cywgZ2xzbEZ1bmMsIG91dHB1dFRlbnNvclR5cGUpXG4gICAgICB9O1xuICAgIH07XG5cbmNvbnN0IGNyZWF0ZUJpbmFyeVByb2dyYW1JbmZvID1cbiAgICAoaGFuZGxlcjogV2ViR0xJbmZlcmVuY2VIYW5kbGVyLCBpbnB1dHM6IFRlbnNvcltdLCBnbHNsRnVuYzogR2xzbFZhbHVlRnVuY3Rpb24sXG4gICAgIG91dHB1dFRlbnNvclR5cGU6IFRlbnNvci5EYXRhVHlwZSA9IGlucHV0c1swXS50eXBlKTogUHJvZ3JhbUluZm8gPT4ge1xuICAgICAgY29uc3QgdGV4dHVyZVR5cGUgPSBoYW5kbGVyLnNlc3Npb24ucGFjayA/IFRleHR1cmVUeXBlLnBhY2tlZCA6IFRleHR1cmVUeXBlLnVucGFja2VkO1xuICAgICAgY29uc3QgaXNCcm9hZGNhc3QgPSAhU2hhcGVVdGlsLmFyZUVxdWFsKGlucHV0c1swXS5kaW1zLCBpbnB1dHNbMV0uZGltcyk7XG4gICAgICBsZXQgb3V0cHV0U2hhcGUgPSBpbnB1dHNbMF0uZGltcztcblxuICAgICAgY29uc3QgdXNlUGFja2VkVGV4dHVyZSA9IGhhbmRsZXIuc2Vzc2lvbi5wYWNrO1xuXG4gICAgICBpZiAoaXNCcm9hZGNhc3QpIHtcbiAgICAgICAgY29uc3QgY2FsY3VsYXRlZFNoYXBlID0gQnJvYWRjYXN0VXRpbC5jYWxjU2hhcGUoaW5wdXRzWzBdLmRpbXMsIGlucHV0c1sxXS5kaW1zLCBmYWxzZSk7XG4gICAgICAgIGlmICghY2FsY3VsYXRlZFNoYXBlKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdDYW5cXCd0IHBlcmZvcm0gYmluYXJ5IG9wIG9uIHRoZSBnaXZlbiB0ZW5zb3JzJyk7XG4gICAgICAgIH1cbiAgICAgICAgb3V0cHV0U2hhcGUgPSBjYWxjdWxhdGVkU2hhcGU7XG4gICAgICAgIGNvbnN0IG91dHB1dFJhbmsgPSBvdXRwdXRTaGFwZS5sZW5ndGg7XG4gICAgICAgIGNvbnN0IGFSYW5rID0gaW5wdXRzWzBdLmRpbXMubGVuZ3RoICE9PSAwID8gaW5wdXRzWzBdLmRpbXMubGVuZ3RoIDogMTtcbiAgICAgICAgY29uc3QgYlJhbmsgPSBpbnB1dHNbMV0uZGltcy5sZW5ndGggIT09IDAgPyBpbnB1dHNbMV0uZGltcy5sZW5ndGggOiAxO1xuICAgICAgICBjb25zdCBhQmNhc3QgPSBpbnB1dHNbMF0uZGltcy5sZW5ndGggIT09IDAgPyAnYmNhc3RJbmRpY2VzX0EoaW5kaWNlcywgYWluZGljZXMpOycgOiAnYWluZGljZXNbMF0gPSAwOyc7XG4gICAgICAgIGNvbnN0IGJCY2FzdCA9IGlucHV0c1sxXS5kaW1zLmxlbmd0aCAhPT0gMCA/ICdiY2FzdEluZGljZXNfQihpbmRpY2VzLCBiaW5kaWNlcyk7JyA6ICdiaW5kaWNlc1swXSA9IDA7JztcblxuICAgICAgICBjb25zdCBnbHNsID0gZ2V0R2xzbChoYW5kbGVyLnNlc3Npb24uYmFja2VuZC5nbENvbnRleHQudmVyc2lvbik7XG4gICAgICAgIGNvbnN0IHNoYWRlclNvdXJjZSA9IHVzZVBhY2tlZFRleHR1cmUgPyBgXG4gICAgICAke2dsc2xGdW5jLmJvZHl9XG4gICAgICB2b2lkIG1haW4oKSB7XG4gICAgICAgIHZlYzQgYSA9IGdldEFBdE91dENvb3JkcygpO1xuICAgICAgICB2ZWM0IGIgPSBnZXRCQXRPdXRDb29yZHMoKTtcbiAgICAgICAgdmVjNCByZXN1bHQgPSAke2dsc2xGdW5jLm5hbWV9KGEsIGIpO1xuICAgICAgICAke2dsc2wub3V0cHV0fSA9IHJlc3VsdDtcbiAgICAgIH1gIDpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGBcbiAgICAgICR7Z2xzbEZ1bmMuYm9keX1cbiAgICAgIGZsb2F0IHByb2Nlc3MoaW50IGluZGljZXNbJHtvdXRwdXRSYW5rfV0pIHtcbiAgICAgICAgaW50IGFpbmRpY2VzWyR7YVJhbmt9XTtcbiAgICAgICAgaW50IGJpbmRpY2VzWyR7YlJhbmt9XTtcbiAgICAgICAgJHthQmNhc3R9XG4gICAgICAgICR7YkJjYXN0fVxuICAgICAgICByZXR1cm4gJHtnbHNsRnVuYy5uYW1lfShfQShhaW5kaWNlcyksIF9CKGJpbmRpY2VzKSk7XG4gICAgICB9YDtcblxuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgIG5hbWU6IGdsc2xGdW5jLm5hbWUsXG4gICAgICAgICAgaW5wdXROYW1lczogWydBJywgJ0InXSxcbiAgICAgICAgICBpbnB1dFR5cGVzOiBbdGV4dHVyZVR5cGUsIHRleHR1cmVUeXBlXSxcbiAgICAgICAgICBvdXRwdXQ6IHtkaW1zOiBvdXRwdXRTaGFwZSwgdHlwZTogb3V0cHV0VGVuc29yVHlwZSwgdGV4dHVyZVR5cGV9LFxuICAgICAgICAgIHNoYWRlclNvdXJjZSxcbiAgICAgICAgICBoYXNNYWluOiB1c2VQYWNrZWRUZXh0dXJlXG4gICAgICAgIH07XG4gICAgICB9XG4gICAgICBjb25zdCBnbHNsID0gZ2V0R2xzbChoYW5kbGVyLnNlc3Npb24uYmFja2VuZC5nbENvbnRleHQudmVyc2lvbik7XG4gICAgICBjb25zdCBzaGFkZXJTb3VyY2UgPSBgXG4gICAgJHtnbHNsRnVuYy5ib2R5fVxuICAgIHZvaWQgbWFpbigpIHtcbiAgICAgIHZlYzQgdjEgPSAke2dsc2wudGV4dHVyZTJEfShBLCBUZXhDb29yZHMpO1xuICAgICAgdmVjNCB2MiA9ICR7Z2xzbC50ZXh0dXJlMkR9KEIsIFRleENvb3Jkcyk7XG4gICAgICB2ZWM0IHJlc3VsdCA9ICR7Z2xzbEZ1bmMubmFtZX0odjEsIHYyKTtcbiAgICAgICR7Z2xzbC5vdXRwdXR9ID0gcmVzdWx0O1xuICAgIH1cbiAgICBgO1xuXG4gICAgICByZXR1cm4ge1xuICAgICAgICBuYW1lOiBnbHNsRnVuYy5uYW1lLFxuICAgICAgICBpbnB1dE5hbWVzOiBbJ0EnLCAnQiddLFxuICAgICAgICBpbnB1dFR5cGVzOiBbdGV4dHVyZVR5cGUsIHRleHR1cmVUeXBlXSxcbiAgICAgICAgb3V0cHV0OiB7ZGltczogaW5wdXRzWzBdLmRpbXMsIHR5cGU6IG91dHB1dFRlbnNvclR5cGUsIHRleHR1cmVUeXBlfSxcbiAgICAgICAgc2hhZGVyU291cmNlLFxuICAgICAgICBoYXNNYWluOiB0cnVlXG4gICAgICB9O1xuICAgIH07XG5cbmV4cG9ydCBjb25zdCBhZGQgPSAoaGFuZGxlcjogV2ViR0xJbmZlcmVuY2VIYW5kbGVyLCBpbnB1dHM6IFRlbnNvcltdKTpcbiAgICBUZW5zb3JbXSA9PiBbaGFuZGxlci5ydW4oY3JlYXRlQmluYXJ5UHJvZ3JhbUluZm9Mb2FkZXIoaGFuZGxlciwgaW5wdXRzLCBnbHNsQWRkKCkpLCBpbnB1dHMpXTtcblxuZXhwb3J0IGNvbnN0IGFuZCA9IChoYW5kbGVyOiBXZWJHTEluZmVyZW5jZUhhbmRsZXIsIGlucHV0czogVGVuc29yW10pOlxuICAgIFRlbnNvcltdID0+IFtoYW5kbGVyLnJ1bihjcmVhdGVCaW5hcnlQcm9ncmFtSW5mb0xvYWRlcihoYW5kbGVyLCBpbnB1dHMsIGdsc2xBbmQoKSwgJ2Jvb2wnKSwgaW5wdXRzKV07XG5cbmV4cG9ydCBjb25zdCBkaXYgPSAoaGFuZGxlcjogV2ViR0xJbmZlcmVuY2VIYW5kbGVyLCBpbnB1dHM6IFRlbnNvcltdKTpcbiAgICBUZW5zb3JbXSA9PiBbaGFuZGxlci5ydW4oY3JlYXRlQmluYXJ5UHJvZ3JhbUluZm9Mb2FkZXIoaGFuZGxlciwgaW5wdXRzLCBnbHNsRGl2KCkpLCBpbnB1dHMpXTtcblxuZXhwb3J0IGNvbnN0IGVxdWFsID0gKGhhbmRsZXI6IFdlYkdMSW5mZXJlbmNlSGFuZGxlciwgaW5wdXRzOiBUZW5zb3JbXSk6XG4gICAgVGVuc29yW10gPT4gW2hhbmRsZXIucnVuKGNyZWF0ZUJpbmFyeVByb2dyYW1JbmZvTG9hZGVyKGhhbmRsZXIsIGlucHV0cywgZ2xzbEVxdWFsKCksICdib29sJyksIGlucHV0cyldO1xuXG5leHBvcnQgY29uc3QgZ3JlYXRlciA9IChoYW5kbGVyOiBXZWJHTEluZmVyZW5jZUhhbmRsZXIsIGlucHV0czogVGVuc29yW10pOlxuICAgIFRlbnNvcltdID0+IFtoYW5kbGVyLnJ1bihjcmVhdGVCaW5hcnlQcm9ncmFtSW5mb0xvYWRlcihoYW5kbGVyLCBpbnB1dHMsIGdsc2xHcmVhdGVyKCksICdib29sJyksIGlucHV0cyldO1xuXG5leHBvcnQgY29uc3QgbGVzcyA9IChoYW5kbGVyOiBXZWJHTEluZmVyZW5jZUhhbmRsZXIsIGlucHV0czogVGVuc29yW10pOlxuICAgIFRlbnNvcltdID0+IFtoYW5kbGVyLnJ1bihjcmVhdGVCaW5hcnlQcm9ncmFtSW5mb0xvYWRlcihoYW5kbGVyLCBpbnB1dHMsIGdsc2xMZXNzKCksICdib29sJyksIGlucHV0cyldO1xuXG5leHBvcnQgY29uc3QgbXVsID0gKGhhbmRsZXI6IFdlYkdMSW5mZXJlbmNlSGFuZGxlciwgaW5wdXRzOiBUZW5zb3JbXSk6XG4gICAgVGVuc29yW10gPT4gW2hhbmRsZXIucnVuKGNyZWF0ZUJpbmFyeVByb2dyYW1JbmZvTG9hZGVyKGhhbmRsZXIsIGlucHV0cywgZ2xzbE11bCgpKSwgaW5wdXRzKV07XG5cbmV4cG9ydCBjb25zdCBvciA9IChoYW5kbGVyOiBXZWJHTEluZmVyZW5jZUhhbmRsZXIsIGlucHV0czogVGVuc29yW10pOlxuICAgIFRlbnNvcltdID0+IFtoYW5kbGVyLnJ1bihjcmVhdGVCaW5hcnlQcm9ncmFtSW5mb0xvYWRlcihoYW5kbGVyLCBpbnB1dHMsIGdsc2xPcigpLCAnYm9vbCcpLCBpbnB1dHMpXTtcblxuZXhwb3J0IGNvbnN0IHBvdyA9IChoYW5kbGVyOiBXZWJHTEluZmVyZW5jZUhhbmRsZXIsIGlucHV0czogVGVuc29yW10pOlxuICAgIFRlbnNvcltdID0+IFtoYW5kbGVyLnJ1bihjcmVhdGVCaW5hcnlQcm9ncmFtSW5mb0xvYWRlcihoYW5kbGVyLCBpbnB1dHMsIGdsc2xQb3coKSksIGlucHV0cyldO1xuXG5leHBvcnQgY29uc3QgcFJlbHUgPSAoaGFuZGxlcjogV2ViR0xJbmZlcmVuY2VIYW5kbGVyLCBpbnB1dHM6IFRlbnNvcltdKTpcbiAgICBUZW5zb3JbXSA9PiBbaGFuZGxlci5ydW4oY3JlYXRlQmluYXJ5UHJvZ3JhbUluZm9Mb2FkZXIoaGFuZGxlciwgaW5wdXRzLCBnbHNsUFJlbHUoKSksIGlucHV0cyldO1xuXG5leHBvcnQgY29uc3Qgc3ViID0gKGhhbmRsZXI6IFdlYkdMSW5mZXJlbmNlSGFuZGxlciwgaW5wdXRzOiBUZW5zb3JbXSk6XG4gICAgVGVuc29yW10gPT4gW2hhbmRsZXIucnVuKGNyZWF0ZUJpbmFyeVByb2dyYW1JbmZvTG9hZGVyKGhhbmRsZXIsIGlucHV0cywgZ2xzbFN1YigpKSwgaW5wdXRzKV07XG5cbmV4cG9ydCBjb25zdCB4b3IgPSAoaGFuZGxlcjogV2ViR0xJbmZlcmVuY2VIYW5kbGVyLCBpbnB1dHM6IFRlbnNvcltdKTpcbiAgICBUZW5zb3JbXSA9PiBbaGFuZGxlci5ydW4oY3JlYXRlQmluYXJ5UHJvZ3JhbUluZm9Mb2FkZXIoaGFuZGxlciwgaW5wdXRzLCBnbHNsWG9yKCksICdib29sJyksIGlucHV0cyldO1xuIiwiLy8gQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXG5cbmltcG9ydCB7R3JhcGh9IGZyb20gJy4uLy4uLy4uL2dyYXBoJztcbmltcG9ydCB7T3BlcmF0b3JJbXBsZW1lbnRhdGlvbiwgT3BlcmF0b3JJbml0aWFsaXphdGlvbn0gZnJvbSAnLi4vLi4vLi4vb3BlcmF0b3JzJztcbmltcG9ydCB7VGVuc29yfSBmcm9tICcuLi8uLi8uLi90ZW5zb3InO1xuaW1wb3J0IHtQcm90b1V0aWx9IGZyb20gJy4uLy4uLy4uL3V0aWwnO1xuaW1wb3J0IHtXZWJHTEluZmVyZW5jZUhhbmRsZXJ9IGZyb20gJy4uL2luZmVyZW5jZS1oYW5kbGVyJztcblxuZXhwb3J0IGNvbnN0IGNhc3Q6IE9wZXJhdG9ySW1wbGVtZW50YXRpb248VGVuc29yLkRhdGFUeXBlPiA9XG4gICAgKGhhbmRsZXI6IFdlYkdMSW5mZXJlbmNlSGFuZGxlciwgaW5wdXRzOiBUZW5zb3JbXSwgdG86IFRlbnNvci5EYXRhVHlwZSk6IFRlbnNvcltdID0+IHtcbiAgICAgIHZhbGlkYXRlSW5wdXRzKGlucHV0cyk7XG4gICAgICByZXR1cm4gW2hhbmRsZXIuY2FzdChpbnB1dHNbMF0sIHRvKV07XG4gICAgfTtcblxuZXhwb3J0IGNvbnN0IHBhcnNlQ2FzdEF0dHJpYnV0ZXM6IE9wZXJhdG9ySW5pdGlhbGl6YXRpb248VGVuc29yLkRhdGFUeXBlPiA9IChub2RlOiBHcmFwaC5Ob2RlKTogVGVuc29yLkRhdGFUeXBlID0+XG4gICAgUHJvdG9VdGlsLnRlbnNvckRhdGFUeXBlRnJvbVByb3RvKG5vZGUuYXR0cmlidXRlcy5nZXRJbnQoJ3RvJykpO1xuXG5jb25zdCB2YWxpZGF0ZUlucHV0cyA9IChpbnB1dHM6IFRlbnNvcltdKTogdm9pZCA9PiB7XG4gIGlmICghaW5wdXRzIHx8IGlucHV0cy5sZW5ndGggIT09IDEpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ0Nhc3QgcmVxdWlyZXMgMSBpbnB1dC4nKTtcbiAgfVxuXG4gIGlmIChpbnB1dHNbMF0udHlwZSA9PT0gJ3N0cmluZycpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ0ludmFsaWQgaW5wdXQgdHlwZS4nKTtcbiAgfVxufTsiLCIvLyBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cblxuaW1wb3J0IHtUZW5zb3J9IGZyb20gJy4uLy4uLy4uL3RlbnNvcic7XG5pbXBvcnQge2dldEdsc2x9IGZyb20gJy4uL2dsc2wtc291cmNlJztcbmltcG9ydCB7V2ViR0xJbmZlcmVuY2VIYW5kbGVyfSBmcm9tICcuLi9pbmZlcmVuY2UtaGFuZGxlcic7XG5pbXBvcnQge1Byb2dyYW1JbmZvLCBQcm9ncmFtSW5mb0xvYWRlciwgUHJvZ3JhbU1ldGFkYXRhLCBUZXh0dXJlVHlwZX0gZnJvbSAnLi4vdHlwZXMnO1xuaW1wb3J0IHtnZXRDb29yZHNEYXRhVHlwZSwgZ2V0R2xDaGFubmVsc30gZnJvbSAnLi4vdXRpbHMnO1xuXG5pbXBvcnQge0NvbmNhdEF0dHJpYnV0ZXN9IGZyb20gJy4vY29uY2F0JztcbmltcG9ydCB7Z2V0Q2hhbm5lbHMsIHVucGFja0Zyb21DaGFubmVsfSBmcm9tICcuL3BhY2tpbmctdXRpbHMnO1xuXG5jb25zdCBjcmVhdGVQYWNrZWRDb25jYXRQcm9ncmFtTWV0YWRhdGEgPSAoaW5wdXRDb3VudDogbnVtYmVyLCBjYWNoZUhpbnQ6IHN0cmluZykgPT4gKHtcbiAgbmFtZTogJ0NvbmNhdCAocGFja2VkKScsXG4gIGlucHV0TmFtZXM6IEFycmF5LmZyb20oe2xlbmd0aDogaW5wdXRDb3VudH0sICh2LCBpKSA9PiBgWCR7aX1gKSxcbiAgaW5wdXRUeXBlczogQXJyYXkoaW5wdXRDb3VudCkuZmlsbChUZXh0dXJlVHlwZS5wYWNrZWQpLFxuICBjYWNoZUhpbnRcbn0pO1xuXG5jb25zdCBjcmVhdGVQYWNrZWRDb25jYXRQcm9ncmFtSW5mbyA9XG4gICAgKGhhbmRsZXI6IFdlYkdMSW5mZXJlbmNlSGFuZGxlciwgbWV0YWRhdGE6IFByb2dyYW1NZXRhZGF0YSwgaW5wdXRzOiBUZW5zb3JbXSwgYXhpczogbnVtYmVyKTogUHJvZ3JhbUluZm8gPT4ge1xuICAgICAgY29uc3QgaW5wdXRTaGFwZSA9IGlucHV0c1swXS5kaW1zLnNsaWNlKCk7XG4gICAgICBpZiAoYXhpcyA+PSBpbnB1dFNoYXBlLmxlbmd0aCB8fCBheGlzIDwgKC0xICogaW5wdXRTaGFwZS5sZW5ndGgpKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignYXhpcyBzcGVjaWZpZWQgZm9yIGNvbmNhdCBkb2VzblxcJ3QgbWF0Y2ggaW5wdXQgZGltZW5zaW9uYWxpdHknKTtcbiAgICAgIH1cbiAgICAgIGlmIChheGlzIDwgMCkge1xuICAgICAgICBheGlzID0gaW5wdXRTaGFwZS5sZW5ndGggKyBheGlzO1xuICAgICAgfVxuICAgICAgLy8gZW5zdXJlIGFsbCBvZiB0aGUgbm9uLWNvbmNhdGVuYXRlZCBheGVzIG1hdGNoIGVhY2ggb3RoZXJcbiAgICAgIC8vIGNhbGN1bGF0ZSB0aGUgc2hhcGUgb2YgdGhlIG91dHB1dCB0ZW5zb3Igd2hpbGUgd2UgZG8gdGhhdFxuICAgICAgY29uc3Qgb3V0cHV0U2hhcGUgPSBpbnB1dFNoYXBlLnNsaWNlKDApO1xuICAgICAgZm9yIChsZXQgaSA9IDE7IGkgPCBpbnB1dHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgY29uc3QgZGF0YU5TaGFwZSA9IGlucHV0c1tpXS5kaW1zLnNsaWNlKCk7XG4gICAgICAgIGZvciAobGV0IGF4aXNJbmRleCA9IDA7IGF4aXNJbmRleCA8IGlucHV0U2hhcGUubGVuZ3RoOyBheGlzSW5kZXgrKykge1xuICAgICAgICAgIC8vIGFkZCB0byB0aGUgcGxhY2Vob2xkZXIgZm9yIGNvbXB1dGluZyBvdXRwdXQgc2hhcGVcbiAgICAgICAgICBpZiAoYXhpc0luZGV4ID09PSBheGlzKSB7XG4gICAgICAgICAgICBvdXRwdXRTaGFwZVtheGlzXSArPSBkYXRhTlNoYXBlW2F4aXNJbmRleF07XG4gICAgICAgICAgfVxuICAgICAgICAgIC8vIGVuc3VyZSBhbGwgbm9uLWNhbmNhdGVuYXRlZCBheGVzIG1hdGNoIGVhY2ggb3RoZXJcbiAgICAgICAgICBlbHNlIGlmIChpbnB1dFNoYXBlW2F4aXNJbmRleF0gIT09IGRhdGFOU2hhcGVbYXhpc0luZGV4XSkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdub24gY29uY2F0IGRpbWVuc2lvbnMgbXVzdCBtYXRjaCcpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBjb25zdCByYW5rID0gb3V0cHV0U2hhcGUubGVuZ3RoO1xuICAgICAgY29uc3QgY29vcmRzID0gZ2V0Q2hhbm5lbHMoJ2Nvb3JkcycsIHJhbmspO1xuICAgICAgY29uc3QgZHR5cGUgPSBnZXRDb29yZHNEYXRhVHlwZShyYW5rKTtcbiAgICAgIGNvbnN0IHVucGFja0NoYW5uZWwgPSB1bnBhY2tGcm9tQ2hhbm5lbCgpO1xuXG4gICAgICBjb25zdCBzaGFwZXMgPSBpbnB1dHMubWFwKGkgPT4gaS5kaW1zKTtcbiAgICAgIGNvbnN0IGNoYW5uZWxzID0gZ2V0R2xDaGFubmVscyhyYW5rKTtcbiAgICAgIGNvbnN0IG9mZnNldHM6IG51bWJlcltdID0gbmV3IEFycmF5KHNoYXBlcy5sZW5ndGggLSAxKTtcblxuICAgICAgb2Zmc2V0c1swXSA9IHNoYXBlc1swXVtheGlzXTtcbiAgICAgIGZvciAobGV0IGkgPSAxOyBpIDwgb2Zmc2V0cy5sZW5ndGg7IGkrKykge1xuICAgICAgICBvZmZzZXRzW2ldID0gb2Zmc2V0c1tpIC0gMV0gKyBzaGFwZXNbaV1bYXhpc107XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IGNoYW5uZWwgPSBjaGFubmVsc1theGlzXTtcbiAgICAgIGNvbnN0IGxhc3RDaGFubmVscyA9IGNoYW5uZWxzLnNsaWNlKC0yKTtcbiAgICAgIGNvbnN0IGFsbENoYW5uZWxzID0gY2hhbm5lbHMuam9pbigpO1xuXG4gICAgICBsZXQgZ2V0VmFsdWVTbmlwcGV0ID0gYGlmICgke2NoYW5uZWx9IDwgJHtvZmZzZXRzWzBdfSkge1xuICAgICAgICByZXR1cm4gZ2V0Q2hhbm5lbChcbiAgICAgICAgICAgIGdldFgwKCR7YWxsQ2hhbm5lbHN9KSwgdmVjMigke2xhc3RDaGFubmVscy5qb2luKCl9KSk7XG4gICAgICAgIH1gO1xuICAgICAgZm9yIChsZXQgaSA9IDE7IGkgPCBvZmZzZXRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGNvbnN0IHNoaWZ0ID0gb2Zmc2V0c1tpIC0gMV07XG4gICAgICAgIGdldFZhbHVlU25pcHBldCArPSBgXG4gICAgICAgICAgICBpZiAoJHtjaGFubmVsfSA8ICR7b2Zmc2V0c1tpXX0gICYmICR7Y2hhbm5lbH0gPj0gJHtvZmZzZXRzW2kgLSAxXX0pIHtcbiAgICAgICAgICAgICAgcmV0dXJuIGdldENoYW5uZWwoXG4gICAgICAgICAgICAgICAgZ2V0WCR7aX0oJHtnZXRTaGlmdGVkQ2hhbm5lbHNTbmlwcGV0KGNoYW5uZWxzLCBjaGFubmVsLCBzaGlmdCl9KSxcbiAgICAgICAgICAgICAgICB2ZWMyKCR7Z2V0U2hpZnRlZENoYW5uZWxzU25pcHBldChsYXN0Q2hhbm5lbHMsIGNoYW5uZWwsIHNoaWZ0KX0pKTtcbiAgICAgICAgICAgIH1gO1xuICAgICAgfVxuICAgICAgY29uc3QgbGFzdEluZGV4ID0gb2Zmc2V0cy5sZW5ndGg7XG4gICAgICBjb25zdCBzaGlmdCA9IG9mZnNldHNbb2Zmc2V0cy5sZW5ndGggLSAxXTtcbiAgICAgIGdldFZhbHVlU25pcHBldCArPSBgXG4gICAgICAgICAgICByZXR1cm4gZ2V0Q2hhbm5lbChcbiAgICAgICAgICAgICAgZ2V0WCR7bGFzdEluZGV4fSgke2dldFNoaWZ0ZWRDaGFubmVsc1NuaXBwZXQoY2hhbm5lbHMsIGNoYW5uZWwsIHNoaWZ0KX0pLFxuICAgICAgICAgICAgICB2ZWMyKCR7Z2V0U2hpZnRlZENoYW5uZWxzU25pcHBldChsYXN0Q2hhbm5lbHMsIGNoYW5uZWwsIHNoaWZ0KX0pKTtgO1xuXG4gICAgICBjb25zdCBnbHNsID0gZ2V0R2xzbChoYW5kbGVyLnNlc3Npb24uYmFja2VuZC5nbENvbnRleHQudmVyc2lvbik7XG5cbiAgICAgIGNvbnN0IHNoYWRlclNvdXJjZSA9IGBcbiAgICAgICAgICAke3VucGFja0NoYW5uZWx9XG4gICAgICAgICAgZmxvYXQgZ2V0VmFsdWUoJHtjaGFubmVscy5tYXAoeCA9PiAnaW50ICcgKyB4KX0pIHtcbiAgICAgICAgICAgICR7Z2V0VmFsdWVTbmlwcGV0fVxuICAgICAgICAgIH1cblxuICAgICAgICAgIHZvaWQgbWFpbigpIHtcbiAgICAgICAgICAgICR7ZHR5cGV9IGNvb3JkcyA9IGdldE91dHB1dENvb3JkcygpO1xuICAgICAgICAgICAgaW50IGxhc3REaW0gPSBjb29yZHMuJHtjaGFubmVsc1tyYW5rIC0gMV19O1xuICAgICAgICAgICAgY29vcmRzLiR7Y2hhbm5lbHNbcmFuayAtIDFdfSA9IGNvb3Jkcy4ke2NoYW5uZWxzW3JhbmsgLSAyXX07XG4gICAgICAgICAgICBjb29yZHMuJHtjaGFubmVsc1tyYW5rIC0gMl19ID0gbGFzdERpbTtcblxuICAgICAgICAgICAgdmVjNCByZXN1bHQgPSB2ZWM0KGdldFZhbHVlKCR7Y29vcmRzfSksIDAuLCAwLiwgMC4pO1xuXG4gICAgICAgICAgICAke2Nvb3Jkc1tyYW5rIC0gMV19ID0gJHtjb29yZHNbcmFuayAtIDFdfSArIDE7XG4gICAgICAgICAgICBpZiAoJHtjb29yZHNbcmFuayAtIDFdfSA8ICR7b3V0cHV0U2hhcGVbcmFuayAtIDFdfSkge1xuICAgICAgICAgICAgICByZXN1bHQuZyA9IGdldFZhbHVlKCR7Y29vcmRzfSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICR7Y29vcmRzW3JhbmsgLSAyXX0gPSAke2Nvb3Jkc1tyYW5rIC0gMl19ICsgMTtcbiAgICAgICAgICAgIGlmICgke2Nvb3Jkc1tyYW5rIC0gMl19IDwgJHtvdXRwdXRTaGFwZVtyYW5rIC0gMl19KSB7XG4gICAgICAgICAgICAgIHJlc3VsdC5hID0gZ2V0VmFsdWUoJHtjb29yZHN9KTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgJHtjb29yZHNbcmFuayAtIDFdfSA9ICR7Y29vcmRzW3JhbmsgLSAxXX0gLSAxO1xuICAgICAgICAgICAgaWYgKCR7Y29vcmRzW3JhbmsgLSAyXX0gPCAke291dHB1dFNoYXBlW3JhbmsgLSAyXX0gJiZcbiAgICAgICAgICAgICAgICAke2Nvb3Jkc1tyYW5rIC0gMV19IDwgJHtvdXRwdXRTaGFwZVtyYW5rIC0gMV19KSB7XG4gICAgICAgICAgICAgIHJlc3VsdC5iID0gZ2V0VmFsdWUoJHtjb29yZHN9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgICR7Z2xzbC5vdXRwdXR9ID0gcmVzdWx0O1xuICAgICAgICAgIH1cbiAgICAgICAgYDtcblxuICAgICAgcmV0dXJuIHtcbiAgICAgICAgLi4ubWV0YWRhdGEsXG4gICAgICAgIG91dHB1dDoge2RpbXM6IG91dHB1dFNoYXBlLCB0eXBlOiBpbnB1dHNbMF0udHlwZSwgdGV4dHVyZVR5cGU6IFRleHR1cmVUeXBlLnBhY2tlZH0sXG4gICAgICAgIHNoYWRlclNvdXJjZSxcbiAgICAgICAgaGFzTWFpbjogdHJ1ZSxcbiAgICAgIH07XG4gICAgfTtcblxuZXhwb3J0IGNvbnN0IGNyZWF0ZVBhY2tlZENvbmNhdFByb2dyYW1JbmZvTG9hZGVyID1cbiAgICAoaGFuZGxlcjogV2ViR0xJbmZlcmVuY2VIYW5kbGVyLCBpbnB1dHM6IFRlbnNvcltdLCBhdHRyaWJ1dGVzOiBDb25jYXRBdHRyaWJ1dGVzKTogUHJvZ3JhbUluZm9Mb2FkZXIgPT4ge1xuICAgICAgY29uc3QgbWV0YWRhdGEgPSBjcmVhdGVQYWNrZWRDb25jYXRQcm9ncmFtTWV0YWRhdGEoaW5wdXRzLmxlbmd0aCwgYXR0cmlidXRlcy5jYWNoZUtleSk7XG4gICAgICByZXR1cm4gey4uLm1ldGFkYXRhLCBnZXQ6ICgpID0+IGNyZWF0ZVBhY2tlZENvbmNhdFByb2dyYW1JbmZvKGhhbmRsZXIsIG1ldGFkYXRhLCBpbnB1dHMsIGF0dHJpYnV0ZXMuYXhpcyl9O1xuICAgIH07XG5cbmNvbnN0IGdldFNoaWZ0ZWRDaGFubmVsc1NuaXBwZXQgPSAoY2hhbm5lbHM6IHN0cmluZ1tdLCBjaGFubmVsOiBzdHJpbmcsIHNoaWZ0OiBudW1iZXIpOiBzdHJpbmcgPT4ge1xuICBjb25zdCBjaGFubmVsSWR4ID0gY2hhbm5lbHMuaW5kZXhPZihjaGFubmVsKTtcbiAgY29uc3QgcmVzID0gY2hhbm5lbHMubWFwKChjLCBpZHgpID0+IHtcbiAgICBpZiAoaWR4ID09PSBjaGFubmVsSWR4KSB7XG4gICAgICByZXR1cm4gYCR7Y30gLSAke3NoaWZ0fWA7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBjO1xuICAgIH1cbiAgfSk7XG4gIHJldHVybiByZXMuam9pbigpO1xufTtcbiIsIi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxuXG5pbXBvcnQge0F0dHJpYnV0ZVdpdGhDYWNoZUtleSwgY3JlYXRlQXR0cmlidXRlV2l0aENhY2hlS2V5fSBmcm9tICcuLi8uLi8uLi9hdHRyaWJ1dGUtd2l0aC1jYWNoZS1rZXknO1xuaW1wb3J0IHtHcmFwaH0gZnJvbSAnLi4vLi4vLi4vZ3JhcGgnO1xuaW1wb3J0IHtPcGVyYXRvckltcGxlbWVudGF0aW9uLCBPcGVyYXRvckluaXRpYWxpemF0aW9ufSBmcm9tICcuLi8uLi8uLi9vcGVyYXRvcnMnO1xuaW1wb3J0IHtUZW5zb3J9IGZyb20gJy4uLy4uLy4uL3RlbnNvcic7XG5pbXBvcnQge1dlYkdMSW5mZXJlbmNlSGFuZGxlcn0gZnJvbSAnLi4vaW5mZXJlbmNlLWhhbmRsZXInO1xuaW1wb3J0IHtQcm9ncmFtSW5mbywgUHJvZ3JhbUluZm9Mb2FkZXIsIFByb2dyYW1NZXRhZGF0YSwgVGV4dHVyZVR5cGV9IGZyb20gJy4uL3R5cGVzJztcblxuaW1wb3J0IHtjcmVhdGVQYWNrZWRDb25jYXRQcm9ncmFtSW5mb0xvYWRlcn0gZnJvbSAnLi9jb25jYXQtcGFja2VkJztcblxuZXhwb3J0IGludGVyZmFjZSBDb25jYXRBdHRyaWJ1dGVzIGV4dGVuZHMgQXR0cmlidXRlV2l0aENhY2hlS2V5IHtcbiAgcmVhZG9ubHkgYXhpczogbnVtYmVyO1xufVxuXG5leHBvcnQgY29uc3QgY29uY2F0OiBPcGVyYXRvckltcGxlbWVudGF0aW9uPENvbmNhdEF0dHJpYnV0ZXM+ID1cbiAgICAoaW5mZXJlbmNlSGFuZGxlcjogV2ViR0xJbmZlcmVuY2VIYW5kbGVyLCBpbnB1dHM6IFRlbnNvcltdLCBhdHRyaWJ1dGVzOiBDb25jYXRBdHRyaWJ1dGVzKTogVGVuc29yW10gPT4ge1xuICAgICAgdmFsaWRhdGVJbnB1dHMoaW5wdXRzKTtcbiAgICAgIGlmIChpbmZlcmVuY2VIYW5kbGVyLnNlc3Npb24ucGFjayAmJiBpbnB1dHNbMF0uZGltcy5sZW5ndGggPiAxKSB7XG4gICAgICAgIGNvbnN0IG91dHB1dCA9XG4gICAgICAgICAgICBpbmZlcmVuY2VIYW5kbGVyLnJ1bihjcmVhdGVQYWNrZWRDb25jYXRQcm9ncmFtSW5mb0xvYWRlcihpbmZlcmVuY2VIYW5kbGVyLCBpbnB1dHMsIGF0dHJpYnV0ZXMpLCBpbnB1dHMpO1xuICAgICAgICByZXR1cm4gW291dHB1dF07XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBjb25zdCBvdXRwdXQgPVxuICAgICAgICAgICAgaW5mZXJlbmNlSGFuZGxlci5ydW4oY3JlYXRlVW5wYWNrZWRDb25jYXRQcm9ncmFtSW5mb0xvYWRlcihpbmZlcmVuY2VIYW5kbGVyLCBpbnB1dHMsIGF0dHJpYnV0ZXMpLCBpbnB1dHMpO1xuICAgICAgICByZXR1cm4gW291dHB1dF07XG4gICAgICB9XG4gICAgfTtcblxuY29uc3QgY3JlYXRlVW5wYWNrZWRDb25jYXRQcm9ncmFtTWV0YWRhdGEgPSAoaW5wdXRDb3VudDogbnVtYmVyLCBjYWNoZUhpbnQ6IHN0cmluZykgPT4gKHtcbiAgbmFtZTogJ0NvbmNhdCcsXG4gIGlucHV0TmFtZXM6IEFycmF5LmZyb20oe2xlbmd0aDogaW5wdXRDb3VudH0sICh2LCBpKSA9PiBgWCR7aX1gKSxcbiAgaW5wdXRUeXBlczogQXJyYXkoaW5wdXRDb3VudCkuZmlsbChUZXh0dXJlVHlwZS51bnBhY2tlZCksXG4gIGNhY2hlSGludFxufSk7XG5cbmNvbnN0IGNyZWF0ZVVucGFja2VkQ29uY2F0UHJvZ3JhbUluZm8gPVxuICAgIChoYW5kbGVyOiBXZWJHTEluZmVyZW5jZUhhbmRsZXIsIG1ldGFkYXRhOiBQcm9ncmFtTWV0YWRhdGEsIGlucHV0czogVGVuc29yW10sIGF4aXM6IG51bWJlcik6IFByb2dyYW1JbmZvID0+IHtcbiAgICAgIGNvbnN0IGlucHV0U2hhcGUgPSBpbnB1dHNbMF0uZGltcy5zbGljZSgpO1xuICAgICAgaWYgKGF4aXMgPj0gaW5wdXRTaGFwZS5sZW5ndGggfHwgYXhpcyA8ICgtMSAqIGlucHV0U2hhcGUubGVuZ3RoKSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ2F4aXMgc3BlY2lmaWVkIGZvciBjb25jYXQgZG9lc25cXCd0IG1hdGNoIGlucHV0IGRpbWVuc2lvbmFsaXR5Jyk7XG4gICAgICB9XG4gICAgICBpZiAoYXhpcyA8IDApIHtcbiAgICAgICAgYXhpcyA9IGlucHV0U2hhcGUubGVuZ3RoICsgYXhpcztcbiAgICAgIH1cbiAgICAgIC8vIGVuc3VyZSBhbGwgb2YgdGhlIG5vbi1jb25jYXRlbmF0ZWQgYXhlcyBtYXRjaCBlYWNoIG90aGVyXG4gICAgICAvLyBjYWxjdWxhdGUgdGhlIHNoYXBlIG9mIHRoZSBvdXRwdXQgdGVuc29yIHdoaWxlIHdlIGRvIHRoYXRcbiAgICAgIGNvbnN0IG91dHB1dFNoYXBlID0gaW5wdXRTaGFwZS5zbGljZSgwKTtcbiAgICAgIGZvciAobGV0IGkgPSAxOyBpIDwgaW5wdXRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGNvbnN0IGRhdGFOU2hhcGUgPSBpbnB1dHNbaV0uZGltcy5zbGljZSgpO1xuICAgICAgICBmb3IgKGxldCBheGlzSW5kZXggPSAwOyBheGlzSW5kZXggPCBpbnB1dFNoYXBlLmxlbmd0aDsgYXhpc0luZGV4KyspIHtcbiAgICAgICAgICAvLyBhZGQgdG8gdGhlIHBsYWNlaG9sZGVyIGZvciBjb21wdXRpbmcgb3V0cHV0IHNoYXBlXG4gICAgICAgICAgaWYgKGF4aXNJbmRleCA9PT0gYXhpcykge1xuICAgICAgICAgICAgb3V0cHV0U2hhcGVbYXhpc10gKz0gZGF0YU5TaGFwZVtheGlzSW5kZXhdO1xuICAgICAgICAgIH1cbiAgICAgICAgICAvLyBlbnN1cmUgYWxsIG5vbi1jYW5jYXRlbmF0ZWQgYXhlcyBtYXRjaCBlYWNoIG90aGVyXG4gICAgICAgICAgZWxzZSBpZiAoaW5wdXRTaGFwZVtheGlzSW5kZXhdICE9PSBkYXRhTlNoYXBlW2F4aXNJbmRleF0pIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignbm9uIGNvbmNhdCBkaW1lbnNpb25zIG11c3QgbWF0Y2gnKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgY29uc3QgcmFuayA9IG91dHB1dFNoYXBlLmxlbmd0aDtcblxuICAgICAgY29uc3Qgc2l6ZUluQ29uY2F0QXhpcyA9IG5ldyBBcnJheTxudW1iZXI+KGlucHV0cy5sZW5ndGgpO1xuICAgICAgbGV0IHByZXZpb3VzU3VtID0gMDtcbiAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgc2l6ZUluQ29uY2F0QXhpcy5sZW5ndGg7ICsraSkge1xuICAgICAgICBwcmV2aW91c1N1bSArPSBpbnB1dHNbaV0uZGltc1theGlzXTtcbiAgICAgICAgc2l6ZUluQ29uY2F0QXhpc1tpXSA9IHByZXZpb3VzU3VtO1xuICAgICAgfVxuXG4gICAgICBsZXQgZ2V0VGV4dHVyZUluZGV4V2hlcmVEYXRhUmVzaWRlc01ldGhvZCA9ICcnO1xuICAgICAgLy8gaW4gbW9zdCBjYXNlcyBsaW5lYXIgc2VhcmNoIGlzIHN1ZmZpY2llbnQsIGFzIGluIG1vc3Qgc2NlbmFyaW9zLCBvbmx5IDIgdGVuc29ycyBhcmUgY29uY2F0ZW5hdGVkXG4gICAgICBpZiAoaW5wdXRzLmxlbmd0aCA8IDUpIHtcbiAgICAgICAgZ2V0VGV4dHVyZUluZGV4V2hlcmVEYXRhUmVzaWRlc01ldGhvZCA9IGdldFRleHR1cmVJbmRleFdoZXJlRGF0YVJlc2lkZXNMaW5lYXJTZWFyY2goc2l6ZUluQ29uY2F0QXhpcyk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBnZXRUZXh0dXJlSW5kZXhXaGVyZURhdGFSZXNpZGVzTWV0aG9kID0gZ2V0VGV4dHVyZUluZGV4V2hlcmVEYXRhUmVzaWRlc0JpbmFyeVNlYXJjaChzaXplSW5Db25jYXRBeGlzKTtcbiAgICAgIH1cblxuICAgICAgY29uc3QgZmV0Y2hEYXRhRnJvbUNvcnJlY3RUZXh0dXJlTWV0aG9kID0gZ2V0RmV0Y2hEYXRhRnJvbUNvcnJlY3RUZXh0dXJlTWV0aG9kKGlucHV0cy5sZW5ndGgsIHJhbmspO1xuICAgICAgY29uc3QgZ2V0U2l6ZUluQ29uY2F0QXhpc1ZhbHVlRnJvbUluZGV4TWV0aG9kID0gZ2V0R2V0U2l6ZUluQ29uY2F0QXhpc1ZhbHVlRnJvbUluZGV4TWV0aG9kKHNpemVJbkNvbmNhdEF4aXMpO1xuICAgICAgY29uc3Qgc2hhZGVyU291cmNlID0gYFxuICAgICAgICAke2ZldGNoRGF0YUZyb21Db3JyZWN0VGV4dHVyZU1ldGhvZH1cbiAgICAgICAgJHtnZXRTaXplSW5Db25jYXRBeGlzVmFsdWVGcm9tSW5kZXhNZXRob2R9XG4gICAgICAgICR7Z2V0VGV4dHVyZUluZGV4V2hlcmVEYXRhUmVzaWRlc01ldGhvZH1cbiAgICAgICAgZmxvYXQgcHJvY2VzcyhpbnQgaW5kaWNlc1ske3Jhbmt9XSkge1xuICAgICAgICAgIGludCB0ZXh0dXJlSW5kZXggPSBnZXRUZXh0dXJlV2hlcmVEYXRhUmVzaWRlcyAoaW5kaWNlc1ske2F4aXN9XSk7XG5cbiAgICAgICAgICBpZih0ZXh0dXJlSW5kZXggIT0gMCkge1xuICAgICAgICAgICAgaW5kaWNlc1ske2F4aXN9XSA9IGluZGljZXNbJHtheGlzfV0gLSBpbnQoZ2V0U2l6ZUluQ29uY2F0QXhpc1ZhbHVlRnJvbUluZGV4KHRleHR1cmVJbmRleC1pbnQoMSkpKTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICByZXR1cm4gZmV0Y2hEYXRhRnJvbUNvcnJlY3RUZXh0dXJlKHRleHR1cmVJbmRleCwgaW5kaWNlcyk7XG4gICAgICAgIH1gO1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgLi4ubWV0YWRhdGEsXG4gICAgICAgIG91dHB1dDoge2RpbXM6IG91dHB1dFNoYXBlLCB0eXBlOiBpbnB1dHNbMF0udHlwZSwgdGV4dHVyZVR5cGU6IFRleHR1cmVUeXBlLnVucGFja2VkfSxcbiAgICAgICAgc2hhZGVyU291cmNlLFxuICAgICAgfTtcbiAgICB9O1xuXG5jb25zdCBjcmVhdGVVbnBhY2tlZENvbmNhdFByb2dyYW1JbmZvTG9hZGVyID1cbiAgICAoaGFuZGxlcjogV2ViR0xJbmZlcmVuY2VIYW5kbGVyLCBpbnB1dHM6IFRlbnNvcltdLCBhdHRyaWJ1dGVzOiBDb25jYXRBdHRyaWJ1dGVzKTogUHJvZ3JhbUluZm9Mb2FkZXIgPT4ge1xuICAgICAgY29uc3QgbWV0YWRhdGEgPSBjcmVhdGVVbnBhY2tlZENvbmNhdFByb2dyYW1NZXRhZGF0YShpbnB1dHMubGVuZ3RoLCBhdHRyaWJ1dGVzLmNhY2hlS2V5KTtcbiAgICAgIHJldHVybiB7Li4ubWV0YWRhdGEsIGdldDogKCkgPT4gY3JlYXRlVW5wYWNrZWRDb25jYXRQcm9ncmFtSW5mbyhoYW5kbGVyLCBtZXRhZGF0YSwgaW5wdXRzLCBhdHRyaWJ1dGVzLmF4aXMpfTtcbiAgICB9O1xuXG5jb25zdCBnZXRUZXh0dXJlSW5kZXhXaGVyZURhdGFSZXNpZGVzTGluZWFyU2VhcmNoID0gKHNpemVJbkNvbmNhdEF4aXM6IG51bWJlcltdKTogc3RyaW5nID0+IHtcbiAgY29uc3Qgc2VhcmNoQXhpcyA9IHNpemVJbkNvbmNhdEF4aXMubWFwKChzaXplLCBpKSA9PiBgaWYoaW5kZXg8JHtzaXplfSkge3JldHVybiAke2l9O31cbmApO1xuICByZXR1cm4gYGludCBnZXRUZXh0dXJlV2hlcmVEYXRhUmVzaWRlcyhpbnQgaW5kZXgpIHtcbiAgICAgICR7c2VhcmNoQXhpcy5qb2luKCcnKX1cbiAgICB9YDtcbn07XG5cbi8vIFRPRE86IEltcGxlbWVudCBCaW5hcnlTZWFyY2ggaW4gR0xTTFxuY29uc3QgZ2V0VGV4dHVyZUluZGV4V2hlcmVEYXRhUmVzaWRlc0JpbmFyeVNlYXJjaCA9IChzaXplSW5Db25jYXRBeGlzOiBudW1iZXJbXSk6IHN0cmluZyA9PlxuICAgIGdldFRleHR1cmVJbmRleFdoZXJlRGF0YVJlc2lkZXNMaW5lYXJTZWFyY2goc2l6ZUluQ29uY2F0QXhpcyk7XG5cbmNvbnN0IGdldEZldGNoRGF0YUZyb21Db3JyZWN0VGV4dHVyZU1ldGhvZCA9IChudW1iZXJPZlRlbnNvcnM6IG51bWJlciwgdGVuc29yUmFuazogbnVtYmVyKSA9PiB7XG4gIGNvbnN0IGNvZGVMaW5lczogc3RyaW5nW10gPSBbYGZsb2F0IGZldGNoRGF0YUZyb21Db3JyZWN0VGV4dHVyZShpbnQgdGV4dHVyZUluZGV4LCBpbnQgaW5kaWNlc1ske3RlbnNvclJhbmt9XSkge2BdO1xuICBmb3IgKGxldCBpID0gMDsgaSA8IG51bWJlck9mVGVuc29yczsgKytpKSB7XG4gICAgaWYgKGkgPT09IDApIHtcbiAgICAgIGNvZGVMaW5lcy5wdXNoKFxuICAgICAgICAgICdcXHQnICtcbiAgICAgICAgICBgaWYgKHRleHR1cmVJbmRleCA9PSAke2l9KSB7IHJldHVybiBfWCR7aX0oaW5kaWNlcyk7IH1gKTtcbiAgICB9IGVsc2UgaWYgKGkgPT09IG51bWJlck9mVGVuc29ycyAtIDEpIHtcbiAgICAgIGNvZGVMaW5lcy5wdXNoKFxuICAgICAgICAgICdcXHQnICtcbiAgICAgICAgICBgZWxzZSB7IHJldHVybiBfWCR7aX0oaW5kaWNlcyk7IH1gKTtcbiAgICB9IGVsc2Uge1xuICAgICAgY29kZUxpbmVzLnB1c2goXG4gICAgICAgICAgJ1xcdCcgK1xuICAgICAgICAgIGBlbHNlIGlmICh0ZXh0dXJlSW5kZXggPT0gJHtpfSkgeyByZXR1cm4gX1gke2l9KGluZGljZXMpOyB9YCk7XG4gICAgfVxuICB9XG4gIGNvZGVMaW5lcy5wdXNoKFxuICAgICAgJ1xcdCcgK1xuICAgICAgJ30nKTtcbiAgcmV0dXJuIGNvZGVMaW5lcy5qb2luKCdcXG4nKTtcbn07XG5cbmNvbnN0IGdldEdldFNpemVJbkNvbmNhdEF4aXNWYWx1ZUZyb21JbmRleE1ldGhvZCA9IChzaXplSW5Db25jYXRBeGlzOiBudW1iZXJbXSk6IHN0cmluZyA9PiB7XG4gIGNvbnN0IGNvZGVMaW5lczogc3RyaW5nW10gPSBbJ2ludCBnZXRTaXplSW5Db25jYXRBeGlzVmFsdWVGcm9tSW5kZXgoaW50IGluZGV4KSB7J107XG4gIGZvciAobGV0IGkgPSAwOyBpIDwgc2l6ZUluQ29uY2F0QXhpcy5sZW5ndGg7ICsraSkge1xuICAgIGlmIChpID09PSAwKSB7XG4gICAgICBjb2RlTGluZXMucHVzaChcbiAgICAgICAgICAnXFx0JyArXG4gICAgICAgICAgYGlmIChpbmRleCA9PSAke2l9KSB7IHJldHVybiAke3NpemVJbkNvbmNhdEF4aXNbaV19OyB9YCk7XG4gICAgfSBlbHNlIGlmIChpID09PSBzaXplSW5Db25jYXRBeGlzLmxlbmd0aCAtIDEpIHtcbiAgICAgIGNvZGVMaW5lcy5wdXNoKFxuICAgICAgICAgICdcXHQnICtcbiAgICAgICAgICBgZWxzZSB7IHJldHVybiAke3NpemVJbkNvbmNhdEF4aXNbaV19OyB9YCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGNvZGVMaW5lcy5wdXNoKFxuICAgICAgICAgICdcXHQnICtcbiAgICAgICAgICBgZWxzZSBpZiAoaW5kZXggPT0gJHtpfSkgeyByZXR1cm4gJHtzaXplSW5Db25jYXRBeGlzW2ldfTsgfWApO1xuICAgIH1cbiAgfVxuICBjb2RlTGluZXMucHVzaChcbiAgICAgICdcXHQnICtcbiAgICAgICd9Jyk7XG5cbiAgcmV0dXJuIGNvZGVMaW5lcy5qb2luKCdcXG4nKTtcbn07XG5cbmV4cG9ydCBjb25zdCBwYXJzZUNvbmNhdEF0dHJpYnV0ZXM6IE9wZXJhdG9ySW5pdGlhbGl6YXRpb248Q29uY2F0QXR0cmlidXRlcz4gPSAobm9kZTogR3JhcGguTm9kZSk6IENvbmNhdEF0dHJpYnV0ZXMgPT5cbiAgICBjcmVhdGVBdHRyaWJ1dGVXaXRoQ2FjaGVLZXkoe2F4aXM6IG5vZGUuYXR0cmlidXRlcy5nZXRJbnQoJ2F4aXMnKX0pO1xuXG5jb25zdCB2YWxpZGF0ZUlucHV0cyA9IChpbnB1dHM6IFRlbnNvcltdKTogdm9pZCA9PiB7XG4gIGlmICghaW5wdXRzIHx8IGlucHV0cy5sZW5ndGggPCAxKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCd0b28gZmV3IGlucHV0cycpO1xuICB9XG5cbiAgY29uc3QgaW5wdXRUeXBlID0gaW5wdXRzWzBdLnR5cGU7XG4gIGNvbnN0IGlucHV0RGltZW5zaW9uYWxpdHkgPSBpbnB1dHNbMF0uZGltcy5sZW5ndGg7XG5cbiAgLy8gVE9ETzogU3VwcG9ydCBzdHJpbmcgY29uY2F0XG4gIGlmIChpbnB1dFR5cGUgPT09ICdzdHJpbmcnKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdzdHJpbmcgdGVuc29yIGlzIG5vdCBzdXBwb3J0ZWQgeWV0Jyk7XG4gIH1cblxuICBmb3IgKGNvbnN0IGlucHV0IG9mIGlucHV0cykge1xuICAgIC8vIG1ha2Ugc3VyZSB0eXBlcyBvZiBhbGwgaW5wdXRzIG1hdGNoXG4gICAgaWYgKGlucHV0LnR5cGUgIT09IGlucHV0VHlwZSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdpbnB1dCB0ZW5zb3JzIHNob3VsZCBiZSBvbmUgdHlwZScpO1xuICAgIH1cblxuICAgIC8vIG1ha2Ugc3VyZSB0aGUgZGltZW5zaW9uYWxpdHkgb2YgYWxsIGlucHV0cyBhcmUgdGhlIHNhbWVcbiAgICBpZiAoaW5wdXQuZGltcy5sZW5ndGggIT09IGlucHV0RGltZW5zaW9uYWxpdHkpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignaW5wdXQgdGVuc29ycyBzaG91bGQgaGF2ZSB0aGUgc2FtZSBzaGFwZScpO1xuICAgIH1cbiAgfVxufTtcbiIsIi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxuXG5pbXBvcnQge0xvZ2dlcn0gZnJvbSAnLi4vLi4vLi4vaW5zdHJ1bWVudCc7XG5pbXBvcnQge1RlbnNvcn0gZnJvbSAnLi4vLi4vLi4vdGVuc29yJztcbmltcG9ydCB7Z2V0R2xzbH0gZnJvbSAnLi4vZ2xzbC1zb3VyY2UnO1xuaW1wb3J0IHtXZWJHTEluZmVyZW5jZUhhbmRsZXJ9IGZyb20gJy4uL2luZmVyZW5jZS1oYW5kbGVyJztcbmltcG9ydCB7UHJvZ3JhbUluZm8sIFByb2dyYW1JbmZvTG9hZGVyLCBQcm9ncmFtTWV0YWRhdGEsIFRleHR1cmVUeXBlfSBmcm9tICcuLi90eXBlcyc7XG5cbmltcG9ydCB7Y2FsY3VsYXRlT3V0cHV0U2hhcGUsIENvbnZBdHRyaWJ1dGVzfSBmcm9tICcuL2NvbnYnO1xuaW1wb3J0IHtnZXRBY3RpdmF0aW9uU25pcHBldH0gZnJvbSAnLi9mdXNlLXV0aWxzJztcblxuY29uc3QgY3JlYXRlVW5wYWNrZWRHcm91cGVkQ29udlByb2dyYW1NZXRhZGF0YSA9IChoYXNCaWFzOiBib29sZWFuLCBjYWNoZUhpbnQ6IHN0cmluZyk6IFByb2dyYW1NZXRhZGF0YSA9PiAoe1xuICBuYW1lOiAnR3JvdXBlZENvbnYnLFxuICBpbnB1dE5hbWVzOiBoYXNCaWFzID8gWydYJywgJ1cnLCAnQmlhcyddIDogWydYJywgJ1cnXSxcbiAgaW5wdXRUeXBlczogaGFzQmlhcyA/IFtUZXh0dXJlVHlwZS51bnBhY2tlZCwgVGV4dHVyZVR5cGUudW5wYWNrZWQsIFRleHR1cmVUeXBlLnVucGFja2VkXSA6XG4gICAgICAgICAgICAgICAgICAgICAgICBbVGV4dHVyZVR5cGUudW5wYWNrZWQsIFRleHR1cmVUeXBlLnVucGFja2VkXSxcbiAgY2FjaGVIaW50XG59KTtcblxuY29uc3QgY3JlYXRlVW5wYWNrZWRHcm91cGVkQ29udlByb2dyYW1JbmZvID1cbiAgICAoaW5mZXJlbmNlSGFuZGxlcjogV2ViR0xJbmZlcmVuY2VIYW5kbGVyLCBpbnB1dHM6IHJlYWRvbmx5IFRlbnNvcltdLCBtZXRhZGF0YTogUHJvZ3JhbU1ldGFkYXRhLFxuICAgICBhdHRyaWJ1dGVzOiBDb252QXR0cmlidXRlcyk6IFByb2dyYW1JbmZvID0+IHtcbiAgICAgIGNvbnN0IGhhc0JpYXMgPSBpbnB1dHMubGVuZ3RoID4gMjtcbiAgICAgIGNvbnN0IHByb2Nlc3NCaWFzID0gaGFzQmlhcyA/ICd2YWx1ZSArPSBnZXRCaWFzKG91dHB1dF9jaGFubmVsKTsnIDogJyc7XG4gICAgICBjb25zdCB4U2hhcGUgPSBpbnB1dHNbMF0uZGltcy5zbGljZSgpO1xuICAgICAgY29uc3Qgd1NoYXBlID0gaW5wdXRzWzFdLmRpbXMuc2xpY2UoKTtcbiAgICAgIGNvbnN0IG91dHB1dENoYW5uZWxzUGVyR3JvdXAgPSB3U2hhcGVbMF0gLyBhdHRyaWJ1dGVzLmdyb3VwO1xuICAgICAgTG9nZ2VyLnZlcmJvc2UoXG4gICAgICAgICAgJ0dyb3VwZWRDb252JyxcbiAgICAgICAgICBgYXV0cFBhZDoke2F0dHJpYnV0ZXMuYXV0b1BhZH0sIGRpbGF0aW9uczoke2F0dHJpYnV0ZXMuZGlsYXRpb25zfSwgZ3JvdXA6JHthdHRyaWJ1dGVzLmdyb3VwfSwga2VybmVsU2hhcGU6JHtcbiAgICAgICAgICAgICAgYXR0cmlidXRlcy5rZXJuZWxTaGFwZX0sIHBhZHM6JHthdHRyaWJ1dGVzLnBhZHN9LCBzdHJpZGVzOiR7YXR0cmlidXRlcy5zdHJpZGVzfWApO1xuICAgICAgY29uc3Qgb3V0cHV0U2hhcGUgPVxuICAgICAgICAgIGNhbGN1bGF0ZU91dHB1dFNoYXBlKHhTaGFwZSwgd1NoYXBlLCBhdHRyaWJ1dGVzLmRpbGF0aW9ucywgYXR0cmlidXRlcy5wYWRzLCBhdHRyaWJ1dGVzLnN0cmlkZXMpO1xuICAgICAgY29uc3QgZ2xzbCA9IGdldEdsc2woaW5mZXJlbmNlSGFuZGxlci5zZXNzaW9uLmJhY2tlbmQuZ2xDb250ZXh0LnZlcnNpb24pO1xuICAgICAgY29uc3Qge2FjdGl2YXRpb25GdW5jdGlvbiwgYXBwbHlBY3RpdmF0aW9ufSA9IGdldEFjdGl2YXRpb25TbmlwcGV0KGF0dHJpYnV0ZXMpO1xuXG4gICAgICBjb25zdCBzaGFkZXJTb3VyY2UgPSBgXG4gIGNvbnN0IGl2ZWMyIHN0cmlkZXMgPSBpdmVjMigke2F0dHJpYnV0ZXMuc3RyaWRlc1swXX0sICR7YXR0cmlidXRlcy5zdHJpZGVzWzFdfSk7XG4gIGNvbnN0IGl2ZWMyIHBhZHMgPSBpdmVjMigke2F0dHJpYnV0ZXMucGFkc1swXX0sICR7YXR0cmlidXRlcy5wYWRzWzFdfSk7XG4gICR7YWN0aXZhdGlvbkZ1bmN0aW9ufVxuICB2b2lkIG1haW4oKSB7XG4gICAgaXZlYzQgY29vcmRzID0gZ2V0T3V0cHV0Q29vcmRzKCk7XG4gICAgaW50IGJhdGNoID0gY29vcmRzLng7XG4gICAgaW50IG91dHB1dF9jaGFubmVsID0gY29vcmRzLnk7XG4gICAgaXZlYzIgeFJDQ29ybmVyID0gY29vcmRzLnp3ICogc3RyaWRlcyAtIHBhZHM7XG4gICAgaW50IGdyb3VwX2lkID0gb3V0cHV0X2NoYW5uZWwgLyAke291dHB1dENoYW5uZWxzUGVyR3JvdXB9O1xuXG4gICAgZmxvYXQgdmFsdWUgPSAwLjA7XG4gICAgZm9yIChpbnQgd0luQ2hhbm5lbCA9IDA7IHdJbkNoYW5uZWwgPCAke3dTaGFwZVsxXX07IHdJbkNoYW5uZWwrKykge1xuICAgICAgaW50IGlucHV0X2NoYW5uZWwgPSBncm91cF9pZCAqICR7d1NoYXBlWzFdfSArIHdJbkNoYW5uZWw7XG4gICAgICBmb3IgKGludCB3SGVpZ2h0ID0gMDsgd0hlaWdodCA8ICR7d1NoYXBlWzJdfTsgd0hlaWdodCsrKSB7XG4gICAgICAgIGludCB4SGVpZ2h0ID0geFJDQ29ybmVyLnggKyB3SGVpZ2h0ICogJHthdHRyaWJ1dGVzLmRpbGF0aW9uc1swXX07XG5cbiAgICAgICAgaWYgKHhIZWlnaHQgPCAwIHx8IHhIZWlnaHQgPj0gJHt4U2hhcGVbMl19KSB7XG4gICAgICAgICAgY29udGludWU7XG4gICAgICAgIH1cblxuICAgICAgICBmb3IgKGludCB3V2lkdGggPSAwOyB3V2lkdGggPCAke3dTaGFwZVszXX07IHdXaWR0aCsrKSB7XG4gICAgICAgICAgaW50IHhXaWR0aCA9IHhSQ0Nvcm5lci55ICsgd1dpZHRoICogJHthdHRyaWJ1dGVzLmRpbGF0aW9uc1sxXX07XG4gICAgICAgICAgaWYgKHhXaWR0aCA8IDAgfHwgeFdpZHRoID49ICR7eFNoYXBlWzNdfSkge1xuICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgZmxvYXQgeFZhbCA9IGdldFgoYmF0Y2gsIGlucHV0X2NoYW5uZWwsIHhXaWR0aCwgeEhlaWdodCk7XG4gICAgICAgICAgZmxvYXQgd1ZhbCA9IGdldFcob3V0cHV0X2NoYW5uZWwsIHdJbkNoYW5uZWwsIHdXaWR0aCwgd0hlaWdodCk7XG4gICAgICAgICAgdmFsdWUgKz0geFZhbCp3VmFsO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICAgICR7cHJvY2Vzc0JpYXN9XG4gICAgJHthcHBseUFjdGl2YXRpb259XG4gICAgJHtnbHNsLm91dHB1dH0gPSB2ZWM0KHZhbHVlLCAuMCwgLjAsIC4wKTtcbiAgfVxuYDtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIC4uLm1ldGFkYXRhLFxuICAgICAgICBvdXRwdXQ6IHtkaW1zOiBvdXRwdXRTaGFwZSwgdHlwZTogaW5wdXRzWzBdLnR5cGUsIHRleHR1cmVUeXBlOiBUZXh0dXJlVHlwZS51bnBhY2tlZH0sXG4gICAgICAgIHNoYWRlclNvdXJjZSxcbiAgICAgICAgaGFzTWFpbjogdHJ1ZSxcbiAgICAgIH07XG4gICAgfTtcblxuZXhwb3J0IGNvbnN0IGNyZWF0ZVVucGFja2VkR3JvdXBlZENvbnZQcm9ncmFtSW5mb0xvYWRlciA9XG4gICAgKGluZmVyZW5jZUhhbmRsZXI6IFdlYkdMSW5mZXJlbmNlSGFuZGxlciwgaW5wdXRzOiByZWFkb25seSBUZW5zb3JbXSwgYXR0cmlidXRlczogQ29udkF0dHJpYnV0ZXMpOlxuICAgICAgICBQcm9ncmFtSW5mb0xvYWRlciA9PiB7XG4gICAgICAgICAgY29uc3QgbWV0YWRhdGEgPSBjcmVhdGVVbnBhY2tlZEdyb3VwZWRDb252UHJvZ3JhbU1ldGFkYXRhKGlucHV0cy5sZW5ndGggPiAyLCBhdHRyaWJ1dGVzLmNhY2hlS2V5KTtcbiAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgLi4ubWV0YWRhdGEsXG4gICAgICAgICAgICBnZXQ6ICgpID0+IGNyZWF0ZVVucGFja2VkR3JvdXBlZENvbnZQcm9ncmFtSW5mbyhpbmZlcmVuY2VIYW5kbGVyLCBpbnB1dHMsIG1ldGFkYXRhLCBhdHRyaWJ1dGVzKVxuICAgICAgICAgIH07XG4gICAgICAgIH07XG4iLCIvLyBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cblxuaW1wb3J0IHtUZW5zb3J9IGZyb20gJy4uLy4uLy4uL3RlbnNvcic7XG5pbXBvcnQge1dlYkdMSW5mZXJlbmNlSGFuZGxlcn0gZnJvbSAnLi4vaW5mZXJlbmNlLWhhbmRsZXInO1xuXG5pbXBvcnQge2NhbGN1bGF0ZU91dHB1dFNoYXBlLCBDb252QXR0cmlidXRlc30gZnJvbSAnLi9jb252JztcbmltcG9ydCB7Y3JlYXRlUGFja2VkSW0yQ29sUHJvZ3JhbUluZm9Mb2FkZXJ9IGZyb20gJy4vaW0yY29sLXBhY2snO1xuaW1wb3J0IHtjcmVhdGVQYWNrZWRNYXRtdWxQcm9ncmFtSW5mb0xvYWRlcn0gZnJvbSAnLi9tYXRtdWwtcGFjayc7XG5cbmV4cG9ydCBjb25zdCBjb252MkRQYWNrZWRQb2ludHdpc2UgPVxuICAgIChpbmZlcmVuY2VIYW5kbGVyOiBXZWJHTEluZmVyZW5jZUhhbmRsZXIsIGlucHV0czogcmVhZG9ubHkgVGVuc29yW10sIGF0dHJpYnV0ZXM6IENvbnZBdHRyaWJ1dGVzKTogVGVuc29yID0+IHtcbiAgICAgIGNvbnN0IHhzaGFwZSA9IGlucHV0c1swXS5kaW1zO1xuICAgICAgY29uc3Qga3NoYXBlID0gaW5wdXRzWzFdLmRpbXM7XG4gICAgICBjb25zdCBvdXRwdXRTaGFwZSA9XG4gICAgICAgICAgY2FsY3VsYXRlT3V0cHV0U2hhcGUoeHNoYXBlLCBrc2hhcGUsIGF0dHJpYnV0ZXMuZGlsYXRpb25zLCBhdHRyaWJ1dGVzLnBhZHMsIGF0dHJpYnV0ZXMuc3RyaWRlcyk7XG4gICAgICBjb25zdCByZXNoYXBlZFggPSBpbmZlcmVuY2VIYW5kbGVyLnJlc2hhcGVQYWNrZWQoaW5wdXRzWzBdLCBbeHNoYXBlWzFdLCB4c2hhcGVbMl0gKiB4c2hhcGVbM11dKTtcbiAgICAgIGNvbnN0IHJlc2hhcGVkSyA9IGluZmVyZW5jZUhhbmRsZXIucmVzaGFwZVBhY2tlZChpbnB1dHNbMV0sIFtrc2hhcGVbMF0sIGtzaGFwZVsxXV0pO1xuXG4gICAgICBjb25zdCBtYXRtdWxJbnB1dHMgPSBpbnB1dHMubGVuZ3RoID4gMiA/IFtyZXNoYXBlZEssIHJlc2hhcGVkWCwgaW5wdXRzWzJdXSA6IFtyZXNoYXBlZEssIHJlc2hhcGVkWF07XG4gICAgICBjb25zdCBtYXRtdWxPdXRwdXQgPSBpbmZlcmVuY2VIYW5kbGVyLnJ1bihcbiAgICAgICAgICBjcmVhdGVQYWNrZWRNYXRtdWxQcm9ncmFtSW5mb0xvYWRlcihpbmZlcmVuY2VIYW5kbGVyLCBtYXRtdWxJbnB1dHMsIGF0dHJpYnV0ZXMpLCBtYXRtdWxJbnB1dHMpO1xuICAgICAgcmV0dXJuIGluZmVyZW5jZUhhbmRsZXIucmVzaGFwZVBhY2tlZChtYXRtdWxPdXRwdXQsIG91dHB1dFNoYXBlKTtcbiAgICB9O1xuXG5leHBvcnQgY29uc3QgY29udjJEUGFja2VkID1cbiAgICAoaW5mZXJlbmNlSGFuZGxlcjogV2ViR0xJbmZlcmVuY2VIYW5kbGVyLCBpbnB1dHM6IHJlYWRvbmx5IFRlbnNvcltdLCBhdHRyaWJ1dGVzOiBDb252QXR0cmlidXRlcyk6IFRlbnNvciA9PiB7XG4gICAgICBjb25zdCB4c2hhcGUgPSBpbnB1dHNbMF0uZGltcztcbiAgICAgIGNvbnN0IGtzaGFwZSA9IGlucHV0c1sxXS5kaW1zO1xuICAgICAgY29uc3Qgb3V0cHV0U2hhcGUgPVxuICAgICAgICAgIGNhbGN1bGF0ZU91dHB1dFNoYXBlKHhzaGFwZSwga3NoYXBlLCBhdHRyaWJ1dGVzLmRpbGF0aW9ucywgYXR0cmlidXRlcy5wYWRzLCBhdHRyaWJ1dGVzLnN0cmlkZXMpO1xuXG4gICAgICAvLyBydW4gaW0yY29sXG4gICAgICBjb25zdCBpbTJjb2xPdXRwdXQgPSBpbmZlcmVuY2VIYW5kbGVyLnJ1bihcbiAgICAgICAgICBjcmVhdGVQYWNrZWRJbTJDb2xQcm9ncmFtSW5mb0xvYWRlcihpbmZlcmVuY2VIYW5kbGVyLCBpbnB1dHNbMF0sIGlucHV0c1sxXSwgb3V0cHV0U2hhcGUsIGF0dHJpYnV0ZXMpLFxuICAgICAgICAgIFtpbnB1dHNbMF1dKTtcblxuICAgICAgLy8gcmVzaGFwZSBrZXJuZWxcbiAgICAgIGNvbnN0IGtlcm5lbFJlc2hhcGVkID0gaW5mZXJlbmNlSGFuZGxlci5yZXNoYXBlUGFja2VkKGlucHV0c1sxXSwgW2tzaGFwZVswXSwga3NoYXBlWzFdICoga3NoYXBlWzJdICoga3NoYXBlWzNdXSk7XG5cbiAgICAgIC8vIHJ1biBtYXRtdWxcbiAgICAgIGNvbnN0IG1hdG11bElucHV0cyA9XG4gICAgICAgICAgKGlucHV0cy5sZW5ndGggPT09IDMpID8gW2tlcm5lbFJlc2hhcGVkLCBpbTJjb2xPdXRwdXQsIGlucHV0c1syXV0gOiBba2VybmVsUmVzaGFwZWQsIGltMmNvbE91dHB1dF07XG4gICAgICBjb25zdCBtYXRtdWxPdXRwdXQgPSBpbmZlcmVuY2VIYW5kbGVyLnJ1bihcbiAgICAgICAgICBjcmVhdGVQYWNrZWRNYXRtdWxQcm9ncmFtSW5mb0xvYWRlcihpbmZlcmVuY2VIYW5kbGVyLCBtYXRtdWxJbnB1dHMsIGF0dHJpYnV0ZXMpLCBtYXRtdWxJbnB1dHMpO1xuXG4gICAgICAvLyByZXNoYXBlIG91dHB1dFxuICAgICAgY29uc3Qgb3V0cHV0UmVzaGFwZWQgPSBpbmZlcmVuY2VIYW5kbGVyLnJlc2hhcGVQYWNrZWQobWF0bXVsT3V0cHV0LCBvdXRwdXRTaGFwZSk7XG4gICAgICByZXR1cm4gb3V0cHV0UmVzaGFwZWQ7XG4gICAgfTtcbiIsIi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxuXG5pbXBvcnQge2NyZWF0ZUF0dHJpYnV0ZVdpdGhDYWNoZUtleX0gZnJvbSAnLi4vLi4vLi4vYXR0cmlidXRlLXdpdGgtY2FjaGUta2V5JztcbmltcG9ydCB7SW5mZXJlbmNlSGFuZGxlcn0gZnJvbSAnLi4vLi4vLi4vYmFja2VuZCc7XG5pbXBvcnQge0dyYXBofSBmcm9tICcuLi8uLi8uLi9ncmFwaCc7XG5pbXBvcnQge09wZXJhdG9ySW1wbGVtZW50YXRpb24sIE9wZXJhdG9ySW5pdGlhbGl6YXRpb259IGZyb20gJy4uLy4uLy4uL29wZXJhdG9ycyc7XG5pbXBvcnQge1RlbnNvcn0gZnJvbSAnLi4vLi4vLi4vdGVuc29yJztcbmltcG9ydCB7Z2V0R2xzbH0gZnJvbSAnLi4vZ2xzbC1zb3VyY2UnO1xuaW1wb3J0IHtXZWJHTEluZmVyZW5jZUhhbmRsZXJ9IGZyb20gJy4uL2luZmVyZW5jZS1oYW5kbGVyJztcbmltcG9ydCB7UHJvZ3JhbUluZm8sIFByb2dyYW1JbmZvTG9hZGVyLCBQcm9ncmFtTWV0YWRhdGEsIFRleHR1cmVUeXBlfSBmcm9tICcuLi90eXBlcyc7XG5cbmltcG9ydCB7Q29udkF0dHJpYnV0ZXN9IGZyb20gJy4vY29udic7XG5pbXBvcnQge2dldEFjdGl2YXRpb25TbmlwcGV0LCBwYXJzZUludGVybmFsQWN0aXZhdGlvbkF0dHJpYnV0ZXN9IGZyb20gJy4vZnVzZS11dGlscyc7XG5cbmNvbnN0IGNvbXB1dGVUb3RhbFBhZCA9XG4gICAgKGluRGltOiBudW1iZXIsIHN0cmlkZTogbnVtYmVyLCBhZGo6IG51bWJlciwga2VybmVsOiBudW1iZXIsIGRpbGF0aW9uOiBudW1iZXIsIG91dFNpemU6IG51bWJlcikgPT5cbiAgICAgICAgKGluRGltIC0gMSkgKiBzdHJpZGUgKyBhZGogKyAoa2VybmVsIC0gMSkgKiBkaWxhdGlvbiArIDEgLSBvdXRTaXplO1xuXG5jb25zdCBkaXN0cmlidXRlUGFkZGluZyA9ICh0b3RhbFBhZDogbnVtYmVyLCBhdXRvUGFkOiBzdHJpbmcsIHBhZHM6IG51bWJlcltdLCBoZWFkOiBudW1iZXIsIHRhaWw6IG51bWJlcikgPT4ge1xuICBjb25zdCBzbWFsbFBhZCA9IE1hdGguZmxvb3IodG90YWxQYWQgLyAyKTtcbiAgaWYgKGF1dG9QYWQgPT09ICdTQU1FX1VQUEVSJykge1xuICAgIHBhZHNbaGVhZF0gPSBzbWFsbFBhZDtcbiAgICBwYWRzW3RhaWxdID0gdG90YWxQYWQgLSBzbWFsbFBhZDtcbiAgfSBlbHNlIGlmIChhdXRvUGFkID09PSAnU0FNRV9MT1dFUicpIHtcbiAgICBwYWRzW2hlYWRdID0gdG90YWxQYWQgLSBzbWFsbFBhZDtcbiAgICBwYWRzW3RhaWxdID0gc21hbGxQYWQ7XG4gIH1cbn07XG5cbmNvbnN0IGNhbGN1bGF0ZU91dHB1dFNoYXBlQW5kUGFkcyA9XG4gICAgKGlucHV0U2hhcGU6IHJlYWRvbmx5IG51bWJlcltdLCBrZXJuZWxTaGFwZTogcmVhZG9ubHkgbnVtYmVyW10sIGRpbGF0aW9uczogcmVhZG9ubHkgbnVtYmVyW10sIGF1dG9QYWQ6IHN0cmluZyxcbiAgICAgcGFkczogbnVtYmVyW10sIHN0cmlkZXM6IHJlYWRvbmx5IG51bWJlcltdLCBvdXRwdXRQYWRkaW5nOiByZWFkb25seSBudW1iZXJbXSwgb3V0cHV0U2hhcGU6IG51bWJlcltdKSA9PiB7XG4gICAgICBjb25zdCBzcGF0aWFsUmFuayA9IGlucHV0U2hhcGUubGVuZ3RoIC0gMjtcbiAgICAgIGNvbnN0IHVwZGF0ZVNoYXBlID0gb3V0cHV0U2hhcGUubGVuZ3RoID09PSAwO1xuICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBzcGF0aWFsUmFuazsgKytpKSB7XG4gICAgICAgIGNvbnN0IG91dFNpemUgPSB1cGRhdGVTaGFwZSA/IGlucHV0U2hhcGVbaSArIDJdICogc3RyaWRlc1tpXSA6IG91dHB1dFNoYXBlW2ldO1xuICAgICAgICBjb25zdCB0b3RhbFBhZCA9IGNvbXB1dGVUb3RhbFBhZChpbnB1dFNoYXBlW2kgKyAyXSwgc3RyaWRlc1tpXSwgcGFkc1tpXSwga2VybmVsU2hhcGVbaV0sIGRpbGF0aW9uc1tpXSwgb3V0U2l6ZSk7XG4gICAgICAgIGRpc3RyaWJ1dGVQYWRkaW5nKHRvdGFsUGFkLCBhdXRvUGFkLCBwYWRzLCBpLCBpICsgc3BhdGlhbFJhbmspO1xuICAgICAgICBpZiAodXBkYXRlU2hhcGUpIHtcbiAgICAgICAgICBvdXRwdXRTaGFwZS5wdXNoKFxuICAgICAgICAgICAgICBzdHJpZGVzW2ldICogKGlucHV0U2hhcGVbaSArIDJdIC0gMSkgKyBvdXRwdXRQYWRkaW5nW2ldICsgKGtlcm5lbFNoYXBlW2ldIC0gMSkgKiBkaWxhdGlvbnNbaV0gKyAxIC1cbiAgICAgICAgICAgICAgcGFkc1tpXSAtIHBhZHNbaSArIHNwYXRpYWxSYW5rXSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9O1xuXG5leHBvcnQgaW50ZXJmYWNlIENvbnZUcmFuc3Bvc2VBdHRyaWJ1dGVzIGV4dGVuZHMgQ29udkF0dHJpYnV0ZXMge1xuICByZWFkb25seSBvdXRwdXRQYWRkaW5nOiByZWFkb25seSBudW1iZXJbXTtcbiAgcmVhZG9ubHkgb3V0cHV0U2hhcGU6IHJlYWRvbmx5IG51bWJlcltdO1xufVxuXG5leHBvcnQgY29uc3QgY29udlRyYW5zcG9zZTogT3BlcmF0b3JJbXBsZW1lbnRhdGlvbjxDb252VHJhbnNwb3NlQXR0cmlidXRlcz4gPVxuICAgIChpbmZlcmVuY2VIYW5kbGVyOiBJbmZlcmVuY2VIYW5kbGVyLCBpbnB1dHM6IFRlbnNvcltdLCBhdHRyaWJ1dGVzOiBDb252VHJhbnNwb3NlQXR0cmlidXRlcyk6IFRlbnNvcltdID0+IHtcbiAgICAgIHZhbGlkYXRlSW5wdXRzKGlucHV0cywgYXR0cmlidXRlcyk7ICAvLyBjdXJyZW50bHkgd2lsbCBmYWlsIGlmIG5vdCBjb252VHJhbnNwb3NlMkRcbiAgICAgIHJldHVybiBjb252VHJhbnNwb3NlMmQoaW5mZXJlbmNlSGFuZGxlciwgaW5wdXRzLCBhdHRyaWJ1dGVzKTtcbiAgICB9O1xuXG5jb25zdCBjb252VHJhbnNwb3NlMmQ6IE9wZXJhdG9ySW1wbGVtZW50YXRpb248Q29udlRyYW5zcG9zZUF0dHJpYnV0ZXM+ID1cbiAgICAoaW5mZXJlbmNlSGFuZGxlcjogV2ViR0xJbmZlcmVuY2VIYW5kbGVyLCBpbnB1dHM6IFRlbnNvcltdLCBhdHRyaWJ1dGVzOiBDb252VHJhbnNwb3NlQXR0cmlidXRlcyk6IFRlbnNvcltdID0+IHtcbiAgICAgIGNvbnN0IGFkanVzdGVkQXR0cmlidXRlcyA9IGdldEFkanVzdGVkQ29udlRyYW5zcG9zZUF0dHJpYnV0ZXMoYXR0cmlidXRlcywgaW5wdXRzKTtcbiAgICAgIHJldHVybiBbY29udlRyYW5zcG9zZTJEVW5wYWNrZWQoaW5mZXJlbmNlSGFuZGxlciwgaW5wdXRzLCBhZGp1c3RlZEF0dHJpYnV0ZXMpXTtcbiAgICB9O1xuXG5jb25zdCBjcmVhdGVDb252VHJhbnNwb3NlUHJvZ3JhbU1ldGFkYXRhID0gKGhhc0JpYXM6IGJvb2xlYW4sIGNhY2hlSGludDogc3RyaW5nKSA9PiAoe1xuICBuYW1lOiAnQ29udlRyYW5zcG9zZScsXG4gIGlucHV0TmFtZXM6IGhhc0JpYXMgPyBbJ1gnLCAnVycsICdCJ10gOiBbJ1gnLCAnVyddLFxuICBpbnB1dFR5cGVzOiBoYXNCaWFzID8gW1RleHR1cmVUeXBlLnVucGFja2VkLCBUZXh0dXJlVHlwZS51bnBhY2tlZCwgVGV4dHVyZVR5cGUudW5wYWNrZWRdIDpcbiAgICAgICAgICAgICAgICAgICAgICAgIFtUZXh0dXJlVHlwZS51bnBhY2tlZCwgVGV4dHVyZVR5cGUudW5wYWNrZWRdLFxuICBjYWNoZUhpbnRcbn0pO1xuXG5jb25zdCBjcmVhdGVVbnBhY2tlZENvbnZUcmFuc3Bvc2VQcm9ncmFtSW5mbyA9XG4gICAgKGluZmVyZW5jZUhhbmRsZXI6IFdlYkdMSW5mZXJlbmNlSGFuZGxlciwgaW5wdXRzOiByZWFkb25seSBUZW5zb3JbXSwgbWV0YWRhdGE6IFByb2dyYW1NZXRhZGF0YSxcbiAgICAgYXR0cmlidXRlczogQ29udlRyYW5zcG9zZUF0dHJpYnV0ZXMpOiBQcm9ncmFtSW5mbyA9PiB7XG4gICAgICBjb25zdCBoYXNCaWFzID0gaW5wdXRzLmxlbmd0aCA+IDI7XG4gICAgICBjb25zdCB2YWx1ZUluaXQgPSBoYXNCaWFzID8gJ2dldEIob3V0cHV0X2NoYW5uZWwpJyA6ICcwLjAnO1xuICAgICAgY29uc3QgeFNoYXBlID0gaW5wdXRzWzBdLmRpbXM7XG4gICAgICBjb25zdCB3U2hhcGUgPSBpbnB1dHNbMV0uZGltcztcbiAgICAgIGNvbnN0IG91dHB1dENoYW5uZWxzUGVyR3JvdXAgPSB3U2hhcGVbMV07XG4gICAgICBjb25zdCBpbnB1dENoYW5uZWxzUGVyR3JvdXAgPSB3U2hhcGVbMF0gLyBhdHRyaWJ1dGVzLmdyb3VwO1xuICAgICAgY29uc3Qgb3V0cHV0U2hhcGUgPSBbaW5wdXRzWzBdLmRpbXNbMF0sIGlucHV0c1sxXS5kaW1zWzFdICogYXR0cmlidXRlcy5ncm91cCwgLi4uYXR0cmlidXRlcy5vdXRwdXRTaGFwZV07XG4gICAgICBjb25zdCBnbHNsID0gZ2V0R2xzbChpbmZlcmVuY2VIYW5kbGVyLnNlc3Npb24uYmFja2VuZC5nbENvbnRleHQudmVyc2lvbik7XG4gICAgICBjb25zdCB7YWN0aXZhdGlvbkZ1bmN0aW9uLCBhcHBseUFjdGl2YXRpb259ID0gZ2V0QWN0aXZhdGlvblNuaXBwZXQoYXR0cmlidXRlcyk7XG5cbiAgICAgIGNvbnN0IHNoYWRlclNvdXJjZSA9IGBcbiAgY29uc3QgaXZlYzIgc3RyaWRlcyA9IGl2ZWMyKCR7YXR0cmlidXRlcy5zdHJpZGVzWzBdfSwgJHthdHRyaWJ1dGVzLnN0cmlkZXNbMV19KTtcbiAgY29uc3QgaXZlYzIgcGFkcyA9IGl2ZWMyKCR7YXR0cmlidXRlcy5wYWRzWzBdfSwgJHthdHRyaWJ1dGVzLnBhZHNbMV19KTtcbiAgJHthY3RpdmF0aW9uRnVuY3Rpb259XG4gIHZvaWQgbWFpbigpIHtcbiAgICBpdmVjNCBjb29yZHMgPSBnZXRPdXRwdXRDb29yZHMoKTtcbiAgICBpbnQgYmF0Y2ggPSBjb29yZHMueDtcbiAgICBpbnQgb3V0cHV0X2NoYW5uZWwgPSBjb29yZHMueTtcblxuICAgIGl2ZWMyIGxvYyA9IGNvb3Jkcy56dyArIHBhZHM7XG5cbiAgICBpbnQgZ3JvdXBfaWQgPSBvdXRwdXRfY2hhbm5lbCAvICR7b3V0cHV0Q2hhbm5lbHNQZXJHcm91cH07XG4gICAgaW50IHdPdXRDaGFubmVsID0gb3V0cHV0X2NoYW5uZWwgLSBncm91cF9pZCAqICR7b3V0cHV0Q2hhbm5lbHNQZXJHcm91cH07XG5cbiAgICBmbG9hdCB2YWx1ZSA9ICR7dmFsdWVJbml0fTtcbiAgICBmb3IgKGludCBpbkNoYW5uZWxPZmZzZXQgPSAwOyBpbkNoYW5uZWxPZmZzZXQgPCAke2lucHV0Q2hhbm5lbHNQZXJHcm91cH07IGluQ2hhbm5lbE9mZnNldCsrKSB7XG4gICAgICBpbnQgaW5wdXRfY2hhbm5lbCA9IGdyb3VwX2lkICogJHtpbnB1dENoYW5uZWxzUGVyR3JvdXB9ICsgaW5DaGFubmVsT2Zmc2V0O1xuICAgICAgZm9yIChpbnQgd1dPZmYgPSAwOyB3V09mZiA8ICR7d1NoYXBlWzJdfTsgd1dPZmYrKykge1xuICAgICAgICBmb3IgKGludCB3SE9mZiA9IDA7IHdIT2ZmIDwgJHt3U2hhcGVbM119OyB3SE9mZisrKSB7XG4gICAgICAgICAgaXZlYzIgd09mZiA9IGl2ZWMyKHdXT2ZmICogJHthdHRyaWJ1dGVzLmRpbGF0aW9uc1swXX0sIHdIT2ZmICogJHthdHRyaWJ1dGVzLmRpbGF0aW9uc1sxXX0pO1xuICAgICAgICAgIGl2ZWMyIHdMb2MgPSBsb2MgLSB3T2ZmO1xuICAgICAgICAgIGl2ZWMyIHdMb2NJbiA9IHdMb2MgLyBzdHJpZGVzO1xuICAgICAgICAgIGlmIChcbiAgICAgICAgICAgIHdMb2NJbiAqIHN0cmlkZXMgPT0gd0xvYyAmJlxuICAgICAgICAgICAgd0xvY0luLnggPj0gMCAmJiB3TG9jSW4ueCA8ICR7eFNoYXBlWzJdfSAmJlxuICAgICAgICAgICAgd0xvY0luLnkgPj0gMCAmJiB3TG9jSW4ueSA8ICR7eFNoYXBlWzNdfVxuICAgICAgICAgICkge1xuICAgICAgICAgICAgZmxvYXQgeFZhbCA9IGdldFgoYmF0Y2gsIGlucHV0X2NoYW5uZWwsIHdMb2NJbi55LCB3TG9jSW4ueCk7XG4gICAgICAgICAgICBmbG9hdCB3VmFsID0gZ2V0VyhpbnB1dF9jaGFubmVsLCB3T3V0Q2hhbm5lbCwgd0hPZmYsIHdXT2ZmKTtcbiAgICAgICAgICAgIHZhbHVlICs9IHhWYWwgKiB3VmFsO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgICAke2FwcGx5QWN0aXZhdGlvbn1cbiAgICAke2dsc2wub3V0cHV0fSA9IHZlYzQodmFsdWUsIC4wLCAuMCwgLjApO1xuICB9XG5gO1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgLi4ubWV0YWRhdGEsXG4gICAgICAgIG91dHB1dDoge2RpbXM6IG91dHB1dFNoYXBlLCB0eXBlOiBpbnB1dHNbMF0udHlwZSwgdGV4dHVyZVR5cGU6IFRleHR1cmVUeXBlLnVucGFja2VkfSxcbiAgICAgICAgc2hhZGVyU291cmNlLFxuICAgICAgICBoYXNNYWluOiB0cnVlLFxuICAgICAgfTtcbiAgICB9O1xuXG5jb25zdCBjcmVhdGVVbnBhY2tlZENvbnZUcmFuc3Bvc2VQcm9ncmFtSW5mb0xvYWRlciA9XG4gICAgKGluZmVyZW5jZUhhbmRsZXI6IFdlYkdMSW5mZXJlbmNlSGFuZGxlciwgaW5wdXRzOiByZWFkb25seSBUZW5zb3JbXSwgYXR0cmlidXRlczogQ29udlRyYW5zcG9zZUF0dHJpYnV0ZXMpOlxuICAgICAgICBQcm9ncmFtSW5mb0xvYWRlciA9PiB7XG4gICAgICAgICAgY29uc3QgbWV0YWRhdGEgPSBjcmVhdGVDb252VHJhbnNwb3NlUHJvZ3JhbU1ldGFkYXRhKGlucHV0cy5sZW5ndGggPiAyLCBhdHRyaWJ1dGVzLmNhY2hlS2V5KTtcbiAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgLi4ubWV0YWRhdGEsXG4gICAgICAgICAgICBnZXQ6ICgpID0+IGNyZWF0ZVVucGFja2VkQ29udlRyYW5zcG9zZVByb2dyYW1JbmZvKGluZmVyZW5jZUhhbmRsZXIsIGlucHV0cywgbWV0YWRhdGEsIGF0dHJpYnV0ZXMpXG4gICAgICAgICAgfTtcbiAgICAgICAgfTtcblxuXG5jb25zdCBjb252VHJhbnNwb3NlMkRVbnBhY2tlZCA9XG4gICAgKGluZmVyZW5jZUhhbmRsZXI6IFdlYkdMSW5mZXJlbmNlSGFuZGxlciwgaW5wdXRzOiByZWFkb25seSBUZW5zb3JbXSwgYXR0cmlidXRlczogQ29udlRyYW5zcG9zZUF0dHJpYnV0ZXMpOlxuICAgICAgICBUZW5zb3IgPT4ge1xuICAgICAgICAgIGNvbnN0IHJlc3VsdCA9IGluZmVyZW5jZUhhbmRsZXIucnVuKFxuICAgICAgICAgICAgICBjcmVhdGVVbnBhY2tlZENvbnZUcmFuc3Bvc2VQcm9ncmFtSW5mb0xvYWRlcihpbmZlcmVuY2VIYW5kbGVyLCBpbnB1dHMsIGF0dHJpYnV0ZXMpLCBpbnB1dHMpO1xuICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgIH07XG5cbmNvbnN0IGdldEFkanVzdGVkQ29udlRyYW5zcG9zZUF0dHJpYnV0ZXMgPSA8VCBleHRlbmRzIENvbnZUcmFuc3Bvc2VBdHRyaWJ1dGVzPihhdHRyaWJ1dGVzOiBULCBpbnB1dHM6IFRlbnNvcltdKTogVCA9PiB7XG4gIGNvbnN0IGtlcm5lbFNoYXBlID0gYXR0cmlidXRlcy5rZXJuZWxTaGFwZS5zbGljZSgpO1xuICAvLyBpZiBrZXJuZWxTaGFwZSBpcyBub3Qgc3BlY2lmaWVkIGluIHRoZSBhdHRyaWJ1dGVzIG9mIHRoaXMgb3AsIGluZmVyIGl0IGZyb20gdGhlIHdlaWdodCB0ZW5zb3IgZGltc1xuICBpZiAoYXR0cmlidXRlcy5rZXJuZWxTaGFwZS5sZW5ndGggPT09IDApIHtcbiAgICBmb3IgKGxldCBpID0gMjsgaSA8IGlucHV0c1sxXS5kaW1zLmxlbmd0aDsgKytpKSB7XG4gICAgICBrZXJuZWxTaGFwZS5wdXNoKGlucHV0c1sxXS5kaW1zW2ldKTtcbiAgICB9XG4gIH1cblxuICBjb25zdCBwYWRzID0gYXR0cmlidXRlcy5wYWRzLnNsaWNlKCk7XG4gIGNvbnN0IG91dHB1dFNoYXBlID0gYXR0cmlidXRlcy5vdXRwdXRTaGFwZS5zbGljZSgpO1xuICBjb25zdCBpbnB1dFNoYXBlID0gaW5wdXRzWzBdLmRpbXM7XG4gIC8vIElmIG91dHB1dFNoYXBlIGlzIG5vdCBzcGVjaWZpZWQgaW4gdGhlIGF0dHJpYnV0ZXMgb2YgdGhpcyBvcCwgaW5mZXIgaXQgZnJvbSB0aGUgcGFyYW1ldGVyc1xuICAvLyBTaW1pbGFybHksIGF1dG9tYXRpY2FsbHkgaW5mZXIgcGFkcyBpZiBub3Qgc3BlY2lmaWVkXG4gIGNhbGN1bGF0ZU91dHB1dFNoYXBlQW5kUGFkcyhcbiAgICAgIGlucHV0U2hhcGUsIGtlcm5lbFNoYXBlLCBhdHRyaWJ1dGVzLmRpbGF0aW9ucywgYXR0cmlidXRlcy5hdXRvUGFkLCBwYWRzLCBhdHRyaWJ1dGVzLnN0cmlkZXMsXG4gICAgICBhdHRyaWJ1dGVzLm91dHB1dFBhZGRpbmcsIG91dHB1dFNoYXBlKTtcblxuICAvLyBhbHdheXMgcmV0dXJuIGEgbmV3IG9iamVjdCBzbyBkb2VzIG5vdCBtb2RpZnkgdGhlIG9yaWdpbmFsIGF0dHJpYnV0ZXNcbiAgY29uc3QgbmV3QXR0cmlidXRlczogVCA9IE9iamVjdC5hc3NpZ24oe30sIGF0dHJpYnV0ZXMpO1xuICBPYmplY3QuYXNzaWduKG5ld0F0dHJpYnV0ZXMsIHtrZXJuZWxTaGFwZSwgcGFkcywgb3V0cHV0U2hhcGUsIGNhY2hlS2V5OiBhdHRyaWJ1dGVzLmNhY2hlS2V5fSk7XG4gIHJldHVybiBuZXdBdHRyaWJ1dGVzO1xufTtcblxuZXhwb3J0IGNvbnN0IHBhcnNlQ29udlRyYW5zcG9zZUF0dHJpYnV0ZXM6IE9wZXJhdG9ySW5pdGlhbGl6YXRpb248Q29udlRyYW5zcG9zZUF0dHJpYnV0ZXM+ID1cbiAgICAobm9kZTogR3JhcGguTm9kZSk6IENvbnZUcmFuc3Bvc2VBdHRyaWJ1dGVzID0+IHtcbiAgICAgIGNvbnN0IGF0dHJpYnV0ZXMgPSBub2RlLmF0dHJpYnV0ZXM7XG4gICAgICBjb25zdCBhY3RpdmF0aW9uQXR0cmlidXRlcyA9IHBhcnNlSW50ZXJuYWxBY3RpdmF0aW9uQXR0cmlidXRlcyhhdHRyaWJ1dGVzKTtcbiAgICAgIC8vIFRPRE8gOiBNYWtlIHRoaXMgZ2VuZXJpYyBlbm91Z2ggdG8gY29tcHV0ZSBkZWZhdWx0IGF0dHJpYnV0ZXMgZm9yIG11bHRpLWRpbWVuc2lvbmFsIGNvbnZcbiAgICAgIGNvbnN0IGF1dG9QYWQgPSBhdHRyaWJ1dGVzLmdldFN0cmluZygnYXV0b19wYWQnLCAnTk9UU0VUJyk7XG4gICAgICBjb25zdCBkaWxhdGlvbnMgPSBhdHRyaWJ1dGVzLmdldEludHMoJ2RpbGF0aW9ucycsIFsxLCAxXSk7XG4gICAgICBjb25zdCBncm91cCA9IGF0dHJpYnV0ZXMuZ2V0SW50KCdncm91cCcsIDEpO1xuICAgICAgY29uc3Qga2VybmVsU2hhcGUgPSBhdHRyaWJ1dGVzLmdldEludHMoJ2tlcm5lbF9zaGFwZScsIFtdKTtcbiAgICAgIGNvbnN0IG91dHB1dFBhZGRpbmcgPSBhdHRyaWJ1dGVzLmdldEludHMoJ291dHB1dF9wYWRkaW5nJywgWzAsIDBdKTtcbiAgICAgIGNvbnN0IG91dHB1dFNoYXBlID0gYXR0cmlidXRlcy5nZXRJbnRzKCdvdXRwdXRfc2hhcGUnLCBbXSk7XG4gICAgICBjb25zdCBwYWRzID0gYXR0cmlidXRlcy5nZXRJbnRzKCdwYWRzJywgWzAsIDAsIDAsIDBdKTtcbiAgICAgIGNvbnN0IHN0cmlkZXMgPSBhdHRyaWJ1dGVzLmdldEludHMoJ3N0cmlkZXMnLCBbMSwgMV0pO1xuXG4gICAgICByZXR1cm4gY3JlYXRlQXR0cmlidXRlV2l0aENhY2hlS2V5KFxuICAgICAgICAgIHthdXRvUGFkLCBkaWxhdGlvbnMsIGdyb3VwLCBrZXJuZWxTaGFwZSwgb3V0cHV0UGFkZGluZywgb3V0cHV0U2hhcGUsIHBhZHMsIHN0cmlkZXMsIC4uLmFjdGl2YXRpb25BdHRyaWJ1dGVzfSk7XG4gICAgfTtcblxuY29uc3QgdmFsaWRhdGVJbnB1dHMgPSAoaW5wdXRzOiBUZW5zb3JbXSwgYXR0cmlidXRlczogQ29udlRyYW5zcG9zZUF0dHJpYnV0ZXMpOiB2b2lkID0+IHtcbiAgLy8gUmVmZXIgdG8gdGhlIGJlbG93IGxpbmsgZm9yIGFsbCBpbnB1dCBjaGVja3NcbiAgLy8gaHR0cHM6Ly9naXRodWIuY29tL29ubngvb25ueC9ibG9iL21haW4vZG9jcy9PcGVyYXRvcnMubWQjQ29udlxuICBpZiAoIWlucHV0cyB8fCAoaW5wdXRzLmxlbmd0aCAhPT0gMiAmJiBpbnB1dHMubGVuZ3RoICE9PSAzKSkge1xuICAgIHRocm93IG5ldyBFcnJvcignQ29udiByZXF1aXJlcyAyIG9yIDMgaW5wdXRzJyk7XG4gIH1cblxuICAvLyBUT0RPIDogTmVlZCB0byBhZGQgc3VwcG9ydCBmb3IgbXVsdGktZGltZW5zaW9uYWwgY29udlxuICBpZiAoaW5wdXRzWzBdLmRpbXMubGVuZ3RoICE9PSA0IHx8IGlucHV0c1sxXS5kaW1zLmxlbmd0aCAhPT0gNCkge1xuICAgIHRocm93IG5ldyBFcnJvcignY3VycmVudGx5IG9ubHkgc3VwcG9ydCAyLWRpbWVuc2lvbmFsIGNvbnYnKTtcbiAgfVxuXG4gIC8vIEZJTFRFUl9JTl9DSEFOTkVMIHNob3VsZCBiZSBlcXVhbCB0byBEQVRBX0NIQU5ORUxcbiAgY29uc3QgZGF0YUNoYW5uZWwgPSBpbnB1dHNbMF0uZGltc1sxXTtcbiAgY29uc3QgZmlsdGVySW5DaGFubmVsID0gaW5wdXRzWzFdLmRpbXNbMF07XG4gIGlmIChkYXRhQ2hhbm5lbCAhPT0gZmlsdGVySW5DaGFubmVsKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdGSUxURVJfSU5fQ0hBTk5FTCBzaG91bGQgYmUgZXF1YWwgdG8gREFUQV9DSEFOTkVMJyk7XG4gIH1cblxuICBjb25zdCBmZWF0dXJlTWFwcyA9IGlucHV0c1sxXS5kaW1zWzFdICogYXR0cmlidXRlcy5ncm91cDtcblxuICAvLyBpZiBiaWFzIGlzIHByb3ZpZGVkIGl0IHNob3VsZCBiZSAxRCBhbmQgdGhlIG51bWJlciBvZiBlbGVtZW50cyBzaG91bGQgYmUgZXF1YWwgdG8gdGhlIG51bWJlciBvZiBmZWF0dXJlIG1hcHNcbiAgaWYgKGlucHV0cy5sZW5ndGggPT09IDMgJiYgKGlucHV0c1syXS5kaW1zLmxlbmd0aCAhPT0gMSB8fCBpbnB1dHNbMl0uZGltc1swXSAhPT0gZmVhdHVyZU1hcHMpKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdpbnZhbGlkIGJpYXMnKTtcbiAgfVxuXG4gIGNvbnN0IHNwYXRpYWxSYW5rID0gaW5wdXRzWzBdLmRpbXMubGVuZ3RoIC0gMjtcbiAgLy8gd3JvbmcgZGlsYXRpb25zIGRpbWVuc2lvblxuICBpZiAoYXR0cmlidXRlcy5kaWxhdGlvbnMubGVuZ3RoICE9PSBzcGF0aWFsUmFuaykge1xuICAgIHRocm93IG5ldyBFcnJvcihgZGlsYXRpb25zIHNob3VsZCBiZSAke3NwYXRpYWxSYW5rfURgKTtcbiAgfVxuXG4gIC8vIFdyb25nIHN0cmlkZXMgZGltZW5zaW9uXG4gIGlmIChhdHRyaWJ1dGVzLnN0cmlkZXMubGVuZ3RoICE9PSBzcGF0aWFsUmFuaykge1xuICAgIHRocm93IG5ldyBFcnJvcihgc3RyaWRlcyBzaG91bGQgYmUgJHtzcGF0aWFsUmFua31EYCk7XG4gIH1cblxuICAvLyBXcm9uZyBwYWRzIGRpbWVuc2lvblxuICBpZiAoYXR0cmlidXRlcy5wYWRzLmxlbmd0aCAhPT0gc3BhdGlhbFJhbmsgKiAyKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGBwYWRzIHNob3VsZCBiZSAke3NwYXRpYWxSYW5rICogMn1EYCk7XG4gIH1cblxuICAvLyBXcm9uZyBvdXRwdXQgcGFkZGluZyBkaW1lbnNpb25cbiAgaWYgKGF0dHJpYnV0ZXMub3V0cHV0UGFkZGluZy5sZW5ndGggIT09IHNwYXRpYWxSYW5rKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGBvdXRwdXRfcGFkZGluZyBzaG91bGQgYmUgJHtzcGF0aWFsUmFua31EYCk7XG4gIH1cblxuICAvLyBpZiBrZXJuZWxTaGFwZSBpcyBzcGVjaWZpZWQsIGl0J3MgZGF0YSBsZW5ndGggbXVzdCBiZSAyIGxlc3MgdGhhbiBkaW1zIGxlbmd0aCBvZiB0aGUgd2VpZ2h0cyB0ZW5zb3JcbiAgLy8gKHRoZSBmaXJzdCAyIGRpbXMgYXJlIGJhdGNoX3NpemUgYW5kIGNoYW5uZWxzKVxuICBpZiAoYXR0cmlidXRlcy5rZXJuZWxTaGFwZS5sZW5ndGggIT09IDAgJiYgYXR0cmlidXRlcy5rZXJuZWxTaGFwZS5sZW5ndGggIT09IGlucHV0c1sxXS5kaW1zLmxlbmd0aCAtIDIpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ2ludmFsaWQga2VybmVsIHNoYXBlJyk7XG4gIH1cblxuICAvLyBhcyB3aXRoIGtlcm5lbFNoYXBlLCBtdXN0IGhhdmUgc2FtZSBudW1iZXIgb2Ygc3BhdGlhbCBkaW1zIGFzIGlucHV0XG4gIGlmIChhdHRyaWJ1dGVzLm91dHB1dFNoYXBlLmxlbmd0aCAhPT0gMCAmJiBhdHRyaWJ1dGVzLm91dHB1dFNoYXBlLmxlbmd0aCAhPT0gaW5wdXRzWzBdLmRpbXMubGVuZ3RoIC0gMikge1xuICAgIHRocm93IG5ldyBFcnJvcignaW52YWxpZCBvdXRwdXQgc2hhcGUnKTtcbiAgfVxuXG4gIC8vIFRPRE8gOiBOZWVkIHRvIGFkZCBzdXBwb3J0IGZvciBmbG9hdDY0XG4gIGlmIChpbnB1dHNbMF0udHlwZSAhPT0gJ2Zsb2F0MzInIHx8IGlucHV0c1sxXS50eXBlICE9PSAnZmxvYXQzMicpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ0NvbnZUcmFuc3Bvc2UgaW5wdXQoWCxXKSBzaG91bGQgYmUgZmxvYXQgdGVuc29yJyk7XG4gIH1cblxuICBpZiAoaW5wdXRzLmxlbmd0aCA9PT0gMyAmJiBpbnB1dHNbMl0udHlwZSAhPT0gJ2Zsb2F0MzInKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdDb252VHJhbnNwb3NlIGlucHV0KGJpYXMpIHNob3VsZCBiZSBmbG9hdCB0ZW5zb3InKTtcbiAgfVxufTtcbiIsIi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxuXG5pbXBvcnQge0F0dHJpYnV0ZVdpdGhDYWNoZUtleSwgY3JlYXRlQXR0cmlidXRlV2l0aENhY2hlS2V5fSBmcm9tICcuLi8uLi8uLi9hdHRyaWJ1dGUtd2l0aC1jYWNoZS1rZXknO1xuaW1wb3J0IHtJbmZlcmVuY2VIYW5kbGVyfSBmcm9tICcuLi8uLi8uLi9iYWNrZW5kJztcbmltcG9ydCB7R3JhcGh9IGZyb20gJy4uLy4uLy4uL2dyYXBoJztcbmltcG9ydCB7T3BlcmF0b3JJbXBsZW1lbnRhdGlvbiwgT3BlcmF0b3JJbml0aWFsaXphdGlvbn0gZnJvbSAnLi4vLi4vLi4vb3BlcmF0b3JzJztcbmltcG9ydCB7VGVuc29yfSBmcm9tICcuLi8uLi8uLi90ZW5zb3InO1xuaW1wb3J0IHtQb29sQ29udlV0aWx9IGZyb20gJy4uLy4uLy4uL3V0aWwnO1xuaW1wb3J0IHtXZWJHTEluZmVyZW5jZUhhbmRsZXJ9IGZyb20gJy4uL2luZmVyZW5jZS1oYW5kbGVyJztcblxuaW1wb3J0IHtjcmVhdGVVbnBhY2tlZEdyb3VwZWRDb252UHJvZ3JhbUluZm9Mb2FkZXJ9IGZyb20gJy4vY29udi1ncm91cGVkJztcbmltcG9ydCB7Y29udjJEUGFja2VkfSBmcm9tICcuL2NvbnYtcGFjayc7XG5pbXBvcnQge2NyZWF0ZURvdFByb2R1Y3RQcm9ncmFtSW5mb0xvYWRlcn0gZnJvbSAnLi9kb3QtcHJvZHVjdCc7XG5pbXBvcnQge0ludGVybmFsQWN0aXZhdGlvbkF0dHJpYnV0ZXMsIHBhcnNlSW50ZXJuYWxBY3RpdmF0aW9uQXR0cmlidXRlc30gZnJvbSAnLi9mdXNlLXV0aWxzJztcbmltcG9ydCB7Y3JlYXRlSW0yQ29sUHJvZ3JhbUluZm9Mb2FkZXJ9IGZyb20gJy4vaW0yY29sJztcbmltcG9ydCB7Y3JlYXRlTWF0bXVsUHJvZ3JhbUluZm9Mb2FkZXJ9IGZyb20gJy4vbWF0bXVsJztcblxuXG5leHBvcnQgY29uc3QgY2FsY3VsYXRlT3V0cHV0U2hhcGUgPVxuICAgIChpbnB1dFNoYXBlOiByZWFkb25seSBudW1iZXJbXSwga2VybmVsU2hhcGU6IHJlYWRvbmx5IG51bWJlcltdLCBkaWxhdGlvbnM6IHJlYWRvbmx5IG51bWJlcltdLFxuICAgICBhZGp1c3RQYWRzOiByZWFkb25seSBudW1iZXJbXSwgc3RyaWRlczogcmVhZG9ubHkgbnVtYmVyW10pOiBudW1iZXJbXSA9PiB7XG4gICAgICBjb25zdCBiYXRjaFNpemUgPSBpbnB1dFNoYXBlWzBdO1xuICAgICAgY29uc3QgaW5wdXRTcGF0aWFsU2hhcGUgPSBpbnB1dFNoYXBlLnNsaWNlKDIpO1xuICAgICAgY29uc3Qgc3BhdGlhbFJhbmsgPSBpbnB1dFNwYXRpYWxTaGFwZS5sZW5ndGg7XG4gICAgICBjb25zdCBvdXRDaGFubmVscyA9IGtlcm5lbFNoYXBlWzBdO1xuICAgICAgY29uc3Qga2VybmVsU3BhdGlhbFNoYXBlID0ga2VybmVsU2hhcGUuc2xpY2UoMik7XG4gICAgICBjb25zdCBkaWxhdGVkS2VybmVsU2hhcGUgPSBrZXJuZWxTcGF0aWFsU2hhcGUubWFwKCh2LCBpKSA9PiB2ICsgKHYgLSAxKSAqIChkaWxhdGlvbnNbaV0gLSAxKSk7XG4gICAgICBjb25zdCBpbnB1dFNwYXRpYWxTaGFwZVdpdGhQYWQgPSBpbnB1dFNwYXRpYWxTaGFwZS5tYXAoKHYsIGkpID0+IHYgKyBhZGp1c3RQYWRzW2ldICsgYWRqdXN0UGFkc1tpICsgc3BhdGlhbFJhbmtdKTtcbiAgICAgIGNvbnN0IG91dHB1dFNwYXRpYWxTaGFwZSA9XG4gICAgICAgICAgaW5wdXRTcGF0aWFsU2hhcGVXaXRoUGFkLm1hcCgodiwgaSkgPT4gTWF0aC5mbG9vcigodiAtIGRpbGF0ZWRLZXJuZWxTaGFwZVtpXSArIHN0cmlkZXNbaV0pIC8gc3RyaWRlc1tpXSkpO1xuICAgICAgY29uc3Qgb3V0cHV0U2hhcGUgPSBbYmF0Y2hTaXplLCBvdXRDaGFubmVsc10uY29uY2F0KC4uLm91dHB1dFNwYXRpYWxTaGFwZSk7XG4gICAgICByZXR1cm4gb3V0cHV0U2hhcGU7XG4gICAgfTtcblxuZXhwb3J0IGludGVyZmFjZSBDb252QXR0cmlidXRlcyBleHRlbmRzIEludGVybmFsQWN0aXZhdGlvbkF0dHJpYnV0ZXMsIEF0dHJpYnV0ZVdpdGhDYWNoZUtleSB7XG4gIHJlYWRvbmx5IGF1dG9QYWQ6IHN0cmluZztcbiAgcmVhZG9ubHkgZGlsYXRpb25zOiByZWFkb25seSBudW1iZXJbXTtcbiAgcmVhZG9ubHkgZ3JvdXA6IG51bWJlcjtcbiAgcmVhZG9ubHkga2VybmVsU2hhcGU6IHJlYWRvbmx5IG51bWJlcltdO1xuICByZWFkb25seSBwYWRzOiByZWFkb25seSBudW1iZXJbXTtcbiAgcmVhZG9ubHkgc3RyaWRlczogcmVhZG9ubHkgbnVtYmVyW107XG59XG5cbmV4cG9ydCBjb25zdCBjb252OiBPcGVyYXRvckltcGxlbWVudGF0aW9uPENvbnZBdHRyaWJ1dGVzPiA9XG4gICAgKGluZmVyZW5jZUhhbmRsZXI6IEluZmVyZW5jZUhhbmRsZXIsIGlucHV0czogVGVuc29yW10sIGF0dHJpYnV0ZXM6IENvbnZBdHRyaWJ1dGVzKTogVGVuc29yW10gPT4ge1xuICAgICAgdmFsaWRhdGVJbnB1dHMoaW5wdXRzLCBhdHRyaWJ1dGVzKTsgIC8vIGN1cnJlbnRseSB3aWxsIGZhaWwgaWYgbm90IGNvbnYyRFxuICAgICAgcmV0dXJuIGNvbnYyZChpbmZlcmVuY2VIYW5kbGVyLCBpbnB1dHMsIGF0dHJpYnV0ZXMpO1xuICAgIH07XG5cbmNvbnN0IGNvbnYyZDogT3BlcmF0b3JJbXBsZW1lbnRhdGlvbjxDb252QXR0cmlidXRlcz4gPVxuICAgIChpbmZlcmVuY2VIYW5kbGVyOiBXZWJHTEluZmVyZW5jZUhhbmRsZXIsIGlucHV0czogVGVuc29yW10sIGF0dHJpYnV0ZXM6IENvbnZBdHRyaWJ1dGVzKTogVGVuc29yW10gPT4ge1xuICAgICAgY29uc3QgYWRqdXN0ZWRBdHRyaWJ1dGVzID0gZ2V0QWRqdXN0ZWRDb252QXR0cmlidXRlcyhhdHRyaWJ1dGVzLCBpbnB1dHMpO1xuICAgICAgY29uc3QgcGFja01vZGUgPSBpbmZlcmVuY2VIYW5kbGVyLnNlc3Npb24ucGFjaztcbiAgICAgIGNvbnN0IGlzUG9pbnR3aXNlID0gYWRqdXN0ZWRBdHRyaWJ1dGVzLmtlcm5lbFNoYXBlWzBdID09PSAxICYmIGFkanVzdGVkQXR0cmlidXRlcy5rZXJuZWxTaGFwZVsxXSA9PT0gMTtcbiAgICAgIGlmIChhZGp1c3RlZEF0dHJpYnV0ZXMuZ3JvdXAgPiAxKSB7XG4gICAgICAgIGNvbnN0IHJlc3VsdCA9IGluZmVyZW5jZUhhbmRsZXIucnVuKFxuICAgICAgICAgICAgY3JlYXRlVW5wYWNrZWRHcm91cGVkQ29udlByb2dyYW1JbmZvTG9hZGVyKGluZmVyZW5jZUhhbmRsZXIsIGlucHV0cywgYWRqdXN0ZWRBdHRyaWJ1dGVzKSwgaW5wdXRzKTtcbiAgICAgICAgcmV0dXJuIFtyZXN1bHRdO1xuICAgICAgfSBlbHNlIGlmIChpc1BvaW50d2lzZSAmJiBwYWNrTW9kZSkge1xuICAgICAgICByZXR1cm4gW2NvbnYyRFVucGFja2VkUG9pbnR3aXNlKGluZmVyZW5jZUhhbmRsZXIsIGlucHV0cywgYWRqdXN0ZWRBdHRyaWJ1dGVzKV07XG4gICAgICB9IGVsc2UgaWYgKHBhY2tNb2RlICYmIGlucHV0c1swXS5kaW1zLmxlbmd0aCA9PT0gNCAmJiBpbnB1dHNbMF0uZGltc1swXSA9PT0gMSAmJiAhaXNQb2ludHdpc2UpIHtcbiAgICAgICAgcmV0dXJuIFtjb252MkRQYWNrZWQoaW5mZXJlbmNlSGFuZGxlciwgaW5wdXRzLCBhZGp1c3RlZEF0dHJpYnV0ZXMpXTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiBbY29udjJEVW5wYWNrZWQoaW5mZXJlbmNlSGFuZGxlciwgaW5wdXRzLCBhZGp1c3RlZEF0dHJpYnV0ZXMpXTtcbiAgICAgIH1cbiAgICB9O1xuXG5jb25zdCBjb252MkRVbnBhY2tlZFBvaW50d2lzZSA9XG4gICAgKGluZmVyZW5jZUhhbmRsZXI6IFdlYkdMSW5mZXJlbmNlSGFuZGxlciwgaW5wdXRzOiByZWFkb25seSBUZW5zb3JbXSwgYXR0cmlidXRlczogQ29udkF0dHJpYnV0ZXMpOiBUZW5zb3IgPT4ge1xuICAgICAgY29uc3QgeHNoYXBlID0gaW5wdXRzWzBdLmRpbXM7XG4gICAgICBjb25zdCBrc2hhcGUgPSBpbnB1dHNbMV0uZGltcztcbiAgICAgIGNvbnN0IG91dHB1dFNoYXBlID1cbiAgICAgICAgICBjYWxjdWxhdGVPdXRwdXRTaGFwZSh4c2hhcGUsIGtzaGFwZSwgYXR0cmlidXRlcy5kaWxhdGlvbnMsIGF0dHJpYnV0ZXMucGFkcywgYXR0cmlidXRlcy5zdHJpZGVzKTtcbiAgICAgIGNvbnN0IHJlc2hhcGVkWCA9IGluZmVyZW5jZUhhbmRsZXIucmVzaGFwZVVucGFja2VkKGlucHV0c1swXSwgW3hzaGFwZVsxXSwgeHNoYXBlWzJdICogeHNoYXBlWzNdXSk7XG4gICAgICBjb25zdCByZXNoYXBlZEsgPSBpbmZlcmVuY2VIYW5kbGVyLnJlc2hhcGVVbnBhY2tlZChpbnB1dHNbMV0sIFtrc2hhcGVbMF0sIGtzaGFwZVsxXV0pO1xuXG4gICAgICBjb25zdCBtYXRtdWxJbnB1dHMgPSBpbnB1dHMubGVuZ3RoID4gMiA/IFtyZXNoYXBlZEssIHJlc2hhcGVkWCwgaW5wdXRzWzJdXSA6IFtyZXNoYXBlZEssIHJlc2hhcGVkWF07XG4gICAgICBjb25zdCBtYXRtdWxPdXRwdXQgPSBpbmZlcmVuY2VIYW5kbGVyLnJ1bihjcmVhdGVNYXRtdWxQcm9ncmFtSW5mb0xvYWRlcihtYXRtdWxJbnB1dHMsIGF0dHJpYnV0ZXMpLCBtYXRtdWxJbnB1dHMpO1xuICAgICAgcmV0dXJuIGluZmVyZW5jZUhhbmRsZXIucmVzaGFwZVVucGFja2VkKG1hdG11bE91dHB1dCwgb3V0cHV0U2hhcGUpO1xuICAgIH07XG5cbmNvbnN0IGNvbnYyRFVucGFja2VkID1cbiAgICAoaW5mZXJlbmNlSGFuZGxlcjogV2ViR0xJbmZlcmVuY2VIYW5kbGVyLCBpbnB1dHM6IHJlYWRvbmx5IFRlbnNvcltdLCBhdHRyaWJ1dGVzOiBDb252QXR0cmlidXRlcyk6IFRlbnNvciA9PiB7XG4gICAgICBjb25zdCB4c2hhcGUgPSBpbnB1dHNbMF0uZGltcztcbiAgICAgIGNvbnN0IGtzaGFwZSA9IGlucHV0c1sxXS5kaW1zO1xuICAgICAgY29uc3Qgb3V0cHV0U2hhcGUgPVxuICAgICAgICAgIGNhbGN1bGF0ZU91dHB1dFNoYXBlKHhzaGFwZSwga3NoYXBlLCBhdHRyaWJ1dGVzLmRpbGF0aW9ucywgYXR0cmlidXRlcy5wYWRzLCBhdHRyaWJ1dGVzLnN0cmlkZXMpO1xuICAgICAgY29uc3QgeEltMkNvbCA9IGluZmVyZW5jZUhhbmRsZXIucnVuKFxuICAgICAgICAgIGNyZWF0ZUltMkNvbFByb2dyYW1JbmZvTG9hZGVyKGluZmVyZW5jZUhhbmRsZXIsIGlucHV0c1swXSwgaW5wdXRzWzFdLCBvdXRwdXRTaGFwZSwgYXR0cmlidXRlcyksIFtpbnB1dHNbMF1dKTtcblxuICAgICAgY29uc3QgZG90UHJvZHVjdElucHV0cyA9IGlucHV0cy5sZW5ndGggPT09IDMgPyBbeEltMkNvbCwgaW5wdXRzWzFdLCBpbnB1dHNbMl1dIDogW3hJbTJDb2wsIGlucHV0c1sxXV07XG4gICAgICBjb25zdCBvdXRwdXQgPSBpbmZlcmVuY2VIYW5kbGVyLnJ1bihcbiAgICAgICAgICBjcmVhdGVEb3RQcm9kdWN0UHJvZ3JhbUluZm9Mb2FkZXIoaW5mZXJlbmNlSGFuZGxlciwgaW5wdXRzLCBvdXRwdXRTaGFwZSwgYXR0cmlidXRlcyksIGRvdFByb2R1Y3RJbnB1dHMpO1xuICAgICAgcmV0dXJuIG91dHB1dDtcbiAgICB9O1xuXG5jb25zdCBnZXRBZGp1c3RlZENvbnZBdHRyaWJ1dGVzID0gPFQgZXh0ZW5kcyBDb252QXR0cmlidXRlcz4oYXR0cmlidXRlczogVCwgaW5wdXRzOiBUZW5zb3JbXSk6IFQgPT4ge1xuICBjb25zdCBrZXJuZWxTaGFwZSA9IGF0dHJpYnV0ZXMua2VybmVsU2hhcGUuc2xpY2UoKTtcbiAgLy8gaWYga2VybmVsU2hhcGUgaXMgbm90IHNwZWNpZmllZCBpbiB0aGUgYXR0cmlidXRlcyBvZiB0aGlzIG9wLCBpbmZlciBpdCBmcm9tIHRoZSB3ZWlnaHQgdGVuc29yIGRpbXNcbiAgaWYgKGF0dHJpYnV0ZXMua2VybmVsU2hhcGUubGVuZ3RoID09PSAwKSB7XG4gICAgZm9yIChsZXQgaSA9IDI7IGkgPCBpbnB1dHNbMV0uZGltcy5sZW5ndGg7ICsraSkge1xuICAgICAga2VybmVsU2hhcGUucHVzaChpbnB1dHNbMV0uZGltc1tpXSk7XG4gICAgfVxuICB9XG4gIGNvbnN0IHBhZHMgPSBhdHRyaWJ1dGVzLnBhZHMuc2xpY2UoKTtcbiAgUG9vbENvbnZVdGlsLmFkanVzdFBhZHNCYXNlZE9uQXV0b1BhZChcbiAgICAgIGlucHV0c1swXS5kaW1zLCBhdHRyaWJ1dGVzLnN0cmlkZXMsIGF0dHJpYnV0ZXMuZGlsYXRpb25zLCBrZXJuZWxTaGFwZSwgcGFkcywgYXR0cmlidXRlcy5hdXRvUGFkKTtcblxuICAvLyBhbHdheXMgcmV0dXJuIGEgbmV3IG9iamVjdCBzbyBkb2VzIG5vdCBtb2RpZnkgdGhlIG9yaWdpbmFsIGF0dHJpYnV0ZXNcbiAgY29uc3QgbmV3QXR0cmlidXRlczogVCA9IE9iamVjdC5hc3NpZ24oe30sIGF0dHJpYnV0ZXMpO1xuICBPYmplY3QuYXNzaWduKG5ld0F0dHJpYnV0ZXMsIHtrZXJuZWxTaGFwZSwgcGFkcywgY2FjaGVLZXk6IGF0dHJpYnV0ZXMuY2FjaGVLZXl9KTtcbiAgcmV0dXJuIG5ld0F0dHJpYnV0ZXM7XG59O1xuXG5leHBvcnQgY29uc3QgcGFyc2VDb252QXR0cmlidXRlczogT3BlcmF0b3JJbml0aWFsaXphdGlvbjxDb252QXR0cmlidXRlcz4gPSAobm9kZTogR3JhcGguTm9kZSk6IENvbnZBdHRyaWJ1dGVzID0+IHtcbiAgY29uc3QgYXR0cmlidXRlcyA9IG5vZGUuYXR0cmlidXRlcztcbiAgY29uc3QgYWN0aXZhdGlvbkF0dHJpYnV0ZXMgPSBwYXJzZUludGVybmFsQWN0aXZhdGlvbkF0dHJpYnV0ZXMoYXR0cmlidXRlcyk7XG4gIC8vIFRPRE8gOiBNYWtlIHRoaXMgZ2VuZXJpYyBlbm91Z2ggdG8gY29tcHV0ZSBkZWZhdWx0IGF0dHJpYnV0ZXMgZm9yIG11bHRpLWRpbWVuc2lvbmFsIGNvbnZcbiAgY29uc3QgYXV0b1BhZCA9IGF0dHJpYnV0ZXMuZ2V0U3RyaW5nKCdhdXRvX3BhZCcsICdOT1RTRVQnKTtcbiAgY29uc3QgZGlsYXRpb25zID0gYXR0cmlidXRlcy5nZXRJbnRzKCdkaWxhdGlvbnMnLCBbMSwgMV0pO1xuICBjb25zdCBncm91cCA9IGF0dHJpYnV0ZXMuZ2V0SW50KCdncm91cCcsIDEpO1xuICBjb25zdCBrZXJuZWxTaGFwZSA9IGF0dHJpYnV0ZXMuZ2V0SW50cygna2VybmVsX3NoYXBlJywgW10pO1xuICBjb25zdCBwYWRzID0gYXR0cmlidXRlcy5nZXRJbnRzKCdwYWRzJywgWzAsIDAsIDAsIDBdKTtcbiAgY29uc3Qgc3RyaWRlcyA9IGF0dHJpYnV0ZXMuZ2V0SW50cygnc3RyaWRlcycsIFsxLCAxXSk7XG5cbiAgcmV0dXJuIGNyZWF0ZUF0dHJpYnV0ZVdpdGhDYWNoZUtleSh7YXV0b1BhZCwgZGlsYXRpb25zLCBncm91cCwga2VybmVsU2hhcGUsIHBhZHMsIHN0cmlkZXMsIC4uLmFjdGl2YXRpb25BdHRyaWJ1dGVzfSk7XG59O1xuXG5jb25zdCB2YWxpZGF0ZUlucHV0cyA9IChpbnB1dHM6IFRlbnNvcltdLCBhdHRyaWJ1dGVzOiBDb252QXR0cmlidXRlcyk6IHZvaWQgPT4ge1xuICAvLyBSZWZlciB0byB0aGUgYmVsb3cgbGluayBmb3IgYWxsIGlucHV0IGNoZWNrc1xuICAvLyBodHRwczovL2dpdGh1Yi5jb20vb25ueC9vbm54L2Jsb2IvbWFpbi9kb2NzL09wZXJhdG9ycy5tZCNDb252XG4gIGlmICghaW5wdXRzIHx8IChpbnB1dHMubGVuZ3RoICE9PSAyICYmIGlucHV0cy5sZW5ndGggIT09IDMpKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdDb252IHJlcXVpcmVzIDIgb3IgMyBpbnB1dHMnKTtcbiAgfVxuXG4gIC8vIFRPRE8gOiBOZWVkIHRvIGFkZCBzdXBwb3J0IGZvciBtdWx0aS1kaW1lbnNpb25hbCBjb252XG4gIGlmIChpbnB1dHNbMF0uZGltcy5sZW5ndGggIT09IDQgfHwgaW5wdXRzWzFdLmRpbXMubGVuZ3RoICE9PSA0KSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdjdXJyZW50bHkgb25seSBzdXBwb3J0IDItZGltZW5zaW9uYWwgY29udicpO1xuICB9XG5cbiAgLy8gRklMVEVSX0lOX0NIQU5ORUwgc2hvdWxkIGJlIGVxdWFsIHRvIERBVEFfQ0hBTk5FTFxuICBjb25zdCBkYXRhQ2hhbm5lbCA9IGlucHV0c1swXS5kaW1zWzFdO1xuICBjb25zdCBmaWx0ZXJJbkNoYW5uZWwgPSBpbnB1dHNbMV0uZGltc1sxXSAqIGF0dHJpYnV0ZXMuZ3JvdXA7XG4gIGlmIChkYXRhQ2hhbm5lbCAhPT0gZmlsdGVySW5DaGFubmVsKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdGSUxURVJfSU5fQ0hBTk5FTCBzaG91bGQgYmUgZXF1YWwgdG8gREFUQV9DSEFOTkVMJyk7XG4gIH1cblxuICAvLyBpZiBiaWFzIGlzIHByb3ZpZGVkIGl0IHNob3VsZCBiZSAxRCBhbmQgdGhlIG51bWJlciBvZiBlbGVtZW50cyBzaG91bGQgYmUgZXF1YWwgdG8gdGhlIG51bWJlciBvZiBmZWF0dXJlIG1hcHNcbiAgaWYgKGlucHV0cy5sZW5ndGggPT09IDMgJiYgKGlucHV0c1syXS5kaW1zLmxlbmd0aCAhPT0gMSB8fCBpbnB1dHNbMV0uZGltc1swXSAhPT0gaW5wdXRzWzJdLmRpbXNbMF0pKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdpbnZhbGlkIGJpYXMnKTtcbiAgfVxuXG4gIGNvbnN0IHNwYXRpYWxSYW5rID0gaW5wdXRzWzBdLmRpbXMubGVuZ3RoIC0gMjtcbiAgLy8gd3JvbmcgZGlsYXRpb25zIGRpbWVuc2lvblxuICBpZiAoYXR0cmlidXRlcy5kaWxhdGlvbnMubGVuZ3RoICE9PSBzcGF0aWFsUmFuaykge1xuICAgIHRocm93IG5ldyBFcnJvcihgZGlsYXRpb25zIHNob3VsZCBiZSAke3NwYXRpYWxSYW5rfURgKTtcbiAgfVxuXG4gIC8vIFdyb25nIHN0cmlkZXMgZGltZW5zaW9uXG4gIGlmIChhdHRyaWJ1dGVzLnN0cmlkZXMubGVuZ3RoICE9PSBzcGF0aWFsUmFuaykge1xuICAgIHRocm93IG5ldyBFcnJvcihgc3RyaWRlcyBzaG91bGQgYmUgJHtzcGF0aWFsUmFua31EYCk7XG4gIH1cblxuICAvLyBXcm9uZyBwYWRzIGRpbWVuc2lvblxuICBpZiAoYXR0cmlidXRlcy5wYWRzLmxlbmd0aCAhPT0gc3BhdGlhbFJhbmsgKiAyKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGBwYWRzIHNob3VsZCBiZSAke3NwYXRpYWxSYW5rICogMn1EYCk7XG4gIH1cblxuICAvLyBpZiBrZXJuZWxTaGFwZSBpcyBzcGVjaWZpZWQsIGl0J3MgZGF0YSBsZW5ndGggbXVzdCBiZSAyIGxlc3MgdGhhbiBkaW1zIGxlbmd0aCBvZiB0aGUgd2VpZ2h0cyB0ZW5zb3JcbiAgLy8gKHRoZSBmaXJzdCAyIGRpbXMgYXJlIGJhdGNoX3NpemUgYW5kIGNoYW5uZWxzKVxuICBpZiAoYXR0cmlidXRlcy5rZXJuZWxTaGFwZS5sZW5ndGggIT09IDAgJiYgYXR0cmlidXRlcy5rZXJuZWxTaGFwZS5sZW5ndGggIT09IGlucHV0c1sxXS5kaW1zLmxlbmd0aCAtIDIpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ2ludmFsaWQga2VybmVsIHNoYXBlJyk7XG4gIH1cblxuICAvLyBUT0RPIDogTmVlZCB0byBhZGQgc3VwcG9ydCBmb3IgZmxvYXQ2NFxuICBpZiAoaW5wdXRzWzBdLnR5cGUgIT09ICdmbG9hdDMyJyB8fCBpbnB1dHNbMV0udHlwZSAhPT0gJ2Zsb2F0MzInKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdDb252IGlucHV0KFgsVykgc2hvdWxkIGJlIGZsb2F0IHRlbnNvcicpO1xuICB9XG5cbiAgaWYgKGlucHV0cy5sZW5ndGggPT09IDMgJiYgaW5wdXRzWzJdLnR5cGUgIT09ICdmbG9hdDMyJykge1xuICAgIHRocm93IG5ldyBFcnJvcignQ29udiBpbnB1dChiaWFzKSBzaG91bGQgYmUgZmxvYXQgdGVuc29yJyk7XG4gIH1cbn07XG4iLCIvLyBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cblxuaW1wb3J0IHtHcmFwaH0gZnJvbSAnLi4vLi4vLi4vZ3JhcGgnO1xuaW1wb3J0IHtPcGVyYXRvckltcGxlbWVudGF0aW9uLCBPcGVyYXRvckluaXRpYWxpemF0aW9ufSBmcm9tICcuLi8uLi8uLi9vcGVyYXRvcnMnO1xuaW1wb3J0IHtUZW5zb3J9IGZyb20gJy4uLy4uLy4uL3RlbnNvcic7XG5pbXBvcnQge1dlYkdMSW5mZXJlbmNlSGFuZGxlcn0gZnJvbSAnLi4vaW5mZXJlbmNlLWhhbmRsZXInO1xuXG5pbXBvcnQge3RyYW5zcG9zZSwgVHJhbnNwb3NlQXR0cmlidXRlc30gZnJvbSAnLi90cmFuc3Bvc2UnO1xuXG5leHBvcnQgaW50ZXJmYWNlIERlcHRoVG9TcGFjZUF0dHJpYnV0ZXMge1xuICBtb2RlOiAnRENSJ3wnQ1JEJztcbiAgYmxvY2tzaXplOiBudW1iZXI7XG59XG5cbmV4cG9ydCBjb25zdCBkZXB0aFRvU3BhY2U6IE9wZXJhdG9ySW1wbGVtZW50YXRpb248RGVwdGhUb1NwYWNlQXR0cmlidXRlcz4gPVxuICAgIChpbmZlcmVuY2VIYW5kbGVyOiBXZWJHTEluZmVyZW5jZUhhbmRsZXIsIGlucHV0czogVGVuc29yW10sIGF0dHJpYnV0ZXM6IERlcHRoVG9TcGFjZUF0dHJpYnV0ZXMpOiBUZW5zb3JbXSA9PiB7XG4gICAgICB2YWxpZGF0ZUlucHV0cyhpbnB1dHMpO1xuICAgICAgY29uc3QgYmxvY2tzaXplID0gYXR0cmlidXRlcy5ibG9ja3NpemU7XG4gICAgICBjb25zdCBibG9ja3NpemVTcXIgPSBibG9ja3NpemUgKiBibG9ja3NpemU7XG4gICAgICBjb25zdCB0cmFuc3Bvc2VQZXJtID0gYXR0cmlidXRlcy5tb2RlID09PSAnRENSJyA/IFswLCAzLCA0LCAxLCA1LCAyXSA6IFswLCAxLCA0LCAyLCA1LCAzXTtcbiAgICAgIGNvbnN0IGZpcnN0UmVzaGFwZVNoYXBlID0gYXR0cmlidXRlcy5tb2RlID09PSAnRENSJyA/XG4gICAgICAgICAgW1xuICAgICAgICAgICAgaW5wdXRzWzBdLmRpbXNbMF0sIGJsb2Nrc2l6ZSwgYmxvY2tzaXplLCBpbnB1dHNbMF0uZGltc1sxXSAvIGJsb2Nrc2l6ZVNxciwgaW5wdXRzWzBdLmRpbXNbMl0sXG4gICAgICAgICAgICBpbnB1dHNbMF0uZGltc1szXVxuICAgICAgICAgIF0gOlxuICAgICAgICAgIFtcbiAgICAgICAgICAgIGlucHV0c1swXS5kaW1zWzBdLCBpbnB1dHNbMF0uZGltc1sxXSAvIGJsb2Nrc2l6ZVNxciwgYmxvY2tzaXplLCBibG9ja3NpemUsIGlucHV0c1swXS5kaW1zWzJdLFxuICAgICAgICAgICAgaW5wdXRzWzBdLmRpbXNbM11cbiAgICAgICAgICBdO1xuXG4gICAgICAvLyBjb25zdCB0cmFuc3Bvc2UgPSBuZXcgV2ViR0xUcmFuc3Bvc2UoKTtcbiAgICAgIC8vIGNvbnN0IGF0dHJpYnV0ZXMgPSBuZXcgQXR0cmlidXRlKHVuZGVmaW5lZCk7XG4gICAgICAvLyBhdHRyaWJ1dGVzLnNldCgncGVybScsICdpbnRzJywgdHJhbnNwb3NlUGVybSk7XG4gICAgICAvLyB0cmFuc3Bvc2UuaW5pdGlhbGl6ZShhdHRyaWJ1dGVzKTtcblxuICAgICAgLy8gRmlyc3QgcmVzaGFwZVxuICAgICAgY29uc3QgZmlyc3RSZXNoYXBlZFRlbnNvciA9IGluZmVyZW5jZUhhbmRsZXIucmVzaGFwZVVucGFja2VkKGlucHV0c1swXSwgZmlyc3RSZXNoYXBlU2hhcGUpO1xuXG4gICAgICAvLyB0cmFuc3Bvc2VcbiAgICAgIGNvbnN0IHRyYW5zcG9zZUF0dHJpYnV0ZXM6IFRyYW5zcG9zZUF0dHJpYnV0ZXMgPSB7cGVybTogdHJhbnNwb3NlUGVybSwgY2FjaGVLZXk6IGAke3RyYW5zcG9zZVBlcm19YH07XG4gICAgICBjb25zdCBbdHJhbnNwb3NlT3V0cHV0XSA9IHRyYW5zcG9zZShpbmZlcmVuY2VIYW5kbGVyLCBbZmlyc3RSZXNoYXBlZFRlbnNvcl0sIHRyYW5zcG9zZUF0dHJpYnV0ZXMpO1xuXG4gICAgICAvLyBTZWNvbmQgcmVzaGFwZVxuICAgICAgY29uc3Qgc2Vjb25kUmVzaGFwZVNoYXBlID0gW1xuICAgICAgICBpbnB1dHNbMF0uZGltc1swXSwgaW5wdXRzWzBdLmRpbXNbMV0gLyBibG9ja3NpemVTcXIsIGlucHV0c1swXS5kaW1zWzJdICogYmxvY2tzaXplLFxuICAgICAgICBpbnB1dHNbMF0uZGltc1szXSAqIGJsb2Nrc2l6ZVxuICAgICAgXTtcbiAgICAgIGNvbnN0IHJlc3VsdCA9IGluZmVyZW5jZUhhbmRsZXIucmVzaGFwZVVucGFja2VkKHRyYW5zcG9zZU91dHB1dCwgc2Vjb25kUmVzaGFwZVNoYXBlKTtcbiAgICAgIHJldHVybiBbcmVzdWx0XTtcbiAgICB9O1xuXG5leHBvcnQgY29uc3QgcGFyc2VEZXB0aFRvU3BhY2VBdHRyaWJ1dGVzOiBPcGVyYXRvckluaXRpYWxpemF0aW9uPERlcHRoVG9TcGFjZUF0dHJpYnV0ZXM+ID1cbiAgICAobm9kZTogR3JhcGguTm9kZSk6IERlcHRoVG9TcGFjZUF0dHJpYnV0ZXMgPT4ge1xuICAgICAgLy8gcHJvY2Vzc2luZyBub2RlIGF0dHJpYnV0ZXNcbiAgICAgIGNvbnN0IGJsb2Nrc2l6ZSA9IG5vZGUuYXR0cmlidXRlcy5nZXRJbnQoJ2Jsb2Nrc2l6ZScpO1xuICAgICAgaWYgKGJsb2Nrc2l6ZSA8IDEpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBibG9ja3NpemUgbXVzdCBiZSA+PSAxLCBidXQgZ290IDogJHtibG9ja3NpemV9IGZvciBEZXB0aFRvU3BhY2VgKTtcbiAgICAgIH1cbiAgICAgIGNvbnN0IG1vZGUgPSBub2RlLmF0dHJpYnV0ZXMuZ2V0U3RyaW5nKCdtb2RlJywgJ0RDUicpO1xuICAgICAgaWYgKG1vZGUgIT09ICdEQ1InICYmIG1vZGUgIT09ICdDUkQnKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgdW5yZWNvZ25pemVkIG1vZGU6ICR7bW9kZX0gZm9yIERlcHRoVG9TcGFjZWApO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHttb2RlLCBibG9ja3NpemV9O1xuICAgIH07XG5cbmNvbnN0IHZhbGlkYXRlSW5wdXRzID0gKGlucHV0czogVGVuc29yW10pOiB2b2lkID0+IHtcbiAgaWYgKGlucHV0cy5sZW5ndGggIT09IDEpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYERlcHRoVG9TcGFjZSBleHBlY3QgMSBpbnB1dHMsIGJ1dCBnb3QgJHtpbnB1dHMubGVuZ3RofWApO1xuICB9XG5cbiAgLy8gSW5wdXQgaGFzIHRvIGJlIGEgNC1EIHRlbnNvclxuICAvLyBUT0RPOiBTdXBwb3J0IHN0cmluZyBkZXB0aC10by1zcGFjZS5cbiAgaWYgKGlucHV0c1swXS50eXBlID09PSAnc3RyaW5nJyB8fCBpbnB1dHNbMF0uZGltcy5sZW5ndGggIT09IDQpIHtcbiAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdEZXB0aFRvU3BhY2UgaW5wdXQgc2hvdWxkIGJlIGEgNC1EIG51bWVyaWMgdGVuc29yJyk7XG4gIH1cbn07XG4iLCIvLyBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cblxuaW1wb3J0IHtUZW5zb3J9IGZyb20gJy4uLy4uLy4uL3RlbnNvcic7XG5pbXBvcnQge1NoYXBlVXRpbH0gZnJvbSAnLi4vLi4vLi4vdXRpbCc7XG5pbXBvcnQge2dldEdsc2x9IGZyb20gJy4uL2dsc2wtc291cmNlJztcbmltcG9ydCB7V2ViR0xJbmZlcmVuY2VIYW5kbGVyfSBmcm9tICcuLi9pbmZlcmVuY2UtaGFuZGxlcic7XG5pbXBvcnQge1Byb2dyYW1JbmZvLCBQcm9ncmFtSW5mb0xvYWRlciwgUHJvZ3JhbU1ldGFkYXRhLCBUZXh0dXJlVHlwZX0gZnJvbSAnLi4vdHlwZXMnO1xuXG5pbXBvcnQge2dldEFjdGl2YXRpb25TbmlwcGV0LCBJbnRlcm5hbEFjdGl2YXRpb25BdHRyaWJ1dGVzfSBmcm9tICcuL2Z1c2UtdXRpbHMnO1xuaW1wb3J0IHtjYWxjdWxhdGVJbTJDb2xEaW1zfSBmcm9tICcuL2ltMmNvbCc7XG5cbmNvbnN0IGNyZWF0ZURvdFByb2R1Y3RQcm9ncmFtTWV0YWRhdGEgPSAoaGFzQmlhczogYm9vbGVhbiwgYXR0cmlidXRlczogSW50ZXJuYWxBY3RpdmF0aW9uQXR0cmlidXRlcykgPT4gKHtcbiAgbmFtZTogJ0NvbnZEb3RQcm9kdWN0JyxcbiAgaW5wdXROYW1lczogaGFzQmlhcyA/IFsnSW0yQ29sJywgJ0snLCAnQiddIDogWydJbTJDb2wnLCAnSyddLFxuICBpbnB1dFR5cGVzOiBoYXNCaWFzID8gW1RleHR1cmVUeXBlLnVucGFja2VkLCBUZXh0dXJlVHlwZS5wYWNrZWRMYXN0RGltZW5zaW9uLCBUZXh0dXJlVHlwZS51bnBhY2tlZF0gOlxuICAgICAgICAgICAgICAgICAgICAgICAgW1RleHR1cmVUeXBlLnVucGFja2VkLCBUZXh0dXJlVHlwZS5wYWNrZWRMYXN0RGltZW5zaW9uXSxcbiAgY2FjaGVLZXk6IGF0dHJpYnV0ZXMuYWN0aXZhdGlvbkNhY2hlS2V5XG59KTtcblxuY29uc3QgY3JlYXRlRG90UHJvZHVjdFByb2dyYW1JbmZvID1cbiAgICAoaW5mZXJlbmNlSGFuZGxlcjogV2ViR0xJbmZlcmVuY2VIYW5kbGVyLCBtZXRhZGF0YTogUHJvZ3JhbU1ldGFkYXRhLCBpbnB1dHM6IHJlYWRvbmx5IFRlbnNvcltdLFxuICAgICBvdXRwdXRTaGFwZTogbnVtYmVyW10sIGF0dHJpYnV0ZXM6IEludGVybmFsQWN0aXZhdGlvbkF0dHJpYnV0ZXMpOiBQcm9ncmFtSW5mbyA9PiB7XG4gICAgICBjb25zdCB4c2hhcGUgPSBpbnB1dHNbMF0uZGltcztcbiAgICAgIGNvbnN0IGtzaGFwZSA9IGlucHV0c1sxXS5kaW1zO1xuICAgICAgY29uc3QgYWRqdXN0ZWRLZXJuZWxTaGFwZSA9IFtrc2hhcGVbMF0sIE1hdGguY2VpbCgoeHNoYXBlWzFdICoga3NoYXBlWzJdICoga3NoYXBlWzNdKSAvIDQpXTtcbiAgICAgIGNvbnN0IGltMmNvbFNoYXBlID0gY2FsY3VsYXRlSW0yQ29sRGltcyh4c2hhcGUsIGtzaGFwZSwgb3V0cHV0U2hhcGUpO1xuICAgICAgY29uc3QgW2tXaWR0aCwga0hlaWdodF0gPVxuICAgICAgICAgIGluZmVyZW5jZUhhbmRsZXIuY2FsY3VsYXRlVGV4dHVyZVdpZHRoQW5kSGVpZ2h0KGFkanVzdGVkS2VybmVsU2hhcGUsIFRleHR1cmVUeXBlLnBhY2tlZExhc3REaW1lbnNpb24pO1xuXG4gICAgICBjb25zdCBpbTJjb2xTdHJpZGVzID0gU2hhcGVVdGlsLmNvbXB1dGVTdHJpZGVzKGltMmNvbFNoYXBlKTtcbiAgICAgIGNvbnN0IFtpbTJjb2xXaWR0aCwgaW0yY29sSGVpZ2h0XSA9XG4gICAgICAgICAgaW5mZXJlbmNlSGFuZGxlci5jYWxjdWxhdGVUZXh0dXJlV2lkdGhBbmRIZWlnaHQoaW0yY29sU2hhcGUsIFRleHR1cmVUeXBlLnBhY2tlZExhc3REaW1lbnNpb24pO1xuICAgICAgY29uc3QgcmFuayA9IG91dHB1dFNoYXBlLmxlbmd0aDtcblxuICAgICAgY29uc3QgaW5pdFZhbHVlID0gKGlucHV0cy5sZW5ndGggPCAzKSA/ICcwLjAnIDogJ19CKGIpJztcbiAgICAgIGNvbnN0IHNoYXJlZERpbSA9IE1hdGguY2VpbCh4c2hhcGVbMV0gKiBrc2hhcGVbMl0gKiBrc2hhcGVbM10gLyA0KTtcbiAgICAgIGNvbnN0IHthY3RpdmF0aW9uRnVuY3Rpb24sIGFwcGx5QWN0aXZhdGlvbn0gPSBnZXRBY3RpdmF0aW9uU25pcHBldChhdHRyaWJ1dGVzKTtcbiAgICAgIGNvbnN0IGdsc2wgPSBnZXRHbHNsKGluZmVyZW5jZUhhbmRsZXIuc2Vzc2lvbi5iYWNrZW5kLmdsQ29udGV4dC52ZXJzaW9uKTtcbiAgICAgIGNvbnN0IHNoYWRlclNvdXJjZSA9IGBcbiR7YWN0aXZhdGlvbkZ1bmN0aW9ufVxuZmxvYXQgcHJvY2VzcyhpbnQgaW5kaWNlc1ske3Jhbmt9XSkge1xuICBpbnQgYlsxXTtcbiAgYlswXSA9IGluZGljZXNbMV07XG4gIGludCBpbTJjb2xbNF07XG4gIGltMmNvbFswXSA9IGluZGljZXNbMF07XG4gIGltMmNvbFsxXSA9IGluZGljZXNbMl07XG4gIGltMmNvbFsyXSA9IGluZGljZXNbM107XG4gIGludCBpbTJjb2xPZmZzZXQgPSBpbTJjb2xbMF0gKiAke2ltMmNvbFN0cmlkZXNbMF19ICsgaW0yY29sWzFdICogJHtpbTJjb2xTdHJpZGVzWzFdfSArIGltMmNvbFsyXSAqICR7XG4gICAgICAgICAgaW0yY29sU3RyaWRlc1syXX07XG4gIGludCBrZXJuZWxPZmZzZXQgPSBpbmRpY2VzWzFdICogJHthZGp1c3RlZEtlcm5lbFNoYXBlWzFdfTtcbiAgZmxvYXQgdmFsdWUgPSAke2luaXRWYWx1ZX07XG4gIGZvciAoaW50IGkgPSAwOyBpIDwgJHtzaGFyZWREaW19OyArK2kpIHtcbiAgICB2ZWMyIGltMmNvbENvb3JkcyA9IG9mZnNldFRvQ29vcmRzKGltMmNvbE9mZnNldCwgJHtpbTJjb2xXaWR0aH0sICR7aW0yY29sSGVpZ2h0fSk7XG4gICAgdmVjMiBrZXJuZWxDb29yZHMgPSBvZmZzZXRUb0Nvb3JkcyhrZXJuZWxPZmZzZXQsICR7a1dpZHRofSwgJHtrSGVpZ2h0fSk7XG4gICAgdmFsdWUgKz0gZG90KCR7Z2xzbC50ZXh0dXJlMkR9KEltMkNvbCwgaW0yY29sQ29vcmRzKSwgJHtnbHNsLnRleHR1cmUyRH0oSywga2VybmVsQ29vcmRzKSk7XG4gICAgKytpbTJjb2xPZmZzZXQ7XG4gICAgKytrZXJuZWxPZmZzZXQ7XG4gIH1cbiAgJHthcHBseUFjdGl2YXRpb259XG4gIHJldHVybiB2YWx1ZTtcbn1gO1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgLi4ubWV0YWRhdGEsXG4gICAgICAgIG91dHB1dDoge2RpbXM6IG91dHB1dFNoYXBlLCB0eXBlOiBpbnB1dHNbMF0udHlwZSwgdGV4dHVyZVR5cGU6IFRleHR1cmVUeXBlLnVucGFja2VkfSxcbiAgICAgICAgc2hhZGVyU291cmNlXG4gICAgICB9O1xuICAgIH07XG5cbmV4cG9ydCBjb25zdCBjcmVhdGVEb3RQcm9kdWN0UHJvZ3JhbUluZm9Mb2FkZXIgPVxuICAgIChpbmZlcmVuY2VIYW5kbGVyOiBXZWJHTEluZmVyZW5jZUhhbmRsZXIsIGlucHV0czogcmVhZG9ubHkgVGVuc29yW10sIG91dHB1dFNoYXBlOiBudW1iZXJbXSxcbiAgICAgYXR0cmlidXRlczogSW50ZXJuYWxBY3RpdmF0aW9uQXR0cmlidXRlcyk6IFByb2dyYW1JbmZvTG9hZGVyID0+IHtcbiAgICAgIGNvbnN0IG1ldGFkYXRhID0gY3JlYXRlRG90UHJvZHVjdFByb2dyYW1NZXRhZGF0YShpbnB1dHMubGVuZ3RoID4gMiwgYXR0cmlidXRlcyk7XG4gICAgICByZXR1cm4ge1xuICAgICAgICAuLi5tZXRhZGF0YSxcbiAgICAgICAgZ2V0OiAoKSA9PiBjcmVhdGVEb3RQcm9kdWN0UHJvZ3JhbUluZm8oaW5mZXJlbmNlSGFuZGxlciwgbWV0YWRhdGEsIGlucHV0cywgb3V0cHV0U2hhcGUsIGF0dHJpYnV0ZXMpXG4gICAgICB9O1xuICAgIH07XG4iLCIvLyBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cblxuaW1wb3J0IHtHcmFwaH0gZnJvbSAnLi4vLi4vLi4vZ3JhcGgnO1xuaW1wb3J0IHtPcGVyYXRvckltcGxlbWVudGF0aW9uLCBPcGVyYXRvckluaXRpYWxpemF0aW9ufSBmcm9tICcuLi8uLi8uLi9vcGVyYXRvcnMnO1xuaW1wb3J0IHtUZW5zb3J9IGZyb20gJy4uLy4uLy4uL3RlbnNvcic7XG5pbXBvcnQge1NoYXBlVXRpbH0gZnJvbSAnLi4vLi4vLi4vdXRpbCc7XG5pbXBvcnQge1dlYkdMSW5mZXJlbmNlSGFuZGxlcn0gZnJvbSAnLi4vaW5mZXJlbmNlLWhhbmRsZXInO1xuXG5leHBvcnQgY29uc3QgZmxhdHRlbjogT3BlcmF0b3JJbXBsZW1lbnRhdGlvbjxudW1iZXI+ID1cbiAgICAoaW5mZXJlbmNlSGFuZGxlcjogV2ViR0xJbmZlcmVuY2VIYW5kbGVyLCBpbnB1dHM6IFRlbnNvcltdLCBheGlzOiBudW1iZXIpOiBUZW5zb3JbXSA9PiB7XG4gICAgICB2YWxpZGF0ZUlucHV0cyhpbnB1dHMsIGF4aXMpO1xuXG4gICAgICBjb25zdCBvdXRwdXREaW1zID0gU2hhcGVVdGlsLmZsYXR0ZW5TaGFwZShpbnB1dHNbMF0uZGltcywgYXhpcyk7XG4gICAgICByZXR1cm4gW2luZmVyZW5jZUhhbmRsZXIucmVzaGFwZVVucGFja2VkKGlucHV0c1swXSwgb3V0cHV0RGltcyldO1xuICAgIH07XG5cbmV4cG9ydCBjb25zdCBwYXJzZUZsYXR0ZW5BdHRyaWJ1dGVzOiBPcGVyYXRvckluaXRpYWxpemF0aW9uPG51bWJlcj4gPSAobm9kZTogR3JhcGguTm9kZSk6IG51bWJlciA9PlxuICAgIG5vZGUuYXR0cmlidXRlcy5nZXRJbnQoJ2F4aXMnLCAxKTsgIC8vIGRlZmF1bHQgYXhpcyBpcyAxXG5cbmNvbnN0IHZhbGlkYXRlSW5wdXRzID0gKGlucHV0czogVGVuc29yW10sIGF4aXM6IG51bWJlcik6IHZvaWQgPT4ge1xuICBpZiAoIWlucHV0cyB8fCBpbnB1dHMubGVuZ3RoICE9PSAxKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdGbGF0dGVuIHJlcXVpcmVzIDEgaW5wdXQuJyk7XG4gIH1cblxuICBjb25zdCByID0gaW5wdXRzWzBdLmRpbXMubGVuZ3RoO1xuICBpZiAociA9PT0gMCkge1xuICAgIHRocm93IG5ldyBFcnJvcignc2NhbGFyIHRlbnNvciBpcyBub3Qgc3VwcG9ydGVkLicpO1xuICB9XG5cbiAgaWYgKGF4aXMgPCAtciB8fCBheGlzID4gcikge1xuICAgIHRocm93IG5ldyBFcnJvcignSW52YWxpZCBheGlzJyk7XG4gIH1cblxuICAvLyBUT0RPOiBTdXBwb3J0IHN0cmluZyB0eXBlXG4gIGlmIChpbnB1dHNbMF0udHlwZSA9PT0gJ3N0cmluZycpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ3N0cmluZyB0ZW5zb3IgaXMgbm90IHN1cHBvcnRlZC4nKTtcbiAgfVxufTsiLCIvLyBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cblxuaW1wb3J0IHtBdHRyaWJ1dGV9IGZyb20gJy4uLy4uLy4uL2F0dHJpYnV0ZSc7XG5pbXBvcnQge01BWF9DTElQLCBNSU5fQ0xJUH0gZnJvbSAnLi4vLi4vLi4vdXRpbCc7XG5pbXBvcnQge0dsc2xWYWx1ZUZ1bmN0aW9ufSBmcm9tICcuLi9nbHNsLWRlZmluaXRpb25zJztcblxuaW1wb3J0IHtnbHNsQ2xpcCwgZ2xzbFJlbHUsIGdsc2xTaWdtb2lkfSBmcm9tICcuL3VuYXJ5LW9wJztcblxuZXhwb3J0IGludGVyZmFjZSBJbnRlcm5hbEFjdGl2YXRpb25BdHRyaWJ1dGVzIHtcbiAgcmVhZG9ubHkgYWN0aXZhdGlvbjogc3RyaW5nO1xuICByZWFkb25seSBjbGlwTWluPzogbnVtYmVyO1xuICByZWFkb25seSBjbGlwTWF4PzogbnVtYmVyO1xuICByZWFkb25seSBhY3RpdmF0aW9uQ2FjaGVLZXk6IHN0cmluZztcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGdldEFjdGl2YXRpb25TbmlwcGV0KGF0dHJpYnV0ZXM6IEludGVybmFsQWN0aXZhdGlvbkF0dHJpYnV0ZXMpIHtcbiAgbGV0IGZ1bmM6IEdsc2xWYWx1ZUZ1bmN0aW9uO1xuICBzd2l0Y2ggKGF0dHJpYnV0ZXMuYWN0aXZhdGlvbikge1xuICAgIGNhc2UgJ1JlbHUnOlxuICAgICAgZnVuYyA9IGdsc2xSZWx1KCk7XG4gICAgICBicmVhaztcbiAgICBjYXNlICdTaWdtb2lkJzpcbiAgICAgIGZ1bmMgPSBnbHNsU2lnbW9pZCgpO1xuICAgICAgYnJlYWs7XG4gICAgY2FzZSAnQ2xpcCc6XG4gICAgICBmdW5jID0gZ2xzbENsaXAoYXR0cmlidXRlcy5jbGlwTWluISwgYXR0cmlidXRlcy5jbGlwTWF4ISk7XG4gICAgICBicmVhaztcbiAgICAvLyBUT0RPOiBhZGRpbmcgb3RoZXIgYWN0aXZhdGlvbnMgdGhhdCBjYW4gYmUgZnVzZWQuXG4gICAgZGVmYXVsdDpcbiAgICAgIHJldHVybiB7YWN0aXZhdGlvbkZ1bmN0aW9uOiAnJywgYXBwbHlBY3RpdmF0aW9uOiAnJ307XG4gIH1cblxuICBjb25zdCBhY3RpdmF0aW9uTmFtZSA9IGZ1bmMubmFtZTtcbiAgY29uc3QgYWN0aXZhdGlvbkZ1bmN0aW9uID0gZnVuYy5ib2R5O1xuICBjb25zdCBhcHBseUFjdGl2YXRpb24gPSBgdmFsdWUgPSAke2FjdGl2YXRpb25OYW1lfV8odmFsdWUpO2A7XG4gIHJldHVybiB7YWN0aXZhdGlvbkZ1bmN0aW9uLCBhcHBseUFjdGl2YXRpb259O1xufVxuXG5leHBvcnQgY29uc3QgcGFyc2VJbnRlcm5hbEFjdGl2YXRpb25BdHRyaWJ1dGVzID0gKGF0dHJpYnV0ZXM6IEF0dHJpYnV0ZSk6IEludGVybmFsQWN0aXZhdGlvbkF0dHJpYnV0ZXMgPT4ge1xuICBjb25zdCBhY3RpdmF0aW9uID0gYXR0cmlidXRlcy5nZXRTdHJpbmcoJ2FjdGl2YXRpb24nLCAnJyk7XG5cbiAgaWYgKGFjdGl2YXRpb24gPT09ICdDbGlwJykge1xuICAgIGNvbnN0IFtjbGlwTWluLCBjbGlwTWF4XSA9IGF0dHJpYnV0ZXMuZ2V0RmxvYXRzKCdhY3RpdmF0aW9uX3BhcmFtcycsIFtNSU5fQ0xJUCwgTUFYX0NMSVBdKTtcbiAgICByZXR1cm4ge2FjdGl2YXRpb24sIGNsaXBNYXgsIGNsaXBNaW4sIGFjdGl2YXRpb25DYWNoZUtleTogYCR7YWN0aXZhdGlvbn06JHtjbGlwTWlufSwke2NsaXBNYXh9YH07XG4gIH1cbiAgcmV0dXJuIHthY3RpdmF0aW9uLCBhY3RpdmF0aW9uQ2FjaGVLZXk6IGFjdGl2YXRpb259O1xufTtcbiIsIi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxuXG5pbXBvcnQge0F0dHJpYnV0ZVdpdGhDYWNoZUtleSwgY3JlYXRlQXR0cmlidXRlV2l0aENhY2hlS2V5fSBmcm9tICcuLi8uLi8uLi9hdHRyaWJ1dGUtd2l0aC1jYWNoZS1rZXknO1xuaW1wb3J0IHtHcmFwaH0gZnJvbSAnLi4vLi4vLi4vZ3JhcGgnO1xuaW1wb3J0IHtOVU1CRVJfVFlQRVMsIE9wZXJhdG9ySW1wbGVtZW50YXRpb24sIE9wZXJhdG9ySW5pdGlhbGl6YXRpb259IGZyb20gJy4uLy4uLy4uL29wZXJhdG9ycyc7XG5pbXBvcnQge1RlbnNvcn0gZnJvbSAnLi4vLi4vLi4vdGVuc29yJztcbmltcG9ydCB7U2hhcGVVdGlsfSBmcm9tICcuLi8uLi8uLi91dGlsJztcbmltcG9ydCB7V2ViR0xJbmZlcmVuY2VIYW5kbGVyfSBmcm9tICcuLi9pbmZlcmVuY2UtaGFuZGxlcic7XG5pbXBvcnQge1Byb2dyYW1JbmZvLCBQcm9ncmFtSW5mb0xvYWRlciwgUHJvZ3JhbU1ldGFkYXRhLCBUZXh0dXJlVHlwZX0gZnJvbSAnLi4vdHlwZXMnO1xuXG5pbnRlcmZhY2UgR2F0aGVyQXR0cmlidXRlcyBleHRlbmRzIEF0dHJpYnV0ZVdpdGhDYWNoZUtleSB7XG4gIHJlYWRvbmx5IGF4aXM6IG51bWJlcjtcbn1cblxuZXhwb3J0IGNvbnN0IGdhdGhlcjogT3BlcmF0b3JJbXBsZW1lbnRhdGlvbjxHYXRoZXJBdHRyaWJ1dGVzPiA9XG4gICAgKGluZmVyZW5jZUhhbmRsZXI6IFdlYkdMSW5mZXJlbmNlSGFuZGxlciwgaW5wdXRzOiBUZW5zb3JbXSwgYXR0cmlidXRlczogR2F0aGVyQXR0cmlidXRlcyk6IFRlbnNvcltdID0+IHtcbiAgICAgIHZhbGlkYXRlSW5wdXRzKGlucHV0cywgYXR0cmlidXRlcy5heGlzKTtcbiAgICAgIGNvbnN0IG91dHB1dCA9IGluZmVyZW5jZUhhbmRsZXIucnVuKGNyZWF0ZUdhdGhlclByb2dyYW1JbmZvTG9hZGVyKGluZmVyZW5jZUhhbmRsZXIsIGlucHV0cywgYXR0cmlidXRlcyksIGlucHV0cyk7XG4gICAgICByZXR1cm4gW291dHB1dF07XG4gICAgfTtcblxuZXhwb3J0IGNvbnN0IHBhcnNlR2F0aGVyQXR0cmlidXRlczogT3BlcmF0b3JJbml0aWFsaXphdGlvbjxHYXRoZXJBdHRyaWJ1dGVzPiA9IChub2RlOiBHcmFwaC5Ob2RlKTogR2F0aGVyQXR0cmlidXRlcyA9PlxuICAgIGNyZWF0ZUF0dHJpYnV0ZVdpdGhDYWNoZUtleSh7YXhpczogbm9kZS5hdHRyaWJ1dGVzLmdldEludCgnYXhpcycsIDApfSk7XG5cbmNvbnN0IGdhdGhlclByb2dyYW1NZXRhZGF0YSA9IHtcbiAgbmFtZTogJ0dhdGhlcicsXG4gIGlucHV0TmFtZXM6IFsnQScsICdCJ10sXG4gIGlucHV0VHlwZXM6IFtUZXh0dXJlVHlwZS51bnBhY2tlZCwgVGV4dHVyZVR5cGUudW5wYWNrZWRdLFxufTtcblxuY29uc3QgY3JlYXRlR2F0aGVyUHJvZ3JhbUluZm8gPVxuICAgIChoYW5kbGVyOiBXZWJHTEluZmVyZW5jZUhhbmRsZXIsIG1ldGFkYXRhOiBQcm9ncmFtTWV0YWRhdGEsIGlucHV0czogVGVuc29yW10sIGF4aXM6IG51bWJlcik6IFByb2dyYW1JbmZvID0+IHtcbiAgICAgIGNvbnN0IGlucHV0U2hhcGUgPSBpbnB1dHNbMF0uZGltcy5zbGljZSgpO1xuICAgICAgY29uc3QgaW5kZXhEYXRhU2hhcGUgPSBpbnB1dHNbMV0uZGltcy5zbGljZSgpO1xuICAgICAgY29uc3Qgb3V0cHV0U2hhcGUgPSBuZXcgQXJyYXkoaW5wdXRTaGFwZS5sZW5ndGggKyBpbmRleERhdGFTaGFwZS5sZW5ndGggLSAxKTtcblxuICAgICAgYXhpcyA9IFNoYXBlVXRpbC5ub3JtYWxpemVBeGlzKGF4aXMsIGlucHV0U2hhcGUubGVuZ3RoKTtcbiAgICAgIGNvbnN0IGluZGV4Q29weU9wczogc3RyaW5nW10gPSBbXTtcbiAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgb3V0cHV0U2hhcGUubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgLy8gb3V0cHV0U2hhcGUgaXMgZGl2aWRlZCBpbnRvIHRocmVlIHBhcnRzOiBBLCBCLCBDXG4gICAgICAgIC8vIHwwICAgICAgICBheGlzfCAgYXhpcyArIGluZGV4RGF0YVNoYXBlLmxlbmd0aCB8ICAgICAgICAgIGVuZHxcbiAgICAgICAgLy8gfCAgICAgQSAgICAgICB8ICAgICAgICAgICAgIEIgICAgICAgICAgICAgICAgIHwgICAgICBDICAgICAgfFxuICAgICAgICAvL1xuICAgICAgICAvLyBpbnB1dElkeDogW0EsIGlucHV0c1sxXVtCXSwgQ11cbiAgICAgICAgaWYgKGkgPCBheGlzKSB7ICAvLyBBXG4gICAgICAgICAgb3V0cHV0U2hhcGVbaV0gPSBpbnB1dFNoYXBlW2ldO1xuICAgICAgICAgIGluZGV4Q29weU9wcy5wdXNoKGBpbnB1dElkeFske2l9XSA9IG91dHB1dElkeFske2l9XTtgKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBpZiAoaSA8IGF4aXMgKyBpbmRleERhdGFTaGFwZS5sZW5ndGgpIHsgIC8vIEJcbiAgICAgICAgICAgIG91dHB1dFNoYXBlW2ldID0gaW5kZXhEYXRhU2hhcGVbaSAtIGF4aXNdO1xuICAgICAgICAgICAgaW5kZXhDb3B5T3BzLnB1c2goYGluZGV4RGF0YUlkeFske2kgLSBheGlzfV0gPSBvdXRwdXRJZHhbJHtpfV07YCk7XG4gICAgICAgICAgfSBlbHNlIHsgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gQ1xuICAgICAgICAgICAgb3V0cHV0U2hhcGVbaV0gPSBpbnB1dFNoYXBlW2kgLSBpbmRleERhdGFTaGFwZS5sZW5ndGggKyAxXTsgIC8vIHNraXAgMSBmb3IgYXhpc1xuICAgICAgICAgICAgaW5kZXhDb3B5T3BzLnB1c2goYGlucHV0SWR4WyR7aSAtIGluZGV4RGF0YVNoYXBlLmxlbmd0aCArIDF9XSA9IG91dHB1dElkeFske2l9XTtgKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgY29uc3Qgb3JhbmsgPSBvdXRwdXRTaGFwZS5sZW5ndGggfHwgMTtcbiAgICAgIGNvbnN0IGlyYW5rID0gaW5wdXRTaGFwZS5sZW5ndGg7XG4gICAgICBjb25zdCBpRHJhbmsgPSBpbmRleERhdGFTaGFwZS5sZW5ndGggfHwgMTtcbiAgICAgIGNvbnN0IHNoYWRlclNvdXJjZSA9IGBcbiAgICAgIGZsb2F0IHByb2Nlc3MoaW50IG91dHB1dElkeFske29yYW5rfV0pIHtcbiAgICAgICAgaW50IGlucHV0SWR4WyR7aXJhbmt9XTtcbiAgICAgICAgaW50IGluZGV4RGF0YUlkeFske2lEcmFua31dO1xuICAgICAgICBpbmRleERhdGFJZHhbMF0gPSAwO1xuICAgICAgICAke2luZGV4Q29weU9wcy5qb2luKCdcXG4gICAgICAgICcpfVxuICAgICAgICBpbnQgaWR4ID0gaW50KF9CKGluZGV4RGF0YUlkeCkpO1xuICAgICAgICBpbnB1dElkeFske2F4aXN9XSA9IGlkeCA8IDAgPyBpZHggKyAke2lucHV0U2hhcGVbYXhpc119IDogaWR4O1xuICAgICAgICByZXR1cm4gX0EoaW5wdXRJZHgpO1xuICAgICAgfWA7XG4gICAgICByZXR1cm4ge1xuICAgICAgICAuLi5tZXRhZGF0YSxcbiAgICAgICAgb3V0cHV0OiB7ZGltczogb3V0cHV0U2hhcGUsIHR5cGU6IGlucHV0c1swXS50eXBlLCB0ZXh0dXJlVHlwZTogVGV4dHVyZVR5cGUudW5wYWNrZWR9LFxuICAgICAgICBzaGFkZXJTb3VyY2VcbiAgICAgIH07XG4gICAgfTtcblxuY29uc3QgY3JlYXRlR2F0aGVyUHJvZ3JhbUluZm9Mb2FkZXIgPVxuICAgIChoYW5kbGVyOiBXZWJHTEluZmVyZW5jZUhhbmRsZXIsIGlucHV0czogVGVuc29yW10sIGF0dHJpYnV0ZXM6IEdhdGhlckF0dHJpYnV0ZXMpOiBQcm9ncmFtSW5mb0xvYWRlciA9PiB7XG4gICAgICBjb25zdCBtZXRhZGF0YSA9IHsuLi5nYXRoZXJQcm9ncmFtTWV0YWRhdGEsIGNhY2hlSGludDogYXR0cmlidXRlcy5jYWNoZUtleX07XG4gICAgICByZXR1cm4gey4uLm1ldGFkYXRhLCBnZXQ6ICgpID0+IGNyZWF0ZUdhdGhlclByb2dyYW1JbmZvKGhhbmRsZXIsIG1ldGFkYXRhLCBpbnB1dHMsIGF0dHJpYnV0ZXMuYXhpcyl9O1xuICAgIH07XG5cbmNvbnN0IHZhbGlkYXRlSW5wdXRzID0gKGlucHV0czogVGVuc29yW10sIGF4aXM6IG51bWJlcik6IHZvaWQgPT4ge1xuICBpZiAoIWlucHV0cyB8fCBpbnB1dHMubGVuZ3RoICE9PSAyKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdHYXRoZXIgcmVxdWlyZXMgMiBpbnB1dHMuJyk7XG4gIH1cbiAgY29uc3QgdGVuc29yUmFuayA9IGlucHV0c1swXS5kaW1zLmxlbmd0aDtcbiAgaWYgKHRlbnNvclJhbmsgPCAxKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIGlucHV0IHNoYXBlLicpO1xuICB9XG4gIGlmIChheGlzIDwgLXRlbnNvclJhbmsgfHwgYXhpcyA+IHRlbnNvclJhbmsgLSAxKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIGF4aXMuJyk7XG4gIH1cbiAgaWYgKE5VTUJFUl9UWVBFUy5pbmRleE9mKGlucHV0c1swXS50eXBlKSA9PT0gLTEpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ0ludmFpZCBpbnB1dCB0eXBlLicpO1xuICB9XG4gIGlmIChpbnB1dHNbMV0udHlwZSAhPT0gJ2ludDMyJyAmJiBpbnB1dHNbMV0udHlwZSAhPT0gJ2ludDE2Jykge1xuICAgIHRocm93IG5ldyBFcnJvcignSW52YWlkIGlucHV0IHR5cGUuJyk7XG4gIH1cbn07XG4iLCIvLyBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cblxuaW1wb3J0IHtBdHRyaWJ1dGVXaXRoQ2FjaGVLZXksIGNyZWF0ZUF0dHJpYnV0ZVdpdGhDYWNoZUtleX0gZnJvbSAnLi4vLi4vLi4vYXR0cmlidXRlLXdpdGgtY2FjaGUta2V5JztcbmltcG9ydCB7R3JhcGh9IGZyb20gJy4uLy4uLy4uL2dyYXBoJztcbmltcG9ydCB7T3BlcmF0b3JJbXBsZW1lbnRhdGlvbiwgT3BlcmF0b3JJbml0aWFsaXphdGlvbn0gZnJvbSAnLi4vLi4vLi4vb3BlcmF0b3JzJztcbmltcG9ydCB7VGVuc29yfSBmcm9tICcuLi8uLi8uLi90ZW5zb3InO1xuaW1wb3J0IHtHZW1tVXRpbH0gZnJvbSAnLi4vLi4vLi4vdXRpbCc7XG5pbXBvcnQge1dlYkdMSW5mZXJlbmNlSGFuZGxlcn0gZnJvbSAnLi4vaW5mZXJlbmNlLWhhbmRsZXInO1xuaW1wb3J0IHtQcm9ncmFtSW5mbywgUHJvZ3JhbUluZm9Mb2FkZXIsIFByb2dyYW1NZXRhZGF0YSwgVGV4dHVyZVR5cGV9IGZyb20gJy4uL3R5cGVzJztcblxuZXhwb3J0IGludGVyZmFjZSBHZW1tQXR0cmlidXRlcyBleHRlbmRzIEF0dHJpYnV0ZVdpdGhDYWNoZUtleSB7XG4gIHRyYW5zQTogYm9vbGVhbjtcbiAgdHJhbnNCOiBib29sZWFuO1xuICBhbHBoYTogbnVtYmVyO1xuICBiZXRhOiBudW1iZXI7XG4gIGlzT3B0aW9uYWxDOiBib29sZWFuOyAgLy8gaW4gb3BzZXQgMTEsIEMgYmVjb21lcyBvcHRpb25hbFxufVxuXG5leHBvcnQgY29uc3QgZ2VtbTogT3BlcmF0b3JJbXBsZW1lbnRhdGlvbjxHZW1tQXR0cmlidXRlcz4gPVxuICAgIChpbmZlcmVuY2VIYW5kbGVyOiBXZWJHTEluZmVyZW5jZUhhbmRsZXIsIGlucHV0czogVGVuc29yW10sIGF0dHJpYnV0ZXM6IEdlbW1BdHRyaWJ1dGVzKTogVGVuc29yW10gPT4ge1xuICAgICAgdmFsaWRhdGVJbnB1dHMoaW5wdXRzLCBhdHRyaWJ1dGVzKTtcbiAgICAgIGNvbnN0IG91dHB1dCA9IGluZmVyZW5jZUhhbmRsZXIucnVuKGNyZWF0ZUdlbW1Qcm9ncmFtSW5mb0xvYWRlcihpbnB1dHMsIGF0dHJpYnV0ZXMpLCBpbnB1dHMpO1xuICAgICAgcmV0dXJuIFtvdXRwdXRdO1xuICAgIH07XG5cbmNvbnN0IHBhcnNlR2VtbUF0dHJpYnV0ZXMgPSAobm9kZTogR3JhcGguTm9kZSwgaXNPcHRpb25hbEM6IGJvb2xlYW4pOiBHZW1tQXR0cmlidXRlcyA9PiB7XG4gIGNvbnN0IHRyYW5zQSA9IG5vZGUuYXR0cmlidXRlcy5nZXRJbnQoJ3RyYW5zQScsIDApICE9PSAwO1xuICBjb25zdCB0cmFuc0IgPSBub2RlLmF0dHJpYnV0ZXMuZ2V0SW50KCd0cmFuc0InLCAwKSAhPT0gMDtcbiAgY29uc3QgYWxwaGEgPSBub2RlLmF0dHJpYnV0ZXMuZ2V0RmxvYXQoJ2FscGhhJywgMS4wKTtcbiAgY29uc3QgYmV0YSA9IG5vZGUuYXR0cmlidXRlcy5nZXRGbG9hdCgnYmV0YScsIDEuMCk7XG4gIHJldHVybiBjcmVhdGVBdHRyaWJ1dGVXaXRoQ2FjaGVLZXkoe3RyYW5zQSwgdHJhbnNCLCBhbHBoYSwgYmV0YSwgaXNPcHRpb25hbEN9KTtcbn07XG5cbmV4cG9ydCBjb25zdCBwYXJzZUdlbW1BdHRyaWJ1dGVzVjc6IE9wZXJhdG9ySW5pdGlhbGl6YXRpb248R2VtbUF0dHJpYnV0ZXM+ID0gKG5vZGU6IEdyYXBoLk5vZGUpOiBHZW1tQXR0cmlidXRlcyA9PlxuICAgIHBhcnNlR2VtbUF0dHJpYnV0ZXMobm9kZSwgZmFsc2UpO1xuXG5leHBvcnQgY29uc3QgcGFyc2VHZW1tQXR0cmlidXRlc1YxMTogT3BlcmF0b3JJbml0aWFsaXphdGlvbjxHZW1tQXR0cmlidXRlcz4gPSAobm9kZTogR3JhcGguTm9kZSk6IEdlbW1BdHRyaWJ1dGVzID0+XG4gICAgcGFyc2VHZW1tQXR0cmlidXRlcyhub2RlLCB0cnVlKTtcblxuY29uc3QgY3JlYXRlR2VtbVByb2dyYW1JbmZvTG9hZGVyID0gKGlucHV0czogVGVuc29yW10sIGF0dHJpYnV0ZXM6IEdlbW1BdHRyaWJ1dGVzKTogUHJvZ3JhbUluZm9Mb2FkZXIgPT4ge1xuICBjb25zdCBtZXRhZGF0YSA9IHtcbiAgICBuYW1lOiAnR2VtbScsXG4gICAgaW5wdXROYW1lczogaW5wdXRzLmxlbmd0aCA9PT0gMyA/IFsnQScsICdCJywgJ0MnXSA6IFsnQScsICdCJ10sXG4gICAgaW5wdXRUeXBlczogaW5wdXRzLmxlbmd0aCA9PT0gMyA/IFtUZXh0dXJlVHlwZS51bnBhY2tlZCwgVGV4dHVyZVR5cGUudW5wYWNrZWQsIFRleHR1cmVUeXBlLnVucGFja2VkXSA6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFtUZXh0dXJlVHlwZS51bnBhY2tlZCwgVGV4dHVyZVR5cGUudW5wYWNrZWRdLFxuICAgIGtleTogYXR0cmlidXRlcy5jYWNoZUtleVxuICB9O1xuXG4gIHJldHVybiB7Li4ubWV0YWRhdGEsIGdldDogKCkgPT4gY3JlYXRlR2VtbVByb2dyYW1JbmZvKG1ldGFkYXRhLCBpbnB1dHMsIGF0dHJpYnV0ZXMpfTtcbn07XG5cbmNvbnN0IGNyZWF0ZUdlbW1Qcm9ncmFtSW5mbyA9XG4gICAgKG1ldGFkYXRhOiBQcm9ncmFtTWV0YWRhdGEsIGlucHV0czogVGVuc29yW10sIGF0dHJpYnV0ZXM6IEdlbW1BdHRyaWJ1dGVzKTogUHJvZ3JhbUluZm8gPT4ge1xuICAgICAgY29uc3QgYVNoYXBlID0gaW5wdXRzWzBdLmRpbXMuc2xpY2UoKTtcbiAgICAgIGNvbnN0IGJTaGFwZSA9IGlucHV0c1sxXS5kaW1zLnNsaWNlKCk7XG4gICAgICBjb25zdCBbTSwgTl0gPSBHZW1tVXRpbC5nZXRTaGFwZU9mR2VtbVJlc3VsdChcbiAgICAgICAgICBhU2hhcGUsIGF0dHJpYnV0ZXMudHJhbnNBLCBiU2hhcGUsIGF0dHJpYnV0ZXMudHJhbnNCLCBpbnB1dHMubGVuZ3RoID09PSAzID8gaW5wdXRzWzJdLmRpbXMgOiB1bmRlZmluZWQpO1xuICAgICAgY29uc3Qgb3V0cHV0U2hhcGUgPSBbTSwgTl07XG4gICAgICBpZiAoIW91dHB1dFNoYXBlKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignQ2FuXFwndCB1c2UgZ2VtbSBvbiB0aGUgZ2l2ZW4gdGVuc29ycycpO1xuICAgICAgfVxuICAgICAgbGV0IHNoYXJlZERpbSA9IGFTaGFwZVthU2hhcGUubGVuZ3RoIC0gMV07XG4gICAgICBsZXQgbGluZSA9ICcnO1xuICAgICAgaWYgKGF0dHJpYnV0ZXMudHJhbnNBKSB7XG4gICAgICAgIHNoYXJlZERpbSA9IGFTaGFwZVswXTtcbiAgICAgIH1cbiAgICAgIGlmIChhdHRyaWJ1dGVzLnRyYW5zQSAmJiBhdHRyaWJ1dGVzLnRyYW5zQikge1xuICAgICAgICBsaW5lID0gJ3ZhbHVlICs9IF9BX1QoYSkgKiBfQl9UKGIpOyc7XG4gICAgICB9IGVsc2UgaWYgKGF0dHJpYnV0ZXMudHJhbnNBICYmICFhdHRyaWJ1dGVzLnRyYW5zQikge1xuICAgICAgICBsaW5lID0gJ3ZhbHVlICs9IF9BX1QoYSkgKiBfQihiKTsnO1xuICAgICAgfSBlbHNlIGlmICghYXR0cmlidXRlcy50cmFuc0EgJiYgYXR0cmlidXRlcy50cmFuc0IpIHtcbiAgICAgICAgbGluZSA9ICd2YWx1ZSArPSBfQShhKSAqIF9CX1QoYik7JztcbiAgICAgIH0gZWxzZSBpZiAoIWF0dHJpYnV0ZXMudHJhbnNBICYmICFhdHRyaWJ1dGVzLnRyYW5zQikge1xuICAgICAgICBsaW5lID0gJ3ZhbHVlICs9IF9BKGEpICogX0IoYik7JztcbiAgICAgIH1cbiAgICAgIGNvbnN0IHJhbmsgPSBvdXRwdXRTaGFwZS5sZW5ndGg7XG4gICAgICBjb25zdCBkZWNsYXJlQyA9IGlucHV0cy5sZW5ndGggPT09IDMgPyBgaW50IGNbJHtpbnB1dHNbMl0uZGltcy5sZW5ndGh9XTtgIDogJyc7XG4gICAgICBjb25zdCBicm9hZGNhc3RDID0gaW5wdXRzLmxlbmd0aCA9PT0gMyA/ICdiY2FzdEluZGljZXNfQyhpbmRpY2VzLCBjKTsnIDogJyc7XG4gICAgICBjb25zdCBjYWxjdWxhdGVDID0gaW5wdXRzLmxlbmd0aCA9PT0gMyA/ICd2YWx1ZSArPSBiZXRhICogX0MoYyk7JyA6ICcnO1xuICAgICAgY29uc3Qgc2hhZGVyU291cmNlID0gYFxuICAgICAgZmxvYXQgcHJvY2VzcyhpbnQgaW5kaWNlc1ske3Jhbmt9XSkge1xuICAgICAgICAgIGludCBhWyR7cmFua31dO1xuICAgICAgICAgIGludCBiWyR7cmFua31dO1xuICAgICAgICAgICR7ZGVjbGFyZUN9XG5cbiAgICAgICAgICBjb3B5VmVjKGluZGljZXMsIGEpO1xuICAgICAgICAgIGNvcHlWZWMoaW5kaWNlcywgYik7XG4gICAgICAgICAgJHticm9hZGNhc3RDfVxuXG4gICAgICAgICAgZmxvYXQgdmFsdWUgPSAwLjA7XG4gICAgICAgICAgZm9yIChpbnQgaz0wOyBrPCR7c2hhcmVkRGltfTsgKytrKSB7XG4gICAgICAgICAgICAgIGFbJHtyYW5rIC0gMX1dID0gaztcbiAgICAgICAgICAgICAgYlske3JhbmsgLSAyfV0gPSBrO1xuICAgICAgICAgICAgICAke2xpbmV9XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgdmFsdWUgPSB2YWx1ZSAqIGFscGhhO1xuICAgICAgICAgICR7Y2FsY3VsYXRlQ31cbiAgICAgICAgICByZXR1cm4gdmFsdWU7XG4gICAgICB9YDtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIC4uLm1ldGFkYXRhLFxuICAgICAgICBvdXRwdXQ6IHtkaW1zOiBvdXRwdXRTaGFwZSwgdHlwZTogaW5wdXRzWzBdLnR5cGUsIHRleHR1cmVUeXBlOiBUZXh0dXJlVHlwZS51bnBhY2tlZH0sXG4gICAgICAgIHZhcmlhYmxlczogW1xuICAgICAgICAgIHtuYW1lOiAnYWxwaGEnLCB0eXBlOiAnZmxvYXQnLCBkYXRhOiBhdHRyaWJ1dGVzLmFscGhhfSwge25hbWU6ICdiZXRhJywgdHlwZTogJ2Zsb2F0JywgZGF0YTogYXR0cmlidXRlcy5iZXRhfVxuICAgICAgICBdLFxuICAgICAgICBzaGFkZXJTb3VyY2VcbiAgICAgIH07XG4gICAgfTtcblxuY29uc3QgdmFsaWRhdGVJbnB1dHMgPSAoaW5wdXRzOiBUZW5zb3JbXSwgYXR0cmlidXRlczogR2VtbUF0dHJpYnV0ZXMpOiB2b2lkID0+IHtcbiAgaWYgKCFpbnB1dHMpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ0lucHV0IGlzIG1pc3NpbmcnKTtcbiAgfVxuICBpZiAoYXR0cmlidXRlcy5pc09wdGlvbmFsQyAmJiAoaW5wdXRzLmxlbmd0aCA8IDIgfHwgaW5wdXRzLmxlbmd0aCA+IDMpKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdJbnZhaWQgaW5wdXQgc2hhcGUuJyk7XG4gIH1cbiAgaWYgKCFhdHRyaWJ1dGVzLmlzT3B0aW9uYWxDICYmIGlucHV0cy5sZW5ndGggIT09IDMpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ0dlbW0gcmVxdWlyZXMgMyBpbnB1dHMnKTtcbiAgfVxuXG4gIC8vICdDJyBjYW4gYmUgb2YgZGltZW5zaW9uYWxpdHkgMSBvciAyIG9ubHlcbiAgaWYgKGlucHV0cy5sZW5ndGggPT09IDMgJiYgaW5wdXRzWzJdLmRpbXMubGVuZ3RoICE9PSAxICYmIGlucHV0c1syXS5kaW1zLmxlbmd0aCAhPT0gMikge1xuICAgIHRocm93IG5ldyBFcnJvcignSW52YWxpZCBpbnB1dCBzaGFwZSBvZiBDJyk7XG4gIH1cblxuICBpZiAoKGlucHV0c1swXS50eXBlICE9PSAnZmxvYXQzMicgJiYgaW5wdXRzWzBdLnR5cGUgIT09ICdmbG9hdDY0JykgfHxcbiAgICAgIChpbnB1dHNbMV0udHlwZSAhPT0gJ2Zsb2F0MzInICYmIGlucHV0c1sxXS50eXBlICE9PSAnZmxvYXQ2NCcpIHx8XG4gICAgICAoaW5wdXRzLmxlbmd0aCA9PT0gMyAmJiBpbnB1dHNbMl0udHlwZSAhPT0gJ2Zsb2F0MzInICYmIGlucHV0c1syXS50eXBlICE9PSAnZmxvYXQ2NCcpKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIGlucHV0IHR5cGUuJyk7XG4gIH1cblxuICBpZiAoKGlucHV0c1swXS50eXBlICE9PSBpbnB1dHNbMV0udHlwZSkgfHwgKGlucHV0cy5sZW5ndGggPT09IDMgJiYgaW5wdXRzWzBdLnR5cGUgIT09IGlucHV0c1syXS50eXBlKSkge1xuICAgIHRocm93IG5ldyBFcnJvcignSW5wdXQgdHlwZXMgYXJlIG1pc21hdGNoZWQnKTtcbiAgfVxufTtcbiIsIi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxuXG5pbXBvcnQge1RlbnNvcn0gZnJvbSAnLi4vLi4vLi4vdGVuc29yJztcbmltcG9ydCB7Z2V0R2xzbH0gZnJvbSAnLi4vZ2xzbC1zb3VyY2UnO1xuaW1wb3J0IHtXZWJHTEluZmVyZW5jZUhhbmRsZXJ9IGZyb20gJy4uL2luZmVyZW5jZS1oYW5kbGVyJztcbmltcG9ydCB7UHJvZ3JhbUluZm8sIFByb2dyYW1JbmZvTG9hZGVyLCBQcm9ncmFtTWV0YWRhdGEsIFRleHR1cmVUeXBlfSBmcm9tICcuLi90eXBlcyc7XG5cbmltcG9ydCB7Q29udkF0dHJpYnV0ZXN9IGZyb20gJy4vY29udic7XG5pbXBvcnQge3VucGFja0Zyb21DaGFubmVsfSBmcm9tICcuL3BhY2tpbmctdXRpbHMnO1xuXG5jb25zdCBjcmVhdGVQYWNrZWRJbTJDb2xQcm9ncmFtTWV0YWRhdGEgPSAoY2FjaGVIaW50OiBzdHJpbmcpID0+ICh7XG4gIG5hbWU6ICdJbTJDb2wgKHBhY2tlZCknLFxuICBpbnB1dE5hbWVzOiBbJ0EnXSxcbiAgaW5wdXRUeXBlczogW1RleHR1cmVUeXBlLnBhY2tlZF0sXG4gIGNhY2hlSGludCxcbn0pO1xuXG5jb25zdCBjcmVhdGVQYWNrZWRJbTJDb2xQcm9ncmFtSW5mbyA9XG4gICAgKGluZmVyZW5jZUhhbmRsZXI6IFdlYkdMSW5mZXJlbmNlSGFuZGxlciwgbWV0YWRhdGE6IFByb2dyYW1NZXRhZGF0YSwgeDogVGVuc29yLCB3OiBUZW5zb3IsXG4gICAgIG91dHB1dFNoYXBlOiByZWFkb25seSBudW1iZXJbXSwgYXR0cmlidXRlczogQ29udkF0dHJpYnV0ZXMpOiBQcm9ncmFtSW5mbyA9PiB7XG4gICAgICBjb25zdCB4c2hhcGUgPSB4LmRpbXM7XG4gICAgICBjb25zdCB3c2hhcGUgPSB3LmRpbXM7XG4gICAgICBjb25zdCByb3dEaW0gPSAyO1xuICAgICAgY29uc3QgY29sRGltID0gMztcbiAgICAgIGNvbnN0IHJhbmsgPSBvdXRwdXRTaGFwZS5sZW5ndGg7XG4gICAgICBjb25zdCBpbTJjb2xTaGFwZSA9IFt3c2hhcGVbMV0gKiB3c2hhcGVbMl0gKiB3c2hhcGVbM10sIG91dHB1dFNoYXBlWzJdICogb3V0cHV0U2hhcGVbM11dO1xuICAgICAgY29uc3Qga2VybmVsU2l6ZSA9IHdzaGFwZVsyXSAqIHdzaGFwZVszXTtcbiAgICAgIGNvbnN0IHVucGFja0NoYW5uZWwgPSB1bnBhY2tGcm9tQ2hhbm5lbCgpO1xuICAgICAgY29uc3QgZ2xzbCA9IGdldEdsc2woaW5mZXJlbmNlSGFuZGxlci5zZXNzaW9uLmJhY2tlbmQuZ2xDb250ZXh0LnZlcnNpb24pO1xuICAgICAgbGV0IHVucm9sbGVkID0gJyc7XG5cbiAgICAgIGZvciAobGV0IHJvdyA9IDA7IHJvdyA8PSAxOyByb3crKykge1xuICAgICAgICBmb3IgKGxldCBjb2wgPSAwOyBjb2wgPD0gMTsgY29sKyspIHtcbiAgICAgICAgICB1bnJvbGxlZCArPSBgXG4gICAgICAgICAgICBibG9ja0luZGV4ID0gcmMueCArICR7Y29sfTtcbiAgICAgICAgICAgIHBvcyA9IHJjLnkgKyAke3Jvd307XG5cbiAgICAgICAgICAgIGlmKGJsb2NrSW5kZXggPCAke2ltMmNvbFNoYXBlWzFdfSAmJiBwb3MgPCAke2ltMmNvbFNoYXBlWzBdfSkge1xuICAgICAgICAgICAgICBvZmZzZXRZID0gaW50KGJsb2NrSW5kZXggLyAoJHtvdXRwdXRTaGFwZVtyYW5rIC0gMV19KSkgKiAke2F0dHJpYnV0ZXMuc3RyaWRlc1swXX0gLVxuICAgICAgICAgICAgICAgICR7YXR0cmlidXRlcy5wYWRzWzBdfTtcbiAgICAgICAgICAgICAgZDAgPSBvZmZzZXRZICsgJHthdHRyaWJ1dGVzLmRpbGF0aW9uc1swXX0gKiAoaW1vZChwb3MsICR7a2VybmVsU2l6ZX0pIC8gJHt3c2hhcGVbMl19KTtcblxuICAgICAgICAgICAgICBpZihkMCA8ICR7eHNoYXBlW3Jvd0RpbV19ICYmIGQwID49IDApIHtcbiAgICAgICAgICAgICAgICBvZmZzZXRYID0gaW1vZChibG9ja0luZGV4LCAke291dHB1dFNoYXBlW3JhbmsgLSAxXX0pICogJHthdHRyaWJ1dGVzLnN0cmlkZXNbMV19IC1cbiAgICAgICAgICAgICAgICAgICR7YXR0cmlidXRlcy5wYWRzWzFdfTtcbiAgICAgICAgICAgICAgICBkMSA9IG9mZnNldFggKyAke2F0dHJpYnV0ZXMuZGlsYXRpb25zWzFdfSAqIGltb2QoaW1vZChwb3MsICR7a2VybmVsU2l6ZX0pLCAke3dzaGFwZVsyXX0pO1xuXG4gICAgICAgICAgICAgICAgaWYoZDEgPCAke3hzaGFwZVtjb2xEaW1dfSAmJiBkMSA+PSAwKSB7XG5cbiAgICAgICAgICAgICAgICAgIGNoID0gaW50KGZsb2F0KHBvcykvICR7a2VybmVsU2l6ZX0uKTtcbiAgICAgICAgICAgICAgICAgICAgaW5uZXJEaW1zID0gdmVjMihkMCwgZDEpO1xuICAgICAgICAgICAgICAgICAgICByZXN1bHRbJHtyb3cgKiAyICsgY29sfV0gPSBnZXRDaGFubmVsKFxuICAgICAgICAgICAgICAgICAgICAgIGdldEEoMCwgY2gsIGludChpbm5lckRpbXMueCksXG4gICAgICAgICAgICAgICAgICAgICAgaW50KGlubmVyRGltcy55KSksIGlubmVyRGltcyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICBgO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IHNoYWRlclNvdXJjZSA9IGBcbiAgICAgICR7dW5wYWNrQ2hhbm5lbH1cblxuICAgICAgdm9pZCBtYWluKCkge1xuICAgICAgICBpdmVjMiByYyA9IGdldE91dHB1dENvb3JkcygpO1xuICAgICAgICAgIHZlYzQgcmVzdWx0ID0gdmVjNCgwLjApO1xuICAgICAgICAgIGludCBibG9ja0luZGV4LCBwb3MsIG9mZnNldFksIGQwLCBvZmZzZXRYLCBkMSwgY2g7XG4gICAgICAgICAgdmVjMiBpbm5lckRpbXM7XG4gICAgICAgICAgJHt1bnJvbGxlZH1cbiAgICAgICAgICAke2dsc2wub3V0cHV0fSA9IHJlc3VsdDtcbiAgICAgIH1cbiAgICAgICAgICAgIGA7XG4gICAgICByZXR1cm4ge1xuICAgICAgICAuLi5tZXRhZGF0YSxcbiAgICAgICAgb3V0cHV0OiB7ZGltczogaW0yY29sU2hhcGUsIHR5cGU6IHgudHlwZSwgdGV4dHVyZVR5cGU6IFRleHR1cmVUeXBlLnBhY2tlZH0sXG4gICAgICAgIHNoYWRlclNvdXJjZSxcbiAgICAgICAgaGFzTWFpbjogdHJ1ZVxuICAgICAgfTtcbiAgICB9O1xuXG5leHBvcnQgY29uc3QgY3JlYXRlUGFja2VkSW0yQ29sUHJvZ3JhbUluZm9Mb2FkZXIgPVxuICAgIChpbmZlcmVuY2VIYW5kbGVyOiBXZWJHTEluZmVyZW5jZUhhbmRsZXIsIHg6IFRlbnNvciwgdzogVGVuc29yLCBvdXRwdXRTaGFwZTogcmVhZG9ubHkgbnVtYmVyW10sXG4gICAgIGF0dHJpYnV0ZXM6IENvbnZBdHRyaWJ1dGVzKTogUHJvZ3JhbUluZm9Mb2FkZXIgPT4ge1xuICAgICAgY29uc3QgbWV0YWRhdGEgPSBjcmVhdGVQYWNrZWRJbTJDb2xQcm9ncmFtTWV0YWRhdGEoYXR0cmlidXRlcy5jYWNoZUtleSk7XG4gICAgICByZXR1cm4ge1xuICAgICAgICAuLi5tZXRhZGF0YSxcbiAgICAgICAgZ2V0OiAoKSA9PiBjcmVhdGVQYWNrZWRJbTJDb2xQcm9ncmFtSW5mbyhpbmZlcmVuY2VIYW5kbGVyLCBtZXRhZGF0YSwgeCwgdywgb3V0cHV0U2hhcGUsIGF0dHJpYnV0ZXMpXG4gICAgICB9O1xuICAgIH07XG4iLCIvLyBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cblxuaW1wb3J0IHtUZW5zb3J9IGZyb20gJy4uLy4uLy4uL3RlbnNvcic7XG5pbXBvcnQge1dlYkdMSW5mZXJlbmNlSGFuZGxlcn0gZnJvbSAnLi4vaW5mZXJlbmNlLWhhbmRsZXInO1xuaW1wb3J0IHtQcm9ncmFtSW5mbywgUHJvZ3JhbUluZm9Mb2FkZXIsIFByb2dyYW1NZXRhZGF0YSwgVGV4dHVyZVR5cGV9IGZyb20gJy4uL3R5cGVzJztcblxuaW1wb3J0IHtDb252QXR0cmlidXRlc30gZnJvbSAnLi9jb252JztcblxuY29uc3QgY3JlYXRlSW0yQ29sUHJvZ3JhbU1ldGFkYXRhID0gKGNhY2hlSGludDogc3RyaW5nKSA9PiAoe1xuICBuYW1lOiAnSW0yQ29sJyxcbiAgaW5wdXROYW1lczogWydYJ10sXG4gIGlucHV0VHlwZXM6IFtUZXh0dXJlVHlwZS51bnBhY2tlZF0sXG4gIGNhY2hlSGludCxcbn0pO1xuXG5jb25zdCBjcmVhdGVJbTJDb2xQcm9ncmFtSW5mbyA9XG4gICAgKGluZmVyZW5jZUhhbmRsZXI6IFdlYkdMSW5mZXJlbmNlSGFuZGxlciwgbWV0YWRhdGE6IFByb2dyYW1NZXRhZGF0YSwgeDogVGVuc29yLCB3OiBUZW5zb3IsXG4gICAgIG91dHB1dFNoYXBlOiByZWFkb25seSBudW1iZXJbXSwgYXR0cmlidXRlczogQ29udkF0dHJpYnV0ZXMpOiBQcm9ncmFtSW5mbyA9PiB7XG4gICAgICBjb25zdCB4c2hhcGUgPSB4LmRpbXM7XG4gICAgICBjb25zdCB3c2hhcGUgPSB3LmRpbXM7XG5cbiAgICAgIGNvbnN0IHJhbmsgPSBvdXRwdXRTaGFwZS5sZW5ndGg7XG4gICAgICBjb25zdCBpbTJjb2xEaW1zID0gY2FsY3VsYXRlSW0yQ29sRGltcyh4c2hhcGUsIHdzaGFwZSwgb3V0cHV0U2hhcGUsIDQpO1xuXG4gICAgICBjb25zdCBzaGFkZXJTb3VyY2UgPSBgXG4gICAgICAgIGNvbnN0IGludCBYQyA9ICR7eHNoYXBlWzFdfTtcbiAgICAgICAgY29uc3QgaW50IFhIID0gJHt4c2hhcGVbMl19O1xuICAgICAgICBjb25zdCBpbnQgWFcgPSAke3hzaGFwZVszXX07XG4gICAgICAgIGNvbnN0IGludCBLSCA9ICR7YXR0cmlidXRlcy5rZXJuZWxTaGFwZVswXX07XG4gICAgICAgIGNvbnN0IGludCBLVyA9ICR7YXR0cmlidXRlcy5rZXJuZWxTaGFwZVsxXX07XG4gICAgICAgIGNvbnN0IGludCBkaWxhdGlvbkggPSAke2F0dHJpYnV0ZXMuZGlsYXRpb25zWzBdfTtcbiAgICAgICAgY29uc3QgaW50IGRpbGF0aW9uVyA9ICR7YXR0cmlidXRlcy5kaWxhdGlvbnNbMV19O1xuICAgICAgICBjb25zdCBpbnQgc3RyaWRlSCA9ICR7YXR0cmlidXRlcy5zdHJpZGVzWzBdfTtcbiAgICAgICAgY29uc3QgaW50IHN0cmlkZVcgPSAke2F0dHJpYnV0ZXMuc3RyaWRlc1sxXX07XG4gICAgICAgIGNvbnN0IGludCBwYWRIID0gJHthdHRyaWJ1dGVzLnBhZHNbMF19O1xuICAgICAgICBjb25zdCBpbnQgcGFkVyA9ICR7YXR0cmlidXRlcy5wYWRzWzFdfTtcbiAgICAgICAgY29uc3QgaW50IEtIS1cgPSBLSCpLVztcbiAgICAgICAgY29uc3QgaW50IFhDS0hLVyA9IFhDICogS0hLVztcbiAgICAgICAgY29uc3QgaW50IG91dHB1dENoYW5uZWxzID0gNDtcbiAgICAgICAgdmVjNCBwcm9jZXNzKGludCBpbmRpY2VzWyR7cmFua31dKSB7XG4gICAgICAgICAgaW50IGIgID0gaW5kaWNlc1swXTsgLy8gYmF0Y2ggc2l6ZVxuICAgICAgICAgIGludCBvaCA9IGluZGljZXNbMV0gKiBzdHJpZGVIIC0gcGFkSDsgLy9vdXRwdXQgaGVpZ2h0XG4gICAgICAgICAgaW50IG93ID0gaW5kaWNlc1syXSAqIHN0cmlkZVcgLSBwYWRXOyAvL291dHB1dCB3aWR0aFxuICAgICAgICAgIGludCBwID0gaW5kaWNlc1szXSAqIG91dHB1dENoYW5uZWxzOyAvL3BhdGNoXG4gICAgICAgICAgdmVjNCB2YWx1ZSA9IHZlYzQoMC4wKTtcbiAgICAgICAgICBmb3IoaW50IGk9MDsgaSA8IG91dHB1dENoYW5uZWxzOyArK2kpIHtcbiAgICAgICAgICAgIGlmKHAgPCBYQ0tIS1cpIHtcbiAgICAgICAgICAgICAgaW50IHBhdGNoQyA9IHAgLyBLSEtXO1xuICAgICAgICAgICAgICBpbnQgcGF0Y2hIID0gKHAgLSBwYXRjaEMqS0hLVykgLyBLVztcbiAgICAgICAgICAgICAgaW50IHBhdGNoVyA9IChwIC0gcGF0Y2hDKktIS1cpIC0gcGF0Y2hIICogS1c7XG4gICAgICAgICAgICAgIGludCB4aDIgPSBvaCArIHBhdGNoSCAqIGRpbGF0aW9uSDtcbiAgICAgICAgICAgICAgaW50IHh3MiA9IG93ICsgcGF0Y2hXICogZGlsYXRpb25XO1xuICAgICAgICAgICAgICBpbnQgeFske3hzaGFwZS5sZW5ndGh9XTtcbiAgICAgICAgICAgICAgeFswXSA9IGI7XG4gICAgICAgICAgICAgIHhbMV0gPSBwYXRjaEM7XG4gICAgICAgICAgICAgIHhbMl0gPSB4aDI7XG4gICAgICAgICAgICAgIHhbM10gPSB4dzI7XG4gICAgICAgICAgICAgIGlmKHhoMiA+PSAwICYmXG4gICAgICAgICAgICAgICAgICB4aDIgPCBYSCAmJlxuICAgICAgICAgICAgICAgICAgeHcyID49IDAgJiZcbiAgICAgICAgICAgICAgICAgIHh3MiA8IFhXKSB7XG4gICAgICAgICAgICAgICAgdmFsdWVbaV0gPSBfWCh4KTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgKytwO1xuICAgICAgICAgIH1cbiAgICAgICAgICByZXR1cm4gdmFsdWU7XG4gICAgICAgIH1cbiAgICAgICAgYDtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIC4uLm1ldGFkYXRhLFxuICAgICAgICBvdXRwdXQ6IHtkaW1zOiBpbTJjb2xEaW1zLCB0eXBlOiB4LnR5cGUsIHRleHR1cmVUeXBlOiBUZXh0dXJlVHlwZS5wYWNrZWRMYXN0RGltZW5zaW9ufSxcbiAgICAgICAgc2hhZGVyU291cmNlXG4gICAgICB9O1xuICAgIH07XG5cbmV4cG9ydCBjb25zdCBjcmVhdGVJbTJDb2xQcm9ncmFtSW5mb0xvYWRlciA9XG4gICAgKGluZmVyZW5jZUhhbmRsZXI6IFdlYkdMSW5mZXJlbmNlSGFuZGxlciwgeDogVGVuc29yLCB3OiBUZW5zb3IsIG91dHB1dFNoYXBlOiByZWFkb25seSBudW1iZXJbXSxcbiAgICAgYXR0cmlidXRlczogQ29udkF0dHJpYnV0ZXMpOiBQcm9ncmFtSW5mb0xvYWRlciA9PiB7XG4gICAgICBjb25zdCBtZXRhZGF0YSA9IGNyZWF0ZUltMkNvbFByb2dyYW1NZXRhZGF0YShhdHRyaWJ1dGVzLmNhY2hlS2V5KTtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIC4uLm1ldGFkYXRhLFxuICAgICAgICBnZXQ6ICgpID0+IGNyZWF0ZUltMkNvbFByb2dyYW1JbmZvKGluZmVyZW5jZUhhbmRsZXIsIG1ldGFkYXRhLCB4LCB3LCBvdXRwdXRTaGFwZSwgYXR0cmlidXRlcylcbiAgICAgIH07XG4gICAgfTtcblxuXG5leHBvcnQgY29uc3QgY2FsY3VsYXRlSW0yQ29sRGltcyA9XG4gICAgKGlucHV0U2hhcGU6IHJlYWRvbmx5IG51bWJlcltdLCBrZXJuZWxTaGFwZTogcmVhZG9ubHkgbnVtYmVyW10sIG91dHB1dFNoYXBlOiByZWFkb25seSBudW1iZXJbXSwgY2hhbm5lbHMgPSA0KTpcbiAgICAgICAgbnVtYmVyW10gPT5cbiAgICAgICAgICAgIFtvdXRwdXRTaGFwZVswXSwgb3V0cHV0U2hhcGVbMl0sIG91dHB1dFNoYXBlWzNdLFxuICAgICAgICAgICAgIE1hdGguY2VpbChpbnB1dFNoYXBlWzFdICoga2VybmVsU2hhcGVbMl0gKiBrZXJuZWxTaGFwZVszXSAvIGNoYW5uZWxzKV07XG4iLCIvLyBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cblxuaW1wb3J0IHtBdHRyaWJ1dGVXaXRoQ2FjaGVLZXksIGNyZWF0ZUF0dHJpYnV0ZVdpdGhDYWNoZUtleX0gZnJvbSAnLi4vLi4vLi4vYXR0cmlidXRlLXdpdGgtY2FjaGUta2V5JztcbmltcG9ydCB7R3JhcGh9IGZyb20gJy4uLy4uLy4uL2dyYXBoJztcbmltcG9ydCB7T3BlcmF0b3JJbXBsZW1lbnRhdGlvbiwgT3BlcmF0b3JJbml0aWFsaXphdGlvbn0gZnJvbSAnLi4vLi4vLi4vb3BlcmF0b3JzJztcbmltcG9ydCB7VGVuc29yfSBmcm9tICcuLi8uLi8uLi90ZW5zb3InO1xuaW1wb3J0IHtXZWJHTEluZmVyZW5jZUhhbmRsZXJ9IGZyb20gJy4uL2luZmVyZW5jZS1oYW5kbGVyJztcbmltcG9ydCB7UHJvZ3JhbUluZm8sIFByb2dyYW1JbmZvTG9hZGVyLCBQcm9ncmFtTWV0YWRhdGEsIFRleHR1cmVUeXBlfSBmcm9tICcuLi90eXBlcyc7XG5cbmV4cG9ydCBpbnRlcmZhY2UgSW1hZ2VTY2FsZXJBdHRyaWJ1dGVzIGV4dGVuZHMgQXR0cmlidXRlV2l0aENhY2hlS2V5IHtcbiAgc2NhbGU6IG51bWJlcjtcbiAgYmlhczogbnVtYmVyW107XG59XG5cbmV4cG9ydCBjb25zdCBpbWFnZVNjYWxlcjogT3BlcmF0b3JJbXBsZW1lbnRhdGlvbjxJbWFnZVNjYWxlckF0dHJpYnV0ZXM+ID1cbiAgICAoaW5mZXJlbmNlSGFuZGxlcjogV2ViR0xJbmZlcmVuY2VIYW5kbGVyLCBpbnB1dHM6IFRlbnNvcltdLCBhdHRyaWJ1dGVzOiBJbWFnZVNjYWxlckF0dHJpYnV0ZXMpOiBUZW5zb3JbXSA9PiB7XG4gICAgICB2YWxpZGF0ZUlucHV0cyhpbnB1dHMpO1xuICAgICAgY29uc3Qgb3V0cHV0ID1cbiAgICAgICAgICBpbmZlcmVuY2VIYW5kbGVyLnJ1bihjcmVhdGVJbWFnZVNjYWxlclByb2dyYW1JbmZvTG9hZGVyKGluZmVyZW5jZUhhbmRsZXIsIGlucHV0cywgYXR0cmlidXRlcyksIGlucHV0cyk7XG4gICAgICByZXR1cm4gW291dHB1dF07XG4gICAgfTtcblxuZXhwb3J0IGNvbnN0IHBhcnNlSW1hZ2VTY2FsZXJBdHRyaWJ1dGVzOiBPcGVyYXRvckluaXRpYWxpemF0aW9uPEltYWdlU2NhbGVyQXR0cmlidXRlcz4gPVxuICAgIChub2RlOiBHcmFwaC5Ob2RlKTogSW1hZ2VTY2FsZXJBdHRyaWJ1dGVzID0+IHtcbiAgICAgIGNvbnN0IHNjYWxlID0gbm9kZS5hdHRyaWJ1dGVzLmdldEZsb2F0KCdzY2FsZScpO1xuICAgICAgY29uc3QgYmlhcyA9IG5vZGUuYXR0cmlidXRlcy5nZXRGbG9hdHMoJ2JpYXMnKTtcbiAgICAgIHJldHVybiBjcmVhdGVBdHRyaWJ1dGVXaXRoQ2FjaGVLZXkoe3NjYWxlLCBiaWFzfSk7XG4gICAgfTtcblxuY29uc3QgaW1hZ2VTY2FsZXJQcm9ncmFtTWV0YWRhdGEgPSB7XG4gIG5hbWU6ICdJbWFnZVNjYWxlcicsXG4gIGlucHV0TmFtZXM6IFsnWCddLFxuICBpbnB1dFR5cGVzOiBbVGV4dHVyZVR5cGUudW5wYWNrZWRdLFxufTtcblxuY29uc3QgY3JlYXRlSW1hZ2VTY2FsZXJQcm9ncmFtSW5mbyA9XG4gICAgKGhhbmRsZXI6IFdlYkdMSW5mZXJlbmNlSGFuZGxlciwgbWV0YWRhdGE6IFByb2dyYW1NZXRhZGF0YSwgaW5wdXRzOiBUZW5zb3JbXSwgYXR0cmlidXRlczogSW1hZ2VTY2FsZXJBdHRyaWJ1dGVzKTpcbiAgICAgICAgUHJvZ3JhbUluZm8gPT4ge1xuICAgICAgICAgIGNvbnN0IG91dHB1dFNoYXBlID0gaW5wdXRzWzBdLmRpbXMuc2xpY2UoKTtcbiAgICAgICAgICBjb25zdCByYW5rID0gb3V0cHV0U2hhcGUubGVuZ3RoO1xuICAgICAgICAgIGNvbnN0IGdldEJpYXNNZXRob2QgPSBjcmVhdGVHZXRCaWFzTWV0aG9kKGF0dHJpYnV0ZXMuYmlhcy5sZW5ndGgpO1xuICAgICAgICAgIGNvbnN0IHNoYWRlclNvdXJjZSA9IGBcbiAgICAgICR7Z2V0Qmlhc01ldGhvZH1cbiAgICAgIGZsb2F0IHByb2Nlc3MoaW50IGluZGljZXNbJHtyYW5rfV0pIHtcbiAgICAgICAgcmV0dXJuIF9YKGluZGljZXMpICogc2NhbGUgKyBnZXRCaWFzKGJpYXMsIGluZGljZXNbMV0pO1xuICAgICAgfWA7XG4gICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIC4uLm1ldGFkYXRhLFxuICAgICAgICAgICAgb3V0cHV0OiB7ZGltczogb3V0cHV0U2hhcGUsIHR5cGU6IGlucHV0c1swXS50eXBlLCB0ZXh0dXJlVHlwZTogVGV4dHVyZVR5cGUudW5wYWNrZWR9LFxuICAgICAgICAgICAgdmFyaWFibGVzOiBbXG4gICAgICAgICAgICAgIHtuYW1lOiAnYmlhcycsIHR5cGU6ICdmbG9hdCcsIGFycmF5TGVuZ3RoOiBhdHRyaWJ1dGVzLmJpYXMubGVuZ3RoLCBkYXRhOiBhdHRyaWJ1dGVzLmJpYXN9LFxuICAgICAgICAgICAgICB7bmFtZTogJ3NjYWxlJywgdHlwZTogJ2Zsb2F0JywgZGF0YTogYXR0cmlidXRlcy5zY2FsZX1cbiAgICAgICAgICAgIF0sXG4gICAgICAgICAgICBzaGFkZXJTb3VyY2VcbiAgICAgICAgICB9O1xuICAgICAgICB9O1xuXG5jb25zdCBjcmVhdGVJbWFnZVNjYWxlclByb2dyYW1JbmZvTG9hZGVyID1cbiAgICAoaGFuZGxlcjogV2ViR0xJbmZlcmVuY2VIYW5kbGVyLCBpbnB1dHM6IFRlbnNvcltdLCBhdHRyaWJ1dGVzOiBJbWFnZVNjYWxlckF0dHJpYnV0ZXMpOiBQcm9ncmFtSW5mb0xvYWRlciA9PiB7XG4gICAgICBjb25zdCBtZXRhZGF0YSA9IHsuLi5pbWFnZVNjYWxlclByb2dyYW1NZXRhZGF0YSwgY2FjaGVIaW50OiBhdHRyaWJ1dGVzLmNhY2hlS2V5fTtcbiAgICAgIHJldHVybiB7Li4ubWV0YWRhdGEsIGdldDogKCkgPT4gY3JlYXRlSW1hZ2VTY2FsZXJQcm9ncmFtSW5mbyhoYW5kbGVyLCBtZXRhZGF0YSwgaW5wdXRzLCBhdHRyaWJ1dGVzKX07XG4gICAgfTtcblxuY29uc3QgY3JlYXRlR2V0Qmlhc01ldGhvZCA9IChudW1DaGFubmVsczogbnVtYmVyKTogc3RyaW5nID0+IHtcbiAgY29uc3QgY29kZUxpbmVzOiBzdHJpbmdbXSA9IFtgZmxvYXQgZ2V0QmlhcyhmbG9hdCBiaWFzWyR7bnVtQ2hhbm5lbHN9XSwgaW50IGNoYW5uZWwpIHtgXTtcbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBudW1DaGFubmVsczsgKytpKSB7XG4gICAgaWYgKGkgPT09IDApIHtcbiAgICAgIGNvZGVMaW5lcy5wdXNoKFxuICAgICAgICAgICdcXHQnICtcbiAgICAgICAgICBgaWYgKGNoYW5uZWwgPT0gJHtpfSkgeyByZXR1cm4gYmlhc1ske2l9XTsgfWApO1xuICAgIH0gZWxzZSBpZiAoaSA9PT0gbnVtQ2hhbm5lbHMgLSAxKSB7XG4gICAgICBjb2RlTGluZXMucHVzaChcbiAgICAgICAgICAnXFx0JyArXG4gICAgICAgICAgYGVsc2UgeyByZXR1cm4gYmlhc1ske2l9XTsgfWApO1xuICAgIH0gZWxzZSB7XG4gICAgICBjb2RlTGluZXMucHVzaChcbiAgICAgICAgICAnXFx0JyArXG4gICAgICAgICAgYGVsc2UgaWYgKGNoYW5uZWwgPT0gJHtpfSkgeyByZXR1cm4gYmlhc1ske2l9XTsgfWApO1xuICAgIH1cbiAgfVxuICBjb2RlTGluZXMucHVzaChcbiAgICAgICdcXHQnICtcbiAgICAgICd9Jyk7XG4gIHJldHVybiBjb2RlTGluZXMuam9pbignXFxuJyk7XG59O1xuXG5jb25zdCB2YWxpZGF0ZUlucHV0cyA9IChpbnB1dHM6IFRlbnNvcltdKTogdm9pZCA9PiB7XG4gIGlmICghaW5wdXRzIHx8IGlucHV0cy5sZW5ndGggIT09IDEpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ0ltYWdlU2NhbGVyIHJlcXVpcmVzIDEgaW5wdXQuJyk7XG4gIH1cbiAgaWYgKGlucHV0c1swXS5kaW1zLmxlbmd0aCAhPT0gNCkge1xuICAgIHRocm93IG5ldyBFcnJvcignSW52YWxpZCBpbnB1dCBzaGFwZS4nKTtcbiAgfVxuICBpZiAoaW5wdXRzWzBdLnR5cGUgIT09ICdmbG9hdDMyJyAmJiBpbnB1dHNbMF0udHlwZSAhPT0gJ2Zsb2F0NjQnKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIGlucHV0IHR5cGUuJyk7XG4gIH1cbn07XG4iLCIvLyBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cblxuaW1wb3J0IHtHcmFwaH0gZnJvbSAnLi4vLi4vLi4vZ3JhcGgnO1xuaW1wb3J0IHtPcGVyYXRvckltcGxlbWVudGF0aW9uLCBPcGVyYXRvckluaXRpYWxpemF0aW9ufSBmcm9tICcuLi8uLi8uLi9vcGVyYXRvcnMnO1xuaW1wb3J0IHtUZW5zb3J9IGZyb20gJy4uLy4uLy4uL3RlbnNvcic7XG5pbXBvcnQge2dldEdsc2x9IGZyb20gJy4uL2dsc2wtc291cmNlJztcbmltcG9ydCB7V2ViR0xJbmZlcmVuY2VIYW5kbGVyfSBmcm9tICcuLi9pbmZlcmVuY2UtaGFuZGxlcic7XG5pbXBvcnQge1Byb2dyYW1JbmZvLCBQcm9ncmFtSW5mb0xvYWRlciwgUHJvZ3JhbU1ldGFkYXRhLCBUZXh0dXJlVHlwZX0gZnJvbSAnLi4vdHlwZXMnO1xuXG5leHBvcnQgY29uc3QgaW5zdGFuY2VOb3JtYWxpemF0aW9uOiBPcGVyYXRvckltcGxlbWVudGF0aW9uPG51bWJlcj4gPVxuICAgIChpbmZlcmVuY2VIYW5kbGVyOiBXZWJHTEluZmVyZW5jZUhhbmRsZXIsIGlucHV0czogVGVuc29yW10sIGVwc2lsb246IG51bWJlcik6IFRlbnNvcltdID0+IHtcbiAgICAgIHZhbGlkYXRlSW5wdXRzKGlucHV0cyk7XG5cbiAgICAgIGNvbnN0IG1lYW5BbmRWYXJpYW5jZSA9IGluZmVyZW5jZUhhbmRsZXIucnVuKGNyZWF0ZU1lYW5BbmRWYXJpYW5jZVByb2dyYW1JbmZvTG9hZGVyKGlucHV0c1swXSksIGlucHV0cyk7XG4gICAgICBjb25zdCBvdXRwdXQgPSBpbmZlcmVuY2VIYW5kbGVyLnJ1bihcbiAgICAgICAgICBjcmVhdGVDb21wdXRlT3V0cHV0UHJvZ3JhbUluZm9Mb2FkZXIoaW5mZXJlbmNlSGFuZGxlciwgaW5wdXRzWzBdLCBlcHNpbG9uLCBtZWFuQW5kVmFyaWFuY2UuZGltcyksXG4gICAgICAgICAgW2lucHV0c1swXSwgbWVhbkFuZFZhcmlhbmNlLCBpbnB1dHNbMV0sIGlucHV0c1syXV0pO1xuICAgICAgcmV0dXJuIFtvdXRwdXRdO1xuICAgIH07XG5cbmV4cG9ydCBjb25zdCBwYXJzZUluc3RhbmNlTm9ybWFsaXphdGlvbkF0dHJpYnV0ZXM6IE9wZXJhdG9ySW5pdGlhbGl6YXRpb248bnVtYmVyPiA9IChub2RlOiBHcmFwaC5Ob2RlKTogbnVtYmVyID0+XG4gICAgbm9kZS5hdHRyaWJ1dGVzLmdldEZsb2F0KCdlcHNpbG9uJywgMWUtNSk7XG5cbmNvbnN0IG1lYW5BbmRWYXJpYW5jZVByb2dyYW1NZXRhZGF0YSA9IHtcbiAgbmFtZTogJ0luc3RhbmNlTm9ybWFsaXphdGlvbl9NZWFuQW5kVmFyaWFuY2UnLFxuICBpbnB1dE5hbWVzOiBbJ1gnXSxcbiAgaW5wdXRUeXBlczogW1RleHR1cmVUeXBlLnVucGFja2VkXSxcbn07XG5cbmNvbnN0IGNyZWF0ZU1lYW5BbmRWYXJpYW5jZVByb2dyYW1JbmZvID0gKG1ldGFkYXRhOiBQcm9ncmFtTWV0YWRhdGEsIGlucHV0OiBUZW5zb3IpOiBQcm9ncmFtSW5mbyA9PiB7XG4gIGNvbnN0IHhEaW1zID0gaW5wdXQuZGltcy5zbGljZSgpO1xuICBjb25zdCBjaGFubmVsID0geERpbXNbMV07XG4gIGNvbnN0IGNoYW5uZWxTaXplID0geERpbXNbMl0gKiB4RGltc1szXTtcbiAgY29uc3Qgb3V0cHV0U2hhcGUgPSBbeERpbXNbMF0sIGNoYW5uZWxdO1xuXG4gIGNvbnN0IHNoYWRlclNvdXJjZSA9IGBcbiAgICAgIHZlYzQgcHJvY2VzcyhpbnRbMl0gaW5kaWNlcykge1xuICAgICAgICB2ZWM0IHYgPSB2ZWM0KDAuMCk7XG4gICAgICAgIGludCBhWzRdO1xuICAgICAgICBhWzBdID0gaW5kaWNlc1swXTtcbiAgICAgICAgYVsxXSA9IGluZGljZXNbMV07XG4gICAgICAgIGZsb2F0IHRlbXAgPSAwLjA7XG4gICAgICAgIGZvcihpbnQgYTI9MDsgYTI8JHt4RGltc1syXX07IGEyKyspIHtcbiAgICAgICAgICBhWzJdID0gYTI7XG4gICAgICAgICAgZm9yKGludCBhMz0wOyBhMzwke3hEaW1zWzNdfTsgYTMrKykge1xuICAgICAgICAgICAgYVszXSA9IGEzO1xuICAgICAgICAgICAgZmxvYXQgeCA9IF9YKGEpO1xuICAgICAgICAgICAgdGVtcCArPSB4O1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBmbG9hdCBtZWFuID0gdGVtcCAvIGZsb2F0KCR7Y2hhbm5lbFNpemV9KTtcbiAgICAgICAgdGVtcCA9IDAuMDtcbiAgICAgICAgZm9yKGludCBhMj0wOyBhMjwke3hEaW1zWzJdfTsgYTIrKykge1xuICAgICAgICAgIGFbMl0gPSBhMjtcbiAgICAgICAgICBmb3IoaW50IGEzPTA7IGEzPCR7eERpbXNbM119OyBhMysrKSB7XG4gICAgICAgICAgICBhWzNdID0gYTM7XG4gICAgICAgICAgICBmbG9hdCB4ID0gX1goYSk7XG4gICAgICAgICAgICB0ZW1wICs9ICh4IC0gbWVhbikgKiAoeCAtIG1lYW4pO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICB2LnIgPSBtZWFuO1xuICAgICAgICB2LmcgPSB0ZW1wIC8gZmxvYXQoJHtjaGFubmVsU2l6ZX0pO1xuXG4gICAgICAgIHJldHVybiB2O1xuICAgICAgfWA7XG4gIHJldHVybiB7XG4gICAgLi4ubWV0YWRhdGEsXG4gICAgb3V0cHV0OiB7ZGltczogb3V0cHV0U2hhcGUsIHR5cGU6IGlucHV0LnR5cGUsIHRleHR1cmVUeXBlOiBUZXh0dXJlVHlwZS5wYWNrZWRMYXN0RGltZW5zaW9ufSxcbiAgICBzaGFkZXJTb3VyY2VcbiAgfTtcbn07XG5cbmNvbnN0IGNyZWF0ZU1lYW5BbmRWYXJpYW5jZVByb2dyYW1JbmZvTG9hZGVyID0gKGlucHV0OiBUZW5zb3IpOiBQcm9ncmFtSW5mb0xvYWRlciA9PiAoe1xuICAuLi5tZWFuQW5kVmFyaWFuY2VQcm9ncmFtTWV0YWRhdGEsXG4gIGdldDogKCkgPT4gY3JlYXRlTWVhbkFuZFZhcmlhbmNlUHJvZ3JhbUluZm8obWVhbkFuZFZhcmlhbmNlUHJvZ3JhbU1ldGFkYXRhLCBpbnB1dClcbn0pO1xuXG5jb25zdCBjb21wdXRlT3V0cHV0UHJvZ3JhbU1ldGFkYXRhID0ge1xuICBuYW1lOiAnSW5zdGFuY2VOb3JtYWxpemF0aW9uX0NvbXB1dGVPdXRwdXQnLFxuICBpbnB1dE5hbWVzOiBbJ1gnLCAnTWVhbkFuZFZhcmlhbmNlJywgJ1NjYWxlJywgJ0InXSxcbiAgaW5wdXRUeXBlczogW1RleHR1cmVUeXBlLnVucGFja2VkLCBUZXh0dXJlVHlwZS5wYWNrZWRMYXN0RGltZW5zaW9uLCBUZXh0dXJlVHlwZS51bnBhY2tlZCwgVGV4dHVyZVR5cGUudW5wYWNrZWRdLFxufTtcblxuY29uc3QgY3JlYXRlQ29tcHV0ZU91dHB1dFByb2dyYW1JbmZvID1cbiAgICAoaW5mZXJlbmNlSGFuZGxlcjogV2ViR0xJbmZlcmVuY2VIYW5kbGVyLCBtZXRhZGF0YTogUHJvZ3JhbU1ldGFkYXRhLCBpbnB1dDogVGVuc29yLCBlcHNpbG9uOiBudW1iZXIsXG4gICAgIG1lYW5BbmRWYXJpYW5jZVNoYXBlOiByZWFkb25seSBudW1iZXJbXSk6IFByb2dyYW1JbmZvID0+IHtcbiAgICAgIGNvbnN0IGdsc2wgPSBnZXRHbHNsKGluZmVyZW5jZUhhbmRsZXIuc2Vzc2lvbi5iYWNrZW5kLmdsQ29udGV4dC52ZXJzaW9uKTtcbiAgICAgIGNvbnN0IFt0ZXh0dXJlV2lkdGgsIHRleHR1cmVIZWlnaHRdID1cbiAgICAgICAgICBpbmZlcmVuY2VIYW5kbGVyLmNhbGN1bGF0ZVRleHR1cmVXaWR0aEFuZEhlaWdodChtZWFuQW5kVmFyaWFuY2VTaGFwZSwgVGV4dHVyZVR5cGUucGFja2VkTGFzdERpbWVuc2lvbik7XG4gICAgICBjb25zdCBbbWVhbkFuZFZhcmlhbmNlV2lkdGgsIG1lYW5BbmRWYXJpYW5jZUhlaWdodF0gPSBbdGV4dHVyZVdpZHRoIC8gNCwgdGV4dHVyZUhlaWdodF07XG4gICAgICBjb25zdCBzaGFkZXJTb3VyY2UgPSBgXG4gICAgICB2ZWM0IGdldF9NZWFuQW5kVmFyaWFuY2UoaW50WzJdIG12KSB7XG4gICAgICAgIGludCBvZmZzZXQgPSBpbmRpY2VzVG9PZmZzZXRfTWVhbkFuZFZhcmlhbmNlKG12KTtcbiAgICAgICAgdmVjMiBjb29yZHMgPSBvZmZzZXRUb0Nvb3JkcyhvZmZzZXQsICR7bWVhbkFuZFZhcmlhbmNlV2lkdGh9LCAke21lYW5BbmRWYXJpYW5jZUhlaWdodH0pO1xuICAgICAgICByZXR1cm4gJHtnbHNsLnRleHR1cmUyRH0oTWVhbkFuZFZhcmlhbmNlLCBjb29yZHMpO1xuICAgICAgfVxuXG4gICAgICBmbG9hdCBwcm9jZXNzKGludFs0XSBpbmRpY2VzKSB7XG4gICAgICAgIGludCBtdlsyXTtcbiAgICAgICAgbXZbMF0gPSBpbmRpY2VzWzBdO1xuICAgICAgICBtdlsxXSA9IGluZGljZXNbMV07XG4gICAgICAgIHZlYzQgbWVhbl9hbmRfdmFyaWFuY2UgPSBnZXRfTWVhbkFuZFZhcmlhbmNlKG12KTtcbiAgICAgICAgZmxvYXQgbWVhbiA9IG1lYW5fYW5kX3ZhcmlhbmNlLnI7XG4gICAgICAgIGZsb2F0IHZhcmlhbmNlID0gbWVhbl9hbmRfdmFyaWFuY2UuZztcblxuICAgICAgICBpbnQgc2JbMV07XG4gICAgICAgIHNiWzBdID0gaW5kaWNlc1sxXTtcbiAgICAgICAgZmxvYXQgc2NhbGUgPSBfU2NhbGUoc2IpO1xuICAgICAgICBmbG9hdCBiID0gX0Ioc2IpO1xuXG4gICAgICAgIHJldHVybiBzY2FsZSAqIChfWChpbmRpY2VzKSAtIG1lYW4pIC8gc3FydCh2YXJpYW5jZSArIGVwc2lsb24pICsgYjtcbiAgICAgIH1gO1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgLi4ubWV0YWRhdGEsXG4gICAgICAgIG91dHB1dDoge2RpbXM6IGlucHV0LmRpbXMsIHR5cGU6IGlucHV0LnR5cGUsIHRleHR1cmVUeXBlOiBUZXh0dXJlVHlwZS51bnBhY2tlZH0sXG4gICAgICAgIHZhcmlhYmxlczogW3tuYW1lOiAnZXBzaWxvbicsIHR5cGU6ICdmbG9hdCcsIGRhdGE6IGVwc2lsb259XSxcbiAgICAgICAgc2hhZGVyU291cmNlXG4gICAgICB9O1xuICAgIH07XG5cbmNvbnN0IGNyZWF0ZUNvbXB1dGVPdXRwdXRQcm9ncmFtSW5mb0xvYWRlciA9XG4gICAgKGluZmVyZW5jZUhhbmRsZXI6IFdlYkdMSW5mZXJlbmNlSGFuZGxlciwgaW5wdXQ6IFRlbnNvciwgZXBzaWxvbjogbnVtYmVyLCBtZWFuQW5kVmFyaWFuY2VTaGFwZTogcmVhZG9ubHkgbnVtYmVyW10pOlxuICAgICAgICBQcm9ncmFtSW5mb0xvYWRlciA9PiB7XG4gICAgICAgICAgY29uc3QgbWV0YWRhdGEgPSB7Li4uY29tcHV0ZU91dHB1dFByb2dyYW1NZXRhZGF0YSwgY2FjaGVIaW50OiBgJHtlcHNpbG9ufWB9O1xuICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAuLi5tZXRhZGF0YSxcbiAgICAgICAgICAgIGdldDogKCkgPT4gY3JlYXRlQ29tcHV0ZU91dHB1dFByb2dyYW1JbmZvKGluZmVyZW5jZUhhbmRsZXIsIG1ldGFkYXRhLCBpbnB1dCwgZXBzaWxvbiwgbWVhbkFuZFZhcmlhbmNlU2hhcGUpXG4gICAgICAgICAgfTtcbiAgICAgICAgfTtcblxuY29uc3QgdmFsaWRhdGVJbnB1dHMgPSAoaW5wdXRzOiBUZW5zb3JbXSk6IHZvaWQgPT4ge1xuICBpZiAoIWlucHV0cyB8fCBpbnB1dHMubGVuZ3RoICE9PSAzKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdJbnN0YW5jZU5vcm1hbGl6YXRpb24gcmVxdWlyZXMgMyBpbnB1dHMuJyk7XG4gIH1cblxuICBjb25zdCBYID0gaW5wdXRzWzBdO1xuICBjb25zdCBzY2FsZSA9IGlucHV0c1sxXTtcbiAgY29uc3QgQiA9IGlucHV0c1syXTtcblxuICAvLyBpbnB1dCBzaG91bGQgYXQgbGVhc3QgaGF2ZSB0aHJlZSBkaW1lbnNpb25zIC0gTixDLGRpbTEsLi4uLGRpbW5cbiAgLy8gb3RoZXIgaW5wdXRzIGNhbiBoYXZlIG9ubHkgb25lIGRpbWVuc2lvbnNcbiAgaWYgKFguZGltcy5sZW5ndGggPCAzIHx8IHNjYWxlLmRpbXMubGVuZ3RoICE9PSAxIHx8IEIuZGltcy5sZW5ndGggIT09IDEpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ0ludmFsaWQgaW5wdXQgc2hhcGUuJyk7XG4gIH1cbiAgaWYgKHNjYWxlLmRpbXNbMF0gIT09IFguZGltc1sxXSB8fCBCLmRpbXNbMF0gIT09IFguZGltc1sxXSkge1xuICAgIHRocm93IG5ldyBFcnJvcignSW5wdXQgc2hhcGVzIGFyZSBtaXNtYXRjaGVkLicpO1xuICB9XG4gIGlmICgoWC50eXBlICE9PSAnZmxvYXQzMicgJiYgWC50eXBlICE9PSAnZmxvYXQ2NCcpIHx8IChzY2FsZS50eXBlICE9PSAnZmxvYXQzMicgJiYgc2NhbGUudHlwZSAhPT0gJ2Zsb2F0NjQnKSB8fFxuICAgICAgKEIudHlwZSAhPT0gJ2Zsb2F0MzInICYmIEIudHlwZSAhPT0gJ2Zsb2F0NjQnKSkge1xuICAgIHRocm93IG5ldyBFcnJvcignSW52YWxpZCBpbnB1dCB0eXBlLicpO1xuICB9XG4gIGlmIChpbnB1dHNbMF0uZGltcy5sZW5ndGggIT09IDQpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ09ubHkgc3VwcG9ydCA0LUQgaW5wdXQgc2hhcGUuJyk7XG4gIH1cbn07XG4iLCIvLyBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cblxuaW1wb3J0IHtUZW5zb3J9IGZyb20gJy4uLy4uLy4uL3RlbnNvcic7XG5pbXBvcnQge0Jyb2FkY2FzdFV0aWwsIFNoYXBlVXRpbH0gZnJvbSAnLi4vLi4vLi4vdXRpbCc7XG5pbXBvcnQge2dldEdsc2x9IGZyb20gJy4uL2dsc2wtc291cmNlJztcbmltcG9ydCB7V2ViR0xJbmZlcmVuY2VIYW5kbGVyfSBmcm9tICcuLi9pbmZlcmVuY2UtaGFuZGxlcic7XG5pbXBvcnQge1Byb2dyYW1JbmZvLCBQcm9ncmFtSW5mb0xvYWRlciwgUHJvZ3JhbU1ldGFkYXRhLCBUZXh0dXJlVHlwZX0gZnJvbSAnLi4vdHlwZXMnO1xuaW1wb3J0IHtnZXRDb29yZHNEYXRhVHlwZSwgZ2V0R2xDaGFubmVsc30gZnJvbSAnLi4vdXRpbHMnO1xuXG5pbXBvcnQge2dldEFjdGl2YXRpb25TbmlwcGV0LCBJbnRlcm5hbEFjdGl2YXRpb25BdHRyaWJ1dGVzfSBmcm9tICcuL2Z1c2UtdXRpbHMnO1xuaW1wb3J0IHtnZXRCaWFzRm9yTWF0bXVsfSBmcm9tICcuL21hdG11bCc7XG5cbmNvbnN0IGNyZWF0ZVBhY2tlZE1hdG11bFByb2dyYW1NZXRhZGF0YSA9IChoYXNCaWFzOiBib29sZWFuLCBjYWNoZUhpbnQ6IHN0cmluZykgPT4gKHtcbiAgbmFtZTogJ01hdE11bCAocGFja2VkKScsXG4gIGlucHV0TmFtZXM6IGhhc0JpYXMgPyBbJ0EnLCAnQicsICdCaWFzJ10gOiBbJ0EnLCAnQiddLFxuICBpbnB1dFR5cGVzOiBoYXNCaWFzID8gW1RleHR1cmVUeXBlLnBhY2tlZCwgVGV4dHVyZVR5cGUucGFja2VkLCBUZXh0dXJlVHlwZS5wYWNrZWRdIDpcbiAgICAgICAgICAgICAgICAgICAgICAgIFtUZXh0dXJlVHlwZS5wYWNrZWQsIFRleHR1cmVUeXBlLnBhY2tlZF0sXG4gIGNhY2hlSGludFxufSk7XG5cbmNvbnN0IGNyZWF0ZVBhY2tlZE1hdG11bFByb2dyYW1JbmZvID1cbiAgICAoaW5mZXJlbmNlSGFuZGxlcjogV2ViR0xJbmZlcmVuY2VIYW5kbGVyLCBtZXRhZGF0YTogUHJvZ3JhbU1ldGFkYXRhLCBpbnB1dHM6IFRlbnNvcltdLFxuICAgICBhY3RpdmF0aW9uQXR0cmlidXRlczogSW50ZXJuYWxBY3RpdmF0aW9uQXR0cmlidXRlcyk6IFByb2dyYW1JbmZvID0+IHtcbiAgICAgIGNvbnN0IGhhc0JpYXMgPSBpbnB1dHMubGVuZ3RoID4gMjtcbiAgICAgIGNvbnN0IHByb2Nlc3NCaWFzID0gaGFzQmlhcyA/ICd2YWx1ZSArPSBnZXRCaWFzRm9yTWF0bXVsKCk7JyA6ICcnO1xuICAgICAgY29uc3QgYVNoYXBlID0gaW5wdXRzWzBdLmRpbXM7XG4gICAgICBjb25zdCBiU2hhcGUgPSBpbnB1dHNbMV0uZGltcztcbiAgICAgIGNvbnN0IG91dHB1dFNoYXBlID0gQnJvYWRjYXN0VXRpbC5jYWxjU2hhcGUoYVNoYXBlLCBiU2hhcGUsIHRydWUpO1xuICAgICAgY29uc3QgaXNCcm9hZGNhc3QgPSAhU2hhcGVVdGlsLmFyZUVxdWFsKGlucHV0c1swXS5kaW1zLCBpbnB1dHNbMV0uZGltcyk7XG5cbiAgICAgIGlmICghb3V0cHV0U2hhcGUpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdDYW5cXCd0IHVzZSBtYXRtdWwgb24gdGhlIGdpdmVuIHRlbnNvcnMnKTtcbiAgICAgIH1cbiAgICAgIGNvbnN0IHNoYXJlZERpbSA9IGFTaGFwZVthU2hhcGUubGVuZ3RoIC0gMV07XG4gICAgICBjb25zdCBzaGFyZWREaW1JbmRleCA9IE1hdGguY2VpbChzaGFyZWREaW0gLyAyKTtcbiAgICAgIGNvbnN0IGFSYW5rID0gYVNoYXBlLmxlbmd0aDtcbiAgICAgIGNvbnN0IGJSYW5rID0gYlNoYXBlLmxlbmd0aDtcblxuICAgICAgY29uc3QgZ2xzbCA9IGdldEdsc2woaW5mZXJlbmNlSGFuZGxlci5zZXNzaW9uLmJhY2tlbmQuZ2xDb250ZXh0LnZlcnNpb24pO1xuICAgICAgY29uc3QgY29vcmRzRGF0YVR5cGUgPSBnZXRDb29yZHNEYXRhVHlwZShvdXRwdXRTaGFwZS5sZW5ndGgpO1xuICAgICAgY29uc3Qgb3V0UmFuayA9IG91dHB1dFNoYXBlLmxlbmd0aDtcbiAgICAgIGNvbnN0IGFsbEdsQ2hhbm5lbHMgPSBnZXRHbENoYW5uZWxzKCk7XG4gICAgICBjb25zdCB7YWN0aXZhdGlvbkZ1bmN0aW9uLCBhcHBseUFjdGl2YXRpb259ID0gZ2V0QWN0aXZhdGlvblNuaXBwZXQoYWN0aXZhdGlvbkF0dHJpYnV0ZXMpO1xuXG4gICAgICBjb25zdCBnZXRCaWFzRm9yTWF0bXVsU25pcHBldCA9XG4gICAgICAgICAgaGFzQmlhcyA/IGAke2dldEJpYXNGb3JNYXRtdWwoY29vcmRzRGF0YVR5cGUsIGFsbEdsQ2hhbm5lbHMsIGlucHV0c1syXS5kaW1zLCBvdXRwdXRTaGFwZSwgdHJ1ZSl9YCA6ICcnO1xuXG4gICAgICBjb25zdCBnZXRCY2FzdGVkU2FtcGxlckZvck1hdG11bFNuaXBwZXQgPVxuICAgICAgICAgIGlzQnJvYWRjYXN0ID8gYCR7Z2V0QmNhc3RTYW1wbGVyRm9yTWF0bXVsKGNvb3Jkc0RhdGFUeXBlLCBhbGxHbENoYW5uZWxzLCBpbnB1dHMsIG91dHB1dFNoYXBlKX1gIDogJyc7XG5cbiAgICAgIGNvbnN0IGdldFNhbXBsZXJBSW5Mb29wU25pcHBldCA9IGlzQnJvYWRjYXN0ID8gJ2dldEFBdE91dENvb3Jkc01hdG11bChpKScgOiBgZ2V0QSgke2dldEEoYWxsR2xDaGFubmVscywgYVJhbmspfSlgO1xuICAgICAgY29uc3QgZ2V0U2FtcGxlckJJbkxvb3BTbmlwcGV0ID0gaXNCcm9hZGNhc3QgPyAnZ2V0QkF0T3V0Q29vcmRzTWF0bXVsKGkpJyA6IGBnZXRCKCR7Z2V0QihhbGxHbENoYW5uZWxzLCBiUmFuayl9KWA7XG4gICAgICBjb25zdCBnZXRPdXRwdXRDb29yZHNTbmlwcGV0ID0gaXNCcm9hZGNhc3QgPyAnJyA6IGAke2Nvb3Jkc0RhdGFUeXBlfSByYyA9XG4gICAgICAgICAgZ2V0T3V0cHV0Q29vcmRzKCk7IGludCBsYXN0RGltID0gcmMuJHthbGxHbENoYW5uZWxzW291dFJhbmsgLSAxXX07IHJjLiR7YWxsR2xDaGFubmVsc1tvdXRSYW5rIC0gMV19ID1cbiAgICAgICAgICByYy4ke2FsbEdsQ2hhbm5lbHNbb3V0UmFuayAtIDJdfTsgcmMuJHthbGxHbENoYW5uZWxzW291dFJhbmsgLSAyXX0gPSBsYXN0RGltO1xuICAgICAgYDtcbiAgICAgIGNvbnN0IHNoYWRlclNvdXJjZSA9IGBcbiAgICAgICAgICAgICR7Z2V0QmNhc3RlZFNhbXBsZXJGb3JNYXRtdWxTbmlwcGV0fVxuICAgICAgICAgICAgJHtnZXRCaWFzRm9yTWF0bXVsU25pcHBldH1cbiAgICAgICAgICAgICR7YWN0aXZhdGlvbkZ1bmN0aW9ufVxuICAgICAgICAgICAgdm9pZCBtYWluKCkge1xuICAgICAgICAgICAgICAke2dldE91dHB1dENvb3Jkc1NuaXBwZXR9XG5cbiAgICAgICAgICAgICAgdmVjNCB2YWx1ZSA9IHZlYzQoMCk7XG4gICAgICAgICAgICAgIGZvciAoaW50IGkgPSAwOyBpIDwgJHtzaGFyZWREaW1JbmRleH07IGkrKykge1xuICAgICAgICAgICAgICAgIHZlYzQgYSA9ICR7Z2V0U2FtcGxlckFJbkxvb3BTbmlwcGV0fTtcbiAgICAgICAgICAgICAgICB2ZWM0IGIgPSAke2dldFNhbXBsZXJCSW5Mb29wU25pcHBldH07XG5cbiAgICAgICAgICAgICAgICB2YWx1ZSArPSAoYS5ycmJiICogYi5yZ3JnKTtcbiAgICAgICAgICAgICAgICB2YWx1ZSArPSAoYS5nZ2FhICogYi5iYWJhKTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAke3Byb2Nlc3NCaWFzfVxuICAgICAgICAgICAgICAke2FwcGx5QWN0aXZhdGlvbn1cbiAgICAgICAgICAgICAgJHtnbHNsLm91dHB1dH0gPSB2YWx1ZTtcbiAgICAgICAgICAgIH1gO1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgLi4ubWV0YWRhdGEsXG4gICAgICAgIG91dHB1dDoge2RpbXM6IG91dHB1dFNoYXBlLCB0eXBlOiBpbnB1dHNbMF0udHlwZSwgdGV4dHVyZVR5cGU6IFRleHR1cmVUeXBlLnBhY2tlZH0sXG4gICAgICAgIHNoYWRlclNvdXJjZSxcbiAgICAgICAgaGFzTWFpbjogdHJ1ZVxuICAgICAgfTtcbiAgICB9O1xuXG5leHBvcnQgY29uc3QgY3JlYXRlUGFja2VkTWF0bXVsUHJvZ3JhbUluZm9Mb2FkZXIgPVxuICAgIChpbmZlcmVuY2VIYW5kbGVyOiBXZWJHTEluZmVyZW5jZUhhbmRsZXIsIGlucHV0czogVGVuc29yW10sXG4gICAgIGFjdGl2YXRpb25BdHRyaWJ1dGVzOiBJbnRlcm5hbEFjdGl2YXRpb25BdHRyaWJ1dGVzKTogUHJvZ3JhbUluZm9Mb2FkZXIgPT4ge1xuICAgICAgY29uc3QgbWV0YWRhdGEgPSBjcmVhdGVQYWNrZWRNYXRtdWxQcm9ncmFtTWV0YWRhdGEoaW5wdXRzLmxlbmd0aCA+IDIsIGFjdGl2YXRpb25BdHRyaWJ1dGVzLmFjdGl2YXRpb25DYWNoZUtleSk7XG4gICAgICByZXR1cm4ge1xuICAgICAgICAuLi5tZXRhZGF0YSxcbiAgICAgICAgZ2V0OiAoKSA9PiBjcmVhdGVQYWNrZWRNYXRtdWxQcm9ncmFtSW5mbyhpbmZlcmVuY2VIYW5kbGVyLCBtZXRhZGF0YSwgaW5wdXRzLCBhY3RpdmF0aW9uQXR0cmlidXRlcylcbiAgICAgIH07XG4gICAgfTtcblxuZnVuY3Rpb24gZ2V0QmNhc3RTYW1wbGVyRm9yTWF0bXVsKFxuICAgIGNvb3Jkc0RhdGFUeXBlOiBzdHJpbmcsIGFsbEdsQ2hhbm5lbHM6IHJlYWRvbmx5IHN0cmluZ1tdLCBpbnB1dHM6IFRlbnNvcltdLCBvdXRTaGFwZTogcmVhZG9ubHkgbnVtYmVyW10pOiBzdHJpbmcge1xuICBsZXQgdW5wYWNrZWRBQ29vcmRzU25pcHBldCA9IFtdO1xuICBsZXQgdW5wYWNrZWRCQ29vcmRzU25pcHBldCA9IFtdO1xuXG4gIGNvbnN0IGluQVNoYXBlID0gaW5wdXRzWzBdLmRpbXM7XG4gIGNvbnN0IGluQlNoYXBlID0gaW5wdXRzWzFdLmRpbXM7XG5cbiAgY29uc3QgaW5BUmFuayA9IGluQVNoYXBlLmxlbmd0aDtcbiAgY29uc3QgaW5CUmFuayA9IGluQlNoYXBlLmxlbmd0aDtcblxuICBjb25zdCBvdXRSYW5rID0gb3V0U2hhcGUubGVuZ3RoO1xuICBjb25zdCByYW5rQURpZmYgPSBvdXRSYW5rIC0gaW5BUmFuaztcbiAgY29uc3QgcmFua0JEaWZmID0gb3V0UmFuayAtIGluQlJhbms7XG5cbiAgdW5wYWNrZWRBQ29vcmRzU25pcHBldCA9IGluQVNoYXBlLm1hcCgocywgaSkgPT4gYGNvb3Jkcy4ke2FsbEdsQ2hhbm5lbHNbaSArIHJhbmtBRGlmZl19YCk7XG4gIHVucGFja2VkQUNvb3Jkc1NuaXBwZXRbaW5BUmFuayAtIDFdID0gJ2kqMic7XG4gIHVucGFja2VkQUNvb3Jkc1NuaXBwZXQuam9pbignLCAnKTtcbiAgdW5wYWNrZWRCQ29vcmRzU25pcHBldCA9IGluQlNoYXBlLm1hcCgocywgaSkgPT4gYGNvb3Jkcy4ke2FsbEdsQ2hhbm5lbHNbaSArIHJhbmtCRGlmZl19YCk7XG4gIHVucGFja2VkQkNvb3Jkc1NuaXBwZXRbaW5CUmFuayAtIDJdID0gJ2kqMic7XG4gIHVucGFja2VkQkNvb3Jkc1NuaXBwZXQuam9pbignLCAnKTtcblxuICBjb25zdCBicm9hZGNhc3RBRGltcyA9IEJyb2FkY2FzdFV0aWwuZ2V0QnJvYWRjYXN0RGltcyhpbkFTaGFwZSwgb3V0U2hhcGUpO1xuICBjb25zdCBicm9hZGNhc3RCRGltcyA9IEJyb2FkY2FzdFV0aWwuZ2V0QnJvYWRjYXN0RGltcyhpbkJTaGFwZSwgb3V0U2hhcGUpO1xuXG4gIGNvbnN0IGNvb3Jkc0FTbmlwcGV0ID0gYnJvYWRjYXN0QURpbXMubWFwKGQgPT4gYGNvb3Jkcy4ke2FsbEdsQ2hhbm5lbHNbZCArIHJhbmtBRGlmZl19ID0gMDtgKS5qb2luKCdcXG4nKTtcbiAgY29uc3QgY29vcmRzQlNuaXBwZXQgPSBicm9hZGNhc3RCRGltcy5tYXAoZCA9PiBgY29vcmRzLiR7YWxsR2xDaGFubmVsc1tkICsgcmFua0JEaWZmXX0gPSAwO2ApLmpvaW4oJ1xcbicpO1xuICBjb25zdCBzd2FwRGltU25pcHBldCA9IGBpbnQgbGFzdERpbSA9IGNvb3Jkcy4ke2FsbEdsQ2hhbm5lbHNbb3V0UmFuayAtIDFdfTtcbiAgY29vcmRzLiR7YWxsR2xDaGFubmVsc1tvdXRSYW5rIC0gMV19ID0gY29vcmRzLiR7YWxsR2xDaGFubmVsc1tvdXRSYW5rIC0gMl19O1xuICBjb29yZHMuJHthbGxHbENoYW5uZWxzW291dFJhbmsgLSAyXX0gPSBsYXN0RGltO2A7XG5cbiAgY29uc3QgZ2V0QmNhc3RTYW1wbGVyTWF0bXVsU291cmNlID0gYFxudmVjNCBnZXRBQXRPdXRDb29yZHNNYXRtdWwoaW50IGkpIHtcbiAgJHtjb29yZHNEYXRhVHlwZX0gY29vcmRzID0gZ2V0T3V0cHV0Q29vcmRzKCk7XG4gICR7c3dhcERpbVNuaXBwZXR9XG4gICR7Y29vcmRzQVNuaXBwZXR9XG4gIHZlYzQgb3V0cHV0VmFsdWUgPSBnZXRBKCR7dW5wYWNrZWRBQ29vcmRzU25pcHBldH0pO1xuICByZXR1cm4gb3V0cHV0VmFsdWU7XG59XG5cbnZlYzQgZ2V0QkF0T3V0Q29vcmRzTWF0bXVsKGludCBpKSB7XG4gICR7Y29vcmRzRGF0YVR5cGV9IGNvb3JkcyA9IGdldE91dHB1dENvb3JkcygpO1xuICAke3N3YXBEaW1TbmlwcGV0fVxuICAke2Nvb3Jkc0JTbmlwcGV0fVxuICB2ZWM0IG91dHB1dFZhbHVlID0gZ2V0Qigke3VucGFja2VkQkNvb3Jkc1NuaXBwZXR9KTtcbiAgcmV0dXJuIG91dHB1dFZhbHVlO1xufWA7XG5cbiAgcmV0dXJuIGdldEJjYXN0U2FtcGxlck1hdG11bFNvdXJjZTtcbn1cblxuZnVuY3Rpb24gZ2V0QShhbGxHbENoYW5uZWxzOiBzdHJpbmdbXSwgcmFuazogbnVtYmVyKTogc3RyaW5nIHtcbiAgbGV0IHJlcyA9ICcnO1xuICBmb3IgKGxldCBpID0gMDsgaSA8IHJhbmsgLSAyOyBpKyspIHtcbiAgICByZXMgKz0gYHJjLiR7YWxsR2xDaGFubmVsc1tpXX0sIGA7XG4gIH1cbiAgcmVzICs9IGByYy4ke2FsbEdsQ2hhbm5lbHNbcmFuayAtIDJdfSwgYCArXG4gICAgICAnaSoyJztcbiAgcmV0dXJuIHJlcztcbn1cblxuZnVuY3Rpb24gZ2V0QihhbGxHbENoYW5uZWxzOiBzdHJpbmdbXSwgcmFuazogbnVtYmVyKTogc3RyaW5nIHtcbiAgbGV0IHJlcyA9ICcnO1xuICBmb3IgKGxldCBpID0gMDsgaSA8IHJhbmsgLSAyOyBpKyspIHtcbiAgICByZXMgKz0gYHJjLiR7YWxsR2xDaGFubmVsc1tpXX0sIGA7XG4gIH1cbiAgcmVzICs9ICdpKjIsICcgK1xuICAgICAgYHJjLiR7YWxsR2xDaGFubmVsc1tyYW5rIC0gMV19YDtcbiAgcmV0dXJuIHJlcztcbn1cbiIsIi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxuXG5pbXBvcnQge0dyYXBofSBmcm9tICcuLi8uLi8uLi9ncmFwaCc7XG5pbXBvcnQge09wZXJhdG9ySW1wbGVtZW50YXRpb24sIE9wZXJhdG9ySW5pdGlhbGl6YXRpb259IGZyb20gJy4uLy4uLy4uL29wZXJhdG9ycyc7XG5pbXBvcnQge1RlbnNvcn0gZnJvbSAnLi4vLi4vLi4vdGVuc29yJztcbmltcG9ydCB7QnJvYWRjYXN0VXRpbCwgU2hhcGVVdGlsfSBmcm9tICcuLi8uLi8uLi91dGlsJztcbmltcG9ydCB7V2ViR0xJbmZlcmVuY2VIYW5kbGVyfSBmcm9tICcuLi9pbmZlcmVuY2UtaGFuZGxlcic7XG5pbXBvcnQge1Byb2dyYW1JbmZvLCBQcm9ncmFtSW5mb0xvYWRlciwgUHJvZ3JhbU1ldGFkYXRhLCBUZXh0dXJlVHlwZX0gZnJvbSAnLi4vdHlwZXMnO1xuaW1wb3J0IHtnZXRDb29yZHNEYXRhVHlwZSwgZ2V0R2xDaGFubmVsc30gZnJvbSAnLi4vdXRpbHMnO1xuXG5pbXBvcnQge2dldEFjdGl2YXRpb25TbmlwcGV0LCBJbnRlcm5hbEFjdGl2YXRpb25BdHRyaWJ1dGVzLCBwYXJzZUludGVybmFsQWN0aXZhdGlvbkF0dHJpYnV0ZXN9IGZyb20gJy4vZnVzZS11dGlscyc7XG5pbXBvcnQge2NyZWF0ZVBhY2tlZE1hdG11bFByb2dyYW1JbmZvTG9hZGVyfSBmcm9tICcuL21hdG11bC1wYWNrJztcblxuZXhwb3J0IGNvbnN0IG1hdE11bDogT3BlcmF0b3JJbXBsZW1lbnRhdGlvbjxJbnRlcm5hbEFjdGl2YXRpb25BdHRyaWJ1dGVzPiA9XG4gICAgKGluZmVyZW5jZUhhbmRsZXI6IFdlYkdMSW5mZXJlbmNlSGFuZGxlciwgaW5wdXRzOiBUZW5zb3JbXSwgYXR0cmlidXRlczogSW50ZXJuYWxBY3RpdmF0aW9uQXR0cmlidXRlcyk6IFRlbnNvcltdID0+IHtcbiAgICAgIHZhbGlkYXRlSW5wdXRzKGlucHV0cyk7XG5cbiAgICAgIGlmIChpbmZlcmVuY2VIYW5kbGVyLnNlc3Npb24ucGFjaykge1xuICAgICAgICByZXR1cm4gW2luZmVyZW5jZUhhbmRsZXIucnVuKFxuICAgICAgICAgICAgY3JlYXRlUGFja2VkTWF0bXVsUHJvZ3JhbUluZm9Mb2FkZXIoaW5mZXJlbmNlSGFuZGxlciwgaW5wdXRzLCBhdHRyaWJ1dGVzKSwgaW5wdXRzKV07XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4gW2luZmVyZW5jZUhhbmRsZXIucnVuKGNyZWF0ZU1hdG11bFByb2dyYW1JbmZvTG9hZGVyKGlucHV0cywgYXR0cmlidXRlcyksIGlucHV0cyldO1xuICAgICAgfVxuICAgIH07XG5cbmV4cG9ydCBjb25zdCBwYXJzZU1hdE11bEF0dHJpYnV0ZXM6IE9wZXJhdG9ySW5pdGlhbGl6YXRpb248SW50ZXJuYWxBY3RpdmF0aW9uQXR0cmlidXRlcz4gPVxuICAgIChub2RlOiBHcmFwaC5Ob2RlKTogSW50ZXJuYWxBY3RpdmF0aW9uQXR0cmlidXRlcyA9PiBwYXJzZUludGVybmFsQWN0aXZhdGlvbkF0dHJpYnV0ZXMobm9kZS5hdHRyaWJ1dGVzKTtcblxuY29uc3QgY3JlYXRlTWF0bXVsUHJvZ3JhbU1ldGFkYXRhID0gKGhhc0JpYXM6IGJvb2xlYW4sIGNhY2hlSGludDogc3RyaW5nKSA9PiAoe1xuICBuYW1lOiAnTWF0TXVsJyxcbiAgaW5wdXROYW1lczogaGFzQmlhcyA/IFsnQScsICdCJywgJ0JpYXMnXSA6IFsnQScsICdCJ10sXG4gIGlucHV0VHlwZXM6IGhhc0JpYXMgPyBbVGV4dHVyZVR5cGUudW5wYWNrZWQsIFRleHR1cmVUeXBlLnVucGFja2VkLCBUZXh0dXJlVHlwZS51bnBhY2tlZF0gOlxuICAgICAgICAgICAgICAgICAgICAgICAgW1RleHR1cmVUeXBlLnVucGFja2VkLCBUZXh0dXJlVHlwZS51bnBhY2tlZF0sXG4gIGNhY2hlSGludFxufSk7XG5cbmZ1bmN0aW9uIGNyZWF0ZU1hdG11bFByb2dyYW1JbmZvKFxuICAgIG1ldGFkYXRhOiBQcm9ncmFtTWV0YWRhdGEsIGlucHV0czogVGVuc29yW10sIGFjdGl2YXRpb25BdHRyaWJ1dGVzOiBJbnRlcm5hbEFjdGl2YXRpb25BdHRyaWJ1dGVzKTogUHJvZ3JhbUluZm8ge1xuICBjb25zdCBhU2hhcGUgPSBpbnB1dHNbMF0uZGltcztcbiAgY29uc3QgYlNoYXBlID0gaW5wdXRzWzFdLmRpbXM7XG4gIGNvbnN0IG91dHB1dFNoYXBlID0gQnJvYWRjYXN0VXRpbC5jYWxjU2hhcGUoYVNoYXBlLCBiU2hhcGUsIHRydWUpO1xuICBpZiAoIW91dHB1dFNoYXBlKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdDYW5cXCd0IHVzZSBtYXRtdWwgb24gdGhlIGdpdmVuIHRlbnNvcnMnKTtcbiAgfVxuICBjb25zdCBjb29yZHNEYXRhVHlwZSA9IGdldENvb3Jkc0RhdGFUeXBlKG91dHB1dFNoYXBlLmxlbmd0aCk7XG4gIGNvbnN0IGFsbEdsQ2hhbm5lbHMgPSBnZXRHbENoYW5uZWxzKCk7XG4gIGNvbnN0IHthY3RpdmF0aW9uRnVuY3Rpb24sIGFwcGx5QWN0aXZhdGlvbn0gPSBnZXRBY3RpdmF0aW9uU25pcHBldChhY3RpdmF0aW9uQXR0cmlidXRlcyk7XG5cbiAgY29uc3QgaGFzQmlhcyA9IGlucHV0cy5sZW5ndGggPiAyO1xuICBjb25zdCBwcm9jZXNzQmlhcyA9IGhhc0JpYXMgPyAndmFsdWUgKz0gZ2V0Qmlhc0Zvck1hdG11bCgpOycgOiAnJztcbiAgY29uc3QgZ2V0Qmlhc0Zvck1hdG11bFNuaXBwZXQgPVxuICAgICAgaGFzQmlhcyA/IGAke2dldEJpYXNGb3JNYXRtdWwoY29vcmRzRGF0YVR5cGUsIGFsbEdsQ2hhbm5lbHMsIGlucHV0c1syXS5kaW1zLCBvdXRwdXRTaGFwZSwgZmFsc2UpfWAgOiAnJztcblxuICBjb25zdCByYW5rID0gb3V0cHV0U2hhcGUubGVuZ3RoO1xuICBjb25zdCBhcmFuayA9IGFTaGFwZS5sZW5ndGg7XG4gIGNvbnN0IGJyYW5rID0gYlNoYXBlLmxlbmd0aDtcbiAgY29uc3Qgc2hhcmVkRGltID0gYVNoYXBlW2FTaGFwZS5sZW5ndGggLSAxXTtcbiAgY29uc3Qgc2hhZGVyU291cmNlID0gYFxuICAgICR7YWN0aXZhdGlvbkZ1bmN0aW9ufVxuICAgICR7Z2V0Qmlhc0Zvck1hdG11bFNuaXBwZXR9XG4gICAgZmxvYXQgcHJvY2VzcyhpbnQgaW5kaWNlc1ske3Jhbmt9XSkge1xuICAgICAgICBpbnQgYVske2FyYW5rfV07XG4gICAgICAgIGludCBiWyR7YnJhbmt9XTtcbiAgICAgICAgYmNhc3RNYXRtdWxJbmRpY2VzX0EoaW5kaWNlcywgYSk7XG4gICAgICAgIGJjYXN0TWF0bXVsSW5kaWNlc19CKGluZGljZXMsIGIpO1xuXG4gICAgICAgIGZsb2F0IHZhbHVlO1xuICAgICAgICBmb3IgKGludCBrPTA7IGs8JHtzaGFyZWREaW19OyArK2spIHtcbiAgICAgICAgICAgIGFbJHthcmFuayAtIDF9XSA9IGs7XG4gICAgICAgICAgICBiWyR7YnJhbmsgLSAyfV0gPSBrO1xuICAgICAgICAgICAgdmFsdWUgKz0gX0EoYSkgKiBfQihiKTtcbiAgICAgICAgfVxuICAgICAgICAke3Byb2Nlc3NCaWFzfVxuICAgICAgICAke2FwcGx5QWN0aXZhdGlvbn1cbiAgICAgICAgcmV0dXJuIHZhbHVlO1xuICAgIH1gO1xuICByZXR1cm4ge1xuICAgIC4uLm1ldGFkYXRhLFxuICAgIG91dHB1dDoge2RpbXM6IG91dHB1dFNoYXBlLCB0eXBlOiBpbnB1dHNbMF0udHlwZSwgdGV4dHVyZVR5cGU6IFRleHR1cmVUeXBlLnVucGFja2VkfSxcbiAgICBzaGFkZXJTb3VyY2UsXG4gIH07XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVNYXRtdWxQcm9ncmFtSW5mb0xvYWRlcihcbiAgICBpbnB1dHM6IFRlbnNvcltdLCBhY3RpdmF0aW9uQXR0cmlidXRlczogSW50ZXJuYWxBY3RpdmF0aW9uQXR0cmlidXRlcyk6IFByb2dyYW1JbmZvTG9hZGVyIHtcbiAgY29uc3QgbWV0YWRhdGEgPSBjcmVhdGVNYXRtdWxQcm9ncmFtTWV0YWRhdGEoaW5wdXRzLmxlbmd0aCA+IDIsIGFjdGl2YXRpb25BdHRyaWJ1dGVzLmFjdGl2YXRpb25DYWNoZUtleSk7XG4gIHJldHVybiB7Li4ubWV0YWRhdGEsIGdldDogKCkgPT4gY3JlYXRlTWF0bXVsUHJvZ3JhbUluZm8obWV0YWRhdGEsIGlucHV0cywgYWN0aXZhdGlvbkF0dHJpYnV0ZXMpfTtcbn1cblxuY29uc3QgdmFsaWRhdGVJbnB1dHMgPSAoaW5wdXRzOiBUZW5zb3JbXSk6IHZvaWQgPT4ge1xuICBpZiAoIWlucHV0cyB8fCBpbnB1dHMubGVuZ3RoICE9PSAyKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdNYXRNdWwgcmVxdWlyZXMgMiBpbnB1dHMuJyk7XG4gIH1cblxuICBpZiAoaW5wdXRzWzBdLmRpbXNbaW5wdXRzWzBdLmRpbXMubGVuZ3RoIC0gMV0gIT09IGlucHV0c1sxXS5kaW1zW2lucHV0c1sxXS5kaW1zLmxlbmd0aCAtIDJdKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdzaGFyZWQgZGltZW5zaW9uIGRvZXMgbm90IG1hdGNoLicpO1xuICB9XG5cbiAgaWYgKChpbnB1dHNbMF0udHlwZSAhPT0gJ2Zsb2F0MzInICYmIGlucHV0c1swXS50eXBlICE9PSAnZmxvYXQ2NCcpIHx8XG4gICAgICAoaW5wdXRzWzFdLnR5cGUgIT09ICdmbG9hdDMyJyAmJiBpbnB1dHNbMV0udHlwZSAhPT0gJ2Zsb2F0NjQnKSkge1xuICAgIHRocm93IG5ldyBFcnJvcignaW5wdXRzIHNob3VsZCBiZSBmbG9hdCB0eXBlJyk7XG4gIH1cblxuICBpZiAoaW5wdXRzWzBdLnR5cGUgIT09IGlucHV0c1sxXS50eXBlKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdpbnB1dHMgdHlwZXMgc2hvdWxkIG1hdGNoJyk7XG4gIH1cbn07XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRCaWFzRm9yTWF0bXVsKFxuICAgIGNvb3Jkc0RhdGFUeXBlOiBzdHJpbmcsIGFsbEdsQ2hhbm5lbHM6IHJlYWRvbmx5IHN0cmluZ1tdLCBpblNoYXBlOiByZWFkb25seSBudW1iZXJbXSwgb3V0U2hhcGU6IHJlYWRvbmx5IG51bWJlcltdLFxuICAgIGlzUGFja2VkOiBib29sZWFuKTogc3RyaW5nIHtcbiAgbGV0IHVucGFja2VkQ29vcmRzU25pcHBldCA9ICcnO1xuICBjb25zdCBpblJhbmsgPSBpblNoYXBlLmxlbmd0aDtcbiAgY29uc3Qgb3V0UmFuayA9IG91dFNoYXBlLmxlbmd0aDtcbiAgY29uc3QgcmFua0RpZmYgPSBvdXRSYW5rIC0gaW5SYW5rO1xuICBpZiAob3V0UmFuayA8IDIgJiYgaW5SYW5rID4gMCkge1xuICAgIHVucGFja2VkQ29vcmRzU25pcHBldCA9ICdjb29yZHMnO1xuICB9IGVsc2Uge1xuICAgIHVucGFja2VkQ29vcmRzU25pcHBldCA9IGluU2hhcGUubWFwKChzLCBpKSA9PiBgY29vcmRzLiR7YWxsR2xDaGFubmVsc1tpICsgcmFua0RpZmZdfWApLmpvaW4oJywgJyk7XG4gIH1cbiAgY29uc3QgYnJvYWRjYXN0RGltcyA9IEJyb2FkY2FzdFV0aWwuZ2V0QnJvYWRjYXN0RGltcyhpblNoYXBlLCBvdXRTaGFwZSk7XG4gIGNvbnN0IGNvb3Jkc1NuaXBwZXQgPSBicm9hZGNhc3REaW1zLm1hcChkID0+IGBjb29yZHMuJHthbGxHbENoYW5uZWxzW2QgKyByYW5rRGlmZl19ID0gMDtgKS5qb2luKCdcXG4nKTtcbiAgY29uc3QgaW5TaXplID0gU2hhcGVVdGlsLnNpemUoaW5TaGFwZSk7XG4gIGNvbnN0IGlzSW5wdXRTY2FsYXIgPSBpblNpemUgPT09IDE7XG4gIGxldCBvdXRwdXQgPSAndmVjNChvdXRwdXRWYWx1ZS54eCwgb3V0cHV0VmFsdWUueXkpJztcbiAgaWYgKGlzSW5wdXRTY2FsYXIpIHtcbiAgICBvdXRwdXQgPSAndmVjNChvdXRwdXRWYWx1ZS54KSc7XG4gIH1cbiAgY29uc3QgZ2V0Qmlhc0Zvck1hdG11bFNvdXJjZSA9IGlzUGFja2VkID8gYFxudmVjNCBnZXRCaWFzRm9yTWF0bXVsKCkge1xuICAke2Nvb3Jkc0RhdGFUeXBlfSBjb29yZHMgPSBnZXRPdXRwdXRDb29yZHMoKTtcbiAgJHtjb29yZHNTbmlwcGV0fVxuICB2ZWM0IG91dHB1dFZhbHVlID0gZ2V0Qmlhcygke3VucGFja2VkQ29vcmRzU25pcHBldH0pO1xuICByZXR1cm4gJHtvdXRwdXR9O1xufWAgOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBgXG5mbG9hdCBnZXRCaWFzRm9yTWF0bXVsKCkge1xuICAke2Nvb3Jkc0RhdGFUeXBlfSBjb29yZHMgPSBnZXRPdXRwdXRDb29yZHMoKTtcbiAgJHtjb29yZHNTbmlwcGV0fVxuICByZXR1cm4gZ2V0Qmlhcyhjb29yZHMueCk7XG59YDtcblxuICByZXR1cm4gZ2V0Qmlhc0Zvck1hdG11bFNvdXJjZTtcbn1cbiIsIi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxuXG5pbXBvcnQge1RlbnNvcn0gZnJvbSAnLi4vLi4vLi4vdGVuc29yJztcbmltcG9ydCB7Z2V0R2xzbH0gZnJvbSAnLi4vZ2xzbC1zb3VyY2UnO1xuaW1wb3J0IHtXZWJHTEluZmVyZW5jZUhhbmRsZXJ9IGZyb20gJy4uL2luZmVyZW5jZS1oYW5kbGVyJztcbmltcG9ydCB7UHJvZ3JhbUluZm8sIFByb2dyYW1JbmZvTG9hZGVyLCBUZXh0dXJlVHlwZX0gZnJvbSAnLi4vdHlwZXMnO1xuaW1wb3J0IHtnZXRDb29yZHNEYXRhVHlwZX0gZnJvbSAnLi4vdXRpbHMnO1xuXG5pbXBvcnQge2dldENoYW5uZWxzfSBmcm9tICcuL3BhY2tpbmctdXRpbHMnO1xuXG5jb25zdCBwYWNrUHJvZ3JhbU1ldGFkYXRhID0ge1xuICBuYW1lOiAncGFjaycsXG4gIGlucHV0TmFtZXM6IFsnQSddLFxuICBpbnB1dFR5cGVzOiBbVGV4dHVyZVR5cGUudW5wYWNrZWRSZXZlcnNlZF1cbn07XG5cbmNvbnN0IGNyZWF0ZVBhY2tQcm9ncmFtSW5mbyA9IChoYW5kbGVyOiBXZWJHTEluZmVyZW5jZUhhbmRsZXIsIGlucHV0OiBUZW5zb3IpOiBQcm9ncmFtSW5mbyA9PiB7XG4gIGNvbnN0IGdsc2wgPSBnZXRHbHNsKGhhbmRsZXIuc2Vzc2lvbi5iYWNrZW5kLmdsQ29udGV4dC52ZXJzaW9uKTtcbiAgY29uc3QgaW5wdXRTaGFwZSA9IGlucHV0LmRpbXM7XG5cbiAgY29uc3QgaW5wdXRSYW5rID0gaW5wdXRTaGFwZS5sZW5ndGg7XG4gIC8vIGNyZWF0ZVRleHR1cmVMYXlvdXRGcm9tU2hhcGUgd29uJ3QgY2hhbmdlIG91dHB1dCByYW5rLiBOZWVkIHRvIHZlcmlmeSBieSBydW5uaW5nIHRlc3RzXG4gIGNvbnN0IG91dHB1dFJhbmsgPSBpbnB1dC5kaW1zLmxlbmd0aDtcblxuICBjb25zdCBjb29yZHNEYXRhVHlwZSA9IGdldENvb3Jkc0RhdGFUeXBlKG91dHB1dFJhbmspO1xuICBjb25zdCBjaGFubmVscyA9IGdldENoYW5uZWxzKCdyYycsIG91dHB1dFJhbmspO1xuICBjb25zdCBzZXR1cCA9IGdldFNldHVwKG91dHB1dFJhbmssIGNoYW5uZWxzLCBpbnB1dFNoYXBlW2lucHV0U2hhcGUubGVuZ3RoIC0gMl0sIGlucHV0U2hhcGVbaW5wdXRTaGFwZS5sZW5ndGggLSAxXSk7XG5cbiAgbGV0IHJldmVyc2VkSW5wdXRXSDtcbiAgaWYgKGlucHV0UmFuayA9PT0gMCkge1xuICAgIHJldmVyc2VkSW5wdXRXSCA9IFsxLCAxXTtcbiAgfSBlbHNlIGlmIChpbnB1dFJhbmsgPT09IDEpIHtcbiAgICByZXZlcnNlZElucHV0V0ggPSBbaW5wdXRTaGFwZVswXSwgMV07XG4gIH0gZWxzZSB7XG4gICAgcmV2ZXJzZWRJbnB1dFdIID0gW2lucHV0U2hhcGVbb3V0cHV0UmFuayAtIDFdLCBpbnB1dFNoYXBlW291dHB1dFJhbmsgLSAyXV07XG4gIH1cbiAgY29uc3Qgb3V0T2ZCb3VuZHNDb25kaXRpb24gPSBnZXRPdXRPZkJvdW5kc0NvbmRpdGlvbihvdXRwdXRSYW5rLCByZXZlcnNlZElucHV0V0gsIGNoYW5uZWxzKTtcbiAgY29uc3Qgb3V0cHV0ID0gZ2V0T3V0cHV0KGlucHV0U2hhcGUsIGNoYW5uZWxzKTtcblxuICBjb25zdCBzaGFkZXJTb3VyY2UgPSBgXG4gICAgICAgIHZvaWQgbWFpbigpIHtcbiAgICAgICAgICAke2Nvb3Jkc0RhdGFUeXBlfSByYyA9IGdldE91dHB1dENvb3JkcygpO1xuXG4gICAgICAgICAgaWYoJHtvdXRPZkJvdW5kc0NvbmRpdGlvbn0pIHtcbiAgICAgICAgICAgICR7Z2xzbC5vdXRwdXR9ID0gdmVjNCgwKTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgJHtzZXR1cH1cblxuICAgICAgICAgICAgJHtnbHNsLm91dHB1dH0gPSB2ZWM0KCR7b3V0cHV0fSk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICBgO1xuICByZXR1cm4ge1xuICAgIC4uLnBhY2tQcm9ncmFtTWV0YWRhdGEsXG4gICAgaGFzTWFpbjogdHJ1ZSxcbiAgICBvdXRwdXQ6IHtkaW1zOiBpbnB1dC5kaW1zLCB0eXBlOiBpbnB1dC50eXBlLCB0ZXh0dXJlVHlwZTogVGV4dHVyZVR5cGUucGFja2VkfSxcbiAgICBzaGFkZXJTb3VyY2VcbiAgfTtcbn07XG5cbmV4cG9ydCBjb25zdCBjcmVhdGVQYWNrUHJvZ3JhbUluZm9Mb2FkZXIgPSAoaGFuZGxlcjogV2ViR0xJbmZlcmVuY2VIYW5kbGVyLCBpbnB1dDogVGVuc29yKTogUHJvZ3JhbUluZm9Mb2FkZXIgPT5cbiAgICAoey4uLnBhY2tQcm9ncmFtTWV0YWRhdGEsIGdldDogKCkgPT4gY3JlYXRlUGFja1Byb2dyYW1JbmZvKGhhbmRsZXIsIGlucHV0KX0pO1xuXG4vKipcbiAqIGNoZWNrIG91dHB1dCBjb29yZGluYXRlIGxvY2F0aW9uIGFuZCByZXR1cm4gZmFsc2UgaWYgaXQgaXMgb3V0c2lkZSBpbnB1dCdzIHdpZHRoL2hlaWdodCBib3VuZGFyeVxuICovXG5mdW5jdGlvbiBnZXRPdXRPZkJvdW5kc0NvbmRpdGlvbihyYW5rOiBudW1iZXIsIHNoYXBlOiByZWFkb25seSBudW1iZXJbXSwgZGltczogc3RyaW5nW10pOiBzdHJpbmcge1xuICBpZiAocmFuayA9PT0gMCkge1xuICAgIHJldHVybiAnZmFsc2UnO1xuICB9XG4gIGlmIChyYW5rID09PSAxKSB7XG4gICAgcmV0dXJuIGByYyA+ICR7c2hhcGVbMF19YDtcbiAgfVxuXG4gIGxldCBjb25kID0gJyc7XG4gIGZvciAobGV0IGkgPSByYW5rIC0gMjsgaSA8IHJhbms7IGkrKykge1xuICAgIGNvbmQgKz0gYCR7ZGltc1tpXX0gPj0gJHtzaGFwZVtpIC0gcmFuayArIDJdfWA7XG4gICAgaWYgKGkgPCByYW5rIC0gMSkge1xuICAgICAgY29uZCArPSAnfHwnO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBjb25kO1xufVxuXG4vKipcbiAqIGNvZGUgc25pcHBldCB0byBzYW1wbGUgaW5wdXQgdGV4dHVyZSB3aXRoIG91dHB1dCBjb29yZGlhbnRlc1xuICovXG5mdW5jdGlvbiBnZXRPdXRwdXQoc2hhcGU6IHJlYWRvbmx5IG51bWJlcltdLCBkaW1zOiBzdHJpbmdbXSk6IHN0cmluZyB7XG4gIGNvbnN0IHJhbmsgPSBzaGFwZS5sZW5ndGg7XG5cbiAgaWYgKHJhbmsgPT09IDApIHtcbiAgICByZXR1cm4gJ2dldEEoKSwgMCwgMCwgMCc7XG4gIH1cblxuICBpZiAocmFuayA9PT0gMSkge1xuICAgIHJldHVybiBgZ2V0QShyYyksXG4gICAgICAgICAgICByYyArIDEgPj0gJHtzaGFwZVswXX0gPyAwLiA6IGdldEEocmMgKyAxKSxcbiAgICAgICAgICAgIDAsIDBgO1xuICB9XG5cbiAgY29uc3QgY29vcmQwMCA9ICdyLCBjJztcbiAgY29uc3QgY29vcmQwMSA9ICdyLCBjcDEnO1xuICBjb25zdCBjb29yZDEwID0gJ3JwMSwgYyc7XG4gIGNvbnN0IGNvb3JkMTEgPSAncnAxLCBjcDEnO1xuICBsZXQgRCA9ICcnO1xuICBpZiAocmFuayA+IDIpIHtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHJhbmsgLSAyOyArK2kpIHtcbiAgICAgIEQgPSBEICsgYCR7ZGltc1tpXX0sYDtcbiAgICB9XG4gIH1cbiAgcmV0dXJuIGBnZXRBKCR7RH0ke2Nvb3JkMDB9KSxcbiAgICAgICAgICByRWRnZSA/IDAuIDogZ2V0QSgke0R9JHtjb29yZDEwfSksXG4gICAgICAgICAgY0VkZ2UgPyAwLiA6IGdldEEoJHtEfSR7Y29vcmQwMX0pLFxuICAgICAgICAgIHJFZGdlIHx8IGNFZGdlID8gMC4gOiBnZXRBKCR7RH0ke2Nvb3JkMTF9KWA7XG59XG5cbi8qKlxuICogY29kZSBzbmlwcGV0IHRvIHNldHVwIDQgY29vcmRpbmF0ZXMgYW5kIGVkZ2UgY29uZGl0aW9uc1xuICovXG5mdW5jdGlvbiBnZXRTZXR1cChyYW5rOiBudW1iZXIsIGRpbXM6IHN0cmluZ1tdLCByb3dzOiBudW1iZXIsIGNvbHM6IG51bWJlcik6IHN0cmluZyB7XG4gIGlmIChyYW5rID09PSAwIHx8IHJhbmsgPT09IDEpIHtcbiAgICByZXR1cm4gJyc7XG4gIH1cbiAgLy8gcmFuayA+PSAyIGZvciB3aWR0aCtoZWlnaHQgcGFjay5cbiAgZWxzZSB7XG4gICAgY29uc3Qgc2V0dXAgPSBgXG4gICAgaW50IHIgPSAke2RpbXNbcmFuayAtIDJdfTtcbiAgICBpbnQgYyA9ICR7ZGltc1tyYW5rIC0gMV19O1xuICAgIGludCBycDEgPSAke2RpbXNbcmFuayAtIDJdfSArIDE7XG4gICAgaW50IGNwMSA9ICR7ZGltc1tyYW5rIC0gMV19ICsgMTtcbiAgICBib29sIHJFZGdlID0gcnAxID49ICR7Y29sc307XG4gICAgYm9vbCBjRWRnZSA9IGNwMSA+PSAke3Jvd3N9O1xuICAgIGA7XG4gICAgcmV0dXJuIHNldHVwO1xuICB9XG59XG4iLCIvLyBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cblxuaW1wb3J0IHtnZXRHbENoYW5uZWxzfSBmcm9tICcuLi91dGlscyc7XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRWZWNDaGFubmVscyhuYW1lOiBzdHJpbmcsIHJhbms6IG51bWJlcik6IHN0cmluZ1tdIHtcbiAgcmV0dXJuIGdldEdsQ2hhbm5lbHMocmFuaykubWFwKGQgPT4gYCR7bmFtZX0uJHtkfWApO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZ2V0Q2hhbm5lbHMobmFtZTogc3RyaW5nLCByYW5rOiBudW1iZXIpOiBzdHJpbmdbXSB7XG4gIGlmIChyYW5rID09PSAxKSB7XG4gICAgcmV0dXJuIFtuYW1lXTtcbiAgfVxuICByZXR1cm4gZ2V0VmVjQ2hhbm5lbHMobmFtZSwgcmFuayk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiB1bnBhY2tGcm9tQ2hhbm5lbCgpOiBzdHJpbmcge1xuICByZXR1cm4gYFxuICAgIGZsb2F0IGdldENoYW5uZWwodmVjNCBmcmFnLCBpbnQgZGltKSB7XG4gICAgICBpbnQgbW9kQ29vcmQgPSBpbW9kKGRpbSwgMik7XG4gICAgICByZXR1cm4gbW9kQ29vcmQgPT0gMCA/IGZyYWcuciA6IGZyYWcuZztcbiAgICB9XG5cbiAgICBmbG9hdCBnZXRDaGFubmVsKHZlYzQgZnJhZywgdmVjMiBpbm5lckRpbXMpIHtcbiAgICAgIHZlYzIgbW9kQ29vcmQgPSBtb2QoaW5uZXJEaW1zLCAyLik7XG4gICAgICByZXR1cm4gbW9kQ29vcmQueCA9PSAwLiA/XG4gICAgICAgIChtb2RDb29yZC55ID09IDAuID8gZnJhZy5yIDogZnJhZy5nKSA6XG4gICAgICAgIChtb2RDb29yZC55ID09IDAuID8gZnJhZy5iIDogZnJhZy5hKTtcbiAgICB9XG4gIGA7XG59XG4iLCIvLyBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cblxuaW1wb3J0IHtBdHRyaWJ1dGVXaXRoQ2FjaGVLZXksIGNyZWF0ZUF0dHJpYnV0ZVdpdGhDYWNoZUtleX0gZnJvbSAnLi4vLi4vLi4vYXR0cmlidXRlLXdpdGgtY2FjaGUta2V5JztcbmltcG9ydCB7R3JhcGh9IGZyb20gJy4uLy4uLy4uL2dyYXBoJztcbmltcG9ydCB7T3BlcmF0b3JJbXBsZW1lbnRhdGlvbiwgT3BlcmF0b3JJbml0aWFsaXphdGlvbn0gZnJvbSAnLi4vLi4vLi4vb3BlcmF0b3JzJztcbmltcG9ydCB7VGVuc29yfSBmcm9tICcuLi8uLi8uLi90ZW5zb3InO1xuaW1wb3J0IHtTaGFwZVV0aWx9IGZyb20gJy4uLy4uLy4uL3V0aWwnO1xuaW1wb3J0IHtnZXRHbHNsLCBHbHNsfSBmcm9tICcuLi9nbHNsLXNvdXJjZSc7XG5pbXBvcnQge1dlYkdMSW5mZXJlbmNlSGFuZGxlcn0gZnJvbSAnLi4vaW5mZXJlbmNlLWhhbmRsZXInO1xuaW1wb3J0IHtQcm9ncmFtSW5mbywgVGV4dHVyZVR5cGV9IGZyb20gJy4uL3R5cGVzJztcblxuZXhwb3J0IGludGVyZmFjZSBQYWRBdHRyaWJ1dGVzIGV4dGVuZHMgQXR0cmlidXRlV2l0aENhY2hlS2V5IHtcbiAgcmVhZG9ubHkgbW9kZTogc3RyaW5nO1xuICByZWFkb25seSBwYWRzOiBudW1iZXJbXTtcbiAgcmVhZG9ubHkgdmFsdWU6IG51bWJlcjtcbn1cblxuY29uc3QgcGFkUHJvZ3JhbU1ldGFkYXRhID0ge1xuICBuYW1lOiAnUGFkJyxcbiAgaW5wdXROYW1lczogWydBJ10sXG4gIGlucHV0VHlwZXM6IFtUZXh0dXJlVHlwZS51bnBhY2tlZF0sXG59O1xuXG5leHBvcnQgY29uc3QgcGFkVjI6IE9wZXJhdG9ySW1wbGVtZW50YXRpb248UGFkQXR0cmlidXRlcz4gPVxuICAgIChpbmZlcmVuY2VIYW5kbGVyOiBXZWJHTEluZmVyZW5jZUhhbmRsZXIsIGlucHV0czogVGVuc29yW10sIGF0dHJpYnV0ZXM6IFBhZEF0dHJpYnV0ZXMpOiBUZW5zb3JbXSA9PiB7XG4gICAgICB2YWxpZGF0ZUlucHV0c1YyKGlucHV0cyk7XG4gICAgICBjb25zdCBvdXRwdXQgPSBpbmZlcmVuY2VIYW5kbGVyLnJ1bihcbiAgICAgICAgICB7XG4gICAgICAgICAgICAuLi5wYWRQcm9ncmFtTWV0YWRhdGEsXG4gICAgICAgICAgICBjYWNoZUhpbnQ6IGF0dHJpYnV0ZXMuY2FjaGVLZXksXG4gICAgICAgICAgICBnZXQ6ICgpID0+IGNyZWF0ZVBhZFByb2dyYW1JbmZvKGluZmVyZW5jZUhhbmRsZXIsIGlucHV0c1swXSwgYXR0cmlidXRlcylcbiAgICAgICAgICB9LFxuICAgICAgICAgIGlucHV0cyk7XG4gICAgICByZXR1cm4gW291dHB1dF07XG4gICAgfTtcblxuZXhwb3J0IGNvbnN0IHBhcnNlUGFkQXR0cmlidXRlc1YyOiBPcGVyYXRvckluaXRpYWxpemF0aW9uPFBhZEF0dHJpYnV0ZXM+ID0gKG5vZGU6IEdyYXBoLk5vZGUpOiBQYWRBdHRyaWJ1dGVzID0+IHtcbiAgY29uc3QgbW9kZSA9IG5vZGUuYXR0cmlidXRlcy5nZXRTdHJpbmcoJ21vZGUnLCAnY29uc3RhbnQnKTtcbiAgY29uc3QgdmFsdWUgPSBub2RlLmF0dHJpYnV0ZXMuZ2V0RmxvYXQoJ3ZhbHVlJywgMC4wKTtcbiAgY29uc3QgcGFkcyA9IG5vZGUuYXR0cmlidXRlcy5nZXRJbnRzKCdwYWRzJyk7XG4gIHJldHVybiBjcmVhdGVBdHRyaWJ1dGVXaXRoQ2FjaGVLZXkoe21vZGUsIHZhbHVlLCBwYWRzfSk7XG59O1xuXG5leHBvcnQgY29uc3QgcGFkVjExOiBPcGVyYXRvckltcGxlbWVudGF0aW9uPHN0cmluZz4gPVxuICAgIChpbmZlcmVuY2VIYW5kbGVyOiBXZWJHTEluZmVyZW5jZUhhbmRsZXIsIGlucHV0czogVGVuc29yW10sIG1vZGU6IHN0cmluZyk6IFRlbnNvcltdID0+IHtcbiAgICAgIHZhbGlkYXRlSW5wdXRzVjExKGlucHV0cyk7XG4gICAgICBjb25zdCBhdHRydWJ1dGVzID0gZ2VuZXJhdGVQYWRBdHRyaWJ1dGVzRnJvbUlucHV0cyhpbmZlcmVuY2VIYW5kbGVyLCBpbnB1dHMsIG1vZGUpO1xuICAgICAgcmV0dXJuIHBhZFYyKGluZmVyZW5jZUhhbmRsZXIsIFtpbnB1dHNbMF1dLCBhdHRydWJ1dGVzKTtcbiAgICB9O1xuXG5leHBvcnQgY29uc3QgcGFyc2VQYWRBdHRyaWJ1dGVzVjExOiBPcGVyYXRvckluaXRpYWxpemF0aW9uPHN0cmluZz4gPSAobm9kZTogR3JhcGguTm9kZSk6IHN0cmluZyA9PlxuICAgIG5vZGUuYXR0cmlidXRlcy5nZXRTdHJpbmcoJ21vZGUnLCAnY29uc3RhbnQnKTtcblxuY29uc3QgZ2VuZXJhdGVQYWRBdHRyaWJ1dGVzRnJvbUlucHV0cyA9XG4gICAgKGluZmVyZW5jZUhhbmRsZXI6IFdlYkdMSW5mZXJlbmNlSGFuZGxlciwgaW5wdXRzOiBUZW5zb3JbXSwgbW9kZTogc3RyaW5nKTogUGFkQXR0cmlidXRlcyA9PiB7XG4gICAgICBpZiAoIWluZmVyZW5jZUhhbmRsZXIuc2Vzc2lvbi5pc0luaXRpYWxpemVyKGlucHV0c1sxXS5kYXRhSWQpIHx8XG4gICAgICAgICAgKGlucHV0cy5sZW5ndGggPj0gMyAmJiAhaW5mZXJlbmNlSGFuZGxlci5zZXNzaW9uLmlzSW5pdGlhbGl6ZXIoaW5wdXRzWzJdLmRhdGFJZCkpKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignZHluYW1pYyBwYWQgYXR0cmlidXRlcyBhcmUgbm90IGFsbG93ZWQnKTtcbiAgICAgIH1cblxuICAgICAgY29uc3QgcGFkcyA9IEFycmF5LmZyb20oaW5wdXRzWzFdLmludGVnZXJEYXRhKTtcbiAgICAgIGNvbnN0IHZhbHVlID0gKGlucHV0cy5sZW5ndGggPj0gMykgPyBpbnB1dHNbMl0uZmxvYXREYXRhWzBdIDogMC4wO1xuXG4gICAgICByZXR1cm4gY3JlYXRlQXR0cmlidXRlV2l0aENhY2hlS2V5KHttb2RlLCBwYWRzLCB2YWx1ZX0pO1xuICAgIH07XG5cbmNvbnN0IGNyZWF0ZVBhZFByb2dyYW1JbmZvID1cbiAgICAoaW5mZXJlbmNlSGFuZGxlcjogV2ViR0xJbmZlcmVuY2VIYW5kbGVyLCBpbnB1dDogVGVuc29yLCBhdHRyaWJ1dGVzOiBQYWRBdHRyaWJ1dGVzKTogUHJvZ3JhbUluZm8gPT4ge1xuICAgICAgY29uc3Qgb3V0cHV0U2hhcGUgPSBTaGFwZVV0aWwucGFkU2hhcGUoaW5wdXQuZGltcy5zbGljZSgpLCBhdHRyaWJ1dGVzLnBhZHMpO1xuICAgICAgY29uc3QgcmFuayA9IG91dHB1dFNoYXBlLmxlbmd0aDtcbiAgICAgIGNvbnN0IHBhZEZ1bmN0aW9uID0gZ2V0UGFkRnVuY3Rpb24oaW5mZXJlbmNlSGFuZGxlciwgaW5wdXQsIGF0dHJpYnV0ZXMpO1xuICAgICAgY29uc3Qgc2hhZGVyU291cmNlID0gYFxuICAgICAgJHtwYWRGdW5jdGlvbn1cbiAgICAgIGZsb2F0IHByb2Nlc3MoaW50WyR7cmFua31dIGluZGljZXMpIHtcbiAgICAgICAgICByZXR1cm4gcGFkQShpbmRpY2VzKTtcbiAgICAgIH1gO1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgbmFtZTogJ1BhZCcsXG4gICAgICAgIGlucHV0TmFtZXM6IFsnQSddLFxuICAgICAgICBpbnB1dFR5cGVzOiBbVGV4dHVyZVR5cGUudW5wYWNrZWRdLFxuICAgICAgICBvdXRwdXQ6IHtkaW1zOiBvdXRwdXRTaGFwZSwgdHlwZTogaW5wdXQudHlwZSwgdGV4dHVyZVR5cGU6IFRleHR1cmVUeXBlLnVucGFja2VkfSxcbiAgICAgICAgc2hhZGVyU291cmNlXG4gICAgICB9O1xuICAgIH07XG5cbmNvbnN0IHZhbGlkYXRlSW5wdXRzVjIgPSAoaW5wdXRzOiBUZW5zb3JbXSk6IHZvaWQgPT4ge1xuICBpZiAoIWlucHV0cyB8fCBpbnB1dHMubGVuZ3RoICE9PSAxKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdQYWQgcmVxdWlyZXMgMSBpbnB1dCcpO1xuICB9XG4gIGlmIChpbnB1dHNbMF0udHlwZSAhPT0gJ2Zsb2F0MzInICYmIGlucHV0c1swXS50eXBlICE9PSAnZmxvYXQ2NCcpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ0ludmFsaWQgaW5wdXQgdHlwZS4nKTtcbiAgfVxufTtcblxuY29uc3QgdmFsaWRhdGVJbnB1dHNWMTEgPSAoaW5wdXRzOiBUZW5zb3JbXSk6IHZvaWQgPT4ge1xuICBpZiAoIWlucHV0cyB8fCAoaW5wdXRzLmxlbmd0aCAhPT0gMiAmJiBpbnB1dHMubGVuZ3RoICE9PSAzKSkge1xuICAgIHRocm93IG5ldyBFcnJvcignUGFkIHJlcXVpcmVzIDIgb3IgMyBpbnB1dHMnKTtcbiAgfVxuICBpZiAoaW5wdXRzWzFdLnR5cGUgIT09ICdpbnQzMicpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ0ludmFsaWQgaW5wdXQgdHlwZS4nKTtcbiAgfVxuICBpZiAoaW5wdXRzLmxlbmd0aCA+PSAzICYmIGlucHV0c1syXS50eXBlID09PSAnc3RyaW5nJykge1xuICAgIHRocm93IG5ldyBFcnJvcignSW52YWxpZCBpbnB1dCB0eXBlLicpO1xuICB9XG59O1xuXG5jb25zdCBnZXRQYWRGdW5jdGlvbiA9IChpbmZlcmVuY2VIYW5kbGVyOiBXZWJHTEluZmVyZW5jZUhhbmRsZXIsIGlucHV0OiBUZW5zb3IsIGF0dHJpYnV0ZXM6IFBhZEF0dHJpYnV0ZXMpOiBzdHJpbmcgPT4ge1xuICBjb25zdCBnbHNsID0gZ2V0R2xzbChpbmZlcmVuY2VIYW5kbGVyLnNlc3Npb24uYmFja2VuZC5nbENvbnRleHQudmVyc2lvbik7XG4gIGNvbnN0IFt3aWR0aCwgaGVpZ2h0XSA9IGluZmVyZW5jZUhhbmRsZXIuY2FsY3VsYXRlVGV4dHVyZVdpZHRoQW5kSGVpZ2h0KGlucHV0LmRpbXMsIFRleHR1cmVUeXBlLnVucGFja2VkKTtcbiAgY29uc3Qgc3RyaWRlcyA9IFNoYXBlVXRpbC5jb21wdXRlU3RyaWRlcyhpbnB1dC5kaW1zKTtcblxuICBzd2l0Y2ggKGF0dHJpYnV0ZXMubW9kZSkge1xuICAgIGNhc2UgJ2NvbnN0YW50JzpcbiAgICAgIHJldHVybiBnZXRQYWRDb25zdGFudChnbHNsLCBpbnB1dC5kaW1zLCBzdHJpZGVzLCB3aWR0aCwgaGVpZ2h0LCBhdHRyaWJ1dGVzLnBhZHMsIGF0dHJpYnV0ZXMudmFsdWUpO1xuICAgIGNhc2UgJ3JlZmxlY3QnOlxuICAgICAgcmV0dXJuIGdldFBhZFJlZmxlY3QoZ2xzbCwgaW5wdXQuZGltcywgc3RyaWRlcywgd2lkdGgsIGhlaWdodCwgYXR0cmlidXRlcy5wYWRzKTtcbiAgICBjYXNlICdlZGdlJzpcbiAgICAgIHJldHVybiBnZXRQYWRFZGdlKGdsc2wsIGlucHV0LmRpbXMsIHN0cmlkZXMsIHdpZHRoLCBoZWlnaHQsIGF0dHJpYnV0ZXMucGFkcyk7XG4gICAgZGVmYXVsdDpcbiAgICAgIHRocm93IG5ldyBFcnJvcignSW52YWxpZCBtb2RlJyk7XG4gIH1cbn07XG5cbmNvbnN0IGdldFBhZENvbnN0YW50ID1cbiAgICAoZ2xzbDogR2xzbCwgc2hhcGU6IHJlYWRvbmx5IG51bWJlcltdLCBzdHJpZGVzOiByZWFkb25seSBudW1iZXJbXSwgd2lkdGg6IG51bWJlciwgaGVpZ2h0OiBudW1iZXIsIHBhZHM6IG51bWJlcltdLFxuICAgICB2YWx1ZTogbnVtYmVyKTogc3RyaW5nID0+IHtcbiAgICAgIGNvbnN0IHJhbmsgPSBzaGFwZS5sZW5ndGg7XG4gICAgICBsZXQgYmxvY2sgPSAnJztcbiAgICAgIGZvciAobGV0IGkgPSByYW5rIC0gMTsgaSA+PSAwOyAtLWkpIHtcbiAgICAgICAgYmxvY2sgKz0gYFxuICAgICAgICBrID0gbVske2l9XSAtICR7cGFkc1tpXX07XG4gICAgICAgIGlmIChrIDwgMCkgIHJldHVybiBjb25zdGFudDtcbiAgICAgICAgaWYgKGsgPj0gJHtzaGFwZVtpXX0pIHJldHVybiBjb25zdGFudDtcbiAgICAgICAgb2Zmc2V0ICs9IGsgKiAke3N0cmlkZXNbaV19O1xuICAgICAgICBgO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGBcbiAgICAgIGZsb2F0IHBhZEEoaW50IG1bJHtyYW5rfV0pIHtcbiAgICAgICAgY29uc3QgZmxvYXQgY29uc3RhbnQgPSBmbG9hdCgke3ZhbHVlfSk7XG4gICAgICAgIGludCBvZmZzZXQgPSAwO1xuICAgICAgICBpbnQgayA9IDA7XG4gICAgICAgICR7YmxvY2t9XG4gICAgICAgIHZlYzIgY29vcmRzID0gb2Zmc2V0VG9Db29yZHMob2Zmc2V0LCAke3dpZHRofSwgJHtoZWlnaHR9KTtcbiAgICAgICAgZmxvYXQgdmFsdWUgPSBnZXRDb2xvckFzRmxvYXQoJHtnbHNsLnRleHR1cmUyRH0oQSwgY29vcmRzKSk7XG4gICAgICAgIHJldHVybiB2YWx1ZTtcbiAgICAgIH1cbiAgICAgIGA7XG4gICAgfTtcblxuY29uc3QgZ2V0UGFkUmVmbGVjdCA9XG4gICAgKGdsc2w6IEdsc2wsIHNoYXBlOiByZWFkb25seSBudW1iZXJbXSwgc3RyaWRlczogcmVhZG9ubHkgbnVtYmVyW10sIHdpZHRoOiBudW1iZXIsIGhlaWdodDogbnVtYmVyLCBwYWRzOiBudW1iZXJbXSk6XG4gICAgICAgIHN0cmluZyA9PiB7XG4gICAgICAgICAgY29uc3QgcmFuayA9IHNoYXBlLmxlbmd0aDtcblxuICAgICAgICAgIGxldCBibG9jayA9ICcnO1xuICAgICAgICAgIGZvciAobGV0IGkgPSByYW5rIC0gMTsgaSA+PSAwOyAtLWkpIHtcbiAgICAgICAgICAgIGJsb2NrICs9IGBcbiAgICAgICAgayA9IG1bJHtpfV0gLSAke3BhZHNbaV19O1xuICAgICAgICBpZiAoayA8IDApIHsgayA9IC1rOyB9XG4gICAgICAgIHtcbiAgICAgICAgICBjb25zdCBpbnQgXzJuXzEgPSAkezIgKiAoc2hhcGVbaV0gLSAxKX07XG4gICAgICAgICAgayA9IGludCggbW9kKCBmbG9hdChrKSwgZmxvYXQoXzJuXzEpICkgKSA7XG4gICAgICAgICAgaWYoayA+PSAke3NoYXBlW2ldfSkgeyBrID0gXzJuXzEgLSBrOyB9XG4gICAgICAgIH1cbiAgICAgICAgb2Zmc2V0ICs9IGsgKiAke3N0cmlkZXNbaV19O1xuICAgICAgICBgO1xuICAgICAgICAgIH1cbiAgICAgICAgICByZXR1cm4gYFxuICAgICAgZmxvYXQgcGFkQShpbnQgbVske3Jhbmt9XSkge1xuICAgICAgICBpbnQgb2Zmc2V0ID0gMDtcbiAgICAgICAgaW50IGsgPSAwO1xuICAgICAgICAke2Jsb2NrfVxuICAgICAgICB2ZWMyIGNvb3JkcyA9IG9mZnNldFRvQ29vcmRzKG9mZnNldCwgJHt3aWR0aH0sICR7aGVpZ2h0fSk7XG4gICAgICAgIGZsb2F0IHZhbHVlID0gZ2V0Q29sb3JBc0Zsb2F0KCR7Z2xzbC50ZXh0dXJlMkR9KEEsIGNvb3JkcykpO1xuICAgICAgICByZXR1cm4gdmFsdWU7XG4gICAgICB9XG4gICAgICBgO1xuICAgICAgICB9O1xuXG5jb25zdCBnZXRQYWRFZGdlID1cbiAgICAoZ2xzbDogR2xzbCwgc2hhcGU6IHJlYWRvbmx5IG51bWJlcltdLCBzdHJpZGVzOiByZWFkb25seSBudW1iZXJbXSwgd2lkdGg6IG51bWJlciwgaGVpZ2h0OiBudW1iZXIsIHBhZHM6IG51bWJlcltdKTpcbiAgICAgICAgc3RyaW5nID0+IHtcbiAgICAgICAgICBjb25zdCByYW5rID0gc2hhcGUubGVuZ3RoO1xuXG4gICAgICAgICAgbGV0IGJsb2NrID0gJyc7XG4gICAgICAgICAgZm9yIChsZXQgaSA9IHJhbmsgLSAxOyBpID49IDA7IC0taSkge1xuICAgICAgICAgICAgYmxvY2sgKz0gYFxuICAgICAgICBrID0gbVske2l9XSAtICR7cGFkc1tpXX07XG4gICAgICAgIGlmIChrIDwgMCkgIGsgPSAwO1xuICAgICAgICBpZiAoayA+PSAke3NoYXBlW2ldfSkgayA9ICR7c2hhcGVbaV0gLSAxfTtcbiAgICAgICAgb2Zmc2V0ICs9IGsgKiAke3N0cmlkZXNbaV19O1xuICAgICAgYDtcbiAgICAgICAgICB9XG4gICAgICAgICAgcmV0dXJuIGBcbiAgICAgIGZsb2F0IHBhZEEoaW50IG1bJHtyYW5rfV0pIHtcbiAgICAgICAgaW50IG9mZnNldCA9IDA7XG4gICAgICAgIGludCBrID0gMDtcbiAgICAgICAgJHtibG9ja31cbiAgICAgICAgdmVjMiBjb29yZHMgPSBvZmZzZXRUb0Nvb3JkcyhvZmZzZXQsICR7d2lkdGh9LCAke2hlaWdodH0pO1xuICAgICAgICBmbG9hdCB2YWx1ZSA9IGdldENvbG9yQXNGbG9hdCgke2dsc2wudGV4dHVyZTJEfShBLCBjb29yZHMpKTtcbiAgICAgICAgcmV0dXJuIHZhbHVlO1xuICAgICAgfVxuICAgICAgYDtcbiAgICAgICAgfTtcbiIsIi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxuXG5pbXBvcnQge0F0dHJpYnV0ZVdpdGhDYWNoZUtleSwgY3JlYXRlQXR0cmlidXRlV2l0aENhY2hlS2V5fSBmcm9tICcuLi8uLi8uLi9hdHRyaWJ1dGUtd2l0aC1jYWNoZS1rZXknO1xuaW1wb3J0IHtHcmFwaH0gZnJvbSAnLi4vLi4vLi4vZ3JhcGgnO1xuaW1wb3J0IHtPcGVyYXRvckltcGxlbWVudGF0aW9uLCBPcGVyYXRvckluaXRpYWxpemF0aW9ufSBmcm9tICcuLi8uLi8uLi9vcGVyYXRvcnMnO1xuaW1wb3J0IHtUZW5zb3J9IGZyb20gJy4uLy4uLy4uL3RlbnNvcic7XG5pbXBvcnQge1Bvb2xDb252VXRpbCwgU2hhcGVVdGlsfSBmcm9tICcuLi8uLi8uLi91dGlsJztcbmltcG9ydCB7V2ViR0xJbmZlcmVuY2VIYW5kbGVyfSBmcm9tICcuLi9pbmZlcmVuY2UtaGFuZGxlcic7XG5pbXBvcnQge1Byb2dyYW1JbmZvLCBQcm9ncmFtTWV0YWRhdGEsIFRleHR1cmVUeXBlfSBmcm9tICcuLi90eXBlcyc7XG5cbmV4cG9ydCBpbnRlcmZhY2UgQXZlcmFnZVBvb2xBdHRyaWJ1dGVzIGV4dGVuZHMgQXR0cmlidXRlV2l0aENhY2hlS2V5IHtcbiAgcmVhZG9ubHkgYXV0b1BhZDogc3RyaW5nO1xuICByZWFkb25seSBjZWlsTW9kZTogbnVtYmVyO1xuICByZWFkb25seSBjb3VudEluY2x1ZGVQYWQ6IGJvb2xlYW47XG4gIHJlYWRvbmx5IGtlcm5lbFNoYXBlOiByZWFkb25seSBudW1iZXJbXTtcbiAgcmVhZG9ubHkgc3RyaWRlczogcmVhZG9ubHkgbnVtYmVyW107XG4gIHJlYWRvbmx5IHBhZHM6IHJlYWRvbmx5IG51bWJlcltdO1xufVxuXG5leHBvcnQgY29uc3QgYXZlcmFnZVBvb2w6IE9wZXJhdG9ySW1wbGVtZW50YXRpb248QXZlcmFnZVBvb2xBdHRyaWJ1dGVzPiA9XG4gICAgKGluZmVyZW5jZUhhbmRsZXI6IFdlYkdMSW5mZXJlbmNlSGFuZGxlciwgaW5wdXRzOiBUZW5zb3JbXSwgYXR0cmlidXRlczogQXZlcmFnZVBvb2xBdHRyaWJ1dGVzKTogVGVuc29yW10gPT4ge1xuICAgICAgdmFsaWRhdGVJbnB1dHMoaW5wdXRzKTtcbiAgICAgIGNvbnN0IG1ldGFkYXRhID1cbiAgICAgICAgICB7bmFtZTogJ0F2ZXJhZ2VQb29sJywgaW5wdXROYW1lczogWydYJ10sIGlucHV0VHlwZXM6IFtUZXh0dXJlVHlwZS51bnBhY2tlZF0sIGNhY2hlSGludDogYXR0cmlidXRlcy5jYWNoZUtleX07XG4gICAgICBjb25zdCBvdXRwdXQgPSBpbmZlcmVuY2VIYW5kbGVyLnJ1bihcbiAgICAgICAgICB7Li4ubWV0YWRhdGEsIGdldDogKCkgPT4gY3JlYXRlQXZlcmFnZVBvb2xQcm9ncmFtSW5mbyhpbnB1dHMsIG1ldGFkYXRhLCBmYWxzZSwgYXR0cmlidXRlcyl9LCBpbnB1dHMpO1xuICAgICAgcmV0dXJuIFtvdXRwdXRdO1xuICAgIH07XG5cbmV4cG9ydCBjb25zdCBwYXJzZUF2ZXJhZ2VQb29sQXR0cmlidXRlczogT3BlcmF0b3JJbml0aWFsaXphdGlvbjxBdmVyYWdlUG9vbEF0dHJpYnV0ZXM+ID1cbiAgICAobm9kZTogR3JhcGguTm9kZSk6IEF2ZXJhZ2VQb29sQXR0cmlidXRlcyA9PiB7XG4gICAgICBjb25zdCBhdXRvUGFkID0gbm9kZS5hdHRyaWJ1dGVzLmdldFN0cmluZygnYXV0b19wYWQnLCAnTk9UU0VUJyk7XG4gICAgICBjb25zdCBjZWlsTW9kZSA9IG5vZGUuYXR0cmlidXRlcy5nZXRJbnQoJ2NlaWxfbW9kZScsIDApO1xuICAgICAgY29uc3QgY291bnRJbmNsdWRlUGFkID0gKG5vZGUuYXR0cmlidXRlcy5nZXRJbnQoJ2NvdW50X2luY2x1ZGVfcGFkJywgMCkgPT09IDAgPyBmYWxzZSA6IHRydWUpO1xuICAgICAgY29uc3Qga2VybmVsU2hhcGUgPSBub2RlLmF0dHJpYnV0ZXMuZ2V0SW50cygna2VybmVsX3NoYXBlJyk7XG4gICAgICBjb25zdCBzdHJpZGVzID0gbm9kZS5hdHRyaWJ1dGVzLmdldEludHMoJ3N0cmlkZXMnLCBbXSk7XG4gICAgICBjb25zdCBwYWRzID0gbm9kZS5hdHRyaWJ1dGVzLmdldEludHMoJ3BhZHMnLCBbXSk7XG5cbiAgICAgIC8vIFRPRE86IHN1cHBvcnQgYXR0cmlidXRlICdjZWlsX21vZGUnXG4gICAgICBpZiAoY2VpbE1vZGUgIT09IDApIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCd1c2luZyBjZWlsKCkgaW4gc2hhcGUgY29tcHV0YXRpb24gaXMgbm90IHlldCBzdXBwb3J0ZWQgZm9yIEF2ZXJhZ2VQb29sJyk7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBjcmVhdGVBdHRyaWJ1dGVXaXRoQ2FjaGVLZXkoe2F1dG9QYWQsIGNlaWxNb2RlLCBjb3VudEluY2x1ZGVQYWQsIGtlcm5lbFNoYXBlLCBzdHJpZGVzLCBwYWRzfSk7XG4gICAgfTtcblxuY29uc3QgY3JlYXRlQXZlcmFnZVBvb2xQcm9ncmFtSW5mbyA9XG4gICAgKGlucHV0czogVGVuc29yW10sIG1ldGFkYXRhOiBQcm9ncmFtTWV0YWRhdGEsIGlzR2xvYmFsT3BlcmF0b3I6IGJvb2xlYW4sIGF0dHJpYnV0ZXM6IEF2ZXJhZ2VQb29sQXR0cmlidXRlcyk6XG4gICAgICAgIFByb2dyYW1JbmZvID0+IHtcbiAgICAgICAgICBjb25zdCBbYWRqdXN0ZWRBdHRyaWJ1dGVzLCBvdXRwdXRTaGFwZV0gPVxuICAgICAgICAgICAgICBnZXRBZGp1c3RlZFBvb2xBdHRyaWJ1dGVzQW5kT3V0cHV0U2hhcGUoaW5wdXRzLCBhdHRyaWJ1dGVzLCBpc0dsb2JhbE9wZXJhdG9yKTtcbiAgICAgICAgICBjb25zdCBrZXJuZWxTaXplID0gU2hhcGVVdGlsLnNpemUoYWRqdXN0ZWRBdHRyaWJ1dGVzLmtlcm5lbFNoYXBlKTtcbiAgICAgICAgICBjb25zdCBvcDEgPSAndmFsdWUgKz0gX1goeCk7JztcbiAgICAgICAgICBsZXQgb3AyID0gJyc7XG4gICAgICAgICAgaWYgKGFkanVzdGVkQXR0cmlidXRlcy5jb3VudEluY2x1ZGVQYWQpIHtcbiAgICAgICAgICAgIG9wMiArPSBgdmFsdWUgLz0gZmxvYXQoJHtrZXJuZWxTaXplfSk7YDtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgb3AyICs9IGB2YWx1ZSAvPSBmbG9hdCgke2tlcm5lbFNpemV9IC0gcGFkKTtgO1xuICAgICAgICAgIH1cbiAgICAgICAgICBjb25zdCBwb29saW5nQ29kZSA9IGdlbmVyYXRlUG9vbGluZ0NvZGUoaW5wdXRzWzBdLmRpbXMsIGFkanVzdGVkQXR0cmlidXRlcywgb3AxLCBvcDIsICcwLjAnKTtcbiAgICAgICAgICBjb25zdCBzaGFkZXJTb3VyY2UgPSBgXG4gICAgICAgICR7cG9vbGluZ0NvZGV9XG4gICAgICBgO1xuICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAuLi5tZXRhZGF0YSxcbiAgICAgICAgICAgIG91dHB1dDoge2RpbXM6IG91dHB1dFNoYXBlLCB0eXBlOiBpbnB1dHNbMF0udHlwZSwgdGV4dHVyZVR5cGU6IFRleHR1cmVUeXBlLnVucGFja2VkfSxcbiAgICAgICAgICAgIHNoYWRlclNvdXJjZVxuICAgICAgICAgIH07XG4gICAgICAgIH07XG5cbmV4cG9ydCBjb25zdCBnbG9iYWxBdmVyYWdlUG9vbDogT3BlcmF0b3JJbXBsZW1lbnRhdGlvbjxBdmVyYWdlUG9vbEF0dHJpYnV0ZXM+ID1cbiAgICAoaW5mZXJlbmNlSGFuZGxlcjogV2ViR0xJbmZlcmVuY2VIYW5kbGVyLCBpbnB1dHM6IFRlbnNvcltdLCBhdHRyaWJ1dGVzOiBBdmVyYWdlUG9vbEF0dHJpYnV0ZXMpOiBUZW5zb3JbXSA9PiB7XG4gICAgICB2YWxpZGF0ZUlucHV0cyhpbnB1dHMpO1xuICAgICAgY29uc3QgbWV0YWRhdGEgPSB7XG4gICAgICAgIG5hbWU6ICdHbG9iYWxBdmVyYWdlUG9vbCcsXG4gICAgICAgIGlucHV0TmFtZXM6IFsnWCddLFxuICAgICAgICBpbnB1dFR5cGVzOiBbVGV4dHVyZVR5cGUudW5wYWNrZWRdLFxuICAgICAgICBjYWNoZUhpbnQ6IGAke2F0dHJpYnV0ZXMuY291bnRJbmNsdWRlUGFkfWBcbiAgICAgIH07XG4gICAgICBjb25zdCBvdXRwdXQgPSBpbmZlcmVuY2VIYW5kbGVyLnJ1bihcbiAgICAgICAgICB7Li4ubWV0YWRhdGEsIGdldDogKCkgPT4gY3JlYXRlQXZlcmFnZVBvb2xQcm9ncmFtSW5mbyhpbnB1dHMsIG1ldGFkYXRhLCB0cnVlLCBhdHRyaWJ1dGVzKX0sIGlucHV0cyk7XG4gICAgICByZXR1cm4gW291dHB1dF07XG4gICAgfTtcblxuZXhwb3J0IGNvbnN0IHBhcnNlR2xvYmFsQXZlcmFnZVBvb2xBdHRyaWJ1dGVzOiBPcGVyYXRvckluaXRpYWxpemF0aW9uPEF2ZXJhZ2VQb29sQXR0cmlidXRlcz4gPVxuICAgIChub2RlOiBHcmFwaC5Ob2RlKTogQXZlcmFnZVBvb2xBdHRyaWJ1dGVzID0+IHtcbiAgICAgIGNvbnN0IGNvdW50SW5jbHVkZVBhZCA9IChub2RlLmF0dHJpYnV0ZXMuZ2V0SW50KCdjb3VudF9pbmNsdWRlX3BhZCcsIDApID09PSAwID8gZmFsc2UgOiB0cnVlKTtcbiAgICAgIHJldHVybiBjcmVhdGVBdHRyaWJ1dGVXaXRoQ2FjaGVLZXkoXG4gICAgICAgICAge2F1dG9QYWQ6ICcnLCBjZWlsTW9kZTogMCwgY291bnRJbmNsdWRlUGFkLCBrZXJuZWxTaGFwZTogW10sIHN0cmlkZXM6IFtdLCBwYWRzOiBbXX0pO1xuICAgIH07XG5cbmV4cG9ydCBpbnRlcmZhY2UgTWF4UG9vbEF0dHJpYnV0ZXMgZXh0ZW5kcyBBdmVyYWdlUG9vbEF0dHJpYnV0ZXMge1xuICByZWFkb25seSBzdG9yYWdlT3JkZXI6IG51bWJlcjtcbiAgcmVhZG9ubHkgZGlsYXRpb25zOiBudW1iZXJbXTtcbn1cblxuZXhwb3J0IGNvbnN0IG1heFBvb2w6IE9wZXJhdG9ySW1wbGVtZW50YXRpb248TWF4UG9vbEF0dHJpYnV0ZXM+ID1cbiAgICAoaW5mZXJlbmNlSGFuZGxlcjogV2ViR0xJbmZlcmVuY2VIYW5kbGVyLCBpbnB1dHM6IFRlbnNvcltdLCBhdHRyaWJ1dGVzOiBNYXhQb29sQXR0cmlidXRlcyk6IFRlbnNvcltdID0+IHtcbiAgICAgIHZhbGlkYXRlSW5wdXRzKGlucHV0cyk7XG4gICAgICBjb25zdCBtZXRhZGF0YSA9XG4gICAgICAgICAge25hbWU6ICdNYXhQb29sJywgaW5wdXROYW1lczogWydYJ10sIGlucHV0VHlwZXM6IFtUZXh0dXJlVHlwZS51bnBhY2tlZF0sIGNhY2hlSGludDogYXR0cmlidXRlcy5jYWNoZUtleX07XG4gICAgICBjb25zdCBvdXRwdXQgPSBpbmZlcmVuY2VIYW5kbGVyLnJ1bihcbiAgICAgICAgICB7Li4ubWV0YWRhdGEsIGdldDogKCkgPT4gY3JlYXRlTWF4UG9vbFByb2dyYW1JbmZvKGlucHV0cywgbWV0YWRhdGEsIGZhbHNlLCBhdHRyaWJ1dGVzKX0sIGlucHV0cyk7XG4gICAgICByZXR1cm4gW291dHB1dF07XG4gICAgfTtcblxuZXhwb3J0IGNvbnN0IHBhcnNlTWF4UG9vbEF0dHJpYnV0ZXM6IE9wZXJhdG9ySW5pdGlhbGl6YXRpb248TWF4UG9vbEF0dHJpYnV0ZXM+ID1cbiAgICAobm9kZTogR3JhcGguTm9kZSk6IE1heFBvb2xBdHRyaWJ1dGVzID0+IHtcbiAgICAgIGNvbnN0IGF1dG9QYWQgPSBub2RlLmF0dHJpYnV0ZXMuZ2V0U3RyaW5nKCdhdXRvX3BhZCcsICdOT1RTRVQnKTtcbiAgICAgIGNvbnN0IGNlaWxNb2RlID0gbm9kZS5hdHRyaWJ1dGVzLmdldEludCgnY2VpbF9tb2RlJywgMCk7XG4gICAgICBjb25zdCBrZXJuZWxTaGFwZSA9IG5vZGUuYXR0cmlidXRlcy5nZXRJbnRzKCdrZXJuZWxfc2hhcGUnKTtcbiAgICAgIGNvbnN0IHN0cmlkZXMgPSBub2RlLmF0dHJpYnV0ZXMuZ2V0SW50cygnc3RyaWRlcycsIFtdKTtcbiAgICAgIGNvbnN0IHBhZHMgPSBub2RlLmF0dHJpYnV0ZXMuZ2V0SW50cygncGFkcycsIFtdKTtcbiAgICAgIGNvbnN0IHN0b3JhZ2VPcmRlciA9IG5vZGUuYXR0cmlidXRlcy5nZXRJbnQoJ3N0b3JhZ2Vfb3JkZXInLCAwKTtcbiAgICAgIGNvbnN0IGRpbGF0aW9ucyA9IG5vZGUuYXR0cmlidXRlcy5nZXRJbnRzKCdkaWxhdGlvbnMnLCBbXSk7XG5cbiAgICAgIC8vIFRPRE86IHN1cHBvcnQgYXR0cmlidXRlICdjZWlsX21vZGUnIGFuZCAnc3RvcmFnZV9vcmRlcidcbiAgICAgIGlmIChzdG9yYWdlT3JkZXIgIT09IDApIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdjb2x1bW4gbWFqb3Igc3RvcmFnZSBvcmRlciBpcyBub3QgeWV0IHN1cHBvcnRlZCBmb3IgTWF4UG9vbCcpO1xuICAgICAgfVxuICAgICAgaWYgKGNlaWxNb2RlICE9PSAwKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcigndXNpbmcgY2VpbCgpIGluIHNoYXBlIGNvbXB1dGF0aW9uIGlzIG5vdCB5ZXQgc3VwcG9ydGVkIGZvciBNYXhQb29sJyk7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBjcmVhdGVBdHRyaWJ1dGVXaXRoQ2FjaGVLZXkoXG4gICAgICAgICAge2F1dG9QYWQsIGNlaWxNb2RlLCBjb3VudEluY2x1ZGVQYWQ6IGZhbHNlLCBrZXJuZWxTaGFwZSwgc3RyaWRlcywgcGFkcywgc3RvcmFnZU9yZGVyLCBkaWxhdGlvbnN9KTtcbiAgICB9O1xuXG5jb25zdCBjcmVhdGVNYXhQb29sUHJvZ3JhbUluZm8gPVxuICAgIChpbnB1dHM6IFRlbnNvcltdLCBtZXRhZGF0YTogUHJvZ3JhbU1ldGFkYXRhLCBpc0dsb2JhbE9wZXJhdG9yOiBib29sZWFuLCBhdHRyaWJ1dGVzOiBNYXhQb29sQXR0cmlidXRlcyk6XG4gICAgICAgIFByb2dyYW1JbmZvID0+IHtcbiAgICAgICAgICBjb25zdCBbYWRqdXN0ZWRBdHRyaWJ1dGVzLCBvdXRwdXRTaGFwZV0gPVxuICAgICAgICAgICAgICBnZXRBZGp1c3RlZFBvb2xBdHRyaWJ1dGVzQW5kT3V0cHV0U2hhcGUoaW5wdXRzLCBhdHRyaWJ1dGVzLCBpc0dsb2JhbE9wZXJhdG9yKTtcbiAgICAgICAgICBjb25zdCBvcDEgPSBgXG4gICAgICB2YWx1ZSA9IG1heChfWCh4KSwgdmFsdWUpO1xuICAgIGA7XG4gICAgICAgICAgY29uc3Qgb3AyID0gJyc7XG4gICAgICAgICAgY29uc3QgcG9vbGluZ0NvZGUgPSBnZW5lcmF0ZVBvb2xpbmdDb2RlKGlucHV0c1swXS5kaW1zLCBhZGp1c3RlZEF0dHJpYnV0ZXMsIG9wMSwgb3AyLCAnLTFlNScpO1xuICAgICAgICAgIGNvbnN0IHNoYWRlclNvdXJjZSA9IGBcbiAgICAgICR7cG9vbGluZ0NvZGV9XG4gICAgYDtcbiAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgLi4ubWV0YWRhdGEsXG4gICAgICAgICAgICBvdXRwdXQ6IHtkaW1zOiBvdXRwdXRTaGFwZSwgdHlwZTogaW5wdXRzWzBdLnR5cGUsIHRleHR1cmVUeXBlOiBUZXh0dXJlVHlwZS51bnBhY2tlZH0sXG4gICAgICAgICAgICBzaGFkZXJTb3VyY2VcbiAgICAgICAgICB9O1xuICAgICAgICB9O1xuXG5jb25zdCBnZXRBZGp1c3RlZFBvb2xBdHRyaWJ1dGVzQW5kT3V0cHV0U2hhcGUgPVxuICAgIChpbnB1dHM6IFRlbnNvcltdLCBhdHRyaWJ1dGVzOiBBdmVyYWdlUG9vbEF0dHJpYnV0ZXN8TWF4UG9vbEF0dHJpYnV0ZXMsIGlzR2xvYmFsT3BlcmF0b3I6IGJvb2xlYW4pOlxuICAgICAgICBbQXZlcmFnZVBvb2xBdHRyaWJ1dGVzfE1heFBvb2xBdHRyaWJ1dGVzLCBudW1iZXJbXV0gPT4ge1xuICAgICAgICAgIGNvbnN0IGlucHV0U2hhcGUgPSBpbnB1dHNbMF0uZGltcy5zbGljZSgpO1xuICAgICAgICAgIGNvbnN0IGhhc0RpbGF0aW9ucyA9IE9iamVjdC5oYXNPd25Qcm9wZXJ0eS5jYWxsKGF0dHJpYnV0ZXMsICdkaWxhdGlvbnMnKTtcbiAgICAgICAgICBjb25zdCBrZXJuZWxTaGFwZSA9IGF0dHJpYnV0ZXMua2VybmVsU2hhcGUuc2xpY2UoKTtcbiAgICAgICAgICBjb25zdCBzdHJpZGVzID0gYXR0cmlidXRlcy5zdHJpZGVzLnNsaWNlKCk7XG4gICAgICAgICAgY29uc3QgZGlsYXRpb25zOiBudW1iZXJbXSA9IGhhc0RpbGF0aW9ucyA/IChhdHRyaWJ1dGVzIGFzIE1heFBvb2xBdHRyaWJ1dGVzKS5kaWxhdGlvbnMuc2xpY2UoKSA6IFtdO1xuICAgICAgICAgIGNvbnN0IHBhZHMgPSBhdHRyaWJ1dGVzLnBhZHMuc2xpY2UoKTtcbiAgICAgICAgICBQb29sQ29udlV0aWwuYWRqdXN0UG9vbEF0dHJpYnV0ZXMoaXNHbG9iYWxPcGVyYXRvciwgaW5wdXRTaGFwZSwga2VybmVsU2hhcGUsIHN0cmlkZXMsIGRpbGF0aW9ucywgcGFkcyk7XG5cbiAgICAgICAgICBjb25zdCBvdXRwdXRTaGFwZSA9IFBvb2xDb252VXRpbC5jb21wdXRlUG9vbE91dHB1dFNoYXBlKFxuICAgICAgICAgICAgICBpc0dsb2JhbE9wZXJhdG9yLCBpbnB1dFNoYXBlLCBzdHJpZGVzLCBkaWxhdGlvbnMsIGtlcm5lbFNoYXBlLCBwYWRzLCBhdHRyaWJ1dGVzLmF1dG9QYWQpO1xuXG4gICAgICAgICAgY29uc3QgbmV3QXR0cmlidXRlcyA9IE9iamVjdC5hc3NpZ24oe30sIGF0dHJpYnV0ZXMpO1xuICAgICAgICAgIGlmIChoYXNEaWxhdGlvbnMpIHtcbiAgICAgICAgICAgIE9iamVjdC5hc3NpZ24obmV3QXR0cmlidXRlcywge2tlcm5lbFNoYXBlLCBzdHJpZGVzLCBwYWRzLCBkaWxhdGlvbnMsIGNhY2hlS2V5OiBhdHRyaWJ1dGVzLmNhY2hlS2V5fSk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIE9iamVjdC5hc3NpZ24obmV3QXR0cmlidXRlcywge2tlcm5lbFNoYXBlLCBzdHJpZGVzLCBwYWRzLCBjYWNoZUtleTogYXR0cmlidXRlcy5jYWNoZUtleX0pO1xuICAgICAgICAgIH1cbiAgICAgICAgICByZXR1cm4gW25ld0F0dHJpYnV0ZXMsIG91dHB1dFNoYXBlXTtcbiAgICAgICAgfTtcblxuY29uc3QgZ2xvYmFsTWF4UG9vbEF0dHJpYnV0ZXMgPSB7XG4gIGF1dG9QYWQ6ICcnLFxuICBjZWlsTW9kZTogMCxcbiAgY291bnRJbmNsdWRlUGFkOiBmYWxzZSxcbiAga2VybmVsU2hhcGU6IFtdLFxuICBzdHJpZGVzOiBbXSxcbiAgcGFkczogW10sXG4gIHN0b3JhZ2VPcmRlcjogMCxcbiAgZGlsYXRpb25zOiBbXSxcbiAgY2FjaGVLZXk6ICcnXG59O1xuXG5jb25zdCBnbG9iYWxNYXhQb29sTWV0YWRhdGEgPSB7XG4gIG5hbWU6ICdHbG9iYWxNYXhQb29sJyxcbiAgaW5wdXROYW1lczogWydYJ10sXG4gIGlucHV0VHlwZXM6IFtUZXh0dXJlVHlwZS51bnBhY2tlZF1cbn07XG5cbmV4cG9ydCBjb25zdCBnbG9iYWxNYXhQb29sID0gKGluZmVyZW5jZUhhbmRsZXI6IFdlYkdMSW5mZXJlbmNlSGFuZGxlciwgaW5wdXRzOiBUZW5zb3JbXSk6IFRlbnNvcltdID0+IHtcbiAgdmFsaWRhdGVJbnB1dHMoaW5wdXRzKTtcbiAgY29uc3Qgb3V0cHV0ID0gaW5mZXJlbmNlSGFuZGxlci5ydW4oXG4gICAgICB7XG4gICAgICAgIC4uLmdsb2JhbE1heFBvb2xNZXRhZGF0YSxcbiAgICAgICAgZ2V0OiAoKSA9PiBjcmVhdGVNYXhQb29sUHJvZ3JhbUluZm8oaW5wdXRzLCBnbG9iYWxNYXhQb29sTWV0YWRhdGEsIHRydWUsIGdsb2JhbE1heFBvb2xBdHRyaWJ1dGVzKVxuICAgICAgfSxcbiAgICAgIGlucHV0cyk7XG4gIHJldHVybiBbb3V0cHV0XTtcbn07XG5cbmNvbnN0IHZhbGlkYXRlSW5wdXRzID0gKGlucHV0czogVGVuc29yW10pOiB2b2lkID0+IHtcbiAgaWYgKCFpbnB1dHMgfHwgaW5wdXRzLmxlbmd0aCAhPT0gMSkge1xuICAgIHRocm93IG5ldyBFcnJvcignUG9vbCBvcHMgcmVxdWlyZXMgMSBpbnB1dC4nKTtcbiAgfVxuICBpZiAoaW5wdXRzWzBdLnR5cGUgIT09ICdmbG9hdDMyJyAmJiBpbnB1dHNbMF0udHlwZSAhPT0gJ2Zsb2F0NjQnKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIGlucHV0IHR5cGUuJyk7XG4gIH1cbn07XG5cbmNvbnN0IGdlbmVyYXRlUG9vbGluZ0NvZGUgPVxuICAgIChpbnB1dERpbXM6IHJlYWRvbmx5IG51bWJlcltdLCBhdHRyaWJ1dGVzOiBBdmVyYWdlUG9vbEF0dHJpYnV0ZXMsIG9wMTogc3RyaW5nLCBvcDI6IHN0cmluZywgc3RhcnQ6IHN0cmluZyk6XG4gICAgICAgIHN0cmluZyA9PiB7XG4gICAgICAgICAgY29uc3QgcmFuayA9IGlucHV0RGltcy5sZW5ndGg7XG4gICAgICAgICAgaWYgKGF0dHJpYnV0ZXMua2VybmVsU2hhcGUubGVuZ3RoIDw9IDIpIHtcbiAgICAgICAgICAgIGNvbnN0IGt3ID0gYXR0cmlidXRlcy5rZXJuZWxTaGFwZVthdHRyaWJ1dGVzLmtlcm5lbFNoYXBlLmxlbmd0aCAtIDFdO1xuICAgICAgICAgICAgY29uc3Qgc3cgPSBhdHRyaWJ1dGVzLnN0cmlkZXNbYXR0cmlidXRlcy5zdHJpZGVzLmxlbmd0aCAtIDFdO1xuICAgICAgICAgICAgY29uc3QgcHdTdGFydCA9IGF0dHJpYnV0ZXMucGFkc1thdHRyaWJ1dGVzLnBhZHMubGVuZ3RoIC8gMiAtIDFdO1xuICAgICAgICAgICAgY29uc3QgcHdFbmQgPSBhdHRyaWJ1dGVzLnBhZHNbYXR0cmlidXRlcy5wYWRzLmxlbmd0aCAtIDFdO1xuICAgICAgICAgICAgY29uc3QgZGltVyA9IGlucHV0RGltc1tyYW5rIC0gMV07XG4gICAgICAgICAgICBsZXQgY29kZVcgPSAnJztcbiAgICAgICAgICAgIGxldCBjb2RlSCA9ICcnO1xuICAgICAgICAgICAgbGV0IGNvZGVIRW5kID0gJyc7XG4gICAgICAgICAgICBpZiAocHdTdGFydCArIHB3RW5kICE9PSAwKSB7XG4gICAgICAgICAgICAgIGNvZGVXID0gYFxuICAgICAgICAgIGZvciAoaW50IGkgPSAwOyBpIDwgJHtrd307IGkrKykge1xuICAgICAgICAgICAgeFske3Jhbmt9IC0gMV0gPSBpbmRpY2VzWyR7cmFua30gLSAxXSAqICR7c3d9IC0gJHtwd1N0YXJ0fSArIGk7XG4gICAgICAgICAgICBpZiAoeFske3Jhbmt9IC0gMV0gPCAwIHx8IHhbJHtyYW5rfSAtIDFdID49ICR7ZGltV30pIHtcbiAgICAgICAgICAgICAgcGFkKys7XG4gICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgJHtvcDF9XG4gICAgICAgICAgfWA7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICBjb2RlVyA9IGBcbiAgICAgICAgICBmb3IgKGludCBpID0gMDsgaSA8ICR7a3d9OyBpKyspIHtcbiAgICAgICAgICAgIHhbJHtyYW5rfSAtIDFdID0gaW5kaWNlc1ske3Jhbmt9IC0gMV0gKiAke3N3fSAtICR7cHdTdGFydH0gKyBpO1xuICAgICAgICAgICAgJHtvcDF9XG4gICAgICAgICAgfWA7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmIChhdHRyaWJ1dGVzLmtlcm5lbFNoYXBlLmxlbmd0aCA9PT0gMikge1xuICAgICAgICAgICAgICBjb25zdCBraCA9IGF0dHJpYnV0ZXMua2VybmVsU2hhcGVbYXR0cmlidXRlcy5rZXJuZWxTaGFwZS5sZW5ndGggLSAyXTtcbiAgICAgICAgICAgICAgY29uc3Qgc2ggPSBhdHRyaWJ1dGVzLnN0cmlkZXNbYXR0cmlidXRlcy5zdHJpZGVzLmxlbmd0aCAtIDJdO1xuICAgICAgICAgICAgICBjb25zdCBwaFN0YXJ0ID0gYXR0cmlidXRlcy5wYWRzW2F0dHJpYnV0ZXMucGFkcy5sZW5ndGggLyAyIC0gMl07XG4gICAgICAgICAgICAgIGNvbnN0IHBoRW5kID0gYXR0cmlidXRlcy5wYWRzW2F0dHJpYnV0ZXMucGFkcy5sZW5ndGggLSAyXTtcbiAgICAgICAgICAgICAgY29uc3QgZGltSCA9IGlucHV0RGltc1tyYW5rIC0gMl07XG4gICAgICAgICAgICAgIGlmIChwaFN0YXJ0ICsgcGhFbmQgIT09IDApIHtcbiAgICAgICAgICAgICAgICBjb2RlSCA9IGBcbiAgICAgICAgICAgIGZvciAoaW50IGogPSAwOyBqIDwgJHtraH07IGorKykge1xuICAgICAgICAgICAgICB4WyR7cmFua30gLSAyXSA9IGluZGljZXNbJHtyYW5rfSAtIDJdICogJHtzaH0gLSAke3BoU3RhcnR9ICsgajtcbiAgICAgICAgICAgICAgaWYgKHhbJHtyYW5rfSAtIDJdIDwgMCB8fCB4WyR7cmFua30gLSAyXSA+PSAke2RpbUh9KSB7XG4gICAgICAgICAgICAgICAgcGFkKz0gJHtrd307XG4gICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICBgO1xuICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGNvZGVIID0gYFxuICAgICAgICAgICAgZm9yIChpbnQgaiA9IDA7IGogPCAke2tofTsgaisrKSB7XG4gICAgICAgICAgICAgIHhbJHtyYW5rfSAtIDJdID0gaW5kaWNlc1ske3Jhbmt9IC0gMl0gKiAke3NofSAtICR7cGhTdGFydH0gKyBqO1xuICAgICAgICAgICAgYDtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICBjb2RlSEVuZCA9IGBcbiAgICAgICAgICB9XG4gICAgICAgIGA7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGNvbnN0IHBvb2xpbmdDb2RlID0gYFxuICAgICAgICBmbG9hdCBwcm9jZXNzKGludCBpbmRpY2VzWyR7cmFua31dKSB7XG4gICAgICAgICAgaW50IHhbJHtyYW5rfV07XG4gICAgICAgICAgY29weVZlYyhpbmRpY2VzLCB4KTtcblxuICAgICAgICAgIGZsb2F0IHZhbHVlID0gJHtzdGFydH07XG4gICAgICAgICAgaW50IHBhZCA9IDA7XG4gICAgICAgICAgJHtjb2RlSH1cbiAgICAgICAgICAke2NvZGVXfVxuICAgICAgICAgICR7Y29kZUhFbmR9XG4gICAgICAgICAgJHtvcDJ9XG4gICAgICAgICAgcmV0dXJuIHZhbHVlO1xuICAgICAgICB9XG4gICAgICBgO1xuICAgICAgICAgICAgcmV0dXJuIHBvb2xpbmdDb2RlO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjb25zdCBrZXJuZWxTaXplID0gU2hhcGVVdGlsLnNpemUoYXR0cmlidXRlcy5rZXJuZWxTaGFwZSk7XG4gICAgICAgICAgICBjb25zdCBrZXJuZWxTdHJpZGVzID0gU2hhcGVVdGlsLmNvbXB1dGVTdHJpZGVzKGF0dHJpYnV0ZXMua2VybmVsU2hhcGUpO1xuICAgICAgICAgICAgY29uc3Qgc3RyaWRlc1JhbmsgPSBrZXJuZWxTdHJpZGVzLmxlbmd0aDtcbiAgICAgICAgICAgIGNvbnN0IHBhZHNSYW5rID0gYXR0cmlidXRlcy5wYWRzLmxlbmd0aDtcbiAgICAgICAgICAgIGNvbnN0IG9mZnNldFRvSW5kaWNlc0Z1bmN0aW9uID0gb2Zmc2V0VG9JbmRpY2VzKHN0cmlkZXNSYW5rKTtcbiAgICAgICAgICAgIGNvbnN0IGNvcHlJbnB1dERpbXMgPSBjb3B5QXJyYXkoaW5wdXREaW1zLCAnaW5wdXREaW1zJyk7XG4gICAgICAgICAgICBjb25zdCBjb3B5UGFkcyA9IGNvcHlBcnJheShhdHRyaWJ1dGVzLnBhZHMsICdwYWRzJyk7XG4gICAgICAgICAgICBjb25zdCBjb3B5S2VybmVsU3RyaWRlcyA9IGNvcHlBcnJheShrZXJuZWxTdHJpZGVzLCAna2VybmVsU3RyaWRlcycpO1xuICAgICAgICAgICAgY29uc3QgY29weVN0cmlkZXMgPSBjb3B5QXJyYXkoYXR0cmlidXRlcy5zdHJpZGVzLCAnc3RyaWRlcycpO1xuICAgICAgICAgICAgY29uc3QgaGFzUGFkcyA9IGF0dHJpYnV0ZXMucGFkcy5yZWR1Y2UoKHN1bSwgY3VyKSA9PiBzdW0gKyBjdXIpO1xuICAgICAgICAgICAgbGV0IHBhZENvZGUgPSAnJztcbiAgICAgICAgICAgIGlmIChoYXNQYWRzKSB7XG4gICAgICAgICAgICAgIHBhZENvZGUgPSBgXG4gICAgICAgICAgICBpZiAoeFtqXSA+PSBpbnB1dERpbXNbal0gfHwgeFtqXSA8IDApIHtcbiAgICAgICAgICAgICAgcGFkKys7XG4gICAgICAgICAgICAgIGlzUGFkID0gdHJ1ZTtcbiAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICAgIGlmICghaXNQYWQpIHtcbiAgICAgICAgICAgICR7b3AxfVxuICAgICAgICAgIH1gO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgcGFkQ29kZSA9IGBcbiAgICAgICAgICB9XG4gICAgICAgICAgJHtvcDF9XG4gICAgICAgIGA7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjb25zdCBwb29saW5nQ29kZSA9IGBcbiAgICAgICAgJHtvZmZzZXRUb0luZGljZXNGdW5jdGlvbn1cbiAgICAgICAgZmxvYXQgcHJvY2VzcyhpbnQgaW5kaWNlc1ske3Jhbmt9XSkge1xuICAgICAgICAgIGludCB4WyR7cmFua31dO1xuICAgICAgICAgIGNvcHlWZWMoaW5kaWNlcywgeCk7XG4gICAgICAgICAgaW50IG9mZnNldFske3N0cmlkZXNSYW5rfV07XG4gICAgICAgICAgaW50IHBhZHNbJHtwYWRzUmFua31dO1xuICAgICAgICAgIGludCBpbnB1dERpbXNbJHtyYW5rfV07XG4gICAgICAgICAgaW50IGtlcm5lbFN0cmlkZXNbJHtzdHJpZGVzUmFua31dO1xuICAgICAgICAgIGludCBzdHJpZGVzWyR7c3RyaWRlc1Jhbmt9XTtcbiAgICAgICAgICAke2NvcHlQYWRzfVxuICAgICAgICAgICR7Y29weUlucHV0RGltc31cbiAgICAgICAgICAke2NvcHlTdHJpZGVzfVxuICAgICAgICAgICR7Y29weUtlcm5lbFN0cmlkZXN9XG5cbiAgICAgICAgICBmbG9hdCB2YWx1ZSA9ICR7c3RhcnR9O1xuICAgICAgICAgIGludCBwYWQgPSAwO1xuICAgICAgICAgIGJvb2wgaXNQYWQgPSBmYWxzZTtcbiAgICAgICAgICBmb3IgKGludCBpID0gMDsgaSA8ICR7a2VybmVsU2l6ZX07IGkrKykge1xuICAgICAgICAgICAgb2Zmc2V0VG9JbmRpY2VzKGksIGtlcm5lbFN0cmlkZXMsIG9mZnNldCk7XG4gICAgICAgICAgICBpc1BhZCA9IGZhbHNlO1xuICAgICAgICAgICAgZm9yIChpbnQgaiA9ICR7cmFua30gLSAke3N0cmlkZXNSYW5rfTsgaiA8ICR7cmFua307IGorKykge1xuICAgICAgICAgICAgICB4W2pdID0gaW5kaWNlc1tqXSAqIHN0cmlkZXNbaiAtICR7cmFua30gKyAke3N0cmlkZXNSYW5rfV1cbiAgICAgICAgICAgICAgICArIG9mZnNldFtqIC0gJHtyYW5rfSArICR7c3RyaWRlc1Jhbmt9XSAtIHBhZHNbaiAtIDJdO1xuICAgICAgICAgICAgICAke3BhZENvZGV9XG4gICAgICAgICAgfVxuICAgICAgICAgICR7b3AyfVxuXG4gICAgICAgICAgcmV0dXJuIHZhbHVlO1xuICAgICAgICB9XG4gICAgICBgO1xuICAgICAgICAgICAgcmV0dXJuIHBvb2xpbmdDb2RlO1xuICAgICAgICAgIH1cbiAgICAgICAgfTtcblxuY29uc3QgY29weUFycmF5ID0gKGFycmF5OiByZWFkb25seSBudW1iZXJbXSwgYXJyYXlOYW1lOiBzdHJpbmcpOiBzdHJpbmcgPT4ge1xuICBsZXQgYmxvY2sgPSAnJztcbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBhcnJheS5sZW5ndGg7IGkrKykge1xuICAgIGJsb2NrICs9IGBcbiAgICAgICR7YXJyYXlOYW1lfVske2l9XSA9ICR7YXJyYXlbaV19O1xuICAgIGA7XG4gIH1cbiAgcmV0dXJuIGJsb2NrO1xufTtcblxuY29uc3Qgb2Zmc2V0VG9JbmRpY2VzID0gKHJhbms6IG51bWJlcik6IHN0cmluZyA9PiBgXG4gIHZvaWQgb2Zmc2V0VG9JbmRpY2VzKGludCBvZmZzZXQsIGludFske3Jhbmt9XSBzdHJpZGVzLCBvdXQgaW50WyR7cmFua31dIGluZGljZXMpIHtcbiAgICBpZiAoJHtyYW5rfSA9PSAwKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGZvciAoaW50IGkgPSAwOyBpIDwgJHtyYW5rfSAtIDE7ICsraSkge1xuICAgICAgaW5kaWNlc1tpXSA9IG9mZnNldCAvIHN0cmlkZXNbaV07XG4gICAgICBvZmZzZXQgLT0gaW5kaWNlc1tpXSAqIHN0cmlkZXNbaV07XG4gICAgfVxuICAgIGluZGljZXNbJHtyYW5rfSAtIDFdID0gb2Zmc2V0O1xuICB9YDtcbiIsIi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxuXG5pbXBvcnQge0F0dHJpYnV0ZVdpdGhDYWNoZUtleSwgY3JlYXRlQXR0cmlidXRlV2l0aENhY2hlS2V5fSBmcm9tICcuLi8uLi8uLi9hdHRyaWJ1dGUtd2l0aC1jYWNoZS1rZXknO1xuaW1wb3J0IHtHcmFwaH0gZnJvbSAnLi4vLi4vLi4vZ3JhcGgnO1xuaW1wb3J0IHtOVU1CRVJfVFlQRVMsIE9wZXJhdG9ySW1wbGVtZW50YXRpb24sIE9wZXJhdG9ySW5pdGlhbGl6YXRpb259IGZyb20gJy4uLy4uLy4uL29wZXJhdG9ycyc7XG5pbXBvcnQge1RlbnNvcn0gZnJvbSAnLi4vLi4vLi4vdGVuc29yJztcbmltcG9ydCB7U2hhcGVVdGlsfSBmcm9tICcuLi8uLi8uLi91dGlsJztcbmltcG9ydCB7V2ViR0xJbmZlcmVuY2VIYW5kbGVyfSBmcm9tICcuLi9pbmZlcmVuY2UtaGFuZGxlcic7XG5pbXBvcnQge1Byb2dyYW1JbmZvLCBQcm9ncmFtTWV0YWRhdGEsIFRleHR1cmVUeXBlfSBmcm9tICcuLi90eXBlcyc7XG5cbmV4cG9ydCBpbnRlcmZhY2UgUmVkdWNlQXR0cmlidXRlcyBleHRlbmRzIEF0dHJpYnV0ZVdpdGhDYWNoZUtleSB7XG4gIHJlYWRvbmx5IGF4ZXM6IG51bWJlcltdO1xuICByZWFkb25seSBrZWVwRGltczogYm9vbGVhbjtcbn1cblxuLy8gcmV0dXJuIFtpbml0IG9wcywgcmVkdWNlIG9wcywgZmluYWwgb3BzXVxudHlwZSBSZWR1Y2VPcCA9IChpbnB1dHM6IFRlbnNvcltdLCBheGVzOiBudW1iZXJbXSkgPT4gc3RyaW5nW107XG5cbmNvbnN0IHJlZHVjZSA9XG4gICAgKGluZmVyZW5jZUhhbmRsZXI6IFdlYkdMSW5mZXJlbmNlSGFuZGxlciwgaW5wdXRzOiBUZW5zb3JbXSwgYXR0cmlidXRlczogUmVkdWNlQXR0cmlidXRlcywgbmFtZTogc3RyaW5nLFxuICAgICByZWR1Y2VPcDogUmVkdWNlT3ApOiBUZW5zb3JbXSA9PiB7XG4gICAgICB2YWxpZGF0ZUlucHV0cyhpbnB1dHMpO1xuXG4gICAgICBjb25zdCByZWR1Y2VQcm9ncmFtTWV0YWRhdGEgPSB7XG4gICAgICAgIG5hbWUsXG4gICAgICAgIGlucHV0TmFtZXM6IFsnQSddLFxuICAgICAgICBpbnB1dFR5cGVzOiBbVGV4dHVyZVR5cGUudW5wYWNrZWRdLFxuICAgICAgfTtcblxuICAgICAgY29uc3Qgb3V0cHV0ID0gaW5mZXJlbmNlSGFuZGxlci5ydW4oXG4gICAgICAgICAge1xuICAgICAgICAgICAgLi4ucmVkdWNlUHJvZ3JhbU1ldGFkYXRhLFxuICAgICAgICAgICAgY2FjaGVIaW50OiBhdHRyaWJ1dGVzLmNhY2hlS2V5LFxuICAgICAgICAgICAgZ2V0OiAoKSA9PlxuICAgICAgICAgICAgICAgIGNyZWF0ZVJlZHVjZVByb2dyYW1JbmZvKGluZmVyZW5jZUhhbmRsZXIsIGlucHV0cywgYXR0cmlidXRlcywgbmFtZSwgcmVkdWNlT3AsIHJlZHVjZVByb2dyYW1NZXRhZGF0YSlcbiAgICAgICAgICB9LFxuICAgICAgICAgIGlucHV0cyk7XG4gICAgICByZXR1cm4gW291dHB1dF07XG4gICAgfTtcblxuZXhwb3J0IGNvbnN0IHBhcnNlUmVkdWNlQXR0cmlidXRlczogT3BlcmF0b3JJbml0aWFsaXphdGlvbjxSZWR1Y2VBdHRyaWJ1dGVzPiA9IChub2RlOiBHcmFwaC5Ob2RlKTogUmVkdWNlQXR0cmlidXRlcyA9PiB7XG4gIGNvbnN0IGF4ZXMgPSBub2RlLmF0dHJpYnV0ZXMuZ2V0SW50cygnYXhlcycsIFtdKTtcbiAgY29uc3Qga2VlcERpbXMgPSBub2RlLmF0dHJpYnV0ZXMuZ2V0SW50KCdrZWVwZGltcycsIDEpID09PSAxO1xuICByZXR1cm4gY3JlYXRlQXR0cmlidXRlV2l0aENhY2hlS2V5KHtheGVzLCBrZWVwRGltc30pO1xufTtcblxuY29uc3QgY3JlYXRlUmVkdWNlUHJvZ3JhbUluZm8gPVxuICAgIChoYW5kbGVyOiBXZWJHTEluZmVyZW5jZUhhbmRsZXIsIGlucHV0czogVGVuc29yW10sIGF0dHJpYnV0ZXM6IFJlZHVjZUF0dHJpYnV0ZXMsIG5hbWU6IHN0cmluZywgcmVkdWNlT3A6IFJlZHVjZU9wLFxuICAgICByZWR1Y2VQcm9ncmFtTWV0YWRhdGE6IFByb2dyYW1NZXRhZGF0YSk6IFByb2dyYW1JbmZvID0+IHtcbiAgICAgIGNvbnN0IG91dHB1dFNoYXBlOiBudW1iZXJbXSA9IFtdO1xuICAgICAgY29uc3QgaVJhbmsgPSBpbnB1dHNbMF0uZGltcy5sZW5ndGggfHwgMTtcblxuICAgICAgY29uc3QgaWR4Q29weSA9IFtdOyAgLy8gY29weSBvdXRwdXQgaW5kZXhlcyB0byBpbnB1dCBpbmRleGVzXG5cbiAgICAgIGNvbnN0IGF4ZXMgPSBTaGFwZVV0aWwubm9ybWFsaXplQXhlcyhhdHRyaWJ1dGVzLmF4ZXMsIGlucHV0c1swXS5kaW1zLmxlbmd0aCk7XG4gICAgICBjb25zdCBvcHMgPSByZWR1Y2VPcChpbnB1dHMsIGF4ZXMpO1xuICAgICAgbGV0IHJlZHVjZU9wcyA9IG9wc1sxXTtcblxuICAgICAgZm9yIChsZXQgayA9IDA7IGsgPCBpbnB1dHNbMF0uZGltcy5sZW5ndGg7IGsrKykge1xuICAgICAgICAvLyBpZiB0aGlzIGF4aXMgaXMgcmVkdWNlZFxuICAgICAgICBpZiAoYXhlcy5pbmRleE9mKGspID49IDAgfHwgYXhlcy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICBpZiAoYXR0cmlidXRlcy5rZWVwRGltcykge1xuICAgICAgICAgICAgb3V0cHV0U2hhcGUucHVzaCgxKTtcbiAgICAgICAgICB9ICAvLyBlbHNlIHsgcmVtb3ZlIHRoZSBheGlzIGZyb20gb3V0cHV0U2hhcGU7IH1cblxuICAgICAgICAgIC8vIGxvb3Agb3ZlciB0aGUgZC10aCBheGlzXG4gICAgICAgICAgcmVkdWNlT3BzID0gYFxuICAgICAgICAgIGZvcihpbnQgaiR7a30gPSAwOyBqJHtrfSA8ICR7aW5wdXRzWzBdLmRpbXNba119OyBqJHtrfSsrKSB7XG4gICAgICAgICAgICBpbnB1dElkeFske2t9XSA9IGoke2t9O1xuICAgICAgICAgICAgJHtyZWR1Y2VPcHN9XG4gICAgICAgICAgfWA7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgaWR4Q29weS5wdXNoKGBpbnB1dElkeFske2t9XSA9IG91dHB1dElkeFske291dHB1dFNoYXBlLmxlbmd0aH1dO2ApO1xuXG4gICAgICAgICAgb3V0cHV0U2hhcGUucHVzaChpbnB1dHNbMF0uZGltc1trXSk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgY29uc3Qgb1JhbmsgPSBvdXRwdXRTaGFwZS5sZW5ndGggfHwgMTtcblxuICAgICAgY29uc3Qgc2hhZGVyU291cmNlID0gYFxuICAgICAgZmxvYXQgcHJvY2VzcyhpbnQgb3V0cHV0SWR4WyR7b1Jhbmt9XSkge1xuICAgICAgICBmbG9hdCB2YWx1ZTsgICAgICAgICAgICAgICAgIC8vIGZpbmFsIHJlc3VsdFxuICAgICAgICBpbnQgaW5wdXRJZHhbJHtpUmFua31dOyAgICAgIC8vIGFkZHJlc3NpbmcgaW5wdXQgZGF0YVxuICAgICAgICAke2lkeENvcHkuam9pbignXFxuJyl9XG4gICAgICAgICR7b3BzWzBdfSAgICAgICAvLyBpbml0IG9wcyBmb3IgcmVkdWNlIG1heC9taW5cbiAgICAgICAgJHtyZWR1Y2VPcHN9XG4gICAgICAgICR7b3BzWzJdfSAgICAgICAvLyBmaW5hbCBjb21wdXRhdGlvbiBmb3IgcmVkdWNlIG1lYW5cbiAgICAgICAgcmV0dXJuIHZhbHVlO1xuICAgICAgfWA7XG5cbiAgICAgIHJldHVybiB7XG4gICAgICAgIC4uLnJlZHVjZVByb2dyYW1NZXRhZGF0YSxcbiAgICAgICAgb3V0cHV0OiB7ZGltczogb3V0cHV0U2hhcGUsIHR5cGU6IGlucHV0c1swXS50eXBlLCB0ZXh0dXJlVHlwZTogVGV4dHVyZVR5cGUudW5wYWNrZWR9LFxuICAgICAgICBzaGFkZXJTb3VyY2VcbiAgICAgIH07XG4gICAgfTtcblxuY29uc3QgdmFsaWRhdGVJbnB1dHMgPSAoaW5wdXRzOiBUZW5zb3JbXSk6IHZvaWQgPT4ge1xuICBpZiAoIWlucHV0cyB8fCBpbnB1dHMubGVuZ3RoICE9PSAxKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdSZWR1Y2Ugb3AgcmVxdWlyZXMgMSBpbnB1dC4nKTtcbiAgfVxuXG4gIGlmIChOVU1CRVJfVFlQRVMuaW5kZXhPZihpbnB1dHNbMF0udHlwZSkgPT09IC0xKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIGlucHV0IHR5cGUuJyk7XG4gIH1cbn07XG5cbmV4cG9ydCBjb25zdCByZWR1Y2VTdW06IE9wZXJhdG9ySW1wbGVtZW50YXRpb248UmVkdWNlQXR0cmlidXRlcz4gPVxuICAgIChpbmZlcmVuY2VIYW5kbGVyOiBXZWJHTEluZmVyZW5jZUhhbmRsZXIsIGlucHV0czogVGVuc29yW10sIGF0dHJpYnV0ZXM6IFJlZHVjZUF0dHJpYnV0ZXMpOiBUZW5zb3JbXSA9PiB7XG4gICAgICBjb25zdCByZWR1Y2VPcDogUmVkdWNlT3AgPSAoKTogc3RyaW5nW10gPT4gWyd2YWx1ZSA9IDAuMDsnLCAndmFsdWUgKz0gX0EoaW5wdXRJZHgpOycsICcnXTtcbiAgICAgIHJldHVybiByZWR1Y2UoaW5mZXJlbmNlSGFuZGxlciwgaW5wdXRzLCBhdHRyaWJ1dGVzLCAnUmVkdWNlU3VtJywgcmVkdWNlT3ApO1xuICAgIH07XG5cbmV4cG9ydCBjb25zdCByZWR1Y2VNZWFuOiBPcGVyYXRvckltcGxlbWVudGF0aW9uPFJlZHVjZUF0dHJpYnV0ZXM+ID1cbiAgICAoaW5mZXJlbmNlSGFuZGxlcjogV2ViR0xJbmZlcmVuY2VIYW5kbGVyLCBpbnB1dHM6IFRlbnNvcltdLCBhdHRyaWJ1dGVzOiBSZWR1Y2VBdHRyaWJ1dGVzKTogVGVuc29yW10gPT4ge1xuICAgICAgY29uc3QgcmVkdWNlT3A6IFJlZHVjZU9wID0gKGlucHV0czogVGVuc29yW10sIGF4ZXM6IG51bWJlcltdKTogc3RyaW5nW10gPT4ge1xuICAgICAgICBsZXQgc2l6ZSA9IDEuMDtcbiAgICAgICAgZm9yIChsZXQgayA9IDA7IGsgPCBpbnB1dHNbMF0uZGltcy5sZW5ndGg7IGsrKykge1xuICAgICAgICAgIGlmIChheGVzLmluZGV4T2YoaykgPj0gMCB8fCBheGVzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgc2l6ZSAqPSBpbnB1dHNbMF0uZGltc1trXTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gWyd2YWx1ZSA9IDAuMDsnLCAndmFsdWUgKz0gX0EoaW5wdXRJZHgpOycsIGB2YWx1ZSAvPSAke3NpemV9LjtgXTsgIC8vIGVuc3VyZSByZWFsIG51bWJlciB3aXRoIGAuYFxuICAgICAgfTtcbiAgICAgIHJldHVybiByZWR1Y2UoaW5mZXJlbmNlSGFuZGxlciwgaW5wdXRzLCBhdHRyaWJ1dGVzLCAnUmVkdWNlTWVhbicsIHJlZHVjZU9wKTtcbiAgICB9O1xuXG5leHBvcnQgY29uc3QgcmVkdWNlTWF4OiBPcGVyYXRvckltcGxlbWVudGF0aW9uPFJlZHVjZUF0dHJpYnV0ZXM+ID1cbiAgICAoaW5mZXJlbmNlSGFuZGxlcjogV2ViR0xJbmZlcmVuY2VIYW5kbGVyLCBpbnB1dHM6IFRlbnNvcltdLCBhdHRyaWJ1dGVzOiBSZWR1Y2VBdHRyaWJ1dGVzKTogVGVuc29yW10gPT4ge1xuICAgICAgY29uc3QgcmVkdWNlT3A6IFJlZHVjZU9wID0gKGlucHV0czogVGVuc29yW10sIGF4ZXM6IG51bWJlcltdKTogc3RyaW5nW10gPT4ge1xuICAgICAgICBjb25zdCBpZHhaZXJvID0gW107XG4gICAgICAgIGZvciAobGV0IGsgPSAwOyBrIDwgaW5wdXRzWzBdLmRpbXMubGVuZ3RoOyBrKyspIHtcbiAgICAgICAgICBpZiAoYXhlcy5pbmRleE9mKGspID49IDAgfHwgYXhlcy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgIGlkeFplcm8ucHVzaChgaW5wdXRJZHhbJHtrfV0gPSAwO2ApOyAgLy8gZmlyc3QgZWxlbWVudFxuICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBbYCR7aWR4WmVyby5qb2luKCdcXG4nKX1cXG52YWx1ZSA9IF9BKGlucHV0SWR4KTtgLCAndmFsdWUgPSBtYXgodmFsdWUsIF9BKGlucHV0SWR4KSk7JywgJyddO1xuICAgICAgfTtcbiAgICAgIHJldHVybiByZWR1Y2UoaW5mZXJlbmNlSGFuZGxlciwgaW5wdXRzLCBhdHRyaWJ1dGVzLCAnUmVkdWNlTWF4JywgcmVkdWNlT3ApO1xuICAgIH07XG5cbmV4cG9ydCBjb25zdCByZWR1Y2VNaW46IE9wZXJhdG9ySW1wbGVtZW50YXRpb248UmVkdWNlQXR0cmlidXRlcz4gPVxuICAgIChpbmZlcmVuY2VIYW5kbGVyOiBXZWJHTEluZmVyZW5jZUhhbmRsZXIsIGlucHV0czogVGVuc29yW10sIGF0dHJpYnV0ZXM6IFJlZHVjZUF0dHJpYnV0ZXMpOiBUZW5zb3JbXSA9PiB7XG4gICAgICBjb25zdCByZWR1Y2VPcDogUmVkdWNlT3AgPSAoaW5wdXRzOiBUZW5zb3JbXSwgYXhlczogbnVtYmVyW10pOiBzdHJpbmdbXSA9PiB7XG4gICAgICAgIGNvbnN0IGlkeFplcm8gPSBbXTtcbiAgICAgICAgZm9yIChsZXQgayA9IDA7IGsgPCBpbnB1dHNbMF0uZGltcy5sZW5ndGg7IGsrKykge1xuICAgICAgICAgIGlmIChheGVzLmluZGV4T2YoaykgPj0gMCB8fCBheGVzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgaWR4WmVyby5wdXNoKGBpbnB1dElkeFske2t9XSA9IDA7YCk7ICAvLyBmaXJzdCBlbGVtZW50XG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIFtgJHtpZHhaZXJvLmpvaW4oJ1xcbicpfVxcbnZhbHVlID0gX0EoaW5wdXRJZHgpO2AsICd2YWx1ZSA9IG1pbih2YWx1ZSwgX0EoaW5wdXRJZHgpKTsnLCAnJ107XG4gICAgICB9O1xuICAgICAgcmV0dXJuIHJlZHVjZShpbmZlcmVuY2VIYW5kbGVyLCBpbnB1dHMsIGF0dHJpYnV0ZXMsICdSZWR1Y2VNaW4nLCByZWR1Y2VPcCk7XG4gICAgfTtcblxuZXhwb3J0IGNvbnN0IHJlZHVjZVByb2Q6IE9wZXJhdG9ySW1wbGVtZW50YXRpb248UmVkdWNlQXR0cmlidXRlcz4gPVxuICAgIChpbmZlcmVuY2VIYW5kbGVyOiBXZWJHTEluZmVyZW5jZUhhbmRsZXIsIGlucHV0czogVGVuc29yW10sIGF0dHJpYnV0ZXM6IFJlZHVjZUF0dHJpYnV0ZXMpOiBUZW5zb3JbXSA9PiB7XG4gICAgICBjb25zdCByZWR1Y2VPcDogUmVkdWNlT3AgPSAoKTogc3RyaW5nW10gPT4gWyd2YWx1ZSA9IDEuMDsnLCAndmFsdWUgKj0gX0EoaW5wdXRJZHgpOycsICcnXTtcbiAgICAgIHJldHVybiByZWR1Y2UoaW5mZXJlbmNlSGFuZGxlciwgaW5wdXRzLCBhdHRyaWJ1dGVzLCAnUmVkdWNlUHJvZCcsIHJlZHVjZU9wKTtcbiAgICB9O1xuXG5leHBvcnQgY29uc3QgcmVkdWNlTG9nU3VtOiBPcGVyYXRvckltcGxlbWVudGF0aW9uPFJlZHVjZUF0dHJpYnV0ZXM+ID1cbiAgICAoaW5mZXJlbmNlSGFuZGxlcjogV2ViR0xJbmZlcmVuY2VIYW5kbGVyLCBpbnB1dHM6IFRlbnNvcltdLCBhdHRyaWJ1dGVzOiBSZWR1Y2VBdHRyaWJ1dGVzKTogVGVuc29yW10gPT4ge1xuICAgICAgY29uc3QgcmVkdWNlT3A6IFJlZHVjZU9wID0gKCk6IHN0cmluZ1tdID0+IFsndmFsdWUgPSAwLjA7JywgJ3ZhbHVlICs9IF9BKGlucHV0SWR4KTsnLCAndmFsdWUgPSBsb2codmFsdWUpOyddO1xuICAgICAgcmV0dXJuIHJlZHVjZShpbmZlcmVuY2VIYW5kbGVyLCBpbnB1dHMsIGF0dHJpYnV0ZXMsICdSZWR1Y2VMb2dTdW0nLCByZWR1Y2VPcCk7XG4gICAgfTtcblxuZXhwb3J0IGNvbnN0IHJlZHVjZUxvZ1N1bVNxdWFyZTogT3BlcmF0b3JJbXBsZW1lbnRhdGlvbjxSZWR1Y2VBdHRyaWJ1dGVzPiA9XG4gICAgKGluZmVyZW5jZUhhbmRsZXI6IFdlYkdMSW5mZXJlbmNlSGFuZGxlciwgaW5wdXRzOiBUZW5zb3JbXSwgYXR0cmlidXRlczogUmVkdWNlQXR0cmlidXRlcyk6IFRlbnNvcltdID0+IHtcbiAgICAgIGNvbnN0IHJlZHVjZU9wOiBSZWR1Y2VPcCA9ICgpOiBzdHJpbmdbXSA9PiBbJ2Zsb2F0IHQ7IHZhbHVlID0gMC4wOycsICd0ID0gX0EoaW5wdXRJZHgpOyB2YWx1ZSArPSB0ICogdDsnLCAnJ107XG4gICAgICByZXR1cm4gcmVkdWNlKGluZmVyZW5jZUhhbmRsZXIsIGlucHV0cywgYXR0cmlidXRlcywgJ1JlZHVjZUxvZ1N1bVNxdWFyZScsIHJlZHVjZU9wKTtcbiAgICB9OyIsIi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxuXG5pbXBvcnQge1RlbnNvcn0gZnJvbSAnLi4vLi4vLi4vdGVuc29yJztcbmltcG9ydCB7U2hhcGVVdGlsfSBmcm9tICcuLi8uLi8uLi91dGlsJztcbmltcG9ydCB7Z2V0R2xzbH0gZnJvbSAnLi4vZ2xzbC1zb3VyY2UnO1xuaW1wb3J0IHtXZWJHTEluZmVyZW5jZUhhbmRsZXJ9IGZyb20gJy4uL2luZmVyZW5jZS1oYW5kbGVyJztcbmltcG9ydCB7UHJvZ3JhbUluZm8sIFByb2dyYW1JbmZvTG9hZGVyLCBQcm9ncmFtTWV0YWRhdGEsIFRleHR1cmVUeXBlfSBmcm9tICcuLi90eXBlcyc7XG5cbmltcG9ydCB7dW5wYWNrRnJvbUNoYW5uZWx9IGZyb20gJy4vcGFja2luZy11dGlscyc7XG5cbmNvbnN0IGNyZWF0ZVBhY2tlZFJlc2hhcGUzRFByb2dyYW1NZXRhZGF0YSA9IChvdXRwdXRTaGFwZTNEOiByZWFkb25seSBudW1iZXJbXSkgPT5cbiAgICAoe25hbWU6ICdSZXNoYXBlIChwYWNrZWQpJywgaW5wdXRUeXBlczogW1RleHR1cmVUeXBlLnBhY2tlZF0sIGlucHV0TmFtZXM6IFsnQSddLCBjYWNoZUhpbnQ6IGAke291dHB1dFNoYXBlM0R9YH0pO1xuXG5jb25zdCBjcmVhdGVQYWNrZWRSZXNoYXBlM0RQcm9ncmFtSW5mbyA9XG4gICAgKGhhbmRsZXI6IFdlYkdMSW5mZXJlbmNlSGFuZGxlciwgaW5wdXQzRDogVGVuc29yLCBtZXRhZGF0YTogUHJvZ3JhbU1ldGFkYXRhLCBvdXRwdXRTaGFwZTNEOiByZWFkb25seSBudW1iZXJbXSk6XG4gICAgICAgIFByb2dyYW1JbmZvID0+IHtcbiAgICAgICAgICBjb25zdCBpbnB1dFNoYXBlM0QgPSBpbnB1dDNELmRpbXMgYXMgW251bWJlciwgbnVtYmVyLCBudW1iZXJdO1xuICAgICAgICAgIGNvbnN0IHNxdWVlemVkT3V0cHV0U2hhcGUgPSBvdXRwdXRTaGFwZTNEIGFzIFtudW1iZXIsIG51bWJlciwgbnVtYmVyXTtcblxuICAgICAgICAgIGxldCBtYWluTG9vcCA9ICcnO1xuICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgNDsgaSsrKSB7XG4gICAgICAgICAgICBsZXQgb3V0cHV0Q29vcmRzID0gJyc7XG4gICAgICAgICAgICBzd2l0Y2ggKGkpIHtcbiAgICAgICAgICAgICAgY2FzZSAwOlxuICAgICAgICAgICAgICAgIG91dHB1dENvb3JkcyA9ICdvdXRwdXRDb29yZHMgPSByYzsnO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICBjYXNlIDE6XG4gICAgICAgICAgICAgICAgb3V0cHV0Q29vcmRzID0gJ291dHB1dENvb3JkcyA9IGl2ZWMzKHJjLngsIHJjLnkrMSwgcmMueik7JztcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgY2FzZSAyOlxuICAgICAgICAgICAgICAgIG91dHB1dENvb3JkcyA9ICdvdXRwdXRDb29yZHMgPSBpdmVjMyhyYy54LCByYy55LCByYy56KzEpOyc7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgIGNhc2UgMzpcbiAgICAgICAgICAgICAgICBvdXRwdXRDb29yZHMgPSAnb3V0cHV0Q29vcmRzID0gaXZlYzMocmMueCwgcmMueSsxLCByYy56KzEpOyc7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIG1haW5Mb29wICs9IGBcbiAgICAgICAgJHtvdXRwdXRDb29yZHN9XG4gICAgICAgICR7aSA+IDAgPyAnaWYob3V0cHV0Q29vcmRzLnkgPCByb3dzICYmIG91dHB1dENvb3Jkcy56IDwgY29scyl7JyA6ICcnfVxuICAgICAgICAgIGludCBmbGF0dGVuZWRJbmRleCA9IGdldEZsYXR0ZW5lZEluZGV4KG91dHB1dENvb3Jkcyk7XG5cbiAgICAgICAgICBpdmVjMyBpbnB1dFJDID0gaW5wdXRDb29yZHNGcm9tUmVzaGFwZWRPdXRDb29yZHMoZmxhdHRlbmVkSW5kZXgpO1xuICAgICAgICAgIHZlYzIgaW5uZXJEaW1zID0gdmVjMihmbG9hdChpbnB1dFJDLnkpLGZsb2F0KGlucHV0UkMueikpO1xuXG4gICAgICAgICAgcmVzdWx0WyR7aX1dID0gZ2V0Q2hhbm5lbChnZXRBKGlucHV0UkMueCwgaW5wdXRSQy55LCBpbnB1dFJDLnopLCBpbm5lckRpbXMpO1xuXG4gICAgICAgICR7aSA+IDAgPyAnfScgOiAnJ31cbiAgICAgIGA7XG4gICAgICAgICAgfVxuICAgICAgICAgIGNvbnN0IGdsc2wgPSBnZXRHbHNsKGhhbmRsZXIuc2Vzc2lvbi5iYWNrZW5kLmdsQ29udGV4dC52ZXJzaW9uKTtcblxuICAgICAgICAgIGNvbnN0IHNoYWRlclNvdXJjZSA9IGBcbiAgICAgICR7Z2V0UmVzaGFwZWRJbnB1dENvb3JkcyhpbnB1dFNoYXBlM0QpfVxuICAgICAgJHtnZXRGbGF0dGVuZWRJbmRleEZyb20zRChzcXVlZXplZE91dHB1dFNoYXBlKX1cbiAgICAgICR7dW5wYWNrRnJvbUNoYW5uZWwoKX1cblxuICAgICAgdm9pZCBtYWluKCkge1xuICAgICAgICBpdmVjMyByYyA9IGdldE91dHB1dENvb3JkcygpO1xuXG4gICAgICAgIHZlYzQgcmVzdWx0ID0gdmVjNCgwLjApO1xuXG4gICAgICAgIGl2ZWMzIG91dHB1dENvb3JkcztcbiAgICAgICAgaW50IHJvd3MgPSAke3NxdWVlemVkT3V0cHV0U2hhcGVbMl19O1xuICAgICAgICBpbnQgY29scyA9ICR7c3F1ZWV6ZWRPdXRwdXRTaGFwZVsxXX07XG5cbiAgICAgICAgJHttYWluTG9vcH1cbiAgICAgICAgJHtnbHNsLm91dHB1dH0gPSByZXN1bHQ7XG4gICAgICB9XG4gICAgYDtcblxuICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAuLi5tZXRhZGF0YSxcbiAgICAgICAgICAgIG91dHB1dDoge2RpbXM6IHNxdWVlemVkT3V0cHV0U2hhcGUsIHR5cGU6IGlucHV0M0QudHlwZSwgdGV4dHVyZVR5cGU6IFRleHR1cmVUeXBlLnBhY2tlZH0sXG4gICAgICAgICAgICBzaGFkZXJTb3VyY2UsXG4gICAgICAgICAgICBoYXNNYWluOiB0cnVlXG4gICAgICAgICAgfTtcbiAgICAgICAgfTtcblxuZXhwb3J0IGNvbnN0IGNyZWF0ZVBhY2tlZFJlc2hhcGUzRFByb2dyYW1JbmZvTG9hZGVyID1cbiAgICAoaGFuZGxlcjogV2ViR0xJbmZlcmVuY2VIYW5kbGVyLCBpbnB1dDNEOiBUZW5zb3IsIG91dHB1dFNoYXBlM0Q6IHJlYWRvbmx5IG51bWJlcltdKTogUHJvZ3JhbUluZm9Mb2FkZXIgPT4ge1xuICAgICAgY29uc3QgbWV0YWRhdGEgPSBjcmVhdGVQYWNrZWRSZXNoYXBlM0RQcm9ncmFtTWV0YWRhdGEob3V0cHV0U2hhcGUzRCk7XG4gICAgICByZXR1cm4gey4uLm1ldGFkYXRhLCBnZXQ6ICgpID0+IGNyZWF0ZVBhY2tlZFJlc2hhcGUzRFByb2dyYW1JbmZvKGhhbmRsZXIsIGlucHV0M0QsIG1ldGFkYXRhLCBvdXRwdXRTaGFwZTNEKX07XG4gICAgfTtcblxuZXhwb3J0IGZ1bmN0aW9uIHByb2Nlc3NEaW1zM0Qoc2hhcGU6IEFycmF5TGlrZTxudW1iZXI+KTogW251bWJlciwgbnVtYmVyLCBudW1iZXJdIHtcbiAgaWYgKHNoYXBlLmxlbmd0aCA9PT0gMCkge1xuICAgIHJldHVybiBbMSwgMSwgMV07XG4gIH1cbiAgLy8gVE9ETzogc3F1ZWV6ZSBvdGhlciBzaGFwZXMgdG8gMkQgY2FzZVxuICBsZXQgYmF0Y2ggPSAxO1xuICBmb3IgKGxldCBpID0gMDsgaSA8IHNoYXBlLmxlbmd0aCAtIDI7ICsraSkge1xuICAgIGJhdGNoICo9IHNoYXBlW2ldO1xuICB9XG4gIHJldHVybiBbYmF0Y2gsIHNoYXBlLmxlbmd0aCA+IDEgPyBzaGFwZVtzaGFwZS5sZW5ndGggLSAyXSA6IDEsIHNoYXBlW3NoYXBlLmxlbmd0aCAtIDFdXTtcbn1cblxuLy8gRm9yIHBhY2tlZCByZXNoYXBlLCB3ZSBuZWVkIHRvIHJlLWFycmFuZ2UgdGV4ZWwgZGF0YSBmb3Igb3V0cHV0IHNoYXBlLlxuLy8gT3VyIHBhY2sgaXMgZGVzaWduZWQgdG8gcGFjayBhIDJ4MiB0aWxlIGluIGxhc3QgaCBhbmQgdyBkaW1lbnNpb24sIHNvXG4vLyBmb3IgdGhlIHJlc2hhcGVkIG5ldyB0ZW5zb3IsIHdlIGp1c3QgbmVlZCB0byByZS1hcnJhbmdlIHRoZSBsYXN0IGggYW5kXG4vLyB3IGRpbWVuc2lvbi4gRm9yIGFueSBzaGFwZSB0aGF0IGlzIG5vdCBpbiAzRCwgaS5lLiBbYmF0Y2gsIFcsIEhdLCB3ZVxuLy8gZmlyc3QgY29udmVydCBpdCB0byAzRCBieSBjb2xsYXBzaW5nIG90aGVyIGRpbWVuc2lvbiB0byBiYXRjaCBkaW0sIHRoZW5cbi8vIHByb2Nlc3Mgd2l0aCB0aGUgbGFzdCB0d28gZGltZW5zaW9ucy5cbi8vIE5vdGU6IHdlIG9ubHkgbmVlZCB0aGUgc2hhcGUgdGVuc29yIHRvIGNhbGN1bGF0ZSBvdXRwdXQgc2hhcGUsIHNvIHRoZVxuLy8gY29udGVudCBpbiBzaGFwZSB0ZW5zb3IgaXMgbmV2ZXIgdXBsb2FkZWQgdG8gR1BVLiBJdCBpcyBhbHdheXMga2VwdCBpbiBDUFUuXG4vLyBUT0RPOiBvcHRpbWl6ZSB0aGUgYWxnb3JpdGhtIC0tIGluIHNvbWUgY2FzZXMsIGlmIHRoZSBsYXN0IHR3byBkaW1zIGFyZVxuLy8gdGhlIHNhbWUgYmV0d2VlbiBpbnB1dCBzaGFwZSBhbmQgb3V0cHV0IHNoYXBlLCB0aGUgcGFja2VkIHJlc2hhcGUgY2FuIGJlXG4vLyB0cmVhdGVkIGFzIG5vLW9wLlxuZXhwb3J0IGZ1bmN0aW9uIGlzUmVzaGFwZUNoZWFwKGRpbXM6IHJlYWRvbmx5IG51bWJlcltdLCByZXNoYXBlZERpbXM6IHJlYWRvbmx5IG51bWJlcltdKSB7XG4gIGxldCBpc0NoZWFwUmVzaGFwZSA9IGZhbHNlO1xuICBpZiAoZGltcy5sZW5ndGggPT09IDAgfHwgcmVzaGFwZWREaW1zLmxlbmd0aCA9PT0gMCkgeyAgLy8gc2NhbGFyXG4gICAgaXNDaGVhcFJlc2hhcGUgPSB0cnVlO1xuICB9IGVsc2UgaWYgKGRpbXMubGVuZ3RoIDwgMiB8fCByZXNoYXBlZERpbXMubGVuZ3RoIDwgMikgeyAgLy8gMURcbiAgICBpc0NoZWFwUmVzaGFwZSA9IGRpbXNbZGltcy5sZW5ndGggLSAxXSA9PT0gcmVzaGFwZWREaW1zW3Jlc2hhcGVkRGltcy5sZW5ndGggLSAxXTtcbiAgfSBlbHNlIHsgIC8vIDJEICtcbiAgICBpc0NoZWFwUmVzaGFwZSA9IGRpbXNbZGltcy5sZW5ndGggLSAxXSA9PT0gcmVzaGFwZWREaW1zW3Jlc2hhcGVkRGltcy5sZW5ndGggLSAxXSAmJlxuICAgICAgICBkaW1zW2RpbXMubGVuZ3RoIC0gMl0gPT09IHJlc2hhcGVkRGltc1tyZXNoYXBlZERpbXMubGVuZ3RoIC0gMl07XG4gIH1cblxuICByZXR1cm4gaXNDaGVhcFJlc2hhcGU7XG59XG5cbmZ1bmN0aW9uIGdldFJlc2hhcGVkSW5wdXRDb29yZHMoc2hhcGU6IFtudW1iZXIsIG51bWJlciwgbnVtYmVyXSk6IHN0cmluZyB7XG4gIGNvbnN0IHN0cmlkZXMgPSBTaGFwZVV0aWwuY29tcHV0ZVN0cmlkZXMoc2hhcGUpO1xuICBjb25zdCBjb29yZHMgPSBbJ2InLCAncicsICdjJ107XG4gIGNvbnN0IGluZGV4ID0gJ2luZGV4JztcbiAgY29uc3QgY29vcmRzRnJvbUluZGV4U25pcHBldCA9IHN0cmlkZXNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAubWFwKChzdHJpZGUsIGkpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGxpbmUxID0gYGludCAke2Nvb3Jkc1tpXX0gPSAke2luZGV4fSAvICR7c3RyaWRlfWA7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBsaW5lMiA9IGkgPT09IHN0cmlkZXMubGVuZ3RoIC0gMSA/XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYGludCAke2Nvb3Jkc1tpICsgMV19ID0gJHtpbmRleH0gLSAke2Nvb3Jkc1tpXX0gKiAke3N0cmlkZX1gIDpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBgaW5kZXggLT0gJHtjb29yZHNbaV19ICogJHtzdHJpZGV9YDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBgJHtsaW5lMX07ICR7bGluZTJ9O2A7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAuam9pbignJyk7XG5cbiAgcmV0dXJuIGBcbiAgICBpdmVjMyBpbnB1dENvb3Jkc0Zyb21SZXNoYXBlZE91dENvb3JkcyhpbnQgaW5kZXgpIHtcbiAgICAgICR7Y29vcmRzRnJvbUluZGV4U25pcHBldH1cbiAgICAgIHJldHVybiBpdmVjMyhiLCByLCBjKTtcbiAgICB9XG4gIGA7XG59XG5cbmZ1bmN0aW9uIGdldEZsYXR0ZW5lZEluZGV4RnJvbTNEKHNoYXBlOiBbbnVtYmVyLCBudW1iZXIsIG51bWJlcl0pOiBzdHJpbmcge1xuICBjb25zdCBzdHJpZGVzID0gU2hhcGVVdGlsLmNvbXB1dGVTdHJpZGVzKHNoYXBlKTtcblxuICByZXR1cm4gYFxuICBpbnQgZ2V0RmxhdHRlbmVkSW5kZXgoaXZlYzMgY29vcmRzKSB7XG4gICAgLy8gcmV2ZXJzZSB5LCB6IG9yZGVyXG4gICAgcmV0dXJuIGNvb3Jkcy54ICogJHtzdHJpZGVzWzBdfSArIGNvb3Jkcy56ICogJHtzdHJpZGVzWzFdfSArIGNvb3Jkcy55O1xuICB9XG5gO1xufVxuIiwiLy8gQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXG5cbmltcG9ydCB7VGVuc29yfSBmcm9tICcuLi8uLi8uLi90ZW5zb3InO1xuaW1wb3J0IHtTaGFwZVV0aWx9IGZyb20gJy4uLy4uLy4uL3V0aWwnO1xuaW1wb3J0IHtXZWJHTEluZmVyZW5jZUhhbmRsZXJ9IGZyb20gJy4uL2luZmVyZW5jZS1oYW5kbGVyJztcblxuZXhwb3J0IGNvbnN0IHJlc2hhcGUgPSAoaGFuZGxlcjogV2ViR0xJbmZlcmVuY2VIYW5kbGVyLCBpbnB1dHM6IFRlbnNvcltdKTogVGVuc29yW10gPT4ge1xuICBjb25zdCByZXNoYXBlZERpbXMgPSBTaGFwZVV0aWwuY2FsY3VsYXRlUmVzaGFwZWREaW1zKGlucHV0c1swXS5kaW1zLCBpbnB1dHNbMV0uaW50ZWdlckRhdGEpO1xuICBpZiAoaGFuZGxlci5zZXNzaW9uLnBhY2spIHtcbiAgICByZXR1cm4gW2hhbmRsZXIucmVzaGFwZVBhY2tlZChpbnB1dHNbMF0sIHJlc2hhcGVkRGltcyldO1xuICB9IGVsc2Uge1xuICAgIHJldHVybiBbaGFuZGxlci5yZXNoYXBlVW5wYWNrZWQoaW5wdXRzWzBdLCByZXNoYXBlZERpbXMpXTtcbiAgfVxufTtcbiIsIi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxuXG5pbXBvcnQge0dyYXBofSBmcm9tICcuLi8uLi8uLi9ncmFwaCc7XG5pbXBvcnQge09wZXJhdG9ySW1wbGVtZW50YXRpb24sIE9wZXJhdG9ySW5pdGlhbGl6YXRpb259IGZyb20gJy4uLy4uLy4uL29wZXJhdG9ycyc7XG5pbXBvcnQge1RlbnNvcn0gZnJvbSAnLi4vLi4vLi4vdGVuc29yJztcbmltcG9ydCB7Z2V0R2xzbH0gZnJvbSAnLi4vZ2xzbC1zb3VyY2UnO1xuaW1wb3J0IHtXZWJHTEluZmVyZW5jZUhhbmRsZXJ9IGZyb20gJy4uL2luZmVyZW5jZS1oYW5kbGVyJztcbmltcG9ydCB7UHJvZ3JhbUluZm8sIFRleHR1cmVUeXBlfSBmcm9tICcuLi90eXBlcyc7XG5pbXBvcnQge2dldENvb3Jkc0RhdGFUeXBlfSBmcm9tICcuLi91dGlscyc7XG5cbmltcG9ydCB7dW5wYWNrRnJvbUNoYW5uZWx9IGZyb20gJy4vcGFja2luZy11dGlscyc7XG5pbXBvcnQge3BhcnNlVXBzYW1wbGVBdHRyaWJ1dGVzLCBzY2FsZXNWYWxpZGF0aW9uLCBVcHNhbXBsZUF0dHJpYnV0ZXMsIHZhbGlkYXRlSW5wdXRzfSBmcm9tICcuL3Vwc2FtcGxlJztcblxuY29uc3QgcmVzaXplUHJvZ3JhbU1ldGFkYXRhID0ge1xuICBuYW1lOiAnUmVzaXplJyxcbiAgaW5wdXROYW1lczogWydBJ10sXG4gIGlucHV0VHlwZXM6IFtUZXh0dXJlVHlwZS5wYWNrZWRdXG59O1xuXG5leHBvcnQgY29uc3QgcmVzaXplOiBPcGVyYXRvckltcGxlbWVudGF0aW9uPFVwc2FtcGxlQXR0cmlidXRlcz4gPVxuICAgIChpbmZlcmVuY2VIYW5kbGVyOiBXZWJHTEluZmVyZW5jZUhhbmRsZXIsIGlucHV0czogVGVuc29yW10sIGF0dHJpYnV0ZXM6IFVwc2FtcGxlQXR0cmlidXRlcyk6IFRlbnNvcltdID0+IHtcbiAgICAgIHZhbGlkYXRlSW5wdXRzKGlucHV0cywgYXR0cmlidXRlcyk7XG4gICAgICBjb25zdCBvdXRwdXQgPSBpbmZlcmVuY2VIYW5kbGVyLnJ1bihcbiAgICAgICAgICB7XG4gICAgICAgICAgICAuLi5yZXNpemVQcm9ncmFtTWV0YWRhdGEsXG4gICAgICAgICAgICBjYWNoZUhpbnQ6IGF0dHJpYnV0ZXMuY2FjaGVLZXksXG4gICAgICAgICAgICBnZXQ6ICgpID0+IGNyZWF0ZVBhY2tlZFJlc2l6ZVByb2dyYW1JbmZvKGluZmVyZW5jZUhhbmRsZXIsIGlucHV0cywgYXR0cmlidXRlcylcbiAgICAgICAgICB9LFxuICAgICAgICAgIGlucHV0cyk7XG4gICAgICByZXR1cm4gW291dHB1dF07XG4gICAgfTtcblxuZXhwb3J0IGNvbnN0IHBhcnNlUmVzaXplQXR0cmlidXRlc1YxMDogT3BlcmF0b3JJbml0aWFsaXphdGlvbjxVcHNhbXBsZUF0dHJpYnV0ZXM+ID1cbiAgICAobm9kZTogR3JhcGguTm9kZSk6IFVwc2FtcGxlQXR0cmlidXRlcyA9PiBwYXJzZVVwc2FtcGxlQXR0cmlidXRlcyhub2RlLCAxMCk7XG5cbmV4cG9ydCBjb25zdCBwYXJzZVJlc2l6ZUF0dHJpYnV0ZXNWMTE6IE9wZXJhdG9ySW5pdGlhbGl6YXRpb248VXBzYW1wbGVBdHRyaWJ1dGVzPiA9XG4gICAgKG5vZGU6IEdyYXBoLk5vZGUpOiBVcHNhbXBsZUF0dHJpYnV0ZXMgPT4gcGFyc2VVcHNhbXBsZUF0dHJpYnV0ZXMobm9kZSwgMTEpO1xuXG5jb25zdCBjcmVhdGVQYWNrZWRSZXNpemVQcm9ncmFtSW5mbyA9XG4gICAgKGluZmVyZW5jZUhhbmRsZXI6IFdlYkdMSW5mZXJlbmNlSGFuZGxlciwgaW5wdXRzOiBUZW5zb3JbXSwgYXR0cmlidXRlczogVXBzYW1wbGVBdHRyaWJ1dGVzKTogUHJvZ3JhbUluZm8gPT4ge1xuICAgICAgY29uc3QgZ2xzbCA9IGdldEdsc2woaW5mZXJlbmNlSGFuZGxlci5zZXNzaW9uLmJhY2tlbmQuZ2xDb250ZXh0LnZlcnNpb24pO1xuICAgICAgY29uc3QgW3NjYWxlcywgb3V0cHV0U2hhcGVdID0gcHJlcGFyZUlucHV0cyhpbnB1dHMsIGF0dHJpYnV0ZXMpO1xuXG4gICAgICBjb25zdCBpc1NhbWUgPVxuICAgICAgICAgIHNjYWxlcy5ldmVyeSgoczogbnVtYmVyKSA9PiBzID09PSAxKSAmJiBhdHRyaWJ1dGVzLmNvb3JkaW5hdGVUcmFuc2Zvcm1Nb2RlICE9PSAndGZfY3JvcF9hbmRfcmVzaXplJztcbiAgICAgIGlmIChpc1NhbWUpIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAuLi5yZXNpemVQcm9ncmFtTWV0YWRhdGEsXG4gICAgICAgICAgb3V0cHV0OiB7ZGltczogb3V0cHV0U2hhcGUsIHR5cGU6IGlucHV0c1swXS50eXBlLCB0ZXh0dXJlVHlwZTogVGV4dHVyZVR5cGUucGFja2VkfSxcbiAgICAgICAgICBoYXNNYWluOiB0cnVlLFxuICAgICAgICAgIHNoYWRlclNvdXJjZTogYHZvaWQgbWFpbigpIHtcbiAgICAgICAgICAgICAgICAgICAgdmVjNCB2ID0gJHtnbHNsLnRleHR1cmUyRH0oWCwgVGV4Q29vcmRzKTtcbiAgICAgICAgICAgICAgICAgICAgJHtnbHNsLm91dHB1dH0gPSB2O1xuICAgICAgICAgICAgICAgIH1gXG4gICAgICAgIH07XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IGRpbSA9IG91dHB1dFNoYXBlLmxlbmd0aDtcbiAgICAgIGlmIChkaW0gPCAyKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgb3V0cHV0IGRpbWVuc2lvbiBzaG91bGQgYmUgYXQgbGVhc3QgMiwgYnV0IGdvdCAke2RpbX1gKTtcbiAgICAgIH1cblxuICAgICAgY29uc3Qgb3V0cHV0SGVpZ2h0ID0gb3V0cHV0U2hhcGVbZGltIC0gMl07XG4gICAgICBjb25zdCBvdXRwdXRXaWR0aCA9IG91dHB1dFNoYXBlW2RpbSAtIDFdO1xuXG4gICAgICBjb25zdCBpbnB1dFNoYXBlID0gaW5wdXRzWzBdLmRpbXM7XG4gICAgICBpZiAoZGltICE9PSBpbnB1dFNoYXBlLmxlbmd0aCkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYG91dHB1dCBkaW1lbnNpb24gc2hvdWxkIG1hdGNoIGlucHV0ICR7aW5wdXRTaGFwZS5sZW5ndGh9LCBidXQgZ290ICR7ZGltfWApO1xuICAgICAgfVxuICAgICAgY29uc3QgaW5wdXRIZWlnaHQgPSBpbnB1dFNoYXBlW2RpbSAtIDJdO1xuICAgICAgY29uc3QgaW5wdXRXaWR0aCA9IGlucHV0U2hhcGVbZGltIC0gMV07XG5cbiAgICAgIGNvbnN0IHNjYWxlc0hlaWdodCA9IHNjYWxlc1tkaW0gLSAyXTtcbiAgICAgIGNvbnN0IHNjYWxlc1dpZHRoID0gc2NhbGVzW2RpbSAtIDFdO1xuXG4gICAgICBsZXQgZ2V0U291cmNlRnJhY0luZGV4ID0gJyc7XG5cbiAgICAgIGlmIChhdHRyaWJ1dGVzLm1vZGUgIT09ICdsaW5lYXInKSB7XG4gICAgICAgIC8vIFRPRE86IHN1cHBvcnQgb3RoZXIgbW9kZXNcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGByZXNpemUgKHBhY2tlZCkgZG9lcyBub3Qgc3VwcG9ydCBtb2RlOiAnJHthdHRyaWJ1dGVzLm1vZGV9J2ApO1xuICAgICAgfVxuICAgICAgc3dpdGNoIChhdHRyaWJ1dGVzLmNvb3JkaW5hdGVUcmFuc2Zvcm1Nb2RlKSB7XG4gICAgICAgIGNhc2UgJ2FzeW1tZXRyaWMnOlxuICAgICAgICAgIGdldFNvdXJjZUZyYWNJbmRleCA9IGBcbiAgICAgICAgICAgICAgICAgICAgdmVjNCBnZXRTb3VyY2VGcmFjSW5kZXgoaXZlYzQgY29vcmRzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdmVjNChjb29yZHMpIC8gc2NhbGVXSFdIO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgYDtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSAnaGFsZl9waXhlbCc6XG4gICAgICAgICAgZ2V0U291cmNlRnJhY0luZGV4ID0gYFxuICAgICAgICAgICAgICAgICAgICB2ZWM0IGdldFNvdXJjZUZyYWNJbmRleChpdmVjNCBjb29yZHMpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAodmVjNChjb29yZHMpICsgMC41KSAvIHNjYWxlV0hXSCAtIDAuNTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGA7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgJ3B5dG9yY2hfaGFsZl9waXhlbCc6XG4gICAgICAgICAgZ2V0U291cmNlRnJhY0luZGV4ID0gYFxuICAgICAgICAgICAgICAgICAgICB2ZWM0IGdldFNvdXJjZUZyYWNJbmRleChpdmVjNCBjb29yZHMpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZlYzQgZmNvb3JkcyA9IHZlYzQoY29vcmRzKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB2ZWM0KFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICR7b3V0cHV0V2lkdGh9LjAgPiAxLjAgPyAoZmNvb3Jkcy54ICsgMC41KSAvIHNjYWxlV0hXSC54IC0gMC41IDogMC4wLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICR7b3V0cHV0SGVpZ2h0fS4wID4gMS4wID8gKGZjb29yZHMueSArIDAuNSkgLyBzY2FsZVdIV0gueSAtIDAuNSA6IDAuMCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAke291dHB1dFdpZHRofS4wID4gMS4wID8gKGZjb29yZHMueiArIDAuNSkgLyBzY2FsZVdIV0gueiAtIDAuNSA6IDAuMCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAke291dHB1dEhlaWdodH0uMCA+IDEuMCA/IChmY29vcmRzLncgKyAwLjUpIC8gc2NhbGVXSFdILncgLSAwLjUgOiAwLjBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGA7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgJ2FsaWduX2Nvcm5lcnMnOlxuICAgICAgICAgIGdldFNvdXJjZUZyYWNJbmRleCA9IGBcbiAgICAgICAgICAgICAgICAgICAgdmVjNCBnZXRTb3VyY2VGcmFjSW5kZXgoaXZlYzQgY29vcmRzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2ZWM0IHJlc2l6ZWQgPSB2ZWM0KCR7b3V0cHV0V2lkdGh9LjAgLSAxLjAsICR7b3V0cHV0SGVpZ2h0fS4wIC0gMS4wLCAke291dHB1dFdpZHRofS4wIC0gMS4wLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICR7b3V0cHV0SGVpZ2h0fS4wIC0gMS4wKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZlYzQgb3JpZ2luYWwgPSB2ZWM0KCR7aW5wdXRXaWR0aH0uMCAtIDEuMCwgJHtpbnB1dEhlaWdodH0uMCAtIDEuMCwgJHtpbnB1dFdpZHRofS4wIC0gMS4wLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICR7aW5wdXRIZWlnaHR9LjAgLSAxLjApO1xuICAgICAgICAgICAgICAgICAgICAgICAgdmVjNCBuZXdfc2NhbGUgPSBvcmlnaW5hbCAvIHJlc2l6ZWQ7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdmVjNChjb29yZHMpICogbmV3X3NjYWxlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgYDtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAvLyBUT0RPOnN1cHBvcnRpbmcgb3RoZXIgY29vcmRpbmF0ZVRyYW5zZm9ybU1vZGVzXG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGByZXNpemUgKHBhY2tlZCkgZG9lcyBub3Qgc3VwcG9ydCBjb29yZGluYXRlVHJhbnNmb3JtTW9kZTogXFxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJyR7YXR0cmlidXRlcy5jb29yZGluYXRlVHJhbnNmb3JtTW9kZX0nYCk7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IGNvb3Jkc0RhdGFUeXBlID0gZ2V0Q29vcmRzRGF0YVR5cGUoZGltKTtcbiAgICAgIGNvbnN0IHVucGFja0NoYW5uZWwgPSB1bnBhY2tGcm9tQ2hhbm5lbCgpO1xuICAgICAgY29uc3Qgc2hhZGVyU291cmNlID0gYFxuICAgICAgICAgICAgY29uc3QgdmVjMiBpbnB1dFdIID0gdmVjMigke2lucHV0SGVpZ2h0fS4wLCAke2lucHV0V2lkdGh9LjApO1xuICAgICAgICAgICAgY29uc3QgdmVjNCBzY2FsZVdIV0ggPSB2ZWM0KGZsb2F0KCR7c2NhbGVzSGVpZ2h0fSksIGZsb2F0KCR7c2NhbGVzV2lkdGh9KSwgZmxvYXQoJHtzY2FsZXNIZWlnaHR9KSwgZmxvYXQoJHtcbiAgICAgICAgICBzY2FsZXNXaWR0aH0pKTtcbiAgICAgICAgICAgICR7dW5wYWNrQ2hhbm5lbH1cbiAgICAgICAgICAgICR7Z2V0U291cmNlRnJhY0luZGV4fVxuICAgICAgICAgICAgZmxvYXQgZ2V0QVZhbHVlKGludCB4MTAsIGludCByLCBpbnQgYywgaW50IGQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZ2V0Q2hhbm5lbChnZXRBKHgxMCwgciwgYywgZCksIHZlYzIoYywgZCkpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdm9pZCBtYWluKCkge1xuICAgICAgICAgICAgICAgICR7Y29vcmRzRGF0YVR5cGV9IHJjID0gZ2V0T3V0cHV0Q29vcmRzKCk7XG5cbiAgICAgICAgICAgICAgICBpbnQgYmF0Y2ggPSByY1swXTtcbiAgICAgICAgICAgICAgICBpbnQgZGVwdGggPSByY1sxXTtcblxuICAgICAgICAgICAgICAgIC8vIHJldHJpZXZlIHRoZSA0IGNvb3JkaW5hdGVzIHRoYXQgaXMgdXNlZCBpbiB0aGUgNCBwYWNrZWQgb3V0cHV0IHZhbHVlcy5cbiAgICAgICAgICAgICAgICBpdmVjNCBjb29yZHMgPSBpdmVjNChyYy53eiwgcmMudyArIDEsIHJjLnogKyAxKTtcblxuICAgICAgICAgICAgICAgIC8vIGNhbGN1bGF0ZSB0aGUgc291cmNlIGluZGV4IGluIGZyYWN0aW9uXG4gICAgICAgICAgICAgICAgdmVjNCBzb3VyY2VGcmFjID0gZ2V0U291cmNlRnJhY0luZGV4KGNvb3Jkcyk7XG5cbiAgICAgICAgICAgICAgICAvLyBnZXQgdGhlIGxvd2VyIGFuZCB1cHBlciBib3VuZCBvZiB0aGUgNCB2YWx1ZXMgdGhhdCB3aWxsIGJlIHBhY2tlZCBpbnRvIG9uZSB0ZXhlbC5cbiAgICAgICAgICAgICAgICBpdmVjNCB4MDAgPSBpdmVjNChtYXgoc291cmNlRnJhYy54eSwgdmVjMigwLjApKSwgbWluKGlucHV0V0ggLSAxLjAsIGNlaWwoc291cmNlRnJhYy54eSkpKTtcbiAgICAgICAgICAgICAgICBpdmVjNCB4MDEgPSBpdmVjNChtYXgoc291cmNlRnJhYy54dywgdmVjMigwLjApKSwgbWluKGlucHV0V0ggLSAxLjAsIGNlaWwoc291cmNlRnJhYy54dykpKTtcbiAgICAgICAgICAgICAgICBpdmVjNCB4MTAgPSBpdmVjNChtYXgoc291cmNlRnJhYy56eSwgdmVjMigwLjApKSwgbWluKGlucHV0V0ggLSAxLjAsIGNlaWwoc291cmNlRnJhYy56eSkpKTtcbiAgICAgICAgICAgICAgICBpdmVjNCB4MTEgPSBpdmVjNChtYXgoc291cmNlRnJhYy56dywgdmVjMigwLjApKSwgbWluKGlucHV0V0ggLSAxLjAsIGNlaWwoc291cmNlRnJhYy56dykpKTtcblxuICAgICAgICAgICAgICAgIGJvb2wgaGFzTmV4dFJvdyA9IHJjLncgPCAke291dHB1dEhlaWdodCAtIDF9O1xuICAgICAgICAgICAgICAgIGJvb2wgaGFzTmV4dENvbCA9IHJjLnogPCAke291dHB1dFdpZHRoIC0gMX07XG5cbiAgICAgICAgICAgICAgICAvLyBwYWNrIHgwMCwgeDAxLCB4MTAsIHgxMSdzIHRvcC1sZWZ0IGNvcm5lciBpbnRvIG9uZSB2ZWM0IHN0cnVjdHVyZVxuICAgICAgICAgICAgICAgIHZlYzQgdG9wTGVmdCA9IHZlYzQoXG4gICAgICAgICAgICAgICAgICAgIGdldEFWYWx1ZShiYXRjaCwgZGVwdGgsIHgwMC54LCB4MDAueSksXG4gICAgICAgICAgICAgICAgICAgIGhhc05leHRDb2wgPyBnZXRBVmFsdWUoYmF0Y2gsIGRlcHRoLCB4MDEueCwgeDAxLnkpIDogMC4wLFxuICAgICAgICAgICAgICAgICAgICBoYXNOZXh0Um93ID8gZ2V0QVZhbHVlKGJhdGNoLCBkZXB0aCwgeDEwLngsIHgxMC55KSA6IDAuMCxcbiAgICAgICAgICAgICAgICAgICAgKGhhc05leHRSb3cgJiYgaGFzTmV4dENvbCkgPyBnZXRBVmFsdWUoYmF0Y2gsIGRlcHRoLCB4MTEueCwgeDExLnkpIDogMC4wKTtcblxuICAgICAgICAgICAgICAgIC8vIHBhY2sgeDAwLCB4MDEsIHgxMCwgeDExJ3MgdG9wLXJpZ2h0IGNvcm5lciBpbnRvIG9uZSB2ZWM0IHN0cnVjdHVyZVxuICAgICAgICAgICAgICAgIHZlYzQgdG9wUmlnaHQgPSB2ZWM0KFxuICAgICAgICAgICAgICAgICAgICBnZXRBVmFsdWUoYmF0Y2gsIGRlcHRoLCB4MDAueCwgeDAwLncpLFxuICAgICAgICAgICAgICAgICAgICBoYXNOZXh0Q29sID8gZ2V0QVZhbHVlKGJhdGNoLCBkZXB0aCwgeDAxLngsIHgwMS53KSA6IDAuMCxcbiAgICAgICAgICAgICAgICAgICAgaGFzTmV4dFJvdyA/IGdldEFWYWx1ZShiYXRjaCwgZGVwdGgsIHgxMC54LCB4MTAudykgOiAwLjAsXG4gICAgICAgICAgICAgICAgICAgIChoYXNOZXh0Um93ICYmIGhhc05leHRDb2wpID8gZ2V0QVZhbHVlKGJhdGNoLCBkZXB0aCwgeDExLngsIHgxMS53KSA6IDAuMCk7XG5cbiAgICAgICAgICAgICAgICAvLyBwYWNrIHgwMCwgeDAxLCB4MTAsIHgxMSdzIGJvdHRvbS1sZWZ0IGNvcm5lciBpbnRvIG9uZSB2ZWM0IHN0cnVjdHVyZVxuICAgICAgICAgICAgICAgIHZlYzQgYm90dG9tTGVmdCA9IHZlYzQoXG4gICAgICAgICAgICAgICAgICAgIGdldEFWYWx1ZShiYXRjaCwgZGVwdGgsIHgwMC56LCB4MDAueSksXG4gICAgICAgICAgICAgICAgICAgIGhhc05leHRDb2wgPyBnZXRBVmFsdWUoYmF0Y2gsIGRlcHRoLCB4MDEueiwgeDAxLnkpIDogMC4wLFxuICAgICAgICAgICAgICAgICAgICBoYXNOZXh0Um93ID8gZ2V0QVZhbHVlKGJhdGNoLCBkZXB0aCwgeDEwLnosIHgxMC55KSA6IDAuMCxcbiAgICAgICAgICAgICAgICAgICAgKGhhc05leHRSb3cgJiYgaGFzTmV4dENvbCkgPyBnZXRBVmFsdWUoYmF0Y2gsIGRlcHRoLCB4MTEueiwgeDExLnkpIDogMC4wKTtcblxuICAgICAgICAgICAgICAgIC8vIHBhY2sgeDAwLCB4MDEsIHgxMCwgeDExJ3MgYm90dG9tLXJpZ2h0IGNvcm5lciBpbnRvIG9uZSB2ZWM0IHN0cnVjdHVyZVxuICAgICAgICAgICAgICAgIHZlYzQgYm90dG9tUmlnaHQgPSB2ZWM0KFxuICAgICAgICAgICAgICAgICAgICBnZXRBVmFsdWUoYmF0Y2gsIGRlcHRoLCB4MDAueiwgeDAwLncpLFxuICAgICAgICAgICAgICAgICAgICBoYXNOZXh0Q29sID8gZ2V0QVZhbHVlKGJhdGNoLCBkZXB0aCwgeDAxLnosIHgwMS53KSA6IDAuMCxcbiAgICAgICAgICAgICAgICAgICAgaGFzTmV4dFJvdyA/IGdldEFWYWx1ZShiYXRjaCwgZGVwdGgsIHgxMC56LCB4MTAudykgOiAwLjAsXG4gICAgICAgICAgICAgICAgICAgIChoYXNOZXh0Um93ICYmIGhhc05leHRDb2wpID8gZ2V0QVZhbHVlKGJhdGNoLCBkZXB0aCwgeDExLnosIHgxMS53KSA6IDAuMCk7XG5cbiAgICAgICAgICAgICAgICAvLyBjYWxjdWxhdGUgdGhlIGludGVycG9sYXRpb24gZnJhY3Rpb24gb24gdSBhbmQgdiBkaXJlY3Rpb25cbiAgICAgICAgICAgICAgICB2ZWM0IGZyYWMgPSB2ZWM0KHNvdXJjZUZyYWMpIC0gZmxvb3Ioc291cmNlRnJhYyk7XG4gICAgICAgICAgICAgICAgdmVjNCBjbGFtcEZyYWMgPSBjbGFtcChmcmFjLCB2ZWM0KDAuMCksIHZlYzQoMS4wKSk7XG5cbiAgICAgICAgICAgICAgICB2ZWM0IHRvcCA9IG1peCh0b3BMZWZ0LCB0b3BSaWdodCwgY2xhbXBGcmFjLnl3eXcpO1xuICAgICAgICAgICAgICAgIHZlYzQgYm90dG9tID0gbWl4KGJvdHRvbUxlZnQsIGJvdHRvbVJpZ2h0LCBjbGFtcEZyYWMueXd5dyk7XG4gICAgICAgICAgICAgICAgdmVjNCBuZXdWYWx1ZSA9IG1peCh0b3AsIGJvdHRvbSwgY2xhbXBGcmFjLnh4enopO1xuXG4gICAgICAgICAgICAgICAgJHtnbHNsLm91dHB1dH0gPSB2ZWM0KG5ld1ZhbHVlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgYDtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIC4uLnJlc2l6ZVByb2dyYW1NZXRhZGF0YSxcbiAgICAgICAgb3V0cHV0OiB7ZGltczogb3V0cHV0U2hhcGUsIHR5cGU6IGlucHV0c1swXS50eXBlLCB0ZXh0dXJlVHlwZTogVGV4dHVyZVR5cGUucGFja2VkfSxcbiAgICAgICAgaGFzTWFpbjogdHJ1ZSxcbiAgICAgICAgc2hhZGVyU291cmNlXG4gICAgICB9O1xuICAgIH07XG5cblxuY29uc3QgcHJlcGFyZUlucHV0cyA9IChpbnB1dHM6IFRlbnNvcltdLCBhdHRyaWJ1dGVzOiBVcHNhbXBsZUF0dHJpYnV0ZXMpOiBbcmVhZG9ubHkgbnVtYmVyW10sIHJlYWRvbmx5IG51bWJlcltdXSA9PiB7XG4gIGNvbnN0IHggPSBpbnB1dHNbMF07XG4gIGNvbnN0IHhEaW1zID0geC5kaW1zO1xuXG4gIGxldCBzY2FsZXMgPSBhdHRyaWJ1dGVzLnNjYWxlcztcbiAgbGV0IG91dHB1dFNpemVzOiBudW1iZXJbXXx1bmRlZmluZWQ7XG4gIGlmIChzY2FsZXMubGVuZ3RoID09PSAwKSB7XG4gICAgY29uc3Qgc2NhbGVzVGVuc29yID0gaW5wdXRzW2F0dHJpYnV0ZXMuc2NhbGVzSW5wdXRJZHhdO1xuICAgIGlmIChzY2FsZXNUZW5zb3IgJiYgc2NhbGVzVGVuc29yLnNpemUgIT09IDApIHtcbiAgICAgIGlmIChpbnB1dHNbYXR0cmlidXRlcy5zaXplc0lucHV0SWR4XSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ09ubHkgb25lIG9mIHNjYWxlcyBvciBzaXplcyBtdXN0IGJlIHByb3ZpZGVkIGFzIGlucHV0LicpO1xuICAgICAgfVxuICAgICAgc2NhbGVzID0gcGFyc2VTY2FsZXNEYXRhKHNjYWxlc1RlbnNvciwgYXR0cmlidXRlcy5tb2RlLCBhdHRyaWJ1dGVzLmlzUmVzaXplKTtcbiAgICB9IGVsc2Uge1xuICAgICAgY29uc3Qgc2l6ZXNUZW5zb3IgPSBpbnB1dHNbYXR0cmlidXRlcy5zaXplc0lucHV0SWR4XTtcbiAgICAgIGlmICghc2l6ZXNUZW5zb3IgfHwgc2l6ZXNUZW5zb3Iuc2l6ZSA9PT0gMCkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0VpdGhlciBzY2FsZXMgb3Igc2l6ZXMgTVVTVCBiZSBwcm92aWRlZCBhcyBpbnB1dC4nKTtcbiAgICAgIH1cblxuICAgICAgb3V0cHV0U2l6ZXMgPSBBcnJheS5mcm9tKHNpemVzVGVuc29yLmludGVnZXJEYXRhKTtcbiAgICAgIHNjYWxlcyA9IHBhcnNlU2NhbGVzRGF0YUZyb21PdXRwdXRTaXplKG91dHB1dFNpemVzLCB4RGltcywgYXR0cmlidXRlcy5tb2RlLCBhdHRyaWJ1dGVzLmlzUmVzaXplKTtcbiAgICB9XG4gIH0gZWxzZSB7XG4gICAgaWYgKGlucHV0c1thdHRyaWJ1dGVzLnNpemVzSW5wdXRJZHhdKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ09ubHkgb25lIG9mIHNjYWxlcyBvciBzaXplcyBtdXN0IGJlIHByb3ZpZGVkIGFzIGlucHV0LicpO1xuICAgIH1cbiAgfVxuXG4gIGNvbnN0IHlEaW1zID0gb3V0cHV0U2l6ZXMgfHwgKHhEaW1zLm1hcCgoZGltLCBpKSA9PiBNYXRoLmZsb29yKGRpbSAqIHNjYWxlc1tpXSkpKTtcblxuICByZXR1cm4gW3NjYWxlcywgeURpbXNdO1xufTtcblxuY29uc3QgcGFyc2VTY2FsZXNEYXRhID0gKHNjYWxlOiBUZW5zb3IsIG1vZGU6IHN0cmluZywgaXNSZXNpemU6IGJvb2xlYW4pOiBudW1iZXJbXSA9PiB7XG4gIGNvbnN0IHNjYWxlcyA9IEFycmF5LmZyb20oc2NhbGUuZmxvYXREYXRhKTtcbiAgc2NhbGVzVmFsaWRhdGlvbihzY2FsZXMsIG1vZGUsIGlzUmVzaXplKTtcbiAgcmV0dXJuIHNjYWxlcztcbn07XG5cbmNvbnN0IHBhcnNlU2NhbGVzRGF0YUZyb21PdXRwdXRTaXplID1cbiAgICAoeURpbXM6IHJlYWRvbmx5IG51bWJlcltdLCB4RGltczogcmVhZG9ubHkgbnVtYmVyW10sIG1vZGU6IHN0cmluZywgaXNSZXNpemU6IGJvb2xlYW4pOiBudW1iZXJbXSA9PiB7XG4gICAgICBjb25zdCBsZW5ndGggPSB4RGltcy5sZW5ndGg7XG4gICAgICBjb25zdCBzY2FsZXMgPSBuZXcgQXJyYXk8bnVtYmVyPihsZW5ndGgpO1xuXG4gICAgICBmb3IgKGxldCBpID0gMCwgZW5kID0gbGVuZ3RoOyBpIDwgZW5kOyBpKyspIHtcbiAgICAgICAgaWYgKHhEaW1zW2ldID09PSAwKSB7XG4gICAgICAgICAgaWYgKHlEaW1zW2ldICE9PSAwKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0lucHV0IGRpbSBpcyB6ZXJvIGJ1dCByZXF1aXJlZCBvdXRwdXQgZGltIGlzIG5vbi16ZXJvLicpO1xuICAgICAgICAgIH1cbiAgICAgICAgICBzY2FsZXNbaV0gPSAxO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHNjYWxlc1tpXSA9IHlEaW1zW2ldIC8geERpbXNbaV07XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHNjYWxlc1ZhbGlkYXRpb24oc2NhbGVzLCBtb2RlLCBpc1Jlc2l6ZSk7XG4gICAgICByZXR1cm4gc2NhbGVzO1xuICAgIH07XG5cbi8vIHJvaSBkYXRhIGlzIG5vdCB1c2VkIHlldC4gYnV0IGxlYXZlIGhlcmUgZm9yIGZ1dHVyZSB1c2FnZS5cbi8vIGNvbnN0IGdldFJvaSA9IChpbnB1dHM6IFRlbnNvcltdLCBhdHRyaWJ1dGVzOiBVcHNhbXBsZUF0dHJpYnV0ZXMpIDogbnVtYmVyW10gPT4ge1xuLy8gICAgIGxldCByb2k6IG51bWJlcltdID0gW107XG4vLyAgICAgaWYgKGF0dHJpYnV0ZXMubmVlZFJvaUlucHV0KSB7XG4vLyAgICAgICAgIGlmIChhdHRyaWJ1dGVzLnJvaUlucHV0SWR4IDw9IDApIHtcbi8vICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignSW52YWxpZCByb2kgaW5wdXQgaW5kZXguJyk7XG4vLyAgICAgICAgIH1cbi8vICAgICAgICAgY29uc3Qgcm9pVGVuc29yID0gaW5wdXRzW2F0dHJpYnV0ZXMucm9pSW5wdXRJZHhdO1xuLy8gICAgICAgICByb2kgPSByb2lUZW5zb3Iuc2l6ZSA+IDAgPyBBcnJheS5mcm9tKHJvaVRlbnNvci5mbG9hdERhdGEpIDogW107XG4vLyAgICAgfSBlbHNlIHtcbi8vICAgICAgICAgcm9pID0gbmV3IEFycmF5KGlucHV0c1swXS5kaW1zLmxlbmd0aCAqIDIpLmZpbGwoMCk7XG4vLyAgICAgfVxuLy8gICAgIHJldHVybiByb2k7XG4vLyB9O1xuIiwiLy8gQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXG5cbmltcG9ydCB7VGVuc29yfSBmcm9tICcuLi8uLi8uLi90ZW5zb3InO1xuaW1wb3J0IHtXZWJHTEluZmVyZW5jZUhhbmRsZXJ9IGZyb20gJy4uL2luZmVyZW5jZS1oYW5kbGVyJztcblxuZXhwb3J0IGNvbnN0IHNoYXBlID0gKGluZmVyZW5jZUhhbmRsZXI6IFdlYkdMSW5mZXJlbmNlSGFuZGxlciwgaW5wdXRzOiBUZW5zb3JbXSk6IFRlbnNvcltdID0+IHtcbiAgdmFsaWRhdGVJbnB1dHMoaW5wdXRzKTtcbiAgcmV0dXJuIFtuZXcgVGVuc29yKFtpbnB1dHNbMF0uZGltcy5sZW5ndGhdLCAnaW50MzInLCB1bmRlZmluZWQsIHVuZGVmaW5lZCwgbmV3IEludDMyQXJyYXkoaW5wdXRzWzBdLmRpbXMpKV07XG59O1xuXG5jb25zdCB2YWxpZGF0ZUlucHV0cyA9IChpbnB1dHM6IFRlbnNvcltdKTogdm9pZCA9PiB7XG4gIGlmICghaW5wdXRzIHx8IGlucHV0cy5sZW5ndGggIT09IDEpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ1NoYXBlIHJlcXVpcmVzIDEgaW5wdXQuJyk7XG4gIH1cbn07IiwiLy8gQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXG5cbmltcG9ydCB7QXR0cmlidXRlV2l0aENhY2hlS2V5LCBjcmVhdGVBdHRyaWJ1dGVXaXRoQ2FjaGVLZXl9IGZyb20gJy4uLy4uLy4uL2F0dHJpYnV0ZS13aXRoLWNhY2hlLWtleSc7XG5pbXBvcnQge0dyYXBofSBmcm9tICcuLi8uLi8uLi9ncmFwaCc7XG5pbXBvcnQge05VTUJFUl9UWVBFUywgT3BlcmF0b3JJbXBsZW1lbnRhdGlvbiwgT3BlcmF0b3JJbml0aWFsaXphdGlvbn0gZnJvbSAnLi4vLi4vLi4vb3BlcmF0b3JzJztcbmltcG9ydCB7VGVuc29yfSBmcm9tICcuLi8uLi8uLi90ZW5zb3InO1xuaW1wb3J0IHtTaGFwZVV0aWx9IGZyb20gJy4uLy4uLy4uL3V0aWwnO1xuaW1wb3J0IHtXZWJHTEluZmVyZW5jZUhhbmRsZXJ9IGZyb20gJy4uL2luZmVyZW5jZS1oYW5kbGVyJztcbmltcG9ydCB7UHJvZ3JhbUluZm8sIFRleHR1cmVUeXBlfSBmcm9tICcuLi90eXBlcyc7XG5cbmV4cG9ydCBpbnRlcmZhY2UgU2xpY2VBdHRyaWJ1dGVzIGV4dGVuZHMgQXR0cmlidXRlV2l0aENhY2hlS2V5IHtcbiAgcmVhZG9ubHkgYXhlczogbnVtYmVyW107XG4gIHJlYWRvbmx5IGVuZHM6IG51bWJlcltdO1xuICByZWFkb25seSBzdGFydHM6IG51bWJlcltdO1xufVxuXG5jb25zdCBzbGljZVByb2dyYW1NZXRhZGF0YSA9IHtcbiAgbmFtZTogJ1NsaWNlJyxcbiAgaW5wdXROYW1lczogWydBJ10sXG4gIGlucHV0VHlwZXM6IFtUZXh0dXJlVHlwZS51bnBhY2tlZF1cbn07XG5cbmV4cG9ydCBjb25zdCBzbGljZTogT3BlcmF0b3JJbXBsZW1lbnRhdGlvbjxTbGljZUF0dHJpYnV0ZXM+ID1cbiAgICAoaW5mZXJlbmNlSGFuZGxlcjogV2ViR0xJbmZlcmVuY2VIYW5kbGVyLCBpbnB1dHM6IFRlbnNvcltdLCBhdHRyaWJ1dGVzOiBTbGljZUF0dHJpYnV0ZXMpOiBUZW5zb3JbXSA9PiB7XG4gICAgICB2YWxpZGF0ZUlucHV0cyhpbnB1dHMpO1xuICAgICAgY29uc3Qgb3V0cHV0ID0gaW5mZXJlbmNlSGFuZGxlci5ydW4oXG4gICAgICAgICAge1xuICAgICAgICAgICAgLi4uc2xpY2VQcm9ncmFtTWV0YWRhdGEsXG4gICAgICAgICAgICBjYWNoZUhpbnQ6IGF0dHJpYnV0ZXMuY2FjaGVLZXksXG4gICAgICAgICAgICBnZXQ6ICgpID0+IGNyZWF0ZVNsaWNlUHJvZ3JhbUluZm8oaW5mZXJlbmNlSGFuZGxlciwgaW5wdXRzWzBdLCBhdHRyaWJ1dGVzKVxuICAgICAgICAgIH0sXG4gICAgICAgICAgaW5wdXRzKTtcbiAgICAgIHJldHVybiBbb3V0cHV0XTtcbiAgICB9O1xuXG5leHBvcnQgY29uc3QgcGFyc2VTbGljZUF0dHJpYnV0ZXM6IE9wZXJhdG9ySW5pdGlhbGl6YXRpb248U2xpY2VBdHRyaWJ1dGVzPiA9IChub2RlOiBHcmFwaC5Ob2RlKTogU2xpY2VBdHRyaWJ1dGVzID0+IHtcbiAgY29uc3Qgc3RhcnRzID0gbm9kZS5hdHRyaWJ1dGVzLmdldEludHMoJ3N0YXJ0cycpO1xuICBjb25zdCBlbmRzID0gbm9kZS5hdHRyaWJ1dGVzLmdldEludHMoJ2VuZHMnKTtcbiAgY29uc3QgYXhlcyA9IG5vZGUuYXR0cmlidXRlcy5nZXRJbnRzKCdheGVzJywgW10pO1xuICByZXR1cm4gY3JlYXRlQXR0cmlidXRlV2l0aENhY2hlS2V5KHtzdGFydHMsIGVuZHMsIGF4ZXN9KTtcbn07XG5cbmNvbnN0IGNyZWF0ZVNsaWNlUHJvZ3JhbUluZm8gPVxuICAgIChpbmZlcmVuY2VIYW5kbGVyOiBXZWJHTEluZmVyZW5jZUhhbmRsZXIsIGlucHV0OiBUZW5zb3IsIGF0dHJpYnV0ZXM6IFNsaWNlQXR0cmlidXRlcyk6IFByb2dyYW1JbmZvID0+IHtcbiAgICAgIGNvbnN0IGF4ZXMgPSAoYXR0cmlidXRlcy5heGVzLmxlbmd0aCA9PT0gMCkgPyBpbnB1dC5kaW1zLnNsaWNlKDApLm1hcCgodmFsLCBpKSA9PiBpKSA6IGF0dHJpYnV0ZXMuYXhlcztcbiAgICAgIGNvbnN0IG5vcm1hbGl6ZWRBeGVzID0gU2hhcGVVdGlsLm5vcm1hbGl6ZUF4ZXMoYXhlcywgaW5wdXQuZGltcy5sZW5ndGgpO1xuICAgICAgY29uc3Qgc3RhcnRzID0gYXR0cmlidXRlcy5zdGFydHMubWFwKChzdGFydCwgaSkgPT4ge1xuICAgICAgICBpZiAoc3RhcnQgPiBpbnB1dC5kaW1zW25vcm1hbGl6ZWRBeGVzW2ldXSAtIDEpIHtcbiAgICAgICAgICByZXR1cm4gaW5wdXQuZGltc1tub3JtYWxpemVkQXhlc1tpXV07XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIFNoYXBlVXRpbC5ub3JtYWxpemVBeGlzKHN0YXJ0LCBpbnB1dC5kaW1zW25vcm1hbGl6ZWRBeGVzW2ldXSk7XG4gICAgICB9KTtcbiAgICAgIGNvbnN0IGVuZHMgPSBhdHRyaWJ1dGVzLmVuZHMubWFwKChlbmQsIGkpID0+IHtcbiAgICAgICAgaWYgKGVuZCA+IGlucHV0LmRpbXNbbm9ybWFsaXplZEF4ZXNbaV1dIC0gMSkge1xuICAgICAgICAgIHJldHVybiBpbnB1dC5kaW1zW25vcm1hbGl6ZWRBeGVzW2ldXTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gU2hhcGVVdGlsLm5vcm1hbGl6ZUF4aXMoZW5kLCBpbnB1dC5kaW1zW25vcm1hbGl6ZWRBeGVzW2ldXSk7XG4gICAgICB9KTtcblxuICAgICAgY29uc3Qgb3V0cHV0U2hhcGUgPSBpbnB1dC5kaW1zLnNsaWNlKCk7XG5cbiAgICAgIGNvbnN0IHNsaWNlT3BzOiBzdHJpbmdbXSA9IFtdO1xuICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBub3JtYWxpemVkQXhlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICBvdXRwdXRTaGFwZVtub3JtYWxpemVkQXhlc1tpXV0gPSBlbmRzW2ldIC0gc3RhcnRzW2ldO1xuICAgICAgICBpZiAoc3RhcnRzW2ldID4gMCkge1xuICAgICAgICAgIHNsaWNlT3BzLnB1c2goYG91dHB1dElkeFske25vcm1hbGl6ZWRBeGVzW2ldfV0gKz0gJHtzdGFydHNbaV19O2ApO1xuICAgICAgICB9ICAvLyBlbHNlIHsgc2xpY2VPcHMucHVzaChgb3V0cHV0SWR4WyR7bm9ybWFsaXplZEF4ZXNbaV19XSArPSAwO2ApOyB9XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IHJhbmsgPSBvdXRwdXRTaGFwZS5sZW5ndGg7XG4gICAgICBjb25zdCBzaGFkZXJTb3VyY2UgPSBgXG4gICAgICBmbG9hdCBwcm9jZXNzKGludCBvdXRwdXRJZHhbJHtyYW5rfV0pIHtcbiAgICAgICAgJHtzbGljZU9wcy5qb2luKCdcXG4gICAgICAnKX1cbiAgICAgICAgcmV0dXJuIF9BKG91dHB1dElkeCk7XG4gICAgICB9YDtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIC4uLnNsaWNlUHJvZ3JhbU1ldGFkYXRhLFxuICAgICAgICBvdXRwdXQ6IHtkaW1zOiBvdXRwdXRTaGFwZSwgdHlwZTogaW5wdXQudHlwZSwgdGV4dHVyZVR5cGU6IFRleHR1cmVUeXBlLnVucGFja2VkfSxcbiAgICAgICAgc2hhZGVyU291cmNlXG4gICAgICB9O1xuICAgIH07XG5cbmNvbnN0IHZhbGlkYXRlSW5wdXRzID0gKGlucHV0czogVGVuc29yW10pOiB2b2lkID0+IHtcbiAgaWYgKCFpbnB1dHMgfHwgaW5wdXRzLmxlbmd0aCAhPT0gMSkge1xuICAgIHRocm93IG5ldyBFcnJvcignU2xpY2UgcmVxdWlyZXMgMSBpbnB1dC4nKTtcbiAgfVxuICBpZiAoTlVNQkVSX1RZUEVTLmluZGV4T2YoaW5wdXRzWzBdLnR5cGUpID09PSAtMSkge1xuICAgIHRocm93IG5ldyBFcnJvcignSW52YWxpZCBpbnB1dCB0eXBlLicpO1xuICB9XG59O1xuXG5leHBvcnQgY29uc3Qgc2xpY2VWMTAgPSAoaW5mZXJlbmNlSGFuZGxlcjogV2ViR0xJbmZlcmVuY2VIYW5kbGVyLCBpbnB1dHM6IFRlbnNvcltdKTogVGVuc29yW10gPT4ge1xuICB2YWxpZGF0ZUlucHV0c1YxMChpbnB1dHMpO1xuICBjb25zdCBhdHRyaWJ1dGVzID0gZ2VuZXJhdGVTbGljZUF0dHJpYnV0ZXNGcm9tSW5wdXRzKGluZmVyZW5jZUhhbmRsZXIsIGlucHV0cyk7XG4gIGNvbnN0IG91dHB1dCA9IGluZmVyZW5jZUhhbmRsZXIucnVuKFxuICAgICAge1xuICAgICAgICAuLi5zbGljZVByb2dyYW1NZXRhZGF0YSxcbiAgICAgICAgY2FjaGVIaW50OiBhdHRyaWJ1dGVzLmNhY2hlS2V5LFxuICAgICAgICBnZXQ6ICgpID0+IGNyZWF0ZVNsaWNlUHJvZ3JhbUluZm8oaW5mZXJlbmNlSGFuZGxlciwgaW5wdXRzWzBdLCBhdHRyaWJ1dGVzKVxuICAgICAgfSxcbiAgICAgIFtpbnB1dHNbMF1dKTtcbiAgcmV0dXJuIFtvdXRwdXRdO1xufTtcblxuY29uc3QgZ2VuZXJhdGVTbGljZUF0dHJpYnV0ZXNGcm9tSW5wdXRzID1cbiAgICAoaW5mZXJlbmNlSGFuZGxlcjogV2ViR0xJbmZlcmVuY2VIYW5kbGVyLCBpbnB1dHM6IFRlbnNvcltdKTogU2xpY2VBdHRyaWJ1dGVzID0+IHtcbiAgICAgIGlmICghaW5mZXJlbmNlSGFuZGxlci5zZXNzaW9uLmlzSW5pdGlhbGl6ZXIoaW5wdXRzWzFdLmRhdGFJZCkgfHxcbiAgICAgICAgICAhaW5mZXJlbmNlSGFuZGxlci5zZXNzaW9uLmlzSW5pdGlhbGl6ZXIoaW5wdXRzWzJdLmRhdGFJZCkgfHxcbiAgICAgICAgICAoaW5wdXRzLmxlbmd0aCA+PSA0ICYmICFpbmZlcmVuY2VIYW5kbGVyLnNlc3Npb24uaXNJbml0aWFsaXplcihpbnB1dHNbM10uZGF0YUlkKSkgfHxcbiAgICAgICAgICAoaW5wdXRzLmxlbmd0aCA+PSA1ICYmICFpbmZlcmVuY2VIYW5kbGVyLnNlc3Npb24uaXNJbml0aWFsaXplcihpbnB1dHNbNF0uZGF0YUlkKSkpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdkeW5hbWljIHNsaWNlIGF0dHJpYnV0ZXMgYXJlIG5vdCBhbGxvd2VkJyk7XG4gICAgICB9XG5cbiAgICAgIGlmIChpbnB1dHMubGVuZ3RoID49IDUgJiYgaW5wdXRzWzRdLmludGVnZXJEYXRhLnNvbWUoKGk6IG51bWJlcikgPT4gaSAhPT0gMSkpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdjdXJyZW50bHkgbm9uLTEgc3RlcHMgaXMgbm90IHN1cHBvcnRlZCBmb3IgU2xpY2UnKTtcbiAgICAgIH1cblxuICAgICAgY29uc3Qgc3RhcnRzID0gQXJyYXkuZnJvbShpbnB1dHNbMV0uaW50ZWdlckRhdGEpO1xuICAgICAgY29uc3QgZW5kcyA9IEFycmF5LmZyb20oaW5wdXRzWzJdLmludGVnZXJEYXRhKTtcbiAgICAgIGNvbnN0IGF4ZXMgPSBpbnB1dHMubGVuZ3RoID49IDQgPyBBcnJheS5mcm9tKGlucHV0c1szXS5pbnRlZ2VyRGF0YSkgOiBbXTtcbiAgICAgIGNvbnN0IGNhY2hlS2V5ID0gYCR7YXhlc307JHtzdGFydHN9OyR7ZW5kc31gO1xuICAgICAgcmV0dXJuIHtzdGFydHMsIGVuZHMsIGF4ZXMsIGNhY2hlS2V5fTtcbiAgICB9O1xuXG5jb25zdCB2YWxpZGF0ZUlucHV0c1YxMCA9IChpbnB1dHM6IFRlbnNvcltdKTogdm9pZCA9PiB7XG4gIGlmICghaW5wdXRzIHx8IGlucHV0cy5sZW5ndGggPCAzIHx8IGlucHV0cy5sZW5ndGggPiA1KSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIGlucHV0IG51bWJlci4nKTtcbiAgfVxuICBpZiAoaW5wdXRzWzFdLnR5cGUgIT09ICdpbnQzMicgfHwgaW5wdXRzWzFdLmRpbXMubGVuZ3RoICE9PSAxKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIGlucHV0IHR5cGUuJyk7XG4gIH1cbiAgaWYgKGlucHV0c1syXS50eXBlICE9PSAnaW50MzInIHx8IGlucHV0c1syXS5kaW1zLmxlbmd0aCAhPT0gMSkge1xuICAgIHRocm93IG5ldyBFcnJvcignSW52YWxpZCBpbnB1dCB0eXBlLicpO1xuICB9XG4gIGlmIChpbnB1dHMubGVuZ3RoID49IDQgJiYgKGlucHV0c1szXS50eXBlICE9PSAnaW50MzInIHx8IGlucHV0c1szXS5kaW1zLmxlbmd0aCAhPT0gMSkpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ0ludmFsaWQgaW5wdXQgdHlwZS4nKTtcbiAgfVxuICBpZiAoaW5wdXRzLmxlbmd0aCA+PSA1ICYmIChpbnB1dHNbNF0udHlwZSAhPT0gJ2ludDMyJyB8fCBpbnB1dHNbNF0uZGltcy5sZW5ndGggIT09IDEpKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIGlucHV0IHR5cGUuJyk7XG4gIH1cbn07XG4iLCIvLyBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cblxuaW1wb3J0IHtBdHRyaWJ1dGVXaXRoQ2FjaGVLZXksIGNyZWF0ZUF0dHJpYnV0ZVdpdGhDYWNoZUtleX0gZnJvbSAnLi4vLi4vLi4vYXR0cmlidXRlLXdpdGgtY2FjaGUta2V5JztcbmltcG9ydCB7R3JhcGh9IGZyb20gJy4uLy4uLy4uL2dyYXBoJztcbmltcG9ydCB7T3BlcmF0b3JJbXBsZW1lbnRhdGlvbiwgT3BlcmF0b3JJbml0aWFsaXphdGlvbn0gZnJvbSAnLi4vLi4vLi4vb3BlcmF0b3JzJztcbmltcG9ydCB7VGVuc29yfSBmcm9tICcuLi8uLi8uLi90ZW5zb3InO1xuaW1wb3J0IHtTaGFwZVV0aWx9IGZyb20gJy4uLy4uLy4uL3V0aWwnO1xuaW1wb3J0IHtnZXRHbHNsfSBmcm9tICcuLi9nbHNsLXNvdXJjZSc7XG5pbXBvcnQge1dlYkdMSW5mZXJlbmNlSGFuZGxlcn0gZnJvbSAnLi4vaW5mZXJlbmNlLWhhbmRsZXInO1xuaW1wb3J0IHtQcm9ncmFtSW5mbywgVGV4dHVyZVR5cGV9IGZyb20gJy4uL3R5cGVzJztcblxuaW1wb3J0IHt0cmFuc3Bvc2UsIFRyYW5zcG9zZUF0dHJpYnV0ZXN9IGZyb20gJy4vdHJhbnNwb3NlJztcblxuZXhwb3J0IGludGVyZmFjZSBTb2Z0bWF4QXR0cmlidXRlcyBleHRlbmRzIEF0dHJpYnV0ZVdpdGhDYWNoZUtleSB7XG4gIHJlYWRvbmx5IGF4aXM6IG51bWJlcjtcbn1cblxuY29uc3Qgc29mdG1heENvbXB1dGVNYXhQcm9ncmFtTWV0YWRhdGEgPSB7XG4gIG5hbWU6ICdTb2Z0bWF4Q29tcHV0ZU1heCcsXG4gIGlucHV0TmFtZXM6IFsnQSddLFxuICBpbnB1dFR5cGVzOiBbVGV4dHVyZVR5cGUudW5wYWNrZWRdLFxufTtcblxuY29uc3Qgc29mdG1heENvbXB1dGVTY2FsZVByb2dyYW1NZXRhZGF0YSA9IHtcbiAgbmFtZTogJ1NvZnRtYXhDb21wdXRlU2NhbGUnLFxuICBpbnB1dE5hbWVzOiBbJ0EnLCAnTWF4J10sXG4gIGlucHV0VHlwZXM6IFtUZXh0dXJlVHlwZS51bnBhY2tlZCwgVGV4dHVyZVR5cGUudW5wYWNrZWRdLFxufTtcblxuY29uc3Qgc29mdG1heFByb2dyYW1NZXRhZGF0YSA9IHtcbiAgbmFtZTogJ1NvZnRNYXgnLFxuICBpbnB1dE5hbWVzOiBbJ0EnLCAnTWF4JywgJ05vcm0nXSxcbiAgaW5wdXRUeXBlczogW1RleHR1cmVUeXBlLnVucGFja2VkLCBUZXh0dXJlVHlwZS51bnBhY2tlZCwgVGV4dHVyZVR5cGUudW5wYWNrZWRdLFxufTtcblxuZXhwb3J0IGNvbnN0IHNvZnRtYXg6IE9wZXJhdG9ySW1wbGVtZW50YXRpb248U29mdG1heEF0dHJpYnV0ZXM+ID1cbiAgICAoaW5mZXJlbmNlSGFuZGxlcjogV2ViR0xJbmZlcmVuY2VIYW5kbGVyLCBpbnB1dHM6IFRlbnNvcltdLCBhdHRyaWJ1dGVzOiBTb2Z0bWF4QXR0cmlidXRlcyk6IFRlbnNvcltdID0+IHtcbiAgICAgIHZhbGlkYXRlSW5wdXRzKGlucHV0cyk7XG5cbiAgICAgIGNvbnN0IGlucHV0U2hhcGUgPSBpbnB1dHNbMF0uZGltcy5zbGljZSgpO1xuICAgICAgY29uc3QgYXhpcyA9IFNoYXBlVXRpbC5ub3JtYWxpemVBeGlzKGF0dHJpYnV0ZXMuYXhpcywgaW5wdXRTaGFwZS5sZW5ndGgpO1xuICAgICAgY29uc3QgbG9naWNhbFJvd0NvdW50ID0gU2hhcGVVdGlsLnNpemVUb0RpbWVuc2lvbihpbnB1dFNoYXBlLCBheGlzKTtcbiAgICAgIGNvbnN0IGZlYXR1cmVDb3VudCA9IFNoYXBlVXRpbC5zaXplRnJvbURpbWVuc2lvbihpbnB1dFNoYXBlLCBheGlzKTtcblxuICAgICAgY29uc3Qgb3V0cHV0ID0gY29tcHV0ZVNvZnRtYXgoaW5mZXJlbmNlSGFuZGxlciwgaW5wdXRzLCBhdHRyaWJ1dGVzLCBsb2dpY2FsUm93Q291bnQsIGZlYXR1cmVDb3VudCk7XG4gICAgICByZXR1cm4gb3V0cHV0O1xuICAgIH07XG5cbmV4cG9ydCBjb25zdCBwYXJzZVNvZnRtYXhBdHRyaWJ1dGVzOiBPcGVyYXRvckluaXRpYWxpemF0aW9uPFNvZnRtYXhBdHRyaWJ1dGVzPiA9XG4gICAgKG5vZGU6IEdyYXBoLk5vZGUpOiBTb2Z0bWF4QXR0cmlidXRlcyA9PiBjcmVhdGVBdHRyaWJ1dGVXaXRoQ2FjaGVLZXkoe2F4aXM6IG5vZGUuYXR0cmlidXRlcy5nZXRJbnQoJ2F4aXMnLCAxKX0pO1xuXG5leHBvcnQgY29uc3QgcGFyc2VTb2Z0bWF4QXR0cmlidXRlc1YxMzogT3BlcmF0b3JJbml0aWFsaXphdGlvbjxTb2Z0bWF4QXR0cmlidXRlcz4gPVxuICAgIChub2RlOiBHcmFwaC5Ob2RlKTogU29mdG1heEF0dHJpYnV0ZXMgPT4gY3JlYXRlQXR0cmlidXRlV2l0aENhY2hlS2V5KHtheGlzOiBub2RlLmF0dHJpYnV0ZXMuZ2V0SW50KCdheGlzJywgLTEpfSk7XG5cbi8vIFRoZSBcInNlbWFudGljXCIgbWVhbmluZyBvZiBheGlzIGhhcyBjaGFuZ2VkIGluIG9wc2V0LTEzLlxuLy8gUGxlYXNlIGNvbXBhcmU6IGh0dHBzOi8vZ2l0aHViLmNvbS9vbm54L29ubngvYmxvYi9tYWluL2RvY3MvT3BlcmF0b3JzLm1kI1NvZnRtYXhcbi8vIHdpdGggaHR0cHM6Ly9naXRodWIuY29tL29ubngvb25ueC9ibG9iL21haW4vZG9jcy9DaGFuZ2Vsb2cubWQjU29mdG1heC0xMSBmb3IgZGV0YWlsZWQgZXhwbGFuYXRpb25zXG4vLyBUbyBhY2NvdW50IGZvciB0aGUgb3BzZXQtMTMgYmVoYXZpb3IsIG91ciBwbGFuIHdpbGwgYmUgdG8gdHJhbnNwb3NlIHRoZSBcImF4aXNcIiBkaW0gdG8gdGhlIGlubmVybW9zdCBkaW1cbi8vIGFuZCBwZXJmb3JtIHNvZnRtYXggYW5kIHRoZW4gcmV2ZXJzZSB0aGUgdHJhbnNwb3NlLiBXZSBjYW4gc2tpcCB0aGUgdHJhbnNwb3NpbmcgYXNwZWN0IGlmIHRoZSBheGlzIGlzIGFscmVhZHlcbi8vIHRoZSBpbm5lcm1vc3QgZGltXG5leHBvcnQgY29uc3Qgc29mdG1heFYxMzogT3BlcmF0b3JJbXBsZW1lbnRhdGlvbjxTb2Z0bWF4QXR0cmlidXRlcz4gPVxuICAgIChpbmZlcmVuY2VIYW5kbGVyOiBXZWJHTEluZmVyZW5jZUhhbmRsZXIsIGlucHV0czogVGVuc29yW10sIGF0dHJpYnV0ZXM6IFNvZnRtYXhBdHRyaWJ1dGVzKTogVGVuc29yW10gPT4ge1xuICAgICAgdmFsaWRhdGVJbnB1dHMoaW5wdXRzKTtcblxuICAgICAgY29uc3QgaW5wdXRTaGFwZSA9IGlucHV0c1swXS5kaW1zLnNsaWNlKCk7XG4gICAgICBjb25zdCBheGlzID0gU2hhcGVVdGlsLm5vcm1hbGl6ZUF4aXMoYXR0cmlidXRlcy5heGlzLCBpbnB1dFNoYXBlLmxlbmd0aCk7XG4gICAgICBjb25zdCByYW5rID0gaW5wdXRTaGFwZS5sZW5ndGg7XG5cbiAgICAgIGNvbnN0IGlzVHJhbnNwb3NlUmVxdWlyZWQgPSAoYXhpcyAhPT0gcmFuayAtIDEpID8gdHJ1ZSA6IGZhbHNlO1xuICAgICAgY29uc3QgdHJhbnNwb3NlZElucHV0U2hhcGU6IG51bWJlcltdID0gW107XG4gICAgICBsZXQgcGVybTogbnVtYmVyW10gPSBbXTtcbiAgICAgIGxldCB0cmFuc3Bvc2VkSW5wdXRzOiBUZW5zb3JbXSA9IFtdO1xuICAgICAgbGV0IHRyYW5zcG9zZUF0dHJpYnV0ZTogVHJhbnNwb3NlQXR0cmlidXRlcztcblxuICAgICAgaWYgKGlzVHJhbnNwb3NlUmVxdWlyZWQpIHtcbiAgICAgICAgcGVybSA9IEFycmF5LmZyb20oe2xlbmd0aDogcmFua30pLm1hcCgoXywgaSkgPT4gaSk7XG5cbiAgICAgICAgLy8gc3dhcCB0aGUgaW5uZXJtb3N0IGRpbSB3aXRoIHRoZSBkaW0gY29ycmVzcG9uZGluZyB0byBheGlzXG4gICAgICAgIHBlcm1bYXhpc10gPSByYW5rIC0gMTtcbiAgICAgICAgcGVybVtyYW5rIC0gMV0gPSBheGlzO1xuXG4gICAgICAgIHBlcm0ubWFwKHAgPT4gdHJhbnNwb3NlZElucHV0U2hhcGUucHVzaChpbnB1dFNoYXBlW3BdKSk7XG5cbiAgICAgICAgdHJhbnNwb3NlQXR0cmlidXRlID0gY3JlYXRlQXR0cmlidXRlV2l0aENhY2hlS2V5KHtwZXJtfSk7XG4gICAgICAgIHRyYW5zcG9zZWRJbnB1dHMgPSB0cmFuc3Bvc2UoaW5mZXJlbmNlSGFuZGxlciwgaW5wdXRzLCB0cmFuc3Bvc2VBdHRyaWJ1dGUpO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBsb2dpY2FsUm93Q291bnQgPSBpc1RyYW5zcG9zZVJlcXVpcmVkID8gU2hhcGVVdGlsLnNpemVUb0RpbWVuc2lvbih0cmFuc3Bvc2VkSW5wdXRTaGFwZSwgcmFuayAtIDEpIDpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBTaGFwZVV0aWwuc2l6ZVRvRGltZW5zaW9uKGlucHV0U2hhcGUsIHJhbmsgLSAxKTtcbiAgICAgIGNvbnN0IGZlYXR1cmVDb3VudCA9IGlzVHJhbnNwb3NlUmVxdWlyZWQgPyBTaGFwZVV0aWwuc2l6ZUZyb21EaW1lbnNpb24odHJhbnNwb3NlZElucHV0U2hhcGUsIHJhbmsgLSAxKSA6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgU2hhcGVVdGlsLnNpemVGcm9tRGltZW5zaW9uKGlucHV0U2hhcGUsIHJhbmsgLSAxKTtcblxuICAgICAgY29uc3Qgb3V0cHV0ID0gY29tcHV0ZVNvZnRtYXgoXG4gICAgICAgICAgaW5mZXJlbmNlSGFuZGxlciwgaXNUcmFuc3Bvc2VSZXF1aXJlZCA/IHRyYW5zcG9zZWRJbnB1dHMgOiBpbnB1dHMsIGF0dHJpYnV0ZXMsIGxvZ2ljYWxSb3dDb3VudCwgZmVhdHVyZUNvdW50KTtcblxuICAgICAgaWYgKGlzVHJhbnNwb3NlUmVxdWlyZWQpIHtcbiAgICAgICAgY29uc3QgcmV2ZXJzZWRPdXRwdXQgPSB0cmFuc3Bvc2UoaW5mZXJlbmNlSGFuZGxlciwgb3V0cHV0LCB0cmFuc3Bvc2VBdHRyaWJ1dGUhKTtcbiAgICAgICAgcmV0dXJuIHJldmVyc2VkT3V0cHV0O1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIG91dHB1dDtcbiAgICAgIH1cbiAgICB9O1xuXG5jb25zdCBjb21wdXRlU29mdG1heCA9XG4gICAgKGluZmVyZW5jZUhhbmRsZXI6IFdlYkdMSW5mZXJlbmNlSGFuZGxlciwgaW5wdXRzOiBUZW5zb3JbXSwgYXR0cmlidXRlczogU29mdG1heEF0dHJpYnV0ZXMsIGxvZ2ljYWxSb3dDb3VudDogbnVtYmVyLFxuICAgICBmZWF0dXJlQ291bnQ6IG51bWJlcik6IFRlbnNvcltdID0+IHtcbiAgICAgIGNvbnN0IGNvbXB1dGVNYXhQcm9ncmFtSW5mbyA9XG4gICAgICAgICAgY3JlYXRlQ29tcHV0ZU1heFByb2dyYW1JbmZvKGluZmVyZW5jZUhhbmRsZXIsIGlucHV0c1swXSwgbG9naWNhbFJvd0NvdW50LCBmZWF0dXJlQ291bnQsIFtsb2dpY2FsUm93Q291bnRdKTtcbiAgICAgIGNvbnN0IG1heCA9IGluZmVyZW5jZUhhbmRsZXIucnVuKFxuICAgICAgICAgIHsuLi5zb2Z0bWF4Q29tcHV0ZU1heFByb2dyYW1NZXRhZGF0YSwgY2FjaGVIaW50OiBhdHRyaWJ1dGVzLmNhY2hlS2V5LCBnZXQ6ICgpID0+IGNvbXB1dGVNYXhQcm9ncmFtSW5mb30sXG4gICAgICAgICAgaW5wdXRzKTtcblxuICAgICAgY29uc3QgY29tcHV0ZVNjYWxlUHJvZ3JhbUluZm8gPSBjcmVhdGVDb21wdXRTY2FsZVByb2dyYW1JbmZvKFxuICAgICAgICAgIGluZmVyZW5jZUhhbmRsZXIsIGlucHV0c1swXSwgbG9naWNhbFJvd0NvdW50LCBmZWF0dXJlQ291bnQsIGNvbXB1dGVNYXhQcm9ncmFtSW5mby5vdXRwdXQuZGltcyxcbiAgICAgICAgICBbbG9naWNhbFJvd0NvdW50XSk7XG4gICAgICBjb25zdCBzY2FsZSA9IGluZmVyZW5jZUhhbmRsZXIucnVuKFxuICAgICAgICAgIHsuLi5zb2Z0bWF4Q29tcHV0ZVNjYWxlUHJvZ3JhbU1ldGFkYXRhLCBjYWNoZUhpbnQ6IGF0dHJpYnV0ZXMuY2FjaGVLZXksIGdldDogKCkgPT4gY29tcHV0ZVNjYWxlUHJvZ3JhbUluZm99LFxuICAgICAgICAgIFtpbnB1dHNbMF0sIG1heF0pO1xuXG4gICAgICBjb25zdCBzb2Z0TWF4UHJvZ3JhbUluZm8gPSBjcmVhdGVTb2Z0TWF4UHJvZ3JhbUluZm8oXG4gICAgICAgICAgaW5mZXJlbmNlSGFuZGxlciwgaW5wdXRzWzBdLCBsb2dpY2FsUm93Q291bnQsIGZlYXR1cmVDb3VudCwgY29tcHV0ZU1heFByb2dyYW1JbmZvLm91dHB1dC5kaW1zLFxuICAgICAgICAgIGNvbXB1dGVTY2FsZVByb2dyYW1JbmZvLm91dHB1dC5kaW1zKTtcbiAgICAgIGNvbnN0IG91dHB1dCA9IGluZmVyZW5jZUhhbmRsZXIucnVuKFxuICAgICAgICAgIHsuLi5zb2Z0bWF4UHJvZ3JhbU1ldGFkYXRhLCBjYWNoZUhpbnQ6IGF0dHJpYnV0ZXMuY2FjaGVLZXksIGdldDogKCkgPT4gc29mdE1heFByb2dyYW1JbmZvfSxcbiAgICAgICAgICBbaW5wdXRzWzBdLCBtYXgsIHNjYWxlXSk7XG4gICAgICByZXR1cm4gW291dHB1dF07XG4gICAgfTtcblxuLyoqXG4gKiBDcmVhdGUgYSB0ZXh0dXJlIHRoYXQgY29udGFpbnMgdGhlIG1heGltdW0gdmFsdWUgb2YgZWFjaCBvZiB0aGUgJ04nIHJvd3NcbiAqL1xuY29uc3QgY3JlYXRlQ29tcHV0ZU1heFByb2dyYW1JbmZvID1cbiAgICAoaW5mZXJlbmNlSGFuZGxlcjogV2ViR0xJbmZlcmVuY2VIYW5kbGVyLCBpbnB1dDogVGVuc29yLCBsb2dpY2FsUm93Q291bnQ6IG51bWJlciwgZmVhdHVyZUNvdW50OiBudW1iZXIsXG4gICAgIG91dHB1dFNoYXBlOiBudW1iZXJbXSk6IFByb2dyYW1JbmZvID0+IHtcbiAgICAgIGNvbnN0IFt0ZXh0dXJlV2lkdGgsIHRleHR1cmVIZWlnaHRdID1cbiAgICAgICAgICBpbmZlcmVuY2VIYW5kbGVyLmNhbGN1bGF0ZVRleHR1cmVXaWR0aEFuZEhlaWdodChpbnB1dC5kaW1zLCBUZXh0dXJlVHlwZS51bnBhY2tlZCk7XG4gICAgICBjb25zdCByYW5rID0gb3V0cHV0U2hhcGUubGVuZ3RoO1xuXG4gICAgICBpZiAobG9naWNhbFJvd0NvdW50IDwgMSB8fCBmZWF0dXJlQ291bnQgPCAxKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignTG9naWNhbCByb3cgY291bnQgTiBhbmQgZmVhdHVyZSBjb3VudCBEIG11c3QgYmUgZ3JlYXRlciB0aGFuIG9yIGVxdWFsIHRvIDEnKTtcbiAgICAgIH1cblxuICAgICAgaWYgKG91dHB1dFNoYXBlLmxlbmd0aCAhPT0gMSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0RpbWVuc2lvbmFsaXR5IG9mIHRoZSBvdXRwdXQgc2hvdWxkIGJlIDEnKTtcbiAgICAgIH1cblxuICAgICAgaWYgKG91dHB1dFNoYXBlWzBdICE9PSBsb2dpY2FsUm93Q291bnQpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdTaGFwZSBvZiB0aGUgb3V0cHV0IHNob3VsZCBiZSBlcXVhbCB0byBsb2dpY2FsIHJvdyBjb3VudCcpO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBnbHNsID0gZ2V0R2xzbChpbmZlcmVuY2VIYW5kbGVyLnNlc3Npb24uYmFja2VuZC5nbENvbnRleHQudmVyc2lvbik7XG4gICAgICBjb25zdCBzaGFkZXJTb3VyY2UgPSBgXG4gICAgICBmbG9hdCBwcm9jZXNzKGludFske3Jhbmt9XSBpbmRpY2VzKSB7XG4gICAgICAgIGludCBsb2dpY2FsX3Jvd19zdGFydF9vZmZzZXQgPSBpbmRpY2VzWzBdICogJHtmZWF0dXJlQ291bnR9O1xuXG4gICAgICAgIGZsb2F0IG1heCA9IGdldENvbG9yQXNGbG9hdCgke2dsc2wudGV4dHVyZTJEfShBLCBvZmZzZXRUb0Nvb3Jkcyhsb2dpY2FsX3Jvd19zdGFydF9vZmZzZXQsICR7dGV4dHVyZVdpZHRofSxcbiAgICAgICAgJHt0ZXh0dXJlSGVpZ2h0fSApKSk7XG4gICAgICAgIGZvcihpbnQgaT0xOyBpPCR7ZmVhdHVyZUNvdW50fTsgKytpKVxuICAgICAgICB7XG4gICAgICAgICAgZmxvYXQgY3VycmVudCA9IGdldENvbG9yQXNGbG9hdCgke2dsc2wudGV4dHVyZTJEfShBLCBvZmZzZXRUb0Nvb3Jkcyhsb2dpY2FsX3Jvd19zdGFydF9vZmZzZXQgKyBpLFxuICAgICAgICAgICAgJHt0ZXh0dXJlV2lkdGh9LCAke3RleHR1cmVIZWlnaHR9KSkpO1xuICAgICAgICAgIGlmKGN1cnJlbnQgPiBtYXgpXG4gICAgICAgICAgbWF4ID0gY3VycmVudDtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBtYXg7XG4gICAgICB9YDtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIC4uLnNvZnRtYXhDb21wdXRlTWF4UHJvZ3JhbU1ldGFkYXRhLFxuICAgICAgICBvdXRwdXQ6IHtkaW1zOiBvdXRwdXRTaGFwZSwgdHlwZTogaW5wdXQudHlwZSwgdGV4dHVyZVR5cGU6IFRleHR1cmVUeXBlLnVucGFja2VkfSxcbiAgICAgICAgc2hhZGVyU291cmNlXG4gICAgICB9O1xuICAgIH07XG5cbi8qKlxuICogQ3JlYXRlIGEgdGV4dHVyZSB0aGF0IGNvbnRhaW5zIHRoZSBub3JtYWxpemF0aW9uIGZhY3RvciBmb3IgZWFjaCBvZiB0aGUgJ04nIHJvd3NcbiAqL1xuY29uc3QgY3JlYXRlQ29tcHV0U2NhbGVQcm9ncmFtSW5mbyA9XG4gICAgKGluZmVyZW5jZUhhbmRsZXI6IFdlYkdMSW5mZXJlbmNlSGFuZGxlciwgaW5wdXQ6IFRlbnNvciwgbG9naWNhbFJvd0NvdW50OiBudW1iZXIsIGZlYXR1cmVDb3VudDogbnVtYmVyLFxuICAgICBtYXhFbGVtZW50UGVyTG9naWNhbFJvdzogcmVhZG9ubHkgbnVtYmVyW10sIG91dHB1dFNoYXBlOiBudW1iZXJbXSk6IFByb2dyYW1JbmZvID0+IHtcbiAgICAgIGNvbnN0IFt0ZXh0dXJlV2lkdGgsIHRleHR1cmVIZWlnaHRdID1cbiAgICAgICAgICBpbmZlcmVuY2VIYW5kbGVyLmNhbGN1bGF0ZVRleHR1cmVXaWR0aEFuZEhlaWdodChpbnB1dC5kaW1zLCBUZXh0dXJlVHlwZS51bnBhY2tlZCk7XG4gICAgICBjb25zdCByYW5rID0gb3V0cHV0U2hhcGUubGVuZ3RoO1xuXG4gICAgICBpZiAobG9naWNhbFJvd0NvdW50IDwgMSB8fCBmZWF0dXJlQ291bnQgPCAxKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignTG9naWNhbCByb3cgY291bnQgTiBhbmQgZmVhdHVyZSBjb3VudCBEIG11c3QgYmUgZ3JlYXRlciB0aGFuIG9yIGVxdWFsIHRvIDEnKTtcbiAgICAgIH1cblxuICAgICAgaWYgKG91dHB1dFNoYXBlLmxlbmd0aCAhPT0gMSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0RpbWVuc2lvbmFsaXR5IG9mIHRoZSBvdXRwdXQgc2hvdWxkIGJlIDEnKTtcbiAgICAgIH1cblxuICAgICAgaWYgKG91dHB1dFNoYXBlWzBdICE9PSBsb2dpY2FsUm93Q291bnQpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdTaGFwZSBvZiB0aGUgb3V0cHV0IHNob3VsZCBiZSBlcXVhbCB0byBsb2dpY2FsIHJvdyBjb3VudCcpO1xuICAgICAgfVxuXG4gICAgICBpZiAobWF4RWxlbWVudFBlckxvZ2ljYWxSb3cubGVuZ3RoICE9PSAxKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignRGltZW5zaW9uYWxpdHkgb2YgdGhlIGludGVybWVkaWF0ZSByZXN1bHRzIHNob3VsZCBiZSAxJyk7XG4gICAgICB9XG5cbiAgICAgIGlmIChtYXhFbGVtZW50UGVyTG9naWNhbFJvd1swXSAhPT0gbG9naWNhbFJvd0NvdW50KSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignU2hhcGUgb2YgdGhlIGludGVybWVkaWF0ZSByZXN1bHRzIHNob3VsZCBiZSBlcXVhbCB0byBsb2dpY2FsIHJvdyBjb3VudCcpO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBnbHNsID0gZ2V0R2xzbChpbmZlcmVuY2VIYW5kbGVyLnNlc3Npb24uYmFja2VuZC5nbENvbnRleHQudmVyc2lvbik7XG4gICAgICBjb25zdCBzaGFkZXJTb3VyY2UgPSBgXG4gICAgICBmbG9hdCBwcm9jZXNzKGludFske3Jhbmt9XSBpbmRpY2VzKSB7XG4gICAgICAgIGludCBsb2dpY2FsX3Jvd19zdGFydF9vZmZzZXQgPSBpbmRpY2VzWzBdICogJHtmZWF0dXJlQ291bnR9O1xuXG4gICAgICAgIGZsb2F0IG5vcm1fZmFjdG9yID0gMC4wO1xuICAgICAgICBmbG9hdCBtYXggPSBfTWF4KGluZGljZXMpO1xuICAgICAgICBmb3IoaW50IGk9MDsgaTwke2ZlYXR1cmVDb3VudH07ICsraSlcbiAgICAgICAge1xuICAgICAgICAgIG5vcm1fZmFjdG9yICs9IGV4cChnZXRDb2xvckFzRmxvYXQoJHtnbHNsLnRleHR1cmUyRH0oQSwgb2Zmc2V0VG9Db29yZHMobG9naWNhbF9yb3dfc3RhcnRfb2Zmc2V0ICsgaSxcbiAgICAgICAgICAgICR7dGV4dHVyZVdpZHRofSwgJHt0ZXh0dXJlSGVpZ2h0fSkpKSAtIG1heCk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gbm9ybV9mYWN0b3I7XG4gICAgICB9YDtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIC4uLnNvZnRtYXhDb21wdXRlU2NhbGVQcm9ncmFtTWV0YWRhdGEsXG4gICAgICAgIG91dHB1dDoge2RpbXM6IG91dHB1dFNoYXBlLCB0eXBlOiBpbnB1dC50eXBlLCB0ZXh0dXJlVHlwZTogVGV4dHVyZVR5cGUudW5wYWNrZWR9LFxuICAgICAgICBzaGFkZXJTb3VyY2VcbiAgICAgIH07XG4gICAgfTtcblxuY29uc3QgY3JlYXRlU29mdE1heFByb2dyYW1JbmZvID1cbiAgICAoaW5mZXJlbmNlSGFuZGxlcjogV2ViR0xJbmZlcmVuY2VIYW5kbGVyLCBpbnB1dDogVGVuc29yLCBsb2dpY2FsUm93Q291bnQ6IG51bWJlciwgZmVhdHVyZUNvdW50OiBudW1iZXIsXG4gICAgIG1heEVsZW1lbnRQZXJMb2dpY2FsUm93OiByZWFkb25seSBudW1iZXJbXSwgbm9ybWFsaXphdGlvblBlckxvZ2ljYWxSb3c6IHJlYWRvbmx5IG51bWJlcltdKTogUHJvZ3JhbUluZm8gPT4ge1xuICAgICAgY29uc3QgW3RleHR1cmVXaWR0aCwgdGV4dHVyZUhlaWdodF0gPVxuICAgICAgICAgIGluZmVyZW5jZUhhbmRsZXIuY2FsY3VsYXRlVGV4dHVyZVdpZHRoQW5kSGVpZ2h0KGlucHV0LmRpbXMsIFRleHR1cmVUeXBlLnVucGFja2VkKTtcbiAgICAgIGNvbnN0IHJhbmsgPSBpbnB1dC5kaW1zLmxlbmd0aDtcblxuICAgICAgaWYgKGxvZ2ljYWxSb3dDb3VudCA8IDEgfHwgZmVhdHVyZUNvdW50IDwgMSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0xvZ2ljYWwgcm93IGNvdW50IE4gYW5kIGZlYXR1cmUgY291bnQgRCBtdXN0IGJlIGdyZWF0ZXIgdGhhbiBvciBlcXVhbCB0byAxJyk7XG4gICAgICB9XG5cbiAgICAgIGlmIChtYXhFbGVtZW50UGVyTG9naWNhbFJvdy5sZW5ndGggIT09IDEgfHwgbm9ybWFsaXphdGlvblBlckxvZ2ljYWxSb3cubGVuZ3RoICE9PSAxKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignRGltZW5zaW9uYWxpdHkgb2YgdGhlIGludGVybWVkaWF0ZSByZXN1bHRzIHNob3VsZCBiZSAxJyk7XG4gICAgICB9XG5cbiAgICAgIGlmIChtYXhFbGVtZW50UGVyTG9naWNhbFJvd1swXSAhPT0gbG9naWNhbFJvd0NvdW50IHx8IG5vcm1hbGl6YXRpb25QZXJMb2dpY2FsUm93WzBdICE9PSBsb2dpY2FsUm93Q291bnQpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdTaGFwZSBvZiB0aGUgaW50ZXJtZWRpYXRlIHJlc3VsdHMgc2hvdWxkIGJlIGVxdWFsIHRvIGxvZ2ljYWwgcm93IGNvdW50Jyk7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IHNoYWRlclNvdXJjZSA9IGBcbiAgICAgIGZsb2F0IHByb2Nlc3MoaW50WyR7cmFua31dIGluZGljZXMpIHtcblxuICAgICAgLy8gZ2V0IG9mZnNldCBvZiBjdXJyZW50IGxvZ2ljYWwgdGVuc29yIGluZGV4IGZyb20gdGhlIDItRCB0ZXh0dXJlIGNvb3JkaW5hdGVzIChUZXhDb29yZHMpXG4gICAgICBpbnQgb2Zmc2V0ID0gY29vcmRzVG9PZmZzZXQoVGV4Q29vcmRzLCAke3RleHR1cmVXaWR0aH0sICR7dGV4dHVyZUhlaWdodH0pO1xuXG4gICAgICAvL2RldGVybWluZSB0aGUgbG9naWNhbCByb3cgZm9yIHRoaXMgaW5kZXhcbiAgICAgIGludCBsb2dpY2FsX3Jvd19pbmRleFsxXTtcbiAgICAgIGxvZ2ljYWxfcm93X2luZGV4WzBdID0gb2Zmc2V0IC8gJHtmZWF0dXJlQ291bnR9O1xuXG4gICAgICBmbG9hdCBub3JtX2ZhY3RvciA9IF9Ob3JtKGxvZ2ljYWxfcm93X2luZGV4KTtcblxuICAgICAgLy8gYXZvaWQgcG9zc2libGUgZGl2aXNpb24gYnkgMFxuICAgICAgLy8gaWYgbm9ybV9mYWNvciBpcyAwLCBhbGwgZWxlbWVudHMgYXJlIHplcm9cbiAgICAgIC8vIGlmIHNvLCByZXR1cm4gMFxuICAgICAgaWYobm9ybV9mYWN0b3IgPT0gMC4wKVxuICAgICAgICByZXR1cm4gMC4wO1xuXG4gICAgICByZXR1cm4gZXhwKF9BKGluZGljZXMpIC0gX01heChsb2dpY2FsX3Jvd19pbmRleCkpIC8gbm9ybV9mYWN0b3I7XG4gICAgfWA7XG4gICAgICByZXR1cm4ge1xuICAgICAgICAuLi5zb2Z0bWF4UHJvZ3JhbU1ldGFkYXRhLFxuICAgICAgICBvdXRwdXQ6IHtkaW1zOiBpbnB1dC5kaW1zLCB0eXBlOiBpbnB1dC50eXBlLCB0ZXh0dXJlVHlwZTogVGV4dHVyZVR5cGUudW5wYWNrZWR9LFxuICAgICAgICBzaGFkZXJTb3VyY2VcbiAgICAgIH07XG4gICAgfTtcblxuY29uc3QgdmFsaWRhdGVJbnB1dHMgPSAoaW5wdXRzOiBUZW5zb3JbXSk6IHZvaWQgPT4ge1xuICBpZiAoIWlucHV0cyB8fCBpbnB1dHMubGVuZ3RoICE9PSAxKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdTb2Z0bWF4IHJlcXVpcmVzIDEgaW5wdXQuJyk7XG4gIH1cblxuICBpZiAoaW5wdXRzWzBdLnR5cGUgIT09ICdmbG9hdDMyJyAmJiBpbnB1dHNbMF0udHlwZSAhPT0gJ2Zsb2F0NjQnKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIGlucHV0IHR5cGUnKTtcbiAgfVxufTtcbiIsIi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxuXG5pbXBvcnQge0F0dHJpYnV0ZVdpdGhDYWNoZUtleSwgY3JlYXRlQXR0cmlidXRlV2l0aENhY2hlS2V5fSBmcm9tICcuLi8uLi8uLi9hdHRyaWJ1dGUtd2l0aC1jYWNoZS1rZXknO1xuaW1wb3J0IHtHcmFwaH0gZnJvbSAnLi4vLi4vLi4vZ3JhcGgnO1xuaW1wb3J0IHtPcGVyYXRvckltcGxlbWVudGF0aW9uLCBPcGVyYXRvckluaXRpYWxpemF0aW9ufSBmcm9tICcuLi8uLi8uLi9vcGVyYXRvcnMnO1xuaW1wb3J0IHtUZW5zb3J9IGZyb20gJy4uLy4uLy4uL3RlbnNvcic7XG5pbXBvcnQge1NoYXBlVXRpbCwgU3BsaXRVdGlsfSBmcm9tICcuLi8uLi8uLi91dGlsJztcbmltcG9ydCB7V2ViR0xJbmZlcmVuY2VIYW5kbGVyfSBmcm9tICcuLi9pbmZlcmVuY2UtaGFuZGxlcic7XG5pbXBvcnQge1Byb2dyYW1JbmZvLCBUZXh0dXJlVHlwZX0gZnJvbSAnLi4vdHlwZXMnO1xuXG5leHBvcnQgaW50ZXJmYWNlIFNwbGl0QXR0cmlidXRlcyBleHRlbmRzIEF0dHJpYnV0ZVdpdGhDYWNoZUtleSB7XG4gIHJlYWRvbmx5IGF4aXM6IG51bWJlcjtcbiAgcmVhZG9ubHkgc3BsaXQ6IG51bWJlcltdO1xuICByZWFkb25seSBudW1PdXRwdXRzOiBudW1iZXI7XG59XG5cbmNvbnN0IHNwbGl0UHJvZ3JhbU1ldGFkYXRhID0ge1xuICBuYW1lOiAnU3BsaXQnLFxuICBpbnB1dE5hbWVzOiBbJ0EnXSxcbiAgaW5wdXRUeXBlczogW1RleHR1cmVUeXBlLnVucGFja2VkXSxcbn07XG5cbmV4cG9ydCBjb25zdCBzcGxpdDogT3BlcmF0b3JJbXBsZW1lbnRhdGlvbjxTcGxpdEF0dHJpYnV0ZXM+ID1cbiAgICAoaW5mZXJlbmNlSGFuZGxlcjogV2ViR0xJbmZlcmVuY2VIYW5kbGVyLCBpbnB1dHM6IFRlbnNvcltdLCBhdHRyaWJ1dGVzOiBTcGxpdEF0dHJpYnV0ZXMpOiBUZW5zb3JbXSA9PiB7XG4gICAgICB2YWxpZGF0ZUlucHV0cyhpbnB1dHMpO1xuXG4gICAgICBjb25zdCBheGlzID0gU2hhcGVVdGlsLm5vcm1hbGl6ZUF4aXMoYXR0cmlidXRlcy5heGlzLCBpbnB1dHNbMF0uZGltcy5sZW5ndGgpO1xuICAgICAgY29uc3QgY291bnQgPSBnZXRQcm9ncmFtQ291bnQoaW5mZXJlbmNlSGFuZGxlciwgaW5wdXRzLCBheGlzLCBhdHRyaWJ1dGVzKTtcbiAgICAgIGNvbnN0IG91dHB1dDogVGVuc29yW10gPSBbXTtcbiAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgY291bnQ7ICsraSkge1xuICAgICAgICBvdXRwdXQucHVzaChpbmZlcmVuY2VIYW5kbGVyLnJ1bihcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgLi4uc3BsaXRQcm9ncmFtTWV0YWRhdGEsXG4gICAgICAgICAgICAgIGNhY2hlSGludDogYCR7YXR0cmlidXRlcy5jYWNoZUtleX07JHtpfWAsXG4gICAgICAgICAgICAgIGdldDogKCkgPT4gY3JlYXRlU3BsaXRQcm9ncmFtSW5mbyhpbmZlcmVuY2VIYW5kbGVyLCBpbnB1dHNbMF0sIGF0dHJpYnV0ZXMsIGF4aXMsIGkpXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgaW5wdXRzKSk7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBvdXRwdXQ7XG4gICAgfTtcblxuZXhwb3J0IGNvbnN0IHBhcnNlU3BsaXRBdHRyaWJ1dGVzOiBPcGVyYXRvckluaXRpYWxpemF0aW9uPFNwbGl0QXR0cmlidXRlcz4gPSAobm9kZTogR3JhcGguTm9kZSk6IFNwbGl0QXR0cmlidXRlcyA9PiB7XG4gIGNvbnN0IGF4aXMgPSBub2RlLmF0dHJpYnV0ZXMuZ2V0SW50KCdheGlzJywgMCk7XG4gIGNvbnN0IHNwbGl0ID0gbm9kZS5hdHRyaWJ1dGVzLmdldEludHMoJ3NwbGl0JywgW10pO1xuICBjb25zdCBudW1PdXRwdXRzID0gbm9kZS5vdXRwdXRzLmxlbmd0aDtcbiAgcmV0dXJuIGNyZWF0ZUF0dHJpYnV0ZVdpdGhDYWNoZUtleSh7YXhpcywgc3BsaXQsIG51bU91dHB1dHN9KTtcbn07XG5cbmNvbnN0IGdldFByb2dyYW1Db3VudCA9XG4gICAgKGluZmVyZW5jZUhhbmRsZXI6IFdlYkdMSW5mZXJlbmNlSGFuZGxlciwgaW5wdXRzOiBUZW5zb3JbXSwgYXhpczogbnVtYmVyLCBhdHRyaWJ1dGVzOiBTcGxpdEF0dHJpYnV0ZXMpOiBudW1iZXIgPT4ge1xuICAgICAgY29uc3QgWywgb2Zmc2V0c10gPSBTcGxpdFV0aWwuc3BsaXRTaGFwZShpbnB1dHNbMF0uZGltcywgYXhpcywgYXR0cmlidXRlcy5zcGxpdCwgYXR0cmlidXRlcy5udW1PdXRwdXRzKTtcbiAgICAgIHJldHVybiBvZmZzZXRzLmxlbmd0aDtcbiAgICB9O1xuXG5jb25zdCBjcmVhdGVTcGxpdFByb2dyYW1JbmZvID1cbiAgICAoaW5mZXJlbmNlSGFuZGxlcjogV2ViR0xJbmZlcmVuY2VIYW5kbGVyLCBpbnB1dDogVGVuc29yLCBhdHRyaWJ1dGVzOiBTcGxpdEF0dHJpYnV0ZXMsIGF4aXM6IG51bWJlciwgaW5kZXg6IG51bWJlcik6XG4gICAgICAgIFByb2dyYW1JbmZvID0+IHtcbiAgICAgICAgICBjb25zdCBbc2hhcGVzLCBvZmZzZXRzXSA9IFNwbGl0VXRpbC5zcGxpdFNoYXBlKGlucHV0LmRpbXMsIGF4aXMsIGF0dHJpYnV0ZXMuc3BsaXQsIGF0dHJpYnV0ZXMubnVtT3V0cHV0cyk7XG4gICAgICAgICAgY29uc3Qgb2Zmc2V0ID0gb2Zmc2V0c1tpbmRleF07XG4gICAgICAgICAgY29uc3Qgb3V0cHV0U2hhcGUgPSBzaGFwZXNbaW5kZXhdO1xuICAgICAgICAgIGNvbnN0IHJhbmsgPSBvdXRwdXRTaGFwZS5sZW5ndGg7XG4gICAgICAgICAgY29uc3Qgc2hhZGVyU291cmNlID0gYFxuICAgICAgZmxvYXQgcHJvY2VzcyhpbnQgaW5kaWNlc1ske3Jhbmt9XSkge1xuICAgICAgICBpbmRpY2VzWyR7YXhpc31dICs9ICR7b2Zmc2V0fTtcbiAgICAgICAgcmV0dXJuIF9BKGluZGljZXMpO1xuICAgICAgfVxuICAgIGA7XG4gICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIC4uLnNwbGl0UHJvZ3JhbU1ldGFkYXRhLFxuICAgICAgICAgICAgY2FjaGVIaW50OiBgJHthdHRyaWJ1dGVzLmNhY2hlS2V5fToke2luZGV4fWAsXG4gICAgICAgICAgICBvdXRwdXQ6IHtkaW1zOiBvdXRwdXRTaGFwZSwgdHlwZTogaW5wdXQudHlwZSwgdGV4dHVyZVR5cGU6IFRleHR1cmVUeXBlLnVucGFja2VkfSxcbiAgICAgICAgICAgIHNoYWRlclNvdXJjZVxuICAgICAgICAgIH07XG4gICAgICAgIH07XG5cbmNvbnN0IHZhbGlkYXRlSW5wdXRzID0gKGlucHV0czogVGVuc29yW10pOiB2b2lkID0+IHtcbiAgaWYgKCFpbnB1dHMgfHwgaW5wdXRzLmxlbmd0aCAhPT0gMSkge1xuICAgIHRocm93IG5ldyBFcnJvcignU3BsaXQgcmVxdWlyZXMgb25lIGlucHV0LicpO1xuICB9XG5cbiAgaWYgKGlucHV0c1swXS50eXBlICE9PSAnaW50OCcgJiYgaW5wdXRzWzBdLnR5cGUgIT09ICd1aW50OCcgJiYgaW5wdXRzWzBdLnR5cGUgIT09ICdpbnQxNicgJiZcbiAgICAgIGlucHV0c1swXS50eXBlICE9PSAndWludDE2JyAmJiBpbnB1dHNbMF0udHlwZSAhPT0gJ2ludDMyJyAmJiBpbnB1dHNbMF0udHlwZSAhPT0gJ3VpbnQzMicgJiZcbiAgICAgIGlucHV0c1swXS50eXBlICE9PSAnZmxvYXQzMicgJiYgaW5wdXRzWzBdLnR5cGUgIT09ICdmbG9hdDY0JyAmJiBpbnB1dHNbMF0udHlwZSAhPT0gJ2Jvb2wnKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIGlucHV0IHR5cGUuJyk7XG4gIH1cbn07XG4iLCIvLyBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cblxuaW1wb3J0IHtHcmFwaH0gZnJvbSAnLi4vLi4vLi4vZ3JhcGgnO1xuaW1wb3J0IHtPcGVyYXRvckltcGxlbWVudGF0aW9uLCBPcGVyYXRvckluaXRpYWxpemF0aW9ufSBmcm9tICcuLi8uLi8uLi9vcGVyYXRvcnMnO1xuaW1wb3J0IHtUZW5zb3J9IGZyb20gJy4uLy4uLy4uL3RlbnNvcic7XG5pbXBvcnQge1NoYXBlVXRpbH0gZnJvbSAnLi4vLi4vLi4vdXRpbCc7XG5pbXBvcnQge1dlYkdMSW5mZXJlbmNlSGFuZGxlcn0gZnJvbSAnLi4vaW5mZXJlbmNlLWhhbmRsZXInO1xuXG5leHBvcnQgY29uc3Qgc3F1ZWV6ZTogT3BlcmF0b3JJbXBsZW1lbnRhdGlvbjxudW1iZXJbXT4gPVxuICAgIChpbmZlcmVuY2VIYW5kbGVyOiBXZWJHTEluZmVyZW5jZUhhbmRsZXIsIGlucHV0czogVGVuc29yW10sIGF4ZXM6IG51bWJlcltdKTogVGVuc29yW10gPT4ge1xuICAgICAgdmFsaWRhdGVJbnB1dHMoaW5wdXRzKTtcbiAgICAgIGNvbnN0IG91dHB1dFNoYXBlID0gU2hhcGVVdGlsLnNxdWVlemVTaGFwZShpbnB1dHNbMF0uZGltcywgYXhlcyk7XG4gICAgICBjb25zdCBvdXRwdXQgPSBpbmZlcmVuY2VIYW5kbGVyLnJlc2hhcGVVbnBhY2tlZChpbnB1dHNbMF0sIG91dHB1dFNoYXBlKTtcbiAgICAgIHJldHVybiBbb3V0cHV0XTtcbiAgICB9O1xuXG5leHBvcnQgY29uc3Qgc3F1ZWV6ZVYxMyA9IChpbmZlcmVuY2VIYW5kbGVyOiBXZWJHTEluZmVyZW5jZUhhbmRsZXIsIGlucHV0czogVGVuc29yW10pOiBUZW5zb3JbXSA9PiB7XG4gIHZhbGlkYXRlSW5wdXRzVjEzKGlucHV0cyk7XG4gIHJldHVybiBzcXVlZXplKGluZmVyZW5jZUhhbmRsZXIsIFtpbnB1dHNbMF1dLCBBcnJheS5mcm9tKGlucHV0c1sxXS5pbnRlZ2VyRGF0YSkpO1xufTtcblxuZXhwb3J0IGNvbnN0IHBhcnNlU3F1ZWV6ZUF0dHJpYnV0ZXM6IE9wZXJhdG9ySW5pdGlhbGl6YXRpb248bnVtYmVyW10+ID0gKG5vZGU6IEdyYXBoLk5vZGUpOiBudW1iZXJbXSA9PlxuICAgIG5vZGUuYXR0cmlidXRlcy5nZXRJbnRzKCdheGVzJyk7XG5cbmNvbnN0IHZhbGlkYXRlSW5wdXRzID0gKGlucHV0czogVGVuc29yW10pOiB2b2lkID0+IHtcbiAgaWYgKCFpbnB1dHMgfHwgaW5wdXRzLmxlbmd0aCAhPT0gMSkge1xuICAgIHRocm93IG5ldyBFcnJvcignU3F1ZWV6ZSByZXF1aXJlcyAxIGlucHV0LicpO1xuICB9XG5cbiAgaWYgKGlucHV0c1swXS50eXBlID09PSAnc3RyaW5nJykge1xuICAgIHRocm93IG5ldyBFcnJvcignaW52YWxpZCBpbnB1dCB0ZW5zb3IgdHlwZXMuJyk7XG4gIH1cbn07XG5cbmNvbnN0IHZhbGlkYXRlSW5wdXRzVjEzID0gKGlucHV0czogVGVuc29yW10pOiB2b2lkID0+IHtcbiAgaWYgKCFpbnB1dHMgfHwgaW5wdXRzLmxlbmd0aCAhPT0gMikge1xuICAgIHRocm93IG5ldyBFcnJvcignU3F1ZWV6ZSByZXF1aXJlcyAyIGlucHV0cy4nKTtcbiAgfVxuXG4gIGlmIChpbnB1dHNbMV0udHlwZSAhPT0gJ2ludDMyJykge1xuICAgIHRocm93IG5ldyBFcnJvcignSW52YWxpZCBpbnB1dCB0eXBlLicpO1xuICB9XG59OyIsIi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxuXG5pbXBvcnQge1RlbnNvcn0gZnJvbSAnLi4vLi4vLi4vdGVuc29yJztcbmltcG9ydCB7Z2V0R2xzbH0gZnJvbSAnLi4vZ2xzbC1zb3VyY2UnO1xuaW1wb3J0IHtXZWJHTEluZmVyZW5jZUhhbmRsZXJ9IGZyb20gJy4uL2luZmVyZW5jZS1oYW5kbGVyJztcbmltcG9ydCB7UHJvZ3JhbUluZm8sIFByb2dyYW1NZXRhZGF0YSwgVGV4dHVyZVR5cGV9IGZyb20gJy4uL3R5cGVzJztcblxuZXhwb3J0IGNvbnN0IHN1bSA9IChpbmZlcmVuY2VIYW5kbGVyOiBXZWJHTEluZmVyZW5jZUhhbmRsZXIsIGlucHV0czogVGVuc29yW10pOiBUZW5zb3JbXSA9PiB7XG4gIHZhbGlkYXRlSW5wdXRzKGlucHV0cyk7XG5cbiAgY29uc3Qgc3VtUHJvZ3JhbU1ldGFkYXRhID0ge1xuICAgIG5hbWU6ICdTdW0nLFxuICAgIGlucHV0TmFtZXM6IGlucHV0cy5tYXAoKHYsIGkpID0+IGBYJHtpfWApLFxuICAgIGlucHV0VHlwZXM6IG5ldyBBcnJheShpbnB1dHMubGVuZ3RoKS5maWxsKFRleHR1cmVUeXBlLnVucGFja2VkKVxuICB9O1xuXG4gIGNvbnN0IG91dHB1dCA9IGluZmVyZW5jZUhhbmRsZXIucnVuKFxuICAgICAgey4uLnN1bVByb2dyYW1NZXRhZGF0YSwgZ2V0OiAoKSA9PiBjcmVhdGVTdW1Qcm9ncmFtSW5mbyhpbmZlcmVuY2VIYW5kbGVyLCBpbnB1dHMsIHN1bVByb2dyYW1NZXRhZGF0YSl9LCBpbnB1dHMpO1xuICByZXR1cm4gW291dHB1dF07XG59O1xuXG5jb25zdCBjcmVhdGVTdW1Qcm9ncmFtSW5mbyA9XG4gICAgKGluZmVyZW5jZUhhbmRsZXI6IFdlYkdMSW5mZXJlbmNlSGFuZGxlciwgaW5wdXRzOiBUZW5zb3JbXSwgc3VtUHJvZ3JhbU1ldGFkYXRhOiBQcm9ncmFtTWV0YWRhdGEpOiBQcm9ncmFtSW5mbyA9PiB7XG4gICAgICBjb25zdCBnbHNsID0gZ2V0R2xzbChpbmZlcmVuY2VIYW5kbGVyLnNlc3Npb24uYmFja2VuZC5nbENvbnRleHQudmVyc2lvbik7XG4gICAgICBjb25zdCBvdXRwdXRTaGFwZSA9IGlucHV0c1swXS5kaW1zLnNsaWNlKCk7XG4gICAgICBjb25zdCBzdW1MaW5lID0gaW5wdXRzLm1hcCgodiwgaSkgPT4gYCR7Z2xzbC50ZXh0dXJlMkR9KFgke2l9LFRleENvb3JkcylgKS5qb2luKCcgKyAnKTtcbiAgICAgIGNvbnN0IHNoYWRlclNvdXJjZSA9IGBcbiAgICAgIHZvaWQgbWFpbigpIHtcbiAgICAgICAgdmVjNCByZXN1bHQgPSAke3N1bUxpbmV9O1xuICAgICAgICAke2dsc2wub3V0cHV0fSA9IHJlc3VsdDtcbiAgICAgIH1cbiAgICBgO1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgLi4uc3VtUHJvZ3JhbU1ldGFkYXRhLFxuICAgICAgICBvdXRwdXQ6IHtkaW1zOiBvdXRwdXRTaGFwZSwgdHlwZTogaW5wdXRzWzBdLnR5cGUsIHRleHR1cmVUeXBlOiBUZXh0dXJlVHlwZS51bnBhY2tlZH0sXG4gICAgICAgIGhhc01haW46IHRydWUsXG4gICAgICAgIHNoYWRlclNvdXJjZVxuICAgICAgfTtcbiAgICB9O1xuXG5jb25zdCB2YWxpZGF0ZUlucHV0cyA9IChpbnB1dHM6IFRlbnNvcltdKTogdm9pZCA9PiB7XG4gIGlmICghaW5wdXRzIHx8IGlucHV0cy5sZW5ndGggPT09IDApIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ1N1bSByZXF1aXJlcyBpbnB1dHMuJyk7XG4gIH1cblxuICBjb25zdCBsZW5ndGggPSBpbnB1dHNbMF0uZGltcy5sZW5ndGg7XG4gIGZvciAobGV0IGkgPSAxOyBpIDwgaW5wdXRzLmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKGxlbmd0aCAhPT0gaW5wdXRzW2ldLmRpbXMubGVuZ3RoKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0lucHV0IHNoYXBlcyBhcmUgbWlzbWF0Y2hlZC4nKTtcbiAgICB9XG5cbiAgICBmb3IgKGxldCBqID0gMDsgaiA8IGxlbmd0aDsgaisrKSB7XG4gICAgICBpZiAoaW5wdXRzWzBdLmRpbXNbal0gIT09IGlucHV0c1tpXS5kaW1zW2pdKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignSW5wdXQgc2hhcGVzIGFyZSBub3QgbWF0Y2hlZC4nKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBpZiAoaW5wdXRzWzBdLnR5cGUgIT09ICdmbG9hdDMyJyAmJiBpbnB1dHNbMF0udHlwZSAhPT0gJ2Zsb2F0NjQnKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIGlucHV0IHR5cGUuJyk7XG4gIH1cbiAgZm9yIChsZXQgaSA9IDE7IGkgPCBpbnB1dHMubGVuZ3RoOyBpKyspIHtcbiAgICBpZiAoaW5wdXRzWzBdLnR5cGUgIT09IGlucHV0c1tpXS50eXBlKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0lucHV0IHR5cGVzIGFyZSBub3QgbWF0Y2hlZC4nKTtcbiAgICB9XG4gIH1cbn07IiwiLy8gQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXG5cbmltcG9ydCB7TlVNQkVSX1RZUEVTfSBmcm9tICcuLi8uLi8uLi9vcGVyYXRvcnMnO1xuaW1wb3J0IHtUZW5zb3J9IGZyb20gJy4uLy4uLy4uL3RlbnNvcic7XG5pbXBvcnQge1dlYkdMSW5mZXJlbmNlSGFuZGxlcn0gZnJvbSAnLi4vaW5mZXJlbmNlLWhhbmRsZXInO1xuaW1wb3J0IHtQcm9ncmFtSW5mbywgUHJvZ3JhbU1ldGFkYXRhLCBUZXh0dXJlVHlwZX0gZnJvbSAnLi4vdHlwZXMnO1xuXG5leHBvcnQgY29uc3QgdGlsZSA9IChpbmZlcmVuY2VIYW5kbGVyOiBXZWJHTEluZmVyZW5jZUhhbmRsZXIsIGlucHV0czogVGVuc29yW10pOiBUZW5zb3JbXSA9PiB7XG4gIHZhbGlkYXRlSW5wdXRzKGlucHV0cyk7XG5cbiAgY29uc3QgdGlsZVByb2dyYW1NZXRhZGF0YSA9IHtcbiAgICBuYW1lOiAnVGlsZScsXG4gICAgaW5wdXROYW1lczogWydBJ10sXG4gICAgaW5wdXRUeXBlczogW1RleHR1cmVUeXBlLnVucGFja2VkXSxcbiAgfTtcblxuICBjb25zdCBvdXRwdXQgPSBpbmZlcmVuY2VIYW5kbGVyLnJ1bihcbiAgICAgIHsuLi50aWxlUHJvZ3JhbU1ldGFkYXRhLCBnZXQ6ICgpID0+IGNyZWF0ZVRpbGVQcm9ncmFtSW5mbyhpbmZlcmVuY2VIYW5kbGVyLCBpbnB1dHMsIHRpbGVQcm9ncmFtTWV0YWRhdGEpfSxcbiAgICAgIGlucHV0cyk7XG4gIHJldHVybiBbb3V0cHV0XTtcbn07XG5cbmNvbnN0IGNyZWF0ZVRpbGVQcm9ncmFtSW5mbyA9XG4gICAgKGhhbmRsZXI6IFdlYkdMSW5mZXJlbmNlSGFuZGxlciwgaW5wdXRzOiBUZW5zb3JbXSwgdGlsZVByb2dyYW1NZXRhZGF0YTogUHJvZ3JhbU1ldGFkYXRhKTogUHJvZ3JhbUluZm8gPT4ge1xuICAgICAgY29uc3QgaW5wdXRTaGFwZSA9IGlucHV0c1swXS5kaW1zLnNsaWNlKCk7XG4gICAgICBjb25zdCBvdXRwdXRTaGFwZSA9IG5ldyBBcnJheShpbnB1dFNoYXBlLmxlbmd0aCk7XG5cbiAgICAgIGNvbnN0IHRpbGVPcHM6IHN0cmluZ1tdID0gW107XG4gICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGlucHV0U2hhcGUubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgb3V0cHV0U2hhcGVbaV0gPSBpbnB1dFNoYXBlW2ldICogaW5wdXRzWzFdLm51bWJlckRhdGFbaV07XG4gICAgICAgIHRpbGVPcHMucHVzaChgaW5wdXRJZHhbJHtpfV0gPSBpbnQobW9kKGZsb2F0KG91dHB1dElkeFske2l9XSksICR7aW5wdXRTaGFwZVtpXX0uKSk7YCk7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IHJhbmsgPSBvdXRwdXRTaGFwZS5sZW5ndGg7XG4gICAgICBjb25zdCBzaGFkZXJTb3VyY2UgPSBgXG4gICAgICBmbG9hdCBwcm9jZXNzKGludCBvdXRwdXRJZHhbJHtyYW5rfV0pIHtcbiAgICAgICAgaW50IGlucHV0SWR4WyR7cmFua31dO1xuICAgICAgICAke3RpbGVPcHMuam9pbignXFxuJyl9XG4gICAgICAgIHJldHVybiBfQShpbnB1dElkeCk7XG4gICAgICB9XG4gICAgYDtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIC4uLnRpbGVQcm9ncmFtTWV0YWRhdGEsXG4gICAgICAgIG91dHB1dDoge2RpbXM6IG91dHB1dFNoYXBlLCB0eXBlOiBpbnB1dHNbMF0udHlwZSwgdGV4dHVyZVR5cGU6IFRleHR1cmVUeXBlLnVucGFja2VkfSxcbiAgICAgICAgc2hhZGVyU291cmNlXG4gICAgICB9O1xuICAgIH07XG5cbmNvbnN0IHZhbGlkYXRlSW5wdXRzID0gKGlucHV0czogVGVuc29yW10pOiB2b2lkID0+IHtcbiAgaWYgKCFpbnB1dHMgfHwgaW5wdXRzLmxlbmd0aCAhPT0gMikge1xuICAgIHRocm93IG5ldyBFcnJvcignVGlsZSByZXF1aXJlcyAyIGlucHV0LicpO1xuICB9XG4gIGlmIChpbnB1dHNbMV0uZGltcy5sZW5ndGggIT09IDEpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ1RoZSBzZWNvbmQgaW5wdXQgc2hhcGUgbXVzdCAxIGRpbWVuc2lvbi4nKTtcbiAgfVxuICBpZiAoaW5wdXRzWzFdLmRpbXNbMF0gIT09IGlucHV0c1swXS5kaW1zLmxlbmd0aCkge1xuICAgIHRocm93IG5ldyBFcnJvcignSW52YWxpZCBpbnB1dCBzaGFwZS4nKTtcbiAgfVxuICBpZiAoTlVNQkVSX1RZUEVTLmluZGV4T2YoaW5wdXRzWzBdLnR5cGUpID09PSAtMSkge1xuICAgIHRocm93IG5ldyBFcnJvcignSW52YWxpZCBpbnB1dCB0eXBlLicpO1xuICB9XG4gIGlmIChpbnB1dHNbMV0udHlwZSAhPT0gJ2ludDMyJyAmJiBpbnB1dHNbMV0udHlwZSAhPT0gJ2ludDE2Jykge1xuICAgIHRocm93IG5ldyBFcnJvcignSW52YWxpZCByZXBlYXQgdHlwZS4nKTtcbiAgfVxufTsiLCIvLyBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cblxuaW1wb3J0IHtBdHRyaWJ1dGVXaXRoQ2FjaGVLZXksIGNyZWF0ZUF0dHJpYnV0ZVdpdGhDYWNoZUtleX0gZnJvbSAnLi4vLi4vLi4vYXR0cmlidXRlLXdpdGgtY2FjaGUta2V5JztcbmltcG9ydCB7R3JhcGh9IGZyb20gJy4uLy4uLy4uL2dyYXBoJztcbmltcG9ydCB7T3BlcmF0b3JJbXBsZW1lbnRhdGlvbiwgT3BlcmF0b3JJbml0aWFsaXphdGlvbn0gZnJvbSAnLi4vLi4vLi4vb3BlcmF0b3JzJztcbmltcG9ydCB7VGVuc29yfSBmcm9tICcuLi8uLi8uLi90ZW5zb3InO1xuaW1wb3J0IHtTaGFwZVV0aWx9IGZyb20gJy4uLy4uLy4uL3V0aWwnO1xuaW1wb3J0IHtXZWJHTEluZmVyZW5jZUhhbmRsZXJ9IGZyb20gJy4uL2luZmVyZW5jZS1oYW5kbGVyJztcbmltcG9ydCB7UHJvZ3JhbUluZm8sIFRleHR1cmVUeXBlfSBmcm9tICcuLi90eXBlcyc7XG5cbmV4cG9ydCBpbnRlcmZhY2UgVHJhbnNwb3NlQXR0cmlidXRlcyBleHRlbmRzIEF0dHJpYnV0ZVdpdGhDYWNoZUtleSB7XG4gIHJlYWRvbmx5IHBlcm06IG51bWJlcltdO1xufVxuXG5jb25zdCB0cmFuc3Bvc2VQcm9ncmFtTWV0YWRhdGEgPSB7XG4gIG5hbWU6ICdUcmFuc3Bvc2UnLFxuICBpbnB1dE5hbWVzOiBbJ0EnXSxcbiAgaW5wdXRUeXBlczogW1RleHR1cmVUeXBlLnVucGFja2VkXVxufTtcblxuZXhwb3J0IGNvbnN0IHRyYW5zcG9zZTogT3BlcmF0b3JJbXBsZW1lbnRhdGlvbjxUcmFuc3Bvc2VBdHRyaWJ1dGVzPiA9XG4gICAgKGluZmVyZW5jZUhhbmRsZXI6IFdlYkdMSW5mZXJlbmNlSGFuZGxlciwgaW5wdXRzOiBUZW5zb3JbXSwgYXR0cmlidXRlczogVHJhbnNwb3NlQXR0cmlidXRlcyk6IFRlbnNvcltdID0+IHtcbiAgICAgIHZhbGlkYXRlSW5wdXRzKGlucHV0cyk7XG4gICAgICBjb25zdCBvdXRwdXQgPSBpbmZlcmVuY2VIYW5kbGVyLnJ1bihcbiAgICAgICAgICB7XG4gICAgICAgICAgICAuLi50cmFuc3Bvc2VQcm9ncmFtTWV0YWRhdGEsXG4gICAgICAgICAgICBjYWNoZUhpbnQ6IGF0dHJpYnV0ZXMuY2FjaGVLZXksXG4gICAgICAgICAgICBnZXQ6ICgpID0+IGNyZWF0ZVRyYW5zcG9zZVByb2dyYW1JbmZvKGluZmVyZW5jZUhhbmRsZXIsIGlucHV0c1swXSwgYXR0cmlidXRlcy5wZXJtKVxuICAgICAgICAgIH0sXG4gICAgICAgICAgaW5wdXRzKTtcbiAgICAgIHJldHVybiBbb3V0cHV0XTtcbiAgICB9O1xuXG5leHBvcnQgY29uc3QgcGFyc2VUcmFuc3Bvc2VBdHRyaWJ1dGVzOiBPcGVyYXRvckluaXRpYWxpemF0aW9uPFRyYW5zcG9zZUF0dHJpYnV0ZXM+ID1cbiAgICAobm9kZTogR3JhcGguTm9kZSk6IFRyYW5zcG9zZUF0dHJpYnV0ZXMgPT4gY3JlYXRlQXR0cmlidXRlV2l0aENhY2hlS2V5KHtwZXJtOiBub2RlLmF0dHJpYnV0ZXMuZ2V0SW50cygncGVybScsIFtdKX0pO1xuXG5jb25zdCBjcmVhdGVUcmFuc3Bvc2VQcm9ncmFtSW5mbyA9XG4gICAgKGluZmVyZW5jZUhhbmRsZXI6IFdlYkdMSW5mZXJlbmNlSGFuZGxlciwgaW5wdXQ6IFRlbnNvciwgcGVybTogbnVtYmVyW10pOiBQcm9ncmFtSW5mbyA9PiB7XG4gICAgICBjb25zdCBpbnB1dFNoYXBlID0gaW5wdXQuZGltcztcbiAgICAgIHBlcm0gPSBnZXRBZGp1c3RlZFBlcm0oaW5wdXRTaGFwZSwgcGVybSk7XG4gICAgICBjb25zdCB1bnBhY2tlZE91dHB1dFNoYXBlID0gZ2V0T3V0cHV0U2hhcGUoaW5wdXRTaGFwZSwgcGVybSk7XG4gICAgICBjb25zdCByYW5rID0gaW5wdXRTaGFwZS5sZW5ndGg7XG4gICAgICAvLyBBIGRpbXM9WyR7aW5wdXRzWzBdLmRpbXMudG9TdHJpbmcoKX1dXG4gICAgICAvLyBvdXQgRGltcz1bJHt1bnBhY2tlZE91dHB1dFNoYXBlLnRvU3RyaW5nKCl9XVxuICAgICAgLy8gYmFzZWQgb24gcGVybT1bJHtwZXJtLnRvU3RyaW5nKCl9XVxuICAgICAgY29uc3Qgc2hhZGVyU291cmNlID0gYFxuICAgICAgJHtnZXRQZXJtRnVuY3Rpb25Cb2R5KCdwZXJtJywgcGVybSwgcmFuayl9XG4gICAgICBmbG9hdCBwcm9jZXNzKGludCBpbmRpY2VzWyR7cmFua31dKSB7XG4gICAgICAgIGludCBhWyR7cmFua31dO1xuICAgICAgICBwZXJtKGEsIGluZGljZXMpO1xuICAgICAgICByZXR1cm4gX0EoYSk7XG4gICAgICB9YDtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIC4uLnRyYW5zcG9zZVByb2dyYW1NZXRhZGF0YSxcbiAgICAgICAgb3V0cHV0OiB7ZGltczogdW5wYWNrZWRPdXRwdXRTaGFwZSwgdHlwZTogaW5wdXQudHlwZSwgdGV4dHVyZVR5cGU6IFRleHR1cmVUeXBlLnVucGFja2VkfSxcbiAgICAgICAgc2hhZGVyU291cmNlXG4gICAgICB9O1xuICAgIH07XG5cbmNvbnN0IGdldEFkanVzdGVkUGVybSA9IChpbnB1dFNoYXBlOiByZWFkb25seSBudW1iZXJbXSwgcGVybTogbnVtYmVyW10pOiBudW1iZXJbXSA9PiB7XG4gIGlmIChwZXJtICYmIHBlcm0ubGVuZ3RoICE9PSBpbnB1dFNoYXBlLmxlbmd0aCkge1xuICAgIHBlcm0gPSBbLi4uKGlucHV0U2hhcGUua2V5cygpKV0ucmV2ZXJzZSgpO1xuICB9XG4gIHJldHVybiBwZXJtO1xufTtcblxuY29uc3QgZ2V0T3V0cHV0U2hhcGUgPSAoaW5wdXRTaGFwZTogcmVhZG9ubHkgbnVtYmVyW10sIHBlcm06IG51bWJlcltdKTogcmVhZG9ubHkgbnVtYmVyW10gPT4ge1xuICBwZXJtID0gZ2V0QWRqdXN0ZWRQZXJtKGlucHV0U2hhcGUsIHBlcm0pO1xuICByZXR1cm4gU2hhcGVVdGlsLnNvcnRCYXNlZE9uUGVybShpbnB1dFNoYXBlLCBwZXJtKTtcbn07XG5cbmNvbnN0IGdldFBlcm1GdW5jdGlvbkJvZHkgPSAobmFtZTogc3RyaW5nLCBwZXJtOiBudW1iZXJbXSwgcmFuazogbnVtYmVyKTogc3RyaW5nID0+IHtcbiAgY29uc3QgcmV2ZXJzZUZ1bmMgPSBbXTtcbiAgcmV2ZXJzZUZ1bmMucHVzaChgdm9pZCAke25hbWV9KG91dCBpbnQgYVske3Jhbmt9XSwgaW50IHNyY1ske3Jhbmt9XSkge2ApO1xuICBmb3IgKGxldCBpID0gMDsgaSA8IHJhbms7ICsraSkge1xuICAgIHJldmVyc2VGdW5jLnB1c2goYFxcdGFbJHtwZXJtW2ldfV09c3JjWyR7aX1dO2ApO1xuICB9XG4gIHJldmVyc2VGdW5jLnB1c2goJ1xcdH0nKTtcbiAgcmV0dXJuIHJldmVyc2VGdW5jLmpvaW4oJ1xcbicpO1xufTtcblxuY29uc3QgdmFsaWRhdGVJbnB1dHMgPSAoaW5wdXRzOiBUZW5zb3JbXSk6IHZvaWQgPT4ge1xuICBpZiAoIWlucHV0cyB8fCBpbnB1dHMubGVuZ3RoICE9PSAxKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdUcmFuc3Bvc2UgcmVxdWlyZXMgMSBpbnB1dC4nKTtcbiAgfVxuXG4gIGlmIChpbnB1dHNbMF0udHlwZSAhPT0gJ2Zsb2F0MzInICYmIGlucHV0c1swXS50eXBlICE9PSAnZmxvYXQ2NCcpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ2lucHV0IHNob3VsZCBiZSBmbG9hdCB0ZW5zb3InKTtcbiAgfVxufTtcbiIsIi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxuXG5pbXBvcnQge2dldEdsc2x9IGZyb20gJy4uL2dsc2wtc291cmNlJztcbmltcG9ydCB7V2ViR0xJbmZlcmVuY2VIYW5kbGVyfSBmcm9tICcuLi9pbmZlcmVuY2UtaGFuZGxlcic7XG5pbXBvcnQge1RleHR1cmVEYXRhLCBUZXh0dXJlVHlwZX0gZnJvbSAnLi4vdHlwZXMnO1xuXG5leHBvcnQgY29uc3QgZW5jb2RlQXNVaW50OCA9IChpbmZlcmVuY2VIYW5kbGVyOiBXZWJHTEluZmVyZW5jZUhhbmRsZXIsIGlucHV0OiBUZXh0dXJlRGF0YSk6IFRleHR1cmVEYXRhID0+IHtcbiAgY29uc3Qgb3V0cHV0U2hhcGUgPSBpbnB1dC5zaGFwZTtcbiAgY29uc3QgZ2xzbCA9IGdldEdsc2woaW5mZXJlbmNlSGFuZGxlci5zZXNzaW9uLmJhY2tlbmQuZ2xDb250ZXh0LnZlcnNpb24pO1xuICAvKipcbiAgICogaHR0cHM6Ly9naXRodWIuY29tL3RlbnNvcmZsb3cvdGZqcy1jb3JlL2Jsb2IvbWFzdGVyL3NyYy9rZXJuZWxzL3dlYmdsL2VuY29kZV9mbG9hdF9ncHUudHNcbiAgICovXG4gIGNvbnN0IHNoYWRlclNvdXJjZSA9IGBcbiAgICBjb25zdCBmbG9hdCBGTE9BVF9NQVggPSAxLjcwMTQxMTg0ZTM4O1xuICAgIGNvbnN0IGZsb2F0IEZMT0FUX01JTiA9IDEuMTc1NDk0MzVlLTM4O1xuXG4gICAgYm9vbCBpc05hTihmbG9hdCB2YWwpIHtcbiAgICAgIHJldHVybiAodmFsIDwgMS4wIHx8IDAuMCA8IHZhbCB8fCB2YWwgPT0gMC4wKSA/IGZhbHNlIDogdHJ1ZTtcbiAgICB9XG5cbiAgICBoaWdocCB2ZWM0IGVuY29kZUFzVWludDgoaGlnaHAgZmxvYXQgdikge1xuICAgICAgaWYgKGlzTmFOKHYpKSB7XG4gICAgICAgIHJldHVybiB2ZWM0KDI1NSwgMjU1LCAyNTUsIDI1NSk7XG4gICAgICB9XG5cbiAgICAgIGhpZ2hwIGZsb2F0IGF2ID0gYWJzKHYpO1xuXG4gICAgICBpZihhdiA8IEZMT0FUX01JTikge1xuICAgICAgICByZXR1cm4gdmVjNCgwLjAsIDAuMCwgMC4wLCAwLjApO1xuICAgICAgfSBlbHNlIGlmKHYgPiBGTE9BVF9NQVgpIHtcbiAgICAgICAgcmV0dXJuIHZlYzQoMC4wLCAwLjAsIDEyOC4wLCAxMjcuMCkgLyAyNTUuMDtcbiAgICAgIH0gZWxzZSBpZih2IDwgLUZMT0FUX01BWCkge1xuICAgICAgICByZXR1cm4gdmVjNCgwLjAsIDAuMCwgIDEyOC4wLCAyNTUuMCkgLyAyNTUuMDtcbiAgICAgIH1cblxuICAgICAgaGlnaHAgdmVjNCBjID0gdmVjNCgwLDAsMCwwKTtcblxuICAgICAgaGlnaHAgZmxvYXQgZSA9IGZsb29yKGxvZzIoYXYpKTtcbiAgICAgIGhpZ2hwIGZsb2F0IG0gPSBleHAyKGZyYWN0KGxvZzIoYXYpKSkgLSAxLjA7XG5cbiAgICAgIGNbMl0gPSBmbG9vcigxMjguMCAqIG0pO1xuICAgICAgbSAtPSBjWzJdIC8gMTI4LjA7XG4gICAgICBjWzFdID0gZmxvb3IoMzI3NjguMCAqIG0pO1xuICAgICAgbSAtPSBjWzFdIC8gMzI3NjguMDtcbiAgICAgIGNbMF0gPSBmbG9vcig4Mzg4NjA4LjAgKiBtKTtcblxuICAgICAgaGlnaHAgZmxvYXQgZWJpYXMgPSBlICsgMTI3LjA7XG4gICAgICBjWzNdID0gZmxvb3IoZWJpYXMgLyAyLjApO1xuICAgICAgZWJpYXMgLT0gY1szXSAqIDIuMDtcbiAgICAgIGNbMl0gKz0gZmxvb3IoZWJpYXMpICogMTI4LjA7XG5cbiAgICAgIGNbM10gKz0gMTI4LjAgKiBzdGVwKDAuMCwgLXYpO1xuXG4gICAgICByZXR1cm4gYyAvIDI1NS4wO1xuICAgIH1cblxuICAgIHZvaWQgbWFpbigpIHtcbiAgICAgIGZsb2F0IHZhbHVlID0gJHtnbHNsLnRleHR1cmUyRH0oWCxUZXhDb29yZHMpLnI7XG4gICAgICAke2dsc2wub3V0cHV0fSA9IGVuY29kZUFzVWludDgodmFsdWUpO1xuICAgIH1gO1xuICBjb25zdCBwcm9ncmFtSW5mbyA9IHtcbiAgICBuYW1lOiAnVWludDhFbmNvZGUnLFxuICAgIGlucHV0VHlwZXM6IFtUZXh0dXJlVHlwZS51bnBhY2tlZF0sXG4gICAgaW5wdXROYW1lczogWydYJ10sXG4gICAgb3V0cHV0OiB7ZGltczogb3V0cHV0U2hhcGUsIHR5cGU6IGlucHV0LnRlbnNvci50eXBlLCB0ZXh0dXJlVHlwZTogVGV4dHVyZVR5cGUuZG93bmxvYWRVaW50OEFzRmxvYXR9LFxuICAgIHNoYWRlclNvdXJjZSxcbiAgICBoYXNNYWluOiB0cnVlXG4gIH07XG4gIHJldHVybiBpbmZlcmVuY2VIYW5kbGVyLmV4ZWN1dGVQcm9ncmFtKHByb2dyYW1JbmZvLCBbaW5wdXQudGVuc29yXSk7XG59O1xuIiwiLy8gQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXG5cbmltcG9ydCB7QXR0cmlidXRlV2l0aENhY2hlS2V5LCBjcmVhdGVBdHRyaWJ1dGVXaXRoQ2FjaGVLZXl9IGZyb20gJy4uLy4uLy4uL2F0dHJpYnV0ZS13aXRoLWNhY2hlLWtleSc7XG5pbXBvcnQge0dyYXBofSBmcm9tICcuLi8uLi8uLi9ncmFwaCc7XG5pbXBvcnQge1RlbnNvcn0gZnJvbSAnLi4vLi4vLi4vdGVuc29yJztcbmltcG9ydCB7TUFYX0NMSVAsIE1JTl9DTElQfSBmcm9tICcuLi8uLi8uLi91dGlsJztcbmltcG9ydCB7RnVuY3Rpb25UeXBlLCBHbHNsVmFsdWVGdW5jdGlvbn0gZnJvbSAnLi4vZ2xzbC1kZWZpbml0aW9ucyc7XG5pbXBvcnQge2dldEdsc2x9IGZyb20gJy4uL2dsc2wtc291cmNlJztcbmltcG9ydCB7V2ViR0xJbmZlcmVuY2VIYW5kbGVyfSBmcm9tICcuLi9pbmZlcmVuY2UtaGFuZGxlcic7XG5pbXBvcnQge1Byb2dyYW1JbmZvLCBQcm9ncmFtSW5mb0xvYWRlciwgUHJvZ3JhbU1ldGFkYXRhLCBUZXh0dXJlVHlwZX0gZnJvbSAnLi4vdHlwZXMnO1xuXG5leHBvcnQgZnVuY3Rpb24gZ2xzbEFicygpOiBHbHNsVmFsdWVGdW5jdGlvbiB7XG4gIHJldHVybiBnbHNsQnVpbHRpblVuYXJ5KCdhYnMnKTtcbn1cbmV4cG9ydCBmdW5jdGlvbiBnbHNsQWNvcygpOiBHbHNsVmFsdWVGdW5jdGlvbiB7XG4gIHJldHVybiBnbHNsQnVpbHRpblVuYXJ5KCdhY29zJyk7XG59XG5leHBvcnQgZnVuY3Rpb24gZ2xzbEFzaW4oKTogR2xzbFZhbHVlRnVuY3Rpb24ge1xuICByZXR1cm4gZ2xzbEJ1aWx0aW5VbmFyeSgnYXNpbicpO1xufVxuZXhwb3J0IGZ1bmN0aW9uIGdsc2xBdGFuKCk6IEdsc2xWYWx1ZUZ1bmN0aW9uIHtcbiAgcmV0dXJuIGdsc2xCdWlsdGluVW5hcnkoJ2F0YW4nKTtcbn1cbmV4cG9ydCBmdW5jdGlvbiBnbHNsQ2VpbCgpOiBHbHNsVmFsdWVGdW5jdGlvbiB7XG4gIHJldHVybiBnbHNsQnVpbHRpblVuYXJ5KCdjZWlsJyk7XG59XG5leHBvcnQgZnVuY3Rpb24gZ2xzbENvcygpOiBHbHNsVmFsdWVGdW5jdGlvbiB7XG4gIHJldHVybiBnbHNsQnVpbHRpblVuYXJ5KCdjb3MnKTtcbn1cbmV4cG9ydCBmdW5jdGlvbiBnbHNsRWx1KGFscGhhOiBudW1iZXIpOiBHbHNsVmFsdWVGdW5jdGlvbiB7XG4gIGNvbnN0IG5hbWUgPSAnZWx1JztcbiAgY29uc3QgYm9keSA9IGBcbiAgY29uc3QgZmxvYXQgYWxwaGEgPSBmbG9hdCgke2FscGhhfSk7XG5cbiAgZmxvYXQgJHtuYW1lfV8oZmxvYXQgYSkge1xuICAgIHJldHVybiBhID49IDAuMCA/IGE6IChleHAoYSkgLSAxLjApICogYWxwaGE7XG4gIH1cbiAgdmVjNCAke25hbWV9Xyh2ZWM0IHYpIHtcbiAgICByZXR1cm4gdmVjNCgke25hbWV9Xyh2LngpLCAke25hbWV9Xyh2LnkpLCAke25hbWV9Xyh2LnopLCAke25hbWV9Xyh2LncpKTtcbiAgfVxuICBgO1xuICByZXR1cm4ge2JvZHksIG5hbWUsIHR5cGU6IEZ1bmN0aW9uVHlwZS5WYWx1ZUJhc2VkfTtcbn1cbmV4cG9ydCBmdW5jdGlvbiBnbHNsRXhwKCk6IEdsc2xWYWx1ZUZ1bmN0aW9uIHtcbiAgcmV0dXJuIGdsc2xCdWlsdGluVW5hcnkoJ2V4cCcpO1xufVxuZXhwb3J0IGZ1bmN0aW9uIGdsc2xGbG9vcigpOiBHbHNsVmFsdWVGdW5jdGlvbiB7XG4gIHJldHVybiBnbHNsQnVpbHRpblVuYXJ5KCdmbG9vcicpO1xufVxuZXhwb3J0IGZ1bmN0aW9uIGdsc2xDbGlwKG1pbjogbnVtYmVyLCBtYXg6IG51bWJlcik6IEdsc2xWYWx1ZUZ1bmN0aW9uIHtcbiAgY29uc3QgbmFtZSA9ICdjbGlwJztcbiAgY29uc3QgYm9keSA9IGBcbiAgY29uc3QgZmxvYXQgbWluID0gZmxvYXQoJHttaW59KTtcbiAgY29uc3QgZmxvYXQgbWF4ID0gZmxvYXQoJHttYXh9KTtcblxuICBmbG9hdCAke25hbWV9XyhmbG9hdCBhKSB7XG4gICAgcmV0dXJuIGNsYW1wKGEsIG1pbiwgbWF4KTtcbiAgfVxuICB2ZWM0ICR7bmFtZX1fKHZlYzQgdikge1xuICAgIHJldHVybiBjbGFtcCh2LCBtaW4sIG1heCk7XG4gIH1cbiAgYDtcbiAgcmV0dXJuIHtib2R5LCBuYW1lLCB0eXBlOiBGdW5jdGlvblR5cGUuVmFsdWVCYXNlZH07XG59XG5leHBvcnQgZnVuY3Rpb24gZ2xzbElkZW50aXR5KCk6IEdsc2xWYWx1ZUZ1bmN0aW9uIHtcbiAgY29uc3QgbmFtZSA9ICdpbmRlbnRpdHknO1xuICBjb25zdCBib2R5ID0gYFxuICBmbG9hdCAke25hbWV9XyhmbG9hdCBhKSB7XG4gICAgcmV0dXJuIGE7XG4gIH1cbiAgdmVjNCAke25hbWV9Xyh2ZWM0IHYpIHtcbiAgICByZXR1cm4gdjtcbiAgfVxuICBgO1xuICByZXR1cm4ge2JvZHksIG5hbWUsIHR5cGU6IEZ1bmN0aW9uVHlwZS5WYWx1ZUJhc2VkfTtcbn1cbmV4cG9ydCBmdW5jdGlvbiBnbHNsTGVha3lSZWx1KGFscGhhOiBudW1iZXIpOiBHbHNsVmFsdWVGdW5jdGlvbiB7XG4gIGNvbnN0IG5hbWUgPSAnbGVha3lSZWx1JztcbiAgY29uc3QgYm9keSA9IGBcbiAgY29uc3QgZmxvYXQgYWxwaGEgPSBmbG9hdCgke2FscGhhfSk7XG5cbiAgZmxvYXQgJHtuYW1lfV8oZmxvYXQgYSkge1xuICAgIHJldHVybiBhIDwgMC4wID8gYSAqIGFscGhhIDogYTtcbiAgfVxuICB2ZWM0ICR7bmFtZX1fKHZlYzQgdikge1xuICAgIHJldHVybiB2ZWM0KCR7bmFtZX1fKHYueCksICR7bmFtZX1fKHYueSksICR7bmFtZX1fKHYueiksICR7bmFtZX1fKHYudykpO1xuICB9XG4gIGA7XG4gIHJldHVybiB7Ym9keSwgbmFtZSwgdHlwZTogRnVuY3Rpb25UeXBlLlZhbHVlQmFzZWR9O1xufVxuZXhwb3J0IGZ1bmN0aW9uIGdsc2xMb2coKTogR2xzbFZhbHVlRnVuY3Rpb24ge1xuICByZXR1cm4gZ2xzbEJ1aWx0aW5VbmFyeSgnbG9nJyk7XG59XG5leHBvcnQgZnVuY3Rpb24gZ2xzbE5lZygpOiBHbHNsVmFsdWVGdW5jdGlvbiB7XG4gIGNvbnN0IG5hbWUgPSAnbmVnJztcbiAgY29uc3QgYm9keSA9IGBcbiAgZmxvYXQgJHtuYW1lfV8oZmxvYXQgYSkge1xuICAgIHJldHVybiAtYTtcbiAgfVxuICB2ZWM0ICR7bmFtZX1fKHZlYzQgdikge1xuICAgIHJldHVybiAtdjtcbiAgfVxuICBgO1xuICByZXR1cm4ge2JvZHksIG5hbWUsIHR5cGU6IEZ1bmN0aW9uVHlwZS5WYWx1ZUJhc2VkfTtcbn1cbmV4cG9ydCBmdW5jdGlvbiBnbHNsTm90KCk6IEdsc2xWYWx1ZUZ1bmN0aW9uIHtcbiAgY29uc3QgbmFtZSA9ICdub3QnO1xuICBjb25zdCBib2R5ID0gYFxuICBmbG9hdCAke25hbWV9XyhmbG9hdCBhKSB7XG4gICAgcmV0dXJuIGZsb2F0KCAhIGJvb2woYSkgKTtcbiAgfVxuICBib29sICR7bmFtZX1fKGJvb2wgYSkge1xuICAgIHJldHVybiAhYTtcbiAgfVxuICB2ZWM0ICR7bmFtZX1fKHZlYzQgdikge1xuICAgIHJldHVybiB2ZWM0KCFib29sKHYueCksICFib29sKHYueSksICFib29sKHYueiksICFib29sKHYudykpO1xuICB9XG4gIGJ2ZWM0ICR7bmFtZX1fKGJ2ZWM0IHYpIHtcbiAgICByZXR1cm4gYnZlYzQoIXYueCwgIXYueSwgIXYueiwgIXYudyk7XG4gIH1cbiAgYDtcbiAgcmV0dXJuIHtib2R5LCBuYW1lLCB0eXBlOiBGdW5jdGlvblR5cGUuVmFsdWVCYXNlZH07XG59XG5leHBvcnQgZnVuY3Rpb24gZ2xzbFNpbigpOiBHbHNsVmFsdWVGdW5jdGlvbiB7XG4gIHJldHVybiBnbHNsQnVpbHRpblVuYXJ5KCdzaW4nKTtcbn1cbmV4cG9ydCBmdW5jdGlvbiBnbHNsUmVsdSgpOiBHbHNsVmFsdWVGdW5jdGlvbiB7XG4gIGNvbnN0IG5hbWUgPSAncmVsdSc7XG4gIGNvbnN0IGJvZHkgPSBgXG4gIGZsb2F0ICR7bmFtZX1fKGZsb2F0IGEpIHtcbiAgICByZXR1cm4gbWF4KCBhLCAwLjAgKTtcbiAgfVxuICB2ZWM0ICR7bmFtZX1fKHZlYzQgdikge1xuICAgIHJldHVybiBtYXgoIHYsIDAuMCApO1xuICB9XG4gIGA7XG4gIHJldHVybiB7Ym9keSwgbmFtZSwgdHlwZTogRnVuY3Rpb25UeXBlLlZhbHVlQmFzZWR9O1xufVxuZXhwb3J0IGZ1bmN0aW9uIGdsc2xTaWdtb2lkKCk6IEdsc2xWYWx1ZUZ1bmN0aW9uIHtcbiAgY29uc3QgbmFtZSA9ICdzaWdtb2lkJztcbiAgY29uc3QgYm9keSA9IGBcbiAgZmxvYXQgJHtuYW1lfV8oZmxvYXQgYSkge1xuICAgIHJldHVybiAxLjAgLyAoMS4wICsgZXhwKC1hKSk7XG4gIH1cbiAgdmVjNCAke25hbWV9Xyh2ZWM0IHYpIHtcbiAgICByZXR1cm4gMS4wIC8gKDEuMCArIGV4cCgtdikpO1xuICB9XG4gIGA7XG4gIHJldHVybiB7Ym9keSwgbmFtZSwgdHlwZTogRnVuY3Rpb25UeXBlLlZhbHVlQmFzZWR9O1xufVxuZXhwb3J0IGZ1bmN0aW9uIGdsc2xTcXJ0KCk6IEdsc2xWYWx1ZUZ1bmN0aW9uIHtcbiAgcmV0dXJuIGdsc2xCdWlsdGluVW5hcnkoJ3NxcnQnKTtcbn1cbmV4cG9ydCBmdW5jdGlvbiBnbHNsVGFuKCk6IEdsc2xWYWx1ZUZ1bmN0aW9uIHtcbiAgcmV0dXJuIGdsc2xCdWlsdGluVW5hcnkoJ3RhbicpO1xufVxuZXhwb3J0IGZ1bmN0aW9uIGdsc2xUYW5oKCk6IEdsc2xWYWx1ZUZ1bmN0aW9uIHtcbiAgY29uc3QgbmFtZSA9ICd0YW5oJztcbiAgY29uc3QgYm9keSA9IGBcbiAgZmxvYXQgJHtuYW1lfV8oZmxvYXQgYSkge1xuICAgIGEgPSBjbGFtcChhLCAtMTAuLCAxMC4pO1xuICAgIGEgPSBleHAoMi4qYSk7XG4gICAgcmV0dXJuIChhIC0gMS4pIC8gKGEgKyAxLik7XG4gIH1cbiAgdmVjNCAke25hbWV9Xyh2ZWM0IHYpIHtcbiAgICB2ID0gY2xhbXAodiwgLTEwLiwgMTAuKTtcbiAgICB2ID0gZXhwKDIuKnYpO1xuICAgIHJldHVybiAodiAtIDEuKSAvICh2ICsgMS4pO1xuICB9XG4gIGA7XG4gIHJldHVybiB7Ym9keSwgbmFtZSwgdHlwZTogRnVuY3Rpb25UeXBlLlZhbHVlQmFzZWR9O1xufVxuZnVuY3Rpb24gZ2xzbEJ1aWx0aW5VbmFyeShuYW1lOiBzdHJpbmcpOiBHbHNsVmFsdWVGdW5jdGlvbiB7XG4gIGNvbnN0IGJvZHkgPSBgXG4gIGZsb2F0ICR7bmFtZX1fKGZsb2F0IGEpIHtcbiAgICByZXR1cm4gJHtuYW1lfShhKTtcbiAgfVxuICB2ZWM0ICR7bmFtZX1fKHZlYzQgdikge1xuICAgIHJldHVybiAke25hbWV9KHYpO1xuICB9XG4gIGA7XG4gIHJldHVybiB7Ym9keSwgbmFtZSwgdHlwZTogRnVuY3Rpb25UeXBlLlZhbHVlQmFzZWR9O1xufVxuXG4vLy8vL1xuLy8vLy9cbi8vLy8vXG5cbmNvbnN0IGNyZWF0ZUVsZW1lbnR3aXNlUHJvZ3JhbUluZm8gPVxuICAgIChoYW5kbGVyOiBXZWJHTEluZmVyZW5jZUhhbmRsZXIsIG1ldGFkYXRhOiBQcm9ncmFtTWV0YWRhdGEsIGlucHV0OiBUZW5zb3IsIGdsc2xGdW5jOiBHbHNsVmFsdWVGdW5jdGlvbik6XG4gICAgICAgIFByb2dyYW1JbmZvID0+IHtcbiAgICAgICAgICBjb25zdCB0ZXh0dXJlVHlwZSA9IGhhbmRsZXIuc2Vzc2lvbi5wYWNrID8gVGV4dHVyZVR5cGUucGFja2VkIDogVGV4dHVyZVR5cGUudW5wYWNrZWQ7XG4gICAgICAgICAgY29uc3QgZ2xzbCA9IGdldEdsc2woaGFuZGxlci5zZXNzaW9uLmJhY2tlbmQuZ2xDb250ZXh0LnZlcnNpb24pO1xuICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAuLi5tZXRhZGF0YSxcbiAgICAgICAgICAgIG91dHB1dDoge2RpbXM6IGlucHV0LmRpbXMsIHR5cGU6IGlucHV0LnR5cGUsIHRleHR1cmVUeXBlfSxcbiAgICAgICAgICAgIHNoYWRlclNvdXJjZTogYFxuICAgICAke2dsc2xGdW5jLmJvZHl9XG4gICAgIHZvaWQgbWFpbigpIHtcbiAgICAgICB2ZWM0IHYgPSAke2dsc2wudGV4dHVyZTJEfShBLCBUZXhDb29yZHMpO1xuICAgICAgIHYgPSAke2dsc2xGdW5jLm5hbWV9Xyh2KTtcbiAgICAgICAke2dsc2wub3V0cHV0fSA9IHY7XG4gICAgIH1cbiAgICAgYCxcbiAgICAgICAgICAgIGhhc01haW46IHRydWVcbiAgICAgICAgICB9O1xuICAgICAgICB9O1xuXG5jb25zdCBjcmVhdGVFbGVtZW50d2lzZVByb2dyYW1JbmZvTG9hZGVyID1cbiAgICAoaGFuZGxlcjogV2ViR0xJbmZlcmVuY2VIYW5kbGVyLCBpbnB1dDogVGVuc29yLCBnbHNsRnVuYzogR2xzbFZhbHVlRnVuY3Rpb24sIGNhY2hlS2V5Pzogc3RyaW5nKTpcbiAgICAgICAgUHJvZ3JhbUluZm9Mb2FkZXIgPT4ge1xuICAgICAgICAgIGNvbnN0IHRleHR1cmVUeXBlID0gaGFuZGxlci5zZXNzaW9uLnBhY2sgPyBUZXh0dXJlVHlwZS5wYWNrZWQgOiBUZXh0dXJlVHlwZS51bnBhY2tlZDtcbiAgICAgICAgICBjb25zdCBtZXRhZGF0YSA9IHtuYW1lOiBnbHNsRnVuYy5uYW1lLCBpbnB1dFR5cGVzOiBbdGV4dHVyZVR5cGVdLCBpbnB1dE5hbWVzOiBbJ0EnXSwgY2FjaGVIaW50OiBjYWNoZUtleX07XG4gICAgICAgICAgcmV0dXJuIHsuLi5tZXRhZGF0YSwgZ2V0OiAoKSA9PiBjcmVhdGVFbGVtZW50d2lzZVByb2dyYW1JbmZvKGhhbmRsZXIsIG1ldGFkYXRhLCBpbnB1dCwgZ2xzbEZ1bmMpfTtcbiAgICAgICAgfTtcblxuZXhwb3J0IGNvbnN0IGFicyA9IChoYW5kbGVyOiBXZWJHTEluZmVyZW5jZUhhbmRsZXIsIGlucHV0czogVGVuc29yW10pOlxuICAgIFRlbnNvcltdID0+IFtoYW5kbGVyLnJ1bihjcmVhdGVFbGVtZW50d2lzZVByb2dyYW1JbmZvTG9hZGVyKGhhbmRsZXIsIGlucHV0c1swXSwgZ2xzbEFicygpKSwgaW5wdXRzKV07XG5cbmV4cG9ydCBjb25zdCBhY29zID0gKGhhbmRsZXI6IFdlYkdMSW5mZXJlbmNlSGFuZGxlciwgaW5wdXRzOiBUZW5zb3JbXSk6XG4gICAgVGVuc29yW10gPT4gW2hhbmRsZXIucnVuKGNyZWF0ZUVsZW1lbnR3aXNlUHJvZ3JhbUluZm9Mb2FkZXIoaGFuZGxlciwgaW5wdXRzWzBdLCBnbHNsQWNvcygpKSwgaW5wdXRzKV07XG5cbmV4cG9ydCBjb25zdCBhc2luID0gKGhhbmRsZXI6IFdlYkdMSW5mZXJlbmNlSGFuZGxlciwgaW5wdXRzOiBUZW5zb3JbXSk6XG4gICAgVGVuc29yW10gPT4gW2hhbmRsZXIucnVuKGNyZWF0ZUVsZW1lbnR3aXNlUHJvZ3JhbUluZm9Mb2FkZXIoaGFuZGxlciwgaW5wdXRzWzBdLCBnbHNsQXNpbigpKSwgaW5wdXRzKV07XG5cbmV4cG9ydCBjb25zdCBhdGFuID0gKGhhbmRsZXI6IFdlYkdMSW5mZXJlbmNlSGFuZGxlciwgaW5wdXRzOiBUZW5zb3JbXSk6XG4gICAgVGVuc29yW10gPT4gW2hhbmRsZXIucnVuKGNyZWF0ZUVsZW1lbnR3aXNlUHJvZ3JhbUluZm9Mb2FkZXIoaGFuZGxlciwgaW5wdXRzWzBdLCBnbHNsQXRhbigpKSwgaW5wdXRzKV07XG5cbmV4cG9ydCBpbnRlcmZhY2UgQ2xpcEF0dHJpYnV0ZXMgZXh0ZW5kcyBBdHRyaWJ1dGVXaXRoQ2FjaGVLZXkge1xuICByZWFkb25seSBtaW46IG51bWJlcjtcbiAgcmVhZG9ubHkgbWF4OiBudW1iZXI7XG59XG5cbmV4cG9ydCBjb25zdCBjbGlwID1cbiAgICAoaGFuZGxlcjogV2ViR0xJbmZlcmVuY2VIYW5kbGVyLCBpbnB1dHM6IFRlbnNvcltdLCBhdHRyaWJ1dGVzOiBDbGlwQXR0cmlidXRlcyk6IFRlbnNvcltdID0+IFtoYW5kbGVyLnJ1bihcbiAgICAgICAgY3JlYXRlRWxlbWVudHdpc2VQcm9ncmFtSW5mb0xvYWRlcihcbiAgICAgICAgICAgIGhhbmRsZXIsIGlucHV0c1swXSwgZ2xzbENsaXAoYXR0cmlidXRlcy5taW4sIGF0dHJpYnV0ZXMubWF4KSwgYXR0cmlidXRlcy5jYWNoZUtleSksXG4gICAgICAgIGlucHV0cyldO1xuXG5leHBvcnQgY29uc3QgcGFyc2VDbGlwQXR0cmlidXRlcyA9IChub2RlOiBHcmFwaC5Ob2RlKTogQ2xpcEF0dHJpYnV0ZXMgPT4gY3JlYXRlQXR0cmlidXRlV2l0aENhY2hlS2V5KFxuICAgIHttaW46IG5vZGUuYXR0cmlidXRlcy5nZXRGbG9hdCgnbWluJywgTUlOX0NMSVApLCBtYXg6IG5vZGUuYXR0cmlidXRlcy5nZXRGbG9hdCgnbWF4JywgTUFYX0NMSVApfSk7XG5cbmV4cG9ydCBjb25zdCBjbGlwVjExID0gKGhhbmRsZXI6IFdlYkdMSW5mZXJlbmNlSGFuZGxlciwgaW5wdXRzOiBUZW5zb3JbXSk6IFRlbnNvcltdID0+IHtcbiAgY29uc3QgYXR0cmlidXRlcyA9IGdlbmVyYXRlQ2xpcEF0dHJpYnV0ZXNGcm9tSW5wdXRzKGhhbmRsZXIsIGlucHV0cyk7XG4gIHJldHVybiBjbGlwKGhhbmRsZXIsIFtpbnB1dHNbMF1dLCBhdHRyaWJ1dGVzKTtcbn07XG5cbmNvbnN0IGdlbmVyYXRlQ2xpcEF0dHJpYnV0ZXNGcm9tSW5wdXRzID0gKGhhbmRsZXI6IFdlYkdMSW5mZXJlbmNlSGFuZGxlciwgaW5wdXRzOiBUZW5zb3JbXSk6IENsaXBBdHRyaWJ1dGVzID0+IHtcbiAgaWYgKGlucHV0cy5sZW5ndGggPj0gMyAmJlxuICAgICAgKCFoYW5kbGVyLnNlc3Npb24uaXNJbml0aWFsaXplcihpbnB1dHNbMV0uZGF0YUlkKSB8fCAhaGFuZGxlci5zZXNzaW9uLmlzSW5pdGlhbGl6ZXIoaW5wdXRzWzJdLmRhdGFJZCkpKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdkeW5hbWljIGNsaXAgYXR0cmlidXRlcyBhcmUgbm90IGFsbG93ZWQnKTtcbiAgfVxuXG4gIGNvbnN0IG1pbiA9IChpbnB1dHMubGVuZ3RoID49IDMpID8gaW5wdXRzWzFdLm51bWJlckRhdGFbMF0gOiBNSU5fQ0xJUDtcbiAgY29uc3QgbWF4ID0gKGlucHV0cy5sZW5ndGggPj0gMykgPyBpbnB1dHNbMl0ubnVtYmVyRGF0YVswXSA6IE1BWF9DTElQO1xuICByZXR1cm4gY3JlYXRlQXR0cmlidXRlV2l0aENhY2hlS2V5KHttaW4sIG1heH0pO1xufTtcblxuZXhwb3J0IGNvbnN0IGNlaWwgPSAoaGFuZGxlcjogV2ViR0xJbmZlcmVuY2VIYW5kbGVyLCBpbnB1dHM6IFRlbnNvcltdKTpcbiAgICBUZW5zb3JbXSA9PiBbaGFuZGxlci5ydW4oY3JlYXRlRWxlbWVudHdpc2VQcm9ncmFtSW5mb0xvYWRlcihoYW5kbGVyLCBpbnB1dHNbMF0sIGdsc2xDZWlsKCkpLCBpbnB1dHMpXTtcblxuZXhwb3J0IGNvbnN0IGNvcyA9IChoYW5kbGVyOiBXZWJHTEluZmVyZW5jZUhhbmRsZXIsIGlucHV0czogVGVuc29yW10pOlxuICAgIFRlbnNvcltdID0+IFtoYW5kbGVyLnJ1bihjcmVhdGVFbGVtZW50d2lzZVByb2dyYW1JbmZvTG9hZGVyKGhhbmRsZXIsIGlucHV0c1swXSwgZ2xzbENvcygpKSwgaW5wdXRzKV07XG5cbmV4cG9ydCBpbnRlcmZhY2UgRWx1QXR0cmlidXRlcyBleHRlbmRzIEF0dHJpYnV0ZVdpdGhDYWNoZUtleSB7XG4gIHJlYWRvbmx5IGFscGhhOiBudW1iZXI7XG59XG5cbmV4cG9ydCBjb25zdCBlbHUgPVxuICAgIChoYW5kbGVyOiBXZWJHTEluZmVyZW5jZUhhbmRsZXIsIGlucHV0czogVGVuc29yW10sIGF0dHJpYnV0ZXM6IEVsdUF0dHJpYnV0ZXMpOiBUZW5zb3JbXSA9PiBbaGFuZGxlci5ydW4oXG4gICAgICAgIGNyZWF0ZUVsZW1lbnR3aXNlUHJvZ3JhbUluZm9Mb2FkZXIoaGFuZGxlciwgaW5wdXRzWzBdLCBnbHNsRWx1KGF0dHJpYnV0ZXMuYWxwaGEpLCBhdHRyaWJ1dGVzLmNhY2hlS2V5KSxcbiAgICAgICAgaW5wdXRzKV07XG5cbmV4cG9ydCBjb25zdCBwYXJzZUVsdUF0dHJpYnV0ZXMgPSAobm9kZTogR3JhcGguTm9kZSk6IEVsdUF0dHJpYnV0ZXMgPT5cbiAgICBjcmVhdGVBdHRyaWJ1dGVXaXRoQ2FjaGVLZXkoe2FscGhhOiBub2RlLmF0dHJpYnV0ZXMuZ2V0RmxvYXQoJ2FscGhhJywgMS4wKX0pO1xuXG5leHBvcnQgY29uc3QgZXhwID0gKGhhbmRsZXI6IFdlYkdMSW5mZXJlbmNlSGFuZGxlciwgaW5wdXRzOiBUZW5zb3JbXSk6XG4gICAgVGVuc29yW10gPT4gW2hhbmRsZXIucnVuKGNyZWF0ZUVsZW1lbnR3aXNlUHJvZ3JhbUluZm9Mb2FkZXIoaGFuZGxlciwgaW5wdXRzWzBdLCBnbHNsRXhwKCkpLCBpbnB1dHMpXTtcblxuZXhwb3J0IGNvbnN0IGZsb29yID0gKGhhbmRsZXI6IFdlYkdMSW5mZXJlbmNlSGFuZGxlciwgaW5wdXRzOiBUZW5zb3JbXSk6XG4gICAgVGVuc29yW10gPT4gW2hhbmRsZXIucnVuKGNyZWF0ZUVsZW1lbnR3aXNlUHJvZ3JhbUluZm9Mb2FkZXIoaGFuZGxlciwgaW5wdXRzWzBdLCBnbHNsRmxvb3IoKSksIGlucHV0cyldO1xuXG5leHBvcnQgY29uc3QgaWRlbnRpdHkgPSAoaGFuZGxlcjogV2ViR0xJbmZlcmVuY2VIYW5kbGVyLCBpbnB1dHM6IFRlbnNvcltdKTpcbiAgICBUZW5zb3JbXSA9PiBbaGFuZGxlci5ydW4oY3JlYXRlRWxlbWVudHdpc2VQcm9ncmFtSW5mb0xvYWRlcihoYW5kbGVyLCBpbnB1dHNbMF0sIGdsc2xJZGVudGl0eSgpKSwgaW5wdXRzKV07XG5cbmV4cG9ydCBpbnRlcmZhY2UgTGVha3lSZWx1QXR0cmlidXRlcyBleHRlbmRzIEF0dHJpYnV0ZVdpdGhDYWNoZUtleSB7XG4gIHJlYWRvbmx5IGFscGhhOiBudW1iZXI7XG59XG5cbmV4cG9ydCBjb25zdCBsZWFreVJlbHUgPVxuICAgIChoYW5kbGVyOiBXZWJHTEluZmVyZW5jZUhhbmRsZXIsIGlucHV0czogVGVuc29yW10sIGF0dHJpYnV0ZXM6IExlYWt5UmVsdUF0dHJpYnV0ZXMpOiBUZW5zb3JbXSA9PiBbaGFuZGxlci5ydW4oXG4gICAgICAgIGNyZWF0ZUVsZW1lbnR3aXNlUHJvZ3JhbUluZm9Mb2FkZXIoaGFuZGxlciwgaW5wdXRzWzBdLCBnbHNsTGVha3lSZWx1KGF0dHJpYnV0ZXMuYWxwaGEpLCBhdHRyaWJ1dGVzLmNhY2hlS2V5KSxcbiAgICAgICAgaW5wdXRzKV07XG5cbmV4cG9ydCBjb25zdCBwYXJzZUxlYWt5UmVsdUF0dHJpYnV0ZXMgPSAobm9kZTogR3JhcGguTm9kZSk6IExlYWt5UmVsdUF0dHJpYnV0ZXMgPT5cbiAgICBjcmVhdGVBdHRyaWJ1dGVXaXRoQ2FjaGVLZXkoe2FscGhhOiBub2RlLmF0dHJpYnV0ZXMuZ2V0RmxvYXQoJ2FscGhhJywgMC4wMSl9KTtcblxuZXhwb3J0IGNvbnN0IGxvZyA9IChoYW5kbGVyOiBXZWJHTEluZmVyZW5jZUhhbmRsZXIsIGlucHV0czogVGVuc29yW10pOlxuICAgIFRlbnNvcltdID0+IFtoYW5kbGVyLnJ1bihjcmVhdGVFbGVtZW50d2lzZVByb2dyYW1JbmZvTG9hZGVyKGhhbmRsZXIsIGlucHV0c1swXSwgZ2xzbExvZygpKSwgaW5wdXRzKV07XG5cbmV4cG9ydCBjb25zdCBuZWcgPSAoaGFuZGxlcjogV2ViR0xJbmZlcmVuY2VIYW5kbGVyLCBpbnB1dHM6IFRlbnNvcltdKTpcbiAgICBUZW5zb3JbXSA9PiBbaGFuZGxlci5ydW4oY3JlYXRlRWxlbWVudHdpc2VQcm9ncmFtSW5mb0xvYWRlcihoYW5kbGVyLCBpbnB1dHNbMF0sIGdsc2xOZWcoKSksIGlucHV0cyldO1xuXG5leHBvcnQgY29uc3Qgbm90ID0gKGhhbmRsZXI6IFdlYkdMSW5mZXJlbmNlSGFuZGxlciwgaW5wdXRzOiBUZW5zb3JbXSk6XG4gICAgVGVuc29yW10gPT4gW2hhbmRsZXIucnVuKGNyZWF0ZUVsZW1lbnR3aXNlUHJvZ3JhbUluZm9Mb2FkZXIoaGFuZGxlciwgaW5wdXRzWzBdLCBnbHNsTm90KCkpLCBpbnB1dHMpXTtcblxuZXhwb3J0IGNvbnN0IHJlbHUgPSAoaGFuZGxlcjogV2ViR0xJbmZlcmVuY2VIYW5kbGVyLCBpbnB1dHM6IFRlbnNvcltdKTpcbiAgICBUZW5zb3JbXSA9PiBbaGFuZGxlci5ydW4oY3JlYXRlRWxlbWVudHdpc2VQcm9ncmFtSW5mb0xvYWRlcihoYW5kbGVyLCBpbnB1dHNbMF0sIGdsc2xSZWx1KCkpLCBpbnB1dHMpXTtcblxuZXhwb3J0IGNvbnN0IHNpZ21vaWQgPSAoaGFuZGxlcjogV2ViR0xJbmZlcmVuY2VIYW5kbGVyLCBpbnB1dHM6IFRlbnNvcltdKTpcbiAgICBUZW5zb3JbXSA9PiBbaGFuZGxlci5ydW4oY3JlYXRlRWxlbWVudHdpc2VQcm9ncmFtSW5mb0xvYWRlcihoYW5kbGVyLCBpbnB1dHNbMF0sIGdsc2xTaWdtb2lkKCkpLCBpbnB1dHMpXTtcblxuZXhwb3J0IGNvbnN0IHNpbiA9IChoYW5kbGVyOiBXZWJHTEluZmVyZW5jZUhhbmRsZXIsIGlucHV0czogVGVuc29yW10pOlxuICAgIFRlbnNvcltdID0+IFtoYW5kbGVyLnJ1bihjcmVhdGVFbGVtZW50d2lzZVByb2dyYW1JbmZvTG9hZGVyKGhhbmRsZXIsIGlucHV0c1swXSwgZ2xzbFNpbigpKSwgaW5wdXRzKV07XG5cbmV4cG9ydCBjb25zdCBzcXJ0ID0gKGhhbmRsZXI6IFdlYkdMSW5mZXJlbmNlSGFuZGxlciwgaW5wdXRzOiBUZW5zb3JbXSk6XG4gICAgVGVuc29yW10gPT4gW2hhbmRsZXIucnVuKGNyZWF0ZUVsZW1lbnR3aXNlUHJvZ3JhbUluZm9Mb2FkZXIoaGFuZGxlciwgaW5wdXRzWzBdLCBnbHNsU3FydCgpKSwgaW5wdXRzKV07XG5cbmV4cG9ydCBjb25zdCB0YW4gPSAoaGFuZGxlcjogV2ViR0xJbmZlcmVuY2VIYW5kbGVyLCBpbnB1dHM6IFRlbnNvcltdKTpcbiAgICBUZW5zb3JbXSA9PiBbaGFuZGxlci5ydW4oY3JlYXRlRWxlbWVudHdpc2VQcm9ncmFtSW5mb0xvYWRlcihoYW5kbGVyLCBpbnB1dHNbMF0sIGdsc2xUYW4oKSksIGlucHV0cyldO1xuXG5leHBvcnQgY29uc3QgdGFuaCA9IChoYW5kbGVyOiBXZWJHTEluZmVyZW5jZUhhbmRsZXIsIGlucHV0czogVGVuc29yW10pOlxuICAgIFRlbnNvcltdID0+IFtoYW5kbGVyLnJ1bihjcmVhdGVFbGVtZW50d2lzZVByb2dyYW1JbmZvTG9hZGVyKGhhbmRsZXIsIGlucHV0c1swXSwgZ2xzbFRhbmgoKSksIGlucHV0cyldO1xuIiwiLy8gQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXG5cbmltcG9ydCB7VGVuc29yfSBmcm9tICcuLi8uLi8uLi90ZW5zb3InO1xuaW1wb3J0IHtnZXRHbHNsfSBmcm9tICcuLi9nbHNsLXNvdXJjZSc7XG5pbXBvcnQge1dlYkdMSW5mZXJlbmNlSGFuZGxlcn0gZnJvbSAnLi4vaW5mZXJlbmNlLWhhbmRsZXInO1xuaW1wb3J0IHtQcm9ncmFtSW5mbywgUHJvZ3JhbUluZm9Mb2FkZXIsIFRleHR1cmVUeXBlfSBmcm9tICcuLi90eXBlcyc7XG5pbXBvcnQge2dldENvb3Jkc0RhdGFUeXBlfSBmcm9tICcuLi91dGlscyc7XG5cbmltcG9ydCB7Z2V0Q2hhbm5lbHMsIHVucGFja0Zyb21DaGFubmVsfSBmcm9tICcuL3BhY2tpbmctdXRpbHMnO1xuXG5jb25zdCB1bnBhY2tQcm9ncmFtTWV0YWRhdGEgPSB7XG4gIG5hbWU6ICd1bnBhY2snLFxuICBpbnB1dE5hbWVzOiBbJ0EnXSxcbiAgaW5wdXRUeXBlczogW1RleHR1cmVUeXBlLnBhY2tlZF1cbn07XG5cbmV4cG9ydCBjb25zdCBjcmVhdGVVbnBhY2tQcm9ncmFtSW5mbyA9IChoYW5kbGVyOiBXZWJHTEluZmVyZW5jZUhhbmRsZXIsIGlucHV0OiBUZW5zb3IpOiBQcm9ncmFtSW5mbyA9PiB7XG4gIGNvbnN0IHJhbmsgPSBpbnB1dC5kaW1zLmxlbmd0aDtcblxuICBjb25zdCBjaGFubmVscyA9IGdldENoYW5uZWxzKCdyYycsIHJhbmspO1xuICBjb25zdCBpbm5lckRpbXMgPSBjaGFubmVscy5zbGljZSgtMik7XG4gIGNvbnN0IGNvb3Jkc0RhdGFUeXBlID0gZ2V0Q29vcmRzRGF0YVR5cGUocmFuayk7XG4gIGNvbnN0IHVucGFja0NoYW5uZWwgPSB1bnBhY2tGcm9tQ2hhbm5lbCgpO1xuICBjb25zdCBpc1NjYWxhciA9IChpbnB1dC5kaW1zLmxlbmd0aCA9PT0gMCk7XG4gIGNvbnN0IHNvdXJjZUNvb3JkcyA9IGlzU2NhbGFyID8gJycgOiBnZXRTb3VyY2VDb29yZHMocmFuaywgY2hhbm5lbHMpO1xuICBjb25zdCBjb29yZHMgPSByYW5rIDw9IDEgPyAncmMnIDogYHZlYzIoJHtpbm5lckRpbXMuam9pbignLCcpfSlgO1xuICBjb25zdCBnbHNsID0gZ2V0R2xzbChoYW5kbGVyLnNlc3Npb24uYmFja2VuZC5nbENvbnRleHQudmVyc2lvbik7XG4gIGNvbnN0IHNoYWRlclNvdXJjZSA9IGBcbiAgICAke3VucGFja0NoYW5uZWx9XG4gICAgdm9pZCBtYWluKCkge1xuICAgICAgJHtjb29yZHNEYXRhVHlwZX0gcmMgPSBnZXRPdXRwdXRDb29yZHMoKTtcblxuICAgICAgIC8vIFNhbXBsZSB0aGUgdGV4dHVyZSB3aXRoIHRoZSBjb29yZHMgdG8gZ2V0IHRoZSByZ2JhIGNoYW5uZWwgdmFsdWUuXG4gICAgICAgdmVjNCBwYWNrZWRJbnB1dCA9IGdldEEoJHtzb3VyY2VDb29yZHN9KTtcblxuICAgICAgICR7Z2xzbC5vdXRwdXR9ID0gdmVjNChnZXRDaGFubmVsKHBhY2tlZElucHV0LCAke2Nvb3Jkc30pLCAwLCAwLCAwKTtcbiAgICAgfVxuICAgYDtcblxuICByZXR1cm4ge1xuICAgIC4uLnVucGFja1Byb2dyYW1NZXRhZGF0YSxcbiAgICBoYXNNYWluOiB0cnVlLFxuICAgIG91dHB1dDoge2RpbXM6IGlucHV0LmRpbXMsIHR5cGU6IGlucHV0LnR5cGUsIHRleHR1cmVUeXBlOiBUZXh0dXJlVHlwZS51bnBhY2tlZH0sXG4gICAgc2hhZGVyU291cmNlXG4gIH07XG59O1xuXG5leHBvcnQgY29uc3QgY3JlYXRlVW5wYWNrUHJvZ3JhbUluZm9Mb2FkZXIgPSAoaGFuZGxlcjogV2ViR0xJbmZlcmVuY2VIYW5kbGVyLCBpbnB1dDogVGVuc29yKTogUHJvZ3JhbUluZm9Mb2FkZXIgPT5cbiAgICAoey4uLnVucGFja1Byb2dyYW1NZXRhZGF0YSwgZ2V0OiAoKSA9PiBjcmVhdGVVbnBhY2tQcm9ncmFtSW5mbyhoYW5kbGVyLCBpbnB1dCl9KTtcblxuZnVuY3Rpb24gZ2V0U291cmNlQ29vcmRzKHJhbms6IG51bWJlciwgZGltczogc3RyaW5nW10pOiBzdHJpbmcge1xuICBpZiAocmFuayA9PT0gMSkge1xuICAgIHJldHVybiAncmMnO1xuICB9XG5cbiAgbGV0IGNvb3JkcyA9ICcnO1xuICBmb3IgKGxldCBpID0gMDsgaSA8IHJhbms7IGkrKykge1xuICAgIGNvb3JkcyArPSBkaW1zW2ldO1xuICAgIGlmIChpIDwgcmFuayAtIDEpIHtcbiAgICAgIGNvb3JkcyArPSAnLCc7XG4gICAgfVxuICB9XG4gIHJldHVybiBjb29yZHM7XG59XG4iLCIvLyBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cblxuaW1wb3J0IHtHcmFwaH0gZnJvbSAnLi4vLi4vLi4vZ3JhcGgnO1xuaW1wb3J0IHtPcGVyYXRvckltcGxlbWVudGF0aW9uLCBPcGVyYXRvckluaXRpYWxpemF0aW9ufSBmcm9tICcuLi8uLi8uLi9vcGVyYXRvcnMnO1xuaW1wb3J0IHtUZW5zb3J9IGZyb20gJy4uLy4uLy4uL3RlbnNvcic7XG5pbXBvcnQge1NoYXBlVXRpbH0gZnJvbSAnLi4vLi4vLi4vdXRpbCc7XG5pbXBvcnQge1dlYkdMSW5mZXJlbmNlSGFuZGxlcn0gZnJvbSAnLi4vaW5mZXJlbmNlLWhhbmRsZXInO1xuXG5leHBvcnQgY29uc3QgdW5zcXVlZXplOiBPcGVyYXRvckltcGxlbWVudGF0aW9uPG51bWJlcltdPiA9XG4gICAgKGluZmVyZW5jZUhhbmRsZXI6IFdlYkdMSW5mZXJlbmNlSGFuZGxlciwgaW5wdXRzOiBUZW5zb3JbXSwgYXhlczogbnVtYmVyW10pOiBUZW5zb3JbXSA9PiB7XG4gICAgICB2YWxpZGF0ZUlucHV0cyhpbnB1dHMpO1xuICAgICAgY29uc3Qgb3V0cHV0U2hhcGUgPSBTaGFwZVV0aWwudW5zcXVlZXplU2hhcGUoaW5wdXRzWzBdLmRpbXMsIGF4ZXMpO1xuICAgICAgY29uc3Qgb3V0cHV0ID0gaW5mZXJlbmNlSGFuZGxlci5yZXNoYXBlVW5wYWNrZWQoaW5wdXRzWzBdLCBvdXRwdXRTaGFwZSk7XG4gICAgICByZXR1cm4gW291dHB1dF07XG4gICAgfTtcblxuZXhwb3J0IGNvbnN0IHVuc3F1ZWV6ZVYxMyA9IChpbmZlcmVuY2VIYW5kbGVyOiBXZWJHTEluZmVyZW5jZUhhbmRsZXIsIGlucHV0czogVGVuc29yW10pOiBUZW5zb3JbXSA9PiB7XG4gIHZhbGlkYXRlSW5wdXRzVjEzKGlucHV0cyk7XG4gIHJldHVybiB1bnNxdWVlemUoaW5mZXJlbmNlSGFuZGxlciwgW2lucHV0c1swXV0sIEFycmF5LmZyb20oaW5wdXRzWzFdLmludGVnZXJEYXRhKSk7XG59O1xuXG5leHBvcnQgY29uc3QgcGFyc2VVbnNxdWVlemVBdHRyaWJ1dGVzOiBPcGVyYXRvckluaXRpYWxpemF0aW9uPG51bWJlcltdPiA9IChub2RlOiBHcmFwaC5Ob2RlKTogbnVtYmVyW10gPT5cbiAgICBub2RlLmF0dHJpYnV0ZXMuZ2V0SW50cygnYXhlcycpO1xuXG5jb25zdCB2YWxpZGF0ZUlucHV0cyA9IChpbnB1dHM6IFRlbnNvcltdKTogdm9pZCA9PiB7XG4gIGlmICghaW5wdXRzIHx8IGlucHV0cy5sZW5ndGggIT09IDEpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ1Vuc3F1ZWV6ZSByZXF1aXJlcyAxIGlucHV0LicpO1xuICB9XG5cbiAgaWYgKGlucHV0c1swXS50eXBlID09PSAnc3RyaW5nJykge1xuICAgIHRocm93IG5ldyBFcnJvcignaW52YWxpZCBpbnB1dCB0ZW5zb3IgdHlwZXMuJyk7XG4gIH1cbn07XG5cbmNvbnN0IHZhbGlkYXRlSW5wdXRzVjEzID0gKGlucHV0czogVGVuc29yW10pOiB2b2lkID0+IHtcbiAgaWYgKCFpbnB1dHMgfHwgaW5wdXRzLmxlbmd0aCAhPT0gMikge1xuICAgIHRocm93IG5ldyBFcnJvcignVW5zcXVlZXplIHJlcXVpcmVzIDIgaW5wdXRzLicpO1xuICB9XG5cbiAgaWYgKGlucHV0c1sxXS50eXBlICE9PSAnaW50MzInKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIGlucHV0IHR5cGUuJyk7XG4gIH1cbn07XG4iLCIvLyBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cblxuaW1wb3J0IHtBdHRyaWJ1dGVXaXRoQ2FjaGVLZXksIGNyZWF0ZUF0dHJpYnV0ZVdpdGhDYWNoZUtleX0gZnJvbSAnLi4vLi4vLi4vYXR0cmlidXRlLXdpdGgtY2FjaGUta2V5JztcbmltcG9ydCB7R3JhcGh9IGZyb20gJy4uLy4uLy4uL2dyYXBoJztcbmltcG9ydCB7T3BlcmF0b3JJbXBsZW1lbnRhdGlvbiwgT3BlcmF0b3JJbml0aWFsaXphdGlvbn0gZnJvbSAnLi4vLi4vLi4vb3BlcmF0b3JzJztcbmltcG9ydCB7VGVuc29yfSBmcm9tICcuLi8uLi8uLi90ZW5zb3InO1xuaW1wb3J0IHtnZXRHbHNsfSBmcm9tICcuLi9nbHNsLXNvdXJjZSc7XG5pbXBvcnQge1dlYkdMSW5mZXJlbmNlSGFuZGxlcn0gZnJvbSAnLi4vaW5mZXJlbmNlLWhhbmRsZXInO1xuaW1wb3J0IHtQcm9ncmFtSW5mbywgVGV4dHVyZVR5cGV9IGZyb20gJy4uL3R5cGVzJztcblxuZXhwb3J0IGludGVyZmFjZSBVcHNhbXBsZUF0dHJpYnV0ZXMgZXh0ZW5kcyBBdHRyaWJ1dGVXaXRoQ2FjaGVLZXkge1xuICByZWFkb25seSBvcHNldDogbnVtYmVyO1xuICByZWFkb25seSBpc1Jlc2l6ZTogYm9vbGVhbjtcbiAgcmVhZG9ubHkgbW9kZTogc3RyaW5nO1xuICByZWFkb25seSBzY2FsZXM6IG51bWJlcltdO1xuICByZWFkb25seSBleHRyYXBvbGF0aW9uVmFsdWU6IG51bWJlcjtcbiAgcmVhZG9ubHkgY29vcmRpbmF0ZVRyYW5zZm9ybU1vZGU6IHN0cmluZztcbiAgcmVhZG9ubHkgdXNlRXh0cmFwb2xhdGlvbjogYm9vbGVhbjtcbiAgcmVhZG9ubHkgbmVlZFJvaUlucHV0OiBib29sZWFuO1xuICByZWFkb25seSBuZWFyZXN0TW9kZTogc3RyaW5nO1xuICByZWFkb25seSBjdWJpY0NvZWZmaWNpZW50QTogbnVtYmVyO1xuICByZWFkb25seSBleGNsdWRlT3V0c2lkZTogYm9vbGVhbjtcbiAgcmVhZG9ubHkgdXNlTmVhcmVzdDJ4T3B0aW1pemF0aW9uOiBib29sZWFuO1xuICByZWFkb25seSByb2lJbnB1dElkeDogbnVtYmVyO1xuICByZWFkb25seSBzY2FsZXNJbnB1dElkeDogbnVtYmVyO1xuICByZWFkb25seSBzaXplc0lucHV0SWR4OiBudW1iZXI7XG59XG5cbmNvbnN0IHVwc2FtcGxlUHJvZ3JhbU1ldGFkYXRhID0ge1xuICBuYW1lOiAnVXBzYW1wbGUnLFxuICBpbnB1dE5hbWVzOiBbJ1gnXSxcbiAgaW5wdXRUeXBlczogW1RleHR1cmVUeXBlLnVucGFja2VkXSxcbn07XG5cbmV4cG9ydCBjb25zdCB1cHNhbXBsZTogT3BlcmF0b3JJbXBsZW1lbnRhdGlvbjxVcHNhbXBsZUF0dHJpYnV0ZXM+ID1cbiAgICAoaW5mZXJlbmNlSGFuZGxlcjogV2ViR0xJbmZlcmVuY2VIYW5kbGVyLCBpbnB1dHM6IFRlbnNvcltdLCBhdHRyaWJ1dGVzOiBVcHNhbXBsZUF0dHJpYnV0ZXMpOiBUZW5zb3JbXSA9PiB7XG4gICAgICB2YWxpZGF0ZUlucHV0cyhpbnB1dHMsIGF0dHJpYnV0ZXMpO1xuICAgICAgY29uc3Qgb3V0cHV0ID0gaW5mZXJlbmNlSGFuZGxlci5ydW4oXG4gICAgICAgICAge1xuICAgICAgICAgICAgLi4udXBzYW1wbGVQcm9ncmFtTWV0YWRhdGEsXG4gICAgICAgICAgICBjYWNoZUhpbnQ6IGF0dHJpYnV0ZXMuY2FjaGVLZXksXG4gICAgICAgICAgICBnZXQ6ICgpID0+IGNyZWF0ZVVwc2FtcGxlUHJvZ3JhbUluZm8oaW5mZXJlbmNlSGFuZGxlciwgaW5wdXRzLCBhdHRyaWJ1dGVzKVxuICAgICAgICAgIH0sXG4gICAgICAgICAgaW5wdXRzKTtcbiAgICAgIHJldHVybiBbb3V0cHV0XTtcbiAgICB9O1xuXG5leHBvcnQgY29uc3QgcGFyc2VVcHNhbXBsZUF0dHJpYnV0ZXNWNzogT3BlcmF0b3JJbml0aWFsaXphdGlvbjxVcHNhbXBsZUF0dHJpYnV0ZXM+ID1cbiAgICAobm9kZTogR3JhcGguTm9kZSk6IFVwc2FtcGxlQXR0cmlidXRlcyA9PiBwYXJzZVVwc2FtcGxlQXR0cmlidXRlcyhub2RlLCA3KTtcblxuZXhwb3J0IGNvbnN0IHBhcnNlVXBzYW1wbGVBdHRyaWJ1dGVzVjk6IE9wZXJhdG9ySW5pdGlhbGl6YXRpb248VXBzYW1wbGVBdHRyaWJ1dGVzPiA9XG4gICAgKG5vZGU6IEdyYXBoLk5vZGUpOiBVcHNhbXBsZUF0dHJpYnV0ZXMgPT4gcGFyc2VVcHNhbXBsZUF0dHJpYnV0ZXMobm9kZSwgOSk7XG5cbmV4cG9ydCBjb25zdCBwYXJzZVVwc2FtcGxlQXR0cmlidXRlcyA9IChub2RlOiBHcmFwaC5Ob2RlLCBvcHNldDogbnVtYmVyKTogVXBzYW1wbGVBdHRyaWJ1dGVzID0+IHtcbiAgY29uc3QgaXNSZXNpemUgPSAob3BzZXQgPj0gMTApO1xuXG4gIC8vIHByb2Nlc3Npbmcgbm9kZSBhdHRyaWJ1dGVzXG4gIGNvbnN0IG1vZGUgPSBub2RlLmF0dHJpYnV0ZXMuZ2V0U3RyaW5nKCdtb2RlJywgJ25lYXJlc3QnKTtcbiAgaWYgKG1vZGUgIT09ICduZWFyZXN0JyAmJiBtb2RlICE9PSAnbGluZWFyJyAmJiAob3BzZXQgPCAxMSB8fCBtb2RlICE9PSAnY3ViaWMnKSkge1xuICAgIHRocm93IG5ldyBFcnJvcihgdW5yZWNvZ25pemVkIG1vZGU6ICR7bW9kZX1gKTtcbiAgfVxuXG4gIGxldCBzY2FsZXM6IG51bWJlcltdID0gW107XG4gIGlmIChvcHNldCA8IDkpIHtcbiAgICBzY2FsZXMgPSBub2RlLmF0dHJpYnV0ZXMuZ2V0RmxvYXRzKCdzY2FsZXMnKTtcbiAgICBzY2FsZXNWYWxpZGF0aW9uKHNjYWxlcywgbW9kZSwgaXNSZXNpemUpO1xuICB9XG5cbiAgY29uc3QgZXh0cmFwb2xhdGlvblZhbHVlID0gbm9kZS5hdHRyaWJ1dGVzLmdldEZsb2F0KCdleHRyYXBvbGF0aW9uX3ZhbHVlJywgMC4wKTtcblxuICBjb25zdCBjb29yZGluYXRlVHJhbnNmb3JtTW9kZSA9XG4gICAgICBvcHNldCA+IDEwID8gbm9kZS5hdHRyaWJ1dGVzLmdldFN0cmluZygnY29vcmRpbmF0ZV90cmFuc2Zvcm1hdGlvbl9tb2RlJywgJ2hhbGZfcGl4ZWwnKSA6ICdhc3ltbWV0cmljJztcbiAgaWYgKFtcbiAgICAgICAgJ2FzeW1tZXRyaWMnLCAncHl0b3JjaF9oYWxmX3BpeGVsJywgJ3RmX2hhbGZfcGl4ZWxfZm9yX25uJywgJ2FsaWduX2Nvcm5lcnMnLCAndGZfY3JvcF9hbmRfcmVzaXplJywgJ2hhbGZfcGl4ZWwnXG4gICAgICBdLmluZGV4T2YoY29vcmRpbmF0ZVRyYW5zZm9ybU1vZGUpID09PSAtMSkge1xuICAgIHRocm93IG5ldyBFcnJvcihgY29vcmRpbmF0ZV90cmFuc2Zvcm1fbW9kZSAnJHtjb29yZGluYXRlVHJhbnNmb3JtTW9kZX0nIGlzIG5vdCBzdXBwb3J0ZWRgKTtcbiAgfVxuICBjb25zdCBuZWVkUm9pSW5wdXQgPSAoY29vcmRpbmF0ZVRyYW5zZm9ybU1vZGUgPT09ICd0Zl9jcm9wX2FuZF9yZXNpemUnKTtcbiAgY29uc3QgdXNlRXh0cmFwb2xhdGlvbiA9IG5lZWRSb2lJbnB1dDtcblxuICBjb25zdCBuZWFyZXN0TW9kZSA9XG4gICAgICAobW9kZSA9PT0gJ25lYXJlc3QnICYmIG9wc2V0ID49IDExKSA/IG5vZGUuYXR0cmlidXRlcy5nZXRTdHJpbmcoJ25lYXJlc3RfbW9kZScsICdyb3VuZF9wcmVmZXJfZmxvb3InKSA6ICcnO1xuICBpZiAoWydyb3VuZF9wcmVmZXJfZmxvb3InLCAncm91bmRfcHJlZmVyX2NlaWwnLCAnZmxvb3InLCAnY2VpbCcsICcnXS5pbmRleE9mKG5lYXJlc3RNb2RlKSA9PT0gLTEpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYG5lYXJlc3RfbW9kZSAnJHtuZWFyZXN0TW9kZX0nIGlzIG5vdCBzdXBwb3J0ZWRgKTtcbiAgfVxuXG4gIGNvbnN0IGN1YmljQ29lZmZpY2llbnRBID0gbm9kZS5hdHRyaWJ1dGVzLmdldEZsb2F0KCdjdWJpY19jb2VmZl9hJywgLTAuNzUpO1xuICBjb25zdCBleGNsdWRlT3V0c2lkZSA9IG5vZGUuYXR0cmlidXRlcy5nZXRJbnQoJ2V4Y2x1ZGVfb3V0c2lkZScsIDApICE9PSAwO1xuICBpZiAoZXhjbHVkZU91dHNpZGUgJiYgbW9kZSAhPT0gJ2N1YmljJykge1xuICAgIHRocm93IG5ldyBFcnJvcignZXhjbHVkZV9vdXRzaWRlIGNhbiBiZSBzZXQgdG8gMSBvbmx5IHdoZW4gbW9kZSBpcyBDVUJJQy4nKTtcbiAgfVxuXG4gIGNvbnN0IHVzZU5lYXJlc3QyeE9wdGltaXphdGlvbiA9XG4gICAgICAob3BzZXQgPCAxMSkgPyB0cnVlIDogKG1vZGUgPT09ICduZWFyZXN0JyAmJiBjb29yZGluYXRlVHJhbnNmb3JtTW9kZSA9PT0gJ2FzeW1tZXRyaWMnICYmIG5lYXJlc3RNb2RlID09PSAnZmxvb3InKTtcblxuICBsZXQgcm9pSW5wdXRJZHggPSAwO1xuICBsZXQgc2NhbGVzSW5wdXRJZHggPSAwO1xuICBsZXQgc2l6ZXNJbnB1dElkeCA9IDA7XG5cbiAgaWYgKG9wc2V0ID4gMTApIHtcbiAgICAvLyBoYW5kbGUgd2hlbiByb2lJbnB1dCBpcyBub3QgZ2l2ZW5cbiAgICBpZiAobm9kZS5pbnB1dHMubGVuZ3RoID4gMikge1xuICAgICAgcm9pSW5wdXRJZHggPSAxO1xuICAgICAgc2NhbGVzSW5wdXRJZHggPSAyO1xuICAgICAgc2l6ZXNJbnB1dElkeCA9IDM7XG4gICAgfSBlbHNlIHtcbiAgICAgIHNjYWxlc0lucHV0SWR4ID0gMTtcbiAgICAgIHNpemVzSW5wdXRJZHggPSAyO1xuICAgIH1cbiAgfSBlbHNlIGlmIChvcHNldCA9PT0gOSkge1xuICAgIHNjYWxlc0lucHV0SWR4ID0gMTtcbiAgfVxuXG4gIHJldHVybiBjcmVhdGVBdHRyaWJ1dGVXaXRoQ2FjaGVLZXkoe1xuICAgIG9wc2V0LFxuICAgIGlzUmVzaXplLFxuICAgIG1vZGUsXG4gICAgc2NhbGVzLFxuICAgIGV4dHJhcG9sYXRpb25WYWx1ZSxcbiAgICBjb29yZGluYXRlVHJhbnNmb3JtTW9kZSxcbiAgICB1c2VFeHRyYXBvbGF0aW9uLFxuICAgIG5lZWRSb2lJbnB1dCxcbiAgICBuZWFyZXN0TW9kZSxcbiAgICBjdWJpY0NvZWZmaWNpZW50QSxcbiAgICBleGNsdWRlT3V0c2lkZSxcbiAgICB1c2VOZWFyZXN0MnhPcHRpbWl6YXRpb24sXG4gICAgcm9pSW5wdXRJZHgsXG4gICAgc2NhbGVzSW5wdXRJZHgsXG4gICAgc2l6ZXNJbnB1dElkeFxuICB9KTtcbn07XG5cbmNvbnN0IGNyZWF0ZVVwc2FtcGxlUHJvZ3JhbUluZm8gPVxuICAgIChpbmZlcmVuY2VIYW5kbGVyOiBXZWJHTEluZmVyZW5jZUhhbmRsZXIsIGlucHV0czogVGVuc29yW10sIGF0dHJpYnV0ZXM6IFVwc2FtcGxlQXR0cmlidXRlcyk6IFByb2dyYW1JbmZvID0+IHtcbiAgICAgIGNvbnN0IGdsc2wgPSBnZXRHbHNsKGluZmVyZW5jZUhhbmRsZXIuc2Vzc2lvbi5iYWNrZW5kLmdsQ29udGV4dC52ZXJzaW9uKTtcbiAgICAgIGNvbnN0IFtpbnB1dFdpZHRoLCBpbnB1dEhlaWdodF0gPVxuICAgICAgICAgIGluZmVyZW5jZUhhbmRsZXIuY2FsY3VsYXRlVGV4dHVyZVdpZHRoQW5kSGVpZ2h0KGlucHV0c1swXS5kaW1zLCBUZXh0dXJlVHlwZS51bnBhY2tlZCk7XG5cbiAgICAgIGNvbnN0IG91dHB1dFNoYXBlID0gaW5wdXRzWzBdLmRpbXMubWFwKChkaW0sIGkpID0+IE1hdGguZmxvb3IoZGltICogYXR0cmlidXRlcy5zY2FsZXNbaV0pKTtcbiAgICAgIGNvbnN0IFtvdXRwdXRXaWR0aCwgb3V0cHV0SGVpZ2h0XSA9XG4gICAgICAgICAgaW5mZXJlbmNlSGFuZGxlci5jYWxjdWxhdGVUZXh0dXJlV2lkdGhBbmRIZWlnaHQob3V0cHV0U2hhcGUsIFRleHR1cmVUeXBlLnVucGFja2VkKTtcbiAgICAgIGNvbnN0IGRpbSA9IG91dHB1dFNoYXBlLmxlbmd0aDtcblxuICAgICAgY29uc3Qgb3V0cHV0UGl0Y2hlcyA9IG5ldyBBcnJheTxudW1iZXI+KGRpbSk7XG4gICAgICBjb25zdCBpbnB1dFBpdGNoZXMgPSBuZXcgQXJyYXk8bnVtYmVyPihkaW0pO1xuICAgICAgbGV0IHByZWNhbGN1bGF0ZWRQaXRjaGVzID0gYFxuICAgICAgaW50IG91dHB1dF9waXRjaGVzWyR7ZGltfV07XG4gICAgICBpbnQgaW5wdXRfcGl0Y2hlc1ske2RpbX1dO1xuICAgICAgYDtcbiAgICAgIGZvciAobGV0IGQgPSBkaW0gLSAxOyBkID49IDA7IGQtLSkge1xuICAgICAgICBvdXRwdXRQaXRjaGVzW2RdID0gKGQgPT09IGRpbSAtIDEpID8gMSA6IG91dHB1dFBpdGNoZXNbZCArIDFdICogb3V0cHV0U2hhcGVbZCArIDFdO1xuICAgICAgICBpbnB1dFBpdGNoZXNbZF0gPSAoZCA9PT0gZGltIC0gMSkgPyAxIDogaW5wdXRQaXRjaGVzW2QgKyAxXSAqIGlucHV0c1swXS5kaW1zW2QgKyAxXTtcblxuICAgICAgICBwcmVjYWxjdWxhdGVkUGl0Y2hlcyArPSBgXG4gICAgICAgIG91dHB1dF9waXRjaGVzWyR7ZH1dID0gJHtvdXRwdXRQaXRjaGVzW2RdfTtcbiAgICAgICAgaW5wdXRfcGl0Y2hlc1ske2R9XSA9ICR7aW5wdXRQaXRjaGVzW2RdfTtcbiAgICAgICAgYDtcbiAgICAgIH1cbiAgICAgIGNvbnN0IGdldElucHV0RmxvYXRGdW5jdGlvbiA9IGBcbiAgICAgIGZsb2F0IGdldElucHV0RmxvYXQoaW50IGluZGV4KSB7XG4gICAgICAgIHZlYzIgY29vcmRzID0gb2Zmc2V0VG9Db29yZHMoaW5kZXgsICR7aW5wdXRXaWR0aH0sICR7aW5wdXRIZWlnaHR9KTtcbiAgICAgICAgZmxvYXQgdmFsdWUgPSBnZXRDb2xvckFzRmxvYXQoJHtnbHNsLnRleHR1cmUyRH0oWCwgY29vcmRzKSk7XG4gICAgICAgIHJldHVybiB2YWx1ZTtcbiAgICAgIH1cbiAgICAgIGA7XG5cbiAgICAgIGNvbnN0IHNoYWRlclNvdXJjZSA9IGF0dHJpYnV0ZXMubW9kZSA9PT0gJ25lYXJlc3QnID9cbiAgICAgICAgICAvLyBuZWFyZXN0XG4gICAgICAgICAgYFxuICAgICR7Z2V0SW5wdXRGbG9hdEZ1bmN0aW9ufVxuICAgIGZsb2F0IHByb2Nlc3MoaW50IGluZGljZXNbJHtkaW19XSkge1xuICAgICAgaW50IGlucHV0X2luZGV4ID0gMDtcbiAgICAgIGludCBvdXRwdXRfaW5kZXggPSBjb29yZHNUb09mZnNldChUZXhDb29yZHMsICR7b3V0cHV0V2lkdGh9LCAke291dHB1dEhlaWdodH0pO1xuXG4gICAgICAke3ByZWNhbGN1bGF0ZWRQaXRjaGVzfVxuXG4gICAgICBpbnQgZCwgbTtcbiAgICAgIGZvciAoaW50IGRpbSA9IDA7IGRpbSA8ICR7ZGltfTsgKytkaW0pIHtcbiAgICAgICAgZCA9IG91dHB1dF9pbmRleCAvIG91dHB1dF9waXRjaGVzW2RpbV07XG4gICAgICAgIG0gPSBvdXRwdXRfaW5kZXggLSBkICogb3V0cHV0X3BpdGNoZXNbZGltXTtcbiAgICAgICAgb3V0cHV0X2luZGV4ID0gbTtcblxuICAgICAgICBpZiAoc2NhbGVzW2RpbV0gIT0gMSAmJiBkID4gMCkge1xuICAgICAgICAgIGludCBkMiA9IGQgLyBzY2FsZXNbZGltXTtcbiAgICAgICAgICBtID0gZCAtIGQyICogc2NhbGVzW2RpbV07XG4gICAgICAgICAgZCA9IGQyO1xuICAgICAgICB9XG4gICAgICAgIGlucHV0X2luZGV4ICs9IGlucHV0X3BpdGNoZXNbZGltXSAqIGQ7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBnZXRJbnB1dEZsb2F0KGlucHV0X2luZGV4KTtcbiAgICB9YCA6XG4gICAgICAgICAgZGltID09PSA0ID9cbiAgICAgICAgICAvLyBiaWxpbmVhciA0RFxuICAgICAgICAgICAgICBgXG4gICAgJHtnZXRJbnB1dEZsb2F0RnVuY3Rpb259XG4gICAgZmxvYXQgcHJvY2VzcyhpbnQgaW5kaWNlc1s0XSkge1xuICAgICAgaW50IGlucHV0X2luZGV4ID0gMDtcbiAgICAgIGludCBvdXRwdXRfaW5kZXggPSBjb29yZHNUb09mZnNldChUZXhDb29yZHMsICR7b3V0cHV0V2lkdGh9LCAke291dHB1dEhlaWdodH0pO1xuXG4gICAgICAke3ByZWNhbGN1bGF0ZWRQaXRjaGVzfVxuXG4gICAgICBpbnQgbTtcbiAgICAgIGludCBpbmRleF9vZl9kaW0wLCBpbmRleF9vZl9kaW0xLCBpbmRleF9vZl9kaW0yLCBpbmRleF9vZl9kaW0zO1xuICAgICAgaW5kZXhfb2ZfZGltMCA9IG91dHB1dF9pbmRleCAvIG91dHB1dF9waXRjaGVzWzBdO1xuICAgICAgbSA9IG91dHB1dF9pbmRleCAtIGluZGV4X29mX2RpbTAgKiBvdXRwdXRfcGl0Y2hlc1swXTtcbiAgICAgIGluZGV4X29mX2RpbTEgPSBtIC8gb3V0cHV0X3BpdGNoZXNbMV07XG4gICAgICBtID0gbSAtIGluZGV4X29mX2RpbTEgKiBvdXRwdXRfcGl0Y2hlc1sxXTtcbiAgICAgIGluZGV4X29mX2RpbTIgPSBtIC8gb3V0cHV0X3BpdGNoZXNbMl07XG4gICAgICBtID0gbSAtIGluZGV4X29mX2RpbTIgKiBvdXRwdXRfcGl0Y2hlc1syXTtcbiAgICAgIGluZGV4X29mX2RpbTMgPSBtO1xuXG4gICAgICBpbnQgaW5kZXhfb2ZfaW5wdXRfZGltMiwgaW5kZXhfb2ZfaW5wdXRfZGltMywgeF9vZmZzZXQsIHlfb2Zmc2V0O1xuICAgICAgaW5kZXhfb2ZfaW5wdXRfZGltMiA9IGluZGV4X29mX2RpbTIgLyBzY2FsZXNbMl07XG4gICAgICB5X29mZnNldCA9IGluZGV4X29mX2RpbTIgLSBpbmRleF9vZl9pbnB1dF9kaW0yICogc2NhbGVzWzJdO1xuICAgICAgaW5kZXhfb2ZfaW5wdXRfZGltMyA9IGluZGV4X29mX2RpbTMgLyBzY2FsZXNbM107XG4gICAgICB4X29mZnNldCA9IGluZGV4X29mX2RpbTMgLSBpbmRleF9vZl9pbnB1dF9kaW0zICogc2NhbGVzWzNdO1xuXG4gICAgICBpbnB1dF9pbmRleCA9IGluZGV4X29mX2RpbTAgKiBpbnB1dF9waXRjaGVzWzBdICtcbiAgICAgICAgICAgIGluZGV4X29mX2RpbTEgKiBpbnB1dF9waXRjaGVzWzFdICtcbiAgICAgICAgICAgIGluZGV4X29mX2lucHV0X2RpbTIgKiBpbnB1dF9waXRjaGVzWzJdICtcbiAgICAgICAgICAgIGluZGV4X29mX2lucHV0X2RpbTM7XG5cbiAgICAgIGZsb2F0IHgwMCA9IGdldElucHV0RmxvYXQoaW5wdXRfaW5kZXgpO1xuICAgICAgZmxvYXQgeDEwLCB4MDEsIHgxMTtcblxuICAgICAgYm9vbCBlbmRfb2ZfZGltMiA9IGZhbHNlO1xuICAgICAgaWYgKGluZGV4X29mX2lucHV0X2RpbTIgPT0gKCR7aW5wdXRzWzBdLmRpbXNbMl19IC0gMSkpIHtcbiAgICAgICAgLy8gSXQncyB0aGUgZW5kIGluIGRpbWVuc2lvbiAyXG4gICAgICAgIHgwMSA9IHgwMDtcbiAgICAgICAgZW5kX29mX2RpbTIgPSB0cnVlO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgeDAxID0gZ2V0SW5wdXRGbG9hdChpbnB1dF9pbmRleCArIGlucHV0X3BpdGNoZXNbMl0pO1xuICAgICAgfVxuXG4gICAgICBpZiAoaW5kZXhfb2ZfaW5wdXRfZGltMyA9PSAoaW5wdXRfcGl0Y2hlc1syXSAtIDEpKSB7XG4gICAgICAgIC8vIEl0J3MgdGhlIGVuZCBpbiBkaW1lbnNpb24gM1xuICAgICAgICB4MTAgPSB4MDA7XG4gICAgICAgIHgxMSA9IHgwMTtcbiAgICAgIH1cbiAgICAgIGVsc2Uge1xuICAgICAgICB4MTAgPSBnZXRJbnB1dEZsb2F0KGlucHV0X2luZGV4ICsgMSk7XG4gICAgICAgIHgxMSA9IGVuZF9vZl9kaW0yID8geDEwIDogZ2V0SW5wdXRGbG9hdChpbnB1dF9pbmRleCArIGlucHV0X3BpdGNoZXNbMl0gKyAxKTtcbiAgICAgIH1cblxuICAgICAgZmxvYXQgeTAgPSB4MDAgKyBmbG9hdCh5X29mZnNldCkgKiAoeDAxIC0geDAwKSAvIGZsb2F0KHNjYWxlc1syXSk7XG4gICAgICBmbG9hdCB5MSA9IHgxMCArIGZsb2F0KHlfb2Zmc2V0KSAqICh4MTEgLSB4MTApIC8gZmxvYXQoc2NhbGVzWzJdKTtcbiAgICAgIHJldHVybiB5MCArIGZsb2F0KHhfb2Zmc2V0KSAqICh5MSAtIHkwKSAvIGZsb2F0KHNjYWxlc1szXSk7XG4gICAgfWAgOlxuICAgICAgICAgICAgICAvLyBiaWxpbmVhciAyRFxuICAgICAgICAgICAgICBgXG4gICAgJHtnZXRJbnB1dEZsb2F0RnVuY3Rpb259XG4gICAgZmxvYXQgcHJvY2VzcyhpbnQgaW5kaWNlc1syXSkge1xuICAgICAgaW50IGlucHV0X2luZGV4ID0gMDtcbiAgICAgIGludCBvdXRwdXRfaW5kZXggPSBjb29yZHNUb09mZnNldChUZXhDb29yZHMsICR7b3V0cHV0V2lkdGh9LCAke291dHB1dEhlaWdodH0pO1xuXG4gICAgICAke3ByZWNhbGN1bGF0ZWRQaXRjaGVzfVxuXG4gICAgICBpbnQgbTtcbiAgICAgIGludCBpbmRleF9vZl9kaW0wLCBpbmRleF9vZl9kaW0xO1xuICAgICAgaW5kZXhfb2ZfZGltMCA9IG91dHB1dF9pbmRleCAvIG91dHB1dF9waXRjaGVzWzBdO1xuICAgICAgbSA9IG91dHB1dF9pbmRleCAtIGluZGV4X29mX2RpbTAgKiBvdXRwdXRfcGl0Y2hlc1swXTtcbiAgICAgIGluZGV4X29mX2RpbTEgPSBtO1xuXG4gICAgICBpbnQgaW5kZXhfb2ZfaW5wdXRfZGltMCwgaW5kZXhfb2ZfaW5wdXRfZGltMSwgeF9vZmZzZXQsIHlfb2Zmc2V0O1xuICAgICAgaW5kZXhfb2ZfaW5wdXRfZGltMCA9IGluZGV4X29mX2RpbTAgLyBzY2FsZXNbMF07XG4gICAgICB5X29mZnNldCA9IGluZGV4X29mX2RpbTAgLSBpbmRleF9vZl9pbnB1dF9kaW0wICogc2NhbGVzWzBdO1xuICAgICAgaW5kZXhfb2ZfaW5wdXRfZGltMSA9IGluZGV4X29mX2RpbTEgLyBzY2FsZXNbMV07XG4gICAgICB4X29mZnNldCA9IGluZGV4X29mX2RpbTEgLSBpbmRleF9vZl9pbnB1dF9kaW0xICogc2NhbGVzWzFdO1xuXG4gICAgICBpbnB1dF9pbmRleCA9IGluZGV4X29mX2lucHV0X2RpbTAgKiBpbnB1dF9waXRjaGVzWzBdICsgaW5kZXhfb2ZfaW5wdXRfZGltMTtcblxuICAgICAgZmxvYXQgeDAwID0gZ2V0SW5wdXRGbG9hdChpbnB1dF9pbmRleCk7XG4gICAgICBmbG9hdCB4MTAsIHgwMSwgeDExO1xuXG4gICAgICBib29sIGVuZF9vZl9kaW0wID0gZmFsc2U7XG4gICAgICBpZiAoaW5kZXhfb2ZfaW5wdXRfZGltMCA9PSAoJHtpbnB1dHNbMF0uZGltc1swXX0gLSAxKSkge1xuICAgICAgICAvLyBJdCdzIHRoZSBlbmQgaW4gZGltZW5zaW9uIDBcbiAgICAgICAgeDAxID0geDAwO1xuICAgICAgICBlbmRfb2ZfZGltMCA9IHRydWU7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB4MDEgPSBnZXRJbnB1dEZsb2F0KGlucHV0X2luZGV4ICsgaW5wdXRfcGl0Y2hlc1swXSk7XG4gICAgICB9XG5cbiAgICAgIGlmIChpbmRleF9vZl9pbnB1dF9kaW0xID09IChpbnB1dF9waXRjaGVzWzBdIC0gMSkpIHtcbiAgICAgICAgLy8gSXQncyB0aGUgZW5kIGluIGRpbWVuc2lvbiAxXG4gICAgICAgIHgxMCA9IHgwMDtcbiAgICAgICAgeDExID0geDAxO1xuICAgICAgfVxuICAgICAgZWxzZSB7XG4gICAgICAgIHgxMCA9IGdldElucHV0RmxvYXQoaW5wdXRfaW5kZXggKyAxKTtcbiAgICAgICAgeDExID0gZW5kX29mX2RpbTAgPyB4MTAgOiBnZXRJbnB1dEZsb2F0KGlucHV0X2luZGV4ICsgaW5wdXRfcGl0Y2hlc1swXSArIDEpO1xuICAgICAgfVxuXG4gICAgICBmbG9hdCB5MCA9IHgwMCArIGZsb2F0KHlfb2Zmc2V0KSAqICh4MDEgLSB4MDApIC8gZmxvYXQoc2NhbGVzWzBdKTtcbiAgICAgIGZsb2F0IHkxID0geDEwICsgZmxvYXQoeV9vZmZzZXQpICogKHgxMSAtIHgxMCkgLyBmbG9hdChzY2FsZXNbMF0pO1xuICAgICAgcmV0dXJuIHkwICsgZmxvYXQoeF9vZmZzZXQpICogKHkxIC0geTApIC8gZmxvYXQoc2NhbGVzWzFdKTtcbiAgICB9YDtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIC4uLnVwc2FtcGxlUHJvZ3JhbU1ldGFkYXRhLFxuICAgICAgICBvdXRwdXQ6IHtkaW1zOiBvdXRwdXRTaGFwZSwgdHlwZTogaW5wdXRzWzBdLnR5cGUsIHRleHR1cmVUeXBlOiBUZXh0dXJlVHlwZS51bnBhY2tlZH0sXG4gICAgICAgIHNoYWRlclNvdXJjZSxcbiAgICAgICAgdmFyaWFibGVzOiBbe1xuICAgICAgICAgIG5hbWU6ICdzY2FsZXMnLFxuICAgICAgICAgIHR5cGU6ICdpbnQnLFxuICAgICAgICAgIGFycmF5TGVuZ3RoOiBhdHRyaWJ1dGVzLnNjYWxlcy5sZW5ndGgsXG4gICAgICAgICAgZGF0YTogYXR0cmlidXRlcy5zY2FsZXMubWFwKHggPT4gTWF0aC5jZWlsKHgpKVxuICAgICAgICB9XVxuICAgICAgfTtcbiAgICB9O1xuXG5leHBvcnQgY29uc3QgdmFsaWRhdGVJbnB1dHMgPSAoaW5wdXRzOiBUZW5zb3JbXSwgYXR0cmlidXRlOiBVcHNhbXBsZUF0dHJpYnV0ZXMpOiB2b2lkID0+IHtcbiAgaWYgKCFpbnB1dHMgfHwgKGF0dHJpYnV0ZS5vcHNldCA8IDkgJiYgaW5wdXRzLmxlbmd0aCAhPT0gMSkgfHxcbiAgICAgIChhdHRyaWJ1dGUub3BzZXQgPj0gOSAmJiBhdHRyaWJ1dGUub3BzZXQgPCAxMSAmJiBpbnB1dHMubGVuZ3RoICE9PSAyKSB8fFxuICAgICAgKGF0dHJpYnV0ZS5vcHNldCA+PSAxMSAmJiBpbnB1dHMubGVuZ3RoIDwgMikpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ2ludmFsaWQgaW5wdXRzLicpO1xuICB9XG5cbiAgaWYgKGF0dHJpYnV0ZS5zY2FsZXMubGVuZ3RoID4gMCAmJiBpbnB1dHNbMF0uZGltcy5sZW5ndGggIT09IGF0dHJpYnV0ZS5zY2FsZXMubGVuZ3RoKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIGlucHV0IHNoYXBlLicpO1xuICB9XG5cbiAgaWYgKGlucHV0c1swXS50eXBlID09PSAnc3RyaW5nJykge1xuICAgIHRocm93IG5ldyBFcnJvcignSW52YWxpZCBpbnB1dCB0ZW5zb3IgdHlwZXMuJyk7XG4gIH1cbn07XG5cbmV4cG9ydCBjb25zdCBzY2FsZXNWYWxpZGF0aW9uID0gKHNjYWxlczogbnVtYmVyW10sIG1vZGU6IHN0cmluZywgaXNSZXNpemU6IGJvb2xlYW4pOiB2b2lkID0+IHtcbiAgaWYgKCFpc1Jlc2l6ZSkge1xuICAgIGZvciAoY29uc3Qgc2NhbGUgb2Ygc2NhbGVzKSB7XG4gICAgICBpZiAoc2NhbGUgPCAxKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignU2NhbGUgdmFsdWUgc2hvdWxkIGJlIGdyZWF0ZXIgdGhhbiBvciBlcXVhbCB0byAxLicpO1xuICAgICAgfVxuICAgIH1cbiAgfSBlbHNlIHtcbiAgICBmb3IgKGNvbnN0IHNjYWxlIG9mIHNjYWxlcykge1xuICAgICAgaWYgKHNjYWxlIDw9IDApIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdTY2FsZSB2YWx1ZSBzaG91bGQgYmUgZ3JlYXRlciB0aGFuIDAuJyk7XG4gICAgICB9XG4gICAgfVxuICB9XG4gIGlmIChtb2RlID09PSAnbGluZWFyJyB8fCBtb2RlID09PSAnY3ViaWMnKSB7XG4gICAgaWYgKHNjYWxlcy5sZW5ndGggIT09IDIgJiYgKHNjYWxlcy5sZW5ndGggIT09IDQgfHwgc2NhbGVzWzBdICE9PSAxIHx8IHNjYWxlc1sxXSAhPT0gMSkpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgJ0xpbmVhcicgbW9kZSBhbmQgJ0N1YmljJyBtb2RlIG9ubHkgc3VwcG9ydCAyLUQgaW5wdXRzICgnQmlsaW5lYXInLCAnQmljdWJpYycpIFxcXG4gICAgICAgIG9yIDQtRCBpbnB1dHMgd2l0aCB0aGUgY29ycmVzcG9uZGluZyBvdXRlcm1vc3QgMiBzY2FsZSB2YWx1ZXMgYmVpbmcgMSBcXFxuICAgICAgICBpbiB0aGUgJHtpc1Jlc2l6ZSA/ICdSZXNpemUnIDogJ1Vwc2FtcGxlJ30gb3BlYXJ0b3IuYCk7XG4gICAgfVxuICB9XG59OyIsIi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxuXG5pbXBvcnQge2Vudn0gZnJvbSAnb25ueHJ1bnRpbWUtY29tbW9uJztcblxuaW1wb3J0IHtMb2dnZXIsIFByb2ZpbGVyfSBmcm9tICcuLi8uLi9pbnN0cnVtZW50JztcblxuaW1wb3J0IHtHbHNsUHJlcHJvY2Vzc29yfSBmcm9tICcuL2dsc2wtcHJlcHJvY2Vzc29yJztcbmltcG9ydCB7Z2V0VmVydGV4U2hhZGVyU291cmNlfSBmcm9tICcuL2dsc2wtc291cmNlJztcbmltcG9ydCB7VGV4dHVyZUxheW91dFN0cmF0ZWd5fSBmcm9tICcuL3RleHR1cmUtbGF5b3V0LXN0cmF0ZWd5JztcbmltcG9ydCB7QXJ0aWZhY3QsIFByb2dyYW1JbmZvLCBQcm9ncmFtVmFyaWFibGUsIFRleHR1cmVEYXRhLCBUZXh0dXJlTGF5b3V0LCBWYXJpYWJsZUluZm99IGZyb20gJy4vdHlwZXMnO1xuaW1wb3J0IHtXZWJHTENvbnRleHR9IGZyb20gJy4vd2ViZ2wtY29udGV4dCc7XG5cbi8qKlxuICogUHJvZ3JhbU1hbmFnZXIgaXMgdGhlIG1haW4gY2xhc3MgYmVoaW5kIHJ1bm5pbmcgY29tcHV0YXRpb25zXG4gKiBJdCBidWlsZHMgUHJvZ3JhbUluZm8ncyBpbnRvIEFydGlmYWN0c1xuICogSXQgY29tcGlsZXMgZ2l2ZW4gUHJvZ3JhbUluZm8ncyBpbnRvIFdlYkdMIFByb3JhbXMgKGNhY2hlZCBhcyBBcnRpZmFjdHMpXG4gKiBVc2VzIHRoZSBhcnRpZmFjdCB0byBydW4gdGhlIGNvbXB1dGF0aW9uIGJ5IGNhbGxpbmcgRHJhdyBvblxuICogdGhlIFdlYkdMIGRyYXdpbmcgYnVmZmVyXG4gKiBQcm9ncmFtTWFuYWdlciBhdXRvbWF0aWNhbGx5IG1hcHMgKGJpbmRzKSBpbnB1dCB2YXJpYWJsZXMgdG8gdGhlaXJcbiAqIGNvcnJlc3BvbmRpbmcgTG9jYXRpb24ncyBpbiB0aGUgYmluYXJ5IHByb2dyYW1cbiAqL1xuZXhwb3J0IGNsYXNzIFByb2dyYW1NYW5hZ2VyIHtcbiAgcmVwbzogTWFwPHVua25vd24sIEFydGlmYWN0PjsgIC8vIHRoaXMgc2hvdWxkIGJlIHBlci1zZXNzaW9uIG9iamVjdFxuICB2ZXJ0ZXhTaGFkZXI6IFdlYkdMU2hhZGVyO1xuICBhdHRyaWJ1dGVzQm91bmQ6IGJvb2xlYW47XG5cbiAgY29uc3RydWN0b3IoXG4gICAgICBwdWJsaWMgcHJvZmlsZXI6IFJlYWRvbmx5PFByb2ZpbGVyPiwgcHVibGljIGdsQ29udGV4dDogV2ViR0xDb250ZXh0LFxuICAgICAgcHVibGljIHRleHR1cmVMYXlvdXRTdHJhdGVneTogVGV4dHVyZUxheW91dFN0cmF0ZWd5KSB7XG4gICAgdGhpcy5yZXBvID0gbmV3IE1hcCgpO1xuICAgIHRoaXMuYXR0cmlidXRlc0JvdW5kID0gZmFsc2U7XG4gIH1cbiAgZ2V0QXJ0aWZhY3Qoa2V5OiB1bmtub3duKTogQXJ0aWZhY3R8dW5kZWZpbmVkIHtcbiAgICByZXR1cm4gdGhpcy5yZXBvLmdldChrZXkpO1xuICB9XG4gIHNldEFydGlmYWN0KGtleTogdW5rbm93biwgYXJ0aWZhY3Q6IEFydGlmYWN0KTogdm9pZCB7XG4gICAgdGhpcy5yZXBvLnNldChrZXksIGFydGlmYWN0KTtcbiAgfVxuICBydW4oYnVpbGRBcnRpZmFjdDogQXJ0aWZhY3QsIGlucHV0czogVGV4dHVyZURhdGFbXSwgb3V0cHV0OiBUZXh0dXJlRGF0YSk6IHZvaWQge1xuICAgIHRoaXMucHJvZmlsZXIuZXZlbnQoJ29wJywgYFByb2dyYW1NYW5hZ2VyLnJ1biAke2J1aWxkQXJ0aWZhY3QucHJvZ3JhbUluZm8ubmFtZSA/PyAndW5rbm93biBrZXJuZWwnfWAsICgpID0+IHtcbiAgICAgIGNvbnN0IGdsID0gdGhpcy5nbENvbnRleHQuZ2w7XG4gICAgICBjb25zdCBwcm9ncmFtID0gYnVpbGRBcnRpZmFjdC5wcm9ncmFtO1xuICAgICAgZ2wudXNlUHJvZ3JhbShwcm9ncmFtKTtcbiAgICAgIHRyeSB7XG4gICAgICAgIHRoaXMuYmluZE91dHB1dChvdXRwdXQpO1xuICAgICAgICBpZiAoIXRoaXMuYXR0cmlidXRlc0JvdW5kKSB7XG4gICAgICAgICAgdGhpcy5iaW5kQXR0cmlidXRlcyhidWlsZEFydGlmYWN0LmF0dHJpYkxvY2F0aW9ucyk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5iaW5kVW5pZm9ybXMoYnVpbGRBcnRpZmFjdC51bmlmb3JtTG9jYXRpb25zLCBidWlsZEFydGlmYWN0LnByb2dyYW1JbmZvLnZhcmlhYmxlcyA/PyBbXSwgaW5wdXRzKTtcbiAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICBMb2dnZXIuZXJyb3IoJ1Byb2dyYW1NYW5hZ2VyJywgYnVpbGRBcnRpZmFjdC5wcm9ncmFtSW5mby5zaGFkZXJTb3VyY2UpO1xuICAgICAgICB0aHJvdyBlcnI7XG4gICAgICB9XG4gICAgICB0aGlzLnByb2ZpbGVyLmV2ZW50KCdiYWNrZW5kJywgJ0dsQ29udGV4dC5kcmF3KCknLCAoKSA9PiB7XG4gICAgICAgIHRoaXMuZ2xDb250ZXh0LmRyYXcoKTtcbiAgICAgIH0pO1xuICAgIH0sIHRoaXMuZ2xDb250ZXh0KTtcbiAgfVxuICBkaXNwb3NlKCk6IHZvaWQge1xuICAgIGlmICh0aGlzLnZlcnRleFNoYWRlcikge1xuICAgICAgdGhpcy5nbENvbnRleHQuZGVsZXRlU2hhZGVyKHRoaXMudmVydGV4U2hhZGVyKTtcbiAgICB9XG4gICAgdGhpcy5yZXBvLmZvckVhY2goYSA9PiB0aGlzLmdsQ29udGV4dC5kZWxldGVQcm9ncmFtKGEucHJvZ3JhbSkpO1xuICB9XG4gIGJ1aWxkKHByb2dyYW1JbmZvOiBQcm9ncmFtSW5mbywgaW5wdXRUZXh0dXJlTGF5b3V0czogVGV4dHVyZUxheW91dFtdLCBvdXRwdXRUZXh0dXJlTGF5b3V0OiBUZXh0dXJlTGF5b3V0KTogQXJ0aWZhY3Qge1xuICAgIHJldHVybiB0aGlzLnByb2ZpbGVyLmV2ZW50KCdiYWNrZW5kJywgJ1Byb2dyYW1NYW5hZ2VyLmJ1aWxkJywgKCkgPT4ge1xuICAgICAgY29uc3QgcHJlcHJvY2Vzc29yID0gbmV3IEdsc2xQcmVwcm9jZXNzb3IodGhpcy5nbENvbnRleHQsIHByb2dyYW1JbmZvLCBpbnB1dFRleHR1cmVMYXlvdXRzLCBvdXRwdXRUZXh0dXJlTGF5b3V0KTtcbiAgICAgIGNvbnN0IGZyYWdTY3JpcHQgPSBwcmVwcm9jZXNzb3IucHJlcHJvY2VzcygpO1xuICAgICAgY29uc3QgcHJvZ3JhbSA9IHRoaXMuY29tcGlsZShmcmFnU2NyaXB0KTtcbiAgICAgIGNvbnN0IGFydGlmYWN0ID0ge1xuICAgICAgICBwcm9ncmFtSW5mbyxcbiAgICAgICAgcHJvZ3JhbSxcbiAgICAgICAgdW5pZm9ybUxvY2F0aW9uczogdGhpcy5nZXRVbmlmb3JtTG9jYXRpb25zKFxuICAgICAgICAgICAgcHJvZ3JhbSwgcHJlcHJvY2Vzc29yLmNvbnRleHQucHJvZ3JhbUluZm8uaW5wdXROYW1lcywgcHJlcHJvY2Vzc29yLmNvbnRleHQucHJvZ3JhbUluZm8udmFyaWFibGVzKSxcbiAgICAgICAgYXR0cmliTG9jYXRpb25zOiB0aGlzLmdldEF0dHJpYkxvY2F0aW9ucyhwcm9ncmFtKVxuICAgICAgfTtcbiAgICAgIHJldHVybiBhcnRpZmFjdDtcbiAgICB9KTtcbiAgfVxuICBwcm90ZWN0ZWQgY29tcGlsZShmcmFnU2hhZGVyU2NyaXB0OiBzdHJpbmcpOiBXZWJHTFByb2dyYW0ge1xuICAgIGlmICghdGhpcy52ZXJ0ZXhTaGFkZXIpIHtcbiAgICAgIExvZ2dlci52ZXJib3NlKCdQcm9yZ3JhbU1hbmFnZXInLCAnQ29tcGlsaW5nIGFuZCBjYWNoaW5nIFZlcnRleCBzaGFkZXIgZm9yIHRoZSBmaXJzdCB0aW1lJyk7XG4gICAgICBjb25zdCB2ZXJ0ZXhTaGFkZXJTY3JpcHQgPSBnZXRWZXJ0ZXhTaGFkZXJTb3VyY2UodGhpcy5nbENvbnRleHQudmVyc2lvbik7XG4gICAgICB0aGlzLnZlcnRleFNoYWRlciA9IHRoaXMuZ2xDb250ZXh0LmNvbXBpbGVTaGFkZXIodmVydGV4U2hhZGVyU2NyaXB0LCB0aGlzLmdsQ29udGV4dC5nbC5WRVJURVhfU0hBREVSKTtcbiAgICB9XG4gICAgaWYgKGVudi5kZWJ1Zykge1xuICAgICAgTG9nZ2VyLnZlcmJvc2UoJ1Byb3JncmFtTWFuYWdlcicsIGBGcmFnU2hhZGVyOlxuJHtmcmFnU2hhZGVyU2NyaXB0fVxuYCk7XG4gICAgfVxuICAgIGNvbnN0IGZyYWdTaGFkZXIgPSB0aGlzLmdsQ29udGV4dC5jb21waWxlU2hhZGVyKGZyYWdTaGFkZXJTY3JpcHQsIHRoaXMuZ2xDb250ZXh0LmdsLkZSQUdNRU5UX1NIQURFUik7XG4gICAgY29uc3QgcHJvZ3JhbSA9IHRoaXMuZ2xDb250ZXh0LmNyZWF0ZVByb2dyYW0odGhpcy52ZXJ0ZXhTaGFkZXIsIGZyYWdTaGFkZXIpO1xuICAgIHRoaXMuZ2xDb250ZXh0LmRlbGV0ZVNoYWRlcihmcmFnU2hhZGVyKTtcbiAgICByZXR1cm4gcHJvZ3JhbTtcbiAgfVxuICBiaW5kT3V0cHV0KHRkOiBUZXh0dXJlRGF0YSk6IHZvaWQge1xuICAgIGNvbnN0IHdpZHRoID0gdGQud2lkdGg7XG4gICAgY29uc3QgaGVpZ2h0ID0gdGQuaGVpZ2h0O1xuICAgIExvZ2dlci52ZXJib3NlKFxuICAgICAgICAnUHJvcmdyYW1NYW5hZ2VyJyxcbiAgICAgICAgYEJpbmRpbmcgb3V0cHV0IHRleHR1cmUgdG8gRnJhbWVidWZmZXI6IHcvaD0ke3dpZHRofS8ke2hlaWdodH0sIHNoYXBlPSR7dGQuc2hhcGV9LCB0eXBlPSR7dGQudGVuc29yLnR5cGV9YCk7XG4gICAgdGhpcy5nbENvbnRleHQuYXR0YWNoRnJhbWVidWZmZXIodGQudGV4dHVyZSwgd2lkdGgsIGhlaWdodCk7XG4gIH1cbiAgYmluZEF0dHJpYnV0ZXMoYXR0cmliTG9jYXRpb25zOiBBcnRpZmFjdC5BdHRyaWJMb2NhdGlvbnMpOiB2b2lkIHtcbiAgICBjb25zdCBwb3NpdGlvbkhhbmRsZSA9IGF0dHJpYkxvY2F0aW9ucy5wb3NpdGlvbjtcbiAgICBjb25zdCB0ZXh0dXJlQ29vcmRIYW5kbGUgPSBhdHRyaWJMb2NhdGlvbnMudGV4dHVyZUNvb3JkO1xuICAgIHRoaXMuZ2xDb250ZXh0LnNldFZlcnRleEF0dHJpYnV0ZXMocG9zaXRpb25IYW5kbGUsIHRleHR1cmVDb29yZEhhbmRsZSk7XG4gICAgdGhpcy5hdHRyaWJ1dGVzQm91bmQgPSB0cnVlO1xuICB9XG4gIGJpbmRVbmlmb3Jtcyh1bmlmb3JtTG9jYXRpb25zOiBBcnRpZmFjdC5Vbmlmb3JtTG9jYXRpb25zLCB2YXJpYWJsZXM6IFByb2dyYW1WYXJpYWJsZVtdLCB0ZXh0dXJlczogVGV4dHVyZURhdGFbXSk6XG4gICAgICB2b2lkIHtcbiAgICBjb25zdCBnbCA9IHRoaXMuZ2xDb250ZXh0LmdsO1xuICAgIGxldCB0ZXh0dXJlUG9zaXRpb24gPSAwO1xuICAgIGZvciAoY29uc3Qge25hbWUsIHR5cGUsIGxvY2F0aW9uLCBhcnJheUxlbmd0aH0gb2YgdW5pZm9ybUxvY2F0aW9ucykge1xuICAgICAgY29uc3QgdmFsdWUgPSB2YXJpYWJsZXMuZmluZCh2ID0+IHYubmFtZSA9PT0gbmFtZSk/LmRhdGE7XG4gICAgICBpZiAodHlwZSAhPT0gJ3NhbXBsZXIyRCcgJiYgIXZhbHVlKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgdmFyaWFibGUgJyR7bmFtZX0nIGRvZXMgbm90IGhhdmUgZGF0YSBkZWZpbmVkIGluIHByb2dyYW0gaW5mb2ApO1xuICAgICAgfVxuICAgICAgc3dpdGNoICh0eXBlKSB7XG4gICAgICAgIGNhc2UgJ3NhbXBsZXIyRCc6XG4gICAgICAgICAgdGhpcy5iaW5kVGV4dHVyZSh0ZXh0dXJlc1t0ZXh0dXJlUG9zaXRpb25dLCBsb2NhdGlvbiwgdGV4dHVyZVBvc2l0aW9uKTtcbiAgICAgICAgICB0ZXh0dXJlUG9zaXRpb24rKztcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSAnZmxvYXQnOlxuICAgICAgICAgIGlmIChhcnJheUxlbmd0aCkge1xuICAgICAgICAgICAgZ2wudW5pZm9ybTFmdihsb2NhdGlvbiwgdmFsdWUgYXMgbnVtYmVyW10pO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBnbC51bmlmb3JtMWYobG9jYXRpb24sIHZhbHVlIGFzIG51bWJlcik7XG4gICAgICAgICAgfVxuICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlICdpbnQnOlxuICAgICAgICAgIGlmIChhcnJheUxlbmd0aCkge1xuICAgICAgICAgICAgZ2wudW5pZm9ybTFpdihsb2NhdGlvbiwgdmFsdWUgYXMgbnVtYmVyW10pO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBnbC51bmlmb3JtMWkobG9jYXRpb24sIHZhbHVlIGFzIG51bWJlcik7XG4gICAgICAgICAgfVxuICAgICAgICAgIGJyZWFrO1xuICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgVW5pZm9ybSBub3QgaW1wbGVtZW50ZWQ6ICR7dHlwZX1gKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cbiAgYmluZFRleHR1cmUodGQ6IFRleHR1cmVEYXRhLCB1bmlmb3JtSGFuZGxlOiBXZWJHTFVuaWZvcm1Mb2NhdGlvbiwgcG9zaXRpb246IG51bWJlcik6IHZvaWQge1xuICAgIHRoaXMuZ2xDb250ZXh0LmJpbmRUZXh0dXJlVG9Vbmlmb3JtKHRkLnRleHR1cmUsIHBvc2l0aW9uLCB1bmlmb3JtSGFuZGxlKTtcbiAgfVxuICBnZXRBdHRyaWJMb2NhdGlvbnMocHJvZ3JhbTogV2ViR0xQcm9ncmFtKTogQXJ0aWZhY3QuQXR0cmliTG9jYXRpb25zIHtcbiAgICByZXR1cm4ge1xuICAgICAgcG9zaXRpb246IHRoaXMuZ2V0QXR0cmliTG9jYXRpb24ocHJvZ3JhbSwgJ3Bvc2l0aW9uJyksXG4gICAgICB0ZXh0dXJlQ29vcmQ6IHRoaXMuZ2V0QXR0cmliTG9jYXRpb24ocHJvZ3JhbSwgJ3RleHR1cmVDb29yZCcpXG4gICAgfTtcbiAgfVxuICBnZXRVbmlmb3JtTG9jYXRpb25zKHByb2dyYW06IFdlYkdMUHJvZ3JhbSwgc2FtcGxlcnM/OiBzdHJpbmdbXSwgdmFyaWFibGVzPzogVmFyaWFibGVJbmZvW10pOlxuICAgICAgQXJ0aWZhY3QuVW5pZm9ybUxvY2F0aW9ucyB7XG4gICAgY29uc3QgdW5pZm9ybUxvY2F0aW9uczogQXJ0aWZhY3QuVW5pZm9ybUxvY2F0aW9ucyA9IFtdO1xuICAgIGlmIChzYW1wbGVycykge1xuICAgICAgZm9yIChjb25zdCBzYW1wbGVyIG9mIHNhbXBsZXJzKSB7XG4gICAgICAgIHVuaWZvcm1Mb2NhdGlvbnMucHVzaCh7bmFtZTogc2FtcGxlciwgdHlwZTogJ3NhbXBsZXIyRCcsIGxvY2F0aW9uOiB0aGlzLmdldFVuaWZvcm1Mb2NhdGlvbihwcm9ncmFtLCBzYW1wbGVyKX0pO1xuICAgICAgfVxuICAgIH1cbiAgICBpZiAodmFyaWFibGVzKSB7XG4gICAgICBmb3IgKGNvbnN0IHZhcmlhYmxlIG9mIHZhcmlhYmxlcykge1xuICAgICAgICB1bmlmb3JtTG9jYXRpb25zLnB1c2goey4uLnZhcmlhYmxlLCBsb2NhdGlvbjogdGhpcy5nZXRVbmlmb3JtTG9jYXRpb24ocHJvZ3JhbSwgdmFyaWFibGUubmFtZSl9KTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHVuaWZvcm1Mb2NhdGlvbnM7XG4gIH1cbiAgZ2V0VW5pZm9ybUxvY2F0aW9uKHByb2dyYW06IFdlYkdMUHJvZ3JhbSwgbmFtZTogc3RyaW5nKTogV2ViR0xVbmlmb3JtTG9jYXRpb24ge1xuICAgIGNvbnN0IGdsID0gdGhpcy5nbENvbnRleHQuZ2w7XG4gICAgY29uc3QgcmVmZXJlbmNlID0gZ2wuZ2V0VW5pZm9ybUxvY2F0aW9uKHByb2dyYW0sIG5hbWUpO1xuICAgIGlmIChyZWZlcmVuY2UgPT09IG51bGwpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgVW5pZm9ybSAke25hbWV9IG5vdCBmb3VuZC5gKTtcbiAgICB9XG4gICAgcmV0dXJuIHJlZmVyZW5jZTtcbiAgfVxuICBnZXRBdHRyaWJMb2NhdGlvbihwcm9ncmFtOiBXZWJHTFByb2dyYW0sIG5hbWU6IHN0cmluZyk6IG51bWJlciB7XG4gICAgY29uc3QgZ2wgPSB0aGlzLmdsQ29udGV4dC5nbDtcbiAgICBjb25zdCBhdHRyaWJ1dGVMb2NhdGlvbjogbnVtYmVyID0gZ2wuZ2V0QXR0cmliTG9jYXRpb24ocHJvZ3JhbSwgbmFtZSk7XG4gICAgcmV0dXJuIGF0dHJpYnV0ZUxvY2F0aW9uO1xuICB9XG59XG4iLCIvLyBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cblxuaW1wb3J0IHtTZXNzaW9uSGFuZGxlcn0gZnJvbSAnLi4vLi4vYmFja2VuZCc7XG5pbXBvcnQge0dyYXBofSBmcm9tICcuLi8uLi9ncmFwaCc7XG5pbXBvcnQge0xvZ2dlcn0gZnJvbSAnLi4vLi4vaW5zdHJ1bWVudCc7XG5pbXBvcnQge09wZXJhdG9yfSBmcm9tICcuLi8uLi9vcGVyYXRvcnMnO1xuaW1wb3J0IHtPcFNldCwgcmVzb2x2ZU9wZXJhdG9yfSBmcm9tICcuLi8uLi9vcHNldCc7XG5pbXBvcnQge1Nlc3Npb259IGZyb20gJy4uLy4uL3Nlc3Npb24nO1xuaW1wb3J0IHtUZW5zb3J9IGZyb20gJy4uLy4uL3RlbnNvcic7XG5pbXBvcnQge1dlYkdMQmFja2VuZH0gZnJvbSAnLi4vYmFja2VuZC13ZWJnbCc7XG5cbmltcG9ydCB7V2ViR0xJbmZlcmVuY2VIYW5kbGVyfSBmcm9tICcuL2luZmVyZW5jZS1oYW5kbGVyJztcbmltcG9ydCB7V0VCR0xfT1BfUkVTT0xWRV9SVUxFU30gZnJvbSAnLi9vcC1yZXNvbHZlLXJ1bGVzJztcbmltcG9ydCB7UHJvZ3JhbU1hbmFnZXJ9IGZyb20gJy4vcHJvZ3JhbS1tYW5hZ2VyJztcbmltcG9ydCB7UHJlZmVyTG9naWNhbFN0cmF0ZWd5LCBUZXh0dXJlTGF5b3V0U3RyYXRlZ3l9IGZyb20gJy4vdGV4dHVyZS1sYXlvdXQtc3RyYXRlZ3knO1xuaW1wb3J0IHtUZXh0dXJlTWFuYWdlcn0gZnJvbSAnLi90ZXh0dXJlLW1hbmFnZXInO1xuaW1wb3J0IHtUZXh0dXJlRGF0YX0gZnJvbSAnLi90eXBlcyc7XG5cbmV4cG9ydCBjbGFzcyBXZWJHTFNlc3Npb25IYW5kbGVyIGltcGxlbWVudHMgU2Vzc2lvbkhhbmRsZXIge1xuICBwcm9ncmFtTWFuYWdlcjogUHJvZ3JhbU1hbmFnZXI7XG4gIHRleHR1cmVNYW5hZ2VyOiBUZXh0dXJlTWFuYWdlcjtcbiAgbGF5b3V0U3RyYXRlZ3k6IFRleHR1cmVMYXlvdXRTdHJhdGVneTtcbiAgcGFja2VkVGV4dHVyZURhdGFDYWNoZTogTWFwPFRlbnNvci5JZCwgVGV4dHVyZURhdGE+O1xuICB1bnBhY2tlZFRleHR1cmVEYXRhQ2FjaGU6IE1hcDxUZW5zb3IuSWQsIFRleHR1cmVEYXRhPjtcbiAgcGFjazJ1bnBhY2tNYXA6IE1hcDxUZW5zb3IuSWQsIFRlbnNvci5JZD47XG4gIHVucGFjazJwYWNrTWFwOiBNYXA8VGVuc29yLklkLCBUZW5zb3IuSWQ+O1xuICBpbml0aWFsaXplcnM6IFNldDxUZW5zb3IuSWQ+O1xuICBwYWNrPzogYm9vbGVhbjtcblxuICBjb25zdHJ1Y3RvcihwdWJsaWMgcmVhZG9ubHkgYmFja2VuZDogV2ViR0xCYWNrZW5kLCBwdWJsaWMgcmVhZG9ubHkgY29udGV4dDogU2Vzc2lvbi5Db250ZXh0KSB7XG4gICAgdGhpcy5sYXlvdXRTdHJhdGVneSA9IG5ldyBQcmVmZXJMb2dpY2FsU3RyYXRlZ3koYmFja2VuZC5nbENvbnRleHQubWF4VGV4dHVyZVNpemUpO1xuICAgIHRoaXMucHJvZ3JhbU1hbmFnZXIgPSBuZXcgUHJvZ3JhbU1hbmFnZXIodGhpcy5jb250ZXh0LnByb2ZpbGVyLCBiYWNrZW5kLmdsQ29udGV4dCwgdGhpcy5sYXlvdXRTdHJhdGVneSk7XG4gICAgdGhpcy50ZXh0dXJlTWFuYWdlciA9IG5ldyBUZXh0dXJlTWFuYWdlcihcbiAgICAgICAgYmFja2VuZC5nbENvbnRleHQsIHRoaXMubGF5b3V0U3RyYXRlZ3ksIHRoaXMuY29udGV4dC5wcm9maWxlcixcbiAgICAgICAge3JldXNlVGV4dHVyZXM6IGJhY2tlbmQudGV4dHVyZUNhY2hlTW9kZSA9PT0gJ2Z1bGwnfSk7XG4gICAgdGhpcy5wYWNrZWRUZXh0dXJlRGF0YUNhY2hlID0gbmV3IE1hcCgpO1xuICAgIHRoaXMudW5wYWNrZWRUZXh0dXJlRGF0YUNhY2hlID0gbmV3IE1hcCgpO1xuICAgIHRoaXMucGFjayA9IGJhY2tlbmQucGFjaztcbiAgICB0aGlzLnBhY2sydW5wYWNrTWFwID0gbmV3IE1hcCgpO1xuICAgIHRoaXMudW5wYWNrMnBhY2tNYXAgPSBuZXcgTWFwKCk7XG4gIH1cblxuICBjcmVhdGVJbmZlcmVuY2VIYW5kbGVyKCkge1xuICAgIHJldHVybiBuZXcgV2ViR0xJbmZlcmVuY2VIYW5kbGVyKHRoaXMpO1xuICB9XG4gIG9uR3JhcGhJbml0aWFsaXplZChncmFwaDogR3JhcGgpOiB2b2lkIHtcbiAgICBjb25zdCBpbml0aWFsaXplcnMgPSBncmFwaC5nZXRWYWx1ZXMoKS5maWx0ZXIodiA9PiB2LmZyb20gPT09IC0xICYmIHYudGVuc29yKS5tYXAodiA9PiB2LnRlbnNvciEuZGF0YUlkKTtcbiAgICB0aGlzLmluaXRpYWxpemVycyA9IG5ldyBTZXQoaW5pdGlhbGl6ZXJzKTtcbiAgfVxuICBpc0luaXRpYWxpemVyKHRlbnNvcklkOiBUZW5zb3IuSWQpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy5pbml0aWFsaXplcnMgPyB0aGlzLmluaXRpYWxpemVycy5oYXModGVuc29ySWQpIDogZmFsc2U7XG4gIH1cbiAgYWRkSW5pdGlhbGl6ZXIodGVuc29ySWQ6IFRlbnNvci5JZCk6IHZvaWQge1xuICAgIHRoaXMuaW5pdGlhbGl6ZXJzLmFkZCh0ZW5zb3JJZCk7XG4gIH1cbiAgZ2V0VGV4dHVyZURhdGEodGVuc29ySWQ6IFRlbnNvci5JZCwgaXNQYWNrZWQ6IGJvb2xlYW4pOiBUZXh0dXJlRGF0YXx1bmRlZmluZWQge1xuICAgIGlmIChpc1BhY2tlZCkge1xuICAgICAgcmV0dXJuIHRoaXMucGFja2VkVGV4dHVyZURhdGFDYWNoZS5nZXQodGVuc29ySWQpO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gdGhpcy51bnBhY2tlZFRleHR1cmVEYXRhQ2FjaGUuZ2V0KHRlbnNvcklkKTtcbiAgICB9XG4gIH1cbiAgc2V0VGV4dHVyZURhdGEodGVuc29ySWQ6IFRlbnNvci5JZCwgdGV4dHVyZURhdGE6IFRleHR1cmVEYXRhLCBpc1BhY2tlZCA9IGZhbHNlKTogdm9pZCB7XG4gICAgTG9nZ2VyLnZlcmJvc2UoJ1dlYkdMU2Vzc2lvbkhhbmRsZXInLCAnU3RvcmluZyBUZXh0dXJlIGRhdGEgaW4gY2FjaGUnKTtcbiAgICBpZiAoaXNQYWNrZWQpIHtcbiAgICAgIHRoaXMucGFja2VkVGV4dHVyZURhdGFDYWNoZS5zZXQodGVuc29ySWQsIHRleHR1cmVEYXRhKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy51bnBhY2tlZFRleHR1cmVEYXRhQ2FjaGUuc2V0KHRlbnNvcklkLCB0ZXh0dXJlRGF0YSk7XG4gICAgfVxuICB9XG4gIGRpc3Bvc2UoKTogdm9pZCB7XG4gICAgdGhpcy5wcm9ncmFtTWFuYWdlci5kaXNwb3NlKCk7XG4gICAgdGhpcy50ZXh0dXJlTWFuYWdlci5jbGVhckFjdGl2ZVRleHR1cmVzKCk7XG4gICAgdGhpcy5wYWNrZWRUZXh0dXJlRGF0YUNhY2hlLmZvckVhY2godGQgPT4gdGhpcy50ZXh0dXJlTWFuYWdlci5yZWxlYXNlVGV4dHVyZSh0ZCwgdHJ1ZSkpO1xuICAgIHRoaXMucGFja2VkVGV4dHVyZURhdGFDYWNoZSA9IG5ldyBNYXAoKTtcbiAgICB0aGlzLnVucGFja2VkVGV4dHVyZURhdGFDYWNoZS5mb3JFYWNoKHRkID0+IHRoaXMudGV4dHVyZU1hbmFnZXIucmVsZWFzZVRleHR1cmUodGQsIHRydWUpKTtcbiAgICB0aGlzLnVucGFja2VkVGV4dHVyZURhdGFDYWNoZSA9IG5ldyBNYXAoKTtcbiAgfVxuICByZXNvbHZlKG5vZGU6IEdyYXBoLk5vZGUsIG9wc2V0czogcmVhZG9ubHkgT3BTZXRbXSwgZ3JhcGg6IEdyYXBoKTogT3BlcmF0b3Ige1xuICAgIGNvbnN0IG9wID0gcmVzb2x2ZU9wZXJhdG9yKG5vZGUsIG9wc2V0cywgV0VCR0xfT1BfUkVTT0xWRV9SVUxFUyk7XG4gICAgcmV0dXJuIHtpbXBsOiBvcC5vcEltcGwsIGNvbnRleHQ6IG9wLm9wSW5pdCA/IG9wLm9wSW5pdChub2RlLCBncmFwaCkgOiBub2RlfTtcbiAgfVxufVxuIiwiLy8gQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXG5cbmltcG9ydCB7TG9nZ2VyfSBmcm9tICcuLi8uLi9pbnN0cnVtZW50JztcblxuZXhwb3J0IGRlY2xhcmUgbmFtZXNwYWNlIEVuY29kZXIge1xuICBleHBvcnQgaW50ZXJmYWNlIERhdGFUeXBlTWFwIHtcbiAgICBmbG9hdDogRmxvYXQzMkFycmF5O1xuICAgIGJ5dGU6IFVpbnQ4QXJyYXk7XG4gICAgaW50OiBVaW50MzJBcnJheTtcbiAgfVxuICBleHBvcnQgdHlwZSBEYXRhVHlwZSA9IGtleW9mIERhdGFUeXBlTWFwO1xuICB0eXBlIERhdGFBcnJheVR5cGUgPSBEYXRhVHlwZU1hcFtEYXRhVHlwZV07XG5cbiAgLyogZXNsaW50LWRpc2FibGUgQHR5cGVzY3JpcHQtZXNsaW50L25hbWluZy1jb252ZW50aW9uICovXG4gIGV4cG9ydCBjb25zdCBlbnVtIFVzYWdlIHtcbiAgICBEZWZhdWx0ID0gMCxcbiAgICBVcGxvYWRPbmx5LFxuICAgIERvd25sb2FkNEJ5dGVzQXNGbG9hdDMyLFxuICB9XG59XG5cbi8qKlxuICogQWJzdHJhY3Rpb24gZm9yIG1hcHBpbmcgZGF0YSB0eXBlcyB0byB0ZXh0dXJlIHRleGxldHNcbiAqIEVuY29kaW5nIG1lYW5zIGhvdyBhIEZsb2F0MzIgaXMgbWFwcGVkIHRvIDEgb3IgNCBjaGFubmVscyBmb3IgZWFjaCB0ZXhsZXRcbiAqIERlY29kaW5nIG1lYW5zIGhvdyBhIHRleGxldCdzIGNoYW5uZWxzIGFyZSBtYXBwZWQgdG8gYSByZXN1bHRpbmcgRmxvYXQzMlxuICovXG5leHBvcnQgaW50ZXJmYWNlIERhdGFFbmNvZGVyIHtcbiAgaW50ZXJuYWxGb3JtYXQ6IG51bWJlcjtcbiAgZm9ybWF0OiBudW1iZXI7XG4gIHRleHR1cmVUeXBlOiBudW1iZXI7XG4gIGNoYW5uZWxTaXplOiBudW1iZXI7XG4gIGVuY29kZShzcmM6IEVuY29kZXIuRGF0YUFycmF5VHlwZSwgdGV4dHVyZVNpemU6IG51bWJlcik6IEVuY29kZXIuRGF0YUFycmF5VHlwZTtcbiAgYWxsb2NhdGUoc2l6ZTogbnVtYmVyKTogRW5jb2Rlci5EYXRhQXJyYXlUeXBlO1xuICBkZWNvZGUoYnVmZmVyOiBFbmNvZGVyLkRhdGFBcnJheVR5cGUsIGRhdGFTaXplOiBudW1iZXIpOiBFbmNvZGVyLkRhdGFBcnJheVR5cGU7XG59XG4vKipcbiAqIFdlYkdMMiBkYXRhIGVuY29kZXJcbiAqIFVzZXMgUjMyRiBhcyB0aGUgZm9ybWF0IGZvciB0ZXhsZXRcbiAqL1xuZXhwb3J0IGNsYXNzIFJlZEZsb2F0MzJEYXRhRW5jb2RlciBpbXBsZW1lbnRzIERhdGFFbmNvZGVyIHtcbiAgaW50ZXJuYWxGb3JtYXQ6IG51bWJlcjtcbiAgZm9ybWF0OiBudW1iZXI7XG4gIHRleHR1cmVUeXBlOiBudW1iZXI7XG4gIGNoYW5uZWxTaXplOiBudW1iZXI7XG4gIGNvbnN0cnVjdG9yKGdsOiBXZWJHTDJSZW5kZXJpbmdDb250ZXh0LCBjaGFubmVscyA9IDEpIHtcbiAgICBpZiAoY2hhbm5lbHMgPT09IDEpIHtcbiAgICAgIHRoaXMuaW50ZXJuYWxGb3JtYXQgPSBnbC5SMzJGO1xuICAgICAgdGhpcy5mb3JtYXQgPSBnbC5SRUQ7XG4gICAgICB0aGlzLnRleHR1cmVUeXBlID0gZ2wuRkxPQVQ7XG4gICAgICB0aGlzLmNoYW5uZWxTaXplID0gY2hhbm5lbHM7XG4gICAgfSBlbHNlIGlmIChjaGFubmVscyA9PT0gNCkge1xuICAgICAgdGhpcy5pbnRlcm5hbEZvcm1hdCA9IGdsLlJHQkEzMkY7XG4gICAgICB0aGlzLmZvcm1hdCA9IGdsLlJHQkE7XG4gICAgICB0aGlzLnRleHR1cmVUeXBlID0gZ2wuRkxPQVQ7XG4gICAgICB0aGlzLmNoYW5uZWxTaXplID0gY2hhbm5lbHM7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgSW52YWxpZCBudW1iZXIgb2YgY2hhbm5lbHM6ICR7Y2hhbm5lbHN9YCk7XG4gICAgfVxuICB9XG4gIGVuY29kZShzcmM6IEVuY29kZXIuRGF0YUFycmF5VHlwZSwgdGV4dHVyZVNpemU6IG51bWJlcik6IEVuY29kZXIuRGF0YUFycmF5VHlwZSB7XG4gICAgbGV0IHJlc3VsdDogRmxvYXQzMkFycmF5O1xuICAgIGxldCBzb3VyY2U6IEZsb2F0MzJBcnJheTtcbiAgICBpZiAoc3JjLmNvbnN0cnVjdG9yICE9PSBGbG9hdDMyQXJyYXkpIHtcbiAgICAgIExvZ2dlci53YXJuaW5nKCdFbmNvZGVyJywgJ2RhdGEgd2FzIG5vdCBvZiB0eXBlIEZsb2F0MzI7IGNyZWF0aW5nIG5ldyBGbG9hdDMyQXJyYXknKTtcbiAgICAgIHNvdXJjZSA9IG5ldyBGbG9hdDMyQXJyYXkoc3JjKTtcbiAgICB9XG4gICAgaWYgKHRleHR1cmVTaXplICogdGhpcy5jaGFubmVsU2l6ZSA+IHNyYy5sZW5ndGgpIHtcbiAgICAgIExvZ2dlci53YXJuaW5nKCdFbmNvZGVyJywgJ1NvdXJjZSBkYXRhIHRvbyBzbWFsbC4gQWxsb2NhdGluZyBsYXJnZXIgYXJyYXknKTtcbiAgICAgIHNvdXJjZSA9IHNyYyBhcyBGbG9hdDMyQXJyYXk7XG4gICAgICByZXN1bHQgPSB0aGlzLmFsbG9jYXRlKHRleHR1cmVTaXplICogdGhpcy5jaGFubmVsU2l6ZSkgYXMgRmxvYXQzMkFycmF5O1xuICAgICAgc291cmNlLmZvckVhY2goKHYsIGkpID0+IHJlc3VsdFtpXSA9IHYpO1xuICAgIH0gZWxzZSB7XG4gICAgICBzb3VyY2UgPSBzcmMgYXMgRmxvYXQzMkFycmF5O1xuICAgICAgcmVzdWx0ID0gc291cmNlO1xuICAgIH1cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9XG4gIGFsbG9jYXRlKHNpemU6IG51bWJlcik6IEVuY29kZXIuRGF0YUFycmF5VHlwZSB7XG4gICAgcmV0dXJuIG5ldyBGbG9hdDMyQXJyYXkoc2l6ZSAqIDQpO1xuICB9XG4gIGRlY29kZShidWZmZXI6IEVuY29kZXIuRGF0YUFycmF5VHlwZSwgZGF0YVNpemU6IG51bWJlcik6IEZsb2F0MzJBcnJheSB7XG4gICAgaWYgKHRoaXMuY2hhbm5lbFNpemUgPT09IDEpIHtcbiAgICAgIGNvbnN0IGZpbHRlcmVkRGF0YSA9IChidWZmZXIgYXMgRmxvYXQzMkFycmF5KS5maWx0ZXIoKHZhbHVlLCBpbmRleCkgPT4gaW5kZXggJSA0ID09PSAwKS5zdWJhcnJheSgwLCBkYXRhU2l6ZSk7XG4gICAgICByZXR1cm4gZmlsdGVyZWREYXRhO1xuICAgIH1cbiAgICByZXR1cm4gYnVmZmVyLnN1YmFycmF5KDAsIGRhdGFTaXplKSBhcyBGbG9hdDMyQXJyYXk7XG4gIH1cbn1cbi8qKlxuICogRGF0YSBlbmNvZGVyIGZvciBXZWJHTCAxIHdpdGggc3VwcG9ydCBmb3IgZmxvYXRpbmcgcG9pbnQgdGV4dHVyZVxuICovXG5leHBvcnQgY2xhc3MgUkdCQUZsb2F0RGF0YUVuY29kZXIgaW1wbGVtZW50cyBEYXRhRW5jb2RlciB7XG4gIGludGVybmFsRm9ybWF0OiBudW1iZXI7XG4gIGZvcm1hdDogbnVtYmVyO1xuICB0ZXh0dXJlVHlwZTogbnVtYmVyO1xuICBjaGFubmVsU2l6ZTogbnVtYmVyO1xuICBjb25zdHJ1Y3RvcihnbDogV2ViR0xSZW5kZXJpbmdDb250ZXh0LCBjaGFubmVscyA9IDEsIHRleHR1cmVUeXBlPzogbnVtYmVyKSB7XG4gICAgaWYgKGNoYW5uZWxzICE9PSAxICYmIGNoYW5uZWxzICE9PSA0KSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYEludmFsaWQgbnVtYmVyIG9mIGNoYW5uZWxzOiAke2NoYW5uZWxzfWApO1xuICAgIH1cbiAgICB0aGlzLmludGVybmFsRm9ybWF0ID0gZ2wuUkdCQTtcbiAgICB0aGlzLmZvcm1hdCA9IGdsLlJHQkE7XG4gICAgdGhpcy5jaGFubmVsU2l6ZSA9IGNoYW5uZWxzO1xuICAgIHRoaXMudGV4dHVyZVR5cGUgPSB0ZXh0dXJlVHlwZSB8fCBnbC5GTE9BVDtcbiAgfVxuICBlbmNvZGUoc3JjOiBGbG9hdDMyQXJyYXksIHRleHR1cmVTaXplOiBudW1iZXIpOiBFbmNvZGVyLkRhdGFBcnJheVR5cGUge1xuICAgIGxldCBkZXN0ID0gc3JjO1xuICAgIGlmICh0aGlzLmNoYW5uZWxTaXplID09PSAxKSB7XG4gICAgICBMb2dnZXIudmVyYm9zZSgnRW5jb2RlcicsICdFeHBsb2RpbmcgaW50byBhIGxhcmdlciBhcnJheScpO1xuICAgICAgZGVzdCA9IHRoaXMuYWxsb2NhdGUodGV4dHVyZVNpemUpIGFzIEZsb2F0MzJBcnJheTtcbiAgICAgIHNyYy5mb3JFYWNoKCh2LCBpKSA9PiBkZXN0W2kgKiA0XSA9IHYpO1xuICAgIH1cbiAgICByZXR1cm4gZGVzdDtcbiAgfVxuICBhbGxvY2F0ZShzaXplOiBudW1iZXIpOiBFbmNvZGVyLkRhdGFBcnJheVR5cGUge1xuICAgIHJldHVybiBuZXcgRmxvYXQzMkFycmF5KHNpemUgKiA0KTtcbiAgfVxuICBkZWNvZGUoYnVmZmVyOiBFbmNvZGVyLkRhdGFBcnJheVR5cGUsIGRhdGFTaXplOiBudW1iZXIpOiBGbG9hdDMyQXJyYXkge1xuICAgIGlmICh0aGlzLmNoYW5uZWxTaXplID09PSAxKSB7XG4gICAgICBjb25zdCBmaWx0ZXJlZERhdGEgPSAoYnVmZmVyIGFzIEZsb2F0MzJBcnJheSkuZmlsdGVyKCh2YWx1ZSwgaW5kZXgpID0+IGluZGV4ICUgNCA9PT0gMCkuc3ViYXJyYXkoMCwgZGF0YVNpemUpO1xuICAgICAgcmV0dXJuIGZpbHRlcmVkRGF0YTtcbiAgICB9XG4gICAgcmV0dXJuIGJ1ZmZlci5zdWJhcnJheSgwLCBkYXRhU2l6ZSkgYXMgRmxvYXQzMkFycmF5O1xuICB9XG59XG5cbmV4cG9ydCBjbGFzcyBVaW50OERhdGFFbmNvZGVyIGltcGxlbWVudHMgRGF0YUVuY29kZXIge1xuICBpbnRlcm5hbEZvcm1hdDogbnVtYmVyO1xuICBmb3JtYXQ6IG51bWJlcjtcbiAgdGV4dHVyZVR5cGU6IG51bWJlcjtcbiAgY2hhbm5lbFNpemUgPSA0O1xuICBjb25zdHJ1Y3RvcihnbDogV2ViR0xSZW5kZXJpbmdDb250ZXh0LCBjaGFubmVscyA9IDEpIHtcbiAgICBpZiAoY2hhbm5lbHMgPT09IDEpIHtcbiAgICAgIHRoaXMuaW50ZXJuYWxGb3JtYXQgPSBnbC5BTFBIQTtcbiAgICAgIHRoaXMuZm9ybWF0ID0gZ2wuQUxQSEE7ICAvLyBub3QgdGVzdGVkXG4gICAgICB0aGlzLnRleHR1cmVUeXBlID0gZ2wuVU5TSUdORURfQllURTtcbiAgICAgIHRoaXMuY2hhbm5lbFNpemUgPSBjaGFubmVscztcbiAgICB9IGVsc2UgaWYgKGNoYW5uZWxzID09PSA0KSB7XG4gICAgICB0aGlzLmludGVybmFsRm9ybWF0ID0gZ2wuUkdCQTtcbiAgICAgIHRoaXMuZm9ybWF0ID0gZ2wuUkdCQTtcbiAgICAgIHRoaXMudGV4dHVyZVR5cGUgPSBnbC5VTlNJR05FRF9CWVRFO1xuICAgICAgdGhpcy5jaGFubmVsU2l6ZSA9IGNoYW5uZWxzO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYEludmFsaWQgbnVtYmVyIG9mIGNoYW5uZWxzOiAke2NoYW5uZWxzfWApO1xuICAgIH1cbiAgfVxuICBlbmNvZGUoc3JjOiBVaW50OEFycmF5LCBfdGV4dHVyZVNpemU6IG51bWJlcik6IEVuY29kZXIuRGF0YUFycmF5VHlwZSB7XG4gICAgcmV0dXJuIG5ldyBVaW50OEFycmF5KHNyYy5idWZmZXIsIHNyYy5ieXRlT2Zmc2V0LCBzcmMuYnl0ZUxlbmd0aCk7XG4gIH1cbiAgYWxsb2NhdGUoc2l6ZTogbnVtYmVyKTogRW5jb2Rlci5EYXRhQXJyYXlUeXBlIHtcbiAgICByZXR1cm4gbmV3IFVpbnQ4QXJyYXkoc2l6ZSAqIHRoaXMuY2hhbm5lbFNpemUpO1xuICB9XG4gIGRlY29kZShidWZmZXI6IEVuY29kZXIuRGF0YUFycmF5VHlwZSwgZGF0YVNpemU6IG51bWJlcik6IFVpbnQ4QXJyYXkge1xuICAgIGlmIChidWZmZXIgaW5zdGFuY2VvZiBVaW50OEFycmF5KSB7XG4gICAgICByZXR1cm4gYnVmZmVyLnN1YmFycmF5KDAsIGRhdGFTaXplKTtcbiAgICB9XG4gICAgdGhyb3cgbmV3IEVycm9yKGBJbnZhbGlkIGFycmF5IHR5cGU6ICR7YnVmZmVyLmNvbnN0cnVjdG9yfWApO1xuICB9XG59XG4iLCIvLyBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cblxuaW1wb3J0IHtMb2dnZXJ9IGZyb20gJy4uLy4uL2luc3RydW1lbnQnO1xuaW1wb3J0IHthc3NlcnR9IGZyb20gJy4uLy4uL3V0aWwnO1xuXG4vKiogTGF5b3V0IHByZWZlcmVuY2VzICovXG5leHBvcnQgaW50ZXJmYWNlIFdpZHRoSGVpZ2h0UHJlZnMge1xuICBicmVha0F4aXM/OiBudW1iZXI7XG4gIGlzUGFja2VkPzogYm9vbGVhbjtcbiAgcmV2ZXJzZVdIPzogYm9vbGVhbjtcbn1cbi8qKlxuICogVGV4dHVyZUxheW91dFN0cmF0ZWd5IGlzIGFuIGFic3RyYWN0aW9uIGZvciBkaWZmZXJlbnQgcGxhbnNcbiAqIGZvciBtYXBwaW5nIG4tZGltZW5zaW9uYWwgYXJyYXlzIHRvIDJEIHRleHR1cmVzIChhbmQgYmFjaylcbiAqL1xuZXhwb3J0IGludGVyZmFjZSBUZXh0dXJlTGF5b3V0U3RyYXRlZ3kge1xuICBjb21wdXRlVGV4dHVyZVdIKHNoYXBlOiByZWFkb25seSBudW1iZXJbXSwgcHJlZnM/OiBXaWR0aEhlaWdodFByZWZzKTogW251bWJlciwgbnVtYmVyXTtcbn1cblxuLyoqXG4gKiBUaGlzIHN0cmF0ZWd5IHRyeSB0byBmaW5kIHRoZSBtaW5pbWFsIG1heChXLEgpIHRoYXQgZnVsZmlsbHMgKFcgKiBIID09IHRvdGFsU2l6ZSlcbiAqL1xuZXhwb3J0IGNsYXNzIEFsd2F5c0tlZXBPcmlnaW5hbFNpemVTdHJhdGVneSBpbXBsZW1lbnRzIFRleHR1cmVMYXlvdXRTdHJhdGVneSB7XG4gIGNvbnN0cnVjdG9yKHB1YmxpYyBtYXhUZXh0dXJlU2l6ZTogbnVtYmVyKSB7fVxuICBjb21wdXRlVGV4dHVyZVdIKHNoYXBlOiByZWFkb25seSBudW1iZXJbXSwgcHJlZnM/OiBXaWR0aEhlaWdodFByZWZzKTogW251bWJlciwgbnVtYmVyXSB7XG4gICAgLy8gc2NhbGFyIHRlbnNvclxuICAgIGlmIChzaGFwZS5sZW5ndGggPT09IDApIHtcbiAgICAgIHJldHVybiBbMSwgMV07XG4gICAgfVxuICAgIGNvbnN0IG1heFRleHR1cmVTaXplID0gdGhpcy5tYXhUZXh0dXJlU2l6ZTtcbiAgICBpZiAocHJlZnMgJiYgcHJlZnMuYnJlYWtBeGlzICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIC8vIGNoZWNrIHRvIHNlZSBpZiBkaW1zIGZpdFxuICAgICAgY29uc3Qgd3NpemUgPSBwcmVmcy5icmVha0F4aXMgPj0gc2hhcGUubGVuZ3RoID8gMSA6IHNoYXBlLnNsaWNlKHByZWZzLmJyZWFrQXhpcykucmVkdWNlKChhLCBiKSA9PiBhICogYik7XG4gICAgICBjb25zdCBoc2l6ZSA9IHByZWZzLmJyZWFrQXhpcyA8PSAwID8gMSA6IHNoYXBlLnNsaWNlKDAsIHByZWZzLmJyZWFrQXhpcykucmVkdWNlKChhLCBiKSA9PiBhICogYik7XG4gICAgICBpZiAod3NpemUgPiBtYXhUZXh0dXJlU2l6ZSB8fCBoc2l6ZSA+IG1heFRleHR1cmVTaXplKSB7XG4gICAgICAgIC8vIGlnbm9yZSBwcmVmZXJlbmNlc1xuICAgICAgICAvLyBjb250aW51ZSB3aXRoIGRlZmF1bHQgbGF5b3V0XG4gICAgICAgIExvZ2dlci52ZXJib3NlKFxuICAgICAgICAgICAgJ1RleHR1cmVMYXlvdXQnLFxuICAgICAgICAgICAgYEdpdmVuIHdpZHRoL2hlaWdodCBwcmVmZXJlbmNlcyB3ZXJlIHVuYXR0YWluYWJsZTogc2hhcGU6JHtzaGFwZX0sIGJyZWFrQXhpczoke3ByZWZzLmJyZWFrQXhpc31gKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiBbd3NpemUsIGhzaXplXTtcbiAgICAgIH1cbiAgICB9XG4gICAgY29uc3QgdG90YWxTaXplID0gc2hhcGUucmVkdWNlKChhLCBiKSA9PiBhICogYik7XG5cbiAgICBsZXQgd2lkdGggPSBNYXRoLmZsb29yKE1hdGguc3FydCh0b3RhbFNpemUpKTtcblxuICAgIGZvciAoOyB3aWR0aCA8IG1heFRleHR1cmVTaXplICYmIHdpZHRoIDwgdG90YWxTaXplOyB3aWR0aCsrKSB7XG4gICAgICBpZiAodG90YWxTaXplICUgd2lkdGggPT09IDApIHtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKHdpZHRoID49IG1heFRleHR1cmVTaXplIHx8IHRvdGFsU2l6ZSAlIHdpZHRoICE9PSAwKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYFRoZSBnaXZlbiBkaW1lbnNpb25zIGFyZSBvdXRzaWRlIHRoaXMgR1BVJ3MgYm91bmRhcmllczogJHtzaGFwZX1gKTtcbiAgICB9XG4gICAgcmV0dXJuIFt3aWR0aCwgdG90YWxTaXplIC8gd2lkdGhdO1xuICB9XG59XG5cbmV4cG9ydCBjbGFzcyBQcmVmZXJMb2dpY2FsU3RyYXRlZ3kgaW1wbGVtZW50cyBUZXh0dXJlTGF5b3V0U3RyYXRlZ3kge1xuICBjb25zdHJ1Y3RvcihwdWJsaWMgbWF4VGV4dHVyZVNpemU6IG51bWJlcikge31cbiAgY29tcHV0ZVRleHR1cmVXSChzaGFwZTogcmVhZG9ubHkgbnVtYmVyW10sIHByZWZzPzogV2lkdGhIZWlnaHRQcmVmcyk6IFtudW1iZXIsIG51bWJlcl0ge1xuICAgIGNvbnN0IHdoID0gdGhpcy5jb21wdXRlVGV4dHVyZShzaGFwZSwgcHJlZnMpO1xuICAgIGlmIChwcmVmcyAmJiBwcmVmcy5pc1BhY2tlZCkge1xuICAgICAgd2hbMF0gLz0gMjtcbiAgICAgIHdoWzFdIC89IDI7XG4gICAgfVxuICAgIGlmIChwcmVmcyAmJiBwcmVmcy5yZXZlcnNlV0gpIHtcbiAgICAgIHJldHVybiBbd2hbMV0sIHdoWzBdXTtcbiAgICB9XG4gICAgcmV0dXJuIHdoO1xuICB9XG5cbiAgY29tcHV0ZVRleHR1cmUoc2hhcGU6IHJlYWRvbmx5IG51bWJlcltdLCBwcmVmcz86IFdpZHRoSGVpZ2h0UHJlZnMpOiBbbnVtYmVyLCBudW1iZXJdIHtcbiAgICBjb25zdCBpc1BhY2tlZCA9IHByZWZzICYmIHByZWZzLmlzUGFja2VkO1xuICAgIC8vIHNjYWxhciB0ZW5zb3JcbiAgICBpZiAoc2hhcGUubGVuZ3RoID09PSAwKSB7XG4gICAgICByZXR1cm4gaXNQYWNrZWQgPyBbMiwgMl0gOiBbMSwgMV07XG4gICAgfVxuICAgIGxldCBtYXhUZXh0dXJlU2l6ZSA9IHRoaXMubWF4VGV4dHVyZVNpemU7XG4gICAgaWYgKHByZWZzICYmIHByZWZzLmJyZWFrQXhpcyAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAvLyBjaGVjayB0byBzZWUgaWYgZGltcyBmaXRcbiAgICAgIGNvbnN0IHdzaXplID0gcHJlZnMuYnJlYWtBeGlzID49IHNoYXBlLmxlbmd0aCA/IDEgOiBzaGFwZS5zbGljZShwcmVmcy5icmVha0F4aXMpLnJlZHVjZSgoYSwgYikgPT4gYSAqIGIpO1xuICAgICAgY29uc3QgaHNpemUgPSBwcmVmcy5icmVha0F4aXMgPD0gMCA/IDEgOiBzaGFwZS5zbGljZSgwLCBwcmVmcy5icmVha0F4aXMpLnJlZHVjZSgoYSwgYikgPT4gYSAqIGIpO1xuICAgICAgaWYgKHdzaXplID4gbWF4VGV4dHVyZVNpemUgfHwgaHNpemUgPiBtYXhUZXh0dXJlU2l6ZSkge1xuICAgICAgICAvLyBpZ25vcmUgcHJlZmVyZW5jZXNcbiAgICAgICAgLy8gY29udGludWUgd2l0aCBkZWZhdWx0IGxheW91dFxuICAgICAgICBMb2dnZXIudmVyYm9zZShcbiAgICAgICAgICAgICdUZXh0dXJlTGF5b3V0JyxcbiAgICAgICAgICAgIGBHaXZlbiB3aWR0aC9oZWlnaHQgcHJlZmVyZW5jZXMgd2VyZSB1bmF0dGFpbmFibGU6IHNoYXBlOiR7c2hhcGV9LCBicmVha0F4aXM6JHtwcmVmcy5icmVha0F4aXN9YCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4gW3dzaXplLCBoc2l6ZV07XG4gICAgICB9XG4gICAgfVxuICAgIGxldCBsb2dTaGFwZSA9IHNoYXBlLnNsaWNlKDApO1xuICAgIGlmIChpc1BhY2tlZCkge1xuICAgICAgbWF4VGV4dHVyZVNpemUgPSBtYXhUZXh0dXJlU2l6ZSAqIDI7XG5cbiAgICAgIC8vIFRoaXMgbG9naWMgZW5zdXJlcyB3ZSBhY2N1cmF0ZWx5IGNvdW50IHRoZSBudW1iZXIgb2YgcGFja2VkIHRleGVscyBuZWVkZWRcbiAgICAgIC8vIHRvIGFjY29tbW9kYXRlIHRoZSB0ZW5zb3IuIFdlIGNhbiBvbmx5IHBhY2sgdmFsdWVzIGluIHRoZSBzYW1lIHRleGVsIGlmXG4gICAgICAvLyB0aGV5IGFyZSBmcm9tIGFkamFjZW50IHBhaXJzIG9mIHJvd3MvY29scyB3aXRoaW4gdGhlIHNhbWUgYmF0Y2guIFNvIGlmIGFcbiAgICAgIC8vIHRlbnNvciBoYXMgMyByb3dzLCB3ZSBwcmV0ZW5kIGl0IGhhcyA0IHJvd3MgaW4gb3JkZXIgdG8gYWNjb3VudCBmb3IgdGhlXG4gICAgICAvLyBmYWN0IHRoYXQgdGhlIHRleGVscyBjb250YWluaW5nIHRoZSB0aGlyZCByb3cgYXJlIGhhbGYgZW1wdHkuXG4gICAgICBsb2dTaGFwZSA9IGxvZ1NoYXBlLm1hcChcbiAgICAgICAgICAoZCwgaSkgPT4gaSA+PSBsb2dTaGFwZS5sZW5ndGggLSAyID8gKGxvZ1NoYXBlW2ldICUgMiA9PT0gMCA/IGxvZ1NoYXBlW2ldIDogbG9nU2hhcGVbaV0gKyAxKSA6IGxvZ1NoYXBlW2ldKTtcblxuICAgICAgLy8gUGFja2VkIHRleHR1cmUgaGVpZ2h0IGlzIGF0IGxlYXN0IDIgKHRoZSBjaGFubmVsIGhlaWdodCBvZiBhIHNpbmdsZVxuICAgICAgLy8gdGV4ZWwpLlxuICAgICAgaWYgKGxvZ1NoYXBlLmxlbmd0aCA9PT0gMSkge1xuICAgICAgICBsb2dTaGFwZSA9IFsyLCBsb2dTaGFwZVswXV07XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gSWYgbG9naWNhbCBzaGFwZSBpcyAyLCB3ZSBkb24ndCBzcXVlZXplLCBzaW5jZSB3ZSB3YW50IHRvIG1hdGNoIHBoeXNpY2FsLlxuICAgIGlmIChsb2dTaGFwZS5sZW5ndGggIT09IDIpIHtcbiAgICAgIGNvbnN0IHNxdWVlemVSZXN1bHQgPSBzcXVlZXplU2hhcGUobG9nU2hhcGUpO1xuICAgICAgbG9nU2hhcGUgPSBzcXVlZXplUmVzdWx0Lm5ld1NoYXBlO1xuICAgIH1cblxuICAgIGNvbnN0IHNpemUgPSBzaXplRnJvbVNoYXBlKGxvZ1NoYXBlKTtcbiAgICBpZiAobG9nU2hhcGUubGVuZ3RoIDw9IDEgJiYgc2l6ZSA8PSBtYXhUZXh0dXJlU2l6ZSkge1xuICAgICAgcmV0dXJuIFsxLCBzaXplXTtcbiAgICB9IGVsc2UgaWYgKGxvZ1NoYXBlLmxlbmd0aCA9PT0gMiAmJiBsb2dTaGFwZVswXSA8PSBtYXhUZXh0dXJlU2l6ZSAmJiBsb2dTaGFwZVsxXSA8PSBtYXhUZXh0dXJlU2l6ZSkge1xuICAgICAgcmV0dXJuIGxvZ1NoYXBlIGFzIFtudW1iZXIsIG51bWJlcl07XG4gICAgfSBlbHNlIGlmIChsb2dTaGFwZS5sZW5ndGggPT09IDMgJiYgbG9nU2hhcGVbMF0gKiBsb2dTaGFwZVsxXSA8PSBtYXhUZXh0dXJlU2l6ZSAmJiBsb2dTaGFwZVsyXSA8PSBtYXhUZXh0dXJlU2l6ZSkge1xuICAgICAgcmV0dXJuIFtsb2dTaGFwZVswXSAqIGxvZ1NoYXBlWzFdLCBsb2dTaGFwZVsyXV07XG4gICAgfSBlbHNlIGlmIChsb2dTaGFwZS5sZW5ndGggPT09IDMgJiYgbG9nU2hhcGVbMF0gPD0gbWF4VGV4dHVyZVNpemUgJiYgbG9nU2hhcGVbMV0gKiBsb2dTaGFwZVsyXSA8PSBtYXhUZXh0dXJlU2l6ZSkge1xuICAgICAgcmV0dXJuIFtsb2dTaGFwZVswXSwgbG9nU2hhcGVbMV0gKiBsb2dTaGFwZVsyXV07XG4gICAgfSBlbHNlIGlmIChcbiAgICAgICAgbG9nU2hhcGUubGVuZ3RoID09PSA0ICYmIGxvZ1NoYXBlWzBdICogbG9nU2hhcGVbMV0gKiBsb2dTaGFwZVsyXSA8PSBtYXhUZXh0dXJlU2l6ZSAmJlxuICAgICAgICBsb2dTaGFwZVszXSA8PSBtYXhUZXh0dXJlU2l6ZSkge1xuICAgICAgcmV0dXJuIFtsb2dTaGFwZVswXSAqIGxvZ1NoYXBlWzFdICogbG9nU2hhcGVbMl0sIGxvZ1NoYXBlWzNdXTtcbiAgICB9IGVsc2UgaWYgKFxuICAgICAgICBsb2dTaGFwZS5sZW5ndGggPT09IDQgJiYgbG9nU2hhcGVbMF0gPD0gbWF4VGV4dHVyZVNpemUgJiZcbiAgICAgICAgbG9nU2hhcGVbMV0gKiBsb2dTaGFwZVsyXSAqIGxvZ1NoYXBlWzNdIDw9IG1heFRleHR1cmVTaXplKSB7XG4gICAgICByZXR1cm4gW2xvZ1NoYXBlWzBdLCBsb2dTaGFwZVsxXSAqIGxvZ1NoYXBlWzJdICogbG9nU2hhcGVbM11dO1xuICAgIH0gZWxzZSB7XG4gICAgICBpZiAoaXNQYWNrZWQpIHtcbiAgICAgICAgLy8gRm9yIHBhY2tlZCB0ZXh0dXJlcyBzaXplIGVxdWFscyB0aGUgbnVtYmVyIG9mIGNoYW5uZWxzIHJlcXVpcmVkIHRvXG4gICAgICAgIC8vIGFjY29tbW9kYXRlIHRoZSB0ZXh0dXJlIGRhdGEuIEhvd2V2ZXIgaW4gb3JkZXIgdG8gc3F1YXJpZnkgc3VjaCB0aGF0XG4gICAgICAgIC8vIGlubmVyIGRpbWVuc2lvbnMgc3RheSBldmVuLCB3ZSByZXdyaXRlIHNpemUgdG8gZXF1YWwgdGhlIG51bWJlciBvZlxuICAgICAgICAvLyB0ZXhlbHMuIFRoZW4gaW4gdGhlIHJldHVybiBzdGF0ZW1lbnQgd2UgcmVoeWRyYXRlIHRoZSBzcXVhcmlmaWVkXG4gICAgICAgIC8vIGRpbWVuc2lvbnMgdG8gY2hhbm5lbCB1bml0cy5cbiAgICAgICAgcmV0dXJuIHNpemVUb1NxdWFyaXNoU2hhcGUoc2l6ZSAvIDQpLm1hcChkID0+IGQgKiAyKSBhcyBbbnVtYmVyLCBudW1iZXJdO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHNpemVUb1NxdWFyaXNoU2hhcGUoc2l6ZSk7XG4gICAgfVxuICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBzcXVlZXplU2hhcGUoc2hhcGU6IG51bWJlcltdLCBheGlzPzogbnVtYmVyW10pOiB7bmV3U2hhcGU6IG51bWJlcltdOyBrZXB0RGltczogbnVtYmVyW119IHtcbiAgY29uc3QgbmV3U2hhcGU6IG51bWJlcltdID0gW107XG4gIGNvbnN0IGtlcHREaW1zOiBudW1iZXJbXSA9IFtdO1xuICBjb25zdCBpc0VtcHR5QXJyYXkgPSBheGlzICE9IG51bGwgJiYgQXJyYXkuaXNBcnJheShheGlzKSAmJiBheGlzLmxlbmd0aCA9PT0gMDtcbiAgY29uc3QgYXhlcyA9IChheGlzID09IG51bGwgfHwgaXNFbXB0eUFycmF5KSA/IG51bGwgOiBwYXJzZUF4aXNQYXJhbShheGlzLCBzaGFwZSkuc29ydCgpO1xuICBsZXQgaiA9IDA7XG4gIGZvciAobGV0IGkgPSAwOyBpIDwgc2hhcGUubGVuZ3RoOyArK2kpIHtcbiAgICBpZiAoYXhlcyAhPSBudWxsKSB7XG4gICAgICBpZiAoYXhlc1tqXSA9PT0gaSAmJiBzaGFwZVtpXSAhPT0gMSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYENhbid0IHNxdWVlemUgYXhpcyAke2l9IHNpbmNlIGl0cyBkaW0gJyR7c2hhcGVbaV19JyBpcyBub3QgMWApO1xuICAgICAgfVxuICAgICAgaWYgKChheGVzW2pdID09IG51bGwgfHwgYXhlc1tqXSA+IGkpICYmIHNoYXBlW2ldID09PSAxKSB7XG4gICAgICAgIG5ld1NoYXBlLnB1c2goc2hhcGVbaV0pO1xuICAgICAgICBrZXB0RGltcy5wdXNoKGkpO1xuICAgICAgfVxuICAgICAgaWYgKGF4ZXNbal0gPD0gaSkge1xuICAgICAgICBqKys7XG4gICAgICB9XG4gICAgfVxuICAgIGlmIChzaGFwZVtpXSAhPT0gMSkge1xuICAgICAgbmV3U2hhcGUucHVzaChzaGFwZVtpXSk7XG4gICAgICBrZXB0RGltcy5wdXNoKGkpO1xuICAgIH1cbiAgfVxuICByZXR1cm4ge25ld1NoYXBlLCBrZXB0RGltc307XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBwYXJzZUF4aXNQYXJhbShheGlzOiBudW1iZXJ8bnVtYmVyW10sIHNoYXBlOiBudW1iZXJbXSk6IG51bWJlcltdIHtcbiAgY29uc3QgcmFuayA9IHNoYXBlLmxlbmd0aDtcblxuICAvLyBOb3JtYWxpemUgaW5wdXRcbiAgYXhpcyA9IGF4aXMgPT0gbnVsbCA/IHNoYXBlLm1hcCgocywgaSkgPT4gaSkgOiAoW10gYXMgbnVtYmVyW10pLmNvbmNhdChheGlzKTtcblxuICAvLyBDaGVjayBmb3IgdmFsaWQgcmFuZ2VcbiAgYXNzZXJ0KFxuICAgICAgYXhpcy5ldmVyeShheCA9PiBheCA+PSAtcmFuayAmJiBheCA8IHJhbmspLFxuICAgICAgKCkgPT4gYEFsbCB2YWx1ZXMgaW4gYXhpcyBwYXJhbSBtdXN0IGJlIGluIHJhbmdlIFstJHtyYW5rfSwgJHtyYW5rfSkgYnV0IGAgK1xuICAgICAgICAgIGBnb3QgYXhpcyAke2F4aXN9YCk7XG5cbiAgLy8gQ2hlY2sgZm9yIG9ubHkgaW50ZWdlcnNcbiAgYXNzZXJ0KFxuICAgICAgYXhpcy5ldmVyeShpc0ludCksXG4gICAgICAoKSA9PiAnQWxsIHZhbHVlcyBpbiBheGlzIHBhcmFtIG11c3QgYmUgaW50ZWdlcnMgYnV0ICcgK1xuICAgICAgICAgIGBnb3QgYXhpcyAke2F4aXN9YCk7XG5cbiAgLy8gSGFuZGxlIG5lZ2F0aXZlIGF4aXMuXG4gIHJldHVybiBheGlzLm1hcChhID0+IGEgPCAwID8gcmFuayArIGEgOiBhKTtcbn1cbmV4cG9ydCBmdW5jdGlvbiBpc0ludChhOiBudW1iZXIpOiBib29sZWFuIHtcbiAgcmV0dXJuIGEgJSAxID09PSAwO1xufVxuZXhwb3J0IGZ1bmN0aW9uIHNpemVGcm9tU2hhcGUoc2hhcGU6IG51bWJlcltdKTogbnVtYmVyIHtcbiAgaWYgKHNoYXBlLmxlbmd0aCA9PT0gMCkge1xuICAgIC8vIFNjYWxhci5cbiAgICByZXR1cm4gMTtcbiAgfVxuICBsZXQgc2l6ZSA9IHNoYXBlWzBdO1xuICBmb3IgKGxldCBpID0gMTsgaSA8IHNoYXBlLmxlbmd0aDsgaSsrKSB7XG4gICAgc2l6ZSAqPSBzaGFwZVtpXTtcbiAgfVxuICByZXR1cm4gc2l6ZTtcbn1cbmV4cG9ydCBmdW5jdGlvbiBnZXRSb3dzQ29scyhzaGFwZTogbnVtYmVyW10pOiBbbnVtYmVyLCBudW1iZXJdIHtcbiAgaWYgKHNoYXBlLmxlbmd0aCA9PT0gMCkge1xuICAgIHRocm93IEVycm9yKCdDYW5ub3QgZ2V0IHJvd3MgYW5kIGNvbHVtbnMgb2YgYW4gZW1wdHkgc2hhcGUgYXJyYXkuJyk7XG4gIH1cblxuICByZXR1cm4gW3NoYXBlLmxlbmd0aCA+IDEgPyBzaGFwZVtzaGFwZS5sZW5ndGggLSAyXSA6IDEsIHNoYXBlW3NoYXBlLmxlbmd0aCAtIDFdXTtcbn1cbmV4cG9ydCBmdW5jdGlvbiBzaXplVG9TcXVhcmlzaFNoYXBlKHNpemU6IG51bWJlcik6IFtudW1iZXIsIG51bWJlcl0ge1xuICBjb25zdCB3aWR0aCA9IE1hdGguY2VpbChNYXRoLnNxcnQoc2l6ZSkpO1xuICByZXR1cm4gW3dpZHRoLCBNYXRoLmNlaWwoc2l6ZSAvIHdpZHRoKV07XG59XG5leHBvcnQgZnVuY3Rpb24gZ2V0QmF0Y2hEaW0oc2hhcGU6IG51bWJlcltdLCBkaW1zVG9Ta2lwID0gMik6IG51bWJlciB7XG4gIHJldHVybiBzaXplRnJvbVNoYXBlKHNoYXBlLnNsaWNlKDAsIHNoYXBlLmxlbmd0aCAtIGRpbXNUb1NraXApKTtcbn1cbiIsIi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxuXG5pbXBvcnQge1NoYXBlVXRpbH0gZnJvbSAnLi4vLi4vdXRpbCc7XG5cbmltcG9ydCB7VGV4dHVyZUxheW91dFN0cmF0ZWd5LCBXaWR0aEhlaWdodFByZWZzfSBmcm9tICcuL3RleHR1cmUtbGF5b3V0LXN0cmF0ZWd5JztcbmltcG9ydCB7VGV4dHVyZUxheW91dCwgVGV4dHVyZVR5cGV9IGZyb20gJy4vdHlwZXMnO1xuXG5leHBvcnQgY29uc3QgY3JlYXRlVGV4dHVyZUxheW91dEZyb21UZXh0dXJlVHlwZSA9XG4gICAgKHRleHR1cmVMYXlvdXRTdHJhdGVneTogVGV4dHVyZUxheW91dFN0cmF0ZWd5LCBzaGFwZTogcmVhZG9ubHkgbnVtYmVyW10sXG4gICAgIHRleHR1cmVUeXBlOiBUZXh0dXJlVHlwZSk6IFRleHR1cmVMYXlvdXQgPT4ge1xuICAgICAgY29uc3QgY2hhbm5lbCA9ICh0ZXh0dXJlVHlwZSA9PT0gVGV4dHVyZVR5cGUudW5wYWNrZWQgfHwgdGV4dHVyZVR5cGUgPT09IFRleHR1cmVUeXBlLnVucGFja2VkUmV2ZXJzZWQpID8gMSA6IDQ7XG4gICAgICBjb25zdCBpc1BhY2tlZCA9IHRleHR1cmVUeXBlID09PSBUZXh0dXJlVHlwZS5wYWNrZWQ7XG4gICAgICBjb25zdCByZXZlcnNlV0ggPSAodGV4dHVyZVR5cGUgPT09IFRleHR1cmVUeXBlLnVucGFja2VkUmV2ZXJzZWQgfHwgdGV4dHVyZVR5cGUgPT09IFRleHR1cmVUeXBlLnBhY2tlZCk7XG4gICAgICBjb25zdCBicmVha0F4aXMgPSB0ZXh0dXJlVHlwZSA9PT0gVGV4dHVyZVR5cGUucGFja2VkTGFzdERpbWVuc2lvbiA/IHNoYXBlLmxlbmd0aCAtIDEgOiB1bmRlZmluZWQ7XG4gICAgICBjb25zdCB1bnBhY2tlZFNoYXBlID0gdGV4dHVyZVR5cGUgPT09IFRleHR1cmVUeXBlLnBhY2tlZExhc3REaW1lbnNpb24gP1xuICAgICAgICAgIHNoYXBlLm1hcCgoZCwgaSkgPT4gaSA9PT0gc2hhcGUubGVuZ3RoIC0gMSA/IGQgKiA0IDogZCkgOlxuICAgICAgICAgIHVuZGVmaW5lZDtcbiAgICAgIHJldHVybiBjcmVhdGVUZXh0dXJlTGF5b3V0RnJvbVNoYXBlKFxuICAgICAgICAgIHRleHR1cmVMYXlvdXRTdHJhdGVneSwgc2hhcGUsIGNoYW5uZWwsIHVucGFja2VkU2hhcGUsIHtpc1BhY2tlZCwgcmV2ZXJzZVdILCBicmVha0F4aXN9KTtcbiAgICB9O1xuXG5leHBvcnQgY29uc3QgY2FsY3VsYXRlVGV4dHVyZVdpZHRoQW5kSGVpZ2h0ID1cbiAgICAodGV4dHVyZUxheW91dFN0cmF0ZWd5OiBUZXh0dXJlTGF5b3V0U3RyYXRlZ3ksIHNoYXBlOiByZWFkb25seSBudW1iZXJbXSwgdGV4dHVyZVR5cGU6IFRleHR1cmVUeXBlKTpcbiAgICAgICAgW251bWJlciwgbnVtYmVyXSA9PiB7XG4gICAgICAgICAgY29uc3QgbGF5b3V0ID0gY3JlYXRlVGV4dHVyZUxheW91dEZyb21UZXh0dXJlVHlwZSh0ZXh0dXJlTGF5b3V0U3RyYXRlZ3ksIHNoYXBlLCB0ZXh0dXJlVHlwZSk7XG4gICAgICAgICAgcmV0dXJuIFtsYXlvdXQud2lkdGgsIGxheW91dC5oZWlnaHRdO1xuICAgICAgICB9O1xuXG4vKipcbiAqIENyZWF0ZSBhIFRleHR1cmVMYXlvdXQgb2JqZWN0IGZyb20gc2hhcGUuXG4gKi9cbmV4cG9ydCBjb25zdCBjcmVhdGVUZXh0dXJlTGF5b3V0RnJvbVNoYXBlID1cbiAgICAodGV4dHVyZUxheW91dFN0cmF0ZWd5OiBUZXh0dXJlTGF5b3V0U3RyYXRlZ3ksIHNoYXBlOiByZWFkb25seSBudW1iZXJbXSwgY2hhbm5lbHM6IDF8NCA9IDEsXG4gICAgIHVucGFja2VkU2hhcGU/OiByZWFkb25seSBudW1iZXJbXSwgcHJlZnM/OiBXaWR0aEhlaWdodFByZWZzKTogVGV4dHVyZUxheW91dCA9PiB7XG4gICAgICBjb25zdCBpc1BhY2tlZCA9ICEhKHByZWZzICYmIHByZWZzLmlzUGFja2VkKTtcbiAgICAgIGNvbnN0IFt3aWR0aCwgaGVpZ2h0XSA9IHRleHR1cmVMYXlvdXRTdHJhdGVneS5jb21wdXRlVGV4dHVyZVdIKGlzUGFja2VkID8gdW5wYWNrZWRTaGFwZSB8fCBzaGFwZSA6IHNoYXBlLCBwcmVmcyk7XG4gICAgICBjb25zdCByYW5rID0gc2hhcGUubGVuZ3RoO1xuICAgICAgbGV0IGluZmVycmVkRGltcyA9IHNoYXBlLnNsaWNlKDApO1xuICAgICAgaWYgKHJhbmsgPT09IDApIHtcbiAgICAgICAgaW5mZXJyZWREaW1zID0gWzFdO1xuICAgICAgfVxuICAgICAgaWYgKGNoYW5uZWxzID09PSAxKSB7XG4gICAgICAgIC8vIHVucGFja2VkU2hhcGUgd2lsbCB0YWtlIGBzaGFwZWAgYW5kIG5vdCBgaW5mZXJyZWREaW1zYCBzbyBhcyB0byBjcmVhdGUgYSBzY2FsYXIgVGVuc29yIGlmIG5lZWQgYmVcbiAgICAgICAgdW5wYWNrZWRTaGFwZSA9IHNoYXBlO1xuICAgICAgfSBlbHNlIGlmIChpc1BhY2tlZCkge1xuICAgICAgICBpZiAoY2hhbm5lbHMgIT09IDQpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ2EgcGFja2VkIHRleHR1cmUgbXVzdCBiZSA0LWNoYW5uZWwnKTtcbiAgICAgICAgfVxuICAgICAgICB1bnBhY2tlZFNoYXBlID0gc2hhcGU7XG4gICAgICAgIGlmIChyYW5rID4gMCkge1xuICAgICAgICAgIGluZmVycmVkRGltc1tyYW5rIC0gMV0gPSBNYXRoLmNlaWwoaW5mZXJyZWREaW1zW3JhbmsgLSAxXSAvIDIpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChyYW5rID4gMSkge1xuICAgICAgICAgIGluZmVycmVkRGltc1tyYW5rIC0gMl0gPSBNYXRoLmNlaWwoaW5mZXJyZWREaW1zW3JhbmsgLSAyXSAvIDIpO1xuICAgICAgICB9XG4gICAgICB9IGVsc2UgaWYgKCF1bnBhY2tlZFNoYXBlKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignVW5wYWNrZWQgc2hhcGUgaXMgbmVlZGVkIHdoZW4gdXNpbmcgY2hhbm5lbHMgPiAxJyk7XG4gICAgICB9XG4gICAgICByZXR1cm4ge1xuICAgICAgICB3aWR0aCxcbiAgICAgICAgaGVpZ2h0LFxuICAgICAgICBjaGFubmVscyxcbiAgICAgICAgaXNQYWNrZWQsXG4gICAgICAgIHNoYXBlOiBpbmZlcnJlZERpbXMsXG4gICAgICAgIHN0cmlkZXM6IFNoYXBlVXRpbC5jb21wdXRlU3RyaWRlcyhpbmZlcnJlZERpbXMpLFxuICAgICAgICB1bnBhY2tlZFNoYXBlLFxuICAgICAgICByZXZlcnNlZFdIOiAocHJlZnMgJiYgcHJlZnMucmV2ZXJzZVdIKVxuICAgICAgfTtcbiAgICB9O1xuIiwiLy8gQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXG5cbmltcG9ydCB7TG9nZ2VyLCBQcm9maWxlcn0gZnJvbSAnLi4vLi4vaW5zdHJ1bWVudCc7XG5pbXBvcnQge1RlbnNvcn0gZnJvbSAnLi4vLi4vdGVuc29yJztcblxuaW1wb3J0IHtFbmNvZGVyfSBmcm9tICcuL3RleHR1cmUtZGF0YS1lbmNvZGVyJztcbmltcG9ydCB7VGV4dHVyZUxheW91dFN0cmF0ZWd5fSBmcm9tICcuL3RleHR1cmUtbGF5b3V0LXN0cmF0ZWd5JztcbmltcG9ydCB7VGV4dHVyZURhdGEsIFRleHR1cmVMYXlvdXR9IGZyb20gJy4vdHlwZXMnO1xuaW1wb3J0IHtXZWJHTENvbnRleHR9IGZyb20gJy4vd2ViZ2wtY29udGV4dCc7XG5cbmV4cG9ydCBpbnRlcmZhY2UgVGV4dHVyZU1hbmFnZXJDb25maWcge1xuICByZXVzZVRleHR1cmVzPzogYm9vbGVhbjtcbn1cblxuLyoqXG4gKiBUZXh0dXJlTWFuYWdlciBpcyB0aGUgbWFpbmx5IHJlc3BvbnNpYmxlIGZvciBjYWNoaW5nIFRleHR1cmVzXG4gKiBUZXh0dXJlcyBhcmUgY2FjaGVkIGluIDIgbGV2ZWxzOlxuICogICAxLiB0aGUgdGV4dXJlcyB3aGljaCBhcmUgYXNzb2NpYXRlZCB3aXRoIGEgZGF0YUlkIChmcm9tIFRlbnNvcilcbiAqICAgIENhY2hpbmcgdGhlc2UgaXMgY3J1Y2lhbCB0byBwZXJmb3JtYW5jZS4gVGhlc2UgYXJlIEluLXVzZSBUZXh0dXJlc1xuICogICAyLiB0ZXh0dXJlcyB3aGljaCBhcmUgbm90IGluIHVzZSBieSBhbnkgY3VycmVudCBQcm9ncmFtSW5mby9UZW5zb3JcbiAqICAgICBUaGVzZSBhcmUgY2FsbGVkIEZyZWUgVGV4dHVyZXNcbiAqIFRleHR1cmVNYW5hZ2VyIGlzIGFsc28gdXNlZCB0byBoZWxwIGNyZWF0aW5nIHRleHR1cmVzLiBGb3IgdGhpcyBpdFxuICogdXNlcyBXZWJHTENvbnRleHQgYW5kIFRleHR1cmVMYXlvdXRTdHJhdGVneVxuICovXG5leHBvcnQgY2xhc3MgVGV4dHVyZU1hbmFnZXIge1xuICBwcml2YXRlIHJlYWRvbmx5IGluVXNlVGV4dHVyZXM6IE1hcDxzdHJpbmcsIFdlYkdMVGV4dHVyZVtdPjtcbiAgcHJpdmF0ZSByZWFkb25seSBpZGxlVGV4dHVyZXM6IE1hcDxzdHJpbmcsIFdlYkdMVGV4dHVyZVtdPjtcbiAgcHJpdmF0ZSByZWFkb25seSB0ZXh0dXJlTG9va3VwOiBNYXA8V2ViR0xUZXh0dXJlLCBzdHJpbmc+O1xuICBwcml2YXRlIHJlYWRvbmx5IHBlbmRpbmdSZWFkOiBNYXA8VGVuc29yLklkLCBBcnJheTwoYXJyOiBUZW5zb3IuTnVtYmVyVHlwZSkgPT4gdm9pZD4+ID0gbmV3IE1hcCgpO1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgICAgcHVibGljIGdsQ29udGV4dDogV2ViR0xDb250ZXh0LCBwdWJsaWMgbGF5b3V0U3RyYXRlZ3k6IFRleHR1cmVMYXlvdXRTdHJhdGVneSwgcHVibGljIHByb2ZpbGVyOiBSZWFkb25seTxQcm9maWxlcj4sXG4gICAgICBwcml2YXRlIGNvbmZpZzogVGV4dHVyZU1hbmFnZXJDb25maWcpIHtcbiAgICBpZiAoY29uZmlnLnJldXNlVGV4dHVyZXMpIHtcbiAgICAgIHRoaXMuaW5Vc2VUZXh0dXJlcyA9IG5ldyBNYXAoKTtcbiAgICAgIHRoaXMuaWRsZVRleHR1cmVzID0gbmV3IE1hcCgpO1xuICAgICAgdGhpcy50ZXh0dXJlTG9va3VwID0gbmV3IE1hcCgpO1xuICAgIH1cbiAgfVxuICBjcmVhdGVUZXh0dXJlRnJvbUxheW91dChcbiAgICAgIGRhdGFUeXBlOiBUZW5zb3IuRGF0YVR5cGUsIGxheW91dDogVGV4dHVyZUxheW91dCwgZGF0YT86IFRlbnNvci5OdW1iZXJUeXBlLCB1c2FnZT86IEVuY29kZXIuVXNhZ2UpIHtcbiAgICBjb25zdCB0ZXh0dXJlRGF0YVR5cGUgPSB0aGlzLnRvRW5jb2RlclR5cGUoZGF0YVR5cGUpO1xuXG4gICAgY29uc3QgZW5jb2RlciA9IHRoaXMuZ2xDb250ZXh0LmdldEVuY29kZXIodGV4dHVyZURhdGFUeXBlLCBsYXlvdXQuY2hhbm5lbHMgfHwgMSwgdXNhZ2UpO1xuICAgIGlmIChsYXlvdXQuaXNQYWNrZWQgJiYgdXNhZ2UgPT09IEVuY29kZXIuVXNhZ2UuVXBsb2FkT25seSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdub3QgaW1wbGVtZW50ZWQnKTtcbiAgICB9XG4gICAgY29uc3Qgd2lkdGggPSBsYXlvdXQud2lkdGg7XG4gICAgY29uc3QgaGVpZ2h0ID0gbGF5b3V0LmhlaWdodDtcblxuICAgIGxldCBrZXk6IHN0cmluZ3x1bmRlZmluZWQ7XG4gICAgbGV0IGluVXNlVGV4dHVyZXM6IFdlYkdMVGV4dHVyZVtdfHVuZGVmaW5lZDtcbiAgICBpZiAodGhpcy5jb25maWcucmV1c2VUZXh0dXJlcykge1xuICAgICAga2V5ID0gYCR7d2lkdGh9eCR7aGVpZ2h0fV8ke2VuY29kZXIuZm9ybWF0fV8ke2VuY29kZXIuaW50ZXJuYWxGb3JtYXR9XyR7ZW5jb2Rlci50ZXh0dXJlVHlwZX1gO1xuICAgICAgaW5Vc2VUZXh0dXJlcyA9IHRoaXMuaW5Vc2VUZXh0dXJlcy5nZXQoa2V5KTtcbiAgICAgIGlmICghaW5Vc2VUZXh0dXJlcykge1xuICAgICAgICBpblVzZVRleHR1cmVzID0gW107XG4gICAgICAgIHRoaXMuaW5Vc2VUZXh0dXJlcy5zZXQoa2V5LCBpblVzZVRleHR1cmVzKTtcbiAgICAgIH1cblxuICAgICAgY29uc3QgaWRsZVRleHR1cmVzID0gdGhpcy5pZGxlVGV4dHVyZXMuZ2V0KGtleSk7XG4gICAgICBpZiAoaWRsZVRleHR1cmVzICYmIGlkbGVUZXh0dXJlcy5sZW5ndGggPiAwKSB7XG4gICAgICAgIGNvbnN0IHRleHR1cmUgPSBpZGxlVGV4dHVyZXMucG9wKCkhO1xuICAgICAgICBpblVzZVRleHR1cmVzLnB1c2godGV4dHVyZSk7XG4gICAgICAgIGlmICh1c2FnZSA9PT0gRW5jb2Rlci5Vc2FnZS5VcGxvYWRPbmx5KSB7XG4gICAgICAgICAgdGhpcy5nbENvbnRleHQudXBkYXRlVGV4dHVyZSh0ZXh0dXJlLCB3aWR0aCwgaGVpZ2h0LCBlbmNvZGVyLCB0aGlzLnRvVGV4dHVyZURhdGEoZGF0YVR5cGUsIGRhdGEpISk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRleHR1cmU7XG4gICAgICB9XG4gICAgfVxuXG4gICAgTG9nZ2VyLnZlcmJvc2UoJ1RleHR1cmVNYW5hZ2VyJywgYENyZWF0aW5nIG5ldyB0ZXh0dXJlIG9mIHNpemUgJHtsYXlvdXQud2lkdGh9eCR7bGF5b3V0LmhlaWdodH1gKTtcbiAgICBjb25zdCB0ZXh0dXJlID0gdGhpcy5nbENvbnRleHQuYWxsb2NhdGVUZXh0dXJlKHdpZHRoLCBoZWlnaHQsIGVuY29kZXIsIHRoaXMudG9UZXh0dXJlRGF0YShkYXRhVHlwZSwgZGF0YSkpO1xuXG4gICAgaWYgKHRoaXMuY29uZmlnLnJldXNlVGV4dHVyZXMpIHtcbiAgICAgIGluVXNlVGV4dHVyZXMhLnB1c2godGV4dHVyZSk7XG4gICAgICB0aGlzLnRleHR1cmVMb29rdXAuc2V0KHRleHR1cmUsIGtleSEpO1xuICAgIH1cbiAgICByZXR1cm4gdGV4dHVyZTtcbiAgfVxuICByZWFkVGV4dHVyZSh0ZDogVGV4dHVyZURhdGEsIGRhdGFUeXBlOiBUZW5zb3IuRGF0YVR5cGUsIGNoYW5uZWxzPzogbnVtYmVyKTogVGVuc29yLk51bWJlclR5cGUge1xuICAgIGlmICghY2hhbm5lbHMpIHtcbiAgICAgIGNoYW5uZWxzID0gMTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMucHJvZmlsZXIuZXZlbnQoJ2JhY2tlbmQnLCAnVGV4dHVyZU1hbmFnZXIucmVhZFRleHR1cmUnLCAoKSA9PiB7XG4gICAgICBjb25zdCBkYXRhU2l6ZSA9IHRkLnNoYXBlLnJlZHVjZSgoYSwgYikgPT4gYSAqIGIpICogY2hhbm5lbHMhO1xuICAgICAgY29uc3QgZGF0YSA9IHRoaXMuZ2xDb250ZXh0LnJlYWRUZXh0dXJlKFxuICAgICAgICAgIHRkLnRleHR1cmUsIHRkLndpZHRoLCB0ZC5oZWlnaHQsIGRhdGFTaXplLCB0aGlzLnRvRW5jb2RlclR5cGUoZGF0YVR5cGUpLCBjaGFubmVscyEpO1xuICAgICAgcmV0dXJuIHRoaXMudG9UZW5zb3JEYXRhKGRhdGFUeXBlLCBkYXRhKTtcbiAgICB9KTtcbiAgfVxuICBhc3luYyByZWFkVGV4dHVyZUFzeW5jKHRkOiBUZXh0dXJlRGF0YSwgZGF0YVR5cGU6IFRlbnNvci5EYXRhVHlwZSwgY2hhbm5lbHM/OiBudW1iZXIpOiBQcm9taXNlPFRlbnNvci5OdW1iZXJUeXBlPiB7XG4gICAgY29uc3QgZGF0YUlkID0gdGQudGVuc29yLmRhdGFJZDtcbiAgICBpZiAoIWNoYW5uZWxzKSB7XG4gICAgICBjaGFubmVscyA9IDE7XG4gICAgfVxuICAgIGlmICh0aGlzLnBlbmRpbmdSZWFkLmhhcyhkYXRhSWQpKSB7XG4gICAgICBjb25zdCBzdWJzY3JpYmVycyA9IHRoaXMucGVuZGluZ1JlYWQuZ2V0KGRhdGFJZCk7XG4gICAgICByZXR1cm4gbmV3IFByb21pc2U8VGVuc29yLk51bWJlclR5cGU+KHJlc29sdmUgPT4gc3Vic2NyaWJlcnM/LnB1c2gocmVzb2x2ZSkpO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy5wcm9maWxlci5ldmVudCgnYmFja2VuZCcsICdUZXh0dXJlTWFuYWdlci5yZWFkVGV4dHVyZUFzeW5jJywgYXN5bmMgKCkgPT4ge1xuICAgICAgdGhpcy5wZW5kaW5nUmVhZC5zZXQoZGF0YUlkLCBbXSk7XG4gICAgICBjb25zdCBkYXRhU2l6ZSA9IHRkLnNoYXBlLnJlZHVjZSgoYSwgYikgPT4gYSAqIGIpICogY2hhbm5lbHMhO1xuICAgICAgLy8gYWRkIGEgZmVuY2Ugd2FpdGluZyBmb3IgdGhlIGRhdGEgdG8gYmUgcmVhZHlcbiAgICAgIGF3YWl0IHRoaXMuZ2xDb250ZXh0LmNyZWF0ZUFuZFdhaXRGb3JGZW5jZSgpO1xuICAgICAgY29uc3QgZGF0YSA9IHRoaXMuZ2xDb250ZXh0LnJlYWRUZXh0dXJlKFxuICAgICAgICAgIHRkLnRleHR1cmUsIHRkLndpZHRoLCB0ZC5oZWlnaHQsIGRhdGFTaXplLCB0aGlzLnRvRW5jb2RlclR5cGUoZGF0YVR5cGUpLCBjaGFubmVscyEpO1xuICAgICAgY29uc3QgdGVuc29yRGF0YSA9IHRoaXMudG9UZW5zb3JEYXRhKGRhdGFUeXBlLCBkYXRhKTtcbiAgICAgIGNvbnN0IHN1YnNjcmliZXJzID0gdGhpcy5wZW5kaW5nUmVhZC5nZXQoZGF0YUlkKTtcbiAgICAgIHRoaXMucGVuZGluZ1JlYWQuZGVsZXRlKGRhdGFJZCk7XG4gICAgICBzdWJzY3JpYmVycz8uZm9yRWFjaChyZXNvbHZlID0+IHJlc29sdmUodGVuc29yRGF0YSkpO1xuICAgICAgcmV0dXJuIHRlbnNvckRhdGE7XG4gICAgfSk7XG4gIH1cbiAgcmVhZFVpbnQ4VGV4dHVyZUFzRmxvYXQodGQ6IFRleHR1cmVEYXRhKTogRmxvYXQzMkFycmF5IHtcbiAgICByZXR1cm4gdGhpcy5wcm9maWxlci5ldmVudCgnYmFja2VuZCcsICdUZXh0dXJlTWFuYWdlci5yZWFkVWludDhUZXh0dXJlQXNGbG9hdCcsICgpID0+IHtcbiAgICAgIGNvbnN0IGRhdGFTaXplID0gdGQuc2hhcGUucmVkdWNlKChhLCBiKSA9PiBhICogYik7XG4gICAgICBjb25zdCBkYXRhID0gdGhpcy5nbENvbnRleHQucmVhZFRleHR1cmUodGQudGV4dHVyZSwgdGQud2lkdGgsIHRkLmhlaWdodCwgZGF0YVNpemUgKiA0LCAnYnl0ZScsIDQpO1xuICAgICAgcmV0dXJuIG5ldyBGbG9hdDMyQXJyYXkoZGF0YS5idWZmZXIsIGRhdGEuYnl0ZU9mZnNldCwgZGF0YVNpemUpO1xuICAgIH0pO1xuICB9XG4gIHJlbGVhc2VUZXh0dXJlKHRleHR1cmVEYXRhOiBUZXh0dXJlRGF0YSwgZGVsZXRlVGV4dHVyZT86IGJvb2xlYW4pOiB2b2lkIHtcbiAgICBsZXQga2V5OiBzdHJpbmd8dW5kZWZpbmVkO1xuICAgIGlmICh0aGlzLmNvbmZpZy5yZXVzZVRleHR1cmVzKSB7XG4gICAgICBrZXkgPSB0aGlzLnRleHR1cmVMb29rdXAuZ2V0KHRleHR1cmVEYXRhLnRleHR1cmUpO1xuICAgICAgaWYgKGtleSkge1xuICAgICAgICBpZiAoZGVsZXRlVGV4dHVyZSkge1xuICAgICAgICAgIHRoaXMudGV4dHVyZUxvb2t1cC5kZWxldGUoa2V5KTtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBpblVzZVRleHR1cmVzID0gdGhpcy5pblVzZVRleHR1cmVzLmdldChrZXkpO1xuICAgICAgICBpZiAoaW5Vc2VUZXh0dXJlcykge1xuICAgICAgICAgIGNvbnN0IGluZGV4ID0gaW5Vc2VUZXh0dXJlcy5pbmRleE9mKHRleHR1cmVEYXRhLnRleHR1cmUpO1xuICAgICAgICAgIGlmIChpbmRleCAhPT0gLTEpIHtcbiAgICAgICAgICAgIGluVXNlVGV4dHVyZXMuc3BsaWNlKGluZGV4LCAxKTtcbiAgICAgICAgICAgIGxldCBpZGxlVGV4dHVyZXMgPSB0aGlzLmlkbGVUZXh0dXJlcy5nZXQoa2V5KTtcbiAgICAgICAgICAgIGlmICghaWRsZVRleHR1cmVzKSB7XG4gICAgICAgICAgICAgIGlkbGVUZXh0dXJlcyA9IFtdO1xuICAgICAgICAgICAgICB0aGlzLmlkbGVUZXh0dXJlcy5zZXQoa2V5LCBpZGxlVGV4dHVyZXMpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWRsZVRleHR1cmVzLnB1c2godGV4dHVyZURhdGEudGV4dHVyZSk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKCFrZXkgfHwgZGVsZXRlVGV4dHVyZSkge1xuICAgICAgTG9nZ2VyLnZlcmJvc2UoJ1RleHR1cmVNYW5hZ2VyJywgYERlbGV0aW5nIHRleHR1cmUgb2Ygc2l6ZSAke3RleHR1cmVEYXRhLndpZHRofXgke3RleHR1cmVEYXRhLmhlaWdodH1gKTtcbiAgICAgIHRoaXMuZ2xDb250ZXh0LmRlbGV0ZVRleHR1cmUodGV4dHVyZURhdGEudGV4dHVyZSk7XG4gICAgfVxuICB9XG4gIHRvVGVuc29yRGF0YShkYXRhVHlwZTogVGVuc29yLkRhdGFUeXBlLCBkYXRhOiBFbmNvZGVyLkRhdGFBcnJheVR5cGUpOiBUZW5zb3IuTnVtYmVyVHlwZSB7XG4gICAgc3dpdGNoIChkYXRhVHlwZSkge1xuICAgICAgY2FzZSAnaW50MTYnOlxuICAgICAgICByZXR1cm4gZGF0YSBpbnN0YW5jZW9mIEludDE2QXJyYXkgPyBkYXRhIDogSW50MTZBcnJheS5mcm9tKGRhdGEpO1xuICAgICAgY2FzZSAnaW50MzInOlxuICAgICAgICByZXR1cm4gZGF0YSBpbnN0YW5jZW9mIEludDMyQXJyYXkgPyBkYXRhIDogSW50MzJBcnJheS5mcm9tKGRhdGEpO1xuICAgICAgY2FzZSAnaW50OCc6XG4gICAgICAgIHJldHVybiBkYXRhIGluc3RhbmNlb2YgSW50OEFycmF5ID8gZGF0YSA6IEludDhBcnJheS5mcm9tKGRhdGEpO1xuICAgICAgY2FzZSAndWludDE2JzpcbiAgICAgICAgcmV0dXJuIGRhdGEgaW5zdGFuY2VvZiBVaW50MTZBcnJheSA/IGRhdGEgOiBVaW50MTZBcnJheS5mcm9tKGRhdGEpO1xuICAgICAgY2FzZSAndWludDMyJzpcbiAgICAgICAgcmV0dXJuIGRhdGEgaW5zdGFuY2VvZiBVaW50MzJBcnJheSA/IGRhdGEgOiBVaW50MzJBcnJheS5mcm9tKGRhdGEpO1xuICAgICAgY2FzZSAndWludDgnOlxuICAgICAgY2FzZSAnYm9vbCc6XG4gICAgICAgIHJldHVybiBkYXRhIGluc3RhbmNlb2YgVWludDhBcnJheSA/IGRhdGEgOiBVaW50OEFycmF5LmZyb20oZGF0YSk7XG4gICAgICBjYXNlICdmbG9hdDMyJzpcbiAgICAgICAgcmV0dXJuIGRhdGEgaW5zdGFuY2VvZiBGbG9hdDMyQXJyYXkgPyBkYXRhIDogRmxvYXQzMkFycmF5LmZyb20oZGF0YSk7XG4gICAgICBjYXNlICdmbG9hdDY0JzpcbiAgICAgICAgcmV0dXJuIGRhdGEgaW5zdGFuY2VvZiBGbG9hdDY0QXJyYXkgPyBkYXRhIDogRmxvYXQ2NEFycmF5LmZyb20oZGF0YSk7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYFRlbnNvckRhdGEgdHlwZSAke2RhdGFUeXBlfSBpcyBub3Qgc3VwcG9ydGVkYCk7XG4gICAgfVxuICB9XG4gIHRvVGV4dHVyZURhdGEoZGF0YVR5cGU6IFRlbnNvci5EYXRhVHlwZSwgZGF0YTogVGVuc29yLk51bWJlclR5cGV8dW5kZWZpbmVkKTogRW5jb2Rlci5EYXRhQXJyYXlUeXBlfHVuZGVmaW5lZCB7XG4gICAgaWYgKCFkYXRhKSB7XG4gICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgIH1cbiAgICByZXR1cm4gKGRhdGEgaW5zdGFuY2VvZiBGbG9hdDMyQXJyYXkpID8gZGF0YSA6IG5ldyBGbG9hdDMyQXJyYXkoZGF0YSk7XG4gICAgLypcbiAgICBzd2l0Y2ggKGRhdGFUeXBlKSB7XG4gICAgICBjYXNlICdpbnQxNic6XG4gICAgICBjYXNlICdpbnQzMic6XG4gICAgICBjYXNlICd1aW50MTYnOlxuICAgICAgY2FzZSAndWludDMyJzpcbiAgICAgICAgcmV0dXJuIChkYXRhLmNvbnN0cnVjdG9yID09PSBVaW50MzJBcnJheSkgPyBkYXRhIGFzIFVpbnQzMkFycmF5IDogbmV3IFVpbnQzMkFycmF5KGRhdGEpO1xuICAgICAgY2FzZSAnaW50OCc6XG4gICAgICBjYXNlICd1aW50OCc6XG4gICAgICBjYXNlICdib29sJzpcbiAgICAgICAgcmV0dXJuIChkYXRhLmNvbnN0cnVjdG9yID09PSBVaW50OEFycmF5KSA/IGRhdGEgYXMgVWludDhBcnJheSA6IG5ldyBVaW50OEFycmF5KGRhdGEpO1xuICAgICAgY2FzZSAnZmxvYXQzMic6XG4gICAgICBjYXNlICdmbG9hdDY0JzpcbiAgICAgICAgcmV0dXJuIChkYXRhLmNvbnN0cnVjdG9yID09PSBGbG9hdDMyQXJyYXkpID8gZGF0YSBhcyBGbG9hdDMyQXJyYXkgOiBuZXcgRmxvYXQzMkFycmF5KGRhdGEpO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBUZW5zb3JEYXRhIHR5cGUgJHtkYXRhVHlwZX0gaXMgbm90IHN1cHBvcnRlZGApO1xuICAgIH1cbiAgICAqL1xuICB9XG4gIHRvRW5jb2RlclR5cGUoX2RhdGFUeXBlOiBUZW5zb3IuRGF0YVR5cGUpOiBFbmNvZGVyLkRhdGFUeXBlIHtcbiAgICByZXR1cm4gJ2Zsb2F0JztcbiAgICAvLyBzd2l0Y2ggKGRhdGFUeXBlKSB7XG4gICAgLy8gICBjYXNlICdpbnQxNic6XG4gICAgLy8gICBjYXNlICdpbnQzMic6XG4gICAgLy8gICBjYXNlICd1aW50MTYnOlxuICAgIC8vICAgY2FzZSAndWludDMyJzpcbiAgICAvLyAgICAgcmV0dXJuICdpbnQnO1xuICAgIC8vICAgY2FzZSAndWludDgnOlxuICAgIC8vICAgY2FzZSAnYm9vbCc6XG4gICAgLy8gICAgIHJldHVybiAnYnl0ZSc7XG4gICAgLy8gICBjYXNlICdmbG9hdDMyJzpcbiAgICAvLyAgIGNhc2UgJ2Zsb2F0NjQnOlxuICAgIC8vICAgICByZXR1cm4gJ2Zsb2F0JztcbiAgICAvLyAgIGRlZmF1bHQ6XG4gICAgLy8gICAgIHRocm93IG5ldyBFcnJvcihgVGVuc29yRGF0YSB0eXBlICR7ZGF0YVR5cGV9IGlzIG5vdCBzdXBwb3J0ZWRgKTtcbiAgICAvLyB9XG4gIH1cbiAgY2xlYXJBY3RpdmVUZXh0dXJlcygpOiB2b2lkIHtcbiAgICB0aGlzLmdsQ29udGV4dC5jbGVhckFjdGl2ZVRleHR1cmVzKCk7XG4gIH1cbn1cbiIsIi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxuXG5pbXBvcnQge1RlbnNvcn0gZnJvbSAnLi4vLi4vdGVuc29yJztcblxuLyoqXG4gKiBMYXlvdXQgaW5mbyBpcyB1c2VkIGZvciBtYXBwaW5nIG4tZGltZW5zaW9uYWwgYXJyYXkgdG8gMkQgdGV4dHVyZXNcbiAqIFRoZSBsYXlvdXQgaXMgY3JlYXRlZCBieSB0aGUgVGV4dHVyZUxheW91dFN0cmF0ZWd5IGJhc2VkIG9uXG4gKiB0aGUgVGVuc29yJ3MgZGltZW5zaW9ucyBhbmQgc3RyaWRlc1xuICovXG5leHBvcnQgaW50ZXJmYWNlIFRleHR1cmVMYXlvdXQge1xuICB3aWR0aDogbnVtYmVyO1xuICBoZWlnaHQ6IG51bWJlcjtcbiAgLyoqXG4gICAqIHNwZWNpZnkgdGhlIG51bWJlciBvZiB2YWx1ZSB0aGF0IGVuY29kZWQgaW4gYSBzaW5nbGUgcGl4ZWxcbiAgICovXG4gIGNoYW5uZWxzOiAxfDJ8M3w0O1xuICAvKipcbiAgICogd2hldGhlciBpbiBwYWNrZWQgbW9kZSBvciBub3RcbiAgICovXG4gIGlzUGFja2VkPzogYm9vbGVhbjtcbiAgLyoqXG4gICAqIHRoZSBub3JtYWxpemVkIHNoYXBlXG4gICAqL1xuICBzaGFwZTogcmVhZG9ubHkgbnVtYmVyW107XG4gIC8qKlxuICAgKiB0aGUgc3RyaWRlIG9mIGVhY2ggZGltZW5zaW9ucywgY2FsY3VsYXRlZCBhY2NvcmRpbmcgdG8gc2hhcGVcbiAgICovXG4gIHN0cmlkZXM6IHJlYWRvbmx5IG51bWJlcltdO1xuICAvKipcbiAgICogdGhlIG9yaWdpbmFsIHNoYXBlKGRpbXMpIG9mIHRoZSBjb3JyZXNwb25kaW5nIHRlbnNvclxuICAgKi9cbiAgdW5wYWNrZWRTaGFwZTogcmVhZG9ubHkgbnVtYmVyW107XG5cbiAgcmV2ZXJzZWRXSD86IGJvb2xlYW47XG59XG5leHBvcnQgaW50ZXJmYWNlIFRleHR1cmVEYXRhIGV4dGVuZHMgVGV4dHVyZUxheW91dCB7XG4gIHRlbnNvcjogVGVuc29yO1xuICB0ZXh0dXJlOiBXZWJHTFRleHR1cmU7XG59XG5cbmV4cG9ydCBlbnVtIFRleHR1cmVUeXBlIHtcbiAgdW5wYWNrZWQsICAgICAgICAgICAgICAvLyA8LS0gbm9ybWFsIHVucGFja2VkIHRleHR1cmVcbiAgdW5wYWNrZWRSZXZlcnNlZCwgICAgICAvLyA8LS0gdW5wYWNrZWQgdGV4dHVyZSB1c2VkIGluIG9sZCBPTk5YLmpzIGltcGxlbWVudGF0aW9uIChkZXByZWNhdGVkKVxuICBwYWNrZWQsICAgICAgICAgICAgICAgIC8vIDwtLSBub3JtYWwgcGFja2VkIHRleHR1cmVcbiAgZG93bmxvYWRVaW50OEFzRmxvYXQsICAvLyA8LS0gT05MWSB1c2VkIGluIHRleHR1cmUgZG93bmxvYWRpbmcgZm9yIGlPUyBkZXZpY2VzXG4gIHBhY2tlZExhc3REaW1lbnNpb24gICAgLy8gPC0tIE9OTFkgdXNlZCBpbiBvbGQgT05OWC5qcyBDb252IGltcGxlbWVudGF0aW9uIGZvciBpbnB1dCBXIChkZXByZWNhdGVkKVxufVxuXG5leHBvcnQgaW50ZXJmYWNlIFRlbnNvckluZm8ge1xuICBpZD86IFRlbnNvci5JZDtcbiAgZGltczogcmVhZG9ubHkgbnVtYmVyW107XG4gIHR5cGU6IFRlbnNvci5EYXRhVHlwZTtcbiAgdGV4dHVyZVR5cGU6IFRleHR1cmVUeXBlO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFByb2dyYW1WYXJpYWJsZSB7XG4gIHR5cGU6ICdmbG9hdCd8J2ludCc7XG4gIG5hbWU6IHN0cmluZztcbiAgYXJyYXlMZW5ndGg/OiBudW1iZXI7XG4gIGRhdGE6IG51bWJlcnxudW1iZXJbXTtcbn1cblxuLyoqXG4gKiBBIHNldCBvZiBtZXRhZGF0YSBvZiBhIHNoYWRlciBwcm9ncmFtLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIFByb2dyYW1NZXRhZGF0YSB7XG4gIC8qKlxuICAgKiB0aGUgbmFtZSBvZiB0aGUgcHJvZ3JhbS4gdXNlZCBmb3IgZGVidWdnaW5nIGFuZCBwcm9maWxpbmdcbiAgICovXG4gIG5hbWU6IHN0cmluZztcbiAgLyoqXG4gICAqIHRleHR1cmUgdHlwZXMgZm9yIGVhY2ggaW5wdXRcbiAgICovXG4gIGlucHV0VHlwZXM6IFRleHR1cmVUeXBlW107XG4gIC8qKlxuICAgKiBuYW1lcyBvZiBlYWNoIGlucHV0XG4gICAqL1xuICBpbnB1dE5hbWVzOiBzdHJpbmdbXTtcbiAgLyoqXG4gICAqIGFuIG9wdGlvbmFsIHN0cmluZyBhcyBhIGNhY2hlIGhpbnQgaW4gdGhlIGFydGlmYWN0IGNhY2hlXG4gICAqL1xuICBjYWNoZUhpbnQ/OiBzdHJpbmc7XG59XG5cbi8qKlxuICogQSBQcm9ncmFtSW5mb0xvYWRlciBhbGxvd3NcbiAqL1xuZXhwb3J0IGludGVyZmFjZSBQcm9ncmFtSW5mb0xvYWRlciBleHRlbmRzIFByb2dyYW1NZXRhZGF0YSB7XG4gIC8qKlxuICAgKiBhIGZ1bmN0aW9uIHRvIGdldCB0aGUgcHJvZ3JhbSBpbmZvXG4gICAqL1xuICBnZXQoKTogUHJvZ3JhbUluZm87XG59XG5cbi8qKlxuICogQSBzZXQgb2YgZGF0YSB0aGF0IHJlcHJlc2VudCBhIHNoYWRlciBwcm9ncmFtXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgUHJvZ3JhbUluZm8gZXh0ZW5kcyBQcm9ncmFtTWV0YWRhdGEge1xuICAvKipcbiAgICogaW5mb3JtYXRpb24gb2YgdW5pZm9ybSB2YXJpYWJsZXNcbiAgICovXG4gIHZhcmlhYmxlcz86IFByb2dyYW1WYXJpYWJsZVtdO1xuICAvKipcbiAgICogdGVuc29yIGluZm8gZm9yIG91dHB1dFxuICAgKi9cbiAgb3V0cHV0OiBUZW5zb3JJbmZvO1xuICAvKipcbiAgICogdGhlIHNoYWRlcidzIHByb2Nlc3Npbmcgc291cmNlIGNvZGVcbiAgICovXG4gIHNoYWRlclNvdXJjZTogc3RyaW5nO1xuICAvKipcbiAgICogd2hldGhlciB0aGUgc2hhZGVyIHNvdXJjZSBjb250YWlucyBhIGN1c3RvbWl6ZWQgbWFpbiBmdW5jdGlvbiBpbXBsZW1lbnRhdGlvblxuICAgKi9cbiAgaGFzTWFpbj86IGJvb2xlYW47XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgVmFyaWFibGVJbmZvIHtcbiAgdHlwZTogJ2Zsb2F0J3wnaW50JztcbiAgbmFtZTogc3RyaW5nO1xuICBhcnJheUxlbmd0aD86IG51bWJlcjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBQcm9ncmFtVmFyaWFibGUge1xuICB0eXBlOiAnZmxvYXQnfCdpbnQnO1xuICBuYW1lOiBzdHJpbmc7XG4gIGFycmF5TGVuZ3RoPzogbnVtYmVyO1xuICBkYXRhOiBudW1iZXJ8bnVtYmVyW107XG59XG5cbi8qKlxuICogSW5mb3JtYXRpb24gb2YgdW5pZm9ybXMgdGhhdCBzaGFkZXIgdXNlc1xuICovXG5leHBvcnQgaW50ZXJmYWNlIFVuaWZvcm1JbmZvIHtcbiAgdHlwZTogJ3NhbXBsZXIyRCd8VmFyaWFibGVJbmZvWyd0eXBlJ107XG4gIG5hbWU6IHN0cmluZztcbiAgYXJyYXlMZW5ndGg/OiBudW1iZXI7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgVW5pZm9ybUxvY2F0aW9uIGV4dGVuZHMgVW5pZm9ybUluZm8ge1xuICBsb2NhdGlvbjogV2ViR0xVbmlmb3JtTG9jYXRpb247XG59XG5cbi8qKlxuICogQXJ0aWZhY3QgaXMgdGhlIHJlc3VsdCBvZiBjb21waWxhdGlvblxuICogSXQgZG9lcyBub3QgY29udGFpbiBpbnB1dCBvZiBvdXRwdXQgZGF0YVxuICogSG93ZXZlciBhbnl0aGluZyB0aGF0IGNvdWxkIGJlIHJ1biBhcyBhIFwicHJvZ3JhbVwiXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgQXJ0aWZhY3Qge1xuICBwcm9ncmFtSW5mbzogUHJvZ3JhbUluZm87XG4gIHByb2dyYW06IFdlYkdMUHJvZ3JhbTtcbiAgdW5pZm9ybUxvY2F0aW9uczogVW5pZm9ybUxvY2F0aW9uW107XG4gIGF0dHJpYkxvY2F0aW9uczoge3Bvc2l0aW9uOiBudW1iZXI7IHRleHR1cmVDb29yZDogbnVtYmVyfTtcbn1cbmV4cG9ydCBkZWNsYXJlIG5hbWVzcGFjZSBBcnRpZmFjdCB7XG4gIHR5cGUgVW5pZm9ybUxvY2F0aW9ucyA9IEFydGlmYWN0Wyd1bmlmb3JtTG9jYXRpb25zJ107XG4gIHR5cGUgQXR0cmliTG9jYXRpb25zID0gQXJ0aWZhY3RbJ2F0dHJpYkxvY2F0aW9ucyddO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFVuaWZvcm1EYXRhIHtcbiAgW25hbWU6IHN0cmluZ106IG51bWJlcnxudW1iZXJbXTtcbn1cbiIsIi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxuXG5pbXBvcnQge2Fzc2VydH0gZnJvbSAnLi4vLi4vdXRpbCc7XG4vKipcbiAqIEdpdmVuIGEgbm9uIFJHQkEgc2hhcGUgY2FsY3VsYXRlIHRoZSBSIHZlcnNpb25cbiAqIEl0IGlzIGFzc3VtZWQgdGhhdCB0aGUgZGltZW5zaW9ucyBhcmUgbXVsdGlwbGVzIG9mIGdpdmVuIGNoYW5uZWxzXG4gKiBOT1RFOiBpdCBpcyBhbHdheXMgdGhlIGxhc3QgZGltIHRoYXQgZ2V0cyBwYWNrZWQuXG4gKiBAcGFyYW0gdW5wYWNrZWRTaGFwZSBvcmlnaW5hbCBzaGFwZSB0byBjcmVhdGUgYSBwYWNrZWQgdmVyc2lvbiBmcm9tXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRQYWNrZWRTaGFwZSh1bnBhY2tlZFNoYXBlOiByZWFkb25seSBudW1iZXJbXSk6IHJlYWRvbmx5IG51bWJlcltdIHtcbiAgY29uc3QgbGVuID0gdW5wYWNrZWRTaGFwZS5sZW5ndGg7XG4gIHJldHVybiB1bnBhY2tlZFNoYXBlLnNsaWNlKDAsIGxlbiAtIDEpLmNvbmNhdCh1bnBhY2tlZFNoYXBlW2xlbiAtIDFdIC8gNCk7XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiByZXBlYXRlZFRyeShcbiAgICBjaGVja0ZuOiAoKSA9PiBib29sZWFuLCBkZWxheUZuID0gKF9jb3VudGVyOiBudW1iZXIpID0+IDAsIG1heENvdW50ZXI/OiBudW1iZXIpOiBQcm9taXNlPHZvaWQ+IHtcbiAgcmV0dXJuIG5ldyBQcm9taXNlPHZvaWQ+KChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICBsZXQgdHJ5Q291bnQgPSAwO1xuXG4gICAgY29uc3QgdHJ5Rm4gPSAoKSA9PiB7XG4gICAgICBpZiAoY2hlY2tGbigpKSB7XG4gICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICB0cnlDb3VudCsrO1xuXG4gICAgICBjb25zdCBuZXh0QmFja29mZiA9IGRlbGF5Rm4odHJ5Q291bnQpO1xuXG4gICAgICBpZiAobWF4Q291bnRlciAhPSBudWxsICYmIHRyeUNvdW50ID49IG1heENvdW50ZXIpIHtcbiAgICAgICAgcmVqZWN0KCk7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICAgIHNldFRpbWVvdXQodHJ5Rm4sIG5leHRCYWNrb2ZmKTtcbiAgICB9O1xuXG4gICAgdHJ5Rm4oKTtcbiAgfSk7XG59XG5cbi8qKlxuICogR2VuZXJhdGVzIHRoZSBmdW5jdGlvbiBuYW1lIGZyb20gYW4gaW5wdXQgc2FtcGxlciBuYW1lLlxuICogQHBhcmFtIHNhbXBsZXJOYW1lIE5hbWUgb2YgdGhlIHNhbXBsZXIuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZW5lcmF0ZVNoYWRlckZ1bmNOYW1lRnJvbUlucHV0U2FtcGxlck5hbWUoc2FtcGxlck5hbWU6IHN0cmluZyk6IHN0cmluZyB7XG4gIGFzc2VydCh0eXBlb2Ygc2FtcGxlck5hbWUgIT09ICd1bmRlZmluZWQnICYmIHNhbXBsZXJOYW1lLmxlbmd0aCAhPT0gMCwgKCkgPT4gJ2VtcHR5IHN0cmluZyBmb3VuZCBmb3Igc2FtcGxlciBuYW1lJyk7XG4gIHJldHVybiAnZ2V0JyArIHNhbXBsZXJOYW1lLmNoYXJBdCgwKS50b1VwcGVyQ2FzZSgpICsgc2FtcGxlck5hbWUuc2xpY2UoMSk7XG59XG5cbi8qKlxuICogR2VuZXJhdGVzIHRoZSBmdW5jdGlvbiBuYW1lIGZyb20gYW4gaW5wdXQgc2FtcGxlciBuYW1lIGF0IG91dHB1dCBjb29yZGluYXRlcy5cbiAqIEBwYXJhbSBzYW1wbGVyTmFtZSBOYW1lIG9mIHRoZSBzYW1wbGVyLlxuICovXG5leHBvcnQgZnVuY3Rpb24gZ2VuZXJhdGVTaGFkZXJGdW5jTmFtZUZyb21JbnB1dFNhbXBsZXJOYW1lQXRPdXRDb29yZHMoc2FtcGxlck5hbWU6IHN0cmluZyk6IHN0cmluZyB7XG4gIGFzc2VydCh0eXBlb2Ygc2FtcGxlck5hbWUgIT09ICd1bmRlZmluZWQnICYmIHNhbXBsZXJOYW1lLmxlbmd0aCAhPT0gMCwgKCkgPT4gJ2VtcHR5IHN0cmluZyBmb3VuZCBmb3Igc2FtcGxlciBuYW1lJyk7XG4gIHJldHVybiAnZ2V0JyArIHNhbXBsZXJOYW1lLmNoYXJBdCgwKS50b1VwcGVyQ2FzZSgpICsgc2FtcGxlck5hbWUuc2xpY2UoMSkgKyAnQXRPdXRDb29yZHMnO1xufVxuXG4vKiogUmV0dXJucyBhIG5ldyBpbnB1dCBzaGFwZSAoYSBjb3B5KSB0aGF0IGhhcyBhIHNxdWVlemVkIGxvZ2ljYWwgc2hhcGUuICovXG5leHBvcnQgZnVuY3Rpb24gc3F1ZWV6ZUlucHV0U2hhcGUoaW5wdXRTaGFwZTogcmVhZG9ubHkgbnVtYmVyW10sIHNxdWVlemVkU2hhcGU6IG51bWJlcltdKTogbnVtYmVyW10ge1xuICAvLyBEZWVwIGNvcHkuXG4gIGxldCBuZXdJbnB1dFNoYXBlOiBudW1iZXJbXSA9IEpTT04ucGFyc2UoSlNPTi5zdHJpbmdpZnkoaW5wdXRTaGFwZSkpO1xuICBuZXdJbnB1dFNoYXBlID0gc3F1ZWV6ZWRTaGFwZTtcbiAgcmV0dXJuIG5ld0lucHV0U2hhcGU7XG59XG5cbi8qKiBSZXR1cm5zIGEgbGlzdCBvZiBzcXVlZXplZCBwYXJhbWV0ZXJzIGZvciBzaGFkZXIgZnVuY3Rpb25zICovXG5leHBvcnQgZnVuY3Rpb24gZ2V0U3F1ZWV6ZWRQYXJhbXMocGFyYW1zOiBzdHJpbmdbXSwga2VwdERpbXM6IG51bWJlcltdKTogc3RyaW5nIHtcbiAgcmV0dXJuIGtlcHREaW1zLm1hcChkID0+IHBhcmFtc1tkXSkuam9pbignLCAnKTtcbn1cblxuLyoqIFJldHVybnMgdGhlIGRhdGEgdHlwZSBmb3IgZGlmZmVyZW50IHJhbmtzLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldENvb3Jkc0RhdGFUeXBlKHJhbms6IG51bWJlcik6IHN0cmluZyB7XG4gIGlmIChyYW5rIDw9IDEpIHtcbiAgICByZXR1cm4gJ2ludCc7XG4gIH0gZWxzZSBpZiAocmFuayA9PT0gMikge1xuICAgIHJldHVybiAnaXZlYzInO1xuICB9IGVsc2UgaWYgKHJhbmsgPT09IDMpIHtcbiAgICByZXR1cm4gJ2l2ZWMzJztcbiAgfSBlbHNlIGlmIChyYW5rID09PSA0KSB7XG4gICAgcmV0dXJuICdpdmVjNCc7XG4gIH0gZWxzZSBpZiAocmFuayA9PT0gNSkge1xuICAgIHJldHVybiAnaXZlYzUnO1xuICB9IGVsc2UgaWYgKHJhbmsgPT09IDYpIHtcbiAgICByZXR1cm4gJ2l2ZWM2JztcbiAgfSBlbHNlIHtcbiAgICB0aHJvdyBFcnJvcihgR1BVIGZvciByYW5rICR7cmFua30gaXMgbm90IHlldCBzdXBwb3J0ZWRgKTtcbiAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24gZ2V0R2xDaGFubmVscyhyYW5rID0gNik6IHN0cmluZ1tdIHtcbiAgcmV0dXJuIFsneCcsICd5JywgJ3onLCAndycsICd1JywgJ3YnXS5zbGljZSgwLCByYW5rKTtcbn1cbiIsIi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxuXG5pbXBvcnQge0xvZ2dlcn0gZnJvbSAnLi4vLi4vaW5zdHJ1bWVudCc7XG5cbmltcG9ydCB7V2ViR0xDb250ZXh0fSBmcm9tICcuL3dlYmdsLWNvbnRleHQnO1xuXG5jb25zdCBjYWNoZToge1tjb250ZXh0SWQ6IHN0cmluZ106IFdlYkdMQ29udGV4dH0gPSB7fTtcblxuLyoqXG4gKiBUaGlzIGZhY3RvcnkgZnVuY3Rpb24gY3JlYXRlcyBwcm9wZXIgV2ViR0xSZW5kZXJpbmdDb250ZXh0IGJhc2VkIG9uXG4gKiB0aGUgY3VycmVudCBicm93c2VycyBjYXBhYmlsaXRpZXNcbiAqIFRoZSBvcmRlciBpcyBmcm9tIGhpZ2hlci9tb3N0IHJlY2VudCB2ZXJzaW9ucyB0byBtb3N0IGJhc2ljXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVXZWJHTENvbnRleHQoY29udGV4dElkPzogJ3dlYmdsJ3wnd2ViZ2wyJyk6IFdlYkdMQ29udGV4dCB7XG4gIGxldCBjb250ZXh0OiBXZWJHTENvbnRleHR8dW5kZWZpbmVkO1xuICBpZiAoKCFjb250ZXh0SWQgfHwgY29udGV4dElkID09PSAnd2ViZ2wyJykgJiYgJ3dlYmdsMicgaW4gY2FjaGUpIHtcbiAgICBjb250ZXh0ID0gY2FjaGUud2ViZ2wyO1xuICB9IGVsc2UgaWYgKCghY29udGV4dElkIHx8IGNvbnRleHRJZCA9PT0gJ3dlYmdsJykgJiYgJ3dlYmdsJyBpbiBjYWNoZSkge1xuICAgIGNvbnRleHQgPSBjYWNoZS53ZWJnbDtcbiAgfVxuXG4gIGNvbnRleHQgPSBjb250ZXh0IHx8IGNyZWF0ZU5ld1dlYkdMQ29udGV4dChjb250ZXh0SWQpO1xuICBjb250ZXh0SWQgPSBjb250ZXh0SWQgfHwgY29udGV4dC52ZXJzaW9uID09PSAxID8gJ3dlYmdsJyA6ICd3ZWJnbDInO1xuICBjb25zdCBnbCA9IGNvbnRleHQuZ2w7XG5cbiAgY2FjaGVbY29udGV4dElkXSA9IGNvbnRleHQ7XG5cbiAgaWYgKGdsLmlzQ29udGV4dExvc3QoKSkge1xuICAgIGRlbGV0ZSBjYWNoZVtjb250ZXh0SWRdO1xuICAgIHJldHVybiBjcmVhdGVXZWJHTENvbnRleHQoY29udGV4dElkKTtcbiAgfVxuXG4gIGdsLmRpc2FibGUoZ2wuREVQVEhfVEVTVCk7XG4gIGdsLmRpc2FibGUoZ2wuU1RFTkNJTF9URVNUKTtcbiAgZ2wuZGlzYWJsZShnbC5CTEVORCk7XG4gIGdsLmRpc2FibGUoZ2wuRElUSEVSKTtcbiAgZ2wuZGlzYWJsZShnbC5QT0xZR09OX09GRlNFVF9GSUxMKTtcbiAgZ2wuZGlzYWJsZShnbC5TQU1QTEVfQ09WRVJBR0UpO1xuICBnbC5lbmFibGUoZ2wuU0NJU1NPUl9URVNUKTtcbiAgZ2wuZW5hYmxlKGdsLkNVTExfRkFDRSk7XG4gIGdsLmN1bGxGYWNlKGdsLkJBQ0spO1xuXG4gIHJldHVybiBjb250ZXh0O1xufVxuXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlTmV3V2ViR0xDb250ZXh0KGNvbnRleHRJZD86ICd3ZWJnbCd8J3dlYmdsMicpOiBXZWJHTENvbnRleHQge1xuICBjb25zdCBjYW52YXMgPSBjcmVhdGVDYW52YXMoKTtcbiAgY29uc3QgY29udGV4dEF0dHJpYnV0ZXM6IFdlYkdMQ29udGV4dEF0dHJpYnV0ZXMgPSB7XG4gICAgYWxwaGE6IGZhbHNlLFxuICAgIGRlcHRoOiBmYWxzZSxcbiAgICBhbnRpYWxpYXM6IGZhbHNlLFxuICAgIHN0ZW5jaWw6IGZhbHNlLFxuICAgIHByZXNlcnZlRHJhd2luZ0J1ZmZlcjogZmFsc2UsXG4gICAgcHJlbXVsdGlwbGllZEFscGhhOiBmYWxzZSxcbiAgICBmYWlsSWZNYWpvclBlcmZvcm1hbmNlQ2F2ZWF0OiBmYWxzZVxuICB9O1xuICBsZXQgZ2w6IFdlYkdMUmVuZGVyaW5nQ29udGV4dHxudWxsO1xuICBjb25zdCBjYSA9IGNvbnRleHRBdHRyaWJ1dGVzO1xuICBpZiAoIWNvbnRleHRJZCB8fCBjb250ZXh0SWQgPT09ICd3ZWJnbDInKSB7XG4gICAgZ2wgPSBjYW52YXMuZ2V0Q29udGV4dCgnd2ViZ2wyJywgY2EpO1xuICAgIGlmIChnbCkge1xuICAgICAgdHJ5IHtcbiAgICAgICAgcmV0dXJuIG5ldyBXZWJHTENvbnRleHQoZ2wsIDIpO1xuICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgIExvZ2dlci53YXJuaW5nKCdHbENvbnRleHRGYWN0b3J5JywgYGZhaWxlZCB0byBjcmVhdGUgV2ViR0xDb250ZXh0IHVzaW5nIGNvbnRleHRJZCAnd2ViZ2wyJy4gRXJyb3I6ICR7ZXJyfWApO1xuICAgICAgfVxuICAgIH1cbiAgfVxuICBpZiAoIWNvbnRleHRJZCB8fCBjb250ZXh0SWQgPT09ICd3ZWJnbCcpIHtcbiAgICBnbCA9IGNhbnZhcy5nZXRDb250ZXh0KCd3ZWJnbCcsIGNhKSB8fCBjYW52YXMuZ2V0Q29udGV4dCgnZXhwZXJpbWVudGFsLXdlYmdsJywgY2EpIGFzIFdlYkdMUmVuZGVyaW5nQ29udGV4dDtcbiAgICBpZiAoZ2wpIHtcbiAgICAgIHRyeSB7XG4gICAgICAgIHJldHVybiBuZXcgV2ViR0xDb250ZXh0KGdsLCAxKTtcbiAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICBMb2dnZXIud2FybmluZyhcbiAgICAgICAgICAgICdHbENvbnRleHRGYWN0b3J5JyxcbiAgICAgICAgICAgIGBmYWlsZWQgdG8gY3JlYXRlIFdlYkdMQ29udGV4dCB1c2luZyBjb250ZXh0SWQgJ3dlYmdsJyBvciAnZXhwZXJpbWVudGFsLXdlYmdsJy4gRXJyb3I6ICR7ZXJyfWApO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHRocm93IG5ldyBFcnJvcignV2ViR0wgaXMgbm90IHN1cHBvcnRlZCcpO1xufVxuXG4vLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25hbWluZy1jb252ZW50aW9uXG5kZWNsYXJlIGxldCBPZmZzY3JlZW5DYW52YXM6IHtuZXcgKHdpZHRoOiBudW1iZXIsIGhlaWdodDogbnVtYmVyKTogSFRNTENhbnZhc0VsZW1lbnR9O1xuXG5mdW5jdGlvbiBjcmVhdGVDYW52YXMoKTogSFRNTENhbnZhc0VsZW1lbnQge1xuICBpZiAodHlwZW9mIGRvY3VtZW50ID09PSAndW5kZWZpbmVkJykge1xuICAgIGlmICh0eXBlb2YgT2Zmc2NyZWVuQ2FudmFzID09PSAndW5kZWZpbmVkJykge1xuICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignZmFpbGVkIHRvIGNyZWF0ZSBjYW52YXM6IE9mZnNjcmVlbkNhbnZhcyBpcyBub3Qgc3VwcG9ydGVkJyk7XG4gICAgfVxuICAgIHJldHVybiBuZXcgT2Zmc2NyZWVuQ2FudmFzKDEsIDEpO1xuICB9XG4gIGNvbnN0IGNhbnZhczogSFRNTENhbnZhc0VsZW1lbnQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdjYW52YXMnKTtcbiAgY2FudmFzLndpZHRoID0gMTtcbiAgY2FudmFzLmhlaWdodCA9IDE7XG4gIHJldHVybiBjYW52YXM7XG59XG4iLCIvLyBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cblxuaW1wb3J0IHtlbnZ9IGZyb20gJ29ubnhydW50aW1lLWNvbW1vbic7XG5cbmltcG9ydCAqIGFzIERhdGFFbmNvZGVycyBmcm9tICcuL3RleHR1cmUtZGF0YS1lbmNvZGVyJztcbmltcG9ydCB7RGF0YUVuY29kZXIsIEVuY29kZXJ9IGZyb20gJy4vdGV4dHVyZS1kYXRhLWVuY29kZXInO1xuaW1wb3J0IHtyZXBlYXRlZFRyeX0gZnJvbSAnLi91dGlscyc7XG5cbmV4cG9ydCBpbnRlcmZhY2UgRmVuY2VDb250ZXh0IHtcbiAgcXVlcnk6IFdlYkdMU3luY3xudWxsO1xuICBpc0ZlbmNlUGFzc2VkKCk6IGJvb2xlYW47XG59XG5cbnR5cGUgUG9sbEl0ZW0gPSB7XG4gIGlzRG9uZUZuOiAoKSA9PiBib29sZWFuOyByZXNvbHZlRm46ICgpID0+IHZvaWQ7XG59O1xuXG5leHBvcnQgZnVuY3Rpb24gbGluZWFyU2VhcmNoTGFzdFRydWUoYXJyOiBBcnJheTwoKSA9PiBib29sZWFuPik6IG51bWJlciB7XG4gIGxldCBpID0gMDtcbiAgZm9yICg7IGkgPCBhcnIubGVuZ3RoOyArK2kpIHtcbiAgICBjb25zdCBpc0RvbmUgPSBhcnJbaV0oKTtcbiAgICBpZiAoIWlzRG9uZSkge1xuICAgICAgYnJlYWs7XG4gICAgfVxuICB9XG4gIHJldHVybiBpIC0gMTtcbn1cblxuLyoqXG4gKiBBYnN0cmFjdGlvbiBhbmQgd3JhcHBlciBhcm91bmQgV2ViR0xSZW5kZXJpbmdDb250ZXh0IGFuZCBpdHMgb3BlcmF0aW9uc1xuICovXG5leHBvcnQgY2xhc3MgV2ViR0xDb250ZXh0IHtcbiAgZ2w6IFdlYkdMUmVuZGVyaW5nQ29udGV4dDtcbiAgdmVyc2lvbjogMXwyO1xuXG4gIHByaXZhdGUgdmVydGV4YnVmZmVyOiBXZWJHTEJ1ZmZlcjtcbiAgcHJpdmF0ZSBmcmFtZWJ1ZmZlcjogV2ViR0xGcmFtZWJ1ZmZlcjtcblxuICAvLyBXZWJHTCBmbGFncyBhbmQgdml0YWwgcGFyYW1ldGVyc1xuICBwcml2YXRlIGlzRmxvYXRUZXh0dXJlQXR0YWNoYWJsZVRvRnJhbWVCdWZmZXI6IGJvb2xlYW47XG4gIGlzRmxvYXQzMkRvd25sb2FkU3VwcG9ydGVkOiBib29sZWFuO1xuICBpc1JlbmRlckZsb2F0MzJTdXBwb3J0ZWQ6IGJvb2xlYW47XG4gIGlzQmxlbmRTdXBwb3J0ZWQ6IGJvb2xlYW47XG4gIG1heFRleHR1cmVTaXplOiBudW1iZXI7XG4gIC8vIHByaXZhdGUgbWF4Q29tYmluZWRUZXh0dXJlSW1hZ2VVbml0czogbnVtYmVyO1xuICBwcml2YXRlIG1heFRleHR1cmVJbWFnZVVuaXRzOiBudW1iZXI7XG4gIC8vIHByaXZhdGUgbWF4Q3ViZU1hcFRleHR1cmVTaXplOiBudW1iZXI7XG4gIC8vIHByaXZhdGUgc2hhZGluZ0xhbmd1YWdlVmVyc2lvbjogc3RyaW5nO1xuICAvLyBwcml2YXRlIHdlYmdsVmVuZG9yOiBzdHJpbmc7XG4gIC8vIHByaXZhdGUgd2ViZ2xWZXJzaW9uOiBzdHJpbmc7XG5cbiAgLy8gV2ViR0wyIGZsYWdzIGFuZCB2aXRhbCBwYXJhbWV0ZXJzXG4gIC8vIHByaXZhdGUgbWF4M0RUZXh0dXJlU2l6ZTogbnVtYmVyO1xuICAvLyBwcml2YXRlIG1heEFycmF5VGV4dHVyZUxheWVyczogbnVtYmVyO1xuICAvLyBwcml2YXRlIG1heENvbG9yQXR0YWNobWVudHM6IG51bWJlcjtcbiAgLy8gcHJpdmF0ZSBtYXhEcmF3QnVmZmVyczogbnVtYmVyO1xuXG4gIC8vIFdlYkdMIGV4dGVuc2lvbnNcbiAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGNhbWVsY2FzZVxuICB0ZXh0dXJlRmxvYXRFeHRlbnNpb246IE9FU190ZXh0dXJlX2Zsb2F0fG51bGw7XG4gIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBjYW1lbGNhc2VcbiAgdGV4dHVyZUhhbGZGbG9hdEV4dGVuc2lvbjogT0VTX3RleHR1cmVfaGFsZl9mbG9hdHxudWxsO1xuXG4gIC8vIFdlYkdMMiBleHRlbnNpb25zXG4gIGNvbG9yQnVmZmVyRmxvYXRFeHRlbnNpb246IHVua25vd258bnVsbDtcbiAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uYW1pbmctY29udmVudGlvblxuICBkaXNqb2ludFRpbWVyUXVlcnlXZWJnbDJFeHRlbnNpb246IHtUSU1FX0VMQVBTRURfRVhUOiBHTGVudW07IEdQVV9ESVNKT0lOVF9FWFQ6IEdMZW51bX18bnVsbDtcblxuICBwcml2YXRlIGRpc3Bvc2VkOiBib29sZWFuO1xuICBwcml2YXRlIGZyYW1lQnVmZmVyQm91bmQgPSBmYWxzZTtcblxuICBjb25zdHJ1Y3RvcihnbDogV2ViR0xSZW5kZXJpbmdDb250ZXh0LCB2ZXJzaW9uOiAxfDIpIHtcbiAgICB0aGlzLmdsID0gZ2w7XG4gICAgdGhpcy52ZXJzaW9uID0gdmVyc2lvbjtcblxuICAgIHRoaXMuZ2V0RXh0ZW5zaW9ucygpO1xuICAgIHRoaXMudmVydGV4YnVmZmVyID0gdGhpcy5jcmVhdGVWZXJ0ZXhidWZmZXIoKTtcbiAgICB0aGlzLmZyYW1lYnVmZmVyID0gdGhpcy5jcmVhdGVGcmFtZWJ1ZmZlcigpO1xuICAgIHRoaXMucXVlcnlWaXRhbFBhcmFtZXRlcnMoKTtcbiAgfVxuXG4gIGFsbG9jYXRlVGV4dHVyZSh3aWR0aDogbnVtYmVyLCBoZWlnaHQ6IG51bWJlciwgZW5jb2RlcjogRGF0YUVuY29kZXIsIGRhdGE/OiBFbmNvZGVyLkRhdGFBcnJheVR5cGUpOiBXZWJHTFRleHR1cmUge1xuICAgIGNvbnN0IGdsID0gdGhpcy5nbDtcbiAgICAvLyBjcmVhdGUgdGhlIHRleHR1cmVcbiAgICBjb25zdCB0ZXh0dXJlID0gZ2wuY3JlYXRlVGV4dHVyZSgpO1xuICAgIC8vIGJpbmQgdGhlIHRleHR1cmUgc28gdGhlIGZvbGxvd2luZyBtZXRob2RzIGVmZmVjdCB0aGlzIHRleHR1cmUuXG4gICAgZ2wuYmluZFRleHR1cmUoZ2wuVEVYVFVSRV8yRCwgdGV4dHVyZSk7XG4gICAgZ2wudGV4UGFyYW1ldGVyaShnbC5URVhUVVJFXzJELCBnbC5URVhUVVJFX01JTl9GSUxURVIsIGdsLk5FQVJFU1QpO1xuICAgIGdsLnRleFBhcmFtZXRlcmkoZ2wuVEVYVFVSRV8yRCwgZ2wuVEVYVFVSRV9NQUdfRklMVEVSLCBnbC5ORUFSRVNUKTtcbiAgICBnbC50ZXhQYXJhbWV0ZXJpKGdsLlRFWFRVUkVfMkQsIGdsLlRFWFRVUkVfV1JBUF9TLCBnbC5DTEFNUF9UT19FREdFKTtcbiAgICBnbC50ZXhQYXJhbWV0ZXJpKGdsLlRFWFRVUkVfMkQsIGdsLlRFWFRVUkVfV1JBUF9ULCBnbC5DTEFNUF9UT19FREdFKTtcbiAgICBjb25zdCBidWZmZXIgPSBkYXRhID8gZW5jb2Rlci5lbmNvZGUoZGF0YSwgd2lkdGggKiBoZWlnaHQpIDogbnVsbDtcbiAgICBnbC50ZXhJbWFnZTJEKFxuICAgICAgICBnbC5URVhUVVJFXzJELFxuICAgICAgICAwLCAgLy8gTGV2ZWwgb2YgZGV0YWlsLlxuICAgICAgICBlbmNvZGVyLmludGVybmFsRm9ybWF0LCB3aWR0aCwgaGVpZ2h0LFxuICAgICAgICAwLCAgLy8gQWx3YXlzIDAgaW4gT3BlbkdMIEVTLlxuICAgICAgICBlbmNvZGVyLmZvcm1hdCwgZW5jb2Rlci50ZXh0dXJlVHlwZSwgYnVmZmVyKTtcbiAgICB0aGlzLmNoZWNrRXJyb3IoKTtcbiAgICByZXR1cm4gdGV4dHVyZSBhcyBXZWJHTFRleHR1cmU7XG4gIH1cbiAgdXBkYXRlVGV4dHVyZShcbiAgICAgIHRleHR1cmU6IFdlYkdMVGV4dHVyZSwgd2lkdGg6IG51bWJlciwgaGVpZ2h0OiBudW1iZXIsIGVuY29kZXI6IERhdGFFbmNvZGVyLCBkYXRhOiBFbmNvZGVyLkRhdGFBcnJheVR5cGUpOiB2b2lkIHtcbiAgICBjb25zdCBnbCA9IHRoaXMuZ2w7XG4gICAgZ2wuYmluZFRleHR1cmUoZ2wuVEVYVFVSRV8yRCwgdGV4dHVyZSk7XG4gICAgY29uc3QgYnVmZmVyID0gZW5jb2Rlci5lbmNvZGUoZGF0YSwgd2lkdGggKiBoZWlnaHQpO1xuICAgIGdsLnRleFN1YkltYWdlMkQoXG4gICAgICAgIGdsLlRFWFRVUkVfMkQsXG4gICAgICAgIDAsICAvLyBsZXZlbFxuICAgICAgICAwLCAgLy8geG9mZnNldFxuICAgICAgICAwLCAgLy8geW9mZnNldFxuICAgICAgICB3aWR0aCwgaGVpZ2h0LCBlbmNvZGVyLmZvcm1hdCwgZW5jb2Rlci50ZXh0dXJlVHlwZSwgYnVmZmVyKTtcbiAgICB0aGlzLmNoZWNrRXJyb3IoKTtcbiAgfVxuICBhdHRhY2hGcmFtZWJ1ZmZlcih0ZXh0dXJlOiBXZWJHTFRleHR1cmUsIHdpZHRoOiBudW1iZXIsIGhlaWdodDogbnVtYmVyKTogdm9pZCB7XG4gICAgY29uc3QgZ2wgPSB0aGlzLmdsO1xuICAgIC8vIE1ha2UgaXQgdGhlIHRhcmdldCBmb3IgZnJhbWVidWZmZXIgb3BlcmF0aW9ucyAtIGluY2x1ZGluZyByZW5kZXJpbmcuXG4gICAgZ2wuYmluZFRleHR1cmUoZ2wuVEVYVFVSRV8yRCwgdGV4dHVyZSk7XG4gICAgZ2wuYmluZEZyYW1lYnVmZmVyKGdsLkZSQU1FQlVGRkVSLCB0aGlzLmZyYW1lYnVmZmVyKTtcbiAgICBnbC5mcmFtZWJ1ZmZlclRleHR1cmUyRChcbiAgICAgICAgZ2wuRlJBTUVCVUZGRVIsIGdsLkNPTE9SX0FUVEFDSE1FTlQwLCBnbC5URVhUVVJFXzJELCB0ZXh0dXJlLFxuICAgICAgICAwKTsgIC8vIDAsIHdlIGFyZW4ndCB1c2luZyBNSVBNQVBzXG4gICAgdGhpcy5jaGVja0Vycm9yKCk7XG4gICAgZ2wudmlld3BvcnQoMCwgMCwgd2lkdGgsIGhlaWdodCk7XG4gICAgZ2wuc2Npc3NvcigwLCAwLCB3aWR0aCwgaGVpZ2h0KTtcbiAgfVxuICByZWFkVGV4dHVyZShcbiAgICAgIHRleHR1cmU6IFdlYkdMVGV4dHVyZSwgd2lkdGg6IG51bWJlciwgaGVpZ2h0OiBudW1iZXIsIGRhdGFTaXplOiBudW1iZXIsIGRhdGFUeXBlOiBFbmNvZGVyLkRhdGFUeXBlLFxuICAgICAgY2hhbm5lbHM6IG51bWJlcik6IEVuY29kZXIuRGF0YUFycmF5VHlwZSB7XG4gICAgY29uc3QgZ2wgPSB0aGlzLmdsO1xuICAgIGlmICghY2hhbm5lbHMpIHtcbiAgICAgIGNoYW5uZWxzID0gMTtcbiAgICB9XG4gICAgaWYgKCF0aGlzLmZyYW1lQnVmZmVyQm91bmQpIHtcbiAgICAgIHRoaXMuYXR0YWNoRnJhbWVidWZmZXIodGV4dHVyZSwgd2lkdGgsIGhlaWdodCk7XG4gICAgfVxuICAgIGNvbnN0IGVuY29kZXIgPSB0aGlzLmdldEVuY29kZXIoZGF0YVR5cGUsIGNoYW5uZWxzKTtcbiAgICBjb25zdCBidWZmZXIgPSBlbmNvZGVyLmFsbG9jYXRlKHdpZHRoICogaGVpZ2h0KTtcbiAgICAvLyBiaW5kIHRleHR1cmUgdG8gZnJhbWVidWZmZXJcbiAgICBnbC5iaW5kVGV4dHVyZShnbC5URVhUVVJFXzJELCB0ZXh0dXJlKTtcbiAgICBnbC5mcmFtZWJ1ZmZlclRleHR1cmUyRChcbiAgICAgICAgZ2wuRlJBTUVCVUZGRVIsIGdsLkNPTE9SX0FUVEFDSE1FTlQwLCBnbC5URVhUVVJFXzJELCB0ZXh0dXJlLFxuICAgICAgICAwKTsgIC8vIDAsIHdlIGFyZW4ndCB1c2luZyBNSVBNQVBzXG4gICAgLy8gVE9ETzogQ2hlY2sgaWYgZnJhbWVidWZmZXIgaXMgcmVhZHlcbiAgICBnbC5yZWFkUGl4ZWxzKDAsIDAsIHdpZHRoLCBoZWlnaHQsIGdsLlJHQkEsIGVuY29kZXIudGV4dHVyZVR5cGUsIGJ1ZmZlcik7XG4gICAgdGhpcy5jaGVja0Vycm9yKCk7XG4gICAgLy8gdW5iaW5kIEZCXG4gICAgcmV0dXJuIGVuY29kZXIuZGVjb2RlKGJ1ZmZlciwgZGF0YVNpemUpO1xuICB9XG5cbiAgaXNGcmFtZWJ1ZmZlclJlYWR5KCk6IGJvb2xlYW4ge1xuICAgIC8vIFRPRE86IEltcGxlbWVudCBsb2dpYyB0byBjaGVjayBpZiB0aGUgZnJhbWVidWZmZXIgaXMgcmVhZHlcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxuICBnZXRBY3RpdmVUZXh0dXJlKCk6IHN0cmluZyB7XG4gICAgY29uc3QgZ2wgPSB0aGlzLmdsO1xuICAgIGNvbnN0IG4gPSBnbC5nZXRQYXJhbWV0ZXIodGhpcy5nbC5BQ1RJVkVfVEVYVFVSRSk7XG4gICAgcmV0dXJuIGBURVhUVVJFJHsobiAtIGdsLlRFWFRVUkUwKX1gO1xuICB9XG4gIGdldFRleHR1cmVCaW5kaW5nKCk6IFdlYkdMVGV4dHVyZSB7XG4gICAgcmV0dXJuIHRoaXMuZ2wuZ2V0UGFyYW1ldGVyKHRoaXMuZ2wuVEVYVFVSRV9CSU5ESU5HXzJEKTtcbiAgfVxuICBnZXRGcmFtZWJ1ZmZlckJpbmRpbmcoKTogV2ViR0xGcmFtZWJ1ZmZlciB7XG4gICAgcmV0dXJuIHRoaXMuZ2wuZ2V0UGFyYW1ldGVyKHRoaXMuZ2wuRlJBTUVCVUZGRVJfQklORElORyk7XG4gIH1cbiAgc2V0VmVydGV4QXR0cmlidXRlcyhwb3NpdGlvbkhhbmRsZTogbnVtYmVyLCB0ZXh0dXJlQ29vcmRIYW5kbGU6IG51bWJlcik6IHZvaWQge1xuICAgIGNvbnN0IGdsID0gdGhpcy5nbDtcbiAgICBnbC52ZXJ0ZXhBdHRyaWJQb2ludGVyKHBvc2l0aW9uSGFuZGxlLCAzLCBnbC5GTE9BVCwgZmFsc2UsIDIwLCAwKTtcbiAgICBnbC5lbmFibGVWZXJ0ZXhBdHRyaWJBcnJheShwb3NpdGlvbkhhbmRsZSk7XG4gICAgaWYgKHRleHR1cmVDb29yZEhhbmRsZSAhPT0gLTEpIHtcbiAgICAgIGdsLnZlcnRleEF0dHJpYlBvaW50ZXIodGV4dHVyZUNvb3JkSGFuZGxlLCAyLCBnbC5GTE9BVCwgZmFsc2UsIDIwLCAxMik7XG4gICAgICBnbC5lbmFibGVWZXJ0ZXhBdHRyaWJBcnJheSh0ZXh0dXJlQ29vcmRIYW5kbGUpO1xuICAgIH1cbiAgICB0aGlzLmNoZWNrRXJyb3IoKTtcbiAgfVxuICBjcmVhdGVQcm9ncmFtKFxuICAgICAgdmVydGV4U2hhZGVyOiBXZWJHTFNoYWRlcixcbiAgICAgIGZyYWdTaGFkZXI6IFdlYkdMU2hhZGVyLFxuICAgICAgKTogV2ViR0xQcm9ncmFtIHtcbiAgICBjb25zdCBnbCA9IHRoaXMuZ2w7XG4gICAgY29uc3QgcHJvZ3JhbSA9IGdsLmNyZWF0ZVByb2dyYW0oKSE7XG5cbiAgICAvLyB0aGUgcHJvZ3JhbSBjb25zaXN0cyBvZiBvdXIgc2hhZGVyc1xuICAgIGdsLmF0dGFjaFNoYWRlcihwcm9ncmFtLCB2ZXJ0ZXhTaGFkZXIpO1xuICAgIGdsLmF0dGFjaFNoYWRlcihwcm9ncmFtLCBmcmFnU2hhZGVyKTtcbiAgICBnbC5saW5rUHJvZ3JhbShwcm9ncmFtKTtcbiAgICByZXR1cm4gcHJvZ3JhbTtcbiAgfVxuICBjb21waWxlU2hhZGVyKHNoYWRlclNvdXJjZTogc3RyaW5nLCBzaGFkZXJUeXBlOiBudW1iZXIpOiBXZWJHTFNoYWRlciB7XG4gICAgY29uc3QgZ2wgPSB0aGlzLmdsO1xuICAgIGNvbnN0IHNoYWRlciA9IGdsLmNyZWF0ZVNoYWRlcihzaGFkZXJUeXBlKTtcbiAgICBpZiAoIXNoYWRlcikge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBjcmVhdGVTaGFkZXIoKSByZXR1cm5lZCBudWxsIHdpdGggdHlwZSAke3NoYWRlclR5cGV9YCk7XG4gICAgfVxuXG4gICAgZ2wuc2hhZGVyU291cmNlKHNoYWRlciwgc2hhZGVyU291cmNlKTtcbiAgICBnbC5jb21waWxlU2hhZGVyKHNoYWRlcik7XG4gICAgaWYgKGdsLmdldFNoYWRlclBhcmFtZXRlcihzaGFkZXIsIGdsLkNPTVBJTEVfU1RBVFVTKSA9PT0gZmFsc2UpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgRmFpbGVkIHRvIGNvbXBpbGUgc2hhZGVyOiAke2dsLmdldFNoYWRlckluZm9Mb2coc2hhZGVyKX1cblNoYWRlciBzb3VyY2U6XG4ke3NoYWRlclNvdXJjZX1gKTtcbiAgICB9XG4gICAgcmV0dXJuIHNoYWRlcjtcbiAgfVxuICBkZWxldGVTaGFkZXIoc2hhZGVyOiBXZWJHTFNoYWRlcik6IHZvaWQge1xuICAgIHRoaXMuZ2wuZGVsZXRlU2hhZGVyKHNoYWRlcik7XG4gIH1cbiAgYmluZFRleHR1cmVUb1VuaWZvcm0odGV4dHVyZTogV2ViR0xUZXh0dXJlLCBwb3NpdGlvbjogbnVtYmVyLCB1bmlmb3JtSGFuZGxlOiBXZWJHTFVuaWZvcm1Mb2NhdGlvbik6IHZvaWQge1xuICAgIGNvbnN0IGdsID0gdGhpcy5nbDtcbiAgICBnbC5hY3RpdmVUZXh0dXJlKGdsLlRFWFRVUkUwICsgcG9zaXRpb24pO1xuICAgIHRoaXMuY2hlY2tFcnJvcigpO1xuICAgIGdsLmJpbmRUZXh0dXJlKGdsLlRFWFRVUkVfMkQsIHRleHR1cmUpO1xuICAgIHRoaXMuY2hlY2tFcnJvcigpO1xuICAgIGdsLnVuaWZvcm0xaSh1bmlmb3JtSGFuZGxlLCBwb3NpdGlvbik7XG4gICAgdGhpcy5jaGVja0Vycm9yKCk7XG4gIH1cbiAgZHJhdygpOiB2b2lkIHtcbiAgICB0aGlzLmdsLmRyYXdBcnJheXModGhpcy5nbC5UUklBTkdMRV9TVFJJUCwgMCwgNCk7XG4gICAgdGhpcy5jaGVja0Vycm9yKCk7XG4gIH1cbiAgY2hlY2tFcnJvcigpOiB2b2lkIHtcbiAgICBpZiAoZW52LmRlYnVnKSB7XG4gICAgICBjb25zdCBnbCA9IHRoaXMuZ2w7XG4gICAgICBjb25zdCBlcnJvciA9IGdsLmdldEVycm9yKCk7XG4gICAgICBsZXQgbGFiZWwgPSAnJztcbiAgICAgIHN3aXRjaCAoZXJyb3IpIHtcbiAgICAgICAgY2FzZSAoZ2wuTk9fRVJST1IpOlxuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgY2FzZSAoZ2wuSU5WQUxJRF9FTlVNKTpcbiAgICAgICAgICBsYWJlbCA9ICdJTlZBTElEX0VOVU0nO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlIChnbC5JTlZBTElEX1ZBTFVFKTpcbiAgICAgICAgICBsYWJlbCA9ICdJTlZBTElEX1ZBTFVFJztcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSAoZ2wuSU5WQUxJRF9PUEVSQVRJT04pOlxuICAgICAgICAgIGxhYmVsID0gJ0lOVkFMSURfT1BFUkFUSU9OJztcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSAoZ2wuSU5WQUxJRF9GUkFNRUJVRkZFUl9PUEVSQVRJT04pOlxuICAgICAgICAgIGxhYmVsID0gJ0lOVkFMSURfRlJBTUVCVUZGRVJfT1BFUkFUSU9OJztcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSAoZ2wuT1VUX09GX01FTU9SWSk6XG4gICAgICAgICAgbGFiZWwgPSAnT1VUX09GX01FTU9SWSc7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgKGdsLkNPTlRFWFRfTE9TVF9XRUJHTCk6XG4gICAgICAgICAgbGFiZWwgPSAnQ09OVEVYVF9MT1NUX1dFQkdMJztcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICBsYWJlbCA9IGBVbmtub3duIFdlYkdMIEVycm9yOiAke2Vycm9yLnRvU3RyaW5nKDE2KX1gO1xuICAgICAgfVxuICAgICAgdGhyb3cgbmV3IEVycm9yKGxhYmVsKTtcbiAgICB9XG4gIH1cbiAgZGVsZXRlVGV4dHVyZSh0ZXh0dXJlOiBXZWJHTFRleHR1cmUpOiB2b2lkIHtcbiAgICB0aGlzLmdsLmRlbGV0ZVRleHR1cmUodGV4dHVyZSk7XG4gIH1cbiAgZGVsZXRlUHJvZ3JhbShwcm9ncmFtOiBXZWJHTFByb2dyYW0pOiB2b2lkIHtcbiAgICB0aGlzLmdsLmRlbGV0ZVByb2dyYW0ocHJvZ3JhbSk7XG4gIH1cbiAgZ2V0RW5jb2RlcihkYXRhVHlwZTogRW5jb2Rlci5EYXRhVHlwZSwgY2hhbm5lbHM6IG51bWJlciwgdXNhZ2U6IEVuY29kZXIuVXNhZ2UgPSBFbmNvZGVyLlVzYWdlLkRlZmF1bHQpOiBEYXRhRW5jb2RlciB7XG4gICAgaWYgKHRoaXMudmVyc2lvbiA9PT0gMikge1xuICAgICAgcmV0dXJuIG5ldyBEYXRhRW5jb2RlcnMuUmVkRmxvYXQzMkRhdGFFbmNvZGVyKHRoaXMuZ2wgYXMgV2ViR0wyUmVuZGVyaW5nQ29udGV4dCwgY2hhbm5lbHMpO1xuICAgIH1cblxuICAgIHN3aXRjaCAoZGF0YVR5cGUpIHtcbiAgICAgIGNhc2UgJ2Zsb2F0JzpcbiAgICAgICAgaWYgKHVzYWdlID09PSBFbmNvZGVyLlVzYWdlLlVwbG9hZE9ubHkgfHwgdGhpcy5pc1JlbmRlckZsb2F0MzJTdXBwb3J0ZWQpIHtcbiAgICAgICAgICByZXR1cm4gbmV3IERhdGFFbmNvZGVycy5SR0JBRmxvYXREYXRhRW5jb2Rlcih0aGlzLmdsLCBjaGFubmVscyk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgcmV0dXJuIG5ldyBEYXRhRW5jb2RlcnMuUkdCQUZsb2F0RGF0YUVuY29kZXIoXG4gICAgICAgICAgICAgIHRoaXMuZ2wsIGNoYW5uZWxzLCB0aGlzLnRleHR1cmVIYWxmRmxvYXRFeHRlbnNpb24hLkhBTEZfRkxPQVRfT0VTKTtcbiAgICAgICAgfVxuICAgICAgY2FzZSAnaW50JzpcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdub3QgaW1wbGVtZW50ZWQnKTtcbiAgICAgIGNhc2UgJ2J5dGUnOlxuICAgICAgICByZXR1cm4gbmV3IERhdGFFbmNvZGVycy5VaW50OERhdGFFbmNvZGVyKHRoaXMuZ2wsIGNoYW5uZWxzKTtcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgSW52YWxpZCBkYXRhVHlwZTogJHtkYXRhVHlwZX1gKTtcbiAgICB9XG4gIH1cbiAgY2xlYXJBY3RpdmVUZXh0dXJlcygpOiB2b2lkIHtcbiAgICBjb25zdCBnbCA9IHRoaXMuZ2w7XG4gICAgZm9yIChsZXQgdW5pdCA9IDA7IHVuaXQgPCB0aGlzLm1heFRleHR1cmVJbWFnZVVuaXRzOyArK3VuaXQpIHtcbiAgICAgIGdsLmFjdGl2ZVRleHR1cmUoZ2wuVEVYVFVSRTAgKyB1bml0KTtcbiAgICAgIGdsLmJpbmRUZXh0dXJlKGdsLlRFWFRVUkVfMkQsIG51bGwpO1xuICAgIH1cbiAgfVxuICBkaXNwb3NlKCk6IHZvaWQge1xuICAgIGlmICh0aGlzLmRpc3Bvc2VkKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGNvbnN0IGdsID0gdGhpcy5nbDtcbiAgICBnbC5iaW5kRnJhbWVidWZmZXIoZ2wuRlJBTUVCVUZGRVIsIG51bGwpO1xuICAgIGdsLmRlbGV0ZUZyYW1lYnVmZmVyKHRoaXMuZnJhbWVidWZmZXIpO1xuICAgIGdsLmJpbmRCdWZmZXIoZ2wuQVJSQVlfQlVGRkVSLCBudWxsKTtcbiAgICBnbC5kZWxldGVCdWZmZXIodGhpcy52ZXJ0ZXhidWZmZXIpO1xuICAgIGdsLmJpbmRCdWZmZXIoZ2wuRUxFTUVOVF9BUlJBWV9CVUZGRVIsIG51bGwpO1xuICAgIGdsLmZpbmlzaCgpO1xuICAgIHRoaXMuZGlzcG9zZWQgPSB0cnVlO1xuICB9XG5cbiAgcHJpdmF0ZSBjcmVhdGVEZWZhdWx0R2VvbWV0cnkoKTogRmxvYXQzMkFycmF5IHtcbiAgICAvLyBTZXRzIG9mIHgseSx6KD0wKSxzLHQgY29vcmRpbmF0ZXMuXG4gICAgcmV0dXJuIG5ldyBGbG9hdDMyQXJyYXkoW1xuICAgICAgLTEuMCwgMS4wLCAgMC4wLCAwLjAsIDEuMCwgIC8vIHVwcGVyIGxlZnRcbiAgICAgIC0xLjAsIC0xLjAsIDAuMCwgMC4wLCAwLjAsICAvLyBsb3dlciBsZWZ0XG4gICAgICAxLjAsICAxLjAsICAwLjAsIDEuMCwgMS4wLCAgLy8gdXBwZXIgcmlnaHRcbiAgICAgIDEuMCwgIC0xLjAsIDAuMCwgMS4wLCAwLjAgICAvLyBsb3dlciByaWdodFxuICAgIF0pO1xuICB9XG4gIHByaXZhdGUgY3JlYXRlVmVydGV4YnVmZmVyKCk6IFdlYkdMQnVmZmVyIHtcbiAgICBjb25zdCBnbCA9IHRoaXMuZ2w7XG4gICAgY29uc3QgYnVmZmVyID0gZ2wuY3JlYXRlQnVmZmVyKCk7XG4gICAgaWYgKCFidWZmZXIpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignY3JlYXRlQnVmZmVyKCkgcmV0dXJuZWQgbnVsbCcpO1xuICAgIH1cbiAgICBjb25zdCBnZW9tZXRyeSA9IHRoaXMuY3JlYXRlRGVmYXVsdEdlb21ldHJ5KCk7XG4gICAgZ2wuYmluZEJ1ZmZlcihnbC5BUlJBWV9CVUZGRVIsIGJ1ZmZlcik7XG4gICAgZ2wuYnVmZmVyRGF0YShnbC5BUlJBWV9CVUZGRVIsIGdlb21ldHJ5LCBnbC5TVEFUSUNfRFJBVyk7XG4gICAgdGhpcy5jaGVja0Vycm9yKCk7XG4gICAgcmV0dXJuIGJ1ZmZlcjtcbiAgfVxuICBwcml2YXRlIGNyZWF0ZUZyYW1lYnVmZmVyKCk6IFdlYkdMRnJhbWVidWZmZXIge1xuICAgIGNvbnN0IGZiID0gdGhpcy5nbC5jcmVhdGVGcmFtZWJ1ZmZlcigpO1xuICAgIGlmICghZmIpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignY3JlYXRlRnJhbWVidWZmZXIgcmV0dXJuZWQgbnVsbCcpO1xuICAgIH1cbiAgICByZXR1cm4gZmI7XG4gIH1cblxuICBwcml2YXRlIHF1ZXJ5Vml0YWxQYXJhbWV0ZXJzKCk6IHZvaWQge1xuICAgIGNvbnN0IGdsID0gdGhpcy5nbDtcblxuICAgIHRoaXMuaXNGbG9hdFRleHR1cmVBdHRhY2hhYmxlVG9GcmFtZUJ1ZmZlciA9IHRoaXMuY2hlY2tGbG9hdFRleHR1cmVBdHRhY2hhYmxlVG9GcmFtZUJ1ZmZlcigpO1xuICAgIHRoaXMuaXNSZW5kZXJGbG9hdDMyU3VwcG9ydGVkID0gdGhpcy5jaGVja1JlbmRlckZsb2F0MzIoKTtcbiAgICB0aGlzLmlzRmxvYXQzMkRvd25sb2FkU3VwcG9ydGVkID0gdGhpcy5jaGVja0Zsb2F0MzJEb3dubG9hZCgpO1xuXG4gICAgaWYgKHRoaXMudmVyc2lvbiA9PT0gMSAmJiAhdGhpcy50ZXh0dXJlSGFsZkZsb2F0RXh0ZW5zaW9uICYmICF0aGlzLmlzUmVuZGVyRmxvYXQzMlN1cHBvcnRlZCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdib3RoIGZsb2F0MzIgYW5kIGZsb2F0MTYgVGV4dHVyZVR5cGUgYXJlIG5vdCBzdXBwb3J0ZWQnKTtcbiAgICB9XG5cbiAgICB0aGlzLmlzQmxlbmRTdXBwb3J0ZWQgPSAhdGhpcy5pc1JlbmRlckZsb2F0MzJTdXBwb3J0ZWQgfHwgdGhpcy5jaGVja0Zsb2F0MzJCbGVuZCgpO1xuXG4gICAgLy8gdGhpcy5tYXhDb21iaW5lZFRleHR1cmVJbWFnZVVuaXRzID0gZ2wuZ2V0UGFyYW1ldGVyKGdsLk1BWF9DT01CSU5FRF9URVhUVVJFX0lNQUdFX1VOSVRTKTtcbiAgICB0aGlzLm1heFRleHR1cmVTaXplID0gZ2wuZ2V0UGFyYW1ldGVyKGdsLk1BWF9URVhUVVJFX1NJWkUpO1xuICAgIHRoaXMubWF4VGV4dHVyZUltYWdlVW5pdHMgPSBnbC5nZXRQYXJhbWV0ZXIoZ2wuTUFYX1RFWFRVUkVfSU1BR0VfVU5JVFMpO1xuICAgIC8vIHRoaXMubWF4Q3ViZU1hcFRleHR1cmVTaXplID0gZ2wuZ2V0UGFyYW1ldGVyKGdsLk1BWF9DVUJFX01BUF9URVhUVVJFX1NJWkUpO1xuICAgIC8vIHRoaXMuc2hhZGluZ0xhbmd1YWdlVmVyc2lvbiA9IGdsLmdldFBhcmFtZXRlcihnbC5TSEFESU5HX0xBTkdVQUdFX1ZFUlNJT04pO1xuICAgIC8vIHRoaXMud2ViZ2xWZW5kb3IgPSBnbC5nZXRQYXJhbWV0ZXIoZ2wuVkVORE9SKTtcbiAgICAvLyB0aGlzLndlYmdsVmVyc2lvbiA9IGdsLmdldFBhcmFtZXRlcihnbC5WRVJTSU9OKTtcblxuICAgIGlmICh0aGlzLnZlcnNpb24gPT09IDIpIHtcbiAgICAgIC8vIHRoaXMubWF4M0RUZXh0dXJlU2l6ZSA9IGdsLmdldFBhcmFtZXRlcihXZWJHTDJSZW5kZXJpbmdDb250ZXh0Lk1BWF8zRF9URVhUVVJFX1NJWkUpO1xuICAgICAgLy8gdGhpcy5tYXhBcnJheVRleHR1cmVMYXllcnMgPSBnbC5nZXRQYXJhbWV0ZXIoV2ViR0wyUmVuZGVyaW5nQ29udGV4dC5NQVhfQVJSQVlfVEVYVFVSRV9MQVlFUlMpO1xuICAgICAgLy8gdGhpcy5tYXhDb2xvckF0dGFjaG1lbnRzID0gZ2wuZ2V0UGFyYW1ldGVyKFdlYkdMMlJlbmRlcmluZ0NvbnRleHQuTUFYX0NPTE9SX0FUVEFDSE1FTlRTKTtcbiAgICAgIC8vIHRoaXMubWF4RHJhd0J1ZmZlcnMgPSBnbC5nZXRQYXJhbWV0ZXIoV2ViR0wyUmVuZGVyaW5nQ29udGV4dC5NQVhfRFJBV19CVUZGRVJTKTtcbiAgICB9XG4gIH1cbiAgcHJpdmF0ZSBnZXRFeHRlbnNpb25zKCk6IHZvaWQge1xuICAgIGlmICh0aGlzLnZlcnNpb24gPT09IDIpIHtcbiAgICAgIHRoaXMuY29sb3JCdWZmZXJGbG9hdEV4dGVuc2lvbiA9IHRoaXMuZ2wuZ2V0RXh0ZW5zaW9uKCdFWFRfY29sb3JfYnVmZmVyX2Zsb2F0Jyk7XG4gICAgICB0aGlzLmRpc2pvaW50VGltZXJRdWVyeVdlYmdsMkV4dGVuc2lvbiA9IHRoaXMuZ2wuZ2V0RXh0ZW5zaW9uKCdFWFRfZGlzam9pbnRfdGltZXJfcXVlcnlfd2ViZ2wyJyk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMudGV4dHVyZUZsb2F0RXh0ZW5zaW9uID0gdGhpcy5nbC5nZXRFeHRlbnNpb24oJ09FU190ZXh0dXJlX2Zsb2F0Jyk7XG4gICAgICB0aGlzLnRleHR1cmVIYWxmRmxvYXRFeHRlbnNpb24gPSB0aGlzLmdsLmdldEV4dGVuc2lvbignT0VTX3RleHR1cmVfaGFsZl9mbG9hdCcpO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgY2hlY2tGbG9hdFRleHR1cmVBdHRhY2hhYmxlVG9GcmFtZUJ1ZmZlcigpOiBib29sZWFuIHtcbiAgICAvLyB0ZXN0IHdoZXRoZXIgRmxvYXQzMiB0ZXh0dXJlIGlzIHN1cHBvcnRlZDpcbiAgICAvLyBTVEVQLjEgY3JlYXRlIGEgZmxvYXQgdGV4dHVyZVxuICAgIGNvbnN0IGdsID0gdGhpcy5nbDtcbiAgICBjb25zdCB0ZXh0dXJlID0gZ2wuY3JlYXRlVGV4dHVyZSgpO1xuICAgIGdsLmJpbmRUZXh0dXJlKGdsLlRFWFRVUkVfMkQsIHRleHR1cmUpO1xuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbmFtaW5nLWNvbnZlbnRpb25cbiAgICBjb25zdCBpbnRlcm5hbEZvcm1hdCA9IHRoaXMudmVyc2lvbiA9PT0gMiA/IChnbCBhcyB1bmtub3duIGFzIHtSR0JBMzJGOiBudW1iZXJ9KS5SR0JBMzJGIDogZ2wuUkdCQTtcbiAgICBnbC50ZXhJbWFnZTJEKGdsLlRFWFRVUkVfMkQsIDAsIGludGVybmFsRm9ybWF0LCAxLCAxLCAwLCBnbC5SR0JBLCBnbC5GTE9BVCwgbnVsbCk7XG4gICAgLy8gU1RFUC4yIGJpbmQgYSBmcmFtZSBidWZmZXJcbiAgICBjb25zdCBmcmFtZUJ1ZmZlciA9IGdsLmNyZWF0ZUZyYW1lYnVmZmVyKCk7XG4gICAgZ2wuYmluZEZyYW1lYnVmZmVyKGdsLkZSQU1FQlVGRkVSLCBmcmFtZUJ1ZmZlcik7XG4gICAgLy8gU1RFUC4zIGF0dGFjaCB0ZXh0dXJlIHRvIGZyYW1lYnVmZmVyXG4gICAgZ2wuZnJhbWVidWZmZXJUZXh0dXJlMkQoZ2wuRlJBTUVCVUZGRVIsIGdsLkNPTE9SX0FUVEFDSE1FTlQwLCBnbC5URVhUVVJFXzJELCB0ZXh0dXJlLCAwKTtcbiAgICAvLyBTVEVQLjQgdGVzdCB3aGV0aGVyIGZyYW1lYnVmZmVyIGlzIGNvbXBsZXRlXG4gICAgY29uc3QgaXNDb21wbGV0ZSA9IGdsLmNoZWNrRnJhbWVidWZmZXJTdGF0dXMoZ2wuRlJBTUVCVUZGRVIpID09PSBnbC5GUkFNRUJVRkZFUl9DT01QTEVURTtcbiAgICBnbC5iaW5kVGV4dHVyZShnbC5URVhUVVJFXzJELCBudWxsKTtcbiAgICBnbC5iaW5kRnJhbWVidWZmZXIoZ2wuRlJBTUVCVUZGRVIsIG51bGwpO1xuICAgIGdsLmRlbGV0ZVRleHR1cmUodGV4dHVyZSk7XG4gICAgZ2wuZGVsZXRlRnJhbWVidWZmZXIoZnJhbWVCdWZmZXIpO1xuICAgIHJldHVybiBpc0NvbXBsZXRlO1xuICB9XG5cbiAgcHJpdmF0ZSBjaGVja1JlbmRlckZsb2F0MzIoKTogYm9vbGVhbiB7XG4gICAgaWYgKHRoaXMudmVyc2lvbiA9PT0gMikge1xuICAgICAgaWYgKCF0aGlzLmNvbG9yQnVmZmVyRmxvYXRFeHRlbnNpb24pIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICBpZiAoIXRoaXMudGV4dHVyZUZsb2F0RXh0ZW5zaW9uKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuaXNGbG9hdFRleHR1cmVBdHRhY2hhYmxlVG9GcmFtZUJ1ZmZlcjtcbiAgfVxuXG4gIHByaXZhdGUgY2hlY2tGbG9hdDMyRG93bmxvYWQoKTogYm9vbGVhbiB7XG4gICAgaWYgKHRoaXMudmVyc2lvbiA9PT0gMikge1xuICAgICAgaWYgKCF0aGlzLmNvbG9yQnVmZmVyRmxvYXRFeHRlbnNpb24pIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICBpZiAoIXRoaXMudGV4dHVyZUZsb2F0RXh0ZW5zaW9uKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH1cbiAgICAgIGlmICghdGhpcy5nbC5nZXRFeHRlbnNpb24oJ1dFQkdMX2NvbG9yX2J1ZmZlcl9mbG9hdCcpKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuaXNGbG9hdFRleHR1cmVBdHRhY2hhYmxlVG9GcmFtZUJ1ZmZlcjtcbiAgfVxuXG4gIC8qKlxuICAgKiBDaGVjayB3aGV0aGVyIEdMX0JMRU5EIGlzIHN1cHBvcnRlZFxuICAgKi9cbiAgcHJpdmF0ZSBjaGVja0Zsb2F0MzJCbGVuZCgpOiBib29sZWFuIHtcbiAgICAvLyBpdCBsb29rcyBsaWtlIGN1cnJlbnRseSAoMjAxOS0wNS0wOCkgdGhlcmUgaXMgbm8gZWFzeSB3YXkgdG8gZGV0ZWN0IHdoZXRoZXIgQkxFTkQgaXMgc3VwcG9ydGVkXG4gICAgLy8gaHR0cHM6Ly9naXRodWIuY29tL21pY3Jvc29mdC9vbm54anMvaXNzdWVzLzE0NVxuXG4gICAgY29uc3QgZ2wgPSB0aGlzLmdsO1xuXG4gICAgbGV0IHRleHR1cmU6IFdlYkdMVGV4dHVyZXxudWxsfHVuZGVmaW5lZDtcbiAgICBsZXQgZnJhbWVCdWZmZXI6IFdlYkdMRnJhbWVidWZmZXJ8bnVsbHx1bmRlZmluZWQ7XG4gICAgbGV0IHZlcnRleFNoYWRlcjogV2ViR0xTaGFkZXJ8bnVsbHx1bmRlZmluZWQ7XG4gICAgbGV0IGZyYWdtZW50U2hhZGVyOiBXZWJHTFNoYWRlcnxudWxsfHVuZGVmaW5lZDtcbiAgICBsZXQgcHJvZ3JhbTogV2ViR0xQcm9ncmFtfG51bGx8dW5kZWZpbmVkO1xuXG4gICAgdHJ5IHtcbiAgICAgIHRleHR1cmUgPSBnbC5jcmVhdGVUZXh0dXJlKCk7XG4gICAgICBmcmFtZUJ1ZmZlciA9IGdsLmNyZWF0ZUZyYW1lYnVmZmVyKCk7XG4gICAgICBnbC5iaW5kVGV4dHVyZShnbC5URVhUVVJFXzJELCB0ZXh0dXJlKTtcblxuICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uYW1pbmctY29udmVudGlvblxuICAgICAgY29uc3QgaW50ZXJuYWxGb3JtYXQgPSB0aGlzLnZlcnNpb24gPT09IDIgPyAoZ2wgYXMgdW5rbm93biBhcyB7UkdCQTMyRjogbnVtYmVyfSkuUkdCQTMyRiA6IGdsLlJHQkE7XG4gICAgICBnbC50ZXhJbWFnZTJEKGdsLlRFWFRVUkVfMkQsIDAsIGludGVybmFsRm9ybWF0LCAxLCAxLCAwLCBnbC5SR0JBLCBnbC5GTE9BVCwgbnVsbCk7XG5cbiAgICAgIGdsLmJpbmRGcmFtZWJ1ZmZlcihnbC5GUkFNRUJVRkZFUiwgZnJhbWVCdWZmZXIpO1xuICAgICAgZ2wuZnJhbWVidWZmZXJUZXh0dXJlMkQoZ2wuRlJBTUVCVUZGRVIsIGdsLkNPTE9SX0FUVEFDSE1FTlQwLCBnbC5URVhUVVJFXzJELCB0ZXh0dXJlLCAwKTtcblxuICAgICAgZ2wuZW5hYmxlKGdsLkJMRU5EKTtcblxuICAgICAgdmVydGV4U2hhZGVyID0gZ2wuY3JlYXRlU2hhZGVyKGdsLlZFUlRFWF9TSEFERVIpO1xuICAgICAgaWYgKCF2ZXJ0ZXhTaGFkZXIpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuICAgICAgZ2wuc2hhZGVyU291cmNlKHZlcnRleFNoYWRlciwgJ3ZvaWQgbWFpbigpe30nKTtcbiAgICAgIGdsLmNvbXBpbGVTaGFkZXIodmVydGV4U2hhZGVyKTtcblxuICAgICAgZnJhZ21lbnRTaGFkZXIgPSBnbC5jcmVhdGVTaGFkZXIoZ2wuRlJBR01FTlRfU0hBREVSKTtcbiAgICAgIGlmICghZnJhZ21lbnRTaGFkZXIpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuICAgICAgZ2wuc2hhZGVyU291cmNlKGZyYWdtZW50U2hhZGVyLCAncHJlY2lzaW9uIGhpZ2hwIGZsb2F0O3ZvaWQgbWFpbigpe2dsX0ZyYWdDb2xvcj12ZWM0KDAuNSk7fScpO1xuICAgICAgZ2wuY29tcGlsZVNoYWRlcihmcmFnbWVudFNoYWRlcik7XG5cbiAgICAgIHByb2dyYW0gPSBnbC5jcmVhdGVQcm9ncmFtKCk7XG4gICAgICBpZiAoIXByb2dyYW0pIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuICAgICAgZ2wuYXR0YWNoU2hhZGVyKHByb2dyYW0sIHZlcnRleFNoYWRlcik7XG4gICAgICBnbC5hdHRhY2hTaGFkZXIocHJvZ3JhbSwgZnJhZ21lbnRTaGFkZXIpO1xuICAgICAgZ2wubGlua1Byb2dyYW0ocHJvZ3JhbSk7XG4gICAgICBnbC51c2VQcm9ncmFtKHByb2dyYW0pO1xuXG4gICAgICBnbC5kcmF3QXJyYXlzKGdsLlBPSU5UUywgMCwgMSk7XG4gICAgICByZXR1cm4gZ2wuZ2V0RXJyb3IoKSA9PT0gZ2wuTk9fRVJST1I7XG5cbiAgICB9IGZpbmFsbHkge1xuICAgICAgZ2wuZGlzYWJsZShnbC5CTEVORCk7XG5cbiAgICAgIGlmIChwcm9ncmFtKSB7XG4gICAgICAgIGdsLmRlbGV0ZVByb2dyYW0ocHJvZ3JhbSk7XG4gICAgICB9XG4gICAgICBpZiAodmVydGV4U2hhZGVyKSB7XG4gICAgICAgIGdsLmRlbGV0ZVNoYWRlcih2ZXJ0ZXhTaGFkZXIpO1xuICAgICAgfVxuICAgICAgaWYgKGZyYWdtZW50U2hhZGVyKSB7XG4gICAgICAgIGdsLmRlbGV0ZVNoYWRlcihmcmFnbWVudFNoYWRlcik7XG4gICAgICB9XG4gICAgICBpZiAoZnJhbWVCdWZmZXIpIHtcbiAgICAgICAgZ2wuYmluZEZyYW1lYnVmZmVyKGdsLkZSQU1FQlVGRkVSLCBudWxsKTtcbiAgICAgICAgZ2wuZGVsZXRlRnJhbWVidWZmZXIoZnJhbWVCdWZmZXIpO1xuICAgICAgfVxuICAgICAgaWYgKHRleHR1cmUpIHtcbiAgICAgICAgZ2wuYmluZFRleHR1cmUoZ2wuVEVYVFVSRV8yRCwgbnVsbCk7XG4gICAgICAgIGdsLmRlbGV0ZVRleHR1cmUodGV4dHVyZSk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgYmVnaW5UaW1lcigpOiBXZWJHTFF1ZXJ5IHtcbiAgICBpZiAodGhpcy52ZXJzaW9uID09PSAyICYmIHRoaXMuZGlzam9pbnRUaW1lclF1ZXJ5V2ViZ2wyRXh0ZW5zaW9uKSB7XG4gICAgICBjb25zdCBnbDIgPSB0aGlzLmdsIGFzIFdlYkdMMlJlbmRlcmluZ0NvbnRleHQ7XG4gICAgICBjb25zdCBleHQgPSB0aGlzLmRpc2pvaW50VGltZXJRdWVyeVdlYmdsMkV4dGVuc2lvbjtcblxuICAgICAgY29uc3QgcXVlcnkgPSBnbDIuY3JlYXRlUXVlcnkoKSBhcyBXZWJHTFF1ZXJ5O1xuICAgICAgZ2wyLmJlZ2luUXVlcnkoZXh0LlRJTUVfRUxBUFNFRF9FWFQsIHF1ZXJ5KTtcbiAgICAgIHJldHVybiBxdWVyeTtcbiAgICB9IGVsc2Uge1xuICAgICAgLy8gVE9ETzogYWRkIHdlYmdsIDEgaGFuZGxpbmcuXG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ1dlYkdMMSBwcm9maWxpbmcgY3VycmVudGx5IG5vdCBzdXBwb3J0ZWQuJyk7XG4gICAgfVxuICB9XG5cbiAgZW5kVGltZXIoKSB7XG4gICAgaWYgKHRoaXMudmVyc2lvbiA9PT0gMiAmJiB0aGlzLmRpc2pvaW50VGltZXJRdWVyeVdlYmdsMkV4dGVuc2lvbikge1xuICAgICAgY29uc3QgZ2wyID0gdGhpcy5nbCBhcyBXZWJHTDJSZW5kZXJpbmdDb250ZXh0O1xuICAgICAgY29uc3QgZXh0ID0gdGhpcy5kaXNqb2ludFRpbWVyUXVlcnlXZWJnbDJFeHRlbnNpb247XG4gICAgICBnbDIuZW5kUXVlcnkoZXh0LlRJTUVfRUxBUFNFRF9FWFQpO1xuICAgICAgcmV0dXJuO1xuICAgIH0gZWxzZSB7XG4gICAgICAvLyBUT0RPOiBhZGQgd2ViZ2wgMSBoYW5kbGluZy5cbiAgICAgIHRocm93IG5ldyBFcnJvcignV2ViR0wxIHByb2ZpbGluZyBjdXJyZW50bHkgbm90IHN1cHBvcnRlZCcpO1xuICAgIH1cbiAgfVxuXG4gIGlzVGltZXJSZXN1bHRBdmFpbGFibGUocXVlcnk6IFdlYkdMUXVlcnkpOiBib29sZWFuIHtcbiAgICBsZXQgYXZhaWxhYmxlID0gZmFsc2UsIGRpc2pvaW50ID0gZmFsc2U7XG4gICAgaWYgKHRoaXMudmVyc2lvbiA9PT0gMiAmJiB0aGlzLmRpc2pvaW50VGltZXJRdWVyeVdlYmdsMkV4dGVuc2lvbikge1xuICAgICAgY29uc3QgZ2wyID0gdGhpcy5nbCBhcyBXZWJHTDJSZW5kZXJpbmdDb250ZXh0O1xuICAgICAgY29uc3QgZXh0ID0gdGhpcy5kaXNqb2ludFRpbWVyUXVlcnlXZWJnbDJFeHRlbnNpb247XG5cbiAgICAgIGF2YWlsYWJsZSA9IGdsMi5nZXRRdWVyeVBhcmFtZXRlcihxdWVyeSwgZ2wyLlFVRVJZX1JFU1VMVF9BVkFJTEFCTEUpO1xuICAgICAgZGlzam9pbnQgPSBnbDIuZ2V0UGFyYW1ldGVyKGV4dC5HUFVfRElTSk9JTlRfRVhUKTtcbiAgICB9IGVsc2Uge1xuICAgICAgLy8gVE9ETzogYWRkIHdlYmdsIDEgaGFuZGxpbmcuXG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ1dlYkdMMSBwcm9maWxpbmcgY3VycmVudGx5IG5vdCBzdXBwb3J0ZWQnKTtcbiAgICB9XG5cbiAgICByZXR1cm4gYXZhaWxhYmxlICYmICFkaXNqb2ludDtcbiAgfVxuXG4gIGdldFRpbWVyUmVzdWx0KHF1ZXJ5OiBXZWJHTFF1ZXJ5KTogbnVtYmVyIHtcbiAgICBsZXQgdGltZUVsYXBzZWQgPSAwO1xuICAgIGlmICh0aGlzLnZlcnNpb24gPT09IDIpIHtcbiAgICAgIGNvbnN0IGdsMiA9IHRoaXMuZ2wgYXMgV2ViR0wyUmVuZGVyaW5nQ29udGV4dDtcbiAgICAgIHRpbWVFbGFwc2VkID0gZ2wyLmdldFF1ZXJ5UGFyYW1ldGVyKHF1ZXJ5LCBnbDIuUVVFUllfUkVTVUxUKTtcbiAgICAgIGdsMi5kZWxldGVRdWVyeShxdWVyeSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIFRPRE86IGFkZCB3ZWJnbCAxIGhhbmRsaW5nLlxuICAgICAgdGhyb3cgbmV3IEVycm9yKCdXZWJHTDEgcHJvZmlsaW5nIGN1cnJlbnRseSBub3Qgc3VwcG9ydGVkJyk7XG4gICAgfVxuICAgIC8vIHJldHVybiBtaWxpc2Vjb25kc1xuICAgIHJldHVybiB0aW1lRWxhcHNlZCAvIDEwMDAwMDA7XG4gIH1cblxuICBhc3luYyB3YWl0Rm9yUXVlcnlBbmRHZXRUaW1lKHF1ZXJ5OiBXZWJHTFF1ZXJ5KTogUHJvbWlzZTxudW1iZXI+IHtcbiAgICBhd2FpdCByZXBlYXRlZFRyeSgoKSA9PiB0aGlzLmlzVGltZXJSZXN1bHRBdmFpbGFibGUocXVlcnkpKTtcbiAgICByZXR1cm4gdGhpcy5nZXRUaW1lclJlc3VsdChxdWVyeSk7XG4gIH1cblxuICBwdWJsaWMgYXN5bmMgY3JlYXRlQW5kV2FpdEZvckZlbmNlKCk6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IGZlbmNlQ29udGV4dCA9IHRoaXMuY3JlYXRlRmVuY2UodGhpcy5nbCk7XG4gICAgcmV0dXJuIHRoaXMucG9sbEZlbmNlKGZlbmNlQ29udGV4dCk7XG4gIH1cblxuICBwcml2YXRlIGNyZWF0ZUZlbmNlKGdsOiBXZWJHTFJlbmRlcmluZ0NvbnRleHQpOiBGZW5jZUNvbnRleHQge1xuICAgIGxldCBpc0ZlbmNlUGFzc2VkOiAoKSA9PiBib29sZWFuO1xuICAgIGNvbnN0IGdsMiA9IGdsIGFzIFdlYkdMMlJlbmRlcmluZ0NvbnRleHQ7XG4gICAgY29uc3QgcXVlcnkgPSBnbDIuZmVuY2VTeW5jKGdsMi5TWU5DX0dQVV9DT01NQU5EU19DT01QTEVURSwgMCk7XG4gICAgZ2wuZmx1c2goKTtcbiAgICBpZiAocXVlcnkgPT09IG51bGwpIHtcbiAgICAgIGlzRmVuY2VQYXNzZWQgPSAoKSA9PiB0cnVlO1xuICAgIH0gZWxzZSB7XG4gICAgICBpc0ZlbmNlUGFzc2VkID0gKCkgPT4ge1xuICAgICAgICBjb25zdCBzdGF0dXMgPSBnbDIuY2xpZW50V2FpdFN5bmMocXVlcnksIDAsIDApO1xuICAgICAgICByZXR1cm4gc3RhdHVzID09PSBnbDIuQUxSRUFEWV9TSUdOQUxFRCB8fCBzdGF0dXMgPT09IGdsMi5DT05ESVRJT05fU0FUSVNGSUVEO1xuICAgICAgfTtcbiAgICB9XG4gICAgcmV0dXJuIHtxdWVyeSwgaXNGZW5jZVBhc3NlZH07XG4gIH1cblxuICBhc3luYyBwb2xsRmVuY2UoZmVuY2VDb250ZXh0OiBGZW5jZUNvbnRleHQpIHtcbiAgICByZXR1cm4gbmV3IFByb21pc2U8dm9pZD4ocmVzb2x2ZSA9PiB7XG4gICAgICB2b2lkIHRoaXMuYWRkSXRlbVRvUG9sbCgoKSA9PiBmZW5jZUNvbnRleHQuaXNGZW5jZVBhc3NlZCgpLCAoKSA9PiByZXNvbHZlKCkpO1xuICAgIH0pO1xuICB9XG5cbiAgcHJpdmF0ZSBpdGVtc1RvUG9sbDogUG9sbEl0ZW1bXSA9IFtdO1xuXG4gIHBvbGxJdGVtcygpOiB2b2lkIHtcbiAgICAvLyBGaW5kIHRoZSBsYXN0IHF1ZXJ5IHRoYXQgaGFzIGZpbmlzaGVkLlxuICAgIGNvbnN0IGluZGV4ID0gbGluZWFyU2VhcmNoTGFzdFRydWUodGhpcy5pdGVtc1RvUG9sbC5tYXAoeCA9PiB4LmlzRG9uZUZuKSk7XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPD0gaW5kZXg7ICsraSkge1xuICAgICAgY29uc3Qge3Jlc29sdmVGbn0gPSB0aGlzLml0ZW1zVG9Qb2xsW2ldO1xuICAgICAgcmVzb2x2ZUZuKCk7XG4gICAgfVxuICAgIHRoaXMuaXRlbXNUb1BvbGwgPSB0aGlzLml0ZW1zVG9Qb2xsLnNsaWNlKGluZGV4ICsgMSk7XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGFkZEl0ZW1Ub1BvbGwoaXNEb25lRm46ICgpID0+IGJvb2xlYW4sIHJlc29sdmVGbjogKCkgPT4gdm9pZCkge1xuICAgIHRoaXMuaXRlbXNUb1BvbGwucHVzaCh7aXNEb25lRm4sIHJlc29sdmVGbn0pO1xuICAgIGlmICh0aGlzLml0ZW1zVG9Qb2xsLmxlbmd0aCA+IDEpIHtcbiAgICAgIC8vIFdlIGFscmVhZHkgaGF2ZSBhIHJ1bm5pbmcgbG9vcCB0aGF0IHBvbGxzLlxuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICAvLyBTdGFydCBhIG5ldyBsb29wIHRoYXQgcG9sbHMuXG4gICAgYXdhaXQgcmVwZWF0ZWRUcnkoKCkgPT4ge1xuICAgICAgdGhpcy5wb2xsSXRlbXMoKTtcbiAgICAgIC8vIEVuZCB0aGUgbG9vcCBpZiBubyBtb3JlIGl0ZW1zIHRvIHBvbGwuXG4gICAgICByZXR1cm4gdGhpcy5pdGVtc1RvUG9sbC5sZW5ndGggPT09IDA7XG4gICAgfSk7XG4gIH1cbn1cbiIsIi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxuXG5pbXBvcnQge1Nlc3Npb25IYW5kbGVyfSBmcm9tICcuL2JhY2tlbmQnO1xuaW1wb3J0IHtHcmFwaH0gZnJvbSAnLi9ncmFwaCc7XG5pbXBvcnQge0xvZ2dlciwgUHJvZmlsZXJ9IGZyb20gJy4vaW5zdHJ1bWVudCc7XG5pbXBvcnQge09wZXJhdG9yfSBmcm9tICcuL29wZXJhdG9ycyc7XG5pbXBvcnQge1RlbnNvcn0gZnJvbSAnLi90ZW5zb3InO1xuXG5jbGFzcyBLZXJuZWxPcCB7XG4gIGNvbnN0cnVjdG9yKHB1YmxpYyBvcDogT3BlcmF0b3IsIHB1YmxpYyBub2RlOiBHcmFwaC5Ob2RlKSB7fVxufVxuXG5leHBvcnQgY2xhc3MgRXhlY3V0aW9uUGxhbiB7XG4gIGNvbnN0cnVjdG9yKHByaXZhdGUgZ3JhcGg6IEdyYXBoLCBvcHM6IE9wZXJhdG9yW10sIHByaXZhdGUgcHJvZmlsZXI6IFJlYWRvbmx5PFByb2ZpbGVyPikge1xuICAgIHRoaXMuaW5pdGlhbGl6ZShvcHMpO1xuICB9XG5cbiAgaW5pdGlhbGl6ZShvcHM6IE9wZXJhdG9yW10pIHtcbiAgICB0aGlzLnByb2ZpbGVyLmV2ZW50KCdzZXNzaW9uJywgJ0V4ZWN1dGlvblBsYW4uaW5pdGlhbGl6ZScsICgpID0+IHtcbiAgICAgIGNvbnN0IGdyYXBoTm9kZXMgPSB0aGlzLmdyYXBoLmdldE5vZGVzKCk7XG4gICAgICBpZiAoZ3JhcGhOb2Rlcy5sZW5ndGggIT09IG9wcy5sZW5ndGgpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdUaGUgc2l6ZSBvZiBub2RlcyBhbmQgT1BzIGRvIG5vdCBtYXRjaC4nKTtcbiAgICAgIH1cblxuICAgICAgdGhpcy5fb3BzID0gb3BzLm1hcCgob3AsIGkpID0+IG5ldyBLZXJuZWxPcChvcCwgZ3JhcGhOb2Rlc1tpXSkpO1xuICAgICAgdGhpcy5yZXNldCgpO1xuXG4gICAgICAvLyBsb29rIGZvciBzdGFydGVyIG5vZGUocylcbiAgICAgIHRoaXMuX3N0YXJ0ZXIgPSBbXTtcbiAgICAgIHRoaXMuX29wcy5mb3JFYWNoKChvcCwgaSkgPT4ge1xuICAgICAgICBsZXQgcmVzb2x2ZWQgPSB0cnVlO1xuICAgICAgICBmb3IgKGNvbnN0IGlucHV0IG9mIG9wLm5vZGUuaW5wdXRzKSB7XG4gICAgICAgICAgaWYgKFxuICAgICAgICAgICAgICAhdGhpcy5fdmFsdWVzW2lucHV0XSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gbm90IGFuIGluaXRpYWxpemVkIGlucHV0XG4gICAgICAgICAgICAgICYmIHRoaXMuZ3JhcGguZ2V0SW5wdXRJbmRpY2VzKCkuaW5kZXhPZihpbnB1dCkgPT09IC0xICAvLyBub3QgbW9kZWwgaW5wdXRcbiAgICAgICAgICApIHtcbiAgICAgICAgICAgIHJlc29sdmVkID0gZmFsc2U7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHJlc29sdmVkKSB7XG4gICAgICAgICAgdGhpcy5fc3RhcnRlci5wdXNoKGkpO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9KTtcbiAgfVxuXG4gIHJlc2V0KCkge1xuICAgIHRoaXMuX3ZhbHVlcyA9IHRoaXMuZ3JhcGguZ2V0VmFsdWVzKCkubWFwKGkgPT4gaS50ZW5zb3IpO1xuICB9XG5cbiAgYXN5bmMgZXhlY3V0ZShzZXNzaW9uSGFuZGxlcjogU2Vzc2lvbkhhbmRsZXIsIG1vZGVsSW5wdXRzOiBUZW5zb3JbXSk6IFByb21pc2U8VGVuc29yW10+IHtcbiAgICByZXR1cm4gdGhpcy5wcm9maWxlci5ldmVudCgnc2Vzc2lvbicsICdFeGVjdXRpb25QbGFuLmV4ZWN1dGUnLCBhc3luYyAoKSA9PiB7XG4gICAgICAvLyByZXNldCBtZWRpZW0gcmVzdWx0XG4gICAgICB0aGlzLnJlc2V0KCk7XG5cbiAgICAgIC8vIGNyZWF0ZSBpbmZlcmVuY2UgaGFuZGxlclxuICAgICAgY29uc3QgaW5mZXJlbmNlSGFuZGxlciA9IHNlc3Npb25IYW5kbGVyLmNyZWF0ZUluZmVyZW5jZUhhbmRsZXIoKTtcblxuICAgICAgLy8gcG9wdWxhdGUgaW5wdXRzIHZhbHVlXG4gICAgICBjb25zdCBncmFwaElucHV0cyA9IHRoaXMuZ3JhcGguZ2V0SW5wdXRJbmRpY2VzKCk7XG4gICAgICBpZiAobW9kZWxJbnB1dHMubGVuZ3RoICE9PSBncmFwaElucHV0cy5sZW5ndGgpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBudW1iZXIgb2YgaW5wdXQgdGVuc29ycyBkb24ndCBtYXRjaCB0aGUgbnVtYmVyIG9mIGlucHV0cyB0byB0aGUgbW9kZWw6IGFjdHVhbDogJHtcbiAgICAgICAgICAgIG1vZGVsSW5wdXRzLmxlbmd0aH0gZXhwZWN0ZWQ6ICR7Z3JhcGhJbnB1dHMubGVuZ3RofWApO1xuICAgICAgfVxuXG4gICAgICBtb2RlbElucHV0cy5mb3JFYWNoKChpbnB1dCwgaSkgPT4ge1xuICAgICAgICBjb25zdCBpbmRleCA9IGdyYXBoSW5wdXRzW2ldO1xuICAgICAgICB0aGlzLl92YWx1ZXNbaW5kZXhdID0gaW5wdXQ7XG4gICAgICB9KTtcblxuICAgICAgLy8gcHJlcGFyZSBydW5uaW5nIHNlcXVlbmNlXG4gICAgICBjb25zdCBzZXF1ZW5jZTogbnVtYmVyW10gPSB0aGlzLl9zdGFydGVyLnNsaWNlKDApO1xuXG4gICAgICAvLyBleGVjdXRpb24gaXRlcmF0aW9uc1xuICAgICAgY29uc3QgZ3JhcGhWYWx1ZXMgPSB0aGlzLmdyYXBoLmdldFZhbHVlcygpO1xuICAgICAgY29uc3QgZ3JhcGhOb2RlcyA9IHRoaXMuZ3JhcGguZ2V0Tm9kZXMoKTtcblxuICAgICAgbGV0IHJlYXIgPSAwO1xuICAgICAgd2hpbGUgKHJlYXIgPCBzZXF1ZW5jZS5sZW5ndGgpIHtcbiAgICAgICAgY29uc3QgdGhpc09wSW5kZXggPSBzZXF1ZW5jZVtyZWFyKytdO1xuICAgICAgICBjb25zdCB0aGlzT3AgPSB0aGlzLl9vcHNbdGhpc09wSW5kZXhdO1xuXG4gICAgICAgIC8vIGNoZWNrIGlucHV0XG4gICAgICAgIGNvbnN0IGlucHV0TGlzdCA9IHRoaXNPcC5ub2RlLmlucHV0cy5tYXAoaSA9PiB0aGlzLl92YWx1ZXNbaV0pO1xuICAgICAgICBpZiAoaW5wdXRMaXN0LmluZGV4T2YodW5kZWZpbmVkKSAhPT0gLTEpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYHVucmVzb2x2ZWQgaW5wdXQgZGV0ZWN0ZWQ6IG9wOiAke3RoaXNPcC5ub2RlfWApO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gcnVuXG4gICAgICAgIGNvbnN0IGlucHV0VGVuc29ycyA9IGlucHV0TGlzdCBhcyBUZW5zb3JbXTtcbiAgICAgICAgTG9nZ2VyLnZlcmJvc2UoXG4gICAgICAgICAgICAnRXhlY1BsYW4nLFxuICAgICAgICAgICAgYFJ1bmluZyBvcDoke3RoaXNPcC5ub2RlLm5hbWV9ICgke1xuICAgICAgICAgICAgICAgIGlucHV0VGVuc29ycy5tYXAoKHQsIGkpID0+IGAnJHt0aGlzT3Aubm9kZS5pbnB1dHNbaV19JzogJHt0LnR5cGV9WyR7dC5kaW1zLmpvaW4oJywnKX1dYCkuam9pbignLCAnKX0pYCk7XG5cbiAgICAgICAgY29uc3Qgb3V0cHV0TGlzdCA9IGF3YWl0IHRoaXMucHJvZmlsZXIuZXZlbnQoXG4gICAgICAgICAgICAnbm9kZScsIHRoaXNPcC5ub2RlLm5hbWUsIGFzeW5jICgpID0+IHRoaXNPcC5vcC5pbXBsKGluZmVyZW5jZUhhbmRsZXIsIGlucHV0VGVuc29ycywgdGhpc09wLm9wLmNvbnRleHQpKTtcblxuICAgICAgICAvLyBjaGVjayBvdXRwdXRcbiAgICAgICAgaWYgKG91dHB1dExpc3QubGVuZ3RoICE9PSB0aGlzT3Aubm9kZS5vdXRwdXRzLmxlbmd0aCkge1xuICAgICAgICAgIHRocm93IG5ldyBFcnJvcigndGhlIHNpemUgb2Ygb3V0cHV0IGRvZXMgbm90IG1hdGNoIG1vZGVsIGRlZmluaXRpb24uJyk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBmaWxsIHZhbHVlXG4gICAgICAgIG91dHB1dExpc3QuZm9yRWFjaCgob3V0cHV0LCBpKSA9PiB7XG4gICAgICAgICAgY29uc3QgaiA9IHRoaXNPcC5ub2RlLm91dHB1dHNbaV07XG4gICAgICAgICAgaWYgKHRoaXMuX3ZhbHVlc1tqXSkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBvdXRwdXQgWyR7an1dIGFscmVhZHkgaGFzIHZhbHVlOiBvcDoke3RoaXNPcC5ub2RlLm5hbWV9YCk7XG4gICAgICAgICAgfVxuICAgICAgICAgIHRoaXMuX3ZhbHVlc1tqXSA9IG91dHB1dDtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgLy8gcmVzb2x2ZSBkb3duc3RyZWFtIG5vZGVzXG4gICAgICAgIGNvbnN0IGRvd25zdHJlYW1Ob2RlcyA9IG5ldyBTZXQ8bnVtYmVyPigpO1xuICAgICAgICBvdXRwdXRMaXN0LmZvckVhY2goKG91dHB1dCwgaSkgPT4ge1xuICAgICAgICAgIGNvbnN0IGogPSB0aGlzT3Aubm9kZS5vdXRwdXRzW2ldO1xuICAgICAgICAgIGZvciAoY29uc3QgY3VycmVudERvd25zdHJlYW1Ob2RlSW5kZXggb2YgZ3JhcGhWYWx1ZXNbal0udG8pIHtcbiAgICAgICAgICAgIGNvbnN0IGN1cnJlbnREb3duc3RyZWFtTm9kZSA9IGdyYXBoTm9kZXNbY3VycmVudERvd25zdHJlYW1Ob2RlSW5kZXhdO1xuICAgICAgICAgICAgbGV0IHJlc29sdmVkID0gdHJ1ZTtcbiAgICAgICAgICAgIGZvciAoY29uc3QgayBvZiBjdXJyZW50RG93bnN0cmVhbU5vZGUuaW5wdXRzKSB7XG4gICAgICAgICAgICAgIGlmICghdGhpcy5fdmFsdWVzW2tdKSB7XG4gICAgICAgICAgICAgICAgcmVzb2x2ZWQgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHJlc29sdmVkKSB7XG4gICAgICAgICAgICAgIGRvd25zdHJlYW1Ob2Rlcy5hZGQoY3VycmVudERvd25zdHJlYW1Ob2RlSW5kZXgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICAgIHNlcXVlbmNlLnB1c2goLi4uZG93bnN0cmVhbU5vZGVzKTtcbiAgICAgIH1cblxuICAgICAgY29uc3Qgb3V0cHV0OiBUZW5zb3JbXSA9IFtdO1xuICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLmdyYXBoLmdldE91dHB1dEluZGljZXMoKS5sZW5ndGg7IGkrKykge1xuICAgICAgICBjb25zdCBvdXRwdXRJbmRleCA9IHRoaXMuZ3JhcGguZ2V0T3V0cHV0SW5kaWNlcygpW2ldO1xuICAgICAgICBjb25zdCBvdXRwdXRUZW5zb3IgPSB0aGlzLl92YWx1ZXNbb3V0cHV0SW5kZXhdO1xuICAgICAgICBpZiAob3V0cHV0VGVuc29yID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYHJlcXVpcmVkIG91dHB1dCBbJHtvdXRwdXRJbmRleH1dIGRvZXMgbm90IGhhdmUgdmFsdWVgKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAob3V0cHV0SW5kZXggPT09IDApIHtcbiAgICAgICAgICBhd2FpdCBvdXRwdXRUZW5zb3IuZ2V0RGF0YSgpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby11bnVzZWQtZXhwcmVzc2lvbnNcbiAgICAgICAgICBvdXRwdXRUZW5zb3IuZGF0YTtcbiAgICAgICAgfVxuICAgICAgICBvdXRwdXQucHVzaChvdXRwdXRUZW5zb3IpO1xuICAgICAgfVxuICAgICAgTG9nZ2VyLnZlcmJvc2UoJ0V4ZWNQbGFuJywgJ2Rpc3Bvc2luZyBvZiBpbmZlcmVuY2VIYW5kbGVyJyk7XG4gICAgICBpbmZlcmVuY2VIYW5kbGVyLmRpc3Bvc2UoKTtcbiAgICAgIHJldHVybiBvdXRwdXQ7XG4gICAgfSk7XG4gIH1cblxuICBfdmFsdWVzOiBBcnJheTxUZW5zb3J8dW5kZWZpbmVkPjtcbiAgX29wczogS2VybmVsT3BbXTtcbiAgX3N0YXJ0ZXI6IG51bWJlcltdO1xufVxuIiwiLy8gQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXG5cbmltcG9ydCB7b25ueH0gZnJvbSAnb25ueC1wcm90byc7XG5cbmltcG9ydCB7QXR0cmlidXRlfSBmcm9tICcuL2F0dHJpYnV0ZSc7XG5pbXBvcnQge29ubnhydW50aW1lfSBmcm9tICcuL29ydC1zY2hlbWEvb3J0LWdlbmVyYXRlZCc7XG5pbXBvcnQge1RlbnNvcn0gZnJvbSAnLi90ZW5zb3InO1xuaW1wb3J0IHtMb25nVXRpbCwgTUFYX0NMSVAsIE1JTl9DTElQLCBQcm90b1V0aWx9IGZyb20gJy4vdXRpbCc7XG5cbmltcG9ydCBvcnRGYnMgPSBvbm54cnVudGltZS5leHBlcmltZW50YWwuZmJzO1xuXG5leHBvcnQgZGVjbGFyZSBuYW1lc3BhY2UgR3JhcGgge1xuICBleHBvcnQgaW50ZXJmYWNlIFNoYXBlIHtcbiAgICByZWFkb25seSBkaW1zOiByZWFkb25seSBudW1iZXJbXTtcbiAgfVxuICBleHBvcnQgaW50ZXJmYWNlIFZhbHVlVHlwZSB7XG4gICAgcmVhZG9ubHkgdGVuc29yVHlwZTogVGVuc29yLkRhdGFUeXBlO1xuICAgIHJlYWRvbmx5IHNoYXBlOiBTaGFwZTtcbiAgfVxuICBleHBvcnQgaW50ZXJmYWNlIFZhbHVlIHtcbiAgICAvLyB0aGUgdGVuc29yIGRhdGEuIGVtcHR5IGZvciBub24taW5pdGlhbGl6ZWQgaW5wdXRzXG4gICAgcmVhZG9ubHkgdGVuc29yPzogVGVuc29yO1xuXG4gICAgLy8gaW5kZXggdG8gdGhlIE5vZGUgd2hlcmUgdGhlIHZhbHVlIGNvbWVzIGZyb20uIC0xIGZvciBpbml0aWFsaXplci5cbiAgICByZWFkb25seSBmcm9tOiBudW1iZXI7XG5cbiAgICAvLyBpbmRpY2VzIHRvIHRoZSBOb2RlcyB3aGVyZSB0aGUgdmFsdWVzIGdvIHRvLlxuICAgIHJlYWRvbmx5IHRvOiByZWFkb25seSBudW1iZXJbXTtcblxuICAgIC8vIHZhbHVlIHR5cGUgc3BlY2lmaWNhdGlvbi4gZW1wdHkgZm9yIG5vbi1pbnB1dCB2YWx1ZXMuXG4gICAgcmVhZG9ubHkgdHlwZT86IFZhbHVlVHlwZTtcbiAgfVxuICBleHBvcnQgaW50ZXJmYWNlIE5vZGUge1xuICAgIC8vIG5hbWUgb2YgdGhlIG5vZGVcbiAgICByZWFkb25seSBuYW1lOiBzdHJpbmc7XG5cbiAgICAvLyB0aGUgb3BlcmF0b3IgdHlwZVxuICAgIHJlYWRvbmx5IG9wVHlwZTogc3RyaW5nO1xuXG4gICAgLy8gaW5kaWNlcyB0byB0aGUgVmFsdWVzIHdoZXJlIHRoZSBpbnB1dHMgY29tZSBmcm9tLlxuICAgIHJlYWRvbmx5IGlucHV0czogcmVhZG9ubHkgbnVtYmVyW107XG5cbiAgICAvLyBpbmRpY2VzIHRvIHRoZSBWYWx1ZXMgd2hlcmUgdGhlIG91dHB1cyBnbyB0by5cbiAgICByZWFkb25seSBvdXRwdXRzOiByZWFkb25seSBudW1iZXJbXTtcblxuICAgIC8vIHRoZSBhdHRyaWJ1dGVzIHRoYXQgdXNlZCBieSB0aGUgb3BlcmF0b3JcbiAgICByZWFkb25seSBhdHRyaWJ1dGVzOiBBdHRyaWJ1dGU7XG4gIH1cblxuICAvKipcbiAgICogYSBUcmFuc2Zvcm1lciBpcyBhbiBpbnN0YW5jZSB0aGF0IGFsbG93cyBhbGwgcG9zc2libGUgdHJhbnNmb3JtYXRpb24gb3BlcmF0aW9ucyB0aGF0IGFwcGxpZWQgdG8gYSBncmFwaFxuICAgKi9cbiAgZXhwb3J0IGludGVyZmFjZSBUcmFuc2Zvcm1lciB7XG4gICAgcmVtb3ZlQWxsSWRlbnRpdHlOb2RlcygpOiB2b2lkO1xuICAgIHJlbW92ZUFsbERyb3BvdXROb2RlcygpOiB2b2lkO1xuICAgIGZ1c2VDb252QWN0aXZhdGlvbk5vZGVzKCk6IHZvaWQ7XG4gICAgLy8gVE9ETzogYWRkIGdlbmVyaWMgZnVuY3Rpb25zIHRvIG1hbmlwdWxhdGUgdGhlIGdyYXBoXG4gIH1cblxuICAvLyBhbiBpbml0aWFsaXplciBjYW4gdXNlIHRyYW5zZm9ybWVyIHRvIHRyYW5zZm9ybSB0aGUgZ3JhcGhcbiAgZXhwb3J0IGludGVyZmFjZSBJbml0aWFsaXplciB7XG4gICAgdHJhbnNmb3JtR3JhcGgodHJhbnNmb3JtZXI6IFRyYW5zZm9ybWVyKTogdm9pZDtcbiAgfVxufVxuXG4vLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXJlZGVjbGFyZVxuZXhwb3J0IGludGVyZmFjZSBHcmFwaCB7XG4gIGdldElucHV0SW5kaWNlcygpOiByZWFkb25seSBudW1iZXJbXTtcbiAgZ2V0SW5wdXROYW1lcygpOiByZWFkb25seSBzdHJpbmdbXTtcbiAgZ2V0T3V0cHV0SW5kaWNlcygpOiByZWFkb25seSBudW1iZXJbXTtcbiAgZ2V0T3V0cHV0TmFtZXMoKTogcmVhZG9ubHkgc3RyaW5nW107XG4gIGdldFZhbHVlcygpOiByZWFkb25seSBHcmFwaC5WYWx1ZVtdO1xuICBnZXROb2RlcygpOiByZWFkb25seSBHcmFwaC5Ob2RlW107XG59XG5cbi8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbmFtaW5nLWNvbnZlbnRpb24sIEB0eXBlc2NyaXB0LWVzbGludC9uby1yZWRlY2xhcmVcbmV4cG9ydCBjb25zdCBHcmFwaCA9IHtcbiAgLyoqXG4gICAqIGNvbnN0cnVjdCBhIGdyYXBoIGZyb20gYSBncmFwaCBwcm90b2J1ZiB0eXBlXG4gICAqL1xuICBmcm9tOiAoZ3JhcGhQcm90bzogb25ueC5JR3JhcGhQcm90b3xvcnRGYnMuR3JhcGgsIGluaXRpYWxpemVyPzogR3JhcGguSW5pdGlhbGl6ZXIpID0+XG4gICAgICBuZXcgR3JhcGhJbXBsKGdyYXBoUHJvdG8sIGluaXRpYWxpemVyKSxcbn07XG5cbmNsYXNzIFZhbHVlIGltcGxlbWVudHMgR3JhcGguVmFsdWUge1xuICBjb25zdHJ1Y3Rvcih2YWx1ZUluZm8/OiBvbm54LklWYWx1ZUluZm9Qcm90bykge1xuICAgIHRoaXMuX2Zyb20gPSB1bmRlZmluZWQ7XG4gICAgdGhpcy5fdG8gPSBbXTtcbiAgICB0aGlzLnRlbnNvciA9IHVuZGVmaW5lZDtcbiAgICB0aGlzLnR5cGUgPSB1bmRlZmluZWQ7XG5cbiAgICBpZiAodmFsdWVJbmZvKSB7XG4gICAgICB0aGlzLnR5cGUgPSBQcm90b1V0aWwudGVuc29yVmFsdWVUeXBlRnJvbVByb3RvKHZhbHVlSW5mby50eXBlIS50ZW5zb3JUeXBlISk7XG4gICAgfVxuICB9XG5cbiAgX2Zyb20/OiBudW1iZXI7ICAvLyAtMSByZXByZXNlbnQgZnJvbSBpbml0aWFsaXplclxuICBnZXQgZnJvbSgpIHtcbiAgICByZXR1cm4gdGhpcy5fZnJvbSE7XG4gIH1cbiAgX3RvOiBudW1iZXJbXTtcbiAgZ2V0IHRvKCkge1xuICAgIHJldHVybiB0aGlzLl90bztcbiAgfVxuICB0eXBlPzogR3JhcGguVmFsdWVUeXBlO1xuICB0ZW5zb3I/OiBUZW5zb3I7XG59XG5cbmNsYXNzIE5vZGUgaW1wbGVtZW50cyBHcmFwaC5Ob2RlIHtcbiAgY29uc3RydWN0b3IoX25vZGVQcm90bzogb25ueC5JTm9kZVByb3RvfG9ydEZicy5Ob2RlLCBuYW1lPzogc3RyaW5nKSB7XG4gICAgaWYgKF9ub2RlUHJvdG8gaW5zdGFuY2VvZiBvbm54Lk5vZGVQcm90bykge1xuICAgICAgdGhpcy5uYW1lID0gX25vZGVQcm90by5uYW1lO1xuICAgICAgdGhpcy5vcFR5cGUgPSBfbm9kZVByb3RvLm9wVHlwZTtcbiAgICAgIHRoaXMuYXR0cmlidXRlcyA9IG5ldyBBdHRyaWJ1dGUoX25vZGVQcm90by5hdHRyaWJ1dGUpO1xuICAgIH0gZWxzZSBpZiAoX25vZGVQcm90byBpbnN0YW5jZW9mIG9ydEZicy5Ob2RlKSB7XG4gICAgICB0aGlzLm5hbWUgPSBuYW1lID8/IF9ub2RlUHJvdG8ubmFtZSgpITtcbiAgICAgIHRoaXMub3BUeXBlID0gX25vZGVQcm90by5vcFR5cGUoKSE7XG4gICAgICB0aGlzLmF0dHJpYnV0ZXMgPSBuZXcgQXR0cmlidXRlKFByb3RvVXRpbC50ZW5zb3JBdHRyaWJ1dGVzRnJvbU9SVEZvcm1hdChfbm9kZVByb3RvKSk7XG4gICAgfVxuXG4gICAgdGhpcy5pbnB1dHMgPSBbXTtcbiAgICB0aGlzLm91dHB1dHMgPSBbXTtcbiAgICB0aGlzLmV4ZWN1dGVOb2RlID0gdHJ1ZTtcbiAgfVxuXG4gIG5hbWU6IHN0cmluZztcbiAgb3BUeXBlOiBzdHJpbmc7XG4gIGlucHV0czogbnVtYmVyW107XG4gIG91dHB1dHM6IG51bWJlcltdO1xuICBhdHRyaWJ1dGVzOiBBdHRyaWJ1dGU7XG4gIGV4ZWN1dGVOb2RlOiBib29sZWFuO1xufVxuXG5jbGFzcyBHcmFwaEltcGwgaW1wbGVtZW50cyBHcmFwaCwgR3JhcGguVHJhbnNmb3JtZXIge1xuICBwcml2YXRlIF9hbGxEYXRhOiBWYWx1ZVtdO1xuXG4gIHByaXZhdGUgX2FsbElucHV0SW5kaWNlczogbnVtYmVyW107XG4gIHByaXZhdGUgX2FsbElucHV0TmFtZXM6IHN0cmluZ1tdO1xuXG4gIHByaXZhdGUgX2FsbE91dHB1dEluZGljZXM6IG51bWJlcltdO1xuICBwcml2YXRlIF9hbGxPdXRwdXROYW1lczogc3RyaW5nW107XG5cbiAgcHJpdmF0ZSBfbm9kZXM6IE5vZGVbXTtcblxuICBjb25zdHJ1Y3RvcihncmFwaDogb25ueC5JR3JhcGhQcm90b3xvcnRGYnMuR3JhcGgsIGdyYXBoSW5pdGlhbGl6ZXI/OiBHcmFwaC5Jbml0aWFsaXplcikge1xuICAgIGlmICghZ3JhcGgpIHtcbiAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ2dyYXBoIGlzIGVtcHR5Jyk7XG4gICAgfVxuXG4gICAgLy8gYnVpbGQgdGhlIGdyYXBoIC0gd2lsbCB0aHJvdyBleGNlcHRpb25zIGlmIHNvbWV0aGluZyBmYXRhbCBpcyBkZXRlY3RlZFxuICAgIHRoaXMuYnVpbGRHcmFwaChncmFwaCk7XG5cbiAgICAvLyBleGVjdXRlIGFueSB0cmFuc2Zvcm1hdGlvbiBsb2dpYyBmb3IgdGhlIGdyYXBoIChpZiBhcHBsaWNhYmxlKVxuICAgIHRoaXMudHJhbnNmb3JtR3JhcGgoZ3JhcGhJbml0aWFsaXplcik7XG5cbiAgICAvLyBjaGVjayBmb3IgY3ljbGVzIGFuZCBvdGhlciBpbmNvbnNpc3RlbmNpZXMgLSB3aWxsIHRocm93IGV4Y2VwdGlvbnMgaWYgc29tZXRoaW5nIGZhdGFsIGlzIGRldGVjdGVkXG4gICAgdGhpcy5jaGVja0lzQWN5Y2xpYygpO1xuICB9XG5cbiAgZ2V0SW5wdXRJbmRpY2VzKCk6IHJlYWRvbmx5IG51bWJlcltdIHtcbiAgICByZXR1cm4gdGhpcy5fYWxsSW5wdXRJbmRpY2VzO1xuICB9XG5cbiAgZ2V0SW5wdXROYW1lcygpOiByZWFkb25seSBzdHJpbmdbXSB7XG4gICAgcmV0dXJuIHRoaXMuX2FsbElucHV0TmFtZXM7XG4gIH1cblxuICBnZXRPdXRwdXRJbmRpY2VzKCk6IHJlYWRvbmx5IG51bWJlcltdIHtcbiAgICByZXR1cm4gdGhpcy5fYWxsT3V0cHV0SW5kaWNlcztcbiAgfVxuXG4gIGdldE91dHB1dE5hbWVzKCk6IHJlYWRvbmx5IHN0cmluZ1tdIHtcbiAgICByZXR1cm4gdGhpcy5fYWxsT3V0cHV0TmFtZXM7XG4gIH1cblxuICBnZXRWYWx1ZXMoKTogcmVhZG9ubHkgR3JhcGguVmFsdWVbXSB7XG4gICAgcmV0dXJuIHRoaXMuX2FsbERhdGE7XG4gIH1cblxuICBnZXROb2RlcygpOiByZWFkb25seSBHcmFwaC5Ob2RlW10ge1xuICAgIHJldHVybiB0aGlzLl9ub2RlcztcbiAgfVxuXG4gIHByaXZhdGUgYnVpbGRHcmFwaChncmFwaDogb25ueC5JR3JhcGhQcm90b3xvcnRGYnMuR3JhcGgpIHtcbiAgICAvLyBidWlsZCB0aGUgZ3JhcGggLSB3aWxsIHRocm93IGV4Y2VwdGlvbnMgaWYgc29tZXRoaW5nIGZhdGFsIGlzIGRldGVjdGVkXG4gICAgaWYgKGdyYXBoIGluc3RhbmNlb2Ygb25ueC5HcmFwaFByb3RvKSB7XG4gICAgICB0aGlzLmJ1aWxkR3JhcGhGcm9tT25ueEZvcm1hdChncmFwaCk7XG4gICAgfSBlbHNlIGlmIChncmFwaCBpbnN0YW5jZW9mIG9ydEZicy5HcmFwaCkge1xuICAgICAgdGhpcy5idWlsZEdyYXBoRnJvbU9ydEZvcm1hdChncmFwaCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ0dyYXBoIHR5cGUgaXMgbm90IHN1cHBvcnRlZC4nKTtcbiAgICB9XG4gIH1cbiAgcHJpdmF0ZSBidWlsZEdyYXBoRnJvbU9ubnhGb3JtYXQoZ3JhcGg6IG9ubnguSUdyYXBoUHJvdG8pIHtcbiAgICBjb25zdCBkYXRhSW5kaWNlcyA9IG5ldyBNYXA8c3RyaW5nLCBudW1iZXI+KCk7XG4gICAgdGhpcy5fYWxsRGF0YSA9IFtdO1xuXG4gICAgdGhpcy5fYWxsSW5wdXRJbmRpY2VzID0gW107XG4gICAgdGhpcy5fYWxsSW5wdXROYW1lcyA9IFtdO1xuXG4gICAgdGhpcy5fYWxsT3V0cHV0SW5kaWNlcyA9IFtdO1xuICAgIHRoaXMuX2FsbE91dHB1dE5hbWVzID0gW107XG5cbiAgICB0aGlzLl9ub2RlcyA9IFtdO1xuXG4gICAgY29uc3Qgbm9kZXNJbmRpY2VzID0gbmV3IE1hcDxzdHJpbmcsIG51bWJlcj4oKTtcblxuICAgIC8vIHNjYW4gYWxsIGlucHV0c1xuICAgIGlmICghZ3JhcGguaW5wdXQpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignbWlzc2luZyBpbmZvcm1hdGlvbiBpbiBncmFwaDogaW5wdXQnKTtcbiAgICB9XG4gICAgY29uc3QgaW5wdXRWYWx1ZU5hbWVzID0gW107XG4gICAgZm9yIChjb25zdCBpIG9mIGdyYXBoLmlucHV0KSB7XG4gICAgICBpZiAoZGF0YUluZGljZXMuaGFzKGkubmFtZSEpKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgZHVwbGljYXRlZCBpbnB1dCBuYW1lOiAke2kubmFtZX1gKTtcbiAgICAgIH1cbiAgICAgIGNvbnN0IGN1cnJlbnRJbmRleCA9IHRoaXMuX2FsbERhdGEucHVzaChuZXcgVmFsdWUoaSkpIC0gMTtcbiAgICAgIGRhdGFJbmRpY2VzLnNldChpLm5hbWUhLCBjdXJyZW50SW5kZXgpO1xuICAgICAgaW5wdXRWYWx1ZU5hbWVzLnB1c2goaS5uYW1lISk7XG4gICAgfVxuXG4gICAgLy8gc2NhbiBhbGwgaW5pdGlhbGl6ZXJzXG4gICAgaWYgKCFncmFwaC5pbml0aWFsaXplcikge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdtaXNzaW5nIGluZm9ybWF0aW9uIGluIGdyYXBoOiBpbml0aWFsaXplcicpO1xuICAgIH1cbiAgICBmb3IgKGNvbnN0IGkgb2YgZ3JhcGguaW5pdGlhbGl6ZXIpIHtcbiAgICAgIGxldCBpbmRleCA9IGRhdGFJbmRpY2VzLmdldChpLm5hbWUhKTtcbiAgICAgIGlmIChpbmRleCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIGNvbnN0IHZhbHVlID0gbmV3IFZhbHVlKCk7XG4gICAgICAgIHZhbHVlLnR5cGUgPSB7XG4gICAgICAgICAgc2hhcGU6IHtkaW1zOiBQcm90b1V0aWwudGVuc29yRGltc0Zyb21Qcm90byhpLmRpbXMhKX0sXG4gICAgICAgICAgdGVuc29yVHlwZTogUHJvdG9VdGlsLnRlbnNvckRhdGFUeXBlRnJvbVByb3RvKGkuZGF0YVR5cGUhKVxuICAgICAgICB9O1xuICAgICAgICBpbmRleCA9IHRoaXMuX2FsbERhdGEucHVzaCh2YWx1ZSkgLSAxO1xuICAgICAgICBkYXRhSW5kaWNlcy5zZXQoaS5uYW1lISwgaW5kZXgpO1xuICAgICAgfVxuICAgICAgdGhpcy5fYWxsRGF0YVtpbmRleF0uX2Zyb20gPSAtMTtcbiAgICAgIHRoaXMuX2FsbERhdGFbaW5kZXhdLnRlbnNvciA9IFRlbnNvci5mcm9tUHJvdG8oaSk7XG4gICAgfVxuXG4gICAgLy8gZmlsdGVyIG91dCBpbnB1dCBpbmRpY2VzXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLl9hbGxEYXRhLmxlbmd0aDsgaSsrKSB7XG4gICAgICBpZiAoIXRoaXMuX2FsbERhdGFbaV0udGVuc29yKSB7XG4gICAgICAgIHRoaXMuX2FsbElucHV0SW5kaWNlcy5wdXNoKGkpO1xuICAgICAgICB0aGlzLl9hbGxJbnB1dE5hbWVzLnB1c2goaW5wdXRWYWx1ZU5hbWVzW2ldKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBzY2FuIGFsbCBvdXRwdXRzXG4gICAgaWYgKCFncmFwaC5vdXRwdXQpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignbWlzc2luZyBpbmZvcm1hdGlvbiBpbiBncmFwaDogb3V0cHV0Jyk7XG4gICAgfVxuICAgIGZvciAoY29uc3QgaSBvZiBncmFwaC5vdXRwdXQpIHtcbiAgICAgIGlmIChkYXRhSW5kaWNlcy5oYXMoaS5uYW1lISkpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBkdXBsaWNhdGVkIG91dHB1dCBuYW1lOiAke2kubmFtZX1gKTtcbiAgICAgIH1cbiAgICAgIGNvbnN0IGN1cnJlbnRJbmRleCA9IHRoaXMuX2FsbERhdGEucHVzaChuZXcgVmFsdWUoaSkpIC0gMTtcbiAgICAgIGRhdGFJbmRpY2VzLnNldChpLm5hbWUhLCBjdXJyZW50SW5kZXgpO1xuICAgICAgdGhpcy5fYWxsT3V0cHV0SW5kaWNlcy5wdXNoKGN1cnJlbnRJbmRleCk7XG4gICAgICB0aGlzLl9hbGxPdXRwdXROYW1lcy5wdXNoKGkubmFtZSEpO1xuICAgIH1cblxuICAgIC8vIHNjYW4gYWxsIG5vZGVzXG4gICAgaWYgKCFncmFwaC5ub2RlKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ21pc3NpbmcgaW5mb3JtYXRpb24gaW4gZ3JhcGg6IG5vZGUnKTtcbiAgICB9XG4gICAgZm9yIChjb25zdCBub2RlUHJvdG8gb2YgZ3JhcGgubm9kZSkge1xuICAgICAgaWYgKCFub2RlUHJvdG8ubmFtZSkge1xuICAgICAgICAvLyBhc3NpZ24gYSBuYW1lIHRvIHRoZSBub2RlIGlmIGl0IGRvZXNuJ3QgaGF2ZSBvbmVcbiAgICAgICAgZm9yIChsZXQgcGljayA9IDA7OyBwaWNrKyspIHtcbiAgICAgICAgICBjb25zdCBuYW1lID0gYHVubmFtZWRfJHtub2RlUHJvdG8ub3BUeXBlfV8ke3BpY2t9YDtcbiAgICAgICAgICBpZiAoIW5vZGVzSW5kaWNlcy5oYXMobmFtZSkpIHtcbiAgICAgICAgICAgIG5vZGVQcm90by5uYW1lID0gbmFtZTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBpZiAobm9kZXNJbmRpY2VzLmhhcyhub2RlUHJvdG8ubmFtZSkpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBkdXBsaWNhdGVkIG5vZGUgbmFtZTogJHtub2RlUHJvdG8ubmFtZX1gKTtcbiAgICAgIH1cbiAgICAgIGNvbnN0IGN1cnJlbnRJbmRleCA9IHRoaXMuX25vZGVzLnB1c2gobmV3IE5vZGUobm9kZVByb3RvKSkgLSAxO1xuICAgICAgbm9kZXNJbmRpY2VzLnNldChub2RlUHJvdG8ubmFtZSwgY3VycmVudEluZGV4KTtcbiAgICB9XG5cbiAgICAvLyBzY2FuIG5vZGUncyBvdXRwdXRzXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLl9ub2Rlcy5sZW5ndGg7IGkrKykge1xuICAgICAgY29uc3Qgbm9kZSA9IHRoaXMuX25vZGVzW2ldO1xuICAgICAgY29uc3Qgbm9kZVByb3RvID0gZ3JhcGgubm9kZVtpXTtcbiAgICAgIGlmICghbm9kZVByb3RvLm91dHB1dCkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYG1pc3Npbmcgb3V0cHV0IGZvciBub2RlOiAke25vZGVQcm90by5uYW1lfWApO1xuICAgICAgfVxuICAgICAgZm9yIChjb25zdCBvdXRwdXQgb2Ygbm9kZVByb3RvLm91dHB1dCkge1xuICAgICAgICBsZXQgZGF0YUluZGV4ID0gZGF0YUluZGljZXMuZ2V0KG91dHB1dCk7XG4gICAgICAgIGlmICh0eXBlb2YgZGF0YUluZGV4ID09PSAndW5kZWZpbmVkJykge1xuICAgICAgICAgIGRhdGFJbmRleCA9IHRoaXMuX2FsbERhdGEucHVzaChuZXcgVmFsdWUoKSkgLSAxO1xuICAgICAgICAgIGRhdGFJbmRpY2VzLnNldChvdXRwdXQsIGRhdGFJbmRleCk7XG4gICAgICAgIH1cbiAgICAgICAgbm9kZS5vdXRwdXRzLnB1c2goZGF0YUluZGV4KTtcblxuICAgICAgICBpZiAodGhpcy5fYWxsRGF0YVtkYXRhSW5kZXhdLl9mcm9tICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYG11bHRpcGxlIG5vZGVzIG91dHB1dCB0byBvbmUgZGF0YSB2YWx1ZTogJHtkYXRhSW5kZXh9YCk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5fYWxsRGF0YVtkYXRhSW5kZXhdLl9mcm9tID0gaTtcblxuICAgICAgICAvLyBmb3IgdGhlICdDb25zdGFudCcgb3BlcmF0b3IsIGp1c3QgY3JlYXRlIGEgbmV3IGVkZ2UgaW4gdGhlIGdyYXBoIGNvcnJlc3BvbmRpbmcgdG8gdGhlICdvdXRwdXQnIG9mIHRoZVxuICAgICAgICAvLyBvcGVyYXRvciBhbmQgaWdub3JlIHRoZSBub2RlIGZyb20gdGhlIGdyYXBoXG4gICAgICAgIGlmIChub2RlUHJvdG8ub3BUeXBlID09PSAnQ29uc3RhbnQnKSB7XG4gICAgICAgICAgaWYgKCFub2RlUHJvdG8uYXR0cmlidXRlIHx8IG5vZGVQcm90by5hdHRyaWJ1dGUubGVuZ3RoICE9PSAxIHx8ICFub2RlUHJvdG8uYXR0cmlidXRlWzBdLnQpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignbWlzc2luZyBhdHRyaWJ1dGVzIG9yIG1pc3NpbmcgdGVuc29yIHZhbHVlIGluIGF0dHJpYnV0ZXMgZm9yIHRoaXMgQ29uc3RhbnQgb3BlcmF0b3InKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgaWYgKCFub2RlUHJvdG8ub3V0cHV0IHx8IG5vZGVQcm90by5vdXRwdXQubGVuZ3RoICE9PSAxKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ21pc3Npbmcgb3V0cHV0IG9yIGluY29ycmVjdCBudW1iZXIgb2Ygb3V0cHV0cyBmb3IgdGhpcyBDb25zdGFudCBvcGVyYXRvcicpO1xuICAgICAgICAgIH1cbiAgICAgICAgICBub2RlLm91dHB1dHMucG9wKCk7XG4gICAgICAgICAgbm9kZS5leGVjdXRlTm9kZSA9IGZhbHNlO1xuXG4gICAgICAgICAgdGhpcy5fYWxsRGF0YVtkYXRhSW5kZXhdLl9mcm9tID0gLTE7XG4gICAgICAgICAgdGhpcy5fYWxsRGF0YVtkYXRhSW5kZXhdLnRlbnNvciA9IFRlbnNvci5mcm9tUHJvdG8obm9kZVByb3RvLmF0dHJpYnV0ZVswXS50KTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cblxuICAgIC8vIHNjYW4gbm9kZSdzIGlucHV0c1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy5fbm9kZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgIGNvbnN0IG5vZGUgPSB0aGlzLl9ub2Rlc1tpXTtcbiAgICAgIGNvbnN0IG5vZGVQcm90byA9IGdyYXBoLm5vZGVbaV07XG5cbiAgICAgIGlmICghbm9kZVByb3RvLmlucHV0KSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgbWlzc2luZyBpbnB1dCBmb3Igbm9kZTogJHtub2RlUHJvdG8ubmFtZX1gKTtcbiAgICAgIH1cbiAgICAgIGZvciAoY29uc3QgaW5wdXQgb2Ygbm9kZVByb3RvLmlucHV0KSB7XG4gICAgICAgIGNvbnN0IGRhdGFJbmRleCA9IGRhdGFJbmRpY2VzLmdldChpbnB1dCk7XG4gICAgICAgIGlmICh0eXBlb2YgZGF0YUluZGV4ID09PSAndW5kZWZpbmVkJykge1xuICAgICAgICAgIC8vIGhhbmRsZSBleGNlcHRpb24gd2hlbiBvcHNldCA+IDkgYW5kIHJvaSBub3QgZ2l2ZW5cbiAgICAgICAgICBpZiAoaW5wdXQgPT09ICcnICYmIG5vZGVQcm90by5pbnB1dC5sZW5ndGggPT09IDMgJiYgbm9kZVByb3RvLm9wVHlwZSA9PT0gJ1Jlc2l6ZScpIHtcbiAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgIH1cbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYHVucmVjb2duaXplZCBpbnB1dCAnJHtpbnB1dH0nIGZvciBub2RlOiAke25vZGVQcm90by5uYW1lfWApO1xuICAgICAgICB9XG4gICAgICAgIG5vZGUuaW5wdXRzLnB1c2goZGF0YUluZGV4KTtcblxuICAgICAgICB0aGlzLl9hbGxEYXRhW2RhdGFJbmRleF0uX3RvLnB1c2goaSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHRydWU7XG4gIH1cblxuICBwcml2YXRlIGJ1aWxkR3JhcGhGcm9tT3J0Rm9ybWF0KGdyYXBoOiBvcnRGYnMuR3JhcGgpIHtcbiAgICBjb25zdCBkYXRhSW5kaWNlcyA9IG5ldyBNYXA8c3RyaW5nLCBudW1iZXI+KCk7XG4gICAgdGhpcy5fYWxsRGF0YSA9IFtdO1xuXG4gICAgdGhpcy5fYWxsSW5wdXRJbmRpY2VzID0gW107XG4gICAgdGhpcy5fYWxsSW5wdXROYW1lcyA9IFtdO1xuXG4gICAgdGhpcy5fYWxsT3V0cHV0SW5kaWNlcyA9IFtdO1xuICAgIHRoaXMuX2FsbE91dHB1dE5hbWVzID0gW107XG5cbiAgICB0aGlzLl9ub2RlcyA9IFtdO1xuXG4gICAgY29uc3Qgbm9kZXNJbmRpY2VzID0gbmV3IE1hcDxzdHJpbmcsIG51bWJlcj4oKTtcblxuICAgIC8vIHNjYW4gYWxsIGlucHV0c1xuICAgIGNvbnN0IGlucHV0VmFsdWVOYW1lcyA9IFtdO1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgZ3JhcGguaW5wdXRzTGVuZ3RoKCk7IGkrKykge1xuICAgICAgY29uc3QgaW5wdXROYW1lID0gZ3JhcGguaW5wdXRzKGkpO1xuICAgICAgaWYgKGRhdGFJbmRpY2VzLmhhcyhpbnB1dE5hbWUpKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgZHVwbGljYXRlZCBpbnB1dCBuYW1lOiAke2lucHV0TmFtZX1gKTtcbiAgICAgIH1cbiAgICAgIC8vIEZpbmQgdGhlIGlucHV0IHR5cGVJbmZvIGZyb20gbm9kZWFyZ3NcbiAgICAgIGZvciAobGV0IGogPSAwOyBqIDwgZ3JhcGgubm9kZUFyZ3NMZW5ndGgoKTsgaisrKSB7XG4gICAgICAgIGlmIChncmFwaC5ub2RlQXJncyhqKT8ubmFtZSgpID09PSBpbnB1dE5hbWUpIHtcbiAgICAgICAgICBjb25zdCB2YWx1ZSA9IG5ldyBWYWx1ZSgpO1xuICAgICAgICAgIGNvbnN0IHZhbHVlVHlwZSA9IGdyYXBoLm5vZGVBcmdzKGopPy50eXBlKCk/LnZhbHVlVHlwZSgpO1xuICAgICAgICAgIGlmICh2YWx1ZVR5cGUgIT09IG9ydEZicy5UeXBlSW5mb1ZhbHVlLnRlbnNvcl90eXBlKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1VuZXhwZWN0ZWQgdmFsdWUgdHlwZSBmb3IgdGhlIG5vZGVBcmcuJyk7XG4gICAgICAgICAgfVxuICAgICAgICAgIGNvbnN0IHZhbHVlSW5mbyA9IGdyYXBoLm5vZGVBcmdzKGopIS50eXBlKCkhLnZhbHVlKG5ldyBvcnRGYnMuVGVuc29yVHlwZUFuZFNoYXBlKCkpITtcbiAgICAgICAgICBjb25zdCB0eXBlID0gUHJvdG9VdGlsLnRlbnNvckRhdGFUeXBlRnJvbVByb3RvKHZhbHVlSW5mby5lbGVtVHlwZSgpKTtcbiAgICAgICAgICBjb25zdCBzaGFwZSA9IHZhbHVlSW5mby5zaGFwZSgpITtcbiAgICAgICAgICBjb25zdCBkaW1zID0gW107XG4gICAgICAgICAgZm9yIChsZXQgayA9IDA7IGsgPCBzaGFwZS5kaW1MZW5ndGgoKSE7IGsrKykge1xuICAgICAgICAgICAgZGltcy5wdXNoKExvbmdVdGlsLmxvbmdUb051bWJlcihzaGFwZS5kaW0oaykhLnZhbHVlKCkhLmRpbVZhbHVlKCkhKSk7XG4gICAgICAgICAgfVxuICAgICAgICAgIHZhbHVlLnR5cGUgPSB7c2hhcGU6IHtkaW1zfSwgdGVuc29yVHlwZTogdHlwZX07XG4gICAgICAgICAgY29uc3QgY3VycmVudEluZGV4ID0gdGhpcy5fYWxsRGF0YS5wdXNoKHZhbHVlKSAtIDE7XG4gICAgICAgICAgZGF0YUluZGljZXMuc2V0KGlucHV0TmFtZSwgY3VycmVudEluZGV4KTtcbiAgICAgICAgICBpbnB1dFZhbHVlTmFtZXMucHVzaChpbnB1dE5hbWUpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICAgIC8vIGNoZWNrIGluaXRpYWxpemVyc1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgZ3JhcGguaW5pdGlhbGl6ZXJzTGVuZ3RoKCk7IGkrKykge1xuICAgICAgY29uc3QgaW5pdGlhbGl6ZXIgPSBncmFwaC5pbml0aWFsaXplcnMoaSkhO1xuICAgICAgbGV0IGluZGV4ID0gZGF0YUluZGljZXMuZ2V0KGluaXRpYWxpemVyLm5hbWUoKSEpO1xuICAgICAgaWYgKGluZGV4ID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgY29uc3QgdmFsdWUgPSBuZXcgVmFsdWUoKTtcbiAgICAgICAgY29uc3QgZGltcyA9IFByb3RvVXRpbC50ZW5zb3JEaW1zRnJvbU9SVEZvcm1hdChpbml0aWFsaXplcik7XG4gICAgICAgIGNvbnN0IHR5cGUgPSBQcm90b1V0aWwudGVuc29yRGF0YVR5cGVGcm9tUHJvdG8oaW5pdGlhbGl6ZXIuZGF0YVR5cGUoKSk7XG4gICAgICAgIHZhbHVlLnR5cGUgPSB7c2hhcGU6IHtkaW1zfSwgdGVuc29yVHlwZTogdHlwZX07XG4gICAgICAgIGluZGV4ID0gdGhpcy5fYWxsRGF0YS5wdXNoKHZhbHVlKSAtIDE7XG4gICAgICAgIGRhdGFJbmRpY2VzLnNldChpbml0aWFsaXplci5uYW1lKCkhLCBpbmRleCk7XG4gICAgICB9XG4gICAgICB0aGlzLl9hbGxEYXRhW2luZGV4XS5fZnJvbSA9IC0xO1xuICAgICAgdGhpcy5fYWxsRGF0YVtpbmRleF0udGVuc29yID0gVGVuc29yLmZyb21PcnRUZW5zb3IoaW5pdGlhbGl6ZXIpO1xuICAgIH1cblxuICAgIC8vIGZpbHRlciBvdXQgaW5wdXQgaW5kaWNlc1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy5fYWxsRGF0YS5sZW5ndGg7IGkrKykge1xuICAgICAgaWYgKCF0aGlzLl9hbGxEYXRhW2ldLnRlbnNvcikge1xuICAgICAgICB0aGlzLl9hbGxJbnB1dEluZGljZXMucHVzaChpKTtcbiAgICAgICAgdGhpcy5fYWxsSW5wdXROYW1lcy5wdXNoKGlucHV0VmFsdWVOYW1lc1tpXSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gc2NhbiBhbGwgb3V0cHV0c1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgZ3JhcGgub3V0cHV0c0xlbmd0aCgpOyBpKyspIHtcbiAgICAgIGNvbnN0IG91dHB1dE5hbWUgPSBncmFwaC5vdXRwdXRzKGkpO1xuICAgICAgaWYgKGRhdGFJbmRpY2VzLmhhcyhvdXRwdXROYW1lKSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYGR1cGxpY2F0ZWQgb3V0cHV0IG5hbWU6ICR7b3V0cHV0TmFtZX1gKTtcbiAgICAgIH1cbiAgICAgIGNvbnN0IGN1cnJlbnRJbmRleCA9IHRoaXMuX2FsbERhdGEucHVzaChuZXcgVmFsdWUoKSkgLSAxO1xuICAgICAgZGF0YUluZGljZXMuc2V0KG91dHB1dE5hbWUsIGN1cnJlbnRJbmRleCk7XG4gICAgICB0aGlzLl9hbGxPdXRwdXRJbmRpY2VzLnB1c2goY3VycmVudEluZGV4KTtcbiAgICAgIHRoaXMuX2FsbE91dHB1dE5hbWVzLnB1c2gob3V0cHV0TmFtZSk7XG4gICAgfVxuXG4gICAgLy8gc2NhbiBhbGwgbm9kZXNcbiAgICBpZiAoIWdyYXBoLm5vZGVzKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ21pc3NpbmcgaW5mb3JtYXRpb24gaW4gZ3JhcGg6IG5vZGUnKTtcbiAgICB9XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBncmFwaC5ub2Rlc0xlbmd0aCgpOyBpKyspIHtcbiAgICAgIGNvbnN0IG5vZGVQcm90byA9IGdyYXBoLm5vZGVzKGkpO1xuICAgICAgbGV0IG5hbWUgPSBub2RlUHJvdG8hLm5hbWUoKTtcbiAgICAgIGlmICghbmFtZSkge1xuICAgICAgICAvLyBhc3NpZ24gYSBuYW1lIHRvIHRoZSBub2RlIGlmIGl0IGRvZXNuJ3QgaGF2ZSBvbmVcbiAgICAgICAgZm9yIChsZXQgcGljayA9IDA7OyBwaWNrKyspIHtcbiAgICAgICAgICBuYW1lID0gYHVubmFtZWRfJHtub2RlUHJvdG8hLm9wVHlwZSgpfV8ke3BpY2t9YDtcbiAgICAgICAgICBpZiAoIW5vZGVzSW5kaWNlcy5oYXMobmFtZSkpIHtcbiAgICAgICAgICAgIC8vIGFuIHVuaXF1ZSBuYW1lIGlzIGZvdW5kLiBicmVhay5cbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBpZiAobm9kZXNJbmRpY2VzLmhhcyhuYW1lKSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYGR1cGxpY2F0ZWQgbm9kZSBuYW1lOiAke25hbWV9YCk7XG4gICAgICB9XG4gICAgICBjb25zdCBjdXJyZW50SW5kZXggPSB0aGlzLl9ub2Rlcy5wdXNoKG5ldyBOb2RlKG5vZGVQcm90byEsIG5hbWUpKSAtIDE7XG4gICAgICBub2Rlc0luZGljZXMuc2V0KG5hbWUsIGN1cnJlbnRJbmRleCk7XG4gICAgfVxuXG4gICAgLy8gc2NhbiBub2RlJ3Mgb3V0cHV0c1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy5fbm9kZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgIGNvbnN0IG5vZGUgPSB0aGlzLl9ub2Rlc1tpXTtcbiAgICAgIGNvbnN0IG5vZGVQcm90byA9IGdyYXBoLm5vZGVzKGkpO1xuICAgICAgaWYgKG5vZGVQcm90byA9PSBudWxsKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgTm8gbm9kZSBleGlzdHMgYXQgaW5kZXggJHtpfWApO1xuICAgICAgfVxuICAgICAgaWYgKG5vZGVQcm90bz8ub3V0cHV0c0xlbmd0aCgpID09PSAwKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgbWlzc2luZyBvdXRwdXQgZm9yIG5vZGU6ICR7bm9kZVByb3RvLm5hbWV9YCk7XG4gICAgICB9XG4gICAgICBmb3IgKGxldCBqID0gMDsgaiA8IG5vZGVQcm90bz8ub3V0cHV0c0xlbmd0aCgpOyBqKyspIHtcbiAgICAgICAgY29uc3Qgb3V0cHV0ID0gbm9kZVByb3RvPy5vdXRwdXRzKGopO1xuICAgICAgICBsZXQgZGF0YUluZGV4ID0gZGF0YUluZGljZXMuZ2V0KG91dHB1dCk7XG4gICAgICAgIGlmICh0eXBlb2YgZGF0YUluZGV4ID09PSAndW5kZWZpbmVkJykge1xuICAgICAgICAgIGRhdGFJbmRleCA9IHRoaXMuX2FsbERhdGEucHVzaChuZXcgVmFsdWUoKSkgLSAxO1xuICAgICAgICAgIGRhdGFJbmRpY2VzLnNldChvdXRwdXQsIGRhdGFJbmRleCk7XG4gICAgICAgIH1cbiAgICAgICAgbm9kZS5vdXRwdXRzLnB1c2goZGF0YUluZGV4KTtcblxuICAgICAgICBpZiAodGhpcy5fYWxsRGF0YVtkYXRhSW5kZXhdLl9mcm9tICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYG11bHRpcGxlIG5vZGVzIG91dHB1dCB0byBvbmUgZGF0YSB2YWx1ZTogJHtkYXRhSW5kZXh9YCk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5fYWxsRGF0YVtkYXRhSW5kZXhdLl9mcm9tID0gaTtcblxuICAgICAgICAvLyBmb3IgdGhlICdDb25zdGFudCcgb3BlcmF0b3IsIGp1c3QgY3JlYXRlIGEgbmV3IGVkZ2UgaW4gdGhlIGdyYXBoIGNvcnJlc3BvbmRpbmcgdG8gdGhlICdvdXRwdXQnIG9mIHRoZVxuICAgICAgICAvLyBvcGVyYXRvciBhbmQgaWdub3JlIHRoZSBub2RlIGZyb20gdGhlIGdyYXBoXG4gICAgICAgIGlmIChub2RlUHJvdG8ub3BUeXBlKCkgPT09ICdDb25zdGFudCcpIHtcbiAgICAgICAgICBpZiAobm9kZVByb3RvLmF0dHJpYnV0ZXNMZW5ndGgoKSAhPT0gMSB8fCAhbm9kZVByb3RvLmF0dHJpYnV0ZXMoMCkhLnQoKSkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdtaXNzaW5nIGF0dHJpYnV0ZXMgb3IgbWlzc2luZyB0ZW5zb3IgdmFsdWUgaW4gYXR0cmlidXRlcyBmb3IgdGhpcyBDb25zdGFudCBvcGVyYXRvcicpO1xuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAobm9kZVByb3RvLm91dHB1dHNMZW5ndGgoKSAhPT0gMSkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdtaXNzaW5nIG91dHB1dCBvciBpbmNvcnJlY3QgbnVtYmVyIG9mIG91dHB1dHMgZm9yIHRoaXMgQ29uc3RhbnQgb3BlcmF0b3InKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgbm9kZS5vdXRwdXRzLnBvcCgpO1xuICAgICAgICAgIG5vZGUuZXhlY3V0ZU5vZGUgPSBmYWxzZTtcblxuICAgICAgICAgIHRoaXMuX2FsbERhdGFbZGF0YUluZGV4XS5fZnJvbSA9IC0xO1xuICAgICAgICAgIHRoaXMuX2FsbERhdGFbZGF0YUluZGV4XS50ZW5zb3IgPSBUZW5zb3IuZnJvbU9ydFRlbnNvcihub2RlUHJvdG8uYXR0cmlidXRlcygwKSEudCgpISk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBzY2FuIG5vZGUncyBpbnB1dHNcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRoaXMuX25vZGVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICBjb25zdCBub2RlID0gdGhpcy5fbm9kZXNbaV07XG4gICAgICBjb25zdCBub2RlUHJvdG8gPSBncmFwaC5ub2RlcyhpKSE7XG5cbiAgICAgIGlmIChub2RlUHJvdG8uaW5wdXRzTGVuZ3RoKCkgPT09IDApIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBtaXNzaW5nIGlucHV0IGZvciBub2RlOiAke25vZGVQcm90by5uYW1lfWApO1xuICAgICAgfVxuICAgICAgZm9yIChsZXQgaiA9IDA7IGogPCBub2RlUHJvdG8uaW5wdXRzTGVuZ3RoKCkhOyBqKyspIHtcbiAgICAgICAgY29uc3QgaW5wdXQgPSBub2RlUHJvdG8uaW5wdXRzKGopITtcbiAgICAgICAgY29uc3QgZGF0YUluZGV4ID0gZGF0YUluZGljZXMuZ2V0KGlucHV0KTtcbiAgICAgICAgaWYgKHR5cGVvZiBkYXRhSW5kZXggPT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGB1bnJlY29nbml6ZWQgaW5wdXQgJyR7aW5wdXR9JyBmb3Igbm9kZTogJHtub2RlUHJvdG8hLm5hbWUoKX1gKTtcbiAgICAgICAgfVxuICAgICAgICBub2RlLmlucHV0cy5wdXNoKGRhdGFJbmRleCk7XG5cbiAgICAgICAgdGhpcy5fYWxsRGF0YVtkYXRhSW5kZXhdLl90by5wdXNoKGkpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgY2hlY2tJc0FjeWNsaWMoKSB7XG4gICAgLy8gZ28gdGhyb3VnaCB0aGUgZ3JhcGggYW5kIGNoZWNrIGZvciBjeWNsZXMgb3Igb3RoZXIgZmF0YWwgaW5jb25zaXN0ZW5jaWVzXG4gICAgY29uc3Qgc3RhcnRlcnM6IFNldDxudW1iZXI+ID0gbmV3IFNldDxudW1iZXI+KCk7XG4gICAgdGhpcy5fYWxsSW5wdXRJbmRpY2VzLmZvckVhY2goaSA9PiB7XG4gICAgICBjb25zdCBkYXRhID0gdGhpcy5fYWxsRGF0YVtpXTtcbiAgICAgIGRhdGEuX3RvLmZvckVhY2goaiA9PiB7XG4gICAgICAgIHN0YXJ0ZXJzLmFkZChqKTtcbiAgICAgIH0pO1xuICAgIH0pO1xuXG4gICAgLy8gSXRlcmF0aXZlIERGUyB0byBjaGVjayBmb3IgY3ljbGVzXG4gICAgY29uc3Qgbm9kZXNTdGFjayA9IEFycmF5LmZyb20oc3RhcnRlcnMpO1xuICAgIGNvbnN0IG5vZGVzU3RhdGUgPSBuZXcgQXJyYXk8c3RyaW5nPih0aGlzLl9ub2Rlcy5sZW5ndGgpLmZpbGwoJ3doaXRlJyk7XG5cbiAgICB3aGlsZSAobm9kZXNTdGFjay5sZW5ndGggPiAwKSB7XG4gICAgICBjb25zdCBub2RlSW5kZXggPSBub2Rlc1N0YWNrLnBvcCgpITtcbiAgICAgIC8vIHRoaXMgbm9kZSBoYXMgbm93IGJlZW4gcHJvY2Vzc2VkIGNvbXBsZXRlbHkuIE1hcmsgdGhpcyBub2RlICdibGFjaycgdG8gZGVub3RlIHRoaXMuXG4gICAgICBpZiAobm9kZXNTdGF0ZVtub2RlSW5kZXhdID09PSAnZ3JheScpIHtcbiAgICAgICAgbm9kZXNTdGF0ZVtub2RlSW5kZXhdID0gJ2JsYWNrJztcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIC8vIHRoaXMgbm9kZSBpcyB1bmRlciBwcm9jZXNzaW5nIHN0YWdlLiBtYXJrIHRoaXMgbm9kZSAnZ3JheScgdG8gZGVub3RlIHRoaXMuXG4gICAgICAgIG5vZGVzU3RhY2sucHVzaChub2RlSW5kZXgpO1xuICAgICAgICBub2Rlc1N0YXRlW25vZGVJbmRleF0gPSAnZ3JheSc7XG5cbiAgICAgICAgdGhpcy5fbm9kZXNbbm9kZUluZGV4XS5vdXRwdXRzLmZvckVhY2goKG91dGdvaW5nRWRnZUluZGV4KSA9PiB7XG4gICAgICAgICAgY29uc3QgZGF0YSA9IHRoaXMuX2FsbERhdGFbb3V0Z29pbmdFZGdlSW5kZXhdO1xuICAgICAgICAgIGlmICh0eXBlb2YgZGF0YS50ZW5zb3IgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ25vZGUgb3V0cHV0cyBzaG91bGQgbm90IGJlIGluaXRpYWxpemVkJyk7XG4gICAgICAgICAgfVxuICAgICAgICAgIGlmIChkYXRhLl9mcm9tICE9PSBub2RlSW5kZXgpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignZnJvbSBwcm9wZXJ0eSBvZiB0aGUgVmFsdWUgb2JqZWN0IGRvZXNuXFwndCBtYXRjaCBpbmRleCBvZiBOb2RlIGJlaW5nIHByb2Nlc3NlZCcpO1xuICAgICAgICAgIH1cbiAgICAgICAgICBkYXRhLl90by5mb3JFYWNoKChkb3duc3RyZWFtTm9kZUluZGV4KSA9PiB7XG4gICAgICAgICAgICAvLyBiYWNrIGVkZ2UgZm91bmQgLSBjeWNsaWNcbiAgICAgICAgICAgIGlmIChub2Rlc1N0YXRlW2Rvd25zdHJlYW1Ob2RlSW5kZXhdID09PSAnZ3JheScpIHtcbiAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdtb2RlbCBncmFwaCBpcyBjeWNsaWMnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIHRyZWUgZWRnZSBmb3VuZCAtIGNvbnRpbnVlIHByb2Nlc3NpbmcgYnkgYWRkaW5nIGl0IHRvIHN0YWNrXG4gICAgICAgICAgICBlbHNlIGlmIChub2Rlc1N0YXRlW2Rvd25zdHJlYW1Ob2RlSW5kZXhdID09PSAnd2hpdGUnKSB7XG4gICAgICAgICAgICAgIG5vZGVzU3RhY2sucHVzaChkb3duc3RyZWFtTm9kZUluZGV4KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSB0cmFuc2Zvcm1HcmFwaChncmFwaEluaXRpYWxpemVyPzogR3JhcGguSW5pdGlhbGl6ZXIpOiB2b2lkIHtcbiAgICAvLyBhcHBseSBjb21tb24gdHJhbnNmb3JtXG4gICAgdGhpcy5yZW1vdmVBbGxJZGVudGl0eU5vZGVzKCk7XG4gICAgdGhpcy5yZW1vdmVBbGxEcm9wb3V0Tm9kZXMoKTtcbiAgICB0aGlzLmZ1c2VDb252QWN0aXZhdGlvbk5vZGVzKCk7XG4gICAgLy8gYXBwbHkgaW5pdGlhbGl6ZXIgc3BlY2lmaWMgdHJhbnNmb3JtXG4gICAgaWYgKGdyYXBoSW5pdGlhbGl6ZXIpIHtcbiAgICAgIGdyYXBoSW5pdGlhbGl6ZXIudHJhbnNmb3JtR3JhcGgodGhpcyk7XG4gICAgfVxuXG4gICAgLy8gZmluYWxpemUgZ3JhcGhcbiAgICB0aGlzLmZpbmFsaXplR3JhcGgoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBmaW5hbGl6ZSB0aGUgZ3JhcGguXG4gICAqXG4gICAqIHRoaXMgZnVuY3Rpb24gc2hvdWxkIGJlIGNhbGxlZCBhZnRlciBhbGwgdGhlIHRyYW5zZm9ybWF0aW9uIGNvbXBsZXRlZC5cbiAgICogdGhpcyBmdW5jdGlvbiByZW1vdmVzIGFsbCB1bm5lY2Vzc2FyeSBub2RlcyBhbmQgdmFsdWVzIGZyb20gdGhlIGdyYXBoXG4gICAqL1xuICBmaW5hbGl6ZUdyYXBoKCkge1xuICAgIGxldCBvZmZzZXQgPSAwO1xuICAgIC8vIGRlbGV0ZSBhbGwgbm9kZXMgdGhhdCBhcmUgbm90IGJlaW5nIGV4ZWN1dGVkXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLl9ub2Rlcy5sZW5ndGg7IGkrKykge1xuICAgICAgaWYgKCF0aGlzLl9ub2Rlc1tpXS5leGVjdXRlTm9kZSkge1xuICAgICAgICAvLyBkZWxldGUgdGhpcyBub2RlIGFuZCBzaGlmdCBhbGwgc3Vic2VxdWVudCBub2RlcyB1cFxuICAgICAgICBvZmZzZXQrKztcbiAgICAgICAgLy8gZGVsZXRlIGFsbCBvdXRwdXQgdmFsdWVzXG4gICAgICAgIHRoaXMuX25vZGVzW2ldLm91dHB1dHMuZm9yRWFjaChpbmQgPT4ge1xuICAgICAgICAgIHRoaXMuX2FsbERhdGFbaW5kXS5fZnJvbSA9IC0yO1xuICAgICAgICB9KTtcbiAgICAgICAgdGhpcy5fbm9kZXMuc3BsaWNlKGksIDEpO1xuICAgICAgICBpLS07XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuICAgICAgaWYgKG9mZnNldCA+IDApIHtcbiAgICAgICAgLy8gdXBkYXRlIHRoZSB2YWx1ZSB0YWJsZVxuICAgICAgICB0aGlzLl9ub2Rlc1tpXS5pbnB1dHMuZm9yRWFjaCh2YWx1ZSA9PiB7XG4gICAgICAgICAgY29uc3QgaW5kID0gdGhpcy5fYWxsRGF0YVt2YWx1ZV0uX3RvLmluZGV4T2YoaSArIG9mZnNldCk7XG4gICAgICAgICAgaWYgKGluZCAhPT0gLTEpIHtcbiAgICAgICAgICAgIHRoaXMuX2FsbERhdGFbdmFsdWVdLl90b1tpbmRdID0gaTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICB0aGlzLl9ub2Rlc1tpXS5vdXRwdXRzLmZvckVhY2godmFsdWUgPT4ge1xuICAgICAgICAgIGlmICh0aGlzLl9hbGxEYXRhW3ZhbHVlXS5fZnJvbSAmJiB0aGlzLl9hbGxEYXRhW3ZhbHVlXS5fZnJvbSEgPT09IGkgKyBvZmZzZXQpIHtcbiAgICAgICAgICAgIHRoaXMuX2FsbERhdGFbdmFsdWVdLl9mcm9tISA9IGk7XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICB9XG4gICAgb2Zmc2V0ID0gMDtcbiAgICAvLyBkZWxldGUgYWxsIHZhbHVlcyB0aGF0IGFyZSBub3QgYmVpbmcgcmVmZXJlbmNlZFxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy5fYWxsRGF0YS5sZW5ndGg7IGkrKykge1xuICAgICAgLy8gaWYgY3VycmVudCB2YWx1ZSBpcyBuZWl0aGVyIGxpbmtlZCB0byBuZXh0IG5vZGUsIG5vciBhbiBvdXRwdXQgdmFsdWUsIHJlbW92ZSBpdC5cbiAgICAgIGlmICh0aGlzLl9hbGxEYXRhW2ldLmZyb20gPT09IC0yICYmIHRoaXMuX2FsbE91dHB1dEluZGljZXMuaW5kZXhPZihpICsgb2Zmc2V0KSA9PT0gLTEpIHtcbiAgICAgICAgb2Zmc2V0Kys7XG4gICAgICAgIHRoaXMuX2FsbERhdGEuc3BsaWNlKGksIDEpO1xuICAgICAgICBpLS07XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuICAgICAgaWYgKG9mZnNldCA+IDApIHtcbiAgICAgICAgbGV0IGluZCA9IC0xO1xuICAgICAgICAvLyBpZiBjdXJyZW50IHZhbHVlIGlzIG5laXRoZXIgYW4gaW5wdXQgdmFsdWUgbm9yIGFuIGluaXRpYWxpemVyLCBmaW5kIHRoZSBub2RlIGl0J3NcbiAgICAgICAgLy8gY29taW5nIGZyb20gYW5kIHVwZGF0ZSB0aGUgY29ycmVzcG9uZGluZyBub2RlIG91dHB1dFxuICAgICAgICBpZiAodGhpcy5fYWxsRGF0YVtpXS5mcm9tICE9PSB1bmRlZmluZWQgJiYgdGhpcy5fYWxsRGF0YVtpXS5mcm9tICE9PSAtMSkge1xuICAgICAgICAgIGluZCA9IHRoaXMuX25vZGVzW3RoaXMuX2FsbERhdGFbaV0uZnJvbV0ub3V0cHV0cy5pbmRleE9mKGkgKyBvZmZzZXQpO1xuICAgICAgICAgIGlmIChpbmQgIT09IC0xKSB7XG4gICAgICAgICAgICB0aGlzLl9ub2Rlc1t0aGlzLl9hbGxEYXRhW2ldLmZyb21dLm91dHB1dHNbaW5kXSA9IGk7XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIC8vIGlmIGN1cnJlbnQgdmFsdWUgaXMgYW4gaW5wdXQgdmFsdWUsIHVwZGF0ZSBpdHMgcmVmZXJlbmNlIGluIGlucHV0SW5kaWNlc1xuICAgICAgICAgIGluZCA9IHRoaXMuX2FsbElucHV0SW5kaWNlcy5pbmRleE9mKGkgKyBvZmZzZXQpO1xuICAgICAgICAgIGlmIChpbmQgIT09IC0xKSB7XG4gICAgICAgICAgICB0aGlzLl9hbGxJbnB1dEluZGljZXNbaW5kXSA9IGk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgLy8gZmluZCB0aGUgbm9kZSB0aGF0IHRoZSBjdXJyZW50IHZhbHVlIGlzIGxpbmtpbmcgdG8gYW5kIHVwZGF0ZSBpdHMgaW5wdXQgcmVmZXJlbmNlXG4gICAgICAgIHRoaXMuX2FsbERhdGFbaV0udG8uZm9yRWFjaChub2RlID0+IHtcbiAgICAgICAgICBpbmQgPSB0aGlzLl9ub2Rlc1tub2RlXS5pbnB1dHMuaW5kZXhPZihpICsgb2Zmc2V0KTtcbiAgICAgICAgICBpZiAoaW5kICE9PSAtMSkge1xuICAgICAgICAgICAgdGhpcy5fbm9kZXNbbm9kZV0uaW5wdXRzW2luZF0gPSBpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICAgIGlmICh0aGlzLl9hbGxEYXRhW2ldLnRvLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgIC8vIGlmIGN1cnJlbnQgdmFsdWUgaXMgYSBncmFwaCBvdXRwdXQsIHVwZGF0ZSBpdHMgcmVmZXJlbmNlIGluIG91dHB1dEluZGljZXNcbiAgICAgICAgICBpbmQgPSB0aGlzLl9hbGxPdXRwdXRJbmRpY2VzLmluZGV4T2YoaSArIG9mZnNldCk7XG4gICAgICAgICAgaWYgKGluZCAhPT0gLTEpIHtcbiAgICAgICAgICAgIHRoaXMuX2FsbE91dHB1dEluZGljZXNbaW5kXSA9IGk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIERlbGV0ZSB0aGUgc3BlY2lmZWQgbm9kZS4gQXNzdW1lIHRoZSBub2RlIGhhcyBvbmUgaW5jb21pbmcgaW5wdXQgYW5kIHRoZSBmaXJzdCBvdXRwdXQgY29ubmVjdGVkIHRvIG90aGVyIG5vZGVzLlxuICAgKiBBbiBpbnB1dCB2YWxpZGF0aW9uIG11c3QgYmUgZG9uZSBiZWZvcmUgY2FsbGluZyB0aGlzIGZ1bmN0aW9uLlxuICAgKiBAcGFyYW0gbm9kZUluZGV4IFRoZSBpbmRleCBvZiBub2RlIHRvIGJlIGRlbGV0ZWRcbiAgICovXG4gIHByaXZhdGUgZGVsZXRlTm9kZShub2RlSW5kZXg6IG51bWJlcikge1xuICAgIGNvbnN0IG5vZGUgPSB0aGlzLl9ub2Rlc1tub2RlSW5kZXhdO1xuICAgIGlmIChub2RlLm91dHB1dHMubGVuZ3RoID4gMSkge1xuICAgICAgZm9yIChsZXQgaSA9IDE7IGkgPCBub2RlLm91dHB1dHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgaWYgKHRoaXMuX2FsbERhdGFbbm9kZS5vdXRwdXRzW2ldXS50by5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdOb2RlIGRlbGV0aW9uIHdpdGggbW9yZSB0aGFuIG9uZSBvdXRwdXQgY29ubmVjdGVkIHRvIG90aGVyIG5vZGVzIGlzIG5vdCBzdXBwb3J0ZWQuICcpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gdGhpcyBub2RlIHdpbCBub3QgYmUgZXhlY3V0ZWRcbiAgICBub2RlLmV4ZWN1dGVOb2RlID0gZmFsc2U7XG4gICAgY29uc3QgaW5wdXRWYWx1ZUluZGV4ID0gbm9kZS5pbnB1dHNbMF07XG4gICAgY29uc3Qgb3V0cHV0VmFsdWVJbmRleCA9IG5vZGUub3V0cHV0c1swXTtcbiAgICBjb25zdCBub2Rlc0NvbnN1bWluZ091dHB1dCA9IHRoaXMuX2FsbERhdGFbb3V0cHV0VmFsdWVJbmRleF0udG87XG5cbiAgICAvLyByZW1vdmUgdGhpcyBub2RlIGZyb20gdGhlIHRvIHByb3BlcnR5IG9mIHRoZSBpbnB1dCBWYWx1ZVxuICAgIGNvbnN0IGRlbEluZGV4ID0gdGhpcy5fYWxsRGF0YVtpbnB1dFZhbHVlSW5kZXhdLnRvLmluZGV4T2Yobm9kZUluZGV4KTtcbiAgICAvLyBzaG91bGQgbm90IGhhcHBlblxuICAgIGlmIChkZWxJbmRleCA9PT0gLTEpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignVGhlIFZhbHVlIG9iamVjdCBkb2VzblxcJ3QgaGF2ZSB0aGUgY3VycmVudCBOb2RlIGluIGl0XFwncyBcXCd0b1xcJyBwcm9wZXJ0eSAnKTtcbiAgICB9XG4gICAgdGhpcy5fYWxsRGF0YVtpbnB1dFZhbHVlSW5kZXhdLnRvLnNwbGljZShkZWxJbmRleCwgMSk7XG5cbiAgICAvLyBjbGVhciBub2RlIGluZGljZXMgY29uc3VtaW5nIHRoaXMgb3V0cHV0IFZhbHVlXG4gICAgdGhpcy5fYWxsRGF0YVtvdXRwdXRWYWx1ZUluZGV4XS5fdG8gPSBbXTtcblxuICAgIC8vIGlmIHRoZSBvdXRwdXQgb2YgdGhpcyBub2RlIGlzIGEgZ3JhcGggb3V0cHV0LCBhZGp1c3QgdGhlIGluZGV4IGFwcHJvcHJpYXRlbHlcbiAgICBjb25zdCBpbmRleCA9IHRoaXMuX2FsbE91dHB1dEluZGljZXMuaW5kZXhPZihvdXRwdXRWYWx1ZUluZGV4KTtcbiAgICBpZiAoaW5kZXggIT09IC0xKSB7XG4gICAgICB0aGlzLl9hbGxPdXRwdXRJbmRpY2VzW2luZGV4XSA9IGlucHV0VmFsdWVJbmRleDtcbiAgICB9XG5cbiAgICAvLyBvdmVycmlkZSB0aGUgaW5wdXRzIGZvciBub2RlcyBjb25zdW1pbmcgdGhpcyBub2RlJ3Mgb3V0cHV0IHdpdGggdGhlIGlucHV0IHRvIHRoaXMgbm9kZVxuICAgIGlmIChub2Rlc0NvbnN1bWluZ091dHB1dCAmJiBub2Rlc0NvbnN1bWluZ091dHB1dC5sZW5ndGggPiAwKSB7XG4gICAgICBmb3IgKGNvbnN0IG5vZGVJbmRleCBvZiBub2Rlc0NvbnN1bWluZ091dHB1dCkge1xuICAgICAgICBjb25zdCByZXBsYWNlSW5kZXggPSB0aGlzLl9ub2Rlc1tub2RlSW5kZXhdLmlucHV0cy5pbmRleE9mKG91dHB1dFZhbHVlSW5kZXgpO1xuICAgICAgICAvLyBzaG91bGQgbm90IGhhcHBlblxuICAgICAgICBpZiAocmVwbGFjZUluZGV4ID09PSAtMSkge1xuICAgICAgICAgIHRocm93IG5ldyBFcnJvcignVGhlIE5vZGUgb2JqZWN0IGRvZXNuXFwndCBoYXZlIHRoZSBvdXRwdXQgVmFsdWUgaW4gaXRcXCdzIFxcJ2lucHV0c1xcJyBwcm9wZXJ0eSAnKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLl9ub2Rlc1tub2RlSW5kZXhdLmlucHV0c1tyZXBsYWNlSW5kZXhdID0gaW5wdXRWYWx1ZUluZGV4O1xuICAgICAgICB0aGlzLl9hbGxEYXRhW2lucHV0VmFsdWVJbmRleF0udG8ucHVzaChub2RlSW5kZXgpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHJlbW92ZUFsbERyb3BvdXROb2RlcygpIHtcbiAgICBsZXQgbm9kZUluZGV4ID0gMDtcbiAgICBmb3IgKGNvbnN0IG5vZGUgb2YgdGhpcy5fbm9kZXMpIHtcbiAgICAgIC8vIHdlZWQgb3V0ICdEcm9wb3V0JyBub2RlcyBzbyB0aGF0IG5vIHRpbWUgaXMgd2FzdGVkIGluIGV4ZWN1dGlvblxuICAgICAgaWYgKG5vZGUub3BUeXBlID09PSAnRHJvcG91dCcpIHtcbiAgICAgICAgLy8gdGhlIG5vZGUgc2hvdWxkIGhhdmUgZXhhY3RseSAxIGlucHV0IGFuZCAxIG9yIDIgb3V0cHV0c1xuICAgICAgICBpZiAobm9kZS5pbnB1dHMubGVuZ3RoICE9PSAxKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdEcm9wb3V0IG5vZGVzIHNob3VsZCBvbmx5IGNvbnRhaW4gb25lIGlucHV0LiAnKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAobm9kZS5vdXRwdXRzLmxlbmd0aCAhPT0gMSAmJiBub2RlLm91dHB1dHMubGVuZ3RoICE9PSAyKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdEcm9wb3V0IG5vZGVzIHNob3VsZCBjb250YWluIGVpdGhlciAxIG9yIDIgb3V0cHV0KHMpJyk7XG4gICAgICAgIH1cbiAgICAgICAgLy8gdGhlIHNlY29uZCBvdXRwdXQgc2hvdWxkIG5vdCBiZSByZWZlcmVuY2VkIGJ5IGFueSBvdGhlciBub2RlXG4gICAgICAgIGlmIChub2RlLm91dHB1dHMubGVuZ3RoID09PSAyICYmIHRoaXMuX2FsbERhdGFbbm9kZS5vdXRwdXRzWzFdXS5fdG8ubGVuZ3RoICE9PSAwKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdEcm9wb3V0IG5vZGVzXFwncyBzZWNvbmQgb3V0cHV0IHNob3VsZCBub3QgYmUgcmVmZXJlbmNlZCBieSBvdGhlciBub2RlcycpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuZGVsZXRlTm9kZShub2RlSW5kZXgpO1xuICAgICAgfVxuICAgICAgbm9kZUluZGV4Kys7XG4gICAgfVxuICB9XG5cbiAgcmVtb3ZlQWxsSWRlbnRpdHlOb2RlcygpIHtcbiAgICBsZXQgbm9kZUluZGV4ID0gMDtcbiAgICBmb3IgKGNvbnN0IG5vZGUgb2YgdGhpcy5fbm9kZXMpIHtcbiAgICAgIC8vIHdlZWQgb3V0ICdJZGVudGl0eScgbm9kZXMgc28gdGhhdCBubyB0aW1lIGlzIHdhc3RlZCBpbiBleGVjdXRpb25cbiAgICAgIGlmIChub2RlLm9wVHlwZSA9PT0gJ0lkZW50aXR5Jykge1xuICAgICAgICB0aGlzLmRlbGV0ZU5vZGUobm9kZUluZGV4KTtcbiAgICAgIH1cbiAgICAgIG5vZGVJbmRleCsrO1xuICAgIH1cbiAgfVxuXG4gIGlzQWN0aXZhdGlvbihuOiBOb2RlKTogYm9vbGVhbiB7XG4gICAgc3dpdGNoIChuLm9wVHlwZSkge1xuICAgICAgLy8gVE9ETzogYWRkIG90aGVyIGFjdGl2YXRpb24gbWV0aG9kc1xuICAgICAgY2FzZSAnUmVsdSc6XG4gICAgICBjYXNlICdTaWdtb2lkJzpcbiAgICAgIGNhc2UgJ0NsaXAnOlxuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gIH1cblxuICBmdXNlQ29udkFjdGl2YXRpb25Ob2RlcygpIHtcbiAgICBmb3IgKGNvbnN0IG5vZGUgb2YgdGhpcy5fbm9kZXMpIHtcbiAgICAgIGlmIChub2RlLm9wVHlwZSA9PT0gJ0NvbnYnKSB7XG4gICAgICAgIGNvbnN0IG5leHQgPSB0aGlzLl9hbGxEYXRhW25vZGUub3V0cHV0c1swXV0uX3RvO1xuICAgICAgICBpZiAobmV4dC5sZW5ndGggPT09IDEgJiYgdGhpcy5pc0FjdGl2YXRpb24odGhpcy5fbm9kZXNbbmV4dFswXV0pKSB7XG4gICAgICAgICAgY29uc3QgY2hpbGQgPSB0aGlzLl9ub2Rlc1tuZXh0WzBdXTtcbiAgICAgICAgICBpZiAoY2hpbGQub3BUeXBlID09PSAnQ2xpcCcpIHtcbiAgICAgICAgICAgIGlmIChjaGlsZC5pbnB1dHMubGVuZ3RoID09PSAxKSB7XG4gICAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgbm9kZS5hdHRyaWJ1dGVzLnNldChcbiAgICAgICAgICAgICAgICAgICAgJ2FjdGl2YXRpb25fcGFyYW1zJywgJ2Zsb2F0cycsXG4gICAgICAgICAgICAgICAgICAgIFtjaGlsZC5hdHRyaWJ1dGVzLmdldEZsb2F0KCdtaW4nKSwgY2hpbGQuYXR0cmlidXRlcy5nZXRGbG9hdCgnbWF4JyldKTtcbiAgICAgICAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgICAgIG5vZGUuYXR0cmlidXRlcy5zZXQoJ2FjdGl2YXRpb25fcGFyYW1zJywgJ2Zsb2F0cycsIFtNSU5fQ0xJUCwgTUFYX0NMSVBdKTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIGlmIChcbiAgICAgICAgICAgICAgICBjaGlsZC5pbnB1dHMubGVuZ3RoID49IDMgJiYgdGhpcy5fYWxsRGF0YVtjaGlsZC5pbnB1dHNbMV1dLnRlbnNvciAhPT0gdW5kZWZpbmVkICYmXG4gICAgICAgICAgICAgICAgdGhpcy5fYWxsRGF0YVtjaGlsZC5pbnB1dHNbMl1dLnRlbnNvciAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgIG5vZGUuYXR0cmlidXRlcy5zZXQoJ2FjdGl2YXRpb25fcGFyYW1zJywgJ2Zsb2F0cycsIFtcbiAgICAgICAgICAgICAgICB0aGlzLl9hbGxEYXRhW2NoaWxkLmlucHV0c1sxXV0udGVuc29yIS5mbG9hdERhdGFbMF0sIHRoaXMuX2FsbERhdGFbY2hpbGQuaW5wdXRzWzJdXS50ZW5zb3IhLmZsb2F0RGF0YVswXVxuICAgICAgICAgICAgICBdKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIC8vIFNraXAgZnVzaW9uIHdpdGggY2xpcCBub2RlIHNpbmNlIGNsaXAgbWluIGFuZCBjbGlwIG1heCBhcmUgbm90IGNvbWluZyBmcm9tIGluaXRpYWxpemVyXG4gICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgICBub2RlLmF0dHJpYnV0ZXMuc2V0KCdhY3RpdmF0aW9uJywgJ3N0cmluZycsIChjaGlsZC5vcFR5cGUpKTtcbiAgICAgICAgICB0aGlzLmRlbGV0ZU5vZGUobmV4dFswXSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gIH1cbn1cbiIsIi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxuXG5pbXBvcnQge0Vudn0gZnJvbSAnb25ueHJ1bnRpbWUtY29tbW9uJztcblxuaW1wb3J0IHtXZWJHTENvbnRleHR9IGZyb20gJy4vYmFja2VuZHMvd2ViZ2wvd2ViZ2wtY29udGV4dCc7XG5cbmV4cG9ydCBkZWNsYXJlIG5hbWVzcGFjZSBMb2dnZXIge1xuICBleHBvcnQgaW50ZXJmYWNlIFNldmVyaXR5VHlwZU1hcCB7XG4gICAgdmVyYm9zZTogJ3YnO1xuICAgIGluZm86ICdpJztcbiAgICB3YXJuaW5nOiAndyc7XG4gICAgZXJyb3I6ICdlJztcbiAgICBmYXRhbDogJ2YnO1xuICB9XG5cbiAgZXhwb3J0IHR5cGUgU2V2ZXJpdHkgPSBrZXlvZiBTZXZlcml0eVR5cGVNYXA7XG5cbiAgZXhwb3J0IHR5cGUgUHJvdmlkZXIgPSAnbm9uZSd8J2NvbnNvbGUnO1xuXG4gIC8qKlxuICAgKiBMb2dnaW5nIGNvbmZpZyB0aGF0IHVzZWQgdG8gY29udHJvbCB0aGUgYmVoYXZpb3Igb2YgbG9nZ2VyXG4gICAqL1xuICBleHBvcnQgaW50ZXJmYWNlIENvbmZpZyB7XG4gICAgLyoqXG4gICAgICogU3BlY2lmeSB0aGUgbG9nZ2luZyBwcm92aWRlci4gJ2NvbnNvbGUnIGJ5IGRlZmF1bHRcbiAgICAgKi9cbiAgICBwcm92aWRlcj86IFByb3ZpZGVyO1xuICAgIC8qKlxuICAgICAqIFNwZWNpZnkgdGhlIG1pbmltYWwgbG9nZ2VyIHNlcnZlcml0eS4gJ3dhcm5pbmcnIGJ5IGRlZmF1bHRcbiAgICAgKi9cbiAgICBtaW5pbWFsU2V2ZXJpdHk/OiBMb2dnZXIuU2V2ZXJpdHk7XG4gICAgLyoqXG4gICAgICogV2hldGhlciB0byBvdXRwdXQgZGF0ZSB0aW1lIGluIGxvZy4gdHJ1ZSBieSBkZWZhdWx0XG4gICAgICovXG4gICAgbG9nRGF0ZVRpbWU/OiBib29sZWFuO1xuICAgIC8qKlxuICAgICAqIFdoZXRoZXIgdG8gb3V0cHV0IHNvdXJjZSBpbmZvcm1hdGlvbiAoTm90IHlldCBzdXBwb3J0ZWQpLiBmYWxzZSBieSBkZWZhdWx0XG4gICAgICovXG4gICAgbG9nU291cmNlTG9jYXRpb24/OiBib29sZWFuO1xuICB9XG5cbiAgZXhwb3J0IGludGVyZmFjZSBDYXRlZ29yaXplZExvZ2dlciB7XG4gICAgdmVyYm9zZShjb250ZW50OiBzdHJpbmcpOiB2b2lkO1xuICAgIGluZm8oY29udGVudDogc3RyaW5nKTogdm9pZDtcbiAgICB3YXJuaW5nKGNvbnRlbnQ6IHN0cmluZyk6IHZvaWQ7XG4gICAgZXJyb3IoY29udGVudDogc3RyaW5nKTogdm9pZDtcbiAgICBmYXRhbChjb250ZW50OiBzdHJpbmcpOiB2b2lkO1xuICB9XG59XG5cbi8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tcmVkZWNsYXJlXG5leHBvcnQgaW50ZXJmYWNlIExvZ2dlciB7XG4gIChjYXRlZ29yeTogc3RyaW5nKTogTG9nZ2VyLkNhdGVnb3JpemVkTG9nZ2VyO1xuXG4gIHZlcmJvc2UoY29udGVudDogc3RyaW5nKTogdm9pZDtcbiAgdmVyYm9zZShjYXRlZ29yeTogc3RyaW5nLCBjb250ZW50OiBzdHJpbmcpOiB2b2lkO1xuICBpbmZvKGNvbnRlbnQ6IHN0cmluZyk6IHZvaWQ7XG4gIGluZm8oY2F0ZWdvcnk6IHN0cmluZywgY29udGVudDogc3RyaW5nKTogdm9pZDtcbiAgd2FybmluZyhjb250ZW50OiBzdHJpbmcpOiB2b2lkO1xuICB3YXJuaW5nKGNhdGVnb3J5OiBzdHJpbmcsIGNvbnRlbnQ6IHN0cmluZyk6IHZvaWQ7XG4gIGVycm9yKGNvbnRlbnQ6IHN0cmluZyk6IHZvaWQ7XG4gIGVycm9yKGNhdGVnb3J5OiBzdHJpbmcsIGNvbnRlbnQ6IHN0cmluZyk6IHZvaWQ7XG4gIGZhdGFsKGNvbnRlbnQ6IHN0cmluZyk6IHZvaWQ7XG4gIGZhdGFsKGNhdGVnb3J5OiBzdHJpbmcsIGNvbnRlbnQ6IHN0cmluZyk6IHZvaWQ7XG5cbiAgLyoqXG4gICAqIFJlc2V0IHRoZSBsb2dnZXIgY29uZmlndXJhdGlvbi5cbiAgICogQHBhcmFtIGNvbmZpZyBzcGVjaWZ5IGFuIG9wdGlvbmFsIGRlZmF1bHQgY29uZmlnXG4gICAqL1xuICByZXNldChjb25maWc/OiBMb2dnZXIuQ29uZmlnKTogdm9pZDtcbiAgLyoqXG4gICAqIFNldCB0aGUgbG9nZ2VyJ3MgYmVoYXZpb3Igb24gdGhlIGdpdmVuIGNhdGVnb3J5XG4gICAqIEBwYXJhbSBjYXRlZ29yeSBzcGVjaWZ5IGEgY2F0ZWdvcnkgc3RyaW5nLiBJZiAnKicgaXMgc3BlY2lmaWVkLCBhbGwgcHJldmlvdXMgY29uZmlndXJhdGlvbiB3aWxsIGJlIG92ZXJ3cml0dGVuLiBJZlxuICAgKiAnJyBpcyBzcGVjaWZpZWQsIHRoZSBkZWZhdWx0IGJlaGF2aW9yIHdpbGwgYmUgdXBkYXRlZC5cbiAgICogQHBhcmFtIGNvbmZpZyB0aGUgY29uZmlnIG9iamVjdCB0byBpbmRpY2F0ZSB0aGUgbG9nZ2VyJ3MgYmVoYXZpb3JcbiAgICovXG4gIHNldChjYXRlZ29yeTogc3RyaW5nLCBjb25maWc6IExvZ2dlci5Db25maWcpOiB2b2lkO1xuXG4gIC8qKlxuICAgKiBTZXQgdGhlIGxvZ2dlcidzIGJlaGF2aW9yIGZyb20gb3J0LWNvbW1vbiBlbnZcbiAgICogQHBhcmFtIGVudiB0aGUgZW52IHVzZWQgdG8gc2V0IGxvZ2dlci4gQ3VycmVudGx5IG9ubHkgc2V0dGluZyBsb2dsZXZlbCBpcyBzdXBwb3J0ZWQgdGhyb3VnaCBFbnYuXG4gICAqL1xuICBzZXRXaXRoRW52KGVudjogRW52KTogdm9pZDtcbn1cblxuaW50ZXJmYWNlIExvZ2dlclByb3ZpZGVyIHtcbiAgbG9nKHNldmVyaXR5OiBMb2dnZXIuU2V2ZXJpdHksIGNvbnRlbnQ6IHN0cmluZywgY2F0ZWdvcnk/OiBzdHJpbmcpOiB2b2lkO1xufVxuY2xhc3MgTm9PcExvZ2dlclByb3ZpZGVyIGltcGxlbWVudHMgTG9nZ2VyUHJvdmlkZXIge1xuICBsb2coX3NldmVyaXR5OiBMb2dnZXIuU2V2ZXJpdHksIF9jb250ZW50OiBzdHJpbmcsIF9jYXRlZ29yeT86IHN0cmluZykge1xuICAgIC8vIGRvIG5vdGhpbmdcbiAgfVxufVxuY2xhc3MgQ29uc29sZUxvZ2dlclByb3ZpZGVyIGltcGxlbWVudHMgTG9nZ2VyUHJvdmlkZXIge1xuICBsb2coc2V2ZXJpdHk6IExvZ2dlci5TZXZlcml0eSwgY29udGVudDogc3RyaW5nLCBjYXRlZ29yeT86IHN0cmluZykge1xuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1jb25zb2xlXG4gICAgY29uc29sZS5sb2coYCR7dGhpcy5jb2xvcihzZXZlcml0eSl9ICR7Y2F0ZWdvcnkgPyAnXFx4MWJbMzVtJyArIGNhdGVnb3J5ICsgJ1xceDFiWzBtICcgOiAnJ30ke2NvbnRlbnR9YCk7XG4gIH1cblxuICBwcml2YXRlIGNvbG9yKHNldmVyaXR5OiBMb2dnZXIuU2V2ZXJpdHkpIHtcbiAgICBzd2l0Y2ggKHNldmVyaXR5KSB7XG4gICAgICBjYXNlICd2ZXJib3NlJzpcbiAgICAgICAgcmV0dXJuICdcXHgxYlszNDs0MG12XFx4MWJbMG0nO1xuICAgICAgY2FzZSAnaW5mbyc6XG4gICAgICAgIHJldHVybiAnXFx4MWJbMzJtaVxceDFiWzBtJztcbiAgICAgIGNhc2UgJ3dhcm5pbmcnOlxuICAgICAgICByZXR1cm4gJ1xceDFiWzMwOzQzbXdcXHgxYlswbSc7XG4gICAgICBjYXNlICdlcnJvcic6XG4gICAgICAgIHJldHVybiAnXFx4MWJbMzE7NDBtZVxceDFiWzBtJztcbiAgICAgIGNhc2UgJ2ZhdGFsJzpcbiAgICAgICAgcmV0dXJuICdcXHgxYlsxMDFtZlxceDFiWzBtJztcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgdW5zdXBwb3J0ZWQgc2V2ZXJpdHk6ICR7c2V2ZXJpdHl9YCk7XG4gICAgfVxuICB9XG59XG5cbmNvbnN0IFNFVkVSSVRZX1ZBTFVFID0ge1xuICB2ZXJib3NlOiAxMDAwLFxuICBpbmZvOiAyMDAwLFxuICB3YXJuaW5nOiA0MDAwLFxuICBlcnJvcjogNTAwMCxcbiAgZmF0YWw6IDYwMDBcbn07XG5cbmNvbnN0IExPR0dFUl9QUk9WSURFUl9NQVA6IHtyZWFkb25seSBbcHJvdmlkZXI6IHN0cmluZ106IFJlYWRvbmx5PExvZ2dlclByb3ZpZGVyPn0gPSB7XG4gIFsnbm9uZSddOiBuZXcgTm9PcExvZ2dlclByb3ZpZGVyKCksXG4gIFsnY29uc29sZSddOiBuZXcgQ29uc29sZUxvZ2dlclByb3ZpZGVyKClcbn07XG5jb25zdCBMT0dHRVJfREVGQVVMVF9DT05GSUcgPSB7XG4gIHByb3ZpZGVyOiAnY29uc29sZScsXG4gIG1pbmltYWxTZXZlcml0eTogJ3dhcm5pbmcnLFxuICBsb2dEYXRlVGltZTogdHJ1ZSxcbiAgbG9nU291cmNlTG9jYXRpb246IGZhbHNlXG59O1xubGV0IExPR0dFUl9DT05GSUdfTUFQOlxuICAgIHtbY2F0ZWdvcnk6IHN0cmluZ106IFJlYWRvbmx5PFJlcXVpcmVkPExvZ2dlci5Db25maWc+Pn0gPSB7WycnXTogTE9HR0VSX0RFRkFVTFRfQ09ORklHIGFzIFJlcXVpcmVkPExvZ2dlci5Db25maWc+fTtcblxuZnVuY3Rpb24gbG9nKGNhdGVnb3J5OiBzdHJpbmcpOiBMb2dnZXIuQ2F0ZWdvcml6ZWRMb2dnZXI7XG5mdW5jdGlvbiBsb2coc2V2ZXJpdHk6IExvZ2dlci5TZXZlcml0eSwgY29udGVudDogc3RyaW5nKTogdm9pZDtcbmZ1bmN0aW9uIGxvZyhzZXZlcml0eTogTG9nZ2VyLlNldmVyaXR5LCBjYXRlZ29yeTogc3RyaW5nLCBjb250ZW50OiBzdHJpbmcpOiB2b2lkO1xuZnVuY3Rpb24gbG9nKHNldmVyaXR5OiBMb2dnZXIuU2V2ZXJpdHksIGFyZzE6IHN0cmluZywgYXJnMj86IHN0cmluZyk6IHZvaWQ7XG5mdW5jdGlvbiBsb2coXG4gICAgYXJnMDogc3RyaW5nfExvZ2dlci5TZXZlcml0eSwgYXJnMT86IHN0cmluZywgYXJnMj86IHN0cmluZ3xudW1iZXIsIGFyZzM/OiBudW1iZXIpOiBMb2dnZXIuQ2F0ZWdvcml6ZWRMb2dnZXJ8dm9pZCB7XG4gIGlmIChhcmcxID09PSB1bmRlZmluZWQpIHtcbiAgICAvLyBsb2coY2F0ZWdvcnk6IHN0cmluZyk6IExvZ2dlci5DYXRlZ29yaXplZExvZ2dlcjtcbiAgICByZXR1cm4gY3JlYXRlQ2F0ZWdvcml6ZWRMb2dnZXIoYXJnMCk7XG4gIH0gZWxzZSBpZiAoYXJnMiA9PT0gdW5kZWZpbmVkKSB7XG4gICAgLy8gbG9nKHNldmVyaXR5LCBjb250ZW50KTtcbiAgICBsb2dJbnRlcm5hbChhcmcwIGFzIExvZ2dlci5TZXZlcml0eSwgYXJnMSwgMSk7XG4gIH0gZWxzZSBpZiAodHlwZW9mIGFyZzIgPT09ICdudW1iZXInICYmIGFyZzMgPT09IHVuZGVmaW5lZCkge1xuICAgIC8vIGxvZyhzZXZlcml0eSwgY29udGVudCwgc3RhY2spXG4gICAgbG9nSW50ZXJuYWwoYXJnMCBhcyBMb2dnZXIuU2V2ZXJpdHksIGFyZzEsIGFyZzIpO1xuICB9IGVsc2UgaWYgKHR5cGVvZiBhcmcyID09PSAnc3RyaW5nJyAmJiBhcmczID09PSB1bmRlZmluZWQpIHtcbiAgICAvLyBsb2coc2V2ZXJpdHksIGNhdGVnb3J5LCBjb250ZW50KVxuICAgIGxvZ0ludGVybmFsKGFyZzAgYXMgTG9nZ2VyLlNldmVyaXR5LCBhcmcyLCAxLCBhcmcxKTtcbiAgfSBlbHNlIGlmICh0eXBlb2YgYXJnMiA9PT0gJ3N0cmluZycgJiYgdHlwZW9mIGFyZzMgPT09ICdudW1iZXInKSB7XG4gICAgLy8gbG9nKHNldmVyaXR5LCBjYXRlZ29yeSwgY29udGVudCwgc3RhY2spXG4gICAgbG9nSW50ZXJuYWwoYXJnMCBhcyBMb2dnZXIuU2V2ZXJpdHksIGFyZzIsIGFyZzMsIGFyZzEpO1xuICB9IGVsc2Uge1xuICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ2lucHV0IGlzIHZhbGlkJyk7XG4gIH1cbn1cblxuZnVuY3Rpb24gY3JlYXRlQ2F0ZWdvcml6ZWRMb2dnZXIoY2F0ZWdvcnk6IHN0cmluZyk6IExvZ2dlci5DYXRlZ29yaXplZExvZ2dlciB7XG4gIHJldHVybiB7XG4gICAgdmVyYm9zZTogbG9nLnZlcmJvc2UuYmluZChudWxsLCBjYXRlZ29yeSksXG4gICAgaW5mbzogbG9nLmluZm8uYmluZChudWxsLCBjYXRlZ29yeSksXG4gICAgd2FybmluZzogbG9nLndhcm5pbmcuYmluZChudWxsLCBjYXRlZ29yeSksXG4gICAgZXJyb3I6IGxvZy5lcnJvci5iaW5kKG51bGwsIGNhdGVnb3J5KSxcbiAgICBmYXRhbDogbG9nLmZhdGFsLmJpbmQobnVsbCwgY2F0ZWdvcnkpXG4gIH07XG59XG5cbi8vIE5PVEU6IGFyZ3VtZW50ICdjYXRlZ29yeScgaXMgcHV0IHRoZSBsYXN0IHBhcmFtZXRlciBiZWFjYXVzZSB0eXBlc2NyaXB0XG4vLyBkb2Vzbid0IGFsbG93IG9wdGlvbmFsIGFyZ3VtZW50IHB1dCBpbiBmcm9udCBvZiByZXF1aXJlZCBhcmd1bWVudC4gVGhpc1xuLy8gb3JkZXIgaXMgZGlmZmVyZW50IGZyb20gYSB1c3VhbCBsb2dnaW5nIEFQSS5cbmZ1bmN0aW9uIGxvZ0ludGVybmFsKHNldmVyaXR5OiBMb2dnZXIuU2V2ZXJpdHksIGNvbnRlbnQ6IHN0cmluZywgc3RhY2s6IG51bWJlciwgY2F0ZWdvcnk/OiBzdHJpbmcpIHtcbiAgY29uc3QgY29uZmlnID0gTE9HR0VSX0NPTkZJR19NQVBbY2F0ZWdvcnkgfHwgJyddIHx8IExPR0dFUl9DT05GSUdfTUFQWycnXTtcbiAgaWYgKFNFVkVSSVRZX1ZBTFVFW3NldmVyaXR5XSA8IFNFVkVSSVRZX1ZBTFVFW2NvbmZpZy5taW5pbWFsU2V2ZXJpdHldKSB7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgaWYgKGNvbmZpZy5sb2dEYXRlVGltZSkge1xuICAgIGNvbnRlbnQgPSBgJHtuZXcgRGF0ZSgpLnRvSVNPU3RyaW5nKCl9fCR7Y29udGVudH1gO1xuICB9XG5cbiAgaWYgKGNvbmZpZy5sb2dTb3VyY2VMb2NhdGlvbikge1xuICAgIC8vIFRPRE86IGNhbGN1bGF0ZSBzb3VyY2UgbG9jYXRpb24gZnJvbSAnc3RhY2snXG4gIH1cblxuICBMT0dHRVJfUFJPVklERVJfTUFQW2NvbmZpZy5wcm92aWRlcl0ubG9nKHNldmVyaXR5LCBjb250ZW50LCBjYXRlZ29yeSk7XG59XG5cbi8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tbmFtZXNwYWNlXG5uYW1lc3BhY2UgbG9nIHtcbiAgZXhwb3J0IGZ1bmN0aW9uIHZlcmJvc2UoY29udGVudDogc3RyaW5nKTogdm9pZDtcbiAgZXhwb3J0IGZ1bmN0aW9uIHZlcmJvc2UoY2F0ZWdvcnk6IHN0cmluZywgY29udGVudDogc3RyaW5nKTogdm9pZDtcbiAgZXhwb3J0IGZ1bmN0aW9uIHZlcmJvc2UoYXJnMDogc3RyaW5nLCBhcmcxPzogc3RyaW5nKSB7XG4gICAgbG9nKCd2ZXJib3NlJywgYXJnMCwgYXJnMSk7XG4gIH1cbiAgZXhwb3J0IGZ1bmN0aW9uIGluZm8oY29udGVudDogc3RyaW5nKTogdm9pZDtcbiAgZXhwb3J0IGZ1bmN0aW9uIGluZm8oY2F0ZWdvcnk6IHN0cmluZywgY29udGVudDogc3RyaW5nKTogdm9pZDtcbiAgZXhwb3J0IGZ1bmN0aW9uIGluZm8oYXJnMDogc3RyaW5nLCBhcmcxPzogc3RyaW5nKSB7XG4gICAgbG9nKCdpbmZvJywgYXJnMCwgYXJnMSk7XG4gIH1cbiAgZXhwb3J0IGZ1bmN0aW9uIHdhcm5pbmcoY29udGVudDogc3RyaW5nKTogdm9pZDtcbiAgZXhwb3J0IGZ1bmN0aW9uIHdhcm5pbmcoY2F0ZWdvcnk6IHN0cmluZywgY29udGVudDogc3RyaW5nKTogdm9pZDtcbiAgZXhwb3J0IGZ1bmN0aW9uIHdhcm5pbmcoYXJnMDogc3RyaW5nLCBhcmcxPzogc3RyaW5nKSB7XG4gICAgbG9nKCd3YXJuaW5nJywgYXJnMCwgYXJnMSk7XG4gIH1cbiAgZXhwb3J0IGZ1bmN0aW9uIGVycm9yKGNvbnRlbnQ6IHN0cmluZyk6IHZvaWQ7XG4gIGV4cG9ydCBmdW5jdGlvbiBlcnJvcihjYXRlZ29yeTogc3RyaW5nLCBjb250ZW50OiBzdHJpbmcpOiB2b2lkO1xuICBleHBvcnQgZnVuY3Rpb24gZXJyb3IoYXJnMDogc3RyaW5nLCBhcmcxPzogc3RyaW5nKSB7XG4gICAgbG9nKCdlcnJvcicsIGFyZzAsIGFyZzEpO1xuICB9XG4gIGV4cG9ydCBmdW5jdGlvbiBmYXRhbChjb250ZW50OiBzdHJpbmcpOiB2b2lkO1xuICBleHBvcnQgZnVuY3Rpb24gZmF0YWwoY2F0ZWdvcnk6IHN0cmluZywgY29udGVudDogc3RyaW5nKTogdm9pZDtcbiAgZXhwb3J0IGZ1bmN0aW9uIGZhdGFsKGFyZzA6IHN0cmluZywgYXJnMT86IHN0cmluZykge1xuICAgIGxvZygnZmF0YWwnLCBhcmcwLCBhcmcxKTtcbiAgfVxuXG4gIGV4cG9ydCBmdW5jdGlvbiByZXNldChjb25maWc/OiBMb2dnZXIuQ29uZmlnKTogdm9pZCB7XG4gICAgTE9HR0VSX0NPTkZJR19NQVAgPSB7fTtcbiAgICBzZXQoJycsIGNvbmZpZyB8fCB7fSk7XG4gIH1cbiAgZXhwb3J0IGZ1bmN0aW9uIHNldChjYXRlZ29yeTogc3RyaW5nLCBjb25maWc6IExvZ2dlci5Db25maWcpOiB2b2lkIHtcbiAgICBpZiAoY2F0ZWdvcnkgPT09ICcqJykge1xuICAgICAgcmVzZXQoY29uZmlnKTtcbiAgICB9IGVsc2Uge1xuICAgICAgY29uc3QgcHJldmlvdXNDb25maWcgPSBMT0dHRVJfQ09ORklHX01BUFtjYXRlZ29yeV0gfHwgTE9HR0VSX0RFRkFVTFRfQ09ORklHO1xuICAgICAgTE9HR0VSX0NPTkZJR19NQVBbY2F0ZWdvcnldID0ge1xuICAgICAgICBwcm92aWRlcjogY29uZmlnLnByb3ZpZGVyIHx8IHByZXZpb3VzQ29uZmlnLnByb3ZpZGVyLFxuICAgICAgICBtaW5pbWFsU2V2ZXJpdHk6IGNvbmZpZy5taW5pbWFsU2V2ZXJpdHkgfHwgcHJldmlvdXNDb25maWcubWluaW1hbFNldmVyaXR5LFxuICAgICAgICBsb2dEYXRlVGltZTogKGNvbmZpZy5sb2dEYXRlVGltZSA9PT0gdW5kZWZpbmVkKSA/IHByZXZpb3VzQ29uZmlnLmxvZ0RhdGVUaW1lIDogY29uZmlnLmxvZ0RhdGVUaW1lLFxuICAgICAgICBsb2dTb3VyY2VMb2NhdGlvbjogKGNvbmZpZy5sb2dTb3VyY2VMb2NhdGlvbiA9PT0gdW5kZWZpbmVkKSA/IHByZXZpb3VzQ29uZmlnLmxvZ1NvdXJjZUxvY2F0aW9uIDpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25maWcubG9nU291cmNlTG9jYXRpb25cbiAgICAgIH07XG4gICAgfVxuXG4gICAgLy8gVE9ETzogd2Ugd2FudCB0byBzdXBwb3J0IHdpbGRjYXJkIG9yIHJlZ2V4P1xuICB9XG5cbiAgZXhwb3J0IGZ1bmN0aW9uIHNldFdpdGhFbnYoZW52OiBFbnYpOiB2b2lkIHtcbiAgICBjb25zdCBjb25maWc6IExvZ2dlci5Db25maWcgPSB7fTtcbiAgICBpZiAoZW52LmxvZ0xldmVsKSB7XG4gICAgICBjb25maWcubWluaW1hbFNldmVyaXR5ID0gZW52LmxvZ0xldmVsIGFzIExvZ2dlci5TZXZlcml0eTtcbiAgICB9XG4gICAgc2V0KCcnLCBjb25maWcpO1xuICB9XG59XG5cbi8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tcmVkZWNsYXJlLCBAdHlwZXNjcmlwdC1lc2xpbnQvbmFtaW5nLWNvbnZlbnRpb25cbmV4cG9ydCBjb25zdCBMb2dnZXI6IExvZ2dlciA9IGxvZztcblxuZXhwb3J0IGRlY2xhcmUgbmFtZXNwYWNlIFByb2ZpbGVyIHtcbiAgZXhwb3J0IGludGVyZmFjZSBDb25maWcge1xuICAgIG1heE51bWJlckV2ZW50cz86IG51bWJlcjtcbiAgICBmbHVzaEJhdGNoU2l6ZT86IG51bWJlcjtcbiAgICBmbHVzaEludGVydmFsSW5NaWxsaXNlY29uZHM/OiBudW1iZXI7XG4gIH1cblxuICBleHBvcnQgdHlwZSBFdmVudENhdGVnb3J5ID0gJ3Nlc3Npb24nfCdub2RlJ3wnb3AnfCdiYWNrZW5kJztcblxuICBleHBvcnQgaW50ZXJmYWNlIEV2ZW50IHtcbiAgICBlbmQoKTogdm9pZHxQcm9taXNlPHZvaWQ+O1xuICB9XG59XG4vLyBUT0RPXG4vLyBjbGFzcyBXZWJHTEV2ZW50IGltcGxlbWVudHMgUHJvZmlsZXIuRXZlbnQge31cblxuY2xhc3MgRXZlbnQgaW1wbGVtZW50cyBQcm9maWxlci5FdmVudCB7XG4gIGNvbnN0cnVjdG9yKFxuICAgICAgcHVibGljIGNhdGVnb3J5OiBQcm9maWxlci5FdmVudENhdGVnb3J5LCBwdWJsaWMgbmFtZTogc3RyaW5nLCBwdWJsaWMgc3RhcnRUaW1lOiBudW1iZXIsXG4gICAgICBwcml2YXRlIGVuZENhbGxiYWNrOiAoZTogRXZlbnQpID0+IHZvaWR8UHJvbWlzZTx2b2lkPiwgcHVibGljIHRpbWVyPzogV2ViR0xRdWVyeSwgcHVibGljIGN0eD86IFdlYkdMQ29udGV4dCkge31cblxuICBlbmQoKSB7XG4gICAgcmV0dXJuIHRoaXMuZW5kQ2FsbGJhY2sodGhpcyk7XG4gIH1cblxuICBhc3luYyBjaGVja1RpbWVyKCk6IFByb21pc2U8bnVtYmVyPiB7XG4gICAgaWYgKHRoaXMuY3R4ID09PSB1bmRlZmluZWQgfHwgdGhpcy50aW1lciA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ05vIHdlYmdsIHRpbWVyIGZvdW5kJyk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMuY3R4LmVuZFRpbWVyKCk7XG4gICAgICByZXR1cm4gdGhpcy5jdHgud2FpdEZvclF1ZXJ5QW5kR2V0VGltZSh0aGlzLnRpbWVyKTtcbiAgICB9XG4gIH1cbn1cblxuY2xhc3MgRXZlbnRSZWNvcmQge1xuICBjb25zdHJ1Y3RvcihcbiAgICAgIHB1YmxpYyBjYXRlZ29yeTogUHJvZmlsZXIuRXZlbnRDYXRlZ29yeSwgcHVibGljIG5hbWU6IHN0cmluZywgcHVibGljIHN0YXJ0VGltZTogbnVtYmVyLCBwdWJsaWMgZW5kVGltZTogbnVtYmVyKSB7fVxufVxuXG5leHBvcnQgY2xhc3MgUHJvZmlsZXIge1xuICBzdGF0aWMgY3JlYXRlKGNvbmZpZz86IFByb2ZpbGVyLkNvbmZpZyk6IFByb2ZpbGVyIHtcbiAgICBpZiAoY29uZmlnID09PSB1bmRlZmluZWQpIHtcbiAgICAgIHJldHVybiBuZXcgdGhpcygpO1xuICAgIH1cbiAgICByZXR1cm4gbmV3IHRoaXMoY29uZmlnLm1heE51bWJlckV2ZW50cywgY29uZmlnLmZsdXNoQmF0Y2hTaXplLCBjb25maWcuZmx1c2hJbnRlcnZhbEluTWlsbGlzZWNvbmRzKTtcbiAgfVxuXG4gIHByaXZhdGUgY29uc3RydWN0b3IobWF4TnVtYmVyRXZlbnRzPzogbnVtYmVyLCBmbHVzaEJhdGNoU2l6ZT86IG51bWJlciwgZmx1c2hJbnRlcnZhbEluTWlsbGlzZWNvbmRzPzogbnVtYmVyKSB7XG4gICAgdGhpcy5fc3RhcnRlZCA9IGZhbHNlO1xuICAgIHRoaXMuX21heE51bWJlckV2ZW50cyA9IG1heE51bWJlckV2ZW50cyA9PT0gdW5kZWZpbmVkID8gMTAwMDAgOiBtYXhOdW1iZXJFdmVudHM7XG4gICAgdGhpcy5fZmx1c2hCYXRjaFNpemUgPSBmbHVzaEJhdGNoU2l6ZSA9PT0gdW5kZWZpbmVkID8gMTAgOiBmbHVzaEJhdGNoU2l6ZTtcbiAgICB0aGlzLl9mbHVzaEludGVydmFsSW5NaWxsaXNlY29uZHMgPSBmbHVzaEludGVydmFsSW5NaWxsaXNlY29uZHMgPT09IHVuZGVmaW5lZCA/IDUwMDAgOiBmbHVzaEludGVydmFsSW5NaWxsaXNlY29uZHM7XG4gIH1cblxuICAvLyBzdGFydCBwcm9maWxpbmdcbiAgc3RhcnQoKSB7XG4gICAgdGhpcy5fc3RhcnRlZCA9IHRydWU7XG4gICAgdGhpcy5fdGltaW5nRXZlbnRzID0gW107XG4gICAgdGhpcy5fZmx1c2hUaW1lID0gbm93KCk7XG4gICAgdGhpcy5fZmx1c2hQb2ludGVyID0gMDtcbiAgfVxuXG4gIC8vIHN0b3AgcHJvZmlsaW5nXG4gIHN0b3AoKSB7XG4gICAgdGhpcy5fc3RhcnRlZCA9IGZhbHNlO1xuICAgIGZvciAoOyB0aGlzLl9mbHVzaFBvaW50ZXIgPCB0aGlzLl90aW1pbmdFdmVudHMubGVuZ3RoOyB0aGlzLl9mbHVzaFBvaW50ZXIrKykge1xuICAgICAgdGhpcy5sb2dPbmVFdmVudCh0aGlzLl90aW1pbmdFdmVudHNbdGhpcy5fZmx1c2hQb2ludGVyXSk7XG4gICAgfVxuICB9XG5cbiAgLy8gY3JlYXRlIGFuIGV2ZW50IHNjb3BlIGZvciB0aGUgc3BlY2lmaWMgZnVuY3Rpb25cbiAgZXZlbnQ8VD4oY2F0ZWdvcnk6IFByb2ZpbGVyLkV2ZW50Q2F0ZWdvcnksIG5hbWU6IHN0cmluZywgZnVuYzogKCkgPT4gVCwgY3R4PzogV2ViR0xDb250ZXh0KTogVDtcbiAgZXZlbnQ8VD4oY2F0ZWdvcnk6IFByb2ZpbGVyLkV2ZW50Q2F0ZWdvcnksIG5hbWU6IHN0cmluZywgZnVuYzogKCkgPT4gUHJvbWlzZTxUPiwgY3R4PzogV2ViR0xDb250ZXh0KTogUHJvbWlzZTxUPjtcblxuICBldmVudDxUPihjYXRlZ29yeTogUHJvZmlsZXIuRXZlbnRDYXRlZ29yeSwgbmFtZTogc3RyaW5nLCBmdW5jOiAoKSA9PiBUIHwgUHJvbWlzZTxUPiwgY3R4PzogV2ViR0xDb250ZXh0KTogVFxuICAgICAgfFByb21pc2U8VD4ge1xuICAgIGNvbnN0IGV2ZW50ID0gdGhpcy5fc3RhcnRlZCA/IHRoaXMuYmVnaW4oY2F0ZWdvcnksIG5hbWUsIGN0eCkgOiB1bmRlZmluZWQ7XG4gICAgbGV0IGlzUHJvbWlzZSA9IGZhbHNlO1xuXG4gICAgY29uc3QgcmVzID0gZnVuYygpO1xuXG4gICAgLy8gd2UgY29uc2lkZXIgYSB0aGVuLWFibGUgb2JqZWN0IGlzIGEgcHJvbWlzZVxuICAgIGlmIChyZXMgJiYgdHlwZW9mIChyZXMgYXMgUHJvbWlzZTxUPikudGhlbiA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgaXNQcm9taXNlID0gdHJ1ZTtcbiAgICAgIHJldHVybiBuZXcgUHJvbWlzZTxUPigocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgIChyZXMgYXMgUHJvbWlzZTxUPilcbiAgICAgICAgICAgIC50aGVuKFxuICAgICAgICAgICAgICAgIGFzeW5jIHZhbHVlID0+IHsgIC8vIGZ1bGZpbGxlZFxuICAgICAgICAgICAgICAgICAgaWYgKGV2ZW50KSB7XG4gICAgICAgICAgICAgICAgICAgIGF3YWl0IGV2ZW50LmVuZCgpO1xuICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgcmVzb2x2ZSh2YWx1ZSk7XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBhc3luYyByZWFzb24gPT4geyAgLy8gcmVqZWN0ZWRcbiAgICAgICAgICAgICAgICAgIGlmIChldmVudCkge1xuICAgICAgICAgICAgICAgICAgICBhd2FpdCBldmVudC5lbmQoKTtcbiAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgIHJlamVjdChyZWFzb24pO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgfSk7XG4gICAgfVxuICAgIGlmICghaXNQcm9taXNlICYmIGV2ZW50KSB7XG4gICAgICBjb25zdCBldmVudFJlcyA9IGV2ZW50LmVuZCgpO1xuICAgICAgaWYgKGV2ZW50UmVzICYmIHR5cGVvZiBldmVudFJlcy50aGVuID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZTxUPigocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgKGV2ZW50UmVzKS50aGVuKFxuICAgICAgICAgICAgICAoKSA9PiB7ICAvLyBmdWxmaWxsZWRcbiAgICAgICAgICAgICAgICByZXNvbHZlKHJlcyk7XG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgIChyZWFzb24pID0+IHsgIC8vIHJlamVjdGVkXG4gICAgICAgICAgICAgICAgcmVqZWN0KHJlYXNvbik7XG4gICAgICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHJlcztcbiAgfVxuXG4gIC8vIGJlZ2luIGFuIGV2ZW50XG4gIGJlZ2luKGNhdGVnb3J5OiBQcm9maWxlci5FdmVudENhdGVnb3J5LCBuYW1lOiBzdHJpbmcsIGN0eD86IFdlYkdMQ29udGV4dCk6IEV2ZW50IHtcbiAgICBpZiAoIXRoaXMuX3N0YXJ0ZWQpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcigncHJvZmlsZXIgaXMgbm90IHN0YXJ0ZWQgeWV0Jyk7XG4gICAgfVxuICAgIGlmIChjdHggPT09IHVuZGVmaW5lZCkge1xuICAgICAgY29uc3Qgc3RhcnRUaW1lID0gbm93KCk7XG4gICAgICB0aGlzLmZsdXNoKHN0YXJ0VGltZSk7XG4gICAgICByZXR1cm4gbmV3IEV2ZW50KGNhdGVnb3J5LCBuYW1lLCBzdGFydFRpbWUsIGUgPT4gdGhpcy5lbmRTeW5jKGUpKTtcbiAgICB9IGVsc2Uge1xuICAgICAgY29uc3QgdGltZXI6IFdlYkdMUXVlcnkgPSBjdHguYmVnaW5UaW1lcigpO1xuICAgICAgcmV0dXJuIG5ldyBFdmVudChjYXRlZ29yeSwgbmFtZSwgMCwgYXN5bmMgZSA9PiB0aGlzLmVuZChlKSwgdGltZXIsIGN0eCk7XG4gICAgfVxuICB9XG5cbiAgLy8gZW5kIHRoZSBzcGVjaWZpYyBldmVudFxuICBwcml2YXRlIGFzeW5jIGVuZChldmVudDogRXZlbnQpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBjb25zdCBlbmRUaW1lOiBudW1iZXIgPSBhd2FpdCBldmVudC5jaGVja1RpbWVyKCk7XG4gICAgaWYgKHRoaXMuX3RpbWluZ0V2ZW50cy5sZW5ndGggPCB0aGlzLl9tYXhOdW1iZXJFdmVudHMpIHtcbiAgICAgIHRoaXMuX3RpbWluZ0V2ZW50cy5wdXNoKG5ldyBFdmVudFJlY29yZChldmVudC5jYXRlZ29yeSwgZXZlbnQubmFtZSwgZXZlbnQuc3RhcnRUaW1lLCBlbmRUaW1lKSk7XG4gICAgICB0aGlzLmZsdXNoKGVuZFRpbWUpO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgZW5kU3luYyhldmVudDogRXZlbnQpOiB2b2lkIHtcbiAgICBjb25zdCBlbmRUaW1lOiBudW1iZXIgPSBub3coKTtcbiAgICBpZiAodGhpcy5fdGltaW5nRXZlbnRzLmxlbmd0aCA8IHRoaXMuX21heE51bWJlckV2ZW50cykge1xuICAgICAgdGhpcy5fdGltaW5nRXZlbnRzLnB1c2gobmV3IEV2ZW50UmVjb3JkKGV2ZW50LmNhdGVnb3J5LCBldmVudC5uYW1lLCBldmVudC5zdGFydFRpbWUsIGVuZFRpbWUpKTtcbiAgICAgIHRoaXMuZmx1c2goZW5kVGltZSk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBsb2dPbmVFdmVudChldmVudDogRXZlbnRSZWNvcmQpIHtcbiAgICBMb2dnZXIudmVyYm9zZShcbiAgICAgICAgYFByb2ZpbGVyLiR7ZXZlbnQuY2F0ZWdvcnl9YCxcbiAgICAgICAgYCR7KGV2ZW50LmVuZFRpbWUgLSBldmVudC5zdGFydFRpbWUpLnRvRml4ZWQoMil9bXMgb24gZXZlbnQgJyR7ZXZlbnQubmFtZX0nIGF0ICR7ZXZlbnQuZW5kVGltZS50b0ZpeGVkKDIpfWApO1xuICB9XG5cbiAgcHJpdmF0ZSBmbHVzaChjdXJyZW50VGltZTogbnVtYmVyKSB7XG4gICAgaWYgKHRoaXMuX3RpbWluZ0V2ZW50cy5sZW5ndGggLSB0aGlzLl9mbHVzaFBvaW50ZXIgPj0gdGhpcy5fZmx1c2hCYXRjaFNpemUgfHxcbiAgICAgICAgY3VycmVudFRpbWUgLSB0aGlzLl9mbHVzaFRpbWUgPj0gdGhpcy5fZmx1c2hJbnRlcnZhbEluTWlsbGlzZWNvbmRzKSB7XG4gICAgICAvLyBzaG91bGQgZmx1c2ggd2hlbiBlaXRoZXIgYmF0Y2ggc2l6ZSBhY2N1bWxhdGVkIG9yIGludGVydmFsIGVsZXBzZWRcblxuICAgICAgZm9yIChjb25zdCBwcmV2aW91c1BvaW50ZXIgPSB0aGlzLl9mbHVzaFBvaW50ZXI7IHRoaXMuX2ZsdXNoUG9pbnRlciA8IHByZXZpb3VzUG9pbnRlciArIHRoaXMuX2ZsdXNoQmF0Y2hTaXplICYmXG4gICAgICAgICAgIHRoaXMuX2ZsdXNoUG9pbnRlciA8IHRoaXMuX3RpbWluZ0V2ZW50cy5sZW5ndGg7XG4gICAgICAgICAgIHRoaXMuX2ZsdXNoUG9pbnRlcisrKSB7XG4gICAgICAgIHRoaXMubG9nT25lRXZlbnQodGhpcy5fdGltaW5nRXZlbnRzW3RoaXMuX2ZsdXNoUG9pbnRlcl0pO1xuICAgICAgfVxuXG4gICAgICB0aGlzLl9mbHVzaFRpbWUgPSBub3coKTtcbiAgICB9XG4gIH1cblxuICBnZXQgc3RhcnRlZCgpIHtcbiAgICByZXR1cm4gdGhpcy5fc3RhcnRlZDtcbiAgfVxuICBwcml2YXRlIF9zdGFydGVkID0gZmFsc2U7XG4gIHByaXZhdGUgX3RpbWluZ0V2ZW50czogRXZlbnRSZWNvcmRbXTtcblxuICBwcml2YXRlIHJlYWRvbmx5IF9tYXhOdW1iZXJFdmVudHM6IG51bWJlcjtcblxuICBwcml2YXRlIHJlYWRvbmx5IF9mbHVzaEJhdGNoU2l6ZTogbnVtYmVyO1xuICBwcml2YXRlIHJlYWRvbmx5IF9mbHVzaEludGVydmFsSW5NaWxsaXNlY29uZHM6IG51bWJlcjtcblxuICBwcml2YXRlIF9mbHVzaFRpbWU6IG51bWJlcjtcbiAgcHJpdmF0ZSBfZmx1c2hQb2ludGVyID0gMDtcbn1cblxuLyoqXG4gKiByZXR1cm5zIGEgbnVtYmVyIHRvIHJlcHJlc2VudCB0aGUgY3VycmVudCB0aW1lc3RhbXAgaW4gYSByZXNvbHV0aW9uIGFzIGhpZ2ggYXMgcG9zc2libGUuXG4gKi9cbmV4cG9ydCBjb25zdCBub3cgPSAodHlwZW9mIHBlcmZvcm1hbmNlICE9PSAndW5kZWZpbmVkJyAmJiBwZXJmb3JtYW5jZS5ub3cpID8gKCkgPT4gcGVyZm9ybWFuY2Uubm93KCkgOiBEYXRlLm5vdztcbiIsIi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxuXG5pbXBvcnQge2ZsYXRidWZmZXJzfSBmcm9tICdmbGF0YnVmZmVycyc7XG5pbXBvcnQge29ubnh9IGZyb20gJ29ubngtcHJvdG8nO1xuXG5pbXBvcnQge0dyYXBofSBmcm9tICcuL2dyYXBoJztcbmltcG9ydCB7T3BTZXR9IGZyb20gJy4vb3BzZXQnO1xuaW1wb3J0IHtvbm54cnVudGltZX0gZnJvbSAnLi9vcnQtc2NoZW1hL29ydC1nZW5lcmF0ZWQnO1xuaW1wb3J0IHtMb25nVXRpbH0gZnJvbSAnLi91dGlsJztcblxuaW1wb3J0IG9ydEZicyA9IG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnM7XG5cbmV4cG9ydCBjbGFzcyBNb2RlbCB7XG4gIC8vIGVtcHR5IG1vZGVsXG4gIGNvbnN0cnVjdG9yKCkge31cblxuICBsb2FkKGJ1ZjogVWludDhBcnJheSwgZ3JhcGhJbml0aWFsaXplcj86IEdyYXBoLkluaXRpYWxpemVyLCBpc09ydEZvcm1hdD86IGJvb2xlYW4pOiB2b2lkIHtcbiAgICBpZiAoIWlzT3J0Rm9ybWF0KSB7XG4gICAgICAvLyBpc09ydEZvcm1hdCA9PT0gZmFsc2UgfHwgaXNPcnRGb3JtYXQgPT09IHVuZGVmaW5lZFxuICAgICAgdHJ5IHtcbiAgICAgICAgdGhpcy5sb2FkRnJvbU9ubnhGb3JtYXQoYnVmLCBncmFwaEluaXRpYWxpemVyKTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICBpZiAoaXNPcnRGb3JtYXQgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgIHRocm93IGU7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICB0aGlzLmxvYWRGcm9tT3J0Rm9ybWF0KGJ1ZiwgZ3JhcGhJbml0aWFsaXplcik7XG4gIH1cblxuICBwcml2YXRlIGxvYWRGcm9tT25ueEZvcm1hdChidWY6IFVpbnQ4QXJyYXksIGdyYXBoSW5pdGlhbGl6ZXI/OiBHcmFwaC5Jbml0aWFsaXplcik6IHZvaWQge1xuICAgIGNvbnN0IG1vZGVsUHJvdG8gPSBvbm54Lk1vZGVsUHJvdG8uZGVjb2RlKGJ1Zik7XG4gICAgY29uc3QgaXJWZXJzaW9uID0gTG9uZ1V0aWwubG9uZ1RvTnVtYmVyKG1vZGVsUHJvdG8uaXJWZXJzaW9uKTtcbiAgICBpZiAoaXJWZXJzaW9uIDwgMykge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdvbmx5IHN1cHBvcnQgT05OWCBtb2RlbCB3aXRoIElSX1ZFUlNJT04+PTMnKTtcbiAgICB9XG5cbiAgICB0aGlzLl9vcHNldHMgPVxuICAgICAgICBtb2RlbFByb3RvLm9wc2V0SW1wb3J0Lm1hcChpID0+ICh7ZG9tYWluOiBpLmRvbWFpbiBhcyBzdHJpbmcsIHZlcnNpb246IExvbmdVdGlsLmxvbmdUb051bWJlcihpLnZlcnNpb24hKX0pKTtcblxuICAgIHRoaXMuX2dyYXBoID0gR3JhcGguZnJvbShtb2RlbFByb3RvLmdyYXBoISwgZ3JhcGhJbml0aWFsaXplcik7XG4gIH1cblxuICBwcml2YXRlIGxvYWRGcm9tT3J0Rm9ybWF0KGJ1ZjogVWludDhBcnJheSwgZ3JhcGhJbml0aWFsaXplcj86IEdyYXBoLkluaXRpYWxpemVyKTogdm9pZCB7XG4gICAgY29uc3QgZmIgPSBuZXcgZmxhdGJ1ZmZlcnMuQnl0ZUJ1ZmZlcihidWYpO1xuICAgIGNvbnN0IG9ydE1vZGVsID0gb3J0RmJzLkluZmVyZW5jZVNlc3Npb24uZ2V0Um9vdEFzSW5mZXJlbmNlU2Vzc2lvbihmYikubW9kZWwoKSE7XG4gICAgY29uc3QgaXJWZXJzaW9uID0gTG9uZ1V0aWwubG9uZ1RvTnVtYmVyKG9ydE1vZGVsLmlyVmVyc2lvbigpKTtcbiAgICBpZiAoaXJWZXJzaW9uIDwgMykge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdvbmx5IHN1cHBvcnQgT05OWCBtb2RlbCB3aXRoIElSX1ZFUlNJT04+PTMnKTtcbiAgICB9XG4gICAgdGhpcy5fb3BzZXRzID0gW107XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBvcnRNb2RlbC5vcHNldEltcG9ydExlbmd0aCgpOyBpKyspIHtcbiAgICAgIGNvbnN0IG9wc2V0SWQgPSBvcnRNb2RlbC5vcHNldEltcG9ydChpKSE7XG4gICAgICB0aGlzLl9vcHNldHMucHVzaCh7ZG9tYWluOiBvcHNldElkPy5kb21haW4oKSBhcyBzdHJpbmcsIHZlcnNpb246IExvbmdVdGlsLmxvbmdUb051bWJlcihvcHNldElkLnZlcnNpb24oKSEpfSk7XG4gICAgfVxuXG4gICAgdGhpcy5fZ3JhcGggPSBHcmFwaC5mcm9tKG9ydE1vZGVsLmdyYXBoKCkhLCBncmFwaEluaXRpYWxpemVyKTtcbiAgfVxuXG4gIHByaXZhdGUgX2dyYXBoOiBHcmFwaDtcbiAgZ2V0IGdyYXBoKCk6IEdyYXBoIHtcbiAgICByZXR1cm4gdGhpcy5fZ3JhcGg7XG4gIH1cblxuICBwcml2YXRlIF9vcHNldHM6IE9wU2V0W107XG4gIGdldCBvcHNldHMoKTogcmVhZG9ubHkgT3BTZXRbXSB7XG4gICAgcmV0dXJuIHRoaXMuX29wc2V0cztcbiAgfVxufVxuIiwiLy8gQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXG5cbmltcG9ydCB7SW5mZXJlbmNlSGFuZGxlcn0gZnJvbSAnLi9iYWNrZW5kJztcbmltcG9ydCB7R3JhcGh9IGZyb20gJy4vZ3JhcGgnO1xuaW1wb3J0IHtUZW5zb3J9IGZyb20gJy4vdGVuc29yJztcblxuZXhwb3J0IHR5cGUgT3BlcmF0b3JJbXBsZW1lbnRhdGlvbjxUPiA9IChpbmZlcmVuY2VIYW5kbGVyOiBJbmZlcmVuY2VIYW5kbGVyLCBpbnB1dHM6IFRlbnNvcltdLCBjb250ZXh0OiBUKSA9PiBUZW5zb3JbXTtcbmV4cG9ydCB0eXBlIE9wZXJhdG9ySW5pdGlhbGl6YXRpb248VD4gPSAobm9kZTogR3JhcGguTm9kZSwgZ3JhcGg6IEdyYXBoKSA9PiBUO1xuXG5leHBvcnQgaW50ZXJmYWNlIE9wZXJhdG9yIHtcbiAgcmVhZG9ubHkgaW1wbDogT3BlcmF0b3JJbXBsZW1lbnRhdGlvbjx1bmtub3duPjtcbiAgcmVhZG9ubHkgY29udGV4dDogR3JhcGguTm9kZXx1bmtub3duO1xufVxuXG5leHBvcnQgY29uc3QgTlVNQkVSX1RZUEVTOiByZWFkb25seSBUZW5zb3IuRGF0YVR5cGVbXSA9XG4gICAgWydmbG9hdDMyJywgJ2Zsb2F0NjQnLCAnaW50MzInLCAnaW50MTYnLCAnaW50OCcsICd1aW50MTYnLCAndWludDMyJywgJ3VpbnQ4J107XG5leHBvcnQgY29uc3QgSU5UX1RZUEVTOiByZWFkb25seSBUZW5zb3IuRGF0YVR5cGVbXSA9IFsnaW50MzInLCAnaW50MTYnLCAnaW50OCcsICd1aW50MTYnLCAndWludDMyJywgJ3VpbnQ4J107XG5leHBvcnQgY29uc3QgRkxPQVRfVFlQRVM6IHJlYWRvbmx5IFRlbnNvci5EYXRhVHlwZVtdID0gWydmbG9hdDMyJywgJ2Zsb2F0NjQnXTtcbiIsIi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxuXG5pbXBvcnQge0dyYXBofSBmcm9tICcuL2dyYXBoJztcbmltcG9ydCB7T3BlcmF0b3JJbXBsZW1lbnRhdGlvbiwgT3BlcmF0b3JJbml0aWFsaXphdGlvbn0gZnJvbSAnLi9vcGVyYXRvcnMnO1xuXG5leHBvcnQgaW50ZXJmYWNlIE9wU2V0IHtcbiAgZG9tYWluOiBzdHJpbmc7XG4gIHZlcnNpb246IG51bWJlcjtcbn1cblxuZXhwb3J0IGRlY2xhcmUgbmFtZXNwYWNlIE9wU2V0IHtcbiAgLyoqXG4gICAqIERvbWFpbiBvZiBhbiBvcHNldCwgaXQgY2FuIGJlIGFuIGVtcHR5IHN0cmluZyhkZWZhdWx0IHZhbHVlLCByZXByZXNlbnQgZm9yIGFpLm9ubngpLCBvciAnYWkub25ueC5tbCdcbiAgICovXG4gIHR5cGUgRG9tYWluID0gJyd8J2FpLm9ubngubWwnfCdjb20ubWljcm9zb2Z0JztcblxuICAvKipcbiAgICogQSByZXNvbHZlIHJ1bGUgY29uc2lzdHMgb2YgNCBvciA1IGl0ZW1zOiBvcFR5cGUsIG9wU2V0RG9tYWluLCB2ZXJzaW9uU2VsZWN0b3IsIG9wZXJhdG9ySW1wbGVtZW50YXRpb24gYW5kXG4gICAqIG9wZXJhdG9ySW5pdGlhbGl6YXRpb24gKG9wdGlvbmFsKVxuICAgKi9cbiAgdHlwZSBSZXNvbHZlUnVsZSA9IFtcbiAgICBzdHJpbmcsIERvbWFpbiwgc3RyaW5nLCBPcGVyYXRvckltcGxlbWVudGF0aW9uPEdyYXBoLk5vZGU+XG4gIF18W3N0cmluZywgRG9tYWluLCBzdHJpbmcsIE9wZXJhdG9ySW1wbGVtZW50YXRpb248dW5rbm93bj4sIE9wZXJhdG9ySW5pdGlhbGl6YXRpb248dW5rbm93bj5dO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gcmVzb2x2ZU9wZXJhdG9yKG5vZGU6IEdyYXBoLk5vZGUsIG9wc2V0czogcmVhZG9ubHkgT3BTZXRbXSwgcnVsZXM6IHJlYWRvbmx5IE9wU2V0LlJlc29sdmVSdWxlW10pIHtcbiAgZm9yIChjb25zdCBydWxlIG9mIHJ1bGVzKSB7XG4gICAgY29uc3Qgb3BUeXBlID0gcnVsZVswXTtcbiAgICBjb25zdCBkb21haW4gPSBydWxlWzFdO1xuICAgIGNvbnN0IHZlcnNpb25TZWxlY3RvciA9IHJ1bGVbMl07XG4gICAgY29uc3Qgb3BJbXBsID0gcnVsZVszXTtcbiAgICBjb25zdCBvcEluaXQgPSBydWxlWzRdO1xuXG4gICAgaWYgKG5vZGUub3BUeXBlID09PSBvcFR5cGUpIHsgIC8vIG9wZXJhdG9yIHR5cGUgbWF0Y2hlc1xuICAgICAgZm9yIChjb25zdCBvcHNldCBvZiBvcHNldHMpIHtcbiAgICAgICAgLy8gb3BzZXQgJycgYW5kICdhaS5vbm54JyBhcmUgY29uc2lkZXJlZCB0aGUgc2FtZS5cbiAgICAgICAgaWYgKG9wc2V0LmRvbWFpbiA9PT0gZG9tYWluIHx8IChvcHNldC5kb21haW4gPT09ICdhaS5vbm54JyAmJiBkb21haW4gPT09ICcnKSkgeyAgLy8gb3BzZXQgZG9tYWluIGZvdW5kXG4gICAgICAgICAgaWYgKG1hdGNoU2VsZWN0b3Iob3BzZXQudmVyc2lvbiwgdmVyc2lvblNlbGVjdG9yKSkge1xuICAgICAgICAgICAgcmV0dXJuIHtvcEltcGwsIG9wSW5pdH07XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgdGhyb3cgbmV3IFR5cGVFcnJvcihgY2Fubm90IHJlc29sdmUgb3BlcmF0b3IgJyR7bm9kZS5vcFR5cGV9JyB3aXRoIG9wc2V0czogJHtcbiAgICAgIG9wc2V0cy5tYXAoc2V0ID0+IGAke3NldC5kb21haW4gfHwgJ2FpLm9ubngnfSB2JHtzZXQudmVyc2lvbn1gKS5qb2luKCcsICcpfWApO1xufVxuXG5mdW5jdGlvbiBtYXRjaFNlbGVjdG9yKHZlcnNpb246IG51bWJlciwgc2VsZWN0b3I6IHN0cmluZyk6IGJvb2xlYW4ge1xuICBpZiAoc2VsZWN0b3IuZW5kc1dpdGgoJysnKSkge1xuICAgIC8vIG1pbmltdW0gdmVyc2lvbiBtYXRjaCAoJzcrJyBleHBlY3RzIHZlcnNpb24+PTcpXG4gICAgY29uc3QgcmFuZ2VTdGFydCA9IE51bWJlci5wYXJzZUludChzZWxlY3Rvci5zdWJzdHJpbmcoMCwgc2VsZWN0b3IubGVuZ3RoIC0gMSksIDEwKTtcbiAgICByZXR1cm4gIWlzTmFOKHJhbmdlU3RhcnQpICYmIHJhbmdlU3RhcnQgPD0gdmVyc2lvbjtcbiAgfSBlbHNlIGlmIChzZWxlY3Rvci5zcGxpdCgnLScpLmxlbmd0aCA9PT0gMikge1xuICAgIC8vIHJhbmdlIG1hdGNoICgnNi04JyBleHBlY3RzIDY8PXZlcnNpb248PTgpXG4gICAgY29uc3QgcGFpciA9IHNlbGVjdG9yLnNwbGl0KCctJyk7XG4gICAgY29uc3QgcmFuZ2VTdGFydCA9IE51bWJlci5wYXJzZUludChwYWlyWzBdLCAxMCk7XG4gICAgY29uc3QgcmFuZ2VFbmQgPSBOdW1iZXIucGFyc2VJbnQocGFpclsxXSwgMTApO1xuICAgIHJldHVybiAhaXNOYU4ocmFuZ2VTdGFydCkgJiYgIWlzTmFOKHJhbmdlRW5kKSAmJiByYW5nZVN0YXJ0IDw9IHZlcnNpb24gJiYgdmVyc2lvbiA8PSByYW5nZUVuZDtcbiAgfSBlbHNlIHtcbiAgICAvLyBleGFjdCBtYXRjaCAoJzcnIGV4cGVjdHMgdmVyc2lvbj09PTcpXG4gICAgcmV0dXJuIE51bWJlci5wYXJzZUludChzZWxlY3RvciwgMTApID09PSB2ZXJzaW9uO1xuICB9XG59XG4iLCIvLyBhdXRvbWF0aWNhbGx5IGdlbmVyYXRlZCBieSB0aGUgRmxhdEJ1ZmZlcnMgY29tcGlsZXIsIGRvIG5vdCBtb2RpZnlcbi8qIGVzbGludC1kaXNhYmxlICovXG5cbmltcG9ydCB7ZmxhdGJ1ZmZlcnN9IGZyb20gJ2ZsYXRidWZmZXJzJztcblxuLyoqXG4gKiBAZW51bSB7bnVtYmVyfVxuICovXG5leHBvcnQgbmFtZXNwYWNlIG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnMge1xuICBleHBvcnQgZW51bSBBdHRyaWJ1dGVUeXBlIHtcbiAgICBVTkRFRklORUQgPSAwLFxuICAgIEZMT0FUID0gMSxcbiAgICBJTlQgPSAyLFxuICAgIFNUUklORyA9IDMsXG4gICAgVEVOU09SID0gNCxcbiAgICBHUkFQSCA9IDUsXG4gICAgRkxPQVRTID0gNixcbiAgICBJTlRTID0gNyxcbiAgICBTVFJJTkdTID0gOCxcbiAgICBURU5TT1JTID0gOSxcbiAgICBHUkFQSFMgPSAxMCxcbiAgICBTUEFSU0VfVEVOU09SID0gMTEsXG4gICAgU1BBUlNFX1RFTlNPUlMgPSAxMlxuICB9XG59XG5cbi8qKlxuICogQGVudW0ge251bWJlcn1cbiAqL1xuZXhwb3J0IG5hbWVzcGFjZSBvbm54cnVudGltZS5leHBlcmltZW50YWwuZmJzIHtcbiAgZXhwb3J0IGVudW0gRGltZW5zaW9uVmFsdWVUeXBlIHtVTktOT1dOID0gMCwgVkFMVUUgPSAxLCBQQVJBTSA9IDJ9XG59XG5cbi8qKlxuICogQGVudW0ge251bWJlcn1cbiAqL1xuZXhwb3J0IG5hbWVzcGFjZSBvbm54cnVudGltZS5leHBlcmltZW50YWwuZmJzIHtcbiAgZXhwb3J0IGVudW0gVGVuc29yRGF0YVR5cGUge1xuICAgIFVOREVGSU5FRCA9IDAsXG4gICAgRkxPQVQgPSAxLFxuICAgIFVJTlQ4ID0gMixcbiAgICBJTlQ4ID0gMyxcbiAgICBVSU5UMTYgPSA0LFxuICAgIElOVDE2ID0gNSxcbiAgICBJTlQzMiA9IDYsXG4gICAgSU5UNjQgPSA3LFxuICAgIFNUUklORyA9IDgsXG4gICAgQk9PTCA9IDksXG4gICAgRkxPQVQxNiA9IDEwLFxuICAgIERPVUJMRSA9IDExLFxuICAgIFVJTlQzMiA9IDEyLFxuICAgIFVJTlQ2NCA9IDEzLFxuICAgIENPTVBMRVg2NCA9IDE0LFxuICAgIENPTVBMRVgxMjggPSAxNSxcbiAgICBCRkxPQVQxNiA9IDE2XG4gIH1cbn1cblxuLyoqXG4gKiBAZW51bSB7bnVtYmVyfVxuICovXG5leHBvcnQgbmFtZXNwYWNlIG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnMge1xuICBleHBvcnQgZW51bSBOb2RlVHlwZSB7UHJpbWl0aXZlID0gMCwgRnVzZWQgPSAxfVxufVxuXG4vKipcbiAqIEBlbnVtIHtudW1iZXJ9XG4gKi9cbmV4cG9ydCBuYW1lc3BhY2Ugb25ueHJ1bnRpbWUuZXhwZXJpbWVudGFsLmZicyB7XG4gIGV4cG9ydCBlbnVtIFR5cGVJbmZvVmFsdWUge05PTkUgPSAwLCB0ZW5zb3JfdHlwZSA9IDEsIHNlcXVlbmNlX3R5cGUgPSAyLCBtYXBfdHlwZSA9IDN9XG59XG5cbi8qKlxuICogQGNvbnN0cnVjdG9yXG4gKi9cbmV4cG9ydCBuYW1lc3BhY2Ugb25ueHJ1bnRpbWUuZXhwZXJpbWVudGFsLmZicyB7XG4gIGV4cG9ydCBjbGFzcyBTaGFwZSB7XG4gICAgYmI6IGZsYXRidWZmZXJzLkJ5dGVCdWZmZXJ8bnVsbCA9IG51bGw7XG5cbiAgICBiYl9wb3MgPSAwO1xuICAgIC8qKlxuICAgICAqIEBwYXJhbSBudW1iZXIgaVxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CeXRlQnVmZmVyIGJiXG4gICAgICogQHJldHVybnMgU2hhcGVcbiAgICAgKi9cbiAgICBfX2luaXQoaTogbnVtYmVyLCBiYjogZmxhdGJ1ZmZlcnMuQnl0ZUJ1ZmZlcik6IFNoYXBlIHtcbiAgICAgIHRoaXMuYmJfcG9zID0gaTtcbiAgICAgIHRoaXMuYmIgPSBiYjtcbiAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CeXRlQnVmZmVyIGJiXG4gICAgICogQHBhcmFtIFNoYXBlPSBvYmpcbiAgICAgKiBAcmV0dXJucyBTaGFwZVxuICAgICAqL1xuICAgIHN0YXRpYyBnZXRSb290QXNTaGFwZShiYjogZmxhdGJ1ZmZlcnMuQnl0ZUJ1ZmZlciwgb2JqPzogU2hhcGUpOiBTaGFwZSB7XG4gICAgICByZXR1cm4gKG9iaiB8fCBuZXcgU2hhcGUoKSkuX19pbml0KGJiLnJlYWRJbnQzMihiYi5wb3NpdGlvbigpKSArIGJiLnBvc2l0aW9uKCksIGJiKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuQnl0ZUJ1ZmZlciBiYlxuICAgICAqIEBwYXJhbSBTaGFwZT0gb2JqXG4gICAgICogQHJldHVybnMgU2hhcGVcbiAgICAgKi9cbiAgICBzdGF0aWMgZ2V0U2l6ZVByZWZpeGVkUm9vdEFzU2hhcGUoYmI6IGZsYXRidWZmZXJzLkJ5dGVCdWZmZXIsIG9iaj86IFNoYXBlKTogU2hhcGUge1xuICAgICAgYmIuc2V0UG9zaXRpb24oYmIucG9zaXRpb24oKSArIGZsYXRidWZmZXJzLlNJWkVfUFJFRklYX0xFTkdUSCk7XG4gICAgICByZXR1cm4gKG9iaiB8fCBuZXcgU2hhcGUoKSkuX19pbml0KGJiLnJlYWRJbnQzMihiYi5wb3NpdGlvbigpKSArIGJiLnBvc2l0aW9uKCksIGJiKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gbnVtYmVyIGluZGV4XG4gICAgICogQHBhcmFtIG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnMuRGltZW5zaW9uPSBvYmpcbiAgICAgKiBAcmV0dXJucyBvbm54cnVudGltZS5leHBlcmltZW50YWwuZmJzLkRpbWVuc2lvblxuICAgICAqL1xuICAgIGRpbShpbmRleDogbnVtYmVyLCBvYmo/OiBvbm54cnVudGltZS5leHBlcmltZW50YWwuZmJzLkRpbWVuc2lvbik6IG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnMuRGltZW5zaW9ufG51bGwge1xuICAgICAgbGV0IG9mZnNldCA9IHRoaXMuYmIhLl9fb2Zmc2V0KHRoaXMuYmJfcG9zLCA0KTtcbiAgICAgIHJldHVybiBvZmZzZXQgPyAob2JqIHx8IG5ldyBvbm54cnVudGltZS5leHBlcmltZW50YWwuZmJzLkRpbWVuc2lvbigpKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAuX19pbml0KHRoaXMuYmIhLl9faW5kaXJlY3QodGhpcy5iYiEuX192ZWN0b3IodGhpcy5iYl9wb3MgKyBvZmZzZXQpICsgaW5kZXggKiA0KSwgdGhpcy5iYiEpIDpcbiAgICAgICAgICAgICAgICAgICAgICBudWxsO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEByZXR1cm5zIG51bWJlclxuICAgICAqL1xuICAgIGRpbUxlbmd0aCgpOiBudW1iZXIge1xuICAgICAgbGV0IG9mZnNldCA9IHRoaXMuYmIhLl9fb2Zmc2V0KHRoaXMuYmJfcG9zLCA0KTtcbiAgICAgIHJldHVybiBvZmZzZXQgPyB0aGlzLmJiIS5fX3ZlY3Rvcl9sZW4odGhpcy5iYl9wb3MgKyBvZmZzZXQpIDogMDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuQnVpbGRlciBidWlsZGVyXG4gICAgICovXG4gICAgc3RhdGljIHN0YXJ0U2hhcGUoYnVpbGRlcjogZmxhdGJ1ZmZlcnMuQnVpbGRlcikge1xuICAgICAgYnVpbGRlci5zdGFydE9iamVjdCgxKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuQnVpbGRlciBidWlsZGVyXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLk9mZnNldCBkaW1PZmZzZXRcbiAgICAgKi9cbiAgICBzdGF0aWMgYWRkRGltKGJ1aWxkZXI6IGZsYXRidWZmZXJzLkJ1aWxkZXIsIGRpbU9mZnNldDogZmxhdGJ1ZmZlcnMuT2Zmc2V0KSB7XG4gICAgICBidWlsZGVyLmFkZEZpZWxkT2Zmc2V0KDAsIGRpbU9mZnNldCwgMCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ1aWxkZXIgYnVpbGRlclxuICAgICAqIEBwYXJhbSBBcnJheS48ZmxhdGJ1ZmZlcnMuT2Zmc2V0PiBkYXRhXG4gICAgICogQHJldHVybnMgZmxhdGJ1ZmZlcnMuT2Zmc2V0XG4gICAgICovXG4gICAgc3RhdGljIGNyZWF0ZURpbVZlY3RvcihidWlsZGVyOiBmbGF0YnVmZmVycy5CdWlsZGVyLCBkYXRhOiBmbGF0YnVmZmVycy5PZmZzZXRbXSk6IGZsYXRidWZmZXJzLk9mZnNldCB7XG4gICAgICBidWlsZGVyLnN0YXJ0VmVjdG9yKDQsIGRhdGEubGVuZ3RoLCA0KTtcbiAgICAgIGZvciAobGV0IGkgPSBkYXRhLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSB7XG4gICAgICAgIGJ1aWxkZXIuYWRkT2Zmc2V0KGRhdGFbaV0pO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGJ1aWxkZXIuZW5kVmVjdG9yKCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ1aWxkZXIgYnVpbGRlclxuICAgICAqIEBwYXJhbSBudW1iZXIgbnVtRWxlbXNcbiAgICAgKi9cbiAgICBzdGF0aWMgc3RhcnREaW1WZWN0b3IoYnVpbGRlcjogZmxhdGJ1ZmZlcnMuQnVpbGRlciwgbnVtRWxlbXM6IG51bWJlcikge1xuICAgICAgYnVpbGRlci5zdGFydFZlY3Rvcig0LCBudW1FbGVtcywgNCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ1aWxkZXIgYnVpbGRlclxuICAgICAqIEByZXR1cm5zIGZsYXRidWZmZXJzLk9mZnNldFxuICAgICAqL1xuICAgIHN0YXRpYyBlbmRTaGFwZShidWlsZGVyOiBmbGF0YnVmZmVycy5CdWlsZGVyKTogZmxhdGJ1ZmZlcnMuT2Zmc2V0IHtcbiAgICAgIGxldCBvZmZzZXQgPSBidWlsZGVyLmVuZE9iamVjdCgpO1xuICAgICAgcmV0dXJuIG9mZnNldDtcbiAgICB9XG5cbiAgICBzdGF0aWMgY3JlYXRlU2hhcGUoYnVpbGRlcjogZmxhdGJ1ZmZlcnMuQnVpbGRlciwgZGltT2Zmc2V0OiBmbGF0YnVmZmVycy5PZmZzZXQpOiBmbGF0YnVmZmVycy5PZmZzZXQge1xuICAgICAgU2hhcGUuc3RhcnRTaGFwZShidWlsZGVyKTtcbiAgICAgIFNoYXBlLmFkZERpbShidWlsZGVyLCBkaW1PZmZzZXQpO1xuICAgICAgcmV0dXJuIFNoYXBlLmVuZFNoYXBlKGJ1aWxkZXIpO1xuICAgIH1cbiAgfVxufVxuLyoqXG4gKiBAY29uc3RydWN0b3JcbiAqL1xuZXhwb3J0IG5hbWVzcGFjZSBvbm54cnVudGltZS5leHBlcmltZW50YWwuZmJzIHtcbiAgZXhwb3J0IGNsYXNzIERpbWVuc2lvbiB7XG4gICAgYmI6IGZsYXRidWZmZXJzLkJ5dGVCdWZmZXJ8bnVsbCA9IG51bGw7XG5cbiAgICBiYl9wb3MgPSAwO1xuICAgIC8qKlxuICAgICAqIEBwYXJhbSBudW1iZXIgaVxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CeXRlQnVmZmVyIGJiXG4gICAgICogQHJldHVybnMgRGltZW5zaW9uXG4gICAgICovXG4gICAgX19pbml0KGk6IG51bWJlciwgYmI6IGZsYXRidWZmZXJzLkJ5dGVCdWZmZXIpOiBEaW1lbnNpb24ge1xuICAgICAgdGhpcy5iYl9wb3MgPSBpO1xuICAgICAgdGhpcy5iYiA9IGJiO1xuICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ5dGVCdWZmZXIgYmJcbiAgICAgKiBAcGFyYW0gRGltZW5zaW9uPSBvYmpcbiAgICAgKiBAcmV0dXJucyBEaW1lbnNpb25cbiAgICAgKi9cbiAgICBzdGF0aWMgZ2V0Um9vdEFzRGltZW5zaW9uKGJiOiBmbGF0YnVmZmVycy5CeXRlQnVmZmVyLCBvYmo/OiBEaW1lbnNpb24pOiBEaW1lbnNpb24ge1xuICAgICAgcmV0dXJuIChvYmogfHwgbmV3IERpbWVuc2lvbigpKS5fX2luaXQoYmIucmVhZEludDMyKGJiLnBvc2l0aW9uKCkpICsgYmIucG9zaXRpb24oKSwgYmIpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CeXRlQnVmZmVyIGJiXG4gICAgICogQHBhcmFtIERpbWVuc2lvbj0gb2JqXG4gICAgICogQHJldHVybnMgRGltZW5zaW9uXG4gICAgICovXG4gICAgc3RhdGljIGdldFNpemVQcmVmaXhlZFJvb3RBc0RpbWVuc2lvbihiYjogZmxhdGJ1ZmZlcnMuQnl0ZUJ1ZmZlciwgb2JqPzogRGltZW5zaW9uKTogRGltZW5zaW9uIHtcbiAgICAgIGJiLnNldFBvc2l0aW9uKGJiLnBvc2l0aW9uKCkgKyBmbGF0YnVmZmVycy5TSVpFX1BSRUZJWF9MRU5HVEgpO1xuICAgICAgcmV0dXJuIChvYmogfHwgbmV3IERpbWVuc2lvbigpKS5fX2luaXQoYmIucmVhZEludDMyKGJiLnBvc2l0aW9uKCkpICsgYmIucG9zaXRpb24oKSwgYmIpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBvbm54cnVudGltZS5leHBlcmltZW50YWwuZmJzLkRpbWVuc2lvblZhbHVlPSBvYmpcbiAgICAgKiBAcmV0dXJucyBvbm54cnVudGltZS5leHBlcmltZW50YWwuZmJzLkRpbWVuc2lvblZhbHVlfG51bGxcbiAgICAgKi9cbiAgICB2YWx1ZShvYmo/OiBvbm54cnVudGltZS5leHBlcmltZW50YWwuZmJzLkRpbWVuc2lvblZhbHVlKTogb25ueHJ1bnRpbWUuZXhwZXJpbWVudGFsLmZicy5EaW1lbnNpb25WYWx1ZXxudWxsIHtcbiAgICAgIGxldCBvZmZzZXQgPSB0aGlzLmJiIS5fX29mZnNldCh0aGlzLmJiX3BvcywgNCk7XG4gICAgICByZXR1cm4gb2Zmc2V0ID8gKG9iaiB8fCBuZXcgb25ueHJ1bnRpbWUuZXhwZXJpbWVudGFsLmZicy5EaW1lbnNpb25WYWx1ZSgpKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAuX19pbml0KHRoaXMuYmIhLl9faW5kaXJlY3QodGhpcy5iYl9wb3MgKyBvZmZzZXQpLCB0aGlzLmJiISkgOlxuICAgICAgICAgICAgICAgICAgICAgIG51bGw7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkVuY29kaW5nPSBvcHRpb25hbEVuY29kaW5nXG4gICAgICogQHJldHVybnMgc3RyaW5nfFVpbnQ4QXJyYXl8bnVsbFxuICAgICAqL1xuICAgIGRlbm90YXRpb24oKTogc3RyaW5nfG51bGw7XG4gICAgZGVub3RhdGlvbihvcHRpb25hbEVuY29kaW5nOiBmbGF0YnVmZmVycy5FbmNvZGluZyk6IHN0cmluZ3xVaW50OEFycmF5fG51bGw7XG4gICAgZGVub3RhdGlvbihvcHRpb25hbEVuY29kaW5nPzogYW55KTogc3RyaW5nfFVpbnQ4QXJyYXl8bnVsbCB7XG4gICAgICBsZXQgb2Zmc2V0ID0gdGhpcy5iYiEuX19vZmZzZXQodGhpcy5iYl9wb3MsIDYpO1xuICAgICAgcmV0dXJuIG9mZnNldCA/IHRoaXMuYmIhLl9fc3RyaW5nKHRoaXMuYmJfcG9zICsgb2Zmc2V0LCBvcHRpb25hbEVuY29kaW5nKSA6IG51bGw7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ1aWxkZXIgYnVpbGRlclxuICAgICAqL1xuICAgIHN0YXRpYyBzdGFydERpbWVuc2lvbihidWlsZGVyOiBmbGF0YnVmZmVycy5CdWlsZGVyKSB7XG4gICAgICBidWlsZGVyLnN0YXJ0T2JqZWN0KDIpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CdWlsZGVyIGJ1aWxkZXJcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuT2Zmc2V0IHZhbHVlT2Zmc2V0XG4gICAgICovXG4gICAgc3RhdGljIGFkZFZhbHVlKGJ1aWxkZXI6IGZsYXRidWZmZXJzLkJ1aWxkZXIsIHZhbHVlT2Zmc2V0OiBmbGF0YnVmZmVycy5PZmZzZXQpIHtcbiAgICAgIGJ1aWxkZXIuYWRkRmllbGRPZmZzZXQoMCwgdmFsdWVPZmZzZXQsIDApO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CdWlsZGVyIGJ1aWxkZXJcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuT2Zmc2V0IGRlbm90YXRpb25PZmZzZXRcbiAgICAgKi9cbiAgICBzdGF0aWMgYWRkRGVub3RhdGlvbihidWlsZGVyOiBmbGF0YnVmZmVycy5CdWlsZGVyLCBkZW5vdGF0aW9uT2Zmc2V0OiBmbGF0YnVmZmVycy5PZmZzZXQpIHtcbiAgICAgIGJ1aWxkZXIuYWRkRmllbGRPZmZzZXQoMSwgZGVub3RhdGlvbk9mZnNldCwgMCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ1aWxkZXIgYnVpbGRlclxuICAgICAqIEByZXR1cm5zIGZsYXRidWZmZXJzLk9mZnNldFxuICAgICAqL1xuICAgIHN0YXRpYyBlbmREaW1lbnNpb24oYnVpbGRlcjogZmxhdGJ1ZmZlcnMuQnVpbGRlcik6IGZsYXRidWZmZXJzLk9mZnNldCB7XG4gICAgICBsZXQgb2Zmc2V0ID0gYnVpbGRlci5lbmRPYmplY3QoKTtcbiAgICAgIHJldHVybiBvZmZzZXQ7XG4gICAgfVxuXG4gICAgc3RhdGljIGNyZWF0ZURpbWVuc2lvbihcbiAgICAgICAgYnVpbGRlcjogZmxhdGJ1ZmZlcnMuQnVpbGRlciwgdmFsdWVPZmZzZXQ6IGZsYXRidWZmZXJzLk9mZnNldCxcbiAgICAgICAgZGVub3RhdGlvbk9mZnNldDogZmxhdGJ1ZmZlcnMuT2Zmc2V0KTogZmxhdGJ1ZmZlcnMuT2Zmc2V0IHtcbiAgICAgIERpbWVuc2lvbi5zdGFydERpbWVuc2lvbihidWlsZGVyKTtcbiAgICAgIERpbWVuc2lvbi5hZGRWYWx1ZShidWlsZGVyLCB2YWx1ZU9mZnNldCk7XG4gICAgICBEaW1lbnNpb24uYWRkRGVub3RhdGlvbihidWlsZGVyLCBkZW5vdGF0aW9uT2Zmc2V0KTtcbiAgICAgIHJldHVybiBEaW1lbnNpb24uZW5kRGltZW5zaW9uKGJ1aWxkZXIpO1xuICAgIH1cbiAgfVxufVxuLyoqXG4gKiBAY29uc3RydWN0b3JcbiAqL1xuZXhwb3J0IG5hbWVzcGFjZSBvbm54cnVudGltZS5leHBlcmltZW50YWwuZmJzIHtcbiAgZXhwb3J0IGNsYXNzIERpbWVuc2lvblZhbHVlIHtcbiAgICBiYjogZmxhdGJ1ZmZlcnMuQnl0ZUJ1ZmZlcnxudWxsID0gbnVsbDtcblxuICAgIGJiX3BvcyA9IDA7XG4gICAgLyoqXG4gICAgICogQHBhcmFtIG51bWJlciBpXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ5dGVCdWZmZXIgYmJcbiAgICAgKiBAcmV0dXJucyBEaW1lbnNpb25WYWx1ZVxuICAgICAqL1xuICAgIF9faW5pdChpOiBudW1iZXIsIGJiOiBmbGF0YnVmZmVycy5CeXRlQnVmZmVyKTogRGltZW5zaW9uVmFsdWUge1xuICAgICAgdGhpcy5iYl9wb3MgPSBpO1xuICAgICAgdGhpcy5iYiA9IGJiO1xuICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ5dGVCdWZmZXIgYmJcbiAgICAgKiBAcGFyYW0gRGltZW5zaW9uVmFsdWU9IG9ialxuICAgICAqIEByZXR1cm5zIERpbWVuc2lvblZhbHVlXG4gICAgICovXG4gICAgc3RhdGljIGdldFJvb3RBc0RpbWVuc2lvblZhbHVlKGJiOiBmbGF0YnVmZmVycy5CeXRlQnVmZmVyLCBvYmo/OiBEaW1lbnNpb25WYWx1ZSk6IERpbWVuc2lvblZhbHVlIHtcbiAgICAgIHJldHVybiAob2JqIHx8IG5ldyBEaW1lbnNpb25WYWx1ZSgpKS5fX2luaXQoYmIucmVhZEludDMyKGJiLnBvc2l0aW9uKCkpICsgYmIucG9zaXRpb24oKSwgYmIpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CeXRlQnVmZmVyIGJiXG4gICAgICogQHBhcmFtIERpbWVuc2lvblZhbHVlPSBvYmpcbiAgICAgKiBAcmV0dXJucyBEaW1lbnNpb25WYWx1ZVxuICAgICAqL1xuICAgIHN0YXRpYyBnZXRTaXplUHJlZml4ZWRSb290QXNEaW1lbnNpb25WYWx1ZShiYjogZmxhdGJ1ZmZlcnMuQnl0ZUJ1ZmZlciwgb2JqPzogRGltZW5zaW9uVmFsdWUpOiBEaW1lbnNpb25WYWx1ZSB7XG4gICAgICBiYi5zZXRQb3NpdGlvbihiYi5wb3NpdGlvbigpICsgZmxhdGJ1ZmZlcnMuU0laRV9QUkVGSVhfTEVOR1RIKTtcbiAgICAgIHJldHVybiAob2JqIHx8IG5ldyBEaW1lbnNpb25WYWx1ZSgpKS5fX2luaXQoYmIucmVhZEludDMyKGJiLnBvc2l0aW9uKCkpICsgYmIucG9zaXRpb24oKSwgYmIpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEByZXR1cm5zIG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnMuRGltZW5zaW9uVmFsdWVUeXBlXG4gICAgICovXG4gICAgZGltVHlwZSgpOiBvbm54cnVudGltZS5leHBlcmltZW50YWwuZmJzLkRpbWVuc2lvblZhbHVlVHlwZSB7XG4gICAgICBsZXQgb2Zmc2V0ID0gdGhpcy5iYiEuX19vZmZzZXQodGhpcy5iYl9wb3MsIDQpO1xuICAgICAgcmV0dXJuIG9mZnNldCA/IC8qKiAgKi8gKHRoaXMuYmIhLnJlYWRJbnQ4KHRoaXMuYmJfcG9zICsgb2Zmc2V0KSkgOlxuICAgICAgICAgICAgICAgICAgICAgIG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnMuRGltZW5zaW9uVmFsdWVUeXBlLlVOS05PV047XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHJldHVybnMgZmxhdGJ1ZmZlcnMuTG9uZ1xuICAgICAqL1xuICAgIGRpbVZhbHVlKCk6IGZsYXRidWZmZXJzLkxvbmcge1xuICAgICAgbGV0IG9mZnNldCA9IHRoaXMuYmIhLl9fb2Zmc2V0KHRoaXMuYmJfcG9zLCA2KTtcbiAgICAgIHJldHVybiBvZmZzZXQgPyB0aGlzLmJiIS5yZWFkSW50NjQodGhpcy5iYl9wb3MgKyBvZmZzZXQpIDogdGhpcy5iYiEuY3JlYXRlTG9uZygwLCAwKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuRW5jb2Rpbmc9IG9wdGlvbmFsRW5jb2RpbmdcbiAgICAgKiBAcmV0dXJucyBzdHJpbmd8VWludDhBcnJheXxudWxsXG4gICAgICovXG4gICAgZGltUGFyYW0oKTogc3RyaW5nfG51bGw7XG4gICAgZGltUGFyYW0ob3B0aW9uYWxFbmNvZGluZzogZmxhdGJ1ZmZlcnMuRW5jb2RpbmcpOiBzdHJpbmd8VWludDhBcnJheXxudWxsO1xuICAgIGRpbVBhcmFtKG9wdGlvbmFsRW5jb2Rpbmc/OiBhbnkpOiBzdHJpbmd8VWludDhBcnJheXxudWxsIHtcbiAgICAgIGxldCBvZmZzZXQgPSB0aGlzLmJiIS5fX29mZnNldCh0aGlzLmJiX3BvcywgOCk7XG4gICAgICByZXR1cm4gb2Zmc2V0ID8gdGhpcy5iYiEuX19zdHJpbmcodGhpcy5iYl9wb3MgKyBvZmZzZXQsIG9wdGlvbmFsRW5jb2RpbmcpIDogbnVsbDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuQnVpbGRlciBidWlsZGVyXG4gICAgICovXG4gICAgc3RhdGljIHN0YXJ0RGltZW5zaW9uVmFsdWUoYnVpbGRlcjogZmxhdGJ1ZmZlcnMuQnVpbGRlcikge1xuICAgICAgYnVpbGRlci5zdGFydE9iamVjdCgzKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuQnVpbGRlciBidWlsZGVyXG4gICAgICogQHBhcmFtIG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnMuRGltZW5zaW9uVmFsdWVUeXBlIGRpbVR5cGVcbiAgICAgKi9cbiAgICBzdGF0aWMgYWRkRGltVHlwZShidWlsZGVyOiBmbGF0YnVmZmVycy5CdWlsZGVyLCBkaW1UeXBlOiBvbm54cnVudGltZS5leHBlcmltZW50YWwuZmJzLkRpbWVuc2lvblZhbHVlVHlwZSkge1xuICAgICAgYnVpbGRlci5hZGRGaWVsZEludDgoMCwgZGltVHlwZSwgb25ueHJ1bnRpbWUuZXhwZXJpbWVudGFsLmZicy5EaW1lbnNpb25WYWx1ZVR5cGUuVU5LTk9XTik7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ1aWxkZXIgYnVpbGRlclxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5Mb25nIGRpbVZhbHVlXG4gICAgICovXG4gICAgc3RhdGljIGFkZERpbVZhbHVlKGJ1aWxkZXI6IGZsYXRidWZmZXJzLkJ1aWxkZXIsIGRpbVZhbHVlOiBmbGF0YnVmZmVycy5Mb25nKSB7XG4gICAgICBidWlsZGVyLmFkZEZpZWxkSW50NjQoMSwgZGltVmFsdWUsIGJ1aWxkZXIuY3JlYXRlTG9uZygwLCAwKSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ1aWxkZXIgYnVpbGRlclxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5PZmZzZXQgZGltUGFyYW1PZmZzZXRcbiAgICAgKi9cbiAgICBzdGF0aWMgYWRkRGltUGFyYW0oYnVpbGRlcjogZmxhdGJ1ZmZlcnMuQnVpbGRlciwgZGltUGFyYW1PZmZzZXQ6IGZsYXRidWZmZXJzLk9mZnNldCkge1xuICAgICAgYnVpbGRlci5hZGRGaWVsZE9mZnNldCgyLCBkaW1QYXJhbU9mZnNldCwgMCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ1aWxkZXIgYnVpbGRlclxuICAgICAqIEByZXR1cm5zIGZsYXRidWZmZXJzLk9mZnNldFxuICAgICAqL1xuICAgIHN0YXRpYyBlbmREaW1lbnNpb25WYWx1ZShidWlsZGVyOiBmbGF0YnVmZmVycy5CdWlsZGVyKTogZmxhdGJ1ZmZlcnMuT2Zmc2V0IHtcbiAgICAgIGxldCBvZmZzZXQgPSBidWlsZGVyLmVuZE9iamVjdCgpO1xuICAgICAgcmV0dXJuIG9mZnNldDtcbiAgICB9XG5cbiAgICBzdGF0aWMgY3JlYXRlRGltZW5zaW9uVmFsdWUoXG4gICAgICAgIGJ1aWxkZXI6IGZsYXRidWZmZXJzLkJ1aWxkZXIsIGRpbVR5cGU6IG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnMuRGltZW5zaW9uVmFsdWVUeXBlLFxuICAgICAgICBkaW1WYWx1ZTogZmxhdGJ1ZmZlcnMuTG9uZywgZGltUGFyYW1PZmZzZXQ6IGZsYXRidWZmZXJzLk9mZnNldCk6IGZsYXRidWZmZXJzLk9mZnNldCB7XG4gICAgICBEaW1lbnNpb25WYWx1ZS5zdGFydERpbWVuc2lvblZhbHVlKGJ1aWxkZXIpO1xuICAgICAgRGltZW5zaW9uVmFsdWUuYWRkRGltVHlwZShidWlsZGVyLCBkaW1UeXBlKTtcbiAgICAgIERpbWVuc2lvblZhbHVlLmFkZERpbVZhbHVlKGJ1aWxkZXIsIGRpbVZhbHVlKTtcbiAgICAgIERpbWVuc2lvblZhbHVlLmFkZERpbVBhcmFtKGJ1aWxkZXIsIGRpbVBhcmFtT2Zmc2V0KTtcbiAgICAgIHJldHVybiBEaW1lbnNpb25WYWx1ZS5lbmREaW1lbnNpb25WYWx1ZShidWlsZGVyKTtcbiAgICB9XG4gIH1cbn1cbi8qKlxuICogQGNvbnN0cnVjdG9yXG4gKi9cbmV4cG9ydCBuYW1lc3BhY2Ugb25ueHJ1bnRpbWUuZXhwZXJpbWVudGFsLmZicyB7XG4gIGV4cG9ydCBjbGFzcyBUZW5zb3JUeXBlQW5kU2hhcGUge1xuICAgIGJiOiBmbGF0YnVmZmVycy5CeXRlQnVmZmVyfG51bGwgPSBudWxsO1xuXG4gICAgYmJfcG9zID0gMDtcbiAgICAvKipcbiAgICAgKiBAcGFyYW0gbnVtYmVyIGlcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuQnl0ZUJ1ZmZlciBiYlxuICAgICAqIEByZXR1cm5zIFRlbnNvclR5cGVBbmRTaGFwZVxuICAgICAqL1xuICAgIF9faW5pdChpOiBudW1iZXIsIGJiOiBmbGF0YnVmZmVycy5CeXRlQnVmZmVyKTogVGVuc29yVHlwZUFuZFNoYXBlIHtcbiAgICAgIHRoaXMuYmJfcG9zID0gaTtcbiAgICAgIHRoaXMuYmIgPSBiYjtcbiAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CeXRlQnVmZmVyIGJiXG4gICAgICogQHBhcmFtIFRlbnNvclR5cGVBbmRTaGFwZT0gb2JqXG4gICAgICogQHJldHVybnMgVGVuc29yVHlwZUFuZFNoYXBlXG4gICAgICovXG4gICAgc3RhdGljIGdldFJvb3RBc1RlbnNvclR5cGVBbmRTaGFwZShiYjogZmxhdGJ1ZmZlcnMuQnl0ZUJ1ZmZlciwgb2JqPzogVGVuc29yVHlwZUFuZFNoYXBlKTogVGVuc29yVHlwZUFuZFNoYXBlIHtcbiAgICAgIHJldHVybiAob2JqIHx8IG5ldyBUZW5zb3JUeXBlQW5kU2hhcGUoKSkuX19pbml0KGJiLnJlYWRJbnQzMihiYi5wb3NpdGlvbigpKSArIGJiLnBvc2l0aW9uKCksIGJiKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuQnl0ZUJ1ZmZlciBiYlxuICAgICAqIEBwYXJhbSBUZW5zb3JUeXBlQW5kU2hhcGU9IG9ialxuICAgICAqIEByZXR1cm5zIFRlbnNvclR5cGVBbmRTaGFwZVxuICAgICAqL1xuICAgIHN0YXRpYyBnZXRTaXplUHJlZml4ZWRSb290QXNUZW5zb3JUeXBlQW5kU2hhcGUoYmI6IGZsYXRidWZmZXJzLkJ5dGVCdWZmZXIsIG9iaj86IFRlbnNvclR5cGVBbmRTaGFwZSk6XG4gICAgICAgIFRlbnNvclR5cGVBbmRTaGFwZSB7XG4gICAgICBiYi5zZXRQb3NpdGlvbihiYi5wb3NpdGlvbigpICsgZmxhdGJ1ZmZlcnMuU0laRV9QUkVGSVhfTEVOR1RIKTtcbiAgICAgIHJldHVybiAob2JqIHx8IG5ldyBUZW5zb3JUeXBlQW5kU2hhcGUoKSkuX19pbml0KGJiLnJlYWRJbnQzMihiYi5wb3NpdGlvbigpKSArIGJiLnBvc2l0aW9uKCksIGJiKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcmV0dXJucyBvbm54cnVudGltZS5leHBlcmltZW50YWwuZmJzLlRlbnNvckRhdGFUeXBlXG4gICAgICovXG4gICAgZWxlbVR5cGUoKTogb25ueHJ1bnRpbWUuZXhwZXJpbWVudGFsLmZicy5UZW5zb3JEYXRhVHlwZSB7XG4gICAgICBsZXQgb2Zmc2V0ID0gdGhpcy5iYiEuX19vZmZzZXQodGhpcy5iYl9wb3MsIDQpO1xuICAgICAgcmV0dXJuIG9mZnNldCA/IC8qKiAgKi8gKHRoaXMuYmIhLnJlYWRJbnQzMih0aGlzLmJiX3BvcyArIG9mZnNldCkpIDpcbiAgICAgICAgICAgICAgICAgICAgICBvbm54cnVudGltZS5leHBlcmltZW50YWwuZmJzLlRlbnNvckRhdGFUeXBlLlVOREVGSU5FRDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gb25ueHJ1bnRpbWUuZXhwZXJpbWVudGFsLmZicy5TaGFwZT0gb2JqXG4gICAgICogQHJldHVybnMgb25ueHJ1bnRpbWUuZXhwZXJpbWVudGFsLmZicy5TaGFwZXxudWxsXG4gICAgICovXG4gICAgc2hhcGUob2JqPzogb25ueHJ1bnRpbWUuZXhwZXJpbWVudGFsLmZicy5TaGFwZSk6IG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnMuU2hhcGV8bnVsbCB7XG4gICAgICBsZXQgb2Zmc2V0ID0gdGhpcy5iYiEuX19vZmZzZXQodGhpcy5iYl9wb3MsIDYpO1xuICAgICAgcmV0dXJuIG9mZnNldCA/IChvYmogfHwgbmV3IG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnMuU2hhcGUoKSlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgLl9faW5pdCh0aGlzLmJiIS5fX2luZGlyZWN0KHRoaXMuYmJfcG9zICsgb2Zmc2V0KSwgdGhpcy5iYiEpIDpcbiAgICAgICAgICAgICAgICAgICAgICBudWxsO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CdWlsZGVyIGJ1aWxkZXJcbiAgICAgKi9cbiAgICBzdGF0aWMgc3RhcnRUZW5zb3JUeXBlQW5kU2hhcGUoYnVpbGRlcjogZmxhdGJ1ZmZlcnMuQnVpbGRlcikge1xuICAgICAgYnVpbGRlci5zdGFydE9iamVjdCgyKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuQnVpbGRlciBidWlsZGVyXG4gICAgICogQHBhcmFtIG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnMuVGVuc29yRGF0YVR5cGUgZWxlbVR5cGVcbiAgICAgKi9cbiAgICBzdGF0aWMgYWRkRWxlbVR5cGUoYnVpbGRlcjogZmxhdGJ1ZmZlcnMuQnVpbGRlciwgZWxlbVR5cGU6IG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnMuVGVuc29yRGF0YVR5cGUpIHtcbiAgICAgIGJ1aWxkZXIuYWRkRmllbGRJbnQzMigwLCBlbGVtVHlwZSwgb25ueHJ1bnRpbWUuZXhwZXJpbWVudGFsLmZicy5UZW5zb3JEYXRhVHlwZS5VTkRFRklORUQpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CdWlsZGVyIGJ1aWxkZXJcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuT2Zmc2V0IHNoYXBlT2Zmc2V0XG4gICAgICovXG4gICAgc3RhdGljIGFkZFNoYXBlKGJ1aWxkZXI6IGZsYXRidWZmZXJzLkJ1aWxkZXIsIHNoYXBlT2Zmc2V0OiBmbGF0YnVmZmVycy5PZmZzZXQpIHtcbiAgICAgIGJ1aWxkZXIuYWRkRmllbGRPZmZzZXQoMSwgc2hhcGVPZmZzZXQsIDApO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CdWlsZGVyIGJ1aWxkZXJcbiAgICAgKiBAcmV0dXJucyBmbGF0YnVmZmVycy5PZmZzZXRcbiAgICAgKi9cbiAgICBzdGF0aWMgZW5kVGVuc29yVHlwZUFuZFNoYXBlKGJ1aWxkZXI6IGZsYXRidWZmZXJzLkJ1aWxkZXIpOiBmbGF0YnVmZmVycy5PZmZzZXQge1xuICAgICAgbGV0IG9mZnNldCA9IGJ1aWxkZXIuZW5kT2JqZWN0KCk7XG4gICAgICByZXR1cm4gb2Zmc2V0O1xuICAgIH1cblxuICAgIHN0YXRpYyBjcmVhdGVUZW5zb3JUeXBlQW5kU2hhcGUoXG4gICAgICAgIGJ1aWxkZXI6IGZsYXRidWZmZXJzLkJ1aWxkZXIsIGVsZW1UeXBlOiBvbm54cnVudGltZS5leHBlcmltZW50YWwuZmJzLlRlbnNvckRhdGFUeXBlLFxuICAgICAgICBzaGFwZU9mZnNldDogZmxhdGJ1ZmZlcnMuT2Zmc2V0KTogZmxhdGJ1ZmZlcnMuT2Zmc2V0IHtcbiAgICAgIFRlbnNvclR5cGVBbmRTaGFwZS5zdGFydFRlbnNvclR5cGVBbmRTaGFwZShidWlsZGVyKTtcbiAgICAgIFRlbnNvclR5cGVBbmRTaGFwZS5hZGRFbGVtVHlwZShidWlsZGVyLCBlbGVtVHlwZSk7XG4gICAgICBUZW5zb3JUeXBlQW5kU2hhcGUuYWRkU2hhcGUoYnVpbGRlciwgc2hhcGVPZmZzZXQpO1xuICAgICAgcmV0dXJuIFRlbnNvclR5cGVBbmRTaGFwZS5lbmRUZW5zb3JUeXBlQW5kU2hhcGUoYnVpbGRlcik7XG4gICAgfVxuICB9XG59XG4vKipcbiAqIEBjb25zdHJ1Y3RvclxuICovXG5leHBvcnQgbmFtZXNwYWNlIG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnMge1xuICBleHBvcnQgY2xhc3MgTWFwVHlwZSB7XG4gICAgYmI6IGZsYXRidWZmZXJzLkJ5dGVCdWZmZXJ8bnVsbCA9IG51bGw7XG5cbiAgICBiYl9wb3MgPSAwO1xuICAgIC8qKlxuICAgICAqIEBwYXJhbSBudW1iZXIgaVxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CeXRlQnVmZmVyIGJiXG4gICAgICogQHJldHVybnMgTWFwVHlwZVxuICAgICAqL1xuICAgIF9faW5pdChpOiBudW1iZXIsIGJiOiBmbGF0YnVmZmVycy5CeXRlQnVmZmVyKTogTWFwVHlwZSB7XG4gICAgICB0aGlzLmJiX3BvcyA9IGk7XG4gICAgICB0aGlzLmJiID0gYmI7XG4gICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuQnl0ZUJ1ZmZlciBiYlxuICAgICAqIEBwYXJhbSBNYXBUeXBlPSBvYmpcbiAgICAgKiBAcmV0dXJucyBNYXBUeXBlXG4gICAgICovXG4gICAgc3RhdGljIGdldFJvb3RBc01hcFR5cGUoYmI6IGZsYXRidWZmZXJzLkJ5dGVCdWZmZXIsIG9iaj86IE1hcFR5cGUpOiBNYXBUeXBlIHtcbiAgICAgIHJldHVybiAob2JqIHx8IG5ldyBNYXBUeXBlKCkpLl9faW5pdChiYi5yZWFkSW50MzIoYmIucG9zaXRpb24oKSkgKyBiYi5wb3NpdGlvbigpLCBiYik7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ5dGVCdWZmZXIgYmJcbiAgICAgKiBAcGFyYW0gTWFwVHlwZT0gb2JqXG4gICAgICogQHJldHVybnMgTWFwVHlwZVxuICAgICAqL1xuICAgIHN0YXRpYyBnZXRTaXplUHJlZml4ZWRSb290QXNNYXBUeXBlKGJiOiBmbGF0YnVmZmVycy5CeXRlQnVmZmVyLCBvYmo/OiBNYXBUeXBlKTogTWFwVHlwZSB7XG4gICAgICBiYi5zZXRQb3NpdGlvbihiYi5wb3NpdGlvbigpICsgZmxhdGJ1ZmZlcnMuU0laRV9QUkVGSVhfTEVOR1RIKTtcbiAgICAgIHJldHVybiAob2JqIHx8IG5ldyBNYXBUeXBlKCkpLl9faW5pdChiYi5yZWFkSW50MzIoYmIucG9zaXRpb24oKSkgKyBiYi5wb3NpdGlvbigpLCBiYik7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHJldHVybnMgb25ueHJ1bnRpbWUuZXhwZXJpbWVudGFsLmZicy5UZW5zb3JEYXRhVHlwZVxuICAgICAqL1xuICAgIGtleVR5cGUoKTogb25ueHJ1bnRpbWUuZXhwZXJpbWVudGFsLmZicy5UZW5zb3JEYXRhVHlwZSB7XG4gICAgICBsZXQgb2Zmc2V0ID0gdGhpcy5iYiEuX19vZmZzZXQodGhpcy5iYl9wb3MsIDQpO1xuICAgICAgcmV0dXJuIG9mZnNldCA/IC8qKiAgKi8gKHRoaXMuYmIhLnJlYWRJbnQzMih0aGlzLmJiX3BvcyArIG9mZnNldCkpIDpcbiAgICAgICAgICAgICAgICAgICAgICBvbm54cnVudGltZS5leHBlcmltZW50YWwuZmJzLlRlbnNvckRhdGFUeXBlLlVOREVGSU5FRDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gb25ueHJ1bnRpbWUuZXhwZXJpbWVudGFsLmZicy5UeXBlSW5mbz0gb2JqXG4gICAgICogQHJldHVybnMgb25ueHJ1bnRpbWUuZXhwZXJpbWVudGFsLmZicy5UeXBlSW5mb3xudWxsXG4gICAgICovXG4gICAgdmFsdWVUeXBlKG9iaj86IG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnMuVHlwZUluZm8pOiBvbm54cnVudGltZS5leHBlcmltZW50YWwuZmJzLlR5cGVJbmZvfG51bGwge1xuICAgICAgbGV0IG9mZnNldCA9IHRoaXMuYmIhLl9fb2Zmc2V0KHRoaXMuYmJfcG9zLCA2KTtcbiAgICAgIHJldHVybiBvZmZzZXQgPyAob2JqIHx8IG5ldyBvbm54cnVudGltZS5leHBlcmltZW50YWwuZmJzLlR5cGVJbmZvKCkpXG4gICAgICAgICAgICAgICAgICAgICAgICAgIC5fX2luaXQodGhpcy5iYiEuX19pbmRpcmVjdCh0aGlzLmJiX3BvcyArIG9mZnNldCksIHRoaXMuYmIhKSA6XG4gICAgICAgICAgICAgICAgICAgICAgbnVsbDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuQnVpbGRlciBidWlsZGVyXG4gICAgICovXG4gICAgc3RhdGljIHN0YXJ0TWFwVHlwZShidWlsZGVyOiBmbGF0YnVmZmVycy5CdWlsZGVyKSB7XG4gICAgICBidWlsZGVyLnN0YXJ0T2JqZWN0KDIpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CdWlsZGVyIGJ1aWxkZXJcbiAgICAgKiBAcGFyYW0gb25ueHJ1bnRpbWUuZXhwZXJpbWVudGFsLmZicy5UZW5zb3JEYXRhVHlwZSBrZXlUeXBlXG4gICAgICovXG4gICAgc3RhdGljIGFkZEtleVR5cGUoYnVpbGRlcjogZmxhdGJ1ZmZlcnMuQnVpbGRlciwga2V5VHlwZTogb25ueHJ1bnRpbWUuZXhwZXJpbWVudGFsLmZicy5UZW5zb3JEYXRhVHlwZSkge1xuICAgICAgYnVpbGRlci5hZGRGaWVsZEludDMyKDAsIGtleVR5cGUsIG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnMuVGVuc29yRGF0YVR5cGUuVU5ERUZJTkVEKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuQnVpbGRlciBidWlsZGVyXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLk9mZnNldCB2YWx1ZVR5cGVPZmZzZXRcbiAgICAgKi9cbiAgICBzdGF0aWMgYWRkVmFsdWVUeXBlKGJ1aWxkZXI6IGZsYXRidWZmZXJzLkJ1aWxkZXIsIHZhbHVlVHlwZU9mZnNldDogZmxhdGJ1ZmZlcnMuT2Zmc2V0KSB7XG4gICAgICBidWlsZGVyLmFkZEZpZWxkT2Zmc2V0KDEsIHZhbHVlVHlwZU9mZnNldCwgMCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ1aWxkZXIgYnVpbGRlclxuICAgICAqIEByZXR1cm5zIGZsYXRidWZmZXJzLk9mZnNldFxuICAgICAqL1xuICAgIHN0YXRpYyBlbmRNYXBUeXBlKGJ1aWxkZXI6IGZsYXRidWZmZXJzLkJ1aWxkZXIpOiBmbGF0YnVmZmVycy5PZmZzZXQge1xuICAgICAgbGV0IG9mZnNldCA9IGJ1aWxkZXIuZW5kT2JqZWN0KCk7XG4gICAgICByZXR1cm4gb2Zmc2V0O1xuICAgIH1cblxuICAgIHN0YXRpYyBjcmVhdGVNYXBUeXBlKFxuICAgICAgICBidWlsZGVyOiBmbGF0YnVmZmVycy5CdWlsZGVyLCBrZXlUeXBlOiBvbm54cnVudGltZS5leHBlcmltZW50YWwuZmJzLlRlbnNvckRhdGFUeXBlLFxuICAgICAgICB2YWx1ZVR5cGVPZmZzZXQ6IGZsYXRidWZmZXJzLk9mZnNldCk6IGZsYXRidWZmZXJzLk9mZnNldCB7XG4gICAgICBNYXBUeXBlLnN0YXJ0TWFwVHlwZShidWlsZGVyKTtcbiAgICAgIE1hcFR5cGUuYWRkS2V5VHlwZShidWlsZGVyLCBrZXlUeXBlKTtcbiAgICAgIE1hcFR5cGUuYWRkVmFsdWVUeXBlKGJ1aWxkZXIsIHZhbHVlVHlwZU9mZnNldCk7XG4gICAgICByZXR1cm4gTWFwVHlwZS5lbmRNYXBUeXBlKGJ1aWxkZXIpO1xuICAgIH1cbiAgfVxufVxuLyoqXG4gKiBAY29uc3RydWN0b3JcbiAqL1xuZXhwb3J0IG5hbWVzcGFjZSBvbm54cnVudGltZS5leHBlcmltZW50YWwuZmJzIHtcbiAgZXhwb3J0IGNsYXNzIFNlcXVlbmNlVHlwZSB7XG4gICAgYmI6IGZsYXRidWZmZXJzLkJ5dGVCdWZmZXJ8bnVsbCA9IG51bGw7XG5cbiAgICBiYl9wb3MgPSAwO1xuICAgIC8qKlxuICAgICAqIEBwYXJhbSBudW1iZXIgaVxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CeXRlQnVmZmVyIGJiXG4gICAgICogQHJldHVybnMgU2VxdWVuY2VUeXBlXG4gICAgICovXG4gICAgX19pbml0KGk6IG51bWJlciwgYmI6IGZsYXRidWZmZXJzLkJ5dGVCdWZmZXIpOiBTZXF1ZW5jZVR5cGUge1xuICAgICAgdGhpcy5iYl9wb3MgPSBpO1xuICAgICAgdGhpcy5iYiA9IGJiO1xuICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ5dGVCdWZmZXIgYmJcbiAgICAgKiBAcGFyYW0gU2VxdWVuY2VUeXBlPSBvYmpcbiAgICAgKiBAcmV0dXJucyBTZXF1ZW5jZVR5cGVcbiAgICAgKi9cbiAgICBzdGF0aWMgZ2V0Um9vdEFzU2VxdWVuY2VUeXBlKGJiOiBmbGF0YnVmZmVycy5CeXRlQnVmZmVyLCBvYmo/OiBTZXF1ZW5jZVR5cGUpOiBTZXF1ZW5jZVR5cGUge1xuICAgICAgcmV0dXJuIChvYmogfHwgbmV3IFNlcXVlbmNlVHlwZSgpKS5fX2luaXQoYmIucmVhZEludDMyKGJiLnBvc2l0aW9uKCkpICsgYmIucG9zaXRpb24oKSwgYmIpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CeXRlQnVmZmVyIGJiXG4gICAgICogQHBhcmFtIFNlcXVlbmNlVHlwZT0gb2JqXG4gICAgICogQHJldHVybnMgU2VxdWVuY2VUeXBlXG4gICAgICovXG4gICAgc3RhdGljIGdldFNpemVQcmVmaXhlZFJvb3RBc1NlcXVlbmNlVHlwZShiYjogZmxhdGJ1ZmZlcnMuQnl0ZUJ1ZmZlciwgb2JqPzogU2VxdWVuY2VUeXBlKTogU2VxdWVuY2VUeXBlIHtcbiAgICAgIGJiLnNldFBvc2l0aW9uKGJiLnBvc2l0aW9uKCkgKyBmbGF0YnVmZmVycy5TSVpFX1BSRUZJWF9MRU5HVEgpO1xuICAgICAgcmV0dXJuIChvYmogfHwgbmV3IFNlcXVlbmNlVHlwZSgpKS5fX2luaXQoYmIucmVhZEludDMyKGJiLnBvc2l0aW9uKCkpICsgYmIucG9zaXRpb24oKSwgYmIpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBvbm54cnVudGltZS5leHBlcmltZW50YWwuZmJzLlR5cGVJbmZvPSBvYmpcbiAgICAgKiBAcmV0dXJucyBvbm54cnVudGltZS5leHBlcmltZW50YWwuZmJzLlR5cGVJbmZvfG51bGxcbiAgICAgKi9cbiAgICBlbGVtVHlwZShvYmo/OiBvbm54cnVudGltZS5leHBlcmltZW50YWwuZmJzLlR5cGVJbmZvKTogb25ueHJ1bnRpbWUuZXhwZXJpbWVudGFsLmZicy5UeXBlSW5mb3xudWxsIHtcbiAgICAgIGxldCBvZmZzZXQgPSB0aGlzLmJiIS5fX29mZnNldCh0aGlzLmJiX3BvcywgNCk7XG4gICAgICByZXR1cm4gb2Zmc2V0ID8gKG9iaiB8fCBuZXcgb25ueHJ1bnRpbWUuZXhwZXJpbWVudGFsLmZicy5UeXBlSW5mbygpKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAuX19pbml0KHRoaXMuYmIhLl9faW5kaXJlY3QodGhpcy5iYl9wb3MgKyBvZmZzZXQpLCB0aGlzLmJiISkgOlxuICAgICAgICAgICAgICAgICAgICAgIG51bGw7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ1aWxkZXIgYnVpbGRlclxuICAgICAqL1xuICAgIHN0YXRpYyBzdGFydFNlcXVlbmNlVHlwZShidWlsZGVyOiBmbGF0YnVmZmVycy5CdWlsZGVyKSB7XG4gICAgICBidWlsZGVyLnN0YXJ0T2JqZWN0KDEpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CdWlsZGVyIGJ1aWxkZXJcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuT2Zmc2V0IGVsZW1UeXBlT2Zmc2V0XG4gICAgICovXG4gICAgc3RhdGljIGFkZEVsZW1UeXBlKGJ1aWxkZXI6IGZsYXRidWZmZXJzLkJ1aWxkZXIsIGVsZW1UeXBlT2Zmc2V0OiBmbGF0YnVmZmVycy5PZmZzZXQpIHtcbiAgICAgIGJ1aWxkZXIuYWRkRmllbGRPZmZzZXQoMCwgZWxlbVR5cGVPZmZzZXQsIDApO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CdWlsZGVyIGJ1aWxkZXJcbiAgICAgKiBAcmV0dXJucyBmbGF0YnVmZmVycy5PZmZzZXRcbiAgICAgKi9cbiAgICBzdGF0aWMgZW5kU2VxdWVuY2VUeXBlKGJ1aWxkZXI6IGZsYXRidWZmZXJzLkJ1aWxkZXIpOiBmbGF0YnVmZmVycy5PZmZzZXQge1xuICAgICAgbGV0IG9mZnNldCA9IGJ1aWxkZXIuZW5kT2JqZWN0KCk7XG4gICAgICByZXR1cm4gb2Zmc2V0O1xuICAgIH1cblxuICAgIHN0YXRpYyBjcmVhdGVTZXF1ZW5jZVR5cGUoYnVpbGRlcjogZmxhdGJ1ZmZlcnMuQnVpbGRlciwgZWxlbVR5cGVPZmZzZXQ6IGZsYXRidWZmZXJzLk9mZnNldCk6IGZsYXRidWZmZXJzLk9mZnNldCB7XG4gICAgICBTZXF1ZW5jZVR5cGUuc3RhcnRTZXF1ZW5jZVR5cGUoYnVpbGRlcik7XG4gICAgICBTZXF1ZW5jZVR5cGUuYWRkRWxlbVR5cGUoYnVpbGRlciwgZWxlbVR5cGVPZmZzZXQpO1xuICAgICAgcmV0dXJuIFNlcXVlbmNlVHlwZS5lbmRTZXF1ZW5jZVR5cGUoYnVpbGRlcik7XG4gICAgfVxuICB9XG59XG4vKipcbiAqIEBjb25zdHJ1Y3RvclxuICovXG5leHBvcnQgbmFtZXNwYWNlIG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnMge1xuICBleHBvcnQgY2xhc3MgRWRnZUVuZCB7XG4gICAgYmI6IGZsYXRidWZmZXJzLkJ5dGVCdWZmZXJ8bnVsbCA9IG51bGw7XG5cbiAgICBiYl9wb3MgPSAwO1xuICAgIC8qKlxuICAgICAqIEBwYXJhbSBudW1iZXIgaVxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CeXRlQnVmZmVyIGJiXG4gICAgICogQHJldHVybnMgRWRnZUVuZFxuICAgICAqL1xuICAgIF9faW5pdChpOiBudW1iZXIsIGJiOiBmbGF0YnVmZmVycy5CeXRlQnVmZmVyKTogRWRnZUVuZCB7XG4gICAgICB0aGlzLmJiX3BvcyA9IGk7XG4gICAgICB0aGlzLmJiID0gYmI7XG4gICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcmV0dXJucyBudW1iZXJcbiAgICAgKi9cbiAgICBub2RlSW5kZXgoKTogbnVtYmVyIHtcbiAgICAgIHJldHVybiB0aGlzLmJiIS5yZWFkVWludDMyKHRoaXMuYmJfcG9zKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcmV0dXJucyBudW1iZXJcbiAgICAgKi9cbiAgICBzcmNBcmdJbmRleCgpOiBudW1iZXIge1xuICAgICAgcmV0dXJuIHRoaXMuYmIhLnJlYWRJbnQzMih0aGlzLmJiX3BvcyArIDQpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEByZXR1cm5zIG51bWJlclxuICAgICAqL1xuICAgIGRzdEFyZ0luZGV4KCk6IG51bWJlciB7XG4gICAgICByZXR1cm4gdGhpcy5iYiEucmVhZEludDMyKHRoaXMuYmJfcG9zICsgOCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ1aWxkZXIgYnVpbGRlclxuICAgICAqIEBwYXJhbSBudW1iZXIgbm9kZV9pbmRleFxuICAgICAqIEBwYXJhbSBudW1iZXIgc3JjX2FyZ19pbmRleFxuICAgICAqIEBwYXJhbSBudW1iZXIgZHN0X2FyZ19pbmRleFxuICAgICAqIEByZXR1cm5zIGZsYXRidWZmZXJzLk9mZnNldFxuICAgICAqL1xuICAgIHN0YXRpYyBjcmVhdGVFZGdlRW5kKFxuICAgICAgICBidWlsZGVyOiBmbGF0YnVmZmVycy5CdWlsZGVyLCBub2RlX2luZGV4OiBudW1iZXIsIHNyY19hcmdfaW5kZXg6IG51bWJlcixcbiAgICAgICAgZHN0X2FyZ19pbmRleDogbnVtYmVyKTogZmxhdGJ1ZmZlcnMuT2Zmc2V0IHtcbiAgICAgIGJ1aWxkZXIucHJlcCg0LCAxMik7XG4gICAgICBidWlsZGVyLndyaXRlSW50MzIoZHN0X2FyZ19pbmRleCk7XG4gICAgICBidWlsZGVyLndyaXRlSW50MzIoc3JjX2FyZ19pbmRleCk7XG4gICAgICBidWlsZGVyLndyaXRlSW50MzIobm9kZV9pbmRleCk7XG4gICAgICByZXR1cm4gYnVpbGRlci5vZmZzZXQoKTtcbiAgICB9XG4gIH1cbn1cbi8qKlxuICogQGNvbnN0cnVjdG9yXG4gKi9cbmV4cG9ydCBuYW1lc3BhY2Ugb25ueHJ1bnRpbWUuZXhwZXJpbWVudGFsLmZicyB7XG4gIGV4cG9ydCBjbGFzcyBOb2RlRWRnZSB7XG4gICAgYmI6IGZsYXRidWZmZXJzLkJ5dGVCdWZmZXJ8bnVsbCA9IG51bGw7XG5cbiAgICBiYl9wb3MgPSAwO1xuICAgIC8qKlxuICAgICAqIEBwYXJhbSBudW1iZXIgaVxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CeXRlQnVmZmVyIGJiXG4gICAgICogQHJldHVybnMgTm9kZUVkZ2VcbiAgICAgKi9cbiAgICBfX2luaXQoaTogbnVtYmVyLCBiYjogZmxhdGJ1ZmZlcnMuQnl0ZUJ1ZmZlcik6IE5vZGVFZGdlIHtcbiAgICAgIHRoaXMuYmJfcG9zID0gaTtcbiAgICAgIHRoaXMuYmIgPSBiYjtcbiAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CeXRlQnVmZmVyIGJiXG4gICAgICogQHBhcmFtIE5vZGVFZGdlPSBvYmpcbiAgICAgKiBAcmV0dXJucyBOb2RlRWRnZVxuICAgICAqL1xuICAgIHN0YXRpYyBnZXRSb290QXNOb2RlRWRnZShiYjogZmxhdGJ1ZmZlcnMuQnl0ZUJ1ZmZlciwgb2JqPzogTm9kZUVkZ2UpOiBOb2RlRWRnZSB7XG4gICAgICByZXR1cm4gKG9iaiB8fCBuZXcgTm9kZUVkZ2UoKSkuX19pbml0KGJiLnJlYWRJbnQzMihiYi5wb3NpdGlvbigpKSArIGJiLnBvc2l0aW9uKCksIGJiKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuQnl0ZUJ1ZmZlciBiYlxuICAgICAqIEBwYXJhbSBOb2RlRWRnZT0gb2JqXG4gICAgICogQHJldHVybnMgTm9kZUVkZ2VcbiAgICAgKi9cbiAgICBzdGF0aWMgZ2V0U2l6ZVByZWZpeGVkUm9vdEFzTm9kZUVkZ2UoYmI6IGZsYXRidWZmZXJzLkJ5dGVCdWZmZXIsIG9iaj86IE5vZGVFZGdlKTogTm9kZUVkZ2Uge1xuICAgICAgYmIuc2V0UG9zaXRpb24oYmIucG9zaXRpb24oKSArIGZsYXRidWZmZXJzLlNJWkVfUFJFRklYX0xFTkdUSCk7XG4gICAgICByZXR1cm4gKG9iaiB8fCBuZXcgTm9kZUVkZ2UoKSkuX19pbml0KGJiLnJlYWRJbnQzMihiYi5wb3NpdGlvbigpKSArIGJiLnBvc2l0aW9uKCksIGJiKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcmV0dXJucyBudW1iZXJcbiAgICAgKi9cbiAgICBub2RlSW5kZXgoKTogbnVtYmVyIHtcbiAgICAgIGxldCBvZmZzZXQgPSB0aGlzLmJiIS5fX29mZnNldCh0aGlzLmJiX3BvcywgNCk7XG4gICAgICByZXR1cm4gb2Zmc2V0ID8gdGhpcy5iYiEucmVhZFVpbnQzMih0aGlzLmJiX3BvcyArIG9mZnNldCkgOiAwO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBudW1iZXIgaW5kZXhcbiAgICAgKiBAcGFyYW0gb25ueHJ1bnRpbWUuZXhwZXJpbWVudGFsLmZicy5FZGdlRW5kPSBvYmpcbiAgICAgKiBAcmV0dXJucyBvbm54cnVudGltZS5leHBlcmltZW50YWwuZmJzLkVkZ2VFbmRcbiAgICAgKi9cbiAgICBpbnB1dEVkZ2VzKGluZGV4OiBudW1iZXIsIG9iaj86IG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnMuRWRnZUVuZCk6IG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnMuRWRnZUVuZHxudWxsIHtcbiAgICAgIGxldCBvZmZzZXQgPSB0aGlzLmJiIS5fX29mZnNldCh0aGlzLmJiX3BvcywgNik7XG4gICAgICByZXR1cm4gb2Zmc2V0ID8gKG9iaiB8fCBuZXcgb25ueHJ1bnRpbWUuZXhwZXJpbWVudGFsLmZicy5FZGdlRW5kKCkpXG4gICAgICAgICAgICAgICAgICAgICAgICAgIC5fX2luaXQodGhpcy5iYiEuX192ZWN0b3IodGhpcy5iYl9wb3MgKyBvZmZzZXQpICsgaW5kZXggKiAxMiwgdGhpcy5iYiEpIDpcbiAgICAgICAgICAgICAgICAgICAgICBudWxsO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEByZXR1cm5zIG51bWJlclxuICAgICAqL1xuICAgIGlucHV0RWRnZXNMZW5ndGgoKTogbnVtYmVyIHtcbiAgICAgIGxldCBvZmZzZXQgPSB0aGlzLmJiIS5fX29mZnNldCh0aGlzLmJiX3BvcywgNik7XG4gICAgICByZXR1cm4gb2Zmc2V0ID8gdGhpcy5iYiEuX192ZWN0b3JfbGVuKHRoaXMuYmJfcG9zICsgb2Zmc2V0KSA6IDA7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIG51bWJlciBpbmRleFxuICAgICAqIEBwYXJhbSBvbm54cnVudGltZS5leHBlcmltZW50YWwuZmJzLkVkZ2VFbmQ9IG9ialxuICAgICAqIEByZXR1cm5zIG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnMuRWRnZUVuZFxuICAgICAqL1xuICAgIG91dHB1dEVkZ2VzKGluZGV4OiBudW1iZXIsIG9iaj86IG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnMuRWRnZUVuZCk6IG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnMuRWRnZUVuZHxudWxsIHtcbiAgICAgIGxldCBvZmZzZXQgPSB0aGlzLmJiIS5fX29mZnNldCh0aGlzLmJiX3BvcywgOCk7XG4gICAgICByZXR1cm4gb2Zmc2V0ID8gKG9iaiB8fCBuZXcgb25ueHJ1bnRpbWUuZXhwZXJpbWVudGFsLmZicy5FZGdlRW5kKCkpXG4gICAgICAgICAgICAgICAgICAgICAgICAgIC5fX2luaXQodGhpcy5iYiEuX192ZWN0b3IodGhpcy5iYl9wb3MgKyBvZmZzZXQpICsgaW5kZXggKiAxMiwgdGhpcy5iYiEpIDpcbiAgICAgICAgICAgICAgICAgICAgICBudWxsO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEByZXR1cm5zIG51bWJlclxuICAgICAqL1xuICAgIG91dHB1dEVkZ2VzTGVuZ3RoKCk6IG51bWJlciB7XG4gICAgICBsZXQgb2Zmc2V0ID0gdGhpcy5iYiEuX19vZmZzZXQodGhpcy5iYl9wb3MsIDgpO1xuICAgICAgcmV0dXJuIG9mZnNldCA/IHRoaXMuYmIhLl9fdmVjdG9yX2xlbih0aGlzLmJiX3BvcyArIG9mZnNldCkgOiAwO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CdWlsZGVyIGJ1aWxkZXJcbiAgICAgKi9cbiAgICBzdGF0aWMgc3RhcnROb2RlRWRnZShidWlsZGVyOiBmbGF0YnVmZmVycy5CdWlsZGVyKSB7XG4gICAgICBidWlsZGVyLnN0YXJ0T2JqZWN0KDMpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CdWlsZGVyIGJ1aWxkZXJcbiAgICAgKiBAcGFyYW0gbnVtYmVyIG5vZGVJbmRleFxuICAgICAqL1xuICAgIHN0YXRpYyBhZGROb2RlSW5kZXgoYnVpbGRlcjogZmxhdGJ1ZmZlcnMuQnVpbGRlciwgbm9kZUluZGV4OiBudW1iZXIpIHtcbiAgICAgIGJ1aWxkZXIuYWRkRmllbGRJbnQzMigwLCBub2RlSW5kZXgsIDApO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CdWlsZGVyIGJ1aWxkZXJcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuT2Zmc2V0IGlucHV0RWRnZXNPZmZzZXRcbiAgICAgKi9cbiAgICBzdGF0aWMgYWRkSW5wdXRFZGdlcyhidWlsZGVyOiBmbGF0YnVmZmVycy5CdWlsZGVyLCBpbnB1dEVkZ2VzT2Zmc2V0OiBmbGF0YnVmZmVycy5PZmZzZXQpIHtcbiAgICAgIGJ1aWxkZXIuYWRkRmllbGRPZmZzZXQoMSwgaW5wdXRFZGdlc09mZnNldCwgMCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ1aWxkZXIgYnVpbGRlclxuICAgICAqIEBwYXJhbSBudW1iZXIgbnVtRWxlbXNcbiAgICAgKi9cbiAgICBzdGF0aWMgc3RhcnRJbnB1dEVkZ2VzVmVjdG9yKGJ1aWxkZXI6IGZsYXRidWZmZXJzLkJ1aWxkZXIsIG51bUVsZW1zOiBudW1iZXIpIHtcbiAgICAgIGJ1aWxkZXIuc3RhcnRWZWN0b3IoMTIsIG51bUVsZW1zLCA0KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuQnVpbGRlciBidWlsZGVyXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLk9mZnNldCBvdXRwdXRFZGdlc09mZnNldFxuICAgICAqL1xuICAgIHN0YXRpYyBhZGRPdXRwdXRFZGdlcyhidWlsZGVyOiBmbGF0YnVmZmVycy5CdWlsZGVyLCBvdXRwdXRFZGdlc09mZnNldDogZmxhdGJ1ZmZlcnMuT2Zmc2V0KSB7XG4gICAgICBidWlsZGVyLmFkZEZpZWxkT2Zmc2V0KDIsIG91dHB1dEVkZ2VzT2Zmc2V0LCAwKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuQnVpbGRlciBidWlsZGVyXG4gICAgICogQHBhcmFtIG51bWJlciBudW1FbGVtc1xuICAgICAqL1xuICAgIHN0YXRpYyBzdGFydE91dHB1dEVkZ2VzVmVjdG9yKGJ1aWxkZXI6IGZsYXRidWZmZXJzLkJ1aWxkZXIsIG51bUVsZW1zOiBudW1iZXIpIHtcbiAgICAgIGJ1aWxkZXIuc3RhcnRWZWN0b3IoMTIsIG51bUVsZW1zLCA0KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuQnVpbGRlciBidWlsZGVyXG4gICAgICogQHJldHVybnMgZmxhdGJ1ZmZlcnMuT2Zmc2V0XG4gICAgICovXG4gICAgc3RhdGljIGVuZE5vZGVFZGdlKGJ1aWxkZXI6IGZsYXRidWZmZXJzLkJ1aWxkZXIpOiBmbGF0YnVmZmVycy5PZmZzZXQge1xuICAgICAgbGV0IG9mZnNldCA9IGJ1aWxkZXIuZW5kT2JqZWN0KCk7XG4gICAgICByZXR1cm4gb2Zmc2V0O1xuICAgIH1cblxuICAgIHN0YXRpYyBjcmVhdGVOb2RlRWRnZShcbiAgICAgICAgYnVpbGRlcjogZmxhdGJ1ZmZlcnMuQnVpbGRlciwgbm9kZUluZGV4OiBudW1iZXIsIGlucHV0RWRnZXNPZmZzZXQ6IGZsYXRidWZmZXJzLk9mZnNldCxcbiAgICAgICAgb3V0cHV0RWRnZXNPZmZzZXQ6IGZsYXRidWZmZXJzLk9mZnNldCk6IGZsYXRidWZmZXJzLk9mZnNldCB7XG4gICAgICBOb2RlRWRnZS5zdGFydE5vZGVFZGdlKGJ1aWxkZXIpO1xuICAgICAgTm9kZUVkZ2UuYWRkTm9kZUluZGV4KGJ1aWxkZXIsIG5vZGVJbmRleCk7XG4gICAgICBOb2RlRWRnZS5hZGRJbnB1dEVkZ2VzKGJ1aWxkZXIsIGlucHV0RWRnZXNPZmZzZXQpO1xuICAgICAgTm9kZUVkZ2UuYWRkT3V0cHV0RWRnZXMoYnVpbGRlciwgb3V0cHV0RWRnZXNPZmZzZXQpO1xuICAgICAgcmV0dXJuIE5vZGVFZGdlLmVuZE5vZGVFZGdlKGJ1aWxkZXIpO1xuICAgIH1cbiAgfVxufVxuLyoqXG4gKiBAY29uc3RydWN0b3JcbiAqL1xuZXhwb3J0IG5hbWVzcGFjZSBvbm54cnVudGltZS5leHBlcmltZW50YWwuZmJzIHtcbiAgZXhwb3J0IGNsYXNzIE5vZGUge1xuICAgIGJiOiBmbGF0YnVmZmVycy5CeXRlQnVmZmVyfG51bGwgPSBudWxsO1xuXG4gICAgYmJfcG9zID0gMDtcbiAgICAvKipcbiAgICAgKiBAcGFyYW0gbnVtYmVyIGlcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuQnl0ZUJ1ZmZlciBiYlxuICAgICAqIEByZXR1cm5zIE5vZGVcbiAgICAgKi9cbiAgICBfX2luaXQoaTogbnVtYmVyLCBiYjogZmxhdGJ1ZmZlcnMuQnl0ZUJ1ZmZlcik6IE5vZGUge1xuICAgICAgdGhpcy5iYl9wb3MgPSBpO1xuICAgICAgdGhpcy5iYiA9IGJiO1xuICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ5dGVCdWZmZXIgYmJcbiAgICAgKiBAcGFyYW0gTm9kZT0gb2JqXG4gICAgICogQHJldHVybnMgTm9kZVxuICAgICAqL1xuICAgIHN0YXRpYyBnZXRSb290QXNOb2RlKGJiOiBmbGF0YnVmZmVycy5CeXRlQnVmZmVyLCBvYmo/OiBOb2RlKTogTm9kZSB7XG4gICAgICByZXR1cm4gKG9iaiB8fCBuZXcgTm9kZSgpKS5fX2luaXQoYmIucmVhZEludDMyKGJiLnBvc2l0aW9uKCkpICsgYmIucG9zaXRpb24oKSwgYmIpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CeXRlQnVmZmVyIGJiXG4gICAgICogQHBhcmFtIE5vZGU9IG9ialxuICAgICAqIEByZXR1cm5zIE5vZGVcbiAgICAgKi9cbiAgICBzdGF0aWMgZ2V0U2l6ZVByZWZpeGVkUm9vdEFzTm9kZShiYjogZmxhdGJ1ZmZlcnMuQnl0ZUJ1ZmZlciwgb2JqPzogTm9kZSk6IE5vZGUge1xuICAgICAgYmIuc2V0UG9zaXRpb24oYmIucG9zaXRpb24oKSArIGZsYXRidWZmZXJzLlNJWkVfUFJFRklYX0xFTkdUSCk7XG4gICAgICByZXR1cm4gKG9iaiB8fCBuZXcgTm9kZSgpKS5fX2luaXQoYmIucmVhZEludDMyKGJiLnBvc2l0aW9uKCkpICsgYmIucG9zaXRpb24oKSwgYmIpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5FbmNvZGluZz0gb3B0aW9uYWxFbmNvZGluZ1xuICAgICAqIEByZXR1cm5zIHN0cmluZ3xVaW50OEFycmF5fG51bGxcbiAgICAgKi9cbiAgICBuYW1lKCk6IHN0cmluZ3xudWxsO1xuICAgIG5hbWUob3B0aW9uYWxFbmNvZGluZzogZmxhdGJ1ZmZlcnMuRW5jb2RpbmcpOiBzdHJpbmd8VWludDhBcnJheXxudWxsO1xuICAgIG5hbWUob3B0aW9uYWxFbmNvZGluZz86IGFueSk6IHN0cmluZ3xVaW50OEFycmF5fG51bGwge1xuICAgICAgbGV0IG9mZnNldCA9IHRoaXMuYmIhLl9fb2Zmc2V0KHRoaXMuYmJfcG9zLCA0KTtcbiAgICAgIHJldHVybiBvZmZzZXQgPyB0aGlzLmJiIS5fX3N0cmluZyh0aGlzLmJiX3BvcyArIG9mZnNldCwgb3B0aW9uYWxFbmNvZGluZykgOiBudWxsO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5FbmNvZGluZz0gb3B0aW9uYWxFbmNvZGluZ1xuICAgICAqIEByZXR1cm5zIHN0cmluZ3xVaW50OEFycmF5fG51bGxcbiAgICAgKi9cbiAgICBkb2NTdHJpbmcoKTogc3RyaW5nfG51bGw7XG4gICAgZG9jU3RyaW5nKG9wdGlvbmFsRW5jb2Rpbmc6IGZsYXRidWZmZXJzLkVuY29kaW5nKTogc3RyaW5nfFVpbnQ4QXJyYXl8bnVsbDtcbiAgICBkb2NTdHJpbmcob3B0aW9uYWxFbmNvZGluZz86IGFueSk6IHN0cmluZ3xVaW50OEFycmF5fG51bGwge1xuICAgICAgbGV0IG9mZnNldCA9IHRoaXMuYmIhLl9fb2Zmc2V0KHRoaXMuYmJfcG9zLCA2KTtcbiAgICAgIHJldHVybiBvZmZzZXQgPyB0aGlzLmJiIS5fX3N0cmluZyh0aGlzLmJiX3BvcyArIG9mZnNldCwgb3B0aW9uYWxFbmNvZGluZykgOiBudWxsO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5FbmNvZGluZz0gb3B0aW9uYWxFbmNvZGluZ1xuICAgICAqIEByZXR1cm5zIHN0cmluZ3xVaW50OEFycmF5fG51bGxcbiAgICAgKi9cbiAgICBkb21haW4oKTogc3RyaW5nfG51bGw7XG4gICAgZG9tYWluKG9wdGlvbmFsRW5jb2Rpbmc6IGZsYXRidWZmZXJzLkVuY29kaW5nKTogc3RyaW5nfFVpbnQ4QXJyYXl8bnVsbDtcbiAgICBkb21haW4ob3B0aW9uYWxFbmNvZGluZz86IGFueSk6IHN0cmluZ3xVaW50OEFycmF5fG51bGwge1xuICAgICAgbGV0IG9mZnNldCA9IHRoaXMuYmIhLl9fb2Zmc2V0KHRoaXMuYmJfcG9zLCA4KTtcbiAgICAgIHJldHVybiBvZmZzZXQgPyB0aGlzLmJiIS5fX3N0cmluZyh0aGlzLmJiX3BvcyArIG9mZnNldCwgb3B0aW9uYWxFbmNvZGluZykgOiBudWxsO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEByZXR1cm5zIG51bWJlclxuICAgICAqL1xuICAgIHNpbmNlVmVyc2lvbigpOiBudW1iZXIge1xuICAgICAgbGV0IG9mZnNldCA9IHRoaXMuYmIhLl9fb2Zmc2V0KHRoaXMuYmJfcG9zLCAxMCk7XG4gICAgICByZXR1cm4gb2Zmc2V0ID8gdGhpcy5iYiEucmVhZEludDMyKHRoaXMuYmJfcG9zICsgb2Zmc2V0KSA6IDA7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHJldHVybnMgbnVtYmVyXG4gICAgICovXG4gICAgaW5kZXgoKTogbnVtYmVyIHtcbiAgICAgIGxldCBvZmZzZXQgPSB0aGlzLmJiIS5fX29mZnNldCh0aGlzLmJiX3BvcywgMTIpO1xuICAgICAgcmV0dXJuIG9mZnNldCA/IHRoaXMuYmIhLnJlYWRVaW50MzIodGhpcy5iYl9wb3MgKyBvZmZzZXQpIDogMDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuRW5jb2Rpbmc9IG9wdGlvbmFsRW5jb2RpbmdcbiAgICAgKiBAcmV0dXJucyBzdHJpbmd8VWludDhBcnJheXxudWxsXG4gICAgICovXG4gICAgb3BUeXBlKCk6IHN0cmluZ3xudWxsO1xuICAgIG9wVHlwZShvcHRpb25hbEVuY29kaW5nOiBmbGF0YnVmZmVycy5FbmNvZGluZyk6IHN0cmluZ3xVaW50OEFycmF5fG51bGw7XG4gICAgb3BUeXBlKG9wdGlvbmFsRW5jb2Rpbmc/OiBhbnkpOiBzdHJpbmd8VWludDhBcnJheXxudWxsIHtcbiAgICAgIGxldCBvZmZzZXQgPSB0aGlzLmJiIS5fX29mZnNldCh0aGlzLmJiX3BvcywgMTQpO1xuICAgICAgcmV0dXJuIG9mZnNldCA/IHRoaXMuYmIhLl9fc3RyaW5nKHRoaXMuYmJfcG9zICsgb2Zmc2V0LCBvcHRpb25hbEVuY29kaW5nKSA6IG51bGw7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHJldHVybnMgb25ueHJ1bnRpbWUuZXhwZXJpbWVudGFsLmZicy5Ob2RlVHlwZVxuICAgICAqL1xuICAgIHR5cGUoKTogb25ueHJ1bnRpbWUuZXhwZXJpbWVudGFsLmZicy5Ob2RlVHlwZSB7XG4gICAgICBsZXQgb2Zmc2V0ID0gdGhpcy5iYiEuX19vZmZzZXQodGhpcy5iYl9wb3MsIDE2KTtcbiAgICAgIHJldHVybiBvZmZzZXQgPyAvKiogICovICh0aGlzLmJiIS5yZWFkSW50MzIodGhpcy5iYl9wb3MgKyBvZmZzZXQpKSA6XG4gICAgICAgICAgICAgICAgICAgICAgb25ueHJ1bnRpbWUuZXhwZXJpbWVudGFsLmZicy5Ob2RlVHlwZS5QcmltaXRpdmU7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkVuY29kaW5nPSBvcHRpb25hbEVuY29kaW5nXG4gICAgICogQHJldHVybnMgc3RyaW5nfFVpbnQ4QXJyYXl8bnVsbFxuICAgICAqL1xuICAgIGV4ZWN1dGlvblByb3ZpZGVyVHlwZSgpOiBzdHJpbmd8bnVsbDtcbiAgICBleGVjdXRpb25Qcm92aWRlclR5cGUob3B0aW9uYWxFbmNvZGluZzogZmxhdGJ1ZmZlcnMuRW5jb2RpbmcpOiBzdHJpbmd8VWludDhBcnJheXxudWxsO1xuICAgIGV4ZWN1dGlvblByb3ZpZGVyVHlwZShvcHRpb25hbEVuY29kaW5nPzogYW55KTogc3RyaW5nfFVpbnQ4QXJyYXl8bnVsbCB7XG4gICAgICBsZXQgb2Zmc2V0ID0gdGhpcy5iYiEuX19vZmZzZXQodGhpcy5iYl9wb3MsIDE4KTtcbiAgICAgIHJldHVybiBvZmZzZXQgPyB0aGlzLmJiIS5fX3N0cmluZyh0aGlzLmJiX3BvcyArIG9mZnNldCwgb3B0aW9uYWxFbmNvZGluZykgOiBudWxsO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBudW1iZXIgaW5kZXhcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuRW5jb2Rpbmc9IG9wdGlvbmFsRW5jb2RpbmdcbiAgICAgKiBAcmV0dXJucyBzdHJpbmd8VWludDhBcnJheVxuICAgICAqL1xuICAgIGlucHV0cyhpbmRleDogbnVtYmVyKTogc3RyaW5nO1xuICAgIGlucHV0cyhpbmRleDogbnVtYmVyLCBvcHRpb25hbEVuY29kaW5nOiBmbGF0YnVmZmVycy5FbmNvZGluZyk6IHN0cmluZ3xVaW50OEFycmF5O1xuICAgIGlucHV0cyhpbmRleDogbnVtYmVyLCBvcHRpb25hbEVuY29kaW5nPzogYW55KTogc3RyaW5nfFVpbnQ4QXJyYXl8bnVsbCB7XG4gICAgICBsZXQgb2Zmc2V0ID0gdGhpcy5iYiEuX19vZmZzZXQodGhpcy5iYl9wb3MsIDIwKTtcbiAgICAgIHJldHVybiBvZmZzZXQgPyB0aGlzLmJiIS5fX3N0cmluZyh0aGlzLmJiIS5fX3ZlY3Rvcih0aGlzLmJiX3BvcyArIG9mZnNldCkgKyBpbmRleCAqIDQsIG9wdGlvbmFsRW5jb2RpbmcpIDogbnVsbDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcmV0dXJucyBudW1iZXJcbiAgICAgKi9cbiAgICBpbnB1dHNMZW5ndGgoKTogbnVtYmVyIHtcbiAgICAgIGxldCBvZmZzZXQgPSB0aGlzLmJiIS5fX29mZnNldCh0aGlzLmJiX3BvcywgMjApO1xuICAgICAgcmV0dXJuIG9mZnNldCA/IHRoaXMuYmIhLl9fdmVjdG9yX2xlbih0aGlzLmJiX3BvcyArIG9mZnNldCkgOiAwO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBudW1iZXIgaW5kZXhcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuRW5jb2Rpbmc9IG9wdGlvbmFsRW5jb2RpbmdcbiAgICAgKiBAcmV0dXJucyBzdHJpbmd8VWludDhBcnJheVxuICAgICAqL1xuICAgIG91dHB1dHMoaW5kZXg6IG51bWJlcik6IHN0cmluZztcbiAgICBvdXRwdXRzKGluZGV4OiBudW1iZXIsIG9wdGlvbmFsRW5jb2Rpbmc6IGZsYXRidWZmZXJzLkVuY29kaW5nKTogc3RyaW5nfFVpbnQ4QXJyYXk7XG4gICAgb3V0cHV0cyhpbmRleDogbnVtYmVyLCBvcHRpb25hbEVuY29kaW5nPzogYW55KTogc3RyaW5nfFVpbnQ4QXJyYXl8bnVsbCB7XG4gICAgICBsZXQgb2Zmc2V0ID0gdGhpcy5iYiEuX19vZmZzZXQodGhpcy5iYl9wb3MsIDIyKTtcbiAgICAgIHJldHVybiBvZmZzZXQgPyB0aGlzLmJiIS5fX3N0cmluZyh0aGlzLmJiIS5fX3ZlY3Rvcih0aGlzLmJiX3BvcyArIG9mZnNldCkgKyBpbmRleCAqIDQsIG9wdGlvbmFsRW5jb2RpbmcpIDogbnVsbDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcmV0dXJucyBudW1iZXJcbiAgICAgKi9cbiAgICBvdXRwdXRzTGVuZ3RoKCk6IG51bWJlciB7XG4gICAgICBsZXQgb2Zmc2V0ID0gdGhpcy5iYiEuX19vZmZzZXQodGhpcy5iYl9wb3MsIDIyKTtcbiAgICAgIHJldHVybiBvZmZzZXQgPyB0aGlzLmJiIS5fX3ZlY3Rvcl9sZW4odGhpcy5iYl9wb3MgKyBvZmZzZXQpIDogMDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gbnVtYmVyIGluZGV4XG4gICAgICogQHBhcmFtIG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnMuQXR0cmlidXRlPSBvYmpcbiAgICAgKiBAcmV0dXJucyBvbm54cnVudGltZS5leHBlcmltZW50YWwuZmJzLkF0dHJpYnV0ZVxuICAgICAqL1xuICAgIGF0dHJpYnV0ZXMoaW5kZXg6IG51bWJlciwgb2JqPzogb25ueHJ1bnRpbWUuZXhwZXJpbWVudGFsLmZicy5BdHRyaWJ1dGUpOiBvbm54cnVudGltZS5leHBlcmltZW50YWwuZmJzLkF0dHJpYnV0ZVxuICAgICAgICB8bnVsbCB7XG4gICAgICBsZXQgb2Zmc2V0ID0gdGhpcy5iYiEuX19vZmZzZXQodGhpcy5iYl9wb3MsIDI0KTtcbiAgICAgIHJldHVybiBvZmZzZXQgPyAob2JqIHx8IG5ldyBvbm54cnVudGltZS5leHBlcmltZW50YWwuZmJzLkF0dHJpYnV0ZSgpKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAuX19pbml0KHRoaXMuYmIhLl9faW5kaXJlY3QodGhpcy5iYiEuX192ZWN0b3IodGhpcy5iYl9wb3MgKyBvZmZzZXQpICsgaW5kZXggKiA0KSwgdGhpcy5iYiEpIDpcbiAgICAgICAgICAgICAgICAgICAgICBudWxsO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEByZXR1cm5zIG51bWJlclxuICAgICAqL1xuICAgIGF0dHJpYnV0ZXNMZW5ndGgoKTogbnVtYmVyIHtcbiAgICAgIGxldCBvZmZzZXQgPSB0aGlzLmJiIS5fX29mZnNldCh0aGlzLmJiX3BvcywgMjQpO1xuICAgICAgcmV0dXJuIG9mZnNldCA/IHRoaXMuYmIhLl9fdmVjdG9yX2xlbih0aGlzLmJiX3BvcyArIG9mZnNldCkgOiAwO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBudW1iZXIgaW5kZXhcbiAgICAgKiBAcmV0dXJucyBudW1iZXJcbiAgICAgKi9cbiAgICBpbnB1dEFyZ0NvdW50cyhpbmRleDogbnVtYmVyKTogbnVtYmVyfG51bGwge1xuICAgICAgbGV0IG9mZnNldCA9IHRoaXMuYmIhLl9fb2Zmc2V0KHRoaXMuYmJfcG9zLCAyNik7XG4gICAgICByZXR1cm4gb2Zmc2V0ID8gdGhpcy5iYiEucmVhZEludDMyKHRoaXMuYmIhLl9fdmVjdG9yKHRoaXMuYmJfcG9zICsgb2Zmc2V0KSArIGluZGV4ICogNCkgOiAwO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEByZXR1cm5zIG51bWJlclxuICAgICAqL1xuICAgIGlucHV0QXJnQ291bnRzTGVuZ3RoKCk6IG51bWJlciB7XG4gICAgICBsZXQgb2Zmc2V0ID0gdGhpcy5iYiEuX19vZmZzZXQodGhpcy5iYl9wb3MsIDI2KTtcbiAgICAgIHJldHVybiBvZmZzZXQgPyB0aGlzLmJiIS5fX3ZlY3Rvcl9sZW4odGhpcy5iYl9wb3MgKyBvZmZzZXQpIDogMDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcmV0dXJucyBJbnQzMkFycmF5XG4gICAgICovXG4gICAgaW5wdXRBcmdDb3VudHNBcnJheSgpOiBJbnQzMkFycmF5fG51bGwge1xuICAgICAgbGV0IG9mZnNldCA9IHRoaXMuYmIhLl9fb2Zmc2V0KHRoaXMuYmJfcG9zLCAyNik7XG4gICAgICByZXR1cm4gb2Zmc2V0ID9cbiAgICAgICAgICBuZXcgSW50MzJBcnJheShcbiAgICAgICAgICAgICAgdGhpcy5iYiEuYnl0ZXMoKS5idWZmZXIsIHRoaXMuYmIhLmJ5dGVzKCkuYnl0ZU9mZnNldCArIHRoaXMuYmIhLl9fdmVjdG9yKHRoaXMuYmJfcG9zICsgb2Zmc2V0KSxcbiAgICAgICAgICAgICAgdGhpcy5iYiEuX192ZWN0b3JfbGVuKHRoaXMuYmJfcG9zICsgb2Zmc2V0KSkgOlxuICAgICAgICAgIG51bGw7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIG51bWJlciBpbmRleFxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5FbmNvZGluZz0gb3B0aW9uYWxFbmNvZGluZ1xuICAgICAqIEByZXR1cm5zIHN0cmluZ3xVaW50OEFycmF5XG4gICAgICovXG4gICAgaW1wbGljaXRJbnB1dHMoaW5kZXg6IG51bWJlcik6IHN0cmluZztcbiAgICBpbXBsaWNpdElucHV0cyhpbmRleDogbnVtYmVyLCBvcHRpb25hbEVuY29kaW5nOiBmbGF0YnVmZmVycy5FbmNvZGluZyk6IHN0cmluZ3xVaW50OEFycmF5O1xuICAgIGltcGxpY2l0SW5wdXRzKGluZGV4OiBudW1iZXIsIG9wdGlvbmFsRW5jb2Rpbmc/OiBhbnkpOiBzdHJpbmd8VWludDhBcnJheXxudWxsIHtcbiAgICAgIGxldCBvZmZzZXQgPSB0aGlzLmJiIS5fX29mZnNldCh0aGlzLmJiX3BvcywgMjgpO1xuICAgICAgcmV0dXJuIG9mZnNldCA/IHRoaXMuYmIhLl9fc3RyaW5nKHRoaXMuYmIhLl9fdmVjdG9yKHRoaXMuYmJfcG9zICsgb2Zmc2V0KSArIGluZGV4ICogNCwgb3B0aW9uYWxFbmNvZGluZykgOiBudWxsO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEByZXR1cm5zIG51bWJlclxuICAgICAqL1xuICAgIGltcGxpY2l0SW5wdXRzTGVuZ3RoKCk6IG51bWJlciB7XG4gICAgICBsZXQgb2Zmc2V0ID0gdGhpcy5iYiEuX19vZmZzZXQodGhpcy5iYl9wb3MsIDI4KTtcbiAgICAgIHJldHVybiBvZmZzZXQgPyB0aGlzLmJiIS5fX3ZlY3Rvcl9sZW4odGhpcy5iYl9wb3MgKyBvZmZzZXQpIDogMDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuQnVpbGRlciBidWlsZGVyXG4gICAgICovXG4gICAgc3RhdGljIHN0YXJ0Tm9kZShidWlsZGVyOiBmbGF0YnVmZmVycy5CdWlsZGVyKSB7XG4gICAgICBidWlsZGVyLnN0YXJ0T2JqZWN0KDEzKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuQnVpbGRlciBidWlsZGVyXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLk9mZnNldCBuYW1lT2Zmc2V0XG4gICAgICovXG4gICAgc3RhdGljIGFkZE5hbWUoYnVpbGRlcjogZmxhdGJ1ZmZlcnMuQnVpbGRlciwgbmFtZU9mZnNldDogZmxhdGJ1ZmZlcnMuT2Zmc2V0KSB7XG4gICAgICBidWlsZGVyLmFkZEZpZWxkT2Zmc2V0KDAsIG5hbWVPZmZzZXQsIDApO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CdWlsZGVyIGJ1aWxkZXJcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuT2Zmc2V0IGRvY1N0cmluZ09mZnNldFxuICAgICAqL1xuICAgIHN0YXRpYyBhZGREb2NTdHJpbmcoYnVpbGRlcjogZmxhdGJ1ZmZlcnMuQnVpbGRlciwgZG9jU3RyaW5nT2Zmc2V0OiBmbGF0YnVmZmVycy5PZmZzZXQpIHtcbiAgICAgIGJ1aWxkZXIuYWRkRmllbGRPZmZzZXQoMSwgZG9jU3RyaW5nT2Zmc2V0LCAwKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuQnVpbGRlciBidWlsZGVyXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLk9mZnNldCBkb21haW5PZmZzZXRcbiAgICAgKi9cbiAgICBzdGF0aWMgYWRkRG9tYWluKGJ1aWxkZXI6IGZsYXRidWZmZXJzLkJ1aWxkZXIsIGRvbWFpbk9mZnNldDogZmxhdGJ1ZmZlcnMuT2Zmc2V0KSB7XG4gICAgICBidWlsZGVyLmFkZEZpZWxkT2Zmc2V0KDIsIGRvbWFpbk9mZnNldCwgMCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ1aWxkZXIgYnVpbGRlclxuICAgICAqIEBwYXJhbSBudW1iZXIgc2luY2VWZXJzaW9uXG4gICAgICovXG4gICAgc3RhdGljIGFkZFNpbmNlVmVyc2lvbihidWlsZGVyOiBmbGF0YnVmZmVycy5CdWlsZGVyLCBzaW5jZVZlcnNpb246IG51bWJlcikge1xuICAgICAgYnVpbGRlci5hZGRGaWVsZEludDMyKDMsIHNpbmNlVmVyc2lvbiwgMCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ1aWxkZXIgYnVpbGRlclxuICAgICAqIEBwYXJhbSBudW1iZXIgaW5kZXhcbiAgICAgKi9cbiAgICBzdGF0aWMgYWRkSW5kZXgoYnVpbGRlcjogZmxhdGJ1ZmZlcnMuQnVpbGRlciwgaW5kZXg6IG51bWJlcikge1xuICAgICAgYnVpbGRlci5hZGRGaWVsZEludDMyKDQsIGluZGV4LCAwKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuQnVpbGRlciBidWlsZGVyXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLk9mZnNldCBvcFR5cGVPZmZzZXRcbiAgICAgKi9cbiAgICBzdGF0aWMgYWRkT3BUeXBlKGJ1aWxkZXI6IGZsYXRidWZmZXJzLkJ1aWxkZXIsIG9wVHlwZU9mZnNldDogZmxhdGJ1ZmZlcnMuT2Zmc2V0KSB7XG4gICAgICBidWlsZGVyLmFkZEZpZWxkT2Zmc2V0KDUsIG9wVHlwZU9mZnNldCwgMCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ1aWxkZXIgYnVpbGRlclxuICAgICAqIEBwYXJhbSBvbm54cnVudGltZS5leHBlcmltZW50YWwuZmJzLk5vZGVUeXBlIHR5cGVcbiAgICAgKi9cbiAgICBzdGF0aWMgYWRkVHlwZShidWlsZGVyOiBmbGF0YnVmZmVycy5CdWlsZGVyLCB0eXBlOiBvbm54cnVudGltZS5leHBlcmltZW50YWwuZmJzLk5vZGVUeXBlKSB7XG4gICAgICBidWlsZGVyLmFkZEZpZWxkSW50MzIoNiwgdHlwZSwgb25ueHJ1bnRpbWUuZXhwZXJpbWVudGFsLmZicy5Ob2RlVHlwZS5QcmltaXRpdmUpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CdWlsZGVyIGJ1aWxkZXJcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuT2Zmc2V0IGV4ZWN1dGlvblByb3ZpZGVyVHlwZU9mZnNldFxuICAgICAqL1xuICAgIHN0YXRpYyBhZGRFeGVjdXRpb25Qcm92aWRlclR5cGUoYnVpbGRlcjogZmxhdGJ1ZmZlcnMuQnVpbGRlciwgZXhlY3V0aW9uUHJvdmlkZXJUeXBlT2Zmc2V0OiBmbGF0YnVmZmVycy5PZmZzZXQpIHtcbiAgICAgIGJ1aWxkZXIuYWRkRmllbGRPZmZzZXQoNywgZXhlY3V0aW9uUHJvdmlkZXJUeXBlT2Zmc2V0LCAwKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuQnVpbGRlciBidWlsZGVyXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLk9mZnNldCBpbnB1dHNPZmZzZXRcbiAgICAgKi9cbiAgICBzdGF0aWMgYWRkSW5wdXRzKGJ1aWxkZXI6IGZsYXRidWZmZXJzLkJ1aWxkZXIsIGlucHV0c09mZnNldDogZmxhdGJ1ZmZlcnMuT2Zmc2V0KSB7XG4gICAgICBidWlsZGVyLmFkZEZpZWxkT2Zmc2V0KDgsIGlucHV0c09mZnNldCwgMCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ1aWxkZXIgYnVpbGRlclxuICAgICAqIEBwYXJhbSBBcnJheS48ZmxhdGJ1ZmZlcnMuT2Zmc2V0PiBkYXRhXG4gICAgICogQHJldHVybnMgZmxhdGJ1ZmZlcnMuT2Zmc2V0XG4gICAgICovXG4gICAgc3RhdGljIGNyZWF0ZUlucHV0c1ZlY3RvcihidWlsZGVyOiBmbGF0YnVmZmVycy5CdWlsZGVyLCBkYXRhOiBmbGF0YnVmZmVycy5PZmZzZXRbXSk6IGZsYXRidWZmZXJzLk9mZnNldCB7XG4gICAgICBidWlsZGVyLnN0YXJ0VmVjdG9yKDQsIGRhdGEubGVuZ3RoLCA0KTtcbiAgICAgIGZvciAobGV0IGkgPSBkYXRhLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSB7XG4gICAgICAgIGJ1aWxkZXIuYWRkT2Zmc2V0KGRhdGFbaV0pO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGJ1aWxkZXIuZW5kVmVjdG9yKCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ1aWxkZXIgYnVpbGRlclxuICAgICAqIEBwYXJhbSBudW1iZXIgbnVtRWxlbXNcbiAgICAgKi9cbiAgICBzdGF0aWMgc3RhcnRJbnB1dHNWZWN0b3IoYnVpbGRlcjogZmxhdGJ1ZmZlcnMuQnVpbGRlciwgbnVtRWxlbXM6IG51bWJlcikge1xuICAgICAgYnVpbGRlci5zdGFydFZlY3Rvcig0LCBudW1FbGVtcywgNCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ1aWxkZXIgYnVpbGRlclxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5PZmZzZXQgb3V0cHV0c09mZnNldFxuICAgICAqL1xuICAgIHN0YXRpYyBhZGRPdXRwdXRzKGJ1aWxkZXI6IGZsYXRidWZmZXJzLkJ1aWxkZXIsIG91dHB1dHNPZmZzZXQ6IGZsYXRidWZmZXJzLk9mZnNldCkge1xuICAgICAgYnVpbGRlci5hZGRGaWVsZE9mZnNldCg5LCBvdXRwdXRzT2Zmc2V0LCAwKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuQnVpbGRlciBidWlsZGVyXG4gICAgICogQHBhcmFtIEFycmF5LjxmbGF0YnVmZmVycy5PZmZzZXQ+IGRhdGFcbiAgICAgKiBAcmV0dXJucyBmbGF0YnVmZmVycy5PZmZzZXRcbiAgICAgKi9cbiAgICBzdGF0aWMgY3JlYXRlT3V0cHV0c1ZlY3RvcihidWlsZGVyOiBmbGF0YnVmZmVycy5CdWlsZGVyLCBkYXRhOiBmbGF0YnVmZmVycy5PZmZzZXRbXSk6IGZsYXRidWZmZXJzLk9mZnNldCB7XG4gICAgICBidWlsZGVyLnN0YXJ0VmVjdG9yKDQsIGRhdGEubGVuZ3RoLCA0KTtcbiAgICAgIGZvciAobGV0IGkgPSBkYXRhLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSB7XG4gICAgICAgIGJ1aWxkZXIuYWRkT2Zmc2V0KGRhdGFbaV0pO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGJ1aWxkZXIuZW5kVmVjdG9yKCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ1aWxkZXIgYnVpbGRlclxuICAgICAqIEBwYXJhbSBudW1iZXIgbnVtRWxlbXNcbiAgICAgKi9cbiAgICBzdGF0aWMgc3RhcnRPdXRwdXRzVmVjdG9yKGJ1aWxkZXI6IGZsYXRidWZmZXJzLkJ1aWxkZXIsIG51bUVsZW1zOiBudW1iZXIpIHtcbiAgICAgIGJ1aWxkZXIuc3RhcnRWZWN0b3IoNCwgbnVtRWxlbXMsIDQpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CdWlsZGVyIGJ1aWxkZXJcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuT2Zmc2V0IGF0dHJpYnV0ZXNPZmZzZXRcbiAgICAgKi9cbiAgICBzdGF0aWMgYWRkQXR0cmlidXRlcyhidWlsZGVyOiBmbGF0YnVmZmVycy5CdWlsZGVyLCBhdHRyaWJ1dGVzT2Zmc2V0OiBmbGF0YnVmZmVycy5PZmZzZXQpIHtcbiAgICAgIGJ1aWxkZXIuYWRkRmllbGRPZmZzZXQoMTAsIGF0dHJpYnV0ZXNPZmZzZXQsIDApO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CdWlsZGVyIGJ1aWxkZXJcbiAgICAgKiBAcGFyYW0gQXJyYXkuPGZsYXRidWZmZXJzLk9mZnNldD4gZGF0YVxuICAgICAqIEByZXR1cm5zIGZsYXRidWZmZXJzLk9mZnNldFxuICAgICAqL1xuICAgIHN0YXRpYyBjcmVhdGVBdHRyaWJ1dGVzVmVjdG9yKGJ1aWxkZXI6IGZsYXRidWZmZXJzLkJ1aWxkZXIsIGRhdGE6IGZsYXRidWZmZXJzLk9mZnNldFtdKTogZmxhdGJ1ZmZlcnMuT2Zmc2V0IHtcbiAgICAgIGJ1aWxkZXIuc3RhcnRWZWN0b3IoNCwgZGF0YS5sZW5ndGgsIDQpO1xuICAgICAgZm9yIChsZXQgaSA9IGRhdGEubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICAgICAgYnVpbGRlci5hZGRPZmZzZXQoZGF0YVtpXSk7XG4gICAgICB9XG4gICAgICByZXR1cm4gYnVpbGRlci5lbmRWZWN0b3IoKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuQnVpbGRlciBidWlsZGVyXG4gICAgICogQHBhcmFtIG51bWJlciBudW1FbGVtc1xuICAgICAqL1xuICAgIHN0YXRpYyBzdGFydEF0dHJpYnV0ZXNWZWN0b3IoYnVpbGRlcjogZmxhdGJ1ZmZlcnMuQnVpbGRlciwgbnVtRWxlbXM6IG51bWJlcikge1xuICAgICAgYnVpbGRlci5zdGFydFZlY3Rvcig0LCBudW1FbGVtcywgNCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ1aWxkZXIgYnVpbGRlclxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5PZmZzZXQgaW5wdXRBcmdDb3VudHNPZmZzZXRcbiAgICAgKi9cbiAgICBzdGF0aWMgYWRkSW5wdXRBcmdDb3VudHMoYnVpbGRlcjogZmxhdGJ1ZmZlcnMuQnVpbGRlciwgaW5wdXRBcmdDb3VudHNPZmZzZXQ6IGZsYXRidWZmZXJzLk9mZnNldCkge1xuICAgICAgYnVpbGRlci5hZGRGaWVsZE9mZnNldCgxMSwgaW5wdXRBcmdDb3VudHNPZmZzZXQsIDApO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CdWlsZGVyIGJ1aWxkZXJcbiAgICAgKiBAcGFyYW0gQXJyYXkuPG51bWJlcj4gZGF0YVxuICAgICAqIEByZXR1cm5zIGZsYXRidWZmZXJzLk9mZnNldFxuICAgICAqL1xuICAgIHN0YXRpYyBjcmVhdGVJbnB1dEFyZ0NvdW50c1ZlY3RvcihidWlsZGVyOiBmbGF0YnVmZmVycy5CdWlsZGVyLCBkYXRhOiBudW1iZXJbXXxVaW50OEFycmF5KTogZmxhdGJ1ZmZlcnMuT2Zmc2V0IHtcbiAgICAgIGJ1aWxkZXIuc3RhcnRWZWN0b3IoNCwgZGF0YS5sZW5ndGgsIDQpO1xuICAgICAgZm9yIChsZXQgaSA9IGRhdGEubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICAgICAgYnVpbGRlci5hZGRJbnQzMihkYXRhW2ldKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBidWlsZGVyLmVuZFZlY3RvcigpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CdWlsZGVyIGJ1aWxkZXJcbiAgICAgKiBAcGFyYW0gbnVtYmVyIG51bUVsZW1zXG4gICAgICovXG4gICAgc3RhdGljIHN0YXJ0SW5wdXRBcmdDb3VudHNWZWN0b3IoYnVpbGRlcjogZmxhdGJ1ZmZlcnMuQnVpbGRlciwgbnVtRWxlbXM6IG51bWJlcikge1xuICAgICAgYnVpbGRlci5zdGFydFZlY3Rvcig0LCBudW1FbGVtcywgNCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ1aWxkZXIgYnVpbGRlclxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5PZmZzZXQgaW1wbGljaXRJbnB1dHNPZmZzZXRcbiAgICAgKi9cbiAgICBzdGF0aWMgYWRkSW1wbGljaXRJbnB1dHMoYnVpbGRlcjogZmxhdGJ1ZmZlcnMuQnVpbGRlciwgaW1wbGljaXRJbnB1dHNPZmZzZXQ6IGZsYXRidWZmZXJzLk9mZnNldCkge1xuICAgICAgYnVpbGRlci5hZGRGaWVsZE9mZnNldCgxMiwgaW1wbGljaXRJbnB1dHNPZmZzZXQsIDApO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CdWlsZGVyIGJ1aWxkZXJcbiAgICAgKiBAcGFyYW0gQXJyYXkuPGZsYXRidWZmZXJzLk9mZnNldD4gZGF0YVxuICAgICAqIEByZXR1cm5zIGZsYXRidWZmZXJzLk9mZnNldFxuICAgICAqL1xuICAgIHN0YXRpYyBjcmVhdGVJbXBsaWNpdElucHV0c1ZlY3RvcihidWlsZGVyOiBmbGF0YnVmZmVycy5CdWlsZGVyLCBkYXRhOiBmbGF0YnVmZmVycy5PZmZzZXRbXSk6IGZsYXRidWZmZXJzLk9mZnNldCB7XG4gICAgICBidWlsZGVyLnN0YXJ0VmVjdG9yKDQsIGRhdGEubGVuZ3RoLCA0KTtcbiAgICAgIGZvciAobGV0IGkgPSBkYXRhLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSB7XG4gICAgICAgIGJ1aWxkZXIuYWRkT2Zmc2V0KGRhdGFbaV0pO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGJ1aWxkZXIuZW5kVmVjdG9yKCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ1aWxkZXIgYnVpbGRlclxuICAgICAqIEBwYXJhbSBudW1iZXIgbnVtRWxlbXNcbiAgICAgKi9cbiAgICBzdGF0aWMgc3RhcnRJbXBsaWNpdElucHV0c1ZlY3RvcihidWlsZGVyOiBmbGF0YnVmZmVycy5CdWlsZGVyLCBudW1FbGVtczogbnVtYmVyKSB7XG4gICAgICBidWlsZGVyLnN0YXJ0VmVjdG9yKDQsIG51bUVsZW1zLCA0KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuQnVpbGRlciBidWlsZGVyXG4gICAgICogQHJldHVybnMgZmxhdGJ1ZmZlcnMuT2Zmc2V0XG4gICAgICovXG4gICAgc3RhdGljIGVuZE5vZGUoYnVpbGRlcjogZmxhdGJ1ZmZlcnMuQnVpbGRlcik6IGZsYXRidWZmZXJzLk9mZnNldCB7XG4gICAgICBsZXQgb2Zmc2V0ID0gYnVpbGRlci5lbmRPYmplY3QoKTtcbiAgICAgIHJldHVybiBvZmZzZXQ7XG4gICAgfVxuXG4gICAgc3RhdGljIGNyZWF0ZU5vZGUoXG4gICAgICAgIGJ1aWxkZXI6IGZsYXRidWZmZXJzLkJ1aWxkZXIsIG5hbWVPZmZzZXQ6IGZsYXRidWZmZXJzLk9mZnNldCwgZG9jU3RyaW5nT2Zmc2V0OiBmbGF0YnVmZmVycy5PZmZzZXQsXG4gICAgICAgIGRvbWFpbk9mZnNldDogZmxhdGJ1ZmZlcnMuT2Zmc2V0LCBzaW5jZVZlcnNpb246IG51bWJlciwgaW5kZXg6IG51bWJlciwgb3BUeXBlT2Zmc2V0OiBmbGF0YnVmZmVycy5PZmZzZXQsXG4gICAgICAgIHR5cGU6IG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnMuTm9kZVR5cGUsIGV4ZWN1dGlvblByb3ZpZGVyVHlwZU9mZnNldDogZmxhdGJ1ZmZlcnMuT2Zmc2V0LFxuICAgICAgICBpbnB1dHNPZmZzZXQ6IGZsYXRidWZmZXJzLk9mZnNldCwgb3V0cHV0c09mZnNldDogZmxhdGJ1ZmZlcnMuT2Zmc2V0LCBhdHRyaWJ1dGVzT2Zmc2V0OiBmbGF0YnVmZmVycy5PZmZzZXQsXG4gICAgICAgIGlucHV0QXJnQ291bnRzT2Zmc2V0OiBmbGF0YnVmZmVycy5PZmZzZXQsIGltcGxpY2l0SW5wdXRzT2Zmc2V0OiBmbGF0YnVmZmVycy5PZmZzZXQpOiBmbGF0YnVmZmVycy5PZmZzZXQge1xuICAgICAgTm9kZS5zdGFydE5vZGUoYnVpbGRlcik7XG4gICAgICBOb2RlLmFkZE5hbWUoYnVpbGRlciwgbmFtZU9mZnNldCk7XG4gICAgICBOb2RlLmFkZERvY1N0cmluZyhidWlsZGVyLCBkb2NTdHJpbmdPZmZzZXQpO1xuICAgICAgTm9kZS5hZGREb21haW4oYnVpbGRlciwgZG9tYWluT2Zmc2V0KTtcbiAgICAgIE5vZGUuYWRkU2luY2VWZXJzaW9uKGJ1aWxkZXIsIHNpbmNlVmVyc2lvbik7XG4gICAgICBOb2RlLmFkZEluZGV4KGJ1aWxkZXIsIGluZGV4KTtcbiAgICAgIE5vZGUuYWRkT3BUeXBlKGJ1aWxkZXIsIG9wVHlwZU9mZnNldCk7XG4gICAgICBOb2RlLmFkZFR5cGUoYnVpbGRlciwgdHlwZSk7XG4gICAgICBOb2RlLmFkZEV4ZWN1dGlvblByb3ZpZGVyVHlwZShidWlsZGVyLCBleGVjdXRpb25Qcm92aWRlclR5cGVPZmZzZXQpO1xuICAgICAgTm9kZS5hZGRJbnB1dHMoYnVpbGRlciwgaW5wdXRzT2Zmc2V0KTtcbiAgICAgIE5vZGUuYWRkT3V0cHV0cyhidWlsZGVyLCBvdXRwdXRzT2Zmc2V0KTtcbiAgICAgIE5vZGUuYWRkQXR0cmlidXRlcyhidWlsZGVyLCBhdHRyaWJ1dGVzT2Zmc2V0KTtcbiAgICAgIE5vZGUuYWRkSW5wdXRBcmdDb3VudHMoYnVpbGRlciwgaW5wdXRBcmdDb3VudHNPZmZzZXQpO1xuICAgICAgTm9kZS5hZGRJbXBsaWNpdElucHV0cyhidWlsZGVyLCBpbXBsaWNpdElucHV0c09mZnNldCk7XG4gICAgICByZXR1cm4gTm9kZS5lbmROb2RlKGJ1aWxkZXIpO1xuICAgIH1cbiAgfVxufVxuLyoqXG4gKiBAY29uc3RydWN0b3JcbiAqL1xuZXhwb3J0IG5hbWVzcGFjZSBvbm54cnVudGltZS5leHBlcmltZW50YWwuZmJzIHtcbiAgZXhwb3J0IGNsYXNzIFZhbHVlSW5mbyB7XG4gICAgYmI6IGZsYXRidWZmZXJzLkJ5dGVCdWZmZXJ8bnVsbCA9IG51bGw7XG5cbiAgICBiYl9wb3MgPSAwO1xuICAgIC8qKlxuICAgICAqIEBwYXJhbSBudW1iZXIgaVxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CeXRlQnVmZmVyIGJiXG4gICAgICogQHJldHVybnMgVmFsdWVJbmZvXG4gICAgICovXG4gICAgX19pbml0KGk6IG51bWJlciwgYmI6IGZsYXRidWZmZXJzLkJ5dGVCdWZmZXIpOiBWYWx1ZUluZm8ge1xuICAgICAgdGhpcy5iYl9wb3MgPSBpO1xuICAgICAgdGhpcy5iYiA9IGJiO1xuICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ5dGVCdWZmZXIgYmJcbiAgICAgKiBAcGFyYW0gVmFsdWVJbmZvPSBvYmpcbiAgICAgKiBAcmV0dXJucyBWYWx1ZUluZm9cbiAgICAgKi9cbiAgICBzdGF0aWMgZ2V0Um9vdEFzVmFsdWVJbmZvKGJiOiBmbGF0YnVmZmVycy5CeXRlQnVmZmVyLCBvYmo/OiBWYWx1ZUluZm8pOiBWYWx1ZUluZm8ge1xuICAgICAgcmV0dXJuIChvYmogfHwgbmV3IFZhbHVlSW5mbygpKS5fX2luaXQoYmIucmVhZEludDMyKGJiLnBvc2l0aW9uKCkpICsgYmIucG9zaXRpb24oKSwgYmIpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CeXRlQnVmZmVyIGJiXG4gICAgICogQHBhcmFtIFZhbHVlSW5mbz0gb2JqXG4gICAgICogQHJldHVybnMgVmFsdWVJbmZvXG4gICAgICovXG4gICAgc3RhdGljIGdldFNpemVQcmVmaXhlZFJvb3RBc1ZhbHVlSW5mbyhiYjogZmxhdGJ1ZmZlcnMuQnl0ZUJ1ZmZlciwgb2JqPzogVmFsdWVJbmZvKTogVmFsdWVJbmZvIHtcbiAgICAgIGJiLnNldFBvc2l0aW9uKGJiLnBvc2l0aW9uKCkgKyBmbGF0YnVmZmVycy5TSVpFX1BSRUZJWF9MRU5HVEgpO1xuICAgICAgcmV0dXJuIChvYmogfHwgbmV3IFZhbHVlSW5mbygpKS5fX2luaXQoYmIucmVhZEludDMyKGJiLnBvc2l0aW9uKCkpICsgYmIucG9zaXRpb24oKSwgYmIpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5FbmNvZGluZz0gb3B0aW9uYWxFbmNvZGluZ1xuICAgICAqIEByZXR1cm5zIHN0cmluZ3xVaW50OEFycmF5fG51bGxcbiAgICAgKi9cbiAgICBuYW1lKCk6IHN0cmluZ3xudWxsO1xuICAgIG5hbWUob3B0aW9uYWxFbmNvZGluZzogZmxhdGJ1ZmZlcnMuRW5jb2RpbmcpOiBzdHJpbmd8VWludDhBcnJheXxudWxsO1xuICAgIG5hbWUob3B0aW9uYWxFbmNvZGluZz86IGFueSk6IHN0cmluZ3xVaW50OEFycmF5fG51bGwge1xuICAgICAgbGV0IG9mZnNldCA9IHRoaXMuYmIhLl9fb2Zmc2V0KHRoaXMuYmJfcG9zLCA0KTtcbiAgICAgIHJldHVybiBvZmZzZXQgPyB0aGlzLmJiIS5fX3N0cmluZyh0aGlzLmJiX3BvcyArIG9mZnNldCwgb3B0aW9uYWxFbmNvZGluZykgOiBudWxsO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5FbmNvZGluZz0gb3B0aW9uYWxFbmNvZGluZ1xuICAgICAqIEByZXR1cm5zIHN0cmluZ3xVaW50OEFycmF5fG51bGxcbiAgICAgKi9cbiAgICBkb2NTdHJpbmcoKTogc3RyaW5nfG51bGw7XG4gICAgZG9jU3RyaW5nKG9wdGlvbmFsRW5jb2Rpbmc6IGZsYXRidWZmZXJzLkVuY29kaW5nKTogc3RyaW5nfFVpbnQ4QXJyYXl8bnVsbDtcbiAgICBkb2NTdHJpbmcob3B0aW9uYWxFbmNvZGluZz86IGFueSk6IHN0cmluZ3xVaW50OEFycmF5fG51bGwge1xuICAgICAgbGV0IG9mZnNldCA9IHRoaXMuYmIhLl9fb2Zmc2V0KHRoaXMuYmJfcG9zLCA2KTtcbiAgICAgIHJldHVybiBvZmZzZXQgPyB0aGlzLmJiIS5fX3N0cmluZyh0aGlzLmJiX3BvcyArIG9mZnNldCwgb3B0aW9uYWxFbmNvZGluZykgOiBudWxsO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBvbm54cnVudGltZS5leHBlcmltZW50YWwuZmJzLlR5cGVJbmZvPSBvYmpcbiAgICAgKiBAcmV0dXJucyBvbm54cnVudGltZS5leHBlcmltZW50YWwuZmJzLlR5cGVJbmZvfG51bGxcbiAgICAgKi9cbiAgICB0eXBlKG9iaj86IG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnMuVHlwZUluZm8pOiBvbm54cnVudGltZS5leHBlcmltZW50YWwuZmJzLlR5cGVJbmZvfG51bGwge1xuICAgICAgbGV0IG9mZnNldCA9IHRoaXMuYmIhLl9fb2Zmc2V0KHRoaXMuYmJfcG9zLCA4KTtcbiAgICAgIHJldHVybiBvZmZzZXQgPyAob2JqIHx8IG5ldyBvbm54cnVudGltZS5leHBlcmltZW50YWwuZmJzLlR5cGVJbmZvKCkpXG4gICAgICAgICAgICAgICAgICAgICAgICAgIC5fX2luaXQodGhpcy5iYiEuX19pbmRpcmVjdCh0aGlzLmJiX3BvcyArIG9mZnNldCksIHRoaXMuYmIhKSA6XG4gICAgICAgICAgICAgICAgICAgICAgbnVsbDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuQnVpbGRlciBidWlsZGVyXG4gICAgICovXG4gICAgc3RhdGljIHN0YXJ0VmFsdWVJbmZvKGJ1aWxkZXI6IGZsYXRidWZmZXJzLkJ1aWxkZXIpIHtcbiAgICAgIGJ1aWxkZXIuc3RhcnRPYmplY3QoMyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ1aWxkZXIgYnVpbGRlclxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5PZmZzZXQgbmFtZU9mZnNldFxuICAgICAqL1xuICAgIHN0YXRpYyBhZGROYW1lKGJ1aWxkZXI6IGZsYXRidWZmZXJzLkJ1aWxkZXIsIG5hbWVPZmZzZXQ6IGZsYXRidWZmZXJzLk9mZnNldCkge1xuICAgICAgYnVpbGRlci5hZGRGaWVsZE9mZnNldCgwLCBuYW1lT2Zmc2V0LCAwKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuQnVpbGRlciBidWlsZGVyXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLk9mZnNldCBkb2NTdHJpbmdPZmZzZXRcbiAgICAgKi9cbiAgICBzdGF0aWMgYWRkRG9jU3RyaW5nKGJ1aWxkZXI6IGZsYXRidWZmZXJzLkJ1aWxkZXIsIGRvY1N0cmluZ09mZnNldDogZmxhdGJ1ZmZlcnMuT2Zmc2V0KSB7XG4gICAgICBidWlsZGVyLmFkZEZpZWxkT2Zmc2V0KDEsIGRvY1N0cmluZ09mZnNldCwgMCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ1aWxkZXIgYnVpbGRlclxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5PZmZzZXQgdHlwZU9mZnNldFxuICAgICAqL1xuICAgIHN0YXRpYyBhZGRUeXBlKGJ1aWxkZXI6IGZsYXRidWZmZXJzLkJ1aWxkZXIsIHR5cGVPZmZzZXQ6IGZsYXRidWZmZXJzLk9mZnNldCkge1xuICAgICAgYnVpbGRlci5hZGRGaWVsZE9mZnNldCgyLCB0eXBlT2Zmc2V0LCAwKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuQnVpbGRlciBidWlsZGVyXG4gICAgICogQHJldHVybnMgZmxhdGJ1ZmZlcnMuT2Zmc2V0XG4gICAgICovXG4gICAgc3RhdGljIGVuZFZhbHVlSW5mbyhidWlsZGVyOiBmbGF0YnVmZmVycy5CdWlsZGVyKTogZmxhdGJ1ZmZlcnMuT2Zmc2V0IHtcbiAgICAgIGxldCBvZmZzZXQgPSBidWlsZGVyLmVuZE9iamVjdCgpO1xuICAgICAgcmV0dXJuIG9mZnNldDtcbiAgICB9XG5cbiAgICBzdGF0aWMgY3JlYXRlVmFsdWVJbmZvKFxuICAgICAgICBidWlsZGVyOiBmbGF0YnVmZmVycy5CdWlsZGVyLCBuYW1lT2Zmc2V0OiBmbGF0YnVmZmVycy5PZmZzZXQsIGRvY1N0cmluZ09mZnNldDogZmxhdGJ1ZmZlcnMuT2Zmc2V0LFxuICAgICAgICB0eXBlT2Zmc2V0OiBmbGF0YnVmZmVycy5PZmZzZXQpOiBmbGF0YnVmZmVycy5PZmZzZXQge1xuICAgICAgVmFsdWVJbmZvLnN0YXJ0VmFsdWVJbmZvKGJ1aWxkZXIpO1xuICAgICAgVmFsdWVJbmZvLmFkZE5hbWUoYnVpbGRlciwgbmFtZU9mZnNldCk7XG4gICAgICBWYWx1ZUluZm8uYWRkRG9jU3RyaW5nKGJ1aWxkZXIsIGRvY1N0cmluZ09mZnNldCk7XG4gICAgICBWYWx1ZUluZm8uYWRkVHlwZShidWlsZGVyLCB0eXBlT2Zmc2V0KTtcbiAgICAgIHJldHVybiBWYWx1ZUluZm8uZW5kVmFsdWVJbmZvKGJ1aWxkZXIpO1xuICAgIH1cbiAgfVxufVxuLyoqXG4gKiBAY29uc3RydWN0b3JcbiAqL1xuZXhwb3J0IG5hbWVzcGFjZSBvbm54cnVudGltZS5leHBlcmltZW50YWwuZmJzIHtcbiAgZXhwb3J0IGNsYXNzIFR5cGVJbmZvIHtcbiAgICBiYjogZmxhdGJ1ZmZlcnMuQnl0ZUJ1ZmZlcnxudWxsID0gbnVsbDtcblxuICAgIGJiX3BvcyA9IDA7XG4gICAgLyoqXG4gICAgICogQHBhcmFtIG51bWJlciBpXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ5dGVCdWZmZXIgYmJcbiAgICAgKiBAcmV0dXJucyBUeXBlSW5mb1xuICAgICAqL1xuICAgIF9faW5pdChpOiBudW1iZXIsIGJiOiBmbGF0YnVmZmVycy5CeXRlQnVmZmVyKTogVHlwZUluZm8ge1xuICAgICAgdGhpcy5iYl9wb3MgPSBpO1xuICAgICAgdGhpcy5iYiA9IGJiO1xuICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ5dGVCdWZmZXIgYmJcbiAgICAgKiBAcGFyYW0gVHlwZUluZm89IG9ialxuICAgICAqIEByZXR1cm5zIFR5cGVJbmZvXG4gICAgICovXG4gICAgc3RhdGljIGdldFJvb3RBc1R5cGVJbmZvKGJiOiBmbGF0YnVmZmVycy5CeXRlQnVmZmVyLCBvYmo/OiBUeXBlSW5mbyk6IFR5cGVJbmZvIHtcbiAgICAgIHJldHVybiAob2JqIHx8IG5ldyBUeXBlSW5mbygpKS5fX2luaXQoYmIucmVhZEludDMyKGJiLnBvc2l0aW9uKCkpICsgYmIucG9zaXRpb24oKSwgYmIpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CeXRlQnVmZmVyIGJiXG4gICAgICogQHBhcmFtIFR5cGVJbmZvPSBvYmpcbiAgICAgKiBAcmV0dXJucyBUeXBlSW5mb1xuICAgICAqL1xuICAgIHN0YXRpYyBnZXRTaXplUHJlZml4ZWRSb290QXNUeXBlSW5mbyhiYjogZmxhdGJ1ZmZlcnMuQnl0ZUJ1ZmZlciwgb2JqPzogVHlwZUluZm8pOiBUeXBlSW5mbyB7XG4gICAgICBiYi5zZXRQb3NpdGlvbihiYi5wb3NpdGlvbigpICsgZmxhdGJ1ZmZlcnMuU0laRV9QUkVGSVhfTEVOR1RIKTtcbiAgICAgIHJldHVybiAob2JqIHx8IG5ldyBUeXBlSW5mbygpKS5fX2luaXQoYmIucmVhZEludDMyKGJiLnBvc2l0aW9uKCkpICsgYmIucG9zaXRpb24oKSwgYmIpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5FbmNvZGluZz0gb3B0aW9uYWxFbmNvZGluZ1xuICAgICAqIEByZXR1cm5zIHN0cmluZ3xVaW50OEFycmF5fG51bGxcbiAgICAgKi9cbiAgICBkZW5vdGF0aW9uKCk6IHN0cmluZ3xudWxsO1xuICAgIGRlbm90YXRpb24ob3B0aW9uYWxFbmNvZGluZzogZmxhdGJ1ZmZlcnMuRW5jb2RpbmcpOiBzdHJpbmd8VWludDhBcnJheXxudWxsO1xuICAgIGRlbm90YXRpb24ob3B0aW9uYWxFbmNvZGluZz86IGFueSk6IHN0cmluZ3xVaW50OEFycmF5fG51bGwge1xuICAgICAgbGV0IG9mZnNldCA9IHRoaXMuYmIhLl9fb2Zmc2V0KHRoaXMuYmJfcG9zLCA0KTtcbiAgICAgIHJldHVybiBvZmZzZXQgPyB0aGlzLmJiIS5fX3N0cmluZyh0aGlzLmJiX3BvcyArIG9mZnNldCwgb3B0aW9uYWxFbmNvZGluZykgOiBudWxsO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEByZXR1cm5zIG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnMuVHlwZUluZm9WYWx1ZVxuICAgICAqL1xuICAgIHZhbHVlVHlwZSgpOiBvbm54cnVudGltZS5leHBlcmltZW50YWwuZmJzLlR5cGVJbmZvVmFsdWUge1xuICAgICAgbGV0IG9mZnNldCA9IHRoaXMuYmIhLl9fb2Zmc2V0KHRoaXMuYmJfcG9zLCA2KTtcbiAgICAgIHJldHVybiBvZmZzZXQgPyAvKiogICovICh0aGlzLmJiIS5yZWFkVWludDgodGhpcy5iYl9wb3MgKyBvZmZzZXQpKSA6XG4gICAgICAgICAgICAgICAgICAgICAgb25ueHJ1bnRpbWUuZXhwZXJpbWVudGFsLmZicy5UeXBlSW5mb1ZhbHVlLk5PTkU7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLlRhYmxlIG9ialxuICAgICAqIEByZXR1cm5zID9mbGF0YnVmZmVycy5UYWJsZVxuICAgICAqL1xuICAgIHZhbHVlPFQgZXh0ZW5kcyBmbGF0YnVmZmVycy5UYWJsZT4ob2JqOiBUKTogVHxudWxsIHtcbiAgICAgIGxldCBvZmZzZXQgPSB0aGlzLmJiIS5fX29mZnNldCh0aGlzLmJiX3BvcywgOCk7XG4gICAgICByZXR1cm4gb2Zmc2V0ID8gdGhpcy5iYiEuX191bmlvbihvYmosIHRoaXMuYmJfcG9zICsgb2Zmc2V0KSA6IG51bGw7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ1aWxkZXIgYnVpbGRlclxuICAgICAqL1xuICAgIHN0YXRpYyBzdGFydFR5cGVJbmZvKGJ1aWxkZXI6IGZsYXRidWZmZXJzLkJ1aWxkZXIpIHtcbiAgICAgIGJ1aWxkZXIuc3RhcnRPYmplY3QoMyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ1aWxkZXIgYnVpbGRlclxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5PZmZzZXQgZGVub3RhdGlvbk9mZnNldFxuICAgICAqL1xuICAgIHN0YXRpYyBhZGREZW5vdGF0aW9uKGJ1aWxkZXI6IGZsYXRidWZmZXJzLkJ1aWxkZXIsIGRlbm90YXRpb25PZmZzZXQ6IGZsYXRidWZmZXJzLk9mZnNldCkge1xuICAgICAgYnVpbGRlci5hZGRGaWVsZE9mZnNldCgwLCBkZW5vdGF0aW9uT2Zmc2V0LCAwKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuQnVpbGRlciBidWlsZGVyXG4gICAgICogQHBhcmFtIG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnMuVHlwZUluZm9WYWx1ZSB2YWx1ZVR5cGVcbiAgICAgKi9cbiAgICBzdGF0aWMgYWRkVmFsdWVUeXBlKGJ1aWxkZXI6IGZsYXRidWZmZXJzLkJ1aWxkZXIsIHZhbHVlVHlwZTogb25ueHJ1bnRpbWUuZXhwZXJpbWVudGFsLmZicy5UeXBlSW5mb1ZhbHVlKSB7XG4gICAgICBidWlsZGVyLmFkZEZpZWxkSW50OCgxLCB2YWx1ZVR5cGUsIG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnMuVHlwZUluZm9WYWx1ZS5OT05FKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuQnVpbGRlciBidWlsZGVyXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLk9mZnNldCB2YWx1ZU9mZnNldFxuICAgICAqL1xuICAgIHN0YXRpYyBhZGRWYWx1ZShidWlsZGVyOiBmbGF0YnVmZmVycy5CdWlsZGVyLCB2YWx1ZU9mZnNldDogZmxhdGJ1ZmZlcnMuT2Zmc2V0KSB7XG4gICAgICBidWlsZGVyLmFkZEZpZWxkT2Zmc2V0KDIsIHZhbHVlT2Zmc2V0LCAwKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuQnVpbGRlciBidWlsZGVyXG4gICAgICogQHJldHVybnMgZmxhdGJ1ZmZlcnMuT2Zmc2V0XG4gICAgICovXG4gICAgc3RhdGljIGVuZFR5cGVJbmZvKGJ1aWxkZXI6IGZsYXRidWZmZXJzLkJ1aWxkZXIpOiBmbGF0YnVmZmVycy5PZmZzZXQge1xuICAgICAgbGV0IG9mZnNldCA9IGJ1aWxkZXIuZW5kT2JqZWN0KCk7XG4gICAgICByZXR1cm4gb2Zmc2V0O1xuICAgIH1cblxuICAgIHN0YXRpYyBjcmVhdGVUeXBlSW5mbyhcbiAgICAgICAgYnVpbGRlcjogZmxhdGJ1ZmZlcnMuQnVpbGRlciwgZGVub3RhdGlvbk9mZnNldDogZmxhdGJ1ZmZlcnMuT2Zmc2V0LFxuICAgICAgICB2YWx1ZVR5cGU6IG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnMuVHlwZUluZm9WYWx1ZSwgdmFsdWVPZmZzZXQ6IGZsYXRidWZmZXJzLk9mZnNldCk6IGZsYXRidWZmZXJzLk9mZnNldCB7XG4gICAgICBUeXBlSW5mby5zdGFydFR5cGVJbmZvKGJ1aWxkZXIpO1xuICAgICAgVHlwZUluZm8uYWRkRGVub3RhdGlvbihidWlsZGVyLCBkZW5vdGF0aW9uT2Zmc2V0KTtcbiAgICAgIFR5cGVJbmZvLmFkZFZhbHVlVHlwZShidWlsZGVyLCB2YWx1ZVR5cGUpO1xuICAgICAgVHlwZUluZm8uYWRkVmFsdWUoYnVpbGRlciwgdmFsdWVPZmZzZXQpO1xuICAgICAgcmV0dXJuIFR5cGVJbmZvLmVuZFR5cGVJbmZvKGJ1aWxkZXIpO1xuICAgIH1cbiAgfVxufVxuLyoqXG4gKiBAY29uc3RydWN0b3JcbiAqL1xuZXhwb3J0IG5hbWVzcGFjZSBvbm54cnVudGltZS5leHBlcmltZW50YWwuZmJzIHtcbiAgZXhwb3J0IGNsYXNzIE9wZXJhdG9yU2V0SWQge1xuICAgIGJiOiBmbGF0YnVmZmVycy5CeXRlQnVmZmVyfG51bGwgPSBudWxsO1xuXG4gICAgYmJfcG9zID0gMDtcbiAgICAvKipcbiAgICAgKiBAcGFyYW0gbnVtYmVyIGlcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuQnl0ZUJ1ZmZlciBiYlxuICAgICAqIEByZXR1cm5zIE9wZXJhdG9yU2V0SWRcbiAgICAgKi9cbiAgICBfX2luaXQoaTogbnVtYmVyLCBiYjogZmxhdGJ1ZmZlcnMuQnl0ZUJ1ZmZlcik6IE9wZXJhdG9yU2V0SWQge1xuICAgICAgdGhpcy5iYl9wb3MgPSBpO1xuICAgICAgdGhpcy5iYiA9IGJiO1xuICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ5dGVCdWZmZXIgYmJcbiAgICAgKiBAcGFyYW0gT3BlcmF0b3JTZXRJZD0gb2JqXG4gICAgICogQHJldHVybnMgT3BlcmF0b3JTZXRJZFxuICAgICAqL1xuICAgIHN0YXRpYyBnZXRSb290QXNPcGVyYXRvclNldElkKGJiOiBmbGF0YnVmZmVycy5CeXRlQnVmZmVyLCBvYmo/OiBPcGVyYXRvclNldElkKTogT3BlcmF0b3JTZXRJZCB7XG4gICAgICByZXR1cm4gKG9iaiB8fCBuZXcgT3BlcmF0b3JTZXRJZCgpKS5fX2luaXQoYmIucmVhZEludDMyKGJiLnBvc2l0aW9uKCkpICsgYmIucG9zaXRpb24oKSwgYmIpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CeXRlQnVmZmVyIGJiXG4gICAgICogQHBhcmFtIE9wZXJhdG9yU2V0SWQ9IG9ialxuICAgICAqIEByZXR1cm5zIE9wZXJhdG9yU2V0SWRcbiAgICAgKi9cbiAgICBzdGF0aWMgZ2V0U2l6ZVByZWZpeGVkUm9vdEFzT3BlcmF0b3JTZXRJZChiYjogZmxhdGJ1ZmZlcnMuQnl0ZUJ1ZmZlciwgb2JqPzogT3BlcmF0b3JTZXRJZCk6IE9wZXJhdG9yU2V0SWQge1xuICAgICAgYmIuc2V0UG9zaXRpb24oYmIucG9zaXRpb24oKSArIGZsYXRidWZmZXJzLlNJWkVfUFJFRklYX0xFTkdUSCk7XG4gICAgICByZXR1cm4gKG9iaiB8fCBuZXcgT3BlcmF0b3JTZXRJZCgpKS5fX2luaXQoYmIucmVhZEludDMyKGJiLnBvc2l0aW9uKCkpICsgYmIucG9zaXRpb24oKSwgYmIpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5FbmNvZGluZz0gb3B0aW9uYWxFbmNvZGluZ1xuICAgICAqIEByZXR1cm5zIHN0cmluZ3xVaW50OEFycmF5fG51bGxcbiAgICAgKi9cbiAgICBkb21haW4oKTogc3RyaW5nfG51bGw7XG4gICAgZG9tYWluKG9wdGlvbmFsRW5jb2Rpbmc6IGZsYXRidWZmZXJzLkVuY29kaW5nKTogc3RyaW5nfFVpbnQ4QXJyYXl8bnVsbDtcbiAgICBkb21haW4ob3B0aW9uYWxFbmNvZGluZz86IGFueSk6IHN0cmluZ3xVaW50OEFycmF5fG51bGwge1xuICAgICAgbGV0IG9mZnNldCA9IHRoaXMuYmIhLl9fb2Zmc2V0KHRoaXMuYmJfcG9zLCA0KTtcbiAgICAgIHJldHVybiBvZmZzZXQgPyB0aGlzLmJiIS5fX3N0cmluZyh0aGlzLmJiX3BvcyArIG9mZnNldCwgb3B0aW9uYWxFbmNvZGluZykgOiBudWxsO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEByZXR1cm5zIGZsYXRidWZmZXJzLkxvbmdcbiAgICAgKi9cbiAgICB2ZXJzaW9uKCk6IGZsYXRidWZmZXJzLkxvbmcge1xuICAgICAgbGV0IG9mZnNldCA9IHRoaXMuYmIhLl9fb2Zmc2V0KHRoaXMuYmJfcG9zLCA2KTtcbiAgICAgIHJldHVybiBvZmZzZXQgPyB0aGlzLmJiIS5yZWFkSW50NjQodGhpcy5iYl9wb3MgKyBvZmZzZXQpIDogdGhpcy5iYiEuY3JlYXRlTG9uZygwLCAwKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuQnVpbGRlciBidWlsZGVyXG4gICAgICovXG4gICAgc3RhdGljIHN0YXJ0T3BlcmF0b3JTZXRJZChidWlsZGVyOiBmbGF0YnVmZmVycy5CdWlsZGVyKSB7XG4gICAgICBidWlsZGVyLnN0YXJ0T2JqZWN0KDIpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CdWlsZGVyIGJ1aWxkZXJcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuT2Zmc2V0IGRvbWFpbk9mZnNldFxuICAgICAqL1xuICAgIHN0YXRpYyBhZGREb21haW4oYnVpbGRlcjogZmxhdGJ1ZmZlcnMuQnVpbGRlciwgZG9tYWluT2Zmc2V0OiBmbGF0YnVmZmVycy5PZmZzZXQpIHtcbiAgICAgIGJ1aWxkZXIuYWRkRmllbGRPZmZzZXQoMCwgZG9tYWluT2Zmc2V0LCAwKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuQnVpbGRlciBidWlsZGVyXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkxvbmcgdmVyc2lvblxuICAgICAqL1xuICAgIHN0YXRpYyBhZGRWZXJzaW9uKGJ1aWxkZXI6IGZsYXRidWZmZXJzLkJ1aWxkZXIsIHZlcnNpb246IGZsYXRidWZmZXJzLkxvbmcpIHtcbiAgICAgIGJ1aWxkZXIuYWRkRmllbGRJbnQ2NCgxLCB2ZXJzaW9uLCBidWlsZGVyLmNyZWF0ZUxvbmcoMCwgMCkpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CdWlsZGVyIGJ1aWxkZXJcbiAgICAgKiBAcmV0dXJucyBmbGF0YnVmZmVycy5PZmZzZXRcbiAgICAgKi9cbiAgICBzdGF0aWMgZW5kT3BlcmF0b3JTZXRJZChidWlsZGVyOiBmbGF0YnVmZmVycy5CdWlsZGVyKTogZmxhdGJ1ZmZlcnMuT2Zmc2V0IHtcbiAgICAgIGxldCBvZmZzZXQgPSBidWlsZGVyLmVuZE9iamVjdCgpO1xuICAgICAgcmV0dXJuIG9mZnNldDtcbiAgICB9XG5cbiAgICBzdGF0aWMgY3JlYXRlT3BlcmF0b3JTZXRJZChcbiAgICAgICAgYnVpbGRlcjogZmxhdGJ1ZmZlcnMuQnVpbGRlciwgZG9tYWluT2Zmc2V0OiBmbGF0YnVmZmVycy5PZmZzZXQsIHZlcnNpb246IGZsYXRidWZmZXJzLkxvbmcpOiBmbGF0YnVmZmVycy5PZmZzZXQge1xuICAgICAgT3BlcmF0b3JTZXRJZC5zdGFydE9wZXJhdG9yU2V0SWQoYnVpbGRlcik7XG4gICAgICBPcGVyYXRvclNldElkLmFkZERvbWFpbihidWlsZGVyLCBkb21haW5PZmZzZXQpO1xuICAgICAgT3BlcmF0b3JTZXRJZC5hZGRWZXJzaW9uKGJ1aWxkZXIsIHZlcnNpb24pO1xuICAgICAgcmV0dXJuIE9wZXJhdG9yU2V0SWQuZW5kT3BlcmF0b3JTZXRJZChidWlsZGVyKTtcbiAgICB9XG4gIH1cbn1cbi8qKlxuICogQGNvbnN0cnVjdG9yXG4gKi9cbmV4cG9ydCBuYW1lc3BhY2Ugb25ueHJ1bnRpbWUuZXhwZXJpbWVudGFsLmZicyB7XG4gIGV4cG9ydCBjbGFzcyBUZW5zb3Ige1xuICAgIGJiOiBmbGF0YnVmZmVycy5CeXRlQnVmZmVyfG51bGwgPSBudWxsO1xuXG4gICAgYmJfcG9zID0gMDtcbiAgICAvKipcbiAgICAgKiBAcGFyYW0gbnVtYmVyIGlcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuQnl0ZUJ1ZmZlciBiYlxuICAgICAqIEByZXR1cm5zIFRlbnNvclxuICAgICAqL1xuICAgIF9faW5pdChpOiBudW1iZXIsIGJiOiBmbGF0YnVmZmVycy5CeXRlQnVmZmVyKTogVGVuc29yIHtcbiAgICAgIHRoaXMuYmJfcG9zID0gaTtcbiAgICAgIHRoaXMuYmIgPSBiYjtcbiAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CeXRlQnVmZmVyIGJiXG4gICAgICogQHBhcmFtIFRlbnNvcj0gb2JqXG4gICAgICogQHJldHVybnMgVGVuc29yXG4gICAgICovXG4gICAgc3RhdGljIGdldFJvb3RBc1RlbnNvcihiYjogZmxhdGJ1ZmZlcnMuQnl0ZUJ1ZmZlciwgb2JqPzogVGVuc29yKTogVGVuc29yIHtcbiAgICAgIHJldHVybiAob2JqIHx8IG5ldyBUZW5zb3IoKSkuX19pbml0KGJiLnJlYWRJbnQzMihiYi5wb3NpdGlvbigpKSArIGJiLnBvc2l0aW9uKCksIGJiKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuQnl0ZUJ1ZmZlciBiYlxuICAgICAqIEBwYXJhbSBUZW5zb3I9IG9ialxuICAgICAqIEByZXR1cm5zIFRlbnNvclxuICAgICAqL1xuICAgIHN0YXRpYyBnZXRTaXplUHJlZml4ZWRSb290QXNUZW5zb3IoYmI6IGZsYXRidWZmZXJzLkJ5dGVCdWZmZXIsIG9iaj86IFRlbnNvcik6IFRlbnNvciB7XG4gICAgICBiYi5zZXRQb3NpdGlvbihiYi5wb3NpdGlvbigpICsgZmxhdGJ1ZmZlcnMuU0laRV9QUkVGSVhfTEVOR1RIKTtcbiAgICAgIHJldHVybiAob2JqIHx8IG5ldyBUZW5zb3IoKSkuX19pbml0KGJiLnJlYWRJbnQzMihiYi5wb3NpdGlvbigpKSArIGJiLnBvc2l0aW9uKCksIGJiKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuRW5jb2Rpbmc9IG9wdGlvbmFsRW5jb2RpbmdcbiAgICAgKiBAcmV0dXJucyBzdHJpbmd8VWludDhBcnJheXxudWxsXG4gICAgICovXG4gICAgbmFtZSgpOiBzdHJpbmd8bnVsbDtcbiAgICBuYW1lKG9wdGlvbmFsRW5jb2Rpbmc6IGZsYXRidWZmZXJzLkVuY29kaW5nKTogc3RyaW5nfFVpbnQ4QXJyYXl8bnVsbDtcbiAgICBuYW1lKG9wdGlvbmFsRW5jb2Rpbmc/OiBhbnkpOiBzdHJpbmd8VWludDhBcnJheXxudWxsIHtcbiAgICAgIGxldCBvZmZzZXQgPSB0aGlzLmJiIS5fX29mZnNldCh0aGlzLmJiX3BvcywgNCk7XG4gICAgICByZXR1cm4gb2Zmc2V0ID8gdGhpcy5iYiEuX19zdHJpbmcodGhpcy5iYl9wb3MgKyBvZmZzZXQsIG9wdGlvbmFsRW5jb2RpbmcpIDogbnVsbDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuRW5jb2Rpbmc9IG9wdGlvbmFsRW5jb2RpbmdcbiAgICAgKiBAcmV0dXJucyBzdHJpbmd8VWludDhBcnJheXxudWxsXG4gICAgICovXG4gICAgZG9jU3RyaW5nKCk6IHN0cmluZ3xudWxsO1xuICAgIGRvY1N0cmluZyhvcHRpb25hbEVuY29kaW5nOiBmbGF0YnVmZmVycy5FbmNvZGluZyk6IHN0cmluZ3xVaW50OEFycmF5fG51bGw7XG4gICAgZG9jU3RyaW5nKG9wdGlvbmFsRW5jb2Rpbmc/OiBhbnkpOiBzdHJpbmd8VWludDhBcnJheXxudWxsIHtcbiAgICAgIGxldCBvZmZzZXQgPSB0aGlzLmJiIS5fX29mZnNldCh0aGlzLmJiX3BvcywgNik7XG4gICAgICByZXR1cm4gb2Zmc2V0ID8gdGhpcy5iYiEuX19zdHJpbmcodGhpcy5iYl9wb3MgKyBvZmZzZXQsIG9wdGlvbmFsRW5jb2RpbmcpIDogbnVsbDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gbnVtYmVyIGluZGV4XG4gICAgICogQHJldHVybnMgZmxhdGJ1ZmZlcnMuTG9uZ1xuICAgICAqL1xuICAgIGRpbXMoaW5kZXg6IG51bWJlcik6IGZsYXRidWZmZXJzLkxvbmd8bnVsbCB7XG4gICAgICBsZXQgb2Zmc2V0ID0gdGhpcy5iYiEuX19vZmZzZXQodGhpcy5iYl9wb3MsIDgpO1xuICAgICAgcmV0dXJuIG9mZnNldCA/IHRoaXMuYmIhLnJlYWRJbnQ2NCh0aGlzLmJiIS5fX3ZlY3Rvcih0aGlzLmJiX3BvcyArIG9mZnNldCkgKyBpbmRleCAqIDgpIDpcbiAgICAgICAgICAgICAgICAgICAgICB0aGlzLmJiIS5jcmVhdGVMb25nKDAsIDApO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEByZXR1cm5zIG51bWJlclxuICAgICAqL1xuICAgIGRpbXNMZW5ndGgoKTogbnVtYmVyIHtcbiAgICAgIGxldCBvZmZzZXQgPSB0aGlzLmJiIS5fX29mZnNldCh0aGlzLmJiX3BvcywgOCk7XG4gICAgICByZXR1cm4gb2Zmc2V0ID8gdGhpcy5iYiEuX192ZWN0b3JfbGVuKHRoaXMuYmJfcG9zICsgb2Zmc2V0KSA6IDA7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHJldHVybnMgb25ueHJ1bnRpbWUuZXhwZXJpbWVudGFsLmZicy5UZW5zb3JEYXRhVHlwZVxuICAgICAqL1xuICAgIGRhdGFUeXBlKCk6IG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnMuVGVuc29yRGF0YVR5cGUge1xuICAgICAgbGV0IG9mZnNldCA9IHRoaXMuYmIhLl9fb2Zmc2V0KHRoaXMuYmJfcG9zLCAxMCk7XG4gICAgICByZXR1cm4gb2Zmc2V0ID8gLyoqICAqLyAodGhpcy5iYiEucmVhZEludDMyKHRoaXMuYmJfcG9zICsgb2Zmc2V0KSkgOlxuICAgICAgICAgICAgICAgICAgICAgIG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnMuVGVuc29yRGF0YVR5cGUuVU5ERUZJTkVEO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBudW1iZXIgaW5kZXhcbiAgICAgKiBAcmV0dXJucyBudW1iZXJcbiAgICAgKi9cbiAgICByYXdEYXRhKGluZGV4OiBudW1iZXIpOiBudW1iZXJ8bnVsbCB7XG4gICAgICBsZXQgb2Zmc2V0ID0gdGhpcy5iYiEuX19vZmZzZXQodGhpcy5iYl9wb3MsIDEyKTtcbiAgICAgIHJldHVybiBvZmZzZXQgPyB0aGlzLmJiIS5yZWFkVWludDgodGhpcy5iYiEuX192ZWN0b3IodGhpcy5iYl9wb3MgKyBvZmZzZXQpICsgaW5kZXgpIDogMDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcmV0dXJucyBudW1iZXJcbiAgICAgKi9cbiAgICByYXdEYXRhTGVuZ3RoKCk6IG51bWJlciB7XG4gICAgICBsZXQgb2Zmc2V0ID0gdGhpcy5iYiEuX19vZmZzZXQodGhpcy5iYl9wb3MsIDEyKTtcbiAgICAgIHJldHVybiBvZmZzZXQgPyB0aGlzLmJiIS5fX3ZlY3Rvcl9sZW4odGhpcy5iYl9wb3MgKyBvZmZzZXQpIDogMDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcmV0dXJucyBVaW50OEFycmF5XG4gICAgICovXG4gICAgcmF3RGF0YUFycmF5KCk6IFVpbnQ4QXJyYXl8bnVsbCB7XG4gICAgICBsZXQgb2Zmc2V0ID0gdGhpcy5iYiEuX19vZmZzZXQodGhpcy5iYl9wb3MsIDEyKTtcbiAgICAgIHJldHVybiBvZmZzZXQgP1xuICAgICAgICAgIG5ldyBVaW50OEFycmF5KFxuICAgICAgICAgICAgICB0aGlzLmJiIS5ieXRlcygpLmJ1ZmZlciwgdGhpcy5iYiEuYnl0ZXMoKS5ieXRlT2Zmc2V0ICsgdGhpcy5iYiEuX192ZWN0b3IodGhpcy5iYl9wb3MgKyBvZmZzZXQpLFxuICAgICAgICAgICAgICB0aGlzLmJiIS5fX3ZlY3Rvcl9sZW4odGhpcy5iYl9wb3MgKyBvZmZzZXQpKSA6XG4gICAgICAgICAgbnVsbDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gbnVtYmVyIGluZGV4XG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkVuY29kaW5nPSBvcHRpb25hbEVuY29kaW5nXG4gICAgICogQHJldHVybnMgc3RyaW5nfFVpbnQ4QXJyYXlcbiAgICAgKi9cbiAgICBzdHJpbmdEYXRhKGluZGV4OiBudW1iZXIpOiBzdHJpbmc7XG4gICAgc3RyaW5nRGF0YShpbmRleDogbnVtYmVyLCBvcHRpb25hbEVuY29kaW5nOiBmbGF0YnVmZmVycy5FbmNvZGluZyk6IHN0cmluZ3xVaW50OEFycmF5O1xuICAgIHN0cmluZ0RhdGEoaW5kZXg6IG51bWJlciwgb3B0aW9uYWxFbmNvZGluZz86IGFueSk6IHN0cmluZ3xVaW50OEFycmF5fG51bGwge1xuICAgICAgbGV0IG9mZnNldCA9IHRoaXMuYmIhLl9fb2Zmc2V0KHRoaXMuYmJfcG9zLCAxNCk7XG4gICAgICByZXR1cm4gb2Zmc2V0ID8gdGhpcy5iYiEuX19zdHJpbmcodGhpcy5iYiEuX192ZWN0b3IodGhpcy5iYl9wb3MgKyBvZmZzZXQpICsgaW5kZXggKiA0LCBvcHRpb25hbEVuY29kaW5nKSA6IG51bGw7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHJldHVybnMgbnVtYmVyXG4gICAgICovXG4gICAgc3RyaW5nRGF0YUxlbmd0aCgpOiBudW1iZXIge1xuICAgICAgbGV0IG9mZnNldCA9IHRoaXMuYmIhLl9fb2Zmc2V0KHRoaXMuYmJfcG9zLCAxNCk7XG4gICAgICByZXR1cm4gb2Zmc2V0ID8gdGhpcy5iYiEuX192ZWN0b3JfbGVuKHRoaXMuYmJfcG9zICsgb2Zmc2V0KSA6IDA7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ1aWxkZXIgYnVpbGRlclxuICAgICAqL1xuICAgIHN0YXRpYyBzdGFydFRlbnNvcihidWlsZGVyOiBmbGF0YnVmZmVycy5CdWlsZGVyKSB7XG4gICAgICBidWlsZGVyLnN0YXJ0T2JqZWN0KDYpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CdWlsZGVyIGJ1aWxkZXJcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuT2Zmc2V0IG5hbWVPZmZzZXRcbiAgICAgKi9cbiAgICBzdGF0aWMgYWRkTmFtZShidWlsZGVyOiBmbGF0YnVmZmVycy5CdWlsZGVyLCBuYW1lT2Zmc2V0OiBmbGF0YnVmZmVycy5PZmZzZXQpIHtcbiAgICAgIGJ1aWxkZXIuYWRkRmllbGRPZmZzZXQoMCwgbmFtZU9mZnNldCwgMCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ1aWxkZXIgYnVpbGRlclxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5PZmZzZXQgZG9jU3RyaW5nT2Zmc2V0XG4gICAgICovXG4gICAgc3RhdGljIGFkZERvY1N0cmluZyhidWlsZGVyOiBmbGF0YnVmZmVycy5CdWlsZGVyLCBkb2NTdHJpbmdPZmZzZXQ6IGZsYXRidWZmZXJzLk9mZnNldCkge1xuICAgICAgYnVpbGRlci5hZGRGaWVsZE9mZnNldCgxLCBkb2NTdHJpbmdPZmZzZXQsIDApO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CdWlsZGVyIGJ1aWxkZXJcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuT2Zmc2V0IGRpbXNPZmZzZXRcbiAgICAgKi9cbiAgICBzdGF0aWMgYWRkRGltcyhidWlsZGVyOiBmbGF0YnVmZmVycy5CdWlsZGVyLCBkaW1zT2Zmc2V0OiBmbGF0YnVmZmVycy5PZmZzZXQpIHtcbiAgICAgIGJ1aWxkZXIuYWRkRmllbGRPZmZzZXQoMiwgZGltc09mZnNldCwgMCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ1aWxkZXIgYnVpbGRlclxuICAgICAqIEBwYXJhbSBBcnJheS48ZmxhdGJ1ZmZlcnMuTG9uZz4gZGF0YVxuICAgICAqIEByZXR1cm5zIGZsYXRidWZmZXJzLk9mZnNldFxuICAgICAqL1xuICAgIHN0YXRpYyBjcmVhdGVEaW1zVmVjdG9yKGJ1aWxkZXI6IGZsYXRidWZmZXJzLkJ1aWxkZXIsIGRhdGE6IGZsYXRidWZmZXJzLkxvbmdbXSk6IGZsYXRidWZmZXJzLk9mZnNldCB7XG4gICAgICBidWlsZGVyLnN0YXJ0VmVjdG9yKDgsIGRhdGEubGVuZ3RoLCA4KTtcbiAgICAgIGZvciAobGV0IGkgPSBkYXRhLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSB7XG4gICAgICAgIGJ1aWxkZXIuYWRkSW50NjQoZGF0YVtpXSk7XG4gICAgICB9XG4gICAgICByZXR1cm4gYnVpbGRlci5lbmRWZWN0b3IoKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuQnVpbGRlciBidWlsZGVyXG4gICAgICogQHBhcmFtIG51bWJlciBudW1FbGVtc1xuICAgICAqL1xuICAgIHN0YXRpYyBzdGFydERpbXNWZWN0b3IoYnVpbGRlcjogZmxhdGJ1ZmZlcnMuQnVpbGRlciwgbnVtRWxlbXM6IG51bWJlcikge1xuICAgICAgYnVpbGRlci5zdGFydFZlY3Rvcig4LCBudW1FbGVtcywgOCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ1aWxkZXIgYnVpbGRlclxuICAgICAqIEBwYXJhbSBvbm54cnVudGltZS5leHBlcmltZW50YWwuZmJzLlRlbnNvckRhdGFUeXBlIGRhdGFUeXBlXG4gICAgICovXG4gICAgc3RhdGljIGFkZERhdGFUeXBlKGJ1aWxkZXI6IGZsYXRidWZmZXJzLkJ1aWxkZXIsIGRhdGFUeXBlOiBvbm54cnVudGltZS5leHBlcmltZW50YWwuZmJzLlRlbnNvckRhdGFUeXBlKSB7XG4gICAgICBidWlsZGVyLmFkZEZpZWxkSW50MzIoMywgZGF0YVR5cGUsIG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnMuVGVuc29yRGF0YVR5cGUuVU5ERUZJTkVEKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuQnVpbGRlciBidWlsZGVyXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLk9mZnNldCByYXdEYXRhT2Zmc2V0XG4gICAgICovXG4gICAgc3RhdGljIGFkZFJhd0RhdGEoYnVpbGRlcjogZmxhdGJ1ZmZlcnMuQnVpbGRlciwgcmF3RGF0YU9mZnNldDogZmxhdGJ1ZmZlcnMuT2Zmc2V0KSB7XG4gICAgICBidWlsZGVyLmFkZEZpZWxkT2Zmc2V0KDQsIHJhd0RhdGFPZmZzZXQsIDApO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CdWlsZGVyIGJ1aWxkZXJcbiAgICAgKiBAcGFyYW0gQXJyYXkuPG51bWJlcj4gZGF0YVxuICAgICAqIEByZXR1cm5zIGZsYXRidWZmZXJzLk9mZnNldFxuICAgICAqL1xuICAgIHN0YXRpYyBjcmVhdGVSYXdEYXRhVmVjdG9yKGJ1aWxkZXI6IGZsYXRidWZmZXJzLkJ1aWxkZXIsIGRhdGE6IG51bWJlcltdfFVpbnQ4QXJyYXkpOiBmbGF0YnVmZmVycy5PZmZzZXQge1xuICAgICAgYnVpbGRlci5zdGFydFZlY3RvcigxLCBkYXRhLmxlbmd0aCwgMSk7XG4gICAgICBmb3IgKGxldCBpID0gZGF0YS5sZW5ndGggLSAxOyBpID49IDA7IGktLSkge1xuICAgICAgICBidWlsZGVyLmFkZEludDgoZGF0YVtpXSk7XG4gICAgICB9XG4gICAgICByZXR1cm4gYnVpbGRlci5lbmRWZWN0b3IoKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuQnVpbGRlciBidWlsZGVyXG4gICAgICogQHBhcmFtIG51bWJlciBudW1FbGVtc1xuICAgICAqL1xuICAgIHN0YXRpYyBzdGFydFJhd0RhdGFWZWN0b3IoYnVpbGRlcjogZmxhdGJ1ZmZlcnMuQnVpbGRlciwgbnVtRWxlbXM6IG51bWJlcikge1xuICAgICAgYnVpbGRlci5zdGFydFZlY3RvcigxLCBudW1FbGVtcywgMSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ1aWxkZXIgYnVpbGRlclxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5PZmZzZXQgc3RyaW5nRGF0YU9mZnNldFxuICAgICAqL1xuICAgIHN0YXRpYyBhZGRTdHJpbmdEYXRhKGJ1aWxkZXI6IGZsYXRidWZmZXJzLkJ1aWxkZXIsIHN0cmluZ0RhdGFPZmZzZXQ6IGZsYXRidWZmZXJzLk9mZnNldCkge1xuICAgICAgYnVpbGRlci5hZGRGaWVsZE9mZnNldCg1LCBzdHJpbmdEYXRhT2Zmc2V0LCAwKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuQnVpbGRlciBidWlsZGVyXG4gICAgICogQHBhcmFtIEFycmF5LjxmbGF0YnVmZmVycy5PZmZzZXQ+IGRhdGFcbiAgICAgKiBAcmV0dXJucyBmbGF0YnVmZmVycy5PZmZzZXRcbiAgICAgKi9cbiAgICBzdGF0aWMgY3JlYXRlU3RyaW5nRGF0YVZlY3RvcihidWlsZGVyOiBmbGF0YnVmZmVycy5CdWlsZGVyLCBkYXRhOiBmbGF0YnVmZmVycy5PZmZzZXRbXSk6IGZsYXRidWZmZXJzLk9mZnNldCB7XG4gICAgICBidWlsZGVyLnN0YXJ0VmVjdG9yKDQsIGRhdGEubGVuZ3RoLCA0KTtcbiAgICAgIGZvciAobGV0IGkgPSBkYXRhLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSB7XG4gICAgICAgIGJ1aWxkZXIuYWRkT2Zmc2V0KGRhdGFbaV0pO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGJ1aWxkZXIuZW5kVmVjdG9yKCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ1aWxkZXIgYnVpbGRlclxuICAgICAqIEBwYXJhbSBudW1iZXIgbnVtRWxlbXNcbiAgICAgKi9cbiAgICBzdGF0aWMgc3RhcnRTdHJpbmdEYXRhVmVjdG9yKGJ1aWxkZXI6IGZsYXRidWZmZXJzLkJ1aWxkZXIsIG51bUVsZW1zOiBudW1iZXIpIHtcbiAgICAgIGJ1aWxkZXIuc3RhcnRWZWN0b3IoNCwgbnVtRWxlbXMsIDQpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CdWlsZGVyIGJ1aWxkZXJcbiAgICAgKiBAcmV0dXJucyBmbGF0YnVmZmVycy5PZmZzZXRcbiAgICAgKi9cbiAgICBzdGF0aWMgZW5kVGVuc29yKGJ1aWxkZXI6IGZsYXRidWZmZXJzLkJ1aWxkZXIpOiBmbGF0YnVmZmVycy5PZmZzZXQge1xuICAgICAgbGV0IG9mZnNldCA9IGJ1aWxkZXIuZW5kT2JqZWN0KCk7XG4gICAgICByZXR1cm4gb2Zmc2V0O1xuICAgIH1cblxuICAgIHN0YXRpYyBjcmVhdGVUZW5zb3IoXG4gICAgICAgIGJ1aWxkZXI6IGZsYXRidWZmZXJzLkJ1aWxkZXIsIG5hbWVPZmZzZXQ6IGZsYXRidWZmZXJzLk9mZnNldCwgZG9jU3RyaW5nT2Zmc2V0OiBmbGF0YnVmZmVycy5PZmZzZXQsXG4gICAgICAgIGRpbXNPZmZzZXQ6IGZsYXRidWZmZXJzLk9mZnNldCwgZGF0YVR5cGU6IG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnMuVGVuc29yRGF0YVR5cGUsXG4gICAgICAgIHJhd0RhdGFPZmZzZXQ6IGZsYXRidWZmZXJzLk9mZnNldCwgc3RyaW5nRGF0YU9mZnNldDogZmxhdGJ1ZmZlcnMuT2Zmc2V0KTogZmxhdGJ1ZmZlcnMuT2Zmc2V0IHtcbiAgICAgIFRlbnNvci5zdGFydFRlbnNvcihidWlsZGVyKTtcbiAgICAgIFRlbnNvci5hZGROYW1lKGJ1aWxkZXIsIG5hbWVPZmZzZXQpO1xuICAgICAgVGVuc29yLmFkZERvY1N0cmluZyhidWlsZGVyLCBkb2NTdHJpbmdPZmZzZXQpO1xuICAgICAgVGVuc29yLmFkZERpbXMoYnVpbGRlciwgZGltc09mZnNldCk7XG4gICAgICBUZW5zb3IuYWRkRGF0YVR5cGUoYnVpbGRlciwgZGF0YVR5cGUpO1xuICAgICAgVGVuc29yLmFkZFJhd0RhdGEoYnVpbGRlciwgcmF3RGF0YU9mZnNldCk7XG4gICAgICBUZW5zb3IuYWRkU3RyaW5nRGF0YShidWlsZGVyLCBzdHJpbmdEYXRhT2Zmc2V0KTtcbiAgICAgIHJldHVybiBUZW5zb3IuZW5kVGVuc29yKGJ1aWxkZXIpO1xuICAgIH1cbiAgfVxufVxuLyoqXG4gKiBAY29uc3RydWN0b3JcbiAqL1xuZXhwb3J0IG5hbWVzcGFjZSBvbm54cnVudGltZS5leHBlcmltZW50YWwuZmJzIHtcbiAgZXhwb3J0IGNsYXNzIFNwYXJzZVRlbnNvciB7XG4gICAgYmI6IGZsYXRidWZmZXJzLkJ5dGVCdWZmZXJ8bnVsbCA9IG51bGw7XG5cbiAgICBiYl9wb3MgPSAwO1xuICAgIC8qKlxuICAgICAqIEBwYXJhbSBudW1iZXIgaVxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CeXRlQnVmZmVyIGJiXG4gICAgICogQHJldHVybnMgU3BhcnNlVGVuc29yXG4gICAgICovXG4gICAgX19pbml0KGk6IG51bWJlciwgYmI6IGZsYXRidWZmZXJzLkJ5dGVCdWZmZXIpOiBTcGFyc2VUZW5zb3Ige1xuICAgICAgdGhpcy5iYl9wb3MgPSBpO1xuICAgICAgdGhpcy5iYiA9IGJiO1xuICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ5dGVCdWZmZXIgYmJcbiAgICAgKiBAcGFyYW0gU3BhcnNlVGVuc29yPSBvYmpcbiAgICAgKiBAcmV0dXJucyBTcGFyc2VUZW5zb3JcbiAgICAgKi9cbiAgICBzdGF0aWMgZ2V0Um9vdEFzU3BhcnNlVGVuc29yKGJiOiBmbGF0YnVmZmVycy5CeXRlQnVmZmVyLCBvYmo/OiBTcGFyc2VUZW5zb3IpOiBTcGFyc2VUZW5zb3Ige1xuICAgICAgcmV0dXJuIChvYmogfHwgbmV3IFNwYXJzZVRlbnNvcigpKS5fX2luaXQoYmIucmVhZEludDMyKGJiLnBvc2l0aW9uKCkpICsgYmIucG9zaXRpb24oKSwgYmIpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CeXRlQnVmZmVyIGJiXG4gICAgICogQHBhcmFtIFNwYXJzZVRlbnNvcj0gb2JqXG4gICAgICogQHJldHVybnMgU3BhcnNlVGVuc29yXG4gICAgICovXG4gICAgc3RhdGljIGdldFNpemVQcmVmaXhlZFJvb3RBc1NwYXJzZVRlbnNvcihiYjogZmxhdGJ1ZmZlcnMuQnl0ZUJ1ZmZlciwgb2JqPzogU3BhcnNlVGVuc29yKTogU3BhcnNlVGVuc29yIHtcbiAgICAgIGJiLnNldFBvc2l0aW9uKGJiLnBvc2l0aW9uKCkgKyBmbGF0YnVmZmVycy5TSVpFX1BSRUZJWF9MRU5HVEgpO1xuICAgICAgcmV0dXJuIChvYmogfHwgbmV3IFNwYXJzZVRlbnNvcigpKS5fX2luaXQoYmIucmVhZEludDMyKGJiLnBvc2l0aW9uKCkpICsgYmIucG9zaXRpb24oKSwgYmIpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBvbm54cnVudGltZS5leHBlcmltZW50YWwuZmJzLlRlbnNvcj0gb2JqXG4gICAgICogQHJldHVybnMgb25ueHJ1bnRpbWUuZXhwZXJpbWVudGFsLmZicy5UZW5zb3J8bnVsbFxuICAgICAqL1xuICAgIHZhbHVlcyhvYmo/OiBvbm54cnVudGltZS5leHBlcmltZW50YWwuZmJzLlRlbnNvcik6IG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnMuVGVuc29yfG51bGwge1xuICAgICAgbGV0IG9mZnNldCA9IHRoaXMuYmIhLl9fb2Zmc2V0KHRoaXMuYmJfcG9zLCA0KTtcbiAgICAgIHJldHVybiBvZmZzZXQgPyAob2JqIHx8IG5ldyBvbm54cnVudGltZS5leHBlcmltZW50YWwuZmJzLlRlbnNvcigpKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAuX19pbml0KHRoaXMuYmIhLl9faW5kaXJlY3QodGhpcy5iYl9wb3MgKyBvZmZzZXQpLCB0aGlzLmJiISkgOlxuICAgICAgICAgICAgICAgICAgICAgIG51bGw7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnMuVGVuc29yPSBvYmpcbiAgICAgKiBAcmV0dXJucyBvbm54cnVudGltZS5leHBlcmltZW50YWwuZmJzLlRlbnNvcnxudWxsXG4gICAgICovXG4gICAgaW5kaWNlcyhvYmo/OiBvbm54cnVudGltZS5leHBlcmltZW50YWwuZmJzLlRlbnNvcik6IG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnMuVGVuc29yfG51bGwge1xuICAgICAgbGV0IG9mZnNldCA9IHRoaXMuYmIhLl9fb2Zmc2V0KHRoaXMuYmJfcG9zLCA2KTtcbiAgICAgIHJldHVybiBvZmZzZXQgPyAob2JqIHx8IG5ldyBvbm54cnVudGltZS5leHBlcmltZW50YWwuZmJzLlRlbnNvcigpKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAuX19pbml0KHRoaXMuYmIhLl9faW5kaXJlY3QodGhpcy5iYl9wb3MgKyBvZmZzZXQpLCB0aGlzLmJiISkgOlxuICAgICAgICAgICAgICAgICAgICAgIG51bGw7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIG51bWJlciBpbmRleFxuICAgICAqIEByZXR1cm5zIGZsYXRidWZmZXJzLkxvbmdcbiAgICAgKi9cbiAgICBkaW1zKGluZGV4OiBudW1iZXIpOiBmbGF0YnVmZmVycy5Mb25nfG51bGwge1xuICAgICAgbGV0IG9mZnNldCA9IHRoaXMuYmIhLl9fb2Zmc2V0KHRoaXMuYmJfcG9zLCA4KTtcbiAgICAgIHJldHVybiBvZmZzZXQgPyB0aGlzLmJiIS5yZWFkSW50NjQodGhpcy5iYiEuX192ZWN0b3IodGhpcy5iYl9wb3MgKyBvZmZzZXQpICsgaW5kZXggKiA4KSA6XG4gICAgICAgICAgICAgICAgICAgICAgdGhpcy5iYiEuY3JlYXRlTG9uZygwLCAwKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcmV0dXJucyBudW1iZXJcbiAgICAgKi9cbiAgICBkaW1zTGVuZ3RoKCk6IG51bWJlciB7XG4gICAgICBsZXQgb2Zmc2V0ID0gdGhpcy5iYiEuX19vZmZzZXQodGhpcy5iYl9wb3MsIDgpO1xuICAgICAgcmV0dXJuIG9mZnNldCA/IHRoaXMuYmIhLl9fdmVjdG9yX2xlbih0aGlzLmJiX3BvcyArIG9mZnNldCkgOiAwO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CdWlsZGVyIGJ1aWxkZXJcbiAgICAgKi9cbiAgICBzdGF0aWMgc3RhcnRTcGFyc2VUZW5zb3IoYnVpbGRlcjogZmxhdGJ1ZmZlcnMuQnVpbGRlcikge1xuICAgICAgYnVpbGRlci5zdGFydE9iamVjdCgzKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuQnVpbGRlciBidWlsZGVyXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLk9mZnNldCB2YWx1ZXNPZmZzZXRcbiAgICAgKi9cbiAgICBzdGF0aWMgYWRkVmFsdWVzKGJ1aWxkZXI6IGZsYXRidWZmZXJzLkJ1aWxkZXIsIHZhbHVlc09mZnNldDogZmxhdGJ1ZmZlcnMuT2Zmc2V0KSB7XG4gICAgICBidWlsZGVyLmFkZEZpZWxkT2Zmc2V0KDAsIHZhbHVlc09mZnNldCwgMCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ1aWxkZXIgYnVpbGRlclxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5PZmZzZXQgaW5kaWNlc09mZnNldFxuICAgICAqL1xuICAgIHN0YXRpYyBhZGRJbmRpY2VzKGJ1aWxkZXI6IGZsYXRidWZmZXJzLkJ1aWxkZXIsIGluZGljZXNPZmZzZXQ6IGZsYXRidWZmZXJzLk9mZnNldCkge1xuICAgICAgYnVpbGRlci5hZGRGaWVsZE9mZnNldCgxLCBpbmRpY2VzT2Zmc2V0LCAwKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuQnVpbGRlciBidWlsZGVyXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLk9mZnNldCBkaW1zT2Zmc2V0XG4gICAgICovXG4gICAgc3RhdGljIGFkZERpbXMoYnVpbGRlcjogZmxhdGJ1ZmZlcnMuQnVpbGRlciwgZGltc09mZnNldDogZmxhdGJ1ZmZlcnMuT2Zmc2V0KSB7XG4gICAgICBidWlsZGVyLmFkZEZpZWxkT2Zmc2V0KDIsIGRpbXNPZmZzZXQsIDApO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CdWlsZGVyIGJ1aWxkZXJcbiAgICAgKiBAcGFyYW0gQXJyYXkuPGZsYXRidWZmZXJzLkxvbmc+IGRhdGFcbiAgICAgKiBAcmV0dXJucyBmbGF0YnVmZmVycy5PZmZzZXRcbiAgICAgKi9cbiAgICBzdGF0aWMgY3JlYXRlRGltc1ZlY3RvcihidWlsZGVyOiBmbGF0YnVmZmVycy5CdWlsZGVyLCBkYXRhOiBmbGF0YnVmZmVycy5Mb25nW10pOiBmbGF0YnVmZmVycy5PZmZzZXQge1xuICAgICAgYnVpbGRlci5zdGFydFZlY3Rvcig4LCBkYXRhLmxlbmd0aCwgOCk7XG4gICAgICBmb3IgKGxldCBpID0gZGF0YS5sZW5ndGggLSAxOyBpID49IDA7IGktLSkge1xuICAgICAgICBidWlsZGVyLmFkZEludDY0KGRhdGFbaV0pO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGJ1aWxkZXIuZW5kVmVjdG9yKCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ1aWxkZXIgYnVpbGRlclxuICAgICAqIEBwYXJhbSBudW1iZXIgbnVtRWxlbXNcbiAgICAgKi9cbiAgICBzdGF0aWMgc3RhcnREaW1zVmVjdG9yKGJ1aWxkZXI6IGZsYXRidWZmZXJzLkJ1aWxkZXIsIG51bUVsZW1zOiBudW1iZXIpIHtcbiAgICAgIGJ1aWxkZXIuc3RhcnRWZWN0b3IoOCwgbnVtRWxlbXMsIDgpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CdWlsZGVyIGJ1aWxkZXJcbiAgICAgKiBAcmV0dXJucyBmbGF0YnVmZmVycy5PZmZzZXRcbiAgICAgKi9cbiAgICBzdGF0aWMgZW5kU3BhcnNlVGVuc29yKGJ1aWxkZXI6IGZsYXRidWZmZXJzLkJ1aWxkZXIpOiBmbGF0YnVmZmVycy5PZmZzZXQge1xuICAgICAgbGV0IG9mZnNldCA9IGJ1aWxkZXIuZW5kT2JqZWN0KCk7XG4gICAgICByZXR1cm4gb2Zmc2V0O1xuICAgIH1cblxuICAgIHN0YXRpYyBjcmVhdGVTcGFyc2VUZW5zb3IoXG4gICAgICAgIGJ1aWxkZXI6IGZsYXRidWZmZXJzLkJ1aWxkZXIsIHZhbHVlc09mZnNldDogZmxhdGJ1ZmZlcnMuT2Zmc2V0LCBpbmRpY2VzT2Zmc2V0OiBmbGF0YnVmZmVycy5PZmZzZXQsXG4gICAgICAgIGRpbXNPZmZzZXQ6IGZsYXRidWZmZXJzLk9mZnNldCk6IGZsYXRidWZmZXJzLk9mZnNldCB7XG4gICAgICBTcGFyc2VUZW5zb3Iuc3RhcnRTcGFyc2VUZW5zb3IoYnVpbGRlcik7XG4gICAgICBTcGFyc2VUZW5zb3IuYWRkVmFsdWVzKGJ1aWxkZXIsIHZhbHVlc09mZnNldCk7XG4gICAgICBTcGFyc2VUZW5zb3IuYWRkSW5kaWNlcyhidWlsZGVyLCBpbmRpY2VzT2Zmc2V0KTtcbiAgICAgIFNwYXJzZVRlbnNvci5hZGREaW1zKGJ1aWxkZXIsIGRpbXNPZmZzZXQpO1xuICAgICAgcmV0dXJuIFNwYXJzZVRlbnNvci5lbmRTcGFyc2VUZW5zb3IoYnVpbGRlcik7XG4gICAgfVxuICB9XG59XG4vKipcbiAqIEBjb25zdHJ1Y3RvclxuICovXG5leHBvcnQgbmFtZXNwYWNlIG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnMge1xuICBleHBvcnQgY2xhc3MgQXR0cmlidXRlIHtcbiAgICBiYjogZmxhdGJ1ZmZlcnMuQnl0ZUJ1ZmZlcnxudWxsID0gbnVsbDtcblxuICAgIGJiX3BvcyA9IDA7XG4gICAgLyoqXG4gICAgICogQHBhcmFtIG51bWJlciBpXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ5dGVCdWZmZXIgYmJcbiAgICAgKiBAcmV0dXJucyBBdHRyaWJ1dGVcbiAgICAgKi9cbiAgICBfX2luaXQoaTogbnVtYmVyLCBiYjogZmxhdGJ1ZmZlcnMuQnl0ZUJ1ZmZlcik6IEF0dHJpYnV0ZSB7XG4gICAgICB0aGlzLmJiX3BvcyA9IGk7XG4gICAgICB0aGlzLmJiID0gYmI7XG4gICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuQnl0ZUJ1ZmZlciBiYlxuICAgICAqIEBwYXJhbSBBdHRyaWJ1dGU9IG9ialxuICAgICAqIEByZXR1cm5zIEF0dHJpYnV0ZVxuICAgICAqL1xuICAgIHN0YXRpYyBnZXRSb290QXNBdHRyaWJ1dGUoYmI6IGZsYXRidWZmZXJzLkJ5dGVCdWZmZXIsIG9iaj86IEF0dHJpYnV0ZSk6IEF0dHJpYnV0ZSB7XG4gICAgICByZXR1cm4gKG9iaiB8fCBuZXcgQXR0cmlidXRlKCkpLl9faW5pdChiYi5yZWFkSW50MzIoYmIucG9zaXRpb24oKSkgKyBiYi5wb3NpdGlvbigpLCBiYik7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ5dGVCdWZmZXIgYmJcbiAgICAgKiBAcGFyYW0gQXR0cmlidXRlPSBvYmpcbiAgICAgKiBAcmV0dXJucyBBdHRyaWJ1dGVcbiAgICAgKi9cbiAgICBzdGF0aWMgZ2V0U2l6ZVByZWZpeGVkUm9vdEFzQXR0cmlidXRlKGJiOiBmbGF0YnVmZmVycy5CeXRlQnVmZmVyLCBvYmo/OiBBdHRyaWJ1dGUpOiBBdHRyaWJ1dGUge1xuICAgICAgYmIuc2V0UG9zaXRpb24oYmIucG9zaXRpb24oKSArIGZsYXRidWZmZXJzLlNJWkVfUFJFRklYX0xFTkdUSCk7XG4gICAgICByZXR1cm4gKG9iaiB8fCBuZXcgQXR0cmlidXRlKCkpLl9faW5pdChiYi5yZWFkSW50MzIoYmIucG9zaXRpb24oKSkgKyBiYi5wb3NpdGlvbigpLCBiYik7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkVuY29kaW5nPSBvcHRpb25hbEVuY29kaW5nXG4gICAgICogQHJldHVybnMgc3RyaW5nfFVpbnQ4QXJyYXl8bnVsbFxuICAgICAqL1xuICAgIG5hbWUoKTogc3RyaW5nfG51bGw7XG4gICAgbmFtZShvcHRpb25hbEVuY29kaW5nOiBmbGF0YnVmZmVycy5FbmNvZGluZyk6IHN0cmluZ3xVaW50OEFycmF5fG51bGw7XG4gICAgbmFtZShvcHRpb25hbEVuY29kaW5nPzogYW55KTogc3RyaW5nfFVpbnQ4QXJyYXl8bnVsbCB7XG4gICAgICBsZXQgb2Zmc2V0ID0gdGhpcy5iYiEuX19vZmZzZXQodGhpcy5iYl9wb3MsIDQpO1xuICAgICAgcmV0dXJuIG9mZnNldCA/IHRoaXMuYmIhLl9fc3RyaW5nKHRoaXMuYmJfcG9zICsgb2Zmc2V0LCBvcHRpb25hbEVuY29kaW5nKSA6IG51bGw7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkVuY29kaW5nPSBvcHRpb25hbEVuY29kaW5nXG4gICAgICogQHJldHVybnMgc3RyaW5nfFVpbnQ4QXJyYXl8bnVsbFxuICAgICAqL1xuICAgIGRvY1N0cmluZygpOiBzdHJpbmd8bnVsbDtcbiAgICBkb2NTdHJpbmcob3B0aW9uYWxFbmNvZGluZzogZmxhdGJ1ZmZlcnMuRW5jb2RpbmcpOiBzdHJpbmd8VWludDhBcnJheXxudWxsO1xuICAgIGRvY1N0cmluZyhvcHRpb25hbEVuY29kaW5nPzogYW55KTogc3RyaW5nfFVpbnQ4QXJyYXl8bnVsbCB7XG4gICAgICBsZXQgb2Zmc2V0ID0gdGhpcy5iYiEuX19vZmZzZXQodGhpcy5iYl9wb3MsIDYpO1xuICAgICAgcmV0dXJuIG9mZnNldCA/IHRoaXMuYmIhLl9fc3RyaW5nKHRoaXMuYmJfcG9zICsgb2Zmc2V0LCBvcHRpb25hbEVuY29kaW5nKSA6IG51bGw7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHJldHVybnMgb25ueHJ1bnRpbWUuZXhwZXJpbWVudGFsLmZicy5BdHRyaWJ1dGVUeXBlXG4gICAgICovXG4gICAgdHlwZSgpOiBvbm54cnVudGltZS5leHBlcmltZW50YWwuZmJzLkF0dHJpYnV0ZVR5cGUge1xuICAgICAgbGV0IG9mZnNldCA9IHRoaXMuYmIhLl9fb2Zmc2V0KHRoaXMuYmJfcG9zLCA4KTtcbiAgICAgIHJldHVybiBvZmZzZXQgPyAvKiogICovICh0aGlzLmJiIS5yZWFkSW50MzIodGhpcy5iYl9wb3MgKyBvZmZzZXQpKSA6XG4gICAgICAgICAgICAgICAgICAgICAgb25ueHJ1bnRpbWUuZXhwZXJpbWVudGFsLmZicy5BdHRyaWJ1dGVUeXBlLlVOREVGSU5FRDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcmV0dXJucyBudW1iZXJcbiAgICAgKi9cbiAgICBmKCk6IG51bWJlciB7XG4gICAgICBsZXQgb2Zmc2V0ID0gdGhpcy5iYiEuX19vZmZzZXQodGhpcy5iYl9wb3MsIDEwKTtcbiAgICAgIHJldHVybiBvZmZzZXQgPyB0aGlzLmJiIS5yZWFkRmxvYXQzMih0aGlzLmJiX3BvcyArIG9mZnNldCkgOiAwLjA7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHJldHVybnMgZmxhdGJ1ZmZlcnMuTG9uZ1xuICAgICAqL1xuICAgIGkoKTogZmxhdGJ1ZmZlcnMuTG9uZyB7XG4gICAgICBsZXQgb2Zmc2V0ID0gdGhpcy5iYiEuX19vZmZzZXQodGhpcy5iYl9wb3MsIDEyKTtcbiAgICAgIHJldHVybiBvZmZzZXQgPyB0aGlzLmJiIS5yZWFkSW50NjQodGhpcy5iYl9wb3MgKyBvZmZzZXQpIDogdGhpcy5iYiEuY3JlYXRlTG9uZygwLCAwKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuRW5jb2Rpbmc9IG9wdGlvbmFsRW5jb2RpbmdcbiAgICAgKiBAcmV0dXJucyBzdHJpbmd8VWludDhBcnJheXxudWxsXG4gICAgICovXG4gICAgcygpOiBzdHJpbmd8bnVsbDtcbiAgICBzKG9wdGlvbmFsRW5jb2Rpbmc6IGZsYXRidWZmZXJzLkVuY29kaW5nKTogc3RyaW5nfFVpbnQ4QXJyYXl8bnVsbDtcbiAgICBzKG9wdGlvbmFsRW5jb2Rpbmc/OiBhbnkpOiBzdHJpbmd8VWludDhBcnJheXxudWxsIHtcbiAgICAgIGxldCBvZmZzZXQgPSB0aGlzLmJiIS5fX29mZnNldCh0aGlzLmJiX3BvcywgMTQpO1xuICAgICAgcmV0dXJuIG9mZnNldCA/IHRoaXMuYmIhLl9fc3RyaW5nKHRoaXMuYmJfcG9zICsgb2Zmc2V0LCBvcHRpb25hbEVuY29kaW5nKSA6IG51bGw7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnMuVGVuc29yPSBvYmpcbiAgICAgKiBAcmV0dXJucyBvbm54cnVudGltZS5leHBlcmltZW50YWwuZmJzLlRlbnNvcnxudWxsXG4gICAgICovXG4gICAgdChvYmo/OiBvbm54cnVudGltZS5leHBlcmltZW50YWwuZmJzLlRlbnNvcik6IG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnMuVGVuc29yfG51bGwge1xuICAgICAgbGV0IG9mZnNldCA9IHRoaXMuYmIhLl9fb2Zmc2V0KHRoaXMuYmJfcG9zLCAxNik7XG4gICAgICByZXR1cm4gb2Zmc2V0ID8gKG9iaiB8fCBuZXcgb25ueHJ1bnRpbWUuZXhwZXJpbWVudGFsLmZicy5UZW5zb3IoKSlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgLl9faW5pdCh0aGlzLmJiIS5fX2luZGlyZWN0KHRoaXMuYmJfcG9zICsgb2Zmc2V0KSwgdGhpcy5iYiEpIDpcbiAgICAgICAgICAgICAgICAgICAgICBudWxsO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBvbm54cnVudGltZS5leHBlcmltZW50YWwuZmJzLkdyYXBoPSBvYmpcbiAgICAgKiBAcmV0dXJucyBvbm54cnVudGltZS5leHBlcmltZW50YWwuZmJzLkdyYXBofG51bGxcbiAgICAgKi9cbiAgICBnKG9iaj86IG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnMuR3JhcGgpOiBvbm54cnVudGltZS5leHBlcmltZW50YWwuZmJzLkdyYXBofG51bGwge1xuICAgICAgbGV0IG9mZnNldCA9IHRoaXMuYmIhLl9fb2Zmc2V0KHRoaXMuYmJfcG9zLCAxOCk7XG4gICAgICByZXR1cm4gb2Zmc2V0ID8gKG9iaiB8fCBuZXcgb25ueHJ1bnRpbWUuZXhwZXJpbWVudGFsLmZicy5HcmFwaCgpKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAuX19pbml0KHRoaXMuYmIhLl9faW5kaXJlY3QodGhpcy5iYl9wb3MgKyBvZmZzZXQpLCB0aGlzLmJiISkgOlxuICAgICAgICAgICAgICAgICAgICAgIG51bGw7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIG51bWJlciBpbmRleFxuICAgICAqIEByZXR1cm5zIG51bWJlclxuICAgICAqL1xuICAgIGZsb2F0cyhpbmRleDogbnVtYmVyKTogbnVtYmVyfG51bGwge1xuICAgICAgbGV0IG9mZnNldCA9IHRoaXMuYmIhLl9fb2Zmc2V0KHRoaXMuYmJfcG9zLCAyMCk7XG4gICAgICByZXR1cm4gb2Zmc2V0ID8gdGhpcy5iYiEucmVhZEZsb2F0MzIodGhpcy5iYiEuX192ZWN0b3IodGhpcy5iYl9wb3MgKyBvZmZzZXQpICsgaW5kZXggKiA0KSA6IDA7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHJldHVybnMgbnVtYmVyXG4gICAgICovXG4gICAgZmxvYXRzTGVuZ3RoKCk6IG51bWJlciB7XG4gICAgICBsZXQgb2Zmc2V0ID0gdGhpcy5iYiEuX19vZmZzZXQodGhpcy5iYl9wb3MsIDIwKTtcbiAgICAgIHJldHVybiBvZmZzZXQgPyB0aGlzLmJiIS5fX3ZlY3Rvcl9sZW4odGhpcy5iYl9wb3MgKyBvZmZzZXQpIDogMDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcmV0dXJucyBGbG9hdDMyQXJyYXlcbiAgICAgKi9cbiAgICBmbG9hdHNBcnJheSgpOiBGbG9hdDMyQXJyYXl8bnVsbCB7XG4gICAgICBsZXQgb2Zmc2V0ID0gdGhpcy5iYiEuX19vZmZzZXQodGhpcy5iYl9wb3MsIDIwKTtcbiAgICAgIHJldHVybiBvZmZzZXQgP1xuICAgICAgICAgIG5ldyBGbG9hdDMyQXJyYXkoXG4gICAgICAgICAgICAgIHRoaXMuYmIhLmJ5dGVzKCkuYnVmZmVyLCB0aGlzLmJiIS5ieXRlcygpLmJ5dGVPZmZzZXQgKyB0aGlzLmJiIS5fX3ZlY3Rvcih0aGlzLmJiX3BvcyArIG9mZnNldCksXG4gICAgICAgICAgICAgIHRoaXMuYmIhLl9fdmVjdG9yX2xlbih0aGlzLmJiX3BvcyArIG9mZnNldCkpIDpcbiAgICAgICAgICBudWxsO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBudW1iZXIgaW5kZXhcbiAgICAgKiBAcmV0dXJucyBmbGF0YnVmZmVycy5Mb25nXG4gICAgICovXG4gICAgaW50cyhpbmRleDogbnVtYmVyKTogZmxhdGJ1ZmZlcnMuTG9uZ3xudWxsIHtcbiAgICAgIGxldCBvZmZzZXQgPSB0aGlzLmJiIS5fX29mZnNldCh0aGlzLmJiX3BvcywgMjIpO1xuICAgICAgcmV0dXJuIG9mZnNldCA/IHRoaXMuYmIhLnJlYWRJbnQ2NCh0aGlzLmJiIS5fX3ZlY3Rvcih0aGlzLmJiX3BvcyArIG9mZnNldCkgKyBpbmRleCAqIDgpIDpcbiAgICAgICAgICAgICAgICAgICAgICB0aGlzLmJiIS5jcmVhdGVMb25nKDAsIDApO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEByZXR1cm5zIG51bWJlclxuICAgICAqL1xuICAgIGludHNMZW5ndGgoKTogbnVtYmVyIHtcbiAgICAgIGxldCBvZmZzZXQgPSB0aGlzLmJiIS5fX29mZnNldCh0aGlzLmJiX3BvcywgMjIpO1xuICAgICAgcmV0dXJuIG9mZnNldCA/IHRoaXMuYmIhLl9fdmVjdG9yX2xlbih0aGlzLmJiX3BvcyArIG9mZnNldCkgOiAwO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBudW1iZXIgaW5kZXhcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuRW5jb2Rpbmc9IG9wdGlvbmFsRW5jb2RpbmdcbiAgICAgKiBAcmV0dXJucyBzdHJpbmd8VWludDhBcnJheVxuICAgICAqL1xuICAgIHN0cmluZ3MoaW5kZXg6IG51bWJlcik6IHN0cmluZztcbiAgICBzdHJpbmdzKGluZGV4OiBudW1iZXIsIG9wdGlvbmFsRW5jb2Rpbmc6IGZsYXRidWZmZXJzLkVuY29kaW5nKTogc3RyaW5nfFVpbnQ4QXJyYXk7XG4gICAgc3RyaW5ncyhpbmRleDogbnVtYmVyLCBvcHRpb25hbEVuY29kaW5nPzogYW55KTogc3RyaW5nfFVpbnQ4QXJyYXl8bnVsbCB7XG4gICAgICBsZXQgb2Zmc2V0ID0gdGhpcy5iYiEuX19vZmZzZXQodGhpcy5iYl9wb3MsIDI0KTtcbiAgICAgIHJldHVybiBvZmZzZXQgPyB0aGlzLmJiIS5fX3N0cmluZyh0aGlzLmJiIS5fX3ZlY3Rvcih0aGlzLmJiX3BvcyArIG9mZnNldCkgKyBpbmRleCAqIDQsIG9wdGlvbmFsRW5jb2RpbmcpIDogbnVsbDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcmV0dXJucyBudW1iZXJcbiAgICAgKi9cbiAgICBzdHJpbmdzTGVuZ3RoKCk6IG51bWJlciB7XG4gICAgICBsZXQgb2Zmc2V0ID0gdGhpcy5iYiEuX19vZmZzZXQodGhpcy5iYl9wb3MsIDI0KTtcbiAgICAgIHJldHVybiBvZmZzZXQgPyB0aGlzLmJiIS5fX3ZlY3Rvcl9sZW4odGhpcy5iYl9wb3MgKyBvZmZzZXQpIDogMDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gbnVtYmVyIGluZGV4XG4gICAgICogQHBhcmFtIG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnMuVGVuc29yPSBvYmpcbiAgICAgKiBAcmV0dXJucyBvbm54cnVudGltZS5leHBlcmltZW50YWwuZmJzLlRlbnNvclxuICAgICAqL1xuICAgIHRlbnNvcnMoaW5kZXg6IG51bWJlciwgb2JqPzogb25ueHJ1bnRpbWUuZXhwZXJpbWVudGFsLmZicy5UZW5zb3IpOiBvbm54cnVudGltZS5leHBlcmltZW50YWwuZmJzLlRlbnNvcnxudWxsIHtcbiAgICAgIGxldCBvZmZzZXQgPSB0aGlzLmJiIS5fX29mZnNldCh0aGlzLmJiX3BvcywgMjYpO1xuICAgICAgcmV0dXJuIG9mZnNldCA/IChvYmogfHwgbmV3IG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnMuVGVuc29yKCkpXG4gICAgICAgICAgICAgICAgICAgICAgICAgIC5fX2luaXQodGhpcy5iYiEuX19pbmRpcmVjdCh0aGlzLmJiIS5fX3ZlY3Rvcih0aGlzLmJiX3BvcyArIG9mZnNldCkgKyBpbmRleCAqIDQpLCB0aGlzLmJiISkgOlxuICAgICAgICAgICAgICAgICAgICAgIG51bGw7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHJldHVybnMgbnVtYmVyXG4gICAgICovXG4gICAgdGVuc29yc0xlbmd0aCgpOiBudW1iZXIge1xuICAgICAgbGV0IG9mZnNldCA9IHRoaXMuYmIhLl9fb2Zmc2V0KHRoaXMuYmJfcG9zLCAyNik7XG4gICAgICByZXR1cm4gb2Zmc2V0ID8gdGhpcy5iYiEuX192ZWN0b3JfbGVuKHRoaXMuYmJfcG9zICsgb2Zmc2V0KSA6IDA7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIG51bWJlciBpbmRleFxuICAgICAqIEBwYXJhbSBvbm54cnVudGltZS5leHBlcmltZW50YWwuZmJzLkdyYXBoPSBvYmpcbiAgICAgKiBAcmV0dXJucyBvbm54cnVudGltZS5leHBlcmltZW50YWwuZmJzLkdyYXBoXG4gICAgICovXG4gICAgZ3JhcGhzKGluZGV4OiBudW1iZXIsIG9iaj86IG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnMuR3JhcGgpOiBvbm54cnVudGltZS5leHBlcmltZW50YWwuZmJzLkdyYXBofG51bGwge1xuICAgICAgbGV0IG9mZnNldCA9IHRoaXMuYmIhLl9fb2Zmc2V0KHRoaXMuYmJfcG9zLCAyOCk7XG4gICAgICByZXR1cm4gb2Zmc2V0ID8gKG9iaiB8fCBuZXcgb25ueHJ1bnRpbWUuZXhwZXJpbWVudGFsLmZicy5HcmFwaCgpKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAuX19pbml0KHRoaXMuYmIhLl9faW5kaXJlY3QodGhpcy5iYiEuX192ZWN0b3IodGhpcy5iYl9wb3MgKyBvZmZzZXQpICsgaW5kZXggKiA0KSwgdGhpcy5iYiEpIDpcbiAgICAgICAgICAgICAgICAgICAgICBudWxsO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEByZXR1cm5zIG51bWJlclxuICAgICAqL1xuICAgIGdyYXBoc0xlbmd0aCgpOiBudW1iZXIge1xuICAgICAgbGV0IG9mZnNldCA9IHRoaXMuYmIhLl9fb2Zmc2V0KHRoaXMuYmJfcG9zLCAyOCk7XG4gICAgICByZXR1cm4gb2Zmc2V0ID8gdGhpcy5iYiEuX192ZWN0b3JfbGVuKHRoaXMuYmJfcG9zICsgb2Zmc2V0KSA6IDA7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ1aWxkZXIgYnVpbGRlclxuICAgICAqL1xuICAgIHN0YXRpYyBzdGFydEF0dHJpYnV0ZShidWlsZGVyOiBmbGF0YnVmZmVycy5CdWlsZGVyKSB7XG4gICAgICBidWlsZGVyLnN0YXJ0T2JqZWN0KDEzKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuQnVpbGRlciBidWlsZGVyXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLk9mZnNldCBuYW1lT2Zmc2V0XG4gICAgICovXG4gICAgc3RhdGljIGFkZE5hbWUoYnVpbGRlcjogZmxhdGJ1ZmZlcnMuQnVpbGRlciwgbmFtZU9mZnNldDogZmxhdGJ1ZmZlcnMuT2Zmc2V0KSB7XG4gICAgICBidWlsZGVyLmFkZEZpZWxkT2Zmc2V0KDAsIG5hbWVPZmZzZXQsIDApO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CdWlsZGVyIGJ1aWxkZXJcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuT2Zmc2V0IGRvY1N0cmluZ09mZnNldFxuICAgICAqL1xuICAgIHN0YXRpYyBhZGREb2NTdHJpbmcoYnVpbGRlcjogZmxhdGJ1ZmZlcnMuQnVpbGRlciwgZG9jU3RyaW5nT2Zmc2V0OiBmbGF0YnVmZmVycy5PZmZzZXQpIHtcbiAgICAgIGJ1aWxkZXIuYWRkRmllbGRPZmZzZXQoMSwgZG9jU3RyaW5nT2Zmc2V0LCAwKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuQnVpbGRlciBidWlsZGVyXG4gICAgICogQHBhcmFtIG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnMuQXR0cmlidXRlVHlwZSB0eXBlXG4gICAgICovXG4gICAgc3RhdGljIGFkZFR5cGUoYnVpbGRlcjogZmxhdGJ1ZmZlcnMuQnVpbGRlciwgdHlwZTogb25ueHJ1bnRpbWUuZXhwZXJpbWVudGFsLmZicy5BdHRyaWJ1dGVUeXBlKSB7XG4gICAgICBidWlsZGVyLmFkZEZpZWxkSW50MzIoMiwgdHlwZSwgb25ueHJ1bnRpbWUuZXhwZXJpbWVudGFsLmZicy5BdHRyaWJ1dGVUeXBlLlVOREVGSU5FRCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ1aWxkZXIgYnVpbGRlclxuICAgICAqIEBwYXJhbSBudW1iZXIgZlxuICAgICAqL1xuICAgIHN0YXRpYyBhZGRGKGJ1aWxkZXI6IGZsYXRidWZmZXJzLkJ1aWxkZXIsIGY6IG51bWJlcikge1xuICAgICAgYnVpbGRlci5hZGRGaWVsZEZsb2F0MzIoMywgZiwgMC4wKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuQnVpbGRlciBidWlsZGVyXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkxvbmcgaVxuICAgICAqL1xuICAgIHN0YXRpYyBhZGRJKGJ1aWxkZXI6IGZsYXRidWZmZXJzLkJ1aWxkZXIsIGk6IGZsYXRidWZmZXJzLkxvbmcpIHtcbiAgICAgIGJ1aWxkZXIuYWRkRmllbGRJbnQ2NCg0LCBpLCBidWlsZGVyLmNyZWF0ZUxvbmcoMCwgMCkpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CdWlsZGVyIGJ1aWxkZXJcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuT2Zmc2V0IHNPZmZzZXRcbiAgICAgKi9cbiAgICBzdGF0aWMgYWRkUyhidWlsZGVyOiBmbGF0YnVmZmVycy5CdWlsZGVyLCBzT2Zmc2V0OiBmbGF0YnVmZmVycy5PZmZzZXQpIHtcbiAgICAgIGJ1aWxkZXIuYWRkRmllbGRPZmZzZXQoNSwgc09mZnNldCwgMCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ1aWxkZXIgYnVpbGRlclxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5PZmZzZXQgdE9mZnNldFxuICAgICAqL1xuICAgIHN0YXRpYyBhZGRUKGJ1aWxkZXI6IGZsYXRidWZmZXJzLkJ1aWxkZXIsIHRPZmZzZXQ6IGZsYXRidWZmZXJzLk9mZnNldCkge1xuICAgICAgYnVpbGRlci5hZGRGaWVsZE9mZnNldCg2LCB0T2Zmc2V0LCAwKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuQnVpbGRlciBidWlsZGVyXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLk9mZnNldCBnT2Zmc2V0XG4gICAgICovXG4gICAgc3RhdGljIGFkZEcoYnVpbGRlcjogZmxhdGJ1ZmZlcnMuQnVpbGRlciwgZ09mZnNldDogZmxhdGJ1ZmZlcnMuT2Zmc2V0KSB7XG4gICAgICBidWlsZGVyLmFkZEZpZWxkT2Zmc2V0KDcsIGdPZmZzZXQsIDApO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CdWlsZGVyIGJ1aWxkZXJcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuT2Zmc2V0IGZsb2F0c09mZnNldFxuICAgICAqL1xuICAgIHN0YXRpYyBhZGRGbG9hdHMoYnVpbGRlcjogZmxhdGJ1ZmZlcnMuQnVpbGRlciwgZmxvYXRzT2Zmc2V0OiBmbGF0YnVmZmVycy5PZmZzZXQpIHtcbiAgICAgIGJ1aWxkZXIuYWRkRmllbGRPZmZzZXQoOCwgZmxvYXRzT2Zmc2V0LCAwKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuQnVpbGRlciBidWlsZGVyXG4gICAgICogQHBhcmFtIEFycmF5LjxudW1iZXI+IGRhdGFcbiAgICAgKiBAcmV0dXJucyBmbGF0YnVmZmVycy5PZmZzZXRcbiAgICAgKi9cbiAgICBzdGF0aWMgY3JlYXRlRmxvYXRzVmVjdG9yKGJ1aWxkZXI6IGZsYXRidWZmZXJzLkJ1aWxkZXIsIGRhdGE6IG51bWJlcltdfFVpbnQ4QXJyYXkpOiBmbGF0YnVmZmVycy5PZmZzZXQge1xuICAgICAgYnVpbGRlci5zdGFydFZlY3Rvcig0LCBkYXRhLmxlbmd0aCwgNCk7XG4gICAgICBmb3IgKGxldCBpID0gZGF0YS5sZW5ndGggLSAxOyBpID49IDA7IGktLSkge1xuICAgICAgICBidWlsZGVyLmFkZEZsb2F0MzIoZGF0YVtpXSk7XG4gICAgICB9XG4gICAgICByZXR1cm4gYnVpbGRlci5lbmRWZWN0b3IoKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuQnVpbGRlciBidWlsZGVyXG4gICAgICogQHBhcmFtIG51bWJlciBudW1FbGVtc1xuICAgICAqL1xuICAgIHN0YXRpYyBzdGFydEZsb2F0c1ZlY3RvcihidWlsZGVyOiBmbGF0YnVmZmVycy5CdWlsZGVyLCBudW1FbGVtczogbnVtYmVyKSB7XG4gICAgICBidWlsZGVyLnN0YXJ0VmVjdG9yKDQsIG51bUVsZW1zLCA0KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuQnVpbGRlciBidWlsZGVyXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLk9mZnNldCBpbnRzT2Zmc2V0XG4gICAgICovXG4gICAgc3RhdGljIGFkZEludHMoYnVpbGRlcjogZmxhdGJ1ZmZlcnMuQnVpbGRlciwgaW50c09mZnNldDogZmxhdGJ1ZmZlcnMuT2Zmc2V0KSB7XG4gICAgICBidWlsZGVyLmFkZEZpZWxkT2Zmc2V0KDksIGludHNPZmZzZXQsIDApO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CdWlsZGVyIGJ1aWxkZXJcbiAgICAgKiBAcGFyYW0gQXJyYXkuPGZsYXRidWZmZXJzLkxvbmc+IGRhdGFcbiAgICAgKiBAcmV0dXJucyBmbGF0YnVmZmVycy5PZmZzZXRcbiAgICAgKi9cbiAgICBzdGF0aWMgY3JlYXRlSW50c1ZlY3RvcihidWlsZGVyOiBmbGF0YnVmZmVycy5CdWlsZGVyLCBkYXRhOiBmbGF0YnVmZmVycy5Mb25nW10pOiBmbGF0YnVmZmVycy5PZmZzZXQge1xuICAgICAgYnVpbGRlci5zdGFydFZlY3Rvcig4LCBkYXRhLmxlbmd0aCwgOCk7XG4gICAgICBmb3IgKGxldCBpID0gZGF0YS5sZW5ndGggLSAxOyBpID49IDA7IGktLSkge1xuICAgICAgICBidWlsZGVyLmFkZEludDY0KGRhdGFbaV0pO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGJ1aWxkZXIuZW5kVmVjdG9yKCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ1aWxkZXIgYnVpbGRlclxuICAgICAqIEBwYXJhbSBudW1iZXIgbnVtRWxlbXNcbiAgICAgKi9cbiAgICBzdGF0aWMgc3RhcnRJbnRzVmVjdG9yKGJ1aWxkZXI6IGZsYXRidWZmZXJzLkJ1aWxkZXIsIG51bUVsZW1zOiBudW1iZXIpIHtcbiAgICAgIGJ1aWxkZXIuc3RhcnRWZWN0b3IoOCwgbnVtRWxlbXMsIDgpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CdWlsZGVyIGJ1aWxkZXJcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuT2Zmc2V0IHN0cmluZ3NPZmZzZXRcbiAgICAgKi9cbiAgICBzdGF0aWMgYWRkU3RyaW5ncyhidWlsZGVyOiBmbGF0YnVmZmVycy5CdWlsZGVyLCBzdHJpbmdzT2Zmc2V0OiBmbGF0YnVmZmVycy5PZmZzZXQpIHtcbiAgICAgIGJ1aWxkZXIuYWRkRmllbGRPZmZzZXQoMTAsIHN0cmluZ3NPZmZzZXQsIDApO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CdWlsZGVyIGJ1aWxkZXJcbiAgICAgKiBAcGFyYW0gQXJyYXkuPGZsYXRidWZmZXJzLk9mZnNldD4gZGF0YVxuICAgICAqIEByZXR1cm5zIGZsYXRidWZmZXJzLk9mZnNldFxuICAgICAqL1xuICAgIHN0YXRpYyBjcmVhdGVTdHJpbmdzVmVjdG9yKGJ1aWxkZXI6IGZsYXRidWZmZXJzLkJ1aWxkZXIsIGRhdGE6IGZsYXRidWZmZXJzLk9mZnNldFtdKTogZmxhdGJ1ZmZlcnMuT2Zmc2V0IHtcbiAgICAgIGJ1aWxkZXIuc3RhcnRWZWN0b3IoNCwgZGF0YS5sZW5ndGgsIDQpO1xuICAgICAgZm9yIChsZXQgaSA9IGRhdGEubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICAgICAgYnVpbGRlci5hZGRPZmZzZXQoZGF0YVtpXSk7XG4gICAgICB9XG4gICAgICByZXR1cm4gYnVpbGRlci5lbmRWZWN0b3IoKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuQnVpbGRlciBidWlsZGVyXG4gICAgICogQHBhcmFtIG51bWJlciBudW1FbGVtc1xuICAgICAqL1xuICAgIHN0YXRpYyBzdGFydFN0cmluZ3NWZWN0b3IoYnVpbGRlcjogZmxhdGJ1ZmZlcnMuQnVpbGRlciwgbnVtRWxlbXM6IG51bWJlcikge1xuICAgICAgYnVpbGRlci5zdGFydFZlY3Rvcig0LCBudW1FbGVtcywgNCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ1aWxkZXIgYnVpbGRlclxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5PZmZzZXQgdGVuc29yc09mZnNldFxuICAgICAqL1xuICAgIHN0YXRpYyBhZGRUZW5zb3JzKGJ1aWxkZXI6IGZsYXRidWZmZXJzLkJ1aWxkZXIsIHRlbnNvcnNPZmZzZXQ6IGZsYXRidWZmZXJzLk9mZnNldCkge1xuICAgICAgYnVpbGRlci5hZGRGaWVsZE9mZnNldCgxMSwgdGVuc29yc09mZnNldCwgMCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ1aWxkZXIgYnVpbGRlclxuICAgICAqIEBwYXJhbSBBcnJheS48ZmxhdGJ1ZmZlcnMuT2Zmc2V0PiBkYXRhXG4gICAgICogQHJldHVybnMgZmxhdGJ1ZmZlcnMuT2Zmc2V0XG4gICAgICovXG4gICAgc3RhdGljIGNyZWF0ZVRlbnNvcnNWZWN0b3IoYnVpbGRlcjogZmxhdGJ1ZmZlcnMuQnVpbGRlciwgZGF0YTogZmxhdGJ1ZmZlcnMuT2Zmc2V0W10pOiBmbGF0YnVmZmVycy5PZmZzZXQge1xuICAgICAgYnVpbGRlci5zdGFydFZlY3Rvcig0LCBkYXRhLmxlbmd0aCwgNCk7XG4gICAgICBmb3IgKGxldCBpID0gZGF0YS5sZW5ndGggLSAxOyBpID49IDA7IGktLSkge1xuICAgICAgICBidWlsZGVyLmFkZE9mZnNldChkYXRhW2ldKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBidWlsZGVyLmVuZFZlY3RvcigpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CdWlsZGVyIGJ1aWxkZXJcbiAgICAgKiBAcGFyYW0gbnVtYmVyIG51bUVsZW1zXG4gICAgICovXG4gICAgc3RhdGljIHN0YXJ0VGVuc29yc1ZlY3RvcihidWlsZGVyOiBmbGF0YnVmZmVycy5CdWlsZGVyLCBudW1FbGVtczogbnVtYmVyKSB7XG4gICAgICBidWlsZGVyLnN0YXJ0VmVjdG9yKDQsIG51bUVsZW1zLCA0KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuQnVpbGRlciBidWlsZGVyXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLk9mZnNldCBncmFwaHNPZmZzZXRcbiAgICAgKi9cbiAgICBzdGF0aWMgYWRkR3JhcGhzKGJ1aWxkZXI6IGZsYXRidWZmZXJzLkJ1aWxkZXIsIGdyYXBoc09mZnNldDogZmxhdGJ1ZmZlcnMuT2Zmc2V0KSB7XG4gICAgICBidWlsZGVyLmFkZEZpZWxkT2Zmc2V0KDEyLCBncmFwaHNPZmZzZXQsIDApO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CdWlsZGVyIGJ1aWxkZXJcbiAgICAgKiBAcGFyYW0gQXJyYXkuPGZsYXRidWZmZXJzLk9mZnNldD4gZGF0YVxuICAgICAqIEByZXR1cm5zIGZsYXRidWZmZXJzLk9mZnNldFxuICAgICAqL1xuICAgIHN0YXRpYyBjcmVhdGVHcmFwaHNWZWN0b3IoYnVpbGRlcjogZmxhdGJ1ZmZlcnMuQnVpbGRlciwgZGF0YTogZmxhdGJ1ZmZlcnMuT2Zmc2V0W10pOiBmbGF0YnVmZmVycy5PZmZzZXQge1xuICAgICAgYnVpbGRlci5zdGFydFZlY3Rvcig0LCBkYXRhLmxlbmd0aCwgNCk7XG4gICAgICBmb3IgKGxldCBpID0gZGF0YS5sZW5ndGggLSAxOyBpID49IDA7IGktLSkge1xuICAgICAgICBidWlsZGVyLmFkZE9mZnNldChkYXRhW2ldKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBidWlsZGVyLmVuZFZlY3RvcigpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CdWlsZGVyIGJ1aWxkZXJcbiAgICAgKiBAcGFyYW0gbnVtYmVyIG51bUVsZW1zXG4gICAgICovXG4gICAgc3RhdGljIHN0YXJ0R3JhcGhzVmVjdG9yKGJ1aWxkZXI6IGZsYXRidWZmZXJzLkJ1aWxkZXIsIG51bUVsZW1zOiBudW1iZXIpIHtcbiAgICAgIGJ1aWxkZXIuc3RhcnRWZWN0b3IoNCwgbnVtRWxlbXMsIDQpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CdWlsZGVyIGJ1aWxkZXJcbiAgICAgKiBAcmV0dXJucyBmbGF0YnVmZmVycy5PZmZzZXRcbiAgICAgKi9cbiAgICBzdGF0aWMgZW5kQXR0cmlidXRlKGJ1aWxkZXI6IGZsYXRidWZmZXJzLkJ1aWxkZXIpOiBmbGF0YnVmZmVycy5PZmZzZXQge1xuICAgICAgbGV0IG9mZnNldCA9IGJ1aWxkZXIuZW5kT2JqZWN0KCk7XG4gICAgICByZXR1cm4gb2Zmc2V0O1xuICAgIH1cblxuICAgIHN0YXRpYyBjcmVhdGVBdHRyaWJ1dGUoXG4gICAgICAgIGJ1aWxkZXI6IGZsYXRidWZmZXJzLkJ1aWxkZXIsIG5hbWVPZmZzZXQ6IGZsYXRidWZmZXJzLk9mZnNldCwgZG9jU3RyaW5nT2Zmc2V0OiBmbGF0YnVmZmVycy5PZmZzZXQsXG4gICAgICAgIHR5cGU6IG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnMuQXR0cmlidXRlVHlwZSwgZjogbnVtYmVyLCBpOiBmbGF0YnVmZmVycy5Mb25nLCBzT2Zmc2V0OiBmbGF0YnVmZmVycy5PZmZzZXQsXG4gICAgICAgIHRPZmZzZXQ6IGZsYXRidWZmZXJzLk9mZnNldCwgZ09mZnNldDogZmxhdGJ1ZmZlcnMuT2Zmc2V0LCBmbG9hdHNPZmZzZXQ6IGZsYXRidWZmZXJzLk9mZnNldCxcbiAgICAgICAgaW50c09mZnNldDogZmxhdGJ1ZmZlcnMuT2Zmc2V0LCBzdHJpbmdzT2Zmc2V0OiBmbGF0YnVmZmVycy5PZmZzZXQsIHRlbnNvcnNPZmZzZXQ6IGZsYXRidWZmZXJzLk9mZnNldCxcbiAgICAgICAgZ3JhcGhzT2Zmc2V0OiBmbGF0YnVmZmVycy5PZmZzZXQpOiBmbGF0YnVmZmVycy5PZmZzZXQge1xuICAgICAgQXR0cmlidXRlLnN0YXJ0QXR0cmlidXRlKGJ1aWxkZXIpO1xuICAgICAgQXR0cmlidXRlLmFkZE5hbWUoYnVpbGRlciwgbmFtZU9mZnNldCk7XG4gICAgICBBdHRyaWJ1dGUuYWRkRG9jU3RyaW5nKGJ1aWxkZXIsIGRvY1N0cmluZ09mZnNldCk7XG4gICAgICBBdHRyaWJ1dGUuYWRkVHlwZShidWlsZGVyLCB0eXBlKTtcbiAgICAgIEF0dHJpYnV0ZS5hZGRGKGJ1aWxkZXIsIGYpO1xuICAgICAgQXR0cmlidXRlLmFkZEkoYnVpbGRlciwgaSk7XG4gICAgICBBdHRyaWJ1dGUuYWRkUyhidWlsZGVyLCBzT2Zmc2V0KTtcbiAgICAgIEF0dHJpYnV0ZS5hZGRUKGJ1aWxkZXIsIHRPZmZzZXQpO1xuICAgICAgQXR0cmlidXRlLmFkZEcoYnVpbGRlciwgZ09mZnNldCk7XG4gICAgICBBdHRyaWJ1dGUuYWRkRmxvYXRzKGJ1aWxkZXIsIGZsb2F0c09mZnNldCk7XG4gICAgICBBdHRyaWJ1dGUuYWRkSW50cyhidWlsZGVyLCBpbnRzT2Zmc2V0KTtcbiAgICAgIEF0dHJpYnV0ZS5hZGRTdHJpbmdzKGJ1aWxkZXIsIHN0cmluZ3NPZmZzZXQpO1xuICAgICAgQXR0cmlidXRlLmFkZFRlbnNvcnMoYnVpbGRlciwgdGVuc29yc09mZnNldCk7XG4gICAgICBBdHRyaWJ1dGUuYWRkR3JhcGhzKGJ1aWxkZXIsIGdyYXBoc09mZnNldCk7XG4gICAgICByZXR1cm4gQXR0cmlidXRlLmVuZEF0dHJpYnV0ZShidWlsZGVyKTtcbiAgICB9XG4gIH1cbn1cbi8qKlxuICogQGNvbnN0cnVjdG9yXG4gKi9cbmV4cG9ydCBuYW1lc3BhY2Ugb25ueHJ1bnRpbWUuZXhwZXJpbWVudGFsLmZicyB7XG4gIGV4cG9ydCBjbGFzcyBHcmFwaCB7XG4gICAgYmI6IGZsYXRidWZmZXJzLkJ5dGVCdWZmZXJ8bnVsbCA9IG51bGw7XG5cbiAgICBiYl9wb3MgPSAwO1xuICAgIC8qKlxuICAgICAqIEBwYXJhbSBudW1iZXIgaVxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CeXRlQnVmZmVyIGJiXG4gICAgICogQHJldHVybnMgR3JhcGhcbiAgICAgKi9cbiAgICBfX2luaXQoaTogbnVtYmVyLCBiYjogZmxhdGJ1ZmZlcnMuQnl0ZUJ1ZmZlcik6IEdyYXBoIHtcbiAgICAgIHRoaXMuYmJfcG9zID0gaTtcbiAgICAgIHRoaXMuYmIgPSBiYjtcbiAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CeXRlQnVmZmVyIGJiXG4gICAgICogQHBhcmFtIEdyYXBoPSBvYmpcbiAgICAgKiBAcmV0dXJucyBHcmFwaFxuICAgICAqL1xuICAgIHN0YXRpYyBnZXRSb290QXNHcmFwaChiYjogZmxhdGJ1ZmZlcnMuQnl0ZUJ1ZmZlciwgb2JqPzogR3JhcGgpOiBHcmFwaCB7XG4gICAgICByZXR1cm4gKG9iaiB8fCBuZXcgR3JhcGgoKSkuX19pbml0KGJiLnJlYWRJbnQzMihiYi5wb3NpdGlvbigpKSArIGJiLnBvc2l0aW9uKCksIGJiKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuQnl0ZUJ1ZmZlciBiYlxuICAgICAqIEBwYXJhbSBHcmFwaD0gb2JqXG4gICAgICogQHJldHVybnMgR3JhcGhcbiAgICAgKi9cbiAgICBzdGF0aWMgZ2V0U2l6ZVByZWZpeGVkUm9vdEFzR3JhcGgoYmI6IGZsYXRidWZmZXJzLkJ5dGVCdWZmZXIsIG9iaj86IEdyYXBoKTogR3JhcGgge1xuICAgICAgYmIuc2V0UG9zaXRpb24oYmIucG9zaXRpb24oKSArIGZsYXRidWZmZXJzLlNJWkVfUFJFRklYX0xFTkdUSCk7XG4gICAgICByZXR1cm4gKG9iaiB8fCBuZXcgR3JhcGgoKSkuX19pbml0KGJiLnJlYWRJbnQzMihiYi5wb3NpdGlvbigpKSArIGJiLnBvc2l0aW9uKCksIGJiKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gbnVtYmVyIGluZGV4XG4gICAgICogQHBhcmFtIG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnMuVGVuc29yPSBvYmpcbiAgICAgKiBAcmV0dXJucyBvbm54cnVudGltZS5leHBlcmltZW50YWwuZmJzLlRlbnNvclxuICAgICAqL1xuICAgIGluaXRpYWxpemVycyhpbmRleDogbnVtYmVyLCBvYmo/OiBvbm54cnVudGltZS5leHBlcmltZW50YWwuZmJzLlRlbnNvcik6IG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnMuVGVuc29yfG51bGwge1xuICAgICAgbGV0IG9mZnNldCA9IHRoaXMuYmIhLl9fb2Zmc2V0KHRoaXMuYmJfcG9zLCA0KTtcbiAgICAgIHJldHVybiBvZmZzZXQgPyAob2JqIHx8IG5ldyBvbm54cnVudGltZS5leHBlcmltZW50YWwuZmJzLlRlbnNvcigpKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAuX19pbml0KHRoaXMuYmIhLl9faW5kaXJlY3QodGhpcy5iYiEuX192ZWN0b3IodGhpcy5iYl9wb3MgKyBvZmZzZXQpICsgaW5kZXggKiA0KSwgdGhpcy5iYiEpIDpcbiAgICAgICAgICAgICAgICAgICAgICBudWxsO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEByZXR1cm5zIG51bWJlclxuICAgICAqL1xuICAgIGluaXRpYWxpemVyc0xlbmd0aCgpOiBudW1iZXIge1xuICAgICAgbGV0IG9mZnNldCA9IHRoaXMuYmIhLl9fb2Zmc2V0KHRoaXMuYmJfcG9zLCA0KTtcbiAgICAgIHJldHVybiBvZmZzZXQgPyB0aGlzLmJiIS5fX3ZlY3Rvcl9sZW4odGhpcy5iYl9wb3MgKyBvZmZzZXQpIDogMDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gbnVtYmVyIGluZGV4XG4gICAgICogQHBhcmFtIG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnMuVmFsdWVJbmZvPSBvYmpcbiAgICAgKiBAcmV0dXJucyBvbm54cnVudGltZS5leHBlcmltZW50YWwuZmJzLlZhbHVlSW5mb1xuICAgICAqL1xuICAgIG5vZGVBcmdzKGluZGV4OiBudW1iZXIsIG9iaj86IG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnMuVmFsdWVJbmZvKTogb25ueHJ1bnRpbWUuZXhwZXJpbWVudGFsLmZicy5WYWx1ZUluZm98bnVsbCB7XG4gICAgICBsZXQgb2Zmc2V0ID0gdGhpcy5iYiEuX19vZmZzZXQodGhpcy5iYl9wb3MsIDYpO1xuICAgICAgcmV0dXJuIG9mZnNldCA/IChvYmogfHwgbmV3IG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnMuVmFsdWVJbmZvKCkpXG4gICAgICAgICAgICAgICAgICAgICAgICAgIC5fX2luaXQodGhpcy5iYiEuX19pbmRpcmVjdCh0aGlzLmJiIS5fX3ZlY3Rvcih0aGlzLmJiX3BvcyArIG9mZnNldCkgKyBpbmRleCAqIDQpLCB0aGlzLmJiISkgOlxuICAgICAgICAgICAgICAgICAgICAgIG51bGw7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHJldHVybnMgbnVtYmVyXG4gICAgICovXG4gICAgbm9kZUFyZ3NMZW5ndGgoKTogbnVtYmVyIHtcbiAgICAgIGxldCBvZmZzZXQgPSB0aGlzLmJiIS5fX29mZnNldCh0aGlzLmJiX3BvcywgNik7XG4gICAgICByZXR1cm4gb2Zmc2V0ID8gdGhpcy5iYiEuX192ZWN0b3JfbGVuKHRoaXMuYmJfcG9zICsgb2Zmc2V0KSA6IDA7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIG51bWJlciBpbmRleFxuICAgICAqIEBwYXJhbSBvbm54cnVudGltZS5leHBlcmltZW50YWwuZmJzLk5vZGU9IG9ialxuICAgICAqIEByZXR1cm5zIG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnMuTm9kZVxuICAgICAqL1xuICAgIG5vZGVzKGluZGV4OiBudW1iZXIsIG9iaj86IG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnMuTm9kZSk6IG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnMuTm9kZXxudWxsIHtcbiAgICAgIGxldCBvZmZzZXQgPSB0aGlzLmJiIS5fX29mZnNldCh0aGlzLmJiX3BvcywgOCk7XG4gICAgICByZXR1cm4gb2Zmc2V0ID8gKG9iaiB8fCBuZXcgb25ueHJ1bnRpbWUuZXhwZXJpbWVudGFsLmZicy5Ob2RlKCkpXG4gICAgICAgICAgICAgICAgICAgICAgICAgIC5fX2luaXQodGhpcy5iYiEuX19pbmRpcmVjdCh0aGlzLmJiIS5fX3ZlY3Rvcih0aGlzLmJiX3BvcyArIG9mZnNldCkgKyBpbmRleCAqIDQpLCB0aGlzLmJiISkgOlxuICAgICAgICAgICAgICAgICAgICAgIG51bGw7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHJldHVybnMgbnVtYmVyXG4gICAgICovXG4gICAgbm9kZXNMZW5ndGgoKTogbnVtYmVyIHtcbiAgICAgIGxldCBvZmZzZXQgPSB0aGlzLmJiIS5fX29mZnNldCh0aGlzLmJiX3BvcywgOCk7XG4gICAgICByZXR1cm4gb2Zmc2V0ID8gdGhpcy5iYiEuX192ZWN0b3JfbGVuKHRoaXMuYmJfcG9zICsgb2Zmc2V0KSA6IDA7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHJldHVybnMgbnVtYmVyXG4gICAgICovXG4gICAgbWF4Tm9kZUluZGV4KCk6IG51bWJlciB7XG4gICAgICBsZXQgb2Zmc2V0ID0gdGhpcy5iYiEuX19vZmZzZXQodGhpcy5iYl9wb3MsIDEwKTtcbiAgICAgIHJldHVybiBvZmZzZXQgPyB0aGlzLmJiIS5yZWFkVWludDMyKHRoaXMuYmJfcG9zICsgb2Zmc2V0KSA6IDA7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIG51bWJlciBpbmRleFxuICAgICAqIEBwYXJhbSBvbm54cnVudGltZS5leHBlcmltZW50YWwuZmJzLk5vZGVFZGdlPSBvYmpcbiAgICAgKiBAcmV0dXJucyBvbm54cnVudGltZS5leHBlcmltZW50YWwuZmJzLk5vZGVFZGdlXG4gICAgICovXG4gICAgbm9kZUVkZ2VzKGluZGV4OiBudW1iZXIsIG9iaj86IG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnMuTm9kZUVkZ2UpOiBvbm54cnVudGltZS5leHBlcmltZW50YWwuZmJzLk5vZGVFZGdlfG51bGwge1xuICAgICAgbGV0IG9mZnNldCA9IHRoaXMuYmIhLl9fb2Zmc2V0KHRoaXMuYmJfcG9zLCAxMik7XG4gICAgICByZXR1cm4gb2Zmc2V0ID8gKG9iaiB8fCBuZXcgb25ueHJ1bnRpbWUuZXhwZXJpbWVudGFsLmZicy5Ob2RlRWRnZSgpKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAuX19pbml0KHRoaXMuYmIhLl9faW5kaXJlY3QodGhpcy5iYiEuX192ZWN0b3IodGhpcy5iYl9wb3MgKyBvZmZzZXQpICsgaW5kZXggKiA0KSwgdGhpcy5iYiEpIDpcbiAgICAgICAgICAgICAgICAgICAgICBudWxsO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEByZXR1cm5zIG51bWJlclxuICAgICAqL1xuICAgIG5vZGVFZGdlc0xlbmd0aCgpOiBudW1iZXIge1xuICAgICAgbGV0IG9mZnNldCA9IHRoaXMuYmIhLl9fb2Zmc2V0KHRoaXMuYmJfcG9zLCAxMik7XG4gICAgICByZXR1cm4gb2Zmc2V0ID8gdGhpcy5iYiEuX192ZWN0b3JfbGVuKHRoaXMuYmJfcG9zICsgb2Zmc2V0KSA6IDA7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIG51bWJlciBpbmRleFxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5FbmNvZGluZz0gb3B0aW9uYWxFbmNvZGluZ1xuICAgICAqIEByZXR1cm5zIHN0cmluZ3xVaW50OEFycmF5XG4gICAgICovXG4gICAgaW5wdXRzKGluZGV4OiBudW1iZXIpOiBzdHJpbmc7XG4gICAgaW5wdXRzKGluZGV4OiBudW1iZXIsIG9wdGlvbmFsRW5jb2Rpbmc6IGZsYXRidWZmZXJzLkVuY29kaW5nKTogc3RyaW5nfFVpbnQ4QXJyYXk7XG4gICAgaW5wdXRzKGluZGV4OiBudW1iZXIsIG9wdGlvbmFsRW5jb2Rpbmc/OiBhbnkpOiBzdHJpbmd8VWludDhBcnJheXxudWxsIHtcbiAgICAgIGxldCBvZmZzZXQgPSB0aGlzLmJiIS5fX29mZnNldCh0aGlzLmJiX3BvcywgMTQpO1xuICAgICAgcmV0dXJuIG9mZnNldCA/IHRoaXMuYmIhLl9fc3RyaW5nKHRoaXMuYmIhLl9fdmVjdG9yKHRoaXMuYmJfcG9zICsgb2Zmc2V0KSArIGluZGV4ICogNCwgb3B0aW9uYWxFbmNvZGluZykgOiBudWxsO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEByZXR1cm5zIG51bWJlclxuICAgICAqL1xuICAgIGlucHV0c0xlbmd0aCgpOiBudW1iZXIge1xuICAgICAgbGV0IG9mZnNldCA9IHRoaXMuYmIhLl9fb2Zmc2V0KHRoaXMuYmJfcG9zLCAxNCk7XG4gICAgICByZXR1cm4gb2Zmc2V0ID8gdGhpcy5iYiEuX192ZWN0b3JfbGVuKHRoaXMuYmJfcG9zICsgb2Zmc2V0KSA6IDA7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIG51bWJlciBpbmRleFxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5FbmNvZGluZz0gb3B0aW9uYWxFbmNvZGluZ1xuICAgICAqIEByZXR1cm5zIHN0cmluZ3xVaW50OEFycmF5XG4gICAgICovXG4gICAgb3V0cHV0cyhpbmRleDogbnVtYmVyKTogc3RyaW5nO1xuICAgIG91dHB1dHMoaW5kZXg6IG51bWJlciwgb3B0aW9uYWxFbmNvZGluZzogZmxhdGJ1ZmZlcnMuRW5jb2RpbmcpOiBzdHJpbmd8VWludDhBcnJheTtcbiAgICBvdXRwdXRzKGluZGV4OiBudW1iZXIsIG9wdGlvbmFsRW5jb2Rpbmc/OiBhbnkpOiBzdHJpbmd8VWludDhBcnJheXxudWxsIHtcbiAgICAgIGxldCBvZmZzZXQgPSB0aGlzLmJiIS5fX29mZnNldCh0aGlzLmJiX3BvcywgMTYpO1xuICAgICAgcmV0dXJuIG9mZnNldCA/IHRoaXMuYmIhLl9fc3RyaW5nKHRoaXMuYmIhLl9fdmVjdG9yKHRoaXMuYmJfcG9zICsgb2Zmc2V0KSArIGluZGV4ICogNCwgb3B0aW9uYWxFbmNvZGluZykgOiBudWxsO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEByZXR1cm5zIG51bWJlclxuICAgICAqL1xuICAgIG91dHB1dHNMZW5ndGgoKTogbnVtYmVyIHtcbiAgICAgIGxldCBvZmZzZXQgPSB0aGlzLmJiIS5fX29mZnNldCh0aGlzLmJiX3BvcywgMTYpO1xuICAgICAgcmV0dXJuIG9mZnNldCA/IHRoaXMuYmIhLl9fdmVjdG9yX2xlbih0aGlzLmJiX3BvcyArIG9mZnNldCkgOiAwO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBudW1iZXIgaW5kZXhcbiAgICAgKiBAcGFyYW0gb25ueHJ1bnRpbWUuZXhwZXJpbWVudGFsLmZicy5TcGFyc2VUZW5zb3I9IG9ialxuICAgICAqIEByZXR1cm5zIG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnMuU3BhcnNlVGVuc29yXG4gICAgICovXG4gICAgc3BhcnNlSW5pdGlhbGl6ZXJzKGluZGV4OiBudW1iZXIsIG9iaj86IG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnMuU3BhcnNlVGVuc29yKTpcbiAgICAgICAgb25ueHJ1bnRpbWUuZXhwZXJpbWVudGFsLmZicy5TcGFyc2VUZW5zb3J8bnVsbCB7XG4gICAgICBsZXQgb2Zmc2V0ID0gdGhpcy5iYiEuX19vZmZzZXQodGhpcy5iYl9wb3MsIDE4KTtcbiAgICAgIHJldHVybiBvZmZzZXQgPyAob2JqIHx8IG5ldyBvbm54cnVudGltZS5leHBlcmltZW50YWwuZmJzLlNwYXJzZVRlbnNvcigpKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAuX19pbml0KHRoaXMuYmIhLl9faW5kaXJlY3QodGhpcy5iYiEuX192ZWN0b3IodGhpcy5iYl9wb3MgKyBvZmZzZXQpICsgaW5kZXggKiA0KSwgdGhpcy5iYiEpIDpcbiAgICAgICAgICAgICAgICAgICAgICBudWxsO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEByZXR1cm5zIG51bWJlclxuICAgICAqL1xuICAgIHNwYXJzZUluaXRpYWxpemVyc0xlbmd0aCgpOiBudW1iZXIge1xuICAgICAgbGV0IG9mZnNldCA9IHRoaXMuYmIhLl9fb2Zmc2V0KHRoaXMuYmJfcG9zLCAxOCk7XG4gICAgICByZXR1cm4gb2Zmc2V0ID8gdGhpcy5iYiEuX192ZWN0b3JfbGVuKHRoaXMuYmJfcG9zICsgb2Zmc2V0KSA6IDA7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ1aWxkZXIgYnVpbGRlclxuICAgICAqL1xuICAgIHN0YXRpYyBzdGFydEdyYXBoKGJ1aWxkZXI6IGZsYXRidWZmZXJzLkJ1aWxkZXIpIHtcbiAgICAgIGJ1aWxkZXIuc3RhcnRPYmplY3QoOCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ1aWxkZXIgYnVpbGRlclxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5PZmZzZXQgaW5pdGlhbGl6ZXJzT2Zmc2V0XG4gICAgICovXG4gICAgc3RhdGljIGFkZEluaXRpYWxpemVycyhidWlsZGVyOiBmbGF0YnVmZmVycy5CdWlsZGVyLCBpbml0aWFsaXplcnNPZmZzZXQ6IGZsYXRidWZmZXJzLk9mZnNldCkge1xuICAgICAgYnVpbGRlci5hZGRGaWVsZE9mZnNldCgwLCBpbml0aWFsaXplcnNPZmZzZXQsIDApO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CdWlsZGVyIGJ1aWxkZXJcbiAgICAgKiBAcGFyYW0gQXJyYXkuPGZsYXRidWZmZXJzLk9mZnNldD4gZGF0YVxuICAgICAqIEByZXR1cm5zIGZsYXRidWZmZXJzLk9mZnNldFxuICAgICAqL1xuICAgIHN0YXRpYyBjcmVhdGVJbml0aWFsaXplcnNWZWN0b3IoYnVpbGRlcjogZmxhdGJ1ZmZlcnMuQnVpbGRlciwgZGF0YTogZmxhdGJ1ZmZlcnMuT2Zmc2V0W10pOiBmbGF0YnVmZmVycy5PZmZzZXQge1xuICAgICAgYnVpbGRlci5zdGFydFZlY3Rvcig0LCBkYXRhLmxlbmd0aCwgNCk7XG4gICAgICBmb3IgKGxldCBpID0gZGF0YS5sZW5ndGggLSAxOyBpID49IDA7IGktLSkge1xuICAgICAgICBidWlsZGVyLmFkZE9mZnNldChkYXRhW2ldKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBidWlsZGVyLmVuZFZlY3RvcigpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CdWlsZGVyIGJ1aWxkZXJcbiAgICAgKiBAcGFyYW0gbnVtYmVyIG51bUVsZW1zXG4gICAgICovXG4gICAgc3RhdGljIHN0YXJ0SW5pdGlhbGl6ZXJzVmVjdG9yKGJ1aWxkZXI6IGZsYXRidWZmZXJzLkJ1aWxkZXIsIG51bUVsZW1zOiBudW1iZXIpIHtcbiAgICAgIGJ1aWxkZXIuc3RhcnRWZWN0b3IoNCwgbnVtRWxlbXMsIDQpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CdWlsZGVyIGJ1aWxkZXJcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuT2Zmc2V0IG5vZGVBcmdzT2Zmc2V0XG4gICAgICovXG4gICAgc3RhdGljIGFkZE5vZGVBcmdzKGJ1aWxkZXI6IGZsYXRidWZmZXJzLkJ1aWxkZXIsIG5vZGVBcmdzT2Zmc2V0OiBmbGF0YnVmZmVycy5PZmZzZXQpIHtcbiAgICAgIGJ1aWxkZXIuYWRkRmllbGRPZmZzZXQoMSwgbm9kZUFyZ3NPZmZzZXQsIDApO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CdWlsZGVyIGJ1aWxkZXJcbiAgICAgKiBAcGFyYW0gQXJyYXkuPGZsYXRidWZmZXJzLk9mZnNldD4gZGF0YVxuICAgICAqIEByZXR1cm5zIGZsYXRidWZmZXJzLk9mZnNldFxuICAgICAqL1xuICAgIHN0YXRpYyBjcmVhdGVOb2RlQXJnc1ZlY3RvcihidWlsZGVyOiBmbGF0YnVmZmVycy5CdWlsZGVyLCBkYXRhOiBmbGF0YnVmZmVycy5PZmZzZXRbXSk6IGZsYXRidWZmZXJzLk9mZnNldCB7XG4gICAgICBidWlsZGVyLnN0YXJ0VmVjdG9yKDQsIGRhdGEubGVuZ3RoLCA0KTtcbiAgICAgIGZvciAobGV0IGkgPSBkYXRhLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSB7XG4gICAgICAgIGJ1aWxkZXIuYWRkT2Zmc2V0KGRhdGFbaV0pO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGJ1aWxkZXIuZW5kVmVjdG9yKCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ1aWxkZXIgYnVpbGRlclxuICAgICAqIEBwYXJhbSBudW1iZXIgbnVtRWxlbXNcbiAgICAgKi9cbiAgICBzdGF0aWMgc3RhcnROb2RlQXJnc1ZlY3RvcihidWlsZGVyOiBmbGF0YnVmZmVycy5CdWlsZGVyLCBudW1FbGVtczogbnVtYmVyKSB7XG4gICAgICBidWlsZGVyLnN0YXJ0VmVjdG9yKDQsIG51bUVsZW1zLCA0KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuQnVpbGRlciBidWlsZGVyXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLk9mZnNldCBub2Rlc09mZnNldFxuICAgICAqL1xuICAgIHN0YXRpYyBhZGROb2RlcyhidWlsZGVyOiBmbGF0YnVmZmVycy5CdWlsZGVyLCBub2Rlc09mZnNldDogZmxhdGJ1ZmZlcnMuT2Zmc2V0KSB7XG4gICAgICBidWlsZGVyLmFkZEZpZWxkT2Zmc2V0KDIsIG5vZGVzT2Zmc2V0LCAwKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuQnVpbGRlciBidWlsZGVyXG4gICAgICogQHBhcmFtIEFycmF5LjxmbGF0YnVmZmVycy5PZmZzZXQ+IGRhdGFcbiAgICAgKiBAcmV0dXJucyBmbGF0YnVmZmVycy5PZmZzZXRcbiAgICAgKi9cbiAgICBzdGF0aWMgY3JlYXRlTm9kZXNWZWN0b3IoYnVpbGRlcjogZmxhdGJ1ZmZlcnMuQnVpbGRlciwgZGF0YTogZmxhdGJ1ZmZlcnMuT2Zmc2V0W10pOiBmbGF0YnVmZmVycy5PZmZzZXQge1xuICAgICAgYnVpbGRlci5zdGFydFZlY3Rvcig0LCBkYXRhLmxlbmd0aCwgNCk7XG4gICAgICBmb3IgKGxldCBpID0gZGF0YS5sZW5ndGggLSAxOyBpID49IDA7IGktLSkge1xuICAgICAgICBidWlsZGVyLmFkZE9mZnNldChkYXRhW2ldKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBidWlsZGVyLmVuZFZlY3RvcigpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CdWlsZGVyIGJ1aWxkZXJcbiAgICAgKiBAcGFyYW0gbnVtYmVyIG51bUVsZW1zXG4gICAgICovXG4gICAgc3RhdGljIHN0YXJ0Tm9kZXNWZWN0b3IoYnVpbGRlcjogZmxhdGJ1ZmZlcnMuQnVpbGRlciwgbnVtRWxlbXM6IG51bWJlcikge1xuICAgICAgYnVpbGRlci5zdGFydFZlY3Rvcig0LCBudW1FbGVtcywgNCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ1aWxkZXIgYnVpbGRlclxuICAgICAqIEBwYXJhbSBudW1iZXIgbWF4Tm9kZUluZGV4XG4gICAgICovXG4gICAgc3RhdGljIGFkZE1heE5vZGVJbmRleChidWlsZGVyOiBmbGF0YnVmZmVycy5CdWlsZGVyLCBtYXhOb2RlSW5kZXg6IG51bWJlcikge1xuICAgICAgYnVpbGRlci5hZGRGaWVsZEludDMyKDMsIG1heE5vZGVJbmRleCwgMCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ1aWxkZXIgYnVpbGRlclxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5PZmZzZXQgbm9kZUVkZ2VzT2Zmc2V0XG4gICAgICovXG4gICAgc3RhdGljIGFkZE5vZGVFZGdlcyhidWlsZGVyOiBmbGF0YnVmZmVycy5CdWlsZGVyLCBub2RlRWRnZXNPZmZzZXQ6IGZsYXRidWZmZXJzLk9mZnNldCkge1xuICAgICAgYnVpbGRlci5hZGRGaWVsZE9mZnNldCg0LCBub2RlRWRnZXNPZmZzZXQsIDApO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CdWlsZGVyIGJ1aWxkZXJcbiAgICAgKiBAcGFyYW0gQXJyYXkuPGZsYXRidWZmZXJzLk9mZnNldD4gZGF0YVxuICAgICAqIEByZXR1cm5zIGZsYXRidWZmZXJzLk9mZnNldFxuICAgICAqL1xuICAgIHN0YXRpYyBjcmVhdGVOb2RlRWRnZXNWZWN0b3IoYnVpbGRlcjogZmxhdGJ1ZmZlcnMuQnVpbGRlciwgZGF0YTogZmxhdGJ1ZmZlcnMuT2Zmc2V0W10pOiBmbGF0YnVmZmVycy5PZmZzZXQge1xuICAgICAgYnVpbGRlci5zdGFydFZlY3Rvcig0LCBkYXRhLmxlbmd0aCwgNCk7XG4gICAgICBmb3IgKGxldCBpID0gZGF0YS5sZW5ndGggLSAxOyBpID49IDA7IGktLSkge1xuICAgICAgICBidWlsZGVyLmFkZE9mZnNldChkYXRhW2ldKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBidWlsZGVyLmVuZFZlY3RvcigpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CdWlsZGVyIGJ1aWxkZXJcbiAgICAgKiBAcGFyYW0gbnVtYmVyIG51bUVsZW1zXG4gICAgICovXG4gICAgc3RhdGljIHN0YXJ0Tm9kZUVkZ2VzVmVjdG9yKGJ1aWxkZXI6IGZsYXRidWZmZXJzLkJ1aWxkZXIsIG51bUVsZW1zOiBudW1iZXIpIHtcbiAgICAgIGJ1aWxkZXIuc3RhcnRWZWN0b3IoNCwgbnVtRWxlbXMsIDQpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CdWlsZGVyIGJ1aWxkZXJcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuT2Zmc2V0IGlucHV0c09mZnNldFxuICAgICAqL1xuICAgIHN0YXRpYyBhZGRJbnB1dHMoYnVpbGRlcjogZmxhdGJ1ZmZlcnMuQnVpbGRlciwgaW5wdXRzT2Zmc2V0OiBmbGF0YnVmZmVycy5PZmZzZXQpIHtcbiAgICAgIGJ1aWxkZXIuYWRkRmllbGRPZmZzZXQoNSwgaW5wdXRzT2Zmc2V0LCAwKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuQnVpbGRlciBidWlsZGVyXG4gICAgICogQHBhcmFtIEFycmF5LjxmbGF0YnVmZmVycy5PZmZzZXQ+IGRhdGFcbiAgICAgKiBAcmV0dXJucyBmbGF0YnVmZmVycy5PZmZzZXRcbiAgICAgKi9cbiAgICBzdGF0aWMgY3JlYXRlSW5wdXRzVmVjdG9yKGJ1aWxkZXI6IGZsYXRidWZmZXJzLkJ1aWxkZXIsIGRhdGE6IGZsYXRidWZmZXJzLk9mZnNldFtdKTogZmxhdGJ1ZmZlcnMuT2Zmc2V0IHtcbiAgICAgIGJ1aWxkZXIuc3RhcnRWZWN0b3IoNCwgZGF0YS5sZW5ndGgsIDQpO1xuICAgICAgZm9yIChsZXQgaSA9IGRhdGEubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICAgICAgYnVpbGRlci5hZGRPZmZzZXQoZGF0YVtpXSk7XG4gICAgICB9XG4gICAgICByZXR1cm4gYnVpbGRlci5lbmRWZWN0b3IoKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuQnVpbGRlciBidWlsZGVyXG4gICAgICogQHBhcmFtIG51bWJlciBudW1FbGVtc1xuICAgICAqL1xuICAgIHN0YXRpYyBzdGFydElucHV0c1ZlY3RvcihidWlsZGVyOiBmbGF0YnVmZmVycy5CdWlsZGVyLCBudW1FbGVtczogbnVtYmVyKSB7XG4gICAgICBidWlsZGVyLnN0YXJ0VmVjdG9yKDQsIG51bUVsZW1zLCA0KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuQnVpbGRlciBidWlsZGVyXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLk9mZnNldCBvdXRwdXRzT2Zmc2V0XG4gICAgICovXG4gICAgc3RhdGljIGFkZE91dHB1dHMoYnVpbGRlcjogZmxhdGJ1ZmZlcnMuQnVpbGRlciwgb3V0cHV0c09mZnNldDogZmxhdGJ1ZmZlcnMuT2Zmc2V0KSB7XG4gICAgICBidWlsZGVyLmFkZEZpZWxkT2Zmc2V0KDYsIG91dHB1dHNPZmZzZXQsIDApO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CdWlsZGVyIGJ1aWxkZXJcbiAgICAgKiBAcGFyYW0gQXJyYXkuPGZsYXRidWZmZXJzLk9mZnNldD4gZGF0YVxuICAgICAqIEByZXR1cm5zIGZsYXRidWZmZXJzLk9mZnNldFxuICAgICAqL1xuICAgIHN0YXRpYyBjcmVhdGVPdXRwdXRzVmVjdG9yKGJ1aWxkZXI6IGZsYXRidWZmZXJzLkJ1aWxkZXIsIGRhdGE6IGZsYXRidWZmZXJzLk9mZnNldFtdKTogZmxhdGJ1ZmZlcnMuT2Zmc2V0IHtcbiAgICAgIGJ1aWxkZXIuc3RhcnRWZWN0b3IoNCwgZGF0YS5sZW5ndGgsIDQpO1xuICAgICAgZm9yIChsZXQgaSA9IGRhdGEubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICAgICAgYnVpbGRlci5hZGRPZmZzZXQoZGF0YVtpXSk7XG4gICAgICB9XG4gICAgICByZXR1cm4gYnVpbGRlci5lbmRWZWN0b3IoKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuQnVpbGRlciBidWlsZGVyXG4gICAgICogQHBhcmFtIG51bWJlciBudW1FbGVtc1xuICAgICAqL1xuICAgIHN0YXRpYyBzdGFydE91dHB1dHNWZWN0b3IoYnVpbGRlcjogZmxhdGJ1ZmZlcnMuQnVpbGRlciwgbnVtRWxlbXM6IG51bWJlcikge1xuICAgICAgYnVpbGRlci5zdGFydFZlY3Rvcig0LCBudW1FbGVtcywgNCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ1aWxkZXIgYnVpbGRlclxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5PZmZzZXQgc3BhcnNlSW5pdGlhbGl6ZXJzT2Zmc2V0XG4gICAgICovXG4gICAgc3RhdGljIGFkZFNwYXJzZUluaXRpYWxpemVycyhidWlsZGVyOiBmbGF0YnVmZmVycy5CdWlsZGVyLCBzcGFyc2VJbml0aWFsaXplcnNPZmZzZXQ6IGZsYXRidWZmZXJzLk9mZnNldCkge1xuICAgICAgYnVpbGRlci5hZGRGaWVsZE9mZnNldCg3LCBzcGFyc2VJbml0aWFsaXplcnNPZmZzZXQsIDApO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CdWlsZGVyIGJ1aWxkZXJcbiAgICAgKiBAcGFyYW0gQXJyYXkuPGZsYXRidWZmZXJzLk9mZnNldD4gZGF0YVxuICAgICAqIEByZXR1cm5zIGZsYXRidWZmZXJzLk9mZnNldFxuICAgICAqL1xuICAgIHN0YXRpYyBjcmVhdGVTcGFyc2VJbml0aWFsaXplcnNWZWN0b3IoYnVpbGRlcjogZmxhdGJ1ZmZlcnMuQnVpbGRlciwgZGF0YTogZmxhdGJ1ZmZlcnMuT2Zmc2V0W10pOlxuICAgICAgICBmbGF0YnVmZmVycy5PZmZzZXQge1xuICAgICAgYnVpbGRlci5zdGFydFZlY3Rvcig0LCBkYXRhLmxlbmd0aCwgNCk7XG4gICAgICBmb3IgKGxldCBpID0gZGF0YS5sZW5ndGggLSAxOyBpID49IDA7IGktLSkge1xuICAgICAgICBidWlsZGVyLmFkZE9mZnNldChkYXRhW2ldKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBidWlsZGVyLmVuZFZlY3RvcigpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CdWlsZGVyIGJ1aWxkZXJcbiAgICAgKiBAcGFyYW0gbnVtYmVyIG51bUVsZW1zXG4gICAgICovXG4gICAgc3RhdGljIHN0YXJ0U3BhcnNlSW5pdGlhbGl6ZXJzVmVjdG9yKGJ1aWxkZXI6IGZsYXRidWZmZXJzLkJ1aWxkZXIsIG51bUVsZW1zOiBudW1iZXIpIHtcbiAgICAgIGJ1aWxkZXIuc3RhcnRWZWN0b3IoNCwgbnVtRWxlbXMsIDQpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CdWlsZGVyIGJ1aWxkZXJcbiAgICAgKiBAcmV0dXJucyBmbGF0YnVmZmVycy5PZmZzZXRcbiAgICAgKi9cbiAgICBzdGF0aWMgZW5kR3JhcGgoYnVpbGRlcjogZmxhdGJ1ZmZlcnMuQnVpbGRlcik6IGZsYXRidWZmZXJzLk9mZnNldCB7XG4gICAgICBsZXQgb2Zmc2V0ID0gYnVpbGRlci5lbmRPYmplY3QoKTtcbiAgICAgIHJldHVybiBvZmZzZXQ7XG4gICAgfVxuXG4gICAgc3RhdGljIGNyZWF0ZUdyYXBoKFxuICAgICAgICBidWlsZGVyOiBmbGF0YnVmZmVycy5CdWlsZGVyLCBpbml0aWFsaXplcnNPZmZzZXQ6IGZsYXRidWZmZXJzLk9mZnNldCwgbm9kZUFyZ3NPZmZzZXQ6IGZsYXRidWZmZXJzLk9mZnNldCxcbiAgICAgICAgbm9kZXNPZmZzZXQ6IGZsYXRidWZmZXJzLk9mZnNldCwgbWF4Tm9kZUluZGV4OiBudW1iZXIsIG5vZGVFZGdlc09mZnNldDogZmxhdGJ1ZmZlcnMuT2Zmc2V0LFxuICAgICAgICBpbnB1dHNPZmZzZXQ6IGZsYXRidWZmZXJzLk9mZnNldCwgb3V0cHV0c09mZnNldDogZmxhdGJ1ZmZlcnMuT2Zmc2V0LFxuICAgICAgICBzcGFyc2VJbml0aWFsaXplcnNPZmZzZXQ6IGZsYXRidWZmZXJzLk9mZnNldCk6IGZsYXRidWZmZXJzLk9mZnNldCB7XG4gICAgICBHcmFwaC5zdGFydEdyYXBoKGJ1aWxkZXIpO1xuICAgICAgR3JhcGguYWRkSW5pdGlhbGl6ZXJzKGJ1aWxkZXIsIGluaXRpYWxpemVyc09mZnNldCk7XG4gICAgICBHcmFwaC5hZGROb2RlQXJncyhidWlsZGVyLCBub2RlQXJnc09mZnNldCk7XG4gICAgICBHcmFwaC5hZGROb2RlcyhidWlsZGVyLCBub2Rlc09mZnNldCk7XG4gICAgICBHcmFwaC5hZGRNYXhOb2RlSW5kZXgoYnVpbGRlciwgbWF4Tm9kZUluZGV4KTtcbiAgICAgIEdyYXBoLmFkZE5vZGVFZGdlcyhidWlsZGVyLCBub2RlRWRnZXNPZmZzZXQpO1xuICAgICAgR3JhcGguYWRkSW5wdXRzKGJ1aWxkZXIsIGlucHV0c09mZnNldCk7XG4gICAgICBHcmFwaC5hZGRPdXRwdXRzKGJ1aWxkZXIsIG91dHB1dHNPZmZzZXQpO1xuICAgICAgR3JhcGguYWRkU3BhcnNlSW5pdGlhbGl6ZXJzKGJ1aWxkZXIsIHNwYXJzZUluaXRpYWxpemVyc09mZnNldCk7XG4gICAgICByZXR1cm4gR3JhcGguZW5kR3JhcGgoYnVpbGRlcik7XG4gICAgfVxuICB9XG59XG4vKipcbiAqIEBjb25zdHJ1Y3RvclxuICovXG5leHBvcnQgbmFtZXNwYWNlIG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnMge1xuICBleHBvcnQgY2xhc3MgTW9kZWwge1xuICAgIGJiOiBmbGF0YnVmZmVycy5CeXRlQnVmZmVyfG51bGwgPSBudWxsO1xuXG4gICAgYmJfcG9zID0gMDtcbiAgICAvKipcbiAgICAgKiBAcGFyYW0gbnVtYmVyIGlcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuQnl0ZUJ1ZmZlciBiYlxuICAgICAqIEByZXR1cm5zIE1vZGVsXG4gICAgICovXG4gICAgX19pbml0KGk6IG51bWJlciwgYmI6IGZsYXRidWZmZXJzLkJ5dGVCdWZmZXIpOiBNb2RlbCB7XG4gICAgICB0aGlzLmJiX3BvcyA9IGk7XG4gICAgICB0aGlzLmJiID0gYmI7XG4gICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuQnl0ZUJ1ZmZlciBiYlxuICAgICAqIEBwYXJhbSBNb2RlbD0gb2JqXG4gICAgICogQHJldHVybnMgTW9kZWxcbiAgICAgKi9cbiAgICBzdGF0aWMgZ2V0Um9vdEFzTW9kZWwoYmI6IGZsYXRidWZmZXJzLkJ5dGVCdWZmZXIsIG9iaj86IE1vZGVsKTogTW9kZWwge1xuICAgICAgcmV0dXJuIChvYmogfHwgbmV3IE1vZGVsKCkpLl9faW5pdChiYi5yZWFkSW50MzIoYmIucG9zaXRpb24oKSkgKyBiYi5wb3NpdGlvbigpLCBiYik7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ5dGVCdWZmZXIgYmJcbiAgICAgKiBAcGFyYW0gTW9kZWw9IG9ialxuICAgICAqIEByZXR1cm5zIE1vZGVsXG4gICAgICovXG4gICAgc3RhdGljIGdldFNpemVQcmVmaXhlZFJvb3RBc01vZGVsKGJiOiBmbGF0YnVmZmVycy5CeXRlQnVmZmVyLCBvYmo/OiBNb2RlbCk6IE1vZGVsIHtcbiAgICAgIGJiLnNldFBvc2l0aW9uKGJiLnBvc2l0aW9uKCkgKyBmbGF0YnVmZmVycy5TSVpFX1BSRUZJWF9MRU5HVEgpO1xuICAgICAgcmV0dXJuIChvYmogfHwgbmV3IE1vZGVsKCkpLl9faW5pdChiYi5yZWFkSW50MzIoYmIucG9zaXRpb24oKSkgKyBiYi5wb3NpdGlvbigpLCBiYik7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHJldHVybnMgZmxhdGJ1ZmZlcnMuTG9uZ1xuICAgICAqL1xuICAgIGlyVmVyc2lvbigpOiBmbGF0YnVmZmVycy5Mb25nIHtcbiAgICAgIGxldCBvZmZzZXQgPSB0aGlzLmJiIS5fX29mZnNldCh0aGlzLmJiX3BvcywgNCk7XG4gICAgICByZXR1cm4gb2Zmc2V0ID8gdGhpcy5iYiEucmVhZEludDY0KHRoaXMuYmJfcG9zICsgb2Zmc2V0KSA6IHRoaXMuYmIhLmNyZWF0ZUxvbmcoMCwgMCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIG51bWJlciBpbmRleFxuICAgICAqIEBwYXJhbSBvbm54cnVudGltZS5leHBlcmltZW50YWwuZmJzLk9wZXJhdG9yU2V0SWQ9IG9ialxuICAgICAqIEByZXR1cm5zIG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnMuT3BlcmF0b3JTZXRJZFxuICAgICAqL1xuICAgIG9wc2V0SW1wb3J0KGluZGV4OiBudW1iZXIsIG9iaj86IG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnMuT3BlcmF0b3JTZXRJZCk6XG4gICAgICAgIG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnMuT3BlcmF0b3JTZXRJZHxudWxsIHtcbiAgICAgIGxldCBvZmZzZXQgPSB0aGlzLmJiIS5fX29mZnNldCh0aGlzLmJiX3BvcywgNik7XG4gICAgICByZXR1cm4gb2Zmc2V0ID8gKG9iaiB8fCBuZXcgb25ueHJ1bnRpbWUuZXhwZXJpbWVudGFsLmZicy5PcGVyYXRvclNldElkKCkpXG4gICAgICAgICAgICAgICAgICAgICAgICAgIC5fX2luaXQodGhpcy5iYiEuX19pbmRpcmVjdCh0aGlzLmJiIS5fX3ZlY3Rvcih0aGlzLmJiX3BvcyArIG9mZnNldCkgKyBpbmRleCAqIDQpLCB0aGlzLmJiISkgOlxuICAgICAgICAgICAgICAgICAgICAgIG51bGw7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHJldHVybnMgbnVtYmVyXG4gICAgICovXG4gICAgb3BzZXRJbXBvcnRMZW5ndGgoKTogbnVtYmVyIHtcbiAgICAgIGxldCBvZmZzZXQgPSB0aGlzLmJiIS5fX29mZnNldCh0aGlzLmJiX3BvcywgNik7XG4gICAgICByZXR1cm4gb2Zmc2V0ID8gdGhpcy5iYiEuX192ZWN0b3JfbGVuKHRoaXMuYmJfcG9zICsgb2Zmc2V0KSA6IDA7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkVuY29kaW5nPSBvcHRpb25hbEVuY29kaW5nXG4gICAgICogQHJldHVybnMgc3RyaW5nfFVpbnQ4QXJyYXl8bnVsbFxuICAgICAqL1xuICAgIHByb2R1Y2VyTmFtZSgpOiBzdHJpbmd8bnVsbDtcbiAgICBwcm9kdWNlck5hbWUob3B0aW9uYWxFbmNvZGluZzogZmxhdGJ1ZmZlcnMuRW5jb2RpbmcpOiBzdHJpbmd8VWludDhBcnJheXxudWxsO1xuICAgIHByb2R1Y2VyTmFtZShvcHRpb25hbEVuY29kaW5nPzogYW55KTogc3RyaW5nfFVpbnQ4QXJyYXl8bnVsbCB7XG4gICAgICBsZXQgb2Zmc2V0ID0gdGhpcy5iYiEuX19vZmZzZXQodGhpcy5iYl9wb3MsIDgpO1xuICAgICAgcmV0dXJuIG9mZnNldCA/IHRoaXMuYmIhLl9fc3RyaW5nKHRoaXMuYmJfcG9zICsgb2Zmc2V0LCBvcHRpb25hbEVuY29kaW5nKSA6IG51bGw7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkVuY29kaW5nPSBvcHRpb25hbEVuY29kaW5nXG4gICAgICogQHJldHVybnMgc3RyaW5nfFVpbnQ4QXJyYXl8bnVsbFxuICAgICAqL1xuICAgIHByb2R1Y2VyVmVyc2lvbigpOiBzdHJpbmd8bnVsbDtcbiAgICBwcm9kdWNlclZlcnNpb24ob3B0aW9uYWxFbmNvZGluZzogZmxhdGJ1ZmZlcnMuRW5jb2RpbmcpOiBzdHJpbmd8VWludDhBcnJheXxudWxsO1xuICAgIHByb2R1Y2VyVmVyc2lvbihvcHRpb25hbEVuY29kaW5nPzogYW55KTogc3RyaW5nfFVpbnQ4QXJyYXl8bnVsbCB7XG4gICAgICBsZXQgb2Zmc2V0ID0gdGhpcy5iYiEuX19vZmZzZXQodGhpcy5iYl9wb3MsIDEwKTtcbiAgICAgIHJldHVybiBvZmZzZXQgPyB0aGlzLmJiIS5fX3N0cmluZyh0aGlzLmJiX3BvcyArIG9mZnNldCwgb3B0aW9uYWxFbmNvZGluZykgOiBudWxsO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5FbmNvZGluZz0gb3B0aW9uYWxFbmNvZGluZ1xuICAgICAqIEByZXR1cm5zIHN0cmluZ3xVaW50OEFycmF5fG51bGxcbiAgICAgKi9cbiAgICBkb21haW4oKTogc3RyaW5nfG51bGw7XG4gICAgZG9tYWluKG9wdGlvbmFsRW5jb2Rpbmc6IGZsYXRidWZmZXJzLkVuY29kaW5nKTogc3RyaW5nfFVpbnQ4QXJyYXl8bnVsbDtcbiAgICBkb21haW4ob3B0aW9uYWxFbmNvZGluZz86IGFueSk6IHN0cmluZ3xVaW50OEFycmF5fG51bGwge1xuICAgICAgbGV0IG9mZnNldCA9IHRoaXMuYmIhLl9fb2Zmc2V0KHRoaXMuYmJfcG9zLCAxMik7XG4gICAgICByZXR1cm4gb2Zmc2V0ID8gdGhpcy5iYiEuX19zdHJpbmcodGhpcy5iYl9wb3MgKyBvZmZzZXQsIG9wdGlvbmFsRW5jb2RpbmcpIDogbnVsbDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcmV0dXJucyBmbGF0YnVmZmVycy5Mb25nXG4gICAgICovXG4gICAgbW9kZWxWZXJzaW9uKCk6IGZsYXRidWZmZXJzLkxvbmcge1xuICAgICAgbGV0IG9mZnNldCA9IHRoaXMuYmIhLl9fb2Zmc2V0KHRoaXMuYmJfcG9zLCAxNCk7XG4gICAgICByZXR1cm4gb2Zmc2V0ID8gdGhpcy5iYiEucmVhZEludDY0KHRoaXMuYmJfcG9zICsgb2Zmc2V0KSA6IHRoaXMuYmIhLmNyZWF0ZUxvbmcoMCwgMCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkVuY29kaW5nPSBvcHRpb25hbEVuY29kaW5nXG4gICAgICogQHJldHVybnMgc3RyaW5nfFVpbnQ4QXJyYXl8bnVsbFxuICAgICAqL1xuICAgIGRvY1N0cmluZygpOiBzdHJpbmd8bnVsbDtcbiAgICBkb2NTdHJpbmcob3B0aW9uYWxFbmNvZGluZzogZmxhdGJ1ZmZlcnMuRW5jb2RpbmcpOiBzdHJpbmd8VWludDhBcnJheXxudWxsO1xuICAgIGRvY1N0cmluZyhvcHRpb25hbEVuY29kaW5nPzogYW55KTogc3RyaW5nfFVpbnQ4QXJyYXl8bnVsbCB7XG4gICAgICBsZXQgb2Zmc2V0ID0gdGhpcy5iYiEuX19vZmZzZXQodGhpcy5iYl9wb3MsIDE2KTtcbiAgICAgIHJldHVybiBvZmZzZXQgPyB0aGlzLmJiIS5fX3N0cmluZyh0aGlzLmJiX3BvcyArIG9mZnNldCwgb3B0aW9uYWxFbmNvZGluZykgOiBudWxsO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBvbm54cnVudGltZS5leHBlcmltZW50YWwuZmJzLkdyYXBoPSBvYmpcbiAgICAgKiBAcmV0dXJucyBvbm54cnVudGltZS5leHBlcmltZW50YWwuZmJzLkdyYXBofG51bGxcbiAgICAgKi9cbiAgICBncmFwaChvYmo/OiBvbm54cnVudGltZS5leHBlcmltZW50YWwuZmJzLkdyYXBoKTogb25ueHJ1bnRpbWUuZXhwZXJpbWVudGFsLmZicy5HcmFwaHxudWxsIHtcbiAgICAgIGxldCBvZmZzZXQgPSB0aGlzLmJiIS5fX29mZnNldCh0aGlzLmJiX3BvcywgMTgpO1xuICAgICAgcmV0dXJuIG9mZnNldCA/IChvYmogfHwgbmV3IG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnMuR3JhcGgoKSlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgLl9faW5pdCh0aGlzLmJiIS5fX2luZGlyZWN0KHRoaXMuYmJfcG9zICsgb2Zmc2V0KSwgdGhpcy5iYiEpIDpcbiAgICAgICAgICAgICAgICAgICAgICBudWxsO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5FbmNvZGluZz0gb3B0aW9uYWxFbmNvZGluZ1xuICAgICAqIEByZXR1cm5zIHN0cmluZ3xVaW50OEFycmF5fG51bGxcbiAgICAgKi9cbiAgICBncmFwaERvY1N0cmluZygpOiBzdHJpbmd8bnVsbDtcbiAgICBncmFwaERvY1N0cmluZyhvcHRpb25hbEVuY29kaW5nOiBmbGF0YnVmZmVycy5FbmNvZGluZyk6IHN0cmluZ3xVaW50OEFycmF5fG51bGw7XG4gICAgZ3JhcGhEb2NTdHJpbmcob3B0aW9uYWxFbmNvZGluZz86IGFueSk6IHN0cmluZ3xVaW50OEFycmF5fG51bGwge1xuICAgICAgbGV0IG9mZnNldCA9IHRoaXMuYmIhLl9fb2Zmc2V0KHRoaXMuYmJfcG9zLCAyMCk7XG4gICAgICByZXR1cm4gb2Zmc2V0ID8gdGhpcy5iYiEuX19zdHJpbmcodGhpcy5iYl9wb3MgKyBvZmZzZXQsIG9wdGlvbmFsRW5jb2RpbmcpIDogbnVsbDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuQnVpbGRlciBidWlsZGVyXG4gICAgICovXG4gICAgc3RhdGljIHN0YXJ0TW9kZWwoYnVpbGRlcjogZmxhdGJ1ZmZlcnMuQnVpbGRlcikge1xuICAgICAgYnVpbGRlci5zdGFydE9iamVjdCg5KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuQnVpbGRlciBidWlsZGVyXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkxvbmcgaXJWZXJzaW9uXG4gICAgICovXG4gICAgc3RhdGljIGFkZElyVmVyc2lvbihidWlsZGVyOiBmbGF0YnVmZmVycy5CdWlsZGVyLCBpclZlcnNpb246IGZsYXRidWZmZXJzLkxvbmcpIHtcbiAgICAgIGJ1aWxkZXIuYWRkRmllbGRJbnQ2NCgwLCBpclZlcnNpb24sIGJ1aWxkZXIuY3JlYXRlTG9uZygwLCAwKSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ1aWxkZXIgYnVpbGRlclxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5PZmZzZXQgb3BzZXRJbXBvcnRPZmZzZXRcbiAgICAgKi9cbiAgICBzdGF0aWMgYWRkT3BzZXRJbXBvcnQoYnVpbGRlcjogZmxhdGJ1ZmZlcnMuQnVpbGRlciwgb3BzZXRJbXBvcnRPZmZzZXQ6IGZsYXRidWZmZXJzLk9mZnNldCkge1xuICAgICAgYnVpbGRlci5hZGRGaWVsZE9mZnNldCgxLCBvcHNldEltcG9ydE9mZnNldCwgMCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ1aWxkZXIgYnVpbGRlclxuICAgICAqIEBwYXJhbSBBcnJheS48ZmxhdGJ1ZmZlcnMuT2Zmc2V0PiBkYXRhXG4gICAgICogQHJldHVybnMgZmxhdGJ1ZmZlcnMuT2Zmc2V0XG4gICAgICovXG4gICAgc3RhdGljIGNyZWF0ZU9wc2V0SW1wb3J0VmVjdG9yKGJ1aWxkZXI6IGZsYXRidWZmZXJzLkJ1aWxkZXIsIGRhdGE6IGZsYXRidWZmZXJzLk9mZnNldFtdKTogZmxhdGJ1ZmZlcnMuT2Zmc2V0IHtcbiAgICAgIGJ1aWxkZXIuc3RhcnRWZWN0b3IoNCwgZGF0YS5sZW5ndGgsIDQpO1xuICAgICAgZm9yIChsZXQgaSA9IGRhdGEubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICAgICAgYnVpbGRlci5hZGRPZmZzZXQoZGF0YVtpXSk7XG4gICAgICB9XG4gICAgICByZXR1cm4gYnVpbGRlci5lbmRWZWN0b3IoKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuQnVpbGRlciBidWlsZGVyXG4gICAgICogQHBhcmFtIG51bWJlciBudW1FbGVtc1xuICAgICAqL1xuICAgIHN0YXRpYyBzdGFydE9wc2V0SW1wb3J0VmVjdG9yKGJ1aWxkZXI6IGZsYXRidWZmZXJzLkJ1aWxkZXIsIG51bUVsZW1zOiBudW1iZXIpIHtcbiAgICAgIGJ1aWxkZXIuc3RhcnRWZWN0b3IoNCwgbnVtRWxlbXMsIDQpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CdWlsZGVyIGJ1aWxkZXJcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuT2Zmc2V0IHByb2R1Y2VyTmFtZU9mZnNldFxuICAgICAqL1xuICAgIHN0YXRpYyBhZGRQcm9kdWNlck5hbWUoYnVpbGRlcjogZmxhdGJ1ZmZlcnMuQnVpbGRlciwgcHJvZHVjZXJOYW1lT2Zmc2V0OiBmbGF0YnVmZmVycy5PZmZzZXQpIHtcbiAgICAgIGJ1aWxkZXIuYWRkRmllbGRPZmZzZXQoMiwgcHJvZHVjZXJOYW1lT2Zmc2V0LCAwKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuQnVpbGRlciBidWlsZGVyXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLk9mZnNldCBwcm9kdWNlclZlcnNpb25PZmZzZXRcbiAgICAgKi9cbiAgICBzdGF0aWMgYWRkUHJvZHVjZXJWZXJzaW9uKGJ1aWxkZXI6IGZsYXRidWZmZXJzLkJ1aWxkZXIsIHByb2R1Y2VyVmVyc2lvbk9mZnNldDogZmxhdGJ1ZmZlcnMuT2Zmc2V0KSB7XG4gICAgICBidWlsZGVyLmFkZEZpZWxkT2Zmc2V0KDMsIHByb2R1Y2VyVmVyc2lvbk9mZnNldCwgMCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ1aWxkZXIgYnVpbGRlclxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5PZmZzZXQgZG9tYWluT2Zmc2V0XG4gICAgICovXG4gICAgc3RhdGljIGFkZERvbWFpbihidWlsZGVyOiBmbGF0YnVmZmVycy5CdWlsZGVyLCBkb21haW5PZmZzZXQ6IGZsYXRidWZmZXJzLk9mZnNldCkge1xuICAgICAgYnVpbGRlci5hZGRGaWVsZE9mZnNldCg0LCBkb21haW5PZmZzZXQsIDApO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CdWlsZGVyIGJ1aWxkZXJcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuTG9uZyBtb2RlbFZlcnNpb25cbiAgICAgKi9cbiAgICBzdGF0aWMgYWRkTW9kZWxWZXJzaW9uKGJ1aWxkZXI6IGZsYXRidWZmZXJzLkJ1aWxkZXIsIG1vZGVsVmVyc2lvbjogZmxhdGJ1ZmZlcnMuTG9uZykge1xuICAgICAgYnVpbGRlci5hZGRGaWVsZEludDY0KDUsIG1vZGVsVmVyc2lvbiwgYnVpbGRlci5jcmVhdGVMb25nKDAsIDApKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuQnVpbGRlciBidWlsZGVyXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLk9mZnNldCBkb2NTdHJpbmdPZmZzZXRcbiAgICAgKi9cbiAgICBzdGF0aWMgYWRkRG9jU3RyaW5nKGJ1aWxkZXI6IGZsYXRidWZmZXJzLkJ1aWxkZXIsIGRvY1N0cmluZ09mZnNldDogZmxhdGJ1ZmZlcnMuT2Zmc2V0KSB7XG4gICAgICBidWlsZGVyLmFkZEZpZWxkT2Zmc2V0KDYsIGRvY1N0cmluZ09mZnNldCwgMCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ1aWxkZXIgYnVpbGRlclxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5PZmZzZXQgZ3JhcGhPZmZzZXRcbiAgICAgKi9cbiAgICBzdGF0aWMgYWRkR3JhcGgoYnVpbGRlcjogZmxhdGJ1ZmZlcnMuQnVpbGRlciwgZ3JhcGhPZmZzZXQ6IGZsYXRidWZmZXJzLk9mZnNldCkge1xuICAgICAgYnVpbGRlci5hZGRGaWVsZE9mZnNldCg3LCBncmFwaE9mZnNldCwgMCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ1aWxkZXIgYnVpbGRlclxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5PZmZzZXQgZ3JhcGhEb2NTdHJpbmdPZmZzZXRcbiAgICAgKi9cbiAgICBzdGF0aWMgYWRkR3JhcGhEb2NTdHJpbmcoYnVpbGRlcjogZmxhdGJ1ZmZlcnMuQnVpbGRlciwgZ3JhcGhEb2NTdHJpbmdPZmZzZXQ6IGZsYXRidWZmZXJzLk9mZnNldCkge1xuICAgICAgYnVpbGRlci5hZGRGaWVsZE9mZnNldCg4LCBncmFwaERvY1N0cmluZ09mZnNldCwgMCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ1aWxkZXIgYnVpbGRlclxuICAgICAqIEByZXR1cm5zIGZsYXRidWZmZXJzLk9mZnNldFxuICAgICAqL1xuICAgIHN0YXRpYyBlbmRNb2RlbChidWlsZGVyOiBmbGF0YnVmZmVycy5CdWlsZGVyKTogZmxhdGJ1ZmZlcnMuT2Zmc2V0IHtcbiAgICAgIGxldCBvZmZzZXQgPSBidWlsZGVyLmVuZE9iamVjdCgpO1xuICAgICAgcmV0dXJuIG9mZnNldDtcbiAgICB9XG5cbiAgICBzdGF0aWMgY3JlYXRlTW9kZWwoXG4gICAgICAgIGJ1aWxkZXI6IGZsYXRidWZmZXJzLkJ1aWxkZXIsIGlyVmVyc2lvbjogZmxhdGJ1ZmZlcnMuTG9uZywgb3BzZXRJbXBvcnRPZmZzZXQ6IGZsYXRidWZmZXJzLk9mZnNldCxcbiAgICAgICAgcHJvZHVjZXJOYW1lT2Zmc2V0OiBmbGF0YnVmZmVycy5PZmZzZXQsIHByb2R1Y2VyVmVyc2lvbk9mZnNldDogZmxhdGJ1ZmZlcnMuT2Zmc2V0LFxuICAgICAgICBkb21haW5PZmZzZXQ6IGZsYXRidWZmZXJzLk9mZnNldCwgbW9kZWxWZXJzaW9uOiBmbGF0YnVmZmVycy5Mb25nLCBkb2NTdHJpbmdPZmZzZXQ6IGZsYXRidWZmZXJzLk9mZnNldCxcbiAgICAgICAgZ3JhcGhPZmZzZXQ6IGZsYXRidWZmZXJzLk9mZnNldCwgZ3JhcGhEb2NTdHJpbmdPZmZzZXQ6IGZsYXRidWZmZXJzLk9mZnNldCk6IGZsYXRidWZmZXJzLk9mZnNldCB7XG4gICAgICBNb2RlbC5zdGFydE1vZGVsKGJ1aWxkZXIpO1xuICAgICAgTW9kZWwuYWRkSXJWZXJzaW9uKGJ1aWxkZXIsIGlyVmVyc2lvbik7XG4gICAgICBNb2RlbC5hZGRPcHNldEltcG9ydChidWlsZGVyLCBvcHNldEltcG9ydE9mZnNldCk7XG4gICAgICBNb2RlbC5hZGRQcm9kdWNlck5hbWUoYnVpbGRlciwgcHJvZHVjZXJOYW1lT2Zmc2V0KTtcbiAgICAgIE1vZGVsLmFkZFByb2R1Y2VyVmVyc2lvbihidWlsZGVyLCBwcm9kdWNlclZlcnNpb25PZmZzZXQpO1xuICAgICAgTW9kZWwuYWRkRG9tYWluKGJ1aWxkZXIsIGRvbWFpbk9mZnNldCk7XG4gICAgICBNb2RlbC5hZGRNb2RlbFZlcnNpb24oYnVpbGRlciwgbW9kZWxWZXJzaW9uKTtcbiAgICAgIE1vZGVsLmFkZERvY1N0cmluZyhidWlsZGVyLCBkb2NTdHJpbmdPZmZzZXQpO1xuICAgICAgTW9kZWwuYWRkR3JhcGgoYnVpbGRlciwgZ3JhcGhPZmZzZXQpO1xuICAgICAgTW9kZWwuYWRkR3JhcGhEb2NTdHJpbmcoYnVpbGRlciwgZ3JhcGhEb2NTdHJpbmdPZmZzZXQpO1xuICAgICAgcmV0dXJuIE1vZGVsLmVuZE1vZGVsKGJ1aWxkZXIpO1xuICAgIH1cbiAgfVxufVxuLyoqXG4gKiBAY29uc3RydWN0b3JcbiAqL1xuZXhwb3J0IG5hbWVzcGFjZSBvbm54cnVudGltZS5leHBlcmltZW50YWwuZmJzIHtcbiAgZXhwb3J0IGNsYXNzIEtlcm5lbENyZWF0ZUluZm9zIHtcbiAgICBiYjogZmxhdGJ1ZmZlcnMuQnl0ZUJ1ZmZlcnxudWxsID0gbnVsbDtcblxuICAgIGJiX3BvcyA9IDA7XG4gICAgLyoqXG4gICAgICogQHBhcmFtIG51bWJlciBpXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ5dGVCdWZmZXIgYmJcbiAgICAgKiBAcmV0dXJucyBLZXJuZWxDcmVhdGVJbmZvc1xuICAgICAqL1xuICAgIF9faW5pdChpOiBudW1iZXIsIGJiOiBmbGF0YnVmZmVycy5CeXRlQnVmZmVyKTogS2VybmVsQ3JlYXRlSW5mb3Mge1xuICAgICAgdGhpcy5iYl9wb3MgPSBpO1xuICAgICAgdGhpcy5iYiA9IGJiO1xuICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ5dGVCdWZmZXIgYmJcbiAgICAgKiBAcGFyYW0gS2VybmVsQ3JlYXRlSW5mb3M9IG9ialxuICAgICAqIEByZXR1cm5zIEtlcm5lbENyZWF0ZUluZm9zXG4gICAgICovXG4gICAgc3RhdGljIGdldFJvb3RBc0tlcm5lbENyZWF0ZUluZm9zKGJiOiBmbGF0YnVmZmVycy5CeXRlQnVmZmVyLCBvYmo/OiBLZXJuZWxDcmVhdGVJbmZvcyk6IEtlcm5lbENyZWF0ZUluZm9zIHtcbiAgICAgIHJldHVybiAob2JqIHx8IG5ldyBLZXJuZWxDcmVhdGVJbmZvcygpKS5fX2luaXQoYmIucmVhZEludDMyKGJiLnBvc2l0aW9uKCkpICsgYmIucG9zaXRpb24oKSwgYmIpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CeXRlQnVmZmVyIGJiXG4gICAgICogQHBhcmFtIEtlcm5lbENyZWF0ZUluZm9zPSBvYmpcbiAgICAgKiBAcmV0dXJucyBLZXJuZWxDcmVhdGVJbmZvc1xuICAgICAqL1xuICAgIHN0YXRpYyBnZXRTaXplUHJlZml4ZWRSb290QXNLZXJuZWxDcmVhdGVJbmZvcyhiYjogZmxhdGJ1ZmZlcnMuQnl0ZUJ1ZmZlciwgb2JqPzogS2VybmVsQ3JlYXRlSW5mb3MpOlxuICAgICAgICBLZXJuZWxDcmVhdGVJbmZvcyB7XG4gICAgICBiYi5zZXRQb3NpdGlvbihiYi5wb3NpdGlvbigpICsgZmxhdGJ1ZmZlcnMuU0laRV9QUkVGSVhfTEVOR1RIKTtcbiAgICAgIHJldHVybiAob2JqIHx8IG5ldyBLZXJuZWxDcmVhdGVJbmZvcygpKS5fX2luaXQoYmIucmVhZEludDMyKGJiLnBvc2l0aW9uKCkpICsgYmIucG9zaXRpb24oKSwgYmIpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBudW1iZXIgaW5kZXhcbiAgICAgKiBAcmV0dXJucyBudW1iZXJcbiAgICAgKi9cbiAgICBub2RlSW5kaWNlcyhpbmRleDogbnVtYmVyKTogbnVtYmVyfG51bGwge1xuICAgICAgbGV0IG9mZnNldCA9IHRoaXMuYmIhLl9fb2Zmc2V0KHRoaXMuYmJfcG9zLCA0KTtcbiAgICAgIHJldHVybiBvZmZzZXQgPyB0aGlzLmJiIS5yZWFkVWludDMyKHRoaXMuYmIhLl9fdmVjdG9yKHRoaXMuYmJfcG9zICsgb2Zmc2V0KSArIGluZGV4ICogNCkgOiAwO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEByZXR1cm5zIG51bWJlclxuICAgICAqL1xuICAgIG5vZGVJbmRpY2VzTGVuZ3RoKCk6IG51bWJlciB7XG4gICAgICBsZXQgb2Zmc2V0ID0gdGhpcy5iYiEuX19vZmZzZXQodGhpcy5iYl9wb3MsIDQpO1xuICAgICAgcmV0dXJuIG9mZnNldCA/IHRoaXMuYmIhLl9fdmVjdG9yX2xlbih0aGlzLmJiX3BvcyArIG9mZnNldCkgOiAwO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEByZXR1cm5zIFVpbnQzMkFycmF5XG4gICAgICovXG4gICAgbm9kZUluZGljZXNBcnJheSgpOiBVaW50MzJBcnJheXxudWxsIHtcbiAgICAgIGxldCBvZmZzZXQgPSB0aGlzLmJiIS5fX29mZnNldCh0aGlzLmJiX3BvcywgNCk7XG4gICAgICByZXR1cm4gb2Zmc2V0ID9cbiAgICAgICAgICBuZXcgVWludDMyQXJyYXkoXG4gICAgICAgICAgICAgIHRoaXMuYmIhLmJ5dGVzKCkuYnVmZmVyLCB0aGlzLmJiIS5ieXRlcygpLmJ5dGVPZmZzZXQgKyB0aGlzLmJiIS5fX3ZlY3Rvcih0aGlzLmJiX3BvcyArIG9mZnNldCksXG4gICAgICAgICAgICAgIHRoaXMuYmIhLl9fdmVjdG9yX2xlbih0aGlzLmJiX3BvcyArIG9mZnNldCkpIDpcbiAgICAgICAgICBudWxsO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBudW1iZXIgaW5kZXhcbiAgICAgKiBAcmV0dXJucyBmbGF0YnVmZmVycy5Mb25nXG4gICAgICovXG4gICAga2VybmVsRGVmSGFzaGVzKGluZGV4OiBudW1iZXIpOiBmbGF0YnVmZmVycy5Mb25nfG51bGwge1xuICAgICAgbGV0IG9mZnNldCA9IHRoaXMuYmIhLl9fb2Zmc2V0KHRoaXMuYmJfcG9zLCA2KTtcbiAgICAgIHJldHVybiBvZmZzZXQgPyB0aGlzLmJiIS5yZWFkVWludDY0KHRoaXMuYmIhLl9fdmVjdG9yKHRoaXMuYmJfcG9zICsgb2Zmc2V0KSArIGluZGV4ICogOCkgOlxuICAgICAgICAgICAgICAgICAgICAgIHRoaXMuYmIhLmNyZWF0ZUxvbmcoMCwgMCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHJldHVybnMgbnVtYmVyXG4gICAgICovXG4gICAga2VybmVsRGVmSGFzaGVzTGVuZ3RoKCk6IG51bWJlciB7XG4gICAgICBsZXQgb2Zmc2V0ID0gdGhpcy5iYiEuX19vZmZzZXQodGhpcy5iYl9wb3MsIDYpO1xuICAgICAgcmV0dXJuIG9mZnNldCA/IHRoaXMuYmIhLl9fdmVjdG9yX2xlbih0aGlzLmJiX3BvcyArIG9mZnNldCkgOiAwO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CdWlsZGVyIGJ1aWxkZXJcbiAgICAgKi9cbiAgICBzdGF0aWMgc3RhcnRLZXJuZWxDcmVhdGVJbmZvcyhidWlsZGVyOiBmbGF0YnVmZmVycy5CdWlsZGVyKSB7XG4gICAgICBidWlsZGVyLnN0YXJ0T2JqZWN0KDIpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CdWlsZGVyIGJ1aWxkZXJcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuT2Zmc2V0IG5vZGVJbmRpY2VzT2Zmc2V0XG4gICAgICovXG4gICAgc3RhdGljIGFkZE5vZGVJbmRpY2VzKGJ1aWxkZXI6IGZsYXRidWZmZXJzLkJ1aWxkZXIsIG5vZGVJbmRpY2VzT2Zmc2V0OiBmbGF0YnVmZmVycy5PZmZzZXQpIHtcbiAgICAgIGJ1aWxkZXIuYWRkRmllbGRPZmZzZXQoMCwgbm9kZUluZGljZXNPZmZzZXQsIDApO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CdWlsZGVyIGJ1aWxkZXJcbiAgICAgKiBAcGFyYW0gQXJyYXkuPG51bWJlcj4gZGF0YVxuICAgICAqIEByZXR1cm5zIGZsYXRidWZmZXJzLk9mZnNldFxuICAgICAqL1xuICAgIHN0YXRpYyBjcmVhdGVOb2RlSW5kaWNlc1ZlY3RvcihidWlsZGVyOiBmbGF0YnVmZmVycy5CdWlsZGVyLCBkYXRhOiBudW1iZXJbXXxVaW50OEFycmF5KTogZmxhdGJ1ZmZlcnMuT2Zmc2V0IHtcbiAgICAgIGJ1aWxkZXIuc3RhcnRWZWN0b3IoNCwgZGF0YS5sZW5ndGgsIDQpO1xuICAgICAgZm9yIChsZXQgaSA9IGRhdGEubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICAgICAgYnVpbGRlci5hZGRJbnQzMihkYXRhW2ldKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBidWlsZGVyLmVuZFZlY3RvcigpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CdWlsZGVyIGJ1aWxkZXJcbiAgICAgKiBAcGFyYW0gbnVtYmVyIG51bUVsZW1zXG4gICAgICovXG4gICAgc3RhdGljIHN0YXJ0Tm9kZUluZGljZXNWZWN0b3IoYnVpbGRlcjogZmxhdGJ1ZmZlcnMuQnVpbGRlciwgbnVtRWxlbXM6IG51bWJlcikge1xuICAgICAgYnVpbGRlci5zdGFydFZlY3Rvcig0LCBudW1FbGVtcywgNCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ1aWxkZXIgYnVpbGRlclxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5PZmZzZXQga2VybmVsRGVmSGFzaGVzT2Zmc2V0XG4gICAgICovXG4gICAgc3RhdGljIGFkZEtlcm5lbERlZkhhc2hlcyhidWlsZGVyOiBmbGF0YnVmZmVycy5CdWlsZGVyLCBrZXJuZWxEZWZIYXNoZXNPZmZzZXQ6IGZsYXRidWZmZXJzLk9mZnNldCkge1xuICAgICAgYnVpbGRlci5hZGRGaWVsZE9mZnNldCgxLCBrZXJuZWxEZWZIYXNoZXNPZmZzZXQsIDApO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CdWlsZGVyIGJ1aWxkZXJcbiAgICAgKiBAcGFyYW0gQXJyYXkuPGZsYXRidWZmZXJzLkxvbmc+IGRhdGFcbiAgICAgKiBAcmV0dXJucyBmbGF0YnVmZmVycy5PZmZzZXRcbiAgICAgKi9cbiAgICBzdGF0aWMgY3JlYXRlS2VybmVsRGVmSGFzaGVzVmVjdG9yKGJ1aWxkZXI6IGZsYXRidWZmZXJzLkJ1aWxkZXIsIGRhdGE6IGZsYXRidWZmZXJzLkxvbmdbXSk6IGZsYXRidWZmZXJzLk9mZnNldCB7XG4gICAgICBidWlsZGVyLnN0YXJ0VmVjdG9yKDgsIGRhdGEubGVuZ3RoLCA4KTtcbiAgICAgIGZvciAobGV0IGkgPSBkYXRhLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSB7XG4gICAgICAgIGJ1aWxkZXIuYWRkSW50NjQoZGF0YVtpXSk7XG4gICAgICB9XG4gICAgICByZXR1cm4gYnVpbGRlci5lbmRWZWN0b3IoKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuQnVpbGRlciBidWlsZGVyXG4gICAgICogQHBhcmFtIG51bWJlciBudW1FbGVtc1xuICAgICAqL1xuICAgIHN0YXRpYyBzdGFydEtlcm5lbERlZkhhc2hlc1ZlY3RvcihidWlsZGVyOiBmbGF0YnVmZmVycy5CdWlsZGVyLCBudW1FbGVtczogbnVtYmVyKSB7XG4gICAgICBidWlsZGVyLnN0YXJ0VmVjdG9yKDgsIG51bUVsZW1zLCA4KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuQnVpbGRlciBidWlsZGVyXG4gICAgICogQHJldHVybnMgZmxhdGJ1ZmZlcnMuT2Zmc2V0XG4gICAgICovXG4gICAgc3RhdGljIGVuZEtlcm5lbENyZWF0ZUluZm9zKGJ1aWxkZXI6IGZsYXRidWZmZXJzLkJ1aWxkZXIpOiBmbGF0YnVmZmVycy5PZmZzZXQge1xuICAgICAgbGV0IG9mZnNldCA9IGJ1aWxkZXIuZW5kT2JqZWN0KCk7XG4gICAgICByZXR1cm4gb2Zmc2V0O1xuICAgIH1cblxuICAgIHN0YXRpYyBjcmVhdGVLZXJuZWxDcmVhdGVJbmZvcyhcbiAgICAgICAgYnVpbGRlcjogZmxhdGJ1ZmZlcnMuQnVpbGRlciwgbm9kZUluZGljZXNPZmZzZXQ6IGZsYXRidWZmZXJzLk9mZnNldCxcbiAgICAgICAga2VybmVsRGVmSGFzaGVzT2Zmc2V0OiBmbGF0YnVmZmVycy5PZmZzZXQpOiBmbGF0YnVmZmVycy5PZmZzZXQge1xuICAgICAgS2VybmVsQ3JlYXRlSW5mb3Muc3RhcnRLZXJuZWxDcmVhdGVJbmZvcyhidWlsZGVyKTtcbiAgICAgIEtlcm5lbENyZWF0ZUluZm9zLmFkZE5vZGVJbmRpY2VzKGJ1aWxkZXIsIG5vZGVJbmRpY2VzT2Zmc2V0KTtcbiAgICAgIEtlcm5lbENyZWF0ZUluZm9zLmFkZEtlcm5lbERlZkhhc2hlcyhidWlsZGVyLCBrZXJuZWxEZWZIYXNoZXNPZmZzZXQpO1xuICAgICAgcmV0dXJuIEtlcm5lbENyZWF0ZUluZm9zLmVuZEtlcm5lbENyZWF0ZUluZm9zKGJ1aWxkZXIpO1xuICAgIH1cbiAgfVxufVxuLyoqXG4gKiBAY29uc3RydWN0b3JcbiAqL1xuZXhwb3J0IG5hbWVzcGFjZSBvbm54cnVudGltZS5leHBlcmltZW50YWwuZmJzIHtcbiAgZXhwb3J0IGNsYXNzIFN1YkdyYXBoU2Vzc2lvblN0YXRlIHtcbiAgICBiYjogZmxhdGJ1ZmZlcnMuQnl0ZUJ1ZmZlcnxudWxsID0gbnVsbDtcblxuICAgIGJiX3BvcyA9IDA7XG4gICAgLyoqXG4gICAgICogQHBhcmFtIG51bWJlciBpXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ5dGVCdWZmZXIgYmJcbiAgICAgKiBAcmV0dXJucyBTdWJHcmFwaFNlc3Npb25TdGF0ZVxuICAgICAqL1xuICAgIF9faW5pdChpOiBudW1iZXIsIGJiOiBmbGF0YnVmZmVycy5CeXRlQnVmZmVyKTogU3ViR3JhcGhTZXNzaW9uU3RhdGUge1xuICAgICAgdGhpcy5iYl9wb3MgPSBpO1xuICAgICAgdGhpcy5iYiA9IGJiO1xuICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ5dGVCdWZmZXIgYmJcbiAgICAgKiBAcGFyYW0gU3ViR3JhcGhTZXNzaW9uU3RhdGU9IG9ialxuICAgICAqIEByZXR1cm5zIFN1YkdyYXBoU2Vzc2lvblN0YXRlXG4gICAgICovXG4gICAgc3RhdGljIGdldFJvb3RBc1N1YkdyYXBoU2Vzc2lvblN0YXRlKGJiOiBmbGF0YnVmZmVycy5CeXRlQnVmZmVyLCBvYmo/OiBTdWJHcmFwaFNlc3Npb25TdGF0ZSk6IFN1YkdyYXBoU2Vzc2lvblN0YXRlIHtcbiAgICAgIHJldHVybiAob2JqIHx8IG5ldyBTdWJHcmFwaFNlc3Npb25TdGF0ZSgpKS5fX2luaXQoYmIucmVhZEludDMyKGJiLnBvc2l0aW9uKCkpICsgYmIucG9zaXRpb24oKSwgYmIpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CeXRlQnVmZmVyIGJiXG4gICAgICogQHBhcmFtIFN1YkdyYXBoU2Vzc2lvblN0YXRlPSBvYmpcbiAgICAgKiBAcmV0dXJucyBTdWJHcmFwaFNlc3Npb25TdGF0ZVxuICAgICAqL1xuICAgIHN0YXRpYyBnZXRTaXplUHJlZml4ZWRSb290QXNTdWJHcmFwaFNlc3Npb25TdGF0ZShiYjogZmxhdGJ1ZmZlcnMuQnl0ZUJ1ZmZlciwgb2JqPzogU3ViR3JhcGhTZXNzaW9uU3RhdGUpOlxuICAgICAgICBTdWJHcmFwaFNlc3Npb25TdGF0ZSB7XG4gICAgICBiYi5zZXRQb3NpdGlvbihiYi5wb3NpdGlvbigpICsgZmxhdGJ1ZmZlcnMuU0laRV9QUkVGSVhfTEVOR1RIKTtcbiAgICAgIHJldHVybiAob2JqIHx8IG5ldyBTdWJHcmFwaFNlc3Npb25TdGF0ZSgpKS5fX2luaXQoYmIucmVhZEludDMyKGJiLnBvc2l0aW9uKCkpICsgYmIucG9zaXRpb24oKSwgYmIpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5FbmNvZGluZz0gb3B0aW9uYWxFbmNvZGluZ1xuICAgICAqIEByZXR1cm5zIHN0cmluZ3xVaW50OEFycmF5fG51bGxcbiAgICAgKi9cbiAgICBncmFwaElkKCk6IHN0cmluZ3xudWxsO1xuICAgIGdyYXBoSWQob3B0aW9uYWxFbmNvZGluZzogZmxhdGJ1ZmZlcnMuRW5jb2RpbmcpOiBzdHJpbmd8VWludDhBcnJheXxudWxsO1xuICAgIGdyYXBoSWQob3B0aW9uYWxFbmNvZGluZz86IGFueSk6IHN0cmluZ3xVaW50OEFycmF5fG51bGwge1xuICAgICAgbGV0IG9mZnNldCA9IHRoaXMuYmIhLl9fb2Zmc2V0KHRoaXMuYmJfcG9zLCA0KTtcbiAgICAgIHJldHVybiBvZmZzZXQgPyB0aGlzLmJiIS5fX3N0cmluZyh0aGlzLmJiX3BvcyArIG9mZnNldCwgb3B0aW9uYWxFbmNvZGluZykgOiBudWxsO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBvbm54cnVudGltZS5leHBlcmltZW50YWwuZmJzLlNlc3Npb25TdGF0ZT0gb2JqXG4gICAgICogQHJldHVybnMgb25ueHJ1bnRpbWUuZXhwZXJpbWVudGFsLmZicy5TZXNzaW9uU3RhdGV8bnVsbFxuICAgICAqL1xuICAgIHNlc3Npb25TdGF0ZShvYmo/OiBvbm54cnVudGltZS5leHBlcmltZW50YWwuZmJzLlNlc3Npb25TdGF0ZSk6IG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnMuU2Vzc2lvblN0YXRlfG51bGwge1xuICAgICAgbGV0IG9mZnNldCA9IHRoaXMuYmIhLl9fb2Zmc2V0KHRoaXMuYmJfcG9zLCA2KTtcbiAgICAgIHJldHVybiBvZmZzZXQgPyAob2JqIHx8IG5ldyBvbm54cnVudGltZS5leHBlcmltZW50YWwuZmJzLlNlc3Npb25TdGF0ZSgpKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAuX19pbml0KHRoaXMuYmIhLl9faW5kaXJlY3QodGhpcy5iYl9wb3MgKyBvZmZzZXQpLCB0aGlzLmJiISkgOlxuICAgICAgICAgICAgICAgICAgICAgIG51bGw7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ1aWxkZXIgYnVpbGRlclxuICAgICAqL1xuICAgIHN0YXRpYyBzdGFydFN1YkdyYXBoU2Vzc2lvblN0YXRlKGJ1aWxkZXI6IGZsYXRidWZmZXJzLkJ1aWxkZXIpIHtcbiAgICAgIGJ1aWxkZXIuc3RhcnRPYmplY3QoMik7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ1aWxkZXIgYnVpbGRlclxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5PZmZzZXQgZ3JhcGhJZE9mZnNldFxuICAgICAqL1xuICAgIHN0YXRpYyBhZGRHcmFwaElkKGJ1aWxkZXI6IGZsYXRidWZmZXJzLkJ1aWxkZXIsIGdyYXBoSWRPZmZzZXQ6IGZsYXRidWZmZXJzLk9mZnNldCkge1xuICAgICAgYnVpbGRlci5hZGRGaWVsZE9mZnNldCgwLCBncmFwaElkT2Zmc2V0LCAwKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuQnVpbGRlciBidWlsZGVyXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLk9mZnNldCBzZXNzaW9uU3RhdGVPZmZzZXRcbiAgICAgKi9cbiAgICBzdGF0aWMgYWRkU2Vzc2lvblN0YXRlKGJ1aWxkZXI6IGZsYXRidWZmZXJzLkJ1aWxkZXIsIHNlc3Npb25TdGF0ZU9mZnNldDogZmxhdGJ1ZmZlcnMuT2Zmc2V0KSB7XG4gICAgICBidWlsZGVyLmFkZEZpZWxkT2Zmc2V0KDEsIHNlc3Npb25TdGF0ZU9mZnNldCwgMCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ1aWxkZXIgYnVpbGRlclxuICAgICAqIEByZXR1cm5zIGZsYXRidWZmZXJzLk9mZnNldFxuICAgICAqL1xuICAgIHN0YXRpYyBlbmRTdWJHcmFwaFNlc3Npb25TdGF0ZShidWlsZGVyOiBmbGF0YnVmZmVycy5CdWlsZGVyKTogZmxhdGJ1ZmZlcnMuT2Zmc2V0IHtcbiAgICAgIGxldCBvZmZzZXQgPSBidWlsZGVyLmVuZE9iamVjdCgpO1xuICAgICAgYnVpbGRlci5yZXF1aXJlZEZpZWxkKG9mZnNldCwgNCk7ICAvLyBncmFwaF9pZFxuICAgICAgcmV0dXJuIG9mZnNldDtcbiAgICB9XG5cbiAgICBzdGF0aWMgY3JlYXRlU3ViR3JhcGhTZXNzaW9uU3RhdGUoXG4gICAgICAgIGJ1aWxkZXI6IGZsYXRidWZmZXJzLkJ1aWxkZXIsIGdyYXBoSWRPZmZzZXQ6IGZsYXRidWZmZXJzLk9mZnNldCxcbiAgICAgICAgc2Vzc2lvblN0YXRlT2Zmc2V0OiBmbGF0YnVmZmVycy5PZmZzZXQpOiBmbGF0YnVmZmVycy5PZmZzZXQge1xuICAgICAgU3ViR3JhcGhTZXNzaW9uU3RhdGUuc3RhcnRTdWJHcmFwaFNlc3Npb25TdGF0ZShidWlsZGVyKTtcbiAgICAgIFN1YkdyYXBoU2Vzc2lvblN0YXRlLmFkZEdyYXBoSWQoYnVpbGRlciwgZ3JhcGhJZE9mZnNldCk7XG4gICAgICBTdWJHcmFwaFNlc3Npb25TdGF0ZS5hZGRTZXNzaW9uU3RhdGUoYnVpbGRlciwgc2Vzc2lvblN0YXRlT2Zmc2V0KTtcbiAgICAgIHJldHVybiBTdWJHcmFwaFNlc3Npb25TdGF0ZS5lbmRTdWJHcmFwaFNlc3Npb25TdGF0ZShidWlsZGVyKTtcbiAgICB9XG4gIH1cbn1cbi8qKlxuICogQGNvbnN0cnVjdG9yXG4gKi9cbmV4cG9ydCBuYW1lc3BhY2Ugb25ueHJ1bnRpbWUuZXhwZXJpbWVudGFsLmZicyB7XG4gIGV4cG9ydCBjbGFzcyBTZXNzaW9uU3RhdGUge1xuICAgIGJiOiBmbGF0YnVmZmVycy5CeXRlQnVmZmVyfG51bGwgPSBudWxsO1xuXG4gICAgYmJfcG9zID0gMDtcbiAgICAvKipcbiAgICAgKiBAcGFyYW0gbnVtYmVyIGlcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuQnl0ZUJ1ZmZlciBiYlxuICAgICAqIEByZXR1cm5zIFNlc3Npb25TdGF0ZVxuICAgICAqL1xuICAgIF9faW5pdChpOiBudW1iZXIsIGJiOiBmbGF0YnVmZmVycy5CeXRlQnVmZmVyKTogU2Vzc2lvblN0YXRlIHtcbiAgICAgIHRoaXMuYmJfcG9zID0gaTtcbiAgICAgIHRoaXMuYmIgPSBiYjtcbiAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CeXRlQnVmZmVyIGJiXG4gICAgICogQHBhcmFtIFNlc3Npb25TdGF0ZT0gb2JqXG4gICAgICogQHJldHVybnMgU2Vzc2lvblN0YXRlXG4gICAgICovXG4gICAgc3RhdGljIGdldFJvb3RBc1Nlc3Npb25TdGF0ZShiYjogZmxhdGJ1ZmZlcnMuQnl0ZUJ1ZmZlciwgb2JqPzogU2Vzc2lvblN0YXRlKTogU2Vzc2lvblN0YXRlIHtcbiAgICAgIHJldHVybiAob2JqIHx8IG5ldyBTZXNzaW9uU3RhdGUoKSkuX19pbml0KGJiLnJlYWRJbnQzMihiYi5wb3NpdGlvbigpKSArIGJiLnBvc2l0aW9uKCksIGJiKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuQnl0ZUJ1ZmZlciBiYlxuICAgICAqIEBwYXJhbSBTZXNzaW9uU3RhdGU9IG9ialxuICAgICAqIEByZXR1cm5zIFNlc3Npb25TdGF0ZVxuICAgICAqL1xuICAgIHN0YXRpYyBnZXRTaXplUHJlZml4ZWRSb290QXNTZXNzaW9uU3RhdGUoYmI6IGZsYXRidWZmZXJzLkJ5dGVCdWZmZXIsIG9iaj86IFNlc3Npb25TdGF0ZSk6IFNlc3Npb25TdGF0ZSB7XG4gICAgICBiYi5zZXRQb3NpdGlvbihiYi5wb3NpdGlvbigpICsgZmxhdGJ1ZmZlcnMuU0laRV9QUkVGSVhfTEVOR1RIKTtcbiAgICAgIHJldHVybiAob2JqIHx8IG5ldyBTZXNzaW9uU3RhdGUoKSkuX19pbml0KGJiLnJlYWRJbnQzMihiYi5wb3NpdGlvbigpKSArIGJiLnBvc2l0aW9uKCksIGJiKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gb25ueHJ1bnRpbWUuZXhwZXJpbWVudGFsLmZicy5LZXJuZWxDcmVhdGVJbmZvcz0gb2JqXG4gICAgICogQHJldHVybnMgb25ueHJ1bnRpbWUuZXhwZXJpbWVudGFsLmZicy5LZXJuZWxDcmVhdGVJbmZvc3xudWxsXG4gICAgICovXG4gICAga2VybmVscyhvYmo/OiBvbm54cnVudGltZS5leHBlcmltZW50YWwuZmJzLktlcm5lbENyZWF0ZUluZm9zKTogb25ueHJ1bnRpbWUuZXhwZXJpbWVudGFsLmZicy5LZXJuZWxDcmVhdGVJbmZvc3xudWxsIHtcbiAgICAgIGxldCBvZmZzZXQgPSB0aGlzLmJiIS5fX29mZnNldCh0aGlzLmJiX3BvcywgNCk7XG4gICAgICByZXR1cm4gb2Zmc2V0ID8gKG9iaiB8fCBuZXcgb25ueHJ1bnRpbWUuZXhwZXJpbWVudGFsLmZicy5LZXJuZWxDcmVhdGVJbmZvcygpKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAuX19pbml0KHRoaXMuYmIhLl9faW5kaXJlY3QodGhpcy5iYl9wb3MgKyBvZmZzZXQpLCB0aGlzLmJiISkgOlxuICAgICAgICAgICAgICAgICAgICAgIG51bGw7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIG51bWJlciBpbmRleFxuICAgICAqIEBwYXJhbSBvbm54cnVudGltZS5leHBlcmltZW50YWwuZmJzLlN1YkdyYXBoU2Vzc2lvblN0YXRlPSBvYmpcbiAgICAgKiBAcmV0dXJucyBvbm54cnVudGltZS5leHBlcmltZW50YWwuZmJzLlN1YkdyYXBoU2Vzc2lvblN0YXRlXG4gICAgICovXG4gICAgc3ViR3JhcGhTZXNzaW9uU3RhdGVzKGluZGV4OiBudW1iZXIsIG9iaj86IG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnMuU3ViR3JhcGhTZXNzaW9uU3RhdGUpOlxuICAgICAgICBvbm54cnVudGltZS5leHBlcmltZW50YWwuZmJzLlN1YkdyYXBoU2Vzc2lvblN0YXRlfG51bGwge1xuICAgICAgbGV0IG9mZnNldCA9IHRoaXMuYmIhLl9fb2Zmc2V0KHRoaXMuYmJfcG9zLCA2KTtcbiAgICAgIHJldHVybiBvZmZzZXQgPyAob2JqIHx8IG5ldyBvbm54cnVudGltZS5leHBlcmltZW50YWwuZmJzLlN1YkdyYXBoU2Vzc2lvblN0YXRlKCkpXG4gICAgICAgICAgICAgICAgICAgICAgICAgIC5fX2luaXQodGhpcy5iYiEuX19pbmRpcmVjdCh0aGlzLmJiIS5fX3ZlY3Rvcih0aGlzLmJiX3BvcyArIG9mZnNldCkgKyBpbmRleCAqIDQpLCB0aGlzLmJiISkgOlxuICAgICAgICAgICAgICAgICAgICAgIG51bGw7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHJldHVybnMgbnVtYmVyXG4gICAgICovXG4gICAgc3ViR3JhcGhTZXNzaW9uU3RhdGVzTGVuZ3RoKCk6IG51bWJlciB7XG4gICAgICBsZXQgb2Zmc2V0ID0gdGhpcy5iYiEuX19vZmZzZXQodGhpcy5iYl9wb3MsIDYpO1xuICAgICAgcmV0dXJuIG9mZnNldCA/IHRoaXMuYmIhLl9fdmVjdG9yX2xlbih0aGlzLmJiX3BvcyArIG9mZnNldCkgOiAwO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CdWlsZGVyIGJ1aWxkZXJcbiAgICAgKi9cbiAgICBzdGF0aWMgc3RhcnRTZXNzaW9uU3RhdGUoYnVpbGRlcjogZmxhdGJ1ZmZlcnMuQnVpbGRlcikge1xuICAgICAgYnVpbGRlci5zdGFydE9iamVjdCgyKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuQnVpbGRlciBidWlsZGVyXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLk9mZnNldCBrZXJuZWxzT2Zmc2V0XG4gICAgICovXG4gICAgc3RhdGljIGFkZEtlcm5lbHMoYnVpbGRlcjogZmxhdGJ1ZmZlcnMuQnVpbGRlciwga2VybmVsc09mZnNldDogZmxhdGJ1ZmZlcnMuT2Zmc2V0KSB7XG4gICAgICBidWlsZGVyLmFkZEZpZWxkT2Zmc2V0KDAsIGtlcm5lbHNPZmZzZXQsIDApO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CdWlsZGVyIGJ1aWxkZXJcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuT2Zmc2V0IHN1YkdyYXBoU2Vzc2lvblN0YXRlc09mZnNldFxuICAgICAqL1xuICAgIHN0YXRpYyBhZGRTdWJHcmFwaFNlc3Npb25TdGF0ZXMoYnVpbGRlcjogZmxhdGJ1ZmZlcnMuQnVpbGRlciwgc3ViR3JhcGhTZXNzaW9uU3RhdGVzT2Zmc2V0OiBmbGF0YnVmZmVycy5PZmZzZXQpIHtcbiAgICAgIGJ1aWxkZXIuYWRkRmllbGRPZmZzZXQoMSwgc3ViR3JhcGhTZXNzaW9uU3RhdGVzT2Zmc2V0LCAwKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuQnVpbGRlciBidWlsZGVyXG4gICAgICogQHBhcmFtIEFycmF5LjxmbGF0YnVmZmVycy5PZmZzZXQ+IGRhdGFcbiAgICAgKiBAcmV0dXJucyBmbGF0YnVmZmVycy5PZmZzZXRcbiAgICAgKi9cbiAgICBzdGF0aWMgY3JlYXRlU3ViR3JhcGhTZXNzaW9uU3RhdGVzVmVjdG9yKGJ1aWxkZXI6IGZsYXRidWZmZXJzLkJ1aWxkZXIsIGRhdGE6IGZsYXRidWZmZXJzLk9mZnNldFtdKTpcbiAgICAgICAgZmxhdGJ1ZmZlcnMuT2Zmc2V0IHtcbiAgICAgIGJ1aWxkZXIuc3RhcnRWZWN0b3IoNCwgZGF0YS5sZW5ndGgsIDQpO1xuICAgICAgZm9yIChsZXQgaSA9IGRhdGEubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICAgICAgYnVpbGRlci5hZGRPZmZzZXQoZGF0YVtpXSk7XG4gICAgICB9XG4gICAgICByZXR1cm4gYnVpbGRlci5lbmRWZWN0b3IoKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuQnVpbGRlciBidWlsZGVyXG4gICAgICogQHBhcmFtIG51bWJlciBudW1FbGVtc1xuICAgICAqL1xuICAgIHN0YXRpYyBzdGFydFN1YkdyYXBoU2Vzc2lvblN0YXRlc1ZlY3RvcihidWlsZGVyOiBmbGF0YnVmZmVycy5CdWlsZGVyLCBudW1FbGVtczogbnVtYmVyKSB7XG4gICAgICBidWlsZGVyLnN0YXJ0VmVjdG9yKDQsIG51bUVsZW1zLCA0KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuQnVpbGRlciBidWlsZGVyXG4gICAgICogQHJldHVybnMgZmxhdGJ1ZmZlcnMuT2Zmc2V0XG4gICAgICovXG4gICAgc3RhdGljIGVuZFNlc3Npb25TdGF0ZShidWlsZGVyOiBmbGF0YnVmZmVycy5CdWlsZGVyKTogZmxhdGJ1ZmZlcnMuT2Zmc2V0IHtcbiAgICAgIGxldCBvZmZzZXQgPSBidWlsZGVyLmVuZE9iamVjdCgpO1xuICAgICAgcmV0dXJuIG9mZnNldDtcbiAgICB9XG5cbiAgICBzdGF0aWMgY3JlYXRlU2Vzc2lvblN0YXRlKFxuICAgICAgICBidWlsZGVyOiBmbGF0YnVmZmVycy5CdWlsZGVyLCBrZXJuZWxzT2Zmc2V0OiBmbGF0YnVmZmVycy5PZmZzZXQsXG4gICAgICAgIHN1YkdyYXBoU2Vzc2lvblN0YXRlc09mZnNldDogZmxhdGJ1ZmZlcnMuT2Zmc2V0KTogZmxhdGJ1ZmZlcnMuT2Zmc2V0IHtcbiAgICAgIFNlc3Npb25TdGF0ZS5zdGFydFNlc3Npb25TdGF0ZShidWlsZGVyKTtcbiAgICAgIFNlc3Npb25TdGF0ZS5hZGRLZXJuZWxzKGJ1aWxkZXIsIGtlcm5lbHNPZmZzZXQpO1xuICAgICAgU2Vzc2lvblN0YXRlLmFkZFN1YkdyYXBoU2Vzc2lvblN0YXRlcyhidWlsZGVyLCBzdWJHcmFwaFNlc3Npb25TdGF0ZXNPZmZzZXQpO1xuICAgICAgcmV0dXJuIFNlc3Npb25TdGF0ZS5lbmRTZXNzaW9uU3RhdGUoYnVpbGRlcik7XG4gICAgfVxuICB9XG59XG4vKipcbiAqIEBjb25zdHJ1Y3RvclxuICovXG5leHBvcnQgbmFtZXNwYWNlIG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnMge1xuICBleHBvcnQgY2xhc3MgSW5mZXJlbmNlU2Vzc2lvbiB7XG4gICAgYmI6IGZsYXRidWZmZXJzLkJ5dGVCdWZmZXJ8bnVsbCA9IG51bGw7XG5cbiAgICBiYl9wb3MgPSAwO1xuICAgIC8qKlxuICAgICAqIEBwYXJhbSBudW1iZXIgaVxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CeXRlQnVmZmVyIGJiXG4gICAgICogQHJldHVybnMgSW5mZXJlbmNlU2Vzc2lvblxuICAgICAqL1xuICAgIF9faW5pdChpOiBudW1iZXIsIGJiOiBmbGF0YnVmZmVycy5CeXRlQnVmZmVyKTogSW5mZXJlbmNlU2Vzc2lvbiB7XG4gICAgICB0aGlzLmJiX3BvcyA9IGk7XG4gICAgICB0aGlzLmJiID0gYmI7XG4gICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuQnl0ZUJ1ZmZlciBiYlxuICAgICAqIEBwYXJhbSBJbmZlcmVuY2VTZXNzaW9uPSBvYmpcbiAgICAgKiBAcmV0dXJucyBJbmZlcmVuY2VTZXNzaW9uXG4gICAgICovXG4gICAgc3RhdGljIGdldFJvb3RBc0luZmVyZW5jZVNlc3Npb24oYmI6IGZsYXRidWZmZXJzLkJ5dGVCdWZmZXIsIG9iaj86IEluZmVyZW5jZVNlc3Npb24pOiBJbmZlcmVuY2VTZXNzaW9uIHtcbiAgICAgIHJldHVybiAob2JqIHx8IG5ldyBJbmZlcmVuY2VTZXNzaW9uKCkpLl9faW5pdChiYi5yZWFkSW50MzIoYmIucG9zaXRpb24oKSkgKyBiYi5wb3NpdGlvbigpLCBiYik7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ5dGVCdWZmZXIgYmJcbiAgICAgKiBAcGFyYW0gSW5mZXJlbmNlU2Vzc2lvbj0gb2JqXG4gICAgICogQHJldHVybnMgSW5mZXJlbmNlU2Vzc2lvblxuICAgICAqL1xuICAgIHN0YXRpYyBnZXRTaXplUHJlZml4ZWRSb290QXNJbmZlcmVuY2VTZXNzaW9uKGJiOiBmbGF0YnVmZmVycy5CeXRlQnVmZmVyLCBvYmo/OiBJbmZlcmVuY2VTZXNzaW9uKTogSW5mZXJlbmNlU2Vzc2lvbiB7XG4gICAgICBiYi5zZXRQb3NpdGlvbihiYi5wb3NpdGlvbigpICsgZmxhdGJ1ZmZlcnMuU0laRV9QUkVGSVhfTEVOR1RIKTtcbiAgICAgIHJldHVybiAob2JqIHx8IG5ldyBJbmZlcmVuY2VTZXNzaW9uKCkpLl9faW5pdChiYi5yZWFkSW50MzIoYmIucG9zaXRpb24oKSkgKyBiYi5wb3NpdGlvbigpLCBiYik7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ5dGVCdWZmZXIgYmJcbiAgICAgKiBAcmV0dXJucyBib29sZWFuXG4gICAgICovXG4gICAgc3RhdGljIGJ1ZmZlckhhc0lkZW50aWZpZXIoYmI6IGZsYXRidWZmZXJzLkJ5dGVCdWZmZXIpOiBib29sZWFuIHtcbiAgICAgIHJldHVybiBiYi5fX2hhc19pZGVudGlmaWVyKCdPUlRNJyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkVuY29kaW5nPSBvcHRpb25hbEVuY29kaW5nXG4gICAgICogQHJldHVybnMgc3RyaW5nfFVpbnQ4QXJyYXl8bnVsbFxuICAgICAqL1xuICAgIG9ydFZlcnNpb24oKTogc3RyaW5nfG51bGw7XG4gICAgb3J0VmVyc2lvbihvcHRpb25hbEVuY29kaW5nOiBmbGF0YnVmZmVycy5FbmNvZGluZyk6IHN0cmluZ3xVaW50OEFycmF5fG51bGw7XG4gICAgb3J0VmVyc2lvbihvcHRpb25hbEVuY29kaW5nPzogYW55KTogc3RyaW5nfFVpbnQ4QXJyYXl8bnVsbCB7XG4gICAgICBsZXQgb2Zmc2V0ID0gdGhpcy5iYiEuX19vZmZzZXQodGhpcy5iYl9wb3MsIDQpO1xuICAgICAgcmV0dXJuIG9mZnNldCA/IHRoaXMuYmIhLl9fc3RyaW5nKHRoaXMuYmJfcG9zICsgb2Zmc2V0LCBvcHRpb25hbEVuY29kaW5nKSA6IG51bGw7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnMuTW9kZWw9IG9ialxuICAgICAqIEByZXR1cm5zIG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnMuTW9kZWx8bnVsbFxuICAgICAqL1xuICAgIG1vZGVsKG9iaj86IG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnMuTW9kZWwpOiBvbm54cnVudGltZS5leHBlcmltZW50YWwuZmJzLk1vZGVsfG51bGwge1xuICAgICAgbGV0IG9mZnNldCA9IHRoaXMuYmIhLl9fb2Zmc2V0KHRoaXMuYmJfcG9zLCA2KTtcbiAgICAgIHJldHVybiBvZmZzZXQgPyAob2JqIHx8IG5ldyBvbm54cnVudGltZS5leHBlcmltZW50YWwuZmJzLk1vZGVsKCkpXG4gICAgICAgICAgICAgICAgICAgICAgICAgIC5fX2luaXQodGhpcy5iYiEuX19pbmRpcmVjdCh0aGlzLmJiX3BvcyArIG9mZnNldCksIHRoaXMuYmIhKSA6XG4gICAgICAgICAgICAgICAgICAgICAgbnVsbDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gb25ueHJ1bnRpbWUuZXhwZXJpbWVudGFsLmZicy5TZXNzaW9uU3RhdGU9IG9ialxuICAgICAqIEByZXR1cm5zIG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnMuU2Vzc2lvblN0YXRlfG51bGxcbiAgICAgKi9cbiAgICBzZXNzaW9uU3RhdGUob2JqPzogb25ueHJ1bnRpbWUuZXhwZXJpbWVudGFsLmZicy5TZXNzaW9uU3RhdGUpOiBvbm54cnVudGltZS5leHBlcmltZW50YWwuZmJzLlNlc3Npb25TdGF0ZXxudWxsIHtcbiAgICAgIGxldCBvZmZzZXQgPSB0aGlzLmJiIS5fX29mZnNldCh0aGlzLmJiX3BvcywgOCk7XG4gICAgICByZXR1cm4gb2Zmc2V0ID8gKG9iaiB8fCBuZXcgb25ueHJ1bnRpbWUuZXhwZXJpbWVudGFsLmZicy5TZXNzaW9uU3RhdGUoKSlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgLl9faW5pdCh0aGlzLmJiIS5fX2luZGlyZWN0KHRoaXMuYmJfcG9zICsgb2Zmc2V0KSwgdGhpcy5iYiEpIDpcbiAgICAgICAgICAgICAgICAgICAgICBudWxsO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CdWlsZGVyIGJ1aWxkZXJcbiAgICAgKi9cbiAgICBzdGF0aWMgc3RhcnRJbmZlcmVuY2VTZXNzaW9uKGJ1aWxkZXI6IGZsYXRidWZmZXJzLkJ1aWxkZXIpIHtcbiAgICAgIGJ1aWxkZXIuc3RhcnRPYmplY3QoMyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ1aWxkZXIgYnVpbGRlclxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5PZmZzZXQgb3J0VmVyc2lvbk9mZnNldFxuICAgICAqL1xuICAgIHN0YXRpYyBhZGRPcnRWZXJzaW9uKGJ1aWxkZXI6IGZsYXRidWZmZXJzLkJ1aWxkZXIsIG9ydFZlcnNpb25PZmZzZXQ6IGZsYXRidWZmZXJzLk9mZnNldCkge1xuICAgICAgYnVpbGRlci5hZGRGaWVsZE9mZnNldCgwLCBvcnRWZXJzaW9uT2Zmc2V0LCAwKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuQnVpbGRlciBidWlsZGVyXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLk9mZnNldCBtb2RlbE9mZnNldFxuICAgICAqL1xuICAgIHN0YXRpYyBhZGRNb2RlbChidWlsZGVyOiBmbGF0YnVmZmVycy5CdWlsZGVyLCBtb2RlbE9mZnNldDogZmxhdGJ1ZmZlcnMuT2Zmc2V0KSB7XG4gICAgICBidWlsZGVyLmFkZEZpZWxkT2Zmc2V0KDEsIG1vZGVsT2Zmc2V0LCAwKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuQnVpbGRlciBidWlsZGVyXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLk9mZnNldCBzZXNzaW9uU3RhdGVPZmZzZXRcbiAgICAgKi9cbiAgICBzdGF0aWMgYWRkU2Vzc2lvblN0YXRlKGJ1aWxkZXI6IGZsYXRidWZmZXJzLkJ1aWxkZXIsIHNlc3Npb25TdGF0ZU9mZnNldDogZmxhdGJ1ZmZlcnMuT2Zmc2V0KSB7XG4gICAgICBidWlsZGVyLmFkZEZpZWxkT2Zmc2V0KDIsIHNlc3Npb25TdGF0ZU9mZnNldCwgMCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ1aWxkZXIgYnVpbGRlclxuICAgICAqIEByZXR1cm5zIGZsYXRidWZmZXJzLk9mZnNldFxuICAgICAqL1xuICAgIHN0YXRpYyBlbmRJbmZlcmVuY2VTZXNzaW9uKGJ1aWxkZXI6IGZsYXRidWZmZXJzLkJ1aWxkZXIpOiBmbGF0YnVmZmVycy5PZmZzZXQge1xuICAgICAgbGV0IG9mZnNldCA9IGJ1aWxkZXIuZW5kT2JqZWN0KCk7XG4gICAgICByZXR1cm4gb2Zmc2V0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CdWlsZGVyIGJ1aWxkZXJcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuT2Zmc2V0IG9mZnNldFxuICAgICAqL1xuICAgIHN0YXRpYyBmaW5pc2hJbmZlcmVuY2VTZXNzaW9uQnVmZmVyKGJ1aWxkZXI6IGZsYXRidWZmZXJzLkJ1aWxkZXIsIG9mZnNldDogZmxhdGJ1ZmZlcnMuT2Zmc2V0KSB7XG4gICAgICBidWlsZGVyLmZpbmlzaChvZmZzZXQsICdPUlRNJyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ1aWxkZXIgYnVpbGRlclxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5PZmZzZXQgb2Zmc2V0XG4gICAgICovXG4gICAgc3RhdGljIGZpbmlzaFNpemVQcmVmaXhlZEluZmVyZW5jZVNlc3Npb25CdWZmZXIoYnVpbGRlcjogZmxhdGJ1ZmZlcnMuQnVpbGRlciwgb2Zmc2V0OiBmbGF0YnVmZmVycy5PZmZzZXQpIHtcbiAgICAgIGJ1aWxkZXIuZmluaXNoKG9mZnNldCwgJ09SVE0nLCB0cnVlKTtcbiAgICB9XG5cbiAgICBzdGF0aWMgY3JlYXRlSW5mZXJlbmNlU2Vzc2lvbihcbiAgICAgICAgYnVpbGRlcjogZmxhdGJ1ZmZlcnMuQnVpbGRlciwgb3J0VmVyc2lvbk9mZnNldDogZmxhdGJ1ZmZlcnMuT2Zmc2V0LCBtb2RlbE9mZnNldDogZmxhdGJ1ZmZlcnMuT2Zmc2V0LFxuICAgICAgICBzZXNzaW9uU3RhdGVPZmZzZXQ6IGZsYXRidWZmZXJzLk9mZnNldCk6IGZsYXRidWZmZXJzLk9mZnNldCB7XG4gICAgICBJbmZlcmVuY2VTZXNzaW9uLnN0YXJ0SW5mZXJlbmNlU2Vzc2lvbihidWlsZGVyKTtcbiAgICAgIEluZmVyZW5jZVNlc3Npb24uYWRkT3J0VmVyc2lvbihidWlsZGVyLCBvcnRWZXJzaW9uT2Zmc2V0KTtcbiAgICAgIEluZmVyZW5jZVNlc3Npb24uYWRkTW9kZWwoYnVpbGRlciwgbW9kZWxPZmZzZXQpO1xuICAgICAgSW5mZXJlbmNlU2Vzc2lvbi5hZGRTZXNzaW9uU3RhdGUoYnVpbGRlciwgc2Vzc2lvblN0YXRlT2Zmc2V0KTtcbiAgICAgIHJldHVybiBJbmZlcmVuY2VTZXNzaW9uLmVuZEluZmVyZW5jZVNlc3Npb24oYnVpbGRlcik7XG4gICAgfVxuICB9XG59XG4iLCIvLyBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cblxuaW1wb3J0IHtJbmZlcmVuY2VTZXNzaW9uLCBTZXNzaW9uSGFuZGxlciwgVGVuc29yfSBmcm9tICdvbm54cnVudGltZS1jb21tb24nO1xuXG5pbXBvcnQge1Nlc3Npb259IGZyb20gJy4vc2Vzc2lvbic7XG5pbXBvcnQge1RlbnNvciBhcyBPbm54anNUZW5zb3J9IGZyb20gJy4vdGVuc29yJztcblxuZXhwb3J0IGNsYXNzIE9ubnhqc1Nlc3Npb25IYW5kbGVyIGltcGxlbWVudHMgU2Vzc2lvbkhhbmRsZXIge1xuICBjb25zdHJ1Y3Rvcihwcml2YXRlIHNlc3Npb246IFNlc3Npb24pIHtcbiAgICB0aGlzLmlucHV0TmFtZXMgPSB0aGlzLnNlc3Npb24uaW5wdXROYW1lcztcbiAgICB0aGlzLm91dHB1dE5hbWVzID0gdGhpcy5zZXNzaW9uLm91dHB1dE5hbWVzO1xuICB9XG5cbiAgYXN5bmMgZGlzcG9zZSgpOiBQcm9taXNlPHZvaWQ+IHt9XG4gIGlucHV0TmFtZXM6IHJlYWRvbmx5IHN0cmluZ1tdO1xuICBvdXRwdXROYW1lczogcmVhZG9ubHkgc3RyaW5nW107XG4gIGFzeW5jIHJ1bihcbiAgICAgIGZlZWRzOiBTZXNzaW9uSGFuZGxlci5GZWVkc1R5cGUsIF9mZXRjaGVzOiBTZXNzaW9uSGFuZGxlci5GZXRjaGVzVHlwZSxcbiAgICAgIF9vcHRpb25zOiBJbmZlcmVuY2VTZXNzaW9uLlJ1bk9wdGlvbnMpOiBQcm9taXNlPFNlc3Npb25IYW5kbGVyLlJldHVyblR5cGU+IHtcbiAgICBjb25zdCBpbnB1dE1hcCA9IG5ldyBNYXA8c3RyaW5nLCBPbm54anNUZW5zb3I+KCk7XG4gICAgZm9yIChjb25zdCBuYW1lIGluIGZlZWRzKSB7XG4gICAgICBpZiAoT2JqZWN0Lmhhc093blByb3BlcnR5LmNhbGwoZmVlZHMsIG5hbWUpKSB7XG4gICAgICAgIGNvbnN0IGZlZWQgPSBmZWVkc1tuYW1lXTtcbiAgICAgICAgaW5wdXRNYXAuc2V0KFxuICAgICAgICAgICAgbmFtZSxcbiAgICAgICAgICAgIG5ldyBPbm54anNUZW5zb3IoXG4gICAgICAgICAgICAgICAgZmVlZC5kaW1zLCBmZWVkLnR5cGUgYXMgT25ueGpzVGVuc29yLkRhdGFUeXBlLCB1bmRlZmluZWQsIHVuZGVmaW5lZCxcbiAgICAgICAgICAgICAgICBmZWVkLmRhdGEgYXMgT25ueGpzVGVuc29yLk51bWJlclR5cGUpKTtcbiAgICAgIH1cbiAgICB9XG4gICAgY29uc3Qgb3V0cHV0TWFwID0gYXdhaXQgdGhpcy5zZXNzaW9uLnJ1bihpbnB1dE1hcCk7XG4gICAgY29uc3Qgb3V0cHV0OiBTZXNzaW9uSGFuZGxlci5SZXR1cm5UeXBlID0ge307XG4gICAgb3V0cHV0TWFwLmZvckVhY2goKHRlbnNvciwgbmFtZSkgPT4ge1xuICAgICAgb3V0cHV0W25hbWVdID0gbmV3IFRlbnNvcih0ZW5zb3IudHlwZSwgdGVuc29yLmRhdGEsIHRlbnNvci5kaW1zKTtcbiAgICB9KTtcbiAgICByZXR1cm4gb3V0cHV0O1xuICB9XG4gIHN0YXJ0UHJvZmlsaW5nKCk6IHZvaWQge1xuICAgIHRoaXMuc2Vzc2lvbi5zdGFydFByb2ZpbGluZygpO1xuICB9XG4gIGVuZFByb2ZpbGluZygpOiB2b2lkIHtcbiAgICB0aGlzLnNlc3Npb24uZW5kUHJvZmlsaW5nKCk7XG4gIH1cbn1cbiIsIi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxuXG5pbXBvcnQge3JlYWRGaWxlfSBmcm9tICdmcyc7XG5pbXBvcnQge3Byb21pc2lmeX0gZnJvbSAndXRpbCc7XG5cbmltcG9ydCB7cmVzb2x2ZUJhY2tlbmQsIFNlc3Npb25IYW5kbGVyVHlwZX0gZnJvbSAnLi9iYWNrZW5kJztcbmltcG9ydCB7RXhlY3V0aW9uUGxhbn0gZnJvbSAnLi9leGVjdXRpb24tcGxhbic7XG5pbXBvcnQge0dyYXBofSBmcm9tICcuL2dyYXBoJztcbmltcG9ydCB7UHJvZmlsZXJ9IGZyb20gJy4vaW5zdHJ1bWVudCc7XG5pbXBvcnQge01vZGVsfSBmcm9tICcuL21vZGVsJztcbmltcG9ydCB7T3BlcmF0b3J9IGZyb20gJy4vb3BlcmF0b3JzJztcbmltcG9ydCB7VGVuc29yfSBmcm9tICcuL3RlbnNvcic7XG5cbmV4cG9ydCBkZWNsYXJlIG5hbWVzcGFjZSBTZXNzaW9uIHtcbiAgZXhwb3J0IGludGVyZmFjZSBDb25maWcge1xuICAgIGJhY2tlbmRIaW50Pzogc3RyaW5nO1xuICAgIHByb2ZpbGVyPzogUHJvZmlsZXIuQ29uZmlnO1xuICB9XG5cbiAgZXhwb3J0IGludGVyZmFjZSBDb250ZXh0IHtcbiAgICBwcm9maWxlcjogUmVhZG9ubHk8UHJvZmlsZXI+O1xuICAgIGdyYXBoSW5wdXRUeXBlcz86IFRlbnNvci5EYXRhVHlwZVtdO1xuICAgIGdyYXBoSW5wdXREaW1zPzogQXJyYXk8cmVhZG9ubHkgbnVtYmVyW10+O1xuICB9XG59XG5cbmV4cG9ydCBjbGFzcyBTZXNzaW9uIHtcbiAgY29uc3RydWN0b3IoY29uZmlnOiBTZXNzaW9uLkNvbmZpZyA9IHt9KSB7XG4gICAgdGhpcy5faW5pdGlhbGl6ZWQgPSBmYWxzZTtcbiAgICB0aGlzLmJhY2tlbmRIaW50ID0gY29uZmlnLmJhY2tlbmRIaW50O1xuICAgIHRoaXMucHJvZmlsZXIgPSBQcm9maWxlci5jcmVhdGUoY29uZmlnLnByb2ZpbGVyKTtcbiAgICB0aGlzLmNvbnRleHQgPSB7cHJvZmlsZXI6IHRoaXMucHJvZmlsZXIsIGdyYXBoSW5wdXRUeXBlczogW10sIGdyYXBoSW5wdXREaW1zOiBbXX07XG4gIH1cblxuICBnZXQgaW5wdXROYW1lcygpOiByZWFkb25seSBzdHJpbmdbXSB7XG4gICAgcmV0dXJuIHRoaXMuX21vZGVsLmdyYXBoLmdldElucHV0TmFtZXMoKTtcbiAgfVxuICBnZXQgb3V0cHV0TmFtZXMoKTogcmVhZG9ubHkgc3RyaW5nW10ge1xuICAgIHJldHVybiB0aGlzLl9tb2RlbC5ncmFwaC5nZXRPdXRwdXROYW1lcygpO1xuICB9XG5cbiAgc3RhcnRQcm9maWxpbmcoKSB7XG4gICAgdGhpcy5wcm9maWxlci5zdGFydCgpO1xuICB9XG5cbiAgZW5kUHJvZmlsaW5nKCkge1xuICAgIHRoaXMucHJvZmlsZXIuc3RvcCgpO1xuICB9XG5cbiAgYXN5bmMgbG9hZE1vZGVsKHVyaTogc3RyaW5nKTogUHJvbWlzZTx2b2lkPjtcbiAgYXN5bmMgbG9hZE1vZGVsKGJ1ZmZlcjogQXJyYXlCdWZmZXIsIGJ5dGVPZmZzZXQ/OiBudW1iZXIsIGxlbmd0aD86IG51bWJlcik6IFByb21pc2U8dm9pZD47XG4gIGFzeW5jIGxvYWRNb2RlbChidWZmZXI6IFVpbnQ4QXJyYXkpOiBQcm9taXNlPHZvaWQ+O1xuICBhc3luYyBsb2FkTW9kZWwoYXJnOiBzdHJpbmd8QXJyYXlCdWZmZXJ8VWludDhBcnJheSwgYnl0ZU9mZnNldD86IG51bWJlciwgbGVuZ3RoPzogbnVtYmVyKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgYXdhaXQgdGhpcy5wcm9maWxlci5ldmVudCgnc2Vzc2lvbicsICdTZXNzaW9uLmxvYWRNb2RlbCcsIGFzeW5jICgpID0+IHtcbiAgICAgIC8vIHJlc29sdmUgYmFja2VuZCBhbmQgc2Vzc2lvbiBoYW5kbGVyXG4gICAgICBjb25zdCBiYWNrZW5kID0gYXdhaXQgcmVzb2x2ZUJhY2tlbmQodGhpcy5iYWNrZW5kSGludCk7XG4gICAgICB0aGlzLnNlc3Npb25IYW5kbGVyID0gYmFja2VuZC5jcmVhdGVTZXNzaW9uSGFuZGxlcih0aGlzLmNvbnRleHQpO1xuXG4gICAgICB0aGlzLl9tb2RlbCA9IG5ldyBNb2RlbCgpO1xuICAgICAgaWYgKHR5cGVvZiBhcmcgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgIGNvbnN0IGlzT3J0Rm9ybWF0ID0gYXJnLmVuZHNXaXRoKCcub3J0Jyk7XG4gICAgICAgIGlmICh0eXBlb2YgZmV0Y2ggPT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgLy8gbm9kZVxuICAgICAgICAgIGNvbnN0IGJ1ZiA9IGF3YWl0IHByb21pc2lmeShyZWFkRmlsZSkoYXJnKTtcbiAgICAgICAgICB0aGlzLmluaXRpYWxpemUoYnVmLCBpc09ydEZvcm1hdCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgLy8gYnJvd3NlclxuICAgICAgICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgZmV0Y2goYXJnKTtcbiAgICAgICAgICBjb25zdCBidWYgPSBhd2FpdCByZXNwb25zZS5hcnJheUJ1ZmZlcigpO1xuICAgICAgICAgIHRoaXMuaW5pdGlhbGl6ZShuZXcgVWludDhBcnJheShidWYpLCBpc09ydEZvcm1hdCk7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSBpZiAoIUFycmF5QnVmZmVyLmlzVmlldyhhcmcpKSB7XG4gICAgICAgIC8vIGxvYWQgbW9kZWwgZnJvbSBBcnJheUJ1ZmZlclxuICAgICAgICBjb25zdCBhcnIgPSBuZXcgVWludDhBcnJheShhcmcsIGJ5dGVPZmZzZXQgfHwgMCwgbGVuZ3RoIHx8IGFyZy5ieXRlTGVuZ3RoKTtcbiAgICAgICAgdGhpcy5pbml0aWFsaXplKGFycik7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICAvLyBsb2FkIG1vZGVsIGZyb20gVWludDhhcnJheVxuICAgICAgICB0aGlzLmluaXRpYWxpemUoYXJnKTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfVxuXG4gIHByaXZhdGUgaW5pdGlhbGl6ZShtb2RlbFByb3RvQmxvYjogVWludDhBcnJheSwgaXNPcnRGb3JtYXQ/OiBib29sZWFuKTogdm9pZCB7XG4gICAgaWYgKHRoaXMuX2luaXRpYWxpemVkKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ2FscmVhZHkgaW5pdGlhbGl6ZWQnKTtcbiAgICB9XG5cbiAgICB0aGlzLnByb2ZpbGVyLmV2ZW50KCdzZXNzaW9uJywgJ1Nlc3Npb24uaW5pdGlhbGl6ZScsICgpID0+IHtcbiAgICAgIC8vIGxvYWQgZ3JhcGhcbiAgICAgIGNvbnN0IGdyYXBoSW5pdGlhbGl6ZXIgPVxuICAgICAgICAgIHRoaXMuc2Vzc2lvbkhhbmRsZXIudHJhbnNmb3JtR3JhcGggPyB0aGlzLnNlc3Npb25IYW5kbGVyIGFzIEdyYXBoLkluaXRpYWxpemVyIDogdW5kZWZpbmVkO1xuICAgICAgdGhpcy5fbW9kZWwubG9hZChtb2RlbFByb3RvQmxvYiwgZ3JhcGhJbml0aWFsaXplciwgaXNPcnRGb3JtYXQpO1xuXG4gICAgICAvLyBncmFwaCBpcyBjb21wbGV0ZWx5IGluaXRpYWx6aWVkIGF0IHRoaXMgc3RhZ2UgLCBsZXQgdGhlIGludGVyZXN0ZWQgaGFuZGxlcnMga25vd1xuICAgICAgaWYgKHRoaXMuc2Vzc2lvbkhhbmRsZXIub25HcmFwaEluaXRpYWxpemVkKSB7XG4gICAgICAgIHRoaXMuc2Vzc2lvbkhhbmRsZXIub25HcmFwaEluaXRpYWxpemVkKHRoaXMuX21vZGVsLmdyYXBoKTtcbiAgICAgIH1cbiAgICAgIC8vIGluaXRpYWxpemUgZWFjaCBvcGVyYXRvciBpbiB0aGUgZ3JhcGhcbiAgICAgIHRoaXMuaW5pdGlhbGl6ZU9wcyh0aGlzLl9tb2RlbC5ncmFwaCk7XG5cbiAgICAgIC8vIGluc3RhbnRpYXRlIGFuIEV4ZWN1dGlvblBsYW4gb2JqZWN0IHRvIGJlIHVzZWQgYnkgdGhlIFNlc3Npb24gb2JqZWN0XG4gICAgICB0aGlzLl9leGVjdXRpb25QbGFuID0gbmV3IEV4ZWN1dGlvblBsYW4odGhpcy5fbW9kZWwuZ3JhcGgsIHRoaXMuX29wcywgdGhpcy5wcm9maWxlcik7XG4gICAgfSk7XG5cbiAgICB0aGlzLl9pbml0aWFsaXplZCA9IHRydWU7XG4gIH1cblxuICBhc3luYyBydW4oaW5wdXRzOiBNYXA8c3RyaW5nLCBUZW5zb3I+fFRlbnNvcltdKTogUHJvbWlzZTxNYXA8c3RyaW5nLCBUZW5zb3I+PiB7XG4gICAgaWYgKCF0aGlzLl9pbml0aWFsaXplZCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdzZXNzaW9uIG5vdCBpbml0aWFsaXplZCB5ZXQnKTtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcy5wcm9maWxlci5ldmVudCgnc2Vzc2lvbicsICdTZXNzaW9uLnJ1bicsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IGlucHV0VGVuc29ycyA9IHRoaXMubm9ybWFsaXplQW5kVmFsaWRhdGVJbnB1dHMoaW5wdXRzKTtcblxuICAgICAgY29uc3Qgb3V0cHV0VGVuc29ycyA9IGF3YWl0IHRoaXMuX2V4ZWN1dGlvblBsYW4uZXhlY3V0ZSh0aGlzLnNlc3Npb25IYW5kbGVyLCBpbnB1dFRlbnNvcnMpO1xuXG4gICAgICByZXR1cm4gdGhpcy5jcmVhdGVPdXRwdXQob3V0cHV0VGVuc29ycyk7XG4gICAgfSk7XG4gIH1cblxuICBwcml2YXRlIG5vcm1hbGl6ZUFuZFZhbGlkYXRlSW5wdXRzKGlucHV0czogTWFwPHN0cmluZywgVGVuc29yPnxUZW5zb3JbXSk6IFRlbnNvcltdIHtcbiAgICBjb25zdCBtb2RlbElucHV0TmFtZXMgPSB0aGlzLl9tb2RlbC5ncmFwaC5nZXRJbnB1dE5hbWVzKCk7XG5cbiAgICAvLyBub3JtYWxpemUgaW5wdXRzXG4gICAgLy8gaW5wdXRzOiBUZW5zb3JbXVxuICAgIGlmIChBcnJheS5pc0FycmF5KGlucHV0cykpIHtcbiAgICAgIGlmIChpbnB1dHMubGVuZ3RoICE9PSBtb2RlbElucHV0TmFtZXMubGVuZ3RoKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgaW5jb3JyZWN0IGlucHV0IGFycmF5IGxlbmd0aDogZXhwZWN0ZWQgJHttb2RlbElucHV0TmFtZXMubGVuZ3RofSBidXQgZ290ICR7aW5wdXRzLmxlbmd0aH1gKTtcbiAgICAgIH1cbiAgICB9XG4gICAgLy8gY29udmVydCBtYXAgdG8gYXJyYXlcbiAgICAvLyBpbnB1dHM6IE1hcDxzdHJpbmcsIFRlbnNvcj5cbiAgICBlbHNlIHtcbiAgICAgIGlmIChpbnB1dHMuc2l6ZSAhPT0gbW9kZWxJbnB1dE5hbWVzLmxlbmd0aCkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYGluY29ycmVjdCBpbnB1dCBtYXAgc2l6ZTogZXhwZWN0ZWQgJHttb2RlbElucHV0TmFtZXMubGVuZ3RofSBidXQgZ290ICR7aW5wdXRzLnNpemV9YCk7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IHNvcnRlZElucHV0cyA9IG5ldyBBcnJheTxUZW5zb3I+KGlucHV0cy5zaXplKTtcbiAgICAgIGxldCBzb3J0ZWRJbnB1dHNJbmRleCA9IDA7XG4gICAgICBmb3IgKGxldCBpID0gMDsgaSA8IG1vZGVsSW5wdXROYW1lcy5sZW5ndGg7ICsraSkge1xuICAgICAgICBjb25zdCB0ZW5zb3IgPSBpbnB1dHMuZ2V0KG1vZGVsSW5wdXROYW1lc1tpXSk7XG4gICAgICAgIGlmICghdGVuc29yKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBtaXNzaW5nIGlucHV0IHRlbnNvciBmb3I6ICcke25hbWV9J2ApO1xuICAgICAgICB9XG4gICAgICAgIHNvcnRlZElucHV0c1tzb3J0ZWRJbnB1dHNJbmRleCsrXSA9IHRlbnNvcjtcbiAgICAgIH1cblxuICAgICAgaW5wdXRzID0gc29ydGVkSW5wdXRzO1xuICAgIH1cblxuICAgIC8vIHZhbGlkYXRlIGRpbXMgcmVxdWlyZW1lbnRzXG4gICAgLy8gRmlyc3Qgc2Vzc2lvbiBydW4gLSBncmFwaCBpbnB1dCBkYXRhIGlzIG5vdCBjYWNoZWQgZm9yIHRoZSBzZXNzaW9uXG4gICAgaWYgKCF0aGlzLmNvbnRleHQuZ3JhcGhJbnB1dFR5cGVzIHx8IHRoaXMuY29udGV4dC5ncmFwaElucHV0VHlwZXMubGVuZ3RoID09PSAwIHx8ICF0aGlzLmNvbnRleHQuZ3JhcGhJbnB1dERpbXMgfHxcbiAgICAgICAgdGhpcy5jb250ZXh0LmdyYXBoSW5wdXREaW1zLmxlbmd0aCA9PT0gMCkge1xuICAgICAgY29uc3QgbW9kZWxJbnB1dEluZGljZXMgPSB0aGlzLl9tb2RlbC5ncmFwaC5nZXRJbnB1dEluZGljZXMoKTtcbiAgICAgIGNvbnN0IG1vZGVsVmFsdWVzID0gdGhpcy5fbW9kZWwuZ3JhcGguZ2V0VmFsdWVzKCk7XG5cbiAgICAgIGNvbnN0IGdyYXBoSW5wdXREaW1zID0gbmV3IEFycmF5PHJlYWRvbmx5IG51bWJlcltdPihtb2RlbElucHV0SW5kaWNlcy5sZW5ndGgpO1xuXG4gICAgICBmb3IgKGxldCBpID0gMDsgaSA8IG1vZGVsSW5wdXRJbmRpY2VzLmxlbmd0aDsgKytpKSB7XG4gICAgICAgIGNvbnN0IGdyYXBoSW5wdXQgPSBtb2RlbFZhbHVlc1ttb2RlbElucHV0SW5kaWNlc1tpXV07XG4gICAgICAgIGdyYXBoSW5wdXREaW1zW2ldID0gZ3JhcGhJbnB1dC50eXBlIS5zaGFwZS5kaW1zO1xuXG4gICAgICAgIC8vIGNhY2hlZCBmb3Igc2Vjb25kIGFuZCBzdWJzZXF1ZW50IHJ1bnMuXG4gICAgICAgIC8vIFNvbWUgcGFydHMgb2YgdGhlIGZyYW1ld29yayB3b3JrcyBvbiB0aGUgYXNzdW1wdGlvbiB0aGF0IHRoZSBncmFwaCBhbmQgdHlwZXMgYW5kIHNoYXBlcyBhcmUgc3RhdGljXG4gICAgICAgIHRoaXMuY29udGV4dC5ncmFwaElucHV0VHlwZXMhLnB1c2goZ3JhcGhJbnB1dC50eXBlIS50ZW5zb3JUeXBlKTtcbiAgICAgICAgdGhpcy5jb250ZXh0LmdyYXBoSW5wdXREaW1zIS5wdXNoKGlucHV0c1tpXS5kaW1zKTtcbiAgICAgIH1cblxuICAgICAgdGhpcy52YWxpZGF0ZUlucHV0VGVuc29yRGltcyhncmFwaElucHV0RGltcywgaW5wdXRzLCB0cnVlKTtcbiAgICB9XG5cbiAgICAvLyBTZWNvbmQgYW5kIHN1YnNlcXVlbnQgc2Vzc2lvbiBydW5zIC0gZ3JhcGggaW5wdXQgZGF0YSBpcyBjYWNoZWQgZm9yIHRoZSBzZXNzaW9uXG4gICAgZWxzZSB7XG4gICAgICB0aGlzLnZhbGlkYXRlSW5wdXRUZW5zb3JEaW1zKHRoaXMuY29udGV4dC5ncmFwaElucHV0RGltcywgaW5wdXRzLCBmYWxzZSk7XG4gICAgfVxuXG4gICAgLy8gdmFsaWRhdGUgdHlwZXMgcmVxdWlyZW1lbnRcbiAgICB0aGlzLnZhbGlkYXRlSW5wdXRUZW5zb3JUeXBlcyh0aGlzLmNvbnRleHQuZ3JhcGhJbnB1dFR5cGVzISwgaW5wdXRzKTtcblxuICAgIHJldHVybiBpbnB1dHM7XG4gIH1cblxuICBwcml2YXRlIHZhbGlkYXRlSW5wdXRUZW5zb3JUeXBlcyhncmFwaElucHV0VHlwZXM6IFRlbnNvci5EYXRhVHlwZVtdLCBnaXZlbklucHV0czogVGVuc29yW10pIHtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGdpdmVuSW5wdXRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICBjb25zdCBleHBlY3RlZFR5cGUgPSBncmFwaElucHV0VHlwZXNbaV07XG4gICAgICBjb25zdCBhY3R1YWxUeXBlID0gZ2l2ZW5JbnB1dHNbaV0udHlwZTtcbiAgICAgIGlmIChleHBlY3RlZFR5cGUgIT09IGFjdHVhbFR5cGUpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBpbnB1dCB0ZW5zb3JbJHtpfV0gY2hlY2sgZmFpbGVkOiBleHBlY3RlZCB0eXBlICcke2V4cGVjdGVkVHlwZX0nIGJ1dCBnb3QgJHthY3R1YWxUeXBlfWApO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgdmFsaWRhdGVJbnB1dFRlbnNvckRpbXMoXG4gICAgICBncmFwaElucHV0RGltczogQXJyYXk8cmVhZG9ubHkgbnVtYmVyW10+LCBnaXZlbklucHV0czogVGVuc29yW10sIG5vbmVEaW1TdXBwb3J0ZWQ6IGJvb2xlYW4pIHtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGdpdmVuSW5wdXRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICBjb25zdCBleHBlY3RlZERpbXMgPSBncmFwaElucHV0RGltc1tpXTtcbiAgICAgIGNvbnN0IGFjdHVhbERpbXMgPSBnaXZlbklucHV0c1tpXS5kaW1zO1xuICAgICAgaWYgKCF0aGlzLmNvbXBhcmVUZW5zb3JEaW1zKGV4cGVjdGVkRGltcywgYWN0dWFsRGltcywgbm9uZURpbVN1cHBvcnRlZCkpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBpbnB1dCB0ZW5zb3JbJHtpfV0gY2hlY2sgZmFpbGVkOiBleHBlY3RlZCBzaGFwZSAnWyR7ZXhwZWN0ZWREaW1zLmpvaW4oJywnKX1dJyBidXQgZ290IFske1xuICAgICAgICAgICAgYWN0dWFsRGltcy5qb2luKCcsJyl9XWApO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgY29tcGFyZVRlbnNvckRpbXMoZXhwZWN0ZWREaW1zOiByZWFkb25seSBudW1iZXJbXSwgYWN0dWFsRGltczogcmVhZG9ubHkgbnVtYmVyW10sIG5vbmVEaW1TdXBwb3J0ZWQ6IGJvb2xlYW4pOlxuICAgICAgYm9vbGVhbiB7XG4gICAgaWYgKGV4cGVjdGVkRGltcy5sZW5ndGggIT09IGFjdHVhbERpbXMubGVuZ3RoKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBleHBlY3RlZERpbXMubGVuZ3RoOyArK2kpIHtcbiAgICAgIGlmIChleHBlY3RlZERpbXNbaV0gIT09IGFjdHVhbERpbXNbaV0gJiYgKCFub25lRGltU3VwcG9ydGVkIHx8IGV4cGVjdGVkRGltc1tpXSAhPT0gMCkpIHtcbiAgICAgICAgLy8gZGF0YSBzaGFwZSBtaXMtbWF0Y2ggQU5EIG5vdCBhICdOb25lJyBkaW1lbnNpb24uXG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxuXG4gIHByaXZhdGUgY3JlYXRlT3V0cHV0KG91dHB1dFRlbnNvcnM6IFRlbnNvcltdKTogTWFwPHN0cmluZywgVGVuc29yPiB7XG4gICAgY29uc3QgbW9kZWxPdXRwdXROYW1lcyA9IHRoaXMuX21vZGVsLmdyYXBoLmdldE91dHB1dE5hbWVzKCk7XG4gICAgaWYgKG91dHB1dFRlbnNvcnMubGVuZ3RoICE9PSBtb2RlbE91dHB1dE5hbWVzLmxlbmd0aCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdleHBlY3RlZCBudW1iZXIgb2Ygb3V0cHV0cyBkbyBub3QgbWF0Y2ggbnVtYmVyIG9mIGdlbmVyYXRlZCBvdXRwdXRzJyk7XG4gICAgfVxuXG4gICAgY29uc3Qgb3V0cHV0ID0gbmV3IE1hcDxzdHJpbmcsIFRlbnNvcj4oKTtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IG1vZGVsT3V0cHV0TmFtZXMubGVuZ3RoOyArK2kpIHtcbiAgICAgIG91dHB1dC5zZXQobW9kZWxPdXRwdXROYW1lc1tpXSwgb3V0cHV0VGVuc29yc1tpXSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIG91dHB1dDtcbiAgfVxuXG4gIHByaXZhdGUgaW5pdGlhbGl6ZU9wcyhncmFwaDogR3JhcGgpOiB2b2lkIHtcbiAgICBjb25zdCBub2RlcyA9IGdyYXBoLmdldE5vZGVzKCk7XG4gICAgdGhpcy5fb3BzID0gbmV3IEFycmF5KG5vZGVzLmxlbmd0aCk7XG5cbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IG5vZGVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICB0aGlzLl9vcHNbaV0gPSB0aGlzLnNlc3Npb25IYW5kbGVyLnJlc29sdmUobm9kZXNbaV0sIHRoaXMuX21vZGVsLm9wc2V0cywgZ3JhcGgpO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgX21vZGVsOiBNb2RlbDtcbiAgcHJpdmF0ZSBfaW5pdGlhbGl6ZWQ6IGJvb2xlYW47XG5cbiAgcHJpdmF0ZSBfb3BzOiBPcGVyYXRvcltdO1xuICBwcml2YXRlIF9leGVjdXRpb25QbGFuOiBFeGVjdXRpb25QbGFuO1xuXG4gIHByaXZhdGUgYmFja2VuZEhpbnQ/OiBzdHJpbmc7XG5cbiAgcHJpdmF0ZSBzZXNzaW9uSGFuZGxlcjogU2Vzc2lvbkhhbmRsZXJUeXBlO1xuICBwcml2YXRlIGNvbnRleHQ6IFNlc3Npb24uQ29udGV4dDtcbiAgcHJpdmF0ZSBwcm9maWxlcjogUmVhZG9ubHk8UHJvZmlsZXI+O1xufVxuIiwiLy8gQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXG5cbmltcG9ydCB7R3VpZH0gZnJvbSAnZ3VpZC10eXBlc2NyaXB0JztcbmltcG9ydCBMb25nIGZyb20gJ2xvbmcnO1xuaW1wb3J0IHtvbm54fSBmcm9tICdvbm54LXByb3RvJztcblxuaW1wb3J0IHtvbm54cnVudGltZX0gZnJvbSAnLi9vcnQtc2NoZW1hL29ydC1nZW5lcmF0ZWQnO1xuaW1wb3J0IHtkZWNvZGVVdGY4U3RyaW5nLCBQcm90b1V0aWwsIFNoYXBlVXRpbH0gZnJvbSAnLi91dGlsJztcblxuaW1wb3J0IG9ydEZicyA9IG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnM7XG5cbmV4cG9ydCBkZWNsYXJlIG5hbWVzcGFjZSBUZW5zb3Ige1xuICBleHBvcnQgaW50ZXJmYWNlIERhdGFUeXBlTWFwIHtcbiAgICBib29sOiBVaW50OEFycmF5O1xuICAgIGZsb2F0MzI6IEZsb2F0MzJBcnJheTtcbiAgICBmbG9hdDY0OiBGbG9hdDY0QXJyYXk7XG4gICAgc3RyaW5nOiBzdHJpbmdbXTtcbiAgICBpbnQ4OiBJbnQ4QXJyYXk7XG4gICAgdWludDg6IFVpbnQ4QXJyYXk7XG4gICAgaW50MTY6IEludDE2QXJyYXk7XG4gICAgdWludDE2OiBVaW50MTZBcnJheTtcbiAgICBpbnQzMjogSW50MzJBcnJheTtcbiAgICB1aW50MzI6IFVpbnQzMkFycmF5O1xuICB9XG5cbiAgZXhwb3J0IHR5cGUgRGF0YVR5cGUgPSBrZXlvZiBEYXRhVHlwZU1hcDtcblxuICBleHBvcnQgdHlwZSBTdHJpbmdUeXBlID0gVGVuc29yLkRhdGFUeXBlTWFwWydzdHJpbmcnXTtcbiAgZXhwb3J0IHR5cGUgQm9vbGVhblR5cGUgPSBUZW5zb3IuRGF0YVR5cGVNYXBbJ2Jvb2wnXTtcbiAgZXhwb3J0IHR5cGUgSW50ZWdlclR5cGUgPSBUZW5zb3IuRGF0YVR5cGVNYXBbJ2ludDgnXXxUZW5zb3IuRGF0YVR5cGVNYXBbJ3VpbnQ4J118VGVuc29yLkRhdGFUeXBlTWFwWydpbnQxNiddfFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRlbnNvci5EYXRhVHlwZU1hcFsndWludDE2J118VGVuc29yLkRhdGFUeXBlTWFwWydpbnQzMiddfFRlbnNvci5EYXRhVHlwZU1hcFsndWludDMyJ107XG4gIGV4cG9ydCB0eXBlIEZsb2F0VHlwZSA9IFRlbnNvci5EYXRhVHlwZU1hcFsnZmxvYXQzMiddfFRlbnNvci5EYXRhVHlwZU1hcFsnZmxvYXQ2NCddO1xuICBleHBvcnQgdHlwZSBOdW1iZXJUeXBlID0gQm9vbGVhblR5cGV8SW50ZWdlclR5cGV8RmxvYXRUeXBlO1xuXG4gIGV4cG9ydCB0eXBlIElkID0gR3VpZDtcbn1cblxudHlwZSBUZW5zb3JEYXRhID0gVGVuc29yLkRhdGFUeXBlTWFwW1RlbnNvci5EYXRhVHlwZV07XG5cbnR5cGUgRGF0YVByb3ZpZGVyID0gKGlkOiBUZW5zb3IuSWQpID0+IFRlbnNvckRhdGE7XG50eXBlIEFzeW5jRGF0YVByb3ZpZGVyID0gKGlkOiBUZW5zb3IuSWQpID0+IFByb21pc2U8VGVuc29yRGF0YT47XG5cbmV4cG9ydCBjbGFzcyBUZW5zb3Ige1xuICAvKipcbiAgICogZ2V0IHRoZSB1bmRlcmx5aW5nIHRlbnNvciBkYXRhXG4gICAqL1xuICBnZXQgZGF0YSgpOiBUZW5zb3JEYXRhIHtcbiAgICBpZiAodGhpcy5jYWNoZSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICBjb25zdCBkYXRhID0gdGhpcy5kYXRhUHJvdmlkZXIhKHRoaXMuZGF0YUlkKTtcbiAgICAgIGlmIChkYXRhLmxlbmd0aCAhPT0gdGhpcy5zaXplKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignTGVuZ3RoIG9mIGRhdGEgcHJvdmlkZWQgYnkgdGhlIERhdGEgUHJvdmlkZXIgaXMgaW5jb25zaXN0ZW50IHdpdGggdGhlIGRpbXMgb2YgdGhpcyBUZW5zb3IuJyk7XG4gICAgICB9XG4gICAgICB0aGlzLmNhY2hlID0gZGF0YTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuY2FjaGU7XG4gIH1cblxuICAvKipcbiAgICogZ2V0IHRoZSB1bmRlcmx5aW5nIHN0cmluZyB0ZW5zb3IgZGF0YS4gU2hvdWxkIG9ubHkgdXNlIHdoZW4gdHlwZSBpcyBTVFJJTkdcbiAgICovXG4gIGdldCBzdHJpbmdEYXRhKCkge1xuICAgIGlmICh0aGlzLnR5cGUgIT09ICdzdHJpbmcnKSB7XG4gICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdkYXRhIHR5cGUgaXMgbm90IHN0cmluZycpO1xuICAgIH1cblxuICAgIHJldHVybiB0aGlzLmRhdGEgYXMgVGVuc29yLlN0cmluZ1R5cGU7XG4gIH1cblxuICAvKipcbiAgICogZ2V0IHRoZSB1bmRlcmx5aW5nIGludGVnZXIgdGVuc29yIGRhdGEuIFNob3VsZCBvbmx5IHVzZSB3aGVuIHR5cGUgaXMgb25lIG9mIHRoZSBmb2xsb3dpbmc6IChVSU5UOCwgSU5UOCwgVUlOVDE2LFxuICAgKiBJTlQxNiwgSU5UMzIsIFVJTlQzMiwgQk9PTClcbiAgICovXG4gIGdldCBpbnRlZ2VyRGF0YSgpIHtcbiAgICBzd2l0Y2ggKHRoaXMudHlwZSkge1xuICAgICAgY2FzZSAndWludDgnOlxuICAgICAgY2FzZSAnaW50OCc6XG4gICAgICBjYXNlICd1aW50MTYnOlxuICAgICAgY2FzZSAnaW50MTYnOlxuICAgICAgY2FzZSAnaW50MzInOlxuICAgICAgY2FzZSAndWludDMyJzpcbiAgICAgIGNhc2UgJ2Jvb2wnOlxuICAgICAgICByZXR1cm4gdGhpcy5kYXRhIGFzIFRlbnNvci5JbnRlZ2VyVHlwZTtcblxuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignZGF0YSB0eXBlIGlzIG5vdCBpbnRlZ2VyICh1aW50OCwgaW50OCwgdWludDE2LCBpbnQxNiwgaW50MzIsIHVpbnQzMiwgYm9vbCknKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogZ2V0IHRoZSB1bmRlcmx5aW5nIGZsb2F0IHRlbnNvciBkYXRhLiBTaG91bGQgb25seSB1c2Ugd2hlbiB0eXBlIGlzIG9uZSBvZiB0aGUgZm9sbG93aW5nOiAoRkxPQVQsIERPVUJMRSlcbiAgICovXG4gIGdldCBmbG9hdERhdGEoKSB7XG4gICAgc3dpdGNoICh0aGlzLnR5cGUpIHtcbiAgICAgIGNhc2UgJ2Zsb2F0MzInOlxuICAgICAgY2FzZSAnZmxvYXQ2NCc6XG4gICAgICAgIHJldHVybiB0aGlzLmRhdGEgYXMgVGVuc29yLkZsb2F0VHlwZTtcblxuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignZGF0YSB0eXBlIGlzIG5vdCBmbG9hdCAoZmxvYXQzMiwgZmxvYXQ2NCknKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogZ2V0IHRoZSB1bmRlcmx5aW5nIG51bWJlciB0ZW5zb3IgZGF0YS4gU2hvdWxkIG9ubHkgdXNlIHdoZW4gdHlwZSBpcyBvbmUgb2YgdGhlIGZvbGxvd2luZzogKFVJTlQ4LCBJTlQ4LCBVSU5UMTYsXG4gICAqIElOVDE2LCBJTlQzMiwgVUlOVDMyLCBCT09MLCBGTE9BVCwgRE9VQkxFKVxuICAgKi9cbiAgZ2V0IG51bWJlckRhdGEoKSB7XG4gICAgaWYgKHRoaXMudHlwZSAhPT0gJ3N0cmluZycpIHtcbiAgICAgIHJldHVybiB0aGlzLmRhdGEgYXMgVGVuc29yLk51bWJlclR5cGU7XG4gICAgfVxuICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ3R5cGUgY2Fubm90IGJlIG5vbi1udW1iZXIgKHN0cmluZyknKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBnZXQgdmFsdWUgb2YgYW4gZWxlbWVudCBhdCB0aGUgZ2l2ZW4gaW5kaWNlc1xuICAgKi9cbiAgZ2V0KGluZGljZXM6IHJlYWRvbmx5IG51bWJlcltdKTogVGVuc29yLkRhdGFUeXBlTWFwW1RlbnNvci5EYXRhVHlwZV1bbnVtYmVyXSB7XG4gICAgcmV0dXJuIHRoaXMuZGF0YVtTaGFwZVV0aWwuaW5kaWNlc1RvT2Zmc2V0KGluZGljZXMsIHRoaXMuc3RyaWRlcyldO1xuICB9XG5cbiAgLyoqXG4gICAqIHNldCB2YWx1ZSBvZiBhbiBlbGVtZW50IGF0IHRoZSBnaXZlbiBpbmRpY2VzXG4gICAqL1xuICBzZXQoaW5kaWNlczogcmVhZG9ubHkgbnVtYmVyW10sIHZhbHVlOiBUZW5zb3IuRGF0YVR5cGVNYXBbVGVuc29yLkRhdGFUeXBlXVtudW1iZXJdKSB7XG4gICAgdGhpcy5kYXRhW1NoYXBlVXRpbC5pbmRpY2VzVG9PZmZzZXQoaW5kaWNlcywgdGhpcy5zdHJpZGVzKV0gPSB2YWx1ZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBnZXQgdGhlIHVuZGVybHlpbmcgdGVuc29yIGRhdGEgYXN5bmNocm9ub3VzbHlcbiAgICovXG4gIGFzeW5jIGdldERhdGEoKTogUHJvbWlzZTxUZW5zb3JEYXRhPiB7XG4gICAgaWYgKHRoaXMuY2FjaGUgPT09IHVuZGVmaW5lZCkge1xuICAgICAgdGhpcy5jYWNoZSA9IGF3YWl0IHRoaXMuYXN5bmNEYXRhUHJvdmlkZXIhKHRoaXMuZGF0YUlkKTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuY2FjaGU7XG4gIH1cblxuICAvKipcbiAgICogZ2V0IHRoZSBudW1iZXIgb2YgZWxlbWVudHMgaW4gdGhlIHRlbnNvclxuICAgKi9cbiAgcHVibGljIHJlYWRvbmx5IHNpemU6IG51bWJlcjtcblxuICBwcml2YXRlIF9zdHJpZGVzOiByZWFkb25seSBudW1iZXJbXTtcbiAgLyoqXG4gICAqIGdldCB0aGUgc3RyaWRlcyBmb3IgZWFjaCBkaW1lbnNpb25cbiAgICovXG4gIGdldCBzdHJpZGVzKCk6IHJlYWRvbmx5IG51bWJlcltdIHtcbiAgICBpZiAoIXRoaXMuX3N0cmlkZXMpIHtcbiAgICAgIHRoaXMuX3N0cmlkZXMgPSBTaGFwZVV0aWwuY29tcHV0ZVN0cmlkZXModGhpcy5kaW1zKTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuX3N0cmlkZXM7XG4gIH1cblxuICBjb25zdHJ1Y3RvcihcbiAgICAgIC8qKlxuICAgICAgICogZ2V0IHRoZSBkaW1lbnNpb25zIG9mIHRoZSB0ZW5zb3JcbiAgICAgICAqL1xuICAgICAgcHVibGljIHJlYWRvbmx5IGRpbXM6IHJlYWRvbmx5IG51bWJlcltdLFxuICAgICAgLyoqXG4gICAgICAgKiBnZXQgdGhlIHR5cGUgb2YgdGhlIHRlbnNvclxuICAgICAgICovXG4gICAgICBwdWJsaWMgcmVhZG9ubHkgdHlwZTogVGVuc29yLkRhdGFUeXBlLCBwcml2YXRlIGRhdGFQcm92aWRlcj86IERhdGFQcm92aWRlcixcbiAgICAgIHByaXZhdGUgYXN5bmNEYXRhUHJvdmlkZXI/OiBBc3luY0RhdGFQcm92aWRlciwgcHJpdmF0ZSBjYWNoZT86IFRlbnNvckRhdGEsXG4gICAgICAvKipcbiAgICAgICAqIGdldCB0aGUgZGF0YSBJRCB0aGF0IHVzZWQgdG8gbWFwIHRvIGEgdGVuc29yIGRhdGFcbiAgICAgICAqL1xuICAgICAgcHVibGljIHJlYWRvbmx5IGRhdGFJZDogR3VpZCA9IEd1aWQuY3JlYXRlKCkpIHtcbiAgICB0aGlzLnNpemUgPSBTaGFwZVV0aWwudmFsaWRhdGVEaW1zQW5kQ2FsY1NpemUoZGltcyk7XG4gICAgY29uc3Qgc2l6ZSA9IHRoaXMuc2l6ZTtcbiAgICBjb25zdCBlbXB0eSA9IChkYXRhUHJvdmlkZXIgPT09IHVuZGVmaW5lZCAmJiBhc3luY0RhdGFQcm92aWRlciA9PT0gdW5kZWZpbmVkICYmIGNhY2hlID09PSB1bmRlZmluZWQpO1xuXG4gICAgaWYgKGNhY2hlICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIGlmIChjYWNoZS5sZW5ndGggIT09IHNpemUpIHtcbiAgICAgICAgdGhyb3cgbmV3IFJhbmdlRXJyb3IoJ0lucHV0IGRpbXMgZG9lc25cXCd0IG1hdGNoIGRhdGEgbGVuZ3RoLicpO1xuICAgICAgfVxuICAgIH1cblxuICAgIGlmICh0eXBlID09PSAnc3RyaW5nJykge1xuICAgICAgaWYgKGNhY2hlICE9PSB1bmRlZmluZWQgJiYgKCFBcnJheS5pc0FycmF5KGNhY2hlKSB8fCAhY2FjaGUuZXZlcnkoaSA9PiB0eXBlb2YgaSA9PT0gJ3N0cmluZycpKSkge1xuICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdjYWNoZSBzaG91bGQgYmUgYSBzdHJpbmcgYXJyYXknKTtcbiAgICAgIH1cblxuICAgICAgaWYgKGVtcHR5KSB7XG4gICAgICAgIHRoaXMuY2FjaGUgPSBuZXcgQXJyYXk8c3RyaW5nPihzaXplKTtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgaWYgKGNhY2hlICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgY29uc3QgY29uc3RydWN0b3IgPSBkYXRhdmlld0NvbnN0cnVjdG9yKHR5cGUpO1xuICAgICAgICBpZiAoIShjYWNoZSBpbnN0YW5jZW9mIGNvbnN0cnVjdG9yKSkge1xuICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoYGNhY2hlIHNob3VsZCBiZSB0eXBlICR7Y29uc3RydWN0b3IubmFtZX1gKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBpZiAoZW1wdHkpIHtcbiAgICAgICAgY29uc3QgYnVmID0gbmV3IEFycmF5QnVmZmVyKHNpemUgKiBzaXplb2YodHlwZSkpO1xuICAgICAgICB0aGlzLmNhY2hlID0gY3JlYXRlVmlldyhidWYsIHR5cGUpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBDb25zdHJ1Y3QgbmV3IFRlbnNvciBmcm9tIGEgT05OWCBUZW5zb3Igb2JqZWN0XG4gICAqIEBwYXJhbSB0ZW5zb3JQcm90byB0aGUgT05OWCBUZW5zb3JcbiAgICovXG4gIHN0YXRpYyBmcm9tUHJvdG8odGVuc29yUHJvdG86IG9ubnguSVRlbnNvclByb3RvKTogVGVuc29yIHtcbiAgICBpZiAoIXRlbnNvclByb3RvKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ2Nhbm5vdCBjb25zdHJ1Y3QgVmFsdWUgZnJvbSBhbiBlbXB0eSB0ZW5zb3InKTtcbiAgICB9XG4gICAgY29uc3QgdHlwZSA9IFByb3RvVXRpbC50ZW5zb3JEYXRhVHlwZUZyb21Qcm90byh0ZW5zb3JQcm90by5kYXRhVHlwZSEpO1xuICAgIGNvbnN0IGRpbXMgPSBQcm90b1V0aWwudGVuc29yRGltc0Zyb21Qcm90byh0ZW5zb3JQcm90by5kaW1zISk7XG5cbiAgICBjb25zdCB2YWx1ZSA9IG5ldyBUZW5zb3IoZGltcywgdHlwZSk7XG5cbiAgICBpZiAodHlwZSA9PT0gJ3N0cmluZycpIHtcbiAgICAgIC8vIFdoZW4gaXQncyBTVFJJTkcgdHlwZSwgdGhlIHZhbHVlIHNob3VsZCBhbHdheXMgYmUgc3RvcmVkIGluIGZpZWxkXG4gICAgICAvLyAnc3RyaW5nRGF0YSdcbiAgICAgIHRlbnNvclByb3RvLnN0cmluZ0RhdGEhLmZvckVhY2goKHN0ciwgaSkgPT4ge1xuICAgICAgICB2YWx1ZS5kYXRhW2ldID0gZGVjb2RlVXRmOFN0cmluZyhzdHIpO1xuICAgICAgfSk7XG5cbiAgICB9IGVsc2UgaWYgKFxuICAgICAgICB0ZW5zb3JQcm90by5yYXdEYXRhICYmIHR5cGVvZiB0ZW5zb3JQcm90by5yYXdEYXRhLmJ5dGVMZW5ndGggPT09ICdudW1iZXInICYmXG4gICAgICAgIHRlbnNvclByb3RvLnJhd0RhdGEuYnl0ZUxlbmd0aCA+IDApIHtcbiAgICAgIC8vIE5PVCBjb25zaWRlcmluZyBzZWdtZW50IGZvciBub3cgKElNUE9SVEFOVClcblxuICAgICAgLy8gcG9wdWxhdGUgdmFsdWUgZnJvbSByYXdEYXRhXG4gICAgICBjb25zdCBkYXRhRGVzdCA9IHZhbHVlLmRhdGE7XG4gICAgICBjb25zdCBkYXRhU291cmNlID1cbiAgICAgICAgICBuZXcgRGF0YVZpZXcodGVuc29yUHJvdG8ucmF3RGF0YS5idWZmZXIsIHRlbnNvclByb3RvLnJhd0RhdGEuYnl0ZU9mZnNldCwgdGVuc29yUHJvdG8ucmF3RGF0YS5ieXRlTGVuZ3RoKTtcbiAgICAgIGNvbnN0IGVsZW1lbnRTaXplID0gc2l6ZW9mUHJvdG8odGVuc29yUHJvdG8uZGF0YVR5cGUhKTtcbiAgICAgIGNvbnN0IGxlbmd0aCA9IHRlbnNvclByb3RvLnJhd0RhdGEuYnl0ZUxlbmd0aCAvIGVsZW1lbnRTaXplO1xuXG4gICAgICBpZiAodGVuc29yUHJvdG8ucmF3RGF0YS5ieXRlTGVuZ3RoICUgZWxlbWVudFNpemUgIT09IDApIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdpbnZhbGlkIGJ1ZmZlciBsZW5ndGgnKTtcbiAgICAgIH1cbiAgICAgIGlmIChkYXRhRGVzdC5sZW5ndGggIT09IGxlbmd0aCkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ2J1ZmZlciBsZW5ndGggbWlzbWF0Y2gnKTtcbiAgICAgIH1cblxuICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBsZW5ndGg7IGkrKykge1xuICAgICAgICBjb25zdCBuID0gcmVhZFByb3RvKGRhdGFTb3VyY2UsIHRlbnNvclByb3RvLmRhdGFUeXBlISwgaSAqIGVsZW1lbnRTaXplKTtcbiAgICAgICAgZGF0YURlc3RbaV0gPSBuO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICAvLyBwb3B1bGF0ZSB2YWx1ZSBmcm9tIGFycmF5XG4gICAgICBsZXQgYXJyYXk6IEFycmF5PG51bWJlcnxMb25nPjtcbiAgICAgIHN3aXRjaCAodGVuc29yUHJvdG8uZGF0YVR5cGUpIHtcbiAgICAgICAgY2FzZSBvbm54LlRlbnNvclByb3RvLkRhdGFUeXBlLkZMT0FUOlxuICAgICAgICAgIGFycmF5ID0gdGVuc29yUHJvdG8uZmxvYXREYXRhITtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSBvbm54LlRlbnNvclByb3RvLkRhdGFUeXBlLklOVDMyOlxuICAgICAgICBjYXNlIG9ubnguVGVuc29yUHJvdG8uRGF0YVR5cGUuSU5UMTY6XG4gICAgICAgIGNhc2Ugb25ueC5UZW5zb3JQcm90by5EYXRhVHlwZS5VSU5UMTY6XG4gICAgICAgIGNhc2Ugb25ueC5UZW5zb3JQcm90by5EYXRhVHlwZS5JTlQ4OlxuICAgICAgICBjYXNlIG9ubnguVGVuc29yUHJvdG8uRGF0YVR5cGUuVUlOVDg6XG4gICAgICAgIGNhc2Ugb25ueC5UZW5zb3JQcm90by5EYXRhVHlwZS5CT09MOlxuICAgICAgICAgIGFycmF5ID0gdGVuc29yUHJvdG8uaW50MzJEYXRhITtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSBvbm54LlRlbnNvclByb3RvLkRhdGFUeXBlLklOVDY0OlxuICAgICAgICAgIGFycmF5ID0gdGVuc29yUHJvdG8uaW50NjREYXRhITtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSBvbm54LlRlbnNvclByb3RvLkRhdGFUeXBlLkRPVUJMRTpcbiAgICAgICAgICBhcnJheSA9IHRlbnNvclByb3RvLmRvdWJsZURhdGEhO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlIG9ubnguVGVuc29yUHJvdG8uRGF0YVR5cGUuVUlOVDMyOlxuICAgICAgICBjYXNlIG9ubnguVGVuc29yUHJvdG8uRGF0YVR5cGUuVUlOVDY0OlxuICAgICAgICAgIGFycmF5ID0gdGVuc29yUHJvdG8udWludDY0RGF0YSE7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgLy8gc2hvdWxkIG5ldmVyIHJ1biBoZXJlXG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCd1bnNwZWNpZmljIGVycm9yJyk7XG4gICAgICB9XG5cbiAgICAgIGlmIChhcnJheSA9PT0gbnVsbCB8fCBhcnJheSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignZmFpbGVkIHRvIHBvcHVsYXRlIGRhdGEgZnJvbSBhIHRlbnNvcnByb3RvIHZhbHVlJyk7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IGRhdGEgPSB2YWx1ZS5kYXRhO1xuICAgICAgaWYgKGRhdGEubGVuZ3RoICE9PSBhcnJheS5sZW5ndGgpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdhcnJheSBsZW5ndGggbWlzbWF0Y2gnKTtcbiAgICAgIH1cblxuICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBhcnJheS5sZW5ndGg7IGkrKykge1xuICAgICAgICBjb25zdCBlbGVtZW50ID0gYXJyYXlbaV07XG4gICAgICAgIGlmIChMb25nLmlzTG9uZyhlbGVtZW50KSkge1xuICAgICAgICAgIGRhdGFbaV0gPSBsb25nVG9OdW1iZXIoZWxlbWVudCwgdGVuc29yUHJvdG8uZGF0YVR5cGUpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGRhdGFbaV0gPSBlbGVtZW50O1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHZhbHVlO1xuICB9XG5cbiAgLyoqXG4gICAqIENvbnN0cnVjdCBuZXcgVGVuc29yIGZyb20gcmF3IGRhdGFcbiAgICogQHBhcmFtIGRhdGEgdGhlIHJhdyBkYXRhIG9iamVjdC4gU2hvdWxkIGJlIGEgc3RyaW5nIGFycmF5IGZvciAnc3RyaW5nJyB0ZW5zb3IsIGFuZCB0aGUgY29ycmVzcG9uZGluZyB0eXBlZCBhcnJheVxuICAgKiBmb3Igb3RoZXIgdHlwZXMgb2YgdGVuc29yLlxuICAgKiBAcGFyYW0gZGltcyB0aGUgZGltZW5zaW9ucyBvZiB0aGUgdGVuc29yXG4gICAqIEBwYXJhbSB0eXBlIHRoZSB0eXBlIG9mIHRoZSB0ZW5zb3JcbiAgICovXG4gIHN0YXRpYyBmcm9tRGF0YShkYXRhOiBUZW5zb3IuRGF0YVR5cGVNYXBbVGVuc29yLkRhdGFUeXBlXSwgZGltczogcmVhZG9ubHkgbnVtYmVyW10sIHR5cGU6IFRlbnNvci5EYXRhVHlwZSkge1xuICAgIHJldHVybiBuZXcgVGVuc29yKGRpbXMsIHR5cGUsIHVuZGVmaW5lZCwgdW5kZWZpbmVkLCBkYXRhKTtcbiAgfVxuXG4gIHN0YXRpYyBmcm9tT3J0VGVuc29yKG9ydFRlbnNvcjogb3J0RmJzLlRlbnNvcikge1xuICAgIGlmICghb3J0VGVuc29yKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ2Nhbm5vdCBjb25zdHJ1Y3QgVmFsdWUgZnJvbSBhbiBlbXB0eSB0ZW5zb3InKTtcbiAgICB9XG4gICAgY29uc3QgZGltcyA9IFByb3RvVXRpbC50ZW5zb3JEaW1zRnJvbU9SVEZvcm1hdChvcnRUZW5zb3IpO1xuICAgIGNvbnN0IHR5cGUgPSBQcm90b1V0aWwudGVuc29yRGF0YVR5cGVGcm9tUHJvdG8ob3J0VGVuc29yLmRhdGFUeXBlKCkpO1xuXG4gICAgY29uc3QgdmFsdWUgPSBuZXcgVGVuc29yKGRpbXMsIHR5cGUpO1xuXG4gICAgaWYgKHR5cGUgPT09ICdzdHJpbmcnKSB7XG4gICAgICAvLyBXaGVuIGl0J3MgU1RSSU5HIHR5cGUsIHRoZSB2YWx1ZSBzaG91bGQgYWx3YXlzIGJlIHN0b3JlZCBpbiBmaWVsZFxuICAgICAgLy8gJ3N0cmluZ0RhdGEnXG4gICAgICBmb3IgKGxldCBpID0gMDsgaSA8IG9ydFRlbnNvci5zdHJpbmdEYXRhTGVuZ3RoKCk7IGkrKykge1xuICAgICAgICB2YWx1ZS5kYXRhW2ldID0gb3J0VGVuc29yLnN0cmluZ0RhdGEoaSk7XG4gICAgICB9XG5cbiAgICB9IGVsc2UgaWYgKFxuICAgICAgICBvcnRUZW5zb3IucmF3RGF0YUFycmF5KCkgJiYgdHlwZW9mIG9ydFRlbnNvci5yYXdEYXRhTGVuZ3RoKCkgPT09ICdudW1iZXInICYmIG9ydFRlbnNvci5yYXdEYXRhTGVuZ3RoKCkgPiAwKSB7XG4gICAgICAvLyBOT1QgY29uc2lkZXJpbmcgc2VnbWVudCBmb3Igbm93IChJTVBPUlRBTlQpXG5cbiAgICAgIC8vIHBvcHVsYXRlIHZhbHVlIGZyb20gcmF3RGF0YVxuICAgICAgY29uc3QgZGF0YURlc3QgPSB2YWx1ZS5kYXRhO1xuICAgICAgY29uc3QgZGF0YVNvdXJjZSA9IG5ldyBEYXRhVmlldyhcbiAgICAgICAgICBvcnRUZW5zb3IucmF3RGF0YUFycmF5KCkhLmJ1ZmZlciwgb3J0VGVuc29yLnJhd0RhdGFBcnJheSgpIS5ieXRlT2Zmc2V0LCBvcnRUZW5zb3IucmF3RGF0YUxlbmd0aCgpKTtcbiAgICAgIGNvbnN0IGVsZW1lbnRTaXplID0gc2l6ZW9mUHJvdG8ob3J0VGVuc29yLmRhdGFUeXBlKCkpO1xuICAgICAgY29uc3QgbGVuZ3RoID0gb3J0VGVuc29yLnJhd0RhdGFMZW5ndGgoKSAvIGVsZW1lbnRTaXplO1xuXG4gICAgICBpZiAob3J0VGVuc29yLnJhd0RhdGFMZW5ndGgoKSAlIGVsZW1lbnRTaXplICE9PSAwKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignaW52YWxpZCBidWZmZXIgbGVuZ3RoJyk7XG4gICAgICB9XG4gICAgICBpZiAoZGF0YURlc3QubGVuZ3RoICE9PSBsZW5ndGgpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdidWZmZXIgbGVuZ3RoIG1pc21hdGNoJyk7XG4gICAgICB9XG5cbiAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbGVuZ3RoOyBpKyspIHtcbiAgICAgICAgY29uc3QgbiA9IHJlYWRQcm90byhkYXRhU291cmNlLCBvcnRUZW5zb3IuZGF0YVR5cGUoKSwgaSAqIGVsZW1lbnRTaXplKTtcbiAgICAgICAgZGF0YURlc3RbaV0gPSBuO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gdmFsdWU7XG4gIH1cbn1cblxuZnVuY3Rpb24gc2l6ZW9mKHR5cGU6IFRlbnNvci5EYXRhVHlwZSk6IG51bWJlciB7XG4gIHN3aXRjaCAodHlwZSkge1xuICAgIGNhc2UgJ2Jvb2wnOlxuICAgIGNhc2UgJ2ludDgnOlxuICAgIGNhc2UgJ3VpbnQ4JzpcbiAgICAgIHJldHVybiAxO1xuICAgIGNhc2UgJ2ludDE2JzpcbiAgICBjYXNlICd1aW50MTYnOlxuICAgICAgcmV0dXJuIDI7XG4gICAgY2FzZSAnaW50MzInOlxuICAgIGNhc2UgJ3VpbnQzMic6XG4gICAgY2FzZSAnZmxvYXQzMic6XG4gICAgICByZXR1cm4gNDtcbiAgICBjYXNlICdmbG9hdDY0JzpcbiAgICAgIHJldHVybiA4O1xuICAgIGRlZmF1bHQ6XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYGNhbm5vdCBjYWxjdWxhdGUgc2l6ZW9mKCkgb24gdHlwZSAke3R5cGV9YCk7XG4gIH1cbn1cblxuZnVuY3Rpb24gc2l6ZW9mUHJvdG8odHlwZTogb25ueC5UZW5zb3JQcm90by5EYXRhVHlwZXxvcnRGYnMuVGVuc29yRGF0YVR5cGUpOiBudW1iZXIge1xuICBzd2l0Y2ggKHR5cGUpIHtcbiAgICBjYXNlIG9ubnguVGVuc29yUHJvdG8uRGF0YVR5cGUuVUlOVDg6XG4gICAgY2FzZSBvbm54LlRlbnNvclByb3RvLkRhdGFUeXBlLklOVDg6XG4gICAgY2FzZSBvbm54LlRlbnNvclByb3RvLkRhdGFUeXBlLkJPT0w6XG4gICAgICByZXR1cm4gMTtcbiAgICBjYXNlIG9ubnguVGVuc29yUHJvdG8uRGF0YVR5cGUuVUlOVDE2OlxuICAgIGNhc2Ugb25ueC5UZW5zb3JQcm90by5EYXRhVHlwZS5JTlQxNjpcbiAgICAgIHJldHVybiAyO1xuICAgIGNhc2Ugb25ueC5UZW5zb3JQcm90by5EYXRhVHlwZS5GTE9BVDpcbiAgICBjYXNlIG9ubnguVGVuc29yUHJvdG8uRGF0YVR5cGUuSU5UMzI6XG4gICAgY2FzZSBvbm54LlRlbnNvclByb3RvLkRhdGFUeXBlLlVJTlQzMjpcbiAgICAgIHJldHVybiA0O1xuICAgIGNhc2Ugb25ueC5UZW5zb3JQcm90by5EYXRhVHlwZS5JTlQ2NDpcbiAgICBjYXNlIG9ubnguVGVuc29yUHJvdG8uRGF0YVR5cGUuRE9VQkxFOlxuICAgIGNhc2Ugb25ueC5UZW5zb3JQcm90by5EYXRhVHlwZS5VSU5UNjQ6XG4gICAgICByZXR1cm4gODtcbiAgICBkZWZhdWx0OlxuICAgICAgdGhyb3cgbmV3IEVycm9yKGBjYW5ub3QgY2FsY3VsYXRlIHNpemVvZigpIG9uIHR5cGUgJHtvbm54LlRlbnNvclByb3RvLkRhdGFUeXBlW3R5cGVdfWApO1xuICB9XG59XG5cbmZ1bmN0aW9uIGNyZWF0ZVZpZXcoZGF0YUJ1ZmZlcjogQXJyYXlCdWZmZXIsIHR5cGU6IFRlbnNvci5EYXRhVHlwZSkge1xuICByZXR1cm4gbmV3IChkYXRhdmlld0NvbnN0cnVjdG9yKHR5cGUpKShkYXRhQnVmZmVyKTtcbn1cblxuZnVuY3Rpb24gZGF0YXZpZXdDb25zdHJ1Y3Rvcih0eXBlOiBUZW5zb3IuRGF0YVR5cGUpIHtcbiAgc3dpdGNoICh0eXBlKSB7XG4gICAgY2FzZSAnYm9vbCc6XG4gICAgY2FzZSAndWludDgnOlxuICAgICAgcmV0dXJuIFVpbnQ4QXJyYXk7XG4gICAgY2FzZSAnaW50OCc6XG4gICAgICByZXR1cm4gSW50OEFycmF5O1xuICAgIGNhc2UgJ2ludDE2JzpcbiAgICAgIHJldHVybiBJbnQxNkFycmF5O1xuICAgIGNhc2UgJ3VpbnQxNic6XG4gICAgICByZXR1cm4gVWludDE2QXJyYXk7XG4gICAgY2FzZSAnaW50MzInOlxuICAgICAgcmV0dXJuIEludDMyQXJyYXk7XG4gICAgY2FzZSAndWludDMyJzpcbiAgICAgIHJldHVybiBVaW50MzJBcnJheTtcbiAgICBjYXNlICdmbG9hdDMyJzpcbiAgICAgIHJldHVybiBGbG9hdDMyQXJyYXk7XG4gICAgY2FzZSAnZmxvYXQ2NCc6XG4gICAgICByZXR1cm4gRmxvYXQ2NEFycmF5O1xuICAgIGRlZmF1bHQ6XG4gICAgICAvLyBzaG91bGQgbmV2ZXIgcnVuIHRvIGhlcmVcbiAgICAgIHRocm93IG5ldyBFcnJvcigndW5zcGVjaWZpZWQgZXJyb3InKTtcbiAgfVxufVxuXG4vLyBjb252ZXJ0IGEgbG9uZyBudW1iZXIgdG8gYSAzMi1iaXQgaW50ZWdlciAoY2FzdC1kb3duKVxuZnVuY3Rpb24gbG9uZ1RvTnVtYmVyKGk6IExvbmcsIHR5cGU6IG9ubnguVGVuc29yUHJvdG8uRGF0YVR5cGV8b3J0RmJzLlRlbnNvckRhdGFUeXBlKTogbnVtYmVyIHtcbiAgLy8gSU5UNjQsIFVJTlQzMiwgVUlOVDY0XG4gIGlmICh0eXBlID09PSBvbm54LlRlbnNvclByb3RvLkRhdGFUeXBlLklOVDY0IHx8IHR5cGUgPT09IG9ydEZicy5UZW5zb3JEYXRhVHlwZS5JTlQ2NCkge1xuICAgIGlmIChpLmdyZWF0ZXJUaGFuT3JFcXVhbCgyMTQ3NDgzNjQ4KSB8fCBpLmxlc3NUaGFuKC0yMTQ3NDgzNjQ4KSkge1xuICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignaW50NjQgaXMgbm90IHN1cHBvcnRlZCcpO1xuICAgIH1cbiAgfSBlbHNlIGlmIChcbiAgICAgIHR5cGUgPT09IG9ubnguVGVuc29yUHJvdG8uRGF0YVR5cGUuVUlOVDMyIHx8IHR5cGUgPT09IG9ydEZicy5UZW5zb3JEYXRhVHlwZS5VSU5UMzIgfHxcbiAgICAgIHR5cGUgPT09IG9ubnguVGVuc29yUHJvdG8uRGF0YVR5cGUuVUlOVDY0IHx8IHR5cGUgPT09IG9ydEZicy5UZW5zb3JEYXRhVHlwZS5VSU5UNjQpIHtcbiAgICBpZiAoaS5ncmVhdGVyVGhhbk9yRXF1YWwoNDI5NDk2NzI5NikgfHwgaS5sZXNzVGhhbigwKSkge1xuICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcigndWludDY0IGlzIG5vdCBzdXBwb3J0ZWQnKTtcbiAgICB9XG4gIH0gZWxzZSB7XG4gICAgdGhyb3cgbmV3IFR5cGVFcnJvcihgbm90IGEgTE9ORyB0eXBlOiAke29ubnguVGVuc29yUHJvdG8uRGF0YVR5cGVbdHlwZV19YCk7XG4gIH1cblxuICByZXR1cm4gaS50b051bWJlcigpO1xufVxuXG4vLyByZWFkIG9uZSB2YWx1ZSBmcm9tIFRlbnNvclByb3RvXG5mdW5jdGlvbiByZWFkUHJvdG8odmlldzogRGF0YVZpZXcsIHR5cGU6IG9ubnguVGVuc29yUHJvdG8uRGF0YVR5cGV8b3J0RmJzLlRlbnNvckRhdGFUeXBlLCBieXRlT2Zmc2V0OiBudW1iZXIpOiBudW1iZXIge1xuICBzd2l0Y2ggKHR5cGUpIHtcbiAgICBjYXNlIG9ubnguVGVuc29yUHJvdG8uRGF0YVR5cGUuQk9PTDpcbiAgICBjYXNlIG9ubnguVGVuc29yUHJvdG8uRGF0YVR5cGUuVUlOVDg6XG4gICAgICByZXR1cm4gdmlldy5nZXRVaW50OChieXRlT2Zmc2V0KTtcbiAgICBjYXNlIG9ubnguVGVuc29yUHJvdG8uRGF0YVR5cGUuSU5UODpcbiAgICAgIHJldHVybiB2aWV3LmdldEludDgoYnl0ZU9mZnNldCk7XG4gICAgY2FzZSBvbm54LlRlbnNvclByb3RvLkRhdGFUeXBlLlVJTlQxNjpcbiAgICAgIHJldHVybiB2aWV3LmdldFVpbnQxNihieXRlT2Zmc2V0LCB0cnVlKTtcbiAgICBjYXNlIG9ubnguVGVuc29yUHJvdG8uRGF0YVR5cGUuSU5UMTY6XG4gICAgICByZXR1cm4gdmlldy5nZXRJbnQxNihieXRlT2Zmc2V0LCB0cnVlKTtcbiAgICBjYXNlIG9ubnguVGVuc29yUHJvdG8uRGF0YVR5cGUuRkxPQVQ6XG4gICAgICByZXR1cm4gdmlldy5nZXRGbG9hdDMyKGJ5dGVPZmZzZXQsIHRydWUpO1xuICAgIGNhc2Ugb25ueC5UZW5zb3JQcm90by5EYXRhVHlwZS5JTlQzMjpcbiAgICAgIHJldHVybiB2aWV3LmdldEludDMyKGJ5dGVPZmZzZXQsIHRydWUpO1xuICAgIGNhc2Ugb25ueC5UZW5zb3JQcm90by5EYXRhVHlwZS5VSU5UMzI6XG4gICAgICByZXR1cm4gdmlldy5nZXRVaW50MzIoYnl0ZU9mZnNldCwgdHJ1ZSk7XG4gICAgY2FzZSBvbm54LlRlbnNvclByb3RvLkRhdGFUeXBlLklOVDY0OlxuICAgICAgcmV0dXJuIGxvbmdUb051bWJlcihcbiAgICAgICAgICBMb25nLmZyb21CaXRzKHZpZXcuZ2V0VWludDMyKGJ5dGVPZmZzZXQsIHRydWUpLCB2aWV3LmdldFVpbnQzMihieXRlT2Zmc2V0ICsgNCwgdHJ1ZSksIGZhbHNlKSwgdHlwZSk7XG4gICAgY2FzZSBvbm54LlRlbnNvclByb3RvLkRhdGFUeXBlLkRPVUJMRTpcbiAgICAgIHJldHVybiB2aWV3LmdldEZsb2F0NjQoYnl0ZU9mZnNldCwgdHJ1ZSk7XG4gICAgY2FzZSBvbm54LlRlbnNvclByb3RvLkRhdGFUeXBlLlVJTlQ2NDpcbiAgICAgIHJldHVybiBsb25nVG9OdW1iZXIoXG4gICAgICAgICAgTG9uZy5mcm9tQml0cyh2aWV3LmdldFVpbnQzMihieXRlT2Zmc2V0LCB0cnVlKSwgdmlldy5nZXRVaW50MzIoYnl0ZU9mZnNldCArIDQsIHRydWUpLCB0cnVlKSwgdHlwZSk7XG4gICAgZGVmYXVsdDpcbiAgICAgIHRocm93IG5ldyBFcnJvcihgY2Fubm90IHJlYWQgZnJvbSBEYXRhVmlldyBmb3IgdHlwZSAke29ubnguVGVuc29yUHJvdG8uRGF0YVR5cGVbdHlwZV19YCk7XG4gIH1cbn1cbiIsIi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxuXG5pbXBvcnQge2ZsYXRidWZmZXJzfSBmcm9tICdmbGF0YnVmZmVycyc7XG5pbXBvcnQgTG9uZyBmcm9tICdsb25nJztcbmltcG9ydCB7b25ueH0gZnJvbSAnb25ueC1wcm90byc7XG5cbmltcG9ydCB7R3JhcGh9IGZyb20gJy4vZ3JhcGgnO1xuaW1wb3J0IHtvbm54cnVudGltZX0gZnJvbSAnLi9vcnQtc2NoZW1hL29ydC1nZW5lcmF0ZWQnO1xuaW1wb3J0IHtUZW5zb3J9IGZyb20gJy4vdGVuc29yJztcblxuLy8gY2hlY2sgdGhlIGlucHV0cyBzaGFwZSBiZWZvcmUgcnVubmluZyBhbiBPUC5cbi8vIHJldHVybiB0cnVlIHdoZW4gdGhlIGlucHV0cyBwYXNzIHRoZSBjaGVja1xuLy8gcmV0dXJuIGZhbHNlIHdoZW4gdGhlIGlucHV0cyBkbyBub3QgZml0IHRoZSByZXF1aXJlbWVudFxuLy8gdGhyb3cgZXhjZXB0aW9uIHdoZW4gZmF0YWwgZXJyb3Igb3Igbm90IGltcGxlbWVudGVkXG5leHBvcnQgZnVuY3Rpb24gY2hlY2tJbnB1dHNTaGFwZShpbnB1dHM6IFRlbnNvcltdLCAuLi5leHBlY3RlZERpbWVuc2lvbnM6IG51bWJlcltdKTogYm9vbGVhbiB7XG4gIGlmICghaW5wdXRzIHx8IGlucHV0cy5sZW5ndGggIT09IGV4cGVjdGVkRGltZW5zaW9ucy5sZW5ndGgpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBpbnB1dHMubGVuZ3RoOyBpKyspIHtcbiAgICBpZiAoIWlucHV0c1tpXS5kaW1zIHx8IGlucHV0c1tpXS5kaW1zLmxlbmd0aCAhPT0gZXhwZWN0ZWREaW1lbnNpb25zW2ldKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICB9XG4gIHJldHVybiB0cnVlO1xufVxuXG4vLyBFdmFsdWF0ZXMgdGhlIGdpdmVuIGV4cHJlc3Npb24gYW5kIGFzc2VydHMgZXJyb3IgbWVzc2FnZSBpZiBjb25kaXRpb24gaXMgdW5tZXQuXG5leHBvcnQgZnVuY3Rpb24gYXNzZXJ0KGV4cHI6IGJvb2xlYW4sIG1zZzogKCkgPT4gc3RyaW5nKSB7XG4gIGlmICghZXhwcikge1xuICAgIHRocm93IG5ldyBFcnJvcih0eXBlb2YgbXNnID09PSAnc3RyaW5nJyA/IG1zZyA6IG1zZygpKTtcbiAgfVxufVxuXG5leHBvcnQgY2xhc3MgQXJyYXlVdGlsIHtcbiAgLyoqXG4gICAqIFZlcmlmaWVzIGlmIDIgaW5wdXQgYXJyYXlzIGNvbnRhaW4gdGhlIHNhbWUgZWxlbWVudHMuXG4gICAqIEBwYXJhbSBuMSBBcnJheSAxXG4gICAqIEBwYXJhbSBuMiBBcnJheSAyXG4gICAqIEByZXR1cm5zIFdoZXRoZXIgdGhlc2UgMiBhcmUgZXF1YWxcbiAgICovXG4gIHN0YXRpYyBhcnJheXNFcXVhbChcbiAgICAgIG4xOiByZWFkb25seSBudW1iZXJbXXxJbnQ4QXJyYXl8VWludDhBcnJheXxJbnQxNkFycmF5fFVpbnQxNkFycmF5fEludDMyQXJyYXl8VWludDMyQXJyYXl8VWludDhDbGFtcGVkQXJyYXl8XG4gICAgICBGbG9hdDMyQXJyYXl8RmxvYXQ2NEFycmF5LFxuICAgICAgbjI6IHJlYWRvbmx5IG51bWJlcltdfEludDhBcnJheXxVaW50OEFycmF5fEludDE2QXJyYXl8VWludDE2QXJyYXl8SW50MzJBcnJheXxVaW50MzJBcnJheXxVaW50OENsYW1wZWRBcnJheXxcbiAgICAgIEZsb2F0MzJBcnJheXxGbG9hdDY0QXJyYXkpIHtcbiAgICBpZiAobjEubGVuZ3RoICE9PSBuMi5sZW5ndGgpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBuMS5sZW5ndGg7IGkrKykge1xuICAgICAgaWYgKG4xW2ldICE9PSBuMltpXSkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiB0cnVlO1xuICB9XG59XG5cbmV4cG9ydCBjbGFzcyBNYXRNdWxVdGlsIHtcbiAgLyoqXG4gICAqIEZpeCB0aGUgaW5wdXQgc2hhcGVzIGZvciBNYXRNdWwgb3BlcmF0aW9uIGlmIHRoZXkgbmVlZCBmaXhpbmdcbiAgICogQHBhcmFtIGRpbXNBIFRoZSBzaGFwZSBvZiB0ZW5zb3IgQS4gU2hvdWxkIGJlIGFuIGFycmF5IG9mIHBvc2l0aXZlIGludGVnZXJzXG4gICAqIEBwYXJhbSBkaW1zQiBUaGUgc2hhcGUgb2YgdGVuc29yIEIuIFNob3VsZCBiZSBhbiBhcnJheSBvZiBwb3NpdGl2ZSBpbnRlZ2Vyc1xuICAgKiBAcmV0dXJucyBBIHR1cGxlIGNvbnRhaW5pbmcgdGhlIHByZXByb2Nlc3NlZCBpbnB1dCBzaGFwZXMgYXMgcmVxdWlyZWQgYnkgT05OWCBzcGVjaWZpY2F0aW9uc1xuICAgKi9cbiAgc3RhdGljIHByZXByb2Nlc3NJbnB1dFNoYXBlcyhkaW1zQTogcmVhZG9ubHkgbnVtYmVyW10sIGRpbXNCOiByZWFkb25seSBudW1iZXJbXSk6XG4gICAgICBbcmVhZG9ubHkgbnVtYmVyW10sIHJlYWRvbmx5IG51bWJlcltdXSB7XG4gICAgLy8gSWYgdGhlIGZpcnN0IGFyZ3VtZW50IGlzIDEtRCwgaXQgaXMgcHJvbW90ZWQgdG8gYSBtYXRyaXggYnkgcHJlcGVuZGluZ1xuICAgIC8vIGEgMSB0byBpdHMgZGltZW5zaW9ucy4gQWZ0ZXIgbWF0cml4IG11bHRpcGxpY2F0aW9uIHRoZSBwcmVwZW5kZWQgMSBpc1xuICAgIC8vIHJlbW92ZWQuXG4gICAgY29uc3QgYSA9IChkaW1zQS5sZW5ndGggPT09IDEpID8gWzEsIGRpbXNBWzBdXSA6IGRpbXNBO1xuXG4gICAgLy8gSWYgdGhlIHNlY29uZCBhcmd1bWVudCBpcyAxLUQsIGl0IGlzIHByb21vdGVkIHRvIGEgbWF0cml4IGJ5IGFwcGVuZGluZ1xuICAgIC8vIGEgMSB0byBpdHMgZGltZW5zaW9ucy4gQWZ0ZXIgbWF0cml4IG11bHRpcGxpY2F0aW9uIHRoZSBhcHBlbmRlZCAxIGlzXG4gICAgLy8gcmVtb3ZlZC5cbiAgICBjb25zdCBiID0gKGRpbXNCLmxlbmd0aCA9PT0gMSkgPyBbZGltc0JbMF0sIDFdIDogZGltc0I7XG5cbiAgICByZXR1cm4gW2EsIGJdO1xuICB9XG5cbiAgLyoqXG4gICAqIEZpeCB0aGUgb3V0cHV0IHNoYXBlIGNvbXB1dGVkIGZvciBNYXRNdWwgb3BlcmF0aW9uIGlmIGl0IG5lZWRzIGZpeGluZ1xuICAgKiBAcGFyYW0gb3V0cHV0U2hhcGUgVGhlIGNvbXB1dGVkIG91dHB1dFNoYXBlLiBTaG91bGQgYmUgYW4gYXJyYXkgKGF0bGVhc3Qgb2YgbGVuZ3RoIDIpIG9mIHBvc2l0aXZlIGludGVnZXJzLlxuICAgKiBUaGlzIHdpbGwgYmUgbXV0YXRlZC5cbiAgICogQHBhcmFtIGFSYW5rIFRoZSByYW5rIG9mIHRlbnNvciBBLlxuICAgKiBAcGFyYW0gYlJhbmsgVGhlIHJhbmsgb2YgdGVuc29yIEIuXG4gICAqL1xuICBzdGF0aWMgcG9zdHByb2Nlc3NPdXRwdXRTaGFwZShvdXRwdXRTaGFwZTogbnVtYmVyW10sIGFSYW5rOiBudW1iZXIsIGJSYW5rOiBudW1iZXIpIHtcbiAgICAvLyBSZW1vdmUgcHJlcGVuZGVkIGRpbWVuc2lvbiBpZiBmaXJzdCBpbnB1dCBpcyAxZFxuICAgIGlmIChhUmFuayA9PT0gMSkge1xuICAgICAgLy8gb3V0cHV0U2hhcGUgPSBvdXRwdXRTaGFwZS5zbGljZSgwLCBvdXRwdXRTaGFwZS5sZW5ndGggLSAyKS5jb25jYXQob3V0cHV0U2hhcGUuc2xpY2Uob3V0cHV0U2hhcGUubGVuZ3RoIC0gMSkpO1xuICAgICAgb3V0cHV0U2hhcGUuc3BsaWNlKG91dHB1dFNoYXBlLmxlbmd0aCAtIDIsIDEpO1xuICAgIH1cbiAgICAvLyBSZW1vdmUgYXBwZW5kZWQgZGltZW5zaW9uIGlmIHNlY29uZCBpbnB1dCBpcyAxZFxuICAgIGlmIChiUmFuayA9PT0gMSkge1xuICAgICAgb3V0cHV0U2hhcGUucG9wKCk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIENhbGN1bGF0ZSB0aGUgZXhwZWN0ZWQgc2hhcGUgd2hlbiBtYXRyaXggbXVsdGlwbGljYXRpb25cbiAgICogQHBhcmFtIGEgVGhlIHNoYXBlIG9mIHRlbnNvciBBLiBTaG91bGQgYmUgYSB0dXBsZSBvZiAyIHBvc2l0aXZlIGludGVnZXJzXG4gICAqIEBwYXJhbSBiIFRoZSBzaGFwZSBvZiB0ZW5zb3IgQi4gU2hvdWxkIGJlIGEgdHVwbGUgb2YgMiBwb3NpdGl2ZSBpbnRlZ2Vyc1xuICAgKiBAcmV0dXJucyBUaGUgZXhwZWN0ZWQgc2hhcGUgb2YgdGhlIHJlc3VsdCwgb3IgdW5kZWZpbmVkIGlmIE4vQVxuICAgKi9cbiAgc3RhdGljIGNhbGNNYXRNdWxTaGFwZShhOiBbbnVtYmVyLCBudW1iZXJdLCBiOiBbbnVtYmVyLCBudW1iZXJdKTogW251bWJlciwgbnVtYmVyXXx1bmRlZmluZWQge1xuICAgIHJldHVybiAoYVsxXSAhPT0gYlswXSkgPyB1bmRlZmluZWQgOiBbYVswXSwgYlsxXV07XG4gIH1cbn1cblxuZXhwb3J0IGNsYXNzIEJyb2FkY2FzdFV0aWwge1xuICAvKipcbiAgICogQ2FsY3VsYXRlIHRoZSBleHBlY3RlZCBzaGFwZSB3aGVuIGJyb2FkY2FzdGluZyAyIHRlbnNvcnNcbiAgICogQHBhcmFtIGEgVGhlIHNoYXBlIG9mIHRlbnNvciBBLiBTaG91bGQgYmUgYW4gYXJyYXkgb2YgcG9zaXRpdmUgaW50ZWdlcnNcbiAgICogQHBhcmFtIGIgVGhlIHNoYXBlIG9mIHRlbnNvciBCLiBTaG91bGQgYmUgYW4gYXJyYXkgb2YgcG9zaXRpdmUgaW50ZWdlcnNcbiAgICogQHBhcmFtIGlzTWF0TXVsIFdoZXRoZXIgdGhlIG9wZXJhdGlvbiBpcyBNYXRNdWxcbiAgICogQHJldHVybnMgVGhlIGV4cGVjdGVkIHNoYXBlIG9mIHRoZSByZXN1bHQsIG9yIHVuZGVmaW5lZCBpZiBOL0FcbiAgICovXG4gIHN0YXRpYyBjYWxjU2hhcGUoYWRpbXM6IHJlYWRvbmx5IG51bWJlcltdLCBiZGltczogcmVhZG9ubHkgbnVtYmVyW10sIGlzTWF0TXVsID0gZmFsc2UpOiByZWFkb25seSBudW1iZXJbXXx1bmRlZmluZWQge1xuICAgIGNvbnN0IGFyYW5rID0gYWRpbXMubGVuZ3RoO1xuICAgIGNvbnN0IGJyYW5rID0gYmRpbXMubGVuZ3RoO1xuICAgIGlmIChhcmFuayA9PT0gMCkge1xuICAgICAgcmV0dXJuIGJkaW1zO1xuICAgIH1cbiAgICBpZiAoYnJhbmsgPT09IDApIHtcbiAgICAgIHJldHVybiBhZGltcztcbiAgICB9XG4gICAgY29uc3QgY3JhbmsgPSBNYXRoLm1heChhZGltcy5sZW5ndGgsIGJkaW1zLmxlbmd0aCk7XG4gICAgY29uc3QgY2RpbXMgPSBuZXcgQXJyYXk8bnVtYmVyPihjcmFuayk7XG5cbiAgICAvLyBjYWxjdWxhdGUgdGhlIGxhc3QgMiBkaW1lbnNpb24gaWYgaXQgaXMgTWF0TXVsXG4gICAgaWYgKGlzTWF0TXVsKSB7XG4gICAgICBpZiAoYXJhbmsgPCAyIHx8IGJyYW5rIDwgMikge1xuICAgICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgICAgfVxuICAgICAgY29uc3QgY1NoYXBlTWF0TXVsID1cbiAgICAgICAgICBNYXRNdWxVdGlsLmNhbGNNYXRNdWxTaGFwZShbYWRpbXNbYXJhbmsgLSAyXSwgYWRpbXNbYXJhbmsgLSAxXV0sIFtiZGltc1ticmFuayAtIDJdLCBiZGltc1ticmFuayAtIDFdXSk7XG4gICAgICBpZiAoY1NoYXBlTWF0TXVsID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICAgIH1cbiAgICAgIFtjZGltc1tjcmFuayAtIDJdLCBjZGltc1tjcmFuayAtIDFdXSA9IGNTaGFwZU1hdE11bDtcbiAgICB9XG5cbiAgICBmb3IgKGxldCBpID0gaXNNYXRNdWwgPyAzIDogMTsgaSA8PSBjcmFuazsgaSsrKSB7XG4gICAgICBjb25zdCBhTGVuID0gYXJhbmsgLSBpIDwgMCA/IDEgOiBhZGltc1thcmFuayAtIGldO1xuICAgICAgY29uc3QgYkxlbiA9IGJyYW5rIC0gaSA8IDAgPyAxIDogYmRpbXNbYnJhbmsgLSBpXTtcblxuICAgICAgaWYgKGFMZW4gIT09IGJMZW4gJiYgYUxlbiA+IDEgJiYgYkxlbiA+IDEpIHtcbiAgICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICAgIH1cbiAgICAgIGNkaW1zW2NyYW5rIC0gaV0gPSBNYXRoLm1heChhTGVuLCBiTGVuKTtcbiAgICB9XG5cbiAgICByZXR1cm4gY2RpbXM7XG4gIH1cblxuICAvKipcbiAgICogR2l2ZW4gdGhlIGluZGljZXMgb2YgYSBicm9hZGNhc3RlZCB0ZW5zb3IsIGNhbGN1bGF0ZSB0aGUgb3JpZ2luYWwgaW5kaWNlc1xuICAgKiBAcGFyYW0gYnJvYWRjYXN0ZWRJbmRpY2VzIFRoZSBnaXZlbiBpbmRpY2VzIG9mIHRoZSBicm9hZGNhc3RlZCB0ZW5zb3IuXG4gICAqIEBwYXJhbSBvcmlnaW5hbFNoYXBlIFRoZSBvcmlnaW5hbCBzaGFwZSBvZiB0aGUgdGVuc29yIGJlZm9yZSBicm9hZGNhc1xuICAgKiBAcmV0dXJucyBUaGUgY2FsY3VsYXRlZCBpbmRpY2VzIHRoYXQgbWFwcyB0byB0aGUgb3JpZ2luYWwgdGVuc29yLlxuICAgKi9cbiAgc3RhdGljIGluZGV4KGJyb2FkY2FzdGVkSW5kaWNlczogcmVhZG9ubHkgbnVtYmVyW10sIG9yaWdpbmFsU2hhcGU6IHJlYWRvbmx5IG51bWJlcltdKTogbnVtYmVyW10ge1xuICAgIC8vIE5PVEUgMTogd2UgYXNzdW1lIHRoZSBwYXJhbWV0ZXIgYnJvYWRjYXN0ZWRJbmRpY2VzIGlzIHZhbGlkLiBpZS4gaXQgc2hvdWxkIGhhdmUgdGhlIHNhbWVcbiAgICAvLyBsZW5ndGggYXMgdGhlIGJyb2FkY2FzdGVkIHNoYXBlLCBhbmQgZm9yIGVhY2ggZGltZW5zaW9uIHRoZSBpbmRleCBzaG91bGRcbiAgICAvLyBub3QgYmUgb3V0IG9mIHJhbmdlLlxuICAgIGNvbnN0IG9yaWdpbmFsSW5kaWNlcyA9IG5ldyBBcnJheShvcmlnaW5hbFNoYXBlLmxlbmd0aCk7XG4gICAgQnJvYWRjYXN0VXRpbC5maWxsSW5kZXgoYnJvYWRjYXN0ZWRJbmRpY2VzLCBvcmlnaW5hbFNoYXBlLCBvcmlnaW5hbEluZGljZXMpO1xuICAgIHJldHVybiBvcmlnaW5hbEluZGljZXM7XG4gIH1cblxuICAvKipcbiAgICogR2l2ZW4gdGhlIGluZGljZXMgb2YgYSBicm9hZGNhc3RlZCB0ZW5zb3IsIGNhbGN1bGF0ZSB0aGUgb3JpZ2luYWwgaW5kaWNlc1xuICAgKiBAcGFyYW0gYnJvYWRjYXN0ZWRJbmRpY2VzIFRoZSBnaXZlbiBpbmRpY2VzIG9mIHRoZSBicm9hZGNhc3RlZCB0ZW5zb3IuXG4gICAqIEBwYXJhbSBvcmlnaW5hbFNoYXBlIFRoZSBvcmlnaW5hbCBzaGFwZSBvZiB0aGUgdGVuc29yIGJlZm9yZSBicm9hZGNhc3RcbiAgICogQHBhcmFtIG9yaWdpbmFsSW5kaWNlcyBUaGUgbWFwcGluZyBvZiBicm9hZGNhc3RlZEluZGljZXMgdG8gdGhlIG9yaWdpbmFsSW5kaWNlcyAob3V0cHV0IHBhcmFtZXRlciAtIHdpbGwgYmVcbiAgICogICAgIG11dGF0ZWQpLlxuICAgKi9cbiAgc3RhdGljIGZpbGxJbmRleChicm9hZGNhc3RlZEluZGljZXM6IHJlYWRvbmx5IG51bWJlcltdLCBvcmlnaW5hbFNoYXBlOiByZWFkb25seSBudW1iZXJbXSwgb3JpZ2luYWxJbmRpY2VzOiBudW1iZXJbXSkge1xuICAgIC8vIE5PVEUgMTogd2UgYXNzdW1lIHRoZSBwYXJhbWV0ZXIgYnJvYWRjYXN0ZWRJbmRpY2VzIGlzIHZhbGlkLiBpZS4gaXQgc2hvdWxkIGhhdmUgdGhlIHNhbWUgbGVuZ3RoIGFzIHRoZVxuICAgIC8vIGJyb2FkY2FzdGVkIHNoYXBlLCBhbmQgZm9yIGVhY2ggZGltZW5zaW9uIHRoZSBpbmRleCBzaG91bGQgbm90IGJlIG91dCBvZiByYW5nZS5cbiAgICAvLyBOT1RFIDI6IHdlIGFzc3VtZSB0aGUgcGFyYW1ldGVyIG9yaWdpbmFsSW5kaWNlcyBoYXMgdGhlIHNhbWUgbGVuZ3RoIGFzIHRoZSBvcmlnaW5hbFNoYXBlXG4gICAgY29uc3QgZGltT2Zmc2V0ID0gYnJvYWRjYXN0ZWRJbmRpY2VzLmxlbmd0aCAtIG9yaWdpbmFsU2hhcGUubGVuZ3RoO1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgb3JpZ2luYWxTaGFwZS5sZW5ndGg7IGkrKykge1xuICAgICAgb3JpZ2luYWxJbmRpY2VzW2ldID0gYnJvYWRjYXN0ZWRJbmRpY2VzW2RpbU9mZnNldCArIGldICUgb3JpZ2luYWxTaGFwZVtpXTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogUGVyZm9ybSB0aGUgYnJvYWRjYXN0aW5nIG9wZXJhdGlvbiBvbiB0aGUgc3BlY2lmaWMgb3BlcmF0b3JcbiAgICogQHBhcmFtIGEgVGhlIGlucHV0IHRlbnNvciBBXG4gICAqIEBwYXJhbSBiIFRoZSBpbnB1dCB0ZW5zb3IgQlxuICAgKiBAcGFyYW0gb3AgVGhlIG9wZXJhdG9yIGxhbWJkYSBmdW5jdGlvblxuICAgKiBAcGFyYW0gaW5wbGFjZSBXaGV0aGVyIHRvIHdyaXRlIHRoZSByZXN1bHQgYmFjayB0byBBLlxuICAgKiBAcmV0dXJucyBUaGUgcmVzdWx0IHRlbnNvciwgb3IgdW5kZWZpbmVkIGlmIGlucHV0IG5vdCBicm9hZGNhc3RhYmxlLlxuICAgKi9cbiAgc3RhdGljIGNhbGMoXG4gICAgICBhOiBUZW5zb3IsIGI6IFRlbnNvciwgb3A6IChhOiBzdHJpbmd8bnVtYmVyLCBiOiBzdHJpbmd8bnVtYmVyKSA9PiAoc3RyaW5nIHwgbnVtYmVyKSwgaW5wbGFjZTogYm9vbGVhbixcbiAgICAgIHJlc3VsdFR5cGU/OiBUZW5zb3IuRGF0YVR5cGUpOiBUZW5zb3J8dW5kZWZpbmVkIHtcbiAgICBjb25zdCBvdXRwdXRTaGFwZSA9IEJyb2FkY2FzdFV0aWwuY2FsY1NoYXBlKGEuZGltcywgYi5kaW1zKTtcblxuICAgIGlmIChvdXRwdXRTaGFwZSkge1xuICAgICAgaWYgKGlucGxhY2UgJiYgIVNoYXBlVXRpbC5hcmVFcXVhbChvdXRwdXRTaGFwZSwgYS5kaW1zKSkge1xuICAgICAgICAvLyBCIGlzIG5vdCBicm9hZGNhc3RhYmxlIHRvIEEsIGZhaWxlZCB0byBjYWxjdWxhdGUgaW5wbGFjZS5cbiAgICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICAgIH1cblxuICAgICAgY29uc3Qgc2l6ZSA9IFNoYXBlVXRpbC5zaXplKG91dHB1dFNoYXBlKTtcbiAgICAgIGNvbnN0IGMgPSBpbnBsYWNlID8gYSA6IG5ldyBUZW5zb3Iob3V0cHV0U2hhcGUsIHJlc3VsdFR5cGUgfHwgYS50eXBlKTtcblxuICAgICAgLy8gYm90aCBpbnB1dHMgYXJlIHNjYWxhcnNcbiAgICAgIGlmIChvdXRwdXRTaGFwZS5sZW5ndGggPT09IDApIHtcbiAgICAgICAgYy5zZXQoW10sIG9wKGEuZ2V0KFtdKSwgYi5nZXQoW10pKSk7XG4gICAgICB9XG5cbiAgICAgIC8vIGF0bGVhc3Qgb25lIGlucHV0IGlzIGEgbm9uLXNjYWxhclxuICAgICAgZWxzZSB7XG4gICAgICAgIGNvbnN0IG91dHB1dEluZGljZXMgPSBuZXcgQXJyYXk8bnVtYmVyPihvdXRwdXRTaGFwZS5sZW5ndGgpO1xuICAgICAgICBjb25zdCBvcmlnaW5hbEluZGljZXNBID0gbmV3IEFycmF5KGEuZGltcy5sZW5ndGgpO1xuICAgICAgICBjb25zdCBvcmlnaW5hbEluZGljZXNCID0gbmV3IEFycmF5KGIuZGltcy5sZW5ndGgpO1xuICAgICAgICBsZXQgdmFsQTogc3RyaW5nfG51bWJlciA9IDA7XG4gICAgICAgIGxldCB2YWxCOiBzdHJpbmd8bnVtYmVyID0gMDtcbiAgICAgICAgbGV0IGlzQVNjYWxhciA9IGZhbHNlO1xuICAgICAgICBsZXQgaXNCU2NhbGFyID0gZmFsc2U7XG4gICAgICAgIGlmIChhLmRpbXMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgdmFsQSA9IGEuZ2V0KFtdKTtcbiAgICAgICAgICBpc0FTY2FsYXIgPSB0cnVlO1xuICAgICAgICB9XG4gICAgICAgIGlmIChiLmRpbXMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgdmFsQiA9IGIuZ2V0KFtdKTtcbiAgICAgICAgICBpc0JTY2FsYXIgPSB0cnVlO1xuICAgICAgICB9XG4gICAgICAgIGxldCByZXN0OiBudW1iZXI7XG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgc2l6ZTsgaSsrKSB7XG4gICAgICAgICAgLy8gdHJhdmVyc2FsIGluZGljZXNcbiAgICAgICAgICByZXN0ID0gaTtcbiAgICAgICAgICBmb3IgKGxldCBqID0gb3V0cHV0U2hhcGUubGVuZ3RoIC0gMTsgaiA+PSAwOyBqLS0pIHtcbiAgICAgICAgICAgIG91dHB1dEluZGljZXNbal0gPSByZXN0ICUgb3V0cHV0U2hhcGVbal07XG4gICAgICAgICAgICByZXN0ID0gTWF0aC5mbG9vcihyZXN0IC8gb3V0cHV0U2hhcGVbal0pO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGlmICghaXNBU2NhbGFyKSB7XG4gICAgICAgICAgICAvLyBtYXAgb3V0cHV0SW5kaWNlcyAod2hpY2ggaXMgYWN0dWFsbHkgYnJvYWRjYXN0ZWQpIHRvIHRoZSBvcmlnaW5hbEluZGljZXNcbiAgICAgICAgICAgIEJyb2FkY2FzdFV0aWwuZmlsbEluZGV4KG91dHB1dEluZGljZXMsIGEuZGltcywgb3JpZ2luYWxJbmRpY2VzQSk7XG4gICAgICAgICAgICB2YWxBID0gYS5nZXQob3JpZ2luYWxJbmRpY2VzQSk7XG4gICAgICAgICAgfVxuICAgICAgICAgIGlmICghaXNCU2NhbGFyKSB7XG4gICAgICAgICAgICBCcm9hZGNhc3RVdGlsLmZpbGxJbmRleChvdXRwdXRJbmRpY2VzLCBiLmRpbXMsIG9yaWdpbmFsSW5kaWNlc0IpO1xuICAgICAgICAgICAgdmFsQiA9IGIuZ2V0KG9yaWdpbmFsSW5kaWNlc0IpO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGMuc2V0KG91dHB1dEluZGljZXMsIG9wKHZhbEEsIHZhbEIpKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICByZXR1cm4gYztcbiAgICB9XG5cbiAgICByZXR1cm4gdW5kZWZpbmVkO1xuICB9XG5cbiAgLyoqXG4gICAqIERldGVybWluZSBpZiBhIHNoYXBlIGlzIHVuaWRpcmVjdGlvbmFsIGJyb2FkY2FzdGFibGUgdG8gYW5vdGhlciBzaGFwZVxuICAgKiBAcGFyYW0gc2hhcGUgVGhlIGlucHV0IHNoYXBlXG4gICAqIEBwYXJhbSBmaW5hbFNoYXBlIFRoZSBkZXNpcmVkIHNoYXBlIGFmdGVyIGJyb2FkY2FzdGluZ1xuICAgKi9cbiAgc3RhdGljIGlzVmFsaWRCcm9hZGNhc3Qoc2hhcGU6IHJlYWRvbmx5IG51bWJlcltdLCBmaW5hbFNoYXBlOiByZWFkb25seSBudW1iZXJbXSk6IGJvb2xlYW4ge1xuICAgIC8vIGFsaWduIHNoYXBlIHRvIHRoZSByaWdodFxuICAgIGNvbnN0IGlucHV0UmFuayA9IHNoYXBlLmxlbmd0aDtcbiAgICBjb25zdCBmaW5hbFJhbmsgPSBmaW5hbFNoYXBlLmxlbmd0aDtcbiAgICBpZiAoaW5wdXRSYW5rID4gZmluYWxSYW5rKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICAgIGZvciAobGV0IGkgPSAxOyBpIDw9IGlucHV0UmFuazsgaSsrKSB7XG4gICAgICBpZiAoc2hhcGVbaW5wdXRSYW5rIC0gaV0gIT09IDEgJiYgc2hhcGVbaW5wdXRSYW5rIC0gaV0gIT09IGZpbmFsU2hhcGVbZmluYWxSYW5rIC0gaV0pIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBEZXRlcm1pbmUgdGhlIGJyb2FkY2FzdGVkIGRpbXMgaW4gaW5wdXQgc2hhcGUgYmFzZWQgb24gdGhlIGdpdmVuIG91dHB1dCBzaGFwZS5cbiAgICogTm90ZSB0aGF0IHRoaXMgZnVuY3Rpb24gb25seSByZXR1cm5zIHRoZSBicm9hZGNhc3RlZCBkaW1zLlxuICAgKiBAcGFyYW0gaW5wdXRTaGFwZSBUaGUgaW5wdXQgc2hhcGVcbiAgICogQHBhcmFtIG91dHB1dFNoYXBlIFRoZSBvdXRwdXQgc2hhcGVcbiAgICogQHJldHVybnMgVGhlIGJyb2FkY2FzdGVkIGRpbXMgaW4gaW5wdXQgc2hhcGUuXG4gICAqL1xuICBzdGF0aWMgZ2V0QnJvYWRjYXN0RGltcyhpbnB1dFNoYXBlOiByZWFkb25seSBudW1iZXJbXSwgb3V0cHV0U2hhcGU6IHJlYWRvbmx5IG51bWJlcltdKTogbnVtYmVyW10ge1xuICAgIGNvbnN0IGluUmFuayA9IGlucHV0U2hhcGUubGVuZ3RoO1xuICAgIGNvbnN0IGRpbXM6IG51bWJlcltdID0gW107XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBpblJhbms7IGkrKykge1xuICAgICAgY29uc3QgZGltID0gaW5SYW5rIC0gMSAtIGk7XG4gICAgICBjb25zdCBhID0gaW5wdXRTaGFwZVtkaW1dIHx8IDE7XG4gICAgICBjb25zdCBiID0gb3V0cHV0U2hhcGVbb3V0cHV0U2hhcGUubGVuZ3RoIC0gMSAtIGldIHx8IDE7XG4gICAgICBpZiAoYiA+IDEgJiYgYSA9PT0gMSkge1xuICAgICAgICBkaW1zLnVuc2hpZnQoZGltKTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIGRpbXM7XG4gIH1cbn1cblxuLy8gY29weSBhcnJheSBoZWxwZXJcbi8vIG1pbWljcyBtZW1jcHkgYXMgbXVjaCBhcyBwb3NzaWJsZVxuZXhwb3J0IGZ1bmN0aW9uIGFycmF5Q29weUhlbHBlcihcbiAgICB0YXJnZXQ6IG51bWJlcltdfFRlbnNvci5OdW1iZXJUeXBlLCBzb3VyY2U6IG51bWJlcltdfFRlbnNvci5OdW1iZXJUeXBlLCB0YXJnZXRJbmRleDogbnVtYmVyLCBzb3VyY2VJbmRleDogbnVtYmVyLFxuICAgIGJsb2NrU2l6ZTogbnVtYmVyKSB7XG4gIGlmIChzb3VyY2VJbmRleCA8IDAgfHwgc291cmNlSW5kZXggPj0gc291cmNlLmxlbmd0aCkge1xuICAgIHRocm93IG5ldyBFcnJvcignc291cmNlSW5kZXggb3V0IG9mIGJvdW5kcycpO1xuICB9XG4gIGlmICh0YXJnZXRJbmRleCA8IDAgfHwgdGFyZ2V0SW5kZXggPj0gdGFyZ2V0Lmxlbmd0aCkge1xuICAgIHRocm93IG5ldyBFcnJvcigndGFyZ2V0SW5kZXggb3V0IG9mIGJvdW5kcycpO1xuICB9XG4gIGlmIChzb3VyY2VJbmRleCArIGJsb2NrU2l6ZSA+IHNvdXJjZS5sZW5ndGgpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ3NvdXJjZSBpbmRpY2VzIHRvIGJlIGNvcGllZCBhcmUgb3V0c2lkZSBib3VuZHMnKTtcbiAgfVxuICBpZiAodGFyZ2V0SW5kZXggKyBibG9ja1NpemUgPiB0YXJnZXQubGVuZ3RoKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCd0YXJnZXQgYXJyYXkgaXMgdG9vIHNtYWxsIHRvIGhvbGQgcmVzdWx0Jyk7XG4gIH1cblxuICBmb3IgKGxldCBvZmZzZXQgPSAwOyBvZmZzZXQgPCBibG9ja1NpemU7IG9mZnNldCsrKSB7XG4gICAgdGFyZ2V0W3RhcmdldEluZGV4ICsgb2Zmc2V0XSA9IHNvdXJjZVtzb3VyY2VJbmRleCArIG9mZnNldF07XG4gIH1cbn1cblxuZXhwb3J0IGNsYXNzIEdlbW1VdGlsIHtcbiAgLy8gd2lsbCBtYWtlIHN1cmUgaW5wdXQgc2hhcGVzIGFyZSBjb21wYXRpYmxlIGZvciB0aGlzIG9wXG4gIC8vIGFuZCByZXR1cm4gYmFjayB0aGUgc2hhcGUgb2YgdGhlIG91dHB1dCBpbiB0aGUgZm9ybSBvZiBhIHR1cGxlXG4gIC8vIHdpbGwgdGhyb3cgZXhjZXB0aW9uIGlmIHRoZSBpbnB1dCBzaGFwZXMgYXJlIG5vdCBjb21wYXRpYmxlXG4gIHN0YXRpYyBnZXRTaGFwZU9mR2VtbVJlc3VsdChcbiAgICAgIGxlZnRTaGFwZTogcmVhZG9ubHkgbnVtYmVyW10sIHRyYW5zTGVmdDogYm9vbGVhbiwgcmlnaHRTaGFwZTogcmVhZG9ubHkgbnVtYmVyW10sIHRyYW5zUmlnaHQ6IGJvb2xlYW4sXG4gICAgICBiaWFzU2hhcGU/OiByZWFkb25seSBudW1iZXJbXSk6IHJlYWRvbmx5IG51bWJlcltdIHtcbiAgICBpZiAobGVmdFNoYXBlLmxlbmd0aCAhPT0gMiB8fCByaWdodFNoYXBlLmxlbmd0aCAhPT0gMikge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdzaGFwZSBuZWVkIHRvIGJlIG9mIHNpemUgMicpO1xuICAgIH1cblxuICAgIGxldCBNOiBudW1iZXI7XG4gICAgbGV0IEs6IG51bWJlcjtcbiAgICBsZXQgTjogbnVtYmVyO1xuXG4gICAgaWYgKHRyYW5zTGVmdCkge1xuICAgICAgTSA9IGxlZnRTaGFwZVsxXTtcbiAgICAgIEsgPSBsZWZ0U2hhcGVbMF07XG4gICAgfSBlbHNlIHtcbiAgICAgIE0gPSBsZWZ0U2hhcGVbMF07XG4gICAgICBLID0gbGVmdFNoYXBlWzFdO1xuICAgIH1cblxuICAgIGxldCBrRGltID0gLTE7XG5cbiAgICBpZiAodHJhbnNSaWdodCkge1xuICAgICAgTiA9IHJpZ2h0U2hhcGVbMF07XG4gICAgICBrRGltID0gMTtcbiAgICB9IGVsc2Uge1xuICAgICAgTiA9IHJpZ2h0U2hhcGVbMV07XG4gICAgICBrRGltID0gMDtcbiAgICB9XG5cbiAgICBpZiAocmlnaHRTaGFwZVtrRGltXSAhPT0gSykge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdkaW1lbnNpb24gbWlzbWF0Y2gnKTtcbiAgICB9XG5cbiAgICBpZiAoTSA8PSAwIHx8IE4gPD0gMCB8fCBLIDw9IDApIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignaW52YWxpZCBzaGFwZSBzcGVjaWZpZWQnKTtcbiAgICB9XG5cbiAgICBpZiAoYmlhc1NoYXBlICYmICFCcm9hZGNhc3RVdGlsLmlzVmFsaWRCcm9hZGNhc3QoYmlhc1NoYXBlLCBbTSwgTl0pKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ2dlbW06IGludmFsaWQgYmlhcyBzaGFwZSBmb3IgYnJvYWRjYXN0Jyk7XG4gICAgfVxuXG4gICAgcmV0dXJuIFtNLCBOLCBLXTtcbiAgfVxufVxuXG5leHBvcnQgY2xhc3MgUHJvdG9VdGlsIHtcbiAgc3RhdGljIHRlbnNvckRhdGFUeXBlRnJvbVByb3RvKHR5cGVQcm90bzogb25ueC5UZW5zb3JQcm90by5EYXRhVHlwZXxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnMuVGVuc29yRGF0YVR5cGUpOiBUZW5zb3IuRGF0YVR5cGUge1xuICAgIHN3aXRjaCAodHlwZVByb3RvKSB7XG4gICAgICBjYXNlIG9ubnguVGVuc29yUHJvdG8uRGF0YVR5cGUuSU5UODpcbiAgICAgICAgcmV0dXJuICdpbnQ4JztcbiAgICAgIGNhc2Ugb25ueC5UZW5zb3JQcm90by5EYXRhVHlwZS5VSU5UODpcbiAgICAgICAgcmV0dXJuICd1aW50OCc7XG4gICAgICBjYXNlIG9ubnguVGVuc29yUHJvdG8uRGF0YVR5cGUuQk9PTDpcbiAgICAgICAgcmV0dXJuICdib29sJztcbiAgICAgIGNhc2Ugb25ueC5UZW5zb3JQcm90by5EYXRhVHlwZS5JTlQxNjpcbiAgICAgICAgcmV0dXJuICdpbnQxNic7XG4gICAgICBjYXNlIG9ubnguVGVuc29yUHJvdG8uRGF0YVR5cGUuVUlOVDE2OlxuICAgICAgICByZXR1cm4gJ3VpbnQxNic7XG4gICAgICBjYXNlIG9ubnguVGVuc29yUHJvdG8uRGF0YVR5cGUuSU5UMzI6XG4gICAgICAgIHJldHVybiAnaW50MzInO1xuICAgICAgY2FzZSBvbm54LlRlbnNvclByb3RvLkRhdGFUeXBlLlVJTlQzMjpcbiAgICAgICAgcmV0dXJuICd1aW50MzInO1xuICAgICAgY2FzZSBvbm54LlRlbnNvclByb3RvLkRhdGFUeXBlLkZMT0FUOlxuICAgICAgICByZXR1cm4gJ2Zsb2F0MzInO1xuICAgICAgY2FzZSBvbm54LlRlbnNvclByb3RvLkRhdGFUeXBlLkRPVUJMRTpcbiAgICAgICAgcmV0dXJuICdmbG9hdDY0JztcbiAgICAgIGNhc2Ugb25ueC5UZW5zb3JQcm90by5EYXRhVHlwZS5TVFJJTkc6XG4gICAgICAgIHJldHVybiAnc3RyaW5nJztcblxuICAgICAgLy8gRm9yIElOVDY0L1VJTlQ2NCwgcmVkdWNlIHRoZWlyIHZhbHVlIHRvIDMyLWJpdHMuXG4gICAgICAvLyBTaG91bGQgdGhyb3cgZXhjZXB0aW9uIHdoZW4gb3ZlcmZsb3dcbiAgICAgIGNhc2Ugb25ueC5UZW5zb3JQcm90by5EYXRhVHlwZS5JTlQ2NDpcbiAgICAgICAgcmV0dXJuICdpbnQzMic7XG4gICAgICBjYXNlIG9ubnguVGVuc29yUHJvdG8uRGF0YVR5cGUuVUlOVDY0OlxuICAgICAgICByZXR1cm4gJ3VpbnQzMic7XG5cbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgdW5zdXBwb3J0ZWQgZGF0YSB0eXBlOiAke29ubnguVGVuc29yUHJvdG8uRGF0YVR5cGVbdHlwZVByb3RvXX1gKTtcbiAgICB9XG4gIH1cblxuICBzdGF0aWMgdGVuc29yRGF0YVR5cGVTdHJpbmdUb0VudW0odHlwZTogc3RyaW5nKTogb25ueC5UZW5zb3JQcm90by5EYXRhVHlwZSB7XG4gICAgc3dpdGNoICh0eXBlKSB7XG4gICAgICBjYXNlICdpbnQ4JzpcbiAgICAgICAgcmV0dXJuIG9ubnguVGVuc29yUHJvdG8uRGF0YVR5cGUuSU5UODtcbiAgICAgIGNhc2UgJ3VpbnQ4JzpcbiAgICAgICAgcmV0dXJuIG9ubnguVGVuc29yUHJvdG8uRGF0YVR5cGUuVUlOVDg7XG4gICAgICBjYXNlICdib29sJzpcbiAgICAgICAgcmV0dXJuIG9ubnguVGVuc29yUHJvdG8uRGF0YVR5cGUuQk9PTDtcbiAgICAgIGNhc2UgJ2ludDE2JzpcbiAgICAgICAgcmV0dXJuIG9ubnguVGVuc29yUHJvdG8uRGF0YVR5cGUuSU5UMTY7XG4gICAgICBjYXNlICd1aW50MTYnOlxuICAgICAgICByZXR1cm4gb25ueC5UZW5zb3JQcm90by5EYXRhVHlwZS5VSU5UMTY7XG4gICAgICBjYXNlICdpbnQzMic6XG4gICAgICAgIHJldHVybiBvbm54LlRlbnNvclByb3RvLkRhdGFUeXBlLklOVDMyO1xuICAgICAgY2FzZSAndWludDMyJzpcbiAgICAgICAgcmV0dXJuIG9ubnguVGVuc29yUHJvdG8uRGF0YVR5cGUuVUlOVDMyO1xuICAgICAgY2FzZSAnZmxvYXQzMic6XG4gICAgICAgIHJldHVybiBvbm54LlRlbnNvclByb3RvLkRhdGFUeXBlLkZMT0FUO1xuICAgICAgY2FzZSAnZmxvYXQ2NCc6XG4gICAgICAgIHJldHVybiBvbm54LlRlbnNvclByb3RvLkRhdGFUeXBlLkRPVUJMRTtcbiAgICAgIGNhc2UgJ3N0cmluZyc6XG4gICAgICAgIHJldHVybiBvbm54LlRlbnNvclByb3RvLkRhdGFUeXBlLlNUUklORztcbiAgICAgIGNhc2UgJ2ludDY0JzpcbiAgICAgICAgcmV0dXJuIG9ubnguVGVuc29yUHJvdG8uRGF0YVR5cGUuSU5UNjQ7XG4gICAgICBjYXNlICd1aW50NjQnOlxuICAgICAgICByZXR1cm4gb25ueC5UZW5zb3JQcm90by5EYXRhVHlwZS5VSU5UNjQ7XG5cbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgdW5zdXBwb3J0ZWQgZGF0YSB0eXBlOiAke3R5cGV9YCk7XG4gICAgfVxuICB9XG5cbiAgc3RhdGljIHRlbnNvckRpbXNGcm9tUHJvdG8oZGltczogQXJyYXk8bnVtYmVyfExvbmc+KTogbnVtYmVyW10ge1xuICAgIC8vIGdldCByaWQgb2YgTG9uZyB0eXBlIGZvciBkaW1zXG4gICAgcmV0dXJuIGRpbXMubWFwKGQgPT4gTG9uZy5pc0xvbmcoZCkgPyBkLnRvTnVtYmVyKCkgOiBkKTtcbiAgfVxuXG4gIHN0YXRpYyB0ZW5zb3JWYWx1ZVR5cGVGcm9tUHJvdG8odmFsdWVUeXBlOiBvbm54LlR5cGVQcm90by5JVGVuc29yKTogR3JhcGguVmFsdWVUeXBlIHtcbiAgICByZXR1cm4ge1xuICAgICAgdGVuc29yVHlwZTogUHJvdG9VdGlsLnRlbnNvckRhdGFUeXBlRnJvbVByb3RvKHZhbHVlVHlwZS5lbGVtVHlwZSEpLFxuICAgICAgc2hhcGU6IHtkaW1zOiBQcm90b1V0aWwudGVuc29yRGltc0Zyb21Qcm90byh2YWx1ZVR5cGUuc2hhcGUhLmRpbSEubWFwKGQgPT4gZC5kaW1WYWx1ZSEpKX1cbiAgICB9O1xuICB9XG5cbiAgc3RhdGljIHRlbnNvckRpbXNGcm9tT1JURm9ybWF0KHRlbnNvcjogb25ueHJ1bnRpbWUuZXhwZXJpbWVudGFsLmZicy5UZW5zb3IpIHtcbiAgICBjb25zdCBkaW1zID0gW107XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0ZW5zb3IuZGltc0xlbmd0aCgpOyBpKyspIHtcbiAgICAgIGRpbXMucHVzaChMb25nVXRpbC5sb25nVG9OdW1iZXIodGVuc29yLmRpbXMoaSkhKSk7XG4gICAgfVxuICAgIHJldHVybiBkaW1zO1xuICB9XG5cbiAgc3RhdGljIHRlbnNvckF0dHJpYnV0ZXNGcm9tT1JURm9ybWF0KG5vZGU6IG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnMuTm9kZSkge1xuICAgIGNvbnN0IGF0dHJpYnV0ZXMgPSBbXTtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IG5vZGUuYXR0cmlidXRlc0xlbmd0aCgpOyBpKyspIHtcbiAgICAgIGF0dHJpYnV0ZXMucHVzaChub2RlLmF0dHJpYnV0ZXMoaSkhKTtcbiAgICB9XG4gICAgcmV0dXJuIGF0dHJpYnV0ZXM7XG4gIH1cbn1cblxuZXhwb3J0IGNsYXNzIExvbmdVdGlsIHtcbiAgLy8gVGhpcyBmdW5jdGlvbiBpcyBjYWxsZWQgdG8gZ2V0IGEgbnVtYmVyIGZyb20gbG9uZyB0eXBlIG9mIGRhdGEgZm9yIGF0dHJpYnV0ZSwgZGltLCBhbmQgaXIgdmVyc2lvbixcbiAgLy8gd2hpY2ggdmFsdWVzIGFyZSBzaWduZWQgaW50ZWdlcnMuXG4gIC8vIFRvIG1ha2UgaXQgbW9yZSBnZW5lcmljLCBhZGQgYW4gb3B0aW9uYWwgcGFyYW10ZXIgdG8gY29udmVydCB0byBhIHVuc2lnbmVkIG51bWJlci5cbiAgc3RhdGljIGxvbmdUb051bWJlcihuOiBMb25nfGZsYXRidWZmZXJzLkxvbmd8bnVtYmVyLCB1bnNpZ25lZD86IGJvb2xlYW4pIHtcbiAgICBpZiAoTG9uZy5pc0xvbmcobikpIHtcbiAgICAgIHJldHVybiBuLnRvTnVtYmVyKCk7XG4gICAgfSBlbHNlIGlmIChuIGluc3RhbmNlb2YgZmxhdGJ1ZmZlcnMuTG9uZykge1xuICAgICAgcmV0dXJuIExvbmcuZnJvbVZhbHVlKHtsb3c6IG4ubG93LCBoaWdoOiBuLmhpZ2gsIHVuc2lnbmVkOiB1bnNpZ25lZCA/PyBmYWxzZX0pLnRvTnVtYmVyKCk7XG4gICAgfVxuICAgIHJldHVybiBuO1xuICB9XG4gIHN0YXRpYyBpc0xvbmcobjogdW5rbm93bikge1xuICAgIHJldHVybiBMb25nLmlzTG9uZyhuKSB8fCBuIGluc3RhbmNlb2YgZmxhdGJ1ZmZlcnMuTG9uZztcbiAgfVxufVxuXG5leHBvcnQgY2xhc3MgU2hhcGVVdGlsIHtcbiAgc3RhdGljIHNpemUoZGltczogcmVhZG9ubHkgbnVtYmVyW10pOiBudW1iZXIge1xuICAgIHJldHVybiBTaGFwZVV0aWwuZ2V0U2l6ZUZyb21EaW1lbnNpb25SYW5nZShkaW1zLCAwLCBkaW1zLmxlbmd0aCk7XG4gIH1cblxuICAvLyBgYXhpc2AgaW5jbHVzaXZlXG4gIHN0YXRpYyBzaXplRnJvbURpbWVuc2lvbihkaW1zOiByZWFkb25seSBudW1iZXJbXSwgYXhpczogbnVtYmVyKTogbnVtYmVyIHtcbiAgICBpZiAoYXhpcyA8IDAgfHwgYXhpcyA+IGRpbXMubGVuZ3RoKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYGludmFsaWQgZGltZW5zaW9uIG9mICR7YXhpc30gZm9yIHNpemVGcm9tRGltZW5zaW9uIGFzIFRlbnNvciBoYXMgJHtkaW1zLmxlbmd0aH0gZGltZW5zaW9ucy5gKTtcbiAgICB9XG4gICAgcmV0dXJuIFNoYXBlVXRpbC5nZXRTaXplRnJvbURpbWVuc2lvblJhbmdlKGRpbXMsIGF4aXMsIGRpbXMubGVuZ3RoKTtcbiAgfVxuXG4gIC8vIGBheGlzYCBleGNsdXNpdmVcbiAgc3RhdGljIHNpemVUb0RpbWVuc2lvbihkaW1zOiByZWFkb25seSBudW1iZXJbXSwgYXhpczogbnVtYmVyKTogbnVtYmVyIHtcbiAgICBpZiAoYXhpcyA8IDAgfHwgYXhpcyA+IGRpbXMubGVuZ3RoKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYGludmFsaWQgZGltZW5zaW9uIG9mICR7YXhpc30gZm9yIHNpemVUb0RpbWVuc2lvbiBhcyBUZW5zb3IgaGFzICR7ZGltcy5sZW5ndGh9IGRpbWVuc2lvbnMuYCk7XG4gICAgfVxuICAgIHJldHVybiBTaGFwZVV0aWwuZ2V0U2l6ZUZyb21EaW1lbnNpb25SYW5nZShkaW1zLCAwLCBheGlzKTtcbiAgfVxuXG4gIHN0YXRpYyBnZXRTaXplRnJvbURpbWVuc2lvblJhbmdlKGRpbXM6IHJlYWRvbmx5IG51bWJlcltdLCBzdGFydDogbnVtYmVyLCBlbmQ6IG51bWJlcik6IG51bWJlciB7XG4gICAgbGV0IHNpemUgPSAxO1xuICAgIGZvciAobGV0IGkgPSBzdGFydDsgaSA8IGVuZDsgaSsrKSB7XG4gICAgICAvLyBzYWZldHkgY2hlY2sgYXMgdGhpcyBtZXRob2QgaXMgY2FsbGVkIGJ5IG11bHRpcGxlIG90aGVyIG1ldGhvZHMgcmVxdWlyaW5nIHNpemUuXG4gICAgICAvLyBzaXplIGNhbm5vdCBiZSAwIG9yIG5lZ2F0aXZlLlxuICAgICAgaWYgKGRpbXNbaV0gPD0gMCkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbWF4LWxlblxuICAgICAgICAgICAgJ2Nhbm5vdCBnZXQgdmFsaWQgc2l6ZSBmcm9tIHNwZWNpZmllZCBkaW1lbnNpb24gcmFuZ2UuIE1vc3QgbGlrZWx5IHRoZSByYW5nZSBjb250YWlucyAwIG9yIG5lZ2F0aXZlIHZhbHVlcyBpbiB0aGVtLicpO1xuICAgICAgfVxuICAgICAgc2l6ZSAqPSBkaW1zW2ldO1xuICAgIH1cbiAgICByZXR1cm4gc2l6ZTtcbiAgfVxuXG4gIHN0YXRpYyBjb21wdXRlU3RyaWRlcyhkaW1zOiByZWFkb25seSBudW1iZXJbXSk6IHJlYWRvbmx5IG51bWJlcltdIHtcbiAgICBjb25zdCByYW5rID0gZGltcy5sZW5ndGg7XG4gICAgaWYgKHJhbmsgPT09IDApIHtcbiAgICAgIHJldHVybiBbXTtcbiAgICB9IGVsc2UgaWYgKHJhbmsgPT09IDEpIHtcbiAgICAgIHJldHVybiBbMV07XG4gICAgfVxuICAgIGNvbnN0IHN0cmlkZXMgPSBuZXcgQXJyYXkocmFuayk7XG4gICAgc3RyaWRlc1tyYW5rIC0gMV0gPSAxO1xuICAgIHN0cmlkZXNbcmFuayAtIDJdID0gZGltc1tyYW5rIC0gMV07XG4gICAgZm9yIChsZXQgaSA9IHJhbmsgLSAzOyBpID49IDA7IC0taSkge1xuICAgICAgc3RyaWRlc1tpXSA9IHN0cmlkZXNbaSArIDFdICogZGltc1tpICsgMV07XG4gICAgfVxuICAgIHJldHVybiBzdHJpZGVzO1xuICB9XG5cbiAgc3RhdGljIHRyYW5zcG9zZShkaW1zOiByZWFkb25seSBudW1iZXJbXSk6IHJlYWRvbmx5IG51bWJlcltdIHtcbiAgICBjb25zdCBjb3B5ID0gZGltcy5zbGljZSgpO1xuICAgIHJldHVybiBjb3B5LnJldmVyc2UoKTtcbiAgfVxuXG4gIHN0YXRpYyBpbmRpY2VzVG9PZmZzZXQoaW5kaWNlczogcmVhZG9ubHkgbnVtYmVyW10sIHN0cmlkZXM6IHJlYWRvbmx5IG51bWJlcltdLCBheGlzPzogbnVtYmVyKTogbnVtYmVyIHtcbiAgICBpZiAoYXhpcyA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICBheGlzID0gaW5kaWNlcy5sZW5ndGg7XG4gICAgfVxuICAgIGxldCBvZmZzZXQgPSAwO1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgYXhpczsgKytpKSB7XG4gICAgICBvZmZzZXQgKz0gc3RyaWRlc1tpXSAqIGluZGljZXNbaV07XG4gICAgfVxuICAgIHJldHVybiBvZmZzZXQ7XG4gIH1cblxuICBzdGF0aWMgb2Zmc2V0VG9JbmRpY2VzKG9mZnNldDogbnVtYmVyLCBzdHJpZGVzOiByZWFkb25seSBudW1iZXJbXSk6IHJlYWRvbmx5IG51bWJlcltdIHtcbiAgICBjb25zdCByYW5rID0gc3RyaWRlcy5sZW5ndGg7XG4gICAgaWYgKHJhbmsgPT09IDApIHtcbiAgICAgIHJldHVybiBbXTtcbiAgICB9IGVsc2UgaWYgKHJhbmsgPT09IDEpIHtcbiAgICAgIHJldHVybiBbb2Zmc2V0ICogc3RyaWRlc1swXV07XG4gICAgfVxuICAgIGNvbnN0IGluZGljZXM6IG51bWJlcltdID0gbmV3IEFycmF5KHN0cmlkZXMubGVuZ3RoKTtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGluZGljZXMubGVuZ3RoIC0gMTsgKytpKSB7XG4gICAgICBpbmRpY2VzW2ldID0gTWF0aC5mbG9vcihvZmZzZXQgLyBzdHJpZGVzW2ldKTtcbiAgICAgIG9mZnNldCAtPSBpbmRpY2VzW2ldICogc3RyaWRlc1tpXTtcbiAgICB9XG4gICAgaW5kaWNlc1tpbmRpY2VzLmxlbmd0aCAtIDFdID0gb2Zmc2V0O1xuICAgIHJldHVybiBpbmRpY2VzO1xuICB9XG5cbiAgLyoqXG4gICAqIG5vcm1haWx6ZSBheGlzIG9mIHJhbmdlIFstciwgcikgaW50byBbMCwgcikuXG4gICAqL1xuICBzdGF0aWMgbm9ybWFsaXplQXhpcyhheGlzOiBudW1iZXIsIHRlbnNvclJhbms6IG51bWJlcik6IG51bWJlciB7XG4gICAgaWYgKGF4aXMgPCAtdGVuc29yUmFuayAmJiBheGlzID49IHRlbnNvclJhbmspIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcigndW5zdXBwb3J0ZWQgYXhpcyBmb3IgdGhpcyBvcGVyYXRpb24uJyk7XG4gICAgfVxuICAgIHJldHVybiBheGlzIDwgMCA/IGF4aXMgKyB0ZW5zb3JSYW5rIDogYXhpcztcbiAgfVxuXG4gIHN0YXRpYyBub3JtYWxpemVBeGVzKGF4ZXM6IHJlYWRvbmx5IG51bWJlcltdLCB0ZW5zb3JSYW5rOiBudW1iZXIpOiBudW1iZXJbXSB7XG4gICAgcmV0dXJuIGF4ZXMubWFwKHggPT4gdGhpcy5ub3JtYWxpemVBeGlzKHgsIHRlbnNvclJhbmspKTtcbiAgfVxuXG4gIC8vIEluY3JlbWVudCBhbiBpbmRleCBpbnRvIGEgdGVuc29yIChpbiBsZXhpY29ncmFwaGljXG4gIC8vIG9yZGVyaW5nKSwgd3JhcHBpbmcgYXJvdW5kIHRoZSBzcGVjaWZpZWQgdXBwZXJfYm91bmQuXG4gIC8qKlxuICAgKiBJbmNyZW1lbnQgYW4gaW5kZXggaW50byBhIHRlbnNvciAoaW4gbGV4aWNvZ3JhcGhpYyBvcmRlcmluZyksIHdyYXBwaW5nIGFyb3VuZCB0aGUgc3BlY2lmaWVkIHVwcGVyX2JvdW5kLlxuICAgKiBAcGFyYW0gaW5kZXggR2l2ZW4gaW5kZXggdG8gaW5jcmVtZW50IChXaWxsIGJlIG11dGF0ZWQpXG4gICAqIEBwYXJhbSBkaW1zIFRoZSBkaW1lbnNpb25zIG9mIHRoZSB0ZW5zb3IgZm9yIHdoaWNoIHRoZSBnaXZlbiBpbmRleCBjb3JyZXNwb25kcyB0b1xuICAgKiBAcGFyYW0gYXhpc1RvSW5jcmVtZW50T24gVGhlIDEtaW5kZXhlZCBheGlzIHRvIGluY3JlbWVudCBvbi4gSWYgdW5kZWZpbmVkLCBheGlzVG9JbmNyZW1lbnRPbiA9PSByYW5rXG4gICAqL1xuICBzdGF0aWMgaW5jcmVtZW50SW5kZXgoaW5kZXg6IG51bWJlcltdLCBkaW1zOiByZWFkb25seSBudW1iZXJbXSwgYXhpc1RvSW5jcmVtZW50T24/OiBudW1iZXIpIHtcbiAgICBpZiAoZGltcy5sZW5ndGggPT09IDAgfHwgaW5kZXgubGVuZ3RoID09PSAwKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0luZGV4IGluY3JlbWVudGluZyB1bnN1cHBvcnRlZCBmb3Igc2NhbGFyIFRlbnNvcicpO1xuICAgIH1cbiAgICBpZiAoYXhpc1RvSW5jcmVtZW50T24gPT09IHVuZGVmaW5lZCkge1xuICAgICAgYXhpc1RvSW5jcmVtZW50T24gPSBkaW1zLmxlbmd0aDtcbiAgICB9IGVsc2Uge1xuICAgICAgaWYgKGF4aXNUb0luY3JlbWVudE9uIDw9IDAgfHwgYXhpc1RvSW5jcmVtZW50T24gPiBkaW1zLmxlbmd0aCkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0luY29ycmVjdCBheGlzIHRvIGluY3JlbWVudCBvbicpO1xuICAgICAgfVxuICAgIH1cblxuICAgIGZvciAobGV0IGsgPSBheGlzVG9JbmNyZW1lbnRPbiAtIDE7IGsgPj0gMDsgLS1rKSB7XG4gICAgICBpbmRleFtrXSsrO1xuICAgICAgaWYgKGluZGV4W2tdIDwgZGltc1trXSkge1xuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICAgIGluZGV4W2tdID0gMDtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogUHJvZHVjZXMgYSBuZXcgZGltZW5zaW9ucyBhcnJheSBiYXNlZCBvbiB0aGUgdmFsdWVzIGluIHRoZSAnb3JpZ2luYWxEaW1lbnNpb25zJyBhbmQgJ3NoYXBlJyBhcnJheVxuICAgKiBVc2VkIGluIFJlc2hhcGVcbiAgICogQHBhcmFtIG9yaWdpbmFsRGltcyBPcmlnaW5hbCBTaGFwZSBhcnJheVxuICAgKiBAcGFyYW0gc2hhcGVIaW50cyBhcnJheSBjb250YWluaW5nIHZhbHVlcyB0byBjb21wdXRlIHRoZSBuZXcgZGltZW5zaW9uc1xuICAgKiBGb3IgZXhhbXBsZTpcbiAgICogb3JpZ2luYWxEaW1zID0gWzIsMl0gYW5kIHNoYXBlSGludHMgPSBbMCwtMV0gd2lsbCByZXR1cm4gWzIsMl1cbiAgICogb3JpZ2luYWxEaW1zID0gWzIsMl0gYW5kIHNoYXBlSGludHMgPSBbNF0gd2lsbCByZXR1cm4gWzRdXG4gICAqIG9yaWdpbmFsRGltcyA9IFsyLDJdIGFuZCBzaGFwZUhpbnRzID0gWzVdIHdpbGwgdGhyb3cgYW4gZXhjZXB0aW9uXG4gICAqIGh0dHBzOi8vZ2l0aHViLmNvbS9vbm54L29ubngvYmxvYi9tYWluL2RvY3MvT3BlcmF0b3JzLm1kI1Jlc2hhcGVcbiAgICovXG5cbiAgc3RhdGljIGNhbGN1bGF0ZVJlc2hhcGVkRGltcyhvcmlnaW5hbERpbXM6IHJlYWRvbmx5IG51bWJlcltdLCBzaGFwZUhpbnRzOiBBcnJheUxpa2U8bnVtYmVyPik6IG51bWJlcltdIHtcbiAgICAvLyByZXNoYXBlIHRvIGEgU2NhbGFyIFRlbnNvclxuICAgIGlmIChzaGFwZUhpbnRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgaWYgKG9yaWdpbmFsRGltcy5sZW5ndGggPT09IDAgfHwgU2hhcGVVdGlsLnNpemUob3JpZ2luYWxEaW1zKSA9PT0gMSkge1xuICAgICAgICByZXR1cm4gW107XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ2Nhbm5vdCByZXNoYXBlIHRvIGEgc2NhbGFyIFRlbnNvcicpO1xuICAgICAgfVxuICAgIH1cblxuICAgIGNvbnN0IG5EaW1zID0gc2hhcGVIaW50cy5sZW5ndGg7XG4gICAgY29uc3QgcmVzaGFwZWREaW1zID0gbmV3IEFycmF5PG51bWJlcj4obkRpbXMpO1xuICAgIGxldCB1bmtub3duRGltZW5zaW9uID0gLTE7XG4gICAgbGV0IG5ld1RlbnNvclNpemUgPSAxO1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbkRpbXM7IGkrKykge1xuICAgICAgaWYgKHNoYXBlSGludHNbaV0gPCAtMSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ2EgZGltZW5zaW9uIGluIHNoYXBlIGhpbnRzIGNhbm5vdCBiZSBsZXNzIHRoYW4gLTEnKTtcbiAgICAgIH1cbiAgICAgIGlmIChzaGFwZUhpbnRzW2ldID09PSAtMSkge1xuICAgICAgICBpZiAodW5rbm93bkRpbWVuc2lvbiAhPT0gLTEpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ2F0IG1vc3Qgb25lIGRpbWVuc2lvbiBpbiBzaGFwZSBoaW50cyBjYW4gYmUgLTEnKTtcbiAgICAgICAgfVxuICAgICAgICB1bmtub3duRGltZW5zaW9uID0gaTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGlmIChzaGFwZUhpbnRzW2ldID09PSAwKSB7XG4gICAgICAgICAgaWYgKGkgPj0gb3JpZ2luYWxEaW1zLmxlbmd0aCkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCd0aGUgZGltZW5zaW9uIHdpdGggdmFsdWUgemVybyBleGNlZWRzIHRoZSBkaW1lbnNpb24gc2l6ZSBvZiB0aGUgaW5wdXQgdGVuc29yJyk7XG4gICAgICAgICAgfVxuICAgICAgICAgIHJlc2hhcGVkRGltc1tpXSA9IG9yaWdpbmFsRGltc1tpXTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICByZXNoYXBlZERpbXNbaV0gPSBzaGFwZUhpbnRzW2ldO1xuICAgICAgICB9XG4gICAgICAgIG5ld1RlbnNvclNpemUgKj0gcmVzaGFwZWREaW1zW2ldO1xuICAgICAgfVxuICAgIH1cblxuICAgIGNvbnN0IG9sZFRlbnNvclNpemUgPSBTaGFwZVV0aWwuc2l6ZShvcmlnaW5hbERpbXMpO1xuICAgIGlmICh1bmtub3duRGltZW5zaW9uICE9PSAtMSkge1xuICAgICAgaWYgKG9sZFRlbnNvclNpemUgJSBuZXdUZW5zb3JTaXplICE9PSAwKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgdGhlIGlucHV0IHRlbnNvciBjYW5ub3QgYmUgcmVzaGFwZWQgdG8gdGhlIHJlcXVlc3RlZCBzaGFwZS4gSW5wdXQgc2hhcGU6IFske1xuICAgICAgICAgICAgb3JpZ2luYWxEaW1zfV0gT3V0cHV0IHNoYXBlOiBbJHtzaGFwZUhpbnRzfV1gKTtcbiAgICAgIH1cbiAgICAgIHJlc2hhcGVkRGltc1t1bmtub3duRGltZW5zaW9uXSA9IG9sZFRlbnNvclNpemUgLyBuZXdUZW5zb3JTaXplO1xuICAgIH1cbiAgICAvLyB2YWxpZGF0ZSBzaXplcyBmcm9tIG9yaWdpbmFsRGltcyBhbmQgcmVzaGFwZWREaW1zIG1hdGNoXG4gICAgZWxzZSB7XG4gICAgICBpZiAobmV3VGVuc29yU2l6ZSAhPT0gb2xkVGVuc29yU2l6ZSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ3Jlc2hhcGVkRGltcyBhbmQgb3JpZ2luYWxEaW1zIGRvblxcJ3QgaGF2ZSBtYXRjaGluZyBzaXplcycpO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gcmVzaGFwZWREaW1zO1xuICB9XG5cbiAgLyoqXG4gICAqIFNvcnRzIGEgZ2l2ZW4gYXJyYXkgYmFzZWQgb24gdGhlIGluZGljZXMgaW4gdGhlIFBlcm0gYXJyYXlcbiAgICogVXNlZCBpbiBUcmFuc3Bvc2VcbiAgICogQHBhcmFtIGEgQXJyYXkgdG8gYmUgc29ydGVkIHN1Y2ggYXMgZGltcyBvciBzdHJpZGVzXG4gICAqIEBwYXJhbSBwZXJtIFBlcm0gZ2l2ZW47IGlmIG51bGwgYSB3aWxsIGJlIHJldmVyc2VkXG4gICAqL1xuICBzdGF0aWMgc29ydEJhc2VkT25QZXJtKGE6IHJlYWRvbmx5IG51bWJlcltdLCBwZXJtPzogcmVhZG9ubHkgbnVtYmVyW10pOiByZWFkb25seSBudW1iZXJbXSB7XG4gICAgaWYgKHBlcm0pIHtcbiAgICAgIHJldHVybiBwZXJtLm1hcCgodikgPT4gYVt2XSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBhLnNsaWNlKCkucmV2ZXJzZSgpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBQYWRzIGEgZ2l2ZW4gc2hhcGUgYWNjb3JkaW5nIHRvIHRoZSBwYWRkaW5nIHZhbHVlc1xuICAgKiBAcGFyYW0gZGltcyBzaGFwZSBvZiB0aGUgVGVuc29yIHRvIGJlIHBhZGRlZFxuICAgKiBAcGFyYW0gcGFkIHBhZCB2YWx1ZXNcbiAgICovXG4gIHN0YXRpYyBwYWRTaGFwZShkaW1zOiByZWFkb25seSBudW1iZXJbXSwgcGFkOiByZWFkb25seSBudW1iZXJbXSk6IHJlYWRvbmx5IG51bWJlcltdIHtcbiAgICBjb25zdCByYW5rID0gZGltcy5sZW5ndGg7XG4gICAgcmV0dXJuIGRpbXMubWFwKCh2LCBpKSA9PiB2ICsgcGFkW2ldICsgcGFkW2kgKyByYW5rXSk7XG4gIH1cblxuICAvKipcbiAgICogRGV0ZXJtaW5lcyBpZiB0aGUgdHdvIHNoYXBlcyBhcmUgaWRlbnRpY2FsXG4gICAqIEBwYXJhbSBzaGFwZTFcbiAgICogQHBhcmFtIHNoYXBlMlxuICAgKi9cbiAgc3RhdGljIGFyZUVxdWFsKHNoYXBlMTogcmVhZG9ubHkgbnVtYmVyW10sIHNoYXBlMjogcmVhZG9ubHkgbnVtYmVyW10pOiBib29sZWFuIHtcbiAgICBpZiAoc2hhcGUxLmxlbmd0aCAhPT0gc2hhcGUyLmxlbmd0aCkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICByZXR1cm4gc2hhcGUxLmV2ZXJ5KCh2LCBpKSA9PiB2ID09PSBzaGFwZTJbaV0pO1xuICB9XG5cbiAgLyoqXG4gICAqIFZhbGlkYXRlcyBpZiB0aGUgZ2l2ZW4gYGRpbXNgIG9yIGBzaGFwZWAgaXMgdmFsaWQgaW4gT05OWC5qcyBjb250ZXh0IGFuZCByZXR1cm5zIGRhdGEgc2l6ZVxuICAgKiBAcGFyYW0gZGltcyAtIGlucHV0IGBkaW1zYCB0aGF0IG5lZWRzIHRvIGJlIGNoZWNrZWRcbiAgICovXG4gIHN0YXRpYyB2YWxpZGF0ZURpbXNBbmRDYWxjU2l6ZShkaW1zOiByZWFkb25seSBudW1iZXJbXSk6IG51bWJlciB7XG4gICAgaWYgKGRpbXMubGVuZ3RoID4gNikge1xuICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignT25seSByYW5rIDAgdG8gNiBpcyBzdXBwb3J0ZWQgZm9yIHRlbnNvciBzaGFwZS4nKTtcbiAgICB9XG4gICAgbGV0IHNpemUgPSAxO1xuICAgIGZvciAoY29uc3QgbiBvZiBkaW1zKSB7XG4gICAgICBpZiAoIU51bWJlci5pc0ludGVnZXIobikpIHtcbiAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihgSW52YWxpZCBzaGFwZTogJHtufSBpcyBub3QgYW4gaW50ZWdlcmApO1xuICAgICAgfVxuICAgICAgaWYgKG4gPCAwIHx8IG4gPiAyMTQ3NDgzNjQ3KSB7XG4gICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoYEludmFsaWQgc2hhcGU6IGxlbmd0aCAke259IGlzIG5vdCBhbGxvd2VkYCk7XG4gICAgICB9XG4gICAgICBzaXplICo9IG47XG4gICAgfVxuICAgIHJldHVybiBzaXplO1xuICB9XG5cbiAgLyoqXG4gICAqIERldGVybWluZXMgdGhlIHNoYXBlIG9mIG91dHB1dCB0ZW5zb3IgeSA9IGZsYXR0ZW4oeCwgYXhpcylcbiAgICogQHBhcmFtIGRpbXMgLSBzaGFwZSBvZiBpbnB1dCB0ZW5zb3JcbiAgICogQHBhcmFtIGF4aXMgLSBmbGF0dGVuIGF4aXMsIGluIHRoZSByYW5nZSBbLXIsIHJdXG4gICAqL1xuICBzdGF0aWMgZmxhdHRlblNoYXBlKGRpbXM6IHJlYWRvbmx5IG51bWJlcltdLCBheGlzOiBudW1iZXIpOiByZWFkb25seSBudW1iZXJbXSB7XG4gICAgaWYgKGF4aXMgPCAwKSB7XG4gICAgICBheGlzICs9IGRpbXMubGVuZ3RoO1xuICAgIH1cbiAgICBjb25zdCB0b3RhbCA9IGRpbXMucmVkdWNlKCh4LCB5KSA9PiB4ICogeSwgMSk7XG4gICAgY29uc3QgcmlnaHQgPSBkaW1zLnNsaWNlKGF4aXMpLnJlZHVjZSgoeCwgeSkgPT4geCAqIHksIDEpO1xuICAgIGNvbnN0IG91dHB1dERpbXMgPSBbdG90YWwgLyByaWdodCwgcmlnaHRdO1xuXG4gICAgcmV0dXJuIG91dHB1dERpbXM7XG4gIH1cblxuICAvKipcbiAgICogRGV0ZXJtaW5lcyB0aGUgc2hhcGUgb2Ygb3V0cHV0IHRlbnNvciB5ID0gc3F1ZWV6ZSh4LCBheGVzKVxuICAgKiBAcGFyYW0gZGltcyAtIHNoYXBlIG9mIGlucHV0IHRlbnNvclxuICAgKiBAcGFyYW0gYXhlcyAtIHNxdWVlemUgYXhlc1xuICAgKi9cbiAgc3RhdGljIHNxdWVlemVTaGFwZShkaW1zOiByZWFkb25seSBudW1iZXJbXSwgYXhlczogcmVhZG9ubHkgbnVtYmVyW10pOiByZWFkb25seSBudW1iZXJbXSB7XG4gICAgY29uc3Qgb3V0cHV0RGltcyA9IG5ldyBBcnJheTxudW1iZXI+KCk7XG5cbiAgICAvLyBzYW5pdHkgY2hlY2tcbiAgICBheGVzID0gU2hhcGVVdGlsLm5vcm1hbGl6ZUF4ZXMoYXhlcywgZGltcy5sZW5ndGgpO1xuXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBkaW1zLmxlbmd0aDsgaSsrKSB7XG4gICAgICBjb25zdCBpblNxdWVlemVMaXN0ID0gYXhlcy5pbmRleE9mKGkpID49IDA7XG4gICAgICBpZiAoaW5TcXVlZXplTGlzdCAmJiBkaW1zW2ldICE9PSAxKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignc3F1ZWV6ZSBhbiBheGlzIG9mIHNpemUgZGlmZmVyZW50IHRoYW4gMScpO1xuICAgICAgfVxuXG4gICAgICBpZiAoKGF4ZXMubGVuZ3RoID09PSAwICYmIGRpbXNbaV0gPiAxKSB8fCAoYXhlcy5sZW5ndGggPiAwICYmICFpblNxdWVlemVMaXN0KSkge1xuICAgICAgICBvdXRwdXREaW1zLnB1c2goZGltc1tpXSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIG91dHB1dERpbXM7XG4gIH1cblxuICAvKipcbiAgICogRGV0ZXJtaW5lcyB0aGUgc2hhcGUgb2Ygb3V0cHV0IHRlbnNvciB5ID0gdW5zcXVlZXplKHgsIGF4ZXMpXG4gICAqIEBwYXJhbSBkaW1zIC0gc2hhcGUgb2YgaW5wdXQgdGVuc29yXG4gICAqIEBwYXJhbSBheGVzIC0gdW5zcXVlZXplIGF4ZXNcbiAgICovXG4gIHN0YXRpYyB1bnNxdWVlemVTaGFwZShkaW1zOiByZWFkb25seSBudW1iZXJbXSwgYXhlczogcmVhZG9ubHkgbnVtYmVyW10pOiByZWFkb25seSBudW1iZXJbXSB7XG4gICAgY29uc3Qgb3V0cHV0RGltcyA9IG5ldyBBcnJheTxudW1iZXI+KGRpbXMubGVuZ3RoICsgYXhlcy5sZW5ndGgpO1xuXG4gICAgLy8gaW5pdGlhbGl6ZSB0aGUgYXJyYXkgZWxlbWVudHMgdG8gMFxuICAgIG91dHB1dERpbXMuZmlsbCgwKTtcblxuICAgIC8vIHNldCBhbGwgYXhlcyBpbmRpY2VzIHRvIDEgaW4gb3V0cHV0RGltcyBhbmQgY2hlY2sgZm9yIGR1cGxpY2F0ZXNcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGF4ZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgIGNvbnN0IGF4aXMgPSBTaGFwZVV0aWwubm9ybWFsaXplQXhpcyhheGVzW2ldLCBvdXRwdXREaW1zLmxlbmd0aCk7XG4gICAgICBpZiAoYXhpcyA+PSBvdXRwdXREaW1zLmxlbmd0aCkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1xcJ2F4ZXNcXCcgaGFzIGFuIG91dCBvZiByYW5nZSBheGlzJyk7XG4gICAgICB9XG4gICAgICBpZiAob3V0cHV0RGltc1theGlzXSAhPT0gMCkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1xcJ2F4ZXNcXCcgaGFzIGEgZHVwbGljYXRlIGF4aXMnKTtcbiAgICAgIH1cblxuICAgICAgb3V0cHV0RGltc1theGlzXSA9IDE7XG4gICAgfVxuXG4gICAgLy8gZmlsbCBpbiB0aGUgemVybyBlbnRyaWVzIG9mIG91dHB1dERpbXMgd2l0aCB0aGUgaW5wdXQgdGVuc29yJ3Mgc2hhcGVcbiAgICBsZXQgaW5wdXREaW1zSXRlcmF0b3IgPSAwO1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgb3V0cHV0RGltcy5sZW5ndGg7IGkrKykge1xuICAgICAgaWYgKG91dHB1dERpbXNbaV0gPT09IDApIHtcbiAgICAgICAgb3V0cHV0RGltc1tpXSA9IGRpbXNbaW5wdXREaW1zSXRlcmF0b3IrK107XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gc2FuaXR5IGNoZWNrIGFzc2VydGlvbi4gJ2lucHV0RGltc0l0ZXJhdG9yJ1xuICAgIC8vIHNob3VsZCBiZSBlcXVhbCB0byB0aGUgbGVuZ3RoIG9mICdkaW1zJ1xuICAgIGlmIChpbnB1dERpbXNJdGVyYXRvciAhPT0gZGltcy5sZW5ndGgpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcigndGhlIHVuc3F1ZWV6ZWQgZGltZW5zaW9uIGNvdWxkIG5vdCBiZSBlc3RhYmxpc2hlZCcpO1xuICAgIH1cblxuICAgIHJldHVybiBvdXRwdXREaW1zO1xuICB9XG59XG5cbi8vIGJ1bmNoIG9mIGhlbHBlciBtZXRob2RzIHRoYXQgZG8gYSB2YXJpZXR5IG9mIG1hdGggb3BlcmF0aW9uc1xuZXhwb3J0IGNsYXNzIE1hdGhVdGlsIHtcbiAgLy8geSA9ICh4KngpICsgeVxuICBzdGF0aWMgc3FyKFxuICAgICAgdGFyZ2V0OiBudW1iZXJbXXxUZW5zb3IuTnVtYmVyVHlwZSwgc291cmNlOiBudW1iZXJbXXxUZW5zb3IuTnVtYmVyVHlwZSwgdGFyZ2V0SW5kZXg6IG51bWJlciwgc291cmNlSW5kZXg6IG51bWJlcixcbiAgICAgIGJsb2NrU2l6ZTogbnVtYmVyKSB7XG4gICAgaWYgKHNvdXJjZUluZGV4IDwgMCB8fCBzb3VyY2VJbmRleCA+PSBzb3VyY2UubGVuZ3RoKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ3NvdXJjZUluZGV4IG91dCBvZiBib3VuZHMnKTtcbiAgICB9XG4gICAgaWYgKHRhcmdldEluZGV4IDwgMCB8fCB0YXJnZXRJbmRleCA+PSB0YXJnZXQubGVuZ3RoKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ3RhcmdldEluZGV4IG91dCBvZiBib3VuZHMnKTtcbiAgICB9XG4gICAgaWYgKHNvdXJjZUluZGV4ICsgYmxvY2tTaXplID4gc291cmNlLmxlbmd0aCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdzb3VyY2UgaW5kaWNlcyB0byBiZSBjb3BpZWQgYXJlIG91dHNpZGUgYm91bmRzJyk7XG4gICAgfVxuICAgIGlmICh0YXJnZXRJbmRleCArIGJsb2NrU2l6ZSA+IHRhcmdldC5sZW5ndGgpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcigndGFyZ2V0IGFycmF5IGlzIHRvbyBzbWFsbCB0byBob2xkIHJlc3VsdCcpO1xuICAgIH1cblxuICAgIGZvciAobGV0IG9mZnNldCA9IDA7IG9mZnNldCA8IGJsb2NrU2l6ZTsgb2Zmc2V0KyspIHtcbiAgICAgIHRhcmdldFt0YXJnZXRJbmRleCArIG9mZnNldF0gKz0gTWF0aC5wb3coc291cmNlW3NvdXJjZUluZGV4ICsgb2Zmc2V0XSwgMik7XG4gICAgfVxuICB9XG5cbiAgLy8geSA9IGF4ICsgeVxuICBzdGF0aWMgYXhweShcbiAgICAgIHRhcmdldDogbnVtYmVyW118VGVuc29yLk51bWJlclR5cGUsIHNvdXJjZTogbnVtYmVyW118VGVuc29yLk51bWJlclR5cGUsIHRhcmdldEluZGV4OiBudW1iZXIsIHNvdXJjZUluZGV4OiBudW1iZXIsXG4gICAgICBibG9ja1NpemU6IG51bWJlciwgYWxwaGE6IG51bWJlcikge1xuICAgIGlmIChzb3VyY2VJbmRleCA8IDAgfHwgc291cmNlSW5kZXggPj0gc291cmNlLmxlbmd0aCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdzb3VyY2VJbmRleCBvdXQgb2YgYm91bmRzJyk7XG4gICAgfVxuICAgIGlmICh0YXJnZXRJbmRleCA8IDAgfHwgdGFyZ2V0SW5kZXggPj0gdGFyZ2V0Lmxlbmd0aCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCd0YXJnZXRJbmRleCBvdXQgb2YgYm91bmRzJyk7XG4gICAgfVxuICAgIGlmIChzb3VyY2VJbmRleCArIGJsb2NrU2l6ZSA+IHNvdXJjZS5sZW5ndGgpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignc291cmNlIGluZGljZXMgdG8gYmUgY29waWVkIGFyZSBvdXRzaWRlIGJvdW5kcycpO1xuICAgIH1cbiAgICBpZiAodGFyZ2V0SW5kZXggKyBibG9ja1NpemUgPiB0YXJnZXQubGVuZ3RoKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ3RhcmdldCBhcnJheSBpcyB0b28gc21hbGwgdG8gaG9sZCByZXN1bHQnKTtcbiAgICB9XG5cbiAgICBmb3IgKGxldCBvZmZzZXQgPSAwOyBvZmZzZXQgPCBibG9ja1NpemU7IG9mZnNldCsrKSB7XG4gICAgICB0YXJnZXRbdGFyZ2V0SW5kZXggKyBvZmZzZXRdICs9IChhbHBoYSAqIHNvdXJjZVtzb3VyY2VJbmRleCArIG9mZnNldF0pO1xuICAgIH1cbiAgfVxuXG4gIC8vIHkgPSBwb3coeCwgYilcbiAgc3RhdGljIHBvd3goXG4gICAgICB0YXJnZXQ6IG51bWJlcltdfFRlbnNvci5OdW1iZXJUeXBlLCBzb3VyY2U6IG51bWJlcltdfFRlbnNvci5OdW1iZXJUeXBlLCB0YXJnZXRJbmRleDogbnVtYmVyLCBzb3VyY2VJbmRleDogbnVtYmVyLFxuICAgICAgYmxvY2tTaXplOiBudW1iZXIsIGI6IG51bWJlcikge1xuICAgIGlmIChzb3VyY2VJbmRleCA8IDAgfHwgc291cmNlSW5kZXggPj0gc291cmNlLmxlbmd0aCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdzb3VyY2VJbmRleCBvdXQgb2YgYm91bmRzJyk7XG4gICAgfVxuICAgIGlmICh0YXJnZXRJbmRleCA8IDAgfHwgdGFyZ2V0SW5kZXggPj0gdGFyZ2V0Lmxlbmd0aCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCd0YXJnZXRJbmRleCBvdXQgb2YgYm91bmRzJyk7XG4gICAgfVxuICAgIGlmIChzb3VyY2VJbmRleCArIGJsb2NrU2l6ZSA+IHNvdXJjZS5sZW5ndGgpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignc291cmNlIGluZGljZXMgdG8gYmUgY29waWVkIGFyZSBvdXRzaWRlIGJvdW5kcycpO1xuICAgIH1cbiAgICBpZiAodGFyZ2V0SW5kZXggKyBibG9ja1NpemUgPiB0YXJnZXQubGVuZ3RoKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ3RhcmdldCBhcnJheSBpcyB0b28gc21hbGwgdG8gaG9sZCByZXN1bHQnKTtcbiAgICB9XG5cbiAgICBmb3IgKGxldCBvZmZzZXQgPSAwOyBvZmZzZXQgPCBibG9ja1NpemU7IG9mZnNldCsrKSB7XG4gICAgICB0YXJnZXRbdGFyZ2V0SW5kZXggKyBvZmZzZXRdID0gTWF0aC5wb3coc291cmNlW3NvdXJjZUluZGV4ICsgb2Zmc2V0XSwgYik7XG4gICAgfVxuICB9XG5cbiAgLy8geSA9IHggKiB5XG4gIHN0YXRpYyBtdWwoXG4gICAgICB0YXJnZXQ6IG51bWJlcltdfFRlbnNvci5OdW1iZXJUeXBlLCBzb3VyY2U6IG51bWJlcltdfFRlbnNvci5OdW1iZXJUeXBlLCB0YXJnZXRJbmRleDogbnVtYmVyLCBzb3VyY2VJbmRleDogbnVtYmVyLFxuICAgICAgYmxvY2tTaXplOiBudW1iZXIpIHtcbiAgICBpZiAoc291cmNlSW5kZXggPCAwIHx8IHNvdXJjZUluZGV4ID49IHNvdXJjZS5sZW5ndGgpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignc291cmNlSW5kZXggb3V0IG9mIGJvdW5kcycpO1xuICAgIH1cbiAgICBpZiAodGFyZ2V0SW5kZXggPCAwIHx8IHRhcmdldEluZGV4ID49IHRhcmdldC5sZW5ndGgpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcigndGFyZ2V0SW5kZXggb3V0IG9mIGJvdW5kcycpO1xuICAgIH1cbiAgICBpZiAoc291cmNlSW5kZXggKyBibG9ja1NpemUgPiBzb3VyY2UubGVuZ3RoKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ3NvdXJjZSBpbmRpY2VzIHRvIGJlIGNvcGllZCBhcmUgb3V0c2lkZSBib3VuZHMnKTtcbiAgICB9XG4gICAgaWYgKHRhcmdldEluZGV4ICsgYmxvY2tTaXplID4gdGFyZ2V0Lmxlbmd0aCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCd0YXJnZXQgYXJyYXkgaXMgdG9vIHNtYWxsIHRvIGhvbGQgcmVzdWx0Jyk7XG4gICAgfVxuXG4gICAgZm9yIChsZXQgb2Zmc2V0ID0gMDsgb2Zmc2V0IDwgYmxvY2tTaXplOyBvZmZzZXQrKykge1xuICAgICAgdGFyZ2V0W3RhcmdldEluZGV4ICsgb2Zmc2V0XSA9IChzb3VyY2Vbc291cmNlSW5kZXggKyBvZmZzZXRdICogdGFyZ2V0W3RhcmdldEluZGV4ICsgb2Zmc2V0XSk7XG4gICAgfVxuICB9XG59XG5cbmV4cG9ydCBjbGFzcyBTcGxpdFV0aWwge1xuICAvKipcbiAgICogQ2FsY3VsYXRlcyBuZXcgU2hhcGVzIGZyb20gZXhpc3Rpbmcgb25lIGFuZCB0aGUgc3BsaXRzIGdpdmVuIGFsb25nIHRoZSBheGlzIHByb3ZpZGVzXG4gICAqIEBwYXJhbSBkaW1zIFNoYXBlIG9mIHRoZSBUZW5zb3IgdG8gYmUgc3BsaXR0ZWQgaW50byB0d28gb3IgbW9yZSBTaGFwZXNcbiAgICogQHBhcmFtIGF4aXMgVGhlIGRpbWVuc2lvbiBhbG9uZyB3aGljaCB0aGUgVGVuc29yIHdpbGwgYmUgc3BsaXRcbiAgICogQHBhcmFtIHNwbGl0cyBPZmZzZXRzIGZvciB0aGUgc3RhcnQgb2YgZWFjaCBzcGxpdFxuICAgKi9cbiAgc3RhdGljIHNwbGl0U2hhcGUoZGltczogcmVhZG9ubHkgbnVtYmVyW10sIGF4aXM6IG51bWJlciwgc3BsaXQ6IG51bWJlcltdLCBudW1PdXRwdXRzPzogbnVtYmVyKTpcbiAgICAgIFtudW1iZXJbXVtdLCBudW1iZXJbXV0ge1xuICAgIGlmIChzcGxpdC5sZW5ndGggPT09IDApIHtcbiAgICAgIGlmICghbnVtT3V0cHV0cykge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ25lZWQgdG8ga25vdyBudW1iZXIgb2Ygb3V0cHV0cyB3aGVuIHRoZSBcXCdzcGxpdFxcJyBhdHRyaWJ1dGUgaXMgbm90IHNwZWNpZmllZCcpO1xuICAgICAgfVxuICAgICAgU3BsaXRVdGlsLmRldGVybWluZVNwbGl0KGRpbXNbYXhpc10sIG51bU91dHB1dHMsIHNwbGl0KTtcbiAgICB9XG5cbiAgICBjb25zdCBzaGFwZXM6IG51bWJlcltdW10gPSBbXTtcbiAgICBjb25zdCBvZmZzZXRzID0gWzBdO1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgc3BsaXQubGVuZ3RoOyArK2kpIHtcbiAgICAgIGlmIChpICE9PSAwKSB7XG4gICAgICAgIG9mZnNldHMucHVzaChvZmZzZXRzW2kgLSAxXSArIHNwbGl0W2kgLSAxXSk7XG4gICAgICB9XG4gICAgICBjb25zdCBzaGFwZSA9IGRpbXMuc2xpY2UoKTtcbiAgICAgIHNoYXBlW2F4aXNdID0gc3BsaXRbaV07XG4gICAgICBzaGFwZXMucHVzaChzaGFwZSk7XG4gICAgfVxuICAgIHJldHVybiBbc2hhcGVzLCBvZmZzZXRzXTtcbiAgfVxuXG4gIHN0YXRpYyBkZXRlcm1pbmVTcGxpdChudW1FbGVtZW50c0Fsb25nQXhpczogbnVtYmVyLCBudW1PdXRwdXRzOiBudW1iZXIsIHNwbGl0OiBudW1iZXJbXSkge1xuICAgIC8vIElmICdzcGxpdCcgaXMgbm90IHNwZWNpZmllZCBieSB0aGUgdXNlciwgd2UgbmVlZCB0byBwYXJ0aXRpb24gdGhlIG51bWJlciBvZiBlbGVtZW50cyBlcXVhbGx5IGFtb25nIHRoZSBvdXRwdXRzXG4gICAgaWYgKG51bUVsZW1lbnRzQWxvbmdBeGlzICUgbnVtT3V0cHV0cyAhPT0gMCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdjYW5ub3Qgc3BsaXQgdGVuc29yIHRvIGVxdWFsIHNpemVkIHBhcnRzJyk7XG4gICAgfVxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbnVtT3V0cHV0czsgKytpKSB7XG4gICAgICBzcGxpdC5wdXNoKG51bUVsZW1lbnRzQWxvbmdBeGlzIC8gbnVtT3V0cHV0cyk7XG4gICAgfVxuICB9XG59XG5cbmV4cG9ydCBjbGFzcyBSZWR1Y2VVdGlsIHtcbiAgLyoqXG4gICAqIFBlcmZvcm0gcmVkdWNlIG9wZXJhdGlvbnMgb24gdGhlIHNwZWNpZmljIG9wZXJhdG9yXG4gICAqIEBwYXJhbSBhIElucHV0IHRlbnNvciBkYXRhXG4gICAqIEBwYXJhbSBheGVzIFRoZSBkaW1lbnNpb25zIGFsb25nIHdoaWNoIHRoZSBUZW5zb3Igd2lsbCBiZSByZWR1Y2VkXG4gICAqIEBwYXJhbSBrZWVwZGltcyBJZiBzZXQgdG8gdHJ1ZSwgdGhlIGF4ZXMgd2hpY2ggYXJlIHJlZHVjZWQgYXJlIGxlZnQgaW4gdGhlXG4gICAqICAgIHJlc3VsdCBhcyBkaW1lbnNpb25zIHdpdGggc2l6ZSBvbmUuXG4gICAqIEBwYXJhbSBvcDEgVGhlIG9wZXJhdGlvbiB0byBiZSBwZXJmb3JtZWQgb24gZWFjaCBlbGVtZW50IGluIHRoZSB0ZW5zb3JcbiAgICogQHBhcmFtIG9wMiBUaGUgb3BlcmF0aW9uIHRvIGJlIHBlcmZvcm1lZCBiZXR3ZWVuIGVsZW1lbnRzIGluIHRoZSB0ZW5zb3JcbiAgICovXG4gIHN0YXRpYyBjYWxjUmVkdWNlKFxuICAgICAgYTogVGVuc29yLCBheGVzOiBudW1iZXJbXSwga2VlcGRpbXM6IGJvb2xlYW4sIG9wMTogKGI6IG51bWJlcikgPT4gbnVtYmVyLFxuICAgICAgb3AyOiAoYTogbnVtYmVyLCBiOiBudW1iZXIpID0+IG51bWJlcik6IFRlbnNvciB7XG4gICAgY29uc3QgZGltcyA9IGEuZGltcy5zbGljZSgwKTtcbiAgICAvLyBpZiBheGVzIGlzIG5vdCBzZXQsIHBlcmZvcm0gcmVkdWNlIG9uIGFsbCBheGVzXG4gICAgaWYgKGF4ZXMubGVuZ3RoID09PSAwKSB7XG4gICAgICBkaW1zLmZvckVhY2goKGQsIGluZCkgPT4gYXhlcy5wdXNoKGluZCkpO1xuICAgIH1cbiAgICAvLyBnZXQgYSB0ZW1wb3JhcnkgYnJvYWRjYXN0YWJsZSBvdXRwdXQgc2hhcGVcbiAgICBjb25zdCBvdXRwdXREaW1zID0gUmVkdWNlVXRpbC5jYWxjUmVkdWNlU2hhcGUoZGltcywgYXhlcywgdHJ1ZSk7XG5cbiAgICAvLyBsb29wIHRocm91Z2ggdGhlIG91dHB1dCBhbmQgY2FsY3VsYXRlIHJlc3VsdCBvbmUgYnkgb25lXG4gICAgY29uc3Qgc2l6ZSA9IFNoYXBlVXRpbC5zaXplKG91dHB1dERpbXMpO1xuICAgIGNvbnN0IHkgPSBuZXcgVGVuc29yKG91dHB1dERpbXMsIGEudHlwZSk7XG4gICAgY29uc3Qgc3RyaWRlcyA9IFNoYXBlVXRpbC5jb21wdXRlU3RyaWRlcyhvdXRwdXREaW1zKTtcbiAgICBjb25zdCBpbnB1dFN0cmlkZXMgPSBTaGFwZVV0aWwuY29tcHV0ZVN0cmlkZXMoZGltcyk7XG4gICAgY29uc3QgaW5kaWNlc1kgPSBuZXcgQXJyYXkoZGltcy5sZW5ndGgpO1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgc2l6ZTsgaSsrKSB7XG4gICAgICBjb25zdCBpbmRpY2VzID0gU2hhcGVVdGlsLm9mZnNldFRvSW5kaWNlcyhpLCBzdHJpZGVzKTtcbiAgICAgIC8vIG1hcCBpbmRleFxuICAgICAgQnJvYWRjYXN0VXRpbC5maWxsSW5kZXgoaW5kaWNlcywgZGltcywgaW5kaWNlc1kpO1xuICAgICAgeS5zZXQoXG4gICAgICAgICAgaW5kaWNlcyxcbiAgICAgICAgICBSZWR1Y2VVdGlsLmNhbGNSZWR1Y2VCeUF4aXMoXG4gICAgICAgICAgICAgIGEubnVtYmVyRGF0YSwgYXhlcywgZGltcywgMCwgU2hhcGVVdGlsLmluZGljZXNUb09mZnNldChpbmRpY2VzWSwgaW5wdXRTdHJpZGVzKSwgb3AxLCBvcDIpKTtcbiAgICB9XG5cbiAgICBpZiAoa2VlcGRpbXMpIHtcbiAgICAgIHJldHVybiB5O1xuICAgIH0gZWxzZSB7XG4gICAgICAvLyBrZWVwZGltcyA9PSAwLCBjYWxjdWxhdGUgdGhlIGV4cGVjdGVkIHNoYXBlXG4gICAgICByZXR1cm4gbmV3IFRlbnNvcihcbiAgICAgICAgICBSZWR1Y2VVdGlsLmNhbGNSZWR1Y2VTaGFwZShkaW1zLCBheGVzLCBrZWVwZGltcyksIHkudHlwZSwgdW5kZWZpbmVkLCB1bmRlZmluZWQsIHkuZGF0YSwgeS5kYXRhSWQpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBQZXJmb3JtIHJlZHVjZSBvcGVyYXRpb25zIG9uIHRoZSBzcGVjaWZpYyBvcGVyYXRvciBvbiBzcGVjaWZpYyBheGVzXG4gICAqIEBwYXJhbSBhIElucHV0IHRlbnNvciBkYXRhXG4gICAqIEBwYXJhbSBheGVzIFRoZSBkaW1lbnNpb25zIGFsb25nIHdoaWNoIHRoZSBUZW5zb3Igd2lsbCBiZSByZWR1Y2VkXG4gICAqIEBwYXJhbSBkaW1zIFRoZSBpbnB1dCBkaW1lbnNpb24uXG4gICAqIEBwYXJhbSBjdXJBeGlzSW5kIEluZGV4IGluIGF4ZXMgc3BlY2lmeWluZyB0aGUgY3VycmVudCBkaW1lbnNpb24gYWxvbmdcbiAgICogICAgICB3aGljaCB0aGUgdGVuc29yIHdpbGwgYmUgcmVkdWNlZFxuICAgKiBAcGFyYW0gcG9zIFRoZSBjdXJyZW50IGluZGV4IG9mIGVsZW1lbnQgdG8gcGVyZm9ybSBvcGVyYXRpb25cbiAgICogQHBhcmFtIG9wMSBUaGUgb3BlcmF0aW9uIHRvIGJlIHBlcmZvcm1lZCBvbiBlYWNoIGVsZW1lbnQgaW4gdGhlIHRlbnNvclxuICAgKiBAcGFyYW0gb3AyIFRoZSBvcGVyYXRpb24gdG8gYmUgcGVyZm9ybWVkIGJldHdlZW4gZWxlbWVudHMgaW4gdGhlIHRlbnNvclxuICAgKi9cbiAgc3RhdGljIGNhbGNSZWR1Y2VCeUF4aXMoXG4gICAgICBpbnB1dDogVGVuc29yLk51bWJlclR5cGUsIGF4ZXM6IG51bWJlcltdLCBkaW1zOiBudW1iZXJbXSwgY3VyQXhpc0luZDogbnVtYmVyLCBwb3M6IG51bWJlcixcbiAgICAgIG9wMTogKGI6IG51bWJlcikgPT4gbnVtYmVyLCBvcDI6IChhOiBudW1iZXIsIGI6IG51bWJlcikgPT4gbnVtYmVyKTogbnVtYmVyIHtcbiAgICBsZXQgcmVzID0gMDtcbiAgICBpZiAoY3VyQXhpc0luZCA+PSBheGVzLmxlbmd0aCkge1xuICAgICAgcmV0dXJuIG9wMShpbnB1dFtwb3NdKTtcbiAgICB9XG4gICAgY29uc3QgYXhpcyA9IGF4ZXNbY3VyQXhpc0luZF07XG4gICAgY29uc3Qgc3RlcCA9IGF4aXMgPj0gZGltcy5sZW5ndGggPyAxIDogU2hhcGVVdGlsLnNpemUoZGltcy5zbGljZShheGlzICsgMSkpO1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgZGltc1theGlzXTsgaSsrKSB7XG4gICAgICByZXMgPSBpID09PSAwID8gUmVkdWNlVXRpbC5jYWxjUmVkdWNlQnlBeGlzKGlucHV0LCBheGVzLCBkaW1zLCBjdXJBeGlzSW5kICsgMSwgcG9zLCBvcDEsIG9wMikgOlxuICAgICAgICAgICAgICAgICAgICAgIG9wMihyZXMsIFJlZHVjZVV0aWwuY2FsY1JlZHVjZUJ5QXhpcyhpbnB1dCwgYXhlcywgZGltcywgY3VyQXhpc0luZCArIDEsIHBvcywgb3AxLCBvcDIpKTtcbiAgICAgIHBvcyArPSBzdGVwO1xuICAgIH1cbiAgICByZXR1cm4gcmVzO1xuICB9XG5cbiAgLyoqXG4gICAqIENhbGN1bGF0ZSB0aGUgZXhwZWN0ZWQgc2hhcGUgb2YgYSByZWR1Y2Ugb3BlcmF0aW9uXG4gICAqIEBwYXJhbSBkaW1zIFRoZSBpbnB1dCB0ZW5zb3IgZGltZW5zaW9uXG4gICAqIEBwYXJhbSBheGVzIFRoZSBkaW1lbnNpb25zIGFsb25nIHdoaWNoIHRoZSBUZW5zb3Igd2lsbCBiZSByZWR1Y2VkXG4gICAqIEBwYXJhbSBrZWVwZGltcyBJZiBzZXQgdG8gdHJ1ZSwgdGhlIGF4ZXMgd2hpY2ggYXJlIHJlZHVjZWQgYXJlIGxlZnQgaW4gdGhlXG4gICAqICAgIHJlc3VsdCBhcyBkaW1lbnNpb25zIHdpdGggc2l6ZSBvbmUuXG4gICAqL1xuICBzdGF0aWMgY2FsY1JlZHVjZVNoYXBlKGRpbXM6IHJlYWRvbmx5IG51bWJlcltdLCBheGVzOiByZWFkb25seSBudW1iZXJbXSwga2VlcERpbXM6IGJvb2xlYW4pOiBudW1iZXJbXSB7XG4gICAgY29uc3Qgb3V0cHV0RGltcyA9IGRpbXMuc2xpY2UoKTtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGF4ZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgIGlmIChrZWVwRGltcykge1xuICAgICAgICBvdXRwdXREaW1zW2F4ZXNbaV1dID0gMTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIG91dHB1dERpbXNbYXhlc1tpXV0gPSAwO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gb3V0cHV0RGltcy5maWx0ZXIoZGltID0+IGRpbSAhPT0gMCk7XG4gIH1cbn1cblxuZXhwb3J0IGNsYXNzIFBvb2xDb252VXRpbCB7XG4gIC8qKlxuICAgKiBBZGp1c3QgdGhlIGtlcm5lbCwgc3RyaWRlcywgcGFkcyB0byBjb3JyZWN0IHJhbmsuIFNldCB0byBkZWZhdWx0IHZhbHVlIGlmIG5vdCBwcmVzZW50XG4gICAqIEBwYXJhbSBpc0dsb2JhbE9wZXJhdG9yIElmIHRydWUsIHBlcmZvcm0gZ2xvYmFsIHBvb2xpbmcuXG4gICAqIEBwYXJhbSBpbnB1dERpbXMgVGhlIGlucHV0IHRlbnNvciBkaW1lbnNpb24uXG4gICAqIEBwYXJhbSBrZXJuZWxTaGFwZSBUaGUgc2l6ZSBvZiB0aGUga2VybmVsIGFsb25nIGVhY2ggYXhpcy5cbiAgICogQHBhcmFtIHN0cmlkZXMgU3RyaWRlIGFsb25nIGVhY2ggYXhpcy5cbiAgICogQHBhcmFtIGRpbGF0aW9ucyBEaWxhdGlvbiBhbG9uZyBlYWNoIGF4aXMuXG4gICAqIEBwYXJhbSBwYWRzIFBhZGRpbmcgZm9yIHRoZSBiZWdpbm5pbmcgYW5kIGVuZGluZyBhbG9uZyBlYWNoIGF4aXMuXG4gICAqL1xuICBzdGF0aWMgYWRqdXN0UG9vbEF0dHJpYnV0ZXMoXG4gICAgICBpc0dsb2JhbE9wZXJhdG9yOiBib29sZWFuLCBpbnB1dERpbXM6IHJlYWRvbmx5IG51bWJlcltdLCBrZXJuZWxTaGFwZTogbnVtYmVyW10sIHN0cmlkZXM6IG51bWJlcltdLFxuICAgICAgZGlsYXRpb25zOiBudW1iZXJbXSwgcGFkczogbnVtYmVyW10pIHtcbiAgICBpZiAoIWlzR2xvYmFsT3BlcmF0b3IgJiYga2VybmVsU2hhcGUubGVuZ3RoICE9PSBpbnB1dERpbXMubGVuZ3RoIC0gMikge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdsZW5ndGggb2Ygc3BlY2lmaWVkIGtlcm5lbCBzaGFwZXMgc2hvdWxkIGJlIDIgbGVzcyB0aGFuIGxlbmd0aCBvZiBpbnB1dCBkaW1lbnNpb25zJyk7XG4gICAgfVxuXG4gICAgaWYgKGlzR2xvYmFsT3BlcmF0b3IpIHtcbiAgICAgIC8vIGFkanVzdCBrZXJuZWwgc2hhcGUgdG8gY292ZXIgdGhlIGlucHV0IGRpbXNcbiAgICAgIGZvciAobGV0IGRpbSA9IDA7IGRpbSA8IGlucHV0RGltcy5sZW5ndGggLSAyOyBkaW0rKykge1xuICAgICAgICBpZiAoZGltID49IGtlcm5lbFNoYXBlLmxlbmd0aCkge1xuICAgICAgICAgIGtlcm5lbFNoYXBlLnB1c2goaW5wdXREaW1zW2RpbSArIDJdKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBrZXJuZWxTaGFwZVtkaW1dID0gaW5wdXREaW1zW2RpbSArIDJdO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gYWRqdXN0IHN0cmlkZXMgbGVuZ3RoIHRvIG1hdGNoIGtlcm5lbCBzaGFwZSBsZW5ndGhcbiAgICBmb3IgKGxldCBkaW0gPSAwOyBkaW0gPCBrZXJuZWxTaGFwZS5sZW5ndGg7IGRpbSsrKSB7XG4gICAgICBpZiAoZGltIDwgc3RyaWRlcy5sZW5ndGgpIHtcbiAgICAgICAgaWYgKHN0cmlkZXNbZGltXSA8IDApIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ3N0cmlkZXMgc2hvdWxkIGJlIGdyZWF0ZXIgdGhhbiBvciBlcXVhbCB0byAxJyk7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHN0cmlkZXMucHVzaCgxKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBhZGp1c3QgZGlsYXRpb24gdmFsdWVcbiAgICBmb3IgKGxldCBkaW0gPSAwOyBkaW0gPCBrZXJuZWxTaGFwZS5sZW5ndGg7IGRpbSsrKSB7XG4gICAgICBpZiAoZGltIDwgZGlsYXRpb25zLmxlbmd0aCkge1xuICAgICAgICBpZiAoZGlsYXRpb25zW2RpbV0gPCAwKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdkaWxhdGlvbnMgc2hvdWxkIGJlIGdyZWF0ZXIgdGhhbiBvciBlcXVhbCB0byAxJyk7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGRpbGF0aW9ucy5wdXNoKDEpO1xuICAgICAgfVxuICAgIH1cblxuICAgIC8vIGFkanVzdCBwYWRzIGxlbmd0aCB0byBtYXRjaCAyICoga2VybmVsIHNoYXBlIGxlbmd0aFxuICAgIGZvciAobGV0IGRpbSA9IDA7IGRpbSA8IGtlcm5lbFNoYXBlLmxlbmd0aCAqIDI7IGRpbSsrKSB7XG4gICAgICBpZiAoZGltIDwgcGFkcy5sZW5ndGgpIHtcbiAgICAgICAgaWYgKHBhZHNbZGltXSA8IDApIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ3BhZCBzaG91bGQgYmUgZ3JlYXRlciB0aGFuIG9yIGVxdWFsIHRvIDEnKTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcGFkcy5wdXNoKDApO1xuICAgICAgfVxuICAgIH1cblxuICAgIC8vIHNhbml0eSBjaGVja3MgZm9yIHZhbHVlcyBpbiBrZXJuZWwgc2hhcGVzIGFuZCBwYWRzXG4gICAgZm9yIChsZXQgZGltID0gMDsgZGltIDwga2VybmVsU2hhcGUubGVuZ3RoOyBkaW0rKykge1xuICAgICAgaWYgKGtlcm5lbFNoYXBlW2RpbV0gPD0gMCkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ2tlcm5lbCBzaGFwZXMgbmVlZCB0byBiZSBncmVhdGVyIHRoYW4gMCcpO1xuICAgICAgfVxuXG4gICAgICBpZiAocGFkc1tkaW1dID49IGtlcm5lbFNoYXBlW2RpbV0gfHwgcGFkc1tkaW0gKyBrZXJuZWxTaGFwZS5sZW5ndGhdID49IGtlcm5lbFNoYXBlW2RpbV0pIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdwYWRzIHNob3VsZCBiZSBzbWFsbGVyIHRoYW4ga2VybmVsJyk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLy8gYWRqdXN0IHBhZCB2YWx1ZXMgYmFzZWQgb24gJ2F1dG9QYWQnIGF0dHJpYnV0ZVxuICBzdGF0aWMgYWRqdXN0UGFkc0Jhc2VkT25BdXRvUGFkKFxuICAgICAgaW5wdXREaW1zOiByZWFkb25seSBudW1iZXJbXSwgc3RyaWRlczogcmVhZG9ubHkgbnVtYmVyW10sIGRpbGF0aW9uczogcmVhZG9ubHkgbnVtYmVyW10sXG4gICAgICBrZXJuZWxTaGFwZTogcmVhZG9ubHkgbnVtYmVyW10sIHBhZHM6IG51bWJlcltdLCBhdXRvUGFkPzogc3RyaW5nKSB7XG4gICAgaWYgKCFhdXRvUGFkKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgaWYgKHBhZHMubGVuZ3RoICE9PSAyICogKGlucHV0RGltcy5sZW5ndGggLSAyKSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdsZW5ndGggb2YgcGFkcyBzaG91bGQgYmUgdHdpY2UgdGhlIGxlbmd0aCBvZiBkYXRhIGRpbWVuc2lvbnMnKTtcbiAgICB9XG5cbiAgICBpZiAoc3RyaWRlcy5sZW5ndGggIT09IChpbnB1dERpbXMubGVuZ3RoIC0gMikpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignbGVuZ3RoIG9mIHN0cmlkZXMgc2hvdWxkIGJlIHRoZSBsZW5ndGggb2YgZGF0YSBkaW1lbnNpb25zJyk7XG4gICAgfVxuXG4gICAgaWYgKGtlcm5lbFNoYXBlLmxlbmd0aCAhPT0gKGlucHV0RGltcy5sZW5ndGggLSAyKSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdsZW5ndGggb2Yga2VybmVsIHNoYXBlcyBzaG91bGQgYmUgdGhlIGxlbmd0aCBvZiBkYXRhIGRpbWVuc2lvbnMnKTtcbiAgICB9XG5cbiAgICBmb3IgKGxldCBkaW0gPSAwOyBkaW0gPCBpbnB1dERpbXMubGVuZ3RoIC0gMjsgZGltKyspIHtcbiAgICAgIFBvb2xDb252VXRpbC5hZGp1c3RQYWRBbmRSZXR1cm5TaGFwZShcbiAgICAgICAgICBpbnB1dERpbXNbZGltICsgMl0sIHN0cmlkZXNbZGltXSwgZGlsYXRpb25zW2RpbV0sIGtlcm5lbFNoYXBlW2RpbV0sIHBhZHMsIGRpbSwgZGltICsgaW5wdXREaW1zLmxlbmd0aCAtIDIsXG4gICAgICAgICAgYXV0b1BhZCk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIENhbGN1bGF0ZSB0aGUgb3V0cHV0IHNoYXBlIGZvciBQb29sIG9wcyBiYXNlZCBvbiBpbnB1dCBhdHRyaWJ1dGVzLiAoU2hvdWxkIGJlIHVzZWQgb25seSBmb3IgUG9vbCBvcHMpXG4gICAqIEBwYXJhbSBpc0dsb2JhbE9wZXJhdG9yIElmIHRydWUsIHBlcmZvcm0gZ2xvYmFsIHBvb2xpbmcuXG4gICAqIEBwYXJhbSBpbnB1dERpbXMgVGhlIGlucHV0IHRlbnNvciBkaW1lbnNpb24uIChpbnB1dHNbMF0uZGltcylcbiAgICogQHBhcmFtIHN0cmlkZXMgU3RyaWRlIGFsb25nIGVhY2ggYXhpcy5cbiAgICogQHBhcmFtIGRpbGF0aW9ucyBEaWxhdGlvbiBhbG9uZyBlYWNoIGF4aXMuXG4gICAqIEBwYXJhbSBrZXJuZWxTaGFwZSBUaGUgc2l6ZSBvZiB0aGUga2VybmVsIGFsb25nIGVhY2ggYXhpcy5cbiAgICogQHBhcmFtIHBhZHMgUGFkZGluZyBmb3IgdGhlIGJlZ2lubmluZyBhbmQgZW5kaW5nIGFsb25nIGVhY2ggYXhpcy5cbiAgICogQHBhcmFtIGF1dG9QYWQgREVQUkVDQVRFRCBhdHRyaWJ1dGUgc3VwcG9ydGVkIGZvciBsZWdhY3kgbW9kZWxzLiBTcGVjaWZpZXMgaG93IHRvIGltcGxpY2l0bHkgY2FsY3VsYXRlIHBhZHMgaW4gZWFjaFxuICAgKiAgICAgZGltZW5zaW9uLiBDYW4gdGFrZSB2YWx1ZXMgTk9UU0VULCBTQU1FX1VQUEVSLCBTQU1FX0xPV0VSLCBvciBWQUxJRC5cbiAgICovXG4gIHN0YXRpYyBjb21wdXRlUG9vbE91dHB1dFNoYXBlKFxuICAgICAgaXNHbG9iYWxPcGVyYXRvcjogYm9vbGVhbiwgaW5wdXREaW1zOiByZWFkb25seSBudW1iZXJbXSwgc3RyaWRlczogbnVtYmVyW10sIGRpbGF0aW9uczogbnVtYmVyW10sXG4gICAgICBrZXJuZWxTaGFwZTogbnVtYmVyW10sIHBhZHM6IG51bWJlcltdLCBhdXRvUGFkPzogc3RyaW5nKTogbnVtYmVyW10ge1xuICAgIGlmIChpbnB1dERpbXMubGVuZ3RoIDw9IDApIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignaW5wdXQgc2hhcGUgbXVzdCBiZSBvZiBzaXplIGdyZWF0ZXIgdGhhbiAwJyk7XG4gICAgfVxuXG4gICAgLy8gQWRkIGJhdGNoIHNpemUgYW5kIG51bWJlciBvZiBjaGFubmVscyBvZiBvdXRwdXRcbiAgICBjb25zdCBvdXRwdXREaW1zID0gW2lucHV0RGltc1swXSwgaW5wdXREaW1zWzFdXTtcblxuICAgIFBvb2xDb252VXRpbC5jb21wdXRlU2hhcGVIZWxwZXIoXG4gICAgICAgIGlzR2xvYmFsT3BlcmF0b3IsIGlucHV0RGltcywgb3V0cHV0RGltcywgc3RyaWRlcywgZGlsYXRpb25zLCBrZXJuZWxTaGFwZSwgcGFkcywgYXV0b1BhZCk7XG4gICAgcmV0dXJuIG91dHB1dERpbXM7XG4gIH1cblxuICAvKipcbiAgICogQ2FsY3VsYXRlIHRoZSBvdXRwdXQgc2hhcGUgZm9yIENvbnYgb3AgYmFzZWQgb24gaW5wdXQgYXR0cmlidXRlcy4gKFNob3VsZCBiZSB1c2VkIG9ubHkgZm9yIENvbnYgb3ApXG4gICAqIEBwYXJhbSBpbnB1dERpbXMgVGhlIGlucHV0IHRlbnNvciBkaW1lbnNpb24uIChpbnB1dHNbMF0uZGltcylcbiAgICogQHBhcmFtIGZpbHRlckRpbXMgVGhlIGZpbHRlciB0ZW5zb3IgZGltZW5zaW9uLiAoaW5wdXRzWzFdLmRpbXMpXG4gICAqIEBwYXJhbSBzdHJpZGVzIFN0cmlkZSBhbG9uZyBlYWNoIGF4aXMuXG4gICAqIEBwYXJhbSBrZXJuZWxTaGFwZSBUaGUgc2l6ZSBvZiB0aGUga2VybmVsIGFsb25nIGVhY2ggYXhpcy5cbiAgICogQHBhcmFtIHBhZHMgUGFkZGluZyBmb3IgdGhlIGJlZ2lubmluZyBhbmQgZW5kaW5nIGFsb25nIGVhY2ggYXhpcy5cbiAgICogQHBhcmFtIGF1dG9QYWQgREVQUkVDQVRFRCBhdHRyaWJ1dGUgc3VwcG9ydGVkIGZvciBsZWdhY3kgbW9kZWxzLiBTcGVjaWZpZXMgaG93IHRvIGltcGxpY2l0bHkgY2FsY3VsYXRlIHBhZHMgaW4gZWFjaFxuICAgKiAgICAgZGltZW5zaW9uLiBDYW4gdGFrZSB2YWx1ZXMgTk9UU0VULCBTQU1FX1VQUEVSLCBTQU1FX0xPV0VSLCBvciBWQUxJRC5cbiAgICovXG4gIHN0YXRpYyBjb21wdXRlQ29udk91dHB1dFNoYXBlKFxuICAgICAgaW5wdXREaW1zOiByZWFkb25seSBudW1iZXJbXSwgZmlsdGVyRGltczogcmVhZG9ubHkgbnVtYmVyW10sIHN0cmlkZXM6IG51bWJlcltdLCBkaWxhdGlvbnM6IG51bWJlcltdLFxuICAgICAga2VybmVsU2hhcGU6IG51bWJlcltdLCBwYWRzOiBudW1iZXJbXSwgYXV0b1BhZD86IHN0cmluZyk6IG51bWJlcltdIHtcbiAgICBpZiAoaW5wdXREaW1zLmxlbmd0aCA8PSAwIHx8IGZpbHRlckRpbXMubGVuZ3RoIDw9IDApIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignaW52YWxpZCBpbnB1dCB0ZW5zb3IgZGltcyBvciBpbnZhbGlkIGZpbHRlciB0ZW5zb3IgZGltcycpO1xuICAgIH1cblxuICAgIC8vIEFkZCBiYXRjaCBzaXplIGFuZCBudW1iZXIgb2YgY2hhbm5lbHMgb2Ygb3V0cHV0XG4gICAgY29uc3Qgb3V0cHV0RGltcyA9IFtpbnB1dERpbXNbMF0sIGZpbHRlckRpbXNbMF1dO1xuXG4gICAgUG9vbENvbnZVdGlsLmNvbXB1dGVTaGFwZUhlbHBlcihmYWxzZSwgaW5wdXREaW1zLCBvdXRwdXREaW1zLCBzdHJpZGVzLCBkaWxhdGlvbnMsIGtlcm5lbFNoYXBlLCBwYWRzLCBhdXRvUGFkKTtcbiAgICByZXR1cm4gb3V0cHV0RGltcztcbiAgfVxuXG4gIC8vIHdpbGwgY29tcHV0ZSBvdXRwdXQgc2hhcGVzIGZvciBkYXRhIGRpbWVuc2lvbnMgT05MWSAoaS5lLikgbm8gYmF0Y2ggc2l6ZSBhbmQgY2hhbm5lbHNcbiAgLy8gY2FsbGVkIGJ5IGNvbXB1dGVQb29sT3V0cHV0U2hhcGUoKSBhbmQgY29tcHV0ZUNvbnZPdXRwdXRTaGFwZSgpXG4gIC8vIGFkanVzdCBwYWRzIGJhc2VkIG9uICdhdXRvUGFkJyBhdHRyaWJ1dGUgcHJpb3IgdG8gc2hhcGUgY29tcHV0YXRpb25cbiAgcHJpdmF0ZSBzdGF0aWMgY29tcHV0ZVNoYXBlSGVscGVyKFxuICAgICAgaXNHbG9iYWxPcGVyYXRvcjogYm9vbGVhbiwgaW5wdXREaW1zOiByZWFkb25seSBudW1iZXJbXSwgb3V0cHV0RGltczogbnVtYmVyW10sIHN0cmlkZXM6IHJlYWRvbmx5IG51bWJlcltdLFxuICAgICAgZGlsYXRpb25zOiByZWFkb25seSBudW1iZXJbXSwga2VybmVsU2hhcGU6IHJlYWRvbmx5IG51bWJlcltdLCBwYWRzOiBudW1iZXJbXSwgYXV0b1BhZD86IHN0cmluZykge1xuICAgIGlmIChpc0dsb2JhbE9wZXJhdG9yKSB7XG4gICAgICBmb3IgKGxldCBkaW0gPSAwOyBkaW0gPCBpbnB1dERpbXMubGVuZ3RoIC0gMjsgZGltKyspIHtcbiAgICAgICAgb3V0cHV0RGltcy5wdXNoKDEpO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICBmb3IgKGxldCBkaW0gPSAwOyBkaW0gPCBpbnB1dERpbXMubGVuZ3RoIC0gMjsgZGltKyspIHtcbiAgICAgICAgb3V0cHV0RGltcy5wdXNoKFBvb2xDb252VXRpbC5hZGp1c3RQYWRBbmRSZXR1cm5TaGFwZShcbiAgICAgICAgICAgIGlucHV0RGltc1tkaW0gKyAyXSwgc3RyaWRlc1tkaW1dLCBkaWxhdGlvbnNbZGltXSwga2VybmVsU2hhcGVbZGltXSwgcGFkcywgZGltLCBkaW0gKyBpbnB1dERpbXMubGVuZ3RoIC0gMixcbiAgICAgICAgICAgIGF1dG9QYWQpKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvLyBoZWxwZXIgZm9yIGNvbXB1dGVTaGFwZUhlbHBlcigpIGFuZCBhZGp1c3RQYWRzQmFzZWRPbkF1dG9QYWQoKVxuICAvLyBhZGp1c3RzIHBhZCB2YWx1ZSBmb3IgZ2l2ZW4gJ2F1dG9QYWQnIHN0cmluZyBhbmQgY29tcHV0ZXMgb3V0cHV0IHNoYXBlIGFsb25nIGEgcGFydGljdWxhciBkaW1lbnNpb25cbiAgcHJpdmF0ZSBzdGF0aWMgYWRqdXN0UGFkQW5kUmV0dXJuU2hhcGUoXG4gICAgICBpblNpemU6IG51bWJlciwgc3RyaWRlOiBudW1iZXIsIGRpbGF0aW9uOiBudW1iZXIsIGtlcm5lbDogbnVtYmVyLCBwYWRzOiBudW1iZXJbXSwgcGFkSGVhZEluZGV4OiBudW1iZXIsXG4gICAgICBwYWRUYWlsSW5kZXg6IG51bWJlciwgYXV0b1BhZD86IHN0cmluZyk6IG51bWJlciB7XG4gICAgY29uc3QgZGtlcm5lbCA9IGRpbGF0aW9uICogKGtlcm5lbCAtIDEpICsgMTtcbiAgICBpZiAoYXV0b1BhZCAmJiBhdXRvUGFkICE9PSAnTk9UU0VUJykge1xuICAgICAgc3dpdGNoIChhdXRvUGFkKSB7XG4gICAgICAgIGNhc2UgJ1ZBTElEJzpcbiAgICAgICAgICBwYWRzW3BhZEhlYWRJbmRleF0gPSAwO1xuICAgICAgICAgIHBhZHNbcGFkVGFpbEluZGV4XSA9IDA7XG4gICAgICAgICAgcmV0dXJuIE1hdGguZmxvb3IoKChpblNpemUgLSBka2VybmVsKSAvIHN0cmlkZSkgKyAxKTtcbiAgICAgICAgY2FzZSAnU0FNRV9MT1dFUic6XG4gICAgICAgIGNhc2UgJ1NBTUVfVVBQRVInOlxuICAgICAgICAgIGlmIChkaWxhdGlvbiAhPT0gMSkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdEaWxhdGlvbiBub3Qgc3VwcG9ydGVkIGZvciBTQU1FX1VQUEVSIG9yIFNBTUVfTE9XRVInKTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgY29uc3QgbGVnYWN5VGFyZ2V0U2l6ZSA9IChpblNpemUgKyBzdHJpZGUgLSAxKSAvIHN0cmlkZTtcbiAgICAgICAgICAgIGNvbnN0IHBhZE5lZWRlZCA9IChsZWdhY3lUYXJnZXRTaXplIC0gMSkgKiBzdHJpZGUgKyBrZXJuZWwgLSBpblNpemU7XG4gICAgICAgICAgICBwYWRzW3BhZEhlYWRJbmRleF0gPVxuICAgICAgICAgICAgICAgIChhdXRvUGFkID09PSAnU0FNRV9MT1dFUicpID8gTWF0aC5mbG9vcigocGFkTmVlZGVkICsgMSkgLyAyKSA6IE1hdGguZmxvb3IocGFkTmVlZGVkIC8gMik7XG4gICAgICAgICAgICBwYWRzW3BhZFRhaWxJbmRleF0gPSBwYWROZWVkZWQgLSBwYWRzW3BhZEhlYWRJbmRleF07XG4gICAgICAgICAgICByZXR1cm4gTWF0aC5mbG9vcigoKGluU2l6ZSArIHBhZE5lZWRlZCAtIGtlcm5lbCkgLyBzdHJpZGUpICsgMSk7XG4gICAgICAgICAgfVxuICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgIHRocm93IG5ldyBFcnJvcignVW5zdXBwb3J0ZWQgQXV0b1BhZCB0eXBlJyk7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBNYXRoLmZsb29yKCgoaW5TaXplICsgcGFkc1twYWRIZWFkSW5kZXhdICsgcGFkc1twYWRUYWlsSW5kZXhdIC0gZGtlcm5lbCkgLyBzdHJpZGUpICsgMSk7XG4gICAgfVxuICB9XG59XG5cbmV4cG9ydCBjb25zdCBNSU5fQ0xJUCA9IC0zLjQwMjgyMzQ2NjM4NTI4ODZlKzM4O1xuZXhwb3J0IGNvbnN0IE1BWF9DTElQID0gMy40MDI4MjM0NjYzODUyODg2ZSszODtcblxuZXhwb3J0IGZ1bmN0aW9uIGRlY29kZVV0ZjhTdHJpbmcoYnVmZmVyOiBVaW50OEFycmF5KTogc3RyaW5nIHtcbiAgcmV0dXJuIG5ldyBUZXh0RGVjb2RlcigpLmRlY29kZShidWZmZXIpO1xufVxuIiwiLy8gQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXG5cbmludGVyZmFjZSBFeHRyYU9wdGlvbnNIYW5kbGVyIHtcbiAgKG5hbWU6IHN0cmluZywgdmFsdWU6IHN0cmluZyk6IHZvaWQ7XG59XG5cbmV4cG9ydCBjb25zdCBpdGVyYXRlRXh0cmFPcHRpb25zID1cbiAgICAob3B0aW9uczogUmVjb3JkPHN0cmluZywgdW5rbm93bj4sIHByZWZpeDogc3RyaW5nLCBzZWVuOiBXZWFrU2V0PFJlY29yZDxzdHJpbmcsIHVua25vd24+PixcbiAgICAgaGFuZGxlcjogRXh0cmFPcHRpb25zSGFuZGxlcik6IHZvaWQgPT4ge1xuICAgICAgaWYgKHR5cGVvZiBvcHRpb25zID09ICdvYmplY3QnICYmIG9wdGlvbnMgIT09IG51bGwpIHtcbiAgICAgICAgaWYgKHNlZW4uaGFzKG9wdGlvbnMpKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdDaXJjdWxhciByZWZlcmVuY2UgaW4gb3B0aW9ucycpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHNlZW4uYWRkKG9wdGlvbnMpO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIE9iamVjdC5lbnRyaWVzKG9wdGlvbnMpLmZvckVhY2goKFtrZXksIHZhbHVlXSkgPT4ge1xuICAgICAgICBjb25zdCBuYW1lID0gKHByZWZpeCkgPyBwcmVmaXggKyBrZXkgOiBrZXk7XG4gICAgICAgIGlmICh0eXBlb2YgdmFsdWUgPT09ICdvYmplY3QnKSB7XG4gICAgICAgICAgaXRlcmF0ZUV4dHJhT3B0aW9ucyh2YWx1ZSBhcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPiwgbmFtZSArICcuJywgc2VlbiwgaGFuZGxlcik7XG4gICAgICAgIH0gZWxzZSBpZiAodHlwZW9mIHZhbHVlID09PSAnc3RyaW5nJyB8fCB0eXBlb2YgdmFsdWUgPT09ICdudW1iZXInKSB7XG4gICAgICAgICAgaGFuZGxlcihuYW1lLCB2YWx1ZS50b1N0cmluZygpKTtcbiAgICAgICAgfSBlbHNlIGlmICh0eXBlb2YgdmFsdWUgPT09ICdib29sZWFuJykge1xuICAgICAgICAgIGhhbmRsZXIobmFtZSwgKHZhbHVlKSA/ICcxJyA6ICcwJyk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBDYW4ndCBoYW5kbGUgZXh0cmEgY29uZmlnIHR5cGU6ICR7dHlwZW9mIHZhbHVlfWApO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9O1xuIiwiLy8gQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXG5cbmltcG9ydCB7ZW52LCBJbmZlcmVuY2VTZXNzaW9ufSBmcm9tICdvbm54cnVudGltZS1jb21tb24nO1xuXG5pbXBvcnQge09ydFdhc21NZXNzYWdlLCBTZXJpYWxpemFibGVNb2RlbGRhdGEsIFNlcmlhbGl6YWJsZVNlc3Npb25NZXRhZGF0YSwgU2VyaWFsaXphYmxlVGVuc29yfSBmcm9tICcuL3Byb3h5LW1lc3NhZ2VzJztcbmltcG9ydCAqIGFzIGNvcmUgZnJvbSAnLi93YXNtLWNvcmUtaW1wbCc7XG5pbXBvcnQge2luaXRpYWxpemVXZWJBc3NlbWJseX0gZnJvbSAnLi93YXNtLWZhY3RvcnknO1xuXG5jb25zdCBpc1Byb3h5ID0gKCk6IGJvb2xlYW4gPT4gISFlbnYud2FzbS5wcm94eSAmJiB0eXBlb2YgZG9jdW1lbnQgIT09ICd1bmRlZmluZWQnO1xubGV0IHByb3h5V29ya2VyOiBXb3JrZXJ8dW5kZWZpbmVkO1xubGV0IGluaXRpYWxpemluZyA9IGZhbHNlO1xubGV0IGluaXRpYWxpemVkID0gZmFsc2U7XG5sZXQgYWJvcnRlZCA9IGZhbHNlO1xuXG4vLyByZXNvbHZlOyByZWplY3RcbnR5cGUgUHJvbWlzZUNhbGxiYWNrczxUID0gdm9pZD4gPSBbKHJlc3VsdDogVCkgPT4gdm9pZCwgKHJlYXNvbjogdW5rbm93bikgPT4gdm9pZF07XG5cbmxldCBpbml0V2FzbUNhbGxiYWNrczogUHJvbWlzZUNhbGxiYWNrcztcbmxldCBpbml0T3J0Q2FsbGJhY2tzOiBQcm9taXNlQ2FsbGJhY2tzO1xuY29uc3QgY3JlYXRlU2Vzc2lvbkFsbG9jYXRlQ2FsbGJhY2tzOiBBcnJheTxQcm9taXNlQ2FsbGJhY2tzPFNlcmlhbGl6YWJsZU1vZGVsZGF0YT4+ID0gW107XG5jb25zdCBjcmVhdGVTZXNzaW9uRmluYWxpemVDYWxsYmFja3M6IEFycmF5PFByb21pc2VDYWxsYmFja3M8U2VyaWFsaXphYmxlU2Vzc2lvbk1ldGFkYXRhPj4gPSBbXTtcbmNvbnN0IGNyZWF0ZVNlc3Npb25DYWxsYmFja3M6IEFycmF5PFByb21pc2VDYWxsYmFja3M8U2VyaWFsaXphYmxlU2Vzc2lvbk1ldGFkYXRhPj4gPSBbXTtcbmNvbnN0IHJlbGVhc2VTZXNzaW9uQ2FsbGJhY2tzOiBBcnJheTxQcm9taXNlQ2FsbGJhY2tzPHZvaWQ+PiA9IFtdO1xuY29uc3QgcnVuQ2FsbGJhY2tzOiBBcnJheTxQcm9taXNlQ2FsbGJhY2tzPFNlcmlhbGl6YWJsZVRlbnNvcltdPj4gPSBbXTtcbmNvbnN0IGVuZFByb2ZpbGluZ0NhbGxiYWNrczogQXJyYXk8UHJvbWlzZUNhbGxiYWNrczx2b2lkPj4gPSBbXTtcblxuY29uc3QgZW5zdXJlV29ya2VyID0gKCk6IHZvaWQgPT4ge1xuICBpZiAoaW5pdGlhbGl6aW5nIHx8ICFpbml0aWFsaXplZCB8fCBhYm9ydGVkIHx8ICFwcm94eVdvcmtlcikge1xuICAgIHRocm93IG5ldyBFcnJvcignd29ya2VyIG5vdCByZWFkeScpO1xuICB9XG59O1xuXG5jb25zdCBvblByb3h5V29ya2VyTWVzc2FnZSA9IChldjogTWVzc2FnZUV2ZW50PE9ydFdhc21NZXNzYWdlPik6IHZvaWQgPT4ge1xuICBzd2l0Y2ggKGV2LmRhdGEudHlwZSkge1xuICAgIGNhc2UgJ2luaXQtd2FzbSc6XG4gICAgICBpbml0aWFsaXppbmcgPSBmYWxzZTtcbiAgICAgIGlmIChldi5kYXRhLmVycikge1xuICAgICAgICBhYm9ydGVkID0gdHJ1ZTtcbiAgICAgICAgaW5pdFdhc21DYWxsYmFja3NbMV0oZXYuZGF0YS5lcnIpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgaW5pdGlhbGl6ZWQgPSB0cnVlO1xuICAgICAgICBpbml0V2FzbUNhbGxiYWNrc1swXSgpO1xuICAgICAgfVxuICAgICAgYnJlYWs7XG4gICAgY2FzZSAnaW5pdC1vcnQnOlxuICAgICAgaWYgKGV2LmRhdGEuZXJyKSB7XG4gICAgICAgIGluaXRPcnRDYWxsYmFja3NbMV0oZXYuZGF0YS5lcnIpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgaW5pdE9ydENhbGxiYWNrc1swXSgpO1xuICAgICAgfVxuICAgICAgYnJlYWs7XG4gICAgY2FzZSAnY3JlYXRlX2FsbG9jYXRlJzpcbiAgICAgIGlmIChldi5kYXRhLmVycikge1xuICAgICAgICBjcmVhdGVTZXNzaW9uQWxsb2NhdGVDYWxsYmFja3Muc2hpZnQoKSFbMV0oZXYuZGF0YS5lcnIpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgY3JlYXRlU2Vzc2lvbkFsbG9jYXRlQ2FsbGJhY2tzLnNoaWZ0KCkhWzBdKGV2LmRhdGEub3V0ISk7XG4gICAgICB9XG4gICAgICBicmVhaztcbiAgICBjYXNlICdjcmVhdGVfZmluYWxpemUnOlxuICAgICAgaWYgKGV2LmRhdGEuZXJyKSB7XG4gICAgICAgIGNyZWF0ZVNlc3Npb25GaW5hbGl6ZUNhbGxiYWNrcy5zaGlmdCgpIVsxXShldi5kYXRhLmVycik7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBjcmVhdGVTZXNzaW9uRmluYWxpemVDYWxsYmFja3Muc2hpZnQoKSFbMF0oZXYuZGF0YS5vdXQhKTtcbiAgICAgIH1cbiAgICAgIGJyZWFrO1xuICAgIGNhc2UgJ2NyZWF0ZSc6XG4gICAgICBpZiAoZXYuZGF0YS5lcnIpIHtcbiAgICAgICAgY3JlYXRlU2Vzc2lvbkNhbGxiYWNrcy5zaGlmdCgpIVsxXShldi5kYXRhLmVycik7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBjcmVhdGVTZXNzaW9uQ2FsbGJhY2tzLnNoaWZ0KCkhWzBdKGV2LmRhdGEub3V0ISk7XG4gICAgICB9XG4gICAgICBicmVhaztcbiAgICBjYXNlICdyZWxlYXNlJzpcbiAgICAgIGlmIChldi5kYXRhLmVycikge1xuICAgICAgICByZWxlYXNlU2Vzc2lvbkNhbGxiYWNrcy5zaGlmdCgpIVsxXShldi5kYXRhLmVycik7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZWxlYXNlU2Vzc2lvbkNhbGxiYWNrcy5zaGlmdCgpIVswXSgpO1xuICAgICAgfVxuICAgICAgYnJlYWs7XG4gICAgY2FzZSAncnVuJzpcbiAgICAgIGlmIChldi5kYXRhLmVycikge1xuICAgICAgICBydW5DYWxsYmFja3Muc2hpZnQoKSFbMV0oZXYuZGF0YS5lcnIpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcnVuQ2FsbGJhY2tzLnNoaWZ0KCkhWzBdKGV2LmRhdGEub3V0ISk7XG4gICAgICB9XG4gICAgICBicmVhaztcbiAgICBjYXNlICdlbmQtcHJvZmlsaW5nJzpcbiAgICAgIGlmIChldi5kYXRhLmVycikge1xuICAgICAgICBlbmRQcm9maWxpbmdDYWxsYmFja3Muc2hpZnQoKSFbMV0oZXYuZGF0YS5lcnIpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgZW5kUHJvZmlsaW5nQ2FsbGJhY2tzLnNoaWZ0KCkhWzBdKCk7XG4gICAgICB9XG4gICAgICBicmVhaztcbiAgICBkZWZhdWx0OlxuICB9XG59O1xuXG5jb25zdCBzY3JpcHRTcmMgPSB0eXBlb2YgZG9jdW1lbnQgIT09ICd1bmRlZmluZWQnID8gKGRvY3VtZW50Py5jdXJyZW50U2NyaXB0IGFzIEhUTUxTY3JpcHRFbGVtZW50KT8uc3JjIDogdW5kZWZpbmVkO1xuXG5leHBvcnQgY29uc3QgaW5pdFdhc20gPSBhc3luYygpOiBQcm9taXNlPHZvaWQ+ID0+IHtcbiAgaWYgKCFCVUlMRF9ERUZTLkRJU0FCTEVfV0FTTV9QUk9YWSAmJiBpc1Byb3h5KCkpIHtcbiAgICBpZiAoaW5pdGlhbGl6ZWQpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgaWYgKGluaXRpYWxpemluZykge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdtdWx0aXBsZSBjYWxscyB0byBcXCdpbml0V2FzbSgpXFwnIGRldGVjdGVkLicpO1xuICAgIH1cbiAgICBpZiAoYWJvcnRlZCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdwcmV2aW91cyBjYWxsIHRvIFxcJ2luaXRXYXNtKClcXCcgZmFpbGVkLicpO1xuICAgIH1cblxuICAgIGluaXRpYWxpemluZyA9IHRydWU7XG5cbiAgICAvLyBvdmVyd3JpdGUgd2FzbSBmaWxlcGF0aHNcbiAgICBpZiAoZW52Lndhc20ud2FzbVBhdGhzID09PSB1bmRlZmluZWQpIHtcbiAgICAgIGlmIChzY3JpcHRTcmMgJiYgc2NyaXB0U3JjLmluZGV4T2YoJ2Jsb2I6JykgIT09IDApIHtcbiAgICAgICAgZW52Lndhc20ud2FzbVBhdGhzID0gc2NyaXB0U3JjLnN1YnN0cigwLCArKHNjcmlwdFNyYykubGFzdEluZGV4T2YoJy8nKSArIDEpO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBuZXcgUHJvbWlzZTx2b2lkPigocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICBwcm94eVdvcmtlcj8udGVybWluYXRlKCk7XG4gICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXZhci1yZXF1aXJlcywgQHR5cGVzY3JpcHQtZXNsaW50L25vLXJlcXVpcmUtaW1wb3J0c1xuICAgICAgcHJveHlXb3JrZXIgPSByZXF1aXJlKCd3b3JrZXItbG9hZGVyP2lubGluZT1uby1mYWxsYmFjayEuL3Byb3h5LXdvcmtlci9tYWluJykuZGVmYXVsdCgpIGFzIFdvcmtlcjtcbiAgICAgIHByb3h5V29ya2VyLm9ubWVzc2FnZSA9IG9uUHJveHlXb3JrZXJNZXNzYWdlO1xuICAgICAgaW5pdFdhc21DYWxsYmFja3MgPSBbcmVzb2x2ZSwgcmVqZWN0XTtcbiAgICAgIGNvbnN0IG1lc3NhZ2U6IE9ydFdhc21NZXNzYWdlID0ge3R5cGU6ICdpbml0LXdhc20nLCBpbiA6IGVudi53YXNtfTtcbiAgICAgIHByb3h5V29ya2VyLnBvc3RNZXNzYWdlKG1lc3NhZ2UpO1xuICAgIH0pO1xuXG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIGluaXRpYWxpemVXZWJBc3NlbWJseShlbnYud2FzbSk7XG4gIH1cbn07XG5cbmV4cG9ydCBjb25zdCBpbml0T3J0ID0gYXN5bmMobnVtVGhyZWFkczogbnVtYmVyLCBsb2dnaW5nTGV2ZWw6IG51bWJlcik6IFByb21pc2U8dm9pZD4gPT4ge1xuICBpZiAoIUJVSUxEX0RFRlMuRElTQUJMRV9XQVNNX1BST1hZICYmIGlzUHJveHkoKSkge1xuICAgIGVuc3VyZVdvcmtlcigpO1xuICAgIHJldHVybiBuZXcgUHJvbWlzZTx2b2lkPigocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICBpbml0T3J0Q2FsbGJhY2tzID0gW3Jlc29sdmUsIHJlamVjdF07XG4gICAgICBjb25zdCBtZXNzYWdlOiBPcnRXYXNtTWVzc2FnZSA9IHt0eXBlOiAnaW5pdC1vcnQnLCBpbiA6IHtudW1UaHJlYWRzLCBsb2dnaW5nTGV2ZWx9fTtcbiAgICAgIHByb3h5V29ya2VyIS5wb3N0TWVzc2FnZShtZXNzYWdlKTtcbiAgICB9KTtcbiAgfSBlbHNlIHtcbiAgICBjb3JlLmluaXRPcnQobnVtVGhyZWFkcywgbG9nZ2luZ0xldmVsKTtcbiAgfVxufTtcblxuZXhwb3J0IGNvbnN0IGNyZWF0ZVNlc3Npb25BbGxvY2F0ZSA9IGFzeW5jKG1vZGVsOiBVaW50OEFycmF5KTogUHJvbWlzZTxTZXJpYWxpemFibGVNb2RlbGRhdGE+ID0+IHtcbiAgaWYgKCFCVUlMRF9ERUZTLkRJU0FCTEVfV0FTTV9QUk9YWSAmJiBpc1Byb3h5KCkpIHtcbiAgICBlbnN1cmVXb3JrZXIoKTtcbiAgICByZXR1cm4gbmV3IFByb21pc2U8U2VyaWFsaXphYmxlTW9kZWxkYXRhPigocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICBjcmVhdGVTZXNzaW9uQWxsb2NhdGVDYWxsYmFja3MucHVzaChbcmVzb2x2ZSwgcmVqZWN0XSk7XG4gICAgICBjb25zdCBtZXNzYWdlOiBPcnRXYXNtTWVzc2FnZSA9IHt0eXBlOiAnY3JlYXRlX2FsbG9jYXRlJywgaW4gOiB7bW9kZWx9fTtcbiAgICAgIHByb3h5V29ya2VyIS5wb3N0TWVzc2FnZShtZXNzYWdlLCBbbW9kZWwuYnVmZmVyXSk7XG4gICAgfSk7XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIGNvcmUuY3JlYXRlU2Vzc2lvbkFsbG9jYXRlKG1vZGVsKTtcbiAgfVxufTtcblxuZXhwb3J0IGNvbnN0IGNyZWF0ZVNlc3Npb25GaW5hbGl6ZSA9IGFzeW5jKG1vZGVsZGF0YTogU2VyaWFsaXphYmxlTW9kZWxkYXRhLCBvcHRpb25zPzogSW5mZXJlbmNlU2Vzc2lvbi5TZXNzaW9uT3B0aW9ucyk6XG4gICAgUHJvbWlzZTxTZXJpYWxpemFibGVTZXNzaW9uTWV0YWRhdGE+ID0+IHtcbiAgICAgIGlmICghQlVJTERfREVGUy5ESVNBQkxFX1dBU01fUFJPWFkgJiYgaXNQcm94eSgpKSB7XG4gICAgICAgIGVuc3VyZVdvcmtlcigpO1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2U8U2VyaWFsaXphYmxlU2Vzc2lvbk1ldGFkYXRhPigocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgY3JlYXRlU2Vzc2lvbkZpbmFsaXplQ2FsbGJhY2tzLnB1c2goW3Jlc29sdmUsIHJlamVjdF0pO1xuICAgICAgICAgIGNvbnN0IG1lc3NhZ2U6IE9ydFdhc21NZXNzYWdlID0ge3R5cGU6ICdjcmVhdGVfZmluYWxpemUnLCBpbiA6IHttb2RlbGRhdGEsIG9wdGlvbnN9fTtcbiAgICAgICAgICBwcm94eVdvcmtlciEucG9zdE1lc3NhZ2UobWVzc2FnZSk7XG4gICAgICAgIH0pO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIGNvcmUuY3JlYXRlU2Vzc2lvbkZpbmFsaXplKG1vZGVsZGF0YSwgb3B0aW9ucyk7XG4gICAgICB9XG4gICAgfTtcblxuZXhwb3J0IGNvbnN0IGNyZWF0ZVNlc3Npb24gPVxuICAgIGFzeW5jKG1vZGVsOiBVaW50OEFycmF5LCBvcHRpb25zPzogSW5mZXJlbmNlU2Vzc2lvbi5TZXNzaW9uT3B0aW9ucyk6IFByb21pc2U8U2VyaWFsaXphYmxlU2Vzc2lvbk1ldGFkYXRhPiA9PiB7XG4gIGlmICghQlVJTERfREVGUy5ESVNBQkxFX1dBU01fUFJPWFkgJiYgaXNQcm94eSgpKSB7XG4gICAgZW5zdXJlV29ya2VyKCk7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlPFNlcmlhbGl6YWJsZVNlc3Npb25NZXRhZGF0YT4oKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgY3JlYXRlU2Vzc2lvbkNhbGxiYWNrcy5wdXNoKFtyZXNvbHZlLCByZWplY3RdKTtcbiAgICAgIGNvbnN0IG1lc3NhZ2U6IE9ydFdhc21NZXNzYWdlID0ge3R5cGU6ICdjcmVhdGUnLCBpbiA6IHttb2RlbCwgb3B0aW9uc319O1xuICAgICAgcHJveHlXb3JrZXIhLnBvc3RNZXNzYWdlKG1lc3NhZ2UsIFttb2RlbC5idWZmZXJdKTtcbiAgICB9KTtcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gY29yZS5jcmVhdGVTZXNzaW9uKG1vZGVsLCBvcHRpb25zKTtcbiAgfVxufTtcblxuZXhwb3J0IGNvbnN0IHJlbGVhc2VTZXNzaW9uID0gYXN5bmMoc2Vzc2lvbklkOiBudW1iZXIpOiBQcm9taXNlPHZvaWQ+ID0+IHtcbiAgaWYgKCFCVUlMRF9ERUZTLkRJU0FCTEVfV0FTTV9QUk9YWSAmJiBpc1Byb3h5KCkpIHtcbiAgICBlbnN1cmVXb3JrZXIoKTtcbiAgICByZXR1cm4gbmV3IFByb21pc2U8dm9pZD4oKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgcmVsZWFzZVNlc3Npb25DYWxsYmFja3MucHVzaChbcmVzb2x2ZSwgcmVqZWN0XSk7XG4gICAgICBjb25zdCBtZXNzYWdlOiBPcnRXYXNtTWVzc2FnZSA9IHt0eXBlOiAncmVsZWFzZScsIGluIDogc2Vzc2lvbklkfTtcbiAgICAgIHByb3h5V29ya2VyIS5wb3N0TWVzc2FnZShtZXNzYWdlKTtcbiAgICB9KTtcbiAgfSBlbHNlIHtcbiAgICBjb3JlLnJlbGVhc2VTZXNzaW9uKHNlc3Npb25JZCk7XG4gIH1cbn07XG5cbmV4cG9ydCBjb25zdCBydW4gPSBhc3luYyhcbiAgICBzZXNzaW9uSWQ6IG51bWJlciwgaW5wdXRJbmRpY2VzOiBudW1iZXJbXSwgaW5wdXRzOiBTZXJpYWxpemFibGVUZW5zb3JbXSwgb3V0cHV0SW5kaWNlczogbnVtYmVyW10sXG4gICAgb3B0aW9uczogSW5mZXJlbmNlU2Vzc2lvbi5SdW5PcHRpb25zKTogUHJvbWlzZTxTZXJpYWxpemFibGVUZW5zb3JbXT4gPT4ge1xuICBpZiAoIUJVSUxEX0RFRlMuRElTQUJMRV9XQVNNX1BST1hZICYmIGlzUHJveHkoKSkge1xuICAgIGVuc3VyZVdvcmtlcigpO1xuICAgIHJldHVybiBuZXcgUHJvbWlzZTxTZXJpYWxpemFibGVUZW5zb3JbXT4oKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgcnVuQ2FsbGJhY2tzLnB1c2goW3Jlc29sdmUsIHJlamVjdF0pO1xuICAgICAgY29uc3QgbWVzc2FnZTogT3J0V2FzbU1lc3NhZ2UgPSB7dHlwZTogJ3J1bicsIGluIDoge3Nlc3Npb25JZCwgaW5wdXRJbmRpY2VzLCBpbnB1dHMsIG91dHB1dEluZGljZXMsIG9wdGlvbnN9fTtcbiAgICAgIHByb3h5V29ya2VyIS5wb3N0TWVzc2FnZShtZXNzYWdlLCBjb3JlLmV4dHJhY3RUcmFuc2ZlcmFibGVCdWZmZXJzKGlucHV0cykpO1xuICAgIH0pO1xuICB9IGVsc2Uge1xuICAgIHJldHVybiBjb3JlLnJ1bihzZXNzaW9uSWQsIGlucHV0SW5kaWNlcywgaW5wdXRzLCBvdXRwdXRJbmRpY2VzLCBvcHRpb25zKTtcbiAgfVxufTtcblxuZXhwb3J0IGNvbnN0IGVuZFByb2ZpbGluZyA9IGFzeW5jKHNlc3Npb25JZDogbnVtYmVyKTogUHJvbWlzZTx2b2lkPiA9PiB7XG4gIGlmICghQlVJTERfREVGUy5ESVNBQkxFX1dBU01fUFJPWFkgJiYgaXNQcm94eSgpKSB7XG4gICAgZW5zdXJlV29ya2VyKCk7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlPHZvaWQ+KChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgIGVuZFByb2ZpbGluZ0NhbGxiYWNrcy5wdXNoKFtyZXNvbHZlLCByZWplY3RdKTtcbiAgICAgIGNvbnN0IG1lc3NhZ2U6IE9ydFdhc21NZXNzYWdlID0ge3R5cGU6ICdlbmQtcHJvZmlsaW5nJywgaW4gOiBzZXNzaW9uSWR9O1xuICAgICAgcHJveHlXb3JrZXIhLnBvc3RNZXNzYWdlKG1lc3NhZ2UpO1xuICAgIH0pO1xuICB9IGVsc2Uge1xuICAgIGNvcmUuZW5kUHJvZmlsaW5nKHNlc3Npb25JZCk7XG4gIH1cbn07XG4iLCIvLyBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cblxuaW1wb3J0IHtJbmZlcmVuY2VTZXNzaW9ufSBmcm9tICdvbm54cnVudGltZS1jb21tb24nO1xuXG5pbXBvcnQge2l0ZXJhdGVFeHRyYU9wdGlvbnN9IGZyb20gJy4vb3B0aW9ucy11dGlscyc7XG5pbXBvcnQge2FsbG9jV2FzbVN0cmluZ30gZnJvbSAnLi9zdHJpbmctdXRpbHMnO1xuaW1wb3J0IHtnZXRJbnN0YW5jZX0gZnJvbSAnLi93YXNtLWZhY3RvcnknO1xuXG5leHBvcnQgY29uc3Qgc2V0UnVuT3B0aW9ucyA9IChvcHRpb25zOiBJbmZlcmVuY2VTZXNzaW9uLlJ1bk9wdGlvbnMpOiBbbnVtYmVyLCBudW1iZXJbXV0gPT4ge1xuICBjb25zdCB3YXNtID0gZ2V0SW5zdGFuY2UoKTtcbiAgbGV0IHJ1bk9wdGlvbnNIYW5kbGUgPSAwO1xuICBjb25zdCBhbGxvY3M6IG51bWJlcltdID0gW107XG5cbiAgY29uc3QgcnVuT3B0aW9uczogSW5mZXJlbmNlU2Vzc2lvbi5SdW5PcHRpb25zID0gb3B0aW9ucyB8fCB7fTtcblxuICB0cnkge1xuICAgIGlmIChvcHRpb25zPy5sb2dTZXZlcml0eUxldmVsID09PSB1bmRlZmluZWQpIHtcbiAgICAgIHJ1bk9wdGlvbnMubG9nU2V2ZXJpdHlMZXZlbCA9IDI7ICAvLyBEZWZhdWx0IHRvIHdhcm5pbmdcbiAgICB9IGVsc2UgaWYgKFxuICAgICAgICB0eXBlb2Ygb3B0aW9ucy5sb2dTZXZlcml0eUxldmVsICE9PSAnbnVtYmVyJyB8fCAhTnVtYmVyLmlzSW50ZWdlcihvcHRpb25zLmxvZ1NldmVyaXR5TGV2ZWwpIHx8XG4gICAgICAgIG9wdGlvbnMubG9nU2V2ZXJpdHlMZXZlbCA8IDAgfHwgb3B0aW9ucy5sb2dTZXZlcml0eUxldmVsID4gNCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBsb2cgc2VydmVyaXR5IGxldmVsIGlzIG5vdCB2YWxpZDogJHtvcHRpb25zLmxvZ1NldmVyaXR5TGV2ZWx9YCk7XG4gICAgfVxuXG4gICAgaWYgKG9wdGlvbnM/LmxvZ1ZlcmJvc2l0eUxldmVsID09PSB1bmRlZmluZWQpIHtcbiAgICAgIHJ1bk9wdGlvbnMubG9nVmVyYm9zaXR5TGV2ZWwgPSAwOyAgLy8gRGVmYXVsdCB0byAwXG4gICAgfSBlbHNlIGlmICh0eXBlb2Ygb3B0aW9ucy5sb2dWZXJib3NpdHlMZXZlbCAhPT0gJ251bWJlcicgfHwgIU51bWJlci5pc0ludGVnZXIob3B0aW9ucy5sb2dWZXJib3NpdHlMZXZlbCkpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgbG9nIHZlcmJvc2l0eSBsZXZlbCBpcyBub3QgdmFsaWQ6ICR7b3B0aW9ucy5sb2dWZXJib3NpdHlMZXZlbH1gKTtcbiAgICB9XG5cbiAgICBpZiAob3B0aW9ucz8udGVybWluYXRlID09PSB1bmRlZmluZWQpIHtcbiAgICAgIHJ1bk9wdGlvbnMudGVybWluYXRlID0gZmFsc2U7XG4gICAgfVxuXG4gICAgbGV0IHRhZ0RhdGFPZmZzZXQgPSAwO1xuICAgIGlmIChvcHRpb25zPy50YWcgIT09IHVuZGVmaW5lZCkge1xuICAgICAgdGFnRGF0YU9mZnNldCA9IGFsbG9jV2FzbVN0cmluZyhvcHRpb25zLnRhZywgYWxsb2NzKTtcbiAgICB9XG5cbiAgICBydW5PcHRpb25zSGFuZGxlID0gd2FzbS5fT3J0Q3JlYXRlUnVuT3B0aW9ucyhcbiAgICAgICAgcnVuT3B0aW9ucy5sb2dTZXZlcml0eUxldmVsISwgcnVuT3B0aW9ucy5sb2dWZXJib3NpdHlMZXZlbCEsICEhcnVuT3B0aW9ucy50ZXJtaW5hdGUhLCB0YWdEYXRhT2Zmc2V0KTtcbiAgICBpZiAocnVuT3B0aW9uc0hhbmRsZSA9PT0gMCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdDYW5cXCd0IGNyZWF0ZSBydW4gb3B0aW9ucycpO1xuICAgIH1cblxuICAgIGlmIChvcHRpb25zPy5leHRyYSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICBpdGVyYXRlRXh0cmFPcHRpb25zKG9wdGlvbnMuZXh0cmEsICcnLCBuZXcgV2Vha1NldDxSZWNvcmQ8c3RyaW5nLCB1bmtub3duPj4oKSwgKGtleSwgdmFsdWUpID0+IHtcbiAgICAgICAgY29uc3Qga2V5RGF0YU9mZnNldCA9IGFsbG9jV2FzbVN0cmluZyhrZXksIGFsbG9jcyk7XG4gICAgICAgIGNvbnN0IHZhbHVlRGF0YU9mZnNldCA9IGFsbG9jV2FzbVN0cmluZyh2YWx1ZSwgYWxsb2NzKTtcblxuICAgICAgICBpZiAod2FzbS5fT3J0QWRkUnVuQ29uZmlnRW50cnkocnVuT3B0aW9uc0hhbmRsZSwga2V5RGF0YU9mZnNldCwgdmFsdWVEYXRhT2Zmc2V0KSAhPT0gMCkge1xuICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgQ2FuJ3Qgc2V0IGEgcnVuIGNvbmZpZyBlbnRyeTogJHtrZXl9IC0gJHt2YWx1ZX1gKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIFtydW5PcHRpb25zSGFuZGxlLCBhbGxvY3NdO1xuICB9IGNhdGNoIChlKSB7XG4gICAgaWYgKHJ1bk9wdGlvbnNIYW5kbGUgIT09IDApIHtcbiAgICAgIHdhc20uX09ydFJlbGVhc2VSdW5PcHRpb25zKHJ1bk9wdGlvbnNIYW5kbGUpO1xuICAgIH1cbiAgICBhbGxvY3MuZm9yRWFjaCh3YXNtLl9mcmVlKTtcbiAgICB0aHJvdyBlO1xuICB9XG59O1xuIiwiLy8gQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXG5cbmltcG9ydCB7cmVhZEZpbGV9IGZyb20gJ2ZzJztcbmltcG9ydCB7ZW52LCBJbmZlcmVuY2VTZXNzaW9uLCBTZXNzaW9uSGFuZGxlciwgVGVuc29yfSBmcm9tICdvbm54cnVudGltZS1jb21tb24nO1xuaW1wb3J0IHtwcm9taXNpZnl9IGZyb20gJ3V0aWwnO1xuXG5pbXBvcnQge1NlcmlhbGl6YWJsZU1vZGVsZGF0YX0gZnJvbSAnLi9wcm94eS1tZXNzYWdlcyc7XG5pbXBvcnQge2NyZWF0ZVNlc3Npb24sIGNyZWF0ZVNlc3Npb25BbGxvY2F0ZSwgY3JlYXRlU2Vzc2lvbkZpbmFsaXplLCBlbmRQcm9maWxpbmcsIGluaXRPcnQsIHJlbGVhc2VTZXNzaW9uLCBydW59IGZyb20gJy4vcHJveHktd3JhcHBlcic7XG5cbmxldCBvcnRJbml0OiBib29sZWFuO1xuXG5cbmNvbnN0IGdldExvZ0xldmVsID0gKGxvZ0xldmVsOiAndmVyYm9zZSd8J2luZm8nfCd3YXJuaW5nJ3wnZXJyb3InfCdmYXRhbCcpOiBudW1iZXIgPT4ge1xuICBzd2l0Y2ggKGxvZ0xldmVsKSB7XG4gICAgY2FzZSAndmVyYm9zZSc6XG4gICAgICByZXR1cm4gMDtcbiAgICBjYXNlICdpbmZvJzpcbiAgICAgIHJldHVybiAxO1xuICAgIGNhc2UgJ3dhcm5pbmcnOlxuICAgICAgcmV0dXJuIDI7XG4gICAgY2FzZSAnZXJyb3InOlxuICAgICAgcmV0dXJuIDM7XG4gICAgY2FzZSAnZmF0YWwnOlxuICAgICAgcmV0dXJuIDQ7XG4gICAgZGVmYXVsdDpcbiAgICAgIHRocm93IG5ldyBFcnJvcihgdW5zdXBwb3J0ZWQgbG9nZ2luZyBsZXZlbDogJHtsb2dMZXZlbH1gKTtcbiAgfVxufTtcblxuXG5leHBvcnQgY2xhc3MgT25ueHJ1bnRpbWVXZWJBc3NlbWJseVNlc3Npb25IYW5kbGVyIGltcGxlbWVudHMgU2Vzc2lvbkhhbmRsZXIge1xuICBwcml2YXRlIHNlc3Npb25JZDogbnVtYmVyO1xuXG4gIGlucHV0TmFtZXM6IHN0cmluZ1tdO1xuICBvdXRwdXROYW1lczogc3RyaW5nW107XG5cbiAgYXN5bmMgY3JlYXRlU2Vzc2lvbkFsbG9jYXRlKHBhdGg6IHN0cmluZyk6IFByb21pc2U8U2VyaWFsaXphYmxlTW9kZWxkYXRhPiB7XG4gICAgLy8gZmV0Y2ggbW9kZWwgZnJvbSB1cmwgYW5kIG1vdmUgdG8gd2FzbSBoZWFwLiBUaGUgYXJyYXlidWZmZmVyIHRoYXQgaGVsZCB0aGUgaHR0cFxuICAgIC8vIHJlc3BvbnNlIGlzIGZyZWVkIG9uY2Ugd2UgcmV0dXJuXG4gICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCBmZXRjaChwYXRoKTtcbiAgICBjb25zdCBhcnJheUJ1ZmZlciA9IGF3YWl0IHJlc3BvbnNlLmFycmF5QnVmZmVyKCk7XG4gICAgcmV0dXJuIGNyZWF0ZVNlc3Npb25BbGxvY2F0ZShuZXcgVWludDhBcnJheShhcnJheUJ1ZmZlcikpO1xuICB9XG5cbiAgYXN5bmMgbG9hZE1vZGVsKHBhdGhPckJ1ZmZlcjogc3RyaW5nfFVpbnQ4QXJyYXksIG9wdGlvbnM/OiBJbmZlcmVuY2VTZXNzaW9uLlNlc3Npb25PcHRpb25zKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgaWYgKCFvcnRJbml0KSB7XG4gICAgICBhd2FpdCBpbml0T3J0KGVudi53YXNtLm51bVRocmVhZHMhLCBnZXRMb2dMZXZlbChlbnYubG9nTGV2ZWwhKSk7XG4gICAgICBvcnRJbml0ID0gdHJ1ZTtcbiAgICB9XG5cbiAgICBpZiAodHlwZW9mIHBhdGhPckJ1ZmZlciA9PT0gJ3N0cmluZycpIHtcbiAgICAgIGlmICh0eXBlb2YgZmV0Y2ggPT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgIC8vIG5vZGVcbiAgICAgICAgY29uc3QgbW9kZWwgPSBhd2FpdCBwcm9taXNpZnkocmVhZEZpbGUpKHBhdGhPckJ1ZmZlcik7XG4gICAgICAgIFt0aGlzLnNlc3Npb25JZCwgdGhpcy5pbnB1dE5hbWVzLCB0aGlzLm91dHB1dE5hbWVzXSA9IGF3YWl0IGNyZWF0ZVNlc3Npb24obW9kZWwsIG9wdGlvbnMpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgLy8gYnJvd3NlclxuICAgICAgICAvLyBmZXRjaCBtb2RlbCBhbmQgbW92ZSB0byB3YXNtIGhlYXAuXG4gICAgICAgIGNvbnN0IG1vZGVsRGF0YTogU2VyaWFsaXphYmxlTW9kZWxkYXRhID0gYXdhaXQgdGhpcy5jcmVhdGVTZXNzaW9uQWxsb2NhdGUocGF0aE9yQnVmZmVyKTtcbiAgICAgICAgLy8gY3JlYXRlIHRoZSBzZXNzaW9uXG4gICAgICAgIFt0aGlzLnNlc3Npb25JZCwgdGhpcy5pbnB1dE5hbWVzLCB0aGlzLm91dHB1dE5hbWVzXSA9IGF3YWl0IGNyZWF0ZVNlc3Npb25GaW5hbGl6ZShtb2RlbERhdGEsIG9wdGlvbnMpO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICBbdGhpcy5zZXNzaW9uSWQsIHRoaXMuaW5wdXROYW1lcywgdGhpcy5vdXRwdXROYW1lc10gPSBhd2FpdCBjcmVhdGVTZXNzaW9uKHBhdGhPckJ1ZmZlciwgb3B0aW9ucyk7XG4gICAgfVxuICB9XG5cbiAgYXN5bmMgZGlzcG9zZSgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICByZXR1cm4gcmVsZWFzZVNlc3Npb24odGhpcy5zZXNzaW9uSWQpO1xuICB9XG5cbiAgYXN5bmMgcnVuKGZlZWRzOiBTZXNzaW9uSGFuZGxlci5GZWVkc1R5cGUsIGZldGNoZXM6IFNlc3Npb25IYW5kbGVyLkZldGNoZXNUeXBlLCBvcHRpb25zOiBJbmZlcmVuY2VTZXNzaW9uLlJ1bk9wdGlvbnMpOlxuICAgICAgUHJvbWlzZTxTZXNzaW9uSGFuZGxlci5SZXR1cm5UeXBlPiB7XG4gICAgY29uc3QgaW5wdXRBcnJheTogVGVuc29yW10gPSBbXTtcbiAgICBjb25zdCBpbnB1dEluZGljZXM6IG51bWJlcltdID0gW107XG4gICAgT2JqZWN0LmVudHJpZXMoZmVlZHMpLmZvckVhY2goa3ZwID0+IHtcbiAgICAgIGNvbnN0IG5hbWUgPSBrdnBbMF07XG4gICAgICBjb25zdCB0ZW5zb3IgPSBrdnBbMV07XG4gICAgICBjb25zdCBpbmRleCA9IHRoaXMuaW5wdXROYW1lcy5pbmRleE9mKG5hbWUpO1xuICAgICAgaWYgKGluZGV4ID09PSAtMSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYGludmFsaWQgaW5wdXQgJyR7bmFtZX0nYCk7XG4gICAgICB9XG4gICAgICBpbnB1dEFycmF5LnB1c2godGVuc29yKTtcbiAgICAgIGlucHV0SW5kaWNlcy5wdXNoKGluZGV4KTtcbiAgICB9KTtcblxuICAgIGNvbnN0IG91dHB1dEluZGljZXM6IG51bWJlcltdID0gW107XG4gICAgT2JqZWN0LmVudHJpZXMoZmV0Y2hlcykuZm9yRWFjaChrdnAgPT4ge1xuICAgICAgY29uc3QgbmFtZSA9IGt2cFswXTtcbiAgICAgIC8vIFRPRE86IHN1cHBvcnQgcHJlLWFsbG9jYXRlZCBvdXRwdXRcbiAgICAgIGNvbnN0IGluZGV4ID0gdGhpcy5vdXRwdXROYW1lcy5pbmRleE9mKG5hbWUpO1xuICAgICAgaWYgKGluZGV4ID09PSAtMSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYGludmFsaWQgb3V0cHV0ICcke25hbWV9J2ApO1xuICAgICAgfVxuICAgICAgb3V0cHV0SW5kaWNlcy5wdXNoKGluZGV4KTtcbiAgICB9KTtcblxuICAgIGNvbnN0IG91dHB1dHMgPVxuICAgICAgICBhd2FpdCBydW4odGhpcy5zZXNzaW9uSWQsIGlucHV0SW5kaWNlcywgaW5wdXRBcnJheS5tYXAodCA9PiBbdC50eXBlLCB0LmRpbXMsIHQuZGF0YV0pLCBvdXRwdXRJbmRpY2VzLCBvcHRpb25zKTtcblxuICAgIGNvbnN0IHJlc3VsdDogU2Vzc2lvbkhhbmRsZXIuUmV0dXJuVHlwZSA9IHt9O1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgb3V0cHV0cy5sZW5ndGg7IGkrKykge1xuICAgICAgcmVzdWx0W3RoaXMub3V0cHV0TmFtZXNbb3V0cHV0SW5kaWNlc1tpXV1dID0gbmV3IFRlbnNvcihvdXRwdXRzW2ldWzBdLCBvdXRwdXRzW2ldWzJdLCBvdXRwdXRzW2ldWzFdKTtcbiAgICB9XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfVxuXG4gIHN0YXJ0UHJvZmlsaW5nKCk6IHZvaWQge1xuICAgIC8vIFRPRE86IGltcGxlbWVudCBwcm9maWxpbmdcbiAgfVxuXG4gIGVuZFByb2ZpbGluZygpOiB2b2lkIHtcbiAgICB2b2lkIGVuZFByb2ZpbGluZyh0aGlzLnNlc3Npb25JZCk7XG4gIH1cbn1cbiIsIi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxuXG5pbXBvcnQge0luZmVyZW5jZVNlc3Npb259IGZyb20gJ29ubnhydW50aW1lLWNvbW1vbic7XG5cbmltcG9ydCB7aXRlcmF0ZUV4dHJhT3B0aW9uc30gZnJvbSAnLi9vcHRpb25zLXV0aWxzJztcbmltcG9ydCB7YWxsb2NXYXNtU3RyaW5nfSBmcm9tICcuL3N0cmluZy11dGlscyc7XG5pbXBvcnQge2dldEluc3RhbmNlfSBmcm9tICcuL3dhc20tZmFjdG9yeSc7XG5cbmNvbnN0IGdldEdyYXBoT3B0aW16YXRpb25MZXZlbCA9IChncmFwaE9wdGltaXphdGlvbkxldmVsOiBzdHJpbmd8dW5rbm93bik6IG51bWJlciA9PiB7XG4gIHN3aXRjaCAoZ3JhcGhPcHRpbWl6YXRpb25MZXZlbCkge1xuICAgIGNhc2UgJ2Rpc2FibGVkJzpcbiAgICAgIHJldHVybiAwO1xuICAgIGNhc2UgJ2Jhc2ljJzpcbiAgICAgIHJldHVybiAxO1xuICAgIGNhc2UgJ2V4dGVuZGVkJzpcbiAgICAgIHJldHVybiAyO1xuICAgIGNhc2UgJ2FsbCc6XG4gICAgICByZXR1cm4gOTk7XG4gICAgZGVmYXVsdDpcbiAgICAgIHRocm93IG5ldyBFcnJvcihgdW5zdXBwb3J0ZWQgZ3JhcGggb3B0aW1pemF0aW9uIGxldmVsOiAke2dyYXBoT3B0aW1pemF0aW9uTGV2ZWx9YCk7XG4gIH1cbn07XG5cbmNvbnN0IGdldEV4ZWN1dGlvbk1vZGUgPSAoZXhlY3V0aW9uTW9kZTogJ3NlcXVlbnRpYWwnfCdwYXJhbGxlbCcpOiBudW1iZXIgPT4ge1xuICBzd2l0Y2ggKGV4ZWN1dGlvbk1vZGUpIHtcbiAgICBjYXNlICdzZXF1ZW50aWFsJzpcbiAgICAgIHJldHVybiAwO1xuICAgIGNhc2UgJ3BhcmFsbGVsJzpcbiAgICAgIHJldHVybiAxO1xuICAgIGRlZmF1bHQ6XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYHVuc3VwcG9ydGVkIGV4ZWN1dGlvbiBtb2RlOiAke2V4ZWN1dGlvbk1vZGV9YCk7XG4gIH1cbn07XG5cbmNvbnN0IGFwcGVuZERlZmF1bHRPcHRpb25zID0gKG9wdGlvbnM6IEluZmVyZW5jZVNlc3Npb24uU2Vzc2lvbk9wdGlvbnMpOiB2b2lkID0+IHtcbiAgaWYgKCFvcHRpb25zLmV4dHJhKSB7XG4gICAgb3B0aW9ucy5leHRyYSA9IHt9O1xuICB9XG4gIGlmICghb3B0aW9ucy5leHRyYS5zZXNzaW9uKSB7XG4gICAgb3B0aW9ucy5leHRyYS5zZXNzaW9uID0ge307XG4gIH1cbiAgY29uc3Qgc2Vzc2lvbiA9IG9wdGlvbnMuZXh0cmEuc2Vzc2lvbiBhcyBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+O1xuICBpZiAoIXNlc3Npb24udXNlX29ydF9tb2RlbF9ieXRlc19kaXJlY3RseSkge1xuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBjYW1lbGNhc2VcbiAgICBzZXNzaW9uLnVzZV9vcnRfbW9kZWxfYnl0ZXNfZGlyZWN0bHkgPSAnMSc7XG4gIH1cbn07XG5cbmNvbnN0IHNldEV4ZWN1dGlvblByb3ZpZGVycyA9XG4gICAgKHNlc3Npb25PcHRpb25zSGFuZGxlOiBudW1iZXIsIGV4ZWN1dGlvblByb3ZpZGVyczogcmVhZG9ubHkgSW5mZXJlbmNlU2Vzc2lvbi5FeGVjdXRpb25Qcm92aWRlckNvbmZpZ1tdLFxuICAgICBhbGxvY3M6IG51bWJlcltdKTogdm9pZCA9PiB7XG4gICAgICBmb3IgKGNvbnN0IGVwIG9mIGV4ZWN1dGlvblByb3ZpZGVycykge1xuICAgICAgICBsZXQgZXBOYW1lID0gdHlwZW9mIGVwID09PSAnc3RyaW5nJyA/IGVwIDogZXAubmFtZTtcblxuICAgICAgICAvLyBjaGVjayBFUCBuYW1lXG4gICAgICAgIHN3aXRjaCAoZXBOYW1lKSB7XG4gICAgICAgICAgY2FzZSAneG5ucGFjayc6XG4gICAgICAgICAgICBlcE5hbWUgPSAnWE5OUEFDSyc7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICBjYXNlICd3YXNtJzpcbiAgICAgICAgICBjYXNlICdjcHUnOlxuICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgbm90IHN1cHBvcnRlZCBFUDogJHtlcE5hbWV9YCk7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBlcE5hbWVEYXRhT2Zmc2V0ID0gYWxsb2NXYXNtU3RyaW5nKGVwTmFtZSwgYWxsb2NzKTtcbiAgICAgICAgaWYgKGdldEluc3RhbmNlKCkuX09ydEFwcGVuZEV4ZWN1dGlvblByb3ZpZGVyKHNlc3Npb25PcHRpb25zSGFuZGxlLCBlcE5hbWVEYXRhT2Zmc2V0KSAhPT0gMCkge1xuICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgQ2FuJ3QgYXBwZW5kIGV4ZWN1dGlvbiBwcm92aWRlcjogJHtlcE5hbWV9YCk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9O1xuXG5leHBvcnQgY29uc3Qgc2V0U2Vzc2lvbk9wdGlvbnMgPSAob3B0aW9ucz86IEluZmVyZW5jZVNlc3Npb24uU2Vzc2lvbk9wdGlvbnMpOiBbbnVtYmVyLCBudW1iZXJbXV0gPT4ge1xuICBjb25zdCB3YXNtID0gZ2V0SW5zdGFuY2UoKTtcbiAgbGV0IHNlc3Npb25PcHRpb25zSGFuZGxlID0gMDtcbiAgY29uc3QgYWxsb2NzOiBudW1iZXJbXSA9IFtdO1xuXG4gIGNvbnN0IHNlc3Npb25PcHRpb25zOiBJbmZlcmVuY2VTZXNzaW9uLlNlc3Npb25PcHRpb25zID0gb3B0aW9ucyB8fCB7fTtcbiAgYXBwZW5kRGVmYXVsdE9wdGlvbnMoc2Vzc2lvbk9wdGlvbnMpO1xuXG4gIHRyeSB7XG4gICAgaWYgKG9wdGlvbnM/LmdyYXBoT3B0aW1pemF0aW9uTGV2ZWwgPT09IHVuZGVmaW5lZCkge1xuICAgICAgc2Vzc2lvbk9wdGlvbnMuZ3JhcGhPcHRpbWl6YXRpb25MZXZlbCA9ICdhbGwnO1xuICAgIH1cbiAgICBjb25zdCBncmFwaE9wdGltaXphdGlvbkxldmVsID0gZ2V0R3JhcGhPcHRpbXphdGlvbkxldmVsKHNlc3Npb25PcHRpb25zLmdyYXBoT3B0aW1pemF0aW9uTGV2ZWwhKTtcblxuICAgIGlmIChvcHRpb25zPy5lbmFibGVDcHVNZW1BcmVuYSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICBzZXNzaW9uT3B0aW9ucy5lbmFibGVDcHVNZW1BcmVuYSA9IHRydWU7XG4gICAgfVxuXG4gICAgaWYgKG9wdGlvbnM/LmVuYWJsZU1lbVBhdHRlcm4gPT09IHVuZGVmaW5lZCkge1xuICAgICAgc2Vzc2lvbk9wdGlvbnMuZW5hYmxlTWVtUGF0dGVybiA9IHRydWU7XG4gICAgfVxuXG4gICAgaWYgKG9wdGlvbnM/LmV4ZWN1dGlvbk1vZGUgPT09IHVuZGVmaW5lZCkge1xuICAgICAgc2Vzc2lvbk9wdGlvbnMuZXhlY3V0aW9uTW9kZSA9ICdzZXF1ZW50aWFsJztcbiAgICB9XG4gICAgY29uc3QgZXhlY3V0aW9uTW9kZSA9IGdldEV4ZWN1dGlvbk1vZGUoc2Vzc2lvbk9wdGlvbnMuZXhlY3V0aW9uTW9kZSEpO1xuXG4gICAgbGV0IGxvZ0lkRGF0YU9mZnNldCA9IDA7XG4gICAgaWYgKG9wdGlvbnM/LmxvZ0lkICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIGxvZ0lkRGF0YU9mZnNldCA9IGFsbG9jV2FzbVN0cmluZyhvcHRpb25zLmxvZ0lkLCBhbGxvY3MpO1xuICAgIH1cblxuICAgIGlmIChvcHRpb25zPy5sb2dTZXZlcml0eUxldmVsID09PSB1bmRlZmluZWQpIHtcbiAgICAgIHNlc3Npb25PcHRpb25zLmxvZ1NldmVyaXR5TGV2ZWwgPSAyOyAgLy8gRGVmYXVsdCB0byB3YXJuaW5nXG4gICAgfSBlbHNlIGlmIChcbiAgICAgICAgdHlwZW9mIG9wdGlvbnMubG9nU2V2ZXJpdHlMZXZlbCAhPT0gJ251bWJlcicgfHwgIU51bWJlci5pc0ludGVnZXIob3B0aW9ucy5sb2dTZXZlcml0eUxldmVsKSB8fFxuICAgICAgICBvcHRpb25zLmxvZ1NldmVyaXR5TGV2ZWwgPCAwIHx8IG9wdGlvbnMubG9nU2V2ZXJpdHlMZXZlbCA+IDQpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgbG9nIHNlcnZlcml0eSBsZXZlbCBpcyBub3QgdmFsaWQ6ICR7b3B0aW9ucy5sb2dTZXZlcml0eUxldmVsfWApO1xuICAgIH1cblxuICAgIGlmIChvcHRpb25zPy5sb2dWZXJib3NpdHlMZXZlbCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICBzZXNzaW9uT3B0aW9ucy5sb2dWZXJib3NpdHlMZXZlbCA9IDA7ICAvLyBEZWZhdWx0IHRvIDBcbiAgICB9IGVsc2UgaWYgKHR5cGVvZiBvcHRpb25zLmxvZ1ZlcmJvc2l0eUxldmVsICE9PSAnbnVtYmVyJyB8fCAhTnVtYmVyLmlzSW50ZWdlcihvcHRpb25zLmxvZ1ZlcmJvc2l0eUxldmVsKSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBsb2cgdmVyYm9zaXR5IGxldmVsIGlzIG5vdCB2YWxpZDogJHtvcHRpb25zLmxvZ1ZlcmJvc2l0eUxldmVsfWApO1xuICAgIH1cblxuICAgIGlmIChvcHRpb25zPy5lbmFibGVQcm9maWxpbmcgPT09IHVuZGVmaW5lZCkge1xuICAgICAgc2Vzc2lvbk9wdGlvbnMuZW5hYmxlUHJvZmlsaW5nID0gZmFsc2U7XG4gICAgfVxuXG4gICAgc2Vzc2lvbk9wdGlvbnNIYW5kbGUgPSB3YXNtLl9PcnRDcmVhdGVTZXNzaW9uT3B0aW9ucyhcbiAgICAgICAgZ3JhcGhPcHRpbWl6YXRpb25MZXZlbCwgISFzZXNzaW9uT3B0aW9ucy5lbmFibGVDcHVNZW1BcmVuYSEsICEhc2Vzc2lvbk9wdGlvbnMuZW5hYmxlTWVtUGF0dGVybiEsIGV4ZWN1dGlvbk1vZGUsXG4gICAgICAgICEhc2Vzc2lvbk9wdGlvbnMuZW5hYmxlUHJvZmlsaW5nISwgMCwgbG9nSWREYXRhT2Zmc2V0LCBzZXNzaW9uT3B0aW9ucy5sb2dTZXZlcml0eUxldmVsISxcbiAgICAgICAgc2Vzc2lvbk9wdGlvbnMubG9nVmVyYm9zaXR5TGV2ZWwhKTtcbiAgICBpZiAoc2Vzc2lvbk9wdGlvbnNIYW5kbGUgPT09IDApIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignQ2FuXFwndCBjcmVhdGUgc2Vzc2lvbiBvcHRpb25zJyk7XG4gICAgfVxuXG4gICAgaWYgKG9wdGlvbnM/LmV4ZWN1dGlvblByb3ZpZGVycykge1xuICAgICAgc2V0RXhlY3V0aW9uUHJvdmlkZXJzKHNlc3Npb25PcHRpb25zSGFuZGxlLCBvcHRpb25zLmV4ZWN1dGlvblByb3ZpZGVycywgYWxsb2NzKTtcbiAgICB9XG5cbiAgICBpZiAob3B0aW9ucz8uZXh0cmEgIT09IHVuZGVmaW5lZCkge1xuICAgICAgaXRlcmF0ZUV4dHJhT3B0aW9ucyhvcHRpb25zLmV4dHJhLCAnJywgbmV3IFdlYWtTZXQ8UmVjb3JkPHN0cmluZywgdW5rbm93bj4+KCksIChrZXksIHZhbHVlKSA9PiB7XG4gICAgICAgIGNvbnN0IGtleURhdGFPZmZzZXQgPSBhbGxvY1dhc21TdHJpbmcoa2V5LCBhbGxvY3MpO1xuICAgICAgICBjb25zdCB2YWx1ZURhdGFPZmZzZXQgPSBhbGxvY1dhc21TdHJpbmcodmFsdWUsIGFsbG9jcyk7XG5cbiAgICAgICAgaWYgKHdhc20uX09ydEFkZFNlc3Npb25Db25maWdFbnRyeShzZXNzaW9uT3B0aW9uc0hhbmRsZSwga2V5RGF0YU9mZnNldCwgdmFsdWVEYXRhT2Zmc2V0KSAhPT0gMCkge1xuICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgQ2FuJ3Qgc2V0IGEgc2Vzc2lvbiBjb25maWcgZW50cnk6ICR7a2V5fSAtICR7dmFsdWV9YCk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH1cblxuICAgIHJldHVybiBbc2Vzc2lvbk9wdGlvbnNIYW5kbGUsIGFsbG9jc107XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICBpZiAoc2Vzc2lvbk9wdGlvbnNIYW5kbGUgIT09IDApIHtcbiAgICAgIHdhc20uX09ydFJlbGVhc2VTZXNzaW9uT3B0aW9ucyhzZXNzaW9uT3B0aW9uc0hhbmRsZSk7XG4gICAgfVxuICAgIGFsbG9jcy5mb3JFYWNoKHdhc20uX2ZyZWUpO1xuICAgIHRocm93IGU7XG4gIH1cbn07XG4iLCIvLyBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cblxuaW1wb3J0IHtnZXRJbnN0YW5jZX0gZnJvbSAnLi93YXNtLWZhY3RvcnknO1xuXG5leHBvcnQgY29uc3QgYWxsb2NXYXNtU3RyaW5nID0gKGRhdGE6IHN0cmluZywgYWxsb2NzOiBudW1iZXJbXSk6IG51bWJlciA9PiB7XG4gIGNvbnN0IHdhc20gPSBnZXRJbnN0YW5jZSgpO1xuXG4gIGNvbnN0IGRhdGFMZW5ndGggPSB3YXNtLmxlbmd0aEJ5dGVzVVRGOChkYXRhKSArIDE7XG4gIGNvbnN0IGRhdGFPZmZzZXQgPSB3YXNtLl9tYWxsb2MoZGF0YUxlbmd0aCk7XG4gIHdhc20uc3RyaW5nVG9VVEY4KGRhdGEsIGRhdGFPZmZzZXQsIGRhdGFMZW5ndGgpO1xuICBhbGxvY3MucHVzaChkYXRhT2Zmc2V0KTtcblxuICByZXR1cm4gZGF0YU9mZnNldDtcbn07XG4iLCIvLyBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cblxuaW1wb3J0IHtJbmZlcmVuY2VTZXNzaW9uLCBUZW5zb3J9IGZyb20gJ29ubnhydW50aW1lLWNvbW1vbic7XG5cbmltcG9ydCB7U2VyaWFsaXphYmxlTW9kZWxkYXRhLCBTZXJpYWxpemFibGVTZXNzaW9uTWV0YWRhdGEsIFNlcmlhbGl6YWJsZVRlbnNvcn0gZnJvbSAnLi9wcm94eS1tZXNzYWdlcyc7XG5pbXBvcnQge3NldFJ1bk9wdGlvbnN9IGZyb20gJy4vcnVuLW9wdGlvbnMnO1xuaW1wb3J0IHtzZXRTZXNzaW9uT3B0aW9uc30gZnJvbSAnLi9zZXNzaW9uLW9wdGlvbnMnO1xuaW1wb3J0IHthbGxvY1dhc21TdHJpbmd9IGZyb20gJy4vc3RyaW5nLXV0aWxzJztcbmltcG9ydCB7Z2V0SW5zdGFuY2V9IGZyb20gJy4vd2FzbS1mYWN0b3J5JztcblxuLyoqXG4gKiBpbml0aWFsaXplIE9SVCBlbnZpcm9ubWVudC5cbiAqIEBwYXJhbSBudW1UaHJlYWRzIFNldEdsb2JhbEludHJhT3BOdW1UaHJlYWRzKG51bVRocmVhZHMpXG4gKiBAcGFyYW0gbG9nZ2luZ0xldmVsIENyZWF0ZUVudihzdGF0aWNfY2FzdDxPcnRMb2dnaW5nTGV2ZWw+KGxvZ2dpbmdfbGV2ZWwpKVxuICovXG5leHBvcnQgY29uc3QgaW5pdE9ydCA9IChudW1UaHJlYWRzOiBudW1iZXIsIGxvZ2dpbmdMZXZlbDogbnVtYmVyKTogdm9pZCA9PiB7XG4gIGNvbnN0IGVycm9yQ29kZSA9IGdldEluc3RhbmNlKCkuX09ydEluaXQobnVtVGhyZWFkcywgbG9nZ2luZ0xldmVsKTtcbiAgaWYgKGVycm9yQ29kZSAhPT0gMCkge1xuICAgIHRocm93IG5ldyBFcnJvcihgQ2FuJ3QgaW5pdGlhbGl6ZSBvbm54cnVudGltZS4gZXJyb3IgY29kZSA9ICR7ZXJyb3JDb2RlfWApO1xuICB9XG59O1xuXG4vKipcbiAqICB0dXBsZSBlbGVtZW50cyBhcmU6IEluZmVyZW5jZVNlc3Npb24gSUQ7IGlucHV0TmFtZXNVVEY4RW5jb2RlZDsgb3V0cHV0TmFtZXNVVEY4RW5jb2RlZFxuICovXG50eXBlIFNlc3Npb25NZXRhZGF0YSA9IFtudW1iZXIsIG51bWJlcltdLCBudW1iZXJbXV07XG5cbmNvbnN0IGFjdGl2ZVNlc3Npb25zID0gbmV3IE1hcDxudW1iZXIsIFNlc3Npb25NZXRhZGF0YT4oKTtcblxuLyoqXG4gKiBjcmVhdGUgYW4gaW5zdGFuY2Ugb2YgSW5mZXJlbmNlU2Vzc2lvbi5cbiAqIEByZXR1cm5zIHRoZSBtZXRhZGF0YSBvZiBJbmZlcmVuY2VTZXNzaW9uLiAwLXZhbHVlIGhhbmRsZSBmb3IgZmFpbHVyZS5cbiAqL1xuZXhwb3J0IGNvbnN0IGNyZWF0ZVNlc3Npb25BbGxvY2F0ZSA9IChtb2RlbDogVWludDhBcnJheSk6IFtudW1iZXIsIG51bWJlcl0gPT4ge1xuICBjb25zdCB3YXNtID0gZ2V0SW5zdGFuY2UoKTtcbiAgY29uc3QgbW9kZWxEYXRhT2Zmc2V0ID0gd2FzbS5fbWFsbG9jKG1vZGVsLmJ5dGVMZW5ndGgpO1xuICB3YXNtLkhFQVBVOC5zZXQobW9kZWwsIG1vZGVsRGF0YU9mZnNldCk7XG4gIHJldHVybiBbbW9kZWxEYXRhT2Zmc2V0LCBtb2RlbC5ieXRlTGVuZ3RoXTtcbn07XG5cbmV4cG9ydCBjb25zdCBjcmVhdGVTZXNzaW9uRmluYWxpemUgPVxuICAgIChtb2RlbERhdGE6IFNlcmlhbGl6YWJsZU1vZGVsZGF0YSwgb3B0aW9ucz86IEluZmVyZW5jZVNlc3Npb24uU2Vzc2lvbk9wdGlvbnMpOiBTZXJpYWxpemFibGVTZXNzaW9uTWV0YWRhdGEgPT4ge1xuICAgICAgY29uc3Qgd2FzbSA9IGdldEluc3RhbmNlKCk7XG5cbiAgICAgIGxldCBzZXNzaW9uSGFuZGxlID0gMDtcbiAgICAgIGxldCBzZXNzaW9uT3B0aW9uc0hhbmRsZSA9IDA7XG4gICAgICBsZXQgYWxsb2NzOiBudW1iZXJbXSA9IFtdO1xuXG4gICAgICB0cnkge1xuICAgICAgICBbc2Vzc2lvbk9wdGlvbnNIYW5kbGUsIGFsbG9jc10gPSBzZXRTZXNzaW9uT3B0aW9ucyhvcHRpb25zKTtcblxuICAgICAgICBzZXNzaW9uSGFuZGxlID0gd2FzbS5fT3J0Q3JlYXRlU2Vzc2lvbihtb2RlbERhdGFbMF0sIG1vZGVsRGF0YVsxXSwgc2Vzc2lvbk9wdGlvbnNIYW5kbGUpO1xuICAgICAgICBpZiAoc2Vzc2lvbkhhbmRsZSA9PT0gMCkge1xuICAgICAgICAgIHRocm93IG5ldyBFcnJvcignQ2FuXFwndCBjcmVhdGUgYSBzZXNzaW9uJyk7XG4gICAgICAgIH1cbiAgICAgIH0gZmluYWxseSB7XG4gICAgICAgIHdhc20uX2ZyZWUobW9kZWxEYXRhWzBdKTtcbiAgICAgICAgd2FzbS5fT3J0UmVsZWFzZVNlc3Npb25PcHRpb25zKHNlc3Npb25PcHRpb25zSGFuZGxlKTtcbiAgICAgICAgYWxsb2NzLmZvckVhY2god2FzbS5fZnJlZSk7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IGlucHV0Q291bnQgPSB3YXNtLl9PcnRHZXRJbnB1dENvdW50KHNlc3Npb25IYW5kbGUpO1xuICAgICAgY29uc3Qgb3V0cHV0Q291bnQgPSB3YXNtLl9PcnRHZXRPdXRwdXRDb3VudChzZXNzaW9uSGFuZGxlKTtcblxuICAgICAgY29uc3QgaW5wdXROYW1lcyA9IFtdO1xuICAgICAgY29uc3QgaW5wdXROYW1lc1VURjhFbmNvZGVkID0gW107XG4gICAgICBjb25zdCBvdXRwdXROYW1lcyA9IFtdO1xuICAgICAgY29uc3Qgb3V0cHV0TmFtZXNVVEY4RW5jb2RlZCA9IFtdO1xuICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBpbnB1dENvdW50OyBpKyspIHtcbiAgICAgICAgY29uc3QgbmFtZSA9IHdhc20uX09ydEdldElucHV0TmFtZShzZXNzaW9uSGFuZGxlLCBpKTtcbiAgICAgICAgaWYgKG5hbWUgPT09IDApIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0NhblxcJ3QgZ2V0IGFuIGlucHV0IG5hbWUnKTtcbiAgICAgICAgfVxuICAgICAgICBpbnB1dE5hbWVzVVRGOEVuY29kZWQucHVzaChuYW1lKTtcbiAgICAgICAgaW5wdXROYW1lcy5wdXNoKHdhc20uVVRGOFRvU3RyaW5nKG5hbWUpKTtcbiAgICAgIH1cbiAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgb3V0cHV0Q291bnQ7IGkrKykge1xuICAgICAgICBjb25zdCBuYW1lID0gd2FzbS5fT3J0R2V0T3V0cHV0TmFtZShzZXNzaW9uSGFuZGxlLCBpKTtcbiAgICAgICAgaWYgKG5hbWUgPT09IDApIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0NhblxcJ3QgZ2V0IGFuIG91dHB1dCBuYW1lJyk7XG4gICAgICAgIH1cbiAgICAgICAgb3V0cHV0TmFtZXNVVEY4RW5jb2RlZC5wdXNoKG5hbWUpO1xuICAgICAgICBvdXRwdXROYW1lcy5wdXNoKHdhc20uVVRGOFRvU3RyaW5nKG5hbWUpKTtcbiAgICAgIH1cblxuICAgICAgYWN0aXZlU2Vzc2lvbnMuc2V0KHNlc3Npb25IYW5kbGUsIFtzZXNzaW9uSGFuZGxlLCBpbnB1dE5hbWVzVVRGOEVuY29kZWQsIG91dHB1dE5hbWVzVVRGOEVuY29kZWRdKTtcbiAgICAgIHJldHVybiBbc2Vzc2lvbkhhbmRsZSwgaW5wdXROYW1lcywgb3V0cHV0TmFtZXNdO1xuICAgIH07XG5cblxuLyoqXG4gKiBjcmVhdGUgYW4gaW5zdGFuY2Ugb2YgSW5mZXJlbmNlU2Vzc2lvbi5cbiAqIEByZXR1cm5zIHRoZSBtZXRhZGF0YSBvZiBJbmZlcmVuY2VTZXNzaW9uLiAwLXZhbHVlIGhhbmRsZSBmb3IgZmFpbHVyZS5cbiAqL1xuZXhwb3J0IGNvbnN0IGNyZWF0ZVNlc3Npb24gPVxuICAgIChtb2RlbDogVWludDhBcnJheSwgb3B0aW9ucz86IEluZmVyZW5jZVNlc3Npb24uU2Vzc2lvbk9wdGlvbnMpOiBTZXJpYWxpemFibGVTZXNzaW9uTWV0YWRhdGEgPT4ge1xuICAgICAgY29uc3QgbW9kZWxEYXRhOiBTZXJpYWxpemFibGVNb2RlbGRhdGEgPSBjcmVhdGVTZXNzaW9uQWxsb2NhdGUobW9kZWwpO1xuICAgICAgcmV0dXJuIGNyZWF0ZVNlc3Npb25GaW5hbGl6ZShtb2RlbERhdGEsIG9wdGlvbnMpO1xuICAgIH07XG5cbmV4cG9ydCBjb25zdCByZWxlYXNlU2Vzc2lvbiA9IChzZXNzaW9uSWQ6IG51bWJlcik6IHZvaWQgPT4ge1xuICBjb25zdCB3YXNtID0gZ2V0SW5zdGFuY2UoKTtcbiAgY29uc3Qgc2Vzc2lvbiA9IGFjdGl2ZVNlc3Npb25zLmdldChzZXNzaW9uSWQpO1xuICBpZiAoIXNlc3Npb24pIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ2ludmFsaWQgc2Vzc2lvbiBpZCcpO1xuICB9XG4gIGNvbnN0IHNlc3Npb25IYW5kbGUgPSBzZXNzaW9uWzBdO1xuICBjb25zdCBpbnB1dE5hbWVzVVRGOEVuY29kZWQgPSBzZXNzaW9uWzFdO1xuICBjb25zdCBvdXRwdXROYW1lc1VURjhFbmNvZGVkID0gc2Vzc2lvblsyXTtcblxuICBpbnB1dE5hbWVzVVRGOEVuY29kZWQuZm9yRWFjaCh3YXNtLl9PcnRGcmVlKTtcbiAgb3V0cHV0TmFtZXNVVEY4RW5jb2RlZC5mb3JFYWNoKHdhc20uX09ydEZyZWUpO1xuICB3YXNtLl9PcnRSZWxlYXNlU2Vzc2lvbihzZXNzaW9uSGFuZGxlKTtcbiAgYWN0aXZlU2Vzc2lvbnMuZGVsZXRlKHNlc3Npb25JZCk7XG59O1xuXG4vKipcbiAqIENvcGllZCBmcm9tIE9OTlggZGVmaW5pdGlvbi4gVXNlIHRoaXMgdG8gZHJvcCBkZXBlbmRlbmN5ICdvbm54X3Byb3RvJyB0byBkZWNyZWFzZSBjb21waWxlZCAuanMgZmlsZSBzaXplLlxuICovXG5jb25zdCBlbnVtIERhdGFUeXBlIHtcbiAgdW5kZWZpbmVkID0gMCxcbiAgZmxvYXQgPSAxLFxuICB1aW50OCA9IDIsXG4gIGludDggPSAzLFxuICB1aW50MTYgPSA0LFxuICBpbnQxNiA9IDUsXG4gIGludDMyID0gNixcbiAgaW50NjQgPSA3LFxuICBzdHJpbmcgPSA4LFxuICBib29sID0gOSxcbiAgZmxvYXQxNiA9IDEwLFxuICBkb3VibGUgPSAxMSxcbiAgdWludDMyID0gMTIsXG4gIHVpbnQ2NCA9IDEzLFxuICBjb21wbGV4NjQgPSAxNCxcbiAgY29tcGxleDEyOCA9IDE1LFxuICBiZmxvYXQxNiA9IDE2XG59XG5cblxuY29uc3QgdGVuc29yRGF0YVR5cGVTdHJpbmdUb0VudW0gPSAodHlwZTogc3RyaW5nKTogRGF0YVR5cGUgPT4ge1xuICBzd2l0Y2ggKHR5cGUpIHtcbiAgICBjYXNlICdpbnQ4JzpcbiAgICAgIHJldHVybiBEYXRhVHlwZS5pbnQ4O1xuICAgIGNhc2UgJ3VpbnQ4JzpcbiAgICAgIHJldHVybiBEYXRhVHlwZS51aW50ODtcbiAgICBjYXNlICdib29sJzpcbiAgICAgIHJldHVybiBEYXRhVHlwZS5ib29sO1xuICAgIGNhc2UgJ2ludDE2JzpcbiAgICAgIHJldHVybiBEYXRhVHlwZS5pbnQxNjtcbiAgICBjYXNlICd1aW50MTYnOlxuICAgICAgcmV0dXJuIERhdGFUeXBlLnVpbnQxNjtcbiAgICBjYXNlICdpbnQzMic6XG4gICAgICByZXR1cm4gRGF0YVR5cGUuaW50MzI7XG4gICAgY2FzZSAndWludDMyJzpcbiAgICAgIHJldHVybiBEYXRhVHlwZS51aW50MzI7XG4gICAgY2FzZSAnZmxvYXQzMic6XG4gICAgICByZXR1cm4gRGF0YVR5cGUuZmxvYXQ7XG4gICAgY2FzZSAnZmxvYXQ2NCc6XG4gICAgICByZXR1cm4gRGF0YVR5cGUuZG91YmxlO1xuICAgIGNhc2UgJ3N0cmluZyc6XG4gICAgICByZXR1cm4gRGF0YVR5cGUuc3RyaW5nO1xuICAgIGNhc2UgJ2ludDY0JzpcbiAgICAgIHJldHVybiBEYXRhVHlwZS5pbnQ2NDtcbiAgICBjYXNlICd1aW50NjQnOlxuICAgICAgcmV0dXJuIERhdGFUeXBlLnVpbnQ2NDtcblxuICAgIGRlZmF1bHQ6XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYHVuc3VwcG9ydGVkIGRhdGEgdHlwZTogJHt0eXBlfWApO1xuICB9XG59O1xuXG5jb25zdCB0ZW5zb3JEYXRhVHlwZUVudW1Ub1N0cmluZyA9ICh0eXBlUHJvdG86IERhdGFUeXBlKTogVGVuc29yLlR5cGUgPT4ge1xuICBzd2l0Y2ggKHR5cGVQcm90bykge1xuICAgIGNhc2UgRGF0YVR5cGUuaW50ODpcbiAgICAgIHJldHVybiAnaW50OCc7XG4gICAgY2FzZSBEYXRhVHlwZS51aW50ODpcbiAgICAgIHJldHVybiAndWludDgnO1xuICAgIGNhc2UgRGF0YVR5cGUuYm9vbDpcbiAgICAgIHJldHVybiAnYm9vbCc7XG4gICAgY2FzZSBEYXRhVHlwZS5pbnQxNjpcbiAgICAgIHJldHVybiAnaW50MTYnO1xuICAgIGNhc2UgRGF0YVR5cGUudWludDE2OlxuICAgICAgcmV0dXJuICd1aW50MTYnO1xuICAgIGNhc2UgRGF0YVR5cGUuaW50MzI6XG4gICAgICByZXR1cm4gJ2ludDMyJztcbiAgICBjYXNlIERhdGFUeXBlLnVpbnQzMjpcbiAgICAgIHJldHVybiAndWludDMyJztcbiAgICBjYXNlIERhdGFUeXBlLmZsb2F0OlxuICAgICAgcmV0dXJuICdmbG9hdDMyJztcbiAgICBjYXNlIERhdGFUeXBlLmRvdWJsZTpcbiAgICAgIHJldHVybiAnZmxvYXQ2NCc7XG4gICAgY2FzZSBEYXRhVHlwZS5zdHJpbmc6XG4gICAgICByZXR1cm4gJ3N0cmluZyc7XG4gICAgY2FzZSBEYXRhVHlwZS5pbnQ2NDpcbiAgICAgIHJldHVybiAnaW50NjQnO1xuICAgIGNhc2UgRGF0YVR5cGUudWludDY0OlxuICAgICAgcmV0dXJuICd1aW50NjQnO1xuXG4gICAgZGVmYXVsdDpcbiAgICAgIHRocm93IG5ldyBFcnJvcihgdW5zdXBwb3J0ZWQgZGF0YSB0eXBlOiAke3R5cGVQcm90b31gKTtcbiAgfVxufTtcblxuY29uc3QgbnVtZXJpY1RlbnNvclR5cGVUb1R5cGVkQXJyYXkgPSAodHlwZTogVGVuc29yLlR5cGUpOiBGbG9hdDMyQXJyYXlDb25zdHJ1Y3RvcnxVaW50OEFycmF5Q29uc3RydWN0b3J8XG4gICAgSW50OEFycmF5Q29uc3RydWN0b3J8VWludDE2QXJyYXlDb25zdHJ1Y3RvcnxJbnQxNkFycmF5Q29uc3RydWN0b3J8SW50MzJBcnJheUNvbnN0cnVjdG9yfEJpZ0ludDY0QXJyYXlDb25zdHJ1Y3RvcnxcbiAgICBVaW50OEFycmF5Q29uc3RydWN0b3J8RmxvYXQ2NEFycmF5Q29uc3RydWN0b3J8VWludDMyQXJyYXlDb25zdHJ1Y3RvcnxCaWdVaW50NjRBcnJheUNvbnN0cnVjdG9yID0+IHtcbiAgICAgIHN3aXRjaCAodHlwZSkge1xuICAgICAgICBjYXNlICdmbG9hdDMyJzpcbiAgICAgICAgICByZXR1cm4gRmxvYXQzMkFycmF5O1xuICAgICAgICBjYXNlICd1aW50OCc6XG4gICAgICAgICAgcmV0dXJuIFVpbnQ4QXJyYXk7XG4gICAgICAgIGNhc2UgJ2ludDgnOlxuICAgICAgICAgIHJldHVybiBJbnQ4QXJyYXk7XG4gICAgICAgIGNhc2UgJ3VpbnQxNic6XG4gICAgICAgICAgcmV0dXJuIFVpbnQxNkFycmF5O1xuICAgICAgICBjYXNlICdpbnQxNic6XG4gICAgICAgICAgcmV0dXJuIEludDE2QXJyYXk7XG4gICAgICAgIGNhc2UgJ2ludDMyJzpcbiAgICAgICAgICByZXR1cm4gSW50MzJBcnJheTtcbiAgICAgICAgY2FzZSAnYm9vbCc6XG4gICAgICAgICAgcmV0dXJuIFVpbnQ4QXJyYXk7XG4gICAgICAgIGNhc2UgJ2Zsb2F0NjQnOlxuICAgICAgICAgIHJldHVybiBGbG9hdDY0QXJyYXk7XG4gICAgICAgIGNhc2UgJ3VpbnQzMic6XG4gICAgICAgICAgcmV0dXJuIFVpbnQzMkFycmF5O1xuICAgICAgICBjYXNlICdpbnQ2NCc6XG4gICAgICAgICAgcmV0dXJuIEJpZ0ludDY0QXJyYXk7XG4gICAgICAgIGNhc2UgJ3VpbnQ2NCc6XG4gICAgICAgICAgcmV0dXJuIEJpZ1VpbnQ2NEFycmF5O1xuICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgdW5zdXBwb3J0ZWQgdHlwZTogJHt0eXBlfWApO1xuICAgICAgfVxuICAgIH07XG5cbi8qKlxuICogcGVyZm9ybSBpbmZlcmVuY2UgcnVuXG4gKi9cbmV4cG9ydCBjb25zdCBydW4gPVxuICAgIChzZXNzaW9uSWQ6IG51bWJlciwgaW5wdXRJbmRpY2VzOiBudW1iZXJbXSwgaW5wdXRzOiBTZXJpYWxpemFibGVUZW5zb3JbXSwgb3V0cHV0SW5kaWNlczogbnVtYmVyW10sXG4gICAgIG9wdGlvbnM6IEluZmVyZW5jZVNlc3Npb24uUnVuT3B0aW9ucyk6IFNlcmlhbGl6YWJsZVRlbnNvcltdID0+IHtcbiAgICAgIGNvbnN0IHdhc20gPSBnZXRJbnN0YW5jZSgpO1xuICAgICAgY29uc3Qgc2Vzc2lvbiA9IGFjdGl2ZVNlc3Npb25zLmdldChzZXNzaW9uSWQpO1xuICAgICAgaWYgKCFzZXNzaW9uKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignaW52YWxpZCBzZXNzaW9uIGlkJyk7XG4gICAgICB9XG4gICAgICBjb25zdCBzZXNzaW9uSGFuZGxlID0gc2Vzc2lvblswXTtcbiAgICAgIGNvbnN0IGlucHV0TmFtZXNVVEY4RW5jb2RlZCA9IHNlc3Npb25bMV07XG4gICAgICBjb25zdCBvdXRwdXROYW1lc1VURjhFbmNvZGVkID0gc2Vzc2lvblsyXTtcblxuICAgICAgY29uc3QgaW5wdXRDb3VudCA9IGlucHV0SW5kaWNlcy5sZW5ndGg7XG4gICAgICBjb25zdCBvdXRwdXRDb3VudCA9IG91dHB1dEluZGljZXMubGVuZ3RoO1xuXG4gICAgICBsZXQgcnVuT3B0aW9uc0hhbmRsZSA9IDA7XG4gICAgICBsZXQgcnVuT3B0aW9uc0FsbG9jczogbnVtYmVyW10gPSBbXTtcblxuICAgICAgY29uc3QgaW5wdXRWYWx1ZXM6IG51bWJlcltdID0gW107XG4gICAgICBjb25zdCBpbnB1dEFsbG9jczogbnVtYmVyW10gPSBbXTtcblxuICAgICAgdHJ5IHtcbiAgICAgICAgW3J1bk9wdGlvbnNIYW5kbGUsIHJ1bk9wdGlvbnNBbGxvY3NdID0gc2V0UnVuT3B0aW9ucyhvcHRpb25zKTtcblxuICAgICAgICAvLyBjcmVhdGUgaW5wdXQgdGVuc29yc1xuICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGlucHV0Q291bnQ7IGkrKykge1xuICAgICAgICAgIGNvbnN0IGRhdGFUeXBlID0gaW5wdXRzW2ldWzBdO1xuICAgICAgICAgIGNvbnN0IGRpbXMgPSBpbnB1dHNbaV1bMV07XG4gICAgICAgICAgY29uc3QgZGF0YSA9IGlucHV0c1tpXVsyXTtcblxuICAgICAgICAgIGxldCBkYXRhT2Zmc2V0OiBudW1iZXI7XG4gICAgICAgICAgbGV0IGRhdGFCeXRlTGVuZ3RoOiBudW1iZXI7XG5cbiAgICAgICAgICBpZiAoQXJyYXkuaXNBcnJheShkYXRhKSkge1xuICAgICAgICAgICAgLy8gc3RyaW5nIHRlbnNvclxuICAgICAgICAgICAgZGF0YUJ5dGVMZW5ndGggPSA0ICogZGF0YS5sZW5ndGg7XG4gICAgICAgICAgICBkYXRhT2Zmc2V0ID0gd2FzbS5fbWFsbG9jKGRhdGFCeXRlTGVuZ3RoKTtcbiAgICAgICAgICAgIGlucHV0QWxsb2NzLnB1c2goZGF0YU9mZnNldCk7XG4gICAgICAgICAgICBsZXQgZGF0YUluZGV4ID0gZGF0YU9mZnNldCAvIDQ7XG4gICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGRhdGEubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgaWYgKHR5cGVvZiBkYXRhW2ldICE9PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoYHRlbnNvciBkYXRhIGF0IGluZGV4ICR7aX0gaXMgbm90IGEgc3RyaW5nYCk7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgd2FzbS5IRUFQVTMyW2RhdGFJbmRleCsrXSA9IGFsbG9jV2FzbVN0cmluZyhkYXRhW2ldLCBpbnB1dEFsbG9jcyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGRhdGFCeXRlTGVuZ3RoID0gZGF0YS5ieXRlTGVuZ3RoO1xuICAgICAgICAgICAgZGF0YU9mZnNldCA9IHdhc20uX21hbGxvYyhkYXRhQnl0ZUxlbmd0aCk7XG4gICAgICAgICAgICBpbnB1dEFsbG9jcy5wdXNoKGRhdGFPZmZzZXQpO1xuICAgICAgICAgICAgd2FzbS5IRUFQVTguc2V0KG5ldyBVaW50OEFycmF5KGRhdGEuYnVmZmVyLCBkYXRhLmJ5dGVPZmZzZXQsIGRhdGFCeXRlTGVuZ3RoKSwgZGF0YU9mZnNldCk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgY29uc3Qgc3RhY2sgPSB3YXNtLnN0YWNrU2F2ZSgpO1xuICAgICAgICAgIGNvbnN0IGRpbXNPZmZzZXQgPSB3YXNtLnN0YWNrQWxsb2MoNCAqIGRpbXMubGVuZ3RoKTtcbiAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgbGV0IGRpbUluZGV4ID0gZGltc09mZnNldCAvIDQ7XG4gICAgICAgICAgICBkaW1zLmZvckVhY2goZCA9PiB3YXNtLkhFQVAzMltkaW1JbmRleCsrXSA9IGQpO1xuICAgICAgICAgICAgY29uc3QgdGVuc29yID0gd2FzbS5fT3J0Q3JlYXRlVGVuc29yKFxuICAgICAgICAgICAgICAgIHRlbnNvckRhdGFUeXBlU3RyaW5nVG9FbnVtKGRhdGFUeXBlKSwgZGF0YU9mZnNldCwgZGF0YUJ5dGVMZW5ndGgsIGRpbXNPZmZzZXQsIGRpbXMubGVuZ3RoKTtcbiAgICAgICAgICAgIGlmICh0ZW5zb3IgPT09IDApIHtcbiAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdDYW5cXCd0IGNyZWF0ZSBhIHRlbnNvcicpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaW5wdXRWYWx1ZXMucHVzaCh0ZW5zb3IpO1xuICAgICAgICAgIH0gZmluYWxseSB7XG4gICAgICAgICAgICB3YXNtLnN0YWNrUmVzdG9yZShzdGFjayk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgYmVmb3JlUnVuU3RhY2sgPSB3YXNtLnN0YWNrU2F2ZSgpO1xuICAgICAgICBjb25zdCBpbnB1dFZhbHVlc09mZnNldCA9IHdhc20uc3RhY2tBbGxvYyhpbnB1dENvdW50ICogNCk7XG4gICAgICAgIGNvbnN0IGlucHV0TmFtZXNPZmZzZXQgPSB3YXNtLnN0YWNrQWxsb2MoaW5wdXRDb3VudCAqIDQpO1xuICAgICAgICBjb25zdCBvdXRwdXRWYWx1ZXNPZmZzZXQgPSB3YXNtLnN0YWNrQWxsb2Mob3V0cHV0Q291bnQgKiA0KTtcbiAgICAgICAgY29uc3Qgb3V0cHV0TmFtZXNPZmZzZXQgPSB3YXNtLnN0YWNrQWxsb2Mob3V0cHV0Q291bnQgKiA0KTtcblxuICAgICAgICB0cnkge1xuICAgICAgICAgIGxldCBpbnB1dFZhbHVlc0luZGV4ID0gaW5wdXRWYWx1ZXNPZmZzZXQgLyA0O1xuICAgICAgICAgIGxldCBpbnB1dE5hbWVzSW5kZXggPSBpbnB1dE5hbWVzT2Zmc2V0IC8gNDtcbiAgICAgICAgICBsZXQgb3V0cHV0VmFsdWVzSW5kZXggPSBvdXRwdXRWYWx1ZXNPZmZzZXQgLyA0O1xuICAgICAgICAgIGxldCBvdXRwdXROYW1lc0luZGV4ID0gb3V0cHV0TmFtZXNPZmZzZXQgLyA0O1xuICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgaW5wdXRDb3VudDsgaSsrKSB7XG4gICAgICAgICAgICB3YXNtLkhFQVBVMzJbaW5wdXRWYWx1ZXNJbmRleCsrXSA9IGlucHV0VmFsdWVzW2ldO1xuICAgICAgICAgICAgd2FzbS5IRUFQVTMyW2lucHV0TmFtZXNJbmRleCsrXSA9IGlucHV0TmFtZXNVVEY4RW5jb2RlZFtpbnB1dEluZGljZXNbaV1dO1xuICAgICAgICAgIH1cbiAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IG91dHB1dENvdW50OyBpKyspIHtcbiAgICAgICAgICAgIHdhc20uSEVBUFUzMltvdXRwdXRWYWx1ZXNJbmRleCsrXSA9IDA7XG4gICAgICAgICAgICB3YXNtLkhFQVBVMzJbb3V0cHV0TmFtZXNJbmRleCsrXSA9IG91dHB1dE5hbWVzVVRGOEVuY29kZWRbb3V0cHV0SW5kaWNlc1tpXV07XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgLy8gc3VwcG9ydCBSdW5PcHRpb25zXG4gICAgICAgICAgbGV0IGVycm9yQ29kZSA9IHdhc20uX09ydFJ1bihcbiAgICAgICAgICAgICAgc2Vzc2lvbkhhbmRsZSwgaW5wdXROYW1lc09mZnNldCwgaW5wdXRWYWx1ZXNPZmZzZXQsIGlucHV0Q291bnQsIG91dHB1dE5hbWVzT2Zmc2V0LCBvdXRwdXRDb3VudCxcbiAgICAgICAgICAgICAgb3V0cHV0VmFsdWVzT2Zmc2V0LCBydW5PcHRpb25zSGFuZGxlKTtcblxuICAgICAgICAgIGNvbnN0IG91dHB1dDogU2VyaWFsaXphYmxlVGVuc29yW10gPSBbXTtcblxuICAgICAgICAgIGlmIChlcnJvckNvZGUgPT09IDApIHtcbiAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgb3V0cHV0Q291bnQ7IGkrKykge1xuICAgICAgICAgICAgICBjb25zdCB0ZW5zb3IgPSB3YXNtLkhFQVBVMzJbb3V0cHV0VmFsdWVzT2Zmc2V0IC8gNCArIGldO1xuXG4gICAgICAgICAgICAgIGNvbnN0IGJlZm9yZUdldFRlbnNvckRhdGFTdGFjayA9IHdhc20uc3RhY2tTYXZlKCk7XG4gICAgICAgICAgICAgIC8vIHN0YWNrIGFsbG9jYXRlIDQgcG9pbnRlciB2YWx1ZVxuICAgICAgICAgICAgICBjb25zdCB0ZW5zb3JEYXRhT2Zmc2V0ID0gd2FzbS5zdGFja0FsbG9jKDQgKiA0KTtcblxuICAgICAgICAgICAgICBsZXQgdHlwZTogVGVuc29yLlR5cGV8dW5kZWZpbmVkLCBkYXRhT2Zmc2V0ID0gMDtcbiAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICBlcnJvckNvZGUgPSB3YXNtLl9PcnRHZXRUZW5zb3JEYXRhKFxuICAgICAgICAgICAgICAgICAgICB0ZW5zb3IsIHRlbnNvckRhdGFPZmZzZXQsIHRlbnNvckRhdGFPZmZzZXQgKyA0LCB0ZW5zb3JEYXRhT2Zmc2V0ICsgOCwgdGVuc29yRGF0YU9mZnNldCArIDEyKTtcbiAgICAgICAgICAgICAgICBpZiAoZXJyb3JDb2RlICE9PSAwKSB7XG4gICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYENhbid0IGFjY2VzcyBvdXRwdXQgdGVuc29yIGRhdGEuIGVycm9yIGNvZGUgPSAke2Vycm9yQ29kZX1gKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgbGV0IHRlbnNvckRhdGFJbmRleCA9IHRlbnNvckRhdGFPZmZzZXQgLyA0O1xuICAgICAgICAgICAgICAgIGNvbnN0IGRhdGFUeXBlID0gd2FzbS5IRUFQVTMyW3RlbnNvckRhdGFJbmRleCsrXTtcbiAgICAgICAgICAgICAgICBkYXRhT2Zmc2V0ID0gd2FzbS5IRUFQVTMyW3RlbnNvckRhdGFJbmRleCsrXTtcbiAgICAgICAgICAgICAgICBjb25zdCBkaW1zT2Zmc2V0ID0gd2FzbS5IRUFQVTMyW3RlbnNvckRhdGFJbmRleCsrXTtcbiAgICAgICAgICAgICAgICBjb25zdCBkaW1zTGVuZ3RoID0gd2FzbS5IRUFQVTMyW3RlbnNvckRhdGFJbmRleCsrXTtcbiAgICAgICAgICAgICAgICBjb25zdCBkaW1zID0gW107XG4gICAgICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBkaW1zTGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgIGRpbXMucHVzaCh3YXNtLkhFQVBVMzJbZGltc09mZnNldCAvIDQgKyBpXSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHdhc20uX09ydEZyZWUoZGltc09mZnNldCk7XG5cbiAgICAgICAgICAgICAgICBjb25zdCBzaXplID0gZGltcy5sZW5ndGggPT09IDAgPyAxIDogZGltcy5yZWR1Y2UoKGEsIGIpID0+IGEgKiBiKTtcbiAgICAgICAgICAgICAgICB0eXBlID0gdGVuc29yRGF0YVR5cGVFbnVtVG9TdHJpbmcoZGF0YVR5cGUpO1xuICAgICAgICAgICAgICAgIGlmICh0eXBlID09PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgICAgICAgY29uc3Qgc3RyaW5nRGF0YTogc3RyaW5nW10gPSBbXTtcbiAgICAgICAgICAgICAgICAgIGxldCBkYXRhSW5kZXggPSBkYXRhT2Zmc2V0IC8gNDtcbiAgICAgICAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgc2l6ZTsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IG9mZnNldCA9IHdhc20uSEVBUFUzMltkYXRhSW5kZXgrK107XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IG1heEJ5dGVzVG9SZWFkID0gaSA9PT0gc2l6ZSAtIDEgPyB1bmRlZmluZWQgOiB3YXNtLkhFQVBVMzJbZGF0YUluZGV4XSAtIG9mZnNldDtcbiAgICAgICAgICAgICAgICAgICAgc3RyaW5nRGF0YS5wdXNoKHdhc20uVVRGOFRvU3RyaW5nKG9mZnNldCwgbWF4Qnl0ZXNUb1JlYWQpKTtcbiAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgIG91dHB1dC5wdXNoKFt0eXBlLCBkaW1zLCBzdHJpbmdEYXRhXSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgIGNvbnN0IHR5cGVkQXJyYXlDb25zdHJ1Y3RvciA9IG51bWVyaWNUZW5zb3JUeXBlVG9UeXBlZEFycmF5KHR5cGUpO1xuICAgICAgICAgICAgICAgICAgY29uc3QgZGF0YSA9IG5ldyB0eXBlZEFycmF5Q29uc3RydWN0b3Ioc2l6ZSk7XG4gICAgICAgICAgICAgICAgICBuZXcgVWludDhBcnJheShkYXRhLmJ1ZmZlciwgZGF0YS5ieXRlT2Zmc2V0LCBkYXRhLmJ5dGVMZW5ndGgpXG4gICAgICAgICAgICAgICAgICAgICAgLnNldCh3YXNtLkhFQVBVOC5zdWJhcnJheShkYXRhT2Zmc2V0LCBkYXRhT2Zmc2V0ICsgZGF0YS5ieXRlTGVuZ3RoKSk7XG4gICAgICAgICAgICAgICAgICBvdXRwdXQucHVzaChbdHlwZSwgZGltcywgZGF0YV0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgfSBmaW5hbGx5IHtcbiAgICAgICAgICAgICAgICB3YXNtLnN0YWNrUmVzdG9yZShiZWZvcmVHZXRUZW5zb3JEYXRhU3RhY2spO1xuICAgICAgICAgICAgICAgIGlmICh0eXBlID09PSAnc3RyaW5nJyAmJiBkYXRhT2Zmc2V0KSB7XG4gICAgICAgICAgICAgICAgICB3YXNtLl9mcmVlKGRhdGFPZmZzZXQpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB3YXNtLl9PcnRSZWxlYXNlVGVuc29yKHRlbnNvcik7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG5cbiAgICAgICAgICBpZiAoZXJyb3JDb2RlID09PSAwKSB7XG4gICAgICAgICAgICByZXR1cm4gb3V0cHV0O1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYGZhaWxlZCB0byBjYWxsIE9ydFJ1bigpLiBlcnJvciBjb2RlID0gJHtlcnJvckNvZGV9LmApO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBmaW5hbGx5IHtcbiAgICAgICAgICB3YXNtLnN0YWNrUmVzdG9yZShiZWZvcmVSdW5TdGFjayk7XG4gICAgICAgIH1cbiAgICAgIH0gZmluYWxseSB7XG4gICAgICAgIGlucHV0VmFsdWVzLmZvckVhY2god2FzbS5fT3J0UmVsZWFzZVRlbnNvcik7XG4gICAgICAgIGlucHV0QWxsb2NzLmZvckVhY2god2FzbS5fZnJlZSk7XG5cbiAgICAgICAgd2FzbS5fT3J0UmVsZWFzZVJ1bk9wdGlvbnMocnVuT3B0aW9uc0hhbmRsZSk7XG4gICAgICAgIHJ1bk9wdGlvbnNBbGxvY3MuZm9yRWFjaCh3YXNtLl9mcmVlKTtcbiAgICAgIH1cbiAgICB9O1xuXG4vKipcbiAqIGVuZCBwcm9maWxpbmdcbiAqL1xuZXhwb3J0IGNvbnN0IGVuZFByb2ZpbGluZyA9IChzZXNzaW9uSWQ6IG51bWJlcik6IHZvaWQgPT4ge1xuICBjb25zdCB3YXNtID0gZ2V0SW5zdGFuY2UoKTtcbiAgY29uc3Qgc2Vzc2lvbiA9IGFjdGl2ZVNlc3Npb25zLmdldChzZXNzaW9uSWQpO1xuICBpZiAoIXNlc3Npb24pIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ2ludmFsaWQgc2Vzc2lvbiBpZCcpO1xuICB9XG4gIGNvbnN0IHNlc3Npb25IYW5kbGUgPSBzZXNzaW9uWzBdO1xuXG4gIC8vIHByb2ZpbGUgZmlsZSBuYW1lIGlzIG5vdCB1c2VkIHlldCwgYnV0IGl0IG11c3QgYmUgZnJlZWQuXG4gIGNvbnN0IHByb2ZpbGVGaWxlTmFtZSA9IHdhc20uX09ydEVuZFByb2ZpbGluZyhzZXNzaW9uSGFuZGxlKTtcbiAgaWYgKHByb2ZpbGVGaWxlTmFtZSA9PT0gMCkge1xuICAgIHRocm93IG5ldyBFcnJvcignQ2FuXFwndCBnZXQgYW4gcHJvZmlsZSBmaWxlIG5hbWUnKTtcbiAgfVxuICB3YXNtLl9PcnRGcmVlKHByb2ZpbGVGaWxlTmFtZSk7XG59O1xuXG5leHBvcnQgY29uc3QgZXh0cmFjdFRyYW5zZmVyYWJsZUJ1ZmZlcnMgPSAodGVuc29yczogcmVhZG9ubHkgU2VyaWFsaXphYmxlVGVuc29yW10pOiBBcnJheUJ1ZmZlckxpa2VbXSA9PiB7XG4gIGNvbnN0IGJ1ZmZlcnM6IEFycmF5QnVmZmVyTGlrZVtdID0gW107XG4gIGZvciAoY29uc3QgdGVuc29yIG9mIHRlbnNvcnMpIHtcbiAgICBjb25zdCBkYXRhID0gdGVuc29yWzJdO1xuICAgIGlmICghQXJyYXkuaXNBcnJheShkYXRhKSAmJiBkYXRhLmJ1ZmZlcikge1xuICAgICAgYnVmZmVycy5wdXNoKGRhdGEuYnVmZmVyKTtcbiAgICB9XG4gIH1cbiAgcmV0dXJuIGJ1ZmZlcnM7XG59O1xuIiwiLy8gQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXG5cbmltcG9ydCB7RW52fSBmcm9tICdvbm54cnVudGltZS1jb21tb24nO1xuaW1wb3J0ICogYXMgcGF0aCBmcm9tICdwYXRoJztcblxuaW1wb3J0IHtPcnRXYXNtTW9kdWxlfSBmcm9tICcuL2JpbmRpbmcvb3J0LXdhc20nO1xuaW1wb3J0IHtPcnRXYXNtVGhyZWFkZWRNb2R1bGV9IGZyb20gJy4vYmluZGluZy9vcnQtd2FzbS10aHJlYWRlZCc7XG5pbXBvcnQgb3J0V2FzbUZhY3RvcnkgZnJvbSAnLi9iaW5kaW5nL29ydC13YXNtLmpzJztcblxuY29uc3Qgb3J0V2FzbUZhY3RvcnlUaHJlYWRlZDogRW1zY3JpcHRlbk1vZHVsZUZhY3Rvcnk8T3J0V2FzbU1vZHVsZT4gPVxuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tcmVxdWlyZS1pbXBvcnRzXG4gICAgIUJVSUxEX0RFRlMuRElTQUJMRV9XQVNNX1RIUkVBRCA/IHJlcXVpcmUoJy4vYmluZGluZy9vcnQtd2FzbS10aHJlYWRlZC5qcycpIDogb3J0V2FzbUZhY3Rvcnk7XG5cbmxldCB3YXNtOiBPcnRXYXNtTW9kdWxlfHVuZGVmaW5lZDtcbmxldCBpbml0aWFsaXplZCA9IGZhbHNlO1xubGV0IGluaXRpYWxpemluZyA9IGZhbHNlO1xubGV0IGFib3J0ZWQgPSBmYWxzZTtcblxuY29uc3QgaXNNdWx0aVRocmVhZFN1cHBvcnRlZCA9ICgpOiBib29sZWFuID0+IHtcbiAgdHJ5IHtcbiAgICAvLyBJZiAnU2hhcmVkQXJyYXlCdWZmZXInIGlzIG5vdCBhdmFpbGFibGUsIFdlYkFzc2VtYmx5IHRocmVhZHMgd2lsbCBub3Qgd29yay5cbiAgICBpZiAodHlwZW9mIFNoYXJlZEFycmF5QnVmZmVyID09PSAndW5kZWZpbmVkJykge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIC8vIFRlc3QgZm9yIHRyYW5zZmVyYWJpbGl0eSBvZiBTQUJzIChmb3IgYnJvd3NlcnMuIG5lZWRlZCBmb3IgRmlyZWZveClcbiAgICAvLyBodHRwczovL2dyb3Vwcy5nb29nbGUuY29tL2ZvcnVtLyMhbXNnL21vemlsbGEuZGV2LnBsYXRmb3JtL0lIa0JabEhFVHBBL2R3c01OY2hXRVFBSlxuICAgIGlmICh0eXBlb2YgTWVzc2FnZUNoYW5uZWwgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICBuZXcgTWVzc2FnZUNoYW5uZWwoKS5wb3J0MS5wb3N0TWVzc2FnZShuZXcgU2hhcmVkQXJyYXlCdWZmZXIoMSkpO1xuICAgIH1cblxuICAgIC8vIFRlc3QgZm9yIFdlYkFzc2VtYmx5IHRocmVhZHMgY2FwYWJpbGl0eSAoZm9yIGJvdGggYnJvd3NlcnMgYW5kIE5vZGUuanMpXG4gICAgLy8gVGhpcyB0eXBlZCBhcnJheSBpcyBhIFdlYkFzc2VtYmx5IHByb2dyYW0gY29udGFpbmluZyB0aHJlYWRlZCBpbnN0cnVjdGlvbnMuXG4gICAgcmV0dXJuIFdlYkFzc2VtYmx5LnZhbGlkYXRlKG5ldyBVaW50OEFycmF5KFtcbiAgICAgIDAsIDk3LCAxMTUsIDEwOSwgMSwgMCwgIDAsICAwLCAxLCA0LCAxLCAgOTYsIDAsICAgMCwgIDMsIDIsIDEsICAwLCA1LFxuICAgICAgNCwgMSwgIDMsICAgMSwgICAxLCAxMCwgMTEsIDEsIDksIDAsIDY1LCAwLCAgMjU0LCAxNiwgMiwgMCwgMjYsIDExXG4gICAgXSkpO1xuICB9IGNhdGNoIChlKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG59O1xuXG5jb25zdCBpc1NpbWRTdXBwb3J0ZWQgPSAoKTogYm9vbGVhbiA9PiB7XG4gIHRyeSB7XG4gICAgLy8gVGVzdCBmb3IgV2ViQXNzZW1ibHkgU0lNRCBjYXBhYmlsaXR5IChmb3IgYm90aCBicm93c2VycyBhbmQgTm9kZS5qcylcbiAgICAvLyBUaGlzIHR5cGVkIGFycmF5IGlzIGEgV2ViQXNzZW1ibHkgcHJvZ3JhbSBjb250YWluaW5nIFNJTUQgaW5zdHJ1Y3Rpb25zLlxuXG4gICAgLy8gVGhlIGJpbmFyeSBkYXRhIGlzIGdlbmVyYXRlZCBmcm9tIHRoZSBmb2xsb3dpbmcgY29kZSBieSB3YXQyd2FzbTpcbiAgICAvL1xuICAgIC8vIChtb2R1bGVcbiAgICAvLyAgICh0eXBlICR0MCAoZnVuYykpXG4gICAgLy8gICAoZnVuYyAkZjAgKHR5cGUgJHQwKVxuICAgIC8vICAgICAoZHJvcFxuICAgIC8vICAgICAgIChpMzJ4NC5kb3RfaTE2eDhfc1xuICAgIC8vICAgICAgICAgKGk4eDE2LnNwbGF0XG4gICAgLy8gICAgICAgICAgIChpMzIuY29uc3QgMCkpXG4gICAgLy8gICAgICAgICAodjEyOC5jb25zdCBpMzJ4NCAweDAwMDAwMDAwIDB4MDAwMDAwMDAgMHgwMDAwMDAwMCAweDAwMDAwMDAwKSkpKSlcblxuICAgIHJldHVybiBXZWJBc3NlbWJseS52YWxpZGF0ZShuZXcgVWludDhBcnJheShbXG4gICAgICAwLCAgIDk3LCAxMTUsIDEwOSwgMSwgMCwgMCwgMCwgMSwgNCwgMSwgOTYsIDAsIDAsIDMsIDIsIDEsIDAsIDEwLCAzMCwgMSwgICAyOCwgIDAsIDY1LCAwLFxuICAgICAgMjUzLCAxNSwgMjUzLCAxMiwgIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsICAwLCAwLCAwLCAwLCAwLCAwLCAwLCAgMCwgIDI1MywgMTg2LCAxLCAyNiwgMTFcbiAgICBdKSk7XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cbn07XG5cbmNvbnN0IGdldFdhc21GaWxlTmFtZSA9ICh1c2VTaW1kOiBib29sZWFuLCB1c2VUaHJlYWRzOiBib29sZWFuKSA9PiB7XG4gIGlmICh1c2VUaHJlYWRzKSB7XG4gICAgcmV0dXJuIHVzZVNpbWQgPyAnb3J0LXdhc20tc2ltZC10aHJlYWRlZC53YXNtJyA6ICdvcnQtd2FzbS10aHJlYWRlZC53YXNtJztcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gdXNlU2ltZCA/ICdvcnQtd2FzbS1zaW1kLndhc20nIDogJ29ydC13YXNtLndhc20nO1xuICB9XG59O1xuXG5leHBvcnQgY29uc3QgaW5pdGlhbGl6ZVdlYkFzc2VtYmx5ID0gYXN5bmMoZmxhZ3M6IEVudi5XZWJBc3NlbWJseUZsYWdzKTogUHJvbWlzZTx2b2lkPiA9PiB7XG4gIGlmIChpbml0aWFsaXplZCkge1xuICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoKTtcbiAgfVxuICBpZiAoaW5pdGlhbGl6aW5nKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdtdWx0aXBsZSBjYWxscyB0byBcXCdpbml0aWFsaXplV2ViQXNzZW1ibHkoKVxcJyBkZXRlY3RlZC4nKTtcbiAgfVxuICBpZiAoYWJvcnRlZCkge1xuICAgIHRocm93IG5ldyBFcnJvcigncHJldmlvdXMgY2FsbCB0byBcXCdpbml0aWFsaXplV2ViQXNzZW1ibHkoKVxcJyBmYWlsZWQuJyk7XG4gIH1cblxuICBpbml0aWFsaXppbmcgPSB0cnVlO1xuXG4gIC8vIHdhc20gZmxhZ3MgYXJlIGFscmVhZHkgaW5pdGlhbGl6ZWRcbiAgY29uc3QgdGltZW91dCA9IGZsYWdzLmluaXRUaW1lb3V0ITtcbiAgY29uc3QgbnVtVGhyZWFkcyA9IGZsYWdzLm51bVRocmVhZHMhO1xuICBjb25zdCBzaW1kID0gZmxhZ3Muc2ltZCE7XG5cbiAgY29uc3QgdXNlVGhyZWFkcyA9IG51bVRocmVhZHMgPiAxICYmIGlzTXVsdGlUaHJlYWRTdXBwb3J0ZWQoKTtcbiAgY29uc3QgdXNlU2ltZCA9IHNpbWQgJiYgaXNTaW1kU3VwcG9ydGVkKCk7XG5cbiAgY29uc3Qgd2FzbVByZWZpeE92ZXJyaWRlID0gdHlwZW9mIGZsYWdzLndhc21QYXRocyA9PT0gJ3N0cmluZycgPyBmbGFncy53YXNtUGF0aHMgOiB1bmRlZmluZWQ7XG4gIGNvbnN0IHdhc21GaWxlTmFtZSA9IGdldFdhc21GaWxlTmFtZShmYWxzZSwgdXNlVGhyZWFkcyk7XG4gIGNvbnN0IHdhc21PdmVycmlkZUZpbGVOYW1lID0gZ2V0V2FzbUZpbGVOYW1lKHVzZVNpbWQsIHVzZVRocmVhZHMpO1xuICBjb25zdCB3YXNtUGF0aE92ZXJyaWRlID0gdHlwZW9mIGZsYWdzLndhc21QYXRocyA9PT0gJ29iamVjdCcgPyBmbGFncy53YXNtUGF0aHNbd2FzbU92ZXJyaWRlRmlsZU5hbWVdIDogdW5kZWZpbmVkO1xuXG4gIGxldCBpc1RpbWVvdXQgPSBmYWxzZTtcblxuICBjb25zdCB0YXNrczogQXJyYXk8UHJvbWlzZTx2b2lkPj4gPSBbXTtcblxuICAvLyBwcm9taXNlIGZvciB0aW1lb3V0XG4gIGlmICh0aW1lb3V0ID4gMCkge1xuICAgIHRhc2tzLnB1c2gobmV3IFByb21pc2UoKHJlc29sdmUpID0+IHtcbiAgICAgIHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgICBpc1RpbWVvdXQgPSB0cnVlO1xuICAgICAgICByZXNvbHZlKCk7XG4gICAgICB9LCB0aW1lb3V0KTtcbiAgICB9KSk7XG4gIH1cblxuICAvLyBwcm9taXNlIGZvciBtb2R1bGUgaW5pdGlhbGl6YXRpb25cbiAgdGFza3MucHVzaChuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgY29uc3QgZmFjdG9yeSA9IHVzZVRocmVhZHMgPyBvcnRXYXNtRmFjdG9yeVRocmVhZGVkIDogb3J0V2FzbUZhY3Rvcnk7XG4gICAgY29uc3QgY29uZmlnOiBQYXJ0aWFsPE9ydFdhc21Nb2R1bGU+ID0ge1xuICAgICAgbG9jYXRlRmlsZTogKGZpbGVOYW1lOiBzdHJpbmcsIHNjcmlwdERpcmVjdG9yeTogc3RyaW5nKSA9PiB7XG4gICAgICAgIGlmICghQlVJTERfREVGUy5ESVNBQkxFX1dBU01fVEhSRUFEICYmIHVzZVRocmVhZHMgJiYgZmlsZU5hbWUuZW5kc1dpdGgoJy53b3JrZXIuanMnKSAmJlxuICAgICAgICAgICAgdHlwZW9mIEJsb2IgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgcmV0dXJuIFVSTC5jcmVhdGVPYmplY3RVUkwobmV3IEJsb2IoXG4gICAgICAgICAgICAgIFtcbiAgICAgICAgICAgICAgICAvLyBUaGlzIHJlcXVpcmUoKSBmdW5jdGlvbiBpcyBoYW5kbGVkIGJ5IHdlYnBhY2sgdG8gbG9hZCBmaWxlIGNvbnRlbnQgb2YgdGhlIGNvcnJlc3BvbmRpbmcgLndvcmtlci5qc1xuICAgICAgICAgICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tcmVxdWlyZS1pbXBvcnRzXG4gICAgICAgICAgICAgICAgcmVxdWlyZSgnLi9iaW5kaW5nL29ydC13YXNtLXRocmVhZGVkLndvcmtlci5qcycpXG4gICAgICAgICAgICAgIF0sXG4gICAgICAgICAgICAgIHt0eXBlOiAndGV4dC9qYXZhc2NyaXB0J30pKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChmaWxlTmFtZSA9PT0gd2FzbUZpbGVOYW1lKSB7XG4gICAgICAgICAgY29uc3QgcHJlZml4OiBzdHJpbmcgPSB3YXNtUHJlZml4T3ZlcnJpZGUgPz8gc2NyaXB0RGlyZWN0b3J5O1xuICAgICAgICAgIHJldHVybiB3YXNtUGF0aE92ZXJyaWRlID8/IHByZWZpeCArIHdhc21PdmVycmlkZUZpbGVOYW1lO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHNjcmlwdERpcmVjdG9yeSArIGZpbGVOYW1lO1xuICAgICAgfVxuICAgIH07XG5cbiAgICBpZiAoIUJVSUxEX0RFRlMuRElTQUJMRV9XQVNNX1RIUkVBRCAmJiB1c2VUaHJlYWRzKSB7XG4gICAgICBpZiAodHlwZW9mIEJsb2IgPT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgIGNvbmZpZy5tYWluU2NyaXB0VXJsT3JCbG9iID0gcGF0aC5qb2luKF9fZGlybmFtZSwgJ29ydC13YXNtLXRocmVhZGVkLmpzJyk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBjb25zdCBzY3JpcHRTb3VyY2VDb2RlID0gYHZhciBvcnRXYXNtVGhyZWFkZWQ9KGZ1bmN0aW9uKCl7dmFyIF9zY3JpcHREaXI7cmV0dXJuICR7ZmFjdG9yeS50b1N0cmluZygpfX0pKCk7YDtcbiAgICAgICAgY29uZmlnLm1haW5TY3JpcHRVcmxPckJsb2IgPSBuZXcgQmxvYihbc2NyaXB0U291cmNlQ29kZV0sIHt0eXBlOiAndGV4dC9qYXZhc2NyaXB0J30pO1xuICAgICAgfVxuICAgIH1cblxuICAgIGZhY3RvcnkoY29uZmlnKS50aGVuKFxuICAgICAgICAvLyB3YXNtIG1vZHVsZSBpbml0aWFsaXplZCBzdWNjZXNzZnVsbHlcbiAgICAgICAgbW9kdWxlID0+IHtcbiAgICAgICAgICBpbml0aWFsaXppbmcgPSBmYWxzZTtcbiAgICAgICAgICBpbml0aWFsaXplZCA9IHRydWU7XG4gICAgICAgICAgd2FzbSA9IG1vZHVsZTtcbiAgICAgICAgICByZXNvbHZlKCk7XG4gICAgICAgIH0sXG4gICAgICAgIC8vIHdhc20gbW9kdWxlIGZhaWxlZCB0byBpbml0aWFsaXplXG4gICAgICAgICh3aGF0KSA9PiB7XG4gICAgICAgICAgaW5pdGlhbGl6aW5nID0gZmFsc2U7XG4gICAgICAgICAgYWJvcnRlZCA9IHRydWU7XG4gICAgICAgICAgcmVqZWN0KHdoYXQpO1xuICAgICAgICB9KTtcbiAgfSkpO1xuXG4gIGF3YWl0IFByb21pc2UucmFjZSh0YXNrcyk7XG5cbiAgaWYgKGlzVGltZW91dCkge1xuICAgIHRocm93IG5ldyBFcnJvcihgV2ViQXNzZW1ibHkgYmFja2VuZCBpbml0aWFsaXppbmcgZmFpbGVkIGR1ZSB0byB0aW1lb3V0OiAke3RpbWVvdXR9bXNgKTtcbiAgfVxufTtcblxuZXhwb3J0IGNvbnN0IGdldEluc3RhbmNlID0gKCk6IE9ydFdhc21Nb2R1bGUgPT4ge1xuICBpZiAoaW5pdGlhbGl6ZWQgJiYgd2FzbSkge1xuICAgIHJldHVybiB3YXNtO1xuICB9XG5cbiAgdGhyb3cgbmV3IEVycm9yKCdXZWJBc3NlbWJseSBpcyBub3QgaW5pdGlhbGl6ZWQgeWV0LicpO1xufTtcblxuZXhwb3J0IGNvbnN0IGRpc3Bvc2UgPSAoKTogdm9pZCA9PiB7XG4gIGlmIChpbml0aWFsaXplZCAmJiAhaW5pdGlhbGl6aW5nICYmICFhYm9ydGVkKSB7XG4gICAgaW5pdGlhbGl6aW5nID0gdHJ1ZTtcblxuICAgICh3YXNtIGFzIE9ydFdhc21UaHJlYWRlZE1vZHVsZSkuUFRocmVhZD8udGVybWluYXRlQWxsVGhyZWFkcygpO1xuICAgIHdhc20gPSB1bmRlZmluZWQ7XG5cbiAgICBpbml0aWFsaXppbmcgPSBmYWxzZTtcbiAgICBpbml0aWFsaXplZCA9IGZhbHNlO1xuICAgIGFib3J0ZWQgPSB0cnVlO1xuICB9XG59O1xuIiwiXG5pbXBvcnQgd29ya2VyIGZyb20gXCIhIS4uLy4uLy4uL25vZGVfbW9kdWxlcy93b3JrZXItbG9hZGVyL2Rpc3QvcnVudGltZS9pbmxpbmUuanNcIjtcblxuZXhwb3J0IGRlZmF1bHQgZnVuY3Rpb24gV29ya2VyX2ZuKCkge1xuICByZXR1cm4gd29ya2VyKFwiLyohXFxuKiBPTk5YIFJ1bnRpbWUgV2ViIHYxLjE0LjBcXG4qIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxcbiogTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxcbiovXFxuLyoqKioqKi8gKCgpID0+IHsgLy8gd2VicGFja0Jvb3RzdHJhcFxcbi8qKioqKiovIFxcdHZhciBfX3dlYnBhY2tfbW9kdWxlc19fID0gKHtcXG5cXG4vKioqLyBcXFwiLi9saWIvd2FzbS9iaW5kaW5nL29ydC13YXNtLXRocmVhZGVkLmpzXFxcIjpcXG4vKiEqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiEqXFxcXFxcbiAgISoqKiAuL2xpYi93YXNtL2JpbmRpbmcvb3J0LXdhc20tdGhyZWFkZWQuanMgKioqIVxcbiAgXFxcXCoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqL1xcbi8qKiovICgobW9kdWxlLCBfX3VudXNlZF93ZWJwYWNrX2V4cG9ydHMsIF9fd2VicGFja19yZXF1aXJlX18pID0+IHtcXG5cXG52YXIgX19maWxlbmFtZSA9IFxcXCIvaW5kZXguanNcXFwiO1xcbnZhciBfX2Rpcm5hbWUgPSBcXFwiL1xcXCI7XFxuXFxyXFxudmFyIG9ydFdhc21UaHJlYWRlZCA9ICgoKSA9PiB7XFxyXFxuICB2YXIgX3NjcmlwdERpciA9IHR5cGVvZiBkb2N1bWVudCAhPT0gJ3VuZGVmaW5lZCcgJiYgZG9jdW1lbnQuY3VycmVudFNjcmlwdCA/IGRvY3VtZW50LmN1cnJlbnRTY3JpcHQuc3JjIDogdW5kZWZpbmVkO1xcclxcbiAgaWYgKHRydWUpIF9zY3JpcHREaXIgPSBfc2NyaXB0RGlyIHx8IF9fZmlsZW5hbWU7XFxyXFxuICByZXR1cm4gKFxcclxcbmZ1bmN0aW9uKG9ydFdhc21UaHJlYWRlZCkge1xcclxcbiAgb3J0V2FzbVRocmVhZGVkID0gb3J0V2FzbVRocmVhZGVkIHx8IHt9O1xcclxcblxcclxcblxcclxcbmZ1bmN0aW9uIGQoKXttLmJ1ZmZlciE9biYmcChtLmJ1ZmZlcik7cmV0dXJuIGFhfWZ1bmN0aW9uIHEoKXttLmJ1ZmZlciE9biYmcChtLmJ1ZmZlcik7cmV0dXJuIGJhfWZ1bmN0aW9uIHIoKXttLmJ1ZmZlciE9biYmcChtLmJ1ZmZlcik7cmV0dXJuIGNhfWZ1bmN0aW9uIHYoKXttLmJ1ZmZlciE9biYmcChtLmJ1ZmZlcik7cmV0dXJuIGRhfWZ1bmN0aW9uIGVhKCl7bS5idWZmZXIhPW4mJnAobS5idWZmZXIpO3JldHVybiBmYX12YXIgeDt4fHwoeD10eXBlb2Ygb3J0V2FzbVRocmVhZGVkICE9PSAndW5kZWZpbmVkJyA/IG9ydFdhc21UaHJlYWRlZCA6IHt9KTt2YXIgaGEsaWE7eC5yZWFkeT1uZXcgUHJvbWlzZShmdW5jdGlvbihhLGIpe2hhPWE7aWE9Yn0pO1xcclxcbnZhciBqYT1PYmplY3QuYXNzaWduKHt9LHgpLGthPVxcXCIuL3RoaXMucHJvZ3JhbVxcXCIsbGE9KGEsYik9Pnt0aHJvdyBiO30sbWE9XFxcIm9iamVjdFxcXCI9PXR5cGVvZiB3aW5kb3cseT1cXFwiZnVuY3Rpb25cXFwiPT10eXBlb2YgaW1wb3J0U2NyaXB0cyxCPVxcXCJvYmplY3RcXFwiPT10eXBlb2YgcHJvY2VzcyYmXFxcIm9iamVjdFxcXCI9PXR5cGVvZiBwcm9jZXNzLnZlcnNpb25zJiZcXFwic3RyaW5nXFxcIj09dHlwZW9mIHByb2Nlc3MudmVyc2lvbnMubm9kZSxDPXguRU5WSVJPTk1FTlRfSVNfUFRIUkVBRHx8ITEsRD1cXFwiXFxcIjtmdW5jdGlvbiBuYShhKXtyZXR1cm4geC5sb2NhdGVGaWxlP3gubG9jYXRlRmlsZShhLEQpOkQrYX12YXIgb2EscGEscWEsZnMscmEsc2E7XFxyXFxuaWYoQil7RD15PyhfX3dlYnBhY2tfcmVxdWlyZV9fKC8qISBwYXRoICovIFxcXCI/NzVjNlxcXCIpLmRpcm5hbWUpKEQpK1xcXCIvXFxcIjpfX2Rpcm5hbWUrXFxcIi9cXFwiO3NhPSgpPT57cmF8fChmcz1fX3dlYnBhY2tfcmVxdWlyZV9fKC8qISBmcyAqLyBcXFwiPzYzYzhcXFwiKSxyYT1fX3dlYnBhY2tfcmVxdWlyZV9fKC8qISBwYXRoICovIFxcXCI/NzVjNlxcXCIpKX07b2E9ZnVuY3Rpb24oYixjKXtzYSgpO2I9cmEubm9ybWFsaXplKGIpO3JldHVybiBmcy5yZWFkRmlsZVN5bmMoYixjP3ZvaWQgMDpcXFwidXRmOFxcXCIpfTtxYT1iPT57Yj1vYShiLCEwKTtiLmJ1ZmZlcnx8KGI9bmV3IFVpbnQ4QXJyYXkoYikpO3JldHVybiBifTtwYT0oYixjLGUpPT57c2EoKTtiPXJhLm5vcm1hbGl6ZShiKTtmcy5yZWFkRmlsZShiLGZ1bmN0aW9uKGYsaCl7Zj9lKGYpOmMoaC5idWZmZXIpfSl9OzE8cHJvY2Vzcy5hcmd2Lmxlbmd0aCYmKGthPXByb2Nlc3MuYXJndlsxXS5yZXBsYWNlKC9cXFxcXFxcXC9nLFxcXCIvXFxcIikpO3Byb2Nlc3MuYXJndi5zbGljZSgyKTtwcm9jZXNzLm9uKFxcXCJ1bmNhdWdodEV4Y2VwdGlvblxcXCIsZnVuY3Rpb24oYil7aWYoIShiIGluc3RhbmNlb2YgRSkpdGhyb3cgYjt9KTtwcm9jZXNzLm9uKFxcXCJ1bmhhbmRsZWRSZWplY3Rpb25cXFwiLFxcclxcbmZ1bmN0aW9uKGIpe3Rocm93IGI7fSk7bGE9KGIsYyk9PntpZihGKCkpdGhyb3cgcHJvY2Vzcy5leGl0Q29kZT1iLGM7YyBpbnN0YW5jZW9mIEV8fEcoXFxcImV4aXRpbmcgZHVlIHRvIGV4Y2VwdGlvbjogXFxcIitjKTtwcm9jZXNzLmV4aXQoYil9O3guaW5zcGVjdD1mdW5jdGlvbigpe3JldHVyblxcXCJbRW1zY3JpcHRlbiBNb2R1bGUgb2JqZWN0XVxcXCJ9O2xldCBhO3RyeXthPV9fd2VicGFja19yZXF1aXJlX18oLyohIHdvcmtlcl90aHJlYWRzICovIFxcXCI/YzZmN1xcXCIpfWNhdGNoKGIpe3Rocm93IGNvbnNvbGUuZXJyb3IoJ1RoZSBcXFwid29ya2VyX3RocmVhZHNcXFwiIG1vZHVsZSBpcyBub3Qgc3VwcG9ydGVkIGluIHRoaXMgbm9kZS5qcyBidWlsZCAtIHBlcmhhcHMgYSBuZXdlciB2ZXJzaW9uIGlzIG5lZWRlZD8nKSxiO31fX3dlYnBhY2tfcmVxdWlyZV9fLmcuV29ya2VyPWEuV29ya2VyfWVsc2UgaWYobWF8fHkpeT9EPXNlbGYubG9jYXRpb24uaHJlZjpcXFwidW5kZWZpbmVkXFxcIiE9dHlwZW9mIGRvY3VtZW50JiZkb2N1bWVudC5jdXJyZW50U2NyaXB0JiYoRD1kb2N1bWVudC5jdXJyZW50U2NyaXB0LnNyYyksXFxyXFxuX3NjcmlwdERpciYmKEQ9X3NjcmlwdERpciksMCE9PUQuaW5kZXhPZihcXFwiYmxvYjpcXFwiKT9EPUQuc3Vic3RyKDAsRC5yZXBsYWNlKC9bPyNdLiovLFxcXCJcXFwiKS5sYXN0SW5kZXhPZihcXFwiL1xcXCIpKzEpOkQ9XFxcIlxcXCIsQnx8KG9hPWE9Pnt2YXIgYj1uZXcgWE1MSHR0cFJlcXVlc3Q7Yi5vcGVuKFxcXCJHRVRcXFwiLGEsITEpO2Iuc2VuZChudWxsKTtyZXR1cm4gYi5yZXNwb25zZVRleHR9LHkmJihxYT1hPT57dmFyIGI9bmV3IFhNTEh0dHBSZXF1ZXN0O2Iub3BlbihcXFwiR0VUXFxcIixhLCExKTtiLnJlc3BvbnNlVHlwZT1cXFwiYXJyYXlidWZmZXJcXFwiO2Iuc2VuZChudWxsKTtyZXR1cm4gbmV3IFVpbnQ4QXJyYXkoYi5yZXNwb25zZSl9KSxwYT0oYSxiLGMpPT57dmFyIGU9bmV3IFhNTEh0dHBSZXF1ZXN0O2Uub3BlbihcXFwiR0VUXFxcIixhLCEwKTtlLnJlc3BvbnNlVHlwZT1cXFwiYXJyYXlidWZmZXJcXFwiO2Uub25sb2FkPSgpPT57MjAwPT1lLnN0YXR1c3x8MD09ZS5zdGF0dXMmJmUucmVzcG9uc2U/YihlLnJlc3BvbnNlKTpjKCl9O2Uub25lcnJvcj1cXHJcXG5jO2Uuc2VuZChudWxsKX0pO0ImJlxcXCJ1bmRlZmluZWRcXFwiPT10eXBlb2YgcGVyZm9ybWFuY2UmJihfX3dlYnBhY2tfcmVxdWlyZV9fLmcucGVyZm9ybWFuY2U9KF9fd2VicGFja19yZXF1aXJlX18oLyohIHBlcmZfaG9va3MgKi8gXFxcIj82NzRmXFxcIikucGVyZm9ybWFuY2UpKTt2YXIgdGE9Y29uc29sZS5sb2cuYmluZChjb25zb2xlKSx1YT1jb25zb2xlLndhcm4uYmluZChjb25zb2xlKTtCJiYoc2EoKSx0YT1hPT5mcy53cml0ZVN5bmMoMSxhK1xcXCJcXFxcblxcXCIpLHVhPWE9PmZzLndyaXRlU3luYygyLGErXFxcIlxcXFxuXFxcIikpO3ZhciB2YT14LnByaW50fHx0YSxHPXgucHJpbnRFcnJ8fHVhO09iamVjdC5hc3NpZ24oeCxqYSk7amE9bnVsbDt4LnRoaXNQcm9ncmFtJiYoa2E9eC50aGlzUHJvZ3JhbSk7eC5xdWl0JiYobGE9eC5xdWl0KTt2YXIgSDt4Lndhc21CaW5hcnkmJihIPXgud2FzbUJpbmFyeSk7dmFyIG5vRXhpdFJ1bnRpbWU9eC5ub0V4aXRSdW50aW1lfHwhMTtcXFwib2JqZWN0XFxcIiE9dHlwZW9mIFdlYkFzc2VtYmx5JiZJKFxcXCJubyBuYXRpdmUgd2FzbSBzdXBwb3J0IGRldGVjdGVkXFxcIik7XFxyXFxudmFyIG0sd2EseGE9ITEseWE9XFxcInVuZGVmaW5lZFxcXCIhPXR5cGVvZiBUZXh0RGVjb2Rlcj9uZXcgVGV4dERlY29kZXIoXFxcInV0ZjhcXFwiKTp2b2lkIDA7XFxyXFxuZnVuY3Rpb24gemEoYSxiLGMpe2I+Pj49MDt2YXIgZT1iK2M7Zm9yKGM9YjthW2NdJiYhKGM+PWUpOykrK2M7aWYoMTY8Yy1iJiZhLmJ1ZmZlciYmeWEpcmV0dXJuIHlhLmRlY29kZShhLmJ1ZmZlciBpbnN0YW5jZW9mIFNoYXJlZEFycmF5QnVmZmVyP2Euc2xpY2UoYixjKTphLnN1YmFycmF5KGIsYykpO2ZvcihlPVxcXCJcXFwiO2I8Yzspe3ZhciBmPWFbYisrXTtpZihmJjEyOCl7dmFyIGg9YVtiKytdJjYzO2lmKDE5Mj09KGYmMjI0KSllKz1TdHJpbmcuZnJvbUNoYXJDb2RlKChmJjMxKTw8NnxoKTtlbHNle3ZhciBrPWFbYisrXSY2MztmPTIyND09KGYmMjQwKT8oZiYxNSk8PDEyfGg8PDZ8azooZiY3KTw8MTh8aDw8MTJ8azw8NnxhW2IrK10mNjM7NjU1MzY+Zj9lKz1TdHJpbmcuZnJvbUNoYXJDb2RlKGYpOihmLT02NTUzNixlKz1TdHJpbmcuZnJvbUNoYXJDb2RlKDU1Mjk2fGY+PjEwLDU2MzIwfGYmMTAyMykpfX1lbHNlIGUrPVN0cmluZy5mcm9tQ2hhckNvZGUoZil9cmV0dXJuIGV9XFxyXFxuZnVuY3Rpb24gQWEoYSxiKXtyZXR1cm4oYT4+Pj0wKT96YShxKCksYSxiKTpcXFwiXFxcIn1cXHJcXG5mdW5jdGlvbiBCYShhLGIsYyxlKXtjPj4+PTA7aWYoISgwPGUpKXJldHVybiAwO3ZhciBmPWM7ZT1jK2UtMTtmb3IodmFyIGg9MDtoPGEubGVuZ3RoOysraCl7dmFyIGs9YS5jaGFyQ29kZUF0KGgpO2lmKDU1Mjk2PD1rJiY1NzM0Mz49ayl7dmFyIGw9YS5jaGFyQ29kZUF0KCsraCk7az02NTUzNisoKGsmMTAyMyk8PDEwKXxsJjEwMjN9aWYoMTI3Pj1rKXtpZihjPj1lKWJyZWFrO2JbYysrPj4+MF09a31lbHNle2lmKDIwNDc+PWspe2lmKGMrMT49ZSlicmVhaztiW2MrKz4+PjBdPTE5MnxrPj42fWVsc2V7aWYoNjU1MzU+PWspe2lmKGMrMj49ZSlicmVhaztiW2MrKz4+PjBdPTIyNHxrPj4xMn1lbHNle2lmKGMrMz49ZSlicmVhaztiW2MrKz4+PjBdPTI0MHxrPj4xODtiW2MrKz4+PjBdPTEyOHxrPj4xMiY2M31iW2MrKz4+PjBdPTEyOHxrPj42JjYzfWJbYysrPj4+MF09MTI4fGsmNjN9fWJbYz4+PjBdPTA7cmV0dXJuIGMtZn1cXHJcXG5mdW5jdGlvbiBDYShhKXtmb3IodmFyIGI9MCxjPTA7YzxhLmxlbmd0aDsrK2Mpe3ZhciBlPWEuY2hhckNvZGVBdChjKTsxMjc+PWU/YisrOjIwNDc+PWU/Yis9Mjo1NTI5Njw9ZSYmNTczNDM+PWU/KGIrPTQsKytjKTpiKz0zfXJldHVybiBifXZhciBuLGFhLGJhLGNhLGRhLGZhO0MmJihuPXguYnVmZmVyKTtmdW5jdGlvbiBwKGEpe249YTt4LkhFQVA4PWFhPW5ldyBJbnQ4QXJyYXkoYSk7eC5IRUFQMTY9bmV3IEludDE2QXJyYXkoYSk7eC5IRUFQMzI9Y2E9bmV3IEludDMyQXJyYXkoYSk7eC5IRUFQVTg9YmE9bmV3IFVpbnQ4QXJyYXkoYSk7eC5IRUFQVTE2PW5ldyBVaW50MTZBcnJheShhKTt4LkhFQVBVMzI9ZGE9bmV3IFVpbnQzMkFycmF5KGEpO3guSEVBUEYzMj1uZXcgRmxvYXQzMkFycmF5KGEpO3guSEVBUEY2ND1mYT1uZXcgRmxvYXQ2NEFycmF5KGEpfXZhciBEYT14LklOSVRJQUxfTUVNT1JZfHwxNjc3NzIxNjtcXHJcXG5pZihDKW09eC53YXNtTWVtb3J5LG49eC5idWZmZXI7ZWxzZSBpZih4Lndhc21NZW1vcnkpbT14Lndhc21NZW1vcnk7ZWxzZSBpZihtPW5ldyBXZWJBc3NlbWJseS5NZW1vcnkoe2luaXRpYWw6RGEvNjU1MzYsbWF4aW11bTo2NTUzNixzaGFyZWQ6ITB9KSwhKG0uYnVmZmVyIGluc3RhbmNlb2YgU2hhcmVkQXJyYXlCdWZmZXIpKXRocm93IEcoXFxcInJlcXVlc3RlZCBhIHNoYXJlZCBXZWJBc3NlbWJseS5NZW1vcnkgYnV0IHRoZSByZXR1cm5lZCBidWZmZXIgaXMgbm90IGEgU2hhcmVkQXJyYXlCdWZmZXIsIGluZGljYXRpbmcgdGhhdCB3aGlsZSB0aGUgYnJvd3NlciBoYXMgU2hhcmVkQXJyYXlCdWZmZXIgaXQgZG9lcyBub3QgaGF2ZSBXZWJBc3NlbWJseSB0aHJlYWRzIHN1cHBvcnQgLSB5b3UgbWF5IG5lZWQgdG8gc2V0IGEgZmxhZ1xcXCIpLEImJmNvbnNvbGUubG9nKFxcXCIob24gbm9kZSB5b3UgbWF5IG5lZWQ6IC0tZXhwZXJpbWVudGFsLXdhc20tdGhyZWFkcyAtLWV4cGVyaW1lbnRhbC13YXNtLWJ1bGstbWVtb3J5IGFuZCBhbHNvIHVzZSBhIHJlY2VudCB2ZXJzaW9uKVxcXCIpLFxcclxcbkVycm9yKFxcXCJiYWQgbWVtb3J5XFxcIik7bSYmKG49bS5idWZmZXIpO0RhPW4uYnl0ZUxlbmd0aDtwKG4pO3ZhciBFYSxGYT1bXSxHYT1bXSxIYT1bXSxJYT1bXSxKYT0wO2Z1bmN0aW9uIEYoKXtyZXR1cm4gbm9FeGl0UnVudGltZXx8MDxKYX1mdW5jdGlvbiBLYSgpe3ZhciBhPXgucHJlUnVuLnNoaWZ0KCk7RmEudW5zaGlmdChhKX12YXIgTD0wLExhPW51bGwsTT1udWxsO2Z1bmN0aW9uIEkoYSl7aWYoQylwb3N0TWVzc2FnZSh7Y21kOlxcXCJvbkFib3J0XFxcIixhcmc6YX0pO2Vsc2UgaWYoeC5vbkFib3J0KXgub25BYm9ydChhKTthPVxcXCJBYm9ydGVkKFxcXCIrYStcXFwiKVxcXCI7RyhhKTt4YT0hMDthPW5ldyBXZWJBc3NlbWJseS5SdW50aW1lRXJyb3IoYStcXFwiLiBCdWlsZCB3aXRoIC1zQVNTRVJUSU9OUyBmb3IgbW9yZSBpbmZvLlxcXCIpO2lhKGEpO3Rocm93IGE7fWZ1bmN0aW9uIE1hKCl7cmV0dXJuIE8uc3RhcnRzV2l0aChcXFwiZGF0YTphcHBsaWNhdGlvbi9vY3RldC1zdHJlYW07YmFzZTY0LFxcXCIpfXZhciBPO089XFxcIm9ydC13YXNtLXRocmVhZGVkLndhc21cXFwiO1xcclxcbk1hKCl8fChPPW5hKE8pKTtmdW5jdGlvbiBOYSgpe3ZhciBhPU87dHJ5e2lmKGE9PU8mJkgpcmV0dXJuIG5ldyBVaW50OEFycmF5KEgpO2lmKHFhKXJldHVybiBxYShhKTt0aHJvd1xcXCJib3RoIGFzeW5jIGFuZCBzeW5jIGZldGNoaW5nIG9mIHRoZSB3YXNtIGZhaWxlZFxcXCI7fWNhdGNoKGIpe0koYil9fVxcclxcbmZ1bmN0aW9uIE9hKCl7aWYoIUgmJihtYXx8eSkpe2lmKFxcXCJmdW5jdGlvblxcXCI9PXR5cGVvZiBmZXRjaCYmIU8uc3RhcnRzV2l0aChcXFwiZmlsZTovL1xcXCIpKXJldHVybiBmZXRjaChPLHtjcmVkZW50aWFsczpcXFwic2FtZS1vcmlnaW5cXFwifSkudGhlbihmdW5jdGlvbihhKXtpZighYS5vayl0aHJvd1xcXCJmYWlsZWQgdG8gbG9hZCB3YXNtIGJpbmFyeSBmaWxlIGF0ICdcXFwiK08rXFxcIidcXFwiO3JldHVybiBhLmFycmF5QnVmZmVyKCl9KS5jYXRjaChmdW5jdGlvbigpe3JldHVybiBOYSgpfSk7aWYocGEpcmV0dXJuIG5ldyBQcm9taXNlKGZ1bmN0aW9uKGEsYil7cGEoTyxmdW5jdGlvbihjKXthKG5ldyBVaW50OEFycmF5KGMpKX0sYil9KX1yZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCkudGhlbihmdW5jdGlvbigpe3JldHVybiBOYSgpfSl9dmFyIFBhPXt9O1xcclxcbmZ1bmN0aW9uIEUoYSl7dGhpcy5uYW1lPVxcXCJFeGl0U3RhdHVzXFxcIjt0aGlzLm1lc3NhZ2U9XFxcIlByb2dyYW0gdGVybWluYXRlZCB3aXRoIGV4aXQoXFxcIithK1xcXCIpXFxcIjt0aGlzLnN0YXR1cz1hfWZ1bmN0aW9uIFFhKGEpeyhhPVAuVmJbYV0pfHxJKCk7UC5tYyhhKX1mdW5jdGlvbiBSYShhKXt2YXIgYj1QLkNjKCk7aWYoIWIpcmV0dXJuIDY7UC5hYy5wdXNoKGIpO1AuVmJbYS5VYl09YjtiLlViPWEuVWI7dmFyIGM9e2NtZDpcXFwicnVuXFxcIixzdGFydF9yb3V0aW5lOmEuSWMsYXJnOmEuemMscHRocmVhZF9wdHI6YS5VYn07Yi4kYj0oKT0+e2MudGltZT1wZXJmb3JtYW5jZS5ub3coKTtiLnBvc3RNZXNzYWdlKGMsYS5OYyl9O2IubG9hZGVkJiYoYi4kYigpLGRlbGV0ZSBiLiRiKTtyZXR1cm4gMH1mdW5jdGlvbiBTYShhKXtpZihDKXJldHVybiBRKDEsMSxhKTtpZighRigpKXtQLm9jKCk7aWYoeC5vbkV4aXQpeC5vbkV4aXQoYSk7eGE9ITB9bGEoYSxuZXcgRShhKSl9XFxyXFxuZnVuY3Rpb24gVGEoYSxiKXtpZighYiYmQyl0aHJvdyBVYShhKSxcXFwidW53aW5kXFxcIjtGKCl8fEN8fChWYSgpLFIoSGEpLFdhKDApLFhhWzFdLmxlbmd0aCYmWWEoMSwxMCksWGFbMl0ubGVuZ3RoJiZZYSgyLDEwKSxQLm9jKCkpO1NhKGEpfVxcclxcbnZhciBQPXtZYjpbXSxhYzpbXSxxYzpbXSxWYjp7fSxmYzpmdW5jdGlvbigpe0MmJlAuRWMoKX0sUGM6ZnVuY3Rpb24oKXt9LEVjOmZ1bmN0aW9uKCl7UC5yZWNlaXZlT2JqZWN0VHJhbnNmZXI9UC5HYztQLnRocmVhZEluaXRUTFM9UC5wYztQLnNldEV4aXRTdGF0dXM9UC5uYztub0V4aXRSdW50aW1lPSExfSxuYzpmdW5jdGlvbigpe30sb2M6ZnVuY3Rpb24oKXtmb3IodmFyIGEgb2YgT2JqZWN0LnZhbHVlcyhQLlZiKSlQLm1jKGEpO2ZvcihhIG9mIFAuWWIpYS50ZXJtaW5hdGUoKTtQLlliPVtdfSxtYzpmdW5jdGlvbihhKXt2YXIgYj1hLlViO2RlbGV0ZSBQLlZiW2JdO1AuWWIucHVzaChhKTtQLmFjLnNwbGljZShQLmFjLmluZGV4T2YoYSksMSk7YS5VYj0wO1phKGIpfSxHYzpmdW5jdGlvbigpe30scGM6ZnVuY3Rpb24oKXtQLnFjLmZvckVhY2goYT0+YSgpKX0sRmM6ZnVuY3Rpb24oYSxiKXthLm9ubWVzc2FnZT1jPT57Yz1jLmRhdGE7dmFyIGU9Yy5jbWQ7YS5VYiYmKFAuQmM9YS5VYik7XFxyXFxuaWYoYy50YXJnZXRUaHJlYWQmJmMudGFyZ2V0VGhyZWFkIT0kYSgpKXt2YXIgZj1QLlZiW2MuUWNdO2Y/Zi5wb3N0TWVzc2FnZShjLGMudHJhbnNmZXJMaXN0KTpHKCdJbnRlcm5hbCBlcnJvciEgV29ya2VyIHNlbnQgYSBtZXNzYWdlIFxcXCInK2UrJ1xcXCIgdG8gdGFyZ2V0IHB0aHJlYWQgJytjLnRhcmdldFRocmVhZCtcXFwiLCBidXQgdGhhdCB0aHJlYWQgbm8gbG9uZ2VyIGV4aXN0cyFcXFwiKX1lbHNlIGlmKFxcXCJwcm9jZXNzUHJveHlpbmdRdWV1ZVxcXCI9PT1lKWFiKGMucXVldWUpO2Vsc2UgaWYoXFxcInNwYXduVGhyZWFkXFxcIj09PWUpUmEoYyk7ZWxzZSBpZihcXFwiY2xlYW51cFRocmVhZFxcXCI9PT1lKVFhKGMudGhyZWFkKTtlbHNlIGlmKFxcXCJraWxsVGhyZWFkXFxcIj09PWUpYz1jLnRocmVhZCxlPVAuVmJbY10sZGVsZXRlIFAuVmJbY10sZS50ZXJtaW5hdGUoKSxaYShjKSxQLmFjLnNwbGljZShQLmFjLmluZGV4T2YoZSksMSksZS5VYj0wO2Vsc2UgaWYoXFxcImNhbmNlbFRocmVhZFxcXCI9PT1lKVAuVmJbYy50aHJlYWRdLnBvc3RNZXNzYWdlKHtjbWQ6XFxcImNhbmNlbFxcXCJ9KTtcXHJcXG5lbHNlIGlmKFxcXCJsb2FkZWRcXFwiPT09ZSlhLmxvYWRlZD0hMCxiJiZiKGEpLGEuJGImJihhLiRiKCksZGVsZXRlIGEuJGIpO2Vsc2UgaWYoXFxcInByaW50XFxcIj09PWUpdmEoXFxcIlRocmVhZCBcXFwiK2MudGhyZWFkSWQrXFxcIjogXFxcIitjLnRleHQpO2Vsc2UgaWYoXFxcInByaW50RXJyXFxcIj09PWUpRyhcXFwiVGhyZWFkIFxcXCIrYy50aHJlYWRJZCtcXFwiOiBcXFwiK2MudGV4dCk7ZWxzZSBpZihcXFwiYWxlcnRcXFwiPT09ZSlhbGVydChcXFwiVGhyZWFkIFxcXCIrYy50aHJlYWRJZCtcXFwiOiBcXFwiK2MudGV4dCk7ZWxzZSBpZihcXFwic2V0aW1tZWRpYXRlXFxcIj09PWMudGFyZ2V0KWEucG9zdE1lc3NhZ2UoYyk7ZWxzZSBpZihcXFwib25BYm9ydFxcXCI9PT1lKXtpZih4Lm9uQWJvcnQpeC5vbkFib3J0KGMuYXJnKX1lbHNlIGUmJkcoXFxcIndvcmtlciBzZW50IGFuIHVua25vd24gY29tbWFuZCBcXFwiK2UpO1AuQmM9dm9pZCAwfTthLm9uZXJyb3I9Yz0+e0coXFxcIndvcmtlciBzZW50IGFuIGVycm9yISBcXFwiK2MuZmlsZW5hbWUrXFxcIjpcXFwiK2MubGluZW5vK1xcXCI6IFxcXCIrYy5tZXNzYWdlKTt0aHJvdyBjO307QiYmXFxyXFxuKGEub24oXFxcIm1lc3NhZ2VcXFwiLGZ1bmN0aW9uKGMpe2Eub25tZXNzYWdlKHtkYXRhOmN9KX0pLGEub24oXFxcImVycm9yXFxcIixmdW5jdGlvbihjKXthLm9uZXJyb3IoYyl9KSxhLm9uKFxcXCJkZXRhY2hlZEV4aXRcXFwiLGZ1bmN0aW9uKCl7fSkpO2EucG9zdE1lc3NhZ2Uoe2NtZDpcXFwibG9hZFxcXCIsdXJsT3JCbG9iOngubWFpblNjcmlwdFVybE9yQmxvYnx8X3NjcmlwdERpcix3YXNtTWVtb3J5Om0sd2FzbU1vZHVsZTp3YX0pfSx5YzpmdW5jdGlvbigpe3ZhciBhPW5hKFxcXCJvcnQtd2FzbS10aHJlYWRlZC53b3JrZXIuanNcXFwiKTtQLlliLnB1c2gobmV3IFdvcmtlcihhKSl9LENjOmZ1bmN0aW9uKCl7MD09UC5ZYi5sZW5ndGgmJihQLnljKCksUC5GYyhQLlliWzBdKSk7cmV0dXJuIFAuWWIucG9wKCl9fTt4LlBUaHJlYWQ9UDtmdW5jdGlvbiBSKGEpe2Zvcig7MDxhLmxlbmd0aDspYS5zaGlmdCgpKHgpfWZ1bmN0aW9uIGJiKGEpe3ZhciBiPVMoKTthPWEoKTtVKGIpO3JldHVybiBhfVxcclxcbnguZXN0YWJsaXNoU3RhY2tTcGFjZT1mdW5jdGlvbigpe3ZhciBhPSRhKCksYj1yKClbYSs0ND4+Mj4+PjBdO2E9cigpW2ErNDg+PjI+Pj4wXTtjYihiLGItYSk7VShiKX07ZnVuY3Rpb24gVWEoYSl7aWYoQylyZXR1cm4gUSgyLDAsYSk7dHJ5e1RhKGEpfWNhdGNoKGIpe2IgaW5zdGFuY2VvZiBFfHxcXFwidW53aW5kXFxcIj09Ynx8bGEoMSxiKX19dmFyIGRiPVtdO2Z1bmN0aW9uIFYoYSl7dmFyIGI9ZGJbYV07Ynx8KGE+PWRiLmxlbmd0aCYmKGRiLmxlbmd0aD1hKzEpLGRiW2FdPWI9RWEuZ2V0KGEpKTtyZXR1cm4gYn14Lmludm9rZUVudHJ5UG9pbnQ9ZnVuY3Rpb24oYSxiKXthPVYoYSkoYik7RigpP1AubmMoYSk6ZWIoYSl9O2Z1bmN0aW9uIGZiKGEsYil7ZCgpLnNldChhLGI+Pj4wKX12YXIgZ2I9W10saGI9MCxXPTA7XFxyXFxuZnVuY3Rpb24gWChhKXt0aGlzLlpiPWE7dGhpcy5TYj1hLTI0O3RoaXMueGM9ZnVuY3Rpb24oYil7digpW3RoaXMuU2IrND4+Mj4+PjBdPWJ9O3RoaXMuYmM9ZnVuY3Rpb24oKXtyZXR1cm4gdigpW3RoaXMuU2IrND4+Mj4+PjBdfTt0aGlzLndjPWZ1bmN0aW9uKGIpe3YoKVt0aGlzLlNiKzg+PjI+Pj4wXT1ifTt0aGlzLkRjPWZ1bmN0aW9uKCl7cmV0dXJuIHYoKVt0aGlzLlNiKzg+PjI+Pj4wXX07dGhpcy5yYz1mdW5jdGlvbigpe3IoKVt0aGlzLlNiPj4yPj4+MF09MH07dGhpcy5oYz1mdW5jdGlvbihiKXtiPWI/MTowO2QoKVt0aGlzLlNiKzEyPj4wPj4+MF09Yn07dGhpcy51Yz1mdW5jdGlvbigpe3JldHVybiAwIT1kKClbdGhpcy5TYisxMj4+MD4+PjBdfTt0aGlzLmljPWZ1bmN0aW9uKGIpe2I9Yj8xOjA7ZCgpW3RoaXMuU2IrMTM+PjA+Pj4wXT1ifTt0aGlzLmtjPWZ1bmN0aW9uKCl7cmV0dXJuIDAhPWQoKVt0aGlzLlNiKzEzPj4wPj4+MF19O3RoaXMuZmM9ZnVuY3Rpb24oYixjKXt0aGlzLmNjKDApO1xcclxcbnRoaXMueGMoYik7dGhpcy53YyhjKTt0aGlzLnJjKCk7dGhpcy5oYyghMSk7dGhpcy5pYyghMSl9O3RoaXMuc2M9ZnVuY3Rpb24oKXtBdG9taWNzLmFkZChyKCksdGhpcy5TYj4+MiwxKX07dGhpcy5IYz1mdW5jdGlvbigpe3JldHVybiAxPT09QXRvbWljcy5zdWIocigpLHRoaXMuU2I+PjIsMSl9O3RoaXMuY2M9ZnVuY3Rpb24oYil7digpW3RoaXMuU2IrMTY+PjI+Pj4wXT1ifTt0aGlzLnRjPWZ1bmN0aW9uKCl7cmV0dXJuIHYoKVt0aGlzLlNiKzE2Pj4yPj4+MF19O3RoaXMudmM9ZnVuY3Rpb24oKXtpZihpYih0aGlzLmJjKCkpKXJldHVybiB2KClbdGhpcy5aYj4+Mj4+PjBdO3ZhciBiPXRoaXMudGMoKTtyZXR1cm4gMCE9PWI/Yjp0aGlzLlpifX1mdW5jdGlvbiBqYihhKXtyZXR1cm4ga2IoKG5ldyBYKGEpKS5TYil9ZnVuY3Rpb24gbGIoYSxiLGMsZSl7cmV0dXJuIEM/USgzLDEsYSxiLGMsZSk6bWIoYSxiLGMsZSl9XFxyXFxuZnVuY3Rpb24gbWIoYSxiLGMsZSl7aWYoXFxcInVuZGVmaW5lZFxcXCI9PXR5cGVvZiBTaGFyZWRBcnJheUJ1ZmZlcilyZXR1cm4gRyhcXFwiQ3VycmVudCBlbnZpcm9ubWVudCBkb2VzIG5vdCBzdXBwb3J0IFNoYXJlZEFycmF5QnVmZmVyLCBwdGhyZWFkcyBhcmUgbm90IGF2YWlsYWJsZSFcXFwiKSw2O3ZhciBmPVtdO2lmKEMmJjA9PT1mLmxlbmd0aClyZXR1cm4gbGIoYSxiLGMsZSk7YT17SWM6YyxVYjphLHpjOmUsTmM6Zn07cmV0dXJuIEM/KGEuT2M9XFxcInNwYXduVGhyZWFkXFxcIixwb3N0TWVzc2FnZShhLGYpLDApOlJhKGEpfWZ1bmN0aW9uIG5iKGEsYixjKXtyZXR1cm4gQz9RKDQsMSxhLGIsYyk6MH1mdW5jdGlvbiBvYihhLGIpe2lmKEMpcmV0dXJuIFEoNSwxLGEsYil9ZnVuY3Rpb24gcGIoYSxiKXtpZihDKXJldHVybiBRKDYsMSxhLGIpfWZ1bmN0aW9uIHFiKGEsYixjKXtpZihDKXJldHVybiBRKDcsMSxhLGIsYyl9ZnVuY3Rpb24gcmIoYSxiLGMpe3JldHVybiBDP1EoOCwxLGEsYixjKTowfVxcclxcbmZ1bmN0aW9uIHNiKGEsYil7aWYoQylyZXR1cm4gUSg5LDEsYSxiKX1mdW5jdGlvbiB0YihhLGIsYyl7aWYoQylyZXR1cm4gUSgxMCwxLGEsYixjKX1mdW5jdGlvbiB1YihhLGIsYyxlKXtpZihDKXJldHVybiBRKDExLDEsYSxiLGMsZSl9ZnVuY3Rpb24gdmIoYSxiLGMsZSl7aWYoQylyZXR1cm4gUSgxMiwxLGEsYixjLGUpfWZ1bmN0aW9uIHdiKGEsYixjLGUpe2lmKEMpcmV0dXJuIFEoMTMsMSxhLGIsYyxlKX1mdW5jdGlvbiB4YihhKXtpZihDKXJldHVybiBRKDE0LDEsYSl9ZnVuY3Rpb24geWIoYSxiKXtpZihDKXJldHVybiBRKDE1LDEsYSxiKX1mdW5jdGlvbiB6YihhLGIsYyl7aWYoQylyZXR1cm4gUSgxNiwxLGEsYixjKX1mdW5jdGlvbiBhYihhKXtBdG9taWNzLnN0b3JlKHIoKSxhPj4yLDEpOyRhKCkmJkFiKGEpO0F0b21pY3MuY29tcGFyZUV4Y2hhbmdlKHIoKSxhPj4yLDEsMCl9eC5leGVjdXRlTm90aWZpZWRQcm94eWluZ1F1ZXVlPWFiO1xcclxcbmZ1bmN0aW9uIEJiKGEpe3JldHVybiB2KClbYT4+PjJdKzQyOTQ5NjcyOTYqcigpW2ErND4+PjJdfWZ1bmN0aW9uIENiKGEsYixjLGUsZixoKXtyZXR1cm4gQz9RKDE3LDEsYSxiLGMsZSxmLGgpOi01Mn1mdW5jdGlvbiBEYihhLGIsYyxlLGYsaCl7aWYoQylyZXR1cm4gUSgxOCwxLGEsYixjLGUsZixoKX1mdW5jdGlvbiBFYihhKXt2YXIgYj1DYShhKSsxLGM9RmIoYik7YyYmQmEoYSxkKCksYyxiKTtyZXR1cm4gY31cXHJcXG5mdW5jdGlvbiBHYihhLGIsYyl7ZnVuY3Rpb24gZSh0KXtyZXR1cm4odD10LnRvVGltZVN0cmluZygpLm1hdGNoKC9cXFxcKChbQS1aYS16IF0rKVxcXFwpJC8pKT90WzFdOlxcXCJHTVRcXFwifWlmKEMpcmV0dXJuIFEoMTksMSxhLGIsYyk7dmFyIGY9KG5ldyBEYXRlKS5nZXRGdWxsWWVhcigpLGg9bmV3IERhdGUoZiwwLDEpLGs9bmV3IERhdGUoZiw2LDEpO2Y9aC5nZXRUaW1lem9uZU9mZnNldCgpO3ZhciBsPWsuZ2V0VGltZXpvbmVPZmZzZXQoKSx1PU1hdGgubWF4KGYsbCk7cigpW2E+PjI+Pj4wXT02MCp1O3IoKVtiPj4yPj4+MF09TnVtYmVyKGYhPWwpO2E9ZShoKTtiPWUoayk7YT1FYihhKTtiPUViKGIpO2w8Zj8odigpW2M+PjI+Pj4wXT1hLHYoKVtjKzQ+PjI+Pj4wXT1iKToodigpW2M+PjI+Pj4wXT1iLHYoKVtjKzQ+PjI+Pj4wXT1hKX1mdW5jdGlvbiBIYihhLGIsYyl7SGIuQWN8fChIYi5BYz0hMCxHYihhLGIsYykpfXZhciBJYixKYjtcXHJcXG5KYj1CPygpPT57dmFyIGE9cHJvY2Vzcy5ocnRpbWUoKTtyZXR1cm4gMUUzKmFbMF0rYVsxXS8xRTZ9OkM/KCk9PnBlcmZvcm1hbmNlLm5vdygpLXguX19wZXJmb3JtYW5jZV9ub3dfY2xvY2tfZHJpZnQ6KCk9PnBlcmZvcm1hbmNlLm5vdygpO2Z1bmN0aW9uIFEoYSxiKXt2YXIgYz1hcmd1bWVudHMubGVuZ3RoLTIsZT1hcmd1bWVudHM7cmV0dXJuIGJiKCgpPT57Zm9yKHZhciBmPUtiKDgqYyksaD1mPj4zLGs9MDtrPGM7aysrKXt2YXIgbD1lWzIra107ZWEoKVtoK2s+Pj4wXT1sfXJldHVybiBMYihhLGMsZixiKX0pfXZhciBNYj1bXSxOYj17fTtcXHJcXG5mdW5jdGlvbiBPYigpe2lmKCFQYil7dmFyIGE9e1VTRVI6XFxcIndlYl91c2VyXFxcIixMT0dOQU1FOlxcXCJ3ZWJfdXNlclxcXCIsUEFUSDpcXFwiL1xcXCIsUFdEOlxcXCIvXFxcIixIT01FOlxcXCIvaG9tZS93ZWJfdXNlclxcXCIsTEFORzooXFxcIm9iamVjdFxcXCI9PXR5cGVvZiBuYXZpZ2F0b3ImJm5hdmlnYXRvci5sYW5ndWFnZXMmJm5hdmlnYXRvci5sYW5ndWFnZXNbMF18fFxcXCJDXFxcIikucmVwbGFjZShcXFwiLVxcXCIsXFxcIl9cXFwiKStcXFwiLlVURi04XFxcIixfOmthfHxcXFwiLi90aGlzLnByb2dyYW1cXFwifSxiO2ZvcihiIGluIE5iKXZvaWQgMD09PU5iW2JdP2RlbGV0ZSBhW2JdOmFbYl09TmJbYl07dmFyIGM9W107Zm9yKGIgaW4gYSljLnB1c2goYitcXFwiPVxcXCIrYVtiXSk7UGI9Y31yZXR1cm4gUGJ9dmFyIFBiO1xcclxcbmZ1bmN0aW9uIFFiKGEsYil7aWYoQylyZXR1cm4gUSgyMCwxLGEsYik7dmFyIGM9MDtPYigpLmZvckVhY2goZnVuY3Rpb24oZSxmKXt2YXIgaD1iK2M7Zj12KClbYSs0KmY+PjI+Pj4wXT1oO2ZvcihoPTA7aDxlLmxlbmd0aDsrK2gpZCgpW2YrKz4+MD4+PjBdPWUuY2hhckNvZGVBdChoKTtkKClbZj4+MD4+PjBdPTA7Yys9ZS5sZW5ndGgrMX0pO3JldHVybiAwfWZ1bmN0aW9uIFJiKGEsYil7aWYoQylyZXR1cm4gUSgyMSwxLGEsYik7dmFyIGM9T2IoKTt2KClbYT4+Mj4+PjBdPWMubGVuZ3RoO3ZhciBlPTA7Yy5mb3JFYWNoKGZ1bmN0aW9uKGYpe2UrPWYubGVuZ3RoKzF9KTt2KClbYj4+Mj4+PjBdPWU7cmV0dXJuIDB9ZnVuY3Rpb24gU2IoYSl7cmV0dXJuIEM/USgyMiwxLGEpOjUyfWZ1bmN0aW9uIFRiKGEsYixjLGUpe3JldHVybiBDP1EoMjMsMSxhLGIsYyxlKTo1Mn1mdW5jdGlvbiBVYihhLGIsYyxlLGYpe3JldHVybiBDP1EoMjQsMSxhLGIsYyxlLGYpOjcwfVxcclxcbnZhciBYYT1bbnVsbCxbXSxbXV07ZnVuY3Rpb24gWWEoYSxiKXt2YXIgYz1YYVthXTswPT09Ynx8MTA9PT1iPygoMT09PWE/dmE6RykoemEoYywwKSksYy5sZW5ndGg9MCk6Yy5wdXNoKGIpfWZ1bmN0aW9uIFZiKGEsYixjLGUpe2lmKEMpcmV0dXJuIFEoMjUsMSxhLGIsYyxlKTtmb3IodmFyIGY9MCxoPTA7aDxjO2grKyl7dmFyIGs9digpW2I+PjI+Pj4wXSxsPXYoKVtiKzQ+PjI+Pj4wXTtiKz04O2Zvcih2YXIgdT0wO3U8bDt1KyspWWEoYSxxKClbayt1Pj4+MF0pO2YrPWx9digpW2U+PjI+Pj4wXT1mO3JldHVybiAwfXZhciBZPTA7XFxyXFxuZnVuY3Rpb24gV2IoKXtpZihcXFwib2JqZWN0XFxcIj09dHlwZW9mIGNyeXB0byYmXFxcImZ1bmN0aW9uXFxcIj09dHlwZW9mIGNyeXB0by5nZXRSYW5kb21WYWx1ZXMpe3ZhciBhPW5ldyBVaW50OEFycmF5KDEpO3JldHVybigpPT57Y3J5cHRvLmdldFJhbmRvbVZhbHVlcyhhKTtyZXR1cm4gYVswXX19aWYoQil0cnl7dmFyIGI9X193ZWJwYWNrX3JlcXVpcmVfXyhPYmplY3QoZnVuY3Rpb24gd2VicGFja01pc3NpbmdNb2R1bGUoKSB7IHZhciBlID0gbmV3IEVycm9yKFxcXCJDYW5ub3QgZmluZCBtb2R1bGUgJ2NyeXB0bydcXFwiKTsgZS5jb2RlID0gJ01PRFVMRV9OT1RfRk9VTkQnOyB0aHJvdyBlOyB9KCkpKTtyZXR1cm4oKT0+Yi5yYW5kb21CeXRlcygxKVswXX1jYXRjaChjKXt9cmV0dXJuKCk9PkkoXFxcInJhbmRvbURldmljZVxcXCIpfWZ1bmN0aW9uIFhiKGEsYil7WGIubGN8fChYYi5sYz1XYigpKTtmb3IodmFyIGM9MDtjPGI7YysrKWQoKVthK2M+PjA+Pj4wXT1YYi5sYygpO3JldHVybiAwfWZ1bmN0aW9uIFliKGEpe3JldHVybiAwPT09YSU0JiYoMCE9PWElMTAwfHwwPT09YSU0MDApfXZhciBaYj1bMzEsMjksMzEsMzAsMzEsMzAsMzEsMzEsMzAsMzEsMzAsMzFdLCRiPVszMSwyOCwzMSwzMCwzMSwzMCwzMSwzMSwzMCwzMSwzMCwzMV07XFxyXFxuZnVuY3Rpb24gYWMoYSl7dmFyIGI9QXJyYXkoQ2EoYSkrMSk7QmEoYSxiLDAsYi5sZW5ndGgpO3JldHVybiBifVxcclxcbmZ1bmN0aW9uIGJjKGEsYixjLGUpe2Z1bmN0aW9uIGYoZyx3LHope2ZvcihnPVxcXCJudW1iZXJcXFwiPT10eXBlb2YgZz9nLnRvU3RyaW5nKCk6Z3x8XFxcIlxcXCI7Zy5sZW5ndGg8dzspZz16WzBdK2c7cmV0dXJuIGd9ZnVuY3Rpb24gaChnLHcpe3JldHVybiBmKGcsdyxcXFwiMFxcXCIpfWZ1bmN0aW9uIGsoZyx3KXtmdW5jdGlvbiB6KFQpe3JldHVybiAwPlQ/LTE6MDxUPzE6MH12YXIgTjswPT09KE49eihnLmdldEZ1bGxZZWFyKCktdy5nZXRGdWxsWWVhcigpKSkmJjA9PT0oTj16KGcuZ2V0TW9udGgoKS13LmdldE1vbnRoKCkpKSYmKE49eihnLmdldERhdGUoKS13LmdldERhdGUoKSkpO3JldHVybiBOfWZ1bmN0aW9uIGwoZyl7c3dpdGNoKGcuZ2V0RGF5KCkpe2Nhc2UgMDpyZXR1cm4gbmV3IERhdGUoZy5nZXRGdWxsWWVhcigpLTEsMTEsMjkpO2Nhc2UgMTpyZXR1cm4gZztjYXNlIDI6cmV0dXJuIG5ldyBEYXRlKGcuZ2V0RnVsbFllYXIoKSwwLDMpO2Nhc2UgMzpyZXR1cm4gbmV3IERhdGUoZy5nZXRGdWxsWWVhcigpLFxcclxcbjAsMik7Y2FzZSA0OnJldHVybiBuZXcgRGF0ZShnLmdldEZ1bGxZZWFyKCksMCwxKTtjYXNlIDU6cmV0dXJuIG5ldyBEYXRlKGcuZ2V0RnVsbFllYXIoKS0xLDExLDMxKTtjYXNlIDY6cmV0dXJuIG5ldyBEYXRlKGcuZ2V0RnVsbFllYXIoKS0xLDExLDMwKX19ZnVuY3Rpb24gdShnKXt2YXIgdz1nLldiO2ZvcihnPW5ldyBEYXRlKChuZXcgRGF0ZShnLlhiKzE5MDAsMCwxKSkuZ2V0VGltZSgpKTswPHc7KXt2YXIgej1nLmdldE1vbnRoKCksTj0oWWIoZy5nZXRGdWxsWWVhcigpKT9aYjokYilbel07aWYodz5OLWcuZ2V0RGF0ZSgpKXctPU4tZy5nZXREYXRlKCkrMSxnLnNldERhdGUoMSksMTE+ej9nLnNldE1vbnRoKHorMSk6KGcuc2V0TW9udGgoMCksZy5zZXRGdWxsWWVhcihnLmdldEZ1bGxZZWFyKCkrMSkpO2Vsc2V7Zy5zZXREYXRlKGcuZ2V0RGF0ZSgpK3cpO2JyZWFrfX16PW5ldyBEYXRlKGcuZ2V0RnVsbFllYXIoKSsxLDAsNCk7dz1sKG5ldyBEYXRlKGcuZ2V0RnVsbFllYXIoKSxcXHJcXG4wLDQpKTt6PWwoeik7cmV0dXJuIDA+PWsodyxnKT8wPj1rKHosZyk/Zy5nZXRGdWxsWWVhcigpKzE6Zy5nZXRGdWxsWWVhcigpOmcuZ2V0RnVsbFllYXIoKS0xfXZhciB0PXIoKVtlKzQwPj4yPj4+MF07ZT17TGM6cigpW2U+PjI+Pj4wXSxLYzpyKClbZSs0Pj4yPj4+MF0sZGM6cigpW2UrOD4+Mj4+PjBdLGpjOnIoKVtlKzEyPj4yPj4+MF0sZWM6cigpW2UrMTY+PjI+Pj4wXSxYYjpyKClbZSsyMD4+Mj4+PjBdLFRiOnIoKVtlKzI0Pj4yPj4+MF0sV2I6cigpW2UrMjg+PjI+Pj4wXSxSYzpyKClbZSszMj4+Mj4+PjBdLEpjOnIoKVtlKzM2Pj4yPj4+MF0sTWM6dD9BYSh0KTpcXFwiXFxcIn07Yz1BYShjKTt0PXtcXFwiJWNcXFwiOlxcXCIlYSAlYiAlZCAlSDolTTolUyAlWVxcXCIsXFxcIiVEXFxcIjpcXFwiJW0vJWQvJXlcXFwiLFxcXCIlRlxcXCI6XFxcIiVZLSVtLSVkXFxcIixcXFwiJWhcXFwiOlxcXCIlYlxcXCIsXFxcIiVyXFxcIjpcXFwiJUk6JU06JVMgJXBcXFwiLFxcXCIlUlxcXCI6XFxcIiVIOiVNXFxcIixcXFwiJVRcXFwiOlxcXCIlSDolTTolU1xcXCIsXFxcIiV4XFxcIjpcXFwiJW0vJWQvJXlcXFwiLFxcXCIlWFxcXCI6XFxcIiVIOiVNOiVTXFxcIixcXFwiJUVjXFxcIjpcXFwiJWNcXFwiLFxcXCIlRUNcXFwiOlxcXCIlQ1xcXCIsXFxyXFxuXFxcIiVFeFxcXCI6XFxcIiVtLyVkLyV5XFxcIixcXFwiJUVYXFxcIjpcXFwiJUg6JU06JVNcXFwiLFxcXCIlRXlcXFwiOlxcXCIleVxcXCIsXFxcIiVFWVxcXCI6XFxcIiVZXFxcIixcXFwiJU9kXFxcIjpcXFwiJWRcXFwiLFxcXCIlT2VcXFwiOlxcXCIlZVxcXCIsXFxcIiVPSFxcXCI6XFxcIiVIXFxcIixcXFwiJU9JXFxcIjpcXFwiJUlcXFwiLFxcXCIlT21cXFwiOlxcXCIlbVxcXCIsXFxcIiVPTVxcXCI6XFxcIiVNXFxcIixcXFwiJU9TXFxcIjpcXFwiJVNcXFwiLFxcXCIlT3VcXFwiOlxcXCIldVxcXCIsXFxcIiVPVVxcXCI6XFxcIiVVXFxcIixcXFwiJU9WXFxcIjpcXFwiJVZcXFwiLFxcXCIlT3dcXFwiOlxcXCIld1xcXCIsXFxcIiVPV1xcXCI6XFxcIiVXXFxcIixcXFwiJU95XFxcIjpcXFwiJXlcXFwifTtmb3IodmFyIEEgaW4gdCljPWMucmVwbGFjZShuZXcgUmVnRXhwKEEsXFxcImdcXFwiKSx0W0FdKTt2YXIgSz1cXFwiU3VuZGF5IE1vbmRheSBUdWVzZGF5IFdlZG5lc2RheSBUaHVyc2RheSBGcmlkYXkgU2F0dXJkYXlcXFwiLnNwbGl0KFxcXCIgXFxcIiksSj1cXFwiSmFudWFyeSBGZWJydWFyeSBNYXJjaCBBcHJpbCBNYXkgSnVuZSBKdWx5IEF1Z3VzdCBTZXB0ZW1iZXIgT2N0b2JlciBOb3ZlbWJlciBEZWNlbWJlclxcXCIuc3BsaXQoXFxcIiBcXFwiKTt0PXtcXFwiJWFcXFwiOmZ1bmN0aW9uKGcpe3JldHVybiBLW2cuVGJdLnN1YnN0cmluZygwLDMpfSxcXFwiJUFcXFwiOmZ1bmN0aW9uKGcpe3JldHVybiBLW2cuVGJdfSxcXHJcXG5cXFwiJWJcXFwiOmZ1bmN0aW9uKGcpe3JldHVybiBKW2cuZWNdLnN1YnN0cmluZygwLDMpfSxcXFwiJUJcXFwiOmZ1bmN0aW9uKGcpe3JldHVybiBKW2cuZWNdfSxcXFwiJUNcXFwiOmZ1bmN0aW9uKGcpe3JldHVybiBoKChnLlhiKzE5MDApLzEwMHwwLDIpfSxcXFwiJWRcXFwiOmZ1bmN0aW9uKGcpe3JldHVybiBoKGcuamMsMil9LFxcXCIlZVxcXCI6ZnVuY3Rpb24oZyl7cmV0dXJuIGYoZy5qYywyLFxcXCIgXFxcIil9LFxcXCIlZ1xcXCI6ZnVuY3Rpb24oZyl7cmV0dXJuIHUoZykudG9TdHJpbmcoKS5zdWJzdHJpbmcoMil9LFxcXCIlR1xcXCI6ZnVuY3Rpb24oZyl7cmV0dXJuIHUoZyl9LFxcXCIlSFxcXCI6ZnVuY3Rpb24oZyl7cmV0dXJuIGgoZy5kYywyKX0sXFxcIiVJXFxcIjpmdW5jdGlvbihnKXtnPWcuZGM7MD09Zz9nPTEyOjEyPGcmJihnLT0xMik7cmV0dXJuIGgoZywyKX0sXFxcIiVqXFxcIjpmdW5jdGlvbihnKXtmb3IodmFyIHc9MCx6PTA7ejw9Zy5lYy0xO3crPShZYihnLlhiKzE5MDApP1piOiRiKVt6KytdKTtyZXR1cm4gaChnLmpjK3csMyl9LFxcXCIlbVxcXCI6ZnVuY3Rpb24oZyl7cmV0dXJuIGgoZy5lYytcXHJcXG4xLDIpfSxcXFwiJU1cXFwiOmZ1bmN0aW9uKGcpe3JldHVybiBoKGcuS2MsMil9LFxcXCIlblxcXCI6ZnVuY3Rpb24oKXtyZXR1cm5cXFwiXFxcXG5cXFwifSxcXFwiJXBcXFwiOmZ1bmN0aW9uKGcpe3JldHVybiAwPD1nLmRjJiYxMj5nLmRjP1xcXCJBTVxcXCI6XFxcIlBNXFxcIn0sXFxcIiVTXFxcIjpmdW5jdGlvbihnKXtyZXR1cm4gaChnLkxjLDIpfSxcXFwiJXRcXFwiOmZ1bmN0aW9uKCl7cmV0dXJuXFxcIlxcXFx0XFxcIn0sXFxcIiV1XFxcIjpmdW5jdGlvbihnKXtyZXR1cm4gZy5UYnx8N30sXFxcIiVVXFxcIjpmdW5jdGlvbihnKXtyZXR1cm4gaChNYXRoLmZsb29yKChnLldiKzctZy5UYikvNyksMil9LFxcXCIlVlxcXCI6ZnVuY3Rpb24oZyl7dmFyIHc9TWF0aC5mbG9vcigoZy5XYis3LShnLlRiKzYpJTcpLzcpOzI+PShnLlRiKzM3MS1nLldiLTIpJTcmJncrKztpZih3KTUzPT13JiYoej0oZy5UYiszNzEtZy5XYiklNyw0PT16fHwzPT16JiZZYihnLlhiKXx8KHc9MSkpO2Vsc2V7dz01Mjt2YXIgej0oZy5UYis3LWcuV2ItMSklNzsoND09enx8NT09eiYmWWIoZy5YYiU0MDAtMSkpJiZ3Kyt9cmV0dXJuIGgodyxcXHJcXG4yKX0sXFxcIiV3XFxcIjpmdW5jdGlvbihnKXtyZXR1cm4gZy5UYn0sXFxcIiVXXFxcIjpmdW5jdGlvbihnKXtyZXR1cm4gaChNYXRoLmZsb29yKChnLldiKzctKGcuVGIrNiklNykvNyksMil9LFxcXCIleVxcXCI6ZnVuY3Rpb24oZyl7cmV0dXJuKGcuWGIrMTkwMCkudG9TdHJpbmcoKS5zdWJzdHJpbmcoMil9LFxcXCIlWVxcXCI6ZnVuY3Rpb24oZyl7cmV0dXJuIGcuWGIrMTkwMH0sXFxcIiV6XFxcIjpmdW5jdGlvbihnKXtnPWcuSmM7dmFyIHc9MDw9ZztnPU1hdGguYWJzKGcpLzYwO3JldHVybih3P1xcXCIrXFxcIjpcXFwiLVxcXCIpK1N0cmluZyhcXFwiMDAwMFxcXCIrKGcvNjAqMTAwK2clNjApKS5zbGljZSgtNCl9LFxcXCIlWlxcXCI6ZnVuY3Rpb24oZyl7cmV0dXJuIGcuTWN9LFxcXCIlJVxcXCI6ZnVuY3Rpb24oKXtyZXR1cm5cXFwiJVxcXCJ9fTtjPWMucmVwbGFjZSgvJSUvZyxcXFwiXFxcXHgwMFxcXFx4MDBcXFwiKTtmb3IoQSBpbiB0KWMuaW5jbHVkZXMoQSkmJihjPWMucmVwbGFjZShuZXcgUmVnRXhwKEEsXFxcImdcXFwiKSx0W0FdKGUpKSk7Yz1jLnJlcGxhY2UoL1xcXFwwXFxcXDAvZyxcXFwiJVxcXCIpO0E9YWMoYyk7aWYoQS5sZW5ndGg+XFxyXFxuYilyZXR1cm4gMDtmYihBLGEpO3JldHVybiBBLmxlbmd0aC0xfVAuZmMoKTtcXHJcXG52YXIgY2M9W251bGwsU2EsVWEsbGIsbmIsb2IscGIscWIscmIsc2IsdGIsdWIsdmIsd2IseGIseWIsemIsQ2IsRGIsR2IsUWIsUmIsU2IsVGIsVWIsVmJdLFBjPXtiOmZ1bmN0aW9uKGEpe3JldHVybiBGYihhKzI0KSsyNH0sbjpmdW5jdGlvbihhKXthPW5ldyBYKGEpO2EudWMoKXx8KGEuaGMoITApLGhiLS0pO2EuaWMoITEpO2diLnB1c2goYSk7YS5zYygpO3JldHVybiBhLnZjKCl9LG1hOmZ1bmN0aW9uKGEpe0coXFxcIlVuZXhwZWN0ZWQgZXhjZXB0aW9uIHRocm93biwgdGhpcyBpcyBub3QgcHJvcGVybHkgc3VwcG9ydGVkIC0gYWJvcnRpbmdcXFwiKTt4YT0hMDt0aHJvdyBhO30seDpmdW5jdGlvbigpe1ooMCk7dmFyIGE9Z2IucG9wKCk7aWYoYS5IYygpJiYhYS5rYygpKXt2YXIgYj1hLkRjKCk7YiYmVihiKShhLlpiKTtqYihhLlpiKX1XPTB9LGU6ZnVuY3Rpb24oKXt2YXIgYT1XO2lmKCFhKXJldHVybiBZPTA7dmFyIGI9bmV3IFgoYSk7Yi5jYyhhKTt2YXIgYz1iLmJjKCk7aWYoIWMpcmV0dXJuIFk9XFxyXFxuMCxhO2Zvcih2YXIgZT1BcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMpLGY9MDtmPGUubGVuZ3RoO2YrKyl7dmFyIGg9ZVtmXTtpZigwPT09aHx8aD09PWMpYnJlYWs7aWYoZGMoaCxjLGIuU2IrMTYpKXJldHVybiBZPWgsYX1ZPWM7cmV0dXJuIGF9LGw6ZnVuY3Rpb24oKXt2YXIgYT1XO2lmKCFhKXJldHVybiBZPTA7dmFyIGI9bmV3IFgoYSk7Yi5jYyhhKTt2YXIgYz1iLmJjKCk7aWYoIWMpcmV0dXJuIFk9MCxhO2Zvcih2YXIgZT1BcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMpLGY9MDtmPGUubGVuZ3RoO2YrKyl7dmFyIGg9ZVtmXTtpZigwPT09aHx8aD09PWMpYnJlYWs7aWYoZGMoaCxjLGIuU2IrMTYpKXJldHVybiBZPWgsYX1ZPWM7cmV0dXJuIGF9LGg6ZnVuY3Rpb24oKXt2YXIgYT1XO2lmKCFhKXJldHVybiBZPTA7dmFyIGI9bmV3IFgoYSk7Yi5jYyhhKTt2YXIgYz1iLmJjKCk7aWYoIWMpcmV0dXJuIFk9MCxhO2Zvcih2YXIgZT1BcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMpLFxcclxcbmY9MDtmPGUubGVuZ3RoO2YrKyl7dmFyIGg9ZVtmXTtpZigwPT09aHx8aD09PWMpYnJlYWs7aWYoZGMoaCxjLGIuU2IrMTYpKXJldHVybiBZPWgsYX1ZPWM7cmV0dXJuIGF9LHQ6amIsTTpmdW5jdGlvbigpe3ZhciBhPWdiLnBvcCgpO2F8fEkoXFxcIm5vIGV4Y2VwdGlvbiB0byB0aHJvd1xcXCIpO3ZhciBiPWEuWmI7YS5rYygpfHwoZ2IucHVzaChhKSxhLmljKCEwKSxhLmhjKCExKSxoYisrKTtXPWI7dGhyb3cgYjt9LGM6ZnVuY3Rpb24oYSxiLGMpeyhuZXcgWChhKSkuZmMoYixjKTtXPWE7aGIrKzt0aHJvdyBhO30scGE6ZnVuY3Rpb24oKXtyZXR1cm4gaGJ9LEZhOmZ1bmN0aW9uKGEpe2VjKGEsIXksMSwhbWEpO1AucGMoKX0sVDpmdW5jdGlvbihhKXtDP3Bvc3RNZXNzYWdlKHtjbWQ6XFxcImNsZWFudXBUaHJlYWRcXFwiLHRocmVhZDphfSk6UWEoYSl9LHhhOm1iLGo6ZnVuY3Rpb24oYSl7V3x8KFc9YSk7dGhyb3cgYTt9LEg6bmIsTWE6b2IsdWE6cGIsd2E6cWIsb2E6cmIsS2E6c2IsQ2E6dGIsSmE6dWIsXFxyXFxuVjp2Yix2YTp3YixzYTp4YixMYTp5Yix0YTp6YixUYTpmdW5jdGlvbigpe30sWDpmdW5jdGlvbigpe0koXFxcIlRvIHVzZSBkbG9wZW4sIHlvdSBuZWVkIGVuYWJsZSBkeW5hbWljIGxpbmtpbmcsIHNlZSBodHRwczovL2dpdGh1Yi5jb20vZW1zY3JpcHRlbi1jb3JlL2Vtc2NyaXB0ZW4vd2lraS9MaW5raW5nXFxcIil9LFVhOmZ1bmN0aW9uKCl7SShcXFwiVG8gdXNlIGRsb3BlbiwgeW91IG5lZWQgZW5hYmxlIGR5bmFtaWMgbGlua2luZywgc2VlIGh0dHBzOi8vZ2l0aHViLmNvbS9lbXNjcmlwdGVuLWNvcmUvZW1zY3JpcHRlbi93aWtpL0xpbmtpbmdcXFwiKX0sVzpmdW5jdGlvbigpe3JldHVybiBEYXRlLm5vdygpfSx5YTpmdW5jdGlvbigpe3JldHVybiAyMDk3MTUyfSxPYTpmdW5jdGlvbigpe3JldHVybiEwfSx6YTpmdW5jdGlvbihhLGIsYyxlKXtpZihhPT1iKXNldFRpbWVvdXQoKCk9PmFiKGUpKTtlbHNlIGlmKEMpcG9zdE1lc3NhZ2Uoe3RhcmdldFRocmVhZDphLGNtZDpcXFwicHJvY2Vzc1Byb3h5aW5nUXVldWVcXFwiLFxcclxcbnF1ZXVlOmV9KTtlbHNle2E9UC5WYlthXTtpZighYSlyZXR1cm47YS5wb3N0TWVzc2FnZSh7Y21kOlxcXCJwcm9jZXNzUHJveHlpbmdRdWV1ZVxcXCIscXVldWU6ZX0pfXJldHVybiAxfSxFYTpmdW5jdGlvbigpe3JldHVybi0xfSxQYTpmdW5jdGlvbihhLGIpe2E9bmV3IERhdGUoMUUzKkJiKGEpKTtyKClbYj4+Mj4+PjBdPWEuZ2V0VVRDU2Vjb25kcygpO3IoKVtiKzQ+PjI+Pj4wXT1hLmdldFVUQ01pbnV0ZXMoKTtyKClbYis4Pj4yPj4+MF09YS5nZXRVVENIb3VycygpO3IoKVtiKzEyPj4yPj4+MF09YS5nZXRVVENEYXRlKCk7cigpW2IrMTY+PjI+Pj4wXT1hLmdldFVUQ01vbnRoKCk7cigpW2IrMjA+PjI+Pj4wXT1hLmdldFVUQ0Z1bGxZZWFyKCktMTkwMDtyKClbYisyND4+Mj4+PjBdPWEuZ2V0VVRDRGF5KCk7YT0oYS5nZXRUaW1lKCktRGF0ZS5VVEMoYS5nZXRVVENGdWxsWWVhcigpLDAsMSwwLDAsMCwwKSkvODY0RTV8MDtyKClbYisyOD4+Mj4+PjBdPWF9LFFhOmZ1bmN0aW9uKGEsYil7YT1cXHJcXG5uZXcgRGF0ZSgxRTMqQmIoYSkpO3IoKVtiPj4yPj4+MF09YS5nZXRTZWNvbmRzKCk7cigpW2IrND4+Mj4+PjBdPWEuZ2V0TWludXRlcygpO3IoKVtiKzg+PjI+Pj4wXT1hLmdldEhvdXJzKCk7cigpW2IrMTI+PjI+Pj4wXT1hLmdldERhdGUoKTtyKClbYisxNj4+Mj4+PjBdPWEuZ2V0TW9udGgoKTtyKClbYisyMD4+Mj4+PjBdPWEuZ2V0RnVsbFllYXIoKS0xOTAwO3IoKVtiKzI0Pj4yPj4+MF09YS5nZXREYXkoKTt2YXIgYz1uZXcgRGF0ZShhLmdldEZ1bGxZZWFyKCksMCwxKSxlPShhLmdldFRpbWUoKS1jLmdldFRpbWUoKSkvODY0RTV8MDtyKClbYisyOD4+Mj4+PjBdPWU7cigpW2IrMzY+PjI+Pj4wXT0tKDYwKmEuZ2V0VGltZXpvbmVPZmZzZXQoKSk7ZT0obmV3IERhdGUoYS5nZXRGdWxsWWVhcigpLDYsMSkpLmdldFRpbWV6b25lT2Zmc2V0KCk7Yz1jLmdldFRpbWV6b25lT2Zmc2V0KCk7YT0oZSE9YyYmYS5nZXRUaW1lem9uZU9mZnNldCgpPT1NYXRoLm1pbihjLGUpKXwwO3IoKVtiK1xcclxcbjMyPj4yPj4+MF09YX0sUmE6ZnVuY3Rpb24oYSl7dmFyIGI9bmV3IERhdGUocigpW2ErMjA+PjI+Pj4wXSsxOTAwLHIoKVthKzE2Pj4yPj4+MF0scigpW2ErMTI+PjI+Pj4wXSxyKClbYSs4Pj4yPj4+MF0scigpW2ErND4+Mj4+PjBdLHIoKVthPj4yPj4+MF0sMCksYz1yKClbYSszMj4+Mj4+PjBdLGU9Yi5nZXRUaW1lem9uZU9mZnNldCgpLGY9bmV3IERhdGUoYi5nZXRGdWxsWWVhcigpLDAsMSksaD0obmV3IERhdGUoYi5nZXRGdWxsWWVhcigpLDYsMSkpLmdldFRpbWV6b25lT2Zmc2V0KCksaz1mLmdldFRpbWV6b25lT2Zmc2V0KCksbD1NYXRoLm1pbihrLGgpOzA+Yz9yKClbYSszMj4+Mj4+PjBdPU51bWJlcihoIT1rJiZsPT1lKTowPGMhPShsPT1lKSYmKGg9TWF0aC5tYXgoayxoKSxiLnNldFRpbWUoYi5nZXRUaW1lKCkrNkU0KigoMDxjP2w6aCktZSkpKTtyKClbYSsyND4+Mj4+PjBdPWIuZ2V0RGF5KCk7Yz0oYi5nZXRUaW1lKCktZi5nZXRUaW1lKCkpLzg2NEU1fDA7cigpW2ErMjg+PlxcclxcbjI+Pj4wXT1jO3IoKVthPj4yPj4+MF09Yi5nZXRTZWNvbmRzKCk7cigpW2ErND4+Mj4+PjBdPWIuZ2V0TWludXRlcygpO3IoKVthKzg+PjI+Pj4wXT1iLmdldEhvdXJzKCk7cigpW2ErMTI+PjI+Pj4wXT1iLmdldERhdGUoKTtyKClbYSsxNj4+Mj4+PjBdPWIuZ2V0TW9udGgoKTtyZXR1cm4gYi5nZXRUaW1lKCkvMUUzfDB9LEFhOkNiLEJhOkRiLFNhOkhiLHk6ZnVuY3Rpb24oKXtJKFxcXCJcXFwiKX0sVTpmdW5jdGlvbigpe2lmKCFCJiYheSl7dmFyIGE9XFxcIkJsb2NraW5nIG9uIHRoZSBtYWluIHRocmVhZCBpcyB2ZXJ5IGRhbmdlcm91cywgc2VlIGh0dHBzOi8vZW1zY3JpcHRlbi5vcmcvZG9jcy9wb3J0aW5nL3B0aHJlYWRzLmh0bWwjYmxvY2tpbmctb24tdGhlLW1haW4tYnJvd3Nlci10aHJlYWRcXFwiO0lifHwoSWI9e30pO0liW2FdfHwoSWJbYV09MSxCJiYoYT1cXFwid2FybmluZzogXFxcIithKSxHKGEpKX19LHJhOmZ1bmN0aW9uKCl7cmV0dXJuIDQyOTQ5MDE3NjB9LEI6SmIsSWE6ZnVuY3Rpb24oYSxiLFxcclxcbmMpe3EoKS5jb3B5V2l0aGluKGE+Pj4wLGI+Pj4wLGIrYz4+PjApfSxGOmZ1bmN0aW9uKCl7cmV0dXJuIEI/KF9fd2VicGFja19yZXF1aXJlX18oLyohIG9zICovIFxcXCI/YWVkYlxcXCIpLmNwdXMpKCkubGVuZ3RoOm5hdmlnYXRvci5oYXJkd2FyZUNvbmN1cnJlbmN5fSxEYTpmdW5jdGlvbihhLGIsYyl7TWIubGVuZ3RoPWI7Yz4+PTM7Zm9yKHZhciBlPTA7ZTxiO2UrKylNYltlXT1lYSgpW2MrZT4+PjBdO3JldHVybigwPmE/UGFbLWEtMV06Y2NbYV0pLmFwcGx5KG51bGwsTWIpfSxxYTpmdW5jdGlvbihhKXt2YXIgYj1xKCkubGVuZ3RoO2E+Pj49MDtpZihhPD1ifHw0Mjk0OTAxNzYwPGEpcmV0dXJuITE7Zm9yKHZhciBjPTE7ND49YztjKj0yKXt2YXIgZT1iKigxKy4yL2MpO2U9TWF0aC5taW4oZSxhKzEwMDY2MzI5Nik7dmFyIGY9TWF0aDtlPU1hdGgubWF4KGEsZSk7Zj1mLm1pbi5jYWxsKGYsNDI5NDkwMTc2MCxlKyg2NTUzNi1lJTY1NTM2KSU2NTUzNik7YTp7dHJ5e20uZ3JvdyhmLW4uYnl0ZUxlbmd0aCs2NTUzNT4+PjE2KTtwKG0uYnVmZmVyKTtcXHJcXG52YXIgaD0xO2JyZWFrIGF9Y2F0Y2goayl7fWg9dm9pZCAwfWlmKGgpcmV0dXJuITB9cmV0dXJuITF9LE5hOmZ1bmN0aW9uKCl7dGhyb3dcXFwidW53aW5kXFxcIjt9LEdhOlFiLEhhOlJiLEo6VGEsSTpTYixTOlRiLGdhOlViLFI6VmIsZDpmdW5jdGlvbigpe3JldHVybiBZfSxuYTpYYixpYTpmYyxqYTpnYyxLOmhjLGY6aWMsUDpqYyxROmtjLGs6bGMscDptYyxxOm5jLE46b2MsczpwYyx3OnFjLEw6cmMsRTpzYyxhYTp0YyxfOnVjLFo6dmMsY2E6d2MsJDp4YyxiYTp5YyxZOnpjLGc6QWMscjpCYyxpOkNjLGhhOkRjLG06RWMsdjpGYyx1OkdjLE86SGMsQTpJYyxrYTpKYyxDOktjLEQ6TGMsZmE6TWMsZGE6TmMsZWE6T2MsbzpmdW5jdGlvbihhKXtyZXR1cm4gYX0sYTptfHx4Lndhc21NZW1vcnksRzpmdW5jdGlvbihhKXtZPWF9LGxhOmJjLHo6ZnVuY3Rpb24oYSxiLGMsZSl7cmV0dXJuIGJjKGEsYixjLGUpfX07XFxyXFxuKGZ1bmN0aW9uKCl7ZnVuY3Rpb24gYShmLGgpe3guYXNtPWYuZXhwb3J0cztQLnFjLnB1c2goeC5hc20uc2IpO0VhPXguYXNtLnViO0dhLnVuc2hpZnQoeC5hc20uVmEpO3dhPWg7Q3x8KEwtLSx4Lm1vbml0b3JSdW5EZXBlbmRlbmNpZXMmJngubW9uaXRvclJ1bkRlcGVuZGVuY2llcyhMKSwwPT1MJiYobnVsbCE9PUxhJiYoY2xlYXJJbnRlcnZhbChMYSksTGE9bnVsbCksTSYmKGY9TSxNPW51bGwsZigpKSkpfWZ1bmN0aW9uIGIoZil7YShmLmluc3RhbmNlLGYubW9kdWxlKX1mdW5jdGlvbiBjKGYpe3JldHVybiBPYSgpLnRoZW4oZnVuY3Rpb24oaCl7cmV0dXJuIFdlYkFzc2VtYmx5Lmluc3RhbnRpYXRlKGgsZSl9KS50aGVuKGZ1bmN0aW9uKGgpe3JldHVybiBofSkudGhlbihmLGZ1bmN0aW9uKGgpe0coXFxcImZhaWxlZCB0byBhc3luY2hyb25vdXNseSBwcmVwYXJlIHdhc206IFxcXCIraCk7SShoKX0pfXZhciBlPXthOlBjfTtDfHwoTCsrLHgubW9uaXRvclJ1bkRlcGVuZGVuY2llcyYmeC5tb25pdG9yUnVuRGVwZW5kZW5jaWVzKEwpKTtcXHJcXG5pZih4Lmluc3RhbnRpYXRlV2FzbSl0cnl7cmV0dXJuIHguaW5zdGFudGlhdGVXYXNtKGUsYSl9Y2F0Y2goZil7cmV0dXJuIEcoXFxcIk1vZHVsZS5pbnN0YW50aWF0ZVdhc20gY2FsbGJhY2sgZmFpbGVkIHdpdGggZXJyb3I6IFxcXCIrZiksITF9KGZ1bmN0aW9uKCl7cmV0dXJuIEh8fFxcXCJmdW5jdGlvblxcXCIhPXR5cGVvZiBXZWJBc3NlbWJseS5pbnN0YW50aWF0ZVN0cmVhbWluZ3x8TWEoKXx8Ty5zdGFydHNXaXRoKFxcXCJmaWxlOi8vXFxcIil8fEJ8fFxcXCJmdW5jdGlvblxcXCIhPXR5cGVvZiBmZXRjaD9jKGIpOmZldGNoKE8se2NyZWRlbnRpYWxzOlxcXCJzYW1lLW9yaWdpblxcXCJ9KS50aGVuKGZ1bmN0aW9uKGYpe3JldHVybiBXZWJBc3NlbWJseS5pbnN0YW50aWF0ZVN0cmVhbWluZyhmLGUpLnRoZW4oYixmdW5jdGlvbihoKXtHKFxcXCJ3YXNtIHN0cmVhbWluZyBjb21waWxlIGZhaWxlZDogXFxcIitoKTtHKFxcXCJmYWxsaW5nIGJhY2sgdG8gQXJyYXlCdWZmZXIgaW5zdGFudGlhdGlvblxcXCIpO3JldHVybiBjKGIpfSl9KX0pKCkuY2F0Y2goaWEpO1xcclxcbnJldHVybnt9fSkoKTt4Ll9fX3dhc21fY2FsbF9jdG9ycz1mdW5jdGlvbigpe3JldHVybih4Ll9fX3dhc21fY2FsbF9jdG9ycz14LmFzbS5WYSkuYXBwbHkobnVsbCxhcmd1bWVudHMpfTt4Ll9PcnRJbml0PWZ1bmN0aW9uKCl7cmV0dXJuKHguX09ydEluaXQ9eC5hc20uV2EpLmFwcGx5KG51bGwsYXJndW1lbnRzKX07eC5fT3J0Q3JlYXRlU2Vzc2lvbk9wdGlvbnM9ZnVuY3Rpb24oKXtyZXR1cm4oeC5fT3J0Q3JlYXRlU2Vzc2lvbk9wdGlvbnM9eC5hc20uWGEpLmFwcGx5KG51bGwsYXJndW1lbnRzKX07eC5fT3J0QXBwZW5kRXhlY3V0aW9uUHJvdmlkZXI9ZnVuY3Rpb24oKXtyZXR1cm4oeC5fT3J0QXBwZW5kRXhlY3V0aW9uUHJvdmlkZXI9eC5hc20uWWEpLmFwcGx5KG51bGwsYXJndW1lbnRzKX07eC5fT3J0QWRkU2Vzc2lvbkNvbmZpZ0VudHJ5PWZ1bmN0aW9uKCl7cmV0dXJuKHguX09ydEFkZFNlc3Npb25Db25maWdFbnRyeT14LmFzbS5aYSkuYXBwbHkobnVsbCxhcmd1bWVudHMpfTtcXHJcXG54Ll9PcnRSZWxlYXNlU2Vzc2lvbk9wdGlvbnM9ZnVuY3Rpb24oKXtyZXR1cm4oeC5fT3J0UmVsZWFzZVNlc3Npb25PcHRpb25zPXguYXNtLl9hKS5hcHBseShudWxsLGFyZ3VtZW50cyl9O3guX09ydENyZWF0ZVNlc3Npb249ZnVuY3Rpb24oKXtyZXR1cm4oeC5fT3J0Q3JlYXRlU2Vzc2lvbj14LmFzbS4kYSkuYXBwbHkobnVsbCxhcmd1bWVudHMpfTt4Ll9PcnRSZWxlYXNlU2Vzc2lvbj1mdW5jdGlvbigpe3JldHVybih4Ll9PcnRSZWxlYXNlU2Vzc2lvbj14LmFzbS5hYikuYXBwbHkobnVsbCxhcmd1bWVudHMpfTt4Ll9PcnRHZXRJbnB1dENvdW50PWZ1bmN0aW9uKCl7cmV0dXJuKHguX09ydEdldElucHV0Q291bnQ9eC5hc20uYmIpLmFwcGx5KG51bGwsYXJndW1lbnRzKX07eC5fT3J0R2V0T3V0cHV0Q291bnQ9ZnVuY3Rpb24oKXtyZXR1cm4oeC5fT3J0R2V0T3V0cHV0Q291bnQ9eC5hc20uY2IpLmFwcGx5KG51bGwsYXJndW1lbnRzKX07XFxyXFxueC5fT3J0R2V0SW5wdXROYW1lPWZ1bmN0aW9uKCl7cmV0dXJuKHguX09ydEdldElucHV0TmFtZT14LmFzbS5kYikuYXBwbHkobnVsbCxhcmd1bWVudHMpfTt4Ll9PcnRHZXRPdXRwdXROYW1lPWZ1bmN0aW9uKCl7cmV0dXJuKHguX09ydEdldE91dHB1dE5hbWU9eC5hc20uZWIpLmFwcGx5KG51bGwsYXJndW1lbnRzKX07eC5fT3J0RnJlZT1mdW5jdGlvbigpe3JldHVybih4Ll9PcnRGcmVlPXguYXNtLmZiKS5hcHBseShudWxsLGFyZ3VtZW50cyl9O3guX09ydENyZWF0ZVRlbnNvcj1mdW5jdGlvbigpe3JldHVybih4Ll9PcnRDcmVhdGVUZW5zb3I9eC5hc20uZ2IpLmFwcGx5KG51bGwsYXJndW1lbnRzKX07eC5fT3J0R2V0VGVuc29yRGF0YT1mdW5jdGlvbigpe3JldHVybih4Ll9PcnRHZXRUZW5zb3JEYXRhPXguYXNtLmhiKS5hcHBseShudWxsLGFyZ3VtZW50cyl9O1xcclxcbnguX09ydFJlbGVhc2VUZW5zb3I9ZnVuY3Rpb24oKXtyZXR1cm4oeC5fT3J0UmVsZWFzZVRlbnNvcj14LmFzbS5pYikuYXBwbHkobnVsbCxhcmd1bWVudHMpfTt4Ll9PcnRDcmVhdGVSdW5PcHRpb25zPWZ1bmN0aW9uKCl7cmV0dXJuKHguX09ydENyZWF0ZVJ1bk9wdGlvbnM9eC5hc20uamIpLmFwcGx5KG51bGwsYXJndW1lbnRzKX07eC5fT3J0QWRkUnVuQ29uZmlnRW50cnk9ZnVuY3Rpb24oKXtyZXR1cm4oeC5fT3J0QWRkUnVuQ29uZmlnRW50cnk9eC5hc20ua2IpLmFwcGx5KG51bGwsYXJndW1lbnRzKX07eC5fT3J0UmVsZWFzZVJ1bk9wdGlvbnM9ZnVuY3Rpb24oKXtyZXR1cm4oeC5fT3J0UmVsZWFzZVJ1bk9wdGlvbnM9eC5hc20ubGIpLmFwcGx5KG51bGwsYXJndW1lbnRzKX07eC5fT3J0UnVuPWZ1bmN0aW9uKCl7cmV0dXJuKHguX09ydFJ1bj14LmFzbS5tYikuYXBwbHkobnVsbCxhcmd1bWVudHMpfTtcXHJcXG54Ll9PcnRFbmRQcm9maWxpbmc9ZnVuY3Rpb24oKXtyZXR1cm4oeC5fT3J0RW5kUHJvZmlsaW5nPXguYXNtLm5iKS5hcHBseShudWxsLGFyZ3VtZW50cyl9O3ZhciAkYT14Ll9wdGhyZWFkX3NlbGY9ZnVuY3Rpb24oKXtyZXR1cm4oJGE9eC5fcHRocmVhZF9zZWxmPXguYXNtLm9iKS5hcHBseShudWxsLGFyZ3VtZW50cyl9LEZiPXguX21hbGxvYz1mdW5jdGlvbigpe3JldHVybihGYj14Ll9tYWxsb2M9eC5hc20ucGIpLmFwcGx5KG51bGwsYXJndW1lbnRzKX0sa2I9eC5fZnJlZT1mdW5jdGlvbigpe3JldHVybihrYj14Ll9mcmVlPXguYXNtLnFiKS5hcHBseShudWxsLGFyZ3VtZW50cyl9LFdhPXguX2ZmbHVzaD1mdW5jdGlvbigpe3JldHVybihXYT14Ll9mZmx1c2g9eC5hc20ucmIpLmFwcGx5KG51bGwsYXJndW1lbnRzKX07eC5fX2Vtc2NyaXB0ZW5fdGxzX2luaXQ9ZnVuY3Rpb24oKXtyZXR1cm4oeC5fX2Vtc2NyaXB0ZW5fdGxzX2luaXQ9eC5hc20uc2IpLmFwcGx5KG51bGwsYXJndW1lbnRzKX07XFxyXFxudmFyIFZhPXguX19fZnVuY3Nfb25fZXhpdD1mdW5jdGlvbigpe3JldHVybihWYT14Ll9fX2Z1bmNzX29uX2V4aXQ9eC5hc20udGIpLmFwcGx5KG51bGwsYXJndW1lbnRzKX0sZWM9eC5fX2Vtc2NyaXB0ZW5fdGhyZWFkX2luaXQ9ZnVuY3Rpb24oKXtyZXR1cm4oZWM9eC5fX2Vtc2NyaXB0ZW5fdGhyZWFkX2luaXQ9eC5hc20udmIpLmFwcGx5KG51bGwsYXJndW1lbnRzKX07eC5fX2Vtc2NyaXB0ZW5fdGhyZWFkX2NyYXNoZWQ9ZnVuY3Rpb24oKXtyZXR1cm4oeC5fX2Vtc2NyaXB0ZW5fdGhyZWFkX2NyYXNoZWQ9eC5hc20ud2IpLmFwcGx5KG51bGwsYXJndW1lbnRzKX07XFxyXFxudmFyIExiPXguX2Vtc2NyaXB0ZW5fcnVuX2luX21haW5fcnVudGltZV90aHJlYWRfanM9ZnVuY3Rpb24oKXtyZXR1cm4oTGI9eC5fZW1zY3JpcHRlbl9ydW5faW5fbWFpbl9ydW50aW1lX3RocmVhZF9qcz14LmFzbS54YikuYXBwbHkobnVsbCxhcmd1bWVudHMpfSxBYj14Ll9fZW1zY3JpcHRlbl9wcm94eV9leGVjdXRlX3Rhc2tfcXVldWU9ZnVuY3Rpb24oKXtyZXR1cm4oQWI9eC5fX2Vtc2NyaXB0ZW5fcHJveHlfZXhlY3V0ZV90YXNrX3F1ZXVlPXguYXNtLnliKS5hcHBseShudWxsLGFyZ3VtZW50cyl9LFphPXguX19lbXNjcmlwdGVuX3RocmVhZF9mcmVlX2RhdGE9ZnVuY3Rpb24oKXtyZXR1cm4oWmE9eC5fX2Vtc2NyaXB0ZW5fdGhyZWFkX2ZyZWVfZGF0YT14LmFzbS56YikuYXBwbHkobnVsbCxhcmd1bWVudHMpfSxlYj14Ll9fZW1zY3JpcHRlbl90aHJlYWRfZXhpdD1mdW5jdGlvbigpe3JldHVybihlYj14Ll9fZW1zY3JpcHRlbl90aHJlYWRfZXhpdD14LmFzbS5BYikuYXBwbHkobnVsbCxcXHJcXG5hcmd1bWVudHMpfSxaPXguX3NldFRocmV3PWZ1bmN0aW9uKCl7cmV0dXJuKFo9eC5fc2V0VGhyZXc9eC5hc20uQmIpLmFwcGx5KG51bGwsYXJndW1lbnRzKX0sY2I9eC5fZW1zY3JpcHRlbl9zdGFja19zZXRfbGltaXRzPWZ1bmN0aW9uKCl7cmV0dXJuKGNiPXguX2Vtc2NyaXB0ZW5fc3RhY2tfc2V0X2xpbWl0cz14LmFzbS5DYikuYXBwbHkobnVsbCxhcmd1bWVudHMpfSxTPXguc3RhY2tTYXZlPWZ1bmN0aW9uKCl7cmV0dXJuKFM9eC5zdGFja1NhdmU9eC5hc20uRGIpLmFwcGx5KG51bGwsYXJndW1lbnRzKX0sVT14LnN0YWNrUmVzdG9yZT1mdW5jdGlvbigpe3JldHVybihVPXguc3RhY2tSZXN0b3JlPXguYXNtLkViKS5hcHBseShudWxsLGFyZ3VtZW50cyl9LEtiPXguc3RhY2tBbGxvYz1mdW5jdGlvbigpe3JldHVybihLYj14LnN0YWNrQWxsb2M9eC5hc20uRmIpLmFwcGx5KG51bGwsYXJndW1lbnRzKX0sZGM9eC5fX19jeGFfY2FuX2NhdGNoPWZ1bmN0aW9uKCl7cmV0dXJuKGRjPXguX19fY3hhX2Nhbl9jYXRjaD1cXHJcXG54LmFzbS5HYikuYXBwbHkobnVsbCxhcmd1bWVudHMpfSxpYj14Ll9fX2N4YV9pc19wb2ludGVyX3R5cGU9ZnVuY3Rpb24oKXtyZXR1cm4oaWI9eC5fX19jeGFfaXNfcG9pbnRlcl90eXBlPXguYXNtLkhiKS5hcHBseShudWxsLGFyZ3VtZW50cyl9LFFjPXguZHluQ2FsbF9qPWZ1bmN0aW9uKCl7cmV0dXJuKFFjPXguZHluQ2FsbF9qPXguYXNtLkliKS5hcHBseShudWxsLGFyZ3VtZW50cyl9LFJjPXguZHluQ2FsbF9paWlpaWo9ZnVuY3Rpb24oKXtyZXR1cm4oUmM9eC5keW5DYWxsX2lpaWlpaj14LmFzbS5KYikuYXBwbHkobnVsbCxhcmd1bWVudHMpfSxTYz14LmR5bkNhbGxfamlpPWZ1bmN0aW9uKCl7cmV0dXJuKFNjPXguZHluQ2FsbF9qaWk9eC5hc20uS2IpLmFwcGx5KG51bGwsYXJndW1lbnRzKX0sVGM9eC5keW5DYWxsX3ZpaWlpaWo9ZnVuY3Rpb24oKXtyZXR1cm4oVGM9eC5keW5DYWxsX3ZpaWlpaWo9eC5hc20uTGIpLmFwcGx5KG51bGwsYXJndW1lbnRzKX0sVWM9eC5keW5DYWxsX3Zqamk9XFxyXFxuZnVuY3Rpb24oKXtyZXR1cm4oVWM9eC5keW5DYWxsX3Zqamk9eC5hc20uTWIpLmFwcGx5KG51bGwsYXJndW1lbnRzKX0sVmM9eC5keW5DYWxsX3ZpaWlqamppaT1mdW5jdGlvbigpe3JldHVybihWYz14LmR5bkNhbGxfdmlpaWpqamlpPXguYXNtLk5iKS5hcHBseShudWxsLGFyZ3VtZW50cyl9LFdjPXguZHluQ2FsbF9paWo9ZnVuY3Rpb24oKXtyZXR1cm4oV2M9eC5keW5DYWxsX2lpaj14LmFzbS5PYikuYXBwbHkobnVsbCxhcmd1bWVudHMpfSxYYz14LmR5bkNhbGxfamk9ZnVuY3Rpb24oKXtyZXR1cm4oWGM9eC5keW5DYWxsX2ppPXguYXNtLlBiKS5hcHBseShudWxsLGFyZ3VtZW50cyl9LFljPXguZHluQ2FsbF9paWlpaWlqPWZ1bmN0aW9uKCl7cmV0dXJuKFljPXguZHluQ2FsbF9paWlpaWlqPXguYXNtLlFiKS5hcHBseShudWxsLGFyZ3VtZW50cyl9LFpjPXguZHluQ2FsbF9paWlqPWZ1bmN0aW9uKCl7cmV0dXJuKFpjPXguZHluQ2FsbF9paWlqPXguYXNtLlJiKS5hcHBseShudWxsLFxcclxcbmFyZ3VtZW50cyl9O2Z1bmN0aW9uIGljKGEsYil7dmFyIGM9UygpO3RyeXtyZXR1cm4gVihhKShiKX1jYXRjaChlKXtVKGMpO2lmKGUhPT1lKzApdGhyb3cgZTtaKDEsMCl9fWZ1bmN0aW9uIEJjKGEsYil7dmFyIGM9UygpO3RyeXtWKGEpKGIpfWNhdGNoKGUpe1UoYyk7aWYoZSE9PWUrMCl0aHJvdyBlO1ooMSwwKX19ZnVuY3Rpb24gQ2MoYSxiLGMpe3ZhciBlPVMoKTt0cnl7VihhKShiLGMpfWNhdGNoKGYpe1UoZSk7aWYoZiE9PWYrMCl0aHJvdyBmO1ooMSwwKX19ZnVuY3Rpb24gbGMoYSxiLGMpe3ZhciBlPVMoKTt0cnl7cmV0dXJuIFYoYSkoYixjKX1jYXRjaChmKXtVKGUpO2lmKGYhPT1mKzApdGhyb3cgZjtaKDEsMCl9fWZ1bmN0aW9uIG1jKGEsYixjLGUpe3ZhciBmPVMoKTt0cnl7cmV0dXJuIFYoYSkoYixjLGUpfWNhdGNoKGgpe1UoZik7aWYoaCE9PWgrMCl0aHJvdyBoO1ooMSwwKX19XFxyXFxuZnVuY3Rpb24gcWMoYSxiLGMsZSxmLGgsayl7dmFyIGw9UygpO3RyeXtyZXR1cm4gVihhKShiLGMsZSxmLGgsayl9Y2F0Y2godSl7VShsKTtpZih1IT09dSswKXRocm93IHU7WigxLDApfX1mdW5jdGlvbiBBYyhhKXt2YXIgYj1TKCk7dHJ5e1YoYSkoKX1jYXRjaChjKXtVKGIpO2lmKGMhPT1jKzApdGhyb3cgYztaKDEsMCl9fWZ1bmN0aW9uIHBjKGEsYixjLGUsZixoKXt2YXIgaz1TKCk7dHJ5e3JldHVybiBWKGEpKGIsYyxlLGYsaCl9Y2F0Y2gobCl7VShrKTtpZihsIT09bCswKXRocm93IGw7WigxLDApfX1mdW5jdGlvbiBuYyhhLGIsYyxlLGYpe3ZhciBoPVMoKTt0cnl7cmV0dXJuIFYoYSkoYixjLGUsZil9Y2F0Y2goayl7VShoKTtpZihrIT09ayswKXRocm93IGs7WigxLDApfX1mdW5jdGlvbiBFYyhhLGIsYyxlKXt2YXIgZj1TKCk7dHJ5e1YoYSkoYixjLGUpfWNhdGNoKGgpe1UoZik7aWYoaCE9PWgrMCl0aHJvdyBoO1ooMSwwKX19XFxyXFxuZnVuY3Rpb24gR2MoYSxiLGMsZSxmLGgpe3ZhciBrPVMoKTt0cnl7VihhKShiLGMsZSxmLGgpfWNhdGNoKGwpe1Uoayk7aWYobCE9PWwrMCl0aHJvdyBsO1ooMSwwKX19ZnVuY3Rpb24gRmMoYSxiLGMsZSxmKXt2YXIgaD1TKCk7dHJ5e1YoYSkoYixjLGUsZil9Y2F0Y2goayl7VShoKTtpZihrIT09ayswKXRocm93IGs7WigxLDApfX1mdW5jdGlvbiBJYyhhLGIsYyxlLGYsaCxrLGwpe3ZhciB1PVMoKTt0cnl7VihhKShiLGMsZSxmLGgsayxsKX1jYXRjaCh0KXtVKHUpO2lmKHQhPT10KzApdGhyb3cgdDtaKDEsMCl9fWZ1bmN0aW9uIGtjKGEsYixjKXt2YXIgZT1TKCk7dHJ5e3JldHVybiBWKGEpKGIsYyl9Y2F0Y2goZil7VShlKTtpZihmIT09ZiswKXRocm93IGY7WigxLDApfX1mdW5jdGlvbiBqYyhhLGIsYyl7dmFyIGU9UygpO3RyeXtyZXR1cm4gVihhKShiLGMpfWNhdGNoKGYpe1UoZSk7aWYoZiE9PWYrMCl0aHJvdyBmO1ooMSwwKX19XFxyXFxuZnVuY3Rpb24gSmMoYSxiLGMsZSxmLGgsayxsLHUpe3ZhciB0PVMoKTt0cnl7VihhKShiLGMsZSxmLGgsayxsLHUpfWNhdGNoKEEpe1UodCk7aWYoQSE9PUErMCl0aHJvdyBBO1ooMSwwKX19ZnVuY3Rpb24gSGMoYSxiLGMsZSxmLGgsayl7dmFyIGw9UygpO3RyeXtWKGEpKGIsYyxlLGYsaCxrKX1jYXRjaCh1KXtVKGwpO2lmKHUhPT11KzApdGhyb3cgdTtaKDEsMCl9fWZ1bmN0aW9uIG9jKGEsYixjLGUsZixoKXt2YXIgaz1TKCk7dHJ5e3JldHVybiBWKGEpKGIsYyxlLGYsaCl9Y2F0Y2gobCl7VShrKTtpZihsIT09bCswKXRocm93IGw7WigxLDApfX1mdW5jdGlvbiByYyhhLGIsYyxlLGYsaCxrLGwpe3ZhciB1PVMoKTt0cnl7cmV0dXJuIFYoYSkoYixjLGUsZixoLGssbCl9Y2F0Y2godCl7VSh1KTtpZih0IT09dCswKXRocm93IHQ7WigxLDApfX1cXHJcXG5mdW5jdGlvbiBzYyhhLGIsYyxlLGYsaCxrLGwsdSx0LEEsSyl7dmFyIEo9UygpO3RyeXtyZXR1cm4gVihhKShiLGMsZSxmLGgsayxsLHUsdCxBLEspfWNhdGNoKGcpe1UoSik7aWYoZyE9PWcrMCl0aHJvdyBnO1ooMSwwKX19ZnVuY3Rpb24gS2MoYSxiLGMsZSxmLGgsayxsLHUsdCxBKXt2YXIgSz1TKCk7dHJ5e1YoYSkoYixjLGUsZixoLGssbCx1LHQsQSl9Y2F0Y2goSil7VShLKTtpZihKIT09SiswKXRocm93IEo7WigxLDApfX1mdW5jdGlvbiBMYyhhLGIsYyxlLGYsaCxrLGwsdSx0LEEsSyxKLGcsdyx6KXt2YXIgTj1TKCk7dHJ5e1YoYSkoYixjLGUsZixoLGssbCx1LHQsQSxLLEosZyx3LHopfWNhdGNoKFQpe1UoTik7aWYoVCE9PVQrMCl0aHJvdyBUO1ooMSwwKX19ZnVuY3Rpb24gaGMoYSl7dmFyIGI9UygpO3RyeXtyZXR1cm4gVihhKSgpfWNhdGNoKGMpe1UoYik7aWYoYyE9PWMrMCl0aHJvdyBjO1ooMSwwKX19XFxyXFxuZnVuY3Rpb24gZ2MoYSxiLGMpe3ZhciBlPVMoKTt0cnl7cmV0dXJuIFYoYSkoYixjKX1jYXRjaChmKXtVKGUpO2lmKGYhPT1mKzApdGhyb3cgZjtaKDEsMCl9fWZ1bmN0aW9uIGZjKGEsYixjKXt2YXIgZT1TKCk7dHJ5e3JldHVybiBWKGEpKGIsYyl9Y2F0Y2goZil7VShlKTtpZihmIT09ZiswKXRocm93IGY7WigxLDApfX1mdW5jdGlvbiBEYyhhLGIsYyxlKXt2YXIgZj1TKCk7dHJ5e1YoYSkoYixjLGUpfWNhdGNoKGgpe1UoZik7aWYoaCE9PWgrMCl0aHJvdyBoO1ooMSwwKX19ZnVuY3Rpb24gTWMoYSxiLGMsZSxmLGgsayxsKXt2YXIgdT1TKCk7dHJ5e1RjKGEsYixjLGUsZixoLGssbCl9Y2F0Y2godCl7VSh1KTtpZih0IT09dCswKXRocm93IHQ7WigxLDApfX1mdW5jdGlvbiBPYyhhLGIsYyxlLGYsaCl7dmFyIGs9UygpO3RyeXtVYyhhLGIsYyxlLGYsaCl9Y2F0Y2gobCl7VShrKTtpZihsIT09bCswKXRocm93IGw7WigxLDApfX1cXHJcXG5mdW5jdGlvbiBOYyhhLGIsYyxlLGYsaCxrLGwsdSx0LEEsSyl7dmFyIEo9UygpO3RyeXtWYyhhLGIsYyxlLGYsaCxrLGwsdSx0LEEsSyl9Y2F0Y2goZyl7VShKKTtpZihnIT09ZyswKXRocm93IGc7WigxLDApfX1mdW5jdGlvbiB3YyhhLGIsYyxlKXt2YXIgZj1TKCk7dHJ5e3JldHVybiBXYyhhLGIsYyxlKX1jYXRjaChoKXtVKGYpO2lmKGghPT1oKzApdGhyb3cgaDtaKDEsMCl9fWZ1bmN0aW9uIHljKGEsYil7dmFyIGM9UygpO3RyeXtyZXR1cm4gWGMoYSxiKX1jYXRjaChlKXtVKGMpO2lmKGUhPT1lKzApdGhyb3cgZTtaKDEsMCl9fWZ1bmN0aW9uIHRjKGEsYixjLGUsZixoLGssbCl7dmFyIHU9UygpO3RyeXtyZXR1cm4gWWMoYSxiLGMsZSxmLGgsayxsKX1jYXRjaCh0KXtVKHUpO2lmKHQhPT10KzApdGhyb3cgdDtaKDEsMCl9fWZ1bmN0aW9uIHhjKGEpe3ZhciBiPVMoKTt0cnl7cmV0dXJuIFFjKGEpfWNhdGNoKGMpe1UoYik7aWYoYyE9PWMrMCl0aHJvdyBjO1ooMSwwKX19XFxyXFxuZnVuY3Rpb24gdWMoYSxiLGMsZSxmLGgsayl7dmFyIGw9UygpO3RyeXtyZXR1cm4gUmMoYSxiLGMsZSxmLGgsayl9Y2F0Y2godSl7VShsKTtpZih1IT09dSswKXRocm93IHU7WigxLDApfX1mdW5jdGlvbiB2YyhhLGIsYyxlLGYpe3ZhciBoPVMoKTt0cnl7cmV0dXJuIFpjKGEsYixjLGUsZil9Y2F0Y2goayl7VShoKTtpZihrIT09ayswKXRocm93IGs7WigxLDApfX1mdW5jdGlvbiB6YyhhLGIsYyl7dmFyIGU9UygpO3RyeXtyZXR1cm4gU2MoYSxiLGMpfWNhdGNoKGYpe1UoZSk7aWYoZiE9PWYrMCl0aHJvdyBmO1ooMSwwKX19eC5VVEY4VG9TdHJpbmc9QWE7eC5zdHJpbmdUb1VURjg9ZnVuY3Rpb24oYSxiLGMpe3JldHVybiBCYShhLHEoKSxiLGMpfTt4Lmxlbmd0aEJ5dGVzVVRGOD1DYTt4LmtlZXBSdW50aW1lQWxpdmU9Rjt4Lndhc21NZW1vcnk9bTt4LnN0YWNrU2F2ZT1TO3guc3RhY2tSZXN0b3JlPVU7eC5zdGFja0FsbG9jPUtiO3guRXhpdFN0YXR1cz1FO3guUFRocmVhZD1QO3ZhciAkYztcXHJcXG5NPWZ1bmN0aW9uIGFkKCl7JGN8fGJkKCk7JGN8fChNPWFkKX07XFxyXFxuZnVuY3Rpb24gYmQoKXtmdW5jdGlvbiBhKCl7aWYoISRjJiYoJGM9ITAseC5jYWxsZWRSdW49ITAsIXhhKSl7Q3x8UihHYSk7aGEoeCk7aWYoeC5vblJ1bnRpbWVJbml0aWFsaXplZCl4Lm9uUnVudGltZUluaXRpYWxpemVkKCk7aWYoIUMpe2lmKHgucG9zdFJ1bilmb3IoXFxcImZ1bmN0aW9uXFxcIj09dHlwZW9mIHgucG9zdFJ1biYmKHgucG9zdFJ1bj1beC5wb3N0UnVuXSk7eC5wb3N0UnVuLmxlbmd0aDspe3ZhciBiPXgucG9zdFJ1bi5zaGlmdCgpO0lhLnVuc2hpZnQoYil9UihJYSl9fX1pZighKDA8TCkpaWYoQyloYSh4KSxDfHxSKEdhKSxwb3N0TWVzc2FnZSh7Y21kOlxcXCJsb2FkZWRcXFwifSk7ZWxzZXtpZih4LnByZVJ1bilmb3IoXFxcImZ1bmN0aW9uXFxcIj09dHlwZW9mIHgucHJlUnVuJiYoeC5wcmVSdW49W3gucHJlUnVuXSk7eC5wcmVSdW4ubGVuZ3RoOylLYSgpO1IoRmEpOzA8THx8KHguc2V0U3RhdHVzPyh4LnNldFN0YXR1cyhcXFwiUnVubmluZy4uLlxcXCIpLHNldFRpbWVvdXQoZnVuY3Rpb24oKXtzZXRUaW1lb3V0KGZ1bmN0aW9uKCl7eC5zZXRTdGF0dXMoXFxcIlxcXCIpfSxcXHJcXG4xKTthKCl9LDEpKTphKCkpfX1pZih4LnByZUluaXQpZm9yKFxcXCJmdW5jdGlvblxcXCI9PXR5cGVvZiB4LnByZUluaXQmJih4LnByZUluaXQ9W3gucHJlSW5pdF0pOzA8eC5wcmVJbml0Lmxlbmd0aDspeC5wcmVJbml0LnBvcCgpKCk7YmQoKTtcXHJcXG5cXHJcXG5cXHJcXG4gIHJldHVybiBvcnRXYXNtVGhyZWFkZWQucmVhZHlcXHJcXG59XFxyXFxuKTtcXHJcXG59KSgpO1xcclxcbmlmICh0cnVlKVxcclxcbiAgbW9kdWxlLmV4cG9ydHMgPSBvcnRXYXNtVGhyZWFkZWQ7XFxyXFxuZWxzZSB7fVxcclxcblxcblxcbi8qKiovIH0pLFxcblxcbi8qKiovIFxcXCIuL2xpYi93YXNtL2JpbmRpbmcvb3J0LXdhc20uanNcXFwiOlxcbi8qISoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqISpcXFxcXFxuICAhKioqIC4vbGliL3dhc20vYmluZGluZy9vcnQtd2FzbS5qcyAqKiohXFxuICBcXFxcKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiovXFxuLyoqKi8gKChtb2R1bGUsIF9fdW51c2VkX3dlYnBhY2tfZXhwb3J0cywgX193ZWJwYWNrX3JlcXVpcmVfXykgPT4ge1xcblxcbnZhciBfX2ZpbGVuYW1lID0gXFxcIi9pbmRleC5qc1xcXCI7XFxudmFyIF9fZGlybmFtZSA9IFxcXCIvXFxcIjtcXG5cXHJcXG52YXIgb3J0V2FzbSA9ICgoKSA9PiB7XFxyXFxuICB2YXIgX3NjcmlwdERpciA9IHR5cGVvZiBkb2N1bWVudCAhPT0gJ3VuZGVmaW5lZCcgJiYgZG9jdW1lbnQuY3VycmVudFNjcmlwdCA/IGRvY3VtZW50LmN1cnJlbnRTY3JpcHQuc3JjIDogdW5kZWZpbmVkO1xcclxcbiAgaWYgKHRydWUpIF9zY3JpcHREaXIgPSBfc2NyaXB0RGlyIHx8IF9fZmlsZW5hbWU7XFxyXFxuICByZXR1cm4gKFxcclxcbmZ1bmN0aW9uKG9ydFdhc20pIHtcXHJcXG4gIG9ydFdhc20gPSBvcnRXYXNtIHx8IHt9O1xcclxcblxcclxcblxcclxcbnZhciBkO2R8fChkPXR5cGVvZiBvcnRXYXNtICE9PSAndW5kZWZpbmVkJyA/IG9ydFdhc20gOiB7fSk7dmFyIGFhLGJhO2QucmVhZHk9bmV3IFByb21pc2UoZnVuY3Rpb24oYSxiKXthYT1hO2JhPWJ9KTt2YXIgY2E9T2JqZWN0LmFzc2lnbih7fSxkKSxkYT1cXFwiLi90aGlzLnByb2dyYW1cXFwiLGVhPShhLGIpPT57dGhyb3cgYjt9LGZhPVxcXCJvYmplY3RcXFwiPT10eXBlb2Ygd2luZG93LG09XFxcImZ1bmN0aW9uXFxcIj09dHlwZW9mIGltcG9ydFNjcmlwdHMscD1cXFwib2JqZWN0XFxcIj09dHlwZW9mIHByb2Nlc3MmJlxcXCJvYmplY3RcXFwiPT10eXBlb2YgcHJvY2Vzcy52ZXJzaW9ucyYmXFxcInN0cmluZ1xcXCI9PXR5cGVvZiBwcm9jZXNzLnZlcnNpb25zLm5vZGUscT1cXFwiXFxcIixoYSxyLHYsZnMseSxpYTtcXHJcXG5pZihwKXE9bT8oX193ZWJwYWNrX3JlcXVpcmVfXygvKiEgcGF0aCAqLyBcXFwiPzc1YzZcXFwiKS5kaXJuYW1lKShxKStcXFwiL1xcXCI6X19kaXJuYW1lK1xcXCIvXFxcIixpYT0oKT0+e3l8fChmcz1fX3dlYnBhY2tfcmVxdWlyZV9fKC8qISBmcyAqLyBcXFwiPzYzYzhcXFwiKSx5PV9fd2VicGFja19yZXF1aXJlX18oLyohIHBhdGggKi8gXFxcIj83NWM2XFxcIikpfSxoYT1mdW5jdGlvbihhLGIpe2lhKCk7YT15Lm5vcm1hbGl6ZShhKTtyZXR1cm4gZnMucmVhZEZpbGVTeW5jKGEsYj92b2lkIDA6XFxcInV0ZjhcXFwiKX0sdj1hPT57YT1oYShhLCEwKTthLmJ1ZmZlcnx8KGE9bmV3IFVpbnQ4QXJyYXkoYSkpO3JldHVybiBhfSxyPShhLGIsYyk9PntpYSgpO2E9eS5ub3JtYWxpemUoYSk7ZnMucmVhZEZpbGUoYSxmdW5jdGlvbihlLGYpe2U/YyhlKTpiKGYuYnVmZmVyKX0pfSwxPHByb2Nlc3MuYXJndi5sZW5ndGgmJihkYT1wcm9jZXNzLmFyZ3ZbMV0ucmVwbGFjZSgvXFxcXFxcXFwvZyxcXFwiL1xcXCIpKSxwcm9jZXNzLmFyZ3Yuc2xpY2UoMikscHJvY2Vzcy5vbihcXFwidW5jYXVnaHRFeGNlcHRpb25cXFwiLGZ1bmN0aW9uKGEpe2lmKCEoYSBpbnN0YW5jZW9mIGphKSl0aHJvdyBhO30pLHByb2Nlc3Mub24oXFxcInVuaGFuZGxlZFJlamVjdGlvblxcXCIsXFxyXFxuZnVuY3Rpb24oYSl7dGhyb3cgYTt9KSxlYT0oYSxiKT0+e2lmKG5vRXhpdFJ1bnRpbWV8fDA8a2EpdGhyb3cgcHJvY2Vzcy5leGl0Q29kZT1hLGI7YiBpbnN0YW5jZW9mIGphfHx6KFxcXCJleGl0aW5nIGR1ZSB0byBleGNlcHRpb246IFxcXCIrYik7cHJvY2Vzcy5leGl0KGEpfSxkLmluc3BlY3Q9ZnVuY3Rpb24oKXtyZXR1cm5cXFwiW0Vtc2NyaXB0ZW4gTW9kdWxlIG9iamVjdF1cXFwifTtlbHNlIGlmKGZhfHxtKW0/cT1zZWxmLmxvY2F0aW9uLmhyZWY6XFxcInVuZGVmaW5lZFxcXCIhPXR5cGVvZiBkb2N1bWVudCYmZG9jdW1lbnQuY3VycmVudFNjcmlwdCYmKHE9ZG9jdW1lbnQuY3VycmVudFNjcmlwdC5zcmMpLF9zY3JpcHREaXImJihxPV9zY3JpcHREaXIpLDAhPT1xLmluZGV4T2YoXFxcImJsb2I6XFxcIik/cT1xLnN1YnN0cigwLHEucmVwbGFjZSgvWz8jXS4qLyxcXFwiXFxcIikubGFzdEluZGV4T2YoXFxcIi9cXFwiKSsxKTpxPVxcXCJcXFwiLGhhPWE9Pnt2YXIgYj1uZXcgWE1MSHR0cFJlcXVlc3Q7Yi5vcGVuKFxcXCJHRVRcXFwiLGEsITEpO2Iuc2VuZChudWxsKTtcXHJcXG5yZXR1cm4gYi5yZXNwb25zZVRleHR9LG0mJih2PWE9Pnt2YXIgYj1uZXcgWE1MSHR0cFJlcXVlc3Q7Yi5vcGVuKFxcXCJHRVRcXFwiLGEsITEpO2IucmVzcG9uc2VUeXBlPVxcXCJhcnJheWJ1ZmZlclxcXCI7Yi5zZW5kKG51bGwpO3JldHVybiBuZXcgVWludDhBcnJheShiLnJlc3BvbnNlKX0pLHI9KGEsYixjKT0+e3ZhciBlPW5ldyBYTUxIdHRwUmVxdWVzdDtlLm9wZW4oXFxcIkdFVFxcXCIsYSwhMCk7ZS5yZXNwb25zZVR5cGU9XFxcImFycmF5YnVmZmVyXFxcIjtlLm9ubG9hZD0oKT0+ezIwMD09ZS5zdGF0dXN8fDA9PWUuc3RhdHVzJiZlLnJlc3BvbnNlP2IoZS5yZXNwb25zZSk6YygpfTtlLm9uZXJyb3I9YztlLnNlbmQobnVsbCl9O3ZhciBsYT1kLnByaW50fHxjb25zb2xlLmxvZy5iaW5kKGNvbnNvbGUpLHo9ZC5wcmludEVycnx8Y29uc29sZS53YXJuLmJpbmQoY29uc29sZSk7T2JqZWN0LmFzc2lnbihkLGNhKTtjYT1udWxsO2QudGhpc1Byb2dyYW0mJihkYT1kLnRoaXNQcm9ncmFtKTtkLnF1aXQmJihlYT1kLnF1aXQpO1xcclxcbnZhciBBO2Qud2FzbUJpbmFyeSYmKEE9ZC53YXNtQmluYXJ5KTt2YXIgbm9FeGl0UnVudGltZT1kLm5vRXhpdFJ1bnRpbWV8fCExO1xcXCJvYmplY3RcXFwiIT10eXBlb2YgV2ViQXNzZW1ibHkmJkIoXFxcIm5vIG5hdGl2ZSB3YXNtIHN1cHBvcnQgZGV0ZWN0ZWRcXFwiKTt2YXIgbWEsRD0hMSxuYT1cXFwidW5kZWZpbmVkXFxcIiE9dHlwZW9mIFRleHREZWNvZGVyP25ldyBUZXh0RGVjb2RlcihcXFwidXRmOFxcXCIpOnZvaWQgMDtcXHJcXG5mdW5jdGlvbiBvYShhLGIsYyl7Yj4+Pj0wO3ZhciBlPWIrYztmb3IoYz1iO2FbY10mJiEoYz49ZSk7KSsrYztpZigxNjxjLWImJmEuYnVmZmVyJiZuYSlyZXR1cm4gbmEuZGVjb2RlKGEuc3ViYXJyYXkoYixjKSk7Zm9yKGU9XFxcIlxcXCI7YjxjOyl7dmFyIGY9YVtiKytdO2lmKGYmMTI4KXt2YXIgaD1hW2IrK10mNjM7aWYoMTkyPT0oZiYyMjQpKWUrPVN0cmluZy5mcm9tQ2hhckNvZGUoKGYmMzEpPDw2fGgpO2Vsc2V7dmFyIGs9YVtiKytdJjYzO2Y9MjI0PT0oZiYyNDApPyhmJjE1KTw8MTJ8aDw8NnxrOihmJjcpPDwxOHxoPDwxMnxrPDw2fGFbYisrXSY2Mzs2NTUzNj5mP2UrPVN0cmluZy5mcm9tQ2hhckNvZGUoZik6KGYtPTY1NTM2LGUrPVN0cmluZy5mcm9tQ2hhckNvZGUoNTUyOTZ8Zj4+MTAsNTYzMjB8ZiYxMDIzKSl9fWVsc2UgZSs9U3RyaW5nLmZyb21DaGFyQ29kZShmKX1yZXR1cm4gZX1mdW5jdGlvbiBwYShhLGIpe3JldHVybihhPj4+PTApP29hKEcsYSxiKTpcXFwiXFxcIn1cXHJcXG5mdW5jdGlvbiBxYShhLGIsYyxlKXtjPj4+PTA7aWYoISgwPGUpKXJldHVybiAwO3ZhciBmPWM7ZT1jK2UtMTtmb3IodmFyIGg9MDtoPGEubGVuZ3RoOysraCl7dmFyIGs9YS5jaGFyQ29kZUF0KGgpO2lmKDU1Mjk2PD1rJiY1NzM0Mz49ayl7dmFyIGw9YS5jaGFyQ29kZUF0KCsraCk7az02NTUzNisoKGsmMTAyMyk8PDEwKXxsJjEwMjN9aWYoMTI3Pj1rKXtpZihjPj1lKWJyZWFrO2JbYysrPj4+MF09a31lbHNle2lmKDIwNDc+PWspe2lmKGMrMT49ZSlicmVhaztiW2MrKz4+PjBdPTE5MnxrPj42fWVsc2V7aWYoNjU1MzU+PWspe2lmKGMrMj49ZSlicmVhaztiW2MrKz4+PjBdPTIyNHxrPj4xMn1lbHNle2lmKGMrMz49ZSlicmVhaztiW2MrKz4+PjBdPTI0MHxrPj4xODtiW2MrKz4+PjBdPTEyOHxrPj4xMiY2M31iW2MrKz4+PjBdPTEyOHxrPj42JjYzfWJbYysrPj4+MF09MTI4fGsmNjN9fWJbYz4+PjBdPTA7cmV0dXJuIGMtZn1cXHJcXG5mdW5jdGlvbiByYShhKXtmb3IodmFyIGI9MCxjPTA7YzxhLmxlbmd0aDsrK2Mpe3ZhciBlPWEuY2hhckNvZGVBdChjKTsxMjc+PWU/YisrOjIwNDc+PWU/Yis9Mjo1NTI5Njw9ZSYmNTczNDM+PWU/KGIrPTQsKytjKTpiKz0zfXJldHVybiBifXZhciBzYSxILEcsSSxKO2Z1bmN0aW9uIHRhKCl7dmFyIGE9bWEuYnVmZmVyO3NhPWE7ZC5IRUFQOD1IPW5ldyBJbnQ4QXJyYXkoYSk7ZC5IRUFQMTY9bmV3IEludDE2QXJyYXkoYSk7ZC5IRUFQMzI9ST1uZXcgSW50MzJBcnJheShhKTtkLkhFQVBVOD1HPW5ldyBVaW50OEFycmF5KGEpO2QuSEVBUFUxNj1uZXcgVWludDE2QXJyYXkoYSk7ZC5IRUFQVTMyPUo9bmV3IFVpbnQzMkFycmF5KGEpO2QuSEVBUEYzMj1uZXcgRmxvYXQzMkFycmF5KGEpO2QuSEVBUEY2ND1uZXcgRmxvYXQ2NEFycmF5KGEpfXZhciB1YSx2YT1bXSx3YT1bXSx4YT1bXSx5YT1bXSxrYT0wO1xcclxcbmZ1bmN0aW9uIHphKCl7dmFyIGE9ZC5wcmVSdW4uc2hpZnQoKTt2YS51bnNoaWZ0KGEpfXZhciBLPTAsQWE9bnVsbCxMPW51bGw7ZnVuY3Rpb24gQihhKXtpZihkLm9uQWJvcnQpZC5vbkFib3J0KGEpO2E9XFxcIkFib3J0ZWQoXFxcIithK1xcXCIpXFxcIjt6KGEpO0Q9ITA7YT1uZXcgV2ViQXNzZW1ibHkuUnVudGltZUVycm9yKGErXFxcIi4gQnVpbGQgd2l0aCAtc0FTU0VSVElPTlMgZm9yIG1vcmUgaW5mby5cXFwiKTtiYShhKTt0aHJvdyBhO31mdW5jdGlvbiBCYSgpe3JldHVybiBOLnN0YXJ0c1dpdGgoXFxcImRhdGE6YXBwbGljYXRpb24vb2N0ZXQtc3RyZWFtO2Jhc2U2NCxcXFwiKX12YXIgTjtOPVxcXCJvcnQtd2FzbS53YXNtXFxcIjtpZighQmEoKSl7dmFyIENhPU47Tj1kLmxvY2F0ZUZpbGU/ZC5sb2NhdGVGaWxlKENhLHEpOnErQ2F9XFxyXFxuZnVuY3Rpb24gRGEoKXt2YXIgYT1OO3RyeXtpZihhPT1OJiZBKXJldHVybiBuZXcgVWludDhBcnJheShBKTtpZih2KXJldHVybiB2KGEpO3Rocm93XFxcImJvdGggYXN5bmMgYW5kIHN5bmMgZmV0Y2hpbmcgb2YgdGhlIHdhc20gZmFpbGVkXFxcIjt9Y2F0Y2goYil7QihiKX19XFxyXFxuZnVuY3Rpb24gRWEoKXtpZighQSYmKGZhfHxtKSl7aWYoXFxcImZ1bmN0aW9uXFxcIj09dHlwZW9mIGZldGNoJiYhTi5zdGFydHNXaXRoKFxcXCJmaWxlOi8vXFxcIikpcmV0dXJuIGZldGNoKE4se2NyZWRlbnRpYWxzOlxcXCJzYW1lLW9yaWdpblxcXCJ9KS50aGVuKGZ1bmN0aW9uKGEpe2lmKCFhLm9rKXRocm93XFxcImZhaWxlZCB0byBsb2FkIHdhc20gYmluYXJ5IGZpbGUgYXQgJ1xcXCIrTitcXFwiJ1xcXCI7cmV0dXJuIGEuYXJyYXlCdWZmZXIoKX0pLmNhdGNoKGZ1bmN0aW9uKCl7cmV0dXJuIERhKCl9KTtpZihyKXJldHVybiBuZXcgUHJvbWlzZShmdW5jdGlvbihhLGIpe3IoTixmdW5jdGlvbihjKXthKG5ldyBVaW50OEFycmF5KGMpKX0sYil9KX1yZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCkudGhlbihmdW5jdGlvbigpe3JldHVybiBEYSgpfSl9ZnVuY3Rpb24gamEoYSl7dGhpcy5uYW1lPVxcXCJFeGl0U3RhdHVzXFxcIjt0aGlzLm1lc3NhZ2U9XFxcIlByb2dyYW0gdGVybWluYXRlZCB3aXRoIGV4aXQoXFxcIithK1xcXCIpXFxcIjt0aGlzLnN0YXR1cz1hfVxcclxcbmZ1bmN0aW9uIE8oYSl7Zm9yKDswPGEubGVuZ3RoOylhLnNoaWZ0KCkoZCl9dmFyIFA9W10sUT0wLFI9MDtcXHJcXG5mdW5jdGlvbiBTKGEpe3RoaXMuRGI9YTt0aGlzLnpiPWEtMjQ7dGhpcy5VYj1mdW5jdGlvbihiKXtKW3RoaXMuemIrND4+Mj4+PjBdPWJ9O3RoaXMuRWI9ZnVuY3Rpb24oKXtyZXR1cm4gSlt0aGlzLnpiKzQ+PjI+Pj4wXX07dGhpcy5TYj1mdW5jdGlvbihiKXtKW3RoaXMuemIrOD4+Mj4+PjBdPWJ9O3RoaXMuV2I9ZnVuY3Rpb24oKXtyZXR1cm4gSlt0aGlzLnpiKzg+PjI+Pj4wXX07dGhpcy5UYj1mdW5jdGlvbigpe0lbdGhpcy56Yj4+Mj4+PjBdPTB9O3RoaXMuSWI9ZnVuY3Rpb24oYil7SFt0aGlzLnpiKzEyPj4wPj4+MF09Yj8xOjB9O3RoaXMuUGI9ZnVuY3Rpb24oKXtyZXR1cm4gMCE9SFt0aGlzLnpiKzEyPj4wPj4+MF19O3RoaXMuSmI9ZnVuY3Rpb24oYil7SFt0aGlzLnpiKzEzPj4wPj4+MF09Yj8xOjB9O3RoaXMuTGI9ZnVuY3Rpb24oKXtyZXR1cm4gMCE9SFt0aGlzLnpiKzEzPj4wPj4+MF19O3RoaXMuUmI9ZnVuY3Rpb24oYixjKXt0aGlzLkZiKDApO3RoaXMuVWIoYik7dGhpcy5TYihjKTtcXHJcXG50aGlzLlRiKCk7dGhpcy5JYighMSk7dGhpcy5KYighMSl9O3RoaXMuTmI9ZnVuY3Rpb24oKXtJW3RoaXMuemI+PjI+Pj4wXSs9MX07dGhpcy5YYj1mdW5jdGlvbigpe3ZhciBiPUlbdGhpcy56Yj4+Mj4+PjBdO0lbdGhpcy56Yj4+Mj4+PjBdPWItMTtyZXR1cm4gMT09PWJ9O3RoaXMuRmI9ZnVuY3Rpb24oYil7Slt0aGlzLnpiKzE2Pj4yPj4+MF09Yn07dGhpcy5PYj1mdW5jdGlvbigpe3JldHVybiBKW3RoaXMuemIrMTY+PjI+Pj4wXX07dGhpcy5RYj1mdW5jdGlvbigpe2lmKEZhKHRoaXMuRWIoKSkpcmV0dXJuIEpbdGhpcy5EYj4+Mj4+PjBdO3ZhciBiPXRoaXMuT2IoKTtyZXR1cm4gMCE9PWI/Yjp0aGlzLkRifX1mdW5jdGlvbiBHYShhKXtyZXR1cm4gSGEoKG5ldyBTKGEpKS56Yil9dmFyIFQ9W107ZnVuY3Rpb24gVShhKXt2YXIgYj1UW2FdO2J8fChhPj1ULmxlbmd0aCYmKFQubGVuZ3RoPWErMSksVFthXT1iPXVhLmdldChhKSk7cmV0dXJuIGJ9XFxyXFxuZnVuY3Rpb24gSWEoYSl7dmFyIGI9cmEoYSkrMSxjPUphKGIpO2MmJnFhKGEsSCxjLGIpO3JldHVybiBjfWZ1bmN0aW9uIEthKGEsYixjKXtmdW5jdGlvbiBlKG4pe3JldHVybihuPW4udG9UaW1lU3RyaW5nKCkubWF0Y2goL1xcXFwoKFtBLVphLXogXSspXFxcXCkkLykpP25bMV06XFxcIkdNVFxcXCJ9dmFyIGY9KG5ldyBEYXRlKS5nZXRGdWxsWWVhcigpLGg9bmV3IERhdGUoZiwwLDEpLGs9bmV3IERhdGUoZiw2LDEpO2Y9aC5nZXRUaW1lem9uZU9mZnNldCgpO3ZhciBsPWsuZ2V0VGltZXpvbmVPZmZzZXQoKTtJW2E+PjI+Pj4wXT02MCpNYXRoLm1heChmLGwpO0lbYj4+Mj4+PjBdPU51bWJlcihmIT1sKTthPWUoaCk7Yj1lKGspO2E9SWEoYSk7Yj1JYShiKTtsPGY/KEpbYz4+Mj4+PjBdPWEsSltjKzQ+PjI+Pj4wXT1iKTooSltjPj4yPj4+MF09YixKW2MrND4+Mj4+PjBdPWEpfWZ1bmN0aW9uIExhKGEsYixjKXtMYS5WYnx8KExhLlZiPSEwLEthKGEsYixjKSl9dmFyIE1hPXt9O1xcclxcbmZ1bmN0aW9uIE5hKCl7aWYoIU9hKXt2YXIgYT17VVNFUjpcXFwid2ViX3VzZXJcXFwiLExPR05BTUU6XFxcIndlYl91c2VyXFxcIixQQVRIOlxcXCIvXFxcIixQV0Q6XFxcIi9cXFwiLEhPTUU6XFxcIi9ob21lL3dlYl91c2VyXFxcIixMQU5HOihcXFwib2JqZWN0XFxcIj09dHlwZW9mIG5hdmlnYXRvciYmbmF2aWdhdG9yLmxhbmd1YWdlcyYmbmF2aWdhdG9yLmxhbmd1YWdlc1swXXx8XFxcIkNcXFwiKS5yZXBsYWNlKFxcXCItXFxcIixcXFwiX1xcXCIpK1xcXCIuVVRGLThcXFwiLF86ZGF8fFxcXCIuL3RoaXMucHJvZ3JhbVxcXCJ9LGI7Zm9yKGIgaW4gTWEpdm9pZCAwPT09TWFbYl0/ZGVsZXRlIGFbYl06YVtiXT1NYVtiXTt2YXIgYz1bXTtmb3IoYiBpbiBhKWMucHVzaChiK1xcXCI9XFxcIithW2JdKTtPYT1jfXJldHVybiBPYX12YXIgT2EsUGE9W251bGwsW10sW11dO2Z1bmN0aW9uIFFhKGEsYil7dmFyIGM9UGFbYV07MD09PWJ8fDEwPT09Yj8oKDE9PT1hP2xhOnopKG9hKGMsMCkpLGMubGVuZ3RoPTApOmMucHVzaChiKX12YXIgVj0wO1xcclxcbmZ1bmN0aW9uIFJhKCl7aWYoXFxcIm9iamVjdFxcXCI9PXR5cGVvZiBjcnlwdG8mJlxcXCJmdW5jdGlvblxcXCI9PXR5cGVvZiBjcnlwdG8uZ2V0UmFuZG9tVmFsdWVzKXt2YXIgYT1uZXcgVWludDhBcnJheSgxKTtyZXR1cm4oKT0+e2NyeXB0by5nZXRSYW5kb21WYWx1ZXMoYSk7cmV0dXJuIGFbMF19fWlmKHApdHJ5e3ZhciBiPV9fd2VicGFja19yZXF1aXJlX18oT2JqZWN0KGZ1bmN0aW9uIHdlYnBhY2tNaXNzaW5nTW9kdWxlKCkgeyB2YXIgZSA9IG5ldyBFcnJvcihcXFwiQ2Fubm90IGZpbmQgbW9kdWxlICdjcnlwdG8nXFxcIik7IGUuY29kZSA9ICdNT0RVTEVfTk9UX0ZPVU5EJzsgdGhyb3cgZTsgfSgpKSk7cmV0dXJuKCk9PmIucmFuZG9tQnl0ZXMoMSlbMF19Y2F0Y2goYyl7fXJldHVybigpPT5CKFxcXCJyYW5kb21EZXZpY2VcXFwiKX1mdW5jdGlvbiBXKGEsYil7Vy5NYnx8KFcuTWI9UmEoKSk7Zm9yKHZhciBjPTA7YzxiO2MrKylIW2ErYz4+MD4+PjBdPVcuTWIoKTtyZXR1cm4gMH1mdW5jdGlvbiBTYShhKXtyZXR1cm4gMD09PWElNCYmKDAhPT1hJTEwMHx8MD09PWElNDAwKX12YXIgVGE9WzMxLDI5LDMxLDMwLDMxLDMwLDMxLDMxLDMwLDMxLDMwLDMxXSxVYT1bMzEsMjgsMzEsMzAsMzEsMzAsMzEsMzEsMzAsMzEsMzAsMzFdO1xcclxcbmZ1bmN0aW9uIFZhKGEpe3ZhciBiPUFycmF5KHJhKGEpKzEpO3FhKGEsYiwwLGIubGVuZ3RoKTtyZXR1cm4gYn1cXHJcXG5mdW5jdGlvbiBXYShhLGIsYyxlKXtmdW5jdGlvbiBmKGcsdSx3KXtmb3IoZz1cXFwibnVtYmVyXFxcIj09dHlwZW9mIGc/Zy50b1N0cmluZygpOmd8fFxcXCJcXFwiO2cubGVuZ3RoPHU7KWc9d1swXStnO3JldHVybiBnfWZ1bmN0aW9uIGgoZyx1KXtyZXR1cm4gZihnLHUsXFxcIjBcXFwiKX1mdW5jdGlvbiBrKGcsdSl7ZnVuY3Rpb24gdyhNKXtyZXR1cm4gMD5NPy0xOjA8TT8xOjB9dmFyIEY7MD09PShGPXcoZy5nZXRGdWxsWWVhcigpLXUuZ2V0RnVsbFllYXIoKSkpJiYwPT09KEY9dyhnLmdldE1vbnRoKCktdS5nZXRNb250aCgpKSkmJihGPXcoZy5nZXREYXRlKCktdS5nZXREYXRlKCkpKTtyZXR1cm4gRn1mdW5jdGlvbiBsKGcpe3N3aXRjaChnLmdldERheSgpKXtjYXNlIDA6cmV0dXJuIG5ldyBEYXRlKGcuZ2V0RnVsbFllYXIoKS0xLDExLDI5KTtjYXNlIDE6cmV0dXJuIGc7Y2FzZSAyOnJldHVybiBuZXcgRGF0ZShnLmdldEZ1bGxZZWFyKCksMCwzKTtjYXNlIDM6cmV0dXJuIG5ldyBEYXRlKGcuZ2V0RnVsbFllYXIoKSxcXHJcXG4wLDIpO2Nhc2UgNDpyZXR1cm4gbmV3IERhdGUoZy5nZXRGdWxsWWVhcigpLDAsMSk7Y2FzZSA1OnJldHVybiBuZXcgRGF0ZShnLmdldEZ1bGxZZWFyKCktMSwxMSwzMSk7Y2FzZSA2OnJldHVybiBuZXcgRGF0ZShnLmdldEZ1bGxZZWFyKCktMSwxMSwzMCl9fWZ1bmN0aW9uIG4oZyl7dmFyIHU9Zy5CYjtmb3IoZz1uZXcgRGF0ZSgobmV3IERhdGUoZy5DYisxOTAwLDAsMSkpLmdldFRpbWUoKSk7MDx1Oyl7dmFyIHc9Zy5nZXRNb250aCgpLEY9KFNhKGcuZ2V0RnVsbFllYXIoKSk/VGE6VWEpW3ddO2lmKHU+Ri1nLmdldERhdGUoKSl1LT1GLWcuZ2V0RGF0ZSgpKzEsZy5zZXREYXRlKDEpLDExPnc/Zy5zZXRNb250aCh3KzEpOihnLnNldE1vbnRoKDApLGcuc2V0RnVsbFllYXIoZy5nZXRGdWxsWWVhcigpKzEpKTtlbHNle2cuc2V0RGF0ZShnLmdldERhdGUoKSt1KTticmVha319dz1uZXcgRGF0ZShnLmdldEZ1bGxZZWFyKCkrMSwwLDQpO3U9bChuZXcgRGF0ZShnLmdldEZ1bGxZZWFyKCksXFxyXFxuMCw0KSk7dz1sKHcpO3JldHVybiAwPj1rKHUsZyk/MD49ayh3LGcpP2cuZ2V0RnVsbFllYXIoKSsxOmcuZ2V0RnVsbFllYXIoKTpnLmdldEZ1bGxZZWFyKCktMX12YXIgdD1JW2UrNDA+PjI+Pj4wXTtlPXskYjpJW2U+PjI+Pj4wXSxaYjpJW2UrND4+Mj4+PjBdLEdiOklbZSs4Pj4yPj4+MF0sS2I6SVtlKzEyPj4yPj4+MF0sSGI6SVtlKzE2Pj4yPj4+MF0sQ2I6SVtlKzIwPj4yPj4+MF0sQWI6SVtlKzI0Pj4yPj4+MF0sQmI6SVtlKzI4Pj4yPj4+MF0sYmM6SVtlKzMyPj4yPj4+MF0sWWI6SVtlKzM2Pj4yPj4+MF0sYWM6dD9wYSh0KTpcXFwiXFxcIn07Yz1wYShjKTt0PXtcXFwiJWNcXFwiOlxcXCIlYSAlYiAlZCAlSDolTTolUyAlWVxcXCIsXFxcIiVEXFxcIjpcXFwiJW0vJWQvJXlcXFwiLFxcXCIlRlxcXCI6XFxcIiVZLSVtLSVkXFxcIixcXFwiJWhcXFwiOlxcXCIlYlxcXCIsXFxcIiVyXFxcIjpcXFwiJUk6JU06JVMgJXBcXFwiLFxcXCIlUlxcXCI6XFxcIiVIOiVNXFxcIixcXFwiJVRcXFwiOlxcXCIlSDolTTolU1xcXCIsXFxcIiV4XFxcIjpcXFwiJW0vJWQvJXlcXFwiLFxcXCIlWFxcXCI6XFxcIiVIOiVNOiVTXFxcIixcXFwiJUVjXFxcIjpcXFwiJWNcXFwiLFxcXCIlRUNcXFwiOlxcXCIlQ1xcXCIsXFxcIiVFeFxcXCI6XFxcIiVtLyVkLyV5XFxcIixcXHJcXG5cXFwiJUVYXFxcIjpcXFwiJUg6JU06JVNcXFwiLFxcXCIlRXlcXFwiOlxcXCIleVxcXCIsXFxcIiVFWVxcXCI6XFxcIiVZXFxcIixcXFwiJU9kXFxcIjpcXFwiJWRcXFwiLFxcXCIlT2VcXFwiOlxcXCIlZVxcXCIsXFxcIiVPSFxcXCI6XFxcIiVIXFxcIixcXFwiJU9JXFxcIjpcXFwiJUlcXFwiLFxcXCIlT21cXFwiOlxcXCIlbVxcXCIsXFxcIiVPTVxcXCI6XFxcIiVNXFxcIixcXFwiJU9TXFxcIjpcXFwiJVNcXFwiLFxcXCIlT3VcXFwiOlxcXCIldVxcXCIsXFxcIiVPVVxcXCI6XFxcIiVVXFxcIixcXFwiJU9WXFxcIjpcXFwiJVZcXFwiLFxcXCIlT3dcXFwiOlxcXCIld1xcXCIsXFxcIiVPV1xcXCI6XFxcIiVXXFxcIixcXFwiJU95XFxcIjpcXFwiJXlcXFwifTtmb3IodmFyIHggaW4gdCljPWMucmVwbGFjZShuZXcgUmVnRXhwKHgsXFxcImdcXFwiKSx0W3hdKTt2YXIgRT1cXFwiU3VuZGF5IE1vbmRheSBUdWVzZGF5IFdlZG5lc2RheSBUaHVyc2RheSBGcmlkYXkgU2F0dXJkYXlcXFwiLnNwbGl0KFxcXCIgXFxcIiksQz1cXFwiSmFudWFyeSBGZWJydWFyeSBNYXJjaCBBcHJpbCBNYXkgSnVuZSBKdWx5IEF1Z3VzdCBTZXB0ZW1iZXIgT2N0b2JlciBOb3ZlbWJlciBEZWNlbWJlclxcXCIuc3BsaXQoXFxcIiBcXFwiKTt0PXtcXFwiJWFcXFwiOmZ1bmN0aW9uKGcpe3JldHVybiBFW2cuQWJdLnN1YnN0cmluZygwLDMpfSxcXFwiJUFcXFwiOmZ1bmN0aW9uKGcpe3JldHVybiBFW2cuQWJdfSxcXFwiJWJcXFwiOmZ1bmN0aW9uKGcpe3JldHVybiBDW2cuSGJdLnN1YnN0cmluZygwLFxcclxcbjMpfSxcXFwiJUJcXFwiOmZ1bmN0aW9uKGcpe3JldHVybiBDW2cuSGJdfSxcXFwiJUNcXFwiOmZ1bmN0aW9uKGcpe3JldHVybiBoKChnLkNiKzE5MDApLzEwMHwwLDIpfSxcXFwiJWRcXFwiOmZ1bmN0aW9uKGcpe3JldHVybiBoKGcuS2IsMil9LFxcXCIlZVxcXCI6ZnVuY3Rpb24oZyl7cmV0dXJuIGYoZy5LYiwyLFxcXCIgXFxcIil9LFxcXCIlZ1xcXCI6ZnVuY3Rpb24oZyl7cmV0dXJuIG4oZykudG9TdHJpbmcoKS5zdWJzdHJpbmcoMil9LFxcXCIlR1xcXCI6ZnVuY3Rpb24oZyl7cmV0dXJuIG4oZyl9LFxcXCIlSFxcXCI6ZnVuY3Rpb24oZyl7cmV0dXJuIGgoZy5HYiwyKX0sXFxcIiVJXFxcIjpmdW5jdGlvbihnKXtnPWcuR2I7MD09Zz9nPTEyOjEyPGcmJihnLT0xMik7cmV0dXJuIGgoZywyKX0sXFxcIiVqXFxcIjpmdW5jdGlvbihnKXtmb3IodmFyIHU9MCx3PTA7dzw9Zy5IYi0xO3UrPShTYShnLkNiKzE5MDApP1RhOlVhKVt3KytdKTtyZXR1cm4gaChnLktiK3UsMyl9LFxcXCIlbVxcXCI6ZnVuY3Rpb24oZyl7cmV0dXJuIGgoZy5IYisxLDIpfSxcXFwiJU1cXFwiOmZ1bmN0aW9uKGcpe3JldHVybiBoKGcuWmIsXFxyXFxuMil9LFxcXCIlblxcXCI6ZnVuY3Rpb24oKXtyZXR1cm5cXFwiXFxcXG5cXFwifSxcXFwiJXBcXFwiOmZ1bmN0aW9uKGcpe3JldHVybiAwPD1nLkdiJiYxMj5nLkdiP1xcXCJBTVxcXCI6XFxcIlBNXFxcIn0sXFxcIiVTXFxcIjpmdW5jdGlvbihnKXtyZXR1cm4gaChnLiRiLDIpfSxcXFwiJXRcXFwiOmZ1bmN0aW9uKCl7cmV0dXJuXFxcIlxcXFx0XFxcIn0sXFxcIiV1XFxcIjpmdW5jdGlvbihnKXtyZXR1cm4gZy5BYnx8N30sXFxcIiVVXFxcIjpmdW5jdGlvbihnKXtyZXR1cm4gaChNYXRoLmZsb29yKChnLkJiKzctZy5BYikvNyksMil9LFxcXCIlVlxcXCI6ZnVuY3Rpb24oZyl7dmFyIHU9TWF0aC5mbG9vcigoZy5CYis3LShnLkFiKzYpJTcpLzcpOzI+PShnLkFiKzM3MS1nLkJiLTIpJTcmJnUrKztpZih1KTUzPT11JiYodz0oZy5BYiszNzEtZy5CYiklNyw0PT13fHwzPT13JiZTYShnLkNiKXx8KHU9MSkpO2Vsc2V7dT01Mjt2YXIgdz0oZy5BYis3LWcuQmItMSklNzsoND09d3x8NT09dyYmU2EoZy5DYiU0MDAtMSkpJiZ1Kyt9cmV0dXJuIGgodSwyKX0sXFxcIiV3XFxcIjpmdW5jdGlvbihnKXtyZXR1cm4gZy5BYn0sXFxcIiVXXFxcIjpmdW5jdGlvbihnKXtyZXR1cm4gaChNYXRoLmZsb29yKChnLkJiK1xcclxcbjctKGcuQWIrNiklNykvNyksMil9LFxcXCIleVxcXCI6ZnVuY3Rpb24oZyl7cmV0dXJuKGcuQ2IrMTkwMCkudG9TdHJpbmcoKS5zdWJzdHJpbmcoMil9LFxcXCIlWVxcXCI6ZnVuY3Rpb24oZyl7cmV0dXJuIGcuQ2IrMTkwMH0sXFxcIiV6XFxcIjpmdW5jdGlvbihnKXtnPWcuWWI7dmFyIHU9MDw9ZztnPU1hdGguYWJzKGcpLzYwO3JldHVybih1P1xcXCIrXFxcIjpcXFwiLVxcXCIpK1N0cmluZyhcXFwiMDAwMFxcXCIrKGcvNjAqMTAwK2clNjApKS5zbGljZSgtNCl9LFxcXCIlWlxcXCI6ZnVuY3Rpb24oZyl7cmV0dXJuIGcuYWN9LFxcXCIlJVxcXCI6ZnVuY3Rpb24oKXtyZXR1cm5cXFwiJVxcXCJ9fTtjPWMucmVwbGFjZSgvJSUvZyxcXFwiXFxcXHgwMFxcXFx4MDBcXFwiKTtmb3IoeCBpbiB0KWMuaW5jbHVkZXMoeCkmJihjPWMucmVwbGFjZShuZXcgUmVnRXhwKHgsXFxcImdcXFwiKSx0W3hdKGUpKSk7Yz1jLnJlcGxhY2UoL1xcXFwwXFxcXDAvZyxcXFwiJVxcXCIpO3g9VmEoYyk7aWYoeC5sZW5ndGg+YilyZXR1cm4gMDtILnNldCh4LGE+Pj4wKTtyZXR1cm4geC5sZW5ndGgtMX1cXHJcXG52YXIgSmI9e2E6ZnVuY3Rpb24oYSl7cmV0dXJuIEphKGErMjQpKzI0fSxtOmZ1bmN0aW9uKGEpe2E9bmV3IFMoYSk7YS5QYigpfHwoYS5JYighMCksUS0tKTthLkpiKCExKTtQLnB1c2goYSk7YS5OYigpO3JldHVybiBhLlFiKCl9LGlhOmZ1bmN0aW9uKGEpe3ooXFxcIlVuZXhwZWN0ZWQgZXhjZXB0aW9uIHRocm93biwgdGhpcyBpcyBub3QgcHJvcGVybHkgc3VwcG9ydGVkIC0gYWJvcnRpbmdcXFwiKTtEPSEwO3Rocm93IGE7fSx3OmZ1bmN0aW9uKCl7WCgwKTt2YXIgYT1QLnBvcCgpO2lmKGEuWGIoKSYmIWEuTGIoKSl7dmFyIGI9YS5XYigpO2ImJlUoYikoYS5EYik7R2EoYS5EYil9Uj0wfSxkOmZ1bmN0aW9uKCl7dmFyIGE9UjtpZighYSlyZXR1cm4gVj0wO3ZhciBiPW5ldyBTKGEpO2IuRmIoYSk7dmFyIGM9Yi5FYigpO2lmKCFjKXJldHVybiBWPTAsYTtmb3IodmFyIGU9QXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoYXJndW1lbnRzKSxmPTA7ZjxlLmxlbmd0aDtmKyspe3ZhciBoPWVbZl07XFxyXFxuaWYoMD09PWh8fGg9PT1jKWJyZWFrO2lmKFhhKGgsYyxiLnpiKzE2KSlyZXR1cm4gVj1oLGF9Vj1jO3JldHVybiBhfSxrOmZ1bmN0aW9uKCl7dmFyIGE9UjtpZighYSlyZXR1cm4gVj0wO3ZhciBiPW5ldyBTKGEpO2IuRmIoYSk7dmFyIGM9Yi5FYigpO2lmKCFjKXJldHVybiBWPTAsYTtmb3IodmFyIGU9QXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoYXJndW1lbnRzKSxmPTA7ZjxlLmxlbmd0aDtmKyspe3ZhciBoPWVbZl07aWYoMD09PWh8fGg9PT1jKWJyZWFrO2lmKFhhKGgsYyxiLnpiKzE2KSlyZXR1cm4gVj1oLGF9Vj1jO3JldHVybiBhfSxnOmZ1bmN0aW9uKCl7dmFyIGE9UjtpZighYSlyZXR1cm4gVj0wO3ZhciBiPW5ldyBTKGEpO2IuRmIoYSk7dmFyIGM9Yi5FYigpO2lmKCFjKXJldHVybiBWPTAsYTtmb3IodmFyIGU9QXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoYXJndW1lbnRzKSxmPTA7ZjxlLmxlbmd0aDtmKyspe3ZhciBoPWVbZl07aWYoMD09PWh8fGg9PT1jKWJyZWFrO1xcclxcbmlmKFhhKGgsYyxiLnpiKzE2KSlyZXR1cm4gVj1oLGF9Vj1jO3JldHVybiBhfSxzOkdhLEw6ZnVuY3Rpb24oKXt2YXIgYT1QLnBvcCgpO2F8fEIoXFxcIm5vIGV4Y2VwdGlvbiB0byB0aHJvd1xcXCIpO3ZhciBiPWEuRGI7YS5MYigpfHwoUC5wdXNoKGEpLGEuSmIoITApLGEuSWIoITEpLFErKyk7Uj1iO3Rocm93IGI7fSxiOmZ1bmN0aW9uKGEsYixjKXsobmV3IFMoYSkpLlJiKGIsYyk7Uj1hO1ErKzt0aHJvdyBhO30sbGE6ZnVuY3Rpb24oKXtyZXR1cm4gUX0saTpmdW5jdGlvbihhKXtSfHwoUj1hKTt0aHJvdyBhO30sSDpmdW5jdGlvbigpe3JldHVybiAwfSxCYTpmdW5jdGlvbigpe30scGE6ZnVuY3Rpb24oKXt9LHJhOmZ1bmN0aW9uKCl7fSxrYTpmdW5jdGlvbigpe3JldHVybiAwfSx6YTpmdW5jdGlvbigpe30sdWE6ZnVuY3Rpb24oKXt9LHlhOmZ1bmN0aW9uKCl7fSxSOmZ1bmN0aW9uKCl7fSxxYTpmdW5jdGlvbigpe30sbmE6ZnVuY3Rpb24oKXt9LEFhOmZ1bmN0aW9uKCl7fSxvYTpmdW5jdGlvbigpe30sXFxyXFxuSGE6ZnVuY3Rpb24oKXt9LEphOmZ1bmN0aW9uKCl7QihcXFwiVG8gdXNlIGRsb3BlbiwgeW91IG5lZWQgZW5hYmxlIGR5bmFtaWMgbGlua2luZywgc2VlIGh0dHBzOi8vZ2l0aHViLmNvbS9lbXNjcmlwdGVuLWNvcmUvZW1zY3JpcHRlbi93aWtpL0xpbmtpbmdcXFwiKX0sSWE6ZnVuY3Rpb24oKXtCKFxcXCJUbyB1c2UgZGxvcGVuLCB5b3UgbmVlZCBlbmFibGUgZHluYW1pYyBsaW5raW5nLCBzZWUgaHR0cHM6Ly9naXRodWIuY29tL2Vtc2NyaXB0ZW4tY29yZS9lbXNjcmlwdGVuL3dpa2kvTGlua2luZ1xcXCIpfSxTOmZ1bmN0aW9uKCl7cmV0dXJuIERhdGUubm93KCl9LENhOmZ1bmN0aW9uKCl7cmV0dXJuITB9LERhOmZ1bmN0aW9uKGEsYil7YT1uZXcgRGF0ZSgxRTMqKEpbYT4+PjJdKzQyOTQ5NjcyOTYqSVthKzQ+Pj4yXSkpO0lbYj4+Mj4+PjBdPWEuZ2V0VVRDU2Vjb25kcygpO0lbYis0Pj4yPj4+MF09YS5nZXRVVENNaW51dGVzKCk7SVtiKzg+PjI+Pj4wXT1hLmdldFVUQ0hvdXJzKCk7SVtiKzEyPj4yPj4+XFxyXFxuMF09YS5nZXRVVENEYXRlKCk7SVtiKzE2Pj4yPj4+MF09YS5nZXRVVENNb250aCgpO0lbYisyMD4+Mj4+PjBdPWEuZ2V0VVRDRnVsbFllYXIoKS0xOTAwO0lbYisyND4+Mj4+PjBdPWEuZ2V0VVRDRGF5KCk7SVtiKzI4Pj4yPj4+MF09KGEuZ2V0VGltZSgpLURhdGUuVVRDKGEuZ2V0VVRDRnVsbFllYXIoKSwwLDEsMCwwLDAsMCkpLzg2NEU1fDB9LEVhOmZ1bmN0aW9uKGEsYil7YT1uZXcgRGF0ZSgxRTMqKEpbYT4+PjJdKzQyOTQ5NjcyOTYqSVthKzQ+Pj4yXSkpO0lbYj4+Mj4+PjBdPWEuZ2V0U2Vjb25kcygpO0lbYis0Pj4yPj4+MF09YS5nZXRNaW51dGVzKCk7SVtiKzg+PjI+Pj4wXT1hLmdldEhvdXJzKCk7SVtiKzEyPj4yPj4+MF09YS5nZXREYXRlKCk7SVtiKzE2Pj4yPj4+MF09YS5nZXRNb250aCgpO0lbYisyMD4+Mj4+PjBdPWEuZ2V0RnVsbFllYXIoKS0xOTAwO0lbYisyND4+Mj4+PjBdPWEuZ2V0RGF5KCk7dmFyIGM9bmV3IERhdGUoYS5nZXRGdWxsWWVhcigpLDAsMSk7SVtiK1xcclxcbjI4Pj4yPj4+MF09KGEuZ2V0VGltZSgpLWMuZ2V0VGltZSgpKS84NjRFNXwwO0lbYiszNj4+Mj4+PjBdPS0oNjAqYS5nZXRUaW1lem9uZU9mZnNldCgpKTt2YXIgZT0obmV3IERhdGUoYS5nZXRGdWxsWWVhcigpLDYsMSkpLmdldFRpbWV6b25lT2Zmc2V0KCk7Yz1jLmdldFRpbWV6b25lT2Zmc2V0KCk7SVtiKzMyPj4yPj4+MF09KGUhPWMmJmEuZ2V0VGltZXpvbmVPZmZzZXQoKT09TWF0aC5taW4oYyxlKSl8MH0sRmE6ZnVuY3Rpb24oYSl7dmFyIGI9bmV3IERhdGUoSVthKzIwPj4yPj4+MF0rMTkwMCxJW2ErMTY+PjI+Pj4wXSxJW2ErMTI+PjI+Pj4wXSxJW2ErOD4+Mj4+PjBdLElbYSs0Pj4yPj4+MF0sSVthPj4yPj4+MF0sMCksYz1JW2ErMzI+PjI+Pj4wXSxlPWIuZ2V0VGltZXpvbmVPZmZzZXQoKSxmPW5ldyBEYXRlKGIuZ2V0RnVsbFllYXIoKSwwLDEpLGg9KG5ldyBEYXRlKGIuZ2V0RnVsbFllYXIoKSw2LDEpKS5nZXRUaW1lem9uZU9mZnNldCgpLGs9Zi5nZXRUaW1lem9uZU9mZnNldCgpLFxcclxcbmw9TWF0aC5taW4oayxoKTswPmM/SVthKzMyPj4yPj4+MF09TnVtYmVyKGghPWsmJmw9PWUpOjA8YyE9KGw9PWUpJiYoaD1NYXRoLm1heChrLGgpLGIuc2V0VGltZShiLmdldFRpbWUoKSs2RTQqKCgwPGM/bDpoKS1lKSkpO0lbYSsyND4+Mj4+PjBdPWIuZ2V0RGF5KCk7SVthKzI4Pj4yPj4+MF09KGIuZ2V0VGltZSgpLWYuZ2V0VGltZSgpKS84NjRFNXwwO0lbYT4+Mj4+PjBdPWIuZ2V0U2Vjb25kcygpO0lbYSs0Pj4yPj4+MF09Yi5nZXRNaW51dGVzKCk7SVthKzg+PjI+Pj4wXT1iLmdldEhvdXJzKCk7SVthKzEyPj4yPj4+MF09Yi5nZXREYXRlKCk7SVthKzE2Pj4yPj4+MF09Yi5nZXRNb250aCgpO3JldHVybiBiLmdldFRpbWUoKS8xRTN8MH0sc2E6ZnVuY3Rpb24oKXtyZXR1cm4tNTJ9LHRhOmZ1bmN0aW9uKCl7fSxHYTpMYSxCOmZ1bmN0aW9uKCl7QihcXFwiXFxcIil9LG1hOmZ1bmN0aW9uKCl7cmV0dXJuIDQyOTQ5MDE3NjB9LEk6cD8oKT0+e3ZhciBhPXByb2Nlc3MuaHJ0aW1lKCk7cmV0dXJuIDFFMypcXHJcXG5hWzBdK2FbMV0vMUU2fTooKT0+cGVyZm9ybWFuY2Uubm93KCkseGE6ZnVuY3Rpb24oYSxiLGMpe0cuY29weVdpdGhpbihhPj4+MCxiPj4+MCxiK2M+Pj4wKX0sRzpmdW5jdGlvbihhKXt2YXIgYj1HLmxlbmd0aDthPj4+PTA7aWYoNDI5NDkwMTc2MDxhKXJldHVybiExO2Zvcih2YXIgYz0xOzQ+PWM7Yyo9Mil7dmFyIGU9YiooMSsuMi9jKTtlPU1hdGgubWluKGUsYSsxMDA2NjMyOTYpO3ZhciBmPU1hdGg7ZT1NYXRoLm1heChhLGUpO2Y9Zi5taW4uY2FsbChmLDQyOTQ5MDE3NjAsZSsoNjU1MzYtZSU2NTUzNiklNjU1MzYpO2E6e3RyeXttYS5ncm93KGYtc2EuYnl0ZUxlbmd0aCs2NTUzNT4+PjE2KTt0YSgpO3ZhciBoPTE7YnJlYWsgYX1jYXRjaChrKXt9aD12b2lkIDB9aWYoaClyZXR1cm4hMH1yZXR1cm4hMX0sdmE6ZnVuY3Rpb24oYSxiKXt2YXIgYz0wO05hKCkuZm9yRWFjaChmdW5jdGlvbihlLGYpe3ZhciBoPWIrYztmPUpbYSs0KmY+PjI+Pj4wXT1oO2ZvcihoPTA7aDxlLmxlbmd0aDsrK2gpSFtmKys+PlxcclxcbjA+Pj4wXT1lLmNoYXJDb2RlQXQoaCk7SFtmPj4wPj4+MF09MDtjKz1lLmxlbmd0aCsxfSk7cmV0dXJuIDB9LHdhOmZ1bmN0aW9uKGEsYil7dmFyIGM9TmEoKTtKW2E+PjI+Pj4wXT1jLmxlbmd0aDt2YXIgZT0wO2MuZm9yRWFjaChmdW5jdGlvbihmKXtlKz1mLmxlbmd0aCsxfSk7SltiPj4yPj4+MF09ZTtyZXR1cm4gMH0sYmE6ZnVuY3Rpb24oYSl7bm9FeGl0UnVudGltZXx8MDxrYXx8KFlhKCksTyh4YSksWmEoMCksUGFbMV0ubGVuZ3RoJiZRYSgxLDEwKSxQYVsyXS5sZW5ndGgmJlFhKDIsMTApKTtpZighKG5vRXhpdFJ1bnRpbWV8fDA8a2EpKXtpZihkLm9uRXhpdClkLm9uRXhpdChhKTtEPSEwfWVhKGEsbmV3IGphKGEpKX0sRTpmdW5jdGlvbigpe3JldHVybiA1Mn0sUTpmdW5jdGlvbigpe3JldHVybiA1Mn0sY2E6ZnVuY3Rpb24oKXtyZXR1cm4gNzB9LFA6ZnVuY3Rpb24oYSxiLGMsZSl7Zm9yKHZhciBmPTAsaD0wO2g8YztoKyspe3ZhciBrPUpbYj4+Mj4+PjBdLGw9SltiKzQ+PlxcclxcbjI+Pj4wXTtiKz04O2Zvcih2YXIgbj0wO248bDtuKyspUWEoYSxHW2srbj4+PjBdKTtmKz1sfUpbZT4+Mj4+PjBdPWY7cmV0dXJuIDB9LGM6ZnVuY3Rpb24oKXtyZXR1cm4gVn0samE6VyxlYTokYSxmYTphYixKOmJiLGU6Y2IsTjpkYixPOmViLGo6ZmIsbzpnYixwOmhiLE06aWIscjpqYix2OmtiLEs6bGIsRDptYixYOm5iLFY6b2IsVTpwYixaOnFiLFc6cmIsWTpzYixUOnRiLGY6dWIscTp2YixoOndiLGRhOnhiLGw6eWIsdDp6Yix1OkFiLHg6QmIsejpDYixnYTpEYixBOkViLEM6RmIsYWE6R2IsXzpIYiwkOkliLG46ZnVuY3Rpb24oYSl7cmV0dXJuIGF9LEY6ZnVuY3Rpb24oYSl7Vj1hfSxoYTpXYSx5OmZ1bmN0aW9uKGEsYixjLGUpe3JldHVybiBXYShhLGIsYyxlKX19O1xcclxcbihmdW5jdGlvbigpe2Z1bmN0aW9uIGEoZil7ZC5hc209Zi5leHBvcnRzO21hPWQuYXNtLkthO3RhKCk7dWE9ZC5hc20uaWI7d2EudW5zaGlmdChkLmFzbS5MYSk7Sy0tO2QubW9uaXRvclJ1bkRlcGVuZGVuY2llcyYmZC5tb25pdG9yUnVuRGVwZW5kZW5jaWVzKEspOzA9PUsmJihudWxsIT09QWEmJihjbGVhckludGVydmFsKEFhKSxBYT1udWxsKSxMJiYoZj1MLEw9bnVsbCxmKCkpKX1mdW5jdGlvbiBiKGYpe2EoZi5pbnN0YW5jZSl9ZnVuY3Rpb24gYyhmKXtyZXR1cm4gRWEoKS50aGVuKGZ1bmN0aW9uKGgpe3JldHVybiBXZWJBc3NlbWJseS5pbnN0YW50aWF0ZShoLGUpfSkudGhlbihmdW5jdGlvbihoKXtyZXR1cm4gaH0pLnRoZW4oZixmdW5jdGlvbihoKXt6KFxcXCJmYWlsZWQgdG8gYXN5bmNocm9ub3VzbHkgcHJlcGFyZSB3YXNtOiBcXFwiK2gpO0IoaCl9KX12YXIgZT17YTpKYn07SysrO2QubW9uaXRvclJ1bkRlcGVuZGVuY2llcyYmZC5tb25pdG9yUnVuRGVwZW5kZW5jaWVzKEspO2lmKGQuaW5zdGFudGlhdGVXYXNtKXRyeXtyZXR1cm4gZC5pbnN0YW50aWF0ZVdhc20oZSxcXHJcXG5hKX1jYXRjaChmKXtyZXR1cm4geihcXFwiTW9kdWxlLmluc3RhbnRpYXRlV2FzbSBjYWxsYmFjayBmYWlsZWQgd2l0aCBlcnJvcjogXFxcIitmKSwhMX0oZnVuY3Rpb24oKXtyZXR1cm4gQXx8XFxcImZ1bmN0aW9uXFxcIiE9dHlwZW9mIFdlYkFzc2VtYmx5Lmluc3RhbnRpYXRlU3RyZWFtaW5nfHxCYSgpfHxOLnN0YXJ0c1dpdGgoXFxcImZpbGU6Ly9cXFwiKXx8cHx8XFxcImZ1bmN0aW9uXFxcIiE9dHlwZW9mIGZldGNoP2MoYik6ZmV0Y2goTix7Y3JlZGVudGlhbHM6XFxcInNhbWUtb3JpZ2luXFxcIn0pLnRoZW4oZnVuY3Rpb24oZil7cmV0dXJuIFdlYkFzc2VtYmx5Lmluc3RhbnRpYXRlU3RyZWFtaW5nKGYsZSkudGhlbihiLGZ1bmN0aW9uKGgpe3ooXFxcIndhc20gc3RyZWFtaW5nIGNvbXBpbGUgZmFpbGVkOiBcXFwiK2gpO3ooXFxcImZhbGxpbmcgYmFjayB0byBBcnJheUJ1ZmZlciBpbnN0YW50aWF0aW9uXFxcIik7cmV0dXJuIGMoYil9KX0pfSkoKS5jYXRjaChiYSk7cmV0dXJue319KSgpO1xcclxcbmQuX19fd2FzbV9jYWxsX2N0b3JzPWZ1bmN0aW9uKCl7cmV0dXJuKGQuX19fd2FzbV9jYWxsX2N0b3JzPWQuYXNtLkxhKS5hcHBseShudWxsLGFyZ3VtZW50cyl9O2QuX09ydEluaXQ9ZnVuY3Rpb24oKXtyZXR1cm4oZC5fT3J0SW5pdD1kLmFzbS5NYSkuYXBwbHkobnVsbCxhcmd1bWVudHMpfTtkLl9PcnRDcmVhdGVTZXNzaW9uT3B0aW9ucz1mdW5jdGlvbigpe3JldHVybihkLl9PcnRDcmVhdGVTZXNzaW9uT3B0aW9ucz1kLmFzbS5OYSkuYXBwbHkobnVsbCxhcmd1bWVudHMpfTtkLl9PcnRBcHBlbmRFeGVjdXRpb25Qcm92aWRlcj1mdW5jdGlvbigpe3JldHVybihkLl9PcnRBcHBlbmRFeGVjdXRpb25Qcm92aWRlcj1kLmFzbS5PYSkuYXBwbHkobnVsbCxhcmd1bWVudHMpfTtkLl9PcnRBZGRTZXNzaW9uQ29uZmlnRW50cnk9ZnVuY3Rpb24oKXtyZXR1cm4oZC5fT3J0QWRkU2Vzc2lvbkNvbmZpZ0VudHJ5PWQuYXNtLlBhKS5hcHBseShudWxsLGFyZ3VtZW50cyl9O1xcclxcbmQuX09ydFJlbGVhc2VTZXNzaW9uT3B0aW9ucz1mdW5jdGlvbigpe3JldHVybihkLl9PcnRSZWxlYXNlU2Vzc2lvbk9wdGlvbnM9ZC5hc20uUWEpLmFwcGx5KG51bGwsYXJndW1lbnRzKX07ZC5fT3J0Q3JlYXRlU2Vzc2lvbj1mdW5jdGlvbigpe3JldHVybihkLl9PcnRDcmVhdGVTZXNzaW9uPWQuYXNtLlJhKS5hcHBseShudWxsLGFyZ3VtZW50cyl9O2QuX09ydFJlbGVhc2VTZXNzaW9uPWZ1bmN0aW9uKCl7cmV0dXJuKGQuX09ydFJlbGVhc2VTZXNzaW9uPWQuYXNtLlNhKS5hcHBseShudWxsLGFyZ3VtZW50cyl9O2QuX09ydEdldElucHV0Q291bnQ9ZnVuY3Rpb24oKXtyZXR1cm4oZC5fT3J0R2V0SW5wdXRDb3VudD1kLmFzbS5UYSkuYXBwbHkobnVsbCxhcmd1bWVudHMpfTtkLl9PcnRHZXRPdXRwdXRDb3VudD1mdW5jdGlvbigpe3JldHVybihkLl9PcnRHZXRPdXRwdXRDb3VudD1kLmFzbS5VYSkuYXBwbHkobnVsbCxhcmd1bWVudHMpfTtcXHJcXG5kLl9PcnRHZXRJbnB1dE5hbWU9ZnVuY3Rpb24oKXtyZXR1cm4oZC5fT3J0R2V0SW5wdXROYW1lPWQuYXNtLlZhKS5hcHBseShudWxsLGFyZ3VtZW50cyl9O2QuX09ydEdldE91dHB1dE5hbWU9ZnVuY3Rpb24oKXtyZXR1cm4oZC5fT3J0R2V0T3V0cHV0TmFtZT1kLmFzbS5XYSkuYXBwbHkobnVsbCxhcmd1bWVudHMpfTtkLl9PcnRGcmVlPWZ1bmN0aW9uKCl7cmV0dXJuKGQuX09ydEZyZWU9ZC5hc20uWGEpLmFwcGx5KG51bGwsYXJndW1lbnRzKX07ZC5fT3J0Q3JlYXRlVGVuc29yPWZ1bmN0aW9uKCl7cmV0dXJuKGQuX09ydENyZWF0ZVRlbnNvcj1kLmFzbS5ZYSkuYXBwbHkobnVsbCxhcmd1bWVudHMpfTtkLl9PcnRHZXRUZW5zb3JEYXRhPWZ1bmN0aW9uKCl7cmV0dXJuKGQuX09ydEdldFRlbnNvckRhdGE9ZC5hc20uWmEpLmFwcGx5KG51bGwsYXJndW1lbnRzKX07XFxyXFxuZC5fT3J0UmVsZWFzZVRlbnNvcj1mdW5jdGlvbigpe3JldHVybihkLl9PcnRSZWxlYXNlVGVuc29yPWQuYXNtLl9hKS5hcHBseShudWxsLGFyZ3VtZW50cyl9O2QuX09ydENyZWF0ZVJ1bk9wdGlvbnM9ZnVuY3Rpb24oKXtyZXR1cm4oZC5fT3J0Q3JlYXRlUnVuT3B0aW9ucz1kLmFzbS4kYSkuYXBwbHkobnVsbCxhcmd1bWVudHMpfTtkLl9PcnRBZGRSdW5Db25maWdFbnRyeT1mdW5jdGlvbigpe3JldHVybihkLl9PcnRBZGRSdW5Db25maWdFbnRyeT1kLmFzbS5hYikuYXBwbHkobnVsbCxhcmd1bWVudHMpfTtkLl9PcnRSZWxlYXNlUnVuT3B0aW9ucz1mdW5jdGlvbigpe3JldHVybihkLl9PcnRSZWxlYXNlUnVuT3B0aW9ucz1kLmFzbS5iYikuYXBwbHkobnVsbCxhcmd1bWVudHMpfTtkLl9PcnRSdW49ZnVuY3Rpb24oKXtyZXR1cm4oZC5fT3J0UnVuPWQuYXNtLmNiKS5hcHBseShudWxsLGFyZ3VtZW50cyl9O1xcclxcbmQuX09ydEVuZFByb2ZpbGluZz1mdW5jdGlvbigpe3JldHVybihkLl9PcnRFbmRQcm9maWxpbmc9ZC5hc20uZGIpLmFwcGx5KG51bGwsYXJndW1lbnRzKX07XFxyXFxudmFyIEphPWQuX21hbGxvYz1mdW5jdGlvbigpe3JldHVybihKYT1kLl9tYWxsb2M9ZC5hc20uZWIpLmFwcGx5KG51bGwsYXJndW1lbnRzKX0sSGE9ZC5fZnJlZT1mdW5jdGlvbigpe3JldHVybihIYT1kLl9mcmVlPWQuYXNtLmZiKS5hcHBseShudWxsLGFyZ3VtZW50cyl9LFphPWQuX2ZmbHVzaD1mdW5jdGlvbigpe3JldHVybihaYT1kLl9mZmx1c2g9ZC5hc20uZ2IpLmFwcGx5KG51bGwsYXJndW1lbnRzKX0sWWE9ZC5fX19mdW5jc19vbl9leGl0PWZ1bmN0aW9uKCl7cmV0dXJuKFlhPWQuX19fZnVuY3Nfb25fZXhpdD1kLmFzbS5oYikuYXBwbHkobnVsbCxhcmd1bWVudHMpfSxYPWQuX3NldFRocmV3PWZ1bmN0aW9uKCl7cmV0dXJuKFg9ZC5fc2V0VGhyZXc9ZC5hc20uamIpLmFwcGx5KG51bGwsYXJndW1lbnRzKX0sWT1kLnN0YWNrU2F2ZT1mdW5jdGlvbigpe3JldHVybihZPWQuc3RhY2tTYXZlPWQuYXNtLmtiKS5hcHBseShudWxsLGFyZ3VtZW50cyl9LFo9ZC5zdGFja1Jlc3RvcmU9XFxyXFxuZnVuY3Rpb24oKXtyZXR1cm4oWj1kLnN0YWNrUmVzdG9yZT1kLmFzbS5sYikuYXBwbHkobnVsbCxhcmd1bWVudHMpfSxLYj1kLnN0YWNrQWxsb2M9ZnVuY3Rpb24oKXtyZXR1cm4oS2I9ZC5zdGFja0FsbG9jPWQuYXNtLm1iKS5hcHBseShudWxsLGFyZ3VtZW50cyl9LFhhPWQuX19fY3hhX2Nhbl9jYXRjaD1mdW5jdGlvbigpe3JldHVybihYYT1kLl9fX2N4YV9jYW5fY2F0Y2g9ZC5hc20ubmIpLmFwcGx5KG51bGwsYXJndW1lbnRzKX0sRmE9ZC5fX19jeGFfaXNfcG9pbnRlcl90eXBlPWZ1bmN0aW9uKCl7cmV0dXJuKEZhPWQuX19fY3hhX2lzX3BvaW50ZXJfdHlwZT1kLmFzbS5vYikuYXBwbHkobnVsbCxhcmd1bWVudHMpfSxMYj1kLmR5bkNhbGxfaj1mdW5jdGlvbigpe3JldHVybihMYj1kLmR5bkNhbGxfaj1kLmFzbS5wYikuYXBwbHkobnVsbCxhcmd1bWVudHMpfSxNYj1kLmR5bkNhbGxfaWlpaWlqPWZ1bmN0aW9uKCl7cmV0dXJuKE1iPWQuZHluQ2FsbF9paWlpaWo9ZC5hc20ucWIpLmFwcGx5KG51bGwsXFxyXFxuYXJndW1lbnRzKX0sTmI9ZC5keW5DYWxsX2ppaT1mdW5jdGlvbigpe3JldHVybihOYj1kLmR5bkNhbGxfamlpPWQuYXNtLnJiKS5hcHBseShudWxsLGFyZ3VtZW50cyl9LE9iPWQuZHluQ2FsbF92aWlpaWlqPWZ1bmN0aW9uKCl7cmV0dXJuKE9iPWQuZHluQ2FsbF92aWlpaWlqPWQuYXNtLnNiKS5hcHBseShudWxsLGFyZ3VtZW50cyl9LFBiPWQuZHluQ2FsbF92amppPWZ1bmN0aW9uKCl7cmV0dXJuKFBiPWQuZHluQ2FsbF92amppPWQuYXNtLnRiKS5hcHBseShudWxsLGFyZ3VtZW50cyl9LFFiPWQuZHluQ2FsbF92aWlpampqaWk9ZnVuY3Rpb24oKXtyZXR1cm4oUWI9ZC5keW5DYWxsX3ZpaWlqamppaT1kLmFzbS51YikuYXBwbHkobnVsbCxhcmd1bWVudHMpfSxSYj1kLmR5bkNhbGxfaWlqPWZ1bmN0aW9uKCl7cmV0dXJuKFJiPWQuZHluQ2FsbF9paWo9ZC5hc20udmIpLmFwcGx5KG51bGwsYXJndW1lbnRzKX0sU2I9ZC5keW5DYWxsX2ppPWZ1bmN0aW9uKCl7cmV0dXJuKFNiPWQuZHluQ2FsbF9qaT1cXHJcXG5kLmFzbS53YikuYXBwbHkobnVsbCxhcmd1bWVudHMpfSxUYj1kLmR5bkNhbGxfaWlpaWlpaj1mdW5jdGlvbigpe3JldHVybihUYj1kLmR5bkNhbGxfaWlpaWlpaj1kLmFzbS54YikuYXBwbHkobnVsbCxhcmd1bWVudHMpfSxVYj1kLmR5bkNhbGxfaWlpaj1mdW5jdGlvbigpe3JldHVybihVYj1kLmR5bkNhbGxfaWlpaj1kLmFzbS55YikuYXBwbHkobnVsbCxhcmd1bWVudHMpfTtmdW5jdGlvbiBjYihhLGIpe3ZhciBjPVkoKTt0cnl7cmV0dXJuIFUoYSkoYil9Y2F0Y2goZSl7WihjKTtpZihlIT09ZSswKXRocm93IGU7WCgxLDApfX1mdW5jdGlvbiB2YihhLGIpe3ZhciBjPVkoKTt0cnl7VShhKShiKX1jYXRjaChlKXtaKGMpO2lmKGUhPT1lKzApdGhyb3cgZTtYKDEsMCl9fWZ1bmN0aW9uIHdiKGEsYixjKXt2YXIgZT1ZKCk7dHJ5e1UoYSkoYixjKX1jYXRjaChmKXtaKGUpO2lmKGYhPT1mKzApdGhyb3cgZjtYKDEsMCl9fVxcclxcbmZ1bmN0aW9uIGZiKGEsYixjKXt2YXIgZT1ZKCk7dHJ5e3JldHVybiBVKGEpKGIsYyl9Y2F0Y2goZil7WihlKTtpZihmIT09ZiswKXRocm93IGY7WCgxLDApfX1mdW5jdGlvbiBnYihhLGIsYyxlKXt2YXIgZj1ZKCk7dHJ5e3JldHVybiBVKGEpKGIsYyxlKX1jYXRjaChoKXtaKGYpO2lmKGghPT1oKzApdGhyb3cgaDtYKDEsMCl9fWZ1bmN0aW9uIGtiKGEsYixjLGUsZixoLGspe3ZhciBsPVkoKTt0cnl7cmV0dXJuIFUoYSkoYixjLGUsZixoLGspfWNhdGNoKG4pe1oobCk7aWYobiE9PW4rMCl0aHJvdyBuO1goMSwwKX19ZnVuY3Rpb24gdWIoYSl7dmFyIGI9WSgpO3RyeXtVKGEpKCl9Y2F0Y2goYyl7WihiKTtpZihjIT09YyswKXRocm93IGM7WCgxLDApfX1mdW5jdGlvbiBqYihhLGIsYyxlLGYsaCl7dmFyIGs9WSgpO3RyeXtyZXR1cm4gVShhKShiLGMsZSxmLGgpfWNhdGNoKGwpe1ooayk7aWYobCE9PWwrMCl0aHJvdyBsO1goMSwwKX19XFxyXFxuZnVuY3Rpb24gaGIoYSxiLGMsZSxmKXt2YXIgaD1ZKCk7dHJ5e3JldHVybiBVKGEpKGIsYyxlLGYpfWNhdGNoKGspe1ooaCk7aWYoayE9PWsrMCl0aHJvdyBrO1goMSwwKX19ZnVuY3Rpb24geWIoYSxiLGMsZSl7dmFyIGY9WSgpO3RyeXtVKGEpKGIsYyxlKX1jYXRjaChoKXtaKGYpO2lmKGghPT1oKzApdGhyb3cgaDtYKDEsMCl9fWZ1bmN0aW9uIEFiKGEsYixjLGUsZixoKXt2YXIgaz1ZKCk7dHJ5e1UoYSkoYixjLGUsZixoKX1jYXRjaChsKXtaKGspO2lmKGwhPT1sKzApdGhyb3cgbDtYKDEsMCl9fWZ1bmN0aW9uIHpiKGEsYixjLGUsZil7dmFyIGg9WSgpO3RyeXtVKGEpKGIsYyxlLGYpfWNhdGNoKGspe1ooaCk7aWYoayE9PWsrMCl0aHJvdyBrO1goMSwwKX19ZnVuY3Rpb24gQmIoYSxiLGMsZSxmLGgsayl7dmFyIGw9WSgpO3RyeXtVKGEpKGIsYyxlLGYsaCxrKX1jYXRjaChuKXtaKGwpO2lmKG4hPT1uKzApdGhyb3cgbjtYKDEsMCl9fVxcclxcbmZ1bmN0aW9uIENiKGEsYixjLGUsZixoLGssbCl7dmFyIG49WSgpO3RyeXtVKGEpKGIsYyxlLGYsaCxrLGwpfWNhdGNoKHQpe1oobik7aWYodCE9PXQrMCl0aHJvdyB0O1goMSwwKX19ZnVuY3Rpb24gZWIoYSxiLGMpe3ZhciBlPVkoKTt0cnl7cmV0dXJuIFUoYSkoYixjKX1jYXRjaChmKXtaKGUpO2lmKGYhPT1mKzApdGhyb3cgZjtYKDEsMCl9fWZ1bmN0aW9uIGRiKGEsYixjKXt2YXIgZT1ZKCk7dHJ5e3JldHVybiBVKGEpKGIsYyl9Y2F0Y2goZil7WihlKTtpZihmIT09ZiswKXRocm93IGY7WCgxLDApfX1mdW5jdGlvbiBEYihhLGIsYyxlLGYsaCxrLGwsbil7dmFyIHQ9WSgpO3RyeXtVKGEpKGIsYyxlLGYsaCxrLGwsbil9Y2F0Y2goeCl7Wih0KTtpZih4IT09eCswKXRocm93IHg7WCgxLDApfX1mdW5jdGlvbiBpYihhLGIsYyxlLGYsaCl7dmFyIGs9WSgpO3RyeXtyZXR1cm4gVShhKShiLGMsZSxmLGgpfWNhdGNoKGwpe1ooayk7aWYobCE9PWwrMCl0aHJvdyBsO1goMSwwKX19XFxyXFxuZnVuY3Rpb24gbGIoYSxiLGMsZSxmLGgsayxsKXt2YXIgbj1ZKCk7dHJ5e3JldHVybiBVKGEpKGIsYyxlLGYsaCxrLGwpfWNhdGNoKHQpe1oobik7aWYodCE9PXQrMCl0aHJvdyB0O1goMSwwKX19ZnVuY3Rpb24gbWIoYSxiLGMsZSxmLGgsayxsLG4sdCx4LEUpe3ZhciBDPVkoKTt0cnl7cmV0dXJuIFUoYSkoYixjLGUsZixoLGssbCxuLHQseCxFKX1jYXRjaChnKXtaKEMpO2lmKGchPT1nKzApdGhyb3cgZztYKDEsMCl9fWZ1bmN0aW9uIEViKGEsYixjLGUsZixoLGssbCxuLHQseCl7dmFyIEU9WSgpO3RyeXtVKGEpKGIsYyxlLGYsaCxrLGwsbix0LHgpfWNhdGNoKEMpe1ooRSk7aWYoQyE9PUMrMCl0aHJvdyBDO1goMSwwKX19ZnVuY3Rpb24gRmIoYSxiLGMsZSxmLGgsayxsLG4sdCx4LEUsQyxnLHUsdyl7dmFyIEY9WSgpO3RyeXtVKGEpKGIsYyxlLGYsaCxrLGwsbix0LHgsRSxDLGcsdSx3KX1jYXRjaChNKXtaKEYpO2lmKE0hPT1NKzApdGhyb3cgTTtYKDEsMCl9fVxcclxcbmZ1bmN0aW9uIGJiKGEpe3ZhciBiPVkoKTt0cnl7cmV0dXJuIFUoYSkoKX1jYXRjaChjKXtaKGIpO2lmKGMhPT1jKzApdGhyb3cgYztYKDEsMCl9fWZ1bmN0aW9uIGFiKGEsYixjKXt2YXIgZT1ZKCk7dHJ5e3JldHVybiBVKGEpKGIsYyl9Y2F0Y2goZil7WihlKTtpZihmIT09ZiswKXRocm93IGY7WCgxLDApfX1mdW5jdGlvbiAkYShhLGIsYyl7dmFyIGU9WSgpO3RyeXtyZXR1cm4gVShhKShiLGMpfWNhdGNoKGYpe1ooZSk7aWYoZiE9PWYrMCl0aHJvdyBmO1goMSwwKX19ZnVuY3Rpb24geGIoYSxiLGMsZSl7dmFyIGY9WSgpO3RyeXtVKGEpKGIsYyxlKX1jYXRjaChoKXtaKGYpO2lmKGghPT1oKzApdGhyb3cgaDtYKDEsMCl9fWZ1bmN0aW9uIEdiKGEsYixjLGUsZixoLGssbCl7dmFyIG49WSgpO3RyeXtPYihhLGIsYyxlLGYsaCxrLGwpfWNhdGNoKHQpe1oobik7aWYodCE9PXQrMCl0aHJvdyB0O1goMSwwKX19XFxyXFxuZnVuY3Rpb24gSWIoYSxiLGMsZSxmLGgpe3ZhciBrPVkoKTt0cnl7UGIoYSxiLGMsZSxmLGgpfWNhdGNoKGwpe1ooayk7aWYobCE9PWwrMCl0aHJvdyBsO1goMSwwKX19ZnVuY3Rpb24gSGIoYSxiLGMsZSxmLGgsayxsLG4sdCx4LEUpe3ZhciBDPVkoKTt0cnl7UWIoYSxiLGMsZSxmLGgsayxsLG4sdCx4LEUpfWNhdGNoKGcpe1ooQyk7aWYoZyE9PWcrMCl0aHJvdyBnO1goMSwwKX19ZnVuY3Rpb24gcWIoYSxiLGMsZSl7dmFyIGY9WSgpO3RyeXtyZXR1cm4gUmIoYSxiLGMsZSl9Y2F0Y2goaCl7WihmKTtpZihoIT09aCswKXRocm93IGg7WCgxLDApfX1mdW5jdGlvbiBzYihhLGIpe3ZhciBjPVkoKTt0cnl7cmV0dXJuIFNiKGEsYil9Y2F0Y2goZSl7WihjKTtpZihlIT09ZSswKXRocm93IGU7WCgxLDApfX1cXHJcXG5mdW5jdGlvbiBuYihhLGIsYyxlLGYsaCxrLGwpe3ZhciBuPVkoKTt0cnl7cmV0dXJuIFRiKGEsYixjLGUsZixoLGssbCl9Y2F0Y2godCl7WihuKTtpZih0IT09dCswKXRocm93IHQ7WCgxLDApfX1mdW5jdGlvbiByYihhKXt2YXIgYj1ZKCk7dHJ5e3JldHVybiBMYihhKX1jYXRjaChjKXtaKGIpO2lmKGMhPT1jKzApdGhyb3cgYztYKDEsMCl9fWZ1bmN0aW9uIG9iKGEsYixjLGUsZixoLGspe3ZhciBsPVkoKTt0cnl7cmV0dXJuIE1iKGEsYixjLGUsZixoLGspfWNhdGNoKG4pe1oobCk7aWYobiE9PW4rMCl0aHJvdyBuO1goMSwwKX19ZnVuY3Rpb24gcGIoYSxiLGMsZSxmKXt2YXIgaD1ZKCk7dHJ5e3JldHVybiBVYihhLGIsYyxlLGYpfWNhdGNoKGspe1ooaCk7aWYoayE9PWsrMCl0aHJvdyBrO1goMSwwKX19ZnVuY3Rpb24gdGIoYSxiLGMpe3ZhciBlPVkoKTt0cnl7cmV0dXJuIE5iKGEsYixjKX1jYXRjaChmKXtaKGUpO2lmKGYhPT1mKzApdGhyb3cgZjtYKDEsMCl9fVxcclxcbmQuVVRGOFRvU3RyaW5nPXBhO2Quc3RyaW5nVG9VVEY4PWZ1bmN0aW9uKGEsYixjKXtyZXR1cm4gcWEoYSxHLGIsYyl9O2QubGVuZ3RoQnl0ZXNVVEY4PXJhO2Quc3RhY2tTYXZlPVk7ZC5zdGFja1Jlc3RvcmU9WjtkLnN0YWNrQWxsb2M9S2I7dmFyIFZiO0w9ZnVuY3Rpb24gV2IoKXtWYnx8WGIoKTtWYnx8KEw9V2IpfTtcXHJcXG5mdW5jdGlvbiBYYigpe2Z1bmN0aW9uIGEoKXtpZighVmImJihWYj0hMCxkLmNhbGxlZFJ1bj0hMCwhRCkpe08od2EpO2FhKGQpO2lmKGQub25SdW50aW1lSW5pdGlhbGl6ZWQpZC5vblJ1bnRpbWVJbml0aWFsaXplZCgpO2lmKGQucG9zdFJ1bilmb3IoXFxcImZ1bmN0aW9uXFxcIj09dHlwZW9mIGQucG9zdFJ1biYmKGQucG9zdFJ1bj1bZC5wb3N0UnVuXSk7ZC5wb3N0UnVuLmxlbmd0aDspe3ZhciBiPWQucG9zdFJ1bi5zaGlmdCgpO3lhLnVuc2hpZnQoYil9Tyh5YSl9fWlmKCEoMDxLKSl7aWYoZC5wcmVSdW4pZm9yKFxcXCJmdW5jdGlvblxcXCI9PXR5cGVvZiBkLnByZVJ1biYmKGQucHJlUnVuPVtkLnByZVJ1bl0pO2QucHJlUnVuLmxlbmd0aDspemEoKTtPKHZhKTswPEt8fChkLnNldFN0YXR1cz8oZC5zZXRTdGF0dXMoXFxcIlJ1bm5pbmcuLi5cXFwiKSxzZXRUaW1lb3V0KGZ1bmN0aW9uKCl7c2V0VGltZW91dChmdW5jdGlvbigpe2Quc2V0U3RhdHVzKFxcXCJcXFwiKX0sMSk7YSgpfSwxKSk6YSgpKX19XFxyXFxuaWYoZC5wcmVJbml0KWZvcihcXFwiZnVuY3Rpb25cXFwiPT10eXBlb2YgZC5wcmVJbml0JiYoZC5wcmVJbml0PVtkLnByZUluaXRdKTswPGQucHJlSW5pdC5sZW5ndGg7KWQucHJlSW5pdC5wb3AoKSgpO1hiKCk7XFxyXFxuXFxyXFxuXFxyXFxuICByZXR1cm4gb3J0V2FzbS5yZWFkeVxcclxcbn1cXHJcXG4pO1xcclxcbn0pKCk7XFxyXFxuaWYgKHRydWUpXFxyXFxuICBtb2R1bGUuZXhwb3J0cyA9IG9ydFdhc207XFxyXFxuZWxzZSB7fVxcclxcblxcblxcbi8qKiovIH0pLFxcblxcbi8qKiovIFxcXCIuL2xpYi93YXNtL29wdGlvbnMtdXRpbHMudHNcXFwiOlxcbi8qISoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqISpcXFxcXFxuICAhKioqIC4vbGliL3dhc20vb3B0aW9ucy11dGlscy50cyAqKiohXFxuICBcXFxcKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiovXFxuLyoqKi8gKChfX3VudXNlZF93ZWJwYWNrX21vZHVsZSwgZXhwb3J0cykgPT4ge1xcblxcblxcXCJ1c2Ugc3RyaWN0XFxcIjtcXG5cXG4vLyBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXFxuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFxcXCJfX2VzTW9kdWxlXFxcIiwgKHsgdmFsdWU6IHRydWUgfSkpO1xcbmV4cG9ydHMuaXRlcmF0ZUV4dHJhT3B0aW9ucyA9IHZvaWQgMDtcXG5jb25zdCBpdGVyYXRlRXh0cmFPcHRpb25zID0gKG9wdGlvbnMsIHByZWZpeCwgc2VlbiwgaGFuZGxlcikgPT4ge1xcbiAgICBpZiAodHlwZW9mIG9wdGlvbnMgPT0gJ29iamVjdCcgJiYgb3B0aW9ucyAhPT0gbnVsbCkge1xcbiAgICAgICAgaWYgKHNlZW4uaGFzKG9wdGlvbnMpKSB7XFxuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdDaXJjdWxhciByZWZlcmVuY2UgaW4gb3B0aW9ucycpO1xcbiAgICAgICAgfVxcbiAgICAgICAgZWxzZSB7XFxuICAgICAgICAgICAgc2Vlbi5hZGQob3B0aW9ucyk7XFxuICAgICAgICB9XFxuICAgIH1cXG4gICAgT2JqZWN0LmVudHJpZXMob3B0aW9ucykuZm9yRWFjaCgoW2tleSwgdmFsdWVdKSA9PiB7XFxuICAgICAgICBjb25zdCBuYW1lID0gKHByZWZpeCkgPyBwcmVmaXggKyBrZXkgOiBrZXk7XFxuICAgICAgICBpZiAodHlwZW9mIHZhbHVlID09PSAnb2JqZWN0Jykge1xcbiAgICAgICAgICAgICgwLCBleHBvcnRzLml0ZXJhdGVFeHRyYU9wdGlvbnMpKHZhbHVlLCBuYW1lICsgJy4nLCBzZWVuLCBoYW5kbGVyKTtcXG4gICAgICAgIH1cXG4gICAgICAgIGVsc2UgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gJ3N0cmluZycgfHwgdHlwZW9mIHZhbHVlID09PSAnbnVtYmVyJykge1xcbiAgICAgICAgICAgIGhhbmRsZXIobmFtZSwgdmFsdWUudG9TdHJpbmcoKSk7XFxuICAgICAgICB9XFxuICAgICAgICBlbHNlIGlmICh0eXBlb2YgdmFsdWUgPT09ICdib29sZWFuJykge1xcbiAgICAgICAgICAgIGhhbmRsZXIobmFtZSwgKHZhbHVlKSA/ICcxJyA6ICcwJyk7XFxuICAgICAgICB9XFxuICAgICAgICBlbHNlIHtcXG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYENhbid0IGhhbmRsZSBleHRyYSBjb25maWcgdHlwZTogJHt0eXBlb2YgdmFsdWV9YCk7XFxuICAgICAgICB9XFxuICAgIH0pO1xcbn07XFxuZXhwb3J0cy5pdGVyYXRlRXh0cmFPcHRpb25zID0gaXRlcmF0ZUV4dHJhT3B0aW9ucztcXG5cXG5cXG4vKioqLyB9KSxcXG5cXG4vKioqLyBcXFwiLi9saWIvd2FzbS9ydW4tb3B0aW9ucy50c1xcXCI6XFxuLyohKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqISpcXFxcXFxuICAhKioqIC4vbGliL3dhc20vcnVuLW9wdGlvbnMudHMgKioqIVxcbiAgXFxcXCoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKi9cXG4vKioqLyAoKF9fdW51c2VkX3dlYnBhY2tfbW9kdWxlLCBleHBvcnRzLCBfX3dlYnBhY2tfcmVxdWlyZV9fKSA9PiB7XFxuXFxuXFxcInVzZSBzdHJpY3RcXFwiO1xcblxcbi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxcbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cXG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXFxcIl9fZXNNb2R1bGVcXFwiLCAoeyB2YWx1ZTogdHJ1ZSB9KSk7XFxuZXhwb3J0cy5zZXRSdW5PcHRpb25zID0gdm9pZCAwO1xcbmNvbnN0IG9wdGlvbnNfdXRpbHNfMSA9IF9fd2VicGFja19yZXF1aXJlX18oLyohIC4vb3B0aW9ucy11dGlscyAqLyBcXFwiLi9saWIvd2FzbS9vcHRpb25zLXV0aWxzLnRzXFxcIik7XFxuY29uc3Qgc3RyaW5nX3V0aWxzXzEgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKC8qISAuL3N0cmluZy11dGlscyAqLyBcXFwiLi9saWIvd2FzbS9zdHJpbmctdXRpbHMudHNcXFwiKTtcXG5jb25zdCB3YXNtX2ZhY3RvcnlfMSA9IF9fd2VicGFja19yZXF1aXJlX18oLyohIC4vd2FzbS1mYWN0b3J5ICovIFxcXCIuL2xpYi93YXNtL3dhc20tZmFjdG9yeS50c1xcXCIpO1xcbmNvbnN0IHNldFJ1bk9wdGlvbnMgPSAob3B0aW9ucykgPT4ge1xcbiAgICBjb25zdCB3YXNtID0gKDAsIHdhc21fZmFjdG9yeV8xLmdldEluc3RhbmNlKSgpO1xcbiAgICBsZXQgcnVuT3B0aW9uc0hhbmRsZSA9IDA7XFxuICAgIGNvbnN0IGFsbG9jcyA9IFtdO1xcbiAgICBjb25zdCBydW5PcHRpb25zID0gb3B0aW9ucyB8fCB7fTtcXG4gICAgdHJ5IHtcXG4gICAgICAgIGlmICgob3B0aW9ucyA9PT0gbnVsbCB8fCBvcHRpb25zID09PSB2b2lkIDAgPyB2b2lkIDAgOiBvcHRpb25zLmxvZ1NldmVyaXR5TGV2ZWwpID09PSB1bmRlZmluZWQpIHtcXG4gICAgICAgICAgICBydW5PcHRpb25zLmxvZ1NldmVyaXR5TGV2ZWwgPSAyOyAvLyBEZWZhdWx0IHRvIHdhcm5pbmdcXG4gICAgICAgIH1cXG4gICAgICAgIGVsc2UgaWYgKHR5cGVvZiBvcHRpb25zLmxvZ1NldmVyaXR5TGV2ZWwgIT09ICdudW1iZXInIHx8ICFOdW1iZXIuaXNJbnRlZ2VyKG9wdGlvbnMubG9nU2V2ZXJpdHlMZXZlbCkgfHxcXG4gICAgICAgICAgICBvcHRpb25zLmxvZ1NldmVyaXR5TGV2ZWwgPCAwIHx8IG9wdGlvbnMubG9nU2V2ZXJpdHlMZXZlbCA+IDQpIHtcXG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYGxvZyBzZXJ2ZXJpdHkgbGV2ZWwgaXMgbm90IHZhbGlkOiAke29wdGlvbnMubG9nU2V2ZXJpdHlMZXZlbH1gKTtcXG4gICAgICAgIH1cXG4gICAgICAgIGlmICgob3B0aW9ucyA9PT0gbnVsbCB8fCBvcHRpb25zID09PSB2b2lkIDAgPyB2b2lkIDAgOiBvcHRpb25zLmxvZ1ZlcmJvc2l0eUxldmVsKSA9PT0gdW5kZWZpbmVkKSB7XFxuICAgICAgICAgICAgcnVuT3B0aW9ucy5sb2dWZXJib3NpdHlMZXZlbCA9IDA7IC8vIERlZmF1bHQgdG8gMFxcbiAgICAgICAgfVxcbiAgICAgICAgZWxzZSBpZiAodHlwZW9mIG9wdGlvbnMubG9nVmVyYm9zaXR5TGV2ZWwgIT09ICdudW1iZXInIHx8ICFOdW1iZXIuaXNJbnRlZ2VyKG9wdGlvbnMubG9nVmVyYm9zaXR5TGV2ZWwpKSB7XFxuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBsb2cgdmVyYm9zaXR5IGxldmVsIGlzIG5vdCB2YWxpZDogJHtvcHRpb25zLmxvZ1ZlcmJvc2l0eUxldmVsfWApO1xcbiAgICAgICAgfVxcbiAgICAgICAgaWYgKChvcHRpb25zID09PSBudWxsIHx8IG9wdGlvbnMgPT09IHZvaWQgMCA/IHZvaWQgMCA6IG9wdGlvbnMudGVybWluYXRlKSA9PT0gdW5kZWZpbmVkKSB7XFxuICAgICAgICAgICAgcnVuT3B0aW9ucy50ZXJtaW5hdGUgPSBmYWxzZTtcXG4gICAgICAgIH1cXG4gICAgICAgIGxldCB0YWdEYXRhT2Zmc2V0ID0gMDtcXG4gICAgICAgIGlmICgob3B0aW9ucyA9PT0gbnVsbCB8fCBvcHRpb25zID09PSB2b2lkIDAgPyB2b2lkIDAgOiBvcHRpb25zLnRhZykgIT09IHVuZGVmaW5lZCkge1xcbiAgICAgICAgICAgIHRhZ0RhdGFPZmZzZXQgPSAoMCwgc3RyaW5nX3V0aWxzXzEuYWxsb2NXYXNtU3RyaW5nKShvcHRpb25zLnRhZywgYWxsb2NzKTtcXG4gICAgICAgIH1cXG4gICAgICAgIHJ1bk9wdGlvbnNIYW5kbGUgPSB3YXNtLl9PcnRDcmVhdGVSdW5PcHRpb25zKHJ1bk9wdGlvbnMubG9nU2V2ZXJpdHlMZXZlbCwgcnVuT3B0aW9ucy5sb2dWZXJib3NpdHlMZXZlbCwgISFydW5PcHRpb25zLnRlcm1pbmF0ZSwgdGFnRGF0YU9mZnNldCk7XFxuICAgICAgICBpZiAocnVuT3B0aW9uc0hhbmRsZSA9PT0gMCkge1xcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignQ2FuXFxcXCd0IGNyZWF0ZSBydW4gb3B0aW9ucycpO1xcbiAgICAgICAgfVxcbiAgICAgICAgaWYgKChvcHRpb25zID09PSBudWxsIHx8IG9wdGlvbnMgPT09IHZvaWQgMCA/IHZvaWQgMCA6IG9wdGlvbnMuZXh0cmEpICE9PSB1bmRlZmluZWQpIHtcXG4gICAgICAgICAgICAoMCwgb3B0aW9uc191dGlsc18xLml0ZXJhdGVFeHRyYU9wdGlvbnMpKG9wdGlvbnMuZXh0cmEsICcnLCBuZXcgV2Vha1NldCgpLCAoa2V5LCB2YWx1ZSkgPT4ge1xcbiAgICAgICAgICAgICAgICBjb25zdCBrZXlEYXRhT2Zmc2V0ID0gKDAsIHN0cmluZ191dGlsc18xLmFsbG9jV2FzbVN0cmluZykoa2V5LCBhbGxvY3MpO1xcbiAgICAgICAgICAgICAgICBjb25zdCB2YWx1ZURhdGFPZmZzZXQgPSAoMCwgc3RyaW5nX3V0aWxzXzEuYWxsb2NXYXNtU3RyaW5nKSh2YWx1ZSwgYWxsb2NzKTtcXG4gICAgICAgICAgICAgICAgaWYgKHdhc20uX09ydEFkZFJ1bkNvbmZpZ0VudHJ5KHJ1bk9wdGlvbnNIYW5kbGUsIGtleURhdGFPZmZzZXQsIHZhbHVlRGF0YU9mZnNldCkgIT09IDApIHtcXG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgQ2FuJ3Qgc2V0IGEgcnVuIGNvbmZpZyBlbnRyeTogJHtrZXl9IC0gJHt2YWx1ZX1gKTtcXG4gICAgICAgICAgICAgICAgfVxcbiAgICAgICAgICAgIH0pO1xcbiAgICAgICAgfVxcbiAgICAgICAgcmV0dXJuIFtydW5PcHRpb25zSGFuZGxlLCBhbGxvY3NdO1xcbiAgICB9XFxuICAgIGNhdGNoIChlKSB7XFxuICAgICAgICBpZiAocnVuT3B0aW9uc0hhbmRsZSAhPT0gMCkge1xcbiAgICAgICAgICAgIHdhc20uX09ydFJlbGVhc2VSdW5PcHRpb25zKHJ1bk9wdGlvbnNIYW5kbGUpO1xcbiAgICAgICAgfVxcbiAgICAgICAgYWxsb2NzLmZvckVhY2god2FzbS5fZnJlZSk7XFxuICAgICAgICB0aHJvdyBlO1xcbiAgICB9XFxufTtcXG5leHBvcnRzLnNldFJ1bk9wdGlvbnMgPSBzZXRSdW5PcHRpb25zO1xcblxcblxcbi8qKiovIH0pLFxcblxcbi8qKiovIFxcXCIuL2xpYi93YXNtL3Nlc3Npb24tb3B0aW9ucy50c1xcXCI6XFxuLyohKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiEqXFxcXFxcbiAgISoqKiAuL2xpYi93YXNtL3Nlc3Npb24tb3B0aW9ucy50cyAqKiohXFxuICBcXFxcKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKi9cXG4vKioqLyAoKF9fdW51c2VkX3dlYnBhY2tfbW9kdWxlLCBleHBvcnRzLCBfX3dlYnBhY2tfcmVxdWlyZV9fKSA9PiB7XFxuXFxuXFxcInVzZSBzdHJpY3RcXFwiO1xcblxcbi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxcbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cXG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXFxcIl9fZXNNb2R1bGVcXFwiLCAoeyB2YWx1ZTogdHJ1ZSB9KSk7XFxuZXhwb3J0cy5zZXRTZXNzaW9uT3B0aW9ucyA9IHZvaWQgMDtcXG5jb25zdCBvcHRpb25zX3V0aWxzXzEgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKC8qISAuL29wdGlvbnMtdXRpbHMgKi8gXFxcIi4vbGliL3dhc20vb3B0aW9ucy11dGlscy50c1xcXCIpO1xcbmNvbnN0IHN0cmluZ191dGlsc18xID0gX193ZWJwYWNrX3JlcXVpcmVfXygvKiEgLi9zdHJpbmctdXRpbHMgKi8gXFxcIi4vbGliL3dhc20vc3RyaW5nLXV0aWxzLnRzXFxcIik7XFxuY29uc3Qgd2FzbV9mYWN0b3J5XzEgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKC8qISAuL3dhc20tZmFjdG9yeSAqLyBcXFwiLi9saWIvd2FzbS93YXNtLWZhY3RvcnkudHNcXFwiKTtcXG5jb25zdCBnZXRHcmFwaE9wdGltemF0aW9uTGV2ZWwgPSAoZ3JhcGhPcHRpbWl6YXRpb25MZXZlbCkgPT4ge1xcbiAgICBzd2l0Y2ggKGdyYXBoT3B0aW1pemF0aW9uTGV2ZWwpIHtcXG4gICAgICAgIGNhc2UgJ2Rpc2FibGVkJzpcXG4gICAgICAgICAgICByZXR1cm4gMDtcXG4gICAgICAgIGNhc2UgJ2Jhc2ljJzpcXG4gICAgICAgICAgICByZXR1cm4gMTtcXG4gICAgICAgIGNhc2UgJ2V4dGVuZGVkJzpcXG4gICAgICAgICAgICByZXR1cm4gMjtcXG4gICAgICAgIGNhc2UgJ2FsbCc6XFxuICAgICAgICAgICAgcmV0dXJuIDk5O1xcbiAgICAgICAgZGVmYXVsdDpcXG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYHVuc3VwcG9ydGVkIGdyYXBoIG9wdGltaXphdGlvbiBsZXZlbDogJHtncmFwaE9wdGltaXphdGlvbkxldmVsfWApO1xcbiAgICB9XFxufTtcXG5jb25zdCBnZXRFeGVjdXRpb25Nb2RlID0gKGV4ZWN1dGlvbk1vZGUpID0+IHtcXG4gICAgc3dpdGNoIChleGVjdXRpb25Nb2RlKSB7XFxuICAgICAgICBjYXNlICdzZXF1ZW50aWFsJzpcXG4gICAgICAgICAgICByZXR1cm4gMDtcXG4gICAgICAgIGNhc2UgJ3BhcmFsbGVsJzpcXG4gICAgICAgICAgICByZXR1cm4gMTtcXG4gICAgICAgIGRlZmF1bHQ6XFxuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGB1bnN1cHBvcnRlZCBleGVjdXRpb24gbW9kZTogJHtleGVjdXRpb25Nb2RlfWApO1xcbiAgICB9XFxufTtcXG5jb25zdCBhcHBlbmREZWZhdWx0T3B0aW9ucyA9IChvcHRpb25zKSA9PiB7XFxuICAgIGlmICghb3B0aW9ucy5leHRyYSkge1xcbiAgICAgICAgb3B0aW9ucy5leHRyYSA9IHt9O1xcbiAgICB9XFxuICAgIGlmICghb3B0aW9ucy5leHRyYS5zZXNzaW9uKSB7XFxuICAgICAgICBvcHRpb25zLmV4dHJhLnNlc3Npb24gPSB7fTtcXG4gICAgfVxcbiAgICBjb25zdCBzZXNzaW9uID0gb3B0aW9ucy5leHRyYS5zZXNzaW9uO1xcbiAgICBpZiAoIXNlc3Npb24udXNlX29ydF9tb2RlbF9ieXRlc19kaXJlY3RseSkge1xcbiAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGNhbWVsY2FzZVxcbiAgICAgICAgc2Vzc2lvbi51c2Vfb3J0X21vZGVsX2J5dGVzX2RpcmVjdGx5ID0gJzEnO1xcbiAgICB9XFxufTtcXG5jb25zdCBzZXRFeGVjdXRpb25Qcm92aWRlcnMgPSAoc2Vzc2lvbk9wdGlvbnNIYW5kbGUsIGV4ZWN1dGlvblByb3ZpZGVycywgYWxsb2NzKSA9PiB7XFxuICAgIGZvciAoY29uc3QgZXAgb2YgZXhlY3V0aW9uUHJvdmlkZXJzKSB7XFxuICAgICAgICBsZXQgZXBOYW1lID0gdHlwZW9mIGVwID09PSAnc3RyaW5nJyA/IGVwIDogZXAubmFtZTtcXG4gICAgICAgIC8vIGNoZWNrIEVQIG5hbWVcXG4gICAgICAgIHN3aXRjaCAoZXBOYW1lKSB7XFxuICAgICAgICAgICAgY2FzZSAneG5ucGFjayc6XFxuICAgICAgICAgICAgICAgIGVwTmFtZSA9ICdYTk5QQUNLJztcXG4gICAgICAgICAgICAgICAgYnJlYWs7XFxuICAgICAgICAgICAgY2FzZSAnd2FzbSc6XFxuICAgICAgICAgICAgY2FzZSAnY3B1JzpcXG4gICAgICAgICAgICAgICAgY29udGludWU7XFxuICAgICAgICAgICAgZGVmYXVsdDpcXG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBub3Qgc3VwcG9ydGVkIEVQOiAke2VwTmFtZX1gKTtcXG4gICAgICAgIH1cXG4gICAgICAgIGNvbnN0IGVwTmFtZURhdGFPZmZzZXQgPSAoMCwgc3RyaW5nX3V0aWxzXzEuYWxsb2NXYXNtU3RyaW5nKShlcE5hbWUsIGFsbG9jcyk7XFxuICAgICAgICBpZiAoKDAsIHdhc21fZmFjdG9yeV8xLmdldEluc3RhbmNlKSgpLl9PcnRBcHBlbmRFeGVjdXRpb25Qcm92aWRlcihzZXNzaW9uT3B0aW9uc0hhbmRsZSwgZXBOYW1lRGF0YU9mZnNldCkgIT09IDApIHtcXG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYENhbid0IGFwcGVuZCBleGVjdXRpb24gcHJvdmlkZXI6ICR7ZXBOYW1lfWApO1xcbiAgICAgICAgfVxcbiAgICB9XFxufTtcXG5jb25zdCBzZXRTZXNzaW9uT3B0aW9ucyA9IChvcHRpb25zKSA9PiB7XFxuICAgIGNvbnN0IHdhc20gPSAoMCwgd2FzbV9mYWN0b3J5XzEuZ2V0SW5zdGFuY2UpKCk7XFxuICAgIGxldCBzZXNzaW9uT3B0aW9uc0hhbmRsZSA9IDA7XFxuICAgIGNvbnN0IGFsbG9jcyA9IFtdO1xcbiAgICBjb25zdCBzZXNzaW9uT3B0aW9ucyA9IG9wdGlvbnMgfHwge307XFxuICAgIGFwcGVuZERlZmF1bHRPcHRpb25zKHNlc3Npb25PcHRpb25zKTtcXG4gICAgdHJ5IHtcXG4gICAgICAgIGlmICgob3B0aW9ucyA9PT0gbnVsbCB8fCBvcHRpb25zID09PSB2b2lkIDAgPyB2b2lkIDAgOiBvcHRpb25zLmdyYXBoT3B0aW1pemF0aW9uTGV2ZWwpID09PSB1bmRlZmluZWQpIHtcXG4gICAgICAgICAgICBzZXNzaW9uT3B0aW9ucy5ncmFwaE9wdGltaXphdGlvbkxldmVsID0gJ2FsbCc7XFxuICAgICAgICB9XFxuICAgICAgICBjb25zdCBncmFwaE9wdGltaXphdGlvbkxldmVsID0gZ2V0R3JhcGhPcHRpbXphdGlvbkxldmVsKHNlc3Npb25PcHRpb25zLmdyYXBoT3B0aW1pemF0aW9uTGV2ZWwpO1xcbiAgICAgICAgaWYgKChvcHRpb25zID09PSBudWxsIHx8IG9wdGlvbnMgPT09IHZvaWQgMCA/IHZvaWQgMCA6IG9wdGlvbnMuZW5hYmxlQ3B1TWVtQXJlbmEpID09PSB1bmRlZmluZWQpIHtcXG4gICAgICAgICAgICBzZXNzaW9uT3B0aW9ucy5lbmFibGVDcHVNZW1BcmVuYSA9IHRydWU7XFxuICAgICAgICB9XFxuICAgICAgICBpZiAoKG9wdGlvbnMgPT09IG51bGwgfHwgb3B0aW9ucyA9PT0gdm9pZCAwID8gdm9pZCAwIDogb3B0aW9ucy5lbmFibGVNZW1QYXR0ZXJuKSA9PT0gdW5kZWZpbmVkKSB7XFxuICAgICAgICAgICAgc2Vzc2lvbk9wdGlvbnMuZW5hYmxlTWVtUGF0dGVybiA9IHRydWU7XFxuICAgICAgICB9XFxuICAgICAgICBpZiAoKG9wdGlvbnMgPT09IG51bGwgfHwgb3B0aW9ucyA9PT0gdm9pZCAwID8gdm9pZCAwIDogb3B0aW9ucy5leGVjdXRpb25Nb2RlKSA9PT0gdW5kZWZpbmVkKSB7XFxuICAgICAgICAgICAgc2Vzc2lvbk9wdGlvbnMuZXhlY3V0aW9uTW9kZSA9ICdzZXF1ZW50aWFsJztcXG4gICAgICAgIH1cXG4gICAgICAgIGNvbnN0IGV4ZWN1dGlvbk1vZGUgPSBnZXRFeGVjdXRpb25Nb2RlKHNlc3Npb25PcHRpb25zLmV4ZWN1dGlvbk1vZGUpO1xcbiAgICAgICAgbGV0IGxvZ0lkRGF0YU9mZnNldCA9IDA7XFxuICAgICAgICBpZiAoKG9wdGlvbnMgPT09IG51bGwgfHwgb3B0aW9ucyA9PT0gdm9pZCAwID8gdm9pZCAwIDogb3B0aW9ucy5sb2dJZCkgIT09IHVuZGVmaW5lZCkge1xcbiAgICAgICAgICAgIGxvZ0lkRGF0YU9mZnNldCA9ICgwLCBzdHJpbmdfdXRpbHNfMS5hbGxvY1dhc21TdHJpbmcpKG9wdGlvbnMubG9nSWQsIGFsbG9jcyk7XFxuICAgICAgICB9XFxuICAgICAgICBpZiAoKG9wdGlvbnMgPT09IG51bGwgfHwgb3B0aW9ucyA9PT0gdm9pZCAwID8gdm9pZCAwIDogb3B0aW9ucy5sb2dTZXZlcml0eUxldmVsKSA9PT0gdW5kZWZpbmVkKSB7XFxuICAgICAgICAgICAgc2Vzc2lvbk9wdGlvbnMubG9nU2V2ZXJpdHlMZXZlbCA9IDI7IC8vIERlZmF1bHQgdG8gd2FybmluZ1xcbiAgICAgICAgfVxcbiAgICAgICAgZWxzZSBpZiAodHlwZW9mIG9wdGlvbnMubG9nU2V2ZXJpdHlMZXZlbCAhPT0gJ251bWJlcicgfHwgIU51bWJlci5pc0ludGVnZXIob3B0aW9ucy5sb2dTZXZlcml0eUxldmVsKSB8fFxcbiAgICAgICAgICAgIG9wdGlvbnMubG9nU2V2ZXJpdHlMZXZlbCA8IDAgfHwgb3B0aW9ucy5sb2dTZXZlcml0eUxldmVsID4gNCkge1xcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgbG9nIHNlcnZlcml0eSBsZXZlbCBpcyBub3QgdmFsaWQ6ICR7b3B0aW9ucy5sb2dTZXZlcml0eUxldmVsfWApO1xcbiAgICAgICAgfVxcbiAgICAgICAgaWYgKChvcHRpb25zID09PSBudWxsIHx8IG9wdGlvbnMgPT09IHZvaWQgMCA/IHZvaWQgMCA6IG9wdGlvbnMubG9nVmVyYm9zaXR5TGV2ZWwpID09PSB1bmRlZmluZWQpIHtcXG4gICAgICAgICAgICBzZXNzaW9uT3B0aW9ucy5sb2dWZXJib3NpdHlMZXZlbCA9IDA7IC8vIERlZmF1bHQgdG8gMFxcbiAgICAgICAgfVxcbiAgICAgICAgZWxzZSBpZiAodHlwZW9mIG9wdGlvbnMubG9nVmVyYm9zaXR5TGV2ZWwgIT09ICdudW1iZXInIHx8ICFOdW1iZXIuaXNJbnRlZ2VyKG9wdGlvbnMubG9nVmVyYm9zaXR5TGV2ZWwpKSB7XFxuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBsb2cgdmVyYm9zaXR5IGxldmVsIGlzIG5vdCB2YWxpZDogJHtvcHRpb25zLmxvZ1ZlcmJvc2l0eUxldmVsfWApO1xcbiAgICAgICAgfVxcbiAgICAgICAgaWYgKChvcHRpb25zID09PSBudWxsIHx8IG9wdGlvbnMgPT09IHZvaWQgMCA/IHZvaWQgMCA6IG9wdGlvbnMuZW5hYmxlUHJvZmlsaW5nKSA9PT0gdW5kZWZpbmVkKSB7XFxuICAgICAgICAgICAgc2Vzc2lvbk9wdGlvbnMuZW5hYmxlUHJvZmlsaW5nID0gZmFsc2U7XFxuICAgICAgICB9XFxuICAgICAgICBzZXNzaW9uT3B0aW9uc0hhbmRsZSA9IHdhc20uX09ydENyZWF0ZVNlc3Npb25PcHRpb25zKGdyYXBoT3B0aW1pemF0aW9uTGV2ZWwsICEhc2Vzc2lvbk9wdGlvbnMuZW5hYmxlQ3B1TWVtQXJlbmEsICEhc2Vzc2lvbk9wdGlvbnMuZW5hYmxlTWVtUGF0dGVybiwgZXhlY3V0aW9uTW9kZSwgISFzZXNzaW9uT3B0aW9ucy5lbmFibGVQcm9maWxpbmcsIDAsIGxvZ0lkRGF0YU9mZnNldCwgc2Vzc2lvbk9wdGlvbnMubG9nU2V2ZXJpdHlMZXZlbCwgc2Vzc2lvbk9wdGlvbnMubG9nVmVyYm9zaXR5TGV2ZWwpO1xcbiAgICAgICAgaWYgKHNlc3Npb25PcHRpb25zSGFuZGxlID09PSAwKSB7XFxuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdDYW5cXFxcJ3QgY3JlYXRlIHNlc3Npb24gb3B0aW9ucycpO1xcbiAgICAgICAgfVxcbiAgICAgICAgaWYgKG9wdGlvbnMgPT09IG51bGwgfHwgb3B0aW9ucyA9PT0gdm9pZCAwID8gdm9pZCAwIDogb3B0aW9ucy5leGVjdXRpb25Qcm92aWRlcnMpIHtcXG4gICAgICAgICAgICBzZXRFeGVjdXRpb25Qcm92aWRlcnMoc2Vzc2lvbk9wdGlvbnNIYW5kbGUsIG9wdGlvbnMuZXhlY3V0aW9uUHJvdmlkZXJzLCBhbGxvY3MpO1xcbiAgICAgICAgfVxcbiAgICAgICAgaWYgKChvcHRpb25zID09PSBudWxsIHx8IG9wdGlvbnMgPT09IHZvaWQgMCA/IHZvaWQgMCA6IG9wdGlvbnMuZXh0cmEpICE9PSB1bmRlZmluZWQpIHtcXG4gICAgICAgICAgICAoMCwgb3B0aW9uc191dGlsc18xLml0ZXJhdGVFeHRyYU9wdGlvbnMpKG9wdGlvbnMuZXh0cmEsICcnLCBuZXcgV2Vha1NldCgpLCAoa2V5LCB2YWx1ZSkgPT4ge1xcbiAgICAgICAgICAgICAgICBjb25zdCBrZXlEYXRhT2Zmc2V0ID0gKDAsIHN0cmluZ191dGlsc18xLmFsbG9jV2FzbVN0cmluZykoa2V5LCBhbGxvY3MpO1xcbiAgICAgICAgICAgICAgICBjb25zdCB2YWx1ZURhdGFPZmZzZXQgPSAoMCwgc3RyaW5nX3V0aWxzXzEuYWxsb2NXYXNtU3RyaW5nKSh2YWx1ZSwgYWxsb2NzKTtcXG4gICAgICAgICAgICAgICAgaWYgKHdhc20uX09ydEFkZFNlc3Npb25Db25maWdFbnRyeShzZXNzaW9uT3B0aW9uc0hhbmRsZSwga2V5RGF0YU9mZnNldCwgdmFsdWVEYXRhT2Zmc2V0KSAhPT0gMCkge1xcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBDYW4ndCBzZXQgYSBzZXNzaW9uIGNvbmZpZyBlbnRyeTogJHtrZXl9IC0gJHt2YWx1ZX1gKTtcXG4gICAgICAgICAgICAgICAgfVxcbiAgICAgICAgICAgIH0pO1xcbiAgICAgICAgfVxcbiAgICAgICAgcmV0dXJuIFtzZXNzaW9uT3B0aW9uc0hhbmRsZSwgYWxsb2NzXTtcXG4gICAgfVxcbiAgICBjYXRjaCAoZSkge1xcbiAgICAgICAgaWYgKHNlc3Npb25PcHRpb25zSGFuZGxlICE9PSAwKSB7XFxuICAgICAgICAgICAgd2FzbS5fT3J0UmVsZWFzZVNlc3Npb25PcHRpb25zKHNlc3Npb25PcHRpb25zSGFuZGxlKTtcXG4gICAgICAgIH1cXG4gICAgICAgIGFsbG9jcy5mb3JFYWNoKHdhc20uX2ZyZWUpO1xcbiAgICAgICAgdGhyb3cgZTtcXG4gICAgfVxcbn07XFxuZXhwb3J0cy5zZXRTZXNzaW9uT3B0aW9ucyA9IHNldFNlc3Npb25PcHRpb25zO1xcblxcblxcbi8qKiovIH0pLFxcblxcbi8qKiovIFxcXCIuL2xpYi93YXNtL3N0cmluZy11dGlscy50c1xcXCI6XFxuLyohKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiEqXFxcXFxcbiAgISoqKiAuL2xpYi93YXNtL3N0cmluZy11dGlscy50cyAqKiohXFxuICBcXFxcKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKi9cXG4vKioqLyAoKF9fdW51c2VkX3dlYnBhY2tfbW9kdWxlLCBleHBvcnRzLCBfX3dlYnBhY2tfcmVxdWlyZV9fKSA9PiB7XFxuXFxuXFxcInVzZSBzdHJpY3RcXFwiO1xcblxcbi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxcbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cXG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXFxcIl9fZXNNb2R1bGVcXFwiLCAoeyB2YWx1ZTogdHJ1ZSB9KSk7XFxuZXhwb3J0cy5hbGxvY1dhc21TdHJpbmcgPSB2b2lkIDA7XFxuY29uc3Qgd2FzbV9mYWN0b3J5XzEgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKC8qISAuL3dhc20tZmFjdG9yeSAqLyBcXFwiLi9saWIvd2FzbS93YXNtLWZhY3RvcnkudHNcXFwiKTtcXG5jb25zdCBhbGxvY1dhc21TdHJpbmcgPSAoZGF0YSwgYWxsb2NzKSA9PiB7XFxuICAgIGNvbnN0IHdhc20gPSAoMCwgd2FzbV9mYWN0b3J5XzEuZ2V0SW5zdGFuY2UpKCk7XFxuICAgIGNvbnN0IGRhdGFMZW5ndGggPSB3YXNtLmxlbmd0aEJ5dGVzVVRGOChkYXRhKSArIDE7XFxuICAgIGNvbnN0IGRhdGFPZmZzZXQgPSB3YXNtLl9tYWxsb2MoZGF0YUxlbmd0aCk7XFxuICAgIHdhc20uc3RyaW5nVG9VVEY4KGRhdGEsIGRhdGFPZmZzZXQsIGRhdGFMZW5ndGgpO1xcbiAgICBhbGxvY3MucHVzaChkYXRhT2Zmc2V0KTtcXG4gICAgcmV0dXJuIGRhdGFPZmZzZXQ7XFxufTtcXG5leHBvcnRzLmFsbG9jV2FzbVN0cmluZyA9IGFsbG9jV2FzbVN0cmluZztcXG5cXG5cXG4vKioqLyB9KSxcXG5cXG4vKioqLyBcXFwiLi9saWIvd2FzbS93YXNtLWNvcmUtaW1wbC50c1xcXCI6XFxuLyohKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqISpcXFxcXFxuICAhKioqIC4vbGliL3dhc20vd2FzbS1jb3JlLWltcGwudHMgKioqIVxcbiAgXFxcXCoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKi9cXG4vKioqLyAoKF9fdW51c2VkX3dlYnBhY2tfbW9kdWxlLCBleHBvcnRzLCBfX3dlYnBhY2tfcmVxdWlyZV9fKSA9PiB7XFxuXFxuXFxcInVzZSBzdHJpY3RcXFwiO1xcblxcbi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxcbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cXG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXFxcIl9fZXNNb2R1bGVcXFwiLCAoeyB2YWx1ZTogdHJ1ZSB9KSk7XFxuZXhwb3J0cy5leHRyYWN0VHJhbnNmZXJhYmxlQnVmZmVycyA9IGV4cG9ydHMuZW5kUHJvZmlsaW5nID0gZXhwb3J0cy5ydW4gPSBleHBvcnRzLnJlbGVhc2VTZXNzaW9uID0gZXhwb3J0cy5jcmVhdGVTZXNzaW9uID0gZXhwb3J0cy5jcmVhdGVTZXNzaW9uRmluYWxpemUgPSBleHBvcnRzLmNyZWF0ZVNlc3Npb25BbGxvY2F0ZSA9IGV4cG9ydHMuaW5pdE9ydCA9IHZvaWQgMDtcXG5jb25zdCBydW5fb3B0aW9uc18xID0gX193ZWJwYWNrX3JlcXVpcmVfXygvKiEgLi9ydW4tb3B0aW9ucyAqLyBcXFwiLi9saWIvd2FzbS9ydW4tb3B0aW9ucy50c1xcXCIpO1xcbmNvbnN0IHNlc3Npb25fb3B0aW9uc18xID0gX193ZWJwYWNrX3JlcXVpcmVfXygvKiEgLi9zZXNzaW9uLW9wdGlvbnMgKi8gXFxcIi4vbGliL3dhc20vc2Vzc2lvbi1vcHRpb25zLnRzXFxcIik7XFxuY29uc3Qgc3RyaW5nX3V0aWxzXzEgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKC8qISAuL3N0cmluZy11dGlscyAqLyBcXFwiLi9saWIvd2FzbS9zdHJpbmctdXRpbHMudHNcXFwiKTtcXG5jb25zdCB3YXNtX2ZhY3RvcnlfMSA9IF9fd2VicGFja19yZXF1aXJlX18oLyohIC4vd2FzbS1mYWN0b3J5ICovIFxcXCIuL2xpYi93YXNtL3dhc20tZmFjdG9yeS50c1xcXCIpO1xcbi8qKlxcbiAqIGluaXRpYWxpemUgT1JUIGVudmlyb25tZW50LlxcbiAqIEBwYXJhbSBudW1UaHJlYWRzIFNldEdsb2JhbEludHJhT3BOdW1UaHJlYWRzKG51bVRocmVhZHMpXFxuICogQHBhcmFtIGxvZ2dpbmdMZXZlbCBDcmVhdGVFbnYoc3RhdGljX2Nhc3Q8T3J0TG9nZ2luZ0xldmVsPihsb2dnaW5nX2xldmVsKSlcXG4gKi9cXG5jb25zdCBpbml0T3J0ID0gKG51bVRocmVhZHMsIGxvZ2dpbmdMZXZlbCkgPT4ge1xcbiAgICBjb25zdCBlcnJvckNvZGUgPSAoMCwgd2FzbV9mYWN0b3J5XzEuZ2V0SW5zdGFuY2UpKCkuX09ydEluaXQobnVtVGhyZWFkcywgbG9nZ2luZ0xldmVsKTtcXG4gICAgaWYgKGVycm9yQ29kZSAhPT0gMCkge1xcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBDYW4ndCBpbml0aWFsaXplIG9ubnhydW50aW1lLiBlcnJvciBjb2RlID0gJHtlcnJvckNvZGV9YCk7XFxuICAgIH1cXG59O1xcbmV4cG9ydHMuaW5pdE9ydCA9IGluaXRPcnQ7XFxuY29uc3QgYWN0aXZlU2Vzc2lvbnMgPSBuZXcgTWFwKCk7XFxuLyoqXFxuICogY3JlYXRlIGFuIGluc3RhbmNlIG9mIEluZmVyZW5jZVNlc3Npb24uXFxuICogQHJldHVybnMgdGhlIG1ldGFkYXRhIG9mIEluZmVyZW5jZVNlc3Npb24uIDAtdmFsdWUgaGFuZGxlIGZvciBmYWlsdXJlLlxcbiAqL1xcbmNvbnN0IGNyZWF0ZVNlc3Npb25BbGxvY2F0ZSA9IChtb2RlbCkgPT4ge1xcbiAgICBjb25zdCB3YXNtID0gKDAsIHdhc21fZmFjdG9yeV8xLmdldEluc3RhbmNlKSgpO1xcbiAgICBjb25zdCBtb2RlbERhdGFPZmZzZXQgPSB3YXNtLl9tYWxsb2MobW9kZWwuYnl0ZUxlbmd0aCk7XFxuICAgIHdhc20uSEVBUFU4LnNldChtb2RlbCwgbW9kZWxEYXRhT2Zmc2V0KTtcXG4gICAgcmV0dXJuIFttb2RlbERhdGFPZmZzZXQsIG1vZGVsLmJ5dGVMZW5ndGhdO1xcbn07XFxuZXhwb3J0cy5jcmVhdGVTZXNzaW9uQWxsb2NhdGUgPSBjcmVhdGVTZXNzaW9uQWxsb2NhdGU7XFxuY29uc3QgY3JlYXRlU2Vzc2lvbkZpbmFsaXplID0gKG1vZGVsRGF0YSwgb3B0aW9ucykgPT4ge1xcbiAgICBjb25zdCB3YXNtID0gKDAsIHdhc21fZmFjdG9yeV8xLmdldEluc3RhbmNlKSgpO1xcbiAgICBsZXQgc2Vzc2lvbkhhbmRsZSA9IDA7XFxuICAgIGxldCBzZXNzaW9uT3B0aW9uc0hhbmRsZSA9IDA7XFxuICAgIGxldCBhbGxvY3MgPSBbXTtcXG4gICAgdHJ5IHtcXG4gICAgICAgIFtzZXNzaW9uT3B0aW9uc0hhbmRsZSwgYWxsb2NzXSA9ICgwLCBzZXNzaW9uX29wdGlvbnNfMS5zZXRTZXNzaW9uT3B0aW9ucykob3B0aW9ucyk7XFxuICAgICAgICBzZXNzaW9uSGFuZGxlID0gd2FzbS5fT3J0Q3JlYXRlU2Vzc2lvbihtb2RlbERhdGFbMF0sIG1vZGVsRGF0YVsxXSwgc2Vzc2lvbk9wdGlvbnNIYW5kbGUpO1xcbiAgICAgICAgaWYgKHNlc3Npb25IYW5kbGUgPT09IDApIHtcXG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0NhblxcXFwndCBjcmVhdGUgYSBzZXNzaW9uJyk7XFxuICAgICAgICB9XFxuICAgIH1cXG4gICAgZmluYWxseSB7XFxuICAgICAgICB3YXNtLl9mcmVlKG1vZGVsRGF0YVswXSk7XFxuICAgICAgICB3YXNtLl9PcnRSZWxlYXNlU2Vzc2lvbk9wdGlvbnMoc2Vzc2lvbk9wdGlvbnNIYW5kbGUpO1xcbiAgICAgICAgYWxsb2NzLmZvckVhY2god2FzbS5fZnJlZSk7XFxuICAgIH1cXG4gICAgY29uc3QgaW5wdXRDb3VudCA9IHdhc20uX09ydEdldElucHV0Q291bnQoc2Vzc2lvbkhhbmRsZSk7XFxuICAgIGNvbnN0IG91dHB1dENvdW50ID0gd2FzbS5fT3J0R2V0T3V0cHV0Q291bnQoc2Vzc2lvbkhhbmRsZSk7XFxuICAgIGNvbnN0IGlucHV0TmFtZXMgPSBbXTtcXG4gICAgY29uc3QgaW5wdXROYW1lc1VURjhFbmNvZGVkID0gW107XFxuICAgIGNvbnN0IG91dHB1dE5hbWVzID0gW107XFxuICAgIGNvbnN0IG91dHB1dE5hbWVzVVRGOEVuY29kZWQgPSBbXTtcXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBpbnB1dENvdW50OyBpKyspIHtcXG4gICAgICAgIGNvbnN0IG5hbWUgPSB3YXNtLl9PcnRHZXRJbnB1dE5hbWUoc2Vzc2lvbkhhbmRsZSwgaSk7XFxuICAgICAgICBpZiAobmFtZSA9PT0gMCkge1xcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignQ2FuXFxcXCd0IGdldCBhbiBpbnB1dCBuYW1lJyk7XFxuICAgICAgICB9XFxuICAgICAgICBpbnB1dE5hbWVzVVRGOEVuY29kZWQucHVzaChuYW1lKTtcXG4gICAgICAgIGlucHV0TmFtZXMucHVzaCh3YXNtLlVURjhUb1N0cmluZyhuYW1lKSk7XFxuICAgIH1cXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBvdXRwdXRDb3VudDsgaSsrKSB7XFxuICAgICAgICBjb25zdCBuYW1lID0gd2FzbS5fT3J0R2V0T3V0cHV0TmFtZShzZXNzaW9uSGFuZGxlLCBpKTtcXG4gICAgICAgIGlmIChuYW1lID09PSAwKSB7XFxuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdDYW5cXFxcJ3QgZ2V0IGFuIG91dHB1dCBuYW1lJyk7XFxuICAgICAgICB9XFxuICAgICAgICBvdXRwdXROYW1lc1VURjhFbmNvZGVkLnB1c2gobmFtZSk7XFxuICAgICAgICBvdXRwdXROYW1lcy5wdXNoKHdhc20uVVRGOFRvU3RyaW5nKG5hbWUpKTtcXG4gICAgfVxcbiAgICBhY3RpdmVTZXNzaW9ucy5zZXQoc2Vzc2lvbkhhbmRsZSwgW3Nlc3Npb25IYW5kbGUsIGlucHV0TmFtZXNVVEY4RW5jb2RlZCwgb3V0cHV0TmFtZXNVVEY4RW5jb2RlZF0pO1xcbiAgICByZXR1cm4gW3Nlc3Npb25IYW5kbGUsIGlucHV0TmFtZXMsIG91dHB1dE5hbWVzXTtcXG59O1xcbmV4cG9ydHMuY3JlYXRlU2Vzc2lvbkZpbmFsaXplID0gY3JlYXRlU2Vzc2lvbkZpbmFsaXplO1xcbi8qKlxcbiAqIGNyZWF0ZSBhbiBpbnN0YW5jZSBvZiBJbmZlcmVuY2VTZXNzaW9uLlxcbiAqIEByZXR1cm5zIHRoZSBtZXRhZGF0YSBvZiBJbmZlcmVuY2VTZXNzaW9uLiAwLXZhbHVlIGhhbmRsZSBmb3IgZmFpbHVyZS5cXG4gKi9cXG5jb25zdCBjcmVhdGVTZXNzaW9uID0gKG1vZGVsLCBvcHRpb25zKSA9PiB7XFxuICAgIGNvbnN0IG1vZGVsRGF0YSA9ICgwLCBleHBvcnRzLmNyZWF0ZVNlc3Npb25BbGxvY2F0ZSkobW9kZWwpO1xcbiAgICByZXR1cm4gKDAsIGV4cG9ydHMuY3JlYXRlU2Vzc2lvbkZpbmFsaXplKShtb2RlbERhdGEsIG9wdGlvbnMpO1xcbn07XFxuZXhwb3J0cy5jcmVhdGVTZXNzaW9uID0gY3JlYXRlU2Vzc2lvbjtcXG5jb25zdCByZWxlYXNlU2Vzc2lvbiA9IChzZXNzaW9uSWQpID0+IHtcXG4gICAgY29uc3Qgd2FzbSA9ICgwLCB3YXNtX2ZhY3RvcnlfMS5nZXRJbnN0YW5jZSkoKTtcXG4gICAgY29uc3Qgc2Vzc2lvbiA9IGFjdGl2ZVNlc3Npb25zLmdldChzZXNzaW9uSWQpO1xcbiAgICBpZiAoIXNlc3Npb24pIHtcXG4gICAgICAgIHRocm93IG5ldyBFcnJvcignaW52YWxpZCBzZXNzaW9uIGlkJyk7XFxuICAgIH1cXG4gICAgY29uc3Qgc2Vzc2lvbkhhbmRsZSA9IHNlc3Npb25bMF07XFxuICAgIGNvbnN0IGlucHV0TmFtZXNVVEY4RW5jb2RlZCA9IHNlc3Npb25bMV07XFxuICAgIGNvbnN0IG91dHB1dE5hbWVzVVRGOEVuY29kZWQgPSBzZXNzaW9uWzJdO1xcbiAgICBpbnB1dE5hbWVzVVRGOEVuY29kZWQuZm9yRWFjaCh3YXNtLl9PcnRGcmVlKTtcXG4gICAgb3V0cHV0TmFtZXNVVEY4RW5jb2RlZC5mb3JFYWNoKHdhc20uX09ydEZyZWUpO1xcbiAgICB3YXNtLl9PcnRSZWxlYXNlU2Vzc2lvbihzZXNzaW9uSGFuZGxlKTtcXG4gICAgYWN0aXZlU2Vzc2lvbnMuZGVsZXRlKHNlc3Npb25JZCk7XFxufTtcXG5leHBvcnRzLnJlbGVhc2VTZXNzaW9uID0gcmVsZWFzZVNlc3Npb247XFxuY29uc3QgdGVuc29yRGF0YVR5cGVTdHJpbmdUb0VudW0gPSAodHlwZSkgPT4ge1xcbiAgICBzd2l0Y2ggKHR5cGUpIHtcXG4gICAgICAgIGNhc2UgJ2ludDgnOlxcbiAgICAgICAgICAgIHJldHVybiAzIC8qIERhdGFUeXBlLmludDggKi87XFxuICAgICAgICBjYXNlICd1aW50OCc6XFxuICAgICAgICAgICAgcmV0dXJuIDIgLyogRGF0YVR5cGUudWludDggKi87XFxuICAgICAgICBjYXNlICdib29sJzpcXG4gICAgICAgICAgICByZXR1cm4gOSAvKiBEYXRhVHlwZS5ib29sICovO1xcbiAgICAgICAgY2FzZSAnaW50MTYnOlxcbiAgICAgICAgICAgIHJldHVybiA1IC8qIERhdGFUeXBlLmludDE2ICovO1xcbiAgICAgICAgY2FzZSAndWludDE2JzpcXG4gICAgICAgICAgICByZXR1cm4gNCAvKiBEYXRhVHlwZS51aW50MTYgKi87XFxuICAgICAgICBjYXNlICdpbnQzMic6XFxuICAgICAgICAgICAgcmV0dXJuIDYgLyogRGF0YVR5cGUuaW50MzIgKi87XFxuICAgICAgICBjYXNlICd1aW50MzInOlxcbiAgICAgICAgICAgIHJldHVybiAxMiAvKiBEYXRhVHlwZS51aW50MzIgKi87XFxuICAgICAgICBjYXNlICdmbG9hdDMyJzpcXG4gICAgICAgICAgICByZXR1cm4gMSAvKiBEYXRhVHlwZS5mbG9hdCAqLztcXG4gICAgICAgIGNhc2UgJ2Zsb2F0NjQnOlxcbiAgICAgICAgICAgIHJldHVybiAxMSAvKiBEYXRhVHlwZS5kb3VibGUgKi87XFxuICAgICAgICBjYXNlICdzdHJpbmcnOlxcbiAgICAgICAgICAgIHJldHVybiA4IC8qIERhdGFUeXBlLnN0cmluZyAqLztcXG4gICAgICAgIGNhc2UgJ2ludDY0JzpcXG4gICAgICAgICAgICByZXR1cm4gNyAvKiBEYXRhVHlwZS5pbnQ2NCAqLztcXG4gICAgICAgIGNhc2UgJ3VpbnQ2NCc6XFxuICAgICAgICAgICAgcmV0dXJuIDEzIC8qIERhdGFUeXBlLnVpbnQ2NCAqLztcXG4gICAgICAgIGRlZmF1bHQ6XFxuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGB1bnN1cHBvcnRlZCBkYXRhIHR5cGU6ICR7dHlwZX1gKTtcXG4gICAgfVxcbn07XFxuY29uc3QgdGVuc29yRGF0YVR5cGVFbnVtVG9TdHJpbmcgPSAodHlwZVByb3RvKSA9PiB7XFxuICAgIHN3aXRjaCAodHlwZVByb3RvKSB7XFxuICAgICAgICBjYXNlIDMgLyogRGF0YVR5cGUuaW50OCAqLzpcXG4gICAgICAgICAgICByZXR1cm4gJ2ludDgnO1xcbiAgICAgICAgY2FzZSAyIC8qIERhdGFUeXBlLnVpbnQ4ICovOlxcbiAgICAgICAgICAgIHJldHVybiAndWludDgnO1xcbiAgICAgICAgY2FzZSA5IC8qIERhdGFUeXBlLmJvb2wgKi86XFxuICAgICAgICAgICAgcmV0dXJuICdib29sJztcXG4gICAgICAgIGNhc2UgNSAvKiBEYXRhVHlwZS5pbnQxNiAqLzpcXG4gICAgICAgICAgICByZXR1cm4gJ2ludDE2JztcXG4gICAgICAgIGNhc2UgNCAvKiBEYXRhVHlwZS51aW50MTYgKi86XFxuICAgICAgICAgICAgcmV0dXJuICd1aW50MTYnO1xcbiAgICAgICAgY2FzZSA2IC8qIERhdGFUeXBlLmludDMyICovOlxcbiAgICAgICAgICAgIHJldHVybiAnaW50MzInO1xcbiAgICAgICAgY2FzZSAxMiAvKiBEYXRhVHlwZS51aW50MzIgKi86XFxuICAgICAgICAgICAgcmV0dXJuICd1aW50MzInO1xcbiAgICAgICAgY2FzZSAxIC8qIERhdGFUeXBlLmZsb2F0ICovOlxcbiAgICAgICAgICAgIHJldHVybiAnZmxvYXQzMic7XFxuICAgICAgICBjYXNlIDExIC8qIERhdGFUeXBlLmRvdWJsZSAqLzpcXG4gICAgICAgICAgICByZXR1cm4gJ2Zsb2F0NjQnO1xcbiAgICAgICAgY2FzZSA4IC8qIERhdGFUeXBlLnN0cmluZyAqLzpcXG4gICAgICAgICAgICByZXR1cm4gJ3N0cmluZyc7XFxuICAgICAgICBjYXNlIDcgLyogRGF0YVR5cGUuaW50NjQgKi86XFxuICAgICAgICAgICAgcmV0dXJuICdpbnQ2NCc7XFxuICAgICAgICBjYXNlIDEzIC8qIERhdGFUeXBlLnVpbnQ2NCAqLzpcXG4gICAgICAgICAgICByZXR1cm4gJ3VpbnQ2NCc7XFxuICAgICAgICBkZWZhdWx0OlxcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgdW5zdXBwb3J0ZWQgZGF0YSB0eXBlOiAke3R5cGVQcm90b31gKTtcXG4gICAgfVxcbn07XFxuY29uc3QgbnVtZXJpY1RlbnNvclR5cGVUb1R5cGVkQXJyYXkgPSAodHlwZSkgPT4ge1xcbiAgICBzd2l0Y2ggKHR5cGUpIHtcXG4gICAgICAgIGNhc2UgJ2Zsb2F0MzInOlxcbiAgICAgICAgICAgIHJldHVybiBGbG9hdDMyQXJyYXk7XFxuICAgICAgICBjYXNlICd1aW50OCc6XFxuICAgICAgICAgICAgcmV0dXJuIFVpbnQ4QXJyYXk7XFxuICAgICAgICBjYXNlICdpbnQ4JzpcXG4gICAgICAgICAgICByZXR1cm4gSW50OEFycmF5O1xcbiAgICAgICAgY2FzZSAndWludDE2JzpcXG4gICAgICAgICAgICByZXR1cm4gVWludDE2QXJyYXk7XFxuICAgICAgICBjYXNlICdpbnQxNic6XFxuICAgICAgICAgICAgcmV0dXJuIEludDE2QXJyYXk7XFxuICAgICAgICBjYXNlICdpbnQzMic6XFxuICAgICAgICAgICAgcmV0dXJuIEludDMyQXJyYXk7XFxuICAgICAgICBjYXNlICdib29sJzpcXG4gICAgICAgICAgICByZXR1cm4gVWludDhBcnJheTtcXG4gICAgICAgIGNhc2UgJ2Zsb2F0NjQnOlxcbiAgICAgICAgICAgIHJldHVybiBGbG9hdDY0QXJyYXk7XFxuICAgICAgICBjYXNlICd1aW50MzInOlxcbiAgICAgICAgICAgIHJldHVybiBVaW50MzJBcnJheTtcXG4gICAgICAgIGNhc2UgJ2ludDY0JzpcXG4gICAgICAgICAgICByZXR1cm4gQmlnSW50NjRBcnJheTtcXG4gICAgICAgIGNhc2UgJ3VpbnQ2NCc6XFxuICAgICAgICAgICAgcmV0dXJuIEJpZ1VpbnQ2NEFycmF5O1xcbiAgICAgICAgZGVmYXVsdDpcXG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYHVuc3VwcG9ydGVkIHR5cGU6ICR7dHlwZX1gKTtcXG4gICAgfVxcbn07XFxuLyoqXFxuICogcGVyZm9ybSBpbmZlcmVuY2UgcnVuXFxuICovXFxuY29uc3QgcnVuID0gKHNlc3Npb25JZCwgaW5wdXRJbmRpY2VzLCBpbnB1dHMsIG91dHB1dEluZGljZXMsIG9wdGlvbnMpID0+IHtcXG4gICAgY29uc3Qgd2FzbSA9ICgwLCB3YXNtX2ZhY3RvcnlfMS5nZXRJbnN0YW5jZSkoKTtcXG4gICAgY29uc3Qgc2Vzc2lvbiA9IGFjdGl2ZVNlc3Npb25zLmdldChzZXNzaW9uSWQpO1xcbiAgICBpZiAoIXNlc3Npb24pIHtcXG4gICAgICAgIHRocm93IG5ldyBFcnJvcignaW52YWxpZCBzZXNzaW9uIGlkJyk7XFxuICAgIH1cXG4gICAgY29uc3Qgc2Vzc2lvbkhhbmRsZSA9IHNlc3Npb25bMF07XFxuICAgIGNvbnN0IGlucHV0TmFtZXNVVEY4RW5jb2RlZCA9IHNlc3Npb25bMV07XFxuICAgIGNvbnN0IG91dHB1dE5hbWVzVVRGOEVuY29kZWQgPSBzZXNzaW9uWzJdO1xcbiAgICBjb25zdCBpbnB1dENvdW50ID0gaW5wdXRJbmRpY2VzLmxlbmd0aDtcXG4gICAgY29uc3Qgb3V0cHV0Q291bnQgPSBvdXRwdXRJbmRpY2VzLmxlbmd0aDtcXG4gICAgbGV0IHJ1bk9wdGlvbnNIYW5kbGUgPSAwO1xcbiAgICBsZXQgcnVuT3B0aW9uc0FsbG9jcyA9IFtdO1xcbiAgICBjb25zdCBpbnB1dFZhbHVlcyA9IFtdO1xcbiAgICBjb25zdCBpbnB1dEFsbG9jcyA9IFtdO1xcbiAgICB0cnkge1xcbiAgICAgICAgW3J1bk9wdGlvbnNIYW5kbGUsIHJ1bk9wdGlvbnNBbGxvY3NdID0gKDAsIHJ1bl9vcHRpb25zXzEuc2V0UnVuT3B0aW9ucykob3B0aW9ucyk7XFxuICAgICAgICAvLyBjcmVhdGUgaW5wdXQgdGVuc29yc1xcbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBpbnB1dENvdW50OyBpKyspIHtcXG4gICAgICAgICAgICBjb25zdCBkYXRhVHlwZSA9IGlucHV0c1tpXVswXTtcXG4gICAgICAgICAgICBjb25zdCBkaW1zID0gaW5wdXRzW2ldWzFdO1xcbiAgICAgICAgICAgIGNvbnN0IGRhdGEgPSBpbnB1dHNbaV1bMl07XFxuICAgICAgICAgICAgbGV0IGRhdGFPZmZzZXQ7XFxuICAgICAgICAgICAgbGV0IGRhdGFCeXRlTGVuZ3RoO1xcbiAgICAgICAgICAgIGlmIChBcnJheS5pc0FycmF5KGRhdGEpKSB7XFxuICAgICAgICAgICAgICAgIC8vIHN0cmluZyB0ZW5zb3JcXG4gICAgICAgICAgICAgICAgZGF0YUJ5dGVMZW5ndGggPSA0ICogZGF0YS5sZW5ndGg7XFxuICAgICAgICAgICAgICAgIGRhdGFPZmZzZXQgPSB3YXNtLl9tYWxsb2MoZGF0YUJ5dGVMZW5ndGgpO1xcbiAgICAgICAgICAgICAgICBpbnB1dEFsbG9jcy5wdXNoKGRhdGFPZmZzZXQpO1xcbiAgICAgICAgICAgICAgICBsZXQgZGF0YUluZGV4ID0gZGF0YU9mZnNldCAvIDQ7XFxuICAgICAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgZGF0YS5sZW5ndGg7IGkrKykge1xcbiAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBkYXRhW2ldICE9PSAnc3RyaW5nJykge1xcbiAgICAgICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoYHRlbnNvciBkYXRhIGF0IGluZGV4ICR7aX0gaXMgbm90IGEgc3RyaW5nYCk7XFxuICAgICAgICAgICAgICAgICAgICB9XFxuICAgICAgICAgICAgICAgICAgICB3YXNtLkhFQVBVMzJbZGF0YUluZGV4KytdID0gKDAsIHN0cmluZ191dGlsc18xLmFsbG9jV2FzbVN0cmluZykoZGF0YVtpXSwgaW5wdXRBbGxvY3MpO1xcbiAgICAgICAgICAgICAgICB9XFxuICAgICAgICAgICAgfVxcbiAgICAgICAgICAgIGVsc2Uge1xcbiAgICAgICAgICAgICAgICBkYXRhQnl0ZUxlbmd0aCA9IGRhdGEuYnl0ZUxlbmd0aDtcXG4gICAgICAgICAgICAgICAgZGF0YU9mZnNldCA9IHdhc20uX21hbGxvYyhkYXRhQnl0ZUxlbmd0aCk7XFxuICAgICAgICAgICAgICAgIGlucHV0QWxsb2NzLnB1c2goZGF0YU9mZnNldCk7XFxuICAgICAgICAgICAgICAgIHdhc20uSEVBUFU4LnNldChuZXcgVWludDhBcnJheShkYXRhLmJ1ZmZlciwgZGF0YS5ieXRlT2Zmc2V0LCBkYXRhQnl0ZUxlbmd0aCksIGRhdGFPZmZzZXQpO1xcbiAgICAgICAgICAgIH1cXG4gICAgICAgICAgICBjb25zdCBzdGFjayA9IHdhc20uc3RhY2tTYXZlKCk7XFxuICAgICAgICAgICAgY29uc3QgZGltc09mZnNldCA9IHdhc20uc3RhY2tBbGxvYyg0ICogZGltcy5sZW5ndGgpO1xcbiAgICAgICAgICAgIHRyeSB7XFxuICAgICAgICAgICAgICAgIGxldCBkaW1JbmRleCA9IGRpbXNPZmZzZXQgLyA0O1xcbiAgICAgICAgICAgICAgICBkaW1zLmZvckVhY2goZCA9PiB3YXNtLkhFQVAzMltkaW1JbmRleCsrXSA9IGQpO1xcbiAgICAgICAgICAgICAgICBjb25zdCB0ZW5zb3IgPSB3YXNtLl9PcnRDcmVhdGVUZW5zb3IodGVuc29yRGF0YVR5cGVTdHJpbmdUb0VudW0oZGF0YVR5cGUpLCBkYXRhT2Zmc2V0LCBkYXRhQnl0ZUxlbmd0aCwgZGltc09mZnNldCwgZGltcy5sZW5ndGgpO1xcbiAgICAgICAgICAgICAgICBpZiAodGVuc29yID09PSAwKSB7XFxuICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0NhblxcXFwndCBjcmVhdGUgYSB0ZW5zb3InKTtcXG4gICAgICAgICAgICAgICAgfVxcbiAgICAgICAgICAgICAgICBpbnB1dFZhbHVlcy5wdXNoKHRlbnNvcik7XFxuICAgICAgICAgICAgfVxcbiAgICAgICAgICAgIGZpbmFsbHkge1xcbiAgICAgICAgICAgICAgICB3YXNtLnN0YWNrUmVzdG9yZShzdGFjayk7XFxuICAgICAgICAgICAgfVxcbiAgICAgICAgfVxcbiAgICAgICAgY29uc3QgYmVmb3JlUnVuU3RhY2sgPSB3YXNtLnN0YWNrU2F2ZSgpO1xcbiAgICAgICAgY29uc3QgaW5wdXRWYWx1ZXNPZmZzZXQgPSB3YXNtLnN0YWNrQWxsb2MoaW5wdXRDb3VudCAqIDQpO1xcbiAgICAgICAgY29uc3QgaW5wdXROYW1lc09mZnNldCA9IHdhc20uc3RhY2tBbGxvYyhpbnB1dENvdW50ICogNCk7XFxuICAgICAgICBjb25zdCBvdXRwdXRWYWx1ZXNPZmZzZXQgPSB3YXNtLnN0YWNrQWxsb2Mob3V0cHV0Q291bnQgKiA0KTtcXG4gICAgICAgIGNvbnN0IG91dHB1dE5hbWVzT2Zmc2V0ID0gd2FzbS5zdGFja0FsbG9jKG91dHB1dENvdW50ICogNCk7XFxuICAgICAgICB0cnkge1xcbiAgICAgICAgICAgIGxldCBpbnB1dFZhbHVlc0luZGV4ID0gaW5wdXRWYWx1ZXNPZmZzZXQgLyA0O1xcbiAgICAgICAgICAgIGxldCBpbnB1dE5hbWVzSW5kZXggPSBpbnB1dE5hbWVzT2Zmc2V0IC8gNDtcXG4gICAgICAgICAgICBsZXQgb3V0cHV0VmFsdWVzSW5kZXggPSBvdXRwdXRWYWx1ZXNPZmZzZXQgLyA0O1xcbiAgICAgICAgICAgIGxldCBvdXRwdXROYW1lc0luZGV4ID0gb3V0cHV0TmFtZXNPZmZzZXQgLyA0O1xcbiAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgaW5wdXRDb3VudDsgaSsrKSB7XFxuICAgICAgICAgICAgICAgIHdhc20uSEVBUFUzMltpbnB1dFZhbHVlc0luZGV4KytdID0gaW5wdXRWYWx1ZXNbaV07XFxuICAgICAgICAgICAgICAgIHdhc20uSEVBUFUzMltpbnB1dE5hbWVzSW5kZXgrK10gPSBpbnB1dE5hbWVzVVRGOEVuY29kZWRbaW5wdXRJbmRpY2VzW2ldXTtcXG4gICAgICAgICAgICB9XFxuICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBvdXRwdXRDb3VudDsgaSsrKSB7XFxuICAgICAgICAgICAgICAgIHdhc20uSEVBUFUzMltvdXRwdXRWYWx1ZXNJbmRleCsrXSA9IDA7XFxuICAgICAgICAgICAgICAgIHdhc20uSEVBUFUzMltvdXRwdXROYW1lc0luZGV4KytdID0gb3V0cHV0TmFtZXNVVEY4RW5jb2RlZFtvdXRwdXRJbmRpY2VzW2ldXTtcXG4gICAgICAgICAgICB9XFxuICAgICAgICAgICAgLy8gc3VwcG9ydCBSdW5PcHRpb25zXFxuICAgICAgICAgICAgbGV0IGVycm9yQ29kZSA9IHdhc20uX09ydFJ1bihzZXNzaW9uSGFuZGxlLCBpbnB1dE5hbWVzT2Zmc2V0LCBpbnB1dFZhbHVlc09mZnNldCwgaW5wdXRDb3VudCwgb3V0cHV0TmFtZXNPZmZzZXQsIG91dHB1dENvdW50LCBvdXRwdXRWYWx1ZXNPZmZzZXQsIHJ1bk9wdGlvbnNIYW5kbGUpO1xcbiAgICAgICAgICAgIGNvbnN0IG91dHB1dCA9IFtdO1xcbiAgICAgICAgICAgIGlmIChlcnJvckNvZGUgPT09IDApIHtcXG4gICAgICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBvdXRwdXRDb3VudDsgaSsrKSB7XFxuICAgICAgICAgICAgICAgICAgICBjb25zdCB0ZW5zb3IgPSB3YXNtLkhFQVBVMzJbb3V0cHV0VmFsdWVzT2Zmc2V0IC8gNCArIGldO1xcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgYmVmb3JlR2V0VGVuc29yRGF0YVN0YWNrID0gd2FzbS5zdGFja1NhdmUoKTtcXG4gICAgICAgICAgICAgICAgICAgIC8vIHN0YWNrIGFsbG9jYXRlIDQgcG9pbnRlciB2YWx1ZVxcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgdGVuc29yRGF0YU9mZnNldCA9IHdhc20uc3RhY2tBbGxvYyg0ICogNCk7XFxuICAgICAgICAgICAgICAgICAgICBsZXQgdHlwZSwgZGF0YU9mZnNldCA9IDA7XFxuICAgICAgICAgICAgICAgICAgICB0cnkge1xcbiAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yQ29kZSA9IHdhc20uX09ydEdldFRlbnNvckRhdGEodGVuc29yLCB0ZW5zb3JEYXRhT2Zmc2V0LCB0ZW5zb3JEYXRhT2Zmc2V0ICsgNCwgdGVuc29yRGF0YU9mZnNldCArIDgsIHRlbnNvckRhdGFPZmZzZXQgKyAxMik7XFxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGVycm9yQ29kZSAhPT0gMCkge1xcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYENhbid0IGFjY2VzcyBvdXRwdXQgdGVuc29yIGRhdGEuIGVycm9yIGNvZGUgPSAke2Vycm9yQ29kZX1gKTtcXG4gICAgICAgICAgICAgICAgICAgICAgICB9XFxuICAgICAgICAgICAgICAgICAgICAgICAgbGV0IHRlbnNvckRhdGFJbmRleCA9IHRlbnNvckRhdGFPZmZzZXQgLyA0O1xcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGRhdGFUeXBlID0gd2FzbS5IRUFQVTMyW3RlbnNvckRhdGFJbmRleCsrXTtcXG4gICAgICAgICAgICAgICAgICAgICAgICBkYXRhT2Zmc2V0ID0gd2FzbS5IRUFQVTMyW3RlbnNvckRhdGFJbmRleCsrXTtcXG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBkaW1zT2Zmc2V0ID0gd2FzbS5IRUFQVTMyW3RlbnNvckRhdGFJbmRleCsrXTtcXG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBkaW1zTGVuZ3RoID0gd2FzbS5IRUFQVTMyW3RlbnNvckRhdGFJbmRleCsrXTtcXG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBkaW1zID0gW107XFxuICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBkaW1zTGVuZ3RoOyBpKyspIHtcXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZGltcy5wdXNoKHdhc20uSEVBUFUzMltkaW1zT2Zmc2V0IC8gNCArIGldKTtcXG4gICAgICAgICAgICAgICAgICAgICAgICB9XFxuICAgICAgICAgICAgICAgICAgICAgICAgd2FzbS5fT3J0RnJlZShkaW1zT2Zmc2V0KTtcXG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBzaXplID0gZGltcy5sZW5ndGggPT09IDAgPyAxIDogZGltcy5yZWR1Y2UoKGEsIGIpID0+IGEgKiBiKTtcXG4gICAgICAgICAgICAgICAgICAgICAgICB0eXBlID0gdGVuc29yRGF0YVR5cGVFbnVtVG9TdHJpbmcoZGF0YVR5cGUpO1xcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0eXBlID09PSAnc3RyaW5nJykge1xcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBzdHJpbmdEYXRhID0gW107XFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldCBkYXRhSW5kZXggPSBkYXRhT2Zmc2V0IC8gNDtcXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBzaXplOyBpKyspIHtcXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IG9mZnNldCA9IHdhc20uSEVBUFUzMltkYXRhSW5kZXgrK107XFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBtYXhCeXRlc1RvUmVhZCA9IGkgPT09IHNpemUgLSAxID8gdW5kZWZpbmVkIDogd2FzbS5IRUFQVTMyW2RhdGFJbmRleF0gLSBvZmZzZXQ7XFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdHJpbmdEYXRhLnB1c2god2FzbS5VVEY4VG9TdHJpbmcob2Zmc2V0LCBtYXhCeXRlc1RvUmVhZCkpO1xcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG91dHB1dC5wdXNoKFt0eXBlLCBkaW1zLCBzdHJpbmdEYXRhXSk7XFxuICAgICAgICAgICAgICAgICAgICAgICAgfVxcbiAgICAgICAgICAgICAgICAgICAgICAgIGVsc2Uge1xcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCB0eXBlZEFycmF5Q29uc3RydWN0b3IgPSBudW1lcmljVGVuc29yVHlwZVRvVHlwZWRBcnJheSh0eXBlKTtcXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgZGF0YSA9IG5ldyB0eXBlZEFycmF5Q29uc3RydWN0b3Ioc2l6ZSk7XFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ldyBVaW50OEFycmF5KGRhdGEuYnVmZmVyLCBkYXRhLmJ5dGVPZmZzZXQsIGRhdGEuYnl0ZUxlbmd0aClcXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC5zZXQod2FzbS5IRUFQVTguc3ViYXJyYXkoZGF0YU9mZnNldCwgZGF0YU9mZnNldCArIGRhdGEuYnl0ZUxlbmd0aCkpO1xcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvdXRwdXQucHVzaChbdHlwZSwgZGltcywgZGF0YV0pO1xcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cXG4gICAgICAgICAgICAgICAgICAgIH1cXG4gICAgICAgICAgICAgICAgICAgIGZpbmFsbHkge1xcbiAgICAgICAgICAgICAgICAgICAgICAgIHdhc20uc3RhY2tSZXN0b3JlKGJlZm9yZUdldFRlbnNvckRhdGFTdGFjayk7XFxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGUgPT09ICdzdHJpbmcnICYmIGRhdGFPZmZzZXQpIHtcXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgd2FzbS5fZnJlZShkYXRhT2Zmc2V0KTtcXG4gICAgICAgICAgICAgICAgICAgICAgICB9XFxuICAgICAgICAgICAgICAgICAgICAgICAgd2FzbS5fT3J0UmVsZWFzZVRlbnNvcih0ZW5zb3IpO1xcbiAgICAgICAgICAgICAgICAgICAgfVxcbiAgICAgICAgICAgICAgICB9XFxuICAgICAgICAgICAgfVxcbiAgICAgICAgICAgIGlmIChlcnJvckNvZGUgPT09IDApIHtcXG4gICAgICAgICAgICAgICAgcmV0dXJuIG91dHB1dDtcXG4gICAgICAgICAgICB9XFxuICAgICAgICAgICAgZWxzZSB7XFxuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgZmFpbGVkIHRvIGNhbGwgT3J0UnVuKCkuIGVycm9yIGNvZGUgPSAke2Vycm9yQ29kZX0uYCk7XFxuICAgICAgICAgICAgfVxcbiAgICAgICAgfVxcbiAgICAgICAgZmluYWxseSB7XFxuICAgICAgICAgICAgd2FzbS5zdGFja1Jlc3RvcmUoYmVmb3JlUnVuU3RhY2spO1xcbiAgICAgICAgfVxcbiAgICB9XFxuICAgIGZpbmFsbHkge1xcbiAgICAgICAgaW5wdXRWYWx1ZXMuZm9yRWFjaCh3YXNtLl9PcnRSZWxlYXNlVGVuc29yKTtcXG4gICAgICAgIGlucHV0QWxsb2NzLmZvckVhY2god2FzbS5fZnJlZSk7XFxuICAgICAgICB3YXNtLl9PcnRSZWxlYXNlUnVuT3B0aW9ucyhydW5PcHRpb25zSGFuZGxlKTtcXG4gICAgICAgIHJ1bk9wdGlvbnNBbGxvY3MuZm9yRWFjaCh3YXNtLl9mcmVlKTtcXG4gICAgfVxcbn07XFxuZXhwb3J0cy5ydW4gPSBydW47XFxuLyoqXFxuICogZW5kIHByb2ZpbGluZ1xcbiAqL1xcbmNvbnN0IGVuZFByb2ZpbGluZyA9IChzZXNzaW9uSWQpID0+IHtcXG4gICAgY29uc3Qgd2FzbSA9ICgwLCB3YXNtX2ZhY3RvcnlfMS5nZXRJbnN0YW5jZSkoKTtcXG4gICAgY29uc3Qgc2Vzc2lvbiA9IGFjdGl2ZVNlc3Npb25zLmdldChzZXNzaW9uSWQpO1xcbiAgICBpZiAoIXNlc3Npb24pIHtcXG4gICAgICAgIHRocm93IG5ldyBFcnJvcignaW52YWxpZCBzZXNzaW9uIGlkJyk7XFxuICAgIH1cXG4gICAgY29uc3Qgc2Vzc2lvbkhhbmRsZSA9IHNlc3Npb25bMF07XFxuICAgIC8vIHByb2ZpbGUgZmlsZSBuYW1lIGlzIG5vdCB1c2VkIHlldCwgYnV0IGl0IG11c3QgYmUgZnJlZWQuXFxuICAgIGNvbnN0IHByb2ZpbGVGaWxlTmFtZSA9IHdhc20uX09ydEVuZFByb2ZpbGluZyhzZXNzaW9uSGFuZGxlKTtcXG4gICAgaWYgKHByb2ZpbGVGaWxlTmFtZSA9PT0gMCkge1xcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdDYW5cXFxcJ3QgZ2V0IGFuIHByb2ZpbGUgZmlsZSBuYW1lJyk7XFxuICAgIH1cXG4gICAgd2FzbS5fT3J0RnJlZShwcm9maWxlRmlsZU5hbWUpO1xcbn07XFxuZXhwb3J0cy5lbmRQcm9maWxpbmcgPSBlbmRQcm9maWxpbmc7XFxuY29uc3QgZXh0cmFjdFRyYW5zZmVyYWJsZUJ1ZmZlcnMgPSAodGVuc29ycykgPT4ge1xcbiAgICBjb25zdCBidWZmZXJzID0gW107XFxuICAgIGZvciAoY29uc3QgdGVuc29yIG9mIHRlbnNvcnMpIHtcXG4gICAgICAgIGNvbnN0IGRhdGEgPSB0ZW5zb3JbMl07XFxuICAgICAgICBpZiAoIUFycmF5LmlzQXJyYXkoZGF0YSkgJiYgZGF0YS5idWZmZXIpIHtcXG4gICAgICAgICAgICBidWZmZXJzLnB1c2goZGF0YS5idWZmZXIpO1xcbiAgICAgICAgfVxcbiAgICB9XFxuICAgIHJldHVybiBidWZmZXJzO1xcbn07XFxuZXhwb3J0cy5leHRyYWN0VHJhbnNmZXJhYmxlQnVmZmVycyA9IGV4dHJhY3RUcmFuc2ZlcmFibGVCdWZmZXJzO1xcblxcblxcbi8qKiovIH0pLFxcblxcbi8qKiovIFxcXCIuL2xpYi93YXNtL3dhc20tZmFjdG9yeS50c1xcXCI6XFxuLyohKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiEqXFxcXFxcbiAgISoqKiAuL2xpYi93YXNtL3dhc20tZmFjdG9yeS50cyAqKiohXFxuICBcXFxcKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKi9cXG4vKioqLyAoZnVuY3Rpb24oX191bnVzZWRfd2VicGFja19tb2R1bGUsIGV4cG9ydHMsIF9fd2VicGFja19yZXF1aXJlX18pIHtcXG5cXG5cXFwidXNlIHN0cmljdFxcXCI7XFxudmFyIF9fZGlybmFtZSA9IFxcXCIvXFxcIjtcXG5cXG4vLyBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXFxudmFyIF9fY3JlYXRlQmluZGluZyA9ICh0aGlzICYmIHRoaXMuX19jcmVhdGVCaW5kaW5nKSB8fCAoT2JqZWN0LmNyZWF0ZSA/IChmdW5jdGlvbihvLCBtLCBrLCBrMikge1xcbiAgICBpZiAoazIgPT09IHVuZGVmaW5lZCkgazIgPSBrO1xcbiAgICB2YXIgZGVzYyA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IobSwgayk7XFxuICAgIGlmICghZGVzYyB8fCAoXFxcImdldFxcXCIgaW4gZGVzYyA/ICFtLl9fZXNNb2R1bGUgOiBkZXNjLndyaXRhYmxlIHx8IGRlc2MuY29uZmlndXJhYmxlKSkge1xcbiAgICAgIGRlc2MgPSB7IGVudW1lcmFibGU6IHRydWUsIGdldDogZnVuY3Rpb24oKSB7IHJldHVybiBtW2tdOyB9IH07XFxuICAgIH1cXG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KG8sIGsyLCBkZXNjKTtcXG59KSA6IChmdW5jdGlvbihvLCBtLCBrLCBrMikge1xcbiAgICBpZiAoazIgPT09IHVuZGVmaW5lZCkgazIgPSBrO1xcbiAgICBvW2syXSA9IG1ba107XFxufSkpO1xcbnZhciBfX3NldE1vZHVsZURlZmF1bHQgPSAodGhpcyAmJiB0aGlzLl9fc2V0TW9kdWxlRGVmYXVsdCkgfHwgKE9iamVjdC5jcmVhdGUgPyAoZnVuY3Rpb24obywgdikge1xcbiAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkobywgXFxcImRlZmF1bHRcXFwiLCB7IGVudW1lcmFibGU6IHRydWUsIHZhbHVlOiB2IH0pO1xcbn0pIDogZnVuY3Rpb24obywgdikge1xcbiAgICBvW1xcXCJkZWZhdWx0XFxcIl0gPSB2O1xcbn0pO1xcbnZhciBfX2ltcG9ydFN0YXIgPSAodGhpcyAmJiB0aGlzLl9faW1wb3J0U3RhcikgfHwgZnVuY3Rpb24gKG1vZCkge1xcbiAgICBpZiAobW9kICYmIG1vZC5fX2VzTW9kdWxlKSByZXR1cm4gbW9kO1xcbiAgICB2YXIgcmVzdWx0ID0ge307XFxuICAgIGlmIChtb2QgIT0gbnVsbCkgZm9yICh2YXIgayBpbiBtb2QpIGlmIChrICE9PSBcXFwiZGVmYXVsdFxcXCIgJiYgT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKG1vZCwgaykpIF9fY3JlYXRlQmluZGluZyhyZXN1bHQsIG1vZCwgayk7XFxuICAgIF9fc2V0TW9kdWxlRGVmYXVsdChyZXN1bHQsIG1vZCk7XFxuICAgIHJldHVybiByZXN1bHQ7XFxufTtcXG52YXIgX19pbXBvcnREZWZhdWx0ID0gKHRoaXMgJiYgdGhpcy5fX2ltcG9ydERlZmF1bHQpIHx8IGZ1bmN0aW9uIChtb2QpIHtcXG4gICAgcmV0dXJuIChtb2QgJiYgbW9kLl9fZXNNb2R1bGUpID8gbW9kIDogeyBcXFwiZGVmYXVsdFxcXCI6IG1vZCB9O1xcbn07XFxuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFxcXCJfX2VzTW9kdWxlXFxcIiwgKHsgdmFsdWU6IHRydWUgfSkpO1xcbmV4cG9ydHMuZGlzcG9zZSA9IGV4cG9ydHMuZ2V0SW5zdGFuY2UgPSBleHBvcnRzLmluaXRpYWxpemVXZWJBc3NlbWJseSA9IHZvaWQgMDtcXG5jb25zdCBwYXRoID0gX19pbXBvcnRTdGFyKF9fd2VicGFja19yZXF1aXJlX18oLyohIHBhdGggKi8gXFxcIj83YWE1XFxcIikpO1xcbmNvbnN0IG9ydF93YXNtX2pzXzEgPSBfX2ltcG9ydERlZmF1bHQoX193ZWJwYWNrX3JlcXVpcmVfXygvKiEgLi9iaW5kaW5nL29ydC13YXNtLmpzICovIFxcXCIuL2xpYi93YXNtL2JpbmRpbmcvb3J0LXdhc20uanNcXFwiKSk7XFxuY29uc3Qgb3J0V2FzbUZhY3RvcnlUaHJlYWRlZCA9IFxcbi8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tcmVxdWlyZS1pbXBvcnRzXFxuIHRydWUgPyBfX3dlYnBhY2tfcmVxdWlyZV9fKC8qISAuL2JpbmRpbmcvb3J0LXdhc20tdGhyZWFkZWQuanMgKi8gXFxcIi4vbGliL3dhc20vYmluZGluZy9vcnQtd2FzbS10aHJlYWRlZC5qc1xcXCIpIDogMDtcXG5sZXQgd2FzbTtcXG5sZXQgaW5pdGlhbGl6ZWQgPSBmYWxzZTtcXG5sZXQgaW5pdGlhbGl6aW5nID0gZmFsc2U7XFxubGV0IGFib3J0ZWQgPSBmYWxzZTtcXG5jb25zdCBpc011bHRpVGhyZWFkU3VwcG9ydGVkID0gKCkgPT4ge1xcbiAgICB0cnkge1xcbiAgICAgICAgLy8gSWYgJ1NoYXJlZEFycmF5QnVmZmVyJyBpcyBub3QgYXZhaWxhYmxlLCBXZWJBc3NlbWJseSB0aHJlYWRzIHdpbGwgbm90IHdvcmsuXFxuICAgICAgICBpZiAodHlwZW9mIFNoYXJlZEFycmF5QnVmZmVyID09PSAndW5kZWZpbmVkJykge1xcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcXG4gICAgICAgIH1cXG4gICAgICAgIC8vIFRlc3QgZm9yIHRyYW5zZmVyYWJpbGl0eSBvZiBTQUJzIChmb3IgYnJvd3NlcnMuIG5lZWRlZCBmb3IgRmlyZWZveClcXG4gICAgICAgIC8vIGh0dHBzOi8vZ3JvdXBzLmdvb2dsZS5jb20vZm9ydW0vIyFtc2cvbW96aWxsYS5kZXYucGxhdGZvcm0vSUhrQlpsSEVUcEEvZHdzTU5jaFdFUUFKXFxuICAgICAgICBpZiAodHlwZW9mIE1lc3NhZ2VDaGFubmVsICE9PSAndW5kZWZpbmVkJykge1xcbiAgICAgICAgICAgIG5ldyBNZXNzYWdlQ2hhbm5lbCgpLnBvcnQxLnBvc3RNZXNzYWdlKG5ldyBTaGFyZWRBcnJheUJ1ZmZlcigxKSk7XFxuICAgICAgICB9XFxuICAgICAgICAvLyBUZXN0IGZvciBXZWJBc3NlbWJseSB0aHJlYWRzIGNhcGFiaWxpdHkgKGZvciBib3RoIGJyb3dzZXJzIGFuZCBOb2RlLmpzKVxcbiAgICAgICAgLy8gVGhpcyB0eXBlZCBhcnJheSBpcyBhIFdlYkFzc2VtYmx5IHByb2dyYW0gY29udGFpbmluZyB0aHJlYWRlZCBpbnN0cnVjdGlvbnMuXFxuICAgICAgICByZXR1cm4gV2ViQXNzZW1ibHkudmFsaWRhdGUobmV3IFVpbnQ4QXJyYXkoW1xcbiAgICAgICAgICAgIDAsIDk3LCAxMTUsIDEwOSwgMSwgMCwgMCwgMCwgMSwgNCwgMSwgOTYsIDAsIDAsIDMsIDIsIDEsIDAsIDUsXFxuICAgICAgICAgICAgNCwgMSwgMywgMSwgMSwgMTAsIDExLCAxLCA5LCAwLCA2NSwgMCwgMjU0LCAxNiwgMiwgMCwgMjYsIDExXFxuICAgICAgICBdKSk7XFxuICAgIH1cXG4gICAgY2F0Y2ggKGUpIHtcXG4gICAgICAgIHJldHVybiBmYWxzZTtcXG4gICAgfVxcbn07XFxuY29uc3QgaXNTaW1kU3VwcG9ydGVkID0gKCkgPT4ge1xcbiAgICB0cnkge1xcbiAgICAgICAgLy8gVGVzdCBmb3IgV2ViQXNzZW1ibHkgU0lNRCBjYXBhYmlsaXR5IChmb3IgYm90aCBicm93c2VycyBhbmQgTm9kZS5qcylcXG4gICAgICAgIC8vIFRoaXMgdHlwZWQgYXJyYXkgaXMgYSBXZWJBc3NlbWJseSBwcm9ncmFtIGNvbnRhaW5pbmcgU0lNRCBpbnN0cnVjdGlvbnMuXFxuICAgICAgICAvLyBUaGUgYmluYXJ5IGRhdGEgaXMgZ2VuZXJhdGVkIGZyb20gdGhlIGZvbGxvd2luZyBjb2RlIGJ5IHdhdDJ3YXNtOlxcbiAgICAgICAgLy9cXG4gICAgICAgIC8vIChtb2R1bGVcXG4gICAgICAgIC8vICAgKHR5cGUgJHQwIChmdW5jKSlcXG4gICAgICAgIC8vICAgKGZ1bmMgJGYwICh0eXBlICR0MClcXG4gICAgICAgIC8vICAgICAoZHJvcFxcbiAgICAgICAgLy8gICAgICAgKGkzMng0LmRvdF9pMTZ4OF9zXFxuICAgICAgICAvLyAgICAgICAgIChpOHgxNi5zcGxhdFxcbiAgICAgICAgLy8gICAgICAgICAgIChpMzIuY29uc3QgMCkpXFxuICAgICAgICAvLyAgICAgICAgICh2MTI4LmNvbnN0IGkzMng0IDB4MDAwMDAwMDAgMHgwMDAwMDAwMCAweDAwMDAwMDAwIDB4MDAwMDAwMDApKSkpKVxcbiAgICAgICAgcmV0dXJuIFdlYkFzc2VtYmx5LnZhbGlkYXRlKG5ldyBVaW50OEFycmF5KFtcXG4gICAgICAgICAgICAwLCA5NywgMTE1LCAxMDksIDEsIDAsIDAsIDAsIDEsIDQsIDEsIDk2LCAwLCAwLCAzLCAyLCAxLCAwLCAxMCwgMzAsIDEsIDI4LCAwLCA2NSwgMCxcXG4gICAgICAgICAgICAyNTMsIDE1LCAyNTMsIDEyLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAyNTMsIDE4NiwgMSwgMjYsIDExXFxuICAgICAgICBdKSk7XFxuICAgIH1cXG4gICAgY2F0Y2ggKGUpIHtcXG4gICAgICAgIHJldHVybiBmYWxzZTtcXG4gICAgfVxcbn07XFxuY29uc3QgZ2V0V2FzbUZpbGVOYW1lID0gKHVzZVNpbWQsIHVzZVRocmVhZHMpID0+IHtcXG4gICAgaWYgKHVzZVRocmVhZHMpIHtcXG4gICAgICAgIHJldHVybiB1c2VTaW1kID8gJ29ydC13YXNtLXNpbWQtdGhyZWFkZWQud2FzbScgOiAnb3J0LXdhc20tdGhyZWFkZWQud2FzbSc7XFxuICAgIH1cXG4gICAgZWxzZSB7XFxuICAgICAgICByZXR1cm4gdXNlU2ltZCA/ICdvcnQtd2FzbS1zaW1kLndhc20nIDogJ29ydC13YXNtLndhc20nO1xcbiAgICB9XFxufTtcXG5jb25zdCBpbml0aWFsaXplV2ViQXNzZW1ibHkgPSBhc3luYyAoZmxhZ3MpID0+IHtcXG4gICAgaWYgKGluaXRpYWxpemVkKSB7XFxuICAgICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XFxuICAgIH1cXG4gICAgaWYgKGluaXRpYWxpemluZykge1xcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdtdWx0aXBsZSBjYWxscyB0byBcXFxcJ2luaXRpYWxpemVXZWJBc3NlbWJseSgpXFxcXCcgZGV0ZWN0ZWQuJyk7XFxuICAgIH1cXG4gICAgaWYgKGFib3J0ZWQpIHtcXG4gICAgICAgIHRocm93IG5ldyBFcnJvcigncHJldmlvdXMgY2FsbCB0byBcXFxcJ2luaXRpYWxpemVXZWJBc3NlbWJseSgpXFxcXCcgZmFpbGVkLicpO1xcbiAgICB9XFxuICAgIGluaXRpYWxpemluZyA9IHRydWU7XFxuICAgIC8vIHdhc20gZmxhZ3MgYXJlIGFscmVhZHkgaW5pdGlhbGl6ZWRcXG4gICAgY29uc3QgdGltZW91dCA9IGZsYWdzLmluaXRUaW1lb3V0O1xcbiAgICBjb25zdCBudW1UaHJlYWRzID0gZmxhZ3MubnVtVGhyZWFkcztcXG4gICAgY29uc3Qgc2ltZCA9IGZsYWdzLnNpbWQ7XFxuICAgIGNvbnN0IHVzZVRocmVhZHMgPSBudW1UaHJlYWRzID4gMSAmJiBpc011bHRpVGhyZWFkU3VwcG9ydGVkKCk7XFxuICAgIGNvbnN0IHVzZVNpbWQgPSBzaW1kICYmIGlzU2ltZFN1cHBvcnRlZCgpO1xcbiAgICBjb25zdCB3YXNtUHJlZml4T3ZlcnJpZGUgPSB0eXBlb2YgZmxhZ3Mud2FzbVBhdGhzID09PSAnc3RyaW5nJyA/IGZsYWdzLndhc21QYXRocyA6IHVuZGVmaW5lZDtcXG4gICAgY29uc3Qgd2FzbUZpbGVOYW1lID0gZ2V0V2FzbUZpbGVOYW1lKGZhbHNlLCB1c2VUaHJlYWRzKTtcXG4gICAgY29uc3Qgd2FzbU92ZXJyaWRlRmlsZU5hbWUgPSBnZXRXYXNtRmlsZU5hbWUodXNlU2ltZCwgdXNlVGhyZWFkcyk7XFxuICAgIGNvbnN0IHdhc21QYXRoT3ZlcnJpZGUgPSB0eXBlb2YgZmxhZ3Mud2FzbVBhdGhzID09PSAnb2JqZWN0JyA/IGZsYWdzLndhc21QYXRoc1t3YXNtT3ZlcnJpZGVGaWxlTmFtZV0gOiB1bmRlZmluZWQ7XFxuICAgIGxldCBpc1RpbWVvdXQgPSBmYWxzZTtcXG4gICAgY29uc3QgdGFza3MgPSBbXTtcXG4gICAgLy8gcHJvbWlzZSBmb3IgdGltZW91dFxcbiAgICBpZiAodGltZW91dCA+IDApIHtcXG4gICAgICAgIHRhc2tzLnB1c2gobmV3IFByb21pc2UoKHJlc29sdmUpID0+IHtcXG4gICAgICAgICAgICBzZXRUaW1lb3V0KCgpID0+IHtcXG4gICAgICAgICAgICAgICAgaXNUaW1lb3V0ID0gdHJ1ZTtcXG4gICAgICAgICAgICAgICAgcmVzb2x2ZSgpO1xcbiAgICAgICAgICAgIH0sIHRpbWVvdXQpO1xcbiAgICAgICAgfSkpO1xcbiAgICB9XFxuICAgIC8vIHByb21pc2UgZm9yIG1vZHVsZSBpbml0aWFsaXphdGlvblxcbiAgICB0YXNrcy5wdXNoKG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcXG4gICAgICAgIGNvbnN0IGZhY3RvcnkgPSB1c2VUaHJlYWRzID8gb3J0V2FzbUZhY3RvcnlUaHJlYWRlZCA6IG9ydF93YXNtX2pzXzEuZGVmYXVsdDtcXG4gICAgICAgIGNvbnN0IGNvbmZpZyA9IHtcXG4gICAgICAgICAgICBsb2NhdGVGaWxlOiAoZmlsZU5hbWUsIHNjcmlwdERpcmVjdG9yeSkgPT4ge1xcbiAgICAgICAgICAgICAgICBpZiAoIHRydWUgJiYgdXNlVGhyZWFkcyAmJiBmaWxlTmFtZS5lbmRzV2l0aCgnLndvcmtlci5qcycpICYmXFxuICAgICAgICAgICAgICAgICAgICB0eXBlb2YgQmxvYiAhPT0gJ3VuZGVmaW5lZCcpIHtcXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBVUkwuY3JlYXRlT2JqZWN0VVJMKG5ldyBCbG9iKFtcXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBUaGlzIHJlcXVpcmUoKSBmdW5jdGlvbiBpcyBoYW5kbGVkIGJ5IHdlYnBhY2sgdG8gbG9hZCBmaWxlIGNvbnRlbnQgb2YgdGhlIGNvcnJlc3BvbmRpbmcgLndvcmtlci5qc1xcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tcmVxdWlyZS1pbXBvcnRzXFxuICAgICAgICAgICAgICAgICAgICAgICAgX193ZWJwYWNrX3JlcXVpcmVfXygvKiEgLi9iaW5kaW5nL29ydC13YXNtLXRocmVhZGVkLndvcmtlci5qcyAqLyBcXFwiLi9saWIvd2FzbS9iaW5kaW5nL29ydC13YXNtLXRocmVhZGVkLndvcmtlci5qc1xcXCIpXFxuICAgICAgICAgICAgICAgICAgICBdLCB7IHR5cGU6ICd0ZXh0L2phdmFzY3JpcHQnIH0pKTtcXG4gICAgICAgICAgICAgICAgfVxcbiAgICAgICAgICAgICAgICBpZiAoZmlsZU5hbWUgPT09IHdhc21GaWxlTmFtZSkge1xcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgcHJlZml4ID0gd2FzbVByZWZpeE92ZXJyaWRlICE9PSBudWxsICYmIHdhc21QcmVmaXhPdmVycmlkZSAhPT0gdm9pZCAwID8gd2FzbVByZWZpeE92ZXJyaWRlIDogc2NyaXB0RGlyZWN0b3J5O1xcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHdhc21QYXRoT3ZlcnJpZGUgIT09IG51bGwgJiYgd2FzbVBhdGhPdmVycmlkZSAhPT0gdm9pZCAwID8gd2FzbVBhdGhPdmVycmlkZSA6IHByZWZpeCArIHdhc21PdmVycmlkZUZpbGVOYW1lO1xcbiAgICAgICAgICAgICAgICB9XFxuICAgICAgICAgICAgICAgIHJldHVybiBzY3JpcHREaXJlY3RvcnkgKyBmaWxlTmFtZTtcXG4gICAgICAgICAgICB9XFxuICAgICAgICB9O1xcbiAgICAgICAgaWYgKCB0cnVlICYmIHVzZVRocmVhZHMpIHtcXG4gICAgICAgICAgICBpZiAodHlwZW9mIEJsb2IgPT09ICd1bmRlZmluZWQnKSB7XFxuICAgICAgICAgICAgICAgIGNvbmZpZy5tYWluU2NyaXB0VXJsT3JCbG9iID0gcGF0aC5qb2luKF9fZGlybmFtZSwgJ29ydC13YXNtLXRocmVhZGVkLmpzJyk7XFxuICAgICAgICAgICAgfVxcbiAgICAgICAgICAgIGVsc2Uge1xcbiAgICAgICAgICAgICAgICBjb25zdCBzY3JpcHRTb3VyY2VDb2RlID0gYHZhciBvcnRXYXNtVGhyZWFkZWQ9KGZ1bmN0aW9uKCl7dmFyIF9zY3JpcHREaXI7cmV0dXJuICR7ZmFjdG9yeS50b1N0cmluZygpfX0pKCk7YDtcXG4gICAgICAgICAgICAgICAgY29uZmlnLm1haW5TY3JpcHRVcmxPckJsb2IgPSBuZXcgQmxvYihbc2NyaXB0U291cmNlQ29kZV0sIHsgdHlwZTogJ3RleHQvamF2YXNjcmlwdCcgfSk7XFxuICAgICAgICAgICAgfVxcbiAgICAgICAgfVxcbiAgICAgICAgZmFjdG9yeShjb25maWcpLnRoZW4oXFxuICAgICAgICAvLyB3YXNtIG1vZHVsZSBpbml0aWFsaXplZCBzdWNjZXNzZnVsbHlcXG4gICAgICAgIG1vZHVsZSA9PiB7XFxuICAgICAgICAgICAgaW5pdGlhbGl6aW5nID0gZmFsc2U7XFxuICAgICAgICAgICAgaW5pdGlhbGl6ZWQgPSB0cnVlO1xcbiAgICAgICAgICAgIHdhc20gPSBtb2R1bGU7XFxuICAgICAgICAgICAgcmVzb2x2ZSgpO1xcbiAgICAgICAgfSwgXFxuICAgICAgICAvLyB3YXNtIG1vZHVsZSBmYWlsZWQgdG8gaW5pdGlhbGl6ZVxcbiAgICAgICAgKHdoYXQpID0+IHtcXG4gICAgICAgICAgICBpbml0aWFsaXppbmcgPSBmYWxzZTtcXG4gICAgICAgICAgICBhYm9ydGVkID0gdHJ1ZTtcXG4gICAgICAgICAgICByZWplY3Qod2hhdCk7XFxuICAgICAgICB9KTtcXG4gICAgfSkpO1xcbiAgICBhd2FpdCBQcm9taXNlLnJhY2UodGFza3MpO1xcbiAgICBpZiAoaXNUaW1lb3V0KSB7XFxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYFdlYkFzc2VtYmx5IGJhY2tlbmQgaW5pdGlhbGl6aW5nIGZhaWxlZCBkdWUgdG8gdGltZW91dDogJHt0aW1lb3V0fW1zYCk7XFxuICAgIH1cXG59O1xcbmV4cG9ydHMuaW5pdGlhbGl6ZVdlYkFzc2VtYmx5ID0gaW5pdGlhbGl6ZVdlYkFzc2VtYmx5O1xcbmNvbnN0IGdldEluc3RhbmNlID0gKCkgPT4ge1xcbiAgICBpZiAoaW5pdGlhbGl6ZWQgJiYgd2FzbSkge1xcbiAgICAgICAgcmV0dXJuIHdhc207XFxuICAgIH1cXG4gICAgdGhyb3cgbmV3IEVycm9yKCdXZWJBc3NlbWJseSBpcyBub3QgaW5pdGlhbGl6ZWQgeWV0LicpO1xcbn07XFxuZXhwb3J0cy5nZXRJbnN0YW5jZSA9IGdldEluc3RhbmNlO1xcbmNvbnN0IGRpc3Bvc2UgPSAoKSA9PiB7XFxuICAgIHZhciBfYTtcXG4gICAgaWYgKGluaXRpYWxpemVkICYmICFpbml0aWFsaXppbmcgJiYgIWFib3J0ZWQpIHtcXG4gICAgICAgIGluaXRpYWxpemluZyA9IHRydWU7XFxuICAgICAgICAoX2EgPSB3YXNtLlBUaHJlYWQpID09PSBudWxsIHx8IF9hID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfYS50ZXJtaW5hdGVBbGxUaHJlYWRzKCk7XFxuICAgICAgICB3YXNtID0gdW5kZWZpbmVkO1xcbiAgICAgICAgaW5pdGlhbGl6aW5nID0gZmFsc2U7XFxuICAgICAgICBpbml0aWFsaXplZCA9IGZhbHNlO1xcbiAgICAgICAgYWJvcnRlZCA9IHRydWU7XFxuICAgIH1cXG59O1xcbmV4cG9ydHMuZGlzcG9zZSA9IGRpc3Bvc2U7XFxuXFxuXFxuLyoqKi8gfSksXFxuXFxuLyoqKi8gXFxcIi4vbGliL3dhc20vYmluZGluZy9vcnQtd2FzbS10aHJlYWRlZC53b3JrZXIuanNcXFwiOlxcbi8qISoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiEqXFxcXFxcbiAgISoqKiAuL2xpYi93YXNtL2JpbmRpbmcvb3J0LXdhc20tdGhyZWFkZWQud29ya2VyLmpzICoqKiFcXG4gIFxcXFwqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiovXFxuLyoqKi8gKChtb2R1bGUpID0+IHtcXG5cXG5cXFwidXNlIHN0cmljdFxcXCI7XFxubW9kdWxlLmV4cG9ydHMgPSBcXFwiXFxcXFxcXCJ1c2Ugc3RyaWN0XFxcXFxcXCI7dmFyIE1vZHVsZT17fTt2YXIgRU5WSVJPTk1FTlRfSVNfTk9ERT10eXBlb2YgcHJvY2Vzcz09XFxcXFxcXCJvYmplY3RcXFxcXFxcIiYmdHlwZW9mIHByb2Nlc3MudmVyc2lvbnM9PVxcXFxcXFwib2JqZWN0XFxcXFxcXCImJnR5cGVvZiBwcm9jZXNzLnZlcnNpb25zLm5vZGU9PVxcXFxcXFwic3RyaW5nXFxcXFxcXCI7aWYoRU5WSVJPTk1FTlRfSVNfTk9ERSl7dmFyIG5vZGVXb3JrZXJUaHJlYWRzPXJlcXVpcmUoXFxcXFxcXCJ3b3JrZXJfdGhyZWFkc1xcXFxcXFwiKTt2YXIgcGFyZW50UG9ydD1ub2RlV29ya2VyVGhyZWFkcy5wYXJlbnRQb3J0O3BhcmVudFBvcnQub24oXFxcXFxcXCJtZXNzYWdlXFxcXFxcXCIsZGF0YT0+b25tZXNzYWdlKHtkYXRhOmRhdGF9KSk7dmFyIGZzPXJlcXVpcmUoXFxcXFxcXCJmc1xcXFxcXFwiKTtPYmplY3QuYXNzaWduKGdsb2JhbCx7c2VsZjpnbG9iYWwscmVxdWlyZTpyZXF1aXJlLE1vZHVsZTpNb2R1bGUsbG9jYXRpb246e2hyZWY6X19maWxlbmFtZX0sV29ya2VyOm5vZGVXb3JrZXJUaHJlYWRzLldvcmtlcixpbXBvcnRTY3JpcHRzOmZ1bmN0aW9uKGYpeygwLGV2YWwpKGZzLnJlYWRGaWxlU3luYyhmLFxcXFxcXFwidXRmOFxcXFxcXFwiKSl9LHBvc3RNZXNzYWdlOmZ1bmN0aW9uKG1zZyl7cGFyZW50UG9ydC5wb3N0TWVzc2FnZShtc2cpfSxwZXJmb3JtYW5jZTpnbG9iYWwucGVyZm9ybWFuY2V8fHtub3c6ZnVuY3Rpb24oKXtyZXR1cm4gRGF0ZS5ub3coKX19fSl9dmFyIGluaXRpYWxpemVkSlM9ZmFsc2U7dmFyIHBlbmRpbmdOb3RpZmllZFByb3h5aW5nUXVldWVzPVtdO2Z1bmN0aW9uIHRocmVhZFByaW50RXJyKCl7dmFyIHRleHQ9QXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoYXJndW1lbnRzKS5qb2luKFxcXFxcXFwiIFxcXFxcXFwiKTtpZihFTlZJUk9OTUVOVF9JU19OT0RFKXtmcy53cml0ZVN5bmMoMix0ZXh0K1xcXFxcXFwiXFxcXFxcXFxuXFxcXFxcXCIpO3JldHVybn1jb25zb2xlLmVycm9yKHRleHQpfWZ1bmN0aW9uIHRocmVhZEFsZXJ0KCl7dmFyIHRleHQ9QXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoYXJndW1lbnRzKS5qb2luKFxcXFxcXFwiIFxcXFxcXFwiKTtwb3N0TWVzc2FnZSh7Y21kOlxcXFxcXFwiYWxlcnRcXFxcXFxcIix0ZXh0OnRleHQsdGhyZWFkSWQ6TW9kdWxlW1xcXFxcXFwiX3B0aHJlYWRfc2VsZlxcXFxcXFwiXSgpfSl9dmFyIGVycj10aHJlYWRQcmludEVycjtzZWxmLmFsZXJ0PXRocmVhZEFsZXJ0O01vZHVsZVtcXFxcXFxcImluc3RhbnRpYXRlV2FzbVxcXFxcXFwiXT0oaW5mbyxyZWNlaXZlSW5zdGFuY2UpPT57dmFyIGluc3RhbmNlPW5ldyBXZWJBc3NlbWJseS5JbnN0YW5jZShNb2R1bGVbXFxcXFxcXCJ3YXNtTW9kdWxlXFxcXFxcXCJdLGluZm8pO3JlY2VpdmVJbnN0YW5jZShpbnN0YW5jZSk7TW9kdWxlW1xcXFxcXFwid2FzbU1vZHVsZVxcXFxcXFwiXT1udWxsO3JldHVybiBpbnN0YW5jZS5leHBvcnRzfTtzZWxmLm9udW5oYW5kbGVkcmVqZWN0aW9uPWU9Pnt0aHJvdyBlLnJlYXNvbj8/ZX07c2VsZi5vbm1lc3NhZ2U9ZT0+e3RyeXtpZihlLmRhdGEuY21kPT09XFxcXFxcXCJsb2FkXFxcXFxcXCIpe01vZHVsZVtcXFxcXFxcIndhc21Nb2R1bGVcXFxcXFxcIl09ZS5kYXRhLndhc21Nb2R1bGU7TW9kdWxlW1xcXFxcXFwid2FzbU1lbW9yeVxcXFxcXFwiXT1lLmRhdGEud2FzbU1lbW9yeTtNb2R1bGVbXFxcXFxcXCJidWZmZXJcXFxcXFxcIl09TW9kdWxlW1xcXFxcXFwid2FzbU1lbW9yeVxcXFxcXFwiXS5idWZmZXI7TW9kdWxlW1xcXFxcXFwiRU5WSVJPTk1FTlRfSVNfUFRIUkVBRFxcXFxcXFwiXT10cnVlO2lmKHR5cGVvZiBlLmRhdGEudXJsT3JCbG9iPT1cXFxcXFxcInN0cmluZ1xcXFxcXFwiKXtpbXBvcnRTY3JpcHRzKGUuZGF0YS51cmxPckJsb2IpfWVsc2V7dmFyIG9iamVjdFVybD1VUkwuY3JlYXRlT2JqZWN0VVJMKGUuZGF0YS51cmxPckJsb2IpO2ltcG9ydFNjcmlwdHMob2JqZWN0VXJsKTtVUkwucmV2b2tlT2JqZWN0VVJMKG9iamVjdFVybCl9b3J0V2FzbVRocmVhZGVkKE1vZHVsZSkudGhlbihmdW5jdGlvbihpbnN0YW5jZSl7TW9kdWxlPWluc3RhbmNlfSl9ZWxzZSBpZihlLmRhdGEuY21kPT09XFxcXFxcXCJydW5cXFxcXFxcIil7TW9kdWxlW1xcXFxcXFwiX19wZXJmb3JtYW5jZV9ub3dfY2xvY2tfZHJpZnRcXFxcXFxcIl09cGVyZm9ybWFuY2Uubm93KCktZS5kYXRhLnRpbWU7TW9kdWxlW1xcXFxcXFwiX19lbXNjcmlwdGVuX3RocmVhZF9pbml0XFxcXFxcXCJdKGUuZGF0YS5wdGhyZWFkX3B0ciwvKmlzTWFpbkJyb3dzZXJUaHJlYWQ9Ki8wLC8qaXNNYWluUnVudGltZVRocmVhZD0qLzAsLypjYW5CbG9jaz0qLzEpO01vZHVsZVtcXFxcXFxcImVzdGFibGlzaFN0YWNrU3BhY2VcXFxcXFxcIl0oKTtNb2R1bGVbXFxcXFxcXCJQVGhyZWFkXFxcXFxcXCJdLnJlY2VpdmVPYmplY3RUcmFuc2ZlcihlLmRhdGEpO01vZHVsZVtcXFxcXFxcIlBUaHJlYWRcXFxcXFxcIl0udGhyZWFkSW5pdFRMUygpO2lmKCFpbml0aWFsaXplZEpTKXtwZW5kaW5nTm90aWZpZWRQcm94eWluZ1F1ZXVlcy5mb3JFYWNoKHF1ZXVlPT57TW9kdWxlW1xcXFxcXFwiZXhlY3V0ZU5vdGlmaWVkUHJveHlpbmdRdWV1ZVxcXFxcXFwiXShxdWV1ZSl9KTtwZW5kaW5nTm90aWZpZWRQcm94eWluZ1F1ZXVlcz1bXTtpbml0aWFsaXplZEpTPXRydWV9dHJ5e01vZHVsZVtcXFxcXFxcImludm9rZUVudHJ5UG9pbnRcXFxcXFxcIl0oZS5kYXRhLnN0YXJ0X3JvdXRpbmUsZS5kYXRhLmFyZyl9Y2F0Y2goZXgpe2lmKGV4IT1cXFxcXFxcInVud2luZFxcXFxcXFwiKXtpZihleCBpbnN0YW5jZW9mIE1vZHVsZVtcXFxcXFxcIkV4aXRTdGF0dXNcXFxcXFxcIl0pe2lmKE1vZHVsZVtcXFxcXFxcImtlZXBSdW50aW1lQWxpdmVcXFxcXFxcIl0oKSl7fWVsc2V7TW9kdWxlW1xcXFxcXFwiX19lbXNjcmlwdGVuX3RocmVhZF9leGl0XFxcXFxcXCJdKGV4LnN0YXR1cyl9fWVsc2V7dGhyb3cgZXh9fX19ZWxzZSBpZihlLmRhdGEuY21kPT09XFxcXFxcXCJjYW5jZWxcXFxcXFxcIil7aWYoTW9kdWxlW1xcXFxcXFwiX3B0aHJlYWRfc2VsZlxcXFxcXFwiXSgpKXtNb2R1bGVbXFxcXFxcXCJfX2Vtc2NyaXB0ZW5fdGhyZWFkX2V4aXRcXFxcXFxcIl0oLTEpfX1lbHNlIGlmKGUuZGF0YS50YXJnZXQ9PT1cXFxcXFxcInNldGltbWVkaWF0ZVxcXFxcXFwiKXt9ZWxzZSBpZihlLmRhdGEuY21kPT09XFxcXFxcXCJwcm9jZXNzUHJveHlpbmdRdWV1ZVxcXFxcXFwiKXtpZihpbml0aWFsaXplZEpTKXtNb2R1bGVbXFxcXFxcXCJleGVjdXRlTm90aWZpZWRQcm94eWluZ1F1ZXVlXFxcXFxcXCJdKGUuZGF0YS5xdWV1ZSl9ZWxzZXtwZW5kaW5nTm90aWZpZWRQcm94eWluZ1F1ZXVlcy5wdXNoKGUuZGF0YS5xdWV1ZSl9fWVsc2V7ZXJyKFxcXFxcXFwid29ya2VyLmpzIHJlY2VpdmVkIHVua25vd24gY29tbWFuZCBcXFxcXFxcIitlLmRhdGEuY21kKTtlcnIoZS5kYXRhKX19Y2F0Y2goZXgpe2VycihcXFxcXFxcIndvcmtlci5qcyBvbm1lc3NhZ2UoKSBjYXB0dXJlZCBhbiB1bmNhdWdodCBleGNlcHRpb246IFxcXFxcXFwiK2V4KTtpZihleCYmZXguc3RhY2spZXJyKGV4LnN0YWNrKTtpZihNb2R1bGVbXFxcXFxcXCJfX2Vtc2NyaXB0ZW5fdGhyZWFkX2NyYXNoZWRcXFxcXFxcIl0pe01vZHVsZVtcXFxcXFxcIl9fZW1zY3JpcHRlbl90aHJlYWRfY3Jhc2hlZFxcXFxcXFwiXSgpfXRocm93IGV4fX07XFxcXHJcXFxcblxcXCI7XFxuXFxuLyoqKi8gfSksXFxuXFxuLyoqKi8gXFxcIj82M2M4XFxcIjpcXG4vKiEqKioqKioqKioqKioqKioqKioqKiEqXFxcXFxcbiAgISoqKiBmcyAoaWdub3JlZCkgKioqIVxcbiAgXFxcXCoqKioqKioqKioqKioqKioqKioqL1xcbi8qKiovICgoKSA9PiB7XFxuXFxuLyogKGlnbm9yZWQpICovXFxuXFxuLyoqKi8gfSksXFxuXFxuLyoqKi8gXFxcIj9hZWRiXFxcIjpcXG4vKiEqKioqKioqKioqKioqKioqKioqKiEqXFxcXFxcbiAgISoqKiBvcyAoaWdub3JlZCkgKioqIVxcbiAgXFxcXCoqKioqKioqKioqKioqKioqKioqL1xcbi8qKiovICgoKSA9PiB7XFxuXFxuLyogKGlnbm9yZWQpICovXFxuXFxuLyoqKi8gfSksXFxuXFxuLyoqKi8gXFxcIj83NWM2XFxcIjpcXG4vKiEqKioqKioqKioqKioqKioqKioqKioqISpcXFxcXFxuICAhKioqIHBhdGggKGlnbm9yZWQpICoqKiFcXG4gIFxcXFwqKioqKioqKioqKioqKioqKioqKioqL1xcbi8qKiovICgoKSA9PiB7XFxuXFxuLyogKGlnbm9yZWQpICovXFxuXFxuLyoqKi8gfSksXFxuXFxuLyoqKi8gXFxcIj82NzRmXFxcIjpcXG4vKiEqKioqKioqKioqKioqKioqKioqKioqKioqKioqISpcXFxcXFxuICAhKioqIHBlcmZfaG9va3MgKGlnbm9yZWQpICoqKiFcXG4gIFxcXFwqKioqKioqKioqKioqKioqKioqKioqKioqKioqL1xcbi8qKiovICgoKSA9PiB7XFxuXFxuLyogKGlnbm9yZWQpICovXFxuXFxuLyoqKi8gfSksXFxuXFxuLyoqKi8gXFxcIj9jNmY3XFxcIjpcXG4vKiEqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiEqXFxcXFxcbiAgISoqKiB3b3JrZXJfdGhyZWFkcyAoaWdub3JlZCkgKioqIVxcbiAgXFxcXCoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqL1xcbi8qKiovICgoKSA9PiB7XFxuXFxuLyogKGlnbm9yZWQpICovXFxuXFxuLyoqKi8gfSksXFxuXFxuLyoqKi8gXFxcIj83YWE1XFxcIjpcXG4vKiEqKioqKioqKioqKioqKioqKioqKioqISpcXFxcXFxuICAhKioqIHBhdGggKGlnbm9yZWQpICoqKiFcXG4gIFxcXFwqKioqKioqKioqKioqKioqKioqKioqL1xcbi8qKiovICgoKSA9PiB7XFxuXFxuLyogKGlnbm9yZWQpICovXFxuXFxuLyoqKi8gfSlcXG5cXG4vKioqKioqLyBcXHR9KTtcXG4vKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqL1xcbi8qKioqKiovIFxcdC8vIFRoZSBtb2R1bGUgY2FjaGVcXG4vKioqKioqLyBcXHR2YXIgX193ZWJwYWNrX21vZHVsZV9jYWNoZV9fID0ge307XFxuLyoqKioqKi8gXFx0XFxuLyoqKioqKi8gXFx0Ly8gVGhlIHJlcXVpcmUgZnVuY3Rpb25cXG4vKioqKioqLyBcXHRmdW5jdGlvbiBfX3dlYnBhY2tfcmVxdWlyZV9fKG1vZHVsZUlkKSB7XFxuLyoqKioqKi8gXFx0XFx0Ly8gQ2hlY2sgaWYgbW9kdWxlIGlzIGluIGNhY2hlXFxuLyoqKioqKi8gXFx0XFx0dmFyIGNhY2hlZE1vZHVsZSA9IF9fd2VicGFja19tb2R1bGVfY2FjaGVfX1ttb2R1bGVJZF07XFxuLyoqKioqKi8gXFx0XFx0aWYgKGNhY2hlZE1vZHVsZSAhPT0gdW5kZWZpbmVkKSB7XFxuLyoqKioqKi8gXFx0XFx0XFx0cmV0dXJuIGNhY2hlZE1vZHVsZS5leHBvcnRzO1xcbi8qKioqKiovIFxcdFxcdH1cXG4vKioqKioqLyBcXHRcXHQvLyBDcmVhdGUgYSBuZXcgbW9kdWxlIChhbmQgcHV0IGl0IGludG8gdGhlIGNhY2hlKVxcbi8qKioqKiovIFxcdFxcdHZhciBtb2R1bGUgPSBfX3dlYnBhY2tfbW9kdWxlX2NhY2hlX19bbW9kdWxlSWRdID0ge1xcbi8qKioqKiovIFxcdFxcdFxcdC8vIG5vIG1vZHVsZS5pZCBuZWVkZWRcXG4vKioqKioqLyBcXHRcXHRcXHQvLyBubyBtb2R1bGUubG9hZGVkIG5lZWRlZFxcbi8qKioqKiovIFxcdFxcdFxcdGV4cG9ydHM6IHt9XFxuLyoqKioqKi8gXFx0XFx0fTtcXG4vKioqKioqLyBcXHRcXG4vKioqKioqLyBcXHRcXHQvLyBFeGVjdXRlIHRoZSBtb2R1bGUgZnVuY3Rpb25cXG4vKioqKioqLyBcXHRcXHRfX3dlYnBhY2tfbW9kdWxlc19fW21vZHVsZUlkXS5jYWxsKG1vZHVsZS5leHBvcnRzLCBtb2R1bGUsIG1vZHVsZS5leHBvcnRzLCBfX3dlYnBhY2tfcmVxdWlyZV9fKTtcXG4vKioqKioqLyBcXHRcXG4vKioqKioqLyBcXHRcXHQvLyBSZXR1cm4gdGhlIGV4cG9ydHMgb2YgdGhlIG1vZHVsZVxcbi8qKioqKiovIFxcdFxcdHJldHVybiBtb2R1bGUuZXhwb3J0cztcXG4vKioqKioqLyBcXHR9XFxuLyoqKioqKi8gXFx0XFxuLyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKi9cXG4vKioqKioqLyBcXHQvKiB3ZWJwYWNrL3J1bnRpbWUvZ2xvYmFsICovXFxuLyoqKioqKi8gXFx0KCgpID0+IHtcXG4vKioqKioqLyBcXHRcXHRfX3dlYnBhY2tfcmVxdWlyZV9fLmcgPSAoZnVuY3Rpb24oKSB7XFxuLyoqKioqKi8gXFx0XFx0XFx0aWYgKHR5cGVvZiBnbG9iYWxUaGlzID09PSAnb2JqZWN0JykgcmV0dXJuIGdsb2JhbFRoaXM7XFxuLyoqKioqKi8gXFx0XFx0XFx0dHJ5IHtcXG4vKioqKioqLyBcXHRcXHRcXHRcXHRyZXR1cm4gdGhpcyB8fCBuZXcgRnVuY3Rpb24oJ3JldHVybiB0aGlzJykoKTtcXG4vKioqKioqLyBcXHRcXHRcXHR9IGNhdGNoIChlKSB7XFxuLyoqKioqKi8gXFx0XFx0XFx0XFx0aWYgKHR5cGVvZiB3aW5kb3cgPT09ICdvYmplY3QnKSByZXR1cm4gd2luZG93O1xcbi8qKioqKiovIFxcdFxcdFxcdH1cXG4vKioqKioqLyBcXHRcXHR9KSgpO1xcbi8qKioqKiovIFxcdH0pKCk7XFxuLyoqKioqKi8gXFx0XFxuLyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKi9cXG52YXIgX193ZWJwYWNrX2V4cG9ydHNfXyA9IHt9O1xcbi8vIFRoaXMgZW50cnkgbmVlZCB0byBiZSB3cmFwcGVkIGluIGFuIElJRkUgYmVjYXVzZSBpdCBuZWVkIHRvIGJlIGluIHN0cmljdCBtb2RlLlxcbigoKSA9PiB7XFxuXFxcInVzZSBzdHJpY3RcXFwiO1xcbnZhciBleHBvcnRzID0gX193ZWJwYWNrX2V4cG9ydHNfXztcXG4vKiEqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiEqXFxcXFxcbiAgISoqKiAuL25vZGVfbW9kdWxlcy90cy1sb2FkZXIvaW5kZXguanM/P3J1bGVTZXRbMV0ucnVsZXNbMF0udXNlWzBdIS4vbGliL3dhc20vcHJveHktd29ya2VyL21haW4udHMgKioqIVxcbiAgXFxcXCoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqL1xcblxcbi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxcbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cXG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXFxcIl9fZXNNb2R1bGVcXFwiLCAoeyB2YWx1ZTogdHJ1ZSB9KSk7XFxuY29uc3Qgd2FzbV9jb3JlX2ltcGxfMSA9IF9fd2VicGFja19yZXF1aXJlX18oLyohIC4uL3dhc20tY29yZS1pbXBsICovIFxcXCIuL2xpYi93YXNtL3dhc20tY29yZS1pbXBsLnRzXFxcIik7XFxuY29uc3Qgd2FzbV9mYWN0b3J5XzEgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKC8qISAuLi93YXNtLWZhY3RvcnkgKi8gXFxcIi4vbGliL3dhc20vd2FzbS1mYWN0b3J5LnRzXFxcIik7XFxuc2VsZi5vbm1lc3NhZ2UgPSAoZXYpID0+IHtcXG4gICAgc3dpdGNoIChldi5kYXRhLnR5cGUpIHtcXG4gICAgICAgIGNhc2UgJ2luaXQtd2FzbSc6XFxuICAgICAgICAgICAgKDAsIHdhc21fZmFjdG9yeV8xLmluaXRpYWxpemVXZWJBc3NlbWJseSkoZXYuZGF0YS5pbilcXG4gICAgICAgICAgICAgICAgLnRoZW4oKCkgPT4gcG9zdE1lc3NhZ2UoeyB0eXBlOiAnaW5pdC13YXNtJyB9KSwgZXJyID0+IHBvc3RNZXNzYWdlKHsgdHlwZTogJ2luaXQtd2FzbScsIGVyciB9KSk7XFxuICAgICAgICAgICAgYnJlYWs7XFxuICAgICAgICBjYXNlICdpbml0LW9ydCc6XFxuICAgICAgICAgICAgdHJ5IHtcXG4gICAgICAgICAgICAgICAgY29uc3QgeyBudW1UaHJlYWRzLCBsb2dnaW5nTGV2ZWwgfSA9IGV2LmRhdGEuaW47XFxuICAgICAgICAgICAgICAgICgwLCB3YXNtX2NvcmVfaW1wbF8xLmluaXRPcnQpKG51bVRocmVhZHMsIGxvZ2dpbmdMZXZlbCk7XFxuICAgICAgICAgICAgICAgIHBvc3RNZXNzYWdlKHsgdHlwZTogJ2luaXQtb3J0JyB9KTtcXG4gICAgICAgICAgICB9XFxuICAgICAgICAgICAgY2F0Y2ggKGVycikge1xcbiAgICAgICAgICAgICAgICBwb3N0TWVzc2FnZSh7IHR5cGU6ICdpbml0LW9ydCcsIGVyciB9KTtcXG4gICAgICAgICAgICB9XFxuICAgICAgICAgICAgYnJlYWs7XFxuICAgICAgICBjYXNlICdjcmVhdGVfYWxsb2NhdGUnOlxcbiAgICAgICAgICAgIHRyeSB7XFxuICAgICAgICAgICAgICAgIGNvbnN0IHsgbW9kZWwgfSA9IGV2LmRhdGEuaW47XFxuICAgICAgICAgICAgICAgIGNvbnN0IG1vZGVsZGF0YSA9ICgwLCB3YXNtX2NvcmVfaW1wbF8xLmNyZWF0ZVNlc3Npb25BbGxvY2F0ZSkobW9kZWwpO1xcbiAgICAgICAgICAgICAgICBwb3N0TWVzc2FnZSh7IHR5cGU6ICdjcmVhdGVfYWxsb2NhdGUnLCBvdXQ6IG1vZGVsZGF0YSB9KTtcXG4gICAgICAgICAgICB9XFxuICAgICAgICAgICAgY2F0Y2ggKGVycikge1xcbiAgICAgICAgICAgICAgICBwb3N0TWVzc2FnZSh7IHR5cGU6ICdjcmVhdGVfYWxsb2NhdGUnLCBlcnIgfSk7XFxuICAgICAgICAgICAgfVxcbiAgICAgICAgICAgIGJyZWFrO1xcbiAgICAgICAgY2FzZSAnY3JlYXRlX2ZpbmFsaXplJzpcXG4gICAgICAgICAgICB0cnkge1xcbiAgICAgICAgICAgICAgICBjb25zdCB7IG1vZGVsZGF0YSwgb3B0aW9ucyB9ID0gZXYuZGF0YS5pbjtcXG4gICAgICAgICAgICAgICAgY29uc3Qgc2Vzc2lvbk1ldGFkYXRhID0gKDAsIHdhc21fY29yZV9pbXBsXzEuY3JlYXRlU2Vzc2lvbkZpbmFsaXplKShtb2RlbGRhdGEsIG9wdGlvbnMpO1xcbiAgICAgICAgICAgICAgICBwb3N0TWVzc2FnZSh7IHR5cGU6ICdjcmVhdGVfZmluYWxpemUnLCBvdXQ6IHNlc3Npb25NZXRhZGF0YSB9KTtcXG4gICAgICAgICAgICB9XFxuICAgICAgICAgICAgY2F0Y2ggKGVycikge1xcbiAgICAgICAgICAgICAgICBwb3N0TWVzc2FnZSh7IHR5cGU6ICdjcmVhdGVfZmluYWxpemUnLCBlcnIgfSk7XFxuICAgICAgICAgICAgfVxcbiAgICAgICAgICAgIGJyZWFrO1xcbiAgICAgICAgY2FzZSAnY3JlYXRlJzpcXG4gICAgICAgICAgICB0cnkge1xcbiAgICAgICAgICAgICAgICBjb25zdCB7IG1vZGVsLCBvcHRpb25zIH0gPSBldi5kYXRhLmluO1xcbiAgICAgICAgICAgICAgICBjb25zdCBzZXNzaW9uTWV0YWRhdGEgPSAoMCwgd2FzbV9jb3JlX2ltcGxfMS5jcmVhdGVTZXNzaW9uKShtb2RlbCwgb3B0aW9ucyk7XFxuICAgICAgICAgICAgICAgIHBvc3RNZXNzYWdlKHsgdHlwZTogJ2NyZWF0ZScsIG91dDogc2Vzc2lvbk1ldGFkYXRhIH0pO1xcbiAgICAgICAgICAgIH1cXG4gICAgICAgICAgICBjYXRjaCAoZXJyKSB7XFxuICAgICAgICAgICAgICAgIHBvc3RNZXNzYWdlKHsgdHlwZTogJ2NyZWF0ZScsIGVyciB9KTtcXG4gICAgICAgICAgICB9XFxuICAgICAgICAgICAgYnJlYWs7XFxuICAgICAgICBjYXNlICdyZWxlYXNlJzpcXG4gICAgICAgICAgICB0cnkge1xcbiAgICAgICAgICAgICAgICBjb25zdCBoYW5kbGVyID0gZXYuZGF0YS5pbjtcXG4gICAgICAgICAgICAgICAgKDAsIHdhc21fY29yZV9pbXBsXzEucmVsZWFzZVNlc3Npb24pKGhhbmRsZXIpO1xcbiAgICAgICAgICAgICAgICBwb3N0TWVzc2FnZSh7IHR5cGU6ICdyZWxlYXNlJyB9KTtcXG4gICAgICAgICAgICB9XFxuICAgICAgICAgICAgY2F0Y2ggKGVycikge1xcbiAgICAgICAgICAgICAgICBwb3N0TWVzc2FnZSh7IHR5cGU6ICdyZWxlYXNlJywgZXJyIH0pO1xcbiAgICAgICAgICAgIH1cXG4gICAgICAgICAgICBicmVhaztcXG4gICAgICAgIGNhc2UgJ3J1bic6XFxuICAgICAgICAgICAgdHJ5IHtcXG4gICAgICAgICAgICAgICAgY29uc3QgeyBzZXNzaW9uSWQsIGlucHV0SW5kaWNlcywgaW5wdXRzLCBvdXRwdXRJbmRpY2VzLCBvcHRpb25zIH0gPSBldi5kYXRhLmluO1xcbiAgICAgICAgICAgICAgICBjb25zdCBvdXRwdXRzID0gKDAsIHdhc21fY29yZV9pbXBsXzEucnVuKShzZXNzaW9uSWQsIGlucHV0SW5kaWNlcywgaW5wdXRzLCBvdXRwdXRJbmRpY2VzLCBvcHRpb25zKTtcXG4gICAgICAgICAgICAgICAgcG9zdE1lc3NhZ2UoeyB0eXBlOiAncnVuJywgb3V0OiBvdXRwdXRzIH0sICgwLCB3YXNtX2NvcmVfaW1wbF8xLmV4dHJhY3RUcmFuc2ZlcmFibGVCdWZmZXJzKShvdXRwdXRzKSk7XFxuICAgICAgICAgICAgfVxcbiAgICAgICAgICAgIGNhdGNoIChlcnIpIHtcXG4gICAgICAgICAgICAgICAgcG9zdE1lc3NhZ2UoeyB0eXBlOiAncnVuJywgZXJyIH0pO1xcbiAgICAgICAgICAgIH1cXG4gICAgICAgICAgICBicmVhaztcXG4gICAgICAgIGNhc2UgJ2VuZC1wcm9maWxpbmcnOlxcbiAgICAgICAgICAgIHRyeSB7XFxuICAgICAgICAgICAgICAgIGNvbnN0IGhhbmRsZXIgPSBldi5kYXRhLmluO1xcbiAgICAgICAgICAgICAgICAoMCwgd2FzbV9jb3JlX2ltcGxfMS5lbmRQcm9maWxpbmcpKGhhbmRsZXIpO1xcbiAgICAgICAgICAgICAgICBwb3N0TWVzc2FnZSh7IHR5cGU6ICdlbmQtcHJvZmlsaW5nJyB9KTtcXG4gICAgICAgICAgICB9XFxuICAgICAgICAgICAgY2F0Y2ggKGVycikge1xcbiAgICAgICAgICAgICAgICBwb3N0TWVzc2FnZSh7IHR5cGU6ICdlbmQtcHJvZmlsaW5nJywgZXJyIH0pO1xcbiAgICAgICAgICAgIH1cXG4gICAgICAgICAgICBicmVhaztcXG4gICAgICAgIGRlZmF1bHQ6XFxuICAgIH1cXG59O1xcblxcbn0pKCk7XFxuXFxuLyoqKioqKi8gfSkoKVxcbjtcXG5cIiwgXCJXb3JrZXJcIiwgdW5kZWZpbmVkLCB1bmRlZmluZWQpO1xufVxuIiwiXCJ1c2Ugc3RyaWN0XCI7XG5cbi8qIGVzbGludC1lbnYgYnJvd3NlciAqL1xuXG4vKiBlc2xpbnQtZGlzYWJsZSBuby11bmRlZiwgbm8tdXNlLWJlZm9yZS1kZWZpbmUsIG5ldy1jYXAgKi9cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKGNvbnRlbnQsIHdvcmtlckNvbnN0cnVjdG9yLCB3b3JrZXJPcHRpb25zLCB1cmwpIHtcbiAgdmFyIGdsb2JhbFNjb3BlID0gc2VsZiB8fCB3aW5kb3c7XG5cbiAgdHJ5IHtcbiAgICB0cnkge1xuICAgICAgdmFyIGJsb2I7XG5cbiAgICAgIHRyeSB7XG4gICAgICAgIC8vIE5ldyBBUElcbiAgICAgICAgYmxvYiA9IG5ldyBnbG9iYWxTY29wZS5CbG9iKFtjb250ZW50XSk7XG4gICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIC8vIEJsb2JCdWlsZGVyID0gRGVwcmVjYXRlZCwgYnV0IHdpZGVseSBpbXBsZW1lbnRlZFxuICAgICAgICB2YXIgQmxvYkJ1aWxkZXIgPSBnbG9iYWxTY29wZS5CbG9iQnVpbGRlciB8fCBnbG9iYWxTY29wZS5XZWJLaXRCbG9iQnVpbGRlciB8fCBnbG9iYWxTY29wZS5Nb3pCbG9iQnVpbGRlciB8fCBnbG9iYWxTY29wZS5NU0Jsb2JCdWlsZGVyO1xuICAgICAgICBibG9iID0gbmV3IEJsb2JCdWlsZGVyKCk7XG4gICAgICAgIGJsb2IuYXBwZW5kKGNvbnRlbnQpO1xuICAgICAgICBibG9iID0gYmxvYi5nZXRCbG9iKCk7XG4gICAgICB9XG5cbiAgICAgIHZhciBVUkwgPSBnbG9iYWxTY29wZS5VUkwgfHwgZ2xvYmFsU2NvcGUud2Via2l0VVJMO1xuICAgICAgdmFyIG9iamVjdFVSTCA9IFVSTC5jcmVhdGVPYmplY3RVUkwoYmxvYik7XG4gICAgICB2YXIgd29ya2VyID0gbmV3IGdsb2JhbFNjb3BlW3dvcmtlckNvbnN0cnVjdG9yXShvYmplY3RVUkwsIHdvcmtlck9wdGlvbnMpO1xuICAgICAgVVJMLnJldm9rZU9iamVjdFVSTChvYmplY3RVUkwpO1xuICAgICAgcmV0dXJuIHdvcmtlcjtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICByZXR1cm4gbmV3IGdsb2JhbFNjb3BlW3dvcmtlckNvbnN0cnVjdG9yXShcImRhdGE6YXBwbGljYXRpb24vamF2YXNjcmlwdCxcIi5jb25jYXQoZW5jb2RlVVJJQ29tcG9uZW50KGNvbnRlbnQpKSwgd29ya2VyT3B0aW9ucyk7XG4gICAgfVxuICB9IGNhdGNoIChlKSB7XG4gICAgaWYgKCF1cmwpIHtcbiAgICAgIHRocm93IEVycm9yKFwiSW5saW5lIHdvcmtlciBpcyBub3Qgc3VwcG9ydGVkXCIpO1xuICAgIH1cblxuICAgIHJldHVybiBuZXcgZ2xvYmFsU2NvcGVbd29ya2VyQ29uc3RydWN0b3JdKHVybCwgd29ya2VyT3B0aW9ucyk7XG4gIH1cbn07IiwiLyogKGlnbm9yZWQpICovIiwiLyogKGlnbm9yZWQpICovIiwiLyogKGlnbm9yZWQpICovIiwiLyogKGlnbm9yZWQpICovIiwiLyogKGlnbm9yZWQpICovIiwiLyogKGlnbm9yZWQpICovIiwiLyogKGlnbm9yZWQpICovIiwiLyogKGlnbm9yZWQpICovIiwiLyogKGlnbm9yZWQpICovIiwiLyogKGlnbm9yZWQpICovIiwiLyogKGlnbm9yZWQpICovIiwiLy8vIEBmaWxlXG4vLy8gQGFkZHRvZ3JvdXAgZmxhdGJ1ZmZlcnNfamF2YXNjcmlwdF9hcGlcbi8vLyBAe1xuLy8vIEBjb25kIEZMQVRCVUZGRVJTX0lOVEVSTkFMXG5cbi8qKlxuICogQGZpbGVvdmVydmlld1xuICpcbiAqIE5lZWQgdG8gc3VwcHJlc3MgJ2dsb2JhbCB0aGlzJyBlcnJvciBzbyB0aGUgTm9kZS5qcyBleHBvcnQgbGluZSBkb2Vzbid0IGNhdXNlXG4gKiBjbG9zdXJlIGNvbXBpbGUgdG8gZXJyb3Igb3V0LlxuICogQHN1cHByZXNzIHtnbG9iYWxUaGlzfVxuICovXG5cbi8qKlxuICogQGNvbnN0XG4gKiBAbmFtZXNwYWNlXG4gKi9cbnZhciBmbGF0YnVmZmVycyA9IHt9O1xuXG4vKipcbiAqIEB0eXBlZGVmIHtudW1iZXJ9XG4gKi9cbmZsYXRidWZmZXJzLk9mZnNldDtcblxuLyoqXG4gKiBAdHlwZWRlZiB7e1xuICogICBiYjogZmxhdGJ1ZmZlcnMuQnl0ZUJ1ZmZlcixcbiAqICAgYmJfcG9zOiBudW1iZXJcbiAqIH19XG4gKi9cbmZsYXRidWZmZXJzLlRhYmxlO1xuXG4vKipcbiAqIEB0eXBlIHtudW1iZXJ9XG4gKiBAY29uc3RcbiAqL1xuZmxhdGJ1ZmZlcnMuU0laRU9GX1NIT1JUID0gMjtcblxuLyoqXG4gKiBAdHlwZSB7bnVtYmVyfVxuICogQGNvbnN0XG4gKi9cbmZsYXRidWZmZXJzLlNJWkVPRl9JTlQgPSA0O1xuXG4vKipcbiAqIEB0eXBlIHtudW1iZXJ9XG4gKiBAY29uc3RcbiAqL1xuZmxhdGJ1ZmZlcnMuRklMRV9JREVOVElGSUVSX0xFTkdUSCA9IDQ7XG5cbi8qKlxuICogQHR5cGUge251bWJlcn1cbiAqIEBjb25zdFxuICovXG5mbGF0YnVmZmVycy5TSVpFX1BSRUZJWF9MRU5HVEggPSA0O1xuXG4vKipcbiAqIEBlbnVtIHtudW1iZXJ9XG4gKi9cbmZsYXRidWZmZXJzLkVuY29kaW5nID0ge1xuICBVVEY4X0JZVEVTOiAxLFxuICBVVEYxNl9TVFJJTkc6IDJcbn07XG5cbi8qKlxuICogQHR5cGUge0ludDMyQXJyYXl9XG4gKiBAY29uc3RcbiAqL1xuZmxhdGJ1ZmZlcnMuaW50MzIgPSBuZXcgSW50MzJBcnJheSgyKTtcblxuLyoqXG4gKiBAdHlwZSB7RmxvYXQzMkFycmF5fVxuICogQGNvbnN0XG4gKi9cbmZsYXRidWZmZXJzLmZsb2F0MzIgPSBuZXcgRmxvYXQzMkFycmF5KGZsYXRidWZmZXJzLmludDMyLmJ1ZmZlcik7XG5cbi8qKlxuICogQHR5cGUge0Zsb2F0NjRBcnJheX1cbiAqIEBjb25zdFxuICovXG5mbGF0YnVmZmVycy5mbG9hdDY0ID0gbmV3IEZsb2F0NjRBcnJheShmbGF0YnVmZmVycy5pbnQzMi5idWZmZXIpO1xuXG4vKipcbiAqIEB0eXBlIHtib29sZWFufVxuICogQGNvbnN0XG4gKi9cbmZsYXRidWZmZXJzLmlzTGl0dGxlRW5kaWFuID0gbmV3IFVpbnQxNkFycmF5KG5ldyBVaW50OEFycmF5KFsxLCAwXSkuYnVmZmVyKVswXSA9PT0gMTtcblxuLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy9cblxuLyoqXG4gKiBAY29uc3RydWN0b3JcbiAqIEBwYXJhbSB7bnVtYmVyfSBsb3dcbiAqIEBwYXJhbSB7bnVtYmVyfSBoaWdoXG4gKi9cbmZsYXRidWZmZXJzLkxvbmcgPSBmdW5jdGlvbihsb3csIGhpZ2gpIHtcbiAgLyoqXG4gICAqIEB0eXBlIHtudW1iZXJ9XG4gICAqIEBjb25zdFxuICAgKi9cbiAgdGhpcy5sb3cgPSBsb3cgfCAwO1xuXG4gIC8qKlxuICAgKiBAdHlwZSB7bnVtYmVyfVxuICAgKiBAY29uc3RcbiAgICovXG4gIHRoaXMuaGlnaCA9IGhpZ2ggfCAwO1xufTtcblxuLyoqXG4gKiBAcGFyYW0ge251bWJlcn0gbG93XG4gKiBAcGFyYW0ge251bWJlcn0gaGlnaFxuICogQHJldHVybnMgeyFmbGF0YnVmZmVycy5Mb25nfVxuICovXG5mbGF0YnVmZmVycy5Mb25nLmNyZWF0ZSA9IGZ1bmN0aW9uKGxvdywgaGlnaCkge1xuICAvLyBTcGVjaWFsLWNhc2UgemVybyB0byBhdm9pZCBHQyBvdmVyaGVhZCBmb3IgZGVmYXVsdCB2YWx1ZXNcbiAgcmV0dXJuIGxvdyA9PSAwICYmIGhpZ2ggPT0gMCA/IGZsYXRidWZmZXJzLkxvbmcuWkVSTyA6IG5ldyBmbGF0YnVmZmVycy5Mb25nKGxvdywgaGlnaCk7XG59O1xuXG4vKipcbiAqIEByZXR1cm5zIHtudW1iZXJ9XG4gKi9cbmZsYXRidWZmZXJzLkxvbmcucHJvdG90eXBlLnRvRmxvYXQ2NCA9IGZ1bmN0aW9uKCkge1xuICByZXR1cm4gKHRoaXMubG93ID4+PiAwKSArIHRoaXMuaGlnaCAqIDB4MTAwMDAwMDAwO1xufTtcblxuLyoqXG4gKiBAcGFyYW0ge2ZsYXRidWZmZXJzLkxvbmd9IG90aGVyXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn1cbiAqL1xuZmxhdGJ1ZmZlcnMuTG9uZy5wcm90b3R5cGUuZXF1YWxzID0gZnVuY3Rpb24ob3RoZXIpIHtcbiAgcmV0dXJuIHRoaXMubG93ID09IG90aGVyLmxvdyAmJiB0aGlzLmhpZ2ggPT0gb3RoZXIuaGlnaDtcbn07XG5cbi8qKlxuICogQHR5cGUgeyFmbGF0YnVmZmVycy5Mb25nfVxuICogQGNvbnN0XG4gKi9cbmZsYXRidWZmZXJzLkxvbmcuWkVSTyA9IG5ldyBmbGF0YnVmZmVycy5Mb25nKDAsIDApO1xuXG4vLy8gQGVuZGNvbmRcbi8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vXG4vKipcbiAqIENyZWF0ZSBhIEZsYXRCdWZmZXJCdWlsZGVyLlxuICpcbiAqIEBjb25zdHJ1Y3RvclxuICogQHBhcmFtIHtudW1iZXI9fSBvcHRfaW5pdGlhbF9zaXplXG4gKi9cbmZsYXRidWZmZXJzLkJ1aWxkZXIgPSBmdW5jdGlvbihvcHRfaW5pdGlhbF9zaXplKSB7XG4gIGlmICghb3B0X2luaXRpYWxfc2l6ZSkge1xuICAgIHZhciBpbml0aWFsX3NpemUgPSAxMDI0O1xuICB9IGVsc2Uge1xuICAgIHZhciBpbml0aWFsX3NpemUgPSBvcHRfaW5pdGlhbF9zaXplO1xuICB9XG5cbiAgLyoqXG4gICAqIEB0eXBlIHtmbGF0YnVmZmVycy5CeXRlQnVmZmVyfVxuICAgKiBAcHJpdmF0ZVxuICAgKi9cbiAgdGhpcy5iYiA9IGZsYXRidWZmZXJzLkJ5dGVCdWZmZXIuYWxsb2NhdGUoaW5pdGlhbF9zaXplKTtcblxuICAvKipcbiAgICogUmVtYWluaW5nIHNwYWNlIGluIHRoZSBCeXRlQnVmZmVyLlxuICAgKlxuICAgKiBAdHlwZSB7bnVtYmVyfVxuICAgKiBAcHJpdmF0ZVxuICAgKi9cbiAgdGhpcy5zcGFjZSA9IGluaXRpYWxfc2l6ZTtcblxuICAvKipcbiAgICogTWluaW11bSBhbGlnbm1lbnQgZW5jb3VudGVyZWQgc28gZmFyLlxuICAgKlxuICAgKiBAdHlwZSB7bnVtYmVyfVxuICAgKiBAcHJpdmF0ZVxuICAgKi9cbiAgdGhpcy5taW5hbGlnbiA9IDE7XG5cbiAgLyoqXG4gICAqIFRoZSB2dGFibGUgZm9yIHRoZSBjdXJyZW50IHRhYmxlLlxuICAgKlxuICAgKiBAdHlwZSB7QXJyYXkuPG51bWJlcj59XG4gICAqIEBwcml2YXRlXG4gICAqL1xuICB0aGlzLnZ0YWJsZSA9IG51bGw7XG5cbiAgLyoqXG4gICAqIFRoZSBhbW91bnQgb2YgZmllbGRzIHdlJ3JlIGFjdHVhbGx5IHVzaW5nLlxuICAgKlxuICAgKiBAdHlwZSB7bnVtYmVyfVxuICAgKiBAcHJpdmF0ZVxuICAgKi9cbiAgdGhpcy52dGFibGVfaW5fdXNlID0gMDtcblxuICAvKipcbiAgICogV2hldGhlciB3ZSBhcmUgY3VycmVudGx5IHNlcmlhbGl6aW5nIGEgdGFibGUuXG4gICAqXG4gICAqIEB0eXBlIHtib29sZWFufVxuICAgKiBAcHJpdmF0ZVxuICAgKi9cbiAgdGhpcy5pc05lc3RlZCA9IGZhbHNlO1xuXG4gIC8qKlxuICAgKiBTdGFydGluZyBvZmZzZXQgb2YgdGhlIGN1cnJlbnQgc3RydWN0L3RhYmxlLlxuICAgKlxuICAgKiBAdHlwZSB7bnVtYmVyfVxuICAgKiBAcHJpdmF0ZVxuICAgKi9cbiAgdGhpcy5vYmplY3Rfc3RhcnQgPSAwO1xuXG4gIC8qKlxuICAgKiBMaXN0IG9mIG9mZnNldHMgb2YgYWxsIHZ0YWJsZXMuXG4gICAqXG4gICAqIEB0eXBlIHtBcnJheS48bnVtYmVyPn1cbiAgICogQHByaXZhdGVcbiAgICovXG4gIHRoaXMudnRhYmxlcyA9IFtdO1xuXG4gIC8qKlxuICAgKiBGb3IgdGhlIGN1cnJlbnQgdmVjdG9yIGJlaW5nIGJ1aWx0LlxuICAgKlxuICAgKiBAdHlwZSB7bnVtYmVyfVxuICAgKiBAcHJpdmF0ZVxuICAgKi9cbiAgdGhpcy52ZWN0b3JfbnVtX2VsZW1zID0gMDtcblxuICAvKipcbiAgICogRmFsc2Ugb21pdHMgZGVmYXVsdCB2YWx1ZXMgZnJvbSB0aGUgc2VyaWFsaXplZCBkYXRhXG4gICAqXG4gICAqIEB0eXBlIHtib29sZWFufVxuICAgKiBAcHJpdmF0ZVxuICAgKi9cbiAgdGhpcy5mb3JjZV9kZWZhdWx0cyA9IGZhbHNlO1xufTtcblxuZmxhdGJ1ZmZlcnMuQnVpbGRlci5wcm90b3R5cGUuY2xlYXIgPSBmdW5jdGlvbigpIHtcbiAgdGhpcy5iYi5jbGVhcigpO1xuICB0aGlzLnNwYWNlID0gdGhpcy5iYi5jYXBhY2l0eSgpO1xuICB0aGlzLm1pbmFsaWduID0gMTtcbiAgdGhpcy52dGFibGUgPSBudWxsO1xuICB0aGlzLnZ0YWJsZV9pbl91c2UgPSAwO1xuICB0aGlzLmlzTmVzdGVkID0gZmFsc2U7XG4gIHRoaXMub2JqZWN0X3N0YXJ0ID0gMDtcbiAgdGhpcy52dGFibGVzID0gW107XG4gIHRoaXMudmVjdG9yX251bV9lbGVtcyA9IDA7XG4gIHRoaXMuZm9yY2VfZGVmYXVsdHMgPSBmYWxzZTtcbn07XG5cbi8qKlxuICogSW4gb3JkZXIgdG8gc2F2ZSBzcGFjZSwgZmllbGRzIHRoYXQgYXJlIHNldCB0byB0aGVpciBkZWZhdWx0IHZhbHVlXG4gKiBkb24ndCBnZXQgc2VyaWFsaXplZCBpbnRvIHRoZSBidWZmZXIuIEZvcmNpbmcgZGVmYXVsdHMgcHJvdmlkZXMgYVxuICogd2F5IHRvIG1hbnVhbGx5IGRpc2FibGUgdGhpcyBvcHRpbWl6YXRpb24uXG4gKlxuICogQHBhcmFtIHtib29sZWFufSBmb3JjZURlZmF1bHRzIHRydWUgYWx3YXlzIHNlcmlhbGl6ZXMgZGVmYXVsdCB2YWx1ZXNcbiAqL1xuZmxhdGJ1ZmZlcnMuQnVpbGRlci5wcm90b3R5cGUuZm9yY2VEZWZhdWx0cyA9IGZ1bmN0aW9uKGZvcmNlRGVmYXVsdHMpIHtcbiAgdGhpcy5mb3JjZV9kZWZhdWx0cyA9IGZvcmNlRGVmYXVsdHM7XG59O1xuXG4vKipcbiAqIEdldCB0aGUgQnl0ZUJ1ZmZlciByZXByZXNlbnRpbmcgdGhlIEZsYXRCdWZmZXIuIE9ubHkgY2FsbCB0aGlzIGFmdGVyIHlvdSd2ZVxuICogY2FsbGVkIGZpbmlzaCgpLiBUaGUgYWN0dWFsIGRhdGEgc3RhcnRzIGF0IHRoZSBCeXRlQnVmZmVyJ3MgY3VycmVudCBwb3NpdGlvbixcbiAqIG5vdCBuZWNlc3NhcmlseSBhdCAwLlxuICpcbiAqIEByZXR1cm5zIHtmbGF0YnVmZmVycy5CeXRlQnVmZmVyfVxuICovXG5mbGF0YnVmZmVycy5CdWlsZGVyLnByb3RvdHlwZS5kYXRhQnVmZmVyID0gZnVuY3Rpb24oKSB7XG4gIHJldHVybiB0aGlzLmJiO1xufTtcblxuLyoqXG4gKiBHZXQgdGhlIGJ5dGVzIHJlcHJlc2VudGluZyB0aGUgRmxhdEJ1ZmZlci4gT25seSBjYWxsIHRoaXMgYWZ0ZXIgeW91J3ZlXG4gKiBjYWxsZWQgZmluaXNoKCkuXG4gKlxuICogQHJldHVybnMgeyFVaW50OEFycmF5fVxuICovXG5mbGF0YnVmZmVycy5CdWlsZGVyLnByb3RvdHlwZS5hc1VpbnQ4QXJyYXkgPSBmdW5jdGlvbigpIHtcbiAgcmV0dXJuIHRoaXMuYmIuYnl0ZXMoKS5zdWJhcnJheSh0aGlzLmJiLnBvc2l0aW9uKCksIHRoaXMuYmIucG9zaXRpb24oKSArIHRoaXMub2Zmc2V0KCkpO1xufTtcblxuLy8vIEBjb25kIEZMQVRCVUZGRVJTX0lOVEVSTkFMXG4vKipcbiAqIFByZXBhcmUgdG8gd3JpdGUgYW4gZWxlbWVudCBvZiBgc2l6ZWAgYWZ0ZXIgYGFkZGl0aW9uYWxfYnl0ZXNgIGhhdmUgYmVlblxuICogd3JpdHRlbiwgZS5nLiBpZiB5b3Ugd3JpdGUgYSBzdHJpbmcsIHlvdSBuZWVkIHRvIGFsaWduIHN1Y2ggdGhlIGludCBsZW5ndGhcbiAqIGZpZWxkIGlzIGFsaWduZWQgdG8gNCBieXRlcywgYW5kIHRoZSBzdHJpbmcgZGF0YSBmb2xsb3dzIGl0IGRpcmVjdGx5LiBJZiBhbGxcbiAqIHlvdSBuZWVkIHRvIGRvIGlzIGFsaWdubWVudCwgYGFkZGl0aW9uYWxfYnl0ZXNgIHdpbGwgYmUgMC5cbiAqXG4gKiBAcGFyYW0ge251bWJlcn0gc2l6ZSBUaGlzIGlzIHRoZSBvZiB0aGUgbmV3IGVsZW1lbnQgdG8gd3JpdGVcbiAqIEBwYXJhbSB7bnVtYmVyfSBhZGRpdGlvbmFsX2J5dGVzIFRoZSBwYWRkaW5nIHNpemVcbiAqL1xuZmxhdGJ1ZmZlcnMuQnVpbGRlci5wcm90b3R5cGUucHJlcCA9IGZ1bmN0aW9uKHNpemUsIGFkZGl0aW9uYWxfYnl0ZXMpIHtcbiAgLy8gVHJhY2sgdGhlIGJpZ2dlc3QgdGhpbmcgd2UndmUgZXZlciBhbGlnbmVkIHRvLlxuICBpZiAoc2l6ZSA+IHRoaXMubWluYWxpZ24pIHtcbiAgICB0aGlzLm1pbmFsaWduID0gc2l6ZTtcbiAgfVxuXG4gIC8vIEZpbmQgdGhlIGFtb3VudCBvZiBhbGlnbm1lbnQgbmVlZGVkIHN1Y2ggdGhhdCBgc2l6ZWAgaXMgcHJvcGVybHlcbiAgLy8gYWxpZ25lZCBhZnRlciBgYWRkaXRpb25hbF9ieXRlc2BcbiAgdmFyIGFsaWduX3NpemUgPSAoKH4odGhpcy5iYi5jYXBhY2l0eSgpIC0gdGhpcy5zcGFjZSArIGFkZGl0aW9uYWxfYnl0ZXMpKSArIDEpICYgKHNpemUgLSAxKTtcblxuICAvLyBSZWFsbG9jYXRlIHRoZSBidWZmZXIgaWYgbmVlZGVkLlxuICB3aGlsZSAodGhpcy5zcGFjZSA8IGFsaWduX3NpemUgKyBzaXplICsgYWRkaXRpb25hbF9ieXRlcykge1xuICAgIHZhciBvbGRfYnVmX3NpemUgPSB0aGlzLmJiLmNhcGFjaXR5KCk7XG4gICAgdGhpcy5iYiA9IGZsYXRidWZmZXJzLkJ1aWxkZXIuZ3Jvd0J5dGVCdWZmZXIodGhpcy5iYik7XG4gICAgdGhpcy5zcGFjZSArPSB0aGlzLmJiLmNhcGFjaXR5KCkgLSBvbGRfYnVmX3NpemU7XG4gIH1cblxuICB0aGlzLnBhZChhbGlnbl9zaXplKTtcbn07XG5cbi8qKlxuICogQHBhcmFtIHtudW1iZXJ9IGJ5dGVfc2l6ZVxuICovXG5mbGF0YnVmZmVycy5CdWlsZGVyLnByb3RvdHlwZS5wYWQgPSBmdW5jdGlvbihieXRlX3NpemUpIHtcbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBieXRlX3NpemU7IGkrKykge1xuICAgIHRoaXMuYmIud3JpdGVJbnQ4KC0tdGhpcy5zcGFjZSwgMCk7XG4gIH1cbn07XG5cbi8qKlxuICogQHBhcmFtIHtudW1iZXJ9IHZhbHVlXG4gKi9cbmZsYXRidWZmZXJzLkJ1aWxkZXIucHJvdG90eXBlLndyaXRlSW50OCA9IGZ1bmN0aW9uKHZhbHVlKSB7XG4gIHRoaXMuYmIud3JpdGVJbnQ4KHRoaXMuc3BhY2UgLT0gMSwgdmFsdWUpO1xufTtcblxuLyoqXG4gKiBAcGFyYW0ge251bWJlcn0gdmFsdWVcbiAqL1xuZmxhdGJ1ZmZlcnMuQnVpbGRlci5wcm90b3R5cGUud3JpdGVJbnQxNiA9IGZ1bmN0aW9uKHZhbHVlKSB7XG4gIHRoaXMuYmIud3JpdGVJbnQxNih0aGlzLnNwYWNlIC09IDIsIHZhbHVlKTtcbn07XG5cbi8qKlxuICogQHBhcmFtIHtudW1iZXJ9IHZhbHVlXG4gKi9cbmZsYXRidWZmZXJzLkJ1aWxkZXIucHJvdG90eXBlLndyaXRlSW50MzIgPSBmdW5jdGlvbih2YWx1ZSkge1xuICB0aGlzLmJiLndyaXRlSW50MzIodGhpcy5zcGFjZSAtPSA0LCB2YWx1ZSk7XG59O1xuXG4vKipcbiAqIEBwYXJhbSB7ZmxhdGJ1ZmZlcnMuTG9uZ30gdmFsdWVcbiAqL1xuZmxhdGJ1ZmZlcnMuQnVpbGRlci5wcm90b3R5cGUud3JpdGVJbnQ2NCA9IGZ1bmN0aW9uKHZhbHVlKSB7XG4gIHRoaXMuYmIud3JpdGVJbnQ2NCh0aGlzLnNwYWNlIC09IDgsIHZhbHVlKTtcbn07XG5cbi8qKlxuICogQHBhcmFtIHtudW1iZXJ9IHZhbHVlXG4gKi9cbmZsYXRidWZmZXJzLkJ1aWxkZXIucHJvdG90eXBlLndyaXRlRmxvYXQzMiA9IGZ1bmN0aW9uKHZhbHVlKSB7XG4gIHRoaXMuYmIud3JpdGVGbG9hdDMyKHRoaXMuc3BhY2UgLT0gNCwgdmFsdWUpO1xufTtcblxuLyoqXG4gKiBAcGFyYW0ge251bWJlcn0gdmFsdWVcbiAqL1xuZmxhdGJ1ZmZlcnMuQnVpbGRlci5wcm90b3R5cGUud3JpdGVGbG9hdDY0ID0gZnVuY3Rpb24odmFsdWUpIHtcbiAgdGhpcy5iYi53cml0ZUZsb2F0NjQodGhpcy5zcGFjZSAtPSA4LCB2YWx1ZSk7XG59O1xuLy8vIEBlbmRjb25kXG5cbi8qKlxuICogQWRkIGFuIGBpbnQ4YCB0byB0aGUgYnVmZmVyLCBwcm9wZXJseSBhbGlnbmVkLCBhbmQgZ3Jvd3MgdGhlIGJ1ZmZlciAoaWYgbmVjZXNzYXJ5KS5cbiAqIEBwYXJhbSB7bnVtYmVyfSB2YWx1ZSBUaGUgYGludDhgIHRvIGFkZCB0aGUgdGhlIGJ1ZmZlci5cbiAqL1xuZmxhdGJ1ZmZlcnMuQnVpbGRlci5wcm90b3R5cGUuYWRkSW50OCA9IGZ1bmN0aW9uKHZhbHVlKSB7XG4gIHRoaXMucHJlcCgxLCAwKTtcbiAgdGhpcy53cml0ZUludDgodmFsdWUpO1xufTtcblxuLyoqXG4gKiBBZGQgYW4gYGludDE2YCB0byB0aGUgYnVmZmVyLCBwcm9wZXJseSBhbGlnbmVkLCBhbmQgZ3Jvd3MgdGhlIGJ1ZmZlciAoaWYgbmVjZXNzYXJ5KS5cbiAqIEBwYXJhbSB7bnVtYmVyfSB2YWx1ZSBUaGUgYGludDE2YCB0byBhZGQgdGhlIHRoZSBidWZmZXIuXG4gKi9cbmZsYXRidWZmZXJzLkJ1aWxkZXIucHJvdG90eXBlLmFkZEludDE2ID0gZnVuY3Rpb24odmFsdWUpIHtcbiAgdGhpcy5wcmVwKDIsIDApO1xuICB0aGlzLndyaXRlSW50MTYodmFsdWUpO1xufTtcblxuLyoqXG4gKiBBZGQgYW4gYGludDMyYCB0byB0aGUgYnVmZmVyLCBwcm9wZXJseSBhbGlnbmVkLCBhbmQgZ3Jvd3MgdGhlIGJ1ZmZlciAoaWYgbmVjZXNzYXJ5KS5cbiAqIEBwYXJhbSB7bnVtYmVyfSB2YWx1ZSBUaGUgYGludDMyYCB0byBhZGQgdGhlIHRoZSBidWZmZXIuXG4gKi9cbmZsYXRidWZmZXJzLkJ1aWxkZXIucHJvdG90eXBlLmFkZEludDMyID0gZnVuY3Rpb24odmFsdWUpIHtcbiAgdGhpcy5wcmVwKDQsIDApO1xuICB0aGlzLndyaXRlSW50MzIodmFsdWUpO1xufTtcblxuLyoqXG4gKiBBZGQgYW4gYGludDY0YCB0byB0aGUgYnVmZmVyLCBwcm9wZXJseSBhbGlnbmVkLCBhbmQgZ3Jvd3MgdGhlIGJ1ZmZlciAoaWYgbmVjZXNzYXJ5KS5cbiAqIEBwYXJhbSB7ZmxhdGJ1ZmZlcnMuTG9uZ30gdmFsdWUgVGhlIGBpbnQ2NGAgdG8gYWRkIHRoZSB0aGUgYnVmZmVyLlxuICovXG5mbGF0YnVmZmVycy5CdWlsZGVyLnByb3RvdHlwZS5hZGRJbnQ2NCA9IGZ1bmN0aW9uKHZhbHVlKSB7XG4gIHRoaXMucHJlcCg4LCAwKTtcbiAgdGhpcy53cml0ZUludDY0KHZhbHVlKTtcbn07XG5cbi8qKlxuICogQWRkIGEgYGZsb2F0MzJgIHRvIHRoZSBidWZmZXIsIHByb3Blcmx5IGFsaWduZWQsIGFuZCBncm93cyB0aGUgYnVmZmVyIChpZiBuZWNlc3NhcnkpLlxuICogQHBhcmFtIHtudW1iZXJ9IHZhbHVlIFRoZSBgZmxvYXQzMmAgdG8gYWRkIHRoZSB0aGUgYnVmZmVyLlxuICovXG5mbGF0YnVmZmVycy5CdWlsZGVyLnByb3RvdHlwZS5hZGRGbG9hdDMyID0gZnVuY3Rpb24odmFsdWUpIHtcbiAgdGhpcy5wcmVwKDQsIDApO1xuICB0aGlzLndyaXRlRmxvYXQzMih2YWx1ZSk7XG59O1xuXG4vKipcbiAqIEFkZCBhIGBmbG9hdDY0YCB0byB0aGUgYnVmZmVyLCBwcm9wZXJseSBhbGlnbmVkLCBhbmQgZ3Jvd3MgdGhlIGJ1ZmZlciAoaWYgbmVjZXNzYXJ5KS5cbiAqIEBwYXJhbSB7bnVtYmVyfSB2YWx1ZSBUaGUgYGZsb2F0NjRgIHRvIGFkZCB0aGUgdGhlIGJ1ZmZlci5cbiAqL1xuZmxhdGJ1ZmZlcnMuQnVpbGRlci5wcm90b3R5cGUuYWRkRmxvYXQ2NCA9IGZ1bmN0aW9uKHZhbHVlKSB7XG4gIHRoaXMucHJlcCg4LCAwKTtcbiAgdGhpcy53cml0ZUZsb2F0NjQodmFsdWUpO1xufTtcblxuLy8vIEBjb25kIEZMQVRCVUZGRVJTX0lOVEVSTkFMXG4vKipcbiAqIEBwYXJhbSB7bnVtYmVyfSB2b2Zmc2V0XG4gKiBAcGFyYW0ge251bWJlcn0gdmFsdWVcbiAqIEBwYXJhbSB7bnVtYmVyfSBkZWZhdWx0VmFsdWVcbiAqL1xuZmxhdGJ1ZmZlcnMuQnVpbGRlci5wcm90b3R5cGUuYWRkRmllbGRJbnQ4ID0gZnVuY3Rpb24odm9mZnNldCwgdmFsdWUsIGRlZmF1bHRWYWx1ZSkge1xuICBpZiAodGhpcy5mb3JjZV9kZWZhdWx0cyB8fCB2YWx1ZSAhPSBkZWZhdWx0VmFsdWUpIHtcbiAgICB0aGlzLmFkZEludDgodmFsdWUpO1xuICAgIHRoaXMuc2xvdCh2b2Zmc2V0KTtcbiAgfVxufTtcblxuLyoqXG4gKiBAcGFyYW0ge251bWJlcn0gdm9mZnNldFxuICogQHBhcmFtIHtudW1iZXJ9IHZhbHVlXG4gKiBAcGFyYW0ge251bWJlcn0gZGVmYXVsdFZhbHVlXG4gKi9cbmZsYXRidWZmZXJzLkJ1aWxkZXIucHJvdG90eXBlLmFkZEZpZWxkSW50MTYgPSBmdW5jdGlvbih2b2Zmc2V0LCB2YWx1ZSwgZGVmYXVsdFZhbHVlKSB7XG4gIGlmICh0aGlzLmZvcmNlX2RlZmF1bHRzIHx8IHZhbHVlICE9IGRlZmF1bHRWYWx1ZSkge1xuICAgIHRoaXMuYWRkSW50MTYodmFsdWUpO1xuICAgIHRoaXMuc2xvdCh2b2Zmc2V0KTtcbiAgfVxufTtcblxuLyoqXG4gKiBAcGFyYW0ge251bWJlcn0gdm9mZnNldFxuICogQHBhcmFtIHtudW1iZXJ9IHZhbHVlXG4gKiBAcGFyYW0ge251bWJlcn0gZGVmYXVsdFZhbHVlXG4gKi9cbmZsYXRidWZmZXJzLkJ1aWxkZXIucHJvdG90eXBlLmFkZEZpZWxkSW50MzIgPSBmdW5jdGlvbih2b2Zmc2V0LCB2YWx1ZSwgZGVmYXVsdFZhbHVlKSB7XG4gIGlmICh0aGlzLmZvcmNlX2RlZmF1bHRzIHx8IHZhbHVlICE9IGRlZmF1bHRWYWx1ZSkge1xuICAgIHRoaXMuYWRkSW50MzIodmFsdWUpO1xuICAgIHRoaXMuc2xvdCh2b2Zmc2V0KTtcbiAgfVxufTtcblxuLyoqXG4gKiBAcGFyYW0ge251bWJlcn0gdm9mZnNldFxuICogQHBhcmFtIHtmbGF0YnVmZmVycy5Mb25nfSB2YWx1ZVxuICogQHBhcmFtIHtmbGF0YnVmZmVycy5Mb25nfSBkZWZhdWx0VmFsdWVcbiAqL1xuZmxhdGJ1ZmZlcnMuQnVpbGRlci5wcm90b3R5cGUuYWRkRmllbGRJbnQ2NCA9IGZ1bmN0aW9uKHZvZmZzZXQsIHZhbHVlLCBkZWZhdWx0VmFsdWUpIHtcbiAgaWYgKHRoaXMuZm9yY2VfZGVmYXVsdHMgfHwgIXZhbHVlLmVxdWFscyhkZWZhdWx0VmFsdWUpKSB7XG4gICAgdGhpcy5hZGRJbnQ2NCh2YWx1ZSk7XG4gICAgdGhpcy5zbG90KHZvZmZzZXQpO1xuICB9XG59O1xuXG4vKipcbiAqIEBwYXJhbSB7bnVtYmVyfSB2b2Zmc2V0XG4gKiBAcGFyYW0ge251bWJlcn0gdmFsdWVcbiAqIEBwYXJhbSB7bnVtYmVyfSBkZWZhdWx0VmFsdWVcbiAqL1xuZmxhdGJ1ZmZlcnMuQnVpbGRlci5wcm90b3R5cGUuYWRkRmllbGRGbG9hdDMyID0gZnVuY3Rpb24odm9mZnNldCwgdmFsdWUsIGRlZmF1bHRWYWx1ZSkge1xuICBpZiAodGhpcy5mb3JjZV9kZWZhdWx0cyB8fCB2YWx1ZSAhPSBkZWZhdWx0VmFsdWUpIHtcbiAgICB0aGlzLmFkZEZsb2F0MzIodmFsdWUpO1xuICAgIHRoaXMuc2xvdCh2b2Zmc2V0KTtcbiAgfVxufTtcblxuLyoqXG4gKiBAcGFyYW0ge251bWJlcn0gdm9mZnNldFxuICogQHBhcmFtIHtudW1iZXJ9IHZhbHVlXG4gKiBAcGFyYW0ge251bWJlcn0gZGVmYXVsdFZhbHVlXG4gKi9cbmZsYXRidWZmZXJzLkJ1aWxkZXIucHJvdG90eXBlLmFkZEZpZWxkRmxvYXQ2NCA9IGZ1bmN0aW9uKHZvZmZzZXQsIHZhbHVlLCBkZWZhdWx0VmFsdWUpIHtcbiAgaWYgKHRoaXMuZm9yY2VfZGVmYXVsdHMgfHwgdmFsdWUgIT0gZGVmYXVsdFZhbHVlKSB7XG4gICAgdGhpcy5hZGRGbG9hdDY0KHZhbHVlKTtcbiAgICB0aGlzLnNsb3Qodm9mZnNldCk7XG4gIH1cbn07XG5cbi8qKlxuICogQHBhcmFtIHtudW1iZXJ9IHZvZmZzZXRcbiAqIEBwYXJhbSB7ZmxhdGJ1ZmZlcnMuT2Zmc2V0fSB2YWx1ZVxuICogQHBhcmFtIHtmbGF0YnVmZmVycy5PZmZzZXR9IGRlZmF1bHRWYWx1ZVxuICovXG5mbGF0YnVmZmVycy5CdWlsZGVyLnByb3RvdHlwZS5hZGRGaWVsZE9mZnNldCA9IGZ1bmN0aW9uKHZvZmZzZXQsIHZhbHVlLCBkZWZhdWx0VmFsdWUpIHtcbiAgaWYgKHRoaXMuZm9yY2VfZGVmYXVsdHMgfHwgdmFsdWUgIT0gZGVmYXVsdFZhbHVlKSB7XG4gICAgdGhpcy5hZGRPZmZzZXQodmFsdWUpO1xuICAgIHRoaXMuc2xvdCh2b2Zmc2V0KTtcbiAgfVxufTtcblxuLyoqXG4gKiBTdHJ1Y3RzIGFyZSBzdG9yZWQgaW5saW5lLCBzbyBub3RoaW5nIGFkZGl0aW9uYWwgaXMgYmVpbmcgYWRkZWQuIGBkYCBpcyBhbHdheXMgMC5cbiAqXG4gKiBAcGFyYW0ge251bWJlcn0gdm9mZnNldFxuICogQHBhcmFtIHtmbGF0YnVmZmVycy5PZmZzZXR9IHZhbHVlXG4gKiBAcGFyYW0ge2ZsYXRidWZmZXJzLk9mZnNldH0gZGVmYXVsdFZhbHVlXG4gKi9cbmZsYXRidWZmZXJzLkJ1aWxkZXIucHJvdG90eXBlLmFkZEZpZWxkU3RydWN0ID0gZnVuY3Rpb24odm9mZnNldCwgdmFsdWUsIGRlZmF1bHRWYWx1ZSkge1xuICBpZiAodmFsdWUgIT0gZGVmYXVsdFZhbHVlKSB7XG4gICAgdGhpcy5uZXN0ZWQodmFsdWUpO1xuICAgIHRoaXMuc2xvdCh2b2Zmc2V0KTtcbiAgfVxufTtcblxuLyoqXG4gKiBTdHJ1Y3R1cmVzIGFyZSBhbHdheXMgc3RvcmVkIGlubGluZSwgdGhleSBuZWVkIHRvIGJlIGNyZWF0ZWQgcmlnaHRcbiAqIHdoZXJlIHRoZXkncmUgdXNlZC4gIFlvdSdsbCBnZXQgdGhpcyBhc3NlcnRpb24gZmFpbHVyZSBpZiB5b3VcbiAqIGNyZWF0ZWQgaXQgZWxzZXdoZXJlLlxuICpcbiAqIEBwYXJhbSB7ZmxhdGJ1ZmZlcnMuT2Zmc2V0fSBvYmogVGhlIG9mZnNldCBvZiB0aGUgY3JlYXRlZCBvYmplY3RcbiAqL1xuZmxhdGJ1ZmZlcnMuQnVpbGRlci5wcm90b3R5cGUubmVzdGVkID0gZnVuY3Rpb24ob2JqKSB7XG4gIGlmIChvYmogIT0gdGhpcy5vZmZzZXQoKSkge1xuICAgIHRocm93IG5ldyBFcnJvcignRmxhdEJ1ZmZlcnM6IHN0cnVjdCBtdXN0IGJlIHNlcmlhbGl6ZWQgaW5saW5lLicpO1xuICB9XG59O1xuXG4vKipcbiAqIFNob3VsZCBub3QgYmUgY3JlYXRpbmcgYW55IG90aGVyIG9iamVjdCwgc3RyaW5nIG9yIHZlY3RvclxuICogd2hpbGUgYW4gb2JqZWN0IGlzIGJlaW5nIGNvbnN0cnVjdGVkXG4gKi9cbmZsYXRidWZmZXJzLkJ1aWxkZXIucHJvdG90eXBlLm5vdE5lc3RlZCA9IGZ1bmN0aW9uKCkge1xuICBpZiAodGhpcy5pc05lc3RlZCkge1xuICAgIHRocm93IG5ldyBFcnJvcignRmxhdEJ1ZmZlcnM6IG9iamVjdCBzZXJpYWxpemF0aW9uIG11c3Qgbm90IGJlIG5lc3RlZC4nKTtcbiAgfVxufTtcblxuLyoqXG4gKiBTZXQgdGhlIGN1cnJlbnQgdnRhYmxlIGF0IGB2b2Zmc2V0YCB0byB0aGUgY3VycmVudCBsb2NhdGlvbiBpbiB0aGUgYnVmZmVyLlxuICpcbiAqIEBwYXJhbSB7bnVtYmVyfSB2b2Zmc2V0XG4gKi9cbmZsYXRidWZmZXJzLkJ1aWxkZXIucHJvdG90eXBlLnNsb3QgPSBmdW5jdGlvbih2b2Zmc2V0KSB7XG4gIHRoaXMudnRhYmxlW3ZvZmZzZXRdID0gdGhpcy5vZmZzZXQoKTtcbn07XG5cbi8qKlxuICogQHJldHVybnMge2ZsYXRidWZmZXJzLk9mZnNldH0gT2Zmc2V0IHJlbGF0aXZlIHRvIHRoZSBlbmQgb2YgdGhlIGJ1ZmZlci5cbiAqL1xuZmxhdGJ1ZmZlcnMuQnVpbGRlci5wcm90b3R5cGUub2Zmc2V0ID0gZnVuY3Rpb24oKSB7XG4gIHJldHVybiB0aGlzLmJiLmNhcGFjaXR5KCkgLSB0aGlzLnNwYWNlO1xufTtcblxuLyoqXG4gKiBEb3VibGVzIHRoZSBzaXplIG9mIHRoZSBiYWNraW5nIEJ5dGVCdWZmZXIgYW5kIGNvcGllcyB0aGUgb2xkIGRhdGEgdG93YXJkc1xuICogdGhlIGVuZCBvZiB0aGUgbmV3IGJ1ZmZlciAoc2luY2Ugd2UgYnVpbGQgdGhlIGJ1ZmZlciBiYWNrd2FyZHMpLlxuICpcbiAqIEBwYXJhbSB7ZmxhdGJ1ZmZlcnMuQnl0ZUJ1ZmZlcn0gYmIgVGhlIGN1cnJlbnQgYnVmZmVyIHdpdGggdGhlIGV4aXN0aW5nIGRhdGFcbiAqIEByZXR1cm5zIHshZmxhdGJ1ZmZlcnMuQnl0ZUJ1ZmZlcn0gQSBuZXcgYnl0ZSBidWZmZXIgd2l0aCB0aGUgb2xkIGRhdGEgY29waWVkXG4gKiB0byBpdC4gVGhlIGRhdGEgaXMgbG9jYXRlZCBhdCB0aGUgZW5kIG9mIHRoZSBidWZmZXIuXG4gKlxuICogdWludDhBcnJheS5zZXQoKSBmb3JtYWxseSB0YWtlcyB7QXJyYXk8bnVtYmVyPnxBcnJheUJ1ZmZlclZpZXd9LCBzbyB0byBwYXNzXG4gKiBpdCBhIHVpbnQ4QXJyYXkgd2UgbmVlZCB0byBzdXBwcmVzcyB0aGUgdHlwZSBjaGVjazpcbiAqIEBzdXBwcmVzcyB7Y2hlY2tUeXBlc31cbiAqL1xuZmxhdGJ1ZmZlcnMuQnVpbGRlci5ncm93Qnl0ZUJ1ZmZlciA9IGZ1bmN0aW9uKGJiKSB7XG4gIHZhciBvbGRfYnVmX3NpemUgPSBiYi5jYXBhY2l0eSgpO1xuXG4gIC8vIEVuc3VyZSB3ZSBkb24ndCBncm93IGJleW9uZCB3aGF0IGZpdHMgaW4gYW4gaW50LlxuICBpZiAob2xkX2J1Zl9zaXplICYgMHhDMDAwMDAwMCkge1xuICAgIHRocm93IG5ldyBFcnJvcignRmxhdEJ1ZmZlcnM6IGNhbm5vdCBncm93IGJ1ZmZlciBiZXlvbmQgMiBnaWdhYnl0ZXMuJyk7XG4gIH1cblxuICB2YXIgbmV3X2J1Zl9zaXplID0gb2xkX2J1Zl9zaXplIDw8IDE7XG4gIHZhciBuYmIgPSBmbGF0YnVmZmVycy5CeXRlQnVmZmVyLmFsbG9jYXRlKG5ld19idWZfc2l6ZSk7XG4gIG5iYi5zZXRQb3NpdGlvbihuZXdfYnVmX3NpemUgLSBvbGRfYnVmX3NpemUpO1xuICBuYmIuYnl0ZXMoKS5zZXQoYmIuYnl0ZXMoKSwgbmV3X2J1Zl9zaXplIC0gb2xkX2J1Zl9zaXplKTtcbiAgcmV0dXJuIG5iYjtcbn07XG4vLy8gQGVuZGNvbmRcblxuLyoqXG4gKiBBZGRzIG9uIG9mZnNldCwgcmVsYXRpdmUgdG8gd2hlcmUgaXQgd2lsbCBiZSB3cml0dGVuLlxuICpcbiAqIEBwYXJhbSB7ZmxhdGJ1ZmZlcnMuT2Zmc2V0fSBvZmZzZXQgVGhlIG9mZnNldCB0byBhZGQuXG4gKi9cbmZsYXRidWZmZXJzLkJ1aWxkZXIucHJvdG90eXBlLmFkZE9mZnNldCA9IGZ1bmN0aW9uKG9mZnNldCkge1xuICB0aGlzLnByZXAoZmxhdGJ1ZmZlcnMuU0laRU9GX0lOVCwgMCk7IC8vIEVuc3VyZSBhbGlnbm1lbnQgaXMgYWxyZWFkeSBkb25lLlxuICB0aGlzLndyaXRlSW50MzIodGhpcy5vZmZzZXQoKSAtIG9mZnNldCArIGZsYXRidWZmZXJzLlNJWkVPRl9JTlQpO1xufTtcblxuLy8vIEBjb25kIEZMQVRCVUZGRVJTX0lOVEVSTkFMXG4vKipcbiAqIFN0YXJ0IGVuY29kaW5nIGEgbmV3IG9iamVjdCBpbiB0aGUgYnVmZmVyLiAgVXNlcnMgd2lsbCBub3QgdXN1YWxseSBuZWVkIHRvXG4gKiBjYWxsIHRoaXMgZGlyZWN0bHkuIFRoZSBGbGF0QnVmZmVycyBjb21waWxlciB3aWxsIGdlbmVyYXRlIGhlbHBlciBtZXRob2RzXG4gKiB0aGF0IGNhbGwgdGhpcyBtZXRob2QgaW50ZXJuYWxseS5cbiAqXG4gKiBAcGFyYW0ge251bWJlcn0gbnVtZmllbGRzXG4gKi9cbmZsYXRidWZmZXJzLkJ1aWxkZXIucHJvdG90eXBlLnN0YXJ0T2JqZWN0ID0gZnVuY3Rpb24obnVtZmllbGRzKSB7XG4gIHRoaXMubm90TmVzdGVkKCk7XG4gIGlmICh0aGlzLnZ0YWJsZSA9PSBudWxsKSB7XG4gICAgdGhpcy52dGFibGUgPSBbXTtcbiAgfVxuICB0aGlzLnZ0YWJsZV9pbl91c2UgPSBudW1maWVsZHM7XG4gIGZvciAodmFyIGkgPSAwOyBpIDwgbnVtZmllbGRzOyBpKyspIHtcbiAgICB0aGlzLnZ0YWJsZVtpXSA9IDA7IC8vIFRoaXMgd2lsbCBwdXNoIGFkZGl0aW9uYWwgZWxlbWVudHMgYXMgbmVlZGVkXG4gIH1cbiAgdGhpcy5pc05lc3RlZCA9IHRydWU7XG4gIHRoaXMub2JqZWN0X3N0YXJ0ID0gdGhpcy5vZmZzZXQoKTtcbn07XG5cbi8qKlxuICogRmluaXNoIG9mZiB3cml0aW5nIHRoZSBvYmplY3QgdGhhdCBpcyB1bmRlciBjb25zdHJ1Y3Rpb24uXG4gKlxuICogQHJldHVybnMge2ZsYXRidWZmZXJzLk9mZnNldH0gVGhlIG9mZnNldCB0byB0aGUgb2JqZWN0IGluc2lkZSBgZGF0YUJ1ZmZlcmBcbiAqL1xuZmxhdGJ1ZmZlcnMuQnVpbGRlci5wcm90b3R5cGUuZW5kT2JqZWN0ID0gZnVuY3Rpb24oKSB7XG4gIGlmICh0aGlzLnZ0YWJsZSA9PSBudWxsIHx8ICF0aGlzLmlzTmVzdGVkKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdGbGF0QnVmZmVyczogZW5kT2JqZWN0IGNhbGxlZCB3aXRob3V0IHN0YXJ0T2JqZWN0Jyk7XG4gIH1cblxuICB0aGlzLmFkZEludDMyKDApO1xuICB2YXIgdnRhYmxlbG9jID0gdGhpcy5vZmZzZXQoKTtcblxuICAvLyBUcmltIHRyYWlsaW5nIHplcm9lcy5cbiAgdmFyIGkgPSB0aGlzLnZ0YWJsZV9pbl91c2UgLSAxO1xuICBmb3IgKDsgaSA+PSAwICYmIHRoaXMudnRhYmxlW2ldID09IDA7IGktLSkge31cbiAgdmFyIHRyaW1tZWRfc2l6ZSA9IGkgKyAxO1xuXG4gIC8vIFdyaXRlIG91dCB0aGUgY3VycmVudCB2dGFibGUuXG4gIGZvciAoOyBpID49IDA7IGktLSkge1xuICAgIC8vIE9mZnNldCByZWxhdGl2ZSB0byB0aGUgc3RhcnQgb2YgdGhlIHRhYmxlLlxuICAgIHRoaXMuYWRkSW50MTYodGhpcy52dGFibGVbaV0gIT0gMCA/IHZ0YWJsZWxvYyAtIHRoaXMudnRhYmxlW2ldIDogMCk7XG4gIH1cblxuICB2YXIgc3RhbmRhcmRfZmllbGRzID0gMjsgLy8gVGhlIGZpZWxkcyBiZWxvdzpcbiAgdGhpcy5hZGRJbnQxNih2dGFibGVsb2MgLSB0aGlzLm9iamVjdF9zdGFydCk7XG4gIHZhciBsZW4gPSAodHJpbW1lZF9zaXplICsgc3RhbmRhcmRfZmllbGRzKSAqIGZsYXRidWZmZXJzLlNJWkVPRl9TSE9SVDtcbiAgdGhpcy5hZGRJbnQxNihsZW4pO1xuXG4gIC8vIFNlYXJjaCBmb3IgYW4gZXhpc3RpbmcgdnRhYmxlIHRoYXQgbWF0Y2hlcyB0aGUgY3VycmVudCBvbmUuXG4gIHZhciBleGlzdGluZ192dGFibGUgPSAwO1xuICB2YXIgdnQxID0gdGhpcy5zcGFjZTtcbm91dGVyX2xvb3A6XG4gIGZvciAoaSA9IDA7IGkgPCB0aGlzLnZ0YWJsZXMubGVuZ3RoOyBpKyspIHtcbiAgICB2YXIgdnQyID0gdGhpcy5iYi5jYXBhY2l0eSgpIC0gdGhpcy52dGFibGVzW2ldO1xuICAgIGlmIChsZW4gPT0gdGhpcy5iYi5yZWFkSW50MTYodnQyKSkge1xuICAgICAgZm9yICh2YXIgaiA9IGZsYXRidWZmZXJzLlNJWkVPRl9TSE9SVDsgaiA8IGxlbjsgaiArPSBmbGF0YnVmZmVycy5TSVpFT0ZfU0hPUlQpIHtcbiAgICAgICAgaWYgKHRoaXMuYmIucmVhZEludDE2KHZ0MSArIGopICE9IHRoaXMuYmIucmVhZEludDE2KHZ0MiArIGopKSB7XG4gICAgICAgICAgY29udGludWUgb3V0ZXJfbG9vcDtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgZXhpc3RpbmdfdnRhYmxlID0gdGhpcy52dGFibGVzW2ldO1xuICAgICAgYnJlYWs7XG4gICAgfVxuICB9XG5cbiAgaWYgKGV4aXN0aW5nX3Z0YWJsZSkge1xuICAgIC8vIEZvdW5kIGEgbWF0Y2g6XG4gICAgLy8gUmVtb3ZlIHRoZSBjdXJyZW50IHZ0YWJsZS5cbiAgICB0aGlzLnNwYWNlID0gdGhpcy5iYi5jYXBhY2l0eSgpIC0gdnRhYmxlbG9jO1xuXG4gICAgLy8gUG9pbnQgdGFibGUgdG8gZXhpc3RpbmcgdnRhYmxlLlxuICAgIHRoaXMuYmIud3JpdGVJbnQzMih0aGlzLnNwYWNlLCBleGlzdGluZ192dGFibGUgLSB2dGFibGVsb2MpO1xuICB9IGVsc2Uge1xuICAgIC8vIE5vIG1hdGNoOlxuICAgIC8vIEFkZCB0aGUgbG9jYXRpb24gb2YgdGhlIGN1cnJlbnQgdnRhYmxlIHRvIHRoZSBsaXN0IG9mIHZ0YWJsZXMuXG4gICAgdGhpcy52dGFibGVzLnB1c2godGhpcy5vZmZzZXQoKSk7XG5cbiAgICAvLyBQb2ludCB0YWJsZSB0byBjdXJyZW50IHZ0YWJsZS5cbiAgICB0aGlzLmJiLndyaXRlSW50MzIodGhpcy5iYi5jYXBhY2l0eSgpIC0gdnRhYmxlbG9jLCB0aGlzLm9mZnNldCgpIC0gdnRhYmxlbG9jKTtcbiAgfVxuXG4gIHRoaXMuaXNOZXN0ZWQgPSBmYWxzZTtcbiAgcmV0dXJuIHZ0YWJsZWxvYztcbn07XG4vLy8gQGVuZGNvbmRcblxuLyoqXG4gKiBGaW5hbGl6ZSBhIGJ1ZmZlciwgcG9pdGluZyB0byB0aGUgZ2l2ZW4gYHJvb3RfdGFibGVgLlxuICpcbiAqIEBwYXJhbSB7ZmxhdGJ1ZmZlcnMuT2Zmc2V0fSByb290X3RhYmxlXG4gKiBAcGFyYW0ge3N0cmluZz19IG9wdF9maWxlX2lkZW50aWZpZXJcbiAqIEBwYXJhbSB7Ym9vbGVhbj19IG9wdF9zaXplX3ByZWZpeFxuICovXG5mbGF0YnVmZmVycy5CdWlsZGVyLnByb3RvdHlwZS5maW5pc2ggPSBmdW5jdGlvbihyb290X3RhYmxlLCBvcHRfZmlsZV9pZGVudGlmaWVyLCBvcHRfc2l6ZV9wcmVmaXgpIHtcbiAgdmFyIHNpemVfcHJlZml4ID0gb3B0X3NpemVfcHJlZml4ID8gZmxhdGJ1ZmZlcnMuU0laRV9QUkVGSVhfTEVOR1RIIDogMDtcbiAgaWYgKG9wdF9maWxlX2lkZW50aWZpZXIpIHtcbiAgICB2YXIgZmlsZV9pZGVudGlmaWVyID0gb3B0X2ZpbGVfaWRlbnRpZmllcjtcbiAgICB0aGlzLnByZXAodGhpcy5taW5hbGlnbiwgZmxhdGJ1ZmZlcnMuU0laRU9GX0lOVCArXG4gICAgICBmbGF0YnVmZmVycy5GSUxFX0lERU5USUZJRVJfTEVOR1RIICsgc2l6ZV9wcmVmaXgpO1xuICAgIGlmIChmaWxlX2lkZW50aWZpZXIubGVuZ3RoICE9IGZsYXRidWZmZXJzLkZJTEVfSURFTlRJRklFUl9MRU5HVEgpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignRmxhdEJ1ZmZlcnM6IGZpbGUgaWRlbnRpZmllciBtdXN0IGJlIGxlbmd0aCAnICtcbiAgICAgICAgZmxhdGJ1ZmZlcnMuRklMRV9JREVOVElGSUVSX0xFTkdUSCk7XG4gICAgfVxuICAgIGZvciAodmFyIGkgPSBmbGF0YnVmZmVycy5GSUxFX0lERU5USUZJRVJfTEVOR1RIIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICAgIHRoaXMud3JpdGVJbnQ4KGZpbGVfaWRlbnRpZmllci5jaGFyQ29kZUF0KGkpKTtcbiAgICB9XG4gIH1cbiAgdGhpcy5wcmVwKHRoaXMubWluYWxpZ24sIGZsYXRidWZmZXJzLlNJWkVPRl9JTlQgKyBzaXplX3ByZWZpeCk7XG4gIHRoaXMuYWRkT2Zmc2V0KHJvb3RfdGFibGUpO1xuICBpZiAoc2l6ZV9wcmVmaXgpIHtcbiAgICB0aGlzLmFkZEludDMyKHRoaXMuYmIuY2FwYWNpdHkoKSAtIHRoaXMuc3BhY2UpO1xuICB9XG4gIHRoaXMuYmIuc2V0UG9zaXRpb24odGhpcy5zcGFjZSk7XG59O1xuXG4vKipcbiAqIEZpbmFsaXplIGEgc2l6ZSBwcmVmaXhlZCBidWZmZXIsIHBvaW50aW5nIHRvIHRoZSBnaXZlbiBgcm9vdF90YWJsZWAuXG4gKlxuICogQHBhcmFtIHtmbGF0YnVmZmVycy5PZmZzZXR9IHJvb3RfdGFibGVcbiAqIEBwYXJhbSB7c3RyaW5nPX0gb3B0X2ZpbGVfaWRlbnRpZmllclxuICovXG5mbGF0YnVmZmVycy5CdWlsZGVyLnByb3RvdHlwZS5maW5pc2hTaXplUHJlZml4ZWQgPSBmdW5jdGlvbiAocm9vdF90YWJsZSwgb3B0X2ZpbGVfaWRlbnRpZmllcikge1xuICB0aGlzLmZpbmlzaChyb290X3RhYmxlLCBvcHRfZmlsZV9pZGVudGlmaWVyLCB0cnVlKTtcbn07XG5cbi8vLyBAY29uZCBGTEFUQlVGRkVSU19JTlRFUk5BTFxuLyoqXG4gKiBUaGlzIGNoZWNrcyBhIHJlcXVpcmVkIGZpZWxkIGhhcyBiZWVuIHNldCBpbiBhIGdpdmVuIHRhYmxlIHRoYXQgaGFzXG4gKiBqdXN0IGJlZW4gY29uc3RydWN0ZWQuXG4gKlxuICogQHBhcmFtIHtmbGF0YnVmZmVycy5PZmZzZXR9IHRhYmxlXG4gKiBAcGFyYW0ge251bWJlcn0gZmllbGRcbiAqL1xuZmxhdGJ1ZmZlcnMuQnVpbGRlci5wcm90b3R5cGUucmVxdWlyZWRGaWVsZCA9IGZ1bmN0aW9uKHRhYmxlLCBmaWVsZCkge1xuICB2YXIgdGFibGVfc3RhcnQgPSB0aGlzLmJiLmNhcGFjaXR5KCkgLSB0YWJsZTtcbiAgdmFyIHZ0YWJsZV9zdGFydCA9IHRhYmxlX3N0YXJ0IC0gdGhpcy5iYi5yZWFkSW50MzIodGFibGVfc3RhcnQpO1xuICB2YXIgb2sgPSB0aGlzLmJiLnJlYWRJbnQxNih2dGFibGVfc3RhcnQgKyBmaWVsZCkgIT0gMDtcblxuICAvLyBJZiB0aGlzIGZhaWxzLCB0aGUgY2FsbGVyIHdpbGwgc2hvdyB3aGF0IGZpZWxkIG5lZWRzIHRvIGJlIHNldC5cbiAgaWYgKCFvaykge1xuICAgIHRocm93IG5ldyBFcnJvcignRmxhdEJ1ZmZlcnM6IGZpZWxkICcgKyBmaWVsZCArICcgbXVzdCBiZSBzZXQnKTtcbiAgfVxufTtcblxuLyoqXG4gKiBTdGFydCBhIG5ldyBhcnJheS92ZWN0b3Igb2Ygb2JqZWN0cy4gIFVzZXJzIHVzdWFsbHkgd2lsbCBub3QgY2FsbFxuICogdGhpcyBkaXJlY3RseS4gVGhlIEZsYXRCdWZmZXJzIGNvbXBpbGVyIHdpbGwgY3JlYXRlIGEgc3RhcnQvZW5kXG4gKiBtZXRob2QgZm9yIHZlY3RvciB0eXBlcyBpbiBnZW5lcmF0ZWQgY29kZS5cbiAqXG4gKiBAcGFyYW0ge251bWJlcn0gZWxlbV9zaXplIFRoZSBzaXplIG9mIGVhY2ggZWxlbWVudCBpbiB0aGUgYXJyYXlcbiAqIEBwYXJhbSB7bnVtYmVyfSBudW1fZWxlbXMgVGhlIG51bWJlciBvZiBlbGVtZW50cyBpbiB0aGUgYXJyYXlcbiAqIEBwYXJhbSB7bnVtYmVyfSBhbGlnbm1lbnQgVGhlIGFsaWdubWVudCBvZiB0aGUgYXJyYXlcbiAqL1xuZmxhdGJ1ZmZlcnMuQnVpbGRlci5wcm90b3R5cGUuc3RhcnRWZWN0b3IgPSBmdW5jdGlvbihlbGVtX3NpemUsIG51bV9lbGVtcywgYWxpZ25tZW50KSB7XG4gIHRoaXMubm90TmVzdGVkKCk7XG4gIHRoaXMudmVjdG9yX251bV9lbGVtcyA9IG51bV9lbGVtcztcbiAgdGhpcy5wcmVwKGZsYXRidWZmZXJzLlNJWkVPRl9JTlQsIGVsZW1fc2l6ZSAqIG51bV9lbGVtcyk7XG4gIHRoaXMucHJlcChhbGlnbm1lbnQsIGVsZW1fc2l6ZSAqIG51bV9lbGVtcyk7IC8vIEp1c3QgaW4gY2FzZSBhbGlnbm1lbnQgPiBpbnQuXG59O1xuXG4vKipcbiAqIEZpbmlzaCBvZmYgdGhlIGNyZWF0aW9uIG9mIGFuIGFycmF5IGFuZCBhbGwgaXRzIGVsZW1lbnRzLiBUaGUgYXJyYXkgbXVzdCBiZVxuICogY3JlYXRlZCB3aXRoIGBzdGFydFZlY3RvcmAuXG4gKlxuICogQHJldHVybnMge2ZsYXRidWZmZXJzLk9mZnNldH0gVGhlIG9mZnNldCBhdCB3aGljaCB0aGUgbmV3bHkgY3JlYXRlZCBhcnJheVxuICogc3RhcnRzLlxuICovXG5mbGF0YnVmZmVycy5CdWlsZGVyLnByb3RvdHlwZS5lbmRWZWN0b3IgPSBmdW5jdGlvbigpIHtcbiAgdGhpcy53cml0ZUludDMyKHRoaXMudmVjdG9yX251bV9lbGVtcyk7XG4gIHJldHVybiB0aGlzLm9mZnNldCgpO1xufTtcbi8vLyBAZW5kY29uZFxuXG4vKipcbiAqIEVuY29kZSB0aGUgc3RyaW5nIGBzYCBpbiB0aGUgYnVmZmVyIHVzaW5nIFVURi04LiBJZiBhIFVpbnQ4QXJyYXkgaXMgcGFzc2VkXG4gKiBpbnN0ZWFkIG9mIGEgc3RyaW5nLCBpdCBpcyBhc3N1bWVkIHRvIGNvbnRhaW4gdmFsaWQgVVRGLTggZW5jb2RlZCBkYXRhLlxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfFVpbnQ4QXJyYXl9IHMgVGhlIHN0cmluZyB0byBlbmNvZGVcbiAqIEByZXR1cm4ge2ZsYXRidWZmZXJzLk9mZnNldH0gVGhlIG9mZnNldCBpbiB0aGUgYnVmZmVyIHdoZXJlIHRoZSBlbmNvZGVkIHN0cmluZyBzdGFydHNcbiAqL1xuZmxhdGJ1ZmZlcnMuQnVpbGRlci5wcm90b3R5cGUuY3JlYXRlU3RyaW5nID0gZnVuY3Rpb24ocykge1xuICBpZiAocyBpbnN0YW5jZW9mIFVpbnQ4QXJyYXkpIHtcbiAgICB2YXIgdXRmOCA9IHM7XG4gIH0gZWxzZSB7XG4gICAgdmFyIHV0ZjggPSBbXTtcbiAgICB2YXIgaSA9IDA7XG5cbiAgICB3aGlsZSAoaSA8IHMubGVuZ3RoKSB7XG4gICAgICB2YXIgY29kZVBvaW50O1xuXG4gICAgICAvLyBEZWNvZGUgVVRGLTE2XG4gICAgICB2YXIgYSA9IHMuY2hhckNvZGVBdChpKyspO1xuICAgICAgaWYgKGEgPCAweEQ4MDAgfHwgYSA+PSAweERDMDApIHtcbiAgICAgICAgY29kZVBvaW50ID0gYTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHZhciBiID0gcy5jaGFyQ29kZUF0KGkrKyk7XG4gICAgICAgIGNvZGVQb2ludCA9IChhIDw8IDEwKSArIGIgKyAoMHgxMDAwMCAtICgweEQ4MDAgPDwgMTApIC0gMHhEQzAwKTtcbiAgICAgIH1cblxuICAgICAgLy8gRW5jb2RlIFVURi04XG4gICAgICBpZiAoY29kZVBvaW50IDwgMHg4MCkge1xuICAgICAgICB1dGY4LnB1c2goY29kZVBvaW50KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGlmIChjb2RlUG9pbnQgPCAweDgwMCkge1xuICAgICAgICAgIHV0ZjgucHVzaCgoKGNvZGVQb2ludCA+PiA2KSAmIDB4MUYpIHwgMHhDMCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgaWYgKGNvZGVQb2ludCA8IDB4MTAwMDApIHtcbiAgICAgICAgICAgIHV0ZjgucHVzaCgoKGNvZGVQb2ludCA+PiAxMikgJiAweDBGKSB8IDB4RTApO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB1dGY4LnB1c2goXG4gICAgICAgICAgICAgICgoY29kZVBvaW50ID4+IDE4KSAmIDB4MDcpIHwgMHhGMCxcbiAgICAgICAgICAgICAgKChjb2RlUG9pbnQgPj4gMTIpICYgMHgzRikgfCAweDgwKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgdXRmOC5wdXNoKCgoY29kZVBvaW50ID4+IDYpICYgMHgzRikgfCAweDgwKTtcbiAgICAgICAgfVxuICAgICAgICB1dGY4LnB1c2goKGNvZGVQb2ludCAmIDB4M0YpIHwgMHg4MCk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgdGhpcy5hZGRJbnQ4KDApO1xuICB0aGlzLnN0YXJ0VmVjdG9yKDEsIHV0ZjgubGVuZ3RoLCAxKTtcbiAgdGhpcy5iYi5zZXRQb3NpdGlvbih0aGlzLnNwYWNlIC09IHV0ZjgubGVuZ3RoKTtcbiAgZm9yICh2YXIgaSA9IDAsIG9mZnNldCA9IHRoaXMuc3BhY2UsIGJ5dGVzID0gdGhpcy5iYi5ieXRlcygpOyBpIDwgdXRmOC5sZW5ndGg7IGkrKykge1xuICAgIGJ5dGVzW29mZnNldCsrXSA9IHV0ZjhbaV07XG4gIH1cbiAgcmV0dXJuIHRoaXMuZW5kVmVjdG9yKCk7XG59O1xuXG4vKipcbiAqIEEgaGVscGVyIGZ1bmN0aW9uIHRvIGF2b2lkIGdlbmVyYXRlZCBjb2RlIGRlcGVuZGluZyBvbiB0aGlzIGZpbGUgZGlyZWN0bHkuXG4gKlxuICogQHBhcmFtIHtudW1iZXJ9IGxvd1xuICogQHBhcmFtIHtudW1iZXJ9IGhpZ2hcbiAqIEByZXR1cm5zIHshZmxhdGJ1ZmZlcnMuTG9uZ31cbiAqL1xuZmxhdGJ1ZmZlcnMuQnVpbGRlci5wcm90b3R5cGUuY3JlYXRlTG9uZyA9IGZ1bmN0aW9uKGxvdywgaGlnaCkge1xuICByZXR1cm4gZmxhdGJ1ZmZlcnMuTG9uZy5jcmVhdGUobG93LCBoaWdoKTtcbn07XG4vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vL1xuLy8vIEBjb25kIEZMQVRCVUZGRVJTX0lOVEVSTkFMXG4vKipcbiAqIENyZWF0ZSBhIG5ldyBCeXRlQnVmZmVyIHdpdGggYSBnaXZlbiBhcnJheSBvZiBieXRlcyAoYFVpbnQ4QXJyYXlgKS5cbiAqXG4gKiBAY29uc3RydWN0b3JcbiAqIEBwYXJhbSB7VWludDhBcnJheX0gYnl0ZXNcbiAqL1xuZmxhdGJ1ZmZlcnMuQnl0ZUJ1ZmZlciA9IGZ1bmN0aW9uKGJ5dGVzKSB7XG4gIC8qKlxuICAgKiBAdHlwZSB7VWludDhBcnJheX1cbiAgICogQHByaXZhdGVcbiAgICovXG4gIHRoaXMuYnl0ZXNfID0gYnl0ZXM7XG5cbiAgLyoqXG4gICAqIEB0eXBlIHtudW1iZXJ9XG4gICAqIEBwcml2YXRlXG4gICAqL1xuICB0aGlzLnBvc2l0aW9uXyA9IDA7XG59O1xuXG4vKipcbiAqIENyZWF0ZSBhbmQgYWxsb2NhdGUgYSBuZXcgQnl0ZUJ1ZmZlciB3aXRoIGEgZ2l2ZW4gc2l6ZS5cbiAqXG4gKiBAcGFyYW0ge251bWJlcn0gYnl0ZV9zaXplXG4gKiBAcmV0dXJucyB7IWZsYXRidWZmZXJzLkJ5dGVCdWZmZXJ9XG4gKi9cbmZsYXRidWZmZXJzLkJ5dGVCdWZmZXIuYWxsb2NhdGUgPSBmdW5jdGlvbihieXRlX3NpemUpIHtcbiAgcmV0dXJuIG5ldyBmbGF0YnVmZmVycy5CeXRlQnVmZmVyKG5ldyBVaW50OEFycmF5KGJ5dGVfc2l6ZSkpO1xufTtcblxuZmxhdGJ1ZmZlcnMuQnl0ZUJ1ZmZlci5wcm90b3R5cGUuY2xlYXIgPSBmdW5jdGlvbigpIHtcbiAgdGhpcy5wb3NpdGlvbl8gPSAwO1xufTtcblxuLyoqXG4gKiBHZXQgdGhlIHVuZGVybHlpbmcgYFVpbnQ4QXJyYXlgLlxuICpcbiAqIEByZXR1cm5zIHtVaW50OEFycmF5fVxuICovXG5mbGF0YnVmZmVycy5CeXRlQnVmZmVyLnByb3RvdHlwZS5ieXRlcyA9IGZ1bmN0aW9uKCkge1xuICByZXR1cm4gdGhpcy5ieXRlc187XG59O1xuXG4vKipcbiAqIEdldCB0aGUgYnVmZmVyJ3MgcG9zaXRpb24uXG4gKlxuICogQHJldHVybnMge251bWJlcn1cbiAqL1xuZmxhdGJ1ZmZlcnMuQnl0ZUJ1ZmZlci5wcm90b3R5cGUucG9zaXRpb24gPSBmdW5jdGlvbigpIHtcbiAgcmV0dXJuIHRoaXMucG9zaXRpb25fO1xufTtcblxuLyoqXG4gKiBTZXQgdGhlIGJ1ZmZlcidzIHBvc2l0aW9uLlxuICpcbiAqIEBwYXJhbSB7bnVtYmVyfSBwb3NpdGlvblxuICovXG5mbGF0YnVmZmVycy5CeXRlQnVmZmVyLnByb3RvdHlwZS5zZXRQb3NpdGlvbiA9IGZ1bmN0aW9uKHBvc2l0aW9uKSB7XG4gIHRoaXMucG9zaXRpb25fID0gcG9zaXRpb247XG59O1xuXG4vKipcbiAqIEdldCB0aGUgYnVmZmVyJ3MgY2FwYWNpdHkuXG4gKlxuICogQHJldHVybnMge251bWJlcn1cbiAqL1xuZmxhdGJ1ZmZlcnMuQnl0ZUJ1ZmZlci5wcm90b3R5cGUuY2FwYWNpdHkgPSBmdW5jdGlvbigpIHtcbiAgcmV0dXJuIHRoaXMuYnl0ZXNfLmxlbmd0aDtcbn07XG5cbi8qKlxuICogQHBhcmFtIHtudW1iZXJ9IG9mZnNldFxuICogQHJldHVybnMge251bWJlcn1cbiAqL1xuZmxhdGJ1ZmZlcnMuQnl0ZUJ1ZmZlci5wcm90b3R5cGUucmVhZEludDggPSBmdW5jdGlvbihvZmZzZXQpIHtcbiAgcmV0dXJuIHRoaXMucmVhZFVpbnQ4KG9mZnNldCkgPDwgMjQgPj4gMjQ7XG59O1xuXG4vKipcbiAqIEBwYXJhbSB7bnVtYmVyfSBvZmZzZXRcbiAqIEByZXR1cm5zIHtudW1iZXJ9XG4gKi9cbmZsYXRidWZmZXJzLkJ5dGVCdWZmZXIucHJvdG90eXBlLnJlYWRVaW50OCA9IGZ1bmN0aW9uKG9mZnNldCkge1xuICByZXR1cm4gdGhpcy5ieXRlc19bb2Zmc2V0XTtcbn07XG5cbi8qKlxuICogQHBhcmFtIHtudW1iZXJ9IG9mZnNldFxuICogQHJldHVybnMge251bWJlcn1cbiAqL1xuZmxhdGJ1ZmZlcnMuQnl0ZUJ1ZmZlci5wcm90b3R5cGUucmVhZEludDE2ID0gZnVuY3Rpb24ob2Zmc2V0KSB7XG4gIHJldHVybiB0aGlzLnJlYWRVaW50MTYob2Zmc2V0KSA8PCAxNiA+PiAxNjtcbn07XG5cbi8qKlxuICogQHBhcmFtIHtudW1iZXJ9IG9mZnNldFxuICogQHJldHVybnMge251bWJlcn1cbiAqL1xuZmxhdGJ1ZmZlcnMuQnl0ZUJ1ZmZlci5wcm90b3R5cGUucmVhZFVpbnQxNiA9IGZ1bmN0aW9uKG9mZnNldCkge1xuICByZXR1cm4gdGhpcy5ieXRlc19bb2Zmc2V0XSB8IHRoaXMuYnl0ZXNfW29mZnNldCArIDFdIDw8IDg7XG59O1xuXG4vKipcbiAqIEBwYXJhbSB7bnVtYmVyfSBvZmZzZXRcbiAqIEByZXR1cm5zIHtudW1iZXJ9XG4gKi9cbmZsYXRidWZmZXJzLkJ5dGVCdWZmZXIucHJvdG90eXBlLnJlYWRJbnQzMiA9IGZ1bmN0aW9uKG9mZnNldCkge1xuICByZXR1cm4gdGhpcy5ieXRlc19bb2Zmc2V0XSB8IHRoaXMuYnl0ZXNfW29mZnNldCArIDFdIDw8IDggfCB0aGlzLmJ5dGVzX1tvZmZzZXQgKyAyXSA8PCAxNiB8IHRoaXMuYnl0ZXNfW29mZnNldCArIDNdIDw8IDI0O1xufTtcblxuLyoqXG4gKiBAcGFyYW0ge251bWJlcn0gb2Zmc2V0XG4gKiBAcmV0dXJucyB7bnVtYmVyfVxuICovXG5mbGF0YnVmZmVycy5CeXRlQnVmZmVyLnByb3RvdHlwZS5yZWFkVWludDMyID0gZnVuY3Rpb24ob2Zmc2V0KSB7XG4gIHJldHVybiB0aGlzLnJlYWRJbnQzMihvZmZzZXQpID4+PiAwO1xufTtcblxuLyoqXG4gKiBAcGFyYW0ge251bWJlcn0gb2Zmc2V0XG4gKiBAcmV0dXJucyB7IWZsYXRidWZmZXJzLkxvbmd9XG4gKi9cbmZsYXRidWZmZXJzLkJ5dGVCdWZmZXIucHJvdG90eXBlLnJlYWRJbnQ2NCA9IGZ1bmN0aW9uKG9mZnNldCkge1xuICByZXR1cm4gbmV3IGZsYXRidWZmZXJzLkxvbmcodGhpcy5yZWFkSW50MzIob2Zmc2V0KSwgdGhpcy5yZWFkSW50MzIob2Zmc2V0ICsgNCkpO1xufTtcblxuLyoqXG4gKiBAcGFyYW0ge251bWJlcn0gb2Zmc2V0XG4gKiBAcmV0dXJucyB7IWZsYXRidWZmZXJzLkxvbmd9XG4gKi9cbmZsYXRidWZmZXJzLkJ5dGVCdWZmZXIucHJvdG90eXBlLnJlYWRVaW50NjQgPSBmdW5jdGlvbihvZmZzZXQpIHtcbiAgcmV0dXJuIG5ldyBmbGF0YnVmZmVycy5Mb25nKHRoaXMucmVhZFVpbnQzMihvZmZzZXQpLCB0aGlzLnJlYWRVaW50MzIob2Zmc2V0ICsgNCkpO1xufTtcblxuLyoqXG4gKiBAcGFyYW0ge251bWJlcn0gb2Zmc2V0XG4gKiBAcmV0dXJucyB7bnVtYmVyfVxuICovXG5mbGF0YnVmZmVycy5CeXRlQnVmZmVyLnByb3RvdHlwZS5yZWFkRmxvYXQzMiA9IGZ1bmN0aW9uKG9mZnNldCkge1xuICBmbGF0YnVmZmVycy5pbnQzMlswXSA9IHRoaXMucmVhZEludDMyKG9mZnNldCk7XG4gIHJldHVybiBmbGF0YnVmZmVycy5mbG9hdDMyWzBdO1xufTtcblxuLyoqXG4gKiBAcGFyYW0ge251bWJlcn0gb2Zmc2V0XG4gKiBAcmV0dXJucyB7bnVtYmVyfVxuICovXG5mbGF0YnVmZmVycy5CeXRlQnVmZmVyLnByb3RvdHlwZS5yZWFkRmxvYXQ2NCA9IGZ1bmN0aW9uKG9mZnNldCkge1xuICBmbGF0YnVmZmVycy5pbnQzMltmbGF0YnVmZmVycy5pc0xpdHRsZUVuZGlhbiA/IDAgOiAxXSA9IHRoaXMucmVhZEludDMyKG9mZnNldCk7XG4gIGZsYXRidWZmZXJzLmludDMyW2ZsYXRidWZmZXJzLmlzTGl0dGxlRW5kaWFuID8gMSA6IDBdID0gdGhpcy5yZWFkSW50MzIob2Zmc2V0ICsgNCk7XG4gIHJldHVybiBmbGF0YnVmZmVycy5mbG9hdDY0WzBdO1xufTtcblxuLyoqXG4gKiBAcGFyYW0ge251bWJlcn0gb2Zmc2V0XG4gKiBAcGFyYW0ge251bWJlcnxib29sZWFufSB2YWx1ZVxuICovXG5mbGF0YnVmZmVycy5CeXRlQnVmZmVyLnByb3RvdHlwZS53cml0ZUludDggPSBmdW5jdGlvbihvZmZzZXQsIHZhbHVlKSB7XG4gIHRoaXMuYnl0ZXNfW29mZnNldF0gPSAvKiogQHR5cGUge251bWJlcn0gKi8odmFsdWUpO1xufTtcblxuLyoqXG4gKiBAcGFyYW0ge251bWJlcn0gb2Zmc2V0XG4gKiBAcGFyYW0ge251bWJlcn0gdmFsdWVcbiAqL1xuZmxhdGJ1ZmZlcnMuQnl0ZUJ1ZmZlci5wcm90b3R5cGUud3JpdGVVaW50OCA9IGZ1bmN0aW9uKG9mZnNldCwgdmFsdWUpIHtcbiAgdGhpcy5ieXRlc19bb2Zmc2V0XSA9IHZhbHVlO1xufTtcblxuLyoqXG4gKiBAcGFyYW0ge251bWJlcn0gb2Zmc2V0XG4gKiBAcGFyYW0ge251bWJlcn0gdmFsdWVcbiAqL1xuZmxhdGJ1ZmZlcnMuQnl0ZUJ1ZmZlci5wcm90b3R5cGUud3JpdGVJbnQxNiA9IGZ1bmN0aW9uKG9mZnNldCwgdmFsdWUpIHtcbiAgdGhpcy5ieXRlc19bb2Zmc2V0XSA9IHZhbHVlO1xuICB0aGlzLmJ5dGVzX1tvZmZzZXQgKyAxXSA9IHZhbHVlID4+IDg7XG59O1xuXG4vKipcbiAqIEBwYXJhbSB7bnVtYmVyfSBvZmZzZXRcbiAqIEBwYXJhbSB7bnVtYmVyfSB2YWx1ZVxuICovXG5mbGF0YnVmZmVycy5CeXRlQnVmZmVyLnByb3RvdHlwZS53cml0ZVVpbnQxNiA9IGZ1bmN0aW9uKG9mZnNldCwgdmFsdWUpIHtcbiAgICB0aGlzLmJ5dGVzX1tvZmZzZXRdID0gdmFsdWU7XG4gICAgdGhpcy5ieXRlc19bb2Zmc2V0ICsgMV0gPSB2YWx1ZSA+PiA4O1xufTtcblxuLyoqXG4gKiBAcGFyYW0ge251bWJlcn0gb2Zmc2V0XG4gKiBAcGFyYW0ge251bWJlcn0gdmFsdWVcbiAqL1xuZmxhdGJ1ZmZlcnMuQnl0ZUJ1ZmZlci5wcm90b3R5cGUud3JpdGVJbnQzMiA9IGZ1bmN0aW9uKG9mZnNldCwgdmFsdWUpIHtcbiAgdGhpcy5ieXRlc19bb2Zmc2V0XSA9IHZhbHVlO1xuICB0aGlzLmJ5dGVzX1tvZmZzZXQgKyAxXSA9IHZhbHVlID4+IDg7XG4gIHRoaXMuYnl0ZXNfW29mZnNldCArIDJdID0gdmFsdWUgPj4gMTY7XG4gIHRoaXMuYnl0ZXNfW29mZnNldCArIDNdID0gdmFsdWUgPj4gMjQ7XG59O1xuXG4vKipcbiAqIEBwYXJhbSB7bnVtYmVyfSBvZmZzZXRcbiAqIEBwYXJhbSB7bnVtYmVyfSB2YWx1ZVxuICovXG5mbGF0YnVmZmVycy5CeXRlQnVmZmVyLnByb3RvdHlwZS53cml0ZVVpbnQzMiA9IGZ1bmN0aW9uKG9mZnNldCwgdmFsdWUpIHtcbiAgICB0aGlzLmJ5dGVzX1tvZmZzZXRdID0gdmFsdWU7XG4gICAgdGhpcy5ieXRlc19bb2Zmc2V0ICsgMV0gPSB2YWx1ZSA+PiA4O1xuICAgIHRoaXMuYnl0ZXNfW29mZnNldCArIDJdID0gdmFsdWUgPj4gMTY7XG4gICAgdGhpcy5ieXRlc19bb2Zmc2V0ICsgM10gPSB2YWx1ZSA+PiAyNDtcbn07XG5cbi8qKlxuICogQHBhcmFtIHtudW1iZXJ9IG9mZnNldFxuICogQHBhcmFtIHtmbGF0YnVmZmVycy5Mb25nfSB2YWx1ZVxuICovXG5mbGF0YnVmZmVycy5CeXRlQnVmZmVyLnByb3RvdHlwZS53cml0ZUludDY0ID0gZnVuY3Rpb24ob2Zmc2V0LCB2YWx1ZSkge1xuICB0aGlzLndyaXRlSW50MzIob2Zmc2V0LCB2YWx1ZS5sb3cpO1xuICB0aGlzLndyaXRlSW50MzIob2Zmc2V0ICsgNCwgdmFsdWUuaGlnaCk7XG59O1xuXG4vKipcbiAqIEBwYXJhbSB7bnVtYmVyfSBvZmZzZXRcbiAqIEBwYXJhbSB7ZmxhdGJ1ZmZlcnMuTG9uZ30gdmFsdWVcbiAqL1xuZmxhdGJ1ZmZlcnMuQnl0ZUJ1ZmZlci5wcm90b3R5cGUud3JpdGVVaW50NjQgPSBmdW5jdGlvbihvZmZzZXQsIHZhbHVlKSB7XG4gICAgdGhpcy53cml0ZVVpbnQzMihvZmZzZXQsIHZhbHVlLmxvdyk7XG4gICAgdGhpcy53cml0ZVVpbnQzMihvZmZzZXQgKyA0LCB2YWx1ZS5oaWdoKTtcbn07XG5cbi8qKlxuICogQHBhcmFtIHtudW1iZXJ9IG9mZnNldFxuICogQHBhcmFtIHtudW1iZXJ9IHZhbHVlXG4gKi9cbmZsYXRidWZmZXJzLkJ5dGVCdWZmZXIucHJvdG90eXBlLndyaXRlRmxvYXQzMiA9IGZ1bmN0aW9uKG9mZnNldCwgdmFsdWUpIHtcbiAgZmxhdGJ1ZmZlcnMuZmxvYXQzMlswXSA9IHZhbHVlO1xuICB0aGlzLndyaXRlSW50MzIob2Zmc2V0LCBmbGF0YnVmZmVycy5pbnQzMlswXSk7XG59O1xuXG4vKipcbiAqIEBwYXJhbSB7bnVtYmVyfSBvZmZzZXRcbiAqIEBwYXJhbSB7bnVtYmVyfSB2YWx1ZVxuICovXG5mbGF0YnVmZmVycy5CeXRlQnVmZmVyLnByb3RvdHlwZS53cml0ZUZsb2F0NjQgPSBmdW5jdGlvbihvZmZzZXQsIHZhbHVlKSB7XG4gIGZsYXRidWZmZXJzLmZsb2F0NjRbMF0gPSB2YWx1ZTtcbiAgdGhpcy53cml0ZUludDMyKG9mZnNldCwgZmxhdGJ1ZmZlcnMuaW50MzJbZmxhdGJ1ZmZlcnMuaXNMaXR0bGVFbmRpYW4gPyAwIDogMV0pO1xuICB0aGlzLndyaXRlSW50MzIob2Zmc2V0ICsgNCwgZmxhdGJ1ZmZlcnMuaW50MzJbZmxhdGJ1ZmZlcnMuaXNMaXR0bGVFbmRpYW4gPyAxIDogMF0pO1xufTtcblxuLyoqXG4gKiBSZXR1cm4gdGhlIGZpbGUgaWRlbnRpZmllci4gICBCZWhhdmlvciBpcyB1bmRlZmluZWQgZm9yIEZsYXRCdWZmZXJzIHdob3NlXG4gKiBzY2hlbWEgZG9lcyBub3QgaW5jbHVkZSBhIGZpbGVfaWRlbnRpZmllciAobGlrZWx5IHBvaW50cyBhdCBwYWRkaW5nIG9yIHRoZVxuICogc3RhcnQgb2YgYSB0aGUgcm9vdCB2dGFibGUpLlxuICogQHJldHVybnMge3N0cmluZ31cbiAqL1xuZmxhdGJ1ZmZlcnMuQnl0ZUJ1ZmZlci5wcm90b3R5cGUuZ2V0QnVmZmVySWRlbnRpZmllciA9IGZ1bmN0aW9uKCkge1xuICBpZiAodGhpcy5ieXRlc18ubGVuZ3RoIDwgdGhpcy5wb3NpdGlvbl8gKyBmbGF0YnVmZmVycy5TSVpFT0ZfSU5UICtcbiAgICAgIGZsYXRidWZmZXJzLkZJTEVfSURFTlRJRklFUl9MRU5HVEgpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgICdGbGF0QnVmZmVyczogQnl0ZUJ1ZmZlciBpcyB0b28gc2hvcnQgdG8gY29udGFpbiBhbiBpZGVudGlmaWVyLicpO1xuICB9XG4gIHZhciByZXN1bHQgPSBcIlwiO1xuICBmb3IgKHZhciBpID0gMDsgaSA8IGZsYXRidWZmZXJzLkZJTEVfSURFTlRJRklFUl9MRU5HVEg7IGkrKykge1xuICAgIHJlc3VsdCArPSBTdHJpbmcuZnJvbUNoYXJDb2RlKFxuICAgICAgICB0aGlzLnJlYWRJbnQ4KHRoaXMucG9zaXRpb25fICsgZmxhdGJ1ZmZlcnMuU0laRU9GX0lOVCArIGkpKTtcbiAgfVxuICByZXR1cm4gcmVzdWx0O1xufTtcblxuLyoqXG4gKiBMb29rIHVwIGEgZmllbGQgaW4gdGhlIHZ0YWJsZSwgcmV0dXJuIGFuIG9mZnNldCBpbnRvIHRoZSBvYmplY3QsIG9yIDAgaWYgdGhlXG4gKiBmaWVsZCBpcyBub3QgcHJlc2VudC5cbiAqXG4gKiBAcGFyYW0ge251bWJlcn0gYmJfcG9zXG4gKiBAcGFyYW0ge251bWJlcn0gdnRhYmxlX29mZnNldFxuICogQHJldHVybnMge251bWJlcn1cbiAqL1xuZmxhdGJ1ZmZlcnMuQnl0ZUJ1ZmZlci5wcm90b3R5cGUuX19vZmZzZXQgPSBmdW5jdGlvbihiYl9wb3MsIHZ0YWJsZV9vZmZzZXQpIHtcbiAgdmFyIHZ0YWJsZSA9IGJiX3BvcyAtIHRoaXMucmVhZEludDMyKGJiX3Bvcyk7XG4gIHJldHVybiB2dGFibGVfb2Zmc2V0IDwgdGhpcy5yZWFkSW50MTYodnRhYmxlKSA/IHRoaXMucmVhZEludDE2KHZ0YWJsZSArIHZ0YWJsZV9vZmZzZXQpIDogMDtcbn07XG5cbi8qKlxuICogSW5pdGlhbGl6ZSBhbnkgVGFibGUtZGVyaXZlZCB0eXBlIHRvIHBvaW50IHRvIHRoZSB1bmlvbiBhdCB0aGUgZ2l2ZW4gb2Zmc2V0LlxuICpcbiAqIEBwYXJhbSB7ZmxhdGJ1ZmZlcnMuVGFibGV9IHRcbiAqIEBwYXJhbSB7bnVtYmVyfSBvZmZzZXRcbiAqIEByZXR1cm5zIHtmbGF0YnVmZmVycy5UYWJsZX1cbiAqL1xuZmxhdGJ1ZmZlcnMuQnl0ZUJ1ZmZlci5wcm90b3R5cGUuX191bmlvbiA9IGZ1bmN0aW9uKHQsIG9mZnNldCkge1xuICB0LmJiX3BvcyA9IG9mZnNldCArIHRoaXMucmVhZEludDMyKG9mZnNldCk7XG4gIHQuYmIgPSB0aGlzO1xuICByZXR1cm4gdDtcbn07XG5cbi8qKlxuICogQ3JlYXRlIGEgSmF2YVNjcmlwdCBzdHJpbmcgZnJvbSBVVEYtOCBkYXRhIHN0b3JlZCBpbnNpZGUgdGhlIEZsYXRCdWZmZXIuXG4gKiBUaGlzIGFsbG9jYXRlcyBhIG5ldyBzdHJpbmcgYW5kIGNvbnZlcnRzIHRvIHdpZGUgY2hhcnMgdXBvbiBlYWNoIGFjY2Vzcy5cbiAqXG4gKiBUbyBhdm9pZCB0aGUgY29udmVyc2lvbiB0byBVVEYtMTYsIHBhc3MgZmxhdGJ1ZmZlcnMuRW5jb2RpbmcuVVRGOF9CWVRFUyBhc1xuICogdGhlIFwib3B0aW9uYWxFbmNvZGluZ1wiIGFyZ3VtZW50LiBUaGlzIGlzIHVzZWZ1bCBmb3IgYXZvaWRpbmcgY29udmVyc2lvbiB0b1xuICogYW5kIGZyb20gVVRGLTE2IHdoZW4gdGhlIGRhdGEgd2lsbCBqdXN0IGJlIHBhY2thZ2VkIGJhY2sgdXAgaW4gYW5vdGhlclxuICogRmxhdEJ1ZmZlciBsYXRlciBvbi5cbiAqXG4gKiBAcGFyYW0ge251bWJlcn0gb2Zmc2V0XG4gKiBAcGFyYW0ge2ZsYXRidWZmZXJzLkVuY29kaW5nPX0gb3B0X2VuY29kaW5nIERlZmF1bHRzIHRvIFVURjE2X1NUUklOR1xuICogQHJldHVybnMge3N0cmluZ3whVWludDhBcnJheX1cbiAqL1xuZmxhdGJ1ZmZlcnMuQnl0ZUJ1ZmZlci5wcm90b3R5cGUuX19zdHJpbmcgPSBmdW5jdGlvbihvZmZzZXQsIG9wdF9lbmNvZGluZykge1xuICBvZmZzZXQgKz0gdGhpcy5yZWFkSW50MzIob2Zmc2V0KTtcblxuICB2YXIgbGVuZ3RoID0gdGhpcy5yZWFkSW50MzIob2Zmc2V0KTtcbiAgdmFyIHJlc3VsdCA9ICcnO1xuICB2YXIgaSA9IDA7XG5cbiAgb2Zmc2V0ICs9IGZsYXRidWZmZXJzLlNJWkVPRl9JTlQ7XG5cbiAgaWYgKG9wdF9lbmNvZGluZyA9PT0gZmxhdGJ1ZmZlcnMuRW5jb2RpbmcuVVRGOF9CWVRFUykge1xuICAgIHJldHVybiB0aGlzLmJ5dGVzXy5zdWJhcnJheShvZmZzZXQsIG9mZnNldCArIGxlbmd0aCk7XG4gIH1cblxuICB3aGlsZSAoaSA8IGxlbmd0aCkge1xuICAgIHZhciBjb2RlUG9pbnQ7XG5cbiAgICAvLyBEZWNvZGUgVVRGLThcbiAgICB2YXIgYSA9IHRoaXMucmVhZFVpbnQ4KG9mZnNldCArIGkrKyk7XG4gICAgaWYgKGEgPCAweEMwKSB7XG4gICAgICBjb2RlUG9pbnQgPSBhO1xuICAgIH0gZWxzZSB7XG4gICAgICB2YXIgYiA9IHRoaXMucmVhZFVpbnQ4KG9mZnNldCArIGkrKyk7XG4gICAgICBpZiAoYSA8IDB4RTApIHtcbiAgICAgICAgY29kZVBvaW50ID1cbiAgICAgICAgICAoKGEgJiAweDFGKSA8PCA2KSB8XG4gICAgICAgICAgKGIgJiAweDNGKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHZhciBjID0gdGhpcy5yZWFkVWludDgob2Zmc2V0ICsgaSsrKTtcbiAgICAgICAgaWYgKGEgPCAweEYwKSB7XG4gICAgICAgICAgY29kZVBvaW50ID1cbiAgICAgICAgICAgICgoYSAmIDB4MEYpIDw8IDEyKSB8XG4gICAgICAgICAgICAoKGIgJiAweDNGKSA8PCA2KSB8XG4gICAgICAgICAgICAoYyAmIDB4M0YpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHZhciBkID0gdGhpcy5yZWFkVWludDgob2Zmc2V0ICsgaSsrKTtcbiAgICAgICAgICBjb2RlUG9pbnQgPVxuICAgICAgICAgICAgKChhICYgMHgwNykgPDwgMTgpIHxcbiAgICAgICAgICAgICgoYiAmIDB4M0YpIDw8IDEyKSB8XG4gICAgICAgICAgICAoKGMgJiAweDNGKSA8PCA2KSB8XG4gICAgICAgICAgICAoZCAmIDB4M0YpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gRW5jb2RlIFVURi0xNlxuICAgIGlmIChjb2RlUG9pbnQgPCAweDEwMDAwKSB7XG4gICAgICByZXN1bHQgKz0gU3RyaW5nLmZyb21DaGFyQ29kZShjb2RlUG9pbnQpO1xuICAgIH0gZWxzZSB7XG4gICAgICBjb2RlUG9pbnQgLT0gMHgxMDAwMDtcbiAgICAgIHJlc3VsdCArPSBTdHJpbmcuZnJvbUNoYXJDb2RlKFxuICAgICAgICAoY29kZVBvaW50ID4+IDEwKSArIDB4RDgwMCxcbiAgICAgICAgKGNvZGVQb2ludCAmICgoMSA8PCAxMCkgLSAxKSkgKyAweERDMDApO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiByZXN1bHQ7XG59O1xuXG4vKipcbiAqIFJldHJpZXZlIHRoZSByZWxhdGl2ZSBvZmZzZXQgc3RvcmVkIGF0IFwib2Zmc2V0XCJcbiAqIEBwYXJhbSB7bnVtYmVyfSBvZmZzZXRcbiAqIEByZXR1cm5zIHtudW1iZXJ9XG4gKi9cbmZsYXRidWZmZXJzLkJ5dGVCdWZmZXIucHJvdG90eXBlLl9faW5kaXJlY3QgPSBmdW5jdGlvbihvZmZzZXQpIHtcbiAgcmV0dXJuIG9mZnNldCArIHRoaXMucmVhZEludDMyKG9mZnNldCk7XG59O1xuXG4vKipcbiAqIEdldCB0aGUgc3RhcnQgb2YgZGF0YSBvZiBhIHZlY3RvciB3aG9zZSBvZmZzZXQgaXMgc3RvcmVkIGF0IFwib2Zmc2V0XCIgaW4gdGhpcyBvYmplY3QuXG4gKlxuICogQHBhcmFtIHtudW1iZXJ9IG9mZnNldFxuICogQHJldHVybnMge251bWJlcn1cbiAqL1xuZmxhdGJ1ZmZlcnMuQnl0ZUJ1ZmZlci5wcm90b3R5cGUuX192ZWN0b3IgPSBmdW5jdGlvbihvZmZzZXQpIHtcbiAgcmV0dXJuIG9mZnNldCArIHRoaXMucmVhZEludDMyKG9mZnNldCkgKyBmbGF0YnVmZmVycy5TSVpFT0ZfSU5UOyAvLyBkYXRhIHN0YXJ0cyBhZnRlciB0aGUgbGVuZ3RoXG59O1xuXG4vKipcbiAqIEdldCB0aGUgbGVuZ3RoIG9mIGEgdmVjdG9yIHdob3NlIG9mZnNldCBpcyBzdG9yZWQgYXQgXCJvZmZzZXRcIiBpbiB0aGlzIG9iamVjdC5cbiAqXG4gKiBAcGFyYW0ge251bWJlcn0gb2Zmc2V0XG4gKiBAcmV0dXJucyB7bnVtYmVyfVxuICovXG5mbGF0YnVmZmVycy5CeXRlQnVmZmVyLnByb3RvdHlwZS5fX3ZlY3Rvcl9sZW4gPSBmdW5jdGlvbihvZmZzZXQpIHtcbiAgcmV0dXJuIHRoaXMucmVhZEludDMyKG9mZnNldCArIHRoaXMucmVhZEludDMyKG9mZnNldCkpO1xufTtcblxuLyoqXG4gKiBAcGFyYW0ge3N0cmluZ30gaWRlbnRcbiAqIEByZXR1cm5zIHtib29sZWFufVxuICovXG5mbGF0YnVmZmVycy5CeXRlQnVmZmVyLnByb3RvdHlwZS5fX2hhc19pZGVudGlmaWVyID0gZnVuY3Rpb24oaWRlbnQpIHtcbiAgaWYgKGlkZW50Lmxlbmd0aCAhPSBmbGF0YnVmZmVycy5GSUxFX0lERU5USUZJRVJfTEVOR1RIKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdGbGF0QnVmZmVyczogZmlsZSBpZGVudGlmaWVyIG11c3QgYmUgbGVuZ3RoICcgK1xuICAgICAgICAgICAgICAgICAgICBmbGF0YnVmZmVycy5GSUxFX0lERU5USUZJRVJfTEVOR1RIKTtcbiAgfVxuICBmb3IgKHZhciBpID0gMDsgaSA8IGZsYXRidWZmZXJzLkZJTEVfSURFTlRJRklFUl9MRU5HVEg7IGkrKykge1xuICAgIGlmIChpZGVudC5jaGFyQ29kZUF0KGkpICE9IHRoaXMucmVhZEludDgodGhpcy5wb3NpdGlvbl8gKyBmbGF0YnVmZmVycy5TSVpFT0ZfSU5UICsgaSkpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gIH1cbiAgcmV0dXJuIHRydWU7XG59O1xuXG4vKipcbiAqIEEgaGVscGVyIGZ1bmN0aW9uIHRvIGF2b2lkIGdlbmVyYXRlZCBjb2RlIGRlcGVuZGluZyBvbiB0aGlzIGZpbGUgZGlyZWN0bHkuXG4gKlxuICogQHBhcmFtIHtudW1iZXJ9IGxvd1xuICogQHBhcmFtIHtudW1iZXJ9IGhpZ2hcbiAqIEByZXR1cm5zIHshZmxhdGJ1ZmZlcnMuTG9uZ31cbiAqL1xuZmxhdGJ1ZmZlcnMuQnl0ZUJ1ZmZlci5wcm90b3R5cGUuY3JlYXRlTG9uZyA9IGZ1bmN0aW9uKGxvdywgaGlnaCkge1xuICByZXR1cm4gZmxhdGJ1ZmZlcnMuTG9uZy5jcmVhdGUobG93LCBoaWdoKTtcbn07XG5cbi8vIEV4cG9ydHMgZm9yIE5vZGUuanMgYW5kIFJlcXVpcmVKU1xuZXhwb3J0IHsgZmxhdGJ1ZmZlcnMgfTtcblxuLy8vIEBlbmRjb25kXG4vLy8gQH1cbiIsIi8vIFRoZSBtb2R1bGUgY2FjaGVcbnZhciBfX3dlYnBhY2tfbW9kdWxlX2NhY2hlX18gPSB7fTtcblxuLy8gVGhlIHJlcXVpcmUgZnVuY3Rpb25cbmZ1bmN0aW9uIF9fd2VicGFja19yZXF1aXJlX18obW9kdWxlSWQpIHtcblx0Ly8gQ2hlY2sgaWYgbW9kdWxlIGlzIGluIGNhY2hlXG5cdHZhciBjYWNoZWRNb2R1bGUgPSBfX3dlYnBhY2tfbW9kdWxlX2NhY2hlX19bbW9kdWxlSWRdO1xuXHRpZiAoY2FjaGVkTW9kdWxlICE9PSB1bmRlZmluZWQpIHtcblx0XHRyZXR1cm4gY2FjaGVkTW9kdWxlLmV4cG9ydHM7XG5cdH1cblx0Ly8gQ3JlYXRlIGEgbmV3IG1vZHVsZSAoYW5kIHB1dCBpdCBpbnRvIHRoZSBjYWNoZSlcblx0dmFyIG1vZHVsZSA9IF9fd2VicGFja19tb2R1bGVfY2FjaGVfX1ttb2R1bGVJZF0gPSB7XG5cdFx0Ly8gbm8gbW9kdWxlLmlkIG5lZWRlZFxuXHRcdC8vIG5vIG1vZHVsZS5sb2FkZWQgbmVlZGVkXG5cdFx0ZXhwb3J0czoge31cblx0fTtcblxuXHQvLyBFeGVjdXRlIHRoZSBtb2R1bGUgZnVuY3Rpb25cblx0X193ZWJwYWNrX21vZHVsZXNfX1ttb2R1bGVJZF0uY2FsbChtb2R1bGUuZXhwb3J0cywgbW9kdWxlLCBtb2R1bGUuZXhwb3J0cywgX193ZWJwYWNrX3JlcXVpcmVfXyk7XG5cblx0Ly8gUmV0dXJuIHRoZSBleHBvcnRzIG9mIHRoZSBtb2R1bGVcblx0cmV0dXJuIG1vZHVsZS5leHBvcnRzO1xufVxuXG4iLCIvLyBnZXREZWZhdWx0RXhwb3J0IGZ1bmN0aW9uIGZvciBjb21wYXRpYmlsaXR5IHdpdGggbm9uLWhhcm1vbnkgbW9kdWxlc1xuX193ZWJwYWNrX3JlcXVpcmVfXy5uID0gKG1vZHVsZSkgPT4ge1xuXHR2YXIgZ2V0dGVyID0gbW9kdWxlICYmIG1vZHVsZS5fX2VzTW9kdWxlID9cblx0XHQoKSA9PiAobW9kdWxlWydkZWZhdWx0J10pIDpcblx0XHQoKSA9PiAobW9kdWxlKTtcblx0X193ZWJwYWNrX3JlcXVpcmVfXy5kKGdldHRlciwgeyBhOiBnZXR0ZXIgfSk7XG5cdHJldHVybiBnZXR0ZXI7XG59OyIsIi8vIGRlZmluZSBnZXR0ZXIgZnVuY3Rpb25zIGZvciBoYXJtb255IGV4cG9ydHNcbl9fd2VicGFja19yZXF1aXJlX18uZCA9IChleHBvcnRzLCBkZWZpbml0aW9uKSA9PiB7XG5cdGZvcih2YXIga2V5IGluIGRlZmluaXRpb24pIHtcblx0XHRpZihfX3dlYnBhY2tfcmVxdWlyZV9fLm8oZGVmaW5pdGlvbiwga2V5KSAmJiAhX193ZWJwYWNrX3JlcXVpcmVfXy5vKGV4cG9ydHMsIGtleSkpIHtcblx0XHRcdE9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBrZXksIHsgZW51bWVyYWJsZTogdHJ1ZSwgZ2V0OiBkZWZpbml0aW9uW2tleV0gfSk7XG5cdFx0fVxuXHR9XG59OyIsIl9fd2VicGFja19yZXF1aXJlX18uZyA9IChmdW5jdGlvbigpIHtcblx0aWYgKHR5cGVvZiBnbG9iYWxUaGlzID09PSAnb2JqZWN0JykgcmV0dXJuIGdsb2JhbFRoaXM7XG5cdHRyeSB7XG5cdFx0cmV0dXJuIHRoaXMgfHwgbmV3IEZ1bmN0aW9uKCdyZXR1cm4gdGhpcycpKCk7XG5cdH0gY2F0Y2ggKGUpIHtcblx0XHRpZiAodHlwZW9mIHdpbmRvdyA9PT0gJ29iamVjdCcpIHJldHVybiB3aW5kb3c7XG5cdH1cbn0pKCk7IiwiX193ZWJwYWNrX3JlcXVpcmVfXy5vID0gKG9iaiwgcHJvcCkgPT4gKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChvYmosIHByb3ApKSIsIi8vIGRlZmluZSBfX2VzTW9kdWxlIG9uIGV4cG9ydHNcbl9fd2VicGFja19yZXF1aXJlX18uciA9IChleHBvcnRzKSA9PiB7XG5cdGlmKHR5cGVvZiBTeW1ib2wgIT09ICd1bmRlZmluZWQnICYmIFN5bWJvbC50b1N0cmluZ1RhZykge1xuXHRcdE9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBTeW1ib2wudG9TdHJpbmdUYWcsIHsgdmFsdWU6ICdNb2R1bGUnIH0pO1xuXHR9XG5cdE9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAnX19lc01vZHVsZScsIHsgdmFsdWU6IHRydWUgfSk7XG59OyIsIiIsIi8vIHN0YXJ0dXBcbi8vIExvYWQgZW50cnkgbW9kdWxlIGFuZCByZXR1cm4gZXhwb3J0c1xuLy8gVGhpcyBlbnRyeSBtb2R1bGUgaXMgcmVmZXJlbmNlZCBieSBvdGhlciBtb2R1bGVzIHNvIGl0IGNhbid0IGJlIGlubGluZWRcbnZhciBfX3dlYnBhY2tfZXhwb3J0c19fID0gX193ZWJwYWNrX3JlcXVpcmVfXyhcIi4vbGliL2luZGV4LnRzXCIpO1xuIiwiIl0sIm5hbWVzIjpbXSwic291cmNlUm9vdCI6IiJ9 |